diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 176a458f94..0000000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto diff --git a/.gitignore b/.gitignore index 7c302ed856..dc5b9dab73 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,25 @@ -/installed.xml -/indra/llcommon/llversionviewer.h /indra/build-* /indra/tools/vstool/obj/ *.aps *.suo *.vshost.exe +*/.vs /bin/ /bin-release/ /bin /bin-release +/indra/out/ /indra/viewer-* /indra/newview/vivox-runtime/ /indra/newview/dbghelp.dll +indra/newview/res/viewer_icon.* +indra/newview/res-sdl/viewer_icon.* /libraries/ /lib/ *.pyc *.orig *.rej *.bak -*~ *.DS_Store /LICENSES/ /edited-files.txt @@ -26,12 +27,4 @@ qtcreator-build/ /.pc /build-* /viewer-* -/indra/newview/res/viewerRes.rc -/indra/newview/res/viewerRes_bc.rc -/indra/newview/English.lproj/InfoPlist.strings -/indra/newview/linux_tools/handle_secondlifeprotocol.sh -/indra/newview/linux_tools/install.sh -/indra/newview/linux_tools/refresh_desktop_app_entry.sh -/indra/newview/linux_tools/wrapper.sh - - +/Pipfile.lock diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000..c32bcbe202 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,286 @@ +stages: + - build + - upload + +default: + interruptible: true + timeout: 4h + +variables: + AUTOBUILD_BUILD_ID: $CI_PIPELINE_ID + AUTOBUILD_INSTALLABLE_CACHE: "$CI_PROJECT_DIR/.cache/autobuild" + PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" + VIEWER_USE_CRASHPAD: "TRUE" + VIEWER_CRASHPAD_URL: $SENTRY_DSN + +.win_build: + stage: build + tags: + - autobuild + - windows + cache: + key: + files: + - autobuild.xml + prefix: ${CI_JOB_NAME} + paths: + - .cache/autobuild + - .cache/pip + - .venv/ + when: 'always' + before_script: + - virtualenv .venv + - .\.venv\Scripts\activate.ps1 + - pip install --upgrade autobuild -i https://pkg.alchemyviewer.org/repository/autobuild/simple --extra-index-url https://pypi.org/simple + script: + - | + autobuild configure -c Release -- -DUSE_FMODSTUDIO=ON -DUSE_NVAPI=ON -DUSE_LTO=ON -DVS_DISABLE_FATAL_WARNINGS=ON -DREVISION_FROM_VCS=FALSE + autobuild build -c Release --no-configure + artifacts: + name: "$env:CI_COMMIT_REF_NAME-$env:CI_COMMIT_SHORT_SHA" + expire_in: 1 week + paths: + - build-vc-*/newview/Release/build_data.json + - build-vc-*/newview/Release/singularity-bin.exe + - build-vc-*/newview/Release/*.pdb + - build-vc-*/newview/Release/*.dll + - build-vc-*/newview/Release/Singularity_*_Setup.exe + +.linux_build: + stage: build + image: r.alchemyviewer.org/singularity/infrastructure/debian-build-image:latest + tags: + - linux + - docker + cache: + key: + files: + - autobuild.xml + prefix: ${CI_JOB_NAME} + paths: + - .cache/autobuild + - .cache/pip + - .venv + when: 'always' + before_script: + - virtualenv .venv -p python2 + - source .venv/bin/activate + - pip install --upgrade autobuild -i https://pkg.alchemyviewer.org/repository/autobuild/simple --extra-index-url https://pypi.org/simple + script: + - | + autobuild configure -c Release -- -DUSE_FMODSTUDIO=ON -DUSE_NVAPI=ON -DUSE_LTO=ON -DUNIX_DISABLE_FATAL_WARNINGS=ON -DREVISION_FROM_VCS=FALSE + autobuild build -c Release --no-configure + artifacts: + name: "$env:CI_COMMIT_REF_NAME-$env:CI_COMMIT_SHORT_SHA" + expire_in: 1 week + paths: + - build-linux-*/build_data.json + - build-linux-*/newview/Singularity_*.tar.xz + +.win32_build: + extends: .win_build + variables: + AUTOBUILD_ADDRSIZE: 32 + VIEWER_USE_CRASHPAD: "FALSE" + cache: + key: + prefix: windows32 + +.win64_build: + extends: .win_build + variables: + AUTOBUILD_ADDRSIZE: 64 + cache: + key: + prefix: windows64 + +.linux32_build: + extends: .linux_build + variables: + AUTOBUILD_ADDRSIZE: 32 + cache: + key: + prefix: linux32 + +.linux64_build: + extends: .linux_build + variables: + AUTOBUILD_ADDRSIZE: 64 + cache: + key: + prefix: linux64 + +.master_rules: + rules: + - if: $BUILD_CHANNEL || $CI_COMMIT_TAG + when: never + - if: '$CI_PIPELINE_SOURCE == "web"' + - if: '$CI_PIPELINE_SOURCE == "schedule"' + #- if: '$CI_COMMIT_BRANCH == "master" && $CI_PIPELINE_SOURCE == "push"' + # when: delayed + # start_in: '12 hours' + variables: + VIEWER_CHANNEL_TYPE: Test + VIEWER_USE_CRASHPAD: "FALSE" + +.project_rules: + rules: + - if: '$BUILD_CHANNEL == "Project" && ($CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "schedule")' + - if: '$CI_COMMIT_TAG =~ /.*-project/' + variables: + VIEWER_CHANNEL_TYPE: Project + +.beta_rules: + rules: + - if: '$BUILD_CHANNEL == "Beta" && ($CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "schedule")' + - if: '$CI_COMMIT_TAG =~ /.*-beta/' + variables: + VIEWER_CHANNEL_TYPE: Beta + +.release_rules: + rules: + - if: '$BUILD_CHANNEL == "Release" && ($CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "schedule")' + - if: '$CI_COMMIT_TAG =~ /.*-release/' + variables: + VIEWER_CHANNEL_TYPE: Release + +.build:master:linux64: + extends: + - .linux64_build + - .master_rules + +build:master:windows32: + extends: + - .win32_build + - .master_rules + +build:master:windows64: + extends: + - .win64_build + - .master_rules + +.build:project:linux64: + extends: + - .linux64_build + - .project_rules + +build:project:windows32: + extends: + - .win32_build + - .project_rules + +build:project:windows64: + extends: + - .win64_build + - .project_rules + +.build:beta:linux64: + extends: + - .linux64_build + - .beta_rules + +build:beta:windows32: + extends: + - .win32_build + - .beta_rules + +build:beta:windows64: + extends: + - .win64_build + - .beta_rules + +.build:release:linux64: + extends: + - .linux64_build + - .release_rules + +build:release:windows32: + extends: + - .win32_build + - .release_rules + +build:release:windows64: + extends: + - .win64_build + - .release_rules + +.upload_template: + stage: upload + tags: + - autobuild + - windows + allow_failure: false + script: + - | + $BuildData = Get-Content .\build-vc-64\newview\Release\build_data.json | ConvertFrom-Json + $BuildChannelVersion = $BuildData."Channel" + ' ' + $BuildData."Version" + $UploadDestViewerDir = $BuildChannelVersion.ToLower().Replace(" ", "/") + $UploadDestURL = "https://pkg.alchemyviewer.org/repository/viewer/${UploadDestViewerDir}" + + $UploadParams = @{ UseBasicParsing = $true; + Method = "PUT"; + Headers = @{ + ContentType = "application/x-executable"; + Authorization = "Basic $([System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("$env:AUTOBUILD_HTTP_USER`:$env:AUTOBUILD_HTTP_PASS")))"; }; + Verbose = $true; }; + + Function try_upload($build_type, $file_pattern) + { + $build_newview = ".\build-${build_type}\newview\" + If (Test-Path -LiteralPath $build_newview) + { + Push-Location $build_newview + $FileName = Get-ChildItem -Path . -Name -Include $file_pattern + Invoke-WebRequest @UploadParams -InFile .\$FileName -Uri "${UploadDestURL}/${FileName}" + + If (($env:VIEWER_USE_CRASHPAD -eq 'TRUE') -and ($build_type -eq "vc-64")) + { + sentry-cli upload-dif --include-sources singularity-bin.exe singularity-bin.pdb crashpad_handler.exe crashpad_handler.pdb fmod.dll libcrypto-1_1.dll libcrypto-1_1.pdb libssl-1_1.dll libssl-1_1.pdb libcrypto-1_1-x64.dll libcrypto-1_1-x64.pdb libssl-1_1-x64.dll libssl-1_1-x64.pdb vcruntime140.dll msvcp140.dll libhunspell.dll libhunspell.pdb glod.dll + } + Pop-Location + } + } + + try_upload("linux-64", "Singularity_*.tar.xz") + try_upload("vc-64", "Singularity_*_Setup.exe") + try_upload("vc-32", "Singularity_*_Setup.exe") + + If ($env:VIEWER_USE_CRASHPAD -eq 'TRUE') + { + sentry-cli releases new $BuildChannelVersion + sentry-cli releases set-commits --auto $BuildChannelVersion + sentry-cli releases finalize $BuildChannelVersion + } + +upload:project: + extends: + - .upload_template + rules: + - if: '$BUILD_CHANNEL == "Project" && ($CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "schedule")' + when: manual + - if: '$CI_COMMIT_TAG =~ /.*-project/' + when: manual + environment: + name: qa + +upload:beta: + extends: + - .upload_template + rules: + - if: '$BUILD_CHANNEL == "Beta" && ($CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "schedule")' + when: manual + - if: '$CI_COMMIT_TAG =~ /.*-beta/' + when: manual + environment: + name: beta + +upload:release: + extends: + - .upload_template + rules: + - if: '$BUILD_CHANNEL == "Release" && ($CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "schedule")' + when: manual + - if: '$CI_COMMIT_TAG =~ /.*-release/' + when: manual + environment: + name: release diff --git a/AscentChangelog.txt b/AscentChangelog.txt deleted file mode 100644 index d7c9aff00c..0000000000 --- a/AscentChangelog.txt +++ /dev/null @@ -1,81 +0,0 @@ -->> Features implemented in Ascent: - -In-World: -------------------------------------------------- -* Alpha skins and Tattoo Layers -* Inventory Pre-caching -* Avatar Radar -* Multiple Attachment Points -* Idle time of avatars around you (Not perfect) -* Client tags/coloring for various clients, and extra client definitions -* Force Away button to fake being away if you really want to avoid someone :V -* Double-Click teleport (Not all the functionality of Emerald yet) -Preferences (Options are in Ascent Options): -* Disable Look At -* Disable Point At and beam end -* Fetch inventory in background on login (No waiting for caching when searching) -* Display your client tag to yourself -* Display your client tag color to yourself -* Rez objects as land group when possible -* Some settings can now be saved per account after changing an option in the preferences. Currently affected settings: - Edit Beam color - Client Tag Color -Communication Window: -- Friend List: - * Friend List Online/Total counts (Not perfect) - * Shows what rights your friends have given you (Mod, See on map, Online) - -Chat Bar: -* Emerald-style Chatbar as Commandline (See Preferences) -* MU-style poses. -* OOC Auto-close. - -Instant Messages: -* MU-style poses. -* OOC Auto-close. - -Advanced -> Ascent: -* Fake Away Status -* Force Ground Sit (Lets you sit anywhere) -* Phantom Avatar (Prevents you visually from being pushed.) -* Toggle IM Notification (Ability to hide '%n is typing...' notification from being sent.) -* Close All Dialogs -* Message Log -* Message Builder -* Sound Explorer -* Asset Blacklist -* AO options - -Object Pie Menus: -* Measure: Select on one object, then another, to get the exact distance between the two -* Data: Reports prim rotation and position in a format usable in LSL scripts. -* Script Counter - -Self Pie Menu: -* Animation Explorer - -Agent Pie Menus: -* Script Counter -* Copy Agent UUID -* Debug - -Parcel Window: -------------------------------------------------- -- General tab: -- Objects tab: - * In Sim/Online/Offline indicators for Parcel Object Owner listings (Online is currently wonky - This is an issue with SL, Emerald has the same problem.) - -Build Window: -------------------------------------------------- -- General tab: - * Last Owner shown in Build "General" Tab - * Group object is set to has a "View" button to see the group's profile - * Copy Object Key button -- Build Tab: - * Copy/Paste Position buttons - * Copy/Paste Size buttons - * Copy/Paste Rotation buttons - * Copy/Paste Primitive Parameters buttons - -Known issues: -Online/Total counts in the friends list sometimes go haywire. Not often or by a large margin, but it happens. \ No newline at end of file diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000000..81e20cec2d --- /dev/null +++ b/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[dev-packages] + +[packages] +llbase = "*" +certifi = "*" +autobuild = {git = "https://git.alchemyviewer.org/alchemy/autobuild.git"} + +[requires] +python_version = "2.7" diff --git a/README b/README index 8d470c1c9f..17136fb371 100644 --- a/README +++ b/README @@ -18,7 +18,7 @@ as those based upon the OpenSim platform. Singularity is maintained by a small group of volunteers who can be contacted both, in-world (SingularityViewer group) as well as on IRC (#SingularityViewer @ FreeNode). Bug requests and features requests can be submitted through our -Issue Tracker (http://code.google.com/p/singularity-viewer/issues/list or from +Issue Tracker (http://links.singularityviewer.org/?to=issues or from the viewer menu: Help --> Bug Reporting --> Singularity Issue Tracker...) diff --git a/autobuild.xml b/autobuild.xml new file mode 100644 index 0000000000..13549ba62a --- /dev/null +++ b/autobuild.xml @@ -0,0 +1,3030 @@ + + + + installables + + SDL + + copyright + Copyright (c) 2004, 2006-2013 Sam Lantinga + description + Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer. + license + lgpl + license_file + LICENSES/SDL.txt + name + SDL + platforms + + linux + + archive + + hash + 8da309d24fb0bad8eaaa667fb04c6dc7 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3pl_3p-sdl-update/rev/290561/arch/Linux/installer/SDL-1.2.15-linux-20140602.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 5c8df43ff04799f3f675b8a0f328f184 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/SDL-1.2.15-linux64-201603241005.tar.bz2 + + name + linux64 + + + version + 1.2.15 + + apr_suite + + copyright + Copyright © 2012 The Apache Software Foundation, Licensed under the Apache License, Version 2.0. + description + Apache portable runtime project + license + Apache 2.0 + license_file + LICENSES/apr_suite.txt + name + apr_suite + platforms + + darwin + + archive + + hash + 1eca2a268913083596127b46570779ab + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/apr_suite-1.5.2-darwin-201511222106.tar.bz2 + + name + darwin + + linux + + archive + + hash + f38c966a430012dc157fdc104f23a59b + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/259951/arch/Linux/installer/apr_suite-1.4.5-linux-20120618.tar.bz2 + + name + linux + + linux64 + + archive + + hash + cd30af9b015c373bed5062b1642a1b3e + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/apr_suite-1.5.2-linux64-201603240800.tar.bz2 + + name + linux64 + + windows + + archive + + hash + d0cf074a2c95a65b8833350dad77c0ae + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/apr_suite-1.5.2-windows-201703090634.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 1e7eb1da6e3e792db85f59012680a877 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/apr_suite-1.6.3-1.6.1-1.2.2-windows64-201712260041.tar.bz2 + + name + windows64 + + + version + 1.6.3-1.6.1-1.2.2 + + ares + + copyright + Copyright 1998 by the Massachusetts Institute of Technology. + description + C-ares, an asynchronous resolver library. + license + c-ares + license_file + LICENSES/c-ares.txt + name + ares + platforms + + darwin + + archive + + hash + 9a42795b21203afe858db16703929436 + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/ares-1.10.0-darwin-201511222040.tar.bz2 + + name + darwin + + linux + + archive + + hash + 92f6a454d90b5740a38fb68e369cc13e + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3pl_3p-ares-update/rev/290399/arch/Linux/installer/ares-1.10.0-linux-20140529.tar.bz2 + + name + linux + + linux64 + + archive + + hash + bef927b60affa6b5c0520f45c56b5cb3 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/ares-1.10.0-linux64-201603240702.tar.bz2 + + name + linux64 + + windows + + archive + + hash + 0c01eb6ae9b92365ace8e70cf3999bfc + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/windows/lib-vc14/ares-1.10.0-windows-201601150954.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 6da2b095ad9616d8a8eae9a6a5b3f2c4 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/windows64/lib-vc14/ares-1.10.0-windows64-201512122047.tar.bz2 + + name + windows64 + + + version + 1.10.0 + + boost + + copyright + (see individual source files) + description + Boost C++ Libraries + license + boost 1.0 + license_file + LICENSES/boost.txt + name + boost + platforms + + darwin + + archive + + hash + 5e6a0930ca5c9e3c26970ac8589a538c + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/boost-1.59.0-darwin-201601091139.tar.bz2 + + name + darwin + + linux + + archive + + hash + 2f076eae296600a1b810ce375dc4b42d + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3pl_3p-boost-update/rev/290566/arch/Linux/installer/boost-1.55.0-linux-20140602.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 74a88afa7ff50462059c17321f91a359 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/boost-1.60.0-linux64-201603241316.tar.bz2 + + name + linux64 + + windows + + archive + + hash + ae0998e5d108c77c5cea2a68ad928151 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/boost-1.63.0-windows-201703281813.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 6faba32dcfb80c26bafd4a3e06cff268 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/boost-1.66.0-windows64-201712260832.tar.bz2 + + name + windows64 + + + version + 1.66.0 + + colladadom + + copyright + Copyright 2006 Sony Computer Entertainment Inc. + license + SCEA + license_file + LICENSES/collada.txt + name + colladadom + platforms + + darwin + + archive + + hash + d6e279fb5ce9093c89819803be5562db + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/colladadom-2.3-darwin-201601091204.tar.bz2 + + name + darwin + + linux + + archive + + hash + bdec5fe5fd008da4328f84115128ee61 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3pl_3p-colladadom-update/rev/290576/arch/Linux/installer/colladadom-2.3-linux-20140602.tar.bz2 + + name + linux + + linux64 + + archive + + hash + c84d1be467d7198103d905f710fa31d3 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/colladadom-2.3-linux64-201603241731.tar.bz2 + + name + linux + + windows + + archive + + hash + 60bd2dbac5559141e05be6c424cf9cd0 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/colladadom-2.3-windows-201703281922.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 65628150b732274f0bdd0fa33d6ca650 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/colladadom-2.3-windows64-201712260938.tar.bz2 + + name + windows64 + + + version + 2.3 + + crashpad + + canonical_repo + https://git.alchemyviewer.org/alchemy/thirdparty/3p-crashpad + copyright + Copyright 2014 The Crashpad Authors. All rights reserved. + description + Crashpad is a crash-reporting system. + license + Apache 2.0 + license_file + LICENSES/crashpad.txt + name + crashpad + platforms + + windows + + archive + + hash + a96fda7ad5cee967823f5c94390ba35b + hash_algorithm + md5 + url + https://pkg.alchemyviewer.org/repository/autobuild-external/crashpad/windows/crashpad-c6d76a90.194-windows-194.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 5ff95ca1007ed2dc300b59de17453201 + hash_algorithm + md5 + url + https://pkg.alchemyviewer.org/repository/autobuild-external/crashpad/windows64/crashpad-c6d76a90.194-windows64-194.tar.bz2 + + name + windows64 + + + version + c6d76a90.194 + + curl + + copyright + Copyright (c) 1996 - 2017, Daniel Stenberg,(daniel@haxx.se), and many contributors. + description + Library for transferring data specified with URL syntax + license + curl + license_file + LICENSES/curl.txt + name + curl + platforms + + darwin + + archive + + hash + cc59e267a98b1b433574470a07737609 + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/curl-7.48.0-darwin-201603231616.tar.bz2 + + name + darwin + + linux + + archive + + hash + 06149da3d7a34adf40853f813ae55328 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3pl_3p-curl-update/rev/295367/arch/Linux/installer/curl-7.38.0-linux-20141010.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 24a88e015ee9c1806e7aeb46887d38f5 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/curl-7.48.0-linux64-201603240914.tar.bz2 + + name + linux64 + + windows + + archive + + hash + da5be630ca350a7ed4c0e99250451d41 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/curl-7.56.1-windows-201711241310.tar.bz2 + + name + windows + + windows64 + + archive + + hash + c797cd1538ab1750adbc28b334a50005 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc1414/curl-7.61.0-windows64-201808061947.tar.bz2 + + name + windows64 + + + version + 7.57.0 + + dbus-glib + + copyright + Copyright (C) Red Hat Inc. + description + D-Bus bindings for glib + license + Academic Free License v. 2.1 + license_file + LICENSES/dbus-glib.txt + name + dbus-glib + platforms + + linux + + archive + + hash + 94b058b9a81114dc4567bd78e4335425 + url + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/dbus_glib-0.76-linux-20110310.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 84e51f2e14db023be5419e74ab3b51d3 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/linux64/lib/dbus_glib-0.76-linux64-201501030130.tar.bz2 + + name + linux64 + + + version + 0.76 + + dictionaries + + copyright + Copyright 2014 Apache OpenOffice software + description + Spell checking dictionaries to bundled into the viewer + license + various open source + license_file + LICENSES/dictionaries.txt + name + dictionaries + platforms + + common + + archive + + hash + 078604ad9373fe35081a7d3e4892ae41 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/common/lib/dictionaries-1-common-201412301501.tar.bz2 + + name + common + + + version + 1 + + discord-rpc + + canonical_repo + https://bitbucket.org/alchemyviewer/3p-discord-rpc + copyright + Copyright 2017 Discord, Inc. + description + Discord Remote Procedure Call library + license + MIT + license_file + LICENSES/discord-rpc.txt + name + discord-rpc + platforms + + windows64 + + archive + + hash + 76bd78e14034e9c518c1a201074d568a + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/packages/windows64/msvc-1916/discord_rpc-3.4.0.190570542-windows64-190570542.tar.bz2 + + name + windows64 + + + version + 3.4.0.190570542 + + dullahan + + copyright + Copyright (c) 2017, Linden Research, Inc. + description + A headless browser SDK that uses the Chromium Embedded Framework (CEF). It is designed to make it easier to write applications that render modern web content directly to a memory buffer, inject synthesized mouse and keyboard events as well as interact with web based features like JavaScript or cookies. + license + MPL + license_file + LICENSES/LICENSE.txt + name + dullahan + platforms + + darwin64 + + archive + + hash + 118987b1a5b56214cfdbd0c763e180da + url + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/15127/97748/dullahan-1.1.1080_3.3325.1750.gaabe4c4-darwin64-513449.tar.bz2 + + name + darwin64 + + linux64 + + archive + + hash + 695efb6fc548a56dc4ff34e8d9a37bfb + hash_algorithm + md5 + url + https://bitbucket.org/router_gray/3p-dullahan/downloads/dullahan-1.3.202002250830_79.1.38_gecefb59_chromium-79.0.3945.130-linux64-200580406.tar.bz2 + + name + linux64 + + windows + + archive + + hash + 1b278ff2535f428ea6536683d096fdd0 + hash_algorithm + md5 + url + https://pkg.alchemyviewer.org/repository/autobuild-external/dullahan/windows/dullahan-1.3.201911222116_78.3.7_gea7ef34_chromium-78.0.3904.108-windows-2.tar.bz2 + + name + windows + + windows64 + + archive + + hash + b9346fea7643b10308c7bd9a769ef5f7 + hash_algorithm + md5 + url + https://pkg.alchemyviewer.org/repository/autobuild-external/dullahan/windows64/dullahan-1.3.201911222103_78.3.7_gea7ef34_chromium-78.0.3904.108-windows64-2.tar.bz2 + + name + windows64 + + + version + 1.3.201911222103_78.3.7_gea7ef34_chromium-78.0.3904.108 + + elfio + + license + lgpl + license_file + LICENSES/elfio.txt + name + elfio + platforms + + linux + + archive + + hash + 031e6315a5c0829c9b9a2ec18aeb7ae3 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-elfio/rev/222074/arch/Linux/installer/elfio-1.0.3-linux-20110225.tar.bz2 + + name + linux + + + + expat + + copyright + Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper - Copyright (c) 2001-2017 Expat maintainers + description + Expat is an XML parser library written in C + license + expat + license_file + LICENSES/expat.txt + name + expat + platforms + + darwin + + archive + + hash + fc3e46e4737b326b0ca926534ddce9f3 + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/expat-2.1.1-darwin-201603271445.tar.bz2 + + name + darwin + + linux + + archive + + hash + 9bd79781b58e556ab1c36084ec4a1c0c + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-expat/rev/221695/arch/Linux/installer/expat-2.0.1-linux-20110219.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 3ed12f7d7b1a3bda07a3c6d8227a3bf2 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/expat-2.1.1-linux64-201603232308.tar.bz2 + + name + linux64 + + windows + + archive + + hash + f10218f7c28d63a3d9f1fb683d116bf8 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/expat-2.2.0-windows-201703090626.tar.bz2 + + name + windows + + windows64 + + archive + + hash + db56a24bbac59d9ad8b98d40b7140c29 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/expat-2.2.5-windows64-201712251923.tar.bz2 + + name + windows64 + + + version + 2.2.5 + + fmodstudio + + copyright + FMOD Studio, Copyright (c) Firelight Technologies Pty Ltd. + description + FMOD Studio audio system library + license + fmodstudio + license_file + LICENSES/fmodstudio.txt + name + fmodstudio + platforms + + darwin64 + + archive + + creds + gitlab + hash + db27e5c974e41d822c75038a6816b07362d54f1b0a64f21a63f0b7076f94c4a34934145bc326a1cc946996abec4b9a5c47e8ef9c68a694e129f09876080d74ac + hash_algorithm + blake2b + url + https://git.alchemyviewer.org/api/v4/projects/49/packages/generic/fmodstudio/2.02.06.1475/fmodstudio-2.02.06-darwin64-1475.tar.zst + + name + darwin64 + + linux64 + + archive + + creds + gitlab + hash + f430175d7af2a8f5e084cd789df904944b117eebb462211eafa80ea5c7f23399449c5a52faf35b3b81a09c51fdff0273741fb32c55f9c615a51b1f15a5094ca5 + hash_algorithm + blake2b + url + https://git.alchemyviewer.org/api/v4/projects/49/packages/generic/fmodstudio/2.02.06.1475/fmodstudio-2.02.06-linux64-1475.tar.zst + + name + linux64 + + windows + + archive + + hash + 50ce25e855c10d3b39f5461f34661c7f + hash_algorithm + md5 + url + https://pkg.alchemyviewer.org/repository/autobuild-internal/fmodstudio/windows/fmodstudio-2.01.04.417-windows-417.tar.bz2 + + name + windows + + windows64 + + archive + + creds + gitlab + hash + 7ad5fe064e3a7f45234a3658315a86d80b85f5f49f8a1767e1453116bd23eda67a014c521cf26529fb6bbada3441e64ddffef98ddfa85ae846d8aec72ba6fc70 + hash_algorithm + blake2b + url + https://git.alchemyviewer.org/api/v4/projects/49/packages/generic/fmodstudio/2.02.06.1475/fmodstudio-2.02.06-windows64-1475.tar.zst + + name + windows64 + + + version + 2.02.06 + + fonts + + copyright + Copyright (c) 2003 by Bitstream, Inc. Copyright (c) 2012 Adobe, Inc. + description + Font collection + license + Various + license_file + LICENSES/fonts.txt + name + fonts + platforms + + common + + archive + + hash + b0172c35f6a8ac385c71604398966f80 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/packages/common/fonts-20190402.1-common-190922141.tar.bz2 + + name + common + + + version + 20190402.1 + + freeglut + + copyright + Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + description + freeglut is a completely OpenSourced alternative to the OpenGL Utility Toolkit (GLUT) library. + license + freeglut + license_file + LICENSES/freeglut.txt + name + freeglut + platforms + + windows + + archive + + hash + f98709114cedcdfdce69c9df6a4ac2f4 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/windows/lib-vc14/freeglut-3.0.0-windows-201601151006.tar.bz2 + + name + windows + + windows64 + + archive + + hash + f281e5b16b380c3e3a77aafa47ba5500 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/windows64/lib-vc14/freeglut-3.0.0-windows64-201512130218.tar.bz2 + + name + windows64 + + + version + 3.0.0 + + freetype + + copyright + Copyright 2006-2018 by David Turner, Robert Wilhelm, and Werner Lemberg. + description + Font rendering library + license + FreeType + license_file + LICENSES/freetype.txt + name + freetype + platforms + + darwin + + archive + + hash + 8d41fe8cb821e7e080160586a53feec8 + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/freetype-2.6.1-darwin-201511222222.tar.bz2 + + name + darwin + + windows + + archive + + hash + bdbfc3b58cfc2f125881be748d092645 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/freetype-2.8.0-windows-201710192344.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 7c028ec152b1dee1313c084d96a5d276 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/freetype-2.8.1-windows64-201712260751.tar.bz2 + + name + windows64 + + + version + 2.8.1 + + glext + + copyright + Copyright (c) 2013-2014 The Khronos Group Inc. + description + glext headers define function prototypes and constants for OpenGL extensions + license + MIT + license_file + LICENSES/glext.txt + name + glext + platforms + + common + + archive + + hash + c00da9333b1bd0f9cc121ebc365fe360 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/common/lib/glext-20150325-common-201504222056.tar.bz2 + + name + common + + + version + 20150325 + + glh-linear + + copyright + Copyright (c) 2000 Cass Everitt + description + glh - is a platform-indepenedent C++ OpenGL helper library + license + BSD + license_file + LICENSES/glh-linear.txt + name + glh-linear + platforms + + common + + archive + + hash + fed9e6e9de1ea8210b0519f54df81bef + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/common/lib/glh_linear-0.0.0-common-201412301528.tar.bz2 + + name + common + + + version + 0.0.0 + + glod + + copyright + Copyright 2003 Jonathan Cohen, Nat Duca, David Luebke, Brenden Schubert - Johns Hopkins University and University of Virginia + description + Geometric Level of Detail library + license + GLOD Open-Source License Version 1.0 + license_file + LICENSES/GLOD.txt + name + glod + platforms + + darwin + + archive + + hash + 71e678d70e276fc42a56926fc28a7abd + hash_algorithm + md5 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glod_3p-update-glod/rev/296895/arch/Darwin/installer/glod-1.0pre4.296895-darwin-296895.tar.bz2 + + name + darwin + + darwin64 + + archive + + hash + 017ef34ddf14293099a90c6eaa3615ca + url + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1626/3627/glod-1.0pre3.501614-darwin64-501614.tar.bz2 + + name + darwin64 + + linux + + archive + + hash + 58113bcbbacbaeb2d278f745867ae6f0 + hash_algorithm + md5 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glod/rev/314201/arch/Linux/installer/glod-1.0pre4.314201-linux-314201.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 9aef5cd576ace19568da01d9bc3db29c + url + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1625/3628/glod-1.0pre3.501614-linux64-501614.tar.bz2 + + name + linux64 + + windows + + archive + + hash + 573e68f46f825a1c040daa4994ee2a61 + hash_algorithm + md5 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1627/3633/glod-1.0pre3.501614-windows-501614.tar.bz2 + + name + windows + + windows64 + + archive + + hash + c122ba644e8ec146b4742428b799d749 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/packages/windows64/msvc-1916/glod-1.0pre3.190390340-windows64-190390340.tar.bz2 + + name + windows64 + + + version + 1.0pre3.190390340 + + gperftools + + copyright + Copyright (c) 2005, Google Inc. + description + Fast, multi-threaded malloc() and nifty performance analysis tools + license + BSD + license_file + LICENSES/gperftools.txt + name + gperftools + platforms + + linux + + archive + + hash + 8aedfdcf670348c18a9991ae1b384a61 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-perftools/rev/262672/arch/Linux/installer/gperftools-2.0-linux-20120727.tar.bz2 + + name + linux + + windows + + archive + + hash + e81d9e4526ceac49f1532d6518085985 + url + https://depot.alchemyviewer.org/pub/windows/lib/gperftools-2.1-windows-20140120.tar.bz2 + + name + windows + + windows64 + + archive + + hash + da6ec7472ed69fe3231eb95432a789d9 + url + https://bitbucket.org/alchemyviewer/publiclibs/downloads/gperftools-2.2-windows64-20140605.tar.bz2 + + name + windows + + + version + 2.0.297263 + + gstreamer + + copyright + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + license + LGPL + license_file + LICENSES/gstreamer.txt + name + gstreamer + platforms + + common + + archive + + hash + df57a59e832f9e3ca8ba31e37e383dfb + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/common/lib/gstreamer-0.10.6.201501032013-common-201501032013.tar.bz2 + + name + common + + + version + 0.10.6.201501032013 + + gtk-atk-pango-glib + + copyright + Copyright various(See license file) + description + gtk-atk-pango-glib + license + lgpl + license_file + LICENSES/gtk-atk-pango-glib.txt + name + gtk-atk-pango-glib + platforms + + linux + + archive + + hash + 03694ade27f53199229c03cbbda89214 + url + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/gtk-atk-pango-glib-linux-20101001.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 9678056c5ad714aa7ba1ba4ffcb09859 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/gtk_atk_pango_glib-0.0.2-linux64-201603241949.tar.bz2 + + name + linux64 + + + version + 0.0.2 + + jpeglib + + copyright + Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding. + description + JPEG encoding, decoding library + license + libjpeg-turbo + license_file + LICENSES/jpeglib.txt + name + jpeglib + platforms + + darwin + + archive + + hash + 5cf289747de86451b6a956adea468ac7 + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/jpeglib-1.4.2-darwin-201511222055.tar.bz2 + + name + darwin + + linux + + archive + + hash + dcca1db348831cdb7c6b26dc4076c597 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-jpeglib/rev/224895/arch/Linux/installer/jpeglib-8c-linux-20110323.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 256812a20a66081e05578f91bab5b3e4 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/jpeglib-1.4.2-linux64-201603240711.tar.bz2 + + name + linux64 + + windows + + archive + + hash + a9a7af50c5c1b5319dfea82cd09fdd84 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/jpeglib-1.5.1-windows-201703090615.tar.bz2 + + name + windows + + windows64 + + archive + + hash + d60f195778344b88cc47dc5e19af2cf8 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/jpeglib-1.5.3-windows64-201712251431.tar.bz2 + + name + windows64 + + + version + 1.5.3 + + libhunspell + + copyright + See hunspell.txt + description + Spell checking library + license + LGPL + license_file + LICENSES/hunspell.txt + name + libhunspell + platforms + + darwin + + archive + + hash + c897e44b3f5ac33436a028e6e3a5b29b + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/libhunspell-1.3.3-darwin-201511222015.tar.bz2 + + name + darwin + + linux + + archive + + hash + 0c432d2626aea2e91a56335879c92965 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-hunspell/rev/259874/arch/Linux/installer/libhunspell-1.3.2-linux-20120616.tar.bz2 + + name + linux + + linux64 + + archive + + hash + f58652f3217c1e897e9051aa19d99139 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/libhunspell-1.3.3-linux64-201603240026.tar.bz2 + + name + linux64 + + windows + + archive + + hash + cfce0b7d65b28b34fd0643cbcf7b0bac + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/libhunspell-1.6.0-windows-201703090619.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 46e0276052dc614fe890f2a5d6f814b9 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/libhunspell-1.6.2-windows64-201712251236.tar.bz2 + + name + windows64 + + + version + 1.3.3 + + libidn + + copyright + Copyright (C) 2002-2013 Simon Josefsson + description + Libidn's purpose is to encode and decode internationalized domain names. + license + LGPL + license_file + LICENSES/libidn.txt + name + libidn + platforms + + darwin + + archive + + hash + 4c1f76a59c9abd7590b60b1507c16540 + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/libidn-1.32-darwin-201511222141.tar.bz2 + + name + darwin + + linux64 + + archive + + hash + e3d59bdb4418f50365fbae7a866b4e23 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/libidn-1.32-linux64-201603240734.tar.bz2 + + name + linux64 + + + version + 1.32 + + libndofdev + + copyright + Copyright (c) 2007, 3Dconnexion, Inc. - All rights reserved. + description + 3DConnexion SDK + license + BSD + license_file + LICENSES/libndofdev.txt + name + libndofdev + platforms + + darwin + + archive + + hash + 1d542606b146462cdfdc47a94f14eaf5 + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/libndofdev-0.1-darwin-201504232110.tar.bz2 + + name + darwin + + windows + + archive + + hash + e2927116641e2c74ada092bfb6b49a8d + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/libndofdev-0.1-windows-201703090613.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 3ac8047b38b617ad686591e00100d6af + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/libndofdev-0.1-windows64-201712251124.tar.bz2 + + name + windows64 + + + version + 0.1 + + libndofdev-open + + copyright + Copyright (c) 2008, Jan Ciger (jan.ciger (at) gmail.com) + description + 3DConnection SDK + license + BSD + license_file + LICENSES/libndofdev.txt + name + libndofdev-open + platforms + + linux64 + + archive + + hash + d3fd1dab78123c39391b0afb372e5cf1 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/libndofdev_open-0.8-linux64-201603241018.tar.bz2 + + name + linux64 + + + version + 0.8 + + libpng + + copyright + Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson + description + PNG Reference library + license + libpng + license_file + LICENSES/libpng.txt + name + libpng + platforms + + darwin + + archive + + hash + 7c315d3fee9f9bf7e36c4251c41fa378 + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/libpng-1.6.19-darwin-201511222146.tar.bz2 + + name + darwin + + linux + + archive + + hash + 3368a25b361c22a03f7ec7e0f8d5ff9d + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3pl_3p-libpng-update/rev/290558/arch/Linux/installer/libpng-1.6.8-linux-20140602.tar.bz2 + + name + linux + + linux64 + + archive + + hash + cd64cda7107b967279d5af03b0d46a8f + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/libpng-1.6.21-linux64-201603240933.tar.bz2 + + name + linux64 + + windows + + archive + + hash + 9aad0afaf2c1895224454c1dc433f481 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/libpng-1.6.34-windows-201710172201.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 528889464c0766d762bd528cf82558db + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/libpng-1.6.34-windows64-201712260746.tar.bz2 + + name + windows64 + + + version + 1.6.34 + + libxml2 + + copyright + Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved. + description + Libxml2 is the XML C parser and toolkit developed for the Gnome project. + license + MIT + license_file + LICENSES/libxml2.txt + name + libxml2 + platforms + + darwin + + archive + + hash + 242ffec9e9f8fca818b750c578eba0dd + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/libxml2-2.9.3-darwin-201511222121.tar.bz2 + + name + darwin + + linux + + archive + + hash + 7eb90f075730f8d7d176f8fb7bad5ef5 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3pl_3p-libxml-update/rev/290562/arch/Linux/installer/libxml2-2.9.1-linux-20140602.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 61351b10787b06045a70c905a58ca2f6 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/libxml2-2.9.3-linux64-201603241216.tar.bz2 + + name + linux64 + + windows + + archive + + hash + a3f7c3421e9e4921dda3558c3b36dc59 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/libxml2-2.9.4-windows-201703090740.tar.bz2 + + name + windows + + windows64 + + archive + + hash + f69b1d4ec7ffdeec4429413ea640583d + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/libxml2-2.9.7-windows64-201712260755.tar.bz2 + + name + windows64 + + + version + 2.9.3 + + llphysicsextensions_stub + + copyright + Copyright (c) 2010, Linden Research, Inc. + license + internal + license_file + LICENSES/llphysicsextensions.txt + name + llphysicsextensions_stub + platforms + + darwin + + archive + + hash + 1175977a191ffc936fd0ccca433c8278 + hash_algorithm + md5 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub_llphysicsextensions-update/rev/298370/arch/Darwin/installer/llphysicsextensions_stub-1.0.298370-darwin-298370.tar.bz2 + + name + darwin + + linux + + archive + + hash + d13d7927692eab2d6a63e36166b72a8a + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub_llphysicsextensions-update/rev/298370/arch/Linux/installer/llphysicsextensions_stub-1.0.298370-linux-298370.tar.bz2 + + name + linux + + linux64 + + archive + + hash + aa8a2f25e8629cf5e6a96cc0eb93de8e + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub/rev/263415/arch/Linux/installer/llphysicsextensions_stub-0.3-linux-20120814.tar.bz2 + + name + linux64 + + windows + + archive + + hash + 9594f6fd79ee924fe675a4a23e30516e + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub_llphysicsextensions-update/rev/298370/arch/CYGWIN/installer/llphysicsextensions_stub-1.0.298370-windows-298370.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 50d7ea325063219a86d9439ce7458582 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/windows64/lib/llphysicsextensions_stub-1.0.298370-windows64-298370.tar.bz2 + + name + windows64 + + + version + 1.0.298370 + + mesa + + license + mesa + license_file + LICENSES/mesa.txt + name + mesa + platforms + + linux + + archive + + hash + 22c50a5d362cad311b4f413cfcffbba2 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/mesa_3p-update-mesa/rev/297294/arch/Linux/installer/mesa-7.11.1.297294-linux-297294.tar.bz2 + + name + linux + + + version + 7.11.1.297294 + + nvapi + + copyright + Copyright (c) 2007- 2019 NVIDIA Corporation. All rights reserved. + license + nvapi + license_file + LICENSES/nvapi.txt + name + nvapi + platforms + + windows + + archive + + hash + 408eff309f6f3031d74da5491c1852a9 + hash_algorithm + md5 + url + https://pkg.alchemyviewer.org/repository/autobuild-internal/nvapi/windows/nvapi-R430.192211828-windows-192211828.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 76a547f558b8499dc85135b8718eb18a + hash_algorithm + md5 + url + https://pkg.alchemyviewer.org/repository/autobuild-internal/nvapi/windows64/nvapi-R430.192211828-windows64-192211828.tar.bz2 + + name + windows64 + + + version + R430.192211828 + + ogg_vorbis + + copyright + Copyright (c) 2002, Xiph.org Foundation + description + Audio encoding library + license + ogg-vorbis + license_file + LICENSES/ogg-vorbis.txt + name + ogg_vorbis + platforms + + darwin + + archive + + hash + 83959618755a09d1af245e402f4b6232 + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/ogg_vorbis-1.3.2-1.3.5-darwin-201511222036.tar.bz2 + + name + darwin + + linux + + archive + + hash + 71eaa462eb0bf8842277a3436483a354 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-ogvorbis/rev/229529/arch/Linux/installer/ogg_vorbis-1.2.2-1.3.2-linux-20110511.tar.bz2 + + name + linux + + linux64 + + archive + + hash + d847ea384530e0bbb3774065dbdae65c + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/ogg_vorbis-1.3.2-1.3.5-linux64-201603240037.tar.bz2 + + name + linux64 + + windows + + archive + + hash + 41d090321853ea941c5ca57ba0d471d0 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/ogg_vorbis-1.3.2-1.3.5-windows-201703090612.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 01ae2d298489ea66597c5e302e8e4525 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/ogg_vorbis-1.3.2-1.3.5-windows64-201712251411.tar.bz2 + + name + windows64 + + + version + 1.3.2-1.3.5 + + openal + + copyright + Creative Labs + description + OpenAL is a cross-platform 3D audio API appropriate for use with gaming applications and many other types of audio applications. + license + lgpl + license_file + LICENSES/openal.txt + name + openal + platforms + + darwin + + archive + + hash + 4c0dd5385dbd8787d134e5e91f82f04a + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/openal-1.16.0-1.1.0-darwin-201412160747.tar.bz2 + + name + darwin + + linux + + archive + + hash + fccdca18a950ac9363c6fb39118b80e1 + hash_algorithm + md5 + url + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/openal-3ad86a1c-linux-20110114.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 7fea13f8caab7bf9184e0790eab9c2f3 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/openal-1.17.2-1.1.0-linux64-201603232035.tar.bz2 + + name + linux64 + + windows + + archive + + hash + fa39ac8fe3714599293563fb7f964fca + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/windows/lib/openal-1.16.0-1.1.0-windows-201504270536.tar.bz2 + + name + windows + + windows64 + + archive + + hash + fec29528320a2a67ffa7b3900135592d + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib/openal-1.16.0-1.1.0-windows64-201504270534.tar.bz2 + + name + windows64 + + + version + 1.17.2-1.1.0 + + openssl + + copyright + Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved; Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + description + Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) Library + license + openssl + license_file + LICENSES/openssl.txt + name + openssl + platforms + + darwin + + archive + + hash + d415e218a7f3d0d1e3dd4f99d6129e6c + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/openssl-1.0.2g-darwin-201603010806.tar.bz2 + + name + darwin + + linux + + archive + + hash + 0665c18f8cdbe2f90cb0a2f088cfe1a6 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3pl_3p-openssl-update/rev/290662/arch/Linux/installer/openssl-1.0.1h-linux-20140605.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 2a50dcb704f6af595fff44defc4b65df + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/openssl-1.0.2g-linux64-201603240821.tar.bz2 + + name + linux64 + + windows + + archive + + hash + 0d25e1794f5d86b675484bf5eda799e4 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/openssl-1.1.0g-windows-201711200028.tar.bz2 + + name + windows + + windows64 + + archive + + hash + bd35903f309ccf026a2c448fd8613cc0 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/openssl-1.1.0g-windows64-201712260729.tar.bz2 + + name + windows64 + + + version + 1.1.0g + + quicktime + + copyright + 2010 Apple + description + QuickTime 7.3 SDK for Windows + license + unknown + license_file + LICENSES/quicktime.txt + name + quicktime + platforms + + windows + + archive + + hash + 66600ab94087d295e48e326ec8961ac5 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/windows/lib/quicktime-7.3-windows-201504280653.tar.bz2 + + name + windows + + + version + 7.3 + + slvoice + + copyright + 2010 Vivox, including audio coding using Polycom¨ Siren14TM (ITU-T Rec. G.722.1 Annex C) + description + Vivox SDK components + license + Mixed + license_file + LICENSES/slvoice.txt + name + slvoice + platforms + + darwin + + archive + + hash + b1b0134bc55f55a7c1a04ee78d70c64d + hash_algorithm + md5 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12438/73598/slvoice-4.9.0002.27586.511884-darwin64-511884.tar.bz2 + + name + darwin + + linux + + archive + + hash + 9f60e56aba35ec90b3045e9d049ac284 + url + http://depot.alchemyviewer.org/pub/linux/lib/slvoice-4.5.0009.17865-linux-20141214.tar.bz2 + + name + linux + + linux64 + + archive + + hash + df43d3df49296bfe93996ec537b9eddf + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib/slvoice-4.6.0009.20030-linux64-201501031918.tar.bz2 + + name + linux64 + + windows + + archive + + hash + ec50c31efce74bdedee470b5388aeeec + hash_algorithm + md5 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12434/73576/slvoice-4.9.0002.27586.511884-windows-511884.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 4bf45d641bf5b2bd6b2cc39edcb01a6e + hash_algorithm + md5 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12433/73570/slvoice-4.9.0002.27586.511884-windows64-511884.tar.bz2 + + name + windows64 + + + version + 4.9.0002.27586.511884 + + tut + + copyright + Copyright 2002-2006 Vladimir Dyuzhev, Copyright 2007 Denis Kononenko, Copyright 2008-2009 Michał Rzechonek + description + TUT is a small and portable unit test framework for C++. + license + bsd + license_file + LICENSES/tut.txt + name + tut + platforms + + common + + archive + + hash + 56601f1217ccd206829e8834e5a1253b + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/common/lib/tut-2008.11.30-common-201504282317.tar.bz2 + + name + common + + + version + 2008.11.30 + + uriparser + + copyright + Copyright (C) 2007, Weijia Song <songweijia@gmail.com>, Sebastian Pipping <webmaster@hartwork.org> + description + uriparser is a strictly RFC 3986 compliant URI parsing and handling library written in C. uriparser is cross-platform, fast, supports Unicode and is licensed under the New BSD license. + license + New BSD license + license_file + LICENSES/uriparser.txt + name + uriparser + platforms + + darwin + + archive + + hash + 364cbc9a049acb2a0d2cd6719a02adf0 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/darwin/lib/uriparser-0.8.4-darwin-201511221948.tar.bz2 + + name + darwin + + linux + + archive + + hash + 34306fb90364b182dc770375140d8557 + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-uriparser/rev/294298/arch/Linux/installer/uriparser-0.8.0.1-linux-20140918.tar.bz2 + + name + linux + + linux64 + + archive + + hash + cf21d9f7ed7949d2230413e8a391fb73 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/linux64/lib-xenial/uriparser-0.8.4-linux64-201609241428.tar.bz2 + + name + linux64 + + windows + + archive + + hash + 89f3fc7f3fe396439d306f099d1a12d3 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/uriparser-0.8.4-windows-201703090606.tar.bz2 + + name + windows + + windows64 + + archive + + hash + ad1a435de73b7ee6d07f6c81a4cb1910 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/uriparser-0.8.4-windows64-201712251116.tar.bz2 + + name + windows64 + + + version + 0.8.4 + + vlc-bin + + copyright + Copyright (C) 1998-2020 VLC authors and VideoLAN + license + GPL2 + license_file + LICENSES/vlc.txt + name + vlc-bin + platforms + + darwin64 + + archive + + hash + e5635e173c75dc0675b48ab5f5e4868b + url + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12143/71451/vlc_bin-2.2.8.511703-darwin64-511703.tar.bz2 + + name + darwin64 + + linux + + archive + + hash + 2f410640df3f9812d1abff02a414cfa8 + url + https://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/315283/arch/Linux/vlc_bin-2.2.3-linux-201606011750-r10.tar.bz2 + + name + linux + + windows + + archive + + hash + 3ff1d097e4f9b8f864a639aff974a506 + url + https://pkg.alchemyviewer.org/repository/autobuild-external/vlc-bin/windows/vlc_bin-3.0.8.189-windows-189.tar.bz2 + + name + windows + + windows64 + + archive + + hash + b890b109b526cc6ad211eadefed83316 + url + https://pkg.alchemyviewer.org/repository/autobuild-external/vlc-bin/windows64/vlc_bin-3.0.8.189-windows64-189.tar.bz2 + + name + windows64 + + + version + 3.0.8.189 + + xmlrpc-epi + + copyright + Copyright: (C) 2000 Epinions, Inc. + description + XMLRPC Library + license + xmlrpc-epi + license_file + LICENSES/xmlrpc-epi.txt + name + xmlrpc-epi + platforms + + darwin + + archive + + hash + 408e34531c6a8ac20ccc8c917435071f + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/xmlrpc_epi-0.54.2-darwin-201603271451.tar.bz2 + + name + darwin + + linux + + archive + + hash + 174ab797440157956eda7061dae37564 + url + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/xmlrpc_epi-0.54.1-linux-20110314.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 0465334ff0f1d57cf354867fd21ee137 + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/xmlrpc_epi-0.54.2-linux64-201603240753.tar.bz2 + + name + linux64 + + windows + + archive + + hash + 4cd5d80362fef95fe486b5bc1c373174 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/xmlrpc_epi-0.54.2-windows-201703090632.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 59f0be2732e93eceaa155d98c2fcee9c + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/xmlrpc_epi-0.54.2-windows64-201712260035.tar.bz2 + + name + windows64 + + + version + 0.54.2 + + zlib + + copyright + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + description + Zlib Data Compression Library + license + zlib + license_file + LICENSES/zlib.txt + name + zlib + platforms + + darwin + + archive + + hash + 635ee875ba478b17b6c64d9698cdf0dd + hash_algorithm + md5 + url + https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/zlib-1.2.8-darwin-201511221937.tar.bz2 + + name + darwin + + linux + + archive + + hash + 63a62bb3cbef2aad3cca49cb6f2d0aeb + url + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3pl_3p-zlib-update/rev/290556/arch/Linux/installer/zlib-1.2.8-linux-20140602.tar.bz2 + + name + linux + + linux64 + + archive + + hash + 1eaee9888043648d5f09716b771dcb4b + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/linux64/lib-trusty/zlib-1.2.8-linux64-201603240746.tar.bz2 + + name + linux64 + + windows + + archive + + hash + 75651f8b2fa45545461f73ba583180bb + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc141/zlib-1.2.11-windows-201703090604.tar.bz2 + + name + windows + + windows64 + + archive + + hash + ed6da4296e2fdfc132b4f12d35890ada + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc142/zlib-1.2.11-windows64-201712260711.tar.bz2 + + name + windows64 + + + version + 1.2.11 + + + package_description + + copyright + Copyright (c) 2010-2016, Singularity Viewer Team + description + Singularity Viewer + license + LGPL + license_file + docs/LICENSE-source.txt + name + Singularity Viewer + platforms + + common + + configurations + + RelWithDebInfo + + configure + + arguments + + ../indra + + command + cmake + options + + -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo + -DADDRESS_SIZE:STRING=$AUTOBUILD_ADDRSIZE + -DROOT_PROJECT_NAME:STRING=Singularity + -DINSTALL_PROPRIETARY=FALSE + + + name + RelWithDebInfo + + Release + + configure + + arguments + + ../indra + + command + cmake + options + + -DCMAKE_BUILD_TYPE:STRING=Release + -DADDRESS_SIZE:STRING=$AUTOBUILD_ADDRSIZE + -DROOT_PROJECT_NAME:STRING=Singularity + -DINSTALL_PROPRIETARY=FALSE + + + name + Release + + + name + common + + darwin + + build_directory + build-darwin-i386 + configurations + + RelWithDebInfo + + build + + command + xcodebuild + options + + -configuration RelWithDebInfo + -project Singularity.xcodeproj + + + configure + + options + + -G + 'Xcode' + + + default + True + name + RelWithDebInfo + + Release + + build + + command + xcodebuild + options + + -configuration Release + -project Singularity.xcodeproj + -DENABLE_SIGNING:BOOL=YES + -DSIGNING_IDENTITY:STRING="Developer ID Application: Linden Research, Inc." + + + configure + + options + + -G + 'Xcode' + + + name + Release + + + name + darwin + + linux + + build_directory + build-linux-i686 + configurations + + RelWithDebInfo + + build + + command + ninja + options + + -v + + + configure + + options + + -G + Ninja + + + default + True + name + RelWithDebInfo + + Release + + build + + command + ninja + options + + -v + + + configure + + options + + -G + Ninja + + + name + Release + + + name + linux + + linux64 + + build_directory + build-linux-x86_64 + configurations + + RelWithDebInfo + + build + + command + ninja + options + + -v + + + configure + + options + + -G + Ninja + -DADDRESS_SIZE:STRING=64 + + + default + True + name + RelWithDebInfo + + Release + + build + + command + ninja + options + + -v + + + configure + + options + + -G + Ninja + -DADDRESS_SIZE:STRING=64 + + + name + Release + + + name + linux64 + + windows + + build_directory + build-vc-$AUTOBUILD_ADDRSIZE + configurations + + RelWithDebInfo + + build + + arguments + + Singularity.sln + + command + msbuild.exe + options + + /p:Configuration=RelWithDebInfo + /p:Platform=Win32 + /t:Build + /p:useenv=true + /verbosity:normal + /m + + + configure + + arguments + + ..\indra + + options + + -G + ${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN} + -A + ${AUTOBUILD_WIN_VSPLATFORM|NOTWIN} + -T + host=${AUTOBUILD_WIN_VSHOST|NOTWIN} + + + default + True + name + RelWithDebInfo + + Release + + build + + arguments + + Singularity.sln + + command + msbuild.exe + options + + /p:Configuration=Release + /p:Platform=${AUTOBUILD_WIN_VSPLATFORM|NOTWIN} + /t:Build + /p:PreferredToolArchitecture=x64 + /p:useenv=true + /verbosity:normal + /m + + + configure + + arguments + + ..\indra + + options + + -G + ${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN} + -A + ${AUTOBUILD_WIN_VSPLATFORM|NOTWIN} + -T + host=${AUTOBUILD_WIN_VSHOST|NOTWIN} + -DINSTALL_PROPRIETARY=FALSE + + + name + Release + + + name + windows + + + version_file + newview/viewer_version.txt + + type + autobuild + version + 1.3 + + diff --git a/doc/asset_urls.txt b/doc/asset_urls.txt deleted file mode 100644 index e42a45c899..0000000000 --- a/doc/asset_urls.txt +++ /dev/null @@ -1,5 +0,0 @@ -SLASSET_LIBS_WIN32=http://automated-builds-secondlife-com.s3.amazonaws.com/oss-viewer/export/slviewer-win32-libs-oss-viewer-1.23.4.0.zip -SLASSET_MD5=http://automated-builds-secondlife-com.s3.amazonaws.com/oss-viewer/export/md5sums-oss-viewer-1.23.4.0.txt -SLASSET_LIBS_DARWIN=http://automated-builds-secondlife-com.s3.amazonaws.com/oss-viewer/export/slviewer-darwin-libs-oss-viewer-1.23.4.0.tar.gz -SLASSET_ART=http://automated-builds-secondlife-com.s3.amazonaws.com/oss-viewer/export/slviewer-artwork-oss-viewer-1.23.4.0.zip -SLASSET_LIBS_LINUXI386=http://automated-builds-secondlife-com.s3.amazonaws.com/oss-viewer/export/slviewer-linux-libs-oss-viewer-1.23.4.0.tar.gz diff --git a/doc/releasenotes-where.txt b/doc/releasenotes-where.txt deleted file mode 100644 index 4af5866905..0000000000 --- a/doc/releasenotes-where.txt +++ /dev/null @@ -1,5 +0,0 @@ -For full release notes, see: - http://wiki.secondlife.com/wiki/Release_Notes - -For a log of viewer changes, see: - doc/viewer-changes.txt diff --git a/doc/viewer-changes.txt b/doc/viewer-changes.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/etc/message.xml b/etc/message.xml index fd019aa706..5f2c3aa068 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -236,6 +236,14 @@ false + ObjectAnimation + + flavor + template + trusted-sender + false + + AvatarAppearance flavor diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 8694c0dccd..3bcd9e1618 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -3,19 +3,7 @@ # cmake_minimum_required should appear before any # other commands to guarantee full compatibility # with the version specified - -cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR) - -# Eventually the third-party support modules (cmake/*.cmake) should -# know the full path to all libraries. Until that happens we need -# per-configuration link directory "libraries//lib/debug" for -# Debug and "libraries//lib/release" for Release, -# RelWithDebInfo, and MinSizeRel. CMake 2.6 does not directly support -# per-configuration link directory specification. However, we can set -# CMP0003 to OLD and link to one library (apr) on a per-configuration -# basis to convince CMake to add the proper link directory. This line -# can be removed when we use full paths for all libraries. -#cmake_policy(SET CMP0003 OLD) +cmake_minimum_required(VERSION 3.14 FATAL_ERROR) set(ROOT_PROJECT_NAME "Singularity" CACHE STRING "The root project/makefile/solution name. Defaults to Singularity.") @@ -23,27 +11,20 @@ project(${ROOT_PROJECT_NAME}) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") -include(Variables) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) -# Load versions now. Install locations need them. -include(BuildVersion) -include(UnixInstall) - -if (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release CACHE STRING +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Build type. One of: Debug Release RelWithDebInfo" FORCE) -endif (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) +endif (NOT CMAKE_BUILD_TYPE) + +include(Variables) +include(00-Common) +include(BuildVersion) +include(CTest) -# Create a 'prepare' target in which to perform setup actions. This -# must be the first target created so other targets can depend on it. -if(NOT STANDALONE) - # We prepare prebuilt binaries when not building standalone. - set(prepare_depends ${CMAKE_BINARY_DIR}/prepare/prebuilt) -endif(NOT STANDALONE) -if(WINDOWS) - set(prepare_depends ${prepare_depends} copy_win_libs) -endif(WINDOWS) -add_custom_target(prepare DEPENDS ${prepare_depends}) +add_subdirectory(deps) add_subdirectory(cmake) add_subdirectory(${LIBS_OPEN_PREFIX}aistatemachine) @@ -66,12 +47,6 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llvfs) add_subdirectory(${LIBS_OPEN_PREFIX}llwindow) add_subdirectory(${LIBS_OPEN_PREFIX}llxml) -if(STANDALONE) - add_subdirectory(${LIBS_OPEN_PREFIX}llqtwebkit) -endif(STANDALONE) - -#add_subdirectory(${LIBS_OPEN_PREFIX}lscript) - if (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts) add_subdirectory(${LIBS_CLOSED_PREFIX}copy_win_scripts) endif (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts) @@ -83,42 +58,12 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llui) # viewer plugins directory add_subdirectory(${LIBS_OPEN_PREFIX}plugins) -# llplugin testbed code (is this the right way to include it?) -#if (NOT LINUX) -# add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest) -#endif (NOT LINUX) - add_subdirectory(${VIEWER_PREFIX}newview/statemachine) add_subdirectory(${VIEWER_PREFIX}newview) -add_dependencies(viewer secondlife-bin) - -# The use_prebuilt_binary macro in cmake/Prebuilt.cmake records -# packages in the PREBUILT property of the 'prepare' target. -get_property(PREBUILT_PACKAGES TARGET prepare PROPERTY PREBUILT) - -# Create a script to download the needed binaries. -configure_file(${CMAKE_SOURCE_DIR}/cmake/DownloadPrebuilt.cmake.in - ${CMAKE_BINARY_DIR}/DownloadPrebuilt.cmake @ONLY) - -# Drive the download script at build time. Depend on 'install.xml' -# to aqcuire new binaries when needed. -add_custom_command( - COMMENT "Obtaining prebuilt binaries..." - OUTPUT ${CMAKE_BINARY_DIR}/prepare/prebuilt - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/DownloadPrebuilt.cmake - DEPENDS ${CMAKE_SOURCE_DIR}/../install.xml - ${CMAKE_BINARY_DIR}/DownloadPrebuilt.cmake - ) +add_dependencies(viewer ${VIEWER_BINARY_NAME}) -if(WINDOWS) - configure_file(${CMAKE_SOURCE_DIR}/cmake/CopyWinLibs.cmake.in - ${CMAKE_BINARY_DIR}/CopyWinLibs.cmake @ONLY) - add_custom_command( - COMMENT "Copying prebuilt libraries to viewer executable directory" - OUTPUT ${CMAKE_BINARY_DIR}/CopyWinLibs - COMMAND ${CMAKE_COMMAND} -DCUR_CONFIG:STRING=${CMAKE_CFG_INTDIR} -P ${CMAKE_BINARY_DIR}/CopyWinLibs.cmake - DEPENDS ${CMAKE_BINARY_DIR}/prepare/prebuilt ${CMAKE_BINARY_DIR}/CopyWinLibs.cmake - ) - add_custom_target(copy_win_libs DEPENDS ${CMAKE_BINARY_DIR}/CopyWinLibs) -endif(WINDOWS) \ No newline at end of file +if (WINDOWS) + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + PROPERTY VS_STARTUP_PROJECT ${VIEWER_BINARY_NAME}) +endif (WINDOWS) diff --git a/indra/aistatemachine/CMakeLists.txt b/indra/aistatemachine/CMakeLists.txt index 806261201b..42cfec5e2b 100644 --- a/indra/aistatemachine/CMakeLists.txt +++ b/indra/aistatemachine/CMakeLists.txt @@ -39,5 +39,9 @@ set_source_files_properties(${aistatemachine_HEADER_FILES} list(APPEND aistatemachine_SOURCE_FILES ${aistatemachine_HEADER_FILES}) add_library (aistatemachine ${aistatemachine_SOURCE_FILES}) -add_dependencies(aistatemachine prepare) +target_link_libraries( + aistatemachine + PUBLIC + llcommon + ) diff --git a/indra/aistatemachine/aistatemachinethread.h b/indra/aistatemachine/aistatemachinethread.h index 193c2e0d49..bf70be6c7b 100644 --- a/indra/aistatemachine/aistatemachinethread.h +++ b/indra/aistatemachine/aistatemachinethread.h @@ -34,6 +34,7 @@ #include "aistatemachine.h" #include "llthread.h" #include "aithreadsafe.h" +#include #ifdef EXAMPLE_CODE // undefined @@ -235,7 +236,7 @@ class AIStateMachineThread : public AIStateMachineThreadBase { /*virtual*/ const char* getName() const { #define STRIZE(arg) #arg - return "AIStateMachineThread<"STRIZE(THREAD_IMPL)">"; + return (boost::format("%1%%2%%3%") % "AIStateMachineThread<" % STRIZE(THREAD_IMPL) % ">").str().c_str(); #undef STRIZE } diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 139a10b3c3..1d0b7f1f60 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -5,9 +5,9 @@ if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") +include(CheckCCompilerFlag) include(Variables) - # Portable compilation flags. set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -DLL_DEBUG=1") @@ -18,44 +18,12 @@ set(CMAKE_C_FLAGS_RELEASE set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DLL_RELEASE=1 -D_SECURE_SCL=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1") -# Configure crash reporting -set(RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in release builds") -set(NON_RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in developer builds") - -if(RELEASE_CRASH_REPORTING) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DLL_SEND_CRASH_REPORTS=1") -endif() - -if(NON_RELEASE_CRASH_REPORTING) - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DLL_SEND_CRASH_REPORTS=1") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DLL_SEND_CRASH_REPORTS=1") -endif() - - # Don't bother with a MinSizeRel build. - set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING "Supported build types." FORCE) # Platform-specific compilation flags. - if (WINDOWS) - # Various libs are compiler specific, generate some variables here we can just use - # when we require them instead of reimplementing the test each time. - if (MSVC10) - set(MSVC_DIR 10.0) - set(MSVC_SUFFIX 100) - elseif (MSVC12) - set(MSVC_DIR 12.0) - set(MSVC_SUFFIX 120) - endif (MSVC10) - - # Remove default /Zm1000 flag that cmake inserts - string (REPLACE "/Zm1000" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - - # Always use /Zm140 - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm140") - # Don't build DLLs. set(BUILD_SHARED_LIBS OFF) @@ -65,61 +33,88 @@ if (WINDOWS) "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP" CACHE STRING "C++ compiler release-with-debug options" FORCE) set(CMAKE_CXX_FLAGS_RELEASE - "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP /fp:fast -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0" + "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /Zo /MD /MP /Ob2 /Zc:inline /fp:fast -D_ITERATOR_DEBUG_LEVEL=0" CACHE STRING "C++ compiler release options" FORCE) set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${LL_C_FLAGS} /O2 /Zi /MD /MP /fp:fast" CACHE STRING "C compiler release options" FORCE) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE") + + if (ADDRESS_SIZE EQUAL 32) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE") + endif (ADDRESS_SIZE EQUAL 32) + + if (FULL_DEBUG_SYMS OR USE_CRASHPAD) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG:FULL") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG:FULL") + else () + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG:FASTLINK") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG:FASTLINK") + endif () + + if (USE_LTO) + if(INCREMENTAL_LINK) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LTCG:INCREMENTAL") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /LTCG:INCREMENTAL") + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /LTCG:INCREMENTAL") + else(INCREMENTAL_LINK) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LTCG") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /LTCG") + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /LTCG") + endif(INCREMENTAL_LINK) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /OPT:REF /OPT:ICF /LTCG") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /OPT:REF /OPT:ICF /LTCG") + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /LTCG") + elseif (INCREMENTAL_LINK) + set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS} /INCREMENTAL /VERBOSE:INCR") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS} /INCREMENTAL /VERBOSE:INCR") + else () + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /OPT:REF /INCREMENTAL:NO") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /OPT:REF /INCREMENTAL:NO") + endif () set(CMAKE_CXX_STANDARD_LIBRARIES "") set(CMAKE_C_STANDARD_LIBRARIES "") add_definitions( /DLL_WINDOWS=1 + /DNOMINMAX /DUNICODE - /D_UNICODE + /D_UNICODE + /DBOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE /GS /TP /W3 /c + /Zc:__cplusplus /Zc:forScope - /Zc:wchar_t- + /Zc:rvalueCast + /Zc:wchar_t /nologo /Oy- + /Zm140 + /wd4267 + /wd4244 ) - - # SSE2 is implied on win64 - if(WORD_SIZE EQUAL 32) - add_definitions(/arch:SSE2 /D_ATL_XP_TARGETING) - else(WORD_SIZE EQUAL 32) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /wd4267 /wd4250 /wd4244") - endif(WORD_SIZE EQUAL 32) - - if (WORD_SIZE EQUAL 32) - # configure win32 API for windows XP+ compatibility - set(WINVER "0x0501" CACHE STRING "Win32 API Target version (see http://msdn.microsoft.com/en-us/library/aa383745%28v=VS.85%29.aspx)") - add_definitions("/DWINVER=${WINVER}" "/D_WIN32_WINNT=${WINVER}") - else (WORD_SIZE EQUAL 32) - # configure win32 API for windows vista+ compatibility - set(WINVER "0x0600" CACHE STRING "Win32 API Target version (see http://msdn.microsoft.com/en-us/library/aa383745%28v=VS.85%29.aspx)") - add_definitions("/DWINVER=${WINVER}" "/D_WIN32_WINNT=${WINVER}") - endif (WORD_SIZE EQUAL 32) - - # Use special XP-compatible toolchain on 32-bit builds - if (MSVC12 AND (WORD_SIZE EQUAL 32)) - set(CMAKE_GENERATOR_TOOLSET "v120xp") - endif (MSVC12 AND (WORD_SIZE EQUAL 32)) - - # Are we using the crummy Visual Studio KDU build workaround? + + if (USE_LTO) + add_compile_options( + /GL + /Gy + /Gw + ) + endif (USE_LTO) + + if (ADDRESS_SIZE EQUAL 32) + add_compile_options(/arch:SSE2) + endif (ADDRESS_SIZE EQUAL 32) + if (NOT DISABLE_FATAL_WARNINGS) add_definitions(/WX) endif (NOT DISABLE_FATAL_WARNINGS) - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") - SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /MANIFEST:NO") - SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /MANIFEST:NO") - + # configure win32 API for windows Vista+ compatibility + set(WINVER "0x0600" CACHE STRING "Win32 API Target version (see http://msdn.microsoft.com/en-us/library/aa383745%28v=VS.85%29.aspx)") + add_definitions("/DWINVER=${WINVER}" "/D_WIN32_WINNT=${WINVER}") endif (WINDOWS) set (GCC_EXTRA_OPTIMIZATIONS "-ffast-math") @@ -127,20 +122,30 @@ set (GCC_EXTRA_OPTIMIZATIONS "-ffast-math") if (LINUX) set(CMAKE_SKIP_RPATH TRUE) + add_compile_options( + -fvisibility=hidden + -fexceptions + -fno-math-errno + -fno-strict-aliasing + -fsigned-char + -g + -pthread + ) + add_definitions( - -DLL_LINUX=1 - -DAPPID=secondlife - -D_REENTRANT - -fexceptions - -fno-math-errno - -fno-strict-aliasing - -fsigned-char - -fvisibility=hidden - -g - -pthread - ) + -DLL_LINUX=1 + -DAPPID=secondlife + -D_REENTRANT + -DGDK_DISABLE_DEPRECATED + -DGTK_DISABLE_DEPRECATED + -DGSEAL_ENABLE + -DGTK_DISABLE_SINGLE_INCLUDES + ) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 ") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2") # Don't catch SIGCHLD in our base application class for the viewer # some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! @@ -195,50 +200,40 @@ if (LINUX) # End of hacks. - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") + CHECK_C_COMPILER_FLAG(-fstack-protector-strong HAS_STRONG_STACK_PROTECTOR) + if (${CMAKE_BUILD_TYPE} STREQUAL "Release") + if(HAS_STRONG_STACK_PROTECTOR) + add_compile_options(-fstack-protector-strong) + endif(HAS_STRONG_STACK_PROTECTOR) + endif (${CMAKE_BUILD_TYPE} STREQUAL "Release") - if (NOT STANDALONE) - # this stops us requiring a really recent glibc at runtime - add_definitions(-fno-stack-protector) - endif (NOT STANDALONE) if (${ARCH} STREQUAL "x86_64") - add_definitions(-DLINUX64=1 -pipe) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -ffast-math -funroll-loops") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fomit-frame-pointer -ffast-math -funroll-loops") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -ffast-math") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -ffast-math") + add_definitions(-pipe) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffast-math -msse4.1") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -ffast-math -msse4.1") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -ffast-math -msse4.1") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -ffast-math -msse4.1") else (${ARCH} STREQUAL "x86_64") if (NOT STANDALONE) set(MARCH_FLAG " -march=pentium4") endif (NOT STANDALONE) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse3") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse3") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}${MARCH_FLAG} -mfpmath=sse,387 -msse3 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}${MARCH_FLAG} -mfpmath=sse,387 -msse3 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse3 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse3 ${GCC_EXTRA_OPTIMIZATIONS}") endif (${ARCH} STREQUAL "x86_64") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - if (NOT STANDALONE) - # this stops us requiring a really recent glibc at runtime - add_definitions(-fno-stack-protector) - endif (NOT STANDALONE) - - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}${MARCH_FLAG} -msse2") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}${MARCH_FLAG} -msse2") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -msse2") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -msse2") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse3") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse3") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}${MARCH_FLAG} -msse3") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}${MARCH_FLAG} -msse3") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -msse3") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -msse3") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") - - if (NOT STANDALONE) - # this stops us requiring a really recent glibc at runtime - add_definitions(-fno-stack-protector) - endif (NOT STANDALONE) - if (NOT STANDALONE) - set(MARCH_FLAG " -axsse4.1 -msse2") + set(MARCH_FLAG " -axsse4.1 -msse3") endif (NOT STANDALONE) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline-functions") @@ -302,27 +297,35 @@ if (LINUX OR DARWIN) set(CMAKE_C_FLAGS "${UNIX_WARNINGS} ${CMAKE_C_FLAGS}") set(CMAKE_CXX_FLAGS "${UNIX_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}") - if (WORD_SIZE EQUAL 32) + if (ADDRESS_SIZE EQUAL 32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") - elseif (WORD_SIZE EQUAL 64) + elseif (ADDRESS_SIZE EQUAL 64) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64") - endif (WORD_SIZE EQUAL 32) + endif (ADDRESS_SIZE EQUAL 32) endif (LINUX OR DARWIN) if (STANDALONE) add_definitions(-DLL_STANDALONE=1) else (STANDALONE) + #Enforce compile-time correctness for fmt strings + add_definitions(-DFMT_STRING_ALIAS=1) + + if(USE_CRASHPAD) + add_definitions(-DUSE_CRASHPAD=1 -DCRASHPAD_URL="${CRASHPAD_URL}") + endif() + set(${ARCH}_linux_INCLUDES - ELFIO atk-1.0 + cairo glib-2.0 + gdk-pixbuf-2.0 gstreamer-0.10 gtk-2.0 - freetype2 pango-1.0 + pixman-1 ) endif (STANDALONE) diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake index c47363aa1c..447470a151 100644 --- a/indra/cmake/APR.cmake +++ b/indra/cmake/APR.cmake @@ -1,4 +1,3 @@ -include(BerkeleyDB) include(Linking) include(Prebuilt) @@ -13,39 +12,41 @@ if (STANDALONE) else (STANDALONE) use_prebuilt_binary(apr_suite) if (WINDOWS) + if (LLCOMMON_LINK_SHARED) + set(APR_selector "lib") + else (LLCOMMON_LINK_SHARED) + set(APR_selector "") + endif (LLCOMMON_LINK_SHARED) set(APR_LIBRARIES - debug libapr-1.lib - optimized libapr-1.lib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/${APR_selector}apr-1.lib + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}apr-1.lib ) set(APRICONV_LIBRARIES - debug libapriconv-1.lib - optimized libapriconv-1.lib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/${APR_selector}apriconv-1.lib + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}apriconv-1.lib ) set(APRUTIL_LIBRARIES - debug libaprutil-1.lib - optimized libaprutil-1.lib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/${APR_selector}aprutil-1.lib ${APRICONV_LIBRARIES} + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}aprutil-1.lib ${APRICONV_LIBRARIES} ) + if(NOT LLCOMMON_LINK_SHARED) + list(APPEND APR_LIBRARIES Rpcrt4) + endif(NOT LLCOMMON_LINK_SHARED) elseif (DARWIN) - set(APR_LIBRARIES - debug libapr-1.0.dylib - optimized libapr-1.0.dylib - ) - set(APRUTIL_LIBRARIES - debug libaprutil-1.dylib - optimized libaprutil-1.dylib - ) + if (LLCOMMON_LINK_SHARED) + set(APR_selector "0.dylib") + set(APRUTIL_selector "0.dylib") + else (LLCOMMON_LINK_SHARED) + set(APR_selector "a") + set(APRUTIL_selector "a") + endif (LLCOMMON_LINK_SHARED) + set(APR_LIBRARIES libapr-1.${APR_selector}) + set(APRUTIL_LIBRARIES libaprutil-1.${APRUTIL_selector}) set(APRICONV_LIBRARIES iconv) else (WINDOWS) set(APR_LIBRARIES apr-1) set(APRUTIL_LIBRARIES aprutil-1) set(APRICONV_LIBRARIES iconv) endif (WINDOWS) - set(APR_INCLUDE_DIR - ${LIBS_PREBUILT_DIR}/include/apr-1 - ${LIBS_PREBUILT_LEGACY_DIR}/include/apr-1 - ) - - if (LINUX) - list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES}) - endif (LINUX) + set(APR_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/apr-1) endif (STANDALONE) diff --git a/indra/cmake/Audio.cmake b/indra/cmake/Audio.cmake index 27633ff72a..ba9f712388 100644 --- a/indra/cmake/Audio.cmake +++ b/indra/cmake/Audio.cmake @@ -1,18 +1,15 @@ # -*- cmake -*- include(Prebuilt) -if (STANDALONE) +if (LINUX) include(FindPkgConfig) pkg_check_modules(OGG REQUIRED ogg) pkg_check_modules(VORBIS REQUIRED vorbis) pkg_check_modules(VORBISENC REQUIRED vorbisenc) pkg_check_modules(VORBISFILE REQUIRED vorbisfile) -else (STANDALONE) - use_prebuilt_binary(ogg-vorbis) - set(VORBIS_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) +else (LINUX) + use_prebuilt_binary(ogg_vorbis) + set(VORBIS_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) set(VORBISENC_INCLUDE_DIRS ${VORBIS_INCLUDE_DIRS}) set(VORBISFILE_INCLUDE_DIRS ${VORBIS_INCLUDE_DIRS}) @@ -35,7 +32,7 @@ else (STANDALONE) set(VORBISENC_LIBRARIES vorbisenc) set(VORBISFILE_LIBRARIES vorbisfile) endif (WINDOWS) -endif (STANDALONE) +endif (LINUX) link_directories( ${VORBIS_LIBRARY_DIRS} diff --git a/indra/cmake/BerkeleyDB.cmake b/indra/cmake/BerkeleyDB.cmake deleted file mode 100644 index 5b885c6a74..0000000000 --- a/indra/cmake/BerkeleyDB.cmake +++ /dev/null @@ -1,20 +0,0 @@ -include(Prebuilt) - -set(DB_FIND_QUIETLY ON) -set(DB_FIND_REQUIRED ON) - -if (STANDALONE) - include(FindBerkeleyDB) -else (STANDALONE) - if (LINUX) - # Need to add dependency pthread explicitely to support ld.gold. - use_prebuilt_binary(db) - set(DB_LIBRARIES db-5.1 pthread) - else (LINUX) - set(DB_LIBRARIES db-4.2) - endif (LINUX) - set(DB_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) -endif (STANDALONE) diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index 0421b1c9e7..844d5dc490 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -11,11 +11,8 @@ if (STANDALONE) find_package(Boost 1.51.0 COMPONENTS date_time filesystem program_options regex system thread wave context) else (STANDALONE) use_prebuilt_binary(boost) - set(Boost_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) - set(Boost_VERSION "1.52") + set(Boost_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) + set(Boost_VERSION "1.60") if (WINDOWS) set(Boost_CONTEXT_LIBRARY diff --git a/indra/cmake/BuildBranding.cmake b/indra/cmake/BuildBranding.cmake new file mode 100644 index 0000000000..4ab86234db --- /dev/null +++ b/indra/cmake/BuildBranding.cmake @@ -0,0 +1,38 @@ +# -*- cmake -*- +if (WINDOWS) + #message(WARNING, ${CMAKE_CURRENT_BINARY_DIR}/newview/viewerRes.rc.in) + configure_file( + ${CMAKE_SOURCE_DIR}/newview/res/viewerRes.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/viewerRes.rc + ) +endif (WINDOWS) + +if (DARWIN) + configure_file( + ${CMAKE_SOURCE_DIR}/newview/English.lproj/InfoPlist.strings.in + ${CMAKE_CURRENT_BINARY_DIR}/English.lproj/InfoPlist.strings + ) +endif (DARWIN) + +if (LINUX) + configure_file( + ${CMAKE_SOURCE_DIR}/newview/linux_tools/wrapper.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/linux_tools/wrapper.sh + @ONLY + ) + configure_file( + ${CMAKE_SOURCE_DIR}/newview/linux_tools/handle_secondlifeprotocol.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/linux_tools/handle_secondlifeprotocol.sh + @ONLY + ) + configure_file( + ${CMAKE_SOURCE_DIR}/newview/linux_tools/install.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/linux_tools/install.sh + @ONLY + ) + configure_file( + ${CMAKE_SOURCE_DIR}/newview/linux_tools/refresh_desktop_app_entry.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/linux_tools/refresh_desktop_app_entry.sh + @ONLY + ) +endif (LINUX) diff --git a/indra/cmake/BuildPackagesInfo.cmake b/indra/cmake/BuildPackagesInfo.cmake new file mode 100644 index 0000000000..26088fcaf6 --- /dev/null +++ b/indra/cmake/BuildPackagesInfo.cmake @@ -0,0 +1,20 @@ +# -*- cmake -*- +# Construct the version and copyright information based on package data. +include(Python) +include(Variables) + +# packages-formatter.py runs autobuild install --versions, which needs to know +# the build_directory, which (on Windows) depends on AUTOBUILD_ADDRSIZE. +# Within an autobuild build, AUTOBUILD_ADDRSIZE is already set. But when +# building in an IDE, it probably isn't. Set it explicitly using +# run_build_test.py. +add_custom_command(OUTPUT packages-info.txt + COMMENT "Generating packages-info.txt for the about box" + MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/../autobuild.xml + DEPENDS ${CMAKE_SOURCE_DIR}/../scripts/packages-formatter.py + ${CMAKE_SOURCE_DIR}/../autobuild.xml + COMMAND ${PYTHON_EXECUTABLE} + ${CMAKE_SOURCE_DIR}/cmake/run_build_test.py -DAUTOBUILD_ADDRSIZE=${ADDRESS_SIZE} + ${PYTHON_EXECUTABLE} + ${CMAKE_SOURCE_DIR}/../scripts/packages-formatter.py "${VIEWER_CHANNEL}" "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}" > packages-info.txt + ) diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake index 457a1bb165..2f36e3ad1b 100644 --- a/indra/cmake/BuildVersion.cmake +++ b/indra/cmake/BuildVersion.cmake @@ -1,81 +1,55 @@ # -*- cmake -*- - -# Read version components from the header file. -file(STRINGS ${LIBS_OPEN_DIR}/llcommon/llversionviewer.h.in lines - REGEX " LL_VERSION_") -foreach(line ${lines}) - string(REGEX REPLACE ".*LL_VERSION_([A-Z]+).*" "\\1" comp "${line}") - string(REGEX REPLACE ".* = ([0-9]+);.*" "\\1" value "${line}") - set(v${comp} "${value}") -endforeach(line) - -execute_process( - COMMAND git rev-list HEAD - OUTPUT_VARIABLE GIT_REV_LIST_STR - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -if(GIT_REV_LIST_STR) - string(REPLACE "\n" ";" GIT_REV_LIST ${GIT_REV_LIST_STR}) -else() - string(REPLACE "\n" ";" GIT_REV_LIST "") -endif() - -if(GIT_REV_LIST) - list(LENGTH GIT_REV_LIST vBUILD) -else() - set(vBUILD 99) -endif() - -configure_file( - ${CMAKE_SOURCE_DIR}/llcommon/llversionviewer.h.in - ${CMAKE_SOURCE_DIR}/llcommon/llversionviewer.h -) - -if (WINDOWS) - configure_file( - ${CMAKE_SOURCE_DIR}/newview/res/viewerRes.rc.in - ${CMAKE_SOURCE_DIR}/newview/res/viewerRes.rc - ) -endif (WINDOWS) - -if (DARWIN) - configure_file( - ${CMAKE_SOURCE_DIR}/newview/English.lproj/InfoPlist.strings.in - ${CMAKE_SOURCE_DIR}/newview/English.lproj/InfoPlist.strings - ) -endif (DARWIN) - -if (LINUX) - configure_file( - ${CMAKE_SOURCE_DIR}/newview/linux_tools/wrapper.sh.in - ${CMAKE_SOURCE_DIR}/newview/linux_tools/wrapper.sh - @ONLY - ) - configure_file( - ${CMAKE_SOURCE_DIR}/newview/linux_tools/handle_secondlifeprotocol.sh.in - ${CMAKE_SOURCE_DIR}/newview/linux_tools/handle_secondlifeprotocol.sh - @ONLY - ) - configure_file( - ${CMAKE_SOURCE_DIR}/newview/linux_tools/install.sh.in - ${CMAKE_SOURCE_DIR}/newview/linux_tools/install.sh - @ONLY - ) - configure_file( - ${CMAKE_SOURCE_DIR}/newview/linux_tools/refresh_desktop_app_entry.sh.in - ${CMAKE_SOURCE_DIR}/newview/linux_tools/refresh_desktop_app_entry.sh - @ONLY - ) -endif (LINUX) - - -# Compose the version. -set(${ROOT_PROJECT_NAME}_VERSION "${vMAJOR}.${vMINOR}.${vPATCH}.${vBUILD}") -if (${ROOT_PROJECT_NAME}_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$") - message(STATUS "Version is ${${ROOT_PROJECT_NAME}_VERSION}") -else (${ROOT_PROJECT_NAME}_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$") - message(FATAL_ERROR "Could not determine version (${${ROOT_PROJECT_NAME}_VERSION})") -endif (${ROOT_PROJECT_NAME}_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$") - +# Construct the viewer version number based on the indra/VIEWER_VERSION file + +if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/newview/ + set(VIEWER_VERSION_BASE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/newview/VIEWER_VERSION.txt") + + if ( EXISTS ${VIEWER_VERSION_BASE_FILE} ) + file(STRINGS ${VIEWER_VERSION_BASE_FILE} VIEWER_SHORT_VERSION REGEX "^[0-9]+\\.[0-9]+\\.[0-9]+") + string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" VIEWER_VERSION_MAJOR ${VIEWER_SHORT_VERSION}) + string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+" "\\1" VIEWER_VERSION_MINOR ${VIEWER_SHORT_VERSION}) + string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" VIEWER_VERSION_PATCH ${VIEWER_SHORT_VERSION}) + + if (DEFINED ENV{revision}) + set(VIEWER_VERSION_REVISION $ENV{revision}) + message("Revision (from environment): ${VIEWER_VERSION_REVISION}") + + else (DEFINED ENV{revision}) + execute_process( + COMMAND git rev-list HEAD + OUTPUT_VARIABLE GIT_REV_LIST_STR + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(GIT_REV_LIST_STR) + string(REPLACE "\n" ";" GIT_REV_LIST ${GIT_REV_LIST_STR}) + else() + string(REPLACE "\n" ";" GIT_REV_LIST "") + endif() + + if(GIT_REV_LIST) + list(LENGTH GIT_REV_LIST VIEWER_VERSION_REVISION) + else(GIT_REV_LIST) + set(VIEWER_VERSION_REVISION 99) + endif(GIT_REV_LIST) + endif (DEFINED ENV{revision}) + message("Building '${VIEWER_CHANNEL}' Version ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}") + else ( EXISTS ${VIEWER_VERSION_BASE_FILE} ) + message(SEND_ERROR "Cannot get viewer version from '${VIEWER_VERSION_BASE_FILE}'") + endif ( EXISTS ${VIEWER_VERSION_BASE_FILE} ) + + if ("${VIEWER_VERSION_REVISION}" STREQUAL "") + message("Ultimate fallback, revision was blank or not set: will use 0") + set(VIEWER_VERSION_REVISION 0) + endif ("${VIEWER_VERSION_REVISION}" STREQUAL "") + + set(VIEWER_CHANNEL_VERSION_DEFINES + "LL_VIEWER_CHANNEL=\"${VIEWER_CHANNEL}\"" + "LL_VIEWER_CHANNEL_GRK=L\"${VIEWER_CHANNEL_GRK}\"" + "LL_VIEWER_VERSION_MAJOR=${VIEWER_VERSION_MAJOR}" + "LL_VIEWER_VERSION_MINOR=${VIEWER_VERSION_MINOR}" + "LL_VIEWER_VERSION_PATCH=${VIEWER_VERSION_PATCH}" + "LL_VIEWER_VERSION_BUILD=${VIEWER_VERSION_REVISION}" + ) +endif (NOT DEFINED VIEWER_SHORT_VERSION) diff --git a/indra/cmake/CARes.cmake b/indra/cmake/CARes.cmake index 062b283c15..02fad1f550 100644 --- a/indra/cmake/CARes.cmake +++ b/indra/cmake/CARes.cmake @@ -20,8 +20,5 @@ else (STANDALONE) else (WINDOWS) set(CARES_LIBRARIES cares) endif (WINDOWS) - set(CARES_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include/ares - ${LIBS_PREBUILT_LEGACY_DIR}/include/ares - ) + set(CARES_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/ares) endif (STANDALONE) diff --git a/indra/cmake/CEFPlugin.cmake b/indra/cmake/CEFPlugin.cmake new file mode 100644 index 0000000000..7f90e6afa6 --- /dev/null +++ b/indra/cmake/CEFPlugin.cmake @@ -0,0 +1,45 @@ +# -*- cmake -*- +include(Linking) +include(Prebuilt) + +if (USESYSTEMLIBS) + set(CEFPLUGIN OFF CACHE BOOL + "CEFPLUGIN support for the llplugin/llmedia test apps.") +else (USESYSTEMLIBS) + use_prebuilt_binary(dullahan) + set(CEFPLUGIN ON CACHE BOOL + "CEFPLUGIN support for the llplugin/llmedia test apps.") + set(CEF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/cef) +endif (USESYSTEMLIBS) + +if (WINDOWS) + set(CEF_PLUGIN_LIBRARIES + libcef.lib + libcef_dll_wrapper.lib + dullahan.lib + ) +elseif (DARWIN) + FIND_LIBRARY(APPKIT_LIBRARY AppKit) + if (NOT APPKIT_LIBRARY) + message(FATAL_ERROR "AppKit not found") + endif() + + FIND_LIBRARY(CEF_LIBRARY "Chromium Embedded Framework" ${ARCH_PREBUILT_DIRS_RELEASE}) + if (NOT CEF_LIBRARY) + message(FATAL_ERROR "CEF not found") + endif() + + set(CEF_PLUGIN_LIBRARIES + ${ARCH_PREBUILT_DIRS_RELEASE}/libcef_dll_wrapper.a + ${ARCH_PREBUILT_DIRS_RELEASE}/libdullahan.a + ${APPKIT_LIBRARY} + ${CEF_LIBRARY} + ) + +elseif (LINUX) + set(CEF_PLUGIN_LIBRARIES + dullahan + cef_dll_wrapper.a + cef + ) +endif (WINDOWS) diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index c6d716fed7..cfd982f96a 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -12,50 +12,44 @@ set(cmake_SOURCE_FILES APR.cmake Audio.cmake BasicPluginBase.cmake - BerkeleyDB.cmake Boost.cmake + BuildBranding.cmake BuildVersion.cmake CARes.cmake + CEFPlugin.cmake CMakeCopyIfDifferent.cmake - CURL.cmake Colladadom.cmake ConfigurePkgConfig.cmake - CopyBackToSource.cmake - CopyWinLibs.cmake + CURL.cmake + Copy3rdPartyLibs.cmake + CrashPad.cmake Cwdebug.cmake DBusGlib.cmake - DirectX.cmake - DownloadPrebuilt.cmake.in - ELFIO.cmake + DeploySharedLibs.cmake EXPAT.cmake ExamplePlugin.cmake - FMODEX.cmake - FMODSTUDIO.cmake FindAPR.cmake - FindBerkeleyDB.cmake + FindAutobuild.cmake FindCARes.cmake FindColladadom.cmake - FindELFIO.cmake FindGLOD.cmake - FindGoogleBreakpad.cmake FindGooglePerfTools.cmake FindHunSpell.cmake - FindJsonCpp.cmake - FindLLQtWebkit.cmake FindNDOF.cmake FindOpenJPEG.cmake FindTut.cmake + FindURIPARSER.cmake FindXmlRpcEpi.cmake + FMODSTUDIO.cmake FreeType.cmake + GeneratePrecompiledHeader.cmake GLOD.cmake GStreamer010Plugin.cmake Glui.cmake Glut.cmake - GoogleBreakpad.cmake GooglePerfTools.cmake Hunspell.cmake JPEG.cmake - JsonCpp.cmake LLAddBuildTest.cmake LLAppearance.cmake LLAudio.cmake @@ -70,9 +64,8 @@ set(cmake_SOURCE_FILES LLPlugin.cmake LLPrimitive.cmake LLPhysicsExtensions.cmake - LLSharedLibs.cmake - LLQtWebkit.cmake LLRender.cmake + LLSharedLibs.cmake LLUI.cmake LLVFS.cmake LLWindow.cmake @@ -91,17 +84,16 @@ set(cmake_SOURCE_FILES Prebuilt.cmake PulseAudio.cmake Python.cmake - Qt4.cmake - QuickTimePlugin.cmake - RunBuildTest.cmake StateMachine.cmake TemplateCheck.cmake Tut.cmake UI.cmake UnixInstall.cmake + URIPARSER.cmake Variables.cmake ViewerMiscLibs.cmake - WebKitLibPlugin.cmake + WinManifest.cmake + LibVLCPlugin.cmake XmlRpcEpi.cmake ZLIB.cmake ) @@ -110,7 +102,6 @@ source_group("Shared Rules" FILES ${cmake_SOURCE_FILES}) set(master_SOURCE_FILES ../CMakeLists.txt - ../develop.py ) source_group("Master Rules" FILES ${master_SOURCE_FILES}) diff --git a/indra/cmake/CURL.cmake b/indra/cmake/CURL.cmake index 8463d6531d..aed230279b 100644 --- a/indra/cmake/CURL.cmake +++ b/indra/cmake/CURL.cmake @@ -10,16 +10,11 @@ else (STANDALONE) use_prebuilt_binary(curl) if (WINDOWS) set(CURL_LIBRARIES - debug libcurld - optimized libcurl) + debug libcurl_a_debug + optimized libcurl_a) else (WINDOWS) - set(CURL_LIBRARIES curl) - if(LINUX AND WORD_SIZE EQUAL 64) - list(APPEND CURL_LIBRARIES idn) - endif(LINUX AND WORD_SIZE EQUAL 64) + use_prebuilt_binary(libidn) + set(CURL_LIBRARIES curl idn) endif (WINDOWS) - set(CURL_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) + set(CURL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) endif (STANDALONE) diff --git a/indra/cmake/Colladadom.cmake b/indra/cmake/Colladadom.cmake index afc8bcce09..e4eb71af01 100644 --- a/indra/cmake/Colladadom.cmake +++ b/indra/cmake/Colladadom.cmake @@ -10,49 +10,22 @@ if (STANDALONE) include (FindColladadom) else (STANDALONE) use_prebuilt_binary(colladadom) - - if (NOT WINDOWS AND NOT LINUX) - use_prebuilt_binary(pcre) - endif (NOT WINDOWS AND NOT LINUX) - - if (NOT DARWIN AND NOT WINDOWS) - use_prebuilt_binary(libxml) - endif (NOT DARWIN AND NOT WINDOWS) - set(COLLADADOM_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include/collada - ${LIBS_PREBUILT_DIR}/include/collada/1.4 - ${LIBS_PREBUILT_LEGACY_DIR}/include/collada - ${LIBS_PREBUILT_LEGACY_DIR}/include/collada/1.4 - ) + ${LIBS_PREBUILT_DIR}/include/collada + ${LIBS_PREBUILT_DIR}/include/collada/1.4 + ) if (WINDOWS) - if(MSVC12) - use_prebuilt_binary(pcre) - use_prebuilt_binary(libxml) - set(COLLADADOM_LIBRARIES - debug libcollada14dom23-sd - optimized libcollada14dom23-s - libxml2_a - debug pcrecppd - optimized pcrecpp - debug pcred - optimized pcre - ${BOOST_SYSTEM_LIBRARIES} - ) - else(MSVC12) - add_definitions(-DDOM_DYNAMIC) - set(COLLADADOM_LIBRARIES - debug libcollada14dom22-d - optimized libcollada14dom22 - ) - endif(MSVC12) - else (WINDOWS) - set(COLLADADOM_LIBRARIES - collada14dom - minizip - xml2 - ) + set(COLLADADOM_LIBRARIES + debug libcollada14dom23-sd + optimized libcollada14dom23-s + ) + else(WINDOWS) + set(COLLADADOM_LIBRARIES + debug collada14dom-d + optimized collada14dom + minizip + ) endif (WINDOWS) endif (STANDALONE) diff --git a/indra/cmake/ConfigurePkgConfig.cmake b/indra/cmake/ConfigurePkgConfig.cmake index afbc36d63e..a2d5b31e25 100644 --- a/indra/cmake/ConfigurePkgConfig.cmake +++ b/indra/cmake/ConfigurePkgConfig.cmake @@ -6,17 +6,17 @@ SET(DEBUG_PKG_CONFIG "YES") IF("$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "") # Guess at architecture-specific system library paths. - if (WORD_SIZE EQUAL 32) + if (ADDRESS_SIZE EQUAL 32) SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib32 /usr/lib) SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib32 /usr/local/lib) SET(PKG_CONFIG_MULTI_GUESS /usr/lib/i386-linux-gnu) SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/i386-linux-gnu) - else (WORD_SIZE EQUAL 32) + else (ADDRESS_SIZE EQUAL 32) SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib64 /usr/lib) SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib64 /usr/local/lib) SET(PKG_CONFIG_MULTI_GUESS /usr/lib/x86_64-linux-gnu) SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/x86_64-linux-gnu) - endif (WORD_SIZE EQUAL 32) + endif (ADDRESS_SIZE EQUAL 32) # Use DPKG architecture, if available. IF (${DPKG_ARCH}) diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake new file mode 100644 index 0000000000..63ecf0cb1c --- /dev/null +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -0,0 +1,255 @@ +# -*- cmake -*- + +# The copy_win_libs folder contains file lists and a script used to +# copy dlls, exes and such needed to run the SecondLife from within +# VisualStudio. + +include(CMakeCopyIfDifferent) +include(Linking) +include(Variables) +include(LLCommon) + +################################################################### +# set up platform specific lists of files that need to be copied +################################################################### +if(WINDOWS) + set(SHARED_LIB_STAGING_DIR_DEBUG "${SHARED_LIB_STAGING_DIR}/Debug") + set(SHARED_LIB_STAGING_DIR_RELWITHDEBINFO "${SHARED_LIB_STAGING_DIR}/RelWithDebInfo") + set(SHARED_LIB_STAGING_DIR_RELEASE "${SHARED_LIB_STAGING_DIR}/Release") + + #******************************* + # VIVOX - *NOTE: no debug version + set(vivox_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}") + set(vivox_files + SLVoice.exe + vivoxplatform.dll + ) + if (ADDRESS_SIZE EQUAL 64) + list(APPEND vivox_files + vivoxsdk_x64.dll + ortp_x64.dll + ) + else (ADDRESS_SIZE EQUAL 64) + list(APPEND vivox_files + vivoxsdk.dll + ortp.dll + ) + endif (ADDRESS_SIZE EQUAL 64) + + #******************************* + # Misc shared libs + + set(debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}") + set(debug_files + libapr-1.dll + libaprutil-1.dll + libapriconv-1.dll + glod.dll + libhunspell.dll + ) + + set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}") + set(release_files + libapr-1.dll + libaprutil-1.dll + libapriconv-1.dll + glod.dll + libhunspell.dll + ) + + if(ADDRESS_SIZE EQUAL 64) + list(APPEND debug_files + libcrypto-1_1-x64.dll + libssl-1_1-x64.dll + ) + list(APPEND release_files + libcrypto-1_1-x64.dll + libssl-1_1-x64.dll + ) + else(ADDRESS_SIZE EQUAL 64) + list(APPEND debug_files + libcrypto-1_1.dll + libssl-1_1.dll + ) + list(APPEND release_files + libcrypto-1_1.dll + libssl-1_1.dll + ) + endif(ADDRESS_SIZE EQUAL 64) + + if(NOT DISABLE_TCMALLOC) + list(APPEND debug_files libtcmalloc_minimal-debug.dll) + list(APPEND release_files libtcmalloc_minimal.dll) + endif(NOT DISABLE_TCMALLOC) + + if(OPENAL) + list(APPEND debug_files alut.dll OpenAL32.dll) + list(APPEND release_files alut.dll OpenAL32.dll) + endif(OPENAL) + + if (USE_FMODSTUDIO) + list(APPEND debug_files fmodL.dll) + list(APPEND release_files fmod.dll) + endif (USE_FMODSTUDIO) + +elseif(DARWIN) + set(SHARED_LIB_STAGING_DIR_DEBUG "${SHARED_LIB_STAGING_DIR}/Debug/Resources") + set(SHARED_LIB_STAGING_DIR_RELWITHDEBINFO "${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/Resources") + set(SHARED_LIB_STAGING_DIR_RELEASE "${SHARED_LIB_STAGING_DIR}/Release/Resources") + + set(vivox_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}") + set(vivox_files + SLVoice + ca-bundle.crt + libsndfile.dylib + libvivoxoal.dylib + libortp.dylib + libvivoxplatform.dylib + libvivoxsdk.dylib + ) + set(debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}") + set(debug_files + ) + set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}") + set(release_files + libapr-1.0.dylib + libapr-1.dylib + libaprutil-1.0.dylib + libaprutil-1.dylib + libexception_handler.dylib + libexpat.1.5.2.dylib + libexpat.dylib + libGLOD.dylib + libhunspell-1.3.0.dylib + libndofdev.dylib + ) + + if (USE_FMODSTUDIO) + list(APPEND debug_files libfmodL.dylib) + list(APPEND release_files libfmod.dylib) + endif (USE_FMODSTUDIO) + +elseif(LINUX) + # linux is weird, multiple side by side configurations aren't supported + # and we don't seem to have any debug shared libs built yet anyways... + set(SHARED_LIB_STAGING_DIR_DEBUG "${SHARED_LIB_STAGING_DIR}") + set(SHARED_LIB_STAGING_DIR_RELWITHDEBINFO "${SHARED_LIB_STAGING_DIR}") + set(SHARED_LIB_STAGING_DIR_RELEASE "${SHARED_LIB_STAGING_DIR}") + + set(vivox_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}") + set(vivox_files + libsndfile.so.1 + libortp.so + libvivoxoal.so.1 + libvivoxplatform.so + libvivoxsdk.so + SLVoice + ) + # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables + # or ARCH_PREBUILT_DIRS + set(debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}") + set(debug_files + ) + # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables + # or ARCH_PREBUILT_DIRS + set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}") + # *FIX - figure out what to do with duplicate libalut.so here -brad + set(release_files + libapr-1.so.0 + libaprutil-1.so.0 + libexpat.so + libexpat.so.1 + libGLOD.so + libopenal.so + ) + + if (USE_TCMALLOC) + list(APPEND release_files "libtcmalloc_minimal.so") + endif (USE_TCMALLOC) + + if (USE_FMODSTUDIO) + list(APPEND debug_files "libfmodL.so") + list(APPEND release_files "libfmod.so") + endif (USE_FMODSTUDIO) + +else(WINDOWS) + message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...") + set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-linux") + set(vivox_files "") + # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables + # or ARCH_PREBUILT_DIRS + set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-linux/lib/debug") + set(debug_files "") + # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables + # or ARCH_PREBUILT_DIRS + set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-linux/lib/release") + set(release_files "") + + set(debug_llkdu_src "") + set(debug_llkdu_dst "") + set(release_llkdu_src "") + set(release_llkdu_dst "") + set(relwithdebinfo_llkdu_dst "") +endif(WINDOWS) + + +################################################################ +# Done building the file lists, now set up the copy commands. +################################################################ + +copy_if_different( + ${vivox_src_dir} + "${SHARED_LIB_STAGING_DIR_DEBUG}" + out_targets + ${vivox_files} + ) +set(third_party_targets ${third_party_targets} ${out_targets}) + +copy_if_different( + ${vivox_src_dir} + "${SHARED_LIB_STAGING_DIR_RELEASE}" + out_targets + ${vivox_files} + ) +set(third_party_targets ${third_party_targets} ${out_targets}) + +copy_if_different( + ${vivox_src_dir} + "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}" + out_targets + ${vivox_files} + ) +set(third_party_targets ${third_party_targets} ${out_targets}) + + + +#copy_if_different( +# ${debug_src_dir} +# "${SHARED_LIB_STAGING_DIR_DEBUG}" +# out_targets +# ${debug_files} +# ) +#set(third_party_targets ${third_party_targets} ${out_targets}) + +copy_if_different( + ${release_src_dir} + "${SHARED_LIB_STAGING_DIR_RELEASE}" + out_targets + ${release_files} + ) +set(third_party_targets ${third_party_targets} ${out_targets}) + +copy_if_different( + ${release_src_dir} + "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}" + out_targets + ${release_files} + ) +set(third_party_targets ${third_party_targets} ${out_targets}) + +if(NOT USESYSTEMLIBS) + add_custom_target( + stage_third_party_libs ALL + DEPENDS ${third_party_targets} + ) +endif(NOT USESYSTEMLIBS) diff --git a/indra/cmake/CopyBackToSource.cmake b/indra/cmake/CopyBackToSource.cmake deleted file mode 100644 index d09a216e84..0000000000 --- a/indra/cmake/CopyBackToSource.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# -*- cmake -*- -# Copies a binary back to the source directory - -MACRO(COPY_BACK_TO_SOURCE target) - SET(FROM $) - SET(TO ${CMAKE_CURRENT_SOURCE_DIR}) - #MESSAGE("TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${FROM} ${TO}") - ADD_CUSTOM_COMMAND( - TARGET ${target} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${FROM} ${TO} - DEPENDS ${FROM} - COMMENT "Copying ${target} to ${CMAKE_CURRENT_BINARY_DIR}" - ) -ENDMACRO(COPY_BACK_TO_SOURCE) - - diff --git a/indra/cmake/CopyWinLibs.cmake.in b/indra/cmake/CopyWinLibs.cmake.in deleted file mode 100644 index 16be776d6c..0000000000 --- a/indra/cmake/CopyWinLibs.cmake.in +++ /dev/null @@ -1,181 +0,0 @@ -# -*- cmake -*- - -# The copy_win_libs folder contains file lists and a script used to -# copy dlls, exes and such needed to run the SecondLife from within -# VisualStudio. - -set(LIBS_PREBUILT_DIR "@LIBS_PREBUILT_DIR@") -set(LIBS_PREBUILT_LEGACY_DIR "@LIBS_PREBUILT_LEGACY_DIR@") -set(MSVC10 "@MSVC10@") -set(WORD_SIZE "@WORD_SIZE@") - -set(LIBS_RELEASE_DIR - ${LIBS_PREBUILT_DIR}/lib/release - ${LIBS_PREBUILT_LEGACY_DIR}/lib/release - ) -set(LIBS_DEBUG_DIR - ${LIBS_PREBUILT_DIR}/lib/debug - ${LIBS_PREBUILT_LEGACY_DIR}/lib/debug - ) - -function(copy_files paths names dest) - string(FIND ${dest} ${CUR_CONFIG} idx) - if(${idx} LESS 0) - return() - endif(${idx} LESS 0) - foreach(f ${names}) - foreach(p ${paths}) - set(from_file "${p}/${f}") - set(to_dest "${CMAKE_BINARY_DIR}/newview/${dest}/") - if(EXISTS ${from_file}) - message("Copying ${from_file} to ${to_dest}") - if(NOT EXISTS ${to_dest}) - execute_process(COMMAND md "${to_dest}") - endif(NOT EXISTS ${to_dest}) - execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${from_file}" "${to_dest}${f}" RESULT_VARIABLE result) - if(${result}) - message(SEND_ERROR "Unsuccessful.") - endif(${result}) - set(found 1) - break() - endif(EXISTS ${from_file}) - endforeach(p) - if(NOT found) - message(SEND_ERROR "Failed to find library: ${f}") - endif(NOT found) - endforeach(f) -endfunction(copy_files) - -set(vivox_files - ca-bundle.crt - libsndfile-1.dll - ortp.dll - SLVoice.exe - vivoxoal.dll - vivoxplatform.dll - vivoxsdk.dll - zlib1.dll - ) -copy_files("${LIBS_RELEASE_DIR}" "${vivox_files}" "Release" ) -copy_files("${LIBS_RELEASE_DIR}" "${vivox_files}" "RelWithDebInfo") -copy_files("${LIBS_DEBUG_DIR}" "${vivox_files}" "Debug") - -set(release_files - libhunspell.dll - libapr-1.dll - libaprutil-1.dll - libapriconv-1.dll - libeay32.dll - ssleay32.dll - glod.dll - qtcore4.dll - ) -copy_files("${LIBS_RELEASE_DIR}" "${release_files}" "Release") -copy_files("${LIBS_RELEASE_DIR}" "${release_files}" "RelWithDebInfo") -copy_files("${LIBS_DEBUG_DIR}" "${release_files}" "Debug") - -if(MSVC10) - copy_files("${LIBS_DEBUG_DIR}" "libcollada14dom22-d.dll" "Debug") -endif(MSVC10) - -if(WORD_SIZE EQUAL 32) -set(release_files - libcollada14dom22.dll - libtcmalloc_minimal.dll - ) - copy_files("${LIBS_RELEASE_DIR}" "${release_files}" "Release") - copy_files("${LIBS_RELEASE_DIR}" "${release_files}" "RelWithDebInfo") -endif(WORD_SIZE EQUAL 32) - -set(plugins_release_files - libeay32.dll - qtcore4.dll - qtgui4.dll - qtnetwork4.dll - qtopengl4.dll - qtwebkit4.dll - ssleay32.dll - qtxmlpatterns4.dll - ) -copy_files("${LIBS_RELEASE_DIR}" "${plugins_release_files}" "Release/llplugin") -copy_files("${LIBS_RELEASE_DIR}" "${plugins_release_files}" "RelWithDebInfo/llplugin") -if(0) - copy_files("${LIBS_RELEASE_DIR}" "${plugin_release_files}" "../test_apps/llplugintest/Release") - copy_files("${LIBS_RELEASE_DIR}" "${plugin_release_files}" "../test_apps/llplugintest/RelWithDebInfo") -endif(0) - -# Debug config runtime files required for the plugins -set(plugins_debug_files - libeay32.dll - qtcored4.dll - qtguid4.dll - qtnetworkd4.dll - qtopengld4.dll - qtwebkitd4.dll - ssleay32.dll - qtxmlpatternsd4.dll - ) -copy_files("${LIBS_DEBUG_DIR}" "${plugins_debug_files}" "Debug/llplugin") -if(0) - copy_files("${LIBS_DEBUG_DIR}" "${plugins_debug_files}" "../test_apps/llplugintest/Debug") -endif(0) - -# Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins) -set(plugin_image_release_files - qgif4.dll - qico4.dll - qjpeg4.dll - qmng4.dll - qsvg4.dll - qtiff4.dll - ) -copy_files("${LIBS_RELEASE_DIR}/imageformats" "${plugin_image_release_files}" "Release/llplugin/imageformats") -copy_files("${LIBS_RELEASE_DIR}/imageformats" "${plugin_image_release_files}" "RelWithDebInfo/llplugin/imageformats") -if(0) - copy_files("${LIBS_RELEASE_DIR}/imageformats" "${plugin_image_release_files}" "../test_apps/llplugintest/imageformats/Release") - copy_files("${LIBS_RELEASE_DIR}/imageformats" "${plugin_image_release_files}" "../test_apps/llplugintest/imageformats/RelWithDebInfo") -endif(0) - - -# Debug config runtime files required for the plugin test mule (Qt image format plugins) -set(plugin_image_debug_files - qgifd4.dll - qicod4.dll - qjpegd4.dll - qmngd4.dll - qsvgd4.dll - qtiffd4.dll - ) -copy_files("${LIBS_DEBUG_DIR}/imageformats" "${plugin_image_debug_files}" "Debug/llplugin/imageformats") -if(0) - copy_files("${LIBS_DEBUG_DIR}/imageformats" "${plugin_image_debug_files}" "../test_apps/llplugintest/imageformats/Debug") -endif(0) - -# Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins) -set(plugin_codec_release_files - qcncodecs4.dll - qjpcodecs4.dll - qkrcodecs4.dll - qtwcodecs4.dll - ) -copy_files("${LIBS_RELEASE_DIR}/codecs" "${plugin_codec_release_files}" "Release/llplugin/codecs") -copy_files("${LIBS_RELEASE_DIR}/codecs" "${plugin_codec_release_files}" "RelWithDebInfo/llplugin/codecs") -if(0) - copy_files("${LIBS_RELEASE_DIR}/codecs" "${plugin_codec_release_files}" "../test_apps/llplugintest/codecs/Release") - copy_files("${LIBS_RELEASE_DIR}/codecs" "${plugin_codec_release_files}" "../test_apps/llplugintest/codecs/RelWithDebInfo") -endif(0) - -# Debug config runtime files required for the plugin test mule (Qt image format plugins) -set(plugin_codec_debug_files - qcncodecsd4.dll - qjpcodecsd4.dll - qkrcodecsd4.dll - qtwcodecsd4.dll - ) -copy_files("${LIBS_DEBUG_DIR}/codecs" "${plugin_codec_debug_files}" "Debug/llplugin/codecs") -if(0) - copy_files("${LIBS_DEBUG_DIR}/codecs" "${plugin_codec_debug_files}" "../test_apps/llplugintest/codecs/Debug") -endif(0) - - - diff --git a/indra/cmake/CrashPad.cmake b/indra/cmake/CrashPad.cmake new file mode 100644 index 0000000000..d3f4ed6b74 --- /dev/null +++ b/indra/cmake/CrashPad.cmake @@ -0,0 +1,22 @@ +# -*- cmake -*- +include(Prebuilt) +include(Variables) + +if(USE_CRASHPAD) + +if (USESYSTEMLIBS) +else (USESYSTEMLIBS) + use_prebuilt_binary(crashpad) + if (WINDOWS) + set(CRASHPAD_LIBRARIES + debug client.lib util.lib base.lib + optimized client.lib util.lib base.lib) + elseif (LINUX) + + else (DARWIN) + + endif () + set(CRASHPAD_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/crashpad) +endif (USESYSTEMLIBS) + +endif() diff --git a/indra/cmake/DBusGlib.cmake b/indra/cmake/DBusGlib.cmake index cb1b3a302f..031796927c 100644 --- a/indra/cmake/DBusGlib.cmake +++ b/indra/cmake/DBusGlib.cmake @@ -1,25 +1,11 @@ # -*- cmake -*- -include(Prebuilt) -if (STANDALONE) +if (LINUX) include(FindPkgConfig) pkg_check_modules(DBUSGLIB REQUIRED dbus-glib-1) -elseif (LINUX) - use_prebuilt_binary(dbusglib) - set(DBUSGLIB_FOUND ON FORCE BOOL) - set(DBUSGLIB_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include/dbus - ${LIBS_PREBUILT_LEGACY_DIR}/include/dbus - ) - # We don't need to explicitly link against dbus-glib itself, because - # the viewer probes for the system's copy at runtime. - set(DBUSGLIB_LIBRARIES - gobject-2.0 - glib-2.0 - ) -endif (STANDALONE) +endif (LINUX) if (DBUSGLIB_FOUND) set(DBUSGLIB ON CACHE BOOL "Build with dbus-glib message bus support.") diff --git a/indra/cmake/DeploySharedLibs.cmake b/indra/cmake/DeploySharedLibs.cmake new file mode 100644 index 0000000000..41b7e6a5bb --- /dev/null +++ b/indra/cmake/DeploySharedLibs.cmake @@ -0,0 +1,70 @@ +# DeploySharedLibs.cmake +# This is a script to be run at build time! Its not part of the cmake configuration! +# See indra/cmake/LLSharedLibs.cmake for a macro that simplifies adding a command to a target to run this script. + +# This script requires a few cmake variable to be set on the command line: +# BIN_NAME= The full path the the binary to search for dependecies. +# SEARCH_DIRS= The full paths to dirs to search for dependencies. +# DST_PATH= The full path where the dependecies will be copied. +get_filename_component(current_dir ${CMAKE_CURRENT_LIST_FILE} PATH) +include(GetPrerequisites) + +message("Getting recursive dependencies for file: ${BIN_NAME}") + +set(EXCLUDE_SYSTEM 1) +set(RECURSE 0) +get_filename_component(EXE_PATH ${BIN_NAME} PATH) + +get_prerequisites( ${BIN_NAME} RESULTS ${EXCLUDE_SYSTEM} ${RECURSE} "${EXE_PATH}" "${SEARCH_DIRS}" ) + +foreach(DEP ${RESULTS}) + Message("Processing dependency: ${DEP}") + get_filename_component(DEP_FILE ${DEP} NAME) + set(DEP_FILES ${DEP_FILES} ${DEP_FILE}) +endforeach(DEP) + +if(DEP_FILES) + list(REMOVE_DUPLICATES DEP_FILES) +endif(DEP_FILES) + +foreach(DEP_FILE ${DEP_FILES}) + if(FOUND_FILES) + list(FIND FOUND_FILES ${DEP_FILE} FOUND) + else(FOUND_FILES) + set(FOUND -1) + endif(FOUND_FILES) + + if(FOUND EQUAL -1) + find_path(DEP_PATH ${DEP_FILE} PATHS ${SEARCH_DIRS} NO_DEFAULT_PATH) + if(DEP_PATH) + set(FOUND_FILES ${FOUND_FILES} "${DEP_PATH}/${DEP_FILE}") + set(DEP_PATH NOTFOUND) #reset DEP_PATH for the next find_path call. + else(DEP_PATH) + set(MISSING_FILES ${MISSING_FILES} ${DEP_FILE}) + endif(DEP_PATH) + endif(FOUND EQUAL -1) +endforeach(DEP_FILE) + +if(MISSING_FILES) + message("Missing:") + foreach(FILE ${MISSING_FILES}) + message(" ${FILE}") + endforeach(FILE) + message("Searched in:") + foreach(SEARCH_DIR ${SEARCH_DIRS}) + message(" ${SEARCH_DIR}") + endforeach(SEARCH_DIR) + message(FATAL_ERROR "Failed") +endif(MISSING_FILES) + +if(FOUND_FILES) + foreach(FILE ${FOUND_FILES}) + get_filename_component(DST_FILE ${FILE} NAME) + set(DST_FILE "${DST_PATH}/${DST_FILE}") + message("Copying ${FILE} to ${DST_FILE}") + execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FILE} ${DST_FILE} + ) + endforeach(FILE ${FOUND_FILES}) +endif(FOUND_FILES) +message("Success!") diff --git a/indra/cmake/DirectX.cmake b/indra/cmake/DirectX.cmake deleted file mode 100644 index 56547bb7d3..0000000000 --- a/indra/cmake/DirectX.cmake +++ /dev/null @@ -1,82 +0,0 @@ -# -*- cmake -*- - -include(Variables) - -if (WINDOWS) - if (WORD_SIZE EQUAL 32) - set (DIRECTX_ARCHITECTURE x86) - elseif (WORD_SIZE EQUAL 64) - set (DIRECTX_ARCHITECTURE x64) - else (WORD_SIZE EQUAL 32) - set (DIRECTX_ARCHITECTURE x86) - endif (WORD_SIZE EQUAL 32) - - SET(program_files $ENV{ProgramW6432}) - if(NOT program_files) - SET(program_files $ENV{ProgramFiles}) - endif(NOT program_files) - SET(program_files_x86 "ProgramFiles(x86)") - SET(program_files_x86 $ENV{${program_files_x86}}) - - find_path(DIRECTX_ROOT_DIR Include/dxdiag.h - PATHS - "$ENV{DXSDK_DIR}" - "${program_files}/Microsoft DirectX SDK (June 2010)" - "${program_files_x86}/Microsoft DirectX SDK (June 2010)" - "${program_files}/Microsoft DirectX SDK (February 2010)" - "${program_files_x86}/Microsoft DirectX SDK (February 2010)" - "${program_files}/Microsoft DirectX SDK (March 2009)" - "${program_files_x86}/Microsoft DirectX SDK (March 2009)" - "${program_files}/Microsoft DirectX SDK (August 2008)" - "${program_files_x86}/Microsoft DirectX SDK (August 2008)" - "${program_files}/Microsoft DirectX SDK (June 2008)" - "${program_files_x86}/Microsoft DirectX SDK (June 2008)" - "${program_files}/Microsoft DirectX SDK (March 2008)" - "${program_files_x86}/Microsoft DirectX SDK (March 2008)" - "${program_files}/Microsoft DirectX SDK (November 2007)" - "${program_files_x86}/Microsoft DirectX SDK (November 2007)" - "${program_files}/Microsoft DirectX SDK (August 2007)" - "${program_files_x86}/Microsoft DirectX SDK (August 2007)" - ) - - if (DIRECTX_ROOT_DIR) - set (DIRECTX_INCLUDE_DIR "${DIRECTX_ROOT_DIR}/Include") - set (DIRECTX_LIBRARY_DIR "${DIRECTX_ROOT_DIR}/Lib/${DIRECTX_ARCHITECTURE}") - else (DIRECTX_ROOT_DIR) - find_path (WIN_KIT_ROOT_DIR Include/um/windows.h - PATHS - "${program_files}/Windows Kits/8.1" - "${program_files_x86}/Windows Kits/8.1" - "${program_files}/Windows Kits/8.0" - "${program_files_x86}/Windows Kits/8.0" - ) - - find_path (WIN_KIT_LIB_DIR dxguid.lib - "${WIN_KIT_ROOT_DIR}/Lib/winv6.3/um/${DIRECTX_ARCHITECTURE}" - "${WIN_KIT_ROOT_DIR}/Lib/Win8/um/${DIRECTX_ARCHITECTURE}" - ) - - if (WIN_KIT_ROOT_DIR AND WIN_KIT_LIB_DIR) - set (DIRECTX_INCLUDE_DIR "${WIN_KIT_ROOT_DIR}/Include/um" "${WIN_KIT_ROOT_DIR}/Include/shared") - set (DIRECTX_LIBRARY_DIR "${WIN_KIT_LIB_DIR}") - endif (WIN_KIT_ROOT_DIR AND WIN_KIT_LIB_DIR) - endif (DIRECTX_ROOT_DIR) - - if (DIRECTX_INCLUDE_DIR) - include_directories(${DIRECTX_INCLUDE_DIR}) - if (DIRECTX_FIND_QUIETLY) - message(STATUS "Found DirectX include: ${DIRECTX_INCLUDE_DIR}") - endif (DIRECTX_FIND_QUIETLY) - else (DIRECTX_INCLUDE_DIR) - message(FATAL_ERROR "Could not find DirectX SDK Include") - endif (DIRECTX_INCLUDE_DIR) - - if (DIRECTX_LIBRARY_DIR) - if (DIRECTX_FIND_QUIETLY) - message(STATUS "Found DirectX include: ${DIRECTX_LIBRARY_DIR}") - endif (DIRECTX_FIND_QUIETLY) - else (DIRECTX_LIBRARY_DIR) - message(FATAL_ERROR "Could not find DirectX SDK Libraries") - endif (DIRECTX_LIBRARY_DIR) - -endif (WINDOWS) diff --git a/indra/cmake/DownloadPrebuilt.cmake.in b/indra/cmake/DownloadPrebuilt.cmake.in deleted file mode 100644 index 5b67fedd45..0000000000 --- a/indra/cmake/DownloadPrebuilt.cmake.in +++ /dev/null @@ -1,45 +0,0 @@ -# This script drives download of prebuilt packages during the build. -# The top-level CMakeLists.txt configures packages and tool locations. -set(packages "@PREBUILT_PACKAGES@") -set(python "@PYTHON_EXECUTABLE@") -set(install_dir "@CMAKE_BINARY_DIR@/packages") -set(scp "@SCP_EXECUTABLE@") -set(scripts_dir "@SCRIPTS_DIR@") -set(sentinel_dir "@CMAKE_BINARY_DIR@/prepare") -set(prebuilt_type "@PREBUILT_TYPE@") - -# In proprietary mode we use scp for download. -set(proprietary "@INSTALL_PROPRIETARY@") -if(proprietary) - set(scp_option "--scp=${scp}") - set(proprietary_message " proprietary") -endif(proprietary) - -foreach(package ${packages}) - if(${install_dir}/install.xml IS_NEWER_THAN ${sentinel_dir}/${package}_installed) - # This package is missing or out of date. - message(STATUS "Obtaining${proprietary_message} prebuilt '${package}'") - execute_process( - COMMAND ${python} install.py -p${prebuilt_type} --install-dir=${install_dir} --installed-manifest=${install_dir}/installed.xml ${scp_option} ${package} - WORKING_DIRECTORY ${scripts_dir} - RESULT_VARIABLE result - ) - if(result STREQUAL 0) - # Write a sentinel to avoid attempting a download again. - file(WRITE ${sentinel_dir}/${package}_installed "Obtained '${package}'") - else(result STREQUAL 0) - # Remove the sentinel to ensure a download is attempted again. - file(REMOVE ${sentinel_dir}/prebuilt - ${sentinel_dir}/${package}_installed) - message(FATAL_ERROR - "Failed to download or unpack prebuilt '${package}'. " - "Process returned: ${result}") - endif(result STREQUAL 0) - else(${install_dir}/install.xml IS_NEWER_THAN ${sentinel_dir}/${package}_installed) - # This package is ready. - message(STATUS "Prebuilt '${package}' is up-to-date") - endif(${install_dir}/install.xml IS_NEWER_THAN ${sentinel_dir}/${package}_installed) -endforeach(package) - -# Store a sentinel to avoid running this script unnecessarily. -file(WRITE ${sentinel_dir}/prebuilt "All prebuilts obtained successfully\n") diff --git a/indra/cmake/ELFIO.cmake b/indra/cmake/ELFIO.cmake deleted file mode 100644 index 8de2c36d4a..0000000000 --- a/indra/cmake/ELFIO.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# -*- cmake -*- -include(Prebuilt) - -set(ELFIO_FIND_QUIETLY ON) - -if (STANDALONE) - include(FindELFIO) -elseif (LINUX) - use_prebuilt_binary(elfio) - set(ELFIO_LIBRARIES ELFIO) - set(ELFIO_INCLUDE_DIR - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) - set(ELFIO_FOUND "YES") -endif (STANDALONE) - -if (ELFIO_FOUND) - add_definitions(-DLL_ELFBIN=1) -else (ELFIO_FOUND) - set(ELFIO_INCLUDE_DIR "") -endif (ELFIO_FOUND) diff --git a/indra/cmake/EXPAT.cmake b/indra/cmake/EXPAT.cmake index bafe1a91e8..d11c6a9aff 100644 --- a/indra/cmake/EXPAT.cmake +++ b/indra/cmake/EXPAT.cmake @@ -9,16 +9,9 @@ if (STANDALONE) else (STANDALONE) use_prebuilt_binary(expat) if (WINDOWS) - if (MSVC12) - set(EXPAT_LIBRARIES expat) - else (MSVC12) - set(EXPAT_LIBRARIES libexpatMT) - endif (MSVC12) + set(EXPAT_LIBRARIES expat) else (WINDOWS) set(EXPAT_LIBRARIES expat) endif (WINDOWS) - set(EXPAT_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) + set(EXPAT_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) endif (STANDALONE) diff --git a/indra/cmake/FMODEX.cmake b/indra/cmake/FMODEX.cmake deleted file mode 100644 index ae95866c4a..0000000000 --- a/indra/cmake/FMODEX.cmake +++ /dev/null @@ -1,116 +0,0 @@ -# -*- cmake -*- - -include(Linking) - -if (FMODEX AND FMODSTUDIO) - message( FATAL_ERROR "You can not enable two FMOD variants at the same time." ) -endif (FMODEX AND FMODSTUDIO) - -unset(FMOD_LIBRARY_RELEASE CACHE) -unset(FMOD_LIBRARY_DEBUG CACHE) -unset(FMOD_INCLUDE_DIR CACHE) - -set(FMOD_EXTERNAL_LIB OFF) - -if(STANDALONE OR WINDOWS) - if (NOT FMODEX_SDK_DIR AND WINDOWS) - GET_FILENAME_COMPONENT(REG_DIR [HKEY_CURRENT_USER\\Software\\FMOD\ Programmers\ API\ Windows] ABSOLUTE) - set(FMODEX_SDK_DIR ${REG_DIR} CACHE PATH "Path to the FMOD Ex SDK." FORCE) - endif (NOT FMODEX_SDK_DIR AND WINDOWS) - if(NOT FMODEX_SDK_DIR AND STANDALONE) - message(FATAL_ERROR "FMODEX_SDK_DIR not set!") - endif(NOT FMODEX_SDK_DIR AND STANDALONE) -endif(STANDALONE OR WINDOWS) - -if(FMODEX_SDK_DIR) - set(fmod_lib_paths "${FMODEX_SDK_DIR}/api" "${FMODEX_SDK_DIR}/api/lib" ) - set(fmod_inc_paths "${FMODEX_SDK_DIR}/api/inc") - - if(WINDOWS) - set(CMAKE_FIND_LIBRARY_SUFFIXES_OLD ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set(CMAKE_FIND_LIBRARY_SUFFIXES .dll) - endif(WINDOWS) - if(WORD_SIZE EQUAL 64) - find_library(FMOD_LIBRARY_RELEASE fmodex64 PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - find_library(FMOD_LIBRARY_DEBUG fmodexL64 PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - else(WORD_SIZE EQUAL 64)#Check if CMAKE_FIND_LIBRARY_PREFIXES is set to 'lib' for darwin. - find_library(FMOD_LIBRARY_RELEASE fmodex PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - find_library(FMOD_LIBRARY_DEBUG fmodexL PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - endif(WORD_SIZE EQUAL 64) - if(WINDOWS) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_OLD}) - if(WORD_SIZE EQUAL 64) - find_library(FMOD_LINK_LIBRARY_RELEASE fmodex64_vc PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - find_library(FMOD_LINK_LIBRARY_DEBUG fmodexL64_vc PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - else(WORD_SIZE EQUAL 64)#Check if CMAKE_FIND_LIBRARY_PREFIXES is set to 'lib' for darwin. - find_library(FMOD_LINK_LIBRARY_RELEASE fmodex_vc PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - find_library(FMOD_LINK_LIBRARY_DEBUG fmodexL_vc PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - endif(WORD_SIZE EQUAL 64) - else(WINDOWS) - set(FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE}) - set(FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG}) - endif(WINDOWS) - find_path(FMOD_INCLUDE_DIR fmod.hpp ${fmod_inc_paths}) - if(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR) - if(STANDALONE) - message(FATAL_ERROR "Provided FMODEX_SDK_DIR path not found '{$FMODEX_SDK_DIR}'") - else(STANDALONE) - message(STATUS "Provided FMODEX_SDK_DIR path not found '${FMODEX_SDK_DIR}'. Falling back to prebuilts") - endif(STANDALONE) - else(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR) - message(STATUS "Using system-provided FMOD Ex Libraries") - set(FMOD_EXTERNAL_LIB ON) - endif(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR) -endif (FMODEX_SDK_DIR) - -if (NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR) - if(WINDOWS) - set(lib_suffix .dll) - elseif(DARWIN) - set(lib_suffix .dylib) - else(WINDOWS) - set(lib_suffix .so) - endif(WINDOWS) - if(WINDOWS) - if(WORD_SIZE EQUAL 64) - set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/fmodex64${lib_suffix}) - set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/fmodexL64${lib_suffix}) - else(WORD_SIZE EQUAL 64) - set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/fmodex${lib_suffix}) - set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/fmodexL${lib_suffix}) - endif(WORD_SIZE EQUAL 64) - else(WINDOWS) - if(WORD_SIZE EQUAL 64) - set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/libfmodex64${lib_suffix}) - set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/libfmodex64L${lib_suffix}) - else(WORD_SIZE EQUAL 64) - set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/libfmodex${lib_suffix}) - set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/libfmodexL${lib_suffix}) - endif(WORD_SIZE EQUAL 64) - endif(WINDOWS) - set(FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE}) - set(FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG}) - if(WINDOWS) - string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE}) - string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG}) - endif(WINDOWS) - use_prebuilt_binary(fmodex) - set(FMOD_INCLUDE_DIR - ${LIBS_PREBUILT_DIR}/include/fmodex) -endif(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR) - -if(FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR) - set(FMOD ON) - if (NOT FMOD_LIBRARY_DEBUG) #Use release library in debug configuration if debug library is absent. - set(FMOD_LIBRARY_DEBUG ${FMOD_LIBRARY_RELEASE}) - endif (NOT FMOD_LIBRARY_DEBUG) -else (FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR) - message(STATUS "No support for FMOD EX audio (need to set FMODEX_SDK_DIR?)") - set(FMOD OFF) - set(FMODEX OFF) -endif (FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR) - -if (FMOD) - message(STATUS "Building with FMOD Ex audio support") - set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") -endif (FMOD) diff --git a/indra/cmake/FMODSTUDIO.cmake b/indra/cmake/FMODSTUDIO.cmake index fac23b3d3d..83ac0ac9c4 100644 --- a/indra/cmake/FMODSTUDIO.cmake +++ b/indra/cmake/FMODSTUDIO.cmake @@ -1,70 +1,8 @@ # -*- cmake -*- -include(Linking) - -if (FMODEX AND FMODSTUDIO) - message( FATAL_ERROR "You can not enable two FMOD variants at the same time." ) -endif (FMODEX AND FMODSTUDIO) - -unset(FMOD_LIBRARY_RELEASE CACHE) -unset(FMOD_LIBRARY_DEBUG CACHE) -unset(FMOD_INCLUDE_DIR CACHE) - -set(FMOD_EXTERNAL_LIB OFF) - -if(STANDALONE OR WINDOWS) - if (NOT FMODSTUDIO_SDK_DIR AND WINDOWS) - #GET_FILENAME_COMPONENT(REG_DIR [HKEY_CURRENT_USER\\Software\\FMOD\ Studio\ API\ Windows] ABSOLUTE) - #set(FMODSTUDIO_SDK_DIR ${REG_DIR} CACHE PATH "Path to the FMOD Studio SDK." FORCE) - endif (NOT FMODSTUDIO_SDK_DIR AND WINDOWS) - if(NOT FMODSTUDIO_SDK_DIR AND STANDALONE) - message(FATAL_ERROR "FMODSTUDIO_SDK_DIR not set!") - endif(NOT FMODSTUDIO_SDK_DIR AND STANDALONE) -endif(STANDALONE OR WINDOWS) - -if(FMODSTUDIO_SDK_DIR) - if(LINUX AND WORD_SIZE EQUAL 32) - set(fmod_lib_paths "${FMODSTUDIO_SDK_DIR}/api/lowlevel/lib/x86" ) - elseif(LINUX) - set(fmod_lib_paths "${FMODSTUDIO_SDK_DIR}/api/lowlevel/lib/x86_64") - else(LINUX AND WORD_SIZE EQUAL 32) - set(fmod_lib_paths "${FMODSTUDIO_SDK_DIR}/api/lowlevel/lib") - endif(LINUX AND WORD_SIZE EQUAL 32) - set(fmod_inc_paths "${FMODSTUDIO_SDK_DIR}/api/lowlevel/inc") - - if(WINDOWS) - set(CMAKE_FIND_LIBRARY_SUFFIXES_OLD ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set(CMAKE_FIND_LIBRARY_SUFFIXES .dll) - endif(WINDOWS) - if(WORD_SIZE EQUAL 64 AND WINDOWS) - find_library(FMOD_LIBRARY_RELEASE fmod64 PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - find_library(FMOD_LIBRARY_DEBUG fmodL64 PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - else(WORD_SIZE EQUAL 64 AND WINDOWS)#Check if CMAKE_FIND_LIBRARY_PREFIXES is set to 'lib' for darwin. - find_library(FMOD_LIBRARY_RELEASE fmod PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - find_library(FMOD_LIBRARY_DEBUG fmodL PATHS ${fmod_lib_paths} NO_DEFAULT_PATH) - endif(WORD_SIZE EQUAL 64 AND WINDOWS) - if(WINDOWS) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_OLD}) - string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE}) - string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG}) - else(WINDOWS) - set(FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE}) - set(FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG}) - endif(WINDOWS) - find_path(FMOD_INCLUDE_DIR fmod.hpp ${fmod_inc_paths}) - if(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR) - if(STANDALONE) - message(FATAL_ERROR "Provided FMODSTUDIO_SDK_DIR path not found '{$FMODSTUDIO_SDK_DIR}'") - else(STANDALONE) - message(STATUS "Provided FMODSTUDIO_SDK_DIR path not found '${FMODSTUDIO_SDK_DIR}'. Falling back to prebuilts") - endif(STANDALONE) - else(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR) - message(STATUS "Using system-provided FMOD Studio Libraries") - set(FMOD_EXTERNAL_LIB ON) - endif(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR) -endif (FMODSTUDIO_SDK_DIR) - -if (NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR) +include(Variables) +if (USE_FMODSTUDIO) + use_prebuilt_binary(fmodstudio) if(WINDOWS) set(lib_suffix .dll) elseif(DARWIN) @@ -73,40 +11,40 @@ if (NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR) set(lib_suffix .so) endif(WINDOWS) if(WINDOWS) - if(WORD_SIZE EQUAL 64) - set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/fmod64${lib_suffix}) - set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/fmodL64${lib_suffix}) - else(WORD_SIZE EQUAL 64) - set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/fmod${lib_suffix}) - set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/fmodL${lib_suffix}) - endif(WORD_SIZE EQUAL 64) + set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/fmod${lib_suffix}) + set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/fmodL${lib_suffix}) else(WINDOWS) set(FMOD_LIBRARY_RELEASE ${LIBS_PREBUILT_DIR}/lib/release/libfmod${lib_suffix}) set(FMOD_LIBRARY_DEBUG ${LIBS_PREBUILT_DIR}/lib/debug/libfmodL${lib_suffix}) endif(WINDOWS) set(FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE}) set(FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG}) + if(WINDOWS) string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_RELEASE ${FMOD_LIBRARY_RELEASE}) string(REPLACE ".dll" "_vc.lib" FMOD_LINK_LIBRARY_DEBUG ${FMOD_LIBRARY_DEBUG}) endif(WINDOWS) - use_prebuilt_binary(fmodstudio) - set(FMOD_INCLUDE_DIR - ${LIBS_PREBUILT_DIR}/include/fmodstudio) -endif(NOT FMOD_LIBRARY_RELEASE OR NOT FMOD_INCLUDE_DIR) -if(FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR) + set (FMOD_LIBRARY + debug ${FMOD_LINK_LIBRARY_DEBUG} + optimized ${FMOD_LINK_LIBRARY_RELEASE} + ) + + set(FMODSTUDIO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodstudio) +endif(USE_FMODSTUDIO) + +if(FMOD_LIBRARY_RELEASE AND FMODSTUDIO_INCLUDE_DIR) set(FMOD ON) if (NOT FMOD_LIBRARY_DEBUG) #Use release library in debug configuration if debug library is absent. set(FMOD_LIBRARY_DEBUG ${FMOD_LIBRARY_RELEASE}) endif (NOT FMOD_LIBRARY_DEBUG) -else (FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR) +else (FMOD_LIBRARY_RELEASE AND FMODSTUDIO_INCLUDE_DIR) message(STATUS "No support for FMOD Studio audio (need to set FMODSTUDIO_SDK_DIR?)") set(FMOD OFF) - set(FMODSTUDIO OFF) -endif (FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR) + set(USE_FMODSTUDIO OFF) +endif (FMOD_LIBRARY_RELEASE AND FMODSTUDIO_INCLUDE_DIR) if (FMOD) message(STATUS "Building with FMOD Studio audio support") - set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODSTUDIO") endif (FMOD) + diff --git a/indra/cmake/FindAutobuild.cmake b/indra/cmake/FindAutobuild.cmake new file mode 100644 index 0000000000..ea5ad6d108 --- /dev/null +++ b/indra/cmake/FindAutobuild.cmake @@ -0,0 +1,43 @@ +# -*- cmake -*- +# +# Find the autobuild tool +# +# Output variables: +# +# AUTOBUILD_EXECUTABLE - path to autobuild executable + + + +IF (NOT AUTOBUILD_EXECUTABLE) + + # If cmake was executed by autobuild, autobuild will have set the AUTOBUILD env var + IF (DEFINED ENV{AUTOBUILD}) + SET(AUTOBUILD_EXECUTABLE $ENV{AUTOBUILD}) + ELSE (DEFINED ENV{AUTOBUILD}) + IF(WIN32) + SET(AUTOBUILD_EXE_NAMES autobuild.exe autobuild.cmd) + ELSE(WIN32) + SET(AUTOBUILD_EXE_NAMES autobuild) + ENDIF(WIN32) + + SET(AUTOBUILD_EXECUTABLE) + FIND_PROGRAM( + AUTOBUILD_EXECUTABLE + NAMES ${AUTOBUILD_EXE_NAMES} + PATHS + ENV PATH + ${CMAKE_SOURCE_DIR}/.. + ${CMAKE_SOURCE_DIR}/../.. + ${CMAKE_SOURCE_DIR}/../../.. + PATH_SUFFIXES "/autobuild/bin/" + ) + ENDIF (DEFINED ENV{AUTOBUILD}) + + IF (NOT AUTOBUILD_EXECUTABLE) + IF (AUTOBUILD_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find autobuild executable") + ENDIF (AUTOBUILD_FIND_REQUIRED) + ENDIF (NOT AUTOBUILD_EXECUTABLE) + + MARK_AS_ADVANCED(AUTOBUILD_EXECUTABLE) +ENDIF (NOT AUTOBUILD_EXECUTABLE) diff --git a/indra/cmake/FindBerkeleyDB.cmake b/indra/cmake/FindBerkeleyDB.cmake deleted file mode 100644 index 2d633c74ec..0000000000 --- a/indra/cmake/FindBerkeleyDB.cmake +++ /dev/null @@ -1,50 +0,0 @@ -# -*- cmake -*- - -# - Find BerkeleyDB -# Find the BerkeleyDB includes and library -# This module defines -# DB_INCLUDE_DIR, where to find db.h, etc. -# DB_LIBRARIES, the libraries needed to use BerkeleyDB. -# DB_FOUND, If false, do not try to use BerkeleyDB. -# also defined, but not for general use are -# DB_LIBRARY, where to find the BerkeleyDB library. - -FIND_PATH(DB_INCLUDE_DIR db.h -/usr/local/include/db4 -/usr/local/include -/usr/include/db4 -/usr/include -) - -SET(DB_NAMES ${DB_NAMES} db) -FIND_LIBRARY(DB_LIBRARY - NAMES ${DB_NAMES} - PATHS /usr/lib /usr/local/lib - ) - -IF (DB_LIBRARY AND DB_INCLUDE_DIR) - SET(DB_LIBRARIES ${DB_LIBRARY}) - SET(DB_FOUND "YES") -ELSE (DB_LIBRARY AND DB_INCLUDE_DIR) - SET(DB_FOUND "NO") -ENDIF (DB_LIBRARY AND DB_INCLUDE_DIR) - - -IF (DB_FOUND) - IF (NOT DB_FIND_QUIETLY) - MESSAGE(STATUS "Found BerkeleyDB: ${DB_LIBRARIES}") - ENDIF (NOT DB_FIND_QUIETLY) -ELSE (DB_FOUND) - IF (DB_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find BerkeleyDB library") - ENDIF (DB_FIND_REQUIRED) -ENDIF (DB_FOUND) - -# Deprecated declarations. -SET (NATIVE_DB_INCLUDE_PATH ${DB_INCLUDE_DIR} ) -GET_FILENAME_COMPONENT (NATIVE_DB_LIB_PATH ${DB_LIBRARY} PATH) - -MARK_AS_ADVANCED( - DB_LIBRARY - DB_INCLUDE_DIR - ) diff --git a/indra/cmake/FindELFIO.cmake b/indra/cmake/FindELFIO.cmake deleted file mode 100644 index 8a5421ab9c..0000000000 --- a/indra/cmake/FindELFIO.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# -*- cmake -*- - -# - Find ELFIO -# Find the ELFIO includes and library -# This module defines -# ELFIO_INCLUDE_DIR, where to find elfio.h, etc. -# ELFIO_LIBRARIES, the libraries needed to use ELFIO. -# ELFIO_FOUND, If false, do not try to use ELFIO. -# also defined, but not for general use are -# ELFIO_LIBRARY, where to find the ELFIO library. - -FIND_PATH(ELFIO_INCLUDE_DIR ELFIO/ELFIO.h -/usr/local/include -/usr/include -) - -SET(ELFIO_NAMES ${ELFIO_NAMES} ELFIO) -FIND_LIBRARY(ELFIO_LIBRARY - NAMES ${ELFIO_NAMES} - PATHS /usr/lib /usr/local/lib - ) - -IF (ELFIO_LIBRARY AND ELFIO_INCLUDE_DIR) - SET(ELFIO_LIBRARIES ${ELFIO_LIBRARY}) - SET(ELFIO_FOUND "YES") -ELSE (ELFIO_LIBRARY AND ELFIO_INCLUDE_DIR) - SET(ELFIO_FOUND "NO") -ENDIF (ELFIO_LIBRARY AND ELFIO_INCLUDE_DIR) - - -IF (ELFIO_FOUND) - IF (NOT ELFIO_FIND_QUIETLY) - MESSAGE(STATUS "Found ELFIO: ${ELFIO_LIBRARIES}") - ENDIF (NOT ELFIO_FIND_QUIETLY) -ELSE (ELFIO_FOUND) - IF (ELFIO_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find ELFIO library") - ENDIF (ELFIO_FIND_REQUIRED) -ENDIF (ELFIO_FOUND) - -# Deprecated declarations. -SET (NATIVE_ELFIO_INCLUDE_PATH ${ELFIO_INCLUDE_DIR} ) -GET_FILENAME_COMPONENT (NATIVE_ELFIO_LIB_PATH ${ELFIO_LIBRARY} PATH) - -MARK_AS_ADVANCED( - ELFIO_LIBRARY - ELFIO_INCLUDE_DIR - ) diff --git a/indra/cmake/FindGoogleBreakpad.cmake b/indra/cmake/FindGoogleBreakpad.cmake deleted file mode 100644 index 18e0b56edf..0000000000 --- a/indra/cmake/FindGoogleBreakpad.cmake +++ /dev/null @@ -1,40 +0,0 @@ -# -*- cmake -*- - -# - Find Google BreakPad -# Find the Google BreakPad includes and library -# This module defines -# BREAKPAD_INCLUDE_DIRECTORIES, where to find the Goole BreakPad includes. -# BREAKPAD_EXCEPTION_HANDLER_LIBRARIES, the libraries needed to use Google BreakPad. -# BREAKPAD_EXCEPTION_HANDLER_FOUND, If false, do not try to use Google BreakPad. -# also defined, but not for general use are -# BREAKPAD_EXCEPTION_HANDLER_LIBRARY, where to find the Google BreakPad library. - -FIND_PATH(BREAKPAD_INCLUDE_DIRECTORIES common/using_std_string.h PATH_SUFFIXES google_breakpad) - -SET(BREAKPAD_EXCEPTION_HANDLER_NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES} breakpad_client) -FIND_LIBRARY(BREAKPAD_EXCEPTION_HANDLER_LIBRARY - NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES} - ) - -IF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_INCLUDE_DIRECTORIES) - SET(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES ${BREAKPAD_EXCEPTION_HANDLER_LIBRARY}) - SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "YES") -ELSE (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_INCLUDE_DIRECTORIES) - SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "NO") -ENDIF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_INCLUDE_DIRECTORIES) - - -IF (BREAKPAD_EXCEPTION_HANDLER_FOUND) - IF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY) - MESSAGE(STATUS "Found Google BreakPad: ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES}") - ENDIF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY) -ELSE (BREAKPAD_EXCEPTION_HANDLER_FOUND) - IF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find Google BreakPad library") - ENDIF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED) -ENDIF (BREAKPAD_EXCEPTION_HANDLER_FOUND) - -MARK_AS_ADVANCED( - BREAKPAD_EXCEPTION_HANDLER_LIBRARY - BREAKPAD_INCLUDE_DIRECTORIES - ) diff --git a/indra/cmake/FindJsonCpp.cmake b/indra/cmake/FindJsonCpp.cmake deleted file mode 100644 index a48c973964..0000000000 --- a/indra/cmake/FindJsonCpp.cmake +++ /dev/null @@ -1,39 +0,0 @@ -# -*- cmake -*- - -# - Find JSONCpp -# Find the JSONCpp includes and library -# This module defines -# JSONCPP_FOUND, System has libjsoncpp. -# JSONCPP_INCLUDE_DIRS - The libjsoncpp include directories. -# JSONCPP_LIBRARIES - The libraries needed to use libjsoncpp. -# JSONCPP_DEFINITIONS - Compiler switches required for using libjsoncpp. - -FIND_PACKAGE(PkgConfig) -PKG_CHECK_MODULES(PC_JSONCPP jsoncpp) -SET(JSONCPP_DEFINITIONS ${PC_JSONCPP_CFLAGS_OTHER}) - -FIND_PATH(JSONCPP_INCLUDE_DIR json/reader.h - HINTS ${PC_JSONCPP_INCLUDE_DIR} ${PC_JSONCPP_INCLUDE_DIRS} - PATH_SUFFIXES jsoncpp) - -# Get the GCC compiler version -EXEC_PROGRAM(${CMAKE_CXX_COMPILER} - ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion - OUTPUT_VARIABLE _gcc_COMPILER_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - -# Try to find a library that was compiled with the same compiler version as we currently use. -FIND_LIBRARY(JSONCPP_LIBRARY - NAMES libjson_linux-gcc-${_gcc_COMPILER_VERSION}_libmt.so libjsoncpp.so - HINTS ${PC_JSONCPP_LIBDIR} ${PC_JSONCPP_LIBRARY_DIRS} - PATHS /usr/lib /usr/local/lib) - -SET(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY}) -SET(JSONCPP_INCLUDE_DIRS ${JSONCPP_INCLUDE_DIR}) - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(JSONCPP DEFAULT_MSG - JSONCPP_LIBRARY JSONCPP_INCLUDE_DIR) - -MARK_AS_ADVANCED(JSONCPP_LIBRARY JSONCPP_INCLUDE_DIR) diff --git a/indra/cmake/FindLLQtWebkit.cmake b/indra/cmake/FindLLQtWebkit.cmake deleted file mode 100644 index 731ae67d75..0000000000 --- a/indra/cmake/FindLLQtWebkit.cmake +++ /dev/null @@ -1,62 +0,0 @@ -# -*- cmake -*- - -# - Find llqtwebkit -# Find the llqtwebkit includes and library -# This module defines -# LLQTWEBKIT_INCLUDE_DIR, where to find llqtwebkit.h, etc. -# LLQTWEBKIT_LIBRARY, the llqtwebkit library with full path. -# LLQTWEBKIT_FOUND, If false, do not try to use llqtwebkit. -# also defined, but not for general use are -# LLQTWEBKIT_LIBRARIES, the libraries needed to use llqtwebkit. -# LLQTWEBKIT_LIBRARY_DIRS, where to find the llqtwebkit library. -# LLQTWEBKIT_DEFINITIONS - You should add_definitions(${LLQTWEBKIT_DEFINITIONS}) -# before compiling code that includes llqtwebkit library files. - -# Try to use pkg-config first. -# This allows to have two different libllqtwebkit packages installed: -# one for viewer 2.x and one for viewer 1.x. -include(FindPkgConfig) -if (PKG_CONFIG_FOUND) - if (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION) - set(_PACKAGE_ARGS libllqtwebkit>=${LLQtWebkit_FIND_VERSION} REQUIRED) - else (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION) - set(_PACKAGE_ARGS libllqtwebkit) - endif (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION) - if (NOT "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_LESS "2.8") - # As virtually nobody will have a pkg-config file for this, do this check always quiet. - # Unfortunately cmake 2.8 or higher is required for pkg_check_modules to have a 'QUIET'. - set(_PACKAGE_ARGS ${_PACKAGE_ARGS} QUIET) - endif () - pkg_check_modules(LLQTWEBKIT ${_PACKAGE_ARGS}) -endif (PKG_CONFIG_FOUND) -set(LLQTWEBKIT_DEFINITIONS ${LLQTWEBKIT_CFLAGS_OTHER}) - -find_path(LLQTWEBKIT_INCLUDE_DIR llqtwebkit.h NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_INCLUDE_DIRS}) - -find_library(LLQTWEBKIT_LIBRARY NAMES llqtwebkit NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_LIBRARY_DIRS}) - -if (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) # If pkg-config couldn't find it, pretend we don't have pkg-config. - set(LLQTWEBKIT_LIBRARIES llqtwebkit) - get_filename_component(LLQTWEBKIT_LIBRARY_DIRS ${LLQTWEBKIT_LIBRARY} PATH) -endif (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) - -# Handle the QUIETLY and REQUIRED arguments and set LLQTWEBKIT_FOUND -# to TRUE if all listed variables are TRUE. -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args( - LLQTWEBKIT - DEFAULT_MSG - LLQTWEBKIT_LIBRARY - LLQTWEBKIT_INCLUDE_DIR - LLQTWEBKIT_LIBRARIES - LLQTWEBKIT_LIBRARY_DIRS - ) - -mark_as_advanced( - LLQTWEBKIT_LIBRARY - LLQTWEBKIT_INCLUDE_DIR - LLQTWEBKIT_LIBRARIES - LLQTWEBKIT_LIBRARY_DIRS - LLQTWEBKIT_DEFINITIONS - ) - diff --git a/indra/cmake/FindURIPARSER.cmake b/indra/cmake/FindURIPARSER.cmake new file mode 100644 index 0000000000..05f2d17374 --- /dev/null +++ b/indra/cmake/FindURIPARSER.cmake @@ -0,0 +1,46 @@ +# -*- cmake -*- + +# - Find uriparser +# Find the URIPARSER includes and library +# This module defines +# URIPARSER_INCLUDE_DIRS, where to find uriparser.h, etc. +# URIPARSER_LIBRARY, the libraries needed to use uriparser. +# URIPARSER_FOUND, If false, do not try to use uriparser. +# +# This FindURIPARSER is about 43 times as fast the one provided with cmake (2.8.x), +# because it doesn't look up the version of uriparser, resulting in a dramatic +# speed up for configure (from 4 minutes 22 seconds to 6 seconds). +# +# Note: Since this file is only used for standalone, the windows +# specific parts were left out. + +FIND_PATH(URIPARSER_INCLUDE_DIR uriparser/Uri.h + NO_SYSTEM_ENVIRONMENT_PATH + ) + +FIND_LIBRARY(URIPARSER_LIBRARY uriparser) + +if (URIPARSER_LIBRARY AND URIPARSER_INCLUDE_DIR) + SET(URIPARSER_INCLUDE_DIRS ${URIPARSER_INCLUDE_DIR}) + SET(URIPARSER_LIBRARY ${URIPARSER_LIBRARY}) + SET(URIPARSER_FOUND "YES") +else (URIPARSER_LIBRARY AND URIPARSER_INCLUDE_DIR) + SET(URIPARSER_FOUND "NO") +endif (URIPARSER_LIBRARY AND URIPARSER_INCLUDE_DIR) + +if (URIPARSER_FOUND) + if (NOT URIPARSER_FIND_QUIETLY) + message(STATUS "Found URIPARSER: ${URIPARSER_LIBRARY}") + SET(URIPARSER_FIND_QUIETLY TRUE) + endif (NOT URIPARSER_FIND_QUIETLY) +else (URIPARSER_FOUND) + if (URIPARSER_FIND_REQUIRED) + message(FATAL_ERROR "Could not find URIPARSER library") + endif (URIPARSER_FIND_REQUIRED) +endif (URIPARSER_FOUND) + +mark_as_advanced( + URIPARSER_LIBRARY + URIPARSER_INCLUDE_DIR + ) + diff --git a/indra/cmake/FreeType.cmake b/indra/cmake/FreeType.cmake index 5cca587cfa..da122419d1 100644 --- a/indra/cmake/FreeType.cmake +++ b/indra/cmake/FreeType.cmake @@ -1,25 +1,14 @@ # -*- cmake -*- include(Prebuilt) -if (STANDALONE) +if (LINUX) include(FindPkgConfig) pkg_check_modules(FREETYPE REQUIRED freetype2) -else (STANDALONE) +else (LINUX) use_prebuilt_binary(freetype) - if(MSVC12) - set(FREETYPE_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include/freetype2 - ${LIBS_PREBUILT_LEGACY_DIR}/include/freetype2 - ) - else(MSVC12) - set(FREETYPE_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) - endif (MSVC12) - + set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/freetype2) set(FREETYPE_LIBRARIES freetype) -endif (STANDALONE) +endif (LINUX) link_directories(${FREETYPE_LIBRARY_DIRS}) diff --git a/indra/cmake/GLOD.cmake b/indra/cmake/GLOD.cmake index d688db2fee..73881e17a1 100644 --- a/indra/cmake/GLOD.cmake +++ b/indra/cmake/GLOD.cmake @@ -7,10 +7,8 @@ set(GLOD_FIND_REQUIRED ON) if (STANDALONE) include(FindGLOD) else (STANDALONE) - use_prebuilt_binary(GLOD) - set(GLOD_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) - set(GLOD_LIBRARIES glod) + use_prebuilt_binary(glod) + + set(GLOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/glod) + set(GLOD_LIBRARIES GLOD) endif (STANDALONE) diff --git a/indra/cmake/GStreamer010Plugin.cmake b/indra/cmake/GStreamer010Plugin.cmake index 9fdf60eba3..c9b071d1ea 100644 --- a/indra/cmake/GStreamer010Plugin.cmake +++ b/indra/cmake/GStreamer010Plugin.cmake @@ -1,30 +1,9 @@ # -*- cmake -*- include(Prebuilt) - -if (STANDALONE) include(FindPkgConfig) - pkg_check_modules(GSTREAMER010 REQUIRED gstreamer-0.10) pkg_check_modules(GSTREAMER010_PLUGINS_BASE REQUIRED gstreamer-plugins-base-0.10) -else (STANDALONE) - - # Possibly libxml and glib should have their own .cmake file instead... - use_prebuilt_binary(glib) # gstreamer needs glib - use_prebuilt_binary(libxml) - use_prebuilt_binary(gstreamer) - set(GSTREAMER010_FOUND ON FORCE BOOL) - set(GSTREAMER010_PLUGINS_BASE_FOUND ON FORCE BOOL) - set(GSTREAMER010_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include/gstreamer-0.10 - ${LIBS_PREBUILT_DIR}/includeg/lib-2.0 - ${LIBS_PREBUILT_DIR}/include/libxml2 - ${LIBS_PREBUILT_LEGACY_DIR}/include/gstreamer-0.10 - ${LIBS_PREBUILT_LEGACY_DIR}/include/glib-2.0 - ${LIBS_PREBUILT_LEGACY_DIR}/include/libxml2 - ) - -endif (STANDALONE) if (WINDOWS) # We don't need to explicitly link against gstreamer itself, because diff --git a/indra/cmake/GeneratePrecompiledHeader.cmake b/indra/cmake/GeneratePrecompiledHeader.cmake new file mode 100644 index 0000000000..67929d3a38 --- /dev/null +++ b/indra/cmake/GeneratePrecompiledHeader.cmake @@ -0,0 +1,116 @@ +# -*- cmake -*- + +# Distributed under the MIT Software License +# Copyright (c) 2015-2017 Borislav Stanimirov +# Modifications Copyright (c) 2019 Cinder Roxley. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# target_precompiled_header +# +# Sets a precompiled header for a given target +# Args: +# TARGET_NAME - Name of the target. Only valid after add_library or add_executable +# PRECOMPILED_HEADER - Header file to precompile +# PRECOMPILED_SOURCE - MSVC specific source to do the actual precompilation. Ignored on other platforms +# + +macro(target_precompiled_header TARGET_NAME PRECOMPILED_HEADER PRECOMPILED_SOURCE) + get_filename_component(PRECOMPILED_HEADER_NAME ${PRECOMPILED_HEADER} NAME) + + if(MSVC) + get_filename_component(PRECOMPILED_SOURCE_NAME ${PRECOMPILED_SOURCE} NAME) + get_filename_component(PRECOMPILED_HEADER_PATH ${PRECOMPILED_HEADER} DIRECTORY) + target_include_directories(${TARGET_NAME} PRIVATE ${PRECOMPILED_HEADER_PATH}) # fixes occasional IntelliSense glitches + + get_filename_component(PRECOMPILED_HEADER_WE ${PRECOMPILED_HEADER} NAME_WE) + if(GEN_IS_MULTI_CONFIG) + set(PRECOMPILED_BINARY "$(IntDir)/${PRECOMPILED_HEADER_WE}.pch") + else() + set(PRECOMPILED_BINARY "${CMAKE_CURRENT_BINARY_DIR}/${PRECOMPILED_HEADER_WE}.pch") + endif() + + set_source_files_properties(${PRECOMPILED_SOURCE} PROPERTIES + COMPILE_OPTIONS "/Yc${PRECOMPILED_HEADER_NAME};/Fp${PRECOMPILED_BINARY}" + OBJECT_OUTPUTS "${PRECOMPILED_BINARY}") + + get_target_property(TARGET_SOURCES ${TARGET_NAME} SOURCES) + foreach(src ${TARGET_SOURCES}) + if(${src} MATCHES \\.\(cpp|cxx|cc\)$) + set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/${src}" PROPERTIES + COMPILE_OPTIONS "/Yu${PRECOMPILED_HEADER_NAME};/FI${PRECOMPILED_HEADER_NAME};/Fp${PRECOMPILED_BINARY}" + OBJECT_DEPENDS "${PRECOMPILED_BINARY}" + ) + endif() + endforeach() + #set_target_properties(${TARGET_NAME} PROPERTIES + # COMPILE_OPTIONS "/Yu${PRECOMPILED_HEADER_NAME};/FI${PRECOMPILED_HEADER_NAME};/Fp${PRECOMPILED_BINARY}") + + target_sources(${TARGET_NAME} PRIVATE ${PRECOMPILED_SOURCE} ${PRECOMPILED_HEADER}) + elseif(CMAKE_GENERATOR STREQUAL Xcode) + set_target_properties( + ${TARGET_NAME} + PROPERTIES + XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${PRECOMPILED_HEADER}" + XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES" + ) + elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # Create and set output directory. + set(OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${PRECOMPILED_HEADER_NAME}.gch") + make_directory(${OUTPUT_DIR}) + set(OUTPUT_NAME "${OUTPUT_DIR}/${PRECOMPILED_HEADER_NAME}.gch") + + # Export compiler flags via a generator to a response file + set(PCH_FLAGS_FILE "${OUTPUT_DIR}/${PRECOMPILED_HEADER_NAME}.rsp") + set(_include_directories "$") + set(_compile_definitions "$") + set(_compile_flags "$") + set(_compile_options "$") + set(_include_directories "$<$:-I$\n>") + set(_compile_definitions "$<$:-D$\n>") + set(_compile_flags "$<$:$\n>") + set(_compile_options "$<$:$\n>") + file(GENERATE OUTPUT "${PCH_FLAGS_FILE}" CONTENT "${_compile_definitions}${_include_directories}${_compile_flags}${_compile_options}\n") + + # Gather global compiler options, definitions, etc. + string(TOUPPER "CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}" CXX_FLAGS) + set(COMPILER_FLAGS "${${CXX_FLAGS}} ${CMAKE_CXX_FLAGS}") + separate_arguments(COMPILER_FLAGS) + + # Add a custom target for building the precompiled header. + add_custom_command( + OUTPUT ${OUTPUT_NAME} + COMMAND ${CMAKE_CXX_COMPILER} @${PCH_FLAGS_FILE} ${COMPILER_FLAGS} -x c++-header -o ${OUTPUT_NAME} ${PRECOMPILED_HEADER} + DEPENDS ${PRECOMPILED_HEADER}) + add_custom_target(${TARGET_NAME}_gch DEPENDS ${OUTPUT_NAME}) + add_dependencies(${TARGET_NAME} ${TARGET_NAME}_gch) + + # set_target_properties(${TARGET_NAME} PROPERTIES COMPILE_FLAGS "-include ${PRECOMPILED_HEADER_NAME} -Winvalid-pch") + get_target_property(SOURCE_FILES ${TARGET_NAME} SOURCES) + get_target_property(asdf ${TARGET_NAME} COMPILE_FLAGS) + foreach(SOURCE_FILE ${SOURCE_FILES}) + if(SOURCE_FILE MATCHES \\.\(c|cc|cxx|cpp\)$) + set_source_files_properties(${SOURCE_FILE} PROPERTIES + COMPILE_FLAGS "-include ${OUTPUT_DIR}/${PRECOMPILED_HEADER_NAME} -Winvalid-pch" + ) + endif() + endforeach() + else() + message(FATAL_ERROR "Unknown generator for target_precompiled_header. [${CMAKE_CXX_COMPILER_ID}]") + endif() +endmacro(target_precompiled_header) + diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake deleted file mode 100644 index de899a462f..0000000000 --- a/indra/cmake/GoogleBreakpad.cmake +++ /dev/null @@ -1,26 +0,0 @@ -# -*- cmake -*- -include(Prebuilt) - -if (STANDALONE) - set(BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED ON) - include(FindGoogleBreakpad) -else (STANDALONE) - use_prebuilt_binary(google_breakpad) - if (DARWIN) - set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler) - endif (DARWIN) - if (LINUX) - set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES breakpad_client) - endif (LINUX) - if (WINDOWS) - set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client crash_generation_server common) - endif (WINDOWS) - # yes, this does look dumb, no, it's not incorrect - # I think it's incorrect: the second one should go --Aleric - set(BREAKPAD_INCLUDE_DIRECTORIES - ${LIBS_PREBUILT_DIR}/include/google_breakpad - ${LIBS_PREBUILT_LEGACY_DIR}/include/google_breakpad - ${LIBS_PREBUILT_DIR}/include/google_breakpad/google_breakpad - ${LIBS_PREBUILT_LEGACY_DIR}/include/google_breakpad/google_breakpad - ) -endif (STANDALONE) diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 49ff3f5eb2..d951bc55ea 100644 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -2,16 +2,16 @@ include(Prebuilt) -if(WORD_SIZE EQUAL 64) +if(ADDRESS_SIZE EQUAL 64) set(DISABLE_TCMALLOC TRUE) -endif(WORD_SIZE EQUAL 64) +endif(ADDRESS_SIZE EQUAL 64) if (STANDALONE) include(FindGooglePerfTools) else (STANDALONE) - if (LINUX OR WINDOWS AND NOT WORD_SIZE EQUAL 64) + if (LINUX OR WINDOWS AND NOT ADDRESS_SIZE EQUAL 64) use_prebuilt_binary(gperftools) - endif (LINUX OR WINDOWS AND NOT WORD_SIZE EQUAL 64) + endif (LINUX OR WINDOWS AND NOT ADDRESS_SIZE EQUAL 64) if (WINDOWS AND NOT DISABLE_TCMALLOC) set(TCMALLOC_LIBRARIES libtcmalloc_minimal.lib) set(TCMALLOC_LINKER_FLAGS "/INCLUDE:\"__tcmalloc\"") diff --git a/indra/cmake/Hunspell.cmake b/indra/cmake/Hunspell.cmake index 3ea97afdf2..83f9bc2fda 100644 --- a/indra/cmake/Hunspell.cmake +++ b/indra/cmake/Hunspell.cmake @@ -4,16 +4,13 @@ include(Prebuilt) if (STANDALONE) include(FindHunSpell) else (STANDALONE) - use_prebuilt_binary(hunspell) - - set(HUNSPELL_INCLUDE_DIR - ${LIBS_PREBUILT_DIR}/include/hunspell - ${LIBS_PREBUILT_LEGACY_DIR}/include/hunspell - ) + use_prebuilt_binary(libhunspell) - if (LINUX OR DARWIN) - set(HUNSPELL_LIBRARY hunspell-1.3) - else (LINUX OR DARWIN) - set(HUNSPELL_LIBRARY libhunspell) - endif (LINUX OR DARWIN) + if (LINUX OR DARWIN) + set(HUNSPELL_LIBRARY hunspell-1.3) + else (LINUX OR DARWIN) + set(HUNSPELL_LIBRARY libhunspell) + endif (LINUX OR DARWIN) + set(HUNSPELL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/hunspell) + use_prebuilt_binary(dictionaries) endif (STANDALONE) diff --git a/indra/cmake/JPEG.cmake b/indra/cmake/JPEG.cmake index 2fe1beb51e..fd04fcce1b 100644 --- a/indra/cmake/JPEG.cmake +++ b/indra/cmake/JPEG.cmake @@ -19,8 +19,5 @@ else (STANDALONE) elseif (WINDOWS) set(JPEG_LIBRARIES jpeglib) endif (LINUX) - set(JPEG_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) + set(JPEG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) endif (STANDALONE) diff --git a/indra/cmake/Json.cmake b/indra/cmake/Json.cmake new file mode 100644 index 0000000000..5c98370476 --- /dev/null +++ b/indra/cmake/Json.cmake @@ -0,0 +1,6 @@ +# -*- cmake -*- + +include(Prebuilt) + +use_prebuilt_binary(modernjson) +set(JSON_INCLUDE_DIR "${LIBS_PREBUILT_DIR}/include") diff --git a/indra/cmake/JsonCpp.cmake b/indra/cmake/JsonCpp.cmake deleted file mode 100644 index 3ab859d4df..0000000000 --- a/indra/cmake/JsonCpp.cmake +++ /dev/null @@ -1,31 +0,0 @@ -# -*- cmake -*- - -include(Prebuilt) - -set(JSONCPP_FIND_QUIETLY OFF) -set(JSONCPP_FIND_REQUIRED ON) - -if (STANDALONE) - include(FindJsonCpp) -else (STANDALONE) - use_prebuilt_binary(jsoncpp) - if (WINDOWS) - if(MSVC12) - set(JSONCPP_LIBRARIES - debug json_vc${MSVC_SUFFIX}debug_libmt.lib - optimized json_vc${MSVC_SUFFIX}_libmt) - else(MSVC12) - set(JSONCPP_LIBRARIES - debug json_vc${MSVC_SUFFIX}d - optimized json_vc${MSVC_SUFFIX}) - endif(MSVC12) - elseif (DARWIN) - set(JSONCPP_LIBRARIES json_linux-gcc-4.0.1_libmt) - elseif (LINUX) - set(JSONCPP_LIBRARIES jsoncpp) - endif (WINDOWS) - set(JSONCPP_INCLUDE_DIR - ${LIBS_PREBUILT_DIR}/include/jsoncpp - ${LIBS_PREBUILT_LEGACY_DIR}/include/jsoncpp - ) -endif (STANDALONE) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 290db9f221..7875e5bfc9 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -105,17 +105,6 @@ MACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files) IF (NOT "$ENV{LD_LIBRARY_PATH}" STREQUAL "") SET(LD_LIBRARY_PATH "$ENV{LD_LIBRARY_PATH}:${LD_LIBRARY_PATH}") ENDIF (NOT "$ENV{LD_LIBRARY_PATH}" STREQUAL "") - ADD_CUSTOM_COMMAND( - OUTPUT ${TEST_OUTPUT} - COMMAND - ${CMAKE_COMMAND} - "-DLD_LIBRARY_PATH=${LD_LIBRARY_PATH}" - "-DTEST_CMD:STRING=${TEST_CMD}" - -P ${CMAKE_SOURCE_DIR}/cmake/RunBuildTest.cmake - DEPENDS ${name}_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - VERBATIM - ) ADD_CUSTOM_TARGET(${name}_test_ok ALL DEPENDS ${TEST_OUTPUT}) IF (${parent}) diff --git a/indra/cmake/LLAudio.cmake b/indra/cmake/LLAudio.cmake index 4400329678..3cd2b98d1c 100644 --- a/indra/cmake/LLAudio.cmake +++ b/indra/cmake/LLAudio.cmake @@ -1,11 +1,12 @@ # -*- cmake -*- include(Audio) +include(OPENAL) set(LLAUDIO_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llaudio ) -add_definitions(-DOV_EXCLUDE_STATIC_CALLBACKS) +#add_definitions(-DOV_EXCLUDE_STATIC_CALLBACKS) set(LLAUDIO_LIBRARIES llaudio ${OPENAL_LIBRARIES}) diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake index b1bb1b6a98..5f87e1e797 100644 --- a/indra/cmake/LLCommon.cmake +++ b/indra/cmake/LLCommon.cmake @@ -3,6 +3,7 @@ include(APR) include(Boost) include(EXPAT) +include(Linking) include(ZLIB) if (DARWIN) @@ -10,7 +11,6 @@ if (DARWIN) find_library(CORESERVICES_LIBRARY CoreServices) endif (DARWIN) - set(LLCOMMON_INCLUDE_DIRS ${LIBS_OPEN_DIR}/cwdebug ${LIBS_OPEN_DIR}/llcommon @@ -19,16 +19,11 @@ set(LLCOMMON_INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ) -if (LINUX) - # In order to support using ld.gold on linux, we need to explicitely - # specify all libraries that llcommon uses. - # llcommon uses `clock_gettime' which is provided by librt on linux. - set(LLCOMMON_LIBRARIES llcommon rt) -else (LINUX) - set(LLCOMMON_LIBRARIES llcommon) -endif (LINUX) +set(LLCOMMON_LIBRARIES llcommon + fmt::fmt + ) -set(LLCOMMON_LINK_SHARED ON CACHE BOOL "Build the llcommon target as a shared library.") +set(LLCOMMON_LINK_SHARED OFF CACHE BOOL "Build the llcommon target as a shared library.") if(LLCOMMON_LINK_SHARED) add_definitions(-DLL_COMMON_LINK_SHARED=1) endif(LLCOMMON_LINK_SHARED) diff --git a/indra/cmake/LLPlugin.cmake b/indra/cmake/LLPlugin.cmake index 399cb332dd..9722f16c3c 100644 --- a/indra/cmake/LLPlugin.cmake +++ b/indra/cmake/LLPlugin.cmake @@ -5,10 +5,4 @@ set(LLPLUGIN_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llplugin ) -if (LINUX) - # In order to support using ld.gold on linux, we need to explicitely - # specify all libraries that llplugin uses. - set(LLPLUGIN_LIBRARIES llplugin pthread) -else (LINUX) - set(LLPLUGIN_LIBRARIES llplugin) -endif (LINUX) +set(LLPLUGIN_LIBRARIES llplugin) diff --git a/indra/cmake/LLPrimitive.cmake b/indra/cmake/LLPrimitive.cmake index dd1d806d5e..ee465dc8bd 100644 --- a/indra/cmake/LLPrimitive.cmake +++ b/indra/cmake/LLPrimitive.cmake @@ -1,22 +1,32 @@ # -*- cmake -*- +# these should be moved to their own cmake file +include(Prebuilt) +include(Boost) include(Colladadom) + +use_prebuilt_binary(libxml2) + set(LLPRIMITIVE_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llprimitive ${COLLADADOM_INCLUDE_DIRS} ) if (WINDOWS) - set(LLPRIMITIVE_LIBRARIES - debug llprimitive - optimized llprimitive - ${COLLADADOM_LIBRARIES} - ) + set(LLPRIMITIVE_LIBRARIES + llprimitive + ${COLLADADOM_LIBRARIES} + libxml2_a + ${BOOST_SYSTEM_LIBRARIES} + ) else (WINDOWS) - set(LLPRIMITIVE_LIBRARIES - llprimitive - ${COLLADADOM_LIBRARIES} - ) + set(LLPRIMITIVE_LIBRARIES + llprimitive + ${COLLADADOM_LIBRARIES} + ${BOOST_SYSTEM_LIBRARIES} + minizip + xml2 + ) endif (WINDOWS) diff --git a/indra/cmake/LLQtWebkit.cmake b/indra/cmake/LLQtWebkit.cmake deleted file mode 100644 index cec7e22e9d..0000000000 --- a/indra/cmake/LLQtWebkit.cmake +++ /dev/null @@ -1,11 +0,0 @@ -# -*- cmake -*- - -if (STANDALONE) - set(LLQTWEBKIT_INCLUDE_DIR - ${LIBS_OPEN_DIR}/llqtwebkit - ) - - set(LLQTWEBKIT_LIBRARY - llqtwebkit - ) -endif (STANDALONE) diff --git a/indra/cmake/LLSharedLibs.cmake b/indra/cmake/LLSharedLibs.cmake index 982b2d3f79..f69b45cd92 100644 --- a/indra/cmake/LLSharedLibs.cmake +++ b/indra/cmake/LLSharedLibs.cmake @@ -1,33 +1,40 @@ # ll_deploy_sharedlibs_command # target_exe: the cmake target of the executable for which the shared libs will be deployed. macro(ll_deploy_sharedlibs_command target_exe) - SET(OUTPUT_PATH $) - - if(DARWIN) - SET_TEST_PATH(SEARCH_DIRS) - get_target_property(IS_BUNDLE ${target_exe} MACOSX_BUNDLE) - if(IS_BUNDLE) - # If its a bundle the exe is not in the target location, this should find it. - set(OUTPUT_PATH ${OUTPUT_PATH}/../Resources) - endif(IS_BUNDLE) - elseif(WINDOWS) - SET_TEST_PATH(SEARCH_DIRS) - LIST(APPEND SEARCH_DIRS "$ENV{SystemRoot}/system32") - elseif(LINUX) - SET_TEST_PATH(SEARCH_DIRS) - set(OUTPUT_PATH ${OUTPUT_PATH}/lib) - endif(DARWIN) + set(TARGET_LOCATION $) + get_filename_component(OUTPUT_PATH ${TARGET_LOCATION} PATH) + + # It's not clear that this does anything useful for us on Darwin. It has + # been broken for some time now; the BIN_NAME was being constructed as a + # ridiculous nonexistent path with duplicated segments. Fixing that only + # produces ominous spammy warnings: at the time the command below is run, we + # have not yet populated the nested mac-crash-logger.app/Contents/Resources + # with the .dylibs with which it was linked. Moreover, the form of the + # embedded @executable_path/../Resources/mumble.dylib pathname confuses the + # GetPrerequisites.cmake tool invoked by DeploySharedLibs.cmake. It seems + # clear that we have long since accomplished by other means what this was + # originally supposed to do. Skipping it only eliminates an annoying + # non-fatal error. + if(NOT DARWIN) + if(WINDOWS) + SET_TEST_PATH(SEARCH_DIRS) + LIST(APPEND SEARCH_DIRS "$ENV{SystemRoot}/system32") + elseif(LINUX) + SET_TEST_PATH(SEARCH_DIRS) + set(OUTPUT_PATH ${OUTPUT_PATH}/lib) + endif(WINDOWS) - add_custom_command( - TARGET ${target_exe} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - "-DBIN_NAME=\"$\"" - "-DSEARCH_DIRS=\"${SEARCH_DIRS}\"" - "-DDST_PATH=\"${OUTPUT_PATH}\"" - "-P" - "${CMAKE_SOURCE_DIR}/cmake/DeploySharedLibs.cmake" - ) + add_custom_command( + TARGET ${target_exe} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + "-DBIN_NAME=\"${TARGET_LOCATION}\"" + "-DSEARCH_DIRS=\"${SEARCH_DIRS}\"" + "-DDST_PATH=\"${OUTPUT_PATH}\"" + "-P" + "${CMAKE_SOURCE_DIR}/cmake/DeploySharedLibs.cmake" + ) + endif(NOT DARWIN) endmacro(ll_deploy_sharedlibs_command) @@ -38,8 +45,7 @@ macro(ll_stage_sharedlib DSO_TARGET) # Also this directory is shared with RunBuildTest.cmake, y'know, for the tests. set_target_properties(${DSO_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${SHARED_LIB_STAGING_DIR}) if(NOT WINDOWS) - - SET(DSO_PATH $) + get_target_property(DSO_PATH ${DSO_TARGET} LOCATION) get_filename_component(DSO_FILE ${DSO_PATH} NAME) if(DARWIN) set(SHARED_LIB_STAGING_DIR_CONFIG ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources) diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake index c5de9d2695..2d78cd76a5 100644 --- a/indra/cmake/LLWindow.cmake +++ b/indra/cmake/LLWindow.cmake @@ -1,9 +1,8 @@ # -*- cmake -*- include(OpenGL) -include(Prebuilt) -if (STANDALONE) +if (LINUX) include(FindSDL) # This should be done by FindSDL. Sigh. @@ -12,22 +11,7 @@ if (STANDALONE) SDL_INCLUDE_DIR SDL_LIBRARY ) -else (STANDALONE) - if (LINUX) - use_prebuilt_binary(mesa) - use_prebuilt_binary(SDL) - set (SDL_FOUND TRUE) - set (SDL_INCLUDE_DIR - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) - if(WORD_SIZE EQUAL 64) - set (SDL_LIBRARY SDL) - else(WORD_SIZE EQUAL 64) - set (SDL_LIBRARY SDL directfb fusion direct) - endif(WORD_SIZE EQUAL 64) - endif (LINUX) -endif (STANDALONE) +endif (LINUX) if (SDL_FOUND) add_definitions(-DLL_SDL=1) diff --git a/indra/cmake/LibVLCPlugin.cmake b/indra/cmake/LibVLCPlugin.cmake new file mode 100644 index 0000000000..0787edd2c9 --- /dev/null +++ b/indra/cmake/LibVLCPlugin.cmake @@ -0,0 +1,30 @@ +# -*- cmake -*- +include(Linking) +include(Prebuilt) +include(Variables) + +if (LIBVLCPLUGIN) +if (USESYSTEMLIBS) +else (USESYSTEMLIBS) + use_prebuilt_binary(vlc-bin) + set(VLC_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/vlc) +endif (USESYSTEMLIBS) + +if (WINDOWS) + set(VLC_PLUGIN_LIBRARIES + libvlc.lib + libvlccore.lib + ) +elseif (DARWIN) + set(VLC_PLUGIN_LIBRARIES + libvlc.dylib + libvlccore.dylib + ) +elseif (LINUX) + # Specify a full path to make sure we get a static link + set(VLC_PLUGIN_LIBRARIES + ${LIBS_PREBUILT_DIR}/lib/libvlc.a + ${LIBS_PREBUILT_DIR}/lib/libvlccore.a + ) +endif (WINDOWS) +endif (LIBVLCPLUGIN) diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index a0ce0f6f1d..22e49fd0ba 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -1,55 +1,66 @@ # -*- cmake -*- + if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") include(Variables) -if (NOT STANDALONE) - - if(CMAKE_BUILD_TYPE) - string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER) - endif(CMAKE_BUILD_TYPE) +set(ARCH_PREBUILT_DIRS ${AUTOBUILD_INSTALL_DIR}/lib) +set(ARCH_PREBUILT_DIRS_PLUGINS ${AUTOBUILD_INSTALL_DIR}/plugins) +set(ARCH_PREBUILT_DIRS_RELEASE ${AUTOBUILD_INSTALL_DIR}/lib/release) +set(ARCH_PREBUILT_DIRS_DEBUG ${AUTOBUILD_INSTALL_DIR}/lib/debug) +if (WINDOWS) + set(SHARED_LIB_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs) + set(EXE_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs) +elseif (LINUX) + set(SHARED_LIB_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs/lib) + set(EXE_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs/bin) +elseif (DARWIN) + set(SHARED_LIB_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs) + set(EXE_STAGING_DIR "${CMAKE_BINARY_DIR}/sharedlibs") +endif (WINDOWS) - if(WINDOWS OR ${CMAKE_GENERATOR} MATCHES "Xcode") - # the cmake xcode and VS generators implicitly append ${CMAKE_CFG_INTDIR} to the library paths for us - # fortunately both windows and darwin are case insensitive filesystems so this works. - set(ARCH_PREBUILT_LINK_DIRS - ${LIBS_PREBUILT_DIR}/lib - ${LIBS_PREBUILT_LEGACY_DIR}/lib - ) - else(WINDOWS OR ${CMAKE_GENERATOR} MATCHES "Xcode") - # else block is for linux and any other makefile based generators - set(ARCH_PREBUILT_LINK_DIRS - ${LIBS_PREBUILT_DIR}/lib/${CMAKE_BUILD_TYPE_LOWER} - ${LIBS_PREBUILT_LEGACY_DIR}/lib/${CMAKE_BUILD_TYPE_LOWER} - ) - endif(WINDOWS OR ${CMAKE_GENERATOR} MATCHES "Xcode") +# Autobuild packages must provide 'release' versions of libraries, but may provide versions for +# specific build types. AUTOBUILD_LIBS_INSTALL_DIRS lists first the build type directory and then +# the 'release' directory (as a default fallback). +# *NOTE - we have to take special care to use CMAKE_CFG_INTDIR on IDE generators (like mac and +# windows) and CMAKE_BUILD_TYPE on Makefile based generators (like linux). The reason for this is +# that CMAKE_BUILD_TYPE is essentially meaningless at configuration time for IDE generators and +# CMAKE_CFG_INTDIR is meaningless at build time for Makefile generators +if(GEN_IS_MULTI_CONFIG) + # the cmake xcode and VS generators implicitly append ${CMAKE_CFG_INTDIR} to the library paths for us + # fortunately both windows and darwin are case insensitive filesystems so this works. + set(AUTOBUILD_LIBS_INSTALL_DIRS "${AUTOBUILD_INSTALL_DIR}/lib/") +else() + # else block is for linux and any other makefile based generators + string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER) + set(AUTOBUILD_LIBS_INSTALL_DIRS ${AUTOBUILD_INSTALL_DIR}/lib/${CMAKE_BUILD_TYPE_LOWER}) +endif() - if (NOT "${CMAKE_BUILD_TYPE_LOWER}" STREQUAL "release") - # When we're building something other than Release, append the - # packages/lib/release directory to deal with autobuild packages that don't - # provide (e.g.) lib/debug libraries. - list(APPEND ARCH_PREBUILT_LINK_DIRS - ${LIBS_PREBUILT_DIR}/lib/release - ${LIBS_PREBUILT_LEGACY_DIR}/lib/release - ) - endif (NOT "${CMAKE_BUILD_TYPE_LOWER}" STREQUAL "release") -endif (NOT STANDALONE) +if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release") + # When we're building something other than Release, append the + # packages/lib/release directory to deal with autobuild packages that don't + # provide (e.g.) lib/debug libraries. + list(APPEND AUTOBUILD_LIBS_INSTALL_DIRS ${ARCH_PREBUILT_DIRS_RELEASE}) +endif (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release") -link_directories(${ARCH_PREBUILT_LINK_DIRS}) +link_directories(${AUTOBUILD_LIBS_INSTALL_DIRS}) if (LINUX) set(DL_LIBRARY dl) + set(RT_LIBRARY rt) set(PTHREAD_LIBRARY pthread) else (LINUX) set(DL_LIBRARY "") + set(RT_LIBRARY "") set(PTHREAD_LIBRARY "") endif (LINUX) -if (WINDOWS) +if (WINDOWS) set(WINDOWS_LIBRARIES advapi32 shell32 + ole32 ws2_32 mswsock psapi @@ -64,6 +75,6 @@ else (WINDOWS) set(WINDOWS_LIBRARIES "") endif (WINDOWS) -mark_as_advanced(DL_LIBRARY PTHREAD_LIBRARY WINDOWS_LIBRARIES) +mark_as_advanced(DL_LIBRARY RT_LIBRARY PTHREAD_LIBRARY WINDOWS_LIBRARIES) endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/cmake/NDOF.cmake b/indra/cmake/NDOF.cmake index d7fb4e686b..20c1e97873 100644 --- a/indra/cmake/NDOF.cmake +++ b/indra/cmake/NDOF.cmake @@ -7,7 +7,11 @@ if (STANDALONE) message(STATUS "Building without N-DoF joystick support") endif(NOT NDOF_FOUND) else (STANDALONE) - use_prebuilt_binary(ndofdev) + if (WINDOWS OR DARWIN) + use_prebuilt_binary(libndofdev) + elseif (LINUX) + use_prebuilt_binary(libndofdev-open) + endif (WINDOWS OR DARWIN) if (WINDOWS) set(NDOF_LIBRARY libndofdev) @@ -15,10 +19,11 @@ else (STANDALONE) set(NDOF_LIBRARY ndofdev) endif (WINDOWS) - set(NDOF_INCLUDE_DIR - ${LIBS_PREBUILT_DIR}/include/ndofdev - ${LIBS_PREBUILT_LEGACY_DIR}/include/ndofdev - ) + if (WINDOWS) + set(NDOF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) + else (WINDOWS) + set(NDOF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/ndofdev) + endif (WINDOWS) set(NDOF_FOUND 1) endif (STANDALONE) @@ -26,6 +31,8 @@ if (NDOF_FOUND) add_definitions(-DLIB_NDOF=1) include_directories(${NDOF_INCLUDE_DIR}) else (NDOF_FOUND) + message(STATUS "Building without N-DoF joystick support") set(NDOF_INCLUDE_DIR "") set(NDOF_LIBRARY "") endif (NDOF_FOUND) + diff --git a/indra/cmake/NVAPI.cmake b/indra/cmake/NVAPI.cmake index d60e42c875..3cdf5ca474 100644 --- a/indra/cmake/NVAPI.cmake +++ b/indra/cmake/NVAPI.cmake @@ -2,20 +2,18 @@ include(Prebuilt) include(Variables) -set(NVAPI ON CACHE BOOL "Use NVAPI.") - -if (NVAPI) +if (USE_NVAPI) if (WINDOWS) use_prebuilt_binary(nvapi) - if (WORD_SIZE EQUAL 32) + if (ADDRESS_SIZE EQUAL 32) set(NVAPI_LIBRARY nvapi) - elseif (WORD_SIZE EQUAL 64) + elseif (ADDRESS_SIZE EQUAL 64) set(NVAPI_LIBRARY nvapi64) - endif (WORD_SIZE EQUAL 32) + endif (ADDRESS_SIZE EQUAL 32) else (WINDOWS) set(NVAPI_LIBRARY "") endif (WINDOWS) -else (NVAPI) +else (USE_NVAPI) set(NVAPI_LIBRARY "") -endif (NVAPI) +endif (USE_NVAPI) diff --git a/indra/cmake/OPENAL.cmake b/indra/cmake/OPENAL.cmake index 39ab8210d6..c25eb929ea 100644 --- a/indra/cmake/OPENAL.cmake +++ b/indra/cmake/OPENAL.cmake @@ -2,7 +2,6 @@ include(Linking) include(Prebuilt) -if(NOT FMOD) if (LINUX) set(OPENAL ON CACHE BOOL "Enable OpenAL") else (LINUX) @@ -10,26 +9,25 @@ else (LINUX) endif (LINUX) if (OPENAL) + set(OPENAL_LIB_INCLUDE_DIRS "${LIBS_PREBUILT_DIR}/include/AL") if (STANDALONE) include(FindPkgConfig) include(FindOpenAL) pkg_check_modules(OPENAL_LIB REQUIRED openal) pkg_check_modules(FREEALUT_LIB REQUIRED freealut) else (STANDALONE) - use_prebuilt_binary(openal-soft) + use_prebuilt_binary(openal) endif (STANDALONE) + if(WINDOWS) set(OPENAL_LIBRARIES - openal + OpenAL32 alut ) - set(OPENAL_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) -endif (OPENAL) - -if (OPENAL) + else() + set(OPENAL_LIBRARIES + openal + alut + ) + endif() message(STATUS "Building with OpenAL audio support") - set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL") endif (OPENAL) -endif(NOT FMOD) diff --git a/indra/cmake/OpenGL.cmake b/indra/cmake/OpenGL.cmake index abf908f236..c77295f630 100644 --- a/indra/cmake/OpenGL.cmake +++ b/indra/cmake/OpenGL.cmake @@ -1,4 +1,6 @@ # -*- cmake -*- + +include(Variables) include(Prebuilt) if (NOT (STANDALONE OR DARWIN)) @@ -8,3 +10,5 @@ if (NOT (STANDALONE OR DARWIN)) ${LIBS_PREBUILT_LEGACY_DIR}/include ) endif (NOT (STANDALONE OR DARWIN)) + +include(FindOpenGL) diff --git a/indra/cmake/OpenSSL.cmake b/indra/cmake/OpenSSL.cmake index d363e6af32..8456fc1d72 100644 --- a/indra/cmake/OpenSSL.cmake +++ b/indra/cmake/OpenSSL.cmake @@ -7,16 +7,13 @@ set(OpenSSL_FIND_REQUIRED ON) if (STANDALONE OR USE_SYSTEM_OPENSSL) include(FindOpenSSL) else (STANDALONE OR USE_SYSTEM_OPENSSL) - use_prebuilt_binary(openSSL) + use_prebuilt_binary(openssl) if (WINDOWS) - set(OPENSSL_LIBRARIES ssleay32 libeay32) + set(OPENSSL_LIBRARIES libssl libcrypto) else (WINDOWS) set(OPENSSL_LIBRARIES ssl) endif (WINDOWS) - set(OPENSSL_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) + set(OPENSSL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) endif (STANDALONE OR USE_SYSTEM_OPENSSL) if (LINUX) diff --git a/indra/cmake/PNG.cmake b/indra/cmake/PNG.cmake index fb71c30677..3d02a5e4f3 100644 --- a/indra/cmake/PNG.cmake +++ b/indra/cmake/PNG.cmake @@ -9,11 +9,7 @@ if (STANDALONE) else (STANDALONE) use_prebuilt_binary(libpng) if (WINDOWS) - if(MSVC12) - set(PNG_LIBRARIES libpng16) - else(MSVC12) - set(PNG_LIBRARIES libpng15) - endif(MSVC12) + set(PNG_LIBRARIES libpng16) elseif(DARWIN) set(PNG_LIBRARIES png15) else(LINUX) @@ -36,15 +32,5 @@ else (STANDALONE) set(PNG_LIBRARIES png16) endif () endif() - if (WINDOWS) - set(PNG_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include/${PNG_LIBRARIES} - ${LIBS_PREBUILT_LEGACY_DIR}/include/${PNG_LIBRARIES} - ) - else (WINDOWS) - set(PNG_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include/lib${PNG_LIBRARIES} - ${LIBS_PREBUILT_LEGACY_DIR}/include/lib${PNG_LIBRARIES} - ) - endif (WINDOWS) + set(PNG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/libpng16) endif (STANDALONE) diff --git a/indra/cmake/Prebuilt.cmake b/indra/cmake/Prebuilt.cmake index 2295a75745..33a6d76916 100644 --- a/indra/cmake/Prebuilt.cmake +++ b/indra/cmake/Prebuilt.cmake @@ -3,14 +3,62 @@ if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") +include(FindAutobuild) +if(INSTALL_PROPRIETARY) + include(FindSCP) +endif(INSTALL_PROPRIETARY) + +set(PREBUILD_TRACKING_DIR ${AUTOBUILD_INSTALL_DIR}/cmake_tracking) +# For the library installation process; +# see cmake/Prebuild.cmake for the counterpart code. +if ("${CMAKE_SOURCE_DIR}/../autobuild.xml" IS_NEWER_THAN "${PREBUILD_TRACKING_DIR}/sentinel_installed") + file(MAKE_DIRECTORY ${PREBUILD_TRACKING_DIR}) + file(WRITE ${PREBUILD_TRACKING_DIR}/sentinel_installed "0") +endif ("${CMAKE_SOURCE_DIR}/../autobuild.xml" IS_NEWER_THAN "${PREBUILD_TRACKING_DIR}/sentinel_installed") + +# The use_prebuilt_binary macro handles automated installation of package +# dependencies using autobuild. The goal is that 'autobuild install' should +# only be run when we know we need to install a new package. This should be +# the case in a clean checkout, or if autobuild.xml has been updated since the +# last run (encapsulated by the file ${PREBUILD_TRACKING_DIR}/sentinel_installed), +# or if a previous attempt to install the package has failed (the exit status +# of previous attempts is serialized in the file +# ${PREBUILD_TRACKING_DIR}/${_binary}_installed) macro (use_prebuilt_binary _binary) - if(NOT STANDALONE) - get_property(PREBUILT_PACKAGES TARGET prepare PROPERTY PREBUILT) - list(FIND PREBUILT_PACKAGES ${_binary} _index) - if(_index LESS 0) - set_property(TARGET prepare APPEND PROPERTY PREBUILT ${_binary}) - endif(_index LESS 0) - endif(NOT STANDALONE) + if (NOT DEFINED USESYSTEMLIBS_${_binary}) + set(USESYSTEMLIBS_${_binary} ${USESYSTEMLIBS}) + endif (NOT DEFINED USESYSTEMLIBS_${_binary}) + + if (NOT USESYSTEMLIBS_${_binary}) + if("${${_binary}_installed}" STREQUAL "" AND EXISTS "${PREBUILD_TRACKING_DIR}/${_binary}_installed") + file(READ ${PREBUILD_TRACKING_DIR}/${_binary}_installed "${_binary}_installed") + if(DEBUG_PREBUILT) + message(STATUS "${_binary}_installed: \"${${_binary}_installed}\"") + endif(DEBUG_PREBUILT) + endif("${${_binary}_installed}" STREQUAL "" AND EXISTS "${PREBUILD_TRACKING_DIR}/${_binary}_installed") + + if(${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/${_binary}_installed OR NOT ${${_binary}_installed} EQUAL 0) + if(DEBUG_PREBUILT) + message(STATUS "cd ${CMAKE_SOURCE_DIR} && ${AUTOBUILD_EXECUTABLE} install + --install-dir=${AUTOBUILD_INSTALL_DIR} + ${_binary} ") + endif(DEBUG_PREBUILT) + execute_process(COMMAND "${AUTOBUILD_EXECUTABLE}" + install + --install-dir=${AUTOBUILD_INSTALL_DIR} + ${_binary} + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + RESULT_VARIABLE ${_binary}_installed + ) + file(WRITE ${PREBUILD_TRACKING_DIR}/${_binary}_installed "${${_binary}_installed}") + endif(${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/${_binary}_installed OR NOT ${${_binary}_installed} EQUAL 0) + + if(NOT ${_binary}_installed EQUAL 0) + message(FATAL_ERROR + "Failed to download or unpack prebuilt '${_binary}'." + " Process returned ${${_binary}_installed}.") + endif (NOT ${_binary}_installed EQUAL 0) + endif (NOT USESYSTEMLIBS_${_binary}) endmacro (use_prebuilt_binary _binary) endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/cmake/PulseAudio.cmake b/indra/cmake/PulseAudio.cmake index 62e2bf9b2a..360a971058 100644 --- a/indra/cmake/PulseAudio.cmake +++ b/indra/cmake/PulseAudio.cmake @@ -1,7 +1,7 @@ # -*- cmake -*- include(Prebuilt) -set(PULSEAUDIO ON CACHE BOOL "Build with PulseAudio support, if available.") +set(PULSEAUDIO OFF CACHE BOOL "Build with PulseAudio support, if available.") if (PULSEAUDIO) if (STANDALONE) @@ -13,9 +13,8 @@ if (PULSEAUDIO) use_prebuilt_binary(pulseaudio) set(PULSEAUDIO_FOUND ON FORCE BOOL) set(PULSEAUDIO_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) + ${LIBS_PREBUILT_DIR}/include + ) # We don't need to explicitly link against pulseaudio itself, because # the viewer probes for the system's copy at runtime. set(PULSEAUDIO_LIBRARIES diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake index 83a0690c64..9f24361f4b 100644 --- a/indra/cmake/Python.cmake +++ b/indra/cmake/Python.cmake @@ -5,25 +5,33 @@ set(PYTHONINTERP_FOUND) if (WINDOWS) # On Windows, explicitly avoid Cygwin Python. - find_program(PYTHON_EXECUTABLE - NAMES python25.exe python23.exe python.exe - NO_DEFAULT_PATH # added so that cmake does not find cygwin python - PATHS - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath] - ) - + if (DEFINED ENV{VIRTUAL_ENV}) + find_program(PYTHON_EXECUTABLE + NAMES python.exe + PATHS + "$ENV{VIRTUAL_ENV}\\scripts" + NO_DEFAULT_PATH + ) + else() + find_program(PYTHON_EXECUTABLE + NAMES python25.exe python23.exe python.exe + NO_DEFAULT_PATH # added so that cmake does not find cygwin python + PATHS + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath] + ) + endif() -elseif (EXISTS /etc/arch-release) - # On Archlinux, use Python 2 +elseif (EXISTS /usr/bin/python2) + # if this is there, use it find_program(PYTHON_EXECUTABLE python2 PATHS /usr/bin) diff --git a/indra/cmake/Qt4.cmake b/indra/cmake/Qt4.cmake deleted file mode 100644 index 37d2799a21..0000000000 --- a/indra/cmake/Qt4.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# -*- cmake -*- -include(Prebuilt) - -if (STANDALONE) - set(Qt4_FIND_REQUIRED ON) - - include(FindQt4) - - find_package(Qt4 4.7.0 COMPONENTS QtCore QtGui QtNetwork QtOpenGL QtWebKit REQUIRED) - include(${QT_USE_FILE}) - add_definitions(${QT_DEFINITIONS}) -endif (STANDALONE) diff --git a/indra/cmake/QuickTimePlugin.cmake b/indra/cmake/QuickTimePlugin.cmake deleted file mode 100644 index 171213d424..0000000000 --- a/indra/cmake/QuickTimePlugin.cmake +++ /dev/null @@ -1,58 +0,0 @@ -# -*- cmake -*- - -if(INSTALL_PROPRIETARY) - include(Prebuilt) - use_prebuilt_binary(quicktime) -endif(INSTALL_PROPRIETARY) - -if (DARWIN) - include(CMakeFindFrameworks) - find_library(QUICKTIME_LIBRARY QuickTime) -elseif (WINDOWS AND WORD_SIZE EQUAL 32) - SET(program_files "ProgramFiles(x86)") - SET(program_files $ENV{${program_files}}) - if(NOT program_files) - SET(program_files $ENV{ProgramW6432}) - endif(NOT program_files) - if(NOT program_files) - SET(program_files $ENV{ProgramFiles}) - endif(NOT program_files) - - set(QUICKTIME_SDK_DIR "${program_files}/QuickTime SDK" - CACHE PATH "Location of the QuickTime SDK.") - - find_library(DEBUG_QUICKTIME_LIBRARY qtmlclient - PATHS - ${LIBS_PREBUILT_DIR}/lib/debug - ${LIBS_PREBUILT_LEGACY_DIR}/lib/debug - "${QUICKTIME_SDK_DIR}\\libraries" - ) - - find_library(RELEASE_QUICKTIME_LIBRARY qtmlclient - PATHS - ${LIBS_PREBUILT_DIR}/lib/release - ${LIBS_PREBUILT_LEGACY_DIR}/lib/release - "${QUICKTIME_SDK_DIR}\\libraries" - ) - - if (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY) - set(QUICKTIME_LIBRARY - optimized ${RELEASE_QUICKTIME_LIBRARY} - debug ${DEBUG_QUICKTIME_LIBRARY} - ) - - endif (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY) - - include_directories( - ${LIBS_PREBUILT_DIR}/include/quicktime - ${LIBS_PREBUILT_LEGACY_DIR}/include/quicktime - "${QUICKTIME_SDK_DIR}\\CIncludes" - ) -endif (DARWIN) - -mark_as_advanced(QUICKTIME_LIBRARY) - -if (QUICKTIME_LIBRARY) - set(QUICKTIME ON CACHE BOOL "Build with QuickTime streaming media support.") -endif (QUICKTIME_LIBRARY) - diff --git a/indra/cmake/RunBuildTest.cmake b/indra/cmake/RunBuildTest.cmake deleted file mode 100644 index dc6c942b78..0000000000 --- a/indra/cmake/RunBuildTest.cmake +++ /dev/null @@ -1,20 +0,0 @@ -#This cmake script is meant to be run as a build time custom command. -#The script is run using cmake w/ the -P option. -# parameters are passed to this scripts execution with the -D option. -# A full command line would look like this: -# cmake -D LD_LIBRARY_PATH=~/checkout/libraries -D TEST_CMD=./llunit_test -D ARGS=--touch=llunit_test_ok.txt -P RunBuildTest.cmake - -# Parameters: -# LD_LIBRARY_PATH: string, What to set the LD_LIBRARY_PATH env var. -# TEST_CMD: string list, command to run the unit test with, followed by its args. -set(ENV{LD_LIBRARY_PATH} ${LD_LIBRARY_PATH}) -#message("Running: ${TEST_CMD}") -execute_process( - COMMAND ${TEST_CMD} - RESULT_VARIABLE RES - ) - -if(NOT ${RES} STREQUAL 0) - message(STATUS "Failure running: ${TEST_CMD}") - message(FATAL_ERROR "Error: ${RES}") -endif(NOT ${RES} STREQUAL 0) \ No newline at end of file diff --git a/indra/cmake/TemplateCheck.cmake b/indra/cmake/TemplateCheck.cmake index 3b73dc82df..2fada2eda9 100644 --- a/indra/cmake/TemplateCheck.cmake +++ b/indra/cmake/TemplateCheck.cmake @@ -8,7 +8,7 @@ macro (check_message_template _target) PRE_LINK COMMAND ${PYTHON_EXECUTABLE} ARGS ${SCRIPTS_DIR}/template_verifier.py - --mode=development --cache_master - COMMENT "Verifying message template" + --mode=development --cache_master --master_url=${TEMPLATE_VERIFIER_MASTER_URL} ${TEMPLATE_VERIFIER_OPTIONS} + COMMENT "Verifying message template - See http://wiki.secondlife.com/wiki/Template_verifier.py" ) endmacro (check_message_template) diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake index 697ac4288c..efdf80b3c8 100644 --- a/indra/cmake/UI.cmake +++ b/indra/cmake/UI.cmake @@ -1,10 +1,9 @@ # -*- cmake -*- -include(Prebuilt) +include(FreeType) -if (STANDALONE) +if (LINUX) include(FindPkgConfig) - - if (LINUX) + set(PKGCONFIG_PACKAGES atk cairo @@ -20,8 +19,8 @@ if (STANDALONE) pangox pangoxft sdl + x11 ) - endif (LINUX) foreach(pkg ${PKGCONFIG_PACKAGES}) pkg_check_modules(${pkg} REQUIRED ${pkg}) @@ -30,46 +29,6 @@ if (STANDALONE) list(APPEND UI_LIBRARIES ${${pkg}_LIBRARIES}) add_definitions(${${pkg}_CFLAGS_OTHERS}) endforeach(pkg) -else (STANDALONE) - if (LINUX) - use_prebuilt_binary(glib) # gtk-etc needs glib - use_prebuilt_binary(gtk-atk-pango-glib) - set(UI_LIBRARIES - atk-1.0 - X11 - gdk-x11-2.0 - gdk_pixbuf-2.0 - Xinerama - glib-2.0 - gio-2.0 - gmodule-2.0 - gobject-2.0 - gthread-2.0 - gtk-x11-2.0 - pango-1.0 - pangoft2-1.0 - pangox-1.0 - pangoxft-1.0 - pangocairo-1.0 - ) - endif (LINUX) - - include_directories ( - ${LIBS_PREBUILT_DIR}/packages/include - ${LIBS_PREBUILT_DIR}/packages/include/cairo - ${LIBS_PREBUILT_DIR}/packages/include/pixman-1 - ${LIBS_PREBUILT_LEGACY_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include/cairo - ${LIBS_PREBUILT_LEGACY_DIR}/include/pixman-1 - ) - foreach(include ${${LL_ARCH}_INCLUDES}) - include_directories( - ${LIBS_PREBUILT_DIR}/include/${include} - ${LIBS_PREBUILT_LEGACY_DIR}/include/${include} - ) - endforeach(include) -endif (STANDALONE) -if (LINUX) add_definitions(-DLL_GTK=1 -DLL_X11=1) endif (LINUX) diff --git a/indra/cmake/URIPARSER.cmake b/indra/cmake/URIPARSER.cmake new file mode 100644 index 0000000000..47c3ccd376 --- /dev/null +++ b/indra/cmake/URIPARSER.cmake @@ -0,0 +1,20 @@ +# -*- cmake -*- + +set(URIPARSER_FIND_QUIETLY ON) +set(URIPARSER_FIND_REQUIRED ON) + +include(Prebuilt) + +if (USESYSTEMLIBS) + include(FindURIPARSER) +else (USESYSTEMLIBS) + use_prebuilt_binary(uriparser) + if (WINDOWS) + set(URIPARSER_LIBRARY + debug uriparserd + optimized uriparser) + elseif (DARWIN OR LINUX) + set(URIPARSER_LIBRARY uriparser) + endif (WINDOWS) + set(URIPARSER_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/uriparser) +endif (USESYSTEMLIBS) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 5b9890d5bb..3b6ec6598c 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -9,9 +9,7 @@ # LINUX - Linux # WINDOWS - Windows - # Relative and absolute paths to subtrees. - if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") @@ -19,60 +17,153 @@ if(NOT DEFINED COMMON_CMAKE_DIR) set(COMMON_CMAKE_DIR "${CMAKE_SOURCE_DIR}/cmake") endif(NOT DEFINED COMMON_CMAKE_DIR) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# https://blog.kitware.com/upcoming-in-cmake-2-8-12-osx-rpath-support/ +set(CMAKE_MACOSX_RPATH ON) +set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH OFF) + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +option(GEN_IS_MULTI_CONFIG "" ${_isMultiConfig}) +mark_as_advanced(GEN_IS_MULTI_CONFIG) + set(LIBS_CLOSED_PREFIX) set(LIBS_OPEN_PREFIX) set(SCRIPTS_PREFIX ../scripts) set(VIEWER_PREFIX) +set(INTEGRATION_TESTS_PREFIX) -set(LIBS_CLOSED_DIR ${CMAKE_SOURCE_DIR}/${LIBS_CLOSED_PREFIX}) -set(LIBS_OPEN_DIR ${CMAKE_SOURCE_DIR}/${LIBS_OPEN_PREFIX}) -set(SCRIPTS_DIR ${CMAKE_SOURCE_DIR}/${SCRIPTS_PREFIX}) -set(VIEWER_DIR ${CMAKE_SOURCE_DIR}/${VIEWER_PREFIX}) +option(LL_TESTS "Build and run unit and integration tests (disable for build timing runs to reduce variation" OFF) +option(BUILD_TESTING "Build test suite" OFF) +option(UNATTENDED "Disable use of uneeded tooling for automated builds" OFF) + +# Compiler and toolchain options +option(USESYSTEMLIBS "Use libraries from your system rather than Linden-supplied prebuilt libraries." OFF) +option(STANDALONE "Use libraries from your system rather than Linden-supplied prebuilt libraries." OFF) +if (USESYSTEMLIBS) + set(STANDALONE ON) +elseif (STANDALONE) + set(USESYSTEMLIBS ON) +endif (USESYSTEMLIBS) +option(INCREMENTAL_LINK "Use incremental linking on win32 builds (enable for faster links on some machines)" OFF) +option(USE_PRECOMPILED_HEADERS "Enable use of precompiled header directives where supported." ON) +option(USE_LTO "Enable global and interprocedural optimizations" OFF) + +# Configure crash reporting +option(USE_CRASHPAD "Build support for crashpad reporting engine" OFF) +if (DEFINED ENV{VIEWER_USE_CRASHPAD}) + set(USE_CRASHPAD $ENV{VIEWER_USE_CRASHPAD}) +endif() + +if (DEFINED ENV{VIEWER_CRASHPAD_URL}) + set(CRASHPAD_URL $ENV{VIEWER_CRASHPAD_URL} CACHE STRING "Viewer Channel Base Name") +else() + set(CRASHPAD_URL "" CACHE STRING "Crashpad endpoint url") +endif() + +set(VIEWER_SYMBOL_FILE "" CACHE STRING "Name of tarball into which to place symbol files") + +# Media Plugins +option(ENABLE_MEDIA_PLUGINS "Turn off building media plugins if they are imported by third-party library mechanism" ON) +option(LIBVLCPLUGIN "Turn off building support for libvlc plugin" ON) +if (${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(LIBVLCPLUGIN OFF) +endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + +# Mallocs set(DISABLE_TCMALLOC OFF CACHE BOOL "Disable linkage of TCMalloc. (64bit builds automatically disable TCMalloc)") -set(LL_TESTS OFF CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation)") set(DISABLE_FATAL_WARNINGS TRUE CACHE BOOL "Set this to FALSE to enable fatal warnings.") -if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") +# Audio Engines +option(USE_FMODSTUDIO "Build with support for the FMOD Studio audio engine" OFF) + +# Proprietary Library Features +option(USE_NVAPI "Use nvapi driver interface library" OFF) + + +if(LIBS_CLOSED_DIR) + file(TO_CMAKE_PATH "${LIBS_CLOSED_DIR}" LIBS_CLOSED_DIR) +else(LIBS_CLOSED_DIR) + set(LIBS_CLOSED_DIR ${CMAKE_SOURCE_DIR}/${LIBS_CLOSED_PREFIX}) +endif(LIBS_CLOSED_DIR) +if(LIBS_COMMON_DIR) + file(TO_CMAKE_PATH "${LIBS_COMMON_DIR}" LIBS_COMMON_DIR) +else(LIBS_COMMON_DIR) + set(LIBS_COMMON_DIR ${CMAKE_SOURCE_DIR}/${LIBS_OPEN_PREFIX}) +endif(LIBS_COMMON_DIR) +set(LIBS_OPEN_DIR ${LIBS_COMMON_DIR}) + +set(SCRIPTS_DIR ${CMAKE_SOURCE_DIR}/${SCRIPTS_PREFIX}) +set(VIEWER_DIR ${CMAKE_SOURCE_DIR}/${VIEWER_PREFIX}) + +set(AUTOBUILD_INSTALL_DIR ${CMAKE_BINARY_DIR}/packages) + +set(LIBS_PREBUILT_DIR ${AUTOBUILD_INSTALL_DIR} CACHE PATH + "Location of prebuilt libraries.") + +if (EXISTS ${CMAKE_SOURCE_DIR}/Server.cmake) + # We use this as a marker that you can try to use the proprietary libraries. + set(INSTALL_PROPRIETARY ON CACHE BOOL "Install proprietary binaries") +endif (EXISTS ${CMAKE_SOURCE_DIR}/Server.cmake) +set(TEMPLATE_VERIFIER_OPTIONS "" CACHE STRING "Options for scripts/template_verifier.py") +set(TEMPLATE_VERIFIER_MASTER_URL "https://git.alchemyviewer.org/alchemy/master-message-template/raw/master/message_template.msg" CACHE STRING "Location of the master message template") + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING + "Build type. One of: Debug Release RelWithDebInfo" FORCE) +endif (NOT CMAKE_BUILD_TYPE) + +# If someone has specified an address size, use that to determine the +# architecture. Otherwise, let the architecture specify the address size. +if (ADDRESS_SIZE EQUAL 32) + #message(STATUS "ADDRESS_SIZE is 32") + set(ARCH i686) +elseif (ADDRESS_SIZE EQUAL 64) + #message(STATUS "ADDRESS_SIZE is 64") + set(ARCH x86_64) +else (ADDRESS_SIZE EQUAL 32) + #message(STATUS "ADDRESS_SIZE is UNDEFINED") + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "Size of void pointer is detected as 8; ARCH is 64-bit") + set(ARCH x86_64) + set(ADDRESS_SIZE 64) + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + message(STATUS "Size of void pointer is detected as 4; ARCH is 32-bit") + set(ADDRESS_SIZE 32) + set(ARCH i686) + else() + message(FATAL_ERROR "Unkown Architecture!") + endif() +endif (ADDRESS_SIZE EQUAL 32) + +if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") set(WINDOWS ON BOOL FORCE) - if (WORD_SIZE EQUAL 32) - set(ARCH i686) + if (ADDRESS_SIZE EQUAL 64) + set(LL_ARCH ${ARCH}_win64) + set(LL_ARCH_DIR ${ARCH}-win64) + elseif (ADDRESS_SIZE EQUAL 32) set(LL_ARCH ${ARCH}_win32) set(LL_ARCH_DIR ${ARCH}-win32) - elseif (WORD_SIZE EQUAL 64) - set(ARCH x86_64) - set(LL_ARCH ${ARCH}_win) - set(LL_ARCH_DIR ${ARCH}-win) - endif (WORD_SIZE EQUAL 32) -endif (${CMAKE_SYSTEM_NAME} MATCHES "Windows") + else() + message(FATAL_ERROR "Unkown Architecture!") + endif () +endif (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set(LINUX ON BOOl FORCE) - - # If someone has specified a word size, use that to determine the - # architecture. Otherwise, let the architecture specify the word size. - if (WORD_SIZE EQUAL 32) - set(ARCH i686) - elseif (WORD_SIZE EQUAL 64) - set(ARCH x86_64) - else (WORD_SIZE EQUAL 32) - if(CMAKE_SIZEOF_VOID_P MATCHES 4) - set(ARCH i686) - set(WORD_SIZE 32) - else(CMAKE_SIZEOF_VOID_P MATCHES 4) - set(ARCH x86_64) - set(WORD_SIZE 64) - endif(CMAKE_SIZEOF_VOID_P MATCHES 4) - endif (WORD_SIZE EQUAL 32) + set(LINUX ON BOOL FORCE) - if (NOT STANDALONE AND MULTIARCH_HACK) - if (WORD_SIZE EQUAL 32) + if (ADDRESS_SIZE EQUAL 32) set(DEB_ARCHITECTURE i386) set(FIND_LIBRARY_USE_LIB64_PATHS OFF) set(CMAKE_SYSTEM_LIBRARY_PATH /usr/lib32 ${CMAKE_SYSTEM_LIBRARY_PATH}) - else (WORD_SIZE EQUAL 32) + else (ADDRESS_SIZE EQUAL 32) set(DEB_ARCHITECTURE amd64) set(FIND_LIBRARY_USE_LIB64_PATHS ON) - endif (WORD_SIZE EQUAL 32) + endif (ADDRESS_SIZE EQUAL 32) execute_process(COMMAND dpkg-architecture -a${DEB_ARCHITECTURE} -qDEB_HOST_MULTIARCH RESULT_VARIABLE DPKG_RESULT @@ -85,103 +176,107 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") endif (DPKG_RESULT EQUAL 0) include(ConfigurePkgConfig) - endif (NOT STANDALONE AND MULTIARCH_HACK) set(LL_ARCH ${ARCH}_linux) set(LL_ARCH_DIR ${ARCH}-linux) endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(DARWIN 1) - - execute_process( - COMMAND sh -c "xcodebuild -version | grep Xcode | cut -d ' ' -f2 | cut -d'.' -f1-2" - OUTPUT_VARIABLE XCODE_VERSION ) - string(REGEX REPLACE "(\r?\n)+$" "" XCODE_VERSION "${XCODE_VERSION}") - -# # To support a different SDK update these Xcode settings: -# if (XCODE_VERSION GREATER 4.9) # (Which would be 5.0+) -# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8) -# set(CMAKE_OSX_SYSROOT macosx10.9) -# else (XCODE_VERION GREATER 4.9) -# if (XCODE_VERSION GREATER 4.5) -# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) -# set(CMAKE_OSX_SYSROOT macosx10.8) -# else (XCODE_VERSION GREATER 4.5) -# if (XCODE_VERSION GREATER 4.2) -# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) -# set(CMAKE_OSX_SYSROOT macosx10.7) -# else (XCODE_VERSION GREATER 4.2) -# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) -# set(CMAKE_OSX_SYSROOT macosx10.7) -# endif (XCODE_VERSION GREATER 4.2) -# endif (XCODE_VERSION GREATER 4.5) -# endif (XCODE_VERSION GREATER 4.9) - - # Hardcode SDK we build against until we can test and allow newer ones - # as autodetected in the code above - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) - set(CMAKE_OSX_SYSROOT macosx10.6) - - # Support for Unix Makefiles generator - if (CMAKE_GENERATOR STREQUAL "Unix Makefiles") - execute_process(COMMAND xcodebuild -version -sdk "${CMAKE_OSX_SYSROOT}" Path | head -n 1 OUTPUT_VARIABLE CMAKE_OSX_SYSROOT) - string(REGEX REPLACE "(\r?\n)+$" "" CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT}") - endif (CMAKE_GENERATOR STREQUAL "Unix Makefiles") - - # LLVM-GCC has been removed in Xcode5 - if (XCODE_VERSION GREATER 4.9) - set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0") - else (XCODE_VERSION GREATER 4.9) - set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42") - endif (XCODE_VERSION GREATER 4.9) - - set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym) - - message(STATUS "Xcode version: ${XCODE_VERSION}") - message(STATUS "OSX sysroot: ${CMAKE_OSX_SYSROOT}") - message(STATUS "OSX deployment target: ${CMAKE_OSX_DEPLOYMENT_TARGET}") - - # Build only for i386 by default, system default on MacOSX 10.6 is x86_64 - set(CMAKE_OSX_ARCHITECTURES i386) - set(ARCH i386) - set(WORD_SIZE 32) + set(DARWIN ON BOOL FORCE) + + # Architecture + set(CMAKE_OSX_SYSROOT macosx10.14) + set(CMAKE_OSX_ARCHITECTURES "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS "x86_64") + + # Build Options + set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0") + set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=Debug] "dwarf") + set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=Release] "dwarf-with-dsym") + + # Deployment + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.13) + + # Linking + set(CMAKE_XCODE_ATTRIBUTE_DEAD_CODE_STRIPPING YES) + + # Apple Clang - Code Gen + set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Release] YES) + set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS sse4.1) + set(CMAKE_XCODE_ATTRIBUTE_GCC_STRICT_ALIASING NO) + set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL[variant=Debug] 0) + set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL[variant=Release] 3) + set(CMAKE_XCODE_ATTRIBUTE_GCC_FAST_MATH NO) + + # Apple Clang - Custom Compiler Flags + set(CMAKE_XCODE_ATTRIBUTE_WARNING_CFLAGS "-Wall -Wextra -Wno-reorder -Wno-sign-compare -Wno-ignored-qualifiers -Wno-unused-local-typedef -Wno-unused-parameter") + + # Apple Clang - Language - C++ + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD c++14) + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + + # Apple Clang - Warning Policies + set(CMAKE_XCODE_ATTRIBUTE_GCC_TREAT_WARNINGS_AS_ERRORS YES) set(LL_ARCH ${ARCH}_darwin) set(LL_ARCH_DIR universal-darwin) endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -set(LIBS_PREBUILT_DIR ${CMAKE_BINARY_DIR}/packages CACHE PATH - "Location of prebuilt libraries.") - -set(LIBS_PREBUILT_LEGACY_DIR ${CMAKE_BINARY_DIR}/packages/libraries/${LL_ARCH_DIR} CACHE PATH - "Legacy location of prebuilt libraries.") - -if (WINDOWS AND WORD_SIZE EQUAL 32) - set(PREBUILT_TYPE windows) -elseif (WINDOWS AND WORD_SIZE EQUAL 64) - set(PREBUILT_TYPE windows64) -elseif(DARWIN) - set(PREBUILT_TYPE darwin) -elseif(LINUX AND WORD_SIZE EQUAL 32) - set(PREBUILT_TYPE linux) -elseif(LINUX AND WORD_SIZE EQUAL 64) - set(PREBUILT_TYPE linux64) -endif(WINDOWS AND WORD_SIZE EQUAL 32) +# Platform specific +if (WINDOWS) + option(LLWINDOW_SDL2 "Use SDL2 for window and input handling. Windows only" OFF) +endif() # Default deploy grid set(GRID agni CACHE STRING "Target Grid") -set(VIEWER_CHANNEL "Singularity" CACHE STRING "Viewer Channel Name") -set(VIEWER_LOGIN_CHANNEL "${VIEWER_CHANNEL}" CACHE STRING "Fake login channel for A/B Testing") -set(VIEWER_BRANDING_ID "singularity" CACHE STRING "Viewer branding id (currently secondlife|snowglobe)") +if (DEFINED ENV{VIEWER_CHANNEL_BASE}) + set(VIEWER_CHANNEL_BASE $ENV{VIEWER_CHANNEL_BASE} CACHE STRING "Viewer Channel Base Name" FORCE) +else() + set(VIEWER_CHANNEL_BASE "Singularity" CACHE STRING "Viewer Channel Base Name") +endif() + +if (DEFINED ENV{VIEWER_CHANNEL_TYPE}) + set(VIEWER_CHANNEL_TYPE $ENV{VIEWER_CHANNEL_TYPE} CACHE STRING "Viewer Channel Type Name" FORCE) +else() + set(VIEWER_CHANNEL_TYPE "Test" CACHE STRING "Viewer Channel Type Name") +endif() + +if (DEFINED ENV{VIEWER_CHANNEL_CODENAME}) + set(VIEWER_CHANNEL_CODENAME $ENV{VIEWER_CHANNEL_CODENAME} CACHE STRING "Viewer Channel Code Name for Project type" FORCE) +else() + set(VIEWER_CHANNEL_CODENAME "Default" CACHE STRING "Viewer Channel Code Name for Project type") +endif() + +if("${VIEWER_CHANNEL_TYPE}" STREQUAL "Project") + set(VIEWER_CHANNEL "${VIEWER_CHANNEL_BASE} ${VIEWER_CHANNEL_TYPE} ${VIEWER_CHANNEL_CODENAME}") +else() + set(VIEWER_CHANNEL "${VIEWER_CHANNEL_BASE} ${VIEWER_CHANNEL_TYPE}") +endif() + +string(TOLOWER "${VIEWER_CHANNEL_BASE}" VIEWER_BRANDING_ID) +string(REPLACE " " "-" VIEWER_BRANDING_ID ${VIEWER_BRANDING_ID}) +set(VIEWER_BINARY_NAME "${VIEWER_BRANDING_ID}-bin" CACHE STRING + "The name of the viewer executable to create.") + +string(REPLACE " " "" VIEWER_CHANNEL_ONEWORD ${VIEWER_CHANNEL}) +set(VIEWER_CHANNEL_NOSPACE ${VIEWER_CHANNEL_ONEWORD} CACHE STRING "Prefix used for resulting artifacts.") -# *TODO: break out proper Branding-secondlife.cmake, Branding-snowglobe.cmake, etc -string(REGEX REPLACE " +" "" VIEWER_CHANNEL_ONE_WORD "${VIEWER_CHANNEL}") -set(VIEWER_BRANDING_NAME "${VIEWER_CHANNEL_ONE_WORD}") -set(VIEWER_BRANDING_NAME_CAMELCASE "${VIEWER_CHANNEL_ONE_WORD}") +option(VIEWER_CHANNEL_GRK "Greek character(s) to represent the viewer channel for support purposes, override only for special branches" "") +if (NOT VIEWER_CHANNEL_GRK) + if (VIEWER_CHANNEL_TYPE MATCHES "Test") + set(VIEWER_CHANNEL_GRK "\\u03C4") # "τ" + elseif (VIEWER_CHANNEL_TYPE MATCHES "Alpha") + set(VIEWER_CHANNEL_GRK "\\u03B1") # "α" + elseif (VIEWER_CHANNEL_TYPE MATCHES "Beta") + set(VIEWER_CHANNEL_GRK "\\u03B2") # "β" + else() + set(VIEWER_CHANNEL_GRK "") + endif () +endif (NOT VIEWER_CHANNEL_GRK) -set(STANDALONE OFF CACHE BOOL "Do not use Linden-supplied prebuilt libraries.") +option(ENABLE_SIGNING "Enable signing the viewer" OFF) +set(SIGNING_IDENTITY "" CACHE STRING "Specifies the signing identity to use, if necessary.") source_group("CMake Rules" FILES CMakeLists.txt) diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake index 275b840a05..36ee514e91 100644 --- a/indra/cmake/ViewerMiscLibs.cmake +++ b/indra/cmake/ViewerMiscLibs.cmake @@ -2,14 +2,7 @@ include(Prebuilt) if (NOT STANDALONE) - use_prebuilt_binary(vivox) - if(LINUX) - use_prebuilt_binary(libuuid) - if (${ARCH} STREQUAL "x86_64") - use_prebuilt_binary(32bitcompatibilitylibs) - endif (${ARCH} STREQUAL "x86_64") - use_prebuilt_binary(fontconfig) - endif(LINUX) + use_prebuilt_binary(slvoice) else (NOT STANDALONE) # Download there even when using standalone. set(STANDALONE OFF) @@ -19,3 +12,10 @@ else (NOT STANDALONE) endif(LINUX AND ${ARCH} STREQUAL "x86_64") set(STANDALONE ON) endif(NOT STANDALONE) + +if(LINUX) + include(FindPkgConfig) + pkg_check_modules(FONTCONFIG REQUIRED fontconfig) +endif(LINUX) + +use_prebuilt_binary(fonts) diff --git a/indra/cmake/WebKitLibPlugin.cmake b/indra/cmake/WebKitLibPlugin.cmake deleted file mode 100644 index 8551aa1634..0000000000 --- a/indra/cmake/WebKitLibPlugin.cmake +++ /dev/null @@ -1,64 +0,0 @@ -# -*- cmake -*- -include(Linking) -include(Prebuilt) -include(LLQtWebkit) -include(Qt4) - -if (STANDALONE) - set(WEBKITLIBPLUGIN OFF CACHE BOOL - "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.") -else (STANDALONE) - use_prebuilt_binary(llqtwebkit) - set(WEBKITLIBPLUGIN ON CACHE BOOL - "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.") -endif (STANDALONE) - -if (WINDOWS) - set(WEBKIT_PLUGIN_LIBRARIES - debug llqtwebkitd - debug QtWebKitd4 - debug QtOpenGLd4 - debug QtNetworkd4 - debug QtGuid4 - debug QtCored4 - debug qtmaind - optimized llqtwebkit - optimized QtWebKit4 - optimized QtOpenGL4 - optimized QtNetwork4 - optimized QtGui4 - optimized QtCore4 - optimized qtmain - ) -elseif (DARWIN) - set(WEBKIT_PLUGIN_LIBRARIES - debug libllqtwebkit.dylib - optimized libllqtwebkit.dylib - ) -elseif (LINUX) - if (STANDALONE) - set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY} ${QT_LIBRARIES} ${QT_PLUGIN_LIBRARIES}) - else (STANDALONE) - set(WEBKIT_PLUGIN_LIBRARIES - llqtwebkit - QtWebKit - QtOpenGL - QtNetwork - QtGui - QtCore - crypto - ssl -# qgif -# qjpeg - jpeg - fontconfig - X11 - Xrender - Xext - GL - ) - if (CMAKE_SIZEOF_VOID_P EQUAL 4) # Singu TODO: update webkit - set(WEBKIT_PLUGIN_LIBRARIES ${WEBKIT_PLUGIN_LIBRARIES} jscore) - endif (CMAKE_SIZEOF_VOID_P EQUAL 4) - endif (STANDALONE) -endif (WINDOWS) diff --git a/indra/cmake/WinManifest.cmake b/indra/cmake/WinManifest.cmake new file mode 100644 index 0000000000..39f4def75d --- /dev/null +++ b/indra/cmake/WinManifest.cmake @@ -0,0 +1,17 @@ +# - Embeds a specific manifest file in a Windows binary +# Defines the following: +# EMBED_MANIFEST - embed manifest in a windows binary with mt +# Parameters - _target is the target file, type - 1 for EXE, 2 for DLL + + MACRO(EMBED_MANIFEST _target type) + ADD_CUSTOM_COMMAND( + TARGET ${_target} + POST_BUILD + COMMAND "mt.exe" + ARGS + -manifest \"${CMAKE_SOURCE_DIR}\\tools\\manifests\\compatibility.manifest\" + -inputresource:\"$\"\;\#${type} + -outputresource:\"$\"\;\#${type} + COMMENT "Adding compatibility manifest to ${_target}" + ) + ENDMACRO(EMBED_MANIFEST _target type) diff --git a/indra/cmake/XmlRpcEpi.cmake b/indra/cmake/XmlRpcEpi.cmake index 2c93fd20c4..5d59c90dbc 100644 --- a/indra/cmake/XmlRpcEpi.cmake +++ b/indra/cmake/XmlRpcEpi.cmake @@ -8,9 +8,13 @@ if (STANDALONE) include(FindXmlRpcEpi) else (STANDALONE) use_prebuilt_binary(xmlrpc-epi) - set(XMLRPCEPI_LIBRARIES xmlrpc-epi) - set(XMLRPCEPI_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include - ${LIBS_PREBUILT_LEGACY_DIR}/include - ) + if (WINDOWS) + set(XMLRPCEPI_LIBRARIES + debug xmlrpc-epid + optimized xmlrpc-epi + ) + else (WINDOWS) + set(XMLRPCEPI_LIBRARIES xmlrpc-epi) + endif (WINDOWS) + set(XMLRPCEPI_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) endif (STANDALONE) diff --git a/indra/cmake/ZLIB.cmake b/indra/cmake/ZLIB.cmake index 3384c55ee5..5b38fc1af4 100644 --- a/indra/cmake/ZLIB.cmake +++ b/indra/cmake/ZLIB.cmake @@ -13,13 +13,25 @@ else (STANDALONE) set(ZLIB_LIBRARIES debug zlibd optimized zlib) + elseif (LINUX) + # + # When we have updated static libraries in competition with older + # shared libraries and we want the former to win, we need to do some + # extra work. The *_PRELOAD_ARCHIVES settings are invoked early + # and will pull in the entire archive to the binary giving it + # priority in symbol resolution. Beware of cmake moving the + # achive load itself to another place on the link command line. If + # that happens, you can try something like -Wl,-lz here to hide + # the archive. Also be aware that the linker will not tolerate a + # second whole-archive load of the archive. See viewer's + # CMakeLists.txt for more information. + # + set(ZLIB_PRELOAD_ARCHIVES -Wl,--whole-archive z -Wl,--no-whole-archive) + set(ZLIB_LIBRARIES z) else (WINDOWS) set(ZLIB_LIBRARIES z) endif (WINDOWS) if (WINDOWS OR LINUX) - set(ZLIB_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include/zlib - ${LIBS_PREBUILT_LEGACY_DIR}/include/zlib - ) + set(ZLIB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/zlib) endif (WINDOWS OR LINUX) endif (STANDALONE) diff --git a/indra/cmake/cmake_dummy.cpp b/indra/cmake/cmake_dummy.cpp index 25191e2a18..ae4475a73e 100644 --- a/indra/cmake/cmake_dummy.cpp +++ b/indra/cmake/cmake_dummy.cpp @@ -1,30 +1,24 @@ /** * @file cmake_dummy.cpp * - * $LicenseInfo:firstyear=2008&license=viewergpl$ - * - * Copyright (c) 2008-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * 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. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py new file mode 100644 index 0000000000..9c7d2f5633 --- /dev/null +++ b/indra/cmake/run_build_test.py @@ -0,0 +1,340 @@ +#!/usr/bin/env python2 +"""\ +@file run_build_test.py +@author Nat Goodspeed +@date 2009-09-03 +@brief Helper script to allow CMake to run some command after setting + environment variables. + +CMake has commands to run an external program. But remember that each CMake +command must be backed by multiple build-system implementations. Unfortunately +it seems CMake can't promise that every target build system can set specified +environment variables before running the external program of interest. + +This helper script is a workaround. It simply sets the requested environment +variables and then executes the program specified on the rest of its command +line. + +Example: + +python run_build_test.py -DFOO=bar myprog somearg otherarg + +sets environment variable FOO=bar, then runs: +myprog somearg otherarg + +$LicenseInfo:firstyear=2009&license=viewerlgpl$ +Second Life Viewer Source Code +Copyright (C) 2009-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$ +""" + +import os +import sys +import errno +import HTMLParser +import re +import signal +import subprocess +import logging + +def main(command, arguments=[], libpath=[], vars={}): + """Pass: + command is the command to be executed + + argument is a sequence (e.g. a list) of strings to be passed to command + + libpath is a sequence of directory pathnames. These will be appended to + the platform-specific dynamic library search path environment variable. + + vars is a dict of arbitrary (var, value) pairs to be added to the + environment before running 'command'. + + This function runs the specified command, waits for it to terminate and + returns its return code. This will be negative if the command terminated + with a signal, else it will be the process's specified exit code. + """ + # Handle platform-dependent libpath first. + if sys.platform == "win32": + lpvars = ["PATH"] + elif sys.platform == "darwin": + lpvars = ["LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH"] + elif sys.platform.startswith("linux"): + lpvars = ["LD_LIBRARY_PATH"] + else: + # No idea what the right pathname might be! But only crump if this + # feature is requested. + if libpath: + raise RuntimeError("run_build_test: unknown platform %s" % sys.platform) + lpvars = [] + for var in lpvars: + # Split the existing path. Bear in mind that the variable in question + # might not exist; instead of KeyError, just use an empty string. + dirs = os.environ.get(var, "").split(os.pathsep) + # Append the sequence in libpath + log.info("%s += %r" % (var, libpath)) + for dir in libpath: + # append system paths at the end + if dir in ('/lib', '/usr/lib'): + dirs.append(dir) + # prepend non-system paths + else: + dirs.insert(0, dir) + + # Filter out some useless pieces + clean_dirs = [] + for dir in dirs: + if dir and dir not in ('', '.'): + clean_dirs.append(dir) + + # Now rebuild the path string. This way we use a minimum of separators + # -- and we avoid adding a pointless separator when libpath is empty. + os.environ[var] = os.pathsep.join(clean_dirs) + log.info("%s = %r" % (var, os.environ[var])) + # Now handle arbitrary environment variables. The tricky part is ensuring + # that all the keys and values we try to pass are actually strings. + if vars: + log.info("Setting: %s" % ("\n".join(["%s=%s" % (key, value) for key, value in vars.iteritems()]))) + os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()])) + # Run the child process. + command_list = [command] + command_list.extend(arguments) + log.info("Running: %s" % " ".join(command_list)) + # Make sure we see all relevant output *before* child-process output. + sys.stdout.flush() + try: + return subprocess.call(command_list) + except OSError as err: + # If the caller is trying to execute a test program that doesn't + # exist, we want to produce a reasonable error message rather than a + # traceback. This happens when the build is halted by errors, but + # CMake tries to proceed with testing anyway . However, do + # NOT attempt to handle any error but "doesn't exist." + if err.errno != errno.ENOENT: + raise + # In practice, the pathnames into CMake's build tree are so long as to + # obscure the name of the test program. Just log its basename. + log.warn("No such program %s; check for preceding build errors" % \ + os.path.basename(command[0])) + # What rc should we simulate for missing executable? Windows produces + # 9009. + return 9009 + +# swiped from vita, sigh, seems like a Bad Idea to introduce dependency +def translate_rc(rc): + """ + Accept an rc encoded as for subprocess.Popen.returncode: + None means still running + int >= 0 means terminated voluntarily with specified rc + int < 0 means terminated by signal (-rc) + + Return a string explaining the outcome. In case of a signal, try to + name the corresponding symbol from the 'signal' module. + """ + if rc is None: + return "still running" + + if rc >= 0: + return "terminated with rc %s" % rc + + if sys.platform.startswith("win"): + # From http://stackoverflow.com/questions/20629027/process-finished-with-exit-code-1073741571 + # [-1073741571] is the signed integer representation of Microsoft's + # "stack overflow/stack exhaustion" error code 0xC00000FD. + # Anytime you see strange, large negative exit codes in windows, convert + # them to hex and then look them up in the ntstatus error codes + # http://msdn.microsoft.com/en-us/library/cc704588.aspx + + # Python bends over backwards to give you all the integer precision + # you need, avoiding truncation. But only with 32-bit signed ints is + # -1073741571 equivalent to 0xC00000FD! Explicitly truncate before + # converting. + hexrc = "0x%X" % (rc & 0xFFFFFFFF) + # At this point, we're only trying to format the rc to make it easier + # for a human being to understand. Any exception here -- file doesn't + # exist, HTML parsing error, unrecognized table structure, unknown key + # -- should NOT kill the script! It should only cause us to shrug and + # present our caller with the best information available. + try: + table = get_windows_table() + symbol, desc = table[hexrc] + except Exception, err: + log.error("(%s -- carrying on)" % err) + log.error("terminated with rc %s (%s)" % (rc, hexrc)) + else: + log.info("terminated with rc %s: %s: %s" % (hexrc, symbol, desc)) + + else: + # On Posix, negative rc means the child was terminated by signal -rc. + rc = -rc + for attr in dir(signal): + if attr.startswith('SIG') and getattr(signal, attr) == rc: + strc = attr + break + else: + strc = str(rc) + return "terminated by signal %s" % strc + +class TableParser(HTMLParser.HTMLParser): + """ + This HTMLParser subclass is designed to parse the table we know exists + in windows-rcs.html, hopefully without building in too much knowledge of + the specific way that table is currently formatted. + """ + # regular expression matching any string containing only whitespace + whitespace = re.compile(r'\s*$') + + def __init__(self): + # Because Python 2.x's HTMLParser is an old-style class, we must use + # old-style syntax to forward the __init__() call -- not super(). + HTMLParser.HTMLParser.__init__(self) + # this will collect all the data, eventually + self.table = [] + # Stack whose top (last item) indicates where to append current + # element data. When empty, don't collect data at all. + self.dest = [] + + def handle_starttag(self, tag, attrs): + if tag == "table": + # This is the outermost tag we recognize. Collect nested elements + # within self.table. + self.dest.append(self.table) + elif tag in ("tr", "td"): + # Nested elements whose contents we want to capture as sublists. + # To the list currently designated by the top of the dest stack, + # append a new empty sublist. + self.dest[-1].append([]) + # Now push THAT new, empty list as the new top of the dest stack. + self.dest.append(self.dest[-1][-1]) + elif tag == "p": + # We could handle

...

just like or , but that + # introduces an unnecessary extra level of nesting. Just skip. + pass + else: + # For any tag we don't recognize (notably ), push a new, empty + # list to the top of the dest stack. This new list is NOT + # referenced by anything in self.table; thus, when we pop it, any + # data we've collected inside that list will be discarded. + self.dest.append([]) + + def handle_endtag(self, tag): + # Because we avoid pushing self.dest for

in handle_starttag(), we + # must refrain from popping it for

here. + if tag != "p": + # For everything else, including unrecognized tags, pop the dest + # stack, reverting to outer collection. + self.dest.pop() + + def handle_startendtag(self, tag, attrs): + # The table of interest contains entries of the form: + #

0x00000000
STATUS_SUCCESS

+ # The
is very useful -- we definitely want two different data + # items for "0x00000000" and "STATUS_SUCCESS" -- but we don't need or + # want it to push, then discard, an empty list as it would if we let + # the default HTMLParser.handle_startendtag() call handle_starttag() + # followed by handle_endtag(). Just ignore
or any other + # singleton tag. + pass + + def handle_data(self, data): + # Outside the of interest, self.dest is empty. Do not bother + # collecting data when self.dest is empty. + # HTMLParser calls handle_data() with every chunk of whitespace + # between tags. That would be lovely if our eventual goal was to + # reconstitute the original input stream with its existing formatting, + # but for us, whitespace only clutters the table. Ignore it. + if self.dest and not self.whitespace.match(data): + # Here we're within our
and we have non-whitespace data. + # Append it to the list designated by the top of the dest stack. + self.dest[-1].append(data) + +# cache for get_windows_table() +_windows_table = None + +def get_windows_table(): + global _windows_table + # If we already loaded _windows_table, no need to load it all over again. + if _windows_table: + return _windows_table + + # windows-rcs.html was fetched on 2015-03-24 with the following command: + # curl -o windows-rcs.html \ + # https://msdn.microsoft.com/en-us/library/cc704588.aspx + parser = TableParser() + with open(os.path.join(os.path.dirname(__file__), "windows-rcs.html")) as hf: + # We tried feeding the file data to TableParser in chunks, to avoid + # buffering the entire file as a single string. Unfortunately its + # handle_data() cannot tell the difference between distinct calls + # separated by HTML tags, and distinct calls necessitated by a chunk + # boundary. Sigh! Read in the whole file. At the time this was + # written, it was only 500KB anyway. + parser.feed(hf.read()) + parser.close() + table = parser.table + + # With our parser, any row leaves a table entry + # consisting only of an empty list. Remove any such. + while table and not table[0]: + table.pop(0) + + # We expect rows of the form: + # [['0x00000000', 'STATUS_SUCCESS'], + # ['The operation completed successfully.']] + # The latter list will have multiple entries if Microsoft embedded
+ # or

...

in the text, in which case joining with '\n' is + # appropriate. + # Turn that into a dict whose key is the hex string, and whose value is + # the pair (symbol, desc). + _windows_table = dict((key, (symbol, '\n'.join(desc))) + for (key, symbol), desc in table) + + return _windows_table + +log=logging.getLogger(__name__) +logging.basicConfig() + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + parser.add_argument("-d", "--debug", dest="loglevel", action="store_const", + const=logging.DEBUG, default=logging.INFO) + parser.add_argument("-D", "--define", dest="vars", default=[], action="append", + metavar="VAR=value", + help="Add VAR=value to the env variables defined") + parser.add_argument("-l", "--libpath", dest="libpath", default=[], action="append", + metavar="DIR", + help="Add DIR to the platform-dependent DLL search path") + parser.add_argument("command") + parser.add_argument('args', nargs=argparse.REMAINDER) + args = parser.parse_args() + + log.setLevel(args.loglevel) + + # What we have in opts.vars is a list of strings of the form "VAR=value" + # or possibly just "VAR". What we want is a dict. We can build that dict by + # constructing a list of ["VAR", "value"] pairs -- so split each + # "VAR=value" string on the '=' sign (but only once, in case we have + # "VAR=some=user=string"). To handle the case of just "VAR", append "" to + # the list returned by split(), then slice off anything after the pair we + # want. + rc = main(command=args.command, arguments=args.args, libpath=args.libpath, + vars=dict([(pair.split('=', 1) + [""])[:2] for pair in args.vars])) + if rc not in (None, 0): + log.error("Failure running: %s" % " ".join([args.command] + args.args)) + log.error("Error %s: %s" % (rc, translate_rc(rc))) + sys.exit((rc < 0) and 255 or rc) diff --git a/indra/copy_win_scripts/start-client.py b/indra/copy_win_scripts/start-client.py index 5f7ff2f293..63c765c2fa 100644 --- a/indra/copy_win_scripts/start-client.py +++ b/indra/copy_win_scripts/start-client.py @@ -1,4 +1,28 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 +"""\ +@file start-client.py + +$LicenseInfo:firstyear=2010&license=viewerlgpl$ +Second Life Viewer Source Code +Copyright (C) 2010-2011, Linden Research, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; +version 2.1 of the License only. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +$/LicenseInfo$ +""" import sys, getopt import os import llstart diff --git a/indra/deps/CMakeLists.txt b/indra/deps/CMakeLists.txt new file mode 100644 index 0000000000..a8df464f19 --- /dev/null +++ b/indra/deps/CMakeLists.txt @@ -0,0 +1,62 @@ +project(deps) + +include(FetchContent) + +set(CMAKE_FOLDER "Third Party") +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v2.11.0 + GIT_SHALLOW TRUE + ) +FetchContent_Declare( + fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt.git + GIT_TAG 8d78045e7cb44d39ad4cd95dd27816b8749e1944 + ) +FetchContent_Declare( + nlohmann_json + GIT_REPOSITORY https://github.com/nlohmann/json.git + GIT_TAG v3.7.3 + GIT_SHALLOW TRUE + ) +FetchContent_Declare( + absl + GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git + GIT_TAG 768eb2ca2857342673fcd462792ce04b8bac3fa3 +) + +# This is a hack because absl has dumb cmake +set(OLD_BUILD_TEST ${BUILD_TESTING}) +set(BUILD_TESTING OFF) +FetchContent_MakeAvailable(absl) +set(BUILD_TESTING ${OLD_BUILD_TEST}) + +# Supress warnings inside abseil under MSVC +if(WINDOWS) + target_compile_options(absl_strings PRIVATE /wd4018) + target_compile_options(absl_str_format_internal PRIVATE /wd4018) + target_compile_options(absl_flags_usage_internal PRIVATE /wd4018) +endif() + + +if (BUILD_TESTING) + FetchContent_MakeAvailable(Catch2) +endif() + +#Download the rest of the libraries +FetchContent_MakeAvailable(fmt) + +# Typically you don't care so much for a third party library's tests to be +# run from your own project's code. +set(JSON_BuildTests OFF CACHE INTERNAL "") + +# If you only include this third party in PRIVATE source files, you do not +# need to install it when your main project gets installed. +set(JSON_Install OFF CACHE INTERNAL "") +FetchContent_MakeAvailable(nlohmann_json) + +unset(CMAKE_FOLDER) +unset(CMAKE_POSITION_INDEPENDENT_CODE) diff --git a/indra/develop.py b/indra/develop.py deleted file mode 100755 index 018003c877..0000000000 --- a/indra/develop.py +++ /dev/null @@ -1,941 +0,0 @@ -#!/usr/bin/env python -# -# @file develop.py -# @authors Bryan O'Sullivan, Mark Palange, Aaron Brashears -# @brief Fire and forget script to appropriately configure cmake for SL. -# -# $LicenseInfo:firstyear=2007&license=viewergpl$ -# -# Copyright (c) 2007-2009, Linden Research, Inc. -# -# Second Life Viewer Source Code -# The source code in this file ("Source Code") is provided by Linden Lab -# to you under the terms of the GNU General Public License, version 2.0 -# ("GPL"), unless you have obtained a separate licensing agreement -# ("Other License"), formally executed by you and Linden Lab. Terms of -# the GPL can be found in doc/GPL-license.txt in this distribution, or -# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 -# -# There are special exceptions to the terms and conditions of the GPL as -# it is applied to this Source Code. View the full text of the exception -# in the file doc/FLOSS-exception.txt in this software distribution, or -# online at -# http://secondlifegrid.net/programs/open_source/licensing/flossexception -# -# By copying, modifying or distributing this software, you acknowledge -# that you have read and understood your obligations described above, -# and agree to abide by those obligations. -# -# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO -# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, -# COMPLETENESS OR PERFORMANCE. -# $/LicenseInfo$ - - -import errno -import getopt -import os -import random -import re -import shutil -import socket -import sys -import commands -import shlex - -class CommandError(Exception): - pass - -def mkdir(path): - try: - os.mkdir(path) - return path - except OSError, err: - if err.errno != errno.EEXIST or not os.path.isdir(path): - raise - -def prettyprint_path_for_cmake(path): - if 'a' <= path[0] <= 'z' and path[1] == ':': - # CMake wants DOS drive letters to be in uppercase. The above - # condition never asserts on platforms whose full path names - # always begin with a slash, so we don't need to test whether - # we are running on Windows. - path = path[0].upper() + path[1:] - return path - -def getcwd(): - return prettyprint_path_for_cmake(os.getcwd()) - -source_indra = prettyprint_path_for_cmake(os.path.dirname(os.path.realpath(__file__))) - -def quote(opts): - return '"' + '" "'.join([ opt.replace('"', '') for opt in opts ]) + '"' - -class PlatformSetup(object): - generator = None - build_types = {} - for t in ('Debug', 'Release', 'RelWithDebInfo'): - build_types[t.lower()] = t - - build_type = build_types['relwithdebinfo'] - standalone = 'OFF' - unattended = 'OFF' - universal = 'OFF' - project_name = 'Singularity' - distcc = True - cmake_opts = [] - word_size = 32 - using_express = False - - def __init__(self): - self.script_dir = os.path.realpath( - os.path.dirname(__import__(__name__).__file__)) - - def os(self): - '''Return the name of the OS.''' - - raise NotImplemented('os') - - def arch(self): - '''Return the CPU architecture.''' - - return None - - def platform(self): - '''Return a stringified two-tuple of the OS name and CPU - architecture.''' - - ret = self.os() - if self.arch(): - ret += '-' + self.arch() - return ret - - def build_dirs(self): - '''Return the top-level directories in which builds occur. - This can return more than one directory, e.g. if doing a - 32-bit viewer and server build on Linux.''' - - if(os.path.basename(os.path.normpath(os.getcwd())) == 'indra'): - prefix = '../' - else: - prefix = '' - - return [prefix+'build-' + self.platform()] - - def cmake_commandline(self, src_dir, build_dir, opts, simple): - '''Return the command line to run cmake with.''' - - args = dict( - dir=src_dir, - generator=self.generator, - opts=quote(opts), - standalone=self.standalone, - unattended=self.unattended, - word_size=self.word_size, - type=self.build_type.upper(), - ) - #if simple: - # return 'cmake %(opts)s %(dir)r' % args - return ('cmake -DCMAKE_BUILD_TYPE:STRING=%(type)s ' - '-DSTANDALONE:BOOL=%(standalone)s ' - '-DUNATTENDED:BOOL=%(unattended)s ' - '-DWORD_SIZE:STRING=%(word_size)s ' - '-G %(generator)r %(opts)s %(dir)r' % args) - - def run_cmake(self, args=[]): - '''Run cmake.''' - - # do a sanity check to make sure we have a generator - if not hasattr(self, 'generator'): - raise "No generator available for '%s'" % (self.__name__,) - cwd = getcwd() - created = [] - try: - for d in self.build_dirs(): - simple = True - if mkdir(d): - created.append(d) - simple = False - try: - os.chdir(d) - cmd = self.cmake_commandline(source_indra, d, args, simple) - print 'Running %r in %r' % (cmd, d) - self.run(cmd, 'cmake') - finally: - os.chdir(cwd) - except: - # If we created a directory in which to run cmake and - # something went wrong, the directory probably just - # contains garbage, so delete it. - os.chdir(cwd) - for d in created: - print 'Cleaning %r' % d - shutil.rmtree(d) - raise - - def parse_build_opts(self, arguments): - opts, targets = getopt.getopt(arguments, 'D:o:', ['option=']) - build_opts = [] - for o, a in opts: - if o in ('-o', '--option'): - build_opts.append(a) - return build_opts, targets - - def run_build(self, opts, targets): - '''Build the default targets for this platform.''' - - raise NotImplemented('run_build') - - def cleanup(self): - '''Delete all build directories.''' - - cleaned = 0 - for d in self.build_dirs(): - if os.path.isdir(d): - print 'Cleaning %r' % d - shutil.rmtree(d) - cleaned += 1 - if not cleaned: - print 'Nothing to clean up!' - - def is_internal_tree(self): - '''Indicate whether we are building in an internal source tree.''' - - return os.path.isdir(os.path.join(self.script_dir, 'newsim')) - - def find_in_path(self, name, defval=None, basename=False): - for ext in self.exe_suffixes: - name_ext = name + ext - if os.sep in name_ext: - path = os.path.abspath(name_ext) - if os.access(path, os.X_OK): - return [basename and os.path.basename(path) or path] - for p in os.getenv('PATH', self.search_path).split(os.pathsep): - path = os.path.join(p, name_ext) - if os.access(path, os.X_OK): - return [basename and os.path.basename(path) or path] - if defval: - return [defval] - return [] - - -class UnixSetup(PlatformSetup): - '''Generic Unixy build instructions.''' - - search_path = '/usr/bin:/usr/local/bin' - exe_suffixes = ('',) - - def __init__(self): - PlatformSetup.__init__(self) - super(UnixSetup, self).__init__() - self.generator = 'Unix Makefiles' - - def os(self): - return 'unix' - - def arch(self): - cpu = os.uname()[-1] - if cpu.endswith('386'): - cpu = 'i386' - elif cpu.endswith('86'): - cpu = 'i686' - elif cpu in ('athlon',): - cpu = 'i686' - elif cpu == 'Power Macintosh': - cpu = 'ppc' - elif cpu == 'x86_64' and self.word_size == 32: - cpu = 'i686' - return cpu - - def run(self, command, name=None): - '''Run a program. If the program fails, raise an exception.''' - ret = os.system(command) - if ret: - if name is None: - name = command.split(None, 1)[0] - if os.WIFEXITED(ret): - st = os.WEXITSTATUS(ret) - if st == 127: - event = 'was not found' - else: - event = 'exited with status %d' % st - elif os.WIFSIGNALED(ret): - event = 'was killed by signal %d' % os.WTERMSIG(ret) - else: - event = 'died unexpectedly (!?) with 16-bit status %d' % ret - raise CommandError('the command %r %s' % - (name, event)) - - -class LinuxSetup(UnixSetup): - def __init__(self): - UnixSetup.__init__(self) - super(LinuxSetup, self).__init__() - try: - self.debian_sarge = open('/etc/debian_version').read().strip() == '3.1' - except: - self.debian_sarge = False - - def os(self): - return 'linux' - - def build_dirs(self): - return [PlatformSetup.build_dirs(self)[0]+'-'+self.build_type.lower()] - - def cmake_commandline(self, src_dir, build_dir, opts, simple): - args = dict( - dir=src_dir, - generator=self.generator, - opts=quote(opts), - standalone=self.standalone, - unattended=self.unattended, - type=self.build_type.upper(), - project_name=self.project_name, - word_size=self.word_size, - cxx="g++" - ) - - cmd = (('cmake -DCMAKE_BUILD_TYPE:STRING=%(type)s ' - '-G %(generator)r -DSTANDALONE:BOOL=%(standalone)s ' - '-DWORD_SIZE:STRING=%(word_size)s ' - '-DROOT_PROJECT_NAME:STRING=%(project_name)s ' - '%(opts)s %(dir)r') - % args) - if 'CXX' not in os.environ: - args.update({'cmd':cmd}) - cmd = ('CXX=%(cxx)r %(cmd)s' % args) - return cmd - - def run_build(self, opts, targets): - job_count = None - - for i in range(len(opts)): - if opts[i].startswith('-j'): - try: - job_count = int(opts[i][2:]) - except ValueError: - try: - job_count = int(opts[i+1]) - except ValueError: - job_count = True - - def get_cpu_count(): - count = 0 - for line in open('/proc/cpuinfo'): - if re.match(r'processor\s*:', line): - count += 1 - return count - - def localhost(): - count = get_cpu_count() - return 'localhost/' + str(count), count - - def get_distcc_hosts(): - try: - hosts = [] - name = os.getenv('DISTCC_DIR', '/etc/distcc') + '/hosts' - for l in open(name): - l = l[l.find('#')+1:].strip() - if l: hosts.append(l) - return hosts - except IOError: - return (os.getenv('DISTCC_HOSTS', '').split() or - [localhost()[0]]) - - def count_distcc_hosts(): - cpus = 0 - hosts = 0 - for host in get_distcc_hosts(): - m = re.match(r'.*/(\d+)', host) - hosts += 1 - cpus += m and int(m.group(1)) or 1 - return hosts, cpus - - def mk_distcc_hosts(basename, range, num_cpus): - '''Generate a list of LL-internal machines to build on.''' - loc_entry, cpus = localhost() - hosts = [loc_entry] - dead = [] - stations = [s for s in xrange(range) if s not in dead] - random.shuffle(stations) - hosts += ['%s%d.lindenlab.com/%d,lzo' % (basename, s, num_cpus) for s in stations] - cpus += 2 * len(stations) - return ' '.join(hosts), cpus - - if job_count is None: - hosts, job_count = count_distcc_hosts() - if hosts == 1: - hostname = socket.gethostname() - if hostname.startswith('station'): - hosts, job_count = mk_distcc_hosts('station', 36, 2) - os.environ['DISTCC_HOSTS'] = hosts - if hostname.startswith('eniac'): - hosts, job_count = mk_distcc_hosts('eniac', 71, 2) - os.environ['DISTCC_HOSTS'] = hosts - if job_count > 4: - job_count = 4; - opts.extend(['-j', str(job_count)]) - - if targets: - targets = ' '.join(targets) - else: - targets = 'all' - - for d in self.build_dirs(): - cmd = 'make -C %r %s %s' % (d, ' '.join(opts), targets) - print 'Running %r' % cmd - self.run(cmd) - - -class DarwinSetup(UnixSetup): - def __init__(self): - UnixSetup.__init__(self) - super(DarwinSetup, self).__init__() - self.generator = 'Xcode' - - def os(self): - return 'darwin' - - def arch(self): - if self.universal == 'ON': - return 'universal' - else: - return UnixSetup.arch(self) - - def build_dirs(self): - if(self.generator == 'Xcode'): - return PlatformSetup.build_dirs(self) - else: - return [PlatformSetup.build_dirs(self)[0]+'-'+self.build_type.lower()] - - def cmake_commandline(self, src_dir, build_dir, opts, simple): - args = dict( - dir=src_dir, - generator=self.generator, - opts=quote(opts), - standalone=self.standalone, - word_size=self.word_size, - unattended=self.unattended, - project_name=self.project_name, - universal='', - type='', - ) - if(self.generator != 'Xcode'): - args['type'] = '-DCMAKE_BUILD_TYPE=%s' % self.build_type.upper() - if self.universal == 'ON': - args['universal'] = '-DCMAKE_OSX_ARCHITECTURES:STRING=\'i386;ppc\'' - #if simple: - # return 'cmake %(opts)s %(dir)r' % args - return ('cmake -G %(generator)r ' - '%(type)s ' - '-DSTANDALONE:BOOL=%(standalone)s ' - '-DUNATTENDED:BOOL=%(unattended)s ' - '-DWORD_SIZE:STRING=%(word_size)s ' - '-DROOT_PROJECT_NAME:STRING=%(project_name)s ' - '%(universal)s ' - '%(opts)s %(dir)r' % args) - - def run_build(self, opts, targets): - if(self.generator != 'Xcode'): - if targets: - targets = ' '.join(targets) - else: - targets = 'all' - - for d in self.build_dirs(): - cmd = 'make -C %r %s %s' % (d, ' '.join(opts), targets) - print 'Running %r' % cmd - self.run(cmd) - return - - cwd = getcwd() - if targets: - targets = ' '.join(['-target ' + repr(t) for t in targets]) - else: - targets = '' - cmd = ('xcodebuild -configuration %s %s %s' % - (self.build_type, ' '.join(opts), targets)) - for d in self.build_dirs(): - try: - os.chdir(d) - print 'Running %r in %r' % (cmd, d) - self.run(cmd) - finally: - os.chdir(cwd) - - -class WindowsSetup(PlatformSetup): - gens = { - 'vc100' : { - 'gen' : r'Visual Studio 10', - 'ver' : r'10.0' - }, - 'vc120' : { - 'gen' : r'Visual Studio 12', - 'ver' : r'12.0' - } - } - - gens['vs2010'] = gens['vc100'] - gens['vs2013'] = gens['vc120'] - - search_path = r'C:\windows' - exe_suffixes = ('.exe', '.bat', '.com') - - def __init__(self): - PlatformSetup.__init__(self) - super(WindowsSetup, self).__init__() - self._generator = None - self.incredibuild = False - - def _get_generator(self): - if self._generator is None: - for version in 'vc100'.split(): - if self.find_visual_studio(version): - self._generator = version - print 'Building with ', self.gens[version]['gen'] - break - else: - print >> sys.stderr, 'Cannot find a Visual Studio installation, testing for express editions' - for version in 'vc100'.split(): - if self.find_visual_studio_express(version): - self._generator = version - self.using_express = True - print 'Building with ', self.gens[version]['gen'] , "Express edition" - break - else: - for version in 'vc100'.split(): - if self.find_visual_studio_express_single(version): - self._generator = version - self.using_express = True - print 'Building with ', self.gens[version]['gen'] , "Express edition" - break - else: - print >> sys.stderr, 'Cannot find any Visual Studio installation' - sys.exit(1) - return self._generator - - def _set_generator(self, gen): - self._generator = gen - - generator = property(_get_generator, _set_generator) - - def get_gen_str(self, gen): - if gen is None: - gen = self._generator - return self.gens[gen.lower()]['ver'] - - def os(self): - return 'win32' - - def build_dirs(self): - if(os.path.basename(os.path.normpath(os.getcwd())) == 'indra'): - prefix = '../' - else: - prefix = '' - - if self.word_size == 64: - return [prefix+'build-' + self.generator + '-Win64'] - else: - return [prefix+'build-' + self.generator] - - def cmake_commandline(self, src_dir, build_dir, opts, simple): - args = dict( - dir=src_dir, - generator=self.gens[self.generator.lower()]['gen'], - opts=quote(opts), - standalone=self.standalone, - unattended=self.unattended, - project_name=self.project_name, - word_size=self.word_size, - ) - if self.word_size == 64: - args["generator"] += r' Win64' - - #if simple: - # return 'cmake %(opts)s "%(dir)s"' % args - return ('cmake -G "%(generator)s" ' - '-DSTANDALONE:BOOL=%(standalone)s ' - '-DUNATTENDED:BOOL=%(unattended)s ' - '-DWORD_SIZE:STRING=%(word_size)s ' - '-DROOT_PROJECT_NAME:STRING=\"%(project_name)s\" ' - '%(opts)s "%(dir)s"' % args) - - def get_HKLM_registry_value(self, key_str, value_str): - import _winreg - reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) - key = _winreg.OpenKey(reg, key_str) - value = _winreg.QueryValueEx(key, value_str)[0] - print 'Found: %s' % value - return value - - def find_visual_studio(self, gen=None): - gen = self.get_gen_str(gen) - value_str = (r'EnvironmentDirectory') - key_str = (r'SOFTWARE\Microsoft\VisualStudio\%s\Setup\VS' % - gen) - print ('Reading VS environment from HKEY_LOCAL_MACHINE\%s\%s' % - (key_str, value_str)) - try: - return self.get_HKLM_registry_value(key_str, value_str) - except WindowsError, err: - key_str = (r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%s\Setup\VS' % - gen) - - try: - return self.get_HKLM_registry_value(key_str, value_str) - except: - print >> sys.stderr, "Didn't find ", self.gens[gen]['gen'] - return '' - - def find_msbuild(self, gen=None): - gen = self.get_gen_str(gen) - - key_str = (r'SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0') - - print ('Checking MSBuild support for vs ver = %s' % gen) - if not self.get_HKLM_registry_value(key_str+'\\'+gen, "VCTargetsPath"): - return (None, None) - print ('Reading MSBuild location from HKEY_LOCAL_MACHINE\%s\MSBuildToolsPath' % - key_str) - print key_str - try: - return (self.get_HKLM_registry_value(key_str, 'MSBuildToolsPath'), gen) - except WindowsError, err: - key_str = (r'SOFTWARE\Wow6432Node\Microsoft\MSBuild\ToolsVersions\%s' % - gen) - - try: - return (self.get_HKLM_registry_value(key_str, 'MSBuildToolsPath'), gen) - except WindowsError, err: - print 'Didn\'t find msbuild' - return (None, None) - - def find_visual_studio_express(self, gen=None): - gen = self.get_gen_str(gen) - try: - import _winreg - key_str = (r'SOFTWARE\Microsoft\VCEXpress\%s\Setup\VC' % - gen) - value_str = (r'ProductDir') - print ('Reading VS environment from HKEY_LOCAL_MACHINE\%s\%s' % - (key_str, value_str)) - print key_str - - reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) - key = _winreg.OpenKey(reg, key_str) - value = _winreg.QueryValueEx(key, value_str)[0]+"IDE" - print 'Found: %s' % value - return value - except WindowsError, err: - print >> sys.stderr, "Didn't find ", gen - return '' - - def find_visual_studio_express_single(self, gen=None): - gen = self.get_gen_str(gen) - try: - import _winreg - key_str = (r'SOFTWARE\Microsoft\VCEXpress\%s_Config\Setup\VC' % - gen) - value_str = (r'ProductDir') - print ('Reading VS environment from HKEY_CURRENT_USER\%s\%s' % - (key_str, value_str)) - print key_str - - reg = _winreg.ConnectRegistry(None, _winreg.HKEY_CURRENT_USER) - key = _winreg.OpenKey(reg, key_str) - value = _winreg.QueryValueEx(key, value_str)[0]+"IDE" - print 'Found: %s' % value - return value - except WindowsError, err: - print >> sys.stderr, "Didn't find ", gen - return '' - - def get_build_cmd(self): - if self.incredibuild: - config = self.build_type - if self.gens[self.generator]['ver'] in [ r'8.0', r'9.0' ]: - config = '\"%s|Win32\"' % config - - return "buildconsole \"%s.sln\" /build %s" % (self.project_name, config), None - environment = self.find_visual_studio() - if environment == '': - environment = self.find_visual_studio_express() - if environment == '': - environment = self.find_visual_studio_express_single() - if environment == '': - print >> sys.stderr, "Something went very wrong during build stage, could not find a Visual Studio?" - else: - build_dirs=self.build_dirs() - print >> sys.stderr, "\nSolution generation complete, it can can now be found in:", build_dirs[0] - print >> sys.stderr, "\nAs you are using an Express Visual Studio, the build step cannot be automated" - print >> sys.stderr, "\nPlease see https://wiki.secondlife.com/wiki/Microsoft_Visual_Studio#Extra_steps_for_Visual_Studio_Express_editions for Visual Studio Express specific information" - exit(0) - - msbuild_dir, tool_ver = self.find_msbuild() - - if msbuild_dir is not None and tool_ver is not None: - return ('\"%smsbuild.exe\" \"%s.sln\" /p:configuration=%s /p:VisualStudioVersion=%s' % - (msbuild_dir, self.project_name, self.build_type, tool_ver)), True - - # devenv.com is CLI friendly, devenv.exe... not so much. - return ('"%sdevenv.com" \"%s.sln\" /build %s' % - (self.find_visual_studio(), self.project_name, self.build_type)), None - - def run(self, command, name=None): - '''Run a program. If the program fails, raise an exception.''' - ret = os.system('\"'+command+'\"') - if ret: - if name is None: - name = os.path.normpath(shlex.split(command.encode('utf8'),posix=False)[0].strip('"')) - - path = self.find_in_path(name) - if not path: - ret = 'was not found' - else: - ret = 'exited with status %d' % ret - raise CommandError('the command %r %s' % - (name, ret)) - - def run_cmake(self, args=[]): - '''Override to add the vstool.exe call after running cmake.''' - PlatformSetup.run_cmake(self, args) - if self.unattended == 'OFF': - if self.using_express == False: - self.run_vstool() - - def run_vstool(self): - for build_dir in self.build_dirs(): - stamp = os.path.join(build_dir, 'vstool.txt') - try: - prev_build = open(stamp).read().strip() - except IOError: - prev_build = '' - if prev_build == self.build_type: - # Only run vstool if the build type has changed. - continue - - if(os.path.basename(os.path.normpath(os.getcwd())) == 'indra'): - tool_path = os.path.join('tools','vstool','VSTool.exe') - else: - tool_path = os.path.join('indra','tools','vstool','VSTool.exe') - vstool_cmd = (tool_path + - ' --solution \"' + - os.path.join(build_dir,'%s.sln' % self.project_name) + - '\" --config ' + self.build_type + - ' --startup secondlife-bin') - print 'Running vstool %r in %r' % (vstool_cmd, getcwd()) - self.run(vstool_cmd) - print >> open(stamp, 'w'), self.build_type - - def run_build(self, opts, targets): - cwd = getcwd() - build_cmd, msbuild = self.get_build_cmd() - - for d in self.build_dirs(): - try: - os.chdir(d) - if targets: - if msbuild: - cmd = '%s /target:%s %s' % (build_cmd, ';'.join(targets), ' '.join(opts)) - print 'Running build(targets) %r in %r' % (cmd, d) - self.run(cmd) - else: - for t in targets: - cmd = '%s /project %s %s' % (build_cmd, t, ' '.join(opts)) - print 'Running build(targets) %r in %r' % (cmd, d) - self.run(cmd) - else: - cmd = '%s %s' % (build_cmd, ' '.join(opts)) - print 'Running build %r in %r' % (cmd, d) - self.run(cmd) - finally: - os.chdir(cwd) - -class CygwinSetup(WindowsSetup): - def __init__(self): - super(CygwinSetup, self).__init__() - self.generator = 'vc80' - - def cmake_commandline(self, src_dir, build_dir, opts, simple): - dos_dir = commands.getoutput("cygpath -w %s" % src_dir) - args = dict( - dir=dos_dir, - generator=self.gens[self.generator.lower()]['gen'], - opts=quote(opts), - standalone=self.standalone, - unattended=self.unattended, - project_name=self.project_name, - word_size=self.word_size, - ) - if self.word_size == 64: - args["generator"] += r' Win64' - #if simple: - # return 'cmake %(opts)s "%(dir)s"' % args - return ('cmake -G "%(generator)s" ' - '-DUNATTENDED:BOOl=%(unattended)s ' - '-DSTANDALONE:BOOL=%(standalone)s ' - '-DWORD_SIZE:STRING=%(word_size)s ' - '-DROOT_PROJECT_NAME:STRING=%(project_name)s ' - '%(opts)s "%(dir)s"' % args) - - def run(self, command, name=None): - '''Run a program. If the program fails, raise an exception.''' - ret = os.system(command) - if ret: - if name is None: - name = os.path.normpath(shlex.split(command.encode('utf8'),posix=False)[0].strip('"')) - - path = self.find_in_path(name) - if not path: - ret = 'was not found' - else: - ret = 'exited with status %d' % ret - raise CommandError('the command %r %s' % - (name, ret)) - - -setup_platform = { - 'darwin': DarwinSetup, - 'linux2': LinuxSetup, - 'linux3': LinuxSetup, - 'win32' : WindowsSetup, - 'cygwin' : CygwinSetup - } - - -usage_msg = ''' -Usage: develop.py [options] [command [command-options]] - -Options: - -h | --help print this help message - --standalone build standalone, without Linden prebuild libraries - --unattended build unattended, do not invoke any tools requiring - a human response - --universal build a universal binary on Mac OS X (unsupported) - -t | --type=NAME build type ("Debug", "Release", or "RelWithDebInfo") - -m32 | -m64 build architecture (32-bit or 64-bit) - -N | --no-distcc disable use of distcc - -G | --generator=NAME generator name - Windows: VC100 (VS2010) (default) - Mac OS X: Xcode (default), Unix Makefiles - Linux: Unix Makefiles (default), KDevelop3 - -p | --project=NAME set the root project name. (Doesn't effect makefiles) - -Commands: - build configure and build default target - clean delete all build directories, does not affect sources - configure configure project by running cmake (default if none given) - printbuilddirs print the build directory that will be used - -Command-options for "configure": - We use cmake variables to change the build configuration. - -DPACKAGE:BOOL=ON Create "package" target to make installers - -DLL_TESTS:BOOL=OFF Don't generate unit test projects - -DEXAMPLEPLUGIN:BOOL=OFF Don't generate example plugin project - -DDISABLE_TCMALLOC:BOOL=ON Disable linkage of TCMalloc. (64bit builds automatically disable TCMalloc) - -DRELEASE_CRASH_REPORTING:BOOL=ON Enable Google Breakpad crash reporting - -DFMODSTUDIO:BOOL=ON Use FMOD Studio audio libraries - -DFMODEX:BOOL=ON Use FMOD Ex audio libraries - -Examples: - Set up a Visual Studio 2010 project with "package" target: - develop.py -G vc100 configure -DPACKAGE:BOOL=ON -''' - -def main(arguments): - setup = setup_platform[sys.platform]() - try: - opts, args = getopt.getopt( - arguments, - '?hNt:p:G:m:', - ['help', 'standalone', 'no-distcc', 'unattended', 'type=', 'incredibuild', 'generator=', 'project=']) - except getopt.GetoptError, err: - print >> sys.stderr, 'Error:', err - print >> sys.stderr, """ -Note: You must pass -D options to cmake after the "configure" command -For example: develop.py configure -DSERVER:BOOL=OFF""" - print >> sys.stderr, usage_msg.strip() - sys.exit(1) - - for o, a in opts: - if o in ('-?', '-h', '--help'): - print usage_msg.strip() - sys.exit(0) - elif o in ('--standalone',): - setup.standalone = 'ON' - elif o in ('--unattended',): - setup.unattended = 'ON' - elif o in ('-m',): - if a in ('32', '64'): - setup.word_size = int(a) - else: - print >> sys.stderr, 'Error: unknown word size', repr(a) - print >> sys.stderr, 'Supported word sizes: 32, 64' - sys.exit(1) - elif o in ('-t', '--type'): - try: - setup.build_type = setup.build_types[a.lower()] - except KeyError: - print >> sys.stderr, 'Error: unknown build type', repr(a) - print >> sys.stderr, 'Supported build types:' - types = setup.build_types.values() - types.sort() - for t in types: - print ' ', t - sys.exit(1) - elif o in ('-G', '--generator'): - setup.generator = a - elif o in ('-N', '--no-distcc'): - setup.distcc = False - elif o in ('-p', '--project'): - setup.project_name = a - elif o in ('--incredibuild'): - setup.incredibuild = True - else: - print >> sys.stderr, 'INTERNAL ERROR: unhandled option', repr(o) - sys.exit(1) - if not args: - setup.run_cmake() - return - try: - cmd = args.pop(0) - if cmd in ('cmake', 'configure'): - setup.run_cmake(args) - elif cmd == 'build': - if os.getenv('DISTCC_DIR') is None: - distcc_dir = os.path.join(getcwd(), '.distcc') - if not os.path.exists(distcc_dir): - os.mkdir(distcc_dir) - print "setting DISTCC_DIR to %s" % distcc_dir - os.environ['DISTCC_DIR'] = distcc_dir - else: - print "DISTCC_DIR is set to %s" % os.getenv('DISTCC_DIR') - for d in setup.build_dirs(): - if not os.path.exists(d): - raise CommandError('run "develop.py cmake" first') - setup.run_cmake() - opts, targets = setup.parse_build_opts(args) - setup.run_build(opts, targets) - elif cmd == 'clean': - if args: - raise CommandError('clean takes no arguments') - setup.cleanup() - elif cmd == 'printbuilddirs': - for d in setup.build_dirs(): - print >> sys.stdout, d - else: - print >> sys.stderr, 'Error: unknown subcommand', repr(cmd) - print >> sys.stderr, "(run 'develop.py --help' for help)" - sys.exit(1) - except getopt.GetoptError, err: - print >> sys.stderr, 'Error with %r subcommand: %s' % (cmd, err) - sys.exit(1) - - -if __name__ == '__main__': - try: - main(sys.argv[1:]) - except CommandError, err: - print >> sys.stderr, 'Error:', err - sys.exit(1) diff --git a/indra/lib/python/indra/base/__init__.py b/indra/lib/python/indra/base/__init__.py deleted file mode 100644 index 2904fd3380..0000000000 --- a/indra/lib/python/indra/base/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -"""\ -@file __init__.py -@brief Initialization file for the indra.base module. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" diff --git a/indra/lib/python/indra/base/cllsd_test.py b/indra/lib/python/indra/base/cllsd_test.py deleted file mode 100644 index 1f06898ffd..0000000000 --- a/indra/lib/python/indra/base/cllsd_test.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/python -## -## $LicenseInfo:firstyear=2011&license=viewerlgpl$ -## Second Life Viewer Source Code -## Copyright (C) 2011, 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$ -from indra.base import llsd, lluuid -from datetime import datetime -import cllsd -import time, sys - -class myint(int): - pass - -values = ( - '&<>', - u'\u81acj', - llsd.uri('http://foo<'), - lluuid.UUID(), - llsd.LLSD(['thing']), - 1, - myint(31337), - sys.maxint + 10, - llsd.binary('foo'), - [], - {}, - {u'f&\u1212': 3}, - 3.1, - True, - None, - datetime.fromtimestamp(time.time()), - ) - -def valuator(values): - for v in values: - yield v - -longvalues = () # (values, list(values), iter(values), valuator(values)) - -for v in values + longvalues: - print '%r => %r' % (v, cllsd.llsd_to_xml(v)) - -a = [[{'a':3}]] * 1000000 - -s = time.time() -print hash(cllsd.llsd_to_xml(a)) -e = time.time() -t1 = e - s -print t1 - -s = time.time() -print hash(llsd.LLSDXMLFormatter()._format(a)) -e = time.time() -t2 = e - s -print t2 - -print 'Speedup:', t2 / t1 diff --git a/indra/lib/python/indra/base/config.py b/indra/lib/python/indra/base/config.py deleted file mode 100644 index adafa29b51..0000000000 --- a/indra/lib/python/indra/base/config.py +++ /dev/null @@ -1,266 +0,0 @@ -"""\ -@file config.py -@brief Utility module for parsing and accessing the indra.xml config file. - -$LicenseInfo:firstyear=2006&license=mit$ - -Copyright (c) 2006-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import copy -import errno -import os -import traceback -import time -import types - -from os.path import dirname, getmtime, join, realpath -from indra.base import llsd - -_g_config = None - -class IndraConfig(object): - """ - IndraConfig loads a 'indra' xml configuration file - and loads into memory. This representation in memory - can get updated to overwrite values or add new values. - - The xml configuration file is considered a live file and changes - to the file are checked and reloaded periodically. If a value had - been overwritten via the update or set method, the loaded values - from the file are ignored (the values from the update/set methods - override) - """ - def __init__(self, indra_config_file): - self._indra_config_file = indra_config_file - self._reload_check_interval = 30 # seconds - self._last_check_time = 0 - self._last_mod_time = 0 - - self._config_overrides = {} - self._config_file_dict = {} - self._combined_dict = {} - - self._load() - - def _load(self): - # if you initialize the IndraConfig with None, no attempt - # is made to load any files - if self._indra_config_file is None: - return - - config_file = open(self._indra_config_file) - self._config_file_dict = llsd.parse(config_file.read()) - self._combine_dictionaries() - config_file.close() - - self._last_mod_time = self._get_last_modified_time() - self._last_check_time = time.time() # now - - def _get_last_modified_time(self): - """ - Returns the mtime (last modified time) of the config file, - if such exists. - """ - if self._indra_config_file is not None: - return os.path.getmtime(self._indra_config_file) - - return 0 - - def _combine_dictionaries(self): - self._combined_dict = {} - self._combined_dict.update(self._config_file_dict) - self._combined_dict.update(self._config_overrides) - - def _reload_if_necessary(self): - now = time.time() - - if (now - self._last_check_time) > self._reload_check_interval: - self._last_check_time = now - try: - modtime = self._get_last_modified_time() - if modtime > self._last_mod_time: - self._load() - except OSError, e: - if e.errno == errno.ENOENT: # file not found - # someone messed with our internal state - # or removed the file - - print 'WARNING: Configuration file has been removed ' + (self._indra_config_file) - print 'Disabling reloading of configuration file.' - - traceback.print_exc() - - self._indra_config_file = None - self._last_check_time = 0 - self._last_mod_time = 0 - else: - raise # pass the exception along to the caller - - def __getitem__(self, key): - self._reload_if_necessary() - - return self._combined_dict[key] - - def get(self, key, default = None): - try: - return self.__getitem__(key) - except KeyError: - return default - - def __setitem__(self, key, value): - """ - Sets the value of the config setting of key to be newval - - Once any key/value pair is changed via the set method, - that key/value pair will remain set with that value until - change via the update or set method - """ - self._config_overrides[key] = value - self._combine_dictionaries() - - def set(self, key, newval): - return self.__setitem__(key, newval) - - def update(self, new_conf): - """ - Load an XML file and apply its map as overrides or additions - to the existing config. Update can be a file or a dict. - - Once any key/value pair is changed via the update method, - that key/value pair will remain set with that value until - change via the update or set method - """ - if isinstance(new_conf, dict): - overrides = new_conf - else: - # assuming that it is a filename - config_file = open(new_conf) - overrides = llsd.parse(config_file.read()) - config_file.close() - - self._config_overrides.update(overrides) - self._combine_dictionaries() - - def as_dict(self): - """ - Returns immutable copy of the IndraConfig as a dictionary - """ - return copy.deepcopy(self._combined_dict) - -def load(config_xml_file = None): - global _g_config - - load_default_files = config_xml_file is None - if load_default_files: - ## going from: - ## "/opt/linden/indra/lib/python/indra/base/config.py" - ## to: - ## "/opt/linden/etc/indra.xml" - config_xml_file = realpath( - dirname(realpath(__file__)) + "../../../../../../etc/indra.xml") - - try: - _g_config = IndraConfig(config_xml_file) - except IOError: - # Failure to load passed in file - # or indra.xml default file - if load_default_files: - try: - config_xml_file = realpath( - dirname(realpath(__file__)) + "../../../../../../etc/globals.xml") - _g_config = IndraConfig(config_xml_file) - return - except IOError: - # Failure to load globals.xml - # fall to code below - pass - - # Either failed to load passed in file - # or failed to load all default files - _g_config = IndraConfig(None) - -def dump(indra_xml_file, indra_cfg = None, update_in_mem=False): - ''' - Dump config contents into a file - Kindof reverse of load. - Optionally takes a new config to dump. - Does NOT update global config unless requested. - ''' - global _g_config - - if not indra_cfg: - if _g_config is None: - return - - indra_cfg = _g_config.as_dict() - - if not indra_cfg: - return - - config_file = open(indra_xml_file, 'w') - _config_xml = llsd.format_xml(indra_cfg) - config_file.write(_config_xml) - config_file.close() - - if update_in_mem: - update(indra_cfg) - -def update(new_conf): - global _g_config - - if _g_config is None: - # To keep with how this function behaved - # previously, a call to update - # before the global is defined - # make a new global config which does not - # load data from a file. - _g_config = IndraConfig(None) - - return _g_config.update(new_conf) - -def get(key, default = None): - global _g_config - - if _g_config is None: - load() - - return _g_config.get(key, default) - -def set(key, newval): - """ - Sets the value of the config setting of key to be newval - - Once any key/value pair is changed via the set method, - that key/value pair will remain set with that value until - change via the update or set method or program termination - """ - global _g_config - - if _g_config is None: - _g_config = IndraConfig(None) - - _g_config.set(key, newval) - -def get_config(): - global _g_config - return _g_config diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py deleted file mode 100644 index 4527b115f9..0000000000 --- a/indra/lib/python/indra/base/llsd.py +++ /dev/null @@ -1,1052 +0,0 @@ -"""\ -@file llsd.py -@brief Types as well as parsing and formatting functions for handling LLSD. - -$LicenseInfo:firstyear=2006&license=mit$ - -Copyright (c) 2006-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import datetime -import base64 -import string -import struct -import time -import types -import re - -from indra.util.fastest_elementtree import ElementTreeError, fromstring -from indra.base import lluuid - -# cllsd.c in server/server-1.25 has memory leaks, -# so disabling cllsd for now -#try: -# import cllsd -#except ImportError: -# cllsd = None -cllsd = None - -int_regex = re.compile(r"[-+]?\d+") -real_regex = re.compile(r"[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?") -alpha_regex = re.compile(r"[a-zA-Z]+") -date_regex = re.compile(r"(?P\d{4})-(?P\d{2})-(?P\d{2})T" - r"(?P\d{2}):(?P\d{2}):(?P\d{2})" - r"(?P(\.\d+)?)Z") -#date: d"YYYY-MM-DDTHH:MM:SS.FFFFFFZ" - -class LLSDParseError(Exception): - pass - -class LLSDSerializationError(TypeError): - pass - - -class binary(str): - pass - -class uri(str): - pass - - -BOOL_TRUE = ('1', '1.0', 'true') -BOOL_FALSE = ('0', '0.0', 'false', '') - - -def format_datestr(v): - """ Formats a datetime or date object into the string format shared by xml and notation serializations.""" - if hasattr(v, 'microsecond'): - return v.isoformat() + 'Z' - else: - return v.strftime('%Y-%m-%dT%H:%M:%SZ') - -def parse_datestr(datestr): - """Parses a datetime object from the string format shared by xml and notation serializations.""" - if datestr == "": - return datetime.datetime(1970, 1, 1) - - match = re.match(date_regex, datestr) - if not match: - raise LLSDParseError("invalid date string '%s'." % datestr) - - year = int(match.group('year')) - month = int(match.group('month')) - day = int(match.group('day')) - hour = int(match.group('hour')) - minute = int(match.group('minute')) - second = int(match.group('second')) - seconds_float = match.group('second_float') - microsecond = 0 - if seconds_float: - microsecond = int(float('0' + seconds_float) * 1e6) - return datetime.datetime(year, month, day, hour, minute, second, microsecond) - - -def bool_to_python(node): - val = node.text or '' - if val in BOOL_TRUE: - return True - else: - return False - -def int_to_python(node): - val = node.text or '' - if not val.strip(): - return 0 - return int(val) - -def real_to_python(node): - val = node.text or '' - if not val.strip(): - return 0.0 - return float(val) - -def uuid_to_python(node): - return lluuid.UUID(node.text) - -def str_to_python(node): - return node.text or '' - -def bin_to_python(node): - return binary(base64.decodestring(node.text or '')) - -def date_to_python(node): - val = node.text or '' - if not val: - val = "1970-01-01T00:00:00Z" - return parse_datestr(val) - - -def uri_to_python(node): - val = node.text or '' - if not val: - return None - return uri(val) - -def map_to_python(node): - result = {} - for index in range(len(node))[::2]: - result[node[index].text] = to_python(node[index+1]) - return result - -def array_to_python(node): - return [to_python(child) for child in node] - - -NODE_HANDLERS = dict( - undef=lambda x: None, - boolean=bool_to_python, - integer=int_to_python, - real=real_to_python, - uuid=uuid_to_python, - string=str_to_python, - binary=bin_to_python, - date=date_to_python, - uri=uri_to_python, - map=map_to_python, - array=array_to_python, - ) - -def to_python(node): - return NODE_HANDLERS[node.tag](node) - -class Nothing(object): - pass - - -class LLSDXMLFormatter(object): - def __init__(self): - self.type_map = { - type(None) : self.UNDEF, - bool : self.BOOLEAN, - int : self.INTEGER, - long : self.INTEGER, - float : self.REAL, - lluuid.UUID : self.UUID, - binary : self.BINARY, - str : self.STRING, - unicode : self.STRING, - uri : self.URI, - datetime.datetime : self.DATE, - datetime.date : self.DATE, - list : self.ARRAY, - tuple : self.ARRAY, - types.GeneratorType : self.ARRAY, - dict : self.MAP, - LLSD : self.LLSD - } - - def elt(self, name, contents=None): - if(contents is None or contents is ''): - return "<%s />" % (name,) - else: - if type(contents) is unicode: - contents = contents.encode('utf-8') - return "<%s>%s" % (name, contents, name) - - def xml_esc(self, v): - if type(v) is unicode: - v = v.encode('utf-8') - return v.replace('&', '&').replace('<', '<').replace('>', '>') - - def LLSD(self, v): - return self.generate(v.thing) - def UNDEF(self, v): - return self.elt('undef') - def BOOLEAN(self, v): - if v: - return self.elt('boolean', 'true') - else: - return self.elt('boolean', 'false') - def INTEGER(self, v): - return self.elt('integer', v) - def REAL(self, v): - return self.elt('real', v) - def UUID(self, v): - if(v.isNull()): - return self.elt('uuid') - else: - return self.elt('uuid', v) - def BINARY(self, v): - return self.elt('binary', base64.encodestring(v)) - def STRING(self, v): - return self.elt('string', self.xml_esc(v)) - def URI(self, v): - return self.elt('uri', self.xml_esc(str(v))) - def DATE(self, v): - return self.elt('date', format_datestr(v)) - def ARRAY(self, v): - return self.elt('array', ''.join([self.generate(item) for item in v])) - def MAP(self, v): - return self.elt( - 'map', - ''.join(["%s%s" % (self.elt('key', self.xml_esc(str(key))), self.generate(value)) - for key, value in v.items()])) - - typeof = type - def generate(self, something): - t = self.typeof(something) - if self.type_map.has_key(t): - return self.type_map[t](something) - else: - raise LLSDSerializationError("Cannot serialize unknown type: %s (%s)" % ( - t, something)) - - def _format(self, something): - return '' + self.elt("llsd", self.generate(something)) - - def format(self, something): - if cllsd: - return cllsd.llsd_to_xml(something) - return self._format(something) - -_g_xml_formatter = None -def format_xml(something): - global _g_xml_formatter - if _g_xml_formatter is None: - _g_xml_formatter = LLSDXMLFormatter() - return _g_xml_formatter.format(something) - -class LLSDXMLPrettyFormatter(LLSDXMLFormatter): - def __init__(self, indent_atom = None): - # Call the super class constructor so that we have the type map - super(LLSDXMLPrettyFormatter, self).__init__() - - # Override the type map to use our specialized formatters to - # emit the pretty output. - self.type_map[list] = self.PRETTY_ARRAY - self.type_map[tuple] = self.PRETTY_ARRAY - self.type_map[types.GeneratorType] = self.PRETTY_ARRAY, - self.type_map[dict] = self.PRETTY_MAP - - # Private data used for indentation. - self._indent_level = 1 - if indent_atom is None: - self._indent_atom = ' ' - else: - self._indent_atom = indent_atom - - def _indent(self): - "Return an indentation based on the atom and indentation level." - return self._indent_atom * self._indent_level - - def PRETTY_ARRAY(self, v): - rv = [] - rv.append('\n') - self._indent_level = self._indent_level + 1 - rv.extend(["%s%s\n" % - (self._indent(), - self.generate(item)) - for item in v]) - self._indent_level = self._indent_level - 1 - rv.append(self._indent()) - rv.append('') - return ''.join(rv) - - def PRETTY_MAP(self, v): - rv = [] - rv.append('\n') - self._indent_level = self._indent_level + 1 - keys = v.keys() - keys.sort() - rv.extend(["%s%s\n%s%s\n" % - (self._indent(), - self.elt('key', key), - self._indent(), - self.generate(v[key])) - for key in keys]) - self._indent_level = self._indent_level - 1 - rv.append(self._indent()) - rv.append('') - return ''.join(rv) - - def format(self, something): - data = [] - data.append('\n') - data.append(self.generate(something)) - data.append('\n') - return '\n'.join(data) - -def format_pretty_xml(something): - """@brief Serialize a python object as 'pretty' llsd xml. - - The output conforms to the LLSD DTD, unlike the output from the - standard python xml.dom DOM::toprettyxml() method which does not - preserve significant whitespace. - This function is not necessarily suited for serializing very large - objects. It is not optimized by the cllsd module, and sorts on - dict (llsd map) keys alphabetically to ease human reading. - """ - return LLSDXMLPrettyFormatter().format(something) - -class LLSDNotationFormatter(object): - def __init__(self): - self.type_map = { - type(None) : self.UNDEF, - bool : self.BOOLEAN, - int : self.INTEGER, - long : self.INTEGER, - float : self.REAL, - lluuid.UUID : self.UUID, - binary : self.BINARY, - str : self.STRING, - unicode : self.STRING, - uri : self.URI, - datetime.datetime : self.DATE, - datetime.date : self.DATE, - list : self.ARRAY, - tuple : self.ARRAY, - types.GeneratorType : self.ARRAY, - dict : self.MAP, - LLSD : self.LLSD - } - - def LLSD(self, v): - return self.generate(v.thing) - def UNDEF(self, v): - return '!' - def BOOLEAN(self, v): - if v: - return 'true' - else: - return 'false' - def INTEGER(self, v): - return "i%s" % v - def REAL(self, v): - return "r%s" % v - def UUID(self, v): - return "u%s" % v - def BINARY(self, v): - return 'b64"' + base64.encodestring(v) + '"' - def STRING(self, v): - if isinstance(v, unicode): - v = v.encode('utf-8') - return "'%s'" % v.replace("\\", "\\\\").replace("'", "\\'") - def URI(self, v): - return 'l"%s"' % str(v).replace("\\", "\\\\").replace('"', '\\"') - def DATE(self, v): - return 'd"%s"' % format_datestr(v) - def ARRAY(self, v): - return "[%s]" % ','.join([self.generate(item) for item in v]) - def MAP(self, v): - def fix(key): - if isinstance(key, unicode): - return key.encode('utf-8') - return key - return "{%s}" % ','.join(["'%s':%s" % (fix(key).replace("\\", "\\\\").replace("'", "\\'"), self.generate(value)) - for key, value in v.items()]) - - def generate(self, something): - t = type(something) - handler = self.type_map.get(t) - if handler: - return handler(something) - else: - try: - return self.ARRAY(iter(something)) - except TypeError: - raise LLSDSerializationError( - "Cannot serialize unknown type: %s (%s)" % (t, something)) - - def format(self, something): - return self.generate(something) - -def format_notation(something): - return LLSDNotationFormatter().format(something) - -def _hex_as_nybble(hex): - if (hex >= '0') and (hex <= '9'): - return ord(hex) - ord('0') - elif (hex >= 'a') and (hex <='f'): - return 10 + ord(hex) - ord('a') - elif (hex >= 'A') and (hex <='F'): - return 10 + ord(hex) - ord('A'); - -class LLSDBinaryParser(object): - def __init__(self): - pass - - def parse(self, buffer, ignore_binary = False): - """ - This is the basic public interface for parsing. - - @param buffer the binary data to parse in an indexable sequence. - @param ignore_binary parser throws away data in llsd binary nodes. - @return returns a python object. - """ - self._buffer = buffer - self._index = 0 - self._keep_binary = not ignore_binary - return self._parse() - - def _parse(self): - cc = self._buffer[self._index] - self._index += 1 - if cc == '{': - return self._parse_map() - elif cc == '[': - return self._parse_array() - elif cc == '!': - return None - elif cc == '0': - return False - elif cc == '1': - return True - elif cc == 'i': - # 'i' = integer - idx = self._index - self._index += 4 - return struct.unpack("!i", self._buffer[idx:idx+4])[0] - elif cc == ('r'): - # 'r' = real number - idx = self._index - self._index += 8 - return struct.unpack("!d", self._buffer[idx:idx+8])[0] - elif cc == 'u': - # 'u' = uuid - idx = self._index - self._index += 16 - return lluuid.uuid_bits_to_uuid(self._buffer[idx:idx+16]) - elif cc == 's': - # 's' = string - return self._parse_string() - elif cc in ("'", '"'): - # delimited/escaped string - return self._parse_string_delim(cc) - elif cc == 'l': - # 'l' = uri - return uri(self._parse_string()) - elif cc == ('d'): - # 'd' = date in seconds since epoch - idx = self._index - self._index += 8 - seconds = struct.unpack("!d", self._buffer[idx:idx+8])[0] - return datetime.datetime.fromtimestamp(seconds) - elif cc == 'b': - binary = self._parse_string() - if self._keep_binary: - return binary - # *NOTE: maybe have a binary placeholder which has the - # length. - return None - else: - raise LLSDParseError("invalid binary token at byte %d: %d" % ( - self._index - 1, ord(cc))) - - def _parse_map(self): - rv = {} - size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0] - self._index += 4 - count = 0 - cc = self._buffer[self._index] - self._index += 1 - key = '' - while (cc != '}') and (count < size): - if cc == 'k': - key = self._parse_string() - elif cc in ("'", '"'): - key = self._parse_string_delim(cc) - else: - raise LLSDParseError("invalid map key at byte %d." % ( - self._index - 1,)) - value = self._parse() - rv[key] = value - count += 1 - cc = self._buffer[self._index] - self._index += 1 - if cc != '}': - raise LLSDParseError("invalid map close token at byte %d." % ( - self._index,)) - return rv - - def _parse_array(self): - rv = [] - size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0] - self._index += 4 - count = 0 - cc = self._buffer[self._index] - while (cc != ']') and (count < size): - rv.append(self._parse()) - count += 1 - cc = self._buffer[self._index] - if cc != ']': - raise LLSDParseError("invalid array close token at byte %d." % ( - self._index,)) - self._index += 1 - return rv - - def _parse_string(self): - size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0] - self._index += 4 - rv = self._buffer[self._index:self._index+size] - self._index += size - return rv - - def _parse_string_delim(self, delim): - list = [] - found_escape = False - found_hex = False - found_digit = False - byte = 0 - while True: - cc = self._buffer[self._index] - self._index += 1 - if found_escape: - if found_hex: - if found_digit: - found_escape = False - found_hex = False - found_digit = False - byte <<= 4 - byte |= _hex_as_nybble(cc) - list.append(chr(byte)) - byte = 0 - else: - found_digit = True - byte = _hex_as_nybble(cc) - elif cc == 'x': - found_hex = True - else: - if cc == 'a': - list.append('\a') - elif cc == 'b': - list.append('\b') - elif cc == 'f': - list.append('\f') - elif cc == 'n': - list.append('\n') - elif cc == 'r': - list.append('\r') - elif cc == 't': - list.append('\t') - elif cc == 'v': - list.append('\v') - else: - list.append(cc) - found_escape = False - elif cc == '\\': - found_escape = True - elif cc == delim: - break - else: - list.append(cc) - return ''.join(list) - -class LLSDNotationParser(object): - """ Parse LLSD notation: - map: { string:object, string:object } - array: [ object, object, object ] - undef: ! - boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE - integer: i#### - real: r#### - uuid: u#### - string: "g\'day" | 'have a "nice" day' | s(size)"raw data" - uri: l"escaped" - date: d"YYYY-MM-DDTHH:MM:SS.FFZ" - binary: b##"ff3120ab1" | b(size)"raw data" - """ - def __init__(self): - pass - - def parse(self, buffer, ignore_binary = False): - """ - This is the basic public interface for parsing. - - @param buffer the notation string to parse. - @param ignore_binary parser throws away data in llsd binary nodes. - @return returns a python object. - """ - if buffer == "": - return False - - self._buffer = buffer - self._index = 0 - return self._parse() - - def _parse(self): - cc = self._buffer[self._index] - self._index += 1 - if cc == '{': - return self._parse_map() - elif cc == '[': - return self._parse_array() - elif cc == '!': - return None - elif cc == '0': - return False - elif cc == '1': - return True - elif cc in ('F', 'f'): - self._skip_alpha() - return False - elif cc in ('T', 't'): - self._skip_alpha() - return True - elif cc == 'i': - # 'i' = integer - return self._parse_integer() - elif cc == ('r'): - # 'r' = real number - return self._parse_real() - elif cc == 'u': - # 'u' = uuid - return self._parse_uuid() - elif cc in ("'", '"', 's'): - return self._parse_string(cc) - elif cc == 'l': - # 'l' = uri - delim = self._buffer[self._index] - self._index += 1 - val = uri(self._parse_string(delim)) - if len(val) == 0: - return None - return val - elif cc == ('d'): - # 'd' = date in seconds since epoch - return self._parse_date() - elif cc == 'b': - return self._parse_binary() - else: - raise LLSDParseError("invalid token at index %d: %d" % ( - self._index - 1, ord(cc))) - - def _parse_binary(self): - i = self._index - if self._buffer[i:i+2] == '64': - q = self._buffer[i+2] - e = self._buffer.find(q, i+3) - try: - return base64.decodestring(self._buffer[i+3:e]) - finally: - self._index = e + 1 - else: - raise LLSDParseError('random horrible binary format not supported') - - def _parse_map(self): - """ map: { string:object, string:object } """ - rv = {} - cc = self._buffer[self._index] - self._index += 1 - key = '' - found_key = False - while (cc != '}'): - if not found_key: - if cc in ("'", '"', 's'): - key = self._parse_string(cc) - found_key = True - elif cc.isspace() or cc == ',': - cc = self._buffer[self._index] - self._index += 1 - else: - raise LLSDParseError("invalid map key at byte %d." % ( - self._index - 1,)) - elif cc.isspace() or cc == ':': - cc = self._buffer[self._index] - self._index += 1 - continue - else: - self._index += 1 - value = self._parse() - rv[key] = value - found_key = False - cc = self._buffer[self._index] - self._index += 1 - - return rv - - def _parse_array(self): - """ array: [ object, object, object ] """ - rv = [] - cc = self._buffer[self._index] - while (cc != ']'): - if cc.isspace() or cc == ',': - self._index += 1 - cc = self._buffer[self._index] - continue - rv.append(self._parse()) - cc = self._buffer[self._index] - - if cc != ']': - raise LLSDParseError("invalid array close token at index %d." % ( - self._index,)) - self._index += 1 - return rv - - def _parse_uuid(self): - match = re.match(lluuid.UUID.uuid_regex, self._buffer[self._index:]) - if not match: - raise LLSDParseError("invalid uuid token at index %d." % self._index) - - (start, end) = match.span() - start += self._index - end += self._index - self._index = end - return lluuid.UUID(self._buffer[start:end]) - - def _skip_alpha(self): - match = re.match(alpha_regex, self._buffer[self._index:]) - if match: - self._index += match.end() - - def _parse_date(self): - delim = self._buffer[self._index] - self._index += 1 - datestr = self._parse_string(delim) - return parse_datestr(datestr) - - def _parse_real(self): - match = re.match(real_regex, self._buffer[self._index:]) - if not match: - raise LLSDParseError("invalid real token at index %d." % self._index) - - (start, end) = match.span() - start += self._index - end += self._index - self._index = end - return float( self._buffer[start:end] ) - - def _parse_integer(self): - match = re.match(int_regex, self._buffer[self._index:]) - if not match: - raise LLSDParseError("invalid integer token at index %d." % self._index) - - (start, end) = match.span() - start += self._index - end += self._index - self._index = end - return int( self._buffer[start:end] ) - - def _parse_string(self, delim): - """ string: "g\'day" | 'have a "nice" day' | s(size)"raw data" """ - rv = "" - - if delim in ("'", '"'): - rv = self._parse_string_delim(delim) - elif delim == 's': - rv = self._parse_string_raw() - else: - raise LLSDParseError("invalid string token at index %d." % self._index) - - return rv - - - def _parse_string_delim(self, delim): - """ string: "g'day 'un" | 'have a "nice" day' """ - list = [] - found_escape = False - found_hex = False - found_digit = False - byte = 0 - while True: - cc = self._buffer[self._index] - self._index += 1 - if found_escape: - if found_hex: - if found_digit: - found_escape = False - found_hex = False - found_digit = False - byte <<= 4 - byte |= _hex_as_nybble(cc) - list.append(chr(byte)) - byte = 0 - else: - found_digit = True - byte = _hex_as_nybble(cc) - elif cc == 'x': - found_hex = True - else: - if cc == 'a': - list.append('\a') - elif cc == 'b': - list.append('\b') - elif cc == 'f': - list.append('\f') - elif cc == 'n': - list.append('\n') - elif cc == 'r': - list.append('\r') - elif cc == 't': - list.append('\t') - elif cc == 'v': - list.append('\v') - else: - list.append(cc) - found_escape = False - elif cc == '\\': - found_escape = True - elif cc == delim: - break - else: - list.append(cc) - return ''.join(list) - - def _parse_string_raw(self): - """ string: s(size)"raw data" """ - # Read the (size) portion. - cc = self._buffer[self._index] - self._index += 1 - if cc != '(': - raise LLSDParseError("invalid string token at index %d." % self._index) - - rparen = self._buffer.find(')', self._index) - if rparen == -1: - raise LLSDParseError("invalid string token at index %d." % self._index) - - size = int(self._buffer[self._index:rparen]) - - self._index = rparen + 1 - delim = self._buffer[self._index] - self._index += 1 - if delim not in ("'", '"'): - raise LLSDParseError("invalid string token at index %d." % self._index) - - rv = self._buffer[self._index:(self._index + size)] - self._index += size - cc = self._buffer[self._index] - self._index += 1 - if cc != delim: - raise LLSDParseError("invalid string token at index %d." % self._index) - - return rv - -def format_binary(something): - return '\n' + _format_binary_recurse(something) - -def _format_binary_recurse(something): - def _format_list(something): - array_builder = [] - array_builder.append('[' + struct.pack('!i', len(something))) - for item in something: - array_builder.append(_format_binary_recurse(item)) - array_builder.append(']') - return ''.join(array_builder) - - if something is None: - return '!' - elif isinstance(something, LLSD): - return _format_binary_recurse(something.thing) - elif isinstance(something, bool): - if something: - return '1' - else: - return '0' - elif isinstance(something, (int, long)): - return 'i' + struct.pack('!i', something) - elif isinstance(something, float): - return 'r' + struct.pack('!d', something) - elif isinstance(something, lluuid.UUID): - return 'u' + something._bits - elif isinstance(something, binary): - return 'b' + struct.pack('!i', len(something)) + something - elif isinstance(something, str): - return 's' + struct.pack('!i', len(something)) + something - elif isinstance(something, unicode): - something = something.encode('utf-8') - return 's' + struct.pack('!i', len(something)) + something - elif isinstance(something, uri): - return 'l' + struct.pack('!i', len(something)) + something - elif isinstance(something, datetime.datetime): - seconds_since_epoch = time.mktime(something.timetuple()) - return 'd' + struct.pack('!d', seconds_since_epoch) - elif isinstance(something, (list, tuple)): - return _format_list(something) - elif isinstance(something, dict): - map_builder = [] - map_builder.append('{' + struct.pack('!i', len(something))) - for key, value in something.items(): - if isinstance(key, unicode): - key = key.encode('utf-8') - map_builder.append('k' + struct.pack('!i', len(key)) + key) - map_builder.append(_format_binary_recurse(value)) - map_builder.append('}') - return ''.join(map_builder) - else: - try: - return _format_list(list(something)) - except TypeError: - raise LLSDSerializationError( - "Cannot serialize unknown type: %s (%s)" % - (type(something), something)) - - -def parse_binary(binary): - if binary.startswith(''): - just_binary = binary.split('\n', 1)[1] - else: - just_binary = binary - return LLSDBinaryParser().parse(just_binary) - -def parse_xml(something): - try: - return to_python(fromstring(something)[0]) - except ElementTreeError, err: - raise LLSDParseError(*err.args) - -def parse_notation(something): - return LLSDNotationParser().parse(something) - -def parse(something): - try: - something = string.lstrip(something) #remove any pre-trailing whitespace - if something.startswith(''): - return parse_binary(something) - # This should be better. - elif something.startswith('<'): - return parse_xml(something) - else: - return parse_notation(something) - except KeyError, e: - raise Exception('LLSD could not be parsed: %s' % (e,)) - -class LLSD(object): - def __init__(self, thing=None): - self.thing = thing - - def __str__(self): - return self.toXML(self.thing) - - parse = staticmethod(parse) - toXML = staticmethod(format_xml) - toPrettyXML = staticmethod(format_pretty_xml) - toBinary = staticmethod(format_binary) - toNotation = staticmethod(format_notation) - - -undef = LLSD(None) - -XML_MIME_TYPE = 'application/llsd+xml' -BINARY_MIME_TYPE = 'application/llsd+binary' - -# register converters for llsd in mulib, if it is available -try: - from mulib import stacked, mu - stacked.NoProducer() # just to exercise stacked - mu.safe_load(None) # just to exercise mu -except: - # mulib not available, don't print an error message since this is normal - pass -else: - mu.add_parser(parse, XML_MIME_TYPE) - mu.add_parser(parse, 'application/llsd+binary') - - def llsd_convert_xml(llsd_stuff, request): - request.write(format_xml(llsd_stuff)) - - def llsd_convert_binary(llsd_stuff, request): - request.write(format_binary(llsd_stuff)) - - for typ in [LLSD, dict, list, tuple, str, int, long, float, bool, unicode, type(None)]: - stacked.add_producer(typ, llsd_convert_xml, XML_MIME_TYPE) - stacked.add_producer(typ, llsd_convert_xml, 'application/xml') - stacked.add_producer(typ, llsd_convert_xml, 'text/xml') - - stacked.add_producer(typ, llsd_convert_binary, 'application/llsd+binary') - - stacked.add_producer(LLSD, llsd_convert_xml, '*/*') - - # in case someone is using the legacy mu.xml wrapper, we need to - # tell mu to produce application/xml or application/llsd+xml - # (based on the accept header) from raw xml. Phoenix 2008-07-21 - stacked.add_producer(mu.xml, mu.produce_raw, XML_MIME_TYPE) - stacked.add_producer(mu.xml, mu.produce_raw, 'application/xml') - - - -# mulib wsgi stuff -# try: -# from mulib import mu, adapters -# -# # try some known attributes from mulib to be ultra-sure we've imported it -# mu.get_current -# adapters.handlers -# except: -# # mulib not available, don't print an error message since this is normal -# pass -# else: -# def llsd_xml_handler(content_type): -# def handle_llsd_xml(env, start_response): -# llsd_stuff, _ = mu.get_current(env) -# result = format_xml(llsd_stuff) -# start_response("200 OK", [('Content-Type', content_type)]) -# env['mu.negotiated_type'] = content_type -# yield result -# return handle_llsd_xml -# -# def llsd_binary_handler(content_type): -# def handle_llsd_binary(env, start_response): -# llsd_stuff, _ = mu.get_current(env) -# result = format_binary(llsd_stuff) -# start_response("200 OK", [('Content-Type', content_type)]) -# env['mu.negotiated_type'] = content_type -# yield result -# return handle_llsd_binary -# -# adapters.DEFAULT_PARSERS[XML_MIME_TYPE] = parse - -# for typ in [LLSD, dict, list, tuple, str, int, float, bool, unicode, type(None)]: -# for content_type in (XML_MIME_TYPE, 'application/xml'): -# adapters.handlers.set_handler(typ, llsd_xml_handler(content_type), content_type) -# -# adapters.handlers.set_handler(typ, llsd_binary_handler(BINARY_MIME_TYPE), BINARY_MIME_TYPE) -# -# adapters.handlers.set_handler(LLSD, llsd_xml_handler(XML_MIME_TYPE), '*/*') diff --git a/indra/lib/python/indra/base/lluuid.py b/indra/lib/python/indra/base/lluuid.py deleted file mode 100644 index 7413ffe10d..0000000000 --- a/indra/lib/python/indra/base/lluuid.py +++ /dev/null @@ -1,319 +0,0 @@ -"""\ -@file lluuid.py -@brief UUID parser/generator. - -$LicenseInfo:firstyear=2004&license=mit$ - -Copyright (c) 2004-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import random, socket, string, time, re -import uuid -try: - # Python 2.6 - from hashlib import md5 -except ImportError: - # Python 2.5 and earlier - from md5 import new as md5 - -def _int2binstr(i,l): - s='' - for a in range(l): - s=chr(i&0xFF)+s - i>>=8 - return s - -def _binstr2int(s): - i = long(0) - for c in s: - i = (i<<8) + ord(c) - return i - -class UUID(object): - """ - A class which represents a 16 byte integer. Stored as a 16 byte 8 - bit character string. - - The string version is to be of the form: - AAAAAAAA-AAAA-BBBB-BBBB-BBBBBBCCCCCC (a 128-bit number in hex) - where A=network address, B=timestamp, C=random. - """ - - NULL_STR = "00000000-0000-0000-0000-000000000000" - - # the UUIDREGEX_STRING is helpful for parsing UUID's in text - hex_wildcard = r"[0-9a-fA-F]" - word = hex_wildcard + r"{4,4}-" - long_word = hex_wildcard + r"{8,8}-" - very_long_word = hex_wildcard + r"{12,12}" - UUID_REGEX_STRING = long_word + word + word + word + very_long_word - uuid_regex = re.compile(UUID_REGEX_STRING) - - rand = random.Random() - ip = '' - try: - ip = socket.gethostbyname(socket.gethostname()) - except(socket.gaierror, socket.error): - # no ip address, so just default to somewhere in 10.x.x.x - ip = '10' - for i in range(3): - ip += '.' + str(rand.randrange(1,254)) - hexip = ''.join(["%04x" % long(i) for i in ip.split('.')]) - lastid = '' - - def __init__(self, possible_uuid=None): - """ - Initialize to first valid UUID in argument (if a string), - or to null UUID if none found or argument is not supplied. - - If the argument is a UUID, the constructed object will be a copy of it. - """ - self._bits = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - if possible_uuid is None: - return - - if isinstance(possible_uuid, type(self)): - self.set(possible_uuid) - return - - uuid_match = UUID.uuid_regex.search(possible_uuid) - if uuid_match: - uuid_string = uuid_match.group() - s = string.replace(uuid_string, '-', '') - self._bits = _int2binstr(string.atol(s[:8],16),4) + \ - _int2binstr(string.atol(s[8:16],16),4) + \ - _int2binstr(string.atol(s[16:24],16),4) + \ - _int2binstr(string.atol(s[24:],16),4) - - def __len__(self): - """ - Used by the len() builtin. - """ - return 36 - - def __nonzero__(self): - return self._bits != "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - - def __str__(self): - uuid_string = self.toString() - return uuid_string - - __repr__ = __str__ - - def __getitem__(self, index): - return str(self)[index] - - def __eq__(self, other): - if isinstance(other, (str, unicode)): - return other == str(self) - return self._bits == getattr(other, '_bits', '') - - def __ne__(self, other): - return not self.__eq__(other) - - def __le__(self, other): - return self._bits <= other._bits - - def __ge__(self, other): - return self._bits >= other._bits - - def __lt__(self, other): - return self._bits < other._bits - - def __gt__(self, other): - return self._bits > other._bits - - def __hash__(self): - return hash(self._bits) - - def set(self, uuid): - self._bits = uuid._bits - - def setFromString(self, uuid_string): - """ - Given a string version of a uuid, set self bits - appropriately. Returns self. - """ - s = string.replace(uuid_string, '-', '') - self._bits = _int2binstr(string.atol(s[:8],16),4) + \ - _int2binstr(string.atol(s[8:16],16),4) + \ - _int2binstr(string.atol(s[16:24],16),4) + \ - _int2binstr(string.atol(s[24:],16),4) - return self - - def setFromMemoryDump(self, gdb_string): - """ - We expect to get gdb_string as four hex units. eg: - 0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2 - Which will be translated to: - db547d14-1b3f4bc3-9b984f71-d22f890a - Returns self. - """ - s = string.replace(gdb_string, '0x', '') - s = string.replace(s, ' ', '') - t = '' - for i in range(8,40,8): - for j in range(0,8,2): - t = t + s[i-j-2:i-j] - self.setFromString(t) - - def toString(self): - """ - Return as a string matching the LL standard - AAAAAAAA-AAAA-BBBB-BBBB-BBBBBBCCCCCC (a 128-bit number in hex) - where A=network address, B=timestamp, C=random. - """ - return uuid_bits_to_string(self._bits) - - def getAsString(self): - """ - Return a different string representation of the form - AAAAAAAA-AAAABBBB-BBBBBBBB-BBCCCCCC (a 128-bit number in hex) - where A=network address, B=timestamp, C=random. - """ - i1 = _binstr2int(self._bits[0:4]) - i2 = _binstr2int(self._bits[4:8]) - i3 = _binstr2int(self._bits[8:12]) - i4 = _binstr2int(self._bits[12:16]) - return '%08lx-%08lx-%08lx-%08lx' % (i1,i2,i3,i4) - - def generate(self): - """ - Generate a new uuid. This algorithm is slightly different - from c++ implementation for portability reasons. - Returns self. - """ - m = md5() - m.update(uuid.uuid1().bytes) - self._bits = m.digest() - return self - - def isNull(self): - """ - Returns 1 if the uuid is null - ie, equal to default uuid. - """ - return (self._bits == "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") - - def xor(self, rhs): - """ - xors self with rhs. - """ - v1 = _binstr2int(self._bits[0:4]) ^ _binstr2int(rhs._bits[0:4]) - v2 = _binstr2int(self._bits[4:8]) ^ _binstr2int(rhs._bits[4:8]) - v3 = _binstr2int(self._bits[8:12]) ^ _binstr2int(rhs._bits[8:12]) - v4 = _binstr2int(self._bits[12:16]) ^ _binstr2int(rhs._bits[12:16]) - self._bits = _int2binstr(v1,4) + \ - _int2binstr(v2,4) + \ - _int2binstr(v3,4) + \ - _int2binstr(v4,4) - - -# module-level null constant -NULL = UUID() - -def printTranslatedMemory(four_hex_uints): - """ - We expect to get the string as four hex units. eg: - 0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2 - Which will be translated to: - db547d14-1b3f4bc3-9b984f71-d22f890a - """ - uuid = UUID() - uuid.setFromMemoryDump(four_hex_uints) - print uuid.toString() - -def isUUID(id_str): - """ - This function returns: - - 1 if the string passed is a UUID - - 0 is the string passed is not a UUID - - None if it neither of the if's below is satisfied - """ - if not id_str or len(id_str) < 5 or len(id_str) > 36: - return 0 - - if isinstance(id_str, UUID) or UUID.uuid_regex.match(id_str): - return 1 - - return None - -def isPossiblyID(id_str): - """ - This function returns 1 if the string passed has some uuid-like - characteristics. Otherwise returns 0. - """ - - is_uuid = isUUID(id_str) - if is_uuid is not None: - return is_uuid - - # build a string which matches every character. - hex_wildcard = r"[0-9a-fA-F]" - chars = len(id_str) - next = min(chars, 8) - matcher = hex_wildcard+"{"+str(next)+","+str(next)+"}" - chars = chars - next - if chars > 0: - matcher = matcher + "-" - chars = chars - 1 - for block in range(3): - next = max(min(chars, 4), 0) - if next: - matcher = matcher + hex_wildcard+"{"+str(next)+","+str(next)+"}" - chars = chars - next - if chars > 0: - matcher = matcher + "-" - chars = chars - 1 - if chars > 0: - next = min(chars, 12) - matcher = matcher + hex_wildcard+"{"+str(next)+","+str(next)+"}" - #print matcher - uuid_matcher = re.compile(matcher) - if uuid_matcher.match(id_str): - return 1 - return 0 - -def uuid_bits_to_string(bits): - i1 = _binstr2int(bits[0:4]) - i2 = _binstr2int(bits[4:6]) - i3 = _binstr2int(bits[6:8]) - i4 = _binstr2int(bits[8:10]) - i5 = _binstr2int(bits[10:12]) - i6 = _binstr2int(bits[12:16]) - return '%08lx-%04lx-%04lx-%04lx-%04lx%08lx' % (i1,i2,i3,i4,i5,i6) - -def uuid_bits_to_uuid(bits): - return UUID(uuid_bits_to_string(bits)) - - -try: - from mulib import stacked - stacked.NoProducer() # just to exercise stacked -except: - #print "Couldn't import mulib.stacked, not registering UUID converter" - pass -else: - def convertUUID(uuid, req): - req.write(str(uuid)) - - stacked.add_producer(UUID, convertUUID, "*/*") - stacked.add_producer(UUID, convertUUID, "text/html") diff --git a/indra/lib/python/indra/base/metrics.py b/indra/lib/python/indra/base/metrics.py deleted file mode 100644 index ff8380265f..0000000000 --- a/indra/lib/python/indra/base/metrics.py +++ /dev/null @@ -1,121 +0,0 @@ -"""\ -@file metrics.py -@author Phoenix -@date 2007-11-27 -@brief simple interface for logging metrics - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import sys -try: - import syslog -except ImportError: - # Windows - import sys - class syslog(object): - # wrap to a lame syslog for windows - _logfp = sys.stderr - def syslog(msg): - _logfp.write(msg) - if not msg.endswith('\n'): - _logfp.write('\n') - syslog = staticmethod(syslog) - -from indra.base.llsd import format_notation - -def record_metrics(table, stats): - "Write a standard metrics log" - _log("LLMETRICS", table, stats) - -def record_event(table, data): - "Write a standard logmessage log" - _log("LLLOGMESSAGE", table, data) - -def set_destination(dest): - """Set the destination of metrics logs for this process. - - If you do not call this function prior to calling a logging - method, that function will open sys.stdout as a destination. - Attempts to set dest to None will throw a RuntimeError. - @param dest a file-like object which will be the destination for logs.""" - if dest is None: - raise RuntimeError("Attempt to unset metrics destination.") - global _destination - _destination = dest - -def destination(): - """Get the destination of the metrics logs for this process. - Returns None if no destination is set""" - global _destination - return _destination - -class SysLogger(object): - "A file-like object which writes to syslog." - def __init__(self, ident='indra', logopt = None, facility = None): - try: - if logopt is None: - logopt = syslog.LOG_CONS | syslog.LOG_PID - if facility is None: - facility = syslog.LOG_LOCAL0 - syslog.openlog(ident, logopt, facility) - import atexit - atexit.register(syslog.closelog) - except AttributeError: - # No syslog module on Windows - pass - - def write(str): - syslog.syslog(str) - write = staticmethod(write) - - def flush(): - pass - flush = staticmethod(flush) - -# -# internal API -# -_sequence_id = 0 -_destination = None - -def _next_id(): - global _sequence_id - next = _sequence_id - _sequence_id += 1 - return next - -def _dest(): - global _destination - if _destination is None: - # this default behavior is documented in the metrics functions above. - _destination = sys.stdout - return _destination - -def _log(header, table, data): - log_line = "%s (%d) %s %s" \ - % (header, _next_id(), table, format_notation(data)) - dest = _dest() - dest.write(log_line) - dest.flush() diff --git a/indra/lib/python/indra/ipc/httputil.py b/indra/lib/python/indra/ipc/httputil.py deleted file mode 100644 index c4ac0a379d..0000000000 --- a/indra/lib/python/indra/ipc/httputil.py +++ /dev/null @@ -1,9 +0,0 @@ - -import warnings - -warnings.warn("indra.ipc.httputil has been deprecated; use eventlet.httpc instead", DeprecationWarning, 2) - -from eventlet.httpc import * - - -makeConnection = make_connection diff --git a/indra/lib/python/indra/ipc/llsdhttp.py b/indra/lib/python/indra/ipc/llsdhttp.py deleted file mode 100644 index cbe8ee1eca..0000000000 --- a/indra/lib/python/indra/ipc/llsdhttp.py +++ /dev/null @@ -1,100 +0,0 @@ -"""\ -@file llsdhttp.py -@brief Functions to ease moving llsd over http - -$LicenseInfo:firstyear=2006&license=mit$ - -Copyright (c) 2006-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import os.path -import os -import urlparse - -from indra.base import llsd - -from eventlet import httpc - -suite = httpc.HttpSuite(llsd.format_xml, llsd.parse, 'application/llsd+xml') -delete = suite.delete -delete_ = suite.delete_ -get = suite.get -get_ = suite.get_ -head = suite.head -head_ = suite.head_ -post = suite.post -post_ = suite.post_ -put = suite.put -put_ = suite.put_ -request = suite.request -request_ = suite.request_ - -# import every httpc error exception into our namespace for convenience -for x in httpc.status_to_error_map.itervalues(): - globals()[x.__name__] = x -ConnectionError = httpc.ConnectionError -Retriable = httpc.Retriable - -for x in (httpc.ConnectionError,): - globals()[x.__name__] = x - - -def postFile(url, filename): - f = open(filename) - body = f.read() - f.close() - llsd_body = llsd.parse(body) - return post_(url, llsd_body) - - -# deprecated in favor of get_ -def getStatus(url, use_proxy=False): - status, _headers, _body = get_(url, use_proxy=use_proxy) - return status - -# deprecated in favor of put_ -def putStatus(url, data): - status, _headers, _body = put_(url, data) - return status - -# deprecated in favor of delete_ -def deleteStatus(url): - status, _headers, _body = delete_(url) - return status - -# deprecated in favor of post_ -def postStatus(url, data): - status, _headers, _body = post_(url, data) - return status - - -def postFileStatus(url, filename): - status, _headers, body = postFile(url, filename) - return status, body - - -def getFromSimulator(path, use_proxy=False): - return get('http://' + simulatorHostAndPort + path, use_proxy=use_proxy) - - -def postToSimulator(path, data=None): - return post('http://' + simulatorHostAndPort + path, data) diff --git a/indra/lib/python/indra/ipc/mysql_pool.py b/indra/lib/python/indra/ipc/mysql_pool.py deleted file mode 100644 index e5855a3091..0000000000 --- a/indra/lib/python/indra/ipc/mysql_pool.py +++ /dev/null @@ -1,81 +0,0 @@ -"""\ -@file mysql_pool.py -@brief Thin wrapper around eventlet.db_pool that chooses MySQLdb and Tpool. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import MySQLdb -from eventlet import db_pool - -class DatabaseConnector(db_pool.DatabaseConnector): - def __init__(self, credentials, *args, **kwargs): - super(DatabaseConnector, self).__init__(MySQLdb, credentials, - conn_pool=db_pool.ConnectionPool, - *args, **kwargs) - - # get is extended relative to eventlet.db_pool to accept a port argument - def get(self, host, dbname, port=3306): - key = (host, dbname, port) - if key not in self._databases: - new_kwargs = self._kwargs.copy() - new_kwargs['db'] = dbname - new_kwargs['host'] = host - new_kwargs['port'] = port - new_kwargs.update(self.credentials_for(host)) - dbpool = ConnectionPool(*self._args, **new_kwargs) - self._databases[key] = dbpool - - return self._databases[key] - -class ConnectionPool(db_pool.TpooledConnectionPool): - """A pool which gives out saranwrapped MySQLdb connections from a pool - """ - - def __init__(self, *args, **kwargs): - super(ConnectionPool, self).__init__(MySQLdb, *args, **kwargs) - - def get(self): - conn = super(ConnectionPool, self).get() - # annotate the connection object with the details on the - # connection; this is used elsewhere to check that you haven't - # suddenly changed databases in midstream while making a - # series of queries on a connection. - arg_names = ['host','user','passwd','db','port','unix_socket','conv','connect_timeout', - 'compress', 'named_pipe', 'init_command', 'read_default_file', 'read_default_group', - 'cursorclass', 'use_unicode', 'charset', 'sql_mode', 'client_flag', 'ssl', - 'local_infile'] - # you could have constructed this connectionpool with a mix of - # keyword and non-keyword arguments, but we want to annotate - # the connection object with a dict so it's easy to check - # against so here we are converting the list of non-keyword - # arguments (in self._args) into a dict of keyword arguments, - # and merging that with the actual keyword arguments - # (self._kwargs). The arg_names variable lists the - # constructor arguments for MySQLdb Connection objects. - converted_kwargs = dict([ (arg_names[i], arg) for i, arg in enumerate(self._args) ]) - converted_kwargs.update(self._kwargs) - conn.connection_parameters = converted_kwargs - return conn - diff --git a/indra/lib/python/indra/ipc/russ.py b/indra/lib/python/indra/ipc/russ.py deleted file mode 100644 index 35d8afb158..0000000000 --- a/indra/lib/python/indra/ipc/russ.py +++ /dev/null @@ -1,165 +0,0 @@ -"""\ -@file russ.py -@brief Recursive URL Substitution Syntax helpers -@author Phoenix - -Many details on how this should work is available on the wiki: -https://wiki.secondlife.com/wiki/Recursive_URL_Substitution_Syntax - -Adding features to this should be reflected in that page in the -implementations section. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import urllib -from indra.ipc import llsdhttp - -class UnbalancedBraces(Exception): - pass - -class UnknownDirective(Exception): - pass - -class BadDirective(Exception): - pass - -def format_value_for_path(value): - if type(value) in [list, tuple]: - # *NOTE: treat lists as unquoted path components so that the quoting - # doesn't get out-of-hand. This is a workaround for the fact that - # russ always quotes, even if the data it's given is already quoted, - # and it's not safe to simply unquote a path directly, so if we want - # russ to substitute urls parts inside other url parts we always - # have to do so via lists of unquoted path components. - return '/'.join([urllib.quote(str(item)) for item in value]) - else: - return urllib.quote(str(value)) - -def format(format_str, context): - """@brief Format format string according to rules for RUSS. -@see https://osiris.lindenlab.com/mediawiki/index.php/Recursive_URL_Substitution_Syntax -@param format_str The input string to format. -@param context A map used for string substitutions. -@return Returns the formatted string. If no match, the braces remain intact. -""" - while True: - #print "format_str:", format_str - all_matches = _find_sub_matches(format_str) - if not all_matches: - break - substitutions = 0 - while True: - matches = all_matches.pop() - # we work from right to left to make sure we do not - # invalidate positions earlier in format_str - matches.reverse() - for pos in matches: - # Use index since _find_sub_matches should have raised - # an exception, and failure to find now is an exception. - end = format_str.index('}', pos) - #print "directive:", format_str[pos+1:pos+5] - if format_str[pos + 1] == '$': - value = context[format_str[pos + 2:end]] - if value is not None: - value = format_value_for_path(value) - elif format_str[pos + 1] == '%': - value = _build_query_string( - context.get(format_str[pos + 2:end])) - elif format_str[pos+1:pos+5] == 'http' or format_str[pos+1:pos+5] == 'file': - value = _fetch_url_directive(format_str[pos + 1:end]) - else: - raise UnknownDirective, format_str[pos:end + 1] - if value is not None: - format_str = format_str[:pos]+str(value)+format_str[end+1:] - substitutions += 1 - - # If there were any substitutions at this depth, re-parse - # since this may have revealed new things to substitute - if substitutions: - break - if not all_matches: - break - - # If there were no substitutions at all, and we have exhausted - # the possible matches, bail. - if not substitutions: - break - return format_str - -def _find_sub_matches(format_str): - """@brief Find all of the substitution matches. -@param format_str the RUSS conformant format string. -@return Returns an array of depths of arrays of positional matches in input. -""" - depth = 0 - matches = [] - for pos in range(len(format_str)): - if format_str[pos] == '{': - depth += 1 - if not len(matches) == depth: - matches.append([]) - matches[depth - 1].append(pos) - continue - if format_str[pos] == '}': - depth -= 1 - continue - if not depth == 0: - raise UnbalancedBraces, format_str - return matches - -def _build_query_string(query_dict): - """\ - @breif given a dict, return a query string. utility wrapper for urllib. - @param query_dict input query dict - @returns Returns an urlencoded query string including leading '?'. - """ - if query_dict: - keys = query_dict.keys() - keys.sort() - def stringize(value): - if type(value) in (str,unicode): - return value - else: - return str(value) - query_list = [urllib.quote(str(key)) + '=' + urllib.quote(stringize(query_dict[key])) for key in keys] - return '?' + '&'.join(query_list) - else: - return '' - -def _fetch_url_directive(directive): - "*FIX: This only supports GET" - commands = directive.split('|') - resource = llsdhttp.get(commands[0]) - if len(commands) == 3: - resource = _walk_resource(resource, commands[2]) - return resource - -def _walk_resource(resource, path): - path = path.split('/') - for child in path: - if not child: - continue - resource = resource[child] - return resource diff --git a/indra/lib/python/indra/ipc/servicebuilder.py b/indra/lib/python/indra/ipc/servicebuilder.py deleted file mode 100644 index 0a0ce2b4e2..0000000000 --- a/indra/lib/python/indra/ipc/servicebuilder.py +++ /dev/null @@ -1,134 +0,0 @@ -"""\ -@file servicebuilder.py -@author Phoenix -@brief Class which will generate service urls. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -from indra.base import config -from indra.ipc import llsdhttp -from indra.ipc import russ - -# *NOTE: agent presence relies on this variable existing and being current, it is a huge hack -services_config = {} -try: - services_config = llsdhttp.get(config.get('services-config')) -except: - pass - -_g_builder = None -def _builder(): - global _g_builder - if _g_builder is None: - _g_builder = ServiceBuilder() - return _g_builder - -def build(name, context={}, **kwargs): - """ Convenience method for using a global, singleton, service builder. Pass arguments either via a dict or via python keyword arguments, or both! - - Example use: - > context = {'channel':'Second Life Release', 'version':'1.18.2.0'} - > servicebuilder.build('version-manager-version', context) - 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0' - > servicebuilder.build('version-manager-version', channel='Second Life Release', version='1.18.2.0') - 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0' - > servicebuilder.build('version-manager-version', context, version='1.18.1.2') - 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.1.2' - """ - global _g_builder - if _g_builder is None: - _g_builder = ServiceBuilder() - return _g_builder.buildServiceURL(name, context, **kwargs) - -def build_path(name, context={}, **kwargs): - context = context.copy() # shouldn't modify the caller's dictionary - context.update(kwargs) - return _builder().buildPath(name, context) - -class ServiceBuilder(object): - def __init__(self, services_definition = services_config): - """\ - @brief - @brief Create a ServiceBuilder. - @param services_definition Complete services definition, services.xml. - """ - # no need to keep a copy of the services section of the - # complete services definition, but it doesn't hurt much. - self.services = services_definition['services'] - self.builders = {} - for service in self.services: - service_builder = service.get('service-builder') - if not service_builder: - continue - if isinstance(service_builder, dict): - # We will be constructing several builders - for name, builder in service_builder.iteritems(): - full_builder_name = service['name'] + '-' + name - self.builders[full_builder_name] = builder - else: - self.builders[service['name']] = service_builder - - def buildPath(self, name, context): - """\ - @brief given the environment on construction, return a service path. - @param name The name of the service. - @param context A dict of name value lookups for the service. - @returns Returns the - """ - return russ.format(self.builders[name], context) - - def buildServiceURL(self, name, context={}, **kwargs): - """\ - @brief given the environment on construction, return a service URL. - @param name The name of the service. - @param context A dict of name value lookups for the service. - @param kwargs Any keyword arguments are treated as members of the - context, this allows you to be all 31337 by writing shit like: - servicebuilder.build('name', param=value) - @returns Returns the - """ - context = context.copy() # shouldn't modify the caller's dictionary - context.update(kwargs) - base_url = config.get('services-base-url') - svc_path = russ.format(self.builders[name], context) - return base_url + svc_path - - -def on_in(query_name, host_key, schema_key): - """\ - @brief Constructs an on/in snippet (for running named queries) - from a schema name and two keys referencing values stored in - indra.xml. - - @param query_name Name of the query. - @param host_key Logical name of destination host. Will be - looked up in indra.xml. - @param schema_key Logical name of destination schema. Will - be looked up in indra.xml. - """ - return "on/config:%s/in/config:%s/%s" % (host_key.strip('/'), - schema_key.strip('/'), - query_name.lstrip('/')) - diff --git a/indra/lib/python/indra/ipc/siesta.py b/indra/lib/python/indra/ipc/siesta.py deleted file mode 100644 index d867e71537..0000000000 --- a/indra/lib/python/indra/ipc/siesta.py +++ /dev/null @@ -1,468 +0,0 @@ -"""\ -@file siesta.py -@brief A tiny llsd based RESTful web services framework - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -from indra.base import config -from indra.base import llsd -from webob import exc -import webob -import re, socket - -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO - -try: - import cjson - json_decode = cjson.decode - json_encode = cjson.encode - JsonDecodeError = cjson.DecodeError - JsonEncodeError = cjson.EncodeError -except ImportError: - import simplejson - json_decode = simplejson.loads - json_encode = simplejson.dumps - JsonDecodeError = ValueError - JsonEncodeError = TypeError - - -llsd_parsers = { - 'application/json': json_decode, - llsd.BINARY_MIME_TYPE: llsd.parse_binary, - 'application/llsd+notation': llsd.parse_notation, - llsd.XML_MIME_TYPE: llsd.parse_xml, - 'application/xml': llsd.parse_xml, - } - - -def mime_type(content_type): - '''Given a Content-Type header, return only the MIME type.''' - - return content_type.split(';', 1)[0].strip().lower() - -class BodyLLSD(object): - '''Give a webob Request or Response an llsd based "content" property. - - Getting the content property parses the body, and caches the result. - - Setting the content property formats a payload, and the body property - is set.''' - - def _llsd__get(self): - '''Get, set, or delete the LLSD value stored in this object.''' - - try: - return self._llsd - except AttributeError: - if not self.body: - raise AttributeError('No llsd attribute has been set') - else: - mtype = mime_type(self.content_type) - try: - parser = llsd_parsers[mtype] - except KeyError: - raise exc.HTTPUnsupportedMediaType( - 'Content type %s not supported' % mtype).exception - try: - self._llsd = parser(self.body) - except (llsd.LLSDParseError, JsonDecodeError, TypeError), err: - raise exc.HTTPBadRequest( - 'Could not parse body: %r' % err.args).exception - return self._llsd - - def _llsd__set(self, val): - req = getattr(self, 'request', None) - if req is not None: - formatter, ctype = formatter_for_request(req) - self.content_type = ctype - else: - formatter, ctype = formatter_for_mime_type( - mime_type(self.content_type)) - self.body = formatter(val) - - def _llsd__del(self): - if hasattr(self, '_llsd'): - del self._llsd - - content = property(_llsd__get, _llsd__set, _llsd__del) - - -class Response(webob.Response, BodyLLSD): - '''Response class with LLSD support. - - A sensible default content type is used. - - Setting the llsd property also sets the body. Getting the llsd - property parses the body if necessary. - - If you set the body property directly, the llsd property will be - deleted.''' - - default_content_type = 'application/llsd+xml' - - def _body__set(self, body): - if hasattr(self, '_llsd'): - del self._llsd - super(Response, self)._body__set(body) - - def cache_forever(self): - self.cache_expires(86400 * 365) - - body = property(webob.Response._body__get, _body__set, - webob.Response._body__del, - webob.Response._body__get.__doc__) - - -class Request(webob.Request, BodyLLSD): - '''Request class with LLSD support. - - Sensible content type and accept headers are used by default. - - Setting the content property also sets the body. Getting the content - property parses the body if necessary. - - If you set the body property directly, the content property will be - deleted.''' - - default_content_type = 'application/llsd+xml' - default_accept = ('application/llsd+xml; q=0.5, ' - 'application/llsd+notation; q=0.3, ' - 'application/llsd+binary; q=0.2, ' - 'application/xml; q=0.1, ' - 'application/json; q=0.0') - - def __init__(self, environ=None, *args, **kwargs): - if environ is None: - environ = {} - else: - environ = environ.copy() - if 'CONTENT_TYPE' not in environ: - environ['CONTENT_TYPE'] = self.default_content_type - if 'HTTP_ACCEPT' not in environ: - environ['HTTP_ACCEPT'] = self.default_accept - super(Request, self).__init__(environ, *args, **kwargs) - - def _body__set(self, body): - if hasattr(self, '_llsd'): - del self._llsd - super(Request, self)._body__set(body) - - def path_urljoin(self, *parts): - return '/'.join([path_url.rstrip('/')] + list(parts)) - - body = property(webob.Request._body__get, _body__set, - webob.Request._body__del, webob.Request._body__get.__doc__) - - def create_response(self, content=None, status='200 OK', - conditional_response=webob.NoDefault): - resp = self.ResponseClass(status=status, request=self, - conditional_response=conditional_response) - resp.content = content - return resp - - def curl(self): - '''Create and fill out a pycurl easy object from this request.''' - - import pycurl - c = pycurl.Curl() - c.setopt(pycurl.URL, self.url()) - if self.headers: - c.setopt(pycurl.HTTPHEADER, - ['%s: %s' % (k, self.headers[k]) for k in self.headers]) - c.setopt(pycurl.FOLLOWLOCATION, True) - c.setopt(pycurl.AUTOREFERER, True) - c.setopt(pycurl.MAXREDIRS, 16) - c.setopt(pycurl.NOSIGNAL, True) - c.setopt(pycurl.READFUNCTION, self.body_file.read) - c.setopt(pycurl.SSL_VERIFYHOST, 2) - - if self.method == 'POST': - c.setopt(pycurl.POST, True) - post301 = getattr(pycurl, 'POST301', None) - if post301 is not None: - # Added in libcurl 7.17.1. - c.setopt(post301, True) - elif self.method == 'PUT': - c.setopt(pycurl.PUT, True) - elif self.method != 'GET': - c.setopt(pycurl.CUSTOMREQUEST, self.method) - return c - -Request.ResponseClass = Response -Response.RequestClass = Request - - -llsd_formatters = { - 'application/json': json_encode, - 'application/llsd+binary': llsd.format_binary, - 'application/llsd+notation': llsd.format_notation, - 'application/llsd+xml': llsd.format_xml, - 'application/xml': llsd.format_xml, - } - -formatter_qualities = ( - ('application/llsd+xml', 1.0), - ('application/llsd+notation', 0.5), - ('application/llsd+binary', 0.4), - ('application/xml', 0.3), - ('application/json', 0.2), - ) - -def formatter_for_mime_type(mime_type): - '''Return a formatter that encodes to the given MIME type. - - The result is a pair of function and MIME type.''' - try: - return llsd_formatters[mime_type], mime_type - except KeyError: - raise exc.HTTPInternalServerError( - 'Could not use MIME type %r to format response' % - mime_type).exception - - -def formatter_for_request(req): - '''Return a formatter that encodes to the preferred type of the client. - - The result is a pair of function and actual MIME type.''' - ctype = req.accept.best_match(formatter_qualities) - try: - return llsd_formatters[ctype], ctype - except KeyError: - raise exc.HTTPNotAcceptable().exception - - -def wsgi_adapter(func, environ, start_response): - '''Adapt a Siesta callable to act as a WSGI application.''' - # Process the request as appropriate. - try: - req = Request(environ) - #print req.urlvars - resp = func(req, **req.urlvars) - if not isinstance(resp, webob.Response): - try: - formatter, ctype = formatter_for_request(req) - resp = req.ResponseClass(formatter(resp), content_type=ctype) - resp._llsd = resp - except (JsonEncodeError, TypeError), err: - resp = exc.HTTPInternalServerError( - detail='Could not format response') - except exc.HTTPException, e: - resp = e - except socket.error, e: - resp = exc.HTTPInternalServerError(detail=e.args[1]) - return resp(environ, start_response) - - -def llsd_callable(func): - '''Turn a callable into a Siesta application.''' - - def replacement(environ, start_response): - return wsgi_adapter(func, environ, start_response) - - return replacement - - -def llsd_method(http_method, func): - def replacement(environ, start_response): - if environ['REQUEST_METHOD'] == http_method: - return wsgi_adapter(func, environ, start_response) - return exc.HTTPMethodNotAllowed()(environ, start_response) - - return replacement - - -http11_methods = 'OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT'.split() -http11_methods.sort() - -def llsd_class(cls): - '''Turn a class into a Siesta application. - - A new instance is created for each request. A HTTP method FOO is - turned into a call to the handle_foo method of the instance.''' - - def foo(req, **kwargs): - instance = cls() - method = req.method.lower() - try: - handler = getattr(instance, 'handle_' + method) - except AttributeError: - allowed = [m for m in http11_methods - if hasattr(instance, 'handle_' + m.lower())] - raise exc.HTTPMethodNotAllowed( - headers={'Allow': ', '.join(allowed)}).exception - #print "kwargs: ", kwargs - return handler(req, **kwargs) - - def replacement(environ, start_response): - return wsgi_adapter(foo, environ, start_response) - - return replacement - - -def curl(reqs): - import pycurl - - m = pycurl.CurlMulti() - curls = [r.curl() for r in reqs] - io = {} - for c in curls: - fp = StringIO() - hdr = StringIO() - c.setopt(pycurl.WRITEFUNCTION, fp.write) - c.setopt(pycurl.HEADERFUNCTION, hdr.write) - io[id(c)] = fp, hdr - m.handles = curls - try: - while True: - ret, num_handles = m.perform() - if ret != pycurl.E_CALL_MULTI_PERFORM: - break - finally: - m.close() - - for req, c in zip(reqs, curls): - fp, hdr = io[id(c)] - hdr.seek(0) - status = hdr.readline().rstrip() - headers = [] - name, values = None, None - - # XXX We don't currently handle bogus header data. - - for line in hdr.readlines(): - if not line[0].isspace(): - if name: - headers.append((name, ' '.join(values))) - name, value = line.strip().split(':', 1) - value = [value] - else: - values.append(line.strip()) - if name: - headers.append((name, ' '.join(values))) - - resp = c.ResponseClass(fp.getvalue(), status, headers, request=req) - - -route_re = re.compile(r''' - \{ # exact character "{" - (\w*) # "config" or variable (restricted to a-z, 0-9, _) - (?:([:~])([^}]+))? # optional :type or ~regex part - \} # exact character "}" - ''', re.VERBOSE) - -predefined_regexps = { - 'uuid': r'[a-f0-9][a-f0-9-]{31,35}', - 'int': r'\d+', - 'host': r'[a-z0-9][a-z0-9\-\.]*', - } - -def compile_route(route): - fp = StringIO() - last_pos = 0 - for match in route_re.finditer(route): - #print "matches: ", match.groups() - fp.write(re.escape(route[last_pos:match.start()])) - var_name = match.group(1) - sep = match.group(2) - expr = match.group(3) - if var_name == 'config': - expr = re.escape(str(config.get(var_name))) - else: - if expr: - if sep == ':': - expr = predefined_regexps[expr] - # otherwise, treat what follows '~' as a regexp - else: - expr = '[^/]+' - if var_name != '': - expr = '(?P<%s>%s)' % (var_name, expr) - else: - expr = '(%s)' % (expr,) - fp.write(expr) - last_pos = match.end() - fp.write(re.escape(route[last_pos:])) - compiled_route = '^%s$' % fp.getvalue() - #print route, "->", compiled_route - return compiled_route - -class Router(object): - '''WSGI routing class. Parses a URL and hands off a request to - some other WSGI application. If no suitable application is found, - responds with a 404.''' - - def __init__(self): - self._new_routes = [] - self._routes = [] - self._paths = [] - - def add(self, route, app, methods=None): - self._new_routes.append((route, app, methods)) - - def _create_routes(self): - for route, app, methods in self._new_routes: - self._paths.append(route) - self._routes.append( - (re.compile(compile_route(route)), - app, - methods and dict.fromkeys(methods))) - self._new_routes = [] - - def __call__(self, environ, start_response): - # load up the config from the config file. Only needs to be - # done once per interpreter. This is the entry point of all - # siesta applications, so this is where we trap it. - _conf = config.get_config() - if _conf is None: - import os.path - fname = os.path.join( - environ.get('ll.config_dir', '/local/linden/etc'), - 'indra.xml') - config.load(fname) - - # proceed with handling the request - self._create_routes() - path_info = environ['PATH_INFO'] - request_method = environ['REQUEST_METHOD'] - allowed = [] - for regex, app, methods in self._routes: - m = regex.match(path_info) - if m: - #print "groupdict:",m.groupdict() - if not methods or request_method in methods: - environ['paste.urlvars'] = m.groupdict() - return app(environ, start_response) - else: - allowed += methods - if allowed: - allowed = dict.fromkeys(allows).keys() - allowed.sort() - resp = exc.HTTPMethodNotAllowed( - headers={'Allow': ', '.join(allowed)}) - else: - resp = exc.HTTPNotFound() - return resp(environ, start_response) diff --git a/indra/lib/python/indra/ipc/siesta_test.py b/indra/lib/python/indra/ipc/siesta_test.py deleted file mode 100644 index 177ea710d1..0000000000 --- a/indra/lib/python/indra/ipc/siesta_test.py +++ /dev/null @@ -1,214 +0,0 @@ -from indra.base import llsd, lluuid -from indra.ipc import siesta -import datetime, math, unittest -from webob import exc - - -class ClassApp(object): - def handle_get(self, req): - pass - - def handle_post(self, req): - return req.llsd - - -def callable_app(req): - if req.method == 'UNDERPANTS': - raise exc.HTTPMethodNotAllowed() - elif req.method == 'GET': - return None - return req.llsd - - -class TestBase: - def test_basic_get(self): - req = siesta.Request.blank('/') - self.assertEquals(req.get_response(self.server).body, - llsd.format_xml(None)) - - def test_bad_method(self): - req = siesta.Request.blank('/') - req.environ['REQUEST_METHOD'] = 'UNDERPANTS' - self.assertEquals(req.get_response(self.server).status_int, - exc.HTTPMethodNotAllowed.code) - - json_safe = { - 'none': None, - 'bool_true': True, - 'bool_false': False, - 'int_zero': 0, - 'int_max': 2147483647, - 'int_min': -2147483648, - 'long_zero': 0, - 'long_max': 2147483647L, - 'long_min': -2147483648L, - 'float_zero': 0, - 'float': math.pi, - 'float_huge': 3.14159265358979323846e299, - 'str_empty': '', - 'str': 'foo', - u'unic\u1e51de_empty': u'', - u'unic\u1e51de': u'\u1e4exx\u10480', - } - json_safe['array'] = json_safe.values() - json_safe['tuple'] = tuple(json_safe.values()) - json_safe['dict'] = json_safe.copy() - - json_unsafe = { - 'uuid_empty': lluuid.UUID(), - 'uuid_full': lluuid.UUID('dc61ab0530200d7554d23510559102c1a98aab1b'), - 'binary_empty': llsd.binary(), - 'binary': llsd.binary('f\0\xff'), - 'uri_empty': llsd.uri(), - 'uri': llsd.uri('http://www.secondlife.com/'), - 'datetime_empty': datetime.datetime(1970,1,1), - 'datetime': datetime.datetime(1999,9,9,9,9,9), - } - json_unsafe.update(json_safe) - json_unsafe['array'] = json_unsafe.values() - json_unsafe['tuple'] = tuple(json_unsafe.values()) - json_unsafe['dict'] = json_unsafe.copy() - json_unsafe['iter'] = iter(json_unsafe.values()) - - def _test_client_content_type_good(self, content_type, ll): - def run(ll): - req = siesta.Request.blank('/') - req.environ['REQUEST_METHOD'] = 'POST' - req.content_type = content_type - req.llsd = ll - req.accept = content_type - resp = req.get_response(self.server) - self.assertEquals(resp.status_int, 200) - return req, resp - - if False and isinstance(ll, dict): - def fixup(v): - if isinstance(v, float): - return '%.5f' % v - if isinstance(v, long): - return int(v) - if isinstance(v, (llsd.binary, llsd.uri)): - return v - if isinstance(v, (tuple, list)): - return [fixup(i) for i in v] - if isinstance(v, dict): - return dict([(k, fixup(i)) for k, i in v.iteritems()]) - return v - for k, v in ll.iteritems(): - l = [k, v] - req, resp = run(l) - self.assertEquals(fixup(resp.llsd), fixup(l)) - - run(ll) - - def test_client_content_type_json_good(self): - self._test_client_content_type_good('application/json', self.json_safe) - - def test_client_content_type_llsd_xml_good(self): - self._test_client_content_type_good('application/llsd+xml', - self.json_unsafe) - - def test_client_content_type_llsd_notation_good(self): - self._test_client_content_type_good('application/llsd+notation', - self.json_unsafe) - - def test_client_content_type_llsd_binary_good(self): - self._test_client_content_type_good('application/llsd+binary', - self.json_unsafe) - - def test_client_content_type_xml_good(self): - self._test_client_content_type_good('application/xml', - self.json_unsafe) - - def _test_client_content_type_bad(self, content_type): - req = siesta.Request.blank('/') - req.environ['REQUEST_METHOD'] = 'POST' - req.body = '\0invalid nonsense under all encodings' - req.content_type = content_type - self.assertEquals(req.get_response(self.server).status_int, - exc.HTTPBadRequest.code) - - def test_client_content_type_json_bad(self): - self._test_client_content_type_bad('application/json') - - def test_client_content_type_llsd_xml_bad(self): - self._test_client_content_type_bad('application/llsd+xml') - - def test_client_content_type_llsd_notation_bad(self): - self._test_client_content_type_bad('application/llsd+notation') - - def test_client_content_type_llsd_binary_bad(self): - self._test_client_content_type_bad('application/llsd+binary') - - def test_client_content_type_xml_bad(self): - self._test_client_content_type_bad('application/xml') - - def test_client_content_type_bad(self): - req = siesta.Request.blank('/') - req.environ['REQUEST_METHOD'] = 'POST' - req.body = 'XXX' - req.content_type = 'application/nonsense' - self.assertEquals(req.get_response(self.server).status_int, - exc.HTTPUnsupportedMediaType.code) - - def test_request_default_content_type(self): - req = siesta.Request.blank('/') - self.assertEquals(req.content_type, req.default_content_type) - - def test_request_default_accept(self): - req = siesta.Request.blank('/') - from webob import acceptparse - self.assertEquals(str(req.accept).replace(' ', ''), - req.default_accept.replace(' ', '')) - - def test_request_llsd_auto_body(self): - req = siesta.Request.blank('/') - req.llsd = {'a': 2} - self.assertEquals(req.body, '' - 'a2') - - def test_request_llsd_mod_body_changes_llsd(self): - req = siesta.Request.blank('/') - req.llsd = {'a': 2} - req.body = '1337' - self.assertEquals(req.llsd, 1337) - - def test_request_bad_llsd_fails(self): - def crashme(ctype): - def boom(): - class foo(object): pass - req = siesta.Request.blank('/') - req.content_type = ctype - req.llsd = foo() - for mime_type in siesta.llsd_parsers: - self.assertRaises(TypeError, crashme(mime_type)) - - -class ClassServer(TestBase, unittest.TestCase): - def __init__(self, *args, **kwargs): - unittest.TestCase.__init__(self, *args, **kwargs) - self.server = siesta.llsd_class(ClassApp) - - -class CallableServer(TestBase, unittest.TestCase): - def __init__(self, *args, **kwargs): - unittest.TestCase.__init__(self, *args, **kwargs) - self.server = siesta.llsd_callable(callable_app) - - -class RouterServer(unittest.TestCase): - def test_router(self): - def foo(req, quux): - print quux - - r = siesta.Router() - r.add('/foo/{quux:int}', siesta.llsd_callable(foo), methods=['GET']) - req = siesta.Request.blank('/foo/33') - req.get_response(r) - - req = siesta.Request.blank('/foo/bar') - self.assertEquals(req.get_response(r).status_int, - exc.HTTPNotFound.code) - -if __name__ == '__main__': - unittest.main() diff --git a/indra/lib/python/indra/ipc/webdav.py b/indra/lib/python/indra/ipc/webdav.py deleted file mode 100644 index 98b8499b6a..0000000000 --- a/indra/lib/python/indra/ipc/webdav.py +++ /dev/null @@ -1,597 +0,0 @@ -""" -@file webdav.py -@brief Classes to make manipulation of a webdav store easier. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import sys, os, httplib, urlparse -import socket, time -import xml.dom.minidom -import syslog -# import signal - -__revision__ = '0' - -dav_debug = False - - -# def urlsafe_b64decode (enc): -# return base64.decodestring (enc.replace ('_', '/').replace ('-', '+')) - -# def urlsafe_b64encode (str): -# return base64.encodestring (str).replace ('+', '-').replace ('/', '_') - - -class DAVError (Exception): - """ Base class for exceptions in this module. """ - def __init__ (self, status=0, message='', body='', details=''): - self.status = status - self.message = message - self.body = body - self.details = details - Exception.__init__ (self, '%d:%s:%s%s' % (self.status, self.message, - self.body, self.details)) - - def print_to_stderr (self): - """ print_to_stderr docstring """ - print >> sys.stderr, str (self.status) + ' ' + self.message - print >> sys.stderr, str (self.details) - - -class Timeout (Exception): - """ Timeout docstring """ - def __init__ (self, arg=''): - Exception.__init__ (self, arg) - - -def alarm_handler (signum, frame): - """ alarm_handler docstring """ - raise Timeout ('caught alarm') - - -class WebDAV: - """ WebDAV docstring """ - def __init__ (self, url, proxy=None, retries_before_fail=6): - self.init_url = url - self.init_proxy = proxy - self.retries_before_fail = retries_before_fail - url_parsed = urlparse.urlsplit (url) - - self.top_path = url_parsed[ 2 ] - # make sure top_path has a trailing / - if self.top_path == None or self.top_path == '': - self.top_path = '/' - elif len (self.top_path) > 1 and self.top_path[-1:] != '/': - self.top_path += '/' - - if dav_debug: - syslog.syslog ('new WebDAV %s : %s' % (str (url), str (proxy))) - - if proxy: - proxy_parsed = urlparse.urlsplit (proxy) - self.host_header = url_parsed[ 1 ] - host_and_port = proxy_parsed[ 1 ].split (':') - self.host = host_and_port[ 0 ] - if len (host_and_port) > 1: - self.port = int(host_and_port[ 1 ]) - else: - self.port = 80 - else: # no proxy - host_and_port = url_parsed[ 1 ].split (':') - self.host_header = None - self.host = host_and_port[ 0 ] - if len (host_and_port) > 1: - self.port = int(host_and_port[ 1 ]) - else: - self.port = 80 - - self.connection = False - self.connect () - - - def log (self, msg, depth=0): - """ log docstring """ - if dav_debug and depth == 0: - host = str (self.init_url) - if host == 'http://int.tuco.lindenlab.com:80/asset/': - host = 'tuco' - if host == 'http://harriet.lindenlab.com/asset-keep/': - host = 'harriet/asset-keep' - if host == 'http://harriet.lindenlab.com/asset-flag/': - host = 'harriet/asset-flag' - if host == 'http://harriet.lindenlab.com/asset/': - host = 'harriet/asset' - if host == 'http://ozzy.lindenlab.com/asset/': - host = 'ozzy/asset' - if host == 'http://station11.lindenlab.com:12041/:': - host = 'station11:12041' - proxy = str (self.init_proxy) - if proxy == 'None': - proxy = '' - if proxy == 'http://int.tuco.lindenlab.com:3128/': - proxy = 'tuco' - syslog.syslog ('WebDAV (%s:%s) %s' % (host, proxy, str (msg))) - - - def connect (self): - """ connect docstring """ - self.log ('connect') - self.connection = httplib.HTTPConnection (self.host, self.port) - - def __err (self, response, details): - """ __err docstring """ - raise DAVError (response.status, response.reason, response.read (), - str (self.init_url) + ':' + \ - str (self.init_proxy) + ':' + str (details)) - - def request (self, method, path, body=None, headers=None, - read_all=True, body_hook = None, recurse=0, allow_cache=True): - """ request docstring """ - # self.log ('request %s %s' % (method, path)) - if headers == None: - headers = {} - if not allow_cache: - headers['Pragma'] = 'no-cache' - headers['cache-control'] = 'no-cache' - try: - if method.lower () != 'purge': - if path.startswith ('/'): - path = path[1:] - if self.host_header: # use proxy - headers[ 'host' ] = self.host_header - fullpath = 'http://%s%s%s' % (self.host_header, - self.top_path, path) - else: # no proxy - fullpath = self.top_path + path - else: - fullpath = path - - self.connection.request (method, fullpath, body, headers) - if body_hook: - body_hook () - - # signal.signal (signal.SIGALRM, alarm_handler) - # try: - # signal.alarm (120) - # signal.alarm (0) - # except Timeout, e: - # if recurse < 6: - # return self.retry_request (method, path, body, headers, - # read_all, body_hook, recurse) - # else: - # raise DAVError (0, 'timeout', self.host, - # (method, path, body, headers, recurse)) - - response = self.connection.getresponse () - - if read_all: - while len (response.read (1024)) > 0: - pass - if (response.status == 500 or \ - response.status == 503 or \ - response.status == 403) and \ - recurse < self.retries_before_fail: - return self.retry_request (method, path, body, headers, - read_all, body_hook, recurse) - return response - except (httplib.ResponseNotReady, - httplib.BadStatusLine, - socket.error): - # if the server hangs up on us (keepalive off, broken pipe), - # we need to reconnect and try again. - if recurse < self.retries_before_fail: - return self.retry_request (method, path, body, headers, - read_all, body_hook, recurse) - raise DAVError (0, 'reconnect failed', self.host, - (method, path, body, headers, recurse)) - - - def retry_request (self, method, path, body, headers, - read_all, body_hook, recurse): - """ retry_request docstring """ - time.sleep (10.0 * recurse) - self.connect () - return self.request (method, path, body, headers, - read_all, body_hook, recurse+1) - - - - def propfind (self, path, body=None, depth=1): - """ propfind docstring """ - # self.log ('propfind %s' % path) - headers = {'Content-Type':'text/xml; charset="utf-8"', - 'Depth':str(depth)} - response = self.request ('PROPFIND', path, body, headers, False) - if response.status == 207: - return response # Multi-Status - self.__err (response, ('PROPFIND', path, body, headers, 0)) - - - def purge (self, path): - """ issue a squid purge command """ - headers = {'Accept':'*/*'} - response = self.request ('PURGE', path, None, headers) - if response.status == 200 or response.status == 404: - # 200 if it was purge, 404 if it wasn't there. - return response - self.__err (response, ('PURGE', path, None, headers)) - - - def get_file_size (self, path): - """ - Use propfind to ask a webdav server what the size of - a file is. If used on a directory (collection) return 0 - """ - self.log ('get_file_size %s' % path) - # "getcontentlength" property - # 8.1.1 Example - Retrieving Named Properties - # http://docs.python.org/lib/module-xml.dom.html - nsurl = 'http://apache.org/dav/props/' - doc = xml.dom.minidom.Document () - propfind_element = doc.createElementNS (nsurl, "D:propfind") - propfind_element.setAttributeNS (nsurl, 'xmlns:D', 'DAV:') - doc.appendChild (propfind_element) - prop_element = doc.createElementNS (nsurl, "D:prop") - propfind_element.appendChild (prop_element) - con_len_element = doc.createElementNS (nsurl, "D:getcontentlength") - prop_element.appendChild (con_len_element) - - response = self.propfind (path, doc.toxml ()) - doc.unlink () - - resp_doc = xml.dom.minidom.parseString (response.read ()) - cln = resp_doc.getElementsByTagNameNS ('DAV:','getcontentlength')[ 0 ] - try: - content_length = int (cln.childNodes[ 0 ].nodeValue) - except IndexError: - return 0 - resp_doc.unlink () - return content_length - - - def file_exists (self, path): - """ - do an http head on the given file. return True if it succeeds - """ - self.log ('file_exists %s' % path) - expect_gzip = path.endswith ('.gz') - response = self.request ('HEAD', path) - got_gzip = response.getheader ('Content-Encoding', '').strip () - if got_gzip.lower () == 'x-gzip' and expect_gzip == False: - # the asset server fakes us out if we ask for the non-gzipped - # version of an asset, but the server has the gzipped version. - return False - return response.status == 200 - - - def mkdir (self, path): - """ mkdir docstring """ - self.log ('mkdir %s' % path) - headers = {} - response = self.request ('MKCOL', path, None, headers) - if response.status == 201: - return # success - if response.status == 405: - return # directory already existed? - self.__err (response, ('MKCOL', path, None, headers, 0)) - - - def delete (self, path): - """ delete docstring """ - self.log ('delete %s' % path) - headers = {'Depth':'infinity'} # collections require infinity - response = self.request ('DELETE', path, None, headers) - if response.status == 204: - return # no content - if response.status == 404: - return # hmm - self.__err (response, ('DELETE', path, None, headers, 0)) - - - def list_directory (self, path, dir_filter=None, allow_cache=True, - minimum_cache_time=False): - """ - Request an http directory listing and parse the filenames out of lines - like: '
  • X'. If a filter function is provided, - only return filenames that the filter returns True for. - - This is sort of grody, but it seems faster than other ways of getting - this information from an isilon. - """ - self.log ('list_directory %s' % path) - - def try_match (lline, before, after): - """ try_match docstring """ - try: - blen = len (before) - asset_start_index = lline.index (before) - asset_end_index = lline.index (after, asset_start_index + blen) - asset = line[ asset_start_index + blen : asset_end_index ] - - if not dir_filter or dir_filter (asset): - return [ asset ] - return [] - except ValueError: - return [] - - if len (path) > 0 and path[-1:] != '/': - path += '/' - - response = self.request ('GET', path, None, {}, False, - allow_cache=allow_cache) - - if allow_cache and minimum_cache_time: # XXX - print response.getheader ('Date') - # s = "2005-12-06T12:13:14" - # from datetime import datetime - # from time import strptime - # datetime(*strptime(s, "%Y-%m-%dT%H:%M:%S")[0:6]) - # datetime.datetime(2005, 12, 6, 12, 13, 14) - - if response.status != 200: - self.__err (response, ('GET', path, None, {}, 0)) - assets = [] - for line in response.read ().split ('\n'): - lline = line.lower () - if lline.find ("parent directory") == -1: - # isilon file - assets += try_match (lline, '
  • ') - # apache dir - assets += try_match (lline, 'alt="[dir]"> ') - # apache file - assets += try_match (lline, 'alt="[ ]"> ') - return assets - - - def __tmp_filename (self, path_and_file): - """ __tmp_filename docstring """ - head, tail = os.path.split (path_and_file) - if head != '': - return head + '/.' + tail + '.' + str (os.getpid ()) - else: - return head + '.' + tail + '.' + str (os.getpid ()) - - - def __put__ (self, filesize, body_hook, remotefile): - """ __put__ docstring """ - headers = {'Content-Length' : str (filesize)} - remotefile_tmp = self.__tmp_filename (remotefile) - response = self.request ('PUT', remotefile_tmp, None, - headers, True, body_hook) - if not response.status in (201, 204): # created, no content - self.__err (response, ('PUT', remotefile, None, headers, 0)) - if filesize != self.get_file_size (remotefile_tmp): - try: - self.delete (remotefile_tmp) - except: - pass - raise DAVError (0, 'tmp upload error', remotefile_tmp) - # move the file to its final location - try: - self.rename (remotefile_tmp, remotefile) - except DAVError, exc: - if exc.status == 403: # try to clean up the tmp file - try: - self.delete (remotefile_tmp) - except: - pass - raise - if filesize != self.get_file_size (remotefile): - raise DAVError (0, 'file upload error', str (remotefile_tmp)) - - - def put_string (self, strng, remotefile): - """ put_string docstring """ - self.log ('put_string %d -> %s' % (len (strng), remotefile)) - filesize = len (strng) - def body_hook (): - """ body_hook docstring """ - self.connection.send (strng) - self.__put__ (filesize, body_hook, remotefile) - - - def put_file (self, localfile, remotefile): - """ - Send a local file to a remote webdav store. First, upload to - a temporary filename. Next make sure the file is the size we - expected. Next, move the file to its final location. Next, - check the file size at the final location. - """ - self.log ('put_file %s -> %s' % (localfile, remotefile)) - filesize = os.path.getsize (localfile) - def body_hook (): - """ body_hook docstring """ - handle = open (localfile) - while True: - data = handle.read (1300) - if len (data) == 0: - break - self.connection.send (data) - handle.close () - self.__put__ (filesize, body_hook, remotefile) - - - def create_empty_file (self, remotefile): - """ create an empty file """ - self.log ('touch_file %s' % (remotefile)) - headers = {'Content-Length' : '0'} - response = self.request ('PUT', remotefile, None, headers) - if not response.status in (201, 204): # created, no content - self.__err (response, ('PUT', remotefile, None, headers, 0)) - if self.get_file_size (remotefile) != 0: - raise DAVError (0, 'file upload error', str (remotefile)) - - - def __get_file_setup (self, remotefile, check_size=True): - """ __get_file_setup docstring """ - if check_size: - remotesize = self.get_file_size (remotefile) - response = self.request ('GET', remotefile, None, {}, False) - if response.status != 200: - self.__err (response, ('GET', remotefile, None, {}, 0)) - try: - content_length = int (response.getheader ("Content-Length")) - except TypeError: - content_length = None - if check_size: - if content_length != remotesize: - raise DAVError (0, 'file DL size error', remotefile) - return (response, content_length) - - - def __get_file_read (self, writehandle, response, content_length): - """ __get_file_read docstring """ - if content_length != None: - so_far_length = 0 - while so_far_length < content_length: - data = response.read (content_length - so_far_length) - if len (data) == 0: - raise DAVError (0, 'short file download') - so_far_length += len (data) - writehandle.write (data) - while len (response.read ()) > 0: - pass - else: - while True: - data = response.read () - if (len (data) < 1): - break - writehandle.write (data) - - - def get_file (self, remotefile, localfile, check_size=True): - """ - Get a remote file from a webdav server. Download to a local - tmp file, then move into place. Sanity check file sizes as - we go. - """ - self.log ('get_file %s -> %s' % (remotefile, localfile)) - (response, content_length) = \ - self.__get_file_setup (remotefile, check_size) - localfile_tmp = self.__tmp_filename (localfile) - handle = open (localfile_tmp, 'w') - self.__get_file_read (handle, response, content_length) - handle.close () - if check_size: - if content_length != os.path.getsize (localfile_tmp): - raise DAVError (0, 'file DL size error', - remotefile+','+localfile) - os.rename (localfile_tmp, localfile) - - - def get_file_as_string (self, remotefile, check_size=True): - """ - download a file from a webdav server and return it as a string. - """ - self.log ('get_file_as_string %s' % remotefile) - (response, content_length) = \ - self.__get_file_setup (remotefile, check_size) - # (tmp_handle, tmp_filename) = tempfile.mkstemp () - tmp_handle = os.tmpfile () - self.__get_file_read (tmp_handle, response, content_length) - tmp_handle.seek (0) - ret = tmp_handle.read () - tmp_handle.close () - # os.unlink (tmp_filename) - return ret - - - def get_post_as_string (self, remotefile, body): - """ - Do an http POST, send body, get response and return it. - """ - self.log ('get_post_as_string %s' % remotefile) - # headers = {'Content-Type':'application/x-www-form-urlencoded'} - headers = {'Content-Type':'text/xml; charset="utf-8"'} - # b64body = urlsafe_b64encode (asset_url) - response = self.request ('POST', remotefile, body, headers, False) - if response.status != 200: - self.__err (response, ('POST', remotefile, body, headers, 0)) - try: - content_length = int (response.getheader ('Content-Length')) - except TypeError: - content_length = None - tmp_handle = os.tmpfile () - self.__get_file_read (tmp_handle, response, content_length) - tmp_handle.seek (0) - ret = tmp_handle.read () - tmp_handle.close () - return ret - - - def __destination_command (self, verb, remotesrc, dstdav, remotedst): - """ - self and dstdav should point to the same http server. - """ - if len (remotedst) > 0 and remotedst[ 0 ] == '/': - remotedst = remotedst[1:] - headers = {'Destination': 'http://%s:%d%s%s' % (dstdav.host, - dstdav.port, - dstdav.top_path, - remotedst)} - response = self.request (verb, remotesrc, None, headers) - if response.status == 201: - return # created - if response.status == 204: - return # no content - self.__err (response, (verb, remotesrc, None, headers, 0)) - - - def rename (self, remotesrc, remotedst): - """ rename a file on a webdav server """ - self.log ('rename %s -> %s' % (remotesrc, remotedst)) - self.__destination_command ('MOVE', remotesrc, self, remotedst) - def xrename (self, remotesrc, dstdav, remotedst): - """ rename a file on a webdav server """ - self.log ('xrename %s -> %s' % (remotesrc, remotedst)) - self.__destination_command ('MOVE', remotesrc, dstdav, remotedst) - - - def copy (self, remotesrc, remotedst): - """ copy a file on a webdav server """ - self.log ('copy %s -> %s' % (remotesrc, remotedst)) - self.__destination_command ('COPY', remotesrc, self, remotedst) - def xcopy (self, remotesrc, dstdav, remotedst): - """ copy a file on a webdav server """ - self.log ('xcopy %s -> %s' % (remotesrc, remotedst)) - self.__destination_command ('COPY', remotesrc, dstdav, remotedst) - - -def put_string (data, url): - """ - upload string s to a url - """ - url_parsed = urlparse.urlsplit (url) - dav = WebDAV ('%s://%s/' % (url_parsed[ 0 ], url_parsed[ 1 ])) - dav.put_string (data, url_parsed[ 2 ]) - - -def get_string (url, check_size=True): - """ - return the contents of a url as a string - """ - url_parsed = urlparse.urlsplit (url) - dav = WebDAV ('%s://%s/' % (url_parsed[ 0 ], url_parsed[ 1 ])) - return dav.get_file_as_string (url_parsed[ 2 ], check_size) diff --git a/indra/lib/python/indra/ipc/xml_rpc.py b/indra/lib/python/indra/ipc/xml_rpc.py deleted file mode 100644 index 47536c10c3..0000000000 --- a/indra/lib/python/indra/ipc/xml_rpc.py +++ /dev/null @@ -1,273 +0,0 @@ -"""\ -@file xml_rpc.py -@brief An implementation of a parser/generator for the XML-RPC xml format. - -$LicenseInfo:firstyear=2006&license=mit$ - -Copyright (c) 2006-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - - -from greenlet import greenlet - -from mulib import mu - -from xml.sax import handler -from xml.sax import parseString - - -# States -class Expected(object): - def __init__(self, tag): - self.tag = tag - - def __getattr__(self, name): - return type(self)(name) - - def __repr__(self): - return '%s(%r)' % ( - type(self).__name__, self.tag) - - -class START(Expected): - pass - - -class END(Expected): - pass - - -class STR(object): - tag = '' - - -START = START('') -END = END('') - - -class Malformed(Exception): - pass - - -class XMLParser(handler.ContentHandler): - def __init__(self, state_machine, next_states): - handler.ContentHandler.__init__(self) - self.state_machine = state_machine - if not isinstance(next_states, tuple): - next_states = (next_states, ) - self.next_states = next_states - self._character_buffer = '' - - def assertState(self, state, name, *rest): - if not isinstance(self.next_states, tuple): - self.next_states = (self.next_states, ) - for next in self.next_states: - if type(state) == type(next): - if next.tag and next.tag != name: - raise Malformed( - "Expected %s, got %s %s %s" % ( - next, state, name, rest)) - break - else: - raise Malformed( - "Expected %s, got %s %s %s" % ( - self.next_states, state, name, rest)) - - def startElement(self, name, attrs): - self.assertState(START, name.lower(), attrs) - self.next_states = self.state_machine.switch(START, (name.lower(), dict(attrs))) - - def endElement(self, name): - if self._character_buffer.strip(): - characters = self._character_buffer.strip() - self._character_buffer = '' - self.assertState(STR, characters) - self.next_states = self.state_machine.switch(characters) - self.assertState(END, name.lower()) - self.next_states = self.state_machine.switch(END, name.lower()) - - def error(self, exc): - self.bozo = 1 - self.exc = exc - - def fatalError(self, exc): - self.error(exc) - raise exc - - def characters(self, characters): - self._character_buffer += characters - - -def parse(what): - child = greenlet(xml_rpc) - me = greenlet.getcurrent() - startup_states = child.switch(me) - parser = XMLParser(child, startup_states) - try: - parseString(what, parser) - except Malformed: - print what - raise - return child.switch() - - -def xml_rpc(yielder): - yielder.switch(START.methodcall) - yielder.switch(START.methodname) - methodName = yielder.switch(STR) - yielder.switch(END.methodname) - - yielder.switch(START.params) - - root = None - params = [] - while True: - state, _ = yielder.switch(START.param, END.params) - if state == END: - break - - yielder.switch(START.value) - - params.append( - handle(yielder)) - - yielder.switch(END.value) - yielder.switch(END.param) - - yielder.switch(END.methodcall) - ## Resume parse - yielder.switch() - ## Return result to parse - return methodName.strip(), params - - -def handle(yielder): - _, (tag, attrs) = yielder.switch(START) - if tag in ['int', 'i4']: - result = int(yielder.switch(STR)) - elif tag == 'boolean': - result = bool(int(yielder.switch(STR))) - elif tag == 'string': - result = yielder.switch(STR) - elif tag == 'double': - result = float(yielder.switch(STR)) - elif tag == 'datetime.iso8601': - result = yielder.switch(STR) - elif tag == 'base64': - result = base64.b64decode(yielder.switch(STR)) - elif tag == 'struct': - result = {} - while True: - state, _ = yielder.switch(START.member, END.struct) - if state == END: - break - - yielder.switch(START.name) - key = yielder.switch(STR) - yielder.switch(END.name) - - yielder.switch(START.value) - result[key] = handle(yielder) - yielder.switch(END.value) - - yielder.switch(END.member) - ## We already handled above, don't want to handle it below - return result - elif tag == 'array': - result = [] - yielder.switch(START.data) - while True: - state, _ = yielder.switch(START.value, END.data) - if state == END: - break - - result.append(handle(yielder)) - - yielder.switch(END.value) - - yielder.switch(getattr(END, tag)) - - return result - - -VALUE = mu.tag_factory('value') -BOOLEAN = mu.tag_factory('boolean') -INT = mu.tag_factory('int') -STRUCT = mu.tag_factory('struct') -MEMBER = mu.tag_factory('member') -NAME = mu.tag_factory('name') -ARRAY = mu.tag_factory('array') -DATA = mu.tag_factory('data') -STRING = mu.tag_factory('string') -DOUBLE = mu.tag_factory('double') -METHODRESPONSE = mu.tag_factory('methodResponse') -PARAMS = mu.tag_factory('params') -PARAM = mu.tag_factory('param') - -mu.inline_elements['string'] = True -mu.inline_elements['boolean'] = True -mu.inline_elements['name'] = True - - -def _generate(something): - if isinstance(something, dict): - result = STRUCT() - for key, value in something.items(): - result[ - MEMBER[ - NAME[key], _generate(value)]] - return VALUE[result] - elif isinstance(something, list): - result = DATA() - for item in something: - result[_generate(item)] - return VALUE[ARRAY[[result]]] - elif isinstance(something, basestring): - return VALUE[STRING[something]] - elif isinstance(something, bool): - if something: - return VALUE[BOOLEAN['1']] - return VALUE[BOOLEAN['0']] - elif isinstance(something, int): - return VALUE[INT[something]] - elif isinstance(something, float): - return VALUE[DOUBLE[something]] - -def generate(*args): - params = PARAMS() - for arg in args: - params[PARAM[_generate(arg)]] - return METHODRESPONSE[params] - - -if __name__ == '__main__': - print parse(""" examples.getStateName 41 -""") - - - - - - - - - diff --git a/indra/lib/python/indra/util/fastest_elementtree.py b/indra/lib/python/indra/util/fastest_elementtree.py deleted file mode 100644 index 3e2189c4e7..0000000000 --- a/indra/lib/python/indra/util/fastest_elementtree.py +++ /dev/null @@ -1,65 +0,0 @@ -"""\ -@file fastest_elementtree.py -@brief Concealing some gnarly import logic in here. This should export the interface of elementtree. - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -# The parsing exception raised by the underlying library depends -# on the ElementTree implementation we're using, so we provide an -# alias here. -# -# Use ElementTreeError as the exception type for catching parsing -# errors. - - -# Using cElementTree might cause some unforeseen problems, so here's a -# convenient off switch. - -use_celementree = True - -try: - if not use_celementree: - raise ImportError() - # Python 2.3 and 2.4. - from cElementTree import * - ElementTreeError = SyntaxError -except ImportError: - try: - if not use_celementree: - raise ImportError() - # Python 2.5 and above. - from xml.etree.cElementTree import * - ElementTreeError = SyntaxError - except ImportError: - # Pure Python code. - try: - # Python 2.3 and 2.4. - from elementtree.ElementTree import * - except ImportError: - # Python 2.5 and above. - from xml.etree.ElementTree import * - - # The pure Python ElementTree module uses Expat for parsing. - from xml.parsers.expat import ExpatError as ElementTreeError diff --git a/indra/lib/python/indra/util/helpformatter.py b/indra/lib/python/indra/util/helpformatter.py deleted file mode 100644 index ba5c9b67d1..0000000000 --- a/indra/lib/python/indra/util/helpformatter.py +++ /dev/null @@ -1,52 +0,0 @@ -"""\ -@file helpformatter.py -@author Phoenix -@brief Class for formatting optparse descriptions. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import optparse -import textwrap - -class Formatter(optparse.IndentedHelpFormatter): - def __init__( - self, - p_indentIncrement = 2, - p_maxHelpPosition = 24, - p_width = 79, - p_shortFirst = 1) : - optparse.HelpFormatter.__init__( - self, - p_indentIncrement, - p_maxHelpPosition, - p_width, - p_shortFirst) - def format_description(self, p_description): - t_descWidth = self.width - self.current_indent - t_indent = " " * (self.current_indent + 2) - return "\n".join( - [textwrap.fill(descr, t_descWidth, initial_indent = t_indent, - subsequent_indent = t_indent) - for descr in p_description.split("\n")] ) diff --git a/indra/lib/python/indra/util/iterators.py b/indra/lib/python/indra/util/iterators.py deleted file mode 100644 index 9013fa6303..0000000000 --- a/indra/lib/python/indra/util/iterators.py +++ /dev/null @@ -1,63 +0,0 @@ -"""\ -@file iterators.py -@brief Useful general-purpose iterators. - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -from __future__ import nested_scopes - -def iter_chunks(rows, aggregate_size=100): - """ - Given an iterable set of items (@p rows), produces lists of up to @p - aggregate_size items at a time, for example: - - iter_chunks([1,2,3,4,5,6,7,8,9,10], 3) - - Values for @p aggregate_size < 1 will raise ValueError. - - Will return a generator that produces, in the following order: - - [1, 2, 3] - - [4, 5, 6] - - [7, 8, 9] - - [10] - """ - if aggregate_size < 1: - raise ValueError() - - def iter_chunks_inner(): - row_iter = iter(rows) - done = False - agg = [] - while not done: - try: - row = row_iter.next() - agg.append(row) - except StopIteration: - done = True - if agg and (len(agg) >= aggregate_size or done): - yield agg - agg = [] - - return iter_chunks_inner() diff --git a/indra/lib/python/indra/util/iterators_test.py b/indra/lib/python/indra/util/iterators_test.py deleted file mode 100755 index 66928c8e7d..0000000000 --- a/indra/lib/python/indra/util/iterators_test.py +++ /dev/null @@ -1,72 +0,0 @@ -"""\ -@file iterators_test.py -@brief Test cases for iterators module. - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import unittest - -from indra.util.iterators import iter_chunks - -class TestIterChunks(unittest.TestCase): - """Unittests for iter_chunks""" - def test_bad_agg_size(self): - rows = [1,2,3,4] - self.assertRaises(ValueError, iter_chunks, rows, 0) - self.assertRaises(ValueError, iter_chunks, rows, -1) - - try: - for i in iter_chunks(rows, 0): - pass - except ValueError: - pass - else: - self.fail() - - try: - result = list(iter_chunks(rows, 0)) - except ValueError: - pass - else: - self.fail() - def test_empty(self): - rows = [] - result = list(iter_chunks(rows)) - self.assertEqual(result, []) - def test_small(self): - rows = [[1]] - result = list(iter_chunks(rows, 2)) - self.assertEqual(result, [[[1]]]) - def test_size(self): - rows = [[1],[2]] - result = list(iter_chunks(rows, 2)) - self.assertEqual(result, [[[1],[2]]]) - def test_multi_agg(self): - rows = [[1],[2],[3],[4],[5]] - result = list(iter_chunks(rows, 2)) - self.assertEqual(result, [[[1],[2]],[[3],[4]],[[5]]]) - -if __name__ == "__main__": - unittest.main() diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 0059faa2ee..b285b46c7d 100644 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -33,13 +33,26 @@ import fnmatch import getopt import glob +import itertools +import operator import os import re import shutil +import subprocess import sys import tarfile -import errno -import subprocess + +class ManifestError(RuntimeError): + """Use an exception more specific than generic Python RuntimeError""" + def __init__(self, msg): + self.msg = msg + super(ManifestError, self).__init__(self.msg) + +class MissingError(ManifestError): + """You specified a file that doesn't exist""" + def __init__(self, msg): + self.msg = msg + super(MissingError, self).__init__(self.msg) def path_ancestors(path): drive, path = os.path.splitdrive(os.path.normpath(path)) @@ -76,33 +89,11 @@ def get_default_platform(dummy): 'darwin':'darwin' }[sys.platform] -def get_default_version(srctree): - # look up llversion.h and parse out the version info - paths = [os.path.join(srctree, x, 'llversionviewer.h') for x in ['llcommon', '../llcommon', '../../indra/llcommon.h']] - for p in paths: - if os.path.exists(p): - contents = open(p, 'r').read() - major = re.search("LL_VERSION_MAJOR\s=\s([0-9]+)", contents).group(1) - minor = re.search("LL_VERSION_MINOR\s=\s([0-9]+)", contents).group(1) - patch = re.search("LL_VERSION_PATCH\s=\s([0-9]+)", contents).group(1) - build = re.search("LL_VERSION_BUILD\s=\s([0-9]+)", contents).group(1) - return major, minor, patch, build - -def get_channel(srctree): - # look up llversionserver.h and parse out the version info - paths = [os.path.join(srctree, x, 'llversionviewer.h') for x in ['llcommon', '../llcommon', '../../indra/llcommon.h']] - for p in paths: - if os.path.exists(p): - contents = open(p, 'r').read() - channel = re.search("LL_CHANNEL\s=\s\"(.+)\";\s*$", contents, flags = re.M).group(1) - return channel - - DEFAULT_SRCTREE = os.path.dirname(sys.argv[0]) -DEFAULT_CHANNEL = 'Second Life Release' -DEFAULT_CHANNEL_SNOWGLOBE = 'Snowglobe Release' +CHANNEL_VENDOR_BASE = 'Singularity' +RELEASE_CHANNEL = CHANNEL_VENDOR_BASE + ' Release' -ARGUMENTS=[ +BASE_ARGUMENTS=[ dict(name='actions', description="""This argument specifies the actions that are to be taken when the script is run. The meaningful actions are currently: @@ -120,28 +111,23 @@ def get_channel(srctree): Example use: %(name)s --arch=i686 On Linux this would try to use Linux_i686Manifest.""", default=""), + dict(name='artwork', description='Artwork directory.', default=DEFAULT_SRCTREE), + dict(name='branding_id', description="Identifier for the branding set to use.", default='singularity'), dict(name='build', description='Build directory.', default=DEFAULT_SRCTREE), - dict(name='buildtype', description="""The build type used. ('Debug', 'Release', or 'RelWithDebInfo') - Default is Release """, - default="Release"), - dict(name='branding_id', description="""Identifier for the branding set to - use. Currently, 'secondlife' or 'snowglobe')""", - default='secondlife'), + dict(name='buildtype', description='Build type (i.e. Debug, Release, RelWithDebInfo).', default=None), + dict(name='channel', + description="""The channel to use for updates, packaging, settings name, etc.""", + default='CHANNEL UNSET'), + dict(name='channel_suffix', + description="""Addition to the channel for packaging and channel value, + but not application name (used internally)""", + default=None), dict(name='configuration', - description="""The build configuration used. Only used on OS X for - now, but it could be used for other platforms as well.""", - default="Universal"), + description="""The build configuration used.""", + default="Release"), dict(name='dest', description='Destination directory.', default=DEFAULT_SRCTREE), dict(name='grid', - description="""Which grid the client will try to connect to. Even - though it's not strictly a grid, 'firstlook' is also an acceptable - value for this parameter.""", - default=""), - dict(name='channel', - description="""The channel to use for updates, packaging, settings name, etc.""", - default=get_channel), - dict(name='login_channel', - description="""The channel to use for login handshake/updates only.""", + description="""Which grid the client will try to connect to.""", default=None), dict(name='installer_name', description=""" The name of the file that the installer should be @@ -154,34 +140,33 @@ def get_channel(srctree): description="""The current platform, to be used for looking up which manifest class to run.""", default=get_default_platform), + dict(name='signature', + description="""This specifies an identity to sign the viewer with, if any. + If no value is supplied, the default signature will be used, if any. Currently + only used on Mac OS X.""", + default=None), dict(name='source', description='Source directory.', default=DEFAULT_SRCTREE), dict(name='standalone', description='Set to ON if this is a standalone build.', default="OFF"), - dict(name='artwork', description='Artwork directory.', default=DEFAULT_SRCTREE), dict(name='touch', description="""File to touch when action is finished. Touch file will contain the name of the final package in a form suitable for use by a .bat file.""", default=None), - dict(name='version', - description="""This specifies the version of Second Life that is - being packaged up.""", - default=get_default_version), - dict(name='extra_libraries', - description="""List of extra libraries to include in package""", - default=None) + dict(name='versionfile', + description="""The name of a file containing the full version number."""), ] -def usage(srctree=""): +def usage(arguments, srctree=""): nd = {'name':sys.argv[0]} print """Usage: %(name)s [options] [destdir] Options: """ % nd - for arg in ARGUMENTS: + for arg in arguments: default = arg['default'] if hasattr(default, '__call__'): default = "(computed value) \"" + str(default(srctree)) + '"' @@ -192,10 +177,15 @@ def usage(srctree=""): default, arg['description'] % nd) -def main(): - print "cwd:", os.getcwd() - print " ".join(sys.argv) - option_names = [arg['name'] + '=' for arg in ARGUMENTS] +def main(extra=[]): +## print ' '.join((("'%s'" % item) if ' ' in item else item) +## for item in itertools.chain([sys.executable], sys.argv)) + # Supplement our default command-line switches with any desired by + # application-specific caller. + arguments = list(itertools.chain(BASE_ARGUMENTS, extra)) + # Alphabetize them by option name in case we display usage. + arguments.sort(key=operator.itemgetter('name')) + option_names = [arg['name'] + '=' for arg in arguments] option_names.append('help') options, remainder = getopt.getopt(sys.argv[1:], "", option_names) @@ -218,11 +208,11 @@ def main(): # early out for help if 'help' in args: # *TODO: it is a huge hack to pass around the srctree like this - usage(args['source']) + usage(arguments, srctree=args['source']) return # defaults - for arg in ARGUMENTS: + for arg in arguments: if arg['name'] not in args: default = arg['default'] if hasattr(default, '__call__'): @@ -231,12 +221,17 @@ def main(): args[arg['name']] = default # fix up version - if isinstance(args.get('version'), str): - args['version'] = args['version'].split('.') - - # default and agni are default - if args['grid'] in ['default', 'agni']: - args['grid'] = '' + if isinstance(args.get('versionfile'), str): + try: # read in the version string + vf = open(args['versionfile'], 'r') + args['version'] = vf.read().strip().split('.') + except: + print "Unable to read versionfile '%s'" % args['versionfile'] + raise + + # unspecified, default, and agni are default + if args['grid'] in ['', 'default', 'agni']: + args['grid'] = None if 'actions' in args: args['actions'] = args['actions'].split() @@ -245,16 +240,69 @@ def main(): for opt in args: print "Option:", opt, "=", args[opt] + # pass in sourceid as an argument now instead of an environment variable + args['sourceid'] = os.environ.get("sourceid", "") + + # Build base package. + touch = args.get('touch') + if touch: + print '================ Creating base package' + else: + print '================ Starting base copy' wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args) wm.do(*args['actions']) - + # Store package file for later if making touched file. + base_package_file = "" + if touch: + print '================ Created base package ', wm.package_file + base_package_file = "" + wm.package_file + else: + print '================ Finished base copy' + + # handle multiple packages if set + # ''.split() produces empty list + additional_packages = os.environ.get("additional_packages", "").split() + if additional_packages: + # Determine destination prefix / suffix for additional packages. + base_dest_parts = list(os.path.split(args['dest'])) + base_dest_parts.insert(-1, "{}") + base_dest_template = os.path.join(*base_dest_parts) + # Determine touched prefix / suffix for additional packages. + if touch: + base_touch_parts = list(os.path.split(touch)) + # Because of the special insert() logic below, we don't just want + # [dirpath, basename]; we want [dirpath, directory, basename]. + # Further split the dirpath and replace it in the list. + base_touch_parts[0:1] = os.path.split(base_touch_parts[0]) + if "arwin" in args['platform']: + base_touch_parts.insert(-1, "{}") + else: + base_touch_parts.insert(-2, "{}") + base_touch_template = os.path.join(*base_touch_parts) + for package_id in additional_packages: + args['channel_suffix'] = os.environ.get(package_id + "_viewer_channel_suffix") + args['sourceid'] = os.environ.get(package_id + "_sourceid") + args['dest'] = base_dest_template.format(package_id) + if touch: + print '================ Creating additional package for "', package_id, '" in ', args['dest'] + else: + print '================ Starting additional copy for "', package_id, '" in ', args['dest'] + try: + wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args) + wm.do(*args['actions']) + except Exception as err: + sys.exit(str(err)) + if touch: + print '================ Created additional package ', wm.package_file, ' for ', package_id + with open(base_touch_template.format(package_id), 'w') as fp: + fp.write('set package_file=%s\n' % wm.package_file) + else: + print '================ Finished additional copy "', package_id, '" in ', args['dest'] # Write out the package file in this format, so that it can easily be called # and used in a .bat file - yeah, it sucks, but this is the simplest... - touch = args.get('touch') if touch: - fp = open(touch, 'w') - fp.write('set package_file=%s\n' % wm.package_file) - fp.close() + with open(touch, 'w') as fp: + fp.write('set package_file=%s\n' % base_package_file) print 'touched', touch return 0 @@ -269,8 +317,8 @@ class LLManifest(object): __metaclass__ = LLManifestRegistry manifests = {} def for_platform(self, platform, arch = None): - if arch and platform != "windows": - platform = platform + '_' + arch + if arch: + platform = platform + '_' + arch + '_' return self.manifests[platform.lower()] for_platform = classmethod(for_platform) @@ -280,26 +328,15 @@ def __init__(self, args): self.file_list = [] self.excludes = [] self.actions = [] - self.src_prefix = list([args['source']]) - self.artwork_prefix = list([args['artwork']]) - self.build_prefix = list([args['build']]) - self.alt_build_prefix = list([args['build']]) - self.dst_prefix = list([args['dest']]) + self.src_prefix = [args['source']] + self.artwork_prefix = [args['artwork']] + self.build_prefix = [args['build']] + self.dst_prefix = [args['dest']] self.created_paths = [] self.package_name = "Unknown" - - def default_grid(self): - return self.args.get('grid', None) == '' + def default_channel(self): - return self.args.get('channel', None) == DEFAULT_CHANNEL - - def default_channel_for_brand(self): - if self.viewer_branding_id()=='secondlife': - return self.args.get('channel', None) == DEFAULT_CHANNEL - elif self.viewer_branding_id()=="snowglobe": - return self.args.get('channel', None) == DEFAULT_CHANNEL_SNOWGLOBE - else: - return True + return self.args.get('channel', None) == RELEASE_CHANNEL def construct(self): """ Meant to be overriden by LLManifest implementors with code that @@ -311,27 +348,113 @@ def exclude(self, glob): in the file list by path().""" self.excludes.append(glob) - def prefix(self, src='', build=None, dst=None, alt_build=None): - """ Pushes a prefix onto the stack. Until end_prefix is - called, all relevant method calls (esp. to path()) will prefix - paths with the entire prefix stack. Source and destination - prefixes can be different, though if only one is provided they - are both equal. To specify a no-op, use an empty string, not - None.""" - if dst is None: - dst = src - if build is None: - build = src - if alt_build is None: - alt_build = build + def prefix(self, src='', build='', dst='', src_dst=None): + """ + Usage: + + with self.prefix(...args as described...): + self.path(...) + + For the duration of the 'with' block, pushes a prefix onto the stack. + Within that block, all relevant method calls (esp. to path()) will + prefix paths with the entire prefix stack. Source and destination + prefixes are independent; if omitted (or passed as the empty string), + the prefix has no effect. Thus: + + with self.prefix(src='foo'): + # no effect on dst + + with self.prefix(dst='bar'): + # no effect on src + If you want to set both at once, use src_dst: + + with self.prefix(src_dst='subdir'): + # same as self.prefix(src='subdir', dst='subdir') + # Passing src_dst makes any src or dst argument in the same + # parameter list irrelevant. + + Also supports the older (pre-Python-2.5) syntax: + + if self.prefix(...args as described...): + self.path(...) + self.end_prefix(...) + + Before the arrival of the 'with' statement, one was required to code + self.prefix() and self.end_prefix() in matching pairs to push and to + pop the prefix stacks, respectively. The older prefix() method + returned True specifically so that the caller could indent the + relevant block of code with 'if', just for aesthetic purposes. + """ + if src_dst is not None: + src = src_dst + dst = src_dst self.src_prefix.append(src) self.artwork_prefix.append(src) self.build_prefix.append(build) self.dst_prefix.append(dst) - self.alt_build_prefix.append(alt_build) - return True # so that you can wrap it in an if to get indentation +## self.display_stacks() + + # The above code is unchanged from the original implementation. What's + # new is the return value. We're going to return an instance of + # PrefixManager that binds this LLManifest instance and Does The Right + # Thing on exit. + return self.PrefixManager(self) + + def display_stacks(self): + width = 1 + max(len(stack) for stack in self.PrefixManager.stacks) + for stack in self.PrefixManager.stacks: + print "{} {}".format((stack + ':').ljust(width), + os.path.join(*getattr(self, stack))) + + class PrefixManager(object): + # stack attributes we manage in this LLManifest (sub)class + # instance + stacks = ("src_prefix", "artwork_prefix", "build_prefix", "dst_prefix") + + def __init__(self, manifest): + self.manifest = manifest + # If the caller wrote: + # with self.prefix(...): + # as intended, then bind the state of each prefix stack as it was + # just BEFORE the call to prefix(). Since prefix() appended an + # entry to each prefix stack, capture len()-1. + self.prevlen = { stack: len(getattr(self.manifest, stack)) - 1 + for stack in self.stacks } + + def __nonzero__(self): + # If the caller wrote: + # if self.prefix(...): + # then a value of this class had better evaluate as 'True'. + return True + + def __enter__(self): + # nobody uses 'with self.prefix(...) as variable:' + return None + + def __exit__(self, type, value, traceback): + # First, if the 'with' block raised an exception, just propagate. + # Do NOT swallow it. + if type is not None: + return False + + # Okay, 'with' block completed successfully. Restore previous + # state of each of the prefix stacks in self.stacks. + # Note that we do NOT simply call pop() on them as end_prefix() + # does. This is to cope with the possibility that the coder + # changed 'if self.prefix(...):' to 'with self.prefix(...):' yet + # forgot to remove the self.end_prefix(...) call at the bottom of + # the block. In that case, calling pop() again would be Bad! But + # if we restore the length of each stack to what it was before the + # current prefix() block, it doesn't matter whether end_prefix() + # was called or not. + for stack, prevlen in self.prevlen.items(): + # find the attribute in 'self.manifest' named by 'stack', and + # truncate that list back to 'prevlen' + del getattr(self.manifest, stack)[prevlen:] + +## self.manifest.display_stacks() def end_prefix(self, descr=None): """Pops a prefix off the stack. If given an argument, checks @@ -343,30 +466,25 @@ def end_prefix(self, descr=None): src = self.src_prefix.pop() artwork = self.artwork_prefix.pop() build = self.build_prefix.pop() - alt_build_prefix = self.alt_build_prefix.pop() dst = self.dst_prefix.pop() if descr and not(src == descr or build == descr or dst == descr): raise ValueError, "End prefix '" + descr + "' didn't match '" +src+ "' or '" +dst + "'" def get_src_prefix(self): """ Returns the current source prefix.""" - return os.path.relpath(os.path.normpath(os.path.join(*self.src_prefix))) + return os.path.join(*self.src_prefix) def get_artwork_prefix(self): """ Returns the current artwork prefix.""" - return os.path.relpath(os.path.normpath(os.path.join(*self.artwork_prefix))) + return os.path.join(*self.artwork_prefix) def get_build_prefix(self): """ Returns the current build prefix.""" - return os.path.relpath(os.path.normpath(os.path.join(*self.build_prefix))) - - def get_alt_build_prefix(self): - """ Returns the current alternate source prefix.""" - return os.path.relpath(os.path.normpath(os.path.join(*self.alt_build_prefix))) + return os.path.join(*self.build_prefix) def get_dst_prefix(self): """ Returns the current destination prefix.""" - return os.path.relpath(os.path.normpath(os.path.join(*self.dst_prefix))) + return os.path.join(*self.dst_prefix) def src_path_of(self, relpath): """Returns the full path to a file or directory specified @@ -383,40 +501,72 @@ def dst_path_of(self, relpath): relative to the destination directory.""" return os.path.join(self.get_dst_prefix(), relpath) + def _relative_dst_path(self, dstpath): + """ + Returns the path to a file or directory relative to the destination directory. + This should only be used for generating diagnostic output in the path method. + """ + dest_root=self.dst_prefix[0] + if dstpath.startswith(dest_root+os.path.sep): + return dstpath[len(dest_root)+1:] + elif dstpath.startswith(dest_root): + return dstpath[len(dest_root):] + else: + return dstpath + + def ensure_src_dir(self, reldir): + """Construct the path for a directory relative to the + source path, and ensures that it exists. Returns the + full path.""" + path = os.path.join(self.get_src_prefix(), reldir) + self.cmakedirs(path) + return path + + def ensure_dst_dir(self, reldir): + """Construct the path for a directory relative to the + destination path, and ensures that it exists. Returns the + full path.""" + path = os.path.join(self.get_dst_prefix(), reldir) + self.cmakedirs(path) + return path + def run_command(self, command): - """ Runs an external command, and returns the output. Raises - an exception if the command reurns a nonzero status code. For - debugging/informational purpoases, prints out the command's - output as it is received.""" + """ + Runs an external command. + Raises ManifestError exception if the command returns a nonzero status. + """ print "Running command:", command - fd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - lines = [] - while True: - lines.append(fd.stdout.readline()) - if lines[-1] == '': - break - else: - print lines[-1].rstrip('\n'), - output = ''.join(lines) - if fd.returncode: - raise RuntimeError( - "Command %s returned non-zero status (%s) \noutput:\n%s" - % (command, fd.returncode, output) ) - return output + sys.stdout.flush() + try: + subprocess.check_call(command) + except subprocess.CalledProcessError as err: + raise ManifestError( "Command %s returned non-zero status (%s)" + % (command, err.returncode) ) def created_path(self, path): """ Declare that you've created a path in order to a) verify that you really have created it b) schedule it for cleanup""" if not os.path.exists(path): - raise RuntimeError, "Should be something at path " + path + raise ManifestError, "Should be something at path " + path self.created_paths.append(path) - def put_in_file(self, contents, dst): + def put_in_file(self, contents, dst, src=None): # write contents as dst - f = open(self.dst_path_of(dst), "wb") - f.write(contents) - f.close() + dst_path = self.dst_path_of(dst) + self.cmakedirs(os.path.dirname(dst_path)) + f = open(dst_path, "wb") + try: + f.write(contents) + finally: + f.close() + + # Why would we create a file in the destination tree if not to include + # it in the installer? The default src=None (plus the fact that the + # src param is last) is to preserve backwards compatibility. + if src: + self.file_list.append([src, dst_path]) + return dst_path def replace_in(self, src, dst=None, searchdict={}): if dst == None: @@ -436,11 +586,7 @@ def copy_action(self, src, dst): # ensure that destination path exists self.cmakedirs(os.path.dirname(dst)) self.created_paths.append(dst) - if not os.path.isdir(src): - self.ccopy(src,dst) - else: - # src is a dir - self.ccopytree(src,dst) + self.ccopymumble(src, dst) else: print "Doesn't exist:", src @@ -470,39 +616,42 @@ def cleanup_finish(self): # *TODO is this gonna be useful? print "Cleaning up " + c + def process_either(self, src, dst): + # If it's a real directory, recurse through it -- + # but not a symlink! Handle those like files. + if os.path.isdir(src) and not os.path.islink(src): + return self.process_directory(src, dst) + else: + return self.process_file(src, dst) + def process_file(self, src, dst): if self.includes(src, dst): -# print src, "=>", dst for action in self.actions: methodname = action + "_action" method = getattr(self, methodname, None) if method is not None: method(src, dst) self.file_list.append([src, dst]) - return [dst] + return 1 else: sys.stdout.write(" (excluding %r, %r)" % (src, dst)) sys.stdout.flush() - return [] + return 0 def process_directory(self, src, dst): if not self.includes(src, dst): sys.stdout.write(" (excluding %r, %r)" % (src, dst)) sys.stdout.flush() - return [] + return 0 names = os.listdir(src) self.cmakedirs(dst) errors = [] - found_files = [] count = 0 for name in names: srcname = os.path.join(src, name) dstname = os.path.join(dst, name) - if os.path.isdir(srcname): - found_files.extend(self.process_directory(srcname, dstname)) - else: - found_files.extend(self.process_file(srcname, dstname)) - return found_files + count += self.process_either(srcname, dstname) + return count def includes(self, src, dst): if src: @@ -520,28 +669,43 @@ def remove(self, *paths): else: os.remove(path) - def ccopy(self, src, dst): - """ Copy a single file or symlink. Uses filecmp to skip copying for existing files.""" + def ccopymumble(self, src, dst): + """Copy a single symlink, file or directory.""" if os.path.islink(src): linkto = os.readlink(src) - if os.path.islink(dst) or os.path.exists(dst): + if os.path.islink(dst) or os.path.isfile(dst): os.remove(dst) # because symlinking over an existing link fails + elif os.path.isdir(dst): + shutil.rmtree(dst) os.symlink(linkto, dst) + elif os.path.isdir(src): + self.ccopytree(src, dst) else: - # Don't recopy file if it's up-to-date. - # If we seem to be not not overwriting files that have been - # updated, set the last arg to False, but it will take longer. - if os.path.exists(dst) and filecmp.cmp(src, dst, True): - return - # only copy if it's not excluded - if self.includes(src, dst): - try: - os.unlink(dst) - except OSError, err: - if err.errno != errno.ENOENT: - raise - - shutil.copy2(src, dst) + self.ccopyfile(src, dst) + # XXX What about devices, sockets etc.? + # YYY would we put such things into a viewer package?! + + def ccopyfile(self, src, dst): + """ Copy a single file. Uses filecmp to skip copying for existing files.""" + # Don't recopy file if it's up-to-date. + # If we seem to be not not overwriting files that have been + # updated, set the last arg to False, but it will take longer. +## reldst = (dst[len(self.dst_prefix[0]):] +## if dst.startswith(self.dst_prefix[0]) +## else dst).lstrip(r'\/') + if os.path.exists(dst) and filecmp.cmp(src, dst, True): +## print "{} (skipping, {} exists)".format(src, reldst) + return + # only copy if it's not excluded + if self.includes(src, dst): + try: + os.unlink(dst) + except OSError as err: + if err.errno != errno.ENOENT: + raise + +## print "{} => {}".format(src, reldst) + shutil.copy2(src, dst) def ccopytree(self, src, dst): """Direct copy of shutil.copytree with the additional @@ -557,15 +721,11 @@ def ccopytree(self, src, dst): srcname = os.path.join(src, name) dstname = os.path.join(dst, name) try: - if os.path.isdir(srcname): - self.ccopytree(srcname, dstname) - else: - self.ccopy(srcname, dstname) - # XXX What about devices, sockets etc.? - except (IOError, os.error), why: + self.ccopymumble(srcname, dstname) + except (IOError, os.error) as why: errors.append((srcname, dstname, why)) if errors: - raise RuntimeError, errors + raise ManifestError, errors def cmakedirs(self, path): @@ -582,11 +742,25 @@ def find_existing_file(self, *list): if os.path.exists(f): return f # didn't find it, return last item in list - if list: + if len(list) > 0: return list[-1] else: return None + def contents_of_tar(self, src_tar, dst_dir): + """ Extracts the contents of the tarfile (specified + relative to the source prefix) into the directory + specified relative to the destination directory.""" + self.check_file_exists(src_tar) + tf = tarfile.open(self.src_path_of(src_tar), 'r') + for member in tf.getmembers(): + tf.extract(member, self.ensure_dst_dir(dst_dir)) + # TODO get actions working on these dudes, perhaps we should extract to a temporary directory and then process_directory on it? + self.file_list.append([src_tar, + self.dst_path_of(os.path.join(dst_dir,member.name))]) + tf.close() + + def wildcard_regex(self, src_glob, dst_glob): src_re = re.escape(src_glob) src_re = src_re.replace('\*', '([-a-zA-Z0-9._ ]*)') @@ -597,7 +771,12 @@ def wildcard_regex(self, src_glob, dst_glob): i = i+1 return re.compile(src_re), dst_temp - wildcard_pattern = re.compile('\*') + def check_file_exists(self, path): + if not os.path.exists(path) and not os.path.islink(path): + raise MissingError("Path %s doesn't exist" % (os.path.abspath(path),)) + + + wildcard_pattern = re.compile(r'\*') def expand_globs(self, src, dst): src_list = glob.glob(src) src_re, d_template = self.wildcard_regex(src.replace('\\', '/'), @@ -626,41 +805,43 @@ def path2basename(self, path, file): def path(self, src, dst=None): sys.stdout.flush() if src == None: - raise RuntimeError("No source file, dst is " + dst) + raise ManifestError("No source file, dst is " + dst) if dst == None: dst = src dst = os.path.join(self.get_dst_prefix(), dst) - sys.stdout.write("Processing %s => %s ... " % (src, dst)) - count = 0 - is_glob = False - found_files = [] - - # look under each prefix for matching paths. Paths are normalized so './../blah' will match '../blah/../blah/' - paths = set([os.path.normpath(os.path.join(self.get_src_prefix(), src)), - os.path.normpath(os.path.join(self.get_artwork_prefix(), src)), - os.path.normpath(os.path.join(self.get_build_prefix(), src)), - os.path.normpath(os.path.join(self.get_alt_build_prefix(), src))] - ) - for path in paths: - if self.wildcard_pattern.search(path): - is_glob = True - for s,d in self.expand_globs(path, dst): + sys.stdout.write("Processing %s => %s ... " % (src, self._relative_dst_path(dst))) + + def try_path(src): + # expand globs + count = 0 + if self.wildcard_pattern.search(src): + for s,d in self.expand_globs(src, dst): assert(s != d) - found_files.extend(self.process_file(s, d)) + count += self.process_file(s, d) else: - # if it's a directory, recurse through it - if os.path.isdir(path): - found_files.extend(self.process_directory(path, dst)) - elif os.path.exists(path): - found_files.extend(self.process_file(path, dst)) - - # if we're specifying a single path (not a glob), - # we should error out if it doesn't exist - if not found_files and not is_glob: - raise RuntimeError("No files match %s\n" % str(paths)) - - print "%d files" % len(found_files) - return found_files + # if we're specifying a single path (not a glob), + # we should error out if it doesn't exist + self.check_file_exists(src) + count += self.process_either(src, dst) + return count + + try_prefixes = [self.get_src_prefix(), self.get_artwork_prefix(), self.get_build_prefix()] + tried=[] + count=0 + while not count and try_prefixes: + pfx = try_prefixes.pop(0) + try: + count = try_path(os.path.join(pfx, src)) + except MissingError: + tried.append(pfx) + if not try_prefixes: + # no more prefixes left to try + print "unable to find '%s'; looked in:\n %s" % (src, '\n '.join(tried)) + print "%d files" % count + + # Let caller check whether we processed as many files as expected. In + # particular, let caller notice 0. + return count def do(self, *actions): self.actions = actions diff --git a/indra/lib/python/indra/util/llperformance.py b/indra/lib/python/indra/util/llperformance.py deleted file mode 100755 index 57dd64de3f..0000000000 --- a/indra/lib/python/indra/util/llperformance.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env python -"""\ -@file llperformance.py - -$LicenseInfo:firstyear=2010&license=viewerlgpl$ -Second Life Viewer Source Code -Copyright (C) 2010-2011, 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$ -""" - -# ------------------------------------------------ -# Sim metrics utility functions. - -import glob, os, time, sys, stat, exceptions - -from indra.base import llsd - -gBlockMap = {} #Map of performance metric data with function hierarchy information. -gCurrentStatPath = "" - -gIsLoggingEnabled=False - -class LLPerfStat: - def __init__(self,key): - self.mTotalTime = 0 - self.mNumRuns = 0 - self.mName=key - self.mTimeStamp = int(time.time()*1000) - self.mUTCTime = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) - - def __str__(self): - return "%f" % self.mTotalTime - - def start(self): - self.mStartTime = int(time.time() * 1000000) - self.mNumRuns += 1 - - def stop(self): - execution_time = int(time.time() * 1000000) - self.mStartTime - self.mTotalTime += execution_time - - def get_map(self): - results={} - results['name']=self.mName - results['utc_time']=self.mUTCTime - results['timestamp']=self.mTimeStamp - results['us']=self.mTotalTime - results['count']=self.mNumRuns - return results - -class PerfError(exceptions.Exception): - def __init__(self): - return - - def __Str__(self): - print "","Unfinished LLPerfBlock" - -class LLPerfBlock: - def __init__( self, key ): - global gBlockMap - global gCurrentStatPath - global gIsLoggingEnabled - - #Check to see if we're running metrics right now. - if gIsLoggingEnabled: - self.mRunning = True #Mark myself as running. - - self.mPreviousStatPath = gCurrentStatPath - gCurrentStatPath += "/" + key - if gCurrentStatPath not in gBlockMap: - gBlockMap[gCurrentStatPath] = LLPerfStat(key) - - self.mStat = gBlockMap[gCurrentStatPath] - self.mStat.start() - - def finish( self ): - global gBlockMap - global gIsLoggingEnabled - - if gIsLoggingEnabled: - self.mStat.stop() - self.mRunning = False - gCurrentStatPath = self.mPreviousStatPath - -# def __del__( self ): -# if self.mRunning: -# #SPATTERS FIXME -# raise PerfError - -class LLPerformance: - #-------------------------------------------------- - # Determine whether or not we want to log statistics - - def __init__( self, process_name = "python" ): - self.process_name = process_name - self.init_testing() - self.mTimeStamp = int(time.time()*1000) - self.mUTCTime = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) - - def init_testing( self ): - global gIsLoggingEnabled - - host_performance_file = "/dev/shm/simperf/simperf_proc_config.llsd" - - #If file exists, open - if os.path.exists(host_performance_file): - file = open (host_performance_file,'r') - - #Read serialized LLSD from file. - body = llsd.parse(file.read()) - - #Calculate time since file last modified. - stats = os.stat(host_performance_file) - now = time.time() - mod = stats[stat.ST_MTIME] - age = now - mod - - if age < ( body['duration'] ): - gIsLoggingEnabled = True - - - def get ( self ): - global gIsLoggingEnabled - return gIsLoggingEnabled - - #def output(self,ptr,path): - # if 'stats' in ptr: - # stats = ptr['stats'] - # self.mOutputPtr[path] = stats.get_map() - - # if 'children' in ptr: - # children=ptr['children'] - - # curptr = self.mOutputPtr - # curchildren={} - # curptr['children'] = curchildren - - # for key in children: - # curchildren[key]={} - # self.mOutputPtr = curchildren[key] - # self.output(children[key],path + '/' + key) - - def done(self): - global gBlockMap - - if not self.get(): - return - - output_name = "/dev/shm/simperf/%s_proc.%d.llsd" % (self.process_name, os.getpid()) - output_file = open(output_name, 'w') - process_info = { - "name" : self.process_name, - "pid" : os.getpid(), - "ppid" : os.getppid(), - "timestamp" : self.mTimeStamp, - "utc_time" : self.mUTCTime, - } - output_file.write(llsd.format_notation(process_info)) - output_file.write('\n') - - for key in gBlockMap.keys(): - gBlockMap[key] = gBlockMap[key].get_map() - output_file.write(llsd.format_notation(gBlockMap)) - output_file.write('\n') - output_file.close() - diff --git a/indra/lib/python/indra/util/llsubprocess.py b/indra/lib/python/indra/util/llsubprocess.py deleted file mode 100644 index 7e0e115d14..0000000000 --- a/indra/lib/python/indra/util/llsubprocess.py +++ /dev/null @@ -1,117 +0,0 @@ -"""\ -@file llsubprocess.py -@author Phoenix -@date 2008-01-18 -@brief The simplest possible wrapper for a common sub-process paradigm. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import os -import popen2 -import time -import select - -class Timeout(RuntimeError): - "Exception raised when a subprocess times out." - pass - -def run(command, args=None, data=None, timeout=None): - """\ -@brief Run command with arguments - -This is it. This is the function I want to run all the time when doing -subprocces, but end up copying the code everywhere. none of the -standard commands are secure and provide a way to specify input, get -all the output, and get the result. -@param command A string specifying a process to launch. -@param args Arguments to be passed to command. Must be list, tuple or None. -@param data input to feed to the command. -@param timeout Maximum number of many seconds to run. -@return Returns (result, stdout, stderr) from process. -""" - cmd = [command] - if args: - cmd.extend([str(arg) for arg in args]) - #print "cmd: ","' '".join(cmd) - child = popen2.Popen3(cmd, True) - #print child.pid - out = [] - err = [] - result = -1 - time_left = timeout - tochild = [child.tochild.fileno()] - while True: - time_start = time.time() - #print "time:",time_left - p_in, p_out, p_err = select.select( - [child.fromchild.fileno(), child.childerr.fileno()], - tochild, - [], - time_left) - if p_in: - new_line = os.read(child.fromchild.fileno(), 32 * 1024) - if new_line: - #print "line:",new_line - out.append(new_line) - new_line = os.read(child.childerr.fileno(), 32 * 1024) - if new_line: - #print "error:", new_line - err.append(new_line) - if p_out: - if data: - #print "p_out" - bytes = os.write(child.tochild.fileno(), data) - data = data[bytes:] - if len(data) == 0: - data = None - tochild = [] - child.tochild.close() - result = child.poll() - if result != -1: - # At this point, the child process has exited and result - # is the return value from the process. Between the time - # we called select() and poll() the process may have - # exited so read all the data left on the child process - # stdout and stderr. - last = child.fromchild.read() - if last: - out.append(last) - last = child.childerr.read() - if last: - err.append(last) - child.tochild.close() - child.fromchild.close() - child.childerr.close() - break - if time_left is not None: - time_left -= (time.time() - time_start) - if time_left < 0: - raise Timeout - #print "result:",result - out = ''.join(out) - #print "stdout:", out - err = ''.join(err) - #print "stderr:", err - return result, out, err diff --git a/indra/lib/python/indra/util/named_query.py b/indra/lib/python/indra/util/named_query.py deleted file mode 100644 index 6bf956107d..0000000000 --- a/indra/lib/python/indra/util/named_query.py +++ /dev/null @@ -1,592 +0,0 @@ -"""\ -@file named_query.py -@author Ryan Williams, Phoenix -@date 2007-07-31 -@brief An API for running named queries. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import errno -import MySQLdb -import MySQLdb.cursors -import os -import os.path -import re -import time - -from indra.base import llsd -from indra.base import config - -DEBUG = False -NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq') -NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX) - -_g_named_manager = None - -def _init_g_named_manager(sql_dir = None): - """Initializes a global NamedManager object to point at a - specified named queries hierarchy. - - This function is intended entirely for testing purposes, - because it's tricky to control the config from inside a test.""" - global NQ_FILE_SUFFIX - NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq') - global NQ_FILE_SUFFIX_LEN - NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX) - - if sql_dir is None: - sql_dir = config.get('named-query-base-dir') - - # extra fallback directory in case config doesn't return what we want - if sql_dir is None: - sql_dir = os.path.abspath( - os.path.join( - os.path.realpath(os.path.dirname(__file__)), "..", "..", "..", "..", "web", "dataservice", "sql")) - - global _g_named_manager - _g_named_manager = NamedQueryManager( - os.path.abspath(os.path.realpath(sql_dir))) - -def get(name, schema = None): - "Get the named query object to be used to perform queries" - if _g_named_manager is None: - _init_g_named_manager() - return _g_named_manager.get(name).for_schema(schema) - -def sql(connection, name, params): - # use module-global NamedQuery object to perform default substitution - return get(name).sql(connection, params) - -def run(connection, name, params, expect_rows = None): - """\ -@brief given a connection, run a named query with the params - -Note that this function will fetch ALL rows. -@param connection The connection to use -@param name The name of the query to run -@param params The parameters passed into the query -@param expect_rows The number of rows expected. Set to 1 if return_as_map is true. Raises ExpectationFailed if the number of returned rows doesn't exactly match. Kind of a hack. -@return Returns the result set as a list of dicts. -""" - return get(name).run(connection, params, expect_rows) - -class ExpectationFailed(Exception): - """ Exception that is raised when an expectation for an sql query - is not met.""" - def __init__(self, message): - Exception.__init__(self, message) - self.message = message - -class NamedQuery(object): - def __init__(self, name, filename): - """ Construct a NamedQuery object. The name argument is an - arbitrary name as a handle for the query, and the filename is - a path to a file or a file-like object containing an llsd named - query document.""" - self._stat_interval_seconds = 5 # 5 seconds - self._name = name - if (filename is not None and isinstance(filename, (str, unicode)) - and NQ_FILE_SUFFIX != filename[-NQ_FILE_SUFFIX_LEN:]): - filename = filename + NQ_FILE_SUFFIX - self._location = filename - self._alternative = dict() - self._last_mod_time = 0 - self._last_check_time = 0 - self.deleted = False - self.load_contents() - - def name(self): - """ The name of the query. """ - return self._name - - def get_modtime(self): - """ Returns the mtime (last modified time) of the named query - filename. For file-like objects, expect a modtime of 0""" - if self._location and isinstance(self._location, (str, unicode)): - return os.path.getmtime(self._location) - return 0 - - def load_contents(self): - """ Loads and parses the named query file into self. Does - nothing if self.location is nonexistant.""" - if self._location: - if isinstance(self._location, (str, unicode)): - contents = llsd.parse(open(self._location).read()) - else: - # we probably have a file-like object. Godspeed! - contents = llsd.parse(self._location.read()) - self._reference_contents(contents) - # Check for alternative implementations - try: - for name, alt in self._contents['alternative'].items(): - nq = NamedQuery(name, None) - nq._reference_contents(alt) - self._alternative[name] = nq - except KeyError, e: - pass - self._last_mod_time = self.get_modtime() - self._last_check_time = time.time() - - def _reference_contents(self, contents): - "Helper method which builds internal structure from parsed contents" - self._contents = contents - self._ttl = int(self._contents.get('ttl', 0)) - self._return_as_map = bool(self._contents.get('return_as_map', False)) - self._legacy_dbname = self._contents.get('legacy_dbname', None) - - # reset these before doing the sql conversion because we will - # read them there. reset these while loading so we pick up - # changes. - self._around = set() - self._append = set() - self._integer = set() - self._options = self._contents.get('dynamic_where', {}) - for key in self._options: - if isinstance(self._options[key], basestring): - self._options[key] = self._convert_sql(self._options[key]) - elif isinstance(self._options[key], list): - lines = [] - for line in self._options[key]: - lines.append(self._convert_sql(line)) - self._options[key] = lines - else: - moreopt = {} - for kk in self._options[key]: - moreopt[kk] = self._convert_sql(self._options[key][kk]) - self._options[key] = moreopt - self._base_query = self._convert_sql(self._contents['base_query']) - self._query_suffix = self._convert_sql( - self._contents.get('query_suffix', '')) - - def _convert_sql(self, sql): - """convert the parsed sql into a useful internal structure. - - This function has to turn the named query format into a pyformat - style. It also has to look for %:name% and :name% and - ready them for use in LIKE statements""" - if sql: - # This first sub is to properly escape any % signs that - # are meant to be literally passed through to mysql in the - # query. It leaves any %'s that are used for - # like-expressions. - expr = re.compile("(?<=[^a-zA-Z0-9_-])%(?=[^:])") - sql = expr.sub('%%', sql) - - # This should tackle the rest of the %'s in the query, by - # converting them to LIKE clauses. - expr = re.compile("(%?):([a-zA-Z][a-zA-Z0-9_-]*)%") - sql = expr.sub(self._prepare_like, sql) - expr = re.compile("#:([a-zA-Z][a-zA-Z0-9_-]*)") - sql = expr.sub(self._prepare_integer, sql) - expr = re.compile(":([a-zA-Z][a-zA-Z0-9_-]*)") - sql = expr.sub("%(\\1)s", sql) - return sql - - def _prepare_like(self, match): - """This function changes LIKE statement replace behavior - - It works by turning %:name% to %(_name_around)s and :name% to - %(_name_append)s. Since a leading '_' is not a valid keyname - input (enforced via unit tests), it will never clash with - existing keys. Then, when building the statement, the query - runner will generate corrected strings.""" - if match.group(1) == '%': - # there is a leading % so this is treated as prefix/suffix - self._around.add(match.group(2)) - return "%(" + self._build_around_key(match.group(2)) + ")s" - else: - # there is no leading %, so this is suffix only - self._append.add(match.group(2)) - return "%(" + self._build_append_key(match.group(2)) + ")s" - - def _build_around_key(self, key): - return "_" + key + "_around" - - def _build_append_key(self, key): - return "_" + key + "_append" - - def _prepare_integer(self, match): - """This function adjusts the sql for #:name replacements - - It works by turning #:name to %(_name_as_integer)s. Since a - leading '_' is not a valid keyname input (enforced via unit - tests), it will never clash with existing keys. Then, when - building the statement, the query runner will generate - corrected strings.""" - self._integer.add(match.group(1)) - return "%(" + self._build_integer_key(match.group(1)) + ")s" - - def _build_integer_key(self, key): - return "_" + key + "_as_integer" - - def _strip_wildcards_to_list(self, value): - """Take string, and strip out the LIKE special characters. - - Technically, this is database dependant, but postgresql and - mysql use the same wildcards, and I am not aware of a general - way to handle this. I think you need a sql statement of the - form: - - LIKE_STRING( [ANY,ONE,str]... ) - - which would treat ANY as their any string, and ONE as their - single glyph, and str as something that needs database - specific encoding to not allow any % or _ to affect the query. - - As it stands, I believe it's impossible to write a named query - style interface which uses like to search the entire space of - text available. Imagine the query: - - % of brain used by average linden - - In order to search for %, it must be escaped, so once you have - escaped the string to not do wildcard searches, and be escaped - for the database, and then prepended the wildcard you come - back with one of: - - 1) %\% of brain used by average linden - 2) %%% of brain used by average linden - - Then, when passed to the database to be escaped to be database - safe, you get back: - - 1) %\\% of brain used by average linden - : which means search for any character sequence, followed by a - backslash, followed by any sequence, followed by ' of - brain...' - 2) %%% of brain used by average linden - : which (I believe) means search for a % followed by any - character sequence followed by 'of brain...' - - Neither of which is what we want! - - So, we need a vendor (or extention) for LIKE_STRING. Anyone - want to write it?""" - if isinstance(value, unicode): - utf8_value = value - else: - utf8_value = unicode(value, "utf-8") - esc_list = [] - remove_chars = set(u"%_") - for glyph in utf8_value: - if glyph in remove_chars: - continue - esc_list.append(glyph.encode("utf-8")) - return esc_list - - def delete(self): - """ Makes this query unusable by deleting all the members and - setting the deleted member. This is desired when the on-disk - query has been deleted but the in-memory copy remains.""" - # blow away all members except _name, _location, and deleted - name, location = self._name, self._location - for key in self.__dict__.keys(): - del self.__dict__[key] - self.deleted = True - self._name, self._location = name, location - - def ttl(self): - """ Estimated time to live of this query. Used for web - services to set the Expires header.""" - return self._ttl - - def legacy_dbname(self): - return self._legacy_dbname - - def return_as_map(self): - """ Returns true if this query is configured to return its - results as a single map (as opposed to a list of maps, the - normal behavior).""" - - return self._return_as_map - - def for_schema(self, db_name): - "Look trough the alternates and return the correct query" - if db_name is None: - return self - try: - return self._alternative[db_name] - except KeyError, e: - pass - return self - - def run(self, connection, params, expect_rows = None, use_dictcursor = True): - """given a connection, run a named query with the params - - Note that this function will fetch ALL rows. We do this because it - opens and closes the cursor to generate the values, and this - isn't a generator so the cursor has no life beyond the method call. - - @param cursor The connection to use (this generates its own cursor for the query) - @param name The name of the query to run - @param params The parameters passed into the query - @param expect_rows The number of rows expected. Set to 1 if return_as_map is true. Raises ExpectationFailed if the number of returned rows doesn't exactly match. Kind of a hack. - @param use_dictcursor Set to false to use a normal cursor and manually convert the rows to dicts. - @return Returns the result set as a list of dicts, or, if the named query has return_as_map set to true, returns a single dict. - """ - if use_dictcursor: - cursor = connection.cursor(MySQLdb.cursors.DictCursor) - else: - cursor = connection.cursor() - - full_query, params = self._construct_sql(params) - if DEBUG: - print "SQL:", self.sql(connection, params) - rows = cursor.execute(full_query, params) - - # *NOTE: the expect_rows argument is a very cheesy way to get some - # validation on the result set. If you want to add more expectation - # logic, do something more object-oriented and flexible. Or use an ORM. - if(self._return_as_map): - expect_rows = 1 - if expect_rows is not None and rows != expect_rows: - cursor.close() - raise ExpectationFailed("Statement expected %s rows, got %s. Sql: '%s' %s" % ( - expect_rows, rows, full_query, params)) - - # convert to dicts manually if we're not using a dictcursor - if use_dictcursor: - result_set = cursor.fetchall() - else: - if cursor.description is None: - # an insert or something - x = cursor.fetchall() - cursor.close() - return x - - names = [x[0] for x in cursor.description] - - result_set = [] - for row in cursor.fetchall(): - converted_row = {} - for idx, col_name in enumerate(names): - converted_row[col_name] = row[idx] - result_set.append(converted_row) - - cursor.close() - if self._return_as_map: - return result_set[0] - return result_set - - def _construct_sql(self, params): - """ Returns a query string and a dictionary of parameters, - suitable for directly passing to the execute() method.""" - self.refresh() - - # build the query from the options available and the params - base_query = [] - base_query.append(self._base_query) - for opt, extra_where in self._options.items(): - if type(extra_where) in (dict, list, tuple): - if opt in params: - base_query.append(extra_where[params[opt]]) - else: - if opt in params and params[opt]: - base_query.append(extra_where) - if self._query_suffix: - base_query.append(self._query_suffix) - full_query = '\n'.join(base_query) - - # Go through the query and rewrite all of the ones with the - # @:name syntax. - rewrite = _RewriteQueryForArray(params) - expr = re.compile("@%\(([a-zA-Z][a-zA-Z0-9_-]*)\)s") - full_query = expr.sub(rewrite.operate, full_query) - params.update(rewrite.new_params) - - # build out the params for like. We only have to do this - # parameters which were detected to have ued the where syntax - # during load. - # - # * treat the incoming string as utf-8 - # * strip wildcards - # * append or prepend % as appropriate - new_params = {} - for key in params: - if key in self._around: - new_value = ['%'] - new_value.extend(self._strip_wildcards_to_list(params[key])) - new_value.append('%') - new_params[self._build_around_key(key)] = ''.join(new_value) - if key in self._append: - new_value = self._strip_wildcards_to_list(params[key]) - new_value.append('%') - new_params[self._build_append_key(key)] = ''.join(new_value) - if key in self._integer: - new_params[self._build_integer_key(key)] = int(params[key]) - params.update(new_params) - - return full_query, params - - def sql(self, connection, params): - """ Generates an SQL statement from the named query document - and a dictionary of parameters. - - *NOTE: Only use for debugging, because it uses the - non-standard MySQLdb 'literal' method. - """ - if not DEBUG: - import warnings - warnings.warn("Don't use named_query.sql() when not debugging. Used on %s" % self._location) - # do substitution using the mysql (non-standard) 'literal' - # function to do the escaping. - full_query, params = self._construct_sql(params) - return full_query % connection.literal(params) - - - def refresh(self): - """ Refresh self from the file on the filesystem. - - This is optimized to be callable as frequently as you wish, - without adding too much load. It does so by only stat-ing the - file every N seconds, where N defaults to 5 and is - configurable through the member _stat_interval_seconds. If the stat - reveals that the file has changed, refresh will re-parse the - contents of the file and use them to update the named query - instance. If the stat reveals that the file has been deleted, - refresh will call self.delete to make the in-memory - representation unusable.""" - now = time.time() - if(now - self._last_check_time > self._stat_interval_seconds): - self._last_check_time = now - try: - modtime = self.get_modtime() - if(modtime > self._last_mod_time): - self.load_contents() - except OSError, e: - if e.errno == errno.ENOENT: # file not found - self.delete() # clean up self - raise # pass the exception along to the caller so they know that this query disappeared - -class NamedQueryManager(object): - """ Manages the lifespan of NamedQuery objects, drawing from a - directory hierarchy of named query documents. - - In practice this amounts to a memory cache of NamedQuery objects.""" - - def __init__(self, named_queries_dir): - """ Initializes a manager to look for named queries in a - directory.""" - self._dir = os.path.abspath(os.path.realpath(named_queries_dir)) - self._cached_queries = {} - - def sql(self, connection, name, params): - nq = self.get(name) - return nq.sql(connection, params) - - def get(self, name): - """ Returns a NamedQuery instance based on the name, either - from memory cache, or by parsing from disk. - - The name is simply a relative path to the directory associated - with the manager object. Before returning the instance, the - NamedQuery object is cached in memory, so that subsequent - accesses don't have to read from disk or do any parsing. This - means that NamedQuery objects returned by this method are - shared across all users of the manager object. - NamedQuery.refresh is used to bring the NamedQuery objects in - sync with the actual files on disk.""" - nq = self._cached_queries.get(name) - if nq is None: - nq = NamedQuery(name, os.path.join(self._dir, name)) - self._cached_queries[name] = nq - else: - try: - nq.refresh() - except OSError, e: - if e.errno == errno.ENOENT: # file not found - del self._cached_queries[name] - raise # pass exception along to caller so they know that the query disappeared - - return nq - -class _RewriteQueryForArray(object): - "Helper class for rewriting queries with the @:name syntax" - def __init__(self, params): - self.params = params - self.new_params = dict() - - def operate(self, match): - "Given a match, return the string that should be in use" - key = match.group(1) - value = self.params[key] - if type(value) in (list,tuple): - rv = [] - for idx in range(len(value)): - # if the value@idx is array-like, we are - # probably dealing with a VALUES - new_key = "_%s_%s"%(key, str(idx)) - val_item = value[idx] - if type(val_item) in (list, tuple, dict): - if type(val_item) is dict: - # this is because in Python, the order of - # key, value retrieval from the dict is not - # guaranteed to match what the input intended - # and for VALUES, order is important. - # TODO: Implemented ordered dict in LLSD parser? - raise ExpectationFailed('Only lists/tuples allowed,\ - received dict') - values_keys = [] - for value_idx, item in enumerate(val_item): - # we want a key of the format : - # key_#replacement_#value_row_#value_col - # ugh... so if we are replacing 10 rows in user_note, - # the first values clause would read (for @:user_notes) :- - # ( :_user_notes_0_1_1, :_user_notes_0_1_2, :_user_notes_0_1_3 ) - # the input LLSD for VALUES will look like: - # ... - # - # user_notes - # - # - # ... - # ... - # ... - # - # ... - # - # - # ... - values_key = "%s_%s"%(new_key, value_idx) - self.new_params[values_key] = item - values_keys.append("%%(%s)s"%values_key) - # now collapse all these new place holders enclosed in () - # from [':_key_0_1_1', ':_key_0_1_2', ':_key_0_1_3,...] - # rv will have [ '(:_key_0_1_1, :_key_0_1_2, :_key_0_1_3)', ] - # which is flattened a few lines below join(rv) - rv.append('(%s)' % ','.join(values_keys)) - else: - self.new_params[new_key] = val_item - rv.append("%%(%s)s"%new_key) - return ','.join(rv) - else: - # not something that can be expanded, so just drop the - # leading @ in the front of the match. This will mean that - # the single value we have, be it a string, int, whatever - # (other than dict) will correctly show up, eg: - # - # where foo in (@:foobar) -- foobar is a string, so we get - # where foo in (:foobar) - return match.group(0)[1:] diff --git a/indra/lib/python/indra/util/shutil2.py b/indra/lib/python/indra/util/shutil2.py deleted file mode 100644 index 9e2e7a6ded..0000000000 --- a/indra/lib/python/indra/util/shutil2.py +++ /dev/null @@ -1,84 +0,0 @@ -''' -@file shutil2.py -@brief a better shutil.copytree replacement - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -''' - -# -# shutil2.py -# Taken from http://www.scons.org/wiki/AccumulateBuilder -# the stock copytree sucks because it insists that the -# target dir not exist -# - -import os.path -import shutil - -def copytree(src, dest, symlinks=False): - """My own copyTree which does not fail if the directory exists. - - Recursively copy a directory tree using copy2(). - - If the optional symlinks flag is true, symbolic links in the - source tree result in symbolic links in the destination tree; if - it is false, the contents of the files pointed to by symbolic - links are copied. - - Behavior is meant to be identical to GNU 'cp -R'. - """ - def copyItems(src, dest, symlinks=False): - """Function that does all the work. - - It is necessary to handle the two 'cp' cases: - - destination does exist - - destination does not exist - - See 'cp -R' documentation for more details - """ - for item in os.listdir(src): - srcPath = os.path.join(src, item) - if os.path.isdir(srcPath): - srcBasename = os.path.basename(srcPath) - destDirPath = os.path.join(dest, srcBasename) - if not os.path.exists(destDirPath): - os.makedirs(destDirPath) - copyItems(srcPath, destDirPath) - elif os.path.islink(item) and symlinks: - linkto = os.readlink(item) - os.symlink(linkto, dest) - else: - shutil.copy2(srcPath, dest) - - # case 'cp -R src/ dest/' where dest/ already exists - if os.path.exists(dest): - destPath = os.path.join(dest, os.path.basename(src)) - if not os.path.exists(destPath): - os.makedirs(destPath) - # case 'cp -R src/ dest/' where dest/ does not exist - else: - os.makedirs(dest) - destPath = dest - # actually copy the files - copyItems(src, destPath) diff --git a/indra/lib/python/indra/util/simperf_host_xml_parser.py b/indra/lib/python/indra/util/simperf_host_xml_parser.py deleted file mode 100755 index 672c1050c2..0000000000 --- a/indra/lib/python/indra/util/simperf_host_xml_parser.py +++ /dev/null @@ -1,338 +0,0 @@ -#!/usr/bin/env python -"""\ -@file simperf_host_xml_parser.py -@brief Digest collector's XML dump and convert to simple dict/list structure - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import sys, os, getopt, time -import simplejson -from xml import sax - - -def usage(): - print "Usage:" - print sys.argv[0] + " [options]" - print " Convert RRD's XML dump to JSON. Script to convert the simperf_host_collector-" - print " generated RRD dump into JSON. Steps include converting selected named" - print " fields from GAUGE type to COUNTER type by computing delta with preceding" - print " values. Top-level named fields are:" - print - print " lastupdate Time (javascript timestamp) of last data sample" - print " step Time in seconds between samples" - print " ds Data specification (name/type) for each column" - print " database Table of data samples, one time step per row" - print - print "Options:" - print " -i, --in Input settings filename. (Default: stdin)" - print " -o, --out Output settings filename. (Default: stdout)" - print " -h, --help Print this message and exit." - print - print "Example: %s -i rrddump.xml -o rrddump.json" % sys.argv[0] - print - print "Interfaces:" - print " class SimPerfHostXMLParser() # SAX content handler" - print " def simperf_host_xml_fixup(parser) # post-parse value fixup" - -class SimPerfHostXMLParser(sax.handler.ContentHandler): - - def __init__(self): - pass - - def startDocument(self): - self.rrd_last_update = 0 # public - self.rrd_step = 0 # public - self.rrd_ds = [] # public - self.rrd_records = [] # public - self._rrd_level = 0 - self._rrd_parse_state = 0 - self._rrd_chars = "" - self._rrd_capture = False - self._rrd_ds_val = {} - self._rrd_data_row = [] - self._rrd_data_row_has_nan = False - - def endDocument(self): - pass - - # Nasty little ad-hoc state machine to extract the elements that are - # necessary from the 'rrdtool dump' XML output. The same element - # name '' is used for two different data sets so we need to pay - # some attention to the actual structure to get the ones we want - # and ignore the ones we don't. - - def startElement(self, name, attrs): - self._rrd_level = self._rrd_level + 1 - self._rrd_capture = False - if self._rrd_level == 1: - if name == "rrd" and self._rrd_parse_state == 0: - self._rrd_parse_state = 1 # In - self._rrd_capture = True - self._rrd_chars = "" - elif self._rrd_level == 2: - if self._rrd_parse_state == 1: - if name == "lastupdate": - self._rrd_parse_state = 2 # In - self._rrd_capture = True - self._rrd_chars = "" - elif name == "step": - self._rrd_parse_state = 3 # In - self._rrd_capture = True - self._rrd_chars = "" - elif name == "ds": - self._rrd_parse_state = 4 # In - self._rrd_ds_val = {} - self._rrd_chars = "" - elif name == "rra": - self._rrd_parse_state = 5 # In - elif self._rrd_level == 3: - if self._rrd_parse_state == 4: - if name == "name": - self._rrd_parse_state = 6 # In - self._rrd_capture = True - self._rrd_chars = "" - elif name == "type": - self._rrd_parse_state = 7 # In - self._rrd_capture = True - self._rrd_chars = "" - elif self._rrd_parse_state == 5: - if name == "database": - self._rrd_parse_state = 8 # In - elif self._rrd_level == 4: - if self._rrd_parse_state == 8: - if name == "row": - self._rrd_parse_state = 9 # In - self._rrd_data_row = [] - self._rrd_data_row_has_nan = False - elif self._rrd_level == 5: - if self._rrd_parse_state == 9: - if name == "v": - self._rrd_parse_state = 10 # In - self._rrd_capture = True - self._rrd_chars = "" - - def endElement(self, name): - self._rrd_capture = False - if self._rrd_parse_state == 10: - self._rrd_capture = self._rrd_level == 6 - if self._rrd_level == 5: - if self._rrd_chars == "NaN": - self._rrd_data_row_has_nan = True - else: - self._rrd_data_row.append(self._rrd_chars) - self._rrd_parse_state = 9 # In - elif self._rrd_parse_state == 9: - if self._rrd_level == 4: - if not self._rrd_data_row_has_nan: - self.rrd_records.append(self._rrd_data_row) - self._rrd_parse_state = 8 # In - elif self._rrd_parse_state == 8: - if self._rrd_level == 3: - self._rrd_parse_state = 5 # In - elif self._rrd_parse_state == 7: - if self._rrd_level == 3: - self._rrd_ds_val["type"] = self._rrd_chars - self._rrd_parse_state = 4 # In - elif self._rrd_parse_state == 6: - if self._rrd_level == 3: - self._rrd_ds_val["name"] = self._rrd_chars - self._rrd_parse_state = 4 # In - elif self._rrd_parse_state == 5: - if self._rrd_level == 2: - self._rrd_parse_state = 1 # In - elif self._rrd_parse_state == 4: - if self._rrd_level == 2: - self.rrd_ds.append(self._rrd_ds_val) - self._rrd_parse_state = 1 # In - elif self._rrd_parse_state == 3: - if self._rrd_level == 2: - self.rrd_step = long(self._rrd_chars) - self._rrd_parse_state = 1 # In - elif self._rrd_parse_state == 2: - if self._rrd_level == 2: - self.rrd_last_update = long(self._rrd_chars) - self._rrd_parse_state = 1 # In - elif self._rrd_parse_state == 1: - if self._rrd_level == 1: - self._rrd_parse_state = 0 # At top - - if self._rrd_level: - self._rrd_level = self._rrd_level - 1 - - def characters(self, content): - if self._rrd_capture: - self._rrd_chars = self._rrd_chars + content.strip() - -def _make_numeric(value): - try: - value = float(value) - except: - value = "" - return value - -def simperf_host_xml_fixup(parser, filter_start_time = None, filter_end_time = None): - # Fixup for GAUGE fields that are really COUNTS. They - # were forced to GAUGE to try to disable rrdtool's - # data interpolation/extrapolation for non-uniform time - # samples. - fixup_tags = [ "cpu_user", - "cpu_nice", - "cpu_sys", - "cpu_idle", - "cpu_waitio", - "cpu_intr", - # "file_active", - # "file_free", - # "inode_active", - # "inode_free", - "netif_in_kb", - "netif_in_pkts", - "netif_in_errs", - "netif_in_drop", - "netif_out_kb", - "netif_out_pkts", - "netif_out_errs", - "netif_out_drop", - "vm_page_in", - "vm_page_out", - "vm_swap_in", - "vm_swap_out", - #"vm_mem_total", - #"vm_mem_used", - #"vm_mem_active", - #"vm_mem_inactive", - #"vm_mem_free", - #"vm_mem_buffer", - #"vm_swap_cache", - #"vm_swap_total", - #"vm_swap_used", - #"vm_swap_free", - "cpu_interrupts", - "cpu_switches", - "cpu_forks" ] - - col_count = len(parser.rrd_ds) - row_count = len(parser.rrd_records) - - # Process the last row separately, just to make all values numeric. - for j in range(col_count): - parser.rrd_records[row_count - 1][j] = _make_numeric(parser.rrd_records[row_count - 1][j]) - - # Process all other row/columns. - last_different_row = row_count - 1 - current_row = row_count - 2 - while current_row >= 0: - # Check for a different value than the previous row. If everything is the same - # then this is probably just a filler/bogus entry. - is_different = False - for j in range(col_count): - parser.rrd_records[current_row][j] = _make_numeric(parser.rrd_records[current_row][j]) - if parser.rrd_records[current_row][j] != parser.rrd_records[last_different_row][j]: - # We're good. This is a different row. - is_different = True - - if not is_different: - # This is a filler/bogus entry. Just ignore it. - for j in range(col_count): - parser.rrd_records[current_row][j] = float('nan') - else: - # Some tags need to be converted into deltas. - for j in range(col_count): - if parser.rrd_ds[j]["name"] in fixup_tags: - parser.rrd_records[last_different_row][j] = \ - parser.rrd_records[last_different_row][j] - parser.rrd_records[current_row][j] - last_different_row = current_row - - current_row -= 1 - - # Set fixup_tags in the first row to 'nan' since they aren't useful anymore. - for j in range(col_count): - if parser.rrd_ds[j]["name"] in fixup_tags: - parser.rrd_records[0][j] = float('nan') - - # Add a timestamp to each row and to the catalog. Format and name - # chosen to match other simulator logging (hopefully). - start_time = parser.rrd_last_update - (parser.rrd_step * (row_count - 1)) - # Build a filtered list of rrd_records if we are limited to a time range. - filter_records = False - if filter_start_time is not None or filter_end_time is not None: - filter_records = True - filtered_rrd_records = [] - if filter_start_time is None: - filter_start_time = start_time * 1000 - if filter_end_time is None: - filter_end_time = parser.rrd_last_update * 1000 - - for i in range(row_count): - record_timestamp = (start_time + (i * parser.rrd_step)) * 1000 - parser.rrd_records[i].insert(0, record_timestamp) - if filter_records: - if filter_start_time <= record_timestamp and record_timestamp <= filter_end_time: - filtered_rrd_records.append(parser.rrd_records[i]) - - if filter_records: - parser.rrd_records = filtered_rrd_records - - parser.rrd_ds.insert(0, {"type": "GAUGE", "name": "javascript_timestamp"}) - - -def main(argv=None): - opts, args = getopt.getopt(sys.argv[1:], "i:o:h", ["in=", "out=", "help"]) - input_file = sys.stdin - output_file = sys.stdout - for o, a in opts: - if o in ("-i", "--in"): - input_file = open(a, 'r') - if o in ("-o", "--out"): - output_file = open(a, 'w') - if o in ("-h", "--help"): - usage() - sys.exit(0) - - # Using the SAX parser as it is at least 4X faster and far, far - # smaller on this dataset than the DOM-based interface in xml.dom.minidom. - # With SAX and a 5.4MB xml file, this requires about seven seconds of - # wall-clock time and 32MB VSZ. With the DOM interface, about 22 seconds - # and over 270MB VSZ. - - handler = SimPerfHostXMLParser() - sax.parse(input_file, handler) - if input_file != sys.stdin: - input_file.close() - - # Various format fixups: string-to-num, gauge-to-counts, add - # a time stamp, etc. - simperf_host_xml_fixup(handler) - - # Create JSONable dict with interesting data and format/print it - print >>output_file, simplejson.dumps({ "step" : handler.rrd_step, - "lastupdate": handler.rrd_last_update * 1000, - "ds" : handler.rrd_ds, - "database" : handler.rrd_records }) - - return 0 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/indra/lib/python/indra/util/simperf_oprof_interface.py b/indra/lib/python/indra/util/simperf_oprof_interface.py deleted file mode 100755 index 547d2f9980..0000000000 --- a/indra/lib/python/indra/util/simperf_oprof_interface.py +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env python -"""\ -@file simperf_oprof_interface.py -@brief Manage OProfile data collection on a host - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import sys, os, getopt -import simplejson - - -def usage(): - print "Usage:" - print sys.argv[0] + " [options]" - print " Digest the OProfile report forms that come out of the" - print " simperf_oprof_ctl program's -r/--report command. The result" - print " is an array of dictionaires with the following keys:" - print - print " symbol Name of sampled, calling, or called procedure" - print " file Executable or library where symbol resides" - print " percentage Percentage contribution to profile, calls or called" - print " samples Sample count" - print " calls Methods called by the method in question (full only)" - print " called_by Methods calling the method (full only)" - print - print " For 'full' reports the two keys 'calls' and 'called_by' are" - print " themselves arrays of dictionaries based on the first four keys." - print - print "Return Codes:" - print " None. Aggressively digests everything. Will likely mung results" - print " if a program or library has whitespace in its name." - print - print "Options:" - print " -i, --in Input settings filename. (Default: stdin)" - print " -o, --out Output settings filename. (Default: stdout)" - print " -h, --help Print this message and exit." - print - print "Interfaces:" - print " class SimPerfOProfileInterface()" - -class SimPerfOProfileInterface: - def __init__(self): - self.isBrief = True # public - self.isValid = False # public - self.result = [] # public - - def parse(self, input): - in_samples = False - for line in input: - if in_samples: - if line[0:6] == "------": - self.isBrief = False - self._parseFull(input) - else: - self._parseBrief(input, line) - self.isValid = True - return - try: - hd1, remain = line.split(None, 1) - if hd1 == "samples": - in_samples = True - except ValueError: - pass - - def _parseBrief(self, input, line1): - try: - fld1, fld2, fld3, fld4 = line1.split(None, 3) - self.result.append({"samples" : fld1, - "percentage" : fld2, - "file" : fld3, - "symbol" : fld4.strip("\n")}) - except ValueError: - pass - for line in input: - try: - fld1, fld2, fld3, fld4 = line.split(None, 3) - self.result.append({"samples" : fld1, - "percentage" : fld2, - "file" : fld3, - "symbol" : fld4.strip("\n")}) - except ValueError: - pass - - def _parseFull(self, input): - state = 0 # In 'called_by' section - calls = [] - called_by = [] - current = {} - for line in input: - if line[0:6] == "------": - if len(current): - current["calls"] = calls - current["called_by"] = called_by - self.result.append(current) - state = 0 - calls = [] - called_by = [] - current = {} - else: - try: - fld1, fld2, fld3, fld4 = line.split(None, 3) - tmp = {"samples" : fld1, - "percentage" : fld2, - "file" : fld3, - "symbol" : fld4.strip("\n")} - except ValueError: - continue - if line[0] != " ": - current = tmp - state = 1 # In 'calls' section - elif state == 0: - called_by.append(tmp) - else: - calls.append(tmp) - if len(current): - current["calls"] = calls - current["called_by"] = called_by - self.result.append(current) - - -def main(argv=None): - opts, args = getopt.getopt(sys.argv[1:], "i:o:h", ["in=", "out=", "help"]) - input_file = sys.stdin - output_file = sys.stdout - for o, a in opts: - if o in ("-i", "--in"): - input_file = open(a, 'r') - if o in ("-o", "--out"): - output_file = open(a, 'w') - if o in ("-h", "--help"): - usage() - sys.exit(0) - - oprof = SimPerfOProfileInterface() - oprof.parse(input_file) - if input_file != sys.stdin: - input_file.close() - - # Create JSONable dict with interesting data and format/print it - print >>output_file, simplejson.dumps(oprof.result) - - return 0 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/indra/lib/python/indra/util/simperf_proc_interface.py b/indra/lib/python/indra/util/simperf_proc_interface.py deleted file mode 100755 index de061f68cc..0000000000 --- a/indra/lib/python/indra/util/simperf_proc_interface.py +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/env python -"""\ -@file simperf_proc_interface.py -@brief Utility to extract log messages from *..llsd files containing performance statistics. - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -# ---------------------------------------------------- -# Utility to extract log messages from *..llsd -# files that contain performance statistics. - -# ---------------------------------------------------- -import sys, os - -if os.path.exists("setup-path.py"): - execfile("setup-path.py") - -from indra.base import llsd - -DEFAULT_PATH="/dev/shm/simperf/" - - -# ---------------------------------------------------- -# Pull out the stats and return a single document -def parse_logfile(filename, target_column=None, verbose=False): - full_doc = [] - # Open source temp log file. Let exceptions percolate up. - sourcefile = open( filename,'r') - - if verbose: - print "Reading " + filename - - # Parse and output all lines from the temp file - for line in sourcefile.xreadlines(): - partial_doc = llsd.parse(line) - if partial_doc is not None: - if target_column is None: - full_doc.append(partial_doc) - else: - trim_doc = { target_column: partial_doc[target_column] } - if target_column != "fps": - trim_doc[ 'fps' ] = partial_doc[ 'fps' ] - trim_doc[ '/total_time' ] = partial_doc[ '/total_time' ] - trim_doc[ 'utc_time' ] = partial_doc[ 'utc_time' ] - full_doc.append(trim_doc) - - sourcefile.close() - return full_doc - -# Extract just the meta info line, and the timestamp of the first/last frame entry. -def parse_logfile_info(filename, verbose=False): - # Open source temp log file. Let exceptions percolate up. - sourcefile = open(filename, 'rU') # U is to open with Universal newline support - - if verbose: - print "Reading " + filename - - # The first line is the meta info line. - info_line = sourcefile.readline() - if not info_line: - sourcefile.close() - return None - - # The rest of the lines are frames. Read the first and last to get the time range. - info = llsd.parse( info_line ) - info['start_time'] = None - info['end_time'] = None - first_frame = sourcefile.readline() - if first_frame: - try: - info['start_time'] = int(llsd.parse(first_frame)['timestamp']) - except: - pass - - # Read the file backwards to find the last two lines. - sourcefile.seek(0, 2) - file_size = sourcefile.tell() - offset = 1024 - num_attempts = 0 - end_time = None - if file_size < offset: - offset = file_size - while 1: - sourcefile.seek(-1*offset, 2) - read_str = sourcefile.read(offset) - # Remove newline at the end - if read_str[offset - 1] == '\n': - read_str = read_str[0:-1] - lines = read_str.split('\n') - full_line = None - if len(lines) > 2: # Got two line - try: - end_time = llsd.parse(lines[-1])['timestamp'] - except: - # We couldn't parse this line. Try once more. - try: - end_time = llsd.parse(lines[-2])['timestamp'] - except: - # Nope. Just move on. - pass - break - if len(read_str) == file_size: # Reached the beginning - break - offset += 1024 - - info['end_time'] = int(end_time) - - sourcefile.close() - return info - - -def parse_proc_filename(filename): - try: - name_as_list = filename.split(".") - cur_stat_type = name_as_list[0].split("_")[0] - cur_pid = name_as_list[1] - except IndexError, ValueError: - return (None, None) - return (cur_pid, cur_stat_type) - -# ---------------------------------------------------- -def get_simstats_list(path=None): - """ Return stats (pid, type) listed in _proc..llsd """ - if path is None: - path = DEFAULT_PATH - simstats_list = [] - for file_name in os.listdir(path): - if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd": - simstats_info = parse_logfile_info(path + file_name) - if simstats_info is not None: - simstats_list.append(simstats_info) - return simstats_list - -def get_log_info_list(pid=None, stat_type=None, path=None, target_column=None, verbose=False): - """ Return data from all llsd files matching the pid and stat type """ - if path is None: - path = DEFAULT_PATH - log_info_list = {} - for file_name in os.listdir ( path ): - if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd": - (cur_pid, cur_stat_type) = parse_proc_filename(file_name) - if cur_pid is None: - continue - if pid is not None and pid != cur_pid: - continue - if stat_type is not None and stat_type != cur_stat_type: - continue - log_info_list[cur_pid] = parse_logfile(path + file_name, target_column, verbose) - return log_info_list - -def delete_simstats_files(pid=None, stat_type=None, path=None): - """ Delete *..llsd files """ - if path is None: - path = DEFAULT_PATH - del_list = [] - for file_name in os.listdir(path): - if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd": - (cur_pid, cur_stat_type) = parse_proc_filename(file_name) - if cur_pid is None: - continue - if pid is not None and pid != cur_pid: - continue - if stat_type is not None and stat_type != cur_stat_type: - continue - del_list.append(cur_pid) - # Allow delete related exceptions to percolate up if this fails. - os.unlink(os.path.join(DEFAULT_PATH, file_name)) - return del_list - diff --git a/indra/lib/python/indra/util/term.py b/indra/lib/python/indra/util/term.py deleted file mode 100644 index 8c316a1f12..0000000000 --- a/indra/lib/python/indra/util/term.py +++ /dev/null @@ -1,222 +0,0 @@ -''' -@file term.py -@brief a better shutil.copytree replacement - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -''' - -#http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/475116 - -import sys, re - -class TerminalController: - """ - A class that can be used to portably generate formatted output to - a terminal. - - `TerminalController` defines a set of instance variables whose - values are initialized to the control sequence necessary to - perform a given action. These can be simply included in normal - output to the terminal: - - >>> term = TerminalController() - >>> print 'This is '+term.GREEN+'green'+term.NORMAL - - Alternatively, the `render()` method can used, which replaces - '${action}' with the string required to perform 'action': - - >>> term = TerminalController() - >>> print term.render('This is ${GREEN}green${NORMAL}') - - If the terminal doesn't support a given action, then the value of - the corresponding instance variable will be set to ''. As a - result, the above code will still work on terminals that do not - support color, except that their output will not be colored. - Also, this means that you can test whether the terminal supports a - given action by simply testing the truth value of the - corresponding instance variable: - - >>> term = TerminalController() - >>> if term.CLEAR_SCREEN: - ... print 'This terminal supports clearning the screen.' - - Finally, if the width and height of the terminal are known, then - they will be stored in the `COLS` and `LINES` attributes. - """ - # Cursor movement: - BOL = '' #: Move the cursor to the beginning of the line - UP = '' #: Move the cursor up one line - DOWN = '' #: Move the cursor down one line - LEFT = '' #: Move the cursor left one char - RIGHT = '' #: Move the cursor right one char - - # Deletion: - CLEAR_SCREEN = '' #: Clear the screen and move to home position - CLEAR_EOL = '' #: Clear to the end of the line. - CLEAR_BOL = '' #: Clear to the beginning of the line. - CLEAR_EOS = '' #: Clear to the end of the screen - - # Output modes: - BOLD = '' #: Turn on bold mode - BLINK = '' #: Turn on blink mode - DIM = '' #: Turn on half-bright mode - REVERSE = '' #: Turn on reverse-video mode - NORMAL = '' #: Turn off all modes - - # Cursor display: - HIDE_CURSOR = '' #: Make the cursor invisible - SHOW_CURSOR = '' #: Make the cursor visible - - # Terminal size: - COLS = None #: Width of the terminal (None for unknown) - LINES = None #: Height of the terminal (None for unknown) - - # Foreground colors: - BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = '' - - # Background colors: - BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = '' - BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = '' - - _STRING_CAPABILITIES = """ - BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1 - CLEAR_SCREEN=clear CLEAR_EOL=el CLEAR_BOL=el1 CLEAR_EOS=ed BOLD=bold - BLINK=blink DIM=dim REVERSE=rev UNDERLINE=smul NORMAL=sgr0 - HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split() - _COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split() - _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split() - - def __init__(self, term_stream=sys.stdout): - """ - Create a `TerminalController` and initialize its attributes - with appropriate values for the current terminal. - `term_stream` is the stream that will be used for terminal - output; if this stream is not a tty, then the terminal is - assumed to be a dumb terminal (i.e., have no capabilities). - """ - # Curses isn't available on all platforms - try: import curses - except: return - - # If the stream isn't a tty, then assume it has no capabilities. - if not term_stream.isatty(): return - - # Check the terminal type. If we fail, then assume that the - # terminal has no capabilities. - try: curses.setupterm() - except: return - - # Look up numeric capabilities. - self.COLS = curses.tigetnum('cols') - self.LINES = curses.tigetnum('lines') - - # Look up string capabilities. - for capability in self._STRING_CAPABILITIES: - (attrib, cap_name) = capability.split('=') - setattr(self, attrib, self._tigetstr(cap_name) or '') - - # Colors - set_fg = self._tigetstr('setf') - if set_fg: - for i,color in zip(range(len(self._COLORS)), self._COLORS): - setattr(self, color, curses.tparm(set_fg, i) or '') - set_fg_ansi = self._tigetstr('setaf') - if set_fg_ansi: - for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS): - setattr(self, color, curses.tparm(set_fg_ansi, i) or '') - set_bg = self._tigetstr('setb') - if set_bg: - for i,color in zip(range(len(self._COLORS)), self._COLORS): - setattr(self, 'BG_'+color, curses.tparm(set_bg, i) or '') - set_bg_ansi = self._tigetstr('setab') - if set_bg_ansi: - for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS): - setattr(self, 'BG_'+color, curses.tparm(set_bg_ansi, i) or '') - - def _tigetstr(self, cap_name): - # String capabilities can include "delays" of the form "$<2>". - # For any modern terminal, we should be able to just ignore - # these, so strip them out. - import curses - cap = curses.tigetstr(cap_name) or '' - return re.sub(r'\$<\d+>[/*]?', '', cap) - - def render(self, template): - """ - Replace each $-substitutions in the given template string with - the corresponding terminal control string (if it's defined) or - '' (if it's not). - """ - return re.sub(r'\$\$|\${\w+}', self._render_sub, template) - - def _render_sub(self, match): - s = match.group() - if s == '$$': return s - else: return getattr(self, s[2:-1]) - -####################################################################### -# Example use case: progress bar -####################################################################### - -class ProgressBar: - """ - A 3-line progress bar, which looks like:: - - Header - 20% [===========----------------------------------] - progress message - - The progress bar is colored, if the terminal supports color - output; and adjusts to the width of the terminal. - """ - BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}\n' - HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n' - - def __init__(self, term, header): - self.term = term - if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL): - raise ValueError("Terminal isn't capable enough -- you " - "should use a simpler progress dispaly.") - self.width = self.term.COLS or 75 - self.bar = term.render(self.BAR) - self.header = self.term.render(self.HEADER % header.center(self.width)) - self.cleared = 1 #: true if we haven't drawn the bar yet. - self.update(0, '') - - def update(self, percent, message): - if self.cleared: - sys.stdout.write(self.header) - self.cleared = 0 - n = int((self.width-10)*percent) - sys.stdout.write( - self.term.BOL + self.term.UP + self.term.CLEAR_EOL + - (self.bar % (100*percent, '='*n, '-'*(self.width-10-n))) + - self.term.CLEAR_EOL + message.center(self.width)) - - def clear(self): - if not self.cleared: - sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL + - self.term.UP + self.term.CLEAR_EOL + - self.term.UP + self.term.CLEAR_EOL) - self.cleared = 1 diff --git a/indra/lib/python/indra/util/test_win32_manifest.py b/indra/lib/python/indra/util/test_win32_manifest.py index 0532cb0065..9863b97778 100644 --- a/indra/lib/python/indra/util/test_win32_manifest.py +++ b/indra/lib/python/indra/util/test_win32_manifest.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """\ @file test_win32_manifest.py @brief Test an assembly binding version and uniqueness in a windows dll or exe. diff --git a/indra/lib/python/uuid.py b/indra/lib/python/uuid.py deleted file mode 100644 index 0bc21a35f8..0000000000 --- a/indra/lib/python/uuid.py +++ /dev/null @@ -1,487 +0,0 @@ -r"""UUID objects (universally unique identifiers) according to RFC 4122. - -This module provides immutable UUID objects (class UUID) and the functions -uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5 -UUIDs as specified in RFC 4122. - -If all you want is a unique ID, you should probably call uuid1() or uuid4(). -Note that uuid1() may compromise privacy since it creates a UUID containing -the computer's network address. uuid4() creates a random UUID. - -Typical usage: - - >>> import uuid - - # make a UUID based on the host ID and current time - >>> uuid.uuid1() - UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') - - # make a UUID using an MD5 hash of a namespace UUID and a name - >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') - UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') - - # make a random UUID - >>> uuid.uuid4() - UUID('16fd2706-8baf-433b-82eb-8c7fada847da') - - # make a UUID using a SHA-1 hash of a namespace UUID and a name - >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') - UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') - - # make a UUID from a string of hex digits (braces and hyphens ignored) - >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') - - # convert a UUID to a string of hex digits in standard form - >>> str(x) - '00010203-0405-0607-0809-0a0b0c0d0e0f' - - # get the raw 16 bytes of the UUID - >>> x.bytes - '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' - - # make a UUID from a 16-byte string - >>> uuid.UUID(bytes=x.bytes) - UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') - -This module works with Python 2.3 or higher.""" - -__author__ = 'Ka-Ping Yee ' -__date__ = '$Date: 2006/06/12 23:15:40 $'.split()[1].replace('/', '-') -__version__ = '$Revision: 1.30 $'.split()[1] - -RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [ - 'reserved for NCS compatibility', 'specified in RFC 4122', - 'reserved for Microsoft compatibility', 'reserved for future definition'] - -class UUID(object): - """Instances of the UUID class represent UUIDs as specified in RFC 4122. - UUID objects are immutable, hashable, and usable as dictionary keys. - Converting a UUID to a string with str() yields something in the form - '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts - four possible forms: a similar string of hexadecimal digits, or a - string of 16 raw bytes as an argument named 'bytes', or a tuple of - six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and - 48-bit values respectively) as an argument named 'fields', or a single - 128-bit integer as an argument named 'int'. - - UUIDs have these read-only attributes: - - bytes the UUID as a 16-byte string - - fields a tuple of the six integer fields of the UUID, - which are also available as six individual attributes - and two derived attributes: - - time_low the first 32 bits of the UUID - time_mid the next 16 bits of the UUID - time_hi_version the next 16 bits of the UUID - clock_seq_hi_variant the next 8 bits of the UUID - clock_seq_low the next 8 bits of the UUID - node the last 48 bits of the UUID - - time the 60-bit timestamp - clock_seq the 14-bit sequence number - - hex the UUID as a 32-character hexadecimal string - - int the UUID as a 128-bit integer - - urn the UUID as a URN as specified in RFC 4122 - - variant the UUID variant (one of the constants RESERVED_NCS, - RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE) - - version the UUID version number (1 through 5, meaningful only - when the variant is RFC_4122) - """ - - def __init__(self, hex=None, bytes=None, fields=None, int=None, - version=None): - r"""Create a UUID from either a string of 32 hexadecimal digits, - a string of 16 bytes as the 'bytes' argument, a tuple of six - integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version, - 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as - the 'fields' argument, or a single 128-bit integer as the 'int' - argument. When a string of hex digits is given, curly braces, - hyphens, and a URN prefix are all optional. For example, these - expressions all yield the same UUID: - - UUID('{12345678-1234-5678-1234-567812345678}') - UUID('12345678123456781234567812345678') - UUID('urn:uuid:12345678-1234-5678-1234-567812345678') - UUID(bytes='\x12\x34\x56\x78'*4) - UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) - UUID(int=0x12345678123456781234567812345678) - - Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given. - The 'version' argument is optional; if given, the resulting UUID - will have its variant and version number set according to RFC 4122, - overriding bits in the given 'hex', 'bytes', 'fields', or 'int'. - """ - - if [hex, bytes, fields, int].count(None) != 3: - raise TypeError('need just one of hex, bytes, fields, or int') - if hex is not None: - hex = hex.replace('urn:', '').replace('uuid:', '') - hex = hex.strip('{}').replace('-', '') - if len(hex) != 32: - raise ValueError('badly formed hexadecimal UUID string') - int = long(hex, 16) - if bytes is not None: - if len(bytes) != 16: - raise ValueError('bytes is not a 16-char string') - int = long(('%02x'*16) % tuple(map(ord, bytes)), 16) - if fields is not None: - if len(fields) != 6: - raise ValueError('fields is not a 6-tuple') - (time_low, time_mid, time_hi_version, - clock_seq_hi_variant, clock_seq_low, node) = fields - if not 0 <= time_low < 1<<32L: - raise ValueError('field 1 out of range (need a 32-bit value)') - if not 0 <= time_mid < 1<<16L: - raise ValueError('field 2 out of range (need a 16-bit value)') - if not 0 <= time_hi_version < 1<<16L: - raise ValueError('field 3 out of range (need a 16-bit value)') - if not 0 <= clock_seq_hi_variant < 1<<8L: - raise ValueError('field 4 out of range (need an 8-bit value)') - if not 0 <= clock_seq_low < 1<<8L: - raise ValueError('field 5 out of range (need an 8-bit value)') - if not 0 <= node < 1<<48L: - raise ValueError('field 6 out of range (need a 48-bit value)') - clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low - int = ((time_low << 96L) | (time_mid << 80L) | - (time_hi_version << 64L) | (clock_seq << 48L) | node) - if int is not None: - if not 0 <= int < 1<<128L: - raise ValueError('int is out of range (need a 128-bit value)') - if version is not None: - if not 1 <= version <= 5: - raise ValueError('illegal version number') - # Set the variant to RFC 4122. - int &= ~(0xc000 << 48L) - int |= 0x8000 << 48L - # Set the version number. - int &= ~(0xf000 << 64L) - int |= version << 76L - self.__dict__['int'] = int - - def __cmp__(self, other): - if isinstance(other, UUID): - return cmp(self.int, other.int) - return NotImplemented - - def __hash__(self): - return hash(self.int) - - def __int__(self): - return self.int - - def __repr__(self): - return 'UUID(%r)' % str(self) - - def __setattr__(self, name, value): - raise TypeError('UUID objects are immutable') - - def __str__(self): - hex = '%032x' % self.int - return '%s-%s-%s-%s-%s' % ( - hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:]) - - def get_bytes(self): - bytes = '' - for shift in range(0, 128, 8): - bytes = chr((self.int >> shift) & 0xff) + bytes - return bytes - - bytes = property(get_bytes) - - def get_fields(self): - return (self.time_low, self.time_mid, self.time_hi_version, - self.clock_seq_hi_variant, self.clock_seq_low, self.node) - - fields = property(get_fields) - - def get_time_low(self): - return self.int >> 96L - - time_low = property(get_time_low) - - def get_time_mid(self): - return (self.int >> 80L) & 0xffff - - time_mid = property(get_time_mid) - - def get_time_hi_version(self): - return (self.int >> 64L) & 0xffff - - time_hi_version = property(get_time_hi_version) - - def get_clock_seq_hi_variant(self): - return (self.int >> 56L) & 0xff - - clock_seq_hi_variant = property(get_clock_seq_hi_variant) - - def get_clock_seq_low(self): - return (self.int >> 48L) & 0xff - - clock_seq_low = property(get_clock_seq_low) - - def get_time(self): - return (((self.time_hi_version & 0x0fffL) << 48L) | - (self.time_mid << 32L) | self.time_low) - - time = property(get_time) - - def get_clock_seq(self): - return (((self.clock_seq_hi_variant & 0x3fL) << 8L) | - self.clock_seq_low) - - clock_seq = property(get_clock_seq) - - def get_node(self): - return self.int & 0xffffffffffff - - node = property(get_node) - - def get_hex(self): - return '%032x' % self.int - - hex = property(get_hex) - - def get_urn(self): - return 'urn:uuid:' + str(self) - - urn = property(get_urn) - - def get_variant(self): - if not self.int & (0x8000 << 48L): - return RESERVED_NCS - elif not self.int & (0x4000 << 48L): - return RFC_4122 - elif not self.int & (0x2000 << 48L): - return RESERVED_MICROSOFT - else: - return RESERVED_FUTURE - - variant = property(get_variant) - - def get_version(self): - # The version bits are only meaningful for RFC 4122 UUIDs. - if self.variant == RFC_4122: - return int((self.int >> 76L) & 0xf) - - version = property(get_version) - -def _ifconfig_getnode(): - """Get the hardware address on Unix by running ifconfig.""" - import os - for dir in ['', '/sbin/', '/usr/sbin']: - try: - path = os.path.join(dir, 'ifconfig') - if os.path.exists(path): - pipe = os.popen(path) - else: - continue - except IOError: - continue - for line in pipe: - words = line.lower().split() - for i in range(len(words)): - if words[i] in ['hwaddr', 'ether']: - return int(words[i + 1].replace(':', ''), 16) - -def _ipconfig_getnode(): - """Get the hardware address on Windows by running ipconfig.exe.""" - import os, re - dirs = ['', r'c:\windows\system32', r'c:\winnt\system32'] - try: - import ctypes - buffer = ctypes.create_string_buffer(300) - ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300) - dirs.insert(0, buffer.value.decode('mbcs')) - except: - pass - for dir in dirs: - try: - pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all') - except IOError: - continue - for line in pipe: - value = line.split(':')[-1].strip().lower() - if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): - return int(value.replace('-', ''), 16) - -def _netbios_getnode(): - """Get the hardware address on Windows using NetBIOS calls. - See http://support.microsoft.com/kb/118623 for details.""" - import win32wnet, netbios - ncb = netbios.NCB() - ncb.Command = netbios.NCBENUM - ncb.Buffer = adapters = netbios.LANA_ENUM() - adapters._pack() - if win32wnet.Netbios(ncb) != 0: - return - adapters._unpack() - for i in range(adapters.length): - ncb.Reset() - ncb.Command = netbios.NCBRESET - ncb.Lana_num = ord(adapters.lana[i]) - if win32wnet.Netbios(ncb) != 0: - continue - ncb.Reset() - ncb.Command = netbios.NCBASTAT - ncb.Lana_num = ord(adapters.lana[i]) - ncb.Callname = '*'.ljust(16) - ncb.Buffer = status = netbios.ADAPTER_STATUS() - if win32wnet.Netbios(ncb) != 0: - continue - status._unpack() - bytes = map(ord, status.adapter_address) - return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) + - (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5]) - -# Thanks to Thomas Heller for ctypes and for his help with its use here. - -# If ctypes is available, use it to find system routines for UUID generation. -_uuid_generate_random = _uuid_generate_time = _UuidCreate = None -try: - import ctypes, ctypes.util - _buffer = ctypes.create_string_buffer(16) - - # The uuid_generate_* routines are provided by libuuid on at least - # Linux and FreeBSD, and provided by libc on Mac OS X. - for libname in ['uuid', 'c']: - try: - lib = ctypes.CDLL(ctypes.util.find_library(libname)) - except: - continue - if hasattr(lib, 'uuid_generate_random'): - _uuid_generate_random = lib.uuid_generate_random - if hasattr(lib, 'uuid_generate_time'): - _uuid_generate_time = lib.uuid_generate_time - - # On Windows prior to 2000, UuidCreate gives a UUID containing the - # hardware address. On Windows 2000 and later, UuidCreate makes a - # random UUID and UuidCreateSequential gives a UUID containing the - # hardware address. These routines are provided by the RPC runtime. - try: - lib = ctypes.windll.rpcrt4 - except: - lib = None - _UuidCreate = getattr(lib, 'UuidCreateSequential', - getattr(lib, 'UuidCreate', None)) -except: - pass - -def _unixdll_getnode(): - """Get the hardware address on Unix using ctypes.""" - _uuid_generate_time(_buffer) - return UUID(bytes=_buffer.raw).node - -def _windll_getnode(): - """Get the hardware address on Windows using ctypes.""" - if _UuidCreate(_buffer) == 0: - return UUID(bytes=_buffer.raw).node - -def _random_getnode(): - """Get a random node ID, with eighth bit set as suggested by RFC 4122.""" - import random - return random.randrange(0, 1<<48L) | 0x010000000000L - -_node = None - -def getnode(): - """Get the hardware address as a 48-bit integer. The first time this - runs, it may launch a separate program, which could be quite slow. If - all attempts to obtain the hardware address fail, we choose a random - 48-bit number with its eighth bit set to 1 as recommended in RFC 4122.""" - - global _node - if _node is not None: - return _node - - import sys - if sys.platform == 'win32': - getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode] - else: - getters = [_unixdll_getnode, _ifconfig_getnode] - - for getter in getters + [_random_getnode]: - try: - _node = getter() - except: - continue - if _node is not None: - return _node - -def uuid1(node=None, clock_seq=None): - """Generate a UUID from a host ID, sequence number, and the current time. - If 'node' is not given, getnode() is used to obtain the hardware - address. If 'clock_seq' is given, it is used as the sequence number; - otherwise a random 14-bit sequence number is chosen.""" - - # When the system provides a version-1 UUID generator, use it (but don't - # use UuidCreate here because its UUIDs don't conform to RFC 4122). - if _uuid_generate_time and node is clock_seq is None: - _uuid_generate_time(_buffer) - return UUID(bytes=_buffer.raw) - - import time - nanoseconds = int(time.time() * 1e9) - # 0x01b21dd213814000 is the number of 100-ns intervals between the - # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. - timestamp = int(nanoseconds/100) + 0x01b21dd213814000L - if clock_seq is None: - import random - clock_seq = random.randrange(1<<14L) # instead of stable storage - time_low = timestamp & 0xffffffffL - time_mid = (timestamp >> 32L) & 0xffffL - time_hi_version = (timestamp >> 48L) & 0x0fffL - clock_seq_low = clock_seq & 0xffL - clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL - if node is None: - node = getnode() - return UUID(fields=(time_low, time_mid, time_hi_version, - clock_seq_hi_variant, clock_seq_low, node), version=1) - -def uuid3(namespace, name): - """Generate a UUID from the MD5 hash of a namespace UUID and a name.""" - try: - # Python 2.6 - from hashlib import md5 - except ImportError: - # Python 2.5 and earlier - from md5 import new as md5 - - hash = md5(namespace.bytes + name).digest() - return UUID(bytes=hash[:16], version=3) - -def uuid4(): - """Generate a random UUID.""" - - # When the system provides a version-4 UUID generator, use it. - if _uuid_generate_random: - _uuid_generate_random(_buffer) - return UUID(bytes=_buffer.raw) - - # Otherwise, get randomness from urandom or the 'random' module. - try: - import os - return UUID(bytes=os.urandom(16), version=4) - except: - import random - bytes = [chr(random.randrange(256)) for i in range(16)] - return UUID(bytes=bytes, version=4) - -def uuid5(namespace, name): - """Generate a UUID from the SHA-1 hash of a namespace UUID and a name.""" - import sha - hash = sha.sha(namespace.bytes + name).digest() - return UUID(bytes=hash[:16], version=5) - -# The following standard UUIDs are for use with uuid3() or uuid5(). - -NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8') -NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8') -NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8') -NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8') diff --git a/indra/libhacd/hacdMicroAllocator.cpp b/indra/libhacd/hacdMicroAllocator.cpp index 47562f6a4f..664b5e8c66 100644 --- a/indra/libhacd/hacdMicroAllocator.cpp +++ b/indra/libhacd/hacdMicroAllocator.cpp @@ -436,7 +436,7 @@ class MyMicroAllocator : public MicroAllocator, public MicroChunkUpdate, public } - ~MyMicroAllocator(void) + virtual ~MyMicroAllocator() { if ( mMicroChunks ) { @@ -746,7 +746,7 @@ class MyHeapManager : public MicroHeap, public HeapManager mMicro = createMicroAllocator(this,defaultChunkSize); } - ~MyHeapManager(void) + virtual ~MyHeapManager() { releaseMicroAllocator(mMicro); } diff --git a/indra/libndhacd/CMakeLists.txt b/indra/libndhacd/CMakeLists.txt index 28c4d2f9a7..ce520fbdc6 100644 --- a/indra/libndhacd/CMakeLists.txt +++ b/indra/libndhacd/CMakeLists.txt @@ -33,3 +33,8 @@ set_source_files_properties(${libndhacd_HEADER_FILES} add_library( nd_hacdConvexDecomposition STATIC ${libndhacd_SOURCE_FILES} ${libndhacd_HEADER_FILES}) +target_link_libraries( + nd_hacdConvexDecomposition + PUBLIC + llcommon + ) diff --git a/indra/libopenjpeg/CMakeLists.txt b/indra/libopenjpeg/CMakeLists.txt index da21fe8dcb..9e41149eae 100644 --- a/indra/libopenjpeg/CMakeLists.txt +++ b/indra/libopenjpeg/CMakeLists.txt @@ -26,6 +26,7 @@ set(openjpeg_SOURCE_FILES mct.c mqc.c openjpeg.c + opj_malloc.c phix_manager.c pi.c ppix_manager.c diff --git a/indra/libopenjpeg/dwt.c b/indra/libopenjpeg/dwt.c index 0fbfc2033f..e641f15492 100644 --- a/indra/libopenjpeg/dwt.c +++ b/indra/libopenjpeg/dwt.c @@ -31,11 +31,16 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#define OPJ_SKIP_POISON +#include "opj_includes.h" + #ifdef __SSE__ #include #endif -#include "opj_includes.h" +#if defined(__GNUC__) +#pragma GCC poison malloc calloc realloc free +#endif /** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ /*@{*/ @@ -499,7 +504,7 @@ void dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, int prec) { /* */ /* Determine maximum computed resolution level for inverse wavelet transform */ /* */ -static int dwt_decode_max_resolution(opj_tcd_resolution_t* restrict r, int i) { +static int dwt_decode_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r, int i) { int mr = 1; int w; while( --i ) { @@ -531,7 +536,7 @@ static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1 v.mem = h.mem; while( --numres) { - int * restrict tiledp = tilec->data; + int * OPJ_RESTRICT tiledp = tilec->data; int j; ++tr; @@ -565,48 +570,49 @@ static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1 opj_aligned_free(h.mem); } -static void v4dwt_interleave_h(v4dwt_t* restrict w, float* restrict a, int x, int size){ - float* restrict bi = (float*) (w->wavelet + w->cas); +static void v4dwt_interleave_h(v4dwt_t* OPJ_RESTRICT w, float* OPJ_RESTRICT a, int x, int size) { + float* OPJ_RESTRICT bi = (float*)(w->wavelet + w->cas); int count = w->sn; int i, k; - for(k = 0; k < 2; ++k){ - if (count + 3 * x < size && ((size_t) a & 0x0f) == 0 && ((size_t) bi & 0x0f) == 0 && (x & 0x0f) == 0) { + for (k = 0; k < 2; ++k) { + if (count + 3 * x < size && ((size_t)a & 0x0f) == 0 && ((size_t)bi & 0x0f) == 0 && (x & 0x0f) == 0) { /* Fast code path */ - for(i = 0; i < count; ++i){ + for (i = 0; i < count; ++i) { int j = i; - bi[i*8 ] = a[j]; + bi[i * 8] = a[j]; j += x; - bi[i*8 + 1] = a[j]; + bi[i * 8 + 1] = a[j]; j += x; - bi[i*8 + 2] = a[j]; + bi[i * 8 + 2] = a[j]; j += x; - bi[i*8 + 3] = a[j]; + bi[i * 8 + 3] = a[j]; } - } else { - /* Slow code path */ - for(i = 0; i < count; ++i){ - int j = i; - bi[i*8 ] = a[j]; - j += x; - if(j > size) continue; - bi[i*8 + 1] = a[j]; - j += x; - if(j > size) continue; - bi[i*8 + 2] = a[j]; - j += x; - if(j > size) continue; - bi[i*8 + 3] = a[j]; } + else { + /* Slow code path */ + for (i = 0; i < count; ++i) { + int j = i; + bi[i * 8] = a[j]; + j += x; + if (j > size) continue; + bi[i * 8 + 1] = a[j]; + j += x; + if (j > size) continue; + bi[i * 8 + 2] = a[j]; + j += x; + if (j > size) continue; + bi[i * 8 + 3] = a[j]; + } } - bi = (float*) (w->wavelet + 1 - w->cas); + bi = (float*)(w->wavelet + 1 - w->cas); a += w->sn; size -= w->sn; count = w->dn; } } -static void v4dwt_interleave_v(v4dwt_t* restrict v , float* restrict a , int x){ - v4* restrict bi = v->wavelet + v->cas; +static void v4dwt_interleave_v(v4dwt_t* OPJ_RESTRICT v , float* OPJ_RESTRICT a , int x){ + v4* OPJ_RESTRICT bi = v->wavelet + v->cas; int i; for(i = 0; i < v->sn; ++i){ memcpy(&bi[i*2], &a[i*x], 4 * sizeof(float)); @@ -621,7 +627,7 @@ static void v4dwt_interleave_v(v4dwt_t* restrict v , float* restrict a , int x){ #ifdef __SSE__ static void v4dwt_decode_step1_sse(v4* w, int count, const __m128 c){ - __m128* restrict vw = (__m128*) w; + __m128* OPJ_RESTRICT vw = (__m128*) w; int i; /* 4x unrolled loop */ for(i = 0; i < count >> 2; ++i){ @@ -642,22 +648,39 @@ static void v4dwt_decode_step1_sse(v4* w, int count, const __m128 c){ } static void v4dwt_decode_step2_sse(v4* l, v4* w, int k, int m, __m128 c){ - __m128* restrict vl = (__m128*) l; - __m128* restrict vw = (__m128*) w; + __m128* OPJ_RESTRICT vl = (__m128*) l; + __m128* OPJ_RESTRICT vw = (__m128*) w; int i; __m128 tmp1, tmp2, tmp3; tmp1 = vl[0]; - for(i = 0; i < m; ++i){ + for (i = 0; i < m - 3; i += 4) { + __m128 tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; + tmp2 = vw[-1]; + tmp3 = vw[0]; + tmp4 = vw[1]; + tmp5 = vw[2]; + tmp6 = vw[3]; + tmp7 = vw[4]; + tmp8 = vw[5]; + tmp9 = vw[6]; + vw[-1] = _mm_add_ps(tmp2, _mm_mul_ps(_mm_add_ps(tmp1, tmp3), c)); + vw[1] = _mm_add_ps(tmp4, _mm_mul_ps(_mm_add_ps(tmp3, tmp5), c)); + vw[3] = _mm_add_ps(tmp6, _mm_mul_ps(_mm_add_ps(tmp5, tmp7), c)); + vw[5] = _mm_add_ps(tmp8, _mm_mul_ps(_mm_add_ps(tmp7, tmp9), c)); + tmp1 = tmp9; + vw += 8; + } + for ( ; i < m; ++i) { tmp2 = vw[-1]; tmp3 = vw[ 0]; vw[-1] = _mm_add_ps(tmp2, _mm_mul_ps(_mm_add_ps(tmp1, tmp3), c)); tmp1 = tmp3; vw += 2; } - vl = vw - 2; if(m >= k){ return; } + vl = vw - 2; c = _mm_add_ps(c, c); c = _mm_mul_ps(c, vl[0]); for(; m < k; ++m){ @@ -670,7 +693,7 @@ static void v4dwt_decode_step2_sse(v4* l, v4* w, int k, int m, __m128 c){ #else static void v4dwt_decode_step1(v4* w, int count, const float c){ - float* restrict fw = (float*) w; + float* OPJ_RESTRICT fw = (float*) w; int i; for(i = 0; i < count; ++i){ float tmp1 = fw[i*8 ]; @@ -685,8 +708,8 @@ static void v4dwt_decode_step1(v4* w, int count, const float c){ } static void v4dwt_decode_step2(v4* l, v4* w, int k, int m, float c){ - float* restrict fl = (float*) l; - float* restrict fw = (float*) w; + float* OPJ_RESTRICT fl = (float*) l; + float* OPJ_RESTRICT fw = (float*) w; int i; for(i = 0; i < m; ++i){ float tmp1_1 = fl[0]; @@ -737,42 +760,44 @@ static void v4dwt_decode_step2(v4* l, v4* w, int k, int m, float c){ /* */ /* Inverse 9-7 wavelet transform in 1-D. */ /* */ -static void v4dwt_decode(v4dwt_t* restrict dwt){ +static void v4dwt_decode(v4dwt_t* OPJ_RESTRICT dwt){ int a, b; if(dwt->cas == 0) { - if(!((dwt->dn > 0) || (dwt->sn > 1))){ + if (dwt->dn <= 0 && dwt->sn <= 1) { return; } a = 0; b = 1; }else{ - if(!((dwt->sn > 0) || (dwt->dn > 1))) { + if (dwt->sn <= 0 && dwt->dn <= 1) { return; } a = 1; b = 0; } + v4* OPJ_RESTRICT waveleta = dwt->wavelet + a; + v4* OPJ_RESTRICT waveletb = dwt->wavelet + b; #ifdef __SSE__ - v4dwt_decode_step1_sse(dwt->wavelet+a, dwt->sn, _mm_set1_ps(K)); - v4dwt_decode_step1_sse(dwt->wavelet+b, dwt->dn, _mm_set1_ps(c13318)); - v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(dwt_delta)); - v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_gamma)); - v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(dwt_beta)); - v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_alpha)); + v4dwt_decode_step1_sse(waveleta, dwt->sn, _mm_set1_ps(K)); + v4dwt_decode_step1_sse(waveletb, dwt->dn, _mm_set1_ps(c13318)); + v4dwt_decode_step2_sse(waveletb, waveleta + 1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(dwt_delta)); + v4dwt_decode_step2_sse(waveleta, waveletb + 1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_gamma)); + v4dwt_decode_step2_sse(waveletb, waveleta + 1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(dwt_beta)); + v4dwt_decode_step2_sse(waveleta, waveletb + 1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_alpha)); #else - v4dwt_decode_step1(dwt->wavelet+a, dwt->sn, K); - v4dwt_decode_step1(dwt->wavelet+b, dwt->dn, c13318); - v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), dwt_delta); - v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_gamma); - v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), dwt_beta); - v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_alpha); + v4dwt_decode_step1(waveleta, dwt->sn, K); + v4dwt_decode_step1(waveletb, dwt->dn, c13318); + v4dwt_decode_step2(waveletb, waveleta + 1, dwt->sn, int_min(dwt->sn, dwt->dn-a), dwt_delta); + v4dwt_decode_step2(waveleta, waveletb + 1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_gamma); + v4dwt_decode_step2(waveletb, waveleta + 1, dwt->sn, int_min(dwt->sn, dwt->dn-a), dwt_beta); + v4dwt_decode_step2(waveleta, waveletb + 1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_alpha); #endif } /* */ /* Inverse 9-7 wavelet transform in 2-D. */ /* */ -void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){ +void dwt_decode_real(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec, int numres){ v4dwt_t h; v4dwt_t v; @@ -787,7 +812,7 @@ void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){ v.wavelet = h.wavelet; while( --numres) { - float * restrict aj = (float*) tilec->data; + float * OPJ_RESTRICT aj = (float*) tilec->data; int bufsize = (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0); int j; diff --git a/indra/libopenjpeg/mct.c b/indra/libopenjpeg/mct.c index 870993b06d..d55a67062e 100644 --- a/indra/libopenjpeg/mct.c +++ b/indra/libopenjpeg/mct.c @@ -29,11 +29,16 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#define OPJ_SKIP_POISON +#include "opj_includes.h" + #ifdef __SSE__ #include #endif -#include "opj_includes.h" +#if defined(__GNUC__) +#pragma GCC poison malloc calloc realloc free +#endif /* */ /* This table contains the norms of the basis function of the reversible MCT. */ @@ -49,17 +54,38 @@ static const double mct_norms_real[3] = { 1.732, 1.805, 1.573 }; /* Foward reversible MCT. */ /* */ void mct_encode( - int* restrict c0, - int* restrict c1, - int* restrict c2, + int* OPJ_RESTRICT c0, + int* OPJ_RESTRICT c1, + int* OPJ_RESTRICT c2, int n) { - int i; - for(i = 0; i < n; ++i) { + int i = 0; +#ifdef __SSE2__ + /* Buffers are normally aligned on 16 bytes... */ + if (((size_t)c0 & 0xf) == 0 && ((size_t)c1 & 0xf) == 0 && ((size_t)c2 & 0xf) == 0) { + const int cnt = n & ~3U; + for (; i < cnt; i += 4) { + __m128i y, u, v; + __m128i r = _mm_load_si128((const __m128i*) & (c0[i])); + __m128i g = _mm_load_si128((const __m128i*) & (c1[i])); + __m128i b = _mm_load_si128((const __m128i*) & (c2[i])); + y = _mm_add_epi32(g, g); + y = _mm_add_epi32(y, b); + y = _mm_add_epi32(y, r); + y = _mm_srai_epi32(y, 2); + u = _mm_sub_epi32(b, g); + v = _mm_sub_epi32(r, g); + _mm_store_si128((__m128i*) & (c0[i]), y); + _mm_store_si128((__m128i*) & (c1[i]), u); + _mm_store_si128((__m128i*) & (c2[i]), v); + } + } +#endif + for (; i < n; ++i) { int r = c0[i]; int g = c1[i]; int b = c2[i]; - int y = (r + (g * 2) + b) >> 2; + int y = (r + g + g + b) >> 2; int u = b - g; int v = r - g; c0[i] = y; @@ -72,13 +98,32 @@ void mct_encode( /* Inverse reversible MCT. */ /* */ void mct_decode( - int* restrict c0, - int* restrict c1, - int* restrict c2, + int* OPJ_RESTRICT c0, + int* OPJ_RESTRICT c1, + int* OPJ_RESTRICT c2, int n) { - int i; - for (i = 0; i < n; ++i) { + int i = 0; +#ifdef __SSE2__ + /* Buffers are normally aligned on 16 bytes... */ + if (((size_t)c0 & 0xf) == 0 && ((size_t)c1 & 0xf) == 0 && ((size_t)c2 & 0xf) == 0) { + const int cnt = n & ~3U; + for (; i < cnt; i += 4) { + __m128i r, g, b; + __m128i y = _mm_load_si128((const __m128i*) & (c0[i])); + __m128i u = _mm_load_si128((const __m128i*) & (c1[i])); + __m128i v = _mm_load_si128((const __m128i*) & (c2[i])); + g = y; + g = _mm_sub_epi32(g, _mm_srai_epi32(_mm_add_epi32(u, v), 2)); + r = _mm_add_epi32(v, g); + b = _mm_add_epi32(u, g); + _mm_store_si128((__m128i*) & (c0[i]), r); + _mm_store_si128((__m128i*) & (c1[i]), g); + _mm_store_si128((__m128i*) & (c2[i]), b); +} + } +#endif + for (; i < n; ++i) { int y = c0[i]; int u = c1[i]; int v = c2[i]; @@ -102,13 +147,119 @@ double mct_getnorm(int compno) { /* Foward irreversible MCT. */ /* */ void mct_encode_real( - int* restrict c0, - int* restrict c1, - int* restrict c2, + int* OPJ_RESTRICT c0, + int* OPJ_RESTRICT c1, + int* OPJ_RESTRICT c2, int n) { - int i; - for(i = 0; i < n; ++i) { + int i = 0; +#ifdef __SSE4_1__ + /* Buffers are normally aligned on 16 bytes... */ + if (((size_t)c0 & 0xf) == 0 && ((size_t)c1 & 0xf) == 0 && ((size_t)c2 & 0xf) == 0) { + const int cnt = n & ~3U; + const __m128i ry = _mm_set1_epi32(2449); + const __m128i gy = _mm_set1_epi32(4809); + const __m128i by = _mm_set1_epi32(934); + const __m128i ru = _mm_set1_epi32(1382); + const __m128i gu = _mm_set1_epi32(2714); + const __m128i gv = _mm_set1_epi32(3430); + const __m128i bv = _mm_set1_epi32(666); + const __m128i mulround = _mm_shuffle_epi32(_mm_cvtsi32_si128(4096), _MM_SHUFFLE(1, 0, 1, 0)); + for (; i < cnt; i += 4) { + __m128i lo, hi, y, u, v; + __m128i r = _mm_load_si128((const __m128i*) & (c0[i])); + __m128i g = _mm_load_si128((const __m128i*) & (c1[i])); + __m128i b = _mm_load_si128((const __m128i*) & (c2[i])); + + hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(r, ry); + hi = _mm_mul_epi32(hi, ry); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + y = _mm_blend_epi16(lo, hi, 0xCC); + + hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(g, gy); + hi = _mm_mul_epi32(hi, gy); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC)); + + hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(b, by); + hi = _mm_mul_epi32(hi, by); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC)); + _mm_store_si128((__m128i*) & (c0[i]), y); + + lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 2, 0))); + hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 3, 1))); + lo = _mm_slli_epi64(lo, 12); + hi = _mm_slli_epi64(hi, 12); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + u = _mm_blend_epi16(lo, hi, 0xCC); + + hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(r, ru); + hi = _mm_mul_epi32(hi, ru); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC)); + + hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(g, gu); + hi = _mm_mul_epi32(hi, gu); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC)); + _mm_store_si128((__m128i*) & (c1[i]), u); + + lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 2, 0))); + hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 3, 1))); + lo = _mm_slli_epi64(lo, 12); + hi = _mm_slli_epi64(hi, 12); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + v = _mm_blend_epi16(lo, hi, 0xCC); + + hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(g, gv); + hi = _mm_mul_epi32(hi, gv); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC)); + + hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(b, bv); + hi = _mm_mul_epi32(hi, bv); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC)); + _mm_store_si128((__m128i*) & (c2[i]), v); + } + } +#endif + for (; i < n; ++i) { int r = c0[i]; int g = c1[i]; int b = c2[i]; @@ -125,19 +276,21 @@ void mct_encode_real( /* Inverse irreversible MCT. */ /* */ void mct_decode_real( - float* restrict c0, - float* restrict c1, - float* restrict c2, + float* OPJ_RESTRICT c0, + float* OPJ_RESTRICT c1, + float* OPJ_RESTRICT c2, int n) { int i; #ifdef __SSE__ + int count; __m128 vrv, vgu, vgv, vbu; vrv = _mm_set1_ps(1.402f); vgu = _mm_set1_ps(0.34413f); vgv = _mm_set1_ps(0.71414f); vbu = _mm_set1_ps(1.772f); - for (i = 0; i < (n >> 3); ++i) { + count = n >> 3; + for (i = 0; i < count; ++i) { __m128 vy, vu, vv; __m128 vr, vg, vb; @@ -174,7 +327,7 @@ void mct_decode_real( float u = c1[i]; float v = c2[i]; float r = y + (v * 1.402f); - float g = y - (u * 0.34413f) - (v * (0.71414f)); + float g = y - (u * 0.34413f) - (v * 0.71414f); float b = y + (u * 1.772f); c0[i] = r; c1[i] = g; diff --git a/indra/libopenjpeg/openjpeg.h b/indra/libopenjpeg/openjpeg.h index 59147c8b3d..ba88114154 100644 --- a/indra/libopenjpeg/openjpeg.h +++ b/indra/libopenjpeg/openjpeg.h @@ -40,33 +40,71 @@ ========================================================== */ +/* +The inline keyword is supported by C99 but not by C90. +Most compilers implement their own version of this keyword ... +*/ +#ifndef INLINE +#if defined(_MSC_VER) +#define INLINE __forceinline +#elif defined(__GNUC__) +#define INLINE __inline__ +#elif defined(__MWERKS__) +#define INLINE inline +#else +/* add other compilers here ... */ +#define INLINE +#endif /* defined() */ +#endif /* INLINE */ #if defined(OPJ_STATIC) || !defined(_WIN32) #define OPJ_API #define OPJ_CALLCONV #else #define OPJ_CALLCONV __stdcall /* -The following ifdef block is the standard way of creating macros which make exporting +The following ifdef block is the standard way of creating macros which make exporting from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS symbol defined on the command line. this symbol should not be defined on any project -that uses this DLL. This way any other project whose source files include this file see -OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols +that uses this DLL. This way any other project whose source files include this file see +OPJ_API functions as being imported from a DLL, whereas this DLL sees symbols defined with this macro as being exported. */ -#if defined(OPJ_EXPORTS) || defined(DLL_EXPORT) -#define OPJ_API __declspec(dllexport) -#else -#define OPJ_API __declspec(dllimport) -#endif /* OPJ_EXPORTS */ +# if defined(OPJ_EXPORTS) || defined(DLL_EXPORT) +# define OPJ_API __declspec(dllexport) +# else +# define OPJ_API __declspec(dllimport) +# endif /* OPJ_EXPORTS */ #endif /* !OPJ_STATIC || !_WIN32 */ typedef int opj_bool; #define OPJ_TRUE 1 #define OPJ_FALSE 0 +typedef char OPJ_CHAR; +typedef float OPJ_FLOAT32; +typedef double OPJ_FLOAT64; +typedef unsigned char OPJ_BYTE; + +#include "opj_stdint.h" + +typedef int8_t OPJ_INT8; +typedef uint8_t OPJ_UINT8; +typedef int16_t OPJ_INT16; +typedef uint16_t OPJ_UINT16; +typedef int32_t OPJ_INT32; +typedef uint32_t OPJ_UINT32; +typedef int64_t OPJ_INT64; +typedef uint64_t OPJ_UINT64; + +typedef int64_t OPJ_OFF_T; /* 64-bit file offset type */ + +#include +typedef size_t OPJ_SIZE_T; + /* Avoid compile-time warning because parameter is not used */ #define OPJ_ARG_NOT_USED(x) (void)(x) -/* + +/* ========================================================== Useful constant definitions ========================================================== diff --git a/indra/libopenjpeg/opj_includes.h b/indra/libopenjpeg/opj_includes.h index 2b5866a999..e4d2374da0 100644 --- a/indra/libopenjpeg/opj_includes.h +++ b/indra/libopenjpeg/opj_includes.h @@ -40,6 +40,8 @@ #include #include #include +#include +#include /* ========================================================== @@ -54,56 +56,115 @@ ========================================================== */ +/* Are restricted pointers available? (C99) */ +#if (__STDC_VERSION__ >= 199901L) +#define OPJ_RESTRICT restrict +#else +/* Not a C99 compiler */ +#if defined(__GNUC__) +#define OPJ_RESTRICT __restrict__ +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) +#define OPJ_RESTRICT __restrict +#else +#define OPJ_RESTRICT /* restrict */ +#endif +#endif + /* Ignore GCC attributes if this is not GCC */ #ifndef __GNUC__ #define __attribute__(x) /* __attribute__(x) */ #endif -/* -The inline keyword is supported by C99 but not by C90. -Most compilers implement their own version of this keyword ... -*/ -#ifndef INLINE - #if defined(_MSC_VER) - #define INLINE __forceinline - #elif defined(__GNUC__) - #define INLINE __inline__ - #elif defined(__MWERKS__) - #define INLINE inline - #else - /* add other compilers here ... */ - #define INLINE - #endif /* defined() */ -#endif /* INLINE */ -/* Are restricted pointers available? (C99) */ -#if (__STDC_VERSION__ != 199901L) - /* Not a C99 compiler */ - #ifdef __GNUC__ - #define restrict __restrict__ - #else - #define restrict /* restrict */ - #endif -#endif +/* MSVC before 2013 and Borland C do not have lrintf */ +#if defined(_MSC_VER) +#include +static INLINE long opj_lrintf(float f) +{ +#ifdef _M_X64 + return _mm_cvt_ss2si(_mm_load_ss(&f)); -/* MSVC and Borland C do not have lrintf */ -#if defined(_MSC_VER) || defined(__BORLANDC__) -static INLINE long lrintf(float f){ + /* commented out line breaks many tests */ + /* return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f)); */ +#elif defined(_M_IX86) + int i; + _asm{ + fld f + fistp i + }; + + return i; +#else + return (long)((f>0.0f) ? (f + 0.5f) : (f - 0.5f)); +#endif +} +#elif defined(__BORLANDC__) +static INLINE long opj_lrintf(float f) +{ #ifdef _M_X64 - return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f)); + return (long)((f > 0.0f) ? (f + 0.5f) : (f - 0.5f)); #else int i; - - _asm{ + + _asm { fld f fistp i }; - + return i; #endif } +#else +static INLINE long opj_lrintf(float f) +{ + return lrintf(f); +} +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1400) +#define vsnprintf _vsnprintf +#endif + +/* MSVC x86 is really bad at doing int64 = int32 * int32 on its own. Use intrinsic. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) && defined(_M_IX86) +# include +# pragma intrinsic(__emul) +#endif + +/* Apparently Visual Studio doesn't define __SSE__ / __SSE2__ macros */ +#if defined(_M_X64) +/* Intel 64bit support SSE and SSE2 */ +# ifndef __SSE__ +# define __SSE__ 1 +# endif +# ifndef __SSE2__ +# define __SSE2__ 1 +# endif +# if !defined(__SSE4_1__) && defined(__AVX__) +# define __SSE4_1__ 1 +# endif #endif +/* For x86, test the value of the _M_IX86_FP macro. */ +/* See https://msdn.microsoft.com/en-us/library/b0084kay.aspx */ +#if defined(_M_IX86_FP) +# if _M_IX86_FP >= 1 +# ifndef __SSE__ +# define __SSE__ 1 +# endif +# endif +# if _M_IX86_FP >= 2 +# ifndef __SSE2__ +# define __SSE2__ 1 +# endif +# endif +#endif + +/* Type to use for bit-fields in internal headers */ +typedef unsigned int OPJ_BITFIELD; + +#define OPJ_UNUSED(x) (void)x + #include "j2k_lib.h" #include "opj_malloc.h" #include "event.h" diff --git a/indra/libopenjpeg/opj_malloc.c b/indra/libopenjpeg/opj_malloc.c new file mode 100644 index 0000000000..dca91bfcbe --- /dev/null +++ b/indra/libopenjpeg/opj_malloc.c @@ -0,0 +1,249 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2015, Mathieu Malaterre + * Copyright (c) 2015, Matthieu Darbois + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#define OPJ_SKIP_POISON +#include "opj_includes.h" + +#if defined(OPJ_HAVE_MALLOC_H) && defined(OPJ_HAVE_MEMALIGN) +# include +#endif + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +static INLINE void *opj_aligned_alloc_n(size_t alignment, size_t size) +{ + void* ptr; + + /* alignment shall be power of 2 */ + assert((alignment != 0U) && ((alignment & (alignment - 1U)) == 0U)); + /* alignment shall be at least sizeof(void*) */ + assert(alignment >= sizeof(void*)); + + if (size == 0U) { /* prevent implementation defined behavior of realloc */ + return NULL; + } + +#if defined(OPJ_HAVE_POSIX_MEMALIGN) + /* aligned_alloc requires c11, restrict to posix_memalign for now. Quote: + * This function was introduced in POSIX 1003.1d. Although this function is + * superseded by aligned_alloc, it is more portable to older POSIX systems + * that do not support ISO C11. */ + if (posix_memalign(&ptr, alignment, size)) { + ptr = NULL; + } + /* older linux */ +#elif defined(OPJ_HAVE_MEMALIGN) + ptr = memalign(alignment, size); + /* _MSC_VER */ +#elif defined(OPJ_HAVE__ALIGNED_MALLOC) + ptr = _aligned_malloc(size, alignment); +#else + /* + * Generic aligned malloc implementation. + * Uses size_t offset for the integer manipulation of the pointer, + * as uintptr_t is not available in C89 to do + * bitwise operations on the pointer itself. + */ + alignment--; + { + size_t offset; + OPJ_UINT8 *mem; + + /* Room for padding and extra pointer stored in front of allocated area */ + size_t overhead = alignment + sizeof(void *); + + /* let's be extra careful */ + assert(alignment <= (SIZE_MAX - sizeof(void *))); + + /* Avoid integer overflow */ + if (size > (SIZE_MAX - overhead)) { + return NULL; + } + + mem = (OPJ_UINT8*)malloc(size + overhead); + if (mem == NULL) { + return mem; + } + /* offset = ((alignment + 1U) - ((size_t)(mem + sizeof(void*)) & alignment)) & alignment; */ + /* Use the fact that alignment + 1U is a power of 2 */ + offset = ((alignment ^ ((size_t)(mem + sizeof(void*)) & alignment)) + 1U) & + alignment; + ptr = (void *)(mem + sizeof(void*) + offset); + ((void**) ptr)[-1] = mem; + } +#endif + return ptr; +} +static INLINE void *opj_aligned_realloc_n(void *ptr, size_t alignment, + size_t new_size) +{ + void *r_ptr; + + /* alignment shall be power of 2 */ + assert((alignment != 0U) && ((alignment & (alignment - 1U)) == 0U)); + /* alignment shall be at least sizeof(void*) */ + assert(alignment >= sizeof(void*)); + + if (new_size == 0U) { /* prevent implementation defined behavior of realloc */ + return NULL; + } + + /* no portable aligned realloc */ +#if defined(OPJ_HAVE_POSIX_MEMALIGN) || defined(OPJ_HAVE_MEMALIGN) + /* glibc doc states one can mix aligned malloc with realloc */ + r_ptr = realloc(ptr, new_size); /* fast path */ + /* we simply use `size_t` to cast, since we are only interest in binary AND + * operator */ + if (((size_t)r_ptr & (alignment - 1U)) != 0U) { + /* this is non-trivial to implement a portable aligned realloc, so use a + * simple approach where we do not need a function that return the size of an + * allocated array (eg. _msize on Windows, malloc_size on MacOS, + * malloc_usable_size on systems with glibc) */ + void *a_ptr = opj_aligned_alloc_n(alignment, new_size); + if (a_ptr != NULL) { + memcpy(a_ptr, r_ptr, new_size); + } + free(r_ptr); + r_ptr = a_ptr; + } + /* _MSC_VER */ +#elif defined(OPJ_HAVE__ALIGNED_MALLOC) + r_ptr = _aligned_realloc(ptr, new_size, alignment); +#else + if (ptr == NULL) { + return opj_aligned_alloc_n(alignment, new_size); + } + alignment--; + { + void *oldmem; + OPJ_UINT8 *newmem; + size_t overhead = alignment + sizeof(void *); + + /* let's be extra careful */ + assert(alignment <= (SIZE_MAX - sizeof(void *))); + + /* Avoid integer overflow */ + if (new_size > SIZE_MAX - overhead) { + return NULL; + } + + oldmem = ((void**) ptr)[-1]; + newmem = (OPJ_UINT8*)realloc(oldmem, new_size + overhead); + if (newmem == NULL) { + return newmem; + } + + if (newmem == oldmem) { + r_ptr = ptr; + } else { + size_t old_offset; + size_t new_offset; + + /* realloc created a new copy, realign the copied memory block */ + old_offset = (size_t)((OPJ_UINT8*)ptr - (OPJ_UINT8*)oldmem); + + /* offset = ((alignment + 1U) - ((size_t)(mem + sizeof(void*)) & alignment)) & alignment; */ + /* Use the fact that alignment + 1U is a power of 2 */ + new_offset = ((alignment ^ ((size_t)(newmem + sizeof(void*)) & alignment)) + + 1U) & alignment; + new_offset += sizeof(void*); + r_ptr = (void *)(newmem + new_offset); + + if (new_offset != old_offset) { + memmove(newmem + new_offset, newmem + old_offset, new_size); + } + ((void**) r_ptr)[-1] = newmem; + } + } +#endif + return r_ptr; +} +void * opj_malloc(size_t size) +{ + if (size == 0U) { /* prevent implementation defined behavior of realloc */ + return NULL; + } + return malloc(size); +} +void * opj_calloc(size_t num, size_t size) +{ + if (num == 0 || size == 0) { + /* prevent implementation defined behavior of realloc */ + return NULL; + } + return calloc(num, size); +} + +void *opj_aligned_malloc(size_t size) +{ + return opj_aligned_alloc_n(16U, size); +} +void * opj_aligned_realloc(void *ptr, size_t size) +{ + return opj_aligned_realloc_n(ptr, 16U, size); +} + +void *opj_aligned_32_malloc(size_t size) +{ + return opj_aligned_alloc_n(32U, size); +} +void * opj_aligned_32_realloc(void *ptr, size_t size) +{ + return opj_aligned_realloc_n(ptr, 32U, size); +} + +void opj_aligned_free(void* ptr) +{ +#if defined(OPJ_HAVE_POSIX_MEMALIGN) || defined(OPJ_HAVE_MEMALIGN) + free(ptr); +#elif defined(OPJ_HAVE__ALIGNED_MALLOC) + _aligned_free(ptr); +#else + /* Generic implementation has malloced pointer stored in front of used area */ + if (ptr != NULL) { + free(((void**) ptr)[-1]); + } +#endif +} + +void * opj_realloc(void *ptr, size_t new_size) +{ + if (new_size == 0U) { /* prevent implementation defined behavior of realloc */ + return NULL; + } + return realloc(ptr, new_size); +} +void opj_free(void *ptr) +{ + free(ptr); +} diff --git a/indra/libopenjpeg/opj_malloc.h b/indra/libopenjpeg/opj_malloc.h index aef2ee3b8c..4eacfa152d 100644 --- a/indra/libopenjpeg/opj_malloc.h +++ b/indra/libopenjpeg/opj_malloc.h @@ -1,4 +1,9 @@ /* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2007, Callum Lerwick * All rights reserved. @@ -24,8 +29,10 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __OPJ_MALLOC_H -#define __OPJ_MALLOC_H +#ifndef OPJ_MALLOC_H +#define OPJ_MALLOC_H + +#include /** @file opj_malloc.h @brief Internal functions @@ -36,6 +43,17 @@ The functions in opj_malloc.h are internal utilities used for memory management. /** @defgroup MISC MISC - Miscellaneous internal functions */ /*@{*/ +/* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */ +#ifdef _WIN32 +#define OPJ_HAVE__ALIGNED_MALLOC +#else /* Not _WIN32 */ +#if defined(__sun) +#define OPJ_HAVE_MEMALIGN +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) +#define OPJ_HAVE_POSIX_MEMALIGN +#endif +#endif + /** @name Exported functions */ /*@{*/ /* ----------------------------------------------------------------------- */ @@ -45,90 +63,32 @@ Allocate an uninitialized memory block @param size Bytes to allocate @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available */ -#ifdef ALLOC_PERF_OPT -void * OPJ_CALLCONV opj_malloc(size_t size); -#else -#define opj_malloc(size) malloc(size) -#endif +void * opj_malloc(size_t size); /** Allocate a memory block with elements initialized to 0 -@param num Blocks to allocate -@param size Bytes per block to allocate +@param numOfElements Blocks to allocate +@param sizeOfElements Bytes per block to allocate @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available */ -#ifdef ALLOC_PERF_OPT -void * OPJ_CALLCONV opj_calloc(size_t _NumOfElements, size_t _SizeOfElements); -#else -#define opj_calloc(num, size) calloc(num, size) -#endif +void * opj_calloc(size_t numOfElements, size_t sizeOfElements); /** -Allocate memory aligned to a 16 byte boundry +Allocate memory aligned to a 16 byte boundary @param size Bytes to allocate @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available */ -/* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */ -#ifdef _WIN32 - /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */ - #ifdef __GNUC__ - #include - #define HAVE_MM_MALLOC - #else /* MSVC, Intel C++ */ - #include - #ifdef _mm_malloc - #define HAVE_MM_MALLOC - #endif - #endif -#else /* Not _WIN32 */ - #if defined(__sun) - #define HAVE_MEMALIGN - #elif defined(__FreeBSD__) - #define HAVE_POSIX_MEMALIGN - /* Linux x86_64 and OSX always align allocations to 16 bytes */ - #elif !defined(__amd64__) && !defined(__APPLE__) && !defined(_AIX) - #define HAVE_MEMALIGN - #include - #endif -#endif +void * opj_aligned_malloc(size_t size); +void * opj_aligned_realloc(void *ptr, size_t size); +void opj_aligned_free(void* ptr); -#define opj_aligned_malloc(size) malloc(size) -#define opj_aligned_free(m) free(m) - -#ifdef HAVE_MM_MALLOC - #undef opj_aligned_malloc - #define opj_aligned_malloc(size) _mm_malloc(size, 16) - #undef opj_aligned_free - #define opj_aligned_free(m) _mm_free(m) -#endif - -#ifdef HAVE_MEMALIGN - extern void* memalign(size_t, size_t); - #undef opj_aligned_malloc - #define opj_aligned_malloc(size) memalign(16, (size)) - #undef opj_aligned_free - #define opj_aligned_free(m) free(m) -#endif - -#ifdef HAVE_POSIX_MEMALIGN - #undef opj_aligned_malloc - extern int posix_memalign(void**, size_t, size_t); - - static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){ - void* mem = NULL; - posix_memalign(&mem, 16, size); - return mem; - } - #undef opj_aligned_free - #define opj_aligned_free(m) free(m) -#endif - -#ifdef ALLOC_PERF_OPT - #undef opj_aligned_malloc - #define opj_aligned_malloc(size) opj_malloc(size) - #undef opj_aligned_free - #define opj_aligned_free(m) opj_free(m) -#endif +/** +Allocate memory aligned to a 32 byte boundary +@param size Bytes to allocate +@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +*/ +void * opj_aligned_32_malloc(size_t size); +void * opj_aligned_32_realloc(void *ptr, size_t size); /** Reallocate memory blocks. @@ -136,23 +96,15 @@ Reallocate memory blocks. @param s New size in bytes @return Returns a void pointer to the reallocated (and possibly moved) memory block */ -#ifdef ALLOC_PERF_OPT -void * OPJ_CALLCONV opj_realloc(void * m, size_t s); -#else -#define opj_realloc(m, s) realloc(m, s) -#endif +void * opj_realloc(void * m, size_t s); /** Deallocates or frees a memory block. @param m Previously allocated memory block to be freed */ -#ifdef ALLOC_PERF_OPT -void OPJ_CALLCONV opj_free(void * m); -#else -#define opj_free(m) free(m) -#endif +void opj_free(void * m); -#ifdef __GNUC__ +#if defined(__GNUC__) && !defined(OPJ_SKIP_POISON) #pragma GCC poison malloc calloc realloc free #endif @@ -161,5 +113,5 @@ void OPJ_CALLCONV opj_free(void * m); /*@}*/ -#endif /* __OPJ_MALLOC_H */ +#endif /* OPJ_MALLOC_H */ diff --git a/indra/libopenjpeg/opj_stdint.h b/indra/libopenjpeg/opj_stdint.h new file mode 100644 index 0000000000..337ad85001 --- /dev/null +++ b/indra/libopenjpeg/opj_stdint.h @@ -0,0 +1,51 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2012, Mathieu Malaterre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef OPJ_STDINT_H +#define OPJ_STDINT_H + +#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || _MSC_VER >= 1900 +#include +#else +#if defined(_WIN32) +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +#error unsupported platform +#endif +#endif + +#endif /* OPJ_STDINT_H */ diff --git a/indra/libopenjpeg/t1.c b/indra/libopenjpeg/t1.c index 93b997b799..6cb8acad15 100644 --- a/indra/libopenjpeg/t1.c +++ b/indra/libopenjpeg/t1.c @@ -1427,7 +1427,7 @@ void t1_encode_cblks( opj_tcd_resolution_t *res = &tilec->resolutions[resno]; for (bandno = 0; bandno < res->numbands; ++bandno) { - opj_tcd_band_t* restrict band = &res->bands[bandno]; + opj_tcd_band_t* OPJ_RESTRICT band = &res->bands[bandno]; int bandconst = 8192 * 8192 / ((int) floor(band->stepsize * 8192)); for (precno = 0; precno < res->pw * res->ph; ++precno) { @@ -1435,8 +1435,8 @@ void t1_encode_cblks( for (cblkno = 0; cblkno < prc->cw * prc->ch; ++cblkno) { opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; - int* restrict datap; - int* restrict tiledp; + int* OPJ_RESTRICT datap; + int* OPJ_RESTRICT tiledp; int cblk_w; int cblk_h; int i, j; @@ -1517,14 +1517,14 @@ void t1_decode_cblks( opj_tcd_resolution_t* res = &tilec->resolutions[resno]; for (bandno = 0; bandno < res->numbands; ++bandno) { - opj_tcd_band_t* restrict band = &res->bands[bandno]; + opj_tcd_band_t* OPJ_RESTRICT band = &res->bands[bandno]; for (precno = 0; precno < res->pw * res->ph; ++precno) { opj_tcd_precinct_t* precinct = &band->precincts[precno]; for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; - int* restrict datap; + int* OPJ_RESTRICT datap; int cblk_w, cblk_h; int x, y; int i, j; @@ -1566,7 +1566,7 @@ void t1_decode_cblks( } if (tccp->qmfbid == 1) { - int* restrict tiledp = &tilec->data[(y * tile_w) + x]; + int* OPJ_RESTRICT tiledp = &tilec->data[(y * tile_w) + x]; for (j = 0; j < cblk_h; ++j) { for (i = 0; i < cblk_w; ++i) { int tmp = datap[(j * cblk_w) + i]; @@ -1574,9 +1574,9 @@ void t1_decode_cblks( } } } else { /* if (tccp->qmfbid == 0) */ - float* restrict tiledp = (float*) &tilec->data[(y * tile_w) + x]; + float* OPJ_RESTRICT tiledp = (float*) &tilec->data[(y * tile_w) + x]; for (j = 0; j < cblk_h; ++j) { - float* restrict tiledp2 = tiledp; + float* OPJ_RESTRICT tiledp2 = tiledp; for (i = 0; i < cblk_w; ++i) { float tmp = *datap * band->stepsize; *tiledp2 = tmp; diff --git a/indra/libopenjpeg/t1_generate_luts.c b/indra/libopenjpeg/t1_generate_luts.c index 39880414fb..605709125a 100644 --- a/indra/libopenjpeg/t1_generate_luts.c +++ b/indra/libopenjpeg/t1_generate_luts.c @@ -194,7 +194,7 @@ int main(){ printf("/* This file was automatically generated by t1_generate_luts.c */\n\n"); - // lut_ctxno_zc + /* lut_ctxno_zc */ for (j = 0; j < 4; ++j) { for (i = 0; i < 256; ++i) { int orient = j; @@ -215,7 +215,7 @@ int main(){ } printf("%i\n};\n\n", lut_ctxno_zc[1023]); - // lut_ctxno_sc + /* lut_ctxno_sc */ printf("static char lut_ctxno_sc[256] = {\n "); for (i = 0; i < 255; ++i) { printf("0x%x, ", t1_init_ctxno_sc(i << 4)); @@ -224,7 +224,7 @@ int main(){ } printf("0x%x\n};\n\n", t1_init_ctxno_sc(255 << 4)); - // lut_spb + /* lut_spb */ printf("static char lut_spb[256] = {\n "); for (i = 0; i < 255; ++i) { printf("%i, ", t1_init_spb(i << 4)); diff --git a/indra/libopenjpeg/t2.c b/indra/libopenjpeg/t2.c index cae29f09b1..2585c3d56a 100644 --- a/indra/libopenjpeg/t2.c +++ b/indra/libopenjpeg/t2.c @@ -30,6 +30,7 @@ */ #include "opj_includes.h" +#include /** @defgroup T2 T2 - Implementation of a tier-2 coding */ /*@{*/ @@ -340,13 +341,15 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t int precno = pi->precno; /* precinct value */ int layno = pi->layno; /* quality layer value */ - opj_tcd_resolution_t* res = &tile->comps[compno].resolutions[resno]; - unsigned char *hd = NULL; int present; opj_bio_t *bio = NULL; /* BIO component */ - + + opj_tcd_resolution_t* res; + assert(&tile->comps[compno] != NULL); + res = &tile->comps[compno].resolutions[resno]; + if (layno == 0) { for (bandno = 0; bandno < res->numbands; bandno++) { opj_tcd_band_t *band = &res->bands[bandno]; diff --git a/indra/libopenjpeg/tcd.c b/indra/libopenjpeg/tcd.c index c19b3eb6a9..4ced7aaff3 100644 --- a/indra/libopenjpeg/tcd.c +++ b/indra/libopenjpeg/tcd.c @@ -1507,7 +1507,7 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno for(j = res->y0; j < res->y1; ++j) { for(i = res->x0; i < res->x1; ++i) { float tmp = ((float*)tilec->data)[i - res->x0 + (j - res->y0) * tw]; - int v = lrintf(tmp); + int v = opj_lrintf(tmp); v += adjust; imagec->data[(i - offset_x) + (j - offset_y) * w] = int_clamp(v, min, max); } diff --git a/indra/libpathing/CMakeLists.txt b/indra/libpathing/CMakeLists.txt index 35086c7160..aefe1a2acd 100644 --- a/indra/libpathing/CMakeLists.txt +++ b/indra/libpathing/CMakeLists.txt @@ -30,5 +30,8 @@ set_source_files_properties(${libpathing_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) add_library(nd_Pathing STATIC ${libpathing_SOURCE_FILES} ${libpathing_HEADER_FILES} ) -add_dependencies(nd_Pathing prepare) +target_link_libraries(nd_Pathing + PUBLIC + llcommon +) diff --git a/indra/libpathing/llpathinglib.cpp b/indra/libpathing/llpathinglib.cpp index 19c0bff0ff..041311de9a 100644 --- a/indra/libpathing/llpathinglib.cpp +++ b/indra/libpathing/llpathinglib.cpp @@ -1,4 +1,3 @@ -#include "sys.h" #include "llpathinglib.h" void LLPathingLib::initSystem() diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index e016b47906..0a85aff0e3 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -24,11 +24,6 @@ * $/LicenseInfo$ */ -#if LL_MSVC -// disable warning about boost::lexical_cast returning uninitialized data -// when it fails to parse the string -#pragma warning (disable:4701) -#endif #include "linden_common.h" @@ -44,6 +39,8 @@ #include "llstl.h" #include "lltexglobalcolor.h" #include "llwearabledata.h" +#include "boost/bind.hpp" +#include "boost/tokenizer.hpp" #if LL_MSVC @@ -51,8 +48,6 @@ #pragma warning (disable:4702) #endif -#include - using namespace LLAvatarAppearanceDefines; //----------------------------------------------------------------------------- @@ -81,13 +76,17 @@ class LLAvatarBoneInfo ~LLAvatarBoneInfo() { std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); + mChildList.clear(); } BOOL parseXml(LLXmlTreeNode* node); private: std::string mName; + std::string mSupport; + std::string mAliases; BOOL mIsJoint; LLVector3 mPos; + LLVector3 mEnd; LLVector3 mRot; LLVector3 mScale; LLVector3 mPivot; @@ -108,6 +107,7 @@ class LLAvatarSkeletonInfo ~LLAvatarSkeletonInfo() { std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); + mBoneInfoList.clear(); } BOOL parseXml(LLXmlTreeNode* node); S32 getNumBones() const { return mNumBones; } @@ -116,6 +116,7 @@ class LLAvatarSkeletonInfo private: S32 mNumBones; S32 mNumCollisionVolumes; + LLAvatarAppearance::joint_alias_map_t mJointAliasMap; typedef std::vector bone_info_list_t; bone_info_list_t mBoneInfoList; }; @@ -132,14 +133,25 @@ LLAvatarAppearance::LLAvatarXmlInfo::LLAvatarXmlInfo() LLAvatarAppearance::LLAvatarXmlInfo::~LLAvatarXmlInfo() { std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); + mMeshInfoList.clear(); + std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); + mSkeletalDistortionInfoList.clear(); + std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer()); + mAttachmentInfoList.clear(); + delete_and_clear(mTexSkinColorInfo); delete_and_clear(mTexHairColorInfo); delete_and_clear(mTexEyeColorInfo); std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); + mLayerInfoList.clear(); + std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer()); + mDriverInfoList.clear(); + std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer()); + mMorphMaskInfoList.clear(); } @@ -167,7 +179,10 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : mPelvisToFoot(0.f), mHeadOffset(), mRoot(NULL), - mWearableData(wearable_data) + mWearableData(wearable_data), + mNumBones(0), + mIsBuilt(FALSE), + mInitFlags(0) { llassert_always(mWearableData); mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES); @@ -180,8 +195,6 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : mBakedTextureDatas[i].mMaskTexName = 0; mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i); } - - mIsBuilt = FALSE; } // virtual @@ -193,8 +206,9 @@ void LLAvatarAppearance::initInstance() mRoot = createAvatarJoint(); mRoot->setName( "mRoot" ); - for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end(); + const auto& mesh_entries = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries(); + for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = mesh_entries.begin(); + iter != mesh_entries.end(); ++iter) { const EMeshIndex mesh_index = iter->first; @@ -211,7 +225,7 @@ void LLAvatarAppearance::initInstance() for (U32 lod = 0; lod < mesh_dict->mLOD; lod++) { LLAvatarJointMesh* mesh = createAvatarJointMesh(); - std::string mesh_name = "m" + mesh_dict->mName + boost::lexical_cast(lod); + std::string mesh_name = fmt::format(FMT_STRING("m{:s}{:d}"), mesh_dict->mName, lod); // We pre-pended an m - need to capitalize first character for camelCase mesh_name[1] = toupper(mesh_name[1]); mesh->setName(mesh_name); @@ -239,8 +253,8 @@ void LLAvatarAppearance::initInstance() //------------------------------------------------------------------------- // associate baked textures with meshes //------------------------------------------------------------------------- - for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end(); + for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = mesh_entries.begin(); + iter != mesh_entries.end(); ++iter) { const EMeshIndex mesh_index = iter->first; @@ -264,6 +278,8 @@ void LLAvatarAppearance::initInstance() } buildCharacter(); + mInitFlags |= 1<<0; + } // virtual @@ -279,7 +295,7 @@ LLAvatarAppearance::~LLAvatarAppearance() mBakedTextureDatas[i].mJointMeshes.clear(); for (morph_list_t::iterator iter2 = mBakedTextureDatas[i].mMaskedMorphs.begin(); - iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); iter2++) + iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); ++iter2) { LLMaskedMorph* masked_morph = (*iter2); delete masked_morph; @@ -314,36 +330,49 @@ LLAvatarAppearance::~LLAvatarAppearance() //static void LLAvatarAppearance::initClass() { - std::string xmlFile; + initClass("",""); +} - xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml"; - BOOL success = sXMLTree.parseFile( xmlFile, FALSE ); +//static +void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, const std::string& skeleton_file_name_arg) +{ + std::string avatar_file_name; + + if (!avatar_file_name_arg.empty()) + { + avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,avatar_file_name_arg); + } + else + { + avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR + "_lad.xml"); + } + BOOL success = sXMLTree.parseFile( avatar_file_name, FALSE ); if (!success) { - LL_ERRS() << "Problem reading avatar configuration file:" << xmlFile << LL_ENDL; + LL_ERRS() << "Problem reading avatar configuration file:" << avatar_file_name << LL_ENDL; } // now sanity check xml file LLXmlTreeNode* root = sXMLTree.getRoot(); if (!root) { - LL_ERRS() << "No root node found in avatar configuration file: " << xmlFile << LL_ENDL; + LL_ERRS() << "No root node found in avatar configuration file: " << avatar_file_name << LL_ENDL; return; } //------------------------------------------------------------------------- - // (root) + // (root) //------------------------------------------------------------------------- if( !root->hasName( "linden_avatar" ) ) { - LL_ERRS() << "Invalid avatar file header: " << xmlFile << LL_ENDL; + LL_ERRS() << "Invalid avatar file header: " << avatar_file_name << LL_ENDL; } std::string version; static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); - if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) + if( !root->getFastAttributeString( version_string, version ) || ((version != "1.0") && (version != "2.0"))) { - LL_ERRS() << "Invalid avatar file version: " << version << " in file: " << xmlFile << LL_ENDL; + LL_ERRS() << "Invalid avatar file version: " << version << " in file: " << avatar_file_name << LL_ENDL; } S32 wearable_def_version = 1; @@ -351,21 +380,22 @@ void LLAvatarAppearance::initClass() root->getFastAttributeS32( wearable_definition_version_string, wearable_def_version ); LLWearable::setCurrentDefinitionVersion( wearable_def_version ); - std::string mesh_file_name; - LLXmlTreeNode* skeleton_node = root->getChildByName( "skeleton" ); if (!skeleton_node) { - LL_ERRS() << "No skeleton in avatar configuration file: " << xmlFile << LL_ENDL; + LL_ERRS() << "No skeleton in avatar configuration file: " << avatar_file_name << LL_ENDL; return; } - - std::string skeleton_file_name; - static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); - if (!skeleton_node->getFastAttributeString(file_name_string, skeleton_file_name)) - { - LL_ERRS() << "No file name in skeleton node in avatar config file: " << xmlFile << LL_ENDL; - } + + std::string skeleton_file_name = skeleton_file_name_arg; + if (skeleton_file_name.empty()) + { + static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); + if (!skeleton_node->getFastAttributeString(file_name_string, skeleton_file_name)) + { + LL_ERRS() << "No file name in skeleton node in avatar config file: " << avatar_file_name << LL_ENDL; + } + } std::string skeleton_path; skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name); @@ -428,11 +458,56 @@ void LLAvatarAppearance::cleanupClass() using namespace LLAvatarAppearanceDefines; +void LLAvatarAppearance::compareJointStateMaps(joint_state_map_t& last_state, + joint_state_map_t& curr_state) +{ + if (!last_state.empty() && (last_state != curr_state)) + { + S32 diff_count = 0; + joint_state_map_t::iterator it; + for (it=last_state.begin(); it != last_state.end(); ++it) + { + const std::string& key = it->first; + if (last_state[key] != curr_state[key]) + { + LL_DEBUGS("AvatarBodySize") << "BodySize change " << key << " " << last_state[key] << "->" << curr_state[key] << LL_ENDL; + diff_count++; + } + } + if (diff_count > 0) + { + LL_DEBUGS("AvatarBodySize") << "Total of BodySize changes " << diff_count << LL_ENDL; + } + + } +} + //------------------------------------------------------------------------ // The viewer can only suggest a good size for the agent, // the simulator will keep it inside a reasonable range. void LLAvatarAppearance::computeBodySize() { + mLastBodySizeState = mCurrBodySizeState; + + mCurrBodySizeState["mPelvis scale"] = mPelvisp->getScale(); + mCurrBodySizeState["mSkull pos"] = mSkullp->getPosition(); + mCurrBodySizeState["mSkull scale"] = mSkullp->getScale(); + mCurrBodySizeState["mNeck pos"] = mNeckp->getPosition(); + mCurrBodySizeState["mNeck scale"] = mNeckp->getScale(); + mCurrBodySizeState["mChest pos"] = mChestp->getPosition(); + mCurrBodySizeState["mChest scale"] = mChestp->getScale(); + mCurrBodySizeState["mHead pos"] = mHeadp->getPosition(); + mCurrBodySizeState["mHead scale"] = mHeadp->getScale(); + mCurrBodySizeState["mTorso pos"] = mTorsop->getPosition(); + mCurrBodySizeState["mTorso scale"] = mTorsop->getScale(); + mCurrBodySizeState["mHipLeft pos"] = mHipLeftp->getPosition(); + mCurrBodySizeState["mHipLeft scale"] = mHipLeftp->getScale(); + mCurrBodySizeState["mKneeLeft pos"] = mKneeLeftp->getPosition(); + mCurrBodySizeState["mKneeLeft scale"] = mKneeLeftp->getScale(); + mCurrBodySizeState["mAnkleLeft pos"] = mAnkleLeftp->getPosition(); + mCurrBodySizeState["mAnkleLeft scale"] = mAnkleLeftp->getScale(); + mCurrBodySizeState["mFootLeft pos"] = mFootLeftp->getPosition(); + LLVector3 pelvis_scale = mPelvisp->getScale(); // some of the joints have not been cached @@ -489,29 +564,11 @@ void LLAvatarAppearance::computeBodySize() mAvatarOffset.mV[VX] = 0.0f; mAvatarOffset.mV[VY] = 0.0f; - // Certain configurations of avatars can force the overall height (with offset) to go negative. - // Enforce a constraint to make sure we don't go below 0.1 meters. - // Camera positioning and other things start to break down when your avatar is "walking" while being fully underground - if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 0.1f) - { - mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 0.11f); // avoid floating point rounding making the above check continue to fail. - - llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 0.1f); - - if (mWearableData && isSelf()) - { - LLWearable* shape = mWearableData->getWearable(LLWearableType::WT_SHAPE, 0); - if (shape) - { - shape->setVisualParamWeight(AVATAR_HOVER, mAvatarOffset.mV[VZ], false); - } - } - } - if (new_body_size != mBodySize || old_offset != mAvatarOffset) { mBodySize = new_body_size; - bodySizeChanged(); + + compareJointStateMaps(mLastBodySizeState, mCurrBodySizeState); } } @@ -547,7 +604,7 @@ BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename) std::string version; static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); - if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) + if( !root->getFastAttributeString( version_string, version ) || ((version != "1.0") && (version != "2.0"))) { LL_ERRS() << "Invalid avatar skeleton file version: " << version << " in file: " << filename << LL_ENDL; return FALSE; @@ -563,6 +620,12 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent { LLJoint* joint = NULL; + LL_DEBUGS("BVH") << "bone info: name " << info->mName + << " isJoint " << info->mIsJoint + << " volume_num " << volume_num + << " joint_num " << joint_num + << LL_ENDL; + if (info->mIsJoint) { joint = getCharacterJoint(joint_num); @@ -577,7 +640,7 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent { if (volume_num >= (S32)mCollisionVolumes.size()) { - LL_WARNS() << "Too many bones" << LL_ENDL; + LL_WARNS() << "Too many collision volumes" << LL_ENDL; return FALSE; } joint = (mCollisionVolumes[volume_num]); @@ -585,28 +648,34 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent } // add to parent - if (parent) + if (parent && (joint->getParent()!=parent)) { parent->addChild( joint ); } + // SL-315 joint->setPosition(info->mPos); + joint->setDefaultPosition(info->mPos); joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], info->mRot.mV[VZ], LLQuaternion::XYZ)); joint->setScale(info->mScale); + joint->setDefaultScale(info->mScale); + joint->setSupport(info->mSupport); + joint->setEnd(info->mEnd); - joint->setDefaultFromCurrentXform(); - if (info->mIsJoint) { joint->setSkinOffset( info->mPivot ); + joint->setJointNum(joint_num); joint_num++; } else // collision volume { + joint->setJointNum(mNumBones+volume_num); volume_num++; } + // setup children LLAvatarBoneInfo::child_list_t::const_iterator iter; for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) @@ -626,18 +695,12 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent //----------------------------------------------------------------------------- BOOL LLAvatarAppearance::allocateCharacterJoints( U32 num ) { - clearSkeleton(); - - for(S32 joint_num = 0; joint_num < (S32)num; joint_num++) - { - mSkeleton.push_back(createAvatarJoint(joint_num)); - } - - - if (mSkeleton.empty() || !mSkeleton[0]) - { - return FALSE; - } + if (mSkeleton.size() != num) + { + clearSkeleton(); + mSkeleton = avatar_joint_list_t(num,NULL); + mNumBones = num; + } return TRUE; } @@ -650,6 +713,8 @@ BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) { if (!info) return FALSE; + LL_DEBUGS("BVH") << "numBones " << info->mNumBones << " numCollisionVolumes " << info->mNumCollisionVolumes << LL_ENDL; + //------------------------------------------------------------------------- // allocate joints //------------------------------------------------------------------------- @@ -676,8 +741,8 @@ BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) LLAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter) { - LLAvatarBoneInfo *info = *iter; - if (!setupBone(info, NULL, current_volume_num, current_joint_num)) + LLAvatarBoneInfo *bone_info = *iter; + if (!setupBone(bone_info, NULL, current_volume_num, current_joint_num)) { LL_ERRS() << "Error parsing bone in skeleton file" << LL_ENDL; return FALSE; @@ -696,6 +761,42 @@ void LLAvatarAppearance::clearSkeleton() mSkeleton.clear(); } +//------------------------------------------------------------------------ +// addPelvisFixup +//------------------------------------------------------------------------ +void LLAvatarAppearance::addPelvisFixup( F32 fixup, const LLUUID& mesh_id ) +{ + LLVector3 pos(0.0,0.0,fixup); + mPelvisFixups.add(mesh_id,pos); +} + +//------------------------------------------------------------------------ +// addPelvisFixup +//------------------------------------------------------------------------ +void LLAvatarAppearance::removePelvisFixup( const LLUUID& mesh_id ) +{ + mPelvisFixups.remove(mesh_id); +} + +//------------------------------------------------------------------------ +// hasPelvisFixup +//------------------------------------------------------------------------ +bool LLAvatarAppearance::hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const +{ + LLVector3 pos; + if (mPelvisFixups.findActiveOverride(mesh_id,pos)) + { + fixup = pos[2]; + return true; + } + return false; +} + +bool LLAvatarAppearance::hasPelvisFixup( F32& fixup ) const +{ + LLUUID mesh_id; + return hasPelvisFixup( fixup, mesh_id ); +} //----------------------------------------------------------------------------- // LLAvatarAppearance::buildCharacter() // Deferred initialization and rebuild of the avatar. @@ -821,11 +922,11 @@ void LLAvatarAppearance::buildCharacter() //----------------------------------------------------------------------------- // loadAvatar() //----------------------------------------------------------------------------- -//static LLFastTimer::DeclareTimer FTM_LOAD_AVATAR("Load Avatar"); +//static LLTrace::BlockTimerStatHandle FTM_LOAD_AVATAR("Load Avatar"); BOOL LLAvatarAppearance::loadAvatar() { -// LLFastTimer t(FTM_LOAD_AVATAR); +// LL_RECORD_BLOCK_TIME(FTM_LOAD_AVATAR); // avatar_skeleton.xml if( !buildSkeleton(sAvatarSkeletonInfo) ) @@ -941,7 +1042,7 @@ BOOL LLAvatarAppearance::loadAvatar() addVisualParam( driver_param ); driver_param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); LLVisualParam*(LLAvatarAppearance::*avatar_function)(S32)const = &LLAvatarAppearance::getVisualParam; - if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLAvatarAppearance*)this,_1 ), false)) + if( !driver_param->linkDrivenParams(std::bind(avatar_function,(LLAvatarAppearance*)this, std::placeholders::_1 ), false)) { LL_WARNS() << "could not link driven params for avatar " << getID().asString() << " param id: " << driver_param->getID() << LL_ENDL; continue; @@ -1100,6 +1201,7 @@ BOOL LLAvatarAppearance::loadMeshNodes() { // This should never happen LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL; + return FALSE; } } else @@ -1115,7 +1217,7 @@ BOOL LLAvatarAppearance::loadMeshNodes() } // Multimap insert - mPolyMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh)); + mPolyMeshes.emplace(info->mMeshFileName, poly_mesh); mesh->setMesh( poly_mesh ); mesh->setLOD( info->mMinPixelArea ); @@ -1236,6 +1338,10 @@ LLJoint *LLAvatarAppearance::getCharacterJoint( U32 num ) { return NULL; } + if (!mSkeleton[num]) + { + mSkeleton[num] = createAvatarJoint(); + } return mSkeleton[num]; } @@ -1261,12 +1367,12 @@ LLVector3 LLAvatarAppearance::getVolumePos(S32 joint_index, LLVector3& volume_of //----------------------------------------------------------------------------- // findCollisionVolume() //----------------------------------------------------------------------------- -LLJoint* LLAvatarAppearance::findCollisionVolume(U32 volume_id) +LLJoint* LLAvatarAppearance::findCollisionVolume(S32 volume_id) { //SNOW-488: As mNumCollisionVolumes is a S32 and we are casting from a U32 to a S32 //to compare we also need to be sure of the wrap around case producing (S32) <0 //or in terms of the U32 an out of bounds index in the array. - if ((S32)volume_id > (S32)mCollisionVolumes.size() || (S32)volume_id<0) + if ((S32)volume_id > (S32)mCollisionVolumes.size() || volume_id<0) { return NULL; } @@ -1454,6 +1560,21 @@ BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name ) param_name[1] = 1072; //"tattoo_green"; param_name[2] = 1073; //"tattoo_blue"; break; + case TEX_HEAD_UNIVERSAL_TATTOO: + case TEX_UPPER_UNIVERSAL_TATTOO: + case TEX_LOWER_UNIVERSAL_TATTOO: + case TEX_SKIRT_TATTOO: + case TEX_HAIR_TATTOO: + case TEX_EYES_TATTOO: + case TEX_LEFT_ARM_TATTOO: + case TEX_LEFT_LEG_TATTOO: + case TEX_AUX1_TATTOO: + case TEX_AUX2_TATTOO: + case TEX_AUX3_TATTOO: + param_name[0] = 1238; //"tattoo_universal_red"; + param_name[1] = 1239; //"tattoo_universal_green"; + param_name[2] = 1240; //"tattoo_universal_blue"; + break; default: llassert(0); @@ -1535,21 +1656,24 @@ LLTexLayerSet* LLAvatarAppearance::getAvatarLayerSet(EBakedTextureIndex baked_in //----------------------------------------------------------------------------- BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num ) { - delete_and_clear(mCollisionVolumes); - mCollisionVolumes.reserve(num); - - LLAvatarJointCollisionVolume* cv; - for (U32 i = 0; i < num; ++i) + if(num != mCollisionVolumes.size() ) { - cv = new LLAvatarJointCollisionVolume(); - if (cv) - { - mCollisionVolumes.push_back(cv); - } - else + delete_and_clear(mCollisionVolumes); + mCollisionVolumes.reserve(num); + + LLAvatarJointCollisionVolume* cv; + for (U32 i = 0; i < num; ++i) { - delete_and_clear(mCollisionVolumes); - return false; + cv = new LLAvatarJointCollisionVolume(); + if (cv) + { + mCollisionVolumes.push_back(cv); + } + else + { + delete_and_clear(mCollisionVolumes); + return false; + } } } return TRUE; @@ -1569,6 +1693,9 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) LL_WARNS() << "Bone without name" << LL_ENDL; return FALSE; } + + static LLStdStringHandle aliases_string = LLXmlTree::addAttributeString("aliases"); + node->getFastAttributeString(aliases_string, mAliases ); //Aliases are not required. } else if (node->hasName("collision_volume")) { @@ -1606,6 +1733,20 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) return FALSE; } + static LLStdStringHandle end_string = LLXmlTree::addAttributeString("end"); + if (!node->getFastAttributeVector3(end_string, mEnd)) + { + LL_WARNS() << "Bone without end " << mName << LL_ENDL; + mEnd = LLVector3(0.0f, 0.0f, 0.0f); + } + + static LLStdStringHandle support_string = LLXmlTree::addAttributeString("support"); + if (!node->getFastAttributeString(support_string,mSupport)) + { + LL_WARNS() << "Bone without support " << mName << LL_ENDL; + mSupport = "base"; + } + if (mIsJoint) { static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); @@ -1661,6 +1802,75 @@ BOOL LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) return TRUE; } +//Make aliases for joint and push to map. +void LLAvatarAppearance::makeJointAliases(LLAvatarBoneInfo *bone_info) +{ + if (! bone_info->mIsJoint ) + { + return; + } + + std::string bone_name = bone_info->mName; + mJointAliasMap[bone_name] = bone_name; //Actual name is a valid alias. + + std::string aliases = bone_info->mAliases; + + boost::char_separator sep(" "); + boost::tokenizer > tok(aliases, sep); + for(boost::tokenizer >::iterator i = tok.begin(); i != tok.end(); ++i) + { + if ( mJointAliasMap.find(*i) != mJointAliasMap.end() ) + { + LL_WARNS() << "avatar skeleton: Joint alias \"" << *i << "\" remapped from " << mJointAliasMap[*i] << " to " << bone_name << LL_ENDL; + } + mJointAliasMap[*i] = bone_name; + } + + LLAvatarBoneInfo::child_list_t::const_iterator iter; + for (iter = bone_info->mChildList.begin(); iter != bone_info->mChildList.end(); ++iter) + { + makeJointAliases( *iter ); + } +} + +const LLAvatarAppearance::joint_alias_map_t& LLAvatarAppearance::getJointAliases () +{ + LLAvatarAppearance::joint_alias_map_t alias_map; + if (mJointAliasMap.empty()) + { + + LLAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; + for (iter = sAvatarSkeletonInfo->mBoneInfoList.begin(); + iter != sAvatarSkeletonInfo->mBoneInfoList.end(); + ++iter) + { + //LLAvatarBoneInfo *bone_info = *iter; + makeJointAliases( *iter ); + } + + LLAvatarXmlInfo::attachment_info_list_t::iterator attach_iter; + for (attach_iter = sAvatarXmlInfo->mAttachmentInfoList.begin(); + attach_iter != sAvatarXmlInfo->mAttachmentInfoList.end(); + ++attach_iter) + { + LLAvatarXmlInfo::LLAvatarAttachmentInfo *info = *attach_iter; + std::string bone_name = info->mName; + + // Also accept the name with spaces substituted with + // underscores. This gives a mechanism for referencing such joints + // in daes, which don't allow spaces. + std::string sub_space_to_underscore = bone_name; + LLStringUtil::replaceChar(sub_space_to_underscore, ' ', '_'); + if (sub_space_to_underscore != bone_name) + { + mJointAliasMap[sub_space_to_underscore] = bone_name; + } + } + } + + return mJointAliasMap; +} + //----------------------------------------------------------------------------- // parseXmlSkeletonNode(): parses nodes from XML tree @@ -1691,7 +1901,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "Unknown param type." << LL_ENDL; } - continue; + return FALSE; } LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo; @@ -1716,7 +1926,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "No name supplied for attachment point." << LL_ENDL; delete info; - continue; + return FALSE; } static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint"); @@ -1724,7 +1934,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "No bone declared in attachment point " << info->mName << LL_ENDL; delete info; - continue; + return FALSE; } static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position"); @@ -1750,7 +1960,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "No id supplied for attachment point " << info->mName << LL_ENDL; delete info; - continue; + return FALSE; } static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice"); @@ -1836,7 +2046,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) { LL_WARNS() << "Unknown param type." << LL_ENDL; } - continue; + return FALSE; } LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo(); @@ -1997,7 +2207,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root { LL_WARNS() << "No name supplied for morph mask." << LL_ENDL; delete info; - continue; + return FALSE; } static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region"); @@ -2005,7 +2215,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root { LL_WARNS() << "No region supplied for morph mask." << LL_ENDL; delete info; - continue; + return FALSE; } static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer"); @@ -2013,7 +2223,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root { LL_WARNS() << "No layer supplied for morph mask." << LL_ENDL; delete info; - continue; + return FALSE; } // optional parameter. don't throw a warning if not present. diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index f691d73783..3fa4c35137 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -35,6 +35,7 @@ #include "llviewervisualparam.h" #include "llxmltree.h" +#include // class LLTexLayerSet; class LLTexGlobalColor; class LLTexGlobalColorInfo; @@ -66,9 +67,11 @@ class LLAvatarAppearance : public LLCharacter LLAvatarAppearance(LLWearableData* wearable_data); virtual ~LLAvatarAppearance(); + static void initClass(const std::string& avatar_file_name, const std::string& skeleton_file_name); // initializes static members static void initClass(); // initializes static members static void cleanupClass(); // Cleanup data that's only init'd once per class. virtual void initInstance(); // Called after construction to initialize the instance. + S32 mInitFlags; virtual BOOL loadSkeletonNode(); BOOL loadMeshNodes(); BOOL loadLayersets(); @@ -91,7 +94,7 @@ class LLAvatarAppearance : public LLCharacter /*virtual*/ const char* getAnimationPrefix() { return "avatar"; } /*virtual*/ LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset); - /*virtual*/ LLJoint* findCollisionVolume(U32 volume_id); + /*virtual*/ LLJoint* findCollisionVolume(S32 volume_id); /*virtual*/ S32 getCollisionVolumeID(std::string &name); /*virtual*/ LLPolyMesh* getHeadMesh(); /*virtual*/ LLPolyMesh* getUpperBodyMesh(); @@ -132,6 +135,7 @@ class LLAvatarAppearance : public LLCharacter virtual LLAvatarJoint* createAvatarJoint() = 0; virtual LLAvatarJoint* createAvatarJoint(S32 joint_num) = 0; virtual LLAvatarJointMesh* createAvatarJointMesh() = 0; + void makeJointAliases(LLAvatarBoneInfo *bone_info); public: F32 getPelvisToFoot() const { return mPelvisToFoot; } /*virtual*/ LLJoint* getRootJoint() { return mRoot; } @@ -139,17 +143,27 @@ class LLAvatarAppearance : public LLCharacter LLVector3 mHeadOffset; // current head position LLAvatarJoint *mRoot; - typedef std::map joint_map_t; + typedef std::vector > joint_map_t; joint_map_t mJointMap; - + + typedef std::map joint_state_map_t; + joint_state_map_t mLastBodySizeState; + joint_state_map_t mCurrBodySizeState; + void compareJointStateMaps(joint_state_map_t& last_state, + joint_state_map_t& curr_state); void computeBodySize(); +public: + typedef std::vector avatar_joint_list_t; + const avatar_joint_list_t& getSkeleton() { return mSkeleton; } + typedef std::map joint_alias_map_t; + const joint_alias_map_t& getJointAliases(); + protected: static BOOL parseSkeletonFile(const std::string& filename); virtual void buildCharacter(); virtual BOOL loadAvatar(); - virtual void bodySizeChanged() = 0; BOOL setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); BOOL allocateCharacterJoints(U32 num); @@ -157,13 +171,20 @@ class LLAvatarAppearance : public LLCharacter protected: void clearSkeleton(); BOOL mIsBuilt; // state of deferred character building - typedef std::vector avatar_joint_list_t; + avatar_joint_list_t mSkeleton; - + LLVector3OverrideMap mPelvisFixups; + joint_alias_map_t mJointAliasMap; + //-------------------------------------------------------------------- // Pelvis height adjustment members. //-------------------------------------------------------------------- public: + void addPelvisFixup( F32 fixup, const LLUUID& mesh_id ); + void removePelvisFixup( const LLUUID& mesh_id ); + bool hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const; + bool hasPelvisFixup( F32& fixup ) const; + LLVector3 mBodySize; LLVector3 mAvatarOffset; protected: @@ -213,7 +234,7 @@ class LLAvatarAppearance : public LLCharacter ** RENDERING **/ public: - BOOL mIsDummy; // for special views + BOOL mIsDummy; // for special views and animated object controllers; local to viewer //-------------------------------------------------------------------- // Morph masks @@ -320,7 +341,7 @@ class LLAvatarAppearance : public LLCharacter bool mIsLoaded; bool mIsUsed; LLAvatarAppearanceDefines::ETextureIndex mTextureIndex; - U32 mMaskTexName; + LLImageGL::GLTextureName mMaskTexName; // Stores pointers to the joint meshes that this baked texture deals with avatar_joint_mesh_list_t mJointMeshes; morph_list_t mMaskedMorphs; @@ -337,6 +358,7 @@ class LLAvatarAppearance : public LLCharacter // Collision volumes //-------------------------------------------------------------------- public: + S32 mNumBones; std::vector mCollisionVolumes; protected: BOOL allocateCollisionVolumes(U32 num); diff --git a/indra/llappearance/llavatarappearancedefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp index f1c78946a1..5f3c7cdaad 100644 --- a/indra/llappearance/llavatarappearancedefines.cpp +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -27,8 +27,11 @@ #include "linden_common.h" #include "llavatarappearancedefines.h" -const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_WIDTH = 512; -const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_HEIGHT = 512; +#include "indra_constants.h" +#include + +const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_WIDTH = 1024; +const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_HEIGHT = 1024; const S32 LLAvatarAppearanceDefines::IMPOSTOR_PERIOD = 2; using namespace LLAvatarAppearanceDefines; @@ -65,12 +68,30 @@ LLAvatarAppearanceDictionary::Textures::Textures() addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + addEntry(TEX_HEAD_UNIVERSAL_TATTOO, new TextureEntry("head_universal_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_UPPER_UNIVERSAL_TATTOO, new TextureEntry("upper_universal_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_LOWER_UNIVERSAL_TATTOO, new TextureEntry("lower_universal_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_SKIRT_TATTOO, new TextureEntry("skirt_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_HAIR_TATTOO, new TextureEntry("hair_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_EYES_TATTOO, new TextureEntry("eyes_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_LEFT_ARM_TATTOO, new TextureEntry("leftarm_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_LEFT_LEG_TATTOO, new TextureEntry("leftleg_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_AUX1_TATTOO, new TextureEntry("aux1_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_AUX2_TATTOO, new TextureEntry("aux2_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_AUX3_TATTOO, new TextureEntry("aux3_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + + addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD, "head")); addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER, "upper")); addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER, "lower")); addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES, "eyes")); addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR, "hair")); addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT, "skirt")); + addEntry(TEX_LEFT_ARM_BAKED, new TextureEntry("leftarm-baked", FALSE, BAKED_LEFT_ARM, "leftarm")); + addEntry(TEX_LEFT_LEG_BAKED, new TextureEntry("leftleg-baked", FALSE, BAKED_LEFT_LEG, "leftleg")); + addEntry(TEX_AUX1_BAKED, new TextureEntry("aux1-baked", FALSE, BAKED_AUX1, "aux1")); + addEntry(TEX_AUX2_BAKED, new TextureEntry("aux2-baked", FALSE, BAKED_AUX2, "aux2")); + addEntry(TEX_AUX3_BAKED, new TextureEntry("aux3-baked", FALSE, BAKED_AUX3, "aux3")); } LLAvatarAppearanceDictionary::BakedTextures::BakedTextures() @@ -78,35 +99,60 @@ LLAvatarAppearanceDictionary::BakedTextures::BakedTextures() // Baked textures addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED, "head", "a4b9dc38-e13b-4df9-b284-751efb0566ff", - 3, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA, - 5, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_HAIR, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); + 4, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA, TEX_HEAD_UNIVERSAL_TATTOO, + 6, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_HAIR, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA, LLWearableType::WT_UNIVERSAL)); addEntry(BAKED_UPPER, new BakedEntry(TEX_UPPER_BAKED, "upper_body", "5943ff64-d26c-4a90-a8c0-d61f56bd98d4", - 7, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET, - TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA, - 8, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_SHIRT, LLWearableType::WT_JACKET, LLWearableType::WT_GLOVES, LLWearableType::WT_UNDERSHIRT, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); + 8, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET, + TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA, TEX_UPPER_UNIVERSAL_TATTOO, + 9, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_SHIRT, LLWearableType::WT_JACKET, LLWearableType::WT_GLOVES, LLWearableType::WT_UNDERSHIRT, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA, LLWearableType::WT_UNIVERSAL)); addEntry(BAKED_LOWER, new BakedEntry(TEX_LOWER_BAKED, "lower_body", "2944ee70-90a7-425d-a5fb-d749c782ed7d", - 8, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES, TEX_LOWER_SOCKS, - TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA, - 9, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_PANTS, LLWearableType::WT_SHOES, LLWearableType::WT_SOCKS, LLWearableType::WT_JACKET, LLWearableType::WT_UNDERPANTS, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); + 9, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES, TEX_LOWER_SOCKS, + TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA, TEX_LOWER_UNIVERSAL_TATTOO, + 10, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_PANTS, LLWearableType::WT_SHOES, LLWearableType::WT_SOCKS, LLWearableType::WT_JACKET, LLWearableType::WT_UNDERPANTS, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA, LLWearableType::WT_UNIVERSAL)); addEntry(BAKED_EYES, new BakedEntry(TEX_EYES_BAKED, "eyes", "27b1bc0f-979f-4b13-95fe-b981c2ba9788", - 2, TEX_EYES_IRIS, TEX_EYES_ALPHA, - 2, LLWearableType::WT_EYES, LLWearableType::WT_ALPHA)); + 3, TEX_EYES_IRIS, TEX_EYES_TATTOO, TEX_EYES_ALPHA, + 3, LLWearableType::WT_EYES, LLWearableType::WT_UNIVERSAL, LLWearableType::WT_ALPHA)); addEntry(BAKED_SKIRT, new BakedEntry(TEX_SKIRT_BAKED, "skirt", "03e7e8cb-1368-483b-b6f3-74850838ba63", - 1, TEX_SKIRT, - 1, LLWearableType::WT_SKIRT)); + 2, TEX_SKIRT, TEX_SKIRT_TATTOO, + 2, LLWearableType::WT_SKIRT, LLWearableType::WT_UNIVERSAL )); addEntry(BAKED_HAIR, new BakedEntry(TEX_HAIR_BAKED, "hair", "a60e85a9-74e8-48d8-8a2d-8129f28d9b61", - 2, TEX_HAIR, TEX_HAIR_ALPHA, - 2, LLWearableType::WT_HAIR, LLWearableType::WT_ALPHA)); + 3, TEX_HAIR, TEX_HAIR_TATTOO, TEX_HAIR_ALPHA, + 3, LLWearableType::WT_HAIR, LLWearableType::WT_UNIVERSAL, LLWearableType::WT_ALPHA)); + + addEntry(BAKED_LEFT_ARM, new BakedEntry(TEX_LEFT_ARM_BAKED, + "leftarm", "9f39febf-22d7-0087-79d1-e9e8c6c9ed19", + 1, TEX_LEFT_ARM_TATTOO, + 1, LLWearableType::WT_UNIVERSAL)); + + addEntry(BAKED_LEFT_LEG, new BakedEntry(TEX_LEFT_LEG_BAKED, + "leftleg", "054a7a58-8ed5-6386-0add-3b636fb28b78", + 1, TEX_LEFT_LEG_TATTOO, + 1, LLWearableType::WT_UNIVERSAL)); + + addEntry(BAKED_AUX1, new BakedEntry(TEX_AUX1_BAKED, + "aux1", "790c11be-b25c-c17e-b4d2-6a4ad786b752", + 1, TEX_AUX1_TATTOO, + 1, LLWearableType::WT_UNIVERSAL)); + + addEntry(BAKED_AUX2, new BakedEntry(TEX_AUX2_BAKED, + "aux2", "d78c478f-48c7-5928-5864-8d99fb1f521e", + 1, TEX_AUX2_TATTOO, + 1, LLWearableType::WT_UNIVERSAL)); + + addEntry(BAKED_AUX3, new BakedEntry(TEX_AUX3_BAKED, + "aux3", "6a95dd53-edd9-aac8-f6d3-27ed99f3c3eb", + 1, TEX_AUX3_TATTOO, + 1, LLWearableType::WT_UNIVERSAL)); } LLAvatarAppearanceDictionary::MeshEntries::MeshEntries() @@ -140,7 +186,7 @@ LLAvatarAppearanceDictionary::~LLAvatarAppearanceDictionary() // map it to the baked texture. void LLAvatarAppearanceDictionary::createAssociations() { - for (BakedTextures::const_iterator iter = mBakedTextures.begin(); iter != mBakedTextures.end(); iter++) + for (BakedTextures::const_iterator iter = mBakedTextures.begin(); iter != mBakedTextures.end(); ++iter) { const EBakedTextureIndex baked_index = (iter->first); const BakedEntry *dict = (iter->second); @@ -149,7 +195,7 @@ void LLAvatarAppearanceDictionary::createAssociations() // with this baked texture index. for (texture_vec_t::const_iterator local_texture_iter = dict->mLocalTextures.begin(); local_texture_iter != dict->mLocalTextures.end(); - local_texture_iter++) + ++local_texture_iter) { const ETextureIndex local_texture_index = (ETextureIndex) *local_texture_iter; mTextures[local_texture_index]->mIsUsedByBakedTexture = true; @@ -212,6 +258,7 @@ LLAvatarAppearanceDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, LLWearableType::EType t = (LLWearableType::EType)va_arg(argp,int); mWearables.push_back(t); } + va_end(argp); } // static @@ -221,7 +268,7 @@ ETextureIndex LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(EBakedTextu } // static -EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::string name) +EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(const std::string& name) { U8 index = 0; while (index < BAKED_NUM_INDICES) @@ -239,7 +286,7 @@ EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::stri } // static -EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::string name) +EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(const std::string& name) { U8 index = 0; while (index < BAKED_NUM_INDICES) @@ -266,3 +313,112 @@ LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIn return getInstance()->getTexture(index)->mWearableType; } +// static +BOOL LLAvatarAppearanceDictionary::isBakedImageId(const LLUUID& id) +{ + if ((id == IMG_USE_BAKED_EYES) || (id == IMG_USE_BAKED_HAIR) || (id == IMG_USE_BAKED_HEAD) || (id == IMG_USE_BAKED_LOWER) || (id == IMG_USE_BAKED_SKIRT) || (id == IMG_USE_BAKED_UPPER) + || (id == IMG_USE_BAKED_LEFTARM) || (id == IMG_USE_BAKED_LEFTLEG) || (id == IMG_USE_BAKED_AUX1) || (id == IMG_USE_BAKED_AUX2) || (id == IMG_USE_BAKED_AUX3) ) + { + return TRUE; + } + + return FALSE; +} + +// static +EBakedTextureIndex LLAvatarAppearanceDictionary::assetIdToBakedTextureIndex(const LLUUID& id) +{ + if (id == IMG_USE_BAKED_EYES) + { + return BAKED_EYES; + } + else if (id == IMG_USE_BAKED_HAIR) + { + return BAKED_HAIR; + } + else if (id == IMG_USE_BAKED_HEAD) + { + return BAKED_HEAD; + } + else if (id == IMG_USE_BAKED_LOWER) + { + return BAKED_LOWER; + } + else if (id == IMG_USE_BAKED_SKIRT) + { + return BAKED_SKIRT; + } + else if (id == IMG_USE_BAKED_UPPER) + { + return BAKED_UPPER; + } + else if (id == IMG_USE_BAKED_LEFTARM) + { + return BAKED_LEFT_ARM; + } + else if (id == IMG_USE_BAKED_LEFTLEG) + { + return BAKED_LEFT_LEG; + } + else if (id == IMG_USE_BAKED_AUX1) + { + return BAKED_AUX1; + } + else if (id == IMG_USE_BAKED_AUX2) + { + return BAKED_AUX2; + } + else if (id == IMG_USE_BAKED_AUX3) + { + return BAKED_AUX3; + } + + return BAKED_NUM_INDICES; +} + +//static +LLUUID LLAvatarAppearanceDictionary::localTextureIndexToMagicId(ETextureIndex t) +{ + LLUUID id = LLUUID::null; + + switch (t) + { + case LLAvatarAppearanceDefines::TEX_HEAD_BAKED: + id = IMG_USE_BAKED_HEAD; + break; + case LLAvatarAppearanceDefines::TEX_UPPER_BAKED: + id = IMG_USE_BAKED_UPPER; + break; + case LLAvatarAppearanceDefines::TEX_LOWER_BAKED: + id = IMG_USE_BAKED_LOWER; + break; + case LLAvatarAppearanceDefines::TEX_EYES_BAKED: + id = IMG_USE_BAKED_EYES; + break; + case LLAvatarAppearanceDefines::TEX_SKIRT_BAKED: + id = IMG_USE_BAKED_SKIRT; + break; + case LLAvatarAppearanceDefines::TEX_HAIR_BAKED: + id = IMG_USE_BAKED_HAIR; + break; + case LLAvatarAppearanceDefines::TEX_LEFT_ARM_BAKED: + id = IMG_USE_BAKED_LEFTARM; + break; + case LLAvatarAppearanceDefines::TEX_LEFT_LEG_BAKED: + id = IMG_USE_BAKED_LEFTLEG; + break; + case LLAvatarAppearanceDefines::TEX_AUX1_BAKED: + id = IMG_USE_BAKED_AUX1; + break; + case LLAvatarAppearanceDefines::TEX_AUX2_BAKED: + id = IMG_USE_BAKED_AUX2; + break; + case LLAvatarAppearanceDefines::TEX_AUX3_BAKED: + id = IMG_USE_BAKED_AUX3; + break; + default: + break; + } + + return id; +} diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h index 8a1d2c4707..444af9c050 100644 --- a/indra/llappearance/llavatarappearancedefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -1,3 +1,4 @@ + /** * @file llavatarappearancedefines.h * @brief Various LLAvatarAppearance related definitions @@ -78,6 +79,22 @@ enum ETextureIndex TEX_HEAD_TATTOO, TEX_UPPER_TATTOO, TEX_LOWER_TATTOO, + TEX_HEAD_UNIVERSAL_TATTOO, + TEX_UPPER_UNIVERSAL_TATTOO, + TEX_LOWER_UNIVERSAL_TATTOO, + TEX_SKIRT_TATTOO, + TEX_HAIR_TATTOO, + TEX_EYES_TATTOO, + TEX_LEFT_ARM_TATTOO, + TEX_LEFT_LEG_TATTOO, + TEX_AUX1_TATTOO, + TEX_AUX2_TATTOO, + TEX_AUX3_TATTOO, + TEX_LEFT_ARM_BAKED, // Pre-composited + TEX_LEFT_LEG_BAKED, // Pre-composited + TEX_AUX1_BAKED, // Pre-composited + TEX_AUX2_BAKED, // Pre-composited + TEX_AUX3_BAKED, // Pre-composited TEX_NUM_INDICES }; @@ -89,6 +106,11 @@ enum EBakedTextureIndex BAKED_EYES, BAKED_SKIRT, BAKED_HAIR, + BAKED_LEFT_ARM, + BAKED_LEFT_LEG, + BAKED_AUX1, + BAKED_AUX2, + BAKED_AUX3, BAKED_NUM_INDICES }; @@ -218,12 +240,15 @@ class LLAvatarAppearanceDictionary : public LLSingleton(*iter); - if (!joint) - continue; - - F32 jointLOD = joint->getLOD(); - - if (found_lod || jointLOD == DEFAULT_AVATAR_JOINT_LOD) - { - // we've already found a joint to enable, so enable the rest as alternatives - lod_changed |= joint->updateLOD(pixel_area, TRUE); - } - else + if (joint) { - if (pixel_area >= jointLOD || sDisableLOD) + F32 jointLOD = joint->getLOD(); + + if (found_lod || jointLOD == DEFAULT_AVATAR_JOINT_LOD) { + // we've already found a joint to enable, so enable the rest as alternatives lod_changed |= joint->updateLOD(pixel_area, TRUE); - found_lod = TRUE; } else { - lod_changed |= joint->updateLOD(pixel_area, FALSE); + if (pixel_area >= jointLOD || sDisableLOD) + { + lod_changed |= joint->updateLOD(pixel_area, TRUE); + found_lod = TRUE; + } + else + { + lod_changed |= joint->updateLOD(pixel_area, FALSE); + } } } } @@ -232,7 +231,7 @@ void LLAvatarJoint::setMeshesToChildren() { removeAllChildren(); for (avatar_joint_mesh_list_t::iterator iter = mMeshParts.begin(); - iter != mMeshParts.end(); iter++) + iter != mMeshParts.end(); ++iter) { addChild((*iter)); } diff --git a/indra/llappearance/llavatarjoint.h b/indra/llappearance/llavatarjoint.h index e4da9bb9ad..95d5a124b8 100644 --- a/indra/llappearance/llavatarjoint.h +++ b/indra/llappearance/llavatarjoint.h @@ -52,7 +52,7 @@ class LLAvatarJoint : virtual ~LLAvatarJoint(); // Gets the validity of this joint - BOOL getValid() { return mValid; } + bool getValid() const { return mValid; } // Sets the validity of this joint virtual void setValid( BOOL valid, BOOL recursive=FALSE ); diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp index 4853a6670b..2cfcac4c18 100644 --- a/indra/llappearance/llavatarjointmesh.cpp +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -57,6 +57,41 @@ #include "llmatrix4a.h" +// Utility functions added with Bento to simplify handling of extra +// spine joints, or other new joints internal to the original +// skeleton, and unknown to the system avatar. + +//----------------------------------------------------------------------------- +// getBaseSkeletonAncestor() +//----------------------------------------------------------------------------- +LLJoint *getBaseSkeletonAncestor(LLJoint* joint) +{ + LLJoint *ancestor = joint->getParent(); + while (ancestor->getParent() && (ancestor->getSupport() != LLJoint::SUPPORT_BASE)) + { + LL_DEBUGS("Avatar") << "skipping non-base ancestor " << ancestor->getName() << LL_ENDL; + ancestor = ancestor->getParent(); + } + return ancestor; +} + +//----------------------------------------------------------------------------- +// totalSkinOffset() +//----------------------------------------------------------------------------- +LLVector3 totalSkinOffset(LLJoint *joint) +{ + LLVector3 totalOffset; + while (joint) + { + if (joint->getSupport() == LLJoint::SUPPORT_BASE) + { + totalOffset += joint->getSkinOffset(); + } + joint = joint->getParent(); + } + return totalOffset; +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // LLAvatarJointMesh::LLSkinJoint @@ -83,28 +118,24 @@ LLSkinJoint::~LLSkinJoint() //----------------------------------------------------------------------------- // LLSkinJoint::setupSkinJoint() //----------------------------------------------------------------------------- -void LLSkinJoint::setupSkinJoint( LLJoint *joint) +BOOL LLSkinJoint::setupSkinJoint( LLJoint *joint) { - mRootToJointSkinOffset.clearVec(); - mRootToParentJointSkinOffset.clearVec(); - // find the named joint - if (!(mJoint = joint)) + if (!(mJoint = dynamic_cast(joint))) { LL_INFOS() << "Can't find joint" << LL_ENDL; - return; + return FALSE; } // compute the inverse root skin matrix - do - { - mRootToJointSkinOffset -= joint->getSkinOffset(); - } while (joint = joint->getParent()); + mRootToJointSkinOffset = totalSkinOffset(mJoint); + mRootToJointSkinOffset = -mRootToJointSkinOffset; - mRootToParentJointSkinOffset = mRootToJointSkinOffset; - mRootToParentJointSkinOffset += mJoint->getSkinOffset(); + //mRootToParentJointSkinOffset = totalSkinOffset((LLAvatarJoint*)joint->getParent()); + mRootToParentJointSkinOffset = totalSkinOffset(getBaseSkeletonAncestor(mJoint)); + mRootToParentJointSkinOffset = -mRootToParentJointSkinOffset; - return; + return TRUE; } @@ -313,9 +344,9 @@ void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh ) if (!mMesh->isLOD()) { setupJoint(getRoot()); + LL_DEBUGS("Avatar") << getName() << " joint render entries: " << mMesh->mJointRenderData.size() << LL_ENDL; } - LL_DEBUGS() << "joint render entries: " << mMesh->mJointRenderData.size() << LL_ENDL; } //----------------------------------------------------------------------------- @@ -323,10 +354,8 @@ void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh ) //----------------------------------------------------------------------------- void LLAvatarJointMesh::setupJoint(LLJoint* current_joint) { -// LL_INFOS() << "Mesh: " << getName() << LL_ENDL; - -// S32 joint_count = 0; U32 sj; + for (sj=0; sjgetName() << " matches skinjoint " << sj << LL_ENDL; // is the last joint in the array our parent? - if(mMesh->mJointRenderData.size() && mMesh->mJointRenderData[mMesh->mJointRenderData.size() - 1]->mWorldMatrix == ¤t_joint->getParent()->getWorldMatrix()) + + std::vector &jrd = mMesh->mJointRenderData; + + // SL-287 - need to update this so the results are the same if + // additional extended-skeleton joints lie between this joint + // and the original parent. + LLJoint *ancestor = getBaseSkeletonAncestor(current_joint); + if(jrd.size() && jrd.back()->mWorldMatrix == &ancestor->getWorldMatrix()) { // ...then just add ourselves LLJoint* jointp = js.mJoint; - mMesh->mJointRenderData.push_back(new LLJointRenderData(&jointp->getWorldMatrix(), &js)); -// LL_INFOS() << "joint " << joint_count << js.mJoint->getName() << LL_ENDL; -// joint_count++; + jrd.push_back(new LLJointRenderData(&jointp->getWorldMatrix(), &js)); + LL_DEBUGS("Avatar") << "add joint[" << (jrd.size()-1) << "] = " << js.mJoint->getName() << LL_ENDL; } - // otherwise add our parent and ourselves + // otherwise add our ancestor and ourselves else { - mMesh->mJointRenderData.push_back(new LLJointRenderData(¤t_joint->getParent()->getWorldMatrix(), NULL)); -// LL_INFOS() << "joint " << joint_count << current_joint->getParent()->getName() << LL_ENDL; -// joint_count++; - mMesh->mJointRenderData.push_back(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js)); -// LL_INFOS() << "joint " << joint_count << current_joint->getName() << LL_ENDL; -// joint_count++; + jrd.push_back(new LLJointRenderData(&ancestor->getWorldMatrix(), NULL)); + LL_DEBUGS("Avatar") << "add2 ancestor joint[" << (jrd.size()-1) << "] = " << ancestor->getName() << LL_ENDL; + jrd.push_back(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js)); + LL_DEBUGS("Avatar") << "add2 joint[" << (jrd.size()-1) << "] = " << current_joint->getName() << LL_ENDL; } } diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h index 5dece5972c..3ee647103d 100644 --- a/indra/llappearance/llavatarjointmesh.h +++ b/indra/llappearance/llavatarjointmesh.h @@ -49,7 +49,7 @@ class LLSkinJoint public: LLSkinJoint(); ~LLSkinJoint(); - void setupSkinJoint( LLJoint *joint); + BOOL setupSkinJoint( LLJoint *joint); LLJoint* mJoint; LLVector3 mRootToJointSkinOffset; @@ -124,6 +124,9 @@ class LLAvatarJointMesh : public virtual LLAvatarJoint // Sets up joint matrix data for rendering void setupJoint(LLJoint* current_joint); + // Render time method to upload batches of joint matrices + void uploadJointMatrices(); + // Sets ID for picking void setMeshID( S32 id ) {mMeshID = id;} diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp index d7e3ce858f..cf16074472 100644 --- a/indra/llappearance/lldriverparam.cpp +++ b/indra/llappearance/lldriverparam.cpp @@ -102,7 +102,7 @@ void LLDriverParamInfo::toStream(std::ostream &out) LLViewerVisualParamInfo::toStream(out); out << "driver" << "\t"; out << mDrivenInfoList.size() << "\t"; - for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++) + for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); ++iter) { LLDrivenEntryInfo driven = *iter; out << driven.mDrivenID << "\t"; @@ -110,14 +110,26 @@ void LLDriverParamInfo::toStream(std::ostream &out) out << std::endl; - if(mDriverParam && mDriverParam->getAvatarAppearance()->isSelf() && - mDriverParam->getAvatarAppearance()->isValid()) + // FIXME - this mDriverParam backlink makes no sense, because the + // LLDriverParamInfos are static objects - there's only one copy + // for each param type, so the backlink will just reference the + // corresponding param in the most recently created + // avatar. Apparently these toStream() methods are not currently + // used anywhere, so it's not an urgent problem. + LL_WARNS_ONCE() << "Invalid usage of mDriverParam." << LL_ENDL; + + if (!mDriverParam) + return; + const auto& avatar_appearance = mDriverParam->getAvatarAppearance(); + + if(avatar_appearance->isSelf() && + avatar_appearance->isValid()) { - for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++) + for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); ++iter) { LLDrivenEntryInfo driven = *iter; LLViewerVisualParam *param = - (LLViewerVisualParam*)mDriverParam->getAvatarAppearance()->getVisualParam(driven.mDrivenID); + (LLViewerVisualParam*) avatar_appearance->getVisualParam(driven.mDrivenID); if (param) { param->getInfo()->toStream(out); @@ -140,7 +152,7 @@ void LLDriverParamInfo::toStream(std::ostream &out) else { LL_WARNS() << "could not get parameter " << driven.mDrivenID << " from avatar " - << mDriverParam->getAvatarAppearance() + << avatar_appearance << " for driver parameter " << getID() << LL_ENDL; } out << std::endl; @@ -224,7 +236,7 @@ void LLDriverParam::setWeight(F32 weight, bool upload_bake) //-------|----|-------|----|-------> driver // | min1 max1 max2 min2 - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); ++iter ) { LLDrivenEntry* driven = &(*iter); LLDrivenEntryInfo* info = driven->mInfo; @@ -297,7 +309,7 @@ void LLDriverParam::setWeight(F32 weight, bool upload_bake) F32 LLDriverParam::getTotalDistortion() { F32 sum = 0.f; - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); ++iter ) { LLDrivenEntry* driven = &(*iter); sum += driven->mParam->getTotalDistortion(); @@ -312,7 +324,7 @@ const LLVector4a &LLDriverParam::getAvgDistortion() LLVector4a sum; sum.clear(); S32 count = 0; - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); ++iter ) { LLDrivenEntry* driven = &(*iter); sum.add(driven->mParam->getAvgDistortion()); @@ -327,7 +339,7 @@ const LLVector4a &LLDriverParam::getAvgDistortion() F32 LLDriverParam::getMaxDistortion() { F32 max = 0.f; - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); ++iter ) { LLDrivenEntry* driven = &(*iter); F32 param_max = driven->mParam->getMaxDistortion(); @@ -345,7 +357,7 @@ LLVector4a LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { LLVector4a sum; sum.clear(); - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); ++iter ) { LLDrivenEntry* driven = &(*iter); sum.add(driven->mParam->getVertexDistortion( index, poly_mesh )); @@ -357,7 +369,7 @@ const LLVector4a* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **pol { mCurrentDistortionParam = NULL; const LLVector4a* v = NULL; - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); ++iter ) { LLDrivenEntry* driven = &(*iter); v = driven->mParam->getFirstDistortion( index, poly_mesh ); @@ -383,7 +395,7 @@ const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly entry_list_t::iterator iter; // Set mDriven iteration to the right point - for( iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + for( iter = mDriven.begin(); iter != mDriven.end(); ++iter ) { driven = &(*iter); if( driven->mParam == mCurrentDistortionParam ) @@ -404,7 +416,7 @@ const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly { // This param is finished, so start the next param. It might not have any // distortions, though, so we have to loop to find the next param that does. - for( iter++; iter != mDriven.end(); iter++ ) + for( ++iter; iter != mDriven.end(); ++iter ) { driven = &(*iter); v = driven->mParam->getFirstDistortion( index, poly_mesh ); @@ -440,7 +452,7 @@ void LLDriverParam::setAnimationTarget( F32 target_value, bool upload_bake ) { LLVisualParam::setAnimationTarget(target_value, upload_bake); - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); ++iter ) { LLDrivenEntry* driven = &(*iter); F32 driven_weight = getDrivenWeight(driven, mTargetWeight); @@ -458,7 +470,7 @@ void LLDriverParam::stopAnimating(bool upload_bake) { LLVisualParam::stopAnimating(upload_bake); - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); ++iter ) { LLDrivenEntry* driven = &(*iter); driven->mParam->setAnimating(FALSE); @@ -515,7 +527,7 @@ void LLDriverParam::updateCrossDrivenParams(LLWearableType::EType driven_type) bool needs_update = (getWearableType()==driven_type); // if the driver has a driven entry for the passed-in wearable type, we need to refresh the value - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); ++iter ) { LLDrivenEntry* driven = &(*iter); if (driven && driven->mParam && driven->mParam->getCrossWearable() && driven->mParam->getWearableType() == driven_type) diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h index ce6fa6345e..a7dec8acb3 100644 --- a/indra/llappearance/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -29,6 +29,7 @@ #include "llviewervisualparam.h" #include "llwearabletype.h" +#include class LLAvatarAppearance; class LLDriverParam; @@ -130,6 +131,10 @@ class LLDriverParam : public LLViewerVisualParam S32 getDrivenParamsCount() const; const LLViewerVisualParam* getDrivenParam(S32 index) const; + typedef std::vector entry_list_t; + entry_list_t& getDrivenList() { return mDriven; } + void setDrivenList(entry_list_t& driven_list) { mDriven = driven_list; } + protected: LLDriverParam(const LLDriverParam& pOther); F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); @@ -137,7 +142,6 @@ class LLDriverParam : public LLViewerVisualParam LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder - typedef std::vector entry_list_t; entry_list_t mDriven; LLViewerVisualParam* mCurrentDistortionParam; // Backlink only; don't make this an LLPointer. diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp index f49cf21512..f0a789c467 100644 --- a/indra/llappearance/lllocaltextureobject.cpp +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -76,6 +76,7 @@ LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject& lto) : LLLocalTextureObject::~LLLocalTextureObject() { + delete_and_clear(mTexLayers); } LLGLTexture* LLLocalTextureObject::getImage() const @@ -95,7 +96,7 @@ LLTexLayer* LLLocalTextureObject::getTexLayer(U32 index) const LLTexLayer* LLLocalTextureObject::getTexLayer(const std::string &name) { - for( tex_layer_vec_t::iterator iter = mTexLayers.begin(); iter != mTexLayers.end(); iter++) + for( tex_layer_vec_t::iterator iter = mTexLayers.begin(); iter != mTexLayers.end(); ++iter) { LLTexLayer *layer = *iter; if (layer->getName().compare(name) == 0) @@ -196,7 +197,7 @@ BOOL LLLocalTextureObject::removeTexLayer(U32 index) return TRUE; } -void LLLocalTextureObject::setID(LLUUID new_id) +void LLLocalTextureObject::setID(const LLUUID& new_id) { mID = new_id; } diff --git a/indra/llappearance/lllocaltextureobject.h b/indra/llappearance/lllocaltextureobject.h index 9b9f41fd19..699dbafcdc 100644 --- a/indra/llappearance/lllocaltextureobject.h +++ b/indra/llappearance/lllocaltextureobject.h @@ -61,7 +61,7 @@ class LLLocalTextureObject BOOL addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable); BOOL removeTexLayer(U32 index); - void setID(LLUUID new_id); + void setID(const LLUUID& new_id); void setDiscard(S32 new_discard); void setBakedReady(BOOL ready); diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index b9e70fd83f..529755819a 100644 --- a/indra/llappearance/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -161,7 +161,7 @@ void LLPolyMeshSharedData::freeMeshData() // mVertFaceMap.deleteAllData(); } -// compate_int is used by the qsort function to sort the index array +// compare_int is used by the qsort function to sort the index array S32 compare_int(const void *a, const void *b); //----------------------------------------------------------------------------- @@ -307,7 +307,11 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) //---------------------------------------------------------------- // File Header (seek past it) //---------------------------------------------------------------- - fseek(fp, 24, SEEK_SET); + if (fseek(fp, 24, SEEK_SET) != 0) + { + LL_ERRS() << "can't seek past header from " << fileName << LL_ENDL; + return FALSE; + } //---------------------------------------------------------------- // HasWeights @@ -605,7 +609,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) //------------------------------------------------------------------------- char morphName[64+1]; morphName[sizeof(morphName)-1] = '\0'; // ensure nul-termination - while(fread(&morphName, sizeof(char), 64, fp) == 64) + while(fread(morphName, sizeof(char), 64, fp) == 64) { if (!strcmp(morphName, "End Morphs")) { @@ -629,10 +633,6 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) mMorphData.insert(clone_morph_param_cleavage(morph_data, .75f, "Breast_Physics_LeftRight_Driven")); - } - - if (!strcmp(morphName, "Breast_Female_Cleavage")) - { mMorphData.insert(clone_morph_param_duplicate(morph_data, "Breast_Physics_InOut_Driven")); } @@ -668,9 +668,6 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0,0.05f), "Butt_Physics_UpDown_Driven")); - } - if (!strcmp(morphName, "Small_Butt")) - { mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0.03f,0), "Butt_Physics_LeftRight_Driven")); diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 873169cba3..626940b190 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -109,7 +109,7 @@ LLPolyMorphData::~LLPolyMorphData() BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) { S32 numVertices; - S32 numRead; + size_t numRead; // numRead = fread(&numVertices, sizeof(S32), 1, fp); llendianswizzle(&numVertices, sizeof(S32), 1); @@ -680,8 +680,8 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) if (!mMorphData) { const std::string driven_tag = "_Driven"; - U32 pos = morph_param_name.find(driven_tag); - if (pos > 0) + size_t pos = morph_param_name.find(driven_tag); + if (pos != std::string::npos) { morph_param_name = morph_param_name.substr(0,pos); mMorphData = mMesh->getMorphData(morph_param_name); @@ -835,7 +835,7 @@ F32 LLPolyMorphTarget::getMaxDistortion() //----------------------------------------------------------------------------- // apply() //----------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_APPLY_MORPH_TARGET("Apply Morph"); +static LLTrace::BlockTimerStatHandle FTM_APPLY_MORPH_TARGET("Apply Morph"); void LLPolyMorphTarget::apply( ESex avatar_sex ) { @@ -844,7 +844,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) return; } - LLFastTimer t(FTM_APPLY_MORPH_TARGET); + LL_RECORD_BLOCK_TIME(FTM_APPLY_MORPH_TARGET); mLastSex = avatar_sex; @@ -937,7 +937,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) } // now apply volume changes - for( volume_list_t::iterator iter = mVolumeMorphs.begin(); iter != mVolumeMorphs.end(); iter++ ) + for( volume_list_t::iterator iter = mVolumeMorphs.begin(); iter != mVolumeMorphs.end(); ++iter ) { LLPolyVolumeMorph* volume_morph = &(*iter); LLVector3 scale_delta = volume_morph->mScale * delta_weight; @@ -1027,6 +1027,20 @@ void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S3 apply(mLastSex); } +void LLPolyMorphTarget::applyVolumeChanges(F32 delta_weight) +{ + // now apply volume changes + for( volume_list_t::iterator iter = mVolumeMorphs.begin(); iter != mVolumeMorphs.end(); ++iter ) + { + LLPolyVolumeMorph* volume_morph = &(*iter); + LLVector3 scale_delta = volume_morph->mScale * delta_weight; + LLVector3 pos_delta = volume_morph->mPos * delta_weight; + + volume_morph->mVolume->setScale(volume_morph->mVolume->getScale() + scale_delta); + // SL-315 + volume_morph->mVolume->setPosition(volume_morph->mVolume->getPosition() + pos_delta); + } +} //----------------------------------------------------------------------------- // LLPolyVertexMask() diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index aa1591bf7f..7c6dca9ec6 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -186,6 +186,7 @@ class LLPolyMorphTarget : public LLViewerVisualParam void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert); void addPendingMorphMask() { mNumMorphMasksPending++; } + void applyVolumeChanges(F32 delta_weight); // SL-315 - for resetSkeleton() void* operator new(size_t size) { diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index 4bfef71a14..a9debf4b47 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -141,54 +141,58 @@ LLPolySkeletalDistortion::~LLPolySkeletalDistortion() BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) { llassert(mInfo == NULL); - if (info->mID < 0) - return FALSE; - mInfo = info; - mID = info->mID; - setWeight(getDefaultWeight()); - - LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter; - for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++) + if (info->mID < 0) + { + return FALSE; + } + mInfo = info; + mID = info->mID; + setWeight(getDefaultWeight()); + + LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter; + for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); ++iter) + { + LLPolySkeletalBoneInfo *bone_info = &(*iter); + LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName); + if (!joint) + { + // There's no point continuing after this error - means + // that either the skeleton or lad file is broken. + LL_WARNS() << "Joint " << bone_info->mBoneName << " not found." << LL_ENDL; + return FALSE; + } + + if (mJointScales.find(joint) != mJointScales.end()) + { + LL_WARNS() << "Scale deformation already supplied for joint " << joint->getName() << "." << LL_ENDL; + } + + // store it + mJointScales[joint] = bone_info->mScaleDeformation; + + // apply to children that need to inherit it + for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin(); + iter != joint->mChildren.end(); ++iter) + { + LLAvatarJoint* child_joint = dynamic_cast(*iter); + if (child_joint && child_joint->inheritScale()) + { + LLVector3 childDeformation = LLVector3(child_joint->getScale()); + childDeformation.scaleVec(bone_info->mScaleDeformation); + mJointScales[child_joint] = childDeformation; + } + } + + if (bone_info->mHasPositionDeformation) { - LLPolySkeletalBoneInfo *bone_info = &(*iter); - LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName); - if (!joint) - { - LL_WARNS() << "Joint " << bone_info->mBoneName << " not found." << LL_ENDL; - continue; - } - - if (mJointScales.find(joint) != mJointScales.end()) - { - LL_WARNS() << "Scale deformation already supplied for joint " << joint->getName() << "." << LL_ENDL; - } - - // store it - mJointScales[joint] = bone_info->mScaleDeformation; - - // apply to children that need to inherit it - for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin(); - iter != joint->mChildren.end(); ++iter) - { - LLAvatarJoint* child_joint = dynamic_cast(*iter); - if (child_joint && child_joint->inheritScale()) - { - LLVector3 childDeformation = LLVector3(child_joint->getScale()); - childDeformation.scaleVec(bone_info->mScaleDeformation); - mJointScales[child_joint] = childDeformation; - } - } - - if (bone_info->mHasPositionDeformation) - { - if (mJointOffsets.find(joint) != mJointOffsets.end()) - { - LL_WARNS() << "Offset deformation already supplied for joint " << joint->getName() << "." << LL_ENDL; - } - mJointOffsets[joint] = bone_info->mPositionDeformation; - } + if (mJointOffsets.find(joint) != mJointOffsets.end()) + { + LL_WARNS() << "Offset deformation already supplied for joint " << joint->getName() << "." << LL_ENDL; + } + mJointOffsets[joint] = bone_info->mPositionDeformation; } - return TRUE; + } + return TRUE; } /*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const @@ -199,44 +203,55 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) //----------------------------------------------------------------------------- // apply() //----------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion"); +static LLTrace::BlockTimerStatHandle FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion"); void LLPolySkeletalDistortion::apply( ESex avatar_sex ) { - LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY); + LL_RECORD_BLOCK_TIME(FTM_POLYSKELETAL_DISTORTION_APPLY); - F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight(); + F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight(); - LLJoint* joint; - joint_vec_map_t::iterator iter; + LLJoint* joint; + joint_vec_map_t::iterator iter; for (iter = mJointScales.begin(); iter != mJointScales.end(); - iter++) + ++iter) { joint = iter->first; LLVector3 newScale = joint->getScale(); - LLVector3 scaleDelta = iter->second; - newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta); - joint->setScale(newScale); + LLVector3 scaleDelta = iter->second; + LLVector3 offset = (effective_weight - mLastWeight) * scaleDelta; + newScale = newScale + offset; + //An aspect of attached mesh objects (which contain joint offsets) that need to be cleaned up when detached + // needed? + // joint->storeScaleForReset( newScale ); + + // BENTO for detailed stack tracing of params. + // std::stringstream ostr; + // ostr << "LLPolySkeletalDistortion::apply, id " << getID() << " " << getName() << " effective wt " << effective_weight << " last wt " << mLastWeight << " scaleDelta " << scaleDelta << " offset " << offset; + + joint->setScale(newScale, true); } - for (iter = mJointOffsets.begin(); - iter != mJointOffsets.end(); - iter++) - { - joint = iter->first; - LLVector3 newPosition = joint->getPosition(); - LLVector3 positionDelta = iter->second; + for (iter = mJointOffsets.begin(); + iter != mJointOffsets.end(); + ++iter) + { + joint = iter->first; + LLVector3 newPosition = joint->getPosition(); + LLVector3 positionDelta = iter->second; newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta); - joint->setPosition(newPosition); - } + // SL-315 + bool allow_attachment_pos_overrides = true; + joint->setPosition(newPosition, allow_attachment_pos_overrides); + } - if (mLastWeight != mCurWeight && !mIsAnimating) + if (mLastWeight != effective_weight && !mIsAnimating) { mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1); } - mLastWeight = mCurWeight; + mLastWeight = effective_weight; } diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp index a241df8e42..0df6981536 100644 --- a/indra/llappearance/lltexglobalcolor.cpp +++ b/indra/llappearance/lltexglobalcolor.cpp @@ -57,7 +57,7 @@ BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) mParamGlobalColorList.reserve(mInfo->mParamColorInfoList.size()); for (param_color_info_list_t::iterator iter = mInfo->mParamColorInfoList.begin(); iter != mInfo->mParamColorInfoList.end(); - iter++) + ++iter) { LLTexParamGlobalColor* param_color = new LLTexParamGlobalColor(this); if (!param_color->setInfo(*iter, TRUE)) @@ -135,6 +135,7 @@ LLTexGlobalColorInfo::LLTexGlobalColorInfo() LLTexGlobalColorInfo::~LLTexGlobalColorInfo() { for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer()); + mParamColorInfoList.clear(); } BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index b0f922b950..83a72eeb1c 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -256,7 +256,7 @@ void LLTexLayerSetInfo::createVisualParams(LLAvatarAppearance *appearance) //layer_info_list_t mLayerInfoList; for (layer_info_list_t::iterator layer_iter = mLayerInfoList.begin(); layer_iter != mLayerInfoList.end(); - layer_iter++) + ++layer_iter) { LLTexLayerInfo *layer_info = *layer_iter; layer_info->createVisualParams(appearance); @@ -299,7 +299,7 @@ BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) mLayerList.reserve(info->mLayerInfoList.size()); for (LLTexLayerSetInfo::layer_info_list_t::const_iterator iter = info->mLayerInfoList.begin(); iter != info->mLayerInfoList.end(); - iter++) + ++iter) { LLTexLayerInterface *layer = NULL; if ( (*iter)->isUserSettable() ) @@ -358,12 +358,12 @@ BOOL LLTexLayerSet::parseData(LLXmlTreeNode* node) void LLTexLayerSet::deleteCaches() { - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); ++iter ) { LLTexLayerInterface* layer = *iter; layer->deleteCaches(); } - for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); ++iter) { LLTexLayerInterface* layer = *iter; layer->deleteCaches(); @@ -378,7 +378,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) if (mMaskLayerList.size() > 0) { - for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); ++iter) { LLTexLayerInterface* layer = *iter; if (layer->isInvisibleAlphaMask()) @@ -397,7 +397,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) // clear buffer area to ensure we don't pick up UI elements { gGL.flush(); - LLGLDisable no_alpha(GL_ALPHA_TEST); + LLGLDisable no_alpha; if (use_shaders) { gAlphaMaskProgram.setMinimumAlpha(0.0f); @@ -417,7 +417,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) if (mIsVisible) { // composite color layers - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); ++iter ) { LLTexLayerInterface* layer = *iter; if (layer->getRenderPass() == LLTexLayer::RP_COLOR) @@ -437,7 +437,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) gGL.flush(); gGL.setSceneBlendType(LLRender::BT_REPLACE); - LLGLDisable no_alpha(GL_ALPHA_TEST); + LLGLDisable no_alpha; if (use_shaders) { gAlphaMaskProgram.setMinimumAlpha(0.f); @@ -521,13 +521,13 @@ const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const return mComposite; } -static LLFastTimer::DeclareTimer FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha"); +static LLTrace::BlockTimerStatHandle FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha"); void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height) { - LLFastTimer t(FTM_GATHER_MORPH_MASK_ALPHA); + LL_RECORD_BLOCK_TIME(FTM_GATHER_MORPH_MASK_ALPHA); memset(data, 255, width * height); - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); ++iter ) { LLTexLayerInterface* layer = *iter; layer->gatherAlphaMasks(data, origin_x, origin_y, width, height); @@ -537,10 +537,10 @@ void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S renderAlphaMaskTextures(origin_x, origin_y, width, height, true); } -static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures"); void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear) { - LLFastTimer t(FTM_RENDER_ALPHA_MASK_TEXTURES); + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_TEXTURES); const LLTexLayerSetInfo *info = getInfo(); bool use_shaders = LLGLSLShader::sNoFixedFunction; @@ -568,7 +568,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, { // Set the alpha channel to one (clean up after previous blending) gGL.flush(); - LLGLDisable no_alpha(GL_ALPHA_TEST); + LLGLDisable no_alpha; if (use_shaders) { gAlphaMaskProgram.setMinimumAlpha(0.f); @@ -591,7 +591,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, { gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); - for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); ++iter) { LLTexLayerInterface* layer = *iter; gGL.flush(); @@ -615,7 +615,7 @@ void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_ BOOL LLTexLayerSet::isMorphValid() const { - for(layer_list_t::const_iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + for(layer_list_t::const_iterator iter = mLayerList.begin(); iter != mLayerList.end(); ++iter ) { const LLTexLayerInterface* layer = *iter; if (layer && !layer->isMorphValid()) @@ -628,7 +628,7 @@ BOOL LLTexLayerSet::isMorphValid() const void LLTexLayerSet::invalidateMorphMasks() { - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); ++iter ) { LLTexLayerInterface* layer = *iter; if (layer) @@ -727,7 +727,7 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) mLocalTexture = TEX_NUM_INDICES; for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); - iter++) + ++iter) { const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (local_texture_name == texture_dict->mName) @@ -801,7 +801,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance) BOOL success = TRUE; for (param_color_info_list_t::iterator color_info_iter = mParamColorInfoList.begin(); color_info_iter != mParamColorInfoList.end(); - color_info_iter++) + ++color_info_iter) { LLTexLayerParamColorInfo * color_info = *color_info_iter; LLTexLayerParamColor* param_color = new LLTexLayerParamColor(appearance); @@ -815,7 +815,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance) for (param_alpha_info_list_t::iterator alpha_info_iter = mParamAlphaInfoList.begin(); alpha_info_iter != mParamAlphaInfoList.end(); - alpha_info_iter++) + ++alpha_info_iter) { LLTexLayerParamAlphaInfo * alpha_info = *alpha_info_iter; LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(appearance); @@ -862,7 +862,7 @@ BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearab mParamColorList.reserve(mInfo->mParamColorInfoList.size()); for (param_color_info_list_t::const_iterator iter = mInfo->mParamColorInfoList.begin(); iter != mInfo->mParamColorInfoList.end(); - iter++) + ++iter) { LLTexLayerParamColor* param_color; if (!wearable) @@ -889,7 +889,7 @@ BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearab mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size()); for (param_alpha_info_list_t::const_iterator iter = mInfo->mParamAlphaInfoList.begin(); iter != mInfo->mParamAlphaInfoList.end(); - iter++) + ++iter) { LLTexLayerParamAlpha* param_alpha; if (!wearable) @@ -940,7 +940,7 @@ LLWearableType::EType LLTexLayerInterface::getWearableType() const param_color_list_t::const_iterator color_iter = mParamColorList.begin(); param_alpha_list_t::const_iterator alpha_iter = mParamAlphaList.begin(); - for (; color_iter != mParamColorList.end(); color_iter++) + for (; color_iter != mParamColorList.end(); ++color_iter) { LLTexLayerParamColor* param = *color_iter; if (param) @@ -957,7 +957,7 @@ LLWearableType::EType LLTexLayerInterface::getWearableType() const } } - for (; alpha_iter != mParamAlphaList.end(); alpha_iter++) + for (; alpha_iter != mParamAlphaList.end(); ++alpha_iter) { LLTexLayerParamAlpha* param = *alpha_iter; if (param) @@ -1059,7 +1059,7 @@ LLTexLayer::~LLTexLayer() //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); for( alpha_cache_t::iterator iter = mAlphaCache.begin(); - iter != mAlphaCache.end(); iter++ ) + iter != mAlphaCache.end(); ++iter ) { U8* alpha_data = iter->second; delete [] alpha_data; @@ -1086,7 +1086,7 @@ BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color) { for (param_color_list_t::const_iterator iter = param_list.begin(); - iter != param_list.end(); iter++) + iter != param_list.end(); ++iter) { const LLTexLayerParamColor* param = *iter; LLColor4 param_net = param->getNetColor(); @@ -1114,7 +1114,7 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL { // Only need to delete caches for alpha params. Color params don't hold extra memory for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); - iter != mParamAlphaList.end(); iter++ ) + iter != mParamAlphaList.end(); ++iter ) { LLTexLayerParamAlpha* param = *iter; param->deleteCaches(); @@ -1123,14 +1123,11 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) { - LLGLEnable color_mat(GL_COLOR_MATERIAL); + LLGLEnable color_mat; // *TODO: Is this correct? //gPipeline.disableLights(); stop_glerror(); - if (!LLGLSLShader::sNoFixedFunction) - { - glDisable(GL_LIGHTING); - } + LLGLDisable no_lighting(!LLGLSLShader::sNoFixedFunction); stop_glerror(); bool use_shaders = LLGLSLShader::sNoFixedFunction; @@ -1217,7 +1214,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) if( tex ) { bool no_alpha_test = getInfo()->mWriteAllChannels; - LLGLDisable alpha_test(no_alpha_test ? GL_ALPHA_TEST : 0); + LLGLDisable alpha_test(no_alpha_test); if (no_alpha_test) { if (use_shaders) @@ -1273,7 +1270,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) getInfo()->mStaticImageFileName.empty() && color_specified ) { - LLGLDisable no_alpha(GL_ALPHA_TEST); + LLGLDisable no_alpha; if (use_shaders) { gAlphaMaskProgram.setMinimumAlpha(0.000f); @@ -1309,7 +1306,7 @@ const U8* LLTexLayer::getAlphaData() const const LLUUID& uuid = getUUID(); alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); - for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) + for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); ++iter) { const LLTexLayerParamAlpha* param = *iter; // MULTI-WEARABLE: verify visual parameters used here @@ -1430,7 +1427,7 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) addAlphaMask(data, originX, originY, width, height); } -static LLFastTimer::DeclareTimer FTM_RENDER_MORPH_MASKS("renderMorphMasks"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_MORPH_MASKS("renderMorphMasks"); void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render) { if (!force_render && !hasMorph()) @@ -1438,7 +1435,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC LL_DEBUGS() << "skipping renderMorphMasks for " << getUUID() << LL_ENDL; return; } - LLFastTimer t(FTM_RENDER_MORPH_MASKS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_MORPH_MASKS); BOOL success = TRUE; llassert( !mParamAlphaList.empty() ); @@ -1456,7 +1453,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // Note: if the first param is a mulitply, multiply against the current buffer's alpha if( !first_param || !first_param->getMultiplyBlend() ) { - LLGLDisable no_alpha(GL_ALPHA_TEST); + LLGLDisable no_alpha; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); // Clear the alpha @@ -1470,7 +1467,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // Accumulate alphas LLGLSNoAlphaTest gls_no_alpha_test; gGL.color4f( 1.f, 1.f, 1.f, 1.f ); - for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) + for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); ++iter) { LLTexLayerParamAlpha* param = *iter; success &= param->render( x, y, width, height ); @@ -1528,7 +1525,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO ); if ( !is_approx_equal(layer_color.mV[VW], 1.f) ) { - LLGLDisable no_alpha(GL_ALPHA_TEST); + LLGLDisable no_alpha; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4fv(layer_color.mV); gl_rect_2d_simple( width, height ); @@ -1549,7 +1546,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC const LLUUID& uuid = getUUID(); alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); - for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) + for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); ++iter) { const LLTexLayerParamAlpha* param = *iter; F32 param_weight = param->getWeight(); @@ -1557,13 +1554,13 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } U32 cache_index = alpha_mask_crc.getCRC(); - U8* alpha_data = NULL;//get_if_there(mAlphaCache,cache_index,(U8*)NULL); + U8* alpha_data = NULL; // We believe we need to generate morph masks, do not assume that the cached version is accurate. // We can get bad morph masks during login, on minimize, and occasional gl errors. // We should only be doing this when we believe something has changed with respect to the user's appearance. - //if (!alpha_data) { - // clear out a slot if we have filled our cache + LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL; + // clear out a slot if we have filled our cache S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1; while ((S32)mAlphaCache.size() >= max_cache_entries) { @@ -1573,8 +1570,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC mAlphaCache.erase(iter2); } alpha_data = new U8[width * height]; + U8* pixels_tmp = new U8[width * height * 4]; + glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels_tmp); + for (int i = 0; i < width * height; ++i) + alpha_data[i] = pixels_tmp[i * 4 + 3]; + delete[] pixels_tmp; mAlphaCache[cache_index] = alpha_data; - glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); } getTexLayerSet()->getAvatarAppearance()->dirtyMesh(); @@ -1584,10 +1585,10 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } } -static LLFastTimer::DeclareTimer FTM_ADD_ALPHA_MASK("addAlphaMask"); +static LLTrace::BlockTimerStatHandle FTM_ADD_ALPHA_MASK("addAlphaMask"); void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height) { - LLFastTimer t(FTM_ADD_ALPHA_MASK); + LL_RECORD_BLOCK_TIME(FTM_ADD_ALPHA_MASK); S32 size = width * height; const U8* alphaData = getAlphaData(); if (!alphaData && hasAlphaParams()) @@ -1740,7 +1741,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const BOOL success = TRUE; updateWearableCache(); - for (wearable_cache_t::const_iterator iter = mWearableCache.begin(); iter!= mWearableCache.end(); iter++) + for (wearable_cache_t::const_iterator iter = mWearableCache.begin(); iter!= mWearableCache.end(); ++iter) { LLWearable* wearable = NULL; LLLocalTextureObject *lto = NULL; @@ -1783,13 +1784,11 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const /*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) { U32 num_wearables = updateWearableCache(); - for (U32 i = 0; i < num_wearables; i++) + U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable + LLTexLayer *layer = getLayer(i); + if (layer) { - LLTexLayer *layer = getLayer(i); - if (layer) - { - layer->addAlphaMask(data, originX, originY, width, height); - } + layer->addAlphaMask(data, originX, originY, width, height); } } @@ -1844,7 +1843,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const //----------------------------------------------------------------------------- LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name) { - for (layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + for (layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); ++iter ) { LLTexLayerInterface* layer = *iter; if (layer->getName() == name) @@ -1852,7 +1851,7 @@ LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name) return layer; } } - for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ ) + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); ++iter ) { LLTexLayerInterface* layer = *iter; if (layer->getName() == name) @@ -1866,7 +1865,7 @@ LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name) void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearanceDefines::ETextureIndex tex_index, LLWearable *wearable) { // initialize all texlayers with this texture type for this LTO - for( LLTexLayerSet::layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + for( LLTexLayerSet::layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); ++iter ) { LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter; if (layer->getInfo()->getLocalTexture() == (S32) tex_index) @@ -1874,7 +1873,7 @@ void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearance lto->addTexLayer(layer, wearable); } } - for( LLTexLayerSet::layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ ) + for( LLTexLayerSet::layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); ++iter ) { LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter; if (layer->getInfo()->getLocalTexture() == (S32) tex_index) @@ -1930,10 +1929,10 @@ void LLTexLayerStaticImageList::deleteCachedImages() // Returns an LLImageTGA that contains the encoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. -static LLFastTimer::DeclareTimer FTM_LOAD_STATIC_TGA("getImageTGA"); +static LLTrace::BlockTimerStatHandle FTM_LOAD_STATIC_TGA("getImageTGA"); LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) { - LLFastTimer t(FTM_LOAD_STATIC_TGA); + LL_RECORD_BLOCK_TIME(FTM_LOAD_STATIC_TGA); const char *namekey = mImageNames.addString(file_name); image_tga_map_t::const_iterator iter = mStaticImageListTGA.find(namekey); if( iter != mStaticImageListTGA.end() ) @@ -1960,10 +1959,10 @@ LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) // Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. -static LLFastTimer::DeclareTimer FTM_LOAD_STATIC_TEXTURE("getTexture"); +static LLTrace::BlockTimerStatHandle FTM_LOAD_STATIC_TEXTURE("getTexture"); LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask) { - LLFastTimer t(FTM_LOAD_STATIC_TEXTURE); + LL_RECORD_BLOCK_TIME(FTM_LOAD_STATIC_TEXTURE); LLPointer tex; const char *namekey = mImageNames.addString(file_name); @@ -1991,7 +1990,7 @@ LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, image_raw->copyUnscaledAlphaMask(alpha_image_raw, LLColor4U::black); } - tex->createGLTexture(0, image_raw, 0, TRUE, LLGLTexture::LOCAL); + tex->createGLTexture(0, image_raw, nullptr, TRUE, LLGLTexture::LOCAL); gGL.getTexUnit(0)->bind(tex); tex->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -2010,10 +2009,10 @@ LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, // Reads a .tga file, decodes it, and puts the decoded data in image_raw. // Returns TRUE if successful. -static LLFastTimer::DeclareTimer FTM_LOAD_IMAGE_RAW("loadImageRaw"); +static LLTrace::BlockTimerStatHandle FTM_LOAD_IMAGE_RAW("loadImageRaw"); BOOL LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw) { - LLFastTimer t(FTM_LOAD_IMAGE_RAW); + LL_RECORD_BLOCK_TIME(FTM_LOAD_IMAGE_RAW); BOOL success = FALSE; std::string path; path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 42cb163a52..7f3f486ca3 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -103,7 +103,7 @@ void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes) *gl_bytes = 0; for (param_alpha_ptr_list_t::iterator iter = sInstances.begin(); - iter != sInstances.end(); iter++) + iter != sInstances.end(); ++iter) { LLTexLayerParamAlpha* instance = *iter; LLGLTexture* tex = instance->mCachedProcessedTexture; @@ -260,10 +260,10 @@ BOOL LLTexLayerParamAlpha::getSkip() const } -static LLFastTimer::DeclareTimer FTM_TEX_LAYER_PARAM_ALPHA("alpha render"); +static LLTrace::BlockTimerStatHandle FTM_TEX_LAYER_PARAM_ALPHA("alpha render"); BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) { - LLFastTimer t(FTM_TEX_LAYER_PARAM_ALPHA); + LL_RECORD_BLOCK_TIME(FTM_TEX_LAYER_PARAM_ALPHA); BOOL success = TRUE; if (!mTexLayer) @@ -363,7 +363,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) } else { - LLGLDisable no_alpha(GL_ALPHA_TEST); + LLGLDisable no_alpha; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4f(0.f, 0.f, 0.f, effective_weight); gl_rect_2d_simple(width, height); @@ -491,7 +491,7 @@ void LLTexLayerParamColor::setWeight(F32 weight, bool upload_bake) { mCurWeight = new_weight; - const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo(); + const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo(); if (info->mNumColors <= 0) { diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp index 9e5deb07d4..61e81ff586 100644 --- a/indra/llappearance/llviewervisualparam.cpp +++ b/indra/llappearance/llviewervisualparam.cpp @@ -76,7 +76,7 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node) static LLStdStringHandle edit_group_string = LLXmlTree::addAttributeString("edit_group"); if (!node->getFastAttributeString( edit_group_string, mEditGroup)) { - mEditGroup = ""; + mEditGroup.clear(); } static LLStdStringHandle cross_wearable_string = LLXmlTree::addAttributeString("cross_wearable"); diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 45962d898a..31edbc67dc 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -86,10 +86,10 @@ LLAssetType::EType LLWearable::getAssetType() const return LLWearableType::getAssetType(mType); } -BOOL LLWearable::exportFile(LLFILE* fp) const +BOOL LLWearable::exportFile(const std::string& filename) const { - llofstream ofs(fp); - return exportStream(ofs); + llofstream ofs(filename.c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary); + return ofs.is_open() && exportStream(ofs); } // virtual @@ -105,13 +105,13 @@ BOOL LLWearable::exportStream( std::ostream& output_stream ) const output_stream << mDescription << "\n"; // permissions - if( !mPermissions.exportStream( output_stream ) ) + if( !mPermissions.exportLegacyStream( output_stream ) ) { return FALSE; } // sale info - if( !mSaleInfo.exportStream( output_stream ) ) + if( !mSaleInfo.exportLegacyStream( output_stream ) ) { return FALSE; } @@ -169,9 +169,9 @@ void LLWearable::createVisualParams(LLAvatarAppearance *avatarp) // need this line to disambiguate between versions of LLCharacter::getVisualParam() LLVisualParam*(LLAvatarAppearance::*param_function)(S32)const = &LLAvatarAppearance::getVisualParam; param->resetDrivenParams(); - if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) + if (!param->linkDrivenParams(std::bind(wearable_function,(LLWearable*)this, std::placeholders::_1), false)) { - if( !param->linkDrivenParams(boost::bind(param_function,avatarp,_1 ), true)) + if (!param->linkDrivenParams(std::bind(param_function,avatarp, std::placeholders::_1 ), true)) { LL_WARNS() << "could not link driven params for wearable " << getName() << " id: " << param->getID() << LL_ENDL; continue; @@ -184,7 +184,7 @@ void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp) { LLTexLayerSet *layer_set = NULL; const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te); - if (texture_dict->mIsUsedByBakedTexture) + if (texture_dict && texture_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; @@ -193,18 +193,19 @@ void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp) if (layer_set) { - layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); + layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); } else { - LL_ERRS() << "could not find layerset for LTO in wearable!" << LL_ENDL; + LL_WARNS() << "could not find layerset for LTO in wearable!" << LL_ENDL; } } -LLWearable::EImportResult LLWearable::importFile(LLFILE* fp, LLAvatarAppearance* avatarp ) +LLWearable::EImportResult LLWearable::importFile(const std::string& filename, + LLAvatarAppearance* avatarp ) { - llifstream ifs(fp); - return importStream(ifs, avatarp); + llifstream ifs(filename.c_str(), std::ios_base::in | std::ios_base::binary); + return (! ifs.is_open())? FAILURE : importStream(ifs, avatarp); } // virtual @@ -287,7 +288,7 @@ LLWearable::EImportResult LLWearable::importStream( std::istream& input_stream, LL_WARNS() << "Bad Wearable asset: missing valid permissions" << LL_ENDL; return LLWearable::FAILURE; } - if( !mPermissions.importStream( input_stream ) ) + if( !mPermissions.importLegacyStream( input_stream ) ) { return LLWearable::FAILURE; } @@ -312,7 +313,7 @@ LLWearable::EImportResult LLWearable::importStream( std::istream& input_stream, // up the vast majority of the tasks. BOOL has_perm_mask = FALSE; U32 perm_mask = 0; - if( !mSaleInfo.importStream(input_stream, has_perm_mask, perm_mask) ) + if( !mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask) ) { return LLWearable::FAILURE; } @@ -437,6 +438,12 @@ LLWearable::EImportResult LLWearable::importStream( std::istream& input_stream, return LLWearable::FAILURE; } + if (te >= ETextureIndex::TEX_NUM_INDICES) //createLayers() converts to ETextureIndex + { + LL_WARNS() << "Bad Wearable asset: bad texture index: " << te << LL_ENDL; + return LLWearable::FAILURE; + } + if( !LLUUID::validate( uuid_buffer ) ) { LL_WARNS() << "Bad Wearable asset: bad texture uuid: " diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index 3ffcc7516b..d9527b9e9c 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -82,8 +82,8 @@ class LLWearable SUCCESS, BAD_HEADER }; - BOOL exportFile(LLFILE* file) const; - EImportResult importFile(LLFILE* file, LLAvatarAppearance* avatarp ); + BOOL exportFile(const std::string& filename) const; + EImportResult importFile(const std::string& filename, LLAvatarAppearance* avatarp ); virtual BOOL exportStream( std::ostream& output_stream ) const; virtual EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ); diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index 24c011d6fb..0e18ec1868 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -47,7 +47,6 @@ using namespace LLAvatarAppearanceDefines; LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index) { - //llassert_always(index == 0); wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); if (wearable_iter == mWearableDatas.end()) { @@ -66,7 +65,6 @@ LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 in void LLWearableData::setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable) { - //llassert_always(index == 0); LLWearable *old_wearable = getWearable(type,index); if (!old_wearable) { @@ -178,8 +176,9 @@ bool LLWearableData::swapWearables(const LLWearableType::EType type, U32 index_a } wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (0 > index_a || index_a >= wearable_vec.size()) return false; - if (0 > index_b || index_b >= wearable_vec.size()) return false; + // removed 0 > index_a and index_b comparisions - can never be true + if (index_a >= wearable_vec.size()) return false; + if (index_b >= wearable_vec.size()) return false; LLWearable* wearable = wearable_vec[index_a]; wearable_vec[index_a] = wearable_vec[index_b]; diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h index 2cf5585e04..b83ba9a565 100644 --- a/indra/llappearance/llwearabledata.h +++ b/indra/llappearance/llwearabledata.h @@ -105,7 +105,7 @@ class LLWearableData //Why this weird structure? LLWearableType::WT_COUNT small and known, therefore it's more efficient to make an array of vectors, indexed //by wearable type. This allows O(1) lookups. This structure simply lets us plug in this optimization without touching any code elsewhere. - typedef boost::array,LLWearableType::WT_COUNT> wearable_array_t; + typedef std::array, LLWearableType::WT_COUNT> wearable_array_t; struct wearableentry_map_t : public wearable_array_t { wearableentry_map_t() diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index 8ad8b09bd6..b14107f9ea 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -29,17 +29,17 @@ #include "llinventorytype.h" #include "llinventorydefines.h" -static LLTranslationBridge* sTrans = NULL; +static LLTranslationBridge::ptr_t sTrans = NULL; // static -void LLWearableType::initClass(LLTranslationBridge* trans) +void LLWearableType::initClass(LLTranslationBridge::ptr_t &trans) { sTrans = trans; } void LLWearableType::cleanupClass() { - delete sTrans; + sTrans.reset(); } struct WearableEntry : public LLDictionaryEntry @@ -53,8 +53,7 @@ struct WearableEntry : public LLDictionaryEntry LLDictionaryEntry(name), mAssetType(assetType), mDefaultNewName(default_new_name), - //*TODO:Translate - mLabel(/*sTrans->getString*/(name)), + mLabel(sTrans->getString(name)), mIconName(iconName), mDisableCameraSwitch(disable_camera_switch), mAllowMultiwear(allow_multiwear) @@ -99,11 +98,12 @@ LLWearableDictionary::LLWearableDictionary() addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); + addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry("universal", "New Universal", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, FALSE, TRUE)); -// addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); // [SL:KB] - Patch: Appearance-Misc | Checked: 2011-05-29 (Catznip-2.6) addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, FALSE)); // [/SL:KB] +// addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); addEntry(LLWearableType::WT_UNKNOWN, new WearableEntry("unknown", "Clothing", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNKNOWN, FALSE, TRUE)); addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE)); @@ -184,6 +184,6 @@ BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type) // static LLWearableType::EType LLWearableType::inventoryFlagsToWearableType(U32 flags) { - return (LLWearableType::EType)(flags & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK); + return (LLWearableType::EType)(flags & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK); } diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h index 26c9fc230a..ec946d5ad3 100644 --- a/indra/llappearance/llwearabletype.h +++ b/indra/llappearance/llwearabletype.h @@ -31,16 +31,7 @@ #include "lldictionary.h" #include "llinventorytype.h" #include "llsingleton.h" - -class LLTranslationBridge -{ -public: - // clang needs this to be happy - virtual ~LLTranslationBridge() {} - - virtual std::string getString(const std::string &xml_desc) = 0; -}; - +#include "llinvtranslationbrdg.h" class LLWearableType { @@ -63,16 +54,18 @@ class LLWearableType WT_ALPHA = 13, WT_TATTOO = 14, WT_PHYSICS = 15, - WT_UNKNOWN = 16, // Singu note: used for corrupt wearables that do not have their type set in the inventory database. + WT_UNIVERSAL = 16, + WT_UNKNOWN = 17, // Singu note: used for corrupt wearables that do not have their type set in the inventory database. // While all the above values are serialized and stored in the database, this value is local only: - // When a new item with value 16 is added by upstream, just increase this value to 17 (and WT_COUNT to 18). - WT_COUNT = 17, + // When a new item with value 17 is added by upstream, just increase this value to 18 (and WT_COUNT to 19). + // Keep WT_UNKNOWN and WT_COUNT in sync with llinventory.cpp + WT_COUNT = 18, WT_INVALID = 255, WT_NONE = -1, }; - static void initClass(LLTranslationBridge* trans); // initializes static members + static void initClass(LLTranslationBridge::ptr_t &trans); // initializes static members static void cleanupClass(); // initializes static members static const std::string& getTypeName(EType type); diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt index 25970a99a6..92aa14ddc7 100644 --- a/indra/llaudio/CMakeLists.txt +++ b/indra/llaudio/CMakeLists.txt @@ -3,24 +3,13 @@ project(llaudio) include(00-Common) -include(Audio) -include(LLAudio) -if (FMODSTUDIO) - include(FMODSTUDIO) -endif (FMODSTUDIO) -if (FMODEX) - include(FMODEX) -endif (FMODEX) +include(FMODSTUDIO) include(OPENAL) include(LLCommon) include(LLMath) include(LLMessage) include(LLVFS) -if (FMOD) - include_directories(${FMOD_INCLUDE_DIR}) -endif(FMOD) - include_directories( ${LLAUDIO_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS} @@ -31,7 +20,7 @@ include_directories( ${VORBISENC_INCLUDE_DIRS} ${VORBISFILE_INCLUDE_DIRS} ${VORBIS_INCLUDE_DIRS} - ${OPENAL_INCLUDE_DIRS} + ${OPENAL_LIB_INCLUDE_DIRS} ${FREEAULT_LIB_INCLUDE_DIRS} ) @@ -54,7 +43,10 @@ set(llaudio_HEADER_FILES llwindgen.h ) -if (FMODSTUDIO) +if (USE_FMODSTUDIO) + include_directories( + ${FMODSTUDIO_INCLUDE_DIR} + ) list(APPEND llaudio_SOURCE_FILES llaudioengine_fmodstudio.cpp lllistener_fmodstudio.cpp @@ -66,21 +58,7 @@ if (FMODSTUDIO) lllistener_fmodstudio.h llstreamingaudio_fmodstudio.h ) -endif (FMODSTUDIO) - -if (FMODEX) - list(APPEND llaudio_SOURCE_FILES - llaudioengine_fmodex.cpp - lllistener_fmodex.cpp - llstreamingaudio_fmodex.cpp - ) - - list(APPEND llaudio_HEADER_FILES - llaudioengine_fmodex.h - lllistener_fmodex.h - llstreamingaudio_fmodex.h - ) -endif (FMODEX) +endif (USE_FMODSTUDIO) if (OPENAL) list(APPEND llaudio_SOURCE_FILES @@ -100,5 +78,9 @@ set_source_files_properties(${llaudio_HEADER_FILES} list(APPEND llaudio_SOURCE_FILES ${llaudio_HEADER_FILES}) add_library (llaudio ${llaudio_SOURCE_FILES}) -add_dependencies(llaudio prepare) +target_link_libraries( + llaudio + PUBLIC + llcommon + ) diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index 18635737b2..5f5696e376 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -33,7 +33,6 @@ #include "llaudiodecodemgr.h" -#include "llvorbisdecode.h" #include "llaudioengine.h" #include "lllfsthread.h" #include "llvfile.h" @@ -43,10 +42,12 @@ #include "llassetstorage.h" #include "llrefcount.h" +#include "llvorbisencode.h" + #include "vorbis/codec.h" #include "vorbis/vorbisfile.h" -#include "llvorbisencode.h" -#include //VS2010 +#include +#include extern LLAudioEngine *gAudiop; @@ -120,7 +121,7 @@ size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource) } } -int vfs_seek(void *datasource, ogg_int64_t offset, int whence) +S32 vfs_seek(void *datasource, ogg_int64_t offset, S32 whence) { LLVFile *file = (LLVFile *)datasource; @@ -142,7 +143,7 @@ int vfs_seek(void *datasource, ogg_int64_t offset, int whence) origin = -1; break; default: - LL_ERRS() << "Invalid whence argument to vfs_seek" << LL_ENDL; + LL_ERRS("AudioEngine") << "Invalid whence argument to vfs_seek" << LL_ENDL; return -1; } @@ -156,7 +157,7 @@ int vfs_seek(void *datasource, ogg_int64_t offset, int whence) } } -int vfs_close (void *datasource) +S32 vfs_close (void *datasource) { LLVFile *file = (LLVFile *)datasource; delete file; @@ -196,25 +197,25 @@ BOOL LLVorbisDecodeState::initDecode() vfs_callbacks.close_func = vfs_close; vfs_callbacks.tell_func = vfs_tell; - //LL_INFOS() << "Initing decode from vfile: " << mUUID << LL_ENDL; + LL_DEBUGS("AudioEngine") << "Initing decode from vfile: " << mUUID << LL_ENDL; mInFilep = new LLVFile(gVFS, mUUID, LLAssetType::AT_SOUND); if (!mInFilep || !mInFilep->getSize()) { - LL_WARNS() << "unable to open vorbis source vfile for reading" << LL_ENDL; + LL_WARNS("AudioEngine") << "unable to open vorbis source vfile for reading" << LL_ENDL; delete mInFilep; mInFilep = NULL; return FALSE; } - int r = ov_open_callbacks(mInFilep, &mVF, NULL, 0, vfs_callbacks); + S32 r = ov_open_callbacks(mInFilep, &mVF, NULL, 0, vfs_callbacks); if(r < 0) { - LL_WARNS() << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << mUUID << LL_ENDL; + LL_WARNS("AudioEngine") << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << mUUID << LL_ENDL; return(FALSE); } - S32 sample_count = ov_pcm_total(&mVF, -1); + S32 sample_count = (S32)ov_pcm_total(&mVF, -1); size_t size_guess = (size_t)sample_count; vorbis_info* vi = ov_info(&mVF, -1); size_guess *= (vi? vi->channels : 1); @@ -228,13 +229,13 @@ BOOL LLVorbisDecodeState::initDecode() if( vi->channels < 1 || vi->channels > LLVORBIS_CLIP_MAX_CHANNELS ) { abort_decode = true; - LL_WARNS() << "Bad channel count: " << vi->channels << LL_ENDL; + LL_WARNS("AudioEngine") << "Bad channel count: " << vi->channels << LL_ENDL; } } else // !vi { abort_decode = true; - LL_WARNS() << "No default bitstream found" << LL_ENDL; + LL_WARNS("AudioEngine") << "No default bitstream found" << LL_ENDL; } // // This magic value is equivalent to 150MiB of data. @@ -252,25 +253,25 @@ BOOL LLVorbisDecodeState::initDecode() (size_t)sample_count <= 0) { abort_decode = true; - LL_WARNS() << "Illegal sample count: " << sample_count << LL_ENDL; + LL_WARNS("AudioEngine") << "Illegal sample count: " << sample_count << LL_ENDL; } if( size_guess > LLVORBIS_CLIP_REJECT_SIZE || size_guess < 0) { abort_decode = true; - LL_WARNS() << "Illegal sample size: " << size_guess << LL_ENDL; + LL_WARNS("AudioEngine") << "Illegal sample size: " << size_guess << LL_ENDL; } // } // if( abort_decode ) { - LL_WARNS() << "Canceling initDecode. Bad asset: " << mUUID << LL_ENDL; + LL_WARNS("AudioEngine") << "Canceling initDecode. Bad asset: " << mUUID << LL_ENDL; vorbis_comment* comment = ov_comment(&mVF,-1); if (comment && comment->vendor) { - LL_WARNS() << "Bad asset encoded by: " << comment->vendor << LL_ENDL; + LL_WARNS("AudioEngine") << "Bad asset encoded by: " << comment->vendor << LL_ENDL; } delete mInFilep; mInFilep = NULL; @@ -388,7 +389,7 @@ BOOL LLVorbisDecodeState::decodeSection() { if (!mInFilep) { - LL_WARNS() << "No VFS file to decode in vorbis!" << LL_ENDL; + LL_WARNS("AudioEngine") << "No VFS file to decode in vorbis!" << LL_ENDL; return TRUE; } if (mDone) @@ -413,7 +414,7 @@ BOOL LLVorbisDecodeState::decodeSection() /* error in the stream. Not a problem, just reporting it in case we (the app) cares. In this case, we don't. */ - LL_WARNS() << "BAD vorbis decode in decodeSection." << LL_ENDL; + LL_WARNS("AudioEngine") << "BAD vorbis decode in decodeSection." << LL_ENDL; mValid = FALSE; mDone = TRUE; @@ -434,7 +435,7 @@ BOOL LLVorbisDecodeState::finishDecode() { if (!isValid()) { - LL_WARNS() << "Bogus vorbis decode state for " << getUUID() << ", aborting!" << LL_ENDL; + LL_WARNS("AudioEngine") << "Bogus vorbis decode state for " << getUUID() << ", aborting!" << LL_ENDL; return TRUE; // We've finished } @@ -515,7 +516,7 @@ BOOL LLVorbisDecodeState::finishDecode() if (36 == data_length) { - LL_WARNS() << "BAD Vorbis decode in finishDecode!" << LL_ENDL; + LL_WARNS("AudioEngine") << "BAD Vorbis decode in finishDecode!" << LL_ENDL; mValid = FALSE; return TRUE; // we've finished } @@ -532,7 +533,7 @@ BOOL LLVorbisDecodeState::finishDecode() { if (mBytesRead == 0) { - LL_WARNS() << "Unable to write file in LLVorbisDecodeState::finishDecode" << LL_ENDL; + LL_WARNS("AudioEngine") << "Unable to write file in LLVorbisDecodeState::finishDecode" << LL_ENDL; mValid = FALSE; return TRUE; // we've finished } @@ -550,7 +551,7 @@ BOOL LLVorbisDecodeState::finishDecode() LLVFile output(gVFS, mUUID, LLAssetType::AT_SOUND_WAV); output.write(&mWAVBuffer[0], mWAVBuffer.size()); #endif - //LL_INFOS() << "Finished decode for " << getUUID() << LL_ENDL; + LL_DEBUGS("AudioEngine") << "Finished decode for " << getUUID() << LL_ENDL; return TRUE; } @@ -559,7 +560,7 @@ void LLVorbisDecodeState::flushBadFile() { if (mInFilep) { - LL_WARNS() << "Flushing bad vorbis file from VFS for " << mUUID << LL_ENDL; + LL_WARNS("AudioEngine") << "Flushing bad vorbis file from VFS for " << mUUID << LL_ENDL; mInFilep->remove(); } } @@ -576,7 +577,7 @@ class LLAudioDecodeMgr::Impl void processQueue(const F32 num_secs = 0.005); protected: - LLLinkedQueue mDecodeQueue; + std::deque mDecodeQueue; LLPointer mCurrentDecodep; }; @@ -608,12 +609,16 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) if (mCurrentDecodep->isDone() && !mCurrentDecodep->isValid()) { // We had an error when decoding, abort. - LL_WARNS() << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << LL_ENDL; + LL_WARNS("AudioEngine") << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << LL_ENDL; mCurrentDecodep->flushBadFile(); - LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID()); - if(adp) + + if (gAudiop) { - adp->setLoadState(LLAudioData::STATE_LOAD_ERROR); + LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID()); + if(adp) + { + adp->setLoadState(LLAudioData::STATE_LOAD_ERROR); + } } mCurrentDecodep = NULL; done = TRUE; @@ -626,13 +631,13 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) } else if (mCurrentDecodep) { - if (mCurrentDecodep->finishDecode()) + if (gAudiop && mCurrentDecodep->finishDecode()) { // We finished! LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID()); if (!adp) { - LL_WARNS() << "Missing LLAudioData for decode of " << mCurrentDecodep->getUUID() << LL_ENDL; + LL_WARNS("AudioEngine") << "Missing LLAudioData for decode of " << mCurrentDecodep->getUUID() << LL_ENDL; } else if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone()) { @@ -645,7 +650,7 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) else { adp->setLoadState(LLAudioData::STATE_LOAD_ERROR); - LL_INFOS() << "Vorbis decode failed for " << mCurrentDecodep->getUUID() << LL_ENDL; + LL_INFOS("AudioEngine") << "Vorbis decode failed for " << mCurrentDecodep->getUUID() << LL_ENDL; } mCurrentDecodep = NULL; } @@ -655,7 +660,7 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) if (!done) { - if (!mDecodeQueue.getLength()) + if (mDecodeQueue.empty()) { // Nothing else on the queue. done = TRUE; @@ -663,8 +668,9 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) else { LLUUID uuid; - mDecodeQueue.pop(uuid); - if (gAudiop->hasDecodedFile(uuid)) + uuid = mDecodeQueue.front(); + mDecodeQueue.pop_front(); + if (!gAudiop || gAudiop->hasDecodedFile(uuid)) { // This file has already been decoded, don't decode it again. continue; @@ -715,11 +721,26 @@ void LLAudioDecodeMgr::processQueue(const F32 num_secs) bool LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid) { - if(!uuid.notNull()) - return false; - else if (!gAssetStorage || !gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND)) - return false; - - mImpl->mDecodeQueue.push(uuid); - return true; + if(uuid.isNull()) + { + return true; + } + + if (gAudiop && gAudiop->hasDecodedFile(uuid)) + { + // Already have a decoded version, don't need to decode it. + LL_DEBUGS("AudioEngine") << "addDecodeRequest for " << uuid << " has decoded file already" << LL_ENDL; + return true; + } + + if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND)) + { + // Just put it on the decode queue. + LL_DEBUGS("AudioEngine") << "addDecodeRequest for " << uuid << " has local asset file already" << LL_ENDL; + mImpl->mDecodeQueue.push_back(uuid); + return true; + } + + LL_DEBUGS("AudioEngine") << "addDecodeRequest for " << uuid << " no file available" << LL_ENDL; + return false; } diff --git a/indra/llaudio/llaudiodecodemgr.h b/indra/llaudio/llaudiodecodemgr.h index 3ff894dba2..e2319a32fa 100644 --- a/indra/llaudio/llaudiodecodemgr.h +++ b/indra/llaudio/llaudiodecodemgr.h @@ -28,7 +28,6 @@ #include "stdtypes.h" -#include "lllinkedqueue.h" #include "lluuid.h" #include "llassettype.h" diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 99e151f126..61aa25be1e 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -1046,8 +1046,12 @@ void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp) LL_WARNS("AudioEngine") << "Cleaning up unknown audio source!" << LL_ENDL; return; } - delete asp; - mAllSources.erase(iter); + else + { + LL_DEBUGS("AudioEngine") << "Cleaning up audio sources for "<< asp->getID() < -#pragma comment(lib, "delayimp.lib") - -bool attemptDelayLoad() -{ - __try - { -#if defined(_WIN64) - if( FAILED( __HrLoadAllImportsForDll( "fmodex64.dll" ) ) ) - return false; -#else - if( FAILED( __HrLoadAllImportsForDll( "fmodex.dll" ) ) ) - return false; -#endif - } - __except( EXCEPTION_EXECUTE_HANDLER ) - { - return false; - } - return true; -} -#endif - -static bool sVerboseDebugging = false; - -FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels); - -FMOD::ChannelGroup *LLAudioEngine_FMODEX::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0}; - -//This class is designed to keep track of all sound<->channel assocations. -//Used to verify validity of sound and channel pointers, as well as catch cases were sounds -//are released with active channels still attached. -class CFMODSoundChecks -{ - typedef std::map > active_sounds_t; - typedef std::set dead_sounds_t; - typedef std::map active_channels_t; - typedef std::map dead_channels_t; - - active_sounds_t mActiveSounds; - dead_sounds_t mDeadSounds; - active_channels_t mActiveChannels; - dead_channels_t mDeadChannels; -public: - enum STATUS - { - ACTIVE, - DEAD, - UNKNOWN - }; - STATUS getPtrStatus(LLAudioChannel* channel) - { - if(!channel) - return UNKNOWN; - return getPtrStatus(dynamic_cast(channel)->mChannelp); - } - STATUS getPtrStatus(LLAudioBuffer* sound) - { - if(!sound) - return UNKNOWN; - return getPtrStatus(dynamic_cast(sound)->mSoundp); - } - STATUS getPtrStatus(FMOD::Channel* channel) - { - if(!channel) - return UNKNOWN; - else if(mActiveChannels.find(channel) != mActiveChannels.end()) - return ACTIVE; - else if(mDeadChannels.find(channel) != mDeadChannels.end()) - return DEAD; - return UNKNOWN; - } - STATUS getPtrStatus(FMOD::Sound* sound) - { - if(!sound) - return UNKNOWN; - if(mActiveSounds.find(sound) != mActiveSounds.end()) - return ACTIVE; - else if(mDeadSounds.find(sound) != mDeadSounds.end()) - return DEAD; - return UNKNOWN; - } - void addNewSound(FMOD::Sound* sound) - { - assertActiveState(sound,true,false); - - mDeadSounds.erase(sound); - mActiveSounds.insert(std::make_pair(sound,std::set())); - } - void removeSound(FMOD::Sound* sound) - { - assertActiveState(sound,true); - - active_sounds_t::const_iterator it = mActiveSounds.find(sound); - llassert(it != mActiveSounds.end()); - if(it != mActiveSounds.end()) - { - if(!it->second.empty()) - { - LL_WARNS("AudioImpl") << "Removing sound " << sound << " with attached channels: \n"; - for(std::set::iterator it2 = it->second.begin(); it2 != it->second.end();++it2) - { - switch(getPtrStatus(*it2)) - { - case ACTIVE: - LL_CONT << " Channel " << *it2 << " ACTIVE\n"; - break; - case DEAD: - LL_CONT << " Channel " << *it2 << " DEAD\n"; - break; - default: - LL_CONT << " Channel " << *it2 << " UNKNOWN\n"; - } - } - LL_CONT << LL_ENDL; - } - llassert(it->second.empty()); - mDeadSounds.insert(sound); - mActiveSounds.erase(sound); - } - } - void addNewChannelToSound(FMOD::Sound* sound,FMOD::Channel* channel) - { - assertActiveState(sound,true); - assertActiveState(channel,true,false); - - mActiveSounds[sound].insert(channel); - mActiveChannels.insert(std::make_pair(channel,sound)); - } - void removeChannel(FMOD::Channel* channel) - { - assertActiveState(channel,true); - - active_channels_t::const_iterator it = mActiveChannels.find(channel); - llassert(it != mActiveChannels.end()); - if(it != mActiveChannels.end()) - { -#ifdef SHOW_ASSERT - STATUS status = getPtrStatus(it->second); - llassert(status != DEAD); - llassert(status != UNKNOWN); -#endif - - active_sounds_t::iterator it2 = mActiveSounds.find(it->second); - llassert(it2 != mActiveSounds.end()); - if(it2 != mActiveSounds.end()) - { - it2->second.erase(channel); - } - mDeadChannels.insert(*it); - mActiveChannels.erase(channel); - } - } - - template - void assertActiveState(T ptr, bool try_log=false, bool active=true) - { -#ifndef SHOW_ASSERT - if(try_log && sVerboseDebugging) -#endif - { - CFMODSoundChecks::STATUS chan = getPtrStatus(ptr); - if(try_log && sVerboseDebugging) - { - if(active) - { - if(chan == CFMODSoundChecks::DEAD) - LL_WARNS("AudioImpl") << __FUNCTION__ << ": Using unexpectedly dead " << typeid(T*).name() << " " << ptr << LL_ENDL; - else if(chan == CFMODSoundChecks::UNKNOWN) - LL_WARNS("AudioImpl") << __FUNCTION__ << ": Using unexpectedly unknown " << typeid(T*).name() << " " << ptr << LL_ENDL; - } - else if(chan == CFMODSoundChecks::ACTIVE) - LL_WARNS("AudioImpl") << __FUNCTION__ << ": Using unexpectedly active " << typeid(T*).name() << " " << ptr << LL_ENDL; - } - llassert( active == (chan == CFMODSoundChecks::ACTIVE) ); - } - } -} gSoundCheck; - -LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler, bool verbose_debugging) -{ - sVerboseDebugging = verbose_debugging; - mInited = false; - mWindGen = NULL; - mWindDSP = NULL; - mSystem = NULL; - mEnableProfiler = enable_profiler; -} - - -LLAudioEngine_FMODEX::~LLAudioEngine_FMODEX() -{ -} - - -inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) -{ - if(result == FMOD_OK) - return false; - LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; - return true; -} - -void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) -{ - if(type & FMOD_MEMORY_STREAM_DECODE) - { - LL_INFOS("AudioImpl") << "Decode buffer size: " << size << LL_ENDL; - } - else if(type & FMOD_MEMORY_STREAM_FILE) - { - LL_INFOS("AudioImpl") << "Stream buffer size: " << size << LL_ENDL; - } - return new char[size]; -} -void* F_STDCALL decode_realloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) -{ - memset(ptr,0,size); - return ptr; -} -void F_STDCALL decode_dealloc(void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr) -{ - delete[] (char*)ptr; -} - -bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) -{ - -#if LL_WINDOWS - if(!attemptDelayLoad()) - return false; -#endif - - U32 version = 0; - FMOD_RESULT result; - - LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL; - - //result = FMOD::Memory_Initialize(NULL, 0, &decode_alloc, &decode_realloc, &decode_dealloc, FMOD_MEMORY_STREAM_DECODE | FMOD_MEMORY_STREAM_FILE); - //if(Check_FMOD_Error(result, "FMOD::Memory_Initialize")) - // return false; - - result = FMOD::System_Create(&mSystem); - if(Check_FMOD_Error(result, "FMOD::System_Create")) - return false; - - //will call LLAudioEngine_FMODEX::allocateListener, which needs a valid mSystem pointer. - LLAudioEngine::init(num_channels, userdata); - - result = mSystem->getVersion(&version); - Check_FMOD_Error(result, "FMOD::System::getVersion"); - - if (version < FMOD_VERSION) - { - LL_WARNS("AppInit") << "Error : You are using the wrong FMOD Ex version (" << version - << ")! You should be using FMOD Ex" << FMOD_VERSION << LL_ENDL; - } - -// result = mSystem->setSoftwareFormat(44100, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR); -// Check_FMOD_Error(result,"FMOD::System::setSoftwareFormat"); - - // In this case, all sounds, PLUS wind and stream will be software. - result = mSystem->setSoftwareChannels(num_channels + 2); - Check_FMOD_Error(result,"FMOD::System::setSoftwareChannels"); - - U32 fmod_flags = FMOD_INIT_NORMAL; - if(mEnableProfiler) - { - fmod_flags |= FMOD_INIT_ENABLE_PROFILE; - } - -#if LL_LINUX - bool audio_ok = false; - - if (!audio_ok) - { - if (NULL == getenv("LL_BAD_FMOD_PULSEAUDIO")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL; - if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO)) == FMOD_OK && - (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) - { - LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } - else - { - Check_FMOD_Error(result, "PulseAudio audio output FAILED to initialize"); - } - } - else - { - LL_DEBUGS("AppInit") << "PulseAudio audio output SKIPPED" << LL_ENDL; - } - } - if (!audio_ok) - { - if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; - if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA)) == FMOD_OK && - (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) - { - LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } - else - { - Check_FMOD_Error(result, "ALSA audio output FAILED to initialize"); - } - } - else - { - LL_DEBUGS("AppInit") << "ALSA audio output SKIPPED" << LL_ENDL; - } - } - if (!audio_ok) - { - if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL; - if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_OSS)) == FMOD_OK && - (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) - { - LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } - else - { - Check_FMOD_Error(result, "OSS audio output FAILED to initialize"); - } - } - else - { - LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; - } - } - if (!audio_ok) - { - LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; - return false; - } - - // We're interested in logging which output method we - // ended up with, for QA purposes. - FMOD_OUTPUTTYPE output_type; - if(!Check_FMOD_Error(mSystem->getOutput(&output_type), "FMOD::System::getOutput")) - { - switch (output_type) - { - case FMOD_OUTPUTTYPE_NOSOUND: - LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; - case FMOD_OUTPUTTYPE_PULSEAUDIO: - LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break; - case FMOD_OUTPUTTYPE_ALSA: - LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; - case FMOD_OUTPUTTYPE_OSS: - LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break; - default: - LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; - }; - } -#else // LL_LINUX - - // initialize the FMOD engine - result = mSystem->init( num_channels + 2, fmod_flags, 0); - if (result == FMOD_ERR_OUTPUT_CREATEBUFFER) - { - /* - Ok, the speaker mode selected isn't supported by this soundcard. Switch it - back to stereo... - */ - result = mSystem->setSpeakerMode(FMOD_SPEAKERMODE_STEREO); - Check_FMOD_Error(result,"Error falling back to stereo mode"); - /* - ... and re-init. - */ - result = mSystem->init( num_channels + 2, fmod_flags, 0); - } - if(Check_FMOD_Error(result, "Error initializing FMOD Ex")) - return false; -#endif - - if (mEnableProfiler) - { - Check_FMOD_Error(mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]), "FMOD::System::createChannelGroup"); - Check_FMOD_Error(mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]), "FMOD::System::createChannelGroup"); - Check_FMOD_Error(mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]), "FMOD::System::createChannelGroup"); - Check_FMOD_Error(mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]), "FMOD::System::createChannelGroup"); - } - - // set up our favourite FMOD-native streaming audio implementation if none has already been added - if (!getStreamingAudioImpl()) // no existing implementation added - setStreamingAudioImpl(new LLStreamingAudio_FMODEX(mSystem)); - - LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init() FMOD Ex initialized correctly" << LL_ENDL; - - int r_numbuffers, r_samplerate, r_channels, r_bits; - unsigned int r_bufferlength; - char r_name[256]; - FMOD_SPEAKERMODE speaker_mode; - if (!Check_FMOD_Error(mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers), "FMOD::System::getDSPBufferSize") && - !Check_FMOD_Error(mSystem->getSoftwareFormat(&r_samplerate, NULL, &r_channels, NULL, NULL, &r_bits), "FMOD::System::getSoftwareFormat") && - !Check_FMOD_Error(mSystem->getDriverInfo(0, r_name, 255, 0), "FMOD::System::getDriverInfo") && - !Check_FMOD_Error(mSystem->getSpeakerMode(&speaker_mode), "FMOD::System::getSpeakerMode")) - { - std::string speaker_mode_str = "unknown"; - switch(speaker_mode) - { - #define SPEAKER_MODE_CASE(MODE) case MODE: speaker_mode_str = #MODE; break; - SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_RAW) - SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_MONO) - SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_STEREO) - SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_QUAD) - SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_SURROUND) - SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_5POINT1) - SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_7POINT1) - SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_SRS5_1_MATRIX) - SPEAKER_MODE_CASE(FMOD_SPEAKERMODE_MYEARS) - default:; - #undef SPEAKER_MODE_CASE - } - - r_name[255] = '\0'; - int latency = 1000.0 * r_bufferlength * r_numbuffers /r_samplerate; - - LL_INFOS("AppInit") << "FMOD device: "<< r_name << "\n" - << "Output mode: "<< speaker_mode_str << "\n" - << "FMOD Ex parameters: " << r_samplerate << " Hz * " << r_channels << " * " <getVersion(&version), "FMOD::System::getVersion")) - { - return llformat("FMOD Ex %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); - } - } - return "FMODEx"; -} - - -void LLAudioEngine_FMODEX::allocateListener(void) -{ - mListenerp = (LLListener *) new LLListener_FMODEX(mSystem); - if (!mListenerp) - { - LL_WARNS("AudioImpl") << "Listener creation failed" << LL_ENDL; - } -} - - -void LLAudioEngine_FMODEX::shutdown() -{ - LL_INFOS("AudioImpl") << "About to LLAudioEngine::shutdown()" << LL_ENDL; - LLAudioEngine::shutdown(); - - LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << LL_ENDL; - if ( mSystem ) // speculative fix for MAINT-2657 - { - LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() Requesting FMOD Ex system closure" << LL_ENDL; - Check_FMOD_Error(mSystem->close(), "FMOD::System::close"); - LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() Requesting FMOD Ex system release" << LL_ENDL; - Check_FMOD_Error(mSystem->release(), "FMOD::System::release"); - } - LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << LL_ENDL; - - delete mListenerp; - mListenerp = NULL; -} - - -LLAudioBuffer * LLAudioEngine_FMODEX::createBuffer() -{ - return new LLAudioBufferFMODEX(mSystem); -} - - -LLAudioChannel * LLAudioEngine_FMODEX::createChannel() -{ - return new LLAudioChannelFMODEX(mSystem); -} - -bool LLAudioEngine_FMODEX::initWind() -{ - mNextWindUpdate = 0.0; - - cleanupWind(); - - - FMOD_DSP_DESCRIPTION dspdesc; - memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Set everything to zero - strncpy(dspdesc.name,"Wind Unit", sizeof(dspdesc.name)); //Set name to "Wind Unit" - dspdesc.channels=2; - dspdesc.read = &windCallback; //Assign callback. - if(Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP") || !mWindDSP) - return false; - - float frequency = 44100; - if (!Check_FMOD_Error(mWindDSP->getDefaults(&frequency,0,0,0), "FMOD::DSP::getDefaults")) - { - mWindGen = new LLWindGen((U32)frequency); - if (!Check_FMOD_Error(mWindDSP->setUserData((void*)mWindGen), "FMOD::DSP::setUserData") && - !Check_FMOD_Error(mSystem->playDSP(FMOD_CHANNEL_FREE, mWindDSP, false, 0), "FMOD::System::playDSP")) - return true; //Success - } - - cleanupWind(); - return false; -} - - -void LLAudioEngine_FMODEX::cleanupWind() -{ - if (mWindDSP) - { - Check_FMOD_Error(mWindDSP->remove(), "FMOD::DSP::remove"); - Check_FMOD_Error(mWindDSP->release(), "FMOD::DSP::release"); - mWindDSP = NULL; - } - - delete mWindGen; - mWindGen = NULL; -} - - -//----------------------------------------------------------------------- -void LLAudioEngine_FMODEX::updateWind(LLVector3 wind_vec, F32 camera_height_above_water) -{ - LLVector3 wind_pos; - F64 pitch; - F64 center_freq; - - if (!mEnableWind) - { - return; - } - - if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) - { - - // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) - // need to convert this to the conventional orientation DS3D and OpenAL use - // where +X = right, +Y = up, +Z = backwards - - wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); - - // cerr << "Wind update" << endl; - - pitch = 1.0 + mapWindVecToPitch(wind_vec); - center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); - - mWindGen->mTargetFreq = (F32)center_freq; - mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; - mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); - } -} - -//----------------------------------------------------------------------- -void LLAudioEngine_FMODEX::setInternalGain(F32 gain) -{ - if (!mInited) - { - return; - } - - gain = llclamp( gain, 0.0f, 1.0f ); - - FMOD::ChannelGroup *master_group; - if(Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup")) - return; - master_group->setVolume(gain); - - LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); - if ( saimpl ) - { - // fmod likes its streaming audio channel gain re-asserted after - // master volume change. - saimpl->setGain(saimpl->getGain()); - } -} - -// -// LLAudioChannelFMODEX implementation -// - -LLAudioChannelFMODEX::LLAudioChannelFMODEX(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(NULL), mLastSamplePos(0) -{ -} - - -LLAudioChannelFMODEX::~LLAudioChannelFMODEX() -{ - if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Destructing Audio Channel. mChannelp = " << mChannelp << LL_ENDL; - - cleanup(); -} - -static FMOD_RESULT F_CALLBACK channel_callback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, void *commanddata1, void *commanddata2) -{ - if(type == FMOD_CHANNEL_CALLBACKTYPE_END) - { - FMOD::Channel* chan = reinterpret_cast(channel); - LLAudioChannelFMODEX* audio_channel = NULL; - chan->getUserData((void**)&audio_channel); - if(audio_channel) - { - audio_channel->onRelease(); - } - } - return FMOD_OK; -} - -void LLAudioChannelFMODEX::onRelease() -{ - llassert(mChannelp); - if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Fmod signaled channel release for channel " << mChannelp << LL_ENDL; - gSoundCheck.removeChannel(mChannelp); - mChannelp = NULL; //Null out channel here so cleanup doesn't try to redundantly stop it. - cleanup(); -} - -bool LLAudioChannelFMODEX::updateBuffer() -{ - if (LLAudioChannel::updateBuffer()) - { - // Base class update returned true, which means the channel buffer was changed, and not is null. - - // Grab the FMOD sample associated with the buffer - FMOD::Sound *soundp = ((LLAudioBufferFMODEX*)mCurrentBufferp)->getSound(); - if (!soundp) - { - // This is bad, there should ALWAYS be a sound associated with a legit - // buffer. - LL_ERRS("AudioImpl") << "No FMOD sound!" << LL_ENDL; - return false; - } - - // Actually play the sound. Start it off paused so we can do all the necessary - // setup. - if(!mChannelp) - { - FMOD_RESULT result = getSystem()->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp); - Check_FMOD_Error(result, "FMOD::System::playSound"); - if(result == FMOD_OK) - { - if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Created channel " << mChannelp << " for sound " << soundp << LL_ENDL; - - gSoundCheck.addNewChannelToSound(soundp,mChannelp); - mChannelp->setCallback(&channel_callback); - mChannelp->setUserData(this); - } - } - } - - // If we have a source for the channel, we need to update its gain. - if (mCurrentSourcep && mChannelp) - { - FMOD_RESULT result; - - gSoundCheck.assertActiveState(this); - result = mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain()); - Check_FMOD_Error(result, "FMOD::Channel::setVolume"); - result = mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); - Check_FMOD_Error(result, "FMOD::Channel::setMode"); - } - - return true; -} - - -void LLAudioChannelFMODEX::update3DPosition() -{ - if (!mChannelp) - { - // We're not actually a live channel (i.e., we're not playing back anything) - return; - } - - LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentBufferp; - if (!bufferp) - { - // We don't have a buffer associated with us (should really have been picked up - // by the above if. - return; - } - - gSoundCheck.assertActiveState(this); - - if (mCurrentSourcep->isAmbient()) - { - // Ambient sound, don't need to do any positional updates. - set3DMode(false); - } - else - { - // Localized sound. Update the position and velocity of the sound. - set3DMode(true); - - LLVector3 float_pos; - float_pos.setVec(mCurrentSourcep->getPositionGlobal()); - FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV); - Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes"); - } -} - - -void LLAudioChannelFMODEX::updateLoop() -{ - if (!mChannelp) - { - // May want to clear up the loop/sample counters. - return; - } - - gSoundCheck.assertActiveState(this); - - // - // Hack: We keep track of whether we looped or not by seeing when the - // sample position looks like it's going backwards. Not reliable; may - // yield false negatives. - // - U32 cur_pos; - Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES),"FMOD::Channel::getPosition"); - - if (cur_pos < (U32)mLastSamplePos) - { - mLoopedThisFrame = true; - } - mLastSamplePos = cur_pos; -} - - -void LLAudioChannelFMODEX::cleanup() -{ - LLAudioChannel::cleanup(); - - if (!mChannelp) - { - llassert(mCurrentBufferp == NULL); - //LL_INFOS("AudioImpl") << "Aborting cleanup with no channel handle." << LL_ENDL; - return; - } - - if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Stopping channel " << mChannelp << LL_ENDL; - - gSoundCheck.removeChannel(mChannelp); - mChannelp->setCallback(NULL); - Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop"); - - mChannelp = NULL; - mLastSamplePos = 0; -} - - -void LLAudioChannelFMODEX::play() -{ - if (!mChannelp) - { - LL_WARNS("AudioImpl") << "Playing without a channel handle, aborting" << LL_ENDL; - return; - } - - gSoundCheck.assertActiveState(this,true); - - bool paused=true; - Check_FMOD_Error(mChannelp->getPaused(&paused), "FMOD::Channel::getPaused"); - if(!paused) - { - Check_FMOD_Error(mChannelp->setPaused(true), "FMOD::Channel::setPaused"); - Check_FMOD_Error(mChannelp->setPosition(0,FMOD_TIMEUNIT_PCMBYTES), "FMOD::Channel::setPosition"); - } - Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::setPaused"); - - if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Playing channel " << mChannelp << LL_ENDL; - - getSource()->setPlayedOnce(true); - - if(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]) - Check_FMOD_Error(mChannelp->setChannelGroup(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]),"FMOD::Channel::setChannelGroup"); -} - - -void LLAudioChannelFMODEX::playSynced(LLAudioChannel *channelp) -{ - LLAudioChannelFMODEX *fmod_channelp = (LLAudioChannelFMODEX*)channelp; - if (!(fmod_channelp->mChannelp && mChannelp)) - { - // Don't have channels allocated to both the master and the slave - return; - } - - gSoundCheck.assertActiveState(this,true); - - U32 cur_pos; - if(Check_FMOD_Error(fmod_channelp->mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position")) - return; - - cur_pos %= mCurrentBufferp->getLength(); - - // Try to match the position of our sync master - Check_FMOD_Error(mChannelp->setPosition(cur_pos,FMOD_TIMEUNIT_PCMBYTES),"Unable to set current position"); - - // Start us playing - play(); -} - - -bool LLAudioChannelFMODEX::isPlaying() -{ - if (!mChannelp) - { - return false; - } - - gSoundCheck.assertActiveState(this); - - bool paused, playing; - Check_FMOD_Error(mChannelp->getPaused(&paused),"FMOD::Channel::getPaused"); - Check_FMOD_Error(mChannelp->isPlaying(&playing),"FMOD::Channel::isPlaying"); - return !paused && playing; -} - - -// -// LLAudioChannelFMODEX implementation -// - - -LLAudioBufferFMODEX::LLAudioBufferFMODEX(FMOD::System *system) : LLAudioBuffer(), mSystemp(system), mSoundp(NULL) -{ -} - - -LLAudioBufferFMODEX::~LLAudioBufferFMODEX() -{ - if(mSoundp) - { - if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Release sound " << mSoundp << LL_ENDL; - - gSoundCheck.removeSound(mSoundp); - Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::Release"); - mSoundp = NULL; - } -} - - -bool LLAudioBufferFMODEX::loadWAV(const std::string& filename) -{ - // Try to open a wav file from disk. This will eventually go away, as we don't - // really want to block doing this. - if (filename.empty()) - { - // invalid filename, abort. - return false; - } - - if (!LLAPRFile::isExist(filename, LL_APR_RPB)) - { - // File not found, abort. - return false; - } - - if (mSoundp) - { - gSoundCheck.removeSound(mSoundp); - // If there's already something loaded in this buffer, clean it up. - Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::release"); - mSoundp = NULL; - } - - FMOD_MODE base_mode = FMOD_LOOP_NORMAL | FMOD_SOFTWARE; - FMOD_CREATESOUNDEXINFO exinfo; - memset(&exinfo,0,sizeof(exinfo)); - exinfo.cbsize = sizeof(exinfo); - exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; //Hint to speed up loading. - // Load up the wav file into an fmod sample -#if LL_WINDOWS - FMOD_RESULT result = getSystem()->createSound((const char*)utf8str_to_utf16str(filename).c_str(), base_mode | FMOD_UNICODE, &exinfo, &mSoundp); -#else - FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp); -#endif - - if (result != FMOD_OK) - { - // We failed to load the file for some reason. - LL_WARNS("AudioImpl") << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << LL_ENDL; - - // - // If we EVER want to load wav files provided by end users, we need - // to rethink this! - // - // file is probably corrupt - remove it. - LLFile::remove(filename); - return false; - } - - gSoundCheck.addNewSound(mSoundp); - - // Everything went well, return true - return true; -} - - -U32 LLAudioBufferFMODEX::getLength() -{ - if (!mSoundp) - { - return 0; - } - - gSoundCheck.assertActiveState(this); - U32 length; - Check_FMOD_Error(mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES),"FMOD::Sound::getLength"); - return length; -} - - -void LLAudioChannelFMODEX::set3DMode(bool use3d) -{ - gSoundCheck.assertActiveState(this); - - FMOD_MODE current_mode; - if(Check_FMOD_Error(mChannelp->getMode(¤t_mode),"FMOD::Channel::getMode")) - return; - FMOD_MODE new_mode = current_mode; - new_mode &= ~(use3d ? FMOD_2D : FMOD_3D); - new_mode |= use3d ? FMOD_3D : FMOD_2D; - - if(current_mode != new_mode) - { - Check_FMOD_Error(mChannelp->setMode(new_mode),"FMOD::Channel::setMode"); - } -} - - -FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *originalbuffer, float *newbuffer, unsigned int length, int inchannels, int outchannels) -{ - // originalbuffer = fmod's original mixbuffer. - // newbuffer = the buffer passed from the previous DSP unit. - // length = length in samples at this mix time. - // userdata = user parameter passed through in FSOUND_DSP_Create. - - LLWindGen *windgen; - FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance; - - thisdsp->getUserData((void **)&windgen); - - if (windgen) - windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length); - - return FMOD_OK; -} diff --git a/indra/llaudio/llaudioengine_fmodex.h b/indra/llaudio/llaudioengine_fmodex.h deleted file mode 100644 index fe93d8c487..0000000000 --- a/indra/llaudio/llaudioengine_fmodex.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @file audioengine_FMODEX.h - * @brief Definition of LLAudioEngine class abstracting the audio - * support as a FMOD 3D implementation - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_AUDIOENGINE_FMODEX_H -#define LL_AUDIOENGINE_FMODEX_H - -#include "llaudioengine.h" -#include "lllistener_fmodex.h" -#include "llwindgen.h" - -//Stubs -class LLAudioStreamManagerFMODEX; -namespace FMOD -{ - class System; - class Channel; - class ChannelGroup; - class Sound; - class DSP; -} - -//Interfaces -class LLAudioEngine_FMODEX : public LLAudioEngine -{ -public: - LLAudioEngine_FMODEX(bool enable_profiler, bool verbose_debugging); - virtual ~LLAudioEngine_FMODEX(); - - // initialization/startup/shutdown - virtual bool init(const S32 num_channels, void *user_data); - virtual std::string getDriverName(bool verbose); - virtual void allocateListener(); - - virtual void shutdown(); - - /*virtual*/ bool initWind(); - /*virtual*/ void cleanupWind(); - - /*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water); - - typedef F32 MIXBUFFERFORMAT; - - FMOD::System *getSystem() const {return mSystem;} -protected: - /*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to. - /*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel. - - /*virtual*/ void setInternalGain(F32 gain); - - bool mInited; - - LLWindGen *mWindGen; - - FMOD::DSP *mWindDSP; - FMOD::System *mSystem; - bool mEnableProfiler; - -public: - static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT]; -}; - - -class LLAudioChannelFMODEX : public LLAudioChannel -{ -public: - LLAudioChannelFMODEX(FMOD::System *audioengine); - virtual ~LLAudioChannelFMODEX(); - void onRelease(); -protected: - /*virtual*/ void play(); - /*virtual*/ void playSynced(LLAudioChannel *channelp); - /*virtual*/ void cleanup(); - /*virtual*/ bool isPlaying(); - - /*virtual*/ bool updateBuffer(); - /*virtual*/ void update3DPosition(); - /*virtual*/ void updateLoop(); - - void set3DMode(bool use3d); -protected: - FMOD::System *getSystem() const {return mSystemp;} - FMOD::System *mSystemp; - FMOD::Channel *mChannelp; - S32 mLastSamplePos; - - friend class CFMODSoundChecks; -}; - - -class LLAudioBufferFMODEX : public LLAudioBuffer -{ -public: - LLAudioBufferFMODEX(FMOD::System *audioengine); - virtual ~LLAudioBufferFMODEX(); - - /*virtual*/ bool loadWAV(const std::string& filename); - /*virtual*/ U32 getLength(); - friend class LLAudioChannelFMODEX; -protected: - FMOD::System *getSystem() const {return mSystemp;} - FMOD::System *mSystemp; - FMOD::Sound *getSound() const{ return mSoundp; } - FMOD::Sound *mSoundp; - - friend class CFMODSoundChecks; -}; - - -#endif // LL_AUDIOENGINE_FMODEX_H diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp index 93541d3de8..823f51cbf2 100644 --- a/indra/llaudio/llaudioengine_fmodstudio.cpp +++ b/indra/llaudio/llaudioengine_fmodstudio.cpp @@ -1,5 +1,5 @@ /** - * @file audioengine_FMODSTUDIO.cpp + * @file audioengine_fmodstudio.cpp * @brief Implementation of LLAudioEngine class abstracting the audio support as a FMOD 3D implementation * * $LicenseInfo:firstyear=2002&license=viewergpl$ @@ -45,7 +45,6 @@ #include "fmod.hpp" #include "fmod_errors.h" #include "lldir.h" -#include "llapr.h" #include "sound_ids.h" @@ -79,7 +78,7 @@ bool attemptDelayLoad() static bool sVerboseDebugging = false; -FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels); +FMOD_RESULT F_CALLBACK windDSPCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels); FMOD::ChannelGroup *LLAudioEngine_FMODSTUDIO::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0}; @@ -234,21 +233,20 @@ class CFMODSoundChecks } gSoundCheck; LLAudioEngine_FMODSTUDIO::LLAudioEngine_FMODSTUDIO(bool enable_profiler, bool verbose_debugging) + : mInited(false) + , mWindGen(NULL) + , mWindDSPDesc(NULL) + , mWindDSP(NULL) + , mSystem(NULL) + , mEnableProfiler(enable_profiler) { sVerboseDebugging = verbose_debugging; - mInited = false; - mWindGen = NULL; - mWindDSP = NULL; - mSystem = NULL; - mEnableProfiler = enable_profiler; } - LLAudioEngine_FMODSTUDIO::~LLAudioEngine_FMODSTUDIO() { } - inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) { if(result == FMOD_OK) @@ -257,45 +255,20 @@ inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) return true; } -void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) -{ - if(type & FMOD_MEMORY_STREAM_DECODE) - { - LL_INFOS("AudioImpl") << "Decode buffer size: " << size << LL_ENDL; - } - else if(type & FMOD_MEMORY_STREAM_FILE) - { - LL_INFOS("AudioImpl") << "Stream buffer size: " << size << LL_ENDL; - } - return new char[size]; -} -void* F_STDCALL decode_realloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) -{ - memset(ptr,0,size); - return ptr; -} -void F_STDCALL decode_dealloc(void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr) -{ - delete[] (char*)ptr; -} - bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata) { - -#if LL_WINDOWS + LL_WARNS("AudioImpl") << "BARKBARKBARK" << LL_ENDL; +#if 0 //LL_WINDOWS if(!attemptDelayLoad()) return false; #endif U32 version = 0; + FMOD_RESULT result; LL_DEBUGS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() initializing FMOD" << LL_ENDL; - //result = FMOD::Memory_Initialize(NULL, 0, &decode_alloc, &decode_realloc, &decode_dealloc, FMOD_MEMORY_STREAM_DECODE | FMOD_MEMORY_STREAM_FILE); - //if(Check_FMOD_Error(result, "FMOD::Memory_Initialize")) - // return false; - result = FMOD::System_Create(&mSystem); if(Check_FMOD_Error(result, "FMOD::System_Create")) return false; @@ -477,7 +450,7 @@ std::string LLAudioEngine_FMODSTUDIO::getDriverName(bool verbose) return llformat("FMOD Studio %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); } } - return "FMODEx"; + return "FMOD Studio"; } @@ -528,24 +501,25 @@ bool LLAudioEngine_FMODSTUDIO::initWind() cleanupWind(); - FMOD_DSP_DESCRIPTION dspdesc; - memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Set everything to zero - dspdesc.pluginsdkversion = FMOD_PLUGIN_SDK_VERSION; - strncpy(dspdesc.name,"Wind Unit", sizeof(dspdesc.name)); //Set name to "Wind Unit" - dspdesc.numoutputbuffers = 1; - dspdesc.read = &windCallback; //Assign callback. - if (Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP") || !mWindDSP) + mWindDSPDesc = new FMOD_DSP_DESCRIPTION(); + memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc)); //Set everything to zero + mWindDSPDesc->pluginsdkversion = FMOD_PLUGIN_SDK_VERSION; + strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name)); //Set name to "Wind Unit" + mWindDSPDesc->numoutputbuffers = 1; + mWindDSPDesc->read = &windDSPCallback; //Assign callback. + if (Check_FMOD_Error(mSystem->createDSP(mWindDSPDesc, &mWindDSP), "FMOD::createDSP") || !mWindDSP) return false; int frequency = 44100; - if (!Check_FMOD_Error(mSystem->getSoftwareFormat(&frequency, NULL, NULL), "FMOD::System::getSoftwareFormat")) + FMOD_SPEAKERMODE mode; + if (!Check_FMOD_Error(mSystem->getSoftwareFormat(&frequency, &mode, NULL), "FMOD::System::getSoftwareFormat")) { mWindGen = new LLWindGen((U32)frequency); - FMOD_SPEAKERMODE mode; + if (!Check_FMOD_Error(mWindDSP->setUserData((void*)mWindGen), "FMOD::DSP::setUserData") && - !Check_FMOD_Error(mSystem->playDSP(mWindDSP, NULL, false, 0), "FMOD::System::playDSP") && !Check_FMOD_Error(mSystem->getSoftwareFormat(NULL, &mode, NULL), "FMOD::System::getSoftwareFormat") && - !Check_FMOD_Error(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO, 2, mode), "FMOD::DSP::setChannelFormat")) + !Check_FMOD_Error(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO, 2, mode), "FMOD::DSP::setChannelFormat") && + !Check_FMOD_Error(mSystem->playDSP(mWindDSP, NULL, false, 0), "FMOD::System::playDSP")) return true; //Success } @@ -565,6 +539,9 @@ void LLAudioEngine_FMODSTUDIO::cleanupWind() mWindDSP = NULL; } + delete mWindDSPDesc; + mWindDSPDesc = NULL; + delete mWindGen; mWindGen = NULL; } @@ -686,6 +663,7 @@ bool LLAudioChannelFMODSTUDIO::updateBuffer() return false; } + // Actually play the sound. Start it off paused so we can do all the necessary // setup. if(!mChannelp) @@ -909,7 +887,7 @@ bool LLAudioBufferFMODSTUDIO::loadWAV(const std::string& filename) return false; } - if (!LLAPRFile::isExist(filename, LL_APR_RPB)) + if (!gDirUtilp->fileExists(filename)) { // File not found, abort. return false; @@ -924,8 +902,7 @@ bool LLAudioBufferFMODSTUDIO::loadWAV(const std::string& filename) } FMOD_MODE base_mode = FMOD_LOOP_NORMAL; - FMOD_CREATESOUNDEXINFO exinfo; - memset(&exinfo,0,sizeof(exinfo)); + FMOD_CREATESOUNDEXINFO exinfo = { }; exinfo.cbsize = sizeof(exinfo); exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; //Hint to speed up loading. // Load up the wav file into an fmod sample @@ -983,7 +960,7 @@ void LLAudioChannelFMODSTUDIO::set3DMode(bool use3d) } -FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels) +FMOD_RESULT F_CALLBACK windDSPCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels) { // inbuffer = incomming data. // newbuffer = outgoing data. AKA this DSP's output. diff --git a/indra/llaudio/llaudioengine_fmodstudio.h b/indra/llaudio/llaudioengine_fmodstudio.h index 730a702a1a..ff45d3ecb9 100644 --- a/indra/llaudio/llaudioengine_fmodstudio.h +++ b/indra/llaudio/llaudioengine_fmodstudio.h @@ -48,6 +48,7 @@ namespace FMOD class Sound; class DSP; } +typedef struct FMOD_DSP_DESCRIPTION FMOD_DSP_DESCRIPTION; //Interfaces class LLAudioEngine_FMODSTUDIO : public LLAudioEngine @@ -81,6 +82,7 @@ class LLAudioEngine_FMODSTUDIO : public LLAudioEngine LLWindGen *mWindGen; + FMOD_DSP_DESCRIPTION *mWindDSPDesc; FMOD::DSP *mWindDSP; FMOD::System *mSystem; bool mEnableProfiler; diff --git a/indra/llaudio/lllistener.cpp b/indra/llaudio/lllistener.cpp index df2366c8c2..0723fdbebe 100644 --- a/indra/llaudio/lllistener.cpp +++ b/indra/llaudio/lllistener.cpp @@ -28,15 +28,18 @@ #include "lllistener.h" -#define DEFAULT_AT 0.0f,0.0f,-1.0f -#define DEFAULT_UP 0.0f,1.0f,0.0f +const LLVector3 DEFAULT_AT(0.0f, 0.0f, -1.0f); +const LLVector3 DEFAULT_UP(0.0f, 1.0f, 0.0f); //----------------------------------------------------------------------- // constructor //----------------------------------------------------------------------- LLListener::LLListener() + : mPosition(LLVector3::zero), + mListenAt(DEFAULT_AT), + mListenUp(DEFAULT_UP), + mVelocity(LLVector3::zero) { - init(); } //----------------------------------------------------------------------- @@ -44,15 +47,6 @@ LLListener::~LLListener() { } -//----------------------------------------------------------------------- -void LLListener::init(void) -{ - mPosition.zeroVec(); - mListenAt.setVec(DEFAULT_AT); - mListenUp.setVec(DEFAULT_UP); - mVelocity.zeroVec(); -} - //----------------------------------------------------------------------- void LLListener::translate(LLVector3 offset) { @@ -99,9 +93,6 @@ void LLListener::orient(LLVector3 up, LLVector3 at) //----------------------------------------------------------------------- void LLListener::set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at) { - mPosition = pos; - mVelocity = vel; - setPosition(pos); setVelocity(vel); orient(up,at); diff --git a/indra/llaudio/lllistener.h b/indra/llaudio/lllistener.h index 41836bf039..11c1ad2ae1 100644 --- a/indra/llaudio/lllistener.h +++ b/indra/llaudio/lllistener.h @@ -45,7 +45,6 @@ class LLListener public: LLListener(); virtual ~LLListener(); - virtual void init(); virtual void set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at); diff --git a/indra/llaudio/lllistener_fmodex.cpp b/indra/llaudio/lllistener_fmodex.cpp deleted file mode 100644 index e70dc7c60c..0000000000 --- a/indra/llaudio/lllistener_fmodex.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/** - * @file listener_fmod.cpp - * @brief implementation of LISTENER class abstracting the audio - * support as a FMOD 3D implementation (windows only) - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llaudioengine.h" -#include "lllistener_fmodex.h" -#include "fmod.hpp" - -//----------------------------------------------------------------------- -// constructor -//----------------------------------------------------------------------- -LLListener_FMODEX::LLListener_FMODEX(FMOD::System *system) -{ - mSystem = system; - init(); -} - -//----------------------------------------------------------------------- -LLListener_FMODEX::~LLListener_FMODEX() -{ -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::init(void) -{ - // do inherited - LLListener::init(); - mDopplerFactor = 1.0f; - mRolloffFactor = 1.0f; -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::translate(LLVector3 offset) -{ - LLListener::translate(offset); - - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::setPosition(LLVector3 pos) -{ - LLListener::setPosition(pos); - - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::setVelocity(LLVector3 vel) -{ - LLListener::setVelocity(vel); - - mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::orient(LLVector3 up, LLVector3 at) -{ - LLListener::orient(up, at); - - // Welcome to the transition between right and left - // (coordinate systems, that is) - // Leaving the at vector alone results in a L/R reversal - // since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed - at = -at; - - mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV); -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::commitDeferredChanges() -{ - mSystem->update(); -} - - -void LLListener_FMODEX::setRolloffFactor(F32 factor) -{ - //An internal FMODEx optimization skips 3D updates if there have not been changes to the 3D sound environment. - //Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well. - //In short: Changing the position ticks a dirtyflag inside fmodex, which makes it not skip 3D processing next update call. - if(mRolloffFactor != factor) - { - LLVector3 pos = mVelocity - LLVector3(0.f,0.f,.1f); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL, NULL); - } - mRolloffFactor = factor; - mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); -} - - -F32 LLListener_FMODEX::getRolloffFactor() -{ - return mRolloffFactor; -} - - -void LLListener_FMODEX::setDopplerFactor(F32 factor) -{ - mDopplerFactor = factor; - mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); -} - - -F32 LLListener_FMODEX::getDopplerFactor() -{ - return mDopplerFactor; -} - - diff --git a/indra/llaudio/lllistener_fmodex.h b/indra/llaudio/lllistener_fmodex.h deleted file mode 100644 index 8a91b3a2ed..0000000000 --- a/indra/llaudio/lllistener_fmodex.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file listener_fmod.h - * @brief Description of LISTENER class abstracting the audio support - * as an FMOD 3D implementation (windows and Linux) - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LISTENER_FMODEX_H -#define LL_LISTENER_FMODEX_H - -#include "lllistener.h" - -//Stubs -namespace FMOD -{ - class System; -} - -//Interfaces -class LLListener_FMODEX : public LLListener -{ - public: - LLListener_FMODEX(FMOD::System *system); - virtual ~LLListener_FMODEX(); - virtual void init(); - - virtual void translate(LLVector3 offset); - virtual void setPosition(LLVector3 pos); - virtual void setVelocity(LLVector3 vel); - virtual void orient(LLVector3 up, LLVector3 at); - virtual void commitDeferredChanges(); - - virtual void setDopplerFactor(F32 factor); - virtual F32 getDopplerFactor(); - virtual void setRolloffFactor(F32 factor); - virtual F32 getRolloffFactor(); - protected: - FMOD::System *mSystem; - F32 mDopplerFactor; - F32 mRolloffFactor; -}; - -#endif - - diff --git a/indra/llaudio/lllistener_fmodstudio.cpp b/indra/llaudio/lllistener_fmodstudio.cpp index e2074ce2da..42d819ef66 100644 --- a/indra/llaudio/lllistener_fmodstudio.cpp +++ b/indra/llaudio/lllistener_fmodstudio.cpp @@ -39,10 +39,12 @@ //----------------------------------------------------------------------- // constructor //----------------------------------------------------------------------- -LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system) +LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system) + : LLListener(), + mDopplerFactor(1.0f), + mRolloffFactor(1.0f) { mSystem = system; - init(); } //----------------------------------------------------------------------- @@ -50,21 +52,12 @@ LLListener_FMODSTUDIO::~LLListener_FMODSTUDIO() { } -//----------------------------------------------------------------------- -void LLListener_FMODSTUDIO::init(void) -{ - // do inherited - LLListener::init(); - mDopplerFactor = 1.0f; - mRolloffFactor = 1.0f; -} - //----------------------------------------------------------------------- void LLListener_FMODSTUDIO::translate(LLVector3 offset) { LLListener::translate(offset); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL); } //----------------------------------------------------------------------- @@ -72,7 +65,7 @@ void LLListener_FMODSTUDIO::setPosition(LLVector3 pos) { LLListener::setPosition(pos); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL); } //----------------------------------------------------------------------- @@ -80,7 +73,7 @@ void LLListener_FMODSTUDIO::setVelocity(LLVector3 vel) { LLListener::setVelocity(vel); - mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); + mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL); } //----------------------------------------------------------------------- @@ -94,20 +87,25 @@ void LLListener_FMODSTUDIO::orient(LLVector3 up, LLVector3 at) //----------------------------------------------------------------------- void LLListener_FMODSTUDIO::commitDeferredChanges() { + if(!mSystem) + { + return; + } + mSystem->update(); } void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor) { - //An internal FMODEx optimization skips 3D updates if there have not been changes to the 3D sound environment. + //An internal FMOD Studio optimization skips 3D updates if there have not been changes to the 3D sound environment. //Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well. - //In short: Changing the position ticks a dirtyflag inside fmodstudio, which makes it not skip 3D processing next update call. + //In short: Changing the position ticks a dirtyflag inside fmod studio, which makes it not skip 3D processing next update call. if(mRolloffFactor != factor) { - LLVector3 pos = mVelocity - LLVector3(0.f,0.f,.1f); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL, NULL); + LLVector3 tmp_pos = mPosition - LLVector3(0.f,0.f,.1f); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*) tmp_pos.mV, NULL, NULL, NULL); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*) mPosition.mV, NULL, NULL, NULL); } mRolloffFactor = factor; mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); diff --git a/indra/llaudio/lllistener_fmodstudio.h b/indra/llaudio/lllistener_fmodstudio.h index 516f4eae82..de9a5e9ca6 100644 --- a/indra/llaudio/lllistener_fmodstudio.h +++ b/indra/llaudio/lllistener_fmodstudio.h @@ -48,7 +48,6 @@ class LLListener_FMODSTUDIO : public LLListener public: LLListener_FMODSTUDIO(FMOD::System *system); virtual ~LLListener_FMODSTUDIO(); - virtual void init(); virtual void translate(LLVector3 offset); virtual void setPosition(LLVector3 pos); diff --git a/indra/llaudio/lllistener_openal.cpp b/indra/llaudio/lllistener_openal.cpp index 462484e33b..d1734a930d 100644 --- a/indra/llaudio/lllistener_openal.cpp +++ b/indra/llaudio/lllistener_openal.cpp @@ -31,21 +31,15 @@ #include "lllistener_openal.h" LLListener_OpenAL::LLListener_OpenAL() + : LLListener(), + mRolloffFactor(1.f) { - init(); } LLListener_OpenAL::~LLListener_OpenAL() { } -void LLListener_OpenAL::init() -{ - // do inherited - LLListener::init(); - mRolloffFactor = 1.0f; -} - void LLListener_OpenAL::translate(LLVector3 offset) { //LL_INFOS() << "LLListener_OpenAL::translate() : " << offset << LL_ENDL; @@ -71,18 +65,20 @@ void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at) void LLListener_OpenAL::commitDeferredChanges() { - ALfloat orientation[6]; - orientation[0] = mListenAt.mV[0]; - orientation[1] = mListenAt.mV[1]; - orientation[2] = mListenAt.mV[2]; - orientation[3] = mListenUp.mV[0]; - orientation[4] = mListenUp.mV[1]; - orientation[5] = mListenUp.mV[2]; - - ALfloat velocity[3]; - velocity[0] = mVelocity.mV[0]; - velocity[1] = mVelocity.mV[1]; - velocity[2] = mVelocity.mV[2]; + ALfloat orientation[] = { + mListenAt.mV[0], + mListenAt.mV[1], + mListenAt.mV[2], + mListenUp.mV[0], + mListenUp.mV[1], + mListenUp.mV[2], + }; + + ALfloat velocity[3] = { + mVelocity.mV[0], + mVelocity.mV[1], + mVelocity.mV[2], + }; alListenerfv(AL_ORIENTATION, orientation); alListenerfv(AL_POSITION, mPosition.mV); diff --git a/indra/llaudio/lllistener_openal.h b/indra/llaudio/lllistener_openal.h index 96af86d998..cb163b11a5 100644 --- a/indra/llaudio/lllistener_openal.h +++ b/indra/llaudio/lllistener_openal.h @@ -38,7 +38,6 @@ class LLListener_OpenAL : public LLListener public: LLListener_OpenAL(); virtual ~LLListener_OpenAL(); - virtual void init(); virtual void translate(LLVector3 offset); virtual void setPosition(LLVector3 pos); diff --git a/indra/llaudio/llstreamingaudio_fmodex.cpp b/indra/llaudio/llstreamingaudio_fmodex.cpp deleted file mode 100644 index 39436977a8..0000000000 --- a/indra/llaudio/llstreamingaudio_fmodex.cpp +++ /dev/null @@ -1,596 +0,0 @@ -/** - * @file streamingaudio_fmod.cpp - * @brief LLStreamingAudio_FMODEX implementation - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llmath.h" - -#include "fmod.hpp" -#include "fmod_errors.h" - -#include "llstreamingaudio_fmodex.h" - -inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) -{ - if (result == FMOD_OK) - return false; - LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; - return true; -} - -class LLAudioStreamManagerFMODEX -{ -public: - LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url); - FMOD::Channel* startStream(); - bool stopStream(); // Returns true if the stream was successfully stopped. - bool ready(); - - const std::string& getURL() { return mInternetStreamURL; } - - FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL); -protected: - FMOD::System* mSystem; - FMOD::Channel* mStreamChannel; - FMOD::Sound* mInternetStream; - bool mReady; - - std::string mInternetStreamURL; -}; - - - -//--------------------------------------------------------------------------- -// Internet Streaming -//--------------------------------------------------------------------------- -LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) : - mSystem(system), - mCurrentInternetStreamp(NULL), - mFMODInternetStreamChannelp(NULL), - mGain(1.0f), - mMetaData(NULL) -{ - FMOD_RESULT result; - - // Number of milliseconds of audio to buffer for the audio card. - // Must be larger than the usual Second Life frame stutter time. - const U32 buffer_seconds = 10; //sec - const U32 estimated_bitrate = 128; //kbit/sec - result = mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES); - Check_FMOD_Error(result, "FMOD::System::setStreamBufferSize"); - - // Here's where we set the size of the network buffer and some buffering - // parameters. In this case we want a network buffer of 16k, we want it - // to prebuffer 40% of that when we first connect, and we want it - // to rebuffer 80% of that whenever we encounter a buffer underrun. - - // Leave the net buffer properties at the default. - //FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80); -} - - -LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX() -{ - stop(); - for (U32 i = 0; i < 100; ++i) - { - if (releaseDeadStreams()) - break; - ms_sleep(10); - } -} - - -void LLStreamingAudio_FMODEX::start(const std::string& url) -{ - //if (!mInited) - //{ - // LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL; - // return; - //} - - // "stop" stream but don't clear url, etc. in case url == mInternetStreamURL - stop(); - - if (!url.empty()) - { - if(mDeadStreams.empty()) - { - LL_INFOS() << "Starting internet stream: " << url << LL_ENDL; - mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url); - mURL = url; - mMetaData = new LLSD; - } - else - { - LL_INFOS() << "Deferring stream load until buffer release: " << url << LL_ENDL; - mPendingURL = url; - } - } - else - { - LL_INFOS() << "Set internet stream to null" << LL_ENDL; - mURL.clear(); - } -} - -enum utf_endian_type_t -{ - UTF16LE, - UTF16BE, - UTF16 -}; - -std::string utf16input_to_utf8(unsigned char* input, U32 len, utf_endian_type_t type) -{ - if (type == UTF16) - { - type = UTF16BE; //Default - if (len > 2) - { - //Parse and strip BOM. - if ((input[0] == 0xFE && input[1] == 0xFF) || - (input[0] == 0xFF && input[1] == 0xFE)) - { - input += 2; - len -= 2; - type = input[0] == 0xFE ? UTF16BE : UTF16LE; - } - } - } - llutf16string out_16((U16*)input, len / 2); - if (len % 2) - { - out_16.push_back((input)[len - 1] << 8); - } - if (type == UTF16BE) - { - for (llutf16string::iterator i = out_16.begin(); i < out_16.end(); ++i) - { - llutf16string::value_type v = *i; - *i = ((v & 0x00FF) << 8) | ((v & 0xFF00) >> 8); - } - } - return utf16str_to_utf8str(out_16); -} - -void LLStreamingAudio_FMODEX::update() -{ - if (!releaseDeadStreams()) - { - llassert_always(mCurrentInternetStreamp == NULL); - return; - } - - if(!mPendingURL.empty()) - { - llassert_always(mCurrentInternetStreamp == NULL); - LL_INFOS() << "Starting internet stream: " << mPendingURL << LL_ENDL; - mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,mPendingURL); - mURL = mPendingURL; - mMetaData = new LLSD; - mPendingURL.clear(); - } - - // Don't do anything if there are no streams playing - if (!mCurrentInternetStreamp) - { - return; - } - - unsigned int progress; - bool starving; - bool diskbusy; - FMOD_OPENSTATE open_state; - FMOD_RESULT res = mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy); - - if (res != FMOD_OK || open_state == FMOD_OPENSTATE_ERROR) - { - stop(); - return; - } - else if (open_state == FMOD_OPENSTATE_READY) - { - // Stream is live - - // start the stream if it's ready - if (!mFMODInternetStreamChannelp && - (mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream())) - { - // Reset volume to previously set volume - setGain(getGain()); - Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused"); - } - } - - if(mFMODInternetStreamChannelp) - { - if(!mMetaData) - mMetaData = new LLSD; - - FMOD::Sound *sound = NULL; - - if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound) - { - FMOD_TAG tag; - S32 tagcount, dirtytagcount; - if(sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount) - { - mMetaData->clear(); - - for(S32 i = 0; i < tagcount; ++i) - { - if(sound->getTag(NULL, i, &tag)!=FMOD_OK) - continue; - std::string name = tag.name; - switch(tag.type) //Crappy tag translate table. - { - case(FMOD_TAGTYPE_ID3V2): - if (!LLStringUtil::compareInsensitive(name, "TIT2")) name = "TITLE"; - else if(name == "TPE1") name = "ARTIST"; - break; - case(FMOD_TAGTYPE_ASF): - if (!LLStringUtil::compareInsensitive(name, "Title")) name = "TITLE"; - else if (!LLStringUtil::compareInsensitive(name, "WM/AlbumArtist")) name = "ARTIST"; - break; - case(FMOD_TAGTYPE_FMOD): - if (!LLStringUtil::compareInsensitive(name, "Sample Rate Change")) - { - LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL; - Check_FMOD_Error(mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data)), "FMOD::Channel::setFrequency"); - } - continue; - default: - if (!LLStringUtil::compareInsensitive(name, "TITLE") || - !LLStringUtil::compareInsensitive(name, "ARTIST")) - LLStringUtil::toUpper(name); - break; - } - - switch(tag.datatype) - { - case(FMOD_TAGDATATYPE_INT): - (*mMetaData)[name]=*(LLSD::Integer*)(tag.data); - LL_INFOS() << tag.name << ": " << *(int*)(tag.data) << LL_ENDL; - break; - case(FMOD_TAGDATATYPE_FLOAT): - (*mMetaData)[name]=*(LLSD::Float*)(tag.data); - LL_INFOS() << tag.name << ": " << *(float*)(tag.data) << LL_ENDL; - break; - case(FMOD_TAGDATATYPE_STRING): - { - std::string out = rawstr_to_utf8(std::string((char*)tag.data,tag.datalen)); - if (out.length() && out[out.size() - 1] == 0) - out.erase(out.size() - 1); - (*mMetaData)[name]=out; - LL_INFOS() << tag.name << "(RAW): " << out << LL_ENDL; - } - break; - case(FMOD_TAGDATATYPE_STRING_UTF8) : - { - U8 offs = 0; - if (tag.datalen > 3 && ((unsigned char*)tag.data)[0] == 0xEF && ((char*)tag.data)[1] == 0xBB && ((char*)tag.data)[2] == 0xBF) - offs = 3; - std::string out((char*)tag.data + offs, tag.datalen - offs); - if (out.length() && out[out.size() - 1] == 0) - out.erase(out.size() - 1); - (*mMetaData)[name] = out; - LL_INFOS() << tag.name << "(UTF8): " << out << LL_ENDL; - } - break; - case(FMOD_TAGDATATYPE_STRING_UTF16): - { - std::string out = utf16input_to_utf8((unsigned char*)tag.data, tag.datalen, UTF16); - if (out.length() && out[out.size() - 1] == 0) - out.erase(out.size() - 1); - (*mMetaData)[name] = out; - LL_INFOS() << tag.name << "(UTF16): " << out << LL_ENDL; - } - break; - case(FMOD_TAGDATATYPE_STRING_UTF16BE): - { - std::string out = utf16input_to_utf8((unsigned char*)tag.data, tag.datalen, UTF16BE); - if (out.length() && out[out.size() - 1] == 0) - out.erase(out.size() - 1); - (*mMetaData)[name] = out; - LL_INFOS() << tag.name << "(UTF16BE): " << out << LL_ENDL; - } - default: - break; - } - } - } - if(starving) - { - bool paused = false; - if (mFMODInternetStreamChannelp->getPaused(&paused) == FMOD_OK && !paused) - { - LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL; - LL_INFOS() << " (diskbusy="<setPaused(true), "FMOD::Channel::setPaused"); - } - } - else if(progress > 80) - { - Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused"); - } - } - } -} - -void LLStreamingAudio_FMODEX::stop() -{ - mPendingURL.clear(); - - if(mMetaData) - { - delete mMetaData; - mMetaData = NULL; - } - if (mFMODInternetStreamChannelp) - { - Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused"); - Check_FMOD_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority"); - mFMODInternetStreamChannelp = NULL; - } - - if (mCurrentInternetStreamp) - { - LL_INFOS() << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL; - if (mCurrentInternetStreamp->stopStream()) - { - delete mCurrentInternetStreamp; - } - else - { - LL_WARNS() << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL; - mDeadStreams.push_back(mCurrentInternetStreamp); - } - mCurrentInternetStreamp = NULL; - //mURL.clear(); - } -} - -void LLStreamingAudio_FMODEX::pause(int pauseopt) -{ - if (pauseopt < 0) - { - pauseopt = mCurrentInternetStreamp ? 1 : 0; - } - - if (pauseopt) - { - if (mCurrentInternetStreamp) - { - stop(); - } - } - else - { - start(getURL()); - } -} - - -// A stream is "playing" if it has been requested to start. That -// doesn't necessarily mean audio is coming out of the speakers. -int LLStreamingAudio_FMODEX::isPlaying() -{ - if (mCurrentInternetStreamp) - { - return 1; // Active and playing - } - else if (!mURL.empty() || !mPendingURL.empty()) - { - return 2; // "Paused" - } - else - { - return 0; - } -} - - -F32 LLStreamingAudio_FMODEX::getGain() -{ - return mGain; -} - - -std::string LLStreamingAudio_FMODEX::getURL() -{ - return mURL; -} - - -void LLStreamingAudio_FMODEX::setGain(F32 vol) -{ - mGain = vol; - - if (mFMODInternetStreamChannelp) - { - vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here? - - Check_FMOD_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume"); - } -} - -/*virtual*/ bool LLStreamingAudio_FMODEX::getWaveData(float* arr, S32 count, S32 stride/*=1*/) -{ - if(!mFMODInternetStreamChannelp || !mCurrentInternetStreamp) - return false; - - bool muted=false; - FMOD_RESULT res = mFMODInternetStreamChannelp->getMute(&muted); - if(res != FMOD_OK || muted) - return false; - - static std::vector local_array(count); //Have to have an extra buffer to mix channels. Bleh. - if(count > (S32)local_array.size()) //Expand the array if needed. Try to minimize allocation calls, so don't ever shrink. - local_array.resize(count); - - if( mFMODInternetStreamChannelp->getWaveData(&local_array[0],count,0) == FMOD_OK && - mFMODInternetStreamChannelp->getWaveData(&arr[0],count,1) == FMOD_OK ) - { - for(S32 i = count-1;i>=0;i-=stride) - { - arr[i] += local_array[i]; - arr[i] *= .5f; - } - return true; - } - return false; -} - -/////////////////////////////////////////////////////// -// manager of possibly-multiple internet audio streams - -LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url) : - mSystem(system), - mStreamChannel(NULL), - mInternetStream(NULL), - mReady(false) -{ - mInternetStreamURL = url; - - /*FMOD_CREATESOUNDEXINFO exinfo; - memset(&exinfo,0,sizeof(exinfo)); - exinfo.cbsize = sizeof(exinfo); - exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_OGGVORBIS; //Hint to speed up loading.*/ - - FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream); - - if (result!= FMOD_OK) - { - LL_WARNS() << "Couldn't open fmod stream, error " - << FMOD_ErrorString(result) - << LL_ENDL; - mReady = false; - return; - } - - mReady = true; -} - -FMOD::Channel *LLAudioStreamManagerFMODEX::startStream() -{ - // We need a live and opened stream before we try and play it. - FMOD_OPENSTATE open_state; - if (getOpenState(open_state) != FMOD_OK || open_state != FMOD_OPENSTATE_READY) - { - LL_WARNS() << "No internet stream to start playing!" << LL_ENDL; - return NULL; - } - - if(mStreamChannel) - return mStreamChannel; //Already have a channel for this stream. - - Check_FMOD_Error(mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel), "FMOD::System::playSound"); - return mStreamChannel; -} - -bool LLAudioStreamManagerFMODEX::stopStream() -{ - if (mInternetStream) - { - bool close = true; - FMOD_OPENSTATE open_state; - if (getOpenState(open_state) == FMOD_OK) - { - switch (open_state) - { - case FMOD_OPENSTATE_CONNECTING: - close = false; - break; - default: - close = true; - } - } - - if (close && mInternetStream->release() == FMOD_OK) - { - mStreamChannel = NULL; - mInternetStream = NULL; - return true; - } - else - { - return false; - } - } - else - { - return true; - } -} - -FMOD_RESULT LLAudioStreamManagerFMODEX::getOpenState(FMOD_OPENSTATE& state, unsigned int* percentbuffered, bool* starving, bool* diskbusy) -{ - if (!mInternetStream) - return FMOD_ERR_INVALID_HANDLE; - FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy); - Check_FMOD_Error(result, "FMOD::Sound::getOpenState"); - return result; -} - -void LLStreamingAudio_FMODEX::setBufferSizes(U32 streambuffertime, U32 decodebuffertime) -{ - Check_FMOD_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize"); - FMOD_ADVANCEDSETTINGS settings; - memset(&settings,0,sizeof(settings)); - settings.cbsize=sizeof(settings); - settings.defaultDecodeBufferSize = decodebuffertime;//ms - Check_FMOD_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings"); -} - -bool LLStreamingAudio_FMODEX::releaseDeadStreams() -{ - // Kill dead internet streams, if possible - std::list::iterator iter; - for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) - { - LLAudioStreamManagerFMODEX *streamp = *iter; - if (streamp->stopStream()) - { - LL_INFOS() << "Closed dead stream" << LL_ENDL; - delete streamp; - mDeadStreams.erase(iter++); - } - else - { - iter++; - } - } - - return mDeadStreams.empty(); -} \ No newline at end of file diff --git a/indra/llaudio/llstreamingaudio_fmodex.h b/indra/llaudio/llstreamingaudio_fmodex.h deleted file mode 100644 index 15a4af9314..0000000000 --- a/indra/llaudio/llstreamingaudio_fmodex.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @file streamingaudio_fmod.h - * @author Tofu Linden - * @brief Definition of LLStreamingAudio_FMOD implementation - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_STREAMINGAUDIO_FMOD_H -#define LL_STREAMINGAUDIO_FMOD_H - -#include "stdtypes.h" // from llcommon - -#include "llstreamingaudio.h" -#include "lltimer.h" - -//Stubs -class LLAudioStreamManagerFMODEX; -namespace FMOD -{ - class System; - class Channel; -} - -//Interfaces -class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface -{ - public: - LLStreamingAudio_FMODEX(FMOD::System *system); - /*virtual*/ ~LLStreamingAudio_FMODEX(); - - /*virtual*/ void start(const std::string& url); - /*virtual*/ void stop(); - /*virtual*/ void pause(int pause); - /*virtual*/ void update(); - /*virtual*/ int isPlaying(); - /*virtual*/ void setGain(F32 vol); - /*virtual*/ F32 getGain(); - /*virtual*/ std::string getURL(); - - /*virtual*/ bool supportsMetaData(){return true;} - /*virtual*/ const LLSD *getMetaData(){return mMetaData;} //return NULL if not playing. - /*virtual*/ bool supportsWaveData(){return true;} - /*virtual*/ bool getWaveData(float* arr, S32 count, S32 stride = 1); - /*virtual*/ bool supportsAdjustableBufferSizes(){return true;} - /*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime); -private: - bool releaseDeadStreams(); - - FMOD::System *mSystem; - - LLAudioStreamManagerFMODEX *mCurrentInternetStreamp; - FMOD::Channel *mFMODInternetStreamChannelp; - std::list mDeadStreams; - - std::string mURL; - std::string mPendingURL; - F32 mGain; - - LLSD *mMetaData; -}; - - -#endif // LL_STREAMINGAUDIO_FMOD_H diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.cpp b/indra/llaudio/llstreamingaudio_fmodstudio.cpp index 5ef93fd008..d7c6b48b78 100644 --- a/indra/llaudio/llstreamingaudio_fmodstudio.cpp +++ b/indra/llaudio/llstreamingaudio_fmodstudio.cpp @@ -31,6 +31,7 @@ */ #include "linden_common.h" +#include "llstreamingaudio_fmodstudio.h" #include "llmath.h" #include "llthread.h" @@ -38,8 +39,6 @@ #include "fmod.hpp" #include "fmod_errors.h" -#include "llstreamingaudio_fmodstudio.h" - inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) { if (result == FMOD_OK) @@ -61,9 +60,9 @@ class LLAudioStreamManagerFMODSTUDIO FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered = NULL, bool* starving = NULL, bool* diskbusy = NULL); protected: FMOD::System* mSystem; + FMOD::ChannelGroup* mChannelGroup; FMOD::Channel* mStreamChannel; FMOD::Sound* mInternetStream; - FMOD::ChannelGroup* mChannelGroup; bool mReady; std::string mInternetStreamURL; @@ -119,11 +118,11 @@ FMOD_RESULT F_CALLBACK waveDataCallback(FMOD_DSP_STATE *dsp_state, float *inbuff LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) : mSystem(system), mCurrentInternetStreamp(NULL), + mStreamDSP(NULL), + mStreamGroup(NULL), mFMODInternetStreamChannelp(NULL), mGain(1.0f), - mMetaData(NULL), - mStreamGroup(NULL), - mStreamDSP(NULL) + mMetaData(NULL) { FMOD_RESULT result; @@ -142,10 +141,9 @@ LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) : // Leave the net buffer properties at the default. //FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80); - Check_FMOD_Error(mSystem->createChannelGroup("stream", &mStreamGroup), "FMOD::System::createChannelGroup"); + Check_FMOD_Error(system->createChannelGroup("stream", &mStreamGroup), "FMOD::System::createChannelGroup"); - FMOD_DSP_DESCRIPTION dspdesc; - memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Zero out everything + FMOD_DSP_DESCRIPTION dspdesc = { }; dspdesc.pluginsdkversion = FMOD_PLUGIN_SDK_VERSION; strncpy(dspdesc.name, "Waveform", sizeof(dspdesc.name)); dspdesc.numoutputbuffers = 1; @@ -154,7 +152,6 @@ LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) : Check_FMOD_Error(system->createDSP(&dspdesc, &mStreamDSP), "FMOD::System::createDSP"); } - LLStreamingAudio_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO() { stop(); @@ -168,7 +165,6 @@ LLStreamingAudio_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO() cleanupWaveData(); } - void LLStreamingAudio_FMODSTUDIO::start(const std::string& url) { //if (!mInited) @@ -209,7 +205,7 @@ enum utf_endian_type_t UTF16 }; -std::string utf16input_to_utf8(char* input, U32 len, utf_endian_type_t type) +std::string utf16input_to_utf8(unsigned char* input, U32 len, utf_endian_type_t type) { if (type == UTF16) { @@ -226,7 +222,7 @@ std::string utf16input_to_utf8(char* input, U32 len, utf_endian_type_t type) } } } - llutf16string out_16((U16*)input, len / 2); + llutf16string out_16((llutf16string::value_type*)input, len / 2); if (len % 2) { out_16.push_back((input)[len - 1] << 8); @@ -254,7 +250,7 @@ void LLStreamingAudio_FMODSTUDIO::update() { llassert_always(mCurrentInternetStreamp == NULL); LL_INFOS() << "Starting internet stream: " << mPendingURL << LL_ENDL; - mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem,mStreamGroup, mPendingURL); + mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, mPendingURL); mURL = mPendingURL; mMetaData = new LLSD; mPendingURL.clear(); @@ -315,6 +311,7 @@ void LLStreamingAudio_FMODSTUDIO::update() { if(sound->getTag(NULL, i, &tag)!=FMOD_OK) continue; + std::string name = tag.name; switch(tag.type) //Crappy tag translate table. { @@ -373,7 +370,7 @@ void LLStreamingAudio_FMODSTUDIO::update() break; case(FMOD_TAGDATATYPE_STRING_UTF16): { - std::string out = utf16input_to_utf8((char*)tag.data, tag.datalen, UTF16); + std::string out = utf16input_to_utf8((unsigned char*)tag.data, tag.datalen, UTF16); if (out.length() && out[out.size() - 1] == 0) out.erase(out.size() - 1); (*mMetaData)[name] = out; @@ -382,7 +379,7 @@ void LLStreamingAudio_FMODSTUDIO::update() break; case(FMOD_TAGDATATYPE_STRING_UTF16BE): { - std::string out = utf16input_to_utf8((char*)tag.data, tag.datalen, UTF16BE); + std::string out = utf16input_to_utf8((unsigned char*)tag.data, tag.datalen, UTF16BE); if (out.length() && out[out.size() - 1] == 0) out.erase(out.size() - 1); (*mMetaData)[name] = out; @@ -393,6 +390,7 @@ void LLStreamingAudio_FMODSTUDIO::update() } } } + static bool was_starved = false; if(starving) { bool paused = false; @@ -403,9 +401,11 @@ void LLStreamingAudio_FMODSTUDIO::update() LL_INFOS() << " (progress="<setPaused(true), "FMOD::Channel::setPaused"); } + was_starved = true; } - else if(progress > 80) + else if(progress > 80 && was_starved) { + was_starved = false; Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused"); } } @@ -446,7 +446,6 @@ void LLStreamingAudio_FMODSTUDIO::stop() mDeadStreams.push_back(mCurrentInternetStreamp); } mCurrentInternetStreamp = NULL; - //mURL.clear(); } } @@ -514,7 +513,8 @@ void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol) } } -/*virtual*/ bool LLStreamingAudio_FMODSTUDIO::getWaveData(float* arr, S32 count, S32 stride/*=1*/) +/* virtual */ +bool LLStreamingAudio_FMODSTUDIO::getWaveData(float* arr, S32 count, S32 stride/*=1*/) { if (count > (WAVE_BUFFER_SIZE / 2)) LL_ERRS("AudioImpl") << "Count=" << count << " exceeds WAVE_BUFFER_SIZE/2=" << WAVE_BUFFER_SIZE << LL_ENDL; @@ -547,9 +547,9 @@ void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol) LLAudioStreamManagerFMODSTUDIO::LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url) : mSystem(system), + mChannelGroup(group), mStreamChannel(NULL), mInternetStream(NULL), - mChannelGroup(group), mReady(false) { mInternetStreamURL = url; @@ -632,8 +632,7 @@ FMOD_RESULT LLAudioStreamManagerFMODSTUDIO::getOpenState(FMOD_OPENSTATE& state, void LLStreamingAudio_FMODSTUDIO::setBufferSizes(U32 streambuffertime, U32 decodebuffertime) { Check_FMOD_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize"); - FMOD_ADVANCEDSETTINGS settings; - memset(&settings,0,sizeof(settings)); + FMOD_ADVANCEDSETTINGS settings = { }; settings.cbSize=sizeof(settings); settings.defaultDecodeBufferSize = decodebuffertime;//ms Check_FMOD_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings"); @@ -672,4 +671,4 @@ void LLStreamingAudio_FMODSTUDIO::cleanupWaveData() if(mStreamDSP) Check_FMOD_Error(mStreamDSP->release(), "FMOD::DSP::release"); mStreamDSP = NULL; -} \ No newline at end of file +} diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp index c0c9d6d6b3..2e7fdb1db3 100644 --- a/indra/llaudio/llvorbisencode.cpp +++ b/indra/llaudio/llvorbisencode.cpp @@ -32,7 +32,6 @@ #include "llerror.h" #include "llrand.h" #include "llmath.h" -#include "llapr.h" //#if LL_DARWIN // MBW -- XXX -- Getting rid of SecondLifeVorbis for now -- no fmod means no name collisions. @@ -81,18 +80,20 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro error_msg.clear(); - // ******************************** - LLAPRFile infile ; - infile.open(in_fname,LL_APR_RB); - // ******************************** - if (!infile.getFileHandle()) + //******************************** + llifstream instream(in_fname, std::ios::in | std::ios::binary); + //******************************** + if (!instream.is_open()) { error_msg = "CannotUploadSoundFile"; return(LLVORBISENC_SOURCE_OPEN_ERR); } - infile.read(wav_header, 44); - physical_file_size = infile.seek(APR_END,0); + instream.read((char*)wav_header, 44); + + instream.seekg(0, instream.end); + physical_file_size = (U32) instream.tellg(); + instream.seekg(0, instream.beg); if (strncmp((char *)&(wav_header[0]),"RIFF",4)) { @@ -112,8 +113,8 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro while ((file_pos + 8)< physical_file_size) { - infile.seek(APR_SET,file_pos); - infile.read(wav_header, 44); + instream.seekg(file_pos); + instream.read((char*)wav_header, 44); chunk_length = ((U32) wav_header[7] << 24) + ((U32) wav_header[6] << 16) @@ -122,7 +123,7 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro if (chunk_length > physical_file_size - file_pos - 4) { - infile.close(); + instream.close(); error_msg = "SoundFileInvalidChunkSize"; return(LLVORBISENC_CHUNK_SIZE_ERR); } @@ -153,9 +154,9 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro file_pos += (chunk_length + 8); chunk_length = 0; } - // **************** - infile.close(); - // **************** + //**************** + instream.close(); + //**************** if (!uncompressed_pcm) { @@ -233,20 +234,18 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname S32 data_left = 0; - LLAPRFile infile ; - infile.open(in_fname,LL_APR_RB); - if (!infile.getFileHandle()) + llifstream instream(in_fname, std::ios::in | std::ios::binary); + if (!instream.is_open()) { - LL_WARNS() << "Couldn't open temporary ogg file for writing: " << in_fname + LL_WARNS() << "Couldn't open temporary ogg file for reading: " << in_fname << LL_ENDL; return(LLVORBISENC_SOURCE_OPEN_ERR); } - LLAPRFile outfile ; - outfile.open(out_fname,LL_APR_WPB); - if (!outfile.getFileHandle()) + llofstream outstream(out_fname, std::ios::out | std::ios::binary | std::ios::trunc); + if (!outstream.is_open()) { - LL_WARNS() << "Couldn't open upload sound file for reading: " << in_fname + LL_WARNS() << "Couldn't open upload sound file for writing: " << in_fname << LL_ENDL; return(LLVORBISENC_DEST_OPEN_ERR); } @@ -255,10 +254,10 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname U32 chunk_length = 0; U32 file_pos = 12; // start at the first chunk (usually fmt but not always) - while (infile.eof() != APR_EOF) + while (!instream.eof()) { - infile.seek(APR_SET,file_pos); - infile.read(wav_header, 44); + instream.seekg(file_pos); + instream.read((char*)wav_header, 44); chunk_length = ((U32) wav_header[7] << 24) + ((U32) wav_header[6] << 16) @@ -278,7 +277,7 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname } else if (!(strncmp((char *)&(wav_header[0]),"data",4))) { - infile.seek(APR_SET,file_pos+8); + instream.seekg(file_pos + 8); // leave the file pointer at the beginning of the data chunk data data_left = chunk_length; break; @@ -351,8 +350,8 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname while(!eos){ int result=ogg_stream_flush(&os,&og); if(result==0)break; - outfile.write(og.header, og.header_len); - outfile.write(og.body, og.body_len); + outstream.write((char*)og.header, og.header_len); + outstream.write((char*)og.body, og.body_len); } } @@ -362,7 +361,8 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname { long bytes_per_sample = bits_per_sample/8; - long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */ + instream.read((char*)readbuffer, llclamp((S32) (READ_BUFFER*num_channels*bytes_per_sample), 0, data_left)); /* stereo hardwired here */ + long bytes = (long) instream.gcount(); if (bytes==0) { @@ -470,8 +470,8 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname if(result==0) break; - outfile.write(og.header, og.header_len); - outfile.write(og.body, og.body_len); + outstream.write((char*)og.header, og.header_len); + outstream.write((char*)og.body, og.body_len); /* this could be set above, but for illustrative purposes, I do it here (to show that vorbis does know where the stream ends) */ diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt index 8dda476d9f..e95b924360 100644 --- a/indra/llcharacter/CMakeLists.txt +++ b/indra/llcharacter/CMakeLists.txt @@ -16,6 +16,10 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(llcharacter_SOURCE_FILES llanimationstates.cpp @@ -73,4 +77,9 @@ set_source_files_properties(${llcharacter_HEADER_FILES} list(APPEND llcharacter_SOURCE_FILES ${llcharacter_HEADER_FILES}) add_library (llcharacter ${llcharacter_SOURCE_FILES}) -add_dependencies(llcharacter prepare) + +target_link_libraries( + llcharacter + PUBLIC + llcommon + ) diff --git a/indra/llcharacter/llanimationstates.cpp b/indra/llcharacter/llanimationstates.cpp index 155226cf17..c16cae1bbc 100644 --- a/indra/llcharacter/llanimationstates.cpp +++ b/indra/llcharacter/llanimationstates.cpp @@ -46,7 +46,7 @@ LLUUID const ANIM_AGENT_BLOW_KISS ("db84829b-462c-ee83-1e27-9bbee66b LLUUID const ANIM_AGENT_BORED ("b906c4ba-703b-1940-32a3-0c7f7d791510"); LLUUID const ANIM_AGENT_BOW ("82e99230-c906-1403-4d9c-3889dd98daba"); LLUUID const ANIM_AGENT_BRUSH ("349a3801-54f9-bf2c-3bd0-1ac89772af01"); -LLUUID const ANIM_AGENT_BUSY ("efcf670c-2d18-8128-973a-034ebc806b67"); +LLUUID const ANIM_AGENT_DO_NOT_DISTURB ("efcf670c-2d18-8128-973a-034ebc806b67"); LLUUID const ANIM_AGENT_CLAP ("9b0c1c4e-8ac7-7969-1494-28c874c4f668"); LLUUID const ANIM_AGENT_COURTBOW ("9ba1c942-08be-e43a-fb29-16ad440efc50"); LLUUID const ANIM_AGENT_CROUCH ("201f3fdf-cb1f-dbec-201f-7333e328ae7c"); @@ -211,7 +211,7 @@ LLAnimationLibrary::LLAnimationLibrary() : mAnimMap[ANIM_AGENT_BORED]= mAnimStringTable.addString("express_bored"); mAnimMap[ANIM_AGENT_BOW]= mAnimStringTable.addString("bow"); mAnimMap[ANIM_AGENT_BRUSH]= mAnimStringTable.addString("brush"); - mAnimMap[ANIM_AGENT_BUSY]= mAnimStringTable.addString("busy"); + mAnimMap[ANIM_AGENT_DO_NOT_DISTURB]= mAnimStringTable.addString("busy"); mAnimMap[ANIM_AGENT_CLAP]= mAnimStringTable.addString("clap"); mAnimMap[ANIM_AGENT_COURTBOW]= mAnimStringTable.addString("courtbow"); mAnimMap[ANIM_AGENT_CROUCH]= mAnimStringTable.addString("crouch"); diff --git a/indra/llcharacter/llanimationstates.h b/indra/llcharacter/llanimationstates.h index a443488388..79cbcabdc1 100644 --- a/indra/llcharacter/llanimationstates.h +++ b/indra/llcharacter/llanimationstates.h @@ -56,7 +56,7 @@ extern const LLUUID ANIM_AGENT_BLOW_KISS; extern const LLUUID ANIM_AGENT_BORED; extern const LLUUID ANIM_AGENT_BOW; extern const LLUUID ANIM_AGENT_BRUSH; -extern const LLUUID ANIM_AGENT_BUSY; +extern const LLUUID ANIM_AGENT_DO_NOT_DISTURB; extern const LLUUID ANIM_AGENT_CLAP; extern const LLUUID ANIM_AGENT_COURTBOW; extern const LLUUID ANIM_AGENT_CROUCH; diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 5bffb1270b..1c811a9244 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -35,10 +35,6 @@ #include "llkeyframemotion.h" #include "llquantize.h" #include "llstl.h" -#include "llapr.h" - - -//using namespace std; #define INCHES_TO_METERS 0.02540005f @@ -219,9 +215,8 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) //-------------------------------------------------------------------- std::string path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName); - LLAPRFile infile(path, LL_APR_R); - apr_file_t *fp = infile.getFileHandle(); - if (!fp) + llifstream infstream(path); + if (!infstream.is_open()) return E_ST_NO_XLT_FILE; LL_INFOS() << "NOTE: Loading translation table: " << fileName << LL_ENDL; @@ -233,7 +228,7 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) //-------------------------------------------------------------------- // load header //-------------------------------------------------------------------- - if ( ! getLine(fp) ) + if ( ! getLine(infstream) ) return E_ST_EOF; if ( strncmp(mLine, "Translations 1.0", 16) ) return E_ST_NO_XLT_HEADER; @@ -243,7 +238,7 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) //-------------------------------------------------------------------- BOOL loadingGlobals = FALSE; Translation *trans = NULL; - while ( getLine(fp) ) + while ( getLine(infstream) ) { //---------------------------------------------------------------- // check the 1st token on the line to determine if it's empty or a comment @@ -660,7 +655,7 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) } - infile.close() ; + infstream.close() ; return E_ST_OK; } @@ -1337,13 +1332,9 @@ void LLBVHLoader::reset() //------------------------------------------------------------------------ // LLBVHLoader::getLine() //------------------------------------------------------------------------ -BOOL LLBVHLoader::getLine(apr_file_t* fp) +BOOL LLBVHLoader::getLine(llifstream& stream) { - if (apr_file_eof(fp) == APR_EOF) - { - return FALSE; - } - if ( apr_file_gets(mLine, BVH_PARSER_LINE_SIZE, fp) == APR_SUCCESS) + if (stream.getline(mLine, BVH_PARSER_LINE_SIZE)) { mLineNumber++; return TRUE; diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h index 38617bd6d4..d1c48e4469 100644 --- a/indra/llcharacter/llbvhloader.h +++ b/indra/llcharacter/llbvhloader.h @@ -2,31 +2,25 @@ * @file llbvhloader.h * @brief Translates a BVH files to LindenLabAnimation format. * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -36,32 +30,11 @@ #include "v3math.h" #include "m3math.h" #include "llmath.h" -#include "llapr.h" #include "llbvhconsts.h" const S32 BVH_PARSER_LINE_SIZE = 2048; class LLDataPacker; -//------------------------------------------------------------------------ -// FileCloser -//------------------------------------------------------------------------ -class FileCloser -{ -public: - FileCloser( apr_file_t *file ) - { - mFile = file; - } - - ~FileCloser() - { - apr_file_close(mFile); - } -protected: - apr_file_t* mFile; -}; - - //------------------------------------------------------------------------ // Key //------------------------------------------------------------------------ @@ -304,7 +277,7 @@ class LLBVHLoader protected: // Consumes one line of input from file. - BOOL getLine(apr_file_t *fp); + BOOL getLine(llifstream& stream); // parser state char mLine[BVH_PARSER_LINE_SIZE]; /* Flawfinder: ignore */ diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index 1bfee5b410..f2d2f0a95a 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -38,7 +38,6 @@ LLStringTable LLCharacter::sVisualParamNames(1024); std::vector< LLCharacter* > LLCharacter::sInstances; -BOOL LLCharacter::sAllowInstancesChange = TRUE ; //----------------------------------------------------------------------------- // LLCharacter() @@ -51,7 +50,6 @@ LLCharacter::LLCharacter() mAppearanceSerialNum( 0 ), mSkeletonSerialNum( 0 ) { - llassert_always(sAllowInstancesChange) ; sInstances.push_back(this); mMotionController.setCharacter( this ); @@ -75,8 +73,6 @@ LLCharacter::~LLCharacter() bool erased = vector_replace_with_last(sInstances,this); llassert_always(erased) ; - - llassert_always(sAllowInstancesChange) ; } @@ -176,9 +172,9 @@ void LLCharacter::requestStopMotion( LLMotion* motion) //----------------------------------------------------------------------------- // updateMotions() //----------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_UPDATE_ANIMATION("Update Animation"); -static LLFastTimer::DeclareTimer FTM_UPDATE_HIDDEN_ANIMATION("Update Hidden Anim"); -static LLFastTimer::DeclareTimer FTM_UPDATE_MOTIONS("Update Motions"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_ANIMATION("Update Animation"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_HIDDEN_ANIMATION("Update Hidden Anim"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_MOTIONS("Update Motions"); void LLCharacter::updateMotions(e_update_t update_type) { @@ -190,11 +186,11 @@ void LLCharacter::updateMotions(e_update_t update_type) // It returns false if we need to keep updating anyway. if (!mMotionController.hidden(true)) { - mMotionController.updateMotions(LLCharacter::NORMAL_UPDATE); + mMotionController.updateMotions(); return; } // - LLFastTimer t(FTM_UPDATE_HIDDEN_ANIMATION); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_HIDDEN_ANIMATION); mMotionController.updateMotionsMinimal(); } else @@ -204,7 +200,7 @@ void LLCharacter::updateMotions(e_update_t update_type) // to keep updating if they are synchronized with us, even if they are hidden. mMotionController.hidden(false); // - LLFastTimer t(FTM_UPDATE_ANIMATION); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_ANIMATION); // unpause if the number of outstanding pause requests has dropped to the initial one if (mMotionController.isPaused() && mPauseRequest->getNumRefs() == 1) { @@ -212,7 +208,7 @@ void LLCharacter::updateMotions(e_update_t update_type) } bool force_update = (update_type == FORCE_UPDATE); { - LLFastTimer t(FTM_UPDATE_MOTIONS); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_MOTIONS); mMotionController.updateMotions(force_update); } } diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index 2bcd2d28db..340b96a5e4 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -182,7 +182,7 @@ class LLCharacter virtual LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset) { return LLVector3::zero; } - virtual LLJoint* findCollisionVolume(U32 volume_id) { return NULL; } + virtual LLJoint* findCollisionVolume(S32 volume_id) { return NULL; } virtual S32 getCollisionVolumeID(std::string &name) { return -1; } @@ -267,7 +267,6 @@ class LLCharacter void setSkeletonSerialNum( U32 num ) { mSkeletonSerialNum = num; } static std::vector< LLCharacter* > sInstances; - static BOOL sAllowInstancesChange ; //debug use virtual void setHoverOffset(const LLVector3& hover_offset, bool send_update=true) { mHoverOffset = hover_offset; } const LLVector3& getHoverOffset() const { return mHoverOffset; } diff --git a/indra/llcharacter/lleditingmotion.cpp b/indra/llcharacter/lleditingmotion.cpp index 8813064dd6..95580ac75d 100644 --- a/indra/llcharacter/lleditingmotion.cpp +++ b/indra/llcharacter/lleditingmotion.cpp @@ -225,6 +225,7 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask) LL_CONT << "NULL"; } LL_CONT << LL_ENDL; + target.setVec(1.f, 1.f, 1.f); } mTarget.setPosition( target + mParentJoint.getPosition()); @@ -239,7 +240,7 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask) mIKSolver.solve(); // use blending... - F32 slerp_amt = LLCriticalDamp::getInterpolant(TARGET_LAG_HALF_LIFE); + F32 slerp_amt = LLSmoothInterpolation::getInterpolant(TARGET_LAG_HALF_LIFE); shoulderRot = slerp(slerp_amt, mShoulderJoint.getRotation(), shoulderRot); elbowRot = slerp(slerp_amt, mElbowJoint.getRotation(), elbowRot); diff --git a/indra/llcharacter/llheadrotmotion.cpp b/indra/llcharacter/llheadrotmotion.cpp index ef670f1580..0f11bd2951 100644 --- a/indra/llcharacter/llheadrotmotion.cpp +++ b/indra/llcharacter/llheadrotmotion.cpp @@ -80,13 +80,14 @@ LLHeadRotMotion::LLHeadRotMotion(LLUUID const& id, LLMotionController* controlle AIMaskedMotion(id, controller, ANIM_AGENT_HEAD_ROT), mCharacter(NULL), mTorsoJoint(NULL), - mHeadJoint(NULL) + mHeadJoint(NULL), + mRootJoint(NULL), + mPelvisJoint(NULL), + mHeadState(new LLJointState), + mTorsoState(new LLJointState), + mNeckState(new LLJointState) { mName = "head_rot"; - - mTorsoState = new LLJointState; - mNeckState = new LLJointState; - mHeadState = new LLJointState; } @@ -181,8 +182,8 @@ BOOL LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask) LLQuaternion currentRootRotWorld = mRootJoint->getWorldRotation(); LLQuaternion currentInvRootRotWorld = ~currentRootRotWorld; - F32 head_slerp_amt = LLCriticalDamp::getInterpolant(HEAD_LOOKAT_LAG_HALF_LIFE); - F32 torso_slerp_amt = LLCriticalDamp::getInterpolant(TORSO_LOOKAT_LAG_HALF_LIFE); + F32 head_slerp_amt = LLSmoothInterpolation::getInterpolant(HEAD_LOOKAT_LAG_HALF_LIFE); + F32 torso_slerp_amt = LLSmoothInterpolation::getInterpolant(TORSO_LOOKAT_LAG_HALF_LIFE); LLVector3* targetPos = (LLVector3*)mCharacter->getAnimationData("LookAtPoint"); @@ -279,7 +280,9 @@ LLEyeMotion::LLEyeMotion(LLUUID const& id, LLMotionController* controller) : AIM mName = "eye_rot"; mLeftEyeState = new LLJointState; + mAltLeftEyeState = new LLJointState; mRightEyeState = new LLJointState; + mAltRightEyeState = new LLJointState; } @@ -312,32 +315,135 @@ LLMotion::LLMotionInitStatus LLEyeMotion::onInitialize(LLCharacter *character) return STATUS_FAILURE; } + mAltLeftEyeState->setJoint( character->getJoint("mFaceEyeAltLeft") ); + if ( ! mAltLeftEyeState->getJoint() ) + { + LL_INFOS() << getName() << ": Can't get alt left eyeball joint." << LL_ENDL; + return STATUS_FAILURE; + } + mRightEyeState->setJoint( character->getJoint("mEyeRight") ); if ( ! mRightEyeState->getJoint() ) { - LL_INFOS() << getName() << ": Can't get Right eyeball joint." << LL_ENDL; + LL_INFOS() << getName() << ": Can't get right eyeball joint." << LL_ENDL; + return STATUS_FAILURE; + } + + mAltRightEyeState->setJoint( character->getJoint("mFaceEyeAltRight") ); + if ( ! mAltRightEyeState->getJoint() ) + { + LL_INFOS() << getName() << ": Can't get alt right eyeball joint." << LL_ENDL; return STATUS_FAILURE; } mLeftEyeState->setUsage(LLJointState::ROT); + mAltLeftEyeState->setUsage(LLJointState::ROT); + mRightEyeState->setUsage(LLJointState::ROT); + mAltRightEyeState->setUsage(LLJointState::ROT); addJointState( mLeftEyeState ); + addJointState( mAltLeftEyeState ); + addJointState( mRightEyeState ); + addJointState( mAltRightEyeState ); return STATUS_SUCCESS; } + //----------------------------------------------------------------------------- -// LLEyeMotion::onUpdate() +// LLEyeMotion::adjustEyeTarget() //----------------------------------------------------------------------------- -BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask) +void LLEyeMotion::adjustEyeTarget(LLVector3* targetPos, LLJointState& left_eye_state, LLJointState& right_eye_state) { // Compute eye rotation. + BOOL has_eye_target = FALSE; LLQuaternion target_eye_rot; LLVector3 eye_look_at; F32 vergence; + if (targetPos) + { + LLVector3 skyward(0.f, 0.f, 1.f); + LLVector3 left; + LLVector3 up; + + eye_look_at = *targetPos; + has_eye_target = TRUE; + F32 lookAtDistance = eye_look_at.normVec(); + + left.setVec(skyward % eye_look_at); + up.setVec(eye_look_at % left); + + target_eye_rot = LLQuaternion(eye_look_at, left, up); + // convert target rotation to head-local coordinates + target_eye_rot *= ~mHeadJoint->getWorldRotation(); + // eliminate any Euler roll - we're lucky that roll is applied last. + F32 roll, pitch, yaw; + target_eye_rot.getEulerAngles(&roll, &pitch, &yaw); + target_eye_rot.setQuat(0.0f, pitch, yaw); + // constrain target orientation to be in front of avatar's face + target_eye_rot.constrain(EYE_ROT_LIMIT_ANGLE); + + // calculate vergence + F32 interocular_dist = (left_eye_state.getJoint()->getWorldPosition() - right_eye_state.getJoint()->getWorldPosition()).magVec(); + vergence = -atan2((interocular_dist / 2.f), lookAtDistance); + vergence = llclamp(vergence, -F_PI_BY_TWO, 0.f); + } + else + { + target_eye_rot = LLQuaternion::DEFAULT; + vergence = 0.f; + } + + //RN: subtract 4 degrees to account for foveal angular offset relative to pupil + vergence += 4.f * DEG_TO_RAD; + + // calculate eye jitter + LLQuaternion eye_jitter_rot; + + // vergence not too high... + if (vergence > -0.05f) + { + //...go ahead and jitter + eye_jitter_rot.setQuat(0.f, mEyeJitterPitch + mEyeLookAwayPitch, mEyeJitterYaw + mEyeLookAwayYaw); + } + else + { + //...or don't + eye_jitter_rot.loadIdentity(); + } + + // calculate vergence of eyes as an object gets closer to the avatar's head + LLQuaternion vergence_quat; + + if (has_eye_target) + { + vergence_quat.setQuat(vergence, LLVector3(0.f, 0.f, 1.f)); + } + else + { + vergence_quat.loadIdentity(); + } + + // calculate eye rotations + LLQuaternion left_eye_rot = target_eye_rot; + left_eye_rot = vergence_quat * eye_jitter_rot * left_eye_rot; + + LLQuaternion right_eye_rot = target_eye_rot; + vergence_quat.transQuat(); + right_eye_rot = vergence_quat * eye_jitter_rot * right_eye_rot; + + left_eye_state.setRotation( left_eye_rot ); + right_eye_state.setRotation( right_eye_rot ); +} + +//----------------------------------------------------------------------------- +// LLEyeMotion::onUpdate() +//----------------------------------------------------------------------------- +BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask) +{ //calculate jitter if (mEyeJitterTimer.getElapsedTimeF32() > mEyeJitterTime) { @@ -410,83 +516,10 @@ BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask) } } - BOOL has_eye_target = FALSE; LLVector3* targetPos = (LLVector3*)mCharacter->getAnimationData("LookAtPoint"); - if (targetPos) - { - LLVector3 skyward(0.f, 0.f, 1.f); - LLVector3 left; - LLVector3 up; - - eye_look_at = *targetPos; - has_eye_target = TRUE; - F32 lookAtDistance = eye_look_at.normVec(); - - left.setVec(skyward % eye_look_at); - up.setVec(eye_look_at % left); - - target_eye_rot = LLQuaternion(eye_look_at, left, up); - // convert target rotation to head-local coordinates - target_eye_rot *= ~mHeadJoint->getWorldRotation(); - // eliminate any Euler roll - we're lucky that roll is applied last. - F32 roll, pitch, yaw; - target_eye_rot.getEulerAngles(&roll, &pitch, &yaw); - target_eye_rot.setQuat(0.0f, pitch, yaw); - // constrain target orientation to be in front of avatar's face - target_eye_rot.constrain(EYE_ROT_LIMIT_ANGLE); - - // calculate vergence - F32 interocular_dist = (mLeftEyeState->getJoint()->getWorldPosition() - mRightEyeState->getJoint()->getWorldPosition()).magVec(); - vergence = -atan2((interocular_dist / 2.f), lookAtDistance); - llclamp(vergence, -F_PI_BY_TWO, 0.f); - } - else - { - target_eye_rot = LLQuaternion::DEFAULT; - vergence = 0.f; - } - - //RN: subtract 4 degrees to account for foveal angular offset relative to pupil - vergence += 4.f * DEG_TO_RAD; - - // calculate eye jitter - LLQuaternion eye_jitter_rot; - - // vergence not too high... - if (vergence > -0.05f) - { - //...go ahead and jitter - eye_jitter_rot.setQuat(0.f, mEyeJitterPitch + mEyeLookAwayPitch, mEyeJitterYaw + mEyeLookAwayYaw); - } - else - { - //...or don't - eye_jitter_rot.loadIdentity(); - } - - // calculate vergence of eyes as an object gets closer to the avatar's head - LLQuaternion vergence_quat; - - if (has_eye_target) - { - vergence_quat.setQuat(vergence, LLVector3(0.f, 0.f, 1.f)); - } - else - { - vergence_quat.loadIdentity(); - } - - // calculate eye rotations - LLQuaternion left_eye_rot = target_eye_rot; - left_eye_rot = vergence_quat * eye_jitter_rot * left_eye_rot; - - LLQuaternion right_eye_rot = target_eye_rot; - vergence_quat.transQuat(); - right_eye_rot = vergence_quat * eye_jitter_rot * right_eye_rot; - - mLeftEyeState->setRotation( left_eye_rot ); - mRightEyeState->setRotation( right_eye_rot ); + adjustEyeTarget(targetPos, *mLeftEyeState, *mRightEyeState); + adjustEyeTarget(targetPos, *mAltLeftEyeState, *mAltRightEyeState); return TRUE; } @@ -503,12 +536,24 @@ void LLEyeMotion::onDeactivate() joint->setRotation(LLQuaternion::DEFAULT); } + joint = mAltLeftEyeState->getJoint(); + if (joint) + { + joint->setRotation(LLQuaternion::DEFAULT); + } + joint = mRightEyeState->getJoint(); if (joint) { joint->setRotation(LLQuaternion::DEFAULT); } + joint = mAltRightEyeState->getJoint(); + if (joint) + { + joint->setRotation(LLQuaternion::DEFAULT); + } + AIMaskedMotion::onDeactivate(); } diff --git a/indra/llcharacter/llheadrotmotion.h b/indra/llcharacter/llheadrotmotion.h index 5fa4610bff..9b00c4c4cd 100644 --- a/indra/llcharacter/llheadrotmotion.h +++ b/indra/llcharacter/llheadrotmotion.h @@ -169,6 +169,9 @@ class LLEyeMotion : // must return true to indicate success and be available for activation virtual LLMotionInitStatus onInitialize(LLCharacter *character); + + void adjustEyeTarget(LLVector3* targetPos, LLJointState& left_eye_state, LLJointState& right_eye_state); + // called per time step // must return TRUE while it is active, and // must return FALSE when the motion is completed. @@ -186,6 +189,8 @@ class LLEyeMotion : LLJoint *mHeadJoint; LLPointer mLeftEyeState; LLPointer mRightEyeState; + LLPointer mAltLeftEyeState; + LLPointer mAltRightEyeState; LLFrameTimer mEyeJitterTimer; F32 mEyeJitterTime; diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 0175a2fe43..0aada2fe86 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -32,10 +32,68 @@ #include "lljoint.h" #include "llmath.h" +#include S32 LLJoint::sNumUpdates = 0; S32 LLJoint::sNumTouches = 0; +template +bool attachment_map_iter_compare_key(const T& a, const T& b) +{ + return a.first < b.first; +} + +bool LLVector3OverrideMap::findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const +{ + pos = LLVector3(0,0,0); + mesh_id = LLUUID(); + bool found = false; + + map_type::const_iterator it = std::max_element(m_map.begin(), + m_map.end(), + attachment_map_iter_compare_key); + if (it != m_map.end()) + { + found = true; + pos = it->second; + mesh_id = it->first; + } + return found; +} + +void LLVector3OverrideMap::showJointVector3Overrides( std::ostringstream& os ) const +{ + map_type::const_iterator max_it = std::max_element(m_map.begin(), + m_map.end(), + attachment_map_iter_compare_key); + for (map_type::const_iterator it = m_map.begin(); + it != m_map.end(); ++it) + { + const LLVector3& pos = it->second; + os << " " << "[" << it->first <<": " << pos << "]" << ((it==max_it) ? "*" : ""); + } +} + +U32 LLVector3OverrideMap::count() const +{ + return m_map.size(); +} + +void LLVector3OverrideMap::add(const LLUUID& mesh_id, const LLVector3& pos) +{ + m_map[mesh_id] = pos; +} + +bool LLVector3OverrideMap::remove(const LLUUID& mesh_id) +{ + U32 remove_count = m_map.erase(mesh_id); + return (remove_count > 0); +} + +void LLVector3OverrideMap::clear() +{ + m_map.clear(); +} //----------------------------------------------------------------------------- // LLJoint() // Class Constructor @@ -50,6 +108,8 @@ void LLJoint::init() mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f)); mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY; mUpdateXform = TRUE; + mSupport = SUPPORT_BASE; + mEnd = LLVector3(0.0f, 0.0f, 0.0f); } LLJoint::LLJoint() : @@ -57,7 +117,6 @@ LLJoint::LLJoint() : { init(); touch(); - mResetAfterRestoreOldXform = false; } LLJoint::LLJoint(S32 joint_num) : @@ -65,7 +124,6 @@ LLJoint::LLJoint(S32 joint_num) : { init(); touch(); - mResetAfterRestoreOldXform = false; } @@ -74,7 +132,7 @@ LLJoint::LLJoint(S32 joint_num) : // Class Constructor //----------------------------------------------------------------------------- LLJoint::LLJoint(const std::string &name, LLJoint *parent) : - mJointNum(0) + mJointNum(-2) { init(); mUpdateXform = FALSE; @@ -114,6 +172,27 @@ void LLJoint::setup(const std::string &name, LLJoint *parent) } } +//----------------------------------------------------------------------------- +// setSupport() +//----------------------------------------------------------------------------- +void LLJoint::setSupport(const std::string& support_name) +{ + if (support_name == "extended") + { + setSupport(SUPPORT_EXTENDED); + } + else if (support_name == "base") + { + setSupport(SUPPORT_BASE); + } + else + { + LL_WARNS() << "unknown support string " << support_name << LL_ENDL; + setSupport(SUPPORT_BASE); + } +} + + //----------------------------------------------------------------------------- // touch() // Sets all dirty flags for all children, recursively. @@ -139,6 +218,18 @@ void LLJoint::touch(U32 flags) } } +//----------------------------------------------------------------------------- +// setJointNum() +//----------------------------------------------------------------------------- +void LLJoint::setJointNum(S32 joint_num) +{ + mJointNum = joint_num; + if (mJointNum + 2 >= LL_CHARACTER_MAX_ANIMATED_JOINTS) + { + LL_INFOS() << "LL_CHARACTER_MAX_ANIMATED_JOINTS needs to be increased" << LL_ENDL; + LL_ERRS() << "joint_num " << joint_num << " + 2 is too large for " << LL_CHARACTER_MAX_ANIMATED_JOINTS << LL_ENDL; + } +} //----------------------------------------------------------------------------- // getRoot() //----------------------------------------------------------------------------- @@ -184,6 +275,7 @@ void LLJoint::addChild(LLJoint* joint) joint->mParent->removeChild(joint); mChildren.push_back(joint); + //LL_INFOS() << getName() << " +child " << joint->getName() << LL_ENDL; joint->mXform.setParent(&mXform); joint->mParent = this; joint->touch(); @@ -199,7 +291,7 @@ void LLJoint::removeChild(LLJoint* joint) if (iter != mChildren.end()) { mChildren.erase(iter); - + //LL_INFOS() << getName() << " -child " << joint->getName() << LL_ENDL; joint->mXform.setParent(NULL); joint->mParent = NULL; joint->touch(); @@ -218,6 +310,7 @@ void LLJoint::removeAllChildren() child_list_t::iterator curiter = iter++; LLJoint* joint = *curiter; mChildren.erase(curiter); + //LL_INFOS() << getName() << " -child " << joint->getName() << LL_ENDL; joint->mXform.setParent(NULL); joint->mParent = NULL; joint->touch(); @@ -233,54 +326,436 @@ const LLVector3& LLJoint::getPosition() return mXform.getPosition(); } +bool do_debug_joint(const std::string& name) +{ + if (std::find(LLJoint::s_debugJointNames.begin(), LLJoint::s_debugJointNames.end(),name) != LLJoint::s_debugJointNames.end()) + { + return true; + } + return false; +} //-------------------------------------------------------------------- // setPosition() //-------------------------------------------------------------------- -void LLJoint::setPosition( const LLVector3& pos ) +void LLJoint::setPosition( const LLVector3& requested_pos, bool apply_attachment_overrides ) { -// if (mXform.getPosition() != pos) + LLVector3 pos(requested_pos); + + LLVector3 active_override; + LLUUID mesh_id; + if (apply_attachment_overrides && m_attachmentPosOverrides.findActiveOverride(mesh_id,active_override)) + { + if (pos != active_override && do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << " joint " << getName() << " requested_pos " << requested_pos + << " overriden by attachment " << active_override << LL_ENDL; + } + pos = active_override; + } + if ((pos != getPosition()) && do_debug_joint(getName())) { - mXform.setPosition(pos); - touch(MATRIX_DIRTY | POSITION_DIRTY); + LL_DEBUGS("Avatar") << " joint " << getName() << " set pos " << pos << LL_ENDL; } + if (pos != getPosition()) + { + mXform.setPosition(pos); + touch(MATRIX_DIRTY | POSITION_DIRTY); + } } +void LLJoint::setDefaultPosition( const LLVector3& pos ) +{ + mDefaultPosition = pos; +} + +const LLVector3& LLJoint::getDefaultPosition() const +{ + return mDefaultPosition; +} + +void LLJoint::setDefaultScale( const LLVector3& scale ) +{ + mDefaultScale = scale; +} + +const LLVector3& LLJoint::getDefaultScale() const +{ + return mDefaultScale; +} + +void showJointPosOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info ) +{ + std::ostringstream os; + os << joint.m_posBeforeOverrides; + joint.m_attachmentPosOverrides.showJointVector3Overrides(os); + LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL; +} + +void showJointScaleOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info ) +{ + std::ostringstream os; + os << joint.m_scaleBeforeOverrides; + joint.m_attachmentScaleOverrides.showJointVector3Overrides(os); + LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL; +} + +bool LLJoint::aboveJointPosThreshold(const LLVector3& pos) const +{ + LLVector3 diff = pos - getDefaultPosition(); + const F32 max_joint_pos_offset = 0.0001f; // 0.1 mm + return diff.lengthSquared() > max_joint_pos_offset * max_joint_pos_offset; +} + +bool LLJoint::aboveJointScaleThreshold(const LLVector3& scale) const +{ + LLVector3 diff = scale - getDefaultScale(); + const F32 max_joint_scale_offset = 0.0001f; // 0.1 mm + return diff.lengthSquared() > max_joint_scale_offset * max_joint_scale_offset; +} //-------------------------------------------------------------------- -// setPosition() +// addAttachmentPosOverride() //-------------------------------------------------------------------- -void LLJoint::setDefaultFromCurrentXform( void ) +void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed ) { - mDefaultXform = mXform; - touch(MATRIX_DIRTY | POSITION_DIRTY); - + active_override_changed = false; + if (mesh_id.isNull()) + { + return; + } + // BENTO + // Not clear pelvis overrides are meaningful/useful. + //if (mName == "mPelvis") + //{ + // return; + //} + + LLVector3 before_pos; + LLUUID before_mesh_id; + bool has_active_override_before = hasAttachmentPosOverride( before_pos, before_mesh_id ); + if (!m_attachmentPosOverrides.count()) + { + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " saving m_posBeforeOverrides " << getPosition() << LL_ENDL; + } + m_posBeforeOverrides = getPosition(); + } + m_attachmentPosOverrides.add(mesh_id,pos); + LLVector3 after_pos; + LLUUID after_mesh_id; + hasAttachmentPosOverride(after_pos, after_mesh_id); + if (!has_active_override_before || (after_pos != before_pos)) + { + active_override_changed = true; + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentPosOverride for mesh " << mesh_id << " pos " << pos << LL_ENDL; + } + updatePos(av_info); + } } //-------------------------------------------------------------------- -// storeCurrentXform() +// removeAttachmentPosOverride() +//-------------------------------------------------------------------- +void LLJoint::removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed ) +{ + active_override_changed = false; + if (mesh_id.isNull()) + { + return; + } + LLVector3 before_pos; + LLUUID before_mesh_id; + hasAttachmentPosOverride( before_pos, before_mesh_id ); + if (m_attachmentPosOverrides.remove(mesh_id)) + { + LLVector3 after_pos; + LLUUID after_mesh_id; + bool has_active_override_after = hasAttachmentPosOverride(after_pos, after_mesh_id); + if (!has_active_override_after || (after_pos != before_pos)) + { + active_override_changed = true; + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() + << " removeAttachmentPosOverride for " << mesh_id << LL_ENDL; + showJointPosOverrides(*this, "remove", av_info); + } + updatePos(av_info); + } + } +} + //-------------------------------------------------------------------- -void LLJoint::storeCurrentXform( const LLVector3& pos ) + // hasAttachmentPosOverride() + //-------------------------------------------------------------------- +bool LLJoint::hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const { - mOldXform = mXform; - mResetAfterRestoreOldXform = true; - setPosition( pos ); + return m_attachmentPosOverrides.findActiveOverride(mesh_id,pos); } + //-------------------------------------------------------------------- -// restoreOldXform() +// clearAttachmentPosOverrides() //-------------------------------------------------------------------- -void LLJoint::restoreOldXform( void ) +void LLJoint::clearAttachmentPosOverrides() { - mResetAfterRestoreOldXform = false; - mXform = mOldXform; + if (m_attachmentPosOverrides.count()) + { + m_attachmentPosOverrides.clear(); + setPosition(m_posBeforeOverrides); + } } + //-------------------------------------------------------------------- -// restoreOldXform() +// getAllAttachmentPosOverrides() //-------------------------------------------------------------------- -void LLJoint::restoreToDefaultXform( void ) -{ - mXform = mDefaultXform; - setPosition( mXform.getPosition() ); +void LLJoint::getAllAttachmentPosOverrides(S32& num_pos_overrides, + std::set& distinct_pos_overrides) +{ + num_pos_overrides = m_attachmentPosOverrides.count(); + LLVector3OverrideMap::map_type::const_iterator it = m_attachmentPosOverrides.getMap().begin(); + for (; it != m_attachmentPosOverrides.getMap().end(); ++it) + { + distinct_pos_overrides.insert(it->second); + } +} + +//-------------------------------------------------------------------- +// getAllAttachmentScaleOverrides() +//-------------------------------------------------------------------- +void LLJoint::getAllAttachmentScaleOverrides(S32& num_scale_overrides, + std::set& distinct_scale_overrides) +{ + num_scale_overrides = m_attachmentScaleOverrides.count(); + LLVector3OverrideMap::map_type::const_iterator it = m_attachmentScaleOverrides.getMap().begin(); + for (; it != m_attachmentScaleOverrides.getMap().end(); ++it) + { + distinct_scale_overrides.insert(it->second); + } +} + +//-------------------------------------------------------------------- +// showAttachmentPosOverrides() +//-------------------------------------------------------------------- +void LLJoint::showAttachmentPosOverrides(const std::string& av_info) const +{ + LLVector3 active_override; + bool has_active_override; + LLUUID mesh_id; + has_active_override = m_attachmentPosOverrides.findActiveOverride(mesh_id,active_override); + U32 count = m_attachmentPosOverrides.count(); + if (count==1) + { + LLVector3OverrideMap::map_type::const_iterator it = m_attachmentPosOverrides.getMap().begin(); + std::string highlight = (has_active_override && (it->second == active_override)) ? "*" : ""; + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() + << " has single attachment pos override " << highlight << "" << it->second << " default " << mDefaultPosition << LL_ENDL; + } + else if (count>1) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " has " << count << " attachment pos overrides" << LL_ENDL; + std::set distinct_offsets; + LLVector3OverrideMap::map_type::const_iterator it = m_attachmentPosOverrides.getMap().begin(); + for (; it != m_attachmentPosOverrides.getMap().end(); ++it) + { + distinct_offsets.insert(it->second); + } + if (distinct_offsets.size()>1) + { + LL_DEBUGS("Avatar") << "CONFLICTS, " << distinct_offsets.size() << " different values" << LL_ENDL; + } + else + { + LL_DEBUGS("Avatar") << "no conflicts" << LL_ENDL; + } + std::set::iterator dit = distinct_offsets.begin(); + for ( ; dit != distinct_offsets.end(); ++dit) + { + std::string highlight = (has_active_override && *dit == active_override) ? "*" : ""; + LL_DEBUGS("Avatar") << " POS " << highlight << "" << (*dit) << " default " << mDefaultPosition << LL_ENDL; + } + } +} + +//-------------------------------------------------------------------- +// updatePos() +//-------------------------------------------------------------------- +void LLJoint::updatePos(const std::string& av_info) +{ + LLVector3 pos, found_pos; + LLUUID mesh_id; + if (m_attachmentPosOverrides.findActiveOverride(mesh_id,found_pos)) + { + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner of " << m_attachmentPosOverrides.count() << " is mesh " << mesh_id << " pos " << found_pos << LL_ENDL; + } + pos = found_pos; + } + else + { + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner is posBeforeOverrides " << m_posBeforeOverrides << LL_ENDL; + } + pos = m_posBeforeOverrides; + } + setPosition(pos); +} + +//-------------------------------------------------------------------- +// updateScale() +//-------------------------------------------------------------------- +void LLJoint::updateScale(const std::string& av_info) +{ + LLVector3 scale, found_scale; + LLUUID mesh_id; + if (m_attachmentScaleOverrides.findActiveOverride(mesh_id,found_scale)) + { + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updateScale, winner of " << m_attachmentScaleOverrides.count() << " is mesh " << mesh_id << " scale " << found_scale << LL_ENDL; + } + scale = found_scale; + } + else + { + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updateScale, winner is scaleBeforeOverrides " << m_scaleBeforeOverrides << LL_ENDL; + } + scale = m_scaleBeforeOverrides; + } + setScale(scale); +} + +//-------------------------------------------------------------------- +// addAttachmentScaleOverride() +//-------------------------------------------------------------------- +void LLJoint::addAttachmentScaleOverride( const LLVector3& scale, const LLUUID& mesh_id, const std::string& av_info ) +{ + if (mesh_id.isNull()) + { + return; + } + if (!m_attachmentScaleOverrides.count()) + { + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " saving m_scaleBeforeOverrides " << getScale() << LL_ENDL; + } + m_scaleBeforeOverrides = getScale(); + } + m_attachmentScaleOverrides.add(mesh_id,scale); + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentScaleOverride for mesh " << mesh_id << " scale " << scale << LL_ENDL; + } + updateScale(av_info); +} + +//-------------------------------------------------------------------- +// removeAttachmentScaleOverride() +//-------------------------------------------------------------------- +void LLJoint::removeAttachmentScaleOverride( const LLUUID& mesh_id, const std::string& av_info ) +{ + if (mesh_id.isNull()) + { + return; + } + if (m_attachmentScaleOverrides.remove(mesh_id)) + { + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() + << " removeAttachmentScaleOverride for " << mesh_id << LL_ENDL; + showJointScaleOverrides(*this, "remove", av_info); + } + updateScale(av_info); + } +} + +//-------------------------------------------------------------------- + // hasAttachmentScaleOverride() + //-------------------------------------------------------------------- +bool LLJoint::hasAttachmentScaleOverride( LLVector3& scale, LLUUID& mesh_id ) const +{ + return m_attachmentScaleOverrides.findActiveOverride(mesh_id,scale); +} + +//-------------------------------------------------------------------- +// clearAttachmentScaleOverrides() +//-------------------------------------------------------------------- +void LLJoint::clearAttachmentScaleOverrides() +{ + if (m_attachmentScaleOverrides.count()) + { + m_attachmentScaleOverrides.clear(); + setScale(m_scaleBeforeOverrides); + } +} + +//-------------------------------------------------------------------- +// showAttachmentScaleOverrides() +//-------------------------------------------------------------------- +void LLJoint::showAttachmentScaleOverrides(const std::string& av_info) const +{ + LLVector3 active_override; + bool has_active_override; + LLUUID mesh_id; + has_active_override = m_attachmentScaleOverrides.findActiveOverride(mesh_id,active_override); + U32 count = m_attachmentScaleOverrides.count(); + if (count==1) + { + LLVector3OverrideMap::map_type::const_iterator it = m_attachmentScaleOverrides.getMap().begin(); + std::string highlight = (has_active_override && (it->second == active_override)) ? "*" : ""; + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() + << " has single attachment scale override " << highlight << "" << it->second << " default " << mDefaultScale << LL_ENDL; + } + else if (count>1) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " has " << count << " attachment scale overrides" << LL_ENDL; + std::set distinct_offsets; + LLVector3OverrideMap::map_type::const_iterator it = m_attachmentScaleOverrides.getMap().begin(); + for (; it != m_attachmentScaleOverrides.getMap().end(); ++it) + { + distinct_offsets.insert(it->second); + } + if (distinct_offsets.size()>1) + { + LL_DEBUGS("Avatar") << "CONFLICTS, " << distinct_offsets.size() << " different values" << LL_ENDL; + } + else + { + LL_DEBUGS("Avatar") << "no conflicts" << LL_ENDL; + } + std::set::iterator dit = distinct_offsets.begin(); + for ( ; dit != distinct_offsets.end(); ++dit) + { + std::string highlight = (has_active_override && *dit == active_override) ? "*" : ""; + LL_DEBUGS("Avatar") << " POS " << highlight << "" << (*dit) << " default " << mDefaultScale << LL_ENDL; + } + } +} + +// init static +LLJoint::debug_joint_name_t LLJoint::s_debugJointNames = debug_joint_name_t(); + +//-------------------------------------------------------------------- +// setDebugJointNames +//-------------------------------------------------------------------- +void LLJoint::setDebugJointNames(const debug_joint_name_t& names) +{ + s_debugJointNames = names; +} +void LLJoint::setDebugJointNames(const std::string& names_string) +{ + debug_joint_name_t names; + boost::split(names, names_string, boost::is_any_of(" :,")); + setDebugJointNames(names); } //-------------------------------------------------------------------- @@ -406,13 +881,22 @@ const LLVector3& LLJoint::getScale() //-------------------------------------------------------------------- // setScale() //-------------------------------------------------------------------- -void LLJoint::setScale( const LLVector3& scale ) +void LLJoint::setScale( const LLVector3& requested_scale, bool apply_attachment_overrides ) { -// if (mXform.getScale() != scale) - { - mXform.setScale(scale); - touch(); - } + LLVector3 scale(requested_scale); + LLUUID mesh_id; + LLVector3 active_override; + if (apply_attachment_overrides && m_attachmentScaleOverrides.findActiveOverride(mesh_id,active_override)) + { + if (scale != active_override && do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << " joint " << getName() << " requested_scale " << requested_scale + << " overriden by attachment " << active_override << LL_ENDL; + } + scale = active_override; + } + mXform.setScale(scale); + touch(); } diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 2196f47bbb..6beffc9f6f 100644 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -40,12 +40,46 @@ #include "xform.h" const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; -const U32 LL_CHARACTER_MAX_JOINTS = 32; // must be divisible by 4! -const U32 LL_HAND_JOINT_NUM = 31; -const U32 LL_FACE_JOINT_NUM = 30; +// Need to set this to count of animate-able joints, +// currently = #bones + #collision_volumes + #attachments + 2, +// rounded to next multiple of 4. +const U32 LL_CHARACTER_MAX_ANIMATED_JOINTS = 216; // must be divisible by 4! +const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 110; + +// These should be higher than the joint_num of any +// other joint, to avoid conflicts in updateMotionsByType() +const U32 LL_HAND_JOINT_NUM = (LL_CHARACTER_MAX_ANIMATED_JOINTS-1); +const U32 LL_FACE_JOINT_NUM = (LL_CHARACTER_MAX_ANIMATED_JOINTS-2); const S32 LL_CHARACTER_MAX_PRIORITY = 7; const F32 LL_MAX_PELVIS_OFFSET = 5.f; +class LLVector3OverrideMap +{ +public: + LLVector3OverrideMap() {} + bool findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const; + void showJointVector3Overrides(std::ostringstream& os) const; + U32 count() const; + void add(const LLUUID& mesh_id, const LLVector3& pos); + bool remove(const LLUUID& mesh_id); + void clear(); + + typedef std::map map_type; + const map_type& getMap() const { return m_map; } +private: + map_type m_map; +}; + +inline bool operator==(const LLVector3OverrideMap& a, const LLVector3OverrideMap& b) +{ + return a.getMap() == b.getMap(); +} + +inline bool operator!=(const LLVector3OverrideMap& a, const LLVector3OverrideMap& b) +{ + return !(a == b); +} + //----------------------------------------------------------------------------- // class LLJoint //----------------------------------------------------------------------------- @@ -71,28 +105,37 @@ class LLJoint POSITION_DIRTY = 0x1 << 2, ALL_DIRTY = 0x7 }; +public: + enum SupportCategory + { + SUPPORT_BASE, + SUPPORT_EXTENDED + }; protected: std::string mName; + SupportCategory mSupport; + // parent joint LLJoint *mParent; // explicit transformation members LLXformMatrix mXform; - LLXformMatrix mOldXform; - LLXformMatrix mDefaultXform; - - LLUUID mId; + LLVector3 mDefaultPosition; + LLVector3 mDefaultScale; + public: U32 mDirtyFlags; BOOL mUpdateXform; - BOOL mResetAfterRestoreOldXform; - // describes the skin binding pose LLVector3 mSkinOffset; + // Endpoint of the bone, if applicable. This is only relevant for + // external programs like Blender, and for diagnostic display. + LLVector3 mEnd; + S32 mJointNum; // child joints @@ -102,6 +145,21 @@ class LLJoint // debug statics static S32 sNumTouches; static S32 sNumUpdates; + typedef std::set debug_joint_name_t; + static debug_joint_name_t s_debugJointNames; + static void setDebugJointNames(const debug_joint_name_t& names); + static void setDebugJointNames(const std::string& names_string); + + // Position overrides + LLVector3OverrideMap m_attachmentPosOverrides; + LLVector3 m_posBeforeOverrides; + + // Scale overrides + LLVector3OverrideMap m_attachmentScaleOverrides; + LLVector3 m_scaleBeforeOverrides; + + void updatePos(const std::string& av_info); + void updateScale(const std::string& av_info); public: LLJoint(); @@ -123,6 +181,19 @@ class LLJoint const std::string& getName() const { return mName; } void setName( const std::string &name ) { mName = name; } + // joint num + S32 getJointNum() const { return mJointNum; } + void setJointNum(S32 joint_num); + + // get/set support + SupportCategory getSupport() const { return mSupport; } + void setSupport( const SupportCategory& support) { mSupport = support; } + void setSupport( const std::string& support_string); + + // get/set end point + void setEnd( const LLVector3& end) { mEnd = end; } + const LLVector3& getEnd() const { return mEnd; } + // getParent LLJoint *getParent() { return mParent; } @@ -139,10 +210,16 @@ class LLJoint // get/set local position const LLVector3& getPosition(); - void setPosition( const LLVector3& pos ); - + void setPosition( const LLVector3& pos, bool apply_attachment_overrides = false ); + + // Tracks the default position defined by the skeleton void setDefaultPosition( const LLVector3& pos ); - + const LLVector3& getDefaultPosition() const; + + // Tracks the default scale defined by the skeleton + void setDefaultScale( const LLVector3& scale ); + const LLVector3& getDefaultScale() const; + // get/set world position LLVector3 getWorldPosition(); LLVector3 getLastWorldPosition(); @@ -159,7 +236,7 @@ class LLJoint // get/set local scale const LLVector3& getScale(); - void setScale( const LLVector3& scale ); + void setScale( const LLVector3& scale, bool apply_attachment_overrides = false ); // get/set world matrix const LLMatrix4a &getWorldMatrix(); @@ -182,26 +259,28 @@ class LLJoint virtual BOOL isAnimatable() const { return TRUE; } - S32 getJointNum() const { return mJointNum; } - - void restoreOldXform( void ); - void restoreToDefaultXform( void ); - void setDefaultFromCurrentXform( void ); - void storeCurrentXform( const LLVector3& pos ); - - //Accessor for the joint id - LLUUID getId( void ) { return mId; } - //Setter for the joints id - void setId( const LLUUID& id ) { mId = id;} - - //If the old transform flag has been set, then the reset logic in avatar needs to be aware(test) of it - const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; } - //Setter for joint reset flag - void setJointToBeReset( BOOL val ) { mResetAfterRestoreOldXform = val; } - - // - std::string exportString(U32 tabs = 0); - // + void addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed ); + void removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed ); + bool hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const; + void clearAttachmentPosOverrides(); + void showAttachmentPosOverrides(const std::string& av_info) const; + + void addAttachmentScaleOverride( const LLVector3& scale, const LLUUID& mesh_id, const std::string& av_info ); + void removeAttachmentScaleOverride( const LLUUID& mesh_id, const std::string& av_info ); + bool hasAttachmentScaleOverride( LLVector3& scale, LLUUID& mesh_id ) const; + void clearAttachmentScaleOverrides(); + void showAttachmentScaleOverrides(const std::string& av_info) const; + + void getAllAttachmentPosOverrides(S32& num_pos_overrides, + std::set& distinct_pos_overrides); + void getAllAttachmentScaleOverrides(S32& num_scale_overrides, + std::set& distinct_scale_overrides); + + // These are used in checks of whether a pos/scale override is considered significant. + bool aboveJointPosThreshold(const LLVector3& pos) const; + bool aboveJointScaleThreshold(const LLVector3& scale) const; + + std::string exportString(U32 tabs); }; #endif // LL_LLJOINT_H diff --git a/indra/llcharacter/lljointstate.h b/indra/llcharacter/lljointstate.h index e40cf2673f..120430ed16 100644 --- a/indra/llcharacter/lljointstate.h +++ b/indra/llcharacter/lljointstate.h @@ -70,22 +70,18 @@ class LLJointState : public LLRefCount public: // Constructor LLJointState() - { - mUsage = 0; - mJoint = NULL; - mUsage = 0; - mWeight = 0.f; - mPriority = LLJoint::USE_MOTION_PRIORITY; - } + : mJoint(NULL) + , mUsage(0) + , mWeight(0.f) + , mPriority(LLJoint::USE_MOTION_PRIORITY) + {} LLJointState(LLJoint* joint) - { - mUsage = 0; - mJoint = joint; - mUsage = 0; - mWeight = 0.f; - mPriority = LLJoint::USE_MOTION_PRIORITY; - } + : mJoint(joint) + , mUsage(0) + , mWeight(0.f) + , mPriority(LLJoint::USE_MOTION_PRIORITY) + {} // joint that this state is applied to LLJoint* getJoint() { return mJoint; } diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index f1cea2f6da..1c842e6b8d 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -42,6 +42,7 @@ #include "llvfile.h" #include "m3math.h" #include "message.h" +#include //----------------------------------------------------------------------------- // Static Definitions @@ -137,257 +138,6 @@ U32 LLKeyframeMotion::JointMotionList::dumpDiagInfo(bool silent) const return total_size; } -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// ****Curve classes -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// ScaleCurve::ScaleCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::ScaleCurve::ScaleCurve() -{ - mInterpolationType = LLKeyframeMotion::IT_LINEAR; - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// ScaleCurve::~ScaleCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::ScaleCurve::~ScaleCurve() -{ - mKeys.clear(); - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// getValue() -//----------------------------------------------------------------------------- -LLVector3 LLKeyframeMotion::ScaleCurve::getValue(F32 time, F32 duration) -{ - LLVector3 value; - - if (mKeys.empty()) - { - value.clearVec(); - return value; - } - - key_map_t::iterator right = mKeys.lower_bound(time); - if (right == mKeys.end()) - { - // Past last key - --right; - value = right->second.mScale; - } - else if (right == mKeys.begin() || right->first == time) - { - // Before first key or exactly on a key - value = right->second.mScale; - } - else - { - // Between two keys - key_map_t::iterator left = right; --left; - F32 index_before = left->first; - F32 index_after = right->first; - ScaleKey& scale_before = left->second; - ScaleKey& scale_after = right->second; - if (right == mKeys.end()) - { - scale_after = mLoopInKey; - index_after = duration; - } - - F32 u = (time - index_before) / (index_after - index_before); - value = interp(u, scale_before, scale_after); - } - return value; -} - -//----------------------------------------------------------------------------- -// interp() -//----------------------------------------------------------------------------- -LLVector3 LLKeyframeMotion::ScaleCurve::interp(F32 u, ScaleKey& before, ScaleKey& after) -{ - switch (mInterpolationType) - { - case IT_STEP: - return before.mScale; - - default: - case IT_LINEAR: - case IT_SPLINE: - return lerp(before.mScale, after.mScale, u); - } -} - -//----------------------------------------------------------------------------- -// RotationCurve::RotationCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::RotationCurve::RotationCurve() -{ - mInterpolationType = LLKeyframeMotion::IT_LINEAR; - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// RotationCurve::~RotationCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::RotationCurve::~RotationCurve() -{ - mKeys.clear(); - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// RotationCurve::getValue() -//----------------------------------------------------------------------------- -LLQuaternion LLKeyframeMotion::RotationCurve::getValue(F32 time, F32 duration) -{ - LLQuaternion value; - - if (mKeys.empty()) - { - value = LLQuaternion::DEFAULT; - return value; - } - - key_map_t::iterator right = mKeys.lower_bound(time); - if (right == mKeys.end()) - { - // Past last key - --right; - value = right->second.mRotation; - } - else if (right == mKeys.begin() || right->first == time) - { - // Before first key or exactly on a key - value = right->second.mRotation; - } - else - { - // Between two keys - key_map_t::iterator left = right; --left; - F32 index_before = left->first; - F32 index_after = right->first; - RotationKey& rot_before = left->second; - RotationKey& rot_after = right->second; - if (right == mKeys.end()) - { - rot_after = mLoopInKey; - index_after = duration; - } - - F32 u = (time - index_before) / (index_after - index_before); - value = interp(u, rot_before, rot_after); - } - return value; -} - -//----------------------------------------------------------------------------- -// interp() -//----------------------------------------------------------------------------- -LLQuaternion LLKeyframeMotion::RotationCurve::interp(F32 u, RotationKey& before, RotationKey& after) -{ - switch (mInterpolationType) - { - case IT_STEP: - return before.mRotation; - - default: - case IT_LINEAR: - case IT_SPLINE: - return nlerp(u, before.mRotation, after.mRotation); - } -} - - -//----------------------------------------------------------------------------- -// PositionCurve::PositionCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::PositionCurve::PositionCurve() -{ - mInterpolationType = LLKeyframeMotion::IT_LINEAR; - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// PositionCurve::~PositionCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::PositionCurve::~PositionCurve() -{ - mKeys.clear(); - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// PositionCurve::getValue() -//----------------------------------------------------------------------------- -LLVector3 LLKeyframeMotion::PositionCurve::getValue(F32 time, F32 duration) -{ - LLVector3 value; - - if (mKeys.empty()) - { - value.clearVec(); - return value; - } - - key_map_t::iterator right = mKeys.lower_bound(time); - if (right == mKeys.end()) - { - // Past last key - --right; - value = right->second.mPosition; - } - else if (right == mKeys.begin() || right->first == time) - { - // Before first key or exactly on a key - value = right->second.mPosition; - } - else - { - // Between two keys - key_map_t::iterator left = right; --left; - F32 index_before = left->first; - F32 index_after = right->first; - PositionKey& pos_before = left->second; - PositionKey& pos_after = right->second; - if (right == mKeys.end()) - { - pos_after = mLoopInKey; - index_after = duration; - } - - F32 u = (time - index_before) / (index_after - index_before); - value = interp(u, pos_before, pos_after); - } - - llassert(value.isFinite()); - - return value; -} - -//----------------------------------------------------------------------------- -// interp() -//----------------------------------------------------------------------------- -LLVector3 LLKeyframeMotion::PositionCurve::interp(F32 u, PositionKey& before, PositionKey& after) -{ - switch (mInterpolationType) - { - case IT_STEP: - return before.mPosition; - default: - case IT_LINEAR: - case IT_SPLINE: - return lerp(before.mPosition, after.mPosition, u); - } -} - - //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // JointMotion class @@ -446,7 +196,9 @@ void LLKeyframeMotion::JointMotion::update(LLJointState* joint_state, F32 time, //----------------------------------------------------------------------------- LLKeyframeMotion::LLKeyframeMotion(const LLUUID &id, LLMotionController* controller) : LLMotion(id, controller), + mJointMotionList(NULL), mPelvisp(NULL), + mCharacter(NULL), mLastSkeletonSerialNum(0), mLastUpdateTime(0.f), mLastLoopedTime(0.f), @@ -620,7 +372,7 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact LLDataPackerBinaryBuffer dp(anim_data, anim_file_size); - if (!deserialize(dp)) + if (!deserialize(dp, getID())) { LL_WARNS() << "Failed to decode asset for animation " << getName() << ":" << getID() << LL_ENDL; mAssetStatus = ASSET_FETCH_FAILED; @@ -700,7 +452,8 @@ BOOL LLKeyframeMotion::onActivate() //----------------------------------------------------------------------------- BOOL LLKeyframeMotion::onUpdate(F32 time, U8* joint_mask) { - llassert(time >= 0.f); + // llassert(time >= 0.f); // This will fire + time = llmax(0.f, time); if (mJointMotionList->mLoop) { @@ -965,7 +718,7 @@ void LLKeyframeMotion::deactivateConstraint(JointConstraint *constraintp) constraintp->mSourceVolume->mUpdateXform = FALSE; } - if (!constraintp->mSharedData->mConstraintTargetType == CONSTRAINT_TARGET_TYPE_GROUND) + if (constraintp->mSharedData->mConstraintTargetType != CONSTRAINT_TARGET_TYPE_GROUND) { if (constraintp->mTargetVolume) { @@ -1047,7 +800,7 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8 { case CONSTRAINT_TARGET_TYPE_GROUND: target_pos = mCharacter->getPosAgentFromGlobal(constraint->mGroundPos); - target_pos += mCharacter->getHoverOffset(); + //target_pos += mCharacter->getHoverOffset(); // LL_INFOS() << "Target Pos " << constraint->mGroundPos << " on " << mCharacter->findCollisionVolume(shared_data->mSourceConstraintVolume)->getName() << LL_ENDL; break; case CONSTRAINT_TARGET_TYPE_BODY: @@ -1099,11 +852,11 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8 if (constraint->mSharedData->mChainLength != 0 && dist_vec_squared(root_pos, target_pos) * 0.95f > constraint->mTotalLength * constraint->mTotalLength) { - constraint->mWeight = lerp(constraint->mWeight, 0.f, LLCriticalDamp::getInterpolant(0.1f)); + constraint->mWeight = LLSmoothInterpolation::lerp(constraint->mWeight, 0.f, 0.1f); } else { - constraint->mWeight = lerp(constraint->mWeight, 1.f, LLCriticalDamp::getInterpolant(0.3f)); + constraint->mWeight = LLSmoothInterpolation::lerp(constraint->mWeight, 1.f, 0.3f); } F32 weight = constraint->mWeight * ((shared_data->mEaseOutStopTime == 0.f) ? 1.f : @@ -1112,7 +865,7 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8 LLVector3 source_to_target = target_pos - keyframe_source_pos; - S32 max_iteration_count = ll_round(clamp_rescale( + S32 max_iteration_count = ll_pos_round(clamp_rescale( mCharacter->getPixelArea(), MAX_PIXEL_AREA_CONSTRAINTS, MIN_PIXEL_AREA_CONSTRAINTS, @@ -1150,9 +903,9 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8 // convert intermediate joint positions to world coordinates positions[joint_num] = ( constraint->mPositions[joint_num] * mPelvisp->getWorldRotation()) + mPelvisp->getWorldPosition(); F32 time_constant = 1.f / clamp_rescale(constraint->mFixupDistanceRMS, 0.f, 0.5f, 0.2f, 8.f); -// LL_INFOS() << "Interpolant " << LLCriticalDamp::getInterpolant(time_constant, FALSE) << " and fixup distance " << constraint->mFixupDistanceRMS << " on " << mCharacter->findCollisionVolume(shared_data->mSourceConstraintVolume)->getName() << LL_ENDL; +// LL_INFOS() << "Interpolant " << LLSmoothInterpolation::getInterpolant(time_constant, FALSE) << " and fixup distance " << constraint->mFixupDistanceRMS << " on " << mCharacter->findCollisionVolume(shared_data->mSourceConstraintVolume)->getName() << LL_ENDL; positions[joint_num] = lerp(positions[joint_num], kinematic_position, - LLCriticalDamp::getInterpolant(time_constant, FALSE)); + LLSmoothInterpolation::getInterpolant(time_constant, FALSE)); } S32 iteration_count; @@ -1284,20 +1037,10 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8 } } -// Helper class. -template -struct AIAutoDestruct -{ - T* mPtr; - AIAutoDestruct() : mPtr(NULL) { } - ~AIAutoDestruct() { delete mPtr; } - void add(T* ptr) { mPtr = ptr; } -}; - //----------------------------------------------------------------------------- // deserialize() //----------------------------------------------------------------------------- -BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) +BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id) { BOOL old_version = FALSE; @@ -1330,13 +1073,13 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (!dp.unpackU16(version, "version")) { - LL_WARNS() << "can't read version number" << LL_ENDL; + LL_WARNS() << "can't read version number for animation " << asset_id << LL_ENDL; return FALSE; } if (!dp.unpackU16(sub_version, "sub_version")) { - LL_WARNS() << "can't read sub version number" << LL_ENDL; + LL_WARNS() << "can't read sub version number for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1347,28 +1090,32 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) else if (version != KEYFRAME_MOTION_VERSION || sub_version != KEYFRAME_MOTION_SUBVERSION) { #if LL_RELEASE - LL_WARNS() << "Bad animation version " << version << "." << sub_version << LL_ENDL; + LL_WARNS() << "Bad animation version " << version << "." << sub_version + << " for animation " << asset_id << LL_ENDL; return FALSE; #else - LL_ERRS() << "Bad animation version " << version << "." << sub_version << LL_ENDL; + LL_ERRS() << "Bad animation version " << version << "." << sub_version + << " for animation " << asset_id << LL_ENDL; #endif } if (!dp.unpackS32(temp_priority, "base_priority")) { - LL_WARNS() << "can't read animation base_priority" << LL_ENDL; + LL_WARNS() << "can't read animation base_priority" + << " for animation " << asset_id << LL_ENDL; return FALSE; } mJointMotionList->mBasePriority = (LLJoint::JointPriority) temp_priority; if (mJointMotionList->mBasePriority >= LLJoint::ADDITIVE_PRIORITY) { - mJointMotionList->mBasePriority = (LLJoint::JointPriority)((int)LLJoint::ADDITIVE_PRIORITY-1); + mJointMotionList->mBasePriority = (LLJoint::JointPriority)((S32)LLJoint::ADDITIVE_PRIORITY-1); mJointMotionList->mMaxPriority = mJointMotionList->mBasePriority; } else if (mJointMotionList->mBasePriority < LLJoint::USE_MOTION_PRIORITY) { - LL_WARNS() << "bad animation base_priority " << mJointMotionList->mBasePriority << LL_ENDL; + LL_WARNS() << "bad animation base_priority " << mJointMotionList->mBasePriority + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1377,14 +1124,16 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) //------------------------------------------------------------------------- if (!dp.unpackF32(mJointMotionList->mDuration, "duration")) { - LL_WARNS() << "can't read duration" << LL_ENDL; + LL_WARNS() << "can't read duration" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if (mJointMotionList->mDuration > MAX_ANIM_DURATION || - !llfinite(mJointMotionList->mDuration)) + !std::isfinite(mJointMotionList->mDuration)) { - LL_WARNS() << "invalid animation duration" << LL_ENDL; + LL_WARNS() << "invalid animation duration" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1393,13 +1142,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) //------------------------------------------------------------------------- if (!dp.unpackString(mJointMotionList->mEmoteName, "emote_name")) { - LL_WARNS() << "can't read optional_emote_animation" << LL_ENDL; + LL_WARNS() << "can't read optional_emote_animation" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if(mJointMotionList->mEmoteName==mID.asString()) { - LL_WARNS() << "Malformed animation mEmoteName==mID" << LL_ENDL; + LL_WARNS() << "Malformed animation mEmoteName==mID" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1407,22 +1158,25 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) // get loop //------------------------------------------------------------------------- if (!dp.unpackF32(mJointMotionList->mLoopInPoint, "loop_in_point") || - !llfinite(mJointMotionList->mLoopInPoint)) + !std::isfinite(mJointMotionList->mLoopInPoint)) { - LL_WARNS() << "can't read loop point" << LL_ENDL; + LL_WARNS() << "can't read loop point" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if (!dp.unpackF32(mJointMotionList->mLoopOutPoint, "loop_out_point") || - !llfinite(mJointMotionList->mLoopOutPoint)) + !std::isfinite(mJointMotionList->mLoopOutPoint)) { - LL_WARNS() << "can't read loop point" << LL_ENDL; + LL_WARNS() << "can't read loop point" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if (!dp.unpackS32(mJointMotionList->mLoop, "loop")) { - LL_WARNS() << "can't read loop" << LL_ENDL; + LL_WARNS() << "can't read loop" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1430,16 +1184,18 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) // get easeIn and easeOut //------------------------------------------------------------------------- if (!dp.unpackF32(mJointMotionList->mEaseInDuration, "ease_in_duration") || - !llfinite(mJointMotionList->mEaseInDuration)) + !std::isfinite(mJointMotionList->mEaseInDuration)) { - LL_WARNS() << "can't read easeIn" << LL_ENDL; + LL_WARNS() << "can't read easeIn" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if (!dp.unpackF32(mJointMotionList->mEaseOutDuration, "ease_out_duration") || - !llfinite(mJointMotionList->mEaseOutDuration)) + !std::isfinite(mJointMotionList->mEaseOutDuration)) { - LL_WARNS() << "can't read easeOut" << LL_ENDL; + LL_WARNS() << "can't read easeOut" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1449,13 +1205,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) U32 word; if (!dp.unpackU32(word, "hand_pose")) { - LL_WARNS() << "can't read hand pose" << LL_ENDL; + LL_WARNS() << "can't read hand pose" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if(word > LLHandMotion::NUM_HAND_POSES) { - LL_WARNS() << "invalid LLHandMotion::eHandPose index: " << word << LL_ENDL; + LL_WARNS() << "invalid LLHandMotion::eHandPose index: " << word + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1467,18 +1225,21 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) U32 num_motions = 0; if (!dp.unpackU32(num_motions, "num_joints")) { - LL_WARNS() << "can't read number of joints" << LL_ENDL; + LL_WARNS() << "can't read number of joints" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if (num_motions == 0) { - LL_WARNS() << "no joints in animation" << LL_ENDL; + LL_WARNS() << "no joints" + << " for animation " << asset_id << LL_ENDL; return FALSE; } - else if (num_motions > LL_CHARACTER_MAX_JOINTS) + else if (num_motions > LL_CHARACTER_MAX_ANIMATED_JOINTS) { - LL_WARNS() << "too many joints in animation" << LL_ENDL; + LL_WARNS() << "too many joints" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1495,30 +1256,26 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) for(U32 i=0; i watcher; - - JointMotion* joint_motion = new JointMotion; + JointMotion* joint_motion = new JointMotion; + std::unique_ptr watcher(joint_motion); if (singu_new_joint_motion_list) { // Pass ownership to mJointMotionList. - mJointMotionList->mJointMotionArray.push_back(joint_motion); - } - else - { - // Just delete this at the end. - watcher.add(joint_motion); + mJointMotionList->mJointMotionArray.push_back(watcher.release()); } std::string joint_name; if (!dp.unpackString(joint_name, "joint_name")) { - LL_WARNS() << "can't read joint name" << LL_ENDL; + LL_WARNS() << "can't read joint name" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if (joint_name == "mScreen" || joint_name == "mRoot") { - LL_WARNS() << "attempted to animate special " << joint_name << " joint" << LL_ENDL; + LL_WARNS() << "attempted to animate special " << joint_name << " joint" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1528,7 +1285,16 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) LLJoint *joint = mCharacter->getJoint( joint_name ); if (joint) { + S32 joint_num = joint->getJointNum(); // LL_INFOS() << " joint: " << joint_name << LL_ENDL; + if ((joint_num >= (S32)LL_CHARACTER_MAX_ANIMATED_JOINTS) || (joint_num < 0)) + { + LL_WARNS() << "Joint will be omitted from animation: joint_num " << joint_num + << " is outside of legal range [0-" + << LL_CHARACTER_MAX_ANIMATED_JOINTS << ") for joint " << joint->getName() + << " for animation " << asset_id << LL_ENDL; + joint = NULL; + } } else { @@ -1544,7 +1310,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) i++; } // - LL_WARNS() << "joint not found: " << joint_name << LL_ENDL; + LL_WARNS() << "invalid joint name: " << joint_name + << " for animation " << asset_id << LL_ENDL; //return FALSE; } @@ -1561,13 +1328,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) S32 joint_priority; if (!dp.unpackS32(joint_priority, "joint_priority")) { - LL_WARNS() << "can't read joint priority." << LL_ENDL; + LL_WARNS() << "can't read joint priority." + << " for animation " << asset_id << LL_ENDL; return FALSE; } if (joint_priority < LLJoint::USE_MOTION_PRIORITY) { - LL_WARNS() << "joint priority unknown - too low." << LL_ENDL; + LL_WARNS() << "joint priority unknown - too low." + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1585,7 +1354,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) //--------------------------------------------------------------------- if (!dp.unpackS32(joint_motion->mRotationCurve.mNumKeys, "num_rot_keys") || joint_motion->mRotationCurve.mNumKeys < 0) { - LL_WARNS() << "can't read number of rotation keys" << LL_ENDL; + LL_WARNS() << "can't read number of rotation keys" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1608,9 +1378,10 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (old_version) { if (!dp.unpackF32(time, "time") || - !llfinite(time)) + !std::isfinite(time)) { - LL_WARNS() << "can't read rotation key (" << k << ")" << LL_ENDL; + LL_WARNS() << "can't read rotation key (" << k << ")" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1619,7 +1390,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) { if (!dp.unpackU16(time_short, "time")) { - LL_WARNS() << "can't read rotation key (" << k << ")" << LL_ENDL; + LL_WARNS() << "can't read rotation key (" << k << ")" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1627,7 +1399,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (time < 0 || time > mJointMotionList->mDuration) { - LL_WARNS() << "invalid frame time" << LL_ENDL; + LL_WARNS() << "invalid frame time" + << " for animation " << asset_id << LL_ENDL; return FALSE; } } @@ -1644,7 +1417,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) success = dp.unpackVector3(rot_angles, "rot_angles") && rot_angles.isFinite(); LLQuaternion::Order ro = StringToOrder("ZYX"); - rot_key.mRotation = mayaQ(rot_angles.mV[VX], rot_angles.mV[VY], rot_angles.mV[VZ], ro); + rot_key.mValue = mayaQ(rot_angles.mV[VX], rot_angles.mV[VY], rot_angles.mV[VZ], ro); } else { @@ -1656,30 +1429,35 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) rot_vec.mV[VX] = U16_to_F32(x, -1.f, 1.f); rot_vec.mV[VY] = U16_to_F32(y, -1.f, 1.f); rot_vec.mV[VZ] = U16_to_F32(z, -1.f, 1.f); - rot_key.mRotation.unpackFromVector3(rot_vec); + rot_key.mValue.unpackFromVector3(rot_vec); } - if( !(rot_key.mRotation.isFinite()) ) + if( !(rot_key.mValue.isFinite()) ) { - LL_WARNS() << "non-finite angle in rotation key" << LL_ENDL; + LL_WARNS() << "non-finite angle in rotation key" + << " for animation " << asset_id << LL_ENDL; success = FALSE; } if (!success) { - LL_WARNS() << "can't read rotation key (" << k << ")" << LL_ENDL; + LL_WARNS() << "can't read rotation key (" << k << ")" + << " for animation " << asset_id << LL_ENDL; return FALSE; } - rCurve->mKeys[time] = rot_key; + rCurve->mKeys.emplace_back(time, rot_key); } + std::sort(rCurve->mKeys.begin(), rCurve->mKeys.end(), [](const auto& a, const auto& b) { return a.first < b.first; }); + //--------------------------------------------------------------------- // scan position curve header //--------------------------------------------------------------------- if (!dp.unpackS32(joint_motion->mPositionCurve.mNumKeys, "num_pos_keys") || joint_motion->mPositionCurve.mNumKeys < 0) { - LL_WARNS() << "can't read number of position keys" << LL_ENDL; + LL_WARNS() << "can't read number of position keys" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1702,9 +1480,10 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (old_version) { if (!dp.unpackF32(pos_key.mTime, "time") || - !llfinite(pos_key.mTime)) + !std::isfinite(pos_key.mTime)) { - LL_WARNS() << "can't read position key (" << k << ")" << LL_ENDL; + LL_WARNS() << "can't read position key (" << k << ")" + << " for animation " << asset_id << LL_ENDL; return FALSE; } } @@ -1712,7 +1491,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) { if (!dp.unpackU16(time_short, "time")) { - LL_WARNS() << "can't read position key (" << k << ")" << LL_ENDL; + LL_WARNS() << "can't read position key (" << k << ")" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1723,7 +1503,13 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (old_version) { - success = dp.unpackVector3(pos_key.mPosition, "pos"); + success = dp.unpackVector3(pos_key.mValue, "pos"); + + //MAINT-6162 + pos_key.mValue.mV[VX] = llclamp( pos_key.mValue.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.mV[VY] = llclamp( pos_key.mValue.mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.mV[VZ] = llclamp( pos_key.mValue.mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + } else { @@ -1733,31 +1519,36 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) success &= dp.unpackU16(y, "pos_y"); success &= dp.unpackU16(z, "pos_z"); - pos_key.mPosition.mV[VX] = U16_to_F32(x, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - pos_key.mPosition.mV[VY] = U16_to_F32(y, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - pos_key.mPosition.mV[VZ] = U16_to_F32(z, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.mV[VX] = U16_to_F32(x, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.mV[VY] = U16_to_F32(y, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.mV[VZ] = U16_to_F32(z, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); } - if( !(pos_key.mPosition.isFinite()) ) + if( !(pos_key.mValue.isFinite()) ) { - LL_WARNS() << "non-finite position in key" << LL_ENDL; + LL_WARNS() << "non-finite position in key" + << " for animation " << asset_id << LL_ENDL; success = FALSE; } if (!success) { - LL_WARNS() << "can't read position key (" << k << ")" << LL_ENDL; + LL_WARNS() << "can't read position key (" << k << ")" + << " for animation " << asset_id << LL_ENDL; return FALSE; } - pCurve->mKeys[pos_key.mTime] = pos_key; + pCurve->mKeys.emplace_back(pos_key.mTime, pos_key); if (is_pelvis) { - mJointMotionList->mPelvisBBox.addPoint(pos_key.mPosition); + mJointMotionList->mPelvisBBox.addPoint(pos_key.mValue); } + } + std::sort(pCurve->mKeys.begin(), pCurve->mKeys.end(), [](const auto& a, const auto& b) { return a.first < b.first; }); + joint_motion->mUsage = joint_state->getUsage(); } @@ -1767,13 +1558,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) S32 num_constraints = 0; if (!dp.unpackS32(num_constraints, "num_constraints")) { - LL_WARNS() << "can't read number of constraints" << LL_ENDL; + LL_WARNS() << "can't read number of constraints" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if (num_constraints > MAX_CONSTRAINTS || num_constraints < 0) { - LL_WARNS() << "Bad number of constraints... ignoring: " << num_constraints << LL_ENDL; + LL_WARNS() << "Bad number of constraints... ignoring: " << num_constraints + << " for animation " << asset_id << LL_ENDL; } else { @@ -1784,35 +1577,36 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) for(S32 i = 0; i < num_constraints; ++i) { // read in constraint data - JointConstraintSharedData* constraintp = new JointConstraintSharedData; + auto constraintp = new JointConstraintSharedData; + std::unique_ptr watcher(constraintp); U8 byte = 0; if (!dp.unpackU8(byte, "chain_length")) { - LL_WARNS() << "can't read constraint chain length" << LL_ENDL; - delete constraintp; + LL_WARNS() << "can't read constraint chain length" + << " for animation " << asset_id << LL_ENDL; return FALSE; } constraintp->mChainLength = (S32) byte; if((U32)constraintp->mChainLength > mJointMotionList->getNumJointMotions()) { - LL_WARNS() << "invalid constraint chain length" << LL_ENDL; - delete constraintp; + LL_WARNS() << "invalid constraint chain length" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if (!dp.unpackU8(byte, "constraint_type")) { - LL_WARNS() << "can't read constraint type" << LL_ENDL; - delete constraintp; + LL_WARNS() << "can't read constraint type" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if( byte >= NUM_CONSTRAINT_TYPES ) { - LL_WARNS() << "invalid constraint type" << LL_ENDL; - delete constraintp; + LL_WARNS() << "invalid constraint type" + << " for animation " << asset_id << LL_ENDL; return FALSE; } constraintp->mConstraintType = (EConstraintType)byte; @@ -1821,42 +1615,39 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) U8 bin_data[BIN_DATA_LENGTH+1]; if (!dp.unpackBinaryDataFixed(bin_data, BIN_DATA_LENGTH, "source_volume")) { - LL_WARNS() << "can't read source volume name" << LL_ENDL; - delete constraintp; + LL_WARNS() << "can't read source volume name" + << " for animation " << asset_id << LL_ENDL; return FALSE; } bin_data[BIN_DATA_LENGTH] = 0; // Ensure null termination str = (char*)bin_data; constraintp->mSourceConstraintVolume = mCharacter->getCollisionVolumeID(str); - - // - if(constraintp->mSourceConstraintVolume == -1) + if (constraintp->mSourceConstraintVolume == -1) { - LL_WARNS() << "can't get source constraint volume" << LL_ENDL; - delete constraintp; + LL_WARNS() << "not a valid source constraint volume " << str + << " for animation " << asset_id << LL_ENDL; return FALSE; } - // if (!dp.unpackVector3(constraintp->mSourceConstraintOffset, "source_offset")) { - LL_WARNS() << "can't read constraint source offset" << LL_ENDL; - delete constraintp; + LL_WARNS() << "can't read constraint source offset" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if( !(constraintp->mSourceConstraintOffset.isFinite()) ) { - LL_WARNS() << "non-finite constraint source offset" << LL_ENDL; - delete constraintp; + LL_WARNS() << "non-finite constraint source offset" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if (!dp.unpackBinaryDataFixed(bin_data, BIN_DATA_LENGTH, "target_volume")) { - LL_WARNS() << "can't read target volume name" << LL_ENDL; - delete constraintp; + LL_WARNS() << "can't read target volume name" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1871,33 +1662,39 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) { constraintp->mConstraintTargetType = CONSTRAINT_TARGET_TYPE_BODY; constraintp->mTargetConstraintVolume = mCharacter->getCollisionVolumeID(str); + if (constraintp->mTargetConstraintVolume == -1) + { + LL_WARNS() << "not a valid target constraint volume " << str + << " for animation " << asset_id << LL_ENDL; + return FALSE; + } } if (!dp.unpackVector3(constraintp->mTargetConstraintOffset, "target_offset")) { - LL_WARNS() << "can't read constraint target offset" << LL_ENDL; - delete constraintp; + LL_WARNS() << "can't read constraint target offset" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if( !(constraintp->mTargetConstraintOffset.isFinite()) ) { - LL_WARNS() << "non-finite constraint target offset" << LL_ENDL; - delete constraintp; + LL_WARNS() << "non-finite constraint target offset" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if (!dp.unpackVector3(constraintp->mTargetConstraintDir, "target_dir")) { - LL_WARNS() << "can't read constraint target direction" << LL_ENDL; - delete constraintp; + LL_WARNS() << "can't read constraint target direction" + << " for animation " << asset_id << LL_ENDL; return FALSE; } if( !(constraintp->mTargetConstraintDir.isFinite()) ) { - LL_WARNS() << "non-finite constraint target direction" << LL_ENDL; - delete constraintp; + LL_WARNS() << "non-finite constraint target direction" + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1907,45 +1704,40 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) // constraintp->mTargetConstraintDir *= constraintp->mSourceConstraintOffset.magVec(); } - if (!dp.unpackF32(constraintp->mEaseInStartTime, "ease_in_start") || !llfinite(constraintp->mEaseInStartTime)) + if (!dp.unpackF32(constraintp->mEaseInStartTime, "ease_in_start") || !std::isfinite(constraintp->mEaseInStartTime)) { - LL_WARNS() << "can't read constraint ease in start time" << LL_ENDL; - delete constraintp; + LL_WARNS() << "can't read constraint ease in start time" + << " for animation " << asset_id << LL_ENDL; return FALSE; } - if (!dp.unpackF32(constraintp->mEaseInStopTime, "ease_in_stop") || !llfinite(constraintp->mEaseInStopTime)) + if (!dp.unpackF32(constraintp->mEaseInStopTime, "ease_in_stop") || !std::isfinite(constraintp->mEaseInStopTime)) { - LL_WARNS() << "can't read constraint ease in stop time" << LL_ENDL; - delete constraintp; + LL_WARNS() << "can't read constraint ease in stop time" + << " for animation " << asset_id << LL_ENDL; return FALSE; } - if (!dp.unpackF32(constraintp->mEaseOutStartTime, "ease_out_start") || !llfinite(constraintp->mEaseOutStartTime)) + if (!dp.unpackF32(constraintp->mEaseOutStartTime, "ease_out_start") || !std::isfinite(constraintp->mEaseOutStartTime)) { - LL_WARNS() << "can't read constraint ease out start time" << LL_ENDL; - delete constraintp; + LL_WARNS() << "can't read constraint ease out start time" + << " for animation " << asset_id << LL_ENDL; return FALSE; } - if (!dp.unpackF32(constraintp->mEaseOutStopTime, "ease_out_stop") || !llfinite(constraintp->mEaseOutStopTime)) + if (!dp.unpackF32(constraintp->mEaseOutStopTime, "ease_out_stop") || !std::isfinite(constraintp->mEaseOutStopTime)) { - LL_WARNS() << "can't read constraint ease out stop time" << LL_ENDL; - delete constraintp; + LL_WARNS() << "can't read constraint ease out stop time" + << " for animation " << asset_id << LL_ENDL; return FALSE; } - AIAutoDestruct watcher; + constraintp->mJointStateIndices = new S32[constraintp->mChainLength + 1]; // note: mChainLength is size-limited - comes from a byte + if (singu_new_joint_motion_list) { - mJointMotionList->mConstraints.push_front(constraintp); + mJointMotionList->mConstraints.push_front(watcher.release()); } - else - { - watcher.add(constraintp); - } - - constraintp->mJointStateIndices = new S32[constraintp->mChainLength + 1]; // note: mChainLength is size-limited - comes from a byte LLJoint* joint = mCharacter->findCollisionVolume(constraintp->mSourceConstraintVolume); // get joint to which this collision volume is attached @@ -1959,7 +1751,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (!parent) { LL_WARNS() << "Joint with no parent: " << joint->getName() - << " Emote: " << mJointMotionList->mEmoteName << LL_ENDL; + << " Emote: " << mJointMotionList->mEmoteName + << " for animation " << asset_id << LL_ENDL; return FALSE; } joint = parent; @@ -1970,7 +1763,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if ( !constraint_joint ) { - LL_WARNS() << "Invalid joint " << j << LL_ENDL; + LL_WARNS() << "Invalid joint " << j + << " for animation " << asset_id << LL_ENDL; return FALSE; } @@ -1982,7 +1776,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) } if (constraintp->mJointStateIndices[i] < 0 ) { - LL_WARNS() << "No joint index for constraint " << i << LL_ENDL; + LL_WARNS() << "No joint index for constraint " << i + << " for animation " << asset_id << LL_ENDL; return FALSE; } } @@ -2003,6 +1798,8 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const { BOOL success = TRUE; + LL_DEBUGS("BVH") << "serializing" << LL_ENDL; + success &= dp.packU16(KEYFRAME_MOTION_VERSION, "version"); success &= dp.packU16(KEYFRAME_MOTION_SUBVERSION, "sub_version"); success &= dp.packS32(mJointMotionList->mBasePriority, "base_priority"); @@ -2016,6 +1813,19 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packU32(mJointMotionList->mHandPose, "hand_pose"); success &= dp.packU32(mJointMotionList->getNumJointMotions(), "num_joints"); + LL_DEBUGS("BVH") << "version " << KEYFRAME_MOTION_VERSION << LL_ENDL; + LL_DEBUGS("BVH") << "sub_version " << KEYFRAME_MOTION_SUBVERSION << LL_ENDL; + LL_DEBUGS("BVH") << "base_priority " << mJointMotionList->mBasePriority << LL_ENDL; + LL_DEBUGS("BVH") << "duration " << mJointMotionList->mDuration << LL_ENDL; + LL_DEBUGS("BVH") << "emote_name " << mJointMotionList->mEmoteName << LL_ENDL; + LL_DEBUGS("BVH") << "loop_in_point " << mJointMotionList->mLoopInPoint << LL_ENDL; + LL_DEBUGS("BVH") << "loop_out_point " << mJointMotionList->mLoopOutPoint << LL_ENDL; + LL_DEBUGS("BVH") << "loop " << mJointMotionList->mLoop << LL_ENDL; + LL_DEBUGS("BVH") << "ease_in_duration " << mJointMotionList->mEaseInDuration << LL_ENDL; + LL_DEBUGS("BVH") << "ease_out_duration " << mJointMotionList->mEaseOutDuration << LL_ENDL; + LL_DEBUGS("BVH") << "hand_pose " << mJointMotionList->mHandPose << LL_ENDL; + LL_DEBUGS("BVH") << "num_joints " << mJointMotionList->getNumJointMotions() << LL_ENDL; + for (U32 i = 0; i < mJointMotionList->getNumJointMotions(); i++) { JointMotion* joint_motionp = mJointMotionList->getJointMotion(i); @@ -2023,6 +1833,7 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packS32(joint_motionp->mPriority, "joint_priority"); success &= dp.packS32(joint_motionp->mRotationCurve.mNumKeys, "num_rot_keys"); + LL_DEBUGS("BVH") << "Joint " << joint_motionp->mJointName << LL_ENDL; for (RotationCurve::key_map_t::iterator iter = joint_motionp->mRotationCurve.mKeys.begin(); iter != joint_motionp->mRotationCurve.mKeys.end(); ++iter) { @@ -2030,7 +1841,7 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const U16 time_short = F32_to_U16(rot_key.mTime, 0.f, mJointMotionList->mDuration); success &= dp.packU16(time_short, "time"); - LLVector3 rot_angles = rot_key.mRotation.packToVector3(); + LLVector3 rot_angles = rot_key.mValue.packToVector3(); U16 x, y, z; rot_angles.quantize16(-1.f, 1.f, -1.f, 1.f); @@ -2040,6 +1851,8 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packU16(x, "rot_angle_x"); success &= dp.packU16(y, "rot_angle_y"); success &= dp.packU16(z, "rot_angle_z"); + + LL_DEBUGS("BVH") << " rot: t " << rot_key.mTime << " angles " << rot_angles.mV[VX] <<","<< rot_angles.mV[VY] <<","<< rot_angles.mV[VZ] << LL_ENDL; } success &= dp.packS32(joint_motionp->mPositionCurve.mNumKeys, "num_pos_keys"); @@ -2051,44 +1864,61 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packU16(time_short, "time"); U16 x, y, z; - pos_key.mPosition.quantize16(-LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - x = F32_to_U16(pos_key.mPosition.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - y = F32_to_U16(pos_key.mPosition.mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - z = F32_to_U16(pos_key.mPosition.mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.quantize16(-LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + x = F32_to_U16(pos_key.mValue.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + y = F32_to_U16(pos_key.mValue.mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + z = F32_to_U16(pos_key.mValue.mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); success &= dp.packU16(x, "pos_x"); success &= dp.packU16(y, "pos_y"); success &= dp.packU16(z, "pos_z"); + + LL_DEBUGS("BVH") << " pos: t " << pos_key.mTime << " pos " << pos_key.mValue.mV[VX] <<","<< pos_key.mValue.mV[VY] <<","<< pos_key.mValue.mV[VZ] << LL_ENDL; } } success &= dp.packS32(mJointMotionList->mConstraints.size(), "num_constraints"); + LL_DEBUGS("BVH") << "num_constraints " << mJointMotionList->mConstraints.size() << LL_ENDL; for (JointMotionList::constraint_list_t::const_iterator iter = mJointMotionList->mConstraints.begin(); iter != mJointMotionList->mConstraints.end(); ++iter) { JointConstraintSharedData* shared_constraintp = *iter; success &= dp.packU8(shared_constraintp->mChainLength, "chain_length"); success &= dp.packU8(shared_constraintp->mConstraintType, "constraint_type"); - char volume_name[16]; /* Flawfinder: ignore */ - snprintf(volume_name, sizeof(volume_name), "%s", /* Flawfinder: ignore */ + char source_volume[16]; /* Flawfinder: ignore */ + snprintf(source_volume, sizeof(source_volume), "%s", /* Flawfinder: ignore */ mCharacter->findCollisionVolume(shared_constraintp->mSourceConstraintVolume)->getName().c_str()); - success &= dp.packBinaryDataFixed((U8*)volume_name, 16, "source_volume"); + + success &= dp.packBinaryDataFixed((U8*)source_volume, 16, "source_volume"); success &= dp.packVector3(shared_constraintp->mSourceConstraintOffset, "source_offset"); + char target_volume[16]; /* Flawfinder: ignore */ if (shared_constraintp->mConstraintTargetType == CONSTRAINT_TARGET_TYPE_GROUND) { - snprintf(volume_name,sizeof(volume_name), "%s", "GROUND"); /* Flawfinder: ignore */ + snprintf(target_volume,sizeof(target_volume), "%s", "GROUND"); /* Flawfinder: ignore */ } else { - snprintf(volume_name, sizeof(volume_name),"%s", /* Flawfinder: ignore */ + snprintf(target_volume, sizeof(target_volume),"%s", /* Flawfinder: ignore */ mCharacter->findCollisionVolume(shared_constraintp->mTargetConstraintVolume)->getName().c_str()); } - success &= dp.packBinaryDataFixed((U8*)volume_name, 16, "target_volume"); + success &= dp.packBinaryDataFixed((U8*)target_volume, 16, "target_volume"); success &= dp.packVector3(shared_constraintp->mTargetConstraintOffset, "target_offset"); success &= dp.packVector3(shared_constraintp->mTargetConstraintDir, "target_dir"); success &= dp.packF32(shared_constraintp->mEaseInStartTime, "ease_in_start"); success &= dp.packF32(shared_constraintp->mEaseInStopTime, "ease_in_stop"); success &= dp.packF32(shared_constraintp->mEaseOutStartTime, "ease_out_start"); success &= dp.packF32(shared_constraintp->mEaseOutStopTime, "ease_out_stop"); + + LL_DEBUGS("BVH") << " chain_length " << shared_constraintp->mChainLength << LL_ENDL; + LL_DEBUGS("BVH") << " constraint_type " << (S32)shared_constraintp->mConstraintType << LL_ENDL; + LL_DEBUGS("BVH") << " source_volume " << source_volume << LL_ENDL; + LL_DEBUGS("BVH") << " source_offset " << shared_constraintp->mSourceConstraintOffset << LL_ENDL; + LL_DEBUGS("BVH") << " target_volume " << target_volume << LL_ENDL; + LL_DEBUGS("BVH") << " target_offset " << shared_constraintp->mTargetConstraintOffset << LL_ENDL; + LL_DEBUGS("BVH") << " target_dir " << shared_constraintp->mTargetConstraintDir << LL_ENDL; + LL_DEBUGS("BVH") << " ease_in_start " << shared_constraintp->mEaseInStartTime << LL_ENDL; + LL_DEBUGS("BVH") << " ease_in_stop " << shared_constraintp->mEaseInStopTime << LL_ENDL; + LL_DEBUGS("BVH") << " ease_out_start " << shared_constraintp->mEaseOutStartTime << LL_ENDL; + LL_DEBUGS("BVH") << " ease_out_stop " << shared_constraintp->mEaseOutStopTime << LL_ENDL; } return success; @@ -2149,7 +1979,7 @@ void LLKeyframeMotion::setEmote(const LLUUID& emote_id) } else { - mJointMotionList->mEmoteName = ""; + mJointMotionList->mEmoteName.clear(); } } @@ -2220,9 +2050,9 @@ void LLKeyframeMotion::setLoopIn(F32 in_point) rot_curve->mLoopInKey.mTime = mJointMotionList->mLoopInPoint; scale_curve->mLoopInKey.mTime = mJointMotionList->mLoopInPoint; - pos_curve->mLoopInKey.mPosition = pos_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); - rot_curve->mLoopInKey.mRotation = rot_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); - scale_curve->mLoopInKey.mScale = scale_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); + pos_curve->mLoopInKey.mValue = pos_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); + rot_curve->mLoopInKey.mValue = rot_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); + scale_curve->mLoopInKey.mValue = scale_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); } } } @@ -2249,9 +2079,9 @@ void LLKeyframeMotion::setLoopOut(F32 out_point) rot_curve->mLoopOutKey.mTime = mJointMotionList->mLoopOutPoint; scale_curve->mLoopOutKey.mTime = mJointMotionList->mLoopOutPoint; - pos_curve->mLoopOutKey.mPosition = pos_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); - rot_curve->mLoopOutKey.mRotation = rot_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); - scale_curve->mLoopOutKey.mScale = scale_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); + pos_curve->mLoopOutKey.mValue = pos_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); + rot_curve->mLoopOutKey.mValue = rot_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); + scale_curve->mLoopOutKey.mValue = scale_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); } } } @@ -2284,7 +2114,7 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs, LLCharacter* character = *char_iter; // look for an existing instance of this motion - LLKeyframeMotion* motionp = (LLKeyframeMotion*) character->findMotion(asset_uuid); + LLKeyframeMotion* motionp = dynamic_cast (character->findMotion(asset_uuid)); if (motionp) { if (0 == status) @@ -2299,11 +2129,11 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs, U8* buffer = new U8[size]; file.read((U8*)buffer, size); /*Flawfinder: ignore*/ - - LL_DEBUGS() << "Loading keyframe data for: " << motionp->getName() << ":" << motionp->getID() << " (" << size << " bytes)" << LL_ENDL; + + LL_DEBUGS("Animation") << "Loading keyframe data for: " << motionp->getName() << ":" << motionp->getID() << " (" << size << " bytes)" << LL_ENDL; LLDataPackerBinaryBuffer dp(buffer, size); - if (motionp->deserialize(dp)) + if (motionp->deserialize(dp, asset_uuid)) { motionp->mAssetStatus = ASSET_LOADED; } @@ -2344,9 +2174,9 @@ void LLKeyframeDataCache::dumpDiagInfo(int quiet) if (quiet < 2) { - LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; - LL_INFOS() << " Global Motion Table" << LL_ENDL; - LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; + LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; + LL_INFOS() << " Global Motion Table (DEBUG only)" << LL_ENDL; + LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; } // print each loaded mesh, and it's memory usage @@ -2364,8 +2194,8 @@ void LLKeyframeDataCache::dumpDiagInfo(int quiet) if (motion_list_p) { - joint_motion_kb = motion_list_p->dumpDiagInfo(quiet); - total_size += joint_motion_kb; + joint_motion_kb = motion_list_p->dumpDiagInfo(quiet); + total_size += joint_motion_kb; } } diff --git a/indra/llcharacter/llkeyframemotion.h b/indra/llcharacter/llkeyframemotion.h index 4c54d55006..82244465bf 100644 --- a/indra/llcharacter/llkeyframemotion.h +++ b/indra/llcharacter/llkeyframemotion.h @@ -171,6 +171,22 @@ int AICachedPointerPtr::sCnt; //----------------------------------------------------------------------------- // class LLKeyframeMotion //----------------------------------------------------------------------------- + +namespace LLKeyframeMotionLerp +{ + template + inline T lerp(F32 t, const T& before, const T& after) + { + return ::lerp(before, after, t); + } + + template<> + inline LLQuaternion lerp(F32 t, const LLQuaternion& before, const LLQuaternion& after) + { + return nlerp(t, before, after); + } +} + class LLKeyframeMotion : public LLMotion { @@ -266,7 +282,7 @@ class LLKeyframeMotion : public: U32 getFileSize(); BOOL serialize(LLDataPacker& dp) const; - BOOL deserialize(LLDataPacker& dp); + BOOL deserialize(LLDataPacker& dp, const LLUUID& asset_id); BOOL isLoaded() { return !!mJointMotionList; } @@ -387,101 +403,84 @@ class LLKeyframeMotion : enum InterpolationType { IT_STEP, IT_LINEAR, IT_SPLINE }; - //------------------------------------------------------------------------- - // ScaleKey - //------------------------------------------------------------------------- - class ScaleKey - { - public: - ScaleKey() { mTime = 0.0f; } - ScaleKey(F32 time, const LLVector3 &scale) { mTime = time; mScale = scale; } - - F32 mTime; - LLVector3 mScale; - }; - - //------------------------------------------------------------------------- - // RotationKey - //------------------------------------------------------------------------- - class RotationKey - { - public: - RotationKey() { mTime = 0.0f; } - RotationKey(F32 time, const LLQuaternion &rotation) { mTime = time; mRotation = rotation; } - - F32 mTime; - LLQuaternion mRotation; - }; - - //------------------------------------------------------------------------- - // PositionKey - //------------------------------------------------------------------------- - class PositionKey + template + struct Curve { - public: - PositionKey() { mTime = 0.0f; } - PositionKey(F32 time, const LLVector3 &position) { mTime = time; mPosition = position; } - - F32 mTime; - LLVector3 mPosition; - }; - - //------------------------------------------------------------------------- - // ScaleCurve - //------------------------------------------------------------------------- - class ScaleCurve - { - public: - ScaleCurve(); - ~ScaleCurve(); - LLVector3 getValue(F32 time, F32 duration); - LLVector3 interp(F32 u, ScaleKey& before, ScaleKey& after); - - InterpolationType mInterpolationType; - S32 mNumKeys; - typedef std::map key_map_t; + struct Key + { + Key() = default; + Key(F32 time, const T& value) { mTime = time; mValue = value; } + F32 mTime = 0; + T mValue; + }; + + T interp(F32 u, Key& before, Key& after) + { + switch (mInterpolationType) + { + case IT_STEP: + return before.mValue; + default: + case IT_LINEAR: + case IT_SPLINE: + return LLKeyframeMotionLerp::lerp(u, before.mValue, after.mValue); + } + } + + T getValue(F32 time, F32 duration) + { + if (mKeys.empty()) + { + return T(); + } + + T value; + typename key_map_t::iterator right = std::lower_bound(mKeys.begin(), mKeys.end(), time, [](const auto& a, const auto& b) { return a.first < b; }); + if (right == mKeys.end()) + { + // Past last key + --right; + value = right->second.mValue; + } + else if (right == mKeys.begin() || right->first == time) + { + // Before first key or exactly on a key + value = right->second.mValue; + } + else + { + // Between two keys + typename key_map_t::iterator left = right; --left; + F32 index_before = left->first; + F32 index_after = right->first; + Key& pos_before = left->second; + Key& pos_after = right->second; + if (right == mKeys.end()) + { + pos_after = mLoopInKey; + index_after = duration; + } + + F32 u = (time - index_before) / (index_after - index_before); + value = interp(u, pos_before, pos_after); + } + return value; + } + + InterpolationType mInterpolationType = LLKeyframeMotion::IT_LINEAR; + S32 mNumKeys = 0; + typedef std::vector< std::pair > key_map_t; key_map_t mKeys; - ScaleKey mLoopInKey; - ScaleKey mLoopOutKey; + Key mLoopInKey; + Key mLoopOutKey; }; - //------------------------------------------------------------------------- - // RotationCurve - //------------------------------------------------------------------------- - class RotationCurve - { - public: - RotationCurve(); - ~RotationCurve(); - LLQuaternion getValue(F32 time, F32 duration); - LLQuaternion interp(F32 u, RotationKey& before, RotationKey& after); - - InterpolationType mInterpolationType; - S32 mNumKeys; - typedef std::map key_map_t; - key_map_t mKeys; - RotationKey mLoopInKey; - RotationKey mLoopOutKey; - }; - - //------------------------------------------------------------------------- - // PositionCurve - //------------------------------------------------------------------------- - class PositionCurve - { - public: - PositionCurve(); - ~PositionCurve(); - LLVector3 getValue(F32 time, F32 duration); - LLVector3 interp(F32 u, PositionKey& before, PositionKey& after); - - InterpolationType mInterpolationType; - S32 mNumKeys; - typedef std::map key_map_t; - key_map_t mKeys; - PositionKey mLoopInKey; - PositionKey mLoopOutKey; - }; + typedef Curve ScaleCurve; + typedef ScaleCurve::Key ScaleKey; + typedef Curve RotationCurve; + typedef RotationCurve::Key RotationKey; + typedef Curve PositionCurve; + typedef PositionCurve::Key PositionKey; //------------------------------------------------------------------------- // JointMotion diff --git a/indra/llcharacter/llkeyframewalkmotion.cpp b/indra/llcharacter/llkeyframewalkmotion.cpp index 8a6eedaaa2..3ec5b2cba3 100644 --- a/indra/llcharacter/llkeyframewalkmotion.cpp +++ b/indra/llcharacter/llkeyframewalkmotion.cpp @@ -140,14 +140,18 @@ BOOL LLKeyframeWalkMotion::onUpdate(F32 time, U8* joint_mask) //----------------------------------------------------------------------------- LLWalkAdjustMotion::LLWalkAdjustMotion(LLUUID const& id, LLMotionController* controller) : AIMaskedMotion(id, controller, ANIM_AGENT_WALK_ADJUST), + mCharacter(NULL), mLastTime(0.f), mAnimSpeed(0.f), mAdjustedSpeed(0.f), mRelativeDir(0.f), - mAnkleOffset(0.f) + mAnkleOffset(0.f), + mLeftAnkleJoint(NULL), + mRightAnkleJoint(NULL), + mPelvisJoint(NULL), + mPelvisState(new LLJointState) { mName = "walk_adjust"; - mPelvisState = new LLJointState; } //----------------------------------------------------------------------------- @@ -258,7 +262,7 @@ BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask) // but this will cause the animation playback rate calculation below to // kick in too slowly and sometimes start playing the animation in reverse. - //mPelvisOffset -= PELVIS_COMPENSATION_WIEGHT * (foot_slip_vector * world_to_avatar_rot);//lerp(LLVector3::zero, -1.f * (foot_slip_vector * world_to_avatar_rot), LLCriticalDamp::getInterpolant(0.1f)); + //mPelvisOffset -= PELVIS_COMPENSATION_WIEGHT * (foot_slip_vector * world_to_avatar_rot);//lerp(LLVector3::zero, -1.f * (foot_slip_vector * world_to_avatar_rot), LLSmoothInterpolation::getInterpolant(0.1f)); ////F32 drift_comp_max = DRIFT_COMP_MAX_TOTAL * (llclamp(speed, 0.f, DRIFT_COMP_MAX_SPEED) / DRIFT_COMP_MAX_SPEED); //F32 drift_comp_max = DRIFT_COMP_MAX_TOTAL; @@ -287,7 +291,7 @@ BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask) F32 desired_speed_multiplier = llclamp(speed / foot_speed, min_speed_multiplier, ANIM_SPEED_MAX); // blend towards new speed adjustment value - F32 new_speed_adjust = lerp(mAdjustedSpeed, desired_speed_multiplier, LLCriticalDamp::getInterpolant(SPEED_ADJUST_TIME_CONSTANT)); + F32 new_speed_adjust = LLSmoothInterpolation::lerp(mAdjustedSpeed, desired_speed_multiplier, SPEED_ADJUST_TIME_CONSTANT); // limit that rate at which the speed adjustment changes F32 speedDelta = llclamp(new_speed_adjust - mAdjustedSpeed, -SPEED_ADJUST_MAX_SEC * delta_time, SPEED_ADJUST_MAX_SEC * delta_time); @@ -305,8 +309,8 @@ BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask) { // standing/turning // damp out speed adjustment to 0 - mAnimSpeed = lerp(mAnimSpeed, 1.f, LLCriticalDamp::getInterpolant(0.2f)); - //mPelvisOffset = lerp(mPelvisOffset, LLVector3::zero, LLCriticalDamp::getInterpolant(0.2f)); + mAnimSpeed = LLSmoothInterpolation::lerp(mAnimSpeed, 1.f, 0.2f); + //mPelvisOffset = lerp(mPelvisOffset, LLVector3::zero, LLSmoothInterpolation::getInterpolant(0.2f)); } // broadcast walk speed change @@ -333,6 +337,7 @@ void LLWalkAdjustMotion::onDeactivate() //----------------------------------------------------------------------------- LLFlyAdjustMotion::LLFlyAdjustMotion(LLUUID const& id, LLMotionController* controller) : AIMaskedMotion(id, controller, ANIM_AGENT_FLY_ADJUST), + mCharacter(NULL), mRoll(0.f) { mName = "fly_adjust"; @@ -384,7 +389,7 @@ BOOL LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask) F32 target_roll = llclamp(ang_vel.mV[VZ], -4.f, 4.f) * roll_factor; // roll is critically damped interpolation between current roll and angular velocity-derived target roll - mRoll = lerp(mRoll, target_roll, LLCriticalDamp::getInterpolant(0.1f)); + mRoll = LLSmoothInterpolation::lerp(mRoll, target_roll, U32Milliseconds(100)); LLQuaternion roll(mRoll, LLVector3(0.f, 0.f, 1.f)); mPelvisState->setRotation(roll); diff --git a/indra/llcharacter/llmotion.cpp b/indra/llcharacter/llmotion.cpp index 526341d20f..6a70c76b9a 100644 --- a/indra/llcharacter/llmotion.cpp +++ b/indra/llcharacter/llmotion.cpp @@ -180,8 +180,8 @@ LLMotion::LLMotion(LLUUID const& id, LLMotionController* controller) : mDeactivateCallback(NULL), mDeactivateCallbackUserData(NULL) { - for (int i=0; i<3; ++i) - memset(&mJointSignature[i][0], 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS); + for (S32 i=0; i<3; ++i) + memset(&mJointSignature[i][0], 0, sizeof(U8) * LL_CHARACTER_MAX_ANIMATED_JOINTS); } //----------------------------------------------------------------------------- @@ -199,7 +199,7 @@ void LLMotion::fadeOut() { if (mFadeWeight > 0.01f) { - mFadeWeight = lerp(mFadeWeight, 0.f, LLCriticalDamp::getInterpolant(0.15f)); + mFadeWeight = lerp(mFadeWeight, 0.f, LLSmoothInterpolation::getInterpolant(0.15f)); } else { @@ -214,7 +214,7 @@ void LLMotion::fadeIn() { if (mFadeWeight < 0.99f) { - mFadeWeight = lerp(mFadeWeight, 1.f, LLCriticalDamp::getInterpolant(0.15f)); + mFadeWeight = lerp(mFadeWeight, 1.f, LLSmoothInterpolation::getInterpolant(0.15f)); } else { @@ -237,9 +237,15 @@ void LLMotion::addJointState(const LLPointer& jointState) U32 usage = jointState->getUsage(); // for now, usage is everything - mJointSignature[0][jointState->getJoint()->getJointNum()] = (usage & LLJointState::POS) ? (0xff >> (7 - priority)) : 0; - mJointSignature[1][jointState->getJoint()->getJointNum()] = (usage & LLJointState::ROT) ? (0xff >> (7 - priority)) : 0; - mJointSignature[2][jointState->getJoint()->getJointNum()] = (usage & LLJointState::SCALE) ? (0xff >> (7 - priority)) : 0; + S32 joint_num = jointState->getJoint()->getJointNum(); + if ((joint_num >= (S32)LL_CHARACTER_MAX_ANIMATED_JOINTS) || (joint_num < 0)) + { + LL_WARNS() << "joint_num " << joint_num << " is outside of legal range [0-" << LL_CHARACTER_MAX_ANIMATED_JOINTS << ") for joint " << jointState->getJoint()->getName() << LL_ENDL; + return; + } + mJointSignature[0][joint_num] = (usage & LLJointState::POS) ? (0xff >> (7 - priority)) : 0; + mJointSignature[1][joint_num] = (usage & LLJointState::ROT) ? (0xff >> (7 - priority)) : 0; + mJointSignature[2][joint_num] = (usage & LLJointState::SCALE) ? (0xff >> (7 - priority)) : 0; } void LLMotion::setDeactivateCallback( void (*cb)(void *), void* userdata ) diff --git a/indra/llcharacter/llmotion.h b/indra/llcharacter/llmotion.h index 8fe6010abf..6448310b2c 100644 --- a/indra/llcharacter/llmotion.h +++ b/indra/llcharacter/llmotion.h @@ -274,7 +274,7 @@ class LLMotion : public AISyncClientMotion F32 mSendStopTimestamp; // time when simulator should be told to stop this motion F32 mResidualWeight; // blend weight at beginning of stop motion phase F32 mFadeWeight; // for fading in and out based on LOD - U8 mJointSignature[3][LL_CHARACTER_MAX_JOINTS]; // signature of which joints are animated at what priority + U8 mJointSignature[3][LL_CHARACTER_MAX_ANIMATED_JOINTS]; // signature of which joints are animated at what priority void (*mDeactivateCallback)(void* data); void* mDeactivateCallbackUserData; }; diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index 6d1ae77613..3f5b65f527 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -42,7 +42,7 @@ #include "llanimationstates.h" #include "llstl.h" -const S32 NUM_JOINT_SIGNATURE_STRIDES = LL_CHARACTER_MAX_JOINTS / 4; +const S32 NUM_JOINT_SIGNATURE_STRIDES = LL_CHARACTER_MAX_ANIMATED_JOINTS / 4; const U32 MAX_MOTION_INSTANCES = 32; //----------------------------------------------------------------------------- @@ -83,7 +83,7 @@ LLMotionRegistry::~LLMotionRegistry() BOOL LLMotionRegistry::registerMotion( const LLUUID& id, LLMotionConstructor constructor ) { // LL_INFOS() << "Registering motion: " << name << LL_ENDL; - return mMotionTable.insert(std::make_pair(id,constructor)).second; + return mMotionTable.emplace(id, constructor).second; } //----------------------------------------------------------------------------- @@ -126,22 +126,22 @@ LLMotion* LLMotionRegistry::createMotion(LLUUID const& id, LLMotionController* c // Class Constructor //----------------------------------------------------------------------------- LLMotionController::LLMotionController() - : mIsSelf(FALSE), - mTimeFactor(sCurrentTimeFactor), + : mTimeFactor(sCurrentTimeFactor), mCharacter(NULL), + mAnimTime(0.f), mActiveMask(0), mDisableSyncing(0), mHidden(false), mHaveVisibleSyncedMotions(false), mPrevTimerElapsed(0.f), - mAnimTime(0.f), mLastTime(0.0f), mHasRunOnce(FALSE), mPaused(FALSE), - mPauseTime(0.f), + mPausedFrame(0), mTimeStep(0.f), mTimeStepCount(0), - mLastInterp(0.f) + mLastInterp(0.f), + mIsSelf(FALSE) { } @@ -200,7 +200,7 @@ void LLMotionController::purgeExcessMotions() } // - std::set motions_to_kill; + uuid_set_t motions_to_kill; if (1) // Singu: leave indentation alone... { @@ -220,7 +220,7 @@ void LLMotionController::purgeExcessMotions() } // clean up all inactive, loaded motions - for (std::set::iterator motion_it = motions_to_kill.begin(); + for (auto motion_it = motions_to_kill.begin(); motion_it != motions_to_kill.end(); ++motion_it) { @@ -467,7 +467,7 @@ BOOL LLMotionController::stopMotionLocally(const LLUUID &id, BOOL stop_immediate { // if already inactive, return false LLMotion *motion = findMotion(id); - return stopMotionInstance(motion, stop_immediate); + return stopMotionInstance(motion, stop_immediate||mPaused); } BOOL LLMotionController::stopMotionInstance(LLMotion* motion, BOOL stop_immediate) @@ -517,8 +517,8 @@ void LLMotionController::updateAdditiveMotions() //----------------------------------------------------------------------------- void LLMotionController::resetJointSignatures() { - memset(&mJointSignature[0][0], 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS); - memset(&mJointSignature[1][0], 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS); + memset(&mJointSignature[0][0], 0, sizeof(U8) * LL_CHARACTER_MAX_ANIMATED_JOINTS); + memset(&mJointSignature[1][0], 0, sizeof(U8) * LL_CHARACTER_MAX_ANIMATED_JOINTS); } //----------------------------------------------------------------------------- @@ -577,14 +577,12 @@ void LLMotionController::updateIdleActiveMotions() //----------------------------------------------------------------------------- // updateMotionsByType() //----------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_MOTION_ON_UPDATE("Motion onUpdate"); +static LLTrace::BlockTimerStatHandle FTM_MOTION_ON_UPDATE("Motion onUpdate"); void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_type) { BOOL update_result = TRUE; - U8 last_joint_signature[LL_CHARACTER_MAX_JOINTS]; - - memset(&last_joint_signature, 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS); + U8 last_joint_signature[LL_CHARACTER_MAX_ANIMATED_JOINTS] = {0}; // iterate through active motions in chronological order for (motion_list_t::iterator iter = mActiveMotions.begin(); @@ -737,7 +735,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty // perform motion update { - LLFastTimer t(FTM_MOTION_ON_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_MOTION_ON_UPDATE); update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature); } } @@ -881,7 +879,7 @@ void LLMotionController::updateMotions(bool force_update) // Moreover, just rounding off to the nearest integer with ll_round(update_time / mTimeStep) makes a lot more sense: // it is the best we can do to get as close to what we should draw as possible. // However, mAnimTime may only be incremented; therefore make sure of that with the llmax. - S32 quantum_count = llmax(ll_round(update_time / mTimeStep), llceil(mAnimTime / mTimeStep)); + S32 quantum_count = llmax(ll_pos_round(update_time / mTimeStep), llceil(mAnimTime / mTimeStep)); // if (quantum_count == mTimeStepCount) { @@ -1314,6 +1312,7 @@ void LLMotionController::pauseAllMotions() { //LL_INFOS() << "Pausing animations..." << LL_ENDL; mPaused = TRUE; + mPausedFrame = LLFrameTimer::getFrameCount(); } } diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h index 054f1c2f98..843cac4252 100644 --- a/indra/llcharacter/llmotioncontroller.h +++ b/indra/llcharacter/llmotioncontroller.h @@ -162,16 +162,20 @@ class LLMotionController void pauseAllMotions(); void unpauseAllMotions(); BOOL isPaused() const { return mPaused; } + U64 getPausedFrame() const { return mPausedFrame; } // void requestPause(std::vector& avatar_pause_handles); void pauseAllSyncedCharacters(std::vector& avatar_pause_handles); // void setTimeStep(F32 step); + F32 getTimeStep() const { return mTimeStep; } void setTimeFactor(F32 time_factor); F32 getTimeFactor() const { return mTimeFactor; } + F32 getAnimTime() const { return mAnimTime; } + motion_list_t& getActiveMotions() { return mActiveMotions; } void incMotionCounts(S32& num_motions, S32& num_loading_motions, S32& num_loaded_motions, S32& num_active_motions, S32& num_deprecated_motions); @@ -248,12 +252,12 @@ class LLMotionController F32 mLastTime; BOOL mHasRunOnce; BOOL mPaused; - F32 mPauseTime; + U64 mPausedFrame; F32 mTimeStep; S32 mTimeStepCount; F32 mLastInterp; - U8 mJointSignature[2][LL_CHARACTER_MAX_JOINTS]; + U8 mJointSignature[2][LL_CHARACTER_MAX_ANIMATED_JOINTS]; // public: @@ -263,7 +267,6 @@ class LLMotionController bool syncing_disabled(void) const { return mDisableSyncing >= 100; } // Accessors needed for synchronization. - F32 getAnimTime(void) const { return mAnimTime; } bool isHidden(void) const { return mHidden; } // Called often. Should return false if we still need to keep updating our motions even if we're not visible. diff --git a/indra/llcharacter/llmultigesture.cpp b/indra/llcharacter/llmultigesture.cpp index a689e840a2..64de502b60 100644 --- a/indra/llcharacter/llmultigesture.cpp +++ b/indra/llcharacter/llmultigesture.cpp @@ -36,7 +36,7 @@ #include "lldatapacker.h" #include "llstl.h" -const S32 GESTURE_VERSION = 2; +constexpr S32 GESTURE_VERSION = 2; //--------------------------------------------------------------------------- // LLMultiGesture @@ -48,10 +48,10 @@ LLMultiGesture::LLMultiGesture() mTrigger(), mReplaceText(), mSteps(), - mPlaying(FALSE), + mPlaying(false), mLocal(false), mCurrentStep(0), - mDoneCallback(NULL) + mDoneCallback(nullptr) { reset(); } @@ -63,13 +63,13 @@ LLMultiGesture::~LLMultiGesture() void LLMultiGesture::reset() { - mPlaying = FALSE; + mPlaying = false; mLocal = false; mCurrentStep = 0; mWaitTimer.reset(); - mWaitingTimer = FALSE; - mWaitingAnimations = FALSE; - mWaitingAtEnd = FALSE; + mWaitingTimer = false; + mWaitingAnimations = false; + mWaitingAtEnd = false; mRequestedAnimIDs.clear(); mPlayingAnimIDs.clear(); } @@ -88,10 +88,8 @@ S32 LLMultiGesture::getMaxSerialSize() const max_size += 64; // step count S32 - std::vector::const_iterator it; - for (it = mSteps.begin(); it != mSteps.end(); ++it) + for (const auto& step : mSteps) { - LLGestureStep* step = *it; max_size += 64; // type S32 max_size += step->getMaxSerialSize(); } @@ -104,10 +102,8 @@ S32 LLMultiGesture::getMaxSerialSize() const max_size += sizeof(S32); // step count - std::vector::const_iterator it; - for (it = mSteps.begin(); it != mSteps.end(); ++it) + for (const auto& step : mSteps) { - LLGestureStep* step = *it; max_size += sizeof(S32); // type max_size += step->getMaxSerialSize(); } @@ -116,7 +112,7 @@ S32 LLMultiGesture::getMaxSerialSize() const return max_size; } -BOOL LLMultiGesture::serialize(LLDataPacker& dp) const +bool LLMultiGesture::serialize(LLDataPacker& dp) const { dp.packS32(GESTURE_VERSION, "version"); dp.packU8(mKey, "key"); @@ -126,22 +122,18 @@ BOOL LLMultiGesture::serialize(LLDataPacker& dp) const S32 count = (S32)mSteps.size(); dp.packS32(count, "step_count"); - S32 i; - for (i = 0; i < count; ++i) + for (const auto& step : mSteps) { - LLGestureStep* step = mSteps[i]; - dp.packS32(step->getType(), "step_type"); - BOOL ok = step->serialize(dp); - if (!ok) + if (!step->serialize(dp)) { - return FALSE; + return false; } } - return TRUE; + return true; } -BOOL LLMultiGesture::deserialize(LLDataPacker& dp) +bool LLMultiGesture::deserialize(LLDataPacker& dp) { S32 version; dp.unpackS32(version, "version"); @@ -150,15 +142,12 @@ BOOL LLMultiGesture::deserialize(LLDataPacker& dp) LL_WARNS() << "Bad LLMultiGesture version " << version << " should be " << GESTURE_VERSION << LL_ENDL; - return FALSE; + return false; } dp.unpackU8(mKey, "key"); dp.unpackU32(mMask, "mask"); - - dp.unpackString(mTrigger, "trigger"); - dp.unpackString(mReplaceText, "replace"); S32 count; @@ -166,58 +155,31 @@ BOOL LLMultiGesture::deserialize(LLDataPacker& dp) if (count < 0) { LL_WARNS() << "Bad LLMultiGesture step count " << count << LL_ENDL; - return FALSE; + return false; } - S32 i; - for (i = 0; i < count; ++i) + std::unique_ptr step; + for (S32 i = 0; i < count; ++i) { S32 type; dp.unpackS32(type, "step_type"); - EStepType step_type = (EStepType)type; - switch(step_type) + switch((EStepType)type) { - case STEP_ANIMATION: - { - LLGestureStepAnimation* step = new LLGestureStepAnimation(); - BOOL ok = step->deserialize(dp); - if (!ok) return FALSE; - mSteps.push_back(step); - break; - } - case STEP_SOUND: - { - LLGestureStepSound* step = new LLGestureStepSound(); - BOOL ok = step->deserialize(dp); - if (!ok) return FALSE; - mSteps.push_back(step); - break; - } - case STEP_CHAT: - { - LLGestureStepChat* step = new LLGestureStepChat(); - BOOL ok = step->deserialize(dp); - if (!ok) return FALSE; - mSteps.push_back(step); - break; - } - case STEP_WAIT: - { - LLGestureStepWait* step = new LLGestureStepWait(); - BOOL ok = step->deserialize(dp); - if (!ok) return FALSE; - mSteps.push_back(step); - break; - } + case STEP_ANIMATION: step.reset(new LLGestureStepAnimation); break; + case STEP_SOUND: step.reset(new LLGestureStepSound); break; + case STEP_CHAT: step.reset(new LLGestureStepChat); break; + case STEP_WAIT: step.reset(new LLGestureStepWait); break; default: { LL_WARNS() << "Bad LLMultiGesture step type " << type << LL_ENDL; - return FALSE; + return false; } } + if (!step->deserialize(dp)) return false; + mSteps.push_back(step.release()); } - return TRUE; + return true; } void LLMultiGesture::dump() @@ -226,10 +188,8 @@ void LLMultiGesture::dump() << " trigger " << mTrigger << " replace " << mReplaceText << LL_ENDL; - U32 i; - for (i = 0; i < mSteps.size(); ++i) + for (const auto& step : mSteps) { - LLGestureStep* step = mSteps[i]; step->dump(); } } @@ -264,21 +224,21 @@ S32 LLGestureStepAnimation::getMaxSerialSize() const return max_size; } -BOOL LLGestureStepAnimation::serialize(LLDataPacker& dp) const +bool LLGestureStepAnimation::serialize(LLDataPacker& dp) const { dp.packString(mAnimName, "anim_name"); dp.packUUID(mAnimAssetID, "asset_id"); dp.packU32(mFlags, "flags"); - return TRUE; + return true; } -BOOL LLGestureStepAnimation::deserialize(LLDataPacker& dp) +bool LLGestureStepAnimation::deserialize(LLDataPacker& dp) { dp.unpackString(mAnimName, "anim_name"); // Apparently an earlier version of the gesture code added \r to the end // of the animation names. Get rid of it. JC - if (!mAnimName.empty() && mAnimName[mAnimName.length() - 1] == '\r') + if (!mAnimName.empty() && mAnimName.back() == '\r') { // chop the last character mAnimName.resize(mAnimName.length() - 1); @@ -286,29 +246,18 @@ BOOL LLGestureStepAnimation::deserialize(LLDataPacker& dp) dp.unpackUUID(mAnimAssetID, "asset_id"); dp.unpackU32(mFlags, "flags"); - return TRUE; + return true; } // *NOTE: result is translated in LLPreviewGesture::getLabel() std::vector LLGestureStepAnimation::getLabel() const { - std::vector strings; - -// std::string label; +/* std::string label; if (mFlags & ANIM_FLAG_STOP) - { - strings.push_back( "AnimFlagStop"); - -// label = "Stop Animation: "; - } + label = "Stop Animation: "; else - { - strings.push_back( "AnimFlagStart"); - -// label = "Start Animation: "; - } - strings.push_back( mAnimName); -// label += mAnimName; - return strings; + label = "Start Animation: "; + label += mAnimName;*/ + return {mFlags & ANIM_FLAG_STOP ? "AnimFlagStop" : "AnimFlagStart", mAnimName}; } void LLGestureStepAnimation::dump() @@ -346,31 +295,28 @@ S32 LLGestureStepSound::getMaxSerialSize() const return max_size; } -BOOL LLGestureStepSound::serialize(LLDataPacker& dp) const +bool LLGestureStepSound::serialize(LLDataPacker& dp) const { dp.packString(mSoundName, "sound_name"); dp.packUUID(mSoundAssetID, "asset_id"); dp.packU32(mFlags, "flags"); - return TRUE; + return true; } -BOOL LLGestureStepSound::deserialize(LLDataPacker& dp) +bool LLGestureStepSound::deserialize(LLDataPacker& dp) { dp.unpackString(mSoundName, "sound_name"); dp.unpackUUID(mSoundAssetID, "asset_id"); dp.unpackU32(mFlags, "flags"); - return TRUE; + return true; } // *NOTE: result is translated in LLPreviewGesture::getLabel() std::vector LLGestureStepSound::getLabel() const { - std::vector strings; - strings.push_back( "Sound"); - strings.push_back( mSoundName); // std::string label("Sound: "); // label += mSoundName; - return strings; + return {"Sound", mSoundName}; } void LLGestureStepSound::dump() @@ -406,27 +352,23 @@ S32 LLGestureStepChat::getMaxSerialSize() const return max_size; } -BOOL LLGestureStepChat::serialize(LLDataPacker& dp) const +bool LLGestureStepChat::serialize(LLDataPacker& dp) const { dp.packString(mChatText, "chat_text"); dp.packU32(mFlags, "flags"); - return TRUE; + return true; } -BOOL LLGestureStepChat::deserialize(LLDataPacker& dp) +bool LLGestureStepChat::deserialize(LLDataPacker& dp) { dp.unpackString(mChatText, "chat_text"); - dp.unpackU32(mFlags, "flags"); - return TRUE; + return true; } // *NOTE: result is translated in LLPreviewGesture::getLabel() std::vector LLGestureStepChat::getLabel() const { - std::vector strings; - strings.push_back("Chat"); - strings.push_back(mChatText); - return strings; + return {"Chat", mChatText}; } void LLGestureStepChat::dump() @@ -461,44 +403,26 @@ S32 LLGestureStepWait::getMaxSerialSize() const return max_size; } -BOOL LLGestureStepWait::serialize(LLDataPacker& dp) const +bool LLGestureStepWait::serialize(LLDataPacker& dp) const { dp.packF32(mWaitSeconds, "wait_seconds"); dp.packU32(mFlags, "flags"); - return TRUE; + return true; } -BOOL LLGestureStepWait::deserialize(LLDataPacker& dp) +bool LLGestureStepWait::deserialize(LLDataPacker& dp) { dp.unpackF32(mWaitSeconds, "wait_seconds"); dp.unpackU32(mFlags, "flags"); - return TRUE; + return true; } // *NOTE: result is translated in LLPreviewGesture::getLabel() std::vector LLGestureStepWait::getLabel() const { - std::vector strings; - strings.push_back( "Wait" ); - -// std::string label("--- Wait: "); - if (mFlags & WAIT_FLAG_TIME) - { - char buffer[64]; /* Flawfinder: ignore */ - snprintf(buffer, sizeof(buffer), "%.1f seconds", (double)mWaitSeconds); /* Flawfinder: ignore */ - strings.push_back(buffer); -// label += buffer; - } - else if (mFlags & WAIT_FLAG_ALL_ANIM) - { - strings.push_back("until animations are done"); - // label += "until animations are done"; - } - else - { - strings.push_back(""); - } - - return strings; + return {"Wait", + mFlags & WAIT_FLAG_TIME ? llformat("%.1f seconds", mWaitSeconds) + : mFlags & WAIT_FLAG_ALL_ANIM ? "until animations are done" + : LLStringUtil::null}; } diff --git a/indra/llcharacter/llmultigesture.h b/indra/llcharacter/llmultigesture.h index 8e48213578..68395465bf 100644 --- a/indra/llcharacter/llmultigesture.h +++ b/indra/llcharacter/llmultigesture.h @@ -27,7 +27,7 @@ #ifndef LL_LLMULTIGESTURE_H #define LL_LLMULTIGESTURE_H -#include +#include #include #include @@ -46,8 +46,8 @@ class LLMultiGesture // Maximum number of bytes this could hold once serialized. S32 getMaxSerialSize() const; - BOOL serialize(LLDataPacker& dp) const; - BOOL deserialize(LLDataPacker& dp); + bool serialize(LLDataPacker& dp) const; + bool deserialize(LLDataPacker& dp); void dump(); @@ -77,7 +77,7 @@ class LLMultiGesture std::vector mSteps; // Is the gesture currently playing? - BOOL mPlaying; + bool mPlaying; // Is the gesture to be played locally? bool mLocal; @@ -86,25 +86,25 @@ class LLMultiGesture S32 mCurrentStep; // We're waiting for triggered animations to stop playing - BOOL mWaitingAnimations; + bool mWaitingAnimations; // We're waiting a fixed amount of time - BOOL mWaitingTimer; + bool mWaitingTimer; // Waiting after the last step played for all animations to complete - BOOL mWaitingAtEnd; + bool mWaitingAtEnd; // Timer for waiting LLFrameTimer mWaitTimer; - boost::function mDoneCallback; + std::function mDoneCallback; // Animations that we requested to start - std::set mRequestedAnimIDs; + uuid_set_t mRequestedAnimIDs; // Once the animation starts playing (sim says to start playing) // the ID is moved from mRequestedAnimIDs to here. - std::set mPlayingAnimIDs; + uuid_set_t mPlayingAnimIDs; }; @@ -127,14 +127,14 @@ class LLGestureStep LLGestureStep() {} virtual ~LLGestureStep() {} - virtual EStepType getType() = 0; + virtual EStepType getType() const = 0; // Return a user-readable label for this step virtual std::vector getLabel() const = 0; virtual S32 getMaxSerialSize() const = 0; - virtual BOOL serialize(LLDataPacker& dp) const = 0; - virtual BOOL deserialize(LLDataPacker& dp) = 0; + virtual bool serialize(LLDataPacker& dp) const = 0; + virtual bool deserialize(LLDataPacker& dp) = 0; virtual void dump() = 0; }; @@ -142,7 +142,7 @@ class LLGestureStep // By default, animation steps start animations. // If the least significant bit is 1, it will stop animations. -const U32 ANIM_FLAG_STOP = 0x01; +constexpr U32 ANIM_FLAG_STOP = 0x01; class LLGestureStepAnimation : public LLGestureStep { @@ -150,15 +150,15 @@ class LLGestureStepAnimation : public LLGestureStep LLGestureStepAnimation(); virtual ~LLGestureStepAnimation(); - virtual EStepType getType() { return STEP_ANIMATION; } + EStepType getType() const override { return STEP_ANIMATION; } - virtual std::vector getLabel() const; + std::vector getLabel() const override; - virtual S32 getMaxSerialSize() const; - virtual BOOL serialize(LLDataPacker& dp) const; - virtual BOOL deserialize(LLDataPacker& dp); + S32 getMaxSerialSize() const override; + bool serialize(LLDataPacker& dp) const override; + bool deserialize(LLDataPacker& dp) override; - virtual void dump(); + void dump() override; public: std::string mAnimName; @@ -173,15 +173,15 @@ class LLGestureStepSound : public LLGestureStep LLGestureStepSound(); virtual ~LLGestureStepSound(); - virtual EStepType getType() { return STEP_SOUND; } + EStepType getType() const override { return STEP_SOUND; } - virtual std::vector getLabel() const; + std::vector getLabel() const override; - virtual S32 getMaxSerialSize() const; - virtual BOOL serialize(LLDataPacker& dp) const; - virtual BOOL deserialize(LLDataPacker& dp); + S32 getMaxSerialSize() const override; + bool serialize(LLDataPacker& dp) const override; + bool deserialize(LLDataPacker& dp) override; - virtual void dump(); + void dump() override; public: std::string mSoundName; @@ -196,15 +196,15 @@ class LLGestureStepChat : public LLGestureStep LLGestureStepChat(); virtual ~LLGestureStepChat(); - virtual EStepType getType() { return STEP_CHAT; } + EStepType getType() const override { return STEP_CHAT; } - virtual std::vector getLabel() const; + std::vector getLabel() const override; - virtual S32 getMaxSerialSize() const; - virtual BOOL serialize(LLDataPacker& dp) const; - virtual BOOL deserialize(LLDataPacker& dp); + S32 getMaxSerialSize() const override; + bool serialize(LLDataPacker& dp) const override; + bool deserialize(LLDataPacker& dp) override; - virtual void dump(); + void dump() override; public: std::string mChatText; @@ -212,8 +212,8 @@ class LLGestureStepChat : public LLGestureStep }; -const U32 WAIT_FLAG_TIME = 0x01; -const U32 WAIT_FLAG_ALL_ANIM = 0x02; +constexpr U32 WAIT_FLAG_TIME = 0x01; +constexpr U32 WAIT_FLAG_ALL_ANIM = 0x02; class LLGestureStepWait : public LLGestureStep { @@ -221,15 +221,15 @@ class LLGestureStepWait : public LLGestureStep LLGestureStepWait(); virtual ~LLGestureStepWait(); - virtual EStepType getType() { return STEP_WAIT; } + EStepType getType() const override { return STEP_WAIT; } - virtual std::vector getLabel() const; + std::vector getLabel() const override; - virtual S32 getMaxSerialSize() const; - virtual BOOL serialize(LLDataPacker& dp) const; - virtual BOOL deserialize(LLDataPacker& dp); + S32 getMaxSerialSize() const override; + bool serialize(LLDataPacker& dp) const override; + bool deserialize(LLDataPacker& dp) override; - virtual void dump(); + void dump() override; public: F32 mWaitSeconds; diff --git a/indra/llcharacter/lltargetingmotion.cpp b/indra/llcharacter/lltargetingmotion.cpp index 7396a1ff53..9dd581f308 100644 --- a/indra/llcharacter/lltargetingmotion.cpp +++ b/indra/llcharacter/lltargetingmotion.cpp @@ -104,7 +104,7 @@ LLMotion::LLMotionInitStatus LLTargetingMotion::onInitialize(LLCharacter *charac //----------------------------------------------------------------------------- BOOL LLTargetingMotion::onUpdate(F32 time, U8* joint_mask) { - F32 slerp_amt = LLCriticalDamp::getInterpolant(TORSO_TARGET_HALF_LIFE); + F32 slerp_amt = LLSmoothInterpolation::getInterpolant(TORSO_TARGET_HALF_LIFE); LLVector3 target; LLVector3* lookAtPoint = (LLVector3*)mCharacter->getAnimationData("LookAtPoint"); diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h index ba6a3d6678..7a6f6a0a1d 100644 --- a/indra/llcharacter/llvisualparam.h +++ b/indra/llcharacter/llvisualparam.h @@ -30,10 +30,6 @@ #include "v3math.h" #include "llstring.h" #include "llxmltree.h" -#ifndef BOOST_FUNCTION_HPP_INCLUDED -#include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif class LLPolyMesh; class LLXmlTreeNode; @@ -107,11 +103,23 @@ LL_ALIGN_PREFIX(16) class LLVisualParam { public: - typedef boost::function visual_param_mapper; + typedef std::function visual_param_mapper; LLVisualParam(); virtual ~LLVisualParam(); + // + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + // + // Special: These functions are overridden by child classes // (They can not be virtual because they use specific derived Info classes) LLVisualParamInfo* getInfo() const { return mInfo; } diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 72e03e7092..ea99d74296 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -4,21 +4,29 @@ project(llcommon) include(Cwdebug) include(00-Common) +include(Linking) include(LLCommon) +include(EXPAT) include(APR) include(Linking) -include(GoogleBreakpad) +include(Boost) +include(OpenSSL) +include(LLSharedLibs) +include(Copy3rdPartyLibs) +include(ZLIB) +include(URIPARSER) include_directories( ${EXPAT_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS} + ${OPENSSL_INCLUDE_DIRS} + ${JSON_INCLUDE_DIR} ${ZLIB_INCLUDE_DIRS} ${BREAKPAD_INCLUDE_DIRECTORIES} ) set(llcommon_SOURCE_FILES aialert.cpp - aifile.cpp aiframetimer.cpp aisyncclient.cpp aithreadid.cpp @@ -32,6 +40,7 @@ set(llcommon_SOURCE_FILES llassettype.cpp llbase32.cpp llbase64.cpp + llcallbacklist.cpp llcommon.cpp llcommonutils.cpp llcoros.cpp @@ -78,6 +87,7 @@ set(llcommon_SOURCE_FILES llrun.cpp llscopedvolatileaprpool.h llsd.cpp + llsdjson.cpp llsdparam.cpp llsdserialize.cpp llsdserialize_xml.cpp @@ -94,6 +104,7 @@ set(llcommon_SOURCE_FILES llthreadsafequeue.cpp lltimer.cpp lluri.cpp + lluriparser.cpp lluuid.cpp llworkerthread.cpp metaclass.cpp @@ -107,7 +118,6 @@ set(llcommon_HEADER_FILES CMakeLists.txt aialert.h - aifile.h aiframetimer.h airecursive.h aisyncclient.h @@ -134,6 +144,7 @@ set(llcommon_HEADER_FILES llbase32.h llbase64.h llboost.h + llcallbacklist.h llchat.h llclickaction.h llcommon.h @@ -202,6 +213,7 @@ set(llcommon_HEADER_FILES llrun.h llsafehandle.h llsd.h + llsdjson.h llsdparam.h llsdserialize.h llsdserialize_xml.h @@ -226,10 +238,14 @@ set(llcommon_HEADER_FILES llthreadsafequeue.h lltimer.h lltreeiterators.h + llunits.h + llunittype.h lltypeinfolookup.h lluri.h + lluriparser.h lluuid.h - llversionviewer.h.in + llwin32headers.h + llwin32headerslean.h llworkerthread.h metaclass.h metaclasst.h @@ -249,19 +265,32 @@ set_source_files_properties(${llcommon_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) list(APPEND llcommon_SOURCE_FILES ${cwdebug_SOURCE_FILES}) + list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) -add_library (llcommon SHARED ${llcommon_SOURCE_FILES}) -if(WINDOWS) -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") -endif(WINDOWS) -add_dependencies(llcommon prepare) +if(LLCOMMON_LINK_SHARED) + add_library (llcommon SHARED ${llcommon_SOURCE_FILES}) + if(WINDOWS) + # always generate llcommon.pdb, even for "Release" builds + set_target_properties(llcommon PROPERTIES LINK_FLAGS "/DEBUG") + endif(WINDOWS) + ll_stage_sharedlib(llcommon) +else(LLCOMMON_LINK_SHARED) + add_library (llcommon ${llcommon_SOURCE_FILES}) +endif(LLCOMMON_LINK_SHARED) + +set_target_properties(llcommon PROPERTIES POSITION_INDEPENDENT_CODE TRUE) + target_link_libraries( llcommon - ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES} + PUBLIC + absl::hash ${APRUTIL_LIBRARIES} ${APR_LIBRARIES} ${EXPAT_LIBRARIES} + ${CRYPTO_LIBRARIES} + ${OPENSSL_LIBRARIES} + ${CRYPTO_LIBRARIES} ${ZLIB_LIBRARIES} ${WINDOWS_LIBRARIES} ${Boost_CONTEXT_LIBRARY} @@ -269,6 +298,11 @@ target_link_libraries( ${Boost_THREAD_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${CORESERVICES_LIBRARY} + ${URIPARSER_LIBRARY} + fmt::fmt + nlohmann_json::nlohmann_json + absl::strings + ${RT_LIBRARY} ) if (DARWIN) @@ -280,3 +314,5 @@ if (DARWIN) INSTALL_NAME_DIR "@executable_path/../Resources" ) endif (DARWIN) + +add_dependencies(llcommon stage_third_party_libs) diff --git a/indra/llcommon/aialert.h b/indra/llcommon/aialert.h index 4d3704cfbc..17042cfcc3 100644 --- a/indra/llcommon/aialert.h +++ b/indra/llcommon/aialert.h @@ -132,7 +132,7 @@ class LL_COMMON_API AIArgs // Add another replacement. AIArgs& operator()(char const* key, std::string const& replacement) { mArgs[key] = replacement; return *this; } // The destructor may not throw. - ~AIArgs() throw() { } + ~AIArgs() noexcept { } // Accessor. LLStringUtil::format_map_t const& operator*() const { return mArgs; } @@ -193,7 +193,7 @@ class LL_COMMON_API Line Line(std::string const& xml_desc, AIArgs const& args, bool newline = false) : mNewline(newline), mXmlDesc(xml_desc), mArgs(args), mType(normal) { } Line(Prefix const& prefix, bool newline = false) : mNewline(newline), mXmlDesc("AIPrefix"), mArgs("[PREFIX]", prefix.str()), mType(prefix.type()) { } // The destructor may not throw. - ~Line() throw() { } + ~Line() noexcept { } // Prepend a newline before this line. void set_newline(void) { mNewline = true; } @@ -225,7 +225,7 @@ class LL_COMMON_API Error : public std::exception typedef std::deque lines_type; // The destructor may not throw. - ~Error() throw() { } + ~Error() noexcept { } // Accessors. lines_type const& lines(void) const { return mLines; } @@ -267,7 +267,7 @@ class LL_COMMON_API ErrorCode : public Error public: // The destructor may not throw. - ~ErrorCode() throw() { } + ~ErrorCode() noexcept { } // Accessor. int getCode(void) const { return mCode; } diff --git a/indra/llcommon/aifile.cpp b/indra/llcommon/aifile.cpp deleted file mode 100644 index cd2ade77ab..0000000000 --- a/indra/llcommon/aifile.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @file aifile.cpp - * @brief POSIX file operations that throw on error. - * - * Copyright (c) 2013, Aleric Inglewood. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution. - * - * CHANGELOG - * and additional copyright holders. - * - * 03/11/2013 - * Initial version, written by Aleric Inglewood @ SL - */ - -#include "linden_common.h" -#include "aifile.h" -#include "aialert.h" - -#if LL_WINDOWS -#include -#include // Windows errno -#else -#include -#endif - -AIFile::AIFile(std::string const& filename, char const* accessmode) -{ - mFp = AIFile::fopen(filename, accessmode); -} - -AIFile::~AIFile() -{ - AIFile::close(mFp); -} - -// Like THROW_MALERTE but appends "LLFile::strerr(errn) << " (" << errn << ')'" as argument to replace [ERROR]. -#define THROW_ERROR(...) \ - do { \ - int errn = errno; \ - std::ostringstream error; \ - error << LLFile::strerr(errn) << " (" << errn << ')'; \ - THROW_MALERT_CLASS(AIAlert::ErrorCode, errn, __VA_ARGS__ ("[ERROR]", error.str())); \ - } while(0) - -//static -void AIFile::mkdir(std::string const& dirname, int perms) -{ - int rc = LLFile::mkdir_nowarn(dirname, perms); - if (rc < 0 && errno != EEXIST) - { - THROW_ERROR("AIFile_mkdir_Failed_to_create_DIRNAME", AIArgs("[DIRNAME]", dirname)); - } -} - -//static -void AIFile::rmdir(std::string const& dirname) -{ - int rc = LLFile::rmdir_nowarn(dirname); - if (rc < 0 && errno != ENOENT) - { - THROW_ERROR("AIFile_rmdir_Failed_to_remove_DIRNAME", AIArgs("[DIRNAME]", dirname)); - } -} - -//static -LLFILE* AIFile::fopen(std::string const& filename, const char* mode) -{ - LLFILE* fp = LLFile::fopen(filename, mode); - if (!fp) - { - THROW_ERROR("AIFile_fopen_Failed_to_open_FILENAME", AIArgs("[FILENAME]", filename)); - } - return fp; -} - -//static -void AIFile::close(LLFILE* file) -{ - if (LLFile::close(file) < 0) - { - THROW_ERROR("AIFile_close_Failed_to_close_file", AIArgs); - } -} - -//static -void AIFile::remove(std::string const& filename) -{ - int rc = LLFile::remove_nowarn(filename); - if (rc < 0 && errno != ENOENT) - { - THROW_ERROR("AIFile_remove_Failed_to_remove_FILENAME", AIArgs("[FILENAME]", filename)); - } -} - -//static -void AIFile::rename(std::string const& filename, std::string const& newname) -{ - if (LLFile::rename_nowarn(filename, newname) < 0) - { - THROW_ERROR("AIFile_rename_Failed_to_rename_FILE_to_NEWFILE", AIArgs("[FILE]", filename)("[NEWFILE]", newname)); - } -} - diff --git a/indra/llcommon/aifile.h b/indra/llcommon/aifile.h deleted file mode 100644 index 1b110496ae..0000000000 --- a/indra/llcommon/aifile.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file aifile.h - * @brief Declaration of AIFile. - * - * Copyright (c) 2013, Aleric Inglewood. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution. - * - * CHANGELOG - * and additional copyright holders. - * - * 02/11/2013 - * Initial version, written by Aleric Inglewood @ SL - */ - -#ifndef AIFILE_H -#define AIFILE_H - -#include "llfile.h" - -// As LLFile, but throws AIAlert instead of printing a warning. -class LL_COMMON_API AIFile -{ - private: - LLFILE* mFp; - - public: - // Scoped file (exception safe). Throws AIAlertCode with errno on failure. - AIFile(std::string const& filename, char const* accessmode); - ~AIFile(); - - operator LLFILE* () const { return mFp; } - - // All these functions take UTF8 path/filenames. - static LLFILE* fopen(std::string const& filename, char const* accessmode); - static void close(LLFILE* file); - - static void mkdir(std::string const& dirname, int perms = 0700); // Does NOT throw when dirname already exists. - static void rmdir(std::string const& dirname); // Does NOT throw when dirname does not exist. - static void remove(std::string const& filename); // Does NOT throw when filename does not exist. - static void rename(std::string const& filename, std::string const& newname); -}; - -#endif // AIFILE_H diff --git a/indra/llcommon/aisyncclient.cpp b/indra/llcommon/aisyncclient.cpp index c62d88efb6..191a2627d4 100644 --- a/indra/llcommon/aisyncclient.cpp +++ b/indra/llcommon/aisyncclient.cpp @@ -90,7 +90,7 @@ bool operator==(AISyncKey const& key1, AISyncKey const& key2) { // Test if these keys match based on time. - if (std::abs((S32)(key1.mStartFrameCount - key2.mStartFrameCount)) > 1 && + if (std::abs((S64)(key1.mStartFrameCount - key2.mStartFrameCount)) > 1 && std::abs(key1.mFrameTimer.getStartTime() - key2.mFrameTimer.getStartTime()) >= sSyncKeyExpirationTime) { return false; @@ -420,7 +420,7 @@ void AISyncServerMap::remove_server(AISyncServer* server) #include //static -U32 LLFrameTimer::sFrameCount; +U64 LLFrameTimer::sFrameCount; double innerloop_count = 0; diff --git a/indra/llcommon/aisyncclient.h b/indra/llcommon/aisyncclient.h index 0f5237f99e..eecad2924d 100644 --- a/indra/llcommon/aisyncclient.h +++ b/indra/llcommon/aisyncclient.h @@ -56,8 +56,8 @@ struct LLFrameTimer double mStartTime; double mExpiry; static double getCurrentTime(void); - static U32 sFrameCount; - static U32 getFrameCount() { return sFrameCount; } + static U64 sFrameCount; + static U64 getFrameCount() { return sFrameCount; } F64 getStartTime() const { return mStartTime; } void reset(double expiration) { mStartTime = getCurrentTime(); mExpiry = mStartTime + expiration; } bool hasExpired(void) const { return getCurrentTime() > mExpiry; } @@ -114,7 +114,7 @@ class LL_COMMON_API AISyncKey { private: LLFrameTimer mFrameTimer; // This timer is started at the moment the sync key is created. - U32 mStartFrameCount; // The frame count at which the timer was started. + U64 mStartFrameCount; // The frame count at which the timer was started. public: // Constructor. diff --git a/indra/llcommon/aithreadsafe.h b/indra/llcommon/aithreadsafe.h index 93b38246fb..ac1531596e 100644 --- a/indra/llcommon/aithreadsafe.h +++ b/indra/llcommon/aithreadsafe.h @@ -96,16 +96,6 @@ #include "llthread.h" #include "llerror.h" -// g++ 4.2.x (and before?) have the bug that when you try to pass a temporary -// to a function taking a const reference, it still calls the copy constructor. -// Define this to hack around that. -// Note that the chosen solution ONLY works for copying an AI*Access object that -// is passed to a function: the lifetime of the copied object must not be longer -// than the original (or at least, it shouldn't be used anymore after the -// original is destructed). This will be guaranteed if the code also compiles -// on a compiler that doesn't need this hack. -#define AI_NEED_ACCESS_CC (defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ < 3)) || (__GNUC__ < 4))) - template struct AIReadAccessConst; template struct AIReadAccess; template struct AIWriteAccess; @@ -339,9 +329,6 @@ struct AIReadAccessConst AIReadAccessConst(AIThreadSafe const& wrapper, bool high_priority = false) : mWrapper(const_cast&>(wrapper)), mState(readlocked) -#if AI_NEED_ACCESS_CC - , mIsCopyConstructed(false) -#endif { mWrapper.mRWLock.rdlock(high_priority); } @@ -350,9 +337,6 @@ struct AIReadAccessConst // These should never be dynamically allocated, so there is no need to make this virtual. ~AIReadAccessConst() { -#if AI_NEED_ACCESS_CC - if (mIsCopyConstructed) return; -#endif if (mState == readlocked) mWrapper.mRWLock.rdunlock(); else if (mState == writelocked) @@ -371,23 +355,14 @@ struct AIReadAccessConst //! Constructor used by AIReadAccess. AIReadAccessConst(AIThreadSafe& wrapper, state_type state) : mWrapper(wrapper), mState(state) -#if AI_NEED_ACCESS_CC - , mIsCopyConstructed(false) -#endif { } AIThreadSafe& mWrapper; //!< Reference to the object that we provide access to. state_type const mState; //!< The lock state that mWrapper is in. -#if AI_NEED_ACCESS_CC - bool mIsCopyConstructed; -public: - AIReadAccessConst(AIReadAccessConst const& orig) : mWrapper(orig.mWrapper), mState(orig.mState), mIsCopyConstructed(true) { } -#else private: // Disallow copy constructing directly. AIReadAccessConst(AIReadAccessConst const&); -#endif }; /** @@ -596,9 +571,6 @@ struct AIAccessConst { //! Construct a AIAccessConst from a constant AIThreadSafeSimple. AIAccessConst(AIThreadSafeSimple const& wrapper) : mWrapper(const_cast&>(wrapper)) -#if AI_NEED_ACCESS_CC - , mIsCopyConstructed(false) -#endif { this->mWrapper.mMutex.lock(); } @@ -611,9 +583,6 @@ struct AIAccessConst ~AIAccessConst() { -#if AI_NEED_ACCESS_CC - if (mIsCopyConstructed) return; -#endif this->mWrapper.mMutex.unlock(); } @@ -625,15 +594,9 @@ struct AIAccessConst protected: AIThreadSafeSimple& mWrapper; //!< Reference to the object that we provide access to. -#if AI_NEED_ACCESS_CC - bool mIsCopyConstructed; -public: - AIAccessConst(AIAccessConst const& orig) : mWrapper(orig.mWrapper), mIsCopyConstructed(true) { } -#else private: // Disallow copy constructing directly. AIAccessConst(AIAccessConst const&); -#endif }; /** @@ -817,14 +780,9 @@ struct AISTAccessConst protected: AIThreadSafeSingleThread& mWrapper; //!< Reference to the object that we provide access to. -#if AI_NEED_ACCESS_CC -public: - AISTAccessConst(AISTAccessConst const& orig) : mWrapper(orig.mWrapper) { } -#else private: // Disallow copy constructing directly. AISTAccessConst(AISTAccessConst const&); -#endif }; /** diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp index 64cbb1131c..daef52756b 100644 --- a/indra/llcommon/indra_constants.cpp +++ b/indra/llcommon/indra_constants.cpp @@ -45,3 +45,15 @@ const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1"); const LLUUID REALESTATE_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1"); // Maintenance's group id. const LLUUID MAINTENANCE_GROUP_ID("dc7b21cd-3c89-fcaa-31c8-25f9ffd224cd"); + +const LLUUID IMG_USE_BAKED_HEAD ("5a9f4a74-30f2-821c-b88d-70499d3e7183"); +const LLUUID IMG_USE_BAKED_UPPER ("ae2de45c-d252-50b8-5c6e-19f39ce79317"); +const LLUUID IMG_USE_BAKED_LOWER ("24daea5f-0539-cfcf-047f-fbc40b2786ba"); +const LLUUID IMG_USE_BAKED_EYES ("52cc6bb6-2ee5-e632-d3ad-50197b1dcb8a"); +const LLUUID IMG_USE_BAKED_SKIRT ("43529ce8-7faa-ad92-165a-bc4078371687"); +const LLUUID IMG_USE_BAKED_HAIR ("09aac1fb-6bce-0bee-7d44-caac6dbb6c63"); +const LLUUID IMG_USE_BAKED_LEFTARM ("ff62763f-d60a-9855-890b-0c96f8f8cd98"); +const LLUUID IMG_USE_BAKED_LEFTLEG ("8e915e25-31d1-cc95-ae08-d58a47488251"); +const LLUUID IMG_USE_BAKED_AUX1 ("9742065b-19b5-297c-858a-29711d539043"); +const LLUUID IMG_USE_BAKED_AUX2 ("03642e83-2bd1-4eb9-34b4-4c47ed586d2d"); +const LLUUID IMG_USE_BAKED_AUX3 ("edd51b77-fc10-ce7a-4b3d-011dfc349e4f"); diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 7e7bdaa85c..786e1bbd26 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -1,3 +1,4 @@ + /** * @file indra_constants.h * @brief some useful short term constants for Indra @@ -32,15 +33,6 @@ class LLUUID; -// At 45 Hz collisions seem stable and objects seem -// to settle down at a reasonable rate. -// JC 3/18/2003 - -// const F32 PHYSICS_TIMESTEP = 1.f / 45.f; -// This must be a #define due to anal retentive restrictions on const expressions -// CG 2008-06-05 -#define PHYSICS_TIMESTEP (1.f / 45.f) - const F32 COLLISION_TOLERANCE = 0.1f; const F32 HALF_COLLISION_TOLERANCE = 0.05f; @@ -140,18 +132,18 @@ const U32 DEFAULT_CGI_SERVICES_PORT = 12045; // on a single host for map tile generation. JC const U32 DEFAULT_MAPSERVER_PORT = 12124; -const char LAND_LAYER_CODE = 'L'; -const char WATER_LAYER_CODE = 'W'; -const char WIND_LAYER_CODE = '7'; -const char CLOUD_LAYER_CODE = '8'; - -// Aurora Sim -// Extended land layer for Aurora Sim -const char AURORA_LAND_LAYER_CODE = 'M'; -const char AURORA_WATER_LAYER_CODE = 'X'; -const char AURORA_WIND_LAYER_CODE = '9'; -const char AURORA_CLOUD_LAYER_CODE = ':'; -// Aurora Sim +enum ETerrainBrushType +{ + // the valid brush numbers cannot be reordered, because they + // are used in the binary LSL format as arguments to llModifyLand() + E_LANDBRUSH_LEVEL = 0, + E_LANDBRUSH_RAISE = 1, + E_LANDBRUSH_LOWER = 2, + E_LANDBRUSH_SMOOTH = 3, + E_LANDBRUSH_NOISE = 4, + E_LANDBRUSH_REVERT = 5, + E_LANDBRUSH_INVALID = 6 +}; // keys // Bit masks for various keyboard modifier keys. @@ -252,7 +244,6 @@ const U8 SIM_ACCESS_DOWN = 254; const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT; // attachment constants -const S32 MAX_AGENT_ATTACHMENTS = 38; const U8 ATTACHMENT_ADD = 0x80; // god levels @@ -303,13 +294,18 @@ const U32 START_LOCATION_ID_COUNT = 6; // group constants const U32 GROUP_MIN_SIZE = 2; -// gMaxAgentGroups is now sent by login.cgi, which -// looks it up from globals.xml. -// -// For now we need an old default value however, -// so the viewer can be deployed ahead of login.cgi. -// -const S32 DEFAULT_MAX_AGENT_GROUPS = 25; + +LL_COMMON_API extern const LLUUID IMG_USE_BAKED_HEAD; +LL_COMMON_API extern const LLUUID IMG_USE_BAKED_UPPER; +LL_COMMON_API extern const LLUUID IMG_USE_BAKED_LOWER; +LL_COMMON_API extern const LLUUID IMG_USE_BAKED_EYES; +LL_COMMON_API extern const LLUUID IMG_USE_BAKED_SKIRT; +LL_COMMON_API extern const LLUUID IMG_USE_BAKED_HAIR; +LL_COMMON_API extern const LLUUID IMG_USE_BAKED_LEFTARM; +LL_COMMON_API extern const LLUUID IMG_USE_BAKED_LEFTLEG; +LL_COMMON_API extern const LLUUID IMG_USE_BAKED_AUX1; +LL_COMMON_API extern const LLUUID IMG_USE_BAKED_AUX2; +LL_COMMON_API extern const LLUUID IMG_USE_BAKED_AUX3; // radius within which a chat message is fully audible const F32 CHAT_WHISPER_RADIUS = 10.f; @@ -341,18 +337,7 @@ const S32 SANDBOX_CLEAN_FREQ = 12; const F32 WIND_SCALE_HACK = 2.0f; // hack to make wind speeds more realistic -enum ETerrainBrushType -{ - // the valid brush numbers cannot be reordered, because they - // are used in the binary LSL format as arguments to llModifyLand() - E_LANDBRUSH_LEVEL = 0, - E_LANDBRUSH_RAISE = 1, - E_LANDBRUSH_LOWER = 2, - E_LANDBRUSH_SMOOTH = 3, - E_LANDBRUSH_NOISE = 4, - E_LANDBRUSH_REVERT = 5, - E_LANDBRUSH_INVALID = 6 -}; + // media commands const U32 PARCEL_MEDIA_COMMAND_STOP = 0; @@ -382,13 +367,6 @@ const U32 MAP_ITEM_CLASSIFIED = 0x08; const U32 MAP_ITEM_ADULT_EVENT = 0x09; const U32 MAP_ITEM_LAND_FOR_SALE_ADULT = 0x0a; -// Crash reporter behavior -const char* const CRASH_SETTINGS_FILE = "settings_crash_behavior.xml"; -const char* const CRASH_BEHAVIOR_SETTING = "CrashSubmitBehavior"; -const S32 CRASH_BEHAVIOR_ASK = 0; -const S32 CRASH_BEHAVIOR_ALWAYS_SEND = 1; -const S32 CRASH_BEHAVIOR_NEVER_SEND = 2; - // Export/Import return values const S32 EXPORT_SUCCESS = 0; const S32 EXPORT_ERROR_PERMISSIONS = -1; diff --git a/indra/llcommon/is_approx_equal_fraction.h b/indra/llcommon/is_approx_equal_fraction.h index d369fbc5b3..3c7f4e9282 100644 --- a/indra/llcommon/is_approx_equal_fraction.h +++ b/indra/llcommon/is_approx_equal_fraction.h @@ -49,9 +49,8 @@ * signatures. */ template -inline BOOL is_approx_equal_fraction_impl(FTYPE x, FTYPE y, U32 frac_bits) +inline bool is_approx_equal_fraction_impl(FTYPE x, FTYPE y, U32 frac_bits) { - BOOL ret = TRUE; FTYPE diff = (FTYPE) fabs(x - y); S32 diffInt = (S32) diff; @@ -64,20 +63,20 @@ inline BOOL is_approx_equal_fraction_impl(FTYPE x, FTYPE y, U32 frac_bits) // based on the number of bits used for packing decimal portion. if (diffInt != 0 || diffFracTolerance > 1) { - ret = FALSE; + return false; } - return ret; + return true; } /// F32 flavor -inline BOOL is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits) +inline bool is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits) { return is_approx_equal_fraction_impl(x, y, frac_bits); } /// F64 flavor -inline BOOL is_approx_equal_fraction(F64 x, F64 y, U32 frac_bits) +inline bool is_approx_equal_fraction(F64 x, F64 y, U32 frac_bits) { return is_approx_equal_fraction_impl(x, y, frac_bits); } diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h index b5e9de73d5..d44c318477 100644 --- a/indra/llcommon/linden_common.h +++ b/indra/llcommon/linden_common.h @@ -43,11 +43,9 @@ #endif #if defined(LL_WINDOWS) && defined(_DEBUG) -# if _MSC_VER >= 1400 // Visual C++ 2005 or later # define _CRTDBG_MAP_ALLOC # include # include -# endif #endif #include "llpreprocessor.h" @@ -68,5 +66,6 @@ #include "lldefs.h" #include "llerror.h" #include "llfile.h" +#include "llformat.h" #endif diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h index 14e25e78d6..d6ab5ed3dc 100644 --- a/indra/llcommon/llalignedarray.h +++ b/indra/llcommon/llalignedarray.h @@ -64,7 +64,7 @@ LLAlignedArray::LLAlignedArray() template LLAlignedArray::~LLAlignedArray() { - ll_aligned_free(mArray); + ll_aligned_free(mArray); mArray = NULL; mElementCount = 0; mCapacity = 0; @@ -78,7 +78,7 @@ void LLAlignedArray::push_back(const T& elem) { mCapacity++; mCapacity *= 2; - T* new_buf = (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment); + T* new_buf = (T*) ll_aligned_malloc(mCapacity*sizeof(T)); if (mArray) { ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount); @@ -90,7 +90,7 @@ void LLAlignedArray::push_back(const T& elem) mArray[mElementCount++] = elem; //delete old array here to prevent error on a.push_back(a[0]) - ll_aligned_free(old_buf); + ll_aligned_free(old_buf); } template @@ -99,11 +99,11 @@ void LLAlignedArray::resize(U32 size) if (mCapacity < size) { mCapacity = size+mCapacity*2; - T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment) : NULL; + T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc(mCapacity*sizeof(T)) : NULL; if (mArray) { ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount); - ll_aligned_free(mArray); + ll_aligned_free(mArray); } /*for (U32 i = mElementCount; i < mCapacity; ++i) diff --git a/indra/llcommon/llallocator_heap_profile.cpp b/indra/llcommon/llallocator_heap_profile.cpp index b2eafde1aa..499d78ed64 100644 --- a/indra/llcommon/llallocator_heap_profile.cpp +++ b/indra/llcommon/llallocator_heap_profile.cpp @@ -40,7 +40,7 @@ #include #include -static const std::string HEAP_PROFILE_MAGIC_STR = "heap profile:"; +static const std::string HEAP_PROFILE_MAGIC_STR("heap profile:"); static bool is_separator(char c) { @@ -70,7 +70,7 @@ void LLAllocatorHeapProfile::parse(std::string const & prof_text) range_t prof_range(prof_begin, prof_text.end()); boost::algorithm::split(prof_lines, prof_range, - boost::bind(std::equal_to(), '\n', _1)); + std::bind(std::equal_to(), '\n', std::placeholders::_1)); std::vector< range_t >::const_iterator i; for(i = prof_lines.begin(); i != prof_lines.end() && !i->empty(); ++i) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index bc3e7196d5..36c6b0f611 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -25,9 +25,8 @@ */ #include "linden_common.h" -#include "llapp.h" -#include +#include "llapp.h" #ifdef LL_DARWIN #include @@ -45,7 +44,6 @@ #include "llstl.h" // for DeletePointer() #include "llstring.h" #include "lleventtimer.h" -#include "exception_handler.h" // // Signal handling @@ -53,16 +51,10 @@ // Windows uses structured exceptions, so it's handled a bit differently. // #if LL_WINDOWS -#include "windows.h" +#include LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop); BOOL ConsoleCtrlHandler(DWORD fdwCtrlType); -bool windows_post_minidump_callback(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded); #else # include # include // for fork() @@ -70,18 +62,6 @@ bool windows_post_minidump_callback(const wchar_t* dump_path, void setup_signals(); void default_unix_signal_handler(int signum, siginfo_t *info, void *); -#if LL_LINUX -#include "client/linux/handler/minidump_descriptor.h" -static bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, - void* context, - bool succeeded); -#else -// Called by breakpad exception handler after the minidump has been generated. -bool unix_post_minidump_callback(const char *dump_dir, - const char *minidump_id, - void *context, bool succeeded); -#endif - # if LL_DARWIN /* OSX doesn't support SIGRT* */ S32 LL_SMACKDOWN_SIGNAL = SIGUSR1; @@ -98,7 +78,7 @@ S32 LL_HEARTBEAT_SIGNAL = (SIGRTMAX >= 0) ? (SIGRTMAX-0) : SIGUSR2; #endif // LL_WINDOWS // the static application instance -LLApp* LLApp::sApplication = NULL; +LLApp* LLApp::sApplication = nullptr; // Allows the generation of core files for post mortem under gdb // and disables crashlogger @@ -110,7 +90,7 @@ BOOL LLApp::sLogInSignal = FALSE; // static LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status -LLAppErrorHandler LLApp::sErrorHandler = NULL; +LLAppErrorHandler LLApp::sErrorHandler = nullptr; BOOL LLApp::sErrorThreadRunning = FALSE; #if !LL_WINDOWS LLApp::child_map LLApp::sChildMap; @@ -119,13 +99,12 @@ LLAppChildCallback LLApp::sDefaultChildCallback = NULL; #endif -LLApp::LLApp() : mThreadErrorp(NULL) +LLApp::LLApp() + : mThreadErrorp(nullptr) { commonCtor(); } -static void* sCrashLoggerReserve = NULL; - void LLApp::commonCtor() { // Set our status to running @@ -150,34 +129,11 @@ void LLApp::commonCtor() // Set the application to this instance. sApplication = this; - mExceptionHandler = 0; - -#if LL_WINDOWS - sCrashLoggerReserve = VirtualAlloc(NULL, 512*1024, MEM_COMMIT|MEM_RESERVE, PAGE_NOACCESS); -#else - sCrashLoggerReserve = malloc(512*1024); -#endif - // initialize the buffer to write the minidump filename to // (this is used to avoid allocating memory in the crash handler) - memset(mMinidumpPath, 0, MAX_MINDUMP_PATH_LENGTH); mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe"; } -#if LL_WINDOWS -static bool clear_CrashLoggerReserve_callback(void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) -{ - VirtualFree(sCrashLoggerReserve, 0, MEM_RELEASE); - return true; -} -#else -static bool clear_CrashLoggerReserve_callback(void* context) -{ - free(sCrashLoggerReserve); - return true; -} -#endif - LLApp::LLApp(LLErrorThread *error_thread) : mThreadErrorp(error_thread) { @@ -198,11 +154,9 @@ LLApp::~LLApp() if (mThreadErrorp) { delete mThreadErrorp; - mThreadErrorp = NULL; + mThreadErrorp = nullptr; } - if(mExceptionHandler != 0) delete mExceptionHandler; - LLCommon::cleanupClass(); } @@ -216,8 +170,8 @@ LLApp* LLApp::instance() LLSD LLApp::getOption(const std::string& name) const { LLSD rv; - LLSD::array_const_iterator iter = mOptions.beginArray(); - LLSD::array_const_iterator end = mOptions.endArray(); + auto iter = mOptions.beginArray(); + auto end = mOptions.endArray(); for(; iter != end; ++iter) { rv = (*iter)[name]; @@ -264,9 +218,9 @@ bool LLApp::parseCommandOptions(int argc, char** argv) #if LL_WINDOWS //Windows changed command line parsing. Deal with it. - S32 slen = value.length() - 1; - S32 start = 0; - S32 end = slen; + size_t slen = value.length() - 1; + size_t start = 0; + size_t end = slen; if (argv[ii][start]=='"')start++; if (argv[ii][end]=='"')end--; if (start!=0 || end!=slen) @@ -311,99 +265,49 @@ LLSD LLApp::getOptionData(OptionPriority level) return mOptions[level]; } -void LLApp::setupErrorHandling() -{ - // Error handling is done by starting up an error handling thread, which just sleeps and - // occasionally checks to see if the app is in an error state, and sees if it needs to be run. - #if LL_WINDOWS - // Windows doesn't have the same signal handling mechanisms as UNIX, thus APR doesn't provide - // a signal handling thread implementation. - // What we do is install an unhandled exception handler, which will try to do the right thing - // in the case of an error (generate a minidump) - -#if LL_SEND_CRASH_REPORTS - // This sets a callback to handle w32 signals to the console window. - // The viewer shouldn't be affected, sicne its a windowed app. - SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE); - - // Install the Google Breakpad crash handler for Windows - if(mExceptionHandler == 0) - { - mExceptionHandler = new google_breakpad::ExceptionHandler( - std::wstring(mDumpPath.begin(),mDumpPath.end()), //Dump path - clear_CrashLoggerReserve_callback, - windows_post_minidump_callback, - 0, - google_breakpad::ExceptionHandler::HANDLER_ALL); - if (mExceptionHandler) +//The following code is needed for 32-bit apps on 64-bit windows to keep it from eating +//crashes. It is a lovely undocumented 'feature' in SP1 of Windows 7. An excellent +//in-depth article on the issue may be found here: http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesn-work/ +void EnableCrashingOnCrashes() +{ + typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags); + typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags); + const DWORD EXCEPTION_SWALLOWING = 0x1; + + HMODULE kernel32 = LoadLibraryA("kernel32.dll"); + tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, + "GetProcessUserModeExceptionPolicy"); + tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, + "SetProcessUserModeExceptionPolicy"); + if (pGetPolicy && pSetPolicy) + { + DWORD dwFlags; + if (pGetPolicy(&dwFlags)) { - mExceptionHandler->set_handle_debug_exceptions(true); + // Turn off the filter + pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING); } } +} #endif -#else + +void LLApp::setupErrorHandling() +{ + // Error handling is done by starting up an error handling thread, which just sleeps and + // occasionally checks to see if the app is in an error state, and sees if it needs to be run. + +#if !LL_WINDOWS // // Start up signal handling. // // There are two different classes of signals. Synchronous signals are delivered to a specific // thread, asynchronous signals can be delivered to any thread (in theory) // - setup_signals(); - - // Add google breakpad exception handler configured for Darwin/Linux. - bool installHandler = true; -#if LL_DARWIN - // For the special case of Darwin, we do not want to install the handler if - // the process is being debugged as the app will exit with value ABRT (6) if - // we do. Unfortunately, the code below which performs that test relies on - // the structure kinfo_proc which has been tagged by apple as an unstable - // API. We disable this test for shipping versions to avoid conflicts with - // future releases of Darwin. This test is really only needed for developers - // starting the app from a debugger anyway. - #ifndef LL_RELEASE_FOR_DOWNLOAD - int mib[4]; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - struct kinfo_proc info; - memset(&info, 0, sizeof(info)); - - size_t size = sizeof(info); - int result = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); - if((result == 0) || (errno == ENOMEM)) - { - // P_TRACED flag is set, so this process is being debugged; do not install - // the handler - if(info.kp_proc.p_flag & P_TRACED) installHandler = false; - } - else - { - // Failed to discover if the process is being debugged; default to - // installing the handler. - installHandler = true; - } - - if(installHandler && (mExceptionHandler == 0)) - { - mExceptionHandler = new google_breakpad::ExceptionHandler(mDumpPath, clear_CrashLoggerReserve_callback, &unix_post_minidump_callback, 0, true, 0); - } - #endif -#elif LL_LINUX - if(installHandler && (mExceptionHandler == 0)) - { - if (mDumpPath.empty()) - { - mDumpPath = "/tmp"; - } - google_breakpad::MinidumpDescriptor desc(mDumpPath); - mExceptionHandler = new google_breakpad::ExceptionHandler(desc, clear_CrashLoggerReserve_callback, unix_minidump_callback, NULL, true, -1); - } -#endif - +#endif // ! LL_WINDOWS +#if !defined(USE_CRASHPAD) + startErrorThread(); #endif } @@ -441,7 +345,6 @@ void LLApp::setErrorHandler(LLAppErrorHandler handler) LLApp::sErrorHandler = handler; } - // static void LLApp::runErrorHandler() { @@ -454,7 +357,6 @@ void LLApp::runErrorHandler() LLApp::setStopped(); } - // static void LLApp::setStatus(EAppStatus status) { @@ -469,43 +371,12 @@ void LLApp::setError() setStatus(APP_STATUS_ERROR); } -void LLApp::setMiniDumpDir(const std::string &path) -{ - if (path.empty()) - { - mDumpPath = "/tmp"; - } - else - { - mDumpPath = path; - } - - if(mExceptionHandler == 0) return; -#ifdef LL_WINDOWS - wchar_t buffer[MAX_MINDUMP_PATH_LENGTH]; - mbstowcs(buffer, mDumpPath.c_str(), MAX_MINDUMP_PATH_LENGTH); - mExceptionHandler->set_dump_path(std::wstring(buffer)); -#elif LL_LINUX - //google_breakpad::MinidumpDescriptor desc("/tmp"); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched. - google_breakpad::MinidumpDescriptor desc(mDumpPath); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched. - mExceptionHandler->set_minidump_descriptor(desc); -#else - mExceptionHandler->set_dump_path(mDumpPath); -#endif -} - void LLApp::setDebugFileNames(const std::string &path) { mStaticDebugFileName = path + "static_debug_info.log"; mDynamicDebugFileName = path + "dynamic_debug_info.log"; } -void LLApp::writeMiniDump() -{ - if(mExceptionHandler == 0) return; - mExceptionHandler->WriteMinidump(); -} - // static void LLApp::setQuitting() { @@ -560,13 +431,6 @@ bool LLApp::isExiting() void LLApp::disableCrashlogger() { - // Disable Breakpad exception handler. - if (mExceptionHandler != 0) - { - delete mExceptionHandler; - mExceptionHandler = 0; - } - sDisableCrashlogger = TRUE; } @@ -635,12 +499,6 @@ LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *except ms_sleep(10); } - // - // Generate a minidump if we can. - // - // TODO: This needs to be ported over form the viewer-specific - // LLWinDebug class - // // At this point, we always want to exit the app. There's no graceful // recovery for an unhandled exception. @@ -940,150 +798,4 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) } } } - -#if LL_LINUX -bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, void* context, bool succeeded) -{ - // Copy minidump file path into fixed buffer in the app instance to avoid - // heap allocations in a crash handler. - - // path format: /.dmp - - //HACK: *path points to the buffer in getMiniDumpFilename which has already allocated space - //to avoid doing allocation during crash. - char * path = LLApp::instance()->getMiniDumpFilename(); - int dir_path_len = strlen(path); - - // The path must not be truncated. - S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH - dir_path_len; - - llassert( (remaining - strlen(minidump_desc.path())) > 5); - - path += dir_path_len; - - if (dir_path_len > 0 && path[-1] != '/') - { - *path++ = '/'; - --remaining; - } - - strncpy(path, minidump_desc.path(), remaining); - - LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL; - LLApp::runErrorHandler(); - -#ifndef LL_RELEASE_FOR_DOWNLOAD - clear_signals(); - return false; -#else - return true; -#endif - -} -#endif - - -bool unix_post_minidump_callback(const char *dump_dir, - const char *minidump_id, - void *context, bool succeeded) -{ - // Copy minidump file path into fixed buffer in the app instance to avoid - // heap allocations in a crash handler. - - // path format: /.dmp - int dirPathLength = strlen(dump_dir); - int idLength = strlen(minidump_id); - - // The path must not be truncated. - llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH); - - char * path = LLApp::instance()->getMiniDumpFilename(); - S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; - strncpy(path, dump_dir, remaining); - remaining -= dirPathLength; - path += dirPathLength; - if (remaining > 0 && dirPathLength > 0 && path[-1] != '/') - { - *path++ = '/'; - --remaining; - } - if (remaining > 0) - { - strncpy(path, minidump_id, remaining); - remaining -= idLength; - path += idLength; - strncpy(path, ".dmp", remaining); - } - - LL_INFOS() << "generated minidump: " << path << LL_ENDL; - LLApp::runErrorHandler(); - -#ifndef LL_RELEASE_FOR_DOWNLOAD - clear_signals(); - return false; -#else - return true; -#endif -} #endif // !WINDOWS - -#ifdef LL_WINDOWS -bool windows_post_minidump_callback(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded) -{ - char * path = LLApp::instance()->getMiniDumpFilename(); - S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; - size_t bytesUsed; - - bytesUsed = wcstombs(path, dump_path, static_cast(remaining)); - remaining -= bytesUsed; - path += bytesUsed; - if(remaining > 0 && bytesUsed > 0 && path[-1] != '\\') - { - *path++ = '\\'; - --remaining; - } - if(remaining > 0) - { - bytesUsed = wcstombs(path, minidump_id, static_cast(remaining)); - remaining -= bytesUsed; - path += bytesUsed; - } - if(remaining > 0) - { - strncpy(path, ".dmp", remaining); - } - - LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL; - // *NOTE:Mani - this code is stolen from LLApp, where its never actually used. - //OSMessageBox("Attach Debugger Now", "Error", OSMB_OK); - // *TODO: Translate the signals/exceptions into cross-platform stuff - // Windows implementation - LL_INFOS() << "Entering Windows Exception Handler..." << LL_ENDL; - - if (LLApp::isError()) - { - LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL; - } - - // Flag status to error, so thread_error starts its work - LLApp::setError(); - - // Block in the exception handler until the app has stopped - // This is pretty sketchy, but appears to work just fine - while (!LLApp::isStopped()) - { - ms_sleep(10); - } - -#ifndef LL_RELEASE_FOR_DOWNLOAD - return false; -#else - return true; -#endif -} -#endif diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index aab871799c..2a8fddfa23 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -60,10 +60,6 @@ class LLChildInfo }; #endif -namespace google_breakpad { - class ExceptionHandler; // See exception_handler.h -} - class LL_COMMON_API LLApp : public LLOptionInterface { friend class LLErrorThread; @@ -233,22 +229,11 @@ class LL_COMMON_API LLApp : public LLOptionInterface static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. //@} - // the maximum length of the minidump filename returned by getMiniDumpFilename() - static const U32 MAX_MINDUMP_PATH_LENGTH = 256; - - // change the directory where Breakpad minidump files are written to - void setMiniDumpDir(const std::string &path); void setDebugFileNames(const std::string &path); - // Return the Google Breakpad minidump filename after a crash. - char *getMiniDumpFilename() { return mMinidumpPath; } std::string* getStaticDebugFile() { return &mStaticDebugFileName; } std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; } - // Write out a Google Breakpad minidump file. - void writeMiniDump(); - - #if !LL_WINDOWS // // Child process handling (Unix only for now) @@ -281,8 +266,6 @@ class LL_COMMON_API LLApp : public LLOptionInterface static BOOL sDisableCrashlogger; // Let the OS handle crashes for us. std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting. - std::string mDumpPath; //output path for google breakpad. Dependency workaround. - #if !LL_WINDOWS static LLAtomicU32* sSigChildCount; // Number of SIGCHLDs received. typedef std::map child_map; // Map key is a PID @@ -290,16 +273,13 @@ class LL_COMMON_API LLApp : public LLOptionInterface static LLAppChildCallback sDefaultChildCallback; #endif - void startErrorThread(); - /** * @brief This method is called at the end, just prior to deinitializing curl. */ void stopErrorThread(); private: - // Contains the filename of the minidump file after a crash. - char mMinidumpPath[MAX_MINDUMP_PATH_LENGTH]; + void startErrorThread(); std::string mStaticDebugFileName; std::string mDynamicDebugFileName; @@ -323,11 +303,8 @@ class LL_COMMON_API LLApp : public LLOptionInterface std::vector mLiveFiles; //@} -private: // the static application instance if it was created. static LLApp* sApplication; - google_breakpad::ExceptionHandler * mExceptionHandler; - #if !LL_WINDOWS friend void default_unix_signal_handler(int signum, siginfo_t *info, void *); diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index de7f3e9dca..a1a445261a 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -29,6 +29,7 @@ #include "linden_common.h" #include "llapr.h" #include "llscopedvolatileaprpool.h" +#include bool ll_apr_warn_status(apr_status_t status) { @@ -150,7 +151,7 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOO return open(filename, flags, use_global_pool ? LLAPRFile::long_lived : LLAPRFile::short_lived); } // File I/O -S32 LLAPRFile::read(void *buf, S32 nbytes) +S32 LLAPRFile::read(void *buf, U64 nbytes) { if(!mFile) { @@ -167,12 +168,12 @@ S32 LLAPRFile::read(void *buf, S32 nbytes) } else { - llassert_always(sz <= 0x7fffffff); + llassert_always(sz <= std::numeric_limits::max()); return (S32)sz; } } -S32 LLAPRFile::write(const void *buf, S32 nbytes) +S32 LLAPRFile::write(const void *buf, U64 nbytes) { if(!mFile) { @@ -189,7 +190,7 @@ S32 LLAPRFile::write(const void *buf, S32 nbytes) } else { - llassert_always(sz <= 0x7fffffff); + llassert_always(sz <= std::numeric_limits::max()); return (S32)sz; } } diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 9baddef5ff..03a010d6c4 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -33,6 +33,8 @@ #include // Need PATH_MAX in APR headers... #endif +#include "llwin32headerslean.h" + #include #include "apr_thread_proc.h" @@ -92,8 +94,8 @@ class LL_COMMON_API LLAPRFile : boost::noncopyable apr_status_t eof() { return apr_file_eof(mFile);} // Returns bytes read/written, 0 if read/write fails: - S32 read(void* buf, S32 nbytes); - S32 write(const void* buf, S32 nbytes); + S32 read(void* buf, U64 nbytes); + S32 write(const void* buf, U64 nbytes); apr_file_t* getFileHandle() {return mFile;} diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 5b22d5babb..66602f4e74 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -101,6 +101,9 @@ LLAssetDictionary::LLAssetDictionary() addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", false, false, false)); addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", false, false, false)); addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, true, true)); + addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true)); + + addEntry(LLAssetType::AT_UNKNOWN, new AssetEntry("UNKNOWN", "invalid", NULL, false, false, false)); addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, false, false, false)); }; diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index e6fee54ca8..9435eeb2b0 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -122,6 +122,9 @@ class LL_COMMON_API LLAssetType AT_LINK_FOLDER = 25, // Inventory folder link + + AT_MARKETPLACE_FOLDER = 26, + // Marketplace folder. Same as an AT_CATEGORY but different display methods. AT_CURRENT_OUTFIT = 46, @@ -132,7 +135,16 @@ class LL_COMMON_API LLAssetType AT_MESH = 49, // Mesh data in our proprietary SLM format - AT_COUNT = 50, + AT_RESERVED_1 = 50, + AT_RESERVED_2 = 51, + AT_RESERVED_3 = 52, + AT_RESERVED_4 = 53, + AT_RESERVED_5 = 54, + AT_RESERVED_6 = 55, + + AT_SETTINGS = 56, // Collection of settings + + AT_COUNT = 57, // +*********************************************************+ // | TO ADD AN ELEMENT TO THIS ENUM: | @@ -143,7 +155,7 @@ class LL_COMMON_API LLAssetType // | 4. ADD TO LLViewerAssetType.cpp | // | 5. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp | // +*********************************************************+ - + AT_UNKNOWN = 255, AT_NONE = -1 }; diff --git a/indra/llcommon/llatomic.h b/indra/llcommon/llatomic.h index 3ffd7e125a..e9a88a7b61 100644 --- a/indra/llcommon/llatomic.h +++ b/indra/llcommon/llatomic.h @@ -50,7 +50,7 @@ #include "boost/atomic.hpp" template struct impl_atomic_type { typedef boost::atomic type; }; -#elif defined(USE_STD_ATOMIC) && defined(LL_CPP11) +#elif defined(USE_STD_ATOMIC) #include template struct impl_atomic_type { typedef std::atomic type; }; diff --git a/indra/llcommon/llavatarconstants.h b/indra/llcommon/llavatarconstants.h index 867d6bdbf3..6e7a492457 100644 --- a/indra/llcommon/llavatarconstants.h +++ b/indra/llcommon/llavatarconstants.h @@ -44,14 +44,6 @@ const char* const BLACKLIST_PROFILE_WEB_URL = "http://secondlife.com/app/webdisa // Maximum number of avatar picks const S32 MAX_AVATAR_PICKS = 10; -// For Flags in AvatarPropertiesReply -const U32 AVATAR_ALLOW_PUBLISH = 0x1 << 0; // whether profile is externally visible or not -const U32 AVATAR_MATURE_PUBLISH = 0x1 << 1; // profile is "mature" -const U32 AVATAR_IDENTIFIED = 0x1 << 2; // whether avatar has provided payment info -const U32 AVATAR_TRANSACTED = 0x1 << 3; // whether avatar has actively used payment info -const U32 AVATAR_ONLINE = 0x1 << 4; // the online status of this avatar, if known. -const U32 AVATAR_AGEVERIFIED = 0x1 << 5; // whether avatar has been age-verified - char const* const VISIBILITY_DEFAULT = "default"; char const* const VISIBILITY_HIDDEN = "hidden"; char const* const VISIBILITY_VISIBLE = "visible"; diff --git a/indra/llcommon/llbase64.cpp b/indra/llcommon/llbase64.cpp index 4e75e45914..bab8b1a310 100644 --- a/indra/llcommon/llbase64.cpp +++ b/indra/llcommon/llbase64.cpp @@ -28,31 +28,28 @@ #include "linden_common.h" #include "llbase64.h" - -#include -#include "apr_base64.h" +#include // static std::string LLBase64::encode(const U8* input, size_t input_size) { if (!(input && input_size > 0)) return LLStringUtil::null; - - // Yes, it returns int. - int b64_buffer_length = apr_base64_encode_len(input_size); - char* b64_buffer = new char[b64_buffer_length]; - // This is faster than apr_base64_encode() if you know - // you're not on an EBCDIC machine. Also, the output is - // null terminated, even though the documentation doesn't - // specify. See apr_base64.c for details. JC - b64_buffer_length = apr_base64_encode_binary( - b64_buffer, - input, - input_size); - std::string result; - result.assign(b64_buffer); - delete[] b64_buffer; - + BIO *b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + BIO *bio = BIO_new(BIO_s_mem()); + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); + bio = BIO_push(b64, bio); + BIO_write(bio, input, input_size); + + (void)BIO_flush(bio); + + char *new_data; + size_t bytes_written = BIO_get_mem_data(bio, &new_data); + std::string result(new_data, bytes_written); + BIO_free_all(bio); + return result; } @@ -70,9 +67,16 @@ std::string LLBase64::encode(const std::string& in_str) size_t LLBase64::decode(const std::string& input, U8 * buffer, size_t buffer_size) { if (input.empty()) return 0; - - size_t bytes_written = apr_base64_decode_binary(buffer, input.data()); - + + BIO *b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + // BIO_new_mem_buf is not const aware, but it doesn't modify the buffer + BIO *bio = BIO_new_mem_buf(const_cast(input.c_str()), input.length()); + bio = BIO_push(b64, bio); + size_t bytes_written = BIO_read(bio, buffer, buffer_size); + BIO_free_all(bio); + return bytes_written; } diff --git a/indra/llcommon/llcallbacklist.cpp b/indra/llcommon/llcallbacklist.cpp new file mode 100644 index 0000000000..1876eedd18 --- /dev/null +++ b/indra/llcommon/llcallbacklist.cpp @@ -0,0 +1,229 @@ +/** + * @file llcallbacklist.cpp + * @brief A simple list of callback functions to call. + * + * $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 "llcallbacklist.h" +#include "lleventtimer.h" +#include "llerrorlegacy.h" + +// Globals +// +LLCallbackList gIdleCallbacks; + +// +// Member functions +// + +LLCallbackList::LLCallbackList() +{ + // nothing +} + +LLCallbackList::~LLCallbackList() +{ +} + + +void LLCallbackList::addFunction( callback_t func, void *data) +{ + if (!func) + { + return; + } + + // only add one callback per func/data pair + // + if (containsFunction(func)) + { + return; + } + + callback_pair_t t(func, data); + mCallbackList.push_back(t); +} + +bool LLCallbackList::containsFunction( callback_t func, void *data) +{ + callback_list_t::iterator iter = find(func,data); + if (iter != mCallbackList.end()) + { + return TRUE; + } + else + { + return FALSE; + } +} + + +bool LLCallbackList::deleteFunction( callback_t func, void *data) +{ + callback_list_t::iterator iter = find(func,data); + if (iter != mCallbackList.end()) + { + mCallbackList.erase(iter); + return TRUE; + } + else + { + return FALSE; + } +} + +inline +LLCallbackList::callback_list_t::iterator +LLCallbackList::find(callback_t func, void *data) +{ + callback_pair_t t(func, data); + return std::find(mCallbackList.begin(), mCallbackList.end(), t); +} + +void LLCallbackList::deleteAllFunctions() +{ + mCallbackList.clear(); +} + + +void LLCallbackList::callFunctions() +{ + for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); ) + { + callback_list_t::iterator curiter = iter++; + curiter->first(curiter->second); + } +} + +// Shim class to allow arbitrary boost::bind +// expressions to be run as one-time idle callbacks. +class OnIdleCallbackOneTime +{ +public: + OnIdleCallbackOneTime(nullary_func_t callable): + mCallable(callable) + { + } + static void onIdle(void *data) + { + gIdleCallbacks.deleteFunction(onIdle, data); + OnIdleCallbackOneTime* self = reinterpret_cast(data); + self->call(); + delete self; + } + void call() + { + mCallable(); + } +private: + nullary_func_t mCallable; +}; + +void doOnIdleOneTime(nullary_func_t callable) +{ + OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable); + gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor); +} + +// Shim class to allow generic boost functions to be run as +// recurring idle callbacks. Callable should return true when done, +// false to continue getting called. +class OnIdleCallbackRepeating +{ +public: + OnIdleCallbackRepeating(bool_func_t callable): + mCallable(callable) + { + } + // Will keep getting called until the callable returns true. + static void onIdle(void *data) + { + OnIdleCallbackRepeating* self = reinterpret_cast(data); + bool done = self->call(); + if (done) + { + gIdleCallbacks.deleteFunction(onIdle, data); + delete self; + } + } + bool call() + { + return mCallable(); + } +private: + bool_func_t mCallable; +}; + +void doOnIdleRepeating(bool_func_t callable) +{ + OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable); + gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor); +} + +class NullaryFuncEventTimer: public LLEventTimer +{ +public: + NullaryFuncEventTimer(nullary_func_t callable, F32 seconds): + LLEventTimer(seconds), + mCallable(callable) + { + } + +private: + BOOL tick() + { + mCallable(); + return TRUE; + } + + nullary_func_t mCallable; +}; + +// Call a given callable once after specified interval. +void doAfterInterval(nullary_func_t callable, F32 seconds) +{ + new NullaryFuncEventTimer(callable, seconds); +} + +class BoolFuncEventTimer: public LLEventTimer +{ +public: + BoolFuncEventTimer(bool_func_t callable, F32 seconds): + LLEventTimer(seconds), + mCallable(callable) + { + } +private: + BOOL tick() + { + return mCallable(); + } + + bool_func_t mCallable; +}; + +// Call a given callable every specified number of seconds, until it returns true. +void doPeriodically(bool_func_t callable, F32 seconds) +{ + new BoolFuncEventTimer(callable, seconds); +} diff --git a/indra/newview/llcallbacklist.h b/indra/llcommon/llcallbacklist.h similarity index 76% rename from indra/newview/llcallbacklist.h rename to indra/llcommon/llcallbacklist.h index 0516c9cdb4..1fdb8ca095 100644 --- a/indra/newview/llcallbacklist.h +++ b/indra/llcommon/llcallbacklist.h @@ -28,27 +28,35 @@ #define LL_LLCALLBACKLIST_H #include "llstl.h" +#include +#include +#include "stdtypes.h" class LLCallbackList { public: typedef void (*callback_t)(void*); + + typedef std::pair< callback_t,void* > callback_pair_t; + // NOTE: It is confirmed that we DEPEND on the order provided by using a list :( + // + typedef std::list< callback_pair_t > callback_list_t; LLCallbackList(); ~LLCallbackList(); - void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data) - BOOL containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair - BOOL deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found - void callFunctions(); // calls all functions + void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data) + bool containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair + bool deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found + void callFunctions(); // calls all functions void deleteAllFunctions(); static void test(); protected: - // Use a list so that the callbacks are ordered in case that matters - typedef std::pair callback_pair_t; - typedef std::list callback_list_t; + + inline callback_list_t::iterator find(callback_t func, void *data); + callback_list_t mCallbackList; }; diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp index b6f715b0ce..6d27c6e209 100644 --- a/indra/llcommon/llcriticaldamp.cpp +++ b/indra/llcommon/llcriticaldamp.cpp @@ -33,63 +33,105 @@ #include "linden_common.h" #include "llcriticaldamp.h" +#include //----------------------------------------------------------------------------- // static members //----------------------------------------------------------------------------- -LLFrameTimer LLCriticalDamp::sInternalTimer; -std::map LLCriticalDamp::sInterpolants; -F32 LLCriticalDamp::sTimeDelta; +LLFrameTimer LLSmoothInterpolation::sInternalTimer; +std::vector LLSmoothInterpolation::sInterpolants; +F32 LLSmoothInterpolation::sTimeDelta; +std::pair sCachedEntry; + +// helper functors +struct LLSmoothInterpolation::CompareTimeConstants +{ + bool operator()(const F32& a, const LLSmoothInterpolation::Interpolant& b) const + { + return a < b.mTimeScale; + } + + bool operator()(const LLSmoothInterpolation::Interpolant& a, const F32& b) const + { + return a.mTimeScale < b; // bottom of a is higher than bottom of b + } + + bool operator()(const LLSmoothInterpolation::Interpolant& a, const LLSmoothInterpolation::Interpolant& b) const + { + return a.mTimeScale < b.mTimeScale; // bottom of a is higher than bottom of b + } +}; //----------------------------------------------------------------------------- -// LLCriticalDamp() +// LLSmoothInterpolation() //----------------------------------------------------------------------------- -LLCriticalDamp::LLCriticalDamp() +LLSmoothInterpolation::LLSmoothInterpolation() { sTimeDelta = 0.f; + sCachedEntry = std::pair(-1.f, -1.f); } // static //----------------------------------------------------------------------------- // updateInterpolants() //----------------------------------------------------------------------------- -void LLCriticalDamp::updateInterpolants() +void LLSmoothInterpolation::updateInterpolants() { sTimeDelta = sInternalTimer.getElapsedTimeAndResetF32(); - F32 time_constant; - - for (std::map::iterator iter = sInterpolants.begin(); - iter != sInterpolants.end(); iter++) + for (size_t i = 0; i < sInterpolants.size(); i++) { - time_constant = iter->first; - F32 new_interpolant = 1.f - pow(2.f, -sTimeDelta / time_constant); - new_interpolant = llclamp(new_interpolant, 0.f, 1.f); - sInterpolants[time_constant] = new_interpolant; + Interpolant& interp = sInterpolants[i]; + interp.mInterpolant = calcInterpolant(interp.mTimeScale); + if (sCachedEntry.first == interp.mTimeScale) + { + sCachedEntry.second = interp.mInterpolant; + } } } //----------------------------------------------------------------------------- // getInterpolant() //----------------------------------------------------------------------------- -F32 LLCriticalDamp::getInterpolant(const F32 time_constant, BOOL use_cache) +F32 LLSmoothInterpolation::getInterpolant(F32SecondsImplicit time_constant, bool use_cache) { if (time_constant == 0.f) { return 1.f; } - if (use_cache && sInterpolants.count(time_constant)) + if (use_cache) { - return sInterpolants[time_constant]; + if (sCachedEntry.first == time_constant) + { + return sCachedEntry.second; + } + interpolant_vec_t::iterator find_it = std::lower_bound(sInterpolants.begin(), sInterpolants.end(), time_constant.value(), CompareTimeConstants()); + if (find_it != sInterpolants.end() && find_it->mTimeScale == time_constant) + { + sCachedEntry = std::make_pair(time_constant.value(), find_it->mInterpolant); + return find_it->mInterpolant; + } + else + { + Interpolant interp; + interp.mTimeScale = time_constant.value(); + interp.mInterpolant = calcInterpolant(time_constant.value()); + sInterpolants.insert(find_it, interp); + sCachedEntry = std::make_pair(time_constant.value(), interp.mInterpolant); + return interp.mInterpolant; + } } - - F32 interpolant = 1.f - pow(2.f, -sTimeDelta / time_constant); - interpolant = llclamp(interpolant, 0.f, 1.f); - if (use_cache) + else { - sInterpolants[time_constant] = interpolant; + return calcInterpolant(time_constant.value()); } +} - return interpolant; +//----------------------------------------------------------------------------- +// calcInterpolant() +//----------------------------------------------------------------------------- +F32 LLSmoothInterpolation::calcInterpolant(F32 time_constant) +{ + return llclamp(1.f - powf(2.f, -sTimeDelta / time_constant), 0.f, 1.f); } diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h index 13e37d8b78..d5c346d8ab 100644 --- a/indra/llcommon/llcriticaldamp.h +++ b/indra/llcommon/llcriticaldamp.h @@ -34,26 +34,46 @@ #ifndef LL_LLCRITICALDAMP_H #define LL_LLCRITICALDAMP_H -#include +#include #include "llframetimer.h" +#include "llunits.h" -class LL_COMMON_API LLCriticalDamp +class LL_COMMON_API LLSmoothInterpolation { public: - LLCriticalDamp(); + LLSmoothInterpolation(); // MANIPULATORS static void updateInterpolants(); // ACCESSORS - static F32 getInterpolant(const F32 time_constant, BOOL use_cache = TRUE); + static F32 getInterpolant(F32SecondsImplicit time_constant, bool use_cache = true); -protected: + template + static T lerp(T a, T b, F32SecondsImplicit time_constant, bool use_cache = true) + { + F32 interpolant = getInterpolant(time_constant, use_cache); + return ((a * (1.f - interpolant)) + + (b * interpolant)); + } + +protected: + static F32 calcInterpolant(F32 time_constant); + + struct CompareTimeConstants; static LLFrameTimer sInternalTimer; // frame timer for calculating deltas - static std::map sInterpolants; + struct Interpolant + { + F32 mTimeScale; + F32 mInterpolant; + }; + typedef std::vector interpolant_vec_t; + static interpolant_vec_t sInterpolants; static F32 sTimeDelta; }; +typedef LLSmoothInterpolation LLCriticalDamp; + #endif // LL_LLCRITICALDAMP_H diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index b24e70fad3..56b19316f9 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -4,69 +4,60 @@ * @date 2006-02-05 * @brief Implementation of the date class * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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 "lldate.h" -#include "apr_time.h" - #include #include #include #include +#include #include -#include "llfasttimer.h" #include "lltimer.h" #include "llstring.h" +#include "llfasttimer.h" -static const F64 DATE_EPOCH = 0.0; - -static const F64 LL_APR_USEC_PER_SEC = 1000000.0; - // should be APR_USEC_PER_SEC, but that relies on INT64_C which - // isn't defined in glib under our build set up for some reason +#if defined(LL_WINDOWS) && !defined(timegm) +# define timegm _mkgmtime +#endif +#define EPOCH_STR "1970-01-01T00:00:00Z" +static const F64 DATE_EPOCH = 0.0; +static std::string sPrevLocale = ""; LLDate::LLDate() : mSecondsSinceEpoch(DATE_EPOCH) -{ -} +{} LLDate::LLDate(const LLDate& date) : mSecondsSinceEpoch(date.mSecondsSinceEpoch) -{ -} +{} -LLDate::LLDate(F64 seconds_since_epoch) : - mSecondsSinceEpoch(seconds_since_epoch) -{ -} +LLDate::LLDate(F64SecondsImplicit seconds_since_epoch) : + mSecondsSinceEpoch(seconds_since_epoch.value()) +{} LLDate::LLDate(const std::string& iso8601_date) { @@ -95,34 +86,40 @@ std::string LLDate::asRFC1123() const return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT")); } -LLFastTimer::DeclareTimer FT_DATE_FORMAT("Date Format"); +LLTrace::BlockTimerStatHandle FT_DATE_FORMAT("Date Format"); -std::string LLDate::toHTTPDateString (std::string fmt) const +std::string LLDate::toHTTPDateString(const std::string& fmt) const { - LLFastTimer ft1(FT_DATE_FORMAT); + LL_RECORD_BLOCK_TIME(FT_DATE_FORMAT); - time_t locSeconds = (time_t) mSecondsSinceEpoch; - struct tm * gmt = gmtime (&locSeconds); + std::time_t locSeconds = (std::time_t) mSecondsSinceEpoch; + std::tm * gmt = gmtime (&locSeconds); + if (!gmt) + { + LL_WARNS() << "The impossible has happened!" << LL_ENDL; + return LLStringExplicit(EPOCH_STR); + } return toHTTPDateString(gmt, fmt); } -std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt) +std::string LLDate::toHTTPDateString(tm * gmt, const std::string& fmt) { - LLFastTimer ft1(FT_DATE_FORMAT); + LL_RECORD_BLOCK_TIME(FT_DATE_FORMAT); // avoid calling setlocale() unnecessarily - it's expensive. - static std::string prev_locale = ""; std::string this_locale = LLStringUtil::getLocale(); - if (this_locale != prev_locale) + if (this_locale != sPrevLocale) { setlocale(LC_TIME, this_locale.c_str()); - prev_locale = this_locale; + sPrevLocale = this_locale; } // use strftime() as it appears to be faster than std::time_put - char buffer[128]; - strftime(buffer, 128, fmt.c_str(), gmt); + char buffer[128] = {}; + if (std::strftime(buffer, sizeof(buffer), fmt.c_str(), gmt) == 0) + return LLStringExplicit(EPOCH_STR); std::string res(buffer); + #if LL_WINDOWS // Convert from locale-dependant charset to UTF-8 (EXT-8524). res = ll_convert_string_to_utf8_string(res); @@ -132,12 +129,18 @@ std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt) void LLDate::toStream(std::ostream& s) const { - apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC); + std::ios::fmtflags f( s.flags() ); - apr_time_exp_t exp_time; - if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS) + std::tm exp_time = {0}; + std::time_t time = static_cast(mSecondsSinceEpoch); + +#if LL_WINDOWS + if (gmtime_s(&exp_time, &time) != 0) +#else + if (!gmtime_r(&time, &exp_time)) +#endif { - s << "1970-01-01T00:00:00Z"; + s << EPOCH_STR; return; } @@ -153,22 +156,29 @@ void LLDate::toStream(std::ostream& s) const << 'T' << std::setw(2) << (exp_time.tm_hour) << ':' << std::setw(2) << (exp_time.tm_min) << ':' << std::setw(2) << (exp_time.tm_sec); - if (exp_time.tm_usec > 0) - { - s << '.' << std::setw(2) - << (int)(exp_time.tm_usec / (LL_APR_USEC_PER_SEC / 100)); - } s << 'Z' << std::setfill(' '); + + s.flags( f ); } bool LLDate::split(S32 *year, S32 *month, S32 *day, S32 *hour, S32 *min, S32 *sec) const { - apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC); + std::tm exp_time = {0}; + std::time_t time = static_cast(mSecondsSinceEpoch); - apr_time_exp_t exp_time; - if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS) +#if LL_WINDOWS + if (gmtime_s(&exp_time, &time) != 0) +#else + if (!gmtime_r(&time, &exp_time)) +#endif { + *year = 1970; + *month = 01; + *day = 01; + *hour = 00; + *min = 00; + *sec = 00; return false; } @@ -201,60 +211,63 @@ bool LLDate::fromString(const std::string& iso8601_date) bool LLDate::fromStream(std::istream& s) { - struct apr_time_exp_t exp_time; - apr_int32_t tm_part; + std::tm time = {0}; int c; - +#if LL_WINDOWS || LL_LINUX // GCC 4.8 lacks this Windows has broken std::get_time() Time for things to get ugly! + int32_t tm_part; s >> tm_part; - exp_time.tm_year = tm_part - 1900; + time.tm_year = tm_part - 1900; c = s.get(); // skip the hypen if (c != '-') { return false; } s >> tm_part; - exp_time.tm_mon = tm_part - 1; + time.tm_mon = tm_part - 1; c = s.get(); // skip the hypen if (c != '-') { return false; } s >> tm_part; - exp_time.tm_mday = tm_part; + time.tm_mday = tm_part; c = s.get(); // skip the T if (c != 'T') { return false; } s >> tm_part; - exp_time.tm_hour = tm_part; + time.tm_hour = tm_part; c = s.get(); // skip the : if (c != ':') { return false; } s >> tm_part; - exp_time.tm_min = tm_part; + time.tm_min = tm_part; c = s.get(); // skip the : if (c != ':') { return false; } s >> tm_part; - exp_time.tm_sec = tm_part; - - // zero out the unused fields - exp_time.tm_usec = 0; - exp_time.tm_wday = 0; - exp_time.tm_yday = 0; - exp_time.tm_isdst = 0; - exp_time.tm_gmtoff = 0; - - // generate a time_t from that - apr_time_t time; - if (apr_time_exp_gmt_get(&time, &exp_time) != APR_SUCCESS) - { - return false; - } - - F64 seconds_since_epoch = time / LL_APR_USEC_PER_SEC; + time.tm_sec = tm_part; - // check for fractional c = s.peek(); if(c == '.') { F64 fractional = 0.0; s >> fractional; - seconds_since_epoch += fractional; } +#else + std::string this_locale = LLStringUtil::getLocale(); + if (this_locale != sPrevLocale) + { + setlocale(LC_TIME, this_locale.c_str()); + sPrevLocale = this_locale; + } + + // Isn't stdlib nice? + s.imbue(std::locale(sPrevLocale.c_str())); + s >> std::get_time(&time, "%Y-%m-%dT%H:%M:%S"); + if (s.fail()) + { + return false; + } +#endif + std::time_t tm = timegm(&time); + if (tm == -1) + return false; + + F64 seconds_since_epoch = static_cast(tm); c = s.peek(); // check for offset if (c == '+' || c == '-') { @@ -270,7 +283,6 @@ bool LLDate::fromStream(std::istream& s) { s >> offset_minutes; } - offset_in_seconds = (offset_hours * 60 + offset_sign * offset_minutes) * 60; seconds_since_epoch -= offset_in_seconds; } @@ -282,7 +294,7 @@ bool LLDate::fromStream(std::istream& s) bool LLDate::fromYMDHMS(S32 year, S32 month, S32 day, S32 hour, S32 min, S32 sec) { - struct apr_time_exp_t exp_time; + std::tm exp_time = {0}; exp_time.tm_year = year - 1900; exp_time.tm_mon = month - 1; @@ -291,21 +303,11 @@ bool LLDate::fromYMDHMS(S32 year, S32 month, S32 day, S32 hour, S32 min, S32 sec exp_time.tm_min = min; exp_time.tm_sec = sec; - // zero out the unused fields - exp_time.tm_usec = 0; - exp_time.tm_wday = 0; - exp_time.tm_yday = 0; - exp_time.tm_isdst = 0; - exp_time.tm_gmtoff = 0; - - // generate a time_t from that - apr_time_t time; - if (apr_time_exp_gmt_get(&time, &exp_time) != APR_SUCCESS) - { + std::time_t tm = timegm(&exp_time); + if (tm == -1) return false; - } - mSecondsSinceEpoch = time / LL_APR_USEC_PER_SEC; + mSecondsSinceEpoch = static_cast(tm); return true; } diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 7e8ae63687..999486ebb4 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -38,9 +38,8 @@ #include #include -#include "llpreprocessor.h" - #include "stdtypes.h" +#include "llunits.h" /** * @class LLDate @@ -64,9 +63,9 @@ class LL_COMMON_API LLDate /** * @brief Construct a date from a seconds since epoch value. * - * @pararm seconds_since_epoch The number of seconds since UTC epoch. + * @param seconds_since_epoch The number of seconds since UTC epoch. */ - LLDate(F64 seconds_since_epoch); + LLDate(F64SecondsImplicit seconds_since_epoch); /** * @brief Construct a date from a string representation @@ -87,8 +86,8 @@ class LL_COMMON_API LLDate std::string asRFC1123() const; void toStream(std::ostream&) const; bool split(S32 *year, S32 *month = NULL, S32 *day = NULL, S32 *hour = NULL, S32 *min = NULL, S32 *sec = NULL) const; - std::string toHTTPDateString (std::string fmt) const; - static std::string toHTTPDateString (tm * gmt, std::string fmt); + std::string toHTTPDateString (const std::string& fmt) const; + static std::string toHTTPDateString (tm * gmt, const std::string& fmt); /** * @brief Set the date from an ISO-8601 string. * @@ -163,4 +162,6 @@ LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLDate& date); // Helper function to stream in a date LL_COMMON_API std::istream& operator>>(std::istream& s, LLDate& date); + + #endif // LL_LLDATE_H diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp index 0e72c175cb..6a1f8ec51b 100644 --- a/indra/llcommon/lldependencies.cpp +++ b/indra/llcommon/lldependencies.cpp @@ -41,7 +41,7 @@ #include // other Linden headers -LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const +LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(std::size_t vertices, const EdgeList& edges) const { // Construct a Boost Graph Library graph according to the constraints // we've collected. It seems as though we ought to be able to capture diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h index d48d298750..a3200a0ca4 100644 --- a/indra/llcommon/lldependencies.h +++ b/indra/llcommon/lldependencies.h @@ -127,9 +127,9 @@ class LL_COMMON_API LLDependenciesBase virtual std::string describe(bool full=true) const; protected: - typedef std::vector< std::pair > EdgeList; - typedef std::vector VertexList; - VertexList topo_sort(int vertices, const EdgeList& edges) const; + typedef std::vector< std::pair > EdgeList; + typedef std::vector VertexList; + VertexList topo_sort(std::size_t vertices, const EdgeList& edges) const; /** * refpair is specifically intended to capture a pair of references. This @@ -511,7 +511,7 @@ class LLDependencies: public LLDependenciesBase // been explicitly added. Rely on std::map rejecting a second attempt // to insert the same key. Use the map's size() as the vertex number // to get a distinct value for each successful insertion. - typedef std::map VertexMap; + typedef std::map VertexMap; VertexMap vmap; // Nest each of these loops because !@#$%? MSVC warns us that its // former broken behavior has finally been fixed -- and our builds @@ -542,7 +542,7 @@ class LLDependencies: public LLDependenciesBase for (typename DepNodeMap::const_iterator nmi = mNodes.begin(), nmend = mNodes.end(); nmi != nmend; ++nmi) { - int thisnode = vmap[nmi->first]; + std::size_t thisnode = vmap[nmi->first]; // after dependencies: build edges from the named node to this one for (typename DepNode::dep_set::const_iterator ai = nmi->second.after.begin(), aend = nmi->second.after.end(); diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h index 5800ec5e5d..144931bb7a 100644 --- a/indra/llcommon/lldictionary.h +++ b/indra/llcommon/lldictionary.h @@ -65,7 +65,7 @@ class LLDictionary : public std::map { for (const_iterator_t dictionary_iter = map_t::begin(); dictionary_iter != map_t::end(); - dictionary_iter++) + ++dictionary_iter) { const Entry *entry = dictionary_iter->second; if (entry->mName == name) diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index e6b688ee0c..f6c58513b0 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -120,6 +120,7 @@ namespace { LL_INFOS() << "Error setting log file to " << filename << LL_ENDL; } mWantsTime = true; + mWantsTags = true; } ~RecordToFile() @@ -252,23 +253,13 @@ namespace { #ifdef __GNUC__ // GCC: type_info::name() returns a mangled class name,st demangle - - static size_t abi_name_len = 100; - static char* abi_name_buf = (char*)malloc(abi_name_len); - // warning: above is voodoo inferred from the GCC manual, - // do NOT change - - int status; - // We don't use status, and shouldn't have to pass apointer to it - // but gcc 3.3 libstc++'s implementation of demangling is broken - // and fails without. - - char* name = abi::__cxa_demangle(type.name(), - abi_name_buf, &abi_name_len, &status); - // this call can realloc the abi_name_buf pointer (!) - - return name ? name : type.name(); - + // passing nullptr, 0 forces allocation of a unique buffer we can free + // fixing MAINT-8724 on OSX 10.14 + int status = -1; + char* name = abi::__cxa_demangle(type.name(), nullptr, 0, &status); + std::string result(name ? name : type.name()); + free(name); + return result; #elif LL_WINDOWS // DevStudio: type_info::name() includes the text "class " at the start @@ -600,7 +591,7 @@ namespace LLError mFunctionString += std::string(mFunction) + ":"; for (size_t i = 0; i < mTagCount; i++) { - mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : " "); + mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : ","); } } } @@ -983,13 +974,19 @@ namespace } if (show_level && r->wantsLevel()) - { - message_stream << site.mLevelString << " "; - } + { + message_stream << site.mLevelString; + } if (show_tags && r->wantsTags()) { - message_stream << site.mTagString << " "; + message_stream << site.mTagString; + } + + if ((show_level && r->wantsLevel())|| + (show_tags && r->wantsTags())) + { + message_stream << " "; } if (show_function && r->wantsFunctionName()) @@ -1341,7 +1338,7 @@ namespace LLError } #if LL_WINDOWS - // VC80 was optimizing the error away. + // MSVC is optimizing the error away. #pragma optimize("", off) #endif void crashAndLoop(const std::string& message) @@ -1350,9 +1347,8 @@ namespace LLError DoutFatal(dc::core, message); #else // Now, we go kaboom! - int* make_me_crash = NULL; - - *make_me_crash = 0; + int* make_me_crash = nullptr; + *make_me_crash = 0xDEADBEEF; while(true) { diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index dc72743120..90ef40bf60 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -72,7 +72,7 @@ const int LL_ERR_NOERR = 0; #endif // !_DEBUG -static const std::string liru_assert_strip(const std::string& file) { return file.substr(1+file.substr(0, file.find_last_of("/\\")).find_last_of("/\\")); } //return foo/bar.cpp or perhaps foo\bar.cpp +inline const std::string liru_assert_strip(const std::string& file) { return file.substr(1+file.substr(0, file.find_last_of("/\\")).find_last_of("/\\")); } //return foo/bar.cpp or perhaps foo\bar.cpp #define llassert_always_msg(func, msg) if (LL_UNLIKELY(!(func))) LL_ERRS() << "ASSERT (" << msg << ")\nfile:" << liru_assert_strip(__FILE__) << " line:" << std::dec << __LINE__ << LL_ENDL @@ -353,8 +353,14 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; // NEW Macros for debugging, allow the passing of a string tag +#ifdef SHOW_DEBUG +#define DO_DEBUG_LOG +#else +#define DO_DEBUG_LOG if (false) +#endif + // Pass comma separated list of tags (currently only supports up to 0, 1, or 2) -#define LL_DEBUGS(...) lllog(LLError::LEVEL_DEBUG, false, false, ##__VA_ARGS__) +#define LL_DEBUGS(...) DO_DEBUG_LOG lllog(LLError::LEVEL_DEBUG, false, false, ##__VA_ARGS__) #define LL_INFOS(...) lllog(LLError::LEVEL_INFO, false, false, ##__VA_ARGS__) #define LL_WARNS(...) lllog(LLError::LEVEL_WARN, false, false, ##__VA_ARGS__) #define LL_ERRS(...) lllog(LLError::LEVEL_ERROR, false, false, ##__VA_ARGS__) @@ -363,12 +369,12 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; // Only print the log message once (good for warnings or infos that would otherwise // spam the log file over and over, such as tighter loops). -#define LL_DEBUGS_ONCE(...) lllog(LLError::LEVEL_DEBUG, true, false, ##__VA_ARGS__) +#define LL_DEBUGS_ONCE(...) DO_DEBUG_LOG lllog(LLError::LEVEL_DEBUG, true, false, ##__VA_ARGS__) #define LL_INFOS_ONCE(...) lllog(LLError::LEVEL_INFO, true, false, ##__VA_ARGS__) #define LL_WARNS_ONCE(...) lllog(LLError::LEVEL_WARN, true, false, ##__VA_ARGS__) // No function name -#define LL_DEBUGS_NF(...) lllog(LLError::LEVEL_DEBUG, false, true, ##__VA_ARGS__) +#define LL_DEBUGS_NF(...) DO_DEBUG_LOG {lllog(LLError::LEVEL_DEBUG, false, true, ##__VA_ARGS__) #define LL_INFOS_NF(...) lllog(LLError::LEVEL_INFO, false, true, ##__VA_ARGS__) #define LL_WARNS_NF(...) lllog(LLError::LEVEL_WARN, false, true, ##__VA_ARGS__) #define LL_ERRS_NF(...) lllog(LLError::LEVEL_ERROR, false, true, ##__VA_ARGS__) diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h index 7307331099..31dd207008 100644 --- a/indra/llcommon/llerrorlegacy.h +++ b/indra/llcommon/llerrorlegacy.h @@ -28,117 +28,5 @@ #ifndef LL_LLERRORLEGACY_H #define LL_LLERRORLEGACY_H -#include "llpreprocessor.h" - -/* - LEGACY -- DO NOT USE THIS STUFF ANYMORE -*/ - -// Specific error codes -const int LL_ERR_NOERR = 0; -const int LL_ERR_ASSET_REQUEST_FAILED = -1; -//const int LL_ERR_ASSET_REQUEST_INVALID = -2; -const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3; -const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4; -const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5; -const int LL_ERR_EOF = -39; -const int LL_ERR_CANNOT_OPEN_FILE = -42; -const int LL_ERR_FILE_NOT_FOUND = -43; -const int LL_ERR_FILE_EMPTY = -44; -const int LL_ERR_TCP_TIMEOUT = -23016; -const int LL_ERR_CIRCUIT_GONE = -23017; -const int LL_ERR_PRICE_MISMATCH = -23018; - - - -// Define one of these for different error levels in release... -// #define RELEASE_SHOW_DEBUG // Define this if you want your release builds to show lldebug output. -#define RELEASE_SHOW_INFO // Define this if you want your release builds to show llinfo output -#define RELEASE_SHOW_WARN // Define this if you want your release builds to show llwarn output. - - -////////////////////////////////////////// -// -// Implementation - ignore -// -// -#ifdef _DEBUG -#define SHOW_DEBUG -#define SHOW_WARN -#define SHOW_INFO -#define SHOW_ASSERT -#else // _DEBUG - -#ifdef LL_RELEASE_WITH_DEBUG_INFO -#define SHOW_ASSERT -#endif // LL_RELEASE_WITH_DEBUG_INFO - -#ifdef RELEASE_SHOW_DEBUG -#define SHOW_DEBUG -#endif - -#ifdef RELEASE_SHOW_WARN -#define SHOW_WARN -#endif - -#ifdef RELEASE_SHOW_INFO -#define SHOW_INFO -#endif - -#ifdef RELEASE_SHOW_ASSERT -#define SHOW_ASSERT -#endif - -#endif // _DEBUG - - - -#define lldebugst(type) lldebugs -#define llendflush llendl - - -#define llerror(msg, num) LL_ERRS() << "Error # " << num << ": " << msg << LL_ENDL; - -#define llwarning(msg, num) LL_WARNS() << "Warning # " << num << ": " << msg << LL_ENDL; - -#define liru_slashpos std::string(__FILE__).find_last_of("/\\") -#define liru_slashpos2 std::string(__FILE__).substr(0,liru_slashpos).find_last_of("/\\") -#define liru_assert_strip /*strip path down to lastlevel directory and filename for assert.*/\ - (liru_slashpos == std::string::npos ? std::string(__FILE__)/*just filename, print as is*/\ - : liru_slashpos2 == std::string::npos ? std::string(__FILE__)/*Apparently, we're in / or perhaps the top of the drive, print as is*/\ - : std::string(__FILE__).substr(1+liru_slashpos2))/*print foo/bar.cpp or perhaps foo\bar.cpp*/ - -#define llassert_always(func) do { if (LL_UNLIKELY(!(func))) LL_ERRS() << "\nASSERT(" #func ")\nfile:" << liru_assert_strip << " line:" << std::dec << __LINE__ << LL_ENDL; } while(0) - -#ifdef SHOW_ASSERT -#define llassert(func) llassert_always(func) -#define llverify(func) llassert_always(func) -#else -#define llassert(func) -#define llverify(func) do {if (func) {}} while(0) -#endif - -// This can be used for function parameters that are only used by llassert. -// The ellipsis is needed in case the parameter contains comma's (ie, as part of the type, -// or trailing comma). The first version can be used as first (or only) parameter of a function, -// or as parameter in the middle when adding a trailing comma, while the second version can be -// used as last parameter. -// -// Example usage: -// -// void foo(ASSERT_ONLY(int x)); -// void foo(x, ASSERT_ONLY(int y,) int z); -// void foo(x/*,*/ ASSERT_ONLY_COMMA(int y)); // The optional /*,*/ makes it just a bit better readable. -#ifdef SHOW_ASSERT -#define ASSERT_ONLY(...) __VA_ARGS__ -#define ASSERT_ONLY_COMMA(...) , __VA_ARGS__ -#else -#define ASSERT_ONLY(...) -#define ASSERT_ONLY_COMMA(...) -#endif - -// handy compile-time assert - enforce those template parameters! -#define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1] /* Flawfinder: ignore */ - //XXX: used in two places in llcommon/llskipmap.h #endif // LL_LLERRORLEGACY_H diff --git a/indra/llcommon/llevent.cpp b/indra/llcommon/llevent.cpp index f669d0e13f..7b3ba795af 100644 --- a/indra/llcommon/llevent.cpp +++ b/indra/llcommon/llevent.cpp @@ -226,7 +226,7 @@ bool LLSimpleDispatcher::fireEvent(LLPointer event, LLSD filter) for (itor=mListeners.begin(); itor!=mListeners.end(); ++itor) { LLListenerEntry& entry = *itor; - if (filter_string == "" || entry.filter.asString() == filter_string) + if (filter_string.empty() || entry.filter.asString() == filter_string) { (entry.listener)->handleEvent(event, (*itor).userdata); } diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h index b451092bfe..3aedb37b1b 100644 --- a/indra/llcommon/lleventcoro.h +++ b/indra/llcommon/lleventcoro.h @@ -412,7 +412,7 @@ class LL_COMMON_API LLErrorEvent: public std::runtime_error std::runtime_error(what), mData(data) {} - virtual ~LLErrorEvent() throw() {} + virtual ~LLErrorEvent() noexcept {} LLSD getData() const { return mData; } diff --git a/indra/llcommon/lleventdispatcher.cpp b/indra/llcommon/lleventdispatcher.cpp index 5b6d4efbe9..b4ed63998e 100644 --- a/indra/llcommon/lleventdispatcher.cpp +++ b/indra/llcommon/lleventdispatcher.cpp @@ -381,10 +381,9 @@ std::string LLSDArgsMapper::formatlist(const LLSD& list) { std::ostringstream out; const char* delim = ""; - for (LLSD::array_const_iterator li(list.beginArray()), lend(list.endArray()); - li != lend; ++li) + for (auto const& entry : list.array()) { - out << delim << li->asString(); + out << delim << entry.asString(); delim = ", "; } return out.str(); @@ -449,7 +448,7 @@ struct LLEventDispatcher::ParamsDispatchEntry: public LLEventDispatcher::Dispatc virtual void call(const std::string& desc, const LLSD& event) const { LLSDArgsSource src(desc, event); - mInvoker(boost::bind(&LLSDArgsSource::next, boost::ref(src))); + mInvoker(std::bind(&LLSDArgsSource::next, std::ref(src))); } }; @@ -494,10 +493,9 @@ struct LLEventDispatcher::MapParamsDispatchEntry: public LLEventDispatcher::Para { // Build the set of all param keys, then delete the ones that are // optional. What's left are the ones that are required. - for (LLSD::array_const_iterator pi(params.beginArray()), pend(params.endArray()); - pi != pend; ++pi) + for (auto const& entry : params.array()) { - mRequired[pi->asString()] = LLSD(); + mRequired[entry.asString()] = LLSD(); } if (defaults.isArray() || defaults.isUndefined()) diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index dc582f2d2d..8f54bc2e52 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -57,19 +57,12 @@ static const int& nil(nil_); #endif #include -#include -#ifndef BOOST_FUNCTION_HPP_INCLUDED #include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif -#include #include #include #include #include #include -#include -#include #include #include #include @@ -303,7 +296,7 @@ class LL_COMMON_API LLEventDispatcher // subclass object. However, I definitely want DispatchMap to destroy // DispatchEntry if no references are outstanding at the time an entry is // removed. This looks like a job for boost::shared_ptr. - typedef std::map > DispatchMap; + typedef std::map > DispatchMap; public: /// We want the flexibility to redefine what data we store per name, @@ -430,7 +423,7 @@ struct LLEventDispatcher::invoker // Instead of grabbing the first item from argsrc and making an // LLSDParam of it, call getter() and pass that as the instance param. invoker::apply - ( func, argsrc, boost::fusion::push_back(boost::fusion::nil(), boost::ref(getter()))); + ( func, argsrc, boost::fusion::push_back(boost::fusion::nil(), std::ref(getter()))); } }; diff --git a/indra/llcommon/lleventfilter.cpp b/indra/llcommon/lleventfilter.cpp index d36a107254..bf0f215844 100644 --- a/indra/llcommon/lleventfilter.cpp +++ b/indra/llcommon/lleventfilter.cpp @@ -33,15 +33,14 @@ // STL headers // std headers // external library headers -#include // other Linden headers #include "llerror.h" // LL_ERRS #include "llsdutil.h" // llsd_matches() LLEventFilter::LLEventFilter(LLEventPump& source, const std::string& name, bool tweak): - LLEventStream(name, tweak) + LLEventStream(name, tweak), + mSource(source.listen(getName(), boost::bind(&LLEventFilter::post, this, _1))) { - source.listen(getName(), boost::bind(&LLEventFilter::post, this, _1)); } LLEventMatching::LLEventMatching(const LLSD& pattern): diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h index 4fff7644af..751aa463c8 100644 --- a/indra/llcommon/lleventfilter.h +++ b/indra/llcommon/lleventfilter.h @@ -32,10 +32,6 @@ #include "llevents.h" #include "stdtypes.h" #include "lltimer.h" -#ifndef BOOST_FUNCTION_HPP_INCLUDED -#include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif /** * Generic base class @@ -52,6 +48,9 @@ class LL_COMMON_API LLEventFilter: public LLEventStream /// Post an event to all listeners virtual bool post(const LLSD& event) = 0; + +private: + LLTempBoundListener mSource; }; /** @@ -89,7 +88,7 @@ class LL_COMMON_API LLEventTimeoutBase: public LLEventFilter LLEventTimeoutBase(LLEventPump& source); /// Callable, can be constructed with boost::bind() - typedef boost::function Action; + typedef std::function Action; /** * Start countdown timer for the specified number of @a seconds. Forward diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 170930c8cb..7770ff4c55 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -182,10 +182,10 @@ class LL_COMMON_API LLListenerOrPumpName bool operator! () const { return ! mListener; } /// explicit accessor - const LLEventListener& getListener() const { return *mListener; } + const ::LLEventListener& getListener() const { return *mListener; } /// implicit conversion to LLEventListener - operator LLEventListener() const { return *mListener; } + operator ::LLEventListener() const { return *mListener; } /// allow calling directly bool operator()(const LLSD& event) const; @@ -277,7 +277,7 @@ namespace LLEventDetail /// Any callable capable of connecting an LLEventListener to an /// LLStandardSignal to produce an LLBoundListener can be mapped to this /// signature. - typedef boost::function ConnectFunc; + typedef boost::function ConnectFunc; /// overload of visit_and_connect() when we have a string identifier available template @@ -547,7 +547,7 @@ class LL_COMMON_API LLEventPump: public LLEventTrackable virtual void reset(); private: - virtual LLBoundListener listen_impl(const std::string& name, const LLEventListener&, + virtual LLBoundListener listen_impl(const std::string& name, const ::LLEventListener&, const NameList& after, const NameList& before); std::string mName; @@ -845,7 +845,7 @@ namespace LLEventDetail * Visitor binds a reference to LLEventListener so we can track() any * shared_ptrs we find in the argument list. */ - Visitor(LLEventListener& listener): + Visitor(::LLEventListener& listener): mListener(listener) { } @@ -988,7 +988,7 @@ namespace LLEventDetail |*==========================================================================*/ /// Bind a reference to the LLEventListener to call its track() method. - LLEventListener& mListener; + ::LLEventListener& mListener; }; /** @@ -1005,7 +1005,7 @@ namespace LLEventDetail const ConnectFunc& connect_func) { // Capture the listener - LLEventListener listener(raw_listener); + ::LLEventListener listener(raw_listener); // Define our Visitor, binding the listener so we can call // listener.track() if we discover any shared_ptr. LLEventDetail::Visitor visitor(listener); diff --git a/indra/llcommon/lleventtimer.cpp b/indra/llcommon/lleventtimer.cpp index 957b502dc5..c491e37cb4 100644 --- a/indra/llcommon/lleventtimer.cpp +++ b/indra/llcommon/lleventtimer.cpp @@ -65,7 +65,7 @@ LLEventTimer::~LLEventTimer() void LLEventTimer::updateClass() { std::list completed_timers; - for (instance_iter iter = beginInstances(), iter_end = endInstances(); iter != iter_end;) + for (instance_iter iter = beginInstances(), end_iter = endInstances(); iter != end_iter;) { LLEventTimer& timer = *iter++; F32 et = timer.mEventTimer.getElapsedTimeF32(); diff --git a/indra/llcommon/llfasttimer_class.h b/indra/llcommon/llfasttimer_class.h index aa1f8ffacf..8967e64ac6 100644 --- a/indra/llcommon/llfasttimer_class.h +++ b/indra/llcommon/llfasttimer_class.h @@ -38,6 +38,8 @@ class LLMutex; #include #include "llsd.h" +#define LL_RECORD_BLOCK_TIME(timer_stat) LLFastTimer LL_GLUE_TOKENS(block_time_recorder, __LINE__)(timer_stat); + LL_COMMON_API void assert_main_thread(); class LL_COMMON_API LLFastTimer @@ -273,4 +275,9 @@ class LL_COMMON_API LLFastTimer }; +namespace LLTrace +{ + typedef LLFastTimer::DeclareTimer BlockTimerStatHandle; +} + #endif // LL_LLFASTTIMER_H diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index 686a516b9a..0b7677fade 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -28,7 +28,7 @@ */ #if LL_WINDOWS -#include +#include "llwin32headerslean.h" #include // Windows errno #else #include @@ -54,6 +54,7 @@ std::string LLFile::strerr(int errn) { char buffer[256]; strerror_s(buffer, errn); // infers sizeof(buffer) -- love it! + buffer[255] = 0; return buffer; } @@ -265,10 +266,10 @@ int LLFile::remove_nowarn(const std::string& filename) return rc; } -int LLFile::remove(const std::string& filename) +int LLFile::remove(const std::string& filename, int supress_error) { int rc = LLFile::remove_nowarn(filename); - return warnif("remove", filename, rc); + return warnif("remove", filename, rc, supress_error); } int LLFile::rename_nowarn(const std::string& filename, const std::string& newname) @@ -281,14 +282,19 @@ int LLFile::rename_nowarn(const std::string& filename, const std::string& newnam int rc = _wrename(utf16filename.c_str(),utf16newname.c_str()); #else int rc = ::rename(filename.c_str(),newname.c_str()); + if (rc == -1 && errno == EXDEV) + { + rc = std::system(("mv '" + filename + "' '" + newname + '\'').data()); + errno = 0; + } #endif return rc; } -int LLFile::rename(const std::string& filename, const std::string& newname) +int LLFile::rename(const std::string& filename, const std::string& newname, int supress_error) { int rc = LLFile::rename_nowarn(filename, newname); - return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc); + return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc, supress_error); } int LLFile::stat(const std::string& filename, llstat* filestatus) @@ -416,679 +422,76 @@ LLFILE * LLFile::_Fiopen(const std::string& filename, #endif /* LL_WINDOWS */ -/************** llstdio file buffer ********************************/ - - -//llstdio_filebuf* llstdio_filebuf::open(const char *_Filename, -// ios_base::openmode _Mode) -//{ -//#if LL_WINDOWS -// _Filet *_File; -// if (is_open() || (_File = LLFILE::_Fiopen(_Filename, _Mode)) == 0) -// return (0); // open failed -// -// _Init(_File, _Openfl); -// _Initcvt(&_USE(_Mysb::getloc(), _Cvt)); -// return (this); // open succeeded -//#else -// std::filebuf* _file = std::filebuf::open(_Filename, _Mode); -// if (NULL == _file) return NULL; -// return this; -//#endif -//} - - -// *TODO: Seek the underlying c stream for better cross-platform compatibility? -#if !LL_WINDOWS -llstdio_filebuf::int_type llstdio_filebuf::overflow(llstdio_filebuf::int_type __c) -{ - int_type __ret = traits_type::eof(); - const bool __testeof = traits_type::eq_int_type(__c, __ret); - const bool __testout = _M_mode & ios_base::out; - if (__testout && !_M_reading) - { - if (this->pbase() < this->pptr()) - { - // If appropriate, append the overflow char. - if (!__testeof) - { - *this->pptr() = traits_type::to_char_type(__c); - this->pbump(1); - } - - // Convert pending sequence to external representation, - // and output. - if (_convert_to_external(this->pbase(), - this->pptr() - this->pbase())) - { - _M_set_buffer(0); - __ret = traits_type::not_eof(__c); - } - } - else if (_M_buf_size > 1) - { - // Overflow in 'uncommitted' mode: set _M_writing, set - // the buffer to the initial 'write' mode, and put __c - // into the buffer. - _M_set_buffer(0); - _M_writing = true; - if (!__testeof) - { - *this->pptr() = traits_type::to_char_type(__c); - this->pbump(1); - } - __ret = traits_type::not_eof(__c); - } - else - { - // Unbuffered. - char_type __conv = traits_type::to_char_type(__c); - if (__testeof || _convert_to_external(&__conv, 1)) - { - _M_writing = true; - __ret = traits_type::not_eof(__c); - } - } - } - return __ret; -} - -bool llstdio_filebuf::_convert_to_external(char_type* __ibuf, - std::streamsize __ilen) -{ - // Sizes of external and pending output. - streamsize __elen; - streamsize __plen; - if (__check_facet(_M_codecvt).always_noconv()) - { - //__elen = _M_file.xsputn(reinterpret_cast(__ibuf), __ilen); - __elen = fwrite(reinterpret_cast(__ibuf), 1, - __ilen, _M_file.file()); - __plen = __ilen; - } - else - { - // Worst-case number of external bytes needed. - // XXX Not done encoding() == -1. - streamsize __blen = __ilen * _M_codecvt->max_length(); - char* __buf = static_cast(__builtin_alloca(__blen)); - - char* __bend; - const char_type* __iend; - codecvt_base::result __r; - __r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen, - __iend, __buf, __buf + __blen, __bend); - - if (__r == codecvt_base::ok || __r == codecvt_base::partial) - __blen = __bend - __buf; - else if (__r == codecvt_base::noconv) - { - // Same as the always_noconv case above. - __buf = reinterpret_cast(__ibuf); - __blen = __ilen; - } - else - __throw_ios_failure(__N("llstdio_filebuf::_convert_to_external " - "conversion error")); - - //__elen = _M_file.xsputn(__buf, __blen); - __elen = fwrite(__buf, 1, __blen, _M_file.file()); - __plen = __blen; - - // Try once more for partial conversions. - if (__r == codecvt_base::partial && __elen == __plen) - { - const char_type* __iresume = __iend; - streamsize __rlen = this->pptr() - __iend; - __r = _M_codecvt->out(_M_state_cur, __iresume, - __iresume + __rlen, __iend, __buf, - __buf + __blen, __bend); - if (__r != codecvt_base::error) - { - __rlen = __bend - __buf; - //__elen = _M_file.xsputn(__buf, __rlen); - __elen = fwrite(__buf, 1, __rlen, _M_file.file()); - __plen = __rlen; - } - else - { - __throw_ios_failure(__N("llstdio_filebuf::_convert_to_external " - "conversion error")); - } - } - } - return __elen == __plen; -} - -llstdio_filebuf::int_type llstdio_filebuf::underflow() -{ - int_type __ret = traits_type::eof(); - const bool __testin = _M_mode & ios_base::in; - if (__testin) - { - if (_M_writing) - { - if (overflow() == traits_type::eof()) - return __ret; - //_M_set_buffer(-1); - //_M_writing = false; - } - // Check for pback madness, and if so switch back to the - // normal buffers and jet outta here before expensive - // fileops happen... - _M_destroy_pback(); - - if (this->gptr() < this->egptr()) - return traits_type::to_int_type(*this->gptr()); - - // Get and convert input sequence. - const size_t __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1; - - // Will be set to true if ::fread() returns 0 indicating EOF. - bool __got_eof = false; - // Number of internal characters produced. - streamsize __ilen = 0; - codecvt_base::result __r = codecvt_base::ok; - if (__check_facet(_M_codecvt).always_noconv()) - { - //__ilen = _M_file.xsgetn(reinterpret_cast(this->eback()), - // __buflen); - __ilen = fread(reinterpret_cast(this->eback()), 1, - __buflen, _M_file.file()); - if (__ilen == 0) - __got_eof = true; - } - else - { - // Worst-case number of external bytes. - // XXX Not done encoding() == -1. - const int __enc = _M_codecvt->encoding(); - streamsize __blen; // Minimum buffer size. - streamsize __rlen; // Number of chars to read. - if (__enc > 0) - __blen = __rlen = __buflen * __enc; - else - { - __blen = __buflen + _M_codecvt->max_length() - 1; - __rlen = __buflen; - } - const streamsize __remainder = _M_ext_end - _M_ext_next; - __rlen = __rlen > __remainder ? __rlen - __remainder : 0; - - // An imbue in 'read' mode implies first converting the external - // chars already present. - if (_M_reading && this->egptr() == this->eback() && __remainder) - __rlen = 0; - - // Allocate buffer if necessary and move unconverted - // bytes to front. - if (_M_ext_buf_size < __blen) - { - char* __buf = new char[__blen]; - if (__remainder) - __builtin_memcpy(__buf, _M_ext_next, __remainder); - - delete [] _M_ext_buf; - _M_ext_buf = __buf; - _M_ext_buf_size = __blen; - } - else if (__remainder) - __builtin_memmove(_M_ext_buf, _M_ext_next, __remainder); - - _M_ext_next = _M_ext_buf; - _M_ext_end = _M_ext_buf + __remainder; - _M_state_last = _M_state_cur; - - do - { - if (__rlen > 0) - { - // Sanity check! - // This may fail if the return value of - // codecvt::max_length() is bogus. - if (_M_ext_end - _M_ext_buf + __rlen > _M_ext_buf_size) - { - __throw_ios_failure(__N("llstdio_filebuf::underflow " - "codecvt::max_length() " - "is not valid")); - } - //streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen); - streamsize __elen = fread(_M_ext_end, 1, - __rlen, _M_file.file()); - if (__elen == 0) - __got_eof = true; - else if (__elen == -1) - break; - //_M_ext_end += __elen; - } - - char_type* __iend = this->eback(); - if (_M_ext_next < _M_ext_end) - { - __r = _M_codecvt->in(_M_state_cur, _M_ext_next, - _M_ext_end, _M_ext_next, - this->eback(), - this->eback() + __buflen, __iend); - } - if (__r == codecvt_base::noconv) - { - size_t __avail = _M_ext_end - _M_ext_buf; - __ilen = std::min(__avail, __buflen); - traits_type::copy(this->eback(), - reinterpret_cast - (_M_ext_buf), __ilen); - _M_ext_next = _M_ext_buf + __ilen; - } - else - __ilen = __iend - this->eback(); - - // _M_codecvt->in may return error while __ilen > 0: this is - // ok, and actually occurs in case of mixed encodings (e.g., - // XML files). - if (__r == codecvt_base::error) - break; - - __rlen = 1; - } while (__ilen == 0 && !__got_eof); - } - - if (__ilen > 0) - { - _M_set_buffer(__ilen); - _M_reading = true; - __ret = traits_type::to_int_type(*this->gptr()); - } - else if (__got_eof) - { - // If the actual end of file is reached, set 'uncommitted' - // mode, thus allowing an immediate write without an - // intervening seek. - _M_set_buffer(-1); - _M_reading = false; - // However, reaching it while looping on partial means that - // the file has got an incomplete character. - if (__r == codecvt_base::partial) - __throw_ios_failure(__N("llstdio_filebuf::underflow " - "incomplete character in file")); - } - else if (__r == codecvt_base::error) - __throw_ios_failure(__N("llstdio_filebuf::underflow " - "invalid byte sequence in file")); - else - __throw_ios_failure(__N("llstdio_filebuf::underflow " - "error reading the file")); - } - return __ret; -} - -std::streamsize llstdio_filebuf::xsgetn(char_type* __s, std::streamsize __n) -{ - // Clear out pback buffer before going on to the real deal... - streamsize __ret = 0; - if (_M_pback_init) - { - if (__n > 0 && this->gptr() == this->eback()) - { - *__s++ = *this->gptr(); - this->gbump(1); - __ret = 1; - --__n; - } - _M_destroy_pback(); - } - - // Optimization in the always_noconv() case, to be generalized in the - // future: when __n > __buflen we read directly instead of using the - // buffer repeatedly. - const bool __testin = _M_mode & ios_base::in; - const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1; - - if (__n > __buflen && __check_facet(_M_codecvt).always_noconv() - && __testin && !_M_writing) - { - // First, copy the chars already present in the buffer. - const streamsize __avail = this->egptr() - this->gptr(); - if (__avail != 0) - { - if (__avail == 1) - *__s = *this->gptr(); - else - traits_type::copy(__s, this->gptr(), __avail); - __s += __avail; - this->gbump(__avail); - __ret += __avail; - __n -= __avail; - } - - // Need to loop in case of short reads (relatively common - // with pipes). - streamsize __len; - for (;;) - { - //__len = _M_file.xsgetn(reinterpret_cast(__s), __n); - __len = fread(reinterpret_cast(__s), 1, - __n, _M_file.file()); - if (__len == -1) - __throw_ios_failure(__N("llstdio_filebuf::xsgetn " - "error reading the file")); - if (__len == 0) - break; - - __n -= __len; - __ret += __len; - if (__n == 0) - break; - - __s += __len; - } - - if (__n == 0) - { - _M_set_buffer(0); - _M_reading = true; - } - else if (__len == 0) - { - // If end of file is reached, set 'uncommitted' - // mode, thus allowing an immediate write without - // an intervening seek. - _M_set_buffer(-1); - _M_reading = false; - } - } - else - __ret += __streambuf_type::xsgetn(__s, __n); - - return __ret; -} - -std::streamsize llstdio_filebuf::xsputn(char_type const* __s, std::streamsize __n) -{ - // Optimization in the always_noconv() case, to be generalized in the - // future: when __n is sufficiently large we write directly instead of - // using the buffer. - streamsize __ret = 0; - const bool __testout = _M_mode & ios_base::out; - if (__check_facet(_M_codecvt).always_noconv() - && __testout && !_M_reading) - { - // Measurement would reveal the best choice. - const streamsize __chunk = 1ul << 10; - streamsize __bufavail = this->epptr() - this->pptr(); - - // Don't mistake 'uncommitted' mode buffered with unbuffered. - if (!_M_writing && _M_buf_size > 1) - __bufavail = _M_buf_size - 1; - - const streamsize __limit = std::min(__chunk, __bufavail); - if (__n >= __limit) - { - const streamsize __buffill = this->pptr() - this->pbase(); - const char* __buf = reinterpret_cast(this->pbase()); - //__ret = _M_file.xsputn_2(__buf, __buffill, - // reinterpret_cast(__s), __n); - if (__buffill) - { - __ret = fwrite(__buf, 1, __buffill, _M_file.file()); - } - if (__ret == __buffill) - { - __ret += fwrite(reinterpret_cast(__s), 1, - __n, _M_file.file()); - } - if (__ret == __buffill + __n) - { - _M_set_buffer(0); - _M_writing = true; - } - if (__ret > __buffill) - __ret -= __buffill; - else - __ret = 0; - } - else - __ret = __streambuf_type::xsputn(__s, __n); - } - else - __ret = __streambuf_type::xsputn(__s, __n); - return __ret; -} - -int llstdio_filebuf::sync() -{ - return (_M_file.sync() == 0 ? 0 : -1); -} -#endif +#if LL_WINDOWS /************** input file stream ********************************/ - -llifstream::llifstream() : _M_filebuf(), -#if LL_WINDOWS - std::istream(&_M_filebuf) {} -#else - std::istream() +llifstream::llifstream() : std::ifstream() { - this->init(&_M_filebuf); } -#endif // explicit -llifstream::llifstream(const std::string& _Filename, - ios_base::openmode _Mode) : _M_filebuf(), -#if LL_WINDOWS - std::istream(&_M_filebuf) -{ - if (_M_filebuf.open(_Filename.c_str(), _Mode | ios_base::in) == 0) - { - _Myios::setstate(ios_base::failbit); - } -} -#else - std::istream() +llifstream::llifstream(const std::string& _Filename, ios_base::openmode _Mode) : + std::ifstream(utf8str_to_utf16str(_Filename), + _Mode | ios_base::in) { - this->init(&_M_filebuf); - this->open(_Filename.c_str(), _Mode | ios_base::in); } -#endif // explicit -llifstream::llifstream(const char* _Filename, - ios_base::openmode _Mode) : _M_filebuf(), -#if LL_WINDOWS - std::istream(&_M_filebuf) -{ - if (_M_filebuf.open(_Filename, _Mode | ios_base::in) == 0) - { - _Myios::setstate(ios_base::failbit); - } -} -#else - std::istream() -{ - this->init(&_M_filebuf); - this->open(_Filename, _Mode | ios_base::in); -} -#endif +llifstream::llifstream(const char* _Filename, ios_base::openmode _Mode) : + std::ifstream(utf8str_to_utf16str(_Filename).c_str(), + _Mode | ios_base::in) - -// explicit -llifstream::llifstream(_Filet *_File, - ios_base::openmode _Mode, size_t _Size) : - _M_filebuf(_File, _Mode, _Size), -#if LL_WINDOWS - std::istream(&_M_filebuf) {} -#else - std::istream() { - this->init(&_M_filebuf); } -#endif -#if !LL_WINDOWS -// explicit -llifstream::llifstream(int __fd, - ios_base::openmode _Mode, size_t _Size) : - _M_filebuf(__fd, _Mode, _Size), - std::istream() +void llifstream::open(const std::string& _Filename, ios_base::openmode _Mode) { - this->init(&_M_filebuf); -} -#endif - -bool llifstream::is_open() const -{ // test if C stream has been opened - return _M_filebuf.is_open(); + std::ifstream::open(utf8str_to_utf16str(_Filename), + _Mode | ios_base::in); } void llifstream::open(const char* _Filename, ios_base::openmode _Mode) -{ // open a C stream with specified mode - if (_M_filebuf.open(_Filename, _Mode | ios_base::in) == 0) -#if LL_WINDOWS - { - _Myios::setstate(ios_base::failbit); - } - else - { - _Myios::clear(); - } -#else - { - this->setstate(ios_base::failbit); - } - else - { - this->clear(); - } -#endif -} - -void llifstream::close() -{ // close the C stream - if (_M_filebuf.close() == 0) - { -#if LL_WINDOWS - _Myios::setstate(ios_base::failbit); -#else - this->setstate(ios_base::failbit); -#endif - } +{ + std::ifstream::open(utf8str_to_utf16str(_Filename).c_str(), + _Mode | ios_base::in); } /************** output file stream ********************************/ -llofstream::llofstream() : _M_filebuf(), -#if LL_WINDOWS - std::ostream(&_M_filebuf) {} -#else - std::ostream() -{ - this->init(&_M_filebuf); -} -#endif - -// explicit -llofstream::llofstream(const std::string& _Filename, - ios_base::openmode _Mode) : _M_filebuf(), -#if LL_WINDOWS - std::ostream(&_M_filebuf) +llofstream::llofstream() : std::ofstream() { - if (_M_filebuf.open(_Filename.c_str(), _Mode | ios_base::out) == 0) - { - _Myios::setstate(ios_base::failbit); - } } -#else - std::ostream() -{ - this->init(&_M_filebuf); - this->open(_Filename.c_str(), _Mode | ios_base::out); -} -#endif // explicit -llofstream::llofstream(const char* _Filename, - ios_base::openmode _Mode) : _M_filebuf(), -#if LL_WINDOWS - std::ostream(&_M_filebuf) -{ - if (_M_filebuf.open(_Filename, _Mode | ios_base::out) == 0) - { - _Myios::setstate(ios_base::failbit); - } -} -#else - std::ostream() +llofstream::llofstream(const std::string& _Filename, ios_base::openmode _Mode) : + std::ofstream(utf8str_to_utf16str(_Filename), + _Mode | ios_base::out) { - this->init(&_M_filebuf); - this->open(_Filename, _Mode | ios_base::out); } -#endif // explicit -llofstream::llofstream(_Filet *_File, - ios_base::openmode _Mode, size_t _Size) : - _M_filebuf(_File, _Mode, _Size), -#if LL_WINDOWS - std::ostream(&_M_filebuf) {} -#else - std::ostream() +llofstream::llofstream(const char* _Filename, ios_base::openmode _Mode) : + std::ofstream(utf8str_to_utf16str(_Filename).c_str(), + _Mode | ios_base::out) { - this->init(&_M_filebuf); } -#endif -#if !LL_WINDOWS -// explicit -llofstream::llofstream(int __fd, - ios_base::openmode _Mode, size_t _Size) : - _M_filebuf(__fd, _Mode, _Size), - std::ostream() +void llofstream::open(const std::string& _Filename, ios_base::openmode _Mode) { - this->init(&_M_filebuf); -} -#endif - -bool llofstream::is_open() const -{ // test if C stream has been opened - return _M_filebuf.is_open(); + std::ofstream::open(utf8str_to_utf16str(_Filename), + _Mode | ios_base::out); } void llofstream::open(const char* _Filename, ios_base::openmode _Mode) -{ // open a C stream with specified mode - if (_M_filebuf.open(_Filename, _Mode | ios_base::out) == 0) -#if LL_WINDOWS - { - _Myios::setstate(ios_base::failbit); - } - else - { - _Myios::clear(); - } -#else - { - this->setstate(ios_base::failbit); - } - else - { - this->clear(); - } -#endif +{ + std::ofstream::open(utf8str_to_utf16str(_Filename).c_str(), + _Mode | ios_base::out); } -void llofstream::close() -{ // close the C stream - if (_M_filebuf.close() == 0) - { -#if LL_WINDOWS - _Myios::setstate(ios_base::failbit); -#else - this->setstate(ios_base::failbit); -#endif - } -} +#endif // LL_WINDOWS /************** helper functions ********************************/ diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index cc990f6abd..f6bcf87287 100644 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -38,15 +38,14 @@ * Attempts to mostly mirror the POSIX style IO functions. */ -typedef FILE LLFILE; +typedef FILE LLFILE; #if LL_WINDOWS // windows version of stat function and stat data structure are called _stat typedef struct _stat llstat; #else typedef struct stat llstat; -#include -#include +#include #endif #ifndef S_ISREG @@ -79,8 +78,8 @@ class LL_COMMON_API LLFile static int mkdir(const std::string& filename, int perms = 0700); static int rmdir(const std::string& filename); - static int remove(const std::string& filename); - static int rename(const std::string& filename,const std::string& newname); + static int remove(const std::string& filename, int supress_error = 0); + static int rename(const std::string& filename,const std::string& newname, int supress_error = 0); static int stat(const std::string& filename,llstat* file_status); static bool isdir(const std::string& filename); static bool isfile(const std::string& filename); @@ -93,135 +92,20 @@ class LL_COMMON_API LLFile static std::string strerr(); }; -/** - * @brief Provides a layer of compatibility for C/POSIX. - * - * This is taken from both the GNU __gnu_cxx::stdio_filebuf extension and - * VC's basic_filebuf implementation. - * This file buffer provides extensions for working with standard C FILE*'s - * and POSIX file descriptors for platforms that support this. -*/ -namespace -{ -#if LL_WINDOWS -//typedef std::filebuf _Myfb; -//Singu note: Wrap around std::filebuf to override the open procedure. -// The client encodes filepaths in UTF-8, however Windows uses UTF-16 encoding natively. -// Need to convert paths to UTF-16 before calling std::filebuf::open. -struct _Myfb : public std::filebuf -{ - _Myfb() : std::filebuf() {} - _Myfb(_Filet* file) : std::filebuf(file) {} - _Myt *open(const char *filename, std::ios_base::openmode mode, int prot = (int)std::ios_base::_Openprot) - { - return std::filebuf::open(utf8str_to_utf16str(filename).c_str(),mode,prot); - } -}; -#else -typedef __gnu_cxx::stdio_filebuf< char > _Myfb; -typedef std::__c_file _Filet; -#endif /* LL_WINDOWS */ -} - -class LL_COMMON_API llstdio_filebuf : public _Myfb -{ -public: - /** - * deferred initialization / destruction - */ - llstdio_filebuf() : _Myfb() {} - virtual ~llstdio_filebuf() {} - - /** - * @param f An open @c FILE*. - * @param mode Same meaning as in a standard filebuf. - * @param size Optimal or preferred size of internal buffer, in chars. - * Defaults to system's @c BUFSIZ. - * - * This constructor associates a file stream buffer with an open - * C @c FILE*. The @c FILE* will not be automatically closed when the - * stdio_filebuf is closed/destroyed. - */ - llstdio_filebuf(_Filet* __f, std::ios_base::openmode __mode, - //size_t __size = static_cast(BUFSIZ)) : - size_t __size = static_cast(1)) : -#if LL_WINDOWS - _Myfb(__f) {} +#if !defined(LL_WINDOWS) +typedef std::ifstream llifstream; +typedef std::ofstream llofstream; #else - _Myfb(__f, __mode, __size) {} -#endif - - /** - * @brief Opens an external file. - * @param s The name of the file. - * @param mode The open mode flags. - * @return @c this on success, NULL on failure - * - * If a file is already open, this function immediately fails. - * Otherwise it tries to open the file named @a s using the flags - * given in @a mode. - */ - //llstdio_filebuf* open(const char *_Filename, - // std::ios_base::openmode _Mode); - - /** - * @param fd An open file descriptor. - * @param mode Same meaning as in a standard filebuf. - * @param size Optimal or preferred size of internal buffer, in chars. - * - * This constructor associates a file stream buffer with an open - * POSIX file descriptor. The file descriptor will be automatically - * closed when the stdio_filebuf is closed/destroyed. - */ -#if !LL_WINDOWS - llstdio_filebuf(int __fd, std::ios_base::openmode __mode, - //size_t __size = static_cast(BUFSIZ)) : - size_t __size = static_cast(1)) : - _Myfb(__fd, __mode, __size) {} -#endif - -// *TODO: Seek the underlying c stream for better cross-platform compatibility? -#if !LL_WINDOWS -protected: - /** underflow() and uflow() functions are called to get the next - * character from the real input source when the buffer is empty. - * Buffered input uses underflow() - */ - /*virtual*/ int_type underflow(); - - /* Convert internal byte sequence to external, char-based - * sequence via codecvt. - */ - bool _convert_to_external(char_type*, std::streamsize); - - /** The overflow() function is called to transfer characters to the - * real output destination when the buffer is full. A call to - * overflow(c) outputs the contents of the buffer plus the - * character c. - * Consume some sequence of the characters in the pending sequence. - */ - /*virtual*/ int_type overflow(int_type __c = traits_type::eof()); - - /** sync() flushes the underlying @c FILE* stream. - */ - /*virtual*/ int sync(); - - std::streamsize xsgetn(char_type*, std::streamsize); - std::streamsize xsputn(char_type const*, std::streamsize); -#endif -}; - /** * @brief Controlling input for files. * * This class supports reading from named files, using the inherited - * functions from std::basic_istream. To control the associated - * sequence, an instance of std::basic_filebuf (or a platform-specific derivative) - * which allows construction using a pre-exisintg file stream buffer. - * We refer to this std::basic_filebuf (or derivative) as @c sb. -*/ -class LL_COMMON_API llifstream : public std::istream + * 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: @@ -247,56 +131,6 @@ class LL_COMMON_API llifstream : public std::istream explicit llifstream(const char* _Filename, ios_base::openmode _Mode = ios_base::in); - /** - * @brief Create a stream using an open c file stream. - * @param File An open @c FILE*. - @param Mode Same meaning as in a standard filebuf. - @param Size Optimal or preferred size of internal buffer, in chars. - Defaults to system's @c BUFSIZ. - */ - explicit llifstream(_Filet *_File, - ios_base::openmode _Mode = ios_base::in, - //size_t _Size = static_cast(BUFSIZ)); - size_t _Size = static_cast(1)); - - /** - * @brief Create a stream using an open file descriptor. - * @param fd An open file descriptor. - @param Mode Same meaning as in a standard filebuf. - @param Size Optimal or preferred size of internal buffer, in chars. - Defaults to system's @c BUFSIZ. - */ -#if !LL_WINDOWS - explicit llifstream(int __fd, - ios_base::openmode _Mode = ios_base::in, - //size_t _Size = static_cast(BUFSIZ)); - size_t _Size = static_cast(1)); -#endif - - /** - * @brief The destructor does nothing. - * - * The file is closed by the filebuf object, not the formatting - * stream. - */ - virtual ~llifstream() {} - - // Members: - /** - * @brief Accessing the underlying buffer. - * @return The current basic_filebuf buffer. - * - * This hides both signatures of std::basic_ios::rdbuf(). - */ - llstdio_filebuf* rdbuf() const - { return const_cast(&_M_filebuf); } - - /** - * @brief Wrapper to test for an open file. - * @return @c rdbuf()->is_open() - */ - bool is_open() const; - /** * @brief Opens an external file. * @param Filename The name of the file. @@ -306,34 +140,21 @@ class LL_COMMON_API llifstream : public std::istream * fails, @c failbit is set in the stream's error state. */ void open(const std::string& _Filename, - ios_base::openmode _Mode = ios_base::in) - { open(_Filename.c_str(), _Mode); } + ios_base::openmode _Mode = ios_base::in); void open(const char* _Filename, ios_base::openmode _Mode = ios_base::in); - - /** - * @brief Close the file. - * - * Calls @c llstdio_filebuf::close(). If that function - * fails, @c failbit is set in the stream's error state. - */ - void close(); - -private: - llstdio_filebuf _M_filebuf; }; /** * @brief Controlling output for files. * - * This class supports writing to named files, using the inherited - * functions from std::basic_ostream. To control the associated - * sequence, an instance of std::basic_filebuf (or a platform-specific derivative) - * which allows construction using a pre-exisintg file stream buffer. - * We refer to this std::basic_filebuf (or derivative) as @c sb. -*/ -class LL_COMMON_API llofstream : public std::ostream + * This class supports writing to named files, using the inherited functions + * from std::ofstream. 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::ofstream. + */ +class LL_COMMON_API llofstream : public std::ofstream { public: // Constructors: @@ -351,64 +172,13 @@ class LL_COMMON_API llofstream : public std::ostream * @param Filename String specifying the filename. * @param Mode Open file in specified mode (see std::ios_base). * - * @c ios_base::out|ios_base::trunc is automatically included in - * @a mode. + * @c ios_base::out is automatically included in @a mode. */ explicit llofstream(const std::string& _Filename, ios_base::openmode _Mode = ios_base::out|ios_base::trunc); explicit llofstream(const char* _Filename, ios_base::openmode _Mode = ios_base::out|ios_base::trunc); - /** - * @brief Create a stream using an open c file stream. - * @param File An open @c FILE*. - @param Mode Same meaning as in a standard filebuf. - @param Size Optimal or preferred size of internal buffer, in chars. - Defaults to system's @c BUFSIZ. - */ - explicit llofstream(_Filet *_File, - ios_base::openmode _Mode = ios_base::out, - //size_t _Size = static_cast(BUFSIZ)); - size_t _Size = static_cast(1)); - - /** - * @brief Create a stream using an open file descriptor. - * @param fd An open file descriptor. - @param Mode Same meaning as in a standard filebuf. - @param Size Optimal or preferred size of internal buffer, in chars. - Defaults to system's @c BUFSIZ. - */ -#if !LL_WINDOWS - explicit llofstream(int __fd, - ios_base::openmode _Mode = ios_base::out, - //size_t _Size = static_cast(BUFSIZ)); - size_t _Size = static_cast(1)); -#endif - - /** - * @brief The destructor does nothing. - * - * The file is closed by the filebuf object, not the formatting - * stream. - */ - virtual ~llofstream() {} - - // Members: - /** - * @brief Accessing the underlying buffer. - * @return The current basic_filebuf buffer. - * - * This hides both signatures of std::basic_ios::rdbuf(). - */ - llstdio_filebuf* rdbuf() const - { return const_cast(&_M_filebuf); } - - /** - * @brief Wrapper to test for an open file. - * @return @c rdbuf()->is_open() - */ - bool is_open() const; - /** * @brief Opens an external file. * @param Filename The name of the file. @@ -418,23 +188,11 @@ class LL_COMMON_API llofstream : public std::ostream * fails, @c failbit is set in the stream's error state. */ void open(const std::string& _Filename, - ios_base::openmode _Mode = ios_base::out|ios_base::trunc) - { open(_Filename.c_str(), _Mode); } + ios_base::openmode _Mode = ios_base::out | ios_base::trunc); void open(const char* _Filename, ios_base::openmode _Mode = ios_base::out|ios_base::trunc); - - /** - * @brief Close the file. - * - * Calls @c llstdio_filebuf::close(). If that function - * fails, @c failbit is set in the stream's error state. - */ - void close(); - -private: - llstdio_filebuf _M_filebuf; }; - +#endif /** * @breif filesize helpers. diff --git a/indra/llcommon/llfindlocale.cpp b/indra/llcommon/llfindlocale.cpp index 505f5c540b..d916209263 100644 --- a/indra/llcommon/llfindlocale.cpp +++ b/indra/llcommon/llfindlocale.cpp @@ -39,7 +39,7 @@ #include #ifdef WIN32 -#include +#include "llwin32headers.h" #include #endif @@ -183,7 +183,7 @@ canonise_fl(FL_Locale *l) { #define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn) struct IDToCode { LANGID id; - char* code; + const char* code; }; static const IDToCode both_to_code[] = { {ML(ENGLISH,US), "en_US.ISO_8859-1"}, diff --git a/indra/llcommon/llfixedbuffer.cpp b/indra/llcommon/llfixedbuffer.cpp index 4b5cdbe288..bd4db8be84 100644 --- a/indra/llcommon/llfixedbuffer.cpp +++ b/indra/llcommon/llfixedbuffer.cpp @@ -30,7 +30,8 @@ LLFixedBuffer::LLFixedBuffer(const U32 max_lines) : LLLineBuffer(), - mMaxLines(max_lines) + mMaxLines(max_lines), + mMutex() { mTimer.reset(); } diff --git a/indra/llcommon/llformat.cpp b/indra/llcommon/llformat.cpp index f9f16006a5..834bcf753a 100644 --- a/indra/llcommon/llformat.cpp +++ b/indra/llcommon/llformat.cpp @@ -36,18 +36,38 @@ #include "llformat.h" #include +#include // common used function with va_list argument // wrapper for vsnprintf to be called from llformatXXX functions. -static void va_format(std::string& out, const char *fmt, va_list va) +static void va_format(std::string& out, const char *fmt, va_list& va) { - char tstr[1024]; /* Flawfinder: ignore */ -#if LL_WINDOWS - _vsnprintf(tstr, 1024, fmt, va); + if (!fmt || !fmt[0]) return; // Don't bother if null or empty c_str + + typedef typename std::vector> vec_t; + static thread_local vec_t charvector(1024); // Evolves into charveleon + #define vsnprintf(va) std::vsnprintf(charvector.data(), charvector.capacity(), fmt, va) +#ifdef LL_WINDOWS // We don't have to copy on windows + #define va2 va #else - vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */ + va_list va2; + va_copy(va2, va); +#endif + const auto smallsize(charvector.capacity()); + const auto size = vsnprintf(va); + if (size < 0) + { + LL_ERRS() << "Encoding failed, code " << size << ". String hint: " << out << '/' << fmt << LL_ENDL; + } + else if (static_cast(size) >= smallsize) // Resize if we need more space + { + charvector.resize(1+size); // Use the String Stone + vsnprintf(va2); + } +#ifndef LL_WINDOWS + va_end(va2); #endif - out.assign(tstr); + out.assign(charvector.data()); } std::string llformat(const char *fmt, ...) diff --git a/indra/llcommon/llformat.h b/indra/llcommon/llformat.h index e2c9cbf7b3..084f07b718 100644 --- a/indra/llcommon/llformat.h +++ b/indra/llcommon/llformat.h @@ -34,6 +34,16 @@ #ifndef LL_LLFORMAT_H #define LL_LLFORMAT_H +#if defined(LL_CLANG) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" +#endif +#include +#include +#if defined(LL_CLANG) +#pragma clang diagnostic pop +#endif + // Use as follows: // LL_INFOS() << llformat("Test:%d (%.2f %.2f)", idx, x, y) << LL_ENDL; // diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp index 94f0c1dee5..a79c470818 100644 --- a/indra/llcommon/llframetimer.cpp +++ b/indra/llcommon/llframetimer.cpp @@ -43,7 +43,7 @@ F64 LLFrameTimer::sTotalSeconds = // Current time in seconds since epoch U64_to_F64(LLFrameTimer::sTotalTime) * USEC_TO_SEC_F64; F64 LLFrameTimer::sFrameTime = 0.0; // Current time in seconds since application start, updated together with LLFrameTimer::sTotalTime. // Updated exactly once per frame: -S32 LLFrameTimer::sFrameCount = 0; // Current frame number (number of frames since application start). +U64 LLFrameTimer::sFrameCount = 0; // Current frame number (number of frames since application start). U64 LLFrameTimer::sPrevTotalTime = LLFrameTimer::sStartTotalTime; // Previous (frame) time in microseconds since epoch, updated once per frame. U64 LLFrameTimer::sFrameDeltaTime = 0; // Microseconds between last two calls to LLFrameTimer::updateFrameTimeAndCount. // Mutex for the above. diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h index 5ebf142478..d0787e9bb7 100644 --- a/indra/llcommon/llframetimer.h +++ b/indra/llcommon/llframetimer.h @@ -51,7 +51,7 @@ class LL_COMMON_API LLFrameTimer // Atomic reads of static variables. // Return the number of seconds since the start of the application. - static F64 getElapsedSeconds(void) + static F64SecondsImplicit getElapsedSeconds(void) { // Loses msec precision after ~4.5 hours... sGlobalMutex.lock(); @@ -84,12 +84,12 @@ class LL_COMMON_API LLFrameTimer } // Return current frame number (the number of frames since application start). - static U32 getFrameCount(void) + static U64 getFrameCount(void) { // sFrameCount is only accessed by the main thread, so no locking is necessary. llassert(is_main_thread()); //sGlobalMutex.lock(); - U32 res = sFrameCount; + U64 res = sFrameCount; //sGlobalMutex.unlock(); return res; } @@ -185,7 +185,7 @@ class LL_COMMON_API LLFrameTimer static F64 sTotalSeconds; // Current frame number (number of frames since application start). - static S32 sFrameCount; + static U64 sFrameCount; static bool sFirstFrameTimerCreated; diff --git a/indra/llcommon/llhandle.h b/indra/llcommon/llhandle.h index 6af5e198d6..92ec54a762 100644 --- a/indra/llcommon/llhandle.h +++ b/indra/llcommon/llhandle.h @@ -28,8 +28,7 @@ #define LLHANDLE_H #include "llpointer.h" -#include -#include +#include /** * Helper object for LLHandle. Don't instantiate these directly, used @@ -86,7 +85,7 @@ class LLHandle LLHandle() : mTombStone(getDefaultTombStone()) {} template - LLHandle(const LLHandle& other, typename boost::enable_if< typename boost::is_convertible >::type* dummy = 0) + LLHandle(const LLHandle& other, typename std::enable_if::value>::type* dummy = nullptr) : mTombStone(other.mTombStone) {} @@ -194,21 +193,20 @@ class LLHandleProvider return mHandle; } -protected: - typedef LLHandle handle_type_t; - LLHandleProvider() - { - // provided here to enforce T deriving from LLHandleProvider - } - template - LLHandle getDerivedHandle(typename boost::enable_if< typename boost::is_convertible >::type* dummy = 0) const + LLHandle getDerivedHandle(typename std::enable_if::value>::type* dummy = nullptr) const { LLHandle downcast_handle; downcast_handle.mTombStone = getHandle().mTombStone; return downcast_handle; } +protected: + typedef LLHandle handle_type_t; + LLHandleProvider() + { + // provided here to enforce T deriving from LLHandleProvider + } private: mutable LLRootHandle mHandle; diff --git a/indra/llcommon/llindexedvector.h b/indra/llcommon/llindexedvector.h index 68c3821802..a1c388aa41 100644 --- a/indra/llcommon/llindexedvector.h +++ b/indra/llcommon/llindexedvector.h @@ -36,8 +36,54 @@ // LLIndexedVector //-------------------------------------------------------- -template -class LLIndexedVector +template +class LLIndexedVector1 +{ +public: + typedef typename std::vector > vec_type_t; + typedef typename vec_type_t::iterator iterator; + typedef typename vec_type_t::const_iterator const_iterator; + typedef typename vec_type_t::reverse_iterator reverse_iterator; + typedef typename vec_type_t::const_reverse_iterator const_reverse_iterator; + typedef typename vec_type_t::size_type size_type; +protected: + std::vector > mVector; + +public: + LLIndexedVector1() { mVector.reserve(BlockSize); } + + const Type& toValue(const_iterator& iter) const { return iter->second; } + Type& toValue(iterator& iter) { return iter->second; } + + iterator begin() { return mVector.begin(); } + const_iterator begin() const { return mVector.begin(); } + iterator end() { return mVector.end(); } + const_iterator end() const { return mVector.end(); } + + reverse_iterator rbegin() { return mVector.rbegin(); } + const_reverse_iterator rbegin() const { return mVector.rbegin(); } + reverse_iterator rend() { return mVector.rend(); } + const_reverse_iterator rend() const { return mVector.rend(); } + + void reset() { mVector.resize(0); } + bool empty() const { return mVector.empty(); } + size_type size() const { return mVector.size(); } + + Type& operator[](const Key& k) + { + return get_val_in_pair_vec(mVector, k); + } + + const_iterator find(const Key& k) const + { + return std::find_if(mVector.begin(), mVector.end(), [&k](const typename vec_type_t::value_type& e) { return e.first == k; }); + } + + using DeletePointer = ::DeletePairedPointer; +}; + +template +class LLIndexedVector2 { public: typedef typename std::vector::iterator iterator; @@ -48,10 +94,16 @@ class LLIndexedVector protected: std::vector mVector; std::map mIndexMap; - +#ifdef DEBUG_LLINDEXEDVECTOR + LLIndexedVector1 mCopy; +#endif + public: - LLIndexedVector() { mVector.reserve(BlockSize); } - + LLIndexedVector2() { mVector.reserve(BlockSize); } + + const Type& toValue(const_iterator& iter) const { return *iter; } + Type& toValue(iterator& iter) { return *iter; } + iterator begin() { return mVector.begin(); } const_iterator begin() const { return mVector.begin(); } iterator end() { return mVector.end(); } @@ -62,19 +114,58 @@ class LLIndexedVector reverse_iterator rend() { return mVector.rend(); } const_reverse_iterator rend() const { return mVector.rend(); } - void reset() { mVector.resize(0); mIndexMap.resize(0); } + void reset() { +#ifdef DEBUG_LLINDEXEDVECTOR + mCopy.reset(); +#endif + mVector.resize(0); + mIndexMap.resize(0); + } bool empty() const { return mVector.empty(); } size_type size() const { return mVector.size(); } - + + void verify() const + { +#ifdef DEBUG_LLINDEXEDVECTOR + llassert_always(mCopy.empty() == empty()); + llassert_always(mCopy.size() == size()); + auto it2 = mCopy.begin(); + int index = 0; + for (auto it1 = begin(); it1 != end(); ++it1) + { + llassert_always(it2->second == &*it1); + ++it2; + ++index; + } + for (auto it = mIndexMap.begin(); it != mIndexMap.end(); ++it) + { + auto i = it->second; + llassert_always((mCopy.begin() + i)->first == it->first); + llassert_always((mCopy.begin() + i)->second == &mVector[i]); + } +#endif + } + Type& operator[](const Key& k) { + verify(); typename std::map::const_iterator iter = mIndexMap.find(k); + if (iter == mIndexMap.end()) { U32 n = mVector.size(); mIndexMap[k] = n; mVector.push_back(Type()); llassert(mVector.size() == mIndexMap.size()); +#ifdef DEBUG_LLINDEXEDVECTOR + mCopy[k] = &mVector[n]; + auto it2 = mCopy.begin(); + for (auto it1 = begin(); it1 != end(); ++it1) + { + it2->second = &(*it1); + ++it2; + } +#endif return mVector[n]; } else @@ -85,7 +176,9 @@ class LLIndexedVector const_iterator find(const Key& k) const { + verify(); typename std::map::const_iterator iter = mIndexMap.find(k); + if(iter == mIndexMap.end()) { return mVector.end(); @@ -95,6 +188,15 @@ class LLIndexedVector return mVector.begin() + iter->second; } } + + using DeletePointer = ::DeletePointer; }; +template +#ifdef DEBUG_LLINDEXEDVECTOR +using LLIndexedVector = LLIndexedVector2; +#else +using LLIndexedVector = LLIndexedVector1; +#endif + #endif diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp index aa2f4eb289..03a4d5bee1 100644 --- a/indra/llcommon/llinitparam.cpp +++ b/indra/llcommon/llinitparam.cpp @@ -67,8 +67,8 @@ namespace LLInitParam mMergeFunc(merge_func), mDeserializeFunc(deserialize_func), mSerializeFunc(serialize_func), + mInspectFunc(inspect_func), mValidationFunc(validation_func), - mInspectFunc(inspect_func), mMinCount(min_count), mMaxCount(max_count), mUserData(NULL) @@ -79,8 +79,8 @@ namespace LLInitParam mMergeFunc(NULL), mDeserializeFunc(NULL), mSerializeFunc(NULL), + mInspectFunc(NULL), mValidationFunc(NULL), - mInspectFunc(NULL), mMinCount(0), mMaxCount(0), mUserData(NULL) @@ -193,7 +193,12 @@ namespace LLInitParam { if (!silent) { - p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str())); + std::string file_name = p.getCurrentFileName(); + if(!file_name.empty()) + { + file_name = "in file: " + file_name; + } + p.parserWarning(llformat("Failed to parse parameter \"%s\" %s", p.getCurrentElementName().c_str(), file_name.c_str())); } return false; } diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index b781baa580..cd58f49ddc 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -30,13 +30,7 @@ #include #include -#ifndef BOOST_FUNCTION_HPP_INCLUDED #include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif -#include -#include -#include #include #include "llerror.h" @@ -118,7 +112,7 @@ namespace LLInitParam // wraps comparison operator between any 2 values of the same type // specialize to handle cases where equality isn't defined well, or at all - template ::value > + template ::value > struct ParamCompare { static bool equals(const T &a, const T &b) @@ -499,7 +493,7 @@ namespace LLInitParam virtual ~Parser(); - template bool readValue(T& param, typename boost::disable_if >::type* dummy = 0) + template bool readValue(T& param, typename std::enable_if::value>::type* dummy = 0) { parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); if (found_it != mParserReadFuncs->end()) @@ -509,8 +503,8 @@ namespace LLInitParam return false; } - - template bool readValue(T& param, typename boost::enable_if >::type* dummy = 0) + + template bool readValue(T& param, typename std::enable_if::value>::type* dummy = nullptr) { parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); if (found_it != mParserReadFuncs->end()) @@ -554,6 +548,7 @@ namespace LLInitParam } virtual std::string getCurrentElementName() = 0; + virtual std::string getCurrentFileName() = 0; virtual void parserWarning(const std::string& message); virtual void parserError(const std::string& message); void setParseSilently(bool silent) { mParseSilently = silent; } @@ -633,7 +628,7 @@ namespace LLInitParam UserData* mUserData; }; - typedef boost::shared_ptr ParamDescriptorPtr; + typedef std::shared_ptr ParamDescriptorPtr; // each derived Block class keeps a static data structure maintaining offsets to various params class LL_COMMON_API BlockDescriptor @@ -1449,7 +1444,7 @@ namespace LLInitParam ++it) { std::string key = it->getValueName(); - name_stack.push_back(std::make_pair(std::string(), true)); + name_stack.emplace_back(std::string(), true); if(key.empty()) // not parsed via name values, write out value directly @@ -1501,7 +1496,7 @@ namespace LLInitParam param_value_t& add() { - mValues.push_back(value_t()); + mValues.emplace_back(value_t()); Param::setProvided(); return mValues.back(); } diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 52db123141..50bf367d1f 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -28,7 +28,7 @@ #ifndef LL_LLINSTANCETRACKER_H #define LL_LLINSTANCETRACKER_H -#include +#include #include #include "llstringtable.h" @@ -89,8 +89,7 @@ template class LLInstanceTracker : public LLInstanceTrackerBase { typedef LLInstanceTracker MyT; - typedef typename std::map InstanceMap; - typedef typename InstanceMap::iterator::difference_type difference_type; + typedef typename boost::unordered_map InstanceMap; struct StaticData: public StaticBase { InstanceMap sMap; @@ -121,10 +120,6 @@ class LLInstanceTracker : public LLInstanceTrackerBase void increment() { mIterator++; } void decrement() { --mIterator; } - difference_type distance_to(instance_iter const& other) const - { - return std::distance(mIterator, other.mIterator); - } bool equal(instance_iter const& other) const { return mIterator == other.mIterator; @@ -166,10 +161,6 @@ class LLInstanceTracker : public LLInstanceTrackerBase void increment() { mIterator++; } void decrement() { --mIterator; } - difference_type distance_to(instance_iter const& other) const - { - return std::distance(mIterator, other.mIterator); - } bool equal(key_iter const& other) const { return mIterator == other.mIterator; diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h index 7544ab1d11..3271a5e33c 100644 --- a/indra/llcommon/llkeythrottle.h +++ b/indra/llcommon/llkeythrottle.h @@ -88,7 +88,7 @@ class LLKeyThrottleImpl } static U64 getFrame() // Return the current frame number { - return (U64) LLFrameTimer::getFrameCount(); + return LLFrameTimer::getFrameCount(); } }; diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp index ce6ac4fac4..88274a91c5 100644 --- a/indra/llcommon/lllivefile.cpp +++ b/indra/llcommon/lllivefile.cpp @@ -88,46 +88,51 @@ LLLiveFile::~LLLiveFile() bool LLLiveFile::Impl::check() { - if (!mForceCheck && mRefreshTimer.getElapsedTimeF32() < mRefreshPeriod) + bool detected_change = false; + // Skip the check if not enough time has elapsed and we're not + // forcing a check of the file + if (mForceCheck || mRefreshTimer.getElapsedTimeF32() >= mRefreshPeriod) { - // Skip the check if not enough time has elapsed and we're not - // forcing a check of the file - return false; - } - mForceCheck = false; - mRefreshTimer.reset(); - - // Stat the file to see if it exists and when it was last modified. - llstat stat_data; - int res = LLFile::stat(mFilename, &stat_data); - - if (res) - { - // Couldn't stat the file, that means it doesn't exist or is - // broken somehow. Clear flags and return. - if (mLastExists) - { - mLastExists = false; - return true; // no longer existing is a change! - } - return false; - } - - // The file exists, decide if we want to load it. - if (mLastExists) - { - // The file existed last time, don't read it if it hasn't changed since - // last time. - if (stat_data.st_mtime <= mLastModTime) - { - return false; - } - } - - // We want to read the file. Update status info for the file. - mLastExists = true; - mLastStatTime = stat_data.st_mtime; - return true; + mForceCheck = false; // force only forces one check + mRefreshTimer.reset(); // don't check again until mRefreshPeriod has passed + + // Stat the file to see if it exists and when it was last modified. + llstat stat_data; + if (LLFile::stat(mFilename, &stat_data)) + { + // Couldn't stat the file, that means it doesn't exist or is + // broken somehow. + if (mLastExists) + { + mLastExists = false; + detected_change = true; // no longer existing is a change! + LL_DEBUGS() << "detected deleted file '" << mFilename << "'" << LL_ENDL; + } + } + else + { + // The file exists + if ( ! mLastExists ) + { + // last check, it did not exist - that counts as a change + LL_DEBUGS() << "detected created file '" << mFilename << "'" << LL_ENDL; + detected_change = true; + } + else if ( stat_data.st_mtime > mLastModTime ) + { + // file modification time is newer than last check + LL_DEBUGS() << "detected updated file '" << mFilename << "'" << LL_ENDL; + detected_change = true; + } + mLastExists = true; + mLastStatTime = stat_data.st_mtime; + } + } + if (detected_change) + { + LL_INFOS() << "detected file change '" << mFilename << "'" << LL_ENDL; + } + return detected_change; } void LLLiveFile::Impl::changed() diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 46775313dd..4855568b5c 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -102,37 +102,37 @@ void LLMD5::update (const uint1 *input, const uint4 input_length) { uint4 input_index, buffer_index; uint4 buffer_space; // how much space is left in buffer - if (finalized){ // so we can't update! + if (mFinalized){ // so we can't update! std::cerr << "LLMD5::update: Can't update a finalized digest!" << std::endl; return; } // Compute number of bytes mod 64 - buffer_index = (unsigned int)((count[0] >> 3) & 0x3F); + buffer_index = (unsigned int)((mCount[0] >> 3) & 0x3F); // Update number of bits - if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) ) - count[1]++; + if ( (mCount[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) ) + mCount[1]++; - count[1] += ((uint4)input_length >> 29); + mCount[1] += ((uint4)input_length >> 29); buffer_space = 64 - buffer_index; // how much space is left in buffer + // now, transform each 64-byte piece of the input, bypassing the buffer + if (input == NULL || input_length == 0){ + std::cerr << "LLMD5::update: Invalid input!" << std::endl; + return; + } + // Transform as many times as possible. if (input_length >= buffer_space) { // ie. we have enough to fill the buffer // fill the rest of the buffer and transform memcpy( /* Flawfinder: ignore */ - buffer + buffer_index, + mBuffer + buffer_index, input, buffer_space); - transform (buffer); - - // now, transform each 64-byte piece of the input, bypassing the buffer - if (input == NULL || input_length == 0){ - std::cerr << "LLMD5::update: Invalid input!" << std::endl; - return; - } + transform (mBuffer); for (input_index = buffer_space; input_index + 63 < input_length; input_index += 64) @@ -145,7 +145,7 @@ void LLMD5::update (const uint1 *input, const uint4 input_length) { // and here we do the buffering: - memcpy(buffer+buffer_index, input+input_index, input_length-input_index); /* Flawfinder: ignore */ + memcpy(mBuffer+buffer_index, input+input_index, input_length-input_index); /* Flawfinder: ignore */ } @@ -200,16 +200,16 @@ void LLMD5::finalize (){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - if (finalized){ + if (mFinalized){ std::cerr << "LLMD5::finalize: Already finalized this digest!" << std::endl; return; } // Save number of bits - encode (bits, count, 8); + encode (bits, mCount, 8); // Pad out to 56 mod 64. - index = (uint4) ((count[0] >> 3) & 0x3f); + index = (uint4) ((mCount[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); update (PADDING, padLen); @@ -217,12 +217,12 @@ void LLMD5::finalize (){ update (bits, 8); // Store state in digest - encode (digest, state, 16); + encode (mDigest, mState, 16); // Zeroize sensitive information - memset (buffer, 0, sizeof(*buffer)); + memset (mBuffer, 0, sizeof(mBuffer)); - finalized=1; + mFinalized=true; } @@ -269,7 +269,7 @@ LLMD5::LLMD5(const unsigned char *s) void LLMD5::raw_digest(unsigned char *s) const { - if (!finalized) + if (!mFinalized) { std::cerr << "LLMD5::raw_digest: Can't get digest if you haven't "<< "finalized the digest!" << std::endl; @@ -277,22 +277,22 @@ void LLMD5::raw_digest(unsigned char *s) const return; } - memcpy(s, digest, 16); /* Flawfinder: ignore */ + memcpy(s, mDigest, 16); /* Flawfinder: ignore */ return; } //Singu extension: the inverse of LLMD5::raw_digest. void LLMD5::clone(unsigned char const* s) { - memcpy(digest, s, 16); - finalized = 1; + memcpy(mDigest, s, 16); + mFinalized = true; } void LLMD5::hex_digest(char *s) const { int i; - if (!finalized) + if (!mFinalized) { std::cerr << "LLMD5::hex_digest: Can't get digest if you haven't "<< "finalized the digest!" <= '0' && c <= '9') ? c - '0' : c - 'a' + 10; byte += nibble << ((1 - j) << 2); } - digest[i] = byte; + mDigest[i] = byte; } - finalized = 1; + mFinalized = 1; } @@ -340,17 +340,17 @@ std::ostream& operator<<(std::ostream &stream, LLMD5 const& context) // PRIVATE METHODS: void LLMD5::init(){ - finalized=0; // we just started! + mFinalized=false; // we just started! // Nothing counted, so count=0 - count[0] = 0; - count[1] = 0; + mCount[0] = 0; + mCount[1] = 0; // Load magic initialization constants. - state[0] = 0x67452301; - state[1] = 0xefcdab89; - state[2] = 0x98badcfe; - state[3] = 0x10325476; + mState[0] = 0x67452301; + mState[1] = 0xefcdab89; + mState[2] = 0x98badcfe; + mState[3] = 0x10325476; } @@ -419,11 +419,11 @@ Rotation is separate from addition to prevent recomputation. // LLMD5 basic transformation. Transforms state based on block. void LLMD5::transform (const U8 block[64]){ - uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + uint4 a = mState[0], b = mState[1], c = mState[2], d = mState[3], x[16]; decode (x, block, 64); - assert(!finalized); // not just a user error, since the method is private + assert(!mFinalized); // not just a user error, since the method is private /* Round 1 */ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ @@ -497,10 +497,10 @@ void LLMD5::transform (const U8 block[64]){ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; + mState[0] += a; + mState[1] += b; + mState[2] += c; + mState[3] += d; // Zeroize sensitive information. memset ( (uint1 *) x, 0, sizeof(x)); diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h index 8909f04d49..30c1838c81 100644 --- a/indra/llcommon/llmd5.h +++ b/indra/llcommon/llmd5.h @@ -102,7 +102,7 @@ class LL_COMMON_API LLMD5 { void update (const std::string& str); void finalize (); - bool isFinalized() const { return finalized; } + bool isFinalized() const { return mFinalized; } // constructors for special circumstances. All these constructors finalize // the MD5 context. @@ -120,19 +120,19 @@ class LL_COMMON_API LLMD5 { void hex_digest(char *string) const; // provide 33-byte array for ascii-hex string friend LL_COMMON_API std::ostream& operator<< (std::ostream&, LLMD5 const& context); - friend LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b) { return std::memcmp(a.digest ,b.digest, 16) == 0; } - friend LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b) { return std::memcmp(a.digest ,b.digest, 16) != 0; } - friend LL_COMMON_API bool operator<(const LLMD5& a, const LLMD5& b) { return std::memcmp(a.digest ,b.digest, 16) < 0; } + friend LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b) { return std::memcmp(a.mDigest ,b.mDigest, 16) == 0; } + friend LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b) { return std::memcmp(a.mDigest,b.mDigest, 16) != 0; } + friend LL_COMMON_API bool operator<(const LLMD5& a, const LLMD5& b) { return std::memcmp(a.mDigest,b.mDigest, 16) < 0; } private: // next, the private data: - uint4 state[4]; - uint4 count[2]; // number of *bits*, mod 2^64 - uint1 buffer[64]; // input buffer - uint1 digest[16]; - uint1 finalized; + uint4 mState[4]; + uint4 mCount[2]; // number of *bits*, mod 2^64 + uint1 mBuffer[64]; // input buffer + uint1 mDigest[16]; + bool mFinalized; // last, the private methods, mostly static: void init (); // called by all constructors diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index aba33abdec..1b73507a14 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -32,7 +32,7 @@ //#endif #if defined(LL_WINDOWS) -//# include +#include "llwin32headerslean.h" # include #elif defined(LL_DARWIN) # include @@ -50,11 +50,11 @@ //static char* LLMemory::reserveMem = 0; -U32 LLMemory::sAvailPhysicalMemInKB = U32_MAX ; -U32 LLMemory::sMaxPhysicalMemInKB = 0; -U32 LLMemory::sAllocatedMemInKB = 0; -U32 LLMemory::sAllocatedPageSizeInKB = 0 ; -U32 LLMemory::sMaxHeapSizeInKB = U32_MAX ; +U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX); +U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0); +U32Kilobytes LLMemory::sAllocatedMemInKB(0); +U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0); +U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX); BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE; #if __DEBUG_PRIVATE_MEM__ @@ -93,45 +93,55 @@ void LLMemory::freeReserve() } //static -void LLMemory::initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure) +void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure) { - sMaxHeapSizeInKB = (U32)(max_heap_size_gb * 1024 * 1024) ; + sMaxHeapSizeInKB = max_heap_size; sEnableMemoryFailurePrevention = prevent_heap_failure ; } //static void LLMemory::updateMemoryInfo() { -#if LL_WINDOWS - HANDLE self = GetCurrentProcess(); - PROCESS_MEMORY_COUNTERS counters; - - if (!GetProcessMemoryInfo(self, &counters, sizeof(counters))) +#if LL_WINDOWS + PROCESS_MEMORY_COUNTERS_EX counters; + counters.cb = sizeof(counters); + + if (!GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*) &counters, sizeof(counters))) { LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL; - return ; + return; } - sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ; - sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ; - - U32 avail_phys, avail_virtual; - LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ; - sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB); + sAllocatedMemInKB = U64Bytes(counters.WorkingSetSize); + sAllocatedPageSizeInKB = (counters.PagefileUsage != 0) ? U64Bytes(counters.PagefileUsage) : U64Bytes(counters.PrivateUsage); - if(sMaxPhysicalMemInKB > sAllocatedMemInKB) + MEMORYSTATUSEX memorystat; + memorystat.dwLength = sizeof(memorystat); + if (!GlobalMemoryStatusEx(&memorystat)) + { + LL_WARNS() << "GlobalMemoryStatusEx failed" << LL_ENDL; + return; + } +#if (defined(_WIN64) || defined(__amd64__) || defined(__x86_64__)) + sMaxPhysicalMemInKB = U64Bytes(memorystat.ullTotalPhys); + sAvailPhysicalMemInKB = U64Bytes(memorystat.ullAvailPhys); +#else + sMaxPhysicalMemInKB = llmin(U32Kilobytes(U64Bytes(memorystat.ullTotalPhys)), sMaxHeapSizeInKB); + if (sMaxPhysicalMemInKB > sAllocatedMemInKB) { - sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ; + sAvailPhysicalMemInKB = U64Bytes(memorystat.ullAvailPhys);; } else { - sAvailPhysicalMemInKB = 0 ; + sAvailPhysicalMemInKB = U32Kilobytes(0); } +#endif + #else //not valid for other systems for now. - sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ; - sMaxPhysicalMemInKB = U32_MAX ; - sAvailPhysicalMemInKB = U32_MAX ; + sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS()); + sMaxPhysicalMemInKB = U64Bytes(U32_MAX); + sAvailPhysicalMemInKB = U64Bytes(U32_MAX); #endif } @@ -156,7 +166,7 @@ void* LLMemory::tryToAlloc(void* address, U32 size) return address ; #else return (void*)0x01 ; //skip checking -#endif +#endif } //static @@ -184,8 +194,8 @@ void LLMemory::logMemoryInfo(BOOL update) //static bool LLMemory::isMemoryPoolLow() { - static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use - const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB + static const U32Megabytes LOW_MEMORY_POOL_THRESHOLD(64); + const static U32Megabytes MAX_SIZE_CHECKED_MEMORY_BLOCK(64); static void* last_reserved_address = NULL ; if(!sEnableMemoryFailurePrevention) @@ -193,32 +203,32 @@ bool LLMemory::isMemoryPoolLow() return false ; //no memory failure prevention. } - if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory + if(sAvailPhysicalMemInKB < (LOW_MEMORY_POOL_THRESHOLD / 4)) //out of physical memory { return true ; } - if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space. + if(sAllocatedPageSizeInKB + (LOW_MEMORY_POOL_THRESHOLD / 4) > sMaxHeapSizeInKB) //out of virtual address space. { return true ; } - bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB || - sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ; + bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD + || sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ; //check the virtual address space fragmentation if(!is_low) { if(!last_reserved_address) { - last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ; } else { - last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ; if(!last_reserved_address) //failed, try once more { - last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ; } } @@ -229,33 +239,33 @@ bool LLMemory::isMemoryPoolLow() } //static -U32 LLMemory::getAvailableMemKB() +U32Kilobytes LLMemory::getAvailableMemKB() { - return sAvailPhysicalMemInKB ; + return sAvailPhysicalMemInKB; } //static -U32 LLMemory::getMaxMemKB() +U32Kilobytes LLMemory::getMaxMemKB() { - return sMaxPhysicalMemInKB ; + return sMaxPhysicalMemInKB; } //static -U32 LLMemory::getAllocatedMemKB() +U32Kilobytes LLMemory::getAllocatedMemKB() { - return sAllocatedMemInKB ; + return sAllocatedMemInKB; } //---------------------------------------------------------------------------- #if defined(LL_WINDOWS) +//static U64 LLMemory::getCurrentRSS() { - HANDLE self = GetCurrentProcess(); PROCESS_MEMORY_COUNTERS counters; - - if (!GetProcessMemoryInfo(self, &counters, sizeof(counters))) + + if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters))) { LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL; return 0; @@ -264,35 +274,7 @@ U64 LLMemory::getCurrentRSS() return counters.WorkingSetSize; } -//static -U32 LLMemory::getWorkingSetSize() -{ - PROCESS_MEMORY_COUNTERS pmc ; - U32 ret = 0 ; - - if (GetProcessMemoryInfo( GetCurrentProcess(), &pmc, sizeof(pmc)) ) - { - ret = pmc.WorkingSetSize ; - } - - return ret ; -} - #elif defined(LL_DARWIN) - -/* - The API used here is not capable of dealing with 64-bit memory sizes, but is available before 10.4. - - Once we start requiring 10.4, we can use the updated API, which looks like this: - - task_basic_info_64_data_t basicInfo; - mach_msg_type_number_t basicInfoCount = TASK_BASIC_INFO_64_COUNT; - if (task_info(mach_task_self(), TASK_BASIC_INFO_64, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS) - - Of course, this doesn't gain us anything unless we start building the viewer as a 64-bit executable, since that's the only way - for our memory allocation to exceed 2^32. -*/ - // if (sysctl(ctl, 2, &page_size, &size, NULL, 0) == -1) // { // LL_WARNS() << "Couldn't get page size" << LL_ENDL; @@ -305,16 +287,15 @@ U32 LLMemory::getWorkingSetSize() U64 LLMemory::getCurrentRSS() { U64 residentSize = 0; - task_basic_info_data_t basicInfo; - mach_msg_type_number_t basicInfoCount = TASK_BASIC_INFO_COUNT; - if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS) + mach_task_basic_info_data_t basicInfo; + mach_msg_type_number_t basicInfoCount = MACH_TASK_BASIC_INFO_COUNT; + if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS) { - residentSize = basicInfo.resident_size; - - // If we ever wanted it, the process virtual size is also available as: - // virtualSize = basicInfo.virtual_size; - -// LL_INFOS() << "resident size is " << residentSize << LL_ENDL; +// residentSize = basicInfo.resident_size; + // Although this method is defined to return the "resident set size," + // in fact what callers want from it is the total virtual memory + // consumed by the application. + residentSize = basicInfo.virtual_size; } else { @@ -324,11 +305,6 @@ U64 LLMemory::getCurrentRSS() return residentSize; } -U32 LLMemory::getWorkingSetSize() -{ - return 0 ; -} - #elif defined(LL_LINUX) U64 LLMemory::getCurrentRSS() @@ -340,7 +316,7 @@ U64 LLMemory::getCurrentRSS() if (fp == NULL) { LL_WARNS() << "couldn't open " << statPath << LL_ENDL; - goto bail; + return rss; } // Eee-yew! See Documentation/filesystems/proc.txt in your @@ -359,49 +335,8 @@ U64 LLMemory::getCurrentRSS() fclose(fp); -bail: return rss; } - -U32 LLMemory::getWorkingSetSize() -{ - return 0 ; -} - -#elif LL_SOLARIS -#include -#include -#include -#define _STRUCTURED_PROC 1 -#include - -U64 LLMemory::getCurrentRSS() -{ - char path [LL_MAX_PATH]; /* Flawfinder: ignore */ - - sprintf(path, "/proc/%d/psinfo", (int)getpid()); - int proc_fd = -1; - if((proc_fd = open(path, O_RDONLY)) == -1){ - LL_WARNS() << "LLmemory::getCurrentRSS() unable to open " << path << ". Returning 0 RSS!" << LL_ENDL; - return 0; - } - psinfo_t proc_psinfo; - if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){ - LL_WARNS() << "LLmemory::getCurrentRSS() Unable to read from " << path << ". Returning 0 RSS!" << LL_ENDL; - close(proc_fd); - return 0; - } - - close(proc_fd); - - return((U64)proc_psinfo.pr_rssize * 1024); -} - -U32 LLMemory::getWorkingSetSize() -{ - return 0 ; -} - #else U64 LLMemory::getCurrentRSS() @@ -409,11 +344,6 @@ U64 LLMemory::getCurrentRSS() return 0; } -U32 LLMemory::getWorkingSetSize() -{ - return 0; -} - #endif //-------------------------------------------------------------------------------------------------- @@ -425,7 +355,7 @@ LLMemTracker* LLMemTracker::sInstance = NULL ; LLMemTracker::LLMemTracker() { - mLastAllocatedMem = LLMemory::getWorkingSetSize() ; + mLastAllocatedMem = LLMemory::getCurrentRSS() ; mCapacity = 128 ; mCurIndex = 0 ; mCounter = 0 ; @@ -478,7 +408,7 @@ void LLMemTracker::track(const char* function, const int line) return ; } - U32 allocated_mem = LLMemory::getWorkingSetSize() ; + U64 allocated_mem = LLMemory::getCurrentRSS() ; LLMutexLock lock(mMutexp) ; diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 48cd2b7b2f..18af01f65c 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -27,7 +27,8 @@ #define LLMEMORY_H #include "linden_common.h" - +#include "llunits.h" +#include "stdtypes.h" #include #include #if !LL_WINDOWS @@ -42,6 +43,21 @@ class LLMutex ; #define LL_CHECK_MEMORY #endif + +#if LL_WINDOWS +#define LL_ALIGN_OF __alignof +#else +#define LL_ALIGN_OF __align_of__ +#endif + +#if LL_WINDOWS +#define LL_DEFAULT_HEAP_ALIGN 8 +#elif LL_DARWIN +#define LL_DEFAULT_HEAP_ALIGN 16 +#elif LL_LINUX +#define LL_DEFAULT_HEAP_ALIGN 8 +#endif + // // ll_assert_aligned seems to only exist to set breakpoints in case an alignment check fails. // However, the implementation was horrible: the test was done using a integer modulo after @@ -102,31 +118,47 @@ template T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) #define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) -inline void* ll_aligned_malloc( size_t size, int align ) -{ -#if defined(LL_WINDOWS) - return _aligned_malloc(size, align); -#else - void* mem = malloc( size + (align - 1) + sizeof(void*) ); - char* aligned = ((char*)mem) + sizeof(void*); - aligned += align - ((uintptr_t)aligned & (align - 1)); - - ((void**)aligned)[-1] = mem; - return aligned; -#endif -} +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ + // for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library + // change preprocessor code to: #if 1 && defined(LL_WINDOWS) -inline void ll_aligned_free( void* ptr ) -{ -#if defined(LL_WINDOWS) - _aligned_free(ptr); +#if 0 && defined(LL_WINDOWS) + void* ll_aligned_malloc_fallback( size_t size, int align ); + void ll_aligned_free_fallback( void* ptr ); +//------------------------------------------------------------------------------------------------ #else - if (ptr) + inline void* ll_aligned_malloc_fallback( size_t size, int align ) { - free( ((void**)ptr)[-1] ); + #if defined(LL_WINDOWS) + return _aligned_malloc(size, align); + #else + char* aligned = NULL; + void* mem = malloc( size + (align - 1) + sizeof(void*) ); + if (mem) + { + aligned = ((char*)mem) + sizeof(void*); + aligned += align - ((uintptr_t)aligned & (align - 1)); + + ((void**)aligned)[-1] = mem; + } + return aligned; + #endif + } + + inline void ll_aligned_free_fallback( void* ptr ) + { + #if defined(LL_WINDOWS) + _aligned_free(ptr); + #else + if (ptr) + { + free( ((void**)ptr)[-1] ); + } + #endif } #endif -} +//------------------------------------------------------------------------------------------------ #if !LL_USE_TCMALLOC inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). @@ -189,7 +221,7 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi #if defined(LL_WINDOWS) return _aligned_malloc(size, 32); #elif defined(LL_DARWIN) - return ll_aligned_malloc( size, 32 ); + return ll_aligned_malloc_fallback( size, 32 ); #else void *rtn; if (LL_LIKELY(0 == posix_memalign(&rtn, 32, size))) @@ -204,12 +236,54 @@ inline void ll_aligned_free_32(void *p) #if defined(LL_WINDOWS) _aligned_free(p); #elif defined(LL_DARWIN) - ll_aligned_free( p ); + ll_aligned_free_fallback( p ); #else free(p); // posix_memalign() is compatible with heap deallocator #endif } +// general purpose dispatch functions that are forced inline so they can compile down to a single call +template +LL_FORCE_INLINE void* ll_aligned_malloc(size_t size) +{ + if (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0) + { + return malloc(size); + } + else if (ALIGNMENT == 16) + { + return ll_aligned_malloc_16(size); + } + else if (ALIGNMENT == 32) + { + return ll_aligned_malloc_32(size); + } + else + { + return ll_aligned_malloc_fallback(size, ALIGNMENT); + } +} + +template +LL_FORCE_INLINE void ll_aligned_free(void* ptr) +{ + if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN) + { + free(ptr); + } + else if (ALIGNMENT == 16) + { + ll_aligned_free_16(ptr); + } + else if (ALIGNMENT == 32) + { + return ll_aligned_free_32(ptr); + } + else + { + return ll_aligned_free_fallback(ptr); + } +} // Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP. // Source and dest must be 16-byte aligned and size must be multiple of 16. @@ -295,24 +369,23 @@ class LL_COMMON_API LLMemory // Return the resident set size of the current process, in bytes. // Return value is zero if not known. static U64 getCurrentRSS(); - static U32 getWorkingSetSize(); static void* tryToAlloc(void* address, U32 size); - static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure); + static void initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure); static void updateMemoryInfo() ; static void logMemoryInfo(BOOL update = FALSE); static bool isMemoryPoolLow(); - static U32 getAvailableMemKB() ; - static U32 getMaxMemKB() ; - static U32 getAllocatedMemKB() ; + static U32Kilobytes getAvailableMemKB() ; + static U32Kilobytes getMaxMemKB() ; + static U32Kilobytes getAllocatedMemKB() ; private: static char* reserveMem; - static U32 sAvailPhysicalMemInKB ; - static U32 sMaxPhysicalMemInKB ; - static U32 sAllocatedMemInKB; - static U32 sAllocatedPageSizeInKB ; + static U32Kilobytes sAvailPhysicalMemInKB ; + static U32Kilobytes sMaxPhysicalMemInKB ; + static U32Kilobytes sAllocatedMemInKB; + static U32Kilobytes sAllocatedPageSizeInKB ; - static U32 sMaxHeapSizeInKB; + static U32Kilobytes sMaxHeapSizeInKB; static BOOL sEnableMemoryFailurePrevention; }; diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h index 59d2841825..074e38fe4c 100644 --- a/indra/llcommon/llmortician.h +++ b/indra/llcommon/llmortician.h @@ -34,6 +34,7 @@ #define LLMORTICIAN_H #include "stdtypes.h" +#include class LL_COMMON_API LLMortician { diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 84087cee3b..b299fd829f 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -109,9 +109,9 @@ #endif -// Check for C++11 support -#if __cplusplus >= 201100L || _MSC_VER >= 1800 -# define LL_CPP11 +// Require C++11 support +#if __cplusplus < 201100L && _MSC_VER < 1800 +#error C++11 support is required to build this project. #endif #if LL_WINDOWS @@ -211,11 +211,7 @@ #endif #endif -#if defined(LL_WINDOWS) || __cplusplus >= 201103L -# define LL_TYPEOF(exp) decltype(exp) -#else -# define LL_TYPEOF(exp) typeof(exp) -#endif +#define LL_TYPEOF(exp) decltype(exp) #define LL_TO_STRING_HELPER(x) #x #define LL_TO_STRING(x) LL_TO_STRING_HELPER(x) @@ -226,8 +222,8 @@ #if LL_WINDOWS #define LL_COMPILE_TIME_MESSAGE(msg) __pragma(message(LL_FILE_LINENO_MSG(msg))) #else -// no way to get gcc 4.2 to print a user-defined diagnostic message only when a macro is used -#define LL_COMPILE_TIME_MESSAGE(msg) +#define PRAGMA_MSG(x) _Pragma(#x) +#define LL_COMPILE_TIME_MESSAGE(msg) PRAGMA_MSG(message msg) #endif #endif // not LL_LINDEN_PREPROCESSOR_H diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h index 0b96f3f7b1..f9b15858f5 100644 --- a/indra/llcommon/llprocesslauncher.h +++ b/indra/llcommon/llprocesslauncher.h @@ -33,9 +33,7 @@ #ifndef LL_LLPROCESSLAUNCHER_H #define LL_LLPROCESSLAUNCHER_H -#if LL_WINDOWS -#include -#endif +#include "llwin32headerslean.h" /* diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 5c731c691f..9754b05359 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -32,9 +32,7 @@ //#include #if LL_WINDOWS -# define WIN32_LEAN_AND_MEAN -# include -# include +# include "llwin32headerslean.h" # define _interlockedbittestandset _renamed_interlockedbittestandset # define _interlockedbittestandreset _renamed_interlockedbittestandreset # include @@ -491,8 +489,7 @@ class LLProcessorInfoWindowsImpl : public LLProcessorInfoImpl unsigned int ids = (unsigned int)cpu_info[0]; setConfig(eMaxID, (S32)ids); - char cpu_vendor[0x20]; - memset(cpu_vendor, 0, sizeof(cpu_vendor)); + char cpu_vendor[0x20] = {0}; *((int*)cpu_vendor) = cpu_info[1]; *((int*)(cpu_vendor+4)) = cpu_info[3]; *((int*)(cpu_vendor+8)) = cpu_info[2]; @@ -558,8 +555,7 @@ class LLProcessorInfoWindowsImpl : public LLProcessorInfoImpl unsigned int ext_ids = cpu_info[0]; setConfig(eMaxExtID, 0); - char cpu_brand_string[0x40]; - memset(cpu_brand_string, 0, sizeof(cpu_brand_string)); + char cpu_brand_string[0x40] = {0}; // Get the information associated with each extended ID. for(unsigned int i=0x80000000; i<=ext_ids; ++i) @@ -640,16 +636,14 @@ class LLProcessorInfoDarwinImpl : public LLProcessorInfoImpl { size_t len = 0; - char cpu_brand_string[0x40]; + char cpu_brand_string[0x40] = {0}; len = sizeof(cpu_brand_string); - memset(cpu_brand_string, 0, len); sysctlbyname("machdep.cpu.brand_string", (void*)cpu_brand_string, &len, NULL, 0); cpu_brand_string[0x3f] = 0; setInfo(eBrandName, cpu_brand_string); - char cpu_vendor[0x20]; + char cpu_vendor[0x20] = {0}; len = sizeof(cpu_vendor); - memset(cpu_vendor, 0, len); sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0); cpu_vendor[0x1f] = 0; setInfo(eVendor, cpu_vendor); @@ -737,8 +731,7 @@ class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); if(cpuinfo_fp) { - char line[MAX_STRING]; - memset(line, 0, MAX_STRING); + char line[MAX_STRING] = {0}; while(fgets(line, MAX_STRING, cpuinfo_fp)) { // /proc/cpuinfo on Linux looks like: @@ -836,8 +829,7 @@ class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); if(cpuinfo) { - char line[MAX_STRING]; - memset(line, 0, MAX_STRING); + char line[MAX_STRING] = {0}; while(fgets(line, MAX_STRING, cpuinfo)) { line[strlen(line)-1] = ' '; @@ -881,7 +873,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) LLProcessorInfo::~LLProcessorInfo() {} -F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } +F64MegahertzImplicit LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); } bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); } bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); } diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index fc2c8dacfb..681dd63144 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -33,6 +33,8 @@ #ifndef LLPROCESSOR_H #define LLPROCESSOR_H +#include "llunits.h" + class LLProcessorInfoImpl; class LL_COMMON_API LLProcessorInfo @@ -41,7 +43,7 @@ class LL_COMMON_API LLProcessorInfo LLProcessorInfo(); ~LLProcessorInfo(); - F64 getCPUFrequency() const; + F64MegahertzImplicit getCPUFrequency() const; bool hasSSE() const; bool hasSSE2() const; bool hasAltivec() const; diff --git a/indra/llcommon/llptrto.h b/indra/llcommon/llptrto.h index 7091d36f6b..e1839beb56 100644 --- a/indra/llcommon/llptrto.h +++ b/indra/llcommon/llptrto.h @@ -31,12 +31,10 @@ #if ! defined(LL_LLPTRTO_H) #define LL_LLPTRTO_H +#include #include "llpointer.h" #include "llrefcount.h" // LLRefCount #include "llthread.h" // LLThreadSafeRefCount -#include -#include -#include /** * LLPtrTo::type is either of two things: @@ -56,14 +54,14 @@ struct LLPtrTo /// specialize for subclasses of LLRefCount template -struct LLPtrTo >::type> +struct LLPtrTo::value>::type> { typedef LLPointer type; }; /// specialize for subclasses of LLThreadSafeRefCount template -struct LLPtrTo >::type> +struct LLPtrTo::value>::type> { typedef LLPointer type; }; @@ -74,7 +72,7 @@ struct LLPtrTo struct LLRemovePointer { - typedef typename boost::remove_pointer::type type; + typedef typename std::remove_pointer::type type; }; /// specialize for LLPointer diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 5ba7b8bd85..8fe3acf542 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -35,7 +35,7 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) : LLThread(name), mThreaded(threaded), - mIdleThread(TRUE), + mIdleThread(true), mNextHandle(0), mStarted(FALSE) { @@ -552,14 +552,15 @@ void LLQueuedThread::run() break; } - mIdleThread = FALSE; + mIdleThread = false; threadedUpdate(); - int res = processNextRequest(); - if (res == 0) + int pending_work = processNextRequest(); + + if (pending_work == 0) { - mIdleThread = TRUE; + mIdleThread = true; ms_sleep(1); } //LLThread::yield(); // thread should yield after each request diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index dda7bf69c1..2da59b8ed5 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -32,8 +32,6 @@ #include #include -#include "llapr.h" - #include "llthread.h" #include "llsimplehash.h" @@ -204,7 +202,7 @@ class LL_COMMON_API LLQueuedThread : public LLThread protected: BOOL mThreaded; // if false, run on main thread and do updates during update() BOOL mStarted; // required when mThreaded is false to call startThread() from update() - LLAtomic32 mIdleThread; // request queue is empty (or we are quitting) and the thread is idle + LLAtomic32 mIdleThread; // request queue is empty (or we are quitting) and the thread is idle typedef std::set request_queue_t; request_queue_t mRequestQueue; diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp index 297c5bb7cf..74f4c046f2 100644 --- a/indra/llcommon/llrefcount.cpp +++ b/indra/llcommon/llrefcount.cpp @@ -31,15 +31,15 @@ #if LL_REF_COUNT_DEBUG #include "llthread.h" -#include "llapr.h" #endif -LLRefCount::LLRefCount(const LLRefCount& other) -: mRef(0) -{ +LLRefCount::LLRefCount(const LLRefCount& other) : #if LL_REF_COUNT_DEBUG - mCrashAtUnlock = FALSE ; + mMutex(), + mCrashAtUnlock(FALSE), #endif + mRef(0) +{ } LLRefCount& LLRefCount::operator=(const LLRefCount&) @@ -49,11 +49,12 @@ LLRefCount& LLRefCount::operator=(const LLRefCount&) } LLRefCount::LLRefCount() : - mRef(0) -{ #if LL_REF_COUNT_DEBUG - mCrashAtUnlock = FALSE ; + mMutex(), + mCrashAtUnlock(FALSE), #endif + mRef(0) +{ } LLRefCount::~LLRefCount() diff --git a/indra/llcommon/llrun.cpp b/indra/llcommon/llrun.cpp index e2f69ff13d..3edfef429e 100644 --- a/indra/llcommon/llrun.cpp +++ b/indra/llcommon/llrun.cpp @@ -53,7 +53,7 @@ LLRunner::~LLRunner() mRunEvery.clear(); } -S32 LLRunner::run() +size_t LLRunner::run() { // We collect all of the runnables which should be run. Since the // runnables are allowed to adjust the run list, we need to copy diff --git a/indra/llcommon/llrun.h b/indra/llcommon/llrun.h index 1701800b14..8cc524ce74 100644 --- a/indra/llcommon/llrun.h +++ b/indra/llcommon/llrun.h @@ -56,7 +56,7 @@ class LL_COMMON_API LLRunner /** * @brief The pointer to a runnable. */ - typedef boost::shared_ptr run_ptr_t; + typedef std::shared_ptr run_ptr_t; /** * @brief The handle for use in the API. @@ -93,7 +93,7 @@ class LL_COMMON_API LLRunner * * @return Returns the number of runnables run. */ - S32 run(); + size_t run(); /** * @brief Add a runnable to the run list. diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index d8bbb3a74f..73a0ab3e71 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -31,7 +31,6 @@ #include "llsd.h" #include "llerror.h" -#include "../llmath/llmath.h" #include "llformat.h" #include "llsdserialize.h" #include "stringize.h" @@ -127,11 +126,12 @@ class LLSD::Impl virtual Date asDate() const { return LLDate(); } virtual URI asURI() const { return LLURI(); } virtual const Binary& asBinary() const { static const std::vector empty; return empty; } - - virtual const String& asStringRef() const { static const std::string empty; return empty; } + virtual const String& asStringRef() const { static const std::string empty; return empty; } + virtual bool has(const String&) const { return false; } virtual LLSD get(const String&) const { return LLSD(); } + virtual LLSD getKeys() const { return LLSD::emptyArray(); } virtual void erase(const String&) { } virtual const LLSD& ref(const String&) const{ return undef(); } @@ -140,10 +140,14 @@ class LLSD::Impl virtual void erase(Integer) { } virtual const LLSD& ref(Integer) const { return undef(); } - virtual LLSD::map_const_iterator beginMap() const { return endMap(); } - virtual LLSD::map_const_iterator endMap() const { static const std::map empty; return empty.end(); } - virtual LLSD::array_const_iterator beginArray() const { return endArray(); } - virtual LLSD::array_const_iterator endArray() const { static const std::vector empty; return empty.end(); } + virtual const std::map& map() const { static const std::map empty; return empty; } + virtual std::map& map() { static std::map empty; return empty; } + LLSD::map_const_iterator beginMap() const { return map().begin(); } + LLSD::map_const_iterator endMap() const { return map().end(); } + virtual const std::vector& array() const { static const std::vector empty; return empty; } + virtual std::vector& array() { static std::vector empty; return empty; } + LLSD::array_const_iterator beginArray() const { return array().begin(); } + LLSD::array_const_iterator endArray() const { return array().end(); } virtual void dumpStats() const; virtual void calcStats(S32 type_counts[], S32 share_counts[]) const; @@ -183,10 +187,11 @@ namespace public: ImplBase(DataRef value) : mValue(value) { } - virtual LLSD::Type type() const { return T; } + LLSD::Type type() const override { return T; } using LLSD::Impl::assign; // Unhiding base class virtuals... - virtual void assign(LLSD::Impl*& var, DataRef value) { + void assign(LLSD::Impl*& var, DataRef value) override + { if (shared()) { Impl::assign(var, value); @@ -199,16 +204,16 @@ namespace }; - class ImplBoolean + class ImplBoolean final : public ImplBase { public: ImplBoolean(LLSD::Boolean v) : Base(v) { } - virtual LLSD::Boolean asBoolean() const { return mValue; } - virtual LLSD::Integer asInteger() const { return mValue ? 1 : 0; } - virtual LLSD::Real asReal() const { return mValue ? 1 : 0; } - virtual LLSD::String asString() const; + LLSD::Boolean asBoolean() const override { return mValue; } + LLSD::Integer asInteger() const override { return mValue ? 1 : 0; } + LLSD::Real asReal() const override { return mValue ? 1 : 0; } + LLSD::String asString() const override; }; LLSD::String ImplBoolean::asString() const @@ -220,59 +225,59 @@ namespace { return mValue ? "true" : ""; } - class ImplInteger + class ImplInteger final : public ImplBase { public: ImplInteger(LLSD::Integer v) : Base(v) { } - virtual LLSD::Boolean asBoolean() const { return mValue != 0; } - virtual LLSD::Integer asInteger() const { return mValue; } - virtual LLSD::Real asReal() const { return mValue; } - virtual LLSD::String asString() const; + LLSD::Boolean asBoolean() const override { return mValue != 0; } + LLSD::Integer asInteger() const override { return mValue; } + LLSD::Real asReal() const override { return mValue; } + LLSD::String asString() const override; }; LLSD::String ImplInteger::asString() const { return llformat("%d", mValue); } - class ImplReal + class ImplReal final : public ImplBase { public: ImplReal(LLSD::Real v) : Base(v) { } - virtual LLSD::Boolean asBoolean() const; - virtual LLSD::Integer asInteger() const; - virtual LLSD::Real asReal() const { return mValue; } - virtual LLSD::String asString() const; + LLSD::Boolean asBoolean() const override; + LLSD::Integer asInteger() const override; + LLSD::Real asReal() const override { return mValue; } + LLSD::String asString() const override; }; LLSD::Boolean ImplReal::asBoolean() const - { return !llisnan(mValue) && mValue != 0.0; } + { return !std::isnan(mValue) && mValue != 0.0; } LLSD::Integer ImplReal::asInteger() const - { return !llisnan(mValue) ? (LLSD::Integer)mValue : 0; } + { return !std::isnan(mValue) ? (LLSD::Integer)mValue : 0; } LLSD::String ImplReal::asString() const { return llformat("%lg", mValue); } - class ImplString + class ImplString final : public ImplBase { public: ImplString(const LLSD::String& v) : Base(v) { } - virtual LLSD::Boolean asBoolean() const { return !mValue.empty(); } - virtual LLSD::Integer asInteger() const; - virtual LLSD::Real asReal() const; - virtual LLSD::String asString() const { return mValue; } - virtual LLSD::UUID asUUID() const { return LLUUID(mValue); } - virtual LLSD::Date asDate() const { return LLDate(mValue); } - virtual LLSD::URI asURI() const { return LLURI(mValue); } - virtual int size() const { return mValue.size(); } - virtual const LLSD::String& asStringRef() const { return mValue; } + LLSD::Boolean asBoolean() const override { return !mValue.empty(); } + LLSD::Integer asInteger() const override; + LLSD::Real asReal() const override; + LLSD::String asString() const override { return mValue; } + LLSD::UUID asUUID() const override { return LLUUID(mValue); } + LLSD::Date asDate() const override { return LLDate(mValue); } + LLSD::URI asURI() const override { return LLURI(mValue); } + int size() const override { return mValue.size(); } + const LLSD::String& asStringRef() const override { return mValue; } }; LLSD::Integer ImplString::asInteger() const @@ -302,18 +307,18 @@ namespace } - class ImplUUID + class ImplUUID final : public ImplBase { public: ImplUUID(const LLSD::UUID& v) : Base(v) { } - virtual LLSD::String asString() const{ return mValue.asString(); } - virtual LLSD::UUID asUUID() const { return mValue; } + LLSD::String asString() const override { return mValue.asString(); } + LLSD::UUID asUUID() const override { return mValue; } }; - class ImplDate + class ImplDate final : public ImplBase { public: @@ -321,41 +326,42 @@ namespace : ImplBase(v) { } - virtual LLSD::Integer asInteger() const + LLSD::Integer asInteger() const override { return (LLSD::Integer)(mValue.secondsSinceEpoch()); } - virtual LLSD::Real asReal() const + LLSD::Real asReal() const override { return mValue.secondsSinceEpoch(); } - virtual LLSD::String asString() const{ return mValue.asString(); } - virtual LLSD::Date asDate() const { return mValue; } + + LLSD::String asString() const override { return mValue.asString(); } + LLSD::Date asDate() const override { return mValue; } }; - class ImplURI + class ImplURI final : public ImplBase { public: ImplURI(const LLSD::URI& v) : Base(v) { } - virtual LLSD::String asString() const{ return mValue.asString(); } - virtual LLSD::URI asURI() const { return mValue; } + LLSD::String asString() const override { return mValue.asString(); } + LLSD::URI asURI() const override { return mValue; } }; - class ImplBinary + class ImplBinary final : public ImplBase { public: ImplBinary(const LLSD::Binary& v) : Base(v) { } - virtual const LLSD::Binary& asBinary() const{ return mValue; } + const LLSD::Binary& asBinary() const override { return mValue; } }; - class ImplMap : public LLSD::Impl + class ImplMap final : public LLSD::Impl { private: typedef std::map DataMap; @@ -368,32 +374,31 @@ namespace public: ImplMap() { } - virtual ImplMap& makeMap(LLSD::Impl*&); + ImplMap& makeMap(LLSD::Impl*&) override; - virtual LLSD::Type type() const { return LLSD::TypeMap; } + LLSD::Type type() const override { return LLSD::TypeMap; } - virtual LLSD::Boolean asBoolean() const { return !mData.empty(); } + LLSD::Boolean asBoolean() const override { return !mData.empty(); } - virtual bool has(const LLSD::String&) const; + bool has(const LLSD::String&) const override; using LLSD::Impl::get; // Unhiding get(LLSD::Integer) using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer) using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer) - virtual LLSD get(const LLSD::String&) const; + LLSD get(const LLSD::String&) const override; + LLSD getKeys() const override; void insert(const LLSD::String& k, const LLSD& v); - virtual void erase(const LLSD::String&); + void erase(const LLSD::String&) override; LLSD& ref(const LLSD::String&); - virtual const LLSD& ref(const LLSD::String&) const; + const LLSD& ref(const LLSD::String&) const override; - virtual int size() const { return mData.size(); } + int size() const override { return mData.size(); } - LLSD::map_iterator beginMap() { return mData.begin(); } - LLSD::map_iterator endMap() { return mData.end(); } - virtual LLSD::map_const_iterator beginMap() const { return mData.begin(); } - virtual LLSD::map_const_iterator endMap() const { return mData.end(); } + DataMap& map() final override { return mData; } + const DataMap& map() const final override { return mData; } - virtual void dumpStats() const; - virtual void calcStats(S32 type_counts[], S32 share_counts[]) const; + void dumpStats() const override; + void calcStats(S32 type_counts[], S32 share_counts[]) const override; }; ImplMap& ImplMap::makeMap(LLSD::Impl*& var) @@ -422,6 +427,18 @@ namespace return (i != mData.end()) ? i->second : LLSD(); } + LLSD ImplMap::getKeys() const + { + LLSD keys = LLSD::emptyArray(); + DataMap::const_iterator iter = mData.begin(); + while (iter != mData.end()) + { + keys.append((*iter).first); + iter++; + } + return keys; + } + void ImplMap::insert(const LLSD::String& k, const LLSD& v) { mData.insert(DataMap::value_type(k, v)); @@ -468,7 +485,7 @@ namespace { //std::cout << " " << (*iter).first << ": " << (*iter).second << std::endl; Impl::calcStats((*iter).second, type_counts, share_counts); - iter++; + ++iter; } // Add in the values for this map @@ -476,7 +493,7 @@ namespace } - class ImplArray : public LLSD::Impl + class ImplArray final : public LLSD::Impl { private: typedef std::vector DataVector; @@ -489,32 +506,28 @@ namespace public: ImplArray() { } - virtual ImplArray& makeArray(Impl*&); + ImplArray& makeArray(Impl*&) override; - virtual LLSD::Type type() const { return LLSD::TypeArray; } + LLSD::Type type() const override { return LLSD::TypeArray; } - virtual LLSD::Boolean asBoolean() const { return !mData.empty(); } + LLSD::Boolean asBoolean() const override { return !mData.empty(); } using LLSD::Impl::get; // Unhiding get(LLSD::String) using LLSD::Impl::erase; // Unhiding erase(LLSD::String) using LLSD::Impl::ref; // Unhiding ref(LLSD::String) - virtual int size() const; - virtual LLSD get(LLSD::Integer) const; + int size() const override; + LLSD get(LLSD::Integer) const override; void set(LLSD::Integer, const LLSD&); void insert(LLSD::Integer, const LLSD&); - void append(const LLSD&); - virtual void erase(LLSD::Integer); + LLSD& append(const LLSD&); + void erase(LLSD::Integer) override; LLSD& ref(LLSD::Integer); - virtual const LLSD& ref(LLSD::Integer) const; + const LLSD& ref(LLSD::Integer) const override; - LLSD::array_iterator beginArray() { return mData.begin(); } - LLSD::array_iterator endArray() { return mData.end(); } - LLSD::reverse_array_iterator rbeginArray() { return mData.rbegin(); } - LLSD::reverse_array_iterator rendArray() { return mData.rend(); } - virtual LLSD::array_const_iterator beginArray() const { return mData.begin(); } - virtual LLSD::array_const_iterator endArray() const { return mData.end(); } + DataVector& array() final override { return mData; } + const DataVector& array() const final override { return mData; } - virtual void calcStats(S32 type_counts[], S32 share_counts[]) const; + void calcStats(S32 type_counts[], S32 share_counts[]) const override; }; ImplArray& ImplArray::makeArray(Impl*& var) @@ -570,9 +583,10 @@ namespace mData.insert(mData.begin() + index, v); } - void ImplArray::append(const LLSD& v) + LLSD& ImplArray::append(const LLSD& v) { mData.push_back(v); + return mData.back(); } void ImplArray::erase(LLSD::Integer i) @@ -617,7 +631,7 @@ namespace while (iter != endArray()) { // Add values for all items held in the array Impl::calcStats((*iter), type_counts, share_counts); - iter++; + ++iter; } // Add in the values for this array @@ -689,7 +703,7 @@ void LLSD::Impl::assign(Impl*& var, const Impl* other) void LLSD::Impl::assignUndefined(Impl*& var) { - reset(var, 0); + reset(var, nullptr); } void LLSD::Impl::assign(Impl*& var, LLSD::Boolean v) @@ -741,11 +755,9 @@ const LLSD& LLSD::Impl::undef() void LLSD::Impl::dumpStats() const { - S32 type_counts[LLSD::TypeLLSDNumTypes + 1]; - memset(&type_counts, 0, sizeof(type_counts)); + S32 type_counts[LLSD::TypeLLSDNumTypes + 1] = {0}; - S32 share_counts[LLSD::TypeLLSDNumTypes + 1]; - memset(&share_counts, 0, sizeof(share_counts)); + S32 share_counts[LLSD::TypeLLSDNumTypes + 1] = {0}; // Add info from all the values this object has calcStats(type_counts, share_counts); @@ -767,7 +779,7 @@ void LLSD::Impl::calcStats(S32 type_counts[], S32 share_counts[]) const S32 tp = S32(type()); if (0 <= tp && tp < LLSD::TypeLLSDNumTypes) { - type_counts[tp]++; + type_counts[tp]++; if (shared()) { share_counts[tp]++; @@ -801,10 +813,10 @@ namespace } -LLSD::LLSD() : impl(0) { ALLOC_LLSD_OBJECT; } -LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::reset(impl, 0); } +LLSD::LLSD() : impl(nullptr) { ALLOC_LLSD_OBJECT; } +LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::reset(impl, nullptr); } -LLSD::LLSD(const LLSD& other) : impl(0) { ALLOC_LLSD_OBJECT; assign(other); } +LLSD::LLSD(const LLSD& other) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(other); } void LLSD::assign(const LLSD& other) { Impl::assign(impl, other.impl); } @@ -813,17 +825,17 @@ void LLSD::clear() { Impl::assignUndefined(impl); } LLSD::Type LLSD::type() const { return safe(impl).type(); } // Scalar Constructors -LLSD::LLSD(Boolean v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } -LLSD::LLSD(Integer v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } -LLSD::LLSD(Real v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } -LLSD::LLSD(const UUID& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } -LLSD::LLSD(const String& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } -LLSD::LLSD(const Date& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } -LLSD::LLSD(const URI& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } -LLSD::LLSD(const Binary& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } +LLSD::LLSD(Boolean v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); } +LLSD::LLSD(Integer v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); } +LLSD::LLSD(Real v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); } +LLSD::LLSD(const UUID& v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); } +LLSD::LLSD(const String& v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); } +LLSD::LLSD(const Date& v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); } +LLSD::LLSD(const URI& v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); } +LLSD::LLSD(const Binary& v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); } // Convenience Constructors -LLSD::LLSD(F32 v) : impl(0) { ALLOC_LLSD_OBJECT; assign((Real)v); } +LLSD::LLSD(F32 v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign((Real)v); } // Scalar Assignment void LLSD::assign(Boolean v) { safe(impl).assign(impl, v); } @@ -848,7 +860,7 @@ const LLSD::Binary& LLSD::asBinary() const { return safe(impl).asBinary(); } const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef(); } // const char * helpers -LLSD::LLSD(const char* v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } +LLSD::LLSD(const char* v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); } void LLSD::assign(const char* v) { if(v) assign(std::string(v)); @@ -865,6 +877,7 @@ LLSD LLSD::emptyMap() bool LLSD::has(const String& k) const { return safe(impl).has(k); } LLSD LLSD::get(const String& k) const { return safe(impl).get(k); } +LLSD LLSD::getKeys() const { return safe(impl).getKeys(); } void LLSD::insert(const String& k, const LLSD& v) { makeMap(impl).insert(k, v); } LLSD& LLSD::with(const String& k, const LLSD& v) @@ -898,7 +911,7 @@ LLSD& LLSD::with(Integer i, const LLSD& v) makeArray(impl).insert(i, v); return *this; } -void LLSD::append(const LLSD& v) { makeArray(impl).append(v); } +LLSD& LLSD::append(const LLSD& v) { return makeArray(impl).append(v); } void LLSD::erase(Integer i) { makeArray(impl).erase(i); } LLSD& LLSD::operator[](Integer i) @@ -914,7 +927,7 @@ static const char *llsd_dump(const LLSD &llsd, bool useXMLFormat) // sStorage will point to the result of the last call. This will actually // be one leak, but since this is used only when running under the // debugger, it should not be an issue. - static char *sStorage = NULL; + static char *sStorage = nullptr; delete[] sStorage; std::string out_string; { @@ -925,7 +938,7 @@ static const char *llsd_dump(const LLSD &llsd, bool useXMLFormat) out << LLSDNotationStreamer(llsd); out_string = out.str(); } - int len = out_string.length(); + size_t len = out_string.length(); sStorage = new char[len + 1]; memcpy(sStorage, out_string.c_str(), len); sStorage[len] = '\0'; @@ -944,18 +957,24 @@ const char *LLSD::dump(const LLSD &llsd) return llsd_dump(llsd, false); } -LLSD::map_iterator LLSD::beginMap() { return makeMap(impl).beginMap(); } -LLSD::map_iterator LLSD::endMap() { return makeMap(impl).endMap(); } -LLSD::map_const_iterator LLSD::beginMap() const { return safe(impl).beginMap(); } -LLSD::map_const_iterator LLSD::endMap() const { return safe(impl).endMap(); } +std::map& LLSD::map() { return makeMap(impl).map(); } +const std::map& LLSD::map() const { return safe(impl).map(); } + +LLSD::map_iterator LLSD::beginMap() { return map().begin(); } +LLSD::map_iterator LLSD::endMap() { return map().end(); } +LLSD::map_const_iterator LLSD::beginMap() const { return map().cbegin(); } +LLSD::map_const_iterator LLSD::endMap() const { return map().cend(); } + +std::vector& LLSD::array() { return makeArray(impl).array(); } +const std::vector& LLSD::array() const { return safe(impl).array(); } -LLSD::array_iterator LLSD::beginArray() { return makeArray(impl).beginArray(); } -LLSD::array_iterator LLSD::endArray() { return makeArray(impl).endArray(); } -LLSD::array_const_iterator LLSD::beginArray() const{ return safe(impl).beginArray(); } -LLSD::array_const_iterator LLSD::endArray() const { return safe(impl).endArray(); } +LLSD::array_iterator LLSD::beginArray() { return array().begin(); } +LLSD::array_iterator LLSD::endArray() { return array().end(); } +LLSD::array_const_iterator LLSD::beginArray() const{ return array().cbegin(); } +LLSD::array_const_iterator LLSD::endArray() const { return array().cend(); } -LLSD::reverse_array_iterator LLSD::rbeginArray() { return makeArray(impl).rbeginArray(); } -LLSD::reverse_array_iterator LLSD::rendArray() { return makeArray(impl).rendArray(); } +LLSD::reverse_array_iterator LLSD::rbeginArray() { return array().rbegin(); } +LLSD::reverse_array_iterator LLSD::rendArray() { return array().rend(); } namespace llsd { diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index 6e71a717e9..1d8950bfc0 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -287,6 +287,7 @@ class LL_COMMON_API LLSD bool has(const String&) const; LLSD get(const String&) const; + LLSD getKeys() const; // Return an LLSD array with keys as strings void insert(const String&, const LLSD&); void erase(const String&); LLSD& with(const String&, const LLSD&); @@ -304,7 +305,7 @@ class LL_COMMON_API LLSD LLSD get(Integer) const; void set(Integer, const LLSD&); void insert(Integer, const LLSD&); - void append(const LLSD&); + LLSD& append(const LLSD&); void erase(Integer); LLSD& with(Integer, const LLSD&); @@ -319,6 +320,8 @@ class LL_COMMON_API LLSD typedef std::map::iterator map_iterator; typedef std::map::const_iterator map_const_iterator; + std::map& map(); + const std::map& map() const; map_iterator beginMap(); map_iterator endMap(); map_const_iterator beginMap() const; @@ -328,6 +331,8 @@ class LL_COMMON_API LLSD typedef std::vector::const_iterator array_const_iterator; typedef std::vector::reverse_iterator reverse_array_iterator; + std::vector& array(); + const std::vector& array() const; array_iterator beginArray(); array_iterator endArray(); array_const_iterator beginArray() const; @@ -384,9 +389,9 @@ class LL_COMMON_API LLSD using an arbitrary pointer or scalar type to std::string. */ //@{ - LLSD(const void*); ///< construct from aribrary pointers - void assign(const void*); ///< assign from arbitrary pointers - LLSD& operator=(const void*); ///< assign from arbitrary pointers + LLSD(const void*) = delete; ///< construct from aribrary pointers + void assign(const void*) = delete; ///< assign from arbitrary pointers + LLSD& operator=(const void*) = delete; ///< assign from arbitrary pointers bool has(Integer) const; ///< has() only works for Maps //@} diff --git a/indra/llcommon/llsdjson.cpp b/indra/llcommon/llsdjson.cpp new file mode 100644 index 0000000000..a31128dd83 --- /dev/null +++ b/indra/llcommon/llsdjson.cpp @@ -0,0 +1,137 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +/** + * @file llsdjson.cpp + * @brief LLSD flexible data system + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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$ + */ + +// Must turn on conditional declarations in header file so definitions end up +// with proper linkage. +#define LLSD_DEBUG_INFO +#include "linden_common.h" + +#include "llsdjson.h" + +#include "llerror.h" + + +//========================================================================= +LLSD LlsdFromJson(const nlohmann::json &val) +{ + LLSD result; + + switch (val.type()) + { + default: + case nlohmann::json::value_t::null: + break; + case nlohmann::json::value_t::number_integer: + result = LLSD(val.get()); + break; + case nlohmann::json::value_t::number_unsigned: + result = LLSD(val.get()); + break; + case nlohmann::json::value_t::number_float: + result = LLSD(val.get()); + break; + case nlohmann::json::value_t::string: + result = LLSD(val.get()); + break; + case nlohmann::json::value_t::boolean: + result = LLSD(val.get()); + break; + case nlohmann::json::value_t::array: + result = LLSD::emptyArray(); + for (const auto &element : val) + { + result.append(LlsdFromJson(element)); + } + break; + case nlohmann::json::value_t::object: + result = LLSD::emptyMap(); + for (auto it = val.cbegin(); it != val.cend(); ++it) + { + result[it.key()] = LlsdFromJson(it.value()); + } + break; + } + return result; +} + +LLSD LlsdFromJsonString(const std::string& str) +{ + auto json = nlohmann::json::parse(str, nullptr, false); + if (json.is_discarded()) + { + LL_WARNS() << "Cannot parse invalid json string:\n" << str << LL_ENDL; + return LLSD(); + } + return LlsdFromJson(json); +} + +//========================================================================= +nlohmann::json LlsdToJson(const LLSD &val) +{ + nlohmann::json result; + + switch (val.type()) + { + case LLSD::TypeUndefined: + result = nullptr; + break; + case LLSD::TypeBoolean: + result = val.asBoolean(); + break; + case LLSD::TypeInteger: + result = val.asInteger(); + break; + case LLSD::TypeReal: + result = val.asReal(); + break; + case LLSD::TypeURI: + case LLSD::TypeDate: + case LLSD::TypeUUID: + case LLSD::TypeString: + result = val.asString(); + break; + case LLSD::TypeMap: + for (LLSD::map_const_iterator it = val.beginMap(); it != val.endMap(); ++it) + { + result[it->first] = LlsdToJson(it->second); + } + break; + case LLSD::TypeArray: + for (auto const& entry : val.array()) + { + result.push_back(LlsdToJson(entry)); + } + break; + case LLSD::TypeBinary: + default: + LL_ERRS("LlsdToJson") << "Unsupported conversion to JSON from LLSD type (" << val.type() << ")." << LL_ENDL; + break; + } + + return result; +} diff --git a/indra/llcommon/llsdjson.h b/indra/llcommon/llsdjson.h new file mode 100644 index 0000000000..5c45f697ee --- /dev/null +++ b/indra/llcommon/llsdjson.h @@ -0,0 +1,78 @@ +/** + * @file llsdjson.cpp + * @brief LLSD flexible data system + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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_LLSDJSON_H +#define LL_LLSDJSON_H + +#include +#include +#include + +#include "stdtypes.h" + +#include "llsd.h" +#include + +/// Convert a parsed JSON structure into LLSD maintaining member names and +/// array indexes. +/// JSON/JavaScript types are converted as follows: +/// +/// JSON Type | LLSD Type +/// --------------+-------------- +/// null | undefined +/// integer | LLSD::Integer +/// unsigned | LLSD::Integer +/// real/numeric | LLSD::Real +/// string | LLSD::String +/// boolean | LLSD::Boolean +/// array | LLSD::Array +/// object | LLSD::Map +/// +/// For maps and arrays child entries will be converted and added to the structure. +/// Order is preserved for an array but not for objects. +LLSD LlsdFromJson(const nlohmann::json &val); +LLSD LlsdFromJsonString(const std::string& body); + +/// Convert an LLSD object into Parsed JSON object maintaining member names and +/// array indexs. +/// +/// Types are converted as follows: +/// LLSD Type | JSON Type +/// --------------+---------------- +/// TypeUndefined | null +/// TypeBoolean | boolean +/// TypeInteger | integer +/// TypeReal | real/numeric +/// TypeString | string +/// TypeURI | string +/// TypeDate | string +/// TypeUUID | string +/// TypeMap | object +/// TypeArray | array +/// TypeBinary | unsupported +nlohmann::json LlsdToJson(const LLSD &val); + +#endif // LL_LLSDJSON_H diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp index 0051bd8e35..b64f3d0e4a 100644 --- a/indra/llcommon/llsdparam.cpp +++ b/indra/llcommon/llsdparam.cpp @@ -30,24 +30,21 @@ // Project includes #include "llsdparam.h" #include "llsdutil.h" -#include "boost/bind.hpp" static LLInitParam::Parser::parser_read_func_map_t sReadFuncs; static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs; static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs; static const LLSD NO_VALUE_MARKER; -LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion"); +LLTrace::BlockTimerStatHandle FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion"); // // LLParamSDParser // LLParamSDParser::LLParamSDParser() : Parser(sReadFuncs, sWriteFuncs, sInspectFuncs), - mCurReadSD(NULL), mCurWriteSD(NULL), mWriteRootSD(NULL) + mCurReadSD(NULL), mWriteRootSD(NULL) { - using boost::bind; - if (sReadFuncs.empty()) { registerParserFuncs(readFlag, &LLParamSDParser::writeFlag); @@ -100,7 +97,7 @@ void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool mNameStack.clear(); setParseSilently(silent); - LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack); + LLParamSDParserUtilities::readSDValues(std::bind(&LLParamSDParser::submit, this, std::ref(block), std::placeholders::_1, std::placeholders::_2), sd, mNameStack); //readSDValues(sd, block); } @@ -270,25 +267,23 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI } else if (sd.isArray()) { - for (LLSD::array_const_iterator it = sd.beginArray(); - it != sd.endArray(); - ++it) + for (auto const& entry : sd.array()) { stack.push_back(make_pair(std::string(), true)); - readSDValues(cb, *it, stack); + readSDValues(cb, entry, stack); stack.pop_back(); } } else if (sd.isUndefined()) { - if (!cb.empty()) + if (cb) { cb(NO_VALUE_MARKER, stack); } } else { - if (!cb.empty()) + if (cb) { cb(sd, stack); } @@ -337,7 +332,7 @@ namespace LLInitParam if (!p.writeValue(mValue, name_stack_range)) { // otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) - LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack_range); + LLParamSDParserUtilities::readSDValues(std::bind(&serializeElement, std::ref(p), std::placeholders::_1, std::placeholders::_2), mValue, name_stack_range); } return true; } diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h index 7cfc265c62..87a4d90247 100644 --- a/indra/llcommon/llsdparam.h +++ b/indra/llcommon/llsdparam.h @@ -29,14 +29,13 @@ #define LL_LLSDPARAM_H #include "llinitparam.h" -#include "boost/function.hpp" #include "llfasttimer.h" struct LL_COMMON_API LLParamSDParserUtilities { static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range); - typedef boost::function read_sd_cb_t; + typedef std::function read_sd_cb_t; static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack); static void readSDValues(read_sd_cb_t cb, const LLSD& sd); }; @@ -66,6 +65,7 @@ typedef LLInitParam::Parser parser_t; } /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ std::string getCurrentFileName(){ return LLStringUtil::null; } private: void writeSDImpl(LLSD& sd, @@ -106,11 +106,10 @@ typedef LLInitParam::Parser parser_t; Parser::name_stack_t mNameStack; const LLSD* mCurReadSD; LLSD* mWriteRootSD; - LLSD* mCurWriteSD; }; -extern LL_COMMON_API LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR; +extern LL_COMMON_API LLTrace::BlockTimerStatHandle FTM_SD_PARAM_ADAPTOR; template class LLSDParamAdapter : public T { @@ -118,7 +117,7 @@ class LLSDParamAdapter : public T LLSDParamAdapter() {} LLSDParamAdapter(const LLSD& sd) { - LLFastTimer _(FTM_SD_PARAM_ADAPTOR); + LL_RECORD_BLOCK_TIME(FTM_SD_PARAM_ADAPTOR); LLParamSDParser parser; // don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it bool parse_silently = true; diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index a61c4ba979..989aed77c5 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -55,6 +55,7 @@ static const int MAX_HDR_LEN = 20; static const char LEGACY_NON_HEADER[] = ""; const std::string LLSD_BINARY_HEADER("LLSD/Binary"); const std::string LLSD_XML_HEADER("LLSD/XML"); +const std::string LLSD_NOTATION_HEADER("llsd/notation"); //used to deflate a gzipped asset (currently used for navmeshes) #define windowBits 15 @@ -81,6 +82,11 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize f = new LLSDXMLFormatter; break; + case LLSD_NOTATION: + str << "\n"; + f = new LLSDNotationFormatter; + break; + default: LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL; } @@ -112,7 +118,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes) fail_if_not_legacy = true; } - if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */ + if (!strnicmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */ { legacy_no_header = true; inbuf = (int)str.gcount(); @@ -135,9 +141,8 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes) } header = hdr_buf; - std::string::size_type start = std::string::npos; + std::string::size_type start = header.find_first_not_of(" mMaxBytesLeft)) + S32 size = (S32)ntohl(size_nbo); // Can return negative size if > 2^31. + if(size < 0 || mCheckLimits && (size > mMaxBytesLeft)) { parse_count = PARSE_FAILURE; } @@ -1104,7 +1113,11 @@ S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const map = LLSD::emptyMap(); U32 value_nbo = 0; read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - S32 size = (S32)ntohl(value_nbo); + S32 size = (S32)ntohl(value_nbo); // Can return negative size if > 2^31. + if (size < 0) + { + return PARSE_FAILURE; + } S32 parse_count = 0; S32 count = 0; char c = get(istr); @@ -1158,7 +1171,11 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const array = LLSD::emptyArray(); U32 value_nbo = 0; read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - S32 size = (S32)ntohl(value_nbo); + S32 size = (S32)ntohl(value_nbo); // Can return negative size if > 2^31. + if (size < 0) + { + return PARSE_FAILURE; + } // *FIX: This would be a good place to reserve some space in the // array... @@ -1199,8 +1216,8 @@ bool LLSDBinaryParser::parseString( // *FIX: This is memory inefficient. U32 value_nbo = 0; read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - S32 size = (S32)ntohl(value_nbo); - if(mCheckLimits && (size > mMaxBytesLeft)) return false; + S32 size = (S32)ntohl(value_nbo); // Can return negative size if > 2^31. + if(size < 0 || mCheckLimits && (size > mMaxBytesLeft)) return false; std::vector buf; if(size) { @@ -1294,8 +1311,8 @@ S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 } bool need_comma = false; - LLSD::map_const_iterator iter = data.beginMap(); - LLSD::map_const_iterator end = data.endMap(); + auto iter = data.beginMap(); + auto end = data.endMap(); for(; iter != end; ++iter) { if(need_comma) ostr << ","; @@ -1313,13 +1330,11 @@ S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 { ostr << post << pre << "["; bool need_comma = false; - LLSD::array_const_iterator iter = data.beginArray(); - LLSD::array_const_iterator end = data.endArray(); - for(; iter != end; ++iter) + for (const auto& entry : data.array()) { - if(need_comma) ostr << ","; + if (need_comma) ostr << ","; need_comma = true; - format_count += format_impl(*iter, ostr, options, level + 1); + format_count += format_impl(entry, ostr, options, level + 1); } ostr << "]"; break; @@ -1330,13 +1345,7 @@ S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 break; case LLSD::TypeBoolean: - if(mBoolAlpha || -#if( LL_WINDOWS || __GNUC__ > 2) - (ostr.flags() & std::ios::boolalpha) -#else - (ostr.flags() & 0x0100) -#endif - ) + if(mBoolAlpha || (ostr.flags() & std::ios::boolalpha)) { ostr << (data.asBoolean() ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL); @@ -1388,22 +1397,22 @@ S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 // *FIX: memory inefficient. const std::vector& buffer = data.asBinary(); ostr << "b(" << buffer.size() << ")\""; - if(buffer.size()) + if(!buffer.empty()) { if (options & LLSDFormatter::OPTIONS_PRETTY_BINARY) { std::ios_base::fmtflags old_flags = ostr.flags(); ostr.setf( std::ios::hex, std::ios::basefield ); ostr << "0x"; - for (size_t i = 0; i < buffer.size(); i++) + for (unsigned char i : buffer) { - ostr << (int) buffer[i]; + ostr << static_cast(i); } ostr.flags(old_flags); } else { - ostr.write((const char*)&buffer[0], buffer.size()); + ostr.write(reinterpret_cast(&buffer[0]), buffer.size()); } } ostr << "\""; @@ -1440,9 +1449,9 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option { ostr.put('{'); U32 size_nbo = htonl(data.size()); - ostr.write((const char*)(&size_nbo), sizeof(U32)); - LLSD::map_const_iterator iter = data.beginMap(); - LLSD::map_const_iterator end = data.endMap(); + ostr.write(reinterpret_cast(&size_nbo), sizeof(U32)); + auto iter = data.beginMap(); + auto end = data.endMap(); for(; iter != end; ++iter) { ostr.put('k'); @@ -1457,12 +1466,10 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option { ostr.put('['); U32 size_nbo = htonl(data.size()); - ostr.write((const char*)(&size_nbo), sizeof(U32)); - LLSD::array_const_iterator iter = data.beginArray(); - LLSD::array_const_iterator end = data.endArray(); - for(; iter != end; ++iter) + ostr.write(reinterpret_cast(&size_nbo), sizeof(U32)); + for (const auto& entry : data.array()) { - format_count += format(*iter, ostr); + format_count += format(entry, ostr); } ostr.put(']'); break; @@ -1525,7 +1532,7 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option const std::vector& buffer = data.asBinary(); U32 size_nbo = htonl(buffer.size()); ostr.write((const char*)(&size_nbo), sizeof(U32)); - if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); + if(!buffer.empty()) ostr.write((const char*)&buffer[0], buffer.size()); break; } @@ -1702,12 +1709,12 @@ int deserialize_string_raw( // *FIX: This is memory inefficient. S32 len = strtol(buf + 1, NULL, 0); if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE; - std::vector buf; + std::vector buf2; if(len) { - buf.resize(len); - count += (int)fullread(istr, (char *)&buf[0], len); - value.assign(buf.begin(), buf.end()); + buf2.resize(len); + count += (int)fullread(istr, (char *)&buf2[0], len); + value.assign(buf2.begin(), buf2.end()); } c = istr.get(); ++count; @@ -2091,7 +2098,18 @@ std::string zip_llsd(LLSD& data) } have = CHUNK-strm.avail_out; - output = (U8*) realloc(output, cur_size+have); + U8* new_output = (U8*) realloc(output, cur_size+have); + if (new_output == NULL) + { + LL_WARNS() << "Failed to compress LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL; + deflateEnd(&strm); + if (output) + { + free(output); + } + return std::string(); + } + output = new_output; memcpy(output+cur_size, out, have); cur_size += have; } @@ -2110,15 +2128,6 @@ std::string zip_llsd(LLSD& data) deflateEnd(&strm); free(output); -#if 0 //verify results work with unzip_llsd - std::istringstream test(result); - LLSD test_sd; - if (!unzip_llsd(test_sd, test, result.size())) - { - LL_ERRS() << "Invalid compression result!" << LL_ENDL; - } -#endif - return result; } @@ -2169,7 +2178,19 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size) U32 have = CHUNK-strm.avail_out; - result = (U8*) realloc(result, cur_size + have); + U8* new_result = (U8*)realloc(result, cur_size + have); + if (new_result == NULL) + { + LL_WARNS() << "Failed to unzip LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL; + inflateEnd(&strm); + if (result) + { + free(result); + } + delete in; + return false; + } + result = new_result; memcpy(result+cur_size, out, have); cur_size += have; @@ -2215,6 +2236,11 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size) //and trailers are different for the formats. U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size ) { + if (size == 0) + { + LL_WARNS() << "No data to unzip." << LL_ENDL; + return NULL; + } U8* result = NULL; U32 cur_size = 0; z_stream strm; @@ -2254,7 +2280,23 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 } U32 have = CHUNK-strm.avail_out; - result = (U8*) realloc(result, cur_size + have); + U8* new_result = (U8*) realloc(result, cur_size + have); + if (new_result == NULL) + { + LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size + << " bytes; requested " << cur_size + have + << " bytes; total syze: ." << size << " bytes." + << LL_ENDL; + inflateEnd(&strm); + if (result) + { + free(result); + } + delete [] in; + valid = false; + return NULL; + } + result = new_result; memcpy(result+cur_size, out, have); cur_size += have; diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index c47cb6885b..3b339355d3 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -694,7 +694,7 @@ class LL_COMMON_API LLSDSerialize public: enum ELLSD_Serialize { - LLSD_BINARY, LLSD_XML + LLSD_BINARY, LLSD_XML, LLSD_NOTATION }; /** diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 0ffb0e9e1b..4608fac889 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -116,11 +116,9 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti else { ostr << pre << "" << post; - LLSD::array_const_iterator iter = data.beginArray(); - LLSD::array_const_iterator end = data.endArray(); - for(; iter != end; ++iter) + for (const auto& entry : data.array()) { - format_count += format_impl(*iter, ostr, options, level + 1); + format_count += format_impl(entry, ostr, options, level + 1); } ostr << pre << "" << post; } @@ -337,10 +335,9 @@ void clear_eol(std::istream& input) static unsigned get_till_eol(std::istream& input, char *buf, unsigned bufsize) { unsigned count = 0; - char c; while (count < bufsize && input.good()) { - input.get(c); + char c = input.get(); buf[count++] = c; if (is_eol(c)) break; diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index da697fe910..dd14984a5a 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -45,7 +45,6 @@ #include #include -#include // U32 LLSD ll_sd_from_U32(const U32 val) @@ -193,6 +192,14 @@ char* ll_pretty_print_sd(const LLSD& sd) return buffer; } +std::string ll_stream_notation_sd(const LLSD& sd) +{ + std::ostringstream stream; + stream << LLSDOStreamer(sd); + return stream.str(); +} + + //compares the structure of an LLSD to a template LLSD and stores the //"valid" values in a 3rd LLSD. Default values pulled from the template //if the tested LLSD does not contain the key/value pair. @@ -314,6 +321,180 @@ BOOL compare_llsd_with_template( return TRUE; } +// filter_llsd_with_template() is a direct clone (copy-n-paste) of +// compare_llsd_with_template with the following differences: +// (1) bool vs BOOL return types +// (2) A map with the key value "*" is a special value and maps any key in the +// test llsd that doesn't have an explicitly matching key in the template. +// (3) The element of an array with exactly one element is taken as a template +// for *all* the elements of the test array. If the template array is of +// different size, compare_llsd_with_template() semantics apply. +bool filter_llsd_with_template( + const LLSD & llsd_to_test, + const LLSD & template_llsd, + LLSD & resultant_llsd) +{ + if (llsd_to_test.isUndefined() && template_llsd.isDefined()) + { + resultant_llsd = template_llsd; + return true; + } + else if (llsd_to_test.type() != template_llsd.type()) + { + resultant_llsd = LLSD(); + return false; + } + + if (llsd_to_test.isArray()) + { + //they are both arrays + //we loop over all the items in the template + //verifying that the to_test has a subset (in the same order) + //any shortcoming in the testing_llsd are just taken + //to be the rest of the template + LLSD data; + LLSD::array_const_iterator test_iter; + LLSD::array_const_iterator template_iter; + + resultant_llsd = LLSD::emptyArray(); + test_iter = llsd_to_test.beginArray(); + + if (1 == template_llsd.size()) + { + // If the template has a single item, treat it as + // the template for *all* items in the test LLSD. + template_iter = template_llsd.beginArray(); + + for (; test_iter != llsd_to_test.endArray(); ++test_iter) + { + if (! filter_llsd_with_template(*test_iter, *template_iter, data)) + { + resultant_llsd = LLSD(); + return false; + } + else + { + resultant_llsd.append(data); + } + } + } + else + { + // Traditional compare_llsd_with_template matching + + for (template_iter = template_llsd.beginArray(); + template_iter != template_llsd.endArray() && + test_iter != llsd_to_test.endArray(); + ++template_iter, ++test_iter) + { + if (! filter_llsd_with_template(*test_iter, *template_iter, data)) + { + resultant_llsd = LLSD(); + return false; + } + else + { + resultant_llsd.append(data); + } + } + + //so either the test or the template ended + //we do another loop now to the end of the template + //grabbing the default values + for (; + template_iter != template_llsd.endArray(); + ++template_iter) + { + resultant_llsd.append(*template_iter); + } + } + } + else if (llsd_to_test.isMap()) + { + resultant_llsd = LLSD::emptyMap(); + + //now we loop over the keys of the two maps + //any excess is taken from the template + //excess is ignored in the test + + // Special tag for wildcarded LLSD map key templates + const LLSD::String wildcard_tag("*"); + + const bool template_has_wildcard = template_llsd.has(wildcard_tag); + LLSD wildcard_value; + LLSD value; + + const LLSD::map_const_iterator template_iter_end(template_llsd.endMap()); + for (LLSD::map_const_iterator template_iter(template_llsd.beginMap()); + template_iter_end != template_iter; + ++template_iter) + { + if (wildcard_tag == template_iter->first) + { + wildcard_value = template_iter->second; + } + else if (llsd_to_test.has(template_iter->first)) + { + //the test LLSD has the same key + if (! filter_llsd_with_template(llsd_to_test[template_iter->first], + template_iter->second, + value)) + { + resultant_llsd = LLSD(); + return false; + } + else + { + resultant_llsd[template_iter->first] = value; + } + } + else if (! template_has_wildcard) + { + // test llsd doesn't have it...take the + // template as default value + resultant_llsd[template_iter->first] = template_iter->second; + } + } + if (template_has_wildcard) + { + LLSD sub_value; + LLSD::map_const_iterator test_iter; + + for (test_iter = llsd_to_test.beginMap(); + test_iter != llsd_to_test.endMap(); + ++test_iter) + { + if (resultant_llsd.has(test_iter->first)) + { + // Final value has test key, assume more specific + // template matched and we shouldn't modify it again. + continue; + } + else if (! filter_llsd_with_template(test_iter->second, + wildcard_value, + sub_value)) + { + // Test value doesn't match wildcarded template + resultant_llsd = LLSD(); + return false; + } + else + { + // Test value matches template, add the actuals. + resultant_llsd[test_iter->first] = sub_value; + } + } + } + } + else + { + //of same type...take the test llsd's value + resultant_llsd = llsd_to_test; + } + + return true; +} + /***************************************************************************** * Helpers for llsd_matches() *****************************************************************************/ @@ -347,7 +528,7 @@ class TypeLookup public: TypeLookup() { - for (const Data *di(boost::begin(typedata)), *dend(boost::end(typedata)); di != dend; ++di) + for (const Data *di(std::begin(typedata)), *dend(std::end(typedata)); di != dend; ++di) { mMap[di->type] = di->name; } @@ -527,7 +708,7 @@ std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::str LLSD::TypeURI }; return match_types(prototype.type(), - TypeVector(boost::begin(accept), boost::end(accept)), + TypeVector(std::begin(accept), std::end(accept)), data.type(), pfx); } @@ -544,7 +725,7 @@ std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::str }; // Funny business: shuffle the set of acceptable types to include all // but the prototype's type. Get the acceptable types in a set. - std::set rest(boost::begin(all), boost::end(all)); + std::set rest(std::begin(all), std::end(all)); // Remove the prototype's type because we pass that separately. rest.erase(prototype.type()); return match_types(prototype.type(), @@ -560,7 +741,7 @@ std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::str LLSD::TypeString }; return match_types(prototype.type(), - TypeVector(boost::begin(accept), boost::end(accept)), + TypeVector(std::begin(accept), std::end(accept)), data.type(), pfx); } @@ -673,3 +854,104 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits) return false; // pacify the compiler } } + +// Construct a deep partial clone of of an LLSD object. primitive types share +// references, however maps, arrays and binary objects are duplicated. An optional +// filter may be include to exclude/include keys in a map. +LLSD llsd_clone(LLSD value, LLSD filter) +{ + LLSD clone; + bool has_filter(filter.isMap()); + + switch (value.type()) + { + case LLSD::TypeMap: + clone = LLSD::emptyMap(); + for (LLSD::map_const_iterator itm = value.beginMap(); itm != value.endMap(); ++itm) + { + if (has_filter) + { + if (filter.has((*itm).first)) + { + if (!filter[(*itm).first].asBoolean()) + continue; + } + else if (filter.has("*")) + { + if (!filter["*"].asBoolean()) + continue; + } + else + { + continue; + } + } + clone[(*itm).first] = llsd_clone((*itm).second, filter); + } + break; + case LLSD::TypeArray: + clone = LLSD::emptyArray(); + for (auto const& entry : value.array()) + { + clone.append(llsd_clone(entry, filter)); + } + break; + + case LLSD::TypeBinary: + { + LLSD::Binary bin(value.asBinary().begin(), value.asBinary().end()); + clone = LLSD::Binary(bin); + break; + } + default: + clone = value; + } + + return clone; +} + +LLSD llsd_shallow(LLSD value, LLSD filter) +{ + LLSD shallow; + bool has_filter(filter.isMap()); + + if (value.isMap()) + { + shallow = LLSD::emptyMap(); + for (LLSD::map_const_iterator itm = value.beginMap(); itm != value.endMap(); ++itm) + { + if (has_filter) + { + if (filter.has((*itm).first)) + { + if (!filter[(*itm).first].asBoolean()) + continue; + } + else if (filter.has("*")) + { + if (!filter["*"].asBoolean()) + continue; + } + else + { + continue; + } + } + shallow[(*itm).first] = (*itm).second; + } + } + else if (value.isArray()) + { + shallow = LLSD::emptyArray(); + for (auto const& entry : value.array()) + { + shallow.append(entry); + } + } + else + { + return value; + } + + return shallow; +} diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index 99cb79aa54..e9c366212b 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -30,6 +30,7 @@ #define LL_LLSDUTIL_H #include "llsd.h" +#include // U32 LL_COMMON_API LLSD ll_sd_from_U32(const U32); @@ -56,6 +57,8 @@ LL_COMMON_API char* ll_print_sd(const LLSD& sd); LL_COMMON_API char* ll_pretty_print_sd_ptr(const LLSD* sd); LL_COMMON_API char* ll_pretty_print_sd(const LLSD& sd); +LL_COMMON_API std::string ll_stream_notation_sd(const LLSD& sd); + //compares the structure of an LLSD to a template LLSD and stores the //"valid" values in a 3rd LLSD. Default values //are pulled from the template. Extra keys/values in the test @@ -68,6 +71,19 @@ LL_COMMON_API BOOL compare_llsd_with_template( const LLSD& template_llsd, LLSD& resultant_llsd); +// filter_llsd_with_template() is a direct clone (copy-n-paste) of +// compare_llsd_with_template with the following differences: +// (1) bool vs BOOL return types +// (2) A map with the key value "*" is a special value and maps any key in the +// test llsd that doesn't have an explicitly matching key in the template. +// (3) The element of an array with exactly one element is taken as a template +// for *all* the elements of the test array. If the template array is of +// different size, compare_llsd_with_template() semantics apply. +bool filter_llsd_with_template( + const LLSD & llsd_to_test, + const LLSD & template_llsd, + LLSD & resultant_llsd); + /** * Recursively determine whether a given LLSD data block "matches" another * LLSD prototype. The returned string is empty() on success, non-empty() on @@ -128,6 +144,11 @@ LL_COMMON_API std::string llsd_matches(const LLSD& prototype, const LLSD& data, /// is_approx_equal_fraction(). LL_COMMON_API bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits=-1); +inline bool operator==(const LLSD& lhs, const LLSD& rhs) +{ + return llsd_equals(lhs, rhs, 8); +} + // Simple function to copy data out of input & output iterators if // there is no need for casting. template LLSD llsd_copy_array(Input iter, Input end) @@ -419,4 +440,87 @@ class inMap } // namespace llsd + +// Creates a deep clone of an LLSD object. Maps, Arrays and binary objects +// are duplicated, atomic primitives (Boolean, Integer, Real, etc) simply +// use a shared reference. +// Optionally a filter may be specified to control what is duplicated. The +// map takes the form "keyname/boolean". +// If the value is true the value will be duplicated otherwise it will be skipped +// when encountered in a map. A key name of "*" can be specified as a wild card +// and will specify the default behavior. If no wild card is given and the clone +// encounters a name not in the filter, that value will be skipped. +LLSD llsd_clone(LLSD value, LLSD filter = LLSD()); + +// Creates a shallow copy of a map or array. If passed any other type of LLSD +// object it simply returns that value. See llsd_clone for a description of +// the filter parameter. +LLSD llsd_shallow(LLSD value, LLSD filter = LLSD()); + + +// Specialization for generating a hash value from an LLSD block. +namespace boost { + template<> struct hash +{ + typedef LLSD argument_type; + typedef std::size_t result_type; + result_type operator()(argument_type const& s) const + { + result_type seed(0); + + LLSD::Type stype = s.type(); + boost::hash_combine(seed, (S32)stype); + + switch (stype) + { + case LLSD::TypeBoolean: + boost::hash_combine(seed, s.asBoolean()); + break; + case LLSD::TypeInteger: + boost::hash_combine(seed, s.asInteger()); + break; + case LLSD::TypeReal: + boost::hash_combine(seed, s.asReal()); + break; + case LLSD::TypeURI: + case LLSD::TypeString: + boost::hash_combine(seed, s.asString()); + break; + case LLSD::TypeUUID: + boost::hash_combine(seed, s.asUUID()); + break; + case LLSD::TypeDate: + boost::hash_combine(seed, s.asDate().secondsSinceEpoch()); + break; + case LLSD::TypeBinary: + { + const LLSD::Binary &b(s.asBinary()); + boost::hash_range(seed, b.begin(), b.end()); + break; + } + case LLSD::TypeMap: + { + for (LLSD::map_const_iterator itm = s.beginMap(); itm != s.endMap(); ++itm) + { + boost::hash_combine(seed, (*itm).first); + boost::hash_combine(seed, (*itm).second); + } + break; + } + case LLSD::TypeArray: + for (LLSD::array_const_iterator ita = s.beginArray(); ita != s.endArray(); ++ita) + { + boost::hash_combine(seed, (*ita)); + } + break; + case LLSD::TypeUndefined: + default: + break; + } + + return seed; + } +}; +} + #endif // LL_LLSDUTIL_H diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp index e0446c5d0d..8212a4a2ee 100644 --- a/indra/llcommon/llstacktrace.cpp +++ b/indra/llcommon/llstacktrace.cpp @@ -39,7 +39,7 @@ #include #include -#include "windows.h" +#include "llwin32headerslean.h" #include "Dbghelp.h" typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( @@ -73,8 +73,7 @@ bool ll_get_stack_trace(std::vector& lines) if(symbolsLoaded) { // create the frames to hold the addresses - void* frames[MAX_STACK_DEPTH]; - memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH); + void* frames[MAX_STACK_DEPTH] = {0}; S32 depth = 0; // get the addresses @@ -110,7 +109,7 @@ bool ll_get_stack_trace(std::vector& lines) if(ret) { std::string file_name = line.FileName; - std::string::size_type index = file_name.rfind("\\"); + std::string::size_type index = file_name.rfind('\\'); stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; } diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp index d47ab91958..cd62c04cbc 100644 --- a/indra/llcommon/llstat.cpp +++ b/indra/llcommon/llstat.cpp @@ -152,7 +152,7 @@ F32 LLStat::getMax() const F32 LLStat::getMean() const { - F32 current_mean = getCurrent(); + F32 current_mean = 0.f; // Don't double-count current. S32 samples = 0; for (S32 i = 0; i < (S32)mNumValues; i++) { @@ -170,10 +170,6 @@ F32 LLStat::getMean() const { current_mean /= samples; } - else - { - current_mean = 0.f; - } return current_mean; } diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h index c506cc7387..3014bd2463 100644 --- a/indra/llcommon/llstat.h +++ b/indra/llcommon/llstat.h @@ -80,9 +80,10 @@ class LL_COMMON_API LLStat private: - BOOL mUseFrameTimer; + const BOOL mUseFrameTimer; + const U32 mNumBins; + U32 mNumValues; - U32 mNumBins; struct ValueEntry { @@ -101,7 +102,7 @@ class LL_COMMON_API LLStat S32 mCurBin; S32 mNextBin; - std::string mName; + const std::string mName; static LLTimer sTimer; static LLFrameTimer sFrameTimer; diff --git a/indra/llcommon/llstaticstringtable.h b/indra/llcommon/llstaticstringtable.h index f3c46e7493..537fa00f31 100644 --- a/indra/llcommon/llstaticstringtable.h +++ b/indra/llcommon/llstaticstringtable.h @@ -45,7 +45,7 @@ class LLStaticHashedString const std::string& String() const { return string; } size_t Hash() const { return string_hash; } - bool operator==(const LLStaticHashedString& b) const { return String() == b.String(); } + bool operator==(const LLStaticHashedString& b) const { return Hash() == b.Hash(); } protected: diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index c0b02e0ccf..34ca7dfce2 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -37,7 +37,11 @@ #include #include #include +#include +#include +#include #include +#include "stdtypes.h" // Use to compare the first element only of a pair // e.g. typedef std::set, compare_pair > some_pair_set_t; @@ -221,14 +225,7 @@ template //Singu note: This has been generalized to support a broader range of map-esque containers inline bool is_in_map(const T& inmap, typename T::key_type const& key) { - if(inmap.find(key) == inmap.end()) - { - return false; - } - else - { - return true; - } + return inmap.find(key) != inmap.end(); } // Similar to get_ptr_in_map, but for any type with a valid T(0) constructor. @@ -268,6 +265,24 @@ inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename T::key_ty return get_if_there(inmap,key,NULL); }; +template +inline typename T::iterator get_in_vec(T& invec, P pred) +{ + return std::find_if(invec.begin(), invec.end(), pred); +} + +template +inline typename T::value_type::second_type& get_val_in_pair_vec(T& invec, K key) +{ + auto it = get_in_vec(invec, [&key](typename T::value_type& e) { return e.first == key; }); + if (it == invec.end()) + { + invec.emplace_back(key, typename T::value_type::second_type()); + return invec.back().second; + } + return it->second; +} + // Useful for replacing the removeObj() functionality of LLDynamicArray // Example: // for (std::vector::iterator iter = mList.begin(); iter != mList.end(); ) @@ -321,26 +336,13 @@ inline bool vector_replace_with_last(T& invec, typename T::value_type const& val // Append N elements to the vector and return a pointer to the first new element. template -inline T* vector_append(std::vector& invec, S32 N) +inline T* vector_append(std::vector& invec, size_t N) { - U32 sz = invec.size(); + size_t sz = invec.size(); invec.resize(sz+N); return &(invec[sz]); } -template -inline void vector_shrink_to_fit(std::vector& invec) -{ - //For Windows: We always assume vs2010 or later, which support this c++11 feature with no configuration needed. - //For GCC: __cplusplus >= 201103L indicates C++11 support. __GXX_EXPERIMENTAL_CXX0X being set indicates experimental c++0x support. C++11 support replaces C++0x support. - // std::vector::shrink_to_fit was added to GCCs C++0x implementation in version 4.5.0. -#if defined(LL_WINDOWS) || __cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X) && __GNUC_MINOR__ >= 5) - invec.shrink_to_fit(); -#else - std::vector(invec).swap(invec); -#endif -} - // call function f to n members starting at first. similar to std::for_each template Function ll_for_n(InputIter first, Size n, Function f) @@ -535,18 +537,8 @@ llbind2nd(const _Operation& __oper, const _Tp& __x) inline bool before(const std::type_info* lhs, const std::type_info* rhs) { -#if LL_LINUX && defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) - // If we're building on Linux with gcc, and it's either gcc 3.x or - // 4.{0,1,2,3}, then we have to use a workaround. Note that we use gcc on - // Mac too, and some people build with gcc on Windows (cygwin or mingw). - // On Linux, different load modules may produce different type_info* - // pointers for the same type. Have to compare name strings to get good - // results. - return strcmp(lhs->name(), rhs->name()) < 0; -#else // not Linux, or gcc 4.4+ - // Just use before(), as we normally would - return lhs->before(*rhs); -#endif + // Just use before(), as we normally would + return lhs->before(*rhs) ? true : false; } /** diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp index 4ed2df58e0..b3c83dadc8 100644 --- a/indra/llcommon/llstreamtools.cpp +++ b/indra/llcommon/llstreamtools.cpp @@ -124,7 +124,7 @@ bool skip_to_next_word(std::istream& input_stream) bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream) { - int key_length = strlen(keyword); /*Flawfinder: ignore*/ + size_t key_length = strlen(keyword); /*Flawfinder: ignore*/ if (0 == key_length) { return false; @@ -139,7 +139,7 @@ bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream } else { - int key_index = 1; + size_t key_index = 1; while ( key_index < key_length && keyword[key_index - 1] == c && input_stream.good()) @@ -321,7 +321,7 @@ bool unget_line(const std::string& line, std::istream& input_stream) // returns true if removed last char bool remove_last_char(char c, std::string& line) { - int line_size = line.size(); + size_t line_size = line.size(); if (line_size > 1 && c == line[line_size - 1]) { diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index b4f310a512..cfded258b9 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -34,6 +34,17 @@ #include "stdtypes.h" +template +inline void copyArray(T* dst, const T* src, const U32 bytes) +{ + memcpy(dst, src, bytes); +} +template<> +inline void copyArray<>(LLVector4a* dst, const LLVector4a* src, const U32 bytes) +{ + LLVector4a::memcpyNonAliased16(dst->getF32ptr(), src->getF32ptr(), bytes); +} + template class LLStrider { union @@ -68,8 +79,22 @@ template class LLStrider Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; } Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; } - Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); } - + Object& operator[](size_t index) { return *(Object*)(mBytep + (mSkip * index)); } + + void copyArray(const U32 offset, const Object* src, const U32 length) + { + if (mSkip == sizeof(Object)) + { + ::copyArray(mObjectp + offset, src, length * sizeof(Object)); + } + else + { + for (U32 i = 0; i < length; i++) + { + (*this)[offset + i] = src[i]; + } + } + } }; #endif // LL_LLSTRIDER_H diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 44c6d14352..e55bb15639 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com /** * @file llstring.cpp * @brief String utility functions and the std::string class. @@ -28,14 +30,17 @@ #include "llstring.h" #include "llerror.h" +#include "llfasttimer.h" +#include "llsd.h" #if LL_WINDOWS -#define WIN32_LEAN_AND_MEAN -#include -#include +#include "llwin32headerslean.h" #include // for WideCharToMultiByte #endif +LLTrace::BlockTimerStatHandle FT_STRING_FORMAT("String Format"); + + std::string ll_safe_string(const char* in) { if(in) return std::string(in); @@ -49,6 +54,23 @@ std::string ll_safe_string(const char* in, S32 maxlen) return std::string(); } +bool is_char_hex(char hex) +{ + if((hex >= '0') && (hex <= '9')) + { + return true; + } + else if((hex >= 'a') && (hex <='f')) + { + return true; + } + else if((hex >= 'A') && (hex <='F')) + { + return true; + } + return false; // uh - oh, not hex any more... +} + U8 hex_as_nybble(char hex) { if((hex >= '0') && (hex <= '9')) @@ -87,7 +109,7 @@ bool iswindividual(llwchar elem) bool _read_file_into_string(std::string& str, const std::string& filename) { - llifstream ifs(filename, llifstream::binary); + llifstream ifs(filename.c_str(), llifstream::binary); if (!ifs.is_open()) { LL_INFOS() << "Unable to open file " << filename << LL_ENDL; @@ -174,10 +196,10 @@ S32 wchar_to_utf8chars(llwchar in_char, char* outchars) return outchars - base; } -S32 utf16chars_to_wchar(const U16* inchars, llwchar* outchar) +S32 utf16chars_to_wchar(const utf16strtype* inchars, llwchar* outchar) { - const U16* base = inchars; - U16 cur_char = *inchars++; + const utf16strtype* base = inchars; + utf16strtype cur_char = *inchars++; llwchar char32 = cur_char; if ((cur_char >= 0xD800) && (cur_char <= 0xDFFF)) { @@ -211,7 +233,7 @@ llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len) { out += cur_char; } - i++; + ++i; } return out; } @@ -236,7 +258,7 @@ LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len) S32 i = 0; // craziness to make gcc happy (llutf16string.c_str() is tweaked on linux): - const U16* chars16 = &(*(utf16str.begin())); + const utf16strtype* chars16 = &(*(utf16str.begin())); while (i < len) { llwchar cur_char; @@ -257,18 +279,18 @@ S32 utf16str_wstring_length(const llutf16string &utf16str, const S32 utf16_len) { S32 surrogate_pairs = 0; // ... craziness to make gcc happy (llutf16string.c_str() is tweaked on linux): - const U16 *const utf16_chars = &(*(utf16str.begin())); + const utf16strtype *const utf16_chars = &(*(utf16str.begin())); S32 i = 0; while (i < utf16_len) { - const U16 c = utf16_chars[i++]; + const utf16strtype c = utf16_chars[i++]; if (c >= 0xD800 && c <= 0xDBFF) // See http://en.wikipedia.org/wiki/UTF-16 { // Have first byte of a surrogate pair if (i >= utf16_len) { break; } - const U16 d = utf16_chars[i]; + const utf16strtype d = utf16_chars[i]; if (d >= 0xDC00 && d <= 0xDFFF) { // Have valid second byte of a surrogate pair surrogate_pairs++; @@ -374,12 +396,12 @@ S32 wstring_utf8_length(const LLWString& wstr) LLWString utf8str_to_wstring(const std::string& utf8str, S32 len) { + llwchar unichar; LLWString wout; + wout.reserve(len); - S32 i = 0; - while (i < len) + for (S32 i = 0; i < len; i++) { - llwchar unichar; U8 cur_char = utf8str[i]; if (cur_char < 0x80) @@ -455,7 +477,6 @@ LLWString utf8str_to_wstring(const std::string& utf8str, S32 len) } wout += unichar; - ++i; } return wout; } @@ -468,16 +489,15 @@ LLWString utf8str_to_wstring(const std::string& utf8str) std::string wstring_to_utf8str(const LLWString& utf32str, S32 len) { + char tchars[8]; /* Flawfinder: ignore */ std::string out; + out.reserve(len); - S32 i = 0; - while (i < len) + for (S32 i = 0; i < len; ++i) { - char tchars[8]; /* Flawfinder: ignore */ S32 n = wchar_to_utf8chars(utf32str[i], tchars); tchars[n] = 0; out += tchars; - i++; } return out; } @@ -556,6 +576,105 @@ std::string utf8str_truncate(const std::string& utf8str, const S32 max_len) } } +// [RLVa:KB] - Checked: RLVa-2.1.0 +std::string utf8str_substr(const std::string& utf8str, const size_t index, const size_t max_len) +{ + if (0 == max_len) + { + return std::string(); + } + if (utf8str.length() - index <= max_len) + { + return utf8str.substr(index, max_len); + } + else + { + size_t cur_char = max_len; + + // If we're ASCII, we don't need to do anything + if ((U8)utf8str[index + cur_char] > 0x7f) + { + // If first two bits are (10), it's the tail end of a multibyte char. We need to shift back + // to the first character + while (0x80 == (0xc0 & utf8str[index + cur_char])) + { + cur_char--; + // Keep moving forward until we hit the first char; + if (cur_char == 0) + { + // Make sure we don't trash memory if we've got a bogus string. + break; + } + } + } + // The byte index we're on is one we want to get rid of, so we only want to copy up to (cur_char-1) chars + return utf8str.substr(index, cur_char); + } +} + +void utf8str_split(std::list& split_list, const std::string& utf8str, size_t maxlen, char split_token) +{ + split_list.clear(); + + std::string::size_type lenMsg = utf8str.length(), lenIt = 0; + + const char* pstrIt = utf8str.c_str(); std::string strTemp; + while (lenIt < lenMsg) + { + if (lenIt + maxlen < lenMsg) + { + // Find the last split character + const char* pstrTemp = pstrIt + maxlen; + while ( (pstrTemp > pstrIt) && (*pstrTemp != split_token) ) + pstrTemp--; + + if (pstrTemp > pstrIt) + strTemp = utf8str.substr(lenIt, pstrTemp - pstrIt); + else + strTemp = utf8str_substr(utf8str, lenIt, maxlen); + } + else + { + strTemp = utf8str.substr(lenIt, std::string::npos); + } + + split_list.push_back(strTemp); + + lenIt += strTemp.length(); + pstrIt = utf8str.c_str() + lenIt; + if (*pstrIt == split_token) + lenIt++; + } +} +// [/RLVa:KB] + +std::string utf8str_symbol_truncate(const std::string& utf8str, const size_t symbol_len) +{ + if (0 == symbol_len) + { + return std::string(); + } + if ((S32)utf8str.length() <= symbol_len) + { + return utf8str; + } + else + { + size_t len = 0, byteIndex = 0; + const char* aStr = utf8str.c_str(); + size_t origSize = utf8str.size(); + + for (byteIndex = 0; len < symbol_len && byteIndex < origSize; byteIndex++) + { + if ((aStr[byteIndex] & 0xc0) != 0x80) + { + len += 1; + } + } + return utf8str.substr(0, byteIndex); + } +} + std::string utf8str_substChar( const std::string& utf8str, const llwchar target_char, @@ -621,20 +740,10 @@ bool LLStringOps::isHexString(const std::string& str) } #if LL_WINDOWS -// documentation moved to header. Phoenix 2007-11-27 -namespace snprintf_hack -{ - int snprintf(char *str, size_t size, const char *format, ...) - { - va_list args; - va_start(args, format); - int num_written = _vsnprintf(str, size, format, args); /* Flawfinder: ignore */ - va_end(args); - - str[size-1] = '\0'; // always null terminate - return num_written; - } +std::string ll_convert_wide_to_string(const wchar_t* in) +{ + return ll_convert_wide_to_string(in, CP_UTF8); } std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) @@ -648,10 +757,10 @@ std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) 0, in, len_in, - NULL, + nullptr, 0, - 0, - 0); + nullptr, + nullptr); // We will need two more bytes for the double NULL ending // created in WideCharToMultiByte(). char* pout = new char [len_out + 2]; @@ -665,8 +774,8 @@ std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) len_in, pout, len_out, - 0, - 0); + nullptr, + nullptr); out.assign(pout); delete[] pout; } @@ -674,6 +783,11 @@ std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) return out; } +wchar_t* ll_convert_string_to_wide(const std::string& in) +{ + return ll_convert_string_to_wide(in, CP_UTF8); +} + wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page) { // From review: @@ -687,14 +801,75 @@ wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page // reserve place to NULL terminator int output_str_len = in.length(); wchar_t* w_out = new wchar_t[output_str_len + 1]; - memset(w_out, 0, output_str_len + 1); + int real_output_str_len = MultiByteToWideChar (code_page, 0, in.c_str(), in.length(), w_out, output_str_len); //looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858. w_out[real_output_str_len] = 0; return w_out; +// return {&w_out[0]}; +} + +S32 wchartchars_to_llwchar(const std::wstring::value_type* inchars, llwchar* outchar) +{ + const std::wstring::value_type* base = inchars; + std::wstring::value_type cur_char = *inchars++; + llwchar char32 = cur_char; + if ((cur_char >= 0xD800) && (cur_char <= 0xDFFF)) + { + // Surrogates + char32 = ((llwchar)(cur_char - 0xD800)) << 10; + cur_char = *inchars++; + char32 += (llwchar)(cur_char - 0xDC00) + 0x0010000UL; + } + else + { + char32 = (llwchar)cur_char; + } + *outchar = char32; + return inchars - base; +} + +LLWString ll_convert_wide_to_wstring(const std::wstring& in) +{ + LLWString wout; + auto len = in.size(); + if ((len <= 0) || in.empty()) return wout; + + size_t i = 0; + // craziness to make gcc happy (llutf16string.c_str() is tweaked on linux): + const std::wstring::value_type* chars16 = &(*(in.begin())); + while (i < len) + { + llwchar cur_char; + i += wchartchars_to_llwchar(chars16 + i, &cur_char); + wout += cur_char; + } + return wout; +} + +std::wstring ll_convert_wstring_to_wide(const LLWString& in) +{ + std::wstring out; + + size_t i = 0; + while (i < in.size()) + { + U32 cur_char = in[i]; + if (cur_char > 0xFFFF) + { + out += (0xD7C0 + (cur_char >> 10)); + out += (0xDC00 | (cur_char & 0x3FF)); + } + else + { + out += cur_char; + } + i++; + } + return out; } std::string ll_convert_string_to_utf8_string(const std::string& in) @@ -705,11 +880,112 @@ std::string ll_convert_string_to_utf8_string(const std::string& in) return out_utf8; } -#endif // LL_WINDOWS + +namespace +{ + +void HeapFree_deleter(void* ptr) +{ + // instead of LocalFree(), per https://stackoverflow.com/a/31541205 + HeapFree(GetProcessHeap(), NULL, ptr); +} + +} // anonymous namespace + +template<> +std::wstring windows_message(DWORD error) +{ + // derived from https://stackoverflow.com/a/455533 + wchar_t* rawptr = nullptr; + auto okay = FormatMessageW( + // use system message tables for GetLastError() codes + FORMAT_MESSAGE_FROM_SYSTEM | + // internally allocate buffer and return its pointer + FORMAT_MESSAGE_ALLOCATE_BUFFER | + // you cannot pass insertion parameters (thanks Gandalf) + FORMAT_MESSAGE_IGNORE_INSERTS | + // ignore line breaks in message definition text + FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, // lpSource, unused with FORMAT_MESSAGE_FROM_SYSTEM + error, // dwMessageId + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // dwLanguageId + (LPWSTR)&rawptr, // lpBuffer: force-cast wchar_t** to wchar_t* + 0, // nSize, unused with FORMAT_MESSAGE_ALLOCATE_BUFFER + NULL); // Arguments, unused + + // make a unique_ptr from rawptr so it gets cleaned up properly + std::unique_ptr bufferptr(rawptr, HeapFree_deleter); + + if (okay && bufferptr) + { + // got the message, return it ('okay' is length in characters) + return { bufferptr.get(), okay }; + } + + // did not get the message, synthesize one + auto format_message_error = GetLastError(); + std::wostringstream out; + out << L"GetLastError() " << error << L" (FormatMessageW() failed with " + << format_message_error << L")"; + return out.str(); +} + +boost::optional llstring_getoptenv(const std::string& key) +{ + auto wkey = ll_convert_string_to_wide(key); + // Take a wild guess as to how big the buffer should be. + std::vector buffer(1024); + auto n = GetEnvironmentVariableW(wkey, &buffer[0], buffer.size()); + // If our initial guess was too short, n will indicate the size (in + // wchar_t's) that buffer should have been, including the terminating nul. + if (n > (buffer.size() - 1)) + { + // make it big enough + buffer.resize(n); + // and try again + n = GetEnvironmentVariableW(wkey, &buffer[0], buffer.size()); + } + // did that (ultimately) succeed? + if (n) + { + // great, return populated boost::optional + return boost::optional(&buffer[0]); + } + + // not successful + auto last_error = GetLastError(); + // Don't bother warning for NOT_FOUND; that's an expected case + if (last_error != ERROR_ENVVAR_NOT_FOUND) + { + LL_WARNS() << "GetEnvironmentVariableW('" << key << "') failed: " + << windows_message(last_error) << LL_ENDL; + } + // return empty boost::optional + return {}; +} + +#else // ! LL_WINDOWS + +boost::optional llstring_getoptenv(const std::string& key) +{ + auto found = getenv(key.c_str()); + if (found) + { + // return populated boost::optional + return boost::optional(found); + } + else + { + // return empty boost::optional + return {}; + } +} + +#endif // ! LL_WINDOWS long LLStringOps::sPacificTimeOffset = 0; long LLStringOps::sLocalTimeOffset = 0; -bool LLStringOps::sPacificDaylightTime = 0; +bool LLStringOps::sPacificDaylightTime = false; std::map LLStringOps::datetimeToCodes; std::vector LLStringOps::sWeekDayList; @@ -728,7 +1004,7 @@ S32 LLStringOps::collate(const llwchar* a, const llwchar* b) #if LL_WINDOWS // in Windows, wide string functions operator on 16-bit strings, // not the proper 32 bit wide string - return strcmp(wstring_to_utf8str(LLWString(a)).c_str(), wstring_to_utf8str(LLWString(b)).c_str()); + return strcoll(wstring_to_utf8str(LLWString(a)).c_str(), wstring_to_utf8str(LLWString(b)).c_str()); #else return wcscoll(a, b); #endif @@ -739,7 +1015,7 @@ void LLStringOps::setupDatetimeInfo (bool daylight) time_t nowT, localT, gmtT; struct tm * tmpT; - nowT = time (NULL); + nowT = time (nullptr); tmpT = gmtime (&nowT); gmtT = mktime (tmpT); @@ -819,7 +1095,7 @@ void LLStringOps::setupDayFormat(const std::string& data) } -std::string LLStringOps::getDatetimeCode (std::string key) +std::string LLStringOps::getDatetimeCode(const std::string& key) { std::map::iterator iter; @@ -830,11 +1106,31 @@ std::string LLStringOps::getDatetimeCode (std::string key) } else { - return std::string(""); + return std::string(); } } +std::string LLStringOps::getReadableNumber(F64 num) +{ + if (fabs(num)>=1e9) + { + return llformat("%.2lfB", num / 1e9); + } + else if (fabs(num)>=1e6) + { + return llformat("%.2lfM", num / 1e6); + } + else if (fabs(num)>=1e3) + { + return llformat("%.2lfK", num / 1e3); + } + else + { + return llformat("%.2lf", num); + } +} + namespace LLStringFn { // NOTE - this restricts output to ascii @@ -1044,7 +1340,8 @@ void LLStringUtil::formatNumber(std::string& numStr, std::string decimals) // std::locale() throws if the locale is unknown! (EXT-7926) try { - strStream.imbue(std::locale(sLocale.c_str())); + std::locale locale(sLocale.c_str()); + strStream.imbue(locale); } catch (const std::exception &) { LL_WARNS_ONCE("Locale") << "Cannot set locale to " << sLocale << LL_ENDL; @@ -1057,8 +1354,7 @@ void LLStringUtil::formatNumber(std::string& numStr, std::string decimals) if (convertToS32(numStr, intStr)) { - strStream << intStr; - numStr = strStream.str(); + numStr = fmt::to_string(intStr); } } else @@ -1101,7 +1397,7 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, } else if (param == "local") { - replacement = ""; // user knows their own timezone + replacement.clear(); // user knows their own timezone } else { @@ -1138,14 +1434,14 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, { struct tm * gmt = gmtime (&loc_seconds); LLStringUtil::format_map_t args; - args["[MDAY]"] = llformat ("%d", gmt->tm_mday); + args["[MDAY]"] = fmt::to_string(gmt->tm_mday); replacement = LLStringOps::sDayFormat; LLStringUtil::format(replacement, args); } else if (code == "%-d") { struct tm * gmt = gmtime (&loc_seconds); - replacement = llformat ("%d", gmt->tm_mday); // day of the month without leading zero + replacement = fmt::to_string(gmt->tm_mday); // day of the month without leading zero } else if( !LLStringOps::sAM.empty() && !LLStringOps::sPM.empty() && code == "%p" ) { @@ -1187,6 +1483,7 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, template<> S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions) { + LL_RECORD_BLOCK_TIME(FT_STRING_FORMAT); S32 res = 0; std::string output; @@ -1259,6 +1556,7 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions) template<> S32 LLStringUtil::format(std::string& s, const LLSD& substitutions) { + LL_RECORD_BLOCK_TIME(FT_STRING_FORMAT); S32 res = 0; if (!substitutions.isMap()) @@ -1387,7 +1685,7 @@ void LLStringUtilBase::testHarness() s2.erase( 4, 1 ); llassert( s2 == "hell"); - s2.insert( 0, 1, 'y' ); + s2.insert( s2.begin(), 'y' ); llassert( s2 == "yhell"); s2.erase( 1, 3 ); llassert( s2 == "yl"); diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 112a25e663..0b7d67232b 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -27,12 +27,29 @@ #ifndef LL_LLSTRING_H #define LL_LLSTRING_H +#include #include + +#if __cplusplus < 201606 +#include +namespace std { + typedef absl::string_view string_view; +} +#else + #include +#endif + #include -#include +//#include #include -#include "llsd.h" -#include "llfasttimer.h" +#include +#include +#include +#include "stdtypes.h" +#include "llpreprocessor.h" +// [RLVa:KB] - Checked: RLVa-2.1.0 +#include +// [/RLVa:KB] #if LL_LINUX || LL_SOLARIS #include @@ -49,6 +66,7 @@ #endif const char LL_UNKNOWN_CHAR = '?'; +class LLSD; #if LL_DARWIN || LL_LINUX || LL_SOLARIS // Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already) @@ -209,7 +227,10 @@ class LL_COMMON_API LLStringOps // currently in daylight savings time? static bool getPacificDaylightTime(void) { return sPacificDaylightTime;} - static std::string getDatetimeCode (std::string key); + static std::string getDatetimeCode (const std::string& key); + + // Express a value like 1234567 as "1.23M" + static std::string getReadableNumber(F64 num); }; /** @@ -232,7 +253,7 @@ class LLFormatMapString bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; } std::size_t length() const { return mString.length(); } // The destructor may not throw. - ~LLFormatMapString() throw() { } + ~LLFormatMapString() noexcept { } private: std::string mString; @@ -308,6 +329,7 @@ class LLStringUtilBase static void trimHead(string_type& string); static void trimTail(string_type& string); + static void trimTail(string_type& string, const string_type& tokens); static void trim(string_type& string) { trimHead(string); trimTail(string); } static void truncate(string_type& string, size_type count); @@ -335,8 +357,22 @@ class LLStringUtilBase const string_type& string, const string_type& substr); + /** + * get environment string value with proper Unicode handling + * (key is always UTF-8) + * detect absence by return value == dflt + */ + static string_type getenv(const std::string& key, const string_type& dflt=""); + /** + * get optional environment string value with proper Unicode handling + * (key is always UTF-8) + * detect absence by (! return value) + */ + static boost::optional getoptenv(const std::string& key); + static void addCRLF(string_type& string); static void removeCRLF(string_type& string); + static void removeWindowsCR(string_type& string); static void replaceTabsWithSpaces( string_type& string, size_type spaces_per_tab ); static void replaceNonstandardASCII( string_type& string, T replacement ); @@ -445,7 +481,7 @@ class LLStringExplicit : public std::string struct LLDictionaryLess { public: - bool operator()(const std::string& a, const std::string& b) + bool operator()(const std::string& a, const std::string& b) const { return (LLStringUtil::precedesDict(a, b) ? true : false); } @@ -475,6 +511,7 @@ inline std::string chop_tail_copy( * @brief This translates a nybble stored as a hex value from 0-f back * to a nybble in the low order bits of the return byte. */ +LL_COMMON_API bool is_char_hex(char hex); LL_COMMON_API U8 hex_as_nybble(char hex); /** @@ -493,6 +530,37 @@ LL_COMMON_API bool iswindividual(llwchar elem); * Unicode support */ +/// generic conversion aliases +template +struct ll_convert_impl +{ + // Don't even provide a generic implementation. We specialize for every + // combination we do support. + TO operator()(const FROM& in) const; +}; + +// Use a function template to get the nice ll_convert(from_value) API. +template +TO ll_convert(const FROM& in) +{ + return ll_convert_impl()(in); +} + +// degenerate case +template +struct ll_convert_impl +{ + T operator()(const T& in) const { return in; } +}; + +// specialize ll_convert_impl to return EXPR +#define ll_convert_alias(TO, FROM, EXPR) \ +template<> \ +struct ll_convert_impl \ +{ \ + TO operator()(const FROM& in) const { return EXPR; } \ +} + // Make the incoming string a utf8 string. Replaces any unknown glyph // with the UNKNOWN_CHARACTER. Once any unknown glyph is found, the rest // of the data may not be recovered. @@ -500,31 +568,95 @@ LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw); // // We should never use UTF16 except when communicating with Win32! +// https://docs.microsoft.com/en-us/cpp/cpp/char-wchar-t-char16-t-char32-t +// nat 2018-12-14: I consider the whole llutf16string thing a mistake, because +// the Windows APIs we want to call are all defined in terms of wchar_t* +// (or worse, LPCTSTR). +// https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types + +// While there is no point coding for an ASCII-only world (! defined(UNICODE)), +// use of U16 and llutf16string for Windows APIs locks in /Zc:wchar_t-. Going +// forward, we should code in terms of wchar_t and std::wstring so as to +// support either setting of /Zc:wchar_t. + +// The first link above states that char can be used to hold ASCII or any +// multi-byte character set, and distinguishes wchar_t (UTF-16LE), char16_t +// (UTF-16) and char32_t (UTF-32). Nonetheless, within this code base: +// * char and std::string always hold UTF-8 (of which ASCII is a subset). It +// is a BUG if they are used to pass strings in any other multi-byte +// encoding. +// * wchar_t and std::wstring should be our interface to Windows wide-string +// APIs, and therefore hold UTF-16LE. +// * U16 and llutf16string are the previous but DEPRECATED UTF-16LE type. Do +// not introduce new uses of U16 or llutf16string for string data. +// * llwchar and LLWString hold UTF-32 strings. +// * Do not introduce char16_t or std::u16string. +// * Do not introduce char32_t or std::u32string. // -typedef std::basic_string llutf16string; +#if _WIN32 && _NATIVE_WCHAR_T_DEFINED +typedef wchar_t utf16strtype; +#else +typedef U16 utf16strtype; +#endif +typedef std::basic_string llutf16string; + +#if ! defined(LL_WCHAR_T_NATIVE) +// wchar_t is identical to U16, and std::wstring is identical to llutf16string. +// Defining an ll_convert alias involving llutf16string would collide with the +// comparable preferred alias involving std::wstring. (In this scenario, if +// you pass llutf16string, it will engage the std::wstring specialization.) +#define ll_convert_u16_alias(TO, FROM, EXPR) // nothing +#else // defined(LL_WCHAR_T_NATIVE) +// wchar_t is a distinct native type, so llutf16string is also a distinct +// type, and there IS a point to converting separately to/from llutf16string. +// (But why? Windows APIs are still defined in terms of wchar_t, and +// in this scenario llutf16string won't work for them!) +#define ll_convert_u16_alias(TO, FROM, EXPR) ll_convert_alias(TO, FROM, EXPR) + +#if LL_WINDOWS +// LL_WCHAR_T_NATIVE is defined on non-Windows systems because, in fact, +// wchar_t is native. Everywhere but Windows, we use it for llwchar (see +// stdtypes.h). That makes LLWString identical to std::wstring, so these +// aliases for std::wstring would collide with those for LLWString. Only +// define on Windows, where converting between std::wstring and llutf16string +// means copying chars. +ll_convert_alias(llutf16string, std::wstring, llutf16string(in.begin(), in.end())); +ll_convert_alias(std::wstring, llutf16string, std::wstring(in.begin(), in.end())); +#endif // LL_WINDOWS +#endif // defined(LL_WCHAR_T_NATIVE) LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len); LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str); +ll_convert_u16_alias(LLWString, llutf16string, utf16str_to_wstring(in)); LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len); LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str); +ll_convert_u16_alias(llutf16string, LLWString, wstring_to_utf16str(in)); LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len); LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str ); +ll_convert_u16_alias(llutf16string, std::string, utf8str_to_utf16str(in)); LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len); LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str); // Same function, better name. JC inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); } +// best name of all +ll_convert_alias(LLWString, std::string, utf8string_to_wstring(in)); // LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars); LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len); LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str); - +ll_convert_alias(std::string, LLWString, wstring_to_utf8str(in)); LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len); LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str); +ll_convert_u16_alias(std::string, llutf16string, utf16str_to_utf8str(in)); + +#if LL_WINDOWS +inline std::string wstring_to_utf8str(const llutf16string &utf16str) { return utf16str_to_utf8str(utf16str);} +#endif // Length of this UTF32 string in bytes when transformed to UTF8 LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr); @@ -541,7 +673,7 @@ LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen); // Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.) -LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL); +LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = nullptr); /** * @brief Properly truncate a utf8 string to a maximum byte count. @@ -555,12 +687,28 @@ LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wst */ LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len); +// [RLVa:KB] - Checked: RLVa-2.1.0 +LL_COMMON_API std::string utf8str_substr(const std::string& utf8str, const S32 index, const S32 max_len); +LL_COMMON_API void utf8str_split(std::list& split_list, const std::string& utf8str, size_t maxlen, char split_token); +// [/RLVa:KB] + LL_COMMON_API std::string utf8str_trim(const std::string& utf8str); LL_COMMON_API S32 utf8str_compare_insensitive( const std::string& lhs, const std::string& rhs); +/** +* @brief Properly truncate a utf8 string to a maximum character count. +* +* If symbol_len is longer than the string passed in, the return +* value == utf8str. +* @param utf8str A valid utf8 string to truncate. +* @param symbol_len The maximum number of symbols in the return value. +* @return Returns a valid utf8 string with symbol count <= max_len. +*/ +LL_COMMON_API std::string utf8str_symbol_truncate(const std::string& utf8str, const S32 symbol_len); + /** * @brief Replace all occurences of target_char with replace_char * @@ -587,53 +735,82 @@ LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str); //@{ /** - * @brief Implementation the expected snprintf interface. - * - * If the size of the passed in buffer is not large enough to hold the string, - * two bad things happen: - * 1. resulting formatted string is NOT null terminated - * 2. Depending on the platform, the return value could be a) the required - * size of the buffer to copy the entire formatted string or b) -1. - * On Windows with VS.Net 2003, it returns -1 e.g. - * - * safe_snprintf always adds a NULL terminator so that the caller does not - * need to check for return value or need to add the NULL terminator. - * It does not, however change the return value - to let the caller know - * that the passed in buffer size was not large enough to hold the - * formatted string. + * @brief Convert a wide string to std::string * + * This replaces the unsafe W2A macro from ATL. */ - -// Deal with the differeneces on Windows -namespace snprintf_hack +LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page); +LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in); // default CP_UTF8 +inline std::string ll_convert_wide_to_string(const std::wstring& in, unsigned int code_page) { - LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...); + return ll_convert_wide_to_string(in.c_str(), code_page); } +inline std::string ll_convert_wide_to_string(const std::wstring& in) +{ + return ll_convert_wide_to_string(in.c_str()); +} +ll_convert_alias(std::string, std::wstring, ll_convert_wide_to_string(in)); -using snprintf_hack::snprintf; +/** + * Converts a string to wide string. + */ +LL_COMMON_API wchar_t* ll_convert_string_to_wide(const std::string& in, + unsigned int code_page); +LL_COMMON_API wchar_t* ll_convert_string_to_wide(const std::string& in); + // default CP_UTF8 +ll_convert_alias(wchar_t*, std::string, ll_convert_string_to_wide(in)); /** - * @brief Convert a wide string to std::string - * - * This replaces the unsafe W2A macro from ATL. + * Convert a Windows wide string to our LLWString */ -LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page); +LL_COMMON_API LLWString ll_convert_wide_to_wstring(const std::wstring& in); +ll_convert_alias(LLWString, std::wstring, ll_convert_wide_to_wstring(in)); /** - * Converts a string to wide string. - * - * It will allocate memory for result string with "new []". Don't forget to release it with "delete []". + * Convert LLWString to Windows wide string */ -LL_COMMON_API wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page); +LL_COMMON_API std::wstring ll_convert_wstring_to_wide(const LLWString& in); +ll_convert_alias(std::wstring, LLWString, ll_convert_wstring_to_wide(in)); /** - * Converts incoming string into urf8 string + * Converts incoming string into utf8 string * */ LL_COMMON_API std::string ll_convert_string_to_utf8_string(const std::string& in); +/// Get Windows message string for passed GetLastError() code +// VS 2013 doesn't let us forward-declare this template, which is what we +// started with, so the implementation could reference the specialization we +// haven't yet declared. Somewhat weirdly, just stating the generic +// implementation in terms of the specialization works, even in this order... + +// the general case is just a conversion from the sole implementation +// Microsoft says DWORD is a typedef for unsigned long +// https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types +// so rather than drag windows.h into everybody's include space... +template +STRING windows_message(unsigned long error) +{ + return ll_convert(windows_message(error)); +} + +/// There's only one real implementation +template<> +LL_COMMON_API std::wstring windows_message(unsigned long error); + +/// Get Windows message string, implicitly calling GetLastError() +template +STRING windows_message() { return windows_message(GetLastError()); } + //@} -#endif // LL_WINDOWS + +LL_COMMON_API boost::optional llstring_getoptenv(const std::string& key); + +#else // ! LL_WINDOWS + +LL_COMMON_API boost::optional llstring_getoptenv(const std::string& key); + +#endif // ! LL_WINDOWS /** * Many of the 'strip' and 'replace' methods of LLStringUtilBase need @@ -829,8 +1006,9 @@ class InEscString: public InString } /// This implementation uses the answer cached by setiter(). - virtual bool escaped() const { return mIsEsc; } - virtual T next() + bool escaped() const override { return mIsEsc; } + + T next() override { // If we're looking at the escape character of an escape sequence, // skip that character. This is the one time we can modify 'mIter' @@ -846,21 +1024,21 @@ class InEscString: public InString return result; } - virtual bool is(T ch) const + bool is(T ch) const override { // Like base-class is(), except that an escaped character matches // nothing. return (! done()) && (! mIsEsc) && *mIter == ch; } - virtual bool oneof(const string_type& delims) const + bool oneof(const string_type& delims) const override { // Like base-class oneof(), except that an escaped character matches // nothing. return (! done()) && (! mIsEsc) && LLStringUtilBase::contains(delims, *mIter); } - virtual bool collect_until(string_type& into, const_iterator from, T delim) + bool collect_until(string_type& into, const_iterator from, T delim) override { // Deal with escapes in the characters we collect; that is, an escaped // character must become just that character without the preceding @@ -1174,7 +1352,7 @@ BOOL LLStringUtilBase::precedesDict( const string_type& a, const string_type& { if( a.size() && b.size() ) { - return (LLStringUtilBase::compareDict(a.c_str(), b.c_str()) < 0); + return (LLStringUtilBase::compareDict(a, b) < 0); } else { @@ -1229,7 +1407,7 @@ void LLStringUtilBase::trimHead(string_type& string) template void LLStringUtilBase::trimTail(string_type& string) { - if( string.size() ) + if(!string.empty()) { size_type len = string.length(); size_type i = len; @@ -1242,12 +1420,31 @@ void LLStringUtilBase::trimTail(string_type& string) } } +template +void LLStringUtilBase::trimTail(string_type& string, const string_type& tokens) +{ + if(!string.empty()) + { + size_type len = string.length(); + size_type i = len; + while( i > 0 && (tokens.find_first_of(string[i-1]) != string_type::npos) ) + { + i--; + } + + string.erase( i, len - i ); + } +} + // Replace line feeds with carriage return-line feed pairs. //static template void LLStringUtilBase::addCRLF(string_type& string) { + if (string.empty()) + return; + const T LF = 10; const T CR = 13; @@ -1290,6 +1487,9 @@ void LLStringUtilBase::addCRLF(string_type& string) template void LLStringUtilBase::removeCRLF(string_type& string) { + if (string.empty()) + return; + const T CR = 13; size_type cr_count = 0; @@ -1309,6 +1509,32 @@ void LLStringUtilBase::removeCRLF(string_type& string) //static template +void LLStringUtilBase::removeWindowsCR(string_type& string) +{ + if (string.empty()) + { + return; + } + const T LF = 10; + const T CR = 13; + + size_type cr_count = 0; + size_type len = string.size(); + size_type i; + for( i = 0; i < len - cr_count - 1; i++ ) + { + if( string[i+cr_count] == CR && string[i+cr_count+1] == LF) + { + cr_count++; + } + + string[i] = string[i+cr_count]; + } + string.erase(i, cr_count); +} + +//static +template void LLStringUtilBase::replaceChar( string_type& string, T target, T replacement ) { size_type found_pos = 0; @@ -1392,6 +1618,7 @@ BOOL LLStringUtilBase::containsNonprintable(const string_type& string) return rv; } +// *TODO: reimplement in terms of algorithm //static template void LLStringUtilBase::stripNonprintable(string_type& string) @@ -1402,29 +1629,23 @@ void LLStringUtilBase::stripNonprintable(string_type& string) { return; } - size_t src_size = string.size(); - char* c_string = new char[src_size + 1]; - if(c_string == NULL) - { - return; - } - copy(c_string, string.c_str(), src_size+1); - char* write_head = &c_string[0]; + const size_t src_size = string.size(); + auto c_string = std::make_unique(src_size + 1); + + copy(c_string.get(), string.c_str(), src_size+1); for (size_type i = 0; i < src_size; i++) { - char* read_head = &string[i]; - write_head = &c_string[j]; - if(!(*read_head < MIN)) + if(string[i] >= MIN) { - *write_head = *read_head; + c_string[j] = string[i]; ++j; } } c_string[j]= '\0'; - string = c_string; - delete []c_string; + string.assign(c_string.get()); } +// *TODO: reimplement in terms of algorithm template std::basic_string LLStringUtilBase::quote(const string_type& str, const string_type& triggers, @@ -1446,7 +1667,9 @@ std::basic_string LLStringUtilBase::quote(const string_type& str, } // For whatever reason, we must quote this string. + auto needed_escapes = std::count(str.begin(), str.end(), '"'); string_type result; + result.reserve(len + (needed_escapes * escape.length())); result.push_back('"'); for (typename string_type::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci) { @@ -1561,6 +1784,37 @@ bool LLStringUtilBase::endsWith( return (idx == (string.size() - substr.size())); } +// static +template +auto LLStringUtilBase::getoptenv(const std::string& key) -> boost::optional +{ + auto found(llstring_getoptenv(key)); + if (found) + { + // return populated boost::optional + return { ll_convert(*found) }; + } + else + { + // empty boost::optional + return {}; + } +} + +// static +template +auto LLStringUtilBase::getenv(const std::string& key, const string_type& dflt) -> string_type +{ + auto found(getoptenv(key)); + if (found) + { + return *found; + } + else + { + return dflt; + } +} template BOOL LLStringUtilBase::convertToBOOL(const string_type& string, BOOL& value) diff --git a/indra/llcommon/llstringtable.cpp b/indra/llcommon/llstringtable.cpp index 73573090b1..1844e7e803 100644 --- a/indra/llcommon/llstringtable.cpp +++ b/indra/llcommon/llstringtable.cpp @@ -264,7 +264,7 @@ LLStringTableEntry* LLStringTable::addStringEntry(const char *str) if (strlist) { string_list_t::iterator iter; - for (iter = strlist->begin(); iter != strlist->end(); iter++) + for (iter = strlist->begin(); iter != strlist->end(); ++iter) { entry = *iter; ret_val = entry->mString; @@ -338,7 +338,7 @@ void LLStringTable::removeString(const char *str) if (strlist) { string_list_t::iterator iter; - for (iter = strlist->begin(); iter != strlist->end(); iter++) + for (iter = strlist->begin(); iter != strlist->end(); ++iter) { entry = *iter; ret_val = entry->mString; diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h index d40c9d8dfd..55bed71f21 100644 --- a/indra/llcommon/llstringtable.h +++ b/indra/llcommon/llstringtable.h @@ -150,7 +150,7 @@ class LL_COMMON_API LLStdStringTable for (S32 i = 0; i #include #include -#include #include -#include -#include -#include -#include using namespace llsd; #if LL_WINDOWS -# define WIN32_LEAN_AND_MEAN -# include -# include +# include "llwin32headerslean.h" # include // GetPerformanceInfo() et al. +# include #elif LL_DARWIN # include # include @@ -95,8 +88,6 @@ const char MEMINFO_FILE[] = "/proc/meminfo"; extern int errno; #endif - -static const S32 CPUINFO_BUFFER_SIZE = 16383; LLCPUInfo gSysCPU; // Don't log memory info any more often than this. It also serves as our @@ -108,78 +99,6 @@ static const F32 MEM_INFO_THROTTLE = 20; // dropped below the login framerate, we'd have very little additional data. static const F32 MEM_INFO_WINDOW = 10*60; -#if LL_WINDOWS -// We cannot trust GetVersionEx function on Win8.1 , we should check this value when creating OS string -static const U32 WINNT_WINBLUE = 0x0603; - -#ifndef DLLVERSIONINFO -typedef struct _DllVersionInfo -{ - DWORD cbSize; - DWORD dwMajorVersion; - DWORD dwMinorVersion; - DWORD dwBuildNumber; - DWORD dwPlatformID; -}DLLVERSIONINFO; -#endif - -#ifndef DLLGETVERSIONPROC -typedef int (FAR WINAPI *DLLGETVERSIONPROC) (DLLVERSIONINFO *); -#endif - -bool get_shell32_dll_version(DWORD& major, DWORD& minor, DWORD& build_number) -{ - bool result = false; - const U32 BUFF_SIZE = 32767; - WCHAR tempBuf[BUFF_SIZE]; - if(GetSystemDirectory((LPWSTR)&tempBuf, BUFF_SIZE)) - { - - std::basic_string shell32_path(tempBuf); - - // Shell32.dll contains the DLLGetVersion function. - // according to msdn its not part of the API - // so you have to go in and get it. - // http://msdn.microsoft.com/en-us/library/bb776404(VS.85).aspx - shell32_path += TEXT("\\shell32.dll"); - - HMODULE hDllInst = LoadLibrary(shell32_path.c_str()); //load the DLL - if(hDllInst) - { // Could successfully load the DLL - DLLGETVERSIONPROC pDllGetVersion; - /* - You must get this function explicitly because earlier versions of the DLL - don't implement this function. That makes the lack of implementation of the - function a version marker in itself. - */ - pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hDllInst, - "DllGetVersion"); - - if(pDllGetVersion) - { - // DLL supports version retrieval function - DLLVERSIONINFO dvi; - - ZeroMemory(&dvi, sizeof(dvi)); - dvi.cbSize = sizeof(dvi); - HRESULT hr = (*pDllGetVersion)(&dvi); - - if(SUCCEEDED(hr)) - { // Finally, the version is at our hands - major = dvi.dwMajorVersion; - minor = dvi.dwMinorVersion; - build_number = dvi.dwBuildNumber; - result = true; - } - } - - FreeLibrary(hDllInst); // Release DLL - } - } - return result; -} -#endif // LL_WINDOWS - // Wrap boost::regex_match() with a function that doesn't throw. template static bool regex_match_no_exc(const S& string, M& match, const R& regex) @@ -212,221 +131,141 @@ static bool regex_search_no_exc(const S& string, M& match, const R& regex) } } -#if LL_WINDOWS -// GetVersionEx should not works correct with Windows 8.1 and the later version. We need to check this case -static bool check_for_version(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) -{ - OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 }; - DWORDLONG const dwlConditionMask = VerSetConditionMask( - VerSetConditionMask( - VerSetConditionMask( - 0, VER_MAJORVERSION, VER_GREATER_EQUAL), - VER_MINORVERSION, VER_GREATER_EQUAL), - VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); - - osvi.dwMajorVersion = wMajorVersion; - osvi.dwMinorVersion = wMinorVersion; - osvi.wServicePackMajor = wServicePackMajor; - - return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; -} -#endif - - LLOSInfo::LLOSInfo() : mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("") { #if LL_WINDOWS - OSVERSIONINFOEX osvi; - BOOL bOsVersionInfoEx; - BOOL bShouldUseShellVersion = false; - - // Try calling GetVersionEx using the OSVERSIONINFOEX structure. - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi))) + bool is_server = IsWindowsServer(); + std::string service_pack; + if (IsWindows10OrGreater()) { - // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. - osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - if(!GetVersionEx( (OSVERSIONINFO *) &osvi)) - return; + if (is_server) + { + mOSStringSimple = "Microsoft Windows Server 2016 "; + } + else + { + mOSStringSimple = "Microsoft Windows 10 "; + } } - mMajorVer = osvi.dwMajorVersion; - mMinorVer = osvi.dwMinorVersion; - mBuild = osvi.dwBuildNumber; - - DWORD shell32_major, shell32_minor, shell32_build; - bool got_shell32_version = get_shell32_dll_version(shell32_major, - shell32_minor, - shell32_build); - - switch(osvi.dwPlatformId) + else if (IsWindows8Point1OrGreater()) { - case VER_PLATFORM_WIN32_NT: + if (is_server) { - // Test for the product. - if(osvi.dwMajorVersion <= 4) - { - mOSStringSimple = "Microsoft Windows NT "; - } - else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) - { - mOSStringSimple = "Microsoft Windows 2000 "; - } - else if(osvi.dwMajorVersion ==5 && osvi.dwMinorVersion == 1) - { - mOSStringSimple = "Microsoft Windows XP "; - } - else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) - { - if(osvi.wProductType == VER_NT_WORKSTATION) - mOSStringSimple = "Microsoft Windows XP x64 Edition "; - else - mOSStringSimple = "Microsoft Windows Server 2003 "; - } - else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 2) - { - if(osvi.dwMinorVersion == 0) - { - if(osvi.wProductType == VER_NT_WORKSTATION) - mOSStringSimple = "Microsoft Windows Vista "; - else - mOSStringSimple = "Windows Server 2008 "; - } - else if(osvi.dwMinorVersion == 1) - { - if(osvi.wProductType == VER_NT_WORKSTATION) - mOSStringSimple = "Microsoft Windows 7 "; - else - mOSStringSimple = "Windows Server 2008 R2 "; - } - else if(osvi.dwMinorVersion == 2) - { - if (check_for_version(HIBYTE(WINNT_WINBLUE), LOBYTE(WINNT_WINBLUE), 0)) - { - mOSStringSimple = "Microsoft Windows 8.1 "; - bShouldUseShellVersion = true; // GetVersionEx failed, going to use shell version - } - else - { - if(osvi.wProductType == VER_NT_WORKSTATION) - mOSStringSimple = "Microsoft Windows 8 "; - else - mOSStringSimple = "Windows Server 2012 "; - } - } - - ///get native system info if available.. - typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo - SYSTEM_INFO si; //System Info object file contains architecture info - PGNSI pGNSI; //pointer object - ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information - pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function - if(NULL != pGNSI) //check if it has failed - pGNSI(&si); //success - else - GetSystemInfo(&si); //if it fails get regular system info - //(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load) - - //msdn microsoft finds 32 bit and 64 bit flavors this way.. - //http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors - //of windows than this code does (in case it is needed for the future) - if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) //check for 64 bit - { - mOSStringSimple += "64-bit "; - } - else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL ) - { - mOSStringSimple += "32-bit "; - } - } - else // Use the registry on early versions of Windows NT. - { - mOSStringSimple = "Microsoft Windows (unrecognized) "; - - HKEY hKey; - WCHAR szProductType[80]; - DWORD dwBufLen; - RegOpenKeyEx( HKEY_LOCAL_MACHINE, - L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", - 0, KEY_QUERY_VALUE, &hKey ); - RegQueryValueEx( hKey, L"ProductType", NULL, NULL, - (LPBYTE) szProductType, &dwBufLen); - RegCloseKey( hKey ); - if ( lstrcmpi( L"WINNT", szProductType) == 0 ) - { - mOSStringSimple += "Professional "; - } - else if ( lstrcmpi( L"LANMANNT", szProductType) == 0 ) - { - mOSStringSimple += "Server "; - } - else if ( lstrcmpi( L"SERVERNT", szProductType) == 0 ) - { - mOSStringSimple += "Advanced Server "; - } - } - - std::string csdversion = utf16str_to_utf8str(osvi.szCSDVersion); - // Display version, service pack (if any), and build number. - std::string tmpstr; - if(osvi.dwMajorVersion <= 4) - { - tmpstr = llformat("version %d.%d %s (Build %d)", - osvi.dwMajorVersion, - osvi.dwMinorVersion, - csdversion.c_str(), - (osvi.dwBuildNumber & 0xffff)); - } - else - { - tmpstr = !bShouldUseShellVersion ? llformat("%s (Build %d)", csdversion.c_str(), (osvi.dwBuildNumber & 0xffff)): - llformat("%s (Build %d)", csdversion.c_str(), shell32_build); - } - - mOSString = mOSStringSimple + tmpstr; + mOSStringSimple = "Microsoft Windows Server 2012 R2 "; } - break; - - case VER_PLATFORM_WIN32_WINDOWS: - // Test for the Windows 95 product family. - if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) + else { - mOSStringSimple = "Microsoft Windows 95 "; - if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' ) - { - mOSStringSimple += "OSR2 "; - } - } - if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) + mOSStringSimple = "Microsoft Windows 8.1 "; + } + } + else if (IsWindows8OrGreater()) + { + if (is_server) { - mOSStringSimple = "Microsoft Windows 98 "; - if ( osvi.szCSDVersion[1] == 'A' ) - { - mOSStringSimple += "SE "; - } - } - if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) + mOSStringSimple = "Microsoft Windows Server 2012 "; + } + else { - mOSStringSimple = "Microsoft Windows Millennium Edition "; + mOSStringSimple = "Microsoft Windows 8 "; } - mOSString = mOSStringSimple; - break; } - - std::string compatibility_mode; - if(got_shell32_version) + else if (IsWindows7OrGreater()) { - if((osvi.dwMajorVersion != shell32_major || osvi.dwMinorVersion != shell32_minor) && !bShouldUseShellVersion) + if (is_server) { - compatibility_mode = llformat(" compatibility mode. real ver: %d.%d (Build %d)", - shell32_major, - shell32_minor, - shell32_build); + mOSStringSimple = "Microsoft Windows Server 2008 R2 "; + } + else + { + mOSStringSimple = "Microsoft Windows 7 "; + } + if (IsWindows7SP1OrGreater()) + { + service_pack = "Service Pack 1 "; + } + } + else if (IsWindowsVistaOrGreater()) + { + if (is_server) + { + mOSStringSimple = "Microsoft Windows Server 2008 "; + } + else + { + mOSStringSimple = "Microsoft Windows Vista "; + } + if (IsWindowsVistaSP2OrGreater()) + { + service_pack = "Service Pack 2 "; + } + else if (IsWindowsVistaSP1OrGreater()) + { + service_pack = "Service Pack 1 "; } } - mOSString += compatibility_mode; + else + { + mOSStringSimple = "Microsoft Windows (unrecognized) "; + } + + ///get native system info if available.. + typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo + SYSTEM_INFO si; //System Info object file contains architecture info + PGNSI pGNSI; //pointer object + ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information + pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function + if (NULL != pGNSI) //check if it has failed + pGNSI(&si); //success + else + GetSystemInfo(&si); //if it fails get regular system info + //(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load) + + //msdn microsoft finds 32 bit and 64 bit flavors this way.. + //http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors + //of windows than this code does (in case it is needed for the future) + if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) //check for 64 bit + { + mOSStringSimple += "64-bit "; + } + else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) + { + mOSStringSimple += "32-bit "; + } + + OSVERSIONINFOEX osvi; + BOOL bOsVersionInfoEx; + // Try calling GetVersionEx using the OSVERSIONINFOEX structure. + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if (!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi))) + { + // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi); + } + + + std::string tmpstr; + if (bOsVersionInfoEx) + { + mMajorVer = osvi.dwMajorVersion; + mMinorVer = osvi.dwMinorVersion; + mBuild = osvi.dwBuildNumber; + tmpstr = llformat("%s(Build %d)", service_pack.c_str(), mBuild); + } + else + { + mMajorVer = 0; + mMinorVer = 0; + mBuild = 0; + tmpstr = llformat("%s(Build %d)", service_pack.c_str(), 0); + } + + // Display version, service pack (if any), and build number. + mOSString = mOSStringSimple + tmpstr; + LLStringUtil::trim(mOSStringSimple); #elif LL_DARWIN @@ -668,8 +507,6 @@ const std::string& LLOSInfo::getOSVersionString() const return mOSVersionString; } -const S32 STATUS_SIZE = 8192; - //static U32 LLOSInfo::getProcessVirtualSizeKB() { @@ -677,6 +514,7 @@ U32 LLOSInfo::getProcessVirtualSizeKB() #if LL_WINDOWS #endif #if LL_LINUX +# define STATUS_SIZE 2048 LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); if (status_filep) { @@ -834,7 +672,7 @@ class Stats // Store every integer type as LLSD::Integer. template void add(const LLSD::String& name, const T& value, - typename boost::enable_if >::type* = 0) + typename std::enable_if::value>::type* = nullptr) { mStats[name] = LLSD::Integer(value); } @@ -842,7 +680,7 @@ class Stats // Store every floating-point type as LLSD::Real. template void add(const LLSD::String& name, const T& value, - typename boost::enable_if >::type* = 0) + typename std::enable_if::value>::type* = nullptr) { mStats[name] = LLSD::Real(value); } @@ -864,28 +702,10 @@ LLMemoryInfo::LLMemoryInfo() refresh(); } -#if LL_WINDOWS -static U32 LLMemoryAdjustKBResult(U32 inKB) -{ - // Moved this here from llfloaterabout.cpp - - //! \bug - // For some reason, the reported amount of memory is always wrong. - // The original adjustment assumes it's always off by one meg, however - // errors of as much as 2520 KB have been observed in the value - // returned from the GetMemoryStatusEx function. Here we keep the - // original adjustment from llfoaterabout.cpp until this can be - // fixed somehow. - inKB += 1024; - - return inKB; -} -#endif - -U32 LLMemoryInfo::getPhysicalMemoryKB() const +U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const { #if LL_WINDOWS - return LLMemoryAdjustKBResult(mStatsMap["Total Physical KB"].asInteger()); + return U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()); #elif LL_DARWIN // This might work on Linux as well. Someone check... @@ -895,17 +715,12 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const size_t len = sizeof(phys); sysctl(mib, 2, &phys, &len, NULL, 0); - return (U32)(phys >> 10); + return U64Bytes(phys); #elif LL_LINUX U64 phys = 0; phys = (U64)(getpagesize()) * (U64)(get_phys_pages()); - return (U32)(phys >> 10); - -#elif LL_SOLARIS - U64 phys = 0; - phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES)); - return (U32)(phys >> 10); + return U64Bytes(phys); #else return 0; @@ -913,32 +728,16 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const #endif } -U32 LLMemoryInfo::getPhysicalMemoryClamped() const -{ - // Return the total physical memory in bytes, but clamp it - // to no more than U32_MAX - - U32 phys_kb = getPhysicalMemoryKB(); - if (phys_kb >= 4194304 /* 4GB in KB */) - { - return U32_MAX; - } - else - { - return phys_kb << 10; - } -} - //static -void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb) +void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb) { #if LL_WINDOWS - // Sigh, this shouldn't be a static method, then we wouldn't have to - // reload this data separately from refresh() - LLSD statsMap(loadStatsMap()); + MEMORYSTATUSEX state; + state.dwLength = sizeof(state); + GlobalMemoryStatusEx(&state); - avail_physical_mem_kb = statsMap["Avail Physical KB"].asInteger(); - avail_virtual_mem_kb = statsMap["Avail Virtual KB"].asInteger(); + avail_physical_mem_kb = U64Bytes(state.ullAvailPhys); + avail_virtual_mem_kb = U64Bytes(state.ullAvailVirtual); #elif LL_DARWIN // mStatsMap is derived from vm_stat, look for (e.g.) "kb free": @@ -955,8 +754,8 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v // Pageins: 2097212. // Pageouts: 41759. // Object cache: 841598 hits of 7629869 lookups (11% hit rate) - avail_physical_mem_kb = -1 ; - avail_virtual_mem_kb = -1 ; + avail_physical_mem_kb = (U32Kilobytes)-1 ; + avail_virtual_mem_kb = (U32Kilobytes)-1 ; #elif LL_LINUX // mStatsMap is derived from MEMINFO_FILE: @@ -1007,15 +806,15 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v // DirectMap4k: 434168 kB // DirectMap2M: 477184 kB // (could also run 'free', but easier to read a file than run a program) - avail_physical_mem_kb = -1 ; - avail_virtual_mem_kb = -1 ; + avail_physical_mem_kb = (U32Kilobytes)-1 ; + avail_virtual_mem_kb = (U32Kilobytes)-1 ; #else //do not know how to collect available memory info for other systems. //leave it blank here for now. - avail_physical_mem_kb = -1 ; - avail_virtual_mem_kb = -1 ; + avail_physical_mem_kb = (U32Kilobytes)-1 ; + avail_virtual_mem_kb = (U32Kilobytes)-1 ; #endif } @@ -1029,7 +828,7 @@ void LLMemoryInfo::stream(std::ostream& s) const // Max key length size_t key_width(0); - BOOST_FOREACH(const MapEntry& pair, inMap(mStatsMap)) + for (const MapEntry& pair : inMap(mStatsMap)) { size_t len(pair.first.length()); if (len > key_width) @@ -1039,7 +838,7 @@ void LLMemoryInfo::stream(std::ostream& s) const } // Now stream stats - BOOST_FOREACH(const MapEntry& pair, inMap(mStatsMap)) + for (const MapEntry& pair : inMap(mStatsMap)) { s << pfx << std::setw(key_width+1) << (pair.first + ':') << ' '; LLSD value(pair.second); @@ -1086,7 +885,7 @@ LLSD LLMemoryInfo::loadStatsMap() DWORDLONG div = 1024; - stats.add("Percent Memory use", state.dwMemoryLoad/div); + stats.add("Percent Memory use", state.dwMemoryLoad); stats.add("Total Physical KB", state.ullTotalPhys/div); stats.add("Avail Physical KB", state.ullAvailPhys/div); stats.add("Total page KB", state.ullTotalPageFile/div); @@ -1135,27 +934,33 @@ LLSD LLMemoryInfo::loadStatsMap() stats.add("PrivateUsage KB", pmem.PrivateUsage/div); #elif LL_DARWIN - - const vm_size_t pagekb(vm_page_size / 1024); + vm_size_t page_size_kb; + if (host_page_size(mach_host_self(), &page_size_kb) != KERN_SUCCESS) + { + LL_WARNS() << "Unable to get host page size. Using default value." << LL_ENDL; + page_size_kb = 4096; + } + page_size_kb = page_size_kb / 1024; + // // Collect the vm_stat's // { - vm_statistics_data_t vmstat; - mach_msg_type_number_t vmstatCount = HOST_VM_INFO_COUNT; + vm_statistics64_data_t vmstat; + mach_msg_type_number_t vmstatCount = HOST_VM_INFO64_COUNT; - if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) &vmstat, &vmstatCount) != KERN_SUCCESS) + if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t) &vmstat, &vmstatCount) != KERN_SUCCESS) { LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL; } else { - stats.add("Pages free KB", pagekb * vmstat.free_count); - stats.add("Pages active KB", pagekb * vmstat.active_count); - stats.add("Pages inactive KB", pagekb * vmstat.inactive_count); - stats.add("Pages wired KB", pagekb * vmstat.wire_count); + stats.add("Pages free KB", page_size_kb * vmstat.free_count); + stats.add("Pages active KB", page_size_kb * vmstat.active_count); + stats.add("Pages inactive KB", page_size_kb * vmstat.inactive_count); + stats.add("Pages wired KB", page_size_kb * vmstat.wire_count); stats.add("Pages zero fill", vmstat.zero_fill_count); stats.add("Page reactivations", vmstat.reactivations); @@ -1204,20 +1009,20 @@ LLSD LLMemoryInfo::loadStatsMap() // { - task_basic_info_64_data_t taskinfo; - unsigned taskinfoSize = sizeof(taskinfo); - - if (task_info(mach_task_self(), TASK_BASIC_INFO_64, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS) + mach_task_basic_info_data_t taskinfo; + mach_msg_type_number_t task_count = MACH_TASK_BASIC_INFO_COUNT; + if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t) &taskinfo, &task_count) != KERN_SUCCESS) { - LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL; - } - else - { - stats.add("Basic suspend count", taskinfo.suspend_count); - stats.add("Basic virtual memory KB", taskinfo.virtual_size / 1024); - stats.add("Basic resident memory KB", taskinfo.resident_size / 1024); - stats.add("Basic new thread policy", taskinfo.policy); - } + LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL; + } + else + { + stats.add("Basic virtual memory KB", taskinfo.virtual_size / 1024); + stats.add("Basic resident memory KB", taskinfo.resident_size / 1024); + stats.add("Basic max resident memory KB", taskinfo.resident_size_max / 1024); + stats.add("Basic new thread policy", taskinfo.policy); + stats.add("Basic suspend count", taskinfo.suspend_count); + } } #elif LL_SOLARIS @@ -1327,7 +1132,8 @@ class FrameWatcher // Hooking onto the "mainloop" event pump gets us one call per frame. mConnection(LLEventPumps::instance() .obtain("mainloop") - .listen("FrameWatcher", boost::bind(&FrameWatcher::tick, this, _1))), + .listen("FrameWatcher", std::bind(&FrameWatcher::tick, this, std::placeholders::_1))), + // Initializing mSampleStart to an invalid timestamp alerts us to skip // trying to compute framerate on the first call. mSampleStart(-1), @@ -1468,18 +1274,22 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile) const S32 UNCOMPRESS_BUFFER_SIZE = 32768; BOOL retval = FALSE; gzFile src = NULL; - U8 buffer[UNCOMPRESS_BUFFER_SIZE]; + std::array buffer; LLFILE *dst = NULL; S32 bytes = 0; tmpfile = dstfile + ".t"; +#if LL_WINDOWS + src = gzopen_w(utf8str_to_utf16str(srcfile).c_str(), "rb"); +#else src = gzopen(srcfile.c_str(), "rb"); +#endif if (! src) goto err; dst = LLFile::fopen(tmpfile, "wb"); /* Flawfinder: ignore */ if (! dst) goto err; do { - bytes = gzread(src, buffer, UNCOMPRESS_BUFFER_SIZE); - size_t nwrit = fwrite(buffer, sizeof(U8), bytes, dst); + bytes = gzread(src, buffer.data(), buffer.size()); + size_t nwrit = fwrite(buffer.data(), sizeof(U8), bytes, dst); if (nwrit < (size_t) bytes) { LL_WARNS() << "Short write on " << tmpfile << ": Wrote " << nwrit << " of " << bytes << " bytes." << LL_ENDL; @@ -1501,19 +1311,23 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile) const S32 COMPRESS_BUFFER_SIZE = 32768; std::string tmpfile; BOOL retval = FALSE; - U8 buffer[COMPRESS_BUFFER_SIZE]; + std::array buffer; gzFile dst = NULL; LLFILE *src = NULL; S32 bytes = 0; tmpfile = dstfile + ".t"; +#if LL_WINDOWS + dst = gzopen_w(utf8str_to_utf16str(tmpfile).c_str(), "wb"); +#else dst = gzopen(tmpfile.c_str(), "wb"); /* Flawfinder: ignore */ +#endif if (! dst) goto err; src = LLFile::fopen(srcfile, "rb"); /* Flawfinder: ignore */ if (! src) goto err; - while ((bytes = (S32)fread(buffer, sizeof(U8), COMPRESS_BUFFER_SIZE, src)) > 0) + while ((bytes = (S32)fread(buffer.data(), sizeof(U8), buffer.size(), src)) > 0) { - if (gzwrite(dst, buffer, bytes) <= 0) + if (gzwrite(dst, buffer.data(), bytes) <= 0) { LL_WARNS() << "gzwrite failed: " << gzerror(dst, NULL) << LL_ENDL; goto err; diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index 52b884e5af..d963199419 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -112,15 +112,10 @@ class LL_COMMON_API LLMemoryInfo LLMemoryInfo(); ///< Default constructor void stream(std::ostream& s) const; ///< output text info to s - U32 getPhysicalMemoryKB() const; ///< Memory size in KiloBytes + U32Kilobytes getPhysicalMemoryKB() const; - /*! Memory size in bytes, if total memory is >= 4GB then U32_MAX will - ** be returned. - */ - U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes - //get the available memory infomation in KiloBytes. - static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb); + static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb); // Retrieve a map of memory statistics. The keys of the map are platform- // dependent. The values are in kilobytes to try to avoid integer overflow. diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 3c72bd3e25..7b6fec9f27 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -467,24 +467,24 @@ void LLConditionVariableImpl::wait(LLMutex& lock) #endif #endif -LLFastTimer::DeclareTimer FT_WAIT_FOR_MUTEX("LLMutex::lock()"); -void LLMutex::lock_main(LLFastTimer::DeclareTimer* timer) +LLTrace::BlockTimerStatHandle FT_WAIT_FOR_MUTEX("LLMutex::lock()"); +void LLMutex::lock_main(LLTrace::BlockTimerStatHandle* timer) { llassert(!isSelfLocked()); - LLFastTimer ft1(timer ? *timer : FT_WAIT_FOR_MUTEX); + LL_RECORD_BLOCK_TIME(timer ? *timer : FT_WAIT_FOR_MUTEX); LLMutexImpl::lock(); } -LLFastTimer::DeclareTimer FT_WAIT_FOR_CONDITION("LLCondition::wait()"); +LLTrace::BlockTimerStatHandle FT_WAIT_FOR_CONDITION("LLCondition::wait()"); void LLCondition::wait_main() { llassert(isSelfLocked()); - LLFastTimer ft1(FT_WAIT_FOR_CONDITION); + LL_RECORD_BLOCK_TIME(FT_WAIT_FOR_CONDITION); LLConditionVariableImpl::wait(*this); llassert(isSelfLocked()); } -LLFastTimer::DeclareTimer FT_WAIT_FOR_MUTEXLOCK("LLMutexLock::lock()"); +LLTrace::BlockTimerStatHandle FT_WAIT_FOR_MUTEXLOCK("LLMutexLock::lock()"); void LLMutexLock::lock() { if (mMutex) diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 33b6e9809c..bf0f26f778 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -201,7 +201,7 @@ class LL_COMMON_API LLThread #include typedef boost::recursive_mutex LLMutexImpl; typedef boost::condition_variable_any LLConditionVariableImpl; -#elif defined(USE_STD_MUTEX) && LL_CPP11 +#elif defined(USE_STD_MUTEX) #include typedef std::recursive_mutex LLMutexImpl; typedef std::condition_variable_any LLConditionVariableImpl; @@ -269,7 +269,7 @@ class LL_COMMON_API LLMutex : public LLMutexImpl ~LLMutex() {} - void lock(LLFastTimer::DeclareTimer* timer = NULL) // blocks + void lock(LLTrace::BlockTimerStatHandle* timer = NULL) // blocks { if (inc_lock_if_recursive()) return; @@ -384,7 +384,7 @@ class LL_COMMON_API LLMutex : public LLMutexImpl #endif private: - void lock_main(LLFastTimer::DeclareTimer* timer); + void lock_main(LLTrace::BlockTimerStatHandle* timer); bool inc_lock_if_recursive() { diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 1ef4aa4145..e458cc66a9 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -31,11 +31,9 @@ #include "u64.h" #if LL_WINDOWS -# define WIN32_LEAN_AND_MEAN -# include -# include +# include "llwin32headerslean.h" #elif LL_LINUX || LL_SOLARIS || LL_DARWIN -# include +# include # include #else # error "architecture not supported" @@ -81,10 +79,10 @@ void ms_sleep(U32 ms) U32 micro_sleep(U64 us, U32 max_yields) { - // max_yields is unused; just fiddle with it to avoid warnings. - max_yields = 0; - ms_sleep(us / 1000); - return 0; + // max_yields is unused; just fiddle with it to avoid warnings. + max_yields = 0; + ms_sleep((U32)(us / 1000)); + return 0; } #elif LL_LINUX || LL_SOLARIS || LL_DARWIN static void _sleep_loop(struct timespec& thiswait) @@ -216,56 +214,68 @@ U64 get_clock_count() #endif -void update_clock_frequencies() +TimerInfo::TimerInfo() +: mClockFrequency(0.0), + mTotalTimeClockCount(0), + mLastTotalTimeClockCount(0) +{} + +void TimerInfo::update() { - gClockFrequency = calc_clock_frequency(); - gClockFrequencyInv = 1.0/gClockFrequency; - gClocksToMicroseconds = gClockFrequencyInv * SEC_TO_MICROSEC; + mClockFrequency = calc_clock_frequency(); + mClockFrequencyInv = 1.0/mClockFrequency; + mClocksToMicroseconds = mClockFrequencyInv; } +TimerInfo& get_timer_info() +{ + static TimerInfo sTimerInfo; + return sTimerInfo; +} /////////////////////////////////////////////////////////////////////////////// // returns a U64 number that represents the number of // microseconds since the Unix epoch - Jan 1, 1970 -U64 totalTime() +U64MicrosecondsImplicit totalTime() { U64 current_clock_count = get_clock_count(); - if (!gTotalTimeClockCount) + if (!get_timer_info().mTotalTimeClockCount || get_timer_info().mClocksToMicroseconds.value() == 0) { - update_clock_frequencies(); - gTotalTimeClockCount = current_clock_count; + get_timer_info().update(); + get_timer_info().mTotalTimeClockCount = current_clock_count; #if LL_WINDOWS - // Synch us up with local time (even though we PROBABLY don't need to, this is how it was implemented) + // Sync us up with local time (even though we PROBABLY don't need to, this is how it was implemented) // Unix platforms use gettimeofday so they are synced, although this probably isn't a good assumption to // make in the future. - gTotalTimeClockCount = (U64)(time(NULL) * gClockFrequency); + get_timer_info().mTotalTimeClockCount = (U64)(time(NULL) * get_timer_info().mClockFrequency); #endif // Update the last clock count - gLastTotalTimeClockCount = current_clock_count; + get_timer_info().mLastTotalTimeClockCount = current_clock_count; } else { - if (LL_LIKELY(current_clock_count >= gLastTotalTimeClockCount)) + if (current_clock_count >= get_timer_info().mLastTotalTimeClockCount) { // No wrapping, we're all okay. - gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount; + get_timer_info().mTotalTimeClockCount += current_clock_count - get_timer_info().mLastTotalTimeClockCount; } else { // We've wrapped. Compensate correctly - gTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - gLastTotalTimeClockCount) + current_clock_count; + get_timer_info().mTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - get_timer_info().mLastTotalTimeClockCount) + current_clock_count; } // Update the last clock count - gLastTotalTimeClockCount = current_clock_count; + get_timer_info().mLastTotalTimeClockCount = current_clock_count; } // Return the total clock tick count in microseconds. - return (U64)(gTotalTimeClockCount*gClocksToMicroseconds); + U64Microseconds time(get_timer_info().mTotalTimeClockCount*get_timer_info().mClocksToMicroseconds); + return time; } @@ -273,9 +283,9 @@ U64 totalTime() LLTimer::LLTimer() { - if (!gClockFrequency) + if (!get_timer_info().mClockFrequency) { - update_clock_frequencies(); + get_timer_info().update(); } mStarted = TRUE; @@ -283,20 +293,32 @@ LLTimer::LLTimer() } LLTimer::~LLTimer() +{} + +// static +void LLTimer::initClass() +{ + if (!sTimer) sTimer = new LLTimer; +} + +// static +void LLTimer::cleanupClass() { + delete sTimer; sTimer = NULL; } // static -U64 LLTimer::getTotalTime() +U64MicrosecondsImplicit LLTimer::getTotalTime() { // simply call into the implementation function. - return totalTime(); + U64MicrosecondsImplicit total_time = totalTime(); + return total_time; } // static -F64 LLTimer::getTotalSeconds() +F64SecondsImplicit LLTimer::getTotalSeconds() { - return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64; + return F64Microseconds(U64_to_F64(getTotalTime())); } void LLTimer::reset() @@ -343,43 +365,43 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount) } -F64 LLTimer::getElapsedTimeF64() const +F64SecondsImplicit LLTimer::getElapsedTimeF64() const { U64 last = mLastClockCount; - return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv; + return (F64)getElapsedTimeAndUpdate(last) * get_timer_info().mClockFrequencyInv; } -F32 LLTimer::getElapsedTimeF32() const +F32SecondsImplicit LLTimer::getElapsedTimeF32() const { return (F32)getElapsedTimeF64(); } -F64 LLTimer::getElapsedTimeAndResetF64() +F64SecondsImplicit LLTimer::getElapsedTimeAndResetF64() { - return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv; + return (F64)getElapsedTimeAndUpdate(mLastClockCount) * get_timer_info().mClockFrequencyInv; } -F32 LLTimer::getElapsedTimeAndResetF32() +F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32() { return (F32)getElapsedTimeAndResetF64(); } /////////////////////////////////////////////////////////////////////////////// -void LLTimer::setTimerExpirySec(F32 expiration) +void LLTimer::setTimerExpirySec(F32SecondsImplicit expiration) { mExpirationTicks = get_clock_count() - + (U64)((F32)(expiration * gClockFrequency)); + + (U64)((F32)(expiration * get_timer_info().mClockFrequency.value())); } -F32 LLTimer::getRemainingTimeF32() const +F32SecondsImplicit LLTimer::getRemainingTimeF32() const { U64 cur_ticks = get_clock_count(); if (cur_ticks > mExpirationTicks) { return 0.0f; } - return F32((mExpirationTicks - cur_ticks) * gClockFrequencyInv); + return F32((mExpirationTicks - cur_ticks) * get_timer_info().mClockFrequencyInv); } @@ -392,7 +414,7 @@ BOOL LLTimer::checkExpirationAndReset(F32 expiration) } mExpirationTicks = cur_ticks - + (U64)((F32)(expiration * gClockFrequency)); + + (U64)((F32)(expiration * get_timer_info().mClockFrequency)); return TRUE; } @@ -491,20 +513,20 @@ BOOL is_daylight_savings() struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time) { - S32 pacific_offset_hours; + S32Hours pacific_offset_hours; if (pacific_daylight_time) { - pacific_offset_hours = 7; + pacific_offset_hours = S32Hours(7); } else { - pacific_offset_hours = 8; + pacific_offset_hours = S32Hours(8); } // We subtract off the PST/PDT offset _before_ getting // "UTC" time, because this will handle wrapping around // for 5 AM UTC -> 10 PM PDT of the previous day. - utc_time -= pacific_offset_hours * MIN_PER_HOUR * SEC_PER_MIN; + utc_time -= S32SecondsImplicit(pacific_offset_hours); // Internal buffer to PST/PDT (see above) struct tm* internal_time = gmtime(&utc_time); @@ -521,7 +543,7 @@ struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time) } -void microsecondsToTimecodeString(U64 current_time, std::string& tcstring) +void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring) { U64 hours; U64 minutes; @@ -543,9 +565,9 @@ void microsecondsToTimecodeString(U64 current_time, std::string& tcstring) } -void secondsToTimecodeString(F32 current_time, std::string& tcstring) +void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring) { - microsecondsToTimecodeString((U64)((F64)(SEC_TO_MICROSEC*current_time)), tcstring); + microsecondsToTimecodeString(current_time, tcstring); } diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 0d2e8e86de..d43267bb66 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -37,6 +37,7 @@ #include #include // units conversions +#include "llunits.h" #ifndef USEC_PER_SEC const U32 USEC_PER_SEC = 1000000; #endif @@ -61,21 +62,28 @@ class LL_COMMON_API LLTimer LLTimer(); ~LLTimer(); - static void initClass() { if (!sTimer) sTimer = new LLTimer; } - static void cleanupClass() { delete sTimer; sTimer = NULL; } + static void initClass(); + static void cleanupClass(); // Return a high precision number of seconds since the start of // this application instance. - static F64 getElapsedSeconds() + static F64SecondsImplicit getElapsedSeconds() + { + if (sTimer) { return sTimer->getElapsedTimeF64(); } + else + { + return 0; + } + } // Return a high precision usec since epoch - static U64 getTotalTime(); + static U64MicrosecondsImplicit getTotalTime(); // Return a high precision seconds since epoch - static F64 getTotalSeconds(); + static F64SecondsImplicit getTotalSeconds(); // MANIPULATORS @@ -83,19 +91,19 @@ class LL_COMMON_API LLTimer void stop() { mStarted = FALSE; } void reset(); // Resets the timer void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time - void setTimerExpirySec(F32 expiration); + void setTimerExpirySec(F32SecondsImplicit expiration); BOOL checkExpirationAndReset(F32 expiration); BOOL hasExpired() const; - F32 getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset - F64 getElapsedTimeAndResetF64(); + F32SecondsImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset + F64SecondsImplicit getElapsedTimeAndResetF64(); - F32 getRemainingTimeF32() const; + F32SecondsImplicit getRemainingTimeF32() const; static BOOL knownBadTimer(); // ACCESSORS - F32 getElapsedTimeF32() const; // Returns elapsed time in seconds - F64 getElapsedTimeF64() const; // Returns elapsed time in seconds + F32SecondsImplicit getElapsedTimeF32() const; // Returns elapsed time in seconds + F64SecondsImplicit getElapsedTimeF64() const; // Returns elapsed time in seconds bool getStarted() const { return mStarted; } @@ -106,6 +114,20 @@ class LL_COMMON_API LLTimer // // Various functions for initializing/accessing clock and timing stuff. Don't use these without REALLY knowing how they work. // +struct TimerInfo +{ + TimerInfo(); + void update(); + + F64HertzImplicit mClockFrequency; + F64SecondsImplicit mClockFrequencyInv; + F64MicrosecondsImplicit mClocksToMicroseconds; + U64 mTotalTimeClockCount; + U64 mLastTotalTimeClockCount; +}; + +TimerInfo& get_timer_info(); + LL_COMMON_API U64 get_clock_count(); LL_COMMON_API F64 calc_clock_frequency(); LL_COMMON_API void update_clock_frequencies(); @@ -160,10 +182,10 @@ LL_COMMON_API BOOL is_daylight_savings(); // struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight); LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time); -LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring); -LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring); +LL_COMMON_API void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring); +LL_COMMON_API void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring); LL_COMMON_API void timeToFormattedString(time_t time, std::string format, std::string ×tr); LL_COMMON_API void timeStructToFormattedString(struct tm * time, std::string format, std::string ×tr); -U64 LL_COMMON_API totalTime(); // Returns current system time in microseconds +U64MicrosecondsImplicit LL_COMMON_API totalTime(); // Returns current system time in microseconds #endif diff --git a/indra/llcommon/lltreeiterators.h b/indra/llcommon/lltreeiterators.h index 6aea5f7cce..19258a9642 100644 --- a/indra/llcommon/lltreeiterators.h +++ b/indra/llcommon/lltreeiterators.h @@ -63,10 +63,6 @@ #include #include #include -#ifndef BOOST_FUNCTION_HPP_INCLUDED -#include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif #include namespace LLTreeIter @@ -96,7 +92,7 @@ class LLBaseIter: public boost::iterator_facade::type ptr_type; /// function that advances from this node to next accepts a node pointer /// and returns another - typedef boost::function func_type; + typedef std::function func_type; typedef SELFTYPE self_type; }; @@ -333,7 +329,7 @@ class LLTreeDFSIter: public LLBaseIter, NODE> typedef typename super::ptr_type ptr_type; // The func_type is different for this: from a NODE pointer, we must // obtain a CHILDITER. - typedef boost::function func_type; + typedef std::function func_type; private: typedef std::vector list_type; public: @@ -438,7 +434,7 @@ class LLTreeDFSPostIter: public LLBaseIter, N typedef typename super::ptr_type ptr_type; // The func_type is different for this: from a NODE pointer, we must // obtain a CHILDITER. - typedef boost::function func_type; + typedef std::function func_type; private: // Upon reaching a given node in our pending list, we need to know whether // we've already pushed that node's children, so we must associate a bool @@ -503,14 +499,17 @@ class LLTreeDFSPostIter: public LLBaseIter, N // Once we've popped the last node, this becomes a no-op. if (mPending.empty()) return; + + auto& pending = mPending.back(); + // Here mPending.back() holds the node pointer we're proposing to // dereference next. Have we pushed that node's children yet? - if (mPending.back().second) + if (pending.second) return; // if so, it's okay to visit this node now // We haven't yet pushed this node's children. Do so now. Remember // that we did -- while the node in question is still back(). - mPending.back().second = true; - addChildren(mPending.back().first); + pending.second = true; + addChildren(pending.first); // Now, because we've just changed mPending.back(), make that new node // current. makeCurrent(); @@ -577,7 +576,7 @@ class LLTreeBFSIter: public LLBaseIter, NODE> typedef typename super::ptr_type ptr_type; // The func_type is different for this: from a NODE pointer, we must // obtain a CHILDITER. - typedef boost::function func_type; + typedef std::function func_type; private: // We need a FIFO queue rather than a LIFO stack. Use a deque rather than // a vector, since vector can't implement pop_front() efficiently. diff --git a/indra/llcommon/llunits.h b/indra/llcommon/llunits.h new file mode 100644 index 0000000000..0fcb8281a0 --- /dev/null +++ b/indra/llcommon/llunits.h @@ -0,0 +1,129 @@ +/** + * @file llunits.h + * @brief Unit definitions + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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_LLUNITTYPE_H +#define LL_LLUNITTYPE_H + +#include "stdtypes.h" +#include "llunittype.h" + +// +// Unit declarations +// + +namespace LLUnits +{ +LL_DECLARE_BASE_UNIT(Bytes, "B"); +// technically, these are kibibytes, mibibytes, etc. but we should stick with commonly accepted terminology +LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, / 1024); +LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Kilobytes, / 1024); +LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Megabytes, / 1024); +} + +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bytes); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobytes); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabytes); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabytes); + +namespace LLUnits +{ +// technically, these are kibibits, mibibits, etc. but we should stick with commonly accepted terminology +LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, * 8 ); +LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bits, / 1024); +LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Kilobits, / 1024); +LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Megabits, / 1024); +} + +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bits); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobits); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabits); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabits); + +namespace LLUnits +{ +LL_DECLARE_BASE_UNIT(Seconds, "s"); +LL_DECLARE_DERIVED_UNIT(Minutes, "min", Seconds, / 60); +LL_DECLARE_DERIVED_UNIT(Hours, "h", Minutes, / 60); +LL_DECLARE_DERIVED_UNIT(Days, "d", Hours, / 24); +LL_DECLARE_DERIVED_UNIT(Milliseconds, "ms", Seconds, * 1000); +LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Milliseconds, * 1000); +LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Microseconds, * 1000); +} + +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Seconds); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Minutes); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hours); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Days); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milliseconds); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Microseconds); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Nanoseconds); + +namespace LLUnits +{ +LL_DECLARE_BASE_UNIT(Meters, "m"); +LL_DECLARE_DERIVED_UNIT(Kilometers, "km", Meters, / 1000); +LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, * 100); +LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, * 1000); +} + +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Meters); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilometers); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Centimeters); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Millimeters); + +namespace LLUnits +{ +// rare units +LL_DECLARE_BASE_UNIT(Hertz, "Hz"); +LL_DECLARE_DERIVED_UNIT(Kilohertz, "KHz", Hertz, / 1000); +LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Kilohertz, / 1000); +LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Megahertz, / 1000); + +LL_DECLARE_BASE_UNIT(Radians, "rad"); +LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 57.29578f); + +LL_DECLARE_BASE_UNIT(Percent, "%"); +LL_DECLARE_DERIVED_UNIT(Ratio, "x", Percent, / 100); + +LL_DECLARE_BASE_UNIT(Triangles, "tris"); +LL_DECLARE_DERIVED_UNIT(Kilotriangles, "ktris", Triangles, / 1000); + +} // namespace LLUnits + +// rare units +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hertz); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilohertz); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megahertz); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigahertz); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Radians); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Degrees); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Percent); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ratio); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Triangles); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilotriangles); + + +#endif // LL_LLUNITTYPE_H diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h new file mode 100644 index 0000000000..81f244e422 --- /dev/null +++ b/indra/llcommon/llunittype.h @@ -0,0 +1,849 @@ +/** + * @file llunit.h + * @brief Unit conversion classes + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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_UNITTYPE_H +#define LL_UNITTYPE_H + +#include "stdtypes.h" +#include "llpreprocessor.h" +#include "llerror.h" + +//lightweight replacement of type traits for simple type equality check +template +struct LLIsSameType +{ + static const bool value = false; +}; + +template +struct LLIsSameType +{ + static const bool value = true; +}; + +// workaround for decltype() not existing and typeof() not working inline in gcc 4.2 +template +struct LLResultTypeAdd +{ + typedef LL_TYPEOF(S() + T()) type_t; +}; + +template +struct LLResultTypeSubtract +{ + typedef LL_TYPEOF(S() - T()) type_t; +}; + +template +struct LLResultTypeMultiply +{ + typedef LL_TYPEOF(S() * T()) type_t; +}; + +template +struct LLResultTypeDivide +{ + typedef LL_TYPEOF(S() / T(1)) type_t; +}; + +template +struct LLResultTypePromote +{ + typedef LL_TYPEOF((true) ? S() : T()) type_t; +}; + +template +struct LLUnit +{ + typedef LLUnit self_t; + typedef STORAGE_TYPE storage_t; + typedef void is_unit_t; + + // value initialization + LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t()) + : mValue(value) + {} + + + LL_FORCE_INLINE static self_t convert(self_t v) + { + return v; + } + + template + LL_FORCE_INLINE static self_t convert(LLUnit v) + { + self_t result; + result.mValue = (STORAGE_TYPE)v.value(); + return result; + } + + template + LL_FORCE_INLINE static self_t convert(LLUnit v) + { + self_t result; + STORAGE_TYPE divisor = ll_convert_units(v, result); + result.mValue /= divisor; + return result; + } + + template + LL_FORCE_INLINE static self_t convert(LLUnit v) + { + typedef typename LLResultTypePromote::type_t result_storage_t; + LLUnit result; + result_storage_t divisor = ll_convert_units(v, result); + result.value(result.value() / divisor); + return self_t(result.value()); + } + + + // unit initialization and conversion + template + LL_FORCE_INLINE LLUnit(LLUnit other) + : mValue(convert(other).mValue) + {} + + LL_FORCE_INLINE storage_t value() const + { + return mValue; + } + + LL_FORCE_INLINE void value(const storage_t& value) + { + mValue = value; + } + + template + storage_t valueInUnits() const + { + return LLUnit(*this).value(); + } + + template + void valueInUnits(const storage_t& value) const + { + *this = LLUnit(value); + } + + LL_FORCE_INLINE operator storage_t() const + { + return value(); + } + + /*LL_FORCE_INLINE self_t& operator= (storage_t v) + { + value(v); + return *this; + }*/ + + LL_FORCE_INLINE void operator += (self_t other) + { + mValue += convert(other).mValue; + } + + LL_FORCE_INLINE void operator -= (self_t other) + { + mValue -= convert(other).mValue; + } + + LL_FORCE_INLINE void operator *= (const storage_t& multiplicand) + { + mValue *= multiplicand; + } + + LL_FORCE_INLINE void operator *= (const self_t& multiplicand) + { + // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported."); + } + + LL_FORCE_INLINE void operator /= (const storage_t& divisor) + { + mValue /= divisor; + } + + void operator /= (const self_t& divisor) + { + // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types."); + } + + template + LL_FORCE_INLINE bool operator == (const LLUnit& other) const + { + return mValue == convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator != (const LLUnit& other) const + { + return mValue != convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator < (const LLUnit& other) const + { + return mValue < convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator <= (const LLUnit& other) const + { + return mValue <= convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator > (const LLUnit& other) const + { + return mValue > convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator >= (const LLUnit& other) const + { + return mValue >= convert(other).value(); + } + +protected: + storage_t mValue; +}; + +template +std::ostream& operator <<(std::ostream& s, const LLUnit& unit) +{ + s << unit.value() << UNITS::getUnitLabel(); + return s; +} + +template +std::istream& operator >>(std::istream& s, LLUnit& unit) +{ + STORAGE_TYPE val; + s >> val; + unit.value(val); + return s; +} + +template +struct LLUnitImplicit : public LLUnit +{ + typedef LLUnitImplicit self_t; + typedef typename LLUnit::storage_t storage_t; + typedef LLUnit base_t; + + LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t()) + : base_t(value) + {} + + template + LL_FORCE_INLINE LLUnitImplicit(LLUnit other) + : base_t(other) + {} + + // unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc) + // this allows for interoperability with legacy code + LL_FORCE_INLINE operator storage_t() const + { + return base_t::value(); + } + + using base_t::operator +=; + LL_FORCE_INLINE void operator += (storage_t value) + { + base_t::mValue += value; + } + + // this overload exists to explicitly catch use of another implicit unit + // without ambiguity between conversion to storage_t vs conversion to base_t + template + LL_FORCE_INLINE void operator += (LLUnitImplicit other) + { + base_t::mValue += base_t::convert(other).value(); + } + + using base_t::operator -=; + LL_FORCE_INLINE void operator -= (storage_t value) + { + base_t::mValue -= value; + } + + // this overload exists to explicitly catch use of another implicit unit + // without ambiguity between conversion to storage_t vs conversion to base_t + template + LL_FORCE_INLINE void operator -= (LLUnitImplicit other) + { + base_t::mValue -= base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator == (LLUnit other) const + { + return base_t::mValue == base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator == (LLUnitImplicit other) const + { + return base_t::mValue == base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator == (STORAGE_T other) const + { + return base_t::mValue == other; + } + + template + LL_FORCE_INLINE bool operator != (LLUnit other) const + { + return base_t::mValue != convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator != (LLUnitImplicit other) const + { + return base_t::mValue != base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator != (STORAGE_T other) const + { + return base_t::mValue != other; + } + + template + LL_FORCE_INLINE bool operator < (LLUnit other) const + { + return base_t::mValue < base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator < (LLUnitImplicit other) const + { + return base_t::mValue < base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator < (STORAGE_T other) const + { + return base_t::mValue < other; + } + + template + LL_FORCE_INLINE bool operator <= (LLUnit other) const + { + return base_t::mValue <= base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator <= (LLUnitImplicit other) const + { + return base_t::mValue <= base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator <= (STORAGE_T other) const + { + return base_t::mValue <= other; + } + + template + LL_FORCE_INLINE bool operator > (LLUnit other) const + { + return base_t::mValue > base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator > (LLUnitImplicit other) const + { + return base_t::mValue > base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator > (STORAGE_T other) const + { + return base_t::mValue > other; + } + + template + LL_FORCE_INLINE bool operator >= (LLUnit other) const + { + return base_t::mValue >= base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator >= (LLUnitImplicit other) const + { + return base_t::mValue >= base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator >= (STORAGE_T other) const + { + return base_t::mValue >= other; + } +}; + +template +std::ostream& operator <<(std::ostream& s, const LLUnitImplicit& unit) +{ + s << unit.value() << UNITS::getUnitLabel(); + return s; +} + +template +std::istream& operator >>(std::istream& s, LLUnitImplicit& unit) +{ + STORAGE_TYPE val; + s >> val; + unit = val; + return s; +} + +template +LL_FORCE_INLINE S2 ll_convert_units(LLUnit in, LLUnit& out) +{ + S2 divisor(1); + + LL_STATIC_ASSERT((LLIsSameType::value + || !LLIsSameType::value + || !LLIsSameType::value), + "conversion requires compatible units"); + + if (LLIsSameType::value) + { + // T1 and T2 same type, just assign + out.value((S2)in.value()); + } + else if (T1::sLevel > T2::sLevel) + { + // reduce T1 + LLUnit new_in; + divisor *= (S2)ll_convert_units(in, new_in); + divisor *= (S2)ll_convert_units(new_in, out); + } + else + { + // reduce T2 + LLUnit new_out; + divisor *= (S2)ll_convert_units(in, new_out); + divisor *= (S2)ll_convert_units(new_out, out); + } + return divisor; +} + +template +struct LLStorageType +{ + typedef T type_t; +}; + +template +struct LLStorageType > +{ + typedef STORAGE_TYPE type_t; +}; + +// all of these operators need to perform type promotion on the storage type of the units, so they +// cannot be expressed as operations on identical types with implicit unit conversion +// e.g. typeof(S32Bytes(x) + F32Megabytes(y)) <==> F32Bytes + +// +// operator + +// +template +LL_FORCE_INLINE LLUnit::type_t, UNITS1> operator + (LLUnit first, LLUnit second) +{ + LLUnit::type_t, UNITS1> result(first); + result += second; + return result; +} + +template +LLUnit operator + (LLUnit first, UNITLESS second) +{ + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types"); + return LLUnit(0); +} + +template +LLUnit operator + (UNITLESS first, LLUnit second) +{ + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types"); + return LLUnit(0); +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator + (LLUnitImplicit first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result += second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator + (LLUnit first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result += second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator + (LLUnitImplicit first, LLUnit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result += LLUnitImplicit(second); + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t>::type_t, UNITS> operator + (LLUnitImplicit first, UNITLESS_TYPE second) +{ + LLUnitImplicit::type_t>::type_t, UNITS> result(first); + result += second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, STORAGE_TYPE>:: + type_t, UNITS> operator + (UNITLESS_TYPE first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, STORAGE_TYPE>::type_t, UNITS> result(first); + result += second; + return result; +} + +// +// operator - +// +template +LL_FORCE_INLINE LLUnit::type_t, UNITS1> operator - (LLUnit first, LLUnit second) +{ + LLUnit::type_t, UNITS1> result(first); + result -= second; + return result; +} + +template +LLUnit operator - (LLUnit first, UNITLESS second) +{ + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types"); + return LLUnit(0); +} + +template +LLUnit operator - (UNITLESS first, LLUnit second) +{ + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types"); + return LLUnit(0); +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator - (LLUnitImplicit first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result -= second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator - (LLUnit first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result -= second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator - (LLUnitImplicit first, LLUnit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result -= LLUnitImplicit(second); + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t>::type_t, UNITS> operator - (LLUnitImplicit first, UNITLESS_TYPE second) +{ + LLUnitImplicit::type_t>::type_t, UNITS> result(first); + result -= second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, STORAGE_TYPE>::type_t, UNITS> operator - (UNITLESS_TYPE first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, STORAGE_TYPE>::type_t, UNITS> result(first); + result -= second; + return result; +} + +// +// operator * +// +template +LLUnit operator * (LLUnit, LLUnit) +{ + // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported."); + return LLUnit(); +} + +template +LL_FORCE_INLINE LLUnit::type_t>::type_t, UNITS> operator * (LLUnit first, UNITLESS_TYPE second) +{ + return LLUnit::type_t>::type_t, UNITS>(first.value() * second); +} + +template +LL_FORCE_INLINE LLUnit::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnit second) +{ + return LLUnit::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value()); +} + +template +LLUnitImplicit operator * (LLUnitImplicit, LLUnitImplicit) +{ + // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported."); + return LLUnitImplicit(); +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t>::type_t, UNITS> operator * (LLUnitImplicit first, UNITLESS_TYPE second) +{ + return LLUnitImplicit::type_t, UNITS>(first.value() * second); +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnitImplicit second) +{ + return LLUnitImplicit::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value()); +} + + +// +// operator / +// + +template +LL_FORCE_INLINE LLUnit::type_t>::type_t, UNITS> operator / (LLUnit first, UNITLESS_TYPE second) +{ + return LLUnit::type_t>::type_t, UNITS>(first.value() / second); +} + +template +LL_FORCE_INLINE typename LLResultTypeDivide::type_t operator / (LLUnit first, LLUnit second) +{ + return first.value() / first.convert(second).value(); +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t>::type_t, UNITS> operator / (LLUnitImplicit first, UNITLESS_TYPE second) +{ + return LLUnitImplicit::type_t>::type_t, UNITS>(first.value() / second); +} + +template +LL_FORCE_INLINE typename LLResultTypeDivide::type_t operator / (LLUnitImplicit first, LLUnitImplicit second) +{ + return (typename LLResultTypeDivide::type_t)(first.value() / first.convert(second).value()); +} + +template +LL_FORCE_INLINE typename LLResultTypeDivide::type_t operator / (LLUnit first, LLUnitImplicit second) +{ + return (typename LLResultTypeDivide::type_t)(first.value() / first.convert(second).value()); +} + +template +LL_FORCE_INLINE typename LLResultTypeDivide::type_t operator / (LLUnitImplicit first, LLUnit second) +{ + return (typename LLResultTypeDivide::type_t)(first.value() / first.convert(second).value()); +} + +template +struct LLGetUnitLabel +{ + static const char* getUnitLabel() { return ""; } +}; + +template +struct LLGetUnitLabel > +{ + static const char* getUnitLabel() { return T::getUnitLabel(); } +}; + +template +struct LLUnitLinearOps +{ + typedef LLUnitLinearOps self_t; + + LLUnitLinearOps(T val) + : mValue(val), + mDivisor(1) + {} + + template + self_t operator * (OTHER_T other) + { + return mValue * other; + } + + template + self_t operator / (OTHER_T other) + { + mDivisor *= other; + return *this; + } + + template + self_t operator + (OTHER_T other) + { + mValue += other * mDivisor; + return *this; + } + + template + self_t operator - (OTHER_T other) + { + mValue -= other * mDivisor; + return *this; + } + + T mValue; + T mDivisor; +}; + +template +struct LLUnitInverseLinearOps +{ + typedef LLUnitInverseLinearOps self_t; + + LLUnitInverseLinearOps(T val) + : mValue(val), + mDivisor(1), + mMultiplicand(1) + {} + + template + self_t operator * (OTHER_T other) + { + mDivisor *= other; + return *this; + } + + template + self_t operator / (OTHER_T other) + { + mValue *= other; + mMultiplicand *= other; + return *this; + } + + template + self_t operator + (OTHER_T other) + { + mValue -= other * mMultiplicand; + return *this; + } + + template + self_t operator - (OTHER_T other) + { + mValue += other * mMultiplicand; + return *this; + } + + T mValue; + T mDivisor; + T mMultiplicand; +}; + +#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \ +struct base_unit_name \ +{ \ + static const int sLevel = 0; \ + typedef base_unit_name base_unit_t; \ + static const char* getUnitLabel() { return unit_label; } \ + template \ + static LLUnit fromValue(T value) { return LLUnit(value); } \ + template \ + static LLUnit fromValue(LLUnit value) \ + { return LLUnit(value); } \ +} + + +#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \ +struct unit_name \ +{ \ + static const int sLevel = base_unit_name::sLevel + 1; \ + typedef base_unit_name base_unit_t; \ + static const char* getUnitLabel() { return unit_label; } \ + template \ + static LLUnit fromValue(T value) { return LLUnit(value); } \ + template \ + static LLUnit fromValue(LLUnit value) \ + { return LLUnit(value); } \ +}; \ + \ +template \ +LL_FORCE_INLINE S2 ll_convert_units(LLUnit in, LLUnit& out) \ +{ \ + typedef typename LLResultTypePromote::type_t result_storage_t; \ + LLUnitInverseLinearOps result = \ + LLUnitInverseLinearOps(in.value()) conversion_operation; \ + out = LLUnit((S2)result.mValue); \ + return result.mDivisor; \ +} \ + \ +template \ +LL_FORCE_INLINE S2 ll_convert_units(LLUnit in, LLUnit& out) \ +{ \ + typedef typename LLResultTypePromote::type_t result_storage_t; \ + LLUnitLinearOps result = \ + LLUnitLinearOps(in.value()) conversion_operation; \ + out = LLUnit((S2)result.mValue); \ + return result.mDivisor; \ +} + +#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name) \ + typedef LLUnit F32##unit_name; \ + typedef LLUnitImplicit F32##unit_name##Implicit;\ + typedef LLUnit F64##unit_name; \ + typedef LLUnitImplicit F64##unit_name##Implicit;\ + typedef LLUnit S32##unit_name; \ + typedef LLUnitImplicit S32##unit_name##Implicit;\ + typedef LLUnit S64##unit_name; \ + typedef LLUnitImplicit S64##unit_name##Implicit;\ + typedef LLUnit U32##unit_name; \ + typedef LLUnitImplicit U32##unit_name##Implicit;\ + typedef LLUnit U64##unit_name; \ + typedef LLUnitImplicit U64##unit_name##Implicit + +#endif //LL_UNITTYPE_H diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index 5588909016..5f5a67a885 100644 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com /** * @file lluri.cpp * @author Phoenix @@ -40,7 +42,8 @@ #include #include -void encode_character(std::ostream& ostr, std::string::value_type val) +// static +void LLURI::encodeCharacter(std::ostream& ostr, std::string::value_type val) { ostr << "%" @@ -95,7 +98,7 @@ std::string LLURI::escape( } else { - encode_character(ostr, c); + encodeCharacter(ostr, c); } } } @@ -106,7 +109,7 @@ std::string LLURI::escape( c = *it; if(allowed.find(c) == std::string::npos) { - encode_character(ostr, c); + encodeCharacter(ostr, c); } else { @@ -129,11 +132,30 @@ std::string LLURI::unescape(const std::string& str) { ++it; if(it == end) break; - U8 c = hex_as_nybble(*it++); - c = c << 4; - if (it == end) break; - c |= hex_as_nybble(*it); - ostr.put((char)c); + + if(is_char_hex(*it)) + { + U8 c = hex_as_nybble(*it++); + + c = c << 4; + if (it == end) break; + + if(is_char_hex(*it)) + { + c |= hex_as_nybble(*it); + ostr.put((char)c); + } + else + { + ostr.put((char)c); + ostr.put(*it); + } + } + else + { + ostr.put('%'); + ostr.put(*it); + } } else { @@ -169,11 +191,10 @@ namespace { return LLURI::escape(s, unreserved() + ":@!$'()*+,="); } // sub_delims - "&;" + ":@" } -// *TODO: Consider using curl. After http textures gets merged everywhere. // static std::string LLURI::escape(const std::string& str) { - static std::string default_allowed(unreserved() + ":@!$'()*+,=/?&#;"); + static std::string default_allowed = unreserved(); static bool initialized = false; if(!initialized) { @@ -191,10 +212,9 @@ LLURI::LLURI(const std::string& escaped_str) { std::string::size_type delim_pos; delim_pos = escaped_str.find(':'); - std::string temp; if (delim_pos == std::string::npos) { - mScheme = ""; + mScheme.clear(); mEscapedOpaque = escaped_str; } else @@ -229,7 +249,8 @@ void LLURI::parseAuthorityAndPathUsingOpaque() { if (mScheme == "http" || mScheme == "https" || mScheme == "ftp" || mScheme == "secondlife" || - mScheme == "x-grid-location-info") + mScheme == "x-grid-info" || + mScheme == "x-grid-location-info") // legacy { if (mEscapedOpaque.substr(0,2) != "//") { @@ -244,7 +265,7 @@ void LLURI::parseAuthorityAndPathUsingOpaque() delim_pos2 == std::string::npos) { mEscapedAuthority = mEscapedOpaque.substr(2); - mEscapedPath = ""; + mEscapedPath.clear(); } // path exist, no query else if (delim_pos2 == std::string::npos) @@ -402,6 +423,15 @@ LLURI LLURI::buildHTTP(const std::string& prefix, return uri; } +// static +LLURI LLURI::buildHTTP(const std::string& scheme, + const std::string& prefix, + const LLSD& path, + const LLSD& query) +{ + return buildHTTP(llformat("%s://%s", scheme.c_str(), prefix.c_str()), path, query); +} + // static LLURI LLURI::buildHTTP(const std::string& host, const U32& port, @@ -456,7 +486,7 @@ namespace { std::string::size_type start_pos = authority.find('@'); if (start_pos == std::string::npos) { - user = ""; + user.clear(); start_pos = 0; } else @@ -469,7 +499,7 @@ namespace { if (end_pos == std::string::npos) { host = authority.substr(start_pos); - port = ""; + port.clear(); } else { @@ -486,6 +516,14 @@ std::string LLURI::hostName() const return unescape(host); } +std::string LLURI::hostNameAndPort() const +{ + std::string user, host, port; + findAuthorityParts(mEscapedAuthority, user, host, port); + return port.empty() ? unescape(host) : unescape(host + ":" + port); +} + + std::string LLURI::userName() const { std::string user, userPass, host, port; @@ -529,7 +567,7 @@ U16 LLURI::hostPort() const return 21; return 0; } - return atoi(port.c_str()); + return static_cast(std::stoi(port)); } std::string LLURI::path() const @@ -582,7 +620,7 @@ LLSD LLURI::queryMap(std::string escaped_query_string) else { tuple = escaped_query_string; - escaped_query_string = ""; + escaped_query_string .clear(); } if (tuple.empty()) continue; diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h index 57bbedf422..591635a29d 100644 --- a/indra/llcommon/lluri.h +++ b/indra/llcommon/lluri.h @@ -4,31 +4,25 @@ * @date 2006-02-05 * @brief Declaration of the URI class. * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,7 +32,6 @@ #include class LLSD; -class LLUUID; class LLApp; /** @@ -72,6 +65,13 @@ class LL_COMMON_API LLURI const std::string& prefix, const LLSD& path, const LLSD& query); + + static LLURI buildHTTP( + const std::string& scheme, + const std::string& prefix, + const LLSD& path, + const LLSD& query); + ///< prefix is either a full URL prefix of the form /// "http://example.com:8080", or it can be simply a host and /// optional port like "example.com" or "example.com:8080", in @@ -99,20 +99,21 @@ class LL_COMMON_API LLURI std::string scheme() const; ///< ex.: "http", note lack of colon std::string opaque() const; ///< everything after the colon - // for schemes that follow path like syntax (http, https, ftp) - std::string authority() const; // ex.: "host.com:80" - std::string hostName() const; // ex.: "host.com" - std::string userName() const; - std::string password() const; - U16 hostPort() const; // ex.: 80, will include implicit port - BOOL defaultPort() const; // true if port is default for scheme - const std::string& escapedPath() const { return mEscapedPath; } - std::string path() const; // ex.: "/abc/def", includes leading slash - LLSD pathArray() const; // above decoded into an array of strings - std::string query() const; // ex.: "x=34", section after "?" - const std::string& escapedQuery() const { return mEscapedQuery; } - LLSD queryMap() const; // above decoded into a map - static LLSD queryMap(std::string escaped_query_string); + // for schemes that follow path like syntax (http, https, ftp) + std::string authority() const; // ex.: "user:pass@host.com:80" + std::string hostName() const; // ex.: "host.com" + std::string hostNameAndPort() const; // ex.: "host.com:80" + std::string userName() const; + std::string password() const; + U16 hostPort() const; // ex.: 80, will include implicit port + BOOL defaultPort() const; // true if port is default for scheme + const std::string& escapedPath() const { return mEscapedPath; } + std::string path() const; // ex.: "/abc/def", includes leading slash + LLSD pathArray() const; // above decoded into an array of strings + std::string query() const; // ex.: "x=34", section after "?" + const std::string& escapedQuery() const { return mEscapedQuery; } + LLSD queryMap() const; // above decoded into a map + static LLSD queryMap(std::string escaped_query_string); /** * @brief given a name value map, return a serialized query string. @@ -127,27 +128,24 @@ class LL_COMMON_API LLURI /** @name Escaping Utilities */ //@{ /** - * @brief Escape a raw url with a reasonable set of allowed characters. + * @brief 'Escape' symbol into stream * - * The default set was chosen to match HTTP urls and general - * guidelines for naming resources. Passing in a raw url does not - * produce well defined results because you really need to know - * which segments are path parts because path parts are supposed - * to be escaped individually. The default set chosen is: + * @param ostr Output stream. + * @param val Symbol to encode. + */ + static void encodeCharacter(std::ostream& ostr, std::string::value_type val); + + /** + * @brief Escape the string passed except for unreserved * * ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz * 0123456789 * -._~ - * :@!$'()*+,=/?&#; * - * *NOTE: This API is basically broken because it does not - * allow you to specify significant path characters. For example, - * if the filename actually contained a /, then you cannot use - * this function to generate the serialized url for that - * resource. + * @see http://www.ietf.org/rfc/rfc1738.txt * * @param str The raw URI to escape. - * @return Returns the escaped uri or an empty string. + * @return Returns the rfc 1738 escaped uri or an empty string. */ static std::string escape(const std::string& str); diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp new file mode 100644 index 0000000000..e32d9f5c0e --- /dev/null +++ b/indra/llcommon/lluriparser.cpp @@ -0,0 +1,266 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +/** + * @file lluriparser.cpp + * @author Protey + * @date 2014-10-07 + * @brief Implementation of the LLUriParser class. + * + * $LicenseInfo:firstyear=2014&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, 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 "lluriparser.h" + +LLUriParser::LLUriParser(const std::string& u) +: mRes(0) +, mTmpScheme(false) +, mNormalizedTmp(false) +{ + mState.uri = &mUri; + + if (u.find("://") == std::string::npos) + { + mNormalizedUri = "http://"; + mTmpScheme = true; + } + + mNormalizedUri += u; + + mRes = parse(); +} + +LLUriParser::~LLUriParser() +{ + uriFreeUriMembersA(&mUri); +} + +S32 LLUriParser::parse() +{ + mRes = uriParseUriA(&mState, mNormalizedUri.c_str()); + return mRes; +} + +const char * LLUriParser::scheme() const +{ + return mScheme.c_str(); +} + +void LLUriParser::scheme(const std::string& s) +{ + mTmpScheme = !s.size(); + mScheme = s; +} + +const char * LLUriParser::port() const +{ + return mPort.c_str(); +} + +void LLUriParser::port(const std::string& s) +{ + mPort = s; +} + +const char * LLUriParser::host() const +{ + return mHost.c_str(); +} + +void LLUriParser::host(const std::string& s) +{ + mHost = s; +} + +const char * LLUriParser::path() const +{ + return mPath.c_str(); +} + +void LLUriParser::path(const std::string& s) +{ + mPath = s; +} + +const char * LLUriParser::query() const +{ + return mQuery.c_str(); +} + +void LLUriParser::query(const std::string& s) +{ + mQuery = s; +} + +const char * LLUriParser::fragment() const +{ + return mFragment.c_str(); +} + +void LLUriParser::fragment(const std::string& s) +{ + mFragment = s; +} + +void LLUriParser::textRangeToString(UriTextRangeA& textRange, std::string& str) +{ + if (textRange.first != nullptr && textRange.afterLast != nullptr && textRange.first < textRange.afterLast) + { + const ptrdiff_t len = textRange.afterLast - textRange.first; + str.assign(textRange.first, static_cast(len)); + } + else + { + str = LLStringUtil::null; + } +} + +void LLUriParser::extractParts() +{ + if (mTmpScheme || mNormalizedTmp) + { + mScheme.clear(); + } + else + { + textRangeToString(mUri.scheme, mScheme); + } + + textRangeToString(mUri.hostText, mHost); + textRangeToString(mUri.portText, mPort); + textRangeToString(mUri.query, mQuery); + textRangeToString(mUri.fragment, mFragment); + + UriPathSegmentA * pathHead = mUri.pathHead; + while (pathHead) + { + std::string partOfPath; + textRangeToString(pathHead->text, partOfPath); + + mPath += '/'; + mPath += partOfPath; + + pathHead = pathHead->next; + } +} + +S32 LLUriParser::normalize() +{ + mNormalizedTmp = mTmpScheme; + if (!mRes) + { + mRes = uriNormalizeSyntaxExA(&mUri, URI_NORMALIZE_SCHEME | URI_NORMALIZE_HOST); + + if (!mRes) + { + S32 chars_required; + mRes = uriToStringCharsRequiredA(&mUri, &chars_required); + + if (!mRes) + { + chars_required++; + std::vector label_buf(chars_required); + mRes = uriToStringA(&label_buf[0], &mUri, chars_required, nullptr); + + if (!mRes) + { + mNormalizedUri = &label_buf[mTmpScheme ? 7 : 0]; + mTmpScheme = false; + } + } + } + } + + if(mTmpScheme) + { + mNormalizedUri = mNormalizedUri.substr(7); + mTmpScheme = false; + } + + return mRes; +} + +void LLUriParser::glue(std::string& uri) const +{ + std::string first_part; + glueFirst(first_part); + + std::string second_part; + glueSecond(second_part); + + uri = first_part + second_part; +} + +void LLUriParser::glueFirst(std::string& uri, bool use_scheme) const +{ + if (use_scheme && mScheme.size()) + { + uri = mScheme; + uri += "://"; + } + else + { + uri.clear(); + } + + uri += mHost; +} + +void LLUriParser::glueSecond(std::string& uri) const +{ + if (mPort.size()) + { + uri = ':'; + uri += mPort; + } + else + { + uri.clear(); + } + + uri += mPath; + + if (mQuery.size()) + { + uri += '?'; + uri += mQuery; + } + + if (mFragment.size()) + { + uri += '#'; + uri += mFragment; + } +} + +bool LLUriParser::test() const +{ + std::string uri; + glue(uri); + + return uri == mNormalizedUri; +} + +const char * LLUriParser::normalizedUri() const +{ + return mNormalizedUri.c_str(); +} diff --git a/indra/llcommon/lluriparser.h b/indra/llcommon/lluriparser.h new file mode 100644 index 0000000000..773d4189f5 --- /dev/null +++ b/indra/llcommon/lluriparser.h @@ -0,0 +1,87 @@ +/** + * @file lluriparser.h + * @author Protey + * @date 20146-10-07 + * @brief Declaration of the UriParser class. + * + * $LicenseInfo:firstyear=2014&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, 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_LLURIPARSER_H +#define LL_LLURIPARSER_H + +#include +#include + +class LL_COMMON_API LLUriParser +{ +public: + LLUriParser(const std::string& u); + ~LLUriParser(); + + const char * scheme() const; + void scheme (const std::string& s); + + const char * port() const; + void port (const std::string& s); + + const char * host() const; + void host (const std::string& s); + + const char * path() const; + void path (const std::string& s); + + const char * query() const; + void query (const std::string& s); + + const char * fragment() const; + void fragment (const std::string& s); + + const char * normalizedUri() const; + + void extractParts(); + void glue(std::string& uri) const; + void glueFirst(std::string& uri, bool use_scheme = true) const; + void glueSecond(std::string& uri) const; + bool test() const; + S32 normalize(); + +private: + S32 parse(); + void textRangeToString(UriTextRangeA& textRange, std::string& str); + std::string mScheme; + std::string mHost; + std::string mPort; + std::string mPath; + std::string mQuery; + std::string mFragment; + std::string mNormalizedUri; + + UriParserStateA mState; + UriUriA mUri; + + S32 mRes; + bool mTmpScheme; + bool mNormalizedTmp; +}; + +#endif // LL_LLURIPARSER_H diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index ce83fbf551..5d80c19051 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -27,9 +27,8 @@ // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes. #if LL_WINDOWS -#undef WIN32_LEAN_AND_MEAN -#include -#include +#include "llwin32headers.h" +#include "nb30.h" #endif #include "lldefs.h" diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index 1eb8a0bab8..8e5f4e02af 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -31,8 +31,10 @@ #include #include #include +#include #include "stdtypes.h" #include "llpreprocessor.h" +#include class LLMutex; @@ -56,10 +58,10 @@ class LL_COMMON_API LLUUID LLUUID(); explicit LLUUID(const char *in_string); // Convert from string. explicit LLUUID(const std::string& in_string); // Convert from string. - LLUUID(const LLUUID &in); - LLUUID &operator=(const LLUUID &rhs); + LLUUID(const LLUUID &in) = default; + LLUUID &operator=(const LLUUID &rhs) = default; - ~LLUUID(); + ~LLUUID() = default; // // MANIPULATORS @@ -93,6 +95,11 @@ class LL_COMMON_API LLUUID bool operator<(const LLUUID &rhs) const; bool operator>(const LLUUID &rhs) const; + template + friend H AbslHashValue(H h, const LLUUID& id) { + return H::combine_contiguous(std::move(h), id.mData, UUID_BYTES); + } + // xor functions. Useful since any two random uuids xored together // will yield a determinate third random unique id that can be // used as a key in a single uuid that represents 2. @@ -192,24 +199,6 @@ inline BOOL LLUUID::isNull() const return !memcmp(mData, null.mData, sizeof(mData)); // } -// Copy constructor -inline LLUUID::LLUUID(const LLUUID& rhs) -{ - memcpy(mData, rhs.mData, sizeof(mData)); // -} - -inline LLUUID::~LLUUID() -{ -} - -// Assignment -inline LLUUID& LLUUID::operator=(const LLUUID& rhs) -{ - memcpy(mData, rhs.mData, sizeof(mData)); // - return *this; -} - - inline LLUUID::LLUUID(const char *in_string) { if (!in_string || in_string[0] == 0) @@ -288,8 +277,10 @@ inline U32 LLUUID::getCRC32() const // } +static_assert(std::is_trivially_copyable::value, "LLUUID must be a trivially copyable type"); + typedef std::vector uuid_vec_t; -typedef std::set uuid_set_t; +typedef boost::unordered_set uuid_set_t; // Helper structure for ordering lluuids in stl containers. eg: // std::map widget_map; @@ -307,29 +298,24 @@ struct lluuid_less typedef std::set uuid_list_t; - -#ifdef LL_CPP11 namespace std { template <> struct hash -{ - public: + { size_t operator()(const LLUUID & id) const { - return id.hash(); + return absl::Hash{}(id); } }; } -#endif namespace boost { - template<> class hash -{ - public: - size_t operator()(const LLUUID& id) const + template<> struct hash { - return id.hash(); - } -}; + size_t operator()(const LLUUID& id) const + { + return absl::Hash{}(id); + } + }; } /* diff --git a/indra/llcommon/llversionviewer.h.in b/indra/llcommon/llversionviewer.h.in deleted file mode 100644 index 76d53b9261..0000000000 --- a/indra/llcommon/llversionviewer.h.in +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @file llversionviewer.h - * @brief - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLVERSIONVIEWER_H -#define LL_LLVERSIONVIEWER_H - -const S32 LL_VERSION_MAJOR = 1; -const S32 LL_VERSION_MINOR = 8; -const S32 LL_VERSION_PATCH = 6; -const S32 LL_VERSION_BUILD = ${vBUILD}; - -const char * const LL_CHANNEL = "${VIEWER_CHANNEL}"; - -#if LL_DARWIN -const char * const LL_VERSION_BUNDLE_ID = "org.singularityviewer.singularity"; -#endif - -#endif - diff --git a/indra/llcommon/llwin32headers.h b/indra/llcommon/llwin32headers.h new file mode 100644 index 0000000000..9d1e40d8cf --- /dev/null +++ b/indra/llcommon/llwin32headers.h @@ -0,0 +1,43 @@ +/** + * @file llwin32headers.h + * @brief sanitized include of windows header files + * + * $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_LLWINDOWS_H +#define LL_LLWINDOWS_H + +#ifdef LL_WINDOWS +#ifndef NOMINMAX +#define NOMINMAX +#endif +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +// reset to default, which is lean +#define WIN32_LEAN_AND_MEAN +#undef NOMINMAX +#endif + +#endif diff --git a/indra/llcommon/llwin32headerslean.h b/indra/llcommon/llwin32headerslean.h new file mode 100644 index 0000000000..d64c307ccf --- /dev/null +++ b/indra/llcommon/llwin32headerslean.h @@ -0,0 +1,41 @@ +/** + * @file llwin32headerslean.h + * @brief sanitized include of windows header files + * + * $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_LLWINDOWS_H +#define LL_LLWINDOWS_H + +#ifdef LL_WINDOWS +#ifndef NOMINMAX +#define NOMINMAX +#endif +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#undef NOMINMAX +#endif + +#endif diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index e66c570f4d..20b99bdc82 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -37,7 +37,7 @@ LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) : LLQueuedThread(name, threaded, should_pause) { - mDeleteMutex = new LLMutex; + mDeleteMutex = new LLMutex(); } LLWorkerThread::~LLWorkerThread() @@ -199,6 +199,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na mWorkerClassName(name), mRequestHandle(LLWorkerThread::nullHandle()), mRequestPriority(LLWorkerThread::PRIORITY_NORMAL), + mMutex(), mWorkFlags(0) { if (!mWorkerThread) @@ -345,10 +346,14 @@ bool LLWorkerClass::checkWork(bool aborting) } LLQueuedThread::status_t status = workreq->getStatus(); - if (status == LLWorkerThread::STATUS_COMPLETE || status == LLWorkerThread::STATUS_ABORTED) + if (status == LLWorkerThread::STATUS_ABORTED) + { + complete = !(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED); + abort = true; + } + else if (status == LLWorkerThread::STATUS_COMPLETE) { complete = !(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED); - abort = status == LLWorkerThread::STATUS_ABORTED; } else { diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h index af0b4dd4ed..7eef3695e8 100644 --- a/indra/llcommon/stdtypes.h +++ b/indra/llcommon/stdtypes.h @@ -108,8 +108,16 @@ typedef U8 LLPCode; #define LL_ARRAY_SIZE( _kArray ) ( sizeof( (_kArray) ) / sizeof( _kArray[0] ) ) -#if LL_LINUX && __GNUC__ <= 2 -typedef int intptr_t; +#if __GNUG__ && __GNUC__ < 5 +namespace std +{ + template + struct is_trivially_copyable + { + static const bool value = __has_trivial_copy(T); + operator bool() { return value; } + }; +} #endif #endif diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index 431744c421..fb41880320 100644 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -54,9 +54,11 @@ set_source_files_properties(${llimage_HEADER_FILES} list(APPEND llimage_SOURCE_FILES ${llimage_HEADER_FILES}) add_library (llimage ${llimage_SOURCE_FILES}) -add_dependencies(llimage prepare) + target_link_libraries( llimage + PUBLIC + llcommon ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 1d6a733ecf..768958d2fa 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -281,7 +281,7 @@ U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 si // LLImageRaw //--------------------------------------------------------------------------- -AIThreadSafeSimpleDC LLImageRaw::sGlobalRawMemory; +AIThreadSafeSimpleDC LLImageRaw::sGlobalRawMemory; S32 LLImageRaw::sRawImageCount = 0; S32 LLImageRaw::sRawImageCachedCount = 0; @@ -358,7 +358,7 @@ LLImageRaw::~LLImageRaw() U8* LLImageRaw::allocateData(S32 size) { U8* res = LLImageBase::allocateData(size); - *AIAccess(sGlobalRawMemory) += getDataSize(); + *AIAccess(sGlobalRawMemory) += getDataSize(); return res; } @@ -367,7 +367,7 @@ U8* LLImageRaw::reallocateData(S32 size) { S32 old_data_size = getDataSize(); U8* res = LLImageBase::reallocateData(size); - *AIAccess(sGlobalRawMemory) += getDataSize() - old_data_size; + *AIAccess(sGlobalRawMemory) += getDataSize() - old_data_size; return res; } @@ -375,7 +375,7 @@ U8* LLImageRaw::reallocateData(S32 size) void LLImageRaw::deleteData() { { - *AIAccess(sGlobalRawMemory) -= getDataSize(); + *AIAccess(sGlobalRawMemory) -= getDataSize(); } LLImageBase::deleteData(); } @@ -392,7 +392,7 @@ void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components) LLImageBase::setSize(width, height, components) ; LLImageBase::setDataAndSize(data, width * height * components) ; - *AIAccess(sGlobalRawMemory) += getDataSize(); + *AIAccess(sGlobalRawMemory) += getDataSize(); } BOOL LLImageRaw::resize(U16 width, U16 height, S8 components) @@ -1084,6 +1084,7 @@ void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixe S32 goff = components >= 2 ? 1 : 0; S32 boff = components >= 3 ? 2 : 0; + // This loop is awful. for( S32 x = 0; x < out_pixel_len; x++ ) { // Sample input pixels in range from sample0 to sample1. @@ -1172,19 +1173,15 @@ void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixe } } - r *= norm_factor; - g *= norm_factor; - b *= norm_factor; - a *= norm_factor; // skip conditional + U8 arr[] = { + U8(ll_pos_round(r * norm_factor)), + U8(ll_pos_round(g * norm_factor)), + U8(ll_pos_round(b * norm_factor)), + U8(ll_pos_round(a * norm_factor)) + }; // skip conditional S32 t4 = x * out_pixel_step * components; - out[t4 + 0] = U8(ll_round(r)); - if (components >= 2) - out[t4 + 1] = U8(ll_round(g)); - if (components >= 3) - out[t4 + 2] = U8(ll_round(b)); - if( components == 4) - out[t4 + 3] = U8(ll_round(a)); + memcpy(out + t4, arr, sizeof(U8) * components); } } } @@ -1259,10 +1256,10 @@ void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S3 b *= norm_factor; a *= norm_factor; - in_scaled_r = U8(ll_round(r)); - in_scaled_g = U8(ll_round(g)); - in_scaled_b = U8(ll_round(b)); - in_scaled_a = U8(ll_round(a)); + in_scaled_r = U8(ll_pos_round(r)); + in_scaled_g = U8(ll_pos_round(g)); + in_scaled_b = U8(ll_pos_round(b)); + in_scaled_a = U8(ll_pos_round(a)); } if( in_scaled_a ) diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 1e94f49f44..d77e0f39b6 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -244,6 +244,9 @@ class LLImageRaw : public LLImageBase // Src and dst are same size. Src has 4 components. Dst has 3 components. void compositeUnscaled4onto3( LLImageRaw* src ); + + std::string getComment() const { return mComment; } + std::string mComment; protected: // Create an image from a local file (generally used in tools) @@ -257,7 +260,7 @@ class LLImageRaw : public LLImageBase void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; public: - static AIThreadSafeSimpleDC sGlobalRawMemory; + static AIThreadSafeSimpleDC sGlobalRawMemory; static S32 sRawImageCount; static S32 sRawImageCachedCount; diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp index dafcc5c825..b60f2064ca 100644 --- a/indra/llimage/llimagebmp.cpp +++ b/indra/llimage/llimagebmp.cpp @@ -1,31 +1,25 @@ /** * @file llimagebmp.cpp * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -81,7 +75,7 @@ LLImageBMP::LLImageBMP() : LLImageFormatted(IMG_CODEC_BMP), mColorPaletteColors( 0 ), - mColorPalette( NULL ), + mColorPalette(nullptr ), mBitmapOffset( 0 ), mBitsPerPixel( 0 ), mOriginAtTop( FALSE ) @@ -324,10 +318,13 @@ BOOL LLImageBMP::updateData() if( 0 != mColorPaletteColors ) { - mColorPalette = new U8[color_palette_size]; - if (!mColorPalette) + try + { + mColorPalette = new U8[color_palette_size]; + } + catch (const std::bad_alloc& e) { - LL_ERRS() << "Out of memory in LLImageBMP::updateData()" << LL_ENDL; + LL_WARNS() << "Failed to allocate bmp color date with exception: " << e.what() << LL_ENDL; return FALSE; } memcpy( mColorPalette, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE + extension_size, color_palette_size ); /* Flawfinder: ignore */ @@ -449,6 +446,10 @@ BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src ) mBitfieldMask[2] = 0x000000FF; } + if (getWidth() * getHeight() * 4 > getDataSize() - mBitmapOffset) + { //here we have situation when data size in src less than actually needed + return FALSE; + } S32 src_row_span = getWidth() * 4; S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4 @@ -482,6 +483,11 @@ BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src ) S32 src_row_span = getWidth() * 1; S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4 + if ((getWidth() * getHeight()) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset) + { //here we have situation when data size in src less than actually needed + return FALSE; + } + for( S32 row = 0; row < getHeight(); row++ ) { for( S32 col = 0; col < getWidth(); col++ ) @@ -507,6 +513,11 @@ BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src ) S32 src_row_span = getWidth() * 3; S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4 + if ((getWidth() * getHeight() * 3) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset) + { //here we have situation when data size in src less than actually needed + return FALSE; + } + for( S32 row = 0; row < getHeight(); row++ ) { for( S32 col = 0; col < getWidth(); col++ ) diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp index 04e0e752eb..8f2a48a5ef 100644 --- a/indra/llimage/llimagedxt.cpp +++ b/indra/llimage/llimagedxt.cpp @@ -271,7 +271,7 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time) S32 width = getWidth(), height = getHeight(); S32 ncomponents = getComponents(); - U8* data = NULL; + U8* data = nullptr; if (mDiscardLevel >= 0) { data = getData() + getMipOffset(mDiscardLevel); @@ -332,7 +332,7 @@ BOOL LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_ break; default: LL_ERRS() << "LLImageDXT::encode: Unhandled channel number: " << ncomponents << LL_ENDL; - return 0; + return false; } S32 width = raw_image->getWidth(); @@ -371,7 +371,7 @@ BOOL LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_ header->maxwidth = width; header->maxheight = height; - U8* prev_mipdata = 0; + U8* prev_mipdata = nullptr; w = width, h = height; for (S32 mip=0; mip= FORMAT_DXT1 && mFileFormat <= FORMAT_DXR5); } + bool isCompressed() const { return (mFileFormat >= FORMAT_DXT1 && mFileFormat <= FORMAT_DXR5); } bool convertToDXR(); // convert from DXT to DXR diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp index f034909da3..01b3c3243a 100644 --- a/indra/llimage/llimagetga.cpp +++ b/indra/llimage/llimagetga.cpp @@ -437,7 +437,13 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu // Origin is the bottom left U8* dst = raw_image->getData(); U8* src = getData() + mDataOffset; + S32 pixels = getWidth() * getHeight(); + + if (pixels * (mIs15Bit ? 2 : getComponents()) > getDataSize() - (S32)mDataOffset) + { //here we have situation when data size in src less than actually needed + return FALSE; + } if (getComponents() == 4) { @@ -1155,7 +1161,7 @@ bool LLImageTGA::loadFile( const std::string& path ) return false; } - S32 file_size = 0; + size_t file_size = 0; if (!fseek(file, 0, SEEK_END)) { file_size = ftell(file); diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index d710a065d1..c4b8c09943 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -35,18 +35,20 @@ LLImageDecodeThread::LLImageDecodeThread(bool threaded) : LLQueuedThread("imagedecode", threaded) { + mCreationMutex = new LLMutex(); } //virtual LLImageDecodeThread::~LLImageDecodeThread() { + delete mCreationMutex ; } // MAIN THREAD // virtual S32 LLImageDecodeThread::update(F32 max_time_ms) { - LLMutexLock lock(&mCreationMutex); + LLMutexLock lock(mCreationMutex); for (creation_list_t::iterator iter = mCreationList.begin(); iter != mCreationList.end(); ++iter) { @@ -69,7 +71,7 @@ S32 LLImageDecodeThread::update(F32 max_time_ms) LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image, U32 priority, S32 discard, BOOL needs_aux, Responder* responder) { - LLMutexLock lock(&mCreationMutex); + LLMutexLock lock(mCreationMutex); handle_t handle = generateHandle(); mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder)); return handle; @@ -79,7 +81,7 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* // Returns the size of the mutex guarded list as an indication of sanity S32 LLImageDecodeThread::tut_size() { - LLMutexLock lock(&mCreationMutex); + LLMutexLock lock(mCreationMutex); S32 res = mCreationList.size(); return res; } diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index 6d9ae3fe9b..1bfb0ddfd3 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -98,7 +98,7 @@ class LLImageDecodeThread : public LLQueuedThread }; typedef std::list creation_list_t; creation_list_t mCreationList; - LLMutex mCreationMutex; + LLMutex* mCreationMutex; }; #endif diff --git a/indra/llimage/llpngwrapper.h b/indra/llimage/llpngwrapper.h index 4105830240..27d7df3bef 100644 --- a/indra/llimage/llpngwrapper.h +++ b/indra/llimage/llpngwrapper.h @@ -26,16 +26,7 @@ #ifndef LL_LLPNGWRAPPER_H #define LL_LLPNGWRAPPER_H -#if LL_STANDALONE || (LL_LINUX && defined(__x86_64__)) -#include -#else -// Workaround for wrongly packaged prebuilt. -#if _MSC_VER >= 1800 -#include -#else -#include "libpng15/png.h" -#endif -#endif +#include "png.h" #include "llimage.h" class LLPngWrapper diff --git a/indra/llimagej2coj/CMakeLists.txt b/indra/llimagej2coj/CMakeLists.txt index e8b87e5879..2d2a5c86fb 100644 --- a/indra/llimagej2coj/CMakeLists.txt +++ b/indra/llimagej2coj/CMakeLists.txt @@ -41,9 +41,11 @@ IF(WIN32) ENDIF(WIN32) add_library (llimagej2coj ${llimagej2coj_SOURCE_FILES}) -add_dependencies(llimagej2coj prepare) + target_link_libraries( llimagej2coj + PUBLIC + llcommon ${OPENJPEG_LIBRARIES} ) diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index 479bdce105..bd88ac4df1 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -33,12 +33,7 @@ #include "lltimer.h" //#include "llmemory.h" -const char* fallbackEngineInfoLLImageJ2CImpl() -{ - static std::string version_string = std::string("OpenJPEG: ") + opj_version(); - return version_string.c_str(); -} - +// Factory function: see declaration in llimagej2c.cpp LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl() { return new LLImageJ2COJ(); @@ -50,6 +45,13 @@ void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl) impl = NULL; } +const char* fallbackEngineInfoLLImageJ2CImpl() +{ + static std::string version_string = std::string("OpenJPEG: ") + + opj_version(); + return version_string.c_str(); +} + // Return string from message, eliminating final \n if present static std::string chomp(const char* msg) { @@ -108,22 +110,57 @@ LLImageJ2COJ::~LLImageJ2COJ() BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) { - // - // FIXME: Get the comment field out of the texture - // - LLTimer decode_timer; + /* Extract metadata */ + /* ---------------- */ + U8* c_data = base.getData(); + size_t c_size = base.getDataSize(); + size_t position = 0; + + while (position < 1024 && position < (c_size - 7)) // the comment field should be in the first 1024 bytes. + { + if (c_data[position] == 0xff && c_data[position + 1] == 0x64) + { + U8 high_byte = c_data[position + 2]; + U8 low_byte = c_data[position + 3]; + S32 c_length = (high_byte * 256) + low_byte; // This size also counts the markers, 00 01 and itself + if (c_length > 200) // sanity check + { + // While comments can be very long, anything longer then 200 is suspect. + break; + } + + if (position + 2 + c_length > c_size) + { + // comment extends past end of data, corruption, or all data not retrived yet. + break; + } + + // if the comment block does not end at the end of data, check to see if the next + // block starts with 0xFF + if (position + 2 + c_length < c_size && c_data[position + 2 + c_length] != 0xff) + { + // invalied comment block + break; + } + + // extract the comment minus the markers, 00 01 + raw_image.mComment.assign((char*)c_data + position + 6, c_length - 4); + break; + } + ++position; + } + opj_dparameters_t parameters; /* decompression parameters */ - opj_event_mgr_t event_mgr; /* event manager */ - opj_image_t *image = NULL; + opj_event_mgr_t event_mgr = { }; /* event manager */ + opj_image_t *image = nullptr; - opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ - opj_cio_t *cio = NULL; + opj_dinfo_t* dinfo = nullptr; /* handle to a decompressor */ + opj_cio_t *cio = nullptr; /* configure the event callbacks (not required) */ - memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = error_callback; event_mgr.warning_handler = warning_callback; event_mgr.info_handler = info_callback; @@ -168,19 +205,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ -#if 0 - std::vector data(base.getData(), base.getData()+base.getDataSize()); - S32 size = data.size(); - if (data[size-1] == 0xFF) { - data.push_back((U8)0xD9); - } else if (data[size-2] != 0xFF || data[size-1] != 0xD9) { - data.push_back((U8)0xFF); - data.push_back((U8)0xD9); - } - cio = opj_cio_open((opj_common_ptr)dinfo, &data[0], data.size()); -#else cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize()); -#endif /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); @@ -199,20 +224,11 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod // dereference the array. if(!image || !image->numcomps) { - LL_WARNS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL; + LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL; if (image) { opj_image_destroy(image); } -#if 0 - std::stringstream filename; - filename << "err" << (int)base.getRawDiscardLevel() << "_" << rand() << ".jp2"; - FILE* file = fopen(filename.str().c_str(), "wb"); - if (file) { - fwrite(base.getData(), base.getDataSize(), 1, file); - fclose(file); - } -#endif base.decodeFailed(); return TRUE; // done } @@ -222,7 +238,6 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod { if (image->comps[i].factor != base.getRawDiscardLevel()) { - LL_WARNS("Texture") << "Expected discard level not reached!" << LL_ENDL; // if we didn't get the discard level we're expecting, fail opj_image_destroy(image); base.decodeFailed(); @@ -262,6 +277,13 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod S32 height = ceildivpow2(image->y1 - image->y0, f); raw_image.resize(width, height, channels); U8 *rawp = raw_image.getData(); + if (!rawp) + { + opj_image_destroy(image); + base.setLastError("Memory error"); + base.decodeFailed(); + return true; // done + } // first_channel is what channel to start copying from // dest is what channel to copy to. first_channel comes from the @@ -283,9 +305,11 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod } else // Some rare OpenJPEG versions have this bug. { - LL_WARNS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL; - opj_image_destroy(image); - + LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL; + if (image) + { + opj_image_destroy(image); + } base.decodeFailed(); return TRUE; // done } @@ -302,14 +326,13 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con { const S32 MAX_COMPS = 5; opj_cparameters_t parameters; /* compression parameters */ - opj_event_mgr_t event_mgr; /* event manager */ + opj_event_mgr_t event_mgr = { }; /* event manager */ /* configure the event callbacks (not required) setting of each callback is optional */ - memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = error_callback; event_mgr.warning_handler = warning_callback; event_mgr.info_handler = info_callback; @@ -354,7 +377,7 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con // OPJ_COLOR_SPACE color_space = CLRSPC_SRGB; opj_image_cmptparm_t cmptparm[MAX_COMPS]; - opj_image_t * image = NULL; + opj_image_t * image = nullptr; S32 numcomps = llmin((S32)raw_image.getComponents(), MAX_COMPS); S32 width = raw_image.getWidth(); S32 height = raw_image.getHeight(); @@ -398,7 +421,7 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con /* ---------------------------- */ int codestream_length; - opj_cio_t *cio = NULL; + opj_cio_t *cio = nullptr; /* get a J2K compressor handle */ opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K); @@ -411,14 +434,14 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con /* open a byte stream for writing */ /* allocate memory for all tiles */ - cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0); + cio = opj_cio_open((opj_common_ptr)cinfo, nullptr, 0); /* encode the image */ - bool bSuccess = opj_encode(cinfo, cio, image, NULL); + bool bSuccess = opj_encode(cinfo, cio, image, nullptr); if (!bSuccess) { opj_cio_close(cio); - LL_WARNS("Texture") << "Failed to encode image." << LL_ENDL; + LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL; return FALSE; } codestream_length = cio_tell(cio); @@ -520,15 +543,14 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base) // Do it the old and slow way, decode the image with openjpeg opj_dparameters_t parameters; /* decompression parameters */ - opj_event_mgr_t event_mgr; /* event manager */ - opj_image_t *image = NULL; + opj_event_mgr_t event_mgr = { }; /* event manager */ + opj_image_t *image = nullptr; - opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ - opj_cio_t *cio = NULL; + opj_dinfo_t* dinfo = nullptr; /* handle to a decompressor */ + opj_cio_t *cio = nullptr; /* configure the event callbacks (not required) */ - memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = error_callback; event_mgr.warning_handler = warning_callback; event_mgr.info_handler = info_callback; diff --git a/indra/llinventory/CMakeLists.txt b/indra/llinventory/CMakeLists.txt index f288fa4965..71909dc093 100644 --- a/indra/llinventory/CMakeLists.txt +++ b/indra/llinventory/CMakeLists.txt @@ -17,16 +17,20 @@ include_directories( set(llinventory_SOURCE_FILES llcategory.cpp - lleconomy.cpp llfoldertype.cpp llinventory.cpp llinventorydefines.cpp + llinventorysettings.cpp llinventorytype.cpp lllandmark.cpp llnotecard.cpp llparcel.cpp llpermissions.cpp llsaleinfo.cpp + llsettingsbase.cpp + llsettingsdaycycle.cpp + llsettingssky.cpp + llsettingswater.cpp lltransactionflags.cpp lluserrelations.cpp ) @@ -35,11 +39,12 @@ set(llinventory_HEADER_FILES CMakeLists.txt llcategory.h - lleconomy.h llfoldertype.h llinventory.h llinventorydefines.h + llinventorysettings.h llinventorytype.h + llinvtranslationbrdg.h lllandmark.h llnotecard.h llparcel.h @@ -47,6 +52,10 @@ set(llinventory_HEADER_FILES llpermissions.h llpermissionsflags.h llsaleinfo.h + llsettingsbase.h + llsettingsdaycycle.h + llsettingssky.h + llsettingswater.h lltransactionflags.h lltransactiontypes.h lluserrelations.h @@ -58,4 +67,9 @@ set_source_files_properties(${llinventory_HEADER_FILES} list(APPEND llinventory_SOURCE_FILES ${llinventory_HEADER_FILES}) add_library (llinventory ${llinventory_SOURCE_FILES}) -add_dependencies(llinventory prepare) + +target_link_libraries( + llinventory + PUBLIC + llcommon + ) diff --git a/indra/llinventory/lleconomy.cpp b/indra/llinventory/lleconomy.cpp deleted file mode 100644 index e10402196f..0000000000 --- a/indra/llinventory/lleconomy.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/** - * @file lleconomy.cpp - * - * $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$ - */ - -#include "linden_common.h" - -#include "lleconomy.h" -#include "llerror.h" -#include "message.h" -#include "v3math.h" - - -LLGlobalEconomy::LLGlobalEconomy() -: mObjectCount( -1 ), - mObjectCapacity( -1 ), - mPriceObjectClaim( -1 ), - mPricePublicObjectDecay( -1 ), - mPricePublicObjectDelete( -1 ), - mPriceEnergyUnit( -1 ), - mPriceUpload( -1 ), - mPriceRentLight( -1 ), - mTeleportMinPrice( -1 ), - mTeleportPriceExponent( -1 ), - mPriceGroupCreate( -1 ) -{ } - -LLGlobalEconomy::~LLGlobalEconomy() -{ } - -void LLGlobalEconomy::addObserver(LLEconomyObserver* observer) -{ - mObservers.push_back(observer); -} - -void LLGlobalEconomy::removeObserver(LLEconomyObserver* observer) -{ - std::list::iterator it = - std::find(mObservers.begin(), mObservers.end(), observer); - if (it != mObservers.end()) - { - mObservers.erase(it); - } -} - -void LLGlobalEconomy::notifyObservers() -{ - for (std::list::iterator it = mObservers.begin(); - it != mObservers.end(); - ++it) - { - (*it)->onEconomyDataChange(); - } -} - -// static -void LLGlobalEconomy::processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data) -{ - S32 i; - F32 f; - - msg->getS32Fast(_PREHASH_Info, _PREHASH_ObjectCapacity, i); - econ_data->setObjectCapacity(i); - msg->getS32Fast(_PREHASH_Info, _PREHASH_ObjectCount, i); - econ_data->setObjectCount(i); - msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceEnergyUnit, i); - econ_data->setPriceEnergyUnit(i); - msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceObjectClaim, i); - econ_data->setPriceObjectClaim(i); - msg->getS32Fast(_PREHASH_Info, _PREHASH_PricePublicObjectDecay, i); - econ_data->setPricePublicObjectDecay(i); - msg->getS32Fast(_PREHASH_Info, _PREHASH_PricePublicObjectDelete, i); - econ_data->setPricePublicObjectDelete(i); - msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceUpload, i); - econ_data->setPriceUpload(i); -#if LL_LINUX - // We can optionally fake the received upload price for testing. - // Note that the server is within its rights to not obey our fake - // price. :) - const char* fakeprice_str = getenv("LL_FAKE_UPLOAD_PRICE"); - if (fakeprice_str) - { - S32 fakeprice = (S32)atoi(fakeprice_str); - LL_WARNS() << "LL_FAKE_UPLOAD_PRICE: Faking upload price as L$" << fakeprice << LL_ENDL; - econ_data->setPriceUpload(fakeprice); - } -#endif - msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceRentLight, i); - econ_data->setPriceRentLight(i); - msg->getS32Fast(_PREHASH_Info, _PREHASH_TeleportMinPrice, i); - econ_data->setTeleportMinPrice(i); - msg->getF32Fast(_PREHASH_Info, _PREHASH_TeleportPriceExponent, f); - econ_data->setTeleportPriceExponent(f); - msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceGroupCreate, i); - econ_data->setPriceGroupCreate(i); - - econ_data->notifyObservers(); -} - -S32 LLGlobalEconomy::calculateTeleportCost(F32 distance) const -{ - S32 min_cost = getTeleportMinPrice(); - F32 exponent = getTeleportPriceExponent(); - F32 divisor = 100.f * pow(3.f, exponent); - S32 cost = (U32)(distance * pow(log10(distance), exponent) / divisor); - if (cost < 0) - { - cost = 0; - } - else if (cost < min_cost) - { - cost = min_cost; - } - - return cost; -} - -S32 LLGlobalEconomy::calculateLightRent(const LLVector3& object_size) const -{ - F32 intensity_mod = llmax(object_size.magVec(), 1.f); - return (S32)(intensity_mod * getPriceRentLight()); -} - -void LLGlobalEconomy::print() -{ - LL_INFOS() << "Global Economy Settings: " << LL_ENDL; - LL_INFOS() << "Object Capacity: " << mObjectCapacity << LL_ENDL; - LL_INFOS() << "Object Count: " << mObjectCount << LL_ENDL; - LL_INFOS() << "Claim Price Per Object: " << mPriceObjectClaim << LL_ENDL; - LL_INFOS() << "Claim Price Per Public Object: " << mPricePublicObjectDecay << LL_ENDL; - LL_INFOS() << "Delete Price Per Public Object: " << mPricePublicObjectDelete << LL_ENDL; - LL_INFOS() << "Release Price Per Public Object: " << getPricePublicObjectRelease() << LL_ENDL; - LL_INFOS() << "Price Per Energy Unit: " << mPriceEnergyUnit << LL_ENDL; - LL_INFOS() << "Price Per Upload: " << mPriceUpload << LL_ENDL; - LL_INFOS() << "Light Base Price: " << mPriceRentLight << LL_ENDL; - LL_INFOS() << "Teleport Min Price: " << mTeleportMinPrice << LL_ENDL; - LL_INFOS() << "Teleport Price Exponent: " << mTeleportPriceExponent << LL_ENDL; - LL_INFOS() << "Price for group creation: " << mPriceGroupCreate << LL_ENDL; -} - -LLRegionEconomy::LLRegionEconomy() -: LLGlobalEconomy(), - mPriceObjectRent( -1.f ), - mPriceObjectScaleFactor( -1.f ), - mEnergyEfficiency( -1.f ), - mBasePriceParcelClaimDefault(-1), - mBasePriceParcelClaimActual(-1), - mPriceParcelClaimFactor(-1.f), - mBasePriceParcelRent(-1), - mAreaOwned(-1.f), - mAreaTotal(-1.f) -{ } - -LLRegionEconomy::~LLRegionEconomy() -{ } - -BOOL LLRegionEconomy::hasData() const -{ - return (mBasePriceParcelRent != -1); -} - -// static -void LLRegionEconomy::processEconomyData(LLMessageSystem *msg, void** user_data) -{ - S32 i; - F32 f; - - LLRegionEconomy *this_ptr = (LLRegionEconomy*)user_data; - - LLGlobalEconomy::processEconomyData(msg, this_ptr); - - msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceParcelClaim, i); - this_ptr->setBasePriceParcelClaimDefault(i); - msg->getF32(_PREHASH_Info, _PREHASH_PriceParcelClaimFactor, f); - this_ptr->setPriceParcelClaimFactor(f); - msg->getF32Fast(_PREHASH_Info, _PREHASH_EnergyEfficiency, f); - this_ptr->setEnergyEfficiency(f); - msg->getF32Fast(_PREHASH_Info, _PREHASH_PriceObjectRent, f); - this_ptr->setPriceObjectRent(f); - msg->getF32Fast(_PREHASH_Info, _PREHASH_PriceObjectScaleFactor, f); - this_ptr->setPriceObjectScaleFactor(f); - msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceParcelRent, i); - this_ptr->setBasePriceParcelRent(i); -} - -// static -void LLRegionEconomy::processEconomyDataRequest(LLMessageSystem *msg, void **user_data) -{ - LLRegionEconomy *this_ptr = (LLRegionEconomy*)user_data; - if (!this_ptr->hasData()) - { - LL_WARNS() << "Dropping EconomyDataRequest, because EconomyData message " - << "has not been processed" << LL_ENDL; - } - - msg->newMessageFast(_PREHASH_EconomyData); - msg->nextBlockFast(_PREHASH_Info); - msg->addS32Fast(_PREHASH_ObjectCapacity, this_ptr->getObjectCapacity()); - msg->addS32Fast(_PREHASH_ObjectCount, this_ptr->getObjectCount()); - msg->addS32Fast(_PREHASH_PriceEnergyUnit, this_ptr->getPriceEnergyUnit()); - msg->addS32Fast(_PREHASH_PriceObjectClaim, this_ptr->getPriceObjectClaim()); - msg->addS32Fast(_PREHASH_PricePublicObjectDecay, this_ptr->getPricePublicObjectDecay()); - msg->addS32Fast(_PREHASH_PricePublicObjectDelete, this_ptr->getPricePublicObjectDelete()); - msg->addS32Fast(_PREHASH_PriceParcelClaim, this_ptr->mBasePriceParcelClaimActual); - msg->addF32Fast(_PREHASH_PriceParcelClaimFactor, this_ptr->mPriceParcelClaimFactor); - msg->addS32Fast(_PREHASH_PriceUpload, this_ptr->getPriceUpload()); - msg->addS32Fast(_PREHASH_PriceRentLight, this_ptr->getPriceRentLight()); - msg->addS32Fast(_PREHASH_TeleportMinPrice, this_ptr->getTeleportMinPrice()); - msg->addF32Fast(_PREHASH_TeleportPriceExponent, this_ptr->getTeleportPriceExponent()); - - msg->addF32Fast(_PREHASH_EnergyEfficiency, this_ptr->getEnergyEfficiency()); - msg->addF32Fast(_PREHASH_PriceObjectRent, this_ptr->getPriceObjectRent()); - msg->addF32Fast(_PREHASH_PriceObjectScaleFactor, this_ptr->getPriceObjectScaleFactor()); - msg->addS32Fast(_PREHASH_PriceParcelRent, this_ptr->getPriceParcelRent()); - msg->addS32Fast(_PREHASH_PriceGroupCreate, this_ptr->getPriceGroupCreate()); - - msg->sendReliable(msg->getSender()); -} - - -S32 LLRegionEconomy::getPriceParcelClaim() const -{ - //return (S32)((F32)mBasePriceParcelClaim * (mAreaTotal / (mAreaTotal - mAreaOwned))); - return (S32)((F32)mBasePriceParcelClaimActual * mPriceParcelClaimFactor); -} - -S32 LLRegionEconomy::getPriceParcelRent() const -{ - return mBasePriceParcelRent; -} - - -void LLRegionEconomy::print() -{ - this->LLGlobalEconomy::print(); - - LL_INFOS() << "Region Economy Settings: " << LL_ENDL; - LL_INFOS() << "Land (square meters): " << mAreaTotal << LL_ENDL; - LL_INFOS() << "Owned Land (square meters): " << mAreaOwned << LL_ENDL; - LL_INFOS() << "Daily Object Rent: " << mPriceObjectRent << LL_ENDL; - LL_INFOS() << "Daily Land Rent (per meter): " << getPriceParcelRent() << LL_ENDL; - LL_INFOS() << "Energey Efficiency: " << mEnergyEfficiency << LL_ENDL; -} - - -void LLRegionEconomy::setBasePriceParcelClaimDefault(S32 val) -{ - mBasePriceParcelClaimDefault = val; - if(mBasePriceParcelClaimActual == -1) - { - mBasePriceParcelClaimActual = val; - } -} - -void LLRegionEconomy::setBasePriceParcelClaimActual(S32 val) -{ - mBasePriceParcelClaimActual = val; -} - -void LLRegionEconomy::setPriceParcelClaimFactor(F32 val) -{ - mPriceParcelClaimFactor = val; -} - -void LLRegionEconomy::setBasePriceParcelRent(S32 val) -{ - mBasePriceParcelRent = val; -} diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h deleted file mode 100644 index eb2ecf71ba..0000000000 --- a/indra/llinventory/lleconomy.h +++ /dev/null @@ -1,159 +0,0 @@ -/** - * @file lleconomy.h - * - * $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_LLECONOMY_H -#define LL_LLECONOMY_H - -#include "llsingleton.h" - -class LLMessageSystem; -class LLVector3; - -/** - * Register an observer to be notified of economy data updates coming from server. - */ -class LLEconomyObserver -{ -public: - virtual ~LLEconomyObserver() {} - virtual void onEconomyDataChange() = 0; -}; - -class LLGlobalEconomy -{ -public: - LLGlobalEconomy(); - virtual ~LLGlobalEconomy(); - - // This class defines its singleton internally as a typedef instead of inheriting from - // LLSingleton like most others because the LLRegionEconomy sub-class might also - // become a singleton and this pattern will more easily disambiguate them. - typedef LLSingleton Singleton; - - void initSingleton() { } - - virtual void print(); - - void addObserver(LLEconomyObserver* observer); - void removeObserver(LLEconomyObserver* observer); - void notifyObservers(); - - static void processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data); - - S32 calculateTeleportCost(F32 distance) const; - S32 calculateLightRent(const LLVector3& object_size) const; - - S32 getObjectCount() const { return mObjectCount; } - S32 getObjectCapacity() const { return mObjectCapacity; } - S32 getPriceObjectClaim() const { return mPriceObjectClaim; } - S32 getPricePublicObjectDecay() const { return mPricePublicObjectDecay; } - S32 getPricePublicObjectDelete() const { return mPricePublicObjectDelete; } - S32 getPricePublicObjectRelease() const { return mPriceObjectClaim - mPricePublicObjectDelete; } - S32 getPriceEnergyUnit() const { return mPriceEnergyUnit; } - S32 getPriceUpload() const { return mPriceUpload; } - S32 getPriceRentLight() const { return mPriceRentLight; } - S32 getTeleportMinPrice() const { return mTeleportMinPrice; } - F32 getTeleportPriceExponent() const { return mTeleportPriceExponent; } - S32 getPriceGroupCreate() const { return mPriceGroupCreate; } - - - void setObjectCount(S32 val) { mObjectCount = val; } - void setObjectCapacity(S32 val) { mObjectCapacity = val; } - void setPriceObjectClaim(S32 val) { mPriceObjectClaim = val; } - void setPricePublicObjectDecay(S32 val) { mPricePublicObjectDecay = val; } - void setPricePublicObjectDelete(S32 val) { mPricePublicObjectDelete = val; } - void setPriceEnergyUnit(S32 val) { mPriceEnergyUnit = val; } - void setPriceUpload(S32 val) { mPriceUpload = val; } - void setPriceRentLight(S32 val) { mPriceRentLight = val; } - void setTeleportMinPrice(S32 val) { mTeleportMinPrice = val; } - void setTeleportPriceExponent(F32 val) { mTeleportPriceExponent = val; } - void setPriceGroupCreate(S32 val) { mPriceGroupCreate = val; } - -private: - S32 mObjectCount; - S32 mObjectCapacity; - S32 mPriceObjectClaim; // per primitive - S32 mPricePublicObjectDecay; // per primitive - S32 mPricePublicObjectDelete; // per primitive - S32 mPriceEnergyUnit; - S32 mPriceUpload; - S32 mPriceRentLight; - S32 mTeleportMinPrice; - F32 mTeleportPriceExponent; - S32 mPriceGroupCreate; - - std::list mObservers; -}; - - -class LLRegionEconomy : public LLGlobalEconomy -{ -public: - LLRegionEconomy(); - ~LLRegionEconomy(); - - static void processEconomyData(LLMessageSystem *msg, void **user_data); - static void processEconomyDataRequest(LLMessageSystem *msg, void **user_data); - - void print(); - - BOOL hasData() const; - F32 getPriceObjectRent() const { return mPriceObjectRent; } - F32 getPriceObjectScaleFactor() const {return mPriceObjectScaleFactor;} - F32 getEnergyEfficiency() const { return mEnergyEfficiency; } - S32 getPriceParcelClaim() const; - S32 getPriceParcelRent() const; - F32 getAreaOwned() const { return mAreaOwned; } - F32 getAreaTotal() const { return mAreaTotal; } - S32 getBasePriceParcelClaimActual() const { return mBasePriceParcelClaimActual; } - - void setPriceObjectRent(F32 val) { mPriceObjectRent = val; } - void setPriceObjectScaleFactor(F32 val) { mPriceObjectScaleFactor = val; } - void setEnergyEfficiency(F32 val) { mEnergyEfficiency = val; } - - void setBasePriceParcelClaimDefault(S32 val); - void setBasePriceParcelClaimActual(S32 val); - void setPriceParcelClaimFactor(F32 val); - void setBasePriceParcelRent(S32 val); - - void setAreaOwned(F32 val) { mAreaOwned = val; } - void setAreaTotal(F32 val) { mAreaTotal = val; } - -private: - F32 mPriceObjectRent; - F32 mPriceObjectScaleFactor; - F32 mEnergyEfficiency; - - S32 mBasePriceParcelClaimDefault; - S32 mBasePriceParcelClaimActual; - F32 mPriceParcelClaimFactor; - S32 mBasePriceParcelRent; - - F32 mAreaOwned; - F32 mAreaTotal; - -}; - -#endif diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp index dbb692bdeb..f0a865f0d4 100644 --- a/indra/llinventory/llfoldertype.cpp +++ b/indra/llinventory/llfoldertype.cpp @@ -101,9 +101,16 @@ LLFolderDictionary::LLFolderDictionary() addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE)); addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", TRUE)); + addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE)); - addEntry(LLFolderType::FT_SUITCASE, new FolderEntry("suitcase", FALSE)); + addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new FolderEntry("merchant", TRUE)); + addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new FolderEntry("stock", FALSE)); + addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new FolderEntry("version", FALSE)); + + addEntry(LLFolderType::FT_SETTINGS, new FolderEntry("settings", TRUE)); + + addEntry(LLFolderType::FT_SUITCASE, new FolderEntry("suitcase", TRUE)); addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE)); }; diff --git a/indra/llinventory/llfoldertype.h b/indra/llinventory/llfoldertype.h index bb9a3f213c..5f41578dd3 100644 --- a/indra/llinventory/llfoldertype.h +++ b/indra/llinventory/llfoldertype.h @@ -94,6 +94,12 @@ class LLFolderType FT_BASIC_ROOT = 52, + FT_MARKETPLACE_LISTINGS = 53, + FT_MARKETPLACE_STOCK = 54, + FT_MARKETPLACE_VERSION = 55, // Note: We actually *never* create folders with that type. This is used for icon override only. + + FT_SETTINGS = 56, + FT_SUITCASE = 100, FT_COUNT, diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 4a21ea3343..e14ae90271 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -416,12 +416,17 @@ U32 LLInventoryItem::getCRC32() const return crc; } +// static +void LLInventoryItem::correctInventoryDescription(std::string& desc) +{ + LLStringUtil::replaceNonstandardASCII(desc, ' '); + LLStringUtil::replaceChar(desc, '|', ' '); +} void LLInventoryItem::setDescription(const std::string& d) { std::string new_desc(d); - LLStringUtil::replaceNonstandardASCII(new_desc, ' '); - LLStringUtil::replaceChar(new_desc, '|', ' '); + LLInventoryItem::correctInventoryDescription(new_desc); if( new_desc != mDescription ) { mDescription = new_desc; @@ -831,7 +836,7 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream) } else if(0 == strcmp("permissions", keyword)) { - success = mPermissions.importStream(input_stream); + success = mPermissions.importLegacyStream(input_stream); } else if(0 == strcmp("sale_info", keyword)) { @@ -841,7 +846,7 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream) // should pick up the vast majority of the tasks. BOOL has_perm_mask = FALSE; U32 perm_mask = 0; - success = mSaleInfo.importStream(input_stream, has_perm_mask, perm_mask); + success = mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask); if(has_perm_mask) { if(perm_mask == PERM_NONE) @@ -957,7 +962,7 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu output_stream << "\t\titem_id\t" << uuid_str << "\n"; mParentUUID.toString(uuid_str); output_stream << "\t\tparent_id\t" << uuid_str << "\n"; - mPermissions.exportStream(output_stream); + mPermissions.exportLegacyStream(output_stream); // Check for permissions to see the asset id, and if so write it // out as an asset id. Otherwise, apply our cheesy encryption. @@ -991,7 +996,7 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu std::string buffer; buffer = llformat( "\t\tflags\t%08x\n", mFlags); output_stream << buffer; - mSaleInfo.exportStream(output_stream); + mSaleInfo.exportLegacyStream(output_stream); output_stream << "\t\tname\t" << mName.c_str() << "|\n"; output_stream << "\t\tdesc\t" << mDescription.c_str() << "|\n"; output_stream << "\t\tcreation_date\t" << mCreationDate << "\n"; @@ -1041,12 +1046,12 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate; } -LLFastTimer::DeclareTimer FTM_INVENTORY_SD_DESERIALIZE("Inventory SD Deserialize"); +LLTrace::BlockTimerStatHandle FTM_INVENTORY_SD_DESERIALIZE("Inventory SD Deserialize"); bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) { - LLFastTimer _(FTM_INVENTORY_SD_DESERIALIZE); + LL_RECORD_BLOCK_TIME(FTM_INVENTORY_SD_DESERIALIZE); if (is_new) { // If we're adding LLSD to an existing object, need avoid @@ -1160,13 +1165,15 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) // mType, these are the two asset types that are IT_WEARABLE: static U32 AT_BODYPART = 13; // LLAssetType::AT_BODYPART // Viewer local values: - static U32 WT_UNKNOWN = 16; // LLWearableType::WT_UNKNOWN - static U32 WT_COUNT = 17; // LLWearableType::WT_COUNT + static U32 WT_UNKNOWN = 17; // LLWearableType::WT_UNKNOWN + static U32 WT_COUNT = 18; // LLWearableType::WT_COUNT + // Keep WT_UNKNOWN and WT_COUNT + // in sync with llwearabletype.h // The last 8 bits of mFlags contain the wearable type. - static U32 II_FLAGS_WEARABLES_MASK = 0xff; // LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK + static U32 II_FLAGS_SUBTYPE_MASK = 0xff; // LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK // The wearable type is stored in the lower 8 bits of mFlags. - U32 wt = mFlags & II_FLAGS_WEARABLES_MASK; + U32 wt = mFlags & II_FLAGS_SUBTYPE_MASK; // Because WT_UNKNOWN now has locally a special meaning, make sure we don't receive it from the server. if (wt == WT_UNKNOWN) @@ -1309,11 +1316,11 @@ void LLInventoryItem::unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size) setUUID(item_id); LLAssetType::EType type; - type = (LLAssetType::EType)(atoi((*(iter++)).c_str())); + type = static_cast(std::stoi((*(iter++)))); setType( type ); LLInventoryType::EType inv_type; - inv_type = (LLInventoryType::EType)(atoi((*(iter++)).c_str())); + inv_type = static_cast(std::stoi((*(iter++)))); setInventoryType( inv_type ); std::string name((*(iter++)).c_str()); @@ -1341,8 +1348,8 @@ void LLInventoryItem::unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size) setDescription(desc); LLSaleInfo::EForSale sale_type; - sale_type = (LLSaleInfo::EForSale)(atoi((*(iter++)).c_str())); - S32 price = atoi((*(iter++)).c_str()); + sale_type = static_cast(std::stoi((*(iter++)))); + S32 price = std::stoi(*(iter++)); LLSaleInfo sale_info(sale_type, price); setSaleInfo(sale_info); @@ -1411,6 +1418,10 @@ LLSD LLInventoryCategory::asLLSD() const return sd; } +bool LLInventoryCategory::isPreferredTypeRoot() const +{ + return (mPreferredType == LLFolderType::FT_ROOT_INVENTORY || mPreferredType == 9); +} // virtual void LLInventoryCategory::packMessage(LLMessageSystem* msg) const diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index ce58bbb2d0..a4bb17b5ab 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -90,16 +90,12 @@ class LLInventoryObject : public LLRefCount // in place correction for inventory name string static void correctInventoryName(std::string& name); // [/RLVa:KB] -private: -// // in place correction for inventory name string -// void correctInventoryName(std::string& name); //-------------------------------------------------------------------- // File Support // Implemented here so that a minimal information set can be transmitted // between simulator and viewer. //-------------------------------------------------------------------- -public: // virtual BOOL importFile(LLFILE* fp); virtual BOOL exportFile(LLFILE* fp, BOOL include_asset_key = TRUE) const; virtual BOOL importLegacyStream(std::istream& input_stream); @@ -177,6 +173,7 @@ class LLInventoryItem : public LLInventoryObject //-------------------------------------------------------------------- public: void setAssetUUID(const LLUUID& asset_id); + static void correctInventoryDescription(std::string& name); void setDescription(const std::string& new_desc); void setSaleInfo(const LLSaleInfo& sale_info); void setPermissions(const LLPermissions& perm); @@ -261,6 +258,7 @@ class LLInventoryCategory : public LLInventoryObject void setPreferredType(LLFolderType::EType type); LLSD asLLSD() const; bool fromLLSD(const LLSD& sd); + bool isPreferredTypeRoot() const; //-------------------------------------------------------------------- // Messaging diff --git a/indra/llinventory/llinventorydefines.cpp b/indra/llinventory/llinventorydefines.cpp index 7def65a308..575331a263 100644 --- a/indra/llinventory/llinventorydefines.cpp +++ b/indra/llinventory/llinventorydefines.cpp @@ -2,33 +2,26 @@ * @file llinventorydefines.cpp * @brief Implementation of the inventory defines. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2010, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlife.com/developers/opensource/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ + * 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" diff --git a/indra/llinventory/llinventorydefines.h b/indra/llinventory/llinventorydefines.h index fc81d1f729..54562673f3 100644 --- a/indra/llinventory/llinventorydefines.h +++ b/indra/llinventory/llinventorydefines.h @@ -2,33 +2,26 @@ * @file llinventorydefines.h * @brief LLInventoryDefines * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2010, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlife.com/developers/opensource/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ + * 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_LLINVENTORYDEFINES_H @@ -88,9 +81,10 @@ class LLInventoryItemFlags II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS = 0x200000, // Whether a returned object is composed of multiple items. - II_FLAGS_WEARABLES_MASK = 0xff, - // Wearables use the low order byte of flags to store the - // LLWearableType::EType enumeration found in newview/llwearable.h + II_FLAGS_SUBTYPE_MASK = 0x0000ff, + // Some items like Wearables and settings use the low order byte + // of flags to store the sub type of the inventory item. + // see LLWearableType::EType enumeration found in newview/llwearable.h II_FLAGS_PERM_OVERWRITE_MASK = (II_FLAGS_OBJECT_SLAM_PERM | II_FLAGS_OBJECT_SLAM_SALE | diff --git a/indra/llinventory/llinventorysettings.cpp b/indra/llinventory/llinventorysettings.cpp new file mode 100644 index 0000000000..bf8043d4d2 --- /dev/null +++ b/indra/llinventory/llinventorysettings.cpp @@ -0,0 +1,117 @@ +/** +* @file llinventorysettings.cpp +* @author optional +* @brief A base class for asset based settings groups. +* +* $LicenseInfo:2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2017, 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 "llinventorysettings.h" +#include "llinventorytype.h" +#include "llinventorydefines.h" +#include "lldictionary.h" +#include "llsingleton.h" +#include "llinvtranslationbrdg.h" + +//========================================================================= +namespace { + LLTranslationBridge::ptr_t sTranslator; +} + +//========================================================================= +struct SettingsEntry : public LLDictionaryEntry +{ + SettingsEntry(const std::string &name, + const std::string& default_new_name, + LLInventoryType::EIconName iconName) : + LLDictionaryEntry(name), + mDefaultNewName(default_new_name), + mLabel(name), + mIconName(iconName) + { + std::string transdname = sTranslator->getString(mLabel); + if (!transdname.empty()) + { + mLabel = transdname; + } + } + + std::string mLabel; + std::string mDefaultNewName; //keep mLabel for backward compatibility + LLInventoryType::EIconName mIconName; +}; + +class LLSettingsDictionary : public LLSingleton, + public LLDictionary +{ + friend class LLSingleton; \ + LLSettingsDictionary(); + + void initSingleton(); +}; + +LLSettingsDictionary::LLSettingsDictionary() +{ +} + +void LLSettingsDictionary::initSingleton() +{ + addEntry(LLSettingsType::ST_SKY, new SettingsEntry("sky", "New Sky", LLInventoryType::ICONNAME_SETTINGS_SKY)); + addEntry(LLSettingsType::ST_WATER, new SettingsEntry("water", "New Water", LLInventoryType::ICONNAME_SETTINGS_WATER)); + addEntry(LLSettingsType::ST_DAYCYCLE, new SettingsEntry("day", "New Day", LLInventoryType::ICONNAME_SETTINGS_DAY)); + addEntry(LLSettingsType::ST_NONE, new SettingsEntry("none", "New Settings", LLInventoryType::ICONNAME_SETTINGS)); + addEntry(LLSettingsType::ST_INVALID, new SettingsEntry("invalid", "New Settings", LLInventoryType::ICONNAME_SETTINGS)); +} + +//========================================================================= + +LLSettingsType::type_e LLSettingsType::fromInventoryFlags(U32 flags) +{ + return (LLSettingsType::type_e)(flags & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK); +} + +LLInventoryType::EIconName LLSettingsType::getIconName(LLSettingsType::type_e type) +{ + const SettingsEntry *entry = LLSettingsDictionary::instance().lookup(type); + if (!entry) + return getIconName(ST_INVALID); + return entry->mIconName; +} + +std::string LLSettingsType::getDefaultName(LLSettingsType::type_e type) +{ + const SettingsEntry *entry = LLSettingsDictionary::instance().lookup(type); + if (!entry) + return getDefaultName(ST_INVALID); + return entry->mDefaultNewName; +} + +void LLSettingsType::initClass(LLTranslationBridge::ptr_t &trans) +{ + sTranslator = trans; +} + +void LLSettingsType::cleanupClass() +{ + sTranslator.reset(); +} diff --git a/indra/llinventory/llinventorysettings.h b/indra/llinventory/llinventorysettings.h new file mode 100644 index 0000000000..906540689c --- /dev/null +++ b/indra/llinventory/llinventorysettings.h @@ -0,0 +1,56 @@ +/** +* @file llinventorysettings.h +* @author optional +* @brief A base class for asset based settings groups. +* +* $LicenseInfo:2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2017, 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_INVENTORY_SETTINGS_H +#define LL_INVENTORY_SETTINGS_H + +#include "llinventorytype.h" +#include "llinvtranslationbrdg.h" + +class LLSettingsType +{ +public: + enum type_e + { + ST_SKY = 0, + ST_WATER = 1, + ST_DAYCYCLE = 2, + + ST_INVALID = 255, + ST_NONE = -1 + }; + + static type_e fromInventoryFlags(U32 flags); + static LLInventoryType::EIconName getIconName(type_e type); + static std::string getDefaultName(type_e type); + + static void initClass(LLTranslationBridge::ptr_t &trans); + static void cleanupClass(); +}; + + +#endif diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index 1f30c771b5..30f98eb2a0 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -53,6 +53,7 @@ struct InventoryEntry : public LLDictionaryEntry LLAssetType::EType t = (LLAssetType::EType)va_arg(argp,int); mAssetTypes.push_back(t); } + va_end(argp); } const std::string mHumanName; @@ -84,6 +85,7 @@ LLInventoryDictionary::LLInventoryDictionary() addEntry(LLInventoryType::IT_ANIMATION, new InventoryEntry("animation", "animation", 1, LLAssetType::AT_ANIMATION)); addEntry(LLInventoryType::IT_GESTURE, new InventoryEntry("gesture", "gesture", 1, LLAssetType::AT_GESTURE)); addEntry(LLInventoryType::IT_MESH, new InventoryEntry("mesh", "mesh", 1, LLAssetType::AT_MESH)); + addEntry(LLInventoryType::IT_SETTINGS, new InventoryEntry("settings", "settings", 1, LLAssetType::AT_SETTINGS)); } @@ -144,6 +146,15 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = LLInventoryType::IT_NONE, // 47 AT_NONE LLInventoryType::IT_NONE, // 48 AT_NONE LLInventoryType::IT_MESH, // 49 AT_MESH + + LLInventoryType::IT_NONE, // 50 AT_RESERVED_1 + LLInventoryType::IT_NONE, // 52 AT_RESERVED_2 + LLInventoryType::IT_NONE, // 53 AT_RESERVED_3 + LLInventoryType::IT_NONE, // 54 AT_RESERVED_4 + LLInventoryType::IT_NONE, // 55 AT_RESERVED_5 + LLInventoryType::IT_NONE, // 56 AT_RESERVED_6 + + LLInventoryType::IT_SETTINGS, // 57 AT_SETTINGS }; // static @@ -180,7 +191,7 @@ LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType a } else { - return IT_NONE; + return IT_UNKNOWN; } } @@ -199,6 +210,12 @@ bool LLInventoryType::cannotRestrictPermissions(LLInventoryType::EType type) } } +// Should show permissions that apply only to objects rezed in world. +bool LLInventoryType::showInWorldPermissions(LLInventoryType::EType type) +{ + return (type != IT_SETTINGS); +} + bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type, LLAssetType::EType asset_type) { diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index b444ecfa54..a7aa1dfbf5 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -62,8 +62,10 @@ class LLInventoryType IT_ANIMATION = 19, IT_GESTURE = 20, IT_MESH = 22, - IT_COUNT = 23, + IT_SETTINGS = 25, + IT_COUNT = 26, + IT_UNKNOWN = 255, IT_NONE = -1 }; @@ -98,6 +100,7 @@ class LLInventoryType ICONNAME_CLOTHING_SKIRT, ICONNAME_CLOTHING_ALPHA, ICONNAME_CLOTHING_TATTOO, + ICONNAME_CLOTHING_UNIVERSAL, ICONNAME_ANIMATION, ICONNAME_GESTURE, @@ -108,8 +111,14 @@ class LLInventoryType ICONNAME_LINKFOLDER, ICONNAME_MESH, + ICONNAME_SETTINGS, + ICONNAME_SETTINGS_SKY, + ICONNAME_SETTINGS_WATER, + ICONNAME_SETTINGS_DAY, + ICONNAME_CLOTHING_UNKNOWN, ICONNAME_INVALID, + ICONNAME_UNKNOWN, ICONNAME_COUNT, ICONNAME_NONE = -1 }; @@ -127,6 +136,8 @@ class LLInventoryType // true if this type cannot have restricted permissions. static bool cannotRestrictPermissions(EType type); + static bool showInWorldPermissions(EType type); + private: // don't instantiate or derive one of these objects LLInventoryType( void ); diff --git a/indra/llinventory/llinvtranslationbrdg.h b/indra/llinventory/llinvtranslationbrdg.h new file mode 100644 index 0000000000..715c60c30d --- /dev/null +++ b/indra/llinventory/llinvtranslationbrdg.h @@ -0,0 +1,43 @@ +/** +* @file llinvtranslationbrdg.h +* @brief Translation adapter for inventory. +* +* $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_TRANSLATIONBRDG_H +#define LL_TRANSLATIONBRDG_H + +#include + +class LLTranslationBridge +{ +public: + typedef std::shared_ptr ptr_t; + + // clang needs this to be happy + virtual ~LLTranslationBridge() {} + + virtual std::string getString(const std::string &xml_desc) = 0; +}; + +#endif diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index 02cc55e1e0..158c2edc52 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -40,6 +40,8 @@ #include "llsdutil_math.h" #include "message.h" #include "u64.h" +#include "llregionflags.h" +#include static const F32 SOME_BIG_NUMBER = 1000.0f; static const F32 SOME_BIG_NEG_NUMBER = -1000.0f; @@ -230,6 +232,9 @@ void LLParcel::init(const LLUUID &owner_id, setAllowGroupAVSounds(TRUE); setAllowAnyAVSounds(TRUE); setHaveNewParcelLimitData(FALSE); + + setRegionAllowEnvironmentOverride(FALSE); + setParcelEnvironmentVersion(INVALID_PARCEL_ENVIRONMENT_VERSION); } void LLParcel::overrideOwner(const LLUUID& owner_id, BOOL is_group_owned) @@ -739,8 +744,8 @@ void LLParcel::unpackMessage(LLMessageSystem* msg) void LLParcel::packAccessEntries(LLMessageSystem* msg, const std::map& list) { - access_map_const_iterator cit = list.begin(); - access_map_const_iterator end = list.end(); + LLAccessEntry::map::const_iterator cit = list.begin(); + LLAccessEntry::map::const_iterator end = list.end(); if (cit == end) { @@ -791,16 +796,35 @@ void LLParcel::unpackAccessEntries(LLMessageSystem* msg, } +void LLParcel::unpackExperienceEntries(LLMessageSystem* msg, U32 type) +{ + LLUUID id; + + S32 i; + S32 count = msg->getNumberOfBlocksFast(_PREHASH_List); + for (i = 0; i < count; i++) + { + msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i); + + if (id.notNull()) + { + mExperienceKeys[id] = type; + } + } +} + + + void LLParcel::expirePasses(S32 now) { - access_map_iterator itor = mAccessList.begin(); + LLAccessEntry::map::iterator itor = mAccessList.begin(); while (itor != mAccessList.end()) { const LLAccessEntry& entry = (*itor).second; if (entry.mTime != 0 && entry.mTime < now) { - mAccessList.erase(itor++); + itor = mAccessList.erase(itor); } else { @@ -883,7 +907,7 @@ BOOL LLParcel::addToAccessList(const LLUUID& agent_id, S32 time) // Can't add owner to these lists return FALSE; } - access_map_iterator itor = mAccessList.begin(); + LLAccessEntry::map::iterator itor = mAccessList.begin(); while (itor != mAccessList.end()) { const LLAccessEntry& entry = (*itor).second; @@ -891,7 +915,7 @@ BOOL LLParcel::addToAccessList(const LLUUID& agent_id, S32 time) { if (time == 0 || (entry.mTime != 0 && entry.mTime < time)) { - mAccessList.erase(itor++); + itor = mAccessList.erase(itor); } else { @@ -928,21 +952,24 @@ BOOL LLParcel::addToBanList(const LLUUID& agent_id, S32 time) return FALSE; } - access_map_iterator itor = mBanList.begin(); + LLAccessEntry::map::iterator itor = mBanList.begin(); while (itor != mBanList.end()) { const LLAccessEntry& entry = (*itor).second; if (entry.mID == agent_id) { - if (time == 0 || (entry.mTime != 0 && entry.mTime < time)) + // Singu Note: Allow amending ban time to be less without needing to remove + //if (time == 0 || (entry.mTime != 0 && entry.mTime < time)) { - mBanList.erase(itor++); + itor = mBanList.erase(itor); } +#if 0 else { // existing one expires later return FALSE; } +#endif } else { @@ -964,13 +991,13 @@ BOOL remove_from_access_array(std::map* list, const LLUUID& agent_id) { BOOL removed = FALSE; - access_map_iterator itor = list->begin(); + LLAccessEntry::map::iterator itor = list->begin(); while (itor != list->end()) { const LLAccessEntry& entry = (*itor).second; if (entry.mID == agent_id) { - list->erase(itor++); + itor = list->erase(itor); removed = TRUE; } else @@ -1083,9 +1110,9 @@ void LLParcel::startSale(const LLUUID& buyer_id, BOOL is_buyer_group) mGroupID.setNull(); } mSaleTimerExpires.start(); - mSaleTimerExpires.setTimerExpirySec(DEFAULT_USEC_SALE_TIMEOUT / SEC_TO_MICROSEC); + mSaleTimerExpires.setTimerExpirySec(U64Microseconds(DEFAULT_USEC_SALE_TIMEOUT)); mStatus = OS_LEASE_PENDING; - mClaimDate = time(NULL); + mClaimDate = time(nullptr); setAuctionID(0); // clear the autoreturn whenever land changes hands setCleanOtherTime(0); @@ -1307,3 +1334,58 @@ LLParcel::ECategory category_ui_string_to_category(const std::string& s) // is a distinct option from "None" and "Other" return LLParcel::C_ANY; } + +LLAccessEntry::map LLParcel::getExperienceKeysByType(U32 type) const +{ + LLAccessEntry::map access; + LLAccessEntry entry; + xp_type_map_t::const_iterator it = mExperienceKeys.begin(); + for(/**/; it != mExperienceKeys.end(); ++it) + { + if(it->second == type) + { + entry.mID = it->first; + access[entry.mID] = entry; + } + } + return access; +} + +void LLParcel::clearExperienceKeysByType(U32 type) +{ + xp_type_map_t::iterator it = mExperienceKeys.begin(); + while(it != mExperienceKeys.end()) + { + if(it->second == type) + { + mExperienceKeys.erase(it++); + } + else + { + ++it; + } + } +} + +void LLParcel::setExperienceKeyType(const LLUUID& experience_key, U32 type) +{ + if (type == EXPERIENCE_KEY_TYPE_NONE) + { + mExperienceKeys.erase(experience_key); + } + else + { + if (countExperienceKeyType(type) < PARCEL_MAX_EXPERIENCE_LIST) + { + mExperienceKeys[experience_key] = type; + } + } +} + +U32 LLParcel::countExperienceKeyType(U32 type) +{ + return std::count_if( + boost::begin(mExperienceKeys | boost::adaptors::map_values), + boost::end(mExperienceKeys | boost::adaptors::map_values), + std::bind2nd(std::equal_to(), type)); +} diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index ce3e0eab17..c1322c3874 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -40,6 +40,7 @@ #include "llpermissions.h" #include "lltimer.h" #include "v3math.h" +#include "llsettingsdaycycle.h" // Grid out of which parcels taken is stepped every 4 meters. const F32 PARCEL_GRID_STEP_METERS = 4.f; @@ -59,6 +60,9 @@ const S32 PARCEL_MAX_ACCESS_LIST = 300; //for access/ban lists. const F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f; +// Maximum number of experiences +const S32 PARCEL_MAX_EXPERIENCE_LIST = 24; + // Weekly charge for listing a parcel in the directory const S32 PARCEL_DIRECTORY_FEE = 30; @@ -105,6 +109,10 @@ const U32 RT_SELL = 0x1 << 5; const S32 INVALID_PARCEL_ID = -1; +const S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2; +// if Region settings are used, parcel env. version is -1 +const S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1; + // Timeouts for parcels // default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000 const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000); @@ -136,9 +144,11 @@ class LLSD; class LLAccessEntry { public: + + typedef std::map map; + LLAccessEntry() - : mID(), - mTime(0), + : mTime(0), mFlags(0) {} @@ -147,8 +157,6 @@ class LLAccessEntry U32 mFlags; // Not used - currently should always be zero }; -typedef std::map::iterator access_map_iterator; -typedef std::map::const_iterator access_map_const_iterator; class LLParcel { @@ -326,6 +334,9 @@ class LLParcel void unpackAccessEntries(LLMessageSystem* msg, std::map* list); + void unpackExperienceEntries(LLMessageSystem* msg, U32 type); + + void setAABBMin(const LLVector3& min) { mAABBMin = min; } void setAABBMax(const LLVector3& max) { mAABBMax = max; } @@ -508,6 +519,13 @@ class LLParcel { return mRegionDenyAnonymousOverride; } BOOL getRegionDenyAgeUnverifiedOverride() const { return mRegionDenyAgeUnverifiedOverride; } + BOOL getRegionAllowAccessOverride() const + { return mRegionAllowAccessoverride; } + BOOL getRegionAllowEnvironmentOverride() const + { return mRegionAllowEnvironmentOverride; } + S32 getParcelEnvironmentVersion() const + { return mCurrentEnvironmentVersion; } + BOOL getAllowGroupAVSounds() const { return mAllowGroupAVSounds; } BOOL getAllowAnyAVSounds() const { return mAllowAnyAVSounds; } @@ -593,6 +611,10 @@ class LLParcel void setRegionPushOverride(BOOL override) {mRegionPushOverride = override; } void setRegionDenyAnonymousOverride(BOOL override) { mRegionDenyAnonymousOverride = override; } void setRegionDenyAgeUnverifiedOverride(BOOL override) { mRegionDenyAgeUnverifiedOverride = override; } + void setRegionAllowAccessOverride(BOOL override) { mRegionAllowAccessoverride = override; } + void setRegionAllowEnvironmentOverride(BOOL override) { mRegionAllowEnvironmentOverride = override; } + + void setParcelEnvironmentVersion(S32 version) { mCurrentEnvironmentVersion = version; } // Accessors for parcel sellWithObjects void setPreviousOwnerID(LLUUID prev_owner) { mPreviousOwnerID = prev_owner; } @@ -603,7 +625,6 @@ class LLParcel BOOL getPreviouslyGroupOwned() const { return mPreviouslyGroupOwned; } BOOL getSellWithObjects() const { return (mParcelFlags & PF_SELL_PARCEL_OBJECTS) ? TRUE : FALSE; } - protected: LLUUID mID; LLUUID mOwnerID; @@ -674,9 +695,13 @@ class LLParcel BOOL mRegionPushOverride; BOOL mRegionDenyAnonymousOverride; BOOL mRegionDenyAgeUnverifiedOverride; + BOOL mRegionAllowAccessoverride; + BOOL mRegionAllowEnvironmentOverride; BOOL mAllowGroupAVSounds; BOOL mAllowAnyAVSounds; + S32 mCurrentEnvironmentVersion; + bool mIsDefaultDayCycle; public: // HACK, make private @@ -688,6 +713,17 @@ class LLParcel std::map mTempBanList; std::map mTempAccessList; + typedef std::map xp_type_map_t; + + void setExperienceKeyType(const LLUUID& experience_key, U32 type); + U32 countExperienceKeyType(U32 type); + U32 getExperienceKeyType(const LLUUID& experience_key)const; + LLAccessEntry::map getExperienceKeysByType(U32 type)const; + void clearExperienceKeysByType(U32 type); + +private: + xp_type_map_t mExperienceKeys; + }; diff --git a/indra/llinventory/llparcelflags.h b/indra/llinventory/llparcelflags.h index 3430447276..fbfc2af1d2 100644 --- a/indra/llinventory/llparcelflags.h +++ b/indra/llinventory/llparcelflags.h @@ -1,31 +1,25 @@ /** * @file llparcelflags.h * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * 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. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -68,7 +62,7 @@ const U32 PF_ALLOW_ALL_OBJECT_ENTRY = 1 << 27; // Allow all objects to enter a const U32 PF_ALLOW_GROUP_OBJECT_ENTRY = 1 << 28; // Only allow group (and owner) objects to enter the parcel const U32 PF_ALLOW_VOICE_CHAT = 1 << 29; // Allow residents to use voice chat on this parcel const U32 PF_USE_ESTATE_VOICE_CHAN = 1 << 30; -const U32 PF_DENY_AGEUNVERIFIED = 1 << 31; // Prevent residents who aren't age-verified +const U32 PF_DENY_AGEUNVERIFIED = 1U << 31; // Prevent residents who aren't age-verified // NOTE: At one point we have used all of the bits. // We have deprecated two of them in 1.19.0 which *could* be reused, // but only after we are certain there are no simstates using those bits. @@ -97,8 +91,10 @@ const U32 PF_DEFAULT = PF_ALLOW_FLY | PF_USE_ESTATE_VOICE_CHAN; // Access list flags -const U32 AL_ACCESS = (1 << 0); -const U32 AL_BAN = (1 << 1); +const U32 AL_ACCESS = (1 << 0); +const U32 AL_BAN = (1 << 1); +const U32 AL_ALLOW_EXPERIENCE = (1 << 3); +const U32 AL_BLOCK_EXPERIENCE = (1 << 4); //const U32 AL_RENTER = (1 << 2); // Block access return values. BA_ALLOWED is the only success case diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp index b0deafdfe8..2316c635d2 100644 --- a/indra/llinventory/llpermissions.cpp +++ b/indra/llinventory/llpermissions.cpp @@ -31,7 +31,6 @@ // library includes #include "message.h" -#include "metapropertyt.h" #include "llsd.h" ///---------------------------------------------------------------------------- @@ -572,17 +571,143 @@ void LLPermissions::unpackMessage(LLMessageSystem* msg, const char* block, S32 b BOOL LLPermissions::importFile(LLFILE* fp) { - llifstream ifs(fp); - return importStream(ifs); + init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null); + const S32 BUFSIZE = 16384; + + // *NOTE: Changing the buffer size will require changing the scanf + // calls below. + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + char uuid_str[256]; /* Flawfinder: ignore */ + U32 mask; + + keyword[0] = '\0'; + valuestr[0] = '\0'; + + while (!feof(fp)) + { + if (fgets(buffer, BUFSIZE, fp) == NULL) + { + buffer[0] = '\0'; + } + + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("creator_mask", keyword)) + { + // legacy support for "creator" masks + sscanf(valuestr, "%x", &mask); + mMaskBase = mask; + fixFairUse(); + } + else if (!strcmp("base_mask", keyword)) + { + sscanf(valuestr, "%x", &mask); + mMaskBase = mask; + //fixFairUse(); + } + else if (!strcmp("owner_mask", keyword)) + { + sscanf(valuestr, "%x", &mask); + mMaskOwner = mask; + } + else if (!strcmp("group_mask", keyword)) + { + sscanf(valuestr, "%x", &mask); + mMaskGroup = mask; + } + else if (!strcmp("everyone_mask", keyword)) + { + sscanf(valuestr, "%x", &mask); + mMaskEveryone = mask; + } + else if (!strcmp("next_owner_mask", keyword)) + { + sscanf(valuestr, "%x", &mask); + mMaskNextOwner = mask; + } + else if (!strcmp("creator_id", keyword)) + { + sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ + mCreator.set(uuid_str); + } + else if (!strcmp("owner_id", keyword)) + { + sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ + mOwner.set(uuid_str); + } + else if (!strcmp("last_owner_id", keyword)) + { + sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ + mLastOwner.set(uuid_str); + } + else if (!strcmp("group_id", keyword)) + { + sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ + mGroup.set(uuid_str); + } + else if (!strcmp("group_owned", keyword)) + { + sscanf(valuestr, "%d", &mask); + if(mask) mIsGroupOwned = true; + else mIsGroupOwned = false; + } + else + { + LL_INFOS() << "unknown keyword " << keyword << " in permissions import" << LL_ENDL; + } + } + fix(); + return TRUE; } + BOOL LLPermissions::exportFile(LLFILE* fp) const { - llofstream ofs(fp); - return exportStream(ofs); + std::string uuid_str; + + fprintf(fp, "\tpermissions 0\n"); + fprintf(fp, "\t{\n"); + + fprintf(fp, "\t\tbase_mask\t%08x\n", mMaskBase); + fprintf(fp, "\t\towner_mask\t%08x\n", mMaskOwner); + fprintf(fp, "\t\tgroup_mask\t%08x\n", mMaskGroup); + fprintf(fp, "\t\teveryone_mask\t%08x\n", mMaskEveryone); + fprintf(fp, "\t\tnext_owner_mask\t%08x\n", mMaskNextOwner); + + mCreator.toString(uuid_str); + fprintf(fp, "\t\tcreator_id\t%s\n", uuid_str.c_str()); + + mOwner.toString(uuid_str); + fprintf(fp, "\t\towner_id\t%s\n", uuid_str.c_str()); + + mLastOwner.toString(uuid_str); + fprintf(fp, "\t\tlast_owner_id\t%s\n", uuid_str.c_str()); + + mGroup.toString(uuid_str); + fprintf(fp, "\t\tgroup_id\t%s\n", uuid_str.c_str()); + + if(mIsGroupOwned) + { + fprintf(fp, "\t\tgroup_owned\t1\n"); + } + fprintf(fp,"\t}\n"); + return TRUE; } -BOOL LLPermissions::importStream(std::istream& input_stream) + +BOOL LLPermissions::importLegacyStream(std::istream& input_stream) { init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null); const S32 BUFSIZE = 16384; @@ -601,18 +726,6 @@ BOOL LLPermissions::importStream(std::istream& input_stream) while (input_stream.good()) { input_stream.getline(buffer, BUFSIZE); - if (input_stream.eof()) - { - LL_WARNS() << "Bad permissions: early end of input stream" - << LL_ENDL; - return FALSE; - } - if (input_stream.fail()) - { - LL_WARNS() << "Bad permissions: failed to read from input stream" - << LL_ENDL; - return FALSE; - } sscanf( /* Flawfinder: ignore */ buffer, " %255s %255s", @@ -695,26 +808,36 @@ BOOL LLPermissions::importStream(std::istream& input_stream) } -BOOL LLPermissions::exportStream(std::ostream& output_stream) const +BOOL LLPermissions::exportLegacyStream(std::ostream& output_stream) const { - if (!output_stream.good()) return FALSE; + std::string uuid_str; + output_stream << "\tpermissions 0\n"; output_stream << "\t{\n"; - char prev_fill = output_stream.fill('0'); - output_stream << std::hex; - output_stream << "\t\tbase_mask\t" << std::setw(8) << mMaskBase << "\n"; - output_stream << "\t\towner_mask\t" << std::setw(8) << mMaskOwner << "\n"; - output_stream << "\t\tgroup_mask\t" << std::setw(8) << mMaskGroup << "\n"; - output_stream << "\t\teveryone_mask\t" << std::setw(8) << mMaskEveryone << "\n"; - output_stream << "\t\tnext_owner_mask\t" << std::setw(8) << mMaskNextOwner << "\n"; - output_stream << std::dec; - output_stream.fill(prev_fill); - - output_stream << "\t\tcreator_id\t" << mCreator << "\n"; - output_stream << "\t\towner_id\t" << mOwner << "\n"; - output_stream << "\t\tlast_owner_id\t" << mLastOwner << "\n"; - output_stream << "\t\tgroup_id\t" << mGroup << "\n"; + std::string buffer; + buffer = llformat( "\t\tbase_mask\t%08x\n", mMaskBase); + output_stream << buffer; + buffer = llformat( "\t\towner_mask\t%08x\n", mMaskOwner); + output_stream << buffer; + buffer = llformat( "\t\tgroup_mask\t%08x\n", mMaskGroup); + output_stream << buffer; + buffer = llformat( "\t\teveryone_mask\t%08x\n", mMaskEveryone); + output_stream << buffer; + buffer = llformat( "\t\tnext_owner_mask\t%08x\n", mMaskNextOwner); + output_stream << buffer; + + mCreator.toString(uuid_str); + output_stream << "\t\tcreator_id\t" << uuid_str << "\n"; + + mOwner.toString(uuid_str); + output_stream << "\t\towner_id\t" << uuid_str << "\n"; + + mLastOwner.toString(uuid_str); + output_stream << "\t\tlast_owner_id\t" << uuid_str << "\n"; + + mGroup.toString(uuid_str); + output_stream << "\t\tgroup_id\t" << uuid_str << "\n"; if(mIsGroupOwned) { @@ -772,21 +895,6 @@ std::ostream& operator<<(std::ostream &s, const LLPermissions &perm) return s; } -template <> -void LLMetaClassT::reflectProperties(LLMetaClass& meta_class) -{ - reflectProperty(meta_class, "mCreator", &LLPermissions::mCreator); - reflectProperty(meta_class, "mOwner", &LLPermissions::mOwner); - reflectProperty(meta_class, "mGroup", &LLPermissions::mGroup); - reflectProperty(meta_class, "mIsGroupOwned", &LLPermissions::mIsGroupOwned); -} - -// virtual -const LLMetaClass& LLPermissions::getMetaClass() const -{ - return LLMetaClassT::instance(); -} - ///---------------------------------------------------------------------------- /// Class LLAggregatePermissions ///---------------------------------------------------------------------------- @@ -1021,7 +1129,7 @@ void mask_to_string(U32 mask, char* str) else { *str = ' '; - } + } str++; if (mask & PERM_EXPORT) diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h index d3a65a5a6f..a69f6033df 100644 --- a/indra/llinventory/llpermissions.h +++ b/indra/llinventory/llpermissions.h @@ -31,7 +31,6 @@ #include "llsd.h" #include "lluuid.h" #include "llxmlnode.h" -#include "reflective.h" #include "llinventorytype.h" // prototypes @@ -89,7 +88,7 @@ enum ExportPolicy { // logical consistency. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLPermissions : public LLReflective +class LLPermissions { private: LLUUID mCreator; // null if object created by system @@ -329,17 +328,14 @@ class LLPermissions : public LLReflective BOOL importFile(LLFILE* fp); BOOL exportFile(LLFILE* fp) const; - BOOL importStream(std::istream& input_stream); - BOOL exportStream(std::ostream& output_stream) const; + BOOL importLegacyStream(std::istream& input_stream); + BOOL exportLegacyStream(std::ostream& output_stream) const; bool operator==(const LLPermissions &rhs) const; bool operator!=(const LLPermissions &rhs) const; friend std::ostream& operator<<(std::ostream &s, const LLPermissions &perm); - // Reflection. - friend class LLMetaClassT; - virtual const LLMetaClass& getMetaClass() const; }; // Inlines diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp index 2c5d163e3e..021c1d9d35 100644 --- a/indra/llinventory/llsaleinfo.cpp +++ b/indra/llinventory/llsaleinfo.cpp @@ -87,13 +87,15 @@ U32 LLSaleInfo::getCRC32() const BOOL LLSaleInfo::exportFile(LLFILE* fp) const { - llofstream ofs(fp); - return exportStream(ofs); + fprintf(fp, "\tsale_info\t0\n\t{\n"); + fprintf(fp, "\t\tsale_type\t%s\n", lookup(mSaleType)); + fprintf(fp, "\t\tsale_price\t%d\n", mSalePrice); + fprintf(fp,"\t}\n"); + return TRUE; } -BOOL LLSaleInfo::exportStream(std::ostream& output_stream) const +BOOL LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const { - if (!output_stream.good()) return FALSE; output_stream << "\tsale_info\t0\n\t{\n"; output_stream << "\t\tsale_type\t" << lookup(mSaleType) << "\n"; output_stream << "\t\tsale_price\t" << mSalePrice << "\n"; @@ -137,40 +139,81 @@ bool LLSaleInfo::fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask) // because I can't find any non-test code references to it. 2009-05-04 JC BOOL LLSaleInfo::importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask) -{ - llifstream ifs(fp); - return importStream(ifs, has_perm_mask, perm_mask); -} - -BOOL LLSaleInfo::importStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask) { has_perm_mask = FALSE; - const S32 BUFSIZE = 16384; - // *NOTE: Changing the buffer size will require changing the scanf // calls below. - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - char keyword[255]; /* Flawfinder: ignore */ - char valuestr[255]; /* Flawfinder: ignore */ + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + char keyword[MAX_STRING]; /* Flawfinder: ignore */ + char valuestr[MAX_STRING]; /* Flawfinder: ignore */ + BOOL success = TRUE; keyword[0] = '\0'; valuestr[0] = '\0'; - while(input_stream.good()) + while(success && (!feof(fp))) { - input_stream.getline(buffer, MAX_STRING); - if (input_stream.eof()) + if (fgets(buffer, MAX_STRING, fp) == NULL) + { + buffer[0] = '\0'; + } + + sscanf( /* Flawfinder: ignore */ + buffer, + " %254s %254s", + keyword, valuestr); + if(!keyword[0]) { - LL_WARNS() << "Bad sale info: early end of input stream" - << LL_ENDL; - return FALSE; + continue; + } + if(0 == strcmp("{",keyword)) + { + continue; + } + if(0 == strcmp("}", keyword)) + { + break; } - if (input_stream.fail()) + else if(0 == strcmp("sale_type", keyword)) { - LL_WARNS() << "Bad sale info: failed to read from input stream" - << LL_ENDL; - return FALSE; + mSaleType = lookup(valuestr); } + else if(0 == strcmp("sale_price", keyword)) + { + sscanf(valuestr, "%d", &mSalePrice); + mSalePrice = llclamp(mSalePrice, 0, S32_MAX); + } + else if (!strcmp("perm_mask", keyword)) + { + //LL_INFOS() << "found deprecated keyword perm_mask" << LL_ENDL; + has_perm_mask = TRUE; + sscanf(valuestr, "%x", &perm_mask); + } + else + { + LL_WARNS() << "unknown keyword '" << keyword + << "' in sale info import" << LL_ENDL; + } + } + return success; +} + +BOOL LLSaleInfo::importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask) +{ + has_perm_mask = FALSE; + + // *NOTE: Changing the buffer size will require changing the scanf + // calls below. + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + char keyword[MAX_STRING]; /* Flawfinder: ignore */ + char valuestr[MAX_STRING]; /* Flawfinder: ignore */ + BOOL success = TRUE; + + keyword[0] = '\0'; + valuestr[0] = '\0'; + while(success && input_stream.good()) + { + input_stream.getline(buffer, MAX_STRING); sscanf( /* Flawfinder: ignore */ buffer, " %254s %254s", @@ -208,7 +251,7 @@ BOOL LLSaleInfo::importStream(std::istream& input_stream, BOOL& has_perm_mask, U << "' in sale info import" << LL_ENDL; } } - return TRUE; + return success; } void LLSaleInfo::setSalePrice(S32 price) diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h index 8a01653a63..262aeb3dd2 100644 --- a/indra/llinventory/llsaleinfo.h +++ b/indra/llinventory/llsaleinfo.h @@ -95,11 +95,11 @@ class LLSaleInfo BOOL exportFile(LLFILE* fp) const; BOOL importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask); - BOOL exportStream(std::ostream& output_stream) const; + BOOL exportLegacyStream(std::ostream& output_stream) const; LLSD asLLSD() const; operator LLSD() const { return asLLSD(); } bool fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask); - BOOL importStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask); + BOOL importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask); LLSD packMessage() const; void unpackMessage(const LLSD& sales); diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp new file mode 100644 index 0000000000..978edbf2e5 --- /dev/null +++ b/indra/llinventory/llsettingsbase.cpp @@ -0,0 +1,758 @@ +/** +* @file llsettingsbase.cpp +* @author optional +* @brief A base class for asset based settings groups. +* +* $LicenseInfo:2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2017, 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 "llsettingsbase.h" + +#include "llmath.h" +#include + +#include "llsdserialize.h" + +//========================================================================= +namespace +{ + const LLSettingsBase::TrackPosition BREAK_POINT = 0.5; +} + +const LLSettingsBase::TrackPosition LLSettingsBase::INVALID_TRACKPOS(-1.0); + +//========================================================================= +std::ostream &operator <<(std::ostream& os, LLSettingsBase &settings) +{ + LLSDSerialize::serialize(settings.getSettings(), os, LLSDSerialize::LLSD_NOTATION); + + return os; +} + +//========================================================================= +const std::string LLSettingsBase::SETTING_ID("id"); +const std::string LLSettingsBase::SETTING_NAME("name"); +const std::string LLSettingsBase::SETTING_HASH("hash"); +const std::string LLSettingsBase::SETTING_TYPE("type"); +const std::string LLSettingsBase::SETTING_ASSETID("asset_id"); +const std::string LLSettingsBase::SETTING_FLAGS("flags"); + +const U32 LLSettingsBase::FLAG_NOCOPY(0x01 << 0); +const U32 LLSettingsBase::FLAG_NOMOD(0x01 << 1); +const U32 LLSettingsBase::FLAG_NOTRANS(0x01 << 2); + +const U32 LLSettingsBase::Validator::VALIDATION_PARTIAL(0x01 << 0); + +//========================================================================= +LLSettingsBase::LLSettingsBase(): + mSettings(LLSD::emptyMap()), + mDirty(true), + mAssetID(), + mBlendedFactor(0.0) +{ +} + +LLSettingsBase::LLSettingsBase(const LLSD setting) : + mSettings(setting), + mDirty(true), + mAssetID(), + mBlendedFactor(0.0) +{ +} + +//========================================================================= +void LLSettingsBase::lerpSettings(const LLSettingsBase &other, F64 mix) +{ + mSettings = interpolateSDMap(mSettings, other.mSettings, other.getParameterMap(), mix); + setDirtyFlag(true); +} + +LLSD LLSettingsBase::combineSDMaps(const LLSD &settings, const LLSD &other) const +{ + LLSD newSettings; + + for (LLSD::map_const_iterator it = settings.beginMap(); it != settings.endMap(); ++it) + { + std::string key_name = (*it).first; + LLSD value = (*it).second; + + LLSD::Type setting_type = value.type(); + switch (setting_type) + { + case LLSD::TypeMap: + newSettings[key_name] = combineSDMaps(value, LLSD()); + break; + case LLSD::TypeArray: + newSettings[key_name] = LLSD::emptyArray(); + for (auto const& entry : value.array()) + { + newSettings[key_name].append(entry); + } + break; + //case LLSD::TypeInteger: + //case LLSD::TypeReal: + //case LLSD::TypeBoolean: + //case LLSD::TypeString: + //case LLSD::TypeUUID: + //case LLSD::TypeURI: + //case LLSD::TypeDate: + //case LLSD::TypeBinary: + default: + newSettings[key_name] = value; + break; + } + } + + if (!other.isUndefined()) + { + for (LLSD::map_const_iterator it = other.beginMap(); it != other.endMap(); ++it) + { + std::string key_name = (*it).first; + LLSD value = (*it).second; + + LLSD::Type setting_type = value.type(); + switch (setting_type) + { + case LLSD::TypeMap: + newSettings[key_name] = combineSDMaps(value, LLSD()); + break; + case LLSD::TypeArray: + newSettings[key_name] = LLSD::emptyArray(); + for (auto const& entry : value.array()) + { + newSettings[key_name].append(entry); + } + break; + //case LLSD::TypeInteger: + //case LLSD::TypeReal: + //case LLSD::TypeBoolean: + //case LLSD::TypeString: + //case LLSD::TypeUUID: + //case LLSD::TypeURI: + //case LLSD::TypeDate: + //case LLSD::TypeBinary: + default: + newSettings[key_name] = value; + break; + } + } + } + + return newSettings; +} + +LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, F64 mix) const +{ + LLSD newSettings; + + stringset_t skip = getSkipInterpolateKeys(); + stringset_t slerps = getSlerpKeys(); + + for (LLSD::map_const_iterator it = settings.beginMap(); it != settings.endMap(); ++it) + { + std::string key_name = (*it).first; + LLSD value = (*it).second; + + if (skip.find(key_name) != skip.end()) + continue; + + LLSD other_value; + if (other.has(key_name)) + { + other_value = other[key_name]; + } + else + { + parammapping_t::const_iterator def_iter = defaults.find(key_name); + if (def_iter != defaults.end()) + { + other_value = def_iter->second.getDefaultValue(); + } + else if (value.type() == LLSD::TypeMap) + { + // interpolate in case there are defaults inside (part of legacy) + other_value = LLSDMap(); + } + else + { + // The other or defaults does not contain this setting, keep the original value + // TODO: Should I blend this out instead? + newSettings[key_name] = value; + continue; + } + } + + newSettings[key_name] = interpolateSDValue(key_name, value, other_value, defaults, mix, slerps); + } + + // Special handling cases + // Flags + if (settings.has(SETTING_FLAGS)) + { + U32 flags = (U32)settings[SETTING_FLAGS].asInteger(); + if (other.has(SETTING_FLAGS)) + flags |= (U32)other[SETTING_FLAGS].asInteger(); + + newSettings[SETTING_FLAGS] = LLSD::Integer(flags); + } + + // Now add anything that is in other but not in the settings + for (LLSD::map_const_iterator it = other.beginMap(); it != other.endMap(); ++it) + { + std::string key_name = (*it).first; + + if (skip.find(key_name) != skip.end()) + continue; + + if (settings.has(key_name)) + continue; + + parammapping_t::const_iterator def_iter = defaults.find(key_name); + if (def_iter != defaults.end()) + { + // Blend against default value + newSettings[key_name] = interpolateSDValue(key_name, def_iter->second.getDefaultValue(), (*it).second, defaults, mix, slerps); + } + else if ((*it).second.type() == LLSD::TypeMap) + { + // interpolate in case there are defaults inside (part of legacy) + newSettings[key_name] = interpolateSDValue(key_name, LLSDMap(), (*it).second, defaults, mix, slerps); + } + // else do nothing when no known defaults + // TODO: Should I blend this out instead? + } + + // Note: writes variables from skip list, bug? + for (LLSD::map_const_iterator it = other.beginMap(); it != other.endMap(); ++it) + { + // TODO: Should I blend this in instead? + if (skip.find((*it).first) == skip.end()) + continue; + + if (!settings.has((*it).first)) + continue; + + newSettings[(*it).first] = (*it).second; + } + + return newSettings; +} + +LLSD LLSettingsBase::interpolateSDValue(const std::string& key_name, const LLSD &value, const LLSD &other_value, const parammapping_t& defaults, BlendFactor mix, const stringset_t& slerps) const +{ + LLSD new_value; + + LLSD::Type setting_type = value.type(); + + if (other_value.type() != setting_type) + { + // The data type mismatched between this and other. Hard switch when we pass the break point + // but issue a warning. + LL_WARNS("SETTINGS") << "Setting lerp between mismatched types for '" << key_name << "'." << LL_ENDL; + new_value = (mix > BREAK_POINT) ? other_value : value; + } + + switch (setting_type) + { + case LLSD::TypeInteger: + // lerp between the two values rounding the result to the nearest integer. + new_value = LLSD::Integer(llroundf(lerp(value.asReal(), other_value.asReal(), mix))); + break; + case LLSD::TypeReal: + // lerp between the two values. + new_value = LLSD::Real(lerp(value.asReal(), other_value.asReal(), mix)); + break; + case LLSD::TypeMap: + // deep copy. + new_value = interpolateSDMap(value, other_value, defaults, mix); + break; + + case LLSD::TypeArray: + { + LLSD new_array(LLSD::emptyArray()); + + if (slerps.find(key_name) != slerps.end()) + { + LLQuaternion a(value); + LLQuaternion b(other_value); + LLQuaternion q = slerp(mix, a, b); + new_array = q.getValue(); + } + else + { // TODO: We could expand this to inspect the type and do a deep lerp based on type. + // for now assume a heterogeneous array of reals. + size_t len = std::max(value.size(), other_value.size()); + + for (size_t i = 0; i < len; ++i) + { + + new_array[i] = lerp(value[i].asReal(), other_value[i].asReal(), mix); + } + } + + new_value = new_array; + } + + break; + + case LLSD::TypeUUID: + new_value = value.asUUID(); + break; + + // case LLSD::TypeBoolean: + // case LLSD::TypeString: + // case LLSD::TypeURI: + // case LLSD::TypeBinary: + // case LLSD::TypeDate: + default: + // atomic or unknown data types. Lerping between them does not make sense so switch at the break. + new_value = (mix > BREAK_POINT) ? other_value : value; + break; + } + + return new_value; +} + +LLSettingsBase::stringset_t LLSettingsBase::getSkipInterpolateKeys() const +{ + static stringset_t skipSet; + + if (skipSet.empty()) + { + skipSet.insert(SETTING_FLAGS); + skipSet.insert(SETTING_HASH); + } + + return skipSet; +} + +LLSD LLSettingsBase::getSettings() const +{ + return mSettings; +} + +LLSD LLSettingsBase::cloneSettings() const +{ + return combineSDMaps(getSettings(), LLSD()); +} + +size_t LLSettingsBase::getHash() const +{ // get a shallow copy of the LLSD filtering out values to not include in the hash + LLSD hash_settings = llsd_shallow(getSettings(), + LLSDMap(SETTING_NAME, false)(SETTING_ID, false)(SETTING_HASH, false)("*", true)); + + boost::hash hasher; + return hasher(hash_settings); +} + +bool LLSettingsBase::validate() +{ + validation_list_t validations = getValidationList(); + + if (!mSettings.has(SETTING_TYPE)) + { + mSettings[SETTING_TYPE] = getSettingsType(); + } + + LLSD result = LLSettingsBase::settingValidation(mSettings, validations); + + if (result["errors"].size() > 0) + { + LL_WARNS("SETTINGS") << "Validation errors: " << result["errors"] << LL_ENDL; + } + if (result["warnings"].size() > 0) + { + LL_DEBUGS("SETTINGS") << "Validation warnings: " << result["warnings"] << LL_ENDL; + } + + return result["success"].asBoolean(); +} + +LLSD LLSettingsBase::settingValidation(LLSD &settings, validation_list_t &validations, bool partial) +{ + static Validator validateName(SETTING_NAME, false, LLSD::TypeString, boost::bind(&Validator::verifyStringLength, _1, 32)); + static Validator validateId(SETTING_ID, false, LLSD::TypeUUID); + static Validator validateHash(SETTING_HASH, false, LLSD::TypeInteger); + static Validator validateType(SETTING_TYPE, false, LLSD::TypeString); + static Validator validateAssetId(SETTING_ASSETID, false, LLSD::TypeUUID); + static Validator validateFlags(SETTING_FLAGS, false, LLSD::TypeInteger); + stringset_t validated; + stringset_t strip; + bool isValid(true); + LLSD errors(LLSD::emptyArray()); + LLSD warnings(LLSD::emptyArray()); + U32 flags(0); + + if (partial) + flags |= Validator::VALIDATION_PARTIAL; + + // Fields common to all settings. + if (!validateName.verify(settings, flags)) + { + errors.append( LLSD::String("Unable to validate 'name'.") ); + isValid = false; + } + validated.insert(validateName.getName()); + + if (!validateId.verify(settings, flags)) + { + errors.append( LLSD::String("Unable to validate 'id'.") ); + isValid = false; + } + validated.insert(validateId.getName()); + + if (!validateHash.verify(settings, flags)) + { + errors.append( LLSD::String("Unable to validate 'hash'.") ); + isValid = false; + } + validated.insert(validateHash.getName()); + + if (!validateAssetId.verify(settings, flags)) + { + errors.append(LLSD::String("Invalid asset Id")); + isValid = false; + } + validated.insert(validateAssetId.getName()); + + if (!validateType.verify(settings, flags)) + { + errors.append( LLSD::String("Unable to validate 'type'.") ); + isValid = false; + } + validated.insert(validateType.getName()); + + if (!validateFlags.verify(settings, flags)) + { + errors.append(LLSD::String("Unable to validate 'flags'.")); + isValid = false; + } + validated.insert(validateFlags.getName()); + + // Fields for specific settings. + for (validation_list_t::iterator itv = validations.begin(); itv != validations.end(); ++itv) + { +#ifdef VALIDATION_DEBUG + LLSD oldvalue; + if (settings.has((*itv).getName())) + { + oldvalue = llsd_clone(mSettings[(*itv).getName()]); + } +#endif + + if (!(*itv).verify(settings, flags)) + { + std::stringstream errtext; + + errtext << "Settings LLSD fails validation and could not be corrected for '" << (*itv).getName() << "'!\n"; + errors.append( errtext.str() ); + isValid = false; + } + validated.insert((*itv).getName()); + +#ifdef VALIDATION_DEBUG + if (!oldvalue.isUndefined()) + { + if (!compare_llsd(settings[(*itv).getName()], oldvalue)) + { + LL_WARNS("SETTINGS") << "Setting '" << (*itv).getName() << "' was changed: " << oldvalue << " -> " << settings[(*itv).getName()] << LL_ENDL; + } + } +#endif + } + + // strip extra entries + for (LLSD::map_const_iterator itm = settings.beginMap(); itm != settings.endMap(); ++itm) + { + if (validated.find((*itm).first) == validated.end()) + { + std::stringstream warntext; + + warntext << "Stripping setting '" << (*itm).first << "'"; + warnings.append( warntext.str() ); + strip.insert((*itm).first); + } + } + + for (stringset_t::iterator its = strip.begin(); its != strip.end(); ++its) + { + settings.erase(*its); + } + + return LLSDMap("success", LLSD::Boolean(isValid)) + ("errors", errors) + ("warnings", warnings); +} + +//========================================================================= + +bool LLSettingsBase::Validator::verify(LLSD &data, U32 flags) +{ + if (!data.has(mName) || (data.has(mName) && data[mName].isUndefined())) + { + if ((flags & VALIDATION_PARTIAL) != 0) // we are doing a partial validation. Do no attempt to set a default if missing (or fail even if required) + return true; + + if (!mDefault.isUndefined()) + { + data[mName] = mDefault; + return true; + } + if (mRequired) + LL_WARNS("SETTINGS") << "Missing required setting '" << mName << "' with no default." << LL_ENDL; + return !mRequired; + } + + if (data[mName].type() != mType) + { + LL_WARNS("SETTINGS") << "Setting '" << mName << "' is incorrect type." << LL_ENDL; + return false; + } + + if (!mVerify.empty() && !mVerify(data[mName])) + { + LL_WARNS("SETTINGS") << "Setting '" << mName << "' fails validation." << LL_ENDL; + return false; + } + + return true; +} + +bool LLSettingsBase::Validator::verifyColor(LLSD &value) +{ + return (value.size() == 3 || value.size() == 4); +} + +bool LLSettingsBase::Validator::verifyVector(LLSD &value, S32 length) +{ + return (value.size() == length); +} + +bool LLSettingsBase::Validator::verifyVectorNormalized(LLSD &value, S32 length) +{ + if (value.size() != length) + return false; + + LLSD newvector; + + switch (length) + { + case 2: + { + LLVector2 vect(value); + + if (is_approx_equal(vect.normalize(), 1.0f)) + return true; + newvector = vect.getValue(); + break; + } + case 3: + { + LLVector3 vect(value); + + if (is_approx_equal(vect.normalize(), 1.0f)) + return true; + newvector = vect.getValue(); + break; + } + case 4: + { + LLVector4 vect(value); + + if (is_approx_equal(vect.normalize(), 1.0f)) + return true; + newvector = vect.getValue(); + break; + } + default: + return false; + } + + return true; +} + +bool LLSettingsBase::Validator::verifyVectorMinMax(LLSD &value, LLSD minvals, LLSD maxvals) +{ + for (S32 index = 0; index < value.size(); ++index) + { + if (minvals[index].asString() != "*") + { + if (minvals[index].asReal() > value[index].asReal()) + { + value[index] = minvals[index].asReal(); + } + } + if (maxvals[index].asString() != "*") + { + if (maxvals[index].asReal() < value[index].asReal()) + { + value[index] = maxvals[index].asReal(); + } + } + } + + return true; +} + +bool LLSettingsBase::Validator::verifyQuaternion(LLSD &value) +{ + return (value.size() == 4); +} + +bool LLSettingsBase::Validator::verifyQuaternionNormal(LLSD &value) +{ + if (value.size() != 4) + return false; + + LLQuaternion quat(value); + + if (is_approx_equal(quat.normalize(), 1.0f)) + return true; + + LLSD newquat = quat.getValue(); + for (S32 index = 0; index < 4; ++index) + { + value[index] = newquat[index]; + } + return true; +} + +bool LLSettingsBase::Validator::verifyFloatRange(LLSD &value, LLSD range) +{ + F64 real = value.asReal(); + + F64 clampedval = llclamp(LLSD::Real(real), range[0].asReal(), range[1].asReal()); + + if (is_approx_equal(clampedval, real)) + return true; + + value = LLSD::Real(clampedval); + return true; +} + +bool LLSettingsBase::Validator::verifyIntegerRange(LLSD &value, LLSD range) +{ + S32 ival = value.asInteger(); + + S32 clampedval = llclamp(LLSD::Integer(ival), range[0].asInteger(), range[1].asInteger()); + + if (clampedval == ival) + return true; + + value = LLSD::Integer(clampedval); + return true; +} + +bool LLSettingsBase::Validator::verifyStringLength(LLSD &value, S32 length) +{ + std::string sval = value.asString(); + + if (!sval.empty()) + { + sval = sval.substr(0, length); + value = LLSD::String(sval); + } + return true; +} + +//========================================================================= +void LLSettingsBlender::update(const LLSettingsBase::BlendFactor& blendf) +{ + F64 res = setBlendFactor(blendf); + + if ((res >= 0.0001) && (res < 1.0)) + mTarget->update(); +} + +F64 LLSettingsBlender::setBlendFactor(const LLSettingsBase::BlendFactor& blendf_in) +{ + LLSettingsBase::TrackPosition blendf = blendf_in; + if (blendf >= 1.0) + { + triggerComplete(); + return 1.0; + } + blendf = llclamp(blendf, 0.0f, 1.0f); + + if (mTarget) + { + mTarget->replaceSettings(mInitial->getSettings()); + if (!mFinal || (mInitial == mFinal) || (blendf == 0.0)) + { // this is a trivial blend. Results will be identical to the initial. + return blendf; + } + mTarget->blend(mFinal, blendf); + } + else + { + LL_WARNS("SETTINGS") << "No target for settings blender." << LL_ENDL; + } + + return blendf; +} + +void LLSettingsBlender::triggerComplete() +{ + if (mTarget) + mTarget->replaceSettings(mFinal->getSettings()); + LLSettingsBlender::ptr_t hold = shared_from_this(); // prevents this from deleting too soon + mTarget->update(); + mOnFinished(shared_from_this()); +} + +//------------------------------------------------------------------------- +const LLSettingsBase::BlendFactor LLSettingsBlenderTimeDelta::MIN_BLEND_DELTA(0.001); + +LLSettingsBase::BlendFactor LLSettingsBlenderTimeDelta::calculateBlend(const LLSettingsBase::TrackPosition& spanpos, const LLSettingsBase::TrackPosition& spanlen) const +{ + return LLSettingsBase::BlendFactor(fmod((F64)spanpos, (F64)spanlen) / (F64)spanlen); +} + +bool LLSettingsBlenderTimeDelta::applyTimeDelta(const LLSettingsBase::Seconds& timedelta) +{ + mTimeSpent += timedelta; + mTimeDeltaPassed += timedelta; + + if (mTimeSpent > mBlendSpan) + { + mIgnoreTimeDelta = false; + triggerComplete(); + return false; + } + + if ((mTimeDeltaPassed < mTimeDeltaThreshold) && (!mIgnoreTimeDelta)) + { + return false; + } + + LLSettingsBase::BlendFactor blendf = calculateBlend(mTimeSpent, mBlendSpan); + mTimeDeltaPassed = LLSettingsBase::Seconds(0.0); + + if (fabs(mLastBlendF - blendf) < mBlendFMinDelta) + { + return false; + } + + mLastBlendF = blendf; + update(blendf); + return true; +} diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h new file mode 100644 index 0000000000..592ae3478a --- /dev/null +++ b/indra/llinventory/llsettingsbase.h @@ -0,0 +1,538 @@ +/** +* @file llsettingsbase.h +* @author optional +* @brief A base class for asset based settings groups. +* +* $LicenseInfo:2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2017, 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_SETTINGS_BASE_H +#define LL_SETTINGS_BASE_H + +#include +#include +#include +#include + +#include "llsd.h" +#include "llsdutil.h" +#include "v2math.h" +#include "v3math.h" +#include "v4math.h" +#include "llquaternion.h" +#include "v4color.h" +#include "v3color.h" +#include "llunits.h" + +#include "llinventorysettings.h" + +#define PTR_NAMESPACE std +#define SETTINGS_OVERRIDE override + +class LLSettingsBase : + public PTR_NAMESPACE::enable_shared_from_this, + private boost::noncopyable +{ + friend class LLEnvironment; + friend class LLSettingsDay; + + friend std::ostream &operator <<(std::ostream& os, LLSettingsBase &settings); + +protected: + LOG_CLASS(LLSettingsBase); +public: + typedef F64Seconds Seconds; + typedef F64 BlendFactor; + typedef F32 TrackPosition; // 32-bit as these are stored in LLSD as such + static const TrackPosition INVALID_TRACKPOS; + + static const std::string SETTING_ID; + static const std::string SETTING_NAME; + static const std::string SETTING_HASH; + static const std::string SETTING_TYPE; + static const std::string SETTING_ASSETID; + static const std::string SETTING_FLAGS; + + static const U32 FLAG_NOCOPY; + static const U32 FLAG_NOMOD; + static const U32 FLAG_NOTRANS; + + class DefaultParam + { + public: + DefaultParam(S32 key, const LLSD& value) : mShaderKey(key), mDefaultValue(value) {} + DefaultParam() : mShaderKey(-1) {} + S32 getShaderKey() const { return mShaderKey; } + const LLSD getDefaultValue() const { return mDefaultValue; } + + private: + S32 mShaderKey; + LLSD mDefaultValue; + }; + // Contains settings' names (map key), related shader id-key and default + // value for revert in case we need to reset shader (no need to search each time) + typedef std::map parammapping_t; + + typedef PTR_NAMESPACE::shared_ptr ptr_t; + + virtual ~LLSettingsBase() { }; + + //--------------------------------------------------------------------- + virtual std::string getSettingsType() const = 0; + + virtual LLSettingsType::type_e getSettingsTypeValue() const = 0; + + //--------------------------------------------------------------------- + // Settings status + inline bool hasSetting(const std::string ¶m) const { return mSettings.has(param); } + virtual bool isDirty() const { return mDirty; } + virtual bool isVeryDirty() const { return mReplaced; } + inline void setDirtyFlag(bool dirty) { mDirty = dirty; clearAssetId(); } + + size_t getHash() const; // Hash will not include Name, ID or a previously stored Hash + + inline LLUUID getId() const + { + return getValue(SETTING_ID).asUUID(); + } + + inline std::string getName() const + { + return getValue(SETTING_NAME).asString(); + } + + inline void setName(std::string val) + { + setValue(SETTING_NAME, val); + } + + inline LLUUID getAssetId() const + { + if (mSettings.has(SETTING_ASSETID)) + return mSettings[SETTING_ASSETID].asUUID(); + return LLUUID(); + } + + inline U32 getFlags() const + { + if (mSettings.has(SETTING_FLAGS)) + return static_cast(mSettings[SETTING_FLAGS].asInteger()); + return 0; + } + + inline void setFlags(U32 value) + { + setLLSD(SETTING_FLAGS, LLSD::Integer(value)); + } + + inline bool getFlag(U32 flag) const + { + if (mSettings.has(SETTING_FLAGS)) + return ((U32)mSettings[SETTING_FLAGS].asInteger() & flag) == flag; + return false; + } + + inline void setFlag(U32 flag) + { + U32 flags((mSettings.has(SETTING_FLAGS)) ? (U32)mSettings[SETTING_FLAGS].asInteger() : 0); + + flags |= flag; + + if (flags) + mSettings[SETTING_FLAGS] = LLSD::Integer(flags); + else + mSettings.erase(SETTING_FLAGS); + } + + inline void clearFlag(U32 flag) + { + U32 flags((mSettings.has(SETTING_FLAGS)) ? (U32)mSettings[SETTING_FLAGS].asInteger() : 0); + + flags &= ~flag; + + if (flags) + mSettings[SETTING_FLAGS] = LLSD::Integer(flags); + else + mSettings.erase(SETTING_FLAGS); + } + + virtual void replaceSettings(LLSD settings) + { + mBlendedFactor = 0.0; + setDirtyFlag(true); + mReplaced = true; + mSettings = settings; + } + + virtual LLSD getSettings() const; + + //--------------------------------------------------------------------- + // + inline void setLLSD(const std::string &name, const LLSD &value) + { + mSettings[name] = value; + mDirty = true; + if (name != SETTING_ASSETID) + clearAssetId(); + } + + inline void setValue(const std::string &name, const LLSD &value) + { + setLLSD(name, value); + } + + inline LLSD getValue(const std::string &name, const LLSD &deflt = LLSD()) const + { + if (!mSettings.has(name)) + return deflt; + return mSettings[name]; + } + + inline void setValue(const std::string &name, F32 v) + { + setLLSD(name, LLSD::Real(v)); + } + + inline void setValue(const std::string &name, const LLVector2 &value) + { + setValue(name, value.getValue()); + } + + inline void setValue(const std::string &name, const LLVector3 &value) + { + setValue(name, value.getValue()); + } + + inline void setValue(const std::string &name, const LLVector4 &value) + { + setValue(name, value.getValue()); + } + + inline void setValue(const std::string &name, const LLQuaternion &value) + { + setValue(name, value.getValue()); + } + + inline void setValue(const std::string &name, const LLColor3 &value) + { + setValue(name, value.getValue()); + } + + inline void setValue(const std::string &name, const LLColor4 &value) + { + setValue(name, value.getValue()); + } + + inline BlendFactor getBlendFactor() const + { + return mBlendedFactor; + } + + // Note this method is marked const but may modify the settings object. + // (note the internal const cast). This is so that it may be called without + // special consideration from getters. + inline void update() const + { + if ((!mDirty) && (!mReplaced)) + return; + (const_cast(this))->updateSettings(); + } + + virtual void blend(const ptr_t &end, BlendFactor blendf) = 0; + + virtual bool validate(); + + virtual ptr_t buildDerivedClone() const = 0; + + class Validator + { + public: + static const U32 VALIDATION_PARTIAL; + + typedef boost::function verify_pr; + + Validator(std::string name, bool required, LLSD::Type type, verify_pr verify = verify_pr(), LLSD defval = LLSD()) : + mName(name), + mRequired(required), + mType(type), + mVerify(verify), + mDefault(defval) + { } + + std::string getName() const { return mName; } + bool isRequired() const { return mRequired; } + LLSD::Type getType() const { return mType; } + + bool verify(LLSD &data, U32 flags); + + // Some basic verifications + static bool verifyColor(LLSD &value); + static bool verifyVector(LLSD &value, S32 length); + static bool verifyVectorMinMax(LLSD &value, LLSD minvals, LLSD maxvals); + static bool verifyVectorNormalized(LLSD &value, S32 length); + static bool verifyQuaternion(LLSD &value); + static bool verifyQuaternionNormal(LLSD &value); + static bool verifyFloatRange(LLSD &value, LLSD range); + static bool verifyIntegerRange(LLSD &value, LLSD range); + static bool verifyStringLength(LLSD &value, S32 length); + + private: + std::string mName; + bool mRequired; + LLSD::Type mType; + verify_pr mVerify; + LLSD mDefault; + }; + typedef std::vector validation_list_t; + + static LLSD settingValidation(LLSD &settings, validation_list_t &validations, bool partial = false); + + inline void setAssetId(LLUUID value) + { // note that this skips setLLSD + mSettings[SETTING_ASSETID] = value; + } + + inline void clearAssetId() + { + if (mSettings.has(SETTING_ASSETID)) + mSettings.erase(SETTING_ASSETID); + } + + // Calculate any custom settings that may need to be cached. + virtual void updateSettings() { mDirty = false; mReplaced = false; } +protected: + + LLSettingsBase(); + LLSettingsBase(const LLSD setting); + + static LLSD settingValidation(LLSD settings); + + typedef std::set stringset_t; + + // combining settings objects. Customize for specific setting types + virtual void lerpSettings(const LLSettingsBase &other, BlendFactor mix); + + // combining settings maps where it can based on mix rate + // @settings initial value (mix==0) + // @other target value (mix==1) + // @defaults list of default values for legacy fields and (re)setting shaders + // @mix from 0 to 1, ratio or rate of transition from initial 'settings' to 'other' + // return interpolated and combined LLSD map + LLSD interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, BlendFactor mix) const; + LLSD interpolateSDValue(const std::string& name, const LLSD &value, const LLSD &other, const parammapping_t& defaults, BlendFactor mix, const stringset_t& slerps) const; + + /// when lerping between settings, some may require special handling. + /// Get a list of these key to be skipped by the default settings lerp. + /// (handling should be performed in the override of lerpSettings. + virtual stringset_t getSkipInterpolateKeys() const; + + // A list of settings that represent quaternions and should be slerped + // rather than lerped. + virtual stringset_t getSlerpKeys() const { return stringset_t(); } + + virtual validation_list_t getValidationList() const = 0; + + // Apply any settings that need special handling. + virtual void applySpecial(void *) { }; + + virtual parammapping_t getParameterMap() const { return parammapping_t(); } + + LLSD mSettings; + bool mIsValid; + LLAssetID mAssetID; + + LLSD cloneSettings() const; + + inline void setBlendFactor(BlendFactor blendfactor) + { + mBlendedFactor = blendfactor; + } + + void replaceWith(LLSettingsBase::ptr_t other) + { + replaceSettings(other->cloneSettings()); + setBlendFactor(other->getBlendFactor()); + } + +private: + bool mDirty; + bool mReplaced; // super dirty! + + LLSD combineSDMaps(const LLSD &first, const LLSD &other) const; + + BlendFactor mBlendedFactor; +}; + + +class LLSettingsBlender : public PTR_NAMESPACE::enable_shared_from_this +{ + LOG_CLASS(LLSettingsBlender); +public: + typedef PTR_NAMESPACE::shared_ptr ptr_t; + typedef boost::signals2::signal finish_signal_t; + typedef boost::signals2::connection connection_t; + + LLSettingsBlender(const LLSettingsBase::ptr_t &target, + const LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting) : + mOnFinished(), + mTarget(target), + mInitial(initsetting), + mFinal(endsetting) + { + if (mInitial && mTarget) + mTarget->replaceSettings(mInitial->getSettings()); + + if (!mFinal) + mFinal = mInitial; + } + + virtual ~LLSettingsBlender() {} + + virtual void reset( LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::TrackPosition&) + { + // note: the 'span' reset parameter is unused by the base class. + if (!mInitial) + LL_WARNS("BLENDER") << "Reseting blender with empty initial setting. Expect badness in the future." << LL_ENDL; + + mInitial = initsetting; + mFinal = endsetting; + + if (!mFinal) + mFinal = mInitial; + + if (mTarget) + mTarget->replaceSettings(mInitial->getSettings()); + } + + LLSettingsBase::ptr_t getTarget() const + { + return mTarget; + } + + LLSettingsBase::ptr_t getInitial() const + { + return mInitial; + } + + LLSettingsBase::ptr_t getFinal() const + { + return mFinal; + } + + connection_t setOnFinished(const finish_signal_t::slot_type &onfinished) + { + return mOnFinished.connect(onfinished); + } + + virtual void update(const LLSettingsBase::BlendFactor& blendf); + virtual bool applyTimeDelta(const LLSettingsBase::Seconds& timedelta) + { + llassert(false); + // your derived class needs to implement an override of this func + return false; + } + + virtual F64 setBlendFactor(const LLSettingsBase::BlendFactor& position); + + virtual void switchTrack(S32 trackno, const LLSettingsBase::TrackPosition& position) { /*NoOp*/ } + +protected: + void triggerComplete(); + + finish_signal_t mOnFinished; + + LLSettingsBase::ptr_t mTarget; + LLSettingsBase::ptr_t mInitial; + LLSettingsBase::ptr_t mFinal; +}; + +class LLSettingsBlenderTimeDelta : public LLSettingsBlender +{ + LOG_CLASS(LLSettingsBlenderTimeDelta); +public: + static const LLSettingsBase::BlendFactor MIN_BLEND_DELTA; + + LLSettingsBlenderTimeDelta(const LLSettingsBase::ptr_t &target, + const LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::Seconds& blend_span) : + LLSettingsBlender(target, initsetting, endsetting), + mBlendSpan(blend_span), + mLastUpdate(0.0f), + mTimeSpent(0.0f), + mTimeDeltaThreshold(0.0f), + mTimeDeltaPassed(0.0f), + mIgnoreTimeDelta(false), + mBlendFMinDelta(MIN_BLEND_DELTA), + mLastBlendF(-1.0f) + { + mTimeStart = LLSettingsBase::Seconds(LLDate::now().secondsSinceEpoch()); + mLastUpdate = mTimeStart; + } + + virtual ~LLSettingsBlenderTimeDelta() + { + } + + virtual void reset(LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::TrackPosition& blend_span) SETTINGS_OVERRIDE + { + LLSettingsBlender::reset(initsetting, endsetting, blend_span); + + mBlendSpan = blend_span; + mTimeStart = LLSettingsBase::Seconds(LLDate::now().secondsSinceEpoch()); + mLastUpdate = mTimeStart; + mTimeSpent = LLSettingsBase::Seconds(0.0f); + mTimeDeltaPassed = LLSettingsBase::Seconds(0.0f); + mLastBlendF = LLSettingsBase::BlendFactor(-1.0f); + } + + virtual bool applyTimeDelta(const LLSettingsBase::Seconds& timedelta) SETTINGS_OVERRIDE; + + inline void setTimeDeltaThreshold(const LLSettingsBase::Seconds time) + { + mTimeDeltaThreshold = time; + mTimeDeltaPassed = time + LLSettingsBase::Seconds(1.0); // take the next update call. + } + + inline LLSettingsBase::Seconds getTimeDeltaThreshold() const + { + return mTimeDeltaThreshold; + } + + inline void setIgnoreTimeDeltaThreshold(bool val) { mIgnoreTimeDelta = val; } + inline bool getIgnoreTimeDeltaThreshold() const { return mIgnoreTimeDelta; } + + inline void setTimeSpent(LLSettingsBase::Seconds time) { mTimeSpent = time; } +protected: + LLSettingsBase::BlendFactor calculateBlend(const LLSettingsBase::TrackPosition& spanpos, const LLSettingsBase::TrackPosition& spanlen) const; + + LLSettingsBase::TrackPosition mBlendSpan; + LLSettingsBase::Seconds mLastUpdate; + LLSettingsBase::Seconds mTimeSpent; + LLSettingsBase::Seconds mTimeStart; + LLSettingsBase::Seconds mTimeDeltaThreshold; + LLSettingsBase::Seconds mTimeDeltaPassed; + bool mIgnoreTimeDelta; + LLSettingsBase::BlendFactor mBlendFMinDelta; + LLSettingsBase::BlendFactor mLastBlendF; +}; + + +#endif diff --git a/indra/llinventory/llsettingsdaycycle.cpp b/indra/llinventory/llsettingsdaycycle.cpp new file mode 100644 index 0000000000..bfb755fd00 --- /dev/null +++ b/indra/llinventory/llsettingsdaycycle.cpp @@ -0,0 +1,891 @@ +/** +* @file llsettingsdaycycle.cpp +* @author optional +* @brief A base class for asset based settings groups. +* +* $LicenseInfo:2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2017, 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 "llsettingsdaycycle.h" +#include "llerror.h" +#include +#include +#include "llfasttimer.h" +#include "v3colorutil.h" + +#include "llsettingssky.h" +#include "llsettingswater.h" + +#include "llframetimer.h" + +//========================================================================= +namespace +{ + LLTrace::BlockTimerStatHandle FTM_BLEND_WATERVALUES("Blending Water Environment"); + LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERVALUES("Update Water Environment"); + + template + inline T get_wrapping_distance(T begin, T end) + { + if (begin < end) + { + return end - begin; + } + else if (begin > end) + { + return T(1.0) - (begin - end); + } + + return 0; + } + + LLSettingsDay::CycleTrack_t::iterator get_wrapping_atafter(LLSettingsDay::CycleTrack_t &collection, const LLSettingsBase::TrackPosition& key) + { + if (collection.empty()) + return collection.end(); + + LLSettingsDay::CycleTrack_t::iterator it = collection.upper_bound(key); + + if (it == collection.end()) + { // wrap around + it = collection.begin(); + } + + return it; + } + + LLSettingsDay::CycleTrack_t::iterator get_wrapping_atbefore(LLSettingsDay::CycleTrack_t &collection, const LLSettingsBase::TrackPosition& key) + { + if (collection.empty()) + return collection.end(); + + LLSettingsDay::CycleTrack_t::iterator it = collection.lower_bound(key); + + if (it == collection.end()) + { // all keyframes are lower, take the last one. + --it; // we know the range is not empty + } + else if ((*it).first > key) + { // the keyframe we are interested in is smaller than the found. + if (it == collection.begin()) + it = collection.end(); + --it; + } + + return it; + } + + +} + +//========================================================================= +const std::string LLSettingsDay::SETTING_KEYID("key_id"); +const std::string LLSettingsDay::SETTING_KEYNAME("key_name"); +const std::string LLSettingsDay::SETTING_KEYKFRAME("key_keyframe"); +const std::string LLSettingsDay::SETTING_KEYHASH("key_hash"); +const std::string LLSettingsDay::SETTING_TRACKS("tracks"); +const std::string LLSettingsDay::SETTING_FRAMES("frames"); + +const LLSettingsDay::Seconds LLSettingsDay::MINIMUM_DAYLENGTH(14400); // 4 hours +const LLSettingsDay::Seconds LLSettingsDay::DEFAULT_DAYLENGTH(14400); // 4 hours +const LLSettingsDay::Seconds LLSettingsDay::MAXIMUM_DAYLENGTH(604800); // 7 days + +const LLSettingsDay::Seconds LLSettingsDay::MINIMUM_DAYOFFSET(0); +const LLSettingsDay::Seconds LLSettingsDay::DEFAULT_DAYOFFSET(57600); // +16 hours == -8 hours (SLT time offset) +const LLSettingsDay::Seconds LLSettingsDay::MAXIMUM_DAYOFFSET(86400); // 24 hours + +const S32 LLSettingsDay::TRACK_WATER(0); // water track is 0 +const S32 LLSettingsDay::TRACK_GROUND_LEVEL(1); +const S32 LLSettingsDay::TRACK_MAX(5); // 5 tracks, 4 skys, 1 water +const S32 LLSettingsDay::FRAME_MAX(56); + +const F32 LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR(0.02501f); + +const LLUUID LLSettingsDay::DEFAULT_ASSET_ID("78751d18-6c51-3c43-2887-3654cd427a42"); + +// Minimum value to prevent multislider in edit floaters from eating up frames that 'encroach' on one another's space +static const F32 DEFAULT_MULTISLIDER_INCREMENT(0.005f); +//========================================================================= +LLSettingsDay::LLSettingsDay(const LLSD &data) : + LLSettingsBase(data), + mInitialized(false) +{ + mDayTracks.resize(TRACK_MAX); +} + +LLSettingsDay::LLSettingsDay() : + LLSettingsBase(), + mInitialized(false) +{ + mDayTracks.resize(TRACK_MAX); +} + +//========================================================================= +LLSD LLSettingsDay::getSettings() const +{ + LLSD settings(LLSD::emptyMap()); + + if (mSettings.has(SETTING_NAME)) + settings[SETTING_NAME] = mSettings[SETTING_NAME]; + + if (mSettings.has(SETTING_ID)) + settings[SETTING_ID] = mSettings[SETTING_ID]; + + if (mSettings.has(SETTING_ASSETID)) + settings[SETTING_ASSETID] = mSettings[SETTING_ASSETID]; + + settings[SETTING_TYPE] = getSettingsType(); + + std::map in_use; + + LLSD tracks(LLSD::emptyArray()); + + for (CycleList_t::const_iterator itTrack = mDayTracks.begin(); itTrack != mDayTracks.end(); ++itTrack) + { + LLSD trackout(LLSD::emptyArray()); + + for (CycleTrack_t::const_iterator itFrame = (*itTrack).begin(); itFrame != (*itTrack).end(); ++itFrame) + { + F32 frame = (*itFrame).first; + LLSettingsBase::ptr_t data = (*itFrame).second; + size_t datahash = data->getHash(); + + std::stringstream keyname; + keyname << datahash; + + trackout.append(LLSD(LLSDMap(SETTING_KEYKFRAME, LLSD::Real(frame))(SETTING_KEYNAME, keyname.str()))); + in_use[keyname.str()] = data; + } + tracks.append(trackout); + } + settings[SETTING_TRACKS] = tracks; + + LLSD frames(LLSD::emptyMap()); + for (std::map::iterator itFrame = in_use.begin(); itFrame != in_use.end(); ++itFrame) + { + LLSD framesettings = llsd_clone((*itFrame).second->getSettings(), + LLSDMap("*", true)(SETTING_NAME, false)(SETTING_ID, false)(SETTING_HASH, false)); + + frames[(*itFrame).first] = framesettings; + } + settings[SETTING_FRAMES] = frames; + + return settings; +} + +bool LLSettingsDay::initialize(bool validate_frames) +{ + LLSD tracks = mSettings[SETTING_TRACKS]; + LLSD frames = mSettings[SETTING_FRAMES]; + + // save for later... + LLUUID assetid; + if (mSettings.has(SETTING_ASSETID)) + { + assetid = mSettings[SETTING_ASSETID].asUUID(); + } + + std::map used; + + for (LLSD::map_const_iterator itFrame = frames.beginMap(); itFrame != frames.endMap(); ++itFrame) + { + std::string name = (*itFrame).first; + LLSD data = (*itFrame).second; + LLSettingsBase::ptr_t keyframe; + + if (data[SETTING_TYPE].asString() == "sky") + { + keyframe = buildSky(data); + } + else if (data[SETTING_TYPE].asString() == "water") + { + keyframe = buildWater(data); + } + else + { + LL_WARNS("DAYCYCLE") << "Unknown child setting type '" << data[SETTING_TYPE].asString() << "' named '" << name << "'" << LL_ENDL; + } + if (!keyframe) + { + LL_WARNS("DAYCYCLE") << "Invalid frame data" << LL_ENDL; + continue; + } + + used[name] = keyframe; + } + + bool haswater(false); + bool hassky(false); + + for (S32 i = 0; (i < tracks.size()) && (i < TRACK_MAX); ++i) + { + mDayTracks[i].clear(); + LLSD curtrack = tracks[i]; + for (const auto& entry : curtrack.array()) + { + LLSettingsBase::TrackPosition keyframe = LLSettingsBase::TrackPosition(entry[SETTING_KEYKFRAME].asReal()); + keyframe = llclamp(keyframe, 0.0f, 1.0f); + LLSettingsBase::ptr_t setting; + + + if (entry.has(SETTING_KEYNAME)) + { + std::string key_name = entry[SETTING_KEYNAME]; + if (i == TRACK_WATER) + { + setting = used[key_name]; + if (setting && setting->getSettingsType() != "water") + { + LL_WARNS("DAYCYCLE") << "Water track referencing " << setting->getSettingsType() << " frame at " << keyframe << "." << LL_ENDL; + setting.reset(); + } + } + else + { + setting = used[key_name]; + if (setting && setting->getSettingsType() != "sky") + { + LL_WARNS("DAYCYCLE") << "Sky track #" << i << " referencing " << setting->getSettingsType() << " frame at " << keyframe << "." << LL_ENDL; + setting.reset(); + } + } + } + + if (setting) + { + if (i == TRACK_WATER) + haswater |= true; + else + hassky |= true; + + if (validate_frames && mDayTracks[i].size() > 0) + { + // check if we hit close to anything in the list + LLSettingsDay::CycleTrack_t::value_type frame = getSettingsNearKeyframe(keyframe, i, DEFAULT_FRAME_SLOP_FACTOR); + if (frame.second) + { + // figure out direction of search + LLSettingsBase::TrackPosition found = frame.first; + LLSettingsBase::TrackPosition new_frame = keyframe; + F32 total_frame_shift = 0; + // We consider frame DEFAULT_FRAME_SLOP_FACTOR away as still encroaching, so add minimum increment + F32 move_factor = DEFAULT_FRAME_SLOP_FACTOR + DEFAULT_MULTISLIDER_INCREMENT; + bool move_forward = true; + if ((new_frame < found && (found - new_frame) <= DEFAULT_FRAME_SLOP_FACTOR) + || (new_frame > found && (new_frame - found) > DEFAULT_FRAME_SLOP_FACTOR)) + { + move_forward = false; + } + + if (move_forward) + { + CycleTrack_t::iterator iter = mDayTracks[i].find(found); + new_frame = found; // for total_frame_shift + while (total_frame_shift < 1) + { + // calculate shifted position from previous found point + total_frame_shift += move_factor + (found >= new_frame ? found : found + 1) - new_frame; + new_frame = found + move_factor; + if (new_frame > 1) new_frame--; + + // we know that current point is too close, go for next one + iter++; + if (iter == mDayTracks[i].end()) + { + iter = mDayTracks[i].begin(); + } + + if (((iter->first >= (new_frame - DEFAULT_MULTISLIDER_INCREMENT)) && ((new_frame + DEFAULT_FRAME_SLOP_FACTOR) >= iter->first)) + || ((iter->first < new_frame) && ((new_frame + DEFAULT_FRAME_SLOP_FACTOR) >= (iter->first + 1)))) + { + // we are encroaching at new point as well + found = iter->first; + } + else // (new_frame + DEFAULT_FRAME_SLOP_FACTOR < iter->first) + { + //we found clear spot + break; + } + } + } + else + { + CycleTrack_t::reverse_iterator iter = mDayTracks[i].rbegin(); + while (iter->first != found) + { + iter++; + } + new_frame = found; // for total_frame_shift + while (total_frame_shift < 1) + { + // calculate shifted position from current found point + total_frame_shift += move_factor + new_frame - (found <= new_frame ? found : found - 1); + new_frame = found - move_factor; + if (new_frame < 0) new_frame++; + + // we know that current point is too close, go for next one + iter++; + if (iter == mDayTracks[i].rend()) + { + iter = mDayTracks[i].rbegin(); + } + + if ((iter->first <= (new_frame + DEFAULT_MULTISLIDER_INCREMENT) && (new_frame - DEFAULT_FRAME_SLOP_FACTOR) <= iter->first) + || ((iter->first > new_frame) && ((new_frame - DEFAULT_FRAME_SLOP_FACTOR) <= (iter->first - 1)))) + { + // we are encroaching at new point as well + found = iter->first; + } + else // (new_frame - DEFAULT_FRAME_SLOP_FACTOR > iter->first) + { + //we found clear spot + break; + } + } + + + } + + if (total_frame_shift >= 1) + { + LL_WARNS("SETTINGS") << "Could not fix frame position, adding as is to position: " << keyframe << LL_ENDL; + } + else + { + // Mark as new position + keyframe = new_frame; + } + } + } + mDayTracks[i][keyframe] = setting; + } + } + } + + if (!haswater || !hassky) + { + LL_WARNS("DAYCYCLE") << "Must have at least one water and one sky frame!" << LL_ENDL; + return false; + } + // these are no longer needed and just take up space now. + mSettings.erase(SETTING_TRACKS); + mSettings.erase(SETTING_FRAMES); + + if (!assetid.isNull()) + { + mSettings[SETTING_ASSETID] = assetid; + } + + mInitialized = true; + return true; +} + + +//========================================================================= +LLSD LLSettingsDay::defaults() +{ + static LLSD dfltsetting; + + if (dfltsetting.size() == 0) + { + dfltsetting[SETTING_NAME] = "_default_"; + dfltsetting[SETTING_TYPE] = "daycycle"; + + LLSD frames(LLSD::emptyMap()); + LLSD waterTrack; + LLSD skyTrack; + + + const U32 FRAME_COUNT = 8; + const F32 FRAME_STEP = 1.0f / F32(FRAME_COUNT); + F32 time = 0.0f; + for (U32 i = 0; i < FRAME_COUNT; i++) + { + std::string name("_default_"); + name += ('a' + i); + + std::string water_frame_name("water:"); + std::string sky_frame_name("sky:"); + + water_frame_name += name; + sky_frame_name += name; + + waterTrack[SETTING_KEYKFRAME] = time; + waterTrack[SETTING_KEYNAME] = water_frame_name; + + skyTrack[SETTING_KEYKFRAME] = time; + skyTrack[SETTING_KEYNAME] = sky_frame_name; + + frames[water_frame_name] = LLSettingsWater::defaults(time); + frames[sky_frame_name] = LLSettingsSky::defaults(time); + + time += FRAME_STEP; + } + + LLSD tracks; + tracks.append(LLSDArray(waterTrack)); + tracks.append(LLSDArray(skyTrack)); + + dfltsetting[SETTING_TRACKS] = tracks; + dfltsetting[SETTING_FRAMES] = frames; + } + + return dfltsetting; +} + +void LLSettingsDay::blend(const LLSettingsBase::ptr_t &other, F64 mix) +{ + LL_ERRS("DAYCYCLE") << "Day cycles are not blendable!" << LL_ENDL; +} + +namespace +{ + bool validateDayCycleTrack(LLSD &value) + { + // Trim extra tracks. + while (value.size() > LLSettingsDay::TRACK_MAX) + { + value.erase(value.size() - 1); + } + + S32 framecount(0); + + for (auto& entry : value.array()) + { + S32 index = 0; + while (index < entry.size()) + { + LLSD& elem = entry[index]; + + ++framecount; + if (index >= LLSettingsDay::FRAME_MAX) + { + entry.erase(index); + continue; + } + + if (!elem.has(LLSettingsDay::SETTING_KEYKFRAME)) + { + entry.erase(index); + continue; + } + + if (!elem[LLSettingsDay::SETTING_KEYKFRAME].isReal()) + { + entry.erase(index); + continue; + } + + if (!elem.has(LLSettingsDay::SETTING_KEYNAME) && + !elem.has(LLSettingsDay::SETTING_KEYID)) + { + entry.erase(index); + continue; + } + + LLSettingsBase::TrackPosition frame = elem[LLSettingsDay::SETTING_KEYKFRAME].asReal(); + if ((frame < 0.0) || (frame > 1.0)) + { + frame = llclamp(frame, 0.0f, 1.0f); + elem[LLSettingsDay::SETTING_KEYKFRAME] = frame; + } + ++index; + } + + } + + int waterTracks = value[0].size(); + int skyTracks = framecount - waterTracks; + + if (waterTracks < 1) + { + LL_WARNS("SETTINGS") << "Missing water track" << LL_ENDL; + return false; + } + + if (skyTracks < 1) + { + LL_WARNS("SETTINGS") << "Missing sky tracks" << LL_ENDL; + return false; + } + return true; + } + + bool validateDayCycleFrames(LLSD &value) + { + bool hasSky(false); + bool hasWater(false); + + for (LLSD::map_iterator itf = value.beginMap(); itf != value.endMap(); ++itf) + { + LLSD frame = (*itf).second; + + std::string ftype = frame[LLSettingsBase::SETTING_TYPE]; + if (ftype == "sky") + { + LLSettingsSky::validation_list_t valid_sky = LLSettingsSky::validationList(); + LLSD res_sky = LLSettingsBase::settingValidation(frame, valid_sky); + + if (res_sky["success"].asInteger() == 0) + { + LL_WARNS("SETTINGS") << "Sky setting named '" << (*itf).first << "' validation failed!: " << res_sky << LL_ENDL; + LL_WARNS("SETTINGS") << "Sky: " << frame << LL_ENDL; + continue; + } + hasSky |= true; + } + else if (ftype == "water") + { + LLSettingsWater::validation_list_t valid_h2o = LLSettingsWater::validationList(); + LLSD res_h2o = LLSettingsBase::settingValidation(frame, valid_h2o); + if (res_h2o["success"].asInteger() == 0) + { + LL_WARNS("SETTINGS") << "Water setting named '" << (*itf).first << "' validation failed!: " << res_h2o << LL_ENDL; + LL_WARNS("SETTINGS") << "Water: " << frame << LL_ENDL; + continue; + } + hasWater |= true; + } + else + { + LL_WARNS("SETTINGS") << "Unknown settings block of type '" << ftype << "' named '" << (*itf).first << "'" << LL_ENDL; + return false; + } + } + + if (!hasSky) + { + LL_WARNS("SETTINGS") << "No skies defined." << LL_ENDL; + return false; + } + + if (!hasWater) + { + LL_WARNS("SETTINGS") << "No waters defined." << LL_ENDL; + return false; + } + + return true; + } +} + +LLSettingsDay::validation_list_t LLSettingsDay::getValidationList() const +{ + return LLSettingsDay::validationList(); +} + +LLSettingsDay::validation_list_t LLSettingsDay::validationList() +{ + static validation_list_t validation; + + if (validation.empty()) + { + validation.push_back(Validator(SETTING_TRACKS, true, LLSD::TypeArray, + &validateDayCycleTrack)); + validation.push_back(Validator(SETTING_FRAMES, true, LLSD::TypeMap, + &validateDayCycleFrames)); + } + + return validation; +} + +LLSettingsDay::CycleTrack_t& LLSettingsDay::getCycleTrack(size_t track) +{ + static CycleTrack_t emptyTrack; + if (mDayTracks.size() <= track) + return emptyTrack; + + return mDayTracks[track]; +} + +const LLSettingsDay::CycleTrack_t& LLSettingsDay::getCycleTrackConst(size_t track) const +{ + static CycleTrack_t emptyTrack; + if (mDayTracks.size() <= track) + return emptyTrack; + + return mDayTracks[track]; +} + +bool LLSettingsDay::clearCycleTrack(S32 track) +{ + if ((track < 0) || (track >= TRACK_MAX)) + { + LL_WARNS("DAYCYCLE") << "Attempt to clear track (#" << track << ") out of range!" << LL_ENDL; + return false; + } + mDayTracks[track].clear(); + clearAssetId(); + setDirtyFlag(true); + return true; +} + +bool LLSettingsDay::replaceCycleTrack(S32 track, const CycleTrack_t &source) +{ + if (source.empty()) + { + LL_WARNS("DAYCYCLE") << "Attempt to copy an empty track." << LL_ENDL; + return false; + } + + { + LLSettingsBase::ptr_t first((*source.begin()).second); + std::string setting_type = first->getSettingsType(); + + if (((setting_type == "water") && (track != 0)) || + ((setting_type == "sky") && (track == 0))) + { + LL_WARNS("DAYCYCLE") << "Attempt to copy track missmatch" << LL_ENDL; + return false; + } + } + + if (!clearCycleTrack(track)) + return false; + + mDayTracks[track] = source; + return true; +} + + +bool LLSettingsDay::isTrackEmpty(S32 track) const +{ + if ((track < 0) || (track >= TRACK_MAX)) + { + LL_WARNS("DAYCYCLE") << "Attempt to test track (#" << track << ") out of range!" << LL_ENDL; + return true; + } + + return mDayTracks[track].empty(); +} + +//========================================================================= +void LLSettingsDay::startDayCycle() +{ + if (!mInitialized) + { + LL_WARNS("DAYCYCLE") << "Attempt to start day cycle on uninitialized object." << LL_ENDL; + return; + } +} + + +void LLSettingsDay::updateSettings() +{ +} + +//========================================================================= +LLSettingsDay::KeyframeList_t LLSettingsDay::getTrackKeyframes(S32 trackno) +{ + if ((trackno < 0) || (trackno >= TRACK_MAX)) + { + LL_WARNS("DAYCYCLE") << "Attempt get track (#" << trackno << ") out of range!" << LL_ENDL; + return KeyframeList_t(); + } + + KeyframeList_t keyframes; + CycleTrack_t &track = mDayTracks[trackno]; + + keyframes.reserve(track.size()); + + for (CycleTrack_t::iterator it = track.begin(); it != track.end(); ++it) + { + keyframes.push_back((*it).first); + } + + return keyframes; +} + +bool LLSettingsDay::moveTrackKeyframe(S32 trackno, const LLSettingsBase::TrackPosition& old_frame, const LLSettingsBase::TrackPosition& new_frame) +{ + if ((trackno < 0) || (trackno >= TRACK_MAX)) + { + LL_WARNS("DAYCYCLE") << "Attempt get track (#" << trackno << ") out of range!" << LL_ENDL; + return false; + } + + if (old_frame == new_frame) + { + return false; + } + + CycleTrack_t &track = mDayTracks[trackno]; + CycleTrack_t::iterator iter = track.find(old_frame); + if (iter != track.end()) + { + LLSettingsBase::ptr_t base = iter->second; + track.erase(iter); + track[llclamp(new_frame, 0.0f, 1.0f)] = base; + track[new_frame] = base; + return true; + } + + return false; + +} + +bool LLSettingsDay::removeTrackKeyframe(S32 trackno, const LLSettingsBase::TrackPosition& frame) +{ + if ((trackno < 0) || (trackno >= TRACK_MAX)) + { + LL_WARNS("DAYCYCLE") << "Attempt get track (#" << trackno << ") out of range!" << LL_ENDL; + return false; + } + + CycleTrack_t &track = mDayTracks[trackno]; + CycleTrack_t::iterator iter = track.find(frame); + if (iter != track.end()) + { + LLSettingsBase::ptr_t base = iter->second; + track.erase(iter); + return true; + } + + return false; +} + +void LLSettingsDay::setWaterAtKeyframe(const LLSettingsWaterPtr_t &water, const LLSettingsBase::TrackPosition& keyframe) +{ + setSettingsAtKeyframe(water, keyframe, TRACK_WATER); +} + +LLSettingsWater::ptr_t LLSettingsDay::getWaterAtKeyframe(const LLSettingsBase::TrackPosition& keyframe) const +{ + LLSettingsBase* p = getSettingsAtKeyframe(keyframe, TRACK_WATER).get(); + return LLSettingsWater::ptr_t((LLSettingsWater*)p); +} + +void LLSettingsDay::setSkyAtKeyframe(const LLSettingsSky::ptr_t &sky, const LLSettingsBase::TrackPosition& keyframe, S32 track) +{ + if ((track < 1) || (track >= TRACK_MAX)) + { + LL_WARNS("DAYCYCLE") << "Attempt to set sky track (#" << track << ") out of range!" << LL_ENDL; + return; + } + + setSettingsAtKeyframe(sky, keyframe, track); +} + +LLSettingsSky::ptr_t LLSettingsDay::getSkyAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const +{ + if ((track < 1) || (track >= TRACK_MAX)) + { + LL_WARNS("DAYCYCLE") << "Attempt to set sky track (#" << track << ") out of range!" << LL_ENDL; + return LLSettingsSky::ptr_t(); + } + + return PTR_NAMESPACE::dynamic_pointer_cast(getSettingsAtKeyframe(keyframe, track)); +} + +void LLSettingsDay::setSettingsAtKeyframe(const LLSettingsBase::ptr_t &settings, const LLSettingsBase::TrackPosition& keyframe, S32 track) +{ + if ((track < 0) || (track >= TRACK_MAX)) + { + LL_WARNS("DAYCYCLE") << "Attempt to set track (#" << track << ") out of range!" << LL_ENDL; + return; + } + + std::string type = settings->getSettingsType(); + if ((track == TRACK_WATER) && (type != "water")) + { + LL_WARNS("DAYCYCLE") << "Attempt to add frame of type '" << type << "' to water track!" << LL_ENDL; + llassert(type == "water"); + return; + } + else if ((track != TRACK_WATER) && (type != "sky")) + { + LL_WARNS("DAYCYCLE") << "Attempt to add frame of type '" << type << "' to sky track!" << LL_ENDL; + llassert(type == "sky"); + return; + } + + mDayTracks[track][llclamp(keyframe, 0.0f, 1.0f)] = settings; + setDirtyFlag(true); +} + +LLSettingsBase::ptr_t LLSettingsDay::getSettingsAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const +{ + if ((track < 0) || (track >= TRACK_MAX)) + { + LL_WARNS("DAYCYCLE") << "Attempt to set sky track (#" << track << ") out of range!" << LL_ENDL; + return LLSettingsBase::ptr_t(); + } + + // todo: better way to identify keyframes? + CycleTrack_t::const_iterator iter = mDayTracks[track].find(keyframe); + if (iter != mDayTracks[track].end()) + { + return iter->second; + } + + return LLSettingsBase::ptr_t(); +} + +LLSettingsDay::CycleTrack_t::value_type LLSettingsDay::getSettingsNearKeyframe(const LLSettingsBase::TrackPosition &keyframe, S32 track, F32 fudge) const +{ + if ((track < 0) || (track >= TRACK_MAX)) + { + LL_WARNS("DAYCYCLE") << "Attempt to get track (#" << track << ") out of range!" << LL_ENDL; + return CycleTrack_t::value_type(TrackPosition(INVALID_TRACKPOS), LLSettingsBase::ptr_t()); + } + + if (mDayTracks[track].empty()) + { + LL_INFOS("DAYCYCLE") << "Empty track" << LL_ENDL; + return CycleTrack_t::value_type(TrackPosition(INVALID_TRACKPOS), LLSettingsBase::ptr_t()); + } + + TrackPosition startframe(keyframe - fudge); + if (startframe < 0.0f) + startframe = 1.0f + startframe; + + CycleTrack_t::iterator it = get_wrapping_atafter(const_cast(mDayTracks[track]), startframe); + + F32 dist = get_wrapping_distance(startframe, (*it).first); + + if (dist <= (fudge * 2.0f)) + return (*it); + + return CycleTrack_t::value_type(TrackPosition(INVALID_TRACKPOS), LLSettingsBase::ptr_t()); +} + +LLSettingsBase::TrackPosition LLSettingsDay::getUpperBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe) +{ + return get_wrapping_atafter(mDayTracks[track], keyframe)->first; +} + +LLSettingsBase::TrackPosition LLSettingsDay::getLowerBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe) +{ + return get_wrapping_atbefore(mDayTracks[track], keyframe)->first; +} + +LLSettingsDay::TrackBound_t LLSettingsDay::getBoundingEntries(LLSettingsDay::CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe) +{ + return TrackBound_t(get_wrapping_atbefore(track, keyframe), get_wrapping_atafter(track, keyframe)); +} + +LLUUID LLSettingsDay::GetDefaultAssetId() +{ + return DEFAULT_ASSET_ID; +} + +//========================================================================= diff --git a/indra/llinventory/llsettingsdaycycle.h b/indra/llinventory/llsettingsdaycycle.h new file mode 100644 index 0000000000..bc5f03fa16 --- /dev/null +++ b/indra/llinventory/llsettingsdaycycle.h @@ -0,0 +1,156 @@ +/** +* @file llsettingsdaycycle.h +* @author optional +* @brief A base class for asset based settings groups. +* +* $LicenseInfo:2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2017, 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_SETTINGS_DAYCYCLE_H +#define LL_SETTINGS_DAYCYCLE_H + +#include "llsettingsbase.h" + +class LLSettingsWater; +class LLSettingsSky; + +// These are alias for LLSettingsWater::ptr_t and LLSettingsSky::ptr_t respectively. +// Here for definitions only. +typedef PTR_NAMESPACE::shared_ptr LLSettingsWaterPtr_t; +typedef PTR_NAMESPACE::shared_ptr LLSettingsSkyPtr_t; + +class LLSettingsDay : public LLSettingsBase +{ +public: + // 32-bit as LLSD only supports that width at present + typedef S32Seconds Seconds; + + static const std::string SETTING_KEYID; + static const std::string SETTING_KEYNAME; + static const std::string SETTING_KEYKFRAME; + static const std::string SETTING_KEYHASH; + static const std::string SETTING_TRACKS; + static const std::string SETTING_FRAMES; + + static const Seconds MINIMUM_DAYLENGTH; + static const Seconds DEFAULT_DAYLENGTH; + static const Seconds MAXIMUM_DAYLENGTH; + + static const Seconds MINIMUM_DAYOFFSET; + static const Seconds DEFAULT_DAYOFFSET; + static const Seconds MAXIMUM_DAYOFFSET; + + static const S32 TRACK_WATER; + static const S32 TRACK_GROUND_LEVEL; + static const S32 TRACK_MAX; + static const S32 FRAME_MAX; + + static const F32 DEFAULT_FRAME_SLOP_FACTOR; + + static const LLUUID DEFAULT_ASSET_ID; + + typedef std::map CycleTrack_t; + typedef std::vector CycleList_t; + typedef PTR_NAMESPACE::shared_ptr ptr_t; + typedef PTR_NAMESPACE::weak_ptr wptr_t; + typedef std::vector KeyframeList_t; + typedef std::pair TrackBound_t; + + //--------------------------------------------------------------------- + LLSettingsDay(const LLSD &data); + virtual ~LLSettingsDay() { }; + + bool initialize(bool validate_frames = false); + + virtual ptr_t buildClone() const = 0; + virtual ptr_t buildDeepCloneAndUncompress() const = 0; + virtual LLSD getSettings() const SETTINGS_OVERRIDE; + virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_DAYCYCLE; } + + + //--------------------------------------------------------------------- + virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("daycycle"); } + + // Settings status + virtual void blend(const LLSettingsBase::ptr_t &other, F64 mix) SETTINGS_OVERRIDE; + + static LLSD defaults(); + + //--------------------------------------------------------------------- + KeyframeList_t getTrackKeyframes(S32 track); + bool moveTrackKeyframe(S32 track, const LLSettingsBase::TrackPosition& old_frame, const LLSettingsBase::TrackPosition& new_frame); + bool removeTrackKeyframe(S32 track, const LLSettingsBase::TrackPosition& frame); + + void setWaterAtKeyframe(const LLSettingsWaterPtr_t &water, const LLSettingsBase::TrackPosition& keyframe); + LLSettingsWaterPtr_t getWaterAtKeyframe(const LLSettingsBase::TrackPosition& keyframe) const; + void setSkyAtKeyframe(const LLSettingsSkyPtr_t &sky, const LLSettingsBase::TrackPosition& keyframe, S32 track); + LLSettingsSkyPtr_t getSkyAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const; + void setSettingsAtKeyframe(const LLSettingsBase::ptr_t &settings, const LLSettingsBase::TrackPosition& keyframe, S32 track); + LLSettingsBase::ptr_t getSettingsAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const; + CycleTrack_t::value_type getSettingsNearKeyframe(const LLSettingsBase::TrackPosition &keyframe, S32 track, F32 fudge) const; + + //--------------------------------------------------------------------- + void startDayCycle(); + + virtual LLSettingsSkyPtr_t getDefaultSky() const = 0; + virtual LLSettingsWaterPtr_t getDefaultWater() const = 0; + + virtual LLSettingsSkyPtr_t buildSky(LLSD) const = 0; + virtual LLSettingsWaterPtr_t buildWater(LLSD) const = 0; + + void setInitialized(bool value = true) { mInitialized = value; } + CycleTrack_t & getCycleTrack(size_t track); + const CycleTrack_t & getCycleTrackConst(size_t track) const; + bool clearCycleTrack(S32 track); + bool replaceCycleTrack(S32 track, const CycleTrack_t &source); + bool isTrackEmpty(S32 track) const; + + virtual validation_list_t getValidationList() const SETTINGS_OVERRIDE; + static validation_list_t validationList(); + + virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); } + + LLSettingsBase::TrackPosition getUpperBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe); + LLSettingsBase::TrackPosition getLowerBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe); + + static LLUUID GetDefaultAssetId(); + +protected: + LLSettingsDay(); + + virtual void updateSettings() SETTINGS_OVERRIDE; + + bool mInitialized; + +private: + CycleList_t mDayTracks; + + LLSettingsBase::Seconds mLastUpdateTime; + + void parseFromLLSD(LLSD &data); + + static CycleTrack_t::iterator getEntryAtOrBefore(CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe); + static CycleTrack_t::iterator getEntryAtOrAfter(CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe); + TrackBound_t getBoundingEntries(CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe); +}; + +#endif diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp new file mode 100644 index 0000000000..8b93ebc00f --- /dev/null +++ b/indra/llinventory/llsettingssky.cpp @@ -0,0 +1,1692 @@ +/** +* @file llsettingssky.cpp +* @author optional +* @brief A base class for asset based settings groups. +* +* $LicenseInfo:2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2017, 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 "llsettingssky.h" +#include "indra_constants.h" +#include +#include "llfasttimer.h" +#include "v3colorutil.h" + +//========================================================================= +namespace { + const F32 NIGHTTIME_ELEVATION = 8.0f; // degrees + const F32 NIGHTTIME_ELEVATION_SIN = (F32)sinf(NIGHTTIME_ELEVATION * DEG_TO_RAD); + const LLUUID IMG_BLOOM1("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); + const LLUUID IMG_RAINBOW("11b4c57c-56b3-04ed-1f82-2004363882e4"); + const LLUUID IMG_HALO("12149143-f599-91a7-77ac-b52a3c0f59cd"); +} + +namespace { + LLQuaternion convert_azimuth_and_altitude_to_quat(F32 azimuth, F32 altitude) + { + F32 sinTheta = sin(azimuth); + F32 cosTheta = cos(azimuth); + F32 sinPhi = sin(altitude); + F32 cosPhi = cos(altitude); + + LLVector3 dir; + // +x right, +z up, +y at... + dir.mV[0] = cosTheta * cosPhi; + dir.mV[1] = sinTheta * cosPhi; + dir.mV[2] = sinPhi; + + LLVector3 axis = LLVector3::x_axis % dir; + axis.normalize(); + + F32 angle = acos(LLVector3::x_axis * dir); + + LLQuaternion quat; + quat.setAngleAxis(angle, axis); + + return quat; + } +} + +static LLTrace::BlockTimerStatHandle FTM_BLEND_SKYVALUES("Blending Sky Environment"); +static LLTrace::BlockTimerStatHandle FTM_RECALCULATE_SKYVALUES("Recalculate Sky"); +static LLTrace::BlockTimerStatHandle FTM_RECALCULATE_BODIES("Recalculate Heavenly Bodies"); +static LLTrace::BlockTimerStatHandle FTM_RECALCULATE_LIGHTING("Recalculate Lighting"); + +//========================================================================= +const std::string LLSettingsSky::SETTING_AMBIENT("ambient"); +const std::string LLSettingsSky::SETTING_BLUE_DENSITY("blue_density"); +const std::string LLSettingsSky::SETTING_BLUE_HORIZON("blue_horizon"); +const std::string LLSettingsSky::SETTING_DENSITY_MULTIPLIER("density_multiplier"); +const std::string LLSettingsSky::SETTING_DISTANCE_MULTIPLIER("distance_multiplier"); +const std::string LLSettingsSky::SETTING_HAZE_DENSITY("haze_density"); +const std::string LLSettingsSky::SETTING_HAZE_HORIZON("haze_horizon"); + +const std::string LLSettingsSky::SETTING_BLOOM_TEXTUREID("bloom_id"); +const std::string LLSettingsSky::SETTING_RAINBOW_TEXTUREID("rainbow_id"); +const std::string LLSettingsSky::SETTING_HALO_TEXTUREID("halo_id"); +const std::string LLSettingsSky::SETTING_CLOUD_COLOR("cloud_color"); +const std::string LLSettingsSky::SETTING_CLOUD_POS_DENSITY1("cloud_pos_density1"); +const std::string LLSettingsSky::SETTING_CLOUD_POS_DENSITY2("cloud_pos_density2"); +const std::string LLSettingsSky::SETTING_CLOUD_SCALE("cloud_scale"); +const std::string LLSettingsSky::SETTING_CLOUD_SCROLL_RATE("cloud_scroll_rate"); +const std::string LLSettingsSky::SETTING_CLOUD_SHADOW("cloud_shadow"); +const std::string LLSettingsSky::SETTING_CLOUD_TEXTUREID("cloud_id"); +const std::string LLSettingsSky::SETTING_CLOUD_VARIANCE("cloud_variance"); + +const std::string LLSettingsSky::SETTING_DOME_OFFSET("dome_offset"); +const std::string LLSettingsSky::SETTING_DOME_RADIUS("dome_radius"); +const std::string LLSettingsSky::SETTING_GAMMA("gamma"); +const std::string LLSettingsSky::SETTING_GLOW("glow"); + +const std::string LLSettingsSky::SETTING_LIGHT_NORMAL("lightnorm"); +const std::string LLSettingsSky::SETTING_MAX_Y("max_y"); +const std::string LLSettingsSky::SETTING_MOON_ROTATION("moon_rotation"); +const std::string LLSettingsSky::SETTING_MOON_SCALE("moon_scale"); +const std::string LLSettingsSky::SETTING_MOON_TEXTUREID("moon_id"); +const std::string LLSettingsSky::SETTING_MOON_BRIGHTNESS("moon_brightness"); + +const std::string LLSettingsSky::SETTING_STAR_BRIGHTNESS("star_brightness"); +const std::string LLSettingsSky::SETTING_SUNLIGHT_COLOR("sunlight_color"); +const std::string LLSettingsSky::SETTING_SUN_ROTATION("sun_rotation"); +const std::string LLSettingsSky::SETTING_SUN_SCALE("sun_scale"); +const std::string LLSettingsSky::SETTING_SUN_TEXTUREID("sun_id"); + +const std::string LLSettingsSky::SETTING_LEGACY_EAST_ANGLE("east_angle"); +const std::string LLSettingsSky::SETTING_LEGACY_ENABLE_CLOUD_SCROLL("enable_cloud_scroll"); +const std::string LLSettingsSky::SETTING_LEGACY_SUN_ANGLE("sun_angle"); + +// these are new settings for the advanced atmospherics model +const std::string LLSettingsSky::SETTING_PLANET_RADIUS("planet_radius"); +const std::string LLSettingsSky::SETTING_SKY_BOTTOM_RADIUS("sky_bottom_radius"); +const std::string LLSettingsSky::SETTING_SKY_TOP_RADIUS("sky_top_radius"); +const std::string LLSettingsSky::SETTING_SUN_ARC_RADIANS("sun_arc_radians"); + +const std::string LLSettingsSky::SETTING_RAYLEIGH_CONFIG("rayleigh_config"); +const std::string LLSettingsSky::SETTING_MIE_CONFIG("mie_config"); +const std::string LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR("anisotropy"); +const std::string LLSettingsSky::SETTING_ABSORPTION_CONFIG("absorption_config"); + +const std::string LLSettingsSky::KEY_DENSITY_PROFILE("density"); +const std::string LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH("width"); +const std::string LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM("exp_term"); +const std::string LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR("exp_scale"); +const std::string LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM("linear_term"); +const std::string LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM("constant_term"); + +const std::string LLSettingsSky::SETTING_SKY_MOISTURE_LEVEL("moisture_level"); +const std::string LLSettingsSky::SETTING_SKY_DROPLET_RADIUS("droplet_radius"); +const std::string LLSettingsSky::SETTING_SKY_ICE_LEVEL("ice_level"); + +const LLUUID LLSettingsSky::DEFAULT_ASSET_ID("eb3a7080-831f-9f37-10f0-7b1f9ea4043c"); + +static const LLUUID DEFAULT_SUN_ID("32bfbcea-24b1-fb9d-1ef9-48a28a63730f"); // dataserver +static const LLUUID DEFAULT_MOON_ID("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver +static const LLUUID DEFAULT_CLOUD_ID("1dc1368f-e8fe-f02d-a08d-9d9f11c1af6b"); + +const std::string LLSettingsSky::SETTING_LEGACY_HAZE("legacy_haze"); + +const F32 LLSettingsSky::DOME_OFFSET(0.96f); +const F32 LLSettingsSky::DOME_RADIUS(15000.f); + +namespace +{ + +LLSettingsSky::validation_list_t legacyHazeValidationList() +{ + static LLSettingsBase::validation_list_t legacyHazeValidation; + if (legacyHazeValidation.empty()) + { + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_AMBIENT, false, LLSD::TypeArray, + boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")), + LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*"))))); + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_DENSITY, false, LLSD::TypeArray, + boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")), + LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*"))))); + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_HORIZON, false, LLSD::TypeArray, + boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")), + LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*"))))); + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_DENSITY, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(5.0f))))); + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_HORIZON, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(5.0f))))); + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_MULTIPLIER, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0001f)(2.0f))))); + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DISTANCE_MULTIPLIER, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0001f)(1000.0f))))); + } + return legacyHazeValidation; +} + +LLSettingsSky::validation_list_t rayleighValidationList() +{ + static LLSettingsBase::validation_list_t rayleighValidation; + if (rayleighValidation.empty()) + { + rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f))))); + + rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f))))); + + rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f))))); + + rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f))))); + + rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + } + return rayleighValidation; +} + +LLSettingsSky::validation_list_t absorptionValidationList() +{ + static LLSettingsBase::validation_list_t absorptionValidation; + if (absorptionValidation.empty()) + { + absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f))))); + + absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f))))); + + absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f))))); + + absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f))))); + + absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + } + return absorptionValidation; +} + +LLSettingsSky::validation_list_t mieValidationList() +{ + static LLSettingsBase::validation_list_t mieValidation; + if (mieValidation.empty()) + { + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f))))); + + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f))))); + + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f))))); + + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f))))); + + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR, false, LLSD::TypeReal, + boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + } + return mieValidation; +} + +bool validateLegacyHaze(LLSD &value) +{ + LLSettingsSky::validation_list_t legacyHazeValidations = legacyHazeValidationList(); + llassert(value.type() == LLSD::TypeMap); + LLSD result = LLSettingsBase::settingValidation(value, legacyHazeValidations); + if (result["errors"].size() > 0) + { + LL_WARNS("SETTINGS") << "Legacy Haze Config Validation errors: " << result["errors"] << LL_ENDL; + return false; + } + if (result["warnings"].size() > 0) + { + LL_WARNS("SETTINGS") << "Legacy Haze Config Validation warnings: " << result["warnings"] << LL_ENDL; + return false; + } + return true; +} + +bool validateRayleighLayers(LLSD &value) +{ + LLSettingsSky::validation_list_t rayleighValidations = rayleighValidationList(); + if (value.isArray()) + { + bool allGood = true; + for (LLSD::array_iterator itf = value.beginArray(); itf != value.endArray(); ++itf) + { + LLSD& layerConfig = (*itf); + if (layerConfig.type() == LLSD::TypeMap) + { + if (!validateRayleighLayers(layerConfig)) + { + allGood = false; + } + } + else if (layerConfig.type() == LLSD::TypeArray) + { + return validateRayleighLayers(layerConfig); + } + else + { + return LLSettingsBase::settingValidation(value, rayleighValidations); + } + } + return allGood; + } + llassert(value.type() == LLSD::TypeMap); + LLSD result = LLSettingsBase::settingValidation(value, rayleighValidations); + if (result["errors"].size() > 0) + { + LL_WARNS("SETTINGS") << "Rayleigh Config Validation errors: " << result["errors"] << LL_ENDL; + return false; + } + if (result["warnings"].size() > 0) + { + LL_WARNS("SETTINGS") << "Rayleigh Config Validation warnings: " << result["errors"] << LL_ENDL; + return false; + } + return true; +} + +bool validateAbsorptionLayers(LLSD &value) +{ + LLSettingsBase::validation_list_t absorptionValidations = absorptionValidationList(); + if (value.isArray()) + { + bool allGood = true; + for (LLSD::array_iterator itf = value.beginArray(); itf != value.endArray(); ++itf) + { + LLSD& layerConfig = (*itf); + if (layerConfig.type() == LLSD::TypeMap) + { + if (!validateAbsorptionLayers(layerConfig)) + { + allGood = false; + } + } + else if (layerConfig.type() == LLSD::TypeArray) + { + return validateAbsorptionLayers(layerConfig); + } + else + { + return LLSettingsBase::settingValidation(value, absorptionValidations); + } + } + return allGood; + } + llassert(value.type() == LLSD::TypeMap); + LLSD result = LLSettingsBase::settingValidation(value, absorptionValidations); + if (result["errors"].size() > 0) + { + LL_WARNS("SETTINGS") << "Absorption Config Validation errors: " << result["errors"] << LL_ENDL; + return false; + } + if (result["warnings"].size() > 0) + { + LL_WARNS("SETTINGS") << "Absorption Config Validation warnings: " << result["errors"] << LL_ENDL; + return false; + } + return true; +} + +bool validateMieLayers(LLSD &value) +{ + LLSettingsBase::validation_list_t mieValidations = mieValidationList(); + if (value.isArray()) + { + bool allGood = true; + for (LLSD::array_iterator itf = value.beginArray(); itf != value.endArray(); ++itf) + { + LLSD& layerConfig = (*itf); + if (layerConfig.type() == LLSD::TypeMap) + { + if (!validateMieLayers(layerConfig)) + { + allGood = false; + } + } + else if (layerConfig.type() == LLSD::TypeArray) + { + return validateMieLayers(layerConfig); + } + else + { + return LLSettingsBase::settingValidation(value, mieValidations); + } + } + return allGood; + } + LLSD result = LLSettingsBase::settingValidation(value, mieValidations); + if (result["errors"].size() > 0) + { + LL_WARNS("SETTINGS") << "Mie Config Validation errors: " << result["errors"] << LL_ENDL; + return false; + } + if (result["warnings"].size() > 0) + { + LL_WARNS("SETTINGS") << "Mie Config Validation warnings: " << result["warnings"] << LL_ENDL; + return false; + } + return true; +} + +} + +//========================================================================= +LLSettingsSky::LLSettingsSky(const LLSD &data) : + LLSettingsBase(data), + mNextSunTextureId(), + mNextMoonTextureId(), + mNextCloudTextureId(), + mNextBloomTextureId(), + mNextRainbowTextureId(), + mNextHaloTextureId() +{ +} + +LLSettingsSky::LLSettingsSky(): + LLSettingsBase(), + mNextSunTextureId(), + mNextMoonTextureId(), + mNextCloudTextureId(), + mNextBloomTextureId(), + mNextRainbowTextureId(), + mNextHaloTextureId() +{ +} + +void LLSettingsSky::replaceSettings(LLSD settings) +{ + LLSettingsBase::replaceSettings(settings); + mNextSunTextureId.setNull(); + mNextMoonTextureId.setNull(); + mNextCloudTextureId.setNull(); + mNextBloomTextureId.setNull(); + mNextRainbowTextureId.setNull(); + mNextHaloTextureId.setNull(); +} + +void LLSettingsSky::replaceWithSky(LLSettingsSky::ptr_t pother) +{ + replaceWith(pother); + + mNextSunTextureId = pother->mNextSunTextureId; + mNextMoonTextureId = pother->mNextMoonTextureId; + mNextCloudTextureId = pother->mNextCloudTextureId; + mNextBloomTextureId = pother->mNextBloomTextureId; + mNextRainbowTextureId = pother->mNextRainbowTextureId; + mNextHaloTextureId = pother->mNextHaloTextureId; +} + +void LLSettingsSky::blend(const LLSettingsBase::ptr_t &end, F64 blendf) +{ + llassert(getSettingsType() == end->getSettingsType()); + + LLSettingsSky::ptr_t other = PTR_NAMESPACE::dynamic_pointer_cast(end); + if (other) + { + if (other->mSettings.has(SETTING_LEGACY_HAZE)) + { + if (!mSettings.has(SETTING_LEGACY_HAZE) || !mSettings[SETTING_LEGACY_HAZE].has(SETTING_AMBIENT)) + { + // Special case since SETTING_AMBIENT is both in outer and legacy maps, we prioritize legacy one + // see getAmbientColor(), we are about to replaceSettings(), so we are free to set it + setAmbientColor(getAmbientColor()); + } + } + else + { + if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_AMBIENT)) + { + // Special case due to ambient's duality + // We need to match 'other's' structure for interpolation. + // We are free to change mSettings, since we are about to reset it + mSettings[SETTING_AMBIENT] = getAmbientColor().getValue(); + mSettings[SETTING_LEGACY_HAZE].erase(SETTING_AMBIENT); + } + } + + LLUUID cloud_noise_id = getCloudNoiseTextureId(); + LLUUID cloud_noise_id_next = other->getCloudNoiseTextureId(); + F64 cloud_shadow = 0; + if (!cloud_noise_id.isNull() && cloud_noise_id_next.isNull()) + { + // If there is no cloud texture in destination, reduce coverage to imitate disappearance + // See LLDrawPoolWLSky::renderSkyClouds... we don't blend present texture with null + // Note: Probably can be done by shader + cloud_shadow = lerp(mSettings[SETTING_CLOUD_SHADOW].asReal(), (F64)0.f, blendf); + cloud_noise_id_next = cloud_noise_id; + } + else if (cloud_noise_id.isNull() && !cloud_noise_id_next.isNull()) + { + // Source has no cloud texture, reduce initial coverage to imitate appearance + // use same texture as destination + cloud_shadow = lerp((F64)0.f, other->mSettings[SETTING_CLOUD_SHADOW].asReal(), blendf); + setCloudNoiseTextureId(cloud_noise_id_next); + } + else + { + cloud_shadow = lerp(mSettings[SETTING_CLOUD_SHADOW].asReal(), other->mSettings[SETTING_CLOUD_SHADOW].asReal(), blendf); + } + + LLSD blenddata = interpolateSDMap(mSettings, other->mSettings, other->getParameterMap(), blendf); + blenddata[SETTING_CLOUD_SHADOW] = LLSD::Real(cloud_shadow); + replaceSettings(blenddata); + mNextSunTextureId = other->getSunTextureId(); + mNextMoonTextureId = other->getMoonTextureId(); + mNextCloudTextureId = cloud_noise_id_next; + mNextBloomTextureId = other->getBloomTextureId(); + mNextRainbowTextureId = other->getRainbowTextureId(); + mNextHaloTextureId = other->getHaloTextureId(); + } + else + { + LL_WARNS("SETTINGS") << "Could not cast end settings to sky. No blend performed." << LL_ENDL; + } + + setBlendFactor(blendf); +} + +LLSettingsSky::stringset_t LLSettingsSky::getSkipInterpolateKeys() const +{ + static stringset_t skipSet; + + if (skipSet.empty()) + { + skipSet = LLSettingsBase::getSkipInterpolateKeys(); + skipSet.insert(SETTING_RAYLEIGH_CONFIG); + skipSet.insert(SETTING_MIE_CONFIG); + skipSet.insert(SETTING_ABSORPTION_CONFIG); + skipSet.insert(SETTING_CLOUD_SHADOW); + } + + return skipSet; +} + +LLSettingsSky::stringset_t LLSettingsSky::getSlerpKeys() const +{ + static stringset_t slepSet; + + if (slepSet.empty()) + { + slepSet.insert(SETTING_SUN_ROTATION); + slepSet.insert(SETTING_MOON_ROTATION); + } + + return slepSet; +} + +LLSettingsSky::validation_list_t LLSettingsSky::getValidationList() const +{ + return LLSettingsSky::validationList(); +} + +LLSettingsSky::validation_list_t LLSettingsSky::validationList() +{ + static validation_list_t validation; + + if (validation.empty()) + { // Note the use of LLSD(LLSDArray()()()...) This is due to an issue with the + // copy constructor for LLSDArray. Directly binding the LLSDArray as + // a parameter without first wrapping it in a pure LLSD object will result + // in deeply nested arrays like this [[[[[[[[[[v1,v2,v3]]]]]]]]]] + validation.push_back(Validator(SETTING_BLOOM_TEXTUREID, true, LLSD::TypeUUID)); + validation.push_back(Validator(SETTING_RAINBOW_TEXTUREID, false, LLSD::TypeUUID)); + validation.push_back(Validator(SETTING_HALO_TEXTUREID, false, LLSD::TypeUUID)); + + validation.push_back(Validator(SETTING_CLOUD_COLOR, true, LLSD::TypeArray, + boost::bind(&Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")), + LLSD(LLSDArray(1.0f)(1.0f)(1.0f)("*"))))); + validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY1, true, LLSD::TypeArray, + boost::bind(&Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")), + LLSD(LLSDArray(1.0f)(1.0f)(3.0f)("*"))))); + validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY2, true, LLSD::TypeArray, + boost::bind(&Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")), + LLSD(LLSDArray(1.0f)(1.0f)(1.0f)("*"))))); + validation.push_back(Validator(SETTING_CLOUD_SCALE, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.001f)(3.0f))))); + validation.push_back(Validator(SETTING_CLOUD_SCROLL_RATE, true, LLSD::TypeArray, + boost::bind(&Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(-50.0f)(-50.0f)), + LLSD(LLSDArray(50.0f)(50.0f))))); + validation.push_back(Validator(SETTING_CLOUD_SHADOW, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + validation.push_back(Validator(SETTING_CLOUD_TEXTUREID, false, LLSD::TypeUUID)); + validation.push_back(Validator(SETTING_CLOUD_VARIANCE, false, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + + validation.push_back(Validator(SETTING_DOME_OFFSET, false, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + validation.push_back(Validator(SETTING_DOME_RADIUS, false, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(2000.0f))))); + validation.push_back(Validator(SETTING_GAMMA, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(20.0f))))); + validation.push_back(Validator(SETTING_GLOW, true, LLSD::TypeArray, + boost::bind(&Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(0.2f)("*")(-10.0f)("*")), + LLSD(LLSDArray(40.0f)("*")(10.0f)("*"))))); + + validation.push_back(Validator(SETTING_MAX_Y, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(10000.0f))))); + validation.push_back(Validator(SETTING_MOON_ROTATION, true, LLSD::TypeArray, &Validator::verifyQuaternionNormal)); + validation.push_back(Validator(SETTING_MOON_SCALE, false, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0))); + validation.push_back(Validator(SETTING_MOON_TEXTUREID, false, LLSD::TypeUUID)); + validation.push_back(Validator(SETTING_MOON_BRIGHTNESS, false, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + + validation.push_back(Validator(SETTING_STAR_BRIGHTNESS, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(500.0f))))); + validation.push_back(Validator(SETTING_SUNLIGHT_COLOR, true, LLSD::TypeArray, + boost::bind(&Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")), + LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*"))))); + validation.push_back(Validator(SETTING_SUN_ROTATION, true, LLSD::TypeArray, &Validator::verifyQuaternionNormal)); + validation.push_back(Validator(SETTING_SUN_SCALE, false, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0))); + validation.push_back(Validator(SETTING_SUN_TEXTUREID, false, LLSD::TypeUUID)); + + validation.push_back(Validator(SETTING_PLANET_RADIUS, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f))))); + + validation.push_back(Validator(SETTING_SKY_BOTTOM_RADIUS, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f))))); + + validation.push_back(Validator(SETTING_SKY_TOP_RADIUS, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f))))); + + validation.push_back(Validator(SETTING_SUN_ARC_RADIANS, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(0.1f))))); + + validation.push_back(Validator(SETTING_SKY_MOISTURE_LEVEL, false, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + + validation.push_back(Validator(SETTING_SKY_DROPLET_RADIUS, false, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(5.0f)(1000.0f))))); + + validation.push_back(Validator(SETTING_SKY_ICE_LEVEL, false, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + + validation.push_back(Validator(SETTING_RAYLEIGH_CONFIG, true, LLSD::TypeArray, &validateRayleighLayers)); + validation.push_back(Validator(SETTING_ABSORPTION_CONFIG, true, LLSD::TypeArray, &validateAbsorptionLayers)); + validation.push_back(Validator(SETTING_MIE_CONFIG, true, LLSD::TypeArray, &validateMieLayers)); + validation.push_back(Validator(SETTING_LEGACY_HAZE, false, LLSD::TypeMap, &validateLegacyHaze)); + } + return validation; +} + +LLSD LLSettingsSky::createDensityProfileLayer( + F32 width, + F32 exponential_term, + F32 exponential_scale_factor, + F32 linear_term, + F32 constant_term, + F32 aniso_factor) +{ + LLSD dflt_layer; + dflt_layer[SETTING_DENSITY_PROFILE_WIDTH] = width; // 0 -> the entire atmosphere + dflt_layer[SETTING_DENSITY_PROFILE_EXP_TERM] = exponential_term; + dflt_layer[SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR] = exponential_scale_factor; + dflt_layer[SETTING_DENSITY_PROFILE_LINEAR_TERM] = linear_term; + dflt_layer[SETTING_DENSITY_PROFILE_CONSTANT_TERM] = constant_term; + + if (aniso_factor != 0.0f) + { + dflt_layer[SETTING_MIE_ANISOTROPY_FACTOR] = aniso_factor; + } + + return dflt_layer; +} + +LLSD LLSettingsSky::createSingleLayerDensityProfile( + F32 width, + F32 exponential_term, + F32 exponential_scale_factor, + F32 linear_term, + F32 constant_term, + F32 aniso_factor) +{ + LLSD dflt; + LLSD dflt_layer = createDensityProfileLayer(width, exponential_term, exponential_scale_factor, linear_term, constant_term, aniso_factor); + dflt.append(dflt_layer); + return dflt; +} + +LLSD LLSettingsSky::rayleighConfigDefault() +{ + return createSingleLayerDensityProfile(0.0f, 1.0f, -1.0f / 8000.0f, 0.0f, 0.0f); +} + +LLSD LLSettingsSky::absorptionConfigDefault() +{ +// absorption (ozone) has two linear ramping zones + LLSD dflt_absorption_layer_a = createDensityProfileLayer(25000.0f, 0.0f, 0.0f, -1.0f / 25000.0f, -2.0f / 3.0f); + LLSD dflt_absorption_layer_b = createDensityProfileLayer(0.0f, 0.0f, 0.0f, -1.0f / 15000.0f, 8.0f / 3.0f); + LLSD dflt_absorption; + dflt_absorption.append(dflt_absorption_layer_a); + dflt_absorption.append(dflt_absorption_layer_b); + return dflt_absorption; +} + +LLSD LLSettingsSky::mieConfigDefault() +{ + LLSD dflt_mie = createSingleLayerDensityProfile(0.0f, 1.0f, -1.0f / 1200.0f, 0.0f, 0.0f, 0.8f); + return dflt_mie; +} + +LLSD LLSettingsSky::defaults(const LLSettingsBase::TrackPosition& position) +{ + static LLSD dfltsetting; + + if (dfltsetting.size() == 0) + { + LLQuaternion sunquat; + LLQuaternion moonquat; + + F32 azimuth = (F_PI * position) + (80.0f * DEG_TO_RAD); + F32 altitude = (F_PI * position); + + // give the sun and moon slightly different tracks through the sky + // instead of positioning them at opposite poles from each other... + sunquat = convert_azimuth_and_altitude_to_quat(altitude, azimuth); + moonquat = convert_azimuth_and_altitude_to_quat(altitude + (F_PI * 0.125f), azimuth + (F_PI * 0.125f)); + + // Magic constants copied form dfltsetting.xml + dfltsetting[SETTING_CLOUD_COLOR] = LLColor4(0.4099f, 0.4099f, 0.4099f, 0.0f).getValue(); + dfltsetting[SETTING_CLOUD_POS_DENSITY1] = LLColor4(1.0000f, 0.5260f, 1.0000f, 0.0f).getValue(); + dfltsetting[SETTING_CLOUD_POS_DENSITY2] = LLColor4(1.0000f, 0.5260f, 1.0000f, 0.0f).getValue(); + dfltsetting[SETTING_CLOUD_SCALE] = LLSD::Real(0.4199); + dfltsetting[SETTING_CLOUD_SCROLL_RATE] = LLSDArray(0.0f)(0.0f); + dfltsetting[SETTING_CLOUD_SHADOW] = LLSD::Real(0.2699); + dfltsetting[SETTING_CLOUD_VARIANCE] = LLSD::Real(0.0); + + dfltsetting[SETTING_DOME_OFFSET] = LLSD::Real(0.96f); + dfltsetting[SETTING_DOME_RADIUS] = LLSD::Real(15000.f); + dfltsetting[SETTING_GAMMA] = LLSD::Real(1.0); + dfltsetting[SETTING_GLOW] = LLColor4(5.000f, 0.0010f, -0.4799f, 1.0f).getValue(); + + dfltsetting[SETTING_MAX_Y] = LLSD::Real(1605); + dfltsetting[SETTING_MOON_ROTATION] = moonquat.getValue(); + dfltsetting[SETTING_MOON_BRIGHTNESS] = LLSD::Real(0.5f); + + dfltsetting[SETTING_STAR_BRIGHTNESS] = LLSD::Real(256.0000); + dfltsetting[SETTING_SUNLIGHT_COLOR] = LLColor4(0.7342f, 0.7815f, 0.8999f, 0.0f).getValue(); + dfltsetting[SETTING_SUN_ROTATION] = sunquat.getValue(); + + dfltsetting[SETTING_BLOOM_TEXTUREID] = GetDefaultBloomTextureId(); + dfltsetting[SETTING_CLOUD_TEXTUREID] = GetDefaultCloudNoiseTextureId(); + dfltsetting[SETTING_MOON_TEXTUREID] = GetDefaultMoonTextureId(); + dfltsetting[SETTING_SUN_TEXTUREID] = GetDefaultSunTextureId(); + dfltsetting[SETTING_RAINBOW_TEXTUREID] = GetDefaultRainbowTextureId(); + dfltsetting[SETTING_HALO_TEXTUREID] = GetDefaultHaloTextureId(); + + dfltsetting[SETTING_TYPE] = "sky"; + + // defaults are for earth... + dfltsetting[SETTING_PLANET_RADIUS] = 6360.0f; + dfltsetting[SETTING_SKY_BOTTOM_RADIUS] = 6360.0f; + dfltsetting[SETTING_SKY_TOP_RADIUS] = 6420.0f; + dfltsetting[SETTING_SUN_ARC_RADIANS] = 0.00045f; + + dfltsetting[SETTING_SKY_MOISTURE_LEVEL] = 0.0f; + dfltsetting[SETTING_SKY_DROPLET_RADIUS] = 800.0f; + dfltsetting[SETTING_SKY_ICE_LEVEL] = 0.0f; + + dfltsetting[SETTING_RAYLEIGH_CONFIG] = rayleighConfigDefault(); + dfltsetting[SETTING_MIE_CONFIG] = mieConfigDefault(); + dfltsetting[SETTING_ABSORPTION_CONFIG] = absorptionConfigDefault(); + } + + return dfltsetting; +} + +LLSD LLSettingsSky::translateLegacyHazeSettings(const LLSD& legacy) +{ + LLSD legacyhazesettings; + +// AdvancedAtmospherics TODO +// These need to be translated into density profile info in the new settings format... +// LEGACY_ATMOSPHERICS + if (legacy.has(SETTING_AMBIENT)) + { + legacyhazesettings[SETTING_AMBIENT] = LLColor3(legacy[SETTING_AMBIENT]).getValue(); + } + if (legacy.has(SETTING_BLUE_DENSITY)) + { + legacyhazesettings[SETTING_BLUE_DENSITY] = LLColor3(legacy[SETTING_BLUE_DENSITY]).getValue(); + } + if (legacy.has(SETTING_BLUE_HORIZON)) + { + legacyhazesettings[SETTING_BLUE_HORIZON] = LLColor3(legacy[SETTING_BLUE_HORIZON]).getValue(); + } + if (legacy.has(SETTING_DENSITY_MULTIPLIER)) + { + legacyhazesettings[SETTING_DENSITY_MULTIPLIER] = LLSD::Real(legacy[SETTING_DENSITY_MULTIPLIER][0].asReal()); + } + if (legacy.has(SETTING_DISTANCE_MULTIPLIER)) + { + legacyhazesettings[SETTING_DISTANCE_MULTIPLIER] = LLSD::Real(legacy[SETTING_DISTANCE_MULTIPLIER][0].asReal()); + } + if (legacy.has(SETTING_HAZE_DENSITY)) + { + legacyhazesettings[SETTING_HAZE_DENSITY] = LLSD::Real(legacy[SETTING_HAZE_DENSITY][0].asReal()); + } + if (legacy.has(SETTING_HAZE_HORIZON)) + { + legacyhazesettings[SETTING_HAZE_HORIZON] = LLSD::Real(legacy[SETTING_HAZE_HORIZON][0].asReal()); + } + + return legacyhazesettings; +} + +LLSD LLSettingsSky::translateLegacySettings(const LLSD& legacy) +{ + bool converted_something(false); + LLSD newsettings(defaults()); + + // Move legacy haze parameters to an inner map + // allowing backward compat and simple conversion to legacy format + LLSD legacyhazesettings; + legacyhazesettings = translateLegacyHazeSettings(legacy); + if (legacyhazesettings.size() > 0) + { + newsettings[SETTING_LEGACY_HAZE] = legacyhazesettings; + converted_something |= true; + } + + if (legacy.has(SETTING_CLOUD_COLOR)) + { + newsettings[SETTING_CLOUD_COLOR] = LLColor3(legacy[SETTING_CLOUD_COLOR]).getValue(); + converted_something |= true; + } + if (legacy.has(SETTING_CLOUD_POS_DENSITY1)) + { + newsettings[SETTING_CLOUD_POS_DENSITY1] = LLColor3(legacy[SETTING_CLOUD_POS_DENSITY1]).getValue(); + converted_something |= true; + } + if (legacy.has(SETTING_CLOUD_POS_DENSITY2)) + { + newsettings[SETTING_CLOUD_POS_DENSITY2] = LLColor3(legacy[SETTING_CLOUD_POS_DENSITY2]).getValue(); + converted_something |= true; + } + if (legacy.has(SETTING_CLOUD_SCALE)) + { + newsettings[SETTING_CLOUD_SCALE] = LLSD::Real(legacy[SETTING_CLOUD_SCALE][0].asReal()); + converted_something |= true; + } + if (legacy.has(SETTING_CLOUD_SCROLL_RATE)) + { + LLVector2 cloud_scroll(legacy[SETTING_CLOUD_SCROLL_RATE]); + + cloud_scroll -= LLVector2(10, 10); + if (legacy.has(SETTING_LEGACY_ENABLE_CLOUD_SCROLL)) + { + LLSD enabled = legacy[SETTING_LEGACY_ENABLE_CLOUD_SCROLL]; + if (!enabled[0].asBoolean()) + cloud_scroll.mV[0] = 0.0f; + if (!enabled[1].asBoolean()) + cloud_scroll.mV[1] = 0.0f; + } + + newsettings[SETTING_CLOUD_SCROLL_RATE] = cloud_scroll.getValue(); + converted_something |= true; + } + if (legacy.has(SETTING_CLOUD_SHADOW)) + { + newsettings[SETTING_CLOUD_SHADOW] = LLSD::Real(legacy[SETTING_CLOUD_SHADOW][0].asReal()); + converted_something |= true; + } + + + if (legacy.has(SETTING_GAMMA)) + { + newsettings[SETTING_GAMMA] = legacy[SETTING_GAMMA][0].asReal(); + converted_something |= true; + } + if (legacy.has(SETTING_GLOW)) + { + newsettings[SETTING_GLOW] = LLColor3(legacy[SETTING_GLOW]).getValue(); + converted_something |= true; + } + + if (legacy.has(SETTING_MAX_Y)) + { + newsettings[SETTING_MAX_Y] = LLSD::Real(legacy[SETTING_MAX_Y][0].asReal()); + converted_something |= true; + } + if (legacy.has(SETTING_STAR_BRIGHTNESS)) + { + newsettings[SETTING_STAR_BRIGHTNESS] = LLSD::Real(legacy[SETTING_STAR_BRIGHTNESS].asReal() * 250.0f); + converted_something |= true; + } + if (legacy.has(SETTING_SUNLIGHT_COLOR)) + { + newsettings[SETTING_SUNLIGHT_COLOR] = LLColor4(legacy[SETTING_SUNLIGHT_COLOR]).getValue(); + converted_something |= true; + } + + if (legacy.has(SETTING_PLANET_RADIUS)) + { + newsettings[SETTING_PLANET_RADIUS] = LLSD::Real(legacy[SETTING_PLANET_RADIUS].asReal()); + converted_something |= true; + } + + if (legacy.has(SETTING_SKY_BOTTOM_RADIUS)) + { + newsettings[SETTING_SKY_BOTTOM_RADIUS] = LLSD::Real(legacy[SETTING_SKY_BOTTOM_RADIUS].asReal()); + converted_something |= true; + } + + if (legacy.has(SETTING_SKY_TOP_RADIUS)) + { + newsettings[SETTING_SKY_TOP_RADIUS] = LLSD::Real(legacy[SETTING_SKY_TOP_RADIUS].asReal()); + converted_something |= true; + } + + if (legacy.has(SETTING_SUN_ARC_RADIANS)) + { + newsettings[SETTING_SUN_ARC_RADIANS] = LLSD::Real(legacy[SETTING_SUN_ARC_RADIANS].asReal()); + converted_something |= true; + } + + if (legacy.has(SETTING_LEGACY_EAST_ANGLE) && legacy.has(SETTING_LEGACY_SUN_ANGLE)) + { + // get counter-clockwise radian angle from clockwise legacy WL east angle... + F32 azimuth = -legacy[SETTING_LEGACY_EAST_ANGLE].asReal(); + F32 altitude = legacy[SETTING_LEGACY_SUN_ANGLE].asReal(); + + LLQuaternion sunquat = convert_azimuth_and_altitude_to_quat(azimuth, altitude); + // original WL moon dir was diametrically opposed to the sun dir + LLQuaternion moonquat = convert_azimuth_and_altitude_to_quat(azimuth + F_PI, -altitude); + + newsettings[SETTING_SUN_ROTATION] = sunquat.getValue(); + newsettings[SETTING_MOON_ROTATION] = moonquat.getValue(); + converted_something |= true; + } + + if (!converted_something) + return LLSD(); + + return newsettings; +} + +void LLSettingsSky::updateSettings() +{ + LL_RECORD_BLOCK_TIME(FTM_RECALCULATE_SKYVALUES); + + // base class clears dirty flag so as to not trigger recursive update + LLSettingsBase::updateSettings(); + + // NOTE: these functions are designed to do nothing unless a dirty bit has been set + // so if you add new settings that are referenced by these update functions, + // you'll need to insure that your setter updates the dirty bits as well + calculateHeavenlyBodyPositions(); + calculateLightSettings(); +} + +F32 LLSettingsSky::getSunMoonGlowFactor() const +{ + LLVector3 sunDir = getSunDirection(); + LLVector3 moonDir = getMoonDirection(); + + // sun glow at full iff moon is not up + if (sunDir.mV[VZ] > -NIGHTTIME_ELEVATION_SIN) + { + if (moonDir.mV[2] <= 0.0f) + { + return 1.0f; + } + } + + if (moonDir.mV[2] > 0.0f) + { + return 0.25f; + } + + return 0.0f; +} + +bool LLSettingsSky::getIsSunUp() const +{ + LLVector3 sunDir = getSunDirection(); + return (sunDir.mV[2] >= 0.0f) || ((sunDir.mV[2] > -NIGHTTIME_ELEVATION_SIN) && !getIsMoonUp()); +} + +bool LLSettingsSky::getIsMoonUp() const +{ + LLVector3 moonDir = getMoonDirection(); + return moonDir.mV[2] > 0.0f; +} + +void LLSettingsSky::calculateHeavenlyBodyPositions() const +{ + LLQuaternion sunq = getSunRotation(); + LLQuaternion moonq = getMoonRotation(); + + mSunDirection = LLVector3::x_axis * sunq; + mMoonDirection = LLVector3::x_axis * moonq; + + mSunDirection.normalize(); + mMoonDirection.normalize(); + + if (mSunDirection.lengthSquared() < 0.01f) + LL_WARNS("SETTINGS") << "Zero length sun direction. Wailing and gnashing of teeth may follow... or not." << LL_ENDL; + if (mMoonDirection.lengthSquared() < 0.01f) + LL_WARNS("SETTINGS") << "Zero length moon direction. Wailing and gnashing of teeth may follow... or not." << LL_ENDL; +} + +LLVector3 LLSettingsSky::getLightDirection() const +{ + update(); + + // is the normal from the sun or the moon + if (getIsSunUp()) + { + return mSunDirection; + } + else if (getIsMoonUp()) + { + return mMoonDirection; + } + + return LLVector3::z_axis; +} + +LLColor3 LLSettingsSky::getLightDiffuse() const +{ + update(); + + // is the normal from the sun or the moon + if (getIsSunUp()) + { + return getSunDiffuse(); + } + else if (getIsMoonUp()) + { + return getMoonDiffuse(); + } + + return LLColor3::white; +} + +LLColor3 LLSettingsSky::getAmbientColor() const +{ + if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_AMBIENT)) + { + return LLColor3(mSettings[SETTING_LEGACY_HAZE][SETTING_AMBIENT]); + } + if (mSettings.has(SETTING_AMBIENT)) + { + return LLColor3(mSettings[SETTING_AMBIENT]); + } + return LLColor3(0.25f, 0.25f, 0.25f); +} + +LLColor3 LLSettingsSky::getBlueDensity() const +{ + if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_BLUE_DENSITY)) + { + return LLColor3(mSettings[SETTING_LEGACY_HAZE][SETTING_BLUE_DENSITY]); + } + return LLColor3(0.2447f, 0.4487f, 0.7599f); +} + +LLColor3 LLSettingsSky::getBlueHorizon() const +{ + if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_BLUE_HORIZON)) + { + return LLColor3(mSettings[SETTING_LEGACY_HAZE][SETTING_BLUE_HORIZON]); + } + return LLColor3(0.4954f, 0.4954f, 0.6399f); +} + +F32 LLSettingsSky::getHazeDensity() const +{ + if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_HAZE_DENSITY)) + { + return mSettings[SETTING_LEGACY_HAZE][SETTING_HAZE_DENSITY].asReal(); + } + return 0.7f; +} + +F32 LLSettingsSky::getHazeHorizon() const +{ + if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_HAZE_HORIZON)) + { + return mSettings[SETTING_LEGACY_HAZE][SETTING_HAZE_HORIZON].asReal(); + } + return 0.19f; +} + +F32 LLSettingsSky::getDensityMultiplier() const +{ + F32 density_multiplier = 0.0001f; + if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_DENSITY_MULTIPLIER)) + { + density_multiplier = mSettings[SETTING_LEGACY_HAZE][SETTING_DENSITY_MULTIPLIER].asReal(); + } + return density_multiplier; +} + +F32 LLSettingsSky::getDistanceMultiplier() const +{ + if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_DISTANCE_MULTIPLIER)) + { + return mSettings[SETTING_LEGACY_HAZE][SETTING_DISTANCE_MULTIPLIER].asReal(); + } + return 0.8f; +} + +void LLSettingsSky::setPlanetRadius(F32 radius) +{ + mSettings[SETTING_PLANET_RADIUS] = radius; +} + +void LLSettingsSky::setSkyBottomRadius(F32 radius) +{ + mSettings[SETTING_SKY_BOTTOM_RADIUS] = radius; +} + +void LLSettingsSky::setSkyTopRadius(F32 radius) +{ + mSettings[SETTING_SKY_TOP_RADIUS] = radius; +} + +void LLSettingsSky::setSunArcRadians(F32 radians) +{ + mSettings[SETTING_SUN_ARC_RADIANS] = radians; +} + +void LLSettingsSky::setMieAnisotropy(F32 aniso_factor) +{ + getMieConfig()[SETTING_MIE_ANISOTROPY_FACTOR] = aniso_factor; +} + +void LLSettingsSky::setSkyMoistureLevel(F32 moisture_level) +{ + setValue(SETTING_SKY_MOISTURE_LEVEL, moisture_level); +} + +void LLSettingsSky::setSkyDropletRadius(F32 radius) +{ + setValue(SETTING_SKY_DROPLET_RADIUS,radius); +} + +void LLSettingsSky::setSkyIceLevel(F32 ice_level) +{ + setValue(SETTING_SKY_ICE_LEVEL, ice_level); +} + +void LLSettingsSky::setAmbientColor(const LLColor3 &val) +{ + mSettings[SETTING_LEGACY_HAZE][SETTING_AMBIENT] = val.getValue(); + setDirtyFlag(true); +} + +void LLSettingsSky::setBlueDensity(const LLColor3 &val) +{ + mSettings[SETTING_LEGACY_HAZE][SETTING_BLUE_DENSITY] = val.getValue(); + setDirtyFlag(true); +} + +void LLSettingsSky::setBlueHorizon(const LLColor3 &val) +{ + mSettings[SETTING_LEGACY_HAZE][SETTING_BLUE_HORIZON] = val.getValue(); + setDirtyFlag(true); +} + +void LLSettingsSky::setDensityMultiplier(F32 val) +{ + mSettings[SETTING_LEGACY_HAZE][SETTING_DENSITY_MULTIPLIER] = val; + setDirtyFlag(true); +} + +void LLSettingsSky::setDistanceMultiplier(F32 val) +{ + mSettings[SETTING_LEGACY_HAZE][SETTING_DISTANCE_MULTIPLIER] = val; + setDirtyFlag(true); +} + +void LLSettingsSky::setHazeDensity(F32 val) +{ + mSettings[SETTING_LEGACY_HAZE][SETTING_HAZE_DENSITY] = val; + setDirtyFlag(true); +} + +void LLSettingsSky::setHazeHorizon(F32 val) +{ + mSettings[SETTING_LEGACY_HAZE][SETTING_HAZE_HORIZON] = val; + setDirtyFlag(true); +} + +// Sunlight attenuation effect (hue and brightness) due to atmosphere +// this is used later for sunlight modulation at various altitudes +LLColor3 LLSettingsSky::getLightAttenuation(F32 distance) const +{ +// LEGACY_ATMOSPHERICS + LLColor3 blue_density = getBlueDensity(); + F32 haze_density = getHazeDensity(); + F32 density_multiplier = getDensityMultiplier(); + LLColor3 density = (blue_density * 1.0 + smear(haze_density * 0.25f)); + LLColor3 light_atten = density * density_multiplier * distance; + return light_atten; +} + +LLColor3 LLSettingsSky::getLightTransmittance() const +{ +// LEGACY_ATMOSPHERICS + LLColor3 blue_density = getBlueDensity(); + F32 haze_density = getHazeDensity(); + F32 density_multiplier = getDensityMultiplier(); + LLColor3 temp1 = blue_density + smear(haze_density); + // Transparency (-> temp1) + temp1 = componentExp((temp1 * -1.f) * density_multiplier); + return temp1; +} + +LLColor3 LLSettingsSky::gammaCorrect(const LLColor3& in) const +{ + F32 gamma = getGamma(); + LLColor3 v(in); + v.clamp(); + v= smear(1.0f) - v; + v = componentPow(v, gamma); + v = smear(1.0f) - v; + return v; +} + +LLVector3 LLSettingsSky::getSunDirection() const +{ + update(); + return mSunDirection; +} + +LLVector3 LLSettingsSky::getMoonDirection() const +{ + update(); + return mMoonDirection; +} + +LLColor4 LLSettingsSky::getMoonAmbient() const +{ + update(); + return mMoonAmbient; +} + +LLColor3 LLSettingsSky::getMoonDiffuse() const +{ + update(); + return mMoonDiffuse; +} + +LLColor4 LLSettingsSky::getSunAmbient() const +{ + update(); + return mSunAmbient; +} + +LLColor3 LLSettingsSky::getSunDiffuse() const +{ + update(); + return mSunDiffuse; +} + +LLColor4 LLSettingsSky::getTotalAmbient() const +{ + update(); + return mTotalAmbient; +} + +void LLSettingsSky::calculateLightSettings() const +{ + // Initialize temp variables + LLColor3 sunlight = getSunlightColor(); + LLColor3 ambient = getAmbientColor(); + F32 cloud_shadow = getCloudShadow(); + LLVector3 lightnorm = getLightDirection(); + + // Sunlight attenuation effect (hue and brightness) due to atmosphere + // this is used later for sunlight modulation at various altitudes + F32 max_y = getMaxY(); + LLColor3 light_atten = getLightAttenuation(max_y); + LLColor3 light_transmittance = getLightTransmittance(); + + // and vary_sunlight will work properly with moon light + F32 lighty = lightnorm[1]; + if(fabs(lighty) > 0.001f) + { + lighty = 1.f / lighty; + } + lighty = llmax(0.001f, lighty); + componentMultBy(sunlight, componentExp((light_atten * -1.f) * lighty)); + + //increase ambient when there are more clouds + LLColor3 tmpAmbient = ambient + (smear(1.f) - ambient) * cloud_shadow * 0.5f; + + //brightness of surface both sunlight and ambient + mSunDiffuse = gammaCorrect(componentMult(sunlight, light_transmittance)); + mSunAmbient = gammaCorrect(componentMult(tmpAmbient, light_transmittance) * 0.5); + + mMoonDiffuse = gammaCorrect(componentMult(LLColor3::white, light_transmittance) * 0.5f); + mMoonAmbient = gammaCorrect(componentMult(LLColor3::white, light_transmittance) * 0.25f); + mTotalAmbient = mSunAmbient; +} + +LLUUID LLSettingsSky::GetDefaultAssetId() +{ + return DEFAULT_ASSET_ID; +} + +LLUUID LLSettingsSky::GetDefaultSunTextureId() +{ + return LLUUID::null; +} + + +LLUUID LLSettingsSky::GetBlankSunTextureId() +{ + return DEFAULT_SUN_ID; +} + +LLUUID LLSettingsSky::GetDefaultMoonTextureId() +{ + return DEFAULT_MOON_ID; +} + +LLUUID LLSettingsSky::GetDefaultCloudNoiseTextureId() +{ + return DEFAULT_CLOUD_ID; +} + +LLUUID LLSettingsSky::GetDefaultBloomTextureId() +{ + return IMG_BLOOM1; +} + +LLUUID LLSettingsSky::GetDefaultRainbowTextureId() +{ + return IMG_RAINBOW; +} + +LLUUID LLSettingsSky::GetDefaultHaloTextureId() +{ + return IMG_HALO; +} + +F32 LLSettingsSky::getPlanetRadius() const +{ + return mSettings[SETTING_PLANET_RADIUS].asReal(); +} + +F32 LLSettingsSky::getSkyMoistureLevel() const +{ + return mSettings[SETTING_SKY_MOISTURE_LEVEL].asReal(); +} + +F32 LLSettingsSky::getSkyDropletRadius() const +{ + return mSettings[SETTING_SKY_DROPLET_RADIUS].asReal(); +} + +F32 LLSettingsSky::getSkyIceLevel() const +{ + return mSettings[SETTING_SKY_ICE_LEVEL].asReal(); +} + +F32 LLSettingsSky::getSkyBottomRadius() const +{ + return mSettings[SETTING_SKY_BOTTOM_RADIUS].asReal(); +} + +F32 LLSettingsSky::getSkyTopRadius() const +{ + return mSettings[SETTING_SKY_TOP_RADIUS].asReal(); +} + +F32 LLSettingsSky::getSunArcRadians() const +{ + return mSettings[SETTING_SUN_ARC_RADIANS].asReal(); +} + +F32 LLSettingsSky::getMieAnisotropy() const +{ + return getMieConfig()[SETTING_MIE_ANISOTROPY_FACTOR].asReal(); +} + +LLSD LLSettingsSky::getRayleighConfig() const +{ + LLSD copy = *(mSettings[SETTING_RAYLEIGH_CONFIG].beginArray()); + return copy; +} + +LLSD LLSettingsSky::getMieConfig() const +{ + LLSD copy = *(mSettings[SETTING_MIE_CONFIG].beginArray()); + return copy; +} + +LLSD LLSettingsSky::getAbsorptionConfig() const +{ + LLSD copy = *(mSettings[SETTING_ABSORPTION_CONFIG].beginArray()); + return copy; +} + +LLSD LLSettingsSky::getRayleighConfigs() const +{ + return mSettings[SETTING_RAYLEIGH_CONFIG]; +} + +LLSD LLSettingsSky::getMieConfigs() const +{ + return mSettings[SETTING_MIE_CONFIG]; +} + +LLSD LLSettingsSky::getAbsorptionConfigs() const +{ + return mSettings[SETTING_ABSORPTION_CONFIG]; +} + +void LLSettingsSky::setRayleighConfigs(const LLSD& rayleighConfig) +{ + mSettings[SETTING_RAYLEIGH_CONFIG] = rayleighConfig; +} + +void LLSettingsSky::setMieConfigs(const LLSD& mieConfig) +{ + mSettings[SETTING_MIE_CONFIG] = mieConfig; +} + +void LLSettingsSky::setAbsorptionConfigs(const LLSD& absorptionConfig) +{ + mSettings[SETTING_ABSORPTION_CONFIG] = absorptionConfig; +} + +LLUUID LLSettingsSky::getBloomTextureId() const +{ + return mSettings[SETTING_BLOOM_TEXTUREID].asUUID(); +} + +LLUUID LLSettingsSky::getRainbowTextureId() const +{ + return mSettings[SETTING_RAINBOW_TEXTUREID].asUUID(); +} + +LLUUID LLSettingsSky::getHaloTextureId() const +{ + return mSettings[SETTING_HALO_TEXTUREID].asUUID(); +} + +//--------------------------------------------------------------------- +LLColor3 LLSettingsSky::getCloudColor() const +{ + return LLColor3(mSettings[SETTING_CLOUD_COLOR]); +} + +void LLSettingsSky::setCloudColor(const LLColor3 &val) +{ + setValue(SETTING_CLOUD_COLOR, val); +} + +LLUUID LLSettingsSky::getCloudNoiseTextureId() const +{ + return mSettings[SETTING_CLOUD_TEXTUREID].asUUID(); +} + +void LLSettingsSky::setCloudNoiseTextureId(const LLUUID &id) +{ + setValue(SETTING_CLOUD_TEXTUREID, id); +} + +LLColor3 LLSettingsSky::getCloudPosDensity1() const +{ + return LLColor3(mSettings[SETTING_CLOUD_POS_DENSITY1]); +} + +void LLSettingsSky::setCloudPosDensity1(const LLColor3 &val) +{ + setValue(SETTING_CLOUD_POS_DENSITY1, val); +} + +LLColor3 LLSettingsSky::getCloudPosDensity2() const +{ + return LLColor3(mSettings[SETTING_CLOUD_POS_DENSITY2]); +} + +void LLSettingsSky::setCloudPosDensity2(const LLColor3 &val) +{ + setValue(SETTING_CLOUD_POS_DENSITY2, val); +} + +F32 LLSettingsSky::getCloudScale() const +{ + return mSettings[SETTING_CLOUD_SCALE].asReal(); +} + +void LLSettingsSky::setCloudScale(F32 val) +{ + setValue(SETTING_CLOUD_SCALE, val); +} + +LLVector2 LLSettingsSky::getCloudScrollRate() const +{ + return LLVector2(mSettings[SETTING_CLOUD_SCROLL_RATE]); +} + +void LLSettingsSky::setCloudScrollRate(const LLVector2 &val) +{ + setValue(SETTING_CLOUD_SCROLL_RATE, val); +} + +void LLSettingsSky::setCloudScrollRateX(F32 val) +{ + mSettings[SETTING_CLOUD_SCROLL_RATE][0] = val; + setDirtyFlag(true); +} + +void LLSettingsSky::setCloudScrollRateY(F32 val) +{ + mSettings[SETTING_CLOUD_SCROLL_RATE][1] = val; + setDirtyFlag(true); +} + +F32 LLSettingsSky::getCloudShadow() const +{ + return mSettings[SETTING_CLOUD_SHADOW].asReal(); +} + +void LLSettingsSky::setCloudShadow(F32 val) +{ + setValue(SETTING_CLOUD_SHADOW, val); +} + +F32 LLSettingsSky::getCloudVariance() const +{ + return mSettings[SETTING_CLOUD_VARIANCE].asReal(); +} + +void LLSettingsSky::setCloudVariance(F32 val) +{ + setValue(SETTING_CLOUD_VARIANCE, val); +} + +F32 LLSettingsSky::getDomeOffset() const +{ + //return mSettings[SETTING_DOME_OFFSET].asReal(); + return DOME_OFFSET; +} + +F32 LLSettingsSky::getDomeRadius() const +{ + //return mSettings[SETTING_DOME_RADIUS].asReal(); + return DOME_RADIUS; +} + +F32 LLSettingsSky::getGamma() const +{ + return mSettings[SETTING_GAMMA].asReal(); +} + +void LLSettingsSky::setGamma(F32 val) +{ + mSettings[SETTING_GAMMA] = LLSD::Real(val); + setDirtyFlag(true); +} + +LLColor3 LLSettingsSky::getGlow() const +{ + return LLColor3(mSettings[SETTING_GLOW]); +} + +void LLSettingsSky::setGlow(const LLColor3 &val) +{ + setValue(SETTING_GLOW, val); +} + +F32 LLSettingsSky::getMaxY() const +{ + return mSettings[SETTING_MAX_Y].asReal(); +} + +void LLSettingsSky::setMaxY(F32 val) +{ + setValue(SETTING_MAX_Y, val); +} + +LLQuaternion LLSettingsSky::getMoonRotation() const +{ + return LLQuaternion(mSettings[SETTING_MOON_ROTATION]); +} + +void LLSettingsSky::setMoonRotation(const LLQuaternion &val) +{ + setValue(SETTING_MOON_ROTATION, val); +} + +F32 LLSettingsSky::getMoonScale() const +{ + return mSettings[SETTING_MOON_SCALE].asReal(); +} + +void LLSettingsSky::setMoonScale(F32 val) +{ + setValue(SETTING_MOON_SCALE, val); +} + +LLUUID LLSettingsSky::getMoonTextureId() const +{ + return mSettings[SETTING_MOON_TEXTUREID].asUUID(); +} + +void LLSettingsSky::setMoonTextureId(LLUUID id) +{ + setValue(SETTING_MOON_TEXTUREID, id); +} + +F32 LLSettingsSky::getMoonBrightness() const +{ + return mSettings[SETTING_MOON_BRIGHTNESS].asReal(); +} + +void LLSettingsSky::setMoonBrightness(F32 brightness_factor) +{ + setValue(SETTING_MOON_BRIGHTNESS, brightness_factor); +} + +F32 LLSettingsSky::getStarBrightness() const +{ + return mSettings[SETTING_STAR_BRIGHTNESS].asReal(); +} + +void LLSettingsSky::setStarBrightness(F32 val) +{ + setValue(SETTING_STAR_BRIGHTNESS, val); +} + +LLColor3 LLSettingsSky::getSunlightColor() const +{ + return LLColor3(mSettings[SETTING_SUNLIGHT_COLOR]); +} + +void LLSettingsSky::setSunlightColor(const LLColor3 &val) +{ + setValue(SETTING_SUNLIGHT_COLOR, val); +} + +LLQuaternion LLSettingsSky::getSunRotation() const +{ + return LLQuaternion(mSettings[SETTING_SUN_ROTATION]); +} + +void LLSettingsSky::setSunRotation(const LLQuaternion &val) +{ + setValue(SETTING_SUN_ROTATION, val); +} + + +F32 LLSettingsSky::getSunScale() const +{ + return mSettings[SETTING_SUN_SCALE].asReal(); +} + +void LLSettingsSky::setSunScale(F32 val) +{ + setValue(SETTING_SUN_SCALE, val); +} + +LLUUID LLSettingsSky::getSunTextureId() const +{ + return mSettings[SETTING_SUN_TEXTUREID].asUUID(); +} + +void LLSettingsSky::setSunTextureId(LLUUID id) +{ + setValue(SETTING_SUN_TEXTUREID, id); +} + +LLUUID LLSettingsSky::getNextSunTextureId() const +{ + return mNextSunTextureId; +} + +LLUUID LLSettingsSky::getNextMoonTextureId() const +{ + return mNextMoonTextureId; +} + +LLUUID LLSettingsSky::getNextCloudNoiseTextureId() const +{ + return mNextCloudTextureId; +} + +LLUUID LLSettingsSky::getNextBloomTextureId() const +{ + return mNextBloomTextureId; +} + diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h new file mode 100644 index 0000000000..cd173a6b18 --- /dev/null +++ b/indra/llinventory/llsettingssky.h @@ -0,0 +1,361 @@ +/** +* @file llsettingssky.h +* @author optional +* @brief A base class for asset based settings groups. +* +* $LicenseInfo:2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2017, 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_SETTINGS_SKY_H +#define LL_SETTINGS_SKY_H + +#include "llsettingsbase.h" +#include "v4coloru.h" + +const F32 EARTH_RADIUS = 6.370e6f; +const F32 SUN_RADIUS = 695.508e6f; +const F32 SUN_DIST = 149598.260e6f; +const F32 MOON_RADIUS = 1.737e6f; +const F32 MOON_DIST = 384.400e6f; + +class LLSettingsSky: public LLSettingsBase +{ +public: + static const std::string SETTING_AMBIENT; + static const std::string SETTING_BLOOM_TEXTUREID; + static const std::string SETTING_RAINBOW_TEXTUREID; + static const std::string SETTING_HALO_TEXTUREID; + static const std::string SETTING_BLUE_DENSITY; + static const std::string SETTING_BLUE_HORIZON; + static const std::string SETTING_DENSITY_MULTIPLIER; + static const std::string SETTING_DISTANCE_MULTIPLIER; + static const std::string SETTING_HAZE_DENSITY; + static const std::string SETTING_HAZE_HORIZON; + static const std::string SETTING_CLOUD_COLOR; + static const std::string SETTING_CLOUD_POS_DENSITY1; + static const std::string SETTING_CLOUD_POS_DENSITY2; + static const std::string SETTING_CLOUD_SCALE; + static const std::string SETTING_CLOUD_SCROLL_RATE; + static const std::string SETTING_CLOUD_SHADOW; + static const std::string SETTING_CLOUD_TEXTUREID; + static const std::string SETTING_CLOUD_VARIANCE; + + static const std::string SETTING_DOME_OFFSET; + static const std::string SETTING_DOME_RADIUS; + static const std::string SETTING_GAMMA; + static const std::string SETTING_GLOW; + static const std::string SETTING_LIGHT_NORMAL; + static const std::string SETTING_MAX_Y; + static const std::string SETTING_MOON_ROTATION; + static const std::string SETTING_MOON_SCALE; + static const std::string SETTING_MOON_TEXTUREID; + static const std::string SETTING_MOON_BRIGHTNESS; + + static const std::string SETTING_STAR_BRIGHTNESS; + static const std::string SETTING_SUNLIGHT_COLOR; + static const std::string SETTING_SUN_ROTATION; + static const std::string SETTING_SUN_SCALE; + static const std::string SETTING_SUN_TEXTUREID; + + static const std::string SETTING_PLANET_RADIUS; + static const std::string SETTING_SKY_BOTTOM_RADIUS; + static const std::string SETTING_SKY_TOP_RADIUS; + static const std::string SETTING_SUN_ARC_RADIANS; + static const std::string SETTING_MIE_ANISOTROPY_FACTOR; + + static const std::string SETTING_RAYLEIGH_CONFIG; + static const std::string SETTING_MIE_CONFIG; + static const std::string SETTING_ABSORPTION_CONFIG; + + static const std::string KEY_DENSITY_PROFILE; + static const std::string SETTING_DENSITY_PROFILE_WIDTH; + static const std::string SETTING_DENSITY_PROFILE_EXP_TERM; + static const std::string SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR; + static const std::string SETTING_DENSITY_PROFILE_LINEAR_TERM; + static const std::string SETTING_DENSITY_PROFILE_CONSTANT_TERM; + + static const std::string SETTING_SKY_MOISTURE_LEVEL; + static const std::string SETTING_SKY_DROPLET_RADIUS; + static const std::string SETTING_SKY_ICE_LEVEL; + + static const std::string SETTING_LEGACY_HAZE; + + static const LLUUID DEFAULT_ASSET_ID; + + typedef PTR_NAMESPACE::shared_ptr ptr_t; + + //--------------------------------------------------------------------- + LLSettingsSky(const LLSD &data); + virtual ~LLSettingsSky() { }; + + virtual ptr_t buildClone() const = 0; + + //--------------------------------------------------------------------- + virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("sky"); } + virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_SKY; } + + // Settings status + virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE; + + virtual void replaceSettings(LLSD settings) SETTINGS_OVERRIDE; + + void replaceWithSky(LLSettingsSky::ptr_t pother); + static LLSD defaults(const LLSettingsBase::TrackPosition& position = 0.0f); + + F32 getPlanetRadius() const; + F32 getSkyBottomRadius() const; + F32 getSkyTopRadius() const; + F32 getSunArcRadians() const; + F32 getMieAnisotropy() const; + + F32 getSkyMoistureLevel() const; + F32 getSkyDropletRadius() const; + F32 getSkyIceLevel() const; + + // Return first (only) profile layer represented in LLSD + LLSD getRayleighConfig() const; + LLSD getMieConfig() const; + LLSD getAbsorptionConfig() const; + + // Return entire LLSDArray of profile layers represented in LLSD + LLSD getRayleighConfigs() const; + LLSD getMieConfigs() const; + LLSD getAbsorptionConfigs() const; + + LLUUID getBloomTextureId() const; + LLUUID getRainbowTextureId() const; + LLUUID getHaloTextureId() const; + + void setRayleighConfigs(const LLSD& rayleighConfig); + void setMieConfigs(const LLSD& mieConfig); + void setAbsorptionConfigs(const LLSD& absorptionConfig); + + void setPlanetRadius(F32 radius); + void setSkyBottomRadius(F32 radius); + void setSkyTopRadius(F32 radius); + void setSunArcRadians(F32 radians); + void setMieAnisotropy(F32 aniso_factor); + + void setSkyMoistureLevel(F32 moisture_level); + void setSkyDropletRadius(F32 radius); + void setSkyIceLevel(F32 ice_level); + + //--------------------------------------------------------------------- + LLColor3 getAmbientColor() const; + void setAmbientColor(const LLColor3 &val); + + LLColor3 getCloudColor() const; + void setCloudColor(const LLColor3 &val); + + LLUUID getCloudNoiseTextureId() const; + void setCloudNoiseTextureId(const LLUUID &id); + + LLColor3 getCloudPosDensity1() const; + void setCloudPosDensity1(const LLColor3 &val); + + LLColor3 getCloudPosDensity2() const; + void setCloudPosDensity2(const LLColor3 &val); + + F32 getCloudScale() const; + void setCloudScale(F32 val); + + LLVector2 getCloudScrollRate() const; + void setCloudScrollRate(const LLVector2 &val); + + void setCloudScrollRateX(F32 val); + void setCloudScrollRateY(F32 val); + + F32 getCloudShadow() const; + void setCloudShadow(F32 val); + + F32 getCloudVariance() const; + void setCloudVariance(F32 val); + + F32 getDomeOffset() const; + F32 getDomeRadius() const; + + F32 getGamma() const; + + void setGamma(F32 val); + + LLColor3 getGlow() const; + void setGlow(const LLColor3 &val); + + F32 getMaxY() const; + + void setMaxY(F32 val); + + LLQuaternion getMoonRotation() const; + void setMoonRotation(const LLQuaternion &val); + + F32 getMoonScale() const; + void setMoonScale(F32 val); + + LLUUID getMoonTextureId() const; + void setMoonTextureId(LLUUID id); + + F32 getMoonBrightness() const; + void setMoonBrightness(F32 brightness_factor); + + F32 getStarBrightness() const; + void setStarBrightness(F32 val); + + LLColor3 getSunlightColor() const; + void setSunlightColor(const LLColor3 &val); + + LLQuaternion getSunRotation() const; + void setSunRotation(const LLQuaternion &val) ; + + F32 getSunScale() const; + void setSunScale(F32 val); + + LLUUID getSunTextureId() const; + void setSunTextureId(LLUUID id); + + //===================================================================== + // transient properties used in animations. + LLUUID getNextSunTextureId() const; + LLUUID getNextMoonTextureId() const; + LLUUID getNextCloudNoiseTextureId() const; + LLUUID getNextBloomTextureId() const; + + //===================================================================== + virtual void loadTextures() { }; + + //===================================================================== + virtual validation_list_t getValidationList() const SETTINGS_OVERRIDE; + static validation_list_t validationList(); + + static LLSD translateLegacySettings(const LLSD& legacy); + +// LEGACY_ATMOSPHERICS + static LLSD translateLegacyHazeSettings(const LLSD& legacy); + + LLColor3 getLightAttenuation(F32 distance) const; + LLColor3 getLightTransmittance() const; + LLColor3 gammaCorrect(const LLColor3& in) const; + + LLColor3 getBlueDensity() const; + LLColor3 getBlueHorizon() const; + F32 getHazeDensity() const; + F32 getHazeHorizon() const; + F32 getDensityMultiplier() const; + F32 getDistanceMultiplier() const; + + void setBlueDensity(const LLColor3 &val); + void setBlueHorizon(const LLColor3 &val); + void setDensityMultiplier(F32 val); + void setDistanceMultiplier(F32 val); + void setHazeDensity(F32 val); + void setHazeHorizon(F32 val); + +// Internal/calculated settings + bool getIsSunUp() const; + bool getIsMoonUp() const; + + // determines how much the haze glow effect occurs in rendering + F32 getSunMoonGlowFactor() const; + + LLVector3 getLightDirection() const; + LLColor3 getLightDiffuse() const; + + LLVector3 getSunDirection() const; + LLVector3 getMoonDirection() const; + + LLColor4 getMoonAmbient() const; + LLColor3 getMoonDiffuse() const; + LLColor4 getSunAmbient() const; + LLColor3 getSunDiffuse() const; + LLColor4 getTotalAmbient() const; + + virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); } + + static LLUUID GetDefaultAssetId(); + static LLUUID GetDefaultSunTextureId(); + static LLUUID GetBlankSunTextureId(); + static LLUUID GetDefaultMoonTextureId(); + static LLUUID GetDefaultCloudNoiseTextureId(); + static LLUUID GetDefaultBloomTextureId(); + static LLUUID GetDefaultRainbowTextureId(); + static LLUUID GetDefaultHaloTextureId(); + + static LLSD createDensityProfileLayer( + F32 width, + F32 exponential_term, + F32 exponential_scale_factor, + F32 linear_term, + F32 constant_term, + F32 aniso_factor = 0.0f); + + static LLSD createSingleLayerDensityProfile( + F32 width, + F32 exponential_term, + F32 exponential_scale_factor, + F32 linear_term, + F32 constant_term, + F32 aniso_factor = 0.0f); + + virtual void updateSettings() SETTINGS_OVERRIDE; +protected: + static const std::string SETTING_LEGACY_EAST_ANGLE; + static const std::string SETTING_LEGACY_ENABLE_CLOUD_SCROLL; + static const std::string SETTING_LEGACY_SUN_ANGLE; + + LLSettingsSky(); + + virtual stringset_t getSlerpKeys() const SETTINGS_OVERRIDE; + virtual stringset_t getSkipInterpolateKeys() const SETTINGS_OVERRIDE; + + LLUUID mNextSunTextureId; + LLUUID mNextMoonTextureId; + LLUUID mNextCloudTextureId; + LLUUID mNextBloomTextureId; + LLUUID mNextRainbowTextureId; + LLUUID mNextHaloTextureId; + +private: + static LLSD rayleighConfigDefault(); + static LLSD absorptionConfigDefault(); + static LLSD mieConfigDefault(); + + void calculateHeavenlyBodyPositions() const; + void calculateLightSettings() const; + + mutable LLVector3 mSunDirection; + mutable LLVector3 mMoonDirection; + mutable LLVector3 mLightDirection; + + static const F32 DOME_RADIUS; + static const F32 DOME_OFFSET; + + mutable LLColor4 mMoonAmbient; + mutable LLColor3 mMoonDiffuse; + mutable LLColor4 mSunAmbient; + mutable LLColor3 mSunDiffuse; + mutable LLColor4 mTotalAmbient; + + typedef std::map mapNameToUniformId_t; + + static mapNameToUniformId_t sNameToUniformMapping; +}; + +#endif diff --git a/indra/llinventory/llsettingswater.cpp b/indra/llinventory/llsettingswater.cpp new file mode 100644 index 0000000000..4af1a5dc08 --- /dev/null +++ b/indra/llinventory/llsettingswater.cpp @@ -0,0 +1,303 @@ +/** +* @file llsettingswater.h +* @author optional +* @brief A base class for asset based settings groups. +* +* $LicenseInfo:2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2017, 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 "llsettingswater.h" +#include +#include +#include "llfasttimer.h" +#include "v3colorutil.h" +#include "imageids.h" + +//========================================================================= +namespace +{ + LLTrace::BlockTimerStatHandle FTM_BLEND_WATERVALUES("Blending Water Environment"); + LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERVALUES("Update Water Environment"); +} + +//========================================================================= +const std::string LLSettingsWater::SETTING_BLUR_MULTIPLIER("blur_multiplier"); +const std::string LLSettingsWater::SETTING_FOG_COLOR("water_fog_color"); +const std::string LLSettingsWater::SETTING_FOG_DENSITY("water_fog_density"); +const std::string LLSettingsWater::SETTING_FOG_MOD("underwater_fog_mod"); +const std::string LLSettingsWater::SETTING_FRESNEL_OFFSET("fresnel_offset"); +const std::string LLSettingsWater::SETTING_FRESNEL_SCALE("fresnel_scale"); +const std::string LLSettingsWater::SETTING_TRANSPARENT_TEXTURE("transparent_texture"); +const std::string LLSettingsWater::SETTING_NORMAL_MAP("normal_map"); +const std::string LLSettingsWater::SETTING_NORMAL_SCALE("normal_scale"); +const std::string LLSettingsWater::SETTING_SCALE_ABOVE("scale_above"); +const std::string LLSettingsWater::SETTING_SCALE_BELOW("scale_below"); +const std::string LLSettingsWater::SETTING_WAVE1_DIR("wave1_direction"); +const std::string LLSettingsWater::SETTING_WAVE2_DIR("wave2_direction"); + +const std::string LLSettingsWater::SETTING_LEGACY_BLUR_MULTIPLIER("blurMultiplier"); +const std::string LLSettingsWater::SETTING_LEGACY_FOG_COLOR("waterFogColor"); +const std::string LLSettingsWater::SETTING_LEGACY_FOG_DENSITY("waterFogDensity"); +const std::string LLSettingsWater::SETTING_LEGACY_FOG_MOD("underWaterFogMod"); +const std::string LLSettingsWater::SETTING_LEGACY_FRESNEL_OFFSET("fresnelOffset"); +const std::string LLSettingsWater::SETTING_LEGACY_FRESNEL_SCALE("fresnelScale"); +const std::string LLSettingsWater::SETTING_LEGACY_NORMAL_MAP("normalMap"); +const std::string LLSettingsWater::SETTING_LEGACY_NORMAL_SCALE("normScale"); +const std::string LLSettingsWater::SETTING_LEGACY_SCALE_ABOVE("scaleAbove"); +const std::string LLSettingsWater::SETTING_LEGACY_SCALE_BELOW("scaleBelow"); +const std::string LLSettingsWater::SETTING_LEGACY_WAVE1_DIR("wave1Dir"); +const std::string LLSettingsWater::SETTING_LEGACY_WAVE2_DIR("wave2Dir"); + +const LLUUID LLSettingsWater::DEFAULT_ASSET_ID("59d1a851-47e7-0e5f-1ed7-6b715154f41a"); + +static const LLUUID DEFAULT_TRANSPARENT_WATER_TEXTURE("2bfd3884-7e27-69b9-ba3a-3e673f680004"); +static const LLUUID DEFAULT_OPAQUE_WATER_TEXTURE("43c32285-d658-1793-c123-bf86315de055"); + +//========================================================================= +LLSettingsWater::LLSettingsWater(const LLSD &data) : + LLSettingsBase(data), + mNextNormalMapID() +{ +} + +LLSettingsWater::LLSettingsWater() : + LLSettingsBase(), + mNextNormalMapID() +{ +} + +//========================================================================= +LLSD LLSettingsWater::defaults(const LLSettingsBase::TrackPosition& position) +{ + static LLSD dfltsetting; + + if (dfltsetting.size() == 0) + { + // give the normal scale offset some variability over track time... + F32 normal_scale_offset = (position * 0.5f) - 0.25f; + + // Magic constants copied form defaults.xml + dfltsetting[SETTING_BLUR_MULTIPLIER] = LLSD::Real(0.04000f); + dfltsetting[SETTING_FOG_COLOR] = LLColor3(0.0156f, 0.1490f, 0.2509f).getValue(); + dfltsetting[SETTING_FOG_DENSITY] = LLSD::Real(2.0f); + dfltsetting[SETTING_FOG_MOD] = LLSD::Real(0.25f); + dfltsetting[SETTING_FRESNEL_OFFSET] = LLSD::Real(0.5f); + dfltsetting[SETTING_FRESNEL_SCALE] = LLSD::Real(0.3999); + dfltsetting[SETTING_TRANSPARENT_TEXTURE] = GetDefaultTransparentTextureAssetId(); + dfltsetting[SETTING_NORMAL_MAP] = GetDefaultWaterNormalAssetId(); + dfltsetting[SETTING_NORMAL_SCALE] = LLVector3(2.0f + normal_scale_offset, 2.0f + normal_scale_offset, 2.0f + normal_scale_offset).getValue(); + dfltsetting[SETTING_SCALE_ABOVE] = LLSD::Real(0.0299f); + dfltsetting[SETTING_SCALE_BELOW] = LLSD::Real(0.2000f); + dfltsetting[SETTING_WAVE1_DIR] = LLVector2(1.04999f, -0.42000f).getValue(); + dfltsetting[SETTING_WAVE2_DIR] = LLVector2(1.10999f, -1.16000f).getValue(); + + dfltsetting[SETTING_TYPE] = "water"; + } + + return dfltsetting; +} + +LLSD LLSettingsWater::translateLegacySettings(LLSD legacy) +{ + bool converted_something(false); + LLSD newsettings(defaults()); + + if (legacy.has(SETTING_LEGACY_BLUR_MULTIPLIER)) + { + newsettings[SETTING_BLUR_MULTIPLIER] = LLSD::Real(legacy[SETTING_LEGACY_BLUR_MULTIPLIER].asReal()); + converted_something |= true; + } + if (legacy.has(SETTING_LEGACY_FOG_COLOR)) + { + newsettings[SETTING_FOG_COLOR] = LLColor3(legacy[SETTING_LEGACY_FOG_COLOR]).getValue(); + converted_something |= true; + } + if (legacy.has(SETTING_LEGACY_FOG_DENSITY)) + { + newsettings[SETTING_FOG_DENSITY] = LLSD::Real(legacy[SETTING_LEGACY_FOG_DENSITY]); + converted_something |= true; + } + if (legacy.has(SETTING_LEGACY_FOG_MOD)) + { + newsettings[SETTING_FOG_MOD] = LLSD::Real(legacy[SETTING_LEGACY_FOG_MOD].asReal()); + converted_something |= true; + } + if (legacy.has(SETTING_LEGACY_FRESNEL_OFFSET)) + { + newsettings[SETTING_FRESNEL_OFFSET] = LLSD::Real(legacy[SETTING_LEGACY_FRESNEL_OFFSET].asReal()); + converted_something |= true; + } + if (legacy.has(SETTING_LEGACY_FRESNEL_SCALE)) + { + newsettings[SETTING_FRESNEL_SCALE] = LLSD::Real(legacy[SETTING_LEGACY_FRESNEL_SCALE].asReal()); + converted_something |= true; + } + if (legacy.has(SETTING_LEGACY_NORMAL_MAP)) + { + newsettings[SETTING_NORMAL_MAP] = LLSD::UUID(legacy[SETTING_LEGACY_NORMAL_MAP].asUUID()); + converted_something |= true; + } + if (legacy.has(SETTING_LEGACY_NORMAL_SCALE)) + { + newsettings[SETTING_NORMAL_SCALE] = LLVector3(legacy[SETTING_LEGACY_NORMAL_SCALE]).getValue(); + converted_something |= true; + } + if (legacy.has(SETTING_LEGACY_SCALE_ABOVE)) + { + newsettings[SETTING_SCALE_ABOVE] = LLSD::Real(legacy[SETTING_LEGACY_SCALE_ABOVE].asReal()); + converted_something |= true; + } + if (legacy.has(SETTING_LEGACY_SCALE_BELOW)) + { + newsettings[SETTING_SCALE_BELOW] = LLSD::Real(legacy[SETTING_LEGACY_SCALE_BELOW].asReal()); + converted_something |= true; + } + if (legacy.has(SETTING_LEGACY_WAVE1_DIR)) + { + newsettings[SETTING_WAVE1_DIR] = LLVector2(legacy[SETTING_LEGACY_WAVE1_DIR]).getValue(); + converted_something |= true; + } + if (legacy.has(SETTING_LEGACY_WAVE2_DIR)) + { + newsettings[SETTING_WAVE2_DIR] = LLVector2(legacy[SETTING_LEGACY_WAVE2_DIR]).getValue(); + converted_something |= true; + } + + if (!converted_something) + return LLSD(); + return newsettings; +} + +void LLSettingsWater::blend(const LLSettingsBase::ptr_t &end, F64 blendf) +{ + LLSettingsWater::ptr_t other = PTR_NAMESPACE::static_pointer_cast(end); + if (other) + { + LLSD blenddata = interpolateSDMap(mSettings, other->mSettings, other->getParameterMap(), blendf); + replaceSettings(blenddata); + mNextNormalMapID = other->getNormalMapID(); + mNextTransparentTextureID = other->getTransparentTextureID(); + } + else + { + LL_WARNS("SETTINGS") << "Could not cast end settings to water. No blend performed." << LL_ENDL; + } + setBlendFactor(blendf); +} + +void LLSettingsWater::replaceSettings(LLSD settings) +{ + LLSettingsBase::replaceSettings(settings); + mNextNormalMapID.setNull(); + mNextTransparentTextureID.setNull(); +} + +void LLSettingsWater::replaceWithWater(LLSettingsWater::ptr_t other) +{ + replaceWith(other); + + mNextNormalMapID = other->mNextNormalMapID; + mNextTransparentTextureID = other->mNextTransparentTextureID; +} + +LLSettingsWater::validation_list_t LLSettingsWater::getValidationList() const +{ + return LLSettingsWater::validationList(); +} + +LLSettingsWater::validation_list_t LLSettingsWater::validationList() +{ + static validation_list_t validation; + + if (validation.empty()) + { // Note the use of LLSD(LLSDArray()()()...) This is due to an issue with the + // copy constructor for LLSDArray. Directly binding the LLSDArray as + // a parameter without first wrapping it in a pure LLSD object will result + // in deeply nested arrays like this [[[[[[[[[[v1,v2,v3]]]]]]]]]] + + validation.push_back(Validator(SETTING_BLUR_MULTIPLIER, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(-0.5f)(0.5f))))); + validation.push_back(Validator(SETTING_FOG_COLOR, true, LLSD::TypeArray, + boost::bind(&Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(0.0f)(0.0f)(0.0f)(1.0f)), + LLSD(LLSDArray(1.0f)(1.0f)(1.0f)(1.0f))))); + validation.push_back(Validator(SETTING_FOG_DENSITY, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(-10.0f)(10.0f))))); + validation.push_back(Validator(SETTING_FOG_MOD, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(20.0f))))); + validation.push_back(Validator(SETTING_FRESNEL_OFFSET, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + validation.push_back(Validator(SETTING_FRESNEL_SCALE, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f))))); + validation.push_back(Validator(SETTING_NORMAL_MAP, true, LLSD::TypeUUID)); + validation.push_back(Validator(SETTING_NORMAL_SCALE, true, LLSD::TypeArray, + boost::bind(&Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(0.0f)(0.0f)(0.0f)), + LLSD(LLSDArray(10.0f)(10.0f)(10.0f))))); + validation.push_back(Validator(SETTING_SCALE_ABOVE, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(3.0f))))); + validation.push_back(Validator(SETTING_SCALE_BELOW, true, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(3.0f))))); + validation.push_back(Validator(SETTING_WAVE1_DIR, true, LLSD::TypeArray, + boost::bind(&Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(-20.0f)(-20.0f)), + LLSD(LLSDArray(20.0f)(20.0f))))); + validation.push_back(Validator(SETTING_WAVE2_DIR, true, LLSD::TypeArray, + boost::bind(&Validator::verifyVectorMinMax, _1, + LLSD(LLSDArray(-20.0f)(-20.0f)), + LLSD(LLSDArray(20.0f)(20.0f))))); + } + + return validation; +} + +LLUUID LLSettingsWater::GetDefaultAssetId() +{ + return DEFAULT_ASSET_ID; +} + +LLUUID LLSettingsWater::GetDefaultWaterNormalAssetId() +{ + return DEFAULT_WATER_NORMAL; +} + +LLUUID LLSettingsWater::GetDefaultTransparentTextureAssetId() +{ + return DEFAULT_TRANSPARENT_WATER_TEXTURE; +} + +LLUUID LLSettingsWater::GetDefaultOpaqueTextureAssetId() +{ + return DEFAULT_OPAQUE_WATER_TEXTURE; +} + +F32 LLSettingsWater::getModifiedWaterFogDensity(bool underwater) const +{ + F32 fog_density = getWaterFogDensity(); + F32 underwater_fog_mod = getFogMod(); + if (underwater && underwater_fog_mod > 0.0f) + { + underwater_fog_mod = llclamp(underwater_fog_mod, 0.0f, 10.0f); + fog_density = pow(fog_density, underwater_fog_mod); + } + return fog_density; +} diff --git a/indra/llinventory/llsettingswater.h b/indra/llinventory/llsettingswater.h new file mode 100644 index 0000000000..e0bfd29f2d --- /dev/null +++ b/indra/llinventory/llsettingswater.h @@ -0,0 +1,249 @@ +/** +* @file llsettingssky.h +* @author optional +* @brief A base class for asset based settings groups. +* +* $LicenseInfo:2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2017, 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_SETTINGS_WATER_H +#define LL_SETTINGS_WATER_H + +#include "llsettingsbase.h" + +class LLSettingsWater : public LLSettingsBase +{ +public: + static const std::string SETTING_BLUR_MULTIPLIER; + static const std::string SETTING_FOG_COLOR; + static const std::string SETTING_FOG_DENSITY; + static const std::string SETTING_FOG_MOD; + static const std::string SETTING_FRESNEL_OFFSET; + static const std::string SETTING_FRESNEL_SCALE; + static const std::string SETTING_TRANSPARENT_TEXTURE; + static const std::string SETTING_NORMAL_MAP; + static const std::string SETTING_NORMAL_SCALE; + static const std::string SETTING_SCALE_ABOVE; + static const std::string SETTING_SCALE_BELOW; + static const std::string SETTING_WAVE1_DIR; + static const std::string SETTING_WAVE2_DIR; + + static const LLUUID DEFAULT_ASSET_ID; + + typedef PTR_NAMESPACE::shared_ptr ptr_t; + + //--------------------------------------------------------------------- + LLSettingsWater(const LLSD &data); + virtual ~LLSettingsWater() { }; + + virtual ptr_t buildClone() const = 0; + + //--------------------------------------------------------------------- + virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("water"); } + virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_WATER; } + + // Settings status + virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE; + + virtual void replaceSettings(LLSD settings) SETTINGS_OVERRIDE; + void replaceWithWater(LLSettingsWater::ptr_t other); + + static LLSD defaults(const LLSettingsBase::TrackPosition& position = 0.0f); + + //--------------------------------------------------------------------- + F32 getBlurMultiplier() const + { + return mSettings[SETTING_BLUR_MULTIPLIER].asReal(); + } + + void setBlurMultiplier(F32 val) + { + setValue(SETTING_BLUR_MULTIPLIER, val); + } + + LLColor3 getWaterFogColor() const + { + return LLColor3(mSettings[SETTING_FOG_COLOR]); + } + + void setWaterFogColor(LLColor3 val) + { + setValue(SETTING_FOG_COLOR, val); + } + + F32 getWaterFogDensity() const + { + return mSettings[SETTING_FOG_DENSITY].asReal(); + } + + F32 getModifiedWaterFogDensity(bool underwater) const; + + void setWaterFogDensity(F32 val) + { + setValue(SETTING_FOG_DENSITY, val); + } + + F32 getFogMod() const + { + return mSettings[SETTING_FOG_MOD].asReal(); + } + + void setFogMod(F32 val) + { + setValue(SETTING_FOG_MOD, val); + } + + F32 getFresnelOffset() const + { + return mSettings[SETTING_FRESNEL_OFFSET].asReal(); + } + + void setFresnelOffset(F32 val) + { + setValue(SETTING_FRESNEL_OFFSET, val); + } + + F32 getFresnelScale() const + { + return mSettings[SETTING_FRESNEL_SCALE].asReal(); + } + + void setFresnelScale(F32 val) + { + setValue(SETTING_FRESNEL_SCALE, val); + } + + LLUUID getTransparentTextureID() const + { + return mSettings[SETTING_TRANSPARENT_TEXTURE].asUUID(); + } + + void setTransparentTextureID(LLUUID val) + { + setValue(SETTING_TRANSPARENT_TEXTURE, val); + } + + LLUUID getNormalMapID() const + { + return mSettings[SETTING_NORMAL_MAP].asUUID(); + } + + void setNormalMapID(LLUUID val) + { + setValue(SETTING_NORMAL_MAP, val); + } + + LLVector3 getNormalScale() const + { + return LLVector3(mSettings[SETTING_NORMAL_SCALE]); + } + + void setNormalScale(LLVector3 val) + { + setValue(SETTING_NORMAL_SCALE, val); + } + + F32 getScaleAbove() const + { + return mSettings[SETTING_SCALE_ABOVE].asReal(); + } + + void setScaleAbove(F32 val) + { + setValue(SETTING_SCALE_ABOVE, val); + } + + F32 getScaleBelow() const + { + return mSettings[SETTING_SCALE_BELOW].asReal(); + } + + void setScaleBelow(F32 val) + { + setValue(SETTING_SCALE_BELOW, val); + } + + LLVector2 getWave1Dir() const + { + return LLVector2(mSettings[SETTING_WAVE1_DIR]); + } + + void setWave1Dir(LLVector2 val) + { + setValue(SETTING_WAVE1_DIR, val); + } + + LLVector2 getWave2Dir() const + { + return LLVector2(mSettings[SETTING_WAVE2_DIR]); + } + + void setWave2Dir(LLVector2 val) + { + setValue(SETTING_WAVE2_DIR, val); + } + + //------------------------------------------- + LLUUID getNextNormalMapID() const + { + return mNextNormalMapID; + } + + LLUUID getNextTransparentTextureID() const + { + return mNextTransparentTextureID; + } + + virtual validation_list_t getValidationList() const SETTINGS_OVERRIDE; + static validation_list_t validationList(); + + static LLSD translateLegacySettings(LLSD legacy); + + virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); } + + static LLUUID GetDefaultAssetId(); + static LLUUID GetDefaultWaterNormalAssetId(); + static LLUUID GetDefaultTransparentTextureAssetId(); + static LLUUID GetDefaultOpaqueTextureAssetId(); + +protected: + static const std::string SETTING_LEGACY_BLUR_MULTIPLIER; + static const std::string SETTING_LEGACY_FOG_COLOR; + static const std::string SETTING_LEGACY_FOG_DENSITY; + static const std::string SETTING_LEGACY_FOG_MOD; + static const std::string SETTING_LEGACY_FRESNEL_OFFSET; + static const std::string SETTING_LEGACY_FRESNEL_SCALE; + static const std::string SETTING_LEGACY_NORMAL_MAP; + static const std::string SETTING_LEGACY_NORMAL_SCALE; + static const std::string SETTING_LEGACY_SCALE_ABOVE; + static const std::string SETTING_LEGACY_SCALE_BELOW; + static const std::string SETTING_LEGACY_WAVE1_DIR; + static const std::string SETTING_LEGACY_WAVE2_DIR; + + LLSettingsWater(); + + LLUUID mNextTransparentTextureID; + LLUUID mNextNormalMapID; + +}; + +#endif diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index 1c43bb2183..e91d08a11c 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -13,20 +13,23 @@ set(llmath_SOURCE_FILES llbbox.cpp llbboxlocal.cpp llcalc.cpp + llcalcparser.cpp llcamera.cpp llcoordframe.cpp llline.cpp llmatrix3a.cpp + llmatrix4a.cpp llmodularmath.cpp llperlin.cpp llquaternion.cpp + llrigginginfo.cpp llrect.cpp - llsdutil_math.cpp llsphere.cpp llvector4a.cpp llvolume.cpp llvolumemgr.cpp llvolumeoctree.cpp + llsdutil_math.cpp m3math.cpp m4math.cpp raytrace.cpp @@ -66,7 +69,7 @@ set(llmath_HEADER_FILES llquaternion2.h llquaternion2.inl llrect.h - llsdutil_math.h + llrigginginfo.h llsimdmath.h llsimdtypes.h llsimdtypes.inl @@ -78,11 +81,13 @@ set(llmath_HEADER_FILES llvolume.h llvolumemgr.h llvolumeoctree.h + llsdutil_math.h m3math.h m4math.h raytrace.h v2math.h v3color.h + v3colorutil.h v3dmath.h v3math.h v4color.h @@ -97,4 +102,9 @@ set_source_files_properties(${llmath_HEADER_FILES} list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES}) add_library (llmath ${llmath_SOURCE_FILES}) -add_dependencies(llmath prepare) + +target_link_libraries( + llmath + PUBLIC + llcommon + ) diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp index 46330a767f..edc6986cc9 100644 --- a/indra/llmath/llcalc.cpp +++ b/indra/llmath/llcalc.cpp @@ -28,61 +28,59 @@ #include "llcalc.h" +#include "llcalcparser.h" #include "llmath.h" -#include "llcalcparser.h" // Variable names for use in the build floater -// must be lower case for parser definition -// case-insensitive for actual parsing -const char* LLCalc::X_POS = "px"; -const char* LLCalc::Y_POS = "py"; -const char* LLCalc::Z_POS = "pz"; -const char* LLCalc::X_SCALE = "sx"; -const char* LLCalc::Y_SCALE = "sy"; -const char* LLCalc::Z_SCALE = "sz"; -const char* LLCalc::X_ROT = "rx"; -const char* LLCalc::Y_ROT = "ry"; -const char* LLCalc::Z_ROT = "rz"; -const char* LLCalc::HOLLOW = "hlw"; -const char* LLCalc::CUT_BEGIN = "cb"; -const char* LLCalc::CUT_END = "ce"; -const char* LLCalc::PATH_BEGIN = "pb"; -const char* LLCalc::PATH_END = "pe"; -const char* LLCalc::TWIST_BEGIN = "tb"; -const char* LLCalc::TWIST_END = "te"; -const char* LLCalc::X_SHEAR = "shx"; -const char* LLCalc::Y_SHEAR = "shy"; -const char* LLCalc::X_TAPER = "tpx"; -const char* LLCalc::Y_TAPER = "tpy"; -const char* LLCalc::RADIUS_OFFSET = "rof"; -const char* LLCalc::REVOLUTIONS = "rev"; -const char* LLCalc::SKEW = "skw"; -const char* LLCalc::X_HOLE = "hlx"; -const char* LLCalc::Y_HOLE = "hly"; -const char* LLCalc::TEX_U_SCALE = "tsu"; -const char* LLCalc::TEX_V_SCALE = "tsv"; -const char* LLCalc::TEX_U_OFFSET = "tou"; -const char* LLCalc::TEX_V_OFFSET = "tov"; -const char* LLCalc::TEX_ROTATION = "trot"; -const char* LLCalc::TEX_TRANSPARENCY = "trns"; -const char* LLCalc::TEX_GLOW = "glow"; +const char* LLCalc::X_POS = "PX"; +const char* LLCalc::Y_POS = "PY"; +const char* LLCalc::Z_POS = "PZ"; +const char* LLCalc::X_SCALE = "SX"; +const char* LLCalc::Y_SCALE = "SY"; +const char* LLCalc::Z_SCALE = "SZ"; +const char* LLCalc::X_ROT = "RX"; +const char* LLCalc::Y_ROT = "RY"; +const char* LLCalc::Z_ROT = "RZ"; +const char* LLCalc::HOLLOW = "HLW"; +const char* LLCalc::CUT_BEGIN = "CB"; +const char* LLCalc::CUT_END = "CE"; +const char* LLCalc::PATH_BEGIN = "PB"; +const char* LLCalc::PATH_END = "PE"; +const char* LLCalc::TWIST_BEGIN = "TB"; +const char* LLCalc::TWIST_END = "TE"; +const char* LLCalc::X_SHEAR = "SHX"; +const char* LLCalc::Y_SHEAR = "SHY"; +const char* LLCalc::X_TAPER = "TPX"; +const char* LLCalc::Y_TAPER = "TPY"; +const char* LLCalc::RADIUS_OFFSET = "ROF"; +const char* LLCalc::REVOLUTIONS = "REV"; +const char* LLCalc::SKEW = "SKW"; +const char* LLCalc::X_HOLE = "HLX"; +const char* LLCalc::Y_HOLE = "HLY"; +const char* LLCalc::TEX_U_SCALE = "TSU"; +const char* LLCalc::TEX_V_SCALE = "TSV"; +const char* LLCalc::TEX_U_OFFSET = "TOU"; +const char* LLCalc::TEX_V_OFFSET = "TOV"; +const char* LLCalc::TEX_ROTATION = "TROT"; +const char* LLCalc::TEX_TRANSPARENCY = "TRNS"; +const char* LLCalc::TEX_GLOW = "GLOW"; + LLCalc* LLCalc::sInstance = NULL; -//TODO: Make this a static global class LLCalc::LLCalc() : mLastErrorPos(0) { // Init table of constants - /*setVar("PI", F_PI); - setVar("TWO_PI", F_TWO_PI); - setVar("PI_BY_TWO", F_PI_BY_TWO); - setVar("SQRT_TWO_PI", F_SQRT_TWO_PI); - setVar("SQRT2", F_SQRT2); - setVar("SQRT3", F_SQRT3); - setVar("DEG_TO_RAD", DEG_TO_RAD); - setVar("RAD_TO_DEG", RAD_TO_DEG); - setVar("GRAVITY", GRAVITY);*/ + mConstants["PI"] = F_PI; + mConstants["TWO_PI"] = F_TWO_PI; + mConstants["PI_BY_TWO"] = F_PI_BY_TWO; + mConstants["SQRT_TWO_PI"] = F_SQRT_TWO_PI; + mConstants["SQRT2"] = F_SQRT2; + mConstants["SQRT3"] = F_SQRT3; + mConstants["DEG_TO_RAD"] = DEG_TO_RAD; + mConstants["RAD_TO_DEG"] = RAD_TO_DEG; + mConstants["GRAVITY"] = GRAVITY; } LLCalc::~LLCalc() @@ -99,7 +97,7 @@ void LLCalc::cleanUp() //static LLCalc* LLCalc::getInstance() { - if (!sInstance) sInstance = new LLCalc(); + if (!sInstance) sInstance = new LLCalc(); return sInstance; } @@ -118,35 +116,47 @@ void LLCalc::clearAllVariables() mVariables.clear(); } +/* +void LLCalc::updateVariables(LLSD& vars) +{ + LLSD::map_iterator cIt = vars.beginMap(); + for(; cIt != vars.endMap(); cIt++) + { + setVar(cIt->first, (F32)(LLSD::Real)cIt->second); + } +} +*/ + bool LLCalc::evalString(const std::string& expression, F32& result) { + std::string expr_upper = expression; + LLStringUtil::toUpper(expr_upper); + + LLCalcParser calc(result, &mConstants, &mVariables); + mLastErrorPos = 0; - std::string::const_iterator itr = expression.begin(); - expression::grammar calc; - calc.constant.add - ("pi", F_PI) - ("two_pi", F_TWO_PI) - ("pi_by_two", F_PI_BY_TWO) - ("sqrt_two_pi", F_SQRT_TWO_PI) - ("sqrt2", F_SQRT2) - ("sqrt3", F_SQRT3) - ("deg_to_rad", DEG_TO_RAD) - ("rad_to_deg", RAD_TO_DEG) - ("gravity", GRAVITY) - ; - for(calc_map_t::const_iterator iter = mVariables.begin(); - iter != mVariables.end(); - ++iter) + std::string::iterator start = expr_upper.begin(); + parse_info info; + + try { - calc.constant.add(iter->first, iter->second); + info = parse(start, expr_upper.end(), calc, space_p); + LL_DEBUGS() << "Math expression: " << expression << " = " << result << LL_ENDL; } - - if (!expression::parse(itr, expression.end(), calc, result) || itr != expression.end()) + catch(parser_error &e) + { + mLastErrorPos = e.where - expr_upper.begin(); + + LL_INFOS() << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << LL_ENDL; + return false; + } + + if (!info.full) { - mLastErrorPos = itr - expression.begin(); + mLastErrorPos = info.stop - expr_upper.begin(); LL_INFOS() << "Unhandled syntax error at " << mLastErrorPos << " in expression: " << expression << LL_ENDL; return false; } - LL_DEBUGS() << "Math expression: " << expression << " = " << result << LL_ENDL; + return true; } diff --git a/indra/llmath/llcalc.h b/indra/llmath/llcalc.h index 8c71569f43..7f4c6e3178 100644 --- a/indra/llmath/llcalc.h +++ b/indra/llmath/llcalc.h @@ -86,6 +86,7 @@ class LLCalc private: std::string::size_type mLastErrorPos; + calc_map_t mConstants; calc_map_t mVariables; // "There shall be only one" diff --git a/indra/llmath/llcalcparser.cpp b/indra/llmath/llcalcparser.cpp new file mode 100644 index 0000000000..b4ca320659 --- /dev/null +++ b/indra/llmath/llcalcparser.cpp @@ -0,0 +1,63 @@ +/* + * LLCalcParser.cpp + * Copyright 2008 Aimee Walton. + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2008, 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 "llcalcparser.h" +using namespace boost::spirit::classic; + +F32 LLCalcParser::lookup(const std::string::iterator& start, const std::string::iterator& end) const +{ + LLCalc::calc_map_t::iterator iter; + + std::string name(start, end); + + if (mConstants) + { + iter = mConstants->find(name); + if (iter != mConstants->end()) + { + return (*iter).second; + } + } + else + { + // This should never happen! + throw_(end, std::string("Missing constants table")); + } + + if (mVariables) + { + iter = mVariables->find(name); + if (iter != mVariables->end()) + { + return (*iter).second; + } + } + + throw_(end, std::string("Unknown symbol " + name)); + return 0.f; +} diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h index 8df507bc83..05e7491fca 100644 --- a/indra/llmath/llcalcparser.h +++ b/indra/llmath/llcalcparser.h @@ -27,200 +27,162 @@ #ifndef LL_CALCPARSER_H #define LL_CALCPARSER_H -#include -#if !defined(SPIRIT_VERSION) || SPIRIT_VERSION < 0x2010 -#error "At least Spirit version 2.1 required" -#endif +#include +#include +#include +#include +#include +#include +using namespace boost::spirit::classic; -// Add this in if we want boost math constants. -//#include -#include -#include +#include "llcalc.h" +#include "llmath.h" -namespace expression { - - -//TODO: If we can find a better way to do this with boost::pheonix::bind lets do it -//namespace { // anonymous - -template -T min_glue(T a, T b) -{ - return std::min(a, b); -} - -template -T max_glue(T a, T b) -{ - return std::max(a, b); -} - -template -struct lazy_ufunc_ +struct LLCalcParser : grammar { - typedef RT result_type; - - template - struct result { typedef RT type; }; - - template - RT operator()(F f, A1 a1) const + LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) : + mResult(result), mConstants(constants), mVariables(vars) {}; + + struct value_closure : closure { - return f(a1); - } -}; - -template -struct lazy_bfunc_ -{ - typedef RT result_type; - - template - struct result { typedef RT type; }; - - template - RT operator()(F f, A1 a1, A2 a2) const + member1 value; + }; + + template + struct definition { - return f(a1, a2); - } -}; + // Rule declarations + rule statement, identifier; + rule expression, term, + power, + unary_expr, + factor, + unary_func, + binary_func, + group; -//} // end namespace anonymous - -template -struct grammar - : boost::spirit::qi::grammar< - Iterator, FPT(), boost::spirit::ascii::space_type - > -{ - - // symbol table for constants - // to be added by the actual calculator - struct constant_ - : boost::spirit::qi::symbols< - typename std::iterator_traits::value_type, - FPT - > - { - constant_() + // start() should return the starting symbol + rule const& start() const { return statement; } + + definition(LLCalcParser const& self) { - } - } constant; - - // symbol table for unary functions like "abs" - struct ufunc_ - : boost::spirit::qi::symbols< - typename std::iterator_traits::value_type, - FPT (*)(FPT) - > - { - ufunc_() - { - this->add - ("abs" , (FPT (*)(FPT)) std::abs ) - ("acos" , (FPT (*)(FPT)) std::acos ) - ("asin" , (FPT (*)(FPT)) std::asin ) - ("atan" , (FPT (*)(FPT)) std::atan ) - ("ceil" , (FPT (*)(FPT)) std::ceil ) - ("cos" , (FPT (*)(FPT)) std::cos ) - ("cosh" , (FPT (*)(FPT)) std::cosh ) - ("exp" , (FPT (*)(FPT)) std::exp ) - ("floor" , (FPT (*)(FPT)) std::floor) - ("log" , (FPT (*)(FPT)) std::log ) - ("log10" , (FPT (*)(FPT)) std::log10) - ("sin" , (FPT (*)(FPT)) std::sin ) - ("sinh" , (FPT (*)(FPT)) std::sinh ) - ("sqrt" , (FPT (*)(FPT)) std::sqrt ) - ("tan" , (FPT (*)(FPT)) std::tan ) - ("tanh" , (FPT (*)(FPT)) std::tanh ) + using namespace phoenix; + + assertion assert_domain("Domain error"); +// assertion assert_symbol("Unknown symbol"); + assertion assert_syntax("Syntax error"); + + identifier = + lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')] + ; + + group = + '(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')')) ; - } - } ufunc; - // symbol table for binary functions like "pow" - struct bfunc_ - : boost::spirit::qi::symbols< - typename std::iterator_traits::value_type, - FPT (*)(FPT, FPT) - > - { - bfunc_() - { - using boost::bind; - this->add - ("pow" , (FPT (*)(FPT, FPT)) std::pow ) - ("atan2", (FPT (*)(FPT, FPT)) std::atan2) - ("min" , (FPT (*)(FPT, FPT)) min_glue) - ("max" , (FPT (*)(FPT, FPT)) max_glue) + unary_func = + ((str_p("SIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sin)(self,arg1)]) | + (str_p("COS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_cos)(self,arg1)]) | + (str_p("TAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_tan)(self,arg1)]) | + (str_p("ASIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_asin)(self,arg1)]) | + (str_p("ACOS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_acos)(self,arg1)]) | + (str_p("ATAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_atan)(self,arg1)]) | + (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sqrt)(self,arg1)]) | + (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_log)(self,arg1)]) | + (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_exp)(self,arg1)]) | + (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)]) | + (str_p("FLR") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_floor)(self,arg1)]) | + (str_p("CEIL") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_ceil)(self,arg1)]) + ) >> assert_syntax(ch_p(')')) + ; + + binary_func = + ((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = bind(&LLCalcParser::_atan2)(self, binary_func.value, arg1)]) | + (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = bind(&LLCalcParser::_min)(self, binary_func.value, arg1)]) | + (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = bind(&LLCalcParser::_max)(self, binary_func.value, arg1)]) + ) >> assert_syntax(ch_p(')')) + ; + + // *TODO: Localisation of the decimal point? + // Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate + // for the current locale. However to do that here could clash with using + // the comma as a separator when passing arguments to functions. + factor = + (ureal_p[factor.value = arg1] | + group[factor.value = arg1] | + unary_func[factor.value = arg1] | + binary_func[factor.value = arg1] | + // Lookup throws an Unknown Symbol error if it is unknown, while this works fine, + // would be "neater" to handle symbol lookup from here with an assertive parser. +// constants_p[factor.value = arg1]| + identifier[factor.value = bind(&LLCalcParser::lookup)(self, arg1, arg2)] + ) >> + // Detect and throw math errors. + assert_domain(eps_p(bind(&LLCalcParser::checkNaN)(self, factor.value))) ; - } - } bfunc; - - boost::spirit::qi::rule< - Iterator, FPT(), boost::spirit::ascii::space_type - > expression, term, factor, primary; - - grammar() : grammar::base_type(expression) - { - using boost::spirit::qi::real_parser; - using boost::spirit::qi::real_policies; - real_parser > real; - - using boost::spirit::qi::_1; - using boost::spirit::qi::_2; - using boost::spirit::qi::_3; - using boost::spirit::qi::no_case; - using boost::spirit::qi::_val; - - boost::phoenix::function< lazy_ufunc_ > lazy_ufunc; - boost::phoenix::function< lazy_bfunc_ > lazy_bfunc; - expression = - term [_val = _1] - >> *( ('+' >> term [_val += _1]) - | ('-' >> term [_val -= _1]) - ) + unary_expr = + !ch_p('+') >> factor[unary_expr.value = arg1] | + '-' >> factor[unary_expr.value = -arg1] ; - - term = - factor [_val = _1] - >> *( ('*' >> factor [_val *= _1]) - | ('/' >> factor [_val /= _1]) + + power = + unary_expr[power.value = arg1] >> + *('^' >> assert_syntax(unary_expr[power.value = bind(&powf)(power.value, arg1)])) + ; + + term = + power[term.value = arg1] >> + *(('*' >> assert_syntax(power[term.value *= arg1])) | + ('/' >> assert_syntax(power[term.value /= arg1])) | + ('%' >> assert_syntax(power[term.value = bind(&fmodf)(term.value, arg1)])) ) ; - - factor = - primary [_val = _1] - >> *( ("**" >> factor [_val = boost::phoenix::bind(static_cast(&std::pow),_val,_1)]) + + expression = + assert_syntax(term[expression.value = arg1]) >> + *(('+' >> assert_syntax(term[expression.value += arg1])) | + ('-' >> assert_syntax(term[expression.value -= arg1])) ) ; - - primary = - real [_val = _1] - | '(' >> expression [_val = _1] >> ')' - | ('-' >> primary [_val = -_1]) - | ('+' >> primary [_val = _1]) - | (no_case[ufunc] >> '(' >> expression >> ')') - [_val = lazy_ufunc(_1, _2)] - | (no_case[bfunc] >> '(' >> expression >> ',' - >> expression >> ')') - [_val = lazy_bfunc(_1, _2, _3)] - | no_case[constant] [_val = _1] + + statement = + !ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p) ; - - } + } + }; + +private: + // Member functions for semantic actions + F32 lookup(const std::string::iterator&, const std::string::iterator&) const; + F32 _min(const F32& a, const F32& b) const { return llmin(a, b); } + F32 _max(const F32& a, const F32& b) const { return llmax(a, b); } + + bool checkNaN(const F32& a) const { return !std::isnan(a); } + + //FIX* non ambiguous function fix making SIN() work for calc -Cryogenic Blitz + F32 _sin(const F32& a) const { return sin(DEG_TO_RAD * a); } + F32 _cos(const F32& a) const { return cos(DEG_TO_RAD * a); } + F32 _tan(const F32& a) const { return tan(DEG_TO_RAD * a); } + F32 _asin(const F32& a) const { return asin(a * RAD_TO_DEG); } + F32 _acos(const F32& a) const { return acos(a * RAD_TO_DEG); } + F32 _atan(const F32& a) const { return atan(a * RAD_TO_DEG); } + F32 _sqrt(const F32& a) const { return sqrt(a); } + F32 _log(const F32& a) const { return log(a); } + F32 _exp(const F32& a) const { return exp(a); } + F32 _fabs(const F32& a) const { return fabs(a); } + F32 _floor(const F32& a) const { return (F32)llfloor(a); } + F32 _ceil(const F32& a) const { return llceil(a); } + F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } + + LLCalc::calc_map_t* mConstants; + LLCalc::calc_map_t* mVariables; +// LLCalc::calc_map_t* mUserVariables; + + F32& mResult; }; - -template -bool parse(Iterator &iter, - Iterator end, - const grammar &g, - FPT &result) -{ - return boost::spirit::qi::phrase_parse( - iter, end, g, boost::spirit::ascii::space, result); -} - -} // end namespace expression #endif // LL_CALCPARSER_H diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp index 721503443f..9ea9f09935 100644 --- a/indra/llmath/llcamera.cpp +++ b/indra/llmath/llcamera.cpp @@ -93,6 +93,11 @@ F32 LLCamera::getMaxView() const : MAX_FIELD_OF_VIEW; // narrow views } +LLPlane LLCamera::getUserClipPlane() const +{ + return mAgentPlanes[AGENT_PLANE_USER_CLIP]; +} + // ---------------- LLCamera::setFoo() member functions ---------------- void LLCamera::setUserClipPlane(const LLPlane& plane) diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index aed99de28d..1495d05846 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -154,6 +154,7 @@ class LLCamera bool isChanged(); //check if mAgentPlanes changed since last frame. + LLPlane getUserClipPlane() const; void setUserClipPlane(const LLPlane& plane); void disableUserClipPlane(); virtual void setView(F32 vertical_fov_rads); diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 7b3586cf36..a802da5bd5 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -41,23 +41,6 @@ // llcommon depend on llmath. #include "is_approx_equal_fraction.h" - -// work around for Windows & older gcc non-standard function names. -#if LL_WINDOWS -#include -#define llisnan(val) _isnan(val) -#define llfinite(val) _finite(val) -#elif (LL_LINUX && __GNUC__ <= 2) -#define llisnan(val) isnan(val) -#define llfinite(val) isfinite(val) -#elif LL_SOLARIS -#define llisnan(val) isnan(val) -#define llfinite(val) (val <= std::numeric_limits::max()) -#else -#define llisnan(val) std::isnan(val) -#define llfinite(val) std::isfinite(val) -#endif - // Single Precision Floating Point Routines // (There used to be more defined here, but they appeared to be redundant and // were breaking some other includes. Removed by Falcon, reviewed by Andrew, 11/25/09) @@ -65,34 +48,34 @@ #define tanf(x) ((F32)tan((F64)(x))) #endif*/ -const F32 GRAVITY = -9.8f; +constexpr F32 GRAVITY = -9.8f; // mathematical constants -const F32 F_PI = 3.1415926535897932384626433832795f; -const F32 F_TWO_PI = 6.283185307179586476925286766559f; -const F32 F_PI_BY_TWO = 1.5707963267948966192313216916398f; -const F32 F_SQRT_TWO_PI = 2.506628274631000502415765284811f; -const F32 F_E = 2.71828182845904523536f; -const F32 F_SQRT2 = 1.4142135623730950488016887242097f; -const F32 F_SQRT3 = 1.73205080756888288657986402541f; -const F32 OO_SQRT2 = 0.7071067811865475244008443621049f; -const F32 OO_SQRT3 = 0.577350269189625764509f; -const F32 DEG_TO_RAD = 0.017453292519943295769236907684886f; -const F32 RAD_TO_DEG = 57.295779513082320876798154814105f; -const F32 F_APPROXIMATELY_ZERO = 0.00001f; -const F32 F_LN10 = 2.3025850929940456840179914546844f; -const F32 OO_LN10 = 0.43429448190325182765112891891661f; -const F32 F_LN2 = 0.69314718056f; -const F32 OO_LN2 = 1.4426950408889634073599246810019f; - -const F32 F_ALMOST_ZERO = 0.0001f; -const F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO; - -const F32 GIMBAL_THRESHOLD = 0.000436f; // sets the gimballock threshold 0.025 away from +/-90 degrees +constexpr F32 F_PI = 3.1415926535897932384626433832795f; +constexpr F32 F_TWO_PI = 6.283185307179586476925286766559f; +constexpr F32 F_PI_BY_TWO = 1.5707963267948966192313216916398f; +constexpr F32 F_SQRT_TWO_PI = 2.506628274631000502415765284811f; +constexpr F32 F_E = 2.71828182845904523536f; +constexpr F32 F_SQRT2 = 1.4142135623730950488016887242097f; +constexpr F32 F_SQRT3 = 1.73205080756888288657986402541f; +constexpr F32 OO_SQRT2 = 0.7071067811865475244008443621049f; +constexpr F32 OO_SQRT3 = 0.577350269189625764509f; +constexpr F32 DEG_TO_RAD = 0.017453292519943295769236907684886f; +constexpr F32 RAD_TO_DEG = 57.295779513082320876798154814105f; +constexpr F32 F_APPROXIMATELY_ZERO = 0.00001f; +constexpr F32 F_LN10 = 2.3025850929940456840179914546844f; +constexpr F32 OO_LN10 = 0.43429448190325182765112891891661f; +constexpr F32 F_LN2 = 0.69314718056f; +constexpr F32 OO_LN2 = 1.4426950408889634073599246810019f; + +constexpr F32 F_ALMOST_ZERO = 0.0001f; +constexpr F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO; + +constexpr F32 GIMBAL_THRESHOLD = 0.000436f; // sets the gimballock threshold 0.025 away from +/-90 degrees // formula: GIMBAL_THRESHOLD = sin(DEG_TO_RAD * gimbal_threshold_angle); // BUG: Eliminate in favor of F_APPROXIMATELY_ZERO above? -const F32 FP_MAG_THRESHOLD = 0.0000001f; +constexpr F32 FP_MAG_THRESHOLD = 0.0000001f; // TODO: Replace with logic like is_approx_equal inline bool is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); } @@ -129,13 +112,13 @@ inline bool is_zero(F32 x) inline bool is_approx_equal(F32 x, F32 y) { - const S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02; + constexpr S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02; return (std::abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); } inline bool is_approx_equal(F64 x, F64 y) { - const S64 COMPARE_MANTISSA_UP_TO_BIT = 0x02; + constexpr S64 COMPARE_MANTISSA_UP_TO_BIT = 0x02; return (std::abs((S32) ((U64&)x - (U64&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); } @@ -156,36 +139,12 @@ inline F64 llabs(const F64 a) inline S32 lltrunc( F32 f ) { -#if LL_WINDOWS && !defined( __INTEL_COMPILER ) && !defined(_WIN64) && !(_MSC_VER >= 1800) - // Avoids changing the floating point control word. - // Add or subtract 0.5 - epsilon and then round - const static U32 zpfp[] = { 0xBEFFFFFF, 0x3EFFFFFF }; - S32 result; - __asm { - fld f - mov eax, f - shr eax, 29 - and eax, 4 - fadd dword ptr [zpfp + eax] - fistp result - } - return result; -#else -#ifdef LL_CPP11 - return (S32)trunc(f); -#else - return (S32)f; -#endif -#endif + return (S32)trunc(f); } inline S32 lltrunc( F64 f ) { -#ifdef LL_CPP11 return (S32)trunc(f); -#else - return (S32)f; -#endif } inline S32 llfloor( F32 f ) @@ -217,29 +176,23 @@ inline S32 llceil( F32 f ) // Use this round. Does an arithmetic round (0.5 always rounds up) inline S32 ll_round(const F32 val) { -#ifdef LL_CPP11 return (S32)round(val); -#else - return llfloor(val + 0.5f); -#endif +} + +// Singu Note: Quick round for values that are known to be >= 0. +inline S32 ll_pos_round(const F32 val) +{ + return val + .5f; } inline F32 ll_round(F32 val, F32 nearest) { -#ifdef LL_CPP11 return F32(round(val * (1.0f / nearest))) * nearest; -#else - return F32(floor(val * (1.0f / nearest) + 0.5f)) * nearest; -#endif } inline F64 ll_round(F64 val, F64 nearest) { -#ifdef LL_CPP11 return F64(round(val * (1.0 / nearest))) * nearest; -#else - return F64(floor(val * (1.0 / nearest) + 0.5)) * nearest; -#endif } // these provide minimum peak error @@ -248,8 +201,8 @@ inline F64 ll_round(F64 val, F64 nearest) // peak error = -31.4 dB // RMS error = -28.1 dB -const F32 FAST_MAG_ALPHA = 0.960433870103f; -const F32 FAST_MAG_BETA = 0.397824734759f; +constexpr F32 FAST_MAG_ALPHA = 0.960433870103f; +constexpr F32 FAST_MAG_BETA = 0.397824734759f; // these provide minimum RMS error // @@ -257,8 +210,8 @@ const F32 FAST_MAG_BETA = 0.397824734759f; // peak error = -32.6 dB // RMS error = -25.7 dB // -//const F32 FAST_MAG_ALPHA = 0.948059448969f; -//const F32 FAST_MAG_BETA = 0.392699081699f; +//constexpr F32 FAST_MAG_ALPHA = 0.948059448969f; +//constexpr F32 FAST_MAG_BETA = 0.392699081699f; inline F32 fastMagnitude(F32 a, F32 b) { @@ -275,8 +228,8 @@ inline F32 fastMagnitude(F32 a, F32 b) // // Culled from www.stereopsis.com/FPU.html -const F64 LL_DOUBLE_TO_FIX_MAGIC = 68719476736.0*1.5; //2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor -const S32 LL_SHIFT_AMOUNT = 16; //16.16 fixed point representation, +constexpr F64 LL_DOUBLE_TO_FIX_MAGIC = 68719476736.0*1.5; //2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor +constexpr S32 LL_SHIFT_AMOUNT = 16; //16.16 fixed point representation, // Endian dependent code #ifdef LL_LITTLE_ENDIAN @@ -442,7 +395,7 @@ inline U32 get_lower_power_two(U32 val, U32 max_power_two) { if(!max_power_two) { - max_power_two = 1 << 31 ; + max_power_two = 1U << 31 ; } if(max_power_two & (max_power_two - 1)) { @@ -464,7 +417,7 @@ inline U32 get_next_power_two(U32 val, U32 max_power_two) { if(!max_power_two) { - max_power_two = 1 << 31 ; + max_power_two = 1U << 31 ; } if(val >= max_power_two) diff --git a/indra/llmath/llmatrix3a.h b/indra/llmath/llmatrix3a.h index 6d896613cc..491fac5f24 100644 --- a/indra/llmath/llmatrix3a.h +++ b/indra/llmath/llmatrix3a.h @@ -57,7 +57,7 @@ class LLMatrix3a ////////////////////////// // Ctor - LLMatrix3a() {} + LLMatrix3a() = default; // Ctor for setting by columns inline LLMatrix3a( const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2 ); @@ -121,10 +121,17 @@ class LLRotation : public LLMatrix3a { public: - LLRotation() {} + LLRotation() = default; // Returns true if this rotation is orthonormal with det ~= 1 inline bool isOkRotation() const; } LL_ALIGN_POSTFIX(16); +#if !defined(LL_DEBUG) +static_assert(std::is_trivial::value, "LLMatrix3a must be a trivial type"); +static_assert(std::is_standard_layout::value, "LLMatrix3a must be a standard layout type"); + +static_assert(std::is_trivial::value, "LLRotation must be a trivial type"); +static_assert(std::is_standard_layout::value, "LLRotation must be a standard layout type"); +#endif #endif diff --git a/indra/llmath/llmatrix4a.cpp b/indra/llmath/llmatrix4a.cpp new file mode 100644 index 0000000000..fe8f0b98f3 --- /dev/null +++ b/indra/llmath/llmatrix4a.cpp @@ -0,0 +1,80 @@ +/** +* @file llmatrix4a.cpp +* @brief Functions for vectorized matrix/vector operations +* +* $LicenseInfo:firstyear=2018&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2018, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llmath.h" +#include "llmatrix4a.h" + +// Convert a bounding box into other coordinate system. Should give +// the same results as transforming every corner of the bounding box +// and extracting the bounding box of that, although that's not +// necessarily the fastest way to implement. +void matMulBoundBox(const LLMatrix4a &mat, const LLVector4a *in_extents, LLVector4a *out_extents) +{ + //get 8 corners of bounding box + LLVector4Logical mask[6]; + + for (U32 i = 0; i < 6; ++i) + { + mask[i].clear(); + } + + mask[0].setElement<2>(); //001 + mask[1].setElement<1>(); //010 + mask[2].setElement<1>(); //011 + mask[2].setElement<2>(); + mask[3].setElement<0>(); //100 + mask[4].setElement<0>(); //101 + mask[4].setElement<2>(); + mask[5].setElement<0>(); //110 + mask[5].setElement<1>(); + + LLVector4a v[8]; + + v[6] = in_extents[0]; + v[7] = in_extents[1]; + + for (U32 i = 0; i < 6; ++i) + { + v[i].setSelectWithMask(mask[i], in_extents[0], in_extents[1]); + } + + LLVector4a tv[8]; + + //transform bounding box into drawable space + for (U32 i = 0; i < 8; ++i) + { + mat.affineTransform(v[i], tv[i]); + } + + //find bounding box + out_extents[0] = out_extents[1] = tv[0]; + + for (U32 i = 1; i < 8; ++i) + { + out_extents[0].setMin(out_extents[0], tv[i]); + out_extents[1].setMax(out_extents[1], tv[i]); + } +} diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index 0af8105ec9..024dbb6c53 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -50,13 +50,22 @@ class LLMatrix4a return ll_aligned_malloc_16(size); } + void* operator new[](size_t size) + { + return ll_aligned_malloc_16(size); + } + void operator delete(void* ptr) { ll_aligned_free_16(ptr); } - LLMatrix4a() - {} + void operator delete[](void* ptr) + { + ll_aligned_free_16(ptr); + } + + LLMatrix4a() = default; LLMatrix4a(const LLQuad& q1,const LLQuad& q2,const LLQuad& q3,const LLQuad& q4) { mMatrix[0] = q1; @@ -263,10 +272,11 @@ class LLMatrix4a inline void setMul(const LLMatrix4a& m, const F32 s) { - mMatrix[0].setMul(m.mMatrix[0], s); - mMatrix[1].setMul(m.mMatrix[1], s); - mMatrix[2].setMul(m.mMatrix[2], s); - mMatrix[3].setMul(m.mMatrix[3], s); + const LLVector4a ssss(s); + mMatrix[0].setMul(m.mMatrix[0], ssss); + mMatrix[1].setMul(m.mMatrix[1], ssss); + mMatrix[2].setMul(m.mMatrix[2], ssss); + mMatrix[3].setMul(m.mMatrix[3], ssss); } inline void setMul(const LLMatrix4a& m0, const LLMatrix4a& m1) @@ -287,10 +297,11 @@ class LLMatrix4a // this = a + d*w - d0.mul(w); - d1.mul(w); - d2.mul(w); - d3.mul(w); + const LLVector4a wwww(w); + d0.mul(wwww); + d1.mul(wwww); + d2.mul(wwww); + d3.mul(wwww); mMatrix[0].setAdd(a.mMatrix[0],d0); mMatrix[1].setAdd(a.mMatrix[1],d1); @@ -698,4 +709,17 @@ class LLMatrix4a } } LL_ALIGN_POSTFIX(16); + +inline std::ostream& operator<<(std::ostream& s, const LLMatrix4a& m) +{ + s << "[" << m.getF32ptr()[0] << ", " << m.getF32ptr()[1] << ", " << m.getF32ptr()[2] << ", " << m.getF32ptr()[3] << "]"; + return s; +} + +void matMulBoundBox(const LLMatrix4a &a, const LLVector4a *in_extents, LLVector4a *out_extents); + +#if !defined(LL_DEBUG) +static_assert(std::is_trivial::value, "LLMatrix4a must be a trivial type"); +static_assert(std::is_standard_layout::value, "LLMatrix4a must be a standard layout type"); +#endif #endif diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 3d6310310e..f82a08f3ef 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -45,6 +45,7 @@ #endif extern U32 gOctreeMaxCapacity; +extern float gOctreeMinSize; extern U32 gOctreeReserveCapacity; #if LL_DEBUG #define LL_OCTREE_PARANOIA_CHECK 0 @@ -404,7 +405,7 @@ class LLOctreeNode : public LLTreeNode F32 size = mSize[0]; F32 p_size = size * 2.f; - return (radius <= 0.001f && size <= 0.001f) || + return (radius <= gOctreeMinSize && size <= gOctreeMinSize) || (radius <= p_size && radius > size); } @@ -425,7 +426,7 @@ class LLOctreeNode : public LLTreeNode } void accept(oct_traveler* visitor) { visitor->visit(this); } - virtual bool isLeaf() const { return mChildCount == 0; } + bool isLeaf() const { return mChildCount == 0; } U32 getElementCount() const { return mData.size(); } bool isEmpty() const { return mData.size() == 0; } @@ -498,7 +499,7 @@ class LLOctreeNode : public LLTreeNode return node; } - virtual bool insert(T* data) + bool insert(T* data) override { OctreeGuard::checkGuarded(this); if (data == NULL || data->getBinIndex() != -1) @@ -511,7 +512,7 @@ class LLOctreeNode : public LLTreeNode //is it here? if (isInside(data->getPositionGroup())) { - if (((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius())) || + if ((((getElementCount() < gOctreeMaxCapacity || getSize()[0] <= gOctreeMinSize) && contains(data->getBinRadius())) || (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) { //it belongs here /*mElementCount++; @@ -537,7 +538,7 @@ class LLOctreeNode : public LLTreeNode OctreeStats::getInstance()->realloc(old_cap,mData.capacity()); #endif - BaseType::insert(data); + LLOctreeNode::notifyAddition(data); return true; } else @@ -566,8 +567,9 @@ class LLOctreeNode : public LLTreeNode LLVector4a val; val.setSub(center, getCenter()); val.setAbs(val); - - S32 lt = val.lessThan(LLVector4a::getEpsilon()).getGatheredBits() & 0x7; + LLVector4a min_diff(gOctreeMinSize); + + S32 lt = val.lessThan(min_diff).getGatheredBits() & 0x7; if( lt == 0x7 ) { @@ -593,7 +595,7 @@ class LLOctreeNode : public LLTreeNode OctreeStats::getInstance()->realloc(old_cap,mData.capacity()); #endif - BaseType::insert(data); + LLOctreeNode::notifyAddition(data); return true; } @@ -616,6 +618,7 @@ class LLOctreeNode : public LLTreeNode } #endif + llassert(size[0] >= gOctreeMinSize*0.5f); //make the new kid child = new LLOctreeNode(center, size, this); addChild(child); @@ -623,10 +626,7 @@ class LLOctreeNode : public LLTreeNode child->insert(data); } } -// Singu note: now that we allow wider range in octree, discard them here -// if they fall out of range -#if 0 - else + else if (parent) { //it's not in here, give it to the root OCT_ERRS << "Octree insertion failed, starting over from root!" << LL_ENDL; @@ -639,12 +639,15 @@ class LLOctreeNode : public LLTreeNode parent = node->getOctParent(); } - if(node != this) - { - node->insert(data); - } + node->insert(data); + } + else + { + // It's not in here, and we are root. + // LLOctreeRoot::insert() should have expanded + // root by now, something is wrong + OCT_ERRS << "Octree insertion failed! Root expansion failed." << LL_ENDL; } -#endif return false; } @@ -696,7 +699,7 @@ class LLOctreeNode : public LLTreeNode (mData.size() > gOctreeReserveCapacity && mData.capacity() > gOctreeReserveCapacity + mData.size() - 1 - (mData.size() - gOctreeReserveCapacity - 1) % 4)) { //Shrink to lowest possible (reserve)+4*i size.. Say reserve is 5, here are [size,capacity] pairs. [10,13],[9,9],[8,9],[7,9],[6,9],[5,5],[4,5],[3,5],[2,5],[1,5],[0,5] - vector_shrink_to_fit(mData); + mData.shrink_to_fit(); } #ifdef LL_OCTREE_STATS if(old_cap != mData.capacity()) @@ -708,7 +711,7 @@ class LLOctreeNode : public LLTreeNode checkAlive(); } - bool remove(T* data) + bool remove(T* data) final override { OctreeGuard::checkGuarded(this); S32 i = data->getBinIndex(); @@ -849,10 +852,9 @@ class LLOctreeNode : public LLTreeNode if (!silent) { - for (U32 i = 0; i < this->getListenerCount(); i++) + for (auto& entry : this->mListeners) { - oct_listener* listener = getOctListener(i); - listener->handleChildAddition(this, child); + ((oct_listener*)entry.get())->handleChildAddition(this, child); } } } @@ -861,16 +863,17 @@ class LLOctreeNode : public LLTreeNode { OctreeGuard::checkGuarded(this); - for (U32 i = 0; i < this->getListenerCount(); i++) + oct_node* child = getChild(index); + + for (auto& entry : this->mListeners) { - oct_listener* listener = getOctListener(i); - listener->handleChildRemoval(this, getChild(index)); + ((oct_listener*)entry.get())->handleChildRemoval(this, child); } if (destroy) { - mChild[index]->destroy(); - delete mChild[index]; + child->destroy(); + delete child; } --mChildCount; @@ -1012,7 +1015,7 @@ class LLOctreeRoot : public LLOctreeNode } // LLOctreeRoot::insert - bool insert(T* data) + bool insert(T* data) final override { if (data == NULL) { @@ -1050,10 +1053,15 @@ class LLOctreeRoot : public LLOctreeNode { LLOctreeNode::insert(data); } - else + else if (node->isInside(data->getPositionGroup())) { node->insert(data); } + else + { + // calling node->insert(data) will return us to root + OCT_ERRS << "Failed to insert data at child node" << LL_ENDL; + } } else if (this->getChildCount() == 0) { @@ -1088,6 +1096,8 @@ class LLOctreeRoot : public LLOctreeNode this->setSize(size2); this->updateMinMax(); + llassert(size[0] >= gOctreeMinSize); + //copy our children to a new branch LLOctreeNode* newnode = new LLOctreeNode(center, size, this); diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h index 0cbf02c835..e1aa741f12 100644 --- a/indra/llmath/llplane.h +++ b/indra/llmath/llplane.h @@ -43,7 +43,7 @@ class LLPlane public: // Constructors - LLPlane() {}; // no default constructor + LLPlane() = default; // no default constructor LLPlane(const LLVector3 &p0, F32 d) { setVec(p0, d); } LLPlane(const LLVector3 &p0, const LLVector3 &n) { setVec(p0, n); } inline void setVec(const LLVector3 &p0, F32 d) { mV.set(p0[0], p0[1], p0[2], d); } @@ -104,6 +104,8 @@ class LLPlane LL_ALIGN_16(LLVector4a mV); } LL_ALIGN_POSTFIX(16); - - +#if !defined(LL_DEBUG) +static_assert(std::is_trivial::value, "LLPlane must be a trivial type"); +static_assert(std::is_standard_layout::value, "LLPlane must be a standard layout type"); +#endif #endif // LL_LLPLANE_H diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp index 699eaf2ab1..1529b25876 100644 --- a/indra/llmath/llquaternion.cpp +++ b/indra/llmath/llquaternion.cpp @@ -104,6 +104,11 @@ LLQuaternion::LLQuaternion(const LLVector3 &x_axis, normalize(); } +LLQuaternion::LLQuaternion(const LLSD &sd) +{ + setValue(sd); +} + // Quatizations void LLQuaternion::quantize16(F32 lower, F32 upper) { @@ -860,6 +865,26 @@ void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const } } +const LLQuaternion& LLQuaternion::setFromAzimuthAndAltitude(F32 azimuthRadians, F32 altitudeRadians) +{ + // euler angle inputs are complements of azimuth/altitude which are measured from zenith + F32 pitch = llclamp(F_PI_BY_TWO - altitudeRadians, 0.0f, F_PI_BY_TWO); + F32 yaw = llclamp(F_PI_BY_TWO - azimuthRadians, 0.0f, F_PI_BY_TWO); + setEulerAngles(0.0f, pitch, yaw); + return *this; +} + +void LLQuaternion::getAzimuthAndAltitude(F32 &azimuthRadians, F32 &altitudeRadians) +{ + F32 rick_roll; + F32 pitch; + F32 yaw; + getEulerAngles(&rick_roll, &pitch, &yaw); + // make these measured from zenith + altitudeRadians = llclamp(F_PI_BY_TWO - pitch, 0.0f, F_PI_BY_TWO); + azimuthRadians = llclamp(F_PI_BY_TWO - yaw, 0.0f, F_PI_BY_TWO); +} + // quaternion does not need to be normalized void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const { diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h index 349af05526..5cf7e20c83 100644 --- a/indra/llmath/llquaternion.h +++ b/indra/llmath/llquaternion.h @@ -28,6 +28,7 @@ #define LLQUATERNION_H #include +#include "llsd.h" #ifndef LLMATH_H //enforce specific include order to avoid tangling inline dependencies #error "Please include llmath.h first." @@ -63,6 +64,10 @@ class LLQuaternion LLQuaternion(const LLVector3 &x_axis, const LLVector3 &y_axis, const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis] + explicit LLQuaternion(const LLSD &sd); // Initializes Quaternion from LLSD array. + + LLSD getValue() const; + void setValue(const LLSD& sd); BOOL isIdentity() const; BOOL isNotIdentity() const; @@ -71,11 +76,15 @@ class LLQuaternion void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization void loadIdentity(); // Loads the quaternion that represents the identity rotation + bool isEqualEps(const LLQuaternion &quat, F32 epsilon) const; + bool isNotEqualEps(const LLQuaternion &quat, F32 epsilon) const; + const LLQuaternion& set(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normalize(x, y, z, w) const LLQuaternion& set(const LLQuaternion &quat); // Copies Quaternion const LLQuaternion& set(const F32 *q); // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW]) const LLQuaternion& set(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat) const LLQuaternion& set(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat) + const LLQuaternion& setFromAzimuthAndAltitude(F32 azimuth, F32 altitude); const LLQuaternion& setAngleAxis(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z) const LLQuaternion& setAngleAxis(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) @@ -97,6 +106,7 @@ class LLQuaternion void getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const; // returns rotation in radians about axis x,y,z void getAngleAxis(F32* angle, LLVector3 &vec) const; void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const; + void getAzimuthAndAltitude(F32 &azimuth, F32 &altitude); F32 normalize(); // Normalizes Quaternion and returns magnitude F32 normQuat(); // deprecated @@ -163,10 +173,30 @@ class LLQuaternion //static U32 mMultCount; }; +inline LLSD LLQuaternion::getValue() const +{ + LLSD ret; + ret[0] = mQ[0]; + ret[1] = mQ[1]; + ret[2] = mQ[2]; + ret[3] = mQ[3]; + return ret; +} + +inline void LLQuaternion::setValue(const LLSD& sd) +{ + mQ[0] = sd[0].asReal(); + mQ[1] = sd[1].asReal(); + mQ[2] = sd[2].asReal(); + mQ[3] = sd[3].asReal(); +} + +static_assert(std::is_trivially_copyable::value, "LLQuaternion must be a trivially copyable type"); + // checker inline BOOL LLQuaternion::isFinite() const { - return (llfinite(mQ[VX]) && llfinite(mQ[VY]) && llfinite(mQ[VZ]) && llfinite(mQ[VS])); + return (std::isfinite(mQ[VX]) && std::isfinite(mQ[VY]) && std::isfinite(mQ[VZ]) && std::isfinite(mQ[VS])); } inline BOOL LLQuaternion::isIdentity() const @@ -239,6 +269,21 @@ inline void LLQuaternion::loadIdentity() mQ[VW] = 1.0f; } +inline bool LLQuaternion::isEqualEps(const LLQuaternion &quat, F32 epsilon) const +{ + return ( fabs(mQ[VX] - quat.mQ[VX]) < epsilon + && fabs(mQ[VY] - quat.mQ[VY]) < epsilon + && fabs(mQ[VZ] - quat.mQ[VZ]) < epsilon + && fabs(mQ[VS] - quat.mQ[VS]) < epsilon ); +} + +inline bool LLQuaternion::isNotEqualEps(const LLQuaternion &quat, F32 epsilon) const +{ + return ( fabs(mQ[VX] - quat.mQ[VX]) > epsilon + || fabs(mQ[VY] - quat.mQ[VY]) > epsilon + || fabs(mQ[VZ] - quat.mQ[VZ]) > epsilon + || fabs(mQ[VS] - quat.mQ[VS]) > epsilon ); +} inline const LLQuaternion& LLQuaternion::set(F32 x, F32 y, F32 z, F32 w) { diff --git a/indra/llmath/llquaternion2.h b/indra/llmath/llquaternion2.h index 6cfe91a024..75b54be0eb 100644 --- a/indra/llmath/llquaternion2.h +++ b/indra/llmath/llquaternion2.h @@ -50,7 +50,7 @@ class LLQuaternion2 ////////////////////////// // Ctor - LLQuaternion2() {} + LLQuaternion2() = default; // Ctor from LLQuaternion explicit LLQuaternion2( const class LLQuaternion& quat ); @@ -105,4 +105,9 @@ class LLQuaternion2 } LL_ALIGN_POSTFIX(16); +#if !defined(LL_DEBUG) +static_assert(std::is_trivial::value, "LLQuaternion2 must be a trivial type"); +static_assert(std::is_standard_layout::value, "LLQuaternion2 must be a standard layout type"); +#endif + #endif diff --git a/indra/llmath/llrigginginfo.cpp b/indra/llmath/llrigginginfo.cpp new file mode 100644 index 0000000000..0de07950c1 --- /dev/null +++ b/indra/llmath/llrigginginfo.cpp @@ -0,0 +1,159 @@ +/** +* @file llrigginginfo.cpp +* @brief Functions for tracking rigged box extents +* +* $LicenseInfo:firstyear=2018&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2018, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llmath.h" +#include "llrigginginfo.h" + +//----------------------------------------------------------------------------- +// LLJointRiggingInfo +//----------------------------------------------------------------------------- +LLJointRiggingInfo::LLJointRiggingInfo() +{ + mRiggedExtents[0].clear(); + mRiggedExtents[1].clear(); + mIsRiggedTo = false; +} + +bool LLJointRiggingInfo::isRiggedTo() const +{ + return mIsRiggedTo; +} + +void LLJointRiggingInfo::setIsRiggedTo(bool val) +{ + mIsRiggedTo = val; +} + +LLVector4a *LLJointRiggingInfo::getRiggedExtents() +{ + return mRiggedExtents; +} + +const LLVector4a *LLJointRiggingInfo::getRiggedExtents() const +{ + return mRiggedExtents; +} + +// Combine two rigging info states. +// - isRiggedTo if either of the source infos are rigged to +// - box is union of the two sources +void LLJointRiggingInfo::merge(const LLJointRiggingInfo& other) +{ + if (other.mIsRiggedTo) + { + if (mIsRiggedTo) + { + // Combine existing boxes + update_min_max(mRiggedExtents[0], mRiggedExtents[1], other.mRiggedExtents[0]); + update_min_max(mRiggedExtents[0], mRiggedExtents[1], other.mRiggedExtents[1]); + } + else + { + // Initialize box + mIsRiggedTo = true; + mRiggedExtents[0] = other.mRiggedExtents[0]; + mRiggedExtents[1] = other.mRiggedExtents[1]; + } + } +} + +LLJointRiggingInfoTab::LLJointRiggingInfoTab(): + mRigInfoPtr(NULL), + mSize(0), + mNeedsUpdate(true) +{ +} + +LLJointRiggingInfoTab::~LLJointRiggingInfoTab() +{ + clear(); +} + +// This doesn't preserve data if the size changes. In practice +// this doesn't matter because the size is always either +// LL_CHARACTER_MAX_ANIMATED_JOINTS or 0. +void LLJointRiggingInfoTab::resize(S32 size) +{ + if (size != mSize) + { + clear(); + if (size > 0) + { + mRigInfoPtr = new LLJointRiggingInfo[size]; + mSize = size; + } + } +} + +void LLJointRiggingInfoTab::clear() +{ + if (mRigInfoPtr) + { + delete[](mRigInfoPtr); + mRigInfoPtr = NULL; + mSize = 0; + } +} + +void showDetails(const LLJointRiggingInfoTab& src, const std::string& str) +{ + S32 count_rigged = 0; + S32 count_box = 0; + LLVector4a zero_vec; + zero_vec.clear(); + for (S32 i=0; i size()) + { + resize(src.size()); + } + S32 min_size = llmin(size(), src.size()); + for (S32 i=0; i to avoid alignment issues. +class LLJointRiggingInfoTab +{ +public: + LLJointRiggingInfoTab(); + ~LLJointRiggingInfoTab(); + void resize(S32 size); + void clear(); + S32 size() const { return mSize; } + void merge(const LLJointRiggingInfoTab& src); + LLJointRiggingInfo& operator[](S32 i) { return mRigInfoPtr[i]; } + const LLJointRiggingInfo& operator[](S32 i) const { return mRigInfoPtr[i]; }; + bool needsUpdate() { return mNeedsUpdate; } + void setNeedsUpdate(bool val) { mNeedsUpdate = val; } +private: + // Not implemented + LLJointRiggingInfoTab& operator=(const LLJointRiggingInfoTab& src); + LLJointRiggingInfoTab(const LLJointRiggingInfoTab& src); + + LLJointRiggingInfo *mRigInfoPtr; + S32 mSize; + bool mNeedsUpdate; +}; + +#endif diff --git a/indra/llmath/llsimdtypes.h b/indra/llmath/llsimdtypes.h index bd991d0e71..72f65a9d87 100644 --- a/indra/llmath/llsimdtypes.h +++ b/indra/llmath/llsimdtypes.h @@ -50,7 +50,7 @@ __forceinline const __m128i _mm_castps_si128( const __m128 a ) { return reinterp class LLBool32 { public: - inline LLBool32() {} + inline LLBool32() = default; inline LLBool32(int rhs) : m_bool(rhs) {} inline LLBool32(unsigned int rhs) : m_bool(rhs) {} inline LLBool32(bool rhs) { m_bool = static_cast(rhs); } @@ -70,7 +70,7 @@ class LLBool32 class LLSimdScalar { public: - inline LLSimdScalar() {} + inline LLSimdScalar() = default; inline LLSimdScalar(LLQuad q) { mQ = q; @@ -120,5 +120,9 @@ class LLSimdScalar private: LLQuad mQ; }; +static_assert(std::is_trivial::value, "LLBool32 must be a trivial type"); +static_assert(std::is_standard_layout::value, "LLBool32 must be a standard layout type"); +static_assert(std::is_trivial::value, "LLSimdScalar must be a trivial type"); +static_assert(std::is_standard_layout::value, "LLSimdScalar must be a standard layout type"); #endif //LL_SIMD_TYPES_H diff --git a/indra/llmath/lltreenode.h b/indra/llmath/lltreenode.h index 36e6f106ad..77b36a290b 100644 --- a/indra/llmath/lltreenode.h +++ b/indra/llmath/lltreenode.h @@ -44,7 +44,6 @@ class LLTreeListener: public LLRefCount virtual void handleInsertion(const LLTreeNode* node, T* data) = 0; virtual void handleRemoval(const LLTreeNode* node, T* data) = 0; virtual void handleDestruction(const LLTreeNode* node) = 0; - virtual void handleStateChange(const LLTreeNode* node) = 0; }; template @@ -53,11 +52,15 @@ class LLTreeNode public: virtual ~LLTreeNode(); - virtual bool insert(T* data); - virtual bool remove(T* data); - virtual void notifyRemoval(T* data); - virtual U32 getListenerCount() { return mListeners.size(); } - virtual LLTreeListener* getListener(U32 index) const + virtual bool insert(T* data) = 0; + virtual bool remove(T* data) = 0; + bool notifyAddition(T* data); + void notifyRemoval(T* data); + U32 getListenerCount() const + { + return mListeners.size(); + } + LLTreeListener* getListener(U32 index) const { if(index < mListeners.size()) { @@ -65,7 +68,10 @@ class LLTreeNode } return NULL; } - virtual void addListener(LLTreeListener* listener) { mListeners.push_back(listener); } + void addListener(LLTreeListener* listener) + { + mListeners.push_back(listener); + } protected: void destroyListeners() @@ -97,7 +103,7 @@ LLTreeNode::~LLTreeNode() }; template -bool LLTreeNode::insert(T* data) +bool LLTreeNode::notifyAddition(T* data) { for (U32 i = 0; i < mListeners.size(); i++) { @@ -106,12 +112,6 @@ bool LLTreeNode::insert(T* data) return true; }; -template -bool LLTreeNode::remove(T* data) -{ - return true; -}; - template void LLTreeNode::notifyRemoval(T* data) { diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h index 2e958b308d..b966718246 100644 --- a/indra/llmath/llvector4a.h +++ b/indra/llmath/llvector4a.h @@ -93,15 +93,19 @@ class LLVector4a //////////////////////////////////// LLVector4a() +#if !defined(LL_DEBUG) + = default; +#else { //DO NOT INITIALIZE -- The overhead is completely unnecessary ll_assert_aligned(this,16); } - +#endif + LLVector4a(F32 x, F32 y, F32 z, F32 w = 0.f) { - set(x,y,z,w); + set(x, y, z, w); } - + LLVector4a(F32 x) { splat(x); @@ -320,9 +324,13 @@ class LLVector4a //////////////////////////////////// // Do NOT add aditional operators without consulting someone with SSE experience - inline const LLVector4a& operator= ( const LLVector4a& rhs ); + //inline const LLVector4a& operator= ( const LLVector4a& rhs ); + //{ + // mQ = rhs.mQ; + // return *this; + //} - inline const LLVector4a& operator= ( const LLQuad& rhs ); + inline const LLVector4a& operator= (const LLQuad& rhs); inline operator LLQuad() const; @@ -336,4 +344,14 @@ inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p max.setMax(max, p); } +inline std::ostream& operator<<(std::ostream& s, const LLVector4a& v) +{ + s << "(" << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << ")"; + return s; +} + +#if !defined(LL_DEBUG) +static_assert(std::is_trivial::value, "LLVector4a must be a be a trivial type"); +static_assert(std::is_standard_layout::value, "LLVector4a must be a standard layout type"); +#endif #endif diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl index c3499d23d5..40d67c86b2 100644 --- a/indra/llmath/llvector4a.inl +++ b/indra/llmath/llvector4a.inl @@ -605,13 +605,7 @@ inline bool LLVector4a::equals3(const LLVector4a& rhs, F32 tolerance ) const //////////////////////////////////// // Do NOT add aditional operators without consulting someone with SSE experience -inline const LLVector4a& LLVector4a::operator= ( const LLVector4a& rhs ) -{ - mQ = rhs.mQ; - return *this; -} - -inline const LLVector4a& LLVector4a::operator= ( const LLQuad& rhs ) +inline const LLVector4a& LLVector4a::operator= (const LLQuad& rhs) { mQ = rhs; return *this; diff --git a/indra/llmath/llvector4logical.h b/indra/llmath/llvector4logical.h index 5e2cc413b3..46b92a7b32 100644 --- a/indra/llmath/llvector4logical.h +++ b/indra/llmath/llvector4logical.h @@ -61,7 +61,7 @@ class LLVector4Logical }; // Empty default ctor - LLVector4Logical() {} + LLVector4Logical() = default; LLVector4Logical( const LLQuad& quad ) { @@ -122,5 +122,7 @@ class LLVector4Logical LLQuad mQ; }; +static_assert(std::is_trivial::value, "LLVector4Logical must be a trivial type"); +static_assert(std::is_standard_layout::value, "LLVector4Logical must be a standard layout type"); #endif //LL_VECTOR4ALOGICAL_H diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index c38075610e..a974390443 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -167,8 +167,8 @@ void calc_tangent_from_triangle( float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero - llassert(llfinite(r)); - llassert(!llisnan(r)); + llassert(std::isfinite(r)); + llassert(!std::isnan(r)); LLVector4a sdir( (t2 * x1 - t1 * x2) * r, @@ -517,8 +517,6 @@ S32 LLProfile::getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 of t += t_step; } - t_fraction = (end - (t - t_step))*sides; - // Find the fraction that we need to add to the end point. t_fraction = (end - (t - t_step))*sides; if (t_fraction > 0.0001f) @@ -546,7 +544,7 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3 { // Generate an n-sided "circular" path. // 0 is (1,0), and we go counter-clockwise along a circular path from there. - const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; + static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; F32 scale = 0.5f; F32 t, t_step, t_first, t_fraction, ang, ang_step; LLVector4a pt1,pt2; @@ -559,7 +557,7 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3 // Scale to have size "match" scale. Compensates to get object to generally fill bounding box. - S32 total_sides = ll_round(sides / ang_scale); // Total number of sides all around + S32 total_sides = ll_pos_round(sides / ang_scale); // Total number of sides all around if (total_sides < 8) { @@ -613,8 +611,6 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3 ang += ang_step; } - t_fraction = (end - (t - t_step))*sides; - // pt1 is the first point on the fractional face // pt2 is the end point on the fractional face pt2.set(cos(ang)*scale,sin(ang)*scale,t); @@ -1305,7 +1301,7 @@ S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) { // Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane. - const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; + static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; F32 revolutions = params.getRevolutions(); F32 skew = params.getSkew(); @@ -1603,6 +1599,7 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, if (is_sculpted) sides = llmax(sculpt_size, 1); + if (0 < sides) genNGon(params, sides); } break; @@ -2085,6 +2082,7 @@ void LLVolume::resizePath(S32 length) { mPathp->resizePath(length); mVolumeFaces.clear(); + setDirty(); } void LLVolume::regen() @@ -2142,19 +2140,22 @@ BOOL LLVolume::generate() F32 profile_detail = mDetail; F32 path_detail = mDetail; - - U8 path_type = mParams.getPathParams().getCurveType(); - U8 profile_type = mParams.getProfileParams().getCurveType(); - - if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) - { //cylinders don't care about Z-Axis - mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); - } - else if (path_type == LL_PCODE_PATH_CIRCLE) - { - mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); + + if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) + { + U8 path_type = mParams.getPathParams().getCurveType(); + U8 profile_type = mParams.getProfileParams().getCurveType(); + if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) + { + //cylinders don't care about Z-Axis + mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); + } + else if (path_type == LL_PCODE_PATH_CIRCLE) + { + mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); + } } - + BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split); BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); @@ -2194,6 +2195,12 @@ BOOL LLVolume::generate() LLVector4a* end_profile = profile+sizeT; LLVector4a offset = mPathp->mPath[s].mPos; + if (!offset.isFinite3()) + { // MAINT-5660; don't know why this happens, does not affect Release builds + LL_WARNS() << "LLVolume using path with non-finite points. Resetting them to 0,0,0" << LL_ENDL; + offset.clear(); + } + LLVector4a tmp; // Run along the profile. @@ -2201,7 +2208,6 @@ BOOL LLVolume::generate() { rot_mat.rotate(*profile++, tmp); dst->setAdd(tmp,offset); - llassert(dst->isFinite3()); ++dst; } } @@ -2532,14 +2538,18 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) U32 cur_influence = 0; LLVector4 wght(0,0,0,0); + U32 joints[4] = {0,0,0,0}; + LLVector4 joints_with_weights(0,0,0,0); while (joint != END_INFLUENCES && idx < weights.size()) { U16 influence = weights[idx++]; influence |= ((U16) weights[idx++] << 8); - F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f); - wght.mV[cur_influence++] = (F32) joint + w; + F32 w = llclamp((F32) influence / 65535.f, 0.001f, 0.999f); + wght.mV[cur_influence] = w; + joints[cur_influence] = joint; + cur_influence++; if (cur_influence >= 4) { @@ -2550,8 +2560,20 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) joint = weights[idx++]; } } - - face.mWeights[cur_vertex].loadua(wght.mV); + F32 wsum = wght.mV[VX] + wght.mV[VY] + wght.mV[VZ] + wght.mV[VW]; + if (wsum <= 0.f) + { + wght = LLVector4(0.999f,0.f,0.f,0.f); + } + for (U32 k=0; k<4; k++) + { + F32 f_combined = (F32) joints[k] + wght[k]; + joints_with_weights[k] = f_combined; + // Any weights we added above should wind up non-zero and applied to a specific bone. + // A failure here would indicate a floating point precision error in the math. + llassert((k >= cur_influence) || (f_combined - S32(f_combined) > 0.0f)); + } + face.mWeights[cur_vertex].loadua(joints_with_weights.mV); cur_vertex++; } @@ -2679,6 +2701,17 @@ void LLVolume::setMeshAssetLoaded(BOOL loaded) mIsMeshAssetLoaded = loaded; } +void LLVolume::copyFacesTo(std::vector &faces) const +{ + faces = mVolumeFaces; +} + +void LLVolume::copyFacesFrom(const std::vector &faces) +{ + mVolumeFaces = faces; + mSculptLevel = 0; +} + void LLVolume::copyVolumeFaces(const LLVolume* volume) { mVolumeFaces = volume->mVolumeFaces; @@ -2883,15 +2916,41 @@ F32 LLVolume::sculptGetSurfaceArea() return area; } -// create placeholder shape -void LLVolume::sculptGeneratePlaceholder() +// create empty placeholder shape +void LLVolume::sculptGenerateEmptyPlaceholder() { S32 sizeS = mPathp->mPath.size(); S32 sizeT = mProfilep->mProfile.size(); - + + S32 line = 0; + + for (S32 s = 0; s < sizeS; s++) + { + for (S32 t = 0; t < sizeT; t++) + { + S32 i = t + line; + LLVector4a& pt = mMesh[i]; + + F32* p = pt.getF32ptr(); + + p[0] = 0; + p[1] = 0; + p[2] = 0; + + llassert(pt.isFinite3()); + } + line += sizeT; + } +} + +// create sphere placeholder shape +void LLVolume::sculptGenerateSpherePlaceholder() +{ + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); + S32 line = 0; - // for now, this is a sphere. for (S32 s = 0; s < sizeS; s++) { for (S32 t = 0; t < sizeT; t++) @@ -3100,7 +3159,7 @@ bool sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32 } // sculpt replaces generate() for sculpted surfaces -void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level) +void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder) { U8 sculpt_type = mParams.getSculptType(); @@ -3164,13 +3223,22 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA) { data_is_empty = TRUE; + visible_placeholder = true; } } } if (data_is_empty) { - sculptGeneratePlaceholder(); + if (visible_placeholder) + { + // Object should be visible since there will be nothing else to display + sculptGenerateSpherePlaceholder(); + } + else + { + sculptGenerateEmptyPlaceholder(); + } } @@ -3700,10 +3768,46 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, continue; } - if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) { + if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) + { + LLVector4a* v = (LLVector4a*)face.mPositions; + LLVector4a* n = (LLVector4a*)face.mNormals; + + for (U32 j = 0; j < (U32)face.mNumIndices / 3; j++) + { + for (S32 k = 0; k < 3; k++) + { + S32 index = face.mEdge[j * 3 + k]; + + if (index == -1) + { + // silhouette edge, currently only cubes, so no other conditions + + S32 v1 = face.mIndices[j * 3 + k]; + S32 v2 = face.mIndices[j * 3 + ((k + 1) % 3)]; + + LLVector4a t; + mat.affineTransform(v[v1], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v1], t); + + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + + mat.affineTransform(v[v2], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v2], t); + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + } + } + } } - else { + else + { //============================================== //DEBUG draw edge map instead of silhouette edge @@ -4577,6 +4681,7 @@ LLVolumeFace::LLVolumeFace() : mTexCoords(NULL), mIndices(NULL), mWeights(NULL), + mWeightsScrubbed(FALSE), mOctree(NULL), mOptimized(FALSE) { @@ -4602,6 +4707,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) mTexCoords(NULL), mIndices(NULL), mWeights(NULL), + mWeightsScrubbed(FALSE), mOctree(NULL), mOptimized(FALSE) { @@ -4645,7 +4751,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) if (src.mNormals) { - LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); + LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); } if(src.mTexCoords) @@ -4653,27 +4759,18 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); } + allocateTangents(src.mTangents ? src.mNumVertices : 0); if (src.mTangents) { - allocateTangents(src.mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mTangents, (F32*) src.mTangents, vert_size); - } - else - { - ll_aligned_free_16(mTangents); - mTangents = NULL; + LLVector4a::memcpyNonAliased16((F32*)mTangents, (F32*)src.mTangents, vert_size); } + allocateWeights(src.mWeights ? src.mNumVertices : 0); if (src.mWeights) { - allocateWeights(src.mNumVertices); LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size); } - else - { - ll_aligned_free_16(mWeights); - mWeights = NULL; - } + mWeightsScrubbed = src.mWeightsScrubbed; } if (mNumIndices) @@ -4693,25 +4790,17 @@ LLVolumeFace::~LLVolumeFace() { ll_aligned_free_16(mExtents); mExtents = NULL; + mCenter = NULL; freeData(); } void LLVolumeFace::freeData() { - ll_aligned_free(mPositions); - mPositions = NULL; - - //normals and texture coordinates are part of the same buffer as mPositions, do not free them separately - mNormals = NULL; - mTexCoords = NULL; - - ll_aligned_free_16(mIndices); - mIndices = NULL; - ll_aligned_free_16(mTangents); - mTangents = NULL; - ll_aligned_free_16(mWeights); - mWeights = NULL; + allocateVertices(0); + allocateTangents(0); + allocateWeights(0); + allocateIndices(0); delete mOctree; mOctree = NULL; @@ -4871,7 +4960,7 @@ void LLVolumeFace::optimize(F32 angle_cutoff) // if (new_face.mNumVertices <= mNumVertices) { - llassert(new_face.mNumIndices == mNumIndices); + llassert(new_face.mNumIndices == mNumIndices); swapData(new_face); } } @@ -5146,12 +5235,12 @@ class LLVCacheLRU void LLVolumeFace::cacheOptimize() { //optimize for vertex cache according to Forsyth method: // http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html - + llassert(!mOptimized); mOptimized = TRUE; LLVCacheLRU cache; - + if (mNumVertices < 3) { //nothing to do return; @@ -5163,17 +5252,17 @@ void LLVolumeFace::cacheOptimize() //mapping of triangles do vertices std::vector triangle_data; - triangle_data.resize(mNumIndices/3); + triangle_data.resize(mNumIndices / 3); vertex_data.resize(mNumVertices); for (U32 i = 0; i < (U32)mNumIndices; i++) { //populate vertex data and triangle data arrays U16 idx = mIndices[i]; - U32 tri_idx = i/3; + U32 tri_idx = i / 3; vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx])); vertex_data[idx].mIdx = idx; - triangle_data[tri_idx].mVertex[i%3] = &(vertex_data[idx]); + triangle_data[tri_idx].mVertex[i % 3] = &(vertex_data[idx]); } /*F32 pre_acmr = 1.f; @@ -5222,7 +5311,7 @@ void LLVolumeFace::cacheOptimize() tri->complete(); U32 breaks = 0; - for (U32 i = 1; i < (U32)mNumIndices/3; ++i) + for (U32 i = 1; i < (U32)mNumIndices / 3; ++i) { cache.updateScores(); tri = cache.mBestTriangle; @@ -5237,8 +5326,8 @@ void LLVolumeFace::cacheOptimize() break; } } - } - + } + cache.addTriangle(tri); new_indices.push_back(tri->mVertex[0]->mIdx); new_indices.push_back(tri->mVertex[1]->mIdx); @@ -5264,29 +5353,36 @@ void LLVolumeFace::cacheOptimize() { test_cache.addVertex(&vertex_data[mIndices[i]]); } - + post_acmr = (F32) test_cache.mMisses/(mNumIndices/3); }*/ //optimize for pre-TnL cache - + //allocate space for new buffer S32 num_verts = mNumVertices; - S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; - LLVector4a* pos = (LLVector4a*) ll_aligned_malloc(sizeof(LLVector4a)*2*num_verts+size, 64); - LLVector4a* norm = pos + num_verts; - LLVector2* tc = (LLVector2*) (norm + num_verts); - LLVector4a* wght = NULL; - if (mWeights) + LLVector4a* old_pos = mPositions; + LLVector4a* old_norm = old_pos + num_verts; + LLVector2* old_tc = (LLVector2*)(old_norm + num_verts); + mPositions = NULL; + if (old_pos) + { + allocateVertices(num_verts); + } + + LLVector4a* old_wght = mWeights; + mWeights = NULL; + if (old_wght) { - wght = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + allocateWeights(num_verts); } - LLVector4a* binorm = NULL; - if (mTangents) + LLVector4a* old_binorm = mTangents; + mTangents = NULL; + if (old_binorm) { - binorm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + allocateTangents(num_verts); } //allocate mapping of old indices to new indices @@ -5302,16 +5398,16 @@ void LLVolumeFace::cacheOptimize() new_idx[idx] = cur_idx; //copy vertex data - pos[cur_idx] = mPositions[idx]; - norm[cur_idx] = mNormals[idx]; - tc[cur_idx] = mTexCoords[idx]; + mPositions[cur_idx] = old_pos[idx]; + mNormals[cur_idx] = old_norm[idx]; + mTexCoords[cur_idx] = old_tc[idx]; if (mWeights) { - wght[cur_idx] = mWeights[idx]; + mWeights[cur_idx] = old_wght[idx]; } if (mTangents) { - binorm[cur_idx] = mTangents[idx]; + mTangents[cur_idx] = old_binorm[idx]; } cur_idx++; @@ -5323,16 +5419,11 @@ void LLVolumeFace::cacheOptimize() mIndices[i] = new_idx[mIndices[i]]; } - ll_aligned_free(mPositions); - // DO NOT free mNormals and mTexCoords as they are part of mPositions buffer - ll_aligned_free_16(mWeights); - ll_aligned_free_16(mTangents); + ll_aligned_free<64>(old_pos); + ll_aligned_free_16(old_binorm); + ll_aligned_free_16(old_wght); - mPositions = pos; - mNormals = norm; - mTexCoords = tc; - mWeights = wght; - mTangents = binorm; + // DO NOT free mNormals and mTexCoords as they are part of mPositions buffer //std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks); //LL_INFOS() << result << LL_ENDL; @@ -5547,10 +5638,17 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) if (!partial_build) { resizeIndices(grid_size*grid_size*6); + if (!volume->isMeshAssetLoaded()) + { + mEdge.resize(grid_size*grid_size * 6); + } U16* out = mIndices; S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; + + int cur_edge = 0; + for(S32 gx = 0;gx=0;i--) { *out++ = ((gy*(grid_size+1))+gx+idxs[i]); - } + } + + S32 edge_value = grid_size * 2 * gy + gx * 2; + + if (gx > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; // Mark face to higlight it + } + + if (gy < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; + + if (gx < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + if (gy > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; } else { @@ -5569,6 +5709,48 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) { *out++ = ((gy*(grid_size+1))+gx+idxs[i]); } + + S32 edge_value = grid_size * 2 * gy + gx * 2; + + if (gy > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + if (gx < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; + + if (gy < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + if (gx > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; } } } @@ -5986,16 +6168,19 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) } else { //degenerate, make up a value - normal.set(0,0,1); + if(normal.getF32ptr()[2] >= 0) + normal.set(0.f,0.f,1.f); + else + normal.set(0.f,0.f,-1.f); } - llassert(llfinite(normal.getF32ptr()[0])); - llassert(llfinite(normal.getF32ptr()[1])); - llassert(llfinite(normal.getF32ptr()[2])); + llassert(std::isfinite(normal.getF32ptr()[0])); + llassert(std::isfinite(normal.getF32ptr()[1])); + llassert(std::isfinite(normal.getF32ptr()[2])); - llassert(!llisnan(normal.getF32ptr()[0])); - llassert(!llisnan(normal.getF32ptr()[1])); - llassert(!llisnan(normal.getF32ptr()[2])); + llassert(!std::isnan(normal.getF32ptr()[0])); + llassert(!std::isnan(normal.getF32ptr()[1])); + llassert(!std::isnan(normal.getF32ptr()[2])); for (S32 i = 0; i < num_vertices; i++) { @@ -6041,32 +6226,12 @@ void LLVolumeFace::createTangents() void LLVolumeFace::resizeVertices(S32 num_verts) { - ll_aligned_free(mPositions); - //DO NOT free mNormals and mTexCoords as they are part of mPositions buffer - ll_aligned_free_16(mTangents); - - mTangents = NULL; - - if (num_verts) - { - //pad texture coordinate block end to allow for QWORD reads - S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; - - mPositions = (LLVector4a*) ll_aligned_malloc(sizeof(LLVector4a)*2*num_verts+size, 64); - mNormals = mPositions+num_verts; - mTexCoords = (LLVector2*) (mNormals+num_verts); - - ll_assert_aligned(mPositions, 64); - } - else - { - mPositions = NULL; - mNormals = NULL; - mTexCoords = NULL; - } - + allocateTangents(0); + allocateVertices(num_verts); mNumVertices = num_verts; - mNumAllocatedVertices = num_verts; + + // Force update + mJointRiggingInfoTab.clear(); } void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv) @@ -6081,48 +6246,10 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con if (new_verts > mNumAllocatedVertices) { //double buffer size on expansion - new_verts *= 2; - - S32 new_tc_size = ((new_verts*8)+0xF) & ~0xF; - S32 old_tc_size = ((mNumVertices*8)+0xF) & ~0xF; - - S32 old_vsize = mNumVertices*16; - - S32 new_size = new_verts*16*2+new_tc_size; - - LLVector4a* old_buf = mPositions; - - mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64); - mNormals = mPositions+new_verts; - mTexCoords = (LLVector2*) (mNormals+new_verts); - - // - llassert(mNumVertices || (old_buf == NULL && mTangents == NULL)); - if (mNumVertices) // It turns out this can be zero, in which case old_buf (and mTangents) is NULL. - { - // - - //positions - LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize); - - //normals - LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize); - - //tex coords - LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tc_size); - - ll_aligned_free(old_buf); - - // - } - // + allocateVertices(new_verts * 2, true); //just clear tangents - ll_aligned_free_16(mTangents); - mTangents = NULL; - - mNumAllocatedVertices = new_verts; - + allocateTangents(0); } mPositions[mNumVertices] = pos; @@ -6135,47 +6262,103 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con void LLVolumeFace::allocateTangents(S32 num_verts) { ll_aligned_free_16(mTangents); - mTangents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + mTangents = NULL; + if (num_verts) + { + mTangents = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + } } void LLVolumeFace::allocateWeights(S32 num_verts) { ll_aligned_free_16(mWeights); - mWeights = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + mWeights = NULL; + if (num_verts) + { + mWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + } } -void LLVolumeFace::resizeIndices(S32 num_indices) +void LLVolumeFace::allocateVertices(S32 num_verts, bool copy) { - ll_aligned_free_16(mIndices); - - if (num_indices) + if (!copy || !num_verts) { - //pad index block end to allow for QWORD reads - S32 size = ((num_indices*sizeof(U16)) + 0xF) & ~0xF; - - mIndices = (U16*) ll_aligned_malloc_16(size); + ll_aligned_free<64>(mPositions); + mPositions = NULL; + mNormals = NULL; + mTexCoords = NULL; } - else + + if (num_verts) + { + const U32 new_vsize = num_verts * sizeof(LLVector4a); + const U32 new_nsize = new_vsize; + const U32 new_tcsize = (num_verts * sizeof(LLVector2) + 0xF) & ~0xF; + const U32 new_size = new_vsize + new_nsize + new_tcsize; + + //allocate new buffer space + LLVector4a* old_buf = mPositions; + mPositions = (LLVector4a*)ll_aligned_malloc<64>(new_size); + mNormals = mPositions + num_verts; + mTexCoords = (LLVector2*)(mNormals + num_verts); + + if (copy && old_buf) + { + U32 verts_to_copy = std::min(mNumVertices, num_verts); + if (verts_to_copy) + { + const U32 old_vsize = verts_to_copy * sizeof(LLVector4a); + const U32 old_nsize = old_vsize; + const U32 old_tcsize = (verts_to_copy * sizeof(LLVector2) + 0xF) & ~0xF; + + LLVector4a::memcpyNonAliased16((F32*)mPositions, (F32*)old_buf, old_vsize); + LLVector4a::memcpyNonAliased16((F32*)mNormals, (F32*)(old_buf + mNumVertices), old_nsize); + LLVector4a::memcpyNonAliased16((F32*)mTexCoords, (F32*)(old_buf + mNumVertices * 2), old_tcsize); + } + ll_aligned_free<64>(old_buf); + } + } + mNumAllocatedVertices = num_verts; +} + +void LLVolumeFace::allocateIndices(S32 num_indices, bool copy) +{ + if (num_indices == mNumIndices) { - mIndices = NULL; + return; + } + + S32 new_size = ((num_indices * sizeof(U16)) + 0xF) & ~0xF; + if (copy && num_indices && mIndices && mNumIndices) + { +#if !LL_USE_TCMALLOC + S32 old_size = ((mNumIndices * sizeof(U16)) + 0xF) & ~0xF; +#endif + + mIndices = (U16*)ll_aligned_realloc_16(mIndices, new_size, old_size); + + mNumIndices = num_indices; + return; + } + ll_aligned_free_16(mIndices); + mIndices = NULL; + if (num_indices) + { + mIndices = (U16*)ll_aligned_malloc_16(new_size); } mNumIndices = num_indices; } +void LLVolumeFace::resizeIndices(S32 num_indices) +{ + allocateIndices(num_indices); +} void LLVolumeFace::pushIndex(const U16& idx) { - S32 new_count = mNumIndices + 1; - S32 new_size = ((new_count*2)+0xF) & ~0xF; + allocateIndices(mNumIndices + 1, true); - S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; - if (new_size != old_size) - { - mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size, old_size); - ll_assert_aligned(mIndices,16); - } - - mIndices[mNumIndices++] = idx; + mIndices[mNumIndices-1] = idx; } void LLVolumeFace::fillFromLegacyData(std::vector& v, std::vector& idx) @@ -6196,96 +6379,6 @@ void LLVolumeFace::fillFromLegacyData(std::vector& v, } } -void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMatrix4& norm_mat_in) -{ - U16 offset = mNumVertices; - - S32 new_count = face.mNumVertices + mNumVertices; - - if (new_count > 65536) - { - LL_ERRS() << "Cannot append face -- 16-bit overflow will occur." << LL_ENDL; - } - - if (face.mNumVertices == 0) - { - LL_ERRS() << "Cannot append empty face." << LL_ENDL; - } - - U32 old_vsize = mNumVertices*16; - U32 new_vsize = new_count * 16; - U32 old_tcsize = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF; - U32 new_tcsize = (new_count*sizeof(LLVector2)+0xF) & ~0xF; - U32 new_size = new_vsize * 2 + new_tcsize; - - //allocate new buffer space - LLVector4a* old_buf = mPositions; - mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64); - mNormals = mPositions + new_count; - mTexCoords = (LLVector2*) (mNormals+new_count); - - mNumAllocatedVertices = new_count; - - LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize); - LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize); - LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tcsize); - - mNumVertices = new_count; - - //get destination address of appended face - LLVector4a* dst_pos = mPositions+offset; - LLVector2* dst_tc = mTexCoords+offset; - LLVector4a* dst_norm = mNormals+offset; - - //get source addresses of appended face - const LLVector4a* src_pos = face.mPositions; - const LLVector2* src_tc = face.mTexCoords; - const LLVector4a* src_norm = face.mNormals; - - //load aligned matrices - LLMatrix4a mat, norm_mat; - mat.loadu(mat_in); - norm_mat.loadu(norm_mat_in); - - for (U32 i = 0; i < (U32)face.mNumVertices; ++i) - { - //transform appended face position and store - mat.affineTransform(src_pos[i], dst_pos[i]); - - //transform appended face normal and store - norm_mat.rotate(src_norm[i], dst_norm[i]); - dst_norm[i].normalize3fast(); - - //copy appended face texture coordinate - dst_tc[i] = src_tc[i]; - - if (offset == 0 && i == 0) - { //initialize bounding box - mExtents[0] = mExtents[1] = dst_pos[i]; - } - else - { - //stretch bounding box - update_min_max(mExtents[0], mExtents[1], dst_pos[i]); - } - } - - - new_count = mNumIndices + face.mNumIndices; - - //allocate new index buffer - mIndices = (U16*) ll_aligned_realloc_16(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF, (mNumIndices*sizeof(U16)+0xF) & ~0xF); - - //get destination address into new index buffer - U16* dst_idx = mIndices+mNumIndices; - mNumIndices = new_count; - - for (U32 i = 0; i < (U32)face.mNumIndices; ++i) - { //copy indices, offsetting by old vertex count - dst_idx[i] = face.mIndices[i]+offset; - } -} - BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { BOOL flat = mTypeMask & FLAT_MASK; @@ -6310,6 +6403,8 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) num_vertices = mNumS*mNumT; num_indices = (mNumS-1)*(mNumT-1)*6; + partial_build = (num_vertices > mNumVertices || num_indices > mNumIndices) ? FALSE : partial_build; + if (!partial_build) { resizeVertices(num_vertices); @@ -6810,8 +6905,8 @@ void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVe float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero - llassert(llfinite(r)); - llassert(!llisnan(r)); + llassert(std::isfinite(r)); + llassert(!std::isnan(r)); LLVector4a sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 058d17132c..80a5698ef1 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -38,7 +38,7 @@ class LLVolumeParams; class LLProfile; class LLPath; -template class LLOctreeNode; +template class LLOctreeRoot; class LLVolumeFace; class LLVolume; @@ -60,6 +60,7 @@ class LLVolumeTriangle; #include "llpointer.h" #include "llfile.h" #include "llalignedarray.h" +#include "llrigginginfo.h" //============================================================================ @@ -194,8 +195,12 @@ const U8 LL_SCULPT_TYPE_MESH = 5; const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH; +// for value checks, assign new value after adding new types +const U8 LL_SCULPT_TYPE_MAX = LL_SCULPT_TYPE_MESH; + const U8 LL_SCULPT_FLAG_INVERT = 64; const U8 LL_SCULPT_FLAG_MIRROR = 128; +const U8 LL_SCULPT_FLAG_MASK = LL_SCULPT_FLAG_INVERT | LL_SCULPT_FLAG_MIRROR; const S32 LL_SCULPT_MESH_MAX_FACES = 8; @@ -866,12 +871,12 @@ class LLVolumeFace BOOL create(LLVolume* volume, BOOL partial_build = FALSE); void createTangents(); - - void appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& normal_tranform); void resizeVertices(S32 num_verts); void allocateTangents(S32 num_verts); void allocateWeights(S32 num_verts); + void allocateVertices(S32 num_verts, bool copy = false); + void allocateIndices(S32 num_indices, bool copy = false); void resizeIndices(S32 num_indices); void fillFromLegacyData(std::vector& v, std::vector& idx); @@ -953,7 +958,13 @@ class LLVolumeFace // mWeights.size() should be empty or match mVertices.size() LLVector4a* mWeights; - LLOctreeNode* mOctree; + mutable BOOL mWeightsScrubbed; + + // Which joints are rigged to, and the bounding box of any rigged + // vertices per joint. + LLJointRiggingInfoTab mJointRiggingInfoTab; + + LLOctreeRoot* mOctree; //whether or not face has been cache optimized BOOL mOptimized; @@ -972,6 +983,7 @@ class LLVolume : public LLRefCount ~LLVolume(); // use unref public: + typedef std::vector face_list_t; struct FaceParams { @@ -1044,17 +1056,23 @@ class LLVolume : public LLRefCount // conversion if *(LLVolume*) to LLVolume& const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE + LLVolumeFace &getVolumeFace(const S32 f) {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE + + face_list_t& getVolumeFaces() { return mVolumeFaces; } U32 mFaceMask; // bit array of which faces exist in this volume LLVector3 mLODScaleBias; // vector for biasing LOD based on scale - void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level); + void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder); void copyVolumeFaces(const LLVolume* volume); + void copyFacesTo(std::vector &faces) const; + void copyFacesFrom(const std::vector &faces); void cacheOptimize(); private: void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); F32 sculptGetSurfaceArea(); - void sculptGeneratePlaceholder(); + void sculptGenerateEmptyPlaceholder(); + void sculptGenerateSpherePlaceholder(); void sculptCalcMeshResolution(U16 width, U16 height, U8 type, S32& s, S32& t); @@ -1081,7 +1099,6 @@ class LLVolume : public LLRefCount BOOL mGenerateSingleFace; - typedef std::vector face_list_t; face_list_t mVolumeFaces; public: diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 07d1749267..a8c2766cb3 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -27,6 +27,7 @@ #include "llvolumemgr.h" #include "llvolume.h" +#include "llthread.h" const F32 BASE_THRESHOLD = 0.03f; @@ -214,7 +215,7 @@ void LLVolumeMgr::useMutex() { if (!mDataMutex) { - mDataMutex = new LLMutex; + mDataMutex = new LLMutex(); } } diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h index c242ca68ca..c2953655a2 100644 --- a/indra/llmath/llvolumemgr.h +++ b/indra/llmath/llvolumemgr.h @@ -31,7 +31,6 @@ #include "llvolume.h" #include "llpointer.h" -#include "llthread.h" class LLVolumeParams; class LLVolumeLODGroup; diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index 0cc78fd138..0c8e1d2b80 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -112,14 +112,13 @@ class LLVolumeOctreeListener : public LLOctreeListener } //LISTENER FUNCTIONS - virtual void handleChildAddition(const LLOctreeNode* parent, - LLOctreeNode* child); - virtual void handleStateChange(const LLTreeNode* node) { } - virtual void handleChildRemoval(const LLOctreeNode* parent, - const LLOctreeNode* child) { } - virtual void handleInsertion(const LLTreeNode* node, LLVolumeTriangle* tri) { } - virtual void handleRemoval(const LLTreeNode* node, LLVolumeTriangle* tri) { } - virtual void handleDestruction(const LLTreeNode* node) { } + void handleChildAddition(const LLOctreeNode* parent, + LLOctreeNode* child) final override; + void handleChildRemoval(const LLOctreeNode* parent, + const LLOctreeNode* child) final override { } + void handleInsertion(const LLTreeNode* node, LLVolumeTriangle* tri) final override { } + void handleRemoval(const LLTreeNode* node, LLVolumeTriangle* tri) final override { } + void handleDestruction(const LLTreeNode* node) final override { } public: diff --git a/indra/llmath/m3math.h b/indra/llmath/m3math.h index 1bf42fefac..a25f3e906e 100644 --- a/indra/llmath/m3math.h +++ b/indra/llmath/m3math.h @@ -144,6 +144,8 @@ class LLMatrix3 friend std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a); // Stream a }; +static_assert(std::is_trivially_copyable::value, "LLMatrix3 must be a trivially copyable type"); + inline LLMatrix3::LLMatrix3(void) { mMatrix[0][0] = 1.f; diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index a1fd340473..a225c51b13 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -152,10 +152,6 @@ LLMatrix4::LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw) mMatrix[3][3] = 1.f; } -LLMatrix4::~LLMatrix4(void) -{ -} - // Clear and Assignment Functions const LLMatrix4& LLMatrix4::setZero() @@ -274,6 +270,19 @@ const LLMatrix4& LLMatrix4::invert(void) return *this; } +// Convenience func for simplifying comparison-heavy code by +// intentionally stomping values in [-FLT_EPS,FLT_EPS] to 0.0f +// +void LLMatrix4::condition(void) +{ + U32 i; + U32 j; + for (i = 0; i < 3;i++) + for (j = 0; j < 3;j++) + mMatrix[i][j] = ((mMatrix[i][j] > -FLT_EPSILON) + && (mMatrix[i][j] < FLT_EPSILON)) ? 0.0f : mMatrix[i][j]; +} + LLVector4 LLMatrix4::getFwdRow4() const { return LLVector4(mMatrix[VX][VX], mMatrix[VX][VY], mMatrix[VX][VZ], mMatrix[VX][VW]); diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index 9330ec332a..c4d37d0f73 100644 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -117,7 +117,7 @@ class LLMatrix4 const LLVector4 &pos); // Initializes Matrix with Euler angles LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw); // Initializes Matrix with Euler angles - ~LLMatrix4(void); // Destructor + ~LLMatrix4() = default; // Destructor LLSD getValue() const; void setValue(const LLSD&); @@ -180,6 +180,11 @@ class LLMatrix4 const LLMatrix4& setTranslation(const LLVector4 &translation); const LLMatrix4& setTranslation(const LLVector3 &translation); + // Convenience func for simplifying comparison-heavy code by + // intentionally stomping values [-FLT_EPS,FLT_EPS] to 0.0 + // + void condition(void); + /////////////////////////// // // Get properties of a matrix @@ -241,6 +246,8 @@ class LLMatrix4 friend std::ostream& operator<<(std::ostream& s, const LLMatrix4 &a); // Stream a }; +static_assert(std::is_trivially_copyable::value, "LLMatrix4 must be a trivially copyable type"); + inline const LLMatrix4& LLMatrix4::setIdentity() { mMatrix[0][0] = 1.f; diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp index bc1c2502d2..e4706c75b5 100644 --- a/indra/llmath/v2math.cpp +++ b/indra/llmath/v2math.cpp @@ -118,7 +118,7 @@ LLSD LLVector2::getValue() const return ret; } -void LLVector2::setValue(LLSD& sd) +void LLVector2::setValue(const LLSD& sd) { mV[0] = (F32) sd[0].asReal(); mV[1] = (F32) sd[1].asReal(); diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index 194bcfcfb2..d6fb004383 100644 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h @@ -49,6 +49,7 @@ class LLVector2 LLVector2(F32 x, F32 y); // Initializes LLVector2 to (x. y) LLVector2(const F32 *vec); // Initializes LLVector2 to (vec[0]. vec[1]) explicit LLVector2(const LLVector3 &vec); // Initializes LLVector2 to (vec[0]. vec[1]) + explicit LLVector2(const LLSD &sd); // Clears LLVector2 to (0, 0). DEPRECATED - prefer zeroVec. void clear(); @@ -61,7 +62,7 @@ class LLVector2 void set(const F32 *vec); // Sets LLVector2 to vec LLSD getValue() const; - void setValue(LLSD& sd); + void setValue(const LLSD& sd); void setVec(F32 x, F32 y); // deprecated void setVec(const LLVector2 &vec); // deprecated @@ -109,6 +110,7 @@ class LLVector2 friend std::ostream& operator<<(std::ostream& s, const LLVector2 &a); // Stream a }; +static_assert(std::is_trivially_copyable::value, "LLVector2 must be a trivially copyable type"); // Non-member functions @@ -145,6 +147,10 @@ inline LLVector2::LLVector2(const LLVector3 &vec) mV[VY] = vec.mV[VY]; } +inline LLVector2::LLVector2(const LLSD &sd) +{ + setValue(sd); +} // Clear and Assignment Functions @@ -250,7 +256,7 @@ inline F32 LLVector2::normalize(void) // checker inline bool LLVector2::isFinite() const { - return (llfinite(mV[VX]) && llfinite(mV[VY])); + return (std::isfinite(mV[VX]) && std::isfinite(mV[VY])); } // deprecated diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h index 6fe39e2191..b8a5fb95e3 100644 --- a/indra/llmath/v3color.h +++ b/indra/llmath/v3color.h @@ -100,6 +100,23 @@ class LLColor3 const LLColor3& operator=(const LLColor4 &a); + LL_FORCE_INLINE LLColor3 divide(const LLColor3 &col2) + { + return LLColor3( + mV[0] / col2.mV[0], + mV[1] / col2.mV[1], + mV[2] / col2.mV[2] ); + } + + LL_FORCE_INLINE LLColor3 color_norm() const + { + F32 l = length(); + return LLColor3( + mV[0] / l, + mV[1] / l, + mV[2] / l ); + } + friend std::ostream& operator<<(std::ostream& s, const LLColor3 &a); // Print a friend LLColor3 operator+(const LLColor3 &a, const LLColor3 &b); // Return vector a + b friend LLColor3 operator-(const LLColor3 &a, const LLColor3 &b); // Return vector a minus b @@ -123,6 +140,8 @@ class LLColor3 inline void exp(); // Do an exponential on the color }; +static_assert(std::is_trivially_copyable::value, "LLColor3 must be a trivially copyable type"); + LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u); diff --git a/indra/llmath/v3colorutil.h b/indra/llmath/v3colorutil.h new file mode 100644 index 0000000000..6d8cd9329b --- /dev/null +++ b/indra/llmath/v3colorutil.h @@ -0,0 +1,115 @@ +/** + * @file v3color.h + * @brief LLColor3 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_V3COLORUTIL_H +#define LL_V3COLORUTIL_H + +#include "v3color.h" + +inline LLColor3 componentDiv(LLColor3 const &left, LLColor3 const & right) +{ + return LLColor3(left.mV[0] / right.mV[0], + left.mV[1] / right.mV[1], + left.mV[2] / right.mV[2]); +} + + +inline LLColor3 componentMult(LLColor3 const &left, LLColor3 const & right) +{ + return LLColor3(left.mV[0] * right.mV[0], + left.mV[1] * right.mV[1], + left.mV[2] * right.mV[2]); +} + + +inline LLColor3 componentExp(LLColor3 const &v) +{ + return LLColor3(exp(v.mV[0]), + exp(v.mV[1]), + exp(v.mV[2])); +} + +inline LLColor3 componentPow(LLColor3 const &v, F32 exponent) +{ + return LLColor3(pow(v.mV[0], exponent), + pow(v.mV[1], exponent), + pow(v.mV[2], exponent)); +} + +inline LLColor3 componentSaturate(LLColor3 const &v) +{ + return LLColor3(std::max(std::min(v.mV[0], 1.f), 0.f), + std::max(std::min(v.mV[1], 1.f), 0.f), + std::max(std::min(v.mV[2], 1.f), 0.f)); +} + + +inline LLColor3 componentSqrt(LLColor3 const &v) +{ + return LLColor3(sqrt(v.mV[0]), + sqrt(v.mV[1]), + sqrt(v.mV[2])); +} + +inline void componentMultBy(LLColor3 & left, LLColor3 const & right) +{ + left.mV[0] *= right.mV[0]; + left.mV[1] *= right.mV[1]; + left.mV[2] *= right.mV[2]; +} + +inline LLColor3 colorMix(LLColor3 const & left, LLColor3 const & right, F32 amount) +{ + return (left + ((right - left) * amount)); +} + +inline LLColor3 smear(F32 val) +{ + return LLColor3(val, val, val); +} + +inline F32 color_intens(const LLColor3 &col) +{ + return col.mV[0] + col.mV[1] + col.mV[2]; +} + +inline F32 color_max(const LLColor3 &col) +{ + return llmax(col.mV[0], col.mV[1], col.mV[2]); +} + +inline F32 color_max(const LLColor4 &col) +{ + return llmax(col.mV[0], col.mV[1], col.mV[2]); +} + + +inline F32 color_min(const LLColor3 &col) +{ + return llmin(col.mV[0], col.mV[1], col.mV[2]); +} + +#endif diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h index f92c3984ed..2efa5a500d 100644 --- a/indra/llmath/v3dmath.h +++ b/indra/llmath/v3dmath.h @@ -130,6 +130,8 @@ class LLVector3d }; +static_assert(std::is_trivially_copyable::value, "LLVector3d must be a trivially copyable type"); + typedef LLVector3d LLGlobalVec; inline const LLVector3d &LLVector3d::set(const LLVector3 &vec) @@ -191,7 +193,7 @@ inline LLVector3d::LLVector3d(const LLVector3d ©) // checker inline BOOL LLVector3d::isFinite() const { - return (llfinite(mdV[VX]) && llfinite(mdV[VY]) && llfinite(mdV[VZ])); + return (std::isfinite(mdV[VX]) && std::isfinite(mdV[VY]) && std::isfinite(mdV[VZ])); } diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp index 898296707b..88e91e8d10 100644 --- a/indra/llmath/v3math.cpp +++ b/indra/llmath/v3math.cpp @@ -76,7 +76,7 @@ BOOL LLVector3::clampLength( F32 length_limit ) BOOL changed = FALSE; F32 len = length(); - if (llfinite(len)) + if (std::isfinite(len)) { if ( len > length_limit) { @@ -97,7 +97,7 @@ BOOL LLVector3::clampLength( F32 length_limit ) for (S32 i = 0; i < 3; ++i) { F32 abs_component = fabs(mV[i]); - if (llfinite(abs_component)) + if (std::isfinite(abs_component)) { if (abs_component > max_abs_component) { @@ -369,3 +369,39 @@ BOOL LLVector3::parseVector3(const std::string& buf, LLVector3* value) return FALSE; } + +// Displacement from query point to nearest neighbor point on bounding box. +// Returns zero vector for points within or on the box. +LLVector3 point_to_box_offset(LLVector3& pos, const LLVector3* box) +{ + LLVector3 offset; + for (S32 k=0; k<3; k++) + { + offset[k] = 0; + if (pos[k] < box[0][k]) + { + offset[k] = pos[k] - box[0][k]; + } + else if (pos[k] > box[1][k]) + { + offset[k] = pos[k] - box[1][k]; + } + } + return offset; +} + +bool box_valid_and_non_zero(const LLVector3* box) +{ + if (!box[0].isFinite() || !box[1].isFinite()) + { + return false; + } + LLVector3 zero_vec; + zero_vec.clear(); + if ((box[0] != zero_vec) || (box[1] != zero_vec)) + { + return true; + } + return false; +} + diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 193533678b..35acead650 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -149,6 +149,8 @@ class LLVector3 static BOOL parseVector3(const std::string& buf, LLVector3* value); }; +static_assert(std::is_trivially_copyable::value, "LLVector3 must be a trivially copyable type"); + typedef LLVector3 LLSimLocalVec; // Non-member functions @@ -163,6 +165,8 @@ LLVector3 inverse_projected_vec(const LLVector3 &a, const LLVector3 &b); // Retu LLVector3 parallel_component(const LLVector3 &a, const LLVector3 &b); // Returns vector a projected on vector b (same as projected_vec) LLVector3 orthogonal_component(const LLVector3 &a, const LLVector3 &b); // Returns component of vector a not parallel to vector b (same as projected_vec) LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u); // Returns a vector that is a linear interpolation between a and b +LLVector3 point_to_box_offset(LLVector3& pos, const LLVector3* box); // Displacement from query point to nearest point on bounding box. +bool box_valid_and_non_zero(const LLVector3* box); inline LLVector3::LLVector3(void) { @@ -199,7 +203,7 @@ inline LLVector3::LLVector3(const LLVector3 ©) // checker inline BOOL LLVector3::isFinite() const { - return (llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ])); + return (std::isfinite(mV[VX]) && std::isfinite(mV[VY]) && std::isfinite(mV[VZ])); } diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp index a47c93e936..6de5fb6329 100644 --- a/indra/llmath/v4color.cpp +++ b/indra/llmath/v4color.cpp @@ -124,11 +124,12 @@ LLColor4 LLColor4::cyan6(0.2f, 0.6f, 0.6f, 1.0f); // conversion LLColor4::operator const LLColor4U() const { + // Singu Note: Some optimization has been done here. return LLColor4U( - (U8)llclampb(ll_round(mV[VRED]*255.f)), - (U8)llclampb(ll_round(mV[VGREEN]*255.f)), - (U8)llclampb(ll_round(mV[VBLUE]*255.f)), - (U8)llclampb(ll_round(mV[VALPHA]*255.f))); + (U8)llmin((S32)(llmax(0.f,mV[VRED]*255.f) + .5f), 255), + (U8)llmin((S32)(llmax(0.f,mV[VGREEN]*255.f) + .5f), 255), + (U8)llmin((S32)(llmax(0.f,mV[VBLUE]*255.f) + .5f), 255), + (U8)llmin((S32)(llmax(0.f,mV[VALPHA]*255.f) + .5f), 255)); } LLColor4::LLColor4(const LLColor3 &vec, F32 a) diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index 3f9e1efd8a..845160d3d1 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -114,9 +114,11 @@ class LLColor4 friend LLColor4 operator-(const LLColor4 &a, const LLColor4 &b); // Return vector a minus b friend LLColor4 operator*(const LLColor4 &a, const LLColor4 &b); // Return component wise a * b friend LLColor4 operator*(const LLColor4 &a, F32 k); // Return rgb times scaler k (no alpha change) + friend LLColor4 operator/(const LLColor4 &a, F32 k); // Return rgb divided by scalar k (no alpha change) friend LLColor4 operator*(F32 k, const LLColor4 &a); // Return rgb times scaler k (no alpha change) friend LLColor4 operator%(const LLColor4 &a, F32 k); // Return alpha times scaler k (no rgb change) friend LLColor4 operator%(F32 k, const LLColor4 &a); // Return alpha times scaler k (no rgb change) + friend bool operator==(const LLColor4 &a, const LLColor4 &b); // Return a == b friend bool operator!=(const LLColor4 &a, const LLColor4 &b); // Return a != b @@ -220,6 +222,7 @@ class LLColor4 inline void clamp(); }; +static_assert(std::is_trivially_copyable::value, "LLColor4 must be a trivially copyable type"); // Non-member functions F32 distVec(const LLColor4 &a, const LLColor4 &b); // Returns distance between a and b @@ -477,6 +480,15 @@ inline LLColor4 operator*(const LLColor4 &a, F32 k) a.mV[VW]); } +inline LLColor4 operator/(const LLColor4 &a, F32 k) +{ + return LLColor4( + a.mV[VX] / k, + a.mV[VY] / k, + a.mV[VZ] / k, + a.mV[VW]); +} + inline LLColor4 operator*(F32 k, const LLColor4 &a) { // only affects rgb (not a!) diff --git a/indra/llmath/v4coloru.h b/indra/llmath/v4coloru.h index 2018a95f5f..3a313759d3 100644 --- a/indra/llmath/v4coloru.h +++ b/indra/llmath/v4coloru.h @@ -139,6 +139,7 @@ class LLColor4U static LLColor4U blue; }; +static_assert(std::is_trivially_copyable::value, "LLColor4U must be a trivially copyable type"); // Non-member functions F32 distVec(const LLColor4U &a, const LLColor4U &b); // Returns distance between a and b @@ -353,10 +354,10 @@ inline LLColor4U LLColor4U::multAll(const F32 k) { // Round to nearest return LLColor4U( - (U8)ll_round(mV[VX] * k), - (U8)ll_round(mV[VY] * k), - (U8)ll_round(mV[VZ] * k), - (U8)ll_round(mV[VW] * k)); + (U8)ll_pos_round(mV[VX] * k), + (U8)ll_pos_round(mV[VY] * k), + (U8)ll_pos_round(mV[VZ] * k), + (U8)ll_pos_round(mV[VW] * k)); } /* inline LLColor4U operator*(const LLColor4U &a, U8 k) @@ -471,7 +472,7 @@ void LLColor4U::setVecScaleClamp(const LLColor4& color) color_scale_factor /= max_color; } const S32 MAX_COLOR = 255; - S32 r = ll_round(color.mV[0] * color_scale_factor); + S32 r = ll_pos_round(color.mV[0] * color_scale_factor); if (r > MAX_COLOR) { r = MAX_COLOR; @@ -482,7 +483,7 @@ void LLColor4U::setVecScaleClamp(const LLColor4& color) } mV[0] = r; - S32 g = ll_round(color.mV[1] * color_scale_factor); + S32 g = ll_pos_round(color.mV[1] * color_scale_factor); if (g > MAX_COLOR) { g = MAX_COLOR; @@ -493,7 +494,7 @@ void LLColor4U::setVecScaleClamp(const LLColor4& color) } mV[1] = g; - S32 b = ll_round(color.mV[2] * color_scale_factor); + S32 b = ll_pos_round(color.mV[2] * color_scale_factor); if (b > MAX_COLOR) { b = MAX_COLOR; @@ -505,7 +506,7 @@ void LLColor4U::setVecScaleClamp(const LLColor4& color) mV[2] = b; // Alpha shouldn't be scaled, just clamped... - S32 a = ll_round(color.mV[3] * MAX_COLOR); + S32 a = ll_pos_round(color.mV[3] * MAX_COLOR); if (a > MAX_COLOR) { a = MAX_COLOR; @@ -527,7 +528,7 @@ void LLColor4U::setVecScaleClamp(const LLColor3& color) } const S32 MAX_COLOR = 255; - S32 r = ll_round(color.mV[0] * color_scale_factor); + S32 r = ll_pos_round(color.mV[0] * color_scale_factor); if (r > MAX_COLOR) { r = MAX_COLOR; @@ -539,7 +540,7 @@ void LLColor4U::setVecScaleClamp(const LLColor3& color) } mV[0] = r; - S32 g = ll_round(color.mV[1] * color_scale_factor); + S32 g = ll_pos_round(color.mV[1] * color_scale_factor); if (g > MAX_COLOR) { g = MAX_COLOR; @@ -551,7 +552,7 @@ void LLColor4U::setVecScaleClamp(const LLColor3& color) } mV[1] = g; - S32 b = ll_round(color.mV[2] * color_scale_factor); + S32 b = ll_pos_round(color.mV[2] * color_scale_factor); if (b > MAX_COLOR) { b = MAX_COLOR; diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h index 4288916e46..7356368053 100644 --- a/indra/llmath/v4math.h +++ b/indra/llmath/v4math.h @@ -30,6 +30,7 @@ #include "llerror.h" #include "llmath.h" #include "v3math.h" +#include "v2math.h" class LLMatrix3; class LLMatrix4; @@ -46,8 +47,11 @@ class LLVector4 LLVector4(); // Initializes LLVector4 to (0, 0, 0, 1) explicit LLVector4(const F32 *vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2], vec[3]) explicit LLVector4(const F64 *vec); // Initialized LLVector4 to ((F32) vec[0], (F32) vec[1], (F32) vec[3], (F32) vec[4]); + explicit LLVector4(const LLVector2 &vec); + explicit LLVector4(const LLVector2 &vec, F32 z, F32 w); explicit LLVector4(const LLVector3 &vec); // Initializes LLVector4 to (vec, 1) explicit LLVector4(const LLVector3 &vec, F32 w); // Initializes LLVector4 to (vec, w) + explicit LLVector4(const LLSD &sd); LLVector4(F32 x, F32 y, F32 z); // Initializes LLVector4 to (x. y, z, 1) LLVector4(F32 x, F32 y, F32 z, F32 w); @@ -61,6 +65,15 @@ class LLVector4 return ret; } + void setValue(const LLSD& sd) + { + mV[0] = sd[0].asReal(); + mV[1] = sd[1].asReal(); + mV[2] = sd[2].asReal(); + mV[3] = sd[3].asReal(); + } + + inline BOOL isFinite() const; // checks to see if all values of LLVector3 are finite inline void clear(); // Clears LLVector4 to (0, 0, 0, 1) @@ -124,6 +137,8 @@ class LLVector4 friend LLVector4 operator-(const LLVector4 &a); // Return vector -a }; +static_assert(std::is_trivially_copyable::value, "LLVector4 must be a trivially copyable type"); + // Non-member functions F32 angle_between(const LLVector4 &a, const LLVector4 &b); // Returns angle (radians) between a and b BOOL are_parallel(const LLVector4 &a, const LLVector4 &b, F32 epsilon=F_APPROXIMATELY_ZERO); // Returns TRUE if a and b are very close to parallel @@ -175,6 +190,22 @@ inline LLVector4::LLVector4(const F64 *vec) mV[VW] = (F32) vec[VW]; } +inline LLVector4::LLVector4(const LLVector2 &vec) +{ + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = 0.f; + mV[VW] = 0.f; +} + +inline LLVector4::LLVector4(const LLVector2 &vec, F32 z, F32 w) +{ + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = z; + mV[VW] = w; +} + inline LLVector4::LLVector4(const LLVector3 &vec) { mV[VX] = vec.mV[VX]; @@ -191,10 +222,15 @@ inline LLVector4::LLVector4(const LLVector3 &vec, F32 w) mV[VW] = w; } +inline LLVector4::LLVector4(const LLSD &sd) +{ + setValue(sd); +} + inline BOOL LLVector4::isFinite() const { - return (llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]) && llfinite(mV[VW])); + return (std::isfinite(mV[VX]) && std::isfinite(mV[VY]) && std::isfinite(mV[VZ]) && std::isfinite(mV[VW])); } // Clear and Assignment Functions diff --git a/indra/llmath/xform.h b/indra/llmath/xform.h index 06c408fa50..b07988e1b1 100644 --- a/indra/llmath/xform.h +++ b/indra/llmath/xform.h @@ -200,7 +200,7 @@ void LLXform::setPosition(const LLVector3& pos) void LLXform::setPosition(const F32 x, const F32 y, const F32 z) { setChanged(TRANSLATED); - if (llfinite(x) && llfinite(y) && llfinite(z)) + if (std::isfinite(x) && std::isfinite(y) && std::isfinite(z)) mPosition.setVec(x,y,z); else { @@ -212,7 +212,7 @@ void LLXform::setPosition(const F32 x, const F32 y, const F32 z) void LLXform::setPositionX(const F32 x) { setChanged(TRANSLATED); - if (llfinite(x)) + if (std::isfinite(x)) mPosition.mV[VX] = x; else { @@ -224,7 +224,7 @@ void LLXform::setPositionX(const F32 x) void LLXform::setPositionY(const F32 y) { setChanged(TRANSLATED); - if (llfinite(y)) + if (std::isfinite(y)) mPosition.mV[VY] = y; else { @@ -236,7 +236,7 @@ void LLXform::setPositionY(const F32 y) void LLXform::setPositionZ(const F32 z) { setChanged(TRANSLATED); - if (llfinite(z)) + if (std::isfinite(z)) mPosition.mV[VZ] = z; else { @@ -268,7 +268,7 @@ void LLXform::setScale(const LLVector3& scale) void LLXform::setScale(const F32 x, const F32 y, const F32 z) { setChanged(SCALED); - if (llfinite(x) && llfinite(y) && llfinite(z)) + if (std::isfinite(x) && std::isfinite(y) && std::isfinite(z)) mScale.setVec(x,y,z); else { @@ -290,7 +290,7 @@ void LLXform::setRotation(const LLQuaternion& rot) void LLXform::setRotation(const F32 x, const F32 y, const F32 z) { setChanged(ROTATED); - if (llfinite(x) && llfinite(y) && llfinite(z)) + if (std::isfinite(x) && std::isfinite(y) && std::isfinite(z)) { mRotation.setQuat(x,y,z); } @@ -303,7 +303,7 @@ void LLXform::setRotation(const F32 x, const F32 y, const F32 z) void LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s) { setChanged(ROTATED); - if (llfinite(x) && llfinite(y) && llfinite(z) && llfinite(s)) + if (std::isfinite(x) && std::isfinite(y) && std::isfinite(z) && std::isfinite(s)) { mRotation.mQ[VX] = x; mRotation.mQ[VY] = y; mRotation.mQ[VZ] = z; mRotation.mQ[VS] = s; } diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 6523a2c9aa..44743b37ff 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -37,7 +37,6 @@ set(llmessage_SOURCE_FILES llassetstorage.cpp llavatarname.cpp llavatarnamecache.cpp - llblowfishcipher.cpp llbuffer.cpp llbufferstream.cpp llcachename.cpp @@ -46,6 +45,7 @@ set(llmessage_SOURCE_FILES llclassifiedflags.cpp lldatapacker.cpp lldispatcher.cpp + llexperiencecache.cpp llfiltersd2xmlrpc.cpp llhost.cpp llhttpclient.cpp @@ -57,7 +57,6 @@ set(llmessage_SOURCE_FILES lliopipe.cpp lliosocket.cpp llioutil.cpp - llmail.cpp llmessagebuilder.cpp llmessageconfig.cpp llmessagelog.cpp @@ -65,7 +64,6 @@ set(llmessage_SOURCE_FILES llmessagetemplate.cpp llmessagetemplateparser.cpp llmessagethrottle.cpp - llmime.cpp llnamevalue.cpp llnullcipher.cpp llpacketack.cpp @@ -128,7 +126,6 @@ set(llmessage_HEADER_FILES llassetstorage.h llavatarname.h llavatarnamecache.h - llblowfishcipher.h llbuffer.h llbufferstream.h llcachename.h @@ -136,11 +133,13 @@ set(llmessage_HEADER_FILES llcipher.h llcircuit.h llclassifiedflags.h + llcororesponder.h llcurl.h lldatapacker.h lldbstrings.h lldispatcher.h lleventflags.h + llexperiencecache.h llfiltersd2xmlrpc.h llfollowcamparams.h llhost.h @@ -156,7 +155,6 @@ set(llmessage_HEADER_FILES lliosocket.h llioutil.h llloginflags.h - llmail.h llmessagebuilder.h llmessageconfig.h llmessagelog.h @@ -164,7 +162,6 @@ set(llmessage_HEADER_FILES llmessagetemplate.h llmessagetemplateparser.h llmessagethrottle.h - llmime.h llmsgvariabletype.h llnamevalue.h llnullcipher.h @@ -220,15 +217,19 @@ set_source_files_properties(${llmessage_HEADER_FILES} list(APPEND llmessage_SOURCE_FILES ${llmessage_HEADER_FILES}) add_library (llmessage ${llmessage_SOURCE_FILES}) -add_dependencies(llmessage prepare) + target_link_libraries( llmessage + PUBLIC + llcommon ${CURL_LIBRARIES} ${CARES_LIBRARIES} + ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARIES} ${XMLRPCEPI_LIBRARIES} - ) + ${PTHREAD_LIBRARY} +) # tests if (LL_TESTS) @@ -238,7 +239,6 @@ if (LL_TESTS) include(Tut) SET(llmessage_TEST_SOURCE_FILES - llmime.cpp llnamevalue.cpp lltrustedmessageservice.cpp lltemplatemessagedispatcher.cpp diff --git a/indra/llmessage/aicurl.cpp b/indra/llmessage/aicurl.cpp index 843b06a288..c969097727 100644 --- a/indra/llmessage/aicurl.cpp +++ b/indra/llmessage/aicurl.cpp @@ -195,10 +195,10 @@ ssl_dyn_create_function_type old_ssl_dyn_create_function; ssl_dyn_destroy_function_type old_ssl_dyn_destroy_function; ssl_dyn_lock_function_type old_ssl_dyn_lock_function; -#if LL_WINDOWS +#if LL_WINDOWS && !HAVE_CRYPTO_THREADID static unsigned long __cdecl apr_os_thread_current_wrapper() { - return (unsigned long)apr_os_thread_current(); + return (unsigned long)(HANDLE)apr_os_thread_current(); } #endif @@ -1077,7 +1077,7 @@ CURLcode CurlEasyRequest::curlCtxCallback(CURL* curl, void* sslctx, void* parm) // Also turn off SSL v2, which is highly broken and strongly discouraged[1]. // [1] http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html#SECURE_RENEGOTIATION long options = SSL_OP_NO_SSLv2; -#ifdef SSL_OP_NO_TLSv1_1 // Only defined for openssl version 1.0.1 and up. +/*#ifdef SSL_OP_NO_TLSv1_1 // Only defined for openssl version 1.0.1 and up. if (need_renegotiation_hack) { // This option disables openssl to use TLS version 1.1. @@ -1095,7 +1095,7 @@ CURLcode CurlEasyRequest::curlCtxCallback(CURL* curl, void* sslctx, void* parm) // This is expected when you compile against the headers of a version < 1.0.1 and then link at runtime with version >= 1.0.1. // Don't do that. llassert_always(!need_renegotiation_hack); -#endif +#endif*/ SSL_CTX_set_options(ctx, options); return CURLE_OK; } diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp index a66790f1d8..c23beea844 100644 --- a/indra/llmessage/aicurlthread.cpp +++ b/indra/llmessage/aicurlthread.cpp @@ -2291,12 +2291,13 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size } else { - reason = "Unexpected HTTP status."; + //reason = "Unexpected HTTP status."; LL_WARNS() << "Received unexpected status value from server (" << status << "): \"" << header << "\"" << LL_ENDL; } + // Singu TODO: WHAT THE HELL WAS THIS?! LYING? WHY WERE WE LYING???? Responders USE These Codes!!!!! // Either way, this status value is not understood (or taken into account). // Set it to internal error so that the rest of code treats it as an error. - status = HTTP_INTERNAL_ERROR_OTHER; + if (!status) status = HTTP_INTERNAL_ERROR_OTHER; } self_w->received_HTTP_header(); self_w->setStatusAndReason(status, reason); diff --git a/indra/llmessage/aicurlthread.h b/indra/llmessage/aicurlthread.h index 908456b130..7046af12b8 100644 --- a/indra/llmessage/aicurlthread.h +++ b/indra/llmessage/aicurlthread.h @@ -45,7 +45,7 @@ class PollSet; // For ordering a std::set with AICurlEasyRequest objects. struct AICurlEasyRequestCompare { - bool operator()(AICurlEasyRequest const& h1, AICurlEasyRequest const& h2) { return h1.get() < h2.get(); } + bool operator()(AICurlEasyRequest const& h1, AICurlEasyRequest const& h2) const { return h1.get() < h2.get(); } }; //----------------------------------------------------------------------------- diff --git a/indra/llmessage/aihttptimeoutpolicy.cpp b/indra/llmessage/aihttptimeoutpolicy.cpp index ff37b849df..80f659bae3 100644 --- a/indra/llmessage/aihttptimeoutpolicy.cpp +++ b/indra/llmessage/aihttptimeoutpolicy.cpp @@ -30,7 +30,6 @@ #include "sys.h" #include "aihttptimeoutpolicy.h" -#define NOMINMAX #include "llerror.h" #include "lldefs.h" #include "v3math.h" @@ -913,7 +912,6 @@ P(blockingLLSDPost); P(blockingLLSDGet); P(blockingRawGet); P(classifiedStatsResponder); -P(createInventoryCategoryResponder); P(emeraldDicDownloader); P(environmentApplyResponder); P(environmentRequestResponder); @@ -929,7 +927,6 @@ P2(groupProposalBallotResponder, transfer_300s); P(homeLocationResponder); P2(HTTPGetResponder, reply_15s); P(iamHere); -P(iamHereVoice); P2(BGFolderHttpHandler, transfer_300s); P(BGItemHttpHandler); P(lcl_responder); @@ -943,14 +940,12 @@ P2(meshHeaderResponder, connect_30s); P2(meshLODResponder, connect_30s); P2(meshPhysicsShapeResponder, connect_30s); P2(meshSkinInfoResponder, connect_30s); -P(moderationResponder); P(objectCostResponder); P(physicsFlagsResponder); P(productInfoRequestResponder); P(regionResponder); P(remoteParcelRequestResponder); P(requestAgentUpdateAppearance); -P2(incrementCofVersionResponder_timeouts, transfer_30s_connect_10s); P(responderIgnore); P(setDisplayNameResponder); P2(baseFeaturesReceived, transfer_22s_connect_10s); @@ -965,4 +960,5 @@ P(webProfileResponders); P(wholeModelFeeResponder); P(wholeModelUploadResponder); P2(XMLRPCResponder, connect_40s); -P2(crashLoggerResponder, transfer_300s); +P(getUpdateInfoResponder); +P2(AISAPIResponder, connect_60s); \ No newline at end of file diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index 029bcc1242..6939a50298 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -162,12 +162,26 @@ void LLAres::getSrvRecords(const std::string &name, SrvResponder *resp) } void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp) -{ - LL_INFOS() << "Rewriting " << uri << LL_ENDL; +{ + if (resp && uri.size()) + { + LLURI* pURI = new LLURI(uri); + + resp->mUri = *pURI; - resp->mUri = LLURI(uri); - search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(), - RES_SRV, resp); + delete pURI; + + if (!resp->mUri.scheme().size() || !resp->mUri.hostName().size()) + { + return; + } + + //LL_INFOS() << "LLAres::rewriteURI (" << uri << ") search: '" << "_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName() << "'" << LL_ENDL; + + search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(), RES_SRV, resp); + + + } } LLQueryResponder::LLQueryResponder() diff --git a/indra/llmessage/llareslistener.cpp b/indra/llmessage/llareslistener.cpp index 58b8a05a9e..3d65906b98 100644 --- a/indra/llmessage/llareslistener.cpp +++ b/indra/llmessage/llareslistener.cpp @@ -93,5 +93,12 @@ class UriRewriteResponder: public LLAres::UriRewriteResponder void LLAresListener::rewriteURI(const LLSD& data) { - mAres->rewriteURI(data["uri"], new UriRewriteResponder(data)); + if (mAres) + { + mAres->rewriteURI(data["uri"], new UriRewriteResponder(data)); + } + else + { + LL_INFOS() << "LLAresListener::rewriteURI requested without Ares present. Ignoring: " << data << LL_ENDL; + } } diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 09216e5adb..5e139e7cb5 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -58,8 +58,40 @@ const LLUUID CATEGORIZE_LOST_AND_FOUND_ID(std::string("00000000-0000-0000-0000-0 const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000); // microseconds -LLTempAssetStorage::~LLTempAssetStorage() +namespace { + bool operator == (const LLAssetStorage::LLGetAssetCallback &lhs, const LLAssetStorage::LLGetAssetCallback &rhs) + { + auto fnPtrLhs = lhs.target(); + auto fnPtrRhs = rhs.target(); + if (fnPtrLhs && fnPtrRhs) + return (*fnPtrLhs == *fnPtrRhs); + else if (!fnPtrLhs && !fnPtrRhs) + return true; + return false; + } + +// Rider: This is the general case of the operator declared above. The code compares the callback +// passed into the LLAssetStorage functions to determine if there are duplicated requests for an +// asset. Unfortunately std::function does not provide a direct way to compare two variables so +// we define the operator here. +// XCode is not very happy with the variadic temples in use below so we will just define the specific +// case of comparing two LLGetAssetCallback objects since that is all we really use. +// +// template +// bool operator == (const std::function &a, const std::function &b) +// { +// typedef T(fnType)(U...); +// +// auto fnPtrA = a.target(); +// auto fnPtrB = b.target(); +// if (fnPtrA && fnPtrB) +// return (*fnPtrA == *fnPtrB); +// else if (!fnPtrA && !fnPtrB) +// return true; +// return false; +// } + } ///---------------------------------------------------------------------------- @@ -153,29 +185,50 @@ void LLAssetInfo::setFromNameValue( const LLNameValue& nv ) LL_DEBUGS("AssetStorage") << "creator: " << mCreatorID << LL_ENDL; } +///---------------------------------------------------------------------------- +/// LLBaseDownloadRequest +///---------------------------------------------------------------------------- + +LLBaseDownloadRequest::LLBaseDownloadRequest(const LLUUID &uuid, const LLAssetType::EType type) + : mUUID(uuid), + mType(type), + mDownCallback(), + mUserData(NULL), + mHost(), + mIsTemp(FALSE), + mIsPriority(FALSE), + mDataSentInFirstPacket(FALSE), + mDataIsInVFS(FALSE) +{ + // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been + // running a message system loop. + mTime = LLMessageSystem::getMessageTimeSeconds(TRUE); +} + +// virtual +LLBaseDownloadRequest::~LLBaseDownloadRequest() +{ +} + +// virtual +LLBaseDownloadRequest* LLBaseDownloadRequest::getCopy() +{ + return new LLBaseDownloadRequest(*this); +} + + ///---------------------------------------------------------------------------- /// LLAssetRequest ///---------------------------------------------------------------------------- LLAssetRequest::LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType type) -: mUUID(uuid), - mType(type), - mDownCallback( NULL ), - mUpCallback( NULL ), - mInfoCallback( NULL ), - mUserData( NULL ), - mHost(), - mIsTemp( FALSE ), - mIsLocal(FALSE), - mIsUserWaiting(FALSE), - mTimeout(LL_ASSET_STORAGE_TIMEOUT), - mIsPriority(FALSE), - mDataSentInFirstPacket(FALSE), - mDataIsInVFS( FALSE ) + : LLBaseDownloadRequest(uuid, type), + mUpCallback(), + mInfoCallback( NULL ), + mIsLocal(FALSE), + mIsUserWaiting(FALSE), + mTimeout(LL_ASSET_STORAGE_TIMEOUT) { - // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been - // running a message system loop. - mTime = LLMessageSystem::getMessageTimeSeconds(TRUE); } // virtual @@ -190,8 +243,8 @@ LLSD LLAssetRequest::getTerseDetails() const sd["asset_id"] = getUUID(); sd["type_long"] = LLAssetType::lookupHumanReadable(getType()); sd["type"] = LLAssetType::lookup(getType()); - sd["time"] = mTime; - time_t timestamp = (time_t) mTime; + sd["time"] = mTime.value(); + time_t timestamp = (time_t) mTime.value(); std::ostringstream time_string; time_string << ctime(×tamp); sd["time_string"] = time_string.str(); @@ -213,56 +266,51 @@ LLSD LLAssetRequest::getFullDetails() const return sd; } +LLBaseDownloadRequest* LLAssetRequest::getCopy() +{ + return new LLAssetRequest(*this); +} + ///---------------------------------------------------------------------------- /// LLInvItemRequest ///---------------------------------------------------------------------------- LLInvItemRequest::LLInvItemRequest(const LLUUID &uuid, const LLAssetType::EType type) -: mUUID(uuid), - mType(type), - mDownCallback( NULL ), - mUserData( NULL ), - mHost(), - mIsTemp( FALSE ), - mIsPriority(FALSE), - mDataSentInFirstPacket(FALSE), - mDataIsInVFS( FALSE ) + : LLBaseDownloadRequest(uuid, type) { - // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been - // running a message system loop. - mTime = LLMessageSystem::getMessageTimeSeconds(TRUE); } +// virtual LLInvItemRequest::~LLInvItemRequest() { } +LLBaseDownloadRequest* LLInvItemRequest::getCopy() +{ + return new LLInvItemRequest(*this); +} + ///---------------------------------------------------------------------------- /// LLEstateAssetRequest ///---------------------------------------------------------------------------- LLEstateAssetRequest::LLEstateAssetRequest(const LLUUID &uuid, const LLAssetType::EType atype, - EstateAssetType etype) -: mUUID(uuid), - mAType(atype), - mEstateAssetType(etype), - mDownCallback( NULL ), - mUserData( NULL ), - mHost(), - mIsTemp( FALSE ), - mIsPriority(FALSE), - mDataSentInFirstPacket(FALSE), - mDataIsInVFS( FALSE ) + EstateAssetType etype) + : LLBaseDownloadRequest(uuid, atype), + mEstateAssetType(etype) { - // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been - // running a message system loop. - mTime = LLMessageSystem::getMessageTimeSeconds(TRUE); } +// Virtual LLEstateAssetRequest::~LLEstateAssetRequest() { } +LLBaseDownloadRequest* LLEstateAssetRequest::getCopy() +{ + return new LLEstateAssetRequest(*this); +} + ///---------------------------------------------------------------------------- /// LLAssetStorage @@ -282,14 +330,12 @@ LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS _init(msg, xfer, vfs, static_vfs, upstream_host); } - LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS *vfs, LLVFS *static_vfs) { _init(msg, xfer, vfs, static_vfs, LLHost::invalid); } - void LLAssetStorage::_init(LLMessageSystem *msg, LLXferManager *xfer, LLVFS *vfs, @@ -337,7 +383,7 @@ void LLAssetStorage::checkForTimeouts() void LLAssetStorage::_cleanupRequests(BOOL all, S32 error) { - F64 mt_secs = LLMessageSystem::getMessageTimeSeconds(); + F64Seconds mt_secs = LLMessageSystem::getMessageTimeSeconds(); request_list_t timed_out; S32 rt; @@ -356,7 +402,7 @@ void LLAssetStorage::_cleanupRequests(BOOL all, S32 error) || ((RT_DOWNLOAD == rt) && LL_ASSET_STORAGE_TIMEOUT < (mt_secs - tmp->mTime))) { - LL_WARNS() << "Asset " << getRequestName((ERequestType)rt) << " request " + LL_WARNS("AssetStorage") << "Asset " << getRequestName((ERequestType)rt) << " request " << (all ? "aborted" : "timed out") << " for " << tmp->getUUID() << "." << LLAssetType::lookup(tmp->getType()) << LL_ENDL; @@ -420,7 +466,7 @@ bool LLAssetStorage::findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAsse } else { - LL_WARNS() << "Asset vfile " << uuid << ":" << type + LL_WARNS("AssetStorage") << "Asset vfile " << uuid << ":" << type << " found in static cache with bad size " << file.getSize() << ", ignoring" << LL_ENDL; } } @@ -432,7 +478,11 @@ bool LLAssetStorage::findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAsse /////////////////////////////////////////////////////////////////////////// // IW - uuid is passed by value to avoid side effects, please don't re-add & -void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LLGetAssetCallback callback, void *user_data, BOOL is_priority) +void LLAssetStorage::getAssetData(const LLUUID uuid, + LLAssetType::EType type, + LLAssetStorage::LLGetAssetCallback callback, + void *user_data, + BOOL is_priority) { LL_DEBUGS("AssetStorage") << "LLAssetStorage::getAssetData() - " << uuid << "," << LLAssetType::lookup(type) << LL_ENDL; @@ -504,7 +554,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LL { if (exists) { - LL_WARNS() << "Asset vfile " << uuid << ":" << type << " found with bad size " << file.getSize() << ", removing" << LL_ENDL; + LL_WARNS("AssetStorage") << "Asset vfile " << uuid << ":" << type << " found with bad size " << file.getSize() << ", removing" << LL_ENDL; file.remove(); } @@ -520,7 +570,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LL if (callback == tmp->mDownCallback && user_data == tmp->mUserData) { // this is a duplicate from the same subsystem - throw it away - LL_WARNS() << "Discarding duplicate request for asset " << uuid + LL_WARNS("AssetStorage") << "Discarding duplicate request for asset " << uuid << "." << LLAssetType::lookup(type) << LL_ENDL; return; } @@ -542,59 +592,45 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LL } -// -// *NOTE: Logic here is replicated in LLViewerAssetStorage::_queueDataRequest. -// Changes here may need to be replicated in the viewer's derived class. -// -void LLAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType atype, - LLGetAssetCallback callback, - void *user_data, BOOL duplicate, - BOOL is_priority) -{ - if (mUpstreamHost.isOk()) +// static +void LLAssetStorage::removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type, + const LLUUID& callback_id, LLAssetType::EType callback_type, + S32 result_code, LLExtStat ext_status) +{ + // find and callback ALL pending requests for this UUID + // SJB: We process the callbacks in reverse order, I do not know if this is important, + // but I didn't want to mess with it. + request_list_t requests; + for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin(); + iter != gAssetStorage->mPendingDownloads.end(); ) { - // stash the callback info so we can find it after we get the response message - LLAssetRequest *req = new LLAssetRequest(uuid, atype); - req->mDownCallback = callback; - req->mUserData = user_data; - req->mIsPriority = is_priority; - - mPendingDownloads.push_back(req); - - if (!duplicate) + request_list_t::iterator curiter = iter++; + LLAssetRequest* tmp = *curiter; + if ((tmp->getUUID() == file_id) && (tmp->getType()== file_type)) { - // send request message to our upstream data provider - // Create a new asset transfer. - LLTransferSourceParamsAsset spa; - spa.setAsset(uuid, atype); - - // Set our destination file, and the completion callback. - LLTransferTargetParamsVFile tpvf; - tpvf.setAsset(uuid, atype); - tpvf.setCallback(downloadCompleteCallback, req); - - //LL_INFOS() << "Starting transfer for " << uuid << LL_ENDL; - LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET); - ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f)); + requests.push_front(tmp); + iter = gAssetStorage->mPendingDownloads.erase(curiter); } } - else + for (request_list_t::iterator iter = requests.begin(); + iter != requests.end(); ) { - // uh-oh, we shouldn't have gotten here - LL_WARNS() << "Attempt to move asset data request upstream w/o valid upstream provider" << LL_ENDL; - if (callback) + request_list_t::iterator curiter = iter++; + LLAssetRequest* tmp = *curiter; + if (tmp->mDownCallback) { - callback(mVFS, uuid, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM); + tmp->mDownCallback(gAssetStorage->mVFS, callback_id, callback_type, tmp->mUserData, result_code, ext_status); } + delete tmp; } } - void LLAssetStorage::downloadCompleteCallback( S32 result, const LLUUID& file_id, LLAssetType::EType file_type, - void* user_data, LLExtStat ext_status) + LLBaseDownloadRequest* user_data, + LLExtStat ext_status) { LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << file_id << " downloadCompleteCallback" << LL_ENDL; @@ -603,73 +639,62 @@ void LLAssetStorage::downloadCompleteCallback( LLAssetRequest* req = (LLAssetRequest*)user_data; if(!req) { - LL_WARNS() << "LLAssetStorage::downloadCompleteCallback called without" + LL_WARNS("AssetStorage") << "LLAssetStorage::downloadCompleteCallback called without" "a valid request." << LL_ENDL; return; } if (!gAssetStorage) { - LL_WARNS() << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << LL_ENDL; + LL_WARNS("AssetStorage") << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << LL_ENDL; return; } - // Inefficient since we're doing a find through a list that may have thousands of elements. + LLUUID callback_id; + LLAssetType::EType callback_type; + + // Inefficient since we're doing a find through a list that may have thousands of elements. // This is due for refactoring; we will probably change mPendingDownloads into a set. - request_list_t::iterator download_iter = std::find(gAssetStorage->mPendingDownloads.begin(), - gAssetStorage->mPendingDownloads.end(), - req); - // If the LLAssetRequest doesn't exist in the downloads queue, then it either has already been deleted - // by _cleanupRequests, or it's a transfer. - if (download_iter != gAssetStorage->mPendingDownloads.end()) + // use findRequest instead. Legacy asset download gets a COPY of the request, thus pointer comparisons wont work here. + LLAssetRequest* download_req = LLAssetStorage::findRequest(&gAssetStorage->mPendingDownloads, req->getType(), req->getUUID() ); + + if (download_req) { - req->setUUID(file_id); - req->setType(file_type); - } + callback_id = file_id; + callback_type = file_type; + } + else + { + // either has already been deleted by _cleanupRequests or it's a transfer. + callback_id = req->getUUID(); + callback_type = req->getType(); + } if (LL_ERR_NOERR == result) { // we might have gotten a zero-size file - LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType()); + LLVFile vfile(gAssetStorage->mVFS, callback_id, callback_type); if (vfile.getSize() <= 0) { - LL_WARNS() << "downloadCompleteCallback has non-existent or zero-size asset " << req->getUUID() << LL_ENDL; + LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset " << callback_id << LL_ENDL; result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE; vfile.remove(); } } - - // find and callback ALL pending requests for this UUID - // SJB: We process the callbacks in reverse order, I do not know if this is important, - // but I didn't want to mess with it. - request_list_t requests; - for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin(); - iter != gAssetStorage->mPendingDownloads.end(); ) - { - request_list_t::iterator curiter = iter++; - LLAssetRequest* tmp = *curiter; - if ((tmp->getUUID() == file_id) && (tmp->getType()== file_type)) - { - requests.push_front(tmp); - iter = gAssetStorage->mPendingDownloads.erase(curiter); - } - } - for (request_list_t::iterator iter = requests.begin(); - iter != requests.end(); ) - { - request_list_t::iterator curiter = iter++; - LLAssetRequest* tmp = *curiter; - if (tmp->mDownCallback) - { - tmp->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), tmp->mUserData, result, ext_status); - } - delete tmp; - } + + removeAndCallbackPendingDownloads(file_id, file_type, callback_id, callback_type, ext_status, result); } -void LLAssetStorage::getEstateAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id, - const LLUUID &asset_id, LLAssetType::EType atype, EstateAssetType etype, - LLGetAssetCallback callback, void *user_data, BOOL is_priority) +void LLAssetStorage::getEstateAsset( + const LLHost &object_sim, + const LLUUID &agent_id, + const LLUUID &session_id, + const LLUUID &asset_id, + LLAssetType::EType atype, + EstateAssetType etype, + LLGetAssetCallback callback, + void *user_data, + BOOL is_priority) { LL_DEBUGS() << "LLAssetStorage::getEstateAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << ", estatetype " << etype << LL_ENDL; @@ -710,7 +735,7 @@ void LLAssetStorage::getEstateAsset(const LLHost &object_sim, const LLUUID &agen { if (exists) { - LL_WARNS() << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << LL_ENDL; + LL_WARNS("AssetStorage") << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << LL_ENDL; file.remove(); } @@ -727,10 +752,10 @@ void LLAssetStorage::getEstateAsset(const LLHost &object_sim, const LLUUID &agen if (source_host.isOk()) { // stash the callback info so we can find it after we get the response message - LLEstateAssetRequest *req = new LLEstateAssetRequest(asset_id, atype, etype); - req->mDownCallback = callback; - req->mUserData = user_data; - req->mIsPriority = is_priority; + LLEstateAssetRequest req(asset_id, atype, etype); + req.mDownCallback = callback; + req.mUserData = user_data; + req.mIsPriority = is_priority; // send request message to our upstream data provider // Create a new asset transfer. @@ -750,7 +775,7 @@ void LLAssetStorage::getEstateAsset(const LLHost &object_sim, const LLUUID &agen else { // uh-oh, we shouldn't have gotten here - LL_WARNS() << "Attempt to move asset data request upstream w/o valid upstream provider" << LL_ENDL; + LL_WARNS("AssetStorage") << "Attempt to move asset data request upstream w/o valid upstream provider" << LL_ENDL; if (callback) { callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM); @@ -763,19 +788,19 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback( S32 result, const LLUUID& file_id, LLAssetType::EType file_type, - void* user_data, + LLBaseDownloadRequest* user_data, LLExtStat ext_status) { LLEstateAssetRequest *req = (LLEstateAssetRequest*)user_data; if(!req) { - LL_WARNS() << "LLAssetStorage::downloadEstateAssetCompleteCallback called" + LL_WARNS("AssetStorage") << "LLAssetStorage::downloadEstateAssetCompleteCallback called" " without a valid request." << LL_ENDL; return; } if (!gAssetStorage) { - LL_WARNS() << "LLAssetStorage::downloadEstateAssetCompleteCallback called" + LL_WARNS("AssetStorage") << "LLAssetStorage::downloadEstateAssetCompleteCallback called" " without any asset system, aborting!" << LL_ENDL; return; } @@ -788,7 +813,7 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback( LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getAType()); if (vfile.getSize() <= 0) { - LL_WARNS() << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL; + LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL; result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE; vfile.remove(); @@ -798,26 +823,21 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback( req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getAType(), req->mUserData, result, ext_status); } -void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id, - const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id, - const LLUUID &asset_id, LLAssetType::EType atype, - LLGetAssetCallback callback, void *user_data, BOOL is_priority) +void LLAssetStorage::getInvItemAsset( + const LLHost &object_sim, + const LLUUID &agent_id, + const LLUUID &session_id, + const LLUUID &owner_id, + const LLUUID &task_id, + const LLUUID &item_id, + const LLUUID &asset_id, + LLAssetType::EType atype, + LLGetAssetCallback callback, + void *user_data, + BOOL is_priority) { LL_DEBUGS() << "LLAssetStorage::getInvItemAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << LL_ENDL; - // - // Probably will get rid of this early out? - // - //if (asset_id.isNull()) - //{ - // // Special case early out for NULL uuid - // if (callback) - // { - // callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE); - // } - // return; - //} - bool exists = false; U32 size = 0; @@ -834,7 +854,7 @@ void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &age size = exists ? file.getSize() : 0; if(exists && size < 1) { - LL_WARNS() << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << LL_ENDL; + LL_WARNS("AssetStorage") << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << LL_ENDL; file.remove(); } @@ -866,10 +886,10 @@ void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &age if (source_host.isOk()) { // stash the callback info so we can find it after we get the response message - LLInvItemRequest *req = new LLInvItemRequest(asset_id, atype); - req->mDownCallback = callback; - req->mUserData = user_data; - req->mIsPriority = is_priority; + LLInvItemRequest req(asset_id, atype); + req.mDownCallback = callback; + req.mUserData = user_data; + req.mIsPriority = is_priority; // send request message to our upstream data provider // Create a new asset transfer. @@ -892,7 +912,7 @@ void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &age else { // uh-oh, we shouldn't have gotten here - LL_WARNS() << "Attempt to move asset data request upstream w/o valid upstream provider" << LL_ENDL; + LL_WARNS("AssetStorage") << "Attempt to move asset data request upstream w/o valid upstream provider" << LL_ENDL; if (callback) { callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM); @@ -906,19 +926,19 @@ void LLAssetStorage::downloadInvItemCompleteCallback( S32 result, const LLUUID& file_id, LLAssetType::EType file_type, - void* user_data, + LLBaseDownloadRequest* user_data, LLExtStat ext_status) { LLInvItemRequest *req = (LLInvItemRequest*)user_data; if(!req) { - LL_WARNS() << "LLAssetStorage::downloadEstateAssetCompleteCallback called" + LL_WARNS("AssetStorage") << "LLAssetStorage::downloadEstateAssetCompleteCallback called" " without a valid request." << LL_ENDL; return; } if (!gAssetStorage) { - LL_WARNS() << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << LL_ENDL; + LL_WARNS("AssetStorage") << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << LL_ENDL; return; } @@ -930,7 +950,7 @@ void LLAssetStorage::downloadInvItemCompleteCallback( LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType()); if (vfile.getSize() <= 0) { - LL_WARNS() << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL; + LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL; result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE; vfile.remove(); @@ -945,11 +965,15 @@ void LLAssetStorage::downloadInvItemCompleteCallback( ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // static -void LLAssetStorage::uploadCompleteCallback(const LLUUID& uuid, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed) +void LLAssetStorage::uploadCompleteCallback( + const LLUUID& uuid, + void *user_data, + S32 result, + LLExtStat ext_status) // StoreAssetData callback (fixed) { if (!gAssetStorage) { - LL_WARNS() << "LLAssetStorage::uploadCompleteCallback has no gAssetStorage!" << LL_ENDL; + LL_WARNS("AssetStorage") << "LLAssetStorage::uploadCompleteCallback has no gAssetStorage!" << LL_ENDL; return; } LLAssetRequest *req = (LLAssetRequest *)user_data; @@ -957,7 +981,7 @@ void LLAssetStorage::uploadCompleteCallback(const LLUUID& uuid, void *user_data, if (result) { - LL_WARNS() << "LLAssetStorage::uploadCompleteCallback " << result << ":" << getErrorString(result) << " trying to upload file to upstream provider" << LL_ENDL; + LL_WARNS("AssetStorage") << "LLAssetStorage::uploadCompleteCallback " << result << ":" << getErrorString(result) << " trying to upload file to upstream provider" << LL_ENDL; success = FALSE; } @@ -1039,7 +1063,7 @@ LLAssetStorage::request_list_t* LLAssetStorage::getRequestList(LLAssetStorage::E case RT_LOCALUPLOAD: return &mPendingLocalUploads; default: - LL_WARNS() << "Unable to find request list for request type '" << rt << "'" << LL_ENDL; + LL_WARNS("AssetStorage") << "Unable to find request list for request type '" << rt << "'" << LL_ENDL; return NULL; } } @@ -1055,7 +1079,7 @@ const LLAssetStorage::request_list_t* LLAssetStorage::getRequestList(LLAssetStor case RT_LOCALUPLOAD: return &mPendingLocalUploads; default: - LL_WARNS() << "Unable to find request list for request type '" << rt << "'" << LL_ENDL; + LL_WARNS("AssetStorage") << "Unable to find request list for request type '" << rt << "'" << LL_ENDL; return NULL; } } @@ -1072,7 +1096,7 @@ std::string LLAssetStorage::getRequestName(LLAssetStorage::ERequestType rt) case RT_LOCALUPLOAD: return "localupload"; default: - LL_WARNS() << "Unable to find request name for request type '" << rt << "'" << LL_ENDL; + LL_WARNS("AssetStorage") << "Unable to find request name for request type '" << rt << "'" << LL_ENDL; return ""; } } @@ -1303,18 +1327,28 @@ const char* LLAssetStorage::getErrorString(S32 status) } } - - -void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, void (*callback)(const char*, const LLUUID&, void *, S32, LLExtStat), void *user_data, BOOL is_priority) +void LLAssetStorage::getAssetData(const LLUUID uuid, + LLAssetType::EType type, + void (*callback)(const char*, + const LLUUID&, + void *, + S32, + LLExtStat), +void *user_data, +BOOL is_priority) { // check for duplicates here, since we're about to fool the normal duplicate checker for (request_list_t::iterator iter = mPendingDownloads.begin(); iter != mPendingDownloads.end(); ) { LLAssetRequest* tmp = *iter++; + + //void(*const* cbptr)(LLVFS *, const LLUUID &, LLAssetType::EType, void *, S32, LLExtStat) + auto cbptr = tmp->mDownCallback.target(); + if (type == tmp->getType() && uuid == tmp->getUUID() && - legacyGetDataCallback == tmp->mDownCallback && + (cbptr && (*cbptr == legacyGetDataCallback)) && callback == ((LLLegacyAssetRequest *)tmp->mUserData)->mDownCallback && user_data == ((LLLegacyAssetRequest *)tmp->mUserData)->mUserData) { @@ -1335,7 +1369,12 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, vo } // static -void LLAssetStorage::legacyGetDataCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 status, LLExtStat ext_status) +void LLAssetStorage::legacyGetDataCallback(LLVFS *vfs, + const LLUUID &uuid, + LLAssetType::EType type, + void *user_data, + S32 status, + LLExtStat ext_status) { LLLegacyAssetRequest *legacy = (LLLegacyAssetRequest *)user_data; std::string filename; @@ -1379,78 +1418,6 @@ void LLAssetStorage::legacyGetDataCallback(LLVFS *vfs, const LLUUID &uuid, LLAss delete legacy; } -// this is overridden on the viewer and the sim, so it doesn't really do anything -// virtual -void LLAssetStorage::storeAssetData( - const LLTransactionID& tid, - LLAssetType::EType asset_type, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file, - bool is_priority, - bool store_local, - bool user_waiting, - F64 timeout) -{ - LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL; - // LLAssetStorage metric: Virtual base call - reportMetric( LLUUID::null, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 1" ); -} - -// virtual -// this does nothing, viewer and sim both override this. -void LLAssetStorage::storeAssetData( - const LLUUID& asset_id, - LLAssetType::EType asset_type, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file , - bool is_priority, - bool store_local, - const LLUUID& requesting_agent_id, - bool user_waiting, - F64 timeout) -{ - LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL; - // LLAssetStorage metric: Virtual base call - reportMetric( asset_id, asset_type, LLStringUtil::null, requesting_agent_id, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 2" ); -} - -// virtual -// this does nothing, viewer and sim both override this. -void LLAssetStorage::storeAssetData( - const std::string& filename, - const LLUUID& asset_id, - LLAssetType::EType asset_type, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file, - bool is_priority, - bool user_waiting, - F64 timeout) -{ - LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL; - // LLAssetStorage metric: Virtual base call - reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 3" ); -} - -// virtual -// this does nothing, viewer and sim both override this. -void LLAssetStorage::storeAssetData( - const std::string& filename, - const LLTransactionID &transactoin_id, - LLAssetType::EType asset_type, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file, - bool is_priority, - bool user_waiting, - F64 timeout) -{ - LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL; - // LLAssetStorage metric: Virtual base call - reportMetric( LLUUID::null, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 4" ); -} // static void LLAssetStorage::legacyStoreDataCallback(const LLUUID &uuid, void *user_data, S32 status, LLExtStat ext_status) @@ -1463,38 +1430,6 @@ void LLAssetStorage::legacyStoreDataCallback(const LLUUID &uuid, void *user_data delete legacy; } -// virtual -void LLAssetStorage::addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name) -{ } - -// virtual -BOOL LLAssetStorage::hasTempAssetData(const LLUUID& texture_id) const -{ return FALSE; } - -// virtual -std::string LLAssetStorage::getTempAssetHostName(const LLUUID& texture_id) const -{ return std::string(); } - -// virtual -LLUUID LLAssetStorage::getTempAssetAgentID(const LLUUID& texture_id) const -{ return LLUUID::null; } - -// virtual -void LLAssetStorage::removeTempAssetData(const LLUUID& asset_id) -{ } - -// virtual -void LLAssetStorage::removeTempAssetDataByAgentID(const LLUUID& agent_id) -{ } - -// virtual -void LLAssetStorage::dumpTempAssetData(const LLUUID& avatar_id) const -{ } - -// virtual -void LLAssetStorage::clearTempAssetData() -{ } - // static void LLAssetStorage::reportMetric( const LLUUID& asset_id, const LLAssetType::EType asset_type, const std::string& in_filename, const LLUUID& agent_id, S32 asset_size, EMetricResult result, diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h index 755d0a2078..0e29d9207e 100644 --- a/indra/llmessage/llassetstorage.h +++ b/indra/llmessage/llassetstorage.h @@ -29,6 +29,7 @@ #define LL_LLASSETSTORAGE_H #include +#include #include "lluuid.h" #include "lltimer.h" @@ -49,7 +50,8 @@ class LLSD; // anything that takes longer than this to download will abort. // HTTP Uploads also timeout if they take longer than this. -const F32 LL_ASSET_STORAGE_TIMEOUT = 5 * 60.0f; +const F32Minutes LL_ASSET_STORAGE_TIMEOUT(5); + // Specific error codes const int LL_ERR_ASSET_REQUEST_FAILED = -1; @@ -59,6 +61,14 @@ const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4; const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5; const int LL_ERR_PRICE_MISMATCH = -23018; +// *TODO: these typedefs are passed into the VFS via a legacy C function pointer +// future project would be to convert these to C++ callables (std::function<>) so that +// we can use bind and remove the userData parameter. +// +typedef std::function LLGetAssetCallback; +typedef std::function LLStoreAssetCallback; + + class LLAssetInfo { protected: @@ -91,38 +101,54 @@ class LLAssetInfo }; -class LLAssetRequest +class LLBaseDownloadRequest { public: - LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType at); - virtual ~LLAssetRequest(); - + LLBaseDownloadRequest(const LLUUID &uuid, const LLAssetType::EType at); + virtual ~LLBaseDownloadRequest(); + LLUUID getUUID() const { return mUUID; } LLAssetType::EType getType() const { return mType; } void setUUID(const LLUUID& id) { mUUID = id; } void setType(LLAssetType::EType type) { mType = type; } - void setTimeout (F64 timeout) { mTimeout = timeout; } + + virtual LLBaseDownloadRequest* getCopy(); protected: LLUUID mUUID; LLAssetType::EType mType; public: - void (*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat); - void (*mUpCallback)(const LLUUID&, void *, S32, LLExtStat); - void (*mInfoCallback)(LLAssetInfo *, void *, S32); + LLGetAssetCallback mDownCallback; +// void(*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat); void *mUserData; LLHost mHost; BOOL mIsTemp; - BOOL mIsLocal; - BOOL mIsUserWaiting; // We don't want to try forever if a user is waiting for a result. - F64 mTime; // Message system time - F64 mTimeout; // Amount of time before timing out. + F64Seconds mTime; // Message system time BOOL mIsPriority; BOOL mDataSentInFirstPacket; BOOL mDataIsInVFS; +}; + +class LLAssetRequest : public LLBaseDownloadRequest +{ +public: + LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType at); + virtual ~LLAssetRequest(); + + void setTimeout(F64Seconds timeout) { mTimeout = timeout; } + + virtual LLBaseDownloadRequest* getCopy(); + + LLStoreAssetCallback mUpCallback; +// void (*mUpCallback)(const LLUUID&, void *, S32, LLExtStat); + void (*mInfoCallback)(LLAssetInfo *, void *, S32); + + BOOL mIsLocal; + BOOL mIsUserWaiting; // We don't want to try forever if a user is waiting for a result. + F64Seconds mTimeout; // Amount of time before timing out. LLUUID mRequestingAgentID; // Only valid for uploads from an agent virtual LLSD getTerseDetails() const; @@ -140,88 +166,43 @@ struct ll_asset_request_equal : public std::equal_to }; -class LLInvItemRequest +class LLInvItemRequest : public LLBaseDownloadRequest { public: LLInvItemRequest(const LLUUID &uuid, const LLAssetType::EType at); virtual ~LLInvItemRequest(); - LLUUID getUUID() const { return mUUID; } - LLAssetType::EType getType() const { return mType; } - - void setUUID(const LLUUID& id) { mUUID = id; } - void setType(LLAssetType::EType type) { mType = type; } - -protected: - LLUUID mUUID; - LLAssetType::EType mType; - -public: - void (*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat); - - void *mUserData; - LLHost mHost; - BOOL mIsTemp; - F64 mTime; // Message system time - BOOL mIsPriority; - BOOL mDataSentInFirstPacket; - BOOL mDataIsInVFS; - + virtual LLBaseDownloadRequest* getCopy(); }; -class LLEstateAssetRequest +class LLEstateAssetRequest : public LLBaseDownloadRequest { public: LLEstateAssetRequest(const LLUUID &uuid, const LLAssetType::EType at, EstateAssetType et); virtual ~LLEstateAssetRequest(); - LLUUID getUUID() const { return mUUID; } - LLAssetType::EType getAType() const { return mAType; } + LLAssetType::EType getAType() const { return mType; } - void setUUID(const LLUUID& id) { mUUID = id; } - void setType(LLAssetType::EType type) { mAType = type; } + virtual LLBaseDownloadRequest* getCopy(); protected: - LLUUID mUUID; - LLAssetType::EType mAType; EstateAssetType mEstateAssetType; - -public: - void (*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat); - - void *mUserData; - LLHost mHost; - BOOL mIsTemp; - F64 mTime; // Message system time - BOOL mIsPriority; - BOOL mDataSentInFirstPacket; - BOOL mDataIsInVFS; - }; // Map of known bad assets typedef std::map toxic_asset_map_t; -typedef void (*LLGetAssetCallback)(LLVFS *vfs, const LLUUID &asset_id, - LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status); -class LLTempAssetStorage -{ -public: - virtual ~LLTempAssetStorage() =0; - virtual void addTempAssetData(const LLUUID& asset_id, - const LLUUID& agent_id, - const std::string& host_name) = 0; -}; -class LLAssetStorage : public LLTempAssetStorage +class LLAssetStorage { public: // VFS member is public because static child methods need it :( LLVFS *mVFS; LLVFS *mStaticVFS; - typedef void (*LLStoreAssetCallback)(const LLUUID &asset_id, void *user_data, S32 status, LLExtStat ext_status); + typedef ::LLStoreAssetCallback LLStoreAssetCallback; + typedef ::LLGetAssetCallback LLGetAssetCallback; enum ERequestType { @@ -262,14 +243,13 @@ class LLAssetStorage : public LLTempAssetStorage return mUpstreamHost.isOk(); } - virtual BOOL hasLocalAsset(const LLUUID &uuid, LLAssetType::EType type); + BOOL hasLocalAsset(const LLUUID &uuid, LLAssetType::EType type); // public interface methods // note that your callback may get called BEFORE the function returns - - virtual void getAssetData(const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback cb, void *user_data, BOOL is_priority = FALSE); + void getAssetData(const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback cb, void *user_data, BOOL is_priority = FALSE); - std::vector mBlackListedAsset; + uuid_vec_t mBlackListedAsset; /* * TransactionID version @@ -284,25 +264,10 @@ class LLAssetStorage : public LLTempAssetStorage bool is_priority = false, bool store_local = false, bool user_waiting= false, - F64 timeout=LL_ASSET_STORAGE_TIMEOUT); + F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT) = 0; - /* - * AssetID version - * Sim needs both store_local and requesting_agent_id. - */ - virtual void storeAssetData( - const LLUUID& asset_id, - LLAssetType::EType asset_type, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file = false, - bool is_priority = false, - bool store_local = false, - const LLUUID& requesting_agent_id = LLUUID::null, - bool user_waiting= false, - F64 timeout=LL_ASSET_STORAGE_TIMEOUT); - virtual void checkForTimeouts(); + void checkForTimeouts(); void getEstateAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id, const LLUUID &asset_id, LLAssetType::EType atype, EstateAssetType etype, @@ -327,15 +292,15 @@ class LLAssetStorage : public LLTempAssetStorage bool findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type, LLGetAssetCallback callback, void *user_data); - virtual LLSD getPendingDetailsImpl(const request_list_t* requests, + LLSD getPendingDetailsImpl(const request_list_t* requests, LLAssetType::EType asset_type, const std::string& detail_prefix) const; - virtual LLSD getPendingRequestImpl(const request_list_t* requests, + LLSD getPendingRequestImpl(const request_list_t* requests, LLAssetType::EType asset_type, const LLUUID& asset_id) const; - virtual bool deletePendingRequestImpl(request_list_t* requests, + bool deletePendingRequestImpl(request_list_t* requests, LLAssetType::EType asset_type, const LLUUID& asset_id); @@ -356,35 +321,39 @@ class LLAssetStorage : public LLTempAssetStorage S32 getNumPendingLocalUploads(); S32 getNumPending(ERequestType rt) const; - virtual LLSD getPendingDetails(ERequestType rt, + LLSD getPendingDetails(ERequestType rt, LLAssetType::EType asset_type, const std::string& detail_prefix) const; - virtual LLSD getPendingRequest(ERequestType rt, + LLSD getPendingRequest(ERequestType rt, LLAssetType::EType asset_type, const LLUUID& asset_id) const; - virtual bool deletePendingRequest(ERequestType rt, + bool deletePendingRequest(ERequestType rt, LLAssetType::EType asset_type, const LLUUID& asset_id); + static void removeAndCallbackPendingDownloads( const LLUUID& file_id, LLAssetType::EType file_type, + const LLUUID& callback_id, LLAssetType::EType callback_type, + S32 result_code, LLExtStat ext_status); + // download process callbacks static void downloadCompleteCallback( S32 result, const LLUUID& file_id, LLAssetType::EType file_type, - void* user_data, LLExtStat ext_status); + LLBaseDownloadRequest* user_data, LLExtStat ext_status); static void downloadEstateAssetCompleteCallback( S32 result, const LLUUID& file_id, LLAssetType::EType file_type, - void* user_data, LLExtStat ext_status); + LLBaseDownloadRequest* user_data, LLExtStat ext_status); static void downloadInvItemCompleteCallback( S32 result, const LLUUID& file_id, LLAssetType::EType file_type, - void* user_data, LLExtStat ext_status); + LLBaseDownloadRequest* user_data, LLExtStat ext_status); // upload process callbacks static void uploadCompleteCallback(const LLUUID&, void *user_data, S32 result, LLExtStat ext_status); @@ -396,20 +365,6 @@ class LLAssetStorage : public LLTempAssetStorage // deprecated file-based methods void getAssetData(const LLUUID uuid, LLAssetType::EType type, void (*callback)(const char*, const LLUUID&, void *, S32, LLExtStat), void *user_data, BOOL is_priority = FALSE); - /* - * AssetID version. - */ - virtual void storeAssetData( - const std::string& filename, - const LLUUID& asset_id, - LLAssetType::EType type, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file = false, - bool is_priority = false, - bool user_waiting = false, - F64 timeout = LL_ASSET_STORAGE_TIMEOUT); - /* * TransactionID version */ @@ -422,33 +377,21 @@ class LLAssetStorage : public LLTempAssetStorage bool temp_file = false, bool is_priority = false, bool user_waiting = false, - F64 timeout = LL_ASSET_STORAGE_TIMEOUT); + F64Seconds timeout = LL_ASSET_STORAGE_TIMEOUT) = 0; static void legacyGetDataCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType, void *user_data, S32 status, LLExtStat ext_status); static void legacyStoreDataCallback(const LLUUID &uuid, void *user_data, S32 status, LLExtStat ext_status); - // Temp assets are stored on sim nodes, they have agent ID and location data associated with them. - // This is a no-op for non-http asset systems - virtual void addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name); - virtual BOOL hasTempAssetData(const LLUUID& texture_id) const; - virtual std::string getTempAssetHostName(const LLUUID& texture_id) const; - virtual LLUUID getTempAssetAgentID(const LLUUID& texture_id) const; - virtual void removeTempAssetData(const LLUUID& asset_id); - virtual void removeTempAssetDataByAgentID(const LLUUID& agent_id); - // Pass LLUUID::null for all - virtual void dumpTempAssetData(const LLUUID& avatar_id) const; - virtual void clearTempAssetData(); - // add extra methods to handle metadata protected: void _cleanupRequests(BOOL all, S32 error); void _callUploadCallbacks(const LLUUID &uuid, const LLAssetType::EType asset_type, BOOL success, LLExtStat ext_status); - virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, - void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), + virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, LLGetAssetCallback callback, +// void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), void *user_data, BOOL duplicate, - BOOL is_priority); + BOOL is_priority) = 0; private: void _init(LLMessageSystem *msg, @@ -492,7 +435,7 @@ class LLLegacyAssetRequest { public: void (*mDownCallback)(const char *, const LLUUID&, void *, S32, LLExtStat); - LLAssetStorage::LLStoreAssetCallback mUpCallback; + LLStoreAssetCallback mUpCallback; void *mUserData; }; diff --git a/indra/llmessage/llavatarname.cpp b/indra/llmessage/llavatarname.cpp index fdcfed1613..a02d7c012d 100644 --- a/indra/llmessage/llavatarname.cpp +++ b/indra/llmessage/llavatarname.cpp @@ -139,7 +139,7 @@ void LLAvatarName::fromString(const std::string& full_name) mLegacyLastName = full_name.substr(index+1); if (mLegacyLastName != "Resident") { - mUsername = mLegacyFirstName + "." + mLegacyLastName; + mUsername = mLegacyFirstName + '.' + mLegacyLastName; mDisplayName = full_name; LLStringUtil::toLower(mUsername); } @@ -184,7 +184,7 @@ std::string LLAvatarName::getCompleteName(bool linefeed) const name = mDisplayName; if (sUseUsernames) { - name += (linefeed ? "\n(" : " (") + mUsername + ")"; + name += (linefeed ? "\n(" : " (") + mUsername + ')'; } } } @@ -238,7 +238,7 @@ std::string LLAvatarName::getUserName() const } else { - name = mLegacyFirstName + " " + mLegacyLastName; + name = mLegacyFirstName + ' ' + mLegacyLastName; } return name; } diff --git a/indra/llmessage/llavatarname.h b/indra/llmessage/llavatarname.h index 5902d34d86..4f0df57cc1 100644 --- a/indra/llmessage/llavatarname.h +++ b/indra/llmessage/llavatarname.h @@ -94,7 +94,7 @@ class LLAvatarName { case 1 : return getCompleteName(); case 2 : return getDisplayName(); - case 3 : return getLegacyName() + (mIsDisplayNameDefault ? "" : " (" + mDisplayName + ")"); break; + case 3 : return getLegacyName() + (mIsDisplayNameDefault ? "" : " (" + mDisplayName + ')'); break; default : return getLegacyName(); } } diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 83e3768585..9fb2c978bf 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -64,7 +64,7 @@ namespace LLAvatarNameCache std::string sNameLookupURL; // Accumulated agent IDs for next query against service - typedef std::set ask_queue_t; + typedef uuid_set_t ask_queue_t; ask_queue_t sAskQueue; // Agent IDs that have been requested, but with no reply. @@ -175,14 +175,14 @@ class LLAvatarNameResponder : public LLHTTPClient::ResponderWithResult private: // need to store agent ids that are part of this request in case of // an error, so we can flag them as unavailable - std::vector mAgentIDs; + uuid_vec_t mAgentIDs; // Need the headers to look up Expires: and Retry-After: /*virtual*/ bool needsHeaders() const { return true; } /*virtual*/ char const* getName() const { return "LLAvatarNameResponder"; } public: - LLAvatarNameResponder(const std::vector& agent_ids) + LLAvatarNameResponder(const uuid_vec_t& agent_ids) : mAgentIDs(agent_ids) { } @@ -253,7 +253,7 @@ class LLAvatarNameResponder : public LLHTTPClient::ResponderWithResult LL_WARNS("AvNameCache") << dumpResponse() << LL_ENDL; // Add dummy records for any agent IDs in this request that we do not have cached already - std::vector::const_iterator it = mAgentIDs.begin(); + auto it = mAgentIDs.begin(); for ( ; it != mAgentIDs.end(); ++it) { const LLUUID& agent_id = *it; @@ -327,7 +327,7 @@ void LLAvatarNameCache::requestNamesViaCapability() std::string url; url.reserve(NAME_URL_MAX); - std::vector agent_ids; + uuid_vec_t agent_ids; agent_ids.reserve(128); U32 ids = 0; @@ -335,7 +335,7 @@ void LLAvatarNameCache::requestNamesViaCapability() while(!sAskQueue.empty()) { it = sAskQueue.begin(); - const LLUUID& agent_id = *it; + const LLUUID agent_id = *it; sAskQueue.erase(it); if (url.empty()) @@ -365,9 +365,7 @@ void LLAvatarNameCache::requestNamesViaCapability() if (!url.empty()) { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability requested " - << ids << " ids" - << LL_ENDL; + LL_INFOS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability getting " << ids << " ids" << LL_ENDL; LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids)); } } @@ -391,8 +389,7 @@ void LLAvatarNameCache::legacyNameFetch(const LLUUID& agent_id, const std::string& full_name, bool is_group) { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::legacyNameFetch " - << "agent " << agent_id << " " + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache agent " << agent_id << " " << "full name '" << full_name << "'" << ( is_group ? " [group]" : "" ) << LL_ENDL; @@ -439,12 +436,13 @@ void LLAvatarNameCache::cleanupClass() sCache.clear(); } -void LLAvatarNameCache::importFile(std::istream& istr) +bool LLAvatarNameCache::importFile(std::istream& istr) { LLSD data; if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(data, istr)) { - return; + LL_WARNS("AvNameCache") << "avatar name cache data xml parse failed" << LL_ENDL; + return false; } // by convention LLSD storage is a map @@ -460,17 +458,19 @@ void LLAvatarNameCache::importFile(std::istream& istr) av_name.fromLLSD( it->second ); sCache[agent_id] = av_name; } - LL_INFOS("AvNameCache") << "loaded " << sCache.size() << LL_ENDL; - + LL_INFOS("AvNameCache") << "LLAvatarNameCache loaded " << sCache.size() << LL_ENDL; // Some entries may have expired since the cache was stored, // but they will be flushed in the first call to eraseUnrefreshed // from LLAvatarNameResponder::idle + + return true; } void LLAvatarNameCache::exportFile(std::ostream& ostr) { LLSD agents; F64 max_unrefreshed = LLFrameTimer::getTotalSeconds() - MAX_UNREFRESHED_TIME; + LL_INFOS("AvNameCache") << "LLAvatarNameCache at exit cache has " << sCache.size() << LL_ENDL; cache_t::const_iterator it = sCache.begin(); for ( ; it != sCache.end(); ++it) { @@ -483,6 +483,7 @@ void LLAvatarNameCache::exportFile(std::ostream& ostr) agents[agent_id.asString()] = av_name.asLLSD(); } } + LL_INFOS("AvNameCache") << "LLAvatarNameCache returning " << agents.size() << LL_ENDL; LLSD data; data["agents"] = agents; LLSDSerialize::toPrettyXML(data, ostr); @@ -525,6 +526,7 @@ void LLAvatarNameCache::idle() } else { + LL_WARNS_ONCE("AvNameCache") << "LLAvatarNameCache still using legacy api" << LL_ENDL; requestNamesViaLegacy(); } } @@ -562,24 +564,26 @@ void LLAvatarNameCache::eraseUnrefreshed() if (!sLastExpireCheck || sLastExpireCheck < max_unrefreshed) { sLastExpireCheck = now; - + S32 expired = 0; for (cache_t::iterator it = sCache.begin(); it != sCache.end();) { const LLAvatarName& av_name = it->second; if (av_name.mExpires < max_unrefreshed) { - LL_DEBUGS("AvNameCache") << it->first + LL_DEBUGS("AvNameCacheExpired") << "LLAvatarNameCache " << it->first << " user '" << av_name.getAccountName() << "' " << "expired " << now - av_name.mExpires << " secs ago" << LL_ENDL; sCache.erase(it++); + expired++; } else { ++it; } } - LL_INFOS("AvNameCache") << sCache.size() << " cached avatar names" << LL_ENDL; + LL_INFOS("AvNameCache") << "LLAvatarNameCache expired " << expired << " cached avatar names, " + << sCache.size() << " remaining" << LL_ENDL; } } @@ -600,8 +604,7 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) { if (!isRequestPending(agent_id)) { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::get " - << "refresh agent " << agent_id + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache refresh agent " << agent_id << LL_ENDL; sAskQueue.insert(agent_id); } @@ -623,9 +626,7 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) if (!isRequestPending(agent_id)) { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::get " - << "queue request for agent " << agent_id - << LL_ENDL; + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache queue request for agent " << agent_id << LL_ENDL; sAskQueue.insert(agent_id); } @@ -784,7 +785,7 @@ bool LLAvatarNameCache::expirationFromCacheControl(AIHTTPReceivedHeaders const& fromCacheControl = true; } } - LL_DEBUGS("AvNameCache") + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache " << ( fromCacheControl ? "expires based on cache control " : "default expiration " ) << "in " << *expires - now << " seconds" << LL_ENDL; diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index e80b3d0108..457adcfc11 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -46,7 +46,7 @@ namespace LLAvatarNameCache void cleanupClass(); // Import/export the name cache to file. - void importFile(std::istream& istr); + bool importFile(std::istream& istr); void exportFile(std::ostream& ostr); // On the viewer, usually a simulator capabilitity. diff --git a/indra/llmessage/llbuffer.h b/indra/llmessage/llbuffer.h index c7624bde30..b7b0fe0142 100644 --- a/indra/llmessage/llbuffer.h +++ b/indra/llmessage/llbuffer.h @@ -306,7 +306,7 @@ class LLBufferArray typedef std::list segment_list_t; typedef segment_list_t::const_iterator const_segment_iterator_t; typedef segment_list_t::iterator segment_iterator_t; - static size_t const npos = (size_t)-1; // (U8*)npos is used as a magic address. + enum { npos = 0xffffffff }; LLBufferArray(); ~LLBufferArray(); diff --git a/indra/llmessage/llbufferstream.cpp b/indra/llmessage/llbufferstream.cpp index ff1c9993cc..15e90872a4 100644 --- a/indra/llmessage/llbufferstream.cpp +++ b/indra/llmessage/llbufferstream.cpp @@ -233,17 +233,10 @@ int LLBufferStreamBuf::sync() } // virtual -#if( LL_WINDOWS || __GNUC__ > 2) LLBufferStreamBuf::pos_type LLBufferStreamBuf::seekoff( LLBufferStreamBuf::off_type off, std::ios::seekdir way, std::ios::openmode which) -#else -streampos LLBufferStreamBuf::seekoff( - streamoff off, - std::ios::seekdir way, - std::ios::openmode which) -#endif { if(!mBuffer || ((way == std::ios::beg) && (off < 0)) @@ -318,12 +311,8 @@ streampos LLBufferStreamBuf::seekoff( } } -#if( LL_WINDOWS || __GNUC__ > 2 ) S32 rv = (S32)(intptr_t)address; return (pos_type)rv; -#else - return (streampos)address; -#endif } diff --git a/indra/llmessage/llbufferstream.h b/indra/llmessage/llbufferstream.h index 723269307e..33ce6a68d6 100644 --- a/indra/llmessage/llbufferstream.h +++ b/indra/llmessage/llbufferstream.h @@ -48,10 +48,8 @@ class LLBufferStreamBuf : public std::streambuf virtual ~LLBufferStreamBuf(); protected: -#if( LL_WINDOWS || __GNUC__ > 2 ) typedef std::streambuf::pos_type pos_type; typedef std::streambuf::off_type off_type; -#endif /* @name streambuf vrtual implementations */ @@ -87,17 +85,10 @@ class LLBufferStreamBuf : public std::streambuf * or both masked together. * @return Returns the new position or an invalid position on failure. */ -#if( LL_WINDOWS || __GNUC__ > 2) virtual pos_type seekoff( off_type off, std::ios::seekdir way, std::ios::openmode which); -#else - virtual streampos seekoff( - streamoff off, - std::ios::seekdir way, - std::ios::openmode which); -#endif /* * @brief Get s sequence of characters from the input diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index eafb0ea974..6dfc69d6a2 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -185,7 +185,7 @@ void ReplySender::flush() } -typedef std::set AskQueue; +typedef uuid_set_t AskQueue; typedef std::list ReplyQueue; typedef std::map PendingQueue; typedef std::map Cache; @@ -262,6 +262,8 @@ LLCacheName::~LLCacheName() delete &impl; } +const ReverseCache& LLCacheName::getReverseMap() const { return impl.mReverseCache; } + LLCacheName::Impl::Impl(LLMessageSystem* msg) : mMsg(msg), mUpstreamHost(LLHost::invalid) { diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index 9acd76221f..58dcd3b4ef 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -57,6 +57,8 @@ class LLCacheName LLCacheName(LLMessageSystem* msg, const LLHost& upstream_host); ~LLCacheName(); + const std::map& getReverseMap() const; + // registers the upstream host // for viewers, this is the currently connected simulator // for simulators, this is the data server diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp index ada598a168..3043f61e6c 100644 --- a/indra/llmessage/llcircuit.cpp +++ b/indra/llmessage/llcircuit.cpp @@ -61,12 +61,12 @@ const S32 PING_START_BLOCK = 3; // How many pings behind we have to be to consider ourself blocked. const S32 PING_RELEASE_BLOCK = 2; // How many pings behind we have to be to consider ourself unblocked. -const F32 TARGET_PERIOD_LENGTH = 5.f; // seconds -const F32 LL_DUPLICATE_SUPPRESSION_TIMEOUT = 60.f; //seconds - this can be long, as time-based cleanup is +const F32Seconds TARGET_PERIOD_LENGTH(5.f); +const F32Seconds LL_DUPLICATE_SUPPRESSION_TIMEOUT(60.f); //this can be long, as time-based cleanup is // only done when wrapping packetids, now... LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id, - const F32 circuit_heartbeat_interval, const F32 circuit_timeout) + const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout) : mHost (host), mWrapID(0), mPacketsOutID(0), @@ -85,7 +85,7 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id, mPingsInTransit(0), mLastPingID(0), mPingDelay(INITIAL_PING_VALUE_MSEC), - mPingDelayAveraged((F32)INITIAL_PING_VALUE_MSEC), + mPingDelayAveraged(INITIAL_PING_VALUE_MSEC), mUnackedPacketCount(0), mUnackedPacketBytes(0), mLastPacketInTime(0.0), @@ -104,6 +104,7 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id, mPeakBPSOut(0.f), mPeriodTime(0.0), mExistenceTimer(), + mAckCreationTime(0.f), mCurrentResendCount(0), mLastPacketGap(0), mHeartbeatInterval(circuit_heartbeat_interval), @@ -111,13 +112,13 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id, { // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been // running a message system loop. - F64 mt_sec = LLMessageSystem::getMessageTimeSeconds(TRUE); + F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds(TRUE); F32 distribution_offset = ll_frand(); mPingTime = mt_sec; mLastPingSendTime = mt_sec + mHeartbeatInterval * distribution_offset; mLastPingReceivedTime = mt_sec; - mNextPingSendTime = mLastPingSendTime + 0.95*mHeartbeatInterval + ll_frand(0.1f*mHeartbeatInterval); + mNextPingSendTime = mLastPingSendTime + 0.95*mHeartbeatInterval + F32Seconds(ll_frand(0.1f*mHeartbeatInterval.value())); mPeriodTime = mt_sec; mLocalEndPointID.generate(); @@ -208,7 +209,7 @@ void LLCircuitData::ackReliablePacket(TPACKETID packet_num) } if (packetp->mCallback) { - if (packetp->mTimeout < 0.f) // negative timeout will always return timeout even for successful ack, for debugging + if (packetp->mTimeout < F32Seconds(0.f)) // negative timeout will always return timeout even for successful ack, for debugging { packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT); } @@ -242,7 +243,7 @@ void LLCircuitData::ackReliablePacket(TPACKETID packet_num) } if (packetp->mCallback) { - if (packetp->mTimeout < 0.f) // negative timeout will always return timeout even for successful ack, for debugging + if (packetp->mTimeout < F32Seconds(0.f)) // negative timeout will always return timeout even for successful ack, for debugging { packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT); } @@ -269,7 +270,7 @@ void LLCircuitData::ackReliablePacket(TPACKETID packet_num) -S32 LLCircuitData::resendUnackedPackets(const F64 now) +S32 LLCircuitData::resendUnackedPackets(const F64Seconds now) { S32 resent_packets = 0; LLReliablePacket *packetp; @@ -356,7 +357,7 @@ S32 LLCircuitData::resendUnackedPackets(const F64 now) // The new method, retry time based on ping if (packetp->mPingBasedRetry) { - packetp->mExpirationTime = now + llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, (LL_RELIABLE_TIMEOUT_FACTOR * getPingDelayAveraged())); + packetp->mExpirationTime = now + llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * getPingDelayAveraged())); } else { @@ -428,10 +429,11 @@ S32 LLCircuitData::resendUnackedPackets(const F64 now) } -LLCircuit::LLCircuit(const F32 circuit_heartbeat_interval, const F32 circuit_timeout) : mLastCircuit(NULL), - mHeartbeatInterval(circuit_heartbeat_interval), mHeartbeatTimeout(circuit_timeout) -{ -} +LLCircuit::LLCircuit(const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout) +: mLastCircuit(NULL), + mHeartbeatInterval(circuit_heartbeat_interval), + mHeartbeatTimeout(circuit_timeout) +{} LLCircuit::~LLCircuit() { @@ -522,17 +524,17 @@ void LLCircuitData::setAllowTimeout(BOOL allow) // Reset per-period counters if necessary. void LLCircuitData::checkPeriodTime() { - F64 mt_sec = LLMessageSystem::getMessageTimeSeconds(); - F64 period_length = mt_sec - mPeriodTime; + F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds(); + F64Seconds period_length = mt_sec - mPeriodTime; if ( period_length > TARGET_PERIOD_LENGTH) { - F32 bps_in = (F32)(mBytesInThisPeriod * 8.f / period_length); + F32 bps_in = F32Bits(mBytesInThisPeriod).value() / period_length.value(); if (bps_in > mPeakBPSIn) { mPeakBPSIn = bps_in; } - F32 bps_out = (F32)(mBytesOutThisPeriod * 8.f / period_length); + F32 bps_out = F32Bits(mBytesOutThisPeriod).value() / period_length.value(); if (bps_out > mPeakBPSOut) { mPeakBPSOut = bps_out; @@ -540,23 +542,23 @@ void LLCircuitData::checkPeriodTime() mBytesInLastPeriod = mBytesInThisPeriod; mBytesOutLastPeriod = mBytesOutThisPeriod; - mBytesInThisPeriod = 0; - mBytesOutThisPeriod = 0; - mLastPeriodLength = (F32)period_length; + mBytesInThisPeriod = S32Bytes(0); + mBytesOutThisPeriod = S32Bytes(0); + mLastPeriodLength = F32Seconds::convert(period_length); mPeriodTime = mt_sec; } } -void LLCircuitData::addBytesIn(S32 bytes) +void LLCircuitData::addBytesIn(S32Bytes bytes) { mBytesIn += bytes; mBytesInThisPeriod += bytes; } -void LLCircuitData::addBytesOut(S32 bytes) +void LLCircuitData::addBytesOut(S32Bytes bytes) { mBytesOut += bytes; mBytesOutThisPeriod += bytes; @@ -585,7 +587,7 @@ void LLCircuitData::addReliablePacket(S32 mSocket, U8 *buf_ptr, S32 buf_len, LLR void LLCircuit::resendUnackedPackets(S32& unacked_list_length, S32& unacked_list_size) { - F64 now = LLMessageSystem::getMessageTimeSeconds(); + F64Seconds now = LLMessageSystem::getMessageTimeSeconds(); unacked_list_length = 0; unacked_list_size = 0; @@ -727,7 +729,7 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent) } else if (!receive_resent) // don't freak out over out-of-order reliable resends { - U64 time = LLMessageSystem::getMessageTimeUsecs(); + U64Microseconds time = LLMessageSystem::getMessageTimeUsecs(); TPACKETID index = mPacketsInID; S32 gap_count = 0; if ((index < id) && ((id - index) < 16)) @@ -781,7 +783,7 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent) void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys) { - F64 cur_time = LLMessageSystem::getMessageTimeSeconds(); + F64Seconds cur_time = LLMessageSystem::getMessageTimeSeconds(); S32 count = mPingSet.size(); S32 cur = 0; @@ -819,7 +821,7 @@ void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys) if (cdp->updateWatchDogTimers(msgsys)) { // Randomize our pings a bit by doing some up to 5% early or late - F64 dt = 0.95f*mHeartbeatInterval + ll_frand(0.1f*mHeartbeatInterval); + F64Seconds dt = 0.95f*mHeartbeatInterval + F32Seconds(ll_frand(0.1f*mHeartbeatInterval.value())); // Remove it, and reinsert it with the new next ping time. // Always remove before changing the sorting key. @@ -847,7 +849,7 @@ void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys) BOOL LLCircuitData::updateWatchDogTimers(LLMessageSystem *msgsys) { - F64 cur_time = LLMessageSystem::getMessageTimeSeconds(); + F64Seconds cur_time = LLMessageSystem::getMessageTimeSeconds(); mLastPingSendTime = cur_time; if (!checkCircuitTimeout()) @@ -964,12 +966,12 @@ BOOL LLCircuitData::updateWatchDogTimers(LLMessageSystem *msgsys) // be considered lost LLCircuitData::packet_time_map::iterator it; - U64 timeout = (U64)(1000000.0*llmin(LL_MAX_LOST_TIMEOUT, getPingDelayAveraged() * LL_LOST_TIMEOUT_FACTOR)); + U64Microseconds timeout = llmin(LL_MAX_LOST_TIMEOUT, F32Seconds(getPingDelayAveraged()) * LL_LOST_TIMEOUT_FACTOR); - U64 mt_usec = LLMessageSystem::getMessageTimeUsecs(); + U64Microseconds mt_usec = LLMessageSystem::getMessageTimeUsecs(); for (it = mPotentialLostPackets.begin(); it != mPotentialLostPackets.end(); ) { - U64 delta_t_usec = mt_usec - (*it).second; + U64Microseconds delta_t_usec = mt_usec - (*it).second; if (delta_t_usec > timeout) { // let's call this one a loss! @@ -1015,7 +1017,7 @@ void LLCircuitData::clearDuplicateList(TPACKETID oldest_id) // Do timeout checks on everything with an ID > mHighestPacketID. // This should be empty except for wrapping IDs. Thus, this should be // highly rare. - U64 mt_usec = LLMessageSystem::getMessageTimeUsecs(); + U64Microseconds mt_usec = LLMessageSystem::getMessageTimeUsecs(); packet_time_map::iterator pit; for(pit = mRecentlyReceivedReliablePackets.upper_bound(mHighestPacketID); @@ -1026,8 +1028,8 @@ void LLCircuitData::clearDuplicateList(TPACKETID oldest_id) { LL_WARNS() << "Probably incorrectly timing out non-wrapped packets!" << LL_ENDL; } - U64 delta_t_usec = mt_usec - (*pit).second; - F64 delta_t_sec = delta_t_usec * SEC_PER_USEC; + U64Microseconds delta_t_usec = mt_usec - (*pit).second; + F64Seconds delta_t_sec = delta_t_usec; if (delta_t_sec > LL_DUPLICATE_SUPPRESSION_TIMEOUT) { // enough time has elapsed we're not likely to get a duplicate on this one @@ -1044,7 +1046,7 @@ void LLCircuitData::clearDuplicateList(TPACKETID oldest_id) BOOL LLCircuitData::checkCircuitTimeout() { - F64 time_since_last_ping = LLMessageSystem::getMessageTimeSeconds() - mLastPingReceivedTime; + F64Seconds time_since_last_ping = LLMessageSystem::getMessageTimeSeconds() - mLastPingReceivedTime; // Nota Bene: This needs to be turned off if you are debugging multiple simulators if (time_since_last_ping > mHeartbeatTimeout) @@ -1078,22 +1080,30 @@ BOOL LLCircuitData::collectRAck(TPACKETID packet_num) } mAcks.push_back(packet_num); + if (mAckCreationTime == 0) + { + mAckCreationTime = getAgeInSeconds(); + } return TRUE; } // this method is called during the message system processAcks() to // send out any acks that did not get sent already. -void LLCircuit::sendAcks() +void LLCircuit::sendAcks(F32 collect_time) { + collect_time = llclamp(collect_time, 0.f, LL_COLLECT_ACK_TIME_MAX); LLCircuitData* cd; - circuit_data_map::iterator end = mSendAckMap.end(); - for(circuit_data_map::iterator it = mSendAckMap.begin(); it != end; ++it) + circuit_data_map::iterator it = mSendAckMap.begin(); + while (it != mSendAckMap.end()) { - cd = (*it).second; - + circuit_data_map::iterator cur_it = it++; + cd = (*cur_it).second; S32 count = (S32)cd->mAcks.size(); - if(count > 0) + F32 age = cd->getAgeInSeconds() - cd->mAckCreationTime; + if (age > collect_time || count == 0) { + if (count>0) + { // send the packet acks S32 acks_this_packet = 0; for(S32 i = 0; i < count; ++i) @@ -1125,13 +1135,14 @@ void LLCircuit::sendAcks() LL_INFOS() << str.str() << LL_ENDL; } - // empty out the acks list - cd->mAcks.clear(); + // empty out the acks list + cd->mAcks.clear(); + cd->mAckCreationTime = 0.f; + } + // remove data map + mSendAckMap.erase(cur_it); } } - - // All acks have been sent, clear the map - mSendAckMap.clear(); } @@ -1140,40 +1151,40 @@ std::ostream& operator<<(std::ostream& s, LLCircuitData& circuit) F32 age = circuit.mExistenceTimer.getElapsedTimeF32(); using namespace std; - s << "Circuit " << circuit.mHost << " "; - s << circuit.mRemoteID << " "; - s << (circuit.mbAlive ? "Alive" : "Not Alive") << " "; - s << (circuit.mbAllowTimeout ? "Timeout Allowed" : "Timeout Not Allowed"); - s << endl; - - s << " Packets Lost: " << circuit.mPacketsLost; - s << " Measured Ping: " << circuit.mPingDelay; - s << " Averaged Ping: " << circuit.mPingDelayAveraged; - s << endl; - - s << "Global In/Out " << S32(age) << " sec"; - s << " KBytes: " << circuit.mBytesIn / 1024 << "/" << circuit.mBytesOut / 1024; - s << " Kbps: "; - s << S32(circuit.mBytesIn * 8.f / circuit.mExistenceTimer.getElapsedTimeF32() / 1024.f); - s << "/"; - s << S32(circuit.mBytesOut * 8.f / circuit.mExistenceTimer.getElapsedTimeF32() / 1024.f); - s << " Packets: " << circuit.mPacketsIn << "/" << circuit.mPacketsOut; - s << endl; - - s << "Recent In/Out " << S32(circuit.mLastPeriodLength) << " sec"; - s << " KBytes: "; - s << circuit.mBytesInLastPeriod / 1024; - s << "/"; - s << circuit.mBytesOutLastPeriod / 1024; - s << " Kbps: "; - s << S32(circuit.mBytesInLastPeriod * 8.f / circuit.mLastPeriodLength / 1024.f); - s << "/"; - s << S32(circuit.mBytesOutLastPeriod * 8.f / circuit.mLastPeriodLength / 1024.f); - s << " Peak kbps: "; - s << S32(circuit.mPeakBPSIn / 1024.f); - s << "/"; - s << S32(circuit.mPeakBPSOut / 1024.f); - s << endl; + s << "Circuit " << circuit.mHost << " " + << circuit.mRemoteID << " " + << (circuit.mbAlive ? "Alive" : "Not Alive") << " " + << (circuit.mbAllowTimeout ? "Timeout Allowed" : "Timeout Not Allowed") + << endl; + + s << " Packets Lost: " << circuit.mPacketsLost + << " Measured Ping: " << circuit.mPingDelay + << " Averaged Ping: " << circuit.mPingDelayAveraged + << endl; + + s << "Global In/Out " << S32(age) << " sec" + << " KBytes: " << circuit.mBytesIn.valueInUnits() << "/" << circuit.mBytesOut.valueInUnits() + << " Kbps: " + << S32(circuit.mBytesIn.valueInUnits() / circuit.mExistenceTimer.getElapsedTimeF32().value()) + << "/" + << S32(circuit.mBytesOut.valueInUnits() / circuit.mExistenceTimer.getElapsedTimeF32().value()) + << " Packets: " << circuit.mPacketsIn << "/" << circuit.mPacketsOut + << endl; + + s << "Recent In/Out " << circuit.mLastPeriodLength + << " KBytes: " + << circuit.mBytesInLastPeriod.valueInUnits() + << "/" + << circuit.mBytesOutLastPeriod.valueInUnits() + << " Kbps: " + << (S32)(circuit.mBytesInLastPeriod.valueInUnits() / circuit.mLastPeriodLength.value()) + << "/" + << (S32)(circuit.mBytesOutLastPeriod.valueInUnits() / circuit.mLastPeriodLength.value()) + << " Peak kbps: " + << S32(circuit.mPeakBPSIn / 1024.f) + << "/" + << S32(circuit.mPeakBPSOut / 1024.f) + << endl; return s; } @@ -1268,11 +1279,11 @@ void LLCircuitData::setPacketInID(TPACKETID id) void LLCircuitData::pingTimerStop(const U8 ping_id) { - F64 mt_secs = LLMessageSystem::getMessageTimeSeconds(); + F64Seconds mt_secs = LLMessageSystem::getMessageTimeSeconds(); // Nota Bene: no averaging of ping times until we get a feel for how this works - F64 time = mt_secs - mPingTime; - if (time == 0.0) + F64Seconds time = mt_secs - mPingTime; + if (time == F32Seconds(0.0)) { // Ack, we got our ping response on the same frame! Sigh, let's get a real time otherwise // all of our ping calculations will be skewed. @@ -1288,7 +1299,7 @@ void LLCircuitData::pingTimerStop(const U8 ping_id) delta_ping += 256; } - U32 msec = (U32) ((delta_ping*mHeartbeatInterval + time) * 1000.f); + U32Milliseconds msec = delta_ping*mHeartbeatInterval + time; setPingDelay(msec); mPingsInTransit = delta_ping; @@ -1317,13 +1328,13 @@ U32 LLCircuitData::getPacketsIn() const } -S32 LLCircuitData::getBytesIn() const +S32Bytes LLCircuitData::getBytesIn() const { return mBytesIn; } -S32 LLCircuitData::getBytesOut() const +S32Bytes LLCircuitData::getBytesOut() const { return mBytesOut; } @@ -1365,41 +1376,41 @@ BOOL LLCircuitData::getAllowTimeout() const } -U32 LLCircuitData::getPingDelay() const +U32Milliseconds LLCircuitData::getPingDelay() const { return mPingDelay; } -F32 LLCircuitData::getPingInTransitTime() +F32Milliseconds LLCircuitData::getPingInTransitTime() { // This may be inaccurate in the case of a circuit that was "dead" and then revived, // but only until the first round trip ping is sent - djs - F32 time_since_ping_was_sent = 0; + F32Milliseconds time_since_ping_was_sent(0); if (mPingsInTransit) { - time_since_ping_was_sent = (F32)((mPingsInTransit*mHeartbeatInterval - 1) - + (LLMessageSystem::getMessageTimeSeconds() - mPingTime))*1000.f; + time_since_ping_was_sent = F32Milliseconds::convert(((mPingsInTransit*mHeartbeatInterval - F32Seconds(1)) + + (LLMessageSystem::getMessageTimeSeconds() - mPingTime))); } return time_since_ping_was_sent; } -void LLCircuitData::setPingDelay(U32 ping) +void LLCircuitData::setPingDelay(U32Milliseconds ping) { mPingDelay = ping; - mPingDelayAveraged = llmax((F32)ping, getPingDelayAveraged()); + mPingDelayAveraged = llmax((F32Milliseconds)ping, getPingDelayAveraged()); mPingDelayAveraged = ((1.f - LL_AVERAGED_PING_ALPHA) * mPingDelayAveraged) - + (LL_AVERAGED_PING_ALPHA * (F32) ping); + + (LL_AVERAGED_PING_ALPHA * (F32Milliseconds) ping); mPingDelayAveraged = llclamp(mPingDelayAveraged, LL_AVERAGED_PING_MIN, LL_AVERAGED_PING_MAX); } -F32 LLCircuitData::getPingDelayAveraged() +F32Milliseconds LLCircuitData::getPingDelayAveraged() { return llmin(llmax(getPingInTransitTime(), mPingDelayAveraged), LL_AVERAGED_PING_MAX); } diff --git a/indra/llmessage/llcircuit.h b/indra/llmessage/llcircuit.h index ab9ebc2d8a..d3db967904 100644 --- a/indra/llmessage/llcircuit.h +++ b/indra/llmessage/llcircuit.h @@ -34,7 +34,6 @@ #include "llerror.h" #include "lltimer.h" -#include "timing.h" #include "net.h" #include "llhost.h" #include "llpacketack.h" @@ -45,10 +44,10 @@ // Constants // const F32 LL_AVERAGED_PING_ALPHA = 0.2f; // relaxation constant on ping running average -const F32 LL_AVERAGED_PING_MAX = 2000; // msec -const F32 LL_AVERAGED_PING_MIN = 100; // msec // IW: increased to avoid retransmits when a process is slow +const F32Milliseconds LL_AVERAGED_PING_MAX(2000); +const F32Milliseconds LL_AVERAGED_PING_MIN(100); // increased to avoid retransmits when a process is slow -const U32 INITIAL_PING_VALUE_MSEC = 1000; // initial value for the ping delay, or for ping delay for an unknown circuit +const U32Milliseconds INITIAL_PING_VALUE_MSEC(1000); // initial value for the ping delay, or for ping delay for an unknown circuit const TPACKETID LL_MAX_OUT_PACKET_ID = 0x01000000; const int LL_ERR_CIRCUIT_GONE = -23017; @@ -61,6 +60,7 @@ const U8 LL_PACKET_ID_SIZE = 6; const S32 LL_MAX_RESENT_PACKETS_PER_FRAME = 100; const S32 LL_MAX_ACKED_PACKETS_PER_FRAME = 200; +const F32 LL_COLLECT_ACK_TIME_MAX = 2.f; // // Prototypes and Predefines @@ -78,10 +78,10 @@ class LLCircuitData { public: LLCircuitData(const LLHost &host, TPACKETID in_id, - const F32 circuit_heartbeat_interval, const F32 circuit_timeout); + const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout); ~LLCircuitData(); - S32 resendUnackedPackets(const F64 now); + S32 resendUnackedPackets(const F64Seconds now); void clearDuplicateList(TPACKETID oldest_id); @@ -107,18 +107,18 @@ class LLCircuitData // mLocalEndPointID should only ever be setup in the LLCircuitData constructor const LLUUID& getLocalEndPointID() const { return mLocalEndPointID; } - U32 getPingDelay() const; + U32Milliseconds getPingDelay() const; S32 getPingsInTransit() const { return mPingsInTransit; } // ACCESSORS BOOL isAlive() const; BOOL isBlocked() const; BOOL getAllowTimeout() const; - F32 getPingDelayAveraged(); - F32 getPingInTransitTime(); + F32Milliseconds getPingDelayAveraged(); + F32Milliseconds getPingInTransitTime(); U32 getPacketsIn() const; - S32 getBytesIn() const; - S32 getBytesOut() const; + S32Bytes getBytesIn() const; + S32Bytes getBytesOut() const; U32 getPacketsOut() const; U32 getPacketsLost() const; TPACKETID getPacketOutID() const; @@ -126,10 +126,10 @@ class LLCircuitData F32 getAgeInSeconds() const; S32 getUnackedPacketCount() const { return mUnackedPacketCount; } S32 getUnackedPacketBytes() const { return mUnackedPacketBytes; } - F64 getNextPingSendTime() const { return mNextPingSendTime; } + F64Seconds getNextPingSendTime() const { return mNextPingSendTime; } U32 getLastPacketGap() const { return mLastPacketGap; } LLHost getHost() const { return mHost; } - F64 getLastPacketInTime() const { return mLastPacketInTime; } + F64Seconds getLastPacketInTime() const { return mLastPacketInTime; } LLThrottleGroup &getThrottleGroup() { return mThrottles; } @@ -165,11 +165,11 @@ class LLCircuitData TPACKETID nextPacketOutID(); void setPacketInID(TPACKETID id); void checkPacketInID(TPACKETID id, BOOL receive_resent); - void setPingDelay(U32 ping); + void setPingDelay(U32Milliseconds ping); BOOL checkCircuitTimeout(); // Return FALSE if the circuit is dead and should be cleaned up - void addBytesIn(S32 bytes); - void addBytesOut(S32 bytes); + void addBytesIn(S32Bytes bytes); + void addBytesOut(S32Bytes bytes); U8 nextPingID() { mLastPingID++; return mLastPingID; } @@ -220,24 +220,25 @@ class LLCircuitData BOOL mBlocked; // Blocked is true if the circuit is hosed, i.e. far behind on pings // Not sure what the difference between this and mLastPingSendTime is - F64 mPingTime; // Time at which a ping was sent. + F64Seconds mPingTime; // Time at which a ping was sent. - F64 mLastPingSendTime; // Time we last sent a ping - F64 mLastPingReceivedTime; // Time we last received a ping - F64 mNextPingSendTime; // Time to try and send the next ping - S32 mPingsInTransit; // Number of pings in transit - U8 mLastPingID; // ID of the last ping that we sent out + F64Seconds mLastPingSendTime; // Time we last sent a ping + F64Seconds mLastPingReceivedTime; // Time we last received a ping + F64Seconds mNextPingSendTime; // Time to try and send the next ping + S32 mPingsInTransit; // Number of pings in transit + U8 mLastPingID; // ID of the last ping that we sent out // Used for determining the resend time for reliable resends. - U32 mPingDelay; // raw ping delay - F32 mPingDelayAveraged; // averaged ping delay (fast attack/slow decay) + U32Milliseconds mPingDelay; // raw ping delay + F32Milliseconds mPingDelayAveraged; // averaged ping delay (fast attack/slow decay) - typedef std::map packet_time_map; + typedef std::map packet_time_map; packet_time_map mPotentialLostPackets; packet_time_map mRecentlyReceivedReliablePackets; std::vector mAcks; + F32 mAckCreationTime; // first ack creation time typedef std::map reliable_map; typedef reliable_map::iterator reliable_iter; @@ -248,7 +249,7 @@ class LLCircuitData S32 mUnackedPacketCount; S32 mUnackedPacketBytes; - F64 mLastPacketInTime; // Time of last packet arrival + F64Seconds mLastPacketInTime; // Time of last packet arrival LLUUID mLocalEndPointID; @@ -260,24 +261,24 @@ class LLCircuitData U32 mPacketsOut; U32 mPacketsIn; S32 mPacketsLost; - S32 mBytesIn; - S32 mBytesOut; - - F32 mLastPeriodLength; // seconds - S32 mBytesInLastPeriod; - S32 mBytesOutLastPeriod; - S32 mBytesInThisPeriod; - S32 mBytesOutThisPeriod; + S32Bytes mBytesIn, + mBytesOut; + + F32Seconds mLastPeriodLength; + S32Bytes mBytesInLastPeriod; + S32Bytes mBytesOutLastPeriod; + S32Bytes mBytesInThisPeriod; + S32Bytes mBytesOutThisPeriod; F32 mPeakBPSIn; // bits per second, max of all period bps F32 mPeakBPSOut; // bits per second, max of all period bps - F64 mPeriodTime; + F64Seconds mPeriodTime; LLTimer mExistenceTimer; // initialized when circuit created, used to track bandwidth numbers S32 mCurrentResendCount; // Number of resent packets since last spam U32 mLastPacketGap; // Gap in sequence number of last packet. - const F32 mHeartbeatInterval; - const F32 mHeartbeatTimeout; + const F32Seconds mHeartbeatInterval; + const F32Seconds mHeartbeatTimeout; }; @@ -287,7 +288,7 @@ class LLCircuit { public: // CREATORS - LLCircuit(const F32 circuit_heartbeat_interval, const F32 circuit_timeout); + LLCircuit(const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout); ~LLCircuit(); // ACCESSORS @@ -303,7 +304,7 @@ class LLCircuit // this method is called during the message system processAcks() // to send out any acks that did not get sent already. - void sendAcks(); + void sendAcks(F32 collect_time); friend std::ostream& operator<<(std::ostream& s, LLCircuit &circuit); void getInfo(LLSD& info) const; @@ -346,7 +347,7 @@ class LLCircuit mutable LLCircuitData* mLastCircuit; private: - const F32 mHeartbeatInterval; - const F32 mHeartbeatTimeout; + const F32Seconds mHeartbeatInterval; + const F32Seconds mHeartbeatTimeout; }; #endif diff --git a/indra/llmessage/llcororesponder.h b/indra/llmessage/llcororesponder.h new file mode 100644 index 0000000000..bacec85a89 --- /dev/null +++ b/indra/llmessage/llcororesponder.h @@ -0,0 +1,63 @@ +/** + * @file llcororesponder.h + * @brief A responder purposed to call coro functions, to ease transition to LLCoro + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * + * Copyright (C) 2020, Liru Færs + * + * 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 +#include "llhttpclient.h" + +struct LLCoroResponderBase : public LLHTTPClient::ResponderWithCompleted +{ + const AIHTTPReceivedHeaders& getHeaders() const { return mReceivedHeaders; } + const LLSD& getContent() const { return mContent; } + + char const* getName() const override final { return "LLCoroResponder"; } +protected: + LLCoroResponderBase() {} +}; + +struct LLCoroResponder final : public LLCoroResponderBase +{ + typedef std::function cb_t; + LLCoroResponder(const cb_t& cb) : mCB(cb) {} + void httpCompleted() override { mCB(*this); } +private: + const cb_t mCB; +}; + +struct LLCoroResponderRaw final : public LLCoroResponderBase +{ + typedef std::function cb_t; + LLCoroResponderRaw(const cb_t& cb) : mCB(cb) {} + void completedRaw(const LLChannelDescriptors& channels, const buffer_ptr_t& buffer) override + { + std::string content; + decode_raw_body(channels, buffer, content); + mCB(*this, content); + } +private: + const cb_t mCB; +}; + diff --git a/indra/llmessage/lldispatcher.cpp b/indra/llmessage/lldispatcher.cpp index 6f740346e0..ffcb68caee 100644 --- a/indra/llmessage/lldispatcher.cpp +++ b/indra/llmessage/lldispatcher.cpp @@ -29,6 +29,7 @@ #include "lldispatcher.h" #include +#include #include "llstl.h" #include "message.h" @@ -145,3 +146,25 @@ bool LLDispatcher::unpackMessage( } return true; } + +// static +bool LLDispatcher::unpackLargeMessage( + LLMessageSystem* msg, + LLDispatcher::key_t& method, + LLUUID& invoice, + LLDispatcher::sparam_t& parameters) +{ + msg->getStringFast(_PREHASH_MethodData, _PREHASH_Method, method); + msg->getUUIDFast(_PREHASH_MethodData, _PREHASH_Invoice, invoice); + S32 count = msg->getNumberOfBlocksFast(_PREHASH_ParamList); + for (S32 i = 0; i < count; ++i) + { + // This method treats all Parameter List params as strings and unpacks + // them regardless of length. If there is binary data it is the callers + // responsibility to decode it. + std::string param; + msg->getStringFast(_PREHASH_ParamList, _PREHASH_Parameter, param, i); + parameters.push_back(param); + } + return true; +} diff --git a/indra/llmessage/lldispatcher.h b/indra/llmessage/lldispatcher.h index 9d1751f588..43c63ac4df 100644 --- a/indra/llmessage/lldispatcher.h +++ b/indra/llmessage/lldispatcher.h @@ -105,6 +105,12 @@ class LLDispatcher LLUUID& invoice, sparam_t& parameters); + static bool unpackLargeMessage( + LLMessageSystem* msg, + key_t& method, + LLUUID& invoice, + sparam_t& parameters); + protected: typedef std::map dispatch_map_t; dispatch_map_t mHandlers; diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp new file mode 100644 index 0000000000..482b870910 --- /dev/null +++ b/indra/llmessage/llexperiencecache.cpp @@ -0,0 +1,921 @@ +/** + * @file llexperiencecache.cpp + * @brief llexperiencecache and related class definitions + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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 "llexperiencecache.h" + +#include "llavatarname.h" +#include "llcororesponder.h" +#include "llsdserialize.h" +#include "lleventfilter.h" +#include "lldir.h" +#include +#include +#include +#include +#include + +//========================================================================= +namespace LLExperienceCacheImpl +{ + void mapKeys(const LLSD& legacyKeys); + F64 getErrorRetryDeltaTime(S32 status, const AIHTTPReceivedHeaders& headers); + bool maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age); + + static const std::string PRIVATE_KEY = "private_id"; + static const std::string EXPERIENCE_ID = "public_id"; + + static const std::string MAX_AGE("max-age"); + static const boost::char_separator EQUALS_SEPARATOR("="); + static const boost::char_separator COMMA_SEPARATOR(","); + + // *TODO$: this seems to be tied to mapKeys which is used by bootstrap.... but I don't think that bootstrap is used. + typedef std::map KeyMap; + KeyMap privateToPublicKeyMap; +} + +//========================================================================= +const std::string LLExperienceCache::PRIVATE_KEY = "private_id"; +const std::string LLExperienceCache::MISSING = "DoesNotExist"; + +const std::string LLExperienceCache::AGENT_ID = "agent_id"; +const std::string LLExperienceCache::GROUP_ID = "group_id"; +const std::string LLExperienceCache::EXPERIENCE_ID = "public_id"; +const std::string LLExperienceCache::NAME = "name"; +const std::string LLExperienceCache::PROPERTIES = "properties"; +const std::string LLExperienceCache::EXPIRES = "expiration"; +const std::string LLExperienceCache::DESCRIPTION = "description"; +const std::string LLExperienceCache::QUOTA = "quota"; +const std::string LLExperienceCache::MATURITY = "maturity"; +const std::string LLExperienceCache::METADATA = "extended_metadata"; +const std::string LLExperienceCache::SLURL = "slurl"; + +// should be in sync with experience-api/experiences/models.py +const int LLExperienceCache::PROPERTY_INVALID = 1 << 0; +const int LLExperienceCache::PROPERTY_PRIVILEGED = 1 << 3; +const int LLExperienceCache::PROPERTY_GRID = 1 << 4; +const int LLExperienceCache::PROPERTY_PRIVATE = 1 << 5; +const int LLExperienceCache::PROPERTY_DISABLED = 1 << 6; +const int LLExperienceCache::PROPERTY_SUSPENDED = 1 << 7; + +// default values +const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0; +const S32 LLExperienceCache::DEFAULT_QUOTA = 128; // this is megabytes +const int LLExperienceCache::SEARCH_PAGE_SIZE = 30; + +//========================================================================= +LLExperienceCache::LLExperienceCache(): + mShutdown(false) +{ +} + +LLExperienceCache::~LLExperienceCache() +{ + +} + +void LLExperienceCache::initSingleton() +{ + mCacheFileName = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); + + LL_INFOS("ExperienceCache") << "Loading " << mCacheFileName << LL_ENDL; + llifstream cache_stream(mCacheFileName.c_str()); + + if (cache_stream.is_open()) + { + cache_stream >> (*this); + } +} + +void LLExperienceCache::cleanup() +{ + LL_INFOS("ExperienceCache") << "Saving " << mCacheFileName << LL_ENDL; + + llofstream cache_stream(mCacheFileName.c_str()); + if (cache_stream.is_open()) + { + cache_stream << (*this); + } + mShutdown = true; +} + +//------------------------------------------------------------------------- +void LLExperienceCache::importFile(std::istream& istr) +{ + LLSD data; + S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr); + if (parse_count < 1) return; + + LLSD experiences = data["experiences"]; + + LLUUID public_key; + for (const auto& it : experiences.map()) + { + public_key.set(it.first); + mCache[public_key] = it.second; + } + + LL_DEBUGS("ExperienceCache") << "importFile() loaded " << mCache.size() << LL_ENDL; +} + +void LLExperienceCache::exportFile(std::ostream& ostr) const +{ + LLSD experiences; + + cache_t::const_iterator it = mCache.begin(); + for (; it != mCache.end(); ++it) + { + if (!it->second.has(EXPERIENCE_ID) || it->second[EXPERIENCE_ID].asUUID().isNull() || + it->second.has("DoesNotExist") || (it->second.has(PROPERTIES) && it->second[PROPERTIES].asInteger() & PROPERTY_INVALID)) + continue; + + experiences[it->first.asString()] = it->second; + } + + LLSD data; + data["experiences"] = experiences; + + LLSDSerialize::toPrettyXML(data, ostr); +} + +// *TODO$: Rider: This method does not seem to be used... it may be useful in testing. +void LLExperienceCache::bootstrap(const LLSD& legacyKeys, int initialExpiration) +{ + LLExperienceCacheImpl::mapKeys(legacyKeys); + for (auto experience : legacyKeys.array()) + { + if (experience.has(EXPERIENCE_ID)) + { + if (!experience.has(EXPIRES)) + { + experience[EXPIRES] = initialExpiration; + } + processExperience(experience[EXPERIENCE_ID].asUUID(), experience); + } + else + { + LL_WARNS("ExperienceCache") + << "Skipping bootstrap entry which is missing " << EXPERIENCE_ID + << LL_ENDL; + } + } +} + +LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_if_not_found) +{ + if (private_key.isNull()) + return LLUUID::null; + + LLExperienceCacheImpl::KeyMap::const_iterator it = LLExperienceCacheImpl::privateToPublicKeyMap.find(private_key); + if (it == LLExperienceCacheImpl::privateToPublicKeyMap.end()) + { + if (null_if_not_found) + { + return LLUUID::null; + } + return private_key; + } + LL_WARNS("LLExperience") << "converted private key " << private_key << " to experience_id " << it->second << LL_ENDL; + return it->second; +} + +//========================================================================= +void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD& experience) +{ + LL_INFOS("ExperienceCache") << "Processing experience \"" << experience[NAME] << "\" with key " << public_key.asString() << LL_ENDL; + + mCache[public_key]=experience; + LLSD & row = mCache[public_key]; + + if(row.has(EXPIRES)) + { + row[EXPIRES] = row[EXPIRES].asReal() + LLFrameTimer::getTotalSeconds(); + } + + if(row.has(EXPERIENCE_ID)) + { + mPendingQueue.erase(row[EXPERIENCE_ID].asUUID()); + } + + //signal + signal_map_t::iterator sig_it = mSignalMap.find(public_key); + if (sig_it != mSignalMap.end()) + { + signal_ptr signal = sig_it->second; + (*signal)(experience); + + mSignalMap.erase(public_key); + } +} + +const LLExperienceCache::cache_t& LLExperienceCache::getCached() +{ + return mCache; +} + +void LLExperienceCache::requestExperiencesCoro(const LLCoroResponder& responder, RequestQueue_t requests) +{ + //LL_INFOS("requestExperiencesCoro") << "url: " << url << LL_ENDL; + + LLSD result = responder.getContent(); + auto status = responder.getStatus(); + + if (!responder.isGoodStatus(status)) + { + F64 now = LLFrameTimer::getTotalSeconds(); + + auto headers = responder.getHeaders(); + // build dummy entries for the failed requests + for (auto request : requests) + { + LLSD exp = get(request); + //leave the properties alone if we already have a cache entry for this xp + if (exp.isUndefined()) + { + exp[PROPERTIES] = PROPERTY_INVALID; + } + exp[EXPIRES] = now + LLExperienceCacheImpl::getErrorRetryDeltaTime(status, headers); + exp[EXPERIENCE_ID] = request; + exp["key_type"] = EXPERIENCE_ID; + exp["uuid"] = request; + exp["error"] = status; + exp[QUOTA] = DEFAULT_QUOTA; + + processExperience(request, exp); + } + return; + } + + LLSD experiences = result["experience_keys"]; + + for (const auto& row : experiences.array()) + { + LLUUID public_key = row[EXPERIENCE_ID].asUUID(); + + LL_DEBUGS("ExperienceCache") << "Received result for " << public_key + << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL; + + processExperience(public_key, row); + } + + LLSD error_ids = result["error_ids"]; + + for (const auto& err : error_ids.array()) + { + LLUUID id = err.asUUID(); + LLSD exp; + exp[EXPIRES] = DEFAULT_EXPIRATION; + exp[EXPERIENCE_ID] = id; + exp[PROPERTIES] = PROPERTY_INVALID; + exp[MISSING] = true; + exp[QUOTA] = DEFAULT_QUOTA; + + processExperience(id, exp); + LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL; + } + +} + +void LLExperienceCache::requestExperiences() +{ + if (mCapability == nullptr) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } + + std::string urlBase = mCapability("GetExperienceInfo"); + if (urlBase.empty()) + { + LL_DEBUGS("ExperienceCache") << "No Experience capability." << LL_ENDL; + return; + } + + if (*urlBase.rbegin() != '/') + { + urlBase += "/"; + } + urlBase += "id/"; + + + F64 now = LLFrameTimer::getTotalSeconds(); + + const U32 EXP_URL_SEND_THRESHOLD = 3000; + constexpr U32 EXP_PAGE_SIZE = EXP_URL_SEND_THRESHOLD / UUID_STR_LENGTH; + + std::ostringstream ostr; + ostr << urlBase << "?page_size=" << EXP_PAGE_SIZE; + RequestQueue_t requests; + + while (!mRequestQueue.empty()) + { + RequestQueue_t::iterator it = mRequestQueue.begin(); + LLUUID key = (*it); + mRequestQueue.erase(it); + requests.insert(key); + + ostr << "&" << EXPERIENCE_ID << "=" << key.asString(); + mPendingQueue[key] = now; + + if (mRequestQueue.empty() || (ostr.tellp() > EXP_URL_SEND_THRESHOLD)) + { // request is placed in the coprocedure pool for the ExpCache cache. Throttling is done by the pool itself. + LLHTTPClient::get(ostr.str(), new LLCoroResponder( + boost::bind(&LLExperienceCache::requestExperiencesCoro, this, _1, requests) )); + + ostr.str(std::string()); + ostr << urlBase << "?page_size=" << EXP_PAGE_SIZE; + requests.clear(); + } + } + +} + + +bool LLExperienceCache::isRequestPending(const LLUUID& public_key) +{ + bool isPending = false; + const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0; + + PendingQueue_t::const_iterator it = mPendingQueue.find(public_key); + + if(it != mPendingQueue.end()) + { + F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS; + isPending = (it->second > expire_time); + } + + return isPending; +} + +void LLExperienceCache::setCapabilityQuery(LLExperienceCache::CapabilityQuery_t queryfn) +{ + mCapability = queryfn; +} + + +void LLExperienceCache::idleCoro() +{ + const F32 SECS_BETWEEN_REQUESTS = 0.5f; + const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds + + { + static LLFrameTimer sRequestTimer; + if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS)) return; + + if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) + { + eraseExpired(); + } + + if (!mRequestQueue.empty()) + { + requestExperiences(); + } + } + + // The coroutine system will likely be shut down by the time we get to this point + // (or at least no further cycling will occur on it since the user has decided to quit.) +} + +void LLExperienceCache::erase(const LLUUID& key) +{ + cache_t::iterator it = mCache.find(key); + + if(it != mCache.end()) + { + mCache.erase(it); + } +} + +void LLExperienceCache::eraseExpired() +{ + F64 now = LLFrameTimer::getTotalSeconds(); + cache_t::iterator it = mCache.begin(); + while (it != mCache.end()) + { + cache_t::iterator cur = it; + LLSD& exp = cur->second; + ++it; + + //LL_INFOS("ExperienceCache") << "Testing experience \"" << exp[NAME] << "\" with exp time " << exp[EXPIRES].asReal() << "(now = " << now << ")" << LL_ENDL; + + if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now) + { + if(!exp.has(EXPERIENCE_ID)) + { + LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ; + mCache.erase(cur); + } + else + { + LLUUID id = exp[EXPERIENCE_ID].asUUID(); + LLUUID private_key = exp.has(LLExperienceCache::PRIVATE_KEY) ? exp[LLExperienceCache::PRIVATE_KEY].asUUID():LLUUID::null; + if(private_key.notNull() || !exp.has("DoesNotExist")) + { + fetch(id, true); + } + else + { + LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ; + mCache.erase(cur); + } + } + } + } +} + +bool LLExperienceCache::fetch(const LLUUID& key, bool refresh/* = true*/) +{ + if(!key.isNull() && !isRequestPending(key) && (refresh || mCache.find(key)==mCache.end())) + { + LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL; + + mRequestQueue.insert(key); + return true; + } + return false; +} + +void LLExperienceCache::insert(const LLSD& experience_data) +{ + if(experience_data.has(EXPERIENCE_ID)) + { + processExperience(experience_data[EXPERIENCE_ID].asUUID(), experience_data); + } + else + { + LL_WARNS("ExperienceCache") << ": Ignoring cache insert of experience which is missing " << EXPERIENCE_ID << LL_ENDL; + } +} + +const LLSD& LLExperienceCache::get(const LLUUID& key) +{ + static const LLSD empty; + + if(key.isNull()) + return empty; + cache_t::const_iterator it = mCache.find(key); + + if (it != mCache.end()) + { + return it->second; + } + fetch(key); + + return empty; +} + +void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::ExperienceGetFn_t slot) +{ + if(key.isNull()) + return; + + cache_t::const_iterator it = mCache.find(key); + if (it != mCache.end()) + { + // ...name already exists in cache, fire callback now + callback_signal_t signal; + signal.connect(slot); + + signal(it->second); + return; + } + + fetch(key); + + signal_ptr signal = boost::make_shared(); + + std::pair result = mSignalMap.insert(signal_map_t::value_type(key, signal)); + if (!result.second) + signal = (*result.first).second; + signal->connect(slot); +} + +//========================================================================= +void LLExperienceCache::fetchAssociatedExperience(const LLUUID& objectId, const LLUUID& itemId, std::string url, ExperienceGetFn_t fn) +{ + if (mCapability == nullptr) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } + + + if (url.empty()) + { + url = mCapability("GetMetadata"); + + if (url.empty()) + { + LL_WARNS("ExperienceCache") << "No Metadata capability." << LL_ENDL; + return; + } + } + + LLSD fields; + fields.append("experience"); + LLSD data; + data["object-id"] = objectId; + data["item-id"] = itemId; + data["fields"] = fields; + + LLHTTPClient::post(url, data, new LLCoroResponder( + boost::bind(&LLExperienceCache::fetchAssociatedExperienceCoro, this, _1, fn))); +} + +void LLExperienceCache::fetchAssociatedExperienceCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn) +{ + LLSD result = responder.getContent(); + auto status = responder.getStatus(); + + if (!responder.isGoodStatus(status) || !result.has("experience")) + { + LLSD failure; + if (!status) + { + failure["error"] = status; + failure["message"] = responder.getReason(); + } + else + { + failure["error"] = -1; + failure["message"] = "no experience"; + } + if (fn != nullptr) + fn(failure); + return; + } + + LLUUID expId = result["experience"].asUUID(); + get(expId, fn); +} + +//------------------------------------------------------------------------- +void LLExperienceCache::findExperienceByName(const std::string text, int page, ExperienceGetFn_t fn) +{ + if (mCapability == nullptr) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } + + std::ostringstream url; + + url << mCapability("FindExperienceByName") << "?page=" << page << "&page_size=" << SEARCH_PAGE_SIZE << "&query=" << LLURI::escape(text); + + LLHTTPClient::get(url.str(), new LLCoroResponder( + boost::bind(&LLExperienceCache::findExperienceByNameCoro, this, _1, fn))); +} + +void LLExperienceCache::findExperienceByNameCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn) +{ + LLSD result = responder.getContent(); + + if (!responder.isGoodStatus(responder.getStatus())) + { + fn(LLSD()); + return; + } + + const LLSD& experiences = result["experience_keys"]; + for (const auto& it : experiences.array()) + { + insert(it); + } + + fn(result); +} + +//------------------------------------------------------------------------- +void LLExperienceCache::getGroupExperiences(const LLUUID &groupId, ExperienceGetFn_t fn) +{ + if (mCapability == nullptr) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } + + // search for experiences owned by the current group + std::string url = mCapability("GroupExperiences"); + if (url.empty()) + { + LL_WARNS("ExperienceCache") << "No Group Experiences capability" << LL_ENDL; + return; + } + + url += "?" + groupId.asString(); + + LLHTTPClient::get(url, new LLCoroResponder( + boost::bind(&LLExperienceCache::getGroupExperiencesCoro, this, _1, fn))); +} + +void LLExperienceCache::getGroupExperiencesCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn) +{ + LLSD result = responder.getContent(); + + if (!responder.isGoodStatus(responder.getStatus())) + { + fn(LLSD()); + return; + } + + const LLSD& experienceIds = result["experience_ids"]; + fn(experienceIds); +} + +//------------------------------------------------------------------------- +void LLExperienceCache::getRegionExperiences(CapabilityQuery_t regioncaps, ExperienceGetFn_t fn) +{ + regionExperiences(regioncaps, LLSD(), false, fn); +} + +void LLExperienceCache::setRegionExperiences(CapabilityQuery_t regioncaps, const LLSD &experiences, ExperienceGetFn_t fn) +{ + regionExperiences(regioncaps, experiences, true, fn); +} + +void LLExperienceCache::regionExperiences(CapabilityQuery_t regioncaps, const LLSD &experiences, bool update, ExperienceGetFn_t fn) +{ + // search for experiences owned by the current group + std::string url = regioncaps("RegionExperiences"); + if (url.empty()) + { + LL_WARNS("ExperienceCache") << "No Region Experiences capability" << LL_ENDL; + return; + } + + auto httpRequest = new LLCoroResponder( + boost::bind(&LLExperienceCache::regionExperiencesCoro, this, _1, fn)); + + LLSD result; + if (update) + LLHTTPClient::post(url, experiences, httpRequest); + else + LLHTTPClient::get(url, httpRequest); +} + +void LLExperienceCache::regionExperiencesCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn) +{ + LLSD result = responder.getContent(); + + if (!responder.isGoodStatus(responder.getStatus())) + { +// fn(LLSD()); + return; + } + + fn(result); + +} + +//------------------------------------------------------------------------- +void LLExperienceCache::getExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn) +{ + if (mCapability == nullptr) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } + + std::string url = mCapability("ExperiencePreferences") + "?" + experienceId.asString(); + + LLHTTPClient::get(url, new LLCoroResponder( + boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, fn))); +} + +void LLExperienceCache::setExperiencePermission(const LLUUID &experienceId, const std::string &permission, ExperienceGetFn_t fn) +{ + if (mCapability == nullptr) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } + + std::string url = mCapability("ExperiencePreferences"); + if (url.empty()) + return; + LLSD permData; + LLSD data; + permData["permission"] = permission; + data[experienceId.asString()] = permData; + + LLHTTPClient::put(url, data, new LLCoroResponder( + boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, fn))); +} + +void LLExperienceCache::forgetExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn) +{ + if (mCapability == nullptr) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } + + std::string url = mCapability("ExperiencePreferences") + "?" + experienceId.asString(); + LLHTTPClient::del(url, new LLCoroResponder( + boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, fn))); +} + +void LLExperienceCache::experiencePermissionCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn) +{ + // search for experiences owned by the current group + + LLSD result = responder.getContent(); + + if (responder.isGoodStatus(responder.getStatus())) + { + fn(result); + } +} + +//------------------------------------------------------------------------- +void LLExperienceCache::getExperienceAdmin(const LLUUID &experienceId, ExperienceGetFn_t fn) +{ + if (mCapability == nullptr) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } + + std::string url = mCapability("IsExperienceAdmin"); + if (url.empty()) + { + LL_WARNS("ExperienceCache") << "No Region Experiences capability" << LL_ENDL; + return; + } + url += "?experience_id=" + experienceId.asString(); + + LLHTTPClient::get(url, new LLCoroResponder( + boost::bind(fn, boost::bind(&LLCoroResponder::getContent, _1)))); +} + +//------------------------------------------------------------------------- +void LLExperienceCache::updateExperience(LLSD updateData, ExperienceGetFn_t fn) +{ + if (mCapability == nullptr) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } + + std::string url = mCapability("UpdateExperience"); + if (url.empty()) + { + LL_WARNS("ExperienceCache") << "No Region Experiences capability" << LL_ENDL; + return; + } + + updateData.erase(LLExperienceCache::QUOTA); + updateData.erase(LLExperienceCache::EXPIRES); + updateData.erase(LLExperienceCache::AGENT_ID); + + LLHTTPClient::post(url, updateData, new LLCoroResponder( + boost::bind(fn, boost::bind(&LLCoroResponder::getContent, _1)))); +} + +//========================================================================= +void LLExperienceCacheImpl::mapKeys(const LLSD& legacyKeys) +{ + for (const auto& exp : legacyKeys.array()) + { + if (exp.has(LLExperienceCacheImpl::EXPERIENCE_ID) && exp.has(LLExperienceCacheImpl::PRIVATE_KEY)) + { + LLExperienceCacheImpl::privateToPublicKeyMap[exp[LLExperienceCacheImpl::PRIVATE_KEY].asUUID()] = + exp[LLExperienceCacheImpl::EXPERIENCE_ID].asUUID(); + } + } +} + +// Return time to retry a request that generated an error, based on +// error type and headers. Return value is seconds-since-epoch. +F64 LLExperienceCacheImpl::getErrorRetryDeltaTime(S32 status, const AIHTTPReceivedHeaders& headers) +{ + // Retry-After takes priority + std::string retry_afters; + if (headers.getFirstValue("retry-after", retry_afters)) + { + LLSD retry_after(retry_afters); + // We only support the delta-seconds type + S32 delta_seconds = retry_after.asInteger(); + if (delta_seconds > 0) + { + // ...valid delta-seconds + return F64(delta_seconds); + } + } + + // If no Retry-After, look for Cache-Control max-age + // Allow the header to override the default + std::string cache_control; + if (headers.getFirstValue("cache-control", cache_control)) + { + S32 max_age = 0; + if (LLExperienceCacheImpl::maxAgeFromCacheControl(cache_control, &max_age)) + { + LL_WARNS("ExperienceCache") + << "got EXPIRES from headers, max_age " << max_age + << LL_ENDL; + return (F64)max_age; + } + } + + // No information in header, make a guess + if (status == 503) + { + // ...service unavailable, retry soon + const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min + return SERVICE_UNAVAILABLE_DELAY; + } + else if (status == 499) + { + // ...we were probably too busy, retry quickly + const F64 BUSY_DELAY = 10.0; // 10 seconds + return BUSY_DELAY; + + } + else + { + // ...other unexpected error + const F64 DEFAULT_DELAY = 3600.0; // 1 hour + return DEFAULT_DELAY; + } +} + +bool LLExperienceCacheImpl::maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age) +{ + // Split the string on "," to get a list of directives + typedef boost::tokenizer > tokenizer; + tokenizer directives(cache_control, COMMA_SEPARATOR); + + tokenizer::iterator token_it = directives.begin(); + for ( ; token_it != directives.end(); ++token_it) + { + // Tokens may have leading or trailing whitespace + std::string token = *token_it; + LLStringUtil::trim(token); + + if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0) + { + // ...this token starts with max-age, so let's chop it up by "=" + tokenizer subtokens(token, EQUALS_SEPARATOR); + tokenizer::iterator subtoken_it = subtokens.begin(); + + // Must have a token + if (subtoken_it == subtokens.end()) return false; + std::string subtoken = *subtoken_it; + + // Must exactly equal "max-age" + LLStringUtil::trim(subtoken); + if (subtoken != MAX_AGE) return false; + + // Must have another token + ++subtoken_it; + if (subtoken_it == subtokens.end()) return false; + subtoken = *subtoken_it; + + // Must be a valid integer + // *NOTE: atoi() returns 0 for invalid values, so we have to + // check the string first. + // *TODO: Do servers ever send "0000" for zero? We don't handle it + LLStringUtil::trim(subtoken); + if (subtoken == "0") + { + *max_age = 0; + return true; + } + S32 val = atoi( subtoken.c_str() ); + if (val > 0 && val < S32_MAX) + { + *max_age = val; + return true; + } + return false; + } + } + return false; +} + + + + diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h new file mode 100644 index 0000000000..cddf5f67e6 --- /dev/null +++ b/indra/llmessage/llexperiencecache.h @@ -0,0 +1,181 @@ +/** + * @file llexperiencecache.h + * @brief Caches information relating to experience keys + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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_LLEXPERIENCECACHE_H +#define LL_LLEXPERIENCECACHE_H + +#include "linden_common.h" +#include "llsingleton.h" +#include "llframetimer.h" +#include "llsd.h" +#include + +struct LLCoroResponder; +class LLSD; +class LLUUID; + + +class LLExperienceCache final : public LLSingleton < LLExperienceCache > +{ + friend class LLSingleton; + LLExperienceCache(); + +public: + typedef std::function CapabilityQuery_t; + typedef std::function ExperienceGetFn_t; + + void idleCoro(); + void setCapabilityQuery(CapabilityQuery_t queryfn); + void cleanup(); + + //------------------------------------------- + // Cache methods + void erase(const LLUUID& key); + bool fetch(const LLUUID& key, bool refresh = false); + void insert(const LLSD& experience_data); + const LLSD& get(const LLUUID& key); + void get(const LLUUID& key, ExperienceGetFn_t slot); // If name information is in cache, callback will be called immediately. + + bool isRequestPending(const LLUUID& public_key); + + //------------------------------------------- + void fetchAssociatedExperience(const LLUUID& objectId, const LLUUID& itemId, ExperienceGetFn_t fn) { fetchAssociatedExperience(objectId, itemId, LLStringUtil::null, fn); } + void fetchAssociatedExperience(const LLUUID& objectId, const LLUUID& itemId, std::string url, ExperienceGetFn_t fn); + void findExperienceByName(const std::string text, int page, ExperienceGetFn_t fn); + void getGroupExperiences(const LLUUID &groupId, ExperienceGetFn_t fn); + + // the Get/Set Region Experiences take a CapabilityQuery to get the capability since + // the region being queried may not be the region that the agent is standing on. + void getRegionExperiences(CapabilityQuery_t regioncaps, ExperienceGetFn_t fn); + void setRegionExperiences(CapabilityQuery_t regioncaps, const LLSD &experiences, ExperienceGetFn_t fn); + + void getExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn); + void setExperiencePermission(const LLUUID &experienceId, const std::string &permission, ExperienceGetFn_t fn); + void forgetExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn); + + void getExperienceAdmin(const LLUUID &experienceId, ExperienceGetFn_t fn); + + void updateExperience(LLSD updateData, ExperienceGetFn_t fn); + //------------------------------------------- + static const std::string NAME; // "name" + static const std::string EXPERIENCE_ID; // "public_id" + static const std::string AGENT_ID; // "agent_id" + static const std::string GROUP_ID; // "group_id" + static const std::string PROPERTIES; // "properties" + static const std::string EXPIRES; // "expiration" + static const std::string DESCRIPTION; // "description" + static const std::string QUOTA; // "quota" + static const std::string MATURITY; // "maturity" + static const std::string METADATA; // "extended_metadata" + static const std::string SLURL; // "slurl" + + static const std::string MISSING; // "DoesNotExist" + + // should be in sync with experience-api/experiences/models.py + static const int PROPERTY_INVALID; // 1 << 0 + static const int PROPERTY_PRIVILEGED; // 1 << 3 + static const int PROPERTY_GRID; // 1 << 4 + static const int PROPERTY_PRIVATE; // 1 << 5 + static const int PROPERTY_DISABLED; // 1 << 6 + static const int PROPERTY_SUSPENDED; // 1 << 7 + +private: + virtual ~LLExperienceCache(); + + void initSingleton() override; + + // Callback types for get() + typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t; + typedef boost::shared_ptr signal_ptr; + // May have multiple callbacks for a single ID, which are + // represented as multiple slots bound to the signal. + // Avoid copying signals via pointers. + typedef std::map signal_map_t; + typedef std::map cache_t; + + typedef uuid_set_t RequestQueue_t; + typedef std::map PendingQueue_t; + + //-------------------------------------------- + static const std::string PRIVATE_KEY; // "private_id" + + // default values + static const F64 DEFAULT_EXPIRATION; // 600.0 + static const S32 DEFAULT_QUOTA; // 128 this is megabytes + static const int SEARCH_PAGE_SIZE; + +//-------------------------------------------- + void processExperience(const LLUUID& public_key, const LLSD& experience); + +//-------------------------------------------- + cache_t mCache; + signal_map_t mSignalMap; + RequestQueue_t mRequestQueue; + PendingQueue_t mPendingQueue; + + LLFrameTimer mEraseExpiredTimer; // Periodically clean out expired entries from the cache + CapabilityQuery_t mCapability; + std::string mCacheFileName; + bool mShutdown; + + void eraseExpired(); + void requestExperiencesCoro(const LLCoroResponder& responder, RequestQueue_t); + void requestExperiences(); + + void fetchAssociatedExperienceCoro(const LLCoroResponder& responder, ExperienceGetFn_t); + void findExperienceByNameCoro(const LLCoroResponder& responder, ExperienceGetFn_t); + void getGroupExperiencesCoro(const LLCoroResponder& responder, ExperienceGetFn_t); + void regionExperiences(CapabilityQuery_t regioncaps, const LLSD& experiences, bool update, ExperienceGetFn_t fn); + void regionExperiencesCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn); + void experiencePermissionCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn); + + void bootstrap(const LLSD& legacyKeys, int initialExpiration); + void exportFile(std::ostream& ostr) const; + void importFile(std::istream& istr); + + // + const cache_t& getCached(); + + // maps an experience private key to the experience id + LLUUID getExperienceId(const LLUUID& private_key, bool null_if_not_found=false); + + //===================================================================== + inline friend std::ostream &operator << (std::ostream &os, const LLExperienceCache &cache) + { + cache.exportFile(os); + return os; + } + + inline friend std::istream &operator >> (std::istream &is, LLExperienceCache &cache) + { + cache.importFile(is); + return is; + } +}; + +#endif // LL_LLEXPERIENCECACHE_H diff --git a/indra/llmessage/llfiltersd2xmlrpc.cpp b/indra/llmessage/llfiltersd2xmlrpc.cpp index f8ef744cae..b9f004a753 100644 --- a/indra/llmessage/llfiltersd2xmlrpc.cpp +++ b/indra/llmessage/llfiltersd2xmlrpc.cpp @@ -84,6 +84,7 @@ #include "llsd.h" #include "llsdserialize.h" #include "lluuid.h" +#include "llfasttimer.h" // spammy mode //#define LL_SPEW_STREAM_OUT_DEBUGGING 1 @@ -308,7 +309,7 @@ LLFilterSD2XMLRPCResponse::~LLFilterSD2XMLRPCResponse() } -static LLFastTimer::DeclareTimer FTM_PROCESS_SD2XMLRPC_RESPONSE("SD2XMLRPC Response"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_SD2XMLRPC_RESPONSE("SD2XMLRPC Response"); // virtual LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl( const LLChannelDescriptors& channels, @@ -317,7 +318,7 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_SD2XMLRPC_RESPONSE); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_SD2XMLRPC_RESPONSE); PUMP_DEBUG; // This pipe does not work if it does not have everyting. This @@ -385,7 +386,7 @@ LLFilterSD2XMLRPCRequest::~LLFilterSD2XMLRPCRequest() { } -static LLFastTimer::DeclareTimer FTM_PROCESS_SD2XMLRPC_REQUEST("S22XMLRPC Request"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_SD2XMLRPC_REQUEST("S22XMLRPC Request"); // virtual LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl( @@ -395,7 +396,7 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_SD2XMLRPC_REQUEST); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_SD2XMLRPC_REQUEST); // This pipe does not work if it does not have everyting. This // could be addressed by making a stream parser for llsd which // handled partial information. @@ -592,7 +593,7 @@ LLFilterXMLRPCResponse2LLSD::~LLFilterXMLRPCResponse2LLSD() { } -static LLFastTimer::DeclareTimer FTM_PROCESS_XMLRPC2LLSD_RESPONSE("XMLRPC2LLSD Response"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_XMLRPC2LLSD_RESPONSE("XMLRPC2LLSD Response"); LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl( const LLChannelDescriptors& channels, @@ -601,7 +602,7 @@ LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_XMLRPC2LLSD_RESPONSE); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_XMLRPC2LLSD_RESPONSE); PUMP_DEBUG; if(!eos) return STATUS_BREAK; @@ -678,7 +679,7 @@ LLFilterXMLRPCRequest2LLSD::~LLFilterXMLRPCRequest2LLSD() { } -static LLFastTimer::DeclareTimer FTM_PROCESS_XMLRPC2LLSD_REQUEST("XMLRPC2LLSD Request"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_XMLRPC2LLSD_REQUEST("XMLRPC2LLSD Request"); LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, @@ -686,7 +687,7 @@ LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_XMLRPC2LLSD_REQUEST); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_XMLRPC2LLSD_REQUEST); PUMP_DEBUG; if(!eos) return STATUS_BREAK; if(!buffer) return STATUS_ERROR; diff --git a/indra/llmessage/llhttpsender.cpp b/indra/llmessage/llhttpsender.cpp index 643735fc18..5363088d79 100644 --- a/indra/llmessage/llhttpsender.cpp +++ b/indra/llmessage/llhttpsender.cpp @@ -38,7 +38,7 @@ namespace { typedef std::map SenderMap; static SenderMap senderMap; - static LLHTTPSender* defaultSender = new LLHTTPSender(); + static LLPointer defaultSender(new LLHTTPSender()); } //virtual @@ -90,6 +90,5 @@ void LLHTTPSender::clearSender(const LLHost& host) //static void LLHTTPSender::setDefaultSender(LLHTTPSender* sender) { - delete defaultSender; defaultSender = sender; } diff --git a/indra/llmessage/llhttpsender.h b/indra/llmessage/llhttpsender.h index 88920db24d..ff8fa2f95b 100644 --- a/indra/llmessage/llhttpsender.h +++ b/indra/llmessage/llhttpsender.h @@ -32,7 +32,7 @@ class LLHost; class LLSD; -class LLHTTPSender +class LLHTTPSender : public LLThreadSafeRefCount { public: diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp index 6036c6ccca..d5e7e4ffe1 100644 --- a/indra/llmessage/llinstantmessage.cpp +++ b/indra/llmessage/llinstantmessage.cpp @@ -58,103 +58,6 @@ const std::string SYSTEM_FROM("Second Life"); const std::string INTERACTIVE_SYSTEM_FROM("F387446C-37C4-45f2-A438-D99CBDBB563B"); const S32 IM_TTL = 1; - -/** - * LLIMInfo - */ -LLIMInfo::LLIMInfo() : - mFromGroup(FALSE), - mParentEstateID(0), - mOffline(0), - mViewerThinksToIsOnline(false), - mIMType(IM_NOTHING_SPECIAL), - mTimeStamp(0), - mSource(IM_FROM_SIM), - mTTL(IM_TTL) -{ -} - -LLIMInfo::LLIMInfo( - const LLUUID& from_id, - BOOL from_group, - const LLUUID& to_id, - EInstantMessage im_type, - const std::string& name, - const std::string& message, - const LLUUID& id, - U32 parent_estate_id, - const LLUUID& region_id, - const LLVector3& position, - LLSD data, - U8 offline, - U32 timestamp, - EIMSource source, - S32 ttl) : - mFromID(from_id), - mFromGroup(from_group), - mToID(to_id), - mParentEstateID(0), - mRegionID(region_id), - mPosition(position), - mOffline(offline), - mViewerThinksToIsOnline(false), - mIMType(im_type), - mID(id), - mTimeStamp(timestamp), - mName(name), - mMessage(message), - mData(data), - mSource(source), - mTTL(ttl) -{ -} - -LLIMInfo::LLIMInfo(LLMessageSystem* msg, EIMSource source, S32 ttl) : - mViewerThinksToIsOnline(false), - mSource(source), - mTTL(ttl) -{ - unpackMessageBlock(msg); -} - -LLIMInfo::~LLIMInfo() -{ -} - -void LLIMInfo::packInstantMessage(LLMessageSystem* msg) const -{ - LL_DEBUGS() << "LLIMInfo::packInstantMessage()" << LL_ENDL; - msg->newMessageFast(_PREHASH_ImprovedInstantMessage); - packMessageBlock(msg); -} - -void LLIMInfo::packMessageBlock(LLMessageSystem* msg) const -{ - // Construct binary bucket - std::vector bucket; - if (mData.has("binary_bucket")) - { - bucket = mData["binary_bucket"].asBinary(); - } - pack_instant_message_block( - msg, - mFromID, - mFromGroup, - LLUUID::null, - mToID, - mName, - mMessage, - mOffline, - mIMType, - mID, - mParentEstateID, - mRegionID, - mPosition, - mTimeStamp, - &bucket[0], - bucket.size()); -} - void pack_instant_message( LLMessageSystem* msg, const LLUUID& from_id, @@ -264,124 +167,3 @@ void pack_instant_message_block( } msg->addBinaryDataFast(_PREHASH_BinaryBucket, bb, binary_bucket_size); } - -void LLIMInfo::unpackMessageBlock(LLMessageSystem* msg) -{ - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, mFromID); - msg->getBOOLFast(_PREHASH_MessageBlock, _PREHASH_FromGroup, mFromGroup); - msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ToAgentID, mToID); - msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_ParentEstateID, mParentEstateID); - msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_RegionID, mRegionID); - msg->getVector3Fast(_PREHASH_MessageBlock, _PREHASH_Position, mPosition); - msg->getU8Fast(_PREHASH_MessageBlock, _PREHASH_Offline, mOffline); - U8 dialog; - msg->getU8Fast(_PREHASH_MessageBlock, _PREHASH_Dialog, dialog); - mIMType = (EInstantMessage) dialog; - msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ID, mID); - msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_Timestamp, mTimeStamp); - msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_FromAgentName, mName); - - msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_Message, mMessage); - - S32 binary_bucket_size = llmin( - MTUBYTES, - msg->getSizeFast( - _PREHASH_MessageBlock, - _PREHASH_BinaryBucket)); - if(binary_bucket_size > 0) - { - std::vector bucket; - bucket.resize(binary_bucket_size); - - msg->getBinaryDataFast( - _PREHASH_MessageBlock, - _PREHASH_BinaryBucket, - &bucket[0], - 0, - 0, - binary_bucket_size); - mData["binary_bucket"] = bucket; - } - else - { - mData.clear(); - } -} - -LLSD im_info_to_llsd(LLPointer im_info) -{ - LLSD param_version; - param_version["version"] = 1; - LLSD param_message; - param_message["from_id"] = im_info->mFromID; - param_message["from_group"] = im_info->mFromGroup; - param_message["to_id"] = im_info->mToID; - param_message["from_name"] = im_info->mName; - param_message["message"] = im_info->mMessage; - param_message["type"] = (S32)im_info->mIMType; - param_message["id"] = im_info->mID; - param_message["timestamp"] = (S32)im_info->mTimeStamp; - param_message["offline"] = (S32)im_info->mOffline; - param_message["parent_estate_id"] = (S32)im_info->mParentEstateID; - param_message["region_id"] = im_info->mRegionID; - param_message["position"] = ll_sd_from_vector3(im_info->mPosition); - param_message["data"] = im_info->mData; - param_message["source"]= im_info->mSource; - param_message["ttl"] = im_info->mTTL; - - LLSD param_agent; - param_agent["agent_id"] = im_info->mFromID; - - LLSD params; - params["version_params"] = param_version; - params["message_params"] = param_message; - params["agent_params"] = param_agent; - - return params; -} - -LLPointer llsd_to_im_info(const LLSD& im_info_sd) -{ - LLSD param_message = im_info_sd["message_params"]; - LLSD param_agent = im_info_sd["agent_params"]; - - LLPointer im_info = new LLIMInfo( - param_message["from_id"].asUUID(), - param_message["from_group"].asBoolean(), - param_message["to_id"].asUUID(), - (EInstantMessage) param_message["type"].asInteger(), - param_message["from_name"].asString(), - param_message["message"].asString(), - param_message["id"].asUUID(), - (U32) param_message["parent_estate_id"].asInteger(), - param_message["region_id"].asUUID(), - ll_vector3_from_sd(param_message["position"]), - param_message["data"], - (U8) param_message["offline"].asInteger(), - (U32) param_message["timestamp"].asInteger(), - (EIMSource)param_message["source"].asInteger(), - param_message["ttl"].asInteger()); - - return im_info; -} - -LLPointer LLIMInfo::clone() -{ - return new LLIMInfo( - mFromID, - mFromGroup, - mToID, - mIMType, - mName, - mMessage, - mID, - mParentEstateID, - mRegionID, - mPosition, - mData, - mOffline, - mTimeStamp, - mSource, - mTTL); -} - diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index febc59c4bc..c0d9bc55ba 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -225,62 +225,6 @@ extern const std::string INTERACTIVE_SYSTEM_FROM; // Number of retry attempts on sending the im. extern const S32 IM_TTL; - -class LLIMInfo : public LLRefCount -{ -protected: - LLIMInfo(); - ~LLIMInfo(); - -public: - LLIMInfo(LLMessageSystem* msg, - EIMSource source = IM_FROM_SIM, - S32 ttl = IM_TTL); - - LLIMInfo( - const LLUUID& from_id, - BOOL from_group, - const LLUUID& to_id, - EInstantMessage im_type, - const std::string& name, - const std::string& message, - const LLUUID& id, - U32 parent_estate_id, - const LLUUID& region_id, - const LLVector3& position, - LLSD data, - U8 offline, - U32 timestamp, - EIMSource source, - S32 ttl = IM_TTL); - - void packInstantMessage(LLMessageSystem* msg) const; - void packMessageBlock(LLMessageSystem* msg) const; - void unpackMessageBlock(LLMessageSystem* msg); - LLPointer clone(); -public: - LLUUID mFromID; - BOOL mFromGroup; - LLUUID mToID; - U32 mParentEstateID; - LLUUID mRegionID; - LLVector3 mPosition; - U8 mOffline; - bool mViewerThinksToIsOnline; - EInstantMessage mIMType; - LLUUID mID; - U32 mTimeStamp; - std::string mName; - std::string mMessage; - LLSD mData; - - EIMSource mSource; - S32 mTTL; -}; - -LLPointer llsd_to_im_info(const LLSD& im_info_sd); -LLSD im_info_to_llsd(LLPointer im_info); - void pack_instant_message( LLMessageSystem* msgsystem, const LLUUID& from_id, diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index dc0f6e928f..7f896469f1 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -139,11 +139,11 @@ class LLHTTPPipe : public LLIOPipe LLSD mHeaders; }; -static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_PIPE("HTTP Pipe"); -static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_GET("HTTP Get"); -static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_PUT("HTTP Put"); -static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_POST("HTTP Post"); -static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_DELETE("HTTP Delete"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_PIPE("HTTP Pipe"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_GET("HTTP Get"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_PUT("HTTP Put"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_POST("HTTP Post"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_DELETE("HTTP Delete"); LLIOPipe::EStatus LLHTTPPipe::process_impl( const LLChannelDescriptors& channels, @@ -152,7 +152,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_HTTP_PIPE); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_PIPE); PUMP_DEBUG; LL_DEBUGS() << "LLSDHTTPServer::process_impl" << LL_ENDL; @@ -181,12 +181,12 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB]; if(verb == HTTP_VERB_GET) { - LLFastTimer _(FTM_PROCESS_HTTP_GET); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_GET); mNode.get(LLHTTPNode::ResponsePtr(mResponse), context); } else if(verb == HTTP_VERB_PUT) { - LLFastTimer _(FTM_PROCESS_HTTP_PUT); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_PUT); LLSD input; if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD) { @@ -202,7 +202,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( } else if(verb == HTTP_VERB_POST) { - LLFastTimer _(FTM_PROCESS_HTTP_POST); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_POST); LLSD input; if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD) { @@ -218,7 +218,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( } else if(verb == HTTP_VERB_DELETE) { - LLFastTimer _(FTM_PROCESS_HTTP_DELETE); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_DELETE); mNode.del(LLHTTPNode::ResponsePtr(mResponse), context); } else if(verb == HTTP_VERB_OPTIONS) @@ -436,7 +436,7 @@ class LLHTTPResponseHeader : public LLIOPipe * LLHTTPResponseHeader */ -static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_HEADER("HTTP Header"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_HEADER("HTTP Header"); // virtual LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( @@ -446,7 +446,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_HTTP_HEADER); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_HEADER); PUMP_DEBUG; if(eos) { @@ -636,7 +636,7 @@ void LLHTTPResponder::markBad( << "\n\n" << std::flush; } -static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_RESPONDER("HTTP Responder"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_RESPONDER("HTTP Responder"); // virtual LLIOPipe::EStatus LLHTTPResponder::process_impl( @@ -646,7 +646,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_HTTP_RESPONDER); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_RESPONDER); PUMP_DEBUG; LLIOPipe::EStatus status = STATUS_OK; diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index 6b17130c81..b6e92e293e 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -277,7 +277,7 @@ LLIOSocketReader::~LLIOSocketReader() //LL_DEBUGS() << "Destroying LLIOSocketReader" << LL_ENDL; } -static LLFastTimer::DeclareTimer FTM_PROCESS_SOCKET_READER("Socket Reader"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_SOCKET_READER("Socket Reader"); // virtual LLIOPipe::EStatus LLIOSocketReader::process_impl( @@ -287,7 +287,7 @@ LLIOPipe::EStatus LLIOSocketReader::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_SOCKET_READER); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_SOCKET_READER); PUMP_DEBUG; if(!mSource) return STATUS_PRECONDITION_NOT_MET; if(!mInitialized) @@ -377,7 +377,7 @@ LLIOSocketWriter::~LLIOSocketWriter() //LL_DEBUGS() << "Destroying LLIOSocketWriter" << LL_ENDL; } -static LLFastTimer::DeclareTimer FTM_PROCESS_SOCKET_WRITER("Socket Writer"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_SOCKET_WRITER("Socket Writer"); // virtual LLIOPipe::EStatus LLIOSocketWriter::process_impl( const LLChannelDescriptors& channels, @@ -386,7 +386,7 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_SOCKET_WRITER); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_SOCKET_WRITER); PUMP_DEBUG; if(!mDestination) return STATUS_PRECONDITION_NOT_MET; if(!mInitialized) @@ -531,7 +531,7 @@ void LLIOServerSocket::setResponseTimeout(F32 timeout_secs) mResponseTimeout = timeout_secs; } -static LLFastTimer::DeclareTimer FTM_PROCESS_SERVER_SOCKET("Server Socket"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_SERVER_SOCKET("Server Socket"); // virtual LLIOPipe::EStatus LLIOServerSocket::process_impl( const LLChannelDescriptors& channels, @@ -540,7 +540,7 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_SERVER_SOCKET); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_SERVER_SOCKET); PUMP_DEBUG; if(!pump) { diff --git a/indra/llmessage/llioutil.cpp b/indra/llmessage/llioutil.cpp index 9fd49d23d4..b8443c0600 100644 --- a/indra/llmessage/llioutil.cpp +++ b/indra/llmessage/llioutil.cpp @@ -45,7 +45,7 @@ LLIOPipe::EStatus LLIOFlush::process_impl( } -static LLFastTimer::DeclareTimer FTM_PROCESS_SLEEP("IO Sleep"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_SLEEP("IO Sleep"); /** * @class LLIOSleep */ @@ -56,7 +56,7 @@ LLIOPipe::EStatus LLIOSleep::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_SLEEP); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_SLEEP); if(mSeconds > 0.0) { if(pump) pump->sleepChain(mSeconds); @@ -66,7 +66,7 @@ LLIOPipe::EStatus LLIOSleep::process_impl( return STATUS_DONE; } -static LLFastTimer::DeclareTimer FTM_PROCESS_ADD_CHAIN("Add Chain"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_ADD_CHAIN("Add Chain"); /** * @class LLIOAddChain */ @@ -77,7 +77,7 @@ LLIOPipe::EStatus LLIOAddChain::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_PROCESS_ADD_CHAIN); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_ADD_CHAIN); pump->addChain(mChain, mTimeout); return STATUS_DONE; } diff --git a/indra/llmessage/llmessagebuilder.h b/indra/llmessage/llmessagebuilder.h index bf5be929f2..9b1d3193d8 100644 --- a/indra/llmessage/llmessagebuilder.h +++ b/indra/llmessage/llmessagebuilder.h @@ -49,7 +49,6 @@ class LLMessageBuilder virtual void newMessage(const char* name) = 0; virtual void nextBlock(const char* blockname) = 0; - virtual BOOL removeLastBlock() = 0; // TODO: babbage: remove this horror /** All add* methods expect pointers to canonical strings. */ virtual void addBinaryData( diff --git a/indra/llmessage/llmessagetemplate.cpp b/indra/llmessage/llmessagetemplate.cpp index c4c7e66703..49ee1294b7 100644 --- a/indra/llmessage/llmessagetemplate.cpp +++ b/indra/llmessage/llmessagetemplate.cpp @@ -30,8 +30,12 @@ #include "message.h" +U32 sMsgDataAllocSize = 0; +U32 sMsgdataAllocCount = 0; + void LLMsgVarData::addData(const void *data, S32 size, EMsgVariableType type, S32 data_size) { + sMsgDataAllocSize += size; mSize = size; mDataSize = data_size; if ( (type != MVT_VARIABLE) && (type != MVT_FIXED) @@ -45,6 +49,7 @@ void LLMsgVarData::addData(const void *data, S32 size, EMsgVariableType type, S3 } if(size) { + ++sMsgdataAllocCount; delete[] mData; // Delete it if it already exists mData = new U8[size]; htonmemcpy(mData, data, mType, size); @@ -120,8 +125,8 @@ std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg) for (LLMessageBlock::message_variable_map_t::iterator iter = msg.mMemberVariables.begin(); iter != msg.mMemberVariables.end(); iter++) { - LLMessageVariable& ci = *(*iter); - s << ci; + LLMessageVariable* ci = msg.mMemberVariables.toValue(iter); + s << *ci; } return s; @@ -164,7 +169,7 @@ std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg) for (LLMessageTemplate::message_block_map_t::iterator iter = msg.mMemberBlocks.begin(); iter != msg.mMemberBlocks.end(); iter++) { - LLMessageBlock* ci = *iter; + LLMessageBlock* ci = msg.mMemberBlocks.toValue(iter); s << *ci; } diff --git a/indra/llmessage/llmessagetemplate.h b/indra/llmessage/llmessagetemplate.h index 6effb63c03..7cc6d55446 100644 --- a/indra/llmessage/llmessagetemplate.h +++ b/indra/llmessage/llmessagetemplate.h @@ -32,6 +32,10 @@ #include "llstl.h" #include "llindexedvector.h" +#include + +extern U32 sMsgDataAllocSize; +extern U32 sMsgdataAllocCount; class LLMsgVarData { public: @@ -86,7 +90,7 @@ class LLMsgBlkData for (msg_var_data_map_t::iterator iter = mMemberVarData.begin(); iter != mMemberVarData.end(); iter++) { - iter->deleteData(); + mMemberVarData.toValue(iter).deleteData(); } } @@ -187,21 +191,21 @@ class LLMessageBlock ~LLMessageBlock() { - for_each(mMemberVariables.begin(), mMemberVariables.end(), DeletePointer()); + for_each(mMemberVariables.begin(), mMemberVariables.end(), message_variable_map_t::DeletePointer()); } void addVariable(char *name, const EMsgVariableType type, const S32 size) { - LLMessageVariable** varp = &mMemberVariables[name]; - if (*varp != NULL) + LLMessageVariable*& varp = mMemberVariables[name]; + if (varp != NULL) { LL_ERRS() << name << " has already been used as a variable name!" << LL_ENDL; } - *varp = new LLMessageVariable(name, type, size); - if (((*varp)->getType() != MVT_VARIABLE) - &&(mTotalSize != -1)) + varp = new LLMessageVariable(name, type, size); + if ((varp->getType() != MVT_VARIABLE) + && (mTotalSize != -1)) { - mTotalSize += (*varp)->getSize(); + mTotalSize += varp->getSize(); } else { @@ -222,7 +226,7 @@ class LLMessageBlock const LLMessageVariable* getVariable(char* name) const { message_variable_map_t::const_iterator iter = mMemberVariables.find(name); - return iter != mMemberVariables.end()? *iter : NULL; + return iter != mMemberVariables.end() ? mMemberVariables.toValue(iter) : NULL; } friend std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg); @@ -294,18 +298,18 @@ class LLMessageTemplate ~LLMessageTemplate() { - for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePointer()); + for_each(mMemberBlocks.begin(), mMemberBlocks.end(), message_block_map_t::DeletePointer()); } void addBlock(LLMessageBlock *blockp) { - LLMessageBlock** member_blockp = &mMemberBlocks[blockp->mName]; - if (*member_blockp != NULL) + LLMessageBlock*& member_blockp = mMemberBlocks[blockp->mName]; + if (member_blockp != NULL) { LL_ERRS() << "Block " << blockp->mName << "has already been used as a block name!" << LL_ENDL; } - *member_blockp = blockp; + member_blockp = blockp; if ( (mTotalSize != -1) &&(blockp->mTotalSize != -1) &&( (blockp->mType == MBT_SINGLE) @@ -388,7 +392,7 @@ class LLMessageTemplate const LLMessageBlock* getBlock(char* name) const { message_block_map_t::const_iterator iter = mMemberBlocks.find(name); - return iter != mMemberBlocks.end()? *iter : NULL; + return iter != mMemberBlocks.end()? mMemberBlocks.toValue(iter): NULL; } public: diff --git a/indra/llmessage/llmime.cpp b/indra/llmessage/llmime.cpp deleted file mode 100644 index 9d9c4ebd68..0000000000 --- a/indra/llmessage/llmime.cpp +++ /dev/null @@ -1,629 +0,0 @@ -/** - * @file llmime.cpp - * @author Phoenix - * @date 2006-12-20 - * @brief Implementation of mime tools. - * - * $LicenseInfo:firstyear=2006&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 "llmime.h" - -#include - -#include "llmemorystream.h" - -/** - * Useful constants. - */ -// Headers specified in rfc-2045 will be canonicalized below. -static const std::string CONTENT_LENGTH("Content-Length"); -static const std::string CONTENT_TYPE("Content-Type"); -static const S32 KNOWN_HEADER_COUNT = 6; -static const std::string KNOWN_HEADER[KNOWN_HEADER_COUNT] = -{ - CONTENT_LENGTH, - CONTENT_TYPE, - std::string("MIME-Version"), - std::string("Content-Transfer-Encoding"), - std::string("Content-ID"), - std::string("Content-Description"), -}; - -// parser helpers -static const std::string MULTIPART("multipart"); -static const std::string BOUNDARY("boundary"); -static const std::string END_OF_CONTENT_PARAMETER("\r\n ;\t"); -static const std::string SEPARATOR_PREFIX("--"); -//static const std::string SEPARATOR_SUFFIX("\r\n"); - -/* -Content-Type: multipart/mixed; boundary="segment" -Content-Length: 24832 - ---segment -Content-Type: image/j2c -Content-Length: 23715 - - - ---segment -Content-Type: text/xml; charset=UTF-8 - - -EOF - -*/ - -/** - * LLMimeIndex - */ - -/** - * @class LLMimeIndex::Impl - * @brief Implementation details of the mime index class. - * @see LLMimeIndex - */ -class LLMimeIndex::Impl -{ -public: - Impl() : mOffset(-1), mUseCount(1) - {} - Impl(LLSD headers, S32 offset) : - mHeaders(headers), mOffset(offset), mUseCount(1) - {} -public: - LLSD mHeaders; - S32 mOffset; - S32 mUseCount; - - typedef std::vector sub_part_t; - sub_part_t mAttachments; -}; - -LLSD LLMimeIndex::headers() const -{ - return mImpl->mHeaders; -} - -S32 LLMimeIndex::offset() const -{ - return mImpl->mOffset; -} - -S32 LLMimeIndex::contentLength() const -{ - // Find the content length in the headers. - S32 length = -1; - LLSD content_length = mImpl->mHeaders[CONTENT_LENGTH]; - if(content_length.isDefined()) - { - length = content_length.asInteger(); - } - return length; -} - -std::string LLMimeIndex::contentType() const -{ - std::string type; - LLSD content_type = mImpl->mHeaders[CONTENT_TYPE]; - if(content_type.isDefined()) - { - type = content_type.asString(); - } - return type; -} - -bool LLMimeIndex::isMultipart() const -{ - bool multipart = false; - LLSD content_type = mImpl->mHeaders[CONTENT_TYPE]; - if(content_type.isDefined()) - { - std::string type = content_type.asString(); - int comp = type.compare(0, MULTIPART.size(), MULTIPART); - if(0 == comp) - { - multipart = true; - } - } - return multipart; -} - -S32 LLMimeIndex::subPartCount() const -{ - return mImpl->mAttachments.size(); -} - -LLMimeIndex LLMimeIndex::subPart(S32 index) const -{ - LLMimeIndex part; - if((index >= 0) && (index < (S32)mImpl->mAttachments.size())) - { - part = mImpl->mAttachments[index]; - } - return part; -} - -LLMimeIndex::LLMimeIndex() : mImpl(new LLMimeIndex::Impl) -{ -} - -LLMimeIndex::LLMimeIndex(LLSD headers, S32 content_offset) : - mImpl(new LLMimeIndex::Impl(headers, content_offset)) -{ -} - -LLMimeIndex::LLMimeIndex(const LLMimeIndex& mime) : - mImpl(mime.mImpl) -{ - ++mImpl->mUseCount; -} - -LLMimeIndex::~LLMimeIndex() -{ - if(0 == --mImpl->mUseCount) - { - delete mImpl; - } -} - -LLMimeIndex& LLMimeIndex::operator=(const LLMimeIndex& mime) -{ - // Increment use count first so that we handle self assignment - // automatically. - ++mime.mImpl->mUseCount; - if(0 == --mImpl->mUseCount) - { - delete mImpl; - } - mImpl = mime.mImpl; - return *this; -} - -bool LLMimeIndex::attachSubPart(LLMimeIndex sub_part) -{ - // *FIX: Should we check for multi-part? - if(mImpl->mAttachments.size() < S32_MAX) - { - mImpl->mAttachments.push_back(sub_part); - return true; - } - return false; -} - -/** - * LLMimeParser - */ -/** - * @class LLMimeParser::Impl - * @brief Implementation details of the mime parser class. - * @see LLMimeParser - */ -class LLMimeParser::Impl -{ -public: - // @brief Constructor. - Impl(); - - // @brief Reset this for a new parse. - void reset(); - - /** - * @brief Parse a mime entity to find the index information. - * - * This method will scan the istr until a single complete mime - * entity is read, an EOF, or limit bytes have been scanned. The - * istr will be modified by this parsing, so pass in a temporary - * stream or rewind/reset the stream after this call. - * @param istr An istream which contains a mime entity. - * @param limit The maximum number of bytes to scan. - * @param separator The multipart separator if it is known. - * @param is_subpart Set true if parsing a multipart sub part. - * @param index[out] The parsed output. - * @return Returns true if an index was parsed and no errors occurred. - */ - bool parseIndex( - std::istream& istr, - S32 limit, - const std::string& separator, - bool is_subpart, - LLMimeIndex& index); - -protected: - /** - * @brief parse the headers. - * - * At the end of a successful parse, mScanCount will be at the - * start of the content. - * @param istr The input stream. - * @param limit maximum number of bytes to process - * @param headers[out] A map of the headers found. - * @return Returns true if the parse was successful. - */ - bool parseHeaders(std::istream& istr, S32 limit, LLSD& headers); - - /** - * @brief Figure out the separator string from a content type header. - * - * @param multipart_content_type The content type value from the headers. - * @return Returns the separator string. - */ - std::string findSeparator(std::string multipart_content_type); - - /** - * @brief Scan through istr past the separator. - * - * @param istr The input stream. - * @param limit Maximum number of bytes to scan. - * @param separator The multipart separator. - */ - void scanPastSeparator( - std::istream& istr, - S32 limit, - const std::string& separator); - - /** - * @brief Scan through istr past the content of the current mime part. - * - * @param istr The input stream. - * @param limit Maximum number of bytes to scan. - * @param headers The headers for this mime part. - * @param separator The multipart separator if known. - */ - void scanPastContent( - std::istream& istr, - S32 limit, - LLSD headers, - const std::string separator); - - /** - * @brief Eat CRLF. - * - * This method has no concept of the limit, so ensure you have at - * least 2 characters left to eat before hitting the limit. This - * method will increment mScanCount as it goes. - * @param istr The input stream. - * @return Returns true if CRLF was found and consumed off of istr. - */ - bool eatCRLF(std::istream& istr); - - // @brief Returns true if parsing should continue. - bool continueParse() const { return (!mError && mContinue); } - - // @brief anonymous enumeration for parse buffer size. - enum - { - LINE_BUFFER_LENGTH = 1024 - }; - -protected: - S32 mScanCount; - bool mContinue; - bool mError; - char mBuffer[LINE_BUFFER_LENGTH]; -}; - -LLMimeParser::Impl::Impl() -{ - reset(); -} - -void LLMimeParser::Impl::reset() -{ - mScanCount = 0; - mContinue = true; - mError = false; - mBuffer[0] = '\0'; -} - -bool LLMimeParser::Impl::parseIndex( - std::istream& istr, - S32 limit, - const std::string& separator, - bool is_subpart, - LLMimeIndex& index) -{ - LLSD headers; - bool parsed_something = false; - if(parseHeaders(istr, limit, headers)) - { - parsed_something = true; - LLMimeIndex mime(headers, mScanCount); - index = mime; - if(index.isMultipart()) - { - // Figure out the separator, scan past it, and recurse. - std::string ct = headers[CONTENT_TYPE].asString(); - std::string sep = findSeparator(ct); - scanPastSeparator(istr, limit, sep); - while(continueParse() && parseIndex(istr, limit, sep, true, mime)) - { - index.attachSubPart(mime); - } - } - else - { - // Scan to the end of content. - scanPastContent(istr, limit, headers, separator); - if(is_subpart) - { - scanPastSeparator(istr, limit, separator); - } - } - } - if(mError) return false; - return parsed_something; -} - -bool LLMimeParser::Impl::parseHeaders( - std::istream& istr, - S32 limit, - LLSD& headers) -{ - while(continueParse()) - { - // Get the next line. - // We subtract 1 from the limit so that we make sure - // not to read past limit when we get() the newline. - S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1); - istr.getline(mBuffer, max_get, '\r'); - mScanCount += (S32)istr.gcount(); - int c = istr.get(); - if(EOF == c) - { - mContinue = false; - return false; - } - ++mScanCount; - if(c != '\n') - { - mError = true; - return false; - } - if(mScanCount >= limit) - { - mContinue = false; - } - - // Check if that's the end of headers. - if('\0' == mBuffer[0]) - { - break; - } - - // Split out the name and value. - // *NOTE: The use of strchr() here is safe since mBuffer is - // guaranteed to be NULL terminated from the call to getline() - // above. - char* colon = strchr(mBuffer, ':'); - if(!colon) - { - mError = true; - return false; - } - - // Cononicalize the name part, and store the name: value in - // the headers structure. We do this by iterating through - // 'known' headers and replacing the value found with the - // correct one. - // *NOTE: Not so efficient, but iterating through a small - // subset should not be too much of an issue. - std::string name(mBuffer, colon++ - mBuffer); - while(isspace(*colon)) ++colon; - std::string value(colon); - for(S32 ii = 0; ii < KNOWN_HEADER_COUNT; ++ii) - { - if(0 == LLStringUtil::compareInsensitive(name, KNOWN_HEADER[ii])) - { - name = KNOWN_HEADER[ii]; - break; - } - } - headers[name] = value; - } - if(headers.isUndefined()) return false; - return true; -} - -std::string LLMimeParser::Impl::findSeparator(std::string header) -{ - // 01234567890 - //Content-Type: multipart/mixed; boundary="segment" - std::string separator; - std::string::size_type pos = header.find(BOUNDARY); - if(std::string::npos == pos) return separator; - pos += BOUNDARY.size() + 1; - std::string::size_type end; - if(header[pos] == '"') - { - // the boundary is quoted, find the end from pos, and take the - // substring. - end = header.find('"', ++pos); - if(std::string::npos == end) - { - // poorly formed boundary. - mError = true; - } - } - else - { - // otherwise, it's every character until a whitespace, end of - // line, or another parameter begins. - end = header.find_first_of(END_OF_CONTENT_PARAMETER, pos); - if(std::string::npos == end) - { - // it goes to the end of the string. - end = header.size(); - } - } - if(!mError) separator = header.substr(pos, end - pos); - return separator; -} - -void LLMimeParser::Impl::scanPastSeparator( - std::istream& istr, - S32 limit, - const std::string& sep) -{ - std::ostringstream ostr; - ostr << SEPARATOR_PREFIX << sep; - std::string separator = ostr.str(); - bool found_separator = false; - while(!found_separator && continueParse()) - { - // Subtract 1 from the limit so that we make sure not to read - // past limit when we get() the newline. - S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1); - istr.getline(mBuffer, max_get, '\r'); - mScanCount += (S32)istr.gcount(); - if(istr.gcount() >= LINE_BUFFER_LENGTH - 1) - { - // that's way too long to be a separator, so ignore it. - continue; - } - int c = istr.get(); - if(EOF == c) - { - mContinue = false; - return; - } - ++mScanCount; - if(c != '\n') - { - mError = true; - return; - } - if(mScanCount >= limit) - { - mContinue = false; - } - if(0 == LLStringUtil::compareStrings(std::string(mBuffer), separator)) - { - found_separator = true; - } - } -} - -void LLMimeParser::Impl::scanPastContent( - std::istream& istr, - S32 limit, - LLSD headers, - const std::string separator) -{ - if(headers.has(CONTENT_LENGTH)) - { - S32 content_length = headers[CONTENT_LENGTH].asInteger(); - // Subtract 2 here for the \r\n after the content. - S32 max_skip = llmin(content_length, limit - mScanCount - 2); - istr.ignore(max_skip); - mScanCount += max_skip; - - // *NOTE: Check for hitting the limit and eof here before - // checking for the trailing EOF, because our mime parser has - // to gracefully handle incomplete mime entites. - if((mScanCount >= limit) || istr.eof()) - { - mContinue = false; - } - else if(!eatCRLF(istr)) - { - mError = true; - return; - } - } -} - -bool LLMimeParser::Impl::eatCRLF(std::istream& istr) -{ - int c = istr.get(); - ++mScanCount; - if(c != '\r') - { - return false; - } - c = istr.get(); - ++mScanCount; - if(c != '\n') - { - return false; - } - return true; -} - - -LLMimeParser::LLMimeParser() : mImpl(* new LLMimeParser::Impl) -{ -} - -LLMimeParser::~LLMimeParser() -{ - delete & mImpl; -} - -void LLMimeParser::reset() -{ - mImpl.reset(); -} - -bool LLMimeParser::parseIndex(std::istream& istr, LLMimeIndex& index) -{ - std::string separator; - return mImpl.parseIndex(istr, S32_MAX, separator, false, index); -} - -bool LLMimeParser::parseIndex( - const std::vector& buffer, - LLMimeIndex& index) -{ - LLMemoryStream mstr(&buffer[0], buffer.size()); - return parseIndex(mstr, buffer.size() + 1, index); -} - -bool LLMimeParser::parseIndex( - std::istream& istr, - S32 limit, - LLMimeIndex& index) -{ - std::string separator; - return mImpl.parseIndex(istr, limit, separator, false, index); -} - -bool LLMimeParser::parseIndex(const U8* buffer, S32 length, LLMimeIndex& index) -{ - LLMemoryStream mstr(buffer, length); - return parseIndex(mstr, length + 1, index); -} - -/* -bool LLMimeParser::verify(std::istream& isr, LLMimeIndex& index) const -{ - return false; -} - -bool LLMimeParser::verify(U8* buffer, S32 length, LLMimeIndex& index) const -{ - LLMemoryStream mstr(buffer, length); - return verify(mstr, index); -} -*/ diff --git a/indra/llmessage/llmime.h b/indra/llmessage/llmime.h deleted file mode 100644 index e6617fb503..0000000000 --- a/indra/llmessage/llmime.h +++ /dev/null @@ -1,292 +0,0 @@ -/** - * @file llmime.h - * @author Phoenix - * @date 2006-12-20 - * @brief Declaration of mime tools. - * - * $LicenseInfo:firstyear=2006&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_LLMIME_H -#define LL_LLMIME_H - -#include -#include "llsd.h" - -/** - * This file declares various tools for parsing and creating MIME - * objects as described in RFCs 2045, 2046, 2047, 2048, and 2049. - */ - -/** - * @class LLMimeIndex - * @brief Skeletal information useful for handling mime packages. - * @see LLMimeParser - * - * An instance of this class is the parsed output from a LLMimeParser - * which then allows for easy access into a data stream to find and - * get what you want out of it. - * - * This class meant as a tool to quickly find what you seek in a - * parsed mime entity. As such, it does not have useful support for - * modification of a mime entity and specializes the interface toward - * querying data from a fixed mime entity. Modifying an instance of - * LLMimeIndx does not alter a mime entity and changes to a mime - * entity itself are not propogated into an instance of a LLMimeIndex. - * - * Usage:
    - * LLMimeIndex mime_index;
    - * std::ifstream fstr("package.mime", ios::binary);
    - * LLMimeParser parser;
    - * if(parser.parseIndex(fstr, mime_index))
    - * {
    - * std::vector content;
    - * content.resize(mime_index.contentLength());
    - * fstr.seekg(mime_index.offset(), ios::beg);
    - * // ...do work on fstr and content
    - * }
    - */ -class LLMimeIndex -{ -public: - /* @name Client interface. - */ - //@{ - /** - * @brief Get the full parsed headers for this. - * - * If there are any headers, it will be a map of header name to - * the value found on the line. The name is everything before the - * colon, and the value is the string found after the colon to the - * end of the line after trimming leading whitespace. So, for - * example: - * Content-Type: text/plain - * would become an entry in the headers of: - * headers["Content-Type"] == "text/plain" - * - * If this instance of an index was generated by the - * LLMimeParser::parseIndex() call, all header names in rfc2045 - * will be capitalized as in rfc, eg Content-Length and - * MIME-Version, not content-length and mime-version. - * @return Returns an LLSD map of header name to value. Returns - * undef if there are no headers. - */ - LLSD headers() const; - - /** - * @brief Get the content offset. - * - * @return Returns the number of bytes to the start of the data - * segment from the start of serialized mime entity. Returns -1 if - * offset is not known. - */ - S32 offset() const; - - /** - * @brief Get the length of the data segment for this mime part. - * - * @return Returns the content length in bytes. Returns -1 if - * length is not known. - */ - S32 contentLength() const; - - /** - * @brief Get the mime type associated with this node. - * - * @return Returns the mimetype. - */ - std::string contentType() const; - - /** - * @brief Helper method which simplifies parsing the return from type() - * - * @return Returns true if this is a multipart mime, and therefore - * getting subparts will succeed. - */ - bool isMultipart() const; - - /** - * @brief Get the number of atachments. - * - * @return Returns the number of sub-parts for this. - */ - S32 subPartCount() const; - - /** - * @brief Get the indicated attachment. - * - * @param index Value from 0 to (subPartCount() - 1). - * @return Returns the indicated sub-part, or an invalid mime - * index on failure. - */ - LLMimeIndex subPart(S32 index) const; - //@} - - /* @name Interface for building, testing, and helpers for typical use. - */ - //@{ - /** - * @brief Default constructor - creates a useless LLMimeIndex. - */ - LLMimeIndex(); - - /** - * @brief Full constructor. - * - * @param headers The complete headers. - * @param content_offset The number of bytes to the start of the - * data segment of this mime entity from the start of the stream - * or buffer. - */ - LLMimeIndex(LLSD headers, S32 content_offset); - - /** - * @brief Copy constructor. - * - * @param mime The other mime object. - */ - LLMimeIndex(const LLMimeIndex& mime); - - // @brief Destructor. - ~LLMimeIndex(); - - /* - * @breif Assignment operator. - * - * @param mime The other mime object. - * @return Returns this after assignment. - */ - LLMimeIndex& operator=(const LLMimeIndex& mime); - - /** - * @brief Add attachment information as a sub-part to a multipart mime. - * - * @param sub_part the part to attach. - * @return Returns true on success, false on failure. - */ - bool attachSubPart(LLMimeIndex sub_part); - //@} - -protected: - // Implementation. - class Impl; - Impl* mImpl; -}; - - -/** - * @class LLMimeParser - * @brief This class implements a MIME parser and verifier. - * - * THOROUGH_DESCRIPTION - */ -class LLMimeParser -{ -public: - // @brief Make a new mime parser. - LLMimeParser(); - - // @brief Mime parser Destructor. - ~LLMimeParser(); - - // @brief Reset internal state of this parser. - void reset(); - - - /* @name Index generation interface. - */ - //@{ - /** - * @brief Parse a stream to find the mime index information. - * - * This method will scan the istr until a single complete mime - * entity is read or EOF. The istr will be modified by this - * parsing, so pass in a temporary stream or rewind/reset the - * stream after this call. - * @param istr An istream which contains a mime entity. - * @param index[out] The parsed output. - * @return Returns true if an index was parsed and no errors occurred. - */ - bool parseIndex(std::istream& istr, LLMimeIndex& index); - - /** - * @brief Parse a vector to find the mime index information. - * - * @param buffer A vector with data to parse. - * @param index[out] The parsed output. - * @return Returns true if an index was parsed and no errors occurred. - */ - bool parseIndex(const std::vector& buffer, LLMimeIndex& index); - - /** - * @brief Parse a stream to find the mime index information. - * - * This method will scan the istr until a single complete mime - * entity is read, an EOF, or limit bytes have been scanned. The - * istr will be modified by this parsing, so pass in a temporary - * stream or rewind/reset the stream after this call. - * @param istr An istream which contains a mime entity. - * @param limit The maximum number of bytes to scan. - * @param index[out] The parsed output. - * @return Returns true if an index was parsed and no errors occurred. - */ - bool parseIndex(std::istream& istr, S32 limit, LLMimeIndex& index); - - /** - * @brief Parse a memory bufffer to find the mime index information. - * - * @param buffer The start of the buffer to parse. - * @param buffer_length The length of the buffer. - * @param index[out] The parsed output. - * @return Returns true if an index was parsed and no errors occurred. - */ - bool parseIndex(const U8* buffer, S32 buffer_length, LLMimeIndex& index); - //@} - - /** - * @brief - * - * @return - */ - //bool verify(std::istream& istr, LLMimeIndex& index) const; - - /** - * @brief - * - * @return - */ - //bool verify(U8* buffer, S32 buffer_length, LLMimeIndex& index) const; - -protected: - // Implementation. - class Impl; - Impl& mImpl; - -private: - // @brief Not implemneted to prevent copy consturction. - LLMimeParser(const LLMimeParser& parser); - - // @brief Not implemneted to prevent assignment. - LLMimeParser& operator=(const LLMimeParser& mime); -}; - -#endif // LL_LLMIME_H diff --git a/indra/llmessage/llnamevalue.cpp b/indra/llmessage/llnamevalue.cpp index c51883ee3d..5e63228f1f 100644 --- a/indra/llmessage/llnamevalue.cpp +++ b/indra/llmessage/llnamevalue.cpp @@ -31,7 +31,6 @@ #include "llnamevalue.h" -#include "u64.h" #include "llstring.h" #include "llstringtable.h" @@ -149,7 +148,7 @@ void LLNameValue::init(const char *name, const char *data, const char *type, con else if (!strcmp(mStringType, "U64")) { mType = NVT_U64; - mNameValueReference.u64 = new U64(str_to_U64(ll_safe_string(data))); + mNameValueReference.u64 = new U64(std::stoull(data)); } else if (!strcmp(mStringType, "VEC3")) { @@ -168,7 +167,7 @@ void LLNameValue::init(const char *name, const char *data, const char *type, con } // finite checks - if (!llfinite(t1) || !llfinite(t2) || !llfinite(t3)) + if (!std::isfinite(t1) || !std::isfinite(t2) || !std::isfinite(t3)) { t1 = 0.f; t2 = 0.f; @@ -919,9 +918,7 @@ std::string LLNameValue::printData() const break; case NVT_U64: { - char u64_string[U64_BUFFER_LEN]; /* Flawfinder: ignore */ - U64_to_str(*mNameValueReference.u64, u64_string, sizeof(u64_string)); - buffer = u64_string; + buffer = fmt::to_string(*mNameValueReference.u64); } break; case NVT_VEC3: @@ -952,11 +949,7 @@ std::ostream& operator<<(std::ostream& s, const LLNameValue &a) s << *(a.mNameValueReference.u32); break; case NVT_U64: - { - char u64_string[U64_BUFFER_LEN]; /* Flawfinder: ignore */ - U64_to_str(*a.mNameValueReference.u64, u64_string, sizeof(u64_string)); - s << u64_string; - } + s << (*a.mNameValueReference.u64); break; case NVT_VEC3: s << *(a.mNameValueReference.vec3); diff --git a/indra/llmessage/llpacketack.cpp b/indra/llmessage/llpacketack.cpp index f08d3404ea..c3c022c297 100644 --- a/indra/llmessage/llpacketack.cpp +++ b/indra/llmessage/llpacketack.cpp @@ -50,7 +50,7 @@ LLReliablePacket::LLReliablePacket( mHost = params->mHost; mRetries = params->mRetries; mPingBasedRetry = params->mPingBasedRetry; - mTimeout = params->mTimeout; + mTimeout = F32Seconds(params->mTimeout); mCallback = params->mCallback; mCallbackData = params->mCallbackData; mMessageName = params->mMessageName; @@ -59,13 +59,13 @@ LLReliablePacket::LLReliablePacket( { mRetries = 0; mPingBasedRetry = TRUE; - mTimeout = 0.f; + mTimeout = F32Seconds(0.f); mCallback = NULL; mCallbackData = NULL; mMessageName = NULL; } - mExpirationTime = (F64)((S64)totalTime())/1000000.0 + mTimeout; + mExpirationTime = (F64Seconds)totalTime() + mTimeout; mPacketID = ntohl(*((U32*)(&buf_ptr[PHL_PACKET_ID]))); mSocket = socket; diff --git a/indra/llmessage/llpacketack.h b/indra/llmessage/llpacketack.h index 2ef3c48e44..f0ed923f19 100644 --- a/indra/llmessage/llpacketack.h +++ b/indra/llmessage/llpacketack.h @@ -28,6 +28,7 @@ #define LL_LLPACKETACK_H #include "llhost.h" +#include "llunits.h" class LLReliablePacketParams { @@ -35,7 +36,7 @@ class LLReliablePacketParams LLHost mHost; S32 mRetries; BOOL mPingBasedRetry; - F32 mTimeout; + F32Seconds mTimeout; void (*mCallback)(void **,S32); void** mCallbackData; char* mMessageName; @@ -53,7 +54,7 @@ class LLReliablePacketParams mHost.invalidate(); mRetries = 0; mPingBasedRetry = TRUE; - mTimeout = 0.f; + mTimeout = F32Seconds(0.f); mCallback = NULL; mCallbackData = NULL; mMessageName = NULL; @@ -63,7 +64,7 @@ class LLReliablePacketParams const LLHost& host, S32 retries, BOOL ping_based_retry, - F32 timeout, + F32Seconds timeout, void (*callback)(void**,S32), void** callback_data, char* name) { @@ -98,7 +99,7 @@ class LLReliablePacket LLHost mHost; S32 mRetries; BOOL mPingBasedRetry; - F32 mTimeout; + F32Seconds mTimeout; void (*mCallback)(void**,S32); void** mCallbackData; char* mMessageName; @@ -108,7 +109,7 @@ class LLReliablePacket TPACKETID mPacketID; - F64 mExpirationTime; + F64Seconds mExpirationTime; }; #endif diff --git a/indra/llmessage/llpacketbuffer.cpp b/indra/llmessage/llpacketbuffer.cpp index 21cdf1b16e..ccf991b1a7 100644 --- a/indra/llmessage/llpacketbuffer.cpp +++ b/indra/llmessage/llpacketbuffer.cpp @@ -29,7 +29,7 @@ #include "llpacketbuffer.h" #include "net.h" -#include "timing.h" +#include "lltimer.h" #include "llhost.h" /////////////////////////////////////////////////////////// diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index c3ebbaab58..93c458b37a 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -41,7 +41,6 @@ #include "llproxy.h" #include "llrand.h" #include "message.h" -#include "timing.h" #include "u64.h" // diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 448b6606b3..97d97e742c 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -115,9 +115,9 @@ S32 LLProxy::proxyHandshake(LLHost proxy) U32 request_size = socks_username.size() + socks_password.size() + 3; char * password_auth = new char[request_size]; password_auth[0] = 0x01; - password_auth[1] = socks_username.size(); + password_auth[1] = static_cast(socks_username.size()); memcpy(&password_auth[2], socks_username.c_str(), socks_username.size()); - password_auth[socks_username.size() + 2] = socks_password.size(); + password_auth[socks_username.size() + 2] = static_cast(socks_password.size()); memcpy(&password_auth[socks_username.size() + 3], socks_password.c_str(), socks_password.size()); authmethod_password_reply_t password_reply; diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index 0f9b7c6cdf..965a3d5b7f 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -440,8 +440,8 @@ void LLPumpIO::pump() pump(DEFAULT_POLL_TIMEOUT); } -static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO"); -static LLFastTimer::DeclareTimer FTM_PUMP_POLL("Pump Poll"); +static LLTrace::BlockTimerStatHandle FTM_PUMP_IO("Pump IO"); +static LLTrace::BlockTimerStatHandle FTM_PUMP_POLL("Pump Poll"); LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t& run_chain) { @@ -455,7 +455,7 @@ LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t //timeout is in microseconds void LLPumpIO::pump(const S32& poll_timeout) { - LLFastTimer t1(FTM_PUMP_IO); + LL_RECORD_BLOCK_TIME(FTM_PUMP_IO); //LL_INFOS() << "LLPumpIO::pump()" << LL_ENDL; // Run any pending runners. @@ -536,7 +536,7 @@ void LLPumpIO::pump(const S32& poll_timeout) S32 count = 0; S32 client_id = 0; { - LLFastTimer _(FTM_PUMP_POLL); + LL_RECORD_BLOCK_TIME(FTM_PUMP_POLL); apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd); } PUMP_DEBUG; @@ -783,7 +783,7 @@ bool LLPumpIO::respond( return true; } -static LLFastTimer::DeclareTimer FTM_PUMP_CALLBACK_CHAIN("Chain"); +static LLTrace::BlockTimerStatHandle FTM_PUMP_CALLBACK_CHAIN("Chain"); void LLPumpIO::callback() { @@ -805,7 +805,7 @@ void LLPumpIO::callback() callbacks_t::iterator end = mCallbacks.end(); for(; it != end; ++it) { - LLFastTimer t(FTM_PUMP_CALLBACK_CHAIN); + LL_RECORD_BLOCK_TIME(FTM_PUMP_CALLBACK_CHAIN); // it's always the first and last time for respone chains (*it).mHead = (*it).mChainLinks.begin(); (*it).mInit = true; diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h index c1cf26574f..95faff21b0 100644 --- a/indra/llmessage/llregionflags.h +++ b/indra/llmessage/llregionflags.h @@ -42,6 +42,9 @@ const U64 REGION_FLAGS_RESET_HOME_ON_TELEPORT = (1 << 3); // Does the sun move? const U64 REGION_FLAGS_SUN_FIXED = (1 << 4); +// Does the estate owner allow private parcels? +const U64 REGION_FLAGS_ALLOW_ACCESS_OVERRIDE = (1 << 5); + // Can't change the terrain heightfield, even on owned parcels, // but can plant trees and grass. const U64 REGION_FLAGS_BLOCK_TERRAFORM = (1 << 6); @@ -51,6 +54,9 @@ const U64 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7); // All content wiped once per night const U64 REGION_FLAGS_SANDBOX = (1 << 8); + +const U64 REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE = (1 << 9); + const U64 REGION_FLAGS_GAMING = (1 << 10); // Denotes a gaming region on certain grids const U64 REGION_FLAGS_HIDE_FROM_SEARCH = (1 << 11); // Hides region from search on certain grids const U64 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies @@ -162,21 +168,22 @@ const U32 ESTATE_ACCESS_ALL = ESTATE_ACCESS_ALLOWED_AGENTS | ESTATE_ACCESS_BANNED_AGENTS | ESTATE_ACCESS_MANAGERS; -// for EstateOwnerRequest, estateaccessdelta message -const U32 ESTATE_ACCESS_APPLY_TO_ALL_ESTATES = 1 << 0; -const U32 ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES = 1 << 1; - -const U32 ESTATE_ACCESS_ALLOWED_AGENT_ADD = 1 << 2; -const U32 ESTATE_ACCESS_ALLOWED_AGENT_REMOVE = 1 << 3; -const U32 ESTATE_ACCESS_ALLOWED_GROUP_ADD = 1 << 4; -const U32 ESTATE_ACCESS_ALLOWED_GROUP_REMOVE = 1 << 5; -const U32 ESTATE_ACCESS_BANNED_AGENT_ADD = 1 << 6; -const U32 ESTATE_ACCESS_BANNED_AGENT_REMOVE = 1 << 7; -const U32 ESTATE_ACCESS_MANAGER_ADD = 1 << 8; -const U32 ESTATE_ACCESS_MANAGER_REMOVE = 1 << 9; -const U32 ESTATE_ACCESS_NO_REPLY = 1 << 10; - -const S32 ESTATE_MAX_MANAGERS = 10; +// for EstateOwnerRequest, estateaccessdelta, estateexperiencedelta messages +const U32 ESTATE_ACCESS_APPLY_TO_ALL_ESTATES = 1U << 0; +const U32 ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES = 1U << 1; + +const U32 ESTATE_ACCESS_ALLOWED_AGENT_ADD = 1U << 2; +const U32 ESTATE_ACCESS_ALLOWED_AGENT_REMOVE = 1U << 3; +const U32 ESTATE_ACCESS_ALLOWED_GROUP_ADD = 1U << 4; +const U32 ESTATE_ACCESS_ALLOWED_GROUP_REMOVE = 1U << 5; +const U32 ESTATE_ACCESS_BANNED_AGENT_ADD = 1U << 6; +const U32 ESTATE_ACCESS_BANNED_AGENT_REMOVE = 1U << 7; +const U32 ESTATE_ACCESS_MANAGER_ADD = 1U << 8; +const U32 ESTATE_ACCESS_MANAGER_REMOVE = 1U << 9; +const U32 ESTATE_ACCESS_NO_REPLY = 1U << 10; +const U32 ESTATE_ACCESS_FAILED_BAN_ESTATE_MANAGER = 1U << 11; + +const S32 ESTATE_MAX_MANAGERS = 15; const S32 ESTATE_MAX_ACCESS_IDS = 500; // max for access, banned const S32 ESTATE_MAX_GROUP_IDS = (S32) ESTATE_ACCESS_MAX_ENTRIES_PER_PACKET; @@ -185,6 +192,26 @@ const U32 SWD_OTHERS_LAND_ONLY = (1 << 0); const U32 SWD_ALWAYS_RETURN_OBJECTS = (1 << 1); const U32 SWD_SCRIPTED_ONLY = (1 << 2); +// Controls experience key validity in the estate +const U32 EXPERIENCE_KEY_TYPE_NONE = 0; +const U32 EXPERIENCE_KEY_TYPE_BLOCKED = 1; +const U32 EXPERIENCE_KEY_TYPE_ALLOWED = 2; +const U32 EXPERIENCE_KEY_TYPE_TRUSTED = 3; + +const U32 EXPERIENCE_KEY_TYPE_FIRST = EXPERIENCE_KEY_TYPE_BLOCKED; +const U32 EXPERIENCE_KEY_TYPE_LAST = EXPERIENCE_KEY_TYPE_TRUSTED; + +// +const U32 ESTATE_EXPERIENCE_TRUSTED_ADD = 1U << 2; +const U32 ESTATE_EXPERIENCE_TRUSTED_REMOVE = 1U << 3; +const U32 ESTATE_EXPERIENCE_ALLOWED_ADD = 1U << 4; +const U32 ESTATE_EXPERIENCE_ALLOWED_REMOVE = 1U << 5; +const U32 ESTATE_EXPERIENCE_BLOCKED_ADD = 1U << 6; +const U32 ESTATE_EXPERIENCE_BLOCKED_REMOVE = 1U << 7; + +const S32 ESTATE_MAX_EXPERIENCE_IDS = 8; + + #endif diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp index 49456c71ed..d65ab1bcf7 100644 --- a/indra/llmessage/llsdmessagebuilder.cpp +++ b/indra/llmessage/llsdmessagebuilder.cpp @@ -95,13 +95,6 @@ void LLSDMessageBuilder::nextBlock(const char* blockname) } } -// TODO: Remove this horror... -BOOL LLSDMessageBuilder::removeLastBlock() -{ - /* TODO: finish implementing this */ - return FALSE; -} - void LLSDMessageBuilder::addBinaryData( const char* varname, const void* data, @@ -264,7 +257,7 @@ void LLSDMessageBuilder::copyFromMessageData(const LLMsgData& data) for(; dit != dend; ++dit) { - const LLMsgVarData& mvci = *dit; + const LLMsgVarData& mvci = mbci->mMemberVarData.toValue(dit); const char* varname = mvci.getName(); switch(mvci.getType()) diff --git a/indra/llmessage/llsdmessagebuilder.h b/indra/llmessage/llsdmessagebuilder.h index 9c7c1bfde3..18c8588881 100644 --- a/indra/llmessage/llsdmessagebuilder.h +++ b/indra/llmessage/llsdmessagebuilder.h @@ -48,7 +48,6 @@ class LLSDMessageBuilder : public LLMessageBuilder virtual void newMessage(const char* name); virtual void nextBlock(const char* blockname); - virtual BOOL removeLastBlock(); // TODO: babbage: remove this horror... /** All add* methods expect pointers to canonical varname strings. */ virtual void addBinaryData( diff --git a/indra/llmessage/lltemplatemessagebuilder.cpp b/indra/llmessage/lltemplatemessagebuilder.cpp index 8d7c4c0282..ccc57796bb 100644 --- a/indra/llmessage/lltemplatemessagebuilder.cpp +++ b/indra/llmessage/lltemplatemessagebuilder.cpp @@ -89,7 +89,7 @@ void LLTemplateMessageBuilder::newMessage(const char *name) iter != msg_template->mMemberBlocks.end(); ++iter) { - LLMessageBlock* ci = *iter; + const LLMessageBlock* ci = msg_template->mMemberBlocks.toValue(iter); LLMsgBlkData* tblockp = new LLMsgBlkData(ci->mName, 0); mCurrentSMessageData->addBlock(tblockp); } @@ -151,8 +151,8 @@ void LLTemplateMessageBuilder::nextBlock(const char* blockname) for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin(); iter != template_data->mMemberVariables.end(); iter++) { - LLMessageVariable& ci = **iter; - mCurrentSDataBlock->addVariable(ci.getName(), ci.getType()); + const LLMessageVariable* ci = template_data->mMemberVariables.toValue(iter); + mCurrentSDataBlock->addVariable(ci->getName(), ci->getType()); } return; } @@ -212,76 +212,13 @@ void LLTemplateMessageBuilder::nextBlock(const char* blockname) end = template_data->mMemberVariables.end(); iter != end; iter++) { - LLMessageVariable& ci = **iter; - mCurrentSDataBlock->addVariable(ci.getName(), ci.getType()); + const LLMessageVariable* ci = template_data->mMemberVariables.toValue(iter); + mCurrentSDataBlock->addVariable(ci->getName(), ci->getType()); } return; } } -// TODO: Remove this horror... -BOOL LLTemplateMessageBuilder::removeLastBlock() -{ - if (mCurrentSBlockName) - { - if ( (mCurrentSMessageData) - &&(mCurrentSMessageTemplate)) - { - if (mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber >= 1) - { - // At least one block for the current block name. - - // Store the current block name for future reference. - char *block_name = mCurrentSBlockName; - - // Decrement the sent total by the size of the - // data in the message block that we're currently building. - - const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName); - - for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin(); - iter != template_data->mMemberVariables.end(); iter++) - { - LLMessageVariable& ci = **iter; - mCurrentSendTotal -= ci.getSize(); - } - - - // Now we want to find the block that we're blowing away. - - // Get the number of blocks. - LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name]; - S32 num_blocks = block_data->mBlockNumber; - - // Use the same (suspect?) algorithm that's used to generate - // the names in the nextBlock method to find it. - char *block_getting_whacked = block_name + num_blocks - 1; - LLMsgBlkData* whacked_data = mCurrentSMessageData->mMemberBlocks[block_getting_whacked]; - delete whacked_data; - mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked); - - if (num_blocks <= 1) - { - // we just blew away the last one, so return FALSE - LL_WARNS() << "not blowing away the only block of message " - << mCurrentSMessageName - << ". Block: " << block_name - << ". Number: " << num_blocks - << LL_ENDL; - return FALSE; - } - else - { - // Decrement the counter. - block_data->mBlockNumber--; - return TRUE; - } - } - } - } - return FALSE; -} - // add data to variable in current block void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type, S32 size) { @@ -665,7 +602,7 @@ static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* templat for (LLMsgBlkData::msg_var_data_map_t::const_iterator iter = mbci->mMemberVarData.begin(); iter != mbci->mMemberVarData.end(); iter++) { - const LLMsgVarData& mvci = *iter; + const LLMsgVarData& mvci = mbci->mMemberVarData.toValue(iter); if (mvci.getSize() == -1) { // oops, this variable wasn't ever set! @@ -821,7 +758,8 @@ U32 LLTemplateMessageBuilder::buildMessage( iter != end; ++iter) { - result += buildBlock(buffer + result, buffer_size - result, *iter, mCurrentSMessageData); + const LLMessageBlock* block = mCurrentSMessageTemplate->mMemberBlocks.toValue(iter); + result += buildBlock(buffer + result, buffer_size - result, block, mCurrentSMessageData); } mbSBuilt = TRUE; @@ -864,7 +802,7 @@ void LLTemplateMessageBuilder::copyFromMessageData(const LLMsgData& data) for(; dit != dend; ++dit) { - const LLMsgVarData& mvci = *dit; + const LLMsgVarData& mvci = mbci->mMemberVarData.toValue(dit); addData(mvci.getName(), mvci.getData(), mvci.getType(), mvci.getSize()); } } diff --git a/indra/llmessage/lltemplatemessagebuilder.h b/indra/llmessage/lltemplatemessagebuilder.h index 4f614a4657..ce743974e9 100644 --- a/indra/llmessage/lltemplatemessagebuilder.h +++ b/indra/llmessage/lltemplatemessagebuilder.h @@ -49,7 +49,6 @@ class LLTemplateMessageBuilder : public LLMessageBuilder virtual void newMessage(const char* name); virtual void nextBlock(const char* blockname); - virtual BOOL removeLastBlock(); // TODO: babbage: remove this horror... /** All add* methods expect pointers to canonical varname strings. */ virtual void addBinaryData(const char *varname, const void *data, diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp index 6f728ff35b..306737fb70 100644 --- a/indra/llmessage/lltemplatemessagereader.cpp +++ b/indra/llmessage/lltemplatemessagereader.cpp @@ -326,7 +326,7 @@ void LLTemplateMessageReader::getF32(const char *block, const char *var, { getData(block, var, &d, sizeof(F32), blocknum); - if( !llfinite( d ) ) + if( !std::isfinite( d ) ) { LL_WARNS() << "non-finite in getF32Fast " << block << " " << var << LL_ENDL; @@ -339,7 +339,7 @@ void LLTemplateMessageReader::getF64(const char *block, const char *var, { getData(block, var, &d, sizeof(F64), blocknum); - if( !llfinite( d ) ) + if( !std::isfinite( d ) ) { LL_WARNS() << "non-finite in getF64Fast " << block << " " << var << LL_ENDL; @@ -501,9 +501,10 @@ BOOL LLTemplateMessageReader::decodeTemplate( else { if(!custom) { + // MAINT-7482 - make viewer more tolerant of unknown messages. LL_WARNS() << "Message #" << std::hex << num << std::dec << " received but not registered!" << LL_ENDL; - gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE); + //gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE); } return(FALSE); } @@ -530,7 +531,7 @@ void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host, const S3 gMessageSystem->callExceptionFunc(MX_RAN_OFF_END_OF_PACKET); } -static LLFastTimer::DeclareTimer FTM_PROCESS_MESSAGES("Process Messages"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_MESSAGES("Process Messages"); // decode a given message BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender, bool custom) @@ -554,7 +555,7 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender, iter != mCurrentRMessageTemplate->mMemberBlocks.end(); ++iter) { - LLMessageBlock* mbci = *iter; + const LLMessageBlock* mbci = mCurrentRMessageTemplate->mMemberBlocks.toValue(iter); U8 repeat_number; S32 i; @@ -621,17 +622,17 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender, mbci->mMemberVariables.begin(); iter != mbci->mMemberVariables.end(); iter++) { - const LLMessageVariable& mvci = **iter; + const LLMessageVariable* mvci = mbci->mMemberVariables.toValue(iter); // ok, build out the variables // add variable block - cur_data_block->addVariable(mvci.getName(), mvci.getType()); + cur_data_block->addVariable(mvci->getName(), mvci->getType()); // what type of variable? - if (mvci.getType() == MVT_VARIABLE) + if (mvci->getType() == MVT_VARIABLE) { // variable, get the number of bytes to read from the template - S32 data_size = mvci.getSize(); + S32 data_size = mvci->getSize(); U8 tsizeb = 0; U16 tsizeh = 0; U32 tsize = 0; @@ -666,32 +667,32 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender, } decode_pos += data_size; - cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType()); + cur_data_block->addData(mvci->getName(), &buffer[decode_pos], tsize, mvci->getType()); decode_pos += tsize; } else { // fixed! // so, copy data pointer and set data size to fixed size - if ((decode_pos + mvci.getSize()) > mReceiveSize) + if ((decode_pos + mvci->getSize()) > mReceiveSize) { if(!custom) - logRanOffEndOfPacket(sender, decode_pos, mvci.getSize()); + logRanOffEndOfPacket(sender, decode_pos, mvci->getSize()); // default to 0s. - U32 size = mvci.getSize(); + U32 size = mvci->getSize(); std::vector data(size, 0); - cur_data_block->addData(mvci.getName(), &(data[0]), - size, mvci.getType()); + cur_data_block->addData(mvci->getName(), &(data[0]), + size, mvci->getType()); } else { - cur_data_block->addData(mvci.getName(), + cur_data_block->addData(mvci->getName(), &buffer[decode_pos], - mvci.getSize(), - mvci.getType()); + mvci->getSize(), + mvci->getType()); } - decode_pos += mvci.getSize(); + decode_pos += mvci->getSize(); } } } @@ -714,7 +715,7 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender, } { - LLFastTimer t(FTM_PROCESS_MESSAGES); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_MESSAGES); if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) ) { LL_WARNS() << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << LL_ENDL; diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp index 1cf034534c..edd230a8da 100644 --- a/indra/llmessage/llthrottle.cpp +++ b/indra/llmessage/llthrottle.cpp @@ -53,8 +53,8 @@ F32 LLThrottle::getAvailable() { // use a temporary bits_available // since we don't want to change mBitsAvailable every time - F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime); - return mAvailable + (mRate * elapsed_time); + F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime; + return mAvailable + (mRate * elapsed_time.value()); } BOOL LLThrottle::checkOverflow(const F32 amount) @@ -65,8 +65,8 @@ BOOL LLThrottle::checkOverflow(const F32 amount) // use a temporary bits_available // since we don't want to change mBitsAvailable every time - F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime); - F32 amount_available = mAvailable + (mRate * elapsed_time); + F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime; + F32 amount_available = mAvailable + (mRate * elapsed_time.value()); if ((amount_available >= lookahead_amount) || (amount_available > amount)) { @@ -80,17 +80,17 @@ BOOL LLThrottle::checkOverflow(const F32 amount) BOOL LLThrottle::throttleOverflow(const F32 amount) { - F32 elapsed_time; + F32Seconds elapsed_time; F32 lookahead_amount; BOOL retval = TRUE; lookahead_amount = mRate * mLookaheadSecs; - F64 mt_sec = LLMessageSystem::getMessageTimeSeconds(); - elapsed_time = (F32)(mt_sec - mLastSendTime); + F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds(); + elapsed_time = mt_sec - mLastSendTime; mLastSendTime = mt_sec; - mAvailable += mRate * elapsed_time; + mAvailable += mRate * elapsed_time.value(); if (mAvailable >= lookahead_amount) { @@ -222,7 +222,7 @@ void LLThrottleGroup::unpackThrottle(LLDataPacker &dp) // into NOT resetting the system. void LLThrottleGroup::resetDynamicAdjust() { - F64 mt_sec = LLMessageSystem::getMessageTimeSeconds(); + F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds(); S32 i; for (i = 0; i < TC_EOF; i++) { @@ -269,8 +269,8 @@ S32 LLThrottleGroup::getAvailable(S32 throttle_cat) // use a temporary bits_available // since we don't want to change mBitsAvailable every time - F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]); - F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time); + F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]; + F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time.value()); if (bits_available >= lookahead_bits) { @@ -294,8 +294,8 @@ BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits) // use a temporary bits_available // since we don't want to change mBitsAvailable every time - F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]); - F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time); + F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]; + F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time.value()); if (bits_available >= lookahead_bits) { @@ -315,7 +315,7 @@ BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits) BOOL LLThrottleGroup::throttleOverflow(S32 throttle_cat, F32 bits) { - F32 elapsed_time; + F32Seconds elapsed_time; F32 category_bps; F32 lookahead_bits; BOOL retval = TRUE; @@ -323,10 +323,10 @@ BOOL LLThrottleGroup::throttleOverflow(S32 throttle_cat, F32 bits) category_bps = mCurrentBPS[throttle_cat]; lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME; - F64 mt_sec = LLMessageSystem::getMessageTimeSeconds(); - elapsed_time = (F32)(mt_sec - mLastSendTime[throttle_cat]); + F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds(); + elapsed_time = mt_sec - mLastSendTime[throttle_cat]; mLastSendTime[throttle_cat] = mt_sec; - mBitsAvailable[throttle_cat] += category_bps * elapsed_time; + mBitsAvailable[throttle_cat] += category_bps * elapsed_time.value(); if (mBitsAvailable[throttle_cat] >= lookahead_bits) { @@ -356,7 +356,7 @@ BOOL LLThrottleGroup::throttleOverflow(S32 throttle_cat, F32 bits) BOOL LLThrottleGroup::dynamicAdjust() { - const F32 DYNAMIC_ADJUST_TIME = 1.0f; // seconds + const F32Seconds DYNAMIC_ADJUST_TIME(1.0f); const F32 CURRENT_PERIOD_WEIGHT = .25f; // how much weight to give to last period while determining BPS utilization const F32 BUSY_PERCENT = 0.75f; // if use more than this fraction of BPS, you are busy const F32 IDLE_PERCENT = 0.70f; // if use less than this fraction, you are "idle" @@ -365,7 +365,7 @@ BOOL LLThrottleGroup::dynamicAdjust() S32 i; - F64 mt_sec = LLMessageSystem::getMessageTimeSeconds(); + F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds(); // Only dynamically adjust every few seconds if ((mt_sec - mDynamicAdjustTime) < DYNAMIC_ADJUST_TIME) @@ -391,7 +391,7 @@ BOOL LLThrottleGroup::dynamicAdjust() } mBitsSentThisPeriod[i] = 0; - total += ll_round(mBitsSentHistory[i]); + total += ll_pos_round(mBitsSentHistory[i]); } // Look for busy channels @@ -405,7 +405,7 @@ BOOL LLThrottleGroup::dynamicAdjust() for (i = 0; i < TC_EOF; i++) { // Is this a busy channel? - if (mBitsSentHistory[i] >= BUSY_PERCENT * DYNAMIC_ADJUST_TIME * mCurrentBPS[i]) + if (mBitsSentHistory[i] >= BUSY_PERCENT * DYNAMIC_ADJUST_TIME.value() * mCurrentBPS[i]) { // this channel is busy channels_busy = TRUE; @@ -418,7 +418,7 @@ BOOL LLThrottleGroup::dynamicAdjust() } // Is this an idle channel? - if ((mBitsSentHistory[i] < IDLE_PERCENT * DYNAMIC_ADJUST_TIME * mCurrentBPS[i]) && + if ((mBitsSentHistory[i] < IDLE_PERCENT * DYNAMIC_ADJUST_TIME.value() * mCurrentBPS[i]) && (mBitsAvailable[i] > 0)) { channel_idle[i] = TRUE; @@ -462,7 +462,7 @@ BOOL LLThrottleGroup::dynamicAdjust() // Therefore it's a candidate to give up some bandwidth. // Figure out how much bandwidth it has been using, and how // much is available to steal. - used_bps = mBitsSentHistory[i] / DYNAMIC_ADJUST_TIME; + used_bps = mBitsSentHistory[i] / DYNAMIC_ADJUST_TIME.value(); // CRO make sure to keep a minimum amount of throttle available // CRO NB: channels set to < MINIMUM_BPS will never give up bps, diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h index ed0aeb4602..e43e54f61b 100644 --- a/indra/llmessage/llthrottle.h +++ b/indra/llmessage/llthrottle.h @@ -50,7 +50,7 @@ class LLThrottle F32 mLookaheadSecs; // Seconds to look ahead, maximum F32 mRate; // BPS available, dynamically adjusted F32 mAvailable; // Bits available to send right now on each channel - F64 mLastSendTime; // Time since last send on this channel + F64Seconds mLastSendTime; // Time since last send on this channel }; typedef enum e_throttle_categories @@ -93,8 +93,8 @@ class LLThrottleGroup F32 mBitsSentThisPeriod[TC_EOF]; // Sent in this dynamic allocation period F32 mBitsSentHistory[TC_EOF]; // Sent before this dynamic allocation period, adjusted to one period length - F64 mLastSendTime[TC_EOF]; // Time since last send on this channel - F64 mDynamicAdjustTime; // Only dynamic adjust every 2 seconds or so. + F64Seconds mLastSendTime[TC_EOF]; // Time since last send on this channel + F64Seconds mDynamicAdjustTime; // Only dynamic adjust every 2 seconds or so. }; diff --git a/indra/llmessage/lltransfermanager.cpp b/indra/llmessage/lltransfermanager.cpp index e647df1c11..ec7b21d8b6 100644 --- a/indra/llmessage/lltransfermanager.cpp +++ b/indra/llmessage/lltransfermanager.cpp @@ -606,16 +606,21 @@ void LLTransferManager::processTransferAbort(LLMessageSystem *msgp, void **) void LLTransferManager::reliablePacketCallback(void **user_data, S32 result) { LLUUID *transfer_idp = (LLUUID *)user_data; - if (result) + if (result && + transfer_idp != NULL) { - LL_WARNS() << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << LL_ENDL; LLTransferSource *tsp = gTransferManager.findTransferSource(*transfer_idp); if (tsp) { + LL_WARNS() << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << LL_ENDL; LLTransferSourceChannel *tscp = tsp->mChannelp; tsp->abortTransfer(); tscp->deleteTransfer(tsp); } + else + { + LL_WARNS() << "Aborting reliable transfer " << *transfer_idp << " but can't find the LLTransferSource object" << LL_ENDL; + } } delete transfer_idp; } @@ -815,7 +820,7 @@ void LLTransferSourceChannel::updateTransfers() gMessageSystem->addS32("Status", status); gMessageSystem->addBinaryData("Data", datap, data_size); sent_bytes = gMessageSystem->getCurrentSendTotal(); - gMessageSystem->sendReliable(getHost(), LL_DEFAULT_RELIABLE_RETRIES, TRUE, 0.f, + gMessageSystem->sendReliable(getHost(), LL_DEFAULT_RELIABLE_RETRIES, TRUE, F32Seconds(0.f), LLTransferManager::reliablePacketCallback, (void**)cb_uuid); // Do bookkeeping for the throttle @@ -892,22 +897,26 @@ LLTransferSource *LLTransferSourceChannel::findTransferSource(const LLUUID &tran } -BOOL LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp) +void LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp) { - - LLPriQueueMap::pqm_iter iter; - for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++) + if (tsp) { - if (iter->second == tsp) + LLPriQueueMap::pqm_iter iter; + for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++) { - delete tsp; - mTransferSources.mMap.erase(iter); - return TRUE; + if (iter->second == tsp) + { + delete tsp; + mTransferSources.mMap.erase(iter); + return; + } } - } - LL_ERRS() << "Unable to find transfer source to delete!" << LL_ENDL; - return FALSE; + LL_WARNS() << "Unable to find transfer source id " + << tsp->getID() + << " to delete!" + << LL_ENDL; + } } @@ -1008,21 +1017,26 @@ LLTransferTarget *LLTransferTargetChannel::findTransferTarget(const LLUUID &tran } -BOOL LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp) +void LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp) { - tt_iter iter; - for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++) + if (ttp) { - if (*iter == ttp) + tt_iter iter; + for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++) { - delete ttp; - mTransferTargets.erase(iter); - return TRUE; + if (*iter == ttp) + { + delete ttp; + mTransferTargets.erase(iter); + return; + } } - } - LL_ERRS() << "Unable to find transfer target to delete!" << LL_ENDL; - return FALSE; + LL_WARNS() << "Unable to find transfer target id " + << ttp->getID() + << " to delete!" + << LL_ENDL; + } } @@ -1246,9 +1260,13 @@ bool LLTransferTarget::addDelayedPacket( size); #ifdef _DEBUG - if (mDelayedPacketMap.find(packet_id) != mDelayedPacketMap.end()) + transfer_packet_map::iterator iter = mDelayedPacketMap.find(packet_id); + if (iter != mDelayedPacketMap.end()) { - LL_ERRS() << "Packet ALREADY in delayed packet map!" << LL_ENDL; + if (!(iter->second->mSize == size) && !(iter->second->mDatap == datap)) + { + LL_ERRS() << "Packet ALREADY in delayed packet map!" << LL_ENDL; + } } #endif diff --git a/indra/llmessage/lltransfermanager.h b/indra/llmessage/lltransfermanager.h index 252e05d1d1..6aad153c24 100644 --- a/indra/llmessage/lltransfermanager.h +++ b/indra/llmessage/lltransfermanager.h @@ -199,7 +199,7 @@ class LLTransferSourceChannel void addTransferSource(LLTransferSource *sourcep); LLTransferSource *findTransferSource(const LLUUID &transfer_id); - BOOL deleteTransfer(LLTransferSource *tsp); + void deleteTransfer(LLTransferSource *tsp); void setThrottleID(const S32 throttle_id) { mThrottleID = throttle_id; } @@ -232,7 +232,7 @@ class LLTransferTargetChannel const F32 priority); LLTransferTarget *findTransferTarget(const LLUUID &transfer_id); - BOOL deleteTransfer(LLTransferTarget *ttp); + void deleteTransfer(LLTransferTarget *ttp); LLTransferChannelType getChannelType() const { return mChannelType; } diff --git a/indra/llmessage/lltransfertargetvfile.cpp b/indra/llmessage/lltransfertargetvfile.cpp index 3c234b9726..a572c68a7f 100644 --- a/indra/llmessage/lltransfertargetvfile.cpp +++ b/indra/llmessage/lltransfertargetvfile.cpp @@ -42,7 +42,7 @@ LLTransferTargetParamsVFile::LLTransferTargetParamsVFile() : LLTransferTargetParams(LLTTT_VFILE), mAssetType(LLAssetType::AT_NONE), mCompleteCallback(NULL), - mUserDatap(NULL), + mRequestDatap(NULL), mErrCode(0) { } @@ -55,10 +55,14 @@ void LLTransferTargetParamsVFile::setAsset( mAssetType = asset_type; } -void LLTransferTargetParamsVFile::setCallback(LLTTVFCompleteCallback cb, void *user_data) +void LLTransferTargetParamsVFile::setCallback(LLTTVFCompleteCallback cb, LLBaseDownloadRequest& request) { mCompleteCallback = cb; - mUserDatap = user_data; + if (mRequestDatap) + { + delete mRequestDatap; + } + mRequestDatap = request.getCopy(); } bool LLTransferTargetParamsVFile::unpackParams(LLDataPacker& dp) @@ -98,6 +102,12 @@ LLTransferTargetVFile::LLTransferTargetVFile( LLTransferTargetVFile::~LLTransferTargetVFile() { + if (mParams.mRequestDatap) + { + // TODO: Consider doing it in LLTransferTargetParamsVFile's destructor + delete mParams.mRequestDatap; + mParams.mRequestDatap = NULL; + } } @@ -208,12 +218,18 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status) err_code = LL_ERR_ASSET_REQUEST_FAILED; break; } - if (mParams.mCompleteCallback) - { - mParams.mCompleteCallback(err_code, - mParams.getAssetID(), - mParams.getAssetType(), - mParams.mUserDatap, - LL_EXSTAT_NONE); - } + + if (mParams.mRequestDatap) + { + if (mParams.mCompleteCallback) + { + mParams.mCompleteCallback(err_code, + mParams.getAssetID(), + mParams.getAssetType(), + mParams.mRequestDatap, + LL_EXSTAT_NONE); + } + delete mParams.mRequestDatap; + mParams.mRequestDatap = NULL; + } } diff --git a/indra/llmessage/lltransfertargetvfile.h b/indra/llmessage/lltransfertargetvfile.h index 23a65e4bb2..c819c1e2f2 100644 --- a/indra/llmessage/lltransfertargetvfile.h +++ b/indra/llmessage/lltransfertargetvfile.h @@ -39,7 +39,7 @@ typedef void (*LLTTVFCompleteCallback)( S32 status, const LLUUID& file_id, LLAssetType::EType file_type, - void* user_data, LLExtStat ext_status ); + LLBaseDownloadRequest* user_data, LLExtStat ext_status ); class LLTransferTargetParamsVFile : public LLTransferTargetParams { @@ -47,7 +47,7 @@ class LLTransferTargetParamsVFile : public LLTransferTargetParams LLTransferTargetParamsVFile(); void setAsset(const LLUUID& asset_id, LLAssetType::EType asset_type); - void setCallback(LLTTVFCompleteCallback cb, void* user_data); + void setCallback(LLTTVFCompleteCallback cb, LLBaseDownloadRequest& request); LLUUID getAssetID() const { return mAssetID; } LLAssetType::EType getAssetType() const { return mAssetType; } @@ -60,7 +60,7 @@ class LLTransferTargetParamsVFile : public LLTransferTargetParams LLAssetType::EType mAssetType; LLTTVFCompleteCallback mCompleteCallback; - void* mUserDatap; + LLBaseDownloadRequest* mRequestDatap; S32 mErrCode; }; diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 4fb27892f8..961e9196d5 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -224,7 +224,7 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w) curlEasyRequest_w->setopt(CURLOPT_HTTPGET, 1); // Set Accept-Encoding to allow response compression - curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : ""); + curlEasyRequest_w->setopt(CURLOPT_ACCEPT_ENCODING, mNoCompression ? "identity" : nullptr); rv = true; break; @@ -234,7 +234,7 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w) curlEasyRequest_w->setPut(mBodySize, mKeepAlive); // Set Accept-Encoding to allow response compression - curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : ""); + curlEasyRequest_w->setopt(CURLOPT_ACCEPT_ENCODING, mNoCompression ? "identity" : nullptr); rv = true; break; @@ -243,7 +243,7 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w) curlEasyRequest_w->setPatch(mBodySize, mKeepAlive); - curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : ""); + curlEasyRequest_w->setopt(CURLOPT_ACCEPT_ENCODING, mNoCompression ? "identity" : nullptr); rv = true; break; @@ -253,7 +253,7 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w) curlEasyRequest_w->setPost(mBodySize, mKeepAlive); // Set Accept-Encoding to allow response compression - curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : ""); + curlEasyRequest_w->setopt(CURLOPT_ACCEPT_ENCODING, mNoCompression ? "identity" : nullptr); rv = true; break; diff --git a/indra/llmessage/llxfer.cpp b/indra/llmessage/llxfer.cpp index 4aba5cae72..81815edcf6 100644 --- a/indra/llmessage/llxfer.cpp +++ b/indra/llmessage/llxfer.cpp @@ -30,7 +30,6 @@ #include "lluuid.h" #include "llerror.h" #include "llmath.h" -#include "u64.h" //number of bytes sent in each message const U32 LL_XFER_CHUNK_SIZE = 1000; @@ -63,7 +62,6 @@ void LLXfer::init (S32 chunk_size) mXferSize = 0; mStatus = e_LL_XFER_UNINITIALIZED; - mNext = NULL; mWaitingForACK = FALSE; mCallback = NULL; @@ -99,7 +97,22 @@ void LLXfer::cleanup () S32 LLXfer::startSend (U64 xfer_id, const LLHost &remote_host) { - LL_WARNS() << "undifferentiated LLXfer::startSend for " << getFileName() << LL_ENDL; + LL_WARNS("Xfer") << "unexpected call to base class LLXfer::startSend for " << getFileName() << LL_ENDL; + return (-1); +} + +/////////////////////////////////////////////////////////// + +void LLXfer::closeFileHandle() +{ + LL_WARNS("Xfer") << "unexpected call to base class LLXfer::closeFileHandle for " << getFileName() << LL_ENDL; +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer::reopenFileHandle() +{ + LL_WARNS("Xfer") << "unexpected call to base class LLXfer::reopenFileHandle for " << getFileName() << LL_ENDL; return (-1); } @@ -115,7 +128,7 @@ void LLXfer::setXferSize (S32 xfer_size) S32 LLXfer::startDownload() { - LL_WARNS() << "undifferentiated LLXfer::startDownload for " << getFileName() + LL_WARNS("Xfer") << "undifferentiated LLXfer::startDownload for " << getFileName() << LL_ENDL; return (-1); } @@ -140,7 +153,7 @@ S32 LLXfer::receiveData (char *datap, S32 data_size) } else { - LL_ERRS() << "NULL data passed in receiveData" << LL_ENDL; + LL_ERRS("Xfer") << "NULL data passed in receiveData" << LL_ENDL; } } @@ -163,7 +176,7 @@ S32 LLXfer::flush() S32 LLXfer::suck(S32 start_position) { - LL_WARNS() << "Attempted to send a packet outside the buffer bounds in LLXfer::suck()" << LL_ENDL; + LL_WARNS("Xfer") << "Attempted to send a packet outside the buffer bounds in LLXfer::suck()" << LL_ENDL; return (-1); } @@ -196,7 +209,7 @@ void LLXfer::sendPacket(S32 packet_num) if (fdata_size < 0) { - LL_WARNS() << "negative data size in xfer send, aborting" << LL_ENDL; + LL_WARNS("Xfer") << "negative data size in xfer send, aborting" << LL_ENDL; abort(LL_ERR_EOF); return; } @@ -248,7 +261,12 @@ void LLXfer::sendPacket(S32 packet_num) gMessageSystem->nextBlockFast(_PREHASH_DataPacket); gMessageSystem->addBinaryDataFast(_PREHASH_Data, &fdata_buf,fdata_size); - gMessageSystem->sendMessage(mRemoteHost); + S32 sent_something = gMessageSystem->sendMessage(mRemoteHost); + if (sent_something == 0) + { + abort(LL_ERR_CIRCUIT_GONE); + return; + } ACKTimer.reset(); mWaitingForACK = TRUE; @@ -289,12 +307,12 @@ S32 LLXfer::processEOF() if (LL_ERR_NOERR == mCallbackResult) { - LL_INFOS() << "xfer from " << mRemoteHost << " complete: " << getFileName() + LL_INFOS("Xfer") << "xfer from " << mRemoteHost << " complete: " << getFileName() << LL_ENDL; } else { - LL_INFOS() << "xfer from " << mRemoteHost << " failed, code " + LL_INFOS("Xfer") << "xfer from " << mRemoteHost << " failed, code " << mCallbackResult << ": " << getFileName() << LL_ENDL; } @@ -323,15 +341,18 @@ void LLXfer::abort (S32 result_code) { mCallbackResult = result_code; - LL_INFOS() << "Aborting xfer from " << mRemoteHost << " named " << getFileName() + LL_INFOS("Xfer") << "Aborting xfer from " << mRemoteHost << " named " << getFileName() << " - error: " << result_code << LL_ENDL; - gMessageSystem->newMessageFast(_PREHASH_AbortXfer); - gMessageSystem->nextBlockFast(_PREHASH_XferID); - gMessageSystem->addU64Fast(_PREHASH_ID, mID); - gMessageSystem->addS32Fast(_PREHASH_Result, result_code); - - gMessageSystem->sendMessage(mRemoteHost); + if (result_code != LL_ERR_CIRCUIT_GONE) + { + gMessageSystem->newMessageFast(_PREHASH_AbortXfer); + gMessageSystem->nextBlockFast(_PREHASH_XferID); + gMessageSystem->addU64Fast(_PREHASH_ID, mID); + gMessageSystem->addS32Fast(_PREHASH_Result, result_code); + + gMessageSystem->sendMessage(mRemoteHost); + } mStatus = e_LL_XFER_ABORTED; } @@ -341,7 +362,7 @@ void LLXfer::abort (S32 result_code) std::string LLXfer::getFileName() { - return U64_to_str(mID); + return fmt::to_string(mID); } /////////////////////////////////////////////////////////// diff --git a/indra/llmessage/llxfer.h b/indra/llmessage/llxfer.h index edf5eeb82d..064278afd4 100644 --- a/indra/llmessage/llxfer.h +++ b/indra/llmessage/llxfer.h @@ -54,7 +54,6 @@ class LLXfer S32 mChunkSize; public: - LLXfer *mNext; U64 mID; S32 mPacketNum; @@ -90,7 +89,9 @@ class LLXfer void init(S32 chunk_size); virtual void cleanup(); - virtual S32 startSend (U64 xfer_id, const LLHost &remote_host); + virtual S32 startSend(U64 xfer_id, const LLHost &remote_host); + virtual void closeFileHandle(); + virtual S32 reopenFileHandle(); virtual void sendPacket(S32 packet_num); virtual void sendNextPacket(); virtual void resendLastPacket(); diff --git a/indra/llmessage/llxfer_file.cpp b/indra/llmessage/llxfer_file.cpp index 257a13f277..41d7dcd6c7 100644 --- a/indra/llmessage/llxfer_file.cpp +++ b/indra/llmessage/llxfer_file.cpp @@ -98,16 +98,16 @@ void LLXfer_File::cleanup () mFp = NULL; } - LLFile::remove(mTempFilename); + LLFile::remove(mTempFilename, ENOENT); if (mDeleteLocalOnCompletion) { - LL_DEBUGS() << "Removing file: " << mLocalFilename << LL_ENDL; - LLFile::remove(mLocalFilename); + LL_DEBUGS("Xfer") << "Removing file: " << mLocalFilename << LL_ENDL; + LLFile::remove(mLocalFilename, ENOENT); } else { - LL_DEBUGS() << "Keeping local file: " << mLocalFilename << LL_ENDL; + LL_DEBUGS("Xfer") << "Keeping local file: " << mLocalFilename << LL_ENDL; } LLXfer::cleanup(); @@ -139,7 +139,7 @@ S32 LLXfer_File::initializeRequest(U64 xfer_id, mCallbackDataHandle = user_data; mCallbackResult = LL_ERR_NOERR; - LL_INFOS() << "Requesting xfer from " << remote_host << " for file: " << mLocalFilename << LL_ENDL; + LL_INFOS("Xfer") << "Requesting xfer from " << remote_host << " for file: " << mLocalFilename << LL_ENDL; if (mBuffer) { @@ -182,7 +182,7 @@ S32 LLXfer_File::startDownload() } else { - LL_WARNS() << "Couldn't create file to be received!" << LL_ENDL; + LL_WARNS("Xfer") << "Couldn't create file to be received!" << LL_ENDL; retval = -1; } @@ -223,7 +223,7 @@ S32 LLXfer_File::startSend (U64 xfer_id, const LLHost &remote_host) } else { - LL_INFOS() << "Warning: " << mLocalFilename << " not found." << LL_ENDL; + LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found." << LL_ENDL; return (LL_ERR_FILE_NOT_FOUND); } @@ -232,6 +232,36 @@ S32 LLXfer_File::startSend (U64 xfer_id, const LLHost &remote_host) return (retval); } +/////////////////////////////////////////////////////////// +void LLXfer_File::closeFileHandle() +{ + if (mFp) + { + fclose(mFp); + mFp = NULL; + } +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_File::reopenFileHandle() +{ + S32 retval = LL_ERR_NOERR; // presume success + + if (mFp == NULL) + { + mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */ + if (mFp == NULL) + { + LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found when re-opening file" << LL_ENDL; + retval = LL_ERR_FILE_NOT_FOUND; + } + } + + return retval; +} + + /////////////////////////////////////////////////////////// S32 LLXfer_File::getMaxBufferSize () @@ -279,18 +309,21 @@ S32 LLXfer_File::flush() { if (mFp) { - LL_ERRS() << "Overwriting open file pointer!" << LL_ENDL; + LL_ERRS("Xfer") << "Overwriting open file pointer!" << LL_ENDL; } mFp = LLFile::fopen(mTempFilename,"a+b"); /* Flawfinder : ignore */ if (mFp) { - if (fwrite(mBuffer,1,mBufferLength,mFp) != mBufferLength) + S32 write_size = fwrite(mBuffer,1,mBufferLength,mFp); + if (write_size != mBufferLength) { - LL_WARNS() << "Short write" << LL_ENDL; + LL_WARNS("Xfer") << "Non-matching write size, requested " << mBufferLength + << " but wrote " << write_size + << LL_ENDL; } -// LL_INFOS() << "******* wrote " << mBufferLength << " bytes of file xfer" << LL_ENDL; +// LL_INFOS("Xfer") << "******* wrote " << mBufferLength << " bytes of file xfer" << LL_ENDL; fclose(mFp); mFp = NULL; @@ -298,7 +331,7 @@ S32 LLXfer_File::flush() } else { - LL_WARNS() << "LLXfer_File::flush() unable to open " << mTempFilename << " for writing!" << LL_ENDL; + LL_WARNS("Xfer") << "LLXfer_File::flush() unable to open " << mTempFilename << " for writing!" << LL_ENDL; retval = LL_ERR_CANNOT_OPEN_FILE; } } @@ -321,7 +354,7 @@ S32 LLXfer_File::processEOF() mCallbackResult = flushval; } - LLFile::remove(mLocalFilename); + LLFile::remove(mLocalFilename, ENOENT); if (!mCallbackResult) { @@ -329,18 +362,18 @@ S32 LLXfer_File::processEOF() { #if !LL_WINDOWS S32 error_number = errno; - LL_INFOS() << "Rename failure (" << error_number << ") - " + LL_INFOS("Xfer") << "Rename failure (" << error_number << ") - " << mTempFilename << " to " << mLocalFilename << LL_ENDL; if(EXDEV == error_number) { if(copy_file(mTempFilename, mLocalFilename) == 0) { - LL_INFOS() << "Rename across mounts; copying+unlinking the file instead." << LL_ENDL; + LL_INFOS("Xfer") << "Rename across mounts; copying+unlinking the file instead." << LL_ENDL; unlink(mTempFilename.c_str()); } else { - LL_WARNS() << "Copy failure - " << mTempFilename << " to " + LL_WARNS("Xfer") << "Copy failure - " << mTempFilename << " to " << mLocalFilename << LL_ENDL; } } @@ -354,11 +387,11 @@ S32 LLXfer_File::processEOF() //LL_WARNS() << "File " << mLocalFilename << " does " // << (!fp ? "not" : "" ) << " exit." << LL_ENDL; //if(fp) fclose(fp); - LL_WARNS() << "Rename fatally failed, can only handle EXDEV (" + LL_WARNS("Xfer") << "Rename fatally failed, can only handle EXDEV (" << EXDEV << ")" << LL_ENDL; } #else - LL_WARNS() << "Rename failure - " << mTempFilename << " to " + LL_WARNS("Xfer") << "Rename failure - " << mTempFilename << " to " << mLocalFilename << LL_ENDL; #endif } diff --git a/indra/llmessage/llxfer_file.h b/indra/llmessage/llxfer_file.h index a37dda6732..ab9374549e 100644 --- a/indra/llmessage/llxfer_file.h +++ b/indra/llmessage/llxfer_file.h @@ -61,8 +61,10 @@ class LLXfer_File : public LLXfer virtual S32 startDownload(); virtual S32 processEOF(); - - virtual S32 startSend (U64 xfer_id, const LLHost &remote_host); + + virtual S32 startSend(U64 xfer_id, const LLHost &remote_host); + virtual void closeFileHandle(); + virtual S32 reopenFileHandle(); virtual S32 suck(S32 start_position); virtual S32 flush(); diff --git a/indra/llmessage/llxfer_mem.cpp b/indra/llmessage/llxfer_mem.cpp index 3bea08f2e5..78a3e4f558 100644 --- a/indra/llmessage/llxfer_mem.cpp +++ b/indra/llmessage/llxfer_mem.cpp @@ -80,28 +80,6 @@ void LLXfer_Mem::setXferSize (S32 xfer_size) /////////////////////////////////////////////////////////// -U64 LLXfer_Mem::registerXfer(U64 xfer_id, const void *datap, const S32 length) -{ - mID = xfer_id; - - if (datap) - { - setXferSize(length); - if (mBuffer) - { - memcpy(mBuffer,datap,length); /* Flawfinder : ignore */ - mBufferLength = length; - } - else - { - xfer_id = 0; - } - } - - mStatus = e_LL_XFER_REGISTERED; - return (xfer_id); -} - S32 LLXfer_Mem::startSend (U64 xfer_id, const LLHost &remote_host) { S32 retval = LL_ERR_NOERR; // presume success diff --git a/indra/llmessage/llxfer_mem.h b/indra/llmessage/llxfer_mem.h index b5adf837df..d07779de87 100644 --- a/indra/llmessage/llxfer_mem.h +++ b/indra/llmessage/llxfer_mem.h @@ -53,7 +53,6 @@ class LLXfer_Mem : public LLXfer virtual void cleanup(); virtual S32 startSend (U64 xfer_id, const LLHost &remote_host); - virtual U64 registerXfer(U64 xfer_id, const void *datap, const S32 length); virtual void setXferSize (S32 data_size); virtual S32 initializeRequest(U64 xfer_id, diff --git a/indra/llmessage/llxfer_vfile.cpp b/indra/llmessage/llxfer_vfile.cpp index 4a378d1d34..988bb75134 100644 --- a/indra/llmessage/llxfer_vfile.cpp +++ b/indra/llmessage/llxfer_vfile.cpp @@ -79,8 +79,20 @@ void LLXfer_VFile::init (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType void LLXfer_VFile::cleanup () { - LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE); - file.remove(); + if (mTempID.notNull() && + mDeleteTempFile) + { + if (mVFS->getExists(mTempID, mType)) + { + LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE); + file.remove(); + } + else + { + LL_WARNS("Xfer") << "LLXfer_VFile::cleanup() can't open to delete VFS file " << mTempID << "." << LLAssetType::lookup(mType) + << ", mRemoteID is " << mRemoteID << LL_ENDL; + } + } delete mVFile; mVFile = NULL; @@ -118,7 +130,7 @@ S32 LLXfer_VFile::initializeRequest(U64 xfer_id, mName = llformat("VFile %s:%s", id_string.c_str(), LLAssetType::lookup(mType)); - LL_INFOS() << "Requesting " << mName << LL_ENDL; + LL_INFOS("Xfer") << "Requesting " << mName << LL_ENDL; if (mBuffer) { @@ -131,6 +143,7 @@ S32 LLXfer_VFile::initializeRequest(U64 xfer_id, mBufferLength = 0; mPacketNum = 0; mTempID.generate(); + mDeleteTempFile = TRUE; mStatus = e_LL_XFER_PENDING; return retval; } @@ -140,7 +153,8 @@ S32 LLXfer_VFile::initializeRequest(U64 xfer_id, S32 LLXfer_VFile::startDownload() { S32 retval = 0; // presume success - LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND); + + // Don't need to create the file here, it will happen when data arrives gMessageSystem->newMessageFast(_PREHASH_RequestXfer); gMessageSystem->nextBlockFast(_PREHASH_XferID); @@ -184,6 +198,8 @@ S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host) if (mVFile->getSize() <= 0) { + LL_WARNS("Xfer") << "LLXfer_VFile::startSend() VFS file " << mLocalID << "." << LLAssetType::lookup(mType) + << " has unexpected file size of " << mVFile->getSize() << LL_ENDL; delete mVFile; mVFile = NULL; @@ -198,6 +214,7 @@ S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host) } else { + LL_WARNS("Xfer") << "LLXfer_VFile::startSend() can't read VFS file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL; retval = LL_ERR_FILE_NOT_FOUND; } @@ -205,6 +222,41 @@ S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host) } /////////////////////////////////////////////////////////// + +void LLXfer_VFile::closeFileHandle() +{ + if (mVFile) + { + delete mVFile; + mVFile = NULL; + } +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_VFile::reopenFileHandle() +{ + S32 retval = LL_ERR_NOERR; // presume success + + if (mVFile == NULL) + { + if (mVFS->getExists(mLocalID, mType)) + { + mVFile = new LLVFile(mVFS, mLocalID, mType, LLVFile::READ); + } + else + { + LL_WARNS("Xfer") << "LLXfer_VFile::reopenFileHandle() can't read VFS file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL; + retval = LL_ERR_FILE_NOT_FOUND; + } + } + + return retval; +} + + +/////////////////////////////////////////////////////////// + void LLXfer_VFile::setXferSize (S32 xfer_size) { LLXfer::setXferSize(xfer_size); @@ -236,8 +288,8 @@ S32 LLXfer_VFile::suck(S32 start_position) // grab a buffer from the right place in the file if (! mVFile->seek(start_position, 0)) { - LL_WARNS() << "VFile Xfer Can't seek to position " << start_position << ", file length " << mVFile->getSize() << LL_ENDL; - LL_WARNS() << "While sending file " << mLocalID << LL_ENDL; + LL_WARNS("Xfer") << "VFile Xfer Can't seek to position " << start_position << ", file length " << mVFile->getSize() << LL_ENDL; + LL_WARNS("Xfer") << "While sending file " << mLocalID << LL_ENDL; return -1; } @@ -288,12 +340,31 @@ S32 LLXfer_VFile::processEOF() if (!mCallbackResult) { - LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE); - if (! file.rename(mLocalID, mType)) + if (mVFS->getExists(mTempID, mType)) { - LL_INFOS() << "copy from temp file failed: unable to rename to " << mLocalID << LL_ENDL; + LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE); + if (!file.rename(mLocalID, mType)) + { + LL_WARNS("Xfer") << "VFS rename of temp file failed: unable to rename " << mTempID << " to " << mLocalID << LL_ENDL; + } + else + { + #ifdef VFS_SPAM + // Debugging spam + LL_INFOS("Xfer") << "VFS rename of temp file done: renamed " << mTempID << " to " << mLocalID + << " LLVFile size is " << file.getSize() + << LL_ENDL; + #endif + + // Rename worked: the original file is gone. Clear mDeleteTempFile + // so we don't attempt to delete the file in cleanup() + mDeleteTempFile = FALSE; + } + } + else + { + LL_WARNS("Xfer") << "LLXfer_VFile::processEOF() can't open for renaming VFS file " << mTempID << "." << LLAssetType::lookup(mType) << LL_ENDL; } - } if (mVFile) diff --git a/indra/llmessage/llxfer_vfile.h b/indra/llmessage/llxfer_vfile.h index 048bf49dcc..5bf9a5cfba 100644 --- a/indra/llmessage/llxfer_vfile.h +++ b/indra/llmessage/llxfer_vfile.h @@ -47,6 +47,8 @@ class LLXfer_VFile : public LLXfer std::string mName; + BOOL mDeleteTempFile; + public: LLXfer_VFile (); LLXfer_VFile (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type); @@ -66,8 +68,10 @@ class LLXfer_VFile : public LLXfer virtual S32 startDownload(); virtual S32 processEOF(); - - virtual S32 startSend (U64 xfer_id, const LLHost &remote_host); + + virtual S32 startSend(U64 xfer_id, const LLHost &remote_host); + virtual void closeFileHandle(); + virtual S32 reopenFileHandle(); virtual S32 suck(S32 start_position); virtual S32 flush(); diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp index 1ea3c576ee..0918300648 100644 --- a/indra/llmessage/llxfermanager.cpp +++ b/indra/llmessage/llxfermanager.cpp @@ -35,7 +35,6 @@ #include "llerror.h" #include "lluuid.h" -#include "u64.h" const F32 LL_XFER_REGISTRATION_TIMEOUT = 60.0f; // timeout if a registered transfer hasn't been requested in 60 seconds const F32 LL_PACKET_TIMEOUT = 3.0f; // packet timeout at 3 s @@ -44,9 +43,15 @@ const S32 LL_PACKET_RETRY_LIMIT = 10; // packet retransmission limit const S32 LL_DEFAULT_MAX_SIMULTANEOUS_XFERS = 10; const S32 LL_DEFAULT_MAX_REQUEST_FIFO_XFERS = 1000; -#define LL_XFER_PROGRESS_MESSAGES 0 -#define LL_XFER_TEST_REXMIT 0 +// Kills the connection if a viewer download queue hits this many requests backed up +// Also set in simulator.xml at "hard_limit_outgoing_xfers_per_circuit" +const S32 LL_DEFAULT_MAX_HARD_LIMIT_SIMULTANEOUS_XFERS = 500; +// Use this to show sending some ConfirmXferPacket messages +//#define LL_XFER_PROGRESS_MESSAGES 1 + +// Use this for lots of diagnostic spam +//#define LL_XFER_DIAGNOISTIC_LOGGING 1 /////////////////////////////////////////////////////////// @@ -66,10 +71,10 @@ LLXferManager::~LLXferManager () void LLXferManager::init (LLVFS *vfs) { - mSendList = NULL; - mReceiveList = NULL; + cleanup(); setMaxOutgoingXfersPerCircuit(LL_DEFAULT_MAX_SIMULTANEOUS_XFERS); + setHardLimitOutgoingXfersPerCircuit(LL_DEFAULT_MAX_HARD_LIMIT_SIMULTANEOUS_XFERS); setMaxIncomingXfers(LL_DEFAULT_MAX_REQUEST_FIFO_XFERS); mVFS = vfs; @@ -83,29 +88,14 @@ void LLXferManager::init (LLVFS *vfs) void LLXferManager::cleanup () { - LLXfer *xferp; - LLXfer *delp; - for_each(mOutgoingHosts.begin(), mOutgoingHosts.end(), DeletePointer()); mOutgoingHosts.clear(); - delp = mSendList; - while (delp) - { - xferp = delp->mNext; - delete delp; - delp = xferp; - } - mSendList = NULL; + for_each(mSendList.begin(), mSendList.end(), DeletePointer()); + mSendList.clear(); - delp = mReceiveList; - while (delp) - { - xferp = delp->mNext; - delete delp; - delp = xferp; - } - mReceiveList = NULL; + for_each(mReceiveList.begin(), mReceiveList.end(), DeletePointer()); + mReceiveList.clear(); } /////////////////////////////////////////////////////////// @@ -122,6 +112,11 @@ void LLXferManager::setMaxOutgoingXfersPerCircuit(S32 max_num) mMaxOutgoingXfersPerCircuit = max_num; } +void LLXferManager::setHardLimitOutgoingXfersPerCircuit(S32 max_num) +{ + mHardLimitOutgoingXfersPerCircuit = max_num; +} + void LLXferManager::setUseAckThrottling(const BOOL use) { mUseAckThrottling = use; @@ -140,6 +135,11 @@ void LLXferManager::setAckThrottleBPS(const F32 bps) F32 actual_rate = llmax(min_bps*1.1f, bps); LL_DEBUGS("AppInit") << "LLXferManager ack throttle min rate: " << min_bps << LL_ENDL; LL_DEBUGS("AppInit") << "LLXferManager ack throttle actual rate: " << actual_rate << LL_ENDL; + #ifdef LL_XFER_DIAGNOISTIC_LOGGING + LL_INFOS("Xfer") << "LLXferManager ack throttle min rate: " << min_bps << LL_ENDL; + LL_INFOS("Xfer") << "LLXferManager ack throttle actual rate: " << actual_rate << LL_ENDL; + #endif // LL_XFER_DIAGNOISTIC_LOGGING + mAckThrottle.setRate(actual_rate); } @@ -148,45 +148,71 @@ void LLXferManager::setAckThrottleBPS(const F32 bps) void LLXferManager::updateHostStatus() { - LLXfer *xferp; - LLHostStatus *host_statusp = NULL; - + // Clear the outgoing host list for_each(mOutgoingHosts.begin(), mOutgoingHosts.end(), DeletePointer()); mOutgoingHosts.clear(); - - for (xferp = mSendList; xferp; xferp = xferp->mNext) + + // Loop through all outgoing xfers and re-build mOutgoingHosts + for (xfer_list_t::iterator send_iter = mSendList.begin(); + send_iter != mSendList.end(); ++send_iter) { + LLHostStatus *host_statusp = NULL; for (status_list_t::iterator iter = mOutgoingHosts.begin(); iter != mOutgoingHosts.end(); ++iter) { - host_statusp = *iter; - if (host_statusp->mHost == xferp->mRemoteHost) - { + if ((*iter)->mHost == (*send_iter)->mRemoteHost) + { // Already have this host + host_statusp = *iter; break; } } if (!host_statusp) - { + { // Don't have this host, so add it host_statusp = new LLHostStatus(); if (host_statusp) { - host_statusp->mHost = xferp->mRemoteHost; + host_statusp->mHost = (*send_iter)->mRemoteHost; mOutgoingHosts.push_front(host_statusp); } } if (host_statusp) - { - if (xferp->mStatus == e_LL_XFER_PENDING) + { // Do the accounting + if ((*send_iter)->mStatus == e_LL_XFER_PENDING) { host_statusp->mNumPending++; } - else if (xferp->mStatus == e_LL_XFER_IN_PROGRESS) + else if ((*send_iter)->mStatus == e_LL_XFER_IN_PROGRESS) { host_statusp->mNumActive++; } } - } + +#ifdef LL_XFER_DIAGNOISTIC_LOGGING + for (xfer_list_t::iterator send_iter = mSendList.begin(); + send_iter != mSendList.end(); ++send_iter) + { + LLXfer * xferp = *send_iter; + LL_INFOS("Xfer") << "xfer to host " << xferp->mRemoteHost + << " is " << xferp->mXferSize << " bytes" + << ", status " << (S32)(xferp->mStatus) + << ", waiting for ACK: " << (S32)(xferp->mWaitingForACK) + << " in frame " << LLFrameTimer::getFrameCount() + << LL_ENDL; + } + + for (status_list_t::iterator iter = mOutgoingHosts.begin(); + iter != mOutgoingHosts.end(); ++iter) + { + LL_INFOS("Xfer") << "LLXfer host " << (*iter)->mHost.getIPandPort() + << " has " << (*iter)->mNumActive + << " active, " << (*iter)->mNumPending + << " pending" + << " in frame " << LLFrameTimer::getFrameCount() + << LL_ENDL; + } +#endif // LL_XFER_DIAGNOISTIC_LOGGING + } /////////////////////////////////////////////////////////// @@ -196,27 +222,28 @@ void LLXferManager::printHostStatus() LLHostStatus *host_statusp = NULL; if (!mOutgoingHosts.empty()) { - LL_INFOS() << "Outgoing Xfers:" << LL_ENDL; + LL_INFOS("Xfer") << "Outgoing Xfers:" << LL_ENDL; for (status_list_t::iterator iter = mOutgoingHosts.begin(); iter != mOutgoingHosts.end(); ++iter) { host_statusp = *iter; - LL_INFOS() << " " << host_statusp->mHost << " active: " << host_statusp->mNumActive << " pending: " << host_statusp->mNumPending << LL_ENDL; + LL_INFOS("Xfer") << " " << host_statusp->mHost << " active: " << host_statusp->mNumActive << " pending: " << host_statusp->mNumPending << LL_ENDL; } } } /////////////////////////////////////////////////////////// -LLXfer *LLXferManager::findXfer (U64 id, LLXfer *list_head) +LLXfer * LLXferManager::findXferByID(U64 id, xfer_list_t & xfer_list) { - LLXfer *xferp; - for (xferp = list_head; xferp; xferp = xferp->mNext) + for (xfer_list_t::iterator iter = xfer_list.begin(); + iter != xfer_list.end(); + ++iter) { - if (xferp->mID == id) + if ((*iter)->mID == id) { - return(xferp); + return(*iter); } } return(NULL); @@ -225,29 +252,34 @@ LLXfer *LLXferManager::findXfer (U64 id, LLXfer *list_head) /////////////////////////////////////////////////////////// -void LLXferManager::removeXfer (LLXfer *delp, LLXfer **list_head) +// WARNING: this invalidates iterators from xfer_list +void LLXferManager::removeXfer(LLXfer *delp, xfer_list_t & xfer_list) { - // This function assumes that delp will only occur in the list - // zero or one times. if (delp) - { - if (*list_head == delp) + { + std::string direction = "send"; + if (&xfer_list == &mReceiveList) { - *list_head = delp->mNext; - delete (delp); + direction = "receive"; } - else + + // This assumes that delp will occur in the list once at most + // Find the pointer in the list + for (xfer_list_t::iterator iter = xfer_list.begin(); + iter != xfer_list.end(); + ++iter) { - LLXfer *xferp = *list_head; - while (xferp->mNext) + if ((*iter) == delp) { - if (xferp->mNext == delp) - { - xferp->mNext = delp->mNext; - delete (delp); - break; - } - xferp = xferp->mNext; + LL_DEBUGS("Xfer") << "Deleting xfer to host " << (*iter)->mRemoteHost + << " of " << (*iter)->mXferSize << " bytes" + << ", status " << (S32)((*iter)->mStatus) + << " from the " << direction << " list" + << LL_ENDL; + + xfer_list.erase(iter); + delete (delp); + break; } } } @@ -255,35 +287,30 @@ void LLXferManager::removeXfer (LLXfer *delp, LLXfer **list_head) /////////////////////////////////////////////////////////// -U32 LLXferManager::numActiveListEntries(LLXfer *list_head) +LLHostStatus * LLXferManager::findHostStatus(const LLHost &host) { - U32 num_entries = 0; + LLHostStatus *host_statusp = NULL; - while (list_head) + for (status_list_t::iterator iter = mOutgoingHosts.begin(); + iter != mOutgoingHosts.end(); ++iter) { - if (list_head->mStatus == e_LL_XFER_IN_PROGRESS) + host_statusp = *iter; + if (host_statusp->mHost == host) { - num_entries++; + return (host_statusp); } - list_head = list_head->mNext; } - return(num_entries); + return 0; } /////////////////////////////////////////////////////////// - + S32 LLXferManager::numPendingXfers(const LLHost &host) { - LLHostStatus *host_statusp = NULL; - - for (status_list_t::iterator iter = mOutgoingHosts.begin(); - iter != mOutgoingHosts.end(); ++iter) + LLHostStatus *host_statusp = findHostStatus(host); + if (host_statusp) { - host_statusp = *iter; - if (host_statusp->mHost == host) - { - return (host_statusp->mNumPending); - } + return host_statusp->mNumPending; } return 0; } @@ -292,16 +319,10 @@ S32 LLXferManager::numPendingXfers(const LLHost &host) S32 LLXferManager::numActiveXfers(const LLHost &host) { - LLHostStatus *host_statusp = NULL; - - for (status_list_t::iterator iter = mOutgoingHosts.begin(); - iter != mOutgoingHosts.end(); ++iter) + LLHostStatus *host_statusp = findHostStatus(host); + if (host_statusp) { - host_statusp = *iter; - if (host_statusp->mHost == host) - { - return (host_statusp->mNumActive); - } + return host_statusp->mNumActive; } return 0; } @@ -372,36 +393,7 @@ BOOL LLXferManager::isLastPacket(S32 packet_num) /////////////////////////////////////////////////////////// -U64 LLXferManager::registerXfer(const void *datap, const S32 length) -{ - LLXfer *xferp; - U64 xfer_id = getNextID(); - - xferp = (LLXfer *) new LLXfer_Mem(); - if (xferp) - { - xferp->mNext = mSendList; - mSendList = xferp; - - xfer_id = ((LLXfer_Mem *)xferp)->registerXfer(xfer_id, datap,length); - - if (!xfer_id) - { - removeXfer(xferp,&mSendList); - } - } - else - { - LL_ERRS() << "Xfer allocation error" << LL_ENDL; - xfer_id = 0; - } - - return(xfer_id); -} - -/////////////////////////////////////////////////////////// - -void LLXferManager::requestFile(const std::string& local_filename, +U64 LLXferManager::requestFile(const std::string& local_filename, const std::string& remote_filename, ELLPath remote_path, const LLHost& remote_host, @@ -411,28 +403,34 @@ void LLXferManager::requestFile(const std::string& local_filename, BOOL is_priority, BOOL use_big_packets) { - LLXfer *xferp; + LLXfer_File* file_xfer_p = NULL; - for (xferp = mReceiveList; xferp ; xferp = xferp->mNext) + // First check to see if it's already requested + for (xfer_list_t::iterator iter = mReceiveList.begin(); + iter != mReceiveList.end(); ++iter) { - if (xferp->getXferTypeTag() == LLXfer::XFER_FILE - && (((LLXfer_File*)xferp)->matchesLocalFilename(local_filename)) - && (((LLXfer_File*)xferp)->matchesRemoteFilename(remote_filename, remote_path)) - && (remote_host == xferp->mRemoteHost) - && (callback == xferp->mCallback) - && (user_data == xferp->mCallbackDataHandle)) - + if ((*iter)->getXferTypeTag() == LLXfer::XFER_FILE) { - // cout << "requested a xfer already in progress" << endl; - return; + file_xfer_p = (LLXfer_File*)(*iter); + if (file_xfer_p->matchesLocalFilename(local_filename) + && file_xfer_p->matchesRemoteFilename(remote_filename, remote_path) + && (remote_host == file_xfer_p->mRemoteHost) + && (callback == file_xfer_p->mCallback) + && (user_data == file_xfer_p->mCallbackDataHandle)) + { + // Already have the request (already in progress) + return (*iter)->mID; + } } } + U64 xfer_id = 0; + S32 chunk_size = use_big_packets ? LL_XFER_LARGE_PAYLOAD : -1; - xferp = (LLXfer *) new LLXfer_File(chunk_size); - if (xferp) + file_xfer_p = new LLXfer_File(chunk_size); + if (file_xfer_p) { - addToList(xferp, mReceiveList, is_priority); + addToList(file_xfer_p, mReceiveList, is_priority); // Remove any file by the same name that happens to be lying // around. @@ -441,10 +439,11 @@ void LLXferManager::requestFile(const std::string& local_filename, if(delete_remote_on_completion && (remote_filename.substr(remote_filename.length()-4) == ".tmp")) { - LLFile::remove(local_filename); + LLFile::remove(local_filename, ENOENT); } - ((LLXfer_File *)xferp)->initializeRequest( - getNextID(), + xfer_id = getNextID(); + file_xfer_p->initializeRequest( + xfer_id, local_filename, remote_filename, remote_path, @@ -455,36 +454,9 @@ void LLXferManager::requestFile(const std::string& local_filename, } else { - LL_ERRS() << "Xfer allocation error" << LL_ENDL; - } -} - -void LLXferManager::requestFile(const std::string& remote_filename, - ELLPath remote_path, - const LLHost& remote_host, - BOOL delete_remote_on_completion, - void (*callback)(void*,S32,void**,S32,LLExtStat), - void** user_data, - BOOL is_priority) -{ - LLXfer *xferp; - - xferp = (LLXfer *) new LLXfer_Mem(); - if (xferp) - { - addToList(xferp, mReceiveList, is_priority); - ((LLXfer_Mem *)xferp)->initializeRequest(getNextID(), - remote_filename, - remote_path, - remote_host, - delete_remote_on_completion, - callback, user_data); - startPendingDownloads(); - } - else - { - LL_ERRS() << "Xfer allocation error" << LL_ENDL; + LL_ERRS("Xfer") << "Xfer allocation error" << LL_ENDL; } + return xfer_id; } void LLXferManager::requestVFile(const LLUUID& local_id, @@ -495,28 +467,46 @@ void LLXferManager::requestVFile(const LLUUID& local_id, void** user_data, BOOL is_priority) { - LLXfer *xferp; - - for (xferp = mReceiveList; xferp ; xferp = xferp->mNext) - { - if (xferp->getXferTypeTag() == LLXfer::XFER_VFILE - && (((LLXfer_VFile*)xferp)->matchesLocalFile(local_id, type)) - && (((LLXfer_VFile*)xferp)->matchesRemoteFile(remote_id, type)) - && (remote_host == xferp->mRemoteHost) - && (callback == xferp->mCallback) - && (user_data == xferp->mCallbackDataHandle)) + LLXfer_VFile * xfer_p = NULL; + for (xfer_list_t::iterator iter = mReceiveList.begin(); + iter != mReceiveList.end(); ++iter) + { // Find any matching existing requests + if ((*iter)->getXferTypeTag() == LLXfer::XFER_VFILE) { - // cout << "requested a xfer already in progress" << endl; - return; + xfer_p = (LLXfer_VFile*) (*iter); + if (xfer_p->matchesLocalFile(local_id, type) + && xfer_p->matchesRemoteFile(remote_id, type) + && (remote_host == xfer_p->mRemoteHost) + && (callback == xfer_p->mCallback) + && (user_data == xfer_p->mCallbackDataHandle)) + + { // Have match, don't add a duplicate + #ifdef LL_XFER_DIAGNOISTIC_LOGGING + LL_INFOS("Xfer") << "Dropping duplicate xfer request for " << remote_id + << " on " << remote_host.getIPandPort() + << " local id " << local_id + << LL_ENDL; + #endif // LL_XFER_DIAGNOISTIC_LOGGING + + return; + } } } - xferp = (LLXfer *) new LLXfer_VFile(); - if (xferp) + xfer_p = new LLXfer_VFile(); + if (xfer_p) { - addToList(xferp, mReceiveList, is_priority); - ((LLXfer_VFile *)xferp)->initializeRequest(getNextID(), + #ifdef LL_XFER_DIAGNOISTIC_LOGGING + LL_INFOS("Xfer") << "Starting file xfer for " << remote_id + << " type " << LLAssetType::lookupHumanReadable(type) + << " from " << xfer_p->mRemoteHost.getIPandPort() + << ", local id " << local_id + << LL_ENDL; + #endif // LL_XFER_DIAGNOISTIC_LOGGING + + addToList(xfer_p, mReceiveList, is_priority); + ((LLXfer_VFile *)xfer_p)->initializeRequest(getNextID(), vfs, local_id, remote_id, @@ -528,78 +518,18 @@ void LLXferManager::requestVFile(const LLUUID& local_id, } else { - LL_ERRS() << "Xfer allocation error" << LL_ENDL; - } - -} - -/* -void LLXferManager::requestXfer( - const std::string& local_filename, - BOOL delete_remote_on_completion, - U64 xfer_id, - const LLHost &remote_host, - void (*callback)(void **,S32), - void **user_data) -{ - LLXfer *xferp; - - for (xferp = mReceiveList; xferp ; xferp = xferp->mNext) - { - if (xferp->getXferTypeTag() == LLXfer::XFER_FILE - && (((LLXfer_File*)xferp)->matchesLocalFilename(local_filename)) - && (xfer_id == xferp->mID) - && (remote_host == xferp->mRemoteHost) - && (callback == xferp->mCallback) - && (user_data == xferp->mCallbackDataHandle)) - - { - // cout << "requested a xfer already in progress" << endl; - return; - } + LL_ERRS("Xfer") << "Xfer allocation error" << LL_ENDL; } - xferp = (LLXfer *) new LLXfer_File(); - if (xferp) - { - xferp->mNext = mReceiveList; - mReceiveList = xferp; - - ((LLXfer_File *)xferp)->initializeRequest(xfer_id,local_filename,"",LL_PATH_NONE,remote_host,delete_remote_on_completion,callback,user_data); - startPendingDownloads(); - } - else - { - LL_ERRS() << "Xfer allcoation error" << LL_ENDL; - } } -void LLXferManager::requestXfer(U64 xfer_id, const LLHost &remote_host, BOOL delete_remote_on_completion, void (*callback)(void *,S32,void **,S32),void **user_data) -{ - LLXfer *xferp; - - xferp = (LLXfer *) new LLXfer_Mem(); - if (xferp) - { - xferp->mNext = mReceiveList; - mReceiveList = xferp; - - ((LLXfer_Mem *)xferp)->initializeRequest(xfer_id,"",LL_PATH_NONE,remote_host,delete_remote_on_completion,callback,user_data); - startPendingDownloads(); - } - else - { - LL_ERRS() << "Xfer allcoation error" << LL_ENDL; - } -} -*/ /////////////////////////////////////////////////////////// void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user_data*/) { // there's sometimes an extra 4 bytes added to an xfer payload const S32 BUF_SIZE = LL_XFER_LARGE_PAYLOAD + 4; - char fdata_buf[LL_XFER_LARGE_PAYLOAD + 4]; /* Flawfinder : ignore */ + char fdata_buf[BUF_SIZE]; /* Flawfinder : ignore */ S32 fdata_size; U64 id; S32 packetnum; @@ -609,16 +539,24 @@ void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Packet, packetnum); fdata_size = mesgsys->getSizeFast(_PREHASH_DataPacket,_PREHASH_Data); - mesgsys->getBinaryDataFast(_PREHASH_DataPacket, _PREHASH_Data, fdata_buf, 0, 0, BUF_SIZE); - - xferp = findXfer(id, mReceiveList); + if (fdata_size < 0 || + fdata_size > BUF_SIZE) + { + LL_WARNS("Xfer") << "Received invalid xfer data size of " << fdata_size + << " in packet number " << packetnum + << " from " << mesgsys->getSender() + << " for xfer id: " << fmt::to_string(id) + << LL_ENDL; + return; + } + mesgsys->getBinaryDataFast(_PREHASH_DataPacket, _PREHASH_Data, fdata_buf, fdata_size, 0, BUF_SIZE); - if (!xferp) + xferp = findXferByID(id, mReceiveList); + if (!xferp) { - char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */ - LL_WARNS() << "received xfer data from " << mesgsys->getSender() + LL_WARNS("Xfer") << "received xfer data from " << mesgsys->getSender() << " for non-existent xfer id: " - << U64_to_str(id, U64_BUF, sizeof(U64_BUF)) << LL_ENDL; + << fmt::to_string(id) << LL_ENDL; return; } @@ -629,11 +567,11 @@ void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user // confirm it if it was a resend of the last one, since the confirmation might have gotten dropped if (decodePacketNum(packetnum) == (xferp->mPacketNum - 1)) { - LL_INFOS() << "Reconfirming xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet " << packetnum << LL_ENDL; sendConfirmPacket(mesgsys, id, decodePacketNum(packetnum), mesgsys->getSender()); + LL_INFOS("Xfer") << "Reconfirming xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet " << packetnum << LL_ENDL; sendConfirmPacket(mesgsys, id, decodePacketNum(packetnum), mesgsys->getSender()); } else { - LL_INFOS() << "Ignoring xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " recv'd packet " << packetnum << "; expecting " << xferp->mPacketNum << LL_ENDL; + LL_INFOS("Xfer") << "Ignoring xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " recv'd packet " << packetnum << "; expecting " << xferp->mPacketNum << LL_ENDL; } return; } @@ -658,7 +596,7 @@ void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user if (result == LL_ERR_CANNOT_OPEN_FILE) { xferp->abort(LL_ERR_CANNOT_OPEN_FILE); - removeXfer(xferp,&mReceiveList); + removeXfer(xferp,mReceiveList); startPendingDownloads(); return; } @@ -677,13 +615,13 @@ void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user ack_info.mID = id; ack_info.mPacketNum = decodePacketNum(packetnum); ack_info.mRemoteHost = mesgsys->getSender(); - mXferAckQueue.push(ack_info); + mXferAckQueue.push_back(ack_info); } if (isLastPacket(packetnum)) { xferp->processEOF(); - removeXfer(xferp,&mReceiveList); + removeXfer(xferp,mReceiveList); startPendingDownloads(); } } @@ -692,7 +630,7 @@ void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user void LLXferManager::sendConfirmPacket (LLMessageSystem *mesgsys, U64 id, S32 packetnum, const LLHost &remote_host) { -#if LL_XFER_PROGRESS_MESSAGES +#ifdef LL_XFER_PROGRESS_MESSAGES if (!(packetnum % 50)) { cout << "confirming xfer packet #" << packetnum << endl; @@ -703,6 +641,7 @@ void LLXferManager::sendConfirmPacket (LLMessageSystem *mesgsys, U64 id, S32 pac mesgsys->addU64Fast(_PREHASH_ID, id); mesgsys->addU32Fast(_PREHASH_Packet, packetnum); + // Ignore a circuit failure here, we'll catch it with another message mesgsys->sendMessage(remote_host); } @@ -741,6 +680,28 @@ bool LLXferManager::validateFileForTransfer(const std::string& filename) return find_and_remove(mExpectedTransfers, filename); } +/* Present in fireengine, not used by viewer +void LLXferManager::expectVFileForRequest(const std::string& filename) +{ + mExpectedVFileRequests.insert(filename); +} + +bool LLXferManager::validateVFileForRequest(const std::string& filename) +{ + return find_and_remove(mExpectedVFileRequests, filename); +} + +void LLXferManager::expectVFileForTransfer(const std::string& filename) +{ + mExpectedVFileTransfers.insert(filename); +} + +bool LLXferManager::validateVFileForTransfer(const std::string& filename) +{ + return find_and_remove(mExpectedVFileTransfers, filename); +} +*/ + static bool remove_prefix(std::string& filename, const std::string& prefix) { if (std::equal(prefix.begin(), prefix.end(), filename.begin())) @@ -801,8 +762,7 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user mesgsys->getBOOL("XferID", "UseBigPackets", b_use_big_packets); mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id); - char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */ - LL_INFOS() << "xfer request id: " << U64_to_str(id, U64_BUF, sizeof(U64_BUF)) + LL_INFOS("Xfer") << "xfer request id: " << fmt::to_string(id) << " to " << mesgsys->getSender() << LL_ENDL; mesgsys->getStringFast(_PREHASH_XferID, _PREHASH_Filename, local_filename); @@ -820,36 +780,45 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user LLXfer *xferp; if (uuid != LLUUID::null) - { + { // Request for an asset - use a VFS file if(NULL == LLAssetType::lookup(type)) { - LL_WARNS() << "Invalid type for xfer request: " << uuid << ":" + LL_WARNS("Xfer") << "Invalid type for xfer request: " << uuid << ":" << type_s16 << " to " << mesgsys->getSender() << LL_ENDL; return; } - LL_INFOS() << "starting vfile transfer: " << uuid << "," << LLAssetType::lookup(type) << " to " << mesgsys->getSender() << LL_ENDL; - if (! mVFS) { - LL_WARNS() << "Attempt to send VFile w/o available VFS" << LL_ENDL; + LL_WARNS("Xfer") << "Attempt to send VFile w/o available VFS" << LL_ENDL; + return; + } + + /* Present in fireengine, not used by viewer + if (!validateVFileForTransfer(uuid.asString())) + { + // it is up to the app sending the file to mark it for expected + // transfer before the request arrives or it will be dropped + LL_WARNS("Xfer") << "SECURITY: Unapproved VFile '" << uuid << "'" << LL_ENDL; return; } + */ + + LL_INFOS("Xfer") << "starting vfile transfer: " << uuid << "," << LLAssetType::lookup(type) << " to " << mesgsys->getSender() << LL_ENDL; xferp = (LLXfer *)new LLXfer_VFile(mVFS, uuid, type); if (xferp) { - xferp->mNext = mSendList; - mSendList = xferp; + mSendList.push_front(xferp); result = xferp->startSend(id,mesgsys->getSender()); } else { - LL_ERRS() << "Xfer allcoation error" << LL_ENDL; + LL_ERRS("Xfer") << "Xfer allcoation error" << LL_ENDL; } } else if (!local_filename.empty()) - { + { // Was given a file name to send // See DEV-21775 for detailed security issues if (local_path == LL_PATH_NONE) @@ -868,7 +837,7 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user case LL_PATH_NONE: if(!validateFileForTransfer(local_filename)) { - LL_WARNS() << "SECURITY: Unapproved filename '" << local_filename << LL_ENDL; + LL_WARNS("Xfer") << "SECURITY: Unapproved filename '" << local_filename << LL_ENDL; return; } break; @@ -876,13 +845,13 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user case LL_PATH_CACHE: if(!verify_cache_filename(local_filename)) { - LL_WARNS() << "SECURITY: Illegal cache filename '" << local_filename << LL_ENDL; + LL_WARNS("Xfer") << "SECURITY: Illegal cache filename '" << local_filename << LL_ENDL; return; } break; default: - LL_WARNS() << "SECURITY: Restricted file dir enum: " << (U32)local_path << LL_ENDL; + LL_WARNS("Xfer") << "SECURITY: Restricted file dir enum: " << (U32)local_path << LL_ENDL; return; } @@ -897,7 +866,7 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user { expanded_filename = local_filename; } - LL_INFOS() << "starting file transfer: " << expanded_filename << " to " << mesgsys->getSender() << LL_ENDL; + LL_INFOS("Xfer") << "starting file transfer: " << expanded_filename << " to " << mesgsys->getSender() << LL_ENDL; BOOL delete_local_on_completion = FALSE; mesgsys->getBOOL("XferID", "DeleteOnCompletion", delete_local_on_completion); @@ -907,23 +876,21 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user if (xferp) { - xferp->mNext = mSendList; - mSendList = xferp; + mSendList.push_front(xferp); result = xferp->startSend(id,mesgsys->getSender()); } else { - LL_ERRS() << "Xfer allcoation error" << LL_ENDL; + LL_ERRS("Xfer") << "Xfer allcoation error" << LL_ENDL; } } else - { - char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */ - LL_INFOS() << "starting memory transfer: " - << U64_to_str(id, U64_BUF, sizeof(U64_BUF)) << " to " + { // no uuid or filename - use the ID sent + LL_INFOS("Xfer") << "starting memory transfer: " + << fmt::to_string(id) << " to " << mesgsys->getSender() << LL_ENDL; - xferp = findXfer(id, mSendList); + xferp = findXferByID(id, mSendList); if (xferp) { @@ -931,7 +898,7 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user } else { - LL_INFOS() << "Warning: " << U64_BUF << " not found." << LL_ENDL; + LL_INFOS("Xfer") << "Warning: xfer ID " << fmt::to_string(id) << " not found." << LL_ENDL; result = LL_ERR_FILE_NOT_FOUND; } } @@ -941,11 +908,11 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user if (xferp) { xferp->abort(result); - removeXfer(xferp,&mSendList); + removeXfer(xferp, mSendList); } else // can happen with a memory transfer not found { - LL_INFOS() << "Aborting xfer to " << mesgsys->getSender() << " with error: " << result << LL_ENDL; + LL_INFOS("Xfer") << "Aborting xfer to " << mesgsys->getSender() << " with error: " << result << LL_ENDL; mesgsys->newMessageFast(_PREHASH_AbortXfer); mesgsys->nextBlockFast(_PREHASH_XferID); @@ -955,24 +922,86 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user mesgsys->sendMessage(mesgsys->getSender()); } } - else if(xferp && (numActiveXfers(xferp->mRemoteHost) < mMaxOutgoingXfersPerCircuit)) + else if(xferp) { - xferp->sendNextPacket(); - changeNumActiveXfers(xferp->mRemoteHost,1); -// LL_INFOS() << "***STARTING XFER IMMEDIATELY***" << LL_ENDL; - } - else - { - if(xferp) + // Figure out how many transfers the host has requested + LLHostStatus *host_statusp = findHostStatus(xferp->mRemoteHost); + if (host_statusp) { - LL_INFOS() << " queueing xfer request, " << numPendingXfers(xferp->mRemoteHost) << " ahead of this one" << LL_ENDL; + if (host_statusp->mNumActive < mMaxOutgoingXfersPerCircuit) + { // Not many transfers in progress already, so start immediately + xferp->sendNextPacket(); + changeNumActiveXfers(xferp->mRemoteHost,1); + LL_DEBUGS("Xfer") << "Starting xfer ID " << fmt::to_string(id) << " immediately" << LL_ENDL; + } + else if (mHardLimitOutgoingXfersPerCircuit == 0 || + (host_statusp->mNumActive + host_statusp->mNumPending) < mHardLimitOutgoingXfersPerCircuit) + { // Must close the file handle and wait for earlier ones to complete + LL_INFOS("Xfer") << " queueing xfer request id " << fmt::to_string(id) << ", " + << host_statusp->mNumActive << " active and " + << host_statusp->mNumPending << " pending ahead of this one" + << LL_ENDL; + xferp->closeFileHandle(); // Close the file handle until we're ready to send again + } + else if (mHardLimitOutgoingXfersPerCircuit > 0) + { // Way too many requested ... it's time to stop being nice and kill the circuit + xferp->closeFileHandle(); // Close the file handle in any case + LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(xferp->mRemoteHost); + if (cdp) + { + if (cdp->getTrusted()) + { // Trusted internal circuit - don't kill it + LL_WARNS("Xfer") << "Trusted circuit to " << xferp->mRemoteHost << " has too many xfer requests in the queue " + << host_statusp->mNumActive << " active and " + << host_statusp->mNumPending << " pending ahead of this one" + << LL_ENDL; + } + else + { // Untrusted circuit - time to stop messing around and kill it + LL_WARNS("Xfer") << "Killing circuit to " << xferp->mRemoteHost << " for having too many xfer requests in the queue " + << host_statusp->mNumActive << " active and " + << host_statusp->mNumPending << " pending ahead of this one" + << LL_ENDL; + gMessageSystem->disableCircuit(xferp->mRemoteHost); + } + } + else + { // WTF? Why can't we find a circuit? Try to kill it off + LL_WARNS("Xfer") << "Backlog with circuit to " << xferp->mRemoteHost << " with too many xfer requests in the queue " + << host_statusp->mNumActive << " active and " + << host_statusp->mNumPending << " pending ahead of this one" + << " but no LLCircuitData found???" + << LL_ENDL; + gMessageSystem->disableCircuit(xferp->mRemoteHost); + } + } } else { - LL_WARNS() << "LLXferManager::processFileRequest() - no xfer found!" - << LL_ENDL; + LL_WARNS("Xfer") << "LLXferManager::processFileRequest() - no LLHostStatus found for id " << fmt::to_string(id) + << " host " << xferp->mRemoteHost << LL_ENDL; } } + else + { + LL_WARNS("Xfer") << "LLXferManager::processFileRequest() - no xfer found for id " << fmt::to_string(id) << LL_ENDL; + } +} + +/////////////////////////////////////////////////////////// + +// Return true if host is in a transfer-flood sitation. Same check for both internal and external hosts +bool LLXferManager::isHostFlooded(const LLHost & host) +{ + bool flooded = false; + LLHostStatus *host_statusp = findHostStatus(host); + if (host_statusp) + { + flooded = (mHardLimitOutgoingXfersPerCircuit > 0 && + (host_statusp->mNumActive + host_statusp->mNumPending) >= (S32)(mHardLimitOutgoingXfersPerCircuit * 0.8f)); + } + + return flooded; } @@ -986,7 +1015,7 @@ void LLXferManager::processConfirmation (LLMessageSystem *mesgsys, void ** /*use mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id); mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Packet, packetNum); - LLXfer* xferp = findXfer(id, mSendList); + LLXfer* xferp = findXferByID(id, mSendList); if (xferp) { // cout << "confirmed packet #" << packetNum << " ping: "<< xferp->ACKTimer.getElapsedTimeF32() << endl; @@ -997,112 +1026,149 @@ void LLXferManager::processConfirmation (LLMessageSystem *mesgsys, void ** /*use } else { - removeXfer(xferp, &mSendList); + removeXfer(xferp, mSendList); } } } /////////////////////////////////////////////////////////// -void LLXferManager::retransmitUnackedPackets () +// Called from LLMessageSystem::processAcks() +void LLXferManager::retransmitUnackedPackets() { LLXfer *xferp; - LLXfer *delp; - xferp = mReceiveList; - while(xferp) + + xfer_list_t::iterator iter = mReceiveList.begin(); + while (iter != mReceiveList.end()) { + xferp = (*iter); if (xferp->mStatus == e_LL_XFER_IN_PROGRESS) { // if the circuit dies, abort if (! gMessageSystem->mCircuitInfo.isCircuitAlive( xferp->mRemoteHost )) { - LL_INFOS() << "Xfer found in progress on dead circuit, aborting" << LL_ENDL; + LL_WARNS("Xfer") << "Xfer found in progress on dead circuit, aborting transfer to " + << xferp->mRemoteHost.getIPandPort() + << LL_ENDL; xferp->mCallbackResult = LL_ERR_CIRCUIT_GONE; xferp->processEOF(); - delp = xferp; - xferp = xferp->mNext; - removeXfer(delp,&mReceiveList); + + iter = mReceiveList.erase(iter); // iter is set to next one after the deletion point + delete (xferp); continue; } } - xferp = xferp->mNext; + ++iter; } - xferp = mSendList; + // Re-build mOutgoingHosts data updateHostStatus(); + F32 et; - while (xferp) + iter = mSendList.begin(); + while (iter != mSendList.end()) { + xferp = (*iter); if (xferp->mWaitingForACK && ( (et = xferp->ACKTimer.getElapsedTimeF32()) > LL_PACKET_TIMEOUT)) { if (xferp->mRetries > LL_PACKET_RETRY_LIMIT) { - LL_INFOS() << "dropping xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet retransmit limit exceeded, xfer dropped" << LL_ENDL; + LL_INFOS("Xfer") << "dropping xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet retransmit limit exceeded, xfer dropped" << LL_ENDL; xferp->abort(LL_ERR_TCP_TIMEOUT); - delp = xferp; - xferp = xferp->mNext; - removeXfer(delp,&mSendList); + iter = mSendList.erase(iter); + delete xferp; + continue; } else { - LL_INFOS() << "resending xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet unconfirmed after: "<< et << " sec, packet " << xferp->mPacketNum << LL_ENDL; + LL_INFOS("Xfer") << "resending xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet unconfirmed after: "<< et << " sec, packet " << xferp->mPacketNum << LL_ENDL; xferp->resendLastPacket(); - xferp = xferp->mNext; } } else if ((xferp->mStatus == e_LL_XFER_REGISTERED) && ( (et = xferp->ACKTimer.getElapsedTimeF32()) > LL_XFER_REGISTRATION_TIMEOUT)) { - LL_INFOS() << "registered xfer never requested, xfer dropped" << LL_ENDL; + LL_INFOS("Xfer") << "registered xfer never requested, xfer dropped" << LL_ENDL; xferp->abort(LL_ERR_TCP_TIMEOUT); - delp = xferp; - xferp = xferp->mNext; - removeXfer(delp,&mSendList); + iter = mSendList.erase(iter); + delete xferp; + continue; } else if (xferp->mStatus == e_LL_XFER_ABORTED) { - LL_WARNS() << "Removing aborted xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << LL_ENDL; - delp = xferp; - xferp = xferp->mNext; - removeXfer(delp,&mSendList); + LL_WARNS("Xfer") << "Removing aborted xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << LL_ENDL; + iter = mSendList.erase(iter); + delete xferp; + continue; } else if (xferp->mStatus == e_LL_XFER_PENDING) { -// LL_INFOS() << "*** numActiveXfers = " << numActiveXfers(xferp->mRemoteHost) << " mMaxOutgoingXfersPerCircuit = " << mMaxOutgoingXfersPerCircuit << LL_ENDL; +// LL_INFOS("Xfer") << "*** numActiveXfers = " << numActiveXfers(xferp->mRemoteHost) << " mMaxOutgoingXfersPerCircuit = " << mMaxOutgoingXfersPerCircuit << LL_ENDL; if (numActiveXfers(xferp->mRemoteHost) < mMaxOutgoingXfersPerCircuit) { -// LL_INFOS() << "bumping pending xfer to active" << LL_ENDL; - xferp->sendNextPacket(); - changeNumActiveXfers(xferp->mRemoteHost,1); - } - xferp = xferp->mNext; - } - else - { - xferp = xferp->mNext; + if (xferp->reopenFileHandle()) + { + LL_WARNS("Xfer") << "Error re-opening file handle for xfer ID " << fmt::to_string(xferp->mID) + << " to host " << xferp->mRemoteHost << LL_ENDL; + xferp->abort(LL_ERR_CANNOT_OPEN_FILE); + iter = mSendList.erase(iter); + delete xferp; + continue; + } + else + { // No error re-opening the file, send the first packet + LL_DEBUGS("Xfer") << "Moving pending xfer ID " << fmt::to_string(xferp->mID) << " to active" << LL_ENDL; + xferp->sendNextPacket(); + changeNumActiveXfers(xferp->mRemoteHost,1); + } + } } - } + ++iter; + } // end while() loop // // HACK - if we're using xfer confirm throttling, throttle our xfer confirms here // so we don't blow through bandwidth. // - while (mXferAckQueue.getLength()) + while (!mXferAckQueue.empty()) { if (mAckThrottle.checkOverflow(1000.0f*8.0f)) { break; } - //LL_INFOS() << "Confirm packet queue length:" << mXferAckQueue.getLength() << LL_ENDL; - LLXferAckInfo ack_info; - mXferAckQueue.pop(ack_info); - //LL_INFOS() << "Sending confirm packet" << LL_ENDL; + //LL_INFOS("Xfer") << "Confirm packet queue length:" << mXferAckQueue.size() << LL_ENDL; + LLXferAckInfo ack_info = mXferAckQueue.front(); + mXferAckQueue.pop_front(); + //LL_INFOS("Xfer") << "Sending confirm packet" << LL_ENDL; sendConfirmPacket(gMessageSystem, ack_info.mID, ack_info.mPacketNum, ack_info.mRemoteHost); mAckThrottle.throttleOverflow(1000.f*8.f); // Assume 1000 bytes/packet } } +/////////////////////////////////////////////////////////// + +void LLXferManager::abortRequestById(U64 xfer_id, S32 result_code) +{ + LLXfer * xferp = findXferByID(xfer_id, mReceiveList); + if (xferp) + { + if (xferp->mStatus == e_LL_XFER_IN_PROGRESS) + { + // causes processAbort(); + xferp->abort(result_code); + } + else + { + xferp->mCallbackResult = result_code; + xferp->processEOF(); //should notify requester + removeXfer(xferp, mReceiveList); + } + // Since already removed or marked as aborted no need + // to wait for processAbort() to start new download + startPendingDownloads(); + } +} /////////////////////////////////////////////////////////// @@ -1115,12 +1181,12 @@ void LLXferManager::processAbort (LLMessageSystem *mesgsys, void ** /*user_data* mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id); mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Result, result_code); - xferp = findXfer(id, mReceiveList); + xferp = findXferByID(id, mReceiveList); if (xferp) { xferp->mCallbackResult = result_code; xferp->processEOF(); - removeXfer(xferp, &mReceiveList); + removeXfer(xferp, mReceiveList); startPendingDownloads(); } } @@ -1136,27 +1202,29 @@ void LLXferManager::startPendingDownloads() // requests get pushed toward the back. Thus, if we didn't do a // stateful iteration, it would be possible for old requests to // never start. - LLXfer* xferp = mReceiveList; + LLXfer* xferp; std::list pending_downloads; S32 download_count = 0; S32 pending_count = 0; - while(xferp) + for (xfer_list_t::iterator iter = mReceiveList.begin(); + iter != mReceiveList.end(); + ++iter) { + xferp = (*iter); if(xferp->mStatus == e_LL_XFER_PENDING) - { + { // Count and accumulate pending downloads ++pending_count; pending_downloads.push_front(xferp); } else if(xferp->mStatus == e_LL_XFER_IN_PROGRESS) - { + { // Count downloads in progress ++download_count; } - xferp = xferp->mNext; } S32 start_count = mMaxIncomingXfers - download_count; - LL_DEBUGS() << "LLXferManager::startPendingDownloads() - XFER_IN_PROGRESS: " + LL_DEBUGS("Xfer") << "LLXferManager::startPendingDownloads() - XFER_IN_PROGRESS: " << download_count << " XFER_PENDING: " << pending_count << " startring " << llmin(start_count, pending_count) << LL_ENDL; @@ -1181,29 +1249,15 @@ void LLXferManager::startPendingDownloads() /////////////////////////////////////////////////////////// -void LLXferManager::addToList(LLXfer* xferp, LLXfer*& head, BOOL is_priority) +void LLXferManager::addToList(LLXfer* xferp, xfer_list_t & xfer_list, BOOL is_priority) { if(is_priority) { - xferp->mNext = NULL; - LLXfer* next = head; - if(next) - { - while(next->mNext) - { - next = next->mNext; - } - next->mNext = xferp; - } - else - { - head = xferp; - } + xfer_list.push_back(xferp); } else { - xferp->mNext = head; - head = xferp; + xfer_list.push_front(xferp); } } diff --git a/indra/llmessage/llxfermanager.h b/indra/llmessage/llxfermanager.h index b84bccb5b7..45ae2ffdd3 100644 --- a/indra/llmessage/llxfermanager.h +++ b/indra/llmessage/llxfermanager.h @@ -41,7 +41,7 @@ class LLVFS; #include "message.h" #include "llassetstorage.h" #include "lldir.h" -#include "lllinkedqueue.h" +#include #include "llthrottle.h" class LLHostStatus @@ -77,10 +77,11 @@ class LLXferManager protected: S32 mMaxOutgoingXfersPerCircuit; + S32 mHardLimitOutgoingXfersPerCircuit; // At this limit, kill off the connection S32 mMaxIncomingXfers; BOOL mUseAckThrottling; // Use ack throttling to cap file xfer bandwidth - LLLinkedQueue mXferAckQueue; + std::deque mXferAckQueue; LLThrottle mAckThrottle; public: @@ -92,19 +93,22 @@ class LLXferManager HIGH_PRIORITY = TRUE, }; - LLXfer *mSendList; - LLXfer *mReceiveList; + // Linked FIFO list, add to the front and pull from back + typedef std::deque xfer_list_t; + xfer_list_t mSendList; + xfer_list_t mReceiveList; typedef std::list status_list_t; status_list_t mOutgoingHosts; - private: protected: // implementation methods virtual void startPendingDownloads(); - virtual void addToList(LLXfer* xferp, LLXfer*& head, BOOL is_priority); + virtual void addToList(LLXfer* xferp, xfer_list_t & xfer_list, BOOL is_priority); std::multiset mExpectedTransfers; // files that are authorized to transfer out std::multiset mExpectedRequests; // files that are authorized to be downloaded on top of + std::multiset mExpectedVFileTransfers; // files that are authorized to transfer out + std::multiset mExpectedVFileRequests; // files that are authorized to be downloaded on top of public: LLXferManager(LLVFS *vfs); @@ -117,14 +121,17 @@ class LLXferManager void setAckThrottleBPS(const F32 bps); // list management routines - virtual LLXfer *findXfer(U64 id, LLXfer *list_head); - virtual void removeXfer (LLXfer *delp, LLXfer **list_head); - virtual U32 numActiveListEntries(LLXfer *list_head); + virtual LLXfer *findXferByID(U64 id, xfer_list_t & xfer_list); + virtual void removeXfer (LLXfer *delp, xfer_list_t & xfer_list); + + LLHostStatus * findHostStatus(const LLHost &host); virtual S32 numActiveXfers(const LLHost &host); virtual S32 numPendingXfers(const LLHost &host); + virtual void changeNumActiveXfers(const LLHost &host, S32 delta); virtual void setMaxOutgoingXfersPerCircuit (S32 max_num); + virtual void setHardLimitOutgoingXfersPerCircuit(S32 max_num); virtual void setMaxIncomingXfers(S32 max_num); virtual void updateHostStatus(); virtual void printHostStatus(); @@ -136,11 +143,9 @@ class LLXferManager virtual S32 decodePacketNum(S32 packet_num); virtual BOOL isLastPacket(S32 packet_num); - virtual U64 registerXfer(const void *datap, const S32 length); - // file requesting routines // .. to file - virtual void requestFile(const std::string& local_filename, + virtual U64 requestFile(const std::string& local_filename, const std::string& remote_filename, ELLPath remote_path, const LLHost& remote_host, @@ -148,7 +153,7 @@ class LLXferManager void (*callback)(void**,S32,LLExtStat), void** user_data, BOOL is_priority = FALSE, BOOL use_big_packets = FALSE); - + /* // .. to memory virtual void requestFile(const std::string& remote_filename, ELLPath remote_path, @@ -157,7 +162,7 @@ class LLXferManager void (*callback)(void*, S32, void**, S32, LLExtStat), void** user_data, BOOL is_priority = FALSE); - + */ // vfile requesting // .. to vfile virtual void requestVFile(const LLUUID &local_id, const LLUUID& remote_id, @@ -180,18 +185,15 @@ class LLXferManager virtual void expectFileForRequest(const std::string& filename); virtual bool validateFileForRequest(const std::string& filename); -/* -// xfer request (may be memory or file) -// .. to file - virtual void requestXfer(const char *local_filename, U64 xfer_id, - BOOL delete_remote_on_completion, - const LLHost &remote_host, void (*callback)(void **,S32),void **user_data); -// .. to memory - virtual void requestXfer(U64 xfer_id, - const LLHost &remote_host, - BOOL delete_remote_on_completion, - void (*callback)(void *, S32, void **, S32),void **user_data); -*/ + /** + Same idea but for VFiles, kept separate to avoid namespace overlap + */ + /* Present in fireengine, not used by viewer + virtual void expectVFileForTransfer(const std::string& filename); + virtual bool validateVFileForTransfer(const std::string& filename); + virtual void expectVFileForRequest(const std::string& filename); + virtual bool validateVFileForRequest(const std::string& filename); + */ virtual void processReceiveData (LLMessageSystem *mesgsys, void **user_data); virtual void sendConfirmPacket (LLMessageSystem *mesgsys, U64 id, S32 packetnum, const LLHost &remote_host); @@ -202,7 +204,10 @@ class LLXferManager virtual void retransmitUnackedPackets (); // error handling + void abortRequestById(U64 xfer_id, S32 result_code); virtual void processAbort (LLMessageSystem *mesgsys, void **user_data); + + virtual bool isHostFlooded(const LLHost & host); }; extern LLXferManager* gXferManager; diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 5037a9284e..e042151ad5 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -73,7 +73,6 @@ #include "llxfermanager.h" #include "timing.h" #include "llquaternion.h" -#include "u64.h" #include "v3dmath.h" #include "v3math.h" #include "v4math.h" @@ -85,7 +84,7 @@ extern AIHTTPTimeoutPolicy fnPtrResponder_timeout; // Constants //const char* MESSAGE_LOG_FILENAME = "message.log"; -static const F32 CIRCUIT_DUMP_TIMEOUT = 30.f; +static const F32Seconds CIRCUIT_DUMP_TIMEOUT(30.f); static const S32 TRUST_TIME_WINDOW = 3; // *NOTE: This needs to be moved into a seperate file so that it never gets @@ -246,7 +245,7 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port, S32 version_patch, bool failure_is_fatal, const F32 circuit_heartbeat_interval, const F32 circuit_timeout) : - mCircuitInfo(circuit_heartbeat_interval, circuit_timeout), + mCircuitInfo(F32Seconds(circuit_heartbeat_interval), F32Seconds(circuit_timeout)), mLastMessageFromTrustedMessageService(false), mPacketRing(new LLPacketRing) { @@ -268,7 +267,7 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port, mSendPacketFailureCount = 0; - mCircuitPrintFreq = 60.f; // seconds + mCircuitPrintFreq = F32Seconds(60.f); loadTemplateFile(filename, failure_is_fatal); @@ -307,20 +306,20 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port, mPollInfop->mPollFD.desc.s = aprSocketp; mPollInfop->mPollFD.client_data = NULL; - F64 mt_sec = getMessageTimeSeconds(); + F64Seconds mt_sec = getMessageTimeSeconds(); mResendDumpTime = mt_sec; mMessageCountTime = mt_sec; mCircuitPrintTime = mt_sec; - mCurrentMessageTimeSeconds = mt_sec; + mCurrentMessageTime = F64Seconds(mt_sec); // Constants for dumping output based on message processing time/count mNumMessageCounts = 0; mMaxMessageCounts = 200; // >= 0 means dump warnings - mMaxMessageTime = 1.f; + mMaxMessageTime = F32Seconds(1.f); mTrueReceiveSize = 0; - mReceiveTime = 0.f; + mReceiveTime = F32Seconds(0.f); } @@ -538,7 +537,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) { // This is the first message being handled after a resetReceiveCounts, // we must be starting the message processing loop. Reset the timers. - mCurrentMessageTimeSeconds = totalTime() * SEC_PER_USEC; + mCurrentMessageTime = totalTime(); mMessageCountTime = getMessageTimeSeconds(); } @@ -765,7 +764,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) } } while (!valid_packet && receive_size > 0); - F64 mt_sec = getMessageTimeSeconds(); + F64Seconds mt_sec = getMessageTimeSeconds(); // Check to see if we need to print debug info if ((mt_sec - mCircuitPrintTime) > mCircuitPrintFreq) { @@ -794,9 +793,9 @@ S32 LLMessageSystem::getReceiveBytes() const } -void LLMessageSystem::processAcks() +void LLMessageSystem::processAcks(F32 collect_time) { - F64 mt_sec = getMessageTimeSeconds(); + F64Seconds mt_sec = getMessageTimeSeconds(); { gTransferManager.updateTransfers(); @@ -820,7 +819,7 @@ void LLMessageSystem::processAcks() mCircuitInfo.resendUnackedPackets(mUnackedListDepth, mUnackedListSize); //cycle through ack list for each host we need to send acks to - mCircuitInfo.sendAcks(); + mCircuitInfo.sendAcks(collect_time); if (!mDenyTrustedCircuitSet.empty()) { @@ -840,10 +839,10 @@ void LLMessageSystem::processAcks() } } - if (mMaxMessageTime >= 0.f) + if (mMaxMessageTime >= F32Seconds(0.f)) { // This is one of the only places where we're required to get REAL message system time. - mReceiveTime = (F32)(getMessageTimeSeconds(TRUE) - mMessageCountTime); + mReceiveTime = getMessageTimeSeconds(TRUE) - mMessageCountTime; if (mReceiveTime > mMaxMessageTime) { dump = TRUE; @@ -1001,14 +1000,6 @@ BOOL LLMessageSystem::isSendFullFast(const char* blockname) return mMessageBuilder->isMessageFull(blockname); } - -// blow away the last block of a message, return FALSE if that leaves no blocks or there wasn't a block to remove -// TODO: Babbage: Remove this horror. -BOOL LLMessageSystem::removeLastBlock() -{ - return mMessageBuilder->removeLastBlock(); -} - S32 LLMessageSystem::sendReliable(const LLHost &host) { return sendReliable(host, LL_DEFAULT_RELIABLE_RETRIES, TRUE, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL); @@ -1017,13 +1008,13 @@ S32 LLMessageSystem::sendReliable(const LLHost &host) S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data) { - F32 timeout; + F32Seconds timeout; LLCircuitData *cdp = mCircuitInfo.findCircuit(host); if (cdp) { timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS, - LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()); + F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged())); } else { @@ -1039,7 +1030,7 @@ S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void S32 LLMessageSystem::sendReliable( const LLHost &host, S32 retries, BOOL ping_based_timeout, - F32 timeout, + F32Seconds timeout, void (*callback)(void **,S32), void ** callback_data) { @@ -1048,11 +1039,11 @@ S32 LLMessageSystem::sendReliable( const LLHost &host, LLCircuitData *cdp = mCircuitInfo.findCircuit(host); if (cdp) { - timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()); + timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged())); } else { - timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX); + timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX)); } } @@ -1084,7 +1075,7 @@ void LLMessageSystem::forwardReliable(const U32 circuit_code) S32 LLMessageSystem::forwardReliable( const LLHost &host, S32 retries, BOOL ping_based_timeout, - F32 timeout, + F32Seconds timeout, void (*callback)(void **,S32), void ** callback_data) { @@ -1094,13 +1085,13 @@ S32 LLMessageSystem::forwardReliable( const LLHost &host, S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data) { - F32 timeout; + F32Seconds timeout; LLCircuitData *cdp = mCircuitInfo.findCircuit(host); if (cdp) { timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS, - LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()); + F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged())); } else { @@ -1344,7 +1335,7 @@ S32 LLMessageSystem::sendMessage(const LLHost &host) else { // mCircuitInfo already points to the correct circuit data - cdp->addBytesOut( buffer_length ); + cdp->addBytesOut( (S32Bytes)buffer_length ); } if(mVerboseLog) @@ -1471,7 +1462,7 @@ void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, BOOL r { // update circuit packet ID tracking (missing/out of order packets) cdp->checkPacketInID( mCurrentRecvPacketID, recv_resent ); - cdp->addBytesIn( mTrueReceiveSize ); + cdp->addBytesIn( (S32Bytes)mTrueReceiveSize ); } if(mVerboseLog) @@ -1738,7 +1729,7 @@ LLHost LLMessageSystem::findHost(const U32 circuit_code) void LLMessageSystem::setMaxMessageTime(const F32 seconds) { - mMaxMessageTime = seconds; + mMaxMessageTime = F32Seconds(seconds); } void LLMessageSystem::setMaxMessageCounts(const S32 num) @@ -2608,54 +2599,54 @@ void LLMessageSystem::summarizeLogs(std::ostream& str) // Incoming str << buffer << std::endl << "Incoming:" << std::endl; - tmp_str = U64_to_str(mTotalBytesIn); + tmp_str = fmt::to_string(mTotalBytesIn); buffer = llformat( "Total bytes received: %20s (%5.2f kbits per second)", tmp_str.c_str(), ((F32)mTotalBytesIn * 0.008f) / run_time); str << buffer << std::endl; - tmp_str = U64_to_str(mPacketsIn); + tmp_str = fmt::to_string(mPacketsIn); buffer = llformat( "Total packets received: %20s (%5.2f packets per second)", tmp_str.c_str(), ((F32) mPacketsIn / run_time)); str << buffer << std::endl; buffer = llformat( "Average packet size: %20.0f bytes", (F32)mTotalBytesIn / (F32)mPacketsIn); str << buffer << std::endl; - tmp_str = U64_to_str(mReliablePacketsIn); + tmp_str = fmt::to_string(mReliablePacketsIn); buffer = llformat( "Total reliable packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mReliablePacketsIn)/((F32) mPacketsIn + 1)); str << buffer << std::endl; - tmp_str = U64_to_str(mCompressedPacketsIn); + tmp_str = fmt::to_string(mCompressedPacketsIn); buffer = llformat( "Total compressed packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mCompressedPacketsIn)/((F32) mPacketsIn + 1)); str << buffer << std::endl; S64 savings = mUncompressedBytesIn - mCompressedBytesIn; - tmp_str = U64_to_str(savings); + tmp_str = fmt::to_string(savings); buffer = llformat( "Total compression savings: %20s bytes", tmp_str.c_str()); str << buffer << std::endl; - tmp_str = U64_to_str(savings/(mCompressedPacketsIn +1)); + tmp_str = fmt::to_string(savings/(mCompressedPacketsIn +1)); buffer = llformat( "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mUncompressedBytesIn)/((F32) mCompressedBytesIn+1)); str << buffer << std::endl; - tmp_str = U64_to_str(savings/(mPacketsIn+1)); + tmp_str = fmt::to_string(savings/(mPacketsIn+1)); buffer = llformat( "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mTotalBytesIn + (F32) savings)/((F32) mTotalBytesIn + 1.f)); // Outgoing str << buffer << std::endl << std::endl << "Outgoing:" << std::endl; - tmp_str = U64_to_str(mTotalBytesOut); + tmp_str = fmt::to_string(mTotalBytesOut); buffer = llformat( "Total bytes sent: %20s (%5.2f kbits per second)", tmp_str.c_str(), ((F32)mTotalBytesOut * 0.008f) / run_time ); str << buffer << std::endl; - tmp_str = U64_to_str(mPacketsOut); + tmp_str = fmt::to_string(mPacketsOut); buffer = llformat( "Total packets sent: %20s (%5.2f packets per second)", tmp_str.c_str(), ((F32)mPacketsOut / run_time)); str << buffer << std::endl; buffer = llformat( "Average packet size: %20.0f bytes", (F32)mTotalBytesOut / (F32)mPacketsOut); str << buffer << std::endl; - tmp_str = U64_to_str(mReliablePacketsOut); + tmp_str = fmt::to_string(mReliablePacketsOut); buffer = llformat( "Total reliable packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mReliablePacketsOut)/((F32) mPacketsOut + 1)); str << buffer << std::endl; - tmp_str = U64_to_str(mCompressedPacketsOut); + tmp_str = fmt::to_string(mCompressedPacketsOut); buffer = llformat( "Total compressed packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mCompressedPacketsOut)/((F32) mPacketsOut + 1)); str << buffer << std::endl; savings = mUncompressedBytesOut - mCompressedBytesOut; - tmp_str = U64_to_str(savings); + tmp_str = fmt::to_string(savings); buffer = llformat( "Total compression savings: %20s bytes", tmp_str.c_str()); str << buffer << std::endl; - tmp_str = U64_to_str(savings/(mCompressedPacketsOut +1)); + tmp_str = fmt::to_string(savings/(mCompressedPacketsOut +1)); buffer = llformat( "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mUncompressedBytesOut)/((F32) mCompressedBytesOut+1)); str << buffer << std::endl; - tmp_str = U64_to_str(savings/(mPacketsOut+1)); + tmp_str = fmt::to_string(savings/(mPacketsOut+1)); buffer = llformat( "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mTotalBytesOut + (F32) savings)/((F32) mTotalBytesOut + 1.f)); str << buffer << std::endl << std::endl; buffer = llformat( "SendPacket failures: %20d", mSendPacketFailureCount); @@ -2755,7 +2746,7 @@ void LLMessageSystem::dumpReceiveCounts() if(mNumMessageCounts > 0) { - LL_DEBUGS("Messaging") << "Dump: " << mNumMessageCounts << " m essages processed in " << mReceiveTime << " seconds" << LL_ENDL; + LL_DEBUGS("Messaging") << "Dump: " << mNumMessageCounts << " messages processed in " << mReceiveTime << " seconds" << LL_ENDL; for (message_template_name_map_t::const_iterator iter = mMessageTemplates.begin(), end = mMessageTemplates.end(); iter != end; iter++) @@ -2764,7 +2755,7 @@ void LLMessageSystem::dumpReceiveCounts() if (mt->mReceiveCount > 0) { LL_INFOS("Messaging") << "Num: " << std::setw(3) << mt->mReceiveCount << " Bytes: " << std::setw(6) << mt->mReceiveBytes - << " Invalid: " << std::setw(3) << mt->mReceiveInvalid << " " << mt->mName << " " << ll_round(100 * mt->mDecodeTimeThisFrame / mReceiveTime) << "%" << LL_ENDL; + << " Invalid: " << std::setw(3) << mt->mReceiveInvalid << " " << mt->mName << " " << ll_round(100 * mt->mDecodeTimeThisFrame / mReceiveTime.value()) << "%" << LL_ENDL; } } } @@ -3412,15 +3403,15 @@ void LLMessageSystem::dumpPacketToLog() //static -U64 LLMessageSystem::getMessageTimeUsecs(const BOOL update) +U64Microseconds LLMessageSystem::getMessageTimeUsecs(const BOOL update) { if (gMessageSystem) { if (update) { - gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC; + gMessageSystem->mCurrentMessageTime = totalTime(); } - return (U64)(gMessageSystem->mCurrentMessageTimeSeconds * USEC_PER_SEC); + return gMessageSystem->mCurrentMessageTime; } else { @@ -3429,19 +3420,19 @@ U64 LLMessageSystem::getMessageTimeUsecs(const BOOL update) } //static -F64 LLMessageSystem::getMessageTimeSeconds(const BOOL update) +F64Seconds LLMessageSystem::getMessageTimeSeconds(const BOOL update) { if (gMessageSystem) { if (update) { - gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC; + gMessageSystem->mCurrentMessageTime = totalTime(); } - return gMessageSystem->mCurrentMessageTimeSeconds; + return gMessageSystem->mCurrentMessageTime; } else { - return totalTime()*SEC_PER_USEC; + return F64Seconds(totalTime()); } } diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index ced674700b..174a202331 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -148,18 +148,15 @@ enum EPacketHeaderLayout const S32 LL_DEFAULT_RELIABLE_RETRIES = 3; -const F32 LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS = 1.f; -const F32 LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS = 1.f; -const F32 LL_PING_BASED_TIMEOUT_DUMMY = 0.0f; - -// *NOTE: Maybe these factors shouldn't include the msec to sec conversion -// implicitly. -// However, all units should be MKS. -const F32 LL_SEMIRELIABLE_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping -const F32 LL_RELIABLE_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping -const F32 LL_FILE_XFER_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping -const F32 LL_LOST_TIMEOUT_FACTOR = 16.f / 1000.f; // factor * averaged ping for marking packets "Lost" -const F32 LL_MAX_LOST_TIMEOUT = 5.f; // Maximum amount of time before considering something "lost" +const F32Seconds LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS(1.f); +const F32Seconds LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS(1.f); +const F32Seconds LL_PING_BASED_TIMEOUT_DUMMY(0.0f); + +const F32 LL_SEMIRELIABLE_TIMEOUT_FACTOR = 5.f; // averaged ping +const F32 LL_RELIABLE_TIMEOUT_FACTOR = 5.f; // averaged ping +const F32 LL_FILE_XFER_TIMEOUT_FACTOR = 5.f; //averaged ping +const F32 LL_LOST_TIMEOUT_FACTOR = 16.f; // averaged ping for marking packets "Lost" +const F32Seconds LL_MAX_LOST_TIMEOUT(5.f); // Maximum amount of time before considering something "lost" const S32 MAX_MESSAGE_COUNT_NUM = 1024; @@ -279,8 +276,8 @@ class LLMessageSystem : public LLMessageSenderInterface BOOL mSendReliable; // does the outgoing message require a pos ack? LLCircuit mCircuitInfo; - F64 mCircuitPrintTime; // used to print circuit debug info every couple minutes - F32 mCircuitPrintFreq; // seconds + F64Seconds mCircuitPrintTime; // used to print circuit debug info every couple minutes + F32Seconds mCircuitPrintFreq; std::map mIPPortToCircuitCode; std::map mCircuitCodeToIPPort; @@ -344,7 +341,7 @@ class LLMessageSystem : public LLMessageSenderInterface BOOL poll(F32 seconds); // Number of seconds that we want to block waiting for data, returns if data was received BOOL checkMessages(S64 frame_count = 0); - void processAcks(); + void processAcks(F32 collect_time = 0.f); BOOL isMessageFast(const char *msg); BOOL isMessage(const char *msg) @@ -460,8 +457,6 @@ class LLMessageSystem : public LLMessageSenderInterface BOOL isSendFull(const char* blockname = NULL); BOOL isSendFullFast(const char* blockname = NULL); - BOOL removeLastBlock(); - //void buildMessage(); S32 zeroCode(U8 **data, S32 *data_size); @@ -478,7 +473,7 @@ class LLMessageSystem : public LLMessageSenderInterface S32 sendReliable( const LLHost &host, S32 retries, BOOL ping_based_retries, - F32 timeout, + F32Seconds timeout, void (*callback)(void **,S32), void ** callback_data); @@ -498,7 +493,7 @@ class LLMessageSystem : public LLMessageSenderInterface const LLHost &host, S32 retries, BOOL ping_based_timeout, - F32 timeout, + F32Seconds timeout, void (*callback)(void **,S32), void ** callback_data); @@ -692,8 +687,8 @@ class LLMessageSystem : public LLMessageSenderInterface void setMaxMessageTime(const F32 seconds); // Max time to process messages before warning and dumping (neg to disable) void setMaxMessageCounts(const S32 num); // Max number of messages before dumping (neg to disable) - static U64 getMessageTimeUsecs(const BOOL update = FALSE); // Get the current message system time in microseconds - static F64 getMessageTimeSeconds(const BOOL update = FALSE); // Get the current message system time in seconds + static U64Microseconds getMessageTimeUsecs(const BOOL update = FALSE); // Get the current message system time in microseconds + static F64Seconds getMessageTimeSeconds(const BOOL update = FALSE); // Get the current message system time in seconds static void setTimeDecodes(BOOL b); static void setTimeDecodesSpamThreshold(F32 seconds); @@ -792,16 +787,16 @@ class LLMessageSystem : public LLMessageSenderInterface BOOL mbError; S32 mErrorCode; - F64 mResendDumpTime; // The last time we dumped resends + F64Seconds mResendDumpTime; // The last time we dumped resends LLMessageCountInfo mMessageCountList[MAX_MESSAGE_COUNT_NUM]; S32 mNumMessageCounts; - F32 mReceiveTime; - F32 mMaxMessageTime; // Max number of seconds for processing messages + F32Seconds mReceiveTime; + F32Seconds mMaxMessageTime; // Max number of seconds for processing messages S32 mMaxMessageCounts; // Max number of messages to process before dumping. - F64 mMessageCountTime; + F64Seconds mMessageCountTime; - F64 mCurrentMessageTimeSeconds; // The current "message system time" (updated the first call to checkMessages after a resetReceiveCount + F64Seconds mCurrentMessageTime; // The current "message system time" (updated the first call to checkMessages after a resetReceiveCount // message system exceptions typedef std::pair exception_t; diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 4d91df1967..a9201ef466 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -618,6 +618,7 @@ char const* const _PREHASH_GroupAccountSummaryRequest = LLMessageStringTable::ge char const* const _PREHASH_GroupVoteHistoryRequest = LLMessageStringTable::getInstance()->getString("GroupVoteHistoryRequest"); char const* const _PREHASH_ParamValue = LLMessageStringTable::getInstance()->getString("ParamValue"); char const* const _PREHASH_MaxAgents = LLMessageStringTable::getInstance()->getString("MaxAgents"); +char const* const _PREHASH_HardMaxAgents = LLMessageStringTable::getInstance()->getString("HardMaxAgents"); char const* const _PREHASH_CreateNewOutfitAttachments = LLMessageStringTable::getInstance()->getString("CreateNewOutfitAttachments"); char const* const _PREHASH_RegionHandle = LLMessageStringTable::getInstance()->getString("RegionHandle"); char const* const _PREHASH_TeleportProgress = LLMessageStringTable::getInstance()->getString("TeleportProgress"); @@ -817,6 +818,7 @@ char const* const _PREHASH_StateSave = LLMessageStringTable::getInstance()->getS char const* const _PREHASH_RoleData = LLMessageStringTable::getInstance()->getString("RoleData"); char const* const _PREHASH_AgentAnimation = LLMessageStringTable::getInstance()->getString("AgentAnimation"); char const* const _PREHASH_AvatarAnimation = LLMessageStringTable::getInstance()->getString("AvatarAnimation"); +char const* const _PREHASH_ObjectAnimation = LLMessageStringTable::getInstance()->getString("ObjectAnimation"); char const* const _PREHASH_LogDwellTime = LLMessageStringTable::getInstance()->getString("LogDwellTime"); char const* const _PREHASH_ParcelGodMarkAsContent = LLMessageStringTable::getInstance()->getString("ParcelGodMarkAsContent"); char const* const _PREHASH_UsePhysics = LLMessageStringTable::getInstance()->getString("UsePhysics"); @@ -1373,6 +1375,11 @@ char const* const _PREHASH_OwnerMask = LLMessageStringTable::getInstance()->getS char const* const _PREHASH_TransferInventoryAck = LLMessageStringTable::getInstance()->getString("TransferInventoryAck"); char const* const _PREHASH_RegionDenyAgeUnverified = LLMessageStringTable::getInstance()->getString("RegionDenyAgeUnverified"); char const* const _PREHASH_AgeVerificationBlock = LLMessageStringTable::getInstance()->getString("AgeVerificationBlock"); +char const* const _PREHASH_RegionAllowAccessBlock = LLMessageStringTable::getInstance()->getString("RegionAllowAccessBlock"); +char const* const _PREHASH_RegionAllowAccessOverride = LLMessageStringTable::getInstance()->getString("RegionAllowAccessOverride"); +char const* const _PREHASH_ParcelEnvironmentBlock = LLMessageStringTable::getInstance()->getString("ParcelEnvironmentBlock"); +char const* const _PREHASH_ParcelEnvironmentVersion = LLMessageStringTable::getInstance()->getString("ParcelEnvironmentVersion"); +char const* const _PREHASH_RegionAllowEnvironmentOverride = LLMessageStringTable::getInstance()->getString("RegionAllowEnvironmentOverride"); char const* const _PREHASH_UCoord = LLMessageStringTable::getInstance()->getString("UCoord"); char const* const _PREHASH_VCoord = LLMessageStringTable::getInstance()->getString("VCoord"); char const* const _PREHASH_FaceIndex = LLMessageStringTable::getInstance()->getString("FaceIndex"); @@ -1386,6 +1393,8 @@ char const* const _PREHASH_AppearanceVersion = LLMessageStringTable::getInstance char const* const _PREHASH_CofVersion = LLMessageStringTable::getInstance()->getString("CofVersion"); char const* const _PREHASH_AppearanceHover = LLMessageStringTable::getInstance()->getString("AppearanceHover"); char const* const _PREHASH_HoverHeight = LLMessageStringTable::getInstance()->getString("HoverHeight"); +char const* const _PREHASH_Experience = LLMessageStringTable::getInstance()->getString("Experience"); +char const* const _PREHASH_ExperienceID = LLMessageStringTable::getInstance()->getString("ExperienceID"); // Aurora Sim char const* const _PREHASH_RegionSizeX = LLMessageStringTable::getInstance()->getString("RegionSizeX"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 50f500f782..390ea8ff7e 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -618,6 +618,7 @@ extern char const* const _PREHASH_GroupAccountSummaryRequest; extern char const* const _PREHASH_GroupVoteHistoryRequest; extern char const* const _PREHASH_ParamValue; extern char const* const _PREHASH_MaxAgents; +extern char const* const _PREHASH_HardMaxAgents; extern char const* const _PREHASH_CreateNewOutfitAttachments; extern char const* const _PREHASH_RegionHandle; extern char const* const _PREHASH_TeleportProgress; @@ -817,6 +818,7 @@ extern char const* const _PREHASH_StateSave; extern char const* const _PREHASH_RoleData; extern char const* const _PREHASH_AgentAnimation; extern char const* const _PREHASH_AvatarAnimation; +extern char const* const _PREHASH_ObjectAnimation; extern char const* const _PREHASH_LogDwellTime; extern char const* const _PREHASH_ParcelGodMarkAsContent; extern char const* const _PREHASH_UsePhysics; @@ -1373,6 +1375,11 @@ extern char const* const _PREHASH_OwnerMask; extern char const* const _PREHASH_TransferInventoryAck; extern char const* const _PREHASH_RegionDenyAgeUnverified; extern char const* const _PREHASH_AgeVerificationBlock; +extern char const* const _PREHASH_RegionAllowAccessBlock; +extern char const* const _PREHASH_RegionAllowAccessOverride; +extern char const* const _PREHASH_ParcelEnvironmentBlock; +extern char const* const _PREHASH_ParcelEnvironmentVersion; +extern char const* const _PREHASH_RegionAllowEnvironmentOverride; extern char const* const _PREHASH_UCoord; extern char const* const _PREHASH_VCoord; extern char const* const _PREHASH_FaceIndex; @@ -1386,6 +1393,8 @@ extern char const* const _PREHASH_AppearanceVersion; extern char const* const _PREHASH_CofVersion; extern char const* const _PREHASH_AppearanceHover; extern char const* const _PREHASH_HoverHeight; +extern char const* const _PREHASH_Experience; +extern char const* const _PREHASH_ExperienceID; // Aurora Sim extern char const* const _PREHASH_RegionSizeX; diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 396f946b48..523bcbb60d 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -32,9 +32,7 @@ #include #if LL_WINDOWS - #define WIN32_LEAN_AND_MEAN - #include - #include +#include "llwin32headerslean.h" #else #include #include diff --git a/indra/llmessage/tests/llmime_test.cpp b/indra/llmessage/tests/llmime_test.cpp deleted file mode 100644 index ea48561ae9..0000000000 --- a/indra/llmessage/tests/llmime_test.cpp +++ /dev/null @@ -1,445 +0,0 @@ -/** - * @file llmime_test.cpp - * @author Phoenix - * @date 2006-12-24 - * @brief BRIEF_DESC of llmime_test.cpp - * - * $LicenseInfo:firstyear=2006&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 "llsdserialize.h" - -#include "../llmime.h" - -#include "../test/lltut.h" - -namespace tut -{ - struct mime_index - { - }; - typedef test_group mime_index_t; - typedef mime_index_t::object mime_index_object_t; - tut::mime_index_t tut_mime_index("LLMime"); - - template<> template<> - void mime_index_object_t::test<1>() - { - LLMimeIndex mime; - ensure("no headers", mime.headers().isUndefined()); - ensure_equals("invalid offset", mime.offset(), -1); - ensure_equals("invalid content length", mime.contentLength(), -1); - ensure("no content type", mime.contentType().empty()); - ensure("not multipart", !mime.isMultipart()); - ensure_equals("no attachments", mime.subPartCount(), 0); - } - - template<> template<> - void mime_index_object_t::test<2>() - { - const S32 CONTENT_LENGTH = 6000; - const S32 CONTENT_OFFSET = 100; - const std::string CONTENT_TYPE = std::string("image/j2c"); - LLSD headers; - headers["Content-Length"] = CONTENT_LENGTH; - headers["Content-Type"] = CONTENT_TYPE; - LLMimeIndex mime(headers, CONTENT_OFFSET); - ensure("headers are map", mime.headers().isMap()); - ensure_equals("offset", mime.offset(), CONTENT_OFFSET); - ensure_equals("content length", mime.contentLength(), CONTENT_LENGTH); - ensure_equals("type is image/j2c", mime.contentType(), CONTENT_TYPE); - ensure("not multipart", !mime.isMultipart()); - ensure_equals("no attachments", mime.subPartCount(), 0); - } - - template<> template<> - void mime_index_object_t::test<3>() - { - const S32 MULTI_CONTENT_LENGTH = 8000; - const S32 MULTI_CONTENT_OFFSET = 100; - const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed"); - LLSD headers; - headers["Content-Length"] = MULTI_CONTENT_LENGTH; - headers["Content-Type"] = MULTI_CONTENT_TYPE; - LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET); - LL_INFOS() << "headers: " << LLSDOStreamer(headers) - << LL_ENDL; - - - const S32 META_CONTENT_LENGTH = 700; - const S32 META_CONTENT_OFFSET = 69; - const std::string META_CONTENT_TYPE = std::string( - "text/llsd+xml"); - headers = LLSD::emptyMap(); - headers["Content-Length"] = META_CONTENT_LENGTH; - headers["Content-Type"] = META_CONTENT_TYPE; - LLMimeIndex meta(headers, META_CONTENT_OFFSET); - mime.attachSubPart(meta); - - const S32 IMAGE_CONTENT_LENGTH = 6000; - const S32 IMAGE_CONTENT_OFFSET = 200; - const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c"); - headers = LLSD::emptyMap(); - headers["Content-Length"] = IMAGE_CONTENT_LENGTH; - headers["Content-Type"] = IMAGE_CONTENT_TYPE; - LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET); - mime.attachSubPart(image); - - // make sure we have a valid multi-part - ensure("is multipart", mime.isMultipart()); - ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET); - ensure_equals( - "multi content length", - mime.contentLength(), - MULTI_CONTENT_LENGTH); - ensure_equals("two attachments", mime.subPartCount(), 2); - - // make sure ranged gets do the right thing with out of bounds - // sub-parts. - LLMimeIndex invalid_child(mime.subPart(-1)); - ensure("no headers", invalid_child.headers().isUndefined()); - ensure_equals("invalid offset", invalid_child.offset(), -1); - ensure_equals( - "invalid content length", invalid_child.contentLength(), -1); - ensure("no content type", invalid_child.contentType().empty()); - ensure("not multipart", !invalid_child.isMultipart()); - ensure_equals("no attachments", invalid_child.subPartCount(), 0); - - invalid_child = mime.subPart(2); - ensure("no headers", invalid_child.headers().isUndefined()); - ensure_equals("invalid offset", invalid_child.offset(), -1); - ensure_equals( - "invalid content length", invalid_child.contentLength(), -1); - ensure("no content type", invalid_child.contentType().empty()); - ensure("not multipart", !invalid_child.isMultipart()); - ensure_equals("no attachments", invalid_child.subPartCount(), 0); - } - - template<> template<> - void mime_index_object_t::test<4>() - { - const S32 MULTI_CONTENT_LENGTH = 8000; - const S32 MULTI_CONTENT_OFFSET = 100; - const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed"); - LLSD headers; - headers["Content-Length"] = MULTI_CONTENT_LENGTH; - headers["Content-Type"] = MULTI_CONTENT_TYPE; - LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET); - - const S32 META_CONTENT_LENGTH = 700; - const S32 META_CONTENT_OFFSET = 69; - const std::string META_CONTENT_TYPE = std::string( - "application/llsd+xml"); - headers = LLSD::emptyMap(); - headers["Content-Length"] = META_CONTENT_LENGTH; - headers["Content-Type"] = META_CONTENT_TYPE; - LLMimeIndex meta(headers, META_CONTENT_OFFSET); - mime.attachSubPart(meta); - - const S32 IMAGE_CONTENT_LENGTH = 6000; - const S32 IMAGE_CONTENT_OFFSET = 200; - const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c"); - headers = LLSD::emptyMap(); - headers["Content-Length"] = IMAGE_CONTENT_LENGTH; - headers["Content-Type"] = IMAGE_CONTENT_TYPE; - LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET); - mime.attachSubPart(image); - - // check what we have - ensure("is multipart", mime.isMultipart()); - ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET); - ensure_equals( - "multi content length", - mime.contentLength(), - MULTI_CONTENT_LENGTH); - ensure_equals("two attachments", mime.subPartCount(), 2); - - LLMimeIndex actual_meta = mime.subPart(0); - ensure_equals( - "meta type", actual_meta.contentType(), META_CONTENT_TYPE); - ensure_equals( - "meta offset", actual_meta.offset(), META_CONTENT_OFFSET); - ensure_equals( - "meta content length", - actual_meta.contentLength(), - META_CONTENT_LENGTH); - - LLMimeIndex actual_image = mime.subPart(1); - ensure_equals( - "image type", actual_image.contentType(), IMAGE_CONTENT_TYPE); - ensure_equals( - "image offset", actual_image.offset(), IMAGE_CONTENT_OFFSET); - ensure_equals( - "image content length", - actual_image.contentLength(), - IMAGE_CONTENT_LENGTH); - } - -/* - template<> template<> - void mime_index_object_t::test<5>() - { - } - template<> template<> - void mime_index_object_t::test<6>() - { - } - template<> template<> - void mime_index_object_t::test<7>() - { - } - template<> template<> - void mime_index_object_t::test<8>() - { - } - template<> template<> - void mime_index_object_t::test<>() - { - } -*/ -} - - -namespace tut -{ - struct mime_parse - { - }; - typedef test_group mime_parse_t; - typedef mime_parse_t::object mime_parse_object_t; - tut::mime_parse_t tut_mime_parse("LLMimeParse"); - - template<> template<> - void mime_parse_object_t::test<1>() - { - // parse one mime object - const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure_equals("content type", mime.contentType(), "text/plain"); - ensure_equals("content length", mime.contentLength(), 200); - ensure_equals("offset", mime.offset(), 49); - } - - template<> template<> - void mime_parse_object_t::test<2>() - { - // make sure we only parse one. - const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\nContent-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure("not multipart.", !mime.isMultipart()); - ensure_equals("content type", mime.contentType(), "text/plain"); - ensure_equals("content length", mime.contentLength(), 200); - ensure_equals("offset", mime.offset(), 49); - } - - template<> template<> - void mime_parse_object_t::test<3>() - { - // test multi-part and lack of content length for some of it. - /* -Content-Type: multipart/mixed; boundary="segment"rnContent-Length: 148rnrn--segmentrnContent-Type: text/plainrnrnsome datarnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrnrnrn - */ - const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=\"segment\"\r\nContent-Length: 150\r\n\r\n--segment\r\nContent-Type: text/plain\r\n\r\nsome data\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n\r\n\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure("is multipart.", mime.isMultipart()); - ensure_equals("sub-part count", mime.subPartCount(), 2); - ensure_equals("content length", mime.contentLength(), 150); - ensure_equals("data offset for multipart", mime.offset(), 74); - - LLMimeIndex mime_plain(mime.subPart(0)); - ensure_equals( - "first part type", - mime_plain.contentType(), - "text/plain"); - ensure_equals( - "first part content length not known.", - mime_plain.contentLength(), - -1); - ensure_equals("first part offset", mime_plain.offset(), 113); - - LLMimeIndex mime_xml(mime.subPart(1)); - ensure_equals( - "second part type", - mime_xml.contentType(), - "text/xml; charset=UTF-8"); - ensure_equals( - "second part content length", - mime_xml.contentLength(), - 22); - ensure_equals("second part offset", mime_xml.offset(), 198); - } - - template<> template<> - void mime_parse_object_t::test<4>() - { - // test multi-part, unquoted separator, and premature eof conditions - /* -Content-Type: multipart/mixed; boundary=segmentrnContent-Length: 220rnrn--segmentrnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrnrnrn */ - const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n\r\n\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure("is multipart.", mime.isMultipart()); - ensure_equals("sub-part count", mime.subPartCount(), 2); - ensure_equals("content length", mime.contentLength(), 220); - ensure_equals("data offset for multipart", mime.offset(), 72); - - LLMimeIndex mime_plain(mime.subPart(0)); - ensure_equals( - "first part type", - mime_plain.contentType(), - "text/plain"); - ensure_equals( - "first part content length", - mime_plain.contentLength(), - 55); - ensure_equals("first part offset", mime_plain.offset(), 131); - - LLMimeIndex mime_xml(mime.subPart(1)); - ensure_equals( - "second part type", - mime_xml.contentType(), - "text/xml; charset=UTF-8"); - ensure_equals( - "second part content length", - mime_xml.contentLength(), - 22); - ensure_equals("second part offset", mime_xml.offset(), 262); - } - - template<> template<> - void mime_parse_object_t::test<5>() - { - // test multi-part with multiple params - const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment; comment=\"testing multiple params.\"\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n\r\n\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure("is multipart.", mime.isMultipart()); - ensure_equals("sub-part count", mime.subPartCount(), 2); - ensure_equals("content length", mime.contentLength(), 220); - - LLMimeIndex mime_plain(mime.subPart(0)); - ensure_equals( - "first part type", - mime_plain.contentType(), - "text/plain"); - ensure_equals( - "first part content length", - mime_plain.contentLength(), - 55); - - LLMimeIndex mime_xml(mime.subPart(1)); - ensure_equals( - "second part type", - mime_xml.contentType(), - "text/xml; charset=UTF-8"); - ensure_equals( - "second part content length", - mime_xml.contentLength(), - 22); - } - - template<> template<> - void mime_parse_object_t::test<6>() - { - // test multi-part with no specified boundary and eof -/* -Content-Type: multipart/relatedrnContent-Length: 220rnrn--rnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--rnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrnrnrn -*/ - const std::string SERIALIZED_MIME("Content-Type: multipart/related\r\nContent-Length: 500\r\n\r\n--\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n\r\n\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure("is multipart.", mime.isMultipart()); - ensure_equals("sub-part count", mime.subPartCount(), 2); - ensure_equals("content length", mime.contentLength(), 500); - ensure_equals("data offset for multipart", mime.offset(), 56); - - LLMimeIndex mime_plain(mime.subPart(0)); - ensure_equals( - "first part type", - mime_plain.contentType(), - "text/plain"); - ensure_equals( - "first part content length", - mime_plain.contentLength(), - 55); - ensure_equals("first part offset", mime_plain.offset(), 108); - - LLMimeIndex mime_xml(mime.subPart(1)); - ensure_equals( - "second part type", - mime_xml.contentType(), - "text/xml; charset=UTF-8"); - ensure_equals( - "second part content length", - mime_xml.contentLength(), - 22); - ensure_equals("second part offset", mime_xml.offset(), 232); - } - -/* - template<> template<> - void mime_parse_object_t::test<>() - { - } - template<> template<> - void mime_parse_object_t::test<>() - { - } - template<> template<> - void mime_parse_object_t::test<>() - { - } - template<> template<> - void mime_parse_object_t::test<>() - { - } -*/ -} diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index 22edd9dad8..a81399a331 100644 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """\ @file test_llsdmessage_peer.py @author Nat Goodspeed diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py index f2c841532a..4c89b11b56 100644 --- a/indra/llmessage/tests/testrunner.py +++ b/indra/llmessage/tests/testrunner.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """\ @file testrunner.py @author Nat Goodspeed diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt index 5aa33696ea..98417bbd7c 100644 --- a/indra/llplugin/CMakeLists.txt +++ b/indra/llplugin/CMakeLists.txt @@ -7,19 +7,19 @@ include(LLCommon) include(LLMath) include(LLMessage) include(LLRender) +include(Boost) include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} - ${LLQTWEBKIT_INCLUDE_DIR} ) set(llplugin_SOURCE_FILES llpluginclassbasic.cpp llpluginclassmedia.cpp - llplugincookiestore.cpp + #llplugincookiestore.cpp llplugininstance.cpp llpluginmessage.cpp llpluginmessagepipe.cpp @@ -34,7 +34,7 @@ set(llplugin_HEADER_FILES llpluginclassbasic.h llpluginclassmedia.h llpluginclassmediaowner.h - llplugincookiestore.h + #llplugincookiestore.h llplugininstance.h llpluginmessage.h llpluginmessageclasses.h @@ -47,22 +47,20 @@ set(llplugin_HEADER_FILES set_source_files_properties(${llplugin_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) -if(NOT WORD_SIZE EQUAL 32) - if(WINDOWS) - # add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) -endif (NOT WORD_SIZE EQUAL 32) - list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES}) add_library (llplugin ${llplugin_SOURCE_FILES}) if(LINUX AND STANDALONE) - target_link_libraries (llplugin rt dl) -endif(LINUX AND STANDALONE) + target_link_libraries (llplugin llcommon rt dl) +else() + target_link_libraries( + llplugin + PUBLIC + llcommon + ) +endif() -add_dependencies(llplugin prepare) +set_target_properties(llplugin PROPERTIES POSITION_INDEPENDENT_CODE TRUE) add_subdirectory(slplugin) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index c5ff97ef73..daa7f4c8a8 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llpluginclassmedia.cpp * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class. * @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&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$ * @endcond @@ -41,7 +41,7 @@ static int nextPowerOf2( int value ) { next_power_of_2 <<= 1; } - + return next_power_of_2; } @@ -62,6 +62,7 @@ bool LLPluginClassMedia::init_impl(void) return true; } + void LLPluginClassMedia::reset_impl(void) { mTextureParamsReceived = false; @@ -91,20 +92,26 @@ void LLPluginClassMedia::reset_impl(void) mMediaHeight = 0; mDirtyRect = LLRect::null; mAutoScaleMedia = false; - mRequestedVolume = 1.0f; + mRequestedVolume = 0.0f; + mPriority = PRIORITY_NORMAL; mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT; mAllowDownsample = false; mPadding = 0; mLastMouseX = 0; mLastMouseY = 0; mStatus = LLPluginClassMediaOwner::MEDIA_NONE; + mSleepTime = 1.0f / 100.0f; + mCanUndo = false; + mCanRedo = false; mCanCut = false; mCanCopy = false; mCanPaste = false; + mCanDoDelete = false; + mCanSelectAll = false; mMediaName.clear(); mMediaDescription.clear(); mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f); - + // media_browser class mNavigateURI.clear(); mNavigateResultCode = -1; @@ -112,13 +119,17 @@ void LLPluginClassMedia::reset_impl(void) mHistoryBackAvailable = false; mHistoryForwardAvailable = false; mStatusText.clear(); - mProgressPercent = 0; + mProgressPercent = 0; mClickURL.clear(); mClickNavType.clear(); mClickTarget.clear(); mClickUUID.clear(); mStatusCode = 0; - + + mClickEnforceTarget = false; + + mZoomFactor = 1.0; + // media_time class mCurrentTime = 0.0f; mDuration = 0.0f; @@ -128,7 +139,12 @@ void LLPluginClassMedia::reset_impl(void) void LLPluginClassMedia::idle_impl(void) { - if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL)) + if(mPlugin) + { + mPlugin->idle(); + } + + if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == nullptr) || (mPlugin->isBlocked()) || (mOwner == nullptr)) { // Can't process a size change at this time } @@ -144,7 +160,7 @@ void LLPluginClassMedia::idle_impl(void) else { mRequestedTextureWidth = mRequestedMediaWidth; - + if(mPadding > 1) { // Pad up to a multiple of the specified number of bytes per row @@ -154,7 +170,7 @@ void LLPluginClassMedia::idle_impl(void) { rowbytes += mPadding - pad; } - + if(rowbytes % mRequestedTextureDepth == 0) { mRequestedTextureWidth = rowbytes / mRequestedTextureDepth; @@ -166,7 +182,7 @@ void LLPluginClassMedia::idle_impl(void) } } - + // Size change has been requested but not initiated yet. size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth; @@ -181,22 +197,29 @@ void LLPluginClassMedia::idle_impl(void) mPlugin->removeSharedMemory(mTextureSharedMemoryName); mTextureSharedMemoryName.clear(); } - + mTextureSharedMemorySize = newsize; mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize); if(!mTextureSharedMemoryName.empty()) { void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName); - + // clear texture memory to avoid random screen visual fuzz from uninitialized texture data - memset( addr, 0x00, newsize ); - + if (addr) + { + memset( addr, 0x00, newsize ); + } + else + { + LL_WARNS("Plugin") << "Failed to get previously created shared memory address: " << mTextureSharedMemoryName << " size: " << mTextureSharedMemorySize << LL_ENDL; + } + // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin, // so it may not be worthwhile. // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight); } } - + // This is our local indicator that a change is in progress. mTextureWidth = -1; mTextureHeight = -1; @@ -205,7 +228,7 @@ void LLPluginClassMedia::idle_impl(void) // This invalidates any existing dirty rect. resetDirty(); - + // Send a size change message to the plugin { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change"); @@ -219,7 +242,7 @@ void LLPluginClassMedia::idle_impl(void) message.setValueReal("background_b", mBackgroundColor.mV[VZ]); message.setValueReal("background_a", mBackgroundColor.mV[VW]); mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue. - + LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL; } } @@ -237,8 +260,8 @@ int LLPluginClassMedia::getTextureHeight() const unsigned char* LLPluginClassMedia::getBitsData() { - unsigned char *result = NULL; - if((mPlugin != NULL) && !mTextureSharedMemoryName.empty()) + unsigned char *result = nullptr; + if((mPlugin != nullptr) && !mTextureSharedMemoryName.empty()) { result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName); } @@ -278,11 +301,11 @@ void LLPluginClassMedia::setSizeInternal(void) mRequestedMediaWidth = mDefaultMediaWidth; mRequestedMediaHeight = mDefaultMediaHeight; } - + // Save these for size/interest calculations mFullMediaWidth = mRequestedMediaWidth; mFullMediaHeight = mRequestedMediaHeight; - + if(mAllowDownsample) { switch(mPriority) @@ -296,24 +319,24 @@ void LLPluginClassMedia::setSizeInternal(void) mRequestedMediaHeight /= 2; } break; - + default: // Don't adjust texture size break; } } - + if(mAutoScaleMedia) { mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth); mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight); } - - if(mRequestedMediaWidth > 2048) - mRequestedMediaWidth = 2048; - if(mRequestedMediaHeight > 2048) - mRequestedMediaHeight = 2048; + if(mRequestedMediaWidth > 6000) + mRequestedMediaWidth = 6000; + + if(mRequestedMediaHeight > 6000) + mRequestedMediaHeight = 6000; } void LLPluginClassMedia::setAutoScale(bool auto_scale) @@ -335,10 +358,10 @@ bool LLPluginClassMedia::textureValid(void) mMediaHeight <= 0 || mRequestedMediaWidth != mMediaWidth || mRequestedMediaHeight != mMediaHeight || - getBitsData() == NULL - ) + getBitsData() == nullptr + ) return false; - + return true; } @@ -346,7 +369,7 @@ bool LLPluginClassMedia::getDirty(LLRect *dirty_rect) { bool result = !mDirtyRect.isEmpty(); - if(dirty_rect != NULL) + if(dirty_rect != nullptr) { *dirty_rect = mDirtyRect; } @@ -362,8 +385,8 @@ void LLPluginClassMedia::resetDirty(void) std::string LLPluginClassMedia::translateModifiers(MASK modifiers) { std::string result; - - + + if(modifiers & MASK_CONTROL) { result += "control|"; @@ -386,7 +409,7 @@ std::string LLPluginClassMedia::translateModifiers(MASK modifiers) { result += "meta|"; } -*/ +*/ return result; } @@ -494,11 +517,11 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int // Don't spam unnecessary mouse move events. return; } - + mLastMouseX = x; mLastMouseY = y; } - + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event"); std::string temp; switch(type) @@ -513,7 +536,7 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int message.setValueS32("button", button); message.setValueS32("x", x); - + // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it. if(!mRequestedTextureCoordsOpenGL) { @@ -523,42 +546,42 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int message.setValueS32("y", y); message.setValue("modifiers", translateModifiers(modifiers)); - + sendMessage(message); } bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data) { bool result = true; - + // FIXME: // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode. // For now, return false for the ones the webkit plugin won't handle properly. - + switch(key_code) { - case KEY_BACKSPACE: - case KEY_TAB: - case KEY_RETURN: - case KEY_PAD_RETURN: - case KEY_SHIFT: - case KEY_CONTROL: - case KEY_ALT: - case KEY_CAPSLOCK: - case KEY_ESCAPE: - case KEY_PAGE_UP: - case KEY_PAGE_DOWN: - case KEY_END: - case KEY_HOME: - case KEY_LEFT: - case KEY_UP: - case KEY_RIGHT: - case KEY_DOWN: - case KEY_INSERT: + case KEY_BACKSPACE: + case KEY_TAB: + case KEY_RETURN: + case KEY_PAD_RETURN: + case KEY_SHIFT: + case KEY_CONTROL: + case KEY_ALT: + case KEY_CAPSLOCK: + case KEY_ESCAPE: + case KEY_PAGE_UP: + case KEY_PAGE_DOWN: + case KEY_END: + case KEY_HOME: + case KEY_LEFT: + case KEY_UP: + case KEY_RIGHT: + case KEY_DOWN: + case KEY_INSERT: case KEY_DELETE: - // These will be handled + // These will be handled break; - + default: // regular ASCII characters will also be handled if(key_code >= KEY_SPECIAL) @@ -569,7 +592,7 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie break; } -#if LL_DARWIN +#if LL_DARWIN if(modifiers & MASK_ALT) { // Option-key modified characters should be handled by the unicode input path instead of this one. @@ -588,29 +611,31 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie case KEY_EVENT_REPEAT: temp = "repeat"; break; } message.setValue("event", temp); - + message.setValueS32("key", key_code); message.setValue("modifiers", translateModifiers(modifiers)); message.setValueLLSD("native_key_data", native_key_data); - + sendMessage(message); } - + return result; } -void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers) +void LLPluginClassMedia::scrollEvent(int x, int y, int clicks_x, int clicks_y, MASK modifiers) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event"); message.setValueS32("x", x); message.setValueS32("y", y); + message.setValueS32("clicks_x", clicks_x); + message.setValueS32("clicks_y", clicks_y); message.setValue("modifiers", translateModifiers(modifiers)); - + sendMessage(message); } - + bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event"); @@ -618,18 +643,33 @@ bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD message.setValue("text", text); message.setValue("modifiers", translateModifiers(modifiers)); message.setValueLLSD("native_key_data", native_key_data); - + sendMessage(message); - + return true; } +void LLPluginClassMedia::setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_cookie"); + + message.setValue("uri", uri); + message.setValue("name", name); + message.setValue("value", value); + message.setValue("domain", domain); + message.setValue("path", path); + message.setValueBoolean("httponly", httponly); + message.setValueBoolean("secure", secure); + + sendMessage(message); +} + void LLPluginClassMedia::loadURI(const std::string &uri) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri"); message.setValue("uri", uri); - + sendMessage(message); } @@ -645,6 +685,7 @@ void LLPluginClassMedia::setLowPrioritySizeLimit(int size) if(mLowPrioritySizeLimit != power) { mLowPrioritySizeLimit = power; + // This may affect the calculated size, so recalculate it here. setSizeInternal(); } @@ -653,24 +694,31 @@ void LLPluginClassMedia::setLowPrioritySizeLimit(int size) F64 LLPluginClassMedia::getCPUUsage() { F64 result = 0.0f; - + if(mPlugin) { result = mPlugin->getCPUUsage(); } - + return result; } -void LLPluginClassMedia::sendPickFileResponse(const std::string &file) +void LLPluginClassMedia::sendPickFileResponse(const std::vector files) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response"); - message.setValue("file", file); if(mPlugin && mPlugin->isBlocked()) { // If the plugin sent a blocking pick-file request, the response should unblock it. message.setValueBoolean("blocking_response", true); } + + LLSD file_list = LLSD::emptyArray(); + for (const auto& file : files) + { + file_list.append(LLSD::String(file)); + } + message.setValueLLSD("file_list", file_list); + sendMessage(message); } @@ -688,6 +736,18 @@ void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, sendMessage(message); } +void LLPluginClassMedia::undo() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_undo"); + sendMessage(message); +} + +void LLPluginClassMedia::redo() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_redo"); + sendMessage(message); +} + void LLPluginClassMedia::cut() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut"); @@ -706,10 +766,33 @@ void LLPluginClassMedia::paste() sendMessage(message); } -void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path) +void LLPluginClassMedia::doDelete() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_delete"); + sendMessage(message); +} + +void LLPluginClassMedia::selectAll() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_select_all"); + sendMessage(message); +} + +void LLPluginClassMedia::showPageSource() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_show_source"); + sendMessage(message); +} + +void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache, + const std::string &user_data_path_cookies, + const std::string &user_data_path_cef_log) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path"); - message.setValue("path", user_data_path); + message.setValue("cache_path", user_data_path_cache); + message.setValue("cookies_path", user_data_path_cookies); + message.setValue("cef_log_file", user_data_path_cef_log); + sendMessage(message); } @@ -722,14 +805,14 @@ void LLPluginClassMedia::setLanguageCode(const std::string &language_code) void LLPluginClassMedia::setPluginsEnabled(const bool enabled) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled"); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "plugins_enabled"); message.setValueBoolean("enable", enabled); sendMessage(message); } void LLPluginClassMedia::setJavascriptEnabled(const bool enabled) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled"); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "javascript_enabled"); message.setValueBoolean("enable", enabled); sendMessage(message); } @@ -746,7 +829,8 @@ void LLPluginClassMedia::setTarget(const std::string &target) { mTarget = target; } -/* virtual */ + +/* virtual */ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { std::string message_class = message.getClass(); @@ -765,21 +849,21 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mRequestedTextureFormat = message.getValueU32("format"); mRequestedTextureType = message.getValueU32("type"); mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes"); - mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl"); - + mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl"); + // These two are optional, and will default to 0 if they're not specified. mDefaultMediaWidth = message.getValueS32("default_width"); mDefaultMediaHeight = message.getValueS32("default_height"); - + mAllowDownsample = message.getValueBoolean("allow_downsample"); mPadding = message.getValueS32("padding"); setSizeInternal(); - + mTextureParamsReceived = true; } else if(message_name == "updated") - { + { if(message.hasValue("left")) { LLRect newDirtyRect; @@ -787,7 +871,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) newDirtyRect.mTop = message.getValueS32("top"); newDirtyRect.mRight = message.getValueS32("right"); newDirtyRect.mBottom = message.getValueS32("bottom"); - + // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion. // If they're backwards, swap them. if(newDirtyRect.mTop < newDirtyRect.mBottom) @@ -796,7 +880,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) newDirtyRect.mTop = newDirtyRect.mBottom; newDirtyRect.mBottom = temp; } - + if(mDirtyRect.isEmpty()) { mDirtyRect = newDirtyRect; @@ -806,7 +890,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mDirtyRect.unionWith(newDirtyRect); } - LL_DEBUGS("PluginUpdated") << "adjusted incoming rect is: (" + LL_DEBUGS("PluginUpdated") << "adjusted incoming rect is: (" << newDirtyRect.mLeft << ", " << newDirtyRect.mTop << ", " << newDirtyRect.mRight << ", " @@ -816,10 +900,10 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) << mDirtyRect.mRight << ", " << mDirtyRect.mBottom << ")" << LL_ENDL; - + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED); - } - + } + bool time_duration_updated = false; int previous_percent = mProgressPercent; @@ -839,7 +923,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { mCurrentRate = message.getValueReal("current_rate"); } - + if(message.hasValue("loaded_duration")) { mLoadedDuration = message.getValueReal("loaded_duration"); @@ -850,7 +934,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) // If the message doesn't contain a loaded_duration param, assume it's equal to duration mLoadedDuration = mDuration; } - + // Calculate a percentage based on the loaded duration and total duration. if(mDuration != 0.0f) // Don't divide by zero. { @@ -861,7 +945,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED); } - + if(previous_percent != mProgressPercent) { mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED); @@ -870,9 +954,9 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) else if(message_name == "media_status") { std::string status = message.getValue("status"); - + LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL; - + if(status == "loading") { mStatus = LLPluginClassMediaOwner::MEDIA_LOADING; @@ -907,29 +991,25 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { S32 width = message.getValueS32("width"); S32 height = message.getValueS32("height"); - std::string name = message.getValue("name"); // TODO: check that name matches? mNaturalMediaWidth = width; mNaturalMediaHeight = height; - + setSizeInternal(); } else if(message_name == "size_change_response") { - std::string name = message.getValue("name"); - // TODO: check that name matches? - mTextureWidth = message.getValueS32("texture_width"); mTextureHeight = message.getValueS32("texture_height"); mMediaWidth = message.getValueS32("width"); mMediaHeight = message.getValueS32("height"); - + // This invalidates any existing dirty rect. resetDirty(); - - // TODO: should we verify that the plugin sent back the right values? + + // TODO: should we verify that the plugin sent back the right values? // Two size changes in a row may cause them to not match, due to queueing, etc. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED); @@ -942,6 +1022,14 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) } else if(message_name == "edit_state") { + if(message.hasValue("undo")) + { + mCanUndo = message.getValueBoolean("undo"); + } + if(message.hasValue("redo")) + { + mCanRedo = message.getValueBoolean("redo"); + } if(message.hasValue("cut")) { mCanCut = message.getValueBoolean("cut"); @@ -954,14 +1042,25 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { mCanPaste = message.getValueBoolean("paste"); } + if (message.hasValue("delete")) + { + mCanDoDelete = message.getValueBoolean("delete"); + } + if (message.hasValue("select_all")) + { + mCanSelectAll = message.getValueBoolean("select_all"); + } } else if(message_name == "name_text") { + mHistoryBackAvailable = message.getValueBoolean("history_back_available"); + mHistoryForwardAvailable = message.getValueBoolean("history_forward_available"); mMediaName = message.getValue("name"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED); } else if(message_name == "pick_file") { + mIsMultipleFilePick = message.getValueBoolean("multiple_files"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST); } else if(message_name == "auth_request") @@ -969,7 +1068,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mAuthURL = message.getValue("url"); mAuthRealm = message.getValue("realm"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST); - } + } + else if (message_name == "file_download") + { + mFileDownloadFilename = message.getValue("filename"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_FILE_DOWNLOAD); + } else if(message_name == "debug_message") { mDebugMessageText = message.getValue("message_text"); @@ -996,7 +1100,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mNavigateResultString = message.getValue("result_string"); mHistoryBackAvailable = message.getValueBoolean("history_back_available"); mHistoryForwardAvailable = message.getValueBoolean("history_forward_available"); - + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE); } else if(message_name == "progress") @@ -1018,7 +1122,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { mClickURL = message.getValue("uri"); mClickTarget = message.getValue("target"); - mClickUUID = message.getValue("uuid"); + + // need a link to have a UUID that identifies it to a system further + // upstream - plugin could make it but we have access to LLUUID here + // so why don't we use it + mClickUUID = LLUUID::generateNewID().asString(); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF); } else if(message_name == "click_nofollow") @@ -1033,13 +1142,6 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mStatusCode = message.getValueS32("status_code"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE); } - else if(message_name == "cookie_set") - { - if(mOwner) - { - mOwner->handleCookieSet(this, message.getValue("cookie")); - } - } else if(message_name == "close_request") { mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST); @@ -1051,7 +1153,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mGeometryY = message.getValueS32("y"); mGeometryWidth = message.getValueS32("width"); mGeometryHeight = message.getValueS32("height"); - + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE); } else if(message_name == "link_hovered") @@ -1060,7 +1162,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mHoverLink = message.getValue("link"); mHoverText = message.getValue("title"); // message.getValue("text"); - + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED); } else @@ -1076,20 +1178,21 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) // if(message_name == "message_name") // { // } -// else +// else { - LL_WARNS("Plugin") << "Unknown " << message_class << " class message: " << message_name << LL_ENDL; + LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; } } + } -/* virtual */ +/* virtual */ void LLPluginClassMedia::pluginLaunchFailed() { mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH); } -/* virtual */ +/* virtual */ void LLPluginClassMedia::pluginDied() { mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED); @@ -1116,11 +1219,11 @@ void LLPluginClassMedia::focus(bool focused) LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus"); message.setValueBoolean("focused", focused); - + sendMessage(message); } -void LLPluginClassMedia::set_page_zoom_factor( double factor ) +void LLPluginClassMedia::set_page_zoom_factor( F64 factor ) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_page_zoom_factor"); @@ -1140,27 +1243,23 @@ void LLPluginClassMedia::clear_cookies() sendMessage(message); } -void LLPluginClassMedia::set_cookies(const std::string &cookies) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies"); - message.setValue("cookies", cookies); - sendMessage(message); -} - -void LLPluginClassMedia::enable_cookies(bool enable) +void LLPluginClassMedia::cookies_enabled(bool enable) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies"); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "cookies_enabled"); message.setValueBoolean("enable", enable); sendMessage(message); } -void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port) +void LLPluginClassMedia::proxy_setup(bool enable, int type, const std::string &host, int port, const std::string &user, const std::string &pass) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup"); message.setValueBoolean("enable", enable); + message.setValueS32("proxy_type", type); message.setValue("host", host); message.setValueS32("port", port); + message.setValue("username", user); + message.setValue("password", pass); sendMessage(message); } @@ -1176,7 +1275,7 @@ void LLPluginClassMedia::browse_reload(bool ignore_cache) LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload"); message.setValueBoolean("ignore_cache", ignore_cache); - + sendMessage(message); } @@ -1192,16 +1291,6 @@ void LLPluginClassMedia::browse_back() sendMessage(message); } -void LLPluginClassMedia::set_status_redirect(int code, const std::string &url) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_status_redirect"); - - message.setValueS32("code", code); - message.setValue("url", url); - - sendMessage(message); -} - void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent"); @@ -1251,6 +1340,12 @@ void LLPluginClassMedia::addCertificateFilePath(const std::string& path) sendMessage(message); } +void LLPluginClassMedia::setOverrideClickTarget(const std::string &target) +{ + mClickEnforceTarget = true; + mOverrideClickTarget = target; +} + void LLPluginClassMedia::crashPlugin() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash"); @@ -1300,7 +1395,7 @@ void LLPluginClassMedia::seek(float time) LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek"); message.setValueReal("time", time); - + sendMessage(message); } @@ -1318,11 +1413,11 @@ void LLPluginClassMedia::setVolume(float volume) if(volume != mRequestedVolume) { mRequestedVolume = volume; - + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume"); message.setValueReal("volume", volume); - + sendMessage(message); } } @@ -1341,4 +1436,3 @@ void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history) LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL; } - diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 8e7a40a674..7e8c2e4eb0 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -57,6 +57,7 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr int getTextureHeight() const; int getFullWidth() const { return mFullMediaWidth; }; int getFullHeight() const { return mFullMediaHeight; }; + F64 getZoomFactor() const { return mZoomFactor; }; // This may return NULL. Callers need to check for and handle this case. unsigned char* getBitsData(); @@ -72,8 +73,9 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr void setSize(int width, int height); void setAutoScale(bool auto_scale); + void setZoomFactor(F64 zoom_factor) { mZoomFactor = zoom_factor; } - void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; }; + void setBackgroundColor(const LLColor4& color) { mBackgroundColor = color; }; void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; }; @@ -83,7 +85,7 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr // until you call idle() again. bool textureValid(void); - bool getDirty(LLRect *dirty_rect = NULL); + bool getDirty(LLRect *dirty_rect = nullptr); void resetDirty(void); typedef enum @@ -105,7 +107,7 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data); - void scrollEvent(int x, int y, MASK modifiers); + void scrollEvent(int x, int y, int clicks_x, int clicks_y, MASK modifiers); // enable/disable media plugin debugging messages and info spam void enableMediaPluginDebugging( bool enable ); @@ -122,12 +124,14 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr // Text may be unicode (utf8 encoded) bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data); + void setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure); + void loadURI(const std::string &uri); // Inherited from LLPluginProcessParentOwner - /* virtual */ void receivePluginMessage(const LLPluginMessage &message); - /* virtual */ void pluginLaunchFailed(); - /* virtual */ void pluginDied(); + /* virtual */ void receivePluginMessage(const LLPluginMessage &message) override; + /* virtual */ void pluginLaunchFailed() override; + /* virtual */ void pluginDied() override; // Inherited from LLPluginClassBasic /* virtual */ void priorityChanged(EPriority priority); @@ -135,7 +139,7 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr F64 getCPUUsage(); - void sendPickFileResponse(const std::string &file); + void sendPickFileResponse(const std::vector files); void sendAuthResponse(bool ok, const std::string &username, const std::string &password); @@ -144,6 +148,12 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; } + void undo(); + bool canUndo() const { return mCanUndo; }; + + void redo(); + bool canRedo() const { return mCanRedo; }; + void cut(); bool canCut() const { return mCanCut; }; @@ -153,8 +163,16 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr void paste(); bool canPaste() const { return mCanPaste; }; + void doDelete(); + bool canDoDelete() const { return mCanDoDelete; }; + + void selectAll(); + bool canSelectAll() const { return mCanSelectAll; }; + + void showPageSource(); + // These can be called before init(), and they will be queued and sent before the media init message. - void setUserDataPath(const std::string &user_data_path); + void setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies, const std::string &user_data_path_cef_log); void setLanguageCode(const std::string &language_code); void setPluginsEnabled(const bool enabled); void setJavascriptEnabled(const bool enabled); @@ -165,17 +183,15 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr bool pluginSupportsMediaBrowser(void); void focus(bool focused); - void set_page_zoom_factor( double factor ); + void set_page_zoom_factor( F64 factor ); void clear_cache(); void clear_cookies(); - void set_cookies(const std::string &cookies); - void enable_cookies(bool enable); - void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0); + void cookies_enabled(bool enable); + void proxy_setup(bool enable, int type = 0, const std::string &host = LLStringUtil::null, int port = 0, const std::string &user = LLStringUtil::null, const std::string &pass = LLStringUtil::null); void browse_stop(); void browse_reload(bool ignore_cache = false); void browse_forward(); void browse_back(); - void set_status_redirect(int code, const std::string &url); void setBrowserUserAgent(const std::string& user_agent); void showWebInspector( bool show ); void proxyWindowOpened(const std::string &target, const std::string &uuid); @@ -213,6 +229,13 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE std::string getClickUUID() const { return mClickUUID; }; + // mClickTarget is received from message and governs how link will be opened + // use this to enforce your own way of opening links inside plugins + void setOverrideClickTarget(const std::string &target); + void resetOverrideClickTarget() { mClickEnforceTarget = false; }; + bool isOverrideClickTarget() const { return mClickEnforceTarget; } + std::string getOverrideClickTarget() const { return mOverrideClickTarget; }; + // These are valid during MEDIA_EVENT_DEBUG_MESSAGE std::string getDebugMessageText() const { return mDebugMessageText; }; std::string getDebugMessageLevel() const { return mDebugMessageLevel; }; @@ -230,10 +253,17 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr std::string getAuthURL() const { return mAuthURL; }; std::string getAuthRealm() const { return mAuthRealm; }; + // These are valid during MEDIA_EVENT_PICK_FILE_REQUEST + bool getIsMultipleFilePick() const { return mIsMultipleFilePick; } + // These are valid during MEDIA_EVENT_LINK_HOVERED std::string getHoverText() const { return mHoverText; }; std::string getHoverLink() const { return mHoverLink; }; + // these are valid during MEDIA_EVENT_LINK_HOVERED + std::string getFileDownloadFilename() const { return mFileDownloadFilename; } + + const std::string& getMediaName() const { return mMediaName; }; std::string getMediaDescription() const { return mMediaDescription; }; @@ -320,8 +350,12 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr int mMediaWidth; int mMediaHeight; + F64 mZoomFactor; + float mRequestedVolume; + // Priority of this media stream + EPriority mPriority; int mLowPrioritySizeLimit; bool mAllowDownsample; @@ -337,9 +371,15 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr LLPluginClassMediaOwner::EMediaStatus mStatus; + F64 mSleepTime; + + bool mCanUndo; + bool mCanRedo; bool mCanCut; bool mCanCopy; bool mCanPaste; + bool mCanDoDelete; + bool mCanSelectAll; std::string mMediaName; std::string mMediaDescription; @@ -362,6 +402,8 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr std::string mClickNavType; std::string mClickTarget; std::string mClickUUID; + bool mClickEnforceTarget; + std::string mOverrideClickTarget; std::string mDebugMessageText; std::string mDebugMessageLevel; S32 mGeometryX; @@ -373,6 +415,8 @@ class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::tr std::string mAuthRealm; std::string mHoverText; std::string mHoverLink; + std::string mFileDownloadFilename; + bool mIsMultipleFilePick; ///////////////////////////////////////// // media_time class diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h index 4a739cf865..010f54c8fd 100644 --- a/indra/llplugin/llpluginclassmediaowner.h +++ b/indra/llplugin/llpluginclassmediaowner.h @@ -3,33 +3,26 @@ * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class. * * @cond - * $LicenseInfo:firstyear=2008&license=viewergpl$ - * - * Copyright (c) 2008-2010, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlife.com/developers/opensource/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ + * 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$ * @endcond */ @@ -41,7 +34,6 @@ #include class LLPluginClassMedia; -class LLPluginCookieStore; class LLPluginClassMediaOwner { @@ -71,6 +63,8 @@ class LLPluginClassMediaOwner MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog + MEDIA_EVENT_FILE_DOWNLOAD, // the plugin wants to download a file + MEDIA_EVENT_DEBUG_MESSAGE, // plugin sending back debug information for host to process MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin @@ -91,7 +85,6 @@ class LLPluginClassMediaOwner virtual ~LLPluginClassMediaOwner() {}; virtual void handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent /*event*/) {}; - virtual void handleCookieSet(LLPluginClassMedia* /*self*/, const std::string &/*cookie*/) {}; }; #endif // LL_LLPLUGINCLASSMEDIAOWNER_H diff --git a/indra/llplugin/slplugin/CMakeLists.txt b/indra/llplugin/slplugin/CMakeLists.txt index 381782ed6d..f8ab569162 100644 --- a/indra/llplugin/slplugin/CMakeLists.txt +++ b/indra/llplugin/slplugin/CMakeLists.txt @@ -6,6 +6,7 @@ include(LLPlugin) include(Linking) include(PluginAPI) include(LLMessage) +include(WinManifest) include_directories( ${LLPLUGIN_INCLUDE_DIRS} @@ -56,8 +57,9 @@ set_target_properties(SLPlugin if (WINDOWS) set_target_properties(SLPlugin PROPERTIES - LINK_FLAGS "/OPT:NOREF" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMTD\"" ) + EMBED_MANIFEST(SLPlugin 1) endif() target_link_libraries(SLPlugin @@ -66,12 +68,7 @@ target_link_libraries(SLPlugin ${LLCOMMON_LIBRARIES} ${APRUTIL_LIBRARIES} ${PLUGIN_API_WINDOWS_LIBRARIES} -) - -add_dependencies(SLPlugin - ${LLPLUGIN_LIBRARIES} - ${LLMESSAGE_LIBRARIES} - ${LLCOMMON_LIBRARIES} + ${PTHREAD_LIBRARY} ) if (DARWIN) diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index e9478bb067..33f51a6f0c 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -9,22 +9,30 @@ include(LLMessage) include(LLXML) include(LLPhysicsExtensions) include(Colladadom) +include(LLCharacter) include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} ${COLLADADOM_INCLUDE_DIRS} + ${LLCHARACTER_INCLUDE_DIRS} + ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} ) set(llprimitive_SOURCE_FILES + lldaeloader.cpp llmaterialid.cpp llmaterial.cpp llmaterialtable.cpp llmediaentry.cpp llmodel.cpp + llmodelloader.cpp llprimitive.cpp llprimtexturelist.cpp lltextureanim.cpp @@ -37,13 +45,14 @@ set(llprimitive_SOURCE_FILES set(llprimitive_HEADER_FILES CMakeLists.txt - + lldaeloader.h legacy_object_types.h llmaterial.h llmaterialid.h llmaterialtable.h llmediaentry.h llmodel.h + llmodelloader.h llprimitive.h llprimtexturelist.h lltextureanim.h @@ -62,4 +71,9 @@ set_source_files_properties(${llprimitive_HEADER_FILES} list(APPEND llprimitive_SOURCE_FILES ${llprimitive_HEADER_FILES}) add_library (llprimitive ${llprimitive_SOURCE_FILES}) -add_dependencies(llprimitive prepare) + +target_link_libraries( + llprimitive + PUBLIC + llcommon + ) diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp new file mode 100644 index 0000000000..a6a97cc1e6 --- /dev/null +++ b/indra/llprimitive/lldaeloader.cpp @@ -0,0 +1,2544 @@ +/** + * @file lldaeloader.cpp + * @brief LLDAELoader class implementation + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "lldaeloader.h" +#include "llsdserialize.h" +#include "lljoint.h" + +#include "llmatrix4a.h" + +std::string colladaVersion[VERSIONTYPE_COUNT + 1] = +{ + "1.4.0", + "1.4.1", + "Unsupported" +}; + +static const std::string lod_suffix[LLModel::NUM_LODS] = +{ + "_LOD0", + "_LOD1", + "_LOD2", + "", + "_PHYS", +}; + +const U32 LIMIT_MATERIALS_OUTPUT = 12; +bool get_dom_sources(const domInputLocalOffset_Array& inputs, U32& pos_offset, U32& tc_offset, U32& norm_offset, U32& idx_stride, + domSource*& pos_source, domSource*& tc_source, domSource*& norm_source) +{ + idx_stride = 0; + for (size_t j = 0; j < inputs.getCount(); ++j) + { + const auto& input = inputs[j]; + const auto input_semantic = input->getSemantic(); + // Offset value sanitization / fault tolerance + idx_stride = (U32)llmax((S32)input->getOffset(), (S32)idx_stride); + if (strcmp(COMMON_PROFILE_INPUT_VERTEX, input_semantic) == 0) + { + //found vertex array + const auto& uri = input->getSource(); + const auto elem = uri.getElement(); + const auto vertices = (domVertices*)elem.cast(); + if (!vertices) + { + return false; + } + + const auto& v_inp = vertices->getInput_array(); + for (size_t k = 0; k < v_inp.getCount(); ++k) + { + const auto& v_inp_k = v_inp[k]; + const auto v_inp_semantic = v_inp_k->getSemantic(); + if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp_semantic) == 0) + { + pos_offset = input->getOffset(); + const auto& uri = v_inp_k->getSource(); + const auto elem = uri.getElement(); + pos_source = (domSource*)elem.cast(); + } + + if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp_semantic) == 0) + { + norm_offset = input->getOffset(); + const auto& uri = v_inp_k->getSource(); + const auto elem = uri.getElement(); + norm_source = (domSource*)elem.cast(); + } + } + } + + + if (strcmp(COMMON_PROFILE_INPUT_NORMAL, input_semantic) == 0) + { + //found normal array for this triangle list + norm_offset = input->getOffset(); + const auto& uri = input->getSource(); + const auto elem = uri.getElement(); + norm_source = (domSource*)elem.cast(); + } + else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, input_semantic) == 0) + { + //found texCoords + tc_offset = input->getOffset(); + const auto& uri = input->getSource(); + const auto elem = uri.getElement(); + tc_source = (domSource*)elem.cast(); + } + } + + idx_stride += 1; + + return true; +} + +LLModel::EModelStatus load_face_from_dom_triangles(std::vector& face_list, std::vector& materials, domTrianglesRef& tri) +{ + LLVolumeFace face; + std::vector verts; + std::vector indices; + + const auto& inputs = tri->getInput_array(); + + U32 pos_offset, tc_offset, norm_offset, idx_stride; + domSource* pos_source = NULL, * tc_source = NULL, * norm_source = NULL; + + if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source) + { + LL_WARNS() << "Could not find dom sources for basic geo data; invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + if (!pos_source || !pos_source->getFloat_array()) + { + LL_WARNS() << "Unable to process mesh without position data; invalid model; invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + const auto p = tri->getP(); + const auto& idx = p->getValue(); + + domListOfFloats dummy; + const auto& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy; + const auto& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy; + const auto& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy; + + const auto index_count = idx.getCount(); + const auto vertex_count = pos_source ? v.getCount() : 0; + const auto tc_count = tc_source ? tc.getCount() : 0; + const auto norm_count = norm_source ? n.getCount() : 0; + + if (pos_source) + { + if (vertex_count == 0) + { + LL_WARNS() << "Unable to process mesh with empty position array; invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + face.mExtents[0].set(v[0], v[1], v[2]); + face.mExtents[1].set(v[0], v[1], v[2]); + + LLVolumeFace::VertexMapData::PointMap point_map; + + for (size_t i = 0; i < index_count; i += idx_stride) + { + LLVolumeFace::VertexData cv; + if (pos_source) + { + // guard against model data specifiying out of range indices or verts + // + const auto p_pos_index = idx[i + pos_offset] * 3; + if (((i + pos_offset) > index_count) + || ((p_pos_index + 2) > vertex_count)) + { + LL_WARNS() << "Out of range index data; invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + const auto cv_position = LLVector4a( + v[p_pos_index], + v[p_pos_index + 1], + v[p_pos_index + 2]); + cv.setPosition(cv_position); + + if (!cv_position.isFinite3()) + { + LL_WARNS() << "Nan positional data, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + if (tc_source) + { + // guard against model data specifiying out of range indices or tcs + // + const auto p_tc_index = idx[i + tc_offset] * 2; + if (((i + tc_offset) > index_count) + || ((p_tc_index + 1) > tc_count)) + { + LL_WARNS() << "Out of range TC indices." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + cv.mTexCoord = LLVector2( + tc[p_tc_index], + tc[p_tc_index + 1]); + + if (!cv.mTexCoord.isFinite()) + { + LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + if (norm_source) + { + // guard against model data specifiying out of range indices or norms + // + const auto p_norm_index = idx[i + norm_offset] * 3; + if (((i + norm_offset) > index_count) + || ((p_norm_index + 2) > norm_count)) + { + LL_WARNS() << "Found out of range norm indices, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + const auto cv_normal = LLVector4a( + n[p_norm_index], + n[p_norm_index + 1], + n[p_norm_index + 2]); + cv.setNormal(cv_normal); + + if (!cv_normal.isFinite3()) + { + LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + BOOL found = FALSE; + + const auto pos3 = LLVector3(cv.getPosition().getF32ptr()); + const auto point_iter = point_map.find(pos3); + + if (point_iter != point_map.end()) + { + const auto& vm_data = point_iter->second; + for (const auto& vm : vm_data) + { + // We have a matching loc + // + if (vm == cv) + { + // Don't share verts within the same tri, degenerate + // + const auto index_size = indices.size(); + const auto verts_new_tri = index_size % 3; + if ((verts_new_tri < 1 || indices[index_size - 1] != vm.mIndex) + && (verts_new_tri < 2 || indices[index_size - 2] != vm.mIndex)) + { + found = true; + indices.push_back(vm.mIndex); + } + break; + } + } + } + + if (!found) + { + update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); + verts.push_back(cv); + if (verts.size() >= 0xFFFFU) + { + //LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; + return LLModel::VERTEX_NUMBER_OVERFLOW; + } + const auto index = (U16)(verts.size() - 1); + indices.push_back(index); + + LLVolumeFace::VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + const auto point = LLVector3(d.getPosition().getF32ptr()); + point_map[point].push_back(d); + } + } + + if (indices.size() % 3 == 0 && verts.size() >= 0xFFFCU) + { + std::string material; + + if (tri->getMaterial()) + { + material = std::string(tri->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + auto& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + face = LLVolumeFace(); + point_map.clear(); + } + } + + if (!verts.empty()) + { + std::string material; + + if (tri->getMaterial()) + { + material = std::string(tri->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + + face_list.rbegin()->fillFromLegacyData(verts, indices); + auto& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS; +} + +LLModel::EModelStatus load_face_from_dom_polylist(std::vector& face_list, std::vector& materials, domPolylistRef& poly) +{ + const auto p = poly->getP(); + const auto& idx = p->getValue(); + + const auto index_count = idx.getCount(); + if (index_count == 0) + { + return LLModel::NO_ERRORS; + } + + const auto& inputs = poly->getInput_array(); + const auto& vcount = poly->getVcount()->getValue(); + + auto pos_offset = 0U, tc_offset = 0U, norm_offset = 0U, idx_stride = 0U; + domSource* pos_source = NULL, * tc_source = NULL, * norm_source = NULL; + + if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source)) + { + LL_WARNS() << "Could not get DOM sources for basic geo data, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + LLVolumeFace face; + + std::vector indices; + std::vector verts; + + domListOfFloats v, tc, n; + + if (pos_source) + { + v = pos_source->getFloat_array()->getValue(); + face.mExtents[0].set(v[0], v[1], v[2]); + face.mExtents[1].set(v[0], v[1], v[2]); + } + + if (tc_source) + { + tc = tc_source->getFloat_array()->getValue(); + } + + if (norm_source) + { + n = norm_source->getFloat_array()->getValue(); + } + + LLVolumeFace::VertexMapData::PointMap point_map; + + const auto vertex_count = pos_source ? v.getCount() : 0; + const auto tc_count = tc_source ? tc.getCount() : 0; + const auto norm_count = norm_source ? n.getCount() : 0; + + size_t cur_idx = 0; + for (size_t i = 0; i < vcount.getCount(); ++i) + { + //for each polygon + auto first_index = (U16)0; + auto last_index = (U16)0; + for (size_t j = 0; j < vcount[i]; ++j) + { + //for each vertex + LLVolumeFace::VertexData cv; + + if (pos_source) + { + // guard against model data specifiying out of range indices or verts + // + const auto cur_idx_offset = cur_idx + pos_offset; + const auto p_pos_index = (size_t)idx[cur_idx_offset] * 3; + if ((cur_idx_offset > index_count) || ((p_pos_index + 2) > vertex_count)) + { + LL_WARNS() << "Out of range position indices, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + const auto cv_position = LLVector4a( + v[p_pos_index], + v[p_pos_index + 1], + v[p_pos_index + 2]); + cv.setPosition(cv_position); + + if (!cv_position.isFinite3()) + { + LL_WARNS() << "Found NaN while loading position data from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + } + + if (tc_source) + { + // guard against model data specifiying out of range indices or tcs + // + const auto cur_idx_offset = cur_idx + tc_offset; + const auto p_tc_index = (size_t)idx[cur_idx_offset] * 2; + if ((cur_idx_offset > index_count) || ((p_tc_index + 1) > tc_count)) + { + LL_WARNS() << "Out of range TC indices, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + cv.mTexCoord = LLVector2( + tc[p_tc_index], + tc[p_tc_index + 1]); + + if (!cv.mTexCoord.isFinite()) + { + LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + if (norm_source) + { + // guard against model data specifiying out of range indices or norms + // + const auto cur_idx_offset = cur_idx + norm_offset; + const auto p_norm_index = (size_t)idx[cur_idx_offset] * 3; + if ((cur_idx_offset > index_count) || ((p_norm_index + 2) > norm_count)) + { + LL_WARNS() << "Out of range norm indices, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + const auto cv_normal = LLVector4a( + n[p_norm_index], + n[p_norm_index + 1], + n[p_norm_index + 2]); + cv.setNormal(cv_normal); + + if (!cv_normal.isFinite3()) + { + LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + cur_idx += idx_stride; + + BOOL found = FALSE; + + LLVector3 pos3(cv.getPosition().getF32ptr()); + const auto point_iter = point_map.find(pos3); + if (point_iter != point_map.end()) + { + const auto& vm_data = point_iter->second; + for (const auto& vm : vm_data) + { + // If vertex data matches current vertex + if (vm == cv) + { + found = TRUE; + const auto index = vm.mIndex; + if (j == 0) + { + first_index = index; + } + else if (j == 1) + { + last_index = index; + } + else + { + // if these are the same, we have a very, very skinny triangle (coincident verts on one or more edges) + // + llassert((first_index != last_index) && (last_index != index) && (first_index != index)); + indices.push_back(first_index); + indices.push_back(last_index); + indices.push_back(index); + last_index = index; + } + + break; + } + } + } + + if (!found) + { + update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); + verts.push_back(cv); + if (verts.size() >= 0xFFFFU) + { + //LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; + return LLModel::VERTEX_NUMBER_OVERFLOW; + } + const auto index = (U16)(verts.size() - 1); + + if (j == 0) + { + first_index = index; + } + else if (j == 1) + { + last_index = index; + } + else + { + // detect very skinny degenerate triangles with collapsed edges + // + llassert((first_index != last_index) && (last_index != index) && (first_index != index)); + indices.push_back(first_index); + indices.push_back(last_index); + indices.push_back(index); + last_index = index; + } + + LLVolumeFace::VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[pos3].push_back(d); + } + } + + if (indices.size() % 3 == 0 && indices.size() >= 0xFFFCU) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + + auto& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + face = LLVolumeFace(); + verts.clear(); + indices.clear(); + point_map.clear(); + } + } + } + + if (!verts.empty()) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + + auto& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS; +} + +LLModel::EModelStatus load_face_from_dom_polygons(std::vector& face_list, std::vector& materials, domPolygonsRef& poly) +{ + LLVolumeFace face; + std::vector indices; + std::vector verts; + + const auto& inputs = poly->getInput_array(); + + auto v_offset = 0U, n_offset = 0U, t_offset = 0U, stride = 0U; + domListOfFloats* v = NULL, * n = NULL, * t = NULL; + + for (size_t i = 0; i < inputs.getCount(); ++i) + { + const auto& input = inputs[i]; + const auto input_semantic = input->getSemantic(); + // Offset value sanitization / fault tolerance + stride = (U32)llmax((S32)input->getOffset() + 1, (S32)stride); + if (strcmp(COMMON_PROFILE_INPUT_VERTEX, input_semantic) == 0) + { + //found vertex array + v_offset = input->getOffset(); + + const auto& uri = input->getSource(); + const auto elem = uri.getElement(); + const auto vertices = (domVertices*)elem.cast(); + if (!vertices) + { + LL_WARNS() << "Could not find vertex source, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + const auto& v_inp = vertices->getInput_array(); + for (size_t k = 0; k < v_inp.getCount(); ++k) + { + auto& v_inp_k = v_inp[k]; + if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp_k->getSemantic()) == 0) + { + const auto& uri = v_inp_k->getSource(); + const auto elem = uri.getElement(); + const auto src = (domSource*)elem.cast(); + if (!src) + { + LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + v = &(src->getFloat_array()->getValue()); + } + } + } + else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, input_semantic) == 0) + { + //found normal array for this triangle list + n_offset = input->getOffset(); + const auto& uri = input->getSource(); + const auto elem = uri.getElement(); + const auto src = (domSource*)elem.cast(); + if (!src) + { + LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + n = &(src->getFloat_array()->getValue()); + } + else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, input_semantic) == 0 && input->getSet() == 0) + { + //found texCoords + t_offset = input->getOffset(); + const auto& uri = input->getSource(); + const auto elem = uri.getElement(); + const auto src = (domSource*)elem.cast(); + if (!src) + { + LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + t = &(src->getFloat_array()->getValue()); + } + } + + const auto& ps = poly->getP_array(); + + //make a triangle list in + for (size_t i = 0; i < ps.getCount(); ++i) + { + //for each polygon + const auto& idx = ps[i]->getValue(); + const auto idx_count_by_stride = idx.getCount() / stride; + for (size_t j = 0; j < idx_count_by_stride; ++j) + { + //for each vertex + if (j > 2) + { + const auto& v0 = verts[(U32)verts.size() - 3]; + const auto& v1 = verts[(U32)verts.size() - 1]; + + verts.push_back(v0); + verts.push_back(v1); + } + + LLVolumeFace::VertexData vert; + + if (v) + { + auto v_idx = (size_t)idx[j * stride + v_offset] * 3; + v_idx = llclamp(v_idx, size_t(0), v->getCount()); + const auto v_pos = LLVector4a( + v->get(v_idx), + v->get(v_idx + 1), + v->get(v_idx + 2)); + vert.setPosition(v_pos); + if (!v_pos.isFinite3()) + { + LL_WARNS() << "Found NaN while loading position data from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + //bounds check n and t lookups because some FBX to DAE converters + //use negative indices and empty arrays to indicate data does not exist + //for a particular channel + if (n && n->getCount() > 0) + { + auto n_idx = (size_t)idx[j * stride + n_offset] * 3; + n_idx = llclamp(n_idx, size_t(0), n->getCount()); + const auto v_norm = LLVector4a( + n->get(n_idx), + n->get(n_idx + 1), + n->get(n_idx + 2)); + vert.setNormal(v_norm); + if (!v_norm.isFinite3()) + { + LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + else + { + vert.getNormal().clear(); + } + + if (t && t->getCount() > 0) + { + auto t_idx = (size_t)idx[j * stride + t_offset] * 2; + t_idx = llclamp(t_idx, size_t(0), t->getCount()); + vert.mTexCoord = LLVector2( + t->get(t_idx), + t->get(t_idx + 1)); + if (!vert.mTexCoord.isFinite()) + { + LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + else + { + vert.mTexCoord.clear(); + } + + verts.push_back(vert); + } + } + + if (verts.empty()) + { + return LLModel::NO_ERRORS; + } + + face.mExtents[0] = verts[0].getPosition(); + face.mExtents[1] = verts[0].getPosition(); + + //create a map of unique vertices to indices + std::map vert_idx; + + auto cur_idx = 0U; + for (size_t i = 0; i < verts.size(); ++i) + { + auto iter = vert_idx.find(verts[i]); + if (iter == vert_idx.end()) + { + vert_idx[verts[i]] = cur_idx++; + } + } + + //build vertex array from map + std::vector new_verts; + new_verts.resize(vert_idx.size()); + + for (const auto& iter : vert_idx) + { + new_verts[iter.second] = iter.first; + update_min_max(face.mExtents[0], face.mExtents[1], iter.first.getPosition()); + } + + //build index array from map + indices.resize(verts.size()); + + for (size_t i = 0; i < verts.size(); ++i) + { + indices[i] = vert_idx[verts[i]]; + llassert(!i || (indices[i - 1] != indices[i])); + } + + // DEBUG just build an expanded triangle list + /*for (U32 i = 0; i < verts.size(); ++i) + { + indices.push_back((U16) i); + update_min_max(face.mExtents[0], face.mExtents[1], verts[i].getPosition()); + }*/ + + if (!new_verts.empty()) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(new_verts, indices); + + auto& new_face = *face_list.rbegin(); + if (!n) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!t) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS; +} + +//----------------------------------------------------------------------------- +// LLDAELoader +//----------------------------------------------------------------------------- +LLDAELoader::LLDAELoader( + std::string filename, + S32 lod, + load_callback_t load_cb, + joint_lookup_func_t joint_lookup_func, + texture_load_func_t texture_load_func, + state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointTransformMap, + JointNameSet& jointsFromNodes, + std::map& jointAliasMap, + U32 maxJointsPerMesh, + U32 modelLimit, + bool preprocess) + : LLModelLoader( + filename, + lod, + load_cb, + joint_lookup_func, + texture_load_func, + state_cb, + opaque_userdata, + jointTransformMap, + jointsFromNodes, + jointAliasMap, + maxJointsPerMesh), + mGeneratedModelLimit(modelLimit), + mPreprocessDAE(preprocess) +{ +} + +LLDAELoader::~LLDAELoader() +{ +} + +struct ModelSort +{ + bool operator()(const LLPointer< LLModel >& lhs, const LLPointer< LLModel >& rhs) + { + if (lhs->mSubmodelID < rhs->mSubmodelID) + { + return true; + } + return LLStringUtil::compareInsensitive(lhs->mLabel, rhs->mLabel) < 0; + } +}; + +bool LLDAELoader::OpenFile(const std::string& filename) +{ + //no suitable slm exists, load from the .dae file + DAE dae; + domCOLLADA* dom; + if (mPreprocessDAE) + { + dom = dae.openFromMemory(filename, preprocessDAE(filename).c_str()); + } + else + { + LL_INFOS() << "Skipping dae preprocessing" << LL_ENDL; + dom = dae.open(filename); + } + + if (!dom) + { + LL_INFOS() << " Error with dae - traditionally indicates a corrupt file." << LL_ENDL; + setLoadState(ERROR_PARSING); + return false; + } + + //Dom version + const auto domVersion = dae.getDomVersion(); + std::string sldom(domVersion); + LL_INFOS() << "Collada Importer Version: " << sldom << LL_ENDL; + + //Dae version + auto docVersion = dom->getVersion(); + //0=1.4 + //1=1.4.1 + //2=Currently unsupported, however may work + if (docVersion > 1) + { + docVersion = VERSIONTYPE_COUNT; + } + LL_INFOS() << "Dae version " << colladaVersion[docVersion] << LL_ENDL; + + const auto db = dae.getDatabase(); + + const auto doc = dae.getDoc(filename); + if (!doc) + { + LL_WARNS() << "can't find internal doc" << LL_ENDL; + return false; + } + + const auto root = doc->getDomRoot(); + if (!root) + { + LL_WARNS() << "document has no root" << LL_ENDL; + return false; + } + + //Verify some basic properties of the dae + //1. Basic validity check on controller + const auto controllerCount = db->getElementCount(NULL, "controller"); + bool result = false; + for (size_t i = 0; i < controllerCount; ++i) + { + domController* pController = NULL; + db->getElement((daeElement**)&pController, i, NULL, "controller"); + result = verifyController(pController); + if (!result) + { + LL_INFOS() << "Could not verify controller" << LL_ENDL; + setLoadState(ERROR_PARSING); + return true; + } + } + + //get unit scale + mTransform.setIdentity(); + + auto unit = daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID()))); + + if (unit) + { + auto meter = (F32)unit->getMeter(); + mTransform.mMatrix[0][0] = meter; + mTransform.mMatrix[1][1] = meter; + mTransform.mMatrix[2][2] = meter; + } + + //get up axis rotation + LLMatrix4 rotation; + + auto up = UPAXISTYPE_Y_UP; // default is Y_UP + const auto up_axis = daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID()))); + + if (up_axis) + { + up = up_axis->getValue(); + } + + if (up == UPAXISTYPE_X_UP) + { + rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f); + } + else if (up == UPAXISTYPE_Y_UP) + { + rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f); + } + + rotation *= mTransform; + mTransform = rotation; + + mTransform.condition(); + + const auto mesh_count = db->getElementCount(NULL, COLLADA_TYPE_MESH); + const auto submodel_limit = mesh_count > 0 ? mGeneratedModelLimit / mesh_count : 0; + for (size_t idx = 0; idx < mesh_count; ++idx) + { + //build map of domEntities to LLModel + domMesh* mesh = NULL; + db->getElement((daeElement**)&mesh, idx, NULL, COLLADA_TYPE_MESH); + + if (mesh) + { + std::vector models; + loadModelsFromDomMesh(mesh, models, submodel_limit); + for (const auto& mdl : models) + { + if (mdl->getStatus() != LLModel::NO_ERRORS) + { + setLoadState(ERROR_MODEL + mdl->getStatus()); + return false; //abort + } + + if (mdl && validate_model(mdl)) + { + mModelList.push_back(mdl); + mModelsMap[mesh].push_back(mdl); + } + } + } + } + + std::sort(mModelList.begin(), mModelList.end(), ModelSort()); + + for (const auto mdl : mModelList) + { + const auto material_count = mdl->mMaterialList.size(); + LL_INFOS() << "Importing " << mdl->mLabel << " model with " << material_count << " material references" << LL_ENDL; + + auto mat_iter = mdl->mMaterialList.begin(); + const auto end_iter = material_count > LIMIT_MATERIALS_OUTPUT + ? mat_iter + LIMIT_MATERIALS_OUTPUT + : mdl->mMaterialList.end(); + for (; mat_iter != end_iter; ++mat_iter) + { + LL_INFOS() << mdl->mLabel << " references " << (*mat_iter) << LL_ENDL; + } + } + + const auto skin_count = db->getElementCount(NULL, COLLADA_TYPE_SKIN); + LL_INFOS() << "Collada skins to be processed: " << skin_count << LL_ENDL; + + const auto scene = root->getDescendant("visual_scene"); + + if (!scene) + { + LL_WARNS() << "document has no visual_scene" << LL_ENDL; + setLoadState(ERROR_PARSING); + return true; + } + + setLoadState(DONE); + + bool badElement = false; + + processElement(scene, badElement, &dae, root); + + if (badElement) + { + LL_INFOS() << "Scene could not be parsed" << LL_ENDL; + setLoadState(ERROR_PARSING); + } + + return true; +} + +std::string LLDAELoader::preprocessDAE(const std::string filename) +{ + // Open a DAE file for some preprocessing (like removing space characters in IDs), see MAINT-5678 + std::ifstream inFile; + inFile.open(filename.c_str(), std::ios_base::in); + std::stringstream strStream; + strStream << inFile.rdbuf(); + std::string buffer = strStream.str(); + + LL_INFOS() << "Preprocessing dae file to remove spaces from the names, ids, etc." << LL_ENDL; + + try + { + boost::regex re("\"[\\w\\.@#$-]*(\\s[\\w\\.@#$-]*)+\""); + boost::sregex_iterator next(buffer.begin(), buffer.end(), re); + boost::sregex_iterator end; + while (next != end) + { + const auto match = *next; + auto s = match.str(); + LL_INFOS() << s << " found" << LL_ENDL; + boost::replace_all(s, " ", "_"); + LL_INFOS() << "Replacing with " << s << LL_ENDL; + boost::replace_all(buffer, match.str(), s); + ++next; + } + } + catch (boost::regex_error&) + { + LL_INFOS() << "Regex error" << LL_ENDL; + } + + return buffer; +} + +void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, domMesh* mesh, domSkin* skin) +{ + llassert(model && dae && mesh && skin); + + if (model) + { + LLVector3 mesh_scale_vector; + LLVector3 mesh_translation_vector; + model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); + + LLMatrix4 normalized_transformation; + normalized_transformation.setTranslation(mesh_translation_vector); + + LLMatrix4 mesh_scale; + mesh_scale.initScale(mesh_scale_vector); + mesh_scale *= normalized_transformation; + normalized_transformation = mesh_scale; + + LLMatrix4a inv_mat; + inv_mat.loadu(normalized_transformation); + inv_mat.invert(); + + LLMatrix4 inverse_normalized_transformation(inv_mat.getF32ptr()); + + const auto bind_mat = skin->getBind_shape_matrix(); + + if (bind_mat) + { + //get bind shape matrix + const auto& dom_value = bind_mat->getValue(); + + auto& skin_info = model->mSkinInfo; + + for (size_t i = 0; i < 4; ++i) + { + for (size_t j = 0; j < 4; ++j) + { + skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j * 4]; + } + } + + auto trans = normalized_transformation; + trans *= skin_info.mBindShapeMatrix; + trans *= mBindTransform; + + skin_info.mBindShapeMatrix = trans; + } + + // Build the joint to node mapping array and update joint aliases (mJointMap) + buildJointToNodeMappingFromScene(root); + + //Some collada setup for accessing the skeleton + const auto skeleton_count = dae->getDatabase()->getElementCount(NULL, "skeleton"); + std::vector skeletons; + for (size_t i = 0; i < skeleton_count; ++i) + { + daeElement* pElement = NULL; + dae->getDatabase()->getElement(&pElement, i, 0, "skeleton"); + + //Try to get at the skeletal instance controller + const auto pSkeleton = daeSafeCast(pElement); + daeElement* pSkeletonRootNode = NULL; + if (pSkeleton) + { + pSkeletonRootNode = pSkeleton->getValue().getElement(); + } + if (pSkeleton && pSkeletonRootNode) + { + skeletons.push_back(pSkeleton); + } + } + bool missingSkeletonOrScene = false; + + //If no skeleton, do a breadth-first search to get at specific joints + if (skeletons.size() == 0) + { + const auto pScene = root->getDescendant("visual_scene"); + if (!pScene) + { + LL_WARNS() << "No visual scene - unable to parse bone offsets " << LL_ENDL; + missingSkeletonOrScene = true; + } + else + { + //Get the children at this level + const auto children = pScene->getChildren(); + + //Process any children that are joints + //Not all children are joints, some code be ambient lights, cameras, geometry etc.. + for (size_t i = 0; i < children.getCount(); ++i) + { + const auto pNode = daeSafeCast(children[i]); + if (isNodeAJoint(pNode)) + { + processJointNode(pNode, mJointList); + } + } + } + } + else + { + //Has one or more skeletons + for (const auto& pSkeleton : skeletons) + { + //Get the root node of the skeleton + if (const auto pSkeletonRootNode = pSkeleton->getValue().getElement()) + { + //Once we have the root node - start acccessing it's joint components + //Loop over all the possible joints within the .dae - using the allowed joint list in the ctor. + for (const auto& jointPair : mJointMap) + { + //Build a joint for the resolver to work with and set up the resolver + char str[64] = { 0 }; + snprintf(str, 64, "./%s", jointPair.first.c_str()); + daeSIDResolver resolver(pSkeletonRootNode, str); + + //Look for the joint + if (const auto pJoint = daeSafeCast(resolver.getElement())) + { + // FIXME this has a lot of overlap with processJointNode(), would be nice to refactor. + + //Pull out the translate id and store it in the jointTranslations map + daeSIDResolver jointResolverA(pJoint, "./translate"); + daeSIDResolver jointResolverB(pJoint, "./location"); + LLMatrix4 workingTransform; + + + if (const auto pTranslateA = daeSafeCast(jointResolverA.getElement())) + { + extractTranslation(pTranslateA, workingTransform); + } + else if (const auto pTranslateB = daeSafeCast(jointResolverB.getElement())) + { + extractTranslation(pTranslateB, workingTransform); + } + else if (const auto pTranslateElement = getChildFromElement(pJoint, "translate")) + { + if (const auto pTranslateC = daeSafeCast(pTranslateElement)) + { + //Translation via child from element + extractTranslation(pTranslateC, workingTransform); + } + else + { + LL_WARNS() << "The found element is not a translate node" << LL_ENDL; + missingSkeletonOrScene = true; + } + } + else + { + //Translation via SID + extractTranslationViaSID(pJoint, workingTransform); + } + + //Store the joint transform w/respect to it's name. + mJointList[jointPair.second.c_str()] = workingTransform; + } + } + + //If anything failed in regards to extracting the skeleton, joints or translation id, + //mention it + if (missingSkeletonOrScene) + { + LL_WARNS() << "Partial jointmap found in asset - did you mean to just have a partial map?" << LL_ENDL; + } + } //got skeleton? + } + } + + const auto joints = skin->getJoints(); + + const auto& joint_input = joints->getInput_array(); + for (size_t i = 0; i < joint_input.getCount(); ++i) + { + const auto input = joint_input.get(i); + const auto semantic = input->getSemantic(); + if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0) + { + //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames + const auto elem = input->getSource().getElement(); + if (const auto source = daeSafeCast(elem)) + { + // TODO: DRY this code + if (auto names_source = source->getName_array()) + { + const auto& names = names_source->getValue(); + for (size_t j = 0; j < names.getCount(); ++j) + { + std::string name(names.get(j)); + const auto& joint_found = mJointMap.find(name); + if (joint_found != mJointMap.end()) + { + name = joint_found->second; + } + model->mSkinInfo.mJointNames.push_back(name); + model->mSkinInfo.mJointNums.push_back(-1); + } + } + else if (auto names_source = source->getIDREF_array()) + { + const auto& names = names_source->getValue(); + for (size_t j = 0; j < names.getCount(); ++j) + { + std::string name(names.get(j).getID()); + const auto& joint_found = mJointMap.find(name); + if (joint_found != mJointMap.end()) + { + name = joint_found->second; + } + model->mSkinInfo.mJointNames.push_back(name); + model->mSkinInfo.mJointNums.push_back(-1); + } + } + } + } + else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0) + { + //found inv_bind_matrix array, fill model->mInvBindMatrix + if (const auto source = daeSafeCast(input->getSource().getElement())) + { + if (const auto t = source->getFloat_array()) + { + const auto& transform = t->getValue(); + const auto n_transforms = transform.getCount() / 16; + + for (size_t k = 0; k < n_transforms; ++k) + { + LLMatrix4 mat; + for (size_t i = 0; i < 4; ++i) + { + for (size_t j = 0; j < 4; ++j) + { + mat.mMatrix[i][j] = transform[k * 16 + i + j * 4]; + } + } + model->mSkinInfo.mInvBindMatrix.push_back(mat); + } + } + } + } + } + + //Now that we've parsed the joint array, let's determine if we have a full rig + //(which means we have all the joint sthat are required for an avatar versus + //a skinned asset attached to a node in a file that contains an entire skeleton, + //but does not use the skeleton). + critiqueRigForUploadApplicability(model->mSkinInfo.mJointNames); + + if (!missingSkeletonOrScene) + { + // FIXME: mesh_id is used to determine which mesh gets to + // set the joint offset, in the event of a conflict. Since + // we don't know the mesh id yet, we can't guarantee that + // joint offsets will be applied with the same priority as + // in the uploaded model. If the file contains multiple + // meshes with conflicting joint offsets, preview may be + // incorrect. + LLUUID fake_mesh_id; + fake_mesh_id.generate(); + + //The joints are reset in the dtor + //if ( getRigWithSceneParity() ) + { + for (const auto& masterJointPair : mJointMap) + { + const auto lookingForJoint = masterJointPair.first; + const auto& joint_found = mJointList.find(lookingForJoint); + if (joint_found != mJointList.end()) + { + //LL_INFOS()<<"joint "<second; + const auto& joint_pos = jointTransform.getTranslation(); + if (pJoint->aboveJointPosThreshold(joint_pos)) + { + bool override_changed; // not used + pJoint->addAttachmentPosOverride(joint_pos, fake_mesh_id, "", override_changed); + if (model->mSkinInfo.mLockScaleIfJointPosition) + { + pJoint->addAttachmentScaleOverride(pJoint->getDefaultScale(), fake_mesh_id, ""); + } + } + } + else + { + //Most likely an error in the asset. + LL_WARNS() << "Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL; + } + } + } + } + } //missingSkeletonOrScene + + //We need to construct the alternate bind matrix (which contains the new joint positions) + //in the same order as they were stored in the joint buffer. The joints associated + //with the skeleton are not stored in the same order as they are in the exported joint buffer. + //This remaps the skeletal joints to be in the same order as the joints stored in the model. + + for (auto const& joint : model->mSkinInfo.mJointNames | boost::adaptors::indexed(0)) + { + std::string lookingForJoint = joint.value().c_str(); + //Look for the joint xform that we extracted from the skeleton, using the jointIt as the key + //and store it in the alternate bind matrix + if (mJointMap.find(lookingForJoint) != mJointMap.end()) + { + auto newInverse = model->mSkinInfo.mInvBindMatrix[joint.index()]; + newInverse.setTranslation(mJointList[lookingForJoint].getTranslation()); + model->mSkinInfo.mAlternateBindMatrix.push_back(newInverse); + } + else + { + LL_DEBUGS("Mesh") << "Possibly misnamed/missing joint [" << lookingForJoint.c_str() << "] " << LL_ENDL; + } + } + + //get raw position array + if (auto verts = mesh->getVertices()) + { + const auto& inputs = verts->getInput_array(); + const auto inputs_count = inputs.getCount(); + for (size_t i = 0; i < inputs_count && model->mPosition.empty(); ++i) + { + if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0) + { + if (const auto* pos_source = daeSafeCast(inputs[i]->getSource().getElement())) + { + if (const auto pos_array = pos_source->getFloat_array()) + { + const auto& pos = pos_array->getValue(); + const auto pos_count = pos.getCount(); + for (size_t j = 0; j < pos_count; j += 3) + { + if (pos_count <= j + 2) + { + LL_ERRS() << "Invalid position array size." << LL_ENDL; + } + + LLVector3 v(pos[j], pos[j + 1], pos[j + 2]); + + //transform from COLLADA space to volume space + v = v * inverse_normalized_transformation; + + model->mPosition.push_back(v); + } + } + } + } + } + } + + //get skin weights array + if (auto weights = skin->getVertex_weights()) + { + const auto& inputs = weights->getInput_array(); + domFloat_array* vertex_weights = NULL; + for (size_t i = 0; i < inputs.getCount(); ++i) + { + if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0) + { + if (const auto weight_source = daeSafeCast(inputs[i]->getSource().getElement())) + { + vertex_weights = weight_source->getFloat_array(); + } + } + } + + if (vertex_weights) + { + const auto& w = vertex_weights->getValue(); + const auto& vcount = weights->getVcount()->getValue(); + const auto vcount_count = vcount.getCount(); // sure ok + const auto& v = weights->getV()->getValue(); + auto c_idx = 0; + for (auto vc_idx = 0; vc_idx < vcount_count; ++vc_idx) + { + //for each vertex + //create list of weights that influence this vertex + LLModel::weight_list weight_list; + + const auto count = vcount[vc_idx]; + for (daeUInt i = 0; i < count; ++i) + { + //for each weight + const auto joint_idx = v[c_idx++]; + const auto weight_idx = v[c_idx++]; + + if (joint_idx == -1) + { + //ignore bindings to bind_shape_matrix + continue; + } + + const auto weight_value = (F32)w[weight_idx]; + + weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value)); + } + + //sort by joint weight + std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater()); + + std::vector wght; + + auto total = 0.f; + const auto n_weights = llmin(size_t(4), weight_list.size()); + for (size_t i = 0; i < n_weights; ++i) + { + //take up to 4 most significant weights + const auto weight = weight_list[i]; + const auto weight_value = weight.mWeight; + if (weight_value > 0.f) + { + wght.push_back(weight); + total += weight_value; + } + } + + if (total != 1.f) + { + //normalize weights + const auto scale = 1.f / total; + for (size_t i = 0; i < wght.size(); ++i) + { + wght[i].mWeight *= scale; + } + } + + model->mSkinWeights[model->mPosition[vc_idx]] = wght; + } + } + + } + //add instance to scene for this model + + LLMatrix4 transformation; + transformation.initScale(mesh_scale_vector); + transformation.setTranslation(mesh_translation_vector); + transformation *= mTransform; + + material_map materials; + for (const auto& m : model->mMaterialList) + { + materials[m] = LLImportMaterial(); + } + mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials)); + stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); + } +} + +//----------------------------------------------------------------------------- +// buildJointToNodeMappingFromScene() +//----------------------------------------------------------------------------- +void LLDAELoader::buildJointToNodeMappingFromScene(daeElement* pRoot) +{ + const auto pScene = pRoot->getDescendant("visual_scene"); + if (pScene) + { + const auto children = pScene->getChildren(); + for (size_t i = 0; i < children.getCount(); ++i) + { + const auto pNode = daeSafeCast(children[i]); + processJointToNodeMapping(pNode); + } + } +} +//----------------------------------------------------------------------------- +// processJointToNodeMapping() +//----------------------------------------------------------------------------- +void LLDAELoader::processJointToNodeMapping(domNode* pNode) +{ + if (isNodeAJoint(pNode)) + { + //1.Store the parent + const auto nodeName = std::string(pNode->getName()); + if (!nodeName.empty()) + { + mJointsFromNode.push_front(nodeName); + // Alias joint node SIDs to joint names for compatibility + const auto nodeSID = std::string(pNode->getSid()); + if (!nodeSID.empty()) + mJointMap[nodeSID] = mJointMap[nodeName]; + } + //2. Handle the kiddo's + processChildJoints(pNode); + } + else + { + //Determine if the're any children wrt to this failed node. + //This occurs when an armature is exported and ends up being what essentially amounts to + //as the root for the visual_scene + if (pNode) + { + processChildJoints(pNode); + } + else + { + LL_INFOS() << "Node is NULL" << LL_ENDL; + } + + } +} +//----------------------------------------------------------------------------- +// processChildJoint() +//----------------------------------------------------------------------------- +void LLDAELoader::processChildJoints(domNode* pParentNode) +{ + const auto childOfChild = pParentNode->getChildren(); + for (size_t i = 0; i < childOfChild.getCount(); ++i) + { + const auto pChildNode = daeSafeCast(childOfChild[i]); + if (pChildNode) + { + processJointToNodeMapping(pChildNode); + } + } +} + +//----------------------------------------------------------------------------- +// isNodeAJoint() +//----------------------------------------------------------------------------- +bool LLDAELoader::isNodeAJoint(const domNode* pNode) const +{ + if (pNode) + { + if (const auto pNodeName = pNode->getName()) + { + return LLModelLoader::isNodeAJoint(pNodeName); + } + } + LL_INFOS() << "Created node is NULL or invalid" << LL_ENDL; + return false; +} +//----------------------------------------------------------------------------- +// verifyCount +//----------------------------------------------------------------------------- +bool LLDAELoader::verifyCount(const size_t expected, const size_t result) const +{ + if (expected != result) + { + LL_INFOS() << "Error: (expected/got)" << expected << "/" << result << "verts" << LL_ENDL; + return false; + } + return true; +} +//----------------------------------------------------------------------------- +// verifyController +//----------------------------------------------------------------------------- +bool LLDAELoader::verifyController(const domController* pController) const +{ + bool result = true; + + if (const auto pSkin = pController->getSkin()) + { + const auto& uri = pSkin->getSource(); + const auto pElement = uri.getElement(); + + if (!pElement) + { + LL_INFOS() << "Can't resolve skin source" << LL_ENDL; + return false; + } + + const auto type_str = pElement->getTypeName(); + if (stricmp(type_str, "geometry") == 0) + { + //Skin is reference directly by geometry and get the vertex count from skin + const auto pVertexWeights = pSkin->getVertex_weights(); + const auto vertexWeightsCount = pVertexWeights->getCount(); + const auto pGeometry = (domGeometry*)(domElement*)uri.getElement(); + if (const auto pMesh = pGeometry->getMesh()) + { + //Get vertex count from geometry + if (const auto pVertices = pMesh->getVertices()) + { + const auto src = pVertices->getInput_array()[0]->getSource(); + const auto pSource = (domSource*)(domElement*)src.getElement(); + const auto verticesCount = pSource->getTechnique_common()->getAccessor()->getCount(); + result = verifyCount(verticesCount, vertexWeightsCount); + if (!result) + { + return false; + } + } + else + { + LL_INFOS() << "No vertices!" << LL_ENDL; + return false; + } + } + + const auto vcount_count = pVertexWeights->getVcount()->getValue().getCount(); + result = verifyCount(vcount_count, vertexWeightsCount); + if (!result) + { + return false; + } + + const auto& inputs = pVertexWeights->getInput_array(); + size_t sum = 0; + for (size_t i = 0; i < vcount_count; ++i) + { + sum += pVertexWeights->getVcount()->getValue()[i]; + } + result = verifyCount(sum * inputs.getCount(), (domInt)pVertexWeights->getV()->getValue().getCount()); + } + } + + return result; +} + +//----------------------------------------------------------------------------- +// extractTranslation() +//----------------------------------------------------------------------------- +void LLDAELoader::extractTranslation(const domTranslate* pTranslate, LLMatrix4& transform) const +{ + const auto& jointTrans = pTranslate->getValue(); + LLVector3 singleJointTranslation(jointTrans[0], jointTrans[1], jointTrans[2]); + transform.setTranslation(singleJointTranslation); +} + +//----------------------------------------------------------------------------- +// extractTranslationViaSID() +//----------------------------------------------------------------------------- +void LLDAELoader::extractTranslationViaSID(daeElement* pElement, LLMatrix4& transform) const +{ + if (pElement) + { + daeSIDResolver resolver(pElement, "./transform"); + const auto pMatrix = daeSafeCast(resolver.getElement()); + //We are only extracting out the translational component atm + LLMatrix4 workingTransform; + if (pMatrix) + { + const auto domArray = pMatrix->getValue(); + for (size_t i = 0; i < 4; ++i) + { + for (size_t j = 0; j < 4; ++j) + { + workingTransform.mMatrix[i][j] = domArray[i + j * 4]; + } + } + const auto trans = workingTransform.getTranslation(); + transform.setTranslation(trans); + } + } + else + { + LL_WARNS() << "Element is nonexistent - empty/unsupported node." << LL_ENDL; + } +} +//----------------------------------------------------------------------------- +// processJointNode() +//----------------------------------------------------------------------------- +void LLDAELoader::processJointNode(domNode* pNode, JointTransformMap& jointTransforms) +{ + if (pNode->getName() == NULL) + { + LL_WARNS() << "nameless node, can't process" << LL_ENDL; + return; + } + + //llwarns<<"ProcessJointNode# Node:" <getName()<(jointResolverA.getElement())) + { + extractTranslation(pTranslateA, workingTransform); + } + else if (const auto pTranslateB = daeSafeCast(jointResolverB.getElement())) + { + extractTranslation(pTranslateB, workingTransform); + } + else + { + const auto pTranslateElement = getChildFromElement(pNode, "translate"); + if (const auto pTranslateC = daeSafeCast(pTranslateElement)) + { + extractTranslation(pTranslateC, workingTransform); + } + else + { + daeSIDResolver jointResolver(pNode, "./matrix"); + if (const auto pMatrix = daeSafeCast(jointResolver.getElement())) + { + //LL_INFOS() <<"A matrix SID was however found!"<getValue(); + for (size_t i = 0; i < 4; ++i) + { + for (size_t j = 0; j < 4; ++j) + { + workingTransform.mMatrix[i][j] = domArray[i + j * 4]; + } + } + } + else + { + LL_WARNS() << "The found element is not translate or matrix node - most likely a corrupt export!" << LL_ENDL; + } + } + } + + //Store the working transform relative to the nodes name. + jointTransforms[pNode->getName()] = workingTransform; + + //2. handle the nodes children + + //Gather and handle the incoming nodes children + const auto childOfChild = pNode->getChildren(); + const auto childOfChildCount = childOfChild.getCount(); + + for (size_t i = 0; i < childOfChildCount; ++i) + { + if (const auto pChildNode = daeSafeCast(childOfChild[i])) + { + processJointNode(pChildNode, jointTransforms); + } + } +} + +//----------------------------------------------------------------------------- +// getChildFromElement() +//----------------------------------------------------------------------------- +daeElement* LLDAELoader::getChildFromElement(daeElement* pElement, std::string const& name) +{ + daeElement* pChildOfElement = pElement->getChild(name.c_str()); + if (pChildOfElement) + { + return pChildOfElement; + } + LL_DEBUGS("Mesh") << "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL; + return NULL; +} + +void LLDAELoader::processElement(daeElement* element, bool& badElement, DAE* dae, daeElement* domRoot) +{ + LLMatrix4 saved_transform, saved_bind_transform; + bool pushed_mat = false; + + if (const auto node = daeSafeCast(element)) + { + pushed_mat = true; + saved_transform = mTransform; + saved_bind_transform = mBindTransform; + } + + if (const auto translate = daeSafeCast(element)) + { + const auto dom_value = translate->getValue(); + + LLMatrix4 translation, translation2; + translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2])); + translation2 = translation; + + translation *= mTransform; + mTransform = translation; + mTransform.condition(); + + translation2 *= mBindTransform; + mBindTransform = translation2; + mBindTransform.condition(); + } + + if (const auto rotate = daeSafeCast(element)) + { + const auto dom_value = rotate->getValue(); + + LLMatrix4 rotation, rotation2; + rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0)); + rotation2 = rotation; + + rotation *= mTransform; + mTransform = rotation; + mTransform.condition(); + + rotation2 *= mBindTransform; + mBindTransform = rotation2; + mBindTransform.condition(); + } + + if (const auto scale = daeSafeCast(element)) + { + const auto dom_value = scale->getValue(); + + auto scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]); + scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes + LLMatrix4 scaling, scaling2; + scaling.initScale(scale_vector); + scaling2 = scaling; + + scaling *= mTransform; + mTransform = scaling; + mTransform.condition(); + + scaling2 *= mBindTransform; + mBindTransform = scaling2; + mBindTransform.condition(); + } + + if (const auto matrix = daeSafeCast(element)) + { + const auto dom_value = matrix->getValue(); + + LLMatrix4 matrix_transform, matrix_transform2; + + for (size_t i = 0; i < 4; ++i) + { + for (size_t j = 0; j < 4; ++j) + { + matrix_transform.mMatrix[i][j] = dom_value[i + j * 4]; + } + } + + matrix_transform2 = matrix_transform; + + matrix_transform *= mTransform; + mTransform = matrix_transform; + mTransform.condition(); + + matrix_transform2 *= mBindTransform; + mBindTransform = matrix_transform2; + mBindTransform.condition(); + } + + // Process instance_geometry for static meshes + if (const auto instance_geo = daeSafeCast(element)) + { + if (const auto geo = daeSafeCast(instance_geo->getUrl().getElement())) + { + if (const auto mesh = daeSafeCast(geo->getDescendant(daeElement::matchType(domMesh::ID())))) + { + for (auto& model : mModelsMap[mesh]) + { + auto transformation = mTransform; + + if (mTransform.determinant() < 0) + { + //negative scales are not supported + LL_INFOS() << "Negative scale detected, unsupported transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL; + badElement = true; + } + + auto materials = getMaterials(model, instance_geo, dae); + + // adjust the transformation to compensate for mesh normalization + LLVector3 mesh_scale_vector; + LLVector3 mesh_translation_vector; + model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); + + LLMatrix4 mesh_translation; + mesh_translation.setTranslation(mesh_translation_vector); + mesh_translation *= transformation; + transformation = mesh_translation; + + LLMatrix4 mesh_scale; + mesh_scale.initScale(mesh_scale_vector); + mesh_scale *= transformation; + transformation = mesh_scale; + + if (transformation.determinant() < 0) + { + //negative scales are not supported + LL_INFOS() << "Negative scale detected, unsupported post-normalization transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL; + badElement = true; + } + + std::string label; + + if (model->mLabel.empty()) + { + label = getLodlessLabel(instance_geo); + + llassert(!label.empty()); + + if (model->mSubmodelID) + { + label += (char)((int)'a' + model->mSubmodelID); + } + + model->mLabel = label + lod_suffix[mLod]; + } + else + { + // Don't change model's name if possible, it will play havoc with scenes that already use said model. + const auto ext_pos = getSuffixPosition(model->mLabel); + if (ext_pos != -1) + { + label = model->mLabel.substr(0, ext_pos); + } + else + { + label = model->mLabel; + } + } + + mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials)); + stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); + } + } + } + else + { + LL_INFOS() << "Unable to resolve geometry URL." << LL_ENDL; + badElement = true; + } + } + + // Process instance_control elements for skinned meshes + if (const auto instance_ctl = daeSafeCast(element)) + { + if (const auto ctl = daeSafeCast(instance_ctl->getUrl().getElement())) + { + if (const auto skin = ctl->getSkin()) + { + if (const auto geom = daeSafeCast(skin->getSource().getElement())) + { + if (const auto mesh = geom->getMesh()) + { + for (const auto mdl : mModelsMap[mesh]) + { + LLDAELoader::processDomModel(mdl, dae, domRoot, mesh, skin); + } + } + } + } + } + } + + // Resolve nodes to instances + if (const auto instance_node = daeSafeCast(element)) + { + if (const auto instance = instance_node->getUrl().getElement()) + { + processElement(instance, badElement, dae, domRoot); + } + } + + //process children + const auto children = element->getChildren(); + for (size_t i = 0; i < children.getCount(); ++i) + { + processElement(children[i], badElement, dae, domRoot); + } + + if (pushed_mat) + { + //this element was a node, restore transform before processiing siblings + mTransform = saved_transform; + mBindTransform = saved_bind_transform; + } +} + +std::map LLDAELoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo, DAE* dae) const +{ + std::map materials; + for (const auto& material : model->mMaterialList) + { + LLImportMaterial import_material; + domInstance_material* instance_mat = NULL; + + if (const auto technique = daeSafeCast( + instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID())))) + { + const auto inst_materials = technique->getChildrenByType(); + for (size_t j = 0; j < inst_materials.getCount(); ++j) + { + std::string symbol(inst_materials[j]->getSymbol()); + + if (symbol == material) // found the binding + { + instance_mat = inst_materials[j]; + break; + } + } + } + + if (instance_mat) + { + if (const auto material = daeSafeCast(instance_mat->getTarget().getElement())) + { + if (const auto instance_effect = daeSafeCast( + material->getDescendant(daeElement::matchType(domInstance_effect::ID())))) + { + if (const auto effect = daeSafeCast( + instance_effect->getUrl().getElement())) + { + if (const auto profile = daeSafeCast( + effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID())))) + { + import_material = profileToMaterial(profile, dae); + } + } + } + } + } + + import_material.mBinding = material; + materials[material] = import_material; + } + + return materials; +} + +LLImportMaterial LLDAELoader::profileToMaterial(domProfile_COMMON* material, DAE* dae) const +{ + LLImportMaterial mat; + mat.mFullbright = FALSE; + + if (const auto diffuse = material->getDescendant("diffuse")) + { + if (const auto texture = daeSafeCast(diffuse->getDescendant("texture"))) + { + const auto& newparams = material->getNewparam_array(); + if (newparams.getCount()) + { + for (size_t i = 0; i < newparams.getCount(); ++i) + { + if (const auto surface = newparams[i]->getSurface()) + { + if (const auto init = surface->getFx_surface_init_common()) + { + const auto init_from = init->getInit_from_array(); + if (init_from.getCount() > i) + { + if (const auto image = daeSafeCast(init_from[i]->getValue().getElement())) + { + // we only support init_from now - embedded data will come later + if (const auto init = image->getInit_from()) + { + mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str()); + mat.mDiffuseMapLabel = getElementLabel(material); + } + } + } + } + } + } + } + else if (texture->getTexture()) + { + domImage* image = NULL; + dae->getDatabase()->getElement((daeElement**)&image, 0, texture->getTexture(), COLLADA_TYPE_IMAGE); + if (image) + { + // we only support init_from now - embedded data will come later + if (const auto init = image->getInit_from()) + { + const auto image_path_value = cdom::uriToNativePath(init->getValue().str()); + +#if LL_WINDOWS + // Work-around DOM tendency to resort to UNC names which are only confusing for downstream... + // + auto i = image_path_value.cbegin(); + while (*i == '\\') + ++i; + + mat.mDiffuseMapFilename.assign(i, image_path_value.end()); +#else + mat.mDiffuseMapFilename = image_path_value; +#endif + mat.mDiffuseMapLabel = getElementLabel(material); + } + } + } + } + + if (const auto color = daeSafeCast(diffuse->getDescendant("color"))) + { + const auto domfx_color = color->getValue(); + const auto value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); + mat.mDiffuseColor = value; + } + } + + if (const auto emission = material->getDescendant("emission")) + { + const auto emission_color = getDaeColor(emission); + const auto color_avg = (emission_color[0] + emission_color[1] + emission_color[2]) / 3.0f; + mat.mFullbright |= color_avg > 0.25f; + } + + return mat; +} + +// try to get a decent label for this element +std::string LLDAELoader::getElementLabel(daeElement* element) +{ + // if we have a name attribute, use it + std::string name = element->getAttribute("name"); + if (name.length()) + { + return name; + } + + // if we have an ID attribute, use it + if (element->getID()) + { + return std::string(element->getID()); + } + + // if we have a parent, use it + const auto parent = element->getParent(); + std::string index_string; + if (parent) + { + // retrieve index to distinguish items inside same parent + auto ind = size_t(0); + parent->getChildren().find(element, ind); + + if (ind > 0) + { + index_string = "_" + fmt::to_string(ind); + } + + // if parent has a name or ID, use it + auto name = parent->getAttribute("name"); + if (!name.length()) + { + name = std::string(parent->getID()); + } + + if (name.length()) + { + // make sure that index won't mix up with pre-named lod extensions + const auto ext_pos = getSuffixPosition(name); + + if (ext_pos == -1) + { + return name + index_string; + } + else + { + return name.insert(ext_pos, index_string); + } + } + } + + // try to use our type + const auto element_name = element->getElementName(); + if (element_name) + { + return std::string(element_name) + index_string; + } + + // if all else fails, use "object" + return std::string("object") + index_string; +} + +// static +size_t LLDAELoader::getSuffixPosition(const std::string label) +{ + if ((label.find("_LOD") != std::string::npos) || (label.find("_PHYS") != std::string::npos)) + { + return label.rfind('_'); + } + return -1; +} + +// static +std::string LLDAELoader::getLodlessLabel(daeElement* element) +{ + std::string label = getElementLabel(element); + size_t ext_pos = getSuffixPosition(label); + if (ext_pos != -1) + { + return label.substr(0, ext_pos); + } + return label; +} + +LLColor4 LLDAELoader::getDaeColor(daeElement* element) const +{ + LLColor4 value; + if (const auto color = daeSafeCast(element->getDescendant("color"))) + { + const auto domfx_color = color->getValue(); + value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); + } + + return value; +} + +bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel, domMesh* mesh) +{ + auto status = LLModel::NO_ERRORS; + auto& tris = mesh->getTriangles_array(); + for (size_t i = 0; i < tris.getCount(); ++i) + { + auto& tri = tris.get(i); + status = load_face_from_dom_triangles(pModel->getVolumeFaces(), pModel->getMaterialList(), tri); + pModel->mStatus = status; + if (status != LLModel::NO_ERRORS) + { + pModel->ClearFacesAndMaterials(); + return false; + } + } + + auto& polys = mesh->getPolylist_array(); + for (size_t i = 0; i < polys.getCount(); ++i) + { + auto& poly = polys.get(i); + status = load_face_from_dom_polylist(pModel->getVolumeFaces(), pModel->getMaterialList(), poly); + if (status != LLModel::NO_ERRORS) + { + pModel->ClearFacesAndMaterials(); + return false; + } + } + + auto& polygons = mesh->getPolygons_array(); + for (size_t i = 0; i < polygons.getCount(); ++i) + { + auto& poly = polygons.get(i); + status = load_face_from_dom_polygons(pModel->getVolumeFaces(), pModel->getMaterialList(), poly); + if (status != LLModel::NO_ERRORS) + { + pModel->ClearFacesAndMaterials(); + return false; + } + } + + return (status == LLModel::NO_ERRORS); +} + +//static +LLModel* LLDAELoader::loadModelFromDomMesh(domMesh* mesh) +{ + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + auto ret = new LLModel(volume_params, 0.f); + createVolumeFacesFromDomMesh(ret, mesh); + if (ret->mLabel.empty()) + { + ret->mLabel = getElementLabel(mesh); + } + return ret; +} + +//static diff version supports creating multiple models when material counts spill +// over the 8 face server-side limit +// +bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector& models_out, U32 submodel_limit) +{ + + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + + models_out.clear(); + + auto ret = new LLModel(volume_params, 0.f); + + const auto model_name = getLodlessLabel(mesh); + ret->mLabel = model_name + lod_suffix[mLod]; + + llassert(!ret->mLabel.empty()); + + // Like a monkey, ready to be shot into space + // + ret->ClearFacesAndMaterials(); + + // Get the whole set of volume faces + // + addVolumeFacesFromDomMesh(ret, mesh); + + auto volume_faces = (U32)ret->getNumVolumeFaces(); + + // Side-steps all manner of issues when splitting models + // and matching lower LOD materials to base models + // + ret->sortVolumeFacesByMaterialName(); + + bool normalized = false; + + auto submodelID = 0; + + // remove all faces that definitely won't fit into one model and submodel limit + const auto face_limit = (submodel_limit + 1) * LL_SCULPT_MESH_MAX_FACES; + if (face_limit < volume_faces) + { + ret->setNumVolumeFaces(face_limit); + } + + LLVolume::face_list_t remainder; + do + { + // Insure we do this once with the whole gang and not per-model + // + if (!normalized && !mNoNormalize) + { + normalized = true; + ret->normalizeVolumeFaces(); + } + + ret->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder); + + if (!mNoOptimize) + { + ret->optimizeVolumeFaces(); + } + + volume_faces = remainder.size(); + + models_out.push_back(ret); + + // If we have left-over volume faces, create another model + // to absorb them... + // + if (volume_faces) + { + auto next = new LLModel(volume_params, 0.f); + next->mSubmodelID = ++submodelID; + next->mLabel = model_name + (char)((int)'a' + next->mSubmodelID) + lod_suffix[mLod]; + next->getVolumeFaces() = remainder; + next->mNormalizedScale = ret->mNormalizedScale; + next->mNormalizedTranslation = ret->mNormalizedTranslation; + if (ret->mMaterialList.size() > LL_SCULPT_MESH_MAX_FACES) + { + next->mMaterialList.assign(ret->mMaterialList.begin() + LL_SCULPT_MESH_MAX_FACES, ret->mMaterialList.end()); + } + ret = next; + } + + remainder.clear(); + + } while (volume_faces); + + return true; +} + +bool LLDAELoader::createVolumeFacesFromDomMesh(LLModel* pModel, domMesh* mesh) +{ + if (mesh) + { + pModel->ClearFacesAndMaterials(); + + addVolumeFacesFromDomMesh(pModel, mesh); + + if (pModel->getNumVolumeFaces() > 0) + { + pModel->normalizeVolumeFaces(); + pModel->optimizeVolumeFaces(); + + if (pModel->getNumVolumeFaces() > 0) + { + return true; + } + } + } + else + { + LL_WARNS() << "no mesh found" << LL_ENDL; + } + + return false; +} + diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h new file mode 100644 index 0000000000..607795be84 --- /dev/null +++ b/indra/llprimitive/lldaeloader.h @@ -0,0 +1,112 @@ +/** + * @file lldaeloader.h + * @brief LLDAELoader class definition + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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_LLDAELOADER_H +#define LL_LLDAELOADER_H + +#include "llmodelloader.h" + +class DAE; +class daeElement; +class domProfile_COMMON; +class domInstance_geometry; +class domNode; +class domTranslate; +class domController; +class domSkin; +class domMesh; + +class LLDAELoader : public LLModelLoader +{ +public: + typedef std::map material_map; + typedef std::map > > dae_model_map; + dae_model_map mModelsMap; + + LLDAELoader( + std::string filename, + S32 lod, + LLModelLoader::load_callback_t load_cb, + LLModelLoader::joint_lookup_func_t joint_lookup_func, + LLModelLoader::texture_load_func_t texture_load_func, + LLModelLoader::state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointTransformMap, + JointNameSet& jointsFromNodes, + std::map& jointAliasMap, + U32 maxJointsPerMesh, + U32 modelLimit, + bool preprocess); + virtual ~LLDAELoader(); + + virtual bool OpenFile(const std::string& filename); + +protected: + + void processElement(daeElement* element, bool& badElement, DAE* dae, daeElement* domRoot); + void processDomModel(LLModel* model, DAE* dae, daeElement* pRoot, domMesh* mesh, domSkin* skin); + + material_map getMaterials(LLModel* model, domInstance_geometry* instance_geo, DAE* dae) const; + LLImportMaterial profileToMaterial(domProfile_COMMON* material, DAE* dae) const; + LLColor4 getDaeColor(daeElement* element) const; + + daeElement* getChildFromElement(daeElement* pElement, std::string const& name); + + bool isNodeAJoint(const domNode* pNode) const; + void processJointNode(domNode* pNode, JointTransformMap& jointTransforms); + void extractTranslation(const domTranslate* pTranslate, LLMatrix4& transform) const; + void extractTranslationViaSID(daeElement* pElement, LLMatrix4& transform) const; + void buildJointToNodeMappingFromScene(daeElement* pRoot); + void processJointToNodeMapping(domNode* pNode); + void processChildJoints(domNode* pParentNode); + + bool verifyCount(const size_t expected, const size_t result) const; + + //Verify that a controller matches vertex counts + bool verifyController(const domController* pController) const; + + static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh); + static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh); + + static LLModel* loadModelFromDomMesh(domMesh* mesh); + + // Loads a mesh breaking it into one or more models as necessary + // to get around volume face limitations while retaining >8 materials + // + bool loadModelsFromDomMesh(domMesh* mesh, std::vector& models_out, U32 submodel_limit); + + static std::string getElementLabel(daeElement* element); + static size_t getSuffixPosition(const std::string label); + static std::string getLodlessLabel(daeElement* element); + + static std::string preprocessDAE(const std::string filename); + +private: + U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels + bool mPreprocessDAE; + +}; +#endif // LL_LLDAELLOADER_H diff --git a/indra/llprimitive/llmaterialid.cpp b/indra/llprimitive/llmaterialid.cpp index 820f62c43c..81b4575423 100644 --- a/indra/llprimitive/llmaterialid.cpp +++ b/indra/llprimitive/llmaterialid.cpp @@ -42,8 +42,11 @@ LLMaterialID::LLMaterialID() LLMaterialID::LLMaterialID(const LLSD& pMaterialID) { - llassert(pMaterialID.isBinary()); - parseFromBinary(pMaterialID.asBinary()); + llassert(pMaterialID.isBinary() || pMaterialID.isUUID()); + if (pMaterialID.isUUID()) + set(pMaterialID.asUUID().mData); + else + parseFromBinary(pMaterialID.asBinary()); } LLMaterialID::LLMaterialID(const LLSD::Binary& pMaterialID) @@ -56,15 +59,6 @@ LLMaterialID::LLMaterialID(const void* pMemory) set(pMemory); } -LLMaterialID::LLMaterialID(const LLMaterialID& pOtherMaterialID) -{ - copyFromOtherMaterialID(pOtherMaterialID); -} - -LLMaterialID::~LLMaterialID() -{ -} - bool LLMaterialID::operator == (const LLMaterialID& pOtherMaterialID) const { return (compareToOtherMaterialID(pOtherMaterialID) == 0); @@ -95,12 +89,6 @@ bool LLMaterialID::operator >= (const LLMaterialID& pOtherMaterialID) const return (compareToOtherMaterialID(pOtherMaterialID) >= 0); } -LLMaterialID& LLMaterialID::operator = (const LLMaterialID& pOtherMaterialID) -{ - copyFromOtherMaterialID(pOtherMaterialID); - return (*this); -} - bool LLMaterialID::isNull() const { return (compareToOtherMaterialID(LLMaterialID::null) == 0); @@ -116,12 +104,12 @@ void LLMaterialID::set(const void* pMemory) llassert(pMemory != NULL); // assumes that the required size of memory is available - memcpy(mID, pMemory, MATERIAL_ID_SIZE * sizeof(U8)); + memcpy(mID, pMemory, sizeof(mID)); } void LLMaterialID::clear() { - memset(mID, 0, MATERIAL_ID_SIZE * sizeof(U8)); + memset(mID, 0, sizeof(mID)); } LLSD LLMaterialID::asLLSD() const @@ -156,18 +144,12 @@ std::ostream& operator<<(std::ostream& s, const LLMaterialID &material_id) return s; } - void LLMaterialID::parseFromBinary (const LLSD::Binary& pMaterialID) { llassert(pMaterialID.size() == (MATERIAL_ID_SIZE * sizeof(U8))); memcpy(mID, &pMaterialID[0], MATERIAL_ID_SIZE * sizeof(U8)); } -void LLMaterialID::copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID) -{ - memcpy(mID, pOtherMaterialID.get(), MATERIAL_ID_SIZE * sizeof(U8)); -} - int LLMaterialID::compareToOtherMaterialID(const LLMaterialID& pOtherMaterialID) const { int retVal = 0; diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h index 0a95204085..1a086e23b6 100644 --- a/indra/llprimitive/llmaterialid.h +++ b/indra/llprimitive/llmaterialid.h @@ -30,16 +30,18 @@ #define MATERIAL_ID_SIZE 16 #include +#include "llsd.h" class LLMaterialID { public: LLMaterialID(); + LLMaterialID(const LLUUID& id) { set(id.mData); } LLMaterialID(const LLSD& pMaterialID); LLMaterialID(const LLSD::Binary& pMaterialID); LLMaterialID(const void* pMemory); - LLMaterialID(const LLMaterialID& pOtherMaterialID); - ~LLMaterialID(); + LLMaterialID(const LLMaterialID& pOtherMaterialID) = default; + ~LLMaterialID() = default; bool operator == (const LLMaterialID& pOtherMaterialID) const; bool operator != (const LLMaterialID& pOtherMaterialID) const; @@ -49,7 +51,7 @@ class LLMaterialID bool operator > (const LLMaterialID& pOtherMaterialID) const; bool operator >= (const LLMaterialID& pOtherMaterialID) const; - LLMaterialID& operator = (const LLMaterialID& pOtherMaterialID); + LLMaterialID& operator = (const LLMaterialID& pOtherMaterialID) = default; bool isNull() const; @@ -66,11 +68,13 @@ class LLMaterialID private: void parseFromBinary(const LLSD::Binary& pMaterialID); - void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID); int compareToOtherMaterialID(const LLMaterialID& pOtherMaterialID) const; U8 mID[MATERIAL_ID_SIZE]; } ; +static_assert(sizeof(LLMaterialID) == MATERIAL_ID_SIZE, "LLMaterialID must be sizeof(mID)"); +static_assert(std::is_trivially_copyable::value, "LLMaterialID must be a trivially copyable type"); + #endif // LL_LLMATERIALID_H diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 27bb606ffe..fa39a37895 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -32,20 +32,6 @@ #include "llsdserialize.h" #include "llvector4a.h" #include "llmatrix4a.h" -#if LL_MSVC -#pragma warning (push) -#pragma warning (disable : 4068) -#pragma warning (disable : 4263) -#pragma warning (disable : 4264) -#endif -#pragma GCC diagnostic ignored "-Woverloaded-virtual" -#include "dae.h" -#include "dae/daeErrorHandler.h" -#include "dom/domConstants.h" -#include "dom/domMesh.h" -#if LL_MSVC -#pragma warning (pop) -#endif #ifdef LL_STANDALONE # include @@ -53,8 +39,6 @@ # include "zlib/zlib.h" #endif - - std::string model_names[] = { "lowest_lod", @@ -67,8 +51,12 @@ std::string model_names[] = const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string); LLModel::LLModel(LLVolumeParams& params, F32 detail) - : LLVolume(params, detail), mNormalizedScale(1,1,1), mNormalizedTranslation(0,0,0) - , mPelvisOffset( 0.0f ), mStatus(NO_ERRORS) + : LLVolume(params, detail), + mNormalizedScale(1,1,1), + mNormalizedTranslation(0,0,0), + mPelvisOffset( 0.0f ), + mStatus(NO_ERRORS), + mSubmodelID(0) { mDecompID = -1; mLocalID = -1; @@ -82,805 +70,6 @@ LLModel::~LLModel() } } - -bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride, - domSource* &pos_source, domSource* &tc_source, domSource* &norm_source) -{ - idx_stride = 0; - - for (U32 j = 0; j < inputs.getCount(); ++j) - { - idx_stride = llmax((S32) inputs[j]->getOffset(), idx_stride); - - if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0) - { //found vertex array - const domURIFragmentType& uri = inputs[j]->getSource(); - daeElementRef elem = uri.getElement(); - domVertices* vertices = (domVertices*) elem.cast(); - if ( !vertices ) - { - return false; - } - - domInputLocal_Array& v_inp = vertices->getInput_array(); - - - for (U32 k = 0; k < v_inp.getCount(); ++k) - { - if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) - { - pos_offset = inputs[j]->getOffset(); - - const domURIFragmentType& uri = v_inp[k]->getSource(); - daeElementRef elem = uri.getElement(); - pos_source = (domSource*) elem.cast(); - } - - if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp[k]->getSemantic()) == 0) - { - norm_offset = inputs[j]->getOffset(); - - const domURIFragmentType& uri = v_inp[k]->getSource(); - daeElementRef elem = uri.getElement(); - norm_source = (domSource*) elem.cast(); - } - } - } - - if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0) - { - //found normal array for this triangle list - norm_offset = inputs[j]->getOffset(); - const domURIFragmentType& uri = inputs[j]->getSource(); - daeElementRef elem = uri.getElement(); - norm_source = (domSource*) elem.cast(); - } - else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0) - { //found texCoords - tc_offset = inputs[j]->getOffset(); - const domURIFragmentType& uri = inputs[j]->getSource(); - daeElementRef elem = uri.getElement(); - tc_source = (domSource*) elem.cast(); - } - } - - idx_stride += 1; - - return true; -} - -LLModel::EModelStatus load_face_from_dom_triangles(std::vector& face_list, std::vector& materials, domTrianglesRef& tri) -{ - LLVolumeFace face; - std::vector verts; - std::vector indices; - - const domInputLocalOffset_Array& inputs = tri->getInput_array(); - - S32 pos_offset = -1; - S32 tc_offset = -1; - S32 norm_offset = -1; - - domSource* pos_source = NULL; - domSource* tc_source = NULL; - domSource* norm_source = NULL; - - S32 idx_stride = 0; - - if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source ) - { - LL_WARNS() << "Could not find dom sources for basic geo data; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - if (!pos_source) - { - LL_WARNS() << "Unable to process mesh without position data; invalid model; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - domPRef p = tri->getP(); - domListOfUInts& idx = p->getValue(); - - domListOfFloats dummy ; - domListOfFloats& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy ; - domListOfFloats& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy ; - domListOfFloats& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy ; - - LLVolumeFace::VertexMapData::PointMap point_map; - - U32 index_count = idx.getCount(); - U32 vertex_count = pos_source ? v.getCount() : 0; - U32 tc_count = tc_source ? tc.getCount() : 0; - U32 norm_count = norm_source ? n.getCount() : 0; - - if (vertex_count == 0) - { - LL_WARNS() << "Unable to process mesh with empty position array; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - face.mExtents[0].set(v[0], v[1], v[2]); - face.mExtents[1].set(v[0], v[1], v[2]); - - for (U32 i = 0; i < index_count; i += idx_stride) - { - LLVolumeFace::VertexData cv; - if (pos_source) - { - // guard against model data specifiying out of range indices or verts - // - if (((i + pos_offset) > index_count) - || ((idx[i+pos_offset]*3+2) > vertex_count)) - { - LL_WARNS() << "Out of range index data; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0], - v[idx[i+pos_offset]*3+1], - v[idx[i+pos_offset]*3+2])); - - if (!cv.getPosition().isFinite3()) - { - LL_WARNS() << "Nan positional data, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - if (tc_source) - { - // guard against model data specifiying out of range indices or tcs - // - - if (((i + tc_offset) > index_count) - || ((idx[i+tc_offset]*2+1) > tc_count)) - { - LL_WARNS() << "Out of range TC indices." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0], - tc[idx[i+tc_offset]*2+1]); - - if (!cv.mTexCoord.isFinite()) - { - LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - if (norm_source) - { - // guard against model data specifiying out of range indices or norms - // - if (((i + norm_offset) > index_count) - || ((idx[i+norm_offset]*3+2) > norm_count)) - { - LL_WARNS() << "Found out of range norm indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0], - n[idx[i+norm_offset]*3+1], - n[idx[i+norm_offset]*3+2])); - - if (!cv.getNormal().isFinite3()) - { - LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - BOOL found = FALSE; - - LLVolumeFace::VertexMapData::PointMap::iterator point_iter; - point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); - - if (point_iter != point_map.end()) - { - for (U32 j = 0; j < point_iter->second.size(); ++j) - { - if ((point_iter->second)[j] == cv) - { - found = TRUE; - indices.push_back((point_iter->second)[j].mIndex); - break; - } - } - } - - if (!found) - { - update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); - verts.push_back(cv); - if (verts.size() >= 65535) - { - //LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; - return LLModel::VERTEX_NUMBER_OVERFLOW ; - } - U16 index = (U16) (verts.size()-1); - indices.push_back(index); - - LLVolumeFace::VertexMapData d; - d.setPosition(cv.getPosition()); - d.mTexCoord = cv.mTexCoord; - d.setNormal(cv.getNormal()); - d.mIndex = index; - if (point_iter != point_map.end()) - { - point_iter->second.push_back(d); - } - else - { - point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); - } - } - - if (indices.size()%3 == 0 && verts.size() >= 65532) - { - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(verts, indices); - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - - face = LLVolumeFace(); - point_map.clear(); - } - } - - if (!verts.empty()) - { - std::string material; - - if (tri->getMaterial()) - { - material = std::string(tri->getMaterial()); - } - - materials.push_back(material); - face_list.push_back(face); - - face_list.rbegin()->fillFromLegacyData(verts, indices); - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - } - - return LLModel::NO_ERRORS ; -} - -LLModel::EModelStatus load_face_from_dom_polylist(std::vector& face_list, std::vector& materials, domPolylistRef& poly) -{ - domPRef p = poly->getP(); - domListOfUInts& idx = p->getValue(); - - if (idx.getCount() == 0) - { - return LLModel::NO_ERRORS ; - } - - const domInputLocalOffset_Array& inputs = poly->getInput_array(); - - - domListOfUInts& vcount = poly->getVcount()->getValue(); - - S32 pos_offset = -1; - S32 tc_offset = -1; - S32 norm_offset = -1; - - domSource* pos_source = NULL; - domSource* tc_source = NULL; - domSource* norm_source = NULL; - - S32 idx_stride = 0; - - if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source)) - { - LL_WARNS() << "Could not get DOM sources for basic geo data, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - LLVolumeFace face; - - std::vector indices; - std::vector verts; - - domListOfFloats v; - domListOfFloats tc; - domListOfFloats n; - - if (pos_source) - { - v = pos_source->getFloat_array()->getValue(); - face.mExtents[0].set(v[0], v[1], v[2]); - face.mExtents[1].set(v[0], v[1], v[2]); - } - - if (tc_source) - { - tc = tc_source->getFloat_array()->getValue(); - } - - if (norm_source) - { - n = norm_source->getFloat_array()->getValue(); - } - - LLVolumeFace::VertexMapData::PointMap point_map; - - U32 index_count = idx.getCount(); - U32 vertex_count = pos_source ? v.getCount() : 0; - U32 tc_count = tc_source ? tc.getCount() : 0; - U32 norm_count = norm_source ? n.getCount() : 0; - - U32 cur_idx = 0; - for (U32 i = 0; i < vcount.getCount(); ++i) - { //for each polygon - U32 first_index = 0; - U32 last_index = 0; - for (U32 j = 0; j < vcount[i]; ++j) - { //for each vertex - - LLVolumeFace::VertexData cv; - - if (pos_source) - { - // guard against model data specifiying out of range indices or verts - // - if (((cur_idx + pos_offset) > index_count) - || ((idx[cur_idx+pos_offset]*3+2) > vertex_count)) - { - LL_WARNS() << "Out of range position indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0], - v[idx[cur_idx+pos_offset]*3+1], - v[idx[cur_idx+pos_offset]*3+2]); - - if (!cv.getPosition().isFinite3()) - { - LL_WARNS() << "Found NaN while loading positions from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - } - - if (tc_source) - { - // guard against model data specifiying out of range indices or tcs - // - if (((cur_idx + tc_offset) > index_count) - || ((idx[cur_idx+tc_offset]*2+1) > tc_count)) - { - LL_WARNS() << "Out of range TC indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0], - tc[idx[cur_idx+tc_offset]*2+1]); - - if (!cv.mTexCoord.isFinite()) - { - LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - if (norm_source) - { - // guard against model data specifiying out of range indices or norms - // - if (((cur_idx + norm_offset) > index_count) - || ((idx[cur_idx+norm_offset]*3+2) > norm_count)) - { - LL_WARNS() << "Out of range norm indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0], - n[idx[cur_idx+norm_offset]*3+1], - n[idx[cur_idx+norm_offset]*3+2]); - - if (!cv.getNormal().isFinite3()) - { - LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - cur_idx += idx_stride; - - BOOL found = FALSE; - - LLVolumeFace::VertexMapData::PointMap::iterator point_iter; - LLVector3 pos3(cv.getPosition().getF32ptr()); - point_iter = point_map.find(pos3); - - if (point_iter != point_map.end()) - { - for (U32 k = 0; k < point_iter->second.size(); ++k) - { - if ((point_iter->second)[k] == cv) - { - found = TRUE; - U32 index = (point_iter->second)[k].mIndex; - if (j == 0) - { - first_index = index; - } - else if (j == 1) - { - last_index = index; - } - else - { - indices.push_back(first_index); - indices.push_back(last_index); - indices.push_back(index); - last_index = index; - } - - break; - } - } - } - - if (!found) - { - update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); - verts.push_back(cv); - if (verts.size() >= 65535) - { - //LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; - return LLModel::VERTEX_NUMBER_OVERFLOW ; - } - U16 index = (U16) (verts.size()-1); - - if (j == 0) - { - first_index = index; - } - else if (j == 1) - { - last_index = index; - } - else - { - indices.push_back(first_index); - indices.push_back(last_index); - indices.push_back(index); - last_index = index; - } - - LLVolumeFace::VertexMapData d; - d.setPosition(cv.getPosition()); - d.mTexCoord = cv.mTexCoord; - d.setNormal(cv.getNormal()); - d.mIndex = index; - if (point_iter != point_map.end()) - { - point_iter->second.push_back(d); - } - else - { - point_map[pos3].push_back(d); - } - } - - if (indices.size()%3 == 0 && indices.size() >= 65532) - { - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(verts, indices); - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - - face = LLVolumeFace(); - verts.clear(); - indices.clear(); - point_map.clear(); - } - } - } - - if (!verts.empty()) - { - std::string material; - - if (poly->getMaterial()) - { - material = std::string(poly->getMaterial()); - } - - materials.push_back(material); - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(verts, indices); - - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - } - - return LLModel::NO_ERRORS ; -} - -LLModel::EModelStatus load_face_from_dom_polygons(std::vector& face_list, std::vector& materials, domPolygonsRef& poly) -{ - LLVolumeFace face; - std::vector indices; - std::vector verts; - - const domInputLocalOffset_Array& inputs = poly->getInput_array(); - - S32 v_offset = -1; - S32 n_offset = -1; - S32 t_offset = -1; - - domListOfFloats* v = NULL; - domListOfFloats* n = NULL; - domListOfFloats* t = NULL; - - U32 stride = 0; - for (U32 i = 0; i < inputs.getCount(); ++i) - { - stride = llmax((U32) inputs[i]->getOffset()+1, stride); - - if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[i]->getSemantic()) == 0) - { //found vertex array - v_offset = inputs[i]->getOffset(); - - const domURIFragmentType& uri = inputs[i]->getSource(); - daeElementRef elem = uri.getElement(); - domVertices* vertices = (domVertices*) elem.cast(); - if (!vertices) - { - LL_WARNS() << "Could not find vertex source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - domInputLocal_Array& v_inp = vertices->getInput_array(); - - for (U32 k = 0; k < v_inp.getCount(); ++k) - { - if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) - { - const domURIFragmentType& uri = v_inp[k]->getSource(); - daeElementRef elem = uri.getElement(); - domSource* src = (domSource*) elem.cast(); - if (!src) - { - LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - v = &(src->getFloat_array()->getValue()); - } - } - } - else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[i]->getSemantic()) == 0) - { - n_offset = inputs[i]->getOffset(); - //found normal array for this triangle list - const domURIFragmentType& uri = inputs[i]->getSource(); - daeElementRef elem = uri.getElement(); - domSource* src = (domSource*) elem.cast(); - if (!src) - { - LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - n = &(src->getFloat_array()->getValue()); - } - else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0) - { //found texCoords - t_offset = inputs[i]->getOffset(); - const domURIFragmentType& uri = inputs[i]->getSource(); - daeElementRef elem = uri.getElement(); - domSource* src = (domSource*) elem.cast(); - if (!src) - { - LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - t = &(src->getFloat_array()->getValue()); - } - } - - domP_Array& ps = poly->getP_array(); - - //make a triangle list in - for (U32 i = 0; i < ps.getCount(); ++i) - { //for each polygon - domListOfUInts& idx = ps[i]->getValue(); - for (U32 j = 0; j < idx.getCount()/stride; ++j) - { //for each vertex - if (j > 2) - { - U32 size = verts.size(); - LLVolumeFace::VertexData v0 = verts[size-3]; - LLVolumeFace::VertexData v1 = verts[size-1]; - - verts.push_back(v0); - verts.push_back(v1); - } - - LLVolumeFace::VertexData vert; - - - if (v) - { - U32 v_idx = idx[j*stride+v_offset]*3; - v_idx = llclamp(v_idx, (U32) 0, (U32) v->getCount()); - vert.getPosition().set(v->get(v_idx), - v->get(v_idx+1), - v->get(v_idx+2)); - - if (!vert.getPosition().isFinite3()) - { - LL_WARNS() << "Found NaN while loading position data from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - //bounds check n and t lookups because some FBX to DAE converters - //use negative indices and empty arrays to indicate data does not exist - //for a particular channel - if (n && n->getCount() > 0) - { - U32 n_idx = idx[j*stride+n_offset]*3; - n_idx = llclamp(n_idx, (U32) 0, (U32) n->getCount()); - vert.getNormal().set(n->get(n_idx), - n->get(n_idx+1), - n->get(n_idx+2)); - - if (!vert.getNormal().isFinite3()) - { - LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - else - { - vert.getNormal().clear(); - } - - - if (t && t->getCount() > 0) - { - U32 t_idx = idx[j*stride+t_offset]*2; - t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount()); - vert.mTexCoord.setVec(t->get(t_idx), - t->get(t_idx+1)); - - if (!vert.mTexCoord.isFinite()) - { - LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - else - { - vert.mTexCoord.clear(); - } - - - verts.push_back(vert); - } - } - - if (verts.empty()) - { - return LLModel::NO_ERRORS; - } - - face.mExtents[0] = verts[0].getPosition(); - face.mExtents[1] = verts[0].getPosition(); - - //create a map of unique vertices to indices - std::map vert_idx; - - U32 cur_idx = 0; - for (U32 i = 0; i < verts.size(); ++i) - { - std::map::iterator iter = vert_idx.find(verts[i]); - if (iter == vert_idx.end()) - { - vert_idx[verts[i]] = cur_idx++; - } - } - - //build vertex array from map - std::vector new_verts; - new_verts.resize(vert_idx.size()); - - for (std::map::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter) - { - new_verts[iter->second] = iter->first; - update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition()); - } - - //build index array from map - indices.resize(verts.size()); - - for (U32 i = 0; i < verts.size(); ++i) - { - indices[i] = vert_idx[verts[i]]; - } - - // DEBUG just build an expanded triangle list - /*for (U32 i = 0; i < verts.size(); ++i) - { - indices.push_back((U16) i); - update_min_max(face.mExtents[0], face.mExtents[1], verts[i].getPosition()); - }*/ - - if (!new_verts.empty()) - { - std::string material; - - if (poly->getMaterial()) - { - material = std::string(poly->getMaterial()); - } - - materials.push_back(material); - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(new_verts, indices); - - LLVolumeFace& new_face = *face_list.rbegin(); - if (!n) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!t) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - } - - return LLModel::NO_ERRORS ; -} - //static std::string LLModel::getStatusString(U32 status) { @@ -900,105 +89,94 @@ std::string LLModel::getStatusString(U32 status) return std::string() ; } -void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh) +void LLModel::offsetMesh( const LLVector3& pivotPoint ) { - domTriangles_Array& tris = mesh->getTriangles_array(); - - for (U32 i = 0; i < tris.getCount(); ++i) + LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] ); + + for (std::vector::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); ) { - domTrianglesRef& tri = tris.get(i); - - mStatus = load_face_from_dom_triangles(mVolumeFaces, mMaterialList, tri); + std::vector:: iterator currentFaceIt = faceIt++; + LLVolumeFace& face = *currentFaceIt; + LLVector4a *pos = (LLVector4a*) face.mPositions; - if(mStatus != NO_ERRORS) + for (U32 i=0; i< (U32)face.mNumVertices; ++i ) { - mVolumeFaces.clear() ; - mMaterialList.clear() ; - return ; //abort + pos[i].add( pivot ); } } +} - domPolylist_Array& polys = mesh->getPolylist_array(); - for (U32 i = 0; i < polys.getCount(); ++i) - { - domPolylistRef& poly = polys.get(i); - mStatus = load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly); - - if(mStatus != NO_ERRORS) - { - mVolumeFaces.clear() ; - mMaterialList.clear() ; - return ; //abort - } - } - - domPolygons_Array& polygons = mesh->getPolygons_array(); - - for (U32 i = 0; i < polygons.getCount(); ++i) +void LLModel::optimizeVolumeFaces() +{ + for (U32 i = 0; i < (U32)getNumVolumeFaces(); ++i) { - domPolygonsRef& poly = polygons.get(i); - mStatus = load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly); - - if(mStatus != NO_ERRORS) - { - mVolumeFaces.clear() ; - mMaterialList.clear() ; - return ; //abort - } + //validate_face(mVolumeFaces[i]); + mVolumeFaces[i].optimize(); + //validate_face(mVolumeFaces[i]); } - } -BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh) +struct MaterialBinding +{ + int index; + std::string matName; +}; + +struct MaterialSort { - if (mesh) + bool operator()(const MaterialBinding& lhs, const MaterialBinding& rhs) { - mVolumeFaces.clear(); - mMaterialList.clear(); + return LLStringUtil::compareInsensitive(lhs.matName, rhs.matName) < 0; + } +}; - addVolumeFacesFromDomMesh(mesh); - - if (getNumVolumeFaces() > 0) +void LLModel::sortVolumeFacesByMaterialName() +{ + std::vector bindings; + bindings.resize(mVolumeFaces.size()); + + for (U32 i = 0; i < bindings.size(); i++) + { + bindings[i].index = i; + if(i < mMaterialList.size()) { - normalizeVolumeFaces(); - optimizeVolumeFaces(); - - if (getNumVolumeFaces() > 0) - { - return TRUE; - } + bindings[i].matName = mMaterialList[i]; } } - else - { - LL_WARNS() << "no mesh found" << LL_ENDL; - } - - return FALSE; -} + std::sort(bindings.begin(), bindings.end(), MaterialSort()); + std::vector< LLVolumeFace > new_faces; -void LLModel::offsetMesh( const LLVector3& pivotPoint ) -{ - LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] ); - - for (std::vector::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); ) + // remap the faces to be in the same order the mats now are... + // + new_faces.resize(bindings.size()); + for (U32 i = 0; i < bindings.size(); i++) { - std::vector:: iterator currentFaceIt = faceIt++; - LLVolumeFace& face = *currentFaceIt; - LLVector4a *pos = (LLVector4a*) face.mPositions; - - for (U32 i=0; i< (U32)face.mNumVertices; ++i ) + new_faces[i] = mVolumeFaces[bindings[i].index]; + if(i < mMaterialList.size()) { - pos[i].add( pivot ); + mMaterialList[i] = bindings[i].matName; } } + + mVolumeFaces = new_faces; } -void LLModel::optimizeVolumeFaces() +void LLModel::trimVolumeFacesToSize(U32 new_count, LLVolume::face_list_t* remainder) { - for (U32 i = 0; i < (U32)getNumVolumeFaces(); ++i) + llassert(new_count <= LL_SCULPT_MESH_MAX_FACES); + + if (new_count && ((U32)getNumVolumeFaces() > new_count)) { - mVolumeFaces[i].optimize(); + // Copy out remaining volume faces for alternative handling, if provided + // + if (remainder) + { + (*remainder).assign(mVolumeFaces.begin() + new_count, mVolumeFaces.end()); + } + + // Trim down to the final set of volume faces (now stuffed to the gills!) + // + mVolumeFaces.resize(new_count); } } @@ -1229,40 +407,6 @@ void LLModel::setVolumeFaceData( LLVector4a::memcpyNonAliased16((F32*) face.mIndices, (F32*) ind.get(), size); } -void LLModel::appendFaces(LLModel *model, LLMatrix4 &transform, LLMatrix4& norm_mat) -{ - if (mVolumeFaces.empty()) - { - setNumVolumeFaces(1); - } - - LLVolumeFace& face = mVolumeFaces[mVolumeFaces.size()-1]; - - - for (S32 i = 0; i < model->getNumFaces(); ++i) - { - face.appendFace(model->getVolumeFace(i), transform, norm_mat); - } - -} - -void LLModel::appendFace(const LLVolumeFace& src_face, std::string src_material, LLMatrix4& mat, LLMatrix4& norm_mat) -{ - S32 rindex = getNumVolumeFaces()-1; - if (rindex == -1 || - mVolumeFaces[rindex].mNumVertices + src_face.mNumVertices >= 65536) - { //empty or overflow will occur, append new face - LLVolumeFace cur_face; - cur_face.appendFace(src_face, mat, norm_mat); - addFace(cur_face); - mMaterialList.push_back(src_material); - } - else - { //append to existing end face - mVolumeFaces.rbegin()->appendFace(src_face, mat, norm_mat); - } -} - void LLModel::addFace(const LLVolumeFace& face) { if (face.mNumVertices == 0) @@ -1345,7 +489,9 @@ void LLModel::generateNormals(F32 angle_cutoff) } //weld vertices in temporary face, respecting angle_cutoff (step 2) + //validate_face(faceted); faceted.optimize(angle_cutoff); + //validate_face(faceted); //generate normals for welded face based on new topology (step 3) @@ -1477,74 +623,17 @@ void LLModel::generateNormals(F32 angle_cutoff) } //remove redundant vertices from new face (step 6) + //validate_face(new_face); new_face.optimize(); + //validate_face(new_face); mVolumeFaces[j] = new_face; } } -//static -std::string LLModel::getElementLabel(daeElement *element) -{ // try to get a decent label for this element - // if we have a name attribute, use it - std::string name = element->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if we have an ID attribute, use it - if (element->getID()) - { - return std::string(element->getID()); - } - - // if we have a parent, use it - daeElement* parent = element->getParent(); - if (parent) - { - // if parent has a name, use it - std::string name = parent->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if parent has an ID, use it - if (parent->getID()) - { - return std::string(parent->getID()); - } - } - - // try to use our type - daeString element_name = element->getElementName(); - if (element_name) - { - return std::string(element_name); - } - - // if all else fails, use "object" - return std::string("object"); -} - -//static -LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh) -{ - LLVolumeParams volume_params; - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - LLModel* ret = new LLModel(volume_params, 0.f); - ret->createVolumeFacesFromDomMesh(mesh); - ret->mLabel = getElementLabel(mesh); - return ret; -} - std::string LLModel::getName() const { - if (!mRequestedLabel.empty()) - return mRequestedLabel; - else - return mLabel; + return mRequestedLabel.empty() ? mLabel : mRequestedLabel; } //static @@ -1558,8 +647,10 @@ LLSD LLModel::writeModel( const LLModel::Decomposition& decomp, BOOL upload_skin, BOOL upload_joints, + BOOL lock_scale_if_joint_position, BOOL nowrite, - BOOL as_slm) + BOOL as_slm, + int submodel_id) { LLSD mdl; @@ -1576,7 +667,7 @@ LLSD LLModel::writeModel( if (skinning) { //write skinning block - mdl["skin"] = high->mSkinInfo.asLLSD(upload_joints); + mdl["skin"] = high->mSkinInfo.asLLSD(upload_joints, lock_scale_if_joint_position); } if (!decomp.mBaseHull.empty() || @@ -1588,6 +679,14 @@ LLSD LLModel::writeModel( model[LLModel::LOD_PHYSICS] = NULL; } } + else if (submodel_id) + { + const LLModel::Decomposition fake_decomp; + mdl["secondary"] = true; + mdl["submodel_id"] = submodel_id; + mdl["physics_convex"] = fake_decomp.asLLSD(); + model[LLModel::LOD_PHYSICS] = NULL; + } if (as_slm) { //save material list names @@ -1599,7 +698,7 @@ LLSD LLModel::writeModel( for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx) { - if (model[idx] && model[idx]->getNumVolumeFaces() > 0) + if (model[idx] && (model[idx]->getNumVolumeFaces() > 0) && model[idx]->getVolumeFace(0).mPositions != NULL) { LLVector3 min_pos = LLVector3(model[idx]->getVolumeFace(0).mPositions[0].getF32ptr()); LLVector3 max_pos = min_pos; @@ -1684,11 +783,11 @@ LLSD LLModel::writeModel( } } - F32* src_tc = (F32*) face.mTexCoords[j].mV; - //texcoord if (face.mTexCoords) { + F32* src_tc = (F32*) face.mTexCoords[j].mV; + for (U32 k = 0; k < 2; ++k) { //for each component //convert to 16-bit normalized @@ -1832,6 +931,11 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BO } } + if (mdl.has("submodel_id")) + { //write out submodel id + header["submodel_id"] = (LLSD::Integer)mdl["submodel_id"]; + } + std::string out[MODEL_NAMES_LENGTH]; for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++) @@ -1905,8 +1009,11 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos) { //no exact match found, get closest point const F32 epsilon = 1e-5f; weight_map::iterator iter_up = mSkinWeights.lower_bound(pos); - weight_map::iterator iter_down = ++iter_up; - + weight_map::iterator iter_down = iter_up; + if (iter_up != mSkinWeights.end()) + { + iter_down = ++iter_up; + } weight_map::iterator best = iter_up; F32 min_dist = (iter->first - pos).magVec(); @@ -2015,21 +1122,20 @@ bool LLModel::loadModel(std::istream& is) } } - std::string nm[] = - { + mSubmodelID = header.has("submodel_id") ? header["submodel_id"].asInteger() : false; + + static const std::array lod_name = {{ "lowest_lod", "low_lod", "medium_lod", "high_lod", "physics_mesh", - }; + }}; - const S32 MODEL_LODS = 5; + S32 lod = llclamp((S32) mDetail, 0, (S32)lod_name.size() - 1); - S32 lod = llclamp((S32) mDetail, 0, MODEL_LODS); - - if (header[nm[lod]]["offset"].asInteger() == -1 || - header[nm[lod]]["size"].asInteger() == 0 ) + if (header[lod_name[lod]]["offset"].asInteger() == -1 || + header[lod_name[lod]]["size"].asInteger() == 0 ) { //cannot load requested LOD LL_WARNS() << "LoD data is invalid!" << LL_ENDL; return false; @@ -2038,23 +1144,23 @@ bool LLModel::loadModel(std::istream& is) bool has_skin = header["skin"]["offset"].asInteger() >=0 && header["skin"]["size"].asInteger() > 0; - if (lod == LLModel::LOD_HIGH) + if ((lod == LLModel::LOD_HIGH) && !mSubmodelID) { //try to load skin info and decomp info std::ios::pos_type cur_pos = is.tellg(); loadSkinInfo(header, is); is.seekg(cur_pos); } - if (lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS) + if ((lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS) && !mSubmodelID) { std::ios::pos_type cur_pos = is.tellg(); loadDecomposition(header, is); is.seekg(cur_pos); } - is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur); + is.seekg(header[lod_name[lod]]["offset"].asInteger(), std::ios_base::cur); - if (unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger())) + if (unpackVolumeFaces(is, header[lod_name[lod]]["size"].asInteger())) { if (has_skin) { @@ -2112,7 +1218,7 @@ bool LLModel::isMaterialListSubset( LLModel* ref ) for (S32 dst = 0; dst < refCnt; ++dst) { - //LL_INFOS() <mMaterialList[dst]<mMaterialList[dst]<mMaterialList[dst]; if ( foundRef ) @@ -2120,8 +1226,10 @@ bool LLModel::isMaterialListSubset( LLModel* ref ) break; } } + if (!foundRef) { + LL_INFOS() << "Could not find material " << mMaterialList[src] << " in reference model " << ref->mLabel << LL_ENDL; return false; } } @@ -2157,7 +1265,7 @@ bool LLModel::matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCn bool isASubset = isMaterialListSubset( ref ); if ( !isASubset ) { - LL_INFOS() <<"Material of model is not a subset of reference."<mMaterialList[i]] = i; - if (!reorder) - { //if any material name does not match reference, we need to reorder - reorder = ref->mMaterialList[i] != mMaterialList[i]; - } + //if any material name does not match reference, we need to reorder + reorder |= ref->mMaterialList[i] != mMaterialList[i]; base_mat.insert(ref->mMaterialList[i]); cur_mat.insert(mMaterialList[i]); } - if (reorder && - base_mat == cur_mat) //don't reorder if material name sets don't match + if (reorder && (base_mat == cur_mat)) //don't reorder if material name sets don't match { std::vector new_face_list; - new_face_list.resize(mVolumeFaces.size()); + new_face_list.resize(mMaterialList.size()); std::vector new_material_list; - new_material_list.resize(mVolumeFaces.size()); + new_material_list.resize(mMaterialList.size()); //rebuild face list so materials have the same order //as the reference model for (U32 i = 0; i < mMaterialList.size(); ++i) { U32 ref_idx = index_map[mMaterialList[i]]; - new_face_list[ref_idx] = mVolumeFaces[i]; + if (i < mVolumeFaces.size()) + { + new_face_list[ref_idx] = mVolumeFaces[i]; + } new_material_list[ref_idx] = mMaterialList[i]; } llassert(new_material_list == ref->mMaterialList); mVolumeFaces = new_face_list; - } - //override material list with reference model ordering - mMaterialList = ref->mMaterialList; + //override material list with reference model ordering + mMaterialList = ref->mMaterialList; + } + return true; } @@ -2237,7 +1346,7 @@ bool LLModel::loadDecomposition(LLSD& header, std::istream& is) S32 offset = header["physics_convex"]["offset"].asInteger(); S32 size = header["physics_convex"]["size"].asInteger(); - if (offset >= 0 && size > 0) + if (offset >= 0 && size > 0 && !mSubmodelID) { is.seekg(offset, std::ios_base::cur); @@ -2253,8 +1362,19 @@ bool LLModel::loadDecomposition(LLSD& header, std::istream& is) return true; } +LLMeshSkinInfo::LLMeshSkinInfo(): + mPelvisOffset(0.0), + mLockScaleIfJointPosition(false), + mInvalidJointsScrubbed(false), + mJointNumsInitialized(false) +{ +} -LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin) +LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin): + mPelvisOffset(0.0), + mLockScaleIfJointPosition(false), + mInvalidJointsScrubbed(false), + mJointNumsInitialized(false) { fromLLSD(skin); } @@ -2263,10 +1383,11 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin) { if (skin.has("joint_names")) { - const U32 joint_count = llmin((U32)skin["joint_names"].size(),(U32)64); + const U32 joint_count = skin["joint_names"].size(); for (U32 i = 0; i < joint_count; ++i) { mJointNames.push_back(skin["joint_names"][i]); + mJointNums.push_back(-1); } } @@ -2319,9 +1440,18 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin) { mPelvisOffset = skin["pelvis_offset"].asReal(); } + + if (skin.has("lock_scale_if_joint_position")) + { + mLockScaleIfJointPosition = skin["lock_scale_if_joint_position"].asBoolean(); + } + else + { + mLockScaleIfJointPosition = false; + } } -LLSD LLMeshSkinInfo::asLLSD(bool include_joints) const +LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_position) const { LLSD ret; @@ -2359,6 +1489,11 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints) const } } + if (lock_scale_if_joint_position) + { + ret["lock_scale_if_joint_position"] = lock_scale_if_joint_position; + } + ret["pelvis_offset"] = mPelvisOffset; } @@ -2452,7 +1587,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp) range = max-min; - U16 count = position.size()/6; + size_t count = position.size()/6; for (U32 j = 0; j < count; ++j) { @@ -2646,3 +1781,228 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs) } } +bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance) +{ + // small area check + { + LLVector4a edge1; edge1.setSub( a, b ); + LLVector4a edge2; edge2.setSub( a, c ); + ////////////////////////////////////////////////////////////////////////// + /// Linden Modified + ////////////////////////////////////////////////////////////////////////// + + // If no one edge is more than 10x longer than any other edge, we weaken + // the tolerance by a factor of 1e-4f. + + LLVector4a edge3; edge3.setSub( c, b ); + const F32 len1sq = edge1.dot3(edge1).getF32(); + const F32 len2sq = edge2.dot3(edge2).getF32(); + const F32 len3sq = edge3.dot3(edge3).getF32(); + bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq); + bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq); + bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq); + if ( abOK && acOK && cbOK ) + { + tolerance *= 1e-4f; + } + + ////////////////////////////////////////////////////////////////////////// + /// End Modified + ////////////////////////////////////////////////////////////////////////// + + LLVector4a cross; cross.setCross3( edge1, edge2 ); + + LLVector4a edge1b; edge1b.setSub( b, a ); + LLVector4a edge2b; edge2b.setSub( b, c ); + LLVector4a crossb; crossb.setCross3( edge1b, edge2b ); + + if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance )) + { + return true; + } + } + + // point triangle distance check + { + LLVector4a Q; Q.setSub(a, b); + LLVector4a R; R.setSub(c, b); + + const F32 QQ = dot3fpu(Q, Q); + const F32 RR = dot3fpu(R, R); + const F32 QR = dot3fpu(R, Q); + + volatile F32 QQRR = QQ * RR; + volatile F32 QRQR = QR * QR; + F32 Det = (QQRR - QRQR); + + if( Det == 0.0f ) + { + return true; + } + } + + return false; +} + +bool validate_face(const LLVolumeFace& face) +{ + for (S32 i = 0; i < face.mNumIndices; ++i) + { + if (face.mIndices[i] >= face.mNumVertices) + { + LL_WARNS() << "Face has invalid index." << LL_ENDL; + LL_WARNS() << "face.mIndices[" << i << "]=" << face.mIndices[i] << " face.mNumVertices=" << face.mNumVertices << LL_ENDL; + return false; + } + } + + if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0) + { + LL_WARNS() << "Face has invalid number of indices." << LL_ENDL; + return false; + } + + /*const LLVector4a scale(0.5f); + + for (U32 i = 0; i < face.mNumIndices; i+=3) + { + U16 idx1 = face.mIndices[i]; + U16 idx2 = face.mIndices[i+1]; + U16 idx3 = face.mIndices[i+2]; + + LLVector4a v1; v1.setMul(face.mPositions[idx1], scale); + LLVector4a v2; v2.setMul(face.mPositions[idx2], scale); + LLVector4a v3; v3.setMul(face.mPositions[idx3], scale); + + if (ll_is_degenerate(v1,v2,v3)) + { + llwarns << "Degenerate face found!" << LL_ENDL; + return false; + } + }*/ + + return true; +} + +bool validate_model(const LLModel* mdl) +{ + if (mdl->getNumVolumeFaces() == 0) + { + LL_WARNS() << "Model has no faces!" << LL_ENDL; + return false; + } + + for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + { + if (mdl->getVolumeFace(i).mNumVertices == 0) + { + LL_WARNS() << "Face has no vertices." << LL_ENDL; + return false; + } + + if (mdl->getVolumeFace(i).mNumIndices == 0) + { + LL_WARNS() << "Face has no indices." << LL_ENDL; + return false; + } + + if (!validate_face(mdl->getVolumeFace(i))) + { + return false; + } + } + + return true; +} + +LLModelInstance::LLModelInstance(LLSD& data) + : LLModelInstanceBase() +{ + mLocalMeshID = data["mesh_id"].asInteger(); + mLabel = data["label"].asString(); + mTransform.setValue(data["transform"]); + + for (U32 i = 0; i < (U32)data["material"].size(); ++i) + { + LLImportMaterial mat(data["material"][i]); + mMaterial[mat.mBinding] = mat; + } +} + + +LLSD LLModelInstance::asLLSD() +{ + LLSD ret; + + ret["mesh_id"] = mModel->mLocalID; + ret["label"] = mLabel; + ret["transform"] = mTransform.getValue(); + + U32 i = 0; + for (std::map::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter) + { + ret["material"][i++] = iter->second.asLLSD(); + } + + return ret; +} + + +LLImportMaterial::~LLImportMaterial() +{ +} + +LLImportMaterial::LLImportMaterial(LLSD& data) +{ + mDiffuseMapFilename = data["diffuse"]["filename"].asString(); + mDiffuseMapLabel = data["diffuse"]["label"].asString(); + mDiffuseColor.setValue(data["diffuse"]["color"]); + mFullbright = data["fullbright"].asBoolean(); + mBinding = data["binding"].asString(); +} + + +LLSD LLImportMaterial::asLLSD() +{ + LLSD ret; + + ret["diffuse"]["filename"] = mDiffuseMapFilename; + ret["diffuse"]["label"] = mDiffuseMapLabel; + ret["diffuse"]["color"] = mDiffuseColor.getValue(); + ret["fullbright"] = mFullbright; + ret["binding"] = mBinding; + + return ret; +} + +bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const +{ + + if (mDiffuseMapID != rhs.mDiffuseMapID) + { + return mDiffuseMapID < rhs.mDiffuseMapID; + } + + if (mDiffuseMapFilename != rhs.mDiffuseMapFilename) + { + return mDiffuseMapFilename < rhs.mDiffuseMapFilename; + } + + if (mDiffuseMapLabel != rhs.mDiffuseMapLabel) + { + return mDiffuseMapLabel < rhs.mDiffuseMapLabel; + } + + if (mDiffuseColor != rhs.mDiffuseColor) + { + return mDiffuseColor < rhs.mDiffuseColor; + } + + if (mBinding != rhs.mBinding) + { + return mBinding < rhs.mBinding; + } + + return mFullbright < rhs.mFullbright; +} + diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index f6063165d3..9b1df2a0e1 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -31,6 +31,7 @@ #include "llvolume.h" #include "v4math.h" #include "m4math.h" +#include class daeElement; class domMesh; @@ -41,18 +42,22 @@ class domMesh; class LLMeshSkinInfo { public: + LLMeshSkinInfo(); + LLMeshSkinInfo(LLSD& data); + void fromLLSD(LLSD& data); + LLSD asLLSD(bool include_joints, bool lock_scale_if_joint_position) const; + LLUUID mMeshID; std::vector mJointNames; + mutable std::vector mJointNums; std::vector mInvBindMatrix; std::vector mAlternateBindMatrix; - std::map mJointMap; - LLMeshSkinInfo() { } - LLMeshSkinInfo(LLSD& data); - void fromLLSD(LLSD& data); - LLSD asLLSD(bool include_joints) const; LLMatrix4 mBindShapeMatrix; float mPelvisOffset; + bool mLockScaleIfJointPosition; + bool mInvalidJointsScrubbed; + bool mJointNumsInitialized; }; class LLModel : public LLVolume @@ -137,24 +142,23 @@ class LLModel : public LLVolume const LLModel::Decomposition& decomp, BOOL upload_skin, BOOL upload_joints, + BOOL lock_scale_if_joint_position, BOOL nowrite = FALSE, - BOOL as_slm = FALSE); + BOOL as_slm = FALSE, + int submodel_id = 0); static LLSD writeModelToStream( std::ostream& ostr, LLSD& mdl, BOOL nowrite = FALSE, BOOL as_slm = FALSE); + + void ClearFacesAndMaterials() { mVolumeFaces.clear(); mMaterialList.clear(); } - static LLModel* loadModelFromDomMesh(domMesh* mesh); - static std::string getElementLabel(daeElement* element); std::string getName() const; std::string getMetric() const {return mMetric;} EModelStatus getStatus() const {return mStatus;} static std::string getStatusString(U32 status) ; - void appendFaces(LLModel* model, LLMatrix4& transform, LLMatrix4& normal_transform); - void appendFace(const LLVolumeFace& src_face, std::string src_material, LLMatrix4& mat, LLMatrix4& norm_mat); - void setNumVolumeFaces(S32 count); void setVolumeFaceData( S32 f, @@ -169,7 +173,9 @@ class LLModel : public LLVolume void addFace(const LLVolumeFace& face); + void sortVolumeFacesByMaterialName(); void normalizeVolumeFaces(); + void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL); void optimizeVolumeFaces(); void offsetMesh( const LLVector3& pivotPoint ); void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out); @@ -181,7 +187,11 @@ class LLModel : public LLVolume bool isMaterialListSubset( LLModel* ref ); bool needToAddFaces( LLModel* ref, int& refFaceCnt, int& modelFaceCnt ); - std::vector mMaterialList; + typedef std::vector material_list; + + material_list mMaterialList; + + material_list& getMaterialList() { return mMaterialList; } //data used for skin weights class JointWeight @@ -274,9 +284,115 @@ class LLModel : public LLVolume Decomposition mPhysics; EModelStatus mStatus ; + + int mSubmodelID; +}; + +typedef std::vector > model_list; +typedef std::queue > model_queue; + +class LLModelMaterialBase +{ +public: + std::string mDiffuseMapFilename; + std::string mDiffuseMapLabel; + std::string mBinding; + LLColor4 mDiffuseColor; + bool mFullbright; + + LLModelMaterialBase() + : mFullbright(false) + { + mDiffuseColor.set(1,1,1,1); + } +}; + +class LLImportMaterial : public LLModelMaterialBase +{ +public: + friend class LLMeshUploadThread; + friend class LLModelPreview; + + bool operator<(const LLImportMaterial ¶ms) const; + + LLImportMaterial() : LLModelMaterialBase() + { + mDiffuseColor.set(1,1,1,1); + } + + LLImportMaterial(LLSD& data); + virtual ~LLImportMaterial(); + + LLSD asLLSD(); + + const LLUUID& getDiffuseMap() const { return mDiffuseMapID; } + void setDiffuseMap(const LLUUID& texId) { mDiffuseMapID = texId; } + protected: - void addVolumeFacesFromDomMesh(domMesh* mesh); - virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh); + + LLUUID mDiffuseMapID; + void* mOpaqueData; // allow refs to viewer/platform-specific structs for each material + // currently only stores an LLPointer< LLViewerFetchedTexture > > to + // maintain refs to textures associated with each material for free + // ref counting. +}; + +typedef std::map material_map; + +class LLModelInstanceBase +{ +public: + LLPointer mModel; + LLPointer mLOD[5]; + LLUUID mMeshID; + + LLMatrix4 mTransform; + material_map mMaterial; + + LLModelInstanceBase(LLModel* model, LLMatrix4& transform, material_map& materials) + : mModel(model), mTransform(transform), mMaterial(materials) + { + } + + LLModelInstanceBase() + : mModel(NULL) + { + } +}; + +typedef std::vector model_instance_list; + +class LLModelInstance : public LLModelInstanceBase +{ +public: + std::string mLabel; + LLUUID mMeshID; + S32 mLocalMeshID; + + LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, material_map& materials) + : LLModelInstanceBase(model, transform, materials), mLabel(label) + { + mLocalMeshID = -1; + } + + LLModelInstance(LLSD& data); + + LLSD asLLSD(); }; +#define LL_DEGENERACY_TOLERANCE 1e-7f + +inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b) +{ + volatile F32 p0 = a[0] * b[0]; + volatile F32 p1 = a[1] * b[1]; + volatile F32 p2 = a[2] * b[2]; + return p0 + p1 + p2; +} + +bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE); + +bool validate_face(const LLVolumeFace& face); +bool validate_model(const LLModel* mdl); + #endif //LL_LLMODEL_H diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp new file mode 100644 index 0000000000..50e36100d6 --- /dev/null +++ b/indra/llprimitive/llmodelloader.cpp @@ -0,0 +1,487 @@ +/** + * @file llmodelloader.cpp + * @brief LLModelLoader class implementation + * + * $LicenseInfo:firstyear=2004&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 "llmodelloader.h" +#include "llsdserialize.h" +#include "lljoint.h" +#include "llcallbacklist.h" + +#include "llmatrix4a.h" +#include +#include "apr_time.h" + +std::list LLModelLoader::sActiveLoaderList; + +void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform) +{ + LLVector4a box[] = + { + LLVector4a(-1, 1,-1), + LLVector4a(-1, 1, 1), + LLVector4a(-1,-1,-1), + LLVector4a(-1,-1, 1), + LLVector4a( 1, 1,-1), + LLVector4a( 1, 1, 1), + LLVector4a( 1,-1,-1), + LLVector4a( 1,-1, 1), + }; + + for (S32 j = 0; j < model->getNumVolumeFaces(); ++j) + { + const LLVolumeFace& face = model->getVolumeFace(j); + + LLVector4a center; + center.setAdd(face.mExtents[0], face.mExtents[1]); + center.mul(0.5f); + LLVector4a size; + size.setSub(face.mExtents[1],face.mExtents[0]); + size.mul(0.5f); + + for (U32 i = 0; i < 8; i++) + { + LLVector4a t; + t.setMul(size, box[i]); + t.add(center); + + LLVector4a v; + + mat.affineTransform(t, v); + + if (first_transform) + { + first_transform = FALSE; + min = max = v; + } + else + { + update_min_max(min, max, v); + } + } + } +} + +void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform) +{ + LLVector4a mina, maxa; + LLMatrix4a mata; + + mata.loadu(mat); + mina.load3(min.mV); + maxa.load3(max.mV); + + stretch_extents(model, mata, mina, maxa, first_transform); + + min.set(mina.getF32ptr()); + max.set(maxa.getF32ptr()); +} + +//----------------------------------------------------------------------------- +// LLModelLoader +//----------------------------------------------------------------------------- +LLModelLoader::LLModelLoader( + std::string filename, + S32 lod, + load_callback_t load_cb, + joint_lookup_func_t joint_lookup_func, + texture_load_func_t texture_load_func, + state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointTransformMap, + JointNameSet& jointsFromNodes, + JointMap& legalJointNamesMap, + U32 maxJointsPerMesh) +: mJointList( jointTransformMap ) +, mJointsFromNode( jointsFromNodes ) +, LLThread("Model Loader") +, mFilename(filename) +, mLod(lod) +, mTrySLM(false) +, mFirstTransform(TRUE) +, mNumOfFetchingTextures(0) +, mLoadCallback(load_cb) +, mJointLookupFunc(joint_lookup_func) +, mTextureLoadFunc(texture_load_func) +, mStateCallback(state_cb) +, mOpaqueData(opaque_userdata) +, mRigValidJointUpload(true) +, mLegacyRigValid(true) +, mNoNormalize(false) +, mNoOptimize(false) +, mCacheOnlyHitIfRigged(false) +, mMaxJointsPerMesh(maxJointsPerMesh) +, mJointMap(legalJointNamesMap) +{ + assert_main_thread(); + sActiveLoaderList.push_back(this) ; +} + +LLModelLoader::~LLModelLoader() +{ + assert_main_thread(); + sActiveLoaderList.remove(this); +} + +void LLModelLoader::run() +{ + doLoadModel(); + doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this)); +} + +// static +bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::string& slm_filename) +{ + slm_filename = model_filename; + + std::string::size_type i = model_filename.rfind("."); + if (i != std::string::npos) + { + slm_filename.replace(i, model_filename.size()-1, ".slm"); + return true; + } + else + { + return false; + } +} + +bool LLModelLoader::doLoadModel() +{ + //first, look for a .slm file of the same name that was modified later + //than the .dae + + if (mTrySLM) + { + std::string slm_filename; + if (getSLMFilename(mFilename, slm_filename)) + { + llstat slm_status; + if (LLFile::stat(slm_filename, &slm_status) == 0) + { //slm file exists + llstat dae_status; + if (LLFile::stat(mFilename, &dae_status) != 0 || + dae_status.st_mtime < slm_status.st_mtime) + { + if (loadFromSLM(slm_filename)) + { //slm successfully loaded, if this fails, fall through and + //try loading from dae + + mLod = -1; //successfully loading from an slm implicitly sets all + //LoDs + return true; + } + } + } + } + } + + return OpenFile(mFilename); +} + +void LLModelLoader::setLoadState(U32 state) +{ + mStateCallback(state, mOpaqueData); +} + +bool LLModelLoader::loadFromSLM(const std::string& filename) +{ + //only need to populate mScene with data from slm + llstat stat; + + if (LLFile::stat(filename, &stat)) + { //file does not exist + return false; + } + + S32 file_size = (S32) stat.st_size; + + llifstream ifstream(filename.c_str(), std::ifstream::in | std::ifstream::binary); + LLSD data; + LLSDSerialize::fromBinary(data, ifstream, file_size); + ifstream.close(); + + //build model list for each LoD + model_list model[LLModel::NUM_LODS]; + + if (data["version"].asInteger() != SLM_SUPPORTED_VERSION) + { //unsupported version + return false; + } + + LLSD& mesh = data["mesh"]; + + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + + for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + { + for (U32 i = 0; i < (U32)mesh.size(); ++i) + { + std::stringstream str(mesh[i].asString()); + LLPointer loaded_model = new LLModel(volume_params, (F32) lod); + if (loaded_model->loadModel(str)) + { + loaded_model->mLocalID = i; + model[lod].push_back(loaded_model); + + if (lod == LLModel::LOD_HIGH) + { + if (!loaded_model->mSkinInfo.mJointNames.empty()) + { + //check to see if rig is valid + critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames ); + } + else if (mCacheOnlyHitIfRigged) + { + return false; + } + } + } + } + } + + if (model[LLModel::LOD_HIGH].empty()) + { //failed to load high lod + return false; + } + + //load instance list + model_instance_list instance_list; + + LLSD& instance = data["instance"]; + + for (U32 i = 0; i < (U32)instance.size(); ++i) + { + //deserialize instance list + instance_list.push_back(LLModelInstance(instance[i])); + + //match up model instance pointers + S32 idx = instance_list[i].mLocalMeshID; + std::string instance_label = instance_list[i].mLabel; + + for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + { + if (!model[lod].empty()) + { + if (idx >= (S32)model[lod].size()) + { + if (model[lod].size()) + { + instance_list[i].mLOD[lod] = model[lod][0]; + } + else + { + instance_list[i].mLOD[lod] = NULL; + } + continue; + } + + if (model[lod][idx] + && model[lod][idx]->mLabel.empty() + && !instance_label.empty()) + { + // restore model names + std::string name = instance_label; + switch (lod) + { + case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; + case LLModel::LOD_LOW: name += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + model[lod][idx]->mLabel = name; + } + + instance_list[i].mLOD[lod] = model[lod][idx]; + } + } + + if (!instance_list[i].mModel) + instance_list[i].mModel = model[LLModel::LOD_HIGH][idx]; + } + + // Set name for UI to use + std::string name = data["name"]; + if (!name.empty()) + { + model[LLModel::LOD_HIGH][0]->mRequestedLabel = name; + } + + + //convert instance_list to mScene + mFirstTransform = TRUE; + for (U32 i = 0; i < instance_list.size(); ++i) + { + LLModelInstance& cur_instance = instance_list[i]; + mScene[cur_instance.mTransform].push_back(cur_instance); + stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform); + } + + setLoadState( DONE ); + + return true; +} + +//static +bool LLModelLoader::isAlive(LLModelLoader* loader) +{ + if(!loader) + { + return false ; + } + + std::list::iterator iter = sActiveLoaderList.begin() ; + for(; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter) ; + + return *iter == loader ; +} + +void LLModelLoader::loadModelCallback() +{ + mLoadCallback(mScene,mModelList,mLod, mOpaqueData); + + while (!isStopped()) + { //wait until this thread is stopped before deleting self + apr_sleep(100); + } + + //double check if "this" is valid before deleting it, in case it is aborted during running. + if(!isAlive(this)) + { + return ; + } + + delete this; +} + +//----------------------------------------------------------------------------- +// critiqueRigForUploadApplicability() +//----------------------------------------------------------------------------- +void LLModelLoader::critiqueRigForUploadApplicability( const std::vector &jointListFromAsset ) +{ + //Determines the following use cases for a rig: + //1. It is suitable for upload with skin weights & joint positions, or + //2. It is suitable for upload as standard av with just skin weights + + bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset ); + bool isRigLegacyOK = isRigLegacy( jointListFromAsset ); + + //It's OK that both could end up being true, both default to false + + // Both start out as true and are forced to false if any mesh in + // the model file is not vald by that criterion. Note that a file + // can contain multiple meshes. + if ( !isJointPositionUploadOK ) + { + // This starts out true, becomes false if false for any loaded + // mesh. + setRigValidForJointPositionUpload( false ); + } + + if ( !isRigLegacyOK) + { + // This starts out true, becomes false if false for any loaded + // mesh. + setLegacyRigValid( false ); + } + +} + +//----------------------------------------------------------------------------- +// isRigLegacy() +//----------------------------------------------------------------------------- +bool LLModelLoader::isRigLegacy( const std::vector &jointListFromAsset ) +{ + //No joints in asset + if ( jointListFromAsset.size() == 0 ) + { + return false; + } + + // Too many joints in asset + if (jointListFromAsset.size()>mMaxJointsPerMesh) + { + LL_WARNS() << "Rigged to " << jointListFromAsset.size() << " joints, max is " << mMaxJointsPerMesh << LL_ENDL; + LL_WARNS() << "Skinning disabled due to too many joints" << LL_ENDL; + return false; + } + + // Unknown joints in asset + S32 unknown_joint_count = 0; + for (std::vector::const_iterator it = jointListFromAsset.begin(); + it != jointListFromAsset.end(); ++it) + { + if (mJointMap.find(*it)==mJointMap.end()) + { + LL_WARNS() << "Rigged to unrecognized joint name " << *it << LL_ENDL; + unknown_joint_count++; + } + } + if (unknown_joint_count>0) + { + LL_WARNS() << "Skinning disabled due to unknown joints" << LL_ENDL; + return false; + } + + return true; +} +//----------------------------------------------------------------------------- +// isRigSuitableForJointPositionUpload() +//----------------------------------------------------------------------------- +bool LLModelLoader::isRigSuitableForJointPositionUpload( const std::vector &jointListFromAsset ) +{ + return true; +} + + +//called in the main thread +void LLModelLoader::loadTextures() +{ + BOOL is_paused = isPaused() ; + pause() ; //pause the loader + + for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter) + { + for(U32 i = 0 ; i < iter->second.size(); i++) + { + for(std::map::iterator j = iter->second[i].mMaterial.begin(); + j != iter->second[i].mMaterial.end(); ++j) + { + LLImportMaterial& material = j->second; + + if(!material.mDiffuseMapFilename.empty()) + { + mNumOfFetchingTextures += mTextureLoadFunc(material, mOpaqueData); + } + } + } + } + + if(!is_paused) + { + unpause() ; + } +} diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h new file mode 100644 index 0000000000..033dc5fd04 --- /dev/null +++ b/indra/llprimitive/llmodelloader.h @@ -0,0 +1,211 @@ +/** + * @file llmodelloader.h + * @brief LLModelLoader class definition + * + * $LicenseInfo:firstyear=2004&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_LLMODELLOADER_H +#define LL_LLMODELLOADER_H + +#include "llmodel.h" +#include "llthread.h" +#include +#include + +class LLJoint; + +typedef std::map JointTransformMap; +typedef std::map:: iterator JointTransformMapIt; +typedef std::map JointMap; +typedef std::deque JointNameSet; + +const S32 SLM_SUPPORTED_VERSION = 3; +const S32 NUM_LOD = 4; + +class LLModelLoader : public LLThread +{ +public: + + typedef std::map material_map; + typedef std::vector > model_list; + typedef std::vector model_instance_list; + typedef std::map scene; + + // Callback with loaded model data and loaded LoD + // + typedef boost::function load_callback_t; + + // Function to provide joint lookup by name + // (within preview avi skeleton, for example) + // + typedef boost::function joint_lookup_func_t; + + // Func to load and associate material with all it's textures, + // returned value is the number of textures loaded + // intentionally non-const so func can modify material to + // store platform-specific data + // + typedef boost::function texture_load_func_t; + + // Callback to inform client of state changes + // during loading process (errors will be reported + // as state changes here as well) + // + typedef boost::function state_callback_t; + + typedef enum + { + STARTING = 0, + READING_FILE, + CREATING_FACES, + GENERATING_VERTEX_BUFFERS, + GENERATING_LOD, + DONE, + WARNING_BIND_SHAPE_ORIENTATION, + ERROR_PARSING, //basically loading failed + ERROR_MATERIALS, + ERROR_PASSWORD_REQUIRED, + ERROR_NEED_MORE_MEMORY, + ERROR_INVALID_FILE, + ERROR_LOADER_SETUP, + ERROR_INVALID_PARAMETERS, + ERROR_OUT_OF_RANGE, + ERROR_FILE_VERSION_INVALID, + ERROR_MODEL // this error should always be last in this list, error code is passed as ERROR_MODEL+error_code + } eLoadState; + + U32 mState; + std::string mFilename; + + S32 mLod; + + LLMatrix4 mTransform, mBindTransform; + BOOL mFirstTransform; + LLVector3 mExtents[2]; + + bool mTrySLM; + bool mCacheOnlyHitIfRigged; // ignore cached SLM if it does not contain rig info (and we want rig info) + + model_list mModelList; + scene mScene; + + typedef std::queue > model_queue; + + //queue of models that need a physics rep + model_queue mPhysicsQ; + + //map of avatar joints as named in COLLADA assets to internal joint names + JointMap mJointMap; + JointTransformMap& mJointList; + JointNameSet& mJointsFromNode; + U32 mMaxJointsPerMesh; + + LLModelLoader( + std::string filename, + S32 lod, + LLModelLoader::load_callback_t load_cb, + LLModelLoader::joint_lookup_func_t joint_lookup_func, + LLModelLoader::texture_load_func_t texture_load_func, + LLModelLoader::state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointTransformMap, + JointNameSet& jointsFromNodes, + JointMap& legalJointNamesMap, + U32 maxJointsPerMesh); + virtual ~LLModelLoader() ; + + virtual void setNoNormalize() { mNoNormalize = true; } + virtual void setNoOptimize() { mNoOptimize = true; } + + virtual void run(); + + static bool getSLMFilename(const std::string& model_filename, std::string& slm_filename); + + // Will try SLM or derived class OpenFile as appropriate + // + virtual bool doLoadModel(); + + // Derived classes need to provide their parsing of files here + // + virtual bool OpenFile(const std::string& filename) = 0; + + bool loadFromSLM(const std::string& filename); + + void loadModelCallback(); + void loadTextures() ; //called in the main thread. + void setLoadState(U32 state); + + + + S32 mNumOfFetchingTextures ; //updated in the main thread + bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread. + + bool verifyCount( int expected, int result ); + + //Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps) + void critiqueRigForUploadApplicability( const std::vector &jointListFromAsset ); + + //Determines if a rig is a legacy from the joint list + bool isRigLegacy( const std::vector &jointListFromAsset ); + + //Determines if a rig is suitable for upload + bool isRigSuitableForJointPositionUpload( const std::vector &jointListFromAsset ); + + const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; } + void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; } + + const bool isLegacyRigValid( void ) const { return mLegacyRigValid; } + void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; } + + //----------------------------------------------------------------------------- + // isNodeAJoint() + //----------------------------------------------------------------------------- + bool isNodeAJoint(const char* name) const + { + return name != NULL && mJointMap.find(name) != mJointMap.end(); + } + +protected: + + LLModelLoader::load_callback_t mLoadCallback; + LLModelLoader::joint_lookup_func_t mJointLookupFunc; + LLModelLoader::texture_load_func_t mTextureLoadFunc; + LLModelLoader::state_callback_t mStateCallback; + void* mOpaqueData; + + bool mRigValidJointUpload; + bool mLegacyRigValid; + + bool mNoNormalize; + bool mNoOptimize; + + JointTransformMap mJointTransformMap; + + static std::list sActiveLoaderList; + static bool isAlive(LLModelLoader* loader) ; +}; +class LLMatrix4a; +void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform); +void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform); + +#endif // LL_LLMODELLOADER_H diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index e9c804b268..c37cc05b4f 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -40,6 +40,7 @@ #include "llprimtexturelist.h" #include "imageids.h" #include "llmaterialid.h" +#include "llvolume.h" /** * exported constants @@ -174,7 +175,7 @@ LLPrimitive::~LLPrimitive() { clearTextureList(); // Cleanup handled by volume manager - if (mVolumep) + if (mVolumep && sVolumeManager) { sVolumeManager->unrefVolume(mVolumep); } @@ -321,6 +322,11 @@ S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMateri return mTextureList.setMaterialParams(index, pMaterialParams); } +LLMaterialPtr LLPrimitive::getTEMaterialParams(const U8 index) +{ + return mTextureList.getMaterialParams(index); +} + //=============================================================== S32 LLPrimitive::setTEBumpShinyFullbright(const U8 index, const U8 bump) { @@ -580,7 +586,7 @@ U8 LLPrimitive::pCodeToLegacy(const LLPCode pcode) // static -// Don't crash or llerrs here! This function is used for debug strings. +// Don't crash or LL_ERRS() here! This function is used for debug strings. std::string LLPrimitive::pCodeToString(const LLPCode pcode) { std::string pcode_string; @@ -723,6 +729,16 @@ S32 face_index_from_id(LLFaceID face_ID, const std::vector& fac BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume) { + if (NO_LOD == detail) + { + // build the new object + setChanged(GEOMETRY); + sVolumeManager->unrefVolume(mVolumep); + mVolumep = new LLVolume(volume_params, 1, TRUE, TRUE); + setNumTEs(mVolumep->getNumFaces()); + return FALSE; + } + LLVolume *volumep; if (unique_volume) { @@ -987,8 +1003,6 @@ BOOL LLPrimitive::setMaterial(U8 material) } } -const F32 LL_MAX_SCALE_S = 100.0f; -const F32 LL_MAX_SCALE_T = 100.0f; S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const { S32 face_index; @@ -1023,14 +1037,26 @@ S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_fa } //assign exception faces to cur_ptr - if (exception_faces >= (0x1 << 7)) + if (exception_faces >= ((U64)0x1 << 7)) { - if (exception_faces >= (0x1 << 14)) + if (exception_faces >= ((U64)0x1 << 14)) { - if (exception_faces >= (0x1 << 21)) + if (exception_faces >= ((U64)0x1 << 21)) { - if (exception_faces >= (0x1 << 28)) + if (exception_faces >= ((U64)0x1 << 28)) { + if (exception_faces >= ((U64)0x1 << 35)) + { + if (exception_faces >= ((U64)0x1 << 42)) + { + if (exception_faces >= ((U64)0x1 << 49)) + { + *cur_ptr++ = (U8)(((exception_faces >> 49) & 0x7F) | 0x80); + } + *cur_ptr++ = (U8)(((exception_faces >> 42) & 0x7F) | 0x80); + } + *cur_ptr++ = (U8)(((exception_faces >> 35) & 0x7F) | 0x80); + } *cur_ptr++ = (U8)(((exception_faces >> 28) & 0x7F) | 0x80); } *cur_ptr++ = (U8)(((exception_faces >> 21) & 0x7F) | 0x80); @@ -1039,6 +1065,7 @@ S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_fa } *cur_ptr++ = (U8)(((exception_faces >> 7) & 0x7F) | 0x80); } + *cur_ptr++ = (U8)(exception_faces & 0x7F); @@ -1098,7 +1125,7 @@ S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 dat // Includes information about image ID, color, scale S,T, offset S,T and rotation BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const { - const U32 MAX_TES = 32; + const U32 MAX_TES = 45; U8 image_ids[MAX_TES*16]; U8 colors[MAX_TES*4]; @@ -1183,7 +1210,7 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const { - const U32 MAX_TES = 32; + const U32 MAX_TES = 45; U8 image_ids[MAX_TES*16]; U8 colors[MAX_TES*4]; @@ -1387,7 +1414,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) { // use a negative block_num to indicate a single-block read (a non-variable block) S32 retval = 0; - const U32 MAX_TES = 32; + const U32 MAX_TES = 45; // Avoid construction of 32 UUIDs per call static LLUUID image_ids[MAX_TES]; @@ -1573,6 +1600,8 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size) return (size == 17); case PARAMS_LIGHT_IMAGE: return (size == 28); + case PARAMS_EXTENDED_MESH: + return (size == 4); } return FALSE; @@ -1843,9 +1872,12 @@ BOOL LLSculptParams::pack(LLDataPacker &dp) const BOOL LLSculptParams::unpack(LLDataPacker &dp) { - dp.unpackUUID(mSculptTexture, "texture"); - dp.unpackU8(mSculptType, "type"); - + U8 type; + LLUUID id; + dp.unpackUUID(id, "texture"); + dp.unpackU8(type, "type"); + + setSculptTexture(id, type); return TRUE; } @@ -1870,8 +1902,7 @@ bool LLSculptParams::operator==(const LLNetworkData& data) const void LLSculptParams::copy(const LLNetworkData& data) { const LLSculptParams *param = (LLSculptParams*)&data; - mSculptTexture = param->mSculptTexture; - mSculptType = param->mSculptType; + setSculptTexture(param->mSculptTexture, param->mSculptType); } @@ -1889,20 +1920,38 @@ LLSD LLSculptParams::asLLSD() const bool LLSculptParams::fromLLSD(LLSD& sd) { const char *w; - w = "texture"; + U8 type; + w = "type"; if (sd.has(w)) { - setSculptTexture( sd[w] ); - } else goto fail; - w = "type"; + type = sd[w].asInteger(); + } + else return false; + + w = "texture"; if (sd.has(w)) { - setSculptType( (U8)sd[w].asInteger() ); - } else goto fail; - + setSculptTexture(sd[w], type); + } + else return false; + return true; - fail: - return false; +} + +void LLSculptParams::setSculptTexture(const LLUUID& texture_id, U8 sculpt_type) +{ + U8 type = sculpt_type & LL_SCULPT_TYPE_MASK; + U8 flags = sculpt_type & LL_SCULPT_FLAG_MASK; + if (sculpt_type != (type | flags) || type > LL_SCULPT_TYPE_MAX) + { + mSculptTexture.set(SCULPT_DEFAULT_TEXTURE); + mSculptType = LL_SCULPT_TYPE_SPHERE; + } + else + { + mSculptTexture = texture_id; + mSculptType = sculpt_type; + } } //============================================================================ @@ -1980,3 +2029,67 @@ bool LLLightImageParams::fromLLSD(LLSD& sd) return false; } + +//============================================================================ + +LLExtendedMeshParams::LLExtendedMeshParams() +{ + mType = PARAMS_EXTENDED_MESH; + mFlags = 0; +} + +BOOL LLExtendedMeshParams::pack(LLDataPacker &dp) const +{ + dp.packU32(mFlags, "flags"); + + return TRUE; +} + +BOOL LLExtendedMeshParams::unpack(LLDataPacker &dp) +{ + dp.unpackU32(mFlags, "flags"); + + return TRUE; +} + +bool LLExtendedMeshParams::operator==(const LLNetworkData& data) const +{ + if (data.mType != PARAMS_EXTENDED_MESH) + { + return false; + } + + const LLExtendedMeshParams *param = (const LLExtendedMeshParams*)&data; + if ( (param->mFlags != mFlags) ) + { + return false; + } + + return true; +} + +void LLExtendedMeshParams::copy(const LLNetworkData& data) +{ + const LLExtendedMeshParams *param = (LLExtendedMeshParams*)&data; + mFlags = param->mFlags; +} + +LLSD LLExtendedMeshParams::asLLSD() const +{ + LLSD sd; + + sd["flags"] = LLSD::Integer(mFlags); + + return sd; +} + +bool LLExtendedMeshParams::fromLLSD(LLSD& sd) +{ + if (sd.has("flags")) + { + setFlags( sd["flags"].asInteger()); + return true; + } + + return false; +} diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 82481feaac..d69c731990 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -106,6 +106,8 @@ class LLNetworkData PARAMS_LIGHT_IMAGE = 0x40, PARAMS_RESERVED = 0x50, // Used on server-side PARAMS_MESH = 0x60, + PARAMS_EXTENDED_MESH = 0x70, + PARAMS_MAX = PARAMS_EXTENDED_MESH }; public: @@ -259,9 +261,8 @@ class LLSculptParams : public LLNetworkData operator LLSD() const { return asLLSD(); } bool fromLLSD(LLSD& sd); - void setSculptTexture(const LLUUID& id) { mSculptTexture = id; } + void setSculptTexture(const LLUUID& texture_id, U8 sculpt_type); LLUUID getSculptTexture() const { return mSculptTexture; } - void setSculptType(U8 type) { mSculptType = type; } U8 getSculptType() const { return mSculptType; } }; @@ -289,6 +290,27 @@ class LLLightImageParams : public LLNetworkData }; +class LLExtendedMeshParams : public LLNetworkData +{ +protected: + U32 mFlags; + +public: + static const U32 ANIMATED_MESH_ENABLED_FLAG = 0x1 << 0; + + LLExtendedMeshParams(); + /*virtual*/ BOOL pack(LLDataPacker &dp) const; + /*virtual*/ BOOL unpack(LLDataPacker &dp); + /*virtual*/ bool operator==(const LLNetworkData& data) const; + /*virtual*/ void copy(const LLNetworkData& data); + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + void setFlags(const U32& flags) { mFlags = flags; } + U32 getFlags() const { return mFlags; } + +}; // This code is not naming-standards compliant. Leaving it like this for // now to make the connection to code in @@ -298,7 +320,7 @@ class LLLightImageParams : public LLNetworkData // - Vir struct LLTEContents { - static const U32 MAX_TES = 32; + static const U32 MAX_TES = 45; U8 image_data[MAX_TES*16]; U8 colors[MAX_TES*4]; @@ -309,9 +331,9 @@ struct LLTEContents S16 image_rot[MAX_TES]; U8 bump[MAX_TES]; U8 media_flags[MAX_TES]; - U8 glow[MAX_TES]; + U8 glow[MAX_TES]; LLMaterialID material_ids[MAX_TES]; - + static const U32 MAX_TE_BUFFER = 4096; U8 packed_buffer[MAX_TE_BUFFER]; @@ -389,6 +411,8 @@ class LLPrimitive : public LLXform virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed virtual void setTESelected(const U8 te, bool sel); + LLMaterialPtr getTEMaterialParams(const U8 index); + void copyTEs(const LLPrimitive *primitive); S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const; S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); @@ -482,6 +506,11 @@ class LLPrimitive : public LLXform U32 mMiscFlags; // home for misc bools static LLVolumeMgr* sVolumeManager; +public: + enum + { + NO_LOD = -1 + }; }; inline BOOL LLPrimitive::isAvatar() const @@ -528,7 +557,7 @@ inline BOOL LLPrimitive::isApp(const LLPCode pcode) // Special case for setPosition. If not check-for-finite, fall through to LLXform method. void LLPrimitive::setPosition(const F32 x, const F32 y, const F32 z) { - if (llfinite(x) && llfinite(y) && llfinite(z)) + if (std::isfinite(x) && std::isfinite(y) && std::isfinite(z)) { LLXform::setPosition(x, y, z); } @@ -565,7 +594,7 @@ void LLPrimitive::setAngularVelocity(const LLVector3& avel) void LLPrimitive::setAngularVelocity(const F32 x, const F32 y, const F32 z) { - if (llfinite(x) && llfinite(y) && llfinite(z)) + if (std::isfinite(x) && std::isfinite(y) && std::isfinite(z)) { mAngularVelocity.setVec(x,y,z); } @@ -589,7 +618,7 @@ void LLPrimitive::setVelocity(const LLVector3& vel) void LLPrimitive::setVelocity(const F32 x, const F32 y, const F32 z) { - if (llfinite(x) && llfinite(y) && llfinite(z)) + if (std::isfinite(x) && std::isfinite(y) && std::isfinite(z)) { mVelocity.setVec(x,y,z); } @@ -601,7 +630,7 @@ void LLPrimitive::setVelocity(const F32 x, const F32 y, const F32 z) void LLPrimitive::setVelocityX(const F32 x) { - if (llfinite(x)) + if (std::isfinite(x)) { mVelocity.mV[VX] = x; } @@ -613,7 +642,7 @@ void LLPrimitive::setVelocityX(const F32 x) void LLPrimitive::setVelocityY(const F32 y) { - if (llfinite(y)) + if (std::isfinite(y)) { mVelocity.mV[VY] = y; } @@ -625,7 +654,7 @@ void LLPrimitive::setVelocityY(const F32 y) void LLPrimitive::setVelocityZ(const F32 z) { - if (llfinite(z)) + if (std::isfinite(z)) { mVelocity.mV[VZ] = z; } @@ -661,7 +690,7 @@ void LLPrimitive::setAcceleration(const LLVector3& accel) void LLPrimitive::setAcceleration(const F32 x, const F32 y, const F32 z) { - if (llfinite(x) && llfinite(y) && llfinite(z)) + if (std::isfinite(x) && std::isfinite(y) && std::isfinite(z)) { mAcceleration.setVec(x,y,z); } diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index dfae9699ec..854003d42b 100644 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -137,7 +137,7 @@ S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te) // we're changing an existing entry llassert(mEntryList[index]); delete (mEntryList[index]); - if (&te) + if (te != LLTextureEntry::null) { mEntryList[index] = te.newCopy(); } @@ -377,6 +377,16 @@ S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMa return TEM_CHANGE_NONE; } +LLMaterialPtr LLPrimTextureList::getMaterialParams(const U8 index) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->getMaterialParams(); + } + + return LLMaterialPtr(); +} + S32 LLPrimTextureList::size() const { return mEntryList.size(); diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h index c91764e7ad..ce5f6b72b3 100644 --- a/indra/llprimitive/llprimtexturelist.h +++ b/indra/llprimitive/llprimtexturelist.h @@ -115,6 +115,8 @@ class LLPrimTextureList S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID); S32 setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams); + LLMaterialPtr getMaterialParams(const U8 index); + S32 size() const; // void forceResize(S32 new_size); diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index 284dfc15f4..91d5c7ca7e 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -417,7 +417,7 @@ S32 LLTextureEntry::setOffsetT(F32 t) S32 LLTextureEntry::setRotation(F32 theta) { - if (mRotation != theta && llfinite(theta)) + if (mRotation != theta && std::isfinite(theta)) { mRotation = theta; return TEM_CHANGE_TEXTURE; diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index 19edcaa27d..a40c3988f2 100644 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -89,6 +89,10 @@ class LLTextureEntry bool operator==(const LLTextureEntry &rhs) const; bool operator!=(const LLTextureEntry &rhs) const; + + // Added to allow use with std::map + // + bool operator <(const LLTextureEntry &rhs) const; LLSD asLLSD() const; void asLLSD(LLSD& sd) const; diff --git a/indra/llprimitive/object_flags.h b/indra/llprimitive/object_flags.h index f48b97d58b..e970144706 100644 --- a/indra/llprimitive/object_flags.h +++ b/indra/llprimitive/object_flags.h @@ -69,6 +69,7 @@ const U32 FLAGS_TEMPORARY = (1U << 30); //const U32 FLAGS_UNUSED_007 = (1U << 31); // was FLAGS_ZLIB_COMPRESSED const U32 FLAGS_LOCAL = FLAGS_ANIM_SOURCE | FLAGS_CAMERA_SOURCE; +const U32 FLAGS_WORLD = FLAGS_USE_PHYSICS | FLAGS_PHANTOM | FLAGS_TEMPORARY_ON_REZ; typedef enum e_havok_joint_type { diff --git a/indra/llqtwebkit/CMakeLists.txt b/indra/llqtwebkit/CMakeLists.txt deleted file mode 100644 index 6fbf5e9606..0000000000 --- a/indra/llqtwebkit/CMakeLists.txt +++ /dev/null @@ -1,70 +0,0 @@ -# -*- cmake -*- - -project(llqtwebkit) - -include(00-Common) -include(Qt4) - -if(NOT WORD_SIZE EQUAL 32) - if(WINDOWS) - add_definitions(/FIXED:NO) - else(WINDOWS) - add_definitions(-fPIC) - endif(WINDOWS) -endif(NOT WORD_SIZE EQUAL 32) - -include_directories(${QT_INCLUDES}) - -add_subdirectory(qtwebkit_cookiejar) -include_directories(qtwebkit_cookiejar/src/) - -set(llqtwebkit_SOURCE_FILES - llembeddedbrowser.cpp - llembeddedbrowserwindow.cpp - lljsobject.cpp - llnetworkaccessmanager.cpp - llqtwebkit.cpp - llstyle.cpp - llwebpage.cpp - llwebpageopenshim.cpp - ) - -set(llqtwebkit_HEADER_FILES - llembeddedbrowser.h - llembeddedbrowser_p.h - llembeddedbrowserwindow.h - llembeddedbrowserwindow_p.h - lljsobject.h - llnetworkaccessmanager.h - llqtwebkit.h - llstyle.h - llwebpage.h - llwebpageopenshim.h - pstdint.h - ) - -set(llqtwebkit_UI_FILES - passworddialog.ui - ) - -set(llqtwebkit_LINK_LIBRARIES - networkcookiejar -) - -QT4_WRAP_UI(llqtwebkit_UI_MOC ${llqtwebkit_UI_FILES}) -QT4_WRAP_CPP(llqtwebkit_HEADERS_MOC ${llqtwebkit_HEADER_FILES}) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -add_library(llqtwebkit - ${llqtwebkit_SOURCE_FILES} - ${llqtwebkit_HEADERS_MOC} - ${llqtwebkit_UI_MOC} -) - -add_dependencies(llqtwebkit prepare) - -target_link_libraries(llqtwebkit ${llqtwebkit_LINK_LIBRARIES}) - -add_dependencies(llqtwebkit - networkcookiejar -) diff --git a/indra/llqtwebkit/autotests/llembeddedbrowser/llembeddedbrowser.pro b/indra/llqtwebkit/autotests/llembeddedbrowser/llembeddedbrowser.pro deleted file mode 100644 index 02ecce5a2b..0000000000 --- a/indra/llqtwebkit/autotests/llembeddedbrowser/llembeddedbrowser.pro +++ /dev/null @@ -1,14 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . - -CONFIG += qtestlib -QT += webkit opengl network - -include(../../llmozlib2.pri) -DEFINES += AUTOTEST - -# Input -SOURCES += tst_llembeddedbrowser.cpp - diff --git a/indra/llqtwebkit/autotests/llembeddedbrowser/tst_llembeddedbrowser.cpp b/indra/llqtwebkit/autotests/llembeddedbrowser/tst_llembeddedbrowser.cpp deleted file mode 100644 index a59cc9e196..0000000000 --- a/indra/llqtwebkit/autotests/llembeddedbrowser/tst_llembeddedbrowser.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include -#include -#include - -class tst_LLEmbeddedBrowser : public QObject -{ - Q_OBJECT - -public slots: - void initTestCase(); - void cleanupTestCase(); - void init(); - void cleanup(); - -private slots: - void llembeddedbrowser_data(); - void llembeddedbrowser(); - - void clearAllCookies(); - void clearCache_data(); - void clearCache(); - void clearLastError_data(); - void clearLastError(); - void createBrowserWindow_data(); - void createBrowserWindow(); - void destroyBrowserWindow(); - void enableCookies_data(); - void enableCookies(); - void enablePlugins_data(); - void enablePlugins(); - void enableProxy_data(); - void enableProxy(); - void getGREVersion_data(); - void getGREVersion(); - void getInstance(); - void getLastError_data(); - void getLastError(); - void initBrowser_data(); - void initBrowser(); //change function init as initbrowser - void reset(); - void setBrowserAgentId_data(); - void setBrowserAgentId(); - void setLastError_data(); - void setLastError(); -}; - -// Subclass that exposes the protected functions. -class SubLLEmbeddedBrowser : public LLEmbeddedBrowser -{ -public: - -}; - -// This will be called before the first test function is executed. -// It is only called once. -void tst_LLEmbeddedBrowser::initTestCase() -{ -} - -// This will be called after the last test function is executed. -// It is only called once. -void tst_LLEmbeddedBrowser::cleanupTestCase() -{ -} - -// This will be called before each test function is executed. -void tst_LLEmbeddedBrowser::init() -{ -} - -// This will be called after every test function. -void tst_LLEmbeddedBrowser::cleanup() -{ -} - -void tst_LLEmbeddedBrowser::llembeddedbrowser_data() -{ -} - -void tst_LLEmbeddedBrowser::llembeddedbrowser() -{ - SubLLEmbeddedBrowser browser; - QCOMPARE(browser.clearAllCookies(), false); - QCOMPARE(browser.clearCache(), false); - browser.clearLastError(); - QCOMPARE(browser.enableCookies(false), false); - QCOMPARE(browser.enablePlugins(false), true); - QCOMPARE(browser.enableProxy(false, std::string(""), -1), true); - QCOMPARE(browser.getGREVersion(), std::string(QT_VERSION_STR)); - QVERIFY(browser.getInstance() != NULL); - QCOMPARE(browser.getLastError(), 0); - browser.setBrowserAgentId("uBrowser"); - browser.setLastError(-1); - QCOMPARE(browser.reset(), true); - browser.destroyBrowserWindow(0); - browser.destroyBrowserWindow((LLEmbeddedBrowserWindow*)6); - QCOMPARE(browser.getWindowCount(), 0); - QCOMPARE(browser.init(std::string(""),std::string(""),std::string(""),0), true); -} - -// public bool clearAllCookies() -void tst_LLEmbeddedBrowser::clearAllCookies() -{ - SubLLEmbeddedBrowser browser; - - QCOMPARE(browser.clearAllCookies(), false); - browser.reset(); - QCOMPARE(browser.clearAllCookies(), true); -} - -void tst_LLEmbeddedBrowser::clearCache_data() -{ - QTest::addColumn("clearCache"); -#if QT_VERSION < 0x040500 - QTest::newRow("QTVersion < 4.5") << false; -#else - QTest::newRow("QTVersion > 4.5") << true; -#endif -} - -// public bool clearCache() -void tst_LLEmbeddedBrowser::clearCache() -{ - QFETCH(bool, clearCache); - - SubLLEmbeddedBrowser browser; - browser.reset(); - QCOMPARE(browser.clearCache(), clearCache); -} - -void tst_LLEmbeddedBrowser::clearLastError_data() -{ - QTest::addColumn("lastError"); - QTest::newRow("1") << 1; -} - -// public void clearLastError() -void tst_LLEmbeddedBrowser::clearLastError() -{ - SubLLEmbeddedBrowser browser; - QFETCH(int, lastError); - - browser.setLastError(lastError); - browser.clearLastError(); - QCOMPARE(browser.getLastError(), 0); -} - -void tst_LLEmbeddedBrowser::createBrowserWindow_data() -{ - QTest::addColumn("width"); - QTest::addColumn("height"); - QTest::newRow("0,0") << 0 << 0; - QTest::newRow("800,600") << 800 << 600; -} - -// public LLEmbeddedBrowserWindow* createBrowserWindow(int width, int height) -void tst_LLEmbeddedBrowser::createBrowserWindow() -{ - QFETCH(int, width); - QFETCH(int, height); - SubLLEmbeddedBrowser browser; - - LLEmbeddedBrowserWindow *window = browser.createBrowserWindow(width, height); - QVERIFY(window); - QCOMPARE(browser.getLastError(), 0); - QCOMPARE(browser.getWindowCount(), 1); - QCOMPARE(window->getBrowserWidth(), (int16_t)width); - QCOMPARE(window->getBrowserHeight(), (int16_t)height); -} - -// public bool destroyBrowserWindow(LLEmbeddedBrowserWindow* browser_window) -void tst_LLEmbeddedBrowser::destroyBrowserWindow() -{ - SubLLEmbeddedBrowser browser; - browser.reset(); - LLEmbeddedBrowserWindow* browser_window = browser.createBrowserWindow(200, 100); - if (browser_window) - { - QCOMPARE(browser.getWindowCount(), 1); - browser.destroyBrowserWindow(browser_window); - QCOMPARE(browser.getLastError(), 0); - QCOMPARE(browser.getWindowCount(), 0); - } - - browser_window = browser.createBrowserWindow(800, 600); - if (browser_window) - { - QCOMPARE(browser.getWindowCount(), 1); - browser.destroyBrowserWindow(browser_window); - QCOMPARE(browser.getLastError(), 0); - QCOMPARE(browser.getWindowCount(), 0); - } -} - -void tst_LLEmbeddedBrowser::enableCookies_data() -{ - QTest::addColumn("enabled"); - QTest::addColumn("enableCookies"); - QTest::newRow("disable") << false << false; - QTest::newRow("enable") << true << false; -} - -// public bool enableCookies(bool enabled) -void tst_LLEmbeddedBrowser::enableCookies() -{ - QFETCH(bool, enabled); - QFETCH(bool, enableCookies); - - SubLLEmbeddedBrowser browser; - browser.reset(); - QCOMPARE(browser.enableCookies(enabled), enableCookies); - // TODO check that cookies are not saved -} - -void tst_LLEmbeddedBrowser::enablePlugins_data() -{ - QTest::addColumn("enabled"); - QTest::addColumn("enablePlugins"); - QTest::newRow("disable") << false << true; - QTest::newRow("enable") << true << true; -} - -// public bool enablePlugins(bool enabled) -void tst_LLEmbeddedBrowser::enablePlugins() -{ - QFETCH(bool, enabled); - QFETCH(bool, enablePlugins); - - SubLLEmbeddedBrowser browser; - browser.reset(); - QCOMPARE(browser.enablePlugins(enabled), enablePlugins); - // TODO check that plugins work/do not work -} - -Q_DECLARE_METATYPE(std::string) -void tst_LLEmbeddedBrowser::enableProxy_data() -{ - QTest::addColumn("enabled"); - QTest::addColumn("host_name"); - QTest::addColumn("port"); - QTest::addColumn("enableProxy"); - QTest::newRow("null") << false << std::string() << 0 << true; - QTest::newRow("valid") << true << std::string("wtfsurf.com") << 80 << true; -} - -// public bool enableProxy(bool enabled, std::string host_name, int port) -void tst_LLEmbeddedBrowser::enableProxy() -{ - QFETCH(bool, enabled); - QFETCH(std::string, host_name); - QFETCH(int, port); - QFETCH(bool, enableProxy); - - SubLLEmbeddedBrowser browser; - browser.reset(); - QCOMPARE(browser.enableProxy(enabled, host_name, port), enableProxy); - // TODO need some proxy servers to test this -} - -void tst_LLEmbeddedBrowser::getGREVersion_data() -{ - QTest::addColumn("getGREVersion"); - QTest::newRow("valid") << std::string(QT_VERSION_STR); -} - -// public std::string getGREVersion() -void tst_LLEmbeddedBrowser::getGREVersion() -{ - QFETCH(std::string, getGREVersion); - - SubLLEmbeddedBrowser browser; - browser.reset(); - QCOMPARE(browser.getGREVersion(), getGREVersion); -} - -// public static LLEmbeddedBrowser* getInstance() -void tst_LLEmbeddedBrowser::getInstance() -{ - SubLLEmbeddedBrowser browser; - QVERIFY(browser.getInstance() != NULL); -} - -void tst_LLEmbeddedBrowser::getLastError_data() -{ - QTest::addColumn("error"); - QTest::newRow("0") << 0; - QTest::newRow("-1") << -1; - QTest::newRow("100") << 100; -} - -// public int getLastError() -void tst_LLEmbeddedBrowser::getLastError() -{ - QFETCH(int, error); - SubLLEmbeddedBrowser browser; - browser.setLastError(error); - QCOMPARE(browser.getLastError(), error); -} - -void tst_LLEmbeddedBrowser::initBrowser_data() -{ - QTest::addColumn("application_directory"); - QTest::addColumn("component_directory"); - QTest::addColumn("profile_directory"); - QTest::addColumn("native_window_handleCount"); - QTest::addColumn("init"); - QTest::newRow("null") << std::string() << std::string() << std::string() << (void *)0 << true; - QTest::newRow("valid") << std::string("/home/crystal/Settings/") << std::string() << std::string() << (void *)0 << true; -} -void tst_LLEmbeddedBrowser::initBrowser() -{ - QFETCH(std::string, application_directory); - QFETCH(std::string, component_directory); - QFETCH(std::string, profile_directory); - QFETCH(void *, native_window_handleCount); - SubLLEmbeddedBrowser browser; - browser.init(application_directory,component_directory,profile_directory,native_window_handleCount); - QCOMPARE(browser.getLastError(), 0); -} - -// public bool reset() -void tst_LLEmbeddedBrowser::reset() -{ - SubLLEmbeddedBrowser browser; - - browser.setLastError(100); - QCOMPARE(browser.getLastError(), 100); - QVERIFY(browser.reset()); - QCOMPARE(browser.getLastError(), 0); - // TODO what should reset really do? -} - -void tst_LLEmbeddedBrowser::setBrowserAgentId_data() -{ - QTest::addColumn("id"); - QTest::newRow("null") << std::string(); - QTest::newRow("valid") << std::string("uBrowser"); - -} - -// public void setBrowserAgentId(std::string id) -void tst_LLEmbeddedBrowser::setBrowserAgentId() -{ - QFETCH(std::string, id); - - SubLLEmbeddedBrowser browser; - browser.reset(); - browser.setBrowserAgentId(id); - LLEmbeddedBrowserWindow *window = browser.createBrowserWindow(0, 0); - Q_UNUSED(window); - // TODO confirm that the page is actually sending the agent ID -} - -void tst_LLEmbeddedBrowser::setLastError_data() -{ - QTest::addColumn("error_number"); - QTest::newRow("0") << 0; - QTest::newRow("-1") << -1; - QTest::newRow("100") << 100; -} - -// public void setLastError(int error_number) -void tst_LLEmbeddedBrowser::setLastError() -{ - QFETCH(int, error_number); - - SubLLEmbeddedBrowser browser; - - browser.setLastError(error_number); - QCOMPARE(browser.getLastError(), error_number); -} - -QTEST_MAIN(tst_LLEmbeddedBrowser) -#include "tst_llembeddedbrowser.moc" - diff --git a/indra/llqtwebkit/autotests/llembeddedbrowserwindow/llembeddedbrowserwindow.pro b/indra/llqtwebkit/autotests/llembeddedbrowserwindow/llembeddedbrowserwindow.pro deleted file mode 100644 index a89f500652..0000000000 --- a/indra/llqtwebkit/autotests/llembeddedbrowserwindow/llembeddedbrowserwindow.pro +++ /dev/null @@ -1,14 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . - -CONFIG += qtestlib -QT += webkit opengl network - -include(../../llmozlib2.pri) -DEFINES += AUTOTEST - -# Input -SOURCES += tst_llembeddedbrowserwindow.cpp - diff --git a/indra/llqtwebkit/autotests/llembeddedbrowserwindow/tst_llembeddedbrowserwindow.cpp b/indra/llqtwebkit/autotests/llembeddedbrowserwindow/tst_llembeddedbrowserwindow.cpp deleted file mode 100644 index 4c365d3713..0000000000 --- a/indra/llqtwebkit/autotests/llembeddedbrowserwindow/tst_llembeddedbrowserwindow.cpp +++ /dev/null @@ -1,1027 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include - -#include "llembeddedbrowserwindow.h" -#include "llembeddedbrowser.h" - -#ifndef QTRY_COMPARE - -#define __TRY_TIMEOUT__ 10000 -#define __TRY_STEP__ 50 - -#define __QTRY(__expression__, __functionToCall__) \ - do { \ - int __i = 0; \ - while (!(__expression__) && __i < __TRY_TIMEOUT__) { \ - QTest::qWait(__TRY_STEP__); \ - __i += __TRY_STEP__; \ - } \ - __functionToCall__; \ - } while(0) - -#define QTRY_COMPARE(__expression__, __expected__) \ - __QTRY((__expression__ == __expected__), QCOMPARE(__expression__, __expected__)); - -#define QTRY_VERIFY(__expression__) \ - __QTRY(__expression__, QVERIFY(__expression__)); - -#endif // QTRY_COMPARE - -class tst_LLEmbeddedBrowserWindow : public QObject -{ - Q_OBJECT - -public slots: - void initTestCase(); - void cleanupTestCase(); - void init(); - void cleanup(); - -private slots: - void llembeddedbrowserwindow_data(); - void llembeddedbrowserwindow(); - - void addObserver_data(); - void addObserver(); - void canNavigateBack_data(); - void canNavigateBack(); - void canNavigateForward_data(); - void canNavigateForward(); - void evaluateJavascript_data(); - void evaluateJavascript(); - void flipWindow_data(); - void flipWindow(); - void focusBrowser_data(); - void focusBrowser(); - void getBrowserDepth_data(); - void getBrowserDepth(); - void getBrowserHeight_data(); - void getBrowserHeight(); - void getBrowserRowSpan_data(); - void getBrowserRowSpan(); - void getBrowserWidth_data(); - void getBrowserWidth(); - void getClickLinkHref_data(); - void getClickLinkHref(); - void getClickLinkTarget_data(); - void getClickLinkTarget(); - void getCurrentUri_data(); - void getCurrentUri(); - void getNoFollowScheme_data(); - void getNoFollowScheme(); - void getPageBuffer_data(); - void getPageBuffer(); - void getPercentComplete_data(); - void getPercentComplete(); - void getStatusMsg_data(); - void getStatusMsg(); - void getWindowId_data(); - void getWindowId(); - void grabWindow_data(); - void grabWindow(); - void keyPress_data(); - void keyPress(); - void mouseDown_data(); - void mouseDown(); - void mouseLeftDoubleClick_data(); - void mouseLeftDoubleClick(); - void mouseMove_data(); - void mouseMove(); - void mouseUp_data(); - void mouseUp(); - void navigateBack_data(); - void navigateBack(); - void navigateForward_data(); - void navigateForward(); - void navigateReload_data(); - void navigateReload(); - void navigateStop_data(); - void navigateStop(); - void navigateTo_data(); - void navigateTo(); - void remObserver_data(); - void remObserver(); - void scrollByLines_data(); - void scrollByLines(); - void setBackgroundColor_data(); - void setBackgroundColor(); - void setCaretColor_data(); - void setCaretColor(); - void setEnabled_data(); - void setEnabled(); - void setNoFollowScheme_data(); - void setNoFollowScheme(); - void setParent_data(); - void setParent(); - void setSize_data(); - void setSize(); - void setWindowId_data(); - void setWindowId(); - void unicodeInput_data(); - void unicodeInput(); -}; - -// Subclass that exposes the protected functions. -class SubLLEmbeddedBrowserWindow : public LLEmbeddedBrowserWindow -{ -public: - -}; - -// This will be called before the first test function is executed. -// It is only called once. -void tst_LLEmbeddedBrowserWindow::initTestCase() -{ -} - -// This will be called after the last test function is executed. -// It is only called once. -void tst_LLEmbeddedBrowserWindow::cleanupTestCase() -{ -} - -// This will be called before each test function is executed. -void tst_LLEmbeddedBrowserWindow::init() -{ -} - -// This will be called after every test function. -void tst_LLEmbeddedBrowserWindow::cleanup() -{ -} - -void tst_LLEmbeddedBrowserWindow::llembeddedbrowserwindow_data() -{ -} - -void tst_LLEmbeddedBrowserWindow::llembeddedbrowserwindow() -{ - SubLLEmbeddedBrowserWindow window; - QCOMPARE(window.addObserver((LLEmbeddedBrowserWindowObserver*)0), false); - QCOMPARE(window.canNavigateBack(), false); - QCOMPARE(window.canNavigateForward(), false); - QCOMPARE(window.evaluateJavascript(std::string()), std::string()); - QCOMPARE(window.flipWindow(false), true); - window.focusBrowser(false); - QCOMPARE(window.getBrowserDepth(), (int16_t)4); - QCOMPARE(window.getBrowserHeight(), (int16_t)0); - QCOMPARE(window.getBrowserRowSpan(), (int32_t)0); - QCOMPARE(window.getBrowserWidth(), (int16_t)0); - QCOMPARE(window.getClickLinkHref(), std::string()); - QCOMPARE(window.getClickLinkTarget(), std::string()); - QCOMPARE(window.getCurrentUri(), std::string()); - QCOMPARE(window.getNoFollowScheme(), std::string("secondlife")); - QCOMPARE(window.getPageBuffer(), (unsigned char*)0); - QCOMPARE(window.getPercentComplete(), (int16_t)0); - QCOMPARE(window.getStatusMsg(), std::string()); - QCOMPARE(window.getWindowId(), -1); - QCOMPARE(window.grabWindow(-1, -1, -1, -1), (unsigned char*)0); - window.keyPress(0); - window.mouseDown(0, 0); - window.mouseLeftDoubleClick(0, 0); - window.mouseMove(0, 0); - window.mouseUp(0, 0); - window.navigateBack(); - window.navigateForward(); - window.navigateReload(); - window.navigateStop(); - QCOMPARE(window.navigateTo(std::string()), true); - QCOMPARE(window.remObserver((LLEmbeddedBrowserWindowObserver*)0), false); - window.scrollByLines(0); - window.setBackgroundColor(0, 0, 0); - window.setCaretColor(0, 0, 0); - window.setEnabled(false); - window.setNoFollowScheme(std::string()); - window.setParent((LLEmbeddedBrowser*)0); - QCOMPARE(window.setSize(0, 0), true); - window.setWindowId(-1); - window.unicodeInput((uint32_t)0); -} - -void tst_LLEmbeddedBrowserWindow::addObserver_data() -{ -#if 0 - QTest::addColumn("observerCount"); - QTest::addColumn("addObserver"); - QTest::newRow("null") << 0 << false; -#endif -} - -// public bool addObserver(LLEmbeddedBrowserWindowObserver* observer) -void tst_LLEmbeddedBrowserWindow::addObserver() -{ -#if 0 - QFETCH(int, observerCount); - QFETCH(bool, addObserver); - - SubLLEmbeddedBrowserWindow window; - - QCOMPARE(window.addObserver(observer), addObserver); -#endif - QSKIP("Test is same with remObserver.", SkipAll); -} - -void tst_LLEmbeddedBrowserWindow::canNavigateBack_data() -{ -#if 0 - QTest::addColumn("canNavigateBack"); - QTest::newRow("true") << true; - QTest::newRow("false") << false; -#endif -} - -// public bool canNavigateBack() -void tst_LLEmbeddedBrowserWindow::canNavigateBack() -{ - //QFETCH(bool, canNavigateForward); - - SubLLEmbeddedBrowserWindow window; - window.setSize(800,600); - window.setParent(new LLEmbeddedBrowser()); - QCOMPARE(window.canNavigateForward(), false); - window.navigateTo(std::string("http://www.google.com")); - QTest::qWait(__TRY_TIMEOUT__); - QCOMPARE(window.canNavigateBack(), false); - window.navigateTo(std::string("http://www.cnn.com")); - QTest::qWait(__TRY_TIMEOUT__); - QCOMPARE(window.canNavigateBack(), true); - window.navigateBack(); - QTRY_COMPARE(window.canNavigateForward(), true); - window.navigateForward(); - QTRY_COMPARE(window.canNavigateBack(), true); -} - -void tst_LLEmbeddedBrowserWindow::canNavigateForward_data() -{ -#if 0 - QTest::addColumn("canNavigateForward"); - QTest::newRow("true") << true; - QTest::newRow("false") << false; -#endif -} - -// public bool canNavigateForward() -void tst_LLEmbeddedBrowserWindow::canNavigateForward() -{ - QSKIP("Test is same with canNavigateBack().", SkipAll); -} - -Q_DECLARE_METATYPE(std::string) -void tst_LLEmbeddedBrowserWindow::evaluateJavascript_data() -{ - QTest::addColumn("script"); - QTest::addColumn("evaluateJavascript"); - QTest::newRow("null") << std::string() << std::string(); - //QTest::newRow("valid") << std::string("alert(\"hey!\")") << std::string("alert(\"hey!\")"); -} - -// public std::string evaluateJavascript(std::string script) -void tst_LLEmbeddedBrowserWindow::evaluateJavascript() -{ - QFETCH(std::string, script); - QFETCH(std::string, evaluateJavascript); - - SubLLEmbeddedBrowserWindow window; - - window.evaluateJavascript(script); -} - -void tst_LLEmbeddedBrowserWindow::flipWindow_data() -{ - QTest::addColumn("flip"); - QTest::addColumn("flipWindow"); - QTest::newRow("false") << false << true; - QTest::newRow("true") << true << true; -} - -// public bool flipWindow(bool flip) -void tst_LLEmbeddedBrowserWindow::flipWindow() -{ - QFETCH(bool, flip); - QFETCH(bool, flipWindow); - - SubLLEmbeddedBrowserWindow window; - - QCOMPARE(window.flipWindow(flip), flipWindow); -} - -void tst_LLEmbeddedBrowserWindow::focusBrowser_data() -{ - QTest::addColumn("focus_browser"); - QTest::newRow("true") << true; - QTest::newRow("false") << false; -} - -// public void focusBrowser(bool focus_browser) -void tst_LLEmbeddedBrowserWindow::focusBrowser() -{ - QFETCH(bool, focus_browser); - - SubLLEmbeddedBrowserWindow window; - window.focusBrowser(focus_browser); -} - -Q_DECLARE_METATYPE(int16_t) -void tst_LLEmbeddedBrowserWindow::getBrowserDepth_data() -{ -#if 0 - QTest::addColumn("getBrowserDepth"); - QTest::newRow("null") << int16_t(); -#endif -} - -// public int16_t getBrowserDepth() -void tst_LLEmbeddedBrowserWindow::getBrowserDepth() -{ - //QFETCH(int16_t, getBrowserDepth); - - SubLLEmbeddedBrowserWindow window; - - QCOMPARE(window.getBrowserDepth(), int16_t(4)); -} - -void tst_LLEmbeddedBrowserWindow::getBrowserHeight_data() -{ -#if 0 - QTest::addColumn("getBrowserHeight"); - QTest::newRow("null") << int16_t(); -#endif -} - -// public int16_t getBrowserHeight() -void tst_LLEmbeddedBrowserWindow::getBrowserHeight() -{ -#if 0 - QFETCH(int16_t, getBrowserHeight); - - SubLLEmbeddedBrowserWindow window; - - QCOMPARE(window.getBrowserHeight(), getBrowserHeight); -#endif - QSKIP("Test is same with setSize().", SkipAll); -} - -Q_DECLARE_METATYPE(int32_t) -void tst_LLEmbeddedBrowserWindow::getBrowserRowSpan_data() -{ -#if 0 - QTest::addColumn("getBrowserRowSpan"); - QTest::newRow("null") << int32_t(); -#endif -} - -// public int32_t getBrowserRowSpan() -void tst_LLEmbeddedBrowserWindow::getBrowserRowSpan() -{ -#if 0 - SubLLEmbeddedBrowserWindow window; - window.setSize(0, 0); - - QCOMPARE(window.getBrowserWidth(), int16_t(0)); - QCOMPARE(window.getBrowserRowSpan(), int32_t(0)); - window.setSize(100, 100); - - QCOMPARE(window.getBrowserWidth(), int16_t(100)); - QCOMPARE(window.getBrowserRowSpan(), int32_t(400)); -#endif - QSKIP("Test is same with setSize().", SkipAll); -} - -void tst_LLEmbeddedBrowserWindow::getBrowserWidth_data() -{ -#if 0 - QTest::addColumn("getBrowserWidth"); - QTest::newRow("null") << int16_t(); -#endif -} - -// public int16_t getBrowserWidth() -void tst_LLEmbeddedBrowserWindow::getBrowserWidth() -{ -#if 0 - //QFETCH(int16_t, getBrowserWidth); - - SubLLEmbeddedBrowserWindow window; - window.setSize(0, 0); - - QCOMPARE(window.getBrowserWidth(), int16_t(0)); - QCOMPARE(window.getBrowserHeight(), int16_t(0)); - window.setSize(100, 100); - - QCOMPARE(window.getBrowserWidth(), int16_t(100)); - QCOMPARE(window.getBrowserHeight(), int16_t(100)); -#endif - QSKIP("Test is same with setSize().", SkipAll); -} - -//Q_DECLARE_METATYPE(std::string const) -void tst_LLEmbeddedBrowserWindow::getClickLinkHref_data() -{ -#if 0 - QTest::addColumn("getClickLinkHref"); - QTest::newRow("null") << std::string const(); -#endif -} - -// public std::string const getClickLinkHref() -void tst_LLEmbeddedBrowserWindow::getClickLinkHref() -{ - //QFETCH(std::string const, getClickLinkHref); - - SubLLEmbeddedBrowserWindow window; - - window.getClickLinkHref(); -} - -void tst_LLEmbeddedBrowserWindow::getClickLinkTarget_data() -{ -#if 0 - QTest::addColumn("getClickLinkTarget"); - QTest::newRow("null") << std::string const(); -#endif -} - -// public std::string const getClickLinkTarget() -void tst_LLEmbeddedBrowserWindow::getClickLinkTarget() -{ - //QFETCH(std::string const, getClickLinkTarget); - - SubLLEmbeddedBrowserWindow window; - - window.getClickLinkTarget(); -} - -void tst_LLEmbeddedBrowserWindow::getCurrentUri_data() -{ -#if 0 - QTest::addColumn("getCurrentUri"); - QTest::newRow("null") << std::string const(); -#endif -} - -// public std::string const getCurrentUri() -void tst_LLEmbeddedBrowserWindow::getCurrentUri() -{ - //QFETCH(std::string const, getCurrentUri); - - SubLLEmbeddedBrowserWindow window; - window.navigateTo(std::string("http://www.google.ca/")); - QTRY_COMPARE(QString::fromStdString(window.getCurrentUri()), QString::fromStdString(std::string("http://www.google.ca/"))); -} - -void tst_LLEmbeddedBrowserWindow::getNoFollowScheme_data() -{ -#if 0 - QTest::addColumn("getNoFollowScheme"); - QTest::newRow("FTP") << std::string("FTP"); -#endif -} - -// public std::string getNoFollowScheme() -void tst_LLEmbeddedBrowserWindow::getNoFollowScheme() -{ - //QFETCH(std::string, getNoFollowScheme); - - SubLLEmbeddedBrowserWindow window; - window.setNoFollowScheme("FTP://www.google.com"); - - QCOMPARE(window.getNoFollowScheme(), std::string("FTP")); -} - -//Q_DECLARE_METATYPE(unsigned char*) -void tst_LLEmbeddedBrowserWindow::getPageBuffer_data() -{ -#if 0 - QTest::addColumn("getPageBuffer"); - QTest::newRow("null") << unsigned char*(); -#endif -} - -// public unsigned char* getPageBuffer() -void tst_LLEmbeddedBrowserWindow::getPageBuffer() -{ - //QFETCH(unsigned char*, getPageBuffer); - - SubLLEmbeddedBrowserWindow window; - window.setSize(100,100); - window.grabWindow(0, 0, 100, 100); - - QVERIFY(window.getPageBuffer() != NULL); -} - -//Q_DECLARE_METATYPE(int16_t const) -void tst_LLEmbeddedBrowserWindow::getPercentComplete_data() -{ -#if 0 - QTest::addColumn("getPercentComplete"); - QTest::newRow("null") << int16_t const(); -#endif -} - -// public int16_t const getPercentComplete() -void tst_LLEmbeddedBrowserWindow::getPercentComplete() -{ - //QFETCH(int16_t const, getPercentComplete); - SubLLEmbeddedBrowserWindow window; - window.navigateTo(std::string("http://www.google.com")); - QTest::qWait(1000); - QVERIFY(window.getPercentComplete() > 0); -} - -void tst_LLEmbeddedBrowserWindow::getStatusMsg_data() -{ -#if 0 - QTest::addColumn("getStatusMsg"); - QTest::newRow("null") << std::string const(); -#endif -} - -// public std::string const getStatusMsg() -void tst_LLEmbeddedBrowserWindow::getStatusMsg() -{ - //QFETCH(std::string const, getStatusMsg); - - SubLLEmbeddedBrowserWindow window; - window.navigateTo(std::string("http://www.google.com")); - QTest::qWait(1000); - window.navigateStop(); - window.navigateTo(std::string("http://www.yahoo.com")); - // Seems status msg will always be null during navigating. - //QTRY_VERIFY(QString::fromStdString(window.getStatusMsg())!= NULL); - QSKIP("Status msg will always be null during navigating", SkipAll); -} - -void tst_LLEmbeddedBrowserWindow::getWindowId_data() -{ -#if 0 - QTest::addColumn("getWindowId"); - QTest::newRow("0") << 0; - QTest::newRow("-1") << -1; -#endif -} - -// public int getWindowId() -void tst_LLEmbeddedBrowserWindow::getWindowId() -{ - //QFETCH(int, getWindowId); - - SubLLEmbeddedBrowserWindow window; - window.setWindowId(0); - QCOMPARE(window.getWindowId(), 0); - window.setWindowId(100); - QCOMPARE(window.getWindowId(), 100); -} - -void tst_LLEmbeddedBrowserWindow::grabWindow_data() -{ -#if 0 - QTest::addColumn("x"); - QTest::addColumn("y"); - QTest::addColumn("width"); - QTest::addColumn("height"); - QTest::addColumn("grabWindow"); - QTest::newRow("null") << 0 << 0 << 0 << 0 << 0; -#endif -} - -// public unsigned char* grabWindow(int x, int y, int width, int height) -void tst_LLEmbeddedBrowserWindow::grabWindow() -{ - QSKIP("Test is same with getPageBuffer().", SkipAll); -} - -void tst_LLEmbeddedBrowserWindow::keyPress_data() -{ - QTest::addColumn("key_code"); - QTest::newRow("null") << int16_t(0); - QTest::newRow("valid") << int16_t(0x0E); -} - -// public void keyPress(int16_t key_code) -void tst_LLEmbeddedBrowserWindow::keyPress() -{ - QFETCH(int16_t, key_code); - - SubLLEmbeddedBrowserWindow window; - window.keyPress(key_code); -} - -void tst_LLEmbeddedBrowserWindow::mouseDown_data() -{ - QTest::addColumn("x"); - QTest::addColumn("y"); - QTest::newRow("0") << int16_t(0) << int16_t(0); - QTest::newRow("bignumber") << int16_t(100000) << int16_t(100000); - QTest::newRow("valid") << int16_t(100) << int16_t(100); -} - -// public void mouseDown(int16_t x, int16_t y) -void tst_LLEmbeddedBrowserWindow::mouseDown() -{ - QFETCH(int16_t, x); - QFETCH(int16_t, y); - - SubLLEmbeddedBrowserWindow window; - window.mouseDown(x, y); -} - -void tst_LLEmbeddedBrowserWindow::mouseLeftDoubleClick_data() -{ - QTest::addColumn("x"); - QTest::addColumn("y"); - QTest::newRow("0") << int16_t(0) << int16_t(0); - QTest::newRow("bignumber") << int16_t(100000) << int16_t(100000); - QTest::newRow("valid") << int16_t(100) << int16_t(100); -} - -// public void mouseLeftDoubleClick(int16_t x, int16_t y) -void tst_LLEmbeddedBrowserWindow::mouseLeftDoubleClick() -{ - QFETCH(int16_t, x); - QFETCH(int16_t, y); - - SubLLEmbeddedBrowserWindow window; - window.mouseLeftDoubleClick(x, y); -} - -void tst_LLEmbeddedBrowserWindow::mouseMove_data() -{ - QTest::addColumn("x"); - QTest::addColumn("y"); - QTest::newRow("0") << int16_t(0) << int16_t(0); - QTest::newRow("bignumber") << int16_t(100000) << int16_t(100000); - QTest::newRow("valid") << int16_t(100) << int16_t(100); -} - -// public void mouseMove(int16_t x, int16_t y) -void tst_LLEmbeddedBrowserWindow::mouseMove() -{ - QFETCH(int16_t, x); - QFETCH(int16_t, y); - - SubLLEmbeddedBrowserWindow window; - window.mouseMove(x, y); -} - -void tst_LLEmbeddedBrowserWindow::mouseUp_data() -{ - QTest::addColumn("x"); - QTest::addColumn("y"); - QTest::newRow("0") << int16_t(0) << int16_t(0); - QTest::newRow("bignumber") << int16_t(100000) << int16_t(100000); - QTest::newRow("valid") << int16_t(100) << int16_t(100); -} - -// public void mouseUp(int16_t x, int16_t y) -void tst_LLEmbeddedBrowserWindow::mouseUp() -{ - QFETCH(int16_t, x); - QFETCH(int16_t, y); - - SubLLEmbeddedBrowserWindow window; - window.mouseUp(x, y); -} - -void tst_LLEmbeddedBrowserWindow::navigateBack_data() -{ -#if 0 - QTest::addColumn("foo"); - QTest::newRow("0") << 0; - QTest::newRow("-1") << -1; -#endif -} - -// public void navigateBack() -void tst_LLEmbeddedBrowserWindow::navigateBack() -{ - //QFETCH(int, foo); - - SubLLEmbeddedBrowserWindow window; - window.navigateTo(std::string("http://www.google.ca/")); - QTest::qWait(__TRY_TIMEOUT__); - QCOMPARE(window.canNavigateForward(), false); - window.navigateTo(std::string("http://www.yahoo.com/")); - QTest::qWait(__TRY_TIMEOUT__); - QCOMPARE(window.canNavigateBack(), true); - window.navigateBack(); - QTRY_COMPARE(QString::fromStdString((window.getCurrentUri())), QString("http://www.google.ca/")); - window.navigateBack(); - QTRY_COMPARE(QString::fromStdString((window.getCurrentUri())), QString("http://www.google.ca/")); -} - -void tst_LLEmbeddedBrowserWindow::navigateForward_data() -{ -#if 0 - QTest::addColumn("foo"); - QTest::newRow("0") << 0; - QTest::newRow("-1") << -1; -#endif -} - -// public void navigateForward() -void tst_LLEmbeddedBrowserWindow::navigateForward() -{ - // QFETCH(int, foo); - SubLLEmbeddedBrowserWindow window; - window.navigateTo(std::string("http://www.google.ca/")); - QTest::qWait(__TRY_TIMEOUT__); - QCOMPARE(window.canNavigateForward(), false); - window.navigateTo(std::string("http://www.yahoo.ca/")); - QTest::qWait(__TRY_TIMEOUT__); - QCOMPARE(window.canNavigateBack(), true); - window.navigateBack(); - QTRY_COMPARE(QString::fromStdString((window.getCurrentUri())), QString("http://www.google.ca/")); - window.navigateForward(); - QTRY_COMPARE(QString::fromStdString((window.getCurrentUri())), QString("http://ca.yahoo.com/")); - window.navigateForward(); - QTRY_COMPARE(QString::fromStdString((window.getCurrentUri())), QString("http://ca.yahoo.com/")); -} - -void tst_LLEmbeddedBrowserWindow::navigateReload_data() -{ -#if 0 - QTest::addColumn("foo"); - QTest::newRow("0") << 0; - QTest::newRow("-1") << -1; -#endif -} - -// public void navigateReload() -void tst_LLEmbeddedBrowserWindow::navigateReload() -{ - SubLLEmbeddedBrowserWindow window; - - window.navigateTo(std::string("http://www.google.ca/")); - QTest::qWait(__TRY_TIMEOUT__); - window.navigateReload(); - QTRY_COMPARE(QString::fromStdString((window.getCurrentUri())), QString("http://www.google.ca/")); -} - -void tst_LLEmbeddedBrowserWindow::navigateStop_data() -{ -#if 0 - QTest::addColumn("foo"); - QTest::newRow("0") << 0; - QTest::newRow("-1") << -1; -#endif -} - -// public void navigateStop() -void tst_LLEmbeddedBrowserWindow::navigateStop() -{ - SubLLEmbeddedBrowserWindow window; - window.navigateTo("www.google.com"); - window.navigateStop(); -} - -void tst_LLEmbeddedBrowserWindow::navigateTo_data() -{ - QTest::addColumn("uri"); - QTest::addColumn("navigateTo"); - QTest::newRow("null") << std::string() << std::string(); - QTest::newRow("valid") << std::string("http://www.google.ca/") << std::string("http://www.google.ca/"); -} - -// public bool navigateTo(std::string const uri) -void tst_LLEmbeddedBrowserWindow::navigateTo() -{ - QSKIP("Test is same with navigateBack(), navigateForward().", SkipAll); -} - -void tst_LLEmbeddedBrowserWindow::remObserver_data() -{ -#if 0 - QTest::addColumn("observerCount"); - QTest::addColumn("remObserver"); - QTest::newRow("null") << 0 << false; -#endif -} - -// public bool remObserver(LLEmbeddedBrowserWindowObserver* observer) -void tst_LLEmbeddedBrowserWindow::remObserver() -{ -// QFETCH(int, observerCount); -// QFETCH(bool, remObserver); - - SubLLEmbeddedBrowserWindow window; - LLEmbeddedBrowserWindowObserver* observer = new LLEmbeddedBrowserWindowObserver(); - window.addObserver(observer); - QCOMPARE(window.getObserverNumber(), 1); - window.remObserver(observer); - QCOMPARE(window.getObserverNumber(), 0); -} - -void tst_LLEmbeddedBrowserWindow::scrollByLines_data() -{ - QTest::addColumn("lines"); - QTest::newRow("null") << int16_t(0); - QTest::addColumn("lines"); - QTest::newRow("100") << int16_t(100); -} - -// public void scrollByLines(int16_t lines) -void tst_LLEmbeddedBrowserWindow::scrollByLines() -{ - QFETCH(int16_t, lines); - - SubLLEmbeddedBrowserWindow window; - - window.scrollByLines(lines); -} - -Q_DECLARE_METATYPE(uint8_t) -void tst_LLEmbeddedBrowserWindow::setBackgroundColor_data() -{ - QTest::addColumn("red"); - QTest::addColumn("green"); - QTest::addColumn("blue"); - QTest::newRow("black") << uint8_t(0) << uint8_t(0) << uint8_t(0); - QTest::newRow("red") << uint8_t(255) << uint8_t(0) << uint8_t(0); - QTest::newRow("green") << uint8_t(0) << uint8_t(255) << uint8_t(0); - QTest::newRow("blue") << uint8_t(0) << uint8_t(0) << uint8_t(255); -} - -// public void setBackgroundColor(uint8_t const red, uint8_t const green, uint8_t const blue) -void tst_LLEmbeddedBrowserWindow::setBackgroundColor() -{ - QFETCH(uint8_t, red); - QFETCH(uint8_t, green); - QFETCH(uint8_t, blue); - - SubLLEmbeddedBrowserWindow window; - - window.setBackgroundColor(red, green, blue); -} - -void tst_LLEmbeddedBrowserWindow::setCaretColor_data() -{ - QTest::addColumn("red"); - QTest::addColumn("green"); - QTest::addColumn("blue"); - QTest::newRow("black") << uint8_t(0) << uint8_t(0) << uint8_t(0); - QTest::newRow("red") << uint8_t(255) << uint8_t(0) << uint8_t(0); - QTest::newRow("green") << uint8_t(0) << uint8_t(255) << uint8_t(0); - QTest::newRow("blue") << uint8_t(0) << uint8_t(0) << uint8_t(255); -} - -// public void setCaretColor(uint8_t const red, uint8_t const green, uint8_t const blue) -void tst_LLEmbeddedBrowserWindow::setCaretColor() -{ - QFETCH(uint8_t, red); - QFETCH(uint8_t, green); - QFETCH(uint8_t, blue); - - SubLLEmbeddedBrowserWindow window; - - window.setCaretColor(red, green, blue); -} - -void tst_LLEmbeddedBrowserWindow::setEnabled_data() -{ - QTest::addColumn("enabledIn"); - QTest::newRow("true") << true; - QTest::newRow("false") << false; -} - -// public void setEnabled(bool enabledIn) -void tst_LLEmbeddedBrowserWindow::setEnabled() -{ - QFETCH(bool, enabledIn); - - SubLLEmbeddedBrowserWindow window; - - window.setEnabled(enabledIn); -} - -void tst_LLEmbeddedBrowserWindow::setNoFollowScheme_data() -{ - QTest::addColumn("scheme"); - QTest::addColumn("result"); - QTest::newRow("null") << std::string() << std::string(); - QTest::newRow("valid") << std::string("ftp://www.google.com") << std::string("ftp");; -} - -// public void setNoFollowScheme(std::string scheme) -void tst_LLEmbeddedBrowserWindow::setNoFollowScheme() -{ - QFETCH(std::string, scheme); - QFETCH(std::string, result); - - SubLLEmbeddedBrowserWindow window; - - window.setNoFollowScheme(scheme); - QCOMPARE(window.getNoFollowScheme(), result); -} - -void tst_LLEmbeddedBrowserWindow::setParent_data() -{ -#if 0 - QTest::addColumn("parentCount"); - QTest::newRow("0") << 0; - QTest::newRow("-1") << -1; -#endif -} - -// public void setParent(LLEmbeddedBrowser* parent) -void tst_LLEmbeddedBrowserWindow::setParent() -{ -#if 0 - QFETCH(int, parentCount); - - SubLLEmbeddedBrowserWindow window; - LLEmbeddedBrowser* parent = new LLEmbeddedBrowser(); - - window.setParent(parent); -#endif - QSKIP("Has been tested before.", SkipAll); -} - -void tst_LLEmbeddedBrowserWindow::setSize_data() -{ - QTest::addColumn("width"); - QTest::addColumn("height"); - QTest::addColumn("setSize"); - QTest::newRow("null") << int16_t(0) << int16_t(0) << true; - QTest::newRow("valid") << int16_t(100) << int16_t(200) << true; -} - -// public bool setSize(int16_t width, int16_t height) -void tst_LLEmbeddedBrowserWindow::setSize() -{ - QFETCH(int16_t, width); - QFETCH(int16_t, height); - QFETCH(bool, setSize); - - SubLLEmbeddedBrowserWindow window; - QCOMPARE(window.setSize(width, height), setSize); - window.grabWindow(0, 0, 800, 600); - - QCOMPARE(window.getBrowserWidth(), width); - QCOMPARE(window.getBrowserHeight(), height); - QCOMPARE(window.getBrowserRowSpan(), (int32_t)width * 4); -} - -void tst_LLEmbeddedBrowserWindow::setWindowId_data() -{ - QTest::addColumn("window_id"); - QTest::newRow("0") << 0; - QTest::newRow("-1") << -1; - QTest::newRow("100") << 100; -} - -// public void setWindowId(int window_id) -void tst_LLEmbeddedBrowserWindow::setWindowId() -{ - QFETCH(int, window_id); - - SubLLEmbeddedBrowserWindow window; - - window.setWindowId(window_id); - QCOMPARE(window.getWindowId(), window_id); -} - -Q_DECLARE_METATYPE(uint32_t) -void tst_LLEmbeddedBrowserWindow::unicodeInput_data() -{ - QTest::addColumn("unicode_char"); - QTest::newRow("null") << uint32_t(); - QTest::newRow("valid") << uint32_t(54); -} - -// public void unicodeInput(uint32_t unicode_char) -void tst_LLEmbeddedBrowserWindow::unicodeInput() -{ - QFETCH(uint32_t, unicode_char); - - SubLLEmbeddedBrowserWindow window; - - window.unicodeInput(unicode_char); -} - -QTEST_MAIN(tst_LLEmbeddedBrowserWindow) -#include "tst_llembeddedbrowserwindow.moc" - diff --git a/indra/llqtwebkit/llembeddedbrowser.cpp b/indra/llqtwebkit/llembeddedbrowser.cpp deleted file mode 100644 index f38019b9b6..0000000000 --- a/indra/llqtwebkit/llembeddedbrowser.cpp +++ /dev/null @@ -1,759 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include "llembeddedbrowser.h" - -#include "llembeddedbrowser_p.h" -#include "llembeddedbrowserwindow.h" -#include "llnetworkaccessmanager.h" -#include "llstyle.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// singleton pattern - initialization -LLEmbeddedBrowser* LLEmbeddedBrowser::sInstance = 0; - -LLEmbeddedBrowserPrivate::LLEmbeddedBrowserPrivate() - : mErrorNum(0) - , mNativeWindowHandle(0) - , mNetworkAccessManager(0) - , mApplication(0) -#if QT_VERSION >= 0x040500 - , mDiskCache(0) -#endif - , mNetworkCookieJar(0) - , mHostLanguage( "en" ) - , mIgnoreSSLCertErrors(false) -{ - if (!qApp) - { - static int argc = 0; - static const char* argv[] = {""}; - QApplication::setAttribute(Qt::AA_MacPluginApplication); - QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); - - mApplication = new QApplication(argc, (char **)argv); - mApplication->addLibraryPath(qApp->applicationDirPath()); - } - qApp->setStyle(new LLStyle()); - mNetworkAccessManager = new LLNetworkAccessManager(this); -#if LL_DARWIN - // HACK: Qt installs CarbonEvent handlers that steal events from our main event loop. - // This uninstalls them. - // It's not clear whether calling this internal function is really a good idea. It's probably not. - // It does, however, seem to fix at least one problem ( https://jira.secondlife.com/browse/MOZ-12 ). - extern void qt_release_app_proc_handler(); - qt_release_app_proc_handler(); - - // This is defined and exported from qwidget_mac.mm. - // Calling it with false should prevent qwidget from bringing its process to the foreground, such as when bringing up a popup menu. - extern void qt_mac_set_raise_process(bool b); - qt_mac_set_raise_process(false); -#endif -} - -LLEmbeddedBrowserPrivate::~LLEmbeddedBrowserPrivate() -{ - delete mApplication; - delete mNetworkAccessManager; - delete mNetworkCookieJar; -} - - - -LLEmbeddedBrowser::LLEmbeddedBrowser() - : d(new LLEmbeddedBrowserPrivate) - , mPluginsEnabled( false ) - , mJavaScriptEnabled( false ) - , mCookiesEnabled( false ) -{ -} - -LLEmbeddedBrowser::~LLEmbeddedBrowser() -{ - if(d->mNetworkCookieJar) - { - d->mNetworkCookieJar->mBrowser = NULL; - } - - delete d; -} - -LLEmbeddedBrowser* LLEmbeddedBrowser::getInstance() -{ - if (!sInstance) - sInstance = new LLEmbeddedBrowser; - return sInstance; -} - -void LLEmbeddedBrowser::setLastError(int error_number) -{ - d->mErrorNum = error_number; -} - -void LLEmbeddedBrowser::clearLastError() -{ - d->mErrorNum = 0x0000; -} - -int LLEmbeddedBrowser::getLastError() -{ - return d->mErrorNum; -} - -std::string LLEmbeddedBrowser::getGREVersion() -{ - // take the string directly from Qt - return std::string(QT_VERSION_STR); -} - -bool LLEmbeddedBrowser::init(std::string application_directory, - std::string component_directory, - std::string profile_directory, - void* native_window_handle) -{ - Q_UNUSED(application_directory); - Q_UNUSED(component_directory); - Q_UNUSED(native_window_handle); - d->mStorageDirectory = QString::fromStdString(profile_directory); - QWebSettings::setIconDatabasePath(d->mStorageDirectory); - // The gif and jpeg libraries should be installed in component_directory/imageformats/ - QCoreApplication::addLibraryPath(QString::fromStdString(component_directory)); - - // turn on plugins by default - enablePlugins( true ); - - // Until QtWebkit defaults to 16 - QWebSettings::globalSettings()->setFontSize(QWebSettings::DefaultFontSize, 16); - QWebSettings::globalSettings()->setFontSize(QWebSettings::DefaultFixedFontSize, 16); - - - QWebSettings::globalSettings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true); - QWebSettings::globalSettings()->setOfflineStoragePath(QDesktopServices::storageLocation(QDesktopServices::DataLocation)); - - // use default text encoding - not sure how this helps right now so commenting out until we - // understand how to use it a little better. - //QWebSettings::globalSettings()->setDefaultTextEncoding ( "" ); - - return reset(); -} - -bool LLEmbeddedBrowser::reset() -{ - foreach(LLEmbeddedBrowserWindow *window, d->windows) - delete window; - d->windows.clear(); - delete d->mNetworkAccessManager; - d->mNetworkAccessManager = new LLNetworkAccessManager(d); -#if QT_VERSION >= 0x040500 - d->mDiskCache = new QNetworkDiskCache(d->mNetworkAccessManager); - d->mDiskCache->setCacheDirectory(d->mStorageDirectory + "/cache"); - if (QLatin1String(qVersion()) != QLatin1String("4.5.1")) - d->mNetworkAccessManager->setCache(d->mDiskCache); -#endif - d->mNetworkCookieJar = new LLNetworkCookieJar(d->mNetworkAccessManager, this); - d->mNetworkAccessManager->setCookieJar(d->mNetworkCookieJar); - clearLastError(); - return true; -} - -bool LLEmbeddedBrowser::clearCache() -{ -#if QT_VERSION >= 0x040500 - if (d->mDiskCache) - { - d->mDiskCache->clear(); - return true; - } -#endif - return false; -} - -bool LLEmbeddedBrowser::enableProxy(bool enabled, std::string host_name, int port) -{ - QNetworkProxy proxy; - if (enabled) - { - proxy.setType(QNetworkProxy::HttpProxy); - QString q_host_name = QString::fromStdString(host_name); - proxy.setHostName(q_host_name); - proxy.setPort(port); - } - d->mNetworkAccessManager->setProxy(proxy); - return true; -} - -bool LLEmbeddedBrowser::clearAllCookies() -{ - if (!d->mNetworkCookieJar) - return false; - d->mNetworkCookieJar->clear(); - return true; -} - -void LLEmbeddedBrowser::setCookies(const std::string &cookies) -{ - if (d->mNetworkCookieJar) - { - d->mNetworkCookieJar->setCookiesFromRawForm(cookies); - } -} - -std::string LLEmbeddedBrowser::getAllCookies() -{ - std::string result; - - if (d->mNetworkCookieJar) - { - result = d->mNetworkCookieJar->getAllCookiesInRawForm(); - } - - return result; -} - -void LLEmbeddedBrowser::enableCookies( bool enabled ) -{ - mCookiesEnabled = enabled; - enableCookiesTransient( mCookiesEnabled ); -} - -void LLEmbeddedBrowser::enableCookiesTransient( bool enabled ) -{ - if ( d->mNetworkCookieJar ) - { - d->mNetworkCookieJar->mAllowCookies = enabled; - } -} - -bool LLEmbeddedBrowser::areCookiesEnabled() -{ - return mCookiesEnabled; -} - -void LLEmbeddedBrowser::enablePlugins( bool enabled ) -{ - mPluginsEnabled = enabled; // record state - enablePluginsTransient( mPluginsEnabled ); -} - -void LLEmbeddedBrowser::enablePluginsTransient( bool enabled ) -{ - QWebSettings* default_settings = QWebSettings::globalSettings(); - default_settings->setAttribute( QWebSettings::PluginsEnabled, enabled ); -} - -bool LLEmbeddedBrowser::arePluginsEnabled() -{ - return mPluginsEnabled; -} - -void LLEmbeddedBrowser::enableJavaScript( bool enabled ) -{ - mJavaScriptEnabled = enabled; // record state - enableJavaScriptTransient( mJavaScriptEnabled ); -} - -void LLEmbeddedBrowser::enableJavaScriptTransient( bool enabled ) -{ - QWebSettings* default_settings = QWebSettings::globalSettings(); - default_settings->setAttribute( QWebSettings::JavascriptEnabled, enabled ); - default_settings->setAttribute( QWebSettings::JavascriptCanOpenWindows, enabled ); -} - -bool LLEmbeddedBrowser::isJavaScriptEnabled() -{ - return mJavaScriptEnabled; -} - -bool LLEmbeddedBrowser::showWebInspector(bool show) -{ - QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, show); - foreach (LLEmbeddedBrowserWindow* window, d->windows) - { - window->showWebInspector(show); - } - return true; -} - -/* - Sets a string that should be addded to the user agent to identify the application -*/ -void LLEmbeddedBrowser::setBrowserAgentId(std::string id) -{ - QCoreApplication::setApplicationName(QString::fromStdString(id)); -} - -// updates value of 'hostLanguage' in JavaScript 'Navigator' obect that -// embedded pages can query to see what language the host app is set to -// IMPORTANT: call this before any windows are created - only gets passed -// to LLWebPage when new window is created -void LLEmbeddedBrowser::setHostLanguage( const std::string& host_language ) -{ - d->mHostLanguage = host_language; -} - -LLEmbeddedBrowserWindow* LLEmbeddedBrowser::createBrowserWindow(int width, int height, const std::string target) -{ - LLEmbeddedBrowserWindow *newWin = new LLEmbeddedBrowserWindow(); - if (newWin) - { - newWin->setSize(width, height); - newWin->setParent(this); - newWin->setHostLanguage(d->mHostLanguage); - clearLastError(); - d->windows.append(newWin); - - if(!target.empty() && (target != "_blank")) - { - newWin->setTarget(target); - } - - return newWin; - } - return 0; -} - -bool LLEmbeddedBrowser::destroyBrowserWindow(LLEmbeddedBrowserWindow* browser_window) -{ - // check if exists in windows list - if (d->windows.removeOne(browser_window)) - { - delete browser_window; - clearLastError(); - return true; - } - return false; -} - -int LLEmbeddedBrowser::getWindowCount() const -{ - return d->windows.size(); -} - -void LLEmbeddedBrowser::pump(int max_milliseconds) -{ -#if 0 - // This USED to be necessary on the mac, but with Qt 4.6 it seems to cause trouble loading some pages, - // and using processEvents() seems to work properly now. - // Leaving this here in case these issues ever come back. - - // On the Mac, calling processEvents hangs the viewer. - // I'm not entirely sure this does everything we need, but it seems to work better, and allows things like animated gifs to work. - qApp->sendPostedEvents(); - qApp->sendPostedEvents(0, QEvent::DeferredDelete); -#else - qApp->processEvents(QEventLoop::AllEvents, max_milliseconds); -#endif -} - -void LLEmbeddedBrowser::cookieChanged(const std::string &cookie, const std::string &url, bool dead) -{ - foreach (LLEmbeddedBrowserWindow* window, d->windows) - { - window->cookieChanged(cookie, url, dead); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLEmbeddedBrowser::setCAFile(const std::string &ca_file) -{ - bool result = false; - //qDebug() << "LLEmbeddedBrowser::" << __FUNCTION__ << "attempting to read certs from file: " << QString::fromStdString(ca_file); - - // Extract the list of certificates from the specified file - QList certs = QSslCertificate::fromPath(QString::fromStdString(ca_file)); - - if(!certs.isEmpty()) - { - //qDebug() << "LLEmbeddedBrowser::" << __FUNCTION__ << "certs read: " << certs; - - // Set the default CA cert for Qt's SSL implementation. - QSslConfiguration config = QSslConfiguration::defaultConfiguration(); - config.setCaCertificates(certs); - QSslConfiguration::setDefaultConfiguration(config); - result = true; - } - - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLEmbeddedBrowser::addCAFile(const std::string &ca_file) -{ - // Enabling this can help diagnose certificate verification issues. - const bool cert_debugging_on = false; - - if ( cert_debugging_on ) - { - //qDebug() << "\n\nLLEmbeddedBrowser::" << __FUNCTION__ << " ------------------- (Before add)"; - QSslCertificate cert; - foreach(cert, QSslSocket::defaultCaCertificates()) - { - //qDebug() << cert.issuerInfo(QSslCertificate::CommonName) << " --- " << cert.subjectInfo(QSslCertificate::CommonName); - } - } - - bool result = false; - //qDebug() << "LLEmbeddedBrowser::" << __FUNCTION__ << "attempting to read certs from file: " << QString::fromStdString(ca_file); - - if ( cert_debugging_on ) - { - //qDebug() << "\n\nLLEmbeddedBrowser::" << __FUNCTION__ << " ------------------- (From CA.pem)"; - QList certs = QSslCertificate::fromPath(QString::fromStdString(ca_file)); - QSslCertificate cert; - foreach(cert, certs) - { - //qDebug() << cert.issuerInfo(QSslCertificate::CommonName) << " --- " << cert.subjectInfo(QSslCertificate::CommonName); - } - } - - result = QSslSocket::addDefaultCaCertificates(QString::fromStdString(ca_file)); - - if ( cert_debugging_on ) - { - //qDebug() << "\n\nLLEmbeddedBrowser::" << __FUNCTION__ << " ------------------- (After add)"; - QSslCertificate cert; - foreach(cert, QSslSocket::defaultCaCertificates()) - { - //qDebug() << cert.issuerInfo(QSslCertificate::CommonName) << " --- " << cert.subjectInfo(QSslCertificate::CommonName); - } - } - - return result; -} - -void LLEmbeddedBrowser::setIgnoreSSLCertErrors(bool ignore) -{ - d->mIgnoreSSLCertErrors = ignore; -} - -bool LLEmbeddedBrowser::getIgnoreSSLCertErrors() -{ - return d->mIgnoreSSLCertErrors; -} - -const std::vector< std::string > LLEmbeddedBrowser::getInstalledCertsList() -{ - std::vector< std::string > cert_list; - - QSslCertificate cert; - foreach(cert, QSslSocket::defaultCaCertificates()) - { - QString cert_info=""; - - QString issuer_info=""; - issuer_info+="C="; - issuer_info+=cert.issuerInfo(QSslCertificate::CountryName); - issuer_info+=", ST="; - issuer_info+=cert.issuerInfo(QSslCertificate::StateOrProvinceName); - issuer_info+=", L="; - issuer_info+=cert.issuerInfo(QSslCertificate::LocalityName); - issuer_info+=", O="; - issuer_info+=cert.issuerInfo(QSslCertificate::Organization); - issuer_info+=", OU="; - issuer_info+=cert.issuerInfo(QSslCertificate::OrganizationalUnitName); - issuer_info+=", CN="; - issuer_info+=cert.issuerInfo(QSslCertificate::CommonName); - cert_info+=issuer_info; - cert_info+="\n"; - - QString subject_info=""; - subject_info+="C="; - subject_info+=cert.subjectInfo(QSslCertificate::CountryName); - subject_info+=", ST="; - subject_info+=cert.subjectInfo(QSslCertificate::StateOrProvinceName); - subject_info+=", L="; - subject_info+=cert.subjectInfo(QSslCertificate::LocalityName); - subject_info+=", O="; - subject_info+=cert.subjectInfo(QSslCertificate::Organization); - subject_info+=", OU="; - subject_info+=cert.subjectInfo(QSslCertificate::OrganizationalUnitName); - subject_info+=", CN="; - subject_info+=cert.subjectInfo(QSslCertificate::CommonName); - cert_info+=subject_info; - cert_info+="\n"; - - cert_info+="Not valid before: "; - cert_info+=cert.effectiveDate().toString(); - cert_info+="\n"; - cert_info+="Not valid after: "; - cert_info+=cert.expiryDate().toString(); - cert_info+="\n"; - - cert_list.push_back( llToStdString(cert_info) ); - } - return cert_list; -} - -// Second Life viewer specific functions -void LLEmbeddedBrowser::setSLObjectEnabled( bool enabled ) -{ - foreach ( LLEmbeddedBrowserWindow* window, d->windows ) - { - window->setSLObjectEnabled( enabled ); - } -} - -void LLEmbeddedBrowser::setAgentLanguage( const std::string& agent_language ) -{ - foreach ( LLEmbeddedBrowserWindow* window, d->windows ) - { - window->setAgentLanguage( agent_language ); - } -} - -void LLEmbeddedBrowser::setAgentRegion( const std::string& agent_region ) -{ - foreach ( LLEmbeddedBrowserWindow* window, d->windows ) - { - window->setAgentRegion( agent_region ); - } -} - -void LLEmbeddedBrowser::setAgentLocation( double x, double y, double z ) -{ - foreach ( LLEmbeddedBrowserWindow* window, d->windows ) - { - window->setAgentLocation( x, y, z ); - } -} - -void LLEmbeddedBrowser::setAgentGlobalLocation( double x, double y, double z ) -{ - foreach ( LLEmbeddedBrowserWindow* window, d->windows ) - { - window->setAgentGlobalLocation( x, y, z ); - } -} - -void LLEmbeddedBrowser::setAgentOrientation( double angle ) -{ - foreach ( LLEmbeddedBrowserWindow* window, d->windows ) - { - window->setAgentOrientation( angle ); - } -} - -void LLEmbeddedBrowser::setAgentMaturity( const std::string& agent_maturity ) -{ - foreach ( LLEmbeddedBrowserWindow* window, d->windows ) - { - window->setAgentMaturity( agent_maturity ); - } -} - -void LLEmbeddedBrowser::emitLocation() -{ - foreach ( LLEmbeddedBrowserWindow* window, d->windows ) - { - window->emitLocation(); - } -} - -void LLEmbeddedBrowser::emitMaturity() -{ - foreach ( LLEmbeddedBrowserWindow* window, d->windows ) - { - window->emitMaturity(); - } -} - -void LLEmbeddedBrowser::emitLanguage() -{ - foreach ( LLEmbeddedBrowserWindow* window, d->windows ) - { - window->emitLanguage(); - } -} - -void LLEmbeddedBrowser::setPageZoomFactor( double factor ) -{ - foreach ( LLEmbeddedBrowserWindow* window, d->windows ) - { - window->setPageZoomFactor( factor ); - } -} - -void LLEmbeddedBrowser::qtMessageHandler(QtMsgType type, const char *msg) -{ - std::string msg_type(""); - switch (type) - { - case QtDebugMsg: - msg_type="Debug"; - break; - case QtWarningMsg: - msg_type="Warning"; - break; - case QtCriticalMsg: - msg_type="Critical"; - break; - case QtFatalMsg: - msg_type="Fatal"; - break; - }; - - foreach ( LLEmbeddedBrowserWindow* window, sInstance->d->windows ) - { - - window->onQtDebugMessage( std::string( msg ), msg_type); - } -} - -void LLEmbeddedBrowser::enableQtMessageHandler( bool enable ) -{ - if ( enable ) - { - qInstallMsgHandler( qtMessageHandler ); - } - else - { - // remove handler - qInstallMsgHandler(0); - }; -} - -LLNetworkCookieJar::LLNetworkCookieJar(QObject* parent, LLEmbeddedBrowser *browser) - : NetworkCookieJar(parent) - , mAllowCookies(true) - , mBrowser(browser) -{ -} - -LLNetworkCookieJar::~LLNetworkCookieJar() -{ -} - -QList LLNetworkCookieJar::cookiesForUrl(const QUrl& url) const -{ - if (!mAllowCookies) - return QList(); - return NetworkCookieJar::cookiesForUrl(url); -} - -bool LLNetworkCookieJar::setCookiesFromUrl(const QList &cookie_list, const QUrl& url) -{ - if (!mAllowCookies) - return false; - return NetworkCookieJar::setCookiesFromUrl(cookie_list, url); -} - -void LLNetworkCookieJar::onCookieSetFromURL(const QNetworkCookie &cookie, const QUrl &url, bool already_dead) -{ -// qDebug() << "LLNetworkCookieJar::" << __FUNCTION__ << (already_dead?"set dead cookie":"set cookie ") << cookie; - - if(mBrowser) - { - QByteArray cookie_bytes = cookie.toRawForm(QNetworkCookie::Full); - std::string cookie_string(cookie_bytes.data(), cookie_bytes.size()); - std::string url_string = llToStdString(url); - mBrowser->cookieChanged(cookie_string, url_string, already_dead); - } -} - -void LLNetworkCookieJar::clear() -{ - clearCookies(); -} - -void LLNetworkCookieJar::setCookiesFromRawForm(const std::string &cookie_string) -{ - QByteArray cookie_bytearray(cookie_string.data(), cookie_string.size()); - QList cookie_list = QNetworkCookie::parseCookies(cookie_bytearray); - setCookies(cookie_list); -} - -std::string LLNetworkCookieJar::getAllCookiesInRawForm() -{ - std::string result; - - QList cookie_list = allCookies(); - - foreach (const QNetworkCookie &cookie, cookie_list) - { - QByteArray raw_form = cookie.toRawForm(QNetworkCookie::Full); - result.append(raw_form.data(), raw_form.size()); - result.append("\n"); - } - - return result; -} - -#include "llembeddedbrowserwindow_p.h" -#include - -QGraphicsWebView *LLEmbeddedBrowserPrivate::findView(QNetworkReply *reply) -{ - for (int i = 0; i < windows.count(); ++i) - if (windows[i]->d->mView->url() == reply->url()) - return windows[i]->d->mView; - return windows[0]->d->mView; -} - -bool LLEmbeddedBrowserPrivate::authRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password) -{ - bool result = false; - -// qDebug() << "LLEmbeddedBrowser::" << __FUNCTION__ << "requesting auth for url " << QString::fromStdString(in_url) << ", realm " << QString::fromStdString(in_realm); -// -// qDebug() << "LLEmbeddedBrowser::" << __FUNCTION__ << "window count is " << windows.count(); - - if(windows.count() > 1) - { - qDebug() << "LLEmbeddedBrowser::" << __FUNCTION__ << "WARNING: authRequest called with more than one window, using the first one"; - } - - LLEmbeddedBrowserWindow* window = windows.first(); - - if(window) - { - result = window->authRequest(in_url, in_realm, out_username, out_password); - } - - return result; -} - -bool LLEmbeddedBrowserPrivate::certError(const std::string &in_url, const std::string &in_msg) -{ - bool result = false; - - LLEmbeddedBrowserWindow* window = windows.first(); - if(window) - { - result = window->certError(in_url, in_msg); - } - - return result; -} diff --git a/indra/llqtwebkit/llembeddedbrowser.h b/indra/llqtwebkit/llembeddedbrowser.h deleted file mode 100644 index c21a6b063d..0000000000 --- a/indra/llqtwebkit/llembeddedbrowser.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LLEMBEDDEDBROWSER_H -#define LLEMBEDDEDBROWSER_H - -#include -#include -#include -#include - -class LLEmbeddedBrowserWindow; -class LLEmbeddedBrowserWindowObserver; - -class LLEmbeddedBrowserPrivate; -class LLEmbeddedBrowser -{ - public: - LLEmbeddedBrowser(); - virtual ~LLEmbeddedBrowser(); - - static LLEmbeddedBrowser* getInstance(); - - bool init(std::string application_directory, - std::string component_directory, - std::string profile_directory, - void* native_window_handle); - bool reset(); - bool clearCache(); - bool enableProxy(bool enabled, std::string host_name, int port); - bool clearAllCookies(); - void setCookies(const std::string &cookies); - std::string getAllCookies(); - - void enableCookies( bool enabled ); - void enableCookiesTransient( bool enabled ); - bool areCookiesEnabled(); - void enablePlugins( bool enabled ); - void enablePluginsTransient( bool enabled ); - bool arePluginsEnabled(); - void enableJavaScript( bool enabled ); - void enableJavaScriptTransient( bool enabled ); - bool isJavaScriptEnabled(); - - bool showWebInspector(bool show); - std::string getGREVersion(); - void setBrowserAgentId(std::string id); - void setHostLanguage( const std::string& host_language ); - LLEmbeddedBrowserWindow* createBrowserWindow(int width, int height, const std::string target); - bool destroyBrowserWindow(LLEmbeddedBrowserWindow* browser_window); - void setLastError(int error_number); - void clearLastError(); - int getLastError(); - int getWindowCount() const; - void pump(int max_milliseconds); - void cookieChanged(const std::string &cookie, const std::string &url, bool dead); - bool setCAFile(const std::string &ca_file); - bool addCAFile(const std::string &ca_file); - void setIgnoreSSLCertErrors(bool ignore); - bool getIgnoreSSLCertErrors(); - const std::vector< std::string > getInstalledCertsList(); - - void enableQtMessageHandler( bool enable ); - - void setPageZoomFactor( double factor ); - - // Second Life specific functions - void setSLObjectEnabled( bool enabled ); - void setAgentLanguage( const std::string& agent_language ); - void setAgentRegion( const std::string& agent_region ); - void setAgentLocation( double x, double y, double z ); - void setAgentGlobalLocation( double x, double y, double z ); - void setAgentOrientation( double angle ); - void setAgentMaturity( const std::string& agent_maturity ); - void emitLocation(); - void emitMaturity(); - void emitLanguage(); - - private: - friend class LLEmbeddedBrowserWindow; - friend class LLEmbeddedBrowserWindowPrivate; - LLEmbeddedBrowserPrivate *d; - bool mPluginsEnabled; - bool mJavaScriptEnabled; - bool mCookiesEnabled; - - static void qtMessageHandler(QtMsgType type, const char *msg); - - static LLEmbeddedBrowser* sInstance; -}; - -#endif // LLEMBEDDEDBROWSER_H - diff --git a/indra/llqtwebkit/llembeddedbrowser_p.h b/indra/llqtwebkit/llembeddedbrowser_p.h deleted file mode 100644 index 9f9f9cd027..0000000000 --- a/indra/llqtwebkit/llembeddedbrowser_p.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LLEMBEDDEDBROWSER_P_H -#define LLEMBEDDEDBROWSER_P_H - -#include -#include -#if QT_VERSION >= 0x040500 -#include -#endif - -#include "networkcookiejar.h" -#include "llembeddedbrowser.h" - -#include - -class LLEmbeddedBrowser; -class LLNetworkCookieJar : public NetworkCookieJar -{ -public: - LLNetworkCookieJar(QObject *parent, LLEmbeddedBrowser *browser); - ~LLNetworkCookieJar(); - - QList cookiesForUrl(const QUrl& url) const; - bool setCookiesFromUrl(const QList &cookie_list, const QUrl& url); - - /*virtual*/ void onCookieSetFromURL(const QNetworkCookie &cookie, const QUrl &url, bool already_dead); - - void clear(); - - void setCookiesFromRawForm(const std::string &cookie_string); - std::string getAllCookiesInRawForm(); - - bool mAllowCookies; - LLEmbeddedBrowser *mBrowser; -}; - -class LLNetworkAccessManager; -class LLEmbeddedBrowserPrivate -{ -public: - LLEmbeddedBrowserPrivate(); - ~LLEmbeddedBrowserPrivate(); - - bool authRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password); - bool certError(const std::string &in_url, const std::string &in_msg); - - int mErrorNum; - void* mNativeWindowHandle; - LLNetworkAccessManager *mNetworkAccessManager; - QApplication *mApplication; -#if QT_VERSION >= 0x040500 - QNetworkDiskCache *mDiskCache; -#endif - LLNetworkCookieJar *mNetworkCookieJar; - - QGraphicsWebView *findView(QNetworkReply *); - - QString mStorageDirectory; - QList windows; - - std::string mHostLanguage; - bool mIgnoreSSLCertErrors; -}; - -#endif - diff --git a/indra/llqtwebkit/llembeddedbrowserwindow.cpp b/indra/llqtwebkit/llembeddedbrowserwindow.cpp deleted file mode 100644 index c990d5567c..0000000000 --- a/indra/llqtwebkit/llembeddedbrowserwindow.cpp +++ /dev/null @@ -1,1136 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "llembeddedbrowserwindow.h" -#include "llembeddedbrowserwindow_p.h" - -#include "llembeddedbrowser.h" -#include "llembeddedbrowser_p.h" -#include "llnetworkaccessmanager.h" - -#ifdef STATIC_QT - #include - // Enable gif and jpeg plugins, since web pages look pretty bleak without gifs or jpegs. - // Qt 4.7 uses the system gif and jpeg libraries by default, so this is no longer necessary. -// Q_IMPORT_PLUGIN(qgif) -// Q_IMPORT_PLUGIN(qjpeg) -#ifndef LL_LINUX - // Qt also has its own translators for CJK text encodings we need to pull in. - Q_IMPORT_PLUGIN(qcncodecs) - Q_IMPORT_PLUGIN(qjpcodecs) - Q_IMPORT_PLUGIN(qkrcodecs) - Q_IMPORT_PLUGIN(qtwcodecs) -#endif -#endif - -//#define LLEMBEDDEDBROWSER_DEBUG 1 - -#ifdef LLEMBEDDEDBROWSER_DEBUG -#include -#endif - -#if LL_DARWIN || defined(STATIC_QT) - // Don't define qt_sendSpontaneousEvent on the mac -- it causes a multiply-defined symbol. - extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); -#else - #include - bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event) - { - return QCoreApplication::sendSpontaneousEvent(receiver, event); - } -#endif - -LLEmbeddedBrowserWindow::LLEmbeddedBrowserWindow() -{ - d = new LLEmbeddedBrowserWindowPrivate(); - - d->mPage = new LLWebPage; - d->mInspector = new QWebInspector; - d->mInspector->setPage(d->mPage); - d->mPage->window = this; - d->mView = new LLWebView; - d->mPage->webView = d->mView; - d->mView->window = this; - d->mView->setPage(d->mPage); - d->mGraphicsScene = new LLGraphicsScene; - d->mGraphicsScene->window = this; - d->mGraphicsView = new QGraphicsView; - d->mGraphicsScene->addItem(d->mView); - d->mGraphicsView->setScene(d->mGraphicsScene); - d->mGraphicsScene->setStickyFocus(true); - d->mGraphicsView->viewport()->setParent(0); - - mEnableLoadingOverlay = false; -} - -LLEmbeddedBrowserWindow::~LLEmbeddedBrowserWindow() -{ - delete d; -} - -void LLEmbeddedBrowserWindow::setParent(LLEmbeddedBrowser* parent) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << parent; -#endif - d->mParent = parent; - if (parent) - { - d->mPage->setNetworkAccessManager(parent->d->mNetworkAccessManager); - } else - { - d->mPage->setNetworkAccessManager(0); - } -} - -void LLEmbeddedBrowserWindow::showWebInspector(bool show) -{ - if ( d ) - { - if ( d->mInspector ) - { - d->mInspector->setVisible( show ); - } - } -} - -void LLEmbeddedBrowserWindow::enableLoadingOverlay(bool enable) -{ - mEnableLoadingOverlay = enable; -} - -// change the background color that gets used between pages (usually white) -void LLEmbeddedBrowserWindow::setBackgroundColor(const uint8_t red, const uint8_t green, const uint8_t blue) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << red << green << blue; -#endif - d->backgroundColor = QColor(red, green, blue); -} - -// -void LLEmbeddedBrowserWindow::setEnabled(bool enabled) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << enabled; -#endif - d->mEnabled = enabled; -} - -// allow consumers of this class to observe events - add themselves as an observer -bool LLEmbeddedBrowserWindow::addObserver(LLEmbeddedBrowserWindowObserver* observer) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << observer; -#endif - return d->mEventEmitter.addObserver(observer); -} - -// allow consumers of this class to observe events - remove themselves as an observer -bool LLEmbeddedBrowserWindow::remObserver(LLEmbeddedBrowserWindowObserver* observer) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << observer; -#endif - return d->mEventEmitter.remObserver(observer); -} - -int LLEmbeddedBrowserWindow::getObserverNumber() -{ - return d->mEventEmitter.getObserverNumber(); -} - -// used by observers of this class to get the current URI -std::string& LLEmbeddedBrowserWindow::getCurrentUri() -{ - d->mCurrentUri = llToStdString(d->mPage->mainFrame()->url()); - return d->mCurrentUri; -} - -// utility method that is used by observers to retrieve data after an event -int16_t LLEmbeddedBrowserWindow::getPercentComplete() -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__; -#endif - return d->mPercentComplete; -} - -// utility method that is used by observers to retrieve data after an event -std::string& LLEmbeddedBrowserWindow::getStatusMsg() -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__; -#endif - return d->mStatusText; -} - -// render a page into memory and grab the window -unsigned char* LLEmbeddedBrowserWindow::grabWindow(int x, int y, int width, int height) -{ -#if LLEMBEDDEDBROWSER_DEBUG > 10 - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << x << y << width << height; -#endif - // only grab the window if it's enabled - if (!d->mEnabled) - return 0; - - if (!d->mDirty) - return d->mPageBuffer; - - Q_ASSERT(d->mImage.size() == d->mView->size()); - if (!d->mPage->mainFrame()->url().isValid()) - { - d->mImage.fill(d->backgroundColor.value()); - } else - { - QPainter painter(&d->mImage); - - QRectF r(x, y, width, height); - QRect g(0, 0, d->mView->width(), d->mView->height()); - d->mGraphicsView->render(&painter, r, g); - - d->mDirty = false; - - const bool spinner_enabled = false; - if ( spinner_enabled ) - { - const time_t seconds_before_show_overlay = 1; - - if ( mEnableLoadingOverlay && - d->mShowLoadingOverlay && - time(NULL) - d->mTimeLoadStarted >= seconds_before_show_overlay ) - { - painter.setRenderHint(QPainter::Antialiasing);; - - QBrush brush; - QPen pen; - - int size = width; - if ( height < width ) - size = height; - - const int symbol_translucency = 64; // 0=fully trans, 255=opaque - const int symbol_proportion_of_sceen = 8; // (1/8) - const int symbol_diameter = size/(symbol_proportion_of_sceen); - const int symbol_start_line = symbol_diameter*2/3; - const int symbol_end_line = symbol_diameter; - const int symbol_num_segments = 20; - const int symbol_line_width = size/60; - if ( size < 4 ) size = 4; - - QColor background_color(QColor(128,128,128,symbol_translucency)); - brush.setColor(background_color); - brush.setStyle(Qt::SolidPattern); - pen.setColor(background_color); - painter.setPen(pen); - painter.setBrush(brush); - painter.drawRect(0,0,width, height); - - painter.translate(QPoint(width/2, height/2)); - - static int offset=0; - painter.rotate(((qreal)(offset++%(symbol_num_segments))/(qreal)symbol_num_segments)*360.0f); - - for ( int count=0; countmDirty = true; // force dirty so updates happen frequently during load - } - } - - painter.end(); - if (d->mFlipBitmap) - { - d->mImage = d->mImage.mirrored(); - } - d->mImage = d->mImage.rgbSwapped(); - } - - d->mPageBuffer = d->mImage.bits(); - - return d->mPageBuffer; -} - -// return the buffer that contains the rendered page -unsigned char* LLEmbeddedBrowserWindow::getPageBuffer() -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__; -#endif - return d->mPageBuffer; -} - -int16_t LLEmbeddedBrowserWindow::getBrowserWidth() -{ -#if LLEMBEDDEDBROWSER_DEBUG > 10 - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__; -#endif - return d->mImage.width(); -} - -int16_t LLEmbeddedBrowserWindow::getBrowserHeight() -{ -#if LLEMBEDDEDBROWSER_DEBUG > 10 - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__; -#endif - return d->mImage.height(); -} - -int16_t LLEmbeddedBrowserWindow::getBrowserDepth() -{ -#if LLEMBEDDEDBROWSER_DEBUG > 10 - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__; -#endif - return 4; -} - -int32_t LLEmbeddedBrowserWindow::getBrowserRowSpan() -{ -#if LLEMBEDDEDBROWSER_DEBUG > 10 - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__; -#endif - return 4 * getBrowserWidth(); -} - -bool LLEmbeddedBrowserWindow::navigateTo(const std::string uri) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << QString::fromStdString(uri); -#endif - QUrl url = QUrl::fromUserInput(QString::fromStdString(uri)); - - d->mPage->triggerAction(QWebPage::Stop); - d->mPage->mainFrame()->setUrl(url); - d->mPage->mainFrame()->load(url); - return true; -} - -bool LLEmbeddedBrowserWindow::userAction(LLQtWebKit::EUserAction action) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << action; -#endif - bool result = true; - - switch(action) - { - case LLQtWebKit::UA_EDIT_CUT: - d->mPage->triggerAction(QWebPage::Cut); - break; - case LLQtWebKit::UA_EDIT_COPY: - d->mPage->triggerAction(QWebPage::Copy); - break; - case LLQtWebKit::UA_EDIT_PASTE: - d->mPage->triggerAction(QWebPage::Paste); - break; - case LLQtWebKit::UA_NAVIGATE_STOP: - d->mPage->triggerAction(QWebPage::Stop); - break; - case LLQtWebKit::UA_NAVIGATE_BACK: - d->mPage->triggerAction(QWebPage::Back); - break; - case LLQtWebKit::UA_NAVIGATE_FORWARD: - d->mPage->triggerAction(QWebPage::Forward); - break; - case LLQtWebKit::UA_NAVIGATE_RELOAD: - d->mPage->triggerAction(QWebPage::ReloadAndBypassCache); - break; - default: - result = false; - break; - } - - return result; -} - -bool LLEmbeddedBrowserWindow::userActionIsEnabled(LLQtWebKit::EUserAction action) -{ -#if LLEMBEDDEDBROWSER_DEBUG > 10 - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << action; -#endif - - bool result; - - switch(action) - { - case LLQtWebKit::UA_EDIT_CUT: - result = d->mPage->action(QWebPage::Cut)->isEnabled(); - break; - case LLQtWebKit::UA_EDIT_COPY: - result = d->mPage->action(QWebPage::Copy)->isEnabled(); - break; - case LLQtWebKit::UA_EDIT_PASTE: - result = d->mPage->action(QWebPage::Paste)->isEnabled(); - break; - case LLQtWebKit::UA_NAVIGATE_STOP: - result = true; - break; - case LLQtWebKit::UA_NAVIGATE_BACK: - result = d->mPage->history()->canGoBack(); - break; - case LLQtWebKit::UA_NAVIGATE_FORWARD: - result = d->mPage->history()->canGoForward(); - break; - case LLQtWebKit::UA_NAVIGATE_RELOAD: - result = true; - break; - default: - result = false; - break; - } - return result; -} - -// set the size of the browser window -bool LLEmbeddedBrowserWindow::setSize(int16_t width, int16_t height) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << width << height; -#endif - d->mPageBuffer = NULL; - d->mImage = QImage(QSize(width, height), QImage::Format_RGB32); - d->mGraphicsView->resize(width, height); - d->mView->resize(width, height); - d->mImage.fill(d->backgroundColor.rgb()); - return true; -} - -bool LLEmbeddedBrowserWindow::flipWindow(bool flip) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << flip; -#endif - d->mFlipBitmap = flip; - return true; -} - -static Qt::KeyboardModifiers convert_modifiers(LLQtWebKit::EKeyboardModifier modifiers) -{ - Qt::KeyboardModifiers result = Qt::NoModifier; - - if(modifiers & LLQtWebKit::KM_MODIFIER_SHIFT) - result |= Qt::ShiftModifier; - - if(modifiers & LLQtWebKit::KM_MODIFIER_CONTROL) - result |= Qt::ControlModifier; - - if(modifiers & LLQtWebKit::KM_MODIFIER_ALT) - result |= Qt::AltModifier; - - if(modifiers & LLQtWebKit::KM_MODIFIER_META) - result |= Qt::MetaModifier; - - return result; -} - -static Qt::MouseButton qt_button_from_button_number(int button) -{ - Qt::MouseButton result; - - switch(button) - { - default: result = Qt::NoButton; break; - case 0: result = Qt::LeftButton; break; - case 1: result = Qt::RightButton; break; - case 2: result = Qt::MidButton; break; - case 3: result = Qt::XButton1; break; - case 4: result = Qt::XButton2; break; - } - - return result; -} - -static QEvent::Type event_from_mouse_event(LLQtWebKit::EMouseEvent mouse_event) -{ - QEvent::Type result; - - switch(mouse_event) - { - default: - result = QEvent::None; - break; - - case LLQtWebKit::ME_MOUSE_MOVE: - result = QEvent::MouseMove; - break; - - case LLQtWebKit::ME_MOUSE_DOWN: - result = QEvent::MouseButtonPress; - break; - - case LLQtWebKit::ME_MOUSE_UP: - result = QEvent::MouseButtonRelease; - break; - - case LLQtWebKit::ME_MOUSE_DOUBLE_CLICK: - result = QEvent::MouseButtonDblClick; - break; - } - - return result; -} - -static QEvent::Type event_from_keyboard_event(LLQtWebKit::EKeyEvent keyboard_event) -{ - QEvent::Type result; - - switch(keyboard_event) - { - default: - result = QEvent::None; - break; - - case LLQtWebKit::KE_KEY_DOWN: - case LLQtWebKit::KE_KEY_REPEAT: - result = QEvent::KeyPress; - break; - - case LLQtWebKit::KE_KEY_UP: - result = QEvent::KeyRelease; - break; - } - - return result; -} - -void LLEmbeddedBrowserWindow::mouseEvent(LLQtWebKit::EMouseEvent mouse_event, int16_t button, int16_t x, int16_t y, LLQtWebKit::EKeyboardModifier modifiers) -{ -#if LLEMBEDDEDBROWSER_DEBUG > 10 - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << x << y; -#endif - - QEvent::Type type = event_from_mouse_event(mouse_event); - Qt::MouseButton qt_button = qt_button_from_button_number(button); - Qt::KeyboardModifiers qt_modifiers = convert_modifiers(modifiers); - - if(type == QEvent::MouseMove) - { - // Mouse move events should always use "no button". - qt_button = Qt::NoButton; - } - - // FIXME: should the current button state be updated before or after constructing the event? - switch(type) - { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonDblClick: - d->mCurrentMouseButtonState |= qt_button; - break; - - case QEvent::MouseButtonRelease: - d->mCurrentMouseButtonState &= ~qt_button; - break; - - default: - break; - } - - QMouseEvent event(type, QPoint(x, y), qt_button, d->mCurrentMouseButtonState, qt_modifiers); - - qt_sendSpontaneousEvent(d->mGraphicsView->viewport(), &event); -} - -void LLEmbeddedBrowserWindow::scrollWheelEvent(int16_t x, int16_t y, int16_t scroll_x, int16_t scroll_y, LLQtWebKit::EKeyboardModifier modifiers) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << x << y; -#endif - - Qt::KeyboardModifiers qt_modifiers = convert_modifiers(modifiers); - - if(scroll_y != 0) - { - QWheelEvent event(QPoint(x, y), scroll_y, d->mCurrentMouseButtonState, qt_modifiers, Qt::Vertical); - qApp->sendEvent(d->mGraphicsView->viewport(), &event); - } - - if(scroll_x != 0) - { - QWheelEvent event(QPoint(x, y), scroll_x, d->mCurrentMouseButtonState, qt_modifiers, Qt::Horizontal); - qApp->sendEvent(d->mGraphicsView->viewport(), &event); - } -} - - -// utility methods to set an error message so something else can look at it -void LLEmbeddedBrowserWindow::scrollByLines(int16_t lines) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << lines; -#endif - int currentScrollValue = d->mPage->mainFrame()->scrollBarValue(Qt::Vertical); - d->mPage->mainFrame()->setScrollBarValue(Qt::Vertical, currentScrollValue + lines); -} - -// Send a keyboard event with native event data. -void LLEmbeddedBrowserWindow::keyboardEvent( - LLQtWebKit::EKeyEvent key_event, - uint32_t key_code, - const char *utf8_text, - LLQtWebKit::EKeyboardModifier modifiers, - uint32_t native_scan_code, - uint32_t native_virtual_key, - uint32_t native_modifiers) -{ - QEvent::Type type = event_from_keyboard_event(key_event); - Qt::KeyboardModifiers qt_modifiers = convert_modifiers(modifiers); - bool auto_repeat = (key_event == LLQtWebKit::KE_KEY_REPEAT); - QString text = QString::fromUtf8(utf8_text); - - Qt::Key key = Qt::Key_unknown; - - switch (key_code) - { - case LLQtWebKit::KEY_RETURN: key = Qt::Key_Return; break; - case LLQtWebKit::KEY_LEFT: key = Qt::Key_Left; break; - case LLQtWebKit::KEY_RIGHT: key = Qt::Key_Right; break; - case LLQtWebKit::KEY_UP: key = Qt::Key_Up; break; - case LLQtWebKit::KEY_DOWN: key = Qt::Key_Down; break; - case LLQtWebKit::KEY_ESCAPE: key = Qt::Key_Escape; break; - case LLQtWebKit::KEY_BACKSPACE: key = Qt::Key_Backspace; break; - case LLQtWebKit::KEY_DELETE: key = Qt::Key_Delete; break; - case LLQtWebKit::KEY_SHIFT: key = Qt::Key_Shift; break; - case LLQtWebKit::KEY_CONTROL: key = Qt::Key_Control; break; - case LLQtWebKit::KEY_ALT: key = Qt::Key_Alt; break; - case LLQtWebKit::KEY_HOME: key = Qt::Key_Home; break; - case LLQtWebKit::KEY_END: key = Qt::Key_End; break; - case LLQtWebKit::KEY_PAGE_UP: key = Qt::Key_PageUp; break; - case LLQtWebKit::KEY_PAGE_DOWN: key = Qt::Key_PageDown; break; - case LLQtWebKit::KEY_HYPHEN: key = Qt::Key_hyphen; break; - case LLQtWebKit::KEY_EQUALS: key = Qt::Key_Equal; break; - case LLQtWebKit::KEY_INSERT: key = Qt::Key_Insert; break; - case LLQtWebKit::KEY_CAPSLOCK: key = Qt::Key_CapsLock; break; - case LLQtWebKit::KEY_TAB: key = Qt::Key_Tab; break; - case LLQtWebKit::KEY_ADD: key = Qt::Key_Plus; break; - case LLQtWebKit::KEY_SUBTRACT: key = Qt::Key_Minus; break; - case LLQtWebKit::KEY_MULTIPLY: key = Qt::Key_Asterisk; break; - case LLQtWebKit::KEY_DIVIDE: key = Qt::Key_Slash; break; - case LLQtWebKit::KEY_F1: key = Qt::Key_F1; break; - case LLQtWebKit::KEY_F2: key = Qt::Key_F2; break; - case LLQtWebKit::KEY_F3: key = Qt::Key_F3; break; - case LLQtWebKit::KEY_F4: key = Qt::Key_F4; break; - case LLQtWebKit::KEY_F5: key = Qt::Key_F5; break; - case LLQtWebKit::KEY_F6: key = Qt::Key_F6; break; - case LLQtWebKit::KEY_F7: key = Qt::Key_F7; break; - case LLQtWebKit::KEY_F8: key = Qt::Key_F8; break; - case LLQtWebKit::KEY_F9: key = Qt::Key_F9; break; - case LLQtWebKit::KEY_F10: key = Qt::Key_F10; break; - case LLQtWebKit::KEY_F11: key = Qt::Key_F11; break; - case LLQtWebKit::KEY_F12: key = Qt::Key_F12; break; - - case LLQtWebKit::KEY_PAD_UP: key = Qt::Key_Up; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_DOWN: key = Qt::Key_Down; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_LEFT: key = Qt::Key_Left; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_RIGHT: key = Qt::Key_Right; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_HOME: key = Qt::Key_Home; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_END: key = Qt::Key_End; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_PGUP: key = Qt::Key_PageUp; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_PGDN: key = Qt::Key_PageDown; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_CENTER: key = Qt::Key_5; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_INS: key = Qt::Key_Insert; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_DEL: key = Qt::Key_Delete; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_RETURN: key = Qt::Key_Enter; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_ADD: key = Qt::Key_Plus; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_SUBTRACT: key = Qt::Key_Minus; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_MULTIPLY: key = Qt::Key_Asterisk; qt_modifiers |= Qt::KeypadModifier; break; - case LLQtWebKit::KEY_PAD_DIVIDE: key = Qt::Key_Slash; qt_modifiers |= Qt::KeypadModifier; break; - - case LLQtWebKit::KEY_NONE: key = Qt::Key_unknown; break; - - default: - key = (Qt::Key)toupper(key_code); - break; - } - - - QKeyEvent *event = - QKeyEvent::createExtendedKeyEvent( - type, - key, - qt_modifiers, - native_scan_code, - native_virtual_key, - native_modifiers, - text, - auto_repeat, - text.count()); - - qApp->sendEvent(d->mGraphicsScene, event); - - delete event; -} - - -// give focus to the browser so that input keyboard events work -void LLEmbeddedBrowserWindow::focusBrowser(bool focus_browser) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << focus_browser; -#endif - QEvent ev(QEvent::WindowActivate); - qApp->sendEvent(d->mGraphicsScene, &ev); - - QEvent ev2(QEvent::ActivationChange); - qApp->sendEvent(d->mGraphicsScene, &ev2); - - QFocusEvent event(focus_browser ? QEvent::FocusIn : QEvent::FocusOut, Qt::ActiveWindowFocusReason); - qApp->sendEvent(d->mPage, &event); -} - -void LLEmbeddedBrowserWindow::setWindowId(int window_id) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << window_id; -#endif - d->mWindowId = window_id; -} - -int LLEmbeddedBrowserWindow::getWindowId() -{ - return d->mWindowId; -} - -void LLEmbeddedBrowserWindow::proxyWindowOpened(const std::string target, const std::string uuid) -{ - LLWebPageOpenShim *shim = findShim(uuid); - if(!shim) - { - // We don't already have a shim with this uuid -- create one. - shim = new LLWebPageOpenShim(this, d->mPage); - d->mProxyPages.push_back(shim); - -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow::proxyWindowOpened: page list size is " << d->mProxyPages.size(); -#endif - } - - shim->setProxy(target, uuid); -} - -void LLEmbeddedBrowserWindow::proxyWindowClosed(const std::string uuid) -{ - LLWebPageOpenShim *shim = findShim(uuid); - if(shim) - { - deleteShim(shim); - } -} - -std::string LLEmbeddedBrowserWindow::evaluateJavaScript(std::string script) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << QString::fromStdString(script); -#endif - QString q_script = QString::fromStdString(script); - QString result = d->mPage->mainFrame()->evaluateJavaScript(q_script).toString(); - return llToStdString(result); -} - -void LLEmbeddedBrowserWindow::setHostLanguage(const std::string host_language) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << QString::fromStdString(host_language); -#endif - if ( d ) - if ( d->mPage ) - d->mPage->setHostLanguage( host_language ); -} - -void LLEmbeddedBrowserWindow::navigateErrorPage( int http_status_code ) -{ - LLEmbeddedBrowserWindowEvent event(getWindowId()); - event.setIntValue( http_status_code ); - - d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onNavigateErrorPage, event); -} - -void LLEmbeddedBrowserWindow::setNoFollowScheme(std::string scheme) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__ << QString::fromStdString(scheme); -#endif - d->mNoFollowScheme = QString::fromStdString(scheme); - // The scheme part of the url is what is before '://' - d->mNoFollowScheme = d->mNoFollowScheme.mid(0, d->mNoFollowScheme.indexOf("://")); -} - -std::string LLEmbeddedBrowserWindow::getNoFollowScheme() -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow" << __FUNCTION__; -#endif - return llToStdString(d->mNoFollowScheme); -} - -void LLEmbeddedBrowserWindow::prependHistoryUrl(std::string url) -{ -#ifdef WEBHISTORYPATCH - // *HACK: we only have a URL here, we set a "" title and "current time" as - // last visited time. - d->mPage->history()->prependItem(QString::fromStdString(url), - QString::fromAscii(""), - QDateTime::currentDateTime()); -#else - Q_UNUSED(url); -#endif -} - -void LLEmbeddedBrowserWindow::clearHistory() -{ - d->mPage->history()->clear(); -} - -std::string LLEmbeddedBrowserWindow::dumpHistory() -{ - std::ostringstream oss; - const QList &items = d->mPage->history()->backItems(9999); - oss << "cur: " << d->mPage->history()->currentItemIndex() << ":" - << d->mPage->history()->currentItem().url().toString().toAscii().data() << "\n"; - for (int i=0; i< items.count(); i++) { - oss << items[i].url().toString().toAscii().data() << "\n"; - } - return oss.str(); -} - -void LLEmbeddedBrowserWindow::cookieChanged(const std::string &cookie, const std::string &url, bool dead) -{ - LLEmbeddedBrowserWindowEvent event(getWindowId()); - event.setEventUri(url); - event.setStringValue(cookie); - event.setIntValue((int)dead); - - d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onCookieChanged, event); -} - -QWebPage *LLEmbeddedBrowserWindow::createWindow() -{ - QWebPage *result = NULL; - if(d->mOpeningSelf) - { - // Special case: opening self to set target, etc. -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow::createWindow: opening self to set target name. "; -#endif - result = d->mPage; - d->mOpeningSelf = false; - } - else - { - LLWebPageOpenShim *shim = new LLWebPageOpenShim(this, d->mPage); - d->mProxyPages.push_back(shim); - result = shim; - -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow::createWindow: page list size is " << d->mProxyPages.size(); -#endif - } - - return result; -} - -LLWebPageOpenShim *LLEmbeddedBrowserWindow::findShim(const std::string &uuid) -{ - LLEmbeddedBrowserWindowPrivate::ProxyList::iterator iter; - for(iter = d->mProxyPages.begin(); iter != d->mProxyPages.end(); iter++) - { - if((*iter)->matchesUUID(uuid)) - return *iter; - } - - return NULL; -} - -void LLEmbeddedBrowserWindow::deleteShim(LLWebPageOpenShim *shim) -{ - shim->window = 0; - shim->deleteLater(); - d->mProxyPages.remove(shim); - -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow::deleteShim: page list size is " << d->mProxyPages.size(); -#endif -} - -void LLEmbeddedBrowserWindow::setTarget(const std::string &target) -{ -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow::setTarget: setting target to " << QString::fromStdString(target); -#endif - - d->mOpeningSelf = true; - - std::stringstream s; - s << "window.open(\"\",\"" << target << "\");"; - - evaluateJavaScript(s.str()); -} - -std::string LLEmbeddedBrowserWindow::requestFilePicker() -{ - std::string filename_chosen; - - LLEmbeddedBrowserWindowEvent event(getWindowId()); - event.setEventUri(getCurrentUri()); - event.setStringValue("*.png;*.jpg"); - - // If there's at least one observer registered, call it with the event. - LLEmbeddedBrowserWindowPrivate::Emitter::iterator i = d->mEventEmitter.begin(); - if(i != d->mEventEmitter.end()) - { - filename_chosen = (*i)->onRequestFilePicker(event); - } - - return filename_chosen; -} - -bool LLEmbeddedBrowserWindow::authRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password) -{ - bool result = false; - -#ifdef LLEMBEDDEDBROWSER_DEBUG - qDebug() << "LLEmbeddedBrowserWindow::authRequest: requesting auth for url " << QString::fromStdString(in_url) << ", realm " << QString::fromStdString(in_realm); -#endif - - // If there's at least one observer registered, send it the auth request. - LLEmbeddedBrowserWindowPrivate::Emitter::iterator i = d->mEventEmitter.begin(); - if(i != d->mEventEmitter.end()) - { - result = (*i)->onAuthRequest(in_url, in_realm, out_username, out_password); - } - - return result; -} - -bool LLEmbeddedBrowserWindow::certError(const std::string &in_url, const std::string &in_msg) -{ - bool result = false; - - // If there's at least one observer registered, send it the auth request. - LLEmbeddedBrowserWindowPrivate::Emitter::iterator i = d->mEventEmitter.begin(); - if(i != d->mEventEmitter.end()) - { - result = (*i)->onCertError(in_url, in_msg); - } - - return result; -} - -void LLEmbeddedBrowserWindow::onQtDebugMessage( const std::string& msg, const std::string& msg_type) -{ - // If there's at least one observer registered, send it the auth request. - LLEmbeddedBrowserWindowPrivate::Emitter::iterator i = d->mEventEmitter.begin(); - if(i != d->mEventEmitter.end()) - { - (*i)->onQtDebugMessage(msg, msg_type); - } -} - -void LLEmbeddedBrowserWindow::setWhiteListRegex( const std::string& regex ) -{ - if ( d ) - if ( d->mPage ) - d->mPage->setWhiteListRegex( regex ); -} - -// Second Life viewer specific functions -void LLEmbeddedBrowserWindow::setSLObjectEnabled( bool enabled ) -{ - if ( d ) - if ( d->mPage ) - d->mPage->setSLObjectEnabled( enabled ); -} - -void LLEmbeddedBrowserWindow::setAgentLanguage( const std::string& agent_language ) -{ - if ( d ) - if ( d->mPage ) - d->mPage->setAgentLanguage( agent_language ); -} - -void LLEmbeddedBrowserWindow::setAgentRegion( const std::string& agent_region ) -{ - if ( d ) - if ( d->mPage ) - d->mPage->setAgentRegion( agent_region ); -} - -void LLEmbeddedBrowserWindow::setAgentLocation( double x, double y, double z ) -{ - if ( d ) - if ( d->mPage ) - d->mPage->setAgentLocation( x, y, z ); -} - -void LLEmbeddedBrowserWindow::setAgentGlobalLocation( double x, double y, double z ) -{ - if ( d ) - if ( d->mPage ) - d->mPage->setAgentGlobalLocation( x, y, z ); -} - -void LLEmbeddedBrowserWindow::setAgentOrientation( double angle ) -{ - if ( d ) - if ( d->mPage ) - d->mPage->setAgentOrientation( angle ); -} - -void LLEmbeddedBrowserWindow::setAgentMaturity( const std::string& agent_maturity ) -{ - if ( d ) - if ( d->mPage ) - d->mPage->setAgentMaturity( agent_maturity ); -} - -void LLEmbeddedBrowserWindow::emitLocation() -{ - if ( d ) - if ( d->mPage ) - d->mPage->emitLocation(); -} - -void LLEmbeddedBrowserWindow::emitMaturity() -{ - if ( d ) - if ( d->mPage ) - d->mPage->emitMaturity(); -} - -void LLEmbeddedBrowserWindow::emitLanguage() -{ - if ( d ) - if ( d->mPage ) - d->mPage->emitLanguage(); -} - -void LLEmbeddedBrowserWindow::setPageZoomFactor( double factor ) -{ - if ( d ) - if ( d->mPage ) - d->mPage->setPageZoomFactor( factor ); -} - -LLGraphicsScene::LLGraphicsScene() - : QGraphicsScene() - , window(0) -{ - connect(this, SIGNAL(changed(const QList &)), - this, SLOT(repaintRequestedSlot(const QList &))); -} - -void LLGraphicsScene::repaintRequestedSlot(const QList ®ions) -{ - if (!window) - return; - window->d->mDirty = true; - for (int i = 0; i < regions.count(); ++i) - { - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setEventUri(window->getCurrentUri()); - event.setRectValue(regions[i].x(), regions[i].y(), regions[i].width(), regions[i].height()); - - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onPageChanged, event); - } -} - -#include -#include -LLWebView::LLWebView(QGraphicsItem *parent) - : QGraphicsWebView(parent) - , window(0) -{ -} - -bool LLWebView::event(QEvent* event) -{ - if (window && event->type() == QEvent::CursorChange) { - QCursor cursor = this->cursor(); - if (currentShape != cursor.shape()) { - currentShape = cursor.shape(); - LLQtWebKit::ECursor llcursor; - switch(currentShape) - { - case Qt::ArrowCursor: - llcursor = LLQtWebKit::C_ARROW; - break; - case Qt::PointingHandCursor: - llcursor = LLQtWebKit::C_POINTINGHAND; - break; - case Qt::IBeamCursor: - llcursor = LLQtWebKit::C_IBEAM; - break; - case Qt::SplitVCursor: - llcursor = LLQtWebKit::C_SPLITV; - break; - case Qt::SplitHCursor: - llcursor = LLQtWebKit::C_SPLITH; - break; - default: - qWarning() << "Unhandled cursor shape:" << currentShape; - llcursor = LLQtWebKit::C_ARROW; - } - - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setEventUri(window->getCurrentUri()); - event.setIntValue((int)llcursor); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onCursorChanged, event); - } - - return true; - } - return QGraphicsWebView::event(event); -} - - -std::string llToStdString(const QString &s) -{ - return llToStdString(s.toUtf8()); -} - -std::string llToStdString(const QByteArray &bytes) -{ - return std::string(bytes.constData(), bytes.size()); -} - -std::string llToStdString(const QUrl &url) -{ - return llToStdString(url.toEncoded()); -} diff --git a/indra/llqtwebkit/llembeddedbrowserwindow.h b/indra/llqtwebkit/llembeddedbrowserwindow.h deleted file mode 100644 index 0c8080c15d..0000000000 --- a/indra/llqtwebkit/llembeddedbrowserwindow.h +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LLEMBEDDEDBROWSERWINDOW_H -#define LLEMBEDDEDBROWSERWINDOW_H - -#include -#include -#include -#if defined _MSC_VER && _MSC_VER < 1600 -#include "pstdint.h" -#else -#include // Use the C99 official header -#endif - -#include "llqtwebkit.h" - -class LLEmbeddedBrowser; -class LLWebPageOpenShim; -class QWebPage; - -//////////////////////////////////////////////////////////////////////////////// -// class for a "window" that holds a browser - there can be lots of these -class LLEmbeddedBrowserWindowPrivate; -class LLEmbeddedBrowserWindow -{ -public: - LLEmbeddedBrowserWindow(); - virtual ~LLEmbeddedBrowserWindow(); - - // housekeeping - void setParent(LLEmbeddedBrowser* parent); - bool setSize(int16_t width, int16_t height); - void focusBrowser(bool focus_browser); - void scrollByLines(int16_t lines); - void setWindowId(int window_id); - int getWindowId(); - void proxyWindowOpened(const std::string target, const std::string uuid); - void proxyWindowClosed(const std::string uuid); - - // random accessors - int16_t getPercentComplete(); - std::string& getStatusMsg(); - std::string& getCurrentUri(); - - // memory buffer management - unsigned char* grabWindow(int x, int y, int width, int height); - bool flipWindow(bool flip); - unsigned char* getPageBuffer(); - int16_t getBrowserWidth(); - int16_t getBrowserHeight(); - int16_t getBrowserDepth(); - int32_t getBrowserRowSpan(); - - // set background color that you see in between pages - default is white but sometimes useful to change - void setBackgroundColor(const uint8_t red, const uint8_t green, const uint8_t blue); - - // can turn off updates to a page - e.g. when it's hidden by your windowing system - void setEnabled(bool enabledIn); - - // navigation - bool userAction(LLQtWebKit::EUserAction action); - bool userActionIsEnabled(LLQtWebKit::EUserAction action); - bool navigateTo(const std::string uri); - - // javascript access/control - std::string evaluateJavaScript(std::string script); - - // redirection when you hit an error page - void navigateErrorPage( int http_status_code ); - - // host language setting - void setHostLanguage(const std::string host_language); - - // mouse & keyboard events - void mouseEvent(LLQtWebKit::EMouseEvent mouse_event, int16_t button, int16_t x, int16_t y, LLQtWebKit::EKeyboardModifier modifiers); - void scrollWheelEvent(int16_t x, int16_t y, int16_t scroll_x, int16_t scroll_y, LLQtWebKit::EKeyboardModifier modifiers); - void keyboardEvent( - LLQtWebKit::EKeyEvent key_event, - uint32_t key_code, - const char *utf8_text, - LLQtWebKit::EKeyboardModifier modifiers, - uint32_t native_scan_code, - uint32_t native_virtual_key, - uint32_t native_modifiers); - - // allow consumers of this class and to observe browser events - bool addObserver(LLEmbeddedBrowserWindowObserver* observer); - bool remObserver(LLEmbeddedBrowserWindowObserver* observer); - int getObserverNumber(); - - // accessor/mutator for scheme that browser doesn't follow - e.g. secondlife.com:// - void setNoFollowScheme(std::string scheme); - std::string getNoFollowScheme(); - - // prepend the current history with the given url - void prependHistoryUrl(std::string url); - // clear the URL history - void clearHistory(); - std::string dumpHistory(); - - void cookieChanged(const std::string &cookie, const std::string &url, bool dead); - - QWebPage *createWindow(); - - LLWebPageOpenShim *findShim(const std::string &uuid); - void deleteShim(LLWebPageOpenShim *shim); - void setTarget(const std::string &target); - - std::string requestFilePicker(); - - void showWebInspector(bool enabled); - - bool authRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password); - bool certError(const std::string &in_url, const std::string &in_msg); - - void onQtDebugMessage( const std::string& msg, const std::string& msg_type); - - void enableLoadingOverlay(bool enable); - - void setWhiteListRegex( const std::string& regex ); - - void setPageZoomFactor( double factor ); - - // Second Life specific functions - void setSLObjectEnabled( bool enabled ); - void setAgentLanguage( const std::string& agent_language ); - void setAgentRegion( const std::string& agent_region ); - void setAgentLocation( double x, double y, double z ); - void setAgentGlobalLocation( double x, double y, double z ); - void setAgentOrientation( double angle ); - void setAgentMaturity( const std::string& agent_maturity ); - void emitLocation(); - void emitMaturity(); - void emitLanguage(); - -private: - friend class LLWebPage; - friend class LLWebPageOpenShim; - friend class LLGraphicsScene; - friend class LLWebView; - friend class LLEmbeddedBrowserPrivate; - LLEmbeddedBrowserWindowPrivate *d; - bool mEnableLoadingOverlay; - -}; - - -// QString::toStdString converts to ascii, not utf8. Define our own versions that do utf8. - -#ifdef QSTRING_H -std::string llToStdString(const QString &s); -#endif - -#ifdef QBYTEARRAY_H -std::string llToStdString(const QByteArray &bytes); -#endif - -#ifdef QURL_H -std::string llToStdString(const QUrl &url); -#endif - -#endif // LLEMBEDEDDBROWSERWINDOW_H diff --git a/indra/llqtwebkit/llembeddedbrowserwindow_p.h b/indra/llqtwebkit/llembeddedbrowserwindow_p.h deleted file mode 100644 index 27b36d9478..0000000000 --- a/indra/llqtwebkit/llembeddedbrowserwindow_p.h +++ /dev/null @@ -1,251 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LLEMBEDDEDBROWSERWINDOW_P_H -#define LLEMBEDDEDBROWSERWINDOW_P_H - -#include "llwebpage.h" -#include "llwebpageopenshim.h" - -#include -#include -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -// manages the process of storing and emitting events that the consumer -// of the embedding class can observe -template< class T > -class LLEmbeddedBrowserWindowEmitter -{ - public: - LLEmbeddedBrowserWindowEmitter() { }; - ~LLEmbeddedBrowserWindowEmitter() { }; - - typedef typename T::EventType EventType; - typedef std::list< T* > ObserverContainer; - typedef typename ObserverContainer::iterator iterator; - typedef void(T::*observerMethod)(const EventType&); - - /////////////////////////////////////////////////////////////////////////////// - // - bool addObserver(T* observer) - { - if (! observer) - return false; - - if (std::find(observers.begin(), observers.end(), observer) != observers.end()) - return false; - - observers.push_back(observer); - - return true; - } - - /////////////////////////////////////////////////////////////////////////////// - // - bool remObserver(T* observer) - { - if (! observer) - return false; - - observers.remove(observer); - - return true; - } - - /////////////////////////////////////////////////////////////////////////////// - // - void update(observerMethod method, const EventType& msg) - { - typename std::list< T* >::iterator iter = observers.begin(); - - while(iter != observers.end()) - { - ((*iter)->*method)(msg); - ++iter; - } - } - - int getObserverNumber() - { - return observers.size(); - } - - iterator begin() - { - return observers.begin(); - } - - iterator end() - { - return observers.end(); - } - - protected: - ObserverContainer observers; -}; - -#include "llqtwebkit.h" -#include "llembeddedbrowserwindow.h" -#include -#include - -class LLGraphicsScene : public QGraphicsScene -{ - Q_OBJECT - -public: - LLGraphicsScene(); - LLEmbeddedBrowserWindow *window; - - void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) { - QGraphicsScene::mouseMoveEvent(mouseEvent); - mouseEvent->setAccepted(true); - mouseEvent->setButtons(Qt::LeftButton); - } - -private slots: - void repaintRequestedSlot(const QList &); - friend class LLEmbeddedBrowserWindow; -}; - - -class LLWebView : public QGraphicsWebView -{ - Q_OBJECT - -public: - LLWebView(QGraphicsItem *parent = 0); - LLEmbeddedBrowserWindow *window; - - static QUrl guessUrlFromString(const QString &string); - - int width() const { return boundingRect().width(); } - int height() const { return boundingRect().height(); } - -protected: - bool event(QEvent *event); - - Qt::CursorShape currentShape; -}; - -class LLEmbeddedBrowserWindowPrivate -{ - public: - LLEmbeddedBrowserWindowPrivate() - : mParent(0) - , mPage(0) - , mView(0) - , mGraphicsScene(0) - , mGraphicsView(0) - , mInspector(0) - , mCurrentMouseButtonState(Qt::NoButton) - , mPercentComplete(0) - , mShowLoadingOverlay(false) - , mTimeLoadStarted(0) - , mStatusText("") - , mTitle("") - , mCurrentUri("") - , mNoFollowScheme("secondlife") - , mWindowId(-1) - , mEnabled(true) - , mFlipBitmap(false) - , mPageBuffer(NULL) - , mDirty(false) - , mOpeningSelf(false) - { - } - - ~LLEmbeddedBrowserWindowPrivate() - { - while(!mProxyPages.empty()) - { - ProxyList::iterator iter = mProxyPages.begin(); - (*iter)->window = 0; - (*iter)->deleteLater(); - } - - if(mGraphicsScene) - { - mGraphicsScene->window = 0; - } - if(mPage) - { - mPage->window = 0; - } - if(mView) - { - mView->deleteLater(); - } - if(mGraphicsScene) - { - mGraphicsScene->deleteLater(); - } - if(mGraphicsView) - { - mGraphicsView->viewport()->setParent(mGraphicsView); - mGraphicsView->deleteLater(); - } - if(mInspector) - { - mInspector->deleteLater(); - } - } - - typedef LLEmbeddedBrowserWindowEmitter< LLEmbeddedBrowserWindowObserver> Emitter; - Emitter mEventEmitter; - QImage mImage; - LLEmbeddedBrowser *mParent; - LLWebPage *mPage; - typedef std::list ProxyList; - ProxyList mProxyPages; - - LLWebView *mView; - QWebInspector* mInspector; - LLGraphicsScene *mGraphicsScene; - QGraphicsView *mGraphicsView; - Qt::MouseButtons mCurrentMouseButtonState; - - int16_t mPercentComplete; - bool mShowLoadingOverlay; - time_t mTimeLoadStarted; - std::string mStatusText; - std::string mTitle; - std::string mCurrentUri; - QString mNoFollowScheme; - int mWindowId; - bool mEnabled; - bool mFlipBitmap; - unsigned char* mPageBuffer; - QColor backgroundColor; - bool mDirty; - bool mOpeningSelf; -}; - - -#endif - diff --git a/indra/llqtwebkit/lljsobject.cpp b/indra/llqtwebkit/lljsobject.cpp deleted file mode 100644 index f5abfa7023..0000000000 --- a/indra/llqtwebkit/lljsobject.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include -#include "lljsobject.h" - -LLJsObject::LLJsObject( QObject* parent ) : - QObject( parent ) -{ - mEnabled = false; - - mAgentLanguage = QString(); - mAgentMaturity = QString(); - mAgentRegion = QString(); - - mAgentLocation[ "x" ] = 0.0; - mAgentLocation[ "y" ] = 0.0; - mAgentLocation[ "z" ] = 0.0; - - mAgentGlobalLocation[ "x" ] = 0.0; - mAgentGlobalLocation[ "y" ] = 0.0; - mAgentGlobalLocation[ "z" ] = 0.0; -} - -void LLJsObject::setSLObjectEnabled( bool enabled ) -{ - mEnabled = enabled; -} - -bool LLJsObject::getSLObjectEnabled() -{ - return mEnabled; -} - -void LLJsObject::setAgentLanguage( const QString& agent_language ) -{ - if ( mEnabled ) - { - mAgentLanguage = agent_language; - } - else - { - mAgentLanguage = QString(); - } -} - -void LLJsObject::setAgentRegion( const QString& agent_region ) -{ - if ( mEnabled ) - { - mAgentRegion = agent_region; - } - else - { - mAgentRegion = QString(); - } -} - -void LLJsObject::setAgentMaturity( const QString& agent_maturity ) -{ - if ( mEnabled ) - { - mAgentMaturity = agent_maturity; - } - else - { - mAgentMaturity = QString(); - } -} - -void LLJsObject::setAgentLocation( const QVariantMap agent_location ) -{ - if ( mEnabled ) - { - mAgentLocation = agent_location; - } - else - { - mAgentLocation[ "x" ] = 0.0; - mAgentLocation[ "y" ] = 0.0; - mAgentLocation[ "z" ] = 0.0; - } -} - -void LLJsObject::setAgentGlobalLocation( const QVariantMap agent_global_location ) -{ - if ( mEnabled ) - { - mAgentGlobalLocation = agent_global_location; - } - else - { - mAgentGlobalLocation[ "x" ] = 0.0; - mAgentGlobalLocation[ "y" ] = 0.0; - mAgentGlobalLocation[ "z" ] = 0.0; - } -} - -void LLJsObject::setAgentOrientation( const double angle ) -{ - if ( mEnabled ) - { - mAgentOrientation = angle; - } - else - { - mAgentOrientation = 0.0; - } -} - -void LLJsObject::emitLocation() -{ - QVariantMap agent_location; - - agent_location[ "region" ] = mAgentRegion; - agent_location[ "location" ] = mAgentLocation; - agent_location[ "orientation" ] = mAgentOrientation; - agent_location[ "globalLocation" ] = mAgentGlobalLocation; - - emit getLocation( agent_location ); -} - -void LLJsObject::emitMaturity() -{ - emit getMaturity( mAgentMaturity ); -} - -void LLJsObject::emitLanguage() -{ - emit getLanguage( mAgentLanguage ); -} diff --git a/indra/llqtwebkit/lljsobject.h b/indra/llqtwebkit/lljsobject.h deleted file mode 100644 index 806a8a8a1b..0000000000 --- a/indra/llqtwebkit/lljsobject.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LLJSOBJECT_H -#define LLJSOBJECT_H - -#include -#include -#include - -class LLJsObject : - public QObject -{ - Q_OBJECT - - public: - LLJsObject( QObject* parent = 0 ); - - void setSLObjectEnabled( bool enabled ); - bool getSLObjectEnabled(); - - void setAgentLanguage( const QString& agent_language ); - void setAgentRegion( const QString& agent_region ); - void setAgentMaturity( const QString& agent_maturity ); - void setAgentLocation( const QVariantMap agent_location ); - void setAgentGlobalLocation( const QVariantMap agent_global_location ); - void setAgentOrientation( const double angle ); - - void emitLocation(); - void emitMaturity(); - void emitLanguage(); - - signals: - void getLocation( const QVariantMap agent_location ); - void getMaturity( const QString agent_maturity ); - void getLanguage( const QString agent_language ); - - private: - bool mEnabled; - - QString mAgentLanguage; - QString mAgentMaturity; - QString mAgentRegion; - QVariantMap mAgentLocation; - QVariantMap mAgentGlobalLocation; - double mAgentOrientation; -}; - -#endif // LLJSOBJECT_H diff --git a/indra/llqtwebkit/llnetworkaccessmanager.cpp b/indra/llqtwebkit/llnetworkaccessmanager.cpp deleted file mode 100644 index 2a51f13400..0000000000 --- a/indra/llqtwebkit/llnetworkaccessmanager.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include -#include "llnetworkaccessmanager.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "llembeddedbrowserwindow.h" -#include "llembeddedbrowser_p.h" - -#include "ui_passworddialog.h" - - -LLNetworkAccessManager::LLNetworkAccessManager(LLEmbeddedBrowserPrivate* browser,QObject* parent) - : QNetworkAccessManager(parent) - , mBrowser(browser) -{ - connect(this, SIGNAL(finished(QNetworkReply*)), - this, SLOT(finishLoading(QNetworkReply*))); - connect(this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), - this, SLOT(authenticationRequiredSlot(QNetworkReply*, QAuthenticator*))); - connect(this, SIGNAL(sslErrors( QNetworkReply *, const QList &)), - this, SLOT(sslErrorsSlot( QNetworkReply *, const QList & ))); -} - -QNetworkReply *LLNetworkAccessManager::createRequest(Operation op, const QNetworkRequest &request, - QIODevice *outgoingData) -{ - - // Create a local copy of the request we can modify. - QNetworkRequest mutable_request(request); - - // Set an Accept-Language header in the request, based on what the host has set through setHostLanguage. - mutable_request.setRawHeader(QByteArray("Accept-Language"), QByteArray(mBrowser->mHostLanguage.c_str())); - - // this is undefine'd in 4.7.1 and leads to caching issues - setting it here explicitly - mutable_request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork); - - if(op == GetOperation) - { - // GET requests should not have a Content-Type header, but it seems somebody somewhere is adding one. - // This removes it. - mutable_request.setRawHeader("Content-Type", QByteArray()); - } - -// qDebug() << "headers for request:" << mutable_request.rawHeaderList(); - - // and pass this through to the parent implementation - return QNetworkAccessManager::createRequest(op, mutable_request, outgoingData); -} - -void LLNetworkAccessManager::sslErrorsSlot(QNetworkReply* reply, const QList& errors) -{ - // Enabling this can help diagnose certificate verification issues. - const bool ssl_debugging_on = false; - - // flag that indicates if the error that brought us here is one we care about or not - bool valid_ssl_error = false; - - foreach( const QSslError &error, errors ) - { - if ( ssl_debugging_on ) - { - qDebug() << "SSL error details are (" << (int)(error.error()) << ") - " << error.error(); - } - - // SSL "error" codes we don't care about - if we get one of these, we want to continue - if ( error.error() != QSslError::NoError - // many more in src/network/ssl/qsslerror.h - ) - { - if ( ssl_debugging_on ) - { - qDebug() << "Found valid SSL error - will not ignore"; - } - - valid_ssl_error = true; - } - else - { - if ( ssl_debugging_on ) - { - qDebug() << "Found invalid SSL error - will ignore and continue"; - } - } - } - - if ( ssl_debugging_on ) - { - qDebug() << "LLNetworkAccessManager" << __FUNCTION__ << "errors: " << errors - << ", peer certificate chain: "; - - QSslCertificate cert; - foreach(cert, reply->sslConfiguration().peerCertificateChain()) - { - qDebug() << " cert: " << cert - << ", issuer = " << cert.issuerInfo(QSslCertificate::CommonName) - << ", subject = " << cert.subjectInfo(QSslCertificate::CommonName); - } - } - - if ( valid_ssl_error ) - { - std::string url = llToStdString(reply->url()); - QString err_msg=""; - foreach( const QSslError &error, errors ) - { - err_msg+=error.errorString(); - err_msg+="\n"; - - QSslCertificate cert = error.certificate(); - - QString issuer_info=""; - issuer_info+="C="; - issuer_info+=cert.issuerInfo(QSslCertificate::CountryName); - issuer_info+=", ST="; - issuer_info+=cert.issuerInfo(QSslCertificate::StateOrProvinceName); - issuer_info+=", L="; - issuer_info+=cert.issuerInfo(QSslCertificate::LocalityName); - issuer_info+=", O="; - issuer_info+=cert.issuerInfo(QSslCertificate::Organization); - issuer_info+=", OU="; - issuer_info+=cert.issuerInfo(QSslCertificate::OrganizationalUnitName); - issuer_info+=", CN="; - issuer_info+=cert.issuerInfo(QSslCertificate::CommonName); - err_msg+=issuer_info; - err_msg+="\n"; - - QString subject_info=""; - subject_info+="C="; - subject_info+=cert.subjectInfo(QSslCertificate::CountryName); - subject_info+=", ST="; - subject_info+=cert.subjectInfo(QSslCertificate::StateOrProvinceName); - subject_info+=", L="; - subject_info+=cert.subjectInfo(QSslCertificate::LocalityName); - subject_info+=", O="; - subject_info+=cert.subjectInfo(QSslCertificate::Organization); - subject_info+=", OU="; - subject_info+=cert.subjectInfo(QSslCertificate::OrganizationalUnitName); - subject_info+=", CN="; - subject_info+=cert.subjectInfo(QSslCertificate::CommonName); - err_msg+=subject_info; - err_msg+="\n"; - - err_msg+="Not valid before: "; - err_msg+=cert.effectiveDate().toString(); - err_msg+="\n"; - err_msg+="Not valid after: "; - err_msg+=cert.expiryDate().toString(); - err_msg+="\n"; - err_msg+="----------\n"; - } - - if(mBrowser->certError(url, llToStdString(err_msg))) - { - // signal we should ignore and continue processing - reply->ignoreSslErrors(); - } - else - { - // The user canceled, don't return yet so we can test ignore variable - } - } - - // we the SSL error is invalid (in our opinion) or we explicitly ignore all SSL errors - if ( valid_ssl_error == false || ( mBrowser && mBrowser->mIgnoreSSLCertErrors ) ) - { - // signal we should ignore and continue processing - reply->ignoreSslErrors(); - }; -} - -void LLNetworkAccessManager::finishLoading(QNetworkReply* reply) -{ - QVariant val = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ); - int http_status_code = val.toInt(); - if ( http_status_code >=400 && http_status_code <=499 ) - { - if (mBrowser) - { - std::string current_url = llToStdString(reply->url()); - foreach (LLEmbeddedBrowserWindow *window, mBrowser->windows) - { - if (window->getCurrentUri() == current_url) - { - window->navigateErrorPage( http_status_code ); - } - } - } - } - - // tests if navigation request resulted in a cache hit - useful for testing so leaving here for the moment. - //QVariant from_cache = reply->attribute( QNetworkRequest::SourceIsFromCacheAttribute ); - //QString url = QString(reply->url().toEncoded()); - //qDebug() << url << " --- from cache?" << fromCache.toBool() << "\n"; -} - -void LLNetworkAccessManager:: authenticationRequiredSlot(QNetworkReply *reply, QAuthenticator *authenticator) -{ - std::string username; - std::string password; - std::string url = llToStdString(reply->url()); - std::string realm = llToStdString(authenticator->realm()); - - if(mBrowser->authRequest(url, realm, username, password)) - { - // Got credentials to try, attempt auth with them. - authenticator->setUser(QString::fromStdString(username)); - authenticator->setPassword(QString::fromStdString(password)); - } - else - { - // The user cancelled, don't attempt auth. - } -} - diff --git a/indra/llqtwebkit/llnetworkaccessmanager.h b/indra/llqtwebkit/llnetworkaccessmanager.h deleted file mode 100644 index 478b679aa2..0000000000 --- a/indra/llqtwebkit/llnetworkaccessmanager.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LLNETWORKACCESSMANAGER_H -#define LLNETWORKACCESSMANAGER_H - -#include -#include - -#include "ui_passworddialog.h" - -class QGraphicsProxyWidget; - -class LLEmbeddedBrowserPrivate; -class LLNetworkAccessManager: public QNetworkAccessManager -{ - Q_OBJECT -public: - LLNetworkAccessManager(LLEmbeddedBrowserPrivate* browser, QObject* parent = 0); - -protected: - virtual QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, - QIODevice *outgoingData = 0); -private slots: - void finishLoading(QNetworkReply* reply); - void authenticationRequiredSlot(QNetworkReply *reply, QAuthenticator *authenticator); - void sslErrorsSlot(QNetworkReply* reply, const QList& errors); - -private: - LLEmbeddedBrowserPrivate* mBrowser; - -}; - -#endif // LLNETWORKACCESSMANAGER_H - diff --git a/indra/llqtwebkit/llqtwebkit.cpp b/indra/llqtwebkit/llqtwebkit.cpp deleted file mode 100644 index 2be066d11a..0000000000 --- a/indra/llqtwebkit/llqtwebkit.cpp +++ /dev/null @@ -1,820 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include -#include -#include -#include - -#include "llqtwebkit.h" - -#include "llembeddedbrowser.h" -#include "llembeddedbrowserwindow.h" - -LLQtWebKit* LLQtWebKit::sInstance = 0; - -//////////////////////////////////////////////////////////////////////////////// -// -LLQtWebKit::LLQtWebKit() : - mMaxBrowserWindows(16) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// -LLQtWebKit* LLQtWebKit::getInstance() -{ - if (! sInstance) - { - sInstance = new LLQtWebKit; - } - - return sInstance; -} - -//////////////////////////////////////////////////////////////////////////////// -// -LLQtWebKit::~LLQtWebKit() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::init(std::string application_directory, - std::string component_directory, - std::string profile_directory, - void* native_window_handle) -{ - return LLEmbeddedBrowser::getInstance()->init(application_directory, - component_directory, - profile_directory, - native_window_handle); -} - -//////////////////////////////////////////////////////////////////////////////// -// -int LLQtWebKit::getLastError() -{ - return LLEmbeddedBrowser::getInstance()->getLastError(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::reset() -{ - mBrowserWindowMap.clear(); - return LLEmbeddedBrowser::getInstance()->reset(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::clearCache() -{ - return LLEmbeddedBrowser::getInstance()->clearCache(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -std::string LLQtWebKit::getVersion() -{ - const int majorVersion = 2; - const int minorVersion = 2; - - // number of hours since "time began" for this library - used to identify builds of same version - const int magicNumber = static_cast< int >((time(NULL) / 3600L) - (321190L)); - - // return as a string for now - don't think we need to expose actual version numbers - std::ostringstream codec; - codec << std::setw(1) << std::setfill('0'); - codec << majorVersion << "."; - codec << std::setw(2) << std::setfill('0'); - codec << minorVersion << "."; - codec << std::setw(5) << std::setfill('0'); - codec << magicNumber; - codec << " (QtWebKit version "; - codec << LLEmbeddedBrowser::getInstance()->getGREVersion(); - codec << ")"; - - return codec.str(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::setBrowserAgentId(std::string id) -{ - LLEmbeddedBrowser::getInstance()->setBrowserAgentId(id); -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::enableProxy(bool enabled, std::string host_name, int port) -{ - return LLEmbeddedBrowser::getInstance()->enableProxy(enabled, host_name, port); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::setHostLanguage(const std::string& host_language ) -{ - LLEmbeddedBrowser::getInstance()->setHostLanguage(host_language); -} - -//////////////////////////////////////////////////////////////////////////////// -// -int LLQtWebKit::createBrowserWindow(int width, int height, const std::string target) -{ - LLEmbeddedBrowserWindow* browser_window = LLEmbeddedBrowser::getInstance()->createBrowserWindow(width, height, target); - - if (browser_window) - { - // arbitrary limit so we don't exhaust system resources - int id(0); - while (++id < mMaxBrowserWindows) - { - std::pair< BrowserWindowMapIter, bool > result = mBrowserWindowMap.insert(std::make_pair(id, browser_window)); - - // find first place the insert succeeds and use that index as the id - if (result.second) - { - browser_window->setWindowId(id); - return id; - } - } - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::proxyWindowOpened(int browser_window_id, const std::string target, const std::string uuid) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->proxyWindowOpened(target, uuid); - } -} -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::proxyWindowClosed(int browser_window_id, const std::string uuid) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->proxyWindowClosed(uuid); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::destroyBrowserWindow(int browser_window_id) -{ - // don't use the utility method here since we need the iteratorator to remove the entry from the map - BrowserWindowMapIter iterator = mBrowserWindowMap.find(browser_window_id); - LLEmbeddedBrowserWindow* browser_window = (*iterator).second; - - if (browser_window) - { - LLEmbeddedBrowser::getInstance()->destroyBrowserWindow(browser_window); - } - - mBrowserWindowMap.erase(iterator); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::setBackgroundColor(int browser_window_id, const int red, const int green, const int blue) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->setBackgroundColor(red, green, blue); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::setEnabled(int browser_window_id, bool enabled) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->setEnabled(enabled); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::setSize(int browser_window_id, int width, int height) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->setSize(width, height); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::scrollByLines(int browser_window_id, int lines) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->scrollByLines(lines); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::addObserver(int browser_window_id, LLEmbeddedBrowserWindowObserver* subject) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->addObserver(subject); - } - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::remObserver(int browser_window_id, LLEmbeddedBrowserWindowObserver* subject) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->remObserver(subject); - } - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::navigateTo(int browser_window_id, const std::string uri) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->navigateTo(uri) ? true : false; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::userAction(int browser_window_id, EUserAction action) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->userAction(action); - } - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::userActionIsEnabled(int browser_window_id, EUserAction action) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->userActionIsEnabled(action); - } - return false; -} - -/////////////////////////////////////////////////////////////////////////////// -// -const unsigned char* LLQtWebKit::grabBrowserWindow(int browser_window_id) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->grabWindow(0, 0, browser_window->getBrowserWidth(), browser_window->getBrowserHeight()); - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// -const unsigned char* LLQtWebKit::getBrowserWindowPixels(int browser_window_id) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->getPageBuffer(); - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::flipWindow(int browser_window_id, bool flip) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->flipWindow(flip); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -int LLQtWebKit::getBrowserWidth(int browser_window_id) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->getBrowserWidth(); - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// -int LLQtWebKit::getBrowserHeight(int browser_window_id) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->getBrowserHeight(); - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// -int LLQtWebKit::getBrowserDepth(int browser_window_id) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->getBrowserDepth(); - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// -int LLQtWebKit::getBrowserRowSpan(int browser_window_id) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->getBrowserRowSpan(); - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::mouseEvent(int browser_window_id, EMouseEvent mouse_event, int button, int x, int y, EKeyboardModifier modifiers) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->mouseEvent(mouse_event, button, x, y, modifiers); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::scrollWheelEvent(int browser_window_id, int x, int y, int scroll_x, int scroll_y, EKeyboardModifier modifiers) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->scrollWheelEvent(x, y, scroll_x, scroll_y, modifiers); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::keyboardEvent( - int browser_window_id, - EKeyEvent key_event, - uint32_t key_code, - const char *utf8_text, - EKeyboardModifier modifiers, - uint32_t native_scan_code, - uint32_t native_virtual_key, - uint32_t native_modifiers) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->keyboardEvent(key_event, key_code, utf8_text, modifiers, native_scan_code, native_virtual_key, native_modifiers); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::focusBrowser(int browser_window_id, bool focus_browser) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->focusBrowser(focus_browser); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::setNoFollowScheme(int browser_window_id, std::string scheme) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->setNoFollowScheme(scheme); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -std::string LLQtWebKit::getNoFollowScheme(int browser_window_id) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->getNoFollowScheme(); - } - - return (""); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::pump(int max_milliseconds) -{ - LLEmbeddedBrowser::getInstance()->pump(max_milliseconds); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::enableCookies(bool enabled) -{ - LLEmbeddedBrowser::getInstance()->enableCookies( enabled ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::clearAllCookies() -{ - return LLEmbeddedBrowser::getInstance()->clearAllCookies(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::setCookies(const std::string &cookies) -{ - return LLEmbeddedBrowser::getInstance()->setCookies(cookies); -} - -//////////////////////////////////////////////////////////////////////////////// -// -std::string LLQtWebKit::getAllCookies() -{ - return LLEmbeddedBrowser::getInstance()->getAllCookies(); -} - - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::enablePlugins(bool enabled) -{ - LLEmbeddedBrowser::getInstance()->enablePlugins(enabled); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::enableJavaScript(bool enabled) -{ - LLEmbeddedBrowser::getInstance()->enableJavaScript(enabled); -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::showWebInspector(bool show) -{ - return LLEmbeddedBrowser::getInstance()->showWebInspector(show); -} - -//////////////////////////////////////////////////////////////////////////////// -// -std::string LLQtWebKit::evaluateJavaScript(int browser_window_id, const std::string script) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->evaluateJavaScript(script); - } - - return ""; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::prependHistoryUrl(int browser_window_id, std::string url) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->prependHistoryUrl(url); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::clearHistory(int browser_window_id) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->clearHistory(); - } -} - -std::string LLQtWebKit::dumpHistory(int browser_window_id) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - return browser_window->dumpHistory(); - } - - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::setCAFile(const std::string &ca_file) -{ - return LLEmbeddedBrowser::getInstance()->setCAFile(ca_file); -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::addCAFile(const std::string &ca_file) -{ - return LLEmbeddedBrowser::getInstance()->addCAFile(ca_file); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLQtWebKit::setIgnoreSSLCertErrors(bool ignore) -{ - LLEmbeddedBrowser::getInstance()->setIgnoreSSLCertErrors(ignore); -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLQtWebKit::getIgnoreSSLCertErrors() -{ - return LLEmbeddedBrowser::getInstance()-> getIgnoreSSLCertErrors(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -const std::vector< std::string > LLQtWebKit::getInstalledCertsList() -{ - return LLEmbeddedBrowser::getInstance()->getInstalledCertsList(); -} - -//////////////////////////////////////////////////////////////////////////////// -// utility method to get an LLEmbeddedBrowserWindow* from a window id (int) -LLEmbeddedBrowserWindow* LLQtWebKit::getBrowserWindowFromWindowId(int browser_window_id) -{ - BrowserWindowMapIter iterator = mBrowserWindowMap.find(browser_window_id); - - if (iterator != mBrowserWindowMap.end()) - return (*iterator).second; - else - return 0; -} - -LLEmbeddedBrowserWindowObserver::~LLEmbeddedBrowserWindowObserver() -{ -} - -void LLEmbeddedBrowserWindowObserver::onCursorChanged(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onPageChanged(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onNavigateBegin(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onNavigateComplete(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onUpdateProgress(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onStatusTextChange(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onTitleChange(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onLocationChange(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onNavigateErrorPage(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onClickLinkHref(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onClickLinkNoFollow(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onCookieChanged(const EventType&) -{ -} - -std::string LLEmbeddedBrowserWindowObserver::onRequestFilePicker(const EventType&) -{ - return std::string(); -} - -void LLEmbeddedBrowserWindowObserver::onWindowCloseRequested(const EventType&) -{ -} - -void LLEmbeddedBrowserWindowObserver::onWindowGeometryChangeRequested(const EventType&) -{ -} - -bool LLEmbeddedBrowserWindowObserver::onAuthRequest(const std::string &, const std::string &, std::string &, std::string &) -{ - return false; -} - -bool LLEmbeddedBrowserWindowObserver::onCertError(const std::string &, const std::string &) -{ - return false; // cancel and abort after cert error -} - -void LLEmbeddedBrowserWindowObserver::onQtDebugMessage( const std::string &, const std::string &) -{ -} - -void LLEmbeddedBrowserWindowObserver::onLinkHovered(const EventType&) -{ -} - -// set the regex used to determine if a page is trusted or not -void LLQtWebKit::setWhiteListRegex( int browser_window_id, const std::string& regex ) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->setWhiteListRegex(regex); - } -} - -// Second Life viewer specific functions -void LLQtWebKit::setSLObjectEnabled( bool enabled ) -{ - LLEmbeddedBrowser::getInstance()->setSLObjectEnabled( enabled ); -} - -void LLQtWebKit::setAgentLanguage( const std::string& agent_language ) -{ - LLEmbeddedBrowser::getInstance()->setAgentLanguage( agent_language ); -} - -void LLQtWebKit::setAgentRegion( const std::string& agent_region ) -{ - LLEmbeddedBrowser::getInstance()->setAgentRegion( agent_region ); -} - -void LLQtWebKit::setAgentLocation( double x, double y, double z ) -{ - LLEmbeddedBrowser::getInstance()->setAgentLocation( x, y, z ); -} - -void LLQtWebKit::setAgentGlobalLocation( double x, double y, double z ) -{ - LLEmbeddedBrowser::getInstance()->setAgentGlobalLocation( x, y, z ); -} - -void LLQtWebKit::setAgentOrientation( double angle ) -{ - LLEmbeddedBrowser::getInstance()->setAgentOrientation( angle ); -} - - -void LLQtWebKit::setAgentMaturity( const std::string& agent_maturity ) -{ - LLEmbeddedBrowser::getInstance()->setAgentMaturity( agent_maturity ); -} - -void LLQtWebKit::emitLocation() -{ - LLEmbeddedBrowser::getInstance()->emitLocation(); -} - -void LLQtWebKit::emitMaturity() -{ - LLEmbeddedBrowser::getInstance()->emitMaturity(); -} - -void LLQtWebKit::emitLanguage() -{ - LLEmbeddedBrowser::getInstance()->emitLanguage(); -} - -void LLQtWebKit::enableQtMessageHandler( bool enable ) -{ - LLEmbeddedBrowser::getInstance()->enableQtMessageHandler( enable ); -} - -void LLQtWebKit::enableLoadingOverlay( int browser_window_id, bool enable) -{ - LLEmbeddedBrowserWindow* browser_window = getBrowserWindowFromWindowId(browser_window_id); - if (browser_window) - { - browser_window->enableLoadingOverlay( enable ); - } -} - -void LLQtWebKit::setPageZoomFactor( double factor ) -{ - LLEmbeddedBrowser::getInstance()->setPageZoomFactor( factor ); -} diff --git a/indra/llqtwebkit/llqtwebkit.h b/indra/llqtwebkit/llqtwebkit.h deleted file mode 100644 index 8e7ebd3906..0000000000 --- a/indra/llqtwebkit/llqtwebkit.h +++ /dev/null @@ -1,470 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LLQTWEBKIT_H -#define LLQTWEBKIT_H - -#if defined _MSC_VER && _MSC_VER < 1600 -// no pstdint.h in the client where this header is used -typedef unsigned long uint32_t; -#else -#include // Use the C99 official header -#endif - -#include -#include -#include - -class LLEmbeddedBrowser; -class LLEmbeddedBrowserWindow; - -// Use this to conditionalize code that depends on particular changes to the llqtwebkit API. -// This can be useful for times when we're waiting for a rebuild on one platform or another. -// When you bump this number, please note what the changes were in a comment below the #define, -// and keep the existing comments as history. -#define LLQTWEBKIT_API_VERSION 16 -// version 16: - // Added LLQtWebKit::enableLoadingOverlay() -// version 15: - // Added LLQtWebKit::setPageZoomFactor() -// version 14: - // Added LLEmbeddedBrowserWindowObserver::onQtDebugMessage -// version 13: - // Added LLEmbeddedBrowserWindowObserver::onCertError -// version 12: - // Pass over value to indicate if host for current URL is trusted as per whitelist regex or not -// version 11: - // Added initial support for url/host whitelist via a regex -// version 10: - // Added initial support for creating and displaying the Qt Web Inspector -// version 9: - // Added initial support for exposing certain Second Life viewer/agent variables to JavaScript -// version 8: - // Removed calls to set/clear 404 redirects and made the API now emit an event that the - // consumer can catch and decide what to do when an HTTP status code after navigate is 400-499 -// version 7: - // Added LLEmbeddedBrowserWindowEvent::setNavigationType() && LLEmbeddedBrowserWindowEvent::getNavigationType() - // Used to pass (and retrieve) the type of navigation event that caused a link to be activated. -// version 6: - // Added LLQtWebKit::addCAFile() -// version 5: - // Added LLEmbeddedBrowserWindowObserver::onLinkHovered -// version 4: - // Added LLEmbeddedBrowserWindowObserver::onAuthRequest -// version 3: - // Added setIgnoreSSLCertErrors and getIgnoreSSLCertErrors -// version 2: - // Changed the usage of the event parameters in onClickLinkHref and onClickLinkNoFollow events slightly. - // The clicked URI for both should now be retrieved with getEventUri() instead of getStringValue(). - // The "target" string in onClickLinkHref is now retrieved with getStringValue() instead of getStringValue2(). - // The contents of getStringValue2() in the onClickLinkHref event is now a unique ID for the window proxy the click targets. - // Removed the "link target type" concept, since it doesn't really belong here. - // Removed most of the construtor variants in LLEmbeddedBrowserWindowEvent and added setters in their place. - // Removed setCaretColor, since it's done nothing for some time now. - // Added LLEmbeddedBrowserWindowObserver::onWindowGeometryChangeRequested - // Added -// version 1: - // Added the LLQTWEBKIT_API_VERSION define. - // Added LLEmbeddedBrowserWindowObserver::onWindowCloseRequested - -//////////////////////////////////////////////////////////////////////////////// -// data class that is passed with an event -class LLEmbeddedBrowserWindowEvent -{ - public: - LLEmbeddedBrowserWindowEvent(int window_id) : - mEventWindowId(window_id) - { - }; - - virtual ~LLEmbeddedBrowserWindowEvent() {} - - void setEventUri(const std::string &uri) { mEventUri = uri; } - void setNavigationType(const std::string &type) { mNavigationType = type; } - void setTrustedHost(const bool trusted) { mTrustedHost = trusted; } - void setIntValue(int val) { mIntVal = val; } - void setStringValue(const std::string &val) { mStringVal = val; } - void setStringValue2(const std::string &val) { mStringVal2 = val; } - void setRectValue(int x, int y, int width, int height) - { - mXVal = x; - mYVal = y; - mWidthVal = width; - mHeightVal = height; - } - - int getEventWindowId() const { return mEventWindowId; } - std::string getEventUri() const { return mEventUri; } - std::string getNavigationType() const { return mNavigationType; } - bool getTrustedHost() const { return mTrustedHost; } - int getIntValue() const { return mIntVal; }; - std::string getStringValue() const { return mStringVal; } - std::string getStringValue2() const { return mStringVal2; } - void getRectValue(int& x, int& y, int& width, int& height) const - { - x = mXVal; - y = mYVal; - width = mWidthVal; - height = mHeightVal; - }; - - private: - int mEventWindowId; - std::string mEventUri; - std::string mNavigationType; - bool mTrustedHost; - int mIntVal; - std::string mStringVal; - std::string mStringVal2; - int mXVal; - int mYVal; - int mWidthVal; - int mHeightVal; -}; - -//////////////////////////////////////////////////////////////////////////////// -// derrive from this class and override these methods to observe these events -#ifdef __GNUC__ -#pragma GCC visibility push(default) -#endif -class LLEmbeddedBrowserWindowObserver -{ - public: - virtual ~LLEmbeddedBrowserWindowObserver(); - typedef LLEmbeddedBrowserWindowEvent EventType; - - virtual void onCursorChanged(const EventType& event); - virtual void onPageChanged(const EventType& event); - virtual void onNavigateBegin(const EventType& event); - virtual void onNavigateComplete(const EventType& event); - virtual void onNavigateErrorPage(const EventType& event); - virtual void onUpdateProgress(const EventType& event); - virtual void onStatusTextChange(const EventType& event); - virtual void onTitleChange(const EventType& event); - virtual void onLocationChange(const EventType& event); - virtual void onClickLinkHref(const EventType& event); - virtual void onClickLinkNoFollow(const EventType& event); - virtual void onCookieChanged(const EventType& event); - // mStringVal will be the cookie in RFC 2109 string format - // mEventUri will be the url that caused the cookie change - // mIntVal will be true if the cookie is dead (i.e. being deleted), false otherwise - virtual std::string onRequestFilePicker(const EventType& event); - virtual void onWindowCloseRequested(const EventType& event); - virtual void onWindowGeometryChangeRequested(const EventType& event); - - // This should return true to attempt auth, or false to cancel. - virtual bool onAuthRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password); - - // This should return true to continue after cert error, or false to cancel and abort. - virtual bool onCertError(const std::string &in_url, const std::string &in_msg); - - virtual void onLinkHovered(const EventType& event); - // mEventURI will be the link - // mStringVal will be the title - // mStringVal2 will be the text - - // catch qDebug() messages from Qt and pipe them back to host application - virtual void onQtDebugMessage( const std::string& msg, const std::string& msg_type); -}; -#ifdef __GNUC__ -#pragma GCC visibility pop -#endif - -//////////////////////////////////////////////////////////////////////////////// -// main library class - -#ifdef __GNUC__ -#pragma GCC visibility push(default) -#endif -class LLQtWebKit -{ - public: - typedef enum e_cursor - { - C_ARROW, - C_IBEAM, - C_SPLITV, - C_SPLITH, - C_POINTINGHAND - } ECursor; - - typedef enum e_user_action - { - UA_EDIT_CUT, - UA_EDIT_COPY, - UA_EDIT_PASTE, - UA_NAVIGATE_STOP, - UA_NAVIGATE_BACK, - UA_NAVIGATE_FORWARD, - UA_NAVIGATE_RELOAD - } EUserAction; - - typedef enum e_key_event - { - KE_KEY_DOWN, - KE_KEY_REPEAT, - KE_KEY_UP - }EKeyEvent; - - typedef enum e_mouse_event - { - ME_MOUSE_MOVE, - ME_MOUSE_DOWN, - ME_MOUSE_UP, - ME_MOUSE_DOUBLE_CLICK - }EMouseEvent; - - typedef enum e_mouse_button - { - MB_MOUSE_BUTTON_LEFT, - MB_MOUSE_BUTTON_RIGHT, - MB_MOUSE_BUTTON_MIDDLE, - MB_MOUSE_BUTTON_EXTRA_1, - MB_MOUSE_BUTTON_EXTRA_2, - }EMouseButton; - - typedef enum e_keyboard_modifier - { - KM_MODIFIER_NONE = 0x00, - KM_MODIFIER_SHIFT = 0x01, - KM_MODIFIER_CONTROL = 0x02, - KM_MODIFIER_ALT = 0x04, - KM_MODIFIER_META = 0x08 - }EKeyboardModifier; - - virtual ~LLQtWebKit(); - - // singleton access - static LLQtWebKit* getInstance(); - - // housekeeping - bool init(std::string application_directory, - std::string component_directory, - std::string profile_directory, - void* native_window_handle); - bool reset(); - bool clearCache(); - int getLastError(); - std::string getVersion(); - void setBrowserAgentId(std::string id); - bool enableProxy(bool enabled, std::string host_name, int port); - - void enableCookies(bool enabled); - bool clearAllCookies(); - - // The following two functions accept and return cookies in the same format that's used for the Set-Cookie: HTTP header - // as defined in RFC 2109 ( http://www.ietf.org/rfc/rfc2109.txt ). The string should not contain the literal "Set-Cookie:", - // just the cookie itself. - // Multiple cookies within the string are separated by a newline character ('\n') - void setCookies(const std::string &cookies); - std::string getAllCookies(); - - void enablePlugins(bool enabled); - void enableJavaScript(bool enabled); - - // Web inspector - Firebug-esque debugger - bool showWebInspector(bool show); - - // updates value of 'hostLanguage' in JavaScript 'Navigator' obect that - // embedded pages can query to see what language the host app is set to - void setHostLanguage(const std::string& host_language); - - // browser window - creation/deletion, mutation etc. - int createBrowserWindow(int width, int height, const std::string target = std::string("")); - void proxyWindowOpened(int browser_window_id, const std::string target, const std::string uuid); - void proxyWindowClosed(int browser_window_id, const std::string uuid); - bool destroyBrowserWindow(int browser_window_id); - bool setSize(int browser_window_id, int width, int height); - bool scrollByLines(int browser_window_id, int lines); - bool setBackgroundColor(int browser_window_id, const int red, const int green, const int blue); - bool setEnabled(int browser_window_id, bool enabled); - - // add/remove yourself as an observer on browser events - see LLEmbeddedBrowserWindowObserver declaration - bool addObserver(int browser_window_id, LLEmbeddedBrowserWindowObserver* subject); - bool remObserver(int browser_window_id, LLEmbeddedBrowserWindowObserver* subject); - - // navigation - self explanatory - bool navigateTo(int browser_window_id, const std::string uri); - bool userAction(int browser_window_id, EUserAction action); - bool userActionIsEnabled(int browser_window_id, EUserAction action); - - // javascript access/control - std::string evaluateJavaScript(int browser_window_id, const std::string script); - - // set/clear URL to redirect to when a 404 page is reached - bool set404RedirectUrl(int browser_window_in, std::string redirect_url); - bool clr404RedirectUrl(int browser_window_in); - - // access to rendered bitmap data - const unsigned char* grabBrowserWindow(int browser_window_id); // renders page to memory and returns pixels - const unsigned char* getBrowserWindowPixels(int browser_window_id); // just returns pixels - no render - bool flipWindow(int browser_window_id, bool flip); // optionally flip window (pixels) you get back - int getBrowserWidth(int browser_window_id); // current browser width (can vary slightly after page is rendered) - int getBrowserHeight(int browser_window_id); // current height - int getBrowserDepth(int browser_window_id); // depth in bytes - int getBrowserRowSpan(int browser_window_id); // width in pixels * depth in bytes - - // mouse/keyboard interaction - bool mouseEvent(int browser_window_id, EMouseEvent mouse_event, int button, int x, int y, EKeyboardModifier modifiers); // send a mouse event to a browser window at given XY in browser space - bool scrollWheelEvent(int browser_window_id, int x, int y, int scroll_x, int scroll_y, EKeyboardModifier modifiers); - bool keyboardEvent( - int browser_window_id, - EKeyEvent key_event, - uint32_t key_code, - const char *utf8_text, - EKeyboardModifier modifiers, - uint32_t native_scan_code = 0, - uint32_t native_virtual_key = 0, - uint32_t native_modifiers = 0); - - bool focusBrowser(int browser_window_id, bool focus_browser); // set/remove focus to given browser window - - // accessor/mutator for scheme that browser doesn't follow - e.g. secondlife.com:// - void setNoFollowScheme(int browser_window_id, std::string scheme); - std::string getNoFollowScheme(int browser_window_id); - - void pump(int max_milliseconds); - - void prependHistoryUrl(int browser_window_id, std::string url); - void clearHistory(int browser_window_id); - std::string dumpHistory(int browser_window_id); - - // Specify a path to a .pem file containing a list of CA certificates the browser should trust. - // NOTE that this will replace the default list of root certs (not add to it). - // If the file isn't found or doesn't contain any certs in the correct format, this call will have no effect and will return false. - // NOTE: Using this function causes strange cert verification issues on the Mac. - // Using addCAFile() instead seems to work better. - bool setCAFile(const std::string &ca_file); - - // This behaves similarly, but instead of replacing the entire list it appends additional trusted root certs to the current list. - bool addCAFile(const std::string &ca_file); - - // Set a flag causing all SSL cert errors to be ignored. - // NOTE: this should only be used for testing, as it negates the security model of https. - void setIgnoreSSLCertErrors(bool ignore); - bool getIgnoreSSLCertErrors(); - - const std::vector< std::string > getInstalledCertsList(); - - void enableQtMessageHandler( bool enable ); - - void enableLoadingOverlay( int browser_window_id, bool enable); - - // Copied from indra_constants.h. - // The key_code argument to keyboardEvent should either be one of these or a 7-bit ascii character. - enum keyCodes - { - // Leading zeroes ensure that these won't sign-extend when assigned to a larger type. - KEY_RETURN = 0x0081, - KEY_LEFT = 0x0082, - KEY_RIGHT = 0x0083, - KEY_UP = 0x0084, - KEY_DOWN = 0x0085, - KEY_ESCAPE = 0x0086, - KEY_BACKSPACE = 0x0087, - KEY_DELETE = 0x0088, - KEY_SHIFT = 0x0089, - KEY_CONTROL = 0x008A, - KEY_ALT = 0x008B, - KEY_HOME = 0x008C, - KEY_END = 0x008D, - KEY_PAGE_UP = 0x008E, - KEY_PAGE_DOWN = 0x008F, - KEY_HYPHEN = 0x0090, - KEY_EQUALS = 0x0091, - KEY_INSERT = 0x0092, - KEY_CAPSLOCK = 0x0093, - KEY_TAB = 0x0094, - KEY_ADD = 0x0095, - KEY_SUBTRACT = 0x0096, - KEY_MULTIPLY = 0x0097, - KEY_DIVIDE = 0x0098, - KEY_F1 = 0x00A1, - KEY_F2 = 0x00A2, - KEY_F3 = 0x00A3, - KEY_F4 = 0x00A4, - KEY_F5 = 0x00A5, - KEY_F6 = 0x00A6, - KEY_F7 = 0x00A7, - KEY_F8 = 0x00A8, - KEY_F9 = 0x00A9, - KEY_F10 = 0x00AA, - KEY_F11 = 0x00AB, - KEY_F12 = 0x00AC, - - KEY_PAD_UP = 0x00C0, - KEY_PAD_DOWN = 0x00C1, - KEY_PAD_LEFT = 0x00C2, - KEY_PAD_RIGHT = 0x00C3, - KEY_PAD_HOME = 0x00C4, - KEY_PAD_END = 0x00C5, - KEY_PAD_PGUP = 0x00C6, - KEY_PAD_PGDN = 0x00C7, - KEY_PAD_CENTER = 0x00C8, // the 5 in the middle - KEY_PAD_INS = 0x00C9, - KEY_PAD_DEL = 0x00CA, - KEY_PAD_RETURN = 0x00CB, - KEY_PAD_ADD = 0x00CC, - KEY_PAD_SUBTRACT = 0x00CD, - KEY_PAD_MULTIPLY = 0x00CE, - KEY_PAD_DIVIDE = 0x00CF, - - KEY_NONE = 0x00FF // not sent from keyboard. For internal use only. - }; - - // set the regex used to determine if a page is trusted or not - void setWhiteListRegex( int browser_window_id, const std::string& regex ); - - // Second Life specific functions - // (Note, this is a departure from the generic nature of this library) - void setSLObjectEnabled( bool enabled ); // enable or disaable feature - void setAgentLanguage( const std::string& agent_language ); // viewer language selected by agent - void setAgentRegion( const std::string& agent_region ); // name of region where agent is located - void setAgentLocation( double x, double y, double z ); // agent's x,y,z location within a region - void setAgentGlobalLocation( double x, double y, double z ); // agent's x,y,z location within the current grid - void setAgentOrientation( double angle ); // direction (0..359) agent is facing - void setAgentMaturity( const std::string& agent_maturity ); // selected maturity level of agent - void emitLocation(); - void emitMaturity(); - void emitLanguage(); - - // set the zoom factor for web pages ( can be less than 0.0) - void setPageZoomFactor( double factor ); - - private: - LLQtWebKit(); - LLEmbeddedBrowserWindow* getBrowserWindowFromWindowId(int browser_window_id); - static LLQtWebKit* sInstance; - const int mMaxBrowserWindows; - typedef std::map< int, LLEmbeddedBrowserWindow* > BrowserWindowMap; - typedef std::map< int, LLEmbeddedBrowserWindow* >::iterator BrowserWindowMapIter; - BrowserWindowMap mBrowserWindowMap; -}; - -#ifdef __GNUC__ -#pragma GCC visibility pop -#endif - -#endif // LLQTWEBKIT_H diff --git a/indra/llqtwebkit/llqtwebkit.pri b/indra/llqtwebkit/llqtwebkit.pri deleted file mode 100644 index 4f85aa423d..0000000000 --- a/indra/llqtwebkit/llqtwebkit.pri +++ /dev/null @@ -1,47 +0,0 @@ -DEPENDPATH += $$PWD -INCLUDEPATH += $$PWD - -!mac { -unix { - DEFINES += LL_LINUX -} -} - -mac { - DEFINES += LL_OSX -} - -win32{ - DEFINES += _WINDOWS -} - -# Input -HEADERS += llembeddedbrowser.h \ - llembeddedbrowser_p.h \ - llembeddedbrowserwindow.h \ - llembeddedbrowserwindow_p.h \ - llnetworkaccessmanager.h \ - llqtwebkit.h \ - llwebpage.h \ - llwebpageopenshim.h \ - llstyle.h \ - lljsobject.h - -SOURCES += llembeddedbrowser.cpp \ - llembeddedbrowserwindow.cpp \ - llnetworkaccessmanager.cpp \ - llqtwebkit.cpp \ - llwebpage.cpp \ - llwebpageopenshim.cpp \ - llstyle.cpp \ - lljsobject.cpp - -FORMS += passworddialog.ui - -RCC_DIR = .rcc -UI_DIR = .ui -MOC_DIR = .moc -OBJECTS_DIR = .obj - -include(static.pri) -include(qtwebkit_cookiejar/src/src.pri) diff --git a/indra/llqtwebkit/llqtwebkit.pro b/indra/llqtwebkit/llqtwebkit.pro deleted file mode 100644 index b6ff077bd1..0000000000 --- a/indra/llqtwebkit/llqtwebkit.pro +++ /dev/null @@ -1,18 +0,0 @@ -TEMPLATE = lib -CONFIG += static staticlib # we always build as static lib whether Qt is static or not -TARGET = -DEPENDPATH += . -INCLUDEPATH += . - -include(llqtwebkit.pri) - -QT += webkit opengl network gui - -win32:CONFIG(debug,debug|release) { - TARGET = llqtwebkitd -} - -RCC_DIR = $$PWD/.rcc -UI_DIR = $$PWD/.ui -MOC_DIR = $$PWD/.moc -OBJECTS_DIR = $$PWD/.obj diff --git a/indra/llqtwebkit/llstyle.cpp b/indra/llqtwebkit/llstyle.cpp deleted file mode 100644 index 8822d481a2..0000000000 --- a/indra/llqtwebkit/llstyle.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include "llstyle.h" - -#include "llembeddedbrowserwindow_p.h" -#include -#include -#include - -LLStyle::LLStyle() - : QPlastiqueStyle() -{ -} - -void LLStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const -{ -#ifdef Q_WS_MAC - if (control == QStyle::CC_ScrollBar) { - QStyleOptionSlider* opt = (QStyleOptionSlider*)option; - const QPoint topLeft = opt->rect.topLeft(); - painter->translate(topLeft); - opt->rect.moveTo(QPoint(0, 0)); - painter->fillRect(opt->rect, opt->palette.background()); - } -#endif - QPlastiqueStyle::drawComplexControl(control, option, painter, widget); -} - -void LLStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const -{ - switch(element) - { - case CE_ScrollBarAddLine: - case CE_ScrollBarSubLine: - // This fixes the "scrollbar arrows pointing the wrong way" bug. - if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) - { - // Make the State_Horizontal bit in the option's state field match its orientation field. - QStyleOptionSlider localOption(*scrollBar); - if(localOption.orientation == Qt::Horizontal) - { - localOption.state |= State_Horizontal; - } - else - { - localOption.state &= ~State_Horizontal; - } - QPlastiqueStyle::drawControl(element, &localOption, painter, widget); - return; - } - default: - break; - } - - QPlastiqueStyle::drawControl(element, option, painter, widget); -} diff --git a/indra/llqtwebkit/llstyle.h b/indra/llqtwebkit/llstyle.h deleted file mode 100644 index 77c09b3bb6..0000000000 --- a/indra/llqtwebkit/llstyle.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LLSTYLE_H -#define LLSTYLE_H - -#include - -class LLStyle : public QPlastiqueStyle -{ - -public: - explicit LLStyle(); - void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = 0) const; - void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const; - -}; - -#endif - diff --git a/indra/llqtwebkit/llwebpage.cpp b/indra/llqtwebkit/llwebpage.cpp deleted file mode 100644 index 113c0c186a..0000000000 --- a/indra/llqtwebkit/llwebpage.cpp +++ /dev/null @@ -1,536 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include "llwebpage.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "llqtwebkit.h" -#include "llembeddedbrowser.h" -#include "llembeddedbrowserwindow.h" -#include "llembeddedbrowserwindow_p.h" -#include "lljsobject.h" - -LLWebPage::LLWebPage(QObject *parent) - : QWebPage(parent) - , window(0) - , mHostLanguage( "en" ) - , mWhiteListRegex( "" ) -{ - mJsObject = new LLJsObject( parent ); - - connect(this, SIGNAL(loadProgress(int)), - this, SLOT(loadProgressSlot(int))); - connect(this, SIGNAL(linkHovered(const QString &, const QString &, const QString &)), - this, SLOT(linkHoveredSlot(const QString &, const QString &, const QString &))); - connect(this, SIGNAL(statusBarMessage(const QString &)), - this, SLOT(statusBarMessageSlot(const QString &))); - connect(mainFrame(), SIGNAL(urlChanged(const QUrl&)), - this, SLOT(urlChangedSlot(const QUrl&))); - connect(this, SIGNAL(loadStarted()), - this, SLOT(loadStarted())); - connect(this, SIGNAL(loadFinished(bool)), - this, SLOT(loadFinished(bool))); - connect(this, SIGNAL(windowCloseRequested()), - this, SLOT(windowCloseRequested())); - connect(this, SIGNAL(geometryChangeRequested(const QRect&)), - this, SLOT(geometryChangeRequested(const QRect&))); - connect(mainFrame(), SIGNAL(titleChanged(const QString&)), - this, SLOT(titleChangedSlot(const QString&))); - connect(mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), - this, SLOT(extendNavigatorObject())); -} - -LLWebPage::~LLWebPage() -{ - delete mJsObject; -} - -void LLWebPage::loadProgressSlot(int progress) -{ - if (!window) - return; - window->d->mPercentComplete = progress; - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setEventUri(window->getCurrentUri()); - event.setIntValue(progress); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onUpdateProgress, event); - - if ( progress >= 100 ) - window->d->mShowLoadingOverlay = false; - - window->d->mDirty = true; - window->grabWindow(0,0,webView->boundingRect().width(),webView->boundingRect().height()); - - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onPageChanged, event); -} - -void LLWebPage::linkHoveredSlot(const QString &link, const QString &title, const QString &textContent) -{ - if (!window) - return; - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setEventUri(llToStdString(link)); - event.setStringValue(llToStdString(title)); - event.setStringValue2(llToStdString(textContent)); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onLinkHovered, event); -} - -void LLWebPage::statusBarMessageSlot(const QString& text) -{ - if (!window) - return; - window->d->mStatusText = llToStdString(text); - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setEventUri(window->getCurrentUri()); - event.setStringValue(window->d->mStatusText); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onStatusTextChange, event); -} - -void LLWebPage::titleChangedSlot(const QString& text) -{ - if (!window) - return; - window->d->mTitle = llToStdString(text); - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setEventUri(window->getCurrentUri()); - event.setStringValue(window->d->mTitle); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onTitleChange, event); -} - -// set the regex used to determine if a page is trusted or not -void LLWebPage::setWhiteListRegex( const std::string& regex ) -{ - mWhiteListRegex = regex; -} - -void LLWebPage::configureTrustedPage( bool is_trusted ) -{ - // action happens in browser window parent - LLEmbeddedBrowser* parent_browser = 0; - if ( window && window->d && window->d->mParent ) - { - parent_browser = window->d->mParent; - if ( parent_browser ) - { - if ( is_trusted ) - { - //qDebug() << "Whitelist passed - turning on"; - - // trusted so turn everything on - parent_browser->enableJavaScriptTransient( true ); - parent_browser->enableCookiesTransient( true ); - parent_browser->enablePluginsTransient( true ); - } - else - { - //qDebug() << "Whitelist failed - reverting to default state"; - - // restore default state set by client - parent_browser->enableJavaScript( parent_browser->isJavaScriptEnabled() ); - parent_browser->enableCookies( parent_browser->areCookiesEnabled() ); - parent_browser->enablePlugins( parent_browser->arePluginsEnabled() ); - } - } - } -} - -bool LLWebPage::checkRegex( const QUrl& url ) -{ - QRegExp reg_exp( QString::fromStdString( mWhiteListRegex ) ); - reg_exp.setCaseSensitivity( Qt::CaseInsensitive ); - reg_exp.setMinimal( true ); - - if ( reg_exp.exactMatch( url.host() ) ) - { - return true; - } - else - { - return false; - } -} - -void LLWebPage::checkWhiteList( const QUrl& url ) -{ - if ( mWhiteListRegex.length() ) - { - if ( checkRegex( url ) ) - { - configureTrustedPage( true ); // page is "trusted" - go ahead and configure it as such - } - else - { - configureTrustedPage( false ); // page is "NOT trusted" - go ahead and configure it as such - } - } - else - // no regex specified, don't do anything (i.e. don't change trust state) - { - } -} - -void LLWebPage::urlChangedSlot(const QUrl& url) -{ - if (!window) - return; - - checkWhiteList( url ); - - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setEventUri(window->getCurrentUri()); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onLocationChange, event); -} - -bool LLWebPage::event(QEvent *event) -{ - bool result = QWebPage::event(event); - - if (event->type() == QEvent::GraphicsSceneMousePress) - currentPoint = ((QGraphicsSceneMouseEvent*)event)->pos().toPoint(); - else if(event->type() == QEvent::GraphicsSceneMouseRelease) - currentPoint = QPoint(); - - return result; -} - -bool LLWebPage::acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, NavigationType type) -{ - Q_UNUSED( frame ); - - if (!window) - return false; - - if (request.url().scheme() == window->d->mNoFollowScheme) - { - QString encodedUrl = request.url().toEncoded(); - // QUrl is turning foo:///home/bar into foo:/home/bar for some reason while Firefox does not - // http://bugs.webkit.org/show_bug.cgi?id=24695 - if (!encodedUrl.startsWith(window->d->mNoFollowScheme + "://")) { - encodedUrl = encodedUrl.mid(window->d->mNoFollowScheme.length() + 1); - encodedUrl = window->d->mNoFollowScheme + "://" + encodedUrl; - } - std::string rawUri = llToStdString(encodedUrl); - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setEventUri(rawUri); - - // pass over the navigation type as per this page: http://apidocs.meego.com/1.1/core/html/qt4/qwebpage.html#NavigationType-enum - // pass as strings because telling everyone who needs to know about enums is too invasive. - std::string nav_type("unknown"); - if (type == QWebPage::NavigationTypeLinkClicked) nav_type="clicked"; - else - if (type == QWebPage::NavigationTypeFormSubmitted) nav_type="form_submited"; - else - if (type == QWebPage::NavigationTypeBackOrForward) nav_type="back_forward"; - else - if (type == QWebPage::NavigationTypeReload) nav_type="reloaded"; - else - if (type == QWebPage::NavigationTypeFormResubmitted) nav_type="form_resubmited"; - event.setNavigationType(nav_type); - - if ( mWhiteListRegex.length() ) - { - if ( frame ) - { - if ( checkRegex( frame->url() ) ) - { - event.setTrustedHost( true ); - } - else - { - event.setTrustedHost( false ); - } - } - else - // no frame - no trust (TODO: when can this happen?) - { - event.setTrustedHost( false ); - } - } - else - // no regex is like switching it off and indicating everything is trusted - { - event.setTrustedHost( true ); - } - - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onClickLinkNoFollow, event); - - //qDebug() << "LLWebPage::acceptNavigationRequest: sending onClickLinkNoFollow, NavigationType is " << type << ", url is " << QString::fromStdString(rawUri) ; - return false; - } - - - return true; -} - - -void LLWebPage::loadStarted() -{ - if (!window) - return; - - QUrl url( QString::fromStdString( window->getCurrentUri() ) ); - checkWhiteList( url ); - - window->d->mShowLoadingOverlay = true; - - window->d->mTimeLoadStarted=time(NULL); - - window->d->mDirty = true; - window->grabWindow(0,0,webView->boundingRect().width(),webView->boundingRect().height()); - - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setEventUri(window->getCurrentUri()); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onNavigateBegin, event); -} - -void LLWebPage::loadFinished(bool) -{ - if (!window) - return; - - window->d->mShowLoadingOverlay = false; - - window->d->mDirty = true; - window->grabWindow(0,0,webView->boundingRect().width(),webView->boundingRect().height()); - - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setEventUri(window->getCurrentUri()); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onPageChanged, event); - - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onNavigateComplete, event); -} - -void LLWebPage::windowCloseRequested() -{ - if (!window) - return; - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onWindowCloseRequested, event); -} - -void LLWebPage::geometryChangeRequested(const QRect& geom) -{ - if (!window) - return; - - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - // empty UUID indicates this is targeting the main window -// event.setStringValue(window->getUUID()); - event.setRectValue(geom.x(), geom.y(), geom.width(), geom.height()); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onWindowGeometryChangeRequested, event); -} - -QString LLWebPage::chooseFile(QWebFrame* parentFrame, const QString& suggestedFile) -{ - Q_UNUSED(parentFrame); - Q_UNUSED(suggestedFile); - - return QString::fromStdString( window->requestFilePicker() ); -} - -void LLWebPage::javaScriptAlert(QWebFrame* frame, const QString& msg) -{ - Q_UNUSED(frame); - QMessageBox *msgBox = new QMessageBox; - msgBox->setWindowTitle(tr("JavaScript Alert - %1").arg(mainFrame()->url().host())); - msgBox->setText(msg); - msgBox->addButton(QMessageBox::Ok); - - QGraphicsProxyWidget *proxy = webView->scene()->addWidget(msgBox); - proxy->setWindowFlags(Qt::Window); // this makes the item a panel (and will make it get a window 'frame') - proxy->setPanelModality(QGraphicsItem::SceneModal); - proxy->setPos((webView->boundingRect().width() - msgBox->sizeHint().width())/2, - (webView->boundingRect().height() - msgBox->sizeHint().height())/2); - proxy->setActive(true); // make it the active item - - connect(msgBox, SIGNAL(finished(int)), proxy, SLOT(deleteLater())); - msgBox->show(); - - webView->scene()->setFocusItem(proxy); -} - -bool LLWebPage::javaScriptConfirm(QWebFrame* frame, const QString& msg) -{ - Q_UNUSED(frame); - Q_UNUSED(msg); - qWarning() << "LLWebPage::" << __FUNCTION__ << "not implemented" << msg << "returning true"; - return true; -} - -bool LLWebPage::javaScriptPrompt(QWebFrame* frame, const QString& msg, const QString& defaultValue, QString* result) -{ - Q_UNUSED(frame); - Q_UNUSED(msg); - Q_UNUSED(defaultValue); - Q_UNUSED(result); - qWarning() << "LLWebPage::" << __FUNCTION__ << "not implemented" << msg << defaultValue << "returning false"; - return false; -} - -void LLWebPage::extendNavigatorObject() -{ - // legacy - will go away in the future - QString q_host_language = QString::fromStdString( mHostLanguage ); - mainFrame()->evaluateJavaScript(QString("navigator.hostLanguage=\"%1\"").arg( q_host_language )); - - // the new way - if ( mJsObject ) - { - bool enabled = mJsObject->getSLObjectEnabled(); - if ( enabled ) - { - mainFrame()->addToJavaScriptWindowObject("slviewer", mJsObject ); - }; - }; -} - -QWebPage *LLWebPage::createWindow(WebWindowType type) -{ - Q_UNUSED(type); - QWebPage *result = NULL; - - if(window) - { - result = window->createWindow(); - } - - return result; -} - -void LLWebPage::setHostLanguage(const std::string& host_language) -{ - mHostLanguage = host_language; -} - -bool LLWebPage::supportsExtension(QWebPage::Extension extension) const -{ - if (extension == QWebPage::ErrorPageExtension) - return true; - return false; -} - -bool LLWebPage::extension(Extension, const ExtensionOption* option, ExtensionReturn* output) -{ - const QWebPage::ErrorPageExtensionOption* info = static_cast(option); - QWebPage::ErrorPageExtensionReturn* errorPage = static_cast(output); - - errorPage->content = QString("Failed loading page

    %1

    ") - .arg(info->errorString).toUtf8(); - - return true; -} - -// Second Life viewer specific functions -void LLWebPage::setSLObjectEnabled( bool enabled ) -{ - if ( mJsObject ) - mJsObject->setSLObjectEnabled( enabled ); -} - -void LLWebPage::setAgentLanguage( const std::string& agent_language ) -{ - if ( mJsObject ) - mJsObject->setAgentLanguage( QString::fromStdString( agent_language ) ); -} - -void LLWebPage::setAgentRegion( const std::string& agent_region ) -{ - if ( mJsObject ) - mJsObject->setAgentRegion( QString::fromStdString( agent_region ) ); -} - -void LLWebPage::setAgentLocation( double x, double y, double z ) -{ - if ( mJsObject ) - { - QVariantMap location; - location["x"] = x; - location["y"] = y; - location["z"] = z; - mJsObject->setAgentLocation( location ); - } -} - -void LLWebPage::setAgentGlobalLocation( double x, double y, double z ) -{ - if ( mJsObject ) - { - QVariantMap global_location; - global_location["x"] = x; - global_location["y"] = y; - global_location["z"] = z; - mJsObject->setAgentGlobalLocation( global_location ); - } -} - -void LLWebPage::setAgentOrientation( double angle ) -{ - if ( mJsObject ) - { - mJsObject->setAgentOrientation( angle ); - } -} - -void LLWebPage::setAgentMaturity( const std::string& agent_maturity ) -{ - if ( mJsObject ) - mJsObject->setAgentMaturity( QString::fromStdString( agent_maturity ) ); -} - -void LLWebPage::emitLocation() -{ - if ( mJsObject ) - mJsObject->emitLocation(); -} - -void LLWebPage::emitMaturity() -{ - if ( mJsObject ) - mJsObject->emitMaturity(); -} - -void LLWebPage::emitLanguage() -{ - if ( mJsObject ) - mJsObject->emitLanguage(); -} - -void LLWebPage::setPageZoomFactor( double factor ) -{ - if ( webView ) - { - webView->setZoomFactor( factor ); - } -} \ No newline at end of file diff --git a/indra/llqtwebkit/llwebpage.h b/indra/llqtwebkit/llwebpage.h deleted file mode 100644 index 1a882254f1..0000000000 --- a/indra/llqtwebkit/llwebpage.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LLWEBPAGE_H -#define LLWEBPAGE_H - -class QGraphicsWebView; -#include -#include "llqtwebkit.h" - -class LLEmbeddedBrowserWindow; -class LLJsObject; - -class LLWebPage : public QWebPage -{ - Q_OBJECT - - public: - LLWebPage(QObject *parent = 0); - ~LLWebPage(); - - LLEmbeddedBrowserWindow *window; - bool event(QEvent *event); - - QGraphicsWebView *webView; - - void setHostLanguage(const std::string& host_language); - virtual bool supportsExtension(QWebPage::Extension extension) const; - virtual bool extension(Extension extension, const ExtensionOption* option, ExtensionReturn* output); - - // set the regex used to determine if a page is trusted or not - void setWhiteListRegex( const std::string& regex ); - - // check the whitelist and update browser config as appropriate - void checkWhiteList( const QUrl& url ); - - // code to change settings if page is known to be trusted goes here - void configureTrustedPage( bool is_trusted ); - - // Second Life specific functions - void setAgentRegion( const std::string& agent_region ); - void setAgentLocation( double x, double y, double z ); - void setAgentGlobalLocation( double x, double y, double z ); - void setAgentOrientation( double angle ); - void setSLObjectEnabled( bool enabled ); - void setAgentLanguage( const std::string& agent_language ); - void setAgentMaturity( const std::string& agent_maturity ); - void emitLocation(); - void emitMaturity(); - void emitLanguage(); - - void setPageZoomFactor( double factor ); - - protected: - bool acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, NavigationType type); - - public slots: - void loadProgressSlot(int progress); - void linkHoveredSlot(const QString &link, const QString &title, const QString &textContent); - void statusBarMessageSlot(const QString &); - void titleChangedSlot(const QString &); - void urlChangedSlot(const QUrl& url); - void loadStarted(); - void loadFinished(bool ok); - void windowCloseRequested(); - void geometryChangeRequested(const QRect& geom); - - private slots: - void extendNavigatorObject(); - - protected: - QString chooseFile(QWebFrame* parentFrame, const QString& suggestedFile); - void javaScriptAlert(QWebFrame* frame, const QString& msg); - bool javaScriptConfirm(QWebFrame* frame, const QString& msg); - bool javaScriptPrompt(QWebFrame* frame, const QString& msg, const QString& defaultValue, QString* result); - QWebPage *createWindow(WebWindowType type); - - private: - bool checkRegex( const QUrl& url ); - QPoint currentPoint; - std::string mHostLanguage; - std::string mWhiteListRegex; - LLJsObject* mJsObject; -}; - -#endif diff --git a/indra/llqtwebkit/llwebpageopenshim.cpp b/indra/llqtwebkit/llwebpageopenshim.cpp deleted file mode 100644 index af9627907f..0000000000 --- a/indra/llqtwebkit/llwebpageopenshim.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include "llwebpageopenshim.h" - -#include -#include -#include -#include - -#include "llqtwebkit.h" -#include "llembeddedbrowserwindow.h" -#include "llembeddedbrowserwindow_p.h" - -LLWebPageOpenShim::LLWebPageOpenShim(LLEmbeddedBrowserWindow *in_window, QObject *parent) - : QWebPage(parent) - , window(in_window) - , mOpeningSelf(false) - , mGeometryChangeRequested(false) - , mHasSentUUID(false) -{ -// qDebug() << "LLWebPageOpenShim created"; - - connect(this, SIGNAL(windowCloseRequested()), - this, SLOT(windowCloseRequested())); - connect(this, SIGNAL(geometryChangeRequested(const QRect&)), - this, SLOT(geometryChangeRequested(const QRect&))); - - // Create a unique UUID for this proxy - mUUID = llToStdString(QUuid::createUuid().toString()); - - // mTarget starts out as the empty string, which is what we want. -} - -LLWebPageOpenShim::~LLWebPageOpenShim() -{ -// qDebug() << "LLWebPageOpenShim destroyed"; -} - -void LLWebPageOpenShim::windowCloseRequested() -{ -// qDebug() << "LLWebPageOpenShim::windowCloseRequested"; - if(window) - { - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setStringValue(mUUID); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onWindowCloseRequested, event); - } -} - -void LLWebPageOpenShim::geometryChangeRequested(const QRect& geom) -{ -// qDebug() << "LLWebPageOpenShim::geometryChangeRequested: " << geom ; - - // This seems to happen before acceptNavigationRequest is called. If this is the case, delay sending the message until afterwards. - - if(window && mHasSentUUID) - { - LLEmbeddedBrowserWindowEvent event(window->getWindowId()); - event.setStringValue(mUUID); - event.setRectValue(geom.x(), geom.y(), geom.width(), geom.height()); - window->d->mEventEmitter.update(&LLEmbeddedBrowserWindowObserver::onWindowGeometryChangeRequested, event); - } - else - { - mGeometry = geom; - mGeometryChangeRequested = true; - } - -} - -bool LLWebPageOpenShim::matchesTarget(const std::string target) -{ - return (target == mTarget); -} - -bool LLWebPageOpenShim::matchesUUID(const std::string uuid) -{ - return (uuid == mUUID); -} - -void LLWebPageOpenShim::setProxy(const std::string &target, const std::string &uuid) -{ - mTarget = target; - mUUID = uuid; - - mHasSentUUID = false; - - mOpeningSelf = true; - - mainFrame()->evaluateJavaScript(QString("window.open("", \"%1\");").arg( QString::fromStdString(target) )); -} - -bool LLWebPageOpenShim::acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, NavigationType type) -{ - Q_UNUSED(type); - if (!window) - { - return false; - } - - if(mOpeningSelf) - { - qDebug() << "LLWebPageOpenShim::acceptNavigationRequest: reopening self to set target name."; - return true; - } - -#if 0 - qDebug() << "LLWebPageOpenShim::acceptNavigationRequest called, NavigationType is " << type - << ", web frame is " << frame - << ", frame->page is " << frame->page() - << ", url is " << request.url() - << ", frame name is " << frame->frameName() - ; -#endif - - if (request.url().scheme() == QString("file")) - { - // For some reason, I'm seeing a spurious call to this function with a file:/// URL that points to the current working directory. - // Ignoring file:/// URLs here isn't a perfect solution (since it could potentially break content in local HTML files), - // but it's the best I could come up with for now. - - return false; - } - - // The name of the incoming frame has been set to the link target that was used when opening this window. - std::string click_href = llToStdString(request.url()); - mTarget = llToStdString(frame->frameName()); - - // build event based on the data we have and emit it - LLEmbeddedBrowserWindowEvent event( window->getWindowId()); - event.setEventUri(click_href); - event.setStringValue(mTarget); - event.setStringValue2(mUUID); - - window->d->mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onClickLinkHref, event ); - - mHasSentUUID = true; - - if(mGeometryChangeRequested) - { - geometryChangeRequested(mGeometry); - mGeometryChangeRequested = false; - } - - return false; -} - -QWebPage *LLWebPageOpenShim::createWindow(WebWindowType type) -{ - Q_UNUSED(type); - - return this; -} diff --git a/indra/llqtwebkit/llwebpageopenshim.h b/indra/llqtwebkit/llwebpageopenshim.h deleted file mode 100644 index 322f832ce0..0000000000 --- a/indra/llqtwebkit/llwebpageopenshim.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LLWEBPAGEOPENSHIM_H -#define LLWEBPAGEOPENSHIM_H - -#include - -class LLEmbeddedBrowserWindow; -class LLWebPageOpenShim : public QWebPage -{ - Q_OBJECT - - public: - LLWebPageOpenShim(LLEmbeddedBrowserWindow *in_window, QObject *parent = 0); - ~LLWebPageOpenShim(); - LLEmbeddedBrowserWindow *window; - bool matchesTarget(const std::string target); - bool matchesUUID(const std::string uuid); - void setProxy(const std::string &target, const std::string &uuid); - - public slots: - void windowCloseRequested(); - void geometryChangeRequested(const QRect& geom); - - protected: - bool acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, NavigationType type); - QWebPage *createWindow(WebWindowType type); - - private: - std::string mUUID; - std::string mTarget; - bool mOpeningSelf; - bool mGeometryChangeRequested; - bool mHasSentUUID; - QRect mGeometry; - -}; - -#endif - diff --git a/indra/llqtwebkit/passworddialog.ui b/indra/llqtwebkit/passworddialog.ui deleted file mode 100644 index 033514eff8..0000000000 --- a/indra/llqtwebkit/passworddialog.ui +++ /dev/null @@ -1,137 +0,0 @@ - - - PasswordDialog - - - - 0 - 0 - 394 - 183 - - - - Dialog - - - - - - Qt::Vertical - - - - 20 - 12 - - - - - - - - - - - true - - - - - - - - 32 - 32 - - - - icon - - - - - - - Qt::Vertical - - - - 20 - 13 - - - - - - - - User name: - - - - - - - - - - Password: - - - - - - - QLineEdit::Password - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - PasswordDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - PasswordDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/indra/llqtwebkit/pstdint.h b/indra/llqtwebkit/pstdint.h deleted file mode 100644 index b36f63db3a..0000000000 --- a/indra/llqtwebkit/pstdint.h +++ /dev/null @@ -1,728 +0,0 @@ -/* A portable stdint.h - **************************************************************************** - * BSD License: - **************************************************************************** - * - * Copyright (c) 2005-2007 Paul Hsieh - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - **************************************************************************** - * - * Version 0.1.10 - * - * The ANSI C standard committee, for the C99 standard, specified the - * inclusion of a new standard include file called stdint.h. This is - * a very useful and long desired include file which contains several - * very precise definitions for integer scalar types that is - * critically important for making portable several classes of - * applications including cryptography, hashing, variable length - * integer libraries and so on. But for most developers its likely - * useful just for programming sanity. - * - * The problem is that most compiler vendors have decided not to - * implement the C99 standard, and the next C++ language standard - * (which has a lot more mindshare these days) will be a long time in - * coming and its unknown whether or not it will include stdint.h or - * how much adoption it will have. Either way, it will be a long time - * before all compilers come with a stdint.h and it also does nothing - * for the extremely large number of compilers available today which - * do not include this file, or anything comparable to it. - * - * So that's what this file is all about. Its an attempt to build a - * single universal include file that works on as many platforms as - * possible to deliver what stdint.h is supposed to. A few things - * that should be noted about this file: - * - * 1) It is not guaranteed to be portable and/or present an identical - * interface on all platforms. The extreme variability of the - * ANSI C standard makes this an impossibility right from the - * very get go. Its really only meant to be useful for the vast - * majority of platforms that possess the capability of - * implementing usefully and precisely defined, standard sized - * integer scalars. Systems which are not intrinsically 2s - * complement may produce invalid constants. - * - * 2) There is an unavoidable use of non-reserved symbols. - * - * 3) Other standard include files are invoked. - * - * 4) This file may come in conflict with future platforms that do - * include stdint.h. The hope is that one or the other can be - * used with no real difference. - * - * 5) In the current verison, if your platform can't represent - * int32_t, int16_t and int8_t, it just dumps out with a compiler - * error. - * - * 6) 64 bit integers may or may not be defined. Test for their - * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. - * Note that this is different from the C99 specification which - * requires the existence of 64 bit support in the compiler. If - * this is not defined for your platform, yet it is capable of - * dealing with 64 bits then it is because this file has not yet - * been extended to cover all of your system's capabilities. - * - * 7) (u)intptr_t may or may not be defined. Test for its presence - * with the test: #ifdef PTRDIFF_MAX. If this is not defined - * for your platform, then it is because this file has not yet - * been extended to cover all of your system's capabilities, not - * because its optional. - * - * 8) The following might not been defined even if your platform is - * capable of defining it: - * - * WCHAR_MIN - * WCHAR_MAX - * (u)int64_t - * PTRDIFF_MIN - * PTRDIFF_MAX - * (u)intptr_t - * - * 9) The following have not been defined: - * - * WINT_MIN - * WINT_MAX - * - * 10) The criteria for defining (u)int_least(*)_t isn't clear, - * except for systems which don't have a type that precisely - * defined 8, 16, or 32 bit types (which this include file does - * not support anyways). Default definitions have been given. - * - * 11) The criteria for defining (u)int_fast(*)_t isn't something I - * would trust to any particular compiler vendor or the ANSI C - * committee. It is well known that "compatible systems" are - * commonly created that have very different performance - * characteristics from the systems they are compatible with, - * especially those whose vendors make both the compiler and the - * system. Default definitions have been given, but its strongly - * recommended that users never use these definitions for any - * reason (they do *NOT* deliver any serious guarantee of - * improved performance -- not in this file, nor any vendor's - * stdint.h). - * - * 12) The following macros: - * - * PRINTF_INTMAX_MODIFIER - * PRINTF_INT64_MODIFIER - * PRINTF_INT32_MODIFIER - * PRINTF_INT16_MODIFIER - * PRINTF_LEAST64_MODIFIER - * PRINTF_LEAST32_MODIFIER - * PRINTF_LEAST16_MODIFIER - * PRINTF_INTPTR_MODIFIER - * - * are strings which have been defined as the modifiers required - * for the "d", "u" and "x" printf formats to correctly output - * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, - * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. - * PRINTF_INTPTR_MODIFIER is not defined for some systems which - * provide their own stdint.h. PRINTF_INT64_MODIFIER is not - * defined if INT64_MAX is not defined. These are an extension - * beyond what C99 specifies must be in stdint.h. - * - * In addition, the following macros are defined: - * - * PRINTF_INTMAX_HEX_WIDTH - * PRINTF_INT64_HEX_WIDTH - * PRINTF_INT32_HEX_WIDTH - * PRINTF_INT16_HEX_WIDTH - * PRINTF_INT8_HEX_WIDTH - * PRINTF_INTMAX_DEC_WIDTH - * PRINTF_INT64_DEC_WIDTH - * PRINTF_INT32_DEC_WIDTH - * PRINTF_INT16_DEC_WIDTH - * PRINTF_INT8_DEC_WIDTH - * - * Which specifies the maximum number of characters required to - * print the number of that type in either hexadecimal or decimal. - * These are an extension beyond what C99 specifies must be in - * stdint.h. - * - * Compilers tested (all with 0 warnings at their highest respective - * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 - * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio - * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 - * - * This file should be considered a work in progress. Suggestions for - * improvements, especially those which increase coverage are strongly - * encouraged. - * - * Acknowledgements - * - * The following people have made significant contributions to the - * development and testing of this file: - * - * Chris Howie - * John Steele Scott - * Dave Thorup - * - */ - -#include -#include -#include - -/* - * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and - * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. - */ - -#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED) -#include -#define _PSTDINT_H_INCLUDED -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -# endif -# ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -# endif -# ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -# endif -# ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -# endif -# ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -# endif -# ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -# endif -# ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -# endif -# ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif - -/* - * Something really weird is going on with Open Watcom. Just pull some of - * these duplicated definitions from Open Watcom's stdint.h file for now. - */ - -# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 -# if !defined (INT64_C) -# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) -# endif -# if !defined (UINT64_C) -# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) -# endif -# if !defined (INT32_C) -# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) -# endif -# if !defined (UINT32_C) -# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) -# endif -# if !defined (INT16_C) -# define INT16_C(x) (x) -# endif -# if !defined (UINT16_C) -# define UINT16_C(x) (x) -# endif -# if !defined (INT8_C) -# define INT8_C(x) (x) -# endif -# if !defined (UINT8_C) -# define UINT8_C(x) (x) -# endif -# if !defined (UINT64_MAX) -# define UINT64_MAX 18446744073709551615ULL -# endif -# if !defined (INT64_MAX) -# define INT64_MAX 9223372036854775807LL -# endif -# if !defined (UINT32_MAX) -# define UINT32_MAX 4294967295UL -# endif -# if !defined (INT32_MAX) -# define INT32_MAX 2147483647L -# endif -# if !defined (INTMAX_MAX) -# define INTMAX_MAX INT64_MAX -# endif -# if !defined (INTMAX_MIN) -# define INTMAX_MIN INT64_MIN -# endif -# endif -#endif - -#ifndef _PSTDINT_H_INCLUDED -#define _PSTDINT_H_INCLUDED - -#ifndef SIZE_MAX -# define SIZE_MAX (~(size_t)0) -#endif - -/* - * Deduce the type assignments from limits.h under the assumption that - * integer sizes in bits are powers of 2, and follow the ANSI - * definitions. - */ - -#ifndef UINT8_MAX -# define UINT8_MAX 0xff -#endif -#ifndef uint8_t -# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) - typedef unsigned char uint8_t; -# define UINT8_C(v) ((uint8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef INT8_MAX -# define INT8_MAX 0x7f -#endif -#ifndef INT8_MIN -# define INT8_MIN INT8_C(0x80) -#endif -#ifndef int8_t -# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) - typedef signed char int8_t; -# define INT8_C(v) ((int8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef UINT16_MAX -# define UINT16_MAX 0xffff -#endif -#ifndef uint16_t -#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) - typedef unsigned int uint16_t; -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -# define UINT16_C(v) ((uint16_t) (v)) -#elif (USHRT_MAX == UINT16_MAX) - typedef unsigned short uint16_t; -# define UINT16_C(v) ((uint16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT16_MAX -# define INT16_MAX 0x7fff -#endif -#ifndef INT16_MIN -# define INT16_MIN INT16_C(0x8000) -#endif -#ifndef int16_t -#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) - typedef signed int int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -#elif (SHRT_MAX == INT16_MAX) - typedef signed short int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef UINT32_MAX -# define UINT32_MAX (0xffffffffUL) -#endif -#ifndef uint32_t -#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) - typedef unsigned long uint32_t; -# define UINT32_C(v) v ## UL -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (UINT_MAX == UINT32_MAX) - typedef unsigned int uint32_t; -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -# define UINT32_C(v) v ## U -#elif (USHRT_MAX == UINT32_MAX) - typedef unsigned short uint32_t; -# define UINT32_C(v) ((unsigned short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT32_MAX -# define INT32_MAX (0x7fffffffL) -#endif -#ifndef INT32_MIN -# define INT32_MIN INT32_C(0x80000000) -#endif -#ifndef int32_t -#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) - typedef signed long int32_t; -# define INT32_C(v) v ## L -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (INT_MAX == INT32_MAX) - typedef signed int int32_t; -# define INT32_C(v) v -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#elif (SHRT_MAX == INT32_MAX) - typedef signed short int32_t; -# define INT32_C(v) ((short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -/* - * The macro stdint_int64_defined is temporarily used to record - * whether or not 64 integer support is available. It must be - * defined for any 64 integer extensions for new platforms that are - * added. - */ - -#undef stdint_int64_defined -#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) -# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# endif -#endif - -#if !defined (stdint_int64_defined) -# if defined(__GNUC__) -# define stdint_int64_defined - __extension__ typedef long long int64_t; - __extension__ typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) -# define stdint_int64_defined - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; -# define UINT64_C(v) v ## UI64 -# define INT64_C(v) v ## I64 -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "I64" -# endif -# endif -#endif - -#if !defined (LONG_LONG_MAX) && defined (INT64_C) -# define LONG_LONG_MAX INT64_C (9223372036854775807) -#endif -#ifndef ULONG_LONG_MAX -# define ULONG_LONG_MAX UINT64_C (18446744073709551615) -#endif - -#if !defined (INT64_MAX) && defined (INT64_C) -# define INT64_MAX INT64_C (9223372036854775807) -#endif -#if !defined (INT64_MIN) && defined (INT64_C) -# define INT64_MIN INT64_C (-9223372036854775808) -#endif -#if !defined (UINT64_MAX) && defined (INT64_C) -# define UINT64_MAX UINT64_C (18446744073709551615) -#endif - -/* - * Width of hexadecimal for number field. - */ - -#ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -#endif -#ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -#endif -#ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -#endif -#ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -#endif - -#ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -#endif -#ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -#endif -#ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -#endif -#ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -#endif - -/* - * Ok, lets not worry about 128 bit integers for now. Moore's law says - * we don't need to worry about that until about 2040 at which point - * we'll have bigger things to worry about. - */ - -#ifdef stdint_int64_defined - typedef int64_t intmax_t; - typedef uint64_t uintmax_t; -# define INTMAX_MAX INT64_MAX -# define INTMAX_MIN INT64_MIN -# define UINTMAX_MAX UINT64_MAX -# define UINTMAX_C(v) UINT64_C(v) -# define INTMAX_C(v) INT64_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif -#else - typedef int32_t intmax_t; - typedef uint32_t uintmax_t; -# define INTMAX_MAX INT32_MAX -# define UINTMAX_MAX UINT32_MAX -# define UINTMAX_C(v) UINT32_C(v) -# define INTMAX_C(v) INT32_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH -# endif -#endif - -/* - * Because this file currently only supports platforms which have - * precise powers of 2 as bit sizes for the default integers, the - * least definitions are all trivial. Its possible that a future - * version of this file could have different definitions. - */ - -#ifndef stdint_least_defined - typedef int8_t int_least8_t; - typedef uint8_t uint_least8_t; - typedef int16_t int_least16_t; - typedef uint16_t uint_least16_t; - typedef int32_t int_least32_t; - typedef uint32_t uint_least32_t; -# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER -# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER -# define UINT_LEAST8_MAX UINT8_MAX -# define INT_LEAST8_MAX INT8_MAX -# define UINT_LEAST16_MAX UINT16_MAX -# define INT_LEAST16_MAX INT16_MAX -# define UINT_LEAST32_MAX UINT32_MAX -# define INT_LEAST32_MAX INT32_MAX -# define INT_LEAST8_MIN INT8_MIN -# define INT_LEAST16_MIN INT16_MIN -# define INT_LEAST32_MIN INT32_MIN -# ifdef stdint_int64_defined - typedef int64_t int_least64_t; - typedef uint64_t uint_least64_t; -# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER -# define UINT_LEAST64_MAX UINT64_MAX -# define INT_LEAST64_MAX INT64_MAX -# define INT_LEAST64_MIN INT64_MIN -# endif -#endif -#undef stdint_least_defined - -/* - * The ANSI C committee pretending to know or specify anything about - * performance is the epitome of misguided arrogance. The mandate of - * this file is to *ONLY* ever support that absolute minimum - * definition of the fast integer types, for compatibility purposes. - * No extensions, and no attempt to suggest what may or may not be a - * faster integer type will ever be made in this file. Developers are - * warned to stay away from these types when using this or any other - * stdint.h. - */ - -typedef int_least8_t int_fast8_t; -typedef uint_least8_t uint_fast8_t; -typedef int_least16_t int_fast16_t; -typedef uint_least16_t uint_fast16_t; -typedef int_least32_t int_fast32_t; -typedef uint_least32_t uint_fast32_t; -#define UINT_FAST8_MAX UINT_LEAST8_MAX -#define INT_FAST8_MAX INT_LEAST8_MAX -#define UINT_FAST16_MAX UINT_LEAST16_MAX -#define INT_FAST16_MAX INT_LEAST16_MAX -#define UINT_FAST32_MAX UINT_LEAST32_MAX -#define INT_FAST32_MAX INT_LEAST32_MAX -#define INT_FAST8_MIN INT_LEAST8_MIN -#define INT_FAST16_MIN INT_LEAST16_MIN -#define INT_FAST32_MIN INT_LEAST32_MIN -#ifdef stdint_int64_defined - typedef int_least64_t int_fast64_t; - typedef uint_least64_t uint_fast64_t; -# define UINT_FAST64_MAX UINT_LEAST64_MAX -# define INT_FAST64_MAX INT_LEAST64_MAX -# define INT_FAST64_MIN INT_LEAST64_MIN -#endif - -#undef stdint_int64_defined - -/* - * Whatever piecemeal, per compiler thing we can do about the wchar_t - * type limits. - */ - -#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) -# include -# ifndef WCHAR_MIN -# define WCHAR_MIN 0 -# endif -# ifndef WCHAR_MAX -# define WCHAR_MAX ((wchar_t)-1) -# endif -#endif - -/* - * Whatever piecemeal, per compiler/platform thing we can do about the - * (u)intptr_t types and limits. - */ - -#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -#ifndef STDINT_H_UINTPTR_T_DEFINED -# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) -# define stdint_intptr_bits 64 -# elif defined (__WATCOMC__) || defined (__TURBOC__) -# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) -# define stdint_intptr_bits 16 -# else -# define stdint_intptr_bits 32 -# endif -# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) -# define stdint_intptr_bits 32 -# elif defined (__INTEL_COMPILER) -/* TODO -- what will Intel do about x86-64? */ -# endif - -# ifdef stdint_intptr_bits -# define stdint_intptr_glue3_i(a,b,c) a##b##c -# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) -# ifndef PRINTF_INTPTR_MODIFIER -# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) -# endif -# ifndef PTRDIFF_MAX -# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef PTRDIFF_MIN -# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef UINTPTR_MAX -# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MAX -# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MIN -# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef INTPTR_C -# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) -# endif -# ifndef UINTPTR_C -# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) -# endif - typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; - typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; -# else -/* TODO -- This following is likely wrong for some platforms, and does - nothing for the definition of uintptr_t. */ - typedef ptrdiff_t intptr_t; -# endif -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -/* - * Assumes sig_atomic_t is signed and we have a 2s complement machine. - */ - -#ifndef SIG_ATOMIC_MAX -# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) -#endif - -#endif diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/CMakeLists.txt b/indra/llqtwebkit/qtwebkit_cookiejar/CMakeLists.txt deleted file mode 100644 index 635765c83c..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# -*- cmake -*- - -add_subdirectory(src) diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/autotest/trie/trie.pro b/indra/llqtwebkit/qtwebkit_cookiejar/autotest/trie/trie.pro deleted file mode 100644 index c031e19718..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/autotest/trie/trie.pro +++ /dev/null @@ -1,15 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . - -win32: CONFIG += console -mac:CONFIG -= app_bundle - -CONFIG += qtestlib - -include(../../src/src.pri) - -# Input -SOURCES += tst_trie.cpp -HEADERS += diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/autotest/trie/tst_trie.cpp b/indra/llqtwebkit/qtwebkit_cookiejar/autotest/trie/tst_trie.cpp deleted file mode 100644 index e4bdc6d4ed..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/autotest/trie/tst_trie.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include -#include - -class tst_Trie : public QObject -{ - Q_OBJECT - -public slots: - void initTestCase(); - void cleanupTestCase(); - void init(); - void cleanup(); - -private slots: - void trie_data(); - void trie(); - - void insert_data(); - void insert(); - void clear(); - void find_data(); - void find(); - void remove_data(); - void remove(); - void all(); -}; - -// Subclass that exposes the protected functions. -class SubTrie : public Trie -{ -public: - -}; - -// This will be called before the first test function is executed. -// It is only called once. -void tst_Trie::initTestCase() -{ -} - -// This will be called after the last test function is executed. -// It is only called once. -void tst_Trie::cleanupTestCase() -{ -} - -// This will be called before each test function is executed. -void tst_Trie::init() -{ -} - -// This will be called after every test function. -void tst_Trie::cleanup() -{ -} - -void tst_Trie::trie_data() -{ -} - -void tst_Trie::trie() -{ - SubTrie t; - t.clear(); - QCOMPARE(t.find(QStringList()), QList()); - QCOMPARE(t.remove(QStringList(), -1), false); - QCOMPARE(t.all(), QList()); - t.insert(QStringList(), -1); -} - -void tst_Trie::insert_data() -{ -#if 0 - QTest::addColumn("key"); - QTest::addColumn("value"); - QTest::newRow("null") << QStringList() << T(); -#endif -} - -// public void insert(QStringList const& key, T value) -void tst_Trie::insert() -{ -#if 0 - QFETCH(QStringList, key); - QFETCH(T, value); - - SubTrie t>; - - t>.insert(key, value); -#endif - QSKIP("Test is not implemented.", SkipAll); -} - -// public void clear() -void tst_Trie::clear() -{ - SubTrie t; - t.insert(QStringList(), 0); - t.clear(); - QCOMPARE(t.find(QStringList()), QList()); - QCOMPARE(t.all(), QList()); -} - -Q_DECLARE_METATYPE(QStringList) -typedef QList IntList; -Q_DECLARE_METATYPE(IntList) -void tst_Trie::find_data() -{ - QTest::addColumn("keys"); - QTest::addColumn("values"); - QTest::addColumn("find"); - QTest::addColumn("found"); - - QTest::newRow("null") << QStringList() << IntList() << QStringList() << IntList(); - - QStringList wiki = (QStringList() << "t,e,a" << "i" << "t,e,n" << "i,n" << "i,n,n" << "t,o"); - IntList wikiNum = (IntList() << 3 << 11 << 12 << 5 << 9 << 7); - - QTest::newRow("wikipedia-0") - << wiki - << wikiNum - << (QStringList() << "t") - << (IntList()); - - QTest::newRow("wikipedia-1") - << wiki - << wikiNum - << (QStringList() << "t" << "o") - << (IntList() << 7); - - QTest::newRow("wikipedia-2") - << (wiki << "t,o") - << (wikiNum << 4) - << (QStringList() << "t" << "o") - << (IntList() << 7 << 4); - - QTest::newRow("wikipedia-3") - << wiki - << wikiNum - << (QStringList() << "i" << "n" << "n") - << (IntList() << 9); - -} - -// public QList const find(QStringList const& key) -void tst_Trie::find() -{ - QFETCH(QStringList, keys); - QFETCH(IntList, values); - QFETCH(QStringList, find); - QFETCH(IntList, found); - - SubTrie t; - for (int i = 0; i < keys.count(); ++i) - t.insert(keys[i].split(","), values[i]); - QCOMPARE(t.all(), values); - QCOMPARE(t.find(find), found); -} - -void tst_Trie::remove_data() -{ - QTest::addColumn("keys"); - QTest::addColumn("values"); - QTest::addColumn("removeKey"); - QTest::addColumn("removeValue"); - QTest::addColumn("removed"); - - QTest::newRow("null") << QStringList() << IntList() << QStringList() << -1 << false; - - QStringList wiki = (QStringList() << "t,e,a" << "i" << "t,e,n" << "i,n" << "i,n,n" << "t,o"); - IntList wikiNum = (IntList() << 3 << 11 << 12 << 5 << 9 << 7); - - QTest::newRow("valid key-0") - << wiki - << wikiNum - << (QStringList() << "t") - << -1 - << false; - - QTest::newRow("valid key-1") - << wiki - << wikiNum - << (QStringList() << "t" << "o") - << -1 - << false; - - QTest::newRow("valid key-2") - << wiki - << wikiNum - << (QStringList() << "t" << "o" << "w") - << 2 - << false; - - QTest::newRow("valid key-3") - << wiki - << wikiNum - << (QStringList() << "t" << "o") - << 7 - << true; - - QTest::newRow("valid key-4") - << wiki - << wikiNum - << (QStringList() << "i" << "n") - << 3 - << false; - - QTest::newRow("valid key-5") - << wiki - << wikiNum - << (QStringList() << "i" << "n") - << 5 - << true; - -} - -// public bool remove(QStringList const& key, T value) -void tst_Trie::remove() -{ - QFETCH(QStringList, keys); - QFETCH(IntList, values); - QFETCH(QStringList, removeKey); - QFETCH(int, removeValue); - QFETCH(bool, removed); - - SubTrie t; - for (int i = 0; i < keys.count(); ++i) - t.insert(keys[i].split(","), values[i]); - QCOMPARE(t.all(), values); - QCOMPARE(t.remove(removeKey, removeValue), removed); - if (removed) - values.removeOne(removeValue); - QCOMPARE(t.all(), values); -} - -void tst_Trie::all() -{ - SubTrie t; - // hmm everyone else tests this it seems - QSKIP("Test is not implemented.", SkipAll); -} - -QTEST_MAIN(tst_Trie) -#include "tst_trie.moc" - diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/benchmark/networkcookiejar/cookiejar.pro b/indra/llqtwebkit/qtwebkit_cookiejar/benchmark/networkcookiejar/cookiejar.pro deleted file mode 100644 index 350fbc0f6e..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/benchmark/networkcookiejar/cookiejar.pro +++ /dev/null @@ -1,17 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . - -win32: CONFIG += console -mac:CONFIG -= app_bundle - -CONFIG += qtestlib - -include(../../src/src.pri) -#include(../../../dev/code/webweaver/src/iris.pri) -#include(../../../dev/arora/src/src.pri) - -# Input -SOURCES += main.cpp -HEADERS += diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/benchmark/networkcookiejar/main.cpp b/indra/llqtwebkit/qtwebkit_cookiejar/benchmark/networkcookiejar/main.cpp deleted file mode 100644 index 863d6b0bec..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/benchmark/networkcookiejar/main.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include -#include -#include - -class CookieJarBenchmark: public QObject { - Q_OBJECT - -private slots: - void setCookiesFromUrl(); - void cookiesForUrl(); - void player(); - -private: - QNetworkCookieJar *getJar(bool populate = true); - QList generateCookies(int size); -}; - -QNetworkCookieJar *CookieJarBenchmark::getJar(bool populate) -{ - QNetworkCookieJar *jar; - if (qgetenv("JAR") == "CookieJar") { - jar = new NetworkCookieJar(this); - } else { - jar = new QNetworkCookieJar(this); - } - if (!populate) - return jar; - - // pre populate - for (int i = 0; i < 500; ++i) { - QList cookies = generateCookies(1); - QUrl url = QUrl(QString("http://%1").arg(cookies[0].domain())); - jar->setCookiesFromUrl(cookies, url); - } - - return jar; -} - -QList CookieJarBenchmark::generateCookies(int size) -{ - QList cookies; - for (int i = 0; i < size; ++i) { - QNetworkCookie cookie; - - QString tld; - int c = qrand() % 3; - if (c == 0) tld = "com"; - if (c == 1) tld = "net"; - if (c == 2) tld = "org"; - - QString mid; - int size = qrand() % 6 + 3; - while (mid.count() < size) - mid += QString(QChar::fromAscii(qrand() % 26 + 65)); - - QString sub; - c = qrand() % 3; - if (c == 0) sub = "."; - if (c == 1) sub = ".www."; - if (c == 2) sub = ".foo"; - - cookie.setDomain(QString("%1%2.%3").arg(sub).arg(mid).arg(tld)); - cookie.setName("a"); - cookie.setValue("b"); - cookie.setPath("/"); - cookies.append(cookie); - } - return cookies; -} - -void CookieJarBenchmark::setCookiesFromUrl() -{ - QNetworkCookieJar *jar = getJar(); - QList cookies = generateCookies(1); - QUrl url = QUrl(QString("http://%1").arg(cookies[0].domain())); - QBENCHMARK { - jar->setCookiesFromUrl(cookies, url); - } - delete jar; -} - -void CookieJarBenchmark::cookiesForUrl() -{ - QNetworkCookieJar *jar = getJar(); - QList cookies = generateCookies(1); - cookies[0].setDomain("www.foo.tld"); - QUrl url = QUrl("http://www.foo.tld"); - //QUrl url = QUrl(QString("http://foo%1/").arg(cookies[0].domain())); - jar->setCookiesFromUrl(cookies, url); - //qDebug() << cookies << url; - int c = 0; - QBENCHMARK { - c += jar->cookiesForUrl(url).count(); - } - delete jar; -} - -// Grab the cookie.log file from the manualtest/browser directory -void CookieJarBenchmark::player() -{ - QBENCHMARK { - QFile file("cookie.log"); - file.open(QFile::ReadOnly); - QDataStream stream(&file); - QNetworkCookieJar *jar = getJar(false); - while (!stream.atEnd()) { - QString command; - QUrl url; - stream >> command; - stream >> url; - //qDebug() << command << url; - if (command == "cookiesForUrl") { - jar->cookiesForUrl(url); - } - if (command == "setCookiesFromUrl") { - QByteArray data; - stream >> data; - QDataStream dstream(&data, QIODevice::ReadWrite); - qint32 c; - dstream >> c; - QList cookies; - for (int i = 0; i < c; ++i) { - QByteArray text; - dstream >> text; - cookies += QNetworkCookie::parseCookies(text); - } - jar->setCookiesFromUrl(cookies, url); - } - } - } -} - -QTEST_MAIN(CookieJarBenchmark) -#include "main.moc" diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/browser/browser.pro b/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/browser/browser.pro deleted file mode 100644 index a363bbefce..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/browser/browser.pro +++ /dev/null @@ -1,11 +0,0 @@ -###################################################################### -# Automatically generated by qmake (2.01a) Wed Jan 7 13:19:00 2009 -###################################################################### - -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . -include(../../src/src.pri) -# Input -SOURCES += main.cpp diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/browser/main.cpp b/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/browser/main.cpp deleted file mode 100644 index 6d21759fc4..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/browser/main.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include -#include -#include -#include - -QFile file; -QDataStream stream; - -class CookieLog : public NetworkCookieJar { - - Q_OBJECT - -public: - CookieLog(QObject *parent = 0) : NetworkCookieJar(parent) - { - file.setFileName("cookie.log"); - file.open(QFile::WriteOnly); - stream.setDevice(&file); - }; - - virtual QList cookiesForUrl(const QUrl & url) const - { - stream << QString("cookiesForUrl") << url; - QList cookies = NetworkCookieJar::cookiesForUrl(url); - //stream << "#" << cookies; - file.flush(); - return cookies; - } - - virtual bool setCookiesFromUrl(const QList &cookieList, const QUrl &url) - { - QByteArray data; - QDataStream dstream(&data, QIODevice::ReadWrite); - qint32 c = cookieList.count(); - dstream << c; - qDebug() << cookieList.count(); - for (int i = 0; i < c; ++i) - dstream << cookieList[i].toRawForm(); - dstream.device()->close(); - stream << QString("setCookiesFromUrl") << url << data;// << cookieList; - bool set = NetworkCookieJar::setCookiesFromUrl(cookieList, url); - file.flush(); - return set; - } - -}; - -int main(int argc, char**argv) { - QApplication application(argc, argv); - QWebView view; - QString url = "http://www.google.com"; - if (argc > 1) - url = argv[1]; - view.load(QUrl(url)); - view.page()->networkAccessManager()->setCookieJar(new CookieLog()); - view.show(); - return application.exec(); -} - -#include "main.moc" diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/fuzz/fuzz.pro b/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/fuzz/fuzz.pro deleted file mode 100644 index 0ad65f1bff..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/fuzz/fuzz.pro +++ /dev/null @@ -1,12 +0,0 @@ -###################################################################### -# Automatically generated by qmake (2.01a) Wed Jan 7 13:19:00 2009 -###################################################################### - -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . -include(../../src/src.pri) -DEFINES += QT_NO_CAST_FROM_ASCII QT_STRICT_ITERATOR -# Input -SOURCES += main.cpp diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/fuzz/main.cpp b/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/fuzz/main.cpp deleted file mode 100644 index 28c79a1c2b..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/manualtest/fuzz/main.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include -#include - -QStringList generateKey() { - QStringList key; - int size = qrand() % 20 + 3; - while (key.count() < size) - key += QString(QChar::fromAscii(qrand() % 26 + 64)); - return key; -} - -void basicCheck() { - QStringList list; - list << QLatin1String("to") << QLatin1String("tea") << QLatin1String("ten") << QLatin1String("i") << QLatin1String("in") << QLatin1String("inn"); - Trie trie; - for (int i = 0; i < list.count(); ++i) { - QString key = list[i]; - QStringList keyList; - for (int j = 0; j < key.count(); ++j) - keyList.append(QString(key[j])); - trie.insert(keyList, i); - } - QByteArray data; - { - QDataStream stream(&data, QIODevice::ReadWrite); - stream << trie; - } - Trie trie2; - { - QDataStream stream(&data, QIODevice::ReadOnly); - stream >> trie2; - } - for (int i = 0; i < list.count(); ++i) { - QString key = list[i]; - QStringList keyList; - for (int j = 0; j < key.count(); ++j) - keyList.append(QString(key[j])); - QList x = trie2.find(keyList); - qDebug() << x.count() << i << x[0] << i; - qDebug() << trie2.remove(keyList, i); - qDebug() << trie2.find(keyList).count(); - } -} - -int main(int argc, char **argv) { - Q_UNUSED(argc); - Q_UNUSED(argv); - - basicCheck(); - - QHash hash; - Trie t; - while (hash.count() < 500) { - qDebug() << hash.count(); - QStringList key = generateKey(); - int value = qrand() % 50000; - hash[key.join(QLatin1String(","))] = value; - t.insert(key, value); - - QHashIterator i(hash); - while (i.hasNext()) { - i.next(); - if (t.find(i.key().split(QLatin1Char(','))).count() == 0) - qDebug() << i.key(); - Q_ASSERT(t.find(i.key().split(QLatin1Char(','))).count() > 0); - if (qrand() % 500 == 0) { - t.remove(i.key().split(QLatin1Char(',')), i.value()); - hash.remove(i.key()); - } - //cout << i.key() << ": " << i.value() << endl; - } - } - return 0; -} - diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/src/CMakeLists.txt b/indra/llqtwebkit/qtwebkit_cookiejar/src/CMakeLists.txt deleted file mode 100644 index 20bacf3ebe..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/src/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# -*- cmake -*- - -project(networkcookiejar) - -set(networkcookiejar_SOURCE_FILES - networkcookiejar.cpp - ) - -set(networkcookiejar_HEADER_FILES - networkcookiejar.h - networkcookiejar_p.h - trie_p.h - twoleveldomains_p.h - - ) - -QT4_WRAP_CPP(networkcookiejar_HEADERS_MOC ${networkcookiejar_HEADER_FILES}) - -add_library(networkcookiejar - ${networkcookiejar_SOURCE_FILES} - ${networkcookiejar_HEADERS_MOC} - ${networkcookiejar_UI_MOC} -) - -add_dependencies(networkcookiejar prepare) - -target_link_libraries(networkcookiejar) \ No newline at end of file diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/src/networkcookiejar.cpp b/indra/llqtwebkit/qtwebkit_cookiejar/src/networkcookiejar.cpp deleted file mode 100644 index 274d9e1c1c..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/src/networkcookiejar.cpp +++ /dev/null @@ -1,444 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include "networkcookiejar.h" -#include "networkcookiejar_p.h" -#include "twoleveldomains_p.h" - -//#define NETWORKCOOKIEJAR_DEBUG - -#ifndef QT_NO_DEBUG -// ^ Prevent being left on in a released product by accident -// qDebug any cookies that are rejected for further inspection -#define NETWORKCOOKIEJAR_LOGREJECTEDCOOKIES -#include -#endif - -#include -#include - -#if defined(NETWORKCOOKIEJAR_DEBUG) -#include -#endif - - -NetworkCookieJar::NetworkCookieJar(QObject *parent) - : QNetworkCookieJar(parent) -{ - d = new NetworkCookieJarPrivate; -} - -NetworkCookieJar::~NetworkCookieJar() -{ - delete d; -} - -static QStringList splitHost(const QString &host) { - QStringList parts = host.split(QLatin1Char('.'), QString::KeepEmptyParts); - // Remove empty components that are on the start and end - while (!parts.isEmpty() && parts.last().isEmpty()) - parts.removeLast(); - while (!parts.isEmpty() && parts.first().isEmpty()) - parts.removeFirst(); - return parts; -} - -inline static bool shorterPaths(const QNetworkCookie &c1, const QNetworkCookie &c2) -{ - return c2.path().length() < c1.path().length(); -} - -QList NetworkCookieJar::cookiesForUrl(const QUrl &url) const -{ -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__ << url; -#endif - // Generate split host - QString host = url.host(); - if (url.scheme().toLower() == QLatin1String("file")) - host = QLatin1String("localhost"); - QStringList urlHost = splitHost(host); - - // Get all the cookies for url - QList cookies = d->tree.find(urlHost); - if (urlHost.count() > 2) { - int top = 2; - if (d->matchesBlacklist(urlHost.last())) - top = 3; - - urlHost.removeFirst(); - while (urlHost.count() >= top) { - cookies += d->tree.find(urlHost); - urlHost.removeFirst(); - } - } - - // Prevent doing anything expensive in the common case where - // there are no cookies to check - if (cookies.isEmpty()) - return cookies; - - QDateTime now = QDateTime::currentDateTime().toTimeSpec(Qt::UTC); - const QString urlPath = d->urlPath(url); - const bool isSecure = url.scheme().toLower() == QLatin1String("https"); - QList::iterator i = cookies.begin(); - for (; i != cookies.end();) { - if (!d->matchingPath(*i, urlPath)) { -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << __FUNCTION__ << "Ignoring cookie, path does not match" << *i << urlPath; -#endif - i = cookies.erase(i); - continue; - } - if (!isSecure && i->isSecure()) { - i = cookies.erase(i); -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << __FUNCTION__ << "Ignoring cookie, security mismatch" - << *i << !isSecure; -#endif - continue; - } - if (!i->isSessionCookie() && now > i->expirationDate()) { - // remove now (expensive short term) because there will - // probably be many more cookiesForUrl calls for this host - d->tree.remove(splitHost(i->domain()), *i); -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << __FUNCTION__ << "Ignoring cookie, expiration issue" - << *i << now; -#endif - i = cookies.erase(i); - continue; - } - ++i; - } - - // shorter paths should go first - qSort(cookies.begin(), cookies.end(), shorterPaths); -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__ << "returning" << cookies.count(); - qDebug() << cookies; -#endif - return cookies; -} - -static const qint32 NetworkCookieJarMagic = 0xae; - -QByteArray NetworkCookieJar::saveState () const -{ - int version = 1; - QByteArray data; - QDataStream stream(&data, QIODevice::WriteOnly); - - stream << qint32(NetworkCookieJarMagic); - stream << qint32(version); - stream << d->tree; - return data; -} - -bool NetworkCookieJar::restoreState(const QByteArray &state) -{ - int version = 1; - QByteArray sd = state; - QDataStream stream(&sd, QIODevice::ReadOnly); - if (stream.atEnd()) - return false; - qint32 marker; - qint32 v; - stream >> marker; - stream >> v; - if (marker != NetworkCookieJarMagic || v != version) - return false; - stream >> d->tree; - if (stream.status() != QDataStream::Ok) { - d->tree.clear(); - return false; - } - return true; -} - -/*! - Remove any session cookies or cookies that have expired. - */ -void NetworkCookieJar::endSession() -{ - const QList cookies = d->tree.all(); - QDateTime now = QDateTime::currentDateTime().toTimeSpec(Qt::UTC); - QList::const_iterator i = cookies.constBegin(); - for (; i != cookies.constEnd();) { - if (i->isSessionCookie() - || (!i->isSessionCookie() && now > i->expirationDate())) { - d->tree.remove(splitHost(i->domain()), *i); - } - ++i; - } -} - -static const int maxCookiePathLength = 1024; - -bool NetworkCookieJar::setCookiesFromUrl(const QList &cookieList, const QUrl &url) -{ -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__ << url; - qDebug() << cookieList; -#endif - QDateTime now = QDateTime::currentDateTime().toTimeSpec(Qt::UTC); - bool changed = false; - QString fullUrlPath = url.path(); - QString defaultPath = fullUrlPath.mid(0, fullUrlPath.lastIndexOf(QLatin1Char('/')) + 1); - if (defaultPath.isEmpty()) - defaultPath = QLatin1Char('/'); - - QString urlPath = d->urlPath(url); - foreach (QNetworkCookie cookie, cookieList) { - if (cookie.path().length() > maxCookiePathLength) - continue; - - bool alreadyDead = !cookie.isSessionCookie() && cookie.expirationDate() < now; - - if (cookie.path().isEmpty()) { - cookie.setPath(defaultPath); - } - // Matching the behavior of Firefox, no path checking is done when setting cookies - // Safari does something even odder, when that paths don't match it keeps - // the cookie, but changes the paths to the default path -#if 0 - else if (!d->matchingPath(cookie, urlPath)) { -#ifdef NETWORKCOOKIEJAR_LOGREJECTEDCOOKIES - qDebug() << "NetworkCookieJar::" << __FUNCTION__ - << "Blocked cookie because: path doesn't match: " << cookie << url; -#endif - continue; - } -#endif - - if (cookie.domain().isEmpty()) { - QString host = url.host().toLower(); - if (host.isEmpty()) - continue; - cookie.setDomain(host); - } else if (!d->matchingDomain(cookie, url)) { -#ifdef NETWORKCOOKIEJAR_LOGREJECTEDCOOKIES - qDebug() << "NetworkCookieJar::" << __FUNCTION__ - << "Blocked cookie because: domain doesn't match: " << cookie << url; -#endif - continue; - } - - // replace/remove existing cookies - removeCookie(cookie); - - // Notify derived class - onCookieSetFromURL(cookie, url, alreadyDead); - - if (alreadyDead) - continue; - - changed = true; - d->tree.insert(splitHost(cookie.domain()), cookie); - } - - return changed; -} - -QList NetworkCookieJar::allCookies() const -{ -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__; -#endif - return d->tree.all(); -} - -void NetworkCookieJar::clearCookies() -{ -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__; -#endif - d->tree.clear(); -} - -void NetworkCookieJar::setCookies(const QList &cookieList) -{ -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__ << cookieList.count(); -#endif - - QDateTime now = QDateTime::currentDateTime().toTimeSpec(Qt::UTC); - - foreach (const QNetworkCookie &cookie, cookieList) - { - // If a matching cookie is already in the list, remove it. - removeCookie(cookie); - - if(!cookie.isSessionCookie() && cookie.expirationDate() < now) - { -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__ << "removing cookie: " << cookie; -#endif - // This cookie has expired -- don't re-add it - } - else - { -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__ << "adding cookie: " << cookie; -#endif - // this cookie has not expired -- save it - d->tree.insert(splitHost(cookie.domain()), cookie); - } - - } -} - -void NetworkCookieJar::setAllCookies(const QList &cookieList) -{ -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__ << cookieList.count(); -#endif - clearCookies(); - setCookies(cookieList); -} - -void NetworkCookieJar::removeCookie(const QNetworkCookie &cookie) -{ -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__ << "removing cookie: " << cookie; -#endif - - // If a cookie with the matching domain, path, and name exists in the cookiejar, remove it. - QString domain = cookie.domain(); - Q_ASSERT(!domain.isEmpty()); - QStringList urlHost = splitHost(domain); - - QList cookies = d->tree.find(urlHost); - QList::const_iterator it = cookies.constBegin(); - for (; it != cookies.constEnd(); ++it) - { - if (cookie.name() == it->name() && - domain == it->domain() && - cookie.path() == it->path()) - { -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__ << "found matching cookie: " << *it; -#endif - d->tree.remove(urlHost, *it); - break; - } - } -} - -void NetworkCookieJar::dump() -{ -#if defined(NETWORKCOOKIEJAR_DEBUG) - qDebug() << "NetworkCookieJar::" << __FUNCTION__ << "dumping all cookies: "; - QList cookies = allCookies(); - foreach (const QNetworkCookie &cookie, cookies) - { - qDebug() << " " << cookie; - } -#endif -} - -QString NetworkCookieJarPrivate::urlPath(const QUrl &url) const -{ - QString urlPath = url.path(); - if (!urlPath.endsWith(QLatin1Char('/'))) - urlPath += QLatin1Char('/'); - return urlPath; -} - -bool NetworkCookieJarPrivate::matchingPath(const QNetworkCookie &cookie, const QString &urlPath) const -{ - QString cookiePath = cookie.path(); - if (!cookiePath.endsWith(QLatin1Char('/'))) - cookiePath += QLatin1Char('/'); - - return urlPath.startsWith(cookiePath); -} - -bool NetworkCookieJarPrivate::matchesBlacklist(const QString &string) const -{ - if (!setSecondLevelDomain) { - // Alternatively to save a little bit of ram we could just - // use bsearch on twoLevelDomains in place - for (int j = 0; twoLevelDomains[j]; ++j) - secondLevelDomains += QLatin1String(twoLevelDomains[j]); - setSecondLevelDomain = true; - } - QStringList::const_iterator i = - qBinaryFind(secondLevelDomains.constBegin(), secondLevelDomains.constEnd(), string); - return (i != secondLevelDomains.constEnd()); -} - -bool NetworkCookieJarPrivate::matchingDomain(const QNetworkCookie &cookie, const QUrl &url) const -{ - QString domain = cookie.domain().simplified().toLower(); - domain.remove(QLatin1Char(' ')); - QStringList parts = splitHost(domain); - if (parts.isEmpty()) - return false; - - // When there is only one part only file://localhost/ is accepted - if (parts.count() == 1) { - QString s = parts.first(); - if (parts.first() != QLatin1String("localhost")) - return false; - if (url.scheme().toLower() == QLatin1String("file")) - return true; - } - - // Check for blacklist - if (parts.count() == 2 && matchesBlacklist(parts.last())) - return false; - - QStringList urlParts = url.host().toLower().split(QLatin1Char('.'), QString::SkipEmptyParts); - if (urlParts.isEmpty()) - return false; - while (urlParts.count() > parts.count()) - urlParts.removeFirst(); - - for (int j = 0; j < urlParts.count(); ++j) { - if (urlParts.at(j) != parts.at(j)) { - return false; - } - } - - return true; -} - -void NetworkCookieJar::setSecondLevelDomains(const QStringList &secondLevelDomains) -{ - d->setSecondLevelDomain = true; - d->secondLevelDomains = secondLevelDomains; - qSort(d->secondLevelDomains); -} - - -void NetworkCookieJar::onCookieSetFromURL(const QNetworkCookie &cookie, const QUrl &url, bool already_dead) -{ - Q_UNUSED(cookie); - Q_UNUSED(url); - Q_UNUSED(already_dead); - - // Derived classes can use this to track cookie changes. -} diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/src/networkcookiejar.h b/indra/llqtwebkit/qtwebkit_cookiejar/src/networkcookiejar.h deleted file mode 100644 index 86b14fa16e..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/src/networkcookiejar.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef NETWORKCOOKIEJAR_H -#define NETWORKCOOKIEJAR_H - -#include - -class NetworkCookieJarPrivate; -class NetworkCookieJar : public QNetworkCookieJar { - Q_OBJECT -public: - NetworkCookieJar(QObject *parent = 0); - ~NetworkCookieJar(); - - virtual QList cookiesForUrl(const QUrl & url) const; - virtual bool setCookiesFromUrl(const QList &cookieList, const QUrl &url); - -protected: - QByteArray saveState() const; - bool restoreState(const QByteArray &state); - void endSession(); - - QList allCookies() const; - void clearCookies(); - void setCookies(const QList &cookieList); - void setAllCookies(const QList &cookieList); - void removeCookie(const QNetworkCookie &cookie); - void dump(); - void setSecondLevelDomains(const QStringList &secondLevelDomains); - - virtual void onCookieSetFromURL(const QNetworkCookie &cookie, const QUrl &url, bool already_dead); - -private: - NetworkCookieJarPrivate *d; -}; - -#endif - diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/src/networkcookiejar_p.h b/indra/llqtwebkit/qtwebkit_cookiejar/src/networkcookiejar_p.h deleted file mode 100644 index d8f22cfce0..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/src/networkcookiejar_p.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef NETWORKCOOKIEJARPRIVATE_H -#define NETWORKCOOKIEJARPRIVATE_H - -#include "trie_p.h" - -QT_BEGIN_NAMESPACE -QDataStream &operator<<(QDataStream &stream, const QNetworkCookie &cookie) -{ - stream << cookie.toRawForm(); - return stream; -} - -QDataStream &operator>>(QDataStream &stream, QNetworkCookie &cookie) -{ - QByteArray value; - stream >> value; - QList newCookies = QNetworkCookie::parseCookies(value); - if (!newCookies.isEmpty()) - cookie = newCookies.first(); - return stream; -} -QT_END_NAMESPACE - -class NetworkCookieJarPrivate { -public: - NetworkCookieJarPrivate() - : setSecondLevelDomain(false) - {} - - Trie tree; - mutable bool setSecondLevelDomain; - mutable QStringList secondLevelDomains; - - bool matchesBlacklist(const QString &string) const; - bool matchingDomain(const QNetworkCookie &cookie, const QUrl &url) const; - QString urlPath(const QUrl &url) const; - bool matchingPath(const QNetworkCookie &cookie, const QString &urlPath) const; -}; - -#endif - diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/src/src.pri b/indra/llqtwebkit/qtwebkit_cookiejar/src/src.pri deleted file mode 100644 index 78ac273a15..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/src/src.pri +++ /dev/null @@ -1,5 +0,0 @@ -INCLUDEPATH += $$PWD -DEPENDPATH += $$PWD - -HEADERS += trie_p.h networkcookiejar.h twoleveldomains_p.h networkcookiejar_p.h -SOURCES += networkcookiejar.cpp diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/src/trie_p.h b/indra/llqtwebkit/qtwebkit_cookiejar/src/trie_p.h deleted file mode 100644 index a4959a198c..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/src/trie_p.h +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef TRIE_H -#define TRIE_H - -//#define TRIE_DEBUG - -#include - -#if defined(TRIE_DEBUG) -#include -#endif - -/* - A Trie tree (prefix tree) where the lookup takes m in the worst case. - - The key is stored in *reverse* order - - Example: - Keys: x,a y,a - - Trie: - a - | \ - x y -*/ - -template -class Trie { -public: - Trie(); - ~Trie(); - - void clear(); - void insert(const QStringList &key, const T &value); - bool remove(const QStringList &key, const T &value); - QList find(const QStringList &key) const; - QList all() const; - - inline bool contains(const QStringList &key) const; - inline bool isEmpty() const { return children.isEmpty() && values.isEmpty(); } - -private: - const Trie* walkTo(const QStringList &key) const; - Trie* walkTo(const QStringList &key, bool create = false); - - template friend QDataStream &operator<<(QDataStream &, const Trie&); - template friend QDataStream &operator>>(QDataStream &, Trie&); - - QList values; - QStringList childrenKeys; - QList > children; -}; - -template -Trie::Trie() { -} - -template -Trie::~Trie() { -} - -template -void Trie::clear() { -#if defined(TRIE_DEBUG) - qDebug() << "Trie::" << __FUNCTION__; -#endif - values.clear(); - childrenKeys.clear(); - children.clear(); -} - -template -bool Trie::contains(const QStringList &key) const { - return walkTo(key); -} - -template -void Trie::insert(const QStringList &key, const T &value) { -#if defined(TRIE_DEBUG) - qDebug() << "Trie::" << __FUNCTION__ << key << value; -#endif - Trie *node = walkTo(key, true); - if (node) - node->values.append(value); -} - -template -bool Trie::remove(const QStringList &key, const T &value) { -#if defined(TRIE_DEBUG) - qDebug() << "Trie::" << __FUNCTION__ << key << value; -#endif - Trie *node = walkTo(key, true); - if (node) { - bool removed = node->values.removeOne(value); - if (!removed) - return false; - - // A faster implementation of removing nodes up the tree - // can be created if profile shows this to be slow - QStringList subKey = key; - while (node->values.isEmpty() - && node->children.isEmpty() - && !subKey.isEmpty()) { - QString currentLevelKey = subKey.first(); - QStringList parentKey = subKey.mid(1); - Trie *parent = walkTo(parentKey, false); - Q_ASSERT(parent); - QStringList::iterator iterator; - iterator = qBinaryFind(parent->childrenKeys.begin(), - parent->childrenKeys.end(), - currentLevelKey); - Q_ASSERT(iterator != parent->childrenKeys.end()); - int index = iterator - parent->childrenKeys.begin(); - parent->children.removeAt(index); - parent->childrenKeys.removeAt(index); - - node = parent; - subKey = parentKey; - } - return removed; - } - return false; -} - -template -QList Trie::find(const QStringList &key) const { -#if defined(TRIE_DEBUG) - qDebug() << "Trie::" << __FUNCTION__ << key; -#endif - const Trie *node = walkTo(key); - if (node) - return node->values; - return QList(); -} - -template -QList Trie::all() const { -#if defined(TRIE_DEBUG) - qDebug() << "Trie::" << __FUNCTION__; -#endif - QList all = values; - for (int i = 0; i < children.count(); ++i) - all += children[i].all(); - return all; -} - -template -QDataStream &operator<<(QDataStream &out, const Trie&trie) { - out << trie.values; - out << trie.childrenKeys; - out << trie.children; - Q_ASSERT(trie.childrenKeys.count() == trie.children.count()); - return out; -} - -template -QDataStream &operator>>(QDataStream &in, Trie &trie) { - trie.clear(); - if (in.status() != QDataStream::Ok) - return in; - in >> trie.values; - in >> trie.childrenKeys; - in >> trie.children; - //Q_ASSERT(trie.childrenKeys.count() == trie.children.count()); - if (trie.childrenKeys.count() != trie.children.count()) - in.setStatus(QDataStream::ReadCorruptData); - return in; -} - -// Very fast const walk -template -const Trie* Trie::walkTo(const QStringList &key) const { - const Trie *node = this; - QStringList::const_iterator childIterator; - QStringList::const_iterator begin, end; - - int depth = key.count() - 1; - while (depth >= 0) { - const QString currentLevelKey = key.at(depth--); - begin = node->childrenKeys.constBegin(); - end = node->childrenKeys.constEnd(); - childIterator = qBinaryFind(begin, end, currentLevelKey); - if (childIterator == end) - return 0; - node = &node->children.at(childIterator - begin); - } - return node; -} - -template -Trie* Trie::walkTo(const QStringList &key, bool create) { - QStringList::iterator iterator; - Trie *node = this; - QStringList::iterator begin, end; - int depth = key.count() - 1; - while (depth >= 0) { - const QString currentLevelKey = key.at(depth--); - begin = node->childrenKeys.begin(); - end = node->childrenKeys.end(); - iterator = qBinaryFind(begin, end, currentLevelKey); -#if defined(TRIE_DEBUG) - qDebug() << "\t" << node << key << currentLevelKey << node->childrenKeys; -#endif - int index = -1; - if (iterator == end) { - if (!create) - return 0; - iterator = qLowerBound(begin, - end, - currentLevelKey); - index = iterator - begin; - node->childrenKeys.insert(iterator, currentLevelKey); - node->children.insert(index, Trie()); - } else { - index = iterator - begin; - } - Q_ASSERT(index >= 0 && index < node->children.count()); - node = &node->children[index]; - } - return node; -} - -#endif diff --git a/indra/llqtwebkit/qtwebkit_cookiejar/src/twoleveldomains_p.h b/indra/llqtwebkit/qtwebkit_cookiejar/src/twoleveldomains_p.h deleted file mode 100644 index e4c046cb68..0000000000 --- a/indra/llqtwebkit/qtwebkit_cookiejar/src/twoleveldomains_p.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -// Updated from https://wiki.mozilla.org/TLD_List#External_Links -// To set a custom list use NetworkCookieJar::setSecondLevelDomains() -static const char *const twoLevelDomains[] = { - "ao", - "ar", - "arpa", - "bd", - "bn", - "br", - "co", - "cr", - "cy", - "do", - "eg", - "et", - "fj", - "fk", - "gh", - "gn", - "gu", - "id", - "il", - "jm", - "ke", - "kh", - "ki", - "kw", - "kz", - "lb", - "lc", - "lr", - "ls", - "ml", - "mm", - "mv", - "mw", - "mx", - "my", - "ng", - "ni", - "np", - "nz", - "om", - "pa", - "pe", - "pg", - "pw", - "py", - "qa", - "sa", - "sb", - "sv", - "sy", - "th", - "tn", - "tz", - "uk", - "uy", - "va", - "ve", - "ye", - "yu", - "za", - "zm", - "zw", - 0 -}; diff --git a/indra/llqtwebkit/static.pri b/indra/llqtwebkit/static.pri deleted file mode 100644 index 8c282347d1..0000000000 --- a/indra/llqtwebkit/static.pri +++ /dev/null @@ -1,18 +0,0 @@ -# Detect if Qt is static or shared -CONFIG(debug, debug|release) { - win32:PRL = $$[QT_INSTALL_LIBS] QtGui.prl -} else { - win32:PRL = $$[QT_INSTALL_LIBS] QtGuid.prl -} - -unix:!mac: PRL = $$[QT_INSTALL_LIBS] libQtGui.prl -mac: PRL = $$[QT_INSTALL_LIBS] QtGui.framework/QtGui.prl -include($$join(PRL, "/")) - -contains(QMAKE_PRL_CONFIG, static) { - DEFINES += STATIC_QT - QTPLUGIN += qgif -} else { - DEFINES += SHARED_QT -} - diff --git a/indra/llqtwebkit/tests/3dgl/3dgl.cpp b/indra/llqtwebkit/tests/3dgl/3dgl.cpp deleted file mode 100644 index c07c5d89c8..0000000000 --- a/indra/llqtwebkit/tests/3dgl/3dgl.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ -#define FREEGLUT_STATIC - -#include "zpr.h" -#include "llqtwebkit.h" - -#include -#include -#include -#include - -bool gDebugMode = false; -int gBrowserWindowId=-1; -GLuint gBrowserTexture=-1; -GLuint gCheckerTexture=-1; - -// manually make part of the browser texture transparent - for testing - LLQtWebKit will handle this eventually -void alphaize_browser_texture(unsigned char* texture_pixels) -{ - const int texture_depth=4; - - int texture_width = LLQtWebKit::getInstance()->getBrowserWidth(gBrowserWindowId); - int texture_height = LLQtWebKit::getInstance()->getBrowserHeight(gBrowserWindowId); - - const int num_squares=16; - int sqr1_alpha=0xff; - int sqr2_alpha=0x00; - - for(int y1=0;y1pump(200); - LLQtWebKit::getInstance()->grabBrowserWindow( gBrowserWindowId ); - glutPostRedisplay(); - }; -} - -void display(void) -{ - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - - glPushMatrix(); - - glBindTexture(GL_TEXTURE_2D, gCheckerTexture); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - glBegin(GL_QUADS); - glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.8f, -0.8f, -0.8f); - glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.8f, 0.8f, -0.8f); - glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.8f, 0.8f, -0.8f); - glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.8f, -0.8f, -0.8f); - glEnd(); - - glBindTexture(GL_TEXTURE_2D, gBrowserTexture); - if(!gDebugMode) - { - const unsigned char* browser_pixels=LLQtWebKit::getInstance()->getBrowserWindowPixels(gBrowserWindowId); - if(browser_pixels) - { - int texture_width = LLQtWebKit::getInstance()->getBrowserWidth(gBrowserWindowId); - int texture_height = LLQtWebKit::getInstance()->getBrowserHeight(gBrowserWindowId); - int texture_depth = 4; - - unsigned char* texture_pixels = new unsigned char[texture_width*texture_height*texture_depth]; - memcpy(texture_pixels, browser_pixels, texture_width*texture_height*texture_depth); - alphaize_browser_texture(texture_pixels); - - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, 0, - texture_width, texture_height, - GL_RGBA, - GL_UNSIGNED_BYTE, - texture_pixels); - - delete [] texture_pixels; - }; - }; - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.8f, -0.8f, 0.8f); - glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.8f, -0.8f, 0.8f); - glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.8f, 0.8f, 0.8f); - glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.8f, 0.8f, 0.8f); - glEnd(); - - glPopMatrix(); - - glutSwapBuffers(); -} - -GLuint make_rgba_texture(int texture_width, int texture_height) -{ - const int texture_depth=4; - - unsigned char* texture_pixels = new unsigned char[texture_width*texture_height*texture_depth]; - - const int num_squares=rand()%10+10; - int sqr1_r=rand()%0xa0+0x20; - int sqr1_g=rand()%0xa0+0x20; - int sqr1_b=rand()%0xa0+0x20; - int sqr1_alpha=0xff; - - int sqr2_r=rand()%0xa0+0x20; - int sqr2_g=rand()%0xa0+0x20; - int sqr2_b=rand()%0xa0+0x20; - int sqr2_alpha=0x00; - - for(int y1=0;y1init(std::string(), app_dir, profile_dir, GetDesktopWindow()); - - LLQtWebKit::getInstance()->enableJavaScript(true); - LLQtWebKit::getInstance()->enableCookies(true); - LLQtWebKit::getInstance()->enablePlugins(true); - - const std::string start_url("http://news.google.com"); - //const std::string start_url("http://www.youtube.com/watch?v=4Z3r9X8OahA&feature=rbl_entertainment"); - gBrowserWindowId=LLQtWebKit::getInstance()->createBrowserWindow(browser_width, browser_height); - LLQtWebKit::getInstance()->setSize(gBrowserWindowId, browser_width, browser_height); - LLQtWebKit::getInstance()->flipWindow(gBrowserWindowId, true); - LLQtWebKit::getInstance()->navigateTo(gBrowserWindowId, start_url); - } - - gCheckerTexture = make_rgba_texture( browser_width, browser_height); - - glutMainLoop(); - - return 0; -} diff --git a/indra/llqtwebkit/tests/3dgl/3dgl.pro b/indra/llqtwebkit/tests/3dgl/3dgl.pro deleted file mode 100644 index 6285128ef7..0000000000 --- a/indra/llqtwebkit/tests/3dgl/3dgl.pro +++ /dev/null @@ -1,38 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . -INCLUDEPATH += ../../ -CONFIG -= app_bundle - -QT += webkit opengl network - -!mac { -unix { - DEFINES += LL_LINUX - LIBS += -lglui -lglut - LIBS += $$PWD/../../libllqtwebkit.a -} -} - -mac { - DEFINES += LL_OSX - LIBS += -framework GLUT -framework OpenGL - LIBS += $$PWD/libllqtwebkit.dylib -} - -win32 { - DEFINES += _WINDOWS - INCLUDEPATH += ../ - INCLUDEPATH += $$PWD/../../stage/packages/include - DESTDIR=../build - release { - LIBS += $$PWD/../../Release/llqtwebkit.lib - LIBS += $$PWD/../build/freeglut_static.lib - LIBS += comdlg32.lib - } -} - -include(../../static.pri) - -SOURCES += 3dgl.cpp zpr.c diff --git a/indra/llqtwebkit/tests/3dgl/zpr.c b/indra/llqtwebkit/tests/3dgl/zpr.c deleted file mode 100644 index 65373efc56..0000000000 --- a/indra/llqtwebkit/tests/3dgl/zpr.c +++ /dev/null @@ -1,429 +0,0 @@ -#include -#include -#include -#include - -#include "zpr.h" - -/* This code was originally C++ :-) */ - -#define bool int -#define true 1 -#define false 0 - -static double _left = 0.0; -static double _right = 0.0; -static double _bottom = 0.0; -static double _top = 0.0; -static double _zNear = -10.0; -static double _zFar = 10.0; - -static int _mouseX = 0; -static int _mouseY = 0; -static bool _mouseLeft = false; -static bool _mouseMiddle = false; -static bool _mouseRight = false; - -static double _dragPosX = 0.0; -static double _dragPosY = 0.0; -static double _dragPosZ = 0.0; - -static double _matrix[16]; -static double _matrixInverse[16]; - -static double vlen(double x,double y,double z); -static void pos(double *px,double *py,double *pz,const int x,const int y,const int *viewport); -static void getMatrix(); -static void invertMatrix(const GLdouble *m, GLdouble *out ); - -static void zprReshape(int w,int h); -static void zprMouse(int button, int state, int x, int y); -static void zprMotion(int x, int y); - -static void zprPick(GLdouble x, GLdouble y,GLdouble delX, GLdouble delY); - -/* Configurable center point for zooming and rotation */ - -GLfloat zprReferencePoint[4] = { 0,0,0,0 }; - -void -zprInit() -{ - getMatrix(); - - glutReshapeFunc(zprReshape); - glutMouseFunc(zprMouse); - glutMotionFunc(zprMotion); -} - -static void -zprReshape(int w,int h) -{ - glViewport(0,0,w,h); - - _top = 1.0; - _bottom = -1.0; - _left = -(double)w/(double)h; - _right = -_left; - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(_left,_right,_bottom,_top,_zNear,_zFar); - - glMatrixMode(GL_MODELVIEW); -} - -static void -zprMouse(int button, int state, int x, int y) -{ - GLint viewport[4]; - - /* Do picking */ - if (state==GLUT_DOWN) - zprPick(x,glutGet(GLUT_WINDOW_HEIGHT)-1-y,3,3); - - _mouseX = x; - _mouseY = y; - - if (state==GLUT_UP) - switch (button) - { - case GLUT_LEFT_BUTTON: _mouseLeft = false; break; - case GLUT_MIDDLE_BUTTON: _mouseMiddle = false; break; - case GLUT_RIGHT_BUTTON: _mouseRight = false; break; - } - else - switch (button) - { - case GLUT_LEFT_BUTTON: _mouseLeft = true; break; - case GLUT_MIDDLE_BUTTON: _mouseMiddle = true; break; - case GLUT_RIGHT_BUTTON: _mouseRight = true; break; - } - - glGetIntegerv(GL_VIEWPORT,viewport); - pos(&_dragPosX,&_dragPosY,&_dragPosZ,x,y,viewport); - glutPostRedisplay(); -} - -static void -zprMotion(int x, int y) -{ - bool changed = false; - - const int dx = x - _mouseX; - const int dy = y - _mouseY; - - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT,viewport); - - if (dx==0 && dy==0) - return; - - if (_mouseMiddle || (_mouseLeft && _mouseRight)) - { - double s = exp((double)dy*0.01); - - glTranslatef( zprReferencePoint[0], zprReferencePoint[1], zprReferencePoint[2]); - glScalef(s,s,s); - glTranslatef(-zprReferencePoint[0],-zprReferencePoint[1],-zprReferencePoint[2]); - - changed = true; - } - else - if (_mouseLeft) - { - double ax,ay,az; - double bx,by,bz; - double angle; - - ax = dy; - ay = dx; - az = 0.0; - angle = vlen(ax,ay,az)/(double)(viewport[2]+1)*180.0; - - /* Use inverse matrix to determine local axis of rotation */ - - bx = _matrixInverse[0]*ax + _matrixInverse[4]*ay + _matrixInverse[8] *az; - by = _matrixInverse[1]*ax + _matrixInverse[5]*ay + _matrixInverse[9] *az; - bz = _matrixInverse[2]*ax + _matrixInverse[6]*ay + _matrixInverse[10]*az; - - glTranslatef( zprReferencePoint[0], zprReferencePoint[1], zprReferencePoint[2]); - glRotatef(angle,bx,by,bz); - glTranslatef(-zprReferencePoint[0],-zprReferencePoint[1],-zprReferencePoint[2]); - - changed = true; - } - else - if (_mouseRight) - { - double px,py,pz; - - pos(&px,&py,&pz,x,y,viewport); - - glLoadIdentity(); - glTranslatef(px-_dragPosX,py-_dragPosY,pz-_dragPosZ); - glMultMatrixd(_matrix); - - _dragPosX = px; - _dragPosY = py; - _dragPosZ = pz; - - changed = true; - } - - _mouseX = x; - _mouseY = y; - - if (changed) - { - getMatrix(); - glutPostRedisplay(); - } -} - -/***************************************************************** - * Utility functions - *****************************************************************/ - -static double -vlen(double x,double y,double z) -{ - return sqrt(x*x+y*y+z*z); -} - -static void -pos(double *px,double *py,double *pz,const int x,const int y,const int *viewport) -{ - /* - Use the ortho projection and viewport information - to map from mouse co-ordinates back into world - co-ordinates - */ - - *px = (double)(x-viewport[0])/(double)(viewport[2]); - *py = (double)(y-viewport[1])/(double)(viewport[3]); - - *px = _left + (*px)*(_right-_left); - *py = _top + (*py)*(_bottom-_top); - *pz = _zNear; -} - -static void -getMatrix() -{ - glGetDoublev(GL_MODELVIEW_MATRIX,_matrix); - invertMatrix(_matrix,_matrixInverse); -} - -/* - * From Mesa-2.2\src\glu\project.c - * - * Compute the inverse of a 4x4 matrix. Contributed by scotter@lafn.org - */ - -static void -invertMatrix(const GLdouble *m, GLdouble *out ) -{ - -/* NB. OpenGL Matrices are COLUMN major. */ -#define MAT(m,r,c) (m)[(c)*4+(r)] - -/* Here's some shorthand converting standard (row,column) to index. */ -#define m11 MAT(m,0,0) -#define m12 MAT(m,0,1) -#define m13 MAT(m,0,2) -#define m14 MAT(m,0,3) -#define m21 MAT(m,1,0) -#define m22 MAT(m,1,1) -#define m23 MAT(m,1,2) -#define m24 MAT(m,1,3) -#define m31 MAT(m,2,0) -#define m32 MAT(m,2,1) -#define m33 MAT(m,2,2) -#define m34 MAT(m,2,3) -#define m41 MAT(m,3,0) -#define m42 MAT(m,3,1) -#define m43 MAT(m,3,2) -#define m44 MAT(m,3,3) - - GLdouble det; - GLdouble d12, d13, d23, d24, d34, d41; - GLdouble tmp[16]; /* Allow out == in. */ - - /* Inverse = adjoint / det. (See linear algebra texts.)*/ - - /* pre-compute 2x2 dets for last two rows when computing */ - /* cofactors of first two rows. */ - d12 = (m31*m42-m41*m32); - d13 = (m31*m43-m41*m33); - d23 = (m32*m43-m42*m33); - d24 = (m32*m44-m42*m34); - d34 = (m33*m44-m43*m34); - d41 = (m34*m41-m44*m31); - - tmp[0] = (m22 * d34 - m23 * d24 + m24 * d23); - tmp[1] = -(m21 * d34 + m23 * d41 + m24 * d13); - tmp[2] = (m21 * d24 + m22 * d41 + m24 * d12); - tmp[3] = -(m21 * d23 - m22 * d13 + m23 * d12); - - /* Compute determinant as early as possible using these cofactors. */ - det = m11 * tmp[0] + m12 * tmp[1] + m13 * tmp[2] + m14 * tmp[3]; - - /* Run singularity test. */ - if (det == 0.0) { - /* printf("invert_matrix: Warning: Singular matrix.\n"); */ -/* memcpy(out,_identity,16*sizeof(double)); */ - } - else { - GLdouble invDet = 1.0 / det; - /* Compute rest of inverse. */ - tmp[0] *= invDet; - tmp[1] *= invDet; - tmp[2] *= invDet; - tmp[3] *= invDet; - - tmp[4] = -(m12 * d34 - m13 * d24 + m14 * d23) * invDet; - tmp[5] = (m11 * d34 + m13 * d41 + m14 * d13) * invDet; - tmp[6] = -(m11 * d24 + m12 * d41 + m14 * d12) * invDet; - tmp[7] = (m11 * d23 - m12 * d13 + m13 * d12) * invDet; - - /* Pre-compute 2x2 dets for first two rows when computing */ - /* cofactors of last two rows. */ - d12 = m11*m22-m21*m12; - d13 = m11*m23-m21*m13; - d23 = m12*m23-m22*m13; - d24 = m12*m24-m22*m14; - d34 = m13*m24-m23*m14; - d41 = m14*m21-m24*m11; - - tmp[8] = (m42 * d34 - m43 * d24 + m44 * d23) * invDet; - tmp[9] = -(m41 * d34 + m43 * d41 + m44 * d13) * invDet; - tmp[10] = (m41 * d24 + m42 * d41 + m44 * d12) * invDet; - tmp[11] = -(m41 * d23 - m42 * d13 + m43 * d12) * invDet; - tmp[12] = -(m32 * d34 - m33 * d24 + m34 * d23) * invDet; - tmp[13] = (m31 * d34 + m33 * d41 + m34 * d13) * invDet; - tmp[14] = -(m31 * d24 + m32 * d41 + m34 * d12) * invDet; - tmp[15] = (m31 * d23 - m32 * d13 + m33 * d12) * invDet; - - memcpy(out, tmp, 16*sizeof(GLdouble)); - } - -#undef m11 -#undef m12 -#undef m13 -#undef m14 -#undef m21 -#undef m22 -#undef m23 -#undef m24 -#undef m31 -#undef m32 -#undef m33 -#undef m34 -#undef m41 -#undef m42 -#undef m43 -#undef m44 -#undef MAT -} - -/***************************************** Picking ****************************************************/ - -static void (*selection)(void) = NULL; -static void (*pick)(GLint name) = NULL; - -void zprSelectionFunc(void (*f)(void)) -{ - selection = f; -} - -void zprPickFunc(void (*f)(GLint name)) -{ - pick = f; -} - -/* Draw in selection mode */ - -static void -zprPick(GLdouble x, GLdouble y,GLdouble delX, GLdouble delY) -{ - GLuint buffer[1024]; - const int bufferSize = sizeof(buffer)/sizeof(GLuint); - - GLint viewport[4]; - GLdouble projection[16]; - - GLint hits; - GLint i,j,k; - - GLint min = -1; - GLuint minZ = -1; - - glSelectBuffer(bufferSize,buffer); /* Selection buffer for hit records */ - glRenderMode(GL_SELECT); /* OpenGL selection mode */ - glInitNames(); /* Clear OpenGL name stack */ - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); /* Push current projection matrix */ - glGetIntegerv(GL_VIEWPORT,viewport); /* Get the current viewport size */ - glGetDoublev(GL_PROJECTION_MATRIX,projection); /* Get the projection matrix */ - glLoadIdentity(); /* Reset the projection matrix */ - gluPickMatrix(x,y,delX,delY,viewport); /* Set the picking matrix */ - glMultMatrixd(projection); /* Apply projection matrix */ - - glMatrixMode(GL_MODELVIEW); - - if (selection) - selection(); /* Draw the scene in selection mode */ - - hits = glRenderMode(GL_RENDER); /* Return to normal rendering mode */ - - /* Diagnostic output to stdout */ - - #ifndef NDEBUG - if (hits!=0) - { - printf("hits = %d\n",hits); - - for (i=0,j=0; i rotate - * Middle button -> zoom - * Right button -> pan - * - * Picking is also provided via two configurable callbacks: - * - * void zprSelectionFunc(void (*f)(void)) - * - * The draw function to be called in OpenGL selection - * mode in response to a mouse-down button event. - * - * void zprPickFunc(void (*f)(GLint name)) - * - * The callback function which will receive the - * top-most item of the name stack of the closest selection - * hit. If there is no selection hit, -1 - * - * Limitations - * ----------- - * - * Works best with zprReferencePoint appropriately configured. - * Works best with ortho projection. - * You may need to use glEnable(GL_NORMALIZATION) for correct lighting. - * Near and far clip planes are hard-coded. - * Zooming and rotation is centered on the origin. - * Only one window can use the callbacks at one time. - * - */ - -#ifdef WIN32 -#include -#endif - -#define FREEGLUT_STATIC - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* - * - */ - -/* Mouse Manipulation API */ - -void zprInit(); - -extern GLfloat zprReferencePoint[4]; - -/* Picking API (Optional) */ - -extern void zprSelectionFunc(void (*f)(void)); /* Selection-mode draw function */ -extern void zprPickFunc(void (*f)(GLint name)); /* Pick event handling function */ - -/* - * - */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/indra/llqtwebkit/tests/qttestapp/main.cpp b/indra/llqtwebkit/tests/qttestapp/main.cpp deleted file mode 100644 index 3ab3a9c179..0000000000 --- a/indra/llqtwebkit/tests/qttestapp/main.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include -#include - -class WebPage : public QWidget, LLEmbeddedBrowserWindowObserver -{ - Q_OBJECT - -signals: - void locationChanged(const QString &); - void canGoBack(bool); - void canGoForward(bool); - -public: - WebPage(QWidget *parent = 0); - ~WebPage(); - - void onCursorChanged(const EventType& event); - void onPageChanged(const EventType& event); - void onNavigateBegin(const EventType& event); - void onNavigateComplete(const EventType& event); - void onUpdateProgress(const EventType& event); - void onStatusTextChange(const EventType& event); - void onLocationChange(const EventType& event); - void onClickLinkHref(const EventType& event); - void onClickLinkNoFollow(const EventType& event); - -public slots: - void goBack(); - void goForward(); - void reload(); - void loadUrl(const QString &); - -protected: - void resizeEvent(QResizeEvent *event); - void paintEvent(QPaintEvent *event); - void mouseDoubleClickEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void keyPressEvent(QKeyEvent *event); - void keyReleaseEvent(QKeyEvent *event); -private: - void updateSLvariables(); - int mBrowserWindowId; -}; - -WebPage::WebPage(QWidget *parent) - : QWidget(parent) -{ - setMouseTracking(true); - std::string applicationDir = std::string(); - std::string componentDir = applicationDir; - std::string profileDir = applicationDir + "\\" + "testGL_profile"; - LLQtWebKit::getInstance()->init(applicationDir, componentDir, profileDir, 0); - - mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow(width(), height()); - - // observer events that LLQtWebKit emits - LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this ); - - // append details to agent string - LLQtWebKit::getInstance()->setBrowserAgentId("testqtapp"); - - // don't flip bitmap - LLQtWebKit::getInstance()->flipWindow(mBrowserWindowId, false); - - // test Second Life viewer specific functions - LLQtWebKit::getInstance()->setSLObjectEnabled( true ); // true means feature is turned on - LLQtWebKit::getInstance()->setAgentLanguage( "tst-en" ); // viewer language selected by agent - LLQtWebKit::getInstance()->setAgentRegion( "QtTestAppRegion" ); // name of region where agent is located - LLQtWebKit::getInstance()->setAgentLocation( 9.8, 7.6, 5.4 ); // agent's x,y,z location within a region - LLQtWebKit::getInstance()->setAgentGlobalLocation( 119.8, 227.6, 335.4 ); // agent's x,y,z location within the grid - LLQtWebKit::getInstance()->setAgentMaturity( "Very immature" ); // selected maturity level of agent - LLQtWebKit::getInstance()->setAgentOrientation( (rand()%36000)/100.0f ); // direction avatar is facing - LLQtWebKit::getInstance()->emitLocation(); - LLQtWebKit::getInstance()->emitLanguage(); - LLQtWebKit::getInstance()->emitMaturity(); - - // go to the "home page" - LLQtWebKit::getInstance()->navigateTo(mBrowserWindowId, "http://callum-linden.s3.amazonaws.com/browsertest.html"); -} - -WebPage::~WebPage() -{ - // unhook observer - LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this ); - - // clean up - LLQtWebKit::getInstance()->reset(); -} - -void WebPage::updateSLvariables() -{ - // randomly update SL values to test - LLQtWebKit::getInstance()->setAgentOrientation( (rand()%36000)/100.0f ); - LLQtWebKit::getInstance()->setAgentLocation( (rand()%25600)/100.0f, (rand()%25600)/100.0f, (rand()%25600)/100.0f ); - LLQtWebKit::getInstance()->setAgentGlobalLocation( (rand()%25600)/100.0f, (rand()%25600)/100.0f, (rand()%25600)/100.0f ); - - if ( rand() % 2 ) - LLQtWebKit::getInstance()->setAgentLanguage( "One language" ); - else - LLQtWebKit::getInstance()->setAgentLanguage( "Another language" ); - - if ( rand() % 2 ) - LLQtWebKit::getInstance()->setAgentRegion( "Region Wibble" ); - else - LLQtWebKit::getInstance()->setAgentRegion( "Region Flasm" ); - - if ( rand() % 2 ) - LLQtWebKit::getInstance()->setAgentMaturity( "Adults only" ); - else - LLQtWebKit::getInstance()->setAgentMaturity( "Children only" ); - - LLQtWebKit::getInstance()->emitLocation(); - LLQtWebKit::getInstance()->emitLanguage(); - LLQtWebKit::getInstance()->emitMaturity(); -} - -void WebPage::onCursorChanged(const EventType& event) -{ - //qDebug() << __FUNCTION__ << QString::fromStdString(event.getEventUri()); - switch (event.getIntValue()) { - case LLQtWebKit::C_ARROW: setCursor(QCursor(Qt::ArrowCursor)); break; - case LLQtWebKit::C_IBEAM: setCursor(QCursor(Qt::IBeamCursor)); break; - case LLQtWebKit::C_SPLITV: setCursor(QCursor(Qt::SplitHCursor)); break; - case LLQtWebKit::C_SPLITH: setCursor(QCursor(Qt::SplitVCursor)); break; - case LLQtWebKit::C_POINTINGHAND: setCursor(QCursor(Qt::PointingHandCursor)); break; - default: break; - } -} - -void WebPage::onPageChanged(const EventType& event) -{ - Q_UNUSED(event); - LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId ); - //qDebug() << __FUNCTION__ << QString::fromStdString(event.getEventUri()); - update(); -} - -void WebPage::onNavigateBegin(const EventType& event) -{ - Q_UNUSED(event); - //qDebug() << __FUNCTION__ << QString::fromStdString(event.getEventUri()); -} - -void WebPage::onNavigateComplete(const EventType& event) -{ - Q_UNUSED(event); - //qDebug() << __FUNCTION__ << QString::fromStdString(event.getEventUri()); -} - -void WebPage::onUpdateProgress(const EventType& event) -{ - Q_UNUSED(event); -} - -void WebPage::onStatusTextChange(const EventType& event) -{ - Q_UNUSED(event); -} - -void WebPage::onLocationChange(const EventType& event) -{ - //qDebug() << __FUNCTION__; - emit locationChanged(QString::fromStdString(event.getEventUri())); - //void canGoBack(bool); - //void canGoForward(bool); -} - -void WebPage::onClickLinkHref(const EventType& event) -{ - Q_UNUSED(event); -} - -void WebPage::onClickLinkNoFollow(const EventType& event) -{ - Q_UNUSED(event); -} - -void WebPage::resizeEvent(QResizeEvent *event) -{ - LLQtWebKit::getInstance()->setSize(mBrowserWindowId, event->size().width(), event->size().height()); - QWidget::resizeEvent(event); -} - -void WebPage::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event); - - int width = LLQtWebKit::getInstance()->getBrowserWidth(mBrowserWindowId); - int height = LLQtWebKit::getInstance()->getBrowserHeight(mBrowserWindowId); - const unsigned char* pixels = LLQtWebKit::getInstance()->getBrowserWindowPixels(mBrowserWindowId); - QImage image(pixels, width, height, QImage::Format_RGB32); - image = image.rgbSwapped(); - QPainter painter(this); - painter.drawImage(QPoint(0, 0), image); -} - -void WebPage::mouseDoubleClickEvent(QMouseEvent *event) -{ - LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, - LLQtWebKit::ME_MOUSE_DOUBLE_CLICK, - LLQtWebKit::MB_MOUSE_BUTTON_LEFT, - event->x(), event->y(), - LLQtWebKit::KM_MODIFIER_NONE ); -} - -void WebPage::mouseMoveEvent(QMouseEvent *event) -{ - updateSLvariables(); - - LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, - LLQtWebKit::ME_MOUSE_MOVE, - LLQtWebKit::MB_MOUSE_BUTTON_LEFT, - event->x(), event->y(), - LLQtWebKit::KM_MODIFIER_NONE ); -} - -void WebPage::mousePressEvent(QMouseEvent *event) -{ - LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, - LLQtWebKit::ME_MOUSE_DOWN, - LLQtWebKit::MB_MOUSE_BUTTON_LEFT, - event->x(), event->y(), - LLQtWebKit::KM_MODIFIER_NONE ); -} - -void WebPage::mouseReleaseEvent(QMouseEvent *event) -{ - LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, - LLQtWebKit::ME_MOUSE_UP, - LLQtWebKit::MB_MOUSE_BUTTON_LEFT, - event->x(), event->y(), - LLQtWebKit::KM_MODIFIER_NONE ); - - LLQtWebKit::getInstance()->focusBrowser(mBrowserWindowId, true); -} - -void WebPage::keyPressEvent(QKeyEvent *event) -{ - Q_UNUSED(event); -} - -void WebPage::keyReleaseEvent(QKeyEvent *event) -{ - Q_UNUSED(event); - //LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, event->text().at(0).unicode(),LLQtWebKit::KM_MODIFIER_NONE); -} - -void WebPage::goBack() -{ - LLQtWebKit::getInstance()->userAction(mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK); -} - -void WebPage::goForward() -{ - LLQtWebKit::getInstance()->userAction(mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD); -} - -void WebPage::reload() -{ - LLQtWebKit::getInstance()->userAction(mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_RELOAD); -} - -void WebPage::loadUrl(const QString &url) -{ - LLQtWebKit::getInstance()->navigateTo(mBrowserWindowId, url.toStdString()); -} - -#include "ui_window.h" - -class Window : public QDialog, public Ui_Dialog -{ - Q_OBJECT -public: - Window(QWidget *parent = 0); - -public slots: - void loadUrl(); -}; - -Window::Window(QWidget *parent) - : QDialog(parent) -{ - setupUi(this); - connect(webpage, SIGNAL(locationChanged(const QString &)), - location, SLOT(setText(const QString &))); - connect(webpage, SIGNAL(canGoBack(bool)), - backButton, SLOT(setEnabled(bool))); - connect(webpage, SIGNAL(canGoForward(bool)), - forwardButton, SLOT(setEnabled(bool))); - connect(backButton, SIGNAL(clicked()), - webpage, SLOT(goBack())); - connect(forwardButton, SIGNAL(clicked()), - webpage, SLOT(goForward())); - connect(reloadButton, SIGNAL(clicked()), - webpage, SLOT(reload())); - connect(location, SIGNAL(returnPressed()), - this, SLOT(loadUrl())); -} - -void Window::loadUrl() -{ - webpage->loadUrl(location->text()); -} - - -int main(int argc, char **argv) -{ - QApplication application(argc, argv); - Window window; - window.show(); - return application.exec(); -} - -#include "main.moc" diff --git a/indra/llqtwebkit/tests/qttestapp/qttestapp.pro b/indra/llqtwebkit/tests/qttestapp/qttestapp.pro deleted file mode 100644 index 5a0ca33cf0..0000000000 --- a/indra/llqtwebkit/tests/qttestapp/qttestapp.pro +++ /dev/null @@ -1,38 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . -INCLUDEPATH += ../../ -CONFIG -= app_bundle - -include(../../static.pri) - -QT += webkit opengl network - -unix { - LIBS += $$PWD/../../libllqtwebkit.a -} - -!mac { -unix { - DEFINES += LL_LINUX -} -} - -mac { - DEFINES += LL_OSX -} - - -win32{ - DEFINES += _WINDOWS - INCLUDEPATH += ../ - DESTDIR=../build - release { - LIBS += $$PWD/../../Release/llqtwebkit.lib - } -} - -# Input -SOURCES += main.cpp -FORMS += window.ui diff --git a/indra/llqtwebkit/tests/qttestapp/webpage.h b/indra/llqtwebkit/tests/qttestapp/webpage.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/indra/llqtwebkit/tests/qttestapp/window.ui b/indra/llqtwebkit/tests/qttestapp/window.ui deleted file mode 100644 index 6125821cc3..0000000000 --- a/indra/llqtwebkit/tests/qttestapp/window.ui +++ /dev/null @@ -1,79 +0,0 @@ - - - Dialog - - - - 0 - 0 - 766 - 613 - - - - Dialog - - - - 0 - - - - - 6 - - - 6 - - - 6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - 0 - - - - - - - - - WebPage - QWidget -
    webpage.h
    - 1 -
    -
    - - -
    diff --git a/indra/llqtwebkit/tests/ssltest/ssltest.cpp b/indra/llqtwebkit/tests/ssltest/ssltest.cpp deleted file mode 100644 index fcbf80314d..0000000000 --- a/indra/llqtwebkit/tests/ssltest/ssltest.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef _WINDOWS -extern "C" { -#include -} -#endif - -#ifdef _WINDOWS -#include -#include -#endif - -#include -#include -#include - -#ifdef LL_OSX -// I'm not sure why STATIC_QT is getting defined, but the Q_IMPORT_PLUGIN thing doesn't seem to be necessary on the mac. -#undef STATIC_QT -#endif - -#ifdef STATIC_QT -#include -Q_IMPORT_PLUGIN(qgif) -#endif - -#include "llqtwebkit.h" - -class sslTest : - public LLEmbeddedBrowserWindowObserver -{ - public: - sslTest( std::string url, bool ignore_ca_file, bool ignore_ssl_errors ) : - mBrowserWindowWidth( 512 ), - mBrowserWindowHeight( 512 ), - mBrowserWindowHandle( 0 ), - mNavigateInProgress( true ) - { -#ifdef _WINDOWS - std::string cwd = std::string( _getcwd( NULL, 1024) ); - std::string profile_dir = cwd + "\\" + "ssltest_profile"; - void* native_window_handle = (void*)GetDesktopWindow(); - std::string ca_file_loc = cwd + "\\" + "CA.pem"; -#else - std::string cwd = std::string( getcwd( NULL, 1024) ); - std::string profile_dir = cwd + "/" + "ssltest_profile"; - void* native_window_handle = 0; - std::string ca_file_loc = cwd + "/" + "CA.pem"; -#endif - std::cout << "ssltest> === begin ===" << std::endl; - std::cout << "ssltest> current working dir is " << cwd << std::endl; - std::cout << "ssltest> profiles dir location is " << profile_dir << std::endl; - - LLQtWebKit::getInstance()->init( cwd, cwd, profile_dir, native_window_handle ); - - LLQtWebKit::getInstance()->enableJavaScript( true ); - LLQtWebKit::getInstance()->enablePlugins( true ); - - mBrowserWindowHandle = LLQtWebKit::getInstance()->createBrowserWindow( mBrowserWindowWidth, mBrowserWindowHeight ); - LLQtWebKit::getInstance()->setSize( mBrowserWindowHandle, mBrowserWindowWidth, mBrowserWindowHeight ); - - LLQtWebKit::getInstance()->addObserver( mBrowserWindowHandle, this ); - - if ( ! ignore_ca_file ) - { - std::cout << "ssltest> Expected certificate authority file location is " << ca_file_loc << std::endl; - LLQtWebKit::getInstance()->setCAFile( ca_file_loc.c_str() ); - } - else - { - std::cout << "ssltest> Not loading certificate authority file" << std::endl; - }; - - if ( ignore_ssl_errors ) - { - LLQtWebKit::getInstance()->setIgnoreSSLCertErrors( true ); - std::cout << "ssltest> Ignoring SSL errors " << std::endl; - } - else - { - std::cout << "ssltest> Not ignoring SSL errors " << std::endl; - }; - - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowHandle, url ); - - std::cout << "ssltest> navigating to " << url << std::endl; - }; - - bool idle( void ) - { - LLQtWebKit::getInstance()->pump( 100 ); - -#if _WINDOWS - MSG msg; - while ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) - { - GetMessage( &msg, NULL, 0, 0 ); - TranslateMessage( &msg ); - DispatchMessage( &msg ); - }; -#endif - return mNavigateInProgress; - }; - - ~sslTest() - { - LLQtWebKit::getInstance()->remObserver( mBrowserWindowHandle, this ); - LLQtWebKit::getInstance()->reset(); - std::cout << "ssltest> === end ===" << std::endl; - }; - - void onNavigateBegin( const EventType& eventIn ) - { - mNavigateInProgress = true; - std::cout << "ssltest> Event: begin navigation to " << eventIn.getEventUri() << std::endl; - }; - - void onNavigateComplete( const EventType& eventIn ) - { - std::cout << "ssltest> Event: end navigation to " << eventIn.getEventUri() << std::endl; - mNavigateInProgress = false; - }; - - void onUpdateProgress( const EventType& eventIn ) - { - std::cout << "ssltest> Event: progress value updated to " << eventIn.getIntValue() << std::endl; - }; - - void onStatusTextChange( const EventType& eventIn ) - { - std::cout << "ssltest> Event: status updated to " << eventIn.getStringValue() << std::endl; - }; - - void onTitleChange( const EventType& eventIn ) - { - std::cout << "ssltest> Event: title changed to " << eventIn.getStringValue() << std::endl; - }; - - void onLocationChange( const EventType& eventIn ) - { - std::cout << "ssltest> Event: location changed to " << eventIn.getStringValue() << std::endl; - }; - - bool onCertError(const std::string &in_url, const std::string &in_msg) - { - std::cout << "ssltest> Cert error triggered\n" << in_url << "\n" << in_msg << std::endl; - return true; - } - - private: - int mBrowserWindowWidth; - int mBrowserWindowHeight; - int mBrowserWindowHandle; - bool mNavigateInProgress; -}; - -int main( int argc, char* argv[] ) -{ - bool ingore_ssl_errors = false; - bool ignore_ca_file = false; - - for( int i = 1; i < argc; ++i ) - { - if ( std::string( argv[ i ] ) == "--help" ) - { - std::cout << std::endl << "ssltest [--ignoresslerrors] [--ignorecafile]" << std::endl; - std::cout << "Looks for cert file CA.pem in the current working directory"; - - exit( 0 ); - }; - - if ( std::string( argv[ i ] ) == "--ignoresslerrors" ) - ingore_ssl_errors = true; - - if ( std::string( argv[ i ] ) == "--ignorecafile" ) - ignore_ca_file = true; - }; - - std::string url ( "https://my.secondlife.com/callum.linden" ); - for( int i = 1; i < argc; ++i ) - { - if ( std::string( argv[ i ] ).substr( 0, 2 ) != "--" ) - { - url = std::string( argv[ i ] ); - break; - }; - }; - - std::cout << std::endl << " --------- sslTest application starting --------- " << std::endl; - std::cout << "ssltest> URL specified is " << url << std::endl; - - sslTest* app = new sslTest( url, ignore_ca_file, ingore_ssl_errors ); - - bool result = app->idle(); - while( result ) - { - result = app->idle(); - }; - - delete app; - - std::cout << " --------- sslTest application ending --------- " << std::endl; - - return 0; -} diff --git a/indra/llqtwebkit/tests/ssltest/ssltest.pro b/indra/llqtwebkit/tests/ssltest/ssltest.pro deleted file mode 100644 index 981e352113..0000000000 --- a/indra/llqtwebkit/tests/ssltest/ssltest.pro +++ /dev/null @@ -1,28 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . -INCLUDEPATH += ../../ -CONFIG -= app_bundle -CONFIG += console - -QT += webkit network - -mac { - DEFINES += LL_OSX - LIBS += $$PWD/libllqtwebkit.dylib -} - -win32 { - DEFINES += _WINDOWS - INCLUDEPATH += ../ - DESTDIR=../build - LIBS += user32.lib - release { - LIBS += $$PWD/../../Release/llqtwebkit.lib - } -} - -include(../../static.pri) - -SOURCES += ssltest.cpp diff --git a/indra/llqtwebkit/tests/testgl/testgl.cpp b/indra/llqtwebkit/tests/testgl/testgl.cpp deleted file mode 100644 index 6dfb11a725..0000000000 --- a/indra/llqtwebkit/tests/testgl/testgl.cpp +++ /dev/null @@ -1,1002 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef _WINDOWS -extern "C" { -#include -} -#endif - -#ifdef _WINDOWS -#include -#include // file choser dialog -#include // for local file access -#endif - -#include -#include -#include -#include -#include - -#ifdef LL_OSX -// I'm not sure why STATIC_QT is getting defined, but the Q_IMPORT_PLUGIN thing doesn't seem to be necessary on the mac. -#undef STATIC_QT -#endif - -#ifdef STATIC_QT -#include -Q_IMPORT_PLUGIN(qgif) -#endif - -#ifdef LL_OSX -#include -#include -#else -#define FREEGLUT_STATIC -#include "GL/glut.h" -#endif -#include "llqtwebkit.h" - -#ifdef _WINDOWS - #define PATH_SEPARATOR "\\" -#else - #define PATH_SEPARATOR "/" -#endif - - -//////////////////////////////////////////////////////////////////////////////// -// -std::string chooseFileName() -{ -#ifdef _WINDOWS - OPENFILENAMEA ofn ; - static char szFile[_MAX_PATH] ; - - ZeroMemory( &ofn , sizeof( ofn) ); - ofn.lStructSize = sizeof ( ofn ); - ofn.hwndOwner = NULL ; - ofn.lpstrFile = szFile ; - ofn.lpstrFile[0] = '\0'; - ofn.nMaxFile = sizeof( szFile ); - ofn.lpstrFilter = "All\0*.*\0Images\0*.jpg;*.png\0"; - ofn.nFilterIndex =1; - ofn.lpstrFileTitle = NULL ; - ofn.nMaxFileTitle = 0 ; - ofn.lpstrInitialDir=NULL ; - ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST ; - - GetOpenFileNameA( &ofn ); - - return ofn.lpstrFile; -#else - return ""; -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -// Implementation of the test app - implemented as a class and derrives from -// the observer so we can catch events emitted by LLQtWebKit -// -class testGL : - public LLEmbeddedBrowserWindowObserver -{ - public: - testGL() : - mAppWindowWidth( 800 ), // dimensions of the app window - can be anything - mAppWindowHeight( 900 ), - mBrowserWindowWidth( mAppWindowWidth ), // dimensions of the embedded browser - can be anything - mBrowserWindowHeight( mAppWindowHeight ), // but looks best when it's the same as the app window - mAppTextureWidth( -1 ), // dimensions of the texture that the browser is rendered into - mAppTextureHeight( -1 ), // calculated at initialization - mAppTexture( 0 ), - mBrowserWindowId( 0 ), - mAppWindowName( "testGL" ), - mCwd(), - mHomeUrl(), - mNeedsUpdate( true ) // flag to indicate if browser texture needs an update - { -#ifdef _WINDOWS // to remove warning on Windows - mCwd = _getcwd(NULL, 1024); -#else - mCwd = getcwd(NULL, 1024); -#endif - mHomeUrl = "http://callum-linden.s3.amazonaws.com/browsertest.html"; - std::cout << "LLQtWebKit version: " << LLQtWebKit::getInstance()->getVersion() << std::endl; - - std::cout << "Current working directory is " << mCwd << std::endl; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void init( const std::string argv0, const std::string argv1 ) - { - // OpenGL initialization - glClearColor( 0.0f, 0.0f, 0.0f, 0.5f); - glEnable( GL_COLOR_MATERIAL ); - glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE ); - glEnable( GL_TEXTURE_2D ); - glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); - glEnable( GL_CULL_FACE ); - - // calculate texture size required (next power of two above browser window size - for ( mAppTextureWidth = 1; mAppTextureWidth < mBrowserWindowWidth; mAppTextureWidth <<= 1 ) - { - }; - - for ( mAppTextureHeight = 1; mAppTextureHeight < mBrowserWindowHeight; mAppTextureHeight <<= 1 ) - { - }; - - // create the texture used to display the browser data - glGenTextures( 1, &mAppTexture ); - glBindTexture( GL_TEXTURE_2D, mAppTexture ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexImage2D( GL_TEXTURE_2D, 0, - GL_RGB, - mAppTextureWidth, mAppTextureHeight, - 0, GL_RGB, GL_UNSIGNED_BYTE, 0 ); - - // create a single browser window and set things up. - mProfileDir = mCwd + PATH_SEPARATOR + "testGL_profile"; - std::cout << "Profiles dir location is " << mProfileDir << std::endl; - - mCookiePath = mProfileDir + PATH_SEPARATOR + "cookies.txt"; - std::cout << "Cookies.txt file location is " << mCookiePath << std::endl; - - LLQtWebKit::getInstance()->init( mApplicationDir, mApplicationDir, mProfileDir, getNativeWindowHandle() ); - - LLQtWebKit::getInstance()->enableQtMessageHandler( false ); - - // set host language test (in reality, string will be language code passed into client) - // IMPORTANT: must be called before createBrowserWindow(...) - LLQtWebKit::getInstance()->setHostLanguage( "EN-AB-CD-EF" ); - - // set up features - LLQtWebKit::getInstance()->enableJavaScript( true ); - LLQtWebKit::getInstance()->enableCookies( true ); - LLQtWebKit::getInstance()->enablePlugins( true ); - - // make a browser window - mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mBrowserWindowWidth, mBrowserWindowHeight ); - - // tell LLQtWebKit about the size of the browser window - LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mBrowserWindowWidth, mBrowserWindowHeight ); - - // observer events that LLQtWebKit emits - LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this ); - - // append details to agent string - LLQtWebKit::getInstance()->setBrowserAgentId( mAppWindowName ); - - // don't flip bitmap - LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, false ); - - // only "trust" pages whose host match this regex - LLQtWebKit::getInstance()->setWhiteListRegex( mBrowserWindowId, "^([^.]+\\.)*amazonaws\\.com$" ); - - LLQtWebKit::getInstance()->enableLoadingOverlay( mBrowserWindowId, true ); - - // Attempt to read cookies from the cookie file and send them to llqtwebkit. - { - std::ifstream cookie_file(mCookiePath.c_str(), std::ios_base::in); - std::string cookies; - - while(cookie_file.good() && !cookie_file.eof()) - { - std::string tmp; - std::getline(cookie_file, tmp); - cookies += tmp; - cookies += "\n"; - } - - if(!cookies.empty()) - { - LLQtWebKit::getInstance()->setCookies(cookies); - } - } - - #if 0 - const std::vector before=LLQtWebKit::getInstance()->getInstalledCertsList(); - std::cout << "Certs before CA.pem load: " << before.size() << " items" << std::endl; - for(int i=0;isetCAFile( ca_pem_file_loc.c_str() ); - std::cout << "Expected CA.pem file location is " << ca_pem_file_loc << std::endl; - - #if 0 - const std::vector after=LLQtWebKit::getInstance()->getInstalledCertsList(); - std::cout << "Certs after CA.pem load: " << after.size() << " items" << std::endl; - for(int i=0;isetSLObjectEnabled( true ); // true means the feature is turned on - LLQtWebKit::getInstance()->setAgentLanguage( "tst-en" ); // viewer language selected by agent - LLQtWebKit::getInstance()->setAgentRegion( "TestGL region" ); // name of region where agent is located - LLQtWebKit::getInstance()->setAgentLocation( 9.8, 7.6, 5.4 ); // agent's x,y,z location within a region - LLQtWebKit::getInstance()->setAgentGlobalLocation( 1234.5, 6789.0, 3456.7 ); // agent's x,y,z location within a region - LLQtWebKit::getInstance()->setAgentOrientation( 175.69 ); // direction (0..359) agent is facing - LLQtWebKit::getInstance()->setAgentMaturity( "Very immature" ); // selected maturity level of agent - - // go to the "home page" or URL passed in via command line - if ( ! argv1.empty() ) - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, argv1 ); - else - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, mHomeUrl ); - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void reset( void ) - { - // Get cookies from this instance - std::string cookies = LLQtWebKit::getInstance()->getAllCookies(); - - // Dump cookies to stdout -// std::cout << "Cookies:" << std::endl; -// std::cout << cookies; - - // and save them to cookies.txt in the profile directory - { - std::ofstream cookie_file(mCookiePath.c_str(), std::ios_base::out|std::ios_base::trunc); - - if(cookie_file.good()) - { - cookie_file << cookies; - } - - cookie_file.close(); - } - - // unhook observer - LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this ); - - // clean up - LLQtWebKit::getInstance()->reset(); - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void reshape( int widthIn, int heightIn ) - { - if ( heightIn == 0 ) - heightIn = 1; - - LLQtWebKit::getInstance()->setSize(mBrowserWindowId, widthIn, heightIn ); - mNeedsUpdate = true; - - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - - glViewport( 0, 0, widthIn, heightIn ); - glOrtho( 0.0f, widthIn, heightIn, 0.0f, -1.0f, 1.0f ); - - // we use these elsewhere so save - mAppWindowWidth = widthIn; - mAppWindowHeight = heightIn; - mBrowserWindowWidth = widthIn; - mBrowserWindowHeight = heightIn; - - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - - mNeedsUpdate = true; - idle(); - - glutPostRedisplay(); - }; - - void updateSLvariables() - { - if ( rand() % 2 ) - LLQtWebKit::getInstance()->setAgentRegion( "Region Wibble" ); - else - LLQtWebKit::getInstance()->setAgentRegion( "Region Flasm" ); - LLQtWebKit::getInstance()->setAgentLocation( (rand()%25600)/100.0f, (rand()%25600)/100.0f, (rand()%25600)/100.0f ); - LLQtWebKit::getInstance()->setAgentGlobalLocation( (rand()%25600)/10.0f, (rand()%25600)/10.0f, (rand()%25600)/10.0f ); - LLQtWebKit::getInstance()->setAgentOrientation( (rand()%3600)/10.0f ); - LLQtWebKit::getInstance()->emitLocation(); - - if ( rand() % 2 ) - LLQtWebKit::getInstance()->setAgentLanguage( "One language" ); - else - LLQtWebKit::getInstance()->setAgentLanguage( "Another language" ); - LLQtWebKit::getInstance()->emitLanguage(); - - if ( rand() % 2 ) - LLQtWebKit::getInstance()->setAgentMaturity( "Adults only" ); - else - LLQtWebKit::getInstance()->setAgentMaturity( "Children only" ); - LLQtWebKit::getInstance()->emitMaturity(); - } - - //////////////////////////////////////////////////////////////////////////////// - // - void idle() - { - static time_t starttime = time( NULL ); - if ( time( NULL ) - starttime ) - { - updateSLvariables(); - time( &starttime ); - }; - - LLQtWebKit::getInstance()->pump(100); - - // onPageChanged event sets this - if ( mNeedsUpdate ) - // grab a page but don't reset 'needs update' flag until we've written it to the texture in display() - LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId ); - - // lots of updates for smooth motion - glutPostRedisplay(); - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void display() - { - // clear screen - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - glLoadIdentity(); - - // use the browser texture - glBindTexture( GL_TEXTURE_2D, mAppTexture ); - - // valid window ? - if ( mBrowserWindowId ) - { - // needs to be updated? - if ( mNeedsUpdate ) - { - // grab the page - const unsigned char* pixels = LLQtWebKit::getInstance()->getBrowserWindowPixels( mBrowserWindowId ); - if ( pixels ) - { - // write them into the texture - glTexSubImage2D( GL_TEXTURE_2D, 0, - 0, 0, - // because sometimes the rowspan != width * bytes per pixel (mBrowserWindowWidth) - LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId ) / LLQtWebKit::getInstance()->getBrowserDepth( mBrowserWindowId ), - mBrowserWindowHeight, -#ifdef _WINDOWS - LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId ) == 3 ? GL_RGBA : GL_RGBA, -#elif defined(__APPLE__) - GL_RGBA, -#elif defined(LL_LINUX) - GL_RGBA, -#endif - GL_UNSIGNED_BYTE, - pixels ); - }; - - // flag as already updated - mNeedsUpdate = false; - }; - }; - - // scale the texture so that it fits the screen - GLfloat textureScaleX = ( GLfloat )mBrowserWindowWidth / ( GLfloat )mAppTextureWidth; - GLfloat textureScaleY = ( GLfloat )mBrowserWindowHeight / ( GLfloat )mAppTextureHeight; - - // draw the single quad full screen (orthographic) - glMatrixMode( GL_TEXTURE ); - glPushMatrix(); - glScalef( textureScaleX, textureScaleY, 1.0f ); - - glEnable( GL_TEXTURE_2D ); - glColor3f( 1.0f, 1.0f, 1.0f ); - glBegin( GL_QUADS ); - glTexCoord2f( 1.0f, 0.0f ); - glVertex2d( mAppWindowWidth, 0 ); - - glTexCoord2f( 0.0f, 0.0f ); - glVertex2d( 0, 0 ); - - glTexCoord2f( 0.0f, 1.0f ); - glVertex2d( 0, mAppWindowHeight ); - - glTexCoord2f( 1.0f, 1.0f ); - glVertex2d( mAppWindowWidth, mAppWindowHeight ); - glEnd(); - - glMatrixMode( GL_TEXTURE ); - glPopMatrix(); - - glutSwapBuffers(); - }; - - //////////////////////////////////////////////////////////////////////////////// - // convert a GLUT keyboard modifier to an LLQtWebKit one - // (only valid in mouse and keyboard callbacks - LLQtWebKit::EKeyboardModifier getLLQtWebKitKeyboardModifierCode() - { - int result = LLQtWebKit::KM_MODIFIER_NONE; - - int modifiers = glutGetModifiers(); - - if ( GLUT_ACTIVE_SHIFT & modifiers ) - { - result |= LLQtWebKit::KM_MODIFIER_SHIFT; - } - - if ( GLUT_ACTIVE_CTRL & modifiers ) - result |= LLQtWebKit::KM_MODIFIER_CONTROL; - - if ( GLUT_ACTIVE_ALT & modifiers ) - result |= LLQtWebKit::KM_MODIFIER_ALT; - - return (LLQtWebKit::EKeyboardModifier)result; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void mouseButton( int button, int state, int xIn, int yIn ) - { - // texture is scaled to fit the screen so we scale mouse coords in the same way - xIn = ( xIn * mBrowserWindowWidth ) / mAppWindowWidth; - yIn = ( yIn * mBrowserWindowHeight ) / mAppWindowHeight; - - if ( button == GLUT_LEFT_BUTTON ) - { - if ( state == GLUT_DOWN ) - { - // send event to LLQtWebKit - LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, - LLQtWebKit::ME_MOUSE_DOWN, - LLQtWebKit::MB_MOUSE_BUTTON_LEFT, - xIn, yIn, - getLLQtWebKitKeyboardModifierCode() ); - } - else - if ( state == GLUT_UP ) - { - // send event to LLQtWebKit - LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, - LLQtWebKit::ME_MOUSE_UP, - LLQtWebKit::MB_MOUSE_BUTTON_LEFT, - xIn, yIn, - getLLQtWebKitKeyboardModifierCode() ); - - - // this seems better than sending focus on mouse down (still need to improve this) - LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, true ); - }; - }; - - // force a GLUT update - glutPostRedisplay(); - } - - //////////////////////////////////////////////////////////////////////////////// - // - void mouseMove( int xIn , int yIn ) - { - // texture is scaled to fit the screen so we scale mouse coords in the same way - xIn = ( xIn * mBrowserWindowWidth ) / mAppWindowWidth; - yIn = ( yIn * mBrowserWindowHeight ) / mAppWindowHeight; - - // send event to LLQtWebKit - LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, - LLQtWebKit::ME_MOUSE_MOVE, - LLQtWebKit::MB_MOUSE_BUTTON_LEFT, - xIn, yIn, - LLQtWebKit::KM_MODIFIER_NONE ); - - - // force a GLUT update - glutPostRedisplay(); - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void keyboard( unsigned char keyIn, bool isDown) - { - // ESC key exits - if ( keyIn == 27 ) - { - reset(); - - exit( 0 ); - }; - - // Translate some keys - switch(keyIn) - { - case 127: - // Turn delete char into backspace - keyIn = LLQtWebKit::KEY_BACKSPACE; - break; - case '\r': - case '\n': - // Turn CR and NL into enter key - keyIn = LLQtWebKit::KEY_RETURN; - break; - - case '\t': - keyIn = LLQtWebKit::KEY_TAB; - break; - - default: - break; - } - - // control-H goes home - if ( keyIn == 8 ) - { - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, mHomeUrl ); - } - // control-B navigates back - else if ( keyIn == 2 ) - { - LLQtWebKit::getInstance()->userAction(mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK); - } - // control-F navigates forward - else if ( keyIn == 6 ) - { - LLQtWebKit::getInstance()->userAction(mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD); - } - // control-R reloads - else if ( keyIn == 18 ) - { - LLQtWebKit::getInstance()->userAction(mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_RELOAD ); - } - // control-I toggles inspector - else if ( keyIn == 23 ) - { - LLQtWebKit::getInstance()->showWebInspector( true ); - } - else if ( keyIn == '1' ) - { - if ( getLLQtWebKitKeyboardModifierCode() == LLQtWebKit::KM_MODIFIER_CONTROL ) - { - LLQtWebKit::getInstance()->setPageZoomFactor( 1.0 ); - } - } - else if ( keyIn == '2' ) - { - if ( getLLQtWebKitKeyboardModifierCode() == LLQtWebKit::KM_MODIFIER_CONTROL ) - { - LLQtWebKit::getInstance()->setPageZoomFactor( 2.0 ); - } - } - - char text[2]; - if(keyIn < 0x80) - { - text[0] = (char)keyIn; - } - else - { - text[0] = 0; - } - - text[1] = 0; - - std::cerr << "key " << (isDown?"down ":"up ") << (int)keyIn << ", modifiers = " << (int)getLLQtWebKitKeyboardModifierCode() << std::endl; - - // send event to LLQtWebKit - LLQtWebKit::getInstance()->keyboardEvent(mBrowserWindowId, isDown?LLQtWebKit::KE_KEY_DOWN:LLQtWebKit::KE_KEY_UP, keyIn, text, getLLQtWebKitKeyboardModifierCode() ); - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void keyboardSpecial( int specialIn, bool isDown) - { - uint32_t key = LLQtWebKit::KEY_NONE; - - switch(specialIn) - { - case GLUT_KEY_F1: key = LLQtWebKit::KEY_F1; break; - case GLUT_KEY_F2: key = LLQtWebKit::KEY_F2; break; - case GLUT_KEY_F3: key = LLQtWebKit::KEY_F3; break; - case GLUT_KEY_F4: key = LLQtWebKit::KEY_F4; break; - case GLUT_KEY_F5: key = LLQtWebKit::KEY_F5; break; - case GLUT_KEY_F6: key = LLQtWebKit::KEY_F6; break; - case GLUT_KEY_F7: key = LLQtWebKit::KEY_F7; break; - case GLUT_KEY_F8: key = LLQtWebKit::KEY_F8; break; - case GLUT_KEY_F9: key = LLQtWebKit::KEY_F9; break; - case GLUT_KEY_F10: key = LLQtWebKit::KEY_F10; break; - case GLUT_KEY_F11: key = LLQtWebKit::KEY_F11; break; - case GLUT_KEY_F12: key = LLQtWebKit::KEY_F12; break; - case GLUT_KEY_LEFT: key = LLQtWebKit::KEY_LEFT; break; - case GLUT_KEY_UP: key = LLQtWebKit::KEY_UP; break; - case GLUT_KEY_RIGHT: key = LLQtWebKit::KEY_RIGHT; break; - case GLUT_KEY_DOWN: key = LLQtWebKit::KEY_DOWN; break; - case GLUT_KEY_PAGE_UP: key = LLQtWebKit::KEY_PAGE_UP; break; - case GLUT_KEY_PAGE_DOWN: key = LLQtWebKit::KEY_PAGE_DOWN;break; - case GLUT_KEY_HOME: key = LLQtWebKit::KEY_HOME; break; - case GLUT_KEY_END: key = LLQtWebKit::KEY_END; break; - case GLUT_KEY_INSERT: key = LLQtWebKit::KEY_INSERT; break; - - default: - break; - } - - if(key != LLQtWebKit::KEY_NONE) - { - keyboard(key, isDown); - } - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onPageChanged( const EventType& /*eventIn*/ ) - { - // flag that an update is required - page grab happens in idle() so we don't stall - mNeedsUpdate = true; - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onNavigateBegin( const EventType& eventIn ) - { - std::cout << "Event: begin navigation to " << eventIn.getEventUri() << std::endl; - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onNavigateComplete( const EventType& eventIn ) - { - std::cout << "Event: end navigation to " << eventIn.getEventUri() << std::endl; - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onUpdateProgress( const EventType& eventIn ) - { - std::cout << "Event: progress value updated to " << eventIn.getIntValue() << std::endl; - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onStatusTextChange( const EventType& eventIn ) - { - std::cout << "Event: status updated to " << eventIn.getStringValue() << std::endl; - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onTitleChange( const EventType& eventIn ) - { - std::cout << "Event: title changed to " << eventIn.getStringValue() << std::endl; - glutSetWindowTitle( eventIn.getStringValue().c_str() ); - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onLocationChange( const EventType& eventIn ) - { - std::cout << "Event: location changed to " << eventIn.getStringValue() << std::endl; - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onClickLinkHref( const EventType& eventIn ) - { - std::string uuid = eventIn.getStringValue2(); - - std::cout << "Event: clicked on link:" << std::endl; - std::cout << " URL:" << eventIn.getEventUri() << std::endl; - std::cout << " target:" << eventIn.getStringValue() << std::endl; - std::cout << " UUID:" << uuid << std::endl; - std::cout << std::endl; - - // Since we never actually open the window, send a "proxy window closed" back to webkit to keep it from leaking. - LLQtWebKit::getInstance()->proxyWindowClosed(mBrowserWindowId, uuid); - }; - - // virtual - void onClickLinkNoFollow(const EventType& eventIn) - { - std::cout << "Clink link no-follow --" << std::endl; - std::cout << " URL:" << eventIn.getEventUri() << std::endl; - std::cout << " type:" << eventIn.getNavigationType() << std::endl; - std::cout << " trusted:" << eventIn.getTrustedHost() << std::endl; - } - - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onCookieChanged( const EventType& eventIn ) - { - int dead = eventIn.getIntValue(); - std::cout << (dead?"deleting cookie: ":"setting cookie: ") << eventIn.getStringValue() << std::endl; - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - std::string onRequestFilePicker( const EventType& ) - { - std::string fn = chooseFileName(); - return fn; - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - bool onAuthRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password) - { - std::cout << "Auth request, url = " << in_url << ", realm = " << in_realm << std::endl; - out_username = ""; // replace these temporarily with site username/password as required. - out_password = ""; - return false; - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - bool onCertError(const std::string &in_url, const std::string &in_msg) - { - std::cout << "Cert error, url = " << in_url << ", message = " << in_msg << std::endl; - return false; // cancel (return true to ignore errors and continue) - } - - virtual void onQtDebugMessage( const std::string& msg, const std::string& msg_type) - { - std::cout << "QtDebugMsg [" << msg_type << "]> " << msg << std::endl; - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onLinkHovered( const EventType& eventIn ) - { - std::cout - << "Link hovered, link = " << eventIn.getEventUri() - << ", title = " << eventIn.getStringValue() - << ", text = " << eventIn.getStringValue2() - << std::endl; - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onWindowCloseRequested( const EventType& ) - { - std::cout << "Event: window close requested" << std::endl; - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onNavigateErrorPage( const EventType& event ) - { - std::cout << "Error page hit with code of " << event.getIntValue() << " - navigating to another URL" << std::endl; - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "http://bestbuy.com" ); - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onWindowGeometryChangeRequested( const EventType& eventIn) - { - int x, y, width, height; - eventIn.getRectValue(x, y, width, height); - - std::cout << "Event: window geometry change requested" << std::endl; - std::cout << " uuid: " << eventIn.getStringValue() << std::endl; - std::cout << " location: (" << x << ", " << y << ")" << std::endl; - std::cout << " size: (" << width << ", " << height << ")" << std::endl; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - int getAppWindowWidth() - { - return mAppWindowWidth; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - int getAppWindowHeight() - { - return mAppWindowHeight; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - std::string getAppWindowName() - { - return mAppWindowName; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void* getNativeWindowHandle() - { - // My implementation of the embedded browser needs a native window handle - // Can't get this via GLUT so had to use this hack - #ifdef _WINDOWS - return FindWindow( NULL, (LPCWSTR)mAppWindowName.c_str() ); - #else - #ifdef LL_OSX - // not needed on osx - return 0; - #else - //#error "You will need an implementation of this method" - return 0; - #endif - #endif - }; - - private: - int mAppWindowWidth; - int mAppWindowHeight; - int mBrowserWindowWidth; - int mBrowserWindowHeight; - int mAppTextureWidth; - int mAppTextureHeight; - GLuint mAppTexture; - int mBrowserWindowId; - std::string mAppWindowName; - std::string mHomeUrl; - std::string mCwd; - bool mNeedsUpdate; - std::string mApplicationDir; - std::string mProfileDir; - std::string mCookiePath; -}; - -testGL* theApp; - -//////////////////////////////////////////////////////////////////////////////// -// -void glutReshape( int widthIn, int heightIn ) -{ - if ( theApp ) - theApp->reshape( widthIn, heightIn ); -}; - -//////////////////////////////////////////////////////////////////////////////// -// -void glutDisplay() -{ - if ( theApp ) - theApp->display(); -}; - -//////////////////////////////////////////////////////////////////////////////// -// -void glutIdle() -{ - if ( theApp ) - theApp->idle(); -}; - -//////////////////////////////////////////////////////////////////////////////// -// -void glutKeyboard( unsigned char keyIn, int /*xIn*/, int /*yIn*/ ) -{ - if ( theApp ) - { - theApp->keyboard( keyIn, true ); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// -void glutKeyboardUp( unsigned char keyIn, int /*xIn*/, int /*yIn*/ ) -{ - if ( theApp ) - { - theApp->keyboard( keyIn, false ); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// -void glutSpecial( int specialIn, int /*xIn*/, int /*yIn*/ ) -{ - if ( theApp ) - { - theApp->keyboardSpecial( specialIn, true ); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// -void glutSpecialUp( int specialIn, int /*xIn*/, int /*yIn*/ ) -{ - if ( theApp ) - { - theApp->keyboardSpecial( specialIn, false ); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// -void glutMouseMove( int xIn , int yIn ) -{ - if ( theApp ) - theApp->mouseMove( xIn, yIn ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void glutMouseButton( int buttonIn, int stateIn, int xIn, int yIn ) -{ - if ( theApp ) - theApp->mouseButton( buttonIn, stateIn, xIn, yIn ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -int main( int argc, char* argv[] ) -{ - glutInit( &argc, argv ); - glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB ); - - // implementation in a class so we can observer events - // means we need this painful GLUT <--> class shim... - theApp = new testGL; - - if ( theApp ) - { - glutInitWindowPosition( 80, 0 ); - glutInitWindowSize( theApp->getAppWindowWidth(), theApp->getAppWindowHeight() ); - - glutCreateWindow( theApp->getAppWindowName().c_str() ); - - std::string url = ""; - if ( 2 == argc ) - url = std::string( argv[ 1 ] ); - - theApp->init( std::string( argv[ 0 ] ), url ); - - glutKeyboardFunc( glutKeyboard ); - glutKeyboardUpFunc( glutKeyboardUp ); - glutSpecialFunc( glutSpecial ); - glutSpecialUpFunc( glutSpecialUp ); - - glutMouseFunc( glutMouseButton ); - glutPassiveMotionFunc( glutMouseMove ); - glutMotionFunc( glutMouseMove ); - - glutDisplayFunc( glutDisplay ); - glutReshapeFunc( glutReshape ); - - glutIdleFunc( glutIdle ); - - glutMainLoop(); - - std::cout << "glutMainLoop returned" << std::endl; - - delete theApp; - }; - - return 0; -} diff --git a/indra/llqtwebkit/tests/testgl/testgl.pro b/indra/llqtwebkit/tests/testgl/testgl.pro deleted file mode 100644 index 42692d68d6..0000000000 --- a/indra/llqtwebkit/tests/testgl/testgl.pro +++ /dev/null @@ -1,38 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . -INCLUDEPATH += ../../ -CONFIG -= app_bundle - -QT += webkit opengl network - -!mac { -unix { - DEFINES += LL_LINUX - LIBS += -lglui -lglut - LIBS += $$PWD/../../libllqtwebkit.a -} -} - -mac { - DEFINES += LL_OSX - LIBS += -framework GLUT -framework OpenGL - LIBS += $$PWD/libllqtwebkit.dylib -} - -win32 { - DEFINES += _WINDOWS - INCLUDEPATH += ../ - INCLUDEPATH += $$PWD/../../stage/packages/include - DESTDIR=../build - release { - LIBS += $$PWD/../../Release/llqtwebkit.lib - LIBS += $$PWD/../build/freeglut_static.lib - LIBS += comdlg32.lib - } -} - -include(../../static.pri) - -SOURCES += testgl.cpp diff --git a/indra/llqtwebkit/tests/textmode/textmode.cpp b/indra/llqtwebkit/tests/textmode/textmode.cpp deleted file mode 100644 index 019fba902d..0000000000 --- a/indra/llqtwebkit/tests/textmode/textmode.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* Copyright (c) 2006-2010, Linden Research, Inc. - * - * LLQtWebKit Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in GPL-license.txt in this distribution, or online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef _WINDOWS -extern "C" { -#include -} -#endif - -#ifdef _WINDOWS -#include -#include -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef LL_OSX -// I'm not sure why STATIC_QT is getting defined, but the Q_IMPORT_PLUGIN thing doesn't seem to be necessary on the mac. -#undef STATIC_QT -#endif - -#ifdef STATIC_QT -#include -Q_IMPORT_PLUGIN(qgif) -#endif - -#include "llqtwebkit.h" - -class textMode : - public LLEmbeddedBrowserWindowObserver -{ - public: - textMode( std::string url, bool ignore_ca_file, bool ignore_ssl_errors ) : - mBrowserWindowWidth( 512 ), - mBrowserWindowHeight( 512 ), - mBrowserWindowHandle( 0 ), - mNavigateInProgress( true ), - mLogLine( "" ) - { - -#ifdef _WINDOWS - std::string cwd = std::string( _getcwd( NULL, 1024) ); - std::string profile_dir = cwd + "\\" + "textmode_profile"; - void* native_window_handle = (void*)GetDesktopWindow(); - std::string ca_file_loc = cwd + "\\" + "CA.pem"; -#else - std::string cwd = std::string( getcwd( NULL, 1024) ); - std::string profile_dir = cwd + "/" + "textmode_profile"; - void* native_window_handle = 0; - std::string ca_file_loc = cwd + "/" + "CA.pem"; -#endif - mLogLine << "Current working dir is " << cwd << std::endl; - mLogLine << "Profiles dir is " << profile_dir; - writeLine( mLogLine.str() ); - - LLQtWebKit::getInstance()->init( cwd, cwd, profile_dir, native_window_handle ); - - LLQtWebKit::getInstance()->enableQtMessageHandler( true ); - - LLQtWebKit::getInstance()->enableJavaScript( true ); - LLQtWebKit::getInstance()->enablePlugins( true ); - - mBrowserWindowHandle = LLQtWebKit::getInstance()->createBrowserWindow( mBrowserWindowWidth, mBrowserWindowHeight ); - LLQtWebKit::getInstance()->setSize( mBrowserWindowHandle, mBrowserWindowWidth, mBrowserWindowHeight ); - - LLQtWebKit::getInstance()->addObserver( mBrowserWindowHandle, this ); - - if ( ! ignore_ca_file ) - { - mLogLine.str(""); - mLogLine << "Expected certificate authority file location is " << ca_file_loc; - writeLine( mLogLine.str() ); - LLQtWebKit::getInstance()->setCAFile( ca_file_loc.c_str() ); - } - else - { - mLogLine.str(""); - mLogLine << "Not loading certificate authority file"; - writeLine( mLogLine.str() ); - }; - - if ( ignore_ssl_errors ) - { - LLQtWebKit::getInstance()->setIgnoreSSLCertErrors( true ); - mLogLine.str(""); - mLogLine << "Ignoring SSL errors"; - writeLine( mLogLine.str() ); - } - else - { - mLogLine.str(""); - mLogLine << "Not ignoring SSL errors"; - writeLine( mLogLine.str() ); - }; - - mLogLine.str(""); - mLogLine << "Navigating to " << url; - writeLine( mLogLine.str() ); - - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowHandle, url ); - }; - - bool idle( void ) - { - LLQtWebKit::getInstance()->pump( 100 ); - -#if _WINDOWS - MSG msg; - while ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) - { - GetMessage( &msg, NULL, 0, 0 ); - TranslateMessage( &msg ); - DispatchMessage( &msg ); - }; -#endif - return mNavigateInProgress; - }; - - ~textMode() - { - LLQtWebKit::getInstance()->remObserver( mBrowserWindowHandle, this ); - LLQtWebKit::getInstance()->reset(); - }; - - void onNavigateBegin( const EventType& eventIn ) - { - mNavigateInProgress = true; - mLogLine.str(""); - mLogLine << "Event: Begin navigation to " << eventIn.getEventUri(); - writeLine( mLogLine.str() ); - }; - - void onNavigateComplete( const EventType& eventIn ) - { - mLogLine.str(""); - mLogLine << "Event: End navigation to " << eventIn.getEventUri(); - writeLine( mLogLine.str() ); - mNavigateInProgress = false; - }; - - void onUpdateProgress( const EventType& eventIn ) - { - mLogLine.str(""); - mLogLine << "Event: progress value updated to " << eventIn.getIntValue(); - writeLine( mLogLine.str() ); - }; - - void onStatusTextChange( const EventType& eventIn ) - { - mLogLine.str(""); - mLogLine << "Event: status updated to " << eventIn.getStringValue(); - writeLine( mLogLine.str() ); - }; - - void onTitleChange( const EventType& eventIn ) - { - mLogLine.str(""); - mLogLine << "Event: title change to " << eventIn.getStringValue(); - writeLine( mLogLine.str() ); - }; - - void onLocationChange( const EventType& eventIn ) - { - mLogLine.str(""); - mLogLine << "Event: location changed to " << eventIn.getStringValue(); - writeLine( mLogLine.str() ); - }; - - bool onCertError(const std::string &in_url, const std::string &in_msg) - { - mLogLine.str(""); - mLogLine << "Cert error triggered: " << std::endl << in_url << "\n" << in_msg; - writeLine( mLogLine.str() ); - return true; - } - - void onCookieChanged(const EventType& event) - { - std::string url = event.getEventUri(); - std::string cookie = event.getStringValue(); - int dead = event.getIntValue(); - mLogLine.str(""); - if ( ! dead ) - mLogLine << "Cookie added:" << cookie; - else - mLogLine << "Cookie deleted:" << cookie; - writeLine( mLogLine.str() ); - } - - virtual void onQtDebugMessage( const std::string& msg, const std::string& msg_type) - { - mLogLine.str(""); - mLogLine << "QtDebugMsg (" << msg_type << "): " << msg.substr(msg.length() - 1); - writeLine( mLogLine.str() ); - } - - void writeLine( std::string line ) - { - double elapsed_seconds = (double)clock() / (double)CLOCKS_PER_SEC; - - std::cout << "[" << std::setprecision(7) << std::setw(3) << std::setfill('0') << elapsed_seconds << "] "; - const int max_len = 140; - if ( line.length() > max_len ) - { - std::cout << line.substr(0, max_len); - std::cout << "...."; - } - else - { - std::cout << line; - } - std::cout << std::endl; - //std::cout << std::endl; - } - - private: - int mBrowserWindowWidth; - int mBrowserWindowHeight; - int mBrowserWindowHandle; - bool mNavigateInProgress; - std::ostringstream mLogLine; -}; - -int main( int argc, char* argv[] ) -{ - bool ingore_ssl_errors = false; - bool ignore_ca_file = false; - - for( int i = 1; i < argc; ++i ) - { - if ( std::string( argv[ i ] ) == "--help" ) - { - std::cout << std::endl << "textmode " << std::endl; - exit( 0 ); - }; - - if ( std::string( argv[ i ] ) == "--ignoresslerrors" ) - ingore_ssl_errors = true; - - if ( std::string( argv[ i ] ) == "--ignorecafile" ) - ignore_ca_file = true; - }; - - std::string url ( "https://my.secondlife.com/callum.linden" ); - for( int i = 1; i < argc; ++i ) - { - if ( std::string( argv[ i ] ).substr( 0, 2 ) != "--" ) - { - url = std::string( argv[ i ] ); - break; - }; - }; - - textMode* app = new textMode( url, ignore_ca_file, ingore_ssl_errors ); - - bool result = app->idle(); - while( result ) - { - result = app->idle(); - }; - - delete app; - - return 0; -} diff --git a/indra/llqtwebkit/tests/textmode/textmode.pro b/indra/llqtwebkit/tests/textmode/textmode.pro deleted file mode 100644 index d41e1ea689..0000000000 --- a/indra/llqtwebkit/tests/textmode/textmode.pro +++ /dev/null @@ -1,28 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . -INCLUDEPATH += ../../ -CONFIG -= app_bundle -CONFIG += console - -QT += webkit network - -mac { - DEFINES += LL_OSX - LIBS += $$PWD/libllqtwebkit.dylib -} - -win32 { - DEFINES += _WINDOWS - INCLUDEPATH += ../ - DESTDIR=../build - LIBS += user32.lib - release { - LIBS += $$PWD/../../Release/llqtwebkit.lib - } -} - -include(../../static.pri) - -SOURCES += textmode.cpp diff --git a/indra/llqtwebkit/win32/3p-qt-vars.bat b/indra/llqtwebkit/win32/3p-qt-vars.bat deleted file mode 100644 index 5ea118848d..0000000000 --- a/indra/llqtwebkit/win32/3p-qt-vars.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off -echo Setting up a Qt environment using 3p-qt HG repository -set QTDIR=C:\Work\3p-llqtwebkit\stage -set PATH=C:\Work\3p-llqtwebkit\stage\bin;%PATH% -set QMAKESPEC=win32-msvc2010 -call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Tools\vsvars32.bat" diff --git a/indra/llqtwebkit/win32/Qt Command Prompt (3p-qt).lnk b/indra/llqtwebkit/win32/Qt Command Prompt (3p-qt).lnk deleted file mode 100644 index 460a9e9cf1..0000000000 Binary files a/indra/llqtwebkit/win32/Qt Command Prompt (3p-qt).lnk and /dev/null differ diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index b03111f7ec..029afac306 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -8,6 +8,7 @@ include(LLCommon) include(LLImage) include(LLMath) include(LLRender) +include(LLVFS) include(LLWindow) include(LLXML) include(LLVFS) @@ -18,6 +19,7 @@ include_directories( ${LLIMAGE_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} + ${LLVFS_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} @@ -82,4 +84,9 @@ endif (DARWIN) list(APPEND llrender_SOURCE_FILES ${llrender_HEADER_FILES}) add_library (llrender ${llrender_SOURCE_FILES}) -add_dependencies(llrender prepare) + +target_link_libraries( + llrender + PUBLIC + llcommon + ) diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 395b2af02e..09c76461da 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -80,18 +80,16 @@ void LLCubeMap::initGL() // Not initialized, do stuff. if (mImages[0].isNull()) { - U32 texname = 0; - - LLImageGL::generateTextures(1, &texname); + LLImageGL::GLTextureName texname = LLImageGL::createTextureName(); for (int i = 0; i < 6; i++) { mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE)); mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP); mRawImages[i] = new LLImageRaw(64, 64, 4); - mImages[i]->createGLTexture(0, mRawImages[i], texname); + mImages[i]->createGLTexture(0, mRawImages[i], &texname); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname->getTexName()); mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); } @@ -169,7 +167,7 @@ void LLCubeMap::init(const std::vector >& rawimages) } } -GLuint LLCubeMap::getGLName() +GLuint LLCubeMap::getTexName() { return mImages[0]->getTexName(); } @@ -301,7 +299,7 @@ void LLCubeMap::restoreMatrix() void LLCubeMap::setReflection (void) { - gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getGLName()); + gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getTexName()); mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP); } diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h index ee2c41e026..78975f2164 100644 --- a/indra/llrender/llcubemap.h +++ b/indra/llrender/llcubemap.h @@ -59,7 +59,7 @@ class LLCubeMap : public LLRefCount void finishPaint(); - GLuint getGLName(); + GLuint getTexName(); LLVector3 map(U8 side, U16 v_val, U16 h_val) const; BOOL project(F32& v_val, F32& h_val, BOOL& outside, diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 4547c2f618..f954d2cc8b 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -31,11 +31,8 @@ // Freetype stuff #include - -// For some reason, this won't work if it's not wrapped in the ifdef -#ifdef FT_FREETYPE_H #include FT_FREETYPE_H -#endif + #include "llerror.h" #include "llimage.h" @@ -104,7 +101,6 @@ LLFontGlyphInfo::LLFontGlyphInfo(U32 index) LLFontFreetype::LLFontFreetype() : mFontBitmapCachep(new LLFontBitmapCache), - mValid(FALSE), mAscender(0.f), mDescender(0.f), mLineHeight(0.f), @@ -112,6 +108,7 @@ LLFontFreetype::LLFontFreetype() mFTFace(NULL), mRenderGlyphCount(0), mAddGlyphCount(0), + mStyle(0), mPointSize(0) { } @@ -184,8 +181,8 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, const F32 point_size, mDescender = -mFTFace->descender * pixels_per_unit; mLineHeight = mFTFace->height * pixels_per_unit; - S32 max_char_width = ll_round(0.5f + (x_max - x_min)); - S32 max_char_height = ll_round(0.5f + (y_max - y_min)); + S32 max_char_width = ll_pos_round(0.5f + (x_max - x_min)); + S32 max_char_height = ll_pos_round(0.5f + (y_max - y_min)); mFontBitmapCachep->init(components, max_char_width, max_char_height); @@ -204,6 +201,19 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, const F32 point_size, mName = filename; mPointSize = point_size; + mStyle = LLFontGL::NORMAL; + if(mFTFace->style_flags & FT_STYLE_FLAG_BOLD) + { + mStyle |= LLFontGL::BOLD; + mStyle &= ~LLFontGL::NORMAL; + } + + if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC) + { + mStyle |= LLFontGL::ITALIC; + mStyle &= ~LLFontGL::NORMAL; + } + return TRUE; } @@ -266,7 +276,7 @@ F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return 0.0; //llassert(!mIsFallback); @@ -285,7 +295,7 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return 0.0; U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0; @@ -474,9 +484,11 @@ void LLFontFreetype::renderGlyph(const U32 glyph_index) const if (mFTFace == NULL) return; - llassert_always(! FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_DEFAULT)); - - llassert_always(! FT_Render_Glyph(mFTFace->glyph, gFontRenderMode) ); + if (FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_RENDER | FT_LOAD_TARGET_LIGHT) != 0) + { + // If glyph fails to load and/or render, render a fallback character + llassert_always(!FT_Load_Char(mFTFace, L'?', FT_LOAD_RENDER | FT_LOAD_TARGET_LIGHT)); + } mRenderGlyphCount++; } @@ -536,6 +548,16 @@ const LLPointer LLFontFreetype::getFontBitmapCache() const return mFontBitmapCachep; } +void LLFontFreetype::setStyle(U8 style) +{ + mStyle = style; +} + +U8 LLFontFreetype::getStyle() const +{ + return mStyle; +} + void LLFontFreetype::setSubImageLuminanceAlpha(const U32 x, const U32 y, const U32 bitmap_num, const U32 width, const U32 height, const U8 *data, S32 stride) const { LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num); diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index 948445835f..649fb254ba 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -93,8 +93,6 @@ class LLFontFreetype : public LLRefCount void setFallbackFonts(const font_vector_t &font); const font_vector_t &getFallbackFonts() const; - void setCharToGlyphMap(llwchar wch, U32 glyph_index) const; - // Global font metrics - in units of pixels F32 getLineHeight() const; F32 getAscenderHeight() const; @@ -140,6 +138,9 @@ class LLFontFreetype : public LLRefCount const std::string& getName() const; const LLPointer getFontBitmapCache() const; + + void setStyle(U8 style); + U8 getStyle() const; static bool sOpenGLcrashOnRestart; @@ -154,6 +155,8 @@ class LLFontFreetype : public LLRefCount std::string mName; + U8 mStyle; + F32 mPointSize; F32 mAscender; F32 mDescender; @@ -164,8 +167,6 @@ class LLFontFreetype : public LLRefCount BOOL mIsFallback; font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) - BOOL mValid; - typedef boost::unordered_map char_glyph_info_map_t; mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index ac425abade..1dea74985b 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -26,23 +26,28 @@ #include "linden_common.h" - - #include "llfontgl.h" // Linden library includes +#include "llfasttimer.h" #include "llfontfreetype.h" #include "llfontbitmapcache.h" #include "llfontregistry.h" #include "llgl.h" #include "llrender.h" -#include "v4color.h" #include "llstl.h" -#include "llfasttimer.h" +#include "v4color.h" +#include "lltexture.h" +#include "lldir.h" // Third party library includes #include +#if LL_WINDOWS +#include "llwin32headerslean.h" +#include +#endif + const S32 BOLD_OFFSET = 1; // static class members @@ -51,9 +56,9 @@ F32 LLFontGL::sHorizDPI = 96.f; F32 LLFontGL::sScaleX = 1.f; F32 LLFontGL::sScaleY = 1.f; BOOL LLFontGL::sDisplayFont = TRUE ; -std::string LLFontGL::sAppDir; +std::string LLFontGL::sFontDir; -LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f); +LLColor4U LLFontGL::sShadowColor(0, 0, 0, 255); LLFontRegistry* LLFontGL::sFontRegistry = NULL; LLCoordGL LLFontGL::sCurOrigin; @@ -69,19 +74,7 @@ const F32 PIXEL_CORRECTION_DISTANCE = 0.01f; const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f; -F32 llfont_round_x(F32 x) -{ - //return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX; - //return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY; - return x; -} - -F32 llfont_round_y(F32 y) -{ - //return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY; - //return llfloor(y+0.5f); - return y; -} +const U32 GLYPH_VERTICES = 6; LLFontGL::LLFontGL() { @@ -113,7 +106,7 @@ BOOL LLFontGL::loadFace(const std::string& filename, const F32 point_size, const return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback); } -static LLFastTimer::DeclareTimer FTM_RENDER_FONTS("Fonts"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_FONTS("Fonts"); S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_embedded, BOOL use_ellipses) const @@ -143,7 +136,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_embedded, BOOL use_ellipses) const { - LLFastTimer _(FTM_RENDER_FONTS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_FONTS); if(!sDisplayFont) //do not display texts { @@ -166,8 +159,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); - // Strip off any style bits that are already accounted for by the font. - style = style & (~getFontDesc().getStyle()); + // determine which style flags need to be added programmatically by stripping off the + // style bits that are drawn by the underlying Freetype font + U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle(); F32 drop_shadow_strength = 0.f; if (shadow != NO_SHADOW) @@ -228,10 +222,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons case LEFT: break; case RIGHT: - cur_x -= llmin(scaled_max_pixels, ll_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)); + cur_x -= llmin(scaled_max_pixels, ll_pos_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)); break; case HCENTER: - cur_x -= llmin(scaled_max_pixels, ll_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)) / 2; + cur_x -= llmin(scaled_max_pixels, ll_pos_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)) / 2; break; default: break; @@ -254,12 +248,12 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (use_ellipses && halign == LEFT) { // check for too long of a string - S32 string_width = ll_round(getWidthF32(wstr, begin_offset, max_chars) * sScaleX); + S32 string_width = ll_pos_round(getWidthF32(wstr, begin_offset, max_chars) * sScaleX); if (string_width > scaled_max_pixels) { // use four dots for ellipsis width to generate padding const LLWString dots(utf8str_to_wstring(std::string("...."))); - scaled_max_pixels = llmax(0, scaled_max_pixels - ll_round(getWidthF32(dots.c_str()))); + scaled_max_pixels = llmax(0, scaled_max_pixels - ll_pos_round(getWidthF32(dots.c_str()))); draw_ellipses = TRUE; } } @@ -267,9 +261,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons const LLFontGlyphInfo* next_glyph = NULL; const S32 GLYPH_BATCH_SIZE = 30; - static LL_ALIGN_16(LLVector4a vertices[GLYPH_BATCH_SIZE * 4]); - static LLVector2 uvs[GLYPH_BATCH_SIZE * 4]; - static LLColor4U colors[GLYPH_BATCH_SIZE * 4]; + static LL_ALIGN_16(LLVector4a vertices[GLYPH_BATCH_SIZE * GLYPH_VERTICES]); + static LLVector2 uvs[GLYPH_BATCH_SIZE * GLYPH_VERTICES]; + static LLColor4U colors[GLYPH_BATCH_SIZE * GLYPH_VERTICES]; LLColor4U text_color(color); @@ -314,18 +308,18 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (glyph_count > 0) { - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * GLYPH_VERTICES); } gGL.end(); glyph_count = 0; } renderQuad(vertices, uvs, colors, screen_rect, uv_rect, LLColor4U::white, 0); //No batching here. It will never happen. - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, 4); + gGL.vertexBatchPreTransformed(vertices, uvs, colors, GLYPH_VERTICES); } gGL.end(); @@ -370,9 +364,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons // otherwise the queued glyphs will be taken from wrong textures. if (glyph_count > 0) { - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * GLYPH_VERTICES); } gGL.end(); glyph_count = 0; @@ -403,16 +397,16 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (glyph_count >= GLYPH_BATCH_SIZE) { - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * GLYPH_VERTICES); } gGL.end(); glyph_count = 0; } - drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style, shadow, drop_shadow_strength); + drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style_to_add, shadow, drop_shadow_strength); chars_drawn++; cur_x += fgi->mXAdvance; @@ -440,9 +434,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if(glyph_count) { - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * GLYPH_VERTICES); } gGL.end(); } @@ -453,7 +447,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons *right_x = (cur_x - origin.mV[VX]) / sScaleX; } - if (style & UNDERLINE) + //FIXME: add underline as glyph? + if (style_to_add & UNDERLINE) { F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight()); @@ -475,7 +470,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons (cur_x - origin.mV[VX]) / sScaleX, (F32)y, color, LEFT, valign, - style, + style_to_add, shadow, S32_MAX, max_pixels, right_x, @@ -506,7 +501,7 @@ F32 LLFontGL::getDescenderHeight() const F32 LLFontGL::getLineHeight() const { - return (F32)ll_round(mFontFreetype->getLineHeight() / sScaleY); + return (F32)ll_pos_round(mFontFreetype->getLineHeight() / sScaleY); } S32 LLFontGL::getWidth(const std::string& utf8text, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const @@ -517,7 +512,7 @@ S32 LLFontGL::getWidth(const std::string& utf8text, const S32 begin_offset, cons S32 LLFontGL::getWidth(const LLWString& utf32text, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const { F32 width = getWidthF32(utf32text, begin_offset, max_chars, use_embedded); - return ll_round(width); + return ll_pos_round(width); } F32 LLFontGL::getWidthF32(const std::string& utf8text, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const @@ -582,7 +577,7 @@ F32 LLFontGL::getWidthF32(const LLWString& utf32text, const S32 begin_offset, co } } // Round after kerning. - cur_x = (F32)ll_round(cur_x); + cur_x = (F32)ll_pos_round(cur_x); } } @@ -698,7 +693,7 @@ S32 LLFontGL::maxDrawableChars(const LLWString& utf32text, F32 max_pixels, S32 m } } // Round after kerning. - cur_x = (F32)ll_round(cur_x); + cur_x = (F32)ll_pos_round(cur_x); drawn_x = cur_x; } @@ -785,7 +780,7 @@ S32 LLFontGL::firstDrawableChar(const LLWString& utf32text, F32 max_pixels, S32 } // Round after kerning. - total_width = (F32)ll_round(total_width); + total_width = (F32)ll_pos_round(total_width); } if (drawable_chars == 0) @@ -872,7 +867,7 @@ S32 LLFontGL::charFromPixelOffset(const LLWString& utf32text, const S32 begin_of // Round after kerning. - cur_x = (F32)ll_round(cur_x); + cur_x = (F32)ll_pos_round(cur_x); } @@ -940,18 +935,18 @@ void LLFontGL::removeEmbeddedChar( llwchar wc ) const } // static -void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector& xui_paths, bool create_gl_textures) +void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures) { sVertDPI = (F32)llfloor(screen_dpi * y_scale); sHorizDPI = (F32)llfloor(screen_dpi * x_scale); sScaleX = x_scale; sScaleY = y_scale; - sAppDir = app_dir; + sFontDir = app_dir; // Font registry init if (!sFontRegistry) { - sFontRegistry = new LLFontRegistry(xui_paths,create_gl_textures); + sFontRegistry = new LLFontRegistry(create_gl_textures); sFontRegistry->parseFontInfo("fonts.xml"); } else @@ -1006,7 +1001,7 @@ void LLFontGL::destroyAllGL() // static U8 LLFontGL::getStyleFromString(const std::string &style) { - S32 ret = 0; + U8 ret = 0; if (style.find("NORMAL") != style.npos) { ret |= NORMAL; @@ -1124,6 +1119,7 @@ LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name) //else leave baseline return gl_vfont_align; } + //static LLFontGL* LLFontGL::getFontMonospace() { @@ -1212,59 +1208,67 @@ LLFontGL* LLFontGL::getFontDefault() return getFontSansSerif(); // Fallback to sans serif as default font } +static std::string sSystemFontPath; // static std::string LLFontGL::getFontPathSystem() { - std::string system_path; + if (!sSystemFontPath.empty()) return sSystemFontPath; - // Try to figure out where the system's font files are stored. - char *system_root = NULL; #if LL_WINDOWS - system_root = getenv("SystemRoot"); /* Flawfinder: ignore */ - if (!system_root) + wchar_t* pPath = nullptr; + if (SHGetKnownFolderPath(FOLDERID_Fonts, 0, nullptr, &pPath) == S_OK) { - LL_WARNS() << "SystemRoot not found, attempting to load fonts from default path." << LL_ENDL; - } -#endif - - if (system_root) - { - system_path = llformat("%s/fonts/", system_root); + sSystemFontPath = ll_convert_wide_to_string(pPath, CP_UTF8) + gDirUtilp->getDirDelimiter(); + LL_INFOS() << "from SHGetKnownFolderPath(): " << sSystemFontPath << LL_ENDL; + CoTaskMemFree(pPath); + pPath = nullptr; } else { -#if LL_WINDOWS - // HACK for windows 98/Me - system_path = "/WINDOWS/FONTS/"; + // Try to figure out where the system's font files are stored. + auto system_root = LLStringUtil::getenv("SystemRoot"); + if (! system_root.empty()) + { + sSystemFontPath = gDirUtilp->add(system_root, "fonts") + gDirUtilp->getDirDelimiter(); + LL_INFOS() << "from SystemRoot: " << sSystemFontPath << LL_ENDL; + } + else + { + LL_WARNS() << "SystemRoot not found, attempting to load fonts from default path." << LL_ENDL; + // HACK for windows 98/Me + sSystemFontPath = "/WINDOWS/FONTS/"; + } + } + #elif LL_DARWIN // HACK for Mac OS X - system_path = "/System/Library/Fonts/"; + sSystemFontPath = "/System/Library/Fonts/"; #endif - } - return system_path; + return sSystemFontPath; } +static std::string sLocalFontPath; // static std::string LLFontGL::getFontPathLocal() { - std::string local_path; + if (!sLocalFontPath.empty()) return sLocalFontPath; // Backup files if we can't load from system fonts directory. // We could store this in an end-user writable directory to allow // end users to switch fonts. - if (LLFontGL::sAppDir.length()) + if (!LLFontGL::sFontDir.empty()) { // use specified application dir to look for fonts - local_path = LLFontGL::sAppDir + "/fonts/"; + sLocalFontPath = gDirUtilp->add(LLFontGL::sFontDir, "fonts") + gDirUtilp->getDirDelimiter(); } else { // assume working directory is executable directory - local_path = "./fonts/"; + sLocalFontPath = "./fonts/"; } - return local_path; + return sLocalFontPath; } LLFontGL::LLFontGL(const LLFontGL &source) @@ -1282,13 +1286,23 @@ void LLFontGL::renderQuad(LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* { S32 index = 0; + vertex_out[index].set(screen_rect.mLeft, screen_rect.mTop, 0.f); + uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); + colors_out[index] = color; + index++; + + vertex_out[index].set(screen_rect.mLeft + slant_amt, screen_rect.mBottom, 0.f); + uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); + colors_out[index] = color; + index++; + vertex_out[index].set(screen_rect.mRight, screen_rect.mTop, 0.f); uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); colors_out[index] = color; index++; - vertex_out[index].set(screen_rect.mLeft, screen_rect.mTop, 0.f); - uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); + vertex_out[index].set(screen_rect.mRight, screen_rect.mTop, 0.f); + uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); colors_out[index] = color; index++; @@ -1316,13 +1330,14 @@ void LLFontGL::drawGlyph(S32& glyph_count, LLVector4a* vertex_out, LLVector2* uv LLRectf screen_rect_offset = screen_rect; screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f); - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, color, slant_offset); + const U32 idx = glyph_count * GLYPH_VERTICES; + renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx], screen_rect_offset, uv_rect, color, slant_offset); glyph_count++; } } else if (shadow == DROP_SHADOW_SOFT) { - LLColor4U shadow_color = LLFontGL::sShadowColor; + LLColor4U& shadow_color = LLFontGL::sShadowColor; shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH); for (S32 pass = 0; pass < 5; pass++) { @@ -1347,26 +1362,31 @@ void LLFontGL::drawGlyph(S32& glyph_count, LLVector4a* vertex_out, LLVector2* uv break; } - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, shadow_color, slant_offset); + const U32 idx = glyph_count * GLYPH_VERTICES; + renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx], screen_rect_offset, uv_rect, shadow_color, slant_offset); glyph_count++; } - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset); + const U32 idx = glyph_count * GLYPH_VERTICES; + renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx], screen_rect, uv_rect, color, slant_offset); glyph_count++; } else if (shadow == DROP_SHADOW) { - LLColor4U shadow_color = LLFontGL::sShadowColor; + LLColor4U& shadow_color = LLFontGL::sShadowColor; shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength); LLRectf screen_rect_shadow = screen_rect; screen_rect_shadow.translate(1.f, -1.f); - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_shadow, uv_rect, shadow_color, slant_offset); + U32 idx = glyph_count * GLYPH_VERTICES; + renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx], screen_rect_shadow, uv_rect, shadow_color, slant_offset); glyph_count++; - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset); + idx = glyph_count * GLYPH_VERTICES; + renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx], screen_rect, uv_rect, color, slant_offset); glyph_count++; } else // normal rendering { - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset); + const U32 idx = glyph_count * GLYPH_VERTICES; + renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx], screen_rect, uv_rect, color, slant_offset); glyph_count++; } } diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 6300f67ab9..4c1d409be6 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -30,7 +30,7 @@ #include "llcoord.h" #include "llfontregistry.h" -#include "lltexture.h" +#include "llimagegl.h" #include "llpointer.h" #include "llrect.h" #include "v2math.h" @@ -152,7 +152,7 @@ class LLFontGL void addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& label) const; void removeEmbeddedChar( llwchar wc ) const; - static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector& xui_paths, bool create_gl_textures = true); + static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures = true); // Load sans-serif, sans-serif-small, etc. // Slow, requires multiple seconds to load fonts. @@ -206,14 +206,16 @@ class LLFontGL static F32 sCurDepth; static std::vector > sOriginStack; - static LLColor4 sShadowColor; + // Singu Note: LLColor4U to avoid converting from LLColor4 to LLColor4U for every glyph(batch). + static LLColor4U sShadowColor; static F32 sVertDPI; static F32 sHorizDPI; static F32 sScaleX; static F32 sScaleY; static BOOL sDisplayFont ; - static std::string sAppDir; // For loading fonts + static std::string sFontDir; // For loading fonts + private: friend class LLFontRegistry; friend class LLTextBillboard; @@ -234,7 +236,6 @@ class LLFontGL // Registry holds all instantiated fonts. static LLFontRegistry* sFontRegistry; - }; #endif diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 53e3a1c576..7e11477e8d 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -34,13 +34,15 @@ #include "llcontrol.h" #include "lldir.h" #include "llwindow.h" +#include "llxmlnode.h" extern LLControlGroup gSavedSettings; using std::string; using std::map; -bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc); +bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc); +bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node); LLFontDescriptor::LLFontDescriptor(): mStyle(0) @@ -163,14 +165,9 @@ LLFontDescriptor LLFontDescriptor::normalize() const return LLFontDescriptor(new_name,new_size,new_style,getFileNames()); } -LLFontRegistry::LLFontRegistry(const string_vec_t& xui_paths, - bool create_gl_textures) +LLFontRegistry::LLFontRegistry(bool create_gl_textures) : mCreateGLTextures(create_gl_textures) { - // Propagate this down from LLUICtrlFactory so LLRender doesn't - // need an upstream dependency on LLUI. - mXUIPaths = xui_paths; - // This is potentially a slow directory traversal, so we want to // cache the result. mUltimateFallbackList = LLWindow::getDynamicFallbackFontList(); @@ -183,23 +180,27 @@ LLFontRegistry::~LLFontRegistry() bool LLFontRegistry::parseFontInfo(const std::string& xml_filename) { - bool success = false; // Succeed if we find at least one XUI file - const string_vec_t& xml_paths = mXUIPaths; + bool success = false; // Succeed if we find and read at least one XUI file + const string_vec_t xml_paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_filename); + if (xml_paths.empty()) + { + // We didn't even find one single XUI file + return false; + } + for (string_vec_t::const_iterator path_it = xml_paths.begin(); path_it != xml_paths.end(); ++path_it) { LLXMLNodePtr root; - std::string full_filename = gDirUtilp->findSkinnedFilename(*path_it, xml_filename); - bool parsed_file = LLXMLNode::parseFile(full_filename, root, NULL); + bool parsed_file = LLXMLNode::parseFile(*path_it, root, NULL); if (!parsed_file) continue; if ( root.isNull() || ! root->hasName( "fonts" ) ) { - LL_WARNS() << "Bad font info file: " - << full_filename << LL_ENDL; + LL_WARNS() << "Bad font info file: " << *path_it << LL_ENDL; continue; } @@ -208,12 +209,12 @@ bool LLFontRegistry::parseFontInfo(const std::string& xml_filename) if (root->hasName("fonts")) { // Expect a collection of children consisting of "font" or "font_size" entries - bool init_succ = initFromXML(root); + bool init_succ = init_from_xml(this, root); success = success || init_succ; } } - if (success) - dump(); + //if (success) + // dump(); return success; } @@ -224,14 +225,14 @@ std::string currentOsName() return "Windows"; #elif LL_DARWIN return "Mac"; -#elif LL_SDL +#elif LL_SDL || LL_MESA_HEADLESS return "Linux"; #else return ""; #endif } -bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc) +bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc) { if (node->hasName("font")) { @@ -264,14 +265,14 @@ bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc) { if (child_name == currentOsName()) { - fontDescInitFromXML(child, desc); + font_desc_init_from_xml(child, desc); } } } return true; } -bool LLFontRegistry::initFromXML(LLXMLNodePtr node) +bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node) { LLXMLNodePtr child; @@ -282,17 +283,17 @@ bool LLFontRegistry::initFromXML(LLXMLNodePtr node) if (child->hasName("font")) { LLFontDescriptor desc; - bool font_succ = fontDescInitFromXML(child, desc); + bool font_succ = font_desc_init_from_xml(child, desc); LLFontDescriptor norm_desc = desc.normalize(); if (font_succ) { // if this is the first time we've seen this font name, // create a new template map entry for it. - const LLFontDescriptor *match_desc = getMatchingFontDesc(desc); + const LLFontDescriptor *match_desc = registry->getMatchingFontDesc(desc); if (match_desc == NULL) { // Create a new entry (with no corresponding font). - mFontMap[norm_desc] = NULL; + registry->mFontMap[norm_desc] = NULL; } // otherwise, find the existing entry and combine data. else @@ -307,8 +308,8 @@ bool LLFontRegistry::initFromXML(LLXMLNodePtr node) desc.getFileNames().end()); LLFontDescriptor new_desc = *match_desc; new_desc.getFileNames() = match_file_names; - mFontMap.erase(*match_desc); - mFontMap[new_desc] = NULL; + registry->mFontMap.erase(*match_desc); + registry->mFontMap[new_desc] = NULL; } } } @@ -319,7 +320,7 @@ bool LLFontRegistry::initFromXML(LLXMLNodePtr node) if (child->getAttributeString("name",size_name) && child->getAttributeF32("size",size_value)) { - mFontSizes[size_name] = size_value; + registry->mFontSizes[size_name] = size_value; } } @@ -425,7 +426,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) LLFontFreetype::font_vector_t fontlist; LLFontGL *result = NULL; - // Snarf all fonts we can into fontlistp. First will get pulled + // Snarf all fonts we can into fontlist. First will get pulled // off the list and become the "head" font, set to non-fallback. // Rest will consitute the fallback list. BOOL is_first_found = TRUE; @@ -440,7 +441,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) ++file_name_it) { LLFontGL *fontp = new LLFontGL; - std::string font_path = local_path + *file_name_it; + std::string font_path = gDirUtilp->add(local_path, *file_name_it); // *HACK: Fallback fonts don't render, so we can use that to suppress // creation of OpenGL textures for test apps. JC BOOL is_fallback = !is_first_found || !mCreateGLTextures; @@ -448,12 +449,12 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) if (!fontp->loadFace(font_path, extra_scale * point_size, LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback)) { - font_path = sys_path + *file_name_it; + font_path = gDirUtilp->add(sys_path, *file_name_it); if (!fontp->loadFace(font_path, extra_scale * point_size, LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback)) { - LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << *file_name_it << LL_ENDL; + LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << *file_name_it << " from path " << font_path << LL_ENDL; delete fontp; fontp = NULL; } @@ -490,6 +491,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) { LL_WARNS() << "createFont failed in some way" << LL_ENDL; } + mFontMap[norm_desc] = result; return result; } @@ -532,19 +534,19 @@ void LLFontRegistry::destroyGL() LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& orig_desc) { - LLFontDescriptor norm_desc = orig_desc.normalize(); + LLFontDescriptor desc = orig_desc.normalize(); - font_reg_map_t::iterator it = mFontMap.find(norm_desc); + font_reg_map_t::iterator it = mFontMap.find(desc); if (it != mFontMap.end()) return it->second; else { - LLFontGL *fontp = createFont(orig_desc); + LLFontGL *fontp = createFont(desc); if (!fontp) { - LL_WARNS() << "getFont failed, name " << orig_desc.getName() - <<" style=[" << ((S32) orig_desc.getStyle()) << "]" - << " size=[" << orig_desc.getSize() << "]" << LL_ENDL; + LL_WARNS() << "getFont failed, name " << desc.getName() + <<" style=[" << ((S32) desc.getStyle()) << "]" + << " size=[" << desc.getSize() << "]" << LL_ENDL; } return fontp; } diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h index 8b06191c56..177eb6c8a5 100644 --- a/indra/llrender/llfontregistry.h +++ b/indra/llrender/llfontregistry.h @@ -28,7 +28,7 @@ #ifndef LL_LLFONTREGISTRY_H #define LL_LLFONTREGISTRY_H -#include "llxmlnode.h" +#include "llpointer.h" class LLFontGL; @@ -65,15 +65,14 @@ class LLFontDescriptor class LLFontRegistry { public: + friend bool init_from_xml(LLFontRegistry*, LLPointer); // create_gl_textures - set to false for test apps with no OpenGL window, // such as llui_libtest - LLFontRegistry(const string_vec_t& xui_paths, - bool create_gl_textures); + LLFontRegistry(bool create_gl_textures); ~LLFontRegistry(); // Load standard font info from XML file(s). bool parseFontInfo(const std::string& xml_filename); - bool initFromXML(LLXMLNodePtr node); // Clear cached glyphs for all fonts. void reset(); @@ -95,6 +94,7 @@ class LLFontRegistry const string_vec_t& getUltimateFallbackList() const; private: + LLFontRegistry(const LLFontRegistry& other); // no-copy LLFontGL *createFont(const LLFontDescriptor& desc); typedef std::map font_reg_map_t; typedef std::map font_size_map_t; @@ -105,7 +105,6 @@ class LLFontRegistry font_size_map_t mFontSizes; string_vec_t mUltimateFallbackList; - string_vec_t mXUIPaths; bool mCreateGLTextures; }; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 3ed54f0ca9..c6b99ba673 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -72,6 +72,12 @@ void* gl_get_proc_address(const char *pStr) } #undef GLH_EXT_GET_PROC_ADDRESS #define GLH_EXT_GET_PROC_ADDRESS(p) gl_get_proc_address(p) +#undef GLH_EXT_GET_PROC_ADDRESS_CORE +#define GLH_EXT_GET_PROC_ADDRESS_CORE(ver, p) gl_get_proc_address((mGLVersion >= ver) ? p : p"ARB") +#undef GLH_EXT_GET_PROC_ADDRESS_CORE_EXT +#define GLH_EXT_GET_PROC_ADDRESS_CORE_EXT(ver, p) gl_get_proc_address((mGLVersion >= ver) ? p : p"EXT") +#undef GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB +#define GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(ver, p, arb) gl_get_proc_address((mGLVersion >= ver) ? p : arb) #endif //!LL_DARWIN #if GL_ARB_debug_output @@ -94,9 +100,84 @@ void APIENTRY gl_debug_callback(GLenum source, } else { - LL_WARNS() << "----- GL WARNING -------" << LL_ENDL; + if (severity == GL_DEBUG_SEVERITY_MEDIUM_ARB) + { + LL_WARNS() << "----- GL WARNING MEDIUM --------" << LL_ENDL; + } + else if (severity == GL_DEBUG_SEVERITY_LOW_ARB) + { + if (type == GL_DEBUG_TYPE_OTHER_ARB) + { + if (id == 0x20004 || // Silence nvidia glClear noop messages + id == 0x20043 || // Silence nvidia CSAA messages. + id == 0x20084 // Silence nvidia texture mapping with no base level messages. + ) + { + return; + } + } + + LL_WARNS() << "----- GL WARNING LOW --------" << LL_ENDL; + } + else if (severity == 0x826b && id == 0x20071 && type == GL_DEBUG_TYPE_OTHER_ARB && source == GL_DEBUG_SOURCE_API_ARB) + { + // Silence nvidia buffer detail info. + return; + } + } + + std::string sourcestr = "Unknown"; + switch (source) + { + case GL_DEBUG_SOURCE_API_ARB: + sourcestr = "OpenGL"; + break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: + sourcestr = "Window manager"; + break; + case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: + sourcestr = "Shader compiler"; + break; + case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: + sourcestr = "3rd party"; + break; + case GL_DEBUG_SOURCE_APPLICATION_ARB: + sourcestr = "Application"; + break; + case GL_DEBUG_SOURCE_OTHER_ARB: + sourcestr = "Other"; + break; + default: + break; + } + + std::string typestr = "Unknown"; + switch (type) + { + case GL_DEBUG_TYPE_ERROR_ARB: + typestr = "Error"; + break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: + typestr = "Deprecated behavior"; + break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: + typestr = "Undefined behavior"; + break; + case GL_DEBUG_TYPE_PORTABILITY_ARB: + typestr = "Portability"; + break; + case GL_DEBUG_TYPE_PERFORMANCE_ARB: + typestr = "Performance"; + break; + case GL_DEBUG_TYPE_OTHER_ARB: + typestr = "Other"; + break; + default: + break; } - LL_WARNS() << "Type: " << std::hex << type << std::dec << LL_ENDL; + + LL_WARNS() << "Source: " << sourcestr << " (" << std::hex << source << std::dec << ")" << LL_ENDL; + LL_WARNS() << "Type: " << typestr << " (" << std::hex << type << std::dec << ")" << LL_ENDL; LL_WARNS() << "ID: " << std::hex << id << std::dec<< LL_ENDL; LL_WARNS() << "Severity: " << std::hex << severity << std::dec << LL_ENDL; LL_WARNS() << "Message: " << message << LL_ENDL; @@ -151,13 +232,59 @@ LLMatrix4 gGLObliqueProjectionInverse; std::list LLGLUpdate::sGLQ; -#if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS -// ATI prototypes +#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS #if LL_WINDOWS -PFNGLGETSTRINGIPROC glGetStringi = NULL; +PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; +PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB = NULL; +PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL; +PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; +PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL; + +// GL_ARB_multitexture +PFNGLMULTITEXCOORD1DARBPROC glMultiTexCoord1dARB = NULL; +PFNGLMULTITEXCOORD1DVARBPROC glMultiTexCoord1dvARB = NULL; +PFNGLMULTITEXCOORD1FARBPROC glMultiTexCoord1fARB = NULL; +PFNGLMULTITEXCOORD1FVARBPROC glMultiTexCoord1fvARB = NULL; +PFNGLMULTITEXCOORD1IARBPROC glMultiTexCoord1iARB = NULL; +PFNGLMULTITEXCOORD1IVARBPROC glMultiTexCoord1ivARB = NULL; +PFNGLMULTITEXCOORD1SARBPROC glMultiTexCoord1sARB = NULL; +PFNGLMULTITEXCOORD1SVARBPROC glMultiTexCoord1svARB = NULL; +PFNGLMULTITEXCOORD2DARBPROC glMultiTexCoord2dARB = NULL; +PFNGLMULTITEXCOORD2DVARBPROC glMultiTexCoord2dvARB = NULL; +PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB = NULL; +PFNGLMULTITEXCOORD2FVARBPROC glMultiTexCoord2fvARB = NULL; +PFNGLMULTITEXCOORD2IARBPROC glMultiTexCoord2iARB = NULL; +PFNGLMULTITEXCOORD2IVARBPROC glMultiTexCoord2ivARB = NULL; +PFNGLMULTITEXCOORD2SARBPROC glMultiTexCoord2sARB = NULL; +PFNGLMULTITEXCOORD2SVARBPROC glMultiTexCoord2svARB = NULL; +PFNGLMULTITEXCOORD3DARBPROC glMultiTexCoord3dARB = NULL; +PFNGLMULTITEXCOORD3DVARBPROC glMultiTexCoord3dvARB = NULL; +PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3fARB = NULL; +PFNGLMULTITEXCOORD3FVARBPROC glMultiTexCoord3fvARB = NULL; +PFNGLMULTITEXCOORD3IARBPROC glMultiTexCoord3iARB = NULL; +PFNGLMULTITEXCOORD3IVARBPROC glMultiTexCoord3ivARB = NULL; +PFNGLMULTITEXCOORD3SARBPROC glMultiTexCoord3sARB = NULL; +PFNGLMULTITEXCOORD3SVARBPROC glMultiTexCoord3svARB = NULL; +PFNGLMULTITEXCOORD4DARBPROC glMultiTexCoord4dARB = NULL; +PFNGLMULTITEXCOORD4DVARBPROC glMultiTexCoord4dvARB = NULL; +PFNGLMULTITEXCOORD4FARBPROC glMultiTexCoord4fARB = NULL; +PFNGLMULTITEXCOORD4FVARBPROC glMultiTexCoord4fvARB = NULL; +PFNGLMULTITEXCOORD4IARBPROC glMultiTexCoord4iARB = NULL; +PFNGLMULTITEXCOORD4IVARBPROC glMultiTexCoord4ivARB = NULL; +PFNGLMULTITEXCOORD4SARBPROC glMultiTexCoord4sARB = NULL; +PFNGLMULTITEXCOORD4SVARBPROC glMultiTexCoord4svARB = NULL; +PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL; +PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = NULL; #endif +#if LL_LINUX_NV_GL_HEADERS +// linux nvidia headers. these define these differently to mesa's. ugh. +PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL; +PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = NULL; +PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL; +#endif // LL_LINUX_NV_GL_HEADERS + // vertex blending prototypes PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB = NULL; PFNGLVERTEXBLENDARBPROC glVertexBlendARB = NULL; @@ -186,6 +313,15 @@ PFNGLISVERTEXARRAYPROC glIsVertexArray = NULL; PFNGLMAPBUFFERRANGEPROC glMapBufferRange = NULL; PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange = NULL; +// GL_ARB_texture_compression +PFNGLCOMPRESSEDTEXIMAGE3DARBPROC glCompressedTexImage3DARB = NULL; +PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB = NULL; +PFNGLCOMPRESSEDTEXIMAGE1DARBPROC glCompressedTexImage1DARB = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC glCompressedTexSubImage3DARB = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC glCompressedTexSubImage2DARB = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC glCompressedTexSubImage1DARB = NULL; +PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB = NULL; + // GL_ARB_sync PFNGLFENCESYNCPROC glFenceSync = NULL; PFNGLISSYNCPROC glIsSync = NULL; @@ -199,21 +335,6 @@ PFNGLGETSYNCIVPROC glGetSynciv = NULL; PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE = NULL; PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE = NULL; -// vertex object prototypes -PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI = NULL; -PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI = NULL; -PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI = NULL; -PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI = NULL; -PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI = NULL; -PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI = NULL; -PFNGLARRAYOBJECTATIPROC glArrayObjectATI = NULL; -PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI = NULL; -PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI = NULL; -PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI = NULL; -PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI = NULL; -PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI = NULL; -PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI = NULL; - // GL_ARB_occlusion_query PFNGLGENQUERIESARBPROC glGenQueriesARB = NULL; PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB = NULL; @@ -223,6 +344,7 @@ PFNGLENDQUERYARBPROC glEndQueryARB = NULL; PFNGLGETQUERYIVARBPROC glGetQueryivARB = NULL; PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB = NULL; PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB = NULL; +PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64vEXT = NULL; // GL_ARB_point_parameters PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB = NULL; @@ -275,8 +397,8 @@ PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL; PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL; //shader object prototypes -PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL; -PFNGLGETHANDLEARBPROC glGetHandleARB = NULL; +PFNGLDELETEOBJECTARBPROC glDeleteShader = NULL; +PFNGLDELETEOBJECTARBPROC glDeleteProgram = NULL; PFNGLDETACHOBJECTARBPROC glDetachObjectARB = NULL; PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL; PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL; @@ -306,9 +428,10 @@ PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB = NULL; PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB = NULL; PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv = NULL; PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB = NULL; -PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB = NULL; -PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB = NULL; -PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL; +PFNGLGETOBJECTPARAMETERIVARBPROC glGetShaderiv = NULL; +PFNGLGETOBJECTPARAMETERIVARBPROC glGetProgramiv = NULL; +PFNGLGETINFOLOGARBPROC glGetShaderInfoLog = NULL; +PFNGLGETINFOLOGARBPROC glGetProgramInfoLog = NULL; PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB = NULL; PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL; PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB = NULL; @@ -317,12 +440,7 @@ PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL; PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL; PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = NULL; -#if LL_WINDOWS -PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; -#endif - // vertex shader prototypes -#if LL_LINUX || LL_SOLARIS PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB = NULL; PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB = NULL; PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB = NULL; @@ -341,15 +459,13 @@ PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB = NULL; PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB = NULL; PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB = NULL; PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB = NULL; -#endif // LL_LINUX || LL_SOLARIS -PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB = NULL; -PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB = NULL; -PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB = NULL; -PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB = NULL; -PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB = NULL; -PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB = NULL; -PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB = NULL; -#if LL_LINUX || LL_SOLARIS +PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4NbvARB = NULL; +PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4NivARB = NULL; +PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4NsvARB = NULL; +PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4NubARB = NULL; +PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4NubvARB = NULL; +PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4NuivARB = NULL; +PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4NusvARB = NULL; PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB = NULL; PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB = NULL; PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB = NULL; @@ -387,21 +503,9 @@ PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB = NULL; PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB = NULL; PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB = NULL; PFNGLISPROGRAMARBPROC glIsProgramARB = NULL; -#endif // LL_LINUX || LL_SOLARIS PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB = NULL; PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB = NULL; PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL; - -#if LL_WINDOWS -PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; -#endif - -#if LL_LINUX_NV_GL_HEADERS -// linux nvidia headers. these define these differently to mesa's. ugh. -PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL; -PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = NULL; -PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL; -#endif // LL_LINUX_NV_GL_HEADERS #endif // (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS LLGLManager gGLManager; @@ -425,7 +529,6 @@ LLGLManager::LLGLManager() : mHasVertexArrayObject(FALSE), mHasMapBufferRange(FALSE), mHasFlushBufferRange(FALSE), - mHasPBuffer(FALSE), mHasShaderObjects(FALSE), mHasVertexShader(FALSE), mHasFragmentShader(FALSE), @@ -434,7 +537,6 @@ LLGLManager::LLGLManager() : mHasOcclusionQuery2(FALSE), mHasPointParameters(FALSE), mHasDrawBuffers(FALSE), - mHasTextureRectangle(FALSE), mHasTransformFeedback(FALSE), mMaxIntegerSamples(0), @@ -443,12 +545,14 @@ LLGLManager::LLGLManager() : mHasCubeMap(FALSE), mHasDebugOutput(FALSE), + mHasGpuShader5(FALSE), mHasAdaptiveVsync(FALSE), mHasTextureSwizzle(FALSE), mIsATI(FALSE), mIsNVIDIA(FALSE), mIsIntel(FALSE), + mIsHD3K(FALSE), mIsGF2or4MX(FALSE), mIsGF3(FALSE), mIsGFFX(FALSE), @@ -459,8 +563,6 @@ LLGLManager::LLGLManager() : #endif mHasRequirements(TRUE), - mHasSeparateSpecularColor(FALSE), - mDebugGPU(FALSE), mDriverVersionMajor(1), @@ -476,45 +578,114 @@ LLGLManager::LLGLManager() : { } +std::set sGLExtensions; // Not techincally safe to issue this before context is created. +#if LL_WINDOWS +std::set sWGLExtensions; // Fine (probably) without context. +#endif +void registerExtension(std::string ext, std::set& extensions) +{ + extensions.emplace(ext); + LL_INFOS("GLExtensions") << ext << LL_ENDL; +} +void loadExtensionStrings() +{ + sGLExtensions.clear(); + U32 gl_version = atoi((const char*)glGetString(GL_VERSION)); + if (gl_version >= 3) + { +#ifndef LL_DARWIN + PFNGLGETSTRINGIPROC glGetStringi = (PFNGLGETSTRINGIPROC)GLH_EXT_GET_PROC_ADDRESS("glGetStringi"); +#endif + GLint count = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &count); + for (GLint i = 0; i < count; ++i) + { + registerExtension((char const*)glGetStringi(GL_EXTENSIONS, i), sGLExtensions); + } + } + else // Deprecated. + { + typedef boost::tokenizer > tokenizer; + boost::char_separator sep(" "); + std::string extensions((const char*)glGetString(GL_EXTENSIONS)); + for (auto& extension : tokenizer(extensions, sep)) + { + registerExtension(extension, sGLExtensions); + } + } +} +#if LL_WINDOWS +void loadWGLExtensionStrings() +{ + sWGLExtensions.clear(); + PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); + if (wglGetExtensionsStringARB) + { + typedef boost::tokenizer > tokenizer; + boost::char_separator sep(" "); + std::string extensions = std::string(wglGetExtensionsStringARB(wglGetCurrentDC())); + for (auto& extension : tokenizer(extensions, sep)) + { + registerExtension(extension, sWGLExtensions); + } + } +} +#endif + +bool ExtensionExists(std::string ext) +{ + auto* extensions = &sGLExtensions; +#if LL_WINDOWS + if (ext.rfind("WGL_", 0) == 0) + { + extensions = &sWGLExtensions; + if (extensions->empty()) + loadWGLExtensionStrings(); + } + else +#endif + if (extensions->empty()) + loadExtensionStrings(); + bool found = extensions->find(ext) != extensions->end(); + if (!found) + LL_INFOS("GLExtensions") << ext << " MISSING" << LL_ENDL; + return found; +} + //--------------------------------------------------------------------- // Global initialization for GL //--------------------------------------------------------------------- void LLGLManager::initWGL() { - mHasPBuffer = FALSE; #if LL_WINDOWS && !LL_MESA_HEADLESS - if (!glh_init_extensions("WGL_ARB_pixel_format")) + loadWGLExtensionStrings(); + if (ExtensionExists("WGL_ARB_pixel_format")) + { + wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetProcAddress("wglGetPixelFormatAttribivARB"); + wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); + } + else { LL_WARNS("RenderInit") << "No ARB pixel format extensions" << LL_ENDL; } - - if (ExtensionExists("WGL_ARB_create_context",gGLHExts.mSysExts)) + + if (ExtensionExists("WGL_ARB_create_context")) { - GLH_EXT_NAME(wglCreateContextAttribsARB) = (PFNWGLCREATECONTEXTATTRIBSARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateContextAttribsARB"); + wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); } else { LL_WARNS("RenderInit") << "No ARB create context extensions" << LL_ENDL; } - if (ExtensionExists("WGL_EXT_swap_control", gGLHExts.mSysExts)) + if (ExtensionExists("WGL_EXT_swap_control")) { - GLH_EXT_NAME(wglSwapIntervalEXT) = (PFNWGLSWAPINTERVALEXTPROC)GLH_EXT_GET_PROC_ADDRESS("wglSwapIntervalEXT"); + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); } - - if( !glh_init_extensions("WGL_ARB_pbuffer") ) - { - LL_WARNS("RenderInit") << "No ARB WGL PBuffer extensions" << LL_ENDL; - } - - if( !glh_init_extensions("WGL_ARB_render_texture") ) + else { - LL_WARNS("RenderInit") << "No ARB WGL render texture extensions" << LL_ENDL; + LL_WARNS("RenderInit") << "No ARB swap control extensions" << LL_ENDL; } - - mHasPBuffer = ExtensionExists("WGL_ARB_pbuffer", gGLHExts.mSysExts) && - ExtensionExists("WGL_ARB_render_texture", gGLHExts.mSysExts) && - ExtensionExists("WGL_ARB_pixel_format", gGLHExts.mSysExts); #endif } @@ -528,40 +699,7 @@ bool LLGLManager::initGL() stop_glerror(); -#if LL_WINDOWS - if (!glGetStringi) - { - glGetStringi = (PFNGLGETSTRINGIPROC) GLH_EXT_GET_PROC_ADDRESS("glGetStringi"); - } - - //reload extensions string (may have changed after using wglCreateContextAttrib) - if (glGetStringi) - { - std::stringstream str; - - GLint count = 0; - glGetIntegerv(GL_NUM_EXTENSIONS, &count); - for (GLint i = 0; i < count; ++i) - { - std::string ext((const char*) glGetStringi(GL_EXTENSIONS, i)); - str << ext << " "; - LL_DEBUGS("GLExtensions") << ext << LL_ENDL; - } - - { - PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0; - wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); - if(wglGetExtensionsStringARB) - { - str << (const char*) wglGetExtensionsStringARB(wglGetCurrentDC()); - } - } - - free(gGLHExts.mSysExts); - std::string extensions = str.str(); - gGLHExts.mSysExts = strdup(extensions.c_str()); - } -#endif + loadExtensionStrings(); stop_glerror(); @@ -594,27 +732,19 @@ bool LLGLManager::initGL() } #endif } - - if (mGLVersion >= 2.1f && LLImageGL::sCompressTextures) - { //use texture compression - glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); - } - else - { //GL version is < 3.0, always disable texture compression - LLImageGL::sCompressTextures = false; - } // Trailing space necessary to keep "nVidia Corpor_ati_on" cards // from being recognized as ATI. - if (mGLVendor.substr(0,4) == "ATI ") + if (mGLVendor.substr(0,4) == "ATI " +//#if LL_LINUX +// // The Mesa-based drivers put this in the Renderer string, +// // not the Vendor string. +// || mGLRenderer.find("AMD") != std::string::npos +//#endif //LL_LINUX + ) { mGLVendorShort = "ATI"; - // "mobile" appears to be unused, and this code was causing warnings. - //BOOL mobile = FALSE; - //if (mGLRenderer.find("MOBILITY") != std::string::npos) - //{ - // mobile = TRUE; - //} + // *TODO: Fix this? mIsATI = TRUE; #if LL_WINDOWS && !LL_MESA_HEADLESS @@ -675,6 +805,14 @@ bool LLGLManager::initGL() { mGLVendorShort = "INTEL"; mIsIntel = TRUE; +#if LL_WINDOWS + if (mGLRenderer.find("HD") != std::string::npos + && ((mGLRenderer.find("2000") != std::string::npos || mGLRenderer.find("3000") != std::string::npos) + || (mGLVersion == 3.1f && mGLRenderer.find("INTEL(R) HD GRAPHICS") != std::string::npos))) + { + mIsHD3K = TRUE; + } +#endif } else { @@ -682,10 +820,18 @@ bool LLGLManager::initGL() } stop_glerror(); - // This is called here because it depends on the setting of mIsGF2or4MX, and sets up mHasMultitexture. initExtensions(); stop_glerror(); + if (mGLVersion >= 2.1f && mHasCompressedTextures && LLImageGL::sCompressTextures) + { //use texture compression + glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); + } + else + { //GL version is < 3.0, always disable texture compression + LLImageGL::sCompressTextures = false; + } + S32 old_vram = mVRAM; if (mHasATIMemInfo) @@ -722,10 +868,15 @@ bool LLGLManager::initGL() { //According to the spec, the resulting value should never be less than 512. We need at least 1024 to use skinned shaders. glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &mGLMaxVertexUniformComponents); + if (mIsHD3K) + { + mGLMaxVertexUniformComponents = llmax(mGLMaxVertexUniformComponents, 4096); + } } if (LLRender::sGLCoreProfile) { + // If core is true, then mNumTextureUnits is pretty much unused. mNumTextureUnits = llmin(mNumTextureImageUnits, MAX_GL_TEXTURE_UNITS); } else if (mHasMultitexture) @@ -760,8 +911,10 @@ bool LLGLManager::initGL() #if LL_WINDOWS if (mHasDebugOutput && gDebugGL) { //setup debug output callback + glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallbackARB((GLDEBUGPROCARB) gl_debug_callback, NULL); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, true); } #endif stop_glerror(); @@ -804,12 +957,9 @@ void LLGLManager::getGLInfo(LLSD& info) info["GLInfo"]["GLVersion"] = std::string((const char *)glGetString(GL_VERSION)); #if !LL_MESA_HEADLESS - std::string all_exts = ll_safe_string((const char *)gGLHExts.mSysExts); - boost::char_separator sep(" "); - boost::tokenizer > tok(all_exts, sep); - for(boost::tokenizer >::iterator i = tok.begin(); i != tok.end(); ++i) + for (auto& extension : sGLExtensions) { - info["GLInfo"]["GLExtensions"].append(*i); + info["GLInfo"]["GLExtensions"].append(extension); } #endif } @@ -823,9 +973,11 @@ std::string LLGLManager::getGLInfoString() info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n"); #if !LL_MESA_HEADLESS - std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts)); - LLStringUtil::replaceChar(all_exts, ' ', '\n'); - info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n"); + info_str += std::string("GL_EXTENSIONS:\n"); + for (auto& extension : sGLExtensions) + { + info_str += extension + "\n"; + } #endif return info_str; @@ -837,10 +989,13 @@ void LLGLManager::printGLInfoString() LL_INFOS("RenderInit") << "GL_RENDERER: " << ((const char *)glGetString(GL_RENDERER)) << LL_ENDL; LL_INFOS("RenderInit") << "GL_VERSION: " << ((const char *)glGetString(GL_VERSION)) << LL_ENDL; -#if !LL_MESA_HEADLESS - std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts)); - LLStringUtil::replaceChar(all_exts, ' ', '\n'); - LL_DEBUGS("RenderInit") << "GL_EXTENSIONS:\n" << all_exts << LL_ENDL; +#if !LL_MESA_HEADLESS + LL_DEBUGS("RenderInit") << "GL_EXTENSIONS:" << "\n"; + for (auto& extension : sGLExtensions) + { + LL_CONT << extension << "\n"; + } + LL_CONT << LL_ENDL; #endif } @@ -913,7 +1068,6 @@ void LLGLManager::initExtensions() mHasBlendFuncSeparate = FALSE; # endif // GL_EXT_blend_func_separate mHasMipMapGeneration = FALSE; - mHasSeparateSpecularColor = FALSE; mHasAnisotropic = FALSE; mHasCubeMap = FALSE; mHasOcclusionQuery = FALSE; @@ -921,60 +1075,61 @@ void LLGLManager::initExtensions() mHasShaderObjects = FALSE; mHasVertexShader = FALSE; mHasFragmentShader = FALSE; - mHasTextureRectangle = FALSE; -#else // LL_MESA_HEADLESS //important, gGLHExts.mSysExts is uninitialized until after glh_init_extensions is called - mHasMultitexture = glh_init_extensions("GL_ARB_multitexture"); - mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts); - mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts); - mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color"); - mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic"); - glh_init_extensions("GL_ARB_texture_cube_map"); - mHasCubeMap = ExtensionExists("GL_ARB_texture_cube_map", gGLHExts.mSysExts); - mHasARBEnvCombine = ExtensionExists("GL_ARB_texture_env_combine", gGLHExts.mSysExts); - mHasCompressedTextures = glh_init_extensions("GL_ARB_texture_compression"); - mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts); - mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts); - mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts); - mHasVertexArrayObject = ExtensionExists("GL_ARB_vertex_array_object", gGLHExts.mSysExts); - mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts); - mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts); - mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts); - mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts); +#ifdef GL_ARB_gpu_shader5 + mHasGpuShader5 = FALSE; +#endif +#else // LL_MESA_HEADLESS + mHasMultitexture = mGLVersion >= 1.3f || ExtensionExists("GL_ARB_multitexture"); + mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo"); + mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info"); + mHasCompressedTextures = mGLVersion >= 1.3 || ExtensionExists("GL_ARB_texture_compression"); + mHasAnisotropic = mGLVersion >= 4.6f || ExtensionExists("GL_EXT_texture_filter_anisotropic"); + mHasCubeMap = mGLVersion >= 1.3f || ExtensionExists("GL_ARB_texture_cube_map"); + mHasARBEnvCombine = mGLVersion >= 2.1f || ExtensionExists("GL_ARB_texture_env_combine"); + mHasOcclusionQuery = mGLVersion >= 1.5f || ExtensionExists("GL_ARB_occlusion_query"); + mHasOcclusionQuery2 = mGLVersion >= 3.3f || ExtensionExists("GL_ARB_occlusion_query2"); + mHasVertexBufferObject = mGLVersion >= 1.5f || ExtensionExists("GL_ARB_vertex_buffer_object"); + mHasVertexArrayObject = mGLVersion >= 3.f || ExtensionExists("GL_ARB_vertex_array_object"); + mHasSync = mGLVersion >= 3.2f || ExtensionExists("GL_ARB_sync"); + mHasMapBufferRange = mGLVersion >= 3.f || ExtensionExists("GL_ARB_map_buffer_range"); + mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range"); + mHasDepthClamp = mGLVersion >= 3.2f || ExtensionExists("GL_ARB_depth_clamp") || ExtensionExists("GL_NV_depth_clamp"); // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad #ifdef GL_ARB_framebuffer_object - mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts); + mHasFramebufferObject = mGLVersion >= 3.f || ExtensionExists("GL_ARB_framebuffer_object"); #else - mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts) && - ExtensionExists("GL_EXT_framebuffer_blit", gGLHExts.mSysExts) && - ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts) && - ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); + mHasFramebufferObject = mGLVersion >= 3.f || (ExtensionExists("GL_EXT_framebuffer_object") && + ExtensionExists("GL_EXT_framebuffer_blit") && + ExtensionExists("GL_EXT_framebuffer_multisample") && + ExtensionExists("GL_EXT_packed_depth_stencil")); #endif - mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts); + mHasFramebufferMultisample = mGLVersion >= 3.f || (mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample")); mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f; - mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); - mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts); - mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts); - mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts); - mHasTransformFeedback = mGLVersion >= 4.f || ExtensionExists("GL_EXT_transform_feedback", gGLHExts.mSysExts); + mHasDrawBuffers = mGLVersion >= 2.f || ExtensionExists("GL_ARB_draw_buffers"); + mHasBlendFuncSeparate = mGLVersion >= 1.4f || ExtensionExists("GL_EXT_blend_func_separate"); + mHasDebugOutput = mGLVersion >= 4.3f || ExtensionExists("GL_ARB_debug_output"); + mHasTransformFeedback = mGLVersion >= 4.f || ExtensionExists("GL_EXT_transform_feedback"); #if !LL_DARWIN - mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); + mHasPointParameters = mGLVersion >= 2.f || (!mIsATI && ExtensionExists("GL_ARB_point_parameters")); #endif - mHasShaderObjects = ExtensionExists("GL_ARB_shader_objects", gGLHExts.mSysExts) && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts)); - mHasVertexShader = ExtensionExists("GL_ARB_vertex_program", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_vertex_shader", gGLHExts.mSysExts) - && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts)); - mHasFragmentShader = ExtensionExists("GL_ARB_fragment_shader", gGLHExts.mSysExts) && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts)); + mHasShaderObjects = mGLVersion >= 2.f || ExtensionExists("GL_ARB_shader_objects") && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100")); + mHasVertexShader = mGLVersion >= 2.f || (ExtensionExists("GL_ARB_vertex_program") && ExtensionExists("GL_ARB_vertex_shader") + && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100"))); + mHasFragmentShader = mGLVersion >= 2.f || ExtensionExists("GL_ARB_fragment_shader") && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100")); +#endif +#ifdef GL_ARB_gpu_shader5 + mHasGpuShader5 = mGLVersion >= 4.f || ExtensionExists("GL_ARB_gpu_shader5");; #endif - #if LL_WINDOWS - mHasAdaptiveVsync = ExtensionExists("WGL_EXT_swap_control_tear", gGLHExts.mSysExts); + mHasAdaptiveVsync = ExtensionExists("WGL_EXT_swap_control_tear"); #elif LL_LINUX - mHasAdaptiveVsync = ExtensionExists("GLX_EXT_swap_control_tear", gGLHExts.mSysExts); + mHasAdaptiveVsync = ExtensionExists("GLX_EXT_swap_control_tear"); #endif #ifdef GL_ARB_texture_swizzle - mHasTextureSwizzle = ExtensionExists("GL_ARB_texture_swizzle", gGLHExts.mSysExts); + mHasTextureSwizzle = mGLVersion >= 3.3f || ExtensionExists("GL_ARB_texture_swizzle"); #endif #if LL_LINUX || LL_SOLARIS @@ -993,7 +1148,6 @@ void LLGLManager::initExtensions() mHasDrawBuffers = FALSE; mHasBlendFuncSeparate = FALSE; mHasMipMapGeneration = FALSE; - mHasSeparateSpecularColor = FALSE; mHasAnisotropic = FALSE; mHasCubeMap = FALSE; mHasOcclusionQuery = FALSE; @@ -1034,7 +1188,6 @@ void LLGLManager::initExtensions() if (strchr(blacklist,'d')) mHasMipMapGeneration = FALSE;//S // if (strchr(blacklist,'f')) mHasNVVertexArrayRange = FALSE;//S // if (strchr(blacklist,'g')) mHasNVFence = FALSE;//S - if (strchr(blacklist,'h')) mHasSeparateSpecularColor = FALSE; if (strchr(blacklist,'i')) mHasAnisotropic = FALSE;//S if (strchr(blacklist,'j')) mHasCubeMap = FALSE;//S // if (strchr(blacklist,'k')) mHasATIVAO = FALSE;//S @@ -1046,7 +1199,6 @@ void LLGLManager::initExtensions() if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE; - if (strchr(blacklist,'t')) mHasTextureRectangle = FALSE; if (strchr(blacklist,'u')) mHasBlendFuncSeparate = FALSE;//S if (strchr(blacklist,'v')) mHasDepthClamp = FALSE; @@ -1065,10 +1217,6 @@ void LLGLManager::initExtensions() { LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_texture_env_combine" << LL_ENDL; } - if (!mHasSeparateSpecularColor) - { - LL_INFOS("RenderInit") << "Couldn't initialize separate specular color" << LL_ENDL; - } if (!mHasAnisotropic) { LL_INFOS("RenderInit") << "Couldn't initialize anisotropic filtering" << LL_ENDL; @@ -1128,23 +1276,72 @@ void LLGLManager::initExtensions() glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange); glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange); -#if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS +#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL; +#if LL_WINDOWS + if (mHasMultitexture) + { + glMultiTexCoord1dARB = (PFNGLMULTITEXCOORD1DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord1d"); + glMultiTexCoord1dvARB = (PFNGLMULTITEXCOORD1DVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord1dv"); + glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord1f"); + glMultiTexCoord1fvARB = (PFNGLMULTITEXCOORD1FVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord1fv"); + glMultiTexCoord1iARB = (PFNGLMULTITEXCOORD1IARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord1i"); + glMultiTexCoord1ivARB = (PFNGLMULTITEXCOORD1IVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord1iv"); + glMultiTexCoord1sARB = (PFNGLMULTITEXCOORD1SARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord1s"); + glMultiTexCoord1svARB = (PFNGLMULTITEXCOORD1SVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord1sv"); + glMultiTexCoord2dARB = (PFNGLMULTITEXCOORD2DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord2d"); + glMultiTexCoord2dvARB = (PFNGLMULTITEXCOORD2DVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord2dv"); + glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord2f"); + glMultiTexCoord2fvARB = (PFNGLMULTITEXCOORD2FVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord2fv"); + glMultiTexCoord2iARB = (PFNGLMULTITEXCOORD2IARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord2i"); + glMultiTexCoord2ivARB = (PFNGLMULTITEXCOORD2IVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord2iv"); + glMultiTexCoord2sARB = (PFNGLMULTITEXCOORD2SARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord2s"); + glMultiTexCoord2svARB = (PFNGLMULTITEXCOORD2SVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord2sv"); + glMultiTexCoord3dARB = (PFNGLMULTITEXCOORD3DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord3d"); + glMultiTexCoord3dvARB = (PFNGLMULTITEXCOORD3DVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord3dv"); + glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord3f"); + glMultiTexCoord3fvARB = (PFNGLMULTITEXCOORD3FVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord3fv"); + glMultiTexCoord3iARB = (PFNGLMULTITEXCOORD3IARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord3i"); + glMultiTexCoord3ivARB = (PFNGLMULTITEXCOORD3IVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord3iv"); + glMultiTexCoord3sARB = (PFNGLMULTITEXCOORD3SARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord3s"); + glMultiTexCoord3svARB = (PFNGLMULTITEXCOORD3SVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord3sv"); + glMultiTexCoord4dARB = (PFNGLMULTITEXCOORD4DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord4d"); + glMultiTexCoord4dvARB = (PFNGLMULTITEXCOORD4DVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord4dv"); + glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord4f"); + glMultiTexCoord4fvARB = (PFNGLMULTITEXCOORD4FVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord4fv"); + glMultiTexCoord4iARB = (PFNGLMULTITEXCOORD4IARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord4i"); + glMultiTexCoord4ivARB = (PFNGLMULTITEXCOORD4IVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord4iv"); + glMultiTexCoord4sARB = (PFNGLMULTITEXCOORD4SARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord4s"); + glMultiTexCoord4svARB = (PFNGLMULTITEXCOORD4SVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glMultiTexCoord4sv"); + glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glActiveTexture"); + glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glClientActiveTexture"); + } +#endif + if (mHasCompressedTextures) + { + glCompressedTexImage3DARB = (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glCompressedTexImage3D"); + glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glCompressedTexImage2D"); + glCompressedTexImage1DARB = (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glCompressedTexImage1D"); + glCompressedTexSubImage3DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glCompressedTexSubImage3D"); + glCompressedTexSubImage2DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glCompressedTexSubImage2D"); + glCompressedTexSubImage1DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glCompressedTexSubImage1D"); + glGetCompressedTexImageARB = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.3, "glGetCompressedTexImage"); + } if (mHasVertexBufferObject) { - glBindBufferARB = (PFNGLBINDBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBufferARB"); + glBindBufferARB = (PFNGLBINDBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.5, "glBindBuffer"); if (glBindBufferARB) { - glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteBuffersARB"); - glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenBuffersARB"); - glIsBufferARB = (PFNGLISBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsBufferARB"); - glBufferDataARB = (PFNGLBUFFERDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferDataARB"); - glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferSubDataARB"); - glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferSubDataARB"); - glMapBufferARB = (PFNGLMAPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMapBufferARB"); - glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glUnmapBufferARB"); - glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferParameterivARB"); - glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferPointervARB"); + glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.5, "glDeleteBuffers"); + glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.5, "glGenBuffers"); + glIsBufferARB = (PFNGLISBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.5, "glIsBuffer"); + glBufferDataARB = (PFNGLBUFFERDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.5, "glBufferData"); + glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.5, "glBufferSubData"); + glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.5, "glGetBufferSubData"); + glMapBufferARB = (PFNGLMAPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.5, "glMapBuffer"); + glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.5, "glUnmapBuffer"); + glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.5, "glGetBufferParameteriv"); + glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.5, "glGetBufferPointerv"); } else { @@ -1199,27 +1396,27 @@ void LLGLManager::initExtensions() } if (mHasDrawBuffers) { - glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDrawBuffersARB"); + glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glDrawBuffers"); } if (mHasBlendFuncSeparate) { - glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT"); + glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)GLH_EXT_GET_PROC_ADDRESS_CORE_EXT(1.4, "glBlendFuncSeparate"); } if (mHasTransformFeedback) { - glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback"); - glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback"); - glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings"); - glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange"); + glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS_CORE_EXT(4.0, "glBeginTransformFeedback"); + glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS_CORE_EXT(4.0, "glEndTransformFeedback"); + glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)GLH_EXT_GET_PROC_ADDRESS_CORE_EXT(4.0, "glTransformFeedbackVaryings"); + glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS_CORE_EXT(3.0, "glBindBufferRange"); } if (mHasDebugOutput) { - glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControlARB"); - glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageInsertARB"); - glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageCallbackARB"); - glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetDebugMessageLogARB"); + glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(4.3, "glDebugMessageControl"); + glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(4.3, "glDebugMessageInsert"); + glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(4.3, "glDebugMessageCallback"); + glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(4.3, "glGetDebugMessageLog"); } -#if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS +#if !LL_LINUX || LL_LINUX_NV_GL_HEADERS // This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements"); if (!glDrawRangeElements) @@ -1230,140 +1427,125 @@ void LLGLManager::initExtensions() #endif // !LL_LINUX || LL_LINUX_NV_GL_HEADERS #if LL_LINUX_NV_GL_HEADERS // nvidia headers are critically different from mesa-esque - glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveTextureARB"); - glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glClientActiveTextureARB"); + glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveTexture"); + glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glClientActiveTexture"); #endif // LL_LINUX_NV_GL_HEADERS if (mHasOcclusionQuery) { LL_INFOS() << "initExtensions() OcclusionQuery-related procs..." << LL_ENDL; - glGenQueriesARB = (PFNGLGENQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenQueriesARB"); - glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteQueriesARB"); - glIsQueryARB = (PFNGLISQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsQueryARB"); - glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginQueryARB"); - glEndQueryARB = (PFNGLENDQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glEndQueryARB"); - glGetQueryivARB = (PFNGLGETQUERYIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryivARB"); - glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectivARB"); - glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectuivARB"); + glGenQueriesARB = (PFNGLGENQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.4, "glGenQueries"); + glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.4, "glDeleteQueries"); + glIsQueryARB = (PFNGLISQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.4, "glIsQuery"); + glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.4, "glBeginQuery"); + glEndQueryARB = (PFNGLENDQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.4, "glEndQuery"); + glGetQueryivARB = (PFNGLGETQUERYIVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.4, "glGetQueryiv"); + glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.4, "glGetQueryObjectiv"); + glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(1.4, "glGetQueryObjectuiv"); } +#if !LL_DARWIN + glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)GLH_EXT_GET_PROC_ADDRESS_CORE_EXT(3.2, "glGetQueryObjectui64v"); +#endif if (mHasPointParameters) { LL_INFOS() << "initExtensions() PointParameters-related procs..." << LL_ENDL; - glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfARB"); - glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvARB"); + glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glPointParameterf"); + glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glPointParameterfv"); } if (mHasShaderObjects) { - glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteObjectARB"); - glGetHandleARB = (PFNGLGETHANDLEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetHandleARB"); - glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDetachObjectARB"); - glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateShaderObjectARB"); - glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glShaderSourceARB"); - glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCompileShaderARB"); - glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateProgramObjectARB"); - glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glAttachObjectARB"); - glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glLinkProgramARB"); - glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUseProgramObjectARB"); - glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glValidateProgramARB"); - glUniform1fARB = (PFNGLUNIFORM1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fARB"); - glUniform2fARB = (PFNGLUNIFORM2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fARB"); - glUniform3fARB = (PFNGLUNIFORM3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fARB"); - glUniform4fARB = (PFNGLUNIFORM4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fARB"); - glUniform1iARB = (PFNGLUNIFORM1IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1iARB"); - glUniform2iARB = (PFNGLUNIFORM2IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2iARB"); - glUniform3iARB = (PFNGLUNIFORM3IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3iARB"); - glUniform4iARB = (PFNGLUNIFORM4IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4iARB"); - glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fvARB"); - glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fvARB"); - glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fvARB"); - glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fvARB"); - glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1ivARB"); - glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2ivARB"); - glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3ivARB"); - glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4ivARB"); - glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2fvARB"); - glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3fvARB"); - glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x4fv"); - glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4fvARB"); - glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterfvARB"); - glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterivARB"); - glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInfoLogARB"); - glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttachedObjectsARB"); - glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformLocationARB"); - glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformARB"); - glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformfvARB"); - glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformivARB"); - glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetShaderSourceARB"); + glDeleteShader = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glDeleteShader", "glDeleteObjectARB"); + glDeleteProgram = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glDeleteProgram", "glDeleteObjectARB"); + glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glDetachShader", "glDetachObjectARB"); + glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glCreateShader", "glCreateShaderObjectARB"); + glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glShaderSource"); + glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glCompileShader"); + glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glCreateProgram", "glCreateProgramObjectARB"); + glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glAttachShader", "glAttachObjectARB"); + glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glLinkProgram"); + glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glUseProgram", "glUseProgramObjectARB"); + glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glValidateProgram"); + glUniform1fARB = (PFNGLUNIFORM1FARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform1f"); + glUniform2fARB = (PFNGLUNIFORM2FARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform2f"); + glUniform3fARB = (PFNGLUNIFORM3FARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform3f"); + glUniform4fARB = (PFNGLUNIFORM4FARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform4f"); + glUniform1iARB = (PFNGLUNIFORM1IARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform1i"); + glUniform2iARB = (PFNGLUNIFORM2IARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform2i"); + glUniform3iARB = (PFNGLUNIFORM3IARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform3i"); + glUniform4iARB = (PFNGLUNIFORM4IARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform4i"); + glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform1fv"); + glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform2fv"); + glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform3fv"); + glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform4fv"); + glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform1iv"); + glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform2iv"); + glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform3iv"); + glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniform4iv"); + glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniformMatrix2fv"); + glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniformMatrix3fv"); + glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.1, "glUniformMatrix3x4fv"); + glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glUniformMatrix4fv"); + glGetShaderiv = (PFNGLGETOBJECTPARAMETERIVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glGetShaderiv", "glGetObjectParameteriv"); + glGetProgramiv = (PFNGLGETOBJECTPARAMETERIVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glGetProgramiv", "glGetObjectParameteriv"); + glGetShaderInfoLog = (PFNGLGETINFOLOGARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glGetShaderInfoLog", "glGetInfoLog"); + glGetProgramInfoLog = (PFNGLGETINFOLOGARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glGetProgramInfoLog", "glGetInfoLog"); + glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE_OR_ARB(2.0, "glGetAttachedShaders", "glGetAttachedObjects"); + glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glGetUniformLocation"); + glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glGetActiveUniform"); + glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glGetUniformfv"); + glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glGetUniformiv"); + glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glGetShaderSource"); } if (mHasVertexShader) { LL_INFOS() << "initExtensions() VertexShader-related procs..." << LL_ENDL; - glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB"); - glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB"); - glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttribARB"); - glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dARB"); - glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvARB"); - glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fARB"); - glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvARB"); - glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sARB"); - glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svARB"); - glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dARB"); - glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvARB"); - glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fARB"); - glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvARB"); - glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sARB"); - glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svARB"); - glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dARB"); - glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvARB"); - glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fARB"); - glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvARB"); - glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sARB"); - glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svARB"); - glVertexAttrib4nbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nbvARB"); - glVertexAttrib4nivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nivARB"); - glVertexAttrib4nsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nsvARB"); - glVertexAttrib4nubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubARB"); - glVertexAttrib4nubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubvARB"); - glVertexAttrib4nuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nuivARB"); - glVertexAttrib4nusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nusvARB"); - glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bvARB"); - glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dARB"); - glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvARB"); - glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fARB"); - glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvARB"); - glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ivARB"); - glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sARB"); - glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svARB"); - glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvARB"); - glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB"); - glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB"); - glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB"); - glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer"); - glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB"); - glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB"); - glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB"); - glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindProgramARB"); - glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsARB"); - glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGenProgramsARB"); - glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dARB"); - glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dvARB"); - glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fARB"); - glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fvARB"); - glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dARB"); - glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dvARB"); - glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fARB"); - glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fvARB"); - glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterdvARB"); - glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterfvARB"); - glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterdvARB"); - glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterfvARB"); - glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramivARB"); - glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringARB"); - glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvARB"); - glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvARB"); - glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivARB"); - glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glgetVertexAttribPointervARB"); - glIsProgramARB = (PFNGLISPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glIsProgramARB"); + glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glGetAttribLocation"); + glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glBindAttribLocation"); + glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glGetActiveAttrib"); + glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib1d"); + glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib1dv"); + glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib1f"); + glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib1fv"); + glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib1s"); + glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib1sv"); + glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib2d"); + glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib2dv"); + glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib2f"); + glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib2fv"); + glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib2s"); + glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib2sv"); + glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib3d"); + glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib3dv"); + glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib3f"); + glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib3fv"); + glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib3s"); + glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib3sv"); + glVertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4Nbv"); + glVertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4Niv"); + glVertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4Nsv"); + glVertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4Nub"); + glVertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4Nubv"); + glVertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4Nuiv"); + glVertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4Nusv"); + glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4bv"); + glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4d"); + glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4dv"); + glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4f"); + glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4fv"); + glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4iv"); + glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4s"); + glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4sv"); + glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4ubv"); + glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4uiv"); + glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttrib4usv"); + glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glVertexAttribPointer"); + glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(3.0, "glVertexAttribIPointer"); + glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glEnableVertexAttribArray"); + glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glDisableVertexAttribArray"); + glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glGetVertexAttribdv"); + glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glGetVertexAttribfv"); + glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glGetVertexAttribiv"); + glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC)GLH_EXT_GET_PROC_ADDRESS_CORE(2.0, "glGetVertexAttribPointerv"); } LL_DEBUGS("RenderInit") << "GL Probe: Got symbols" << LL_ENDL; #endif @@ -1506,33 +1688,49 @@ void clear_glerror() // // Static members -boost::unordered_map LLGLState::sStateMap; +std::vector LLGLStateValidator::sStateDataVec; GLboolean LLGLDepthTest::sDepthEnabled = GL_FALSE; // OpenGL default GLenum LLGLDepthTest::sDepthFunc = GL_LESS; // OpenGL default GLboolean LLGLDepthTest::sWriteEnabled = GL_TRUE; // OpenGL default //static -void LLGLState::initClass() +void LLGLStateValidator::initClass() { - sStateMap[GL_DITHER] = GL_TRUE; - // sStateMap[GL_TEXTURE_2D] = GL_TRUE; - + stop_glerror(); + + gGL.setSceneBlendType(LLRender::BT_ALPHA); //make sure multisample defaults to disabled - sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE; glDisable(GL_MULTISAMPLE_ARB); + stop_glerror(); + for (auto data : sStateDataVec) + { + llassert_always(data->depth == 0); + llassert_always(data->activeInstance == nullptr); + if (data->disabler && *data->disabler) + { + continue; + } + const char* stateStr = data->stateStr; + LLGLenum state = data->state; + LLGLboolean cur_state = data->currentState; + llassert_always_msg(cur_state == glIsEnabled(state), llformat("%s expected %s", stateStr, cur_state ? "TRUE" : "FALSE")); + } + const bool old = gDebugGL; + gDebugGL = true; + checkStates(); + gDebugGL = old; } //static -void LLGLState::restoreGL() +void LLGLStateValidator::restoreGL() { - sStateMap.clear(); initClass(); } //static // Really shouldn't be needed, but seems we sometimes do. -void LLGLState::resetTextureStates() +void LLGLStateValidator::resetTextureStates() { gGL.flush(); GLint maxTextureUnits; @@ -1546,35 +1744,60 @@ void LLGLState::resetTextureStates() } } -void LLGLState::dumpStates() +void LLGLStateValidator::dumpStates() { LL_INFOS("RenderState") << "GL States:" << LL_ENDL; - for (boost::unordered_map::iterator iter = sStateMap.begin(); - iter != sStateMap.end(); ++iter) + for (auto data : sStateDataVec) { - LL_INFOS("RenderState") << llformat(" 0x%04x : %s",(S32)iter->first,iter->second?"TRUE":"FALSE") << LL_ENDL; + LL_INFOS("RenderState") << llformat("%s : %s", data->stateStr, data->currentState ? "TRUE" : "FALSE") << LL_ENDL; } } -void LLGLState::checkStates(const std::string& msg) +void LLGLStateValidator::checkState(LLGLStateStaticData& data) { - if (!gDebugGL) + if (gDebugGL) + { + if (data.disabler && *data.disabler) + { + return; + } + if (!gDebugSession) + { + llassert_always(data.currentState == (bool)glIsEnabled(data.state)); + } + else + { + if (data.currentState != (bool)glIsEnabled(data.state)) + { + ll_fail(llformat("GL enabled state for %s does not match expected state of %s.", data.stateStr, data.currentState ? "TRUE" : "FALSE")); + } + } + } +} + +bool LLGLStateValidator::registerStateData(LLGLStateStaticData& data) +{ + sStateDataVec.emplace_back(&data); + return true; +} + +void LLGLStateValidator::checkStates(const std::string& msg) +{ + if (!gDebugGL || gGLManager.mIsDisabled) { return; } stop_glerror(); - GLint src; - GLint dst; - glGetIntegerv(GL_BLEND_SRC, &src); - glGetIntegerv(GL_BLEND_DST, &dst); + GLint src = gGL.getContextSnapshot().blendColorSFactor; + GLint dst = gGL.getContextSnapshot().blendColorDFactor; stop_glerror(); BOOL error = FALSE; - if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) + if (src != LLRender::BF_SOURCE_ALPHA || dst != LLRender::BF_ONE_MINUS_SOURCE_ALPHA) { if (gDebugSession) { @@ -1587,11 +1810,15 @@ void LLGLState::checkStates(const std::string& msg) } } - for (boost::unordered_map::iterator iter = sStateMap.begin(); - iter != sStateMap.end(); ++iter) + for (auto data : sStateDataVec) { - LLGLenum state = iter->first; - LLGLboolean cur_state = iter->second; + if (data->disabler && *data->disabler) + { + continue; + } + const char* stateStr = data->stateStr; + LLGLenum state = data->state; + LLGLboolean cur_state = data->currentState; stop_glerror(); LLGLboolean gl_state = glIsEnabled(state); stop_glerror(); @@ -1600,24 +1827,24 @@ void LLGLState::checkStates(const std::string& msg) dumpStates(); if (gDebugSession) { - gFailLog << llformat("LLGLState error. State: 0x%04x",state) << std::endl; + gFailLog << llformat("LLGLState error. State: %s 0x%04x. Expected %s", stateStr, state, cur_state ? "TRUE" : "FALSE") << std::endl; error = TRUE; } else { - LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL; + LL_GL_ERRS << llformat("LLGLState error. State: %s 0x%04x. Expected %s", stateStr, state, cur_state ? "TRUE" : "FALSE") << LL_ENDL; } } } if (error) { - ll_fail("LLGLState::checkStates failed."); + ll_fail("LLGLStateValidator::checkStates failed."); } stop_glerror(); } -void LLGLState::checkTextureChannels(const std::string& msg) +void LLGLStateValidator::checkTextureChannels(const std::string& msg) { #if 0 if (!gDebugGL) @@ -1714,7 +1941,7 @@ void LLGLState::checkTextureChannels(const std::string& msg) for (S32 j = (i == 0 ? 1 : 0); - j < (gGLManager.mHasTextureRectangle ? 9 : 8); j++) + j < 8; j++) { if (glIsEnabled(value[j])) { @@ -1769,7 +1996,7 @@ void LLGLState::checkTextureChannels(const std::string& msg) { if (gDebugSession) { - ll_fail("LLGLState::checkTextureChannels failed."); + ll_fail("LLGLStateValidator::checkTextureChannels failed."); } else { @@ -1779,7 +2006,7 @@ void LLGLState::checkTextureChannels(const std::string& msg) #endif } -void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) +void LLGLStateValidator::checkClientArrays(const std::string& msg, U32 data_mask) { if (!gDebugGL || LLGLSLShader::sNoFixedFunction) { @@ -1945,7 +2172,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { if (gDebugSession) { - ll_fail("LLGLState::checkClientArrays failed."); + ll_fail("LLGLStateValidator::checkClientArrays failed."); } else { @@ -1956,108 +2183,36 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) /////////////////////////////////////////////////////////////////////// -LLGLState::LLGLState(LLGLenum state, S32 enabled) : - mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE) -{ - if (LLGLSLShader::sNoFixedFunction) - { //always ignore state that's deprecated post GL 3.0 - switch (state) - { - case GL_ALPHA_TEST: - case GL_NORMALIZE: - case GL_TEXTURE_GEN_R: - case GL_TEXTURE_GEN_S: - case GL_TEXTURE_GEN_T: - case GL_TEXTURE_GEN_Q: - case GL_LIGHTING: - case GL_COLOR_MATERIAL: - case GL_FOG: - case GL_LINE_STIPPLE: - case GL_POLYGON_STIPPLE: - mState = 0; - break; - } - } - - stop_glerror(); - if (mState) - { - mWasEnabled = sStateMap[state]; - llassert(mWasEnabled == glIsEnabled(state)); - setEnabled(enabled); - stop_glerror(); - } -} - -void LLGLState::setEnabled(S32 enabled) -{ - if (!mState) - { - return; - } - if (enabled == CURRENT_STATE) - { - enabled = sStateMap[mState] == GL_TRUE ? TRUE : FALSE; - } - else if (enabled == TRUE && sStateMap[mState] != GL_TRUE) - { - gGL.flush(); - glEnable(mState); - sStateMap[mState] = GL_TRUE; - } - else if (enabled == FALSE && sStateMap[mState] != GL_FALSE) - { - gGL.flush(); - glDisable(mState); - sStateMap[mState] = GL_FALSE; - } - mIsEnabled = enabled; -} - -LLGLState::~LLGLState() -{ - stop_glerror(); - if (mState) - { - if (gDebugGL) - { - if (!gDebugSession) - { - llassert_always(sStateMap[mState] == glIsEnabled(mState)); - } - else - { - if (sStateMap[mState] != glIsEnabled(mState)) - { - ll_fail("GL enabled state does not match expected"); - } - } - } - - if (mIsEnabled != mWasEnabled) - { - gGL.flush(); - if (mWasEnabled) - { - glEnable(mState); - sStateMap[mState] = GL_TRUE; - } - else - { - glDisable(mState); - sStateMap[mState] = GL_FALSE; - } - } - } - stop_glerror(); -} - //////////////////////////////////////////////////////////////////////////////// +initLLGLState(GL_BLEND, false, nullptr); +initLLGLState(GL_CLIP_PLANE0, false, nullptr); +initLLGLState(GL_CULL_FACE, false, nullptr); +initLLGLState(GL_DEPTH_CLAMP, false, nullptr); +initLLGLState(GL_DITHER, true, nullptr); +initLLGLState(GL_LINE_SMOOTH, false, nullptr); +initLLGLState(GL_MULTISAMPLE_ARB, false, nullptr); +initLLGLState(GL_POLYGON_OFFSET_FILL, false, nullptr); +initLLGLState(GL_POLYGON_OFFSET_LINE, false, nullptr); +initLLGLState(GL_POLYGON_SMOOTH, false, nullptr); +initLLGLState(GL_SCISSOR_TEST, false, nullptr); +initLLGLState(GL_STENCIL_TEST, false, nullptr); +initLLGLState(GL_ALPHA_TEST, false, &LLGLSLShader::sNoFixedFunction); +initLLGLState(GL_COLOR_MATERIAL, false, &LLGLSLShader::sNoFixedFunction); +initLLGLState(GL_FOG, false, &LLGLSLShader::sNoFixedFunction); +initLLGLState(GL_LINE_STIPPLE, false, &LLGLSLShader::sNoFixedFunction); +initLLGLState(GL_LIGHTING, false, &LLGLSLShader::sNoFixedFunction); +initLLGLState(GL_NORMALIZE, false, &LLGLSLShader::sNoFixedFunction); +initLLGLState(GL_POLYGON_STIPPLE, false, &LLGLSLShader::sNoFixedFunction); +initLLGLState(GL_TEXTURE_GEN_Q, false, &LLGLSLShader::sNoFixedFunction); +initLLGLState(GL_TEXTURE_GEN_R, false, &LLGLSLShader::sNoFixedFunction); +initLLGLState(GL_TEXTURE_GEN_S, false, &LLGLSLShader::sNoFixedFunction); +initLLGLState(GL_TEXTURE_GEN_T, false, &LLGLSLShader::sNoFixedFunction); + void LLGLManager::initGLStates() { //gl states moved to classes in llglstates.h - LLGLState::initClass(); + LLGLStateValidator::initClass(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 1cf65c8ca3..39b7a70ebe 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -30,7 +30,7 @@ // This file contains various stuff for handling gl extensions and other gl related stuff. #include -#include +#include #include #include "llerror.h" @@ -41,6 +41,7 @@ #include "llmatrix4a.h" #include "llplane.h" #include "llgltypes.h" +#include "llrender.h" #include "llinstancetracker.h" #include "llglheaders.h" @@ -93,7 +94,6 @@ class LLGLManager BOOL mHasSync; BOOL mHasMapBufferRange; BOOL mHasFlushBufferRange; - BOOL mHasPBuffer; BOOL mHasShaderObjects; BOOL mHasVertexShader; BOOL mHasFragmentShader; @@ -103,7 +103,6 @@ class LLGLManager BOOL mHasPointParameters; BOOL mHasDrawBuffers; BOOL mHasDepthClamp; - BOOL mHasTextureRectangle; BOOL mHasTransformFeedback; S32 mMaxIntegerSamples; @@ -112,14 +111,17 @@ class LLGLManager BOOL mHasARBEnvCombine; BOOL mHasCubeMap; BOOL mHasDebugOutput; - + BOOL mHasGpuShader5; BOOL mHasAdaptiveVsync; BOOL mHasTextureSwizzle; + bool mHasTextureCompression; + // Vendor-specific extensions BOOL mIsATI; BOOL mIsNVIDIA; BOOL mIsIntel; + BOOL mIsHD3K; BOOL mIsGF2or4MX; BOOL mIsGF3; BOOL mIsGFFX; @@ -135,7 +137,6 @@ class LLGLManager BOOL mHasRequirements; // Misc extensions - BOOL mHasSeparateSpecularColor; //whether this GPU is in the debug list. BOOL mDebugGPU; @@ -226,13 +227,13 @@ void clear_glerror(); //disable lighting for rendering hud objects //INCORRECT USAGE - LLGLEnable lighting(GL_LIGHTING); + LLGLEnable lighting; renderHUD(); - LLGLDisable lighting(GL_LIGHTING); + LLGLDisable lighting; //CORRECT USAGE { - LLGLEnable lighting(GL_LIGHTING); + LLGLEnable lighting; renderHUD(); } @@ -240,12 +241,10 @@ void clear_glerror(); is useful: { - LLGLEnable lighting(light_hud ? GL_LIGHTING : 0); + LLGLEnable lighting(light_hud); renderHUD(); } - A LLGLState initialized with a parameter of 0 does nothing. - LLGLState works by maintaining a map of the current GL states, and ignoring redundant enables/disables. If a redundant call is attempted, it becomes a noop, otherwise, it is set in the constructor and reset in the destructor. @@ -254,59 +253,131 @@ void clear_glerror(); if the existing GL state does not match the expected GL state. */ -class LLGLState + +struct LLGLStateStaticData { -public: - static void initClass(); - static void restoreGL(); + const char* stateStr; + LLGLenum state; + bool currentState; + U32 depth; + char* activeInstance; + bool* disabler; +}; +class LLGLStateValidator { +public: static void resetTextureStates(); static void dumpStates(); static void checkStates(const std::string& msg = ""); static void checkTextureChannels(const std::string& msg = ""); static void checkClientArrays(const std::string& msg = "", U32 data_mask = 0); - -protected: - static boost::unordered_map sStateMap; - + static void checkState(LLGLStateStaticData& data); + static void initClass(); + static void restoreGL(); + static bool registerStateData(LLGLStateStaticData& data); +private: + static std::vector sStateDataVec; +}; + +class LLGLStateIface { public: enum { CURRENT_STATE = -2 }; - LLGLState(LLGLenum state, S32 enabled = CURRENT_STATE); - ~LLGLState(); - void setEnabled(S32 enabled); - void enable() { setEnabled(TRUE); } - void disable() { setEnabled(FALSE); } -protected: - LLGLenum mState; - BOOL mWasEnabled; - BOOL mIsEnabled; + virtual ~LLGLStateIface() {} + virtual void enable() = 0; + virtual void disable() = 0; }; -// New LLGLState class wrappers that don't depend on actual GL flags. -class LLGLEnableBlending : public LLGLState +template +class LLGLState : public LLGLStateIface { public: - LLGLEnableBlending(bool enable); + + LLGLState(S8 newState = CURRENT_STATE) + { + ++staticData.depth; + mPriorInstance = staticData.activeInstance; + staticData.activeInstance = (char*)this; + mPriorState = staticData.currentState; + setEnabled(newState); + } + virtual ~LLGLState() + { + llassert_always(staticData.activeInstance == (char*)this); + if (staticData.depth != 0) + { + staticData.activeInstance = mPriorInstance; + --staticData.depth; + if (gDebugGL) { + LLGLStateValidator::checkState(staticData); + } + setState(mPriorState); + } + else + { + llassert_always(mPriorInstance == nullptr); + } + } + + virtual void enable() { setEnabled(true); } + virtual void disable() { setEnabled(false); } + + static LLGLStateStaticData staticData; + // Getter + static bool isEnabled() { return staticData.currentState && (!staticData.disabler || !*staticData.disabler); } + // For assertions. If feature is on or unsupported, return true. + static bool checkEnabled() { return (!staticData.disabler || !*staticData.disabler) ? staticData.currentState : true; } + // For assertions. If feature is off or unsupported, return true. + static bool checkDisabled() { return (!staticData.disabler || !*staticData.disabler) ? !staticData.currentState : true; } +private: + char *mPriorInstance; + bool mPriorState; + + void setEnabled(S32 newState) + { + llassert_always(staticData.activeInstance == (char*)this); + bool enabled = newState == CURRENT_STATE ? staticData.currentState : !!newState; + setState(enabled); + } + + static void setState(bool enabled) + { + if (staticData.currentState != enabled && (!staticData.disabler || !*staticData.disabler)) + { + gGL.flush(); + staticData.currentState = enabled; + staticData.currentState ? glEnable(state) : glDisable(state); + } + } }; +#define initLLGLState(state, value, disabler_ptr) \ + template <> \ + LLGLStateStaticData LLGLState::staticData = {#state, state, value, 0, nullptr, disabler_ptr}; \ + bool registered_##state = LLGLStateValidator::registerStateData(LLGLState::staticData); -class LLGLEnableAlphaReject : public LLGLState +template <> +class LLGLState<0> : public LLGLStateIface { -public: - LLGLEnableAlphaReject(bool enable); + LLGLState(S8 newState = CURRENT_STATE) { } + virtual ~LLGLState() { } + virtual void enable() { } + virtual void disable() { } + static bool isEnabled() { return false; } + // For assertions. If feature is on or unsupported, return true. + static bool checkEnabled() { return true; } + // For assertions. If feature is off or unsupported, return true. + static bool checkDisabled() { return true; } }; -/// TODO: Being deprecated. -class LLGLEnable : public LLGLState +template +struct LLGLEnable : public LLGLState { -public: - LLGLEnable(LLGLenum state) : LLGLState(state, TRUE) {} + LLGLEnable(bool noskip = true) : LLGLState(noskip ? TRUE : LLGLState::CURRENT_STATE) {} }; -/// TODO: Being deprecated. -class LLGLDisable : public LLGLState +template +struct LLGLDisable : public LLGLState { -public: - LLGLDisable(LLGLenum state) : LLGLState(state, FALSE) {} + LLGLDisable(bool noskip = true) : LLGLState(noskip ? FALSE : LLGLState::CURRENT_STATE) {} }; /* @@ -459,8 +530,6 @@ class LLGLSyncFence : public LLGLFence #include "llglstates.h" -void init_glstates(); - void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string ); extern BOOL gClothRipple; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 3a91c50ff1..542ed4458e 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -27,238 +27,7 @@ #ifndef LL_LLGLHEADERS_H #define LL_LLGLHEADERS_H -#if LL_SOLARIS -# if defined(__sparc) -# define I_NEED_OS2_H // avoiding BOOL conflicts -# endif -# include "GL/gl.h" -# if defined(__sparc) -# undef I_NEED_OS2_H -# ifdef BOOL -# undef BOOL // now get rid of Xmd.h crap -# endif -# endif -# include "GL/glx.h" -# define GL_GLEXT_PROTOTYPES 1 -# include "GL/glext.h" -# include "GL/glx.h" -# define GLX_GLXEXT_PROTOTYPES 1 -# include "GL/glxext.h" -//# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p)) -# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddress((const GLubyte*)(p)) -// the X headers define 'Status'. Undefine to avoid confusion. -#undef Status - -// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly -// This header is distributed with SL. You'll find it in linden/libraries/include/GL/ -# define __APPLE__ -# include "GL/glh_extensions.h" -# undef __APPLE__ - - -// GL_ARB_vertex_buffer_object -extern PFNGLBINDBUFFERARBPROC glBindBufferARB; -extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB; -extern PFNGLGENBUFFERSARBPROC glGenBuffersARB; -extern PFNGLISBUFFERARBPROC glIsBufferARB; -extern PFNGLBUFFERDATAARBPROC glBufferDataARB; -extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB; -extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB; -extern PFNGLMAPBUFFERARBPROC glMapBufferARB; -extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; -extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; -extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; - -// GL_ARB_vertex_array_object -extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; -extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; -extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; -extern PFNGLISVERTEXARRAYPROC glIsVertexArray; - -// GL_ARB_sync -extern PFNGLFENCESYNCPROC glFenceSync; -extern PFNGLISSYNCPROC glIsSync; -extern PFNGLDELETESYNCPROC glDeleteSync; -extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; -extern PFNGLWAITSYNCPROC glWaitSync; -extern PFNGLGETINTEGER64VPROC glGetInteger64v; -extern PFNGLGETSYNCIVPROC glGetSynciv; - -// GL_APPLE_flush_buffer_range -extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE; -extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; - -// GL_ARB_map_buffer_range -extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; -extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; - -// GL_ATI_vertex_array_object -extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI; -extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI; -extern PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI; -extern PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI; -extern PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI; -extern PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI; -extern PFNGLARRAYOBJECTATIPROC glArrayObjectATI; -extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI; -extern PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI; -extern PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI; -extern PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI; -extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI; -extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI; - -// GL_ARB_occlusion_query -extern PFNGLGENQUERIESARBPROC glGenQueriesARB; -extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB; -extern PFNGLISQUERYARBPROC glIsQueryARB; -extern PFNGLBEGINQUERYARBPROC glBeginQueryARB; -extern PFNGLENDQUERYARBPROC glEndQueryARB; -extern PFNGLGETQUERYIVARBPROC glGetQueryivARB; -extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB; -extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB; - -// GL_ARB_point_parameters -extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB; -extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB; - -// GL_ARB_shader_objects -extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; -extern PFNGLGETHANDLEARBPROC glGetHandleARB; -extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB; -extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; -extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB; -extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB; -extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; -extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB; -extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB; -extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; -extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB; -extern PFNGLUNIFORM1FARBPROC glUniform1fARB; -extern PFNGLUNIFORM2FARBPROC glUniform2fARB; -extern PFNGLUNIFORM3FARBPROC glUniform3fARB; -extern PFNGLUNIFORM4FARBPROC glUniform4fARB; -extern PFNGLUNIFORM1IARBPROC glUniform1iARB; -extern PFNGLUNIFORM2IARBPROC glUniform2iARB; -extern PFNGLUNIFORM3IARBPROC glUniform3iARB; -extern PFNGLUNIFORM4IARBPROC glUniform4iARB; -extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB; -extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB; -extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB; -extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB; -extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB; -extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB; -extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB; -extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB; -extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB; -extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB; -extern PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv; -extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB; -extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB; -extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; -extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB; -extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB; -extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; -extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB; -extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB; -extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB; -extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB; - -// GL_ARB_vertex_shader -extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB; -extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB; -extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB; -extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB; -extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB; -extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB; -extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB; -extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB; -extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB; -extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB; -extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB; -extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB; -extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB; -extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB; -extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB; -extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB; -extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB; -extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB; -extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB; -extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB; -extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB; -extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB; -extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB; -extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB; -extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB; -extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB; -extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB; -extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB; -extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB; -extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB; -extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB; -extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB; -extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB; -extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB; -extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB; -extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB; -extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB; -extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer; -extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB; -extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB; -extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB; -extern PFNGLBINDPROGRAMARBPROC glBindProgramARB; -extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB; -extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB; -extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB; -extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB; -extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB; -extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB; -extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB; -extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB; -extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB; -extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB; -extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB; -extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB; -extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB; -extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB; -extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB; -extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB; -extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB; -extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB; -extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB; -extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB; -extern PFNGLISPROGRAMARBPROC glIsProgramARB; -extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB; -extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB; -extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; - -extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB; -extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; - -extern PFNGLCOLORTABLEEXTPROC glColorTableEXT; - -//GL_EXT_blend_func_separate -extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; - -//GL_EXT_framebuffer_object -extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; -extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; -extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; -extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; -extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; -extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; -extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; -extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; -extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; -extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; -extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; -extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; -extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; -extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; -extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; -extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; -extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; - -#elif LL_MESA +#if LL_MESA //---------------------------------------------------------------------------- // MESA headers // quotes so we get libraries/.../GL/ version @@ -266,11 +35,6 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; #include "GL/gl.h" #include "GL/glext.h" -// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly -# define __APPLE__ -# include "GL/glh_extensions.h" -# undef __APPLE__ - #elif LL_LINUX //---------------------------------------------------------------------------- // LL_LINUX @@ -281,12 +45,7 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; #include "GL/gl.h" #include "GL/glext.h" - #if LL_LINUX && !LL_MESA_HEADLESS -// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly -# define __APPLE__ -# include "GL/glh_extensions.h" -# undef __APPLE__ /* Although SDL very likely ends up calling glXGetProcAddress() itself, if we use SDL_GL_GetProcAddress() then we get bogus addresses back on @@ -318,244 +77,87 @@ extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB; extern PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements; #endif // LL_LINUX_NV_GL_HEADERS -// GL_ARB_vertex_array_object -extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; -extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; -extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; -extern PFNGLISVERTEXARRAYPROC glIsVertexArray; - -// GL_ARB_vertex_buffer_object -extern PFNGLBINDBUFFERARBPROC glBindBufferARB; -extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB; -extern PFNGLGENBUFFERSARBPROC glGenBuffersARB; -extern PFNGLISBUFFERARBPROC glIsBufferARB; -extern PFNGLBUFFERDATAARBPROC glBufferDataARB; -extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB; -extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB; -extern PFNGLMAPBUFFERARBPROC glMapBufferARB; -extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; -extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; -extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; - -// GL_ARB_sync -extern PFNGLFENCESYNCPROC glFenceSync; -extern PFNGLISSYNCPROC glIsSync; -extern PFNGLDELETESYNCPROC glDeleteSync; -extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; -extern PFNGLWAITSYNCPROC glWaitSync; -extern PFNGLGETINTEGER64VPROC glGetInteger64v; -extern PFNGLGETSYNCIVPROC glGetSynciv; - -// GL_APPLE_flush_buffer_range -extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE; -extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; - -// GL_ARB_map_buffer_range -extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; -extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; - -// GL_ATI_vertex_array_object -extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI; -extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI; -extern PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI; -extern PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI; -extern PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI; -extern PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI; -extern PFNGLARRAYOBJECTATIPROC glArrayObjectATI; -extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI; -extern PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI; -extern PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI; -extern PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI; -extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI; -extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI; - -// GL_ARB_occlusion_query -extern PFNGLGENQUERIESARBPROC glGenQueriesARB; -extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB; -extern PFNGLISQUERYARBPROC glIsQueryARB; -extern PFNGLBEGINQUERYARBPROC glBeginQueryARB; -extern PFNGLENDQUERYARBPROC glEndQueryARB; -extern PFNGLGETQUERYIVARBPROC glGetQueryivARB; -extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB; -extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB; - -// GL_ARB_point_parameters -extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB; -extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB; - -// GL_ARB_shader_objects -extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; -extern PFNGLGETHANDLEARBPROC glGetHandleARB; -extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB; -extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; -extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB; -extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB; -extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; -extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB; -extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB; -extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; -extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB; -extern PFNGLUNIFORM1FARBPROC glUniform1fARB; -extern PFNGLUNIFORM2FARBPROC glUniform2fARB; -extern PFNGLUNIFORM3FARBPROC glUniform3fARB; -extern PFNGLUNIFORM4FARBPROC glUniform4fARB; -extern PFNGLUNIFORM1IARBPROC glUniform1iARB; -extern PFNGLUNIFORM2IARBPROC glUniform2iARB; -extern PFNGLUNIFORM3IARBPROC glUniform3iARB; -extern PFNGLUNIFORM4IARBPROC glUniform4iARB; -extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB; -extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB; -extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB; -extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB; -extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB; -extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB; -extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB; -extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB; -extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB; -extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB; -extern PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv; -extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB; -extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB; -extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; -extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB; -extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB; -extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; -extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB; -extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB; -extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB; -extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB; - -// GL_ARB_vertex_shader -extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB; -extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB; -extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB; -extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB; -extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB; -extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB; -extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB; -extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB; -extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB; -extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB; -extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB; -extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB; -extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB; -extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB; -extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB; -extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB; -extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB; -extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB; -extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB; -extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB; -extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB; -extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB; -extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB; -extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB; -extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB; -extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB; -extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB; -extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB; -extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB; -extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB; -extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB; -extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB; -extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB; -extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB; -extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB; -extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB; -extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB; -extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer; -extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB; -extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB; -extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB; -extern PFNGLBINDPROGRAMARBPROC glBindProgramARB; -extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB; -extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB; -extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB; -extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB; -extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB; -extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB; -extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB; -extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB; -extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB; -extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB; -extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB; -extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB; -extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB; -extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB; -extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB; -extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB; -extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB; -extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB; -extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB; -extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB; -extern PFNGLISPROGRAMARBPROC glIsProgramARB; -extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB; -extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB; -extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; - -extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB; -extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; - -//GL_EXT_blend_func_separate -extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; - -//GL_ARB_framebuffer_object -extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer; -extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; -extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; -extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; -extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; -extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv; -extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer; -extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; -extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; -extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; -extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; -extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D; -extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; -extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D; -extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; -extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv; -extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap; -extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; -extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample; -extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer; - -//GL_ARB_draw_buffers -extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; - -//GL_ARB_texture_multisample -extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample; -extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; -extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; -extern PFNGLSAMPLEMASKIPROC glSampleMaski; - -//transform feedback (4.0 core) -extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback; -extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback; -extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings; -extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; - - #elif LL_WINDOWS //---------------------------------------------------------------------------- // LL_WINDOWS -// windows gl headers depend on things like APIENTRY, so include windows. -#define WIN32_LEAN_AND_MEAN -#include -#include +#include "llwin32headerslean.h" //---------------------------------------------------------------------------- #include // quotes so we get libraries/.../GL/ version #include "GL/glext.h" -#include "GL/glh_extensions.h" +#include +#define GLH_EXT_GET_PROC_ADDRESS(p) wglGetProcAddress(p) // WGL_ARB_create_context -extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; -extern PFNGLGETSTRINGIPROC glGetStringi; +extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; +// WGL_ARB_swap_control +extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; +// WGL_ARB_pixel_format +extern PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB; +extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; + +// Mesa goes up to Opengl 1.3. Windows api only includes 1.1. Include 1.2 and 1.3 features here +// Opengl 1.2 +extern PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements; + +// GL_ARB_multitexture +extern PFNGLMULTITEXCOORD1DARBPROC glMultiTexCoord1dARB; +extern PFNGLMULTITEXCOORD1DVARBPROC glMultiTexCoord1dvARB; +extern PFNGLMULTITEXCOORD1FARBPROC glMultiTexCoord1fARB; +extern PFNGLMULTITEXCOORD1FVARBPROC glMultiTexCoord1fvARB; +extern PFNGLMULTITEXCOORD1IARBPROC glMultiTexCoord1iARB; +extern PFNGLMULTITEXCOORD1IVARBPROC glMultiTexCoord1ivARB; +extern PFNGLMULTITEXCOORD1SARBPROC glMultiTexCoord1sARB; +extern PFNGLMULTITEXCOORD1SVARBPROC glMultiTexCoord1svARB; +extern PFNGLMULTITEXCOORD2DARBPROC glMultiTexCoord2dARB; +extern PFNGLMULTITEXCOORD2DVARBPROC glMultiTexCoord2dvARB; +extern PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB; +extern PFNGLMULTITEXCOORD2FVARBPROC glMultiTexCoord2fvARB; +extern PFNGLMULTITEXCOORD2IARBPROC glMultiTexCoord2iARB; +extern PFNGLMULTITEXCOORD2IVARBPROC glMultiTexCoord2ivARB; +extern PFNGLMULTITEXCOORD2SARBPROC glMultiTexCoord2sARB; +extern PFNGLMULTITEXCOORD2SVARBPROC glMultiTexCoord2svARB; +extern PFNGLMULTITEXCOORD3DARBPROC glMultiTexCoord3dARB; +extern PFNGLMULTITEXCOORD3DVARBPROC glMultiTexCoord3dvARB; +extern PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3fARB; +extern PFNGLMULTITEXCOORD3FVARBPROC glMultiTexCoord3fvARB; +extern PFNGLMULTITEXCOORD3IARBPROC glMultiTexCoord3iARB; +extern PFNGLMULTITEXCOORD3IVARBPROC glMultiTexCoord3ivARB; +extern PFNGLMULTITEXCOORD3SARBPROC glMultiTexCoord3sARB; +extern PFNGLMULTITEXCOORD3SVARBPROC glMultiTexCoord3svARB; +extern PFNGLMULTITEXCOORD4DARBPROC glMultiTexCoord4dARB; +extern PFNGLMULTITEXCOORD4DVARBPROC glMultiTexCoord4dvARB; +extern PFNGLMULTITEXCOORD4FARBPROC glMultiTexCoord4fARB; +extern PFNGLMULTITEXCOORD4FVARBPROC glMultiTexCoord4fvARB; +extern PFNGLMULTITEXCOORD4IARBPROC glMultiTexCoord4iARB; +extern PFNGLMULTITEXCOORD4IVARBPROC glMultiTexCoord4ivARB; +extern PFNGLMULTITEXCOORD4SARBPROC glMultiTexCoord4sARB; +extern PFNGLMULTITEXCOORD4SVARBPROC glMultiTexCoord4svARB; +extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; +extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB; + +#endif + +#if LL_WINDOWS || (LL_LINUX && !LL_MESA_HEADLESS && !LL_MESA) + +//GL_ARB_texture_compression +// ARB variants of these are missing from mesa gl.h for some odd reason. +extern PFNGLCOMPRESSEDTEXIMAGE3DARBPROC glCompressedTexImage3DARB; +extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB; +extern PFNGLCOMPRESSEDTEXIMAGE1DARBPROC glCompressedTexImage1DARB; +extern PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC glCompressedTexSubImage3DARB; +extern PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC glCompressedTexSubImage2DARB; +extern PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC glCompressedTexSubImage1DARB; +extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; + +// GL_ARB_vertex_array_object +extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; +extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; +extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; +extern PFNGLISVERTEXARRAYPROC glIsVertexArray; // GL_ARB_vertex_buffer_object extern PFNGLBINDBUFFERARBPROC glBindBufferARB; @@ -570,12 +172,6 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; -// GL_ARB_vertex_array_object -extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; -extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; -extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; -extern PFNGLISVERTEXARRAYPROC glIsVertexArray; - // GL_ARB_sync extern PFNGLFENCESYNCPROC glFenceSync; extern PFNGLISSYNCPROC glIsSync; @@ -593,23 +189,6 @@ extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; -// GL_ATI_vertex_array_object -extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI; -extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI; -extern PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI; -extern PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI; -extern PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI; -extern PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI; -extern PFNGLARRAYOBJECTATIPROC glArrayObjectATI; -extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI; -extern PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI; -extern PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI; -extern PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI; -extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI; -extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI; - -extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; - // GL_ARB_occlusion_query extern PFNGLGENQUERIESARBPROC glGenQueriesARB; extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB; @@ -620,13 +199,15 @@ extern PFNGLGETQUERYIVARBPROC glGetQueryivARB; extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB; extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB; +extern PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64vEXT; + // GL_ARB_point_parameters extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB; extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB; // GL_ARB_shader_objects -extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; -extern PFNGLGETHANDLEARBPROC glGetHandleARB; +extern PFNGLDELETEOBJECTARBPROC glDeleteShader; +extern PFNGLDELETEOBJECTARBPROC glDeleteProgram; extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB; extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB; @@ -656,9 +237,10 @@ extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB; extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB; extern PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv; extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB; -extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB; -extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; -extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB; +extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetShaderiv; +extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetProgramiv; +extern PFNGLGETINFOLOGARBPROC glGetShaderInfoLog; +extern PFNGLGETINFOLOGARBPROC glGetProgramInfoLog; extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB; extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB; @@ -685,13 +267,13 @@ extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB; extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB; extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB; extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB; -extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB; -extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB; -extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB; -extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB; -extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB; -extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB; -extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB; +extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4NbvARB; +extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4NivARB; +extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4NsvARB; +extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4NubARB; +extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4NubvARB; +extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4NuivARB; +extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4NusvARB; extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB; extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB; extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB; @@ -774,6 +356,7 @@ extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback; extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings; extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; + //GL_ARB_debug_output extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB; extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB; @@ -789,8 +372,6 @@ extern PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB; #define GL_EXT_separate_specular_color 1 #include -#include "GL/glh_extensions.h" - // These symbols don't exist on 10.3.9, so they have to be declared weak. Redeclaring them here fixes the problem. // Note that they also must not be called on 10.3.9. This should be taken care of by a runtime check for the existence of the GL extension. #include diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 33404433f2..0066dbc851 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -38,6 +38,11 @@ #include "OpenGL/OpenGL.h" #endif +#ifdef LL_RELEASE_FOR_DOWNLOAD +#define UNIFORM_ERRS LL_WARNS_ONCE("Shader") +#else +#define UNIFORM_ERRS LL_ERRS("Shader") +#endif // Lots of STL stuff in here, using namespace std to keep things more readable using std::vector; using std::pair; @@ -48,6 +53,12 @@ GLhandleARB LLGLSLShader::sCurBoundShader = 0; LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL; S32 LLGLSLShader::sIndexedTextureChannels = 0; bool LLGLSLShader::sNoFixedFunction = false; +bool LLGLSLShader::sProfileEnabled = false; +std::set LLGLSLShader::sInstances; +U64 LLGLSLShader::sTotalTimeElapsed = 0; +U32 LLGLSLShader::sTotalTrianglesDrawn = 0; +U64 LLGLSLShader::sTotalSamplesDrawn = 0; +U32 LLGLSLShader::sTotalDrawCalls = 0; //UI shader -- declared here so llui_libtest will link properly //Singu note: Not using llui_libtest... and LLViewerShaderMgr is a part of newview. So, @@ -77,13 +88,221 @@ LLShaderFeatures::LLShaderFeatures() , hasGamma(false) , mIndexedTextureChannels(0) , disableTextureIndex(false) - , hasAlphaMask(false) + , hasAlphaMask(false) + , attachNothing(false) { } //=============================== // LLGLSL Shader implementation //=============================== + +//static +void LLGLSLShader::initProfile() +{ + sProfileEnabled = true; + sTotalTimeElapsed = 0; + sTotalTrianglesDrawn = 0; + sTotalSamplesDrawn = 0; + sTotalDrawCalls = 0; + + for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + { + (*iter)->clearStats(); + } +} + + +struct LLGLSLShaderCompareTimeElapsed +{ + bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs) + { + return lhs->mTimeElapsed < rhs->mTimeElapsed; + } +}; + +//static +void LLGLSLShader::finishProfile(bool emit_report) +{ + sProfileEnabled = false; + + if (emit_report) + { + std::vector sorted; + + for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + { + sorted.push_back(*iter); + } + + std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed()); + + for (std::vector::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) + { + (*iter)->dumpStats(); + } + + LL_INFOS() << "-----------------------------------" << LL_ENDL; + LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed/1000000.f) << LL_ENDL; + LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn/1000000.f) << LL_ENDL; + LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn/1000000.f) << LL_ENDL; + } +} + +void LLGLSLShader::clearStats() +{ + mTrianglesDrawn = 0; + mTimeElapsed = 0; + mSamplesDrawn = 0; + mDrawCalls = 0; + mTextureStateFetched = false; + mTextureMagFilter.clear(); + mTextureMinFilter.clear(); +} + +void LLGLSLShader::dumpStats() +{ + if (mDrawCalls > 0) + { + LL_INFOS() << "=============================================" << LL_ENDL; + LL_INFOS() << mName << LL_ENDL; + for (U32 i = 0; i < mShaderFiles.size(); ++i) + { + LL_INFOS() << mShaderFiles[i].first << LL_ENDL; + } + for (U32 i = 0; i < mTexture.size(); ++i) + { + GLint idx = mTexture[i]; + + if (idx >= 0) + { + GLint uniform_idx = getUniformLocation(i); + LL_INFOS() << mUniformNameMap[uniform_idx] << " - " << std::hex << mTextureMagFilter[i] << "/" << mTextureMinFilter[i] << std::dec << LL_ENDL; + } + } + LL_INFOS() << "=============================================" << LL_ENDL; + + F32 ms = mTimeElapsed/1000000.f; + F32 seconds = ms/1000.f; + + F32 pct_tris = (F32) mTrianglesDrawn/(F32)sTotalTrianglesDrawn*100.f; + F32 tris_sec = (F32) (mTrianglesDrawn/1000000.0); + tris_sec /= seconds; + + F32 pct_samples = (F32) ((F64)mSamplesDrawn/(F64)sTotalSamplesDrawn)*100.f; + F32 samples_sec = (F32) mSamplesDrawn/1000000000.0; + samples_sec /= seconds; + + F32 pct_calls = (F32) mDrawCalls/(F32)sTotalDrawCalls*100.f; + U32 avg_batch = mTrianglesDrawn/mDrawCalls; + + LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec ) << LL_ENDL; + LL_INFOS() << "Draw Calls: " << mDrawCalls << " " << llformat("(%.2f pct of total, avg %d tris/call)", pct_calls, avg_batch) << LL_ENDL; + LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL; + LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32) ((F64)mTimeElapsed/(F64)sTotalTimeElapsed)*100.f, ms) << LL_ENDL; + } +} + +//static +void LLGLSLShader::startProfile() +{ + if (sProfileEnabled && sCurBoundShaderPtr) + { + sCurBoundShaderPtr->placeProfileQuery(); + } + +} + +//static +void LLGLSLShader::stopProfile(U32 count, U32 mode) +{ + if (sProfileEnabled && sCurBoundShaderPtr) + { + sCurBoundShaderPtr->readProfileQuery(count, mode); + } +} + +void LLGLSLShader::placeProfileQuery() +{ +#if !LL_DARWIN + if (mTimerQuery == 0) + { + glGenQueriesARB(1, &mSamplesQuery); + glGenQueriesARB(1, &mTimerQuery); + } + + if (!mTextureStateFetched) + { + mTextureStateFetched = true; + mTextureMagFilter.resize(mTexture.size()); + mTextureMinFilter.resize(mTexture.size()); + + U32 cur_active = gGL.getCurrentTexUnitIndex(); + + for (U32 i = 0; i < mTexture.size(); ++i) + { + GLint idx = mTexture[i]; + + if (idx >= 0) + { + gGL.getTexUnit(idx)->activate(); + + U32 mag = 0xFFFFFFFF; + U32 min = 0xFFFFFFFF; + + U32 type = LLTexUnit::getInternalType(gGL.getTexUnit(idx)->getCurrType()); + + glGetTexParameteriv(type, GL_TEXTURE_MAG_FILTER, (GLint*) &mag); + glGetTexParameteriv(type, GL_TEXTURE_MIN_FILTER, (GLint*) &min); + + mTextureMagFilter[i] = mag; + mTextureMinFilter[i] = min; + } + } + + gGL.getTexUnit(cur_active)->activate(); + } + + + glBeginQueryARB(GL_SAMPLES_PASSED, mSamplesQuery); + glBeginQueryARB(GL_TIME_ELAPSED, mTimerQuery); +#endif +} + +void LLGLSLShader::readProfileQuery(U32 count, U32 mode) +{ +#if !LL_DARWIN + glEndQueryARB(GL_TIME_ELAPSED); + glEndQueryARB(GL_SAMPLES_PASSED); + + GLuint64 time_elapsed = 0; + glGetQueryObjectui64vEXT(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); + + GLuint64 samples_passed = 0; + glGetQueryObjectui64vEXT(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); + + sTotalTimeElapsed += time_elapsed; + mTimeElapsed += time_elapsed; + + sTotalSamplesDrawn += samples_passed; + mSamplesDrawn += samples_passed; + + U32 tri_count = 0; + switch (mode) + { + case LLRender::TRIANGLES: tri_count = count/3; break; + case LLRender::TRIANGLE_FAN: tri_count = count-2; break; + case LLRender::TRIANGLE_STRIP: tri_count = count-2; break; + default: tri_count = count; break; //points lines etc just use primitive count + } + + mTrianglesDrawn += tri_count; + sTotalTrianglesDrawn += tri_count; + + sTotalDrawCalls++; + mDrawCalls++; +#endif +} LLGLSLShader::LLGLSLShader(S32 shader_class) : mProgramObject(0), mShaderClass(shader_class), @@ -91,20 +310,26 @@ LLGLSLShader::LLGLSLShader(S32 shader_class) mTotalUniformSize(0), mActiveTextureChannels(0), mShaderLevel(0), - mShaderGroup(SG_DEFAULT), - mUniformsDirty(FALSE) + mShaderGroup(SG_DEFAULT), + mUniformsDirty(FALSE), + mTimerQuery(0), + mLightHash(0), + mSamplesQuery(0) + { LLShaderMgr::getGlobalShaderList().push_back(this); } LLGLSLShader::~LLGLSLShader() -{ - +{ } + void LLGLSLShader::unload() { - stop_glerror(); - mAttribute.clear(); + sInstances.erase(this); + + stop_glerror(); + mAttribute.clear(); mTexture.clear(); mUniform.clear(); mShaderFiles.clear(); @@ -123,13 +348,25 @@ void LLGLSLShader::unload() glDeleteObjectARB(obj[i]); }*/ if(mProgramObject) - glDeleteObjectARB(mProgramObject); + glDeleteProgram(mProgramObject); mProgramObject = 0; } - - //hack to make apple not complain - glGetError(); - + + if (mTimerQuery) + { + glDeleteQueriesARB(1, &mTimerQuery); + mTimerQuery = 0; + } + + if (mSamplesQuery) + { + glDeleteQueriesARB(1, &mSamplesQuery); + mSamplesQuery = 0; + } + + //hack to make apple not complain + glGetError(); + stop_glerror(); } @@ -138,9 +375,11 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, U32 varying_count, const char** varyings) { - //reloading, reset matrix hash values - for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) - { + sInstances.insert(this); + + //reloading, reset matrix hash values + for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) + { mMatHash[i] = 0xFFFFFFFF; } mLightHash = 0xFFFFFFFF; @@ -149,7 +388,7 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, BOOL success = TRUE; if(mProgramObject) //purge the old program - glDeleteObjectARB(mProgramObject); + glDeleteProgram(mProgramObject); // Create program mProgramObject = glCreateProgramObjectARB(); @@ -175,10 +414,10 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, } // Attach existing objects - if (!LLShaderMgr::instance()->attachShaderFeatures(this)) + if (!LLShaderMgr::instance()->attachClassSharedShaders(*this, mShaderClass) || !LLShaderMgr::instance()->attachShaderFeatures(this)) { if(mProgramObject) - glDeleteObjectARB(mProgramObject); + glDeleteProgram(mProgramObject); mProgramObject = 0; return FALSE; } @@ -208,7 +447,7 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, if( !success ) { if(mProgramObject) - glDeleteObjectARB(mProgramObject); + glDeleteProgram(mProgramObject); mProgramObject = 0; LL_WARNS("ShaderLoading") << "Failed to link shader: " << mName << LL_ENDL; @@ -221,31 +460,17 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, return createShader(attributes,uniforms); } } - else if (mFeatures.mIndexedTextureChannels > 0) - { //override texture channels for indexed texture rendering - bind(); - S32 channel_count = mFeatures.mIndexedTextureChannels; - for (S32 i = 0; i < channel_count; i++) - { - LLStaticHashedString uniName(llformat("tex%d", i)); - uniform1i(uniName, i); - } + if (LLShaderMgr::instance()->mProgramObjects.find(mName) == LLShaderMgr::instance()->mProgramObjects.end()) + { + LLShaderMgr::instance()->mProgramObjects.emplace(mName, mProgramObject); + } + else + { + LL_WARNS("ShaderLoading") << "Attempting to create shader program with duplicate name: " << mName << LL_ENDL; + } - S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten - for (U32 i = 0; i < mTexture.size(); i++) - { - if (mTexture[i] > -1 && mTexture[i] < channel_count) - { - llassert(cur_tex < gGLManager.mNumTextureImageUnits); - uniform1i(i, cur_tex); - mTexture[i] = cur_tex++; - } - } - unbind(); - } - - return success; + return success; } BOOL LLGLSLShader::attachObject(std::string object) @@ -355,24 +580,14 @@ BOOL LLGLSLShader::mapAttributes(const std::vector * attri return FALSE; } -void LLGLSLShader::mapUniform(GLint index, const vector * uniforms) +void LLGLSLShader::mapUniform(const gl_uniform_data_t& gl_uniform, const vector * uniforms) { - if (index == -1) - { - return; - } - - GLenum type; - GLsizei length; - GLint size = -1; - char name[1024]; /* Flawfinder: ignore */ - name[0] = 0; - - glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, (GLcharARB *)name); + GLint size = gl_uniform.size; + char* name = (char*)gl_uniform.name.c_str(); //blegh #if !LL_DARWIN if (size > 0) { - switch(type) + switch(gl_uniform.type) { case GL_FLOAT_VEC2: size *= 2; break; case GL_FLOAT_VEC3: size *= 3; break; @@ -425,33 +640,44 @@ void LLGLSLShader::mapUniform(GLint index, const vector * } LLStaticHashedString hashedName(name); + mUniformNameMap[location] = name; mUniformMap[hashedName] = location; LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL; + + // Indexed textures are referenced by hardcoded tex unit index. This is where that mapping happens. + if (gl_uniform.texunit_priority < (U32)mFeatures.mIndexedTextureChannels) + { + // mUniform and mTexture are irrelivant for indexed textures, since there's no enum to look them up through. + // Thus, only call mapUniformTextureChannel to create the texunit => uniform location mapping in opengl. + mapUniformTextureChannel(location, gl_uniform.type); + return; + } //find the index of this uniform - for (S32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedUniforms.size(); i++) + for (U32 i = 0; i < LLShaderMgr::instance()->mReservedUniforms.size(); i++) { if ( (mUniform[i] == -1) && (LLShaderMgr::instance()->mReservedUniforms[i] == name)) { //found it mUniform[i] = location; - mTexture[i] = mapUniformTextureChannel(location, type); + mTexture[i] = mapUniformTextureChannel(location, gl_uniform.type); return; } } if (uniforms != NULL) { - for (U32 i = 0; i < uniforms->size(); i++) + U32 j = LLShaderMgr::instance()->mReservedUniforms.size(); + for (U32 i = 0; i < uniforms->size(); i++, j++) { - if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1) + if ( (mUniform[j] == -1) && ((*uniforms)[i].String() == name)) { //found it - mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location; - mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type); + mUniform[j] = location; + mTexture[j] = mapUniformTextureChannel(location, gl_uniform.type);; return; } } @@ -474,6 +700,7 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB /*|| type == GL_SAMPLER_2D_MULTISAMPLE*/) { //this here is a texture + gGL.syncShaders(); glUniform1iARB(location, mActiveTextureChannels); LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL; return mActiveTextureChannels++; @@ -484,29 +711,85 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) BOOL LLGLSLShader::mapUniforms(const vector * uniforms) { BOOL res = TRUE; + + auto& reservedUniforms = LLShaderMgr::instance()->mReservedUniforms; mTotalUniformSize = 0; mActiveTextureChannels = 0; mUniform.clear(); mUniformMap.clear(); + mUniformNameMap.clear(); mTexture.clear(); mValueVec4.clear(); mValueMat3.clear(); mValueMat4.clear(); //initialize arrays U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); - mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); - mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); + mUniform.resize(numUniforms + reservedUniforms.size(), -1); + mTexture.resize(numUniforms + reservedUniforms.size(), -1); bind(); //get the number of active uniforms GLint activeCount; - glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount); + glGetProgramiv(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount); + std::vector< gl_uniform_data_t > gl_uniforms; + + bool has_diffuse = false; + U32 max_index = mFeatures.mIndexedTextureChannels; + // Gather active uniforms. for (S32 i = 0; i < activeCount; i++) { - mapUniform(i, uniforms); + // Fetch name and size from opengl + char name[1024]; + gl_uniform_data_t gl_uniform; + GLsizei length; + glGetActiveUniformARB(mProgramObject, i, 1024, &length, &gl_uniform.size, &gl_uniform.type, (GLcharARB *)name); + if (length && name[length - 1] == '\0') + { + --length; // Some drivers can't be trusted... + } + if (gl_uniform.size < 0 || length <= 0) + continue; + gl_uniform.name = std::string(name, length); + + // Track if diffuseMap uniform was detected. If so, flag as such to assert indexed textures aren't also used in this shader. + has_diffuse |= gl_uniform.name == "diffuseMap"; + + // Use mReservedUniforms to calculate texunit ordering. Reserve priority [0,max_index) for indexed textures if applicable. + auto it = std::find(reservedUniforms.begin(), reservedUniforms.end(), gl_uniform.name); + gl_uniform.texunit_priority = it != reservedUniforms.end() ? max_index + std::distance(reservedUniforms.begin(), it) : UINT_MAX; + + // Indexed texture uniforms must ALWAYS have highest texunit priority. Ensures [texunit[0],texunit[max_index]) map to [tex[0],tex[max_index]) uniforms. + // Note that this logic will break if a tex# index is skipped over in the shader. + if (gl_uniform.texunit_priority == UINT_MAX) + { + S32 idx; + if (sscanf(gl_uniform.name.c_str(), "tex%d", &idx)) + { + gl_uniform.texunit_priority = idx; + } + } + + gl_uniforms.push_back(gl_uniform); + } + + // Sort uniforms by texunit_priority + std::sort(gl_uniforms.begin(), gl_uniforms.end(), [](gl_uniform_data_t& lhs, gl_uniform_data_t& rhs) + { + return lhs.texunit_priority < rhs.texunit_priority; + }); + + // Sanity check + if (gl_uniforms.size() && gl_uniforms[0].name == "tex0") + { + llassert_always_msg(!has_diffuse, "Indexed textures and diffuseMap are incompatible!"); + } + + for (auto& gl_uniform : gl_uniforms) + { + mapUniform(gl_uniform, uniforms); } unbind(); @@ -526,7 +809,7 @@ void LLGLSLShader::bind() if (gGLManager.mHasShaderObjects) { LLVertexBuffer::unbind(); - glUseProgramObjectARB(mProgramObject); + gGL.setShader(mProgramObject); sCurBoundShader = mProgramObject; sCurBoundShaderPtr = this; if (mUniformsDirty) @@ -552,7 +835,7 @@ void LLGLSLShader::unbind() } } LLVertexBuffer::unbind(); - glUseProgramObjectARB(0); + gGL.setShader(0); sCurBoundShader = 0; sCurBoundShaderPtr = NULL; stop_glerror(); @@ -564,7 +847,7 @@ void LLGLSLShader::bindNoShader(void) LLVertexBuffer::unbind(); if (gGLManager.mHasShaderObjects) { - glUseProgramObjectARB(0); + gGL.setShader(0); sCurBoundShader = 0; sCurBoundShaderPtr = NULL; } @@ -699,6 +982,5 @@ void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GL void LLGLSLShader::setMinimumAlpha(F32 minimum) { - gGL.flush(); uniform1f(LLShaderMgr::MINIMUM_ALPHA, minimum); } diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index e57ac1702f..d1d9fde09e 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -56,6 +56,7 @@ class LLShaderFeatures S32 mIndexedTextureChannels; bool disableTextureIndex; bool hasAlphaMask; + bool attachNothing; // char numLights; @@ -72,16 +73,38 @@ class LLGLSLShader SG_SKY, SG_WATER }; + + struct gl_uniform_data_t { + std::string name; + GLenum type = -1; + GLint size = -1; + U32 texunit_priority = UINT_MAX; // Lower gets earlier texunits indices. + }; + static std::set sInstances; + static bool sProfileEnabled; + LLGLSLShader(S32 shader_class); ~LLGLSLShader(); static GLhandleARB sCurBoundShader; static LLGLSLShader* sCurBoundShaderPtr; + static S32 sIndexedTextureChannels; static bool sNoFixedFunction; + static void initProfile(); + static void finishProfile(bool emit_report = true); + + static void startProfile(); + static void stopProfile(U32 count, U32 mode); + void unload(); + void clearStats(); + void dumpStats(); + void placeProfileQuery(); + void readProfileQuery(U32 count, U32 mode); + BOOL createShader(std::vector * attributes, std::vector * uniforms, U32 varying_count = 0, @@ -91,7 +114,7 @@ class LLGLSLShader void attachObjects(GLhandleARB* objects = NULL, S32 count = 0); BOOL mapAttributes(const std::vector * attributes); BOOL mapUniforms(const std::vector *); - void mapUniform(GLint index, const std::vector *); + void mapUniform(const gl_uniform_data_t& gl_uniform, const std::vector *); S32 getUniformFromIndex(const U32 index) { if (mUniform.size() <= index) @@ -130,6 +153,7 @@ class LLGLSLShader F32 val = x; if (updateUniform(mValueVec4, getUniformFromIndex(index), &val)) { + gGL.syncShaders(); glUniform1iARB(mUniform[index], x); } } @@ -137,6 +161,7 @@ class LLGLSLShader { if (updateUniform(mValueVec4, getUniformFromIndex(index), &x)) { + gGL.syncShaders(); glUniform1fARB(mUniform[index], x); } } @@ -145,6 +170,7 @@ class LLGLSLShader F32 val[] = { x, y }; if (updateUniform(mValueVec4, getUniformFromIndex(index), val)) { + gGL.syncShaders(); glUniform2fARB(mUniform[index], x, y); } } @@ -153,6 +179,7 @@ class LLGLSLShader F32 val[] = { x, y, z }; if (updateUniform(mValueVec4, getUniformFromIndex(index), val)) { + gGL.syncShaders(); glUniform3fARB(mUniform[index], x, y, z); } } @@ -161,6 +188,7 @@ class LLGLSLShader F32 val[] = { x, y, z, w }; if (updateUniform(mValueVec4, getUniformFromIndex(index), val)) { + gGL.syncShaders(); glUniform4fARB(mUniform[index], x, y, z, w); } } @@ -169,6 +197,7 @@ class LLGLSLShader F32 val[] = { static_cast(v[0]) }; if (updateUniform(mValueVec4, getUniformFromIndex(index), val) || count > 1) { + gGL.syncShaders(); glUniform1ivARB(mUniform[index], count, v); } } @@ -176,6 +205,7 @@ class LLGLSLShader { if (updateUniform(mValueVec4, getUniformFromIndex(index), v) || count > 1) { + gGL.syncShaders(); glUniform1fvARB(mUniform[index], count, v); } } @@ -183,6 +213,7 @@ class LLGLSLShader { if (updateUniform(mValueVec4, getUniformFromIndex(index), v) || count > 1) { + gGL.syncShaders(); glUniform2fvARB(mUniform[index], count, v); } } @@ -190,6 +221,7 @@ class LLGLSLShader { if (updateUniform(mValueVec4, getUniformFromIndex(index), v) || count > 1) { + gGL.syncShaders(); glUniform3fvARB(mUniform[index], count, v); } } @@ -197,6 +229,7 @@ class LLGLSLShader { if (updateUniform(mValueVec4, getUniformFromIndex(index), v) || count > 1) { + gGL.syncShaders(); glUniform4fvARB(mUniform[index], count, v); } } @@ -204,6 +237,7 @@ class LLGLSLShader { if (updateUniform(mValueMat3, getUniformFromIndex(index), v) || count > 1) { + gGL.syncShaders(); glUniformMatrix3fvARB(mUniform[index], count, transpose, v); } } @@ -211,6 +245,7 @@ class LLGLSLShader { if (updateUniform(mValueMat4, getUniformFromIndex(index), v) || count > 1) { + gGL.syncShaders(); glUniformMatrix3x4fv(mUniform[index], count, transpose, v); } } @@ -218,6 +253,7 @@ class LLGLSLShader { if (updateUniform(mValueMat4, getUniformFromIndex(index), v) || count > 1) { + gGL.syncShaders(); glUniformMatrix4fvARB(mUniform[index], count, transpose, v); } } @@ -229,6 +265,7 @@ class LLGLSLShader F32 val = i; if (updateUniform(mValueVec4, getUniformLocation(uniform), &val)) { + gGL.syncShaders(); glUniform1iARB(location, i); } } @@ -239,6 +276,7 @@ class LLGLSLShader return; if (updateUniform(mValueVec4, location, &v)) { + gGL.syncShaders(); glUniform1fARB(location, v); } } @@ -250,6 +288,7 @@ class LLGLSLShader F32 val[] = { x, y }; if (updateUniform(mValueVec4, location, val)) { + gGL.syncShaders(); glUniform2fARB(location, x, y); } } @@ -261,6 +300,7 @@ class LLGLSLShader F32 val[] = { x, y, z }; if (updateUniform(mValueVec4, location, val)) { + gGL.syncShaders(); glUniform3fARB(location, x, y, z); } } @@ -271,6 +311,7 @@ class LLGLSLShader return; if (updateUniform(mValueVec4, location, v)) { + gGL.syncShaders(); glUniform1fvARB(location, count, v); } } @@ -281,6 +322,7 @@ class LLGLSLShader return; if (updateUniform(mValueVec4, location, v)) { + gGL.syncShaders(); glUniform2fvARB(location, count, v); } } @@ -291,6 +333,7 @@ class LLGLSLShader return; if (updateUniform(mValueVec4, location, v)) { + gGL.syncShaders(); glUniform3fvARB(location, count, v); } } @@ -301,6 +344,7 @@ class LLGLSLShader return; if (updateUniform(mValueVec4, location, v)) { + gGL.syncShaders(); glUniform4fvARB(location, count, v); } } @@ -311,6 +355,7 @@ class LLGLSLShader return; if (updateUniform(mValueMat4, location, v)) { + gGL.syncShaders(); glUniformMatrix4fvARB(location, count, transpose, v); } } @@ -329,6 +374,7 @@ class LLGLSLShader { if (gDebugGL) { + gGL.syncShaders(); stop_glerror(); if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.String().c_str())) { @@ -379,6 +425,7 @@ class LLGLSLShader U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask()) std::vector mUniform; //lookup table of uniform enum to uniform location LLStaticStringTable mUniformMap; //lookup map of uniform name to uniform location + std::map mUniformNameMap; //lookup map of uniform location to uniform name //There are less naive ways to do this than just having several vectors for the differing types, but this method is of least complexity and has some inherent type-safety. std::vector > mValueVec4; //lookup map of uniform location to last known value std::vector > mValueMat3; //lookup map of uniform location to last known value @@ -395,6 +442,23 @@ class LLGLSLShader std::vector< std::pair< std::string, GLenum > > mShaderFiles; std::string mName; std::map mDefines; + + //statistcis for profiling shader performance + U32 mTimerQuery; + U32 mSamplesQuery; + U64 mTimeElapsed; + static U64 sTotalTimeElapsed; + U32 mTrianglesDrawn; + static U32 sTotalTrianglesDrawn; + U64 mSamplesDrawn; + static U64 sTotalSamplesDrawn; + U32 mDrawCalls; + static U32 sTotalDrawCalls; + + bool mTextureStateFetched; + std::vector mTextureMagFilter; + std::vector mTextureMinFilter; + }; //UI shader (declared here so llui_libtest will link properly) diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h index 266f266a6a..3a81eac94f 100644 --- a/indra/llrender/llglstates.h +++ b/indra/llrender/llglstates.h @@ -53,181 +53,128 @@ class LLGLDepthTest //---------------------------------------------------------------------------- -class LLGLSDefault +struct LLGLSDefault { -protected: - LLGLEnable mColorMaterial; - LLGLDisable mAlphaTest, mBlend, mCullFace, mDither, mFog, - mLineSmooth, mLineStipple, mNormalize, mPolygonSmooth, - mGLMultisample; -public: - LLGLSDefault() - : - // Enable - mColorMaterial(GL_COLOR_MATERIAL), - // Disable - mAlphaTest(GL_ALPHA_TEST), - mBlend(GL_BLEND), - mCullFace(GL_CULL_FACE), - mDither(GL_DITHER), - mFog(GL_FOG), - mLineSmooth(GL_LINE_SMOOTH), - mLineStipple(GL_LINE_STIPPLE), - mNormalize(GL_NORMALIZE), - mPolygonSmooth(GL_POLYGON_SMOOTH), - mGLMultisample(GL_MULTISAMPLE_ARB) - { } -}; - -class LLGLSObjectSelect -{ -protected: - LLGLDisable mBlend, mFog, mAlphaTest; - LLGLEnable mCullFace; -public: - LLGLSObjectSelect() - : mBlend(GL_BLEND), mFog(GL_FOG), - mAlphaTest(GL_ALPHA_TEST), - mCullFace(GL_CULL_FACE) - { } +private: + LLGLEnable mColorMaterial; + LLGLDisable mAlphaTest; + LLGLDisable mBlend; + LLGLDisable mCullFace; + LLGLDisable mDither; + LLGLDisable mFog; + LLGLDisable mLineSmooth; + LLGLDisable mLineStipple; + LLGLDisable mNormalize; + LLGLDisable mPolygonSmooth; + LLGLDisable mGLMultisample; + LLGLDisable lighting; +}; + +struct LLGLSObjectSelect +{ +private: + LLGLDisable mBlend; + LLGLDisable mAlphaTest; + LLGLDisable mFog; + LLGLEnable mCullFace; }; -class LLGLSObjectSelectAlpha +struct LLGLSObjectSelectAlpha { -protected: - LLGLEnable mAlphaTest; -public: - LLGLSObjectSelectAlpha() - : mAlphaTest(GL_ALPHA_TEST) - {} +private: + LLGLEnable mAlphaTest; }; //---------------------------------------------------------------------------- -class LLGLSUIDefault +struct LLGLSUIDefault { -protected: - LLGLEnable mBlend, mAlphaTest; - LLGLDisable mCullFace; +private: + LLGLEnable mBlend; + LLGLEnable mAlphaTest; + LLGLDisable mCullFace; + LLGLDisable mMSAA; + //LLGLEnable mScissor; LLGLDepthTest mDepthTest; - LLGLDisable mMSAA; public: - LLGLSUIDefault() - : mBlend(GL_BLEND), mAlphaTest(GL_ALPHA_TEST), - mCullFace(GL_CULL_FACE), - mDepthTest(GL_FALSE, GL_TRUE, GL_LEQUAL), - mMSAA(GL_MULTISAMPLE_ARB) + LLGLSUIDefault() + : mDepthTest(GL_FALSE, GL_TRUE, GL_LEQUAL) {} }; -class LLGLSNoAlphaTest // : public LLGLSUIDefault +struct LLGLSNoAlphaTest // : public LLGLSUIDefault { -protected: - LLGLDisable mAlphaTest; -public: - LLGLSNoAlphaTest() - : mAlphaTest(GL_ALPHA_TEST) - {} +private: + LLGLDisable mAlphaTest; }; //---------------------------------------------------------------------------- -class LLGLSFog +struct LLGLSFog { -protected: - LLGLEnable mFog; -public: - LLGLSFog() - : mFog(GL_FOG) - {} +private: + LLGLEnable mFog; }; -class LLGLSNoFog +struct LLGLSNoFog { -protected: - LLGLDisable mFog; -public: - LLGLSNoFog() - : mFog(GL_FOG) - {} +private: + LLGLDisable mFog; }; //---------------------------------------------------------------------------- -class LLGLSPipeline +struct LLGLSPipeline { -protected: - LLGLEnable mCullFace; +private: + LLGLEnable mCullFace; LLGLDepthTest mDepthTest; public: LLGLSPipeline() - : mCullFace(GL_CULL_FACE), - mDepthTest(GL_TRUE, GL_TRUE, GL_LEQUAL) - { } + : mDepthTest(GL_TRUE, GL_TRUE, GL_LEQUAL) + {} }; -class LLGLSPipelineAlpha // : public LLGLSPipeline +struct LLGLSPipelineAlpha // : public LLGLSPipeline { -protected: - LLGLEnable mBlend, mAlphaTest; -public: - LLGLSPipelineAlpha() - : mBlend(GL_BLEND), - mAlphaTest(GL_ALPHA_TEST) - { } +private: + LLGLEnable mAlphaTest; + LLGLEnable mBlend; }; -class LLGLSPipelineEmbossBump +struct LLGLSPipelineEmbossBump { -protected: - LLGLDisable mFog; -public: - LLGLSPipelineEmbossBump() - : mFog(GL_FOG) - { } +private: + LLGLDisable mFog; }; -class LLGLSPipelineSelection +struct LLGLSPipelineSelection { -protected: - LLGLDisable mCullFace; -public: - LLGLSPipelineSelection() - : mCullFace(GL_CULL_FACE) - {} +private: + LLGLDisable mCullFace; }; -class LLGLSPipelineAvatar +struct LLGLSPipelineAvatar { -protected: - LLGLEnable mNormalize; -public: - LLGLSPipelineAvatar() - : mNormalize(GL_NORMALIZE) - {} +private: + LLGLEnable mNormalize; }; -class LLGLSPipelineSkyBox +struct LLGLSPipelineSkyBox { -protected: - LLGLDisable mAlphaTest, mCullFace, mFog; -public: - LLGLSPipelineSkyBox() - : mAlphaTest(GL_ALPHA_TEST), mCullFace(GL_CULL_FACE), mFog(GL_FOG) - { } +private: + LLGLDisable mAlphaTest; + LLGLDisable mCullFace; + LLGLDisable mFog; + LLGLDisable mLighting; }; -class LLGLSTracker +struct LLGLSTracker { -protected: - LLGLEnable mCullFace, mBlend, mAlphaTest; -public: - LLGLSTracker() : - mCullFace(GL_CULL_FACE), - mBlend(GL_BLEND), - mAlphaTest(GL_ALPHA_TEST) - - { } +private: + LLGLEnable mAlphaTest; + LLGLEnable mBlend; + LLGLEnable mCullFace; }; //---------------------------------------------------------------------------- diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index 5154a854fe..3e86385954 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -46,28 +46,25 @@ S32 LLGLTexture::getCategoryFromIndex(S32 index) return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ; } -LLGLTexture::LLGLTexture(BOOL usemipmaps) +LLGLTexture::LLGLTexture(BOOL usemipmaps, bool allow_compresssion) { - init(); - mUseMipMaps = usemipmaps; + init(usemipmaps, allow_compresssion); } -LLGLTexture::LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) +LLGLTexture::LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, bool allow_compresssion) { - init(); + init(usemipmaps, allow_compresssion); mFullWidth = width ; mFullHeight = height ; - mUseMipMaps = usemipmaps ; mComponents = components ; setTexelsPerImage(); } -LLGLTexture::LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) +LLGLTexture::LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps, bool allow_compresssion) { - init(); - mUseMipMaps = usemipmaps ; + init(usemipmaps, allow_compresssion); // Create an empty image of the specified size and width - mGLTexturep = new LLImageGL(raw, usemipmaps) ; + mGLTexturep = new LLImageGL(raw, usemipmaps, mAllowCompression) ; } LLGLTexture::~LLGLTexture() @@ -75,14 +72,15 @@ LLGLTexture::~LLGLTexture() cleanup(); } -void LLGLTexture::init() +void LLGLTexture::init(bool use_mipmaps, bool allow_compression) { mBoostLevel = LLGLTexture::BOOST_NONE; + mUseMipMaps = use_mipmaps; + mAllowCompression = allow_compression; mFullWidth = 0; mFullHeight = 0; mTexelsPerImage = 0 ; - mUseMipMaps = FALSE ; mComponents = 0 ; mTextureState = NO_DELETE ; @@ -146,7 +144,7 @@ void LLGLTexture::generateGLTexture() { if(mGLTexturep.isNull()) { - mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ; + mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps, mAllowCompression) ; } } @@ -167,7 +165,7 @@ BOOL LLGLTexture::createGLTexture() return mGLTexturep->createGLTexture() ; } -BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category) +BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, LLImageGL::GLTextureName* usename, BOOL to_create, S32 category) { llassert(mGLTexturep.notNull()) ; @@ -298,7 +296,7 @@ LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const return mGLTexturep->getAddressMode() ; } -S32 LLGLTexture::getTextureMemory() const +S32Bytes LLGLTexture::getTextureMemory() const { llassert(mGLTexturep.notNull()) ; @@ -312,11 +310,11 @@ LLGLenum LLGLTexture::getPrimaryFormat() const return mGLTexturep->getPrimaryFormat() ; } -BOOL LLGLTexture::getIsAlphaMask(const F32 max_rmse) const +BOOL LLGLTexture::getIsAlphaMask(const F32 max_rmse, const F32 max_mid) const { llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getIsAlphaMask(max_rmse) ; + return mGLTexturep->getIsAlphaMask(max_rmse, max_mid) ; } BOOL LLGLTexture::getMask(const LLVector2 &tc) @@ -395,4 +393,4 @@ void LLGLTexture::setTexelsPerImage() S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); mTexelsPerImage = (F32)fullwidth * fullheight; -} \ No newline at end of file +} diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 1b61078583..122ae77723 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -49,6 +49,7 @@ class LLGLTexture : public LLTexture enum EBoostLevel { BOOST_NONE = 0, + BOOST_ALM , //acts like NONE when ALM is on, max discard when ALM is off BOOST_AVATAR_BAKED , BOOST_AVATAR , BOOST_CLOUDS , @@ -97,9 +98,9 @@ class LLGLTexture : public LLTexture LOG_CLASS(LLGLTexture); public: - LLGLTexture(BOOL usemipmaps = TRUE); - LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) ; - LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; + LLGLTexture(BOOL usemipmaps = TRUE, bool allow_compresssion=false); + LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps, bool allow_compresssion=false) ; + LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, bool allow_compresssion=false) ; virtual void dump(); // debug info to llinfos @@ -123,8 +124,7 @@ class LLGLTexture : public LLTexture BOOL hasGLTexture() const ; LLGLuint getTexName() const ; BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLGLTexture::OTHER); - + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, LLImageGL::GLTextureName* usename = nullptr, BOOL to_create = TRUE, S32 category = LLGLTexture::OTHER); void setFilteringOption(LLTexUnit::eTextureFilterOptions option); void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); void setAddressMode(LLTexUnit::eTextureAddressMode mode); @@ -138,9 +138,9 @@ class LLGLTexture : public LLTexture S32 getDiscardLevel() const; S8 getComponents() const; BOOL getBoundRecently() const; - S32 getTextureMemory() const ; + S32Bytes getTextureMemory() const ; LLGLenum getPrimaryFormat() const; - BOOL getIsAlphaMask(const F32 max_rmse) const ; + BOOL getIsAlphaMask(const F32 max_rmse, const F32 max_mid) const ; LLTexUnit::eTextureType getTarget(void) const ; BOOL getMask(const LLVector2 &tc); F32 getTimePassedSinceLastBound(); @@ -168,7 +168,7 @@ class LLGLTexture : public LLTexture private: void cleanup(); - void init(); + void init(bool use_mipmaps, bool allow_compression); protected: void setTexelsPerImage(); @@ -187,7 +187,8 @@ class LLGLTexture : public LLTexture //GL texture LLPointer mGLTexturep ; - S8 mDontDiscard; // Keep full res version of this image (for UI, etc) + bool mDontDiscard; // Keep full res version of this image (for UI, etc) + bool mAllowCompression; protected: LLGLTextureState mTextureState ; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 68ff5d6a07..c1a9c51e92 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -50,9 +50,9 @@ U32 wpo2(U32 i); U32 LLImageGL::sUniqueCount = 0; U32 LLImageGL::sBindCount = 0; -S32 LLImageGL::sGlobalTextureMemoryInBytes = 0; -S32 LLImageGL::sBoundTextureMemoryInBytes = 0; -S32 LLImageGL::sCurBoundTextureMemory = 0; +S64Bytes LLImageGL::sGlobalTextureMemory(0); +S64Bytes LLImageGL::sBoundTextureMemory(0); +S64Bytes LLImageGL::sCurBoundTextureMemory(0); S32 LLImageGL::sCount = 0; BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; @@ -78,14 +78,17 @@ S32 LLImageGL::sCurTexPickSize = -1 ; LLPointer LLImageGL::sHighlightTexturep = NULL; S32 LLImageGL::sMaxCategories = 1 ; -std::vector LLImageGL::sTextureMemByCategory; -std::vector LLImageGL::sTextureMemByCategoryBound ; -std::vector LLImageGL::sTextureCurMemByCategoryBound ; +std::vector LLImageGL::sTextureMemByCategory; +std::vector LLImageGL::sTextureMemByCategoryBound ; +std::vector LLImageGL::sTextureCurMemByCategoryBound ; //------------------------ // **************************************************************************************************** //End for texture auditing use only // **************************************************************************************************** +//static std::vector sActiveTextureNames; +//static std::vector sDeletedTextureNames; + // ************************************************************************************** //below are functions for debug use //do not delete them even though they are not currently being used. @@ -118,9 +121,9 @@ void LLImageGL::checkTexSize(bool forced) const GLint texname; glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname); BOOL error = FALSE; - if (texname != mTexName) + if (texname != getTexName()) { - LL_INFOS() << "Bound: " << texname << " Should bind: " << mTexName << " Default: " << LLImageGL::sDefaultGLTexture->getTexName() << LL_ENDL; + LL_INFOS() << "Bound: " << texname << " Should bind: " << getTexName() << " Default: " << (LLImageGL::sDefaultGLTexture ? LLImageGL::sDefaultGLTexture->getTexName() : 0) << LL_ENDL; error = TRUE; if (gDebugSession) @@ -219,7 +222,7 @@ void LLImageGL::setHighlightTexture(S32 category) } } } - sHighlightTexturep->createGLTexture(0, image_raw, 0, TRUE, category); + sHighlightTexturep->createGLTexture(0, image_raw, nullptr, TRUE, category); image_raw = NULL; } @@ -286,14 +289,14 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) //---------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_STATS("Image Stats"); +static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_STATS("Image Stats"); // static void LLImageGL::updateStats(F32 current_time) { - LLFastTimer t(FTM_IMAGE_UPDATE_STATS); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_STATS); sLastFrameTime = current_time; - sBoundTextureMemoryInBytes = sCurBoundTextureMemory; - sCurBoundTextureMemory = 0; + sBoundTextureMemory = sCurBoundTextureMemory; + sCurBoundTextureMemory = S64Bytes(0); if(gAuditTexture) { @@ -305,22 +308,22 @@ void LLImageGL::updateStats(F32 current_time) for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++) { sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ; - sTextureCurMemByCategoryBound[i] = 0 ; + sTextureCurMemByCategoryBound[i] = (S64Bytes)0 ; } } } //static -S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) +S32 LLImageGL::updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category) { if(gAuditTexture && ncomponents > 0 && category > -1) { - sTextureCurBoundCounter[getTextureCounterIndex(mem / ncomponents)]++ ; + sTextureCurBoundCounter[getTextureCounterIndex(mem.value() / ncomponents)]++ ; sTextureCurMemByCategoryBound[category] += mem ; } LLImageGL::sCurBoundTextureMemory += mem ; - return LLImageGL::sCurBoundTextureMemory; + return LLImageGL::sCurBoundTextureMemory.value(); } //---------------------------------------------------------------------------- @@ -328,47 +331,48 @@ S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 categ //static void LLImageGL::destroyGL(BOOL save_state) { - for (S32 stage = 0; stage < gGLManager.mNumTextureUnits; stage++) - { - gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); - } - - sAllowReadBackRaw = true ; - std::set stored_images; - for (std::set::iterator iter = sImageList.begin(); - iter != sImageList.end(); iter++) + LLTexUnit::sWhiteTexture = 0; + if (save_state) { - LLImageGL* glimage = *iter; - if (glimage->mTexName) + U32 count = 0; + sAllowReadBackRaw = true; + for (std::set::iterator iter = sImageList.begin(); + iter != sImageList.end(); iter++) { - if (save_state && glimage->isGLTextureCreated() && glimage->mComponents) + LLImageGL* glimage = *iter; + GLuint tex = glimage->getTexName(); + if (tex) { - glimage->mSaveData = new LLImageRaw; - if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it. - { - delete glimage; - } - else + if (glimage->isGLTextureCreated()) { - glimage->mSaveDiscardLevel = glimage->mCurrentDiscardLevel; - stored_images.insert(glimage); - glimage->destroyGLTexture(); + glimage->mSaveData = new LLImageRaw; + if (glimage->mComponents && glimage->readBackRaw(-1, glimage->mSaveData, false))//necessary, keep it. + { + ++count; + glimage->mSaveDiscardLevel = glimage->mCurrentDiscardLevel; + glimage->destroyGLTexture(); + continue; + } } } - + glimage->mSaveData = nullptr; + glimage->forceToInvalidateGLTexture(); stop_glerror(); } + LL_INFOS() << "Storing " << count << " images..." << LL_ENDL; + sAllowReadBackRaw = false; } - sImageList = stored_images; - LL_INFOS() << "Storing " << stored_images.size() << " images..." << LL_ENDL; - sAllowReadBackRaw = false ; + for (S32 stage = 0; stage < gGLManager.mNumTextureUnits; stage++) + { + gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); + } + //clean_validate_buffers(); } //static void LLImageGL::restoreGL() { - - std::set restored_images; + U32 count = 0; for (std::set::iterator iter = sImageList.begin(); iter != sImageList.end(); iter++) { @@ -377,22 +381,32 @@ void LLImageGL::restoreGL() { LL_ERRS() << "tex name is not 0." << LL_ENDL ; } - if (glimage->mSaveData.notNull() && glimage->getComponents() && - glimage->mSaveData->getComponents() && + LLPointer data = glimage->mSaveData; + glimage->mSaveData = nullptr; + if (data.notNull() && glimage->getComponents() && + data->getComponents() && glimage->mSaveDiscardLevel >= 0 && - glimage->createGLTexture(glimage->mSaveDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory())) + glimage->createGLTexture(glimage->mSaveDiscardLevel, data, nullptr, TRUE, glimage->getCategory())) { stop_glerror(); - restored_images.insert(glimage); + /*if (glimage->getHasGLTexture()) + { + LL_INFOS() << "Restored " << glimage << " texid:" << glimage->getTexName() << LL_ENDL; + } + else + { + LL_INFOS() << "Restored " << glimage << " texid: (null)" << LL_ENDL; + }*/ + ++count; } else { - delete glimage; + //LL_INFOS() << "Skipped " << glimage << LL_ENDL; + glimage->forceToInvalidateGLTexture(); } } - restored_images = restored_images; - LL_INFOS() << "Restored " << restored_images.size() << " images" << LL_ENDL; + LL_INFOS() << "Restored " << count << " images" << LL_ENDL; } //static @@ -433,29 +447,29 @@ BOOL LLImageGL::create(LLPointer& dest, const LLImageRaw* imageraw, B //---------------------------------------------------------------------------- -LLImageGL::LLImageGL(BOOL usemipmaps) - : mSaveData(0), mSaveDiscardLevel(-1) +LLImageGL::LLImageGL(BOOL usemipmaps, bool allow_compression) + : mSaveData(0), mSaveDiscardLevel(-1), mIsCompressed(false) { - init(usemipmaps); + init(usemipmaps, allow_compression); setSize(0, 0, 0); sImageList.insert(this); sCount++; } -LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps) +LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps, bool allow_compression) : mSaveData(0), mSaveDiscardLevel(-1) { llassert( components <= 4 ); - init(usemipmaps); + init(usemipmaps, allow_compression); setSize(width, height, components); sImageList.insert(this); sCount++; } -LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps) +LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps, bool allow_compression) : mSaveData(0), mSaveDiscardLevel(-1) { - init(usemipmaps); + init(usemipmaps, allow_compression); setSize(0, 0, 0); sImageList.insert(this); sCount++; @@ -474,37 +488,36 @@ LLImageGL::~LLImageGL() const S8 INVALID_OFFSET = -99 ; -void LLImageGL::init(BOOL usemipmaps) +void LLImageGL::init(BOOL usemipmaps, bool allow_compression) { // keep these members in the same order as declared in llimagehl.h // so that it is obvious by visual inspection if we forgot to // init a field. - mTextureMemory = 0; + mTextureMemory = (S32Bytes)0; mLastBindTime = 0.f; mPickMask = NULL; mPickMaskWidth = 0; mPickMaskHeight = 0; mUseMipMaps = usemipmaps; + mAllowCompression = allow_compression; mHasExplicitFormat = FALSE; mAutoGenMips = FALSE; mIsMask = FALSE; mMaskRMSE = 1.f ; + mMaskMidPercentile = 1.f; mNeedsAlphaAndPickMask = FALSE ; mAlphaStride = 0 ; mAlphaOffset = INVALID_OFFSET ; mGLTextureCreated = FALSE ; - mTexName = 0; + mTexName.reset(); mWidth = 0; mHeight = 0; mCurrentDiscardLevel = -1; - - - mAllowCompression = true; mTarget = GL_TEXTURE_2D; mBindTarget = LLTexUnit::TT_TEXTURE; @@ -571,12 +584,12 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve // Check if dimensions are a power of two! if (!checkSize(width,height)) { - LL_WARNS() << llformat("Texture has non power of two dimension: %dx%d",width,height) << " Unless on Aurora-Sim, beware." << LL_ENDL; + LL_WARNS() << llformat("Texture has non power of two dimension: %dx%d",width,height) << " Unless on WhiteCore, beware." << LL_ENDL; } if (mTexName) { -// LL_WARNS() << "Setting Size of LLImageGL with existing mTexName = " << mTexName << LL_ENDL; +// LL_WARNS() << "Setting Size of LLImageGL with existing mTexName = " << getTexName() << LL_ENDL; destroyGLTexture(); } @@ -633,7 +646,7 @@ void LLImageGL::dump() << LL_ENDL; LL_INFOS() << " mTextureMemory " << mTextureMemory - << " mTexNames " << mTexName + << " mTexNames " << getTexName() << " mIsResident " << S32(mIsResident) << LL_ENDL; } @@ -644,9 +657,9 @@ void LLImageGL::forceUpdateBindStats(void) const mLastBindTime = sLastFrameTime; } -BOOL LLImageGL::updateBindStats(S32 tex_mem) const +BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const { - if (mTexName != 0) + if (getTexName()) { #ifdef DEBUG_MISS mMissed = ! getIsResident(TRUE); @@ -697,10 +710,10 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) setImage(rawdata, FALSE); } -static LLFastTimer::DeclareTimer FTM_SET_IMAGE("setImage"); +static LLTrace::BlockTimerStatHandle FTM_SET_IMAGE("setImage"); void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { - LLFastTimer t(FTM_SET_IMAGE); + LL_RECORD_BLOCK_TIME(FTM_SET_IMAGE); bool is_compressed = false; if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { @@ -724,7 +737,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) llverify(gGL.getTexUnit(0)->bind(this)); - + mIsCompressed = false; if (mUseMipMaps) { if (data_hasmips) @@ -749,10 +762,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) S32 tex_size = dataFormatBytes(mFormatPrimary, w, h); glCompressedTexImage2DARB(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in); stop_glerror(); + mIsCompressed = true; } else { -// LLFastTimer t2(FTM_TEMP4); +// LL_RECORD_BLOCK_TIME(FTM_TEMP4); if(mFormatSwapBytes) { @@ -760,7 +774,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) stop_glerror(); } - LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in, mAllowCompression); + mIsCompressed = LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in, mAllowCompression); if (gl_level == 0) { analyzeAlpha(data_in, w, h); @@ -784,7 +798,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { stop_glerror(); { -// LLFastTimer t2(FTM_TEMP4); +// LL_RECORD_BLOCK_TIME(FTM_TEMP4); if(mFormatSwapBytes) { @@ -805,7 +819,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE); } - LLImageGL::setManualImage(mTarget, 0, mFormatInternal, + mIsCompressed = LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, mFormatPrimary, mFormatType, data_in, mAllowCompression); @@ -869,14 +883,14 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } llassert(w > 0 && h > 0 && cur_mip_data); { -// LLFastTimer t1(FTM_TEMP4); +// LL_RECORD_BLOCK_TIME(FTM_TEMP4); if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } - LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression); + mIsCompressed = LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression); if (m == 0) { analyzeAlpha(data_in, w, h); @@ -923,6 +937,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) S32 tex_size = dataFormatBytes(mFormatPrimary, w, h); glCompressedTexImage2DARB(mTarget, 0, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in); stop_glerror(); + mIsCompressed = true; } else { @@ -932,7 +947,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) stop_glerror(); } - LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, + mIsCompressed = LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, mFormatPrimary, mFormatType, (GLvoid *)data_in, mAllowCompression); analyzeAlpha(data_in, w, h); @@ -958,7 +973,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 { return TRUE; } - if (mTexName == 0) + if (!getTexName()) { // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18 //LL_WARNS() << "Setting subimage on image without GL texture" << LL_ENDL; @@ -1026,7 +1041,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 datap += (y_pos * data_width + x_pos) * getComponents(); // Update the GL texture - BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName); + BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, getTexName()); if (!res) LL_ERRS() << "LLImageGL::setSubImage(): bindTexture failed" << LL_ENDL; stop_glerror(); @@ -1070,237 +1085,123 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ } } +/*void validate_add_texture(U32 name) +{ + auto found = std::find(sActiveTextureNames.begin(), sActiveTextureNames.end(), name); + if (found != sActiveTextureNames.end()) + { + LL_ERRS() << "Allocating allocated texture name " << name << LL_ENDL; + } + else + { + //LL_INFOS() << "Allocated buffer name " << name << LL_ENDL; + sActiveTextureNames.push_back(name); + } +} + +void validate_del_texture(U32 name) +{ + auto found = std::find(sActiveTextureNames.begin(), sActiveTextureNames.end(), name); + if (found == sActiveTextureNames.end()) + { + if (std::find(sDeletedTextureNames.begin(), sDeletedTextureNames.end(), name) == sDeletedTextureNames.end()) + { + LL_ERRS() << "Deleting unknown texture name " << name << LL_ENDL; + } + else + { + LL_ERRS() << "Deleting deleted texture name " << name << LL_ENDL; + } + } + else + { + //LL_INFOS() << "Deleted buffer name " << name << LL_ENDL; + sActiveTextureNames.erase(found); + sDeletedTextureNames.push_back(name); + } + +} + +void validate_bind_texture(U32 name) +{ + auto found = std::find(sActiveTextureNames.begin(), sActiveTextureNames.end(), name); + if (found == sActiveTextureNames.end()) + { + if (std::find(sDeletedTextureNames.begin(), sDeletedTextureNames.end(), name) == sDeletedTextureNames.end()) + { + LL_ERRS() << "Binding unknown texture name " << name << LL_ENDL; + } + else + { + LL_ERRS() << "Binding deleted texture name " << name << LL_ENDL; + } + } +} + +void clean_validate_buffers() +{ + LL_INFOS() << "Clearing active buffer names. Count " << sActiveBufferNames.size() << LL_ENDL; + sActiveTextureNames.clear(); + LL_INFOS() << "Clearing deleted buffer names. Count " << sDeletedBufferNames.size() << LL_ENDL; + sDeletedTextureNames.clear(); +}*/ + // static -static LLFastTimer::DeclareTimer FTM_GENERATE_TEXTURES("generate textures"); +static LLTrace::BlockTimerStatHandle FTM_GENERATE_TEXTURES("generate textures"); void LLImageGL::generateTextures(S32 numTextures, U32 *textures) { - LLFastTimer t(FTM_GENERATE_TEXTURES); + LL_RECORD_BLOCK_TIME(FTM_GENERATE_TEXTURES); glGenTextures(numTextures, textures); + /*for (S32 i = 0; i < numTextures; ++i) + { + validate_add_texture(textures[i]); + }*/ } // static -void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) +void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, const std::vector& allocationData) { if (gGLManager.mInited) { + for (auto& entry : allocationData) + { + texMemoryDeallocated(entry); + } + glDeleteTextures(numTextures, textures); + /*for (S32 i = 0; i < numTextures; ++i) + { + validate_del_texture(textures[i]); + }*/ + } +} + +// static +void LLImageGL::texMemoryAllocated(const AllocationInfo& entry) +{ + sGlobalTextureMemory += (S64Bytes)entry.size; + if (gAuditTexture) + { + incTextureCounter((S64Bytes)entry.size, entry.components, entry.category); } } -//#include "crnlib.h" -struct DDS_PIXELFORMAT { - U32 dwSize; - U32 dwFlags; - U32 dwFourCC; - U32 dwRGBBitCount; - U32 dwRBitMask; - U32 dwGBitMask; - U32 dwBBitMask; - U32 dwABitMask; -}; - -typedef struct { - U32 dwSize; - U32 dwFlags; - U32 dwHeight; - U32 dwWidth; - U32 dwPitchOrLinearSize; - U32 dwDepth; - U32 dwMipMapCount; - U32 dwReserved1[11]; - DDS_PIXELFORMAT ddspf; - U32 dwCaps; - U32 dwCaps2; - U32 dwCaps3; - U32 dwCaps4; - U32 dwReserved2; -} DDS_HEADER; - -typedef enum DXGI_FORMAT { - DXGI_FORMAT_UNKNOWN = 0, - DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, - DXGI_FORMAT_R32G32B32A32_FLOAT = 2, - DXGI_FORMAT_R32G32B32A32_UINT = 3, - DXGI_FORMAT_R32G32B32A32_SINT = 4, - DXGI_FORMAT_R32G32B32_TYPELESS = 5, - DXGI_FORMAT_R32G32B32_FLOAT = 6, - DXGI_FORMAT_R32G32B32_UINT = 7, - DXGI_FORMAT_R32G32B32_SINT = 8, - DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, - DXGI_FORMAT_R16G16B16A16_FLOAT = 10, - DXGI_FORMAT_R16G16B16A16_UNORM = 11, - DXGI_FORMAT_R16G16B16A16_UINT = 12, - DXGI_FORMAT_R16G16B16A16_SNORM = 13, - DXGI_FORMAT_R16G16B16A16_SINT = 14, - DXGI_FORMAT_R32G32_TYPELESS = 15, - DXGI_FORMAT_R32G32_FLOAT = 16, - DXGI_FORMAT_R32G32_UINT = 17, - DXGI_FORMAT_R32G32_SINT = 18, - DXGI_FORMAT_R32G8X24_TYPELESS = 19, - DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, - DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, - DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, - DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, - DXGI_FORMAT_R10G10B10A2_UNORM = 24, - DXGI_FORMAT_R10G10B10A2_UINT = 25, - DXGI_FORMAT_R11G11B10_FLOAT = 26, - DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, - DXGI_FORMAT_R8G8B8A8_UNORM = 28, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, - DXGI_FORMAT_R8G8B8A8_UINT = 30, - DXGI_FORMAT_R8G8B8A8_SNORM = 31, - DXGI_FORMAT_R8G8B8A8_SINT = 32, - DXGI_FORMAT_R16G16_TYPELESS = 33, - DXGI_FORMAT_R16G16_FLOAT = 34, - DXGI_FORMAT_R16G16_UNORM = 35, - DXGI_FORMAT_R16G16_UINT = 36, - DXGI_FORMAT_R16G16_SNORM = 37, - DXGI_FORMAT_R16G16_SINT = 38, - DXGI_FORMAT_R32_TYPELESS = 39, - DXGI_FORMAT_D32_FLOAT = 40, - DXGI_FORMAT_R32_FLOAT = 41, - DXGI_FORMAT_R32_UINT = 42, - DXGI_FORMAT_R32_SINT = 43, - DXGI_FORMAT_R24G8_TYPELESS = 44, - DXGI_FORMAT_D24_UNORM_S8_UINT = 45, - DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, - DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, - DXGI_FORMAT_R8G8_TYPELESS = 48, - DXGI_FORMAT_R8G8_UNORM = 49, - DXGI_FORMAT_R8G8_UINT = 50, - DXGI_FORMAT_R8G8_SNORM = 51, - DXGI_FORMAT_R8G8_SINT = 52, - DXGI_FORMAT_R16_TYPELESS = 53, - DXGI_FORMAT_R16_FLOAT = 54, - DXGI_FORMAT_D16_UNORM = 55, - DXGI_FORMAT_R16_UNORM = 56, - DXGI_FORMAT_R16_UINT = 57, - DXGI_FORMAT_R16_SNORM = 58, - DXGI_FORMAT_R16_SINT = 59, - DXGI_FORMAT_R8_TYPELESS = 60, - DXGI_FORMAT_R8_UNORM = 61, - DXGI_FORMAT_R8_UINT = 62, - DXGI_FORMAT_R8_SNORM = 63, - DXGI_FORMAT_R8_SINT = 64, - DXGI_FORMAT_A8_UNORM = 65, - DXGI_FORMAT_R1_UNORM = 66, - DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, - DXGI_FORMAT_R8G8_B8G8_UNORM = 68, - DXGI_FORMAT_G8R8_G8B8_UNORM = 69, - DXGI_FORMAT_BC1_TYPELESS = 70, - DXGI_FORMAT_BC1_UNORM = 71, - DXGI_FORMAT_BC1_UNORM_SRGB = 72, - DXGI_FORMAT_BC2_TYPELESS = 73, - DXGI_FORMAT_BC2_UNORM = 74, - DXGI_FORMAT_BC2_UNORM_SRGB = 75, - DXGI_FORMAT_BC3_TYPELESS = 76, - DXGI_FORMAT_BC3_UNORM = 77, - DXGI_FORMAT_BC3_UNORM_SRGB = 78, - DXGI_FORMAT_BC4_TYPELESS = 79, - DXGI_FORMAT_BC4_UNORM = 80, - DXGI_FORMAT_BC4_SNORM = 81, - DXGI_FORMAT_BC5_TYPELESS = 82, - DXGI_FORMAT_BC5_UNORM = 83, - DXGI_FORMAT_BC5_SNORM = 84, - DXGI_FORMAT_B5G6R5_UNORM = 85, - DXGI_FORMAT_B5G5R5A1_UNORM = 86, - DXGI_FORMAT_B8G8R8A8_UNORM = 87, - DXGI_FORMAT_B8G8R8X8_UNORM = 88, - DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, - DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, - DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, - DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, - DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, - DXGI_FORMAT_BC6H_TYPELESS = 94, - DXGI_FORMAT_BC6H_UF16 = 95, - DXGI_FORMAT_BC6H_SF16 = 96, - DXGI_FORMAT_BC7_TYPELESS = 97, - DXGI_FORMAT_BC7_UNORM = 98, - DXGI_FORMAT_BC7_UNORM_SRGB = 99, - DXGI_FORMAT_AYUV = 100, - DXGI_FORMAT_Y410 = 101, - DXGI_FORMAT_Y416 = 102, - DXGI_FORMAT_NV12 = 103, - DXGI_FORMAT_P010 = 104, - DXGI_FORMAT_P016 = 105, - DXGI_FORMAT_420_OPAQUE = 106, - DXGI_FORMAT_YUY2 = 107, - DXGI_FORMAT_Y210 = 108, - DXGI_FORMAT_Y216 = 109, - DXGI_FORMAT_NV11 = 110, - DXGI_FORMAT_AI44 = 111, - DXGI_FORMAT_IA44 = 112, - DXGI_FORMAT_P8 = 113, - DXGI_FORMAT_A8P8 = 114, - DXGI_FORMAT_B4G4R4A4_UNORM = 115, - DXGI_FORMAT_P208 = 130, - DXGI_FORMAT_V208 = 131, - DXGI_FORMAT_V408 = 132, - DXGI_FORMAT_ASTC_4X4_UNORM = 134, - DXGI_FORMAT_ASTC_4X4_UNORM_SRGB = 135, - DXGI_FORMAT_ASTC_5X4_TYPELESS = 137, - DXGI_FORMAT_ASTC_5X4_UNORM = 138, - DXGI_FORMAT_ASTC_5X4_UNORM_SRGB = 139, - DXGI_FORMAT_ASTC_5X5_TYPELESS = 141, - DXGI_FORMAT_ASTC_5X5_UNORM = 142, - DXGI_FORMAT_ASTC_5X5_UNORM_SRGB = 143, - DXGI_FORMAT_ASTC_6X5_TYPELESS = 145, - DXGI_FORMAT_ASTC_6X5_UNORM = 146, - DXGI_FORMAT_ASTC_6X5_UNORM_SRGB = 147, - DXGI_FORMAT_ASTC_6X6_TYPELESS = 149, - DXGI_FORMAT_ASTC_6X6_UNORM = 150, - DXGI_FORMAT_ASTC_6X6_UNORM_SRGB = 151, - DXGI_FORMAT_ASTC_8X5_TYPELESS = 153, - DXGI_FORMAT_ASTC_8X5_UNORM = 154, - DXGI_FORMAT_ASTC_8X5_UNORM_SRGB = 155, - DXGI_FORMAT_ASTC_8X6_TYPELESS = 157, - DXGI_FORMAT_ASTC_8X6_UNORM = 158, - DXGI_FORMAT_ASTC_8X6_UNORM_SRGB = 159, - DXGI_FORMAT_ASTC_8X8_TYPELESS = 161, - DXGI_FORMAT_ASTC_8X8_UNORM = 162, - DXGI_FORMAT_ASTC_8X8_UNORM_SRGB = 163, - DXGI_FORMAT_ASTC_10X5_TYPELESS = 165, - DXGI_FORMAT_ASTC_10X5_UNORM = 166, - DXGI_FORMAT_ASTC_10X5_UNORM_SRGB = 167, - DXGI_FORMAT_ASTC_10X6_TYPELESS = 169, - DXGI_FORMAT_ASTC_10X6_UNORM = 170, - DXGI_FORMAT_ASTC_10X6_UNORM_SRGB = 171, - DXGI_FORMAT_ASTC_10X8_TYPELESS = 173, - DXGI_FORMAT_ASTC_10X8_UNORM = 174, - DXGI_FORMAT_ASTC_10X8_UNORM_SRGB = 175, - DXGI_FORMAT_ASTC_10X10_TYPELESS = 177, - DXGI_FORMAT_ASTC_10X10_UNORM = 178, - DXGI_FORMAT_ASTC_10X10_UNORM_SRGB = 179, - DXGI_FORMAT_ASTC_12X10_TYPELESS = 181, - DXGI_FORMAT_ASTC_12X10_UNORM = 182, - DXGI_FORMAT_ASTC_12X10_UNORM_SRGB = 183, - DXGI_FORMAT_ASTC_12X12_TYPELESS = 185, - DXGI_FORMAT_ASTC_12X12_UNORM = 186, - DXGI_FORMAT_ASTC_12X12_UNORM_SRGB = 187, - DXGI_FORMAT_FORCE_UINT = 0xffffffff -} DXGI_FORMAT; - -typedef enum D3D10_RESOURCE_DIMENSION { - D3D10_RESOURCE_DIMENSION_UNKNOWN = 0, - D3D10_RESOURCE_DIMENSION_BUFFER = 1, - D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2, - D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3, - D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4 -} D3D10_RESOURCE_DIMENSION; - -typedef struct { - DXGI_FORMAT dxgiFormat; - D3D10_RESOURCE_DIMENSION resourceDimension; - U32 miscFlag; - U32 arraySize; - U32 miscFlags2; -} DDS_HEADER_DXT10; +// static +void LLImageGL::texMemoryDeallocated(const AllocationInfo& entry) +{ + sGlobalTextureMemory -= (S64Bytes)entry.size; + if (gAuditTexture) + { + decTextureCounter((S64Bytes)entry.size, entry.components, entry.category); + } +} // static -static LLFastTimer::DeclareTimer FTM_SET_MANUAL_IMAGE("setManualImage"); -void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression) +static LLTrace::BlockTimerStatHandle FTM_SET_MANUAL_IMAGE("setManualImage"); +bool LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression) { - LLFastTimer t(FTM_SET_MANUAL_IMAGE); + LL_RECORD_BLOCK_TIME(FTM_SET_MANUAL_IMAGE); + bool compressed = false; std::vector scratch; if (LLRender::sGLCoreProfile) { @@ -1396,6 +1297,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt } if (LLImageGL::sCompressTextures && allow_compression) { + compressed = true; switch (intformat) { case GL_RED: @@ -1408,68 +1310,11 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt break; case GL_RGB: case GL_RGB8: - { - /*std::vector tex; - tex.resize(height*width); - for (U32 i = 0; i < tex.size(); ++i) - { - ((U8*)&tex[i])[0] = ((U8*)pixels)[i * 3]; - ((U8*)&tex[i])[1] = ((U8*)pixels)[i * 3 + 1]; - ((U8*)&tex[i])[2] = ((U8*)pixels)[i * 3 + 2]; - ((U8*)&tex[i])[3] = 255; - } - crn_comp_params comp_params; - comp_params.m_width = width; - comp_params.m_height = height; - comp_params.set_flag(cCRNCompFlagPerceptual, true); - comp_params.set_flag(cCRNCompFlagHierarchical, false); - comp_params.m_file_type = cCRNFileTypeDDS; - comp_params.m_format = cCRNFmtDXT5; - comp_params.m_pImages[0][0] = &tex[0]; - comp_params.m_quality_level = cCRNDXTQualityUber; - SYSTEM_INFO g_system_info; - GetSystemInfo(&g_system_info); - comp_params.m_num_helper_threads = std::max(0, (S32)g_system_info.dwNumberOfProcessors - 1); - crn_mipmap_params mip_params; - mip_params.m_gamma_filtering = true; - mip_params.m_mode = cCRNMipModeGenerateMips; - - crn_uint32 output_file_size; - void *compressed_data = crn_compress(comp_params, mip_params, output_file_size); - if (compressed_data) - { - glTexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE); - - U32 pos = sizeof(U32); - const DDS_HEADER& header = *(DDS_HEADER*)(((U8*)compressed_data) + pos); - pos += sizeof(DDS_HEADER); - if (header.ddspf.dwFlags & 0x4 && header.ddspf.dwFourCC == '01XD') - { - pos += sizeof(DDS_HEADER_DXT10); - } - - U32 num_mips = (header.dwFlags & 0x20000) ? header.dwMipMapCount : 1; - - U32 x = width; - U32 y = height; - for (U32 i = 0; i < num_mips; ++i) - { - size_t size = llmax(4u, x) / 4 * llmax(4u, y) / 4 * 16; - glCompressedTexImage2DARB(GL_TEXTURE_2D, i, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, x, y, 0, size, (const void*)(((U8*)compressed_data) + pos)); - x = (x + 1) >> 1; - y = (y + 1) >> 1; - pos += size; - } - crn_free_block(compressed_data); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_mips - 1); - return; - }*/ - } - + intformat = GL_COMPRESSED_RGB; break; case GL_RGBA: case GL_RGBA8: - //intformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + intformat = GL_COMPRESSED_RGBA; break; case GL_LUMINANCE: case GL_LUMINANCE8: @@ -1484,6 +1329,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt intformat = GL_COMPRESSED_ALPHA; break; default: + compressed = false; LL_WARNS() << "Could not compress format: " << std::hex << intformat << std::dec << LL_ENDL; break; } @@ -1492,14 +1338,15 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt stop_glerror(); glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels); stop_glerror(); + return compressed; } //create an empty GL texture: just create a texture name //the texture is assiciate with some image by calling glTexImage outside LLImageGL -static LLFastTimer::DeclareTimer FTM_CREATE_GL_TEXTURE1("createGLTexture()"); +static LLTrace::BlockTimerStatHandle FTM_CREATE_GL_TEXTURE1("createGLTexture()"); BOOL LLImageGL::createGLTexture() { - LLFastTimer t(FTM_CREATE_GL_TEXTURE1); + LL_RECORD_BLOCK_TIME(FTM_CREATE_GL_TEXTURE1); if (gGLManager.mIsDisabled) { LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL; @@ -1511,15 +1358,10 @@ BOOL LLImageGL::createGLTexture() llassert(gGLManager.mInited); stop_glerror(); - if(mTexName) - { - LLImageGL::deleteTextures(1, (reinterpret_cast(&mTexName))) ; - } - + mTexName = createTextureName(); - LLImageGL::generateTextures(1, &mTexName); stop_glerror(); - if (!mTexName) + if (!getTexName()) { LL_ERRS() << "LLImageGL::createGLTexture failed to make an empty texture" << LL_ENDL; } @@ -1527,10 +1369,10 @@ BOOL LLImageGL::createGLTexture() return TRUE ; } -static LLFastTimer::DeclareTimer FTM_CREATE_GL_TEXTURE2("createGLTexture(raw)"); -BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category) +static LLTrace::BlockTimerStatHandle FTM_CREATE_GL_TEXTURE2("createGLTexture(raw)"); +BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, GLTextureName* usename, BOOL to_create, S32 category) { - LLFastTimer t(FTM_CREATE_GL_TEXTURE2); + LL_RECORD_BLOCK_TIME(FTM_CREATE_GL_TEXTURE2); if (gGLManager.mIsDisabled) { LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL; @@ -1547,6 +1389,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S discard_level = mCurrentDiscardLevel; } + discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); + // Actual image width/height = raw image width/height * 2^discard_level S32 raw_w = imageraw->getWidth() ; S32 raw_h = imageraw->getHeight() ; @@ -1604,10 +1448,10 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S return createGLTexture(discard_level, rawdata, FALSE, usename); } -static LLFastTimer::DeclareTimer FTM_CREATE_GL_TEXTURE3("createGLTexture3(data)"); -BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) +static LLTrace::BlockTimerStatHandle FTM_CREATE_GL_TEXTURE3("createGLTexture3(data)"); +BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, GLTextureName* usename) { - LLFastTimer t(FTM_CREATE_GL_TEXTURE3); + LL_RECORD_BLOCK_TIME(FTM_CREATE_GL_TEXTURE3); llassert(data_in); stop_glerror(); @@ -1618,23 +1462,23 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - if (mTexName != 0 && discard_level == mCurrentDiscardLevel) + if (getTexName() != 0 && discard_level == mCurrentDiscardLevel) { // This will only be true if the size has not changed setImage(data_in, data_hasmips); + //checkTexSize(); return TRUE; } - U32 old_name = mTexName; // S32 old_discard = mCurrentDiscardLevel; - if (usename != 0) + if (usename && *usename) { - mTexName = usename; + mTexName = *usename; } else { - LLImageGL::generateTextures(1, &mTexName); + mTexName = createTextureName(); stop_glerror(); { llverify(gGL.getTexUnit(0)->bind(this)); @@ -1645,7 +1489,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ stop_glerror(); } } - if (!mTexName) + if (!getTexName()) { LL_ERRS() << "LLImageGL::createGLTexture failed to make texture" << LL_ENDL; } @@ -1665,37 +1509,25 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ mCurrentDiscardLevel = discard_level; setImage(data_in, data_hasmips); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel - discard_level); // Set texture options to our defaults. gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); + //gGL.getTexUnit(0)->unbind(mBindTarget); + //llverify(gGL.getTexUnit(0)->bindManual(mBindTarget, getTexName())); + //checkTexSize(); + // things will break if we don't unbind after creation gGL.getTexUnit(0)->unbind(mBindTarget); stop_glerror(); - if (old_name != 0) - { - sGlobalTextureMemoryInBytes -= mTextureMemory; - - if(gAuditTexture) - { - decTextureCounter(mTextureMemory, mComponents, mCategory) ; - } - - LLImageGL::deleteTextures(1, &old_name); - - stop_glerror(); - } + mTextureMemory = (S32Bytes)getMipBytes(discard_level); - mTextureMemory = getMipBytes(discard_level); - sGlobalTextureMemoryInBytes += mTextureMemory; + mTexName->addAllocatedMemory(mTextureMemory, mComponents, mCategory); - if(gAuditTexture) - { - incTextureCounter(mTextureMemory, mComponents, mCategory) ; - } // mark this as bound at this point, so we don't throw it out immediately mLastBindTime = sLastFrameTime; return TRUE; @@ -1714,7 +1546,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre return FALSE; } - if (mTexName == 0 || discard_level < mCurrentDiscardLevel || discard_level > mMaxDiscardLevel ) + if (getTexName() == 0 || discard_level < mCurrentDiscardLevel || discard_level > mMaxDiscardLevel ) { return FALSE; } @@ -1723,7 +1555,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre //explicitly unbind texture gGL.getTexUnit(0)->unbind(mBindTarget); - llverify(gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName)); + llverify(gGL.getTexUnit(0)->bindManual(mBindTarget, getTexName())); //debug code, leave it there commented. checkTexSize() ; @@ -1756,12 +1588,6 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre LL_ERRS() << llformat("LLImageGL::readBackRaw: bogus params: %d x %d x %d",width,height,ncomponents) << LL_ENDL; } - LLGLint is_compressed = 0; - if (compressed_ok) - { - glGetTexLevelParameteriv(mTarget, is_compressed, GL_TEXTURE_COMPRESSED, (GLint*)&is_compressed); - } - //----------------------------------------------------------------------------------------------- GLenum error ; while((error = glGetError()) != GL_NO_ERROR) @@ -1770,8 +1596,13 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre } //----------------------------------------------------------------------------------------------- - if (is_compressed) + if (mIsCompressed) { + if (!compressed_ok) + { + return false; + } + LLGLint glbytes; glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint*)&glbytes); if(!imageraw->allocateDataSize(width, height, ncomponents, glbytes)) @@ -1827,21 +1658,10 @@ void LLImageGL::deleteDeadTextures() void LLImageGL::destroyGLTexture() { - if (mTexName != 0) + if (getTexName()) { - if(mTextureMemory) - { - if(gAuditTexture) - { - decTextureCounter(mTextureMemory, mComponents, mCategory) ; - } - sGlobalTextureMemoryInBytes -= mTextureMemory; - mTextureMemory = 0; - } - - LLImageGL::deleteTextures(1, &mTexName); - mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. - mTexName = 0; + mTexName.reset(); + mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. mGLTextureCreated = FALSE ; } } @@ -1849,7 +1669,7 @@ void LLImageGL::destroyGLTexture() //force to invalidate the gl texture, most likely a sculpty texture void LLImageGL::forceToInvalidateGLTexture() { - if (mTexName != 0) + if (getTexName() != 0) { destroyGLTexture(); } @@ -1869,7 +1689,8 @@ void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode) mAddressMode = mode; } - if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) + GLuint tex = getTexName(); + if (tex && gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == tex) { gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureAddressMode(mode); mTexOptionsDirty = false; @@ -1884,7 +1705,8 @@ void LLImageGL::setFilteringOption(LLTexUnit::eTextureFilterOptions option) mFilterOption = option; } - if (mTexName != 0 && gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) + GLuint tex = getTexName(); + if (tex && gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == tex) { gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureFilteringOption(option); mTexOptionsDirty = false; @@ -1896,9 +1718,10 @@ BOOL LLImageGL::getIsResident(BOOL test_now) { if (test_now) { - if (mTexName != 0) + GLuint tex = getTexName(); + if (tex) { - glAreTexturesResident(1, (GLuint*)&mTexName, &mIsResident); + glAreTexturesResident(1, (GLuint*)&tex, &mIsResident); } else { @@ -2083,6 +1906,9 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) U32 sample[16]; memset(sample, 0, sizeof(U32)*16); + U32 min = 0, max = 0; + U32 mids = 0; + // generate histogram of quantized alpha. // also add-in the histogram of a 2x2 box-sampled version. The idea is // this will mid-skew the data (and thus increase the chances of not @@ -2114,6 +1940,10 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) ++sample[s3/16]; ++sample[s4/16]; + min = std::min(std::min(std::min(std::min(min, s1), s2), s3), s4); + max = std::max(std::max(std::max(std::max(max, s1), s2), s3), s4); + mids += (s1 > 2 && s1 < 253) + (s2 > 2 && s2 < 253) + (s3 > 2 && s3 < 253) + (s4 > 2 && s4 < 253); + const U32 asum = (s1+s2+s3+s4); alphatotal += asum; sample[asum/(16*4)] += 4; @@ -2142,9 +1972,18 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) ++sample[s1/16]; current += mAlphaStride; + min = std::min(min, s1); + max = std::max(max, s1); + mids += (s1 > 2 && s1 < 253); + if(i%2==0) { - S32 avg = (s1+current[mAlphaStride])/2; + const U32 s2 = *current; + min = std::min(min, s2); + max = std::max(max, s2); + mids += (s2 > 2 && s2 < 253); + + S32 avg = (s1+s2)/2; if(avg >=128) avg-=255; sum+=F64(avg*avg*2)/F64(length); @@ -2186,7 +2025,8 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) mIsMask = TRUE; } - mMaskRMSE = sqrt(sum)/255.0; + mMaskMidPercentile = (F32)mids / (F32)(w * h); + mMaskRMSE = ((max-min)%255)==0 ? sqrt(sum)/255.0 : FLT_MAX; /*std::list > &data = sTextureMaskMap[getTexName()]; data.clear(); @@ -2203,6 +2043,35 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) } +//---------------------------------------------------------------------------- +U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight) +{ + U32 pick_width = pWidth/2 + 1; + U32 pick_height = pHeight/2 + 1; + + U32 size = pick_width * pick_height; + size = (size + 7) / 8; // pixelcount-to-bits + mPickMask = new U8[size]; + mPickMaskWidth = pick_width - 1; + mPickMaskHeight = pick_height - 1; + + memset(mPickMask, 0, sizeof(U8) * size); + + return size; +} + +//---------------------------------------------------------------------------- +void LLImageGL::freePickMask() +{ + // pickmask validity depends on old image size, delete it + if (mPickMask != NULL) + { + delete [] mPickMask; + } + mPickMask = NULL; + mPickMaskWidth = mPickMaskHeight = 0; +} + //---------------------------------------------------------------------------- void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) { @@ -2211,9 +2080,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) return ; } - delete [] mPickMask; - mPickMask = NULL; - mPickMaskWidth = mPickMaskHeight = 0; + freePickMask(); if (mFormatType != GL_UNSIGNED_BYTE || mFormatPrimary != GL_RGBA) @@ -2222,16 +2089,11 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) return; } - U32 pick_width = width/2 + 1; - U32 pick_height = height/2 + 1; - - U32 size = pick_width * pick_height; - size = (size + 7) / 8; // pixelcount-to-bits - mPickMask = new U8[size]; - mPickMaskWidth = pick_width - 1; - mPickMaskHeight = pick_height - 1; - - memset(mPickMask, 0, sizeof(U8) * size); +#ifdef SHOW_ASSERT + const U32 pickSize = createPickMask(width, height); +#else // SHOW_ASSERT + createPickMask(width, height); +#endif // SHOW_ASSERT U32 pick_bit = 0; @@ -2245,7 +2107,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) { U32 pick_idx = pick_bit/8; U32 pick_offset = pick_bit%8; - llassert(pick_idx < size); + llassert(pick_idx < pickSize); mPickMask[pick_idx] |= 1 << pick_offset; } @@ -2356,19 +2218,19 @@ S32 LLImageGL::getTextureCounterIndex(U32 val) } //static -void LLImageGL::incTextureCounter(U32 val, S32 ncomponents, S32 category) +void LLImageGL::incTextureCounter(S32Bytes val, S32 ncomponents, S32 category) { - sTextureLoadedCounter[getTextureCounterIndex(val)]++ ; + sTextureLoadedCounter[getTextureCounterIndex(val.value())]++ ; if(category > -1) - sTextureMemByCategory[category] += (S32)val * ncomponents ; + sTextureMemByCategory[category] += (S32Bytes)val * ncomponents ; } //static -void LLImageGL::decTextureCounter(U32 val, S32 ncomponents, S32 category) +void LLImageGL::decTextureCounter(S32Bytes val, S32 ncomponents, S32 category) { - sTextureLoadedCounter[getTextureCounterIndex(val)]-- ; + sTextureLoadedCounter[getTextureCounterIndex(val.value())]-- ; if(category > -1) - sTextureMemByCategory[category] -= (S32)val * ncomponents ; + sTextureMemByCategory[category] -= (S32Bytes)val * ncomponents ; } void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size) diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index ecb5222deb..c35a8a24ae 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -34,6 +34,7 @@ #include "llpointer.h" #include "llrefcount.h" #include "v2math.h" +#include "llunits.h" #include "llrender.h" @@ -44,18 +45,72 @@ class LLImageGL : public LLRefCount { friend class LLTexUnit; + friend class GLTextureName; public: + struct AllocationInfo; +private: // These 2 functions replace glGenTextures() and glDeleteTextures() static void generateTextures(S32 numTextures, U32 *textures); - static void deleteTextures(S32 numTextures, U32 *textures); + static void deleteTextures(S32 numTextures, U32 *textures, const std::vector& allocationData); + static void texMemoryAllocated(const AllocationInfo& entry); + static void texMemoryDeallocated(const AllocationInfo& entry); +public: static void deleteDeadTextures(); + struct AllocationInfo + { + AllocationInfo(S32Bytes& _size, U8 _components, U32 _category) : + size(_size), components(_components), category(_category) + {} + S32Bytes size; + U8 components; + U32 category; + }; + // Singu Note: + // The topology of GLImageGL is wrong. As a result, tex names are shared across multiple LLImageGL + // instances. To avoid redundant glDelete calls gl tex names have been wrapped in GLTextureName, + // which is refcounted via std::shared_ptr. + class GLTextureNameInstance { + public: + GLTextureNameInstance(U32 size = 1) : mTexCount(size) + { + mTexNames.resize(mTexCount, 0); + LLImageGL::generateTextures(1, mTexNames.data()); + } + ~GLTextureNameInstance() + { + LLImageGL::deleteTextures(1, mTexNames.data(), mAllocationData); + } + GLuint getTexName(U32 idx = 0) const + { + return mTexNames[idx]; + } + void addAllocatedMemory(S32Bytes size, U8 components, U32 category) + { + mAllocationData.emplace_back(size, components, category); + LLImageGL::texMemoryAllocated(mAllocationData.back()); + } + const std::vector& getAllocatedMemoryInfo() const + { + return mAllocationData; + } + private: + const size_t mTexCount; + std::vector mTexNames; + std::vector mAllocationData; + }; + typedef std::shared_ptr GLTextureName; + + static GLTextureName createTextureName(U32 size = 0) { + return std::make_shared(); + } + // Size calculation static S32 dataFormatBits(S32 dataformat); static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height); static S32 dataFormatComponents(S32 dataformat); - BOOL updateBindStats(S32 tex_mem) const ; + BOOL updateBindStats(S32Bytes tex_mem) const ; F32 getTimePassedSinceLastBound(); void forceUpdateBindStats(void) const; @@ -68,7 +123,7 @@ class LLImageGL : public LLRefCount static void dirtyTexOptions(); // Sometimes called externally for textures not using LLImageGL (should go away...) - static S32 updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) ; + static S32 updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category) ; static bool checkSize(S32 width, S32 height); @@ -80,9 +135,9 @@ class LLImageGL : public LLRefCount static BOOL create(LLPointer& dest, const LLImageRaw* imageraw, BOOL usemipmaps = TRUE); public: - LLImageGL(BOOL usemipmaps = TRUE); - LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE); - LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps = TRUE); + LLImageGL(BOOL usemipmaps = TRUE, bool allow_compression = false); + LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE, bool allow_compression = false); + LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps = TRUE, bool allow_compression = false); protected: virtual ~LLImageGL(); @@ -97,12 +152,12 @@ class LLImageGL : public LLRefCount void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;} void setAllowCompression(bool allow) { mAllowCompression = allow; } - static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true); + static bool setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels = nullptr, bool allow_compression = false); BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, GLTextureName* usename = nullptr, BOOL to_create = TRUE, S32 category = sMaxCategories-1); - BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); + BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, GLTextureName* usename = nullptr); void setImage(const LLImageRaw* imageraw); void setImage(const U8* data_in, BOOL data_hasmips = FALSE); BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); @@ -132,10 +187,10 @@ class LLImageGL : public LLRefCount LLGLenum getPrimaryFormat() const { return mFormatPrimary; } LLGLenum getFormatType() const { return mFormatType; } - BOOL getHasGLTexture() const { return mTexName != 0; } - LLGLuint getTexName() const { return mTexName; } + BOOL getHasGLTexture() const { return mTexName != nullptr; } + LLGLuint getTexName() const { return mTexName ? mTexName->getTexName() : 0; } - BOOL getIsAlphaMask(const F32 max_rmse) const { return mNeedsAlphaAndPickMask && (max_rmse < 0.f ? (bool)mIsMask : (mMaskRMSE <= max_rmse)); } + BOOL getIsAlphaMask(const F32 max_rmse, const F32 max_mid) const { return mNeedsAlphaAndPickMask && (max_rmse < 0.f ? (bool)mIsMask : (mMaskRMSE <= max_rmse && mMaskMidPercentile <= max_mid)); } BOOL getIsResident(BOOL test_now = FALSE); // not const @@ -166,16 +221,19 @@ class LLImageGL : public LLRefCount LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; } LLGLenum getTexTarget()const { return mTarget ;} - void init(BOOL usemipmaps); + void init(BOOL usemipmaps, bool allow_compression); virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors void setNeedsAlphaAndPickMask(BOOL need_mask); public: // Various GL/Rendering options - S32 mTextureMemory; + S32Bytes mTextureMemory; mutable F32 mLastBindTime; // last time this was bound, by discard level private: + U32 createPickMask(S32 pWidth, S32 pHeight); + void freePickMask(); + LLPointer mSaveData; // used for destroyGL/restoreGL S32 mSaveDiscardLevel; U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel @@ -187,17 +245,19 @@ class LLImageGL : public LLRefCount BOOL mIsMask; F32 mMaskRMSE; + F32 mMaskMidPercentile; BOOL mNeedsAlphaAndPickMask; S8 mAlphaStride ; S8 mAlphaOffset ; bool mGLTextureCreated ; - LLGLuint mTexName; + GLTextureName mTexName; U16 mWidth; U16 mHeight; S8 mCurrentDiscardLevel; bool mAllowCompression; + bool mIsCompressed = false; protected: LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) @@ -228,9 +288,9 @@ class LLImageGL : public LLRefCount static F32 sLastFrameTime; // Global memory statistics - static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem - static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame - static S32 sCurBoundTextureMemory; // Tracks bound texmem for current frame + static S64Bytes sGlobalTextureMemory; // Tracks main memory texmem + static S64Bytes sBoundTextureMemory; // Tracks bound texmem for last completed frame + static S64Bytes sCurBoundTextureMemory; // Tracks bound texmem for current frame static U32 sBindCount; // Tracks number of texture binds for current frame static U32 sUniqueCount; // Tracks number of unique texture binds for current frame static BOOL sGlobalUseAnisotropic; @@ -274,8 +334,8 @@ class LLImageGL : public LLRefCount static void setHighlightTexture(S32 category) ; static S32 getTextureCounterIndex(U32 val) ; - static void incTextureCounter(U32 val, S32 ncomponents, S32 category) ; - static void decTextureCounter(U32 val, S32 ncomponents, S32 category) ; + static void incTextureCounter(S32Bytes val, S32 ncomponents, S32 category) ; + static void decTextureCounter(S32Bytes val, S32 ncomponents, S32 category) ; static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ; static void resetCurTexSizebar(); //---------------------------------------- @@ -283,9 +343,9 @@ class LLImageGL : public LLRefCount //for debug use: show texture category distribution //---------------------------------------- - static std::vector sTextureMemByCategory; - static std::vector sTextureMemByCategoryBound ; - static std::vector sTextureCurMemByCategoryBound ; + static std::vector sTextureMemByCategory; + static std::vector sTextureMemByCategoryBound ; + static std::vector sTextureCurMemByCategoryBound ; //---------------------------------------- // **************************************************************************************************** //End of definitions for texture auditing use only diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp index 9991870bc4..0096525f08 100644 --- a/indra/llrender/llpostprocess.cpp +++ b/indra/llrender/llpostprocess.cpp @@ -35,6 +35,7 @@ #include "llpostprocess.h" #include "lldir.h" +#include "llcontrol.h" #include "llfasttimer.h" #include "llgl.h" #include "llglslshader.h" @@ -67,9 +68,9 @@ static LLStaticHashedString sVignettRadius("vignette_radius"); static LLStaticHashedString sVignetteDarkness("vignette_darkness"); static LLStaticHashedString sVignetteDesaturation("vignette_desaturation"); static LLStaticHashedString sVignetteChromaticAberration("vignette_chromatic_aberration"); -static LLStaticHashedString sScreenRes("screen_res"); static LLStaticHashedString sHorizontalPass("horizontalPass"); +static LLStaticHashedString sKern("kern"); static LLStaticHashedString sPrevProj("prev_proj"); static LLStaticHashedString sInvProj("inv_proj"); @@ -262,7 +263,6 @@ class LLVignetteShader : public LLPostProcessSinglePassColorShader getShader().uniform1f(sVignetteDarkness, mDarkness); getShader().uniform1f(sVignetteDesaturation, mDesaturation); getShader().uniform1f(sVignetteChromaticAberration, mChromaticAberration); - getShader().uniform2fv(sScreenRes, 1, screen_rect.mV); return QUAD_NORMAL; } }; @@ -284,13 +284,18 @@ class LLGaussBlurShader : public LLPostProcessShader /*virtual*/ S32 getDepthChannel() const { return -1; } /*virtual*/ QuadType preDraw() { + LLVector2 screen_rect = LLPostProcess::getInstance()->getDimensions(); + mPassLoc = getShader().getUniformLocation(sHorizontalPass); + LLVector4 vec[] = { LLVector4(1.3846153846f, 3.2307692308f, 0.f, 0.f) / screen_rect.mV[VX], LLVector4( 0.f,0.f, 1.3846153846f, 3.2307692308f ) / screen_rect.mV[VY] }; + getShader().uniform4fv(sKern, LL_ARRAY_SIZE(vec), (GLfloat*)vec); return QUAD_NORMAL; } /*virtual*/ bool draw(U32 pass) { if((S32)pass > mNumPasses*2) return false; + gGL.syncShaders(); glUniform1iARB(mPassLoc, (pass-1) % 2); return true; } @@ -322,7 +327,6 @@ class LLMotionShader : public LLPostProcessShader getShader().uniformMatrix4fv(sPrevProj, 1, GL_FALSE, prev_proj.getF32ptr()); getShader().uniformMatrix4fv(sInvProj, 1, GL_FALSE, inv_proj.getF32ptr()); - getShader().uniform2fv(sScreenRes, 1, screen_rect.mV); getShader().uniform1i(sBlurStrength, mStrength); return QUAD_NORMAL; @@ -352,41 +356,44 @@ LLPostProcess::LLPostProcess(void) : mShaders.push_back(new LLPosterizeShader()); /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.*/ - std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); - LL_DEBUGS("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL; - - llifstream effectsXML(pathName); - - if (effectsXML) + auto load_effects = [&](const std::string& pathName) { - LLPointer parser = new LLSDXMLParser(); + LL_DEBUGS("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL; + llifstream effectsXML(pathName); - parser->parse(effectsXML, mAllEffectInfo, LLSDSerialize::SIZE_UNLIMITED); - } + if (effectsXML) + { + LLPointer parser = new LLSDXMLParser(); + parser->parse(effectsXML, mAllEffectInfo, LLSDSerialize::SIZE_UNLIMITED); + } + }; + load_effects(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); + load_effects(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "windlight", XML_FILENAME)); - if (!mAllEffectInfo.has("default")) - mAllEffectInfo["default"] = LLSD::emptyMap(); + auto setting = gSavedSettings.getControl("SinguPostProcessDefault"); + setting->getSignal()->connect(std::bind(&LLPostProcess::setSelectedEffect, this, std::bind(&LLSD::asStringRef, std::placeholders::_2))); + const auto& str = setting->get().asStringRef(); + if (!mAllEffectInfo.has(str)) + mAllEffectInfo[str] = LLSD::emptyMap(); - LLSD& defaults = mAllEffectInfo["default"]; + LLSD& defaults = mAllEffectInfo[str]; - for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) + // Add defaults for all missing effects + for(auto& shader : mShaders) { - LLSD shader_defaults = (*it)->getDefaults(); + const LLSD shader_defaults = shader->getDefaults(); for (LLSD::map_const_iterator it2 = defaults.beginMap();it2 != defaults.endMap();++it2) { if(!defaults.has(it2->first)) defaults[it2->first]=it2->second; } } - for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) - { - (*it)->loadSettings(defaults); - } - setSelectedEffect("default"); + setSelectedEffect(str); } LLPostProcess::~LLPostProcess(void) { + gSavedSettings.setString("SinguPostProcessDefault", mSelectedEffectName); destroyGL() ; } @@ -411,11 +418,22 @@ void LLPostProcess::initialize(unsigned int width, unsigned int height) mVBO->getVertexStrider(v); mVBO->getTexCoord0Strider(uv1); mVBO->getTexCoord1Strider(uv2); - - v[0] = LLVector3( uv2[0] = uv1[0] = LLVector2(0, 0) ); - v[1] = LLVector3( uv2[1] = uv1[1] = LLVector2(0, mScreenHeight) ); - v[2] = LLVector3( uv2[2] = uv1[2] = LLVector2(mScreenWidth, 0) ); - v[3] = LLVector3( uv2[3] = uv1[3] = LLVector2(mScreenWidth, mScreenHeight) ); + + uv2[0] = uv1[0] = LLVector2(0, 0); + uv2[1] = uv1[1] = LLVector2(0, 1); + uv2[2] = uv1[2] = LLVector2(1, 0); + uv2[3] = uv1[3] = LLVector2(1, 1); + + LLVector3 vec1[4] = { + LLVector3(0, 0, 0), + LLVector3(0, mScreenHeight, 0), + LLVector3(mScreenWidth, 0, 0), + LLVector3(mScreenWidth, mScreenHeight, 0) }; + + v[0] = vec1[0]; + v[1] = vec1[1]; + v[2] = vec1[2]; + v[3] = vec1[3]; mVBO->flush(); } @@ -424,26 +442,22 @@ void LLPostProcess::initialize(unsigned int width, unsigned int height) void LLPostProcess::createScreenTextures() { - const LLTexUnit::eTextureType type = LLTexUnit::TT_RECT_TEXTURE; + const LLTexUnit::eTextureType type = LLTexUnit::TT_TEXTURE; mRenderTarget[0].allocate(mScreenWidth,mScreenHeight,GL_RGBA,FALSE,FALSE,type,FALSE); if(mRenderTarget[0].getFBO())//Only need pingpong between two rendertargets if FBOs are supported. mRenderTarget[1].allocate(mScreenWidth,mScreenHeight,GL_RGBA,FALSE,FALSE,type,FALSE); stop_glerror(); - if(mDepthTexture) - { - LLImageGL::deleteTextures(1, &mDepthTexture); - mDepthTexture = 0; - } + mDepthTexture.reset(); for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) { if((*it)->getDepthChannel()>=0) { - LLImageGL::generateTextures(1, &mDepthTexture); - gGL.getTexUnit(0)->bindManual(type, mDepthTexture); - LLImageGL::setManualImage(LLTexUnit::getInternalType(type), 0, GL_DEPTH_COMPONENT24, mScreenWidth, mScreenHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + mDepthTexture = LLImageGL::createTextureName(); + gGL.getTexUnit(0)->bindManual(type, mDepthTexture->getTexName()); + LLImageGL::setManualImage(LLTexUnit::getInternalType(type), 0, GL_DEPTH_COMPONENT24, mScreenWidth, mScreenHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); stop_glerror(); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); @@ -463,18 +477,12 @@ void LLPostProcess::createNoiseTexture() } } - if(mNoiseTexture) - { - LLImageGL::deleteTextures(1, &mNoiseTexture); - mNoiseTexture = 0; - } - - LLImageGL::generateTextures(1, &mNoiseTexture); + mNoiseTexture = LLImageGL::createTextureName(); stop_glerror(); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseTexture); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseTexture->getTexName()); stop_glerror(); - LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE8, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0], false); + LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE8, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); stop_glerror(); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); @@ -486,25 +494,22 @@ void LLPostProcess::destroyGL() { mRenderTarget[0].release(); mRenderTarget[1].release(); - if(mDepthTexture) - LLImageGL::deleteTextures(1, &mDepthTexture); - mDepthTexture=0; - if(mNoiseTexture) - LLImageGL::deleteTextures(1, &mNoiseTexture); + mDepthTexture.reset(); + mNoiseTexture.reset(); mNoiseTexture=0 ; mVBO = NULL ; } /*static*/void LLPostProcess::cleanupClass() { - if(instanceExists()) - getInstance()->destroyGL() ; + if (instanceExists()) + deleteSingleton(); } void LLPostProcess::copyFrameBuffer() { mRenderTarget[!!mRenderTarget[0].getFBO()].bindTexture(0,0); - glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,0,0,0,0,0,mScreenWidth, mScreenHeight); + glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,mScreenWidth, mScreenHeight); stop_glerror(); if(mDepthTexture) @@ -513,8 +518,8 @@ void LLPostProcess::copyFrameBuffer() { if((*it)->isEnabled() && (*it)->getDepthChannel()>=0) { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mDepthTexture); - glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,0,0,0,0,0,mScreenWidth, mScreenHeight); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mDepthTexture->getTexName()); + glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,mScreenWidth, mScreenHeight); stop_glerror(); break; } @@ -525,7 +530,7 @@ void LLPostProcess::copyFrameBuffer() void LLPostProcess::bindNoise(U32 channel) { - gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE,mNoiseTexture); + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE,mNoiseTexture->getTexName()); } void LLPostProcess::renderEffects(unsigned int width, unsigned int height) @@ -556,7 +561,7 @@ void LLPostProcess::doEffects(void) //Disable depth. Set blendmode to replace. LLGLDepthTest depth(GL_FALSE,GL_FALSE); - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.setSceneBlendType(LLRender::BT_REPLACE); /// Change to an orthogonal view @@ -594,7 +599,7 @@ void LLPostProcess::applyShaders(void) S32 color_channel = (*it)->getColorChannel(); S32 depth_channel = (*it)->getDepthChannel(); if(depth_channel >= 0) - gGL.getTexUnit(depth_channel)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mDepthTexture); + gGL.getTexUnit(depth_channel)->bindManual(LLTexUnit::TT_TEXTURE, mDepthTexture->getTexName()); U32 pass = 1; (*it)->bindShader(); @@ -639,11 +644,11 @@ void LLPostProcess::drawOrthoQuad(QuadType type) mVBO->getTexCoord1Strider(uv2); float offs[2] = { - /*ll_round*/(((float) rand() / (float) RAND_MAX) * (float)NOISE_SIZE)/float(NOISE_SIZE), - /*ll_round*/(((float) rand() / (float) RAND_MAX) * (float)NOISE_SIZE)/float(NOISE_SIZE) }; + /*ll_round*/((float) rand() / (float) RAND_MAX), + /*ll_round*/((float) rand() / (float) RAND_MAX) }; float scale[2] = { - (float)mScreenWidth * mNoiseTextureScale, - (float)mScreenHeight * mNoiseTextureScale }; + ((float)mScreenWidth * mNoiseTextureScale), + ((float)mScreenHeight * mNoiseTextureScale) }; uv2[0] = LLVector2(offs[0],offs[1]); uv2[1] = LLVector2(offs[0],offs[1]+scale[1]); @@ -661,10 +666,11 @@ void LLPostProcess::setSelectedEffect(std::string const & effectName) { mSelectedEffectName = effectName; mSelectedEffectInfo = mAllEffectInfo[effectName]; - for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) + for(auto shader : mShaders) { - (*it)->loadSettings(mSelectedEffectInfo); + shader->loadSettings(mSelectedEffectInfo); } + mSelectedEffectChanged(mSelectedEffectName); } void LLPostProcess::setSelectedEffectValue(std::string const & setting, LLSD value) @@ -700,8 +706,9 @@ void LLPostProcess::resetSelectedEffect() void LLPostProcess::saveEffectAs(std::string const & effectName) { mAllEffectInfo[effectName] = mSelectedEffectInfo; + mSelectedEffectChanged(mSelectedEffectName); // Might've changed, either way update the lists - std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); + std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "windlight", XML_FILENAME)); //LL_INFOS() << "Saving PostProcess Effects settings to " << pathName << LL_ENDL; llofstream effectsXML(pathName); diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h index 57bd58ef01..b130cf2af1 100644 --- a/indra/llrender/llpostprocess.h +++ b/indra/llrender/llpostprocess.h @@ -34,6 +34,7 @@ #define LL_POSTPROCESS_H #include +#include #include "llsd.h" #include "llrendertarget.h" @@ -89,8 +90,8 @@ class LLPostProcess : public LLSingleton U32 mNextDrawTarget; //Need to pingpong between two rendertargets. Cannot sample target texture of currently bound FBO. // However this is ONLY the case if fbos are actually supported, else swapping isn't needed. LLRenderTarget mRenderTarget[2]; - U32 mDepthTexture; - U32 mNoiseTexture ; + LLImageGL::GLTextureName mDepthTexture; + LLImageGL::GLTextureName mNoiseTexture ; U32 mScreenWidth; U32 mScreenHeight; @@ -103,6 +104,9 @@ class LLPostProcess : public LLSingleton // The map of all availible effects LLSD mAllEffectInfo; + typedef boost::signals2::signal selected_effect_changed_signal; + selected_effect_changed_signal mSelectedEffectChanged; + public: LLPostProcess(void); ~LLPostProcess(void); @@ -144,6 +148,7 @@ class LLPostProcess : public LLSingleton // Setters void setSelectedEffect(std::string const & effectName); void setSelectedEffectValue(std::string const & setting, LLSD value); + auto setSelectedEffectChangeCallback(const selected_effect_changed_signal::slot_type& func) { return mSelectedEffectChanged.connect(func); } void resetSelectedEffect(); void saveEffectAs(std::string const & effectName); }; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index b8a7234156..a40a0f1acb 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -46,7 +46,7 @@ LLMatrix4a gGLLastModelView; LLMatrix4a gGLPreviousModelView; LLMatrix4a gGLLastProjection; LLMatrix4a gGLProjection; -S32 gGLViewport[4]; +LLRect gGLViewport; U32 LLRender::sUICalls = 0; U32 LLRender::sUIVerts = 0; @@ -54,24 +54,21 @@ U32 LLTexUnit::sWhiteTexture = 0; bool LLRender::sGLCoreProfile = false; static const U32 LL_NUM_TEXTURE_LAYERS = 32; -static const U32 LL_NUM_LIGHT_UNITS = 8; -static GLenum sGLTextureType[] = +static const GLenum sGLTextureType[] = { GL_TEXTURE_2D, - GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_CUBE_MAP_ARB - //,GL_TEXTURE_2D_MULTISAMPLE Don't use. }; -static GLint sGLAddressMode[] = +static const GLint sGLAddressMode[] = { GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP_TO_EDGE }; -static GLenum sGLCompareFunc[] = +static const GLenum sGLCompareFunc[] = { GL_NEVER, GL_ALWAYS, @@ -85,7 +82,7 @@ static GLenum sGLCompareFunc[] = const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0; -static GLenum sGLBlendFactor[] = +static const GLenum sGLBlendFactor[] = { GL_ONE, GL_ZERO, @@ -101,16 +98,30 @@ static GLenum sGLBlendFactor[] = GL_ZERO // 'BF_UNDEF' }; +static const GLenum sGLPolygonFaceType[] = +{ + GL_FRONT, + GL_BACK, + GL_FRONT_AND_BACK +}; + +static const GLenum sGLPolygonMode[] = +{ + GL_POINT, + GL_LINE, + GL_FILL +}; + LLTexUnit::LLTexUnit(S32 index) -: mCurrTexType(TT_NONE), mCurrBlendType(TB_MULT), -mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT), -mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR), -mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), -mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), -mHasMipMaps(false) + : mCurrTexType(TT_NONE), mCurrBlendType(TB_MULT), + mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT), + mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR), + mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), + mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), + mHasMipMaps(false), + mIndex(index) { llassert_always(index < (S32)LL_NUM_TEXTURE_LAYERS); - mIndex = index; } //static @@ -119,6 +130,8 @@ U32 LLTexUnit::getInternalType(eTextureType type) return sGLTextureType[type]; } +//void validate_bind_texture(U32 name); + void LLTexUnit::refreshState(void) { // We set dirty to true so that the tex unit knows to ignore caching @@ -142,6 +155,7 @@ void LLTexUnit::refreshState(void) glEnable(sGLTextureType[mCurrTexType]); } + //if (mCurrTexture) validate_bind_texture(mCurrTexture); glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture); } else @@ -169,11 +183,12 @@ void LLTexUnit::activate(void) { if (mIndex < 0) return; - if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty) + if ((S32)gGL.getCurrentTexUnitIndex() != mIndex || gGL.mDirty) { - gGL.flush(); + //gGL.flush(); + // Apply immediately. glActiveTextureARB(GL_TEXTURE0_ARB + mIndex); - gGL.mCurrTextureUnitIndex = mIndex; + gGL.mContext.texUnit = gGL.mNewContext.texUnit = mIndex; } } @@ -228,59 +243,72 @@ void LLTexUnit::disable(void) bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) { stop_glerror(); - if (mIndex < 0) return false; - - LLImageGL* gl_tex = NULL ; - if (texture == NULL || !(gl_tex = texture->getGLTexture())) - { - LL_WARNS() << "NULL LLTexUnit::bind texture" << LL_ENDL; - return false; - } - - if (!gl_tex->getTexName()) //if texture does not exist + if (mIndex >= 0) { - //if deleted, will re-generate it immediately - texture->forceImmediateUpdate() ; + //gGL.flush(); - gl_tex->forceUpdateBindStats() ; - return texture->bindDefaultImage(mIndex); - } + LLImageGL* gl_tex = NULL ; - //in audit, replace the selected texture by the default one. - if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0) - { - if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize) - { - gl_tex->updateBindStats(gl_tex->mTextureMemory); - return bind(LLImageGL::sHighlightTexturep.get()); - } - } - if ((mCurrTexture != gl_tex->getTexName()) || forceBind) - { - gGL.flush(); - activate(); - enable(gl_tex->getTarget()); - mCurrTexture = gl_tex->getTexName(); - glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); - if(gl_tex->updateBindStats(gl_tex->mTextureMemory)) + if (texture != NULL && (gl_tex = texture->getGLTexture())) { - texture->setActive() ; - texture->updateBindStatsForTester() ; + if (gl_tex->getTexName()) //if texture exists + { + //in audit, replace the selected texture by the default one. + if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0) + { + if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize) + { + gl_tex->updateBindStats(gl_tex->mTextureMemory); + return bind(LLImageGL::sHighlightTexturep.get()); + } + } + if ((mCurrTexture != gl_tex->getTexName()) || forceBind) + { + gGL.flush(); + activate(); + enable(gl_tex->getTarget()); + mCurrTexture = gl_tex->getTexName(); + //validate_bind_texture(mCurrTexture); + glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); + if(gl_tex->updateBindStats(gl_tex->mTextureMemory)) + { + texture->setActive() ; + texture->updateBindStatsForTester() ; + } + mHasMipMaps = gl_tex->mHasMipMaps; + if (gl_tex->mTexOptionsDirty) + { + gl_tex->mTexOptionsDirty = false; + setTextureAddressMode(gl_tex->mAddressMode); + setTextureFilteringOption(gl_tex->mFilterOption); + } + } + } + else + { + //if deleted, will re-generate it immediately + texture->forceImmediateUpdate() ; + + gl_tex->forceUpdateBindStats() ; + return texture->bindDefaultImage(mIndex); + } } - mHasMipMaps = gl_tex->mHasMipMaps; - if (gl_tex->mTexOptionsDirty) + else { - gl_tex->mTexOptionsDirty = false; - setTextureAddressMode(gl_tex->mAddressMode); - setTextureFilteringOption(gl_tex->mFilterOption); + LL_WARNS() << "NULL LLTexUnit::bind texture" << LL_ENDL; + return false; } } + else + { // mIndex < 0 + return false; + } + return true; } bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) { - stop_glerror(); if (mIndex < 0) return false; if(!texture) @@ -295,35 +323,27 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) { return bind(LLImageGL::sDefaultGLTexture) ; } - stop_glerror(); return false ; } if ((mCurrTexture != texture->getTexName()) || forceBind) { gGL.flush(); - stop_glerror(); activate(); - stop_glerror(); enable(texture->getTarget()); - stop_glerror(); mCurrTexture = texture->getTexName(); + //validate_bind_texture(mCurrTexture); glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); - stop_glerror(); texture->updateBindStats(texture->mTextureMemory); mHasMipMaps = texture->mHasMipMaps; if (texture->mTexOptionsDirty) { - stop_glerror(); texture->mTexOptionsDirty = false; setTextureAddressMode(texture->mAddressMode); setTextureFilteringOption(texture->mFilterOption); - stop_glerror(); } } - stop_glerror(); - return true; } @@ -331,8 +351,6 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap) { if (mIndex < 0) return false; - gGL.flush(); - if (cubeMap == NULL) { LL_WARNS() << "NULL LLTexUnit::bind cubemap" << LL_ENDL; @@ -348,9 +366,11 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap) { if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) { + gGL.flush(); activate(); enable(LLTexUnit::TT_CUBE_MAP); mCurrTexture = cubeMap->mImages[0]->getTexName(); + //validate_bind_texture(mCurrTexture); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture); mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps; cubeMap->mImages[0]->updateBindStats(cubeMap->mImages[0]->mTextureMemory); @@ -377,7 +397,7 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) { if (mIndex < 0) return false; - gGL.flush(); + //gGL.flush(); if (bindDepth) { @@ -411,6 +431,7 @@ bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips) activate(); enable(type); mCurrTexture = texture; + //validate_bind_texture(texture); glBindTexture(sGLTextureType[type], texture); mHasMipMaps = hasMips; } @@ -419,28 +440,31 @@ bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips) void LLTexUnit::unbind(eTextureType type) { - stop_glerror(); - if (mIndex < 0) return; //always flush and activate for consistency // some code paths assume unbind always flushes and sets the active texture - gGL.flush(); - activate(); + if (gGL.getCurrentTexUnitIndex() != mIndex || gGL.mDirty) + { + gGL.flush(); + activate(); + } // Disabled caching of binding state. - if (mCurrTexType == type) + if (mCurrTexType == type && mCurrTexture != 0) { + gGL.flush(); mCurrTexture = 0; - if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE) + if (/*LLGLSLShader::sNoFixedFunction && */type == LLTexUnit::TT_TEXTURE) { + //if (sWhiteTexture) + // validate_bind_texture(sWhiteTexture); glBindTexture(sGLTextureType[type], sWhiteTexture); } else { glBindTexture(sGLTextureType[type], 0); } - stop_glerror(); } } @@ -529,7 +553,7 @@ void LLTexUnit::setTextureBlendType(eTextureBlendType type) return; } - if (mIndex < 0) return; + if (mIndex < 0 || mIndex >= gGLManager.mNumTextureUnits) return; // Do nothing if it's already correctly set. if (mCurrBlendType == type && !gGL.mDirty) @@ -654,7 +678,7 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT return; } - if (mIndex < 0) return; + if (mIndex < 0 || mIndex >= gGLManager.mNumTextureUnits) return; activate(); if (mCurrBlendType != TB_COMBINE || gGL.mDirty) @@ -804,8 +828,8 @@ void LLTexUnit::setColorScale(S32 scale) { if (mCurrColorScale != scale || gGL.mDirty) { - mCurrColorScale = scale; gGL.flush(); + mCurrColorScale = scale; glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale ); } } @@ -814,8 +838,8 @@ void LLTexUnit::setAlphaScale(S32 scale) { if (mCurrAlphaScale != scale || gGL.mDirty) { - mCurrAlphaScale = scale; gGL.flush(); + mCurrAlphaScale = scale; glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale ); } } @@ -835,203 +859,91 @@ void LLTexUnit::debugTextureUnit(void) } } -LLLightState::LLLightState(S32 index) -: mIndex(index), - mEnabled(false), - mConstantAtten(1.f), - mLinearAtten(0.f), - mQuadraticAtten(0.f), - mSpotExponent(0.f), - mSpotCutoff(180.f) +LLLightState::LLLightState(S32 index) : + mState(index), + mIndex(index) { - if (mIndex == 0) - { - mDiffuse.set(1,1,1,1); - mSpecular.set(1,1,1,1); - } - - mAmbient.set(0,0,0,1); - mPosition.set(0,0,1,0); - mSpotDirection.set(0,0,-1); + mPosMatrix.setIdentity(); + mSpotMatrix.setIdentity(); } -void LLLightState::enable() -{ - if (!mEnabled) - { - if (!LLGLSLShader::sNoFixedFunction) - { - glEnable(GL_LIGHT0+mIndex); - } - mEnabled = true; +#define UPDATE_LIGHTSTATE(state, value) \ + if (mState.state != value) { \ + mState.state = value; \ + ++gGL.mLightHash; \ } -} -void LLLightState::disable() -{ - if (mEnabled) - { - if (!LLGLSLShader::sNoFixedFunction) - { - glDisable(GL_LIGHT0+mIndex); - } - mEnabled = false; +#define UPDATE_LIGHTSTATE_AND_TRANSFORM(state, value, matrix, transformhash) \ + if (mState.state != value || memcmp(matrix.getF32ptr(), gGL.getModelviewMatrix().getF32ptr(), sizeof(LLMatrix4a))) { \ + mState.state = value; \ + ++gGL.mLightHash; \ + ++gGL.transformhash[mIndex]; \ + matrix = gGL.getModelviewMatrix(); \ } -} void LLLightState::setDiffuse(const LLColor4& diffuse) { - if (mDiffuse != diffuse) - { - ++gGL.mLightHash; - mDiffuse = diffuse; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightfv(GL_LIGHT0+mIndex, GL_DIFFUSE, mDiffuse.mV); - } - } -} - -void LLLightState::setAmbient(const LLColor4& ambient) -{ - if (mAmbient != ambient) - { - ++gGL.mLightHash; - mAmbient = ambient; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightfv(GL_LIGHT0+mIndex, GL_AMBIENT, mAmbient.mV); - } - } + UPDATE_LIGHTSTATE(mDiffuse, diffuse); } void LLLightState::setSpecular(const LLColor4& specular) { - if (mSpecular != specular) - { - ++gGL.mLightHash; - mSpecular = specular; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightfv(GL_LIGHT0+mIndex, GL_SPECULAR, mSpecular.mV); - } - } + UPDATE_LIGHTSTATE(mSpecular, specular); } void LLLightState::setPosition(const LLVector4& position) { - //always set position because modelview matrix may have changed - ++gGL.mLightHash; - mPosition = position; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightfv(GL_LIGHT0+mIndex, GL_POSITION, mPosition.mV); - } - else - { //transform position by current modelview matrix - LLVector4a pos; - pos.loadua(position.mV); - - gGL.getModelviewMatrix().rotate4(pos,pos); - - mPosition.set(pos.getF32ptr()); - } - + UPDATE_LIGHTSTATE_AND_TRANSFORM(mPosition, position, mPosMatrix, mLightPositionTransformHash); } void LLLightState::setConstantAttenuation(const F32& atten) { - if (mConstantAtten != atten) - { - mConstantAtten = atten; - ++gGL.mLightHash; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightf(GL_LIGHT0+mIndex, GL_CONSTANT_ATTENUATION, atten); - } - } + UPDATE_LIGHTSTATE(mConstantAtten, atten); } void LLLightState::setLinearAttenuation(const F32& atten) { - if (mLinearAtten != atten) - { - ++gGL.mLightHash; - mLinearAtten = atten; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightf(GL_LIGHT0+mIndex, GL_LINEAR_ATTENUATION, atten); - } - } + UPDATE_LIGHTSTATE(mLinearAtten, atten); } void LLLightState::setQuadraticAttenuation(const F32& atten) { - if (mQuadraticAtten != atten) - { - ++gGL.mLightHash; - mQuadraticAtten = atten; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightf(GL_LIGHT0+mIndex, GL_QUADRATIC_ATTENUATION, atten); - } - } + UPDATE_LIGHTSTATE(mQuadraticAtten, atten); } void LLLightState::setSpotExponent(const F32& exponent) { - if (mSpotExponent != exponent) - { - ++gGL.mLightHash; - mSpotExponent = exponent; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightf(GL_LIGHT0+mIndex, GL_SPOT_EXPONENT, exponent); - } - } + UPDATE_LIGHTSTATE(mSpotExponent, exponent); } void LLLightState::setSpotCutoff(const F32& cutoff) { - if (mSpotCutoff != cutoff) - { - ++gGL.mLightHash; - mSpotCutoff = cutoff; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightf(GL_LIGHT0+mIndex, GL_SPOT_CUTOFF, cutoff); - } - } + UPDATE_LIGHTSTATE(mSpotCutoff, cutoff); } void LLLightState::setSpotDirection(const LLVector3& direction) { - //always set direction because modelview matrix may have changed - ++gGL.mLightHash; - mSpotDirection = direction; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightfv(GL_LIGHT0+mIndex, GL_SPOT_DIRECTION, direction.mV); - } - else - { //transform direction by current modelview matrix - LLVector4a dir; - dir.load3(direction.mV); - - gGL.getModelviewMatrix().rotate(dir,dir); + UPDATE_LIGHTSTATE_AND_TRANSFORM(mSpotDirection, direction, mSpotMatrix, mLightSpotTransformHash); +} - mSpotDirection.set(dir.getF32ptr()); +void LLLightState::setEnabled(const bool enabled) +{ + if (mEnabled != enabled) + { + mEnabled = enabled; + ++gGL.mLightHash; } } -LLRender::eBlendFactor blendfunc_debug[4]={LLRender::BF_UNDEF}; + LLRender::LLRender() : mDirty(false), mCount(0), - mQuadCycle(0), mMode(LLRender::TRIANGLES), - mCurrTextureUnitIndex(0), - mMaxAnisotropy(0.f) + mMatrixMode(LLRender::MM_MODELVIEW), + mMatIdx{ 0 }, + mMaxAnisotropy(0.f), + mPrimitiveReset(false) { mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS); for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++) @@ -1040,33 +952,12 @@ LLRender::LLRender() } mDummyTexUnit = new LLTexUnit(-1); - for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; ++i) + for (U32 i = 0; i < NUM_LIGHTS; ++i) { mLightState.push_back(new LLLightState(i)); } - - for (U32 i = 0; i < 4; i++) - { - mCurrColorMask[i] = true; - } - - mCurrAlphaFunc = CF_DEFAULT; - mCurrAlphaFuncVal = 0.01f; - mCurrBlendColorSFactor = BF_UNDEF; - mCurrBlendAlphaSFactor = BF_UNDEF; - mCurrBlendColorDFactor = BF_UNDEF; - mCurrBlendAlphaDFactor = BF_UNDEF; - - mMatrixMode = LLRender::MM_MODELVIEW; - for (U32 i = 0; i < NUM_MATRIX_MODES; ++i) - { - mMatIdx[i] = 0; - mMatHash[i] = 0; - mCurMatHash[i] = 0xFFFFFFFF; - } - - mLightHash = 0; + resetSyncHashes(); //Init base matrix for each mode for(S32 i = 0; i < NUM_MATRIX_MODES; ++i) @@ -1096,6 +987,7 @@ void LLRender::init() glBindVertexArray(ret); #endif } + stop_glerror(); restoreVertexBuffers(); } @@ -1117,25 +1009,48 @@ void LLRender::shutdown() mBuffer = NULL ; } +void LLRender::destroyGL() +{ + // Reset gl state cache + mCurShader = 0; + mContext = Context(); + resetSyncHashes(); + LLTexUnit::sWhiteTexture = 0; // Also done in LLImageGL::destroyGL. + for (auto unit : mTexUnits) + { + if (unit->getCurrTexture() > 0) + { + unit->unbind(unit->getCurrType()); + } + } + + resetVertexBuffers(); +} + void LLRender::refreshState(void) { mDirty = true; - U32 active_unit = mCurrTextureUnitIndex; + U32 active_unit = getCurrentTexUnitIndex(); for (U32 i = 0; i < mTexUnits.size(); i++) { mTexUnits[i]->refreshState(); + stop_glerror(); } mTexUnits[active_unit]->activate(); + stop_glerror(); - setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]); + /*setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]); + stop_glerror(); setAlphaRejectSettings(mCurrAlphaFunc, mCurrAlphaFuncVal); + stop_glerror(); //Singu note: Also reset glBlendFunc blendFunc(mCurrBlendColorSFactor,mCurrBlendColorDFactor,mCurrBlendAlphaSFactor,mCurrBlendAlphaDFactor); + stop_glerror();*/ mDirty = false; } @@ -1147,48 +1062,233 @@ void LLRender::resetVertexBuffers() void LLRender::restoreVertexBuffers() { - llassert_always(mBuffer.isNull()); + if (!mBuffer.isNull()) + return; stop_glerror(); mBuffer = new LLVertexBuffer(immediate_mask, 0); + stop_glerror(); mBuffer->allocateBuffer(4096, 0, TRUE); + stop_glerror(); mBuffer->getVertexStrider(mVerticesp); + stop_glerror(); mBuffer->getTexCoord0Strider(mTexcoordsp); + stop_glerror(); mBuffer->getColorStrider(mColorsp); stop_glerror(); } -void LLRender::syncLightState() +void LLRender::syncShaders() { - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + if (mCurShader != mNextShader) + { + glUseProgramObjectARB(mNextShader); + mCurShader = mNextShader; + } +} - if (!shader) +void LLRender::syncContextState() +{ + if (mContext.color != mNewContext.color) + { + mContext.color = mNewContext.color; + glColor4fv(mContext.color.mV); + } + if (mContext.colorMask != mNewContext.colorMask) + { + mContext.colorMask = mNewContext.colorMask; + glColorMask( + mContext.colorMask & (1 << 0), + mContext.colorMask & (1 << 1), + mContext.colorMask & (1 << 2), + mContext.colorMask & (1 << 3)); + } + if (mContext.alphaFunc != mNewContext.alphaFunc || + mContext.alphaVal != mNewContext.alphaVal) + { + mContext.alphaFunc = mNewContext.alphaFunc; + mContext.alphaVal = mNewContext.alphaVal; + if (mContext.alphaFunc == CF_DEFAULT) + { + glAlphaFunc(GL_GREATER, 0.01f); + } + else + { + glAlphaFunc(sGLCompareFunc[mContext.alphaFunc], mContext.alphaVal); + } + } + if (LLGLState::isEnabled() && ( + mContext.blendColorSFactor != mNewContext.blendColorSFactor || + mContext.blendAlphaSFactor != mNewContext.blendAlphaSFactor || + mContext.blendColorDFactor != mNewContext.blendColorDFactor || + mContext.blendAlphaDFactor != mNewContext.blendAlphaDFactor)) + { + mContext.blendColorSFactor = mNewContext.blendColorSFactor; + mContext.blendAlphaSFactor = mNewContext.blendAlphaSFactor; + mContext.blendColorDFactor = mNewContext.blendColorDFactor; + mContext.blendAlphaDFactor = mNewContext.blendAlphaDFactor; + if (mContext.blendColorSFactor == mContext.blendAlphaSFactor && + mContext.blendColorDFactor == mContext.blendAlphaDFactor) + { + glBlendFunc(sGLBlendFactor[mContext.blendColorSFactor], sGLBlendFactor[mContext.blendColorDFactor]); + } + else + { + glBlendFuncSeparateEXT(sGLBlendFactor[mContext.blendColorSFactor], sGLBlendFactor[mContext.blendColorDFactor], + sGLBlendFactor[mContext.blendAlphaSFactor], sGLBlendFactor[mContext.blendAlphaDFactor]); + } + } + if (mContext.lineWidth != mNewContext.lineWidth) + { + mContext.lineWidth = mNewContext.lineWidth; + glLineWidth(mContext.lineWidth); + } + if (mContext.pointSize != mNewContext.pointSize) + { + mContext.pointSize = mNewContext.pointSize; + glPointSize(mContext.pointSize); + } + if (mContext.polygonMode[0] != mNewContext.polygonMode[0] || mContext.polygonMode[1] != mNewContext.polygonMode[1]) + { + if (mNewContext.polygonMode[0] == mNewContext.polygonMode[1]) + { + glPolygonMode(GL_FRONT_AND_BACK, sGLPolygonMode[mNewContext.polygonMode[0]]); + } + else + { + if (mContext.polygonMode[0] != mNewContext.polygonMode[0]) + { + glPolygonMode(GL_FRONT, sGLPolygonMode[mNewContext.polygonMode[0]]); + } + if (mContext.polygonMode[1] != mNewContext.polygonMode[1]) + { + glPolygonMode(GL_BACK, sGLPolygonMode[mNewContext.polygonMode[1]]); + } + } + + mContext.polygonMode[0] = mNewContext.polygonMode[0]; + mContext.polygonMode[1] = mNewContext.polygonMode[1]; + } + if (mContext.polygonOffset[0] != mNewContext.polygonOffset[0] || mContext.polygonOffset[1] != mNewContext.polygonOffset[1]) + { + mContext.polygonOffset[0] = mNewContext.polygonOffset[0]; + mContext.polygonOffset[1] = mNewContext.polygonOffset[1]; + glPolygonOffset(mContext.polygonOffset[0], mContext.polygonOffset[1]); + } + if (mContext.viewPort != mNewContext.viewPort) + { + mContext.viewPort = mNewContext.viewPort; + glViewport(mContext.viewPort.mLeft, mContext.viewPort.mBottom, mContext.viewPort.getWidth(), mContext.viewPort.getHeight()); + } + if (LLGLState::isEnabled() && mContext.scissor != mNewContext.scissor) + { + mContext.scissor = mNewContext.scissor; + glScissor(mContext.scissor.mLeft, mContext.scissor.mBottom, mContext.scissor.getWidth(), mContext.scissor.getHeight()); + } +} + +U32 sLightMask = 0xFFFFFFFF; +void LLRender::syncLightState() +{ + if (!LLGLSLShader::sNoFixedFunction) { + // Legacy + if (mCurLegacyLightHash != mLightHash) + { + mCurLegacyLightHash = mLightHash; + for (U32 i = 0; i < NUM_LIGHTS; i++) + { + const LLLightState* light = mLightState[i]; + const U32 idx = GL_LIGHT0 + i; + const LLLightStateData& state = light->mState; + + if (light->mEnabled && (1 << i) & sLightMask) { + glEnable(idx); + if (mLightSpotTransformHash[i] != mCurLightSpotTransformHash[i] || + mLightPositionTransformHash[i] != mCurLightPositionTransformHash[i]) + { + + glPushAttrib(GL_TRANSFORM_BIT); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + if (mLightPositionTransformHash[i] != mCurLightPositionTransformHash[i]) + { + glLoadMatrixf(light->mPosMatrix.getF32ptr()); + glLightfv(idx, GL_POSITION, state.mPosition.mV); + } + if (mLightSpotTransformHash[i] != mCurLightSpotTransformHash[i]) + { + glLoadMatrixf(light->mSpotMatrix.getF32ptr()); + glLightfv(idx, GL_SPOT_DIRECTION, state.mSpotDirection.mV); + } + mCurLightPositionTransformHash[i] = mLightPositionTransformHash[i]; + mCurLightSpotTransformHash[i] = mLightSpotTransformHash[i]; + + glPopMatrix(); + glPopAttrib(); + } + glLightfv(idx, GL_DIFFUSE, state.mDiffuse.mV); + glLightfv(idx, GL_SPECULAR, state.mSpecular.mV); + glLightf(idx, GL_CONSTANT_ATTENUATION, state.mConstantAtten); + glLightf(idx, GL_LINEAR_ATTENUATION, state.mLinearAtten); + glLightf(idx, GL_QUADRATIC_ATTENUATION, state.mQuadraticAtten); + glLightf(idx, GL_SPOT_EXPONENT, state.mSpotExponent); + glLightf(idx, GL_SPOT_CUTOFF, state.mSpotCutoff); + } + else + { + glDisable(idx); + } + } + + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, mAmbientLightColor.mV); + } return; } + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + if (!shader || (!shader->mFeatures.hasLighting && !shader->mFeatures.calculatesLighting)) + { + return; + } if (shader->mLightHash != mLightHash) { shader->mLightHash = mLightHash; - LLVector4 position[8]; - LLVector3 direction[8]; LLVector3 attenuation[8]; LLVector3 diffuse[8]; - for (U32 i = 0; i < 8; i++) + for (U32 i = 0; i < NUM_LIGHTS; i++) { - LLLightState* light = mLightState[i]; + const LLLightState* light = mLightState[i]; + const LLLightStateData& state = light->mState; + + attenuation[i].set(state.mLinearAtten, state.mQuadraticAtten, state.mSpecular.mV[3]); + diffuse[i].set((light->mEnabled && (1 << i) & sLightMask) ? state.mDiffuse.mV : LLVector3::zero.mV); - position[i] = light->mPosition; - direction[i] = light->mSpotDirection; - attenuation[i].set(light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[3]); - diffuse[i].set(light->mDiffuse.mV); + if (mLightPositionTransformHash[i] != mCurLightPositionTransformHash[i]) + { + LLVector4a pos; + pos.loadua(state.mPosition.mV); + light->mPosMatrix.rotate4(pos, pos); + mCurLightPosition[i].set(pos.getF32ptr()); + mCurLightPositionTransformHash[i] = mLightPositionTransformHash[i]; + } + // If state.mSpecular.mV[3] == 0.f then this light is a spotlight, thus update the direction... + // Otherwise don't bother and leave the hash stale in case it turns into a spotlight later. + if (state.mSpecular.mV[3] == 0.f && mLightSpotTransformHash[i] != mCurLightSpotTransformHash[i]) + { + LLVector4a dir; + dir.load3(state.mSpotDirection.mV); + light->mSpotMatrix.rotate(dir, dir); + mCurSpotDirection[i].set(dir.getF32ptr()); + mCurLightSpotTransformHash[i] = mLightSpotTransformHash[i]; + } } - shader->uniform4fv(LLShaderMgr::LIGHT_POSITION, 8, position[0].mV); - shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, 8, direction[0].mV); - shader->uniform3fv(LLShaderMgr::LIGHT_ATTENUATION, 8, attenuation[0].mV); - shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, 8, diffuse[0].mV); + shader->uniform4fv(LLShaderMgr::LIGHT_POSITION, NUM_LIGHTS, mCurLightPosition[0].mV); + shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, NUM_LIGHTS, mCurSpotDirection[0].mV); + shader->uniform3fv(LLShaderMgr::LIGHT_ATTENUATION, NUM_LIGHTS, attenuation[0].mV); + shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, NUM_LIGHTS, diffuse[0].mV); shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV); //HACK -- duplicate sunlight color for compatibility with drivers that can't deal with multiple shader objects referencing the same uniform shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV); @@ -1199,7 +1299,9 @@ void LLRender::syncMatrices() { stop_glerror(); - U32 name[] = + syncShaders(); + + static const U32 name[] = { LLShaderMgr::MODELVIEW_MATRIX, LLShaderMgr::PROJECTION_MATRIX, @@ -1307,12 +1409,6 @@ void LLRender::syncMatrices() shader->mMatHash[i] = mMatHash[i]; } } - - - if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting) - { //also sync light state - syncLightState(); - } } else if (!LLGLSLShader::sNoFixedFunction) { @@ -1328,26 +1424,31 @@ void LLRender::syncMatrices() for (U32 i = 0; i < 2; ++i) { - if (mMatHash[i] != mCurMatHash[i]) + if (mMatHash[i] != mCurLegacyMatHash[i]) { glMatrixMode(mode[i]); glLoadMatrixf(mMatrix[i][mMatIdx[i]].getF32ptr()); - mCurMatHash[i] = mMatHash[i]; + mCurLegacyMatHash[i] = mMatHash[i]; } } for (U32 i = 2; i < NUM_MATRIX_MODES; ++i) { - if (mMatHash[i] != mCurMatHash[i]) + if (mMatHash[i] != mCurLegacyMatHash[i]) { gGL.getTexUnit(i-2)->activate(); glMatrixMode(mode[i]); glLoadMatrixf(mMatrix[i][mMatIdx[i]].getF32ptr()); - mCurMatHash[i] = mMatHash[i]; + mCurLegacyMatHash[i] = mMatHash[i]; } } } + //also sync light state + syncLightState(); + //sync context. + syncContextState(); + stop_glerror(); } @@ -1650,8 +1751,6 @@ bool LLRender::unprojectf(const LLVector3& windowCoordinate, const LLMatrix4a& m void LLRender::pushMatrix() { - flush(); - { if (mMatIdx[mMatrixMode] < LL_MATRIX_STACK_DEPTH-1) { @@ -1667,15 +1766,19 @@ void LLRender::pushMatrix() void LLRender::popMatrix() { - flush(); { if (mMatIdx[mMatrixMode] > 0) { + if ( memcmp(mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].getF32ptr(), mMatrix[mMatrixMode][mMatIdx[mMatrixMode] - 1].getF32ptr(), sizeof(LLMatrix4a)) ) + { + flush(); + } --mMatIdx[mMatrixMode]; mMatHash[mMatrixMode]++; } else { + flush(); LL_WARNS() << "Matrix stack underflow." << LL_ENDL; } } @@ -1684,6 +1787,7 @@ void LLRender::popMatrix() void LLRender::loadMatrix(const LLMatrix4a& mat) { flush(); + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = mat; mMatHash[mMatrixMode]++; } @@ -1759,11 +1863,23 @@ void LLRender::scaleUI(F32 x, F32 y, F32 z) mUIScale.back().mul(scale); } +void LLRender::rotateUI(LLQuaternion& rot) +{ + if (mUIRotation.empty()) + { + mUIRotation.push_back(rot); + } + else + { + mUIRotation.push_back(mUIRotation.back()*rot); + } +} + void LLRender::pushUIMatrix() { if (mUIOffset.empty()) { - mUIOffset.push_back(LLVector4a(0.f)); + mUIOffset.emplace_back(LLVector4a(0.f)); } else { @@ -1772,22 +1888,30 @@ void LLRender::pushUIMatrix() if (mUIScale.empty()) { - mUIScale.push_back(LLVector4a(1.f)); + mUIScale.emplace_back(LLVector4a(1.f)); } else { mUIScale.push_back(mUIScale.back()); } + if (!mUIRotation.empty()) + { + mUIRotation.push_back(mUIRotation.back()); + } } void LLRender::popUIMatrix() { - if (mUIOffset.empty()) + if (mUIOffset.empty() || mUIScale.empty()) { - LL_ERRS() << "UI offset stack blown." << LL_ENDL; + LL_ERRS() << "UI offset or scale stack blown." << LL_ENDL; } mUIOffset.pop_back(); mUIScale.pop_back(); + if (!mUIRotation.empty()) + { + mUIRotation.pop_back(); + } } LLVector3 LLRender::getUITranslation() @@ -1817,6 +1941,8 @@ void LLRender::loadUIIdentity() } mUIOffset.back().splat(0.f); mUIScale.back().splat(1.f); + if (!mUIRotation.empty()) + mUIRotation.push_back(LLQuaternion()); } void LLRender::setColorMask(bool writeColor, bool writeAlpha) @@ -1826,22 +1952,11 @@ void LLRender::setColorMask(bool writeColor, bool writeAlpha) void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha) { - flush(); - - if (mCurrColorMask[0] != writeColorR || - mCurrColorMask[1] != writeColorG || - mCurrColorMask[2] != writeColorB || - mCurrColorMask[3] != writeAlpha || mDirty) + const U8 mask = (U8)writeColorR | ((U8)writeColorG << 1) | ((U8)writeColorB << 2) | ((U8)writeAlpha << 3); + if (mNewContext.colorMask != mask || mDirty) { - mCurrColorMask[0] = writeColorR; - mCurrColorMask[1] = writeColorG; - mCurrColorMask[2] = writeColorB; - mCurrColorMask[3] = writeAlpha; - - glColorMask(writeColorR ? GL_TRUE : GL_FALSE, - writeColorG ? GL_TRUE : GL_FALSE, - writeColorB ? GL_TRUE : GL_FALSE, - writeAlpha ? GL_TRUE : GL_FALSE); + flush(); + mNewContext.colorMask = mask; } } @@ -1878,29 +1993,20 @@ void LLRender::setSceneBlendType(eBlendType type) void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) { - flush(); - if (LLGLSLShader::sNoFixedFunction) { //glAlphaFunc is deprecated in OpenGL 3.3 return; } - if (mCurrAlphaFunc != func || - mCurrAlphaFuncVal != value || mDirty) + if (mNewContext.alphaFunc != func || + mNewContext.alphaVal != value || mDirty) { - mCurrAlphaFunc = func; - mCurrAlphaFuncVal = value; - if (func == CF_DEFAULT) - { - glAlphaFunc(GL_GREATER, 0.01f); - } - else - { - glAlphaFunc(sGLCompareFunc[func], value); - } + flush(); + mNewContext.alphaFunc = func; + mNewContext.alphaVal = value; } - if (gDebugGL) + /*if (gDebugGL) { //make sure cached state is correct GLint cur_func = 0; glGetIntegerv(GL_ALPHA_TEST_FUNC, &cur_func); @@ -1922,32 +2028,53 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) { LL_ERRS() << "Alpha test value corrupted!" << LL_ENDL; } + }*/ +} + +void LLRender::setViewport(const LLRect& rect) +{ + if (mNewContext.viewPort != rect || mDirty) + { + flush(); + mNewContext.viewPort = rect; + } +} + +void LLRender::setScissor(const LLRect& rect) +{ + if (mNewContext.scissor != rect || mDirty) + { + if (LLGLState::isEnabled()) + { + flush(); + } + mNewContext.scissor = rect; } } void check_blend_funcs() { - llassert_always(blendfunc_debug[0] == LLRender::BF_SOURCE_ALPHA ); - llassert_always(blendfunc_debug[1] == LLRender::BF_SOURCE_ALPHA ); - llassert_always(blendfunc_debug[2] == LLRender::BF_ONE_MINUS_SOURCE_ALPHA ); - llassert_always(blendfunc_debug[3] == LLRender::BF_ONE_MINUS_SOURCE_ALPHA ); + llassert_always(gGL.mNewContext.blendColorSFactor == LLRender::BF_SOURCE_ALPHA ); + llassert_always(gGL.mNewContext.blendAlphaSFactor == LLRender::BF_SOURCE_ALPHA ); + llassert_always(gGL.mNewContext.blendColorDFactor == LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + llassert_always(gGL.mNewContext.blendAlphaDFactor == LLRender::BF_ONE_MINUS_SOURCE_ALPHA ); } void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor) { llassert(sfactor < BF_UNDEF); llassert(dfactor < BF_UNDEF); - if (mCurrBlendColorSFactor != sfactor || mCurrBlendColorDFactor != dfactor || - mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor || mDirty) - { - mCurrBlendColorSFactor = sfactor; - mCurrBlendAlphaSFactor = sfactor; - mCurrBlendColorDFactor = dfactor; - mCurrBlendAlphaDFactor = dfactor; - blendfunc_debug[0]=blendfunc_debug[1]=sfactor; - blendfunc_debug[2]=blendfunc_debug[3]=dfactor; - flush(); - glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]); + if (mNewContext.blendColorSFactor != sfactor || mNewContext.blendColorDFactor != dfactor || + mNewContext.blendAlphaSFactor != sfactor || mNewContext.blendAlphaDFactor != dfactor || mDirty) + { + if (LLGLState::isEnabled()) + { + flush(); + } + mNewContext.blendColorSFactor = sfactor; + mNewContext.blendAlphaSFactor = sfactor; + mNewContext.blendColorDFactor = dfactor; + mNewContext.blendAlphaDFactor = dfactor; } } @@ -1964,20 +2091,17 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, blendFunc(color_sfactor, color_dfactor); return; } - if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor || - mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor || mDirty) - { - mCurrBlendColorSFactor = color_sfactor; - mCurrBlendAlphaSFactor = alpha_sfactor; - mCurrBlendColorDFactor = color_dfactor; - mCurrBlendAlphaDFactor = alpha_dfactor; - blendfunc_debug[0]=color_sfactor; - blendfunc_debug[1]=alpha_sfactor; - blendfunc_debug[2]=color_dfactor; - blendfunc_debug[3]=alpha_dfactor; - flush(); - glBlendFuncSeparateEXT(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor], - sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]); + if (mNewContext.blendColorSFactor != color_sfactor || mNewContext.blendColorDFactor != color_dfactor || + mNewContext.blendAlphaSFactor != alpha_sfactor || mNewContext.blendAlphaDFactor != alpha_dfactor || mDirty) + { + if (LLGLState::isEnabled()) + { + flush(); + } + mNewContext.blendColorSFactor = color_sfactor; + mNewContext.blendAlphaSFactor = alpha_sfactor; + mNewContext.blendColorDFactor = color_dfactor; + mNewContext.blendAlphaDFactor = alpha_dfactor; } } @@ -2006,26 +2130,82 @@ LLLightState* LLRender::getLight(U32 index) void LLRender::setAmbientLightColor(const LLColor4& color) { - if (color != mAmbientLightColor) + if (color != mAmbientLightColor || mDirty) { ++mLightHash; mAmbientLightColor = color; - if (!LLGLSLShader::sNoFixedFunction) + } +} + +void LLRender::setLineWidth(F32 line_width) +{ + if (LLRender::sGLCoreProfile) + { + mNewContext.lineWidth = 1.f; + return; + } + if (mNewContext.lineWidth != line_width || mDirty) + { + if (mMode == LLRender::LINES || mMode == LLRender::LINE_STRIP) + { + flush(); + } + mNewContext.lineWidth = line_width; + } +} + +void LLRender::setPointSize(F32 point_size) +{ + if (mNewContext.pointSize != point_size || mDirty) + { + if (mMode == LLRender::POINTS) { - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, color.mV); + flush(); } + mNewContext.pointSize = point_size; + } +} + +void LLRender::setPolygonMode(ePolygonFaceType type, ePolygonMode mode) +{ + ePolygonMode newMode[] = { + (type == PF_FRONT_AND_BACK || type == PF_FRONT) ? mode : mNewContext.polygonMode[0], + (type == PF_FRONT_AND_BACK || type == PF_BACK) ? mode : mNewContext.polygonMode[1] + }; + + if (newMode[0] != mNewContext.polygonMode[0] || newMode[1] != mNewContext.polygonMode[1] || mDirty) + { + flush(); + mNewContext.polygonMode[0] = newMode[0]; + mNewContext.polygonMode[1] = newMode[1]; + } +} + +void LLRender::setPolygonOffset(F32 factor, F32 bias) +{ + if (factor != mNewContext.polygonOffset[0] || + bias != mNewContext.polygonOffset[1] || mDirty) + { + if (LLGLState::isEnabled() || + LLGLState::isEnabled() /*|| + Unused: LLGLState::isEnabled()*/ ) + { + flush(); + } + mNewContext.polygonOffset[0] = factor; + mNewContext.polygonOffset[1] = bias; } } bool LLRender::verifyTexUnitActive(U32 unitToVerify) { - if (mCurrTextureUnitIndex == unitToVerify) + if (getCurrentTexUnitIndex() == unitToVerify) { return true; } else { - LL_WARNS() << "TexUnit currently active: " << mCurrTextureUnitIndex << " (expecting " << unitToVerify << ")" << LL_ENDL; + LL_WARNS() << "TexUnit currently active: " << getCurrentTexUnitIndex() << " (expecting " << unitToVerify << ")" << LL_ENDL; return false; } } @@ -2038,19 +2218,25 @@ void LLRender::clearErrors() } } +void LLRender::resetSyncHashes() { + memset(&mLightHash, 0, sizeof(mLightHash)); + memset(&mCurLegacyLightHash, 0xFF, sizeof(mCurLegacyLightHash)); + memset(mMatHash, 0, sizeof(mMatHash)); + memset(mCurLegacyMatHash, 0xFF, sizeof(mCurLegacyMatHash)); + memset(mLightPositionTransformHash, 0, sizeof(mLightPositionTransformHash)); + memset(mCurLightPositionTransformHash, 0xFF, sizeof(mCurLightPositionTransformHash)); + memset(mLightSpotTransformHash, 0, sizeof(mLightSpotTransformHash)); + memset(mCurLightSpotTransformHash, 0xFF, sizeof(mLightSpotTransformHash)); +} + void LLRender::begin(const GLuint& mode) { if (mode != mMode) { - if (mode == LLRender::QUADS) - { - mQuadCycle = 1; - } - - if (mMode == LLRender::QUADS || - mMode == LLRender::LINES || + if (mMode == LLRender::LINES || mMode == LLRender::TRIANGLES || - mMode == LLRender::POINTS) + mMode == LLRender::POINTS || + mMode == LLRender::TRIANGLE_STRIP ) { flush(); } @@ -2071,15 +2257,20 @@ void LLRender::end() //IMM_ERRS << "GL begin and end called with no vertices specified." << LL_ENDL; } - if ((mMode != LLRender::QUADS && - mMode != LLRender::LINES && + if ((mMode != LLRender::LINES && mMode != LLRender::TRIANGLES && - mMode != LLRender::POINTS) || + mMode != LLRender::POINTS && + mMode != LLRender::TRIANGLE_STRIP) || mCount > 2048) { flush(); } + else if (mMode == LLRender::TRIANGLE_STRIP) + { + mPrimitiveReset = true; + } } + void LLRender::flush() { if (mCount > 0) @@ -2134,14 +2325,6 @@ void LLRender::flush() if (gDebugGL) { - if (mMode == LLRender::QUADS && !sGLCoreProfile) - { - if (mCount%4 != 0) - { - LL_ERRS() << "Incomplete quad rendered." << LL_ENDL; - } - } - if (mMode == LLRender::TRIANGLES) { if (mCount%3 != 0) @@ -2173,21 +2356,14 @@ void LLRender::flush() mBuffer->flush(); mBuffer->setBuffer(immediate_mask); - if (mMode == LLRender::QUADS && sGLCoreProfile) - { - mBuffer->drawArrays(LLRender::TRIANGLES, 0, count); - mQuadCycle = 1; - } - else - { - mBuffer->drawArrays(mMode, 0, count); - } + mBuffer->drawArrays(mMode, 0, count); mVerticesp[0] = mVerticesp[count]; mTexcoordsp[0] = mTexcoordsp[count]; mColorsp[0] = mColorsp[count]; mCount = 0; + mPrimitiveReset = false; } } @@ -2200,8 +2376,22 @@ void LLRender::vertex4a(const LLVector4a& vertex) { case LLRender::POINTS: flush(); break; case LLRender::TRIANGLES: if (mCount%3==0) flush(); break; - case LLRender::QUADS: if(mCount%4 == 0) flush(); break; case LLRender::LINES: if (mCount%2 == 0) flush(); break; + case LLRender::TRIANGLE_STRIP: + { + LLVector4a vert[] = { mVerticesp[mCount - 2], mVerticesp[mCount - 1], mVerticesp[mCount] }; + LLColor4U col[] = { mColorsp[mCount - 2], mColorsp[mCount - 1], mColorsp[mCount] }; + LLVector2 tc[] = { mTexcoordsp[mCount - 2], mTexcoordsp[mCount - 1], mTexcoordsp[mCount] }; + flush(); + for (int i = 0; i < LL_ARRAY_SIZE(vert); ++i) + { + mVerticesp[i] = vert[i]; + mColorsp[i] = col[i]; + mTexcoordsp[i] = tc[i]; + } + mCount = 2; + break; + } } } @@ -2211,40 +2401,63 @@ void LLRender::vertex4a(const LLVector4a& vertex) return; } - if (mUIOffset.empty()) + if (mPrimitiveReset && mCount) { - mVerticesp[mCount]=vertex; + // Insert degenerate + ++mCount; + mVerticesp[mCount] = mVerticesp[mCount - 1]; + mColorsp[mCount] = mColorsp[mCount - 1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; + mVerticesp[mCount - 1] = mVerticesp[mCount - 2]; + mColorsp[mCount - 1] = mColorsp[mCount - 2]; + mTexcoordsp[mCount - 1] = mTexcoordsp[mCount - 2]; } - else + + if (mUIOffset.empty()) { - //LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back()); - mVerticesp[mCount].setAdd(vertex,mUIOffset.back()); - mVerticesp[mCount].mul(mUIScale.back()); + if (!mUIRotation.empty() && mUIRotation.back().isNotIdentity()) + { + LLVector4 vert(vertex.getF32ptr()); + mVerticesp[mCount].loadua((vert*mUIRotation.back()).mV); + } + else + { + mVerticesp[mCount] = vertex; + } } - - if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile) + else { - mQuadCycle++; - if (mQuadCycle == 4) - { //copy two vertices so fourth quad element will add a triangle - mQuadCycle = 0; - - mCount++; - mVerticesp[mCount] = mVerticesp[mCount-3]; - mColorsp[mCount] = mColorsp[mCount-3]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-3]; - - mCount++; - mVerticesp[mCount] = mVerticesp[mCount-2]; - mColorsp[mCount] = mColorsp[mCount-2]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-2]; + if (!mUIRotation.empty() && mUIRotation.back().isNotIdentity()) + { + LLVector4 vert(vertex.getF32ptr()); + vert = vert * mUIRotation.back(); + LLVector4a postrot_vert; + postrot_vert.loadua(vert.mV); + mVerticesp[mCount].setAdd(postrot_vert, mUIOffset.back()); + mVerticesp[mCount].mul(mUIScale.back()); + } + else + { + //LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back()); + mVerticesp[mCount].setAdd(vertex, mUIOffset.back()); + mVerticesp[mCount].mul(mUIScale.back()); } } mCount++; mVerticesp[mCount] = mVerticesp[mCount-1]; mColorsp[mCount] = mColorsp[mCount-1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + + if (mPrimitiveReset && mCount) + { + mCount++; + mVerticesp[mCount] = mVerticesp[mCount - 1]; + mColorsp[mCount] = mColorsp[mCount - 1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; + } + + mPrimitiveReset = false; } void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) @@ -2255,53 +2468,34 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) return; } - if (sGLCoreProfile && mMode == LLRender::QUADS) - { //quads are deprecated, convert to triangle list - S32 i = 0; - - while (i < vert_count) - { - //read first three - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - //copy two - mVerticesp[mCount++] = verts[i-3]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount++] = verts[i-1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - //copy last one - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - } - } - else + if (mPrimitiveReset && mCount) { - for (S32 i = 0; i < vert_count; i++) - { - mVerticesp[mCount] = verts[i]; + // Insert degenerate + ++mCount; + mVerticesp[mCount] = verts[0]; + mColorsp[mCount] = mColorsp[mCount - 1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; + mVerticesp[mCount - 1] = mVerticesp[mCount - 2]; + mColorsp[mCount - 1] = mColorsp[mCount - 2]; + mTexcoordsp[mCount - 1] = mTexcoordsp[mCount - 2]; + ++mCount; + mColorsp[mCount] = mColorsp[mCount - 1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; + } - mCount++; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - } + mVerticesp.copyArray(mCount, verts, vert_count); + + for (S32 i = 0; i < vert_count; i++) + { + mCount++; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; } - mVerticesp[mCount] = mVerticesp[mCount-1]; + if (mCount > 0) // ND: Guard against crashes if mCount is zero, yes it can happen + mVerticesp[mCount] = mVerticesp[mCount-1]; + + mPrimitiveReset = false; } void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count) @@ -2312,54 +2506,37 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 return; } - if (sGLCoreProfile && mMode == LLRender::QUADS) - { //quads are deprecated, convert to triangle list - S32 i = 0; - - while (i < vert_count) - { - //read first three - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - - //copy last two - mVerticesp[mCount] = verts[i-3]; - mTexcoordsp[mCount++] = uvs[i-3]; - mColorsp[mCount] = mColorsp[mCount-1]; + if (mPrimitiveReset && mCount) + { + // Insert degenerate + ++mCount; + mVerticesp[mCount] = verts[0]; + mColorsp[mCount] = mColorsp[mCount - 1]; + mTexcoordsp[mCount] = uvs[0]; + mVerticesp[mCount - 1] = mVerticesp[mCount - 2]; + mColorsp[mCount - 1] = mColorsp[mCount - 2]; + mTexcoordsp[mCount - 1] = mTexcoordsp[mCount - 2]; + ++mCount; + mColorsp[mCount] = mColorsp[mCount - 1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; + } - mVerticesp[mCount] = verts[i-1]; - mTexcoordsp[mCount++] = uvs[i-1]; - mColorsp[mCount] = mColorsp[mCount-1]; + mVerticesp.copyArray(mCount, verts, vert_count); + mTexcoordsp.copyArray(mCount, uvs, vert_count); - //copy last one - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - } - } - else + for (S32 i = 0; i < vert_count; i++) { - for (S32 i = 0; i < vert_count; i++) - { - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; + mCount++; + mColorsp[mCount] = mColorsp[mCount-1]; + } - mCount++; - mColorsp[mCount] = mColorsp[mCount-1]; - } + if (mCount > 0) + { + mVerticesp[mCount] = mVerticesp[mCount - 1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; } - mVerticesp[mCount] = mVerticesp[mCount-1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + mPrimitiveReset = false; } void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) @@ -2370,56 +2547,35 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLCo return; } - - if (sGLCoreProfile && mMode == LLRender::QUADS) - { //quads are deprecated, convert to triangle list - S32 i = 0; - - while (i < vert_count) - { - //read first three - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - - //copy last two - mVerticesp[mCount] = verts[i-3]; - mTexcoordsp[mCount] = uvs[i-3]; - mColorsp[mCount++] = colors[i-3]; + if (mPrimitiveReset && mCount) + { + // Insert degenerate + ++mCount; + mVerticesp[mCount] = verts[0]; + mColorsp[mCount] = colors[mCount - 1]; + mTexcoordsp[mCount] = uvs[0]; + mVerticesp[mCount - 1] = mVerticesp[mCount - 2]; + mColorsp[mCount - 1] = mColorsp[mCount - 2]; + mTexcoordsp[mCount - 1] = mTexcoordsp[mCount - 2]; + ++mCount; + mColorsp[mCount] = mColorsp[mCount - 1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; + } - mVerticesp[mCount] = verts[i-1]; - mTexcoordsp[mCount] = uvs[i-1]; - mColorsp[mCount++] = colors[i-1]; + // Singu Note: Batch copies instead of iterating. + mVerticesp.copyArray(mCount, verts, vert_count); + mTexcoordsp.copyArray(mCount, uvs, vert_count); + mColorsp.copyArray(mCount, colors, vert_count); + mCount += vert_count; - //copy last one - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - } - } - else + if (mCount > 0) { - for (S32 i = 0; i < vert_count; i++) - { - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount] = colors[i]; - - mCount++; - } + mVerticesp[mCount] = mVerticesp[mCount - 1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; + mColorsp[mCount] = mColorsp[mCount - 1]; } - mVerticesp[mCount] = mVerticesp[mCount-1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; + mPrimitiveReset = false; } void LLRender::texCoord2f(const GLfloat& x, const GLfloat& y) @@ -2486,9 +2642,10 @@ void LLRender::diffuseColor3f(F32 r, F32 g, F32 b) { shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,1.f); } - else + else if (r != mNewContext.color.mV[0] || g != mNewContext.color.mV[1] || b != mNewContext.color.mV[2] || mNewContext.color.mV[3] != 1.f || mDirty) { - glColor3f(r,g,b); + flush(); + mNewContext.color.set(r, g, b, 1.f); } } @@ -2501,9 +2658,10 @@ void LLRender::diffuseColor3fv(const F32* c) { shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0], c[1], c[2], 1.f); } - else + else if (c[0] != mNewContext.color.mV[0] || c[1] != mNewContext.color.mV[1] || c[2] != mNewContext.color.mV[2] || mNewContext.color.mV[3] != 1.f || mDirty) { - glColor3fv(c); + flush(); + mNewContext.color.set(c[0], c[1], c[2], 1.f); } } @@ -2516,9 +2674,10 @@ void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a) { shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,a); } - else + else if (r != mNewContext.color.mV[0] || g != mNewContext.color.mV[1] || b != mNewContext.color.mV[2] || a != mNewContext.color.mV[3] || mDirty) { - glColor4f(r,g,b,a); + flush(); + mNewContext.color = { r, g, b, a }; } } @@ -2531,9 +2690,10 @@ void LLRender::diffuseColor4fv(const F32* c) { shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, c); } - else + else if (c[0] != mNewContext.color.mV[0] || c[1] != mNewContext.color.mV[1] || c[2] != mNewContext.color.mV[2] || c[3] != mNewContext.color.mV[3] || mDirty) { - glColor4fv(c); + flush(); + mNewContext.color.set(c); } } @@ -2546,9 +2706,13 @@ void LLRender::diffuseColor4ubv(const U8* c) { shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0]/255.f, c[1]/255.f, c[2]/255.f, c[3]/255.f); } - else + else if (c[0] / 255.f != mNewContext.color.mV[0] || c[1] / 255.f != mNewContext.color.mV[1] || c[2] / 255.f != mNewContext.color.mV[2] || c[3] / 255.f != mNewContext.color.mV[3] || mDirty) { - glColor4ubv(c); + flush(); + mNewContext.color.mV[0] = c[0] / 255.f; + mNewContext.color.mV[1] = c[1] / 255.f; + mNewContext.color.mV[2] = c[2] / 255.f; + mNewContext.color.mV[3] = c[3] / 255.f; } } @@ -2561,22 +2725,25 @@ void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a) { shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f); } - else + else if (r / 255.f != mNewContext.color.mV[0] || g / 255.f != mNewContext.color.mV[1] || b / 255.f != mNewContext.color.mV[2] || a / 255.f != mNewContext.color.mV[3] || mDirty) { - glColor4ub(r,g,b,a); + flush(); + mNewContext.color.mV[0] = r / 255.f; + mNewContext.color.mV[1] = g / 255.f; + mNewContext.color.mV[2] = b / 255.f; + mNewContext.color.mV[3] = a / 255.f; } } - void LLRender::debugTexUnits(void) { - LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL; + LL_INFOS("TextureUnit") << "Active TexUnit: " << getCurrentTexUnitIndex() << LL_ENDL; std::string active_enabled = "false"; for (U32 i = 0; i < mTexUnits.size(); i++) { if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE) { - if (i == mCurrTextureUnitIndex) active_enabled = "true"; + if (i == getCurrentTexUnitIndex()) active_enabled = "true"; LL_INFOS("TextureUnit") << "TexUnit: " << i << " Enabled" << LL_ENDL; LL_INFOS("TextureUnit") << "Enabled As: " ; switch (getTexUnit(i)->mCurrTexType) @@ -2584,9 +2751,6 @@ void LLRender::debugTexUnits(void) case LLTexUnit::TT_TEXTURE: LL_CONT << "Texture 2D"; break; - case LLTexUnit::TT_RECT_TEXTURE: - LL_CONT << "Texture Rectangle"; - break; case LLTexUnit::TT_CUBE_MAP: LL_CONT << "Cube Map"; break; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index cdadd5b03b..381e7592b8 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -38,12 +38,13 @@ #include "v3math.h" #include "v4coloru.h" #include "v4math.h" -#include "llmatrix4a.h" -#include "llalignedarray.h" #include "llstrider.h" #include "llpointer.h" #include "llglheaders.h" +#include "llmatrix4a.h" #include "llrect.h" +#include "llvector4a.h" +#include class LLVertexBuffer; class LLCubeMap; @@ -63,9 +64,7 @@ class LLTexUnit typedef enum { TT_TEXTURE = 0, // Standard 2D Texture - TT_RECT_TEXTURE, // Non power of 2 texture TT_CUBE_MAP, // 6-sided cube map texture - //TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample Do not use TT_NONE // No texture type is currently enabled } eTextureType; @@ -200,7 +199,7 @@ class LLTexUnit void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; } protected: - S32 mIndex; + const S32 mIndex; U32 mCurrTexture; eTextureType mCurrTexType; eTextureBlendType mCurrBlendType; @@ -222,15 +221,57 @@ class LLTexUnit void setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha = false); }; +struct LLLightStateData +{ + LLLightStateData(bool notSun=true) : + mConstantAtten(1.f), + mLinearAtten(0.f), + mQuadraticAtten(0.f), + mSpotExponent(0.f), + mSpotCutoff(180.f) + { + if (!notSun) + { + mDiffuse.set(1, 1, 1, 1); + mSpecular.set(1, 1, 1, 1); + } + mPosition.set(0, 0, 1, 0); + mSpotDirection.set(0, 0, -1); + } + + LLColor4 mDiffuse; + LLColor4 mSpecular; + LLVector4 mPosition; + LLVector3 mSpotDirection; + + F32 mConstantAtten; + F32 mLinearAtten; + F32 mQuadraticAtten; + + F32 mSpotExponent; + F32 mSpotCutoff; +}; + class LLLightState { public: LLLightState(S32 index); - void enable(); - void disable(); + void enable() { setEnabled(true); } + void disable() { setEnabled(false); } + void setState(LLLightStateData& state) { + setDiffuse(state.mDiffuse); + setSpecular(state.mSpecular); + setPosition(state.mPosition); + setConstantAttenuation(state.mConstantAtten); + setLinearAttenuation(state.mLinearAtten); + setQuadraticAttenuation(state.mQuadraticAtten); + setSpotExponent(state.mSpotExponent); + setSpotCutoff(state.mSpotCutoff); + setSpotDirection(state.mSpotDirection); + } + const LLColor4& getDiffuse() const { return mState.mDiffuse; } void setDiffuse(const LLColor4& diffuse); - void setAmbient(const LLColor4& ambient); void setSpecular(const LLColor4& specular); void setPosition(const LLVector4& position); void setConstantAttenuation(const F32& atten); @@ -239,30 +280,23 @@ class LLLightState void setSpotExponent(const F32& exponent); void setSpotCutoff(const F32& cutoff); void setSpotDirection(const LLVector3& direction); + void setEnabled(const bool enabled); protected: friend class LLRender; S32 mIndex; + LLLightStateData mState; bool mEnabled; - LLColor4 mDiffuse; - LLColor4 mAmbient; - LLColor4 mSpecular; - LLVector4 mPosition; - LLVector3 mSpotDirection; - - F32 mConstantAtten; - F32 mLinearAtten; - F32 mQuadraticAtten; - - F32 mSpotExponent; - F32 mSpotCutoff; + LLMatrix4a mPosMatrix; + LLMatrix4a mSpotMatrix; }; LL_ALIGN_PREFIX(16) class LLRender { friend class LLTexUnit; + friend void check_blend_funcs(); public: enum eTexIndex @@ -272,6 +306,13 @@ class LLRender SPECULAR_MAP, NUM_TEXTURE_CHANNELS, }; + + enum eVolumeTexIndex + { + LIGHT_TEX = 0, + SCULPT_TEX, + NUM_VOLUME_TEXTURE_CHANNELS, + }; typedef enum { TRIANGLES = 0, @@ -280,7 +321,6 @@ class LLRender POINTS, LINES, LINE_STRIP, - QUADS, LINE_LOOP, NUM_MODES } eGeomModes; @@ -337,10 +377,101 @@ class LLRender MM_TEXTURE } eMatrixMode; + typedef enum + { + PF_FRONT, + PF_BACK, + PF_FRONT_AND_BACK + } ePolygonFaceType; + + typedef enum + { + PM_POINT, + PM_LINE, + PM_FILL + } ePolygonMode; + + static const U8 NUM_LIGHTS = 8; + + // Cache of global gl state. (excludes nested texunit/light states) + struct Context { + Context() : + texUnit(0), + color{ 1.f,1.f,1.f,1.f }, + colorMask{ 0xf }, + alphaFunc(CF_ALWAYS), + alphaVal(0.f), + blendColorSFactor(BF_ONE), + blendAlphaDFactor(BF_ZERO), + blendAlphaSFactor(BF_ONE), + blendColorDFactor(BF_ZERO), + lineWidth(1.f), + pointSize(1.f), + polygonMode{ PM_FILL, PM_FILL }, + polygonOffset{ 0.f, 0.f }, + viewPort(), + scissor() + { + } + U32 texUnit; + LLColor4 color; + U8 colorMask : 4; + eCompareFunc alphaFunc; + F32 alphaVal; + eBlendFactor blendColorSFactor; + eBlendFactor blendColorDFactor; + eBlendFactor blendAlphaSFactor; + eBlendFactor blendAlphaDFactor; + F32 lineWidth; + F32 pointSize; + ePolygonMode polygonMode[2]; + F32 polygonOffset[2]; + LLRect viewPort; + LLRect scissor; + void printDiff(const Context& other) const + { + if (memcmp(this, &other, sizeof(other)) == 0) + { + return; + } +#define PRINT_DIFF(prop) \ + LL_INFOS() << #prop << ": " << other.prop; \ + if (prop != other.prop) { LL_CONT << " -> " << prop; } \ + LL_CONT << LL_ENDL; +#define PRINT_DIFF_BIT(prop, bit) \ + LL_INFOS() << #prop << "(1<<" << #bit << "): " << (other.prop&(1< " << (prop&(1< mBuffer; LLStrider mVerticesp; @@ -486,15 +649,13 @@ class LLRender LLTexUnit* mDummyTexUnit; std::vector mLightState; - eBlendFactor mCurrBlendColorSFactor; - eBlendFactor mCurrBlendColorDFactor; - eBlendFactor mCurrBlendAlphaSFactor; - eBlendFactor mCurrBlendAlphaDFactor; - F32 mMaxAnisotropy; - LLAlignedArray mUIOffset; - LLAlignedArray mUIScale; + std::vector > mUIOffset; + std::vector > mUIScale; + std::vector mUIRotation; + + bool mPrimitiveReset; } LL_ALIGN_POSTFIX(16); @@ -503,7 +664,7 @@ extern LLMatrix4a gGLLastModelView; extern LLMatrix4a gGLLastProjection; extern LLMatrix4a gGLPreviousModelView; extern LLMatrix4a gGLProjection; -extern S32 gGLViewport[4]; +extern LLRect gGLViewport; extern LLRender gGL; diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index cc447d8700..c869381868 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -123,11 +123,13 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled ) // Counterclockwise quad will face the viewer if( filled ) { - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLES ); gGL.vertex2i(left, top); gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); gGL.vertex2i(right, top); + gGL.vertex2i(right, top); + gGL.vertex2i(left, bottom); + gGL.vertex2i(right, bottom); gGL.end(); } else @@ -195,50 +197,61 @@ void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &st LLColor4 end_color = start_color; end_color.mV[VALPHA] = 0.f; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); // Right edge, CCW faces screen gGL.color4fv(start_color.mV); - gGL.vertex2i(right, top-lines); - gGL.vertex2i(right, bottom); + gGL.vertex2i(right, top - lines); + gGL.vertex2i(right, bottom); gGL.color4fv(end_color.mV); - gGL.vertex2i(right+lines, bottom); - gGL.vertex2i(right+lines, top-lines); + gGL.vertex2i(right + lines, bottom); + gGL.vertex2i(right + lines, bottom); + gGL.vertex2i(right + lines, top - lines); + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, top - lines); // Bottom edge, CCW faces screen - gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); - gGL.vertex2i(left+lines, bottom); + gGL.vertex2i(left + lines, bottom); gGL.color4fv(end_color.mV); - gGL.vertex2i(left+lines, bottom-lines); - gGL.vertex2i(right, bottom-lines); + gGL.vertex2i(left + lines, bottom - lines); + gGL.vertex2i(right, bottom - lines); + gGL.vertex2i(right, bottom - lines); + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, bottom); + gGL.vertex2i(left + lines, bottom); // bottom left Corner gGL.color4fv(start_color.mV); - gGL.vertex2i(left+lines, bottom); + gGL.vertex2i(left + lines, bottom); gGL.color4fv(end_color.mV); - gGL.vertex2i(left, bottom); + gGL.vertex2i(left, bottom); + gGL.vertex2i(left + lines, bottom - lines); + gGL.vertex2i(left + lines, bottom - lines); + gGL.vertex2i(left, bottom); // make the bottom left corner not sharp - gGL.vertex2i(left+1, bottom-lines+1); - gGL.vertex2i(left+lines, bottom-lines); + gGL.vertex2i(left + 1, bottom - lines + 1); // bottom right corner gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); + gGL.vertex2i(right, bottom); gGL.color4fv(end_color.mV); - gGL.vertex2i(right, bottom-lines); + gGL.vertex2i(right, bottom - lines); + gGL.vertex2i(right + lines, bottom); + gGL.vertex2i(right + lines, bottom); + gGL.vertex2i(right, bottom - lines); // make the rightmost corner not sharp - gGL.vertex2i(right+lines-1, bottom-lines+1); - gGL.vertex2i(right+lines, bottom); + gGL.vertex2i(right + lines - 1, bottom - lines + 1); // top right corner gGL.color4fv(start_color.mV); - gGL.vertex2i( right, top-lines ); + gGL.vertex2i(right, top - lines); gGL.color4fv(end_color.mV); - gGL.vertex2i( right+lines, top-lines ); + gGL.vertex2i(right + lines, top - lines); + gGL.vertex2i(right, top); + gGL.vertex2i(right, top); + gGL.vertex2i(right + lines, top - lines); // make the corner not sharp - gGL.vertex2i( right+lines-1, top-1 ); - gGL.vertex2i( right, top ); + gGL.vertex2i(right + lines - 1, top - 1 ); gGL.end(); stop_glerror(); @@ -348,6 +361,11 @@ void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect ); } +void gl_draw_scaled_target(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* target, const LLColor4& color, const LLRectf& uv_rect) +{ + gl_draw_scaled_rotated_image(x, y, width, height, 0.f, NULL, color, uv_rect, target); +} + void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) { if (NULL == image) @@ -358,7 +376,7 @@ void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect ); } -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect) +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect, bool scale_inner) { if (NULL == image) { @@ -371,10 +389,10 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0); LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction); - gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect); + gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect, scale_inner); } -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect) +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect, bool scale_inner) { stop_glerror(); @@ -384,238 +402,230 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex return; } - // add in offset of current image to current UI translation - const LLVector3 ui_scale = gGL.getUIScale(); - const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale); - - F32 uv_width = uv_outer_rect.getWidth(); - F32 uv_height = uv_outer_rect.getHeight(); - - // shrink scaling region to be proportional to clipped image region - LLRectf uv_center_rect( - uv_outer_rect.mLeft + (center_rect.mLeft * uv_width), - uv_outer_rect.mBottom + (center_rect.mTop * uv_height), - uv_outer_rect.mLeft + (center_rect.mRight * uv_width), - uv_outer_rect.mBottom + (center_rect.mBottom * uv_height)); - - F32 image_width = image->getWidth(0); - F32 image_height = image->getHeight(0); + if (solid_color) + { + if (LLGLSLShader::sNoFixedFunction) + { + gSolidColorProgram.bind(); + } + else + { + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); + } + } - S32 image_natural_width = ll_round(image_width * uv_width); - S32 image_natural_height = ll_round(image_height * uv_height); + if (center_rect.mLeft == 0.f + && center_rect.mRight == 1.f + && center_rect.mBottom == 0.f + && center_rect.mTop == 1.f) + { + gl_draw_scaled_image(x, y, width, height, image, color, uv_outer_rect); + } + else + { + // add in offset of current image to current UI translation + const LLVector3 ui_scale = gGL.getUIScale(); + const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale); - LLRectf draw_center_rect( uv_center_rect.mLeft * image_width, - uv_center_rect.mTop * image_height, - uv_center_rect.mRight * image_width, - uv_center_rect.mBottom * image_height); + F32 uv_width = uv_outer_rect.getWidth(); + F32 uv_height = uv_outer_rect.getHeight(); - { // scale fixed region of image to drawn region - draw_center_rect.mRight += width - image_natural_width; - draw_center_rect.mTop += height - image_natural_height; + // shrink scaling region to be proportional to clipped image region + LLRectf uv_center_rect( uv_outer_rect.mLeft + (center_rect.mLeft * uv_width), + uv_outer_rect.mBottom + (center_rect.mTop * uv_height), + uv_outer_rect.mLeft + (center_rect.mRight * uv_width), + uv_outer_rect.mBottom + (center_rect.mBottom * uv_height)); - F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight); - F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop); + F32 image_width = image->getWidth(0); + F32 image_height = image->getHeight(0); - F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth())); - F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight())); + S32 image_natural_width = ll_pos_round(image_width * uv_width); + S32 image_natural_height = ll_pos_round(image_height * uv_height); - F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio); + LLRectf draw_center_rect( uv_center_rect.mLeft * image_width, + uv_center_rect.mTop * image_height, + uv_center_rect.mRight * image_width, + uv_center_rect.mBottom * image_height); + + if (scale_inner) + { + // scale center region of image to drawn region + draw_center_rect.mRight += width - image_natural_width; + draw_center_rect.mTop += height - image_natural_height; - draw_center_rect.mLeft = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]); - draw_center_rect.mTop = ll_round(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]); - draw_center_rect.mRight = ll_round(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]); - draw_center_rect.mBottom = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]); - } + const F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight); + const F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop); - LLRectf draw_outer_rect(ui_translation.mV[VX], - ui_translation.mV[VY] + height * ui_scale.mV[VY], - ui_translation.mV[VX] + width * ui_scale.mV[VX], - ui_translation.mV[VY]); + const F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth())); + const F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight())); - LLGLSUIDefault gls_ui; - - if (solid_color) - { - if (LLGLSLShader::sNoFixedFunction) - { - gSolidColorProgram.bind(); + const F32 border_shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio); + draw_center_rect.mLeft *= border_shrink_scale; + draw_center_rect.mTop = lerp((F32)height, (F32)draw_center_rect.mTop, border_shrink_scale); + draw_center_rect.mRight = lerp((F32)width, (F32)draw_center_rect.mRight, border_shrink_scale); + draw_center_rect.mBottom *= border_shrink_scale; } else { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); + // keep center region of image at fixed scale, but in same relative position + F32 scale_factor = llmin((F32)width / draw_center_rect.getWidth(), (F32)height / draw_center_rect.getHeight(), 1.f); + F32 scaled_width = draw_center_rect.getWidth() * scale_factor; + F32 scaled_height = draw_center_rect.getHeight() * scale_factor; + draw_center_rect.setCenterAndSize(uv_center_rect.getCenterX() * width, uv_center_rect.getCenterY() * height, scaled_width, scaled_height); } - } - gGL.getTexUnit(0)->bind(image, true); + draw_center_rect.mLeft = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * ui_scale.mV[VX]); + draw_center_rect.mTop = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mTop * ui_scale.mV[VY]); + draw_center_rect.mRight = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mRight * ui_scale.mV[VX]); + draw_center_rect.mBottom = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * ui_scale.mV[VY]); + + LLRectf draw_outer_rect(ui_translation.mV[VX], + ui_translation.mV[VY] + height * ui_scale.mV[VY], + ui_translation.mV[VX] + width * ui_scale.mV[VX], + ui_translation.mV[VY]); + + LLGLSUIDefault gls_ui; + + gGL.getTexUnit(0)->bind(image, true); gGL.color4fv(color.mV); - gGL.diffuseColor4fv(color.mV); //workaround: Intel HD 4000 - const S32 NUM_VERTICES = 9 * 4; // 9 quads + const S32 NUM_VERTICES = (2 + 2 * 3) * 3 + 4; LLVector2 uv[NUM_VERTICES]; LLVector4a pos[NUM_VERTICES]; S32 index = 0; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { - // draw bottom left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); - pos[index].set(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + // draw top left + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop); + pos[index].set(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); index++; - // draw bottom middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index].set(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + // draw top middle + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + // draw top right + uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); + pos[index].set(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); index++; - // draw bottom right - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index].set(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom); - pos[index].set(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); + // draw degenerate + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + // draw left + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); index++; - // draw left uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - // draw middle uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - + // draw middle uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - // draw right uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - + // draw right uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); pos[index].set(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - // draw top left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + // draw degenerate + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop); - pos[index].set(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - // draw top middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + // draw bottom left + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); + pos[index].set(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; - // draw top right - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + // draw bottom middle + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index].set(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); - pos[index].set(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); + // draw bottom right + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom); + pos[index].set(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); + } + gGL.end(); } - gGL.end(); if (solid_color) { @@ -635,9 +645,9 @@ void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LL gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect ); } -void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) +void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect, LLRenderTarget* target) { - if (NULL == image) + if (!image && !target) { LL_WARNS() << "image == NULL; aborting function" << LL_ENDL; return; @@ -645,18 +655,24 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre LLGLSUIDefault gls_ui; - - gGL.getTexUnit(0)->bind(image, true); + if(image != NULL) + { + gGL.getTexUnit(0)->bind(image, true); + } + else + { + gGL.getTexUnit(0)->bind(target); + } gGL.color4fv(color.mV); if (degrees == 0.f) { - const S32 NUM_VERTICES = 4; // 9 quads + const S32 NUM_VERTICES = 4; LLVector2 uv[NUM_VERTICES]; LLVector4a pos[NUM_VERTICES]; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { LLVector3 ui_scale = gGL.getUIScale(); LLVector3 ui_translation = gGL.getUITranslation(); @@ -664,12 +680,8 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre ui_translation.mV[VY] += y; ui_translation.scaleVec(ui_scale); S32 index = 0; - S32 scaled_width = ll_round(width * ui_scale.mV[VX]); - S32 scaled_height = ll_round(height * ui_scale.mV[VY]); - - uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); - pos[index].set(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); - index++; + S32 scaled_width = ll_pos_round(width * ui_scale.mV[VX]); + S32 scaled_height = ll_pos_round(height * ui_scale.mV[VY]); uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); pos[index].set(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); @@ -679,6 +691,10 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre pos[index].set(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); index++; + uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); + pos[index].set(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); + index++; + uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); pos[index].set(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); index++; @@ -698,19 +714,22 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre gGL.translateUI(offset_x, offset_y, 0.f); LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD); - - gGL.getTexUnit(0)->bind(image, true); + + if(image != NULL) + { + gGL.getTexUnit(0)->bind(image, true); + } + else + { + gGL.getTexUnit(0)->bind(target); + } gGL.color4fv(color.mV); - - gGL.begin(LLRender::QUADS); + + gGL.begin(LLRender::TRIANGLE_STRIP); { LLVector3 v; - v = LLVector3(offset_x, offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); - gGL.vertex2f(v.mV[0], v.mV[1] ); - v = LLVector3(-offset_x, offset_y, 0.f) * quat; gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop); gGL.vertex2f(v.mV[0], v.mV[1] ); @@ -719,6 +738,10 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); gGL.vertex2f(v.mV[0], v.mV[1] ); + v = LLVector3(offset_x, offset_y, 0.f) * quat; + gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); + gGL.vertex2f(v.mV[0], v.mV[1]); + v = LLVector3(offset_x, -offset_y, 0.f) * quat; gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom); gGL.vertex2f(v.mV[0], v.mV[1] ); @@ -736,12 +759,12 @@ void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LL S32 shift = S32(phase * 4.f) % 4; // Stippled line - LLGLEnable stipple(GL_LINE_STIPPLE); + LLGLEnable stipple; gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]); gGL.flush(); - glLineWidth(2.5f); + gGL.setLineWidth(2.5f); if (!LLGLSLShader::sNoFixedFunction) { @@ -870,15 +893,14 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor if( render_center ) { gGL.color4fv(center_color.mV); - gGL.diffuseColor4fv(center_color.mV); gl_deep_circle( radius, width, steps ); } else { - gGL.diffuseColor4fv(side_color.mV); - gl_washer_2d(radius, radius - width, steps, side_color, side_color); - gGL.translateUI(0.f, 0.f, width); + gGL.color4fv(side_color.mV); gl_washer_2d(radius - width, radius, steps, side_color, side_color); + gGL.translateUI(0.f, 0.f, width); + gl_washer_2d(radius, radius - width, steps, side_color, side_color); } } gGL.popUIMatrix(); @@ -921,15 +943,15 @@ void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin( LLRender::TRIANGLE_STRIP ); + gGL.begin( LLRender::TRIANGLE_STRIP ); { steps += 1; // An extra step to close the circle. while( steps-- ) { + gGL.color4fv(inner_color.mV); + gGL.vertex2f(x2, y2); gGL.color4fv(outer_color.mV); gGL.vertex2f( x1, y1 ); - gGL.color4fv(inner_color.mV); - gGL.vertex2f( x2, y2 ); F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; y1 = x1 * SIN_DELTA + y1 * COS_DELTA; @@ -962,10 +984,10 @@ void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, steps += 1; // An extra step to close the circle. while( steps-- ) { + gGL.color4fv(inner_color.mV); + gGL.vertex2f(x2, y2); gGL.color4fv(outer_color.mV); gGL.vertex2f( x1, y1 ); - gGL.color4fv(inner_color.mV); - gGL.vertex2f( x2, y2 ); F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; y1 = x1 * SIN_DELTA + y1 * COS_DELTA; @@ -1017,41 +1039,45 @@ void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LL void gl_rect_2d_simple_tex( S32 width, S32 height ) { - gGL.begin( LLRender::QUADS ); - - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2i(width, height); - + gGL.begin( LLRender::TRIANGLE_STRIP ); + { gGL.texCoord2f(0.f, 1.f); gGL.vertex2i(0, height); gGL.texCoord2f(0.f, 0.f); gGL.vertex2i(0, 0); + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2i(width, height); + gGL.texCoord2f(1.f, 0.f); gGL.vertex2i(width, 0); - + } gGL.end(); } -void gl_rect_2d_simple( S32 width, S32 height ) +void gl_rect_2d_simple(S32 width, S32 height) { - gGL.begin( LLRender::QUADS ); - gGL.vertex2i(width, height); + gGL.begin(LLRender::TRIANGLES); + { gGL.vertex2i(0, height); gGL.vertex2i(0, 0); + gGL.vertex2i(width, height); + gGL.vertex2i(width, height); + gGL.vertex2i(0, 0); gGL.vertex2i(width, 0); + } gGL.end(); } -void gl_segmented_rect_2d_tex(const S32 left, - const S32 top, - const S32 right, - const S32 bottom, - const S32 texture_width, - const S32 texture_height, - const S32 border_size, - const U32 edges) +void gl_segmented_rect_2d_tex(const S32 left, + const S32 top, + const S32 right, + const S32 bottom, + const S32 texture_width, + const S32 texture_height, + const S32 border_size, + const U32 edges) { S32 width = llabs(right - left); S32 height = llabs(top - bottom); @@ -1078,142 +1104,113 @@ void gl_segmented_rect_2d_tex(const S32 left, LLVector2 width_vec((F32)width, 0.f); LLVector2 height_vec(0.f, (F32)height); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { - // draw bottom left - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2f(0.f, 0.f); - - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(border_width_left.mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); - gGL.vertex2fv(border_height_bottom.mV); - - // draw bottom middle - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(border_width_left.mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((width_vec - border_width_right).mV); + // draw top left + gGL.texCoord2f(0.f, 1.f); + gGL.vertex2fv((height_vec).mV); - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((height_vec - border_height_top).mV); - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((border_width_left + height_vec).mV); - // draw bottom right - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((width_vec - border_width_right).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2fv(width_vec.mV); + // draw top middle + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); - gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + border_height_bottom).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + // draw top right + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2fv((width_vec + height_vec).mV); + gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); + } + gGL.end(); + gGL.begin(LLRender::TRIANGLE_STRIP); + { // draw left + gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((height_vec - border_height_top).mV); + gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); gGL.vertex2fv(border_height_bottom.mV); - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((height_vec - border_height_top).mV); - - // draw middle gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((border_width_left + border_height_bottom).mV); - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - + // draw middle gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - // draw right gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + border_height_bottom).mV); - + // draw right gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - // draw top left - gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((border_width_left + height_vec).mV); - - gGL.texCoord2f(0.f, 1.f); - gGL.vertex2fv((height_vec).mV); + gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + border_height_bottom).mV); - // draw top middle - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + } + gGL.end(); + gGL.begin(LLRender::TRIANGLE_STRIP); + { + // draw bottom left + gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); + gGL.vertex2fv(border_height_bottom.mV); - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2f(0.f, 0.f); - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((border_width_left + height_vec).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(border_width_left.mV); - // draw top right - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + // draw bottom middle + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv((width_vec - border_width_right).mV); - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2fv((width_vec + height_vec).mV); + // draw bottom right + gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + border_height_bottom).mV); - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); + gGL.texCoord2f(1.f , 0.f); + gGL.vertex2fv(width_vec.mV); } gGL.end(); gGL.popUIMatrix(); } -//FIXME: rewrite to use scissor? -void gl_segmented_rect_2d_fragment_tex(const S32 left, - const S32 top, - const S32 right, - const S32 bottom, - const S32 texture_width, - const S32 texture_height, - const S32 border_size, - const F32 start_fragment, - const F32 end_fragment, - const U32 edges) +void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, + const S32 texture_width, + const S32 texture_height, + const S32 border_size, + const F32 start_fragment, + const F32 end_fragment, + const U32 edges) { + const S32 left = rect.mLeft; + const S32 right = rect.mRight; + const S32 top = rect.mTop; + const S32 bottom = rect.mBottom; S32 width = llabs(right - left); S32 height = llabs(top - bottom); @@ -1247,10 +1244,10 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left, LLVector2 x_min; LLVector2 x_max; - gGL.begin(LLRender::QUADS); { if (start_fragment < middle_start) { + gGL.begin(LLRender::TRIANGLE_STRIP); u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX]; u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX]; x_min = (start_fragment / middle_start) * border_width_left; @@ -1263,41 +1260,31 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left, gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); gGL.vertex2fv(x_max.mV); - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - // draw left gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + border_height_bottom).mV); gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + border_height_bottom).mV); - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top left + // draw left gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + height_vec - border_height_top).mV); gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - gGL.texCoord2f(u_max, 1.f); - gGL.vertex2fv((x_max + height_vec).mV); - + // draw top left gGL.texCoord2f(u_min, 1.f); gGL.vertex2fv((x_min + height_vec).mV); + + gGL.texCoord2f(u_max, 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + gGL.end(); } if (end_fragment > middle_start || start_fragment < middle_end) { + gGL.begin(LLRender::TRIANGLE_STRIP); x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec; x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec; @@ -1306,47 +1293,39 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left, gGL.vertex2fv(x_min.mV); gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((x_max).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); + gGL.vertex2fv(x_max.mV); - // draw middle gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + border_height_bottom).mV); gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + border_height_bottom).mV); - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top middle + // draw middle gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + height_vec - border_height_top).mV); gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + // draw top middle + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((x_min + height_vec).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((x_max + height_vec).mV); - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((x_min + height_vec).mV); + gGL.end(); + } if (end_fragment > middle_end) { - u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX]; - u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]; - x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right); - x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right); + gGL.begin(LLRender::TRIANGLE_STRIP); + u_min = 1.f - ((1.f - llmax(0.f, (start_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]); + u_max = 1.f - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]); + x_min = width_vec - ((1.f - llmax(0.f, (start_fragment - middle_end) / middle_start)) * border_width_right); + x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right); // draw bottom right gGL.texCoord2f(u_min, 0.f); @@ -1355,183 +1334,129 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left, gGL.texCoord2f(u_max, 0.f); gGL.vertex2fv(x_max.mV); - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - // draw right gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + border_height_bottom).mV); gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + border_height_bottom).mV); - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top right + // draw right gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + height_vec - border_height_top).mV); gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - gGL.texCoord2f(u_max, 1.f); - gGL.vertex2fv((x_max + height_vec).mV); - + // draw top right gGL.texCoord2f(u_min, 1.f); gGL.vertex2fv((x_min + height_vec).mV); + + gGL.texCoord2f(u_max, 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + gGL.end(); } } - gGL.end(); gGL.popUIMatrix(); } -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, - const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, - const U32 edges) +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, + const LLVector3& width_vec, const LLVector3& height_vec) { - LLVector3 left_border_width = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? border_width : LLVector3::zero; - LLVector3 right_border_width = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? border_width : LLVector3::zero; - - LLVector3 top_border_height = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? border_height : LLVector3::zero; - LLVector3 bottom_border_height = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? border_height : LLVector3::zero; - - - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { - // draw bottom left - gGL.texCoord2f(0.f, 0.f); - gGL.vertex3f(0.f, 0.f, 0.f); - - gGL.texCoord2f(border_scale.mV[VX], 0.f); - gGL.vertex3fv(left_border_width.mV); - - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); - - gGL.texCoord2f(0.f, border_scale.mV[VY]); - gGL.vertex3fv(bottom_border_height.mV); - - // draw bottom middle - gGL.texCoord2f(border_scale.mV[VX], 0.f); - gGL.vertex3fv(left_border_width.mV); - - gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); - gGL.vertex3fv((width_vec - right_border_width).mV); + // draw top left + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop); + gGL.vertex3fv((height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); - // draw bottom right - gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); - gGL.vertex3fv((width_vec - right_border_width).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex3fv(width_vec.mV); + // draw top middle + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); - gGL.texCoord2f(1.f, border_scale.mV[VY]); - gGL.vertex3fv((width_vec + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + // draw top right + gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((width_vec + height_vec).mV); + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); + } + gGL.end(); + gGL.begin(LLRender::TRIANGLE_STRIP); + { // draw left - gGL.texCoord2f(0.f, border_scale.mV[VY]); - gGL.vertex3fv(bottom_border_height.mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); // draw middle - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); - - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); - - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); // draw right - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); - - gGL.texCoord2f(1.f, border_scale.mV[VY]); - gGL.vertex3fv((width_vec + bottom_border_height).mV); - - gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); - // draw top left - gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((height_vec - top_border_height).mV); - - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); - - gGL.texCoord2f(border_scale.mV[VX], 1.f); - gGL.vertex3fv((left_border_width + height_vec).mV); - - gGL.texCoord2f(0.f, 1.f); - gGL.vertex3fv((height_vec).mV); - - // draw top middle - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + } + gGL.end(); + gGL.begin(LLRender::TRIANGLE_STRIP); + { + // draw bottom left + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom); + gGL.vertex3f(0.f, 0.f, 0.f); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); - gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f); - gGL.vertex3fv((left_border_width + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); - // draw top right - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + // draw bottom middle + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); - gGL.texCoord2f(1.f, 1.f); - gGL.vertex3fv((width_vec + height_vec).mV); + // draw bottom right + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); - gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); + gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom); + gGL.vertex3fv(width_vec.mV); } gGL.end(); } -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec) -{ - gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP); -} - // static void LLRender2D::initClass(LLImageProviderInterface* image_provider, const LLVector2* scale_factor) @@ -1593,8 +1518,7 @@ void LLRender2D::setScaleFactor(const LLVector2 &scale_factor) //static void LLRender2D::setLineWidth(F32 width) { - gGL.flush(); - glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f)); + gGL.setLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f)); } //static diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h index 0323af6a26..1a2fbdbf43 100644 --- a/indra/llrender/llrender2dutils.h +++ b/indra/llrender/llrender2dutils.h @@ -71,11 +71,12 @@ void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color); void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_target(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* target, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), LLRenderTarget* target = NULL); +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true); +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true); void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f ); @@ -105,9 +106,8 @@ typedef enum e_rounded_edge void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec); +void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec); inline void gl_rect_2d( const LLRect& rect, BOOL filled ) { diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 3010f9dc58..af5ad22e2f 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -85,7 +85,7 @@ void LLRenderTarget::resize(U32 resx, U32 resy) for (U32 i = 0; i < mTex.size(); ++i) { //resize color attachments gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]); - LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, mInternalFormat[i], mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, mInternalFormat[i], mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE); sBytesAllocated += pix_diff*4; } @@ -103,9 +103,9 @@ void LLRenderTarget::resize(U32 resx, U32 resy) gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); if(!mStencil) - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); else - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8, mResX, mResY, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL, false); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8, mResX, mResY, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); } sBytesAllocated += pix_diff*4; @@ -195,8 +195,8 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) return false; } - U32 tex; - LLImageGL::generateTextures(1, &tex); + auto texName = LLImageGL::createTextureName(); + U32 tex = texName->getTexName(); gGL.getTexUnit(0)->bindManual(mUsage, tex); stop_glerror(); @@ -204,7 +204,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) { clear_glerror(); - LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE); if (glGetError() != GL_NO_ERROR) { LL_WARNS() << "Could not allocate color buffer for render target." << LL_ENDL; @@ -228,17 +228,8 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) stop_glerror(); } - if (mUsage != LLTexUnit::TT_RECT_TEXTURE) - { - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); - stop_glerror(); - } - else - { - // ATI doesn't support mirrored repeat for rectangular textures. - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - stop_glerror(); - } + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); + stop_glerror(); if (mFBO) { @@ -254,6 +245,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) } mTex.push_back(tex); + mTexName.push_back(texName); mInternalFormat.push_back(color_fmt); if (gDebugGL) @@ -267,6 +259,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) bool LLRenderTarget::allocateDepth() { + mDepthName.reset(); if (mStencil && mFBO) { //use render buffers where stencil buffers are in play @@ -279,16 +272,18 @@ bool LLRenderTarget::allocateDepth() } else { - LLImageGL::generateTextures(1, &mDepth); + mDepthName = LLImageGL::createTextureName(); + mDepth = mDepthName->getTexName(); + gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); stop_glerror(); clear_glerror(); if(!mStencil) - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); else - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8, mResX, mResY, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL, false); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8, mResX, mResY, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } @@ -366,7 +361,6 @@ void LLRenderTarget::release() glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0); glBindFramebuffer(GL_FRAMEBUFFER,0); } - LLImageGL::deleteTextures(1, &mDepth); stop_glerror(); } mDepth = 0; @@ -396,13 +390,11 @@ void LLRenderTarget::release() mFBO = 0; } - if (mTex.size() > 0) - { - sBytesAllocated -= mResX*mResY*4*mTex.size(); - LLImageGL::deleteTextures(mTex.size(), &mTex[0]); - mTex.clear(); - mInternalFormat.clear(); - } + sBytesAllocated -= mResX * mResY * 4 * mTex.size(); + mTex.clear(); + mInternalFormat.clear(); + mDepthName.reset(); + mTexName.clear(); // Were textures not being released at all..? mResX = mResY = 0; @@ -449,8 +441,7 @@ void LLRenderTarget::bindTarget() stop_glerror(); } } - - glViewport(0, 0, mResX, mResY); + gGL.setViewport(0, 0, mResX, mResY); sBoundTarget = this; } @@ -461,18 +452,22 @@ void LLRenderTarget::clear(U32 mask_in) { mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; } + if (mFBO) { check_framebuffer_status(); stop_glerror(); + LLGLDisable scissor; + gGL.syncContextState(); glClear(mask & mask_in); stop_glerror(); } else { - LLGLEnable scissor(GL_SCISSOR_TEST); - glScissor(0, 0, mResX, mResY); + LLGLEnable scissor; + gGL.setScissor(0, 0, mResX, mResY); stop_glerror(); + gGL.syncContextState(); glClear(mask & mask_in); } } @@ -524,7 +519,7 @@ void LLRenderTarget::flush(bool fetch_depth) stop_glerror(); if(mSampleBuffer) { - LLGLEnable multisample(GL_MULTISAMPLE); + LLGLEnable multisample; stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); stop_glerror(); @@ -584,12 +579,12 @@ void LLRenderTarget::flush(bool fetch_depth) if(mPreviousFBO) { - glViewport(0, 0, mPreviousFBO->mResX, mPreviousFBO->mResY); + gGL.setViewport(0, 0, mPreviousFBO->mResX, mPreviousFBO->mResY); mPreviousFBO = NULL; } else { - glViewport(gGLViewport[0],gGLViewport[1],gGLViewport[2],gGLViewport[3]); + gGL.setViewport(gGLViewport); } stop_glerror(); } @@ -692,12 +687,9 @@ bool LLRenderTarget::isComplete() const return (!mTex.empty() || mDepth) ? true : false; } -void LLRenderTarget::getViewport(S32* viewport) +void LLRenderTarget::getViewport(LLRect& viewport) { - viewport[0] = 0; - viewport[1] = 0; - viewport[2] = mResX; - viewport[3] = mResY; + viewport = LLRect(0, mResY, mResX, 0); } //================================================== @@ -763,7 +755,7 @@ void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) check_framebuffer_status(); - glViewport(0, 0, mResX, mResY); + gGL.setViewport(0, 0, mResX, mResY); sBoundTarget = this; } diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index a0f4093343..bf37cba2bd 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -107,7 +107,7 @@ class LLRenderTarget void clear(U32 mask = 0xFFFFFFFF); //get applied viewport - void getViewport(S32* viewport); + void getViewport(LLRect& viewport); //get X resolution U32 getWidth() const { return mResX; } @@ -152,9 +152,11 @@ class LLRenderTarget U32 mResX; U32 mResY; std::vector mTex; + std::vector mTexName; std::vector mInternalFormat; U32 mFBO; LLRenderTarget* mPreviousFBO; + LLImageGL::GLTextureName mDepthName; U32 mDepth; bool mStencil; bool mUseDepth; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index f7496140c3..568ec8c14f 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -80,7 +80,11 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) { llassert_always(shader != NULL); LLShaderFeatures *features = & shader->mFeatures; - + + if (features->attachNothing) + { + return TRUE; + } ////////////////////////////////////// // Attach Vertex Shader Features First ////////////////////////////////////// @@ -494,27 +498,28 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) //============================================================================ // Load Shader -static std::string get_object_log(GLhandleARB ret) +static std::string get_object_log(GLhandleARB ret, bool isProgram) { std::string res; //get log length GLint length; - glGetObjectParameterivARB(ret, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + (isProgram ? glGetProgramiv : glGetShaderiv)(ret, GL_INFO_LOG_LENGTH, &length); + if (length > 0) { //the log could be any size, so allocate appropriately GLcharARB* log = new GLcharARB[length]; - glGetInfoLogARB(ret, length, &length, log); + (isProgram ? glGetProgramInfoLog : glGetShaderInfoLog)(ret, length, &length, log); res = std::string((char *)log); delete[] log; } return res; } -void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) +void LLShaderMgr::dumpObjectLog(GLhandleARB ret, bool isProgram, bool warns) { - std::string log = get_object_log(ret); + std::string log = get_object_log(ret, isProgram); if ( log.length() > 0 ) { if (warns) @@ -534,7 +539,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade range = mShaderObjects.equal_range(filename); for (std::multimap::iterator it = range.first; it != range.second;++it) { - if((*it).second.mLevel == shader_level && (*it).second.mType == type && (*it).second.mDefinitions == (defines ? *defines : std::map())) + if((*it).second.mLevel == shader_level && (*it).second.mType == type && (*it).second.mIndexChannels == texture_index_channels && (*it).second.mDefinitions == (defines ? *defines : std::map())) { //LL_INFOS("ShaderLoading") << "Loading cached shader for " << filename << LL_ENDL; return (*it).second.mHandle; @@ -551,7 +556,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } } - LL_DEBUGS("ShaderLoading") << "Loading shader file: " << filename << " class " << shader_level << LL_ENDL; + LL_INFOS("ShaderLoading") << "Loading shader file: " << filename << " class " << shader_level << LL_ENDL; if (filename.empty()) { @@ -607,92 +612,90 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (minor_version <= 19) { text[count++] = strdup("#version 110\n"); - text[count++] = strdup("#define ATTRIBUTE attribute\n"); - text[count++] = strdup("#define VARYING varying\n"); - text[count++] = strdup("#define VARYING_FLAT varying\n"); - // Need to enable extensions here instead of in the shader files, - // before any non-preprocessor directives (per spec) - text[count++] = strdup("#extension GL_ARB_texture_rectangle : enable\n"); - text[count++] = strdup("#extension GL_ARB_shader_texture_lod : enable\n"); } else if (minor_version <= 29) { //set version to 1.20 text[count++] = strdup("#version 120\n"); - text[count++] = strdup("#define FXAA_GLSL_120 1\n"); - text[count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n"); - text[count++] = strdup("#define ATTRIBUTE attribute\n"); - text[count++] = strdup("#define VARYING varying\n"); - text[count++] = strdup("#define VARYING_FLAT varying\n"); - // Need to enable extensions here instead of in the shader files, - // before any non-preprocessor directives (per spec) - text[count++] = strdup("#extension GL_ARB_texture_rectangle : enable\n"); - text[count++] = strdup("#extension GL_ARB_shader_texture_lod : enable\n"); + if (type == GL_FRAGMENT_SHADER_ARB) + { + // Need to enable extensions here instead of in the shader files, + // before any non-preprocessor directives (per spec) + text[count++] = strdup("#extension GL_ARB_shader_texture_lod : enable\n"); + text[count++] = strdup("#define FXAA_GLSL_120 1\n"); + text[count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n"); + } } + + text[count++] = strdup("#define ATTRIBUTE attribute\n"); + text[count++] = strdup("#define VARYING varying\n"); + text[count++] = strdup("#define VARYING_FLAT varying\n"); } else { if (major_version < 4) { - //set version to 1.30 - text[count++] = strdup("#version 130\n"); - // Need to enable extensions here instead of in the shader files, - // before any non-preprocessor directives (per spec) - text[count++] = strdup("#extension GL_ARB_texture_rectangle : enable\n"); - text[count++] = strdup("#extension GL_ARB_shader_texture_lod : enable\n"); - - + if (major_version > 1 || minor_version >= 40) + { + //set version to 1.40 + text[count++] = strdup("#version 140\n"); + } + else + { + //set version to 1.30 + text[count++] = strdup("#version 130\n"); + } + if (minor_version == 50 && gGLManager.mHasGpuShader5) + { + // Need to enable extensions here instead of in the shader files, + // before any non-preprocessor directives (per spec) + text[count++] = strdup("#extension GL_ARB_gpu_shader5 : enable\n"); + } //some implementations of GLSL 1.30 require integer precision be explicitly declared text[count++] = strdup("precision mediump int;\n"); text[count++] = strdup("precision highp float;\n"); + if (type == GL_FRAGMENT_SHADER_ARB) + { + text[count++] = strdup("#define FXAA_GLSL_130 1\n"); + } } else { //set version to 400 text[count++] = strdup("#version 400\n"); - // Need to enable extensions here instead of in the shader files, - // before any non-preprocessor directives (per spec) - text[count++] = strdup("#extension GL_ARB_texture_rectangle : enable\n"); - text[count++] = strdup("#extension GL_ARB_shader_texture_lod : enable\n"); + if (type == GL_FRAGMENT_SHADER_ARB) + { + text[count++] = strdup("#define FXAA_GLSL_400 1\n"); + } } - - - text[count++] = strdup("#define DEFINE_GL_FRAGCOLOR 1\n"); - text[count++] = strdup("#define FXAA_GLSL_130 1\n"); - - text[count++] = strdup("#define ATTRIBUTE in\n"); if (type == GL_VERTEX_SHADER_ARB) { //"varying" state is "out" in a vertex program, "in" in a fragment program // ("varying" is deprecated after version 1.20) + text[count++] = strdup("#define ATTRIBUTE in\n"); text[count++] = strdup("#define VARYING out\n"); text[count++] = strdup("#define VARYING_FLAT flat out\n"); } else { + text[count++] = strdup("#define DEFINE_GL_FRAGCOLOR 1\n"); text[count++] = strdup("#define VARYING in\n"); text[count++] = strdup("#define VARYING_FLAT flat in\n"); - } - - //backwards compatibility with legacy texture lookup syntax - text[count++] = strdup("#define texture2D texture\n"); - text[count++] = strdup("#define textureCube texture\n"); - text[count++] = strdup("#define texture2DLod textureLod\n"); - text[count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n"); - if (major_version > 1 || minor_version >= 40) - { //GLSL 1.40 replaces texture2DRect et al with texture - text[count++] = strdup("#define texture2DRect texture\n"); - text[count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n"); + //backwards compatibility with legacy texture lookup syntax + text[count++] = strdup("#define texture2D texture\n"); + text[count++] = strdup("#define textureCube texture\n"); + text[count++] = strdup("#define texture2DLod textureLod\n"); + text[count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n"); } } if(defines) { for (std::map::iterator iter = defines->begin(); iter != defines->end(); ++iter) - { - std::string define = "#define " + iter->first + " " + iter->second + "\n"; - text[count++] = (GLcharARB *) strdup(define.c_str()); - } + { + std::string define = "#define " + iter->first + " " + iter->second + "\n"; + text[count++] = (GLcharARB *) strdup(define.c_str()); + } } if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB) @@ -789,7 +792,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade LL_ERRS() << "Indexed texture rendering requires GLSL 1.30 or later." << LL_ENDL; } } - else + else if( type == GL_FRAGMENT_SHADER_ARB ) { text[count++] = strdup("#define HAS_DIFFUSE_LOOKUP 0\n"); } @@ -809,7 +812,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (error != GL_NO_ERROR) { LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; - glDeleteObjectARB(ret); //no longer need handle + glDeleteShader(ret); //no longer need handle ret=0; } } @@ -825,7 +828,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (error != GL_NO_ERROR) { LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << LL_ENDL; - glDeleteObjectARB(ret); //no longer need handle + glDeleteShader(ret); //no longer need handle ret=0; } } @@ -842,7 +845,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (error != GL_NO_ERROR) { LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL; - glDeleteObjectARB(ret); //no longer need handle + glDeleteShader(ret); //no longer need handle ret=0; } } @@ -854,7 +857,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade { //check for errors GLint success = GL_TRUE; - glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success); + glGetShaderiv(ret, GL_COMPILE_STATUS, &success); if (gDebugGL || success == GL_FALSE) { error = glGetError(); @@ -862,10 +865,9 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade { //an error occured, print log LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL; - dumpObjectLog(ret); - error_str = get_object_log(ret); + dumpObjectLog(ret, false); + error_str = get_object_log(ret, false); -#if LL_WINDOWS std::stringstream ostr; //dump shader source for debugging for (GLuint i = 0; i < count; i++) @@ -876,31 +878,19 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade { //dump every 128 lines LL_WARNS("ShaderLoading") << "\n" << ostr.str() << LL_ENDL; - ostr = std::stringstream(); + ostr.clear(); + ostr.str(LLStringUtil::null); } } LL_WARNS("ShaderLoading") << "\n" << ostr.str() << LL_ENDL; -#else - std::string str; - - for (GLuint i = 0; i < count; i++) { - str.append(text[i]); - - if (i % 128 == 0) - { - LL_WARNS("ShaderLoading") << str << LL_ENDL; - str = ""; - } - } -#endif - glDeleteObjectARB(ret); //no longer need handle + glDeleteShader(ret); //no longer need handle ret = 0; } } if(ret) - dumpObjectLog(ret,false); + dumpObjectLog(ret, false, false); } static const LLCachedControl dump_raw_shaders("ShyotlDumpRawShaders",false); @@ -941,7 +931,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (ret) { // Add shader file to map - mShaderObjects.insert(make_pair(filename,CachedObjectInfo(ret,try_gpu_class,type,defines))); + mShaderObjects.insert(make_pair(filename,CachedObjectInfo(ret,try_gpu_class,type, texture_index_channels,defines))); shader_level = try_gpu_class; } else @@ -956,12 +946,69 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade return ret; } +void LLShaderMgr::unloadShaders() +{ + //Instead of manually unloading, shaders are now automatically accumulated in a list. + //Simply iterate and unload. + std::vector &shader_list = LLShaderMgr::getGlobalShaderList(); + for (std::vector::iterator it = shader_list.begin(); it != shader_list.end(); ++it) + (*it)->unload(); + mShaderObjects.clear(); + mProgramObjects.clear(); +} + +void LLShaderMgr::unloadShaderObjects() +{ + std::multimap::iterator it = mShaderObjects.begin(); + for (; it != mShaderObjects.end(); ++it) + if (it->second.mHandle) + glDeleteShader(it->second.mHandle); + mShaderObjects.clear(); + cleanupShaderSources(); +} + +void LLShaderMgr::cleanupShaderSources() +{ + if (!mProgramObjects.empty()) + { + for (auto iter = mProgramObjects.cbegin(), + iter_end = mProgramObjects.cend(); iter != iter_end; ++iter) + { + GLuint program = iter->second; + if (program > 0) + { + GLhandleARB shaders[1024] = {}; + GLsizei count = -1; + glGetAttachedObjectsARB(program, 1024, &count, shaders); + if (count > 0) + { + for (GLsizei i = 0; i < count; ++i) + { + std::multimap::iterator it = mShaderObjects.begin(); + for (; it != mShaderObjects.end(); it++) + { + if ((*it).second.mHandle == shaders[i]) + { + glDetachObjectARB(program, shaders[i]); + break; + } + } + } + } + } + } + + // Clear the linked program list as its no longer needed + mProgramObjects.clear(); + } +} + BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors) { //check for errors glLinkProgramARB(obj); GLint success = GL_TRUE; - glGetObjectParameterivARB(obj, GL_OBJECT_LINK_STATUS_ARB, &success); + glGetProgramiv(obj, GL_LINK_STATUS, &success); if (!suppress_errors && success == GL_FALSE) { //an error occured, print log @@ -1005,7 +1052,7 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors) } #else - std::string log = get_object_log(obj); + std::string log = get_object_log(obj, true); LLStringUtil::toLower(log); if (log.find("software") != std::string::npos) { @@ -1016,7 +1063,7 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors) #endif if (!suppress_errors) { - dumpObjectLog(obj, !success); + dumpObjectLog(obj, true, !success); } return success; @@ -1027,15 +1074,15 @@ BOOL LLShaderMgr::validateProgramObject(GLhandleARB obj) //check program validity against current GL glValidateProgramARB(obj); GLint success = GL_TRUE; - glGetObjectParameterivARB(obj, GL_OBJECT_VALIDATE_STATUS_ARB, &success); + glGetProgramiv(obj, GL_VALIDATE_STATUS, &success); if (success == GL_FALSE) { LL_WARNS("ShaderLoading") << "GLSL program not valid: " << LL_ENDL; - dumpObjectLog(obj); + dumpObjectLog(obj, true); } else { - dumpObjectLog(obj, FALSE); + dumpObjectLog(obj, true, false); } return success; @@ -1073,8 +1120,6 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("object_plane_t"); llassert(mReservedUniforms.size() == LLShaderMgr::OBJECT_PLANE_T+1); - mReservedUniforms.push_back("viewport"); - mReservedUniforms.push_back("light_position"); mReservedUniforms.push_back("light_direction"); mReservedUniforms.push_back("light_attenuation"); @@ -1109,7 +1154,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("specularMap"); mReservedUniforms.push_back("bumpMap"); mReservedUniforms.push_back("environmentMap"); - mReservedUniforms.push_back("cloude_noise_texture"); + mReservedUniforms.push_back("cloud_noise_texture"); mReservedUniforms.push_back("fullbright"); mReservedUniforms.push_back("lightnorm"); mReservedUniforms.push_back("sunlight_color_copy"); @@ -1165,7 +1210,9 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("ssao_factor"); mReservedUniforms.push_back("ssao_factor_inv"); mReservedUniforms.push_back("ssao_effect"); - mReservedUniforms.push_back("screen_res"); + mReservedUniforms.push_back("ssao_scale"); + mReservedUniforms.push_back("kern_scale"); + mReservedUniforms.push_back("noise_scale"); mReservedUniforms.push_back("near_clip"); mReservedUniforms.push_back("shadow_offset"); mReservedUniforms.push_back("shadow_bias"); @@ -1181,7 +1228,6 @@ void LLShaderMgr::initAttribsAndUniforms() llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_DOWNSAMPLED_DEPTH_SCALE+1); - mReservedUniforms.push_back("tc_scale"); mReservedUniforms.push_back("rcp_screen_res"); mReservedUniforms.push_back("rcp_frame_opt"); mReservedUniforms.push_back("rcp_frame_opt2"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index e29f80f103..61c949c540 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -49,7 +49,6 @@ class LLShaderMgr TEXTURE_MATRIX3, OBJECT_PLANE_S, OBJECT_PLANE_T, - VIEWPORT, LIGHT_POSITION, LIGHT_DIRECTION, LIGHT_ATTENUATION, @@ -124,7 +123,9 @@ class LLShaderMgr DEFERRED_SSAO_FACTOR, DEFERRED_SSAO_FACTOR_INV, DEFERRED_SSAO_EFFECT, - DEFERRED_SCREEN_RES, + DEFERRED_SSAO_SCALE, + DEFERRED_KERN_SCALE, + DEFERRED_NOISE_SCALE, DEFERRED_NEAR_CLIP, DEFERRED_SHADOW_OFFSET, DEFERRED_SHADOW_BIAS, @@ -138,7 +139,6 @@ class LLShaderMgr DEFERRED_SHADOW_TARGET_WIDTH, DEFERRED_DOWNSAMPLED_DEPTH_SCALE, - FXAA_TC_SCALE, FXAA_RCP_SCREEN_RES, FXAA_RCP_FRAME_OPT, FXAA_RCP_FRAME_OPT2, @@ -228,30 +228,37 @@ DISPLAY_GAMMA, virtual void initAttribsAndUniforms(void); BOOL attachShaderFeatures(LLGLSLShader * shader); - void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE); + void dumpObjectLog(GLhandleARB ret, bool isProgram, bool warns = TRUE); BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE); BOOL validateProgramObject(GLhandleARB obj); GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map* defines = NULL, S32 texture_index_channels = -1); + void unloadShaders(); + void unloadShaderObjects(); // Implemented in the application to actually point to the shader directory. virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual // Implemented in the application to actually update out of date uniforms for a particular shader virtual void updateShaderUniforms(LLGLSLShader * shader) = 0; // Pure Virtual + virtual bool attachClassSharedShaders(LLGLSLShader& shader, S32 shader_class) = 0; // Pure Virtual public: struct CachedObjectInfo { - CachedObjectInfo(GLhandleARB handle, U32 level, GLenum type, std::map *definitions) : - mHandle(handle), mLevel(level), mType(type), mDefinitions(definitions ? *definitions : std::map()){} + CachedObjectInfo(GLhandleARB handle, U32 level, GLenum type, U32 texture_index_channels, std::map *definitions) : + mHandle(handle), mLevel(level), mType(type), mIndexChannels(texture_index_channels), mDefinitions(definitions ? *definitions : std::map()){} GLhandleARB mHandle; //Actual handle of the opengl shader object. U32 mLevel; //Level /might/ not be needed, but it's stored to ensure there's no change in behavior. GLenum mType; //GL_VERTEX_SHADER_ARB or GL_FRAGMENT_SHADER_ARB. Tracked because some utility shaders can be loaded as both types (carefully). + U32 mIndexChannels; //LLShaderFeatures::mIndexedTextureChannels std::map mDefinitions; }; // Map of shader names to compiled std::multimap mShaderObjects; //Singu Note: Packing more info here. Doing such provides capability to skip unneeded duplicate loading.. + // Map of program names linked + std::map mProgramObjects; + //global (reserved slot) shader parameters std::vector mReservedAttribs; @@ -261,6 +268,7 @@ DISPLAY_GAMMA, std::map mDefinitions; protected: + void cleanupShaderSources(); // our parameter manager singleton instance static LLShaderMgr * sInstance; diff --git a/indra/llrender/lluiimage.cpp b/indra/llrender/lluiimage.cpp index 2be700aad9..58478ac520 100644 --- a/indra/llrender/lluiimage.cpp +++ b/indra/llrender/lluiimage.cpp @@ -38,11 +38,9 @@ LLUIImage::LLUIImage(const std::string& name, LLPointer image) mImage(image), mScaleRegion(0.f, 1.f, 1.f, 0.f), mClipRegion(0.f, 1.f, 1.f, 0.f), - mUniformScaling(TRUE), - mNoClip(TRUE), - mImageLoaded(NULL) -{ -} + mImageLoaded(NULL), + mScaleStyle(SCALE_INNER) +{} LLUIImage::~LLUIImage() { @@ -52,44 +50,35 @@ LLUIImage::~LLUIImage() void LLUIImage::setClipRegion(const LLRectf& region) { mClipRegion = region; - mNoClip = mClipRegion.mLeft == 0.f - && mClipRegion.mRight == 1.f - && mClipRegion.mBottom == 0.f - && mClipRegion.mTop == 1.f; } void LLUIImage::setScaleRegion(const LLRectf& region) { mScaleRegion = region; - mUniformScaling = mScaleRegion.mLeft == 0.f - && mScaleRegion.mRight == 1.f - && mScaleRegion.mBottom == 0.f - && mScaleRegion.mTop == 1.f; +} + +void LLUIImage::setScaleStyle(LLUIImage::EScaleStyle style) +{ + mScaleStyle = style; } //TODO: move drawing implementation inside class void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const { - gl_draw_scaled_image(x, y, getWidth(), getHeight(), mImage, color, mClipRegion); + draw(x, y, getWidth(), getHeight(), color); } void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const { - if (mUniformScaling) - { - gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion); - } - else - { - gl_draw_scaled_image_with_border( - x, y, - width, height, - mImage, - color, - FALSE, - mClipRegion, - mScaleRegion); - } + gl_draw_scaled_image_with_border( + x, y, + width, height, + mImage, + color, + FALSE, + mClipRegion, + mScaleRegion, + mScaleStyle == SCALE_INNER); } void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const @@ -101,7 +90,8 @@ void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& c color, TRUE, mClipRegion, - mScaleRegion); + mScaleRegion, + mScaleStyle == SCALE_INNER); } void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const @@ -112,16 +102,60 @@ void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& drawSolid(border_rect, color); } +void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, + const LLRect& rect, const LLColor4& color) +{ + F32 border_scale = 1.f; + F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight(); + F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth(); + if (rect.getHeight() < border_height || rect.getWidth() < border_width) + { + if(border_height - rect.getHeight() > border_width - rect.getWidth()) + { + border_scale = (F32)rect.getHeight() / border_height; + } + else + { + border_scale = (F32)rect.getWidth() / border_width; + } + } + + LLRender2D::pushMatrix(); + { + LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis); + LLRender2D::translate(rect_origin.mV[VX], + rect_origin.mV[VY], + rect_origin.mV[VZ]); + gGL.getTexUnit(0)->bind(getImage()); + gGL.color4fv(color.mV); + + LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(), + mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(), + mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(), + mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight()); + gl_segmented_rect_3d_tex(mClipRegion, + center_uv_rect, + LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(), + (rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(), + (rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(), + (border_height * border_scale * 0.5f) / (F32)rect.getHeight()), + rect.getWidth() * x_axis, + rect.getHeight() * y_axis); + + } LLRender2D::popMatrix(); +} + + S32 LLUIImage::getWidth() const { // return clipped dimensions of actual image area - return ll_round((F32)mImage->getWidth(0) * mClipRegion.getWidth()); + return ll_pos_round((F32)mImage->getWidth(0) * mClipRegion.getWidth()); } S32 LLUIImage::getHeight() const { // return clipped dimensions of actual image area - return ll_round((F32)mImage->getHeight(0) * mClipRegion.getHeight()); + return ll_pos_round((F32)mImage->getHeight(0) * mClipRegion.getHeight()); } S32 LLUIImage::getTextureWidth() const @@ -152,3 +186,48 @@ void LLUIImage::onImageLoaded() } } + +namespace LLInitParam +{ + void ParamValue::updateValueFromBlock() + { + // The keyword "none" is specifically requesting a null image + // do not default to current value. Used to overwrite template images. + if (name() == "none") + { + updateValue(NULL); + return; + } + + LLUIImage* imagep = LLRender2D::getUIImage(name()); + if (imagep) + { + updateValue(imagep); + } + } + + void ParamValue::updateBlockFromValue(bool make_block_authoritative) + { + if (getValue() == NULL) + { + name.set("none", make_block_authoritative); + } + else + { + name.set(getValue()->getName(), make_block_authoritative); + } + } + + + bool ParamCompare::equals( + LLUIImage* const &a, + LLUIImage* const &b) + { + // force all LLUIImages for XML UI export to be "non-default" + if (!a && !b) + return false; + else + return (a == b); + } +} + diff --git a/indra/llrender/lluiimage.h b/indra/llrender/lluiimage.h index 7df662119e..939f78d65d 100644 --- a/indra/llrender/lluiimage.h +++ b/indra/llrender/lluiimage.h @@ -37,6 +37,7 @@ #define BOOST_FUNCTION_HPP_INCLUDED #endif #include +#include "llinitparam.h" #include "lltexture.h" extern const LLColor4 UI_VERTEX_COLOR; @@ -44,6 +45,12 @@ extern const LLColor4 UI_VERTEX_COLOR; class LLUIImage : public LLRefCount { public: + enum EScaleStyle + { + SCALE_INNER, + SCALE_OUTER + }; + typedef boost::signals2::signal image_loaded_signal_t; LLUIImage(const std::string& name, LLPointer image); @@ -51,6 +58,7 @@ class LLUIImage : public LLRefCount void setClipRegion(const LLRectf& region); void setScaleRegion(const LLRectf& region); + void setScaleStyle(EScaleStyle style); LLPointer getImage() { return mImage; } const LLPointer& getImage() const { return mImage; } @@ -66,7 +74,9 @@ class LLUIImage : public LLRefCount void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const; void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); } void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); } - + + void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color); + const std::string& getName() const { return mName; } virtual S32 getWidth() const; @@ -83,14 +93,43 @@ class LLUIImage : public LLRefCount protected: image_loaded_signal_t* mImageLoaded; - std::string mName; - LLRectf mScaleRegion; - LLRectf mClipRegion; - LLPointer mImage; - BOOL mUniformScaling; - BOOL mNoClip; + std::string mName; + LLRectf mScaleRegion; + LLRectf mClipRegion; + LLPointer mImage; + EScaleStyle mScaleStyle; }; +namespace LLInitParam +{ + template<> + class ParamValue + : public CustomParamValue + { + typedef boost::add_reference::type>::type T_const_ref; + typedef CustomParamValue super_t; + public: + Optional name; + + ParamValue(LLUIImage* const& image = NULL) + : super_t(image) + { + updateBlockFromValue(false); + addSynonym(name, "name"); + } + + void updateValueFromBlock(); + void updateBlockFromValue(bool make_block_authoritative); + }; + + // Need custom comparison function for our test app, which only loads + // LLUIImage* as NULL. + template<> + struct ParamCompare + { + static bool equals(LLUIImage* const &a, LLUIImage* const &b); + }; +} typedef LLPointer LLUIImagePtr; #endif diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1d02fa44a6..f766af31b8 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -74,10 +74,10 @@ U32 vbo_block_size(U32 size) U32 vbo_block_index(U32 size) { - return vbo_block_size(size)/LL_VBO_BLOCK_SIZE; + return ((vbo_block_size(size)-1)/LL_VBO_BLOCK_SIZE); } -const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE); +const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE)+1; //============================================================================ @@ -88,16 +88,16 @@ LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_A LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB); LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB); -U32 LLVBOPool::sBytesPooled = 0; -U32 LLVBOPool::sIndexBytesPooled = 0; +U64 LLVBOPool::sBytesPooled = 0; +U64 LLVBOPool::sIndexBytesPooled = 0; +std::vector LLVBOPool::sPendingDeletions; -std::list LLVertexBuffer::sAvailableVAOName; +std::vector LLVertexBuffer::sAvailableVAOName; U32 LLVertexBuffer::sCurVAOName = 1; -U32 LLVertexBuffer::sAllocatedIndexBytes = 0; +U64 LLVertexBuffer::sAllocatedIndexBytes = 0; U32 LLVertexBuffer::sIndexCount = 0; -LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL; U32 LLVertexBuffer::sBindCount = 0; U32 LLVertexBuffer::sSetCount = 0; S32 LLVertexBuffer::sCount = 0; @@ -111,19 +111,83 @@ U32 LLVertexBuffer::sGLRenderIndices = 0; U32 LLVertexBuffer::sLastMask = 0; bool LLVertexBuffer::sVBOActive = false; bool LLVertexBuffer::sIBOActive = false; -U32 LLVertexBuffer::sAllocatedBytes = 0; +U64 LLVertexBuffer::sAllocatedBytes = 0; U32 LLVertexBuffer::sVertexCount = 0; bool LLVertexBuffer::sMapped = false; bool LLVertexBuffer::sUseStreamDraw = true; bool LLVertexBuffer::sUseVAO = false; bool LLVertexBuffer::sPreferStreamDraw = false; +LLVertexBuffer* LLVertexBuffer::sUtilityBuffer = nullptr; +static std::vector sActiveBufferNames; +static std::vector sDeletedBufferNames; + +/*void validate_add_buffer(U32 name) +{ + auto found = std::find(sActiveBufferNames.begin(), sActiveBufferNames.end(), name); + if (found != sActiveBufferNames.end()) + { + LL_ERRS() << "Allocating allocated buffer name " << name << LL_ENDL; + } + else + { + //LL_INFOS() << "Allocated buffer name " << name << LL_ENDL; + sActiveBufferNames.push_back(name); + } +} + +void validate_del_buffer(U32 name) +{ + auto found = std::find(sActiveBufferNames.begin(), sActiveBufferNames.end(), name); + if (found == sActiveBufferNames.end()) + { + if (std::find(sDeletedBufferNames.begin(), sDeletedBufferNames.end(), name) == sDeletedBufferNames.end()) + { + LL_ERRS() << "Deleting unknown buffer name " << name << LL_ENDL; + } + else + { + LL_ERRS() << "Deleting deleted buffer name " << name << LL_ENDL; + } + } + else + { + //LL_INFOS() << "Deleted buffer name " << name << LL_ENDL; + sActiveBufferNames.erase(found); + sDeletedBufferNames.push_back(name); + } +} + +void validate_bind_buffer(U32 name) +{ + auto found = std::find(sActiveBufferNames.begin(), sActiveBufferNames.end(), name); + if (found == sActiveBufferNames.end()) + { + if (std::find(sDeletedBufferNames.begin(), sDeletedBufferNames.end(), name) == sDeletedBufferNames.end()) + { + LL_ERRS() << "Binding unknown buffer name " << name << LL_ENDL; + } + else + { + LL_ERRS() << "Binding deleted buffer name " << name << LL_ENDL; + } + } +} + +void clean_validate_buffers() +{ + LL_INFOS() << "Clearing active buffer names. Count " << sActiveBufferNames.size() << LL_ENDL; + sActiveBufferNames.clear(); + LL_INFOS() << "Clearing deleted buffer names. Count " << sDeletedBufferNames.size() << LL_ENDL; + sDeletedBufferNames.clear(); +}*/ U32 LLVBOPool::genBuffer() { U32 ret = 0; glGenBuffersARB(1, &ret); + //validate_add_buffer(ret); return ret; } @@ -132,13 +196,20 @@ void LLVBOPool::deleteBuffer(U32 name) { if (gGLManager.mInited) { - LLVertexBuffer::unbind(); + //LLVertexBuffer::unbind(); - glBindBufferARB(mType, name); - glBufferDataARB(mType, 0, NULL, mUsage); - glBindBufferARB(mType, 0); + //validate_bind_buffer(name); + //glBindBufferARB(mType, name); + //glBufferDataARB(mType, 0, nullptr, mUsage); + //glBindBufferARB(mType, 0); - glDeleteBuffersARB(1, &name); + //validate_del_buffer(name); + if (LLVertexBuffer::sGLRenderBuffer == name) { + //LLVertexBuffer::sGLRenderBuffer = 0; + LLVertexBuffer::unbind(); + } + sPendingDeletions.emplace_back(name); + //glDeleteBuffersARB(1, &name); } } @@ -150,11 +221,11 @@ LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType) std::fill(mMissCount.begin(), mMissCount.end(), 0); } -volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) +volatile U8* LLVBOPool::allocate(U32& name, U32 size, U32 seed) { llassert(vbo_block_size(size) == size); - volatile U8* ret = NULL; + volatile U8* ret = nullptr; U32 i = vbo_block_index(size); @@ -163,16 +234,17 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) mFreeList.resize(i+1); } - if (mFreeList[i].empty() || for_seed) + if (mFreeList[i].empty() || seed) { //make a new buffer - name = genBuffer(); - + name = seed > 0 ? seed : genBuffer(); + + //validate_bind_buffer(name); glBindBufferARB(mType, name); - if (!for_seed && i < LL_VBO_POOL_SEED_COUNT) + if (!seed && i < LL_VBO_POOL_SEED_COUNT) { //record this miss - mMissCount[i]++; + mMissCount[i]++; } if (mType == GL_ARRAY_BUFFER_ARB) @@ -186,17 +258,20 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) { - glBufferDataARB(mType, size, 0, mUsage); - ret = (U8*) ll_aligned_malloc(size, 64); + glBufferDataARB(mType, size, nullptr, mUsage); + ret = (U8*)ll_aligned_malloc<64>(size); } else { //always use a true hint of static draw when allocating non-client-backed buffers - glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB); + glBufferDataARB(mType, size, nullptr, GL_STATIC_DRAW_ARB); } - glBindBufferARB(mType, 0); + if (!seed) + { + glBindBufferARB(mType, 0); + } - if (for_seed) + if (seed) { //put into pool for future use llassert(mFreeList.size() > i); @@ -206,11 +281,11 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) if (mType == GL_ARRAY_BUFFER_ARB) { - sBytesPooled += size; - } - else - { - sIndexBytesPooled += size; + sBytesPooled += size; + } + else + { + sIndexBytesPooled += size; } mFreeList[i].push_back(rec); } @@ -240,7 +315,7 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size) llassert(vbo_block_size(size) == size); deleteBuffer(name); - ll_aligned_free((U8*) buffer); + ll_aligned_free<64>((U8*) buffer); if (mType == GL_ARRAY_BUFFER_ARB) { @@ -261,22 +336,45 @@ void LLVBOPool::seedPool() mFreeList.resize(LL_VBO_POOL_SEED_COUNT); } + static std::vector< U32 > sizes; for (U32 i = 0; i < LL_VBO_POOL_SEED_COUNT; i++) { if (mMissCount[i] > mFreeList[i].size()) - { - U32 size = i*LL_VBO_BLOCK_SIZE; - + { + U32 size = i * LL_VBO_BLOCK_SIZE + LL_VBO_BLOCK_SIZE; + S32 count = mMissCount[i] - mFreeList[i].size(); for (S32 j = 0; j < count; ++j) { - allocate(dummy_name, size, true); + sizes.push_back(size); } } } -} + if (!sizes.empty()) + { + const U32 len = sizes.size(); + U32* names = new U32[len]; + glGenBuffersARB(len, names); + for (U32 i = 0; i < len; ++i) + { + allocate(dummy_name, sizes[i], names[i]); + } + delete[] names; + glBindBufferARB(mType, 0); + } + sizes.clear(); +} + +void LLVBOPool::deleteReleasedBuffers() +{ + if (!sPendingDeletions.empty()) + { + glDeleteBuffersARB(sPendingDeletions.size(), sPendingDeletions.data()); + sPendingDeletions.clear(); + } +} void LLVBOPool::cleanup() { @@ -294,7 +392,7 @@ void LLVBOPool::cleanup() if (r.mClientData) { - ll_aligned_free((void*) r.mClientData); + ll_aligned_free<64>((void*) r.mClientData); } l.pop_front(); @@ -316,6 +414,7 @@ void LLVBOPool::cleanup() //reset miss counts std::fill(mMissCount.begin(), mMissCount.end(), 0); + deleteReleasedBuffers(); } @@ -371,7 +470,6 @@ U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] = GL_POINTS, GL_LINES, GL_LINE_STRIP, - GL_QUADS, GL_LINE_LOOP, }; @@ -382,8 +480,8 @@ U32 LLVertexBuffer::getVAOName() if (!sAvailableVAOName.empty()) { - ret = sAvailableVAOName.front(); - sAvailableVAOName.pop_front(); + ret = sAvailableVAOName.back(); + sAvailableVAOName.pop_back(); } else { @@ -450,7 +548,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) else { - GLenum array[] = + static const GLenum array[] = { GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, @@ -458,7 +556,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) GL_COLOR_ARRAY, }; - GLenum mask[] = + static const GLenum mask[] = { MAP_VERTEX, MAP_NORMAL, @@ -565,77 +663,96 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector& pos, con gGL.syncMatrices(); U32 count = pos.size(); - + llassert(norm.size() >= pos.size()); llassert(count > 0); - if( count == 0 ) + if (count == 0) { LL_WARNS() << "Called drawArrays with 0 vertices" << LL_ENDL; return; } - if( norm.size() < pos.size() ) + if (norm.size() < pos.size()) { LL_WARNS() << "Called drawArrays with #" << norm.size() << " normals and #" << pos.size() << " vertices" << LL_ENDL; return; } - unbind(); - - setupClientArrays(MAP_VERTEX | MAP_NORMAL); - - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - - if (shader) + if (!sUtilityBuffer) { - glVertexAttribPointerARB(TYPE_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, pos[0].mV); - glVertexAttribPointerARB(TYPE_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, norm[0].mV); + sUtilityBuffer = new LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD0, GL_STREAM_DRAW); + sUtilityBuffer->allocateBuffer(count, count, true); } - else + if (sUtilityBuffer->getNumVerts() < (S32)count) + { + sUtilityBuffer->resizeBuffer(count, count); + } + + LLStrider vertex_strider; + LLStrider normal_strider; + sUtilityBuffer->getVertexStrider(vertex_strider); + sUtilityBuffer->getNormalStrider(normal_strider); + for (U32 i = 0; i < count; ++i) { - glVertexPointer(3, GL_FLOAT, 0, pos[0].mV); - glNormalPointer(GL_FLOAT, 0, norm[0].mV); + *(vertex_strider++) = pos[i]; + *(normal_strider++) = norm[i]; } - glDrawArrays(sGLMode[mode], 0, count); + sUtilityBuffer->setBuffer(MAP_VERTEX | MAP_NORMAL); + sUtilityBuffer->drawArrays(mode, 0, pos.size()); } //static -void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp) +void LLVertexBuffer::drawElements(U32 mode, const S32 num_vertices, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp) { llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - gGL.syncMatrices(); + if (num_vertices <= 0) + { + LL_WARNS() << "Called drawElements with 0 vertices" << LL_ENDL; + return; + } - U32 mask = LLVertexBuffer::MAP_VERTEX; - if (tc) + if (num_indices <= 0) { - mask = mask | LLVertexBuffer::MAP_TEXCOORD0; + LL_WARNS() << "Called drawElements with 0 indices" << LL_ENDL; + return; } - unbind(); - - setupClientArrays(mask); + gGL.syncMatrices(); - if (LLGLSLShader::sNoFixedFunction) + if (!sUtilityBuffer) { - glVertexAttribPointerARB(TYPE_VERTEX, 3, GL_FLOAT, GL_FALSE, 16, pos); - if (tc) - { - glVertexAttribPointerARB(TYPE_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, 0, tc); - } + sUtilityBuffer = new LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD0, GL_STREAM_DRAW); + sUtilityBuffer->allocateBuffer(num_vertices, num_indices, true); } - else + if (sUtilityBuffer->getNumVerts() < num_vertices || sUtilityBuffer->getNumIndices() < num_indices) { - glVertexPointer(3, GL_FLOAT, 16, pos); - if (tc) - { - glTexCoordPointer(2, GL_FLOAT, 0, tc); - } + sUtilityBuffer->resizeBuffer(llmax(sUtilityBuffer->getNumVerts(), num_vertices), llmax(sUtilityBuffer->getNumIndices(), num_indices)); } - glDrawElements(sGLMode[mode], num_indices, GL_UNSIGNED_SHORT, indicesp); + U32 mask = LLVertexBuffer::MAP_VERTEX; + + LLStrider index_strider; + LLStrider vertex_strider; + sUtilityBuffer->getIndexStrider(index_strider); + sUtilityBuffer->getVertexStrider(vertex_strider); + const S32 index_size = ((num_indices * sizeof(U16)) + 0xF) & ~0xF; + const S32 vertex_size = ((num_vertices * 4 * sizeof(F32)) + 0xF) & ~0xF; + LLVector4a::memcpyNonAliased16((F32*)index_strider.get(), (F32*)indicesp, index_size); + LLVector4a::memcpyNonAliased16((F32*)vertex_strider.get(), (F32*)pos, vertex_size); + if (tc) + { + mask = mask | LLVertexBuffer::MAP_TEXCOORD0; + LLStrider tc_strider; + sUtilityBuffer->getTexCoord0Strider(tc_strider); + const S32 tc_size = ((num_vertices * 2 * sizeof(F32)) + 0xF) & ~0xF; + LLVector4a::memcpyNonAliased16((F32*)tc_strider.get(), (F32*)tc, tc_size); + } + + sUtilityBuffer->setBuffer(mask); + sUtilityBuffer->draw(mode, num_indices, 0); } void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const @@ -787,7 +904,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const placeFence(); } -static LLFastTimer::DeclareTimer FTM_GL_DRAW_ARRAYS("GL draw arrays"); +static LLTrace::BlockTimerStatHandle FTM_GL_DRAW_ARRAYS("GL draw arrays"); void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); @@ -823,7 +940,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const } { - LLFastTimer t2(FTM_GL_DRAW_ARRAYS); + //LL_RECORD_BLOCK_TIME(FTM_GL_DRAW_ARRAYS); stop_glerror(); glDrawArrays(sGLMode[mode], first, count); } @@ -835,12 +952,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping) { sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject; - sDisableVBOMapping = sEnableVBOs;// && no_vbo_mapping; //Temporary workaround for vbo mapping being straight up broken - - if (!sPrivatePoolp) - { - sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC); - } + sDisableVBOMapping = sEnableVBOs;// && no_vbo_mapping; } //static @@ -882,12 +994,17 @@ void LLVertexBuffer::cleanupClass() sDynamicIBOPool.cleanup(); sStreamVBOPool.cleanup(); sDynamicVBOPool.cleanup(); + //clean_validate_buffers(); - if(sPrivatePoolp) + if (!sAvailableVAOName.empty()) { - LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp); - sPrivatePoolp = NULL; + glDeleteVertexArrays(sAvailableVAOName.size(), sAvailableVAOName.data()); + sAvailableVAOName.clear(); } + sLastMask = 0; + + delete sUtilityBuffer; + sUtilityBuffer = nullptr; } //---------------------------------------------------------------------------- @@ -939,14 +1056,16 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mAlignedOffset(0), mAlignedIndexOffset(0), mSize(0), + mResidentSize(0), mIndicesSize(0), + mResidentIndicesSize(0), mTypeMask(typemask), mUsage(LLVertexBuffer::determineUsage(usage)), mGLBuffer(0), mGLIndices(0), mGLArray(0), - mMappedData(NULL), - mMappedIndexData(NULL), + mMappedData(nullptr), + mMappedIndexData(nullptr), mMappedDataUsingVBOs(false), mMappedIndexDataUsingVBOs(false), mVertexLocked(false), @@ -954,7 +1073,7 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mFinal(false), mEmpty(true), mMappable(false), - mFence(NULL) + mFence(nullptr) { mMappable = (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping); @@ -987,7 +1106,7 @@ S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_verti offsets[TYPE_TEXTURE_INDEX] = offsets[TYPE_VERTEX] + 12; - return offset+16; + return offset; } //static @@ -1032,7 +1151,7 @@ LLVertexBuffer::~LLVertexBuffer() delete mFence; } - mFence = NULL; + mFence = nullptr; sVertexCount -= mNumVerts; sIndexCount -= mNumIndices; @@ -1078,6 +1197,10 @@ void LLVertexBuffer::genBuffer(U32 size) { mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize); } + if ((sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) && !mMappedData) + { + LL_ERRS() << "mMappedData allocation failedd" << LL_ENDL; + } sGLCount++; } @@ -1094,6 +1217,10 @@ void LLVertexBuffer::genIndices(U32 size) { mMappedIndexData = sDynamicIBOPool.allocate(mGLIndices, mIndicesSize); } + if ((sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) && !mMappedIndexData) + { + LL_ERRS() << "mMappedIndexData allocation failedd" << LL_ENDL; + } sGLCount++; } @@ -1110,7 +1237,7 @@ void LLVertexBuffer::releaseBuffer() } mGLBuffer = 0; - mMappedData = NULL; + mMappedData = nullptr; sGLCount--; } @@ -1127,7 +1254,7 @@ void LLVertexBuffer::releaseIndices() } mGLIndices = 0; - mMappedIndexData = NULL; + mMappedIndexData = nullptr; sGLCount--; } @@ -1145,6 +1272,7 @@ void LLVertexBuffer::createGLBuffer(U32 size) } mEmpty = true; + mResidentSize = size; mMappedDataUsingVBOs = useVBOs(); @@ -1156,7 +1284,7 @@ void LLVertexBuffer::createGLBuffer(U32 size) { static int gl_buffer_idx = 0; mGLBuffer = ++gl_buffer_idx; - mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); + mMappedData = (U8*)ll_aligned_malloc_16(size); mSize = size; } } @@ -1174,6 +1302,7 @@ void LLVertexBuffer::createGLIndices(U32 size) } mEmpty = true; + mResidentIndicesSize = size; //pad by 16 bytes for aligned copies size += 16; @@ -1188,7 +1317,7 @@ void LLVertexBuffer::createGLIndices(U32 size) } else { - mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); + mMappedIndexData = (U8*)ll_aligned_malloc_16(size); static int gl_buffer_idx = 0; mGLIndices = ++gl_buffer_idx; mIndicesSize = size; @@ -1205,8 +1334,8 @@ void LLVertexBuffer::destroyGLBuffer() } else { - FREE_MEM(sPrivatePoolp, (void*) mMappedData); - mMappedData = NULL; + ll_aligned_free_16((void*) mMappedData); + mMappedData = nullptr; mEmpty = true; } } @@ -1225,8 +1354,8 @@ void LLVertexBuffer::destroyGLIndices() } else { - FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData); - mMappedIndexData = NULL; + ll_aligned_free_16((void*) mMappedIndexData); + mMappedIndexData = nullptr; mEmpty = true; } } @@ -1301,7 +1430,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) } } -static LLFastTimer::DeclareTimer FTM_SETUP_VERTEX_ARRAY("Setup VAO"); +static LLTrace::BlockTimerStatHandle FTM_SETUP_VERTEX_ARRAY("Setup VAO"); void LLVertexBuffer::setupVertexArray() { @@ -1310,7 +1439,7 @@ void LLVertexBuffer::setupVertexArray() return; } - LLFastTimer t(FTM_SETUP_VERTEX_ARRAY); + //LL_RECORD_BLOCK_TIME(FTM_SETUP_VERTEX_ARRAY); #if GL_ARB_vertex_array_object glBindVertexArray(mGLArray); #endif @@ -1384,8 +1513,8 @@ void LLVertexBuffer::setupVertexArray() GL_FALSE, //TYPE_TEXTURE_INDEX }; - bindGLBuffer(true); - bindGLIndices(true); + bindGLBuffer(); + bindGLIndices(); for (U32 i = 0; i < TYPE_MAX; ++i) { @@ -1399,13 +1528,13 @@ void LLVertexBuffer::setupVertexArray() //glVertexattribIPointer requires GLSL 1.30 or later if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) { - glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], reinterpret_cast(mOffsets[i])); + glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], reinterpret_cast(static_cast(mOffsets[i]))); } #endif } else { - glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], reinterpret_cast(mOffsets[i])); + glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], reinterpret_cast(static_cast(mOffsets[i]))); } } else @@ -1447,31 +1576,31 @@ bool LLVertexBuffer::useVBOs() const //---------------------------------------------------------------------------- -bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) +bool expand_region(LLVertexBuffer::MappedRegion& region, U32 offset, U32 length) { - S32 end = index+count; - S32 region_end = region.mIndex+region.mCount; + U32 end = offset + length; + U32 region_end = region.mOffset + region.mLength; - if (end < region.mIndex || - index > region_end) + if (end < region.mOffset || + offset > region_end) { //gap exists, do not merge return false; } - S32 new_end = llmax(end, region_end); - S32 new_index = llmin(index, region.mIndex); - region.mIndex = new_index; - region.mCount = new_end-new_index; + U32 new_end = llmax(end, region_end); + U32 new_offset = llmin(offset, region.mOffset); + region.mOffset = new_offset; + region.mLength = new_end-new_offset; return true; } -static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER_RANGE("VBO Map Range"); -static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER("VBO Map"); +static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_BUFFER_RANGE("VBO Map Range"); +static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_BUFFER("VBO Map"); // Map for data access volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) { - bindGLBuffer(true); + bindGLBuffer(); if (mFinal) { LL_ERRS() << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << LL_ENDL; @@ -1490,26 +1619,41 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo count = mNumVerts-index; } - bool mapped = false; - //see if range is already mapped - for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) + if (getSize() > LL_VBO_BLOCK_SIZE) { - MappedRegion& region = mMappedVertexRegions[i]; - if (region.mType == type) + U32 offset = mOffsets[type] + sTypeSize[type] * index; + U32 length = sTypeSize[type] * count; + + bool mapped = false; + //see if range is already mapped + for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) { - if (expand_region(region, index, count)) + MappedRegion& region = mMappedVertexRegions[i]; + if (expand_region(region, offset, length)) { + ++i; + while (MappedRegion* pNext = i < mMappedVertexRegions.size() ? &mMappedVertexRegions[i] : nullptr) + { + if (expand_region(region, pNext->mOffset, pNext->mLength)) + { + mMappedVertexRegions.erase(mMappedVertexRegions.begin() + i); + } + else + { + ++i; + } + } mapped = true; break; } } - } - if (!mapped) - { - //not already mapped, map new region - MappedRegion region(type, mMappable && map_range ? -1 : index, count); - mMappedVertexRegions.push_back(region); + if (!mapped) + { + //not already mapped, map new region + MappedRegion region(type, mMappable && map_range ? -1 : offset, length); + mMappedVertexRegions.push_back(region); + } } } @@ -1530,14 +1674,14 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo } else { - volatile U8* src = NULL; + volatile U8* src = nullptr; waitFence(); if (gGLManager.mHasMapBufferRange) { if (map_range) { #ifdef GL_ARB_map_buffer_range - LLFastTimer t(FTM_VBO_MAP_BUFFER_RANGE); + //LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_BUFFER_RANGE); S32 offset = mOffsets[type] + sTypeSize[type]*index; S32 length = (sTypeSize[type]*count+0xF) & ~0xF; src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, @@ -1561,7 +1705,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo } } - LLFastTimer t(FTM_VBO_MAP_BUFFER); + //LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_BUFFER); src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); @@ -1645,12 +1789,12 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo } -static LLFastTimer::DeclareTimer FTM_VBO_MAP_INDEX_RANGE("IBO Map Range"); -static LLFastTimer::DeclareTimer FTM_VBO_MAP_INDEX("IBO Map"); +static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_INDEX_RANGE("IBO Map Range"); +static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_INDEX("IBO Map"); volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) { - bindGLIndices(true); + bindGLIndices(); if (mFinal) { LL_ERRS() << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << LL_ENDL; @@ -1669,23 +1813,41 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range count = mNumIndices-index; } - bool mapped = false; - //see if range is already mapped - for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) + if (getIndicesSize() > LL_VBO_BLOCK_SIZE) { - MappedRegion& region = mMappedIndexRegions[i]; - if (expand_region(region, index, count)) + U32 offset = sizeof(U16) * index; + U32 length = sizeof(U16) * count; + + bool mapped = false; + //see if range is already mapped + for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) { - mapped = true; - break; + MappedRegion& region = mMappedIndexRegions[i]; + if (expand_region(region, offset, length)) + { + ++i; + while (MappedRegion* pNext = i < mMappedIndexRegions.size() ? &mMappedIndexRegions[i] : nullptr) + { + if (expand_region(region, pNext->mOffset, pNext->mLength)) + { + mMappedIndexRegions.erase(mMappedIndexRegions.begin() + i); + } + else + { + ++i; + } + } + mapped = true; + break; + } } - } - if (!mapped) - { - //not already mapped, map new region - MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : index, count); - mMappedIndexRegions.push_back(region); + if (!mapped) + { + //not already mapped, map new region + MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : offset, length); + mMappedIndexRegions.push_back(region); + } } } @@ -1694,6 +1856,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range LL_ERRS() << "Attempted to map a specific range of a buffer that was already mapped." << LL_ENDL; } + bool was_locked = mIndexLocked; if (!mIndexLocked) { mIndexLocked = true; @@ -1717,14 +1880,14 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range } else { - volatile U8* src = NULL; + volatile U8* src = nullptr; waitFence(); if (gGLManager.mHasMapBufferRange) { if (map_range) { #ifdef GL_ARB_map_buffer_range - LLFastTimer t(FTM_VBO_MAP_INDEX_RANGE); + //LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_INDEX_RANGE); S32 offset = sizeof(U16)*index; S32 length = sizeof(U16)*count; src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, @@ -1736,7 +1899,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range else { #ifdef GL_ARB_map_buffer_range - LLFastTimer t(FTM_VBO_MAP_INDEX); + //LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_INDEX); src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); @@ -1758,7 +1921,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range } else { - LLFastTimer t(FTM_VBO_MAP_INDEX); + //LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_INDEX); map_range = false; src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } @@ -1788,6 +1951,10 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range LL_ERRS() << "glMapBuffer returned NULL (no index data)" << LL_ENDL; } + else if (was_locked) + { + LL_ERRS() << "mIndexLocked was true but no Index data allocated" << LL_ENDL; + } else { LL_ERRS() << "memory allocation for Index data failed. " << LL_ENDL; @@ -1809,12 +1976,12 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range } } -static LLFastTimer::DeclareTimer FTM_VBO_UNMAP("VBO Unmap"); -static LLFastTimer::DeclareTimer FTM_VBO_FLUSH_RANGE("Flush VBO Range"); +static LLTrace::BlockTimerStatHandle FTM_VBO_UNMAP("VBO Unmap"); +static LLTrace::BlockTimerStatHandle FTM_VBO_FLUSH_RANGE("Flush VBO Range"); -static LLFastTimer::DeclareTimer FTM_IBO_UNMAP("IBO Unmap"); -static LLFastTimer::DeclareTimer FTM_IBO_FLUSH_RANGE("Flush IBO Range"); +static LLTrace::BlockTimerStatHandle FTM_IBO_UNMAP("IBO Unmap"); +static LLTrace::BlockTimerStatHandle FTM_IBO_FLUSH_RANGE("Flush IBO Range"); void LLVertexBuffer::unmapBuffer() { @@ -1827,8 +1994,8 @@ void LLVertexBuffer::unmapBuffer() if (mMappedData && mVertexLocked) { - LLFastTimer t(FTM_VBO_UNMAP); - bindGLBuffer(true); + //LL_RECORD_BLOCK_TIME(FTM_VBO_UNMAP); + bindGLBuffer(); updated_all = mIndexLocked; //both vertex and index buffers done updating if(!mMappable) @@ -1839,9 +2006,18 @@ void LLVertexBuffer::unmapBuffer() for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) { const MappedRegion& region = mMappedVertexRegions[i]; - S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0; - S32 length = sTypeSize[region.mType]*region.mCount; - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedData+offset); + U32 offset = region.mOffset; + U32 length = region.mLength; + if ((mResidentSize - length) <= LL_VBO_BLOCK_SIZE * 2 || (offset == 0 && length >= mResidentSize)) + { + glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), nullptr, mUsage); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (U8*)mMappedData); + break; + } + else + { + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, (U8*)mMappedData + offset); + } stop_glerror(); } @@ -1850,7 +2026,7 @@ void LLVertexBuffer::unmapBuffer() else { stop_glerror(); - glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), NULL, mUsage); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), nullptr, mUsage); // glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (U8*) mMappedData); stop_glerror(); } @@ -1865,11 +2041,11 @@ void LLVertexBuffer::unmapBuffer() for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) { const MappedRegion& region = mMappedVertexRegions[i]; - S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0; - S32 length = sTypeSize[region.mType]*region.mCount; + U32 offset = region.mOffset; + U32 length = region.mLength; if (gGLManager.mHasMapBufferRange) { - LLFastTimer t(FTM_VBO_FLUSH_RANGE); + //LL_RECORD_BLOCK_TIME(FTM_VBO_FLUSH_RANGE); #ifdef GL_ARB_map_buffer_range glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length); #endif @@ -1888,7 +2064,7 @@ void LLVertexBuffer::unmapBuffer() glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); stop_glerror(); - mMappedData = NULL; + mMappedData = nullptr; } mVertexLocked = false; @@ -1897,7 +2073,7 @@ void LLVertexBuffer::unmapBuffer() if (mMappedIndexData && mIndexLocked) { - LLFastTimer t(FTM_IBO_UNMAP); + //LL_RECORD_BLOCK_TIME(FTM_IBO_UNMAP); bindGLIndices(); if(!mMappable) { @@ -1906,9 +2082,18 @@ void LLVertexBuffer::unmapBuffer() for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) { const MappedRegion& region = mMappedIndexRegions[i]; - S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0; - S32 length = sizeof(U16)*region.mCount; - glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedIndexData+offset); + U32 offset = region.mOffset; + U32 length = region.mLength; + if ((mResidentIndicesSize - length) <= LL_VBO_BLOCK_SIZE * 2 || (offset == 0 && length >= mResidentIndicesSize)) + { + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), nullptr, mUsage); // + glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), (U8*)mMappedIndexData); + break; + } + else + { + glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, (U8*)mMappedIndexData + offset); + } stop_glerror(); } @@ -1917,7 +2102,7 @@ void LLVertexBuffer::unmapBuffer() else { stop_glerror(); - glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), NULL, mUsage); + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), nullptr, mUsage); // glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), (U8*) mMappedIndexData); stop_glerror(); } @@ -1931,11 +2116,11 @@ void LLVertexBuffer::unmapBuffer() for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) { const MappedRegion& region = mMappedIndexRegions[i]; - S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0; - S32 length = sizeof(U16)*region.mCount; + U32 offset = region.mOffset; + U32 length = region.mLength; if (gGLManager.mHasMapBufferRange) { - LLFastTimer t(FTM_IBO_FLUSH_RANGE); + //LL_RECORD_BLOCK_TIME(FTM_IBO_FLUSH_RANGE); #ifdef GL_ARB_map_buffer_range glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length); #endif @@ -1956,7 +2141,7 @@ void LLVertexBuffer::unmapBuffer() glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); stop_glerror(); - mMappedIndexData = NULL; + mMappedIndexData = nullptr; } mIndexLocked = false; @@ -1971,34 +2156,21 @@ void LLVertexBuffer::unmapBuffer() //---------------------------------------------------------------------------- -template struct VertexBufferStrider +template +struct VertexBufferStrider { typedef LLStrider strider_t; static bool get(LLVertexBuffer& vbo, strider_t& strider, S32 index, S32 count, bool map_range) { - if (type == LLVertexBuffer::TYPE_INDEX) - { - volatile U8* ptr = vbo.mapIndexBuffer(index, count, map_range); - - if (ptr == NULL) - { - LL_WARNS() << "mapIndexBuffer failed!" << LL_ENDL; - return false; - } - - strider = (T*)ptr; - strider.setStride(0); - return true; - } - else if (vbo.hasDataType(type)) + if (vbo.hasDataType(type)) { S32 stride = LLVertexBuffer::sTypeSize[type]; volatile U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range); - if (ptr == NULL) + if (ptr == nullptr) { LL_WARNS() << "mapVertexBuffer failed!" << LL_ENDL; return false; @@ -2016,6 +2188,28 @@ template struct VertexBufferStrider } }; +template +struct VertexBufferStrider +{ + typedef LLStrider strider_t; + static bool get(LLVertexBuffer& vbo, + strider_t& strider, + S32 index, S32 count, bool map_range) + { + volatile U8* ptr = vbo.mapIndexBuffer(index, count, map_range); + + if (ptr == nullptr) + { + LL_WARNS() << "mapIndexBuffer failed!" << LL_ENDL; + return false; + } + + strider = (T*) ptr; + strider.setStride(0); + return true; + } +}; + bool LLVertexBuffer::getVertexStrider(LLStrider& strider, S32 index, S32 count, bool map_range) { return VertexBufferStrider::get(*this, strider, index, count, map_range); @@ -2081,13 +2275,13 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, S32 i //---------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_BIND_GL_ARRAY("Bind Array"); +static LLTrace::BlockTimerStatHandle FTM_BIND_GL_ARRAY("Bind Array"); bool LLVertexBuffer::bindGLArray() { if (mGLArray && sGLRenderArray != mGLArray) { { - LLFastTimer t(FTM_BIND_GL_ARRAY); + //LL_RECORD_BLOCK_TIME(FTM_BIND_GL_ARRAY); #if GL_ARB_vertex_array_object glBindVertexArray(mGLArray); #endif @@ -2104,22 +2298,28 @@ bool LLVertexBuffer::bindGLArray() return false; } -static LLFastTimer::DeclareTimer FTM_BIND_GL_BUFFER("Bind Buffer"); +static LLTrace::BlockTimerStatHandle FTM_BIND_GL_BUFFER("Bind Buffer"); bool LLVertexBuffer::bindGLBuffer(bool force_bind) { + //stop_glerror(); bindGLArray(); + //stop_glerror(); bool ret = false; if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive)))) { - //LLFastTimer t(FTM_BIND_GL_BUFFER); + //LL_RECORD_BLOCK_TIME(FTM_BIND_GL_BUFFER); /*if (sMapped) { LL_ERRS() << "VBO bound while another VBO mapped!" << LL_ENDL; }*/ + //stop_glerror(); + + //validate_bind_buffer(mGLBuffer); glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); + //stop_glerror(); sGLRenderBuffer = mGLBuffer; sBindCount++; sVBOActive = true; @@ -2136,7 +2336,7 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind) return ret; } -static LLFastTimer::DeclareTimer FTM_BIND_GL_INDICES("Bind Indices"); +static LLTrace::BlockTimerStatHandle FTM_BIND_GL_INDICES("Bind Indices"); bool LLVertexBuffer::bindGLIndices(bool force_bind) { @@ -2145,11 +2345,12 @@ bool LLVertexBuffer::bindGLIndices(bool force_bind) bool ret = false; if (useVBOs() && (force_bind || (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive)))) { - LLFastTimer t(FTM_BIND_GL_INDICES); + //LL_RECORD_BLOCK_TIME(FTM_BIND_GL_INDICES); /*if (sMapped) { LL_ERRS() << "VBO bound while another VBO mapped!" << LL_ENDL; }*/ + //validate_bind_buffer(mGLIndices); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices); sGLRenderIndices = mGLIndices; stop_glerror(); @@ -2169,16 +2370,6 @@ void LLVertexBuffer::flush() } } -// bind for transform feedback (quick 'n dirty) -void LLVertexBuffer::bindForFeedback(U32 channel, U32 type, U32 index, U32 count) -{ -#ifdef GL_TRANSFORM_FEEDBACK_BUFFER - U32 offset = mOffsets[type] + sTypeSize[type]*index; - U32 size= (sTypeSize[type]*count); - glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, channel, mGLBuffer, offset, size); -#endif -} - // Set for rendering void LLVertexBuffer::setBuffer(U32 data_mask) { @@ -2476,8 +2667,8 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) llglassertok(); } -LLVertexBuffer::MappedRegion::MappedRegion(S32 type, S32 index, S32 count) -: mType(type), mIndex(index), mCount(count) +LLVertexBuffer::MappedRegion::MappedRegion(S32 type, U32 offset, U32 length) +: mType(type), mOffset(offset), mLength(length) { llassert(mType == LLVertexBuffer::TYPE_INDEX || mType < LLVertexBuffer::TYPE_TEXTURE_INDEX); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 1cebd96bdb..906e62dbb1 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -54,16 +54,20 @@ class LLVBOPool { public: - static U32 sBytesPooled; - static U32 sIndexBytesPooled; - + static U64 sBytesPooled; + static U64 sIndexBytesPooled; + static std::vector sPendingDeletions; + + // Periodically call from render loop. Batches VBO deletions together in a single call. + static void deleteReleasedBuffers(); + LLVBOPool(U32 vboUsage, U32 vboType); const U32 mUsage; const U32 mType; //size MUST be a power of 2 - volatile U8* allocate(U32& name, U32 size, bool for_seed = false); + volatile U8* allocate(U32& name, U32 size, U32 seed = 0); //size MUST be the size provided to allocate that returned the given name void release(U32 name, volatile U8* buffer, U32 size); @@ -93,7 +97,6 @@ class LLVBOPool //============================================================================ // base class -class LLPrivateMemoryPool; class LLVertexBuffer : public LLRefCount { public: @@ -101,10 +104,10 @@ class LLVertexBuffer : public LLRefCount { public: S32 mType; - S32 mIndex; - S32 mCount; + U32 mOffset; + U32 mLength; - MappedRegion(S32 type, S32 index, S32 count); + MappedRegion(S32 type, U32 offset, U32 length); }; LLVertexBuffer(const LLVertexBuffer& rhs) @@ -126,7 +129,7 @@ class LLVertexBuffer : public LLRefCount static LLVBOPool sStreamIBOPool; static LLVBOPool sDynamicIBOPool; - static std::list sAvailableVAOName; + static std::vector sAvailableVAOName; static U32 sCurVAOName; static bool sUseStreamDraw; @@ -142,7 +145,7 @@ class LLVertexBuffer : public LLRefCount static void cleanupClass(); static void setupClientArrays(U32 data_mask); static void drawArrays(U32 mode, const std::vector& pos, const std::vector& norm); - static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp); + static void drawElements(U32 mode, const S32 num_vertices, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp); static void unbind(); //unbind any bound vertex buffer @@ -227,8 +230,6 @@ class LLVertexBuffer : public LLRefCount volatile U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); volatile U8* mapIndexBuffer(S32 index, S32 count, bool map_range); - void bindForFeedback(U32 channel, U32 type, U32 index, U32 count); - // set for rendering virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0 void flush(); //flush pending data to GL memory @@ -294,7 +295,9 @@ class LLVertexBuffer : public LLRefCount ptrdiff_t mAlignedOffset; ptrdiff_t mAlignedIndexOffset; S32 mSize; + U32 mResidentSize; S32 mIndicesSize; + U32 mResidentIndicesSize; U32 mTypeMask; const S32 mUsage; // GL usage @@ -327,9 +330,6 @@ class LLVertexBuffer : public LLRefCount static S32 determineUsage(S32 usage); -private: - static LLPrivateMemoryPool* sPrivatePoolp; - public: static S32 sCount; static S32 sGLCount; @@ -347,12 +347,15 @@ class LLVertexBuffer : public LLRefCount static bool sVBOActive; static bool sIBOActive; static U32 sLastMask; - static U32 sAllocatedBytes; - static U32 sAllocatedIndexBytes; + static U64 sAllocatedBytes; + static U64 sAllocatedIndexBytes; static U32 sVertexCount; static U32 sIndexCount; static U32 sBindCount; static U32 sSetCount; + +private: + static LLVertexBuffer* sUtilityBuffer; }; diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index cb9a4e4a32..3caf919eb6 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -24,6 +24,9 @@ include_directories( ) set(llui_SOURCE_FILES + lfidbearer.cpp + llaccordionctrl.cpp + llaccordionctrltab.cpp llalertdialog.cpp llbutton.cpp llcheckboxctrl.cpp @@ -34,6 +37,7 @@ set(llui_SOURCE_FILES lldraghandle.cpp lleditmenuhandler.cpp llfiltereditor.cpp + llflatlistview.cpp llfloater.cpp llflyoutbutton.cpp llfocusmgr.cpp @@ -42,6 +46,7 @@ set(llui_SOURCE_FILES llkeywords.cpp lllayoutstack.cpp lllineeditor.cpp + llloadingindicator.cpp lllocalcliprect.cpp llmenugl.cpp llmodaldialog.cpp @@ -98,6 +103,9 @@ set(llui_HEADER_FILES CMakeLists.txt ailist.h + lfidbearer.h + llaccordionctrl.h + llaccordionctrltab.h llalertdialog.h llbutton.h llcallbackmap.h @@ -109,6 +117,7 @@ set(llui_HEADER_FILES lldraghandle.h lleditmenuhandler.h llfiltereditor.h + llflatlistview.h llfloater.h llflyoutbutton.h llfocusmgr.h @@ -118,6 +127,7 @@ set(llui_HEADER_FILES llkeywords.h lllayoutstack.h lllineeditor.h + llloadingindicator.h lllocalcliprect.h llmemberlistener.h llmenugl.h diff --git a/indra/llui/ailist.h b/indra/llui/ailist.h index 14ef05f0c6..1511fef2e0 100644 --- a/indra/llui/ailist.h +++ b/indra/llui/ailist.h @@ -253,11 +253,15 @@ class AIConstListIterator { typedef AIConstListIterator _Self; typedef std::list > _Container; typedef typename _Container::iterator _Iterator; +#if LL_LINUX && GCC_VERSION <= 40899 + typedef _Iterator _ConstIterator; +#else typedef typename _Container::const_iterator _ConstIterator; +#endif typedef AIListIterator iterator; _Container const* mContainer; - _Iterator mConstIterator; // This has to be an _Iterator instead of _ConstIterator, because the compiler doesn't accept a const_iterator for erase yet (C++11 does). + _ConstIterator mConstIterator; void ref(void) { @@ -289,7 +293,7 @@ class AIConstListIterator { typedef T const& reference; AIConstListIterator(void) : mContainer(NULL) { } - AIConstListIterator(_Container const* __c, _Iterator const& __i) : mContainer(__c), mConstIterator(__i) + AIConstListIterator(_Container const* __c, _ConstIterator const& __i) : mContainer(__c), mConstIterator(__i) { llassert(mContainer); ref(); @@ -343,7 +347,7 @@ class AIConstListIterator { _Self& operator++() { - _Iterator cur = mConstIterator; + _ConstIterator cur = mConstIterator; ++cur; unref(); while(cur != mContainer->end() && cur->dead) @@ -364,7 +368,7 @@ class AIConstListIterator { _Self& operator--() { - _Iterator cur = mConstIterator; + _ConstIterator cur = mConstIterator; --cur; unref(); while(cur->dead) diff --git a/indra/llui/lfidbearer.cpp b/indra/llui/lfidbearer.cpp new file mode 100644 index 0000000000..6ac6714d56 --- /dev/null +++ b/indra/llui/lfidbearer.cpp @@ -0,0 +1,59 @@ +/* Copyright (C) 2019 Liru Færs + * + * LFIDBearer is a class that holds an ID or IDs that menus can use + * + * 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * 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 */ + +#include "linden_common.h" +#include "lfidbearer.h" +#include "llmenugl.h" +#include "lluictrlfactory.h" + +const std::array LFIDBearer::sMenuStrings +{ + "menu_avs_list.xml" // 0 +, "menu_groups_list.xml" // 1 +, "menu_objects_list.xml" // 2 +, "menu_experiences.xml" // 3 +}; +std::array LFIDBearer::sMenus {}; + +const LFIDBearer* LFIDBearer::sActive = nullptr; +LFIDBearer::Type LFIDBearer::sActiveType = LFIDBearer::AVATAR; +uuid_vec_t LFIDBearer::sActiveIDs {}; + +void LFIDBearer::buildMenus() +{ + auto& factory = LLUICtrlFactory::instance(); + for (auto i = 0; i < COUNT; ++i) + sMenus[i] = factory.buildMenu(sMenuStrings[i], LLMenuGL::sMenuContainer); +} + +LLMenuGL* LFIDBearer::showMenu(LLView* self, const std::string& menu_name, S32 x, S32 y, std::function on_menu_built) +{ + auto menu = LLUICtrlFactory::instance().buildMenu(menu_name, LLMenuGL::sMenuContainer); + if (on_menu_built) on_menu_built(menu); + showMenu(self, menu, x, y); + return menu; +} + +void LFIDBearer::showMenu(LLView* self, LLMenuGL* menu, S32 x, S32 y) +{ + setActive(); // Menu listeners rely on this + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(self, menu, x, y); +} diff --git a/indra/llui/lfidbearer.h b/indra/llui/lfidbearer.h new file mode 100644 index 0000000000..3f434a5a7e --- /dev/null +++ b/indra/llui/lfidbearer.h @@ -0,0 +1,73 @@ +/* Copyright (C) 2019 Liru Færs + * + * LFIDBearer is a class that holds an ID or IDs that menus can use + * This class also bears the type of ID/IDs that it is holding + * + * 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * 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 */ + +#pragma once + +#include "lluuid.h" + +class LLMenuGL; +class LLView; + +struct LFIDBearer +{ + enum Type : S8 + { + MULTIPLE = -2, + NONE = -1, + AVATAR = 0, + GROUP, + OBJECT, + EXPERIENCE, + COUNT + }; + + virtual ~LFIDBearer() { if (sActive == this) sActive = nullptr; } + virtual LLUUID getStringUUIDSelectedItem() const = 0; + virtual uuid_vec_t getSelectedIDs() const { return { getStringUUIDSelectedItem() }; } + virtual Type getSelectedType() const { return AVATAR; } + + template static const T* getActive() { return static_cast(sActive); } + static const LLUUID& getActiveSelectedID() { return sActiveIDs.empty() ? LLUUID::null : sActiveIDs[0]; } + static const uuid_vec_t& getActiveSelectedIDs() { return sActiveIDs; } + static size_t getActiveNumSelected() { return sActiveIDs.size(); } + static const Type& getActiveType() { return sActiveType; } + + void setActive() const + { + sActive = this; + sActiveType = getSelectedType(); + sActiveIDs = getSelectedIDs(); + //sActiveIDs or even some kinda hybrid map, if Type is MULTIPLE fill the vals? and remove a buncha virtual functions? + } + + static void buildMenus(); + LLMenuGL* showMenu(LLView* self, const std::string& menu_name, S32 x, S32 y, std::function on_menu_built = nullptr); + void showMenu(LLView* self, LLMenuGL* menu, S32 x, S32 y); + +protected: + // Menus that recur, such as general avatars or groups menus + static const std::array sMenuStrings; + static std::array sMenus; + +private: + static const LFIDBearer* sActive; + static Type sActiveType; + static uuid_vec_t sActiveIDs; +}; diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp new file mode 100644 index 0000000000..be26d58a72 --- /dev/null +++ b/indra/llui/llaccordionctrl.cpp @@ -0,0 +1,925 @@ +/** + * @file llaccordionctrl.cpp + * @brief Accordion panel implementation + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llaccordionctrl.h" +#include "llaccordionctrltab.h" + +#include "lluictrlfactory.h" // builds floaters from XML + +#include "llwindow.h" +#include "llfocusmgr.h" +#include "lllocalcliprect.h" + +#include "boost/bind.hpp" + +static const S32 BORDER_MARGIN = 2; +static const S32 PARENT_BORDER_MARGIN = 5; +static const S32 VERTICAL_MULTIPLE = 16; +static const F32 MIN_AUTO_SCROLL_RATE = 120.f; +static const F32 MAX_AUTO_SCROLL_RATE = 500.f; +static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f; + +// LLAccordionCtrl =================================================================| + +//static LLDefaultChildRegistry::Register t2("accordion"); +static LLRegisterWidget t2("accordion"); + +/*LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) + , mFitParent(params.fit_parent) + , mAutoScrolling( false ) + , mAutoScrollRate( 0.f ) + , mSelectedTab( NULL ) + , mTabComparator( NULL ) + , mNoVisibleTabsHelpText(NULL) + , mNoVisibleTabsOrigString(params.no_visible_tabs_text.initial_value().asString()) +{ + initNoTabsWidget(params.no_matched_tabs_text); + + mSingleExpansion = params.single_expansion; + if(mFitParent && !mSingleExpansion) + { + LL_INFOS() << "fit_parent works best when combined with single_expansion" << LL_ENDL; + } +}*/ + +LLAccordionCtrl::LLAccordionCtrl() : LLPanel() + , mAutoScrolling( false ) + , mAutoScrollRate( 0.f ) + , mSelectedTab( NULL ) + , mNoVisibleTabsHelpText(NULL) +{ + initNoTabsWidget(""/*LLTextBox::Params()*/); + + mSingleExpansion = false; + mFitParent = false; + LLUICtrlFactory::getInstance()->buildPanel(this, "accordion_parent.xml"); +} + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::draw() +{ + if (mAutoScrolling) + { + // add acceleration to autoscroll + mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), MAX_AUTO_SCROLL_RATE); + } + else + { + // reset to minimum for next time + mAutoScrollRate = MIN_AUTO_SCROLL_RATE; + } + // clear this flag to be set on next call to autoScroll + mAutoScrolling = false; + + LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + + LLLocalClipRect clip(local_rect); + + LLPanel::draw(); +} + + +//--------------------------------------------------------------------------------- +BOOL LLAccordionCtrl::postBuild() +{ + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + LLRect scroll_rect; + scroll_rect.setOriginAndSize( + getRect().getWidth() - scrollbar_size, + 1, + scrollbar_size, + getRect().getHeight() - 1); + + mScrollbar = new LLScrollbar("scrollable vertical", scroll_rect, LLScrollbar::VERTICAL, mInnerRect.getHeight(), 0, mInnerRect.getHeight(), boost::bind(&LLAccordionCtrl::onScrollPosChangeCallback, this, _1, _2), VERTICAL_MULTIPLE); + mScrollbar->setFollows(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + LLView::addChild( mScrollbar ); + mScrollbar->setVisible( false ); + mScrollbar->setFollows(FOLLOWS_RIGHT|FOLLOWS_TOP|FOLLOWS_BOTTOM); + + //if it was created from xml... + std::vector accordion_tabs; + for(child_list_const_iter_t it = getChildList()->begin(); + getChildList()->end() != it; ++it) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(*it); + if(accordion_tab == NULL) + continue; + if(std::find(mAccordionTabs.begin(),mAccordionTabs.end(),accordion_tab) == mAccordionTabs.end()) + { + accordion_tabs.push_back(accordion_tab); + } + } + + for(std::vector::reverse_iterator it = accordion_tabs.rbegin();it!=accordion_tabs.rend();++it) + addCollapsibleCtrl(*it); + + arrange (); + + if(mSingleExpansion) + { + if(!mAccordionTabs[0]->getDisplayChildren()) + mAccordionTabs[0]->setDisplayChildren(true); + for(size_t i=1;igetDisplayChildren()) + mAccordionTabs[i]->setDisplayChildren(false); + } + } + + updateNoTabsHelpTextVisibility(); + + return TRUE; +} + + +//--------------------------------------------------------------------------------- +LLAccordionCtrl::~LLAccordionCtrl() +{ + mAccordionTabs.clear(); +} + +//--------------------------------------------------------------------------------- + +void LLAccordionCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + // adjust our rectangle + LLRect rcLocal = getRect(); + rcLocal.mRight = rcLocal.mLeft + width; + rcLocal.mTop = rcLocal.mBottom + height; + + // get textbox a chance to reshape its content + mNoVisibleTabsHelpText->reshape(width, height, called_from_parent); + + setRect(rcLocal); + + // assume that help text is always fit accordion. + // necessary text paddings can be set via h_pad and v_pad + mNoVisibleTabsHelpText->setRect(getLocalRect()); + + arrange(); +} + +//--------------------------------------------------------------------------------- +BOOL LLAccordionCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + return LLPanel::handleRightMouseDown(x, y, mask); +} + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::shiftAccordionTabs(S16 panel_num, S32 delta) +{ + for(size_t i = panel_num; i < mAccordionTabs.size(); i++ ) + { + ctrlShiftVertical(mAccordionTabs[i],delta); + } +} + + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num) +{ + if(mSingleExpansion) + { + for(size_t i=0;igetDisplayChildren()) + mAccordionTabs[i]->setDisplayChildren(false); + } + + } + arrange(); +} + +void LLAccordionCtrl::show_hide_scrollbar(S32 width, S32 height) +{ + calcRecuiredHeight(); + if(getRecuiredHeight() > height ) + showScrollbar(width,height); + else + hideScrollbar(width,height); +} + +void LLAccordionCtrl::showScrollbar(S32 width, S32 height) +{ + bool was_visible = mScrollbar->getVisible(); + + mScrollbar->setVisible(true); + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + ctrlSetLeftTopAndSize(mScrollbar + ,width-scrollbar_size - PARENT_BORDER_MARGIN/2 + ,height-PARENT_BORDER_MARGIN + ,scrollbar_size + ,height-2*PARENT_BORDER_MARGIN); + + mScrollbar->setPageSize(height); + mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos()); + + if(was_visible) + { + S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1); + mScrollbar->setDocPos(scroll_pos); + } +} + +void LLAccordionCtrl::hideScrollbar( S32 width, S32 height ) +{ + if(mScrollbar->getVisible() == false) + return; + mScrollbar->setVisible(false); + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + S32 panel_width = width - 2*BORDER_MARGIN; + + //reshape all accordeons and shift all draggers + for(size_t i=0;igetRect(); + ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_rect.mTop,panel_width,panel_rect.getHeight()); + } + + mScrollbar->setDocPos(0); + + if(mAccordionTabs.size()>0) + { + S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel + S32 diff = panel_top - mAccordionTabs[0]->getRect().mTop; + shiftAccordionTabs(0,diff); + } +} + + +//--------------------------------------------------------------------------------- +S32 LLAccordionCtrl::calcRecuiredHeight() +{ + S32 rec_height = 0; + + std::vector::iterator panel; + for(panel=mAccordionTabs.begin(); panel!=mAccordionTabs.end(); ++panel) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(*panel); + if(accordion_tab && accordion_tab->getVisible()) + { + rec_height += accordion_tab->getRect().getHeight(); + } + } + + mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN); + + return mInnerRect.getHeight(); +} + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height) +{ + if(!panel) + return; + LLRect panel_rect = panel->getRect(); + panel_rect.setLeftTopAndSize( left, top, width, height); + panel->reshape( width, height, 1); + panel->setRect(panel_rect); +} + +void LLAccordionCtrl::ctrlShiftVertical(LLView* panel,S32 delta) +{ + if(!panel) + return; + panel->translate(0,delta); +} + +//--------------------------------------------------------------------------------- + +void LLAccordionCtrl::addCollapsibleCtrl(LLView* view) +{ + LLAccordionCtrlTab* accordion_tab = dynamic_cast(view); + if(!accordion_tab) + return; + if(std::find(beginChild(), endChild(), accordion_tab) == endChild()) + addChild(accordion_tab); + mAccordionTabs.push_back(accordion_tab); + + accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, S16(mAccordionTabs.size() - 1)) ); + arrange(); +} + +void LLAccordionCtrl::removeCollapsibleCtrl(LLView* view) +{ + LLAccordionCtrlTab* accordion_tab = dynamic_cast(view); + if(!accordion_tab) + return; + + if(std::find(beginChild(), endChild(), accordion_tab) != endChild()) + removeChild(accordion_tab); + + for (std::vector::iterator iter = mAccordionTabs.begin(); + iter != mAccordionTabs.end(); ++iter) + { + if (accordion_tab == (*iter)) + { + mAccordionTabs.erase(iter); + break; + } + } + + // if removed is selected - reset selection + if (mSelectedTab == view) + { + mSelectedTab = NULL; + } +} + +void LLAccordionCtrl::initNoTabsWidget(const std::string/*LLTextBox::Params*/& tb_params) +{ + //LLTextBox::Params tp = tb_params; + //tp.rect(getLocalRect()); + mNoMatchedTabsOrigString = tb_params; //tp.initial_value().asString(); + mNoVisibleTabsHelpText = new LLTextBox(tb_params, getLocalRect()); //LLUICtrlFactory::create(tp, this); +} + +void LLAccordionCtrl::updateNoTabsHelpTextVisibility() +{ + bool visible_exists = false; + std::vector::const_iterator it = mAccordionTabs.begin(); + const std::vector::const_iterator it_end = mAccordionTabs.end(); + for (; it != it_end; ++it) + { + if ((*it)->getVisible()) + { + visible_exists = true; + break; + } + } + + mNoVisibleTabsHelpText->setVisible(!visible_exists); +} + +void LLAccordionCtrl::arrangeSinge() +{ + S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter + S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel + S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel + S32 panel_height; + + S32 collapsed_height = 0; + + for(size_t i=0;i(mAccordionTabs[i]); + + if(accordion_tab->getVisible() == false) //skip hidden accordion tabs + continue; + if(!accordion_tab->isExpanded() ) + { + collapsed_height+=mAccordionTabs[i]->getRect().getHeight(); + } + } + + S32 expanded_height = getRect().getHeight() - BORDER_MARGIN - collapsed_height; + + for(size_t i=0;i(mAccordionTabs[i]); + + if(accordion_tab->getVisible() == false) //skip hidden accordion tabs + continue; + if(!accordion_tab->isExpanded() ) + { + panel_height = accordion_tab->getRect().getHeight(); + } + else + { + if(mFitParent) + { + panel_height = expanded_height; + } + else + { + if(accordion_tab->getAccordionView()) + { + panel_height = accordion_tab->getAccordionView()->getRect().getHeight() + + accordion_tab->getHeaderHeight() + 2*BORDER_MARGIN; + } + else + { + panel_height = accordion_tab->getRect().getHeight(); + } + } + } + + // make sure at least header is shown + panel_height = llmax(panel_height, accordion_tab->getHeaderHeight()); + + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height); + panel_top-=mAccordionTabs[i]->getRect().getHeight(); + } + + show_hide_scrollbar(getRect().getWidth(), getRect().getHeight()); + updateLayout(getRect().getWidth(), getRect().getHeight()); +} + +void LLAccordionCtrl::arrangeMultiple() +{ + S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter + S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel + S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel + + //Calculate params + for(size_t i = 0; i < mAccordionTabs.size(); i++ ) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); + + if(accordion_tab->getVisible() == false) //skip hidden accordion tabs + continue; + + if(!accordion_tab->isExpanded() ) + { + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, accordion_tab->getRect().getHeight()); + panel_top-=mAccordionTabs[i]->getRect().getHeight(); + } + else + { + S32 panel_height = accordion_tab->getRect().getHeight(); + + if(mFitParent) + { + // all expanded tabs will have equal height + panel_height = calcExpandedTabHeight(i, panel_top); + ctrlSetLeftTopAndSize(accordion_tab, panel_left, panel_top, panel_width, panel_height); + + // try to make accordion tab fit accordion view height. + // Accordion View should implement getRequiredRect() and provide valid height + S32 optimal_height = accordion_tab->getAccordionView()->getRequiredRect().getHeight(); + optimal_height += accordion_tab->getHeaderHeight() + 2 * BORDER_MARGIN; + if(optimal_height < panel_height) + { + panel_height = optimal_height; + } + + // minimum tab height is equal to header height + if(mAccordionTabs[i]->getHeaderHeight() > panel_height) + { + panel_height = mAccordionTabs[i]->getHeaderHeight(); + } + } + + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height); + panel_top-=panel_height; + + } + } + + show_hide_scrollbar(getRect().getWidth(),getRect().getHeight()); + + updateLayout(getRect().getWidth(),getRect().getHeight()); +} + + +void LLAccordionCtrl::arrange() +{ + updateNoTabsHelpTextVisibility(); + + if( mAccordionTabs.size() == 0) + { + //We do not arrange if we do not have what should be arranged + return; + } + + + if(mAccordionTabs.size() == 1) + { + S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel + S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel + + LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[0]); + + LLRect panel_rect = accordion_tab->getRect(); + + S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN; + + if (accordion_tab->getFitParent()) + panel_height = accordion_tab->getRect().getHeight(); + ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height); + + show_hide_scrollbar(getRect().getWidth(),getRect().getHeight()); + return; + + } + + if(mSingleExpansion) + arrangeSinge (); + else + arrangeMultiple (); +} + +//--------------------------------------------------------------------------------- + +BOOL LLAccordionCtrl::handleScrollWheel ( S32 x, S32 y, S32 clicks ) +{ + if(LLPanel::handleScrollWheel(x,y,clicks)) + return TRUE; + if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) ) + return TRUE; + return false; + +} + +BOOL LLAccordionCtrl::handleKeyHere (KEY key, MASK mask) +{ + if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) ) + return TRUE; + return LLPanel::handleKeyHere(key,mask); +} + +BOOL LLAccordionCtrl::handleDragAndDrop (S32 x, S32 y, MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + // Scroll folder view if needed. Never accepts a drag or drop. + *accept = ACCEPT_NO; + BOOL handled = autoScroll(x, y); + + if( !handled ) + { + handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, + cargo_data, accept, tooltip_msg) != NULL; + } + return TRUE; +} + +BOOL LLAccordionCtrl::autoScroll (S32 x, S32 y) +{ + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + bool scrolling = false; + if( mScrollbar->getVisible() ) + { + LLRect rect_local( 0, getRect().getHeight(), getRect().getWidth() - scrollbar_size, 0 ); + LLRect screen_local_extents; + + // clip rect against root view + screenRectToLocal(getRootView()->getLocalRect(), &screen_local_extents); + rect_local.intersectWith(screen_local_extents); + + // autoscroll region should take up no more than one third of visible scroller area + S32 auto_scroll_region_height = llmin(rect_local.getHeight() / 3, 10); + S32 auto_scroll_speed = ll_pos_round(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32()); + + LLRect bottom_scroll_rect = screen_local_extents; + bottom_scroll_rect.mTop = rect_local.mBottom + auto_scroll_region_height; + if( bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() < mScrollbar->getDocPosMax()) ) + { + mScrollbar->setDocPos( mScrollbar->getDocPos() + auto_scroll_speed ); + mAutoScrolling = true; + scrolling = true; + } + + LLRect top_scroll_rect = screen_local_extents; + top_scroll_rect.mBottom = rect_local.mTop - auto_scroll_region_height; + if( top_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() > 0) ) + { + mScrollbar->setDocPos( mScrollbar->getDocPos() - auto_scroll_speed ); + mAutoScrolling = true; + scrolling = true; + } + } + return scrolling; +} + +void LLAccordionCtrl::updateLayout (S32 width, S32 height) +{ + S32 panel_top = height - BORDER_MARGIN ; + if(mScrollbar->getVisible()) + panel_top+=mScrollbar->getDocPos(); + + S32 panel_width = width - 2*BORDER_MARGIN; + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + if(mScrollbar->getVisible()) + panel_width-=scrollbar_size; + + //set sizes for first panels and dragbars + for(size_t i=0;igetVisible()) + continue; + LLRect panel_rect = mAccordionTabs[i]->getRect(); + ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight()); + panel_top-=panel_rect.getHeight(); + } +} + +void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*) +{ + updateLayout(getRect().getWidth(),getRect().getHeight()); +} +/*void LLAccordionCtrl::onOpen (const LLSD& key) +{ + for(size_t i=0;i(mAccordionTabs[i]); + LLPanel* panel = dynamic_cast(accordion_tab->getAccordionView()); + if(panel!=NULL) + { + panel->onOpen(key); + } + } +}*/ +S32 LLAccordionCtrl::notifyParent(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "size_changes") + { + // + arrange(); + return 1; + } + else if(str_action == "select_next") + { + for(size_t i=0;i(mAccordionTabs[i]); + if(accordion_tab->hasFocus()) + { + while(++igetVisible()) + break; + } + if(i(mAccordionTabs[i]); + accordion_tab->notify(LLSD().with("action","select_first")); + return 1; + } + break; + } + } + return 0; + } + else if(str_action == "select_prev") + { + for(size_t i=0;i(mAccordionTabs[i]); + if(accordion_tab->hasFocus() && i>0) + { + bool prev_visible_tab_found = false; + while(i>0) + { + if(mAccordionTabs[--i]->getVisible()) + { + prev_visible_tab_found = true; + break; + } + } + + if (prev_visible_tab_found) + { + accordion_tab = dynamic_cast(mAccordionTabs[i]); + accordion_tab->notify(LLSD().with("action","select_last")); + return 1; + } + break; + } + } + return 0; + } + else if(str_action == "select_current") + { + for(size_t i=0;ihasFocus()) + { + if (mAccordionTabs[i] != mSelectedTab) + { + if (mSelectedTab) + { + mSelectedTab->setSelected(false); + } + mSelectedTab = mAccordionTabs[i]; + mSelectedTab->setSelected(true); + } + + return 1; + } + } + return 0; + } + else if(str_action == "deselect_current") + { + // Reset selection to the currently selected tab. + if (mSelectedTab) + { + mSelectedTab->setSelected(false); + mSelectedTab = NULL; + return 1; + } + return 0; + } + } + else if (info.has("scrollToShowRect")) + { + LLRect screen_rc, local_rc; + screen_rc.setValue(info["scrollToShowRect"]); + screenRectToLocal(screen_rc, &local_rc); + + // Translate to parent coordinatess to check if we are in visible rectangle + local_rc.translate( getRect().mLeft, getRect().mBottom ); + + if ( !getRect().contains (local_rc) ) + { + // Back to local coords and calculate position for scroller + S32 bottom = mScrollbar->getDocPos() - local_rc.mBottom + getRect().mBottom; + S32 top = mScrollbar->getDocPos() - local_rc.mTop + getRect().mTop; + + S32 scroll_pos = llclamp(mScrollbar->getDocPos(), + bottom, // min vertical scroll + top); // max vertical scroll + + mScrollbar->setDocPos( scroll_pos ); + } + return 1; + } + else if (info.has("child_visibility_change")) + { + BOOL new_visibility = info["child_visibility_change"]; + if (new_visibility) + { + // there is at least one visible tab + mNoVisibleTabsHelpText->setVisible(FALSE); + } + else + { + // it could be the latest visible tab, check all of them + updateNoTabsHelpTextVisibility(); + } + } + return LLPanel::notifyParent(info); +} +void LLAccordionCtrl::reset () +{ + if(mScrollbar) + mScrollbar->setDocPos(0); +} + +void LLAccordionCtrl::expandDefaultTab() +{ + if (mAccordionTabs.size() > 0) + { + LLAccordionCtrlTab* tab = mAccordionTabs.front(); + + if (!tab->getDisplayChildren()) + { + tab->setDisplayChildren(true); + } + + for (size_t i = 1; i < mAccordionTabs.size(); ++i) + { + tab = mAccordionTabs[i]; + + if (tab->getDisplayChildren()) + { + tab->setDisplayChildren(false); + } + } + + arrange(); + } +} + +void LLAccordionCtrl::sort() +{ + if (!mTabComparator) + { + LL_WARNS() << "No comparator specified for sorting accordion tabs." << LL_ENDL; + return; + } + + std::sort(mAccordionTabs.begin(), mAccordionTabs.end(), LLComparatorAdaptor(*mTabComparator)); + arrange(); +} + +void LLAccordionCtrl::setFilterSubString(const std::string& filter_string) +{ + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(filter_string); + std::string text = filter_string.empty() ? mNoVisibleTabsOrigString : mNoMatchedTabsOrigString; + LLStringUtil::format(text, args); + + mNoVisibleTabsHelpText->setValue(text); +} + +const LLAccordionCtrlTab* LLAccordionCtrl::getExpandedTab() const +{ + typedef std::vector::const_iterator tabs_const_iterator; + + const LLAccordionCtrlTab* result = 0; + + for (tabs_const_iterator i = mAccordionTabs.begin(); i != mAccordionTabs.end(); ++i) + { + if ((*i)->isExpanded()) + { + result = *i; + break; + } + } + + return result; +} + +S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */) +{ + if(tab_index < 0) + { + return available_height; + } + + S32 collapsed_tabs_height = 0; + S32 num_expanded = 0; + + for(size_t n = tab_index; n < mAccordionTabs.size(); ++n) + { + if(!mAccordionTabs[n]->isExpanded()) + { + collapsed_tabs_height += mAccordionTabs[n]->getHeaderHeight(); + } + else + { + ++num_expanded; + } + } + + if(0 == num_expanded) + { + return available_height; + } + + S32 expanded_tab_height = available_height - collapsed_tabs_height - BORDER_MARGIN; // top BORDER_MARGIN is added in arrange(), here we add bottom BORDER_MARGIN + expanded_tab_height /= num_expanded; + return expanded_tab_height; +} + + +//static +LLView* LLAccordionCtrl::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory* factory) +{ + LLAccordionCtrl* ctrl = new LLAccordionCtrl(); + ctrl->mCommitCallbackRegistrar.pushScope(); + ctrl->mEnableCallbackRegistrar.pushScope(); + ctrl->initPanelXML(node, parent, factory); + ctrl->mCommitCallbackRegistrar.popScope(); + ctrl->mEnableCallbackRegistrar.popScope(); + return ctrl; +} + +void LLAccordionCtrl::initFromXML(LLXMLNodePtr node, LLView* parent) +{ + if (node->hasAttribute("single_expansion")) + node->getAttribute_bool("single_expansion", mSingleExpansion); + if (node->hasAttribute("fit_parent")) + node->getAttribute_bool("fit_parent", mFitParent); + if (node->hasAttribute("no_matched_tabs_text")) + { + node->getAttributeString("no_matched_tabs_text", mNoMatchedTabsOrigString); + mNoVisibleTabsHelpText->setValue(mNoMatchedTabsOrigString); + } + if (node->hasAttribute("no_visible_tabs_text")) + node->getAttributeString("no_visible_tabs_text", mNoVisibleTabsOrigString); + + LLPanel::initFromXML(node, parent); +} diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h new file mode 100644 index 0000000000..95e321df35 --- /dev/null +++ b/indra/llui/llaccordionctrl.h @@ -0,0 +1,197 @@ +/** + * @file LLAccordionCtrl.h + * @brief Accordion Panel implementation + * + * $LicenseInfo:firstyear=2004&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_ACCORDIONCTRL_H +#define LL_ACCORDIONCTRL_H + +#include "llpanel.h" +#include "lltextbox.h" +#include "llscrollbar.h" + +#include +#include +#include + +class LLAccordionCtrlTab; + +class LLAccordionCtrl: public LLPanel +{ +private: + + std::vector mAccordionTabs; + + void ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height); + void ctrlShiftVertical(LLView* panel,S32 delta); + + void onCollapseCtrlCloseOpen(S16 panel_num); + void shiftAccordionTabs(S16 panel_num, S32 delta); + + +public: + /** + * Abstract comparator for accordion tabs. + */ + class LLTabComparator + { + public: + LLTabComparator() {}; + virtual ~LLTabComparator() {}; + + /** Returns true if tab1 < tab2, false otherwise */ + virtual bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const = 0; + }; + + #if 0 // Singu TODO: LLPanel::Params, LLTextBox::Params + struct Params + : public LLInitParam::Block + { + Optional single_expansion, + fit_parent; /* Accordion will fit its parent size, controls that are placed into + accordion tabs are responsible for scrolling their content. + *NOTE fit_parent works best when combined with single_expansion. + Accordion view should implement getRequiredRect() and provide valid height*/ + Optional no_matched_tabs_text; + Optional no_visible_tabs_text; + + Params() + : single_expansion("single_expansion",false) + , fit_parent("fit_parent", false) + , no_matched_tabs_text("no_matched_tabs_text") + , no_visible_tabs_text("no_visible_tabs_text") + {}; + }; + + LLAccordionCtrl(const Params& params); + #endif + + LLAccordionCtrl(); + virtual ~LLAccordionCtrl(); + + virtual BOOL postBuild(); + static LLView* fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFactory* factory); + virtual void initFromXML(LLXMLNodePtr node, LLView* parent); + + virtual BOOL handleRightMouseDown ( S32 x, S32 y, MASK mask); + virtual BOOL handleScrollWheel ( S32 x, S32 y, S32 clicks ); + virtual BOOL handleKeyHere (KEY key, MASK mask); + virtual BOOL handleDragAndDrop (S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + // + + // Call reshape after changing splitter's size + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + void addCollapsibleCtrl(LLView* view); + void removeCollapsibleCtrl(LLView* view); + void arrange(); + + + void draw(); + + void onScrollPosChangeCallback(S32, LLScrollbar*); + + //void onOpen (const LLSD& key); + S32 notifyParent(const LLSD& info); + + void reset (); + void expandDefaultTab(); + + void setComparator(const LLTabComparator* comp) { mTabComparator = comp; } + void sort(); + + /** + * Sets filter substring as a search_term for help text when there are no any visible tabs. + */ + void setFilterSubString(const std::string& filter_string); + + /** + * This method returns the first expanded accordion tab. + * It is expected to be called for accordion which doesn't allow multiple + * tabs to be expanded. Use with care. + */ + const LLAccordionCtrlTab* getExpandedTab() const; + + LLAccordionCtrlTab* getSelectedTab() const { return mSelectedTab; } + + bool getFitParent() const {return mFitParent;} + +private: + void initNoTabsWidget(const std::string/*LLTextBox::Params*/& tb_params); + void updateNoTabsHelpTextVisibility(); + + void arrangeSinge(); + void arrangeMultiple(); + + // Calc Splitter's height that is necessary to display all child content + S32 calcRecuiredHeight(); + S32 getRecuiredHeight() const { return mInnerRect.getHeight(); } + S32 calcExpandedTabHeight(S32 tab_index = 0, S32 available_height = 0); + + void updateLayout (S32 width, S32 height); + + void show_hide_scrollbar (S32 width, S32 height); + + void showScrollbar (S32 width, S32 height); + void hideScrollbar (S32 width, S32 height); + + BOOL autoScroll (S32 x, S32 y); + + /** + * An adaptor for LLTabComparator + */ + struct LLComparatorAdaptor + { + LLComparatorAdaptor(const LLTabComparator& comparator) : mComparator(comparator) {}; + + bool operator()(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) + { + return mComparator.compare(tab1, tab2); + } + + const LLTabComparator& mComparator; + }; + +private: + LLRect mInnerRect; + LLScrollbar* mScrollbar; + bool mSingleExpansion; + bool mFitParent; + bool mAutoScrolling; + F32 mAutoScrollRate; + LLTextBox* mNoVisibleTabsHelpText; + + std::string mNoMatchedTabsOrigString; + std::string mNoVisibleTabsOrigString; + + LLAccordionCtrlTab* mSelectedTab; + const LLTabComparator* mTabComparator; +}; + + +#endif // LL_LLSPLITTER_H diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp new file mode 100644 index 0000000000..79ebd97057 --- /dev/null +++ b/indra/llui/llaccordionctrltab.cpp @@ -0,0 +1,1278 @@ +/** + * @file LLAccordionCtrlTab.cpp + * @brief Collapsible control implementation + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llaccordionctrltab.h" +#include "llaccordionctrl.h" + +#include "lllocalcliprect.h" +#include "llscrollbar.h" +#include "lltextbox.h" +//#include "lltextutil.h" +#include "lluictrl.h" +#include "lluictrlfactory.h" + +static const std::string DD_BUTTON_NAME = "dd_button"; +static const std::string DD_TEXTBOX_NAME = "dd_textbox"; +static const std::string DD_HEADER_NAME = "dd_header"; + +static const S32 HEADER_HEIGHT = 23; +static const S32 HEADER_IMAGE_LEFT_OFFSET = 5; +static const S32 HEADER_TEXT_LEFT_OFFSET = 30; +static const F32 AUTO_OPEN_TIME = 1.f; +static const S32 VERTICAL_MULTIPLE = 16; +static const S32 PARENT_BORDER_MARGIN = 5; + +//static LLDefaultChildRegistry::Register t1("accordion_tab"); +static LLRegisterWidget t1("accordion_tab"); + +class LLAccordionCtrlTab::LLAccordionCtrlTabHeader : public LLUICtrl +{ +public: + friend class LLUICtrlFactory; + + struct Params : public LLAccordionCtrlTab::Params //LLInitParam::Block + { + Params(); + Params(const LLAccordionCtrlTab::Params& p) : LLAccordionCtrlTab::Params(p) {} + }; + + LLAccordionCtrlTabHeader(const LLAccordionCtrlTabHeader::Params& p); + + virtual ~LLAccordionCtrlTabHeader(); + + virtual void draw(); + + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + virtual BOOL postBuild(); + + std::string getTitle(); + void setTitle(const std::string& title, const std::string& hl); + + void setTitleFontStyle(std::string style); + + void setTitleColor(LLUIColor); + + void setSelected(bool is_selected) { mIsSelected = is_selected; } + + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); +private: + + LLTextBox* mHeaderTextbox; + + // Overlay images (arrows) + LLPointer mImageCollapsed; + LLPointer mImageExpanded; + LLPointer mImageCollapsedPressed; + LLPointer mImageExpandedPressed; + + // Background images + LLPointer mImageHeader; + LLPointer mImageHeaderOver; + LLPointer mImageHeaderPressed; + LLPointer mImageHeaderFocused; + + // style saved when applying it in setTitleFontStyle + //U8/*LLStyle::Params*/ mStyleParams; + + LLUIColor mHeaderBGColor; + + bool mNeedsHighlight; + bool mIsSelected; + + LLFrameTimer mAutoOpenTimer; +}; + +LLAccordionCtrlTab::LLAccordionCtrlTabHeader::Params::Params() +{ +} + +LLAccordionCtrlTab::LLAccordionCtrlTabHeader::LLAccordionCtrlTabHeader( + const LLAccordionCtrlTabHeader::Params& p) +: LLUICtrl(p) +, mHeaderBGColor(p.header_bg_color()) +, mNeedsHighlight(false) +, mIsSelected(false), + mImageCollapsed(p.header_collapse_img), + mImageCollapsedPressed(p.header_collapse_img_pressed), + mImageExpanded(p.header_expand_img), + mImageExpandedPressed(p.header_expand_img_pressed), + mImageHeader(p.header_image), + mImageHeaderOver(p.header_image_over), + mImageHeaderPressed(p.header_image_pressed), + mImageHeaderFocused(p.header_image_focused) +{ + mHeaderTextbox = new LLTextBox(DD_TEXTBOX_NAME, p.title(), 200, p.font(), false); + mHeaderTextbox->setColor(p.header_text_color()); + mHeaderTextbox->setFollows(FOLLOWS_NONE); + mHeaderTextbox->setFontShadow(LLFontGL::NO_SHADOW); + mHeaderTextbox->setUseEllipses(true); + mHeaderTextbox->setBackgroundVisible(false); + addChild(mHeaderTextbox); +} + +LLAccordionCtrlTab::LLAccordionCtrlTabHeader::~LLAccordionCtrlTabHeader() +{ +} + +BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::postBuild() +{ + return TRUE; +} + +std::string LLAccordionCtrlTab::LLAccordionCtrlTabHeader::getTitle() +{ + if(mHeaderTextbox) + { + return mHeaderTextbox->getText(); + } + else + { + return LLStringUtil::null; + } +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title, const std::string& hl) +{ + if(mHeaderTextbox) + { + mHeaderTextbox->setText(title); + /*LLTextUtil::textboxSetHighlightedVal( + mHeaderTextbox, + mStyleParams, + title, + hl);*/ + } +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitleFontStyle(std::string style) +{ + if (mHeaderTextbox) + { + mHeaderTextbox->setFontStyle(/*mStyleParams =*/ LLFontGL::getStyleFromString(style)); + } +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitleColor(LLUIColor color) +{ + if(mHeaderTextbox) + { + mHeaderTextbox->setColor(color); + } +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw() +{ + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); + + //F32 alpha = getCurrentTransparency(); // Singu TODO + gl_rect_2d(0,0,width - 1 ,height - 1,mHeaderBGColor.get() /*% alpha*/,true); + + LLAccordionCtrlTab* parent = dynamic_cast(getParent()); + bool collapsible = (parent && parent->getCollapsible()); + bool expanded = (parent && parent->getDisplayChildren()); + + // Handle overlay images, if needed + // Only show green "focus" background image if the accordion is open, + // because the user's mental model of focus is that it goes away after + // the accordion is closed. + if (getParent()->hasFocus() || mIsSelected + /*&& !(collapsible && !expanded)*/ // WHY?? + ) + { + mImageHeaderFocused->draw(0,0,width,height); + } + else + { + mImageHeader->draw(0,0,width,height); + } + + if(mNeedsHighlight) + { + mImageHeaderOver->draw(0,0,width,height); + } + + + if(collapsible) + { + LLPointer overlay_image; + if(expanded) + { + overlay_image = mImageExpanded; + } + else + { + overlay_image = mImageCollapsed; + } + overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET, + (height - overlay_image->getHeight()) / 2); + } + + LLUICtrl::draw(); +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +{ + S32 header_height = mHeaderTextbox->getTextPixelHeight(); + + LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET,(height+header_height)/2 ,width,(height-header_height)/2); + mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight()); + mHeaderTextbox->setRect(textboxRect); + + if (mHeaderTextbox->getTextPixelWidth() > mHeaderTextbox->getRect().getWidth()) + { + setToolTip(mHeaderTextbox->getText()); + } + else + { + setToolTip(LLStringUtil::null); + } +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseEnter(S32 x, S32 y, MASK mask) +{ + LLUICtrl::onMouseEnter(x, y, mask); + mNeedsHighlight = true; +} +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseLeave(S32 x, S32 y, MASK mask) +{ + LLUICtrl::onMouseLeave(x, y, mask); + mNeedsHighlight = false; + mAutoOpenTimer.stop(); +} +BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + if ( ( key == KEY_LEFT || key == KEY_RIGHT) && mask == MASK_NONE) + { + return getParent()->handleKey(key, mask, called_from_parent); + } + return LLUICtrl::handleKey(key, mask, called_from_parent); +} +BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + LLAccordionCtrlTab* parent = dynamic_cast(getParent()); + + if ( parent && !parent->getDisplayChildren() && parent->getCollapsible() && parent->canOpenClose() ) + { + if (mAutoOpenTimer.getStarted()) + { + if (mAutoOpenTimer.getElapsedTimeF32() > AUTO_OPEN_TIME) + { + parent->changeOpenClose(false); + mAutoOpenTimer.stop(); + return TRUE; + } + } + else + mAutoOpenTimer.start(); + } + + return LLUICtrl::handleDragAndDrop(x, y, mask, drop, cargo_type, + cargo_data, accept, tooltip_msg); +} +LLAccordionCtrlTab::Params::Params() + : title("title") + ,display_children("expanded", true) + ,header_height("header_height", HEADER_HEIGHT), + min_width("min_width", 0), + min_height("min_height", 0) + ,collapsible("collapsible", true) + ,header_bg_color("header_bg_color") + ,dropdown_bg_color("dropdown_bg_color") + ,header_visible("header_visible",true) + ,padding_left("padding_left",2) + ,padding_right("padding_right",2) + ,padding_top("padding_top",2) + ,padding_bottom("padding_bottom",2) + ,header_expand_img("header_expand_img") + ,header_expand_img_pressed("header_expand_img_pressed") + ,header_collapse_img("header_collapse_img") + ,header_collapse_img_pressed("header_collapse_img_pressed") + ,header_image("header_image") + ,header_image_over("header_image_over") + ,header_image_pressed("header_image_pressed") + ,header_image_focused("header_image_focused") + ,header_text_color("header_text_color") + ,fit_panel("fit_panel",true) + ,selection_enabled("selection_enabled", false) +{ + changeDefault(mouse_opaque, false); +} + +LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p) + : LLUICtrl(p) + ,mDisplayChildren(p.display_children) + ,mCollapsible(p.collapsible) + ,mExpandedHeight(0) + ,mDropdownBGColor(p.dropdown_bg_color()) + ,mHeaderVisible(p.header_visible) + ,mPaddingLeft(p.padding_left) + ,mPaddingRight(p.padding_right) + ,mPaddingTop(p.padding_top) + ,mPaddingBottom(p.padding_bottom) + ,mCanOpenClose(true) + ,mFitPanel(p.fit_panel) + ,mSelectionEnabled(p.selection_enabled) + ,mContainerPanel(NULL) + ,mScrollbar(NULL) +{ + mStoredOpenCloseState = false; + mWasStateStored = false; + + mDropdownBGColor = LLColor4::white; + LLAccordionCtrlTabHeader::Params headerParams(p); + headerParams.name(DD_HEADER_NAME); + headerParams.title(p.title); + mHeader = LLUICtrlFactory::create(headerParams); + addChild(mHeader, 1); + + LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLAccordionCtrlTab::selectOnFocusReceived, this)); + + if (!p.selection_enabled) + { + LLFocusableElement::setFocusLostCallback(boost::bind(&LLAccordionCtrlTab::deselectOnFocusLost, this)); + } + + reshape(100, 200,FALSE); +} + +LLAccordionCtrlTab::~LLAccordionCtrlTab() +{ +} + + +void LLAccordionCtrlTab::setDisplayChildren(bool display) +{ + mDisplayChildren = display; + LLRect rect = getRect(); + + rect.mBottom = rect.mTop - (getDisplayChildren() ? + mExpandedHeight : HEADER_HEIGHT); + setRect(rect); + + if(mContainerPanel) + mContainerPanel->setVisible(getDisplayChildren()); + + if(mDisplayChildren) + { + adjustContainerPanel(); + } + else + { + if(mScrollbar) + mScrollbar->setVisible(false); + } + +} + +void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +{ + LLRect headerRect; + + headerRect.setLeftTopAndSize( + 0,height,width,HEADER_HEIGHT); + mHeader->setRect(headerRect); + mHeader->reshape(headerRect.getWidth(), headerRect.getHeight()); + + if(!mDisplayChildren) + return; + + LLRect childRect; + + childRect.setLeftTopAndSize( + getPaddingLeft(), + height - getHeaderHeight() - getPaddingTop(), + width - getPaddingLeft() - getPaddingRight(), + height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() ); + + adjustContainerPanel(childRect); +} + +void LLAccordionCtrlTab::changeOpenClose(bool is_open) +{ + if(is_open) + mExpandedHeight = getRect().getHeight(); + + setDisplayChildren(!is_open); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + if (mCommitSignal) + { + (*mCommitSignal)(this, getDisplayChildren()); + } +} + +/*void LLAccordionCtrlTab::onVisibilityChange(BOOL new_visibility) +{ + LLUICtrl::onVisibilityChange(new_visibility); + + notifyParent(LLSD().with("child_visibility_change", new_visibility)); +}*/ + +BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if(mCollapsible && mHeaderVisible && mCanOpenClose) + { + if(y >= (getRect().getHeight() - HEADER_HEIGHT) ) + { + mHeader->setFocus(true); + changeOpenClose(getDisplayChildren()); + + //reset stored state + mWasStateStored = false; + return TRUE; + } + } + return LLUICtrl::handleMouseDown(x,y,mask); +} + +BOOL LLAccordionCtrlTab::handleMouseUp(S32 x, S32 y, MASK mask) +{ + return LLUICtrl::handleMouseUp(x,y,mask); +} + +boost::signals2::connection LLAccordionCtrlTab::setDropDownStateChangedCallback(commit_callback_t cb) +{ + return setCommitCallback(cb); +} + +bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group) +{ + if(DD_HEADER_NAME != child->getName()) + { + reshape(child->getRect().getWidth() , child->getRect().getHeight() + HEADER_HEIGHT ); + mExpandedHeight = getRect().getHeight(); + } + + bool res = LLUICtrl::addChild(child, tab_group); + + if(DD_HEADER_NAME != child->getName()) + { + if(!mCollapsible) + setDisplayChildren(true); + else + setDisplayChildren(getDisplayChildren()); + } + + if (!mContainerPanel) + mContainerPanel = findContainerView(); + + return res; +} + +void LLAccordionCtrlTab::setAccordionView(LLView* panel) +{ + addChild(panel,0); +} + +std::string LLAccordionCtrlTab::getTitle() const +{ + if (mHeader) + { + return mHeader->getTitle(); + } + else + { + return LLStringUtil::null; + } +} + +void LLAccordionCtrlTab::setTitle(const std::string& title, const std::string& hl) +{ + if (mHeader) + { + mHeader->setTitle(title, hl); + } +} + +void LLAccordionCtrlTab::setTitleFontStyle(std::string style) +{ + if (mHeader) + { + mHeader->setTitleFontStyle(style); + } +} + +void LLAccordionCtrlTab::setTitleColor(LLUIColor color) +{ + if (mHeader) + { + mHeader->setTitleColor(color); + } +} + +boost::signals2::connection LLAccordionCtrlTab::setFocusReceivedCallback(const focus_signal_t::slot_type& cb) +{ + if (mHeader) + { + return mHeader->setFocusReceivedCallback(cb); + } + return boost::signals2::connection(); +} + +boost::signals2::connection LLAccordionCtrlTab::setFocusLostCallback(const focus_signal_t::slot_type& cb) +{ + if (mHeader) + { + return mHeader->setFocusLostCallback(cb); + } + return boost::signals2::connection(); +} + +void LLAccordionCtrlTab::setSelected(bool is_selected) +{ + if (mHeader) + { + mHeader->setSelected(is_selected); + } +} + +LLView* LLAccordionCtrlTab::findContainerView() +{ + for(child_list_const_iter_t it = getChildList()->begin(); + getChildList()->end() != it; ++it) + { + LLView* child = *it; + if(DD_HEADER_NAME == child->getName()) + continue; + if(!child->getVisible()) + continue; + return child; + } + return NULL; +} + +void LLAccordionCtrlTab::selectOnFocusReceived() +{ + if (getParent()) // A parent may not be set if tabs are added dynamically. + getParent()->notifyParent(LLSD().with("action", "select_current")); +} + +void LLAccordionCtrlTab::deselectOnFocusLost() +{ + if(getParent()) // A parent may not be set if tabs are added dynamically. + { + getParent()->notifyParent(LLSD().with("action", "deselect_current")); + } + +} + +S32 LLAccordionCtrlTab::getHeaderHeight() +{ + return mHeaderVisible?HEADER_HEIGHT:0; +} + +void LLAccordionCtrlTab::setHeaderVisible(bool value) +{ + if(mHeaderVisible == value) + return; + mHeaderVisible = value; + if(mHeader) + mHeader->setVisible(value); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); +}; + +//virtual +BOOL LLAccordionCtrlTab::postBuild() +{ + if(mHeader) + mHeader->setVisible(mHeaderVisible); + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + LLRect scroll_rect; + scroll_rect.setOriginAndSize( + getRect().getWidth() - scrollbar_size, + 1, + scrollbar_size, + getRect().getHeight() - 1); + + mContainerPanel = findContainerView(); + + if(!mFitPanel) + { + mScrollbar = new LLScrollbar("scrollable vertical", scroll_rect, LLScrollbar::VERTICAL, getRect().getHeight(), 0, getRect().getHeight(), boost::bind(&LLAccordionCtrlTab::onScrollPosChangeCallback, this, _1, _2), VERTICAL_MULTIPLE); + mScrollbar->setFollows(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + LLView::addChild( mScrollbar ); + mScrollbar->setFollows(FOLLOWS_RIGHT|FOLLOWS_TOP|FOLLOWS_BOTTOM); + + mScrollbar->setVisible(false); + } + + if(mContainerPanel) + mContainerPanel->setVisible(mDisplayChildren); + + return LLUICtrl::postBuild(); +} +bool LLAccordionCtrlTab::notifyChildren (const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "store_state") + { + storeOpenCloseState(); + return true; + } + if(str_action == "restore_state") + { + restoreOpenCloseState(); + return true; + } + } + return LLUICtrl::notifyChildren(info); +} + +S32 LLAccordionCtrlTab::notifyParent(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "size_changes") + { + // + S32 height = info["height"]; + height = llmax(height,10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom(); + + mExpandedHeight = height; + + if(isExpanded()) + { + LLRect panel_rect = getRect(); + panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), height); + reshape(getRect().getWidth(),height); + setRect(panel_rect); + } + + //LLAccordionCtrl should rearrange accordion tab if one of accordion change its size + if (getParent()) // A parent may not be set if tabs are added dynamically. + getParent()->notifyParent(info); + return 1; + } + else if(str_action == "select_prev") + { + showAndFocusHeader(); + return 1; + } + } + else if (info.has("scrollToShowRect")) + { + LLAccordionCtrl* parent = dynamic_cast(getParent()); + if (parent && parent->getFitParent()) + { + // EXT-8285 ('No attachments worn' text appears at the bottom of blank 'Attachments' accordion) + // The problem was in passing message "scrollToShowRect" IN LLAccordionCtrlTab::notifyParent + // FROM child LLScrollContainer TO parent LLAccordionCtrl with "it_parent" set to true. + + // It is wrong notification for parent accordion which leads to recursive call of adjustContainerPanel + // As the result of recursive call of adjustContainerPanel we got LLAccordionCtrlTab + // that reshaped and re-sized with different rectangles. + + // LLAccordionCtrl has own scrollContainer and LLAccordionCtrlTab has own scrollContainer + // both should handle own scroll container's event. + // So, if parent accordion "fit_parent" accordion tab should handle its scroll container events itself. + + return 1; + } + + if (!getDisplayChildren()) + { + // Don't pass scrolling event further if our contents are invisible (STORM-298). + return 1; + } + } + + return LLUICtrl::notifyParent(info); +} + +S32 LLAccordionCtrlTab::notify(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "select_first") + { + showAndFocusHeader(); + return 1; + } + else if( str_action == "select_last" ) + { + if(getDisplayChildren() == false) + { + showAndFocusHeader(); + } + else + { + LLView* view = getAccordionView(); + if(view) + view->notify(LLSD().with("action","select_last")); + } + } + } + return 0; +} + +BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + if( !mHeader->hasFocus() ) + return LLUICtrl::handleKey(key, mask, called_from_parent); + + if ( (key == KEY_RETURN )&& mask == MASK_NONE) + { + changeOpenClose(getDisplayChildren()); + return TRUE; + } + + if ( (key == KEY_ADD || key == KEY_RIGHT)&& mask == MASK_NONE) + { + if(getDisplayChildren() == false) + { + changeOpenClose(getDisplayChildren()); + return TRUE; + } + } + if ( (key == KEY_SUBTRACT || key == KEY_LEFT)&& mask == MASK_NONE) + { + if(getDisplayChildren() == true) + { + changeOpenClose(getDisplayChildren()); + return TRUE; + } + } + + if ( key == KEY_DOWN && mask == MASK_NONE) + { + //if collapsed go to the next accordion + if(getDisplayChildren() == false) + //we processing notifyParent so let call parent directly + getParent()->notifyParent(LLSD().with("action","select_next")); + else + { + getAccordionView()->notify(LLSD().with("action","select_first")); + } + return TRUE; + } + + if ( key == KEY_UP && mask == MASK_NONE) + { + //go to the previous accordion + + //we processing notifyParent so let call parent directly + getParent()->notifyParent(LLSD().with("action","select_prev")); + return TRUE; + } + + return LLUICtrl::handleKey(key, mask, called_from_parent); +} + +void LLAccordionCtrlTab::showAndFocusHeader() +{ + mHeader->setFocus(true); + mHeader->setSelected(mSelectionEnabled); + + LLRect screen_rc; + LLRect selected_rc = mHeader->getRect(); + localRectToScreen(selected_rc, &screen_rc); + + // This call to notifyParent() is intended to deliver "scrollToShowRect" command + // to the parent LLAccordionCtrl so by calling it from the direct parent of this + // accordion tab (assuming that the parent is an LLAccordionCtrl) the calls chain + // is shortened and messages from inside the collapsed tabs are avoided. + // See STORM-536. + getParent()->notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue())); +} +void LLAccordionCtrlTab::storeOpenCloseState() +{ + if(mWasStateStored) + return; + mStoredOpenCloseState = getDisplayChildren(); + mWasStateStored = true; +} + +void LLAccordionCtrlTab::restoreOpenCloseState() +{ + if(!mWasStateStored) + return; + if(getDisplayChildren() != mStoredOpenCloseState) + { + changeOpenClose(getDisplayChildren()); + } + mWasStateStored = false; +} + +void LLAccordionCtrlTab::adjustContainerPanel () +{ + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); + + LLRect child_rect; + child_rect.setLeftTopAndSize( + getPaddingLeft(), + height - getHeaderHeight() - getPaddingTop(), + width - getPaddingLeft() - getPaddingRight(), + height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() ); + + adjustContainerPanel(child_rect); +} + +void LLAccordionCtrlTab::adjustContainerPanel(const LLRect& child_rect) +{ + if(!mContainerPanel) + return; + + if(!mFitPanel) + { + show_hide_scrollbar(child_rect); + updateLayout(child_rect); + } + else + { + mContainerPanel->reshape(child_rect.getWidth(),child_rect.getHeight()); + mContainerPanel->setRect(child_rect); + } +} + +S32 LLAccordionCtrlTab::getChildViewHeight() +{ + if(!mContainerPanel) + return 0; + return mContainerPanel->getRect().getHeight(); +} + +void LLAccordionCtrlTab::show_hide_scrollbar(const LLRect& child_rect) +{ + if(getChildViewHeight() > child_rect.getHeight() ) + showScrollbar(child_rect); + else + hideScrollbar(child_rect); +} +void LLAccordionCtrlTab::showScrollbar(const LLRect& child_rect) +{ + if(!mContainerPanel || !mScrollbar) + return; + bool was_visible = mScrollbar->getVisible(); + mScrollbar->setVisible(true); + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + { + ctrlSetLeftTopAndSize(mScrollbar,child_rect.getWidth()-scrollbar_size, + child_rect.getHeight()-PARENT_BORDER_MARGIN, + scrollbar_size, + child_rect.getHeight()-2*PARENT_BORDER_MARGIN); + } + + LLRect orig_rect = mContainerPanel->getRect(); + + mScrollbar->setPageSize(child_rect.getHeight()); + mScrollbar->setDocParams(orig_rect.getHeight(),mScrollbar->getDocPos()); + + if(was_visible) + { + S32 scroll_pos = llmin(mScrollbar->getDocPos(), orig_rect.getHeight() - child_rect.getHeight() - 1); + mScrollbar->setDocPos(scroll_pos); + } + else//shrink child panel + { + updateLayout(child_rect); + } + +} + +void LLAccordionCtrlTab::hideScrollbar( const LLRect& child_rect ) +{ + if(!mContainerPanel || !mScrollbar) + return; + + if(mScrollbar->getVisible() == false) + return; + mScrollbar->setVisible(false); + mScrollbar->setDocPos(0); + + //shrink child panel + updateLayout(child_rect); +} + +void LLAccordionCtrlTab::onScrollPosChangeCallback(S32, LLScrollbar*) +{ + LLRect child_rect; + + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); + + child_rect.setLeftTopAndSize( + getPaddingLeft(), + height - getHeaderHeight() - getPaddingTop(), + width - getPaddingLeft() - getPaddingRight(), + height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() ); + + updateLayout(child_rect); +} + +void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child) +{ + if (child && child->getVisible() && child->getRect().isValid()) + { + LLRect screen_rect; + localRectToScreen(child->getRect(),&screen_rect); + + if ( root_rect.overlaps(screen_rect) /*&& LLUI::sDirtyRect.overlaps(screen_rect)*/)// Singu TODO: LLUI::sDirtyRect + { + gGL.matrixMode(LLRender::MM_MODELVIEW); + LLUI::pushMatrix(); + { + LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom); + child->draw(); + + } + LLUI::popMatrix(); + } + } +} + +void LLAccordionCtrlTab::draw() +{ + if(mFitPanel) + LLUICtrl::draw(); + else + { + LLRect root_rect = getRootView()->getRect(); + drawChild(root_rect,mHeader); + drawChild(root_rect,mScrollbar ); + { + LLRect child_rect; + + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); + + child_rect.setLeftTopAndSize( + getPaddingLeft(), + height - getHeaderHeight() - getPaddingTop(), + width - getPaddingLeft() - getPaddingRight(), + height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() ); + + LLLocalClipRect clip(child_rect); + drawChild(root_rect,mContainerPanel); + } + } +} + +void LLAccordionCtrlTab::updateLayout ( const LLRect& child_rect ) +{ + LLView* child = getAccordionView(); + if(!mContainerPanel) + return; + + S32 panel_top = child_rect.getHeight(); + S32 panel_width = child_rect.getWidth(); + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + if(mScrollbar && mScrollbar->getVisible() != false) + { + panel_top+=mScrollbar->getDocPos(); + panel_width-=scrollbar_size; + } + + //set sizes for first panels and dragbars + LLRect panel_rect = child->getRect(); + ctrlSetLeftTopAndSize(mContainerPanel,child_rect.mLeft,panel_top,panel_width,panel_rect.getHeight()); +} +void LLAccordionCtrlTab::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height) +{ + if(!panel) + return; + LLRect panel_rect = panel->getRect(); + panel_rect.setLeftTopAndSize( left, top, width, height); + panel->reshape( width, height, 1); + panel->setRect(panel_rect); +} +BOOL LLAccordionCtrlTab::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect) +{ + //header may be not the first child but we need to process it first + if(y >= (getRect().getHeight() - HEADER_HEIGHT - HEADER_HEIGHT/2) ) + { + //inside tab header + //fix for EXT-6619 + mHeader->handleToolTip(x, y, msg, sticky_rect); + return TRUE; + } + return LLUICtrl::handleToolTip(x, y, msg, sticky_rect); +} +BOOL LLAccordionCtrlTab::handleScrollWheel ( S32 x, S32 y, S32 clicks ) +{ + if( LLUICtrl::handleScrollWheel(x,y,clicks)) + { + return TRUE; + } + if( mScrollbar && mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) ) + { + return TRUE; + } + return FALSE; +} + +//static +LLView* LLAccordionCtrlTab::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory* factory) +{ + Params p; + // Singu TODO: Widgets folder for defaults instead of shoving into params here where noted + if (node->hasAttribute("title")) + { + std::string title; + node->getAttributeString("title", title); + p.title(title); + } + + if (node->hasAttribute("expanded")) + { + bool display_children; + node->getAttribute_bool("expanded", display_children); + p.display_children(display_children); + } + + if (node->hasAttribute("header_height")) + { + S32 header_height; + node->getAttributeS32("header_height", header_height); + p.header_height(header_height); + } + + if (node->hasAttribute("min_width")) + { + S32 min_width; + node->getAttributeS32("min_width", min_width); + p.min_width(min_width); + } + + if (node->hasAttribute("min_width")) + { + S32 min_height; + node->getAttributeS32("min_height", min_height); + p.min_height(min_height); + } + + if (node->hasAttribute("collapsible")) + { + bool collapsible; + node->getAttribute_bool("collapsible", collapsible); + p.collapsible(collapsible); + } + + if (node->hasAttribute("header_bg_color")) + { + LLColor4 color; + node->getAttributeColor("header_bg_color", color); + p.header_bg_color(color); + } + else // widget + { + p.header_bg_color(LLUI::sColorsGroup->getColor("ButtonUnselectedBgColor")); // was DkGray2 + } + + if (node->hasAttribute("dropdown_bg_color")) + { + LLColor4 color; + node->getAttributeColor("dropdown_bg_color", color); + p.dropdown_bg_color(color); + } + + if (node->hasAttribute("header_visible")) + { + bool header_visible; + node->getAttribute_bool("header_visible", header_visible); + p.header_visible(header_visible); + } + + if (node->hasAttribute("padding_left")) + { + S32 padding_left; + node->getAttributeS32("padding_left", padding_left); + p.padding_left(padding_left); + } + + if (node->hasAttribute("padding_right")) + { + S32 padding_right; + node->getAttributeS32("padding_right", padding_right); + p.padding_right(padding_right); + } + + if (node->hasAttribute("padding_top")) + { + S32 padding_top; + node->getAttributeS32("padding_top", padding_top); + p.padding_top(padding_top); + } + + if (node->hasAttribute("padding_bottom")) + { + S32 padding_bottom; + node->getAttributeS32("padding_bottom", padding_bottom); + p.padding_bottom(padding_bottom); + } + + if (node->hasAttribute("header_expand_img")) + { + std::string image; + node->getAttributeString("header_expand_img", image); + p.header_expand_img.name(image); + } + else // widget + { + p.header_expand_img.name("Accordion_ArrowOpened_Off"); + } + + if (node->hasAttribute("header_expand_img_pressed")) + { + std::string image; + node->getAttributeString("header_expand_img_pressed", image); + p.header_expand_img_pressed.name(image); + } + else // widget + { + p.header_expand_img_pressed.name("Accordion_ArrowOpened_Press"); + } + + if (node->hasAttribute("header_collapse_img")) + { + std::string image; + node->getAttributeString("header_collapse_img", image); + p.header_collapse_img.name(image); + } + else // widget + { + p.header_collapse_img.name("Accordion_ArrowClosed_Off"); + } + + if (node->hasAttribute("header_collapse_img_pressed")) + { + std::string image; + node->getAttributeString("header_collapse_img_pressed", image); + p.header_collapse_img_pressed.name(image); + } + else // widget + { + p.header_collapse_img_pressed.name("Accordion_ArrowClosed_Press"); + } + + if (node->hasAttribute("header_image")) + { + std::string image; + node->getAttributeString("header_image", image); + p.header_image.name(image); + } + else // widget + { + p.header_image.name("Accordion_Off"); + } + + if (node->hasAttribute("header_image_over")) + { + std::string image; + node->getAttributeString("header_image_over", image); + p.header_image_over.name(image); + } + else // widget + { + p.header_image_over.name("Accordion_Over"); + } + + if (node->hasAttribute("header_image_pressed")) + { + std::string image; + node->getAttributeString("header_image_pressed", image); + p.header_image_pressed.name(image); + } + else // widget + { + p.header_image_pressed.name("Accordion_Press"); + } + + if (node->hasAttribute("header_image_focused")) + { + std::string image; + node->getAttributeString("header_image_focused", image); + p.header_image_focused.name(image); + } + else // widget + { + p.header_image_focused.name("Accordion_Selected"); + } + + if (node->hasAttribute("header_text_color")) + { + LLColor4 color; + node->getAttributeColor("header_text_color", color); + p.header_text_color(color); + } + else // widget + { + p.header_text_color(LLUI::sColorsGroup->getColor("ButtonLabelColor")); // AccordionHeaderTextColor + } + + if (node->hasAttribute("fit_panel")) + { + bool fit_panel; + node->getAttribute_bool("fit_panel", fit_panel); + p.fit_panel(fit_panel); + } + + if (node->hasAttribute("selection_enabled")) + { + bool selection_enabled; + node->getAttribute_bool("selection_enabled", selection_enabled); + p.selection_enabled(selection_enabled); + } + + if (node->hasAttribute("font")) + { + std::string font; + node->getAttributeString("font", font); + p.font.name(font); + } + else // widget + { + p.font.name("SansSerif"); + } + + LLAccordionCtrlTab* ctrl = new LLAccordionCtrlTab(p); + ctrl->initFromXML(node, parent); + return ctrl; +} diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h new file mode 100644 index 0000000000..45321c85c5 --- /dev/null +++ b/indra/llui/llaccordionctrltab.h @@ -0,0 +1,248 @@ +/** + * @file LLAccordionCtrlTab.h + * @brief Collapsible box control implementation + * + * $LicenseInfo:firstyear=2004&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_ACCORDIONCTRLTAB_H_ +#define LL_ACCORDIONCTRLTAB_H_ + +#include +#include "llrect.h" +#include "lluictrl.h" +#include "lluicolor.h" +#include "llstyle.h" + +class LLUICtrlFactory; +class LLUIImage; +class LLButton; +class LLTextBox; +class LLScrollbar; + + + +// LLAccordionCtrlTab is a container for other controls. +// It has a Header, by clicking on which hosted controls are shown or hidden. +// When hosted controls are show - LLAccordionCtrlTab is expanded. +// When hosted controls are hidden - LLAccordionCtrlTab is collapsed. + +class LLAccordionCtrlTab : public LLUICtrl +{ +// Interface +public: + + struct Params + : public LLInitParam::Block + { + Optional display_children, //expanded or collapsed after initialization + collapsible; + + Optional title; + + Optional header_height, + min_width, + min_height; + + // Overlay images (arrows on the left) + Mandatory header_expand_img, + header_expand_img_pressed, + header_collapse_img, + header_collapse_img_pressed; + + // Background images for the accordion tabs + Mandatory header_image, + header_image_over, + header_image_pressed, + header_image_focused; + + Optional header_bg_color, + header_text_color, + dropdown_bg_color; + + Optional header_visible; + + Optional fit_panel; + + Optional selection_enabled; + + Optional padding_left, + padding_right, + padding_top, + padding_bottom; + + Params(); + }; + +// typedef LLDefaultChildRegistry child_registry_t; // Singu TODO: NOTE: This comes in with the VMM merge. + + virtual ~LLAccordionCtrlTab(); + + // Registers callback for expand/collapse events. + boost::signals2::connection setDropDownStateChangedCallback(commit_callback_t cb); + + // Changes expand/collapse state + virtual void setDisplayChildren(bool display); + + // Returns expand/collapse state + virtual bool getDisplayChildren() const {return mDisplayChildren;}; + + //set LLAccordionCtrlTab panel + void setAccordionView(LLView* panel); + LLView* getAccordionView() { return mContainerPanel; }; + + std::string getTitle() const; + + // Set text and highlight substring in LLAccordionCtrlTabHeader + void setTitle(const std::string& title, const std::string& hl = LLStringUtil::null); + + // Set text font style in LLAccordionCtrlTabHeader + void setTitleFontStyle(std::string style); + + // Set text color in LLAccordionCtrlTabHeader + void setTitleColor(LLUIColor color); + + boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb); + boost::signals2::connection setFocusLostCallback(const focus_signal_t::slot_type& cb); + + void setSelected(bool is_selected); + + bool getCollapsible() {return mCollapsible;}; + + void setCollapsible(bool collapsible) {mCollapsible = collapsible;}; + void changeOpenClose(bool is_open); + + void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;}; + bool canOpenClose() const { return mCanOpenClose; }; + + virtual BOOL postBuild(); + static LLView* fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFactory* factory); + + S32 notifyParent(const LLSD& info); + S32 notify(const LLSD& info); + bool notifyChildren(const LLSD& info); + + void draw(); + + void storeOpenCloseState (); + void restoreOpenCloseState (); + +protected: + LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&); + friend class LLUICtrlFactory; + +// Overrides +public: + + // Call reshape after changing size + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + /** + * Raises notifyParent event with "child_visibility_change" = new_visibility + */ + //void onVisibilityChange(BOOL new_visibility); + + // Changes expand/collapse state and triggers expand/collapse callbacks + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + + virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); + virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); + + + virtual bool addChild(LLView* child, S32 tab_group = 0 ); + + bool isExpanded() const { return mDisplayChildren; } + + S32 getHeaderHeight(); + + // Min size functions + + void setHeaderVisible(bool value); + + bool getHeaderVisible() { return mHeaderVisible;} + + S32 mExpandedHeight; // Height of expanded ctrl. + // Used to restore height after expand. + + S32 getPaddingLeft() const { return mPaddingLeft;} + S32 getPaddingRight() const { return mPaddingRight;} + S32 getPaddingTop() const { return mPaddingTop;} + S32 getPaddingBottom() const { return mPaddingBottom;} + + void showAndFocusHeader(); + + void setFitPanel( bool fit ) { mFitPanel = true; } + bool getFitParent() const { return mFitPanel; } + +protected: + void adjustContainerPanel (const LLRect& child_rect); + void adjustContainerPanel (); + S32 getChildViewHeight (); + + void onScrollPosChangeCallback(S32, LLScrollbar*); + + void show_hide_scrollbar (const LLRect& child_rect); + void showScrollbar (const LLRect& child_rect); + void hideScrollbar (const LLRect& child_rect); + + void updateLayout ( const LLRect& child_rect ); + void ctrlSetLeftTopAndSize (LLView* panel, S32 left, S32 top, S32 width, S32 height); + + void drawChild(const LLRect& root_rect,LLView* child); + + LLView* findContainerView (); + + void selectOnFocusReceived(); + void deselectOnFocusLost(); + +private: + + class LLAccordionCtrlTabHeader; + LLAccordionCtrlTabHeader* mHeader; //Header + + bool mDisplayChildren; //Expanded/collapsed + bool mCollapsible; + bool mHeaderVisible; + + bool mCanOpenClose; + bool mFitPanel; + + S32 mPaddingLeft; + S32 mPaddingRight; + S32 mPaddingTop; + S32 mPaddingBottom; + + bool mStoredOpenCloseState; + bool mWasStateStored; + + bool mSelectionEnabled; + + LLScrollbar* mScrollbar; + LLView* mContainerPanel; + + LLUIColor mDropdownBGColor; +}; + +#endif diff --git a/indra/llui/llalertdialog.cpp b/indra/llui/llalertdialog.cpp index 3b4931341e..b7cef0a2ec 100644 --- a/indra/llui/llalertdialog.cpp +++ b/indra/llui/llalertdialog.cpp @@ -48,6 +48,7 @@ #include "lluictrlfactory.h" #include "llnotifications.h" #include "llfunctorregistry.h" +#include "lldraghandle.h" const S32 MAX_ALLOWED_MSG_WIDTH = 400; const F32 DEFAULT_BUTTON_DELAY = 0.5f; @@ -233,6 +234,12 @@ LLAlertDialog::LLAlertDialog( LLNotificationPtr notification, bool modal) msg_box->setColor( LLUI::sColorsGroup->getColor( "AlertTextColor" ) ); } + LLDragHandle* handle = getDragHandle(); + if (handle) + { + getDragHandle()->setTextColor(LLUI::sColorsGroup->getColor(mCaution ? "AlertCautionTextColor" : "AlertTextColor")); + } + LLRect rect; rect.setLeftTopAndSize( msg_x, msg_y, text_rect.getWidth(), text_rect.getHeight() ); msg_box->setRect( rect ); @@ -257,6 +264,10 @@ LLAlertDialog::LLAlertDialog( LLNotificationPtr notification, bool modal) button_data.mText); btn->setClickedCallback(boost::bind(&LLAlertDialog::onButtonPressed, this, _1, button_data.mUrl)); + if (mCaution) + { + btn->setColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor")); + } addChild(btn); @@ -370,6 +381,11 @@ bool LLAlertDialog::setCheckBox( const std::string& check_title, const std::stri max_msg_width, LINE_HEIGHT); mCheck = new LLCheckboxCtrl(std::string("check"), check_rect, check_title, font, boost::bind(&LLAlertDialog::onClickIgnore, this, _1)); + mCheck->setEnabledColor(LLUI::sColorsGroup->getColor( mCaution ? "AlertCautionTextColor" : "AlertTextColor")); + if (mCaution) + { + mCheck->setButtonColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor")); + } addChild(mCheck); return true; diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 7e93d10521..120c378dfa 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -61,66 +61,92 @@ S32 BTN_HEIGHT = 0; S32 BTN_GRID = 12; S32 BORDER_SIZE = 1; + +LLButton::Params::Params() + : label_selected("label_selected"), // requires is_toggle true + label_shadow("label_shadow", true), + auto_resize("auto_resize", false), + use_ellipses("use_ellipses", false), + image_unselected("image_unselected", LLUI::getUIImage("button_enabled_32x128.tga")), + image_selected("image_selected", LLUI::getUIImage("button_enabled_selected_32x128.tga")), + image_hover_selected("image_hover_selected"), + image_hover_unselected("image_hover_unselected"), + image_disabled_selected("image_disabled_selected", LLUI::getUIImage("button_disabled_32x128.tga")), + image_disabled("image_disabled", LLUI::getUIImage("button_disabled_32x128.tga")), + image_pressed("image_pressed", LLUI::getUIImage("button_enabled_selected_32x128.tga")), + image_pressed_selected("image_pressed_selected", LLUI::getUIImage("button_enabled_32x128.tga")), + image_overlay("image_overlay"), + image_overlay_selected("image_overlay_selected"), + image_overlay_alignment("image_overlay_alignment", std::string("center")), + image_overlay_enable("image_overlay_enable", true), + label_color("label_color", LLUI::sColorsGroup->getColor("ButtonLabelColor")), + label_color_selected("label_color_selected", LLUI::sColorsGroup->getColor("ButtonLabelSelectedColor")), + label_color_disabled("label_color_disabled", LLUI::sColorsGroup->getColor("ButtonLabelDisabledColor")), + label_color_disabled_selected("label_color_disabled_selected", LLUI::sColorsGroup->getColor("ButtonLabelSelectedDisabledColor")), + image_color("image_color", LLUI::sColorsGroup->getColor("ButtonImageColor")), // requires is_toggle true + image_color_disabled("image_color_disabled", LLUI::sColorsGroup->getColor("ButtonImageColor")), + image_overlay_color("image_overlay_color", LLColor4::white), + image_overlay_selected_color("image_overlay_selected_color", LLColor4::white), + image_overlay_disabled_color("image_overlay_disabled_color", LLColor4(1.f, 1.f, 1.f, .5f)), + flash_color("flash_color", LLUI::sColorsGroup->getColor("ButtonFlashBgColor")), + pad_right("pad_right", LLUI::sConfigGroup->getS32("ButtonHPad")), + pad_left("pad_left", LLUI::sConfigGroup->getS32("ButtonHPad")), + pad_bottom("pad_bottom", LLUI::sConfigGroup->getS32("ButtonVPad")), + image_top_pad("image_top_pad"), + image_bottom_pad("image_bottom_pad"), + imgoverlay_label_space("imgoverlay_label_space", 1), + click_callback("click_callback"), + mouse_down_callback("mouse_down_callback"), + mouse_up_callback("mouse_up_callback"), + mouse_held_callback("mouse_held_callback"), + is_toggle("is_toggle", false), + scale_image("scale_image", true), + commit_on_return("commit_on_return", true), + display_pressed_state("display_pressed_state", true), + hover_glow_amount("hover_glow_amount", 0.25f), + //held_down_delay("held_down_delay"), + use_draw_context_alpha("use_draw_context_alpha", true), + //badge("badge"), + handle_right_mouse("handle_right_mouse", false), + button_flash_enable("button_flash_enable", false), + button_flash_count("button_flash_count", LLUI::sConfigGroup->getS32("ButtonFlashCount")), + button_flash_rate("button_flash_rate", LLUI::sConfigGroup->getF32("ButtonFlashRate")), + fade_when_disabled("fade_when_disabled", false), + help_url("help_url") +{ + addSynonym(is_toggle, "toggle"); + changeDefault(initial_value, LLSD(false)); + changeDefault(font_halign, LLFontGL::HCENTER); +} + LLButton::LLButton( const std::string& name, const LLRect& rect, const std::string& control_name, commit_callback_t commit_callback) : LLUICtrl(name, rect, TRUE, commit_callback), - - mMouseDownFrame( 0 ), + mMouseDownFrame(0), mMouseHeldDownCount(0), - mBorderEnabled( FALSE ), - mFlashing( FALSE ), + mBorderEnabled(FALSE), + mFlashing(FALSE), mCurGlowStrength(0.f), mNeedsHighlight(FALSE), - mUnselectedLabel(name), - mSelectedLabel(name), - mGLFont( LLFontGL::getFontSansSerif() ), - mHeldDownDelay( 0.5f ), // seconds until held-down callback is called - mHeldDownFrameDelay( 0 ), - mImageUnselected(LLUI::getUIImage("button_enabled_32x128.tga")), - mImageSelected(LLUI::getUIImage("button_enabled_selected_32x128.tga")), - mImageDisabled(LLUI::getUIImage("button_disabled_32x128.tga")), - mImageDisabledSelected(LLUI::getUIImage("button_disabled_32x128.tga")), - mImagePressed(LLUI::getUIImage("button_enabled_selected_32x128.tga")), - mImagePressedSelected(LLUI::getUIImage("button_enabled_32x128.tga")), + mHeldDownDelay(0.5f), // seconds until held-down callback is called + mHeldDownFrameDelay(0), mImageFlash(NULL), - mImageHoverSelected( NULL ), - mImageHoverUnselected( NULL ), - mUnselectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelColor" )), - mSelectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelSelectedColor")), - mDisabledLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelDisabledColor")), - mDisabledSelectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelSelectedDisabledColor")), - mImageColor(LLUI::sColorsGroup->getColor("ButtonImageColor")), - mFlashBgColor(LLUI::sColorsGroup->getColor("ButtonFlashBgColor")), - mDisabledImageColor(LLUI::sColorsGroup->getColor("ButtonImageColor")), - mImageOverlay(NULL), - mImageOverlayColor(LLColor4::white), - mImageOverlayDisabledColor(LLColor4(1.f,1.f,1.f,.5f)), - mImageOverlaySelectedColor(LLColor4::white), - mImageOverlayAlignment(LLFontGL::HCENTER), mImageOverlayTopPad(0), mImageOverlayBottomPad(0), mImgOverlayLabelSpace(1), - mIsToggle( FALSE ), - mScaleImage( TRUE ), - mDropShadowedText( TRUE ), - mAutoResize( FALSE ), - mHAlign( LLFontGL::HCENTER ), - mLeftHPad( LLBUTTON_H_PAD ), - mRightHPad( LLBUTTON_H_PAD ), - mBottomVPad( LLBUTTON_V_PAD ), - mHoverGlowStrength(0.25f), - mCommitOnReturn(TRUE), - mFadeWhenDisabled(FALSE), + mDropShadowedText(TRUE), mForcePressedState(false), - mDisplayPressedState(TRUE), - mMouseDownSignal(NULL), - mMouseUpSignal(NULL), - mHeldDownSignal(NULL), - mHandleRightMouse(false), - mButtonFlashCount(LLUI::sConfigGroup->getS32("ButtonFlashCount")), - mButtonFlashRate(LLUI::sConfigGroup->getF32("ButtonFlashRate")), - mAlpha(1.f) + mAlpha(1.f), + mMouseDownSignal(nullptr), + mMouseUpSignal(nullptr), + mHeldDownSignal(nullptr) { - init(control_name); + Params params; + params.label_selected(name) + .label(name) + .control_name(control_name) + .name(name) + .rect(rect); + initFromParams(params); } @@ -133,92 +159,133 @@ LLButton::LLButton(const std::string& name, const LLRect& rect, const std::string& unselected_label, const std::string& selected_label ) : LLUICtrl(name, rect, TRUE, commit_callback), - mMouseDownFrame( 0 ), + mMouseDownFrame(0), mMouseHeldDownCount(0), - mBorderEnabled( FALSE ), - mFlashing( FALSE ), + mBorderEnabled(FALSE), + mFlashing(FALSE), mCurGlowStrength(0.f), mNeedsHighlight(FALSE), - mUnselectedLabel(unselected_label), - mSelectedLabel(selected_label), - mGLFont( font ? font : LLFontGL::getFontSansSerif() ), - mHeldDownDelay( 0.5f ), // seconds until held-down callback is called - mHeldDownFrameDelay( 0 ), - mImageUnselected(LLUI::getUIImage("button_enabled_32x128.tga")), - mImageSelected(LLUI::getUIImage("button_enabled_selected_32x128.tga")), - mImageDisabled(LLUI::getUIImage("button_disabled_32x128.tga")), - mImageDisabledSelected(LLUI::getUIImage("button_disabled_32x128.tga")), - mImagePressed(LLUI::getUIImage("button_enabled_selected_32x128.tga")), - mImagePressedSelected(LLUI::getUIImage("button_enabled_32x128.tga")), + mHeldDownDelay(0.5f), // seconds until held-down callback is called + mHeldDownFrameDelay(0), mImageFlash(NULL), - mImageHoverSelected( NULL ), - mImageHoverUnselected( NULL ), - mUnselectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelColor" )), - mSelectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelSelectedColor")), - mDisabledLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelDisabledColor")), - mDisabledSelectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelSelectedDisabledColor")), - mImageColor(LLUI::sColorsGroup->getColor("ButtonImageColor")), - mFlashBgColor(LLUI::sColorsGroup->getColor("ButtonFlashBgColor")), - mDisabledImageColor(LLUI::sColorsGroup->getColor("ButtonImageColor")), - mImageOverlay(NULL), - mImageOverlayColor(LLColor4::white), - mImageOverlayDisabledColor(LLColor4(1.f,1.f,1.f,.5f)), - mImageOverlaySelectedColor(LLColor4::white), - mImageOverlayAlignment(LLFontGL::HCENTER), mImageOverlayTopPad(0), mImageOverlayBottomPad(0), mImgOverlayLabelSpace(1), - mIsToggle( FALSE ), - mScaleImage( TRUE ), - mDropShadowedText( TRUE ), - mAutoResize( FALSE ), - mHAlign( LLFontGL::HCENTER ), - mLeftHPad( LLBUTTON_H_PAD ), - mRightHPad( LLBUTTON_H_PAD ), - mBottomVPad( LLBUTTON_V_PAD ), - mHoverGlowStrength(0.25f), - mCommitOnReturn(TRUE), - mFadeWhenDisabled(FALSE), + mDropShadowedText(TRUE), mForcePressedState(false), - mDisplayPressedState(TRUE), - mMouseDownSignal(NULL), - mMouseUpSignal(NULL), - mHeldDownSignal(NULL), - mHandleRightMouse(false), - mButtonFlashCount(LLUI::sConfigGroup->getS32("ButtonFlashCount")), - mButtonFlashRate(LLUI::sConfigGroup->getF32("ButtonFlashRate")), - mAlpha(1.f) + mAlpha(1.f), + mMouseDownSignal(nullptr), + mMouseUpSignal(nullptr), + mHeldDownSignal(nullptr) { - - if( unselected_image_name != "" ) + Params params; + params.label_selected(selected_label) + .label(unselected_label) + .font(font) + .control_name(control_name) + .name(name) + .rect(rect); + + if (!unselected_image_name.empty()) { // user-specified image - don't use fixed borders unless requested - mImageUnselected = LLUI::getUIImage(unselected_image_name); - mImageDisabled = mImageUnselected; + auto image = LLUI::getUIImage(unselected_image_name); + params.image_unselected(image) + .image_disabled(image) + .image_pressed_selected(image) - mFadeWhenDisabled = TRUE; - //mScaleImage = FALSE; - - mImagePressedSelected = mImageUnselected; + .fade_when_disabled(true); + //params.scale_image(false); } - if( selected_image_name != "" ) + if (!selected_image_name.empty()) { // user-specified image - don't use fixed borders unless requested - mImageSelected = LLUI::getUIImage(selected_image_name); - mImageDisabledSelected = mImageSelected; + auto image = LLUI::getUIImage(selected_image_name); + params.image_selected(image) + .image_disabled_selected(image) + .image_pressed(image) - mFadeWhenDisabled = TRUE; - //mScaleImage = FALSE; - - mImagePressed = mImageSelected; + .fade_when_disabled(true); + //params.scale_image(false); } - init(control_name); + initFromParams(params); } -void LLButton::init(const std::string& control_name) +LLButton::LLButton(const Params& params) +: LLUICtrl(params), + mMouseDownFrame(0), + mMouseHeldDownCount(0), + mBorderEnabled(FALSE), + mFlashing(FALSE), + mCurGlowStrength(0.f), + mNeedsHighlight(FALSE), + mHeldDownDelay(0.5f), // seconds until held-down callback is called + mHeldDownFrameDelay(0), + mImageFlash(NULL), + mImageOverlayTopPad(0), + mImageOverlayBottomPad(0), + mImgOverlayLabelSpace(1), + mDropShadowedText(TRUE), + mForcePressedState(false), + mAlpha(1.f), + mMouseDownSignal(nullptr), + mMouseUpSignal(nullptr), + mHeldDownSignal(nullptr) { + initFromParams(params); +} + +void LLButton::initFromParams(const Params& params) +{ + LLUICtrl::initFromParams(params); + mUnselectedLabel = params.label; + mSelectedLabel = params.label_selected; + auto font = params.font(); + mGLFont = font ? font : LLFontGL::getFontSansSerif(); + mHAlign = params.font_halign; + mImageUnselected = params.image_unselected; + mImageSelected = params.image_selected; + mImageDisabled = params.image_disabled; + mImageDisabledSelected = params.image_disabled_selected; + mImagePressed = params.image_pressed; + mImagePressedSelected = params.image_pressed_selected; + mImageHoverSelected = params.image_hover_selected; + mImageHoverUnselected = params.image_hover_unselected; + mUnselectedLabelColor = params.label_color; + mSelectedLabelColor = params.label_color_selected; + mDisabledLabelColor = params.label_color_disabled; + mDisabledSelectedLabelColor = params.label_color_disabled_selected; + mImageColor = params.image_color; + mFlashBgColor = params.flash_color; + mDisabledImageColor = params.image_color_disabled; + mImageOverlay = params.image_overlay; + mImageOverlaySelected = params.image_overlay_selected; + mImageOverlayColor = params.image_overlay_color; + mImageOverlayDisabledColor = params.image_overlay_disabled_color; + mImageOverlaySelectedColor = params.image_overlay_selected_color; + mImageOverlayAlignment = LLFontGL::hAlignFromName(params.image_overlay_alignment); + mIsToggle = params.is_toggle; + mScaleImage = params.scale_image; + mAutoResize = params.auto_resize; + mLeftHPad = params.pad_left; + mRightHPad = params.pad_right; + mBottomVPad = params.pad_bottom; + mHoverGlowStrength = params.hover_glow_amount; + mCommitOnReturn = params.commit_on_return; + mFadeWhenDisabled = params.fade_when_disabled; + mDisplayPressedState = params.display_pressed_state; + if (params.mouse_down_callback.isProvided()) + setMouseDownCallback(params.mouse_down_callback); + if (params.mouse_up_callback.isProvided()) + setMouseUpCallback(params.mouse_up_callback); + if (params.mouse_held_callback.isProvided()) + setHeldDownCallback(params.mouse_held_callback); + mHandleRightMouse = params.handle_right_mouse; + mButtonFlashCount = params.button_flash_count; + mButtonFlashRate = params.button_flash_rate; + // Hack to make sure there is space for at least one character if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) { @@ -229,9 +296,16 @@ void LLButton::init(const std::string& control_name) mMouseDownTimer.stop(); - setControlName(control_name, NULL); + setControlName(params.control_name, NULL); } +//static +const LLButton::Params& LLButton::getDefaultParams() +{ + // Singu Note: We diverge here, not using LLUICtrlFactory::getDefaultParams + static const Params p; + return p; +} // virtual LLButton::~LLButton() @@ -387,7 +461,7 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) if(mMouseDownSignal) (*mMouseDownSignal)(this, LLSD()); mMouseDownTimer.start(); - mMouseDownFrame = (S32) LLFrameTimer::getFrameCount(); + mMouseDownFrame = LLFrameTimer::getFrameCount(); mMouseHeldDownCount = 0; @@ -515,7 +589,7 @@ BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) if (mMouseDownTimer.getStarted()) { F32 elapsed = getHeldDownTime(); - if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= (S32)LLFrameTimer::getFrameCount() - mMouseDownFrame) + if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= LLFrameTimer::getFrameCount() - mMouseDownFrame) { LLSD param; param["count"] = mMouseHeldDownCount++; @@ -704,11 +778,11 @@ void LLButton::draw() mCurGlowStrength = lerp(mCurGlowStrength, mFlashing ? (flash? 1.0 : 0.0) : mHoverGlowStrength, - LLCriticalDamp::getInterpolant(0.05f)); + LLSmoothInterpolation::getInterpolant(0.05f)); } else { - mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLCriticalDamp::getInterpolant(0.05f)); + mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLSmoothInterpolation::getInterpolant(0.05f)); } // Draw button image, if available. @@ -783,12 +857,13 @@ void LLButton::draw() } overlay_color.mV[VALPHA] *= alpha; + auto& overlay = (mIsToggle && mImageOverlaySelected && getToggleState()) ? mImageOverlaySelected : mImageOverlay; switch(mImageOverlayAlignment) { case LLFontGL::LEFT: text_left += overlay_width + mImgOverlayLabelSpace; text_width -= overlay_width + mImgOverlayLabelSpace; - mImageOverlay->draw( + overlay->draw( mLeftHPad, center_y - (overlay_height / 2), overlay_width, @@ -796,7 +871,7 @@ void LLButton::draw() overlay_color); break; case LLFontGL::HCENTER: - mImageOverlay->draw( + overlay->draw( center_x - (overlay_width / 2), center_y - (overlay_height / 2), overlay_width, @@ -806,7 +881,7 @@ void LLButton::draw() case LLFontGL::RIGHT: text_right -= overlay_width + mImgOverlayLabelSpace; text_width -= overlay_width + mImgOverlayLabelSpace; - mImageOverlay->draw( + overlay->draw( getRect().getWidth() - mRightHPad - overlay_width, center_y - (overlay_height / 2), overlay_width, @@ -1199,6 +1274,9 @@ LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa std::string image_overlay; node->getAttributeString("image_overlay", image_overlay); + std::string image_overlay_selected; + node->getAttributeString("image_overlay_selected", image_overlay_selected); + LLFontGL::HAlign image_overlay_alignment = LLFontGL::HCENTER; std::string image_overlay_alignment_string; if (node->hasAttribute("image_overlay_alignment")) @@ -1234,6 +1312,7 @@ LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa if(image_disabled != LLStringUtil::null) button->setImageDisabled(LLUI::getUIImage(image_disabled)); if(image_overlay != LLStringUtil::null) button->setImageOverlay(image_overlay, image_overlay_alignment); + if (!image_overlay_selected.empty()) button->mImageOverlaySelected = LLUI::getUIImage(image_overlay_selected); if (node->hasAttribute("halign")) { diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 1495740c6d..dfa405f63a 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -74,6 +74,87 @@ class LLButton : public LLUICtrl { public: + struct Params + : public LLInitParam::Block + { + // text label + Optional label_selected; + Optional label_shadow; + Optional auto_resize; + Optional use_ellipses; + + // images + Optional image_unselected, + image_selected, + image_hover_selected, + image_hover_unselected, + image_disabled_selected, + image_disabled, + image_flash, + image_pressed, + image_pressed_selected, + image_overlay, + image_overlay_selected; + + Optional image_overlay_alignment; + Optional image_overlay_enable; + + // colors + Optional label_color, + label_color_selected, + label_color_disabled, + label_color_disabled_selected, + image_color, + image_color_disabled, + image_overlay_color, + image_overlay_selected_color, + image_overlay_disabled_color, + flash_color; + + // layout + Optional pad_right; + Optional pad_left; + Optional pad_bottom; // under text label + + //image overlay paddings + Optional image_top_pad; + Optional image_bottom_pad; + + /** + * Space between image_overlay and label + */ + Optional imgoverlay_label_space; + + // callbacks + Optional click_callback, // alias -> commit_callback + mouse_down_callback, + mouse_up_callback, + mouse_held_callback; + + // misc + Optional is_toggle, + scale_image, + commit_on_return, + display_pressed_state; + + Optional hover_glow_amount; + //Optional held_down_delay; + + Optional use_draw_context_alpha; + + //Optional badge; + + Optional handle_right_mouse; + + Optional button_flash_enable; + Optional button_flash_count; + Optional button_flash_rate; + Optional fade_when_disabled; + Optional help_url; + + Params(); + }; + // simple button with text label LLButton(const std::string& name, const LLRect &rect = LLRect(), const std::string& control_name = std::string(), commit_callback_t commit_callback = NULL); @@ -86,6 +167,11 @@ class LLButton const LLFontGL* mGLFont = NULL, const std::string& unselected_label = LLStringUtil::null, const std::string& selected_label = LLStringUtil::null ); + + void initFromParams(const Params& p); + static const LLButton::Params& getDefaultParams(); + LLButton(const Params& p = getDefaultParams()); + public: ~LLButton(); @@ -93,7 +179,6 @@ class LLButton typedef boost::function button_callback_t; void addImageAttributeToXML(LLXMLNodePtr node, const LLPointer, const std::string& xmlTagName) const; - void init(const std::string& control_name); virtual LLXMLNodePtr getXML(bool save_children = true) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); @@ -161,7 +246,6 @@ class LLButton const std::string getLabelUnselected() const { return wstring_to_utf8str(mUnselectedLabel); } const std::string getLabelSelected() const { return wstring_to_utf8str(mSelectedLabel); } - void setImageColor(const std::string& color_control); void setImageColor(const LLColor4& c); /*virtual*/ void setColor(const LLColor4& c); @@ -205,9 +289,7 @@ class LLButton void setImageDisabled(LLPointer image); void setImageDisabledSelected(LLPointer image); void setImageFlash(LLPointer image); - void setImagePressed(LLPointer image); - - static void onHeldDown(void *userdata); // to be called by gIdleCallbacks + void setHelpURLCallback(const std::string &help_url); const std::string& getHelpURL() const { return mHelpURL; } @@ -237,12 +319,13 @@ class LLButton const LLFontGL *mGLFont; - S32 mMouseDownFrame; + U64 mMouseDownFrame; S32 mMouseHeldDownCount; // Counter for parameter passed to held-down callback F32 mHeldDownDelay; // seconds, after which held-down callbacks get called S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called LLPointer mImageOverlay; + LLPointer mImageOverlaySelected; LLFontGL::HAlign mImageOverlayAlignment; LLUIColor mImageOverlayColor; LLUIColor mImageOverlaySelectedColor; diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index e8e34e64d3..ad0166f4e9 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -93,13 +93,14 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const std::string& name, const LLRect& rect, // *HACK Get rid of this with SL-55508... // this allows blank check boxes and radio boxes for now - std::string local_label = label; + // Singu Note: Don't do this. Slows rendering down dramatically, and also seems to not fix anything? + /*std::string local_label = label; if(local_label.empty()) { local_label = " "; - } + }*/ - mLabel = new LLTextBox( std::string("CheckboxCtrl Label"), label_rect, local_label, mFont ); + mLabel = new LLTextBox( std::string("CheckboxCtrl Label"), label_rect, label, mFont ); mLabel->setFollowsLeft(); mLabel->setFollowsBottom(); addChild(mLabel); diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index 47eb46670a..c0fdf842dc 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -100,8 +100,10 @@ class LLCheckBoxCtrl // LLCheckBoxCtrl interface virtual BOOL toggle() { return mButton->toggleState(); } // returns new state - void setEnabledColor( const LLColor4 &color ) { mTextEnabledColor = color; } - void setDisabledColor( const LLColor4 &color ) { mTextDisabledColor = color; } + void setEnabledColor(const LLColor4 &color) { mTextEnabledColor = color; setEnabled(getEnabled()); } + void setDisabledColor( const LLColor4 &color ) { mTextDisabledColor = color; setEnabled(getEnabled()); } + + void setButtonColor(const LLColor4 &color) { if (mButton) mButton->setColor(color); } void setLabel( const LLStringExplicit& label ); std::string getLabel() const; diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 65a03b0b56..284aa77506 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -200,9 +200,14 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory * // if we haven't already gotten a value from our control_name and // if providing user text entry or descriptive label // don't select an item under the hood - if (combo_box->getControlName().empty() && !combo_box->acceptsTextInput() && combo_box->mLabel.empty()) + if (combo_box->getControlName().empty()) { - combo_box->selectFirstItem(); + const auto text = combo_box->acceptsTextInput(); + std::string label; + if (node->getAttributeString("label", label)) + text ? combo_box->setLabel(label) : (void)combo_box->mList->selectItemByLabel(label, FALSE); + else if (!text && combo_box->mLabel.empty()) + combo_box->selectFirstItem(); } return combo_box; @@ -436,12 +441,12 @@ void LLComboBox::setLabel(const LLStringExplicit& name) { if (!mSuppressTentative) mTextEntry->setTentative(mTextEntryTentative); } + mTextEntry->setCursor(0); // Be scrolled to the beginning! } if (!mAllowTextEntry) { - mButton->setLabelUnselected(name); - mButton->setLabelSelected(name); + mButton->setLabel(name); } } @@ -459,9 +464,7 @@ void LLComboBox::updateLabel() // the combo button label. if (!mAllowTextEntry) { - std::string label = getSelectedItemLabel(); - mButton->setLabelUnselected(label); - mButton->setLabelSelected(label); + mButton->setLabel(getSelectedItemLabel()); } } @@ -507,13 +510,16 @@ void LLComboBox::onFocusLost() void LLComboBox::setButtonVisible(BOOL visible) { + static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); + mButton->setVisible(visible); if (mTextEntry) { LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); if (visible) { - text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton"); + S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; } //mTextEntry->setRect(text_entry_rect); mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); @@ -552,18 +558,21 @@ S32 LLComboBox::getCurrentIndex() const void LLComboBox::updateLayout() { + static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); LLRect rect = getLocalRect(); if (mAllowTextEntry) { - S32 shadow_size = LLUI::sConfigGroup->getS32("DropShadowButton"); - mButton->setRect(LLRect( getRect().getWidth() - llmax(8,mArrowImage->getWidth()) - 2 * shadow_size, + S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; + S32 shadow_size = drop_shadow_button; + mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size, rect.mTop, rect.mRight, rect.mBottom)); mButton->setTabStop(FALSE); + mButton->setHAlign(LLFontGL::HCENTER); if (!mTextEntry) { LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * shadow_size; + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; // clear label on button std::string cur_label = mButton->getLabelSelected(); mTextEntry = new LLLineEditor(std::string("combo_text_entry"), @@ -712,6 +721,7 @@ void LLComboBox::showList() mList->setVisible(TRUE); setUseBoundingRect(TRUE); +// updateBoundingRect(); } void LLComboBox::hideList() @@ -738,6 +748,7 @@ void LLComboBox::hideList() { gFocusMgr.setTopCtrl(NULL); } +// updateBoundingRect(); } } @@ -1023,9 +1034,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor) void LLComboBox::updateSelection() { - if(mSuppressAutoComplete) { - return; - } + if(mSuppressAutoComplete) return; LLWString left_wstring = mTextEntry->getWText().substr(0, mTextEntry->getCursor()); // user-entered portion of string, based on assumption that any selected @@ -1236,3 +1245,25 @@ BOOL LLComboBox::selectItemRange( S32 first, S32 last ) return mList->selectItemRange(first, last); } + +/* Singu Note: This isn't very necessary for now, let's not bother. +static LLRegisterWidget register_icons_combo_box("icons_combo_box"); + +LLIconsComboBox::Params::Params() +: icon_column("icon_column", ICON_COLUMN), + label_column("label_column", LABEL_COLUMN) +{} + +LLIconsComboBox::LLIconsComboBox(const LLIconsComboBox::Params& p) +: LLComboBox(p), + mIconColumnIndex(p.icon_column), + mLabelColumnIndex(p.label_column) +{} + +const std::string LLIconsComboBox::getSelectedItemLabel(S32 column) const +{ + mButton->setImageOverlay(LLComboBox::getSelectedItemLabel(mIconColumnIndex), mButton->getImageOverlayHAlign()); + + return LLComboBox::getSelectedItemLabel(mLabelColumnIndex); +} +*/ diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 929548137e..741f1c6943 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -301,6 +301,13 @@ BOOL LLDragHandle::handleMouseUp(S32 x, S32 y, MASK mask) return TRUE; } +void LLDragHandle::setTextColor(const LLColor4& color) +{ + if (mTitleBox) + { + mTitleBox->setColor(color); + } +} BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask) { diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index 9eb3e55a6c..a573d458d5 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -63,6 +63,8 @@ class LLDragHandle : public LLView virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual void setTextColor(const LLColor4& color); + protected: LLTextBox* getTitleBox() const { return mTitleBox; } void setTitleBox(LLTextBox*); diff --git a/indra/llui/lleditmenuhandler.h b/indra/llui/lleditmenuhandler.h index d72283cd99..966ab352e5 100644 --- a/indra/llui/lleditmenuhandler.h +++ b/indra/llui/lleditmenuhandler.h @@ -49,7 +49,7 @@ class LLEditMenuHandler virtual void cut() {}; virtual BOOL canCut() const { return FALSE; } - virtual void copy() {}; + virtual void copy() const {}; virtual BOOL canCopy() const { return FALSE; } virtual void paste() {}; diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp new file mode 100644 index 0000000000..205bea49d3 --- /dev/null +++ b/indra/llui/llflatlistview.cpp @@ -0,0 +1,1464 @@ +/** + * @file llflatlistview.cpp + * @brief LLFlatListView base class and extension to support messages for several cases of an empty list. + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llpanel.h" +#include "lltextbox.h" +#include "lluictrlfactory.h" + +#include "llflatlistview.h" + +static const LLRegisterWidget flat_list_view("flat_list_view"); + +const LLSD SELECTED_EVENT = LLSD().with("selected", true); +const LLSD UNSELECTED_EVENT = LLSD().with("selected", false); + +//forward declaration +bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2); + +LLFlatListView::Params::Params() +: allow_select("allow_select"), + multi_select("multi_select"), + keep_one_selected("keep_one_selected"), + keep_selection_visible_on_reshape("keep_selection_visible_on_reshape",false), + item_pad("item_pad"), + no_items_text("no_items_text") +{}; + +void LLFlatListView::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +{ + S32 delta = height - getRect().getHeight(); + LLScrollContainer::reshape(width, height, called_from_parent); + setItemsNoScrollWidth(width); + rearrangeItems(); + + if (delta!= 0 && mKeepSelectionVisibleOnReshape) + { + ensureSelectedVisible(); + } +} + +const LLRect& LLFlatListView::getItemsRect() const +{ + return mItemsPanel->getRect(); +} + +bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/,bool rearrange /*= true*/) +{ + if (!item) return false; + if (value.isUndefined()) return false; + + //force uniqueness of items, easiest check but unreliable + if (item->getParent() == mItemsPanel) return false; + + item_pair_t* new_pair = new item_pair_t(item, value); + switch (pos) + { + case ADD_TOP: + mItemPairs.push_front(new_pair); + //in LLView::draw() children are iterated in backorder + mItemsPanel->addChildInBack(item); + break; + case ADD_BOTTOM: + mItemPairs.push_back(new_pair); + mItemsPanel->addChild(item); + break; + default: + break; + } + + //_4 is for MASK + item->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); + item->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); + + // Children don't accept the focus + item->setTabStop(false); + + if (rearrange) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + } + return true; +} + +bool LLFlatListView::addItemPairs(pairs_list_t panel_list, bool rearrange /*= true*/) +{ + if (!mItemComparator) + { + LL_WARNS_ONCE() << "No comparator specified for inserting FlatListView items." << LL_ENDL; + return false; + } + if (panel_list.size() == 0) + { + return false; + } + + // presort list so that it will be easier to sort elements into mItemPairs + panel_list.sort(ComparatorAdaptor(*mItemComparator)); + + pairs_const_iterator_t new_pair_it = panel_list.begin(); + item_pair_t* new_pair = *new_pair_it; + pairs_iterator_t pair_it = mItemPairs.begin(); + item_pair_t* item_pair = *pair_it; + + // sort panel_list into mItemPars + while (new_pair_it != panel_list.end() && pair_it != mItemPairs.end()) + { + if (!new_pair->first || new_pair->first->getParent() == mItemsPanel) + { + // iterator already used or we are reusing existing panel + new_pair_it++; + new_pair = *new_pair_it; + } + else if (mItemComparator->compare(new_pair->first, item_pair->first)) + { + LLPanel* panel = new_pair->first; + + mItemPairs.insert(pair_it, new_pair); + mItemsPanel->addChild(panel); + + //_4 is for MASK + panel->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); + panel->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); + // Children don't accept the focus + panel->setTabStop(false); + } + else + { + pair_it++; + item_pair = *pair_it; + } + } + + // Add what is left of panel_list into the end of mItemPairs. + for (; new_pair_it != panel_list.end(); ++new_pair_it) + { + item_pair_t* item_pair = *new_pair_it; + LLPanel *panel = item_pair->first; + if (panel && panel->getParent() != mItemsPanel) + { + mItemPairs.push_back(item_pair); + mItemsPanel->addChild(panel); + + //_4 is for MASK + panel->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, item_pair, _4)); + panel->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, item_pair, _4)); + // Children don't accept the focus + panel->setTabStop(false); + } + } + + if (rearrange) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + } + return true; +} + + +bool LLFlatListView::insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value /*= LLUUID::null*/) +{ + if (!after_item) return false; + if (!item_to_add) return false; + if (value.isUndefined()) return false; + + if (mItemPairs.empty()) return false; + + //force uniqueness of items, easiest check but unreliable + if (item_to_add->getParent() == mItemsPanel) return false; + + item_pair_t* after_pair = getItemPair(after_item); + if (!after_pair) return false; + + item_pair_t* new_pair = new item_pair_t(item_to_add, value); + if (after_pair == mItemPairs.back()) + { + mItemPairs.push_back(new_pair); + mItemsPanel->addChild(item_to_add); + } + else + { + pairs_iterator_t it = mItemPairs.begin(); + for (; it != mItemPairs.end(); ++it) + { + if (*it == after_pair) + { + // insert new elements before the element at position of passed iterator. + mItemPairs.insert(++it, new_pair); + mItemsPanel->addChild(item_to_add); + break; + } + } + } + + //_4 is for MASK + item_to_add->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); + item_to_add->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); + + rearrangeItems(); + notifyParentItemsRectChanged(); + return true; +} + + +bool LLFlatListView::removeItem(LLPanel* item, bool rearrange) +{ + if (!item) return false; + if (item->getParent() != mItemsPanel) return false; + + item_pair_t* item_pair = getItemPair(item); + if (!item_pair) return false; + + return removeItemPair(item_pair, rearrange); +} + +bool LLFlatListView::removeItemByValue(const LLSD& value, bool rearrange) +{ + if (value.isUndefined()) return false; + + item_pair_t* item_pair = getItemPair(value); + if (!item_pair) return false; + + return removeItemPair(item_pair, rearrange); +} + +bool LLFlatListView::removeItemByUUID(const LLUUID& uuid, bool rearrange) +{ + return removeItemByValue(LLSD(uuid), rearrange); +} + +LLPanel* LLFlatListView::getItemByValue(const LLSD& value) const +{ + if (value.isUndefined()) return nullptr; + + item_pair_t* pair = getItemPair(value); + if (pair) return pair->first; + return nullptr; +} + +bool LLFlatListView::valueExists(const LLSD& value) const +{ + if (value.isUndefined()) return false; + item_pair_t* pair = getItemPair(value); + return pair != nullptr; +} + +bool LLFlatListView::selectItem(LLPanel* item, bool select /*= true*/) +{ + if (!item) return false; + if (item->getParent() != mItemsPanel) return false; + + item_pair_t* item_pair = getItemPair(item); + if (!item_pair) return false; + + return selectItemPair(item_pair, select); +} + +bool LLFlatListView::selectItemByValue(const LLSD& value, bool select /*= true*/) +{ + if (value.isUndefined()) return false; + + item_pair_t* item_pair = getItemPair(value); + if (!item_pair) return false; + + return selectItemPair(item_pair, select); +} + +bool LLFlatListView::selectItemByUUID(const LLUUID& uuid, bool select /* = true*/) +{ + return selectItemByValue(LLSD(uuid), select); +} + + +LLSD LLFlatListView::getSelectedValue() const +{ + if (mSelectedItemPairs.empty()) return LLSD(); + + item_pair_t* first_selected_pair = mSelectedItemPairs.front(); + return first_selected_pair->second; +} + +void LLFlatListView::getSelectedValues(std::vector& selected_values) const +{ + if (mSelectedItemPairs.empty()) return; + + for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + selected_values.push_back((*it)->second); + } +} + +LLUUID LLFlatListView::getSelectedUUID() const +{ + const LLSD& value = getSelectedValue(); + if (value.isDefined() && value.isUUID()) + { + return value.asUUID(); + } + else + { + return LLUUID::null; + } +} + +void LLFlatListView::getSelectedUUIDs(uuid_vec_t& selected_uuids) const +{ + if (mSelectedItemPairs.empty()) return; + + for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + selected_uuids.push_back((*it)->second.asUUID()); + } +} + +LLPanel* LLFlatListView::getSelectedItem() const +{ + if (mSelectedItemPairs.empty()) return nullptr; + + return mSelectedItemPairs.front()->first; +} + +void LLFlatListView::getSelectedItems(std::vector& selected_items) const +{ + if (mSelectedItemPairs.empty()) return; + + for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + selected_items.push_back((*it)->first); + } +} + +void LLFlatListView::resetSelection(bool no_commit_on_deselection /*= false*/) +{ + if (mSelectedItemPairs.empty()) return; + + for (pairs_iterator_t it= mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + item_pair_t* pair_to_deselect = *it; + LLPanel* item = pair_to_deselect->first; + item->setValue(UNSELECTED_EVENT); + } + + mSelectedItemPairs.clear(); + + if (mCommitOnSelectionChange && !no_commit_on_deselection) + { + onCommit(); + } + + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); +} + +void LLFlatListView::setNoItemsCommentText(const std::string& comment_text) +{ + mNoItemsCommentTextbox->setValue(comment_text); +} + +U32 LLFlatListView::size(const bool only_visible_items) const +{ + if (only_visible_items) + { + U32 size = 0; + for (pairs_const_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + if ((*iter)->first->getVisible()) + ++size; + } + return size; + } + else + { + return mItemPairs.size(); + } +} + +void LLFlatListView::clear() +{ + // This will clear mSelectedItemPairs, calling all appropriate callbacks. + resetSelection(); + + // do not use LLView::deleteAllChildren to avoid removing nonvisible items. drag-n-drop for ex. + for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + mItemsPanel->removeChild((*it)->first); + (*it)->first->die(); + delete *it; + } + mItemPairs.clear(); + + // also set items panel height to zero. Reshape it to allow reshaping of non-item children + LLRect rc = mItemsPanel->getRect(); + rc.mBottom = rc.mTop; + mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); + mItemsPanel->setRect(rc); + + setNoItemsCommentVisible(true); + notifyParentItemsRectChanged(); +} + +void LLFlatListView::sort() +{ + if (!mItemComparator) + { + LL_WARNS() << "No comparator specified for sorting FlatListView items." << LL_ENDL; + return; + } + + mItemPairs.sort(ComparatorAdaptor(*mItemComparator)); + rearrangeItems(); +} + +bool LLFlatListView::updateValue(const LLSD& old_value, const LLSD& new_value) +{ + if (old_value.isUndefined() || new_value.isUndefined()) return false; + if (llsds_are_equal(old_value, new_value)) return false; + + item_pair_t* item_pair = getItemPair(old_value); + if (!item_pair) return false; + + item_pair->second = new_value; + return true; +} + +////////////////////////////////////////////////////////////////////////// +// PROTECTED STUFF +////////////////////////////////////////////////////////////////////////// + +LLFlatListView::LLFlatListView(const std::string& name, const LLRect& rect, bool opaque, const LLColor4& color, const S32& item_pad, bool allow_select, bool multi_select, bool keep_one_selected, bool keep_selection_visible_on_reshape, const std::string& no_items_text) +: LLScrollContainer(name, rect, nullptr, opaque, color) + , mItemComparator(nullptr) + , mItemsPanel(nullptr) + , mItemPad(item_pad) + , mAllowSelection(allow_select) + , mMultipleSelection(multi_select) + , mCommitOnSelectionChange(false) + , mKeepOneItemSelected(keep_one_selected) + , mIsConsecutiveSelection(false) + , mKeepSelectionVisibleOnReshape(keep_selection_visible_on_reshape) + , mPrevNotifyParentRect(LLRect()) + , mNoItemsCommentTextbox(nullptr) +{ + mBorderThickness = getBorderWidth(); + + LLRect scroll_rect = getRect(); + LLRect items_rect; + + setItemsNoScrollWidth(scroll_rect.getWidth()); + items_rect.setLeftTopAndSize(mBorderThickness, scroll_rect.getHeight() - mBorderThickness, mItemsNoScrollWidth, 0); + + mItemsPanel = new LLPanel("items panel", items_rect); + addChild(mItemsPanel); + + //we don't need to stretch in vertical direction on reshaping by a parent + //no bottom following! + mItemsPanel->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); + + mSelectedItemsBorder = new LLViewBorder( + "scroll border", + getLastSelectedItemRect(), + LLViewBorder::BEVEL_IN); + mSelectedItemsBorder->setVisible(false); + mItemsPanel->addChild(mSelectedItemsBorder); + + { + // create textbox for "No Items" comment text + { + LLRect comment_rect = getRect(); + comment_rect.setOriginAndSize(0, 0, comment_rect.getWidth(), comment_rect.getHeight()); + comment_rect.stretch(-getBorderWidth()); + mNoItemsCommentTextbox = new LLTextBox(no_items_text, comment_rect, no_items_text); + } + mNoItemsCommentTextbox->setBorderVisible(false); + + { + mNoItemsCommentTextbox->setFollows(FOLLOWS_ALL); + } + } +}; + +LLFlatListView::~LLFlatListView() +{ + delete_and_clear(mItemPairs); +} + +// virtual +void LLFlatListView::draw() +{ + // Highlight border if a child of this container has keyboard focus + if ( mSelectedItemsBorder->getVisible() ) + { + mSelectedItemsBorder->setKeyboardFocusHighlight( hasFocus() ); + } + LLScrollContainer::draw(); +} + +// virtual +BOOL LLFlatListView::postBuild() +{ + setTabStop(true); + return LLScrollContainer::postBuild(); +} + +void LLFlatListView::rearrangeItems() +{ + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + setNoItemsCommentVisible(0==size()); + + if (mItemPairs.empty()) return; + + //calculating required height - assuming items can be of different height + //list should accommodate all its items + S32 height = 0; + + S32 invisible_children_count = 0; + pairs_iterator_t it = mItemPairs.begin(); + for (; it != mItemPairs.end(); ++it) + { + LLPanel* item = (*it)->first; + + // skip invisible child + if (!item->getVisible()) + { + ++invisible_children_count; + continue; + } + + height += item->getRect().getHeight(); + } + + // add paddings between items, excluding invisible ones + height += mItemPad * (mItemPairs.size() - invisible_children_count - 1); + + LLRect rc = mItemsPanel->getRect(); + S32 width = mItemsNoScrollWidth; + + // update width to avoid horizontal scrollbar + if (height > getRect().getHeight() - 2 * mBorderThickness) + width -= scrollbar_size; + + //changes the bottom, end of the list goes down in the scroll container + rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height); + mItemsPanel->setRect(rc); + + //reshaping items + S32 item_new_top = height; + pairs_iterator_t it2, first_it = mItemPairs.begin(); + for (it2 = first_it; it2 != mItemPairs.end(); ++it2) + { + LLPanel* item = (*it2)->first; + + // skip invisible child + if (!item->getVisible()) + continue; + + LLRect rc = item->getRect(); + rc.setLeftTopAndSize(rc.mLeft, item_new_top, width, rc.getHeight()); + item->reshape(rc.getWidth(), rc.getHeight()); + item->setRect(rc); + + // move top for next item in list + item_new_top -= (rc.getHeight() + mItemPad); + } + + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); +} + +void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask) +{ + if (!item_pair) return; + + if (!item_pair->first) + { + LL_WARNS() << "Attempt to selet an item pair containing null panel item" << LL_ENDL; + return; + } + + setFocus(TRUE); + + bool select_item = !isSelected(item_pair); + + //*TODO find a better place for that enforcing stuff + if (mKeepOneItemSelected && numSelected() == 1 && !select_item) return; + + if ( (mask & MASK_SHIFT) && !(mask & MASK_CONTROL) + && mMultipleSelection && !mSelectedItemPairs.empty() ) + { + item_pair_t* last_selected_pair = mSelectedItemPairs.back(); + + // If item_pair is already selected - do nothing + if (last_selected_pair == item_pair) + return; + + bool grab_items = false; + bool reverse = false; + pairs_list_t pairs_to_select; + + // Pick out items from list between last selected and current clicked item_pair. + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + item_pair_t* cur = *iter; + if (cur == last_selected_pair || cur == item_pair) + { + // We've got reverse selection if last grabed item isn't a new selection. + reverse = grab_items && (cur != item_pair); + grab_items = !grab_items; + // Skip last selected and current clicked item pairs. + continue; + } + if (!cur->first->getVisible()) + { + // Skip invisible item pairs. + continue; + } + if (grab_items) + { + pairs_to_select.push_back(cur); + } + } + + if (reverse) + { + pairs_to_select.reverse(); + } + + pairs_to_select.push_back(item_pair); + + for (pairs_iterator_t + iter = pairs_to_select.begin(), + iter_end = pairs_to_select.end(); + iter != iter_end; ++iter) + { + item_pair_t* pair_to_select = *iter; + if (isSelected(pair_to_select)) + { + // Item was already selected but there is a need to keep order from last selected pair to new selection. + // Do it here to prevent extra mCommitOnSelectionChange in selectItemPair(). + mSelectedItemPairs.remove(pair_to_select); + mSelectedItemPairs.push_back(pair_to_select); + } + else + { + selectItemPair(pair_to_select, true); + } + } + + if (!select_item) + { + // Update last selected item border. + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + } + return; + } + + //no need to do additional commit on selection reset + if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection(true); + + //only CTRL usage allows to deselect an item, usual clicking on an item cannot deselect it + if (mask & MASK_CONTROL) + selectItemPair(item_pair, select_item); + else + selectItemPair(item_pair, true); +} + +void LLFlatListView::onItemRightMouseClick(item_pair_t* item_pair, MASK mask) +{ + if (!item_pair) + return; + + // Forbid deselecting of items on right mouse button click if mMultipleSelection flag is set on, + // because some of derived classes may have context menu and selected items must be kept. + if ( !(mask & MASK_CONTROL) && mMultipleSelection && isSelected(item_pair) ) + return; + + // else got same behavior as at onItemMouseClick + onItemMouseClick(item_pair, mask); +} + +BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask) +{ + BOOL reset_selection = (mask != MASK_SHIFT); + BOOL handled = FALSE; + switch (key) + { + case KEY_RETURN: + { + if (mSelectedItemPairs.size() && mask == MASK_NONE) + { + mOnReturnSignal(this, getValue()); + handled = TRUE; + } + break; + } + case KEY_UP: + { + if ( !selectNextItemPair(true, reset_selection) && reset_selection) + { + // If case we are in accordion tab notify parent to go to the previous accordion + if (notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed + resetSelection(); + } + break; + } + case KEY_DOWN: + { + if ( !selectNextItemPair(false, reset_selection) && reset_selection) + { + // If case we are in accordion tab notify parent to go to the next accordion + if ( notifyParent(LLSD().with("action","select_next")) > 0 ) //message was processed + resetSelection(); + } + break; + } + case KEY_ESCAPE: + { + if (mask == MASK_NONE) + { + setFocus(FALSE); // pass focus to the game area (EXT-8357) + } + break; + } + default: + break; + } + + if ( ( key == KEY_UP || key == KEY_DOWN ) && mSelectedItemPairs.size() ) + { + ensureSelectedVisible(); + /* + LLRect visible_rc = getVisibleContentRect(); + LLRect selected_rc = getLastSelectedItemRect(); + + if ( !visible_rc.contains (selected_rc) ) + { + // But scroll in Items panel coordinates + scrollToShowRect(selected_rc); + } + + // In case we are in accordion tab notify parent to show selected rectangle + LLRect screen_rc; + localRectToScreen(selected_rc, &screen_rc); + notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));*/ + + handled = TRUE; + } + + return handled ? handled : LLScrollContainer::handleKeyHere(key, mask); +} + +LLFlatListView::item_pair_t* LLFlatListView::getItemPair(LLPanel* item) const +{ + llassert(item); + + for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* item_pair = *it; + if (item_pair->first == item) return item_pair; + } + return nullptr; +} + +//compares two LLSD's +bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2) +{ + llassert(llsd_1.isDefined()); + llassert(llsd_2.isDefined()); + + if (llsd_1.type() != llsd_2.type()) return false; + + if (!llsd_1.isMap()) + { + if (llsd_1.isUUID()) return llsd_1.asUUID() == llsd_2.asUUID(); + + //assumptions that string representaion is enough for other types + return llsd_1.asString() == llsd_2.asString(); + } + + if (llsd_1.size() != llsd_2.size()) return false; + + LLSD::map_const_iterator llsd_1_it = llsd_1.beginMap(); + LLSD::map_const_iterator llsd_2_it = llsd_2.beginMap(); + for (S32 i = 0; i < llsd_1.size(); ++i) + { + if ((*llsd_1_it).first != (*llsd_2_it).first) return false; + if (!llsds_are_equal((*llsd_1_it).second, (*llsd_2_it).second)) return false; + ++llsd_1_it; + ++llsd_2_it; + } + return true; +} + +LLFlatListView::item_pair_t* LLFlatListView::getItemPair(const LLSD& value) const +{ + llassert(value.isDefined()); + + for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* item_pair = *it; + if (llsds_are_equal(item_pair->second, value)) return item_pair; + } + return nullptr; +} + +bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select) +{ + llassert(item_pair); + + if (!mAllowSelection && select) return false; + + if (isSelected(item_pair) == select) return true; //already in specified selection state + if (select) + { + mSelectedItemPairs.push_back(item_pair); + } + else + { + mSelectedItemPairs.remove(item_pair); + } + + //a way of notifying panel of selection state changes + LLPanel* item = item_pair->first; + item->setValue(select ? SELECTED_EVENT : UNSELECTED_EVENT); + + if (mCommitOnSelectionChange) + { + onCommit(); + } + + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + // By default mark it as not consecutive selection + mIsConsecutiveSelection = false; + + return true; +} + +void LLFlatListView::scrollToShowFirstSelectedItem() +{ + if (!mSelectedItemPairs.size()) return; + + LLRect selected_rc = mSelectedItemPairs.front()->first->getRect(); + + if (selected_rc.isValid()) + { + scrollToShowRect(selected_rc); + } +} + +LLRect LLFlatListView::getLastSelectedItemRect() +{ + if (!mSelectedItemPairs.size()) + { + return LLRect::null; + } + + return mSelectedItemPairs.back()->first->getRect(); +} + +void LLFlatListView::selectFirstItem () +{ + // No items - no actions! + if (0 == size()) return; + + // Select first visible item + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + // skip invisible items + if ( (*iter)->first->getVisible() ) + { + selectItemPair(*iter, true); + ensureSelectedVisible(); + break; + } + } +} + +void LLFlatListView::selectLastItem () +{ + // No items - no actions! + if (0 == size()) return; + + // Select last visible item + for (pairs_list_t::reverse_iterator + r_iter = mItemPairs.rbegin(), + r_iter_end = mItemPairs.rend(); + r_iter != r_iter_end; ++r_iter) + { + // skip invisible items + if ( (*r_iter)->first->getVisible() ) + { + selectItemPair(*r_iter, true); + ensureSelectedVisible(); + break; + } + } +} + +void LLFlatListView::ensureSelectedVisible() +{ + LLRect selected_rc = getLastSelectedItemRect(); + + if (selected_rc.isValid()) + { + scrollToShowRect(selected_rc); + } +} + + +// virtual +bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selection) +{ + // No items - no actions! + if (0 == size()) + return false; + + if (!mIsConsecutiveSelection) + { + // Leave only one item selected if list has not consecutive selection + if (mSelectedItemPairs.size() && !reset_selection) + { + item_pair_t* cur_sel_pair = mSelectedItemPairs.back(); + resetSelection(); + selectItemPair (cur_sel_pair, true); + } + } + + if (mSelectedItemPairs.size()) + { + item_pair_t* to_sel_pair = nullptr; + item_pair_t* cur_sel_pair = nullptr; + + // Take the last selected pair + cur_sel_pair = mSelectedItemPairs.back(); + // Bases on given direction choose next item to select + if (is_up_direction) + { + // Find current selected item position in mItemPairs list + pairs_list_t::reverse_iterator sel_it = std::find(mItemPairs.rbegin(), mItemPairs.rend(), cur_sel_pair); + + for (;++sel_it != mItemPairs.rend();) + { + // skip invisible items + if ( (*sel_it)->first->getVisible() ) + { + to_sel_pair = *sel_it; + break; + } + } + } + else + { + // Find current selected item position in mItemPairs list + pairs_list_t::iterator sel_it = std::find(mItemPairs.begin(), mItemPairs.end(), cur_sel_pair); + + for (;++sel_it != mItemPairs.end();) + { + // skip invisible items + if ( (*sel_it)->first->getVisible() ) + { + to_sel_pair = *sel_it; + break; + } + } + } + + if (to_sel_pair) + { + bool select = true; + if (reset_selection) + { + // Reset current selection if we were asked about it + resetSelection(); + } + else + { + // If item already selected and no reset request than we should deselect last selected item. + select = (mSelectedItemPairs.end() == std::find(mSelectedItemPairs.begin(), mSelectedItemPairs.end(), to_sel_pair)); + } + // Select/Deselect next item + selectItemPair(select ? to_sel_pair : cur_sel_pair, select); + // Mark it as consecutive selection + mIsConsecutiveSelection = true; + return true; + } + } + else + { + // If there weren't selected items then choose the first one bases on given direction + // Force selection to first item + if (is_up_direction) + selectLastItem(); + else + selectFirstItem(); + // Mark it as consecutive selection + mIsConsecutiveSelection = true; + return true; + } + + return false; +} + +BOOL LLFlatListView::canSelectAll() const +{ + return 0 != size() && mAllowSelection && mMultipleSelection; +} + +void LLFlatListView::selectAll() +{ + if (!mAllowSelection || !mMultipleSelection) + return; + + mSelectedItemPairs.clear(); + + for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* item_pair = *it; + mSelectedItemPairs.push_back(item_pair); + //a way of notifying panel of selection state changes + LLPanel* item = item_pair->first; + item->setValue(SELECTED_EVENT); + } + + if (mCommitOnSelectionChange) + { + onCommit(); + } + + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); +} + +bool LLFlatListView::isSelected(item_pair_t* item_pair) const +{ + llassert(item_pair); + + pairs_const_iterator_t it_end = mSelectedItemPairs.end(); + return std::find(mSelectedItemPairs.begin(), it_end, item_pair) != it_end; +} + +bool LLFlatListView::removeItemPair(item_pair_t* item_pair, bool rearrange) +{ + llassert(item_pair); + + bool deleted = false; + bool selection_changed = false; + for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* _item_pair = *it; + if (_item_pair == item_pair) + { + mItemPairs.erase(it); + deleted = true; + break; + } + } + + if (!deleted) return false; + + for (pairs_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + item_pair_t* selected_item_pair = *it; + if (selected_item_pair == item_pair) + { + it = mSelectedItemPairs.erase(it); + selection_changed = true; + break; + } + } + + mItemsPanel->removeChild(item_pair->first); + item_pair->first->die(); + delete item_pair; + + if (rearrange) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + } + + if (selection_changed && mCommitOnSelectionChange) + { + onCommit(); + } + + return true; +} + +void LLFlatListView::notifyParentItemsRectChanged() +{ + S32 comment_height = 0; + + // take into account comment text height if exists + if (mNoItemsCommentTextbox && mNoItemsCommentTextbox->getVisible()) + { + // top text padding inside the textbox is included into the height + comment_height = mNoItemsCommentTextbox->getTextPixelHeight(); + + // take into account a distance from parent's top border to textbox's top + comment_height += getRect().getHeight() - mNoItemsCommentTextbox->getRect().mTop; + } + + LLRect req_rect = getItemsRect(); + + // get maximum of items total height and comment text height + req_rect.setOriginAndSize(req_rect.mLeft, req_rect.mBottom, req_rect.getWidth(), llmax(req_rect.getHeight(), comment_height)); + + // take into account border size. + req_rect.stretch(getBorderWidth()); + + if (req_rect == mPrevNotifyParentRect) + return; + + mPrevNotifyParentRect = req_rect; + + LLSD params; + params["action"] = "size_changes"; + params["width"] = req_rect.getWidth(); + params["height"] = req_rect.getHeight(); + + if (getParent()) // dummy widgets don't have a parent + getParent()->notifyParent(params); +} + +void LLFlatListView::setNoItemsCommentVisible(bool visible) const +{ + if (mNoItemsCommentTextbox) + { + mSelectedItemsBorder->setVisible(!visible); + mNoItemsCommentTextbox->setVisible(visible); + } +} + +void LLFlatListView::getItems(std::vector& items) const +{ + if (mItemPairs.empty()) return; + + items.clear(); + for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + items.push_back((*it)->first); + } +} + +void LLFlatListView::getValues(std::vector& values) const +{ + if (mItemPairs.empty()) return; + + values.clear(); + for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + values.push_back((*it)->second); + } +} + +// virtual +void LLFlatListView::onFocusReceived() +{ + if (size()) + { + mSelectedItemsBorder->setVisible(TRUE); + } + gEditMenuHandler = this; +} +// virtual +void LLFlatListView::onFocusLost() +{ + mSelectedItemsBorder->setVisible(FALSE); + // Route menu back to the default + if (gEditMenuHandler == this) + { + gEditMenuHandler = nullptr; + } +} + +//virtual +S32 LLFlatListView::notify(const LLSD& info) +{ + if (info.has("action")) + { + std::string str_action = info["action"]; + if (str_action == "select_first") + { + setFocus(true); + selectFirstItem(); + return 1; + } + else if (str_action == "select_last") + { + setFocus(true); + selectLastItem(); + return 1; + } + } + else if (info.has("rearrange")) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + return 1; + } + return 0; +} + +void LLFlatListView::detachItems(std::vector& detached_items) +{ + LLSD action; + action.with("detach", LLSD()); + // Clear detached_items list + detached_items.clear(); + // Go through items and detach valid items, remove them from items panel + // and add to detached_items. + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + LLPanel* pItem = (*iter)->first; + if (1 == pItem->notify(action)) + { + selectItemPair((*iter), false); + mItemsPanel->removeChild(pItem); + detached_items.push_back(pItem); + } + } + if (!detached_items.empty()) + { + // Some items were detached, clean ourself from unusable memory + if (detached_items.size() == mItemPairs.size()) + { + // This way will be faster if all items were disconnected + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + (*iter)->first = nullptr; + delete *iter; + } + mItemPairs.clear(); + // Also set items panel height to zero. + // Reshape it to allow reshaping of non-item children. + LLRect rc = mItemsPanel->getRect(); + rc.mBottom = rc.mTop; + mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); + mItemsPanel->setRect(rc); + setNoItemsCommentVisible(true); + } + else + { + for (std::vector::const_iterator + detached_iter = detached_items.begin(), + detached_iter_end = detached_items.end(); + detached_iter != detached_iter_end; ++detached_iter) + { + LLPanel* pDetachedItem = *detached_iter; + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + item_pair_t* item_pair = *iter; + if (item_pair->first == pDetachedItem) + { + mItemPairs.erase(iter); + item_pair->first = nullptr; + delete item_pair; + break; + } + } + } + rearrangeItems(); + } + notifyParentItemsRectChanged(); + } +} + + +/************************************************************************/ +/* LLFlatListViewEx implementation */ +/************************************************************************/ +/* Singu Note: Let's not use this for now... +LLFlatListViewEx::Params::Params() +: no_items_msg("no_items_msg") +, no_filtered_items_msg("no_filtered_items_msg") +{ + +} + +LLFlatListViewEx::LLFlatListViewEx(const Params& p) +: LLFlatListView(p) +, mNoFilteredItemsMsg(p.no_filtered_items_msg) +, mNoItemsMsg(p.no_items_msg) +, mForceShowingUnmatchedItems(false) +, mHasMatchedItems(false) +{ + +} + +void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string) +{ + bool items_filtered = !filter_string.empty(); + if (items_filtered) + { + // items were filtered + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(filter_string); + std::string text = mNoFilteredItemsMsg; + LLStringUtil::format(text, args); + setNoItemsCommentText(text); + } + else + { + // list does not contain any items at all + setNoItemsCommentText(mNoItemsMsg); + } + +} + +bool LLFlatListViewEx::getForceShowingUnmatchedItems() +{ + return mForceShowingUnmatchedItems; +} + +void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show) +{ + mForceShowingUnmatchedItems = show; +} + +void LLFlatListViewEx::setFilterSubString(const std::string& filter_str) +{ + if (0 != LLStringUtil::compareInsensitive(filter_str, mFilterSubString)) + { + mFilterSubString = filter_str; + updateNoItemsMessage(mFilterSubString); + filterItems(); + } +} + +void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) +{ + if (!item) return; + + // 0 signifies that filter is matched, + // i.e. we don't hide items that don't support 'match_filter' action, separators etc. + if (0 == item->notify(action)) + { + mHasMatchedItems = true; + item->setVisible(true); + } + else + { + // TODO: implement (re)storing of current selection. + if (!mForceShowingUnmatchedItems) + { + selectItem(item, false); + } + item->setVisible(mForceShowingUnmatchedItems); + } +} + +void LLFlatListViewEx::filterItems() +{ + typedef std::vector item_panel_list_t; + + std::string cur_filter = mFilterSubString; + LLStringUtil::toUpper(cur_filter); + + LLSD action; + action.with("match_filter", cur_filter); + + item_panel_list_t items; + getItems(items); + + mHasMatchedItems = false; + for (item_panel_list_t::iterator + iter = items.begin(), + iter_end = items.end(); + iter != iter_end; ++iter) + { + LLPanel* pItem = (*iter); + updateItemVisibility(pItem, action); + } + + sort(); + notifyParentItemsRectChanged(); +} + +bool LLFlatListViewEx::hasMatchedItems() +{ + return mHasMatchedItems; +} +*/ + +// Old-style fromXML stuffs +// static +LLView* LLFlatListView::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +{ + // Stuff from scroll container + std::string name("flat_list_view"); + node->getAttributeString("name", name); + + LLRect rect; + createRect(node, rect, parent, LLRect()); + + BOOL opaque = FALSE; + node->getAttributeBOOL("opaque", opaque); + + LLColor4 color(0,0,0,0); + LLUICtrlFactory::getAttributeColor(node, "color", color); + + // Stuff from flat list + bool allow_select = false; + node->getAttribute_bool("allow_select", allow_select); + bool multi_select = false; + node->getAttribute_bool("multi_select", multi_select); + bool keep_one_selected = false; + node->getAttribute_bool("keep_one_selected", keep_one_selected); + bool keep_selection_visible_on_reshape = false; + node->getAttribute_bool("keep_selection_visible_on_reshape", keep_selection_visible_on_reshape); + U32 item_pad; + node->getAttributeU32("item_pad", item_pad); + std::string no_items_text; + node->getAttributeString("no_items_text", no_items_text); + + return new LLFlatListView(name, rect, opaque, color, item_pad, allow_select, multi_select, keep_one_selected, keep_selection_visible_on_reshape, no_items_text); +} +// + +//EOF diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h new file mode 100644 index 0000000000..ade20412af --- /dev/null +++ b/indra/llui/llflatlistview.h @@ -0,0 +1,540 @@ +/** + * @file llflatlistview.h + * @brief LLFlatListView base class and extension to support messages for several cases of an empty list. + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLATLISTVIEW_H +#define LL_LLFLATLISTVIEW_H + +#include "llpanel.h" +#include "llscrollcontainer.h" +#include "lltextbox.h" + + +/** + * LLFlatListView represents a flat list ui control that operates on items in a form of LLPanel's. + * LLSD can be associated with each added item, it can keep data from an item in digested form. + * Associated LLSD's can be of any type (singular, a map etc.). + * Items (LLPanel's subclasses) can be of different height. + * The list is LLPanel created in itself and grows in height while new items are added. + * + * The control can manage selection of its items when the flag "allow_select" is set. Also ability to select + * multiple items (by using CTRL) is enabled through setting the flag "multi_select" - if selection is not allowed that flag + * is ignored. The option "keep_one_selected" forces at least one item to be selected at any time (only for mouse events on items) + * since any item of the list was selected. + * + * Examples of using this control are presented in Picks panel (My Profile and Profile View), where this control is used to + * manage the list of pick items. + * + * ASSUMPTIONS AND STUFF + * - NULL pointers and undefined LLSD's are not accepted by any method of this class unless specified otherwise + * - Order of returned selected items are not guaranteed + * - The control assumes that all items being added are unique. + */ +class LLFlatListView : public LLScrollContainer, public LLEditMenuHandler +{ + LOG_CLASS(LLFlatListView); +public: + + /** + * Abstract comparator for comparing flat list items in a form of LLPanel + */ + class ItemComparator + { + public: + ItemComparator() {}; + virtual ~ItemComparator() {}; + + /** Returns true if item1 < item2, false otherwise */ + virtual bool compare(const LLPanel* item1, const LLPanel* item2) const = 0; + }; + + /** + * Represents reverse comparator which acts as a decorator for a comparator that need to be reversed + */ + class ItemReverseComparator : public ItemComparator + { + public: + ItemReverseComparator(const ItemComparator& comparator) : mComparator(comparator) {}; + virtual ~ItemReverseComparator() {}; + + bool compare(const LLPanel* item1, const LLPanel* item2) const override + { + return mComparator.compare(item2, item1); + } + + private: + const ItemComparator& mComparator; + }; + + + struct Params : public LLInitParam::Block + { + /** turning on/off selection support */ + Optional allow_select; + + /** turning on/off multiple selection (works while clicking and holding CTRL)*/ + Optional multi_select; + + /** don't allow to deselect all selected items (for mouse events on items only) */ + Optional keep_one_selected; + + /** try to keep selection visible after reshape */ + Optional keep_selection_visible_on_reshape; + + /** padding between items */ + Optional item_pad; + + /** textbox with info message when list is empty*/ + Optional no_items_text; + + Params(); + }; + + // disable traversal when finding widget to hand focus off to + /*virtual*/ BOOL canFocusChildren() const override { return FALSE; } + + /** + * Connects callback to signal called when Return key is pressed. + */ + boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); } + + /** Overridden LLPanel's reshape, height is ignored, the list sets its height to accommodate all items */ + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override; + + /** Returns full rect of child panel */ + const LLRect& getItemsRect() const; + + LLRect getRequiredRect() override { return getItemsRect(); } + + /** Returns distance between items */ + const S32 getItemsPad() const { return mItemPad; } + + /** + * Adds and item and LLSD value associated with it to the list at specified position + * @return true if the item was added, false otherwise + */ + virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM, bool rearrange = true); + + /** + * Insert item_to_add along with associated value to the list right after the after_item. + * @return true if the item was successfully added, false otherwise + */ + virtual bool insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value = LLUUID::null); + + /** + * Remove specified item + * @return true if the item was removed, false otherwise + */ + virtual bool removeItem(LLPanel* item, bool rearrange = true); + + /** + * Remove an item specified by value + * @return true if the item was removed, false otherwise + */ + virtual bool removeItemByValue(const LLSD& value, bool rearrange = true); + + /** + * Remove an item specified by uuid + * @return true if the item was removed, false otherwise + */ + virtual bool removeItemByUUID(const LLUUID& uuid, bool rearrange = true); + + /** + * Get an item by value + * @return the item as LLPanel if associated with value, NULL otherwise + */ + virtual LLPanel* getItemByValue(const LLSD& value) const; + + /** + * Check for item by value in list + * @return bool whether item exists by value or not + */ + virtual bool valueExists(const LLSD& value) const; + + template + T* getTypedItemByValue(const LLSD& value) const + { + return dynamic_cast(getItemByValue(value)); + } + + /** + * Select or deselect specified item based on select + * @return true if succeed, false otherwise + */ + virtual bool selectItem(LLPanel* item, bool select = true); + + /** + * Select or deselect an item by associated value based on select + * @return true if succeed, false otherwise + */ + virtual bool selectItemByValue(const LLSD& value, bool select = true); + + /** + * Select or deselect an item by associated uuid based on select + * @return true if succeed, false otherwise + */ + virtual bool selectItemByUUID(const LLUUID& uuid, bool select = true); + + /** + * Get all panels stored in the list. + */ + virtual void getItems(std::vector& items) const; + + /** + * Get all items values. + */ + virtual void getValues(std::vector& values) const; + + /** + * Get LLSD associated with the first selected item + */ + virtual LLSD getSelectedValue() const; + + /** + * Get LLSD's associated with selected items. + * @param selected_values std::vector being populated with LLSD associated with selected items + */ + virtual void getSelectedValues(std::vector& selected_values) const; + + + /** + * Get LLUUID associated with selected item + * @return LLUUID if such was associated with selected item + */ + virtual LLUUID getSelectedUUID() const; + + /** + * Get LLUUIDs associated with selected items + * @param selected_uuids An std::vector being populated with LLUUIDs associated with selected items + */ + virtual void getSelectedUUIDs(uuid_vec_t& selected_uuids) const; + + /** Get the top selected item */ + virtual LLPanel* getSelectedItem() const; + + /** + * Get selected items + * @param selected_items An std::vector being populated with pointers to selected items + */ + virtual void getSelectedItems(std::vector& selected_items) const; + + + /** + * Resets selection of items. + * + * It calls onCommit callback if setCommitOnSelectionChange(bool b) was called with "true" + * argument for current Flat List. + * @param no_commit_on_deselection - if true onCommit callback will not be called + */ + virtual void resetSelection(bool no_commit_on_deselection = false); + + /** + * Sets comment text which will be shown in the list is it is empty. + * + * Textbox to hold passed text is created while this method is called at the first time. + * + * @param comment_text - string to be shown as a comment. + */ + void setNoItemsCommentText( const std::string& comment_text); + + /** Turn on/off multiple selection support */ + void setAllowMultipleSelection(bool allow) { mMultipleSelection = allow; } + + /** Turn on/off selection support */ + void setAllowSelection(bool can_select) { mAllowSelection = can_select; } + + /** Sets flag whether onCommit should be fired if selection was changed */ + // FIXME: this should really be a separate signal, since "Commit" implies explicit user action, and selection changes can happen more indirectly. + void setCommitOnSelectionChange(bool b) { mCommitOnSelectionChange = b; } + + /** Get number of selected items in the list */ + U32 numSelected() const {return mSelectedItemPairs.size(); } + + /** Get number of (visible) items in the list */ + U32 size(const bool only_visible_items = true) const; + + /** Removes all items from the list */ + void clear() override; + + /** + * Removes all items that can be detached from the list but doesn't destroy + * them, caller responsible to manage items after they are detached. + * Detachable item should accept "detach" action via notify() method, + * where it disconnect all callbacks, does other valuable routines and + * return 1. + */ + void detachItems(std::vector& detached_items); + + /** + * Set comparator to use for future sorts. + * + * This class does NOT manage lifetime of the comparator + * but assumes that the comparator is always alive. + */ + void setComparator(const ItemComparator* comp) { mItemComparator = comp; } + void sort(); + + bool updateValue(const LLSD& old_value, const LLSD& new_value); + + void scrollToShowFirstSelectedItem(); + + void selectFirstItem (); + void selectLastItem (); + + S32 notify(const LLSD& info) override; + + static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); // Old-style + + virtual ~LLFlatListView(); +protected: + + /** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */ + typedef std::pair item_pair_t; + + typedef std::list pairs_list_t; + typedef pairs_list_t::iterator pairs_iterator_t; + typedef pairs_list_t::const_iterator pairs_const_iterator_t; + + /** An adapter for a ItemComparator */ + struct ComparatorAdaptor + { + ComparatorAdaptor(const ItemComparator& comparator) : mComparator(comparator) {}; + + bool operator()(const item_pair_t* item_pair1, const item_pair_t* item_pair2) const + { + return mComparator.compare(item_pair1->first, item_pair2->first); + } + + const ItemComparator& mComparator; + }; + + + friend class LLUICtrlFactory; + LLFlatListView(const std::string& name, const LLRect& rect, bool opaque, const LLColor4& color, const S32& item_pad, bool allow_select, bool multi_select, bool keep_one_selected, bool keep_selection_visible_on_reshape, const std::string& no_items_text); + + /** Manage selection on mouse events */ + void onItemMouseClick(item_pair_t* item_pair, MASK mask); + + void onItemRightMouseClick(item_pair_t* item_pair, MASK mask); + + /** + * Updates position of items. + * It does not take into account invisible items. + */ + virtual void rearrangeItems(); + + virtual item_pair_t* getItemPair(LLPanel* item) const; + + virtual item_pair_t* getItemPair(const LLSD& value) const; + + virtual bool selectItemPair(item_pair_t* item_pair, bool select); + + virtual bool selectNextItemPair(bool is_up_direction, bool reset_selection); + + BOOL canSelectAll() const override; + void selectAll() override; + + virtual bool isSelected(item_pair_t* item_pair) const; + + virtual bool removeItemPair(item_pair_t* item_pair, bool rearrange); + + bool addItemPairs(pairs_list_t panel_list, bool rearrange = true); + + /** + * Notify parent about changed size of internal controls with "size_changes" action + * + * Size includes Items Rect width and either Items Rect height or comment text height. + * Comment text height is included if comment text is set and visible. + * List border size is also included into notified size. + */ + void notifyParentItemsRectChanged(); + + BOOL handleKeyHere(KEY key, MASK mask) override; + + BOOL postBuild() override; + + void onFocusReceived() override; + + void onFocusLost() override; + + void draw() override; + + LLRect getLastSelectedItemRect(); + + void ensureSelectedVisible(); + +private: + + void setItemsNoScrollWidth(S32 new_width) {mItemsNoScrollWidth = new_width - 2 * mBorderThickness;} + + void setNoItemsCommentVisible(bool visible) const; + +protected: + + /** Comparator to use when sorting the list. */ + const ItemComparator* mItemComparator; + + +private: + + LLPanel* mItemsPanel; + + S32 mItemsNoScrollWidth; + + S32 mBorderThickness; + + /** Items padding */ + S32 mItemPad; + + /** Selection support flag */ + bool mAllowSelection; + + /** Multiselection support flag, ignored if selection is not supported */ + bool mMultipleSelection; + + /** + * Flag specified whether onCommit be called if selection is changed in the list. + * + * Can be ignored in the resetSelection() method. + * @see resetSelection() + */ + bool mCommitOnSelectionChange; + + bool mKeepOneItemSelected; + + bool mIsConsecutiveSelection; + + bool mKeepSelectionVisibleOnReshape; + + /** All pairs of the list */ + pairs_list_t mItemPairs; + + /** Selected pairs for faster access */ + pairs_list_t mSelectedItemPairs; + + /** + * Rectangle contained previous size of items parent notified last time. + * Is used to reduce amount of parentNotify() calls if size was not changed. + */ + LLRect mPrevNotifyParentRect; + + LLTextBox* mNoItemsCommentTextbox; + + LLViewBorder* mSelectedItemsBorder; + + commit_signal_t mOnReturnSignal; +}; + +/** + * Extends LLFlatListView functionality to show different messages when there are no items in the + * list depend on whether they are filtered or not. + * + * Class provides one message per case of empty list. + * It also provides protected updateNoItemsMessage() method to be called each time when derived list + * is changed to update base mNoItemsCommentTextbox value. + * + * It is implemented to avoid duplication of this functionality in concrete implementations of the + * lists. It is intended to be used as a base class for lists which should support two different + * messages for empty state. Can be improved to support more than two messages via state-to-message map. + */ +class LLFlatListViewEx : public LLFlatListView +{ +public: + LOG_CLASS(LLFlatListViewEx); + + struct Params : public LLInitParam::Block + { + /** + * Contains a message for empty list when it does not contain any items at all. + */ + Optional no_items_msg; + + /** + * Contains a message for empty list when its items are removed by filtering. + */ + Optional no_filtered_items_msg; + Params(); + }; + + // *WORKAROUND: two methods to overload appropriate Params due to localization issue: + // no_items_msg & no_filtered_items_msg attributes are not defined as translatable in VLT. See EXT-5931 + void setNoItemsMsg(const std::string& msg) { mNoItemsMsg = msg; } + void setNoFilteredItemsMsg(const std::string& msg) { mNoFilteredItemsMsg = msg; } + + bool getForceShowingUnmatchedItems(); + + void setForceShowingUnmatchedItems(bool show); + + /** + * Sets up new filter string and filters the list. + */ + void setFilterSubString(const std::string& filter_str); + std::string getFilterSubString() const { return mFilterSubString; } + + /** + * Filters the list, rearranges and notifies parent about shape changes. + * Derived classes may want to overload rearrangeItems() to exclude repeated separators after filtration. + */ + void filterItems(); + + /** + * Returns true if last call of filterItems() found at least one matching item + */ + bool hasMatchedItems(); + +protected: + LLFlatListViewEx(const Params& p); + + /** + * Applies a message for empty list depend on passed argument. + * + * @param filter_string - if is not empty, message for filtered items will be set, otherwise for + * completely empty list. Value of filter string will be passed as search_term in SLURL. + */ + void updateNoItemsMessage(const std::string& filter_string); + + /** + * Applies visibility acording to action and LLFlatListView settings. + * + * @param item - item we are changing + * @param item - action - parameters to determin visibility from + */ + void updateItemVisibility(LLPanel* item, const LLSD &action); + +private: + std::string mNoFilteredItemsMsg; + std::string mNoItemsMsg; + std::string mFilterSubString; + /** + * Show list items that don't match current filter + */ + bool mForceShowingUnmatchedItems; + /** + * True if last call of filterItems() found at least one matching item + */ + bool mHasMatchedItems; +}; + +#endif diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index fbd2a646dc..c86e4ae507 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -35,8 +35,6 @@ #include "linden_common.h" -#include "llmultifloater.h" - #include "llfocusmgr.h" #include "lluictrlfactory.h" @@ -56,10 +54,13 @@ #include "llcontrol.h" #include "lltabcontainer.h" #include "v2math.h" +#include "lltrans.h" +#include "llmultifloater.h" #include "llfasttimer.h" #include "airecursive.h" #include "llnotifications.h" + const S32 MINIMIZED_WIDTH = 160; const S32 CLOSE_BOX_FROM_TOP = 1; // use this to control "jumping" behavior when Ctrl-Tabbing @@ -104,14 +105,14 @@ std::string LLFloater::sButtonNames[BUTTON_COUNT] = std::string LLFloater::sButtonToolTips[BUTTON_COUNT] = { #ifdef LL_DARWIN - "Close (Cmd-W)", //BUTTON_CLOSE + "BUTTON_CLOSE_DARWIN", //"Close (Cmd-W)", //BUTTON_CLOSE #else - "Close (Ctrl-W)", //BUTTON_CLOSE + "BUTTON_CLOSE_WIN", //"Close (Ctrl-W)", //BUTTON_CLOSE #endif - "Restore", //BUTTON_RESTORE - "Minimize", //BUTTON_MINIMIZE - "Tear Off", //BUTTON_TEAR_OFF - "Edit", //BUTTON_EDIT + "BUTTON_RESTORE", //"Restore", //BUTTON_RESTORE + "BUTTON_MINIMIZE", //"Minimize", //BUTTON_MINIMIZE + "BUTTON_TEAR_OFF", //"Tear Off", //BUTTON_TEAR_OFF + "BUTTON_EDIT", //"Edit", //BUTTON_EDIT }; @@ -130,6 +131,31 @@ LLFloater::handle_map_t LLFloater::sFloaterMap; LLFloaterView* gFloaterView = NULL; +//static +void LLFloater::initClass() +{ + // translate tooltips for floater buttons + for (S32 i = 0; i < BUTTON_COUNT; i++) + { + sButtonToolTips[i] = LLTrans::getString( sButtonToolTips[i] ); + } + + LLControlVariable* ctrl = LLUI::sConfigGroup->getControl("ActiveFloaterTransparency"); + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLFloater::updateActiveFloaterTransparency)); + updateActiveFloaterTransparency(); + } + + ctrl = LLUI::sConfigGroup->getControl("InactiveFloaterTransparency"); + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLFloater::updateInactiveFloaterTransparency)); + updateInactiveFloaterTransparency(); + } + +} + LLFloater::LLFloater() : //FIXME: we should initialize *all* member variables here LLPanel(), mAutoFocus(TRUE), @@ -355,6 +381,18 @@ void LLFloater::initFloater(const std::string& title, } } +// static +void LLFloater::updateActiveFloaterTransparency() +{ + sActiveControlTransparency = LLUI::sConfigGroup->getF32("ActiveFloaterTransparency"); +} + +// static +void LLFloater::updateInactiveFloaterTransparency() +{ + sInactiveControlTransparency = LLUI::sConfigGroup->getF32("InactiveFloaterTransparency"); +} + void LLFloater::addResizeCtrls() { // Resize bars (sides) @@ -636,6 +674,31 @@ void LLFloater::close(bool app_quitting) } } + //If floater is a dependent, remove it from parent (dependee) + LLFloater* dependee = mDependeeHandle.get(); + if (dependee) + { + dependee->removeDependentFloater(this); + } + + // now close dependent floater + for (handle_set_iter_t dependent_it = mDependents.begin(); + dependent_it != mDependents.end(); ) + { + LLFloater* floaterp = dependent_it->get(); + if (floaterp) + { + ++dependent_it; + floaterp->close(app_quitting); + } + else + { + mDependents.erase(dependent_it++); + } + } + + cleanupHandles(); + if (!app_quitting && !getControlName().empty()) setControlValue(false); @@ -720,11 +783,6 @@ void LLFloater::applyRectControl() void LLFloater::applyTitle() { - if (gNoRender) - { - return; - } - if (!mDragHandle) { return; @@ -753,7 +811,7 @@ void LLFloater::setTitle( const std::string& title ) applyTitle(); } -std::string LLFloater::getTitle() +std::string LLFloater::getTitle() const { if (mTitle.empty()) { @@ -771,7 +829,7 @@ void LLFloater::setShortTitle( const std::string& short_title ) applyTitle(); } -std::string LLFloater::getShortTitle() +std::string LLFloater::getShortTitle() const { if (mShortTitle.empty()) { @@ -783,8 +841,6 @@ std::string LLFloater::getShortTitle() } } - - BOOL LLFloater::canSnapTo(const LLView* other_view) { if (NULL == other_view) @@ -1023,7 +1079,8 @@ void LLFloater::setFocus( BOOL b ) if (b) { // only push focused floaters to front of stack if not in midst of ctrl-tab cycle - if (!getHost() && !((LLFloaterView*)getParent())->getCycleMode()) + LLFloaterView * parent = dynamic_cast(getParent()); + if (!getHost() && parent && !parent->getCycleMode()) { if (!isFrontmost()) { @@ -1040,6 +1097,7 @@ void LLFloater::setFocus( BOOL b ) last_focus->setFocus(TRUE); } } + updateTransparency(b ? TT_ACTIVE : TT_INACTIVE); } // virtual @@ -1081,8 +1139,9 @@ void LLFloater::setForeground(BOOL front) releaseFocus(); } - if (front || !LLUI::sConfigGroup->getBOOL("FloaterUnfocusedBackgroundOpaque")) // Singu Note: This can be removed when InactiveFloaterTransparency is added - setBackgroundOpaque( front ); + setBackgroundOpaque( front ); + // Singu Note: Upstream isn't doing this, I can't see where they were actually going inactive. Maybe setFocus(false) isn't being called, but we have parity there.. + updateTransparency(front || getIsChrome() ? TT_ACTIVE : TT_INACTIVE); } } @@ -1191,7 +1250,7 @@ void LLFloater::removeDependentFloater(LLFloater* floaterp) floaterp->mDependeeHandle = LLHandle(); } -BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index) +BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index) { if( mButtonsEnabled[index] ) { @@ -1297,7 +1356,14 @@ void LLFloater::setFrontmost(BOOL take_focus) { // there are more than one floater view // so we need to query our parent directly - ((LLFloaterView*)getParent())->bringToFront(this, take_focus); + LLFloaterView * parent = dynamic_cast( getParent() ); + if (parent) + { + parent->bringToFront(this, take_focus); + } + + // Make sure to set the appropriate transparency type (STORM-732). + updateTransparency(hasFocus() || getIsChrome() ? TT_ACTIVE : TT_INACTIVE); } } @@ -1432,42 +1498,45 @@ void LLFloater::onClickClose() // virtual void LLFloater::draw() { + const F32 alpha = getCurrentTransparency(); + // draw background if( isBackgroundVisible() ) { + drawShadow(this); + S32 left = LLPANEL_BORDER_WIDTH; S32 top = getRect().getHeight() - LLPANEL_BORDER_WIDTH; S32 right = getRect().getWidth() - LLPANEL_BORDER_WIDTH; S32 bottom = LLPANEL_BORDER_WIDTH; - static LLColor4 shadow_color = LLUI::sColorsGroup->getColor("ColorDropShadow"); - static F32 shadow_offset = (F32)LLUI::sConfigGroup->getS32("DropShadowFloater"); - if (!isBackgroundOpaque()) - { - shadow_offset *= 0.2f; - shadow_color.mV[VALPHA] *= 0.5f; - } - gl_drop_shadow(left, top, right, bottom, - shadow_color, - ll_round(shadow_offset)); - // No transparent windows in simple UI + LLColor4 color; if (isBackgroundOpaque()) { - gl_rect_2d( left, top, right, bottom, getBackgroundColor() ); + color = getBackgroundColor(); } else { - gl_rect_2d( left, top, right, bottom, getTransparentColor() ); + color = getTransparentColor(); } - if(gFocusMgr.childHasKeyboardFocus(this) && !getIsChrome() && !getCurrentTitle().empty()) { + // We're not using images, use old-school flat colors + gl_rect_2d( left, top, right, bottom, color % alpha ); + // draw highlight on title bar to indicate focus. RDW - const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ); - LLRect r = getRect(); - gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, - LLUI::sColorsGroup->getColor("TitleBarFocusColor"), 0, TRUE); + if(gFocusMgr.childHasKeyboardFocus(this) + && !getIsChrome() + && !getCurrentTitle().empty()) + { + static auto titlebar_focus_color = LLUI::sColorsGroup->getColor("TitleBarFocusColor"); + + const LLFontGL* font = LLFontGL::getFontSansSerif(); + LLRect r = getRect(); + gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, + titlebar_focus_color % alpha, 0, TRUE); + } } } @@ -1524,6 +1593,49 @@ void LLFloater::draw() } } +void LLFloater::drawShadow(LLPanel* panel) +{ + S32 left = LLPANEL_BORDER_WIDTH; + S32 top = panel->getRect().getHeight() - LLPANEL_BORDER_WIDTH; + S32 right = panel->getRect().getWidth() - LLPANEL_BORDER_WIDTH; + S32 bottom = LLPANEL_BORDER_WIDTH; + + static LLUICachedControl shadow_offset_S32 ("DropShadowFloater", 0); + static LLColor4 shadow_color = LLUI::sColorsGroup->getColor("ColorDropShadow"); + F32 shadow_offset = (F32)shadow_offset_S32; + + if (!panel->isBackgroundOpaque()) + { + shadow_offset *= 0.2f; + shadow_color.mV[VALPHA] *= 0.5f; + } + gl_drop_shadow(left, top, right, bottom, + shadow_color % getCurrentTransparency(), + ll_round(shadow_offset)); +} + +void LLFloater::updateTransparency(LLView* view, ETypeTransparency transparency_type) +{ + if (view) + { + if (view->isCtrl()) + { + static_cast(view)->setTransparencyType(transparency_type); + } + + for (LLView* pChild : *view->getChildList()) + { + if ((pChild->getChildCount()) || (pChild->isCtrl())) + updateTransparency(pChild, transparency_type); + } + } +} + +void LLFloater::updateTransparency(ETypeTransparency transparency_type) +{ + updateTransparency(this, transparency_type); +} + void LLFloater::setCanMinimize(BOOL can_minimize) { // if removing minimize/restore button programmatically, @@ -2319,7 +2431,7 @@ LLRect LLFloaterView::getSnapRect() const return snap_rect; } -LLFloater *LLFloaterView::getFocusedFloater() +LLFloater *LLFloaterView::getFocusedFloater() const { for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { @@ -2332,7 +2444,7 @@ LLFloater *LLFloaterView::getFocusedFloater() return NULL; } -LLFloater *LLFloaterView::getFrontmost() +LLFloater *LLFloaterView::getFrontmost() const { for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { @@ -2345,7 +2457,7 @@ LLFloater *LLFloaterView::getFrontmost() return NULL; } -LLFloater *LLFloaterView::getBackmost() +LLFloater *LLFloaterView::getBackmost() const { LLFloater* back_most = NULL; for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) @@ -2380,7 +2492,7 @@ void LLFloaterView::syncFloaterTabOrder() } } -LLFloater* LLFloaterView::getParentFloater(LLView* viewp) +LLFloater* LLFloaterView::getParentFloater(LLView* viewp) const { LLView* parentp = viewp->getParent(); @@ -2501,7 +2613,7 @@ LLView* LLFloater::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f return floaterp; } -LLFastTimer::DeclareTimer POST_BUILD("Floater Post Build"); +LLTrace::BlockTimerStatHandle POST_BUILD("Floater Post Build"); void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open) /* Flawfinder: ignore */ { std::string name(getName()); @@ -2573,7 +2685,7 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor BOOL result; { - LLFastTimer ft(POST_BUILD); + LL_RECORD_BLOCK_TIME(POST_BUILD); result = postBuild(); } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 0aeb115016..f53e2714f5 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -94,16 +94,19 @@ class LLFloater : public LLPanel friend class LLFloaterView; friend class LLMultiFloater; public: - enum EFloaterButtons + enum EFloaterButton { - BUTTON_CLOSE, + BUTTON_CLOSE = 0, BUTTON_RESTORE, BUTTON_MINIMIZE, BUTTON_TEAR_OFF, BUTTON_EDIT, BUTTON_COUNT }; - + + // Load translations for tooltips for standard buttons + static void initClass(); + LLFloater(); LLFloater(const std::string& name); //simple constructor for data-driven initialization LLFloater( const std::string& name, const LLRect& rect, const std::string& title, @@ -164,9 +167,9 @@ class LLFloater : public LLPanel void applyTitle(); const std::string& getCurrentTitle() const; void setTitle( const std::string& title); - std::string getTitle(); + std::string getTitle() const; void setShortTitle( const std::string& short_title ); - std::string getShortTitle(); + std::string getShortTitle() const; void setTitleVisible(bool visible); virtual void setMinimized(BOOL b); void moveResizeHandlesToFront(); @@ -174,8 +177,8 @@ class LLFloater : public LLPanel void addDependentFloater(LLHandle dependent_handle, BOOL reposition = TRUE); LLFloater* getDependee() { return (LLFloater*)mDependeeHandle.get(); } void removeDependentFloater(LLFloater* dependent); - BOOL isMinimized() { return mMinimized; } - BOOL isFrontmost(); + BOOL isMinimized() const { return mMinimized; } + virtual BOOL isFrontmost(); BOOL isDependent() { return !mDependeeHandle.isDead(); } void setCanMinimize(BOOL can_minimize); void setCanClose(BOOL can_close); @@ -199,6 +202,7 @@ class LLFloater : public LLPanel virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); virtual void draw(); + virtual void drawShadow(LLPanel* panel); virtual void onOpen() {} @@ -244,6 +248,8 @@ class LLFloater : public LLPanel static BOOL getEditModeEnabled() { return sEditModeEnabled; } static LLMultiFloater* getFloaterHost() {return sHostp; } + void updateTransparency(ETypeTransparency transparency_type); + void enableResizeCtrls(bool enable, bool width = true, bool height = true); protected: @@ -259,21 +265,29 @@ class LLFloater : public LLPanel void destroy() { die(); } // Don't call this directly. You probably want to call close(). JC private: - void setForeground(BOOL b); // called only by floaterview void cleanupHandles(); // remove handles to dead floaters void createMinimizeButton(); void updateButtons(); void buildButtons(); - BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index); + BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index); void addResizeCtrls(); void layoutResizeCtrls(); + static void updateActiveFloaterTransparency(); + static void updateInactiveFloaterTransparency(); + void updateTransparency(LLView* view, ETypeTransparency transparency_type); + LLRect mExpandedRect; + +protected: LLDragHandle* mDragHandle; LLResizeBar* mResizeBar[4]; LLResizeHandle* mResizeHandle[4]; LLButton *mMinimizeButton; + + LLButton* mButtons[BUTTON_COUNT]; +private: BOOL mCanTearOff; BOOL mMinimized; BOOL mForeground; @@ -294,10 +308,7 @@ class LLFloater : public LLPanel handle_set_t mDependents; bool mDragOnLeft; - BOOL mButtonsEnabled[BUTTON_COUNT]; -protected: - LLButton* mButtons[BUTTON_COUNT]; -private: + bool mButtonsEnabled[BUTTON_COUNT]; F32 mButtonScale; BOOL mAutoFocus; LLHandle mSnappedTo; @@ -344,7 +355,7 @@ class LLFloaterView : public LLUICtrl /*virtual*/ void draw(); /*virtual*/ LLRect getSnapRect() const; - void refresh(); + /*virtual*/ void refresh(); void getNewFloaterPosition( S32* left, S32* top ); void resetStartingFloaterPosition(); @@ -373,10 +384,10 @@ class LLFloaterView : public LLUICtrl void minimizeAllChildren(); //
    - LLFloater* getFrontmost(); - LLFloater* getBackmost(); - LLFloater* getParentFloater(LLView* viewp); - LLFloater* getFocusedFloater(); + LLFloater* getFrontmost() const; + LLFloater* getBackmost() const; + LLFloater* getParentFloater(LLView* viewp) const; + LLFloater* getFocusedFloater() const; void syncFloaterTabOrder(); // Returns z order of child provided. 0 is closest, larger numbers diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp index afcafdace8..60983c9d4e 100644 --- a/indra/llui/llfocusmgr.cpp +++ b/indra/llui/llfocusmgr.cpp @@ -33,10 +33,10 @@ const F32 FOCUS_FADE_TIME = 0.3f; LLFocusableElement::LLFocusableElement() -: mFocusLostCallback(NULL), - mFocusReceivedCallback(NULL), - mFocusChangedCallback(NULL), - mTopLostCallback(NULL) +: mFocusLostCallback(nullptr), + mFocusReceivedCallback(nullptr), + mFocusChangedCallback(nullptr), + mTopLostCallback(nullptr) { } @@ -46,12 +46,30 @@ BOOL LLFocusableElement::handleKey(KEY key, MASK mask, BOOL called_from_parent) return FALSE; } +// virtual +BOOL LLFocusableElement::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent) +{ + return FALSE; +} + // virtual BOOL LLFocusableElement::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) { return FALSE; } +// virtual +bool LLFocusableElement::wantsKeyUpKeyDown() const +{ + return false; +} + +//virtual +bool LLFocusableElement::wantsReturnKey() const +{ + return false; +} + // virtual LLFocusableElement::~LLFocusableElement() { @@ -128,14 +146,14 @@ struct LLFocusMgr::Impl LLFocusMgr gFocusMgr; LLFocusMgr::LLFocusMgr() -: mLockedView( NULL ), - mMouseCaptor( NULL ), - mKeyboardFocus( NULL ), - mLastKeyboardFocus( NULL ), - mDefaultKeyboardFocus( NULL ), - mLastDefaultKeyboardFocus( NULL ), +: mLockedView(nullptr ), + mMouseCaptor(nullptr ), + mKeyboardFocus(nullptr ), + mLastKeyboardFocus(nullptr ), + mDefaultKeyboardFocus(nullptr ), + mLastDefaultKeyboardFocus(nullptr ), mKeystrokesOnly(FALSE), - mTopCtrl( NULL ), + mTopCtrl(nullptr ), mAppHasFocus(TRUE), // Macs don't seem to notify us that we've gotten focus, so default to true mImpl(new LLFocusMgr::Impl) { @@ -145,22 +163,22 @@ LLFocusMgr::~LLFocusMgr() { mImpl->mFocusHistory.clear(); delete mImpl; - mImpl = NULL; + mImpl = nullptr; } void LLFocusMgr::releaseFocusIfNeeded( const LLView* view ) { if( childHasMouseCapture( view ) ) { - setMouseCapture( NULL ); + setMouseCapture(nullptr ); } if( childHasKeyboardFocus( view )) { if (view == mLockedView) { - mLockedView = NULL; - setKeyboardFocus( NULL ); + mLockedView = nullptr; + setKeyboardFocus(nullptr ); } else { @@ -170,7 +188,7 @@ void LLFocusMgr::releaseFocusIfNeeded( const LLView* view ) if( childIsTopCtrl( view ) ) { - setTopCtrl( NULL ); + setTopCtrl(nullptr); } } @@ -179,7 +197,7 @@ void LLFocusMgr::restoreDefaultKeyboardFocus(LLFocusableElement* current_default if (current_default_focus && mDefaultKeyboardFocus == current_default_focus) { setDefaultKeyboardFocus(mLastDefaultKeyboardFocus); - mLastDefaultKeyboardFocus = NULL; + mLastDefaultKeyboardFocus = nullptr; } } @@ -188,7 +206,7 @@ void LLFocusMgr::restoreKeyboardFocus(LLFocusableElement* current_focus) if (current_focus && mKeyboardFocus == current_focus) { setKeyboardFocus(mLastKeyboardFocus); - mLastKeyboardFocus = NULL; + mLastKeyboardFocus = nullptr; } } @@ -201,7 +219,7 @@ void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL focus_dirty = false; if (mLockedView && - (new_focus == NULL || + (new_focus == nullptr || (new_focus != mLockedView && dynamic_cast(new_focus) && !dynamic_cast(new_focus)->hasAncestor(mLockedView)))) @@ -273,7 +291,7 @@ void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL // If we've got a default keyboard focus, and the caller is // releasing keyboard focus, move to the default. - if (mDefaultKeyboardFocus != NULL && mKeyboardFocus == NULL) + if (mDefaultKeyboardFocus != nullptr && mKeyboardFocus == nullptr) { mDefaultKeyboardFocus->setFocus(TRUE); } @@ -325,7 +343,7 @@ BOOL LLFocusMgr::childHasKeyboardFocus(const LLView* parent ) const // Returns TRUE is parent or any descedent of parent is the mouse captor. BOOL LLFocusMgr::childHasMouseCapture( const LLView* parent ) const { - if( mMouseCaptor && dynamic_cast(mMouseCaptor) != NULL ) + if( mMouseCaptor && dynamic_cast(mMouseCaptor) != nullptr ) { LLView* captor_view = (LLView*)mMouseCaptor; while( captor_view ) @@ -346,23 +364,24 @@ void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLFocusableElement* f // in order to unlock it if (focus == mLockedView) { - mLockedView = NULL; + mLockedView = nullptr; } + if (mKeyboardFocus == focus) { - mKeyboardFocus = NULL; + mKeyboardFocus = nullptr; } if (mLastKeyboardFocus == focus) { - mLastKeyboardFocus = NULL; + mLastKeyboardFocus = nullptr; } if (mDefaultKeyboardFocus == focus) { - mDefaultKeyboardFocus = NULL; + mDefaultKeyboardFocus = nullptr; } if (mLastDefaultKeyboardFocus == focus) { - mLastDefaultKeyboardFocus = NULL; + mLastDefaultKeyboardFocus = nullptr; } } @@ -412,7 +431,7 @@ void LLFocusMgr::removeMouseCaptureWithoutCallback( const LLMouseHandler* captor { if( mMouseCaptor == captor ) { - mMouseCaptor = NULL; + mMouseCaptor = nullptr; } } @@ -452,7 +471,7 @@ void LLFocusMgr::removeTopCtrlWithoutCallback( const LLUICtrl* top_view ) { if( mTopCtrl == top_view ) { - mTopCtrl = NULL; + mTopCtrl = nullptr; } } @@ -463,7 +482,7 @@ void LLFocusMgr::lockFocus() void LLFocusMgr::unlockFocus() { - mLockedView = NULL; + mLockedView = nullptr; } F32 LLFocusMgr::getFocusFlashAmt() const @@ -498,7 +517,7 @@ void LLFocusMgr::setAppHasFocus(BOOL focus) // release focus from "top ctrl"s, which generally hides them if (!focus && mTopCtrl) { - setTopCtrl(NULL); + setTopCtrl(nullptr); } mAppHasFocus = focus; } @@ -514,7 +533,7 @@ LLUICtrl* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) const return static_cast(found_it->second.get()); } } - return NULL; + return nullptr; } void LLFocusMgr::clearLastFocusForGroup(LLView* subtree_root) diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h index 483ef81371..04c32e11f7 100644 --- a/indra/llui/llfocusmgr.h +++ b/indra/llui/llfocusmgr.h @@ -57,8 +57,17 @@ class LLFocusableElement // These were brought up the hierarchy from LLView so that we don't have to use dynamic_cast when dealing with keyboard focus. virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + virtual BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent); virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); + /** + * If true this LLFocusableElement wants to receive KEYUP and KEYDOWN messages + * even for normal character strokes. + * Default implementation returns false. + */ + virtual bool wantsKeyUpKeyDown() const; + virtual bool wantsReturnKey() const; + virtual void onTopLost(); // called when registered as top ctrl and user clicks elsewhere protected: virtual void onFocusReceived(); diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 2d3e23e67d..148aedda4c 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -353,13 +353,13 @@ LLColor3 LLKeywords::readColor( const std::string& s ) return LLColor3( r, g, b ); } -LLFastTimer::DeclareTimer FTM_SYNTAX_COLORING("Syntax Coloring"); +LLTrace::BlockTimerStatHandle FTM_SYNTAX_COLORING("Syntax Coloring"); // Walk through a string, applying the rules specified by the keyword token list and // create a list of color segments. void LLKeywords::findSegments(std::vector* seg_list, const LLWString& wtext, const LLColor4 &defaultColor) { - LLFastTimer ft(FTM_SYNTAX_COLORING); + LL_RECORD_BLOCK_TIME(FTM_SYNTAX_COLORING); seg_list->clear(); if( wtext.empty() ) diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index e724dfb544..f704035544 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -34,7 +34,8 @@ #include "llpanel.h" #include "lluictrlfactory.h" #include "llcriticaldamp.h" -#include "boost/foreach.hpp" + +#include static const F32 MIN_FRACTIONAL_SIZE = 0.00001f; static const F32 MAX_FRACTIONAL_SIZE = 1.f; @@ -245,7 +246,7 @@ void LLLayoutStack::draw() // always clip to stack itself LLLocalClipRect clip(getLocalRect()); - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + for (LLLayoutPanel* panelp : mPanels) { // clip to layout rectangle, not bounding rectangle LLRect clip_rect = panelp->getRect(); @@ -352,11 +353,11 @@ void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed) mNeedsLayout = true; } -static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_LAYOUT("Update LayoutStacks"); void LLLayoutStack::updateLayout() { - LLFastTimer ft(FTM_UPDATE_LAYOUT); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_LAYOUT); if (!mNeedsLayout) return; @@ -367,8 +368,8 @@ void LLLayoutStack::updateLayout() : getRect().getHeight(); // first, assign minimum dimensions - LLLayoutPanel* panelp = NULL; - BOOST_FOREACH(panelp, mPanels) + LLLayoutPanel* panelp = mPanels.size() ? *mPanels.rbegin() : nullptr; + for (auto* panelp : mPanels) { if (panelp->mAutoResize) { @@ -387,7 +388,7 @@ void LLLayoutStack::updateLayout() F32 fraction_distributed = 0.f; if (space_to_distribute > 0 && total_visible_fraction > 0.f) { // give space proportionally to visible auto resize panels - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + for (LLLayoutPanel* panelp : mPanels) { if (panelp->mAutoResize) { @@ -401,7 +402,7 @@ void LLLayoutStack::updateLayout() } // distribute any left over pixels to non-collapsed, visible panels - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + for (LLLayoutPanel* panelp : mPanels) { if (remaining_space == 0) break; @@ -417,7 +418,7 @@ void LLLayoutStack::updateLayout() F32 cur_pos = (mOrientation == HORIZONTAL) ? 0.f : (F32)getRect().getHeight(); - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + for (LLLayoutPanel* panelp : mPanels) { F32 panel_dim = llmax(panelp->getExpandedMinDim(), panelp->mTargetDim); F32 panel_visible_dim = panelp->getVisibleDim(); @@ -473,7 +474,7 @@ LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const if (!panelp) return NULL; e_panel_list_t::const_iterator panel_it; - BOOST_FOREACH(LLLayoutPanel* p, mPanels) + for (LLLayoutPanel* p : mPanels) { if (p == panelp) { @@ -487,7 +488,7 @@ LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) c { LLLayoutPanel* result = NULL; - BOOST_FOREACH(LLLayoutPanel* p, mPanels) + for (LLLayoutPanel* p : mPanels) { if (p->getName() == name) { @@ -501,7 +502,7 @@ LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) c void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp) { - BOOST_FOREACH(LLLayoutPanel* lp, mPanels) + for (LLLayoutPanel* lp : mPanels) { if (lp->mResizeBar == NULL) { @@ -545,7 +546,7 @@ void LLLayoutStack::updateFractionalSizes() { F32 total_resizable_dim = 0.f; - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + for (LLLayoutPanel* panelp : mPanels) { if (panelp->mAutoResize) { @@ -553,7 +554,7 @@ void LLLayoutStack::updateFractionalSizes() } } - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + for (LLLayoutPanel* panelp : mPanels) { if (panelp->mAutoResize) { @@ -561,7 +562,7 @@ void LLLayoutStack::updateFractionalSizes() panelp->mFractionalSize = panel_resizable_dim > 0.f ? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE) : MIN_FRACTIONAL_SIZE; - llassert(!llisnan(panelp->mFractionalSize)); + llassert(!std::isnan(panelp->mFractionalSize)); } } @@ -574,7 +575,7 @@ void LLLayoutStack::normalizeFractionalSizes() S32 num_auto_resize_panels = 0; F32 total_fractional_size = 0.f; - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + for (LLLayoutPanel* panelp : mPanels) { if (panelp->mAutoResize) { @@ -585,7 +586,7 @@ void LLLayoutStack::normalizeFractionalSizes() if (total_fractional_size == 0.f) { // equal distribution - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + for (LLLayoutPanel* panelp : mPanels) { if (panelp->mAutoResize) { @@ -595,7 +596,7 @@ void LLLayoutStack::normalizeFractionalSizes() } else { // renormalize - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + for (LLLayoutPanel* panelp : mPanels) { if (panelp->mAutoResize) { @@ -612,7 +613,7 @@ bool LLLayoutStack::animatePanels() // // animate visibility // - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + for (LLLayoutPanel* panelp : mPanels) { if (panelp->getVisible()) { @@ -620,7 +621,7 @@ bool LLLayoutStack::animatePanels() { if (!mAnimatedThisFrame) { - panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(mOpenTimeConstant)); + panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 1.f, LLSmoothInterpolation::getInterpolant(mOpenTimeConstant)); if (panelp->mVisibleAmt > 0.99f) { panelp->mVisibleAmt = 1.f; @@ -645,7 +646,7 @@ bool LLLayoutStack::animatePanels() { if (!mAnimatedThisFrame) { - panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); + panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 0.f, LLSmoothInterpolation::getInterpolant(mCloseTimeConstant)); if (panelp->mVisibleAmt < 0.001f) { panelp->mVisibleAmt = 0.f; @@ -672,7 +673,7 @@ bool LLLayoutStack::animatePanels() { if (!mAnimatedThisFrame) { - panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); + panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLSmoothInterpolation::getInterpolant(mCloseTimeConstant)); } if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f) @@ -710,7 +711,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& LLLayoutPanel* other_resize_panel = NULL; LLLayoutPanel* following_panel = NULL; - BOOST_REVERSE_FOREACH(LLLayoutPanel* panelp, mPanels) + for(LLLayoutPanel* panelp : boost::adaptors::reverse(mPanels)) { if (panelp->mAutoResize) { @@ -759,7 +760,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& AFTER_RESIZED_PANEL } which_panel = BEFORE_RESIZED_PANEL; - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + for (LLLayoutPanel* panelp : mPanels) { if (!panelp->getVisible() || panelp->mCollapsed) { @@ -789,7 +790,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& fraction_given_up -= new_fractional_size - panelp->mFractionalSize; fraction_remaining -= panelp->mFractionalSize; panelp->mFractionalSize = new_fractional_size; - llassert(!llisnan(panelp->mFractionalSize)); + llassert(!std::isnan(panelp->mFractionalSize)); } else { @@ -805,7 +806,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& fraction_given_up -= new_fractional_size - panelp->mFractionalSize; fraction_remaining -= panelp->mFractionalSize; panelp->mFractionalSize = new_fractional_size; - llassert(!llisnan(panelp->mFractionalSize)); + llassert(!std::isnan(panelp->mFractionalSize)); } else { // freeze new size as original size @@ -867,7 +868,7 @@ void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent) void LLLayoutStack::updateResizeBarLimits() { LLLayoutPanel* previous_visible_panelp = NULL; - BOOST_REVERSE_FOREACH(LLLayoutPanel* visible_panelp, mPanels) + for(LLLayoutPanel* visible_panelp : boost::adaptors::reverse(mPanels)) { if (!visible_panelp->getVisible() || visible_panelp->mCollapsed) { diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 66b8d64ec7..87ee96dfe1 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -43,18 +43,18 @@ #include "lltimer.h" #include "llcalc.h" -//#include "llclipboard.h" +#include "llclipboard.h" #include "llcontrol.h" #include "llbutton.h" #include "llfocusmgr.h" #include "llkeyboard.h" +#include "llmenugl.h" #include "llrect.h" #include "llresmgr.h" #include "llstring.h" #include "llwindow.h" #include "llui.h" #include "lluictrlfactory.h" -#include "llclipboard.h" #include "../newview/lgghunspell_wrapper.h" // @@ -178,19 +178,9 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect, sImage = LLUI::getUIImage("sm_rounded_corners_simple.tga"); } mImage = sImage; + // make the popup menu available - //LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_texteditor.xml", parent_view); - LLMenuGL* menu = new LLMenuGL("wot"); - /*if (!menu) - { - menu = new LLMenuGL(LLStringUtil::null); - }*/ - menu->addChild(new LLMenuItemCallGL("Cut", context_cut, NULL, this)); - menu->addChild(new LLMenuItemCallGL("Copy", context_copy, NULL, this)); - menu->addChild(new LLMenuItemCallGL("Paste", context_paste, NULL, this)); - menu->addChild(new LLMenuItemCallGL("Delete", context_delete, NULL, this)); - menu->addChild(new LLMenuItemCallGL("Select All", context_selectall, NULL, this)); - menu->addSeparator(); + LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_texteditor.xml", LLMenuGL::sMenuContainer); //menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor")); menu->setCanTearOff(FALSE); menu->setVisible(FALSE); @@ -432,6 +422,13 @@ void LLLineEditor::setCursorToEnd() deselect(); } +void LLLineEditor::resetScrollPosition() +{ + mScrollHPos = 0; + // make sure cursor stays in visible range + setCursor(getCursor()); +} + BOOL LLLineEditor::canDeselect() const { return hasSelection(); @@ -445,40 +442,9 @@ void LLLineEditor::deselect() } -void LLLineEditor::context_cut(void* data) -{ - LLLineEditor* line = (LLLineEditor*)data; - if(line)line->cut(); -} -void LLLineEditor::context_copy(void* data) -{ - LLLineEditor* line = (LLLineEditor*)data; - if(line)line->copy(); -} - - -void LLLineEditor::spell_correct(void* data) -{ - SpellMenuBind* tempBind = (SpellMenuBind*)data; - LLLineEditor* line = tempBind->origin; - if(tempBind && line) - { - LL_INFOS() << ((LLMenuItemCallGL *)(tempBind->menuItem))->getName() << " : " << tempBind->origin->getName() << " : " << tempBind->word << LL_ENDL; - if(line)line->spellReplace(tempBind); - } -} - - -void LLLineEditor::spell_show(void * data) +void LLLineEditor::spell_show(void* show) { - SpellMenuBind* tempBind = (SpellMenuBind*)data; - LLLineEditor* line = tempBind->origin; - - if (tempBind && line) - { - BOOL show = (tempBind->word == "Show Misspellings"); - glggHunSpell->setSpellCheckHighlight(show); - } + glggHunSpell->setSpellCheckHighlight(!!show); } std::vector LLLineEditor::getMisspelledWordsPositions() @@ -530,33 +496,15 @@ std::vector LLLineEditor::getMisspelledWordsPositions() void LLLineEditor::spell_add(void* data) { - SpellMenuBind* tempBind = (SpellMenuBind*)data; - if(tempBind) + auto self = static_cast(data); + S32 wordStart = 0, wordLen = 0; + if (self->getWordBoundriesAt(self->calculateCursorFromMouse(self->mLastContextMenuX), &wordStart, &wordLen)) { - glggHunSpell->addWordToCustomDictionary(tempBind->word); - tempBind->origin->mPrevSpelledText="";//make it update + glggHunSpell->addWordToCustomDictionary(wstring_to_utf8str(self->getWText().substr(wordStart, wordLen))); + self->mPrevSpelledText.clear(); //make it update } } - -void LLLineEditor::context_paste(void* data) -{ - LLLineEditor* line = (LLLineEditor*)data; - if(line)line->paste(); -} - -void LLLineEditor::context_delete(void* data) -{ - LLLineEditor* line = (LLLineEditor*)data; - if(line)line->doDelete(); -} - -void LLLineEditor::context_selectall(void* data) -{ - LLLineEditor* line = (LLLineEditor*)data; - if(line)line->selectAll(); -} - void LLLineEditor::startSelection() { mIsSelecting = TRUE; @@ -1171,7 +1119,7 @@ BOOL LLLineEditor::canCopy() const // copy selection to clipboard -void LLLineEditor::copy() +void LLLineEditor::copy() const { if( canCopy() ) { @@ -1182,12 +1130,19 @@ void LLLineEditor::copy() } -void LLLineEditor::spellReplace(SpellMenuBind* spellData) +void LLLineEditor::spell_correct(void* data) { - mText.erase(spellData->wordPositionStart, - spellData->wordPositionEnd - spellData->wordPositionStart); - insert(spellData->word,spellData->wordPositionStart); - mCursorPos+=spellData->word.length() - (spellData->wordPositionEnd-spellData->wordPositionStart); + auto self = static_cast(data); + S32 wordStart = 0, wordLen = 0; + if (self->getWordBoundriesAt(self->calculateCursorFromMouse(self->mLastContextMenuX), &wordStart, &wordLen)) + { + auto word = utf8str_to_wstring(LLMenuGL::sMenuContainer->getActivatedItem()->getLabel()); + LLWStringUtil::replaceTabsWithSpaces(word, 4); + + self->mText.erase(wordStart, wordLen); + self->mText.insert(wordStart, word); + self->mCursorPos += word.length() - wordLen; + } } @@ -1497,8 +1452,9 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) break; case KEY_RETURN: + if (getCommitOnReturn()) onCommit(); // store sent line in history - updateHistory(); + else updateHistory(); break; case KEY_ESCAPE: @@ -2519,7 +2475,7 @@ BOOL LLLineEditor::evaluateFloat() else { // Replace the expression with the result - std::string result_str = llformat("%f", result); + std::string result_str = fmt::to_string(result); setText(result_str); selectAll(); } @@ -3049,102 +3005,47 @@ void LLLineEditor::showContextMenu(S32 x, S32 y) { gEditMenuHandler = this; - /*S32 screen_x, screen_y; - localPointToScreen(x, y, &screen_x, &screen_y); - menu->show(screen_x, screen_y);*/ - - - //setCursorAtLocalPos( x); - S32 wordStart = 0; - S32 wordLen = 0; - S32 pos = calculateCursorFromMouse(x); + if(menu->isOpen()) + { + menu->setVisible(FALSE); + } - LLMenuGL* menu = (LLMenuGL*)mContextMenuHandle.get(); - if (menu) + // spell_check="true" in xui + if (!mReadOnly && mSpellCheckable) { - if(menu->isOpen()) - { - menu->setVisible(FALSE); - } - for (int i = 0;i<(int)suggestionMenuItems.size();i++) - { - SpellMenuBind * tempBind = suggestionMenuItems[i]; - if(tempBind) - { - menu->removeChild((LLMenuItemCallGL *)tempBind->menuItem); - ((LLMenuItemCallGL *)tempBind->menuItem)->die(); - //delete tempBind->menuItem; - //tempBind->menuItem = NULL; - delete tempBind; - } - } - suggestionMenuItems.clear(); + constexpr auto spell_sep = "Spell Check Sep"; + // Remove everything after the separator if we added it, because menus don't autodie yet. + menu->erase(menu->find(menu->findChild(spell_sep)), menu->end()); + menu->addSeparator(spell_sep); - // spell_check="true" in xui - menu->setItemVisible("Spelsep", !mReadOnly && mSpellCheckable); - if (!mReadOnly && mSpellCheckable) + // search for word matches + S32 wordStart = 0; + S32 wordLen = 0; + S32 pos = calculateCursorFromMouse(x); + if (getWordBoundriesAt(pos, &wordStart, &wordLen)) { - // search for word matches - bool is_word_part = getWordBoundriesAt(pos, &wordStart, &wordLen); - if (is_word_part) - { - const LLWString& text = mText.getWString(); - std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart,wordLen)); - - if (!glggHunSpell->isSpelledRight(selectedWord)) - { - //misspelled word here, and you have just right clicked on it! - std::vector suggs = glggHunSpell->getSuggestionList(selectedWord); - - for (int i = 0; i<(int)suggs.size() ;i++) - { - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - tempStruct->word = suggs[i]; - tempStruct->wordPositionEnd = wordStart + wordLen; - tempStruct->wordPositionStart=wordStart; - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - tempStruct->word, spell_correct, NULL, tempStruct); - //new LLMenuItemCallGL("Select All", context_selectall, NULL, this)); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); - } - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - tempStruct->word = selectedWord; - tempStruct->wordPositionEnd = wordStart + wordLen; - tempStruct->wordPositionStart=wordStart; - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - "Add Word", spell_add, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); - } - } + const auto selectedWord = wstring_to_utf8str(getWText().substr(wordStart, wordLen)); - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - if (glggHunSpell->getSpellCheckHighlight()) - { - tempStruct->word = "Hide Misspellings"; - } - else + if (!glggHunSpell->isSpelledRight(selectedWord)) { - tempStruct->word = "Show Misspellings"; + //misspelled word here, and you have just right clicked on it! + + for (const auto& word : glggHunSpell->getSuggestionList(selectedWord)) + { + menu->addChild(new LLMenuItemCallGL(word, spell_correct, nullptr, this)); + } + menu->addChild(new LLMenuItemCallGL("Add Word", spell_add, nullptr, this)); } - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - tempStruct->word, spell_show, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); } - mLastContextMenuX = x; - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, menu, x, y); + bool show = !glggHunSpell->getSpellCheckHighlight(); + menu->addChild(new LLMenuItemCallGL(show ? "Show Misspellings" : "Hide Misspellings", spell_show, nullptr, show ? menu : nullptr)); } + + mLastContextMenuX = x; + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, menu, x, y); } } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 91a7983f4a..ec002a452a 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -101,23 +101,13 @@ class LLLineEditor /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char); /*virtual*/ void onMouseCaptureLost(); - struct SpellMenuBind - { - LLLineEditor* origin; - void * menuItem; - std::string word; - S32 wordPositionStart; - S32 wordPositionEnd; - }; - - virtual void spellReplace(SpellMenuBind* spellData); virtual void insert(std::string what,S32 wher); // LLEditMenuHandler overrides virtual void cut(); virtual BOOL canCut() const; - virtual void copy(); + void copy() const override final; virtual BOOL canCopy() const; virtual void paste(); @@ -137,11 +127,6 @@ class LLLineEditor virtual void deselect(); virtual BOOL canDeselect() const; - static void context_cut(void* data); - static void context_copy(void* data); - static void context_paste(void* data); - static void context_delete(void* data); - static void context_selectall(void* data); static void spell_correct(void* data); static void spell_show(void* data); static void spell_add(void* data); @@ -190,6 +175,9 @@ class LLLineEditor void setCursor( S32 pos ); void setCursorToEnd(); + // set scroll to earliest position it can reasonably be set + void resetScrollPosition(); + // Selects characters 'start' to 'end'. void setSelection(S32 start, S32 end); @@ -306,7 +294,6 @@ class LLLineEditor S32 mEndSpellHere; // the location of the last char on the screen BOOL mSpellCheckable; // set in xui as "spell_check". Default value for a field LLFrameTimer mSpellTimer; - std::vector suggestionMenuItems; S32 mLastContextMenuX; // line history support: diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp new file mode 100644 index 0000000000..915571874f --- /dev/null +++ b/indra/llui/llloadingindicator.cpp @@ -0,0 +1,104 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +/** + * @file llloadingindicator.cpp + * @brief Perpetual loading indicator + * + * $LicenseInfo:firstyear=2010&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 "llloadingindicator.h" + +// Linden library includes +#include "llsingleton.h" + +// Project includes +#include "lluictrlfactory.h" +#include "lluiimage.h" + +static LLRegisterWidget r("loading_indicator"); + +/////////////////////////////////////////////////////////////////////////////// +// LLLoadingIndicator class +/////////////////////////////////////////////////////////////////////////////// + +LLLoadingIndicator::LLLoadingIndicator(const Params& p) +: LLUICtrl(p), + mImagesPerSec(p.images_per_sec > 0 ? p.images_per_sec : 1.0f), + mCurImageIdx(0) +{ +} + +void LLLoadingIndicator::initFromParams(const Params& p) +{ + for (LLUIImage* image : p.images().image) + { + mImages.push_back(image); + } + + if (mImages.empty()) // Singu Note: We don't have default widgets yet, so let's just handle this here + for (int i = 1; i <= 12; ++i) + mImages.push_back(LLUI::getUIImage(llformat("Progress_%d", i))); + + // Start timer for switching images. + start(); +} + +void LLLoadingIndicator::draw() +{ + // Time to switch to the next image? + if (mImageSwitchTimer.getStarted() && mImageSwitchTimer.hasExpired()) + { + // Switch to the next image. + if (!mImages.empty()) + { + mCurImageIdx = (mCurImageIdx + 1) % mImages.size(); + } + + // Restart timer. + start(); + } + + LLUIImagePtr cur_image = mImages.empty() ? LLUIImagePtr(NULL) : mImages[mCurImageIdx]; + + // Draw current image. + if( cur_image.notNull() ) + { + cur_image->draw(getLocalRect(), LLColor4::white % getDrawContext().mAlpha); + } + + LLUICtrl::draw(); +} + +void LLLoadingIndicator::stop() +{ + mImageSwitchTimer.stop(); +} + +void LLLoadingIndicator::start() +{ + mImageSwitchTimer.start(); + F32 period = 1.0f / (mImages.size() * mImagesPerSec); + mImageSwitchTimer.setTimerExpirySec(period); +} diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h new file mode 100644 index 0000000000..b5e86c0ac1 --- /dev/null +++ b/indra/llui/llloadingindicator.h @@ -0,0 +1,104 @@ +/** + * @file llloadingindicator.h + * @brief Perpetual loading indicator + * + * $LicenseInfo:firstyear=2010&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_LLLOADINGINDICATOR_H +#define LL_LLLOADINGINDICATOR_H + +#include "lluictrl.h" +#include "lluiimage.h" + +/////////////////////////////////////////////////////////////////////////////// +// class LLLoadingIndicator +/////////////////////////////////////////////////////////////////////////////// + +/** + * Perpetual loading indicator (a la MacOSX or YouTube) + * + * Number of rotations per second can be overridden + * with the "images_per_sec" parameter. + * + * Can start/stop spinning. + * + * @see start() + * @see stop() + */ +class LLLoadingIndicator +: public LLUICtrl +{ + LOG_CLASS(LLLoadingIndicator); +public: + + struct Images : public LLInitParam::Block + { + Multiple image; + + Images() + : image("image") + {} + }; + + struct Params : public LLInitParam::Block + { + Optional images_per_sec; + Optional > images; + + Params() + : images_per_sec("images_per_sec", 1.0f), + images("images") + {} + }; + + virtual ~LLLoadingIndicator() {} + + // llview overrides + void draw() override; + + /** + * Stop spinning. + */ + void stop(); + + /** + * Start spinning. + */ + void start(); + + void reset() { mCurImageIdx = 0; } + +private: + LLLoadingIndicator(const Params&); + void initFromParams(const Params&); + + friend class LLUICtrlFactory; + + F32 mImagesPerSec; + S8 mCurImageIdx; + LLFrameTimer mImageSwitchTimer; + + std::vector mImages; +}; + +#endif // LL_LLLOADINGINDICATOR_H diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp index f3a526faeb..cacc9e0224 100644 --- a/indra/llui/lllocalcliprect.cpp +++ b/indra/llui/lllocalcliprect.cpp @@ -33,14 +33,13 @@ LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled) -: mScissorState(GL_SCISSOR_TEST), - mEnabled(enabled) +: mScissorState(enabled), + mEnabled(enabled), + mRootScissorRect(gGL.getScissor()) { if (mEnabled) { pushClipRect(rect); - mScissorState.setEnabled(!sClipRectStack.empty()); - updateScissorRegion(); } } @@ -49,11 +48,9 @@ LLScreenClipRect::~LLScreenClipRect() if (mEnabled) { popClipRect(); - updateScissorRegion(); } } -//static void LLScreenClipRect::pushClipRect(const LLRect& rect) { LLRect combined_clip_rect = rect; @@ -68,23 +65,27 @@ void LLScreenClipRect::pushClipRect(const LLRect& rect) combined_clip_rect = LLRect::null; } } + sClipRectStack.push(combined_clip_rect); + updateScissorRegion(); } -//static void LLScreenClipRect::popClipRect() { sClipRectStack.pop(); + if (!sClipRectStack.empty()) + { + updateScissorRegion(); + } + else + { + gGL.setScissor(mRootScissorRect); + } } -//static +// static void LLScreenClipRect::updateScissorRegion() { - if (sClipRectStack.empty()) return; - - // finish any deferred calls in the old clipping region - gGL.flush(); - LLRect rect = sClipRectStack.top(); stop_glerror(); S32 x,y,w,h; @@ -92,7 +93,7 @@ void LLScreenClipRect::updateScissorRegion() y = llfloor(rect.mBottom * LLUI::getScaleFactor().mV[VY]); w = llmax(0, llceil(rect.getWidth() * LLUI::getScaleFactor().mV[VX])) + 1; h = llmax(0, llceil(rect.getHeight() * LLUI::getScaleFactor().mV[VY])) + 1; - glScissor( x,y,w,h ); + gGL.setScissor( x,y,w,h ); stop_glerror(); } diff --git a/indra/llui/lllocalcliprect.h b/indra/llui/lllocalcliprect.h index eeeaf2adb6..18b0eccade 100644 --- a/indra/llui/lllocalcliprect.h +++ b/indra/llui/lllocalcliprect.h @@ -42,13 +42,14 @@ class LLScreenClipRect virtual ~LLScreenClipRect(); private: - static void pushClipRect(const LLRect& rect); - static void popClipRect(); + void pushClipRect(const LLRect& rect); + void popClipRect(); static void updateScissorRegion(); private: - LLGLState mScissorState; - BOOL mEnabled; + LLGLState mScissorState; + const BOOL mEnabled; + const LLRect mRootScissorRect; static std::stack sClipRectStack; }; diff --git a/indra/llui/llmemberlistener.h b/indra/llui/llmemberlistener.h index a70ab926ba..9b90c757bf 100644 --- a/indra/llui/llmemberlistener.h +++ b/indra/llui/llmemberlistener.h @@ -8,7 +8,7 @@ * (in header) * * class T { - * class LLDoTest : public LLMemberListener + * class LLDoTest : public LLMemberListener * { * bool handleEvent(LLPointer event, const LLSD& userdata); * }; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 7470f5d5ba..d7175b9aa2 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -70,10 +70,9 @@ using namespace LLOldEvents; // static -LLMenuHolderGL *LLMenuGL::sMenuContainer = NULL; +LLMenuHolderGL *LLMenuGL::sMenuContainer = nullptr; S32 MENU_BAR_HEIGHT = 0; -S32 MENU_BAR_WIDTH = 0; ///============================================================================ /// Local function declarations, constants, enums, and typedefs @@ -258,7 +257,7 @@ BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask) // if not, it will be added to the list BOOL LLMenuItemGL::addToAcceleratorList(std::list *listp) { - LLKeyBinding *accelerator = NULL; + LLKeyBinding *accelerator = nullptr; if (mAcceleratorKey != KEY_NONE) { @@ -268,19 +267,37 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list *listp) accelerator = *list_it; if ((accelerator->mKey == mAcceleratorKey) && (accelerator->mMask == (mAcceleratorMask & MASK_NORMALKEYS))) { + + // *NOTE: get calling code to throw up warning or route + // warning messages back to app-provided output + // std::string warning; + // warning.append("Duplicate key binding <"); + // appendAcceleratorString( warning ); + // warning.append("> for menu items:\n "); + // warning.append(accelerator->mName); + // warning.append("\n "); + // warning.append(mLabel); + + // LL_WARNS() << warning << LL_ENDL; + // LLAlertDialog::modalAlert(warning); return FALSE; } } if (!accelerator) { - accelerator = new LLKeyBinding; - if (accelerator) + try { + accelerator = new LLKeyBinding; accelerator->mKey = mAcceleratorKey; accelerator->mMask = (mAcceleratorMask & MASK_NORMALKEYS); // accelerator->mName = mLabel; + listp->push_back(accelerator);//addData(accelerator); + } + catch (const std::bad_alloc& e) + { + LL_WARNS() << "Failed to allocate memory for keybinding with exception: " << e.what() << LL_ENDL; + return FALSE; } - listp->push_back(accelerator);//addData(accelerator); } } return TRUE; @@ -675,16 +692,17 @@ BOOL LLMenuItemSeparatorGL::handleHover(S32 x, S32 y, MASK mask) // This class represents a vertical separator. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLMenuItemVerticalSeparatorGL +class LLMenuItemVerticalSeparatorGL final : public LLMenuItemSeparatorGL { public: - LLMenuItemVerticalSeparatorGL( void ); + LLMenuItemVerticalSeparatorGL(const std::string& name = LLStringUtil::null); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; } + BOOL handleMouseDown(S32 x, S32 y, MASK mask) override { return FALSE; } }; -LLMenuItemVerticalSeparatorGL::LLMenuItemVerticalSeparatorGL( void ) +LLMenuItemVerticalSeparatorGL::LLMenuItemVerticalSeparatorGL(const std::string& name) +: LLMenuItemSeparatorGL(name) { setLabel( VERTICAL_SEPARATOR_LABEL ); } @@ -733,7 +751,7 @@ LLFloater* LLMenuItemTearOffGL::getParentFloater() } } - return NULL; + return nullptr; } void LLMenuItemTearOffGL::onCommit() @@ -809,15 +827,15 @@ U32 LLMenuItemTearOffGL::getNominalHeight( void ) const // This class represents a blank, non-functioning item. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLMenuItemBlankGL : public LLMenuItemGL +class LLMenuItemBlankGL final : public LLMenuItemGL { public: - LLMenuItemBlankGL( void ) : LLMenuItemGL( LLStringUtil::null, LLStringUtil::null ) + LLMenuItemBlankGL(const std::string& name = LLStringUtil::null) : LLMenuItemGL(name, LLStringUtil::null) { setEnabled(FALSE); } - virtual void onCommit( void ) {} - virtual void draw( void ) {} + void onCommit() override {} + void draw() override {} }; @@ -1509,11 +1527,18 @@ void LLMenuItemBranchGL::openMenu() branch->localPointToOtherView( 0, 0, &x, &y, branch->getParent() ); F32 center_y = top - (getRect().getHeight() / 2.f); + if( y < menu_region_rect.mBottom && center_y <= menu_region_rect.getCenterY()) { // open upwards if menu extends past bottom // adjust by the height of the menu item branch since it is a submenu - delta_y = branch_rect.getHeight() - getRect().getHeight(); + delta_y = branch_rect.getHeight() - getRect().getHeight(); + // Singu: Handle menu clipping off the top of the screen too. + if ( branch_rect.mTop + delta_y > menu_region_rect.mTop ) + { + delta_y -= branch_rect.mTop + delta_y - menu_region_rect.mTop; + delta_y -= delta_y % getRect().getHeight(); + } } if( x + branch_rect.getWidth() > menu_region_rect.mRight ) @@ -2084,13 +2109,13 @@ LLXMLNodePtr LLMenuGL::getXML(bool save_children) const return node; } -void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory *factory) +void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent) { std::string name(child->getName()->mString); if (child->hasName(LL_MENU_GL_TAG)) { // SUBMENU - LLMenuGL *submenu = (LLMenuGL*)LLMenuGL::fromXML(child, parent, factory); + LLMenuGL *submenu = (LLMenuGL*)LLMenuGL::fromXML(child, parent, LLUICtrlFactory::getInstance()); appendMenu(submenu); if (LLMenuGL::sMenuContainer != NULL) { @@ -2168,7 +2193,7 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory { mask |= MASK_SHIFT; } - S32 pipe_pos = shortcut.rfind("|"); + S32 pipe_pos = shortcut.rfind('|'); std::string key_str = shortcut.substr(pipe_pos+1); KEY key = KEY_NONE; @@ -2446,63 +2471,80 @@ BOOL LLMenuGL::isOpen() } } // static -LLView* LLMenuGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +LLView* LLMenuGL::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory* factory) { std::string name("menu"); node->getAttributeString("name", name); - std::string label = name; - node->getAttributeString("label", label); + LLMenuGL* menu = new LLMenuGL(name); - LLStringUtil::format(label, LLTrans::getDefaultArgs()); - - // parse jump key out of label - std::string new_menu_label; + // Menus can be extended using filename + if (node->hasAttribute("filename")) + { + std::string filename; + node->getAttributeString("filename", filename); + LLXMLNodePtr root; + LLUICtrlFactory::getLayeredXMLNode(filename, root); + menu->initMenuXML(root, parent); + } + menu->initMenuXML(node, parent); - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("_"); - tokenizer tokens(label, sep); - tokenizer::iterator token_iter; + return menu; +} - KEY jump_key = KEY_NONE; - S32 token_count = 0; - for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) +void LLMenuGL::initMenuXML(LLXMLNodePtr node, LLView* parent) +{ + std::string label; + if (node->getAttributeString("label", label)) { - new_menu_label += (*token_iter); - if (token_count > 0) + LLStringUtil::format(label, LLTrans::getDefaultArgs()); + + // parse jump key out of label + std::string new_menu_label; + + typedef boost::tokenizer> tokenizer; + boost::char_separator sep("_"); + + KEY jump_key = KEY_NONE; + S32 token_count = 0; + for (auto token : tokenizer(label, sep)) { - jump_key = (*token_iter).c_str()[0]; + new_menu_label += token; + if (token_count > 0) + { + jump_key = token.front(); + } + ++token_count; } - ++token_count; + + setLabel(new_menu_label); + setJumpKey(jump_key); } BOOL opaque = TRUE; node->getAttributeBOOL("opaque", opaque); - LLMenuGL *menu = new LLMenuGL(name, new_menu_label); - bool b(false); node->getAttribute_bool("scrollable", b); - menu->setScrollable(b); + setScrollable(b); - menu->setJumpKey(jump_key); BOOL tear_off = FALSE; node->getAttributeBOOL("tear_off", tear_off); - menu->setCanTearOff(tear_off); + setCanTearOff(tear_off); if (node->hasAttribute("drop_shadow")) { BOOL drop_shadow = FALSE; node->getAttributeBOOL("drop_shadow", drop_shadow); - menu->setDropShadowed(drop_shadow); + setDropShadowed(drop_shadow); } - menu->setBackgroundVisible(opaque); + setBackgroundVisible(opaque); LLColor4 color(0,0,0,1); if (opaque && LLUICtrlFactory::getAttributeColor(node,"color", color)) { - menu->setBackgroundColor(color); + setBackgroundColor(color); } BOOL create_jump_keys = FALSE; @@ -2511,14 +2553,13 @@ LLView* LLMenuGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa LLXMLNodePtr child; for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) { - menu->parseChildXML(child, parent, factory); + parseChildXML(child, parent); } if (create_jump_keys) { - menu->createJumpKeys(); + createJumpKeys(); } - return menu; } @@ -3126,12 +3167,7 @@ void LLMenuGL::erase( S32 begin, S32 end, bool arrange/* = true*/) item_list_t::iterator end_position = mItems.begin(); std::advance(end_position, end); - for (item_list_t::iterator position_iter = start_position; position_iter != end_position; position_iter++) - { - LLUICtrl::removeChild(*position_iter); - } - - mItems.erase(start_position, end_position); + erase(start_position, end_position); if (arrange) { @@ -3153,7 +3189,7 @@ void LLMenuGL::insert(S32 position, LLView* ctrl, bool arrange /*= true*/) std::advance(position_iter, position); insert(position_iter, item, arrange); } -void LLMenuGL::insert(item_list_t::iterator position_iter, LLMenuItemGL* item, bool arrange /*= true*/) +void LLMenuGL::insert(item_list_t::const_iterator position_iter, LLMenuItemGL* item, bool arrange /*= true*/) { mItems.insert(position_iter, item); LLUICtrl::addChild(item); @@ -3203,9 +3239,9 @@ BOOL LLMenuGL::append( LLMenuItemGL* item ) } // add a separator to this menu -BOOL LLMenuGL::addSeparator() +BOOL LLMenuGL::addSeparator(const std::string& name) { - LLMenuItemGL* separator = new LLMenuItemSeparatorGL(); + LLMenuItemGL* separator = new LLMenuItemSeparatorGL(name); return addChild(separator); } @@ -3292,11 +3328,6 @@ void LLMenuGL::setTornOff(BOOL torn_off) mTornOff = torn_off; } -U32 LLMenuGL::getItemCount() -{ - return mItems.size(); -} - LLMenuItemGL* LLMenuGL::getItem(S32 number) { if (number >= 0 && number < (S32)mItems.size()) @@ -4157,10 +4188,10 @@ S32 LLMenuBarGL::getRightmostMenuEdge() } // add a vertical separator to this menu -BOOL LLMenuBarGL::addSeparator() +BOOL LLMenuBarGL::addSeparator(const std::string& name) { - LLMenuItemGL* separator = new LLMenuItemVerticalSeparatorGL(); - return append( separator ); + LLMenuItemGL* separator = new LLMenuItemVerticalSeparatorGL(name); + return append(separator); } // add a menu - this will create a drop down menu. @@ -4502,7 +4533,7 @@ void LLTearOffMenu::draw() if (getRect().getHeight() != mTargetHeight) { // animate towards target height - reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), mTargetHeight, LLCriticalDamp::getInterpolant(0.05f)))); + reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), mTargetHeight, LLSmoothInterpolation::getInterpolant(0.05f)))); } LLFloater::draw(); } @@ -4751,7 +4782,7 @@ void LLContextMenu::initXML(LLXMLNodePtr node, LLView *context, LLUICtrlFactory } else { - parseChildXML(child, context, factory); + parseChildXML(child, context); } } } @@ -4866,7 +4897,7 @@ void LLContextMenu::hide() { mHoverItem->setHighlight( FALSE ); } - mHoverItem = NULL; + mHoverItem = nullptr; } @@ -4976,7 +5007,11 @@ bool LLContextMenu::addChild(LLView* view, S32 tab_group) if (LLContextMenu* context = dynamic_cast(view)) return appendContextSubMenu(context); if (LLMenuItemGL* item = dynamic_cast(view)) + { + if (!mItems.empty() && mItems.back()->getType() == "separator" && item->getType() == "separator") // Singu TODO: Profile this? Does it matter? + item->setVisible(false); return append(item); + } if (LLMenuGL* menu = dynamic_cast(view)) return appendMenu(menu); return false; @@ -5017,7 +5052,7 @@ LLPieMenu::LLPieMenu(const std::string& name, const std::string& label) // Separators on pie menus are invisible bool LLPieMenu::addChild(LLView* view, S32 tab_group) { - if (LLContextMenu::addChild(view, tab_group)) + if (LLContextMenu::addChild(view, tab_group) && view->getVisible()) { LLMenuItemSeparatorGL* sep = dynamic_cast(view); if(sep) @@ -5235,30 +5270,30 @@ void LLPieMenu::draw() mHoverIndex = -1; } - F32 width = (F32) getRect().getWidth(); - F32 height = (F32) getRect().getHeight(); - mCurRadius = PIE_SCALE_FACTOR * llmax( width/2, height/2 ); + const auto& rect = getRect(); + // correct for non-square pixels + F32 center_x = ((F32) rect.getWidth())/2; + F32 center_y = ((F32) rect.getHeight())/2; + constexpr S32 steps = 100; + mCurRadius = PIE_SCALE_FACTOR * llmax(center_x, center_y); mOuterRingAlpha = mUseInfiniteRadius ? 0.f : 1.f; if (mShrinkBorderTimer.getStarted()) { - mOuterRingAlpha = clamp_rescale(mShrinkBorderTimer.getElapsedTimeF32(), 0.f, PIE_SHRINK_TIME, 0.f, 1.f); - mCurRadius *= clamp_rescale(mShrinkBorderTimer.getElapsedTimeF32(), 0.f, PIE_SHRINK_TIME, 1.f, 1.f / PIE_SCALE_FACTOR); + const auto& elapsed = mShrinkBorderTimer.getElapsedTimeF32(); + mOuterRingAlpha = clamp_rescale(elapsed, 0.f, PIE_SHRINK_TIME, 0.f, 1.f); + mCurRadius *= clamp_rescale(elapsed, 0.f, PIE_SHRINK_TIME, 1.f, 1.f / PIE_SCALE_FACTOR); } - // correct for non-square pixels - F32 center_x = width/2; - F32 center_y = height/2; - S32 steps = 100; gGL.pushUIMatrix(); { gGL.translateUI(center_x, center_y, 0.f); - F32 line_width = LLUI::sConfigGroup->getF32("PieMenuLineWidth"); - LLColor4 line_color = LLUI::sColorsGroup->getColor("PieMenuLineColor"); - LLColor4 bg_color = LLUI::sColorsGroup->getColor("PieMenuBgColor"); - LLColor4 selected_color = LLUI::sColorsGroup->getColor("PieMenuSelectedColor"); + static const LLUICachedControl line_width("PieMenuLineWidth"); + static const LLCachedControl line_color(*LLUI::sColorsGroup, "PieMenuLineColor"); + static const LLCachedControl bg_color(*LLUI::sColorsGroup, "PieMenuBgColor"); + static const LLCachedControl selected_color(*LLUI::sColorsGroup, "PieMenuSelectedColor"); // main body LLColor4 outer_color = bg_color; @@ -5268,7 +5303,7 @@ void LLPieMenu::draw() // selected wedge if (mHoverItem) { - F32 arc_size = F_PI * 0.25f; + constexpr F32 arc_size = F_PI * 0.25f; F32 start_radians = (mHoverIndex * arc_size) - (arc_size * 0.5f); F32 end_radians = start_radians + arc_size; @@ -5286,7 +5321,7 @@ void LLPieMenu::draw() gl_washer_spokes_2d( mCurRadius, (F32)PIE_CENTER_SIZE, 8, line_color, outer_color ); // inner circle - gGL.color4fv( line_color.mV ); + gGL.color4fv( line_color().mV ); gl_circle_2d( 0, 0, (F32)PIE_CENTER_SIZE, steps, FALSE ); // outer circle @@ -5317,9 +5352,9 @@ BOOL LLPieMenu::append(LLMenuItemGL *item) } // virtual -BOOL LLPieMenu::addSeparator() +BOOL LLPieMenu::addSeparator(const std::string& name) { - return append( new LLMenuItemBlankGL() ); + return append(new LLMenuItemBlankGL(name)); } // virtual diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 4c58113210..d63b294d80 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -47,7 +47,6 @@ extern S32 MENU_BAR_HEIGHT; -extern S32 MENU_BAR_WIDTH; // These callbacks are used by the LLMenuItemCallGL and LLMenuItemCheckGL // classes during their work. @@ -458,8 +457,9 @@ class LLMenuGL virtual ~LLMenuGL( void ); virtual LLXMLNodePtr getXML(bool save_children = true) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); + void initMenuXML(LLXMLNodePtr node, LLView* parent); - void parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory *factory); + void parseChildXML(LLXMLNodePtr child, LLView *parent); // LLView Functionality /*virtual*/ BOOL handleUnicodeCharHere( llwchar uni_char ); @@ -490,7 +490,7 @@ class LLMenuGL void setCanTearOff(BOOL tear_off); // add a separator to this menu - virtual BOOL addSeparator(); + virtual BOOL addSeparator(const std::string& name = LLStringUtil::null); // for branching menu items, bring sub menus up to root level of menu hierarchy virtual void updateParent( LLView* parentp ); @@ -527,16 +527,31 @@ class LLMenuGL // erase group of items from menu void erase(S32 begin, S32 end, bool arrange = true); + typedef std::list item_list_t; + inline item_list_t::iterator erase(item_list_t::const_iterator first, item_list_t::const_iterator last) + { + for (auto it = first; it != last; ++it) + LLUICtrl::removeChild(*it); + return mItems.erase(first, last); + } // add new item at position void insert(S32 begin, LLView* ctrl, bool arrange = true); - void insert(std::list::iterator position_iter, LLMenuItemGL* item, bool arrange = true); + void insert(item_list_t::const_iterator position_iter, LLMenuItemGL* item, bool arrange = true); // find an item's position - std::list::iterator find(LLMenuItemGL* item) { return std::find(mItems.begin(), mItems.end(), item); } + item_list_t::const_iterator find(LLMenuItemGL* item) const { return std::find(mItems.begin(), mItems.end(), item); } + + // end of items, for use with other members that return an iterator + item_list_t::const_iterator end() const { return mItems.cend(); } + + // get list of items + const item_list_t& getItems() const { return mItems; } + + // number of menu items + item_list_t::size_type getItemCount() const { return mItems.size(); } void setItemLastSelected(LLMenuItemGL* item); // must be in menu - U32 getItemCount(); // number of menu items LLMenuItemGL* getItem(S32 number); // 0 = first item LLMenuItemGL* getHighlightedItem(); @@ -582,15 +597,17 @@ class LLMenuGL protected: void createSpilloverBranch(); void cleanupSpilloverBranch(); + +public: // Add the menu item to this menu. virtual BOOL append( LLMenuItemGL* item ); // add a menu - this will create a cascading menu virtual BOOL appendMenu( LLMenuGL* menu ); - // TODO: create accessor methods for these? - typedef std::list< LLMenuItemGL* > item_list_t; +protected: item_list_t mItems; + // TODO: create accessor methods for these? LLMenuItemGL*mFirstVisibleItem; LLMenuItemGL *mArrowUpItem, *mArrowDownItem; @@ -761,7 +778,7 @@ class LLPieMenu private: virtual BOOL append(LLMenuItemGL* item); public: - virtual BOOL addSeparator(); + virtual BOOL addSeparator(const std::string& name = LLStringUtil::null) override final; virtual void arrange( void ); @@ -841,7 +858,7 @@ class LLMenuBarGL : public LLMenuGL /*virtual*/ BOOL jumpKeysActive(); // add a vertical separator to this menu - virtual BOOL addSeparator(); + virtual BOOL addSeparator(const std::string& name = LLStringUtil::null) override final; // LLView Functionality virtual BOOL handleHover( S32 x, S32 y, MASK mask ); @@ -893,6 +910,7 @@ class LLMenuHolderGL : public LLPanel LLView*const getVisibleMenu() const; virtual BOOL hasVisibleMenu() const {return getVisibleMenu() != NULL;} + static LLMenuItemGL* getActivatedItem() { return static_cast(sItemLastSelectedHandle.get()); } static void setActivatedItem(LLMenuItemGL* item); // Need to detect if mouse-up after context menu spawn has moved. diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index f4643fa9e2..fa431d6766 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -466,7 +466,7 @@ void LLMultiSlider::draw() F32 opacity = getEnabled() ? 1.f : 0.3f; // Track - LLUIImagePtr thumb_imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr thumb_imagep = LLUI::getUIImage("Rounded_Square"); S32 height_offset = (getRect().getHeight() - MULTI_TRACK_HEIGHT) / 2; LLRect track_rect(0, getRect().getHeight() - height_offset, getRect().getWidth(), height_offset ); diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 3d66d0d36a..e2cdfa8ed3 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -74,8 +74,9 @@ class LLNotificationHistoryChannel : public LLNotificationChannel bool historyHandler(const LLSD& payload) { // we ignore "load" messages, but rewrite the persistence file on any other + // onDelete handes "delete" message, so skip that too. std::string sigtype = payload["sigtype"]; - if (sigtype != "load") + if (sigtype != "load" && sigtype != "delete") { savePersistentNotifications(); } @@ -85,11 +86,15 @@ class LLNotificationHistoryChannel : public LLNotificationChannel // The history channel gets all notifications except those that have been cancelled static bool historyFilter(LLNotificationPtr pNotification) { - return !pNotification->isCancelled(); + return pNotification->isPersistent() && !pNotification->isCancelled() && !pNotification->isRespondedTo() && !pNotification->isExpired(); } void savePersistentNotifications() { + if (mLoading) + { + return; + } LL_INFOS() << "Saving open notifications to " << mFileName << LL_ENDL; llofstream notify_file(mFileName.c_str()); @@ -104,6 +109,9 @@ class LLNotificationHistoryChannel : public LLNotificationChannel LLSD& data = output["data"]; AILOCK_mItems; + + static LLCachedControl maxPersistentNotificaitons("MaxPersistentNotifications"); + for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) { if (!LLNotificationTemplates::instance().templateExists((*it)->getName())) continue; @@ -111,7 +119,15 @@ class LLNotificationHistoryChannel : public LLNotificationChannel // only store notifications flagged as persisting LLNotificationTemplatePtr templatep = LLNotificationTemplates::instance().getTemplate((*it)->getName()); if (!templatep->mPersist) continue; + if ((*it)->isCancelled() || (*it)->isExpired() || (*it)->isRespondedTo()) continue; + if (data.size() >= maxPersistentNotificaitons) + { + LL_WARNS() << "Too many persistent notifications." + << " Saved " << maxPersistentNotificaitons << " of " << mItems.size() + << " persistent notifications." << LL_ENDL; + break; + } data.append((*it)->asLLSD()); } @@ -121,53 +137,75 @@ class LLNotificationHistoryChannel : public LLNotificationChannel void loadPersistentNotifications() { - LL_INFOS() << "Loading open notifications from " << mFileName << LL_ENDL; - - llifstream notify_file(mFileName.c_str()); - if (!notify_file.is_open()) + if (mLoading) { - LL_WARNS() << "Failed to open " << mFileName << LL_ENDL; return; } + mLoading = true; + LL_INFOS() << "Loading open notifications from " << mFileName << LL_ENDL; - LLSD input; - LLPointer parser = new LLSDXMLParser(); - if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0) + while (true) { - LL_WARNS() << "Failed to parse open notifications" << LL_ENDL; - return; - } + llifstream notify_file(mFileName.c_str()); + if (!notify_file.is_open()) + { + LL_WARNS() << "Failed to open " << mFileName << LL_ENDL; + break; + } - if (input.isUndefined()) return; - std::string version = input["version"]; - if (version != NOTIFICATION_PERSIST_VERSION) - { - LL_WARNS() << "Bad open notifications version: " << version << LL_ENDL; - return; - } - LLSD& data = input["data"]; - if (data.isUndefined()) return; + LLSD input; + LLPointer parser = new LLSDXMLParser(); + if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0) + { + LL_WARNS() << "Failed to parse open notifications" << LL_ENDL; + break; + } - LLNotifications& instance = LLNotifications::instance(); - for (LLSD::array_const_iterator notification_it = data.beginArray(); - notification_it != data.endArray(); - ++notification_it) - { - instance.add(LLNotificationPtr(new LLNotification(*notification_it))); + if (input.isUndefined()) return; + std::string version = input["version"]; + if (version != NOTIFICATION_PERSIST_VERSION) + { + LL_WARNS() << "Bad open notifications version: " << version << LL_ENDL; + break; + } + LLSD& data = input["data"]; + if (data.isUndefined()) break; + + S32 processed_notifications = 0; + static LLCachedControl maxPersistentNotificaitons("MaxPersistentNotifications"); + + LLNotifications& instance = LLNotifications::instance(); + for (LLSD::array_const_iterator notification_it = data.beginArray(); + notification_it != data.endArray(); + ++notification_it) + { + if (processed_notifications++ >= maxPersistentNotificaitons) + { + LL_WARNS() << "Too many persistent notifications." + << " Processed " << maxPersistentNotificaitons << " of " << data.size() << " persistent notifications." << LL_ENDL; + break; + } + instance.add(LLNotificationPtr(new LLNotification(*notification_it))); + + } + break; } + mLoading = false; + savePersistentNotifications(); } //virtual void onDelete(LLNotificationPtr pNotification) { - // we want to keep deleted notifications in our log - AILOCK_mItems; - mItems.insert(pNotification); - - return; + { + AILOCK_mItems; + mItems.erase(pNotification); // Delete immediately. + } + savePersistentNotifications(); } private: + bool mLoading = false; std::string mFileName; }; @@ -277,6 +315,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodeP } LLNotificationForm::LLNotificationForm(const LLSD& sd) + : mIgnore(IGNORE_NO) { if (sd.isArray()) { @@ -284,7 +323,8 @@ LLNotificationForm::LLNotificationForm(const LLSD& sd) } else { - LL_WARNS() << "Invalid form data " << sd << LL_ENDL; + if (!sd.isUndefined()) + LL_WARNS() << "Invalid form data " << sd << LL_ENDL; mFormData = LLSD::emptyArray(); } } @@ -415,7 +455,7 @@ LLNotification::LLNotification(const LLNotification::Params& p) : mTimestamp(p.timestamp), mSubstitutions(p.substitutions), mPayload(p.payload), - mExpiresAt(0), + mExpiresAt(F64SecondsImplicit()), mResponseFunctorName(p.functor_name), mTemporaryResponder(p.mTemporaryResponder), mRespondedTo(false), @@ -891,7 +931,7 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt assert(!wasFound); if (passesFilter) { - LL_INFOS() << "Inserting " << pNotification->getName() << LL_ENDL; + //LL_INFOS() << "Inserting " << pNotification->getName() << LL_ENDL; // not in our list, add it and say so mItems.insert(pNotification); abortProcessing = mChanged(payload); @@ -903,9 +943,9 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt // if we have it in our list, pass on the delete, then delete it, else do nothing if (wasFound) { + onDelete(pNotification); abortProcessing = mChanged(payload); mItems.erase(pNotification); - onDelete(pNotification); } } return abortProcessing; @@ -1145,13 +1185,6 @@ void LLNotifications::createDefaultChannels() LLNotificationChannel::buildChannel("Visible", "Ignore", &LLNotificationFilters::includeEverything); - // create special history channel - //std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml" ); - // use ^^^ when done debugging notifications serialization - std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_USER_SETTINGS, "open_notifications.xml" ); - // this isn't a leak, don't worry about the empty "new" - new LLNotificationHistoryChannel(notifications_log_file); - // connect action methods to these channels LLNotifications::instance().getChannel("Expiration")-> connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1)); @@ -1163,6 +1196,14 @@ void LLNotifications::createDefaultChannels() connectFailedFilter(&handleIgnoredNotification); } +void LLNotifications::onLoginCompleted() +{ + // create special history channel + std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "singu_open_notifications_" + gHippoGridManager->getCurrentGrid()->getGridName() + ".xml"); + // this isn't a leak, don't worry about the empty "new" + new LLNotificationHistoryChannel(notifications_log_file ); +} + static std::string sStringSkipNextTime("Skip this dialog next time"); static std::string sStringAlwaysChoose("Always choose this option"); @@ -1297,14 +1338,20 @@ LLXMLNodePtr LLNotificationTemplates::checkForXMLTemplate(LLXMLNodePtr item) bool LLNotificationTemplates::loadTemplates() { - const std::string xml_filename = "notifications.xml"; + LL_INFOS() << "Reading notifications template" << LL_ENDL; + // Passing findSkinnedFilenames(constraint=LLDir::ALL_SKINS) makes it + // output all relevant pathnames instead of just the ones from the most + // specific skin. + std::vector search_paths = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS); + + std::string base_filename = search_paths.front(); LLXMLNodePtr root; - - BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); + BOOL success = LLXMLNode::getLayeredXMLNode(root, search_paths); if (!success || root.isNull() || !root->hasName( "notifications" )) { - LL_ERRS() << "Problem reading UI Notifications file: " << xml_filename << LL_ENDL; + LL_ERRS() << "Problem reading XML from UI Notifications file: " << base_filename << LL_ENDL; return false; } @@ -1337,7 +1384,7 @@ bool LLNotificationTemplates::loadTemplates() if (!item->hasName("notification")) { LL_WARNS() << "Unexpected entity " << item->getName()->mString << - " found in " << xml_filename << LL_ENDL; + " found in notifications.xml [language=]" << LLUI::getLanguage() << LL_ENDL; continue; } } @@ -1347,14 +1394,20 @@ bool LLNotificationTemplates::loadTemplates() bool LLNotifications::loadNotifications() { - const std::string xml_filename = "notifications.xml"; + LL_INFOS() << "Reading notifications template" << LL_ENDL; + // Passing findSkinnedFilenames(constraint=LLDir::ALL_SKINS) makes it + // output all relevant pathnames instead of just the ones from the most + // specific skin. + std::vector search_paths = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS); + + std::string base_filename = search_paths.front(); LLXMLNodePtr root; - - BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); + BOOL success = LLXMLNode::getLayeredXMLNode(root, search_paths); if (!success || root.isNull() || !root->hasName( "notifications" )) { - LL_ERRS() << "Problem reading UI Notifications file: " << xml_filename << LL_ENDL; + LL_ERRS() << "Problem reading XML from UI Notifications file: " << base_filename << LL_ENDL; return false; } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 81611090f1..ea308ebb42 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -92,8 +92,9 @@ #include #include #include +#include #include - +#include // we want to minimize external dependencies, but this one is important #include "llsd.h" #include "llinstancetracker.h" @@ -102,6 +103,7 @@ #include "llavatarname.h" #include "llevents.h" #include "llfunctorregistry.h" +#include "llinitparam.h" #include "llui.h" #include "llxmlnode.h" #include "llnotificationptr.h" @@ -131,6 +133,70 @@ class LLNotificationForm LOG_CLASS(LLNotificationForm); public: + struct FormElementBase : public LLInitParam::Block + { + Optional name; + Optional enabled; + + FormElementBase(); + }; + + struct FormIgnore : public LLInitParam::Block + { + Optional text; + Optional save_option; + Optional control; + Optional invert_control; + + FormIgnore(); + }; + + struct FormButton : public LLInitParam::Block + { + Mandatory index; + Mandatory text; + Optional ignore; + Optional is_default; + + Mandatory type; + + FormButton(); + }; + + struct FormInput : public LLInitParam::Block + { + Mandatory type; + Optional width; + Optional max_length_chars; + Optional text; + + Optional value; + FormInput(); + }; + + struct FormElement : public LLInitParam::ChoiceBlock + { + Alternative button; + Alternative input; + + FormElement(); + }; + + struct FormElements : public LLInitParam::Block + { + Multiple elements; + FormElements(); + }; + + struct Params : public LLInitParam::Block + { + Optional name; + Optional ignore; + Optional form_elements; + + Params(); + }; + typedef enum e_ignore_type { IGNORE_NO, @@ -730,6 +796,7 @@ class LLNotifications : // OK to call more than once because it will reload bool loadNotifications(); void createDefaultChannels(); + void onLoginCompleted(); // we provide a collection of simple add notification functions so that it's reasonable to create notifications in one line LLNotificationPtr add(const std::string& name, diff --git a/indra/llui/llnotificationsutil.h b/indra/llui/llnotificationsutil.h index 0715d12998..018db39c56 100644 --- a/indra/llui/llnotificationsutil.h +++ b/indra/llui/llnotificationsutil.h @@ -30,6 +30,7 @@ // to avoid including the heavyweight llnotifications.h #include "llnotificationptr.h" +#include "lluuid.h" #include "aialert.h" #ifndef BOOST_FUNCTION_HPP_INCLUDED diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 005e23268b..e311daa1c5 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -196,14 +196,16 @@ void LLPanel::draw() // draw background if( mBgVisible ) { - LLRect local_rect = getLocalRect(); + F32 alpha = getCurrentTransparency(); + + LLRect&& local_rect = getLocalRect(); if (mBgOpaque ) { - gl_rect_2d( local_rect, mBgColorOpaque ); + gl_rect_2d( local_rect, mBgColorOpaque % alpha); } else { - gl_rect_2d( local_rect, mBgColorAlpha ); + gl_rect_2d( local_rect, mBgColorAlpha % alpha); } } @@ -384,7 +386,7 @@ void LLPanel::setBorderVisible(BOOL b) } } -LLFastTimer::DeclareTimer FTM_PANEL_CONSTRUCTION("Panel Construction"); +LLTrace::BlockTimerStatHandle FTM_PANEL_CONSTRUCTION("Panel Construction"); // virtual LLXMLNodePtr LLPanel::getXML(bool save_children) const { @@ -439,8 +441,31 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *fac std::string name("panel"); node->getAttributeString("name", name); - LLPanel* panelp = factory->createFactoryPanel(name); - LLFastTimer _(FTM_PANEL_CONSTRUCTION); + std::string class_attr; + node->getAttributeString("class", class_attr); + + LLPanel* panelp = NULL; + + { + if(!class_attr.empty()) + { + panelp = LLRegisterPanelClass::instance().createPanelClass(class_attr); + } + + if (!panelp) + { + panelp = factory->createFactoryPanel(name); + /* Singu TODO: Future? + llassert(panelp); + + if (!panelp) + { + return NULL; // :( + }*/ + } + } + LL_RECORD_BLOCK_TIME(FTM_PANEL_CONSTRUCTION); + // Fall back on a default panel, if there was no special factory. if (!panelp) { diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index d2ca151e5a..f379cd2a62 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -39,8 +39,8 @@ #include "lluictrl.h" #include "llbutton.h" #include "lllineeditor.h" -#include "lluiimage.h" #include "llviewborder.h" +#include "lluiimage.h" #include "lluistring.h" #include "v4color.h" #include @@ -142,6 +142,7 @@ class LLPanel : public LLUICtrl CommitCallbackRegistry::ScopedRegistrar& getCommitCallbackRegistrar() { return mCommitCallbackRegistrar; } EnableCallbackRegistry::ScopedRegistrar& getEnableCallbackRegistrar() { return mEnableCallbackRegistrar; } + virtual BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); void initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory); void setPanelParameters(LLXMLNodePtr node, LLView *parentp); @@ -151,6 +152,7 @@ class LLPanel : public LLUICtrl std::string getString(const std::string& name) const; // ** Wrappers for setting child properties by name ** -TomY + // WARNING: These are deprecated, please use getChild("name")->doStuff() idiom instead // LLView void childSetVisible(const std::string& name, bool visible); @@ -196,7 +198,7 @@ class LLPanel : public LLUICtrl BOOL childSetTextArg(const std::string& id, const std::string& key, const LLStringExplicit& text); BOOL childSetLabelArg(const std::string& id, const std::string& key, const LLStringExplicit& text); BOOL childSetToolTipArg(const std::string& id, const std::string& key, const LLStringExplicit& text); - + // LLSlider / LLMultiSlider / LLSpinCtrl void childSetMinValue(const std::string& id, LLSD min_value); void childSetMaxValue(const std::string& id, LLSD max_value); @@ -228,6 +230,7 @@ class LLPanel : public LLUICtrl static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); boost::signals2::connection setVisibleCallback( const commit_signal_t::slot_type& cb ); + protected: // Override to set not found list LLButton* getDefaultButton() { return mDefaultBtn; } @@ -262,4 +265,56 @@ class LLPanel : public LLUICtrl }; // end class LLPanel +typedef boost::function LLPanelClassCreatorFunc; + +// local static instance for registering a particular panel class + +class LLRegisterPanelClass +: public LLSingleton< LLRegisterPanelClass > +{ +public: + // reigister with either the provided builder, or the generic templated builder + void addPanelClass(const std::string& tag,LLPanelClassCreatorFunc func) + { + mPanelClassesNames[tag] = func; + } + + LLPanel* createPanelClass(const std::string& tag) + { + param_name_map_t::iterator iT = mPanelClassesNames.find(tag); + if(iT == mPanelClassesNames.end()) + return 0; + return iT->second(); + } + template + static T* defaultPanelClassBuilder() + { + T* pT = new T(); + return pT; + } + +private: + typedef std::map< std::string, LLPanelClassCreatorFunc> param_name_map_t; + + param_name_map_t mPanelClassesNames; +}; + + +// local static instance for registering a particular panel class +template + class LLPanelInjector +{ +public: + // register with either the provided builder, or the generic templated builder + LLPanelInjector(const std::string& tag); +}; + + +template + LLPanelInjector::LLPanelInjector(const std::string& tag) +{ + LLRegisterPanelClass::instance().addPanelClass(tag,&LLRegisterPanelClass::defaultPanelClassBuilder); +} + + #endif diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp index c1c842d548..9ba58039ed 100644 --- a/indra/llui/llprogressbar.cpp +++ b/indra/llui/llprogressbar.cpp @@ -48,16 +48,16 @@ static LLRegisterWidget r("progress_bar"); LLProgressBar::LLProgressBar(const std::string& name, const LLRect &rect) - : LLView(name, rect, FALSE), - mImageBar( NULL ), - mImageShadow( NULL ) + : LLView(name, rect, FALSE) + //mImageBar( NULL ), + // mImageShadow( NULL ) { mPercentDone = 0.f; // Defaults: - setImageBar("rounded_square.tga"); - setImageShadow("rounded_square_soft.tga"); + setImageBar("Rounded_Square"); + setImageShadow("Rounded_Square_Soft"); mColorBackground = LLColor4(0.3254f, 0.4000f, 0.5058f, 1.0f); mColorBar = LLColor4(0.5764f, 0.6627f, 0.8352f, 1.0f); @@ -75,10 +75,8 @@ void LLProgressBar::draw() static LLTimer timer; F32 alpha = getDrawContext().mAlpha; - //LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga"); - LLUIImagePtr bar_fg_imagep = LLUI::getUIImage("progressbar_fill.tga"); - LLUIImagePtr bar_bg_imagep = LLUI::getUIImage("progressbar_track.tga"); - //LLUIImagePtr bar_imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr bar_fg_imagep = LLUI::getUIImage("ProgressBar"); + LLUIImagePtr bar_bg_imagep = LLUI::getUIImage("ProgressTrack"); LLColor4 background_color = LLUI::sColorsGroup->getColor("LoginProgressBarBgColor"); bar_bg_imagep->draw(getLocalRect(), background_color % alpha); @@ -95,12 +93,12 @@ void LLProgressBar::setPercent(const F32 percent) void LLProgressBar::setImageBar( const std::string &bar_name ) { - mImageBar = LLUI::getUIImage(bar_name)->getImage(); + //mImageBar = LLUI::getUIImage(bar_name)->getImage(); } void LLProgressBar::setImageShadow(const std::string &shadow_name) { - mImageShadow = LLUI::getUIImage(shadow_name)->getImage(); + //mImageShadow = LLUI::getUIImage(shadow_name)->getImage(); } void LLProgressBar::setColorBar(const LLColor4 &c) @@ -140,14 +138,14 @@ LLView* LLProgressBar::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor LLProgressBar *progress = new LLProgressBar(name, LLRect()); - std::string image_bar; + /*std::string image_bar; if (node->hasAttribute("image_bar")) node->getAttributeString("image_bar",image_bar); if (image_bar != LLStringUtil::null) progress->setImageBar(image_bar); std::string image_shadow; if (node->hasAttribute("image_shadow")) node->getAttributeString("image_shadow",image_shadow); - if (image_shadow != LLStringUtil::null) progress->setImageShadow(image_shadow); + if (image_shadow != LLStringUtil::null) progress->setImageShadow(image_shadow);*/ LLColor4 color_bar; diff --git a/indra/llui/llprogressbar.h b/indra/llui/llprogressbar.h index 8f548da660..d7af5360c6 100644 --- a/indra/llui/llprogressbar.h +++ b/indra/llui/llprogressbar.h @@ -62,13 +62,13 @@ class LLProgressBar protected: F32 mPercentDone; - LLPointer mImageBar; + // mImageBar; //LLUUID mImageBarID; //LLString mImageBarName; LLColor4 mColorBar; LLColor4 mColorBar2; - LLPointer mImageShadow; + //LLPointer mImageShadow; //LLUUID mImageShadowID; //LLString mImageShadowName; LLColor4 mColorShadow; diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp index 0d2aa393e8..fc810d567f 100644 --- a/indra/llui/llresmgr.cpp +++ b/indra/llui/llresmgr.cpp @@ -414,7 +414,7 @@ void LLResMgr::getIntegerString( std::string& output, S32 input ) const { if (fraction == remaining_count) { - fraction_string = llformat("%d", fraction); + fraction_string = fmt::to_string(fraction); } else { diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index 1b8fe5ce21..96912a0f5a 100644 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -2,31 +2,25 @@ * @file llscrollbar.cpp * @brief Scrollbar UI widget * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * 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. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -46,6 +40,7 @@ #include "llwindow.h" #include "llcontrol.h" #include "llrender.h" +#include "lluictrlfactory.h" LLScrollbar::LLScrollbar( const std::string& name, LLRect rect, @@ -402,7 +397,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) } getWindow()->setCursor(UI_CURSOR_ARROW); - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL; + LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL; handled = TRUE; } else @@ -414,7 +409,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) if( !handled ) { getWindow()->setCursor(UI_CURSOR_ARROW); - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL; + LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL; handled = TRUE; } @@ -468,6 +463,13 @@ BOOL LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask) return handled; } +BOOL LLScrollbar::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + // just treat a double click as a second click + return handleMouseDown(x, y, mask); +} + + void LLScrollbar::reshape(S32 width, S32 height, BOOL called_from_parent) { if (width == getRect().getWidth() && height == getRect().getHeight()) return; @@ -502,16 +504,15 @@ void LLScrollbar::draw() BOOL hovered = getEnabled() && !other_captor && (hasMouseCapture() || mThumbRect.pointInRect(local_mouse_x, local_mouse_y)); if (hovered) { - mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f)); + mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLSmoothInterpolation::getInterpolant(0.05f)); } else { - mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLCriticalDamp::getInterpolant(0.05f)); + mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLSmoothInterpolation::getInterpolant(0.05f)); } - // Draw background and thumb. - LLUIImage* rounded_rect_imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImage* rounded_rect_imagep = LLUI::getUIImage("Rounded_Square"); if (!rounded_rect_imagep) { @@ -525,6 +526,9 @@ void LLScrollbar::draw() } else { + // Thumb + LLRect outline_rect = mThumbRect; + outline_rect.stretch(2); // Background rounded_rect_imagep->drawSolid(mOrientation == HORIZONTAL ? SCROLLBAR_SIZE : 0, mOrientation == VERTICAL ? SCROLLBAR_SIZE : 0, @@ -532,9 +536,6 @@ void LLScrollbar::draw() mOrientation == VERTICAL ? getRect().getHeight() - 2 * SCROLLBAR_SIZE : getRect().getHeight(), mTrackColor); - // Thumb - LLRect outline_rect = mThumbRect; - outline_rect.stretch(2); if (gFocusMgr.getKeyboardFocus() == this) { @@ -636,3 +637,8 @@ void LLScrollbar::onLineDownBtnPressed( const LLSD& data ) { changeLine( mStepSize, TRUE ); } + +void LLScrollbar::setThickness(S32 thickness) +{ + mThickness = thickness < 0 ? SCROLLBAR_SIZE : thickness; +} diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h index fab34326cb..2482cce2f0 100644 --- a/indra/llui/llscrollbar.h +++ b/indra/llui/llscrollbar.h @@ -2,31 +2,25 @@ * @file llscrollbar.h * @brief Scrollbar UI widget * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -36,6 +30,7 @@ #include "stdtypes.h" #include "lluictrl.h" #include "v4color.h" +#include "llbutton.h" // // Constants @@ -59,6 +54,7 @@ class LLScrollbar callback_t change_callback, S32 step_size = 1); +public: virtual ~LLScrollbar(); virtual void setValue(const LLSD& value); @@ -67,6 +63,7 @@ class LLScrollbar virtual BOOL handleKeyHere(KEY key, MASK mask); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, @@ -104,6 +101,9 @@ class LLScrollbar void onLineUpBtnPressed(const LLSD& data); void onLineDownBtnPressed(const LLSD& data); + S32 getThickness() const { return mThickness; } + void setThickness(S32 thickness); + void setTrackColor( const LLColor4& color ) { mTrackColor = color; } void setThumbColor( const LLColor4& color ) { mThumbColor = color; } void setHighlightColor( const LLColor4& color ) { mHighlightColor = color; } @@ -145,5 +145,4 @@ class LLScrollbar }; - #endif // LL_SCROLLBAR_H diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 9f2cfb3061..778329d1da 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -218,6 +218,15 @@ BOOL LLScrollContainer::handleKeyHere(KEY key, MASK mask) return FALSE; } +BOOL LLScrollContainer::handleUnicodeCharHere(llwchar uni_char) +{ + if (mScrolledView && mScrolledView->handleUnicodeCharHere(uni_char)) + { + return TRUE; + } + return FALSE; +} + BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks ) { // Give event to my child views - they may have scroll bars @@ -262,7 +271,6 @@ BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - //S32 scrollbar_size = SCROLLBAR_SIZE; // Scroll folder view if needed. Never accepts a drag or drop. *accept = ACCEPT_NO; BOOL handled = autoScroll(x, y); @@ -413,6 +421,7 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height } } + void LLScrollContainer::draw() { S32 scrollbar_size = SCROLLBAR_SIZE; @@ -525,7 +534,7 @@ bool LLScrollContainer::addChild(LLView* view, S32 tab_group) void LLScrollContainer::updateScroll() { - if (!mScrolledView) + if (!getVisible() || !mScrolledView) { return; } @@ -626,6 +635,7 @@ LLRect LLScrollContainer::getVisibleContentRect() visible_rect.translate(-contents_rect.mLeft, -contents_rect.mBottom); return visible_rect; } + LLRect LLScrollContainer::getContentWindowRect() { updateScroll(); @@ -729,6 +739,13 @@ S32 LLScrollContainer::getBorderWidth() const return 0; } +void LLScrollContainer::setSize(S32 size) +{ + mSize = size; + mScrollbar[VERTICAL]->setThickness(size); + mScrollbar[HORIZONTAL]->setThickness(size); +} + // virtual LLXMLNodePtr LLScrollContainer::getXML(bool save_children) const { @@ -801,7 +818,7 @@ LLView* LLScrollContainer::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFa panelp = new LLPanel(std::string("dummy"), LLRect::null, FALSE); } - ret->mScrolledView = panelp; + ret->addChild(panelp); return ret; } diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index 8239789b36..c40b95cbe3 100644 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -2,31 +2,25 @@ * @file llscrollcontainer.h * @brief LLScrollContainer class header file. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -78,7 +72,7 @@ class LLScrollContainer : public LLUICtrl void setReserveScrollCorner( BOOL b ) { mReserveScrollCorner = b; } LLRect getVisibleContentRect(); LLRect getContentWindowRect(); - const LLRect& getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; } + virtual const LLRect& getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; } void pageUp(S32 overlap = 0); void pageDown(S32 overlap = 0); void goToTop(); @@ -90,6 +84,7 @@ class LLScrollContainer : public LLUICtrl // LLView functionality virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); virtual BOOL handleKeyHere(KEY key, MASK mask); + virtual BOOL handleUnicodeCharHere(llwchar uni_char); virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, @@ -105,9 +100,14 @@ class LLScrollContainer : public LLUICtrl virtual LLXMLNodePtr getXML(bool save_children) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); + S32 getSize() const { return mSize; } + void setSize(S32 thickness); + +protected: + LLView* mScrolledView; + private: void init(); - // internal scrollbar handlers virtual void scrollHorizontal( S32 new_pos ); virtual void scrollVertical( S32 new_pos ); @@ -117,7 +117,6 @@ class LLScrollContainer : public LLUICtrl private: LLScrollbar* mScrollbar[SCROLLBAR_COUNT]; - LLView* mScrolledView; S32 mSize; BOOL mIsOpaque; LLColor4 mBackgroundColor; diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 82484b0bbe..24a81cf941 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -203,7 +203,7 @@ LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p) // initialize rounded rect image if (!mRoundedRectImage) { - mRoundedRectImage = LLUI::getUIImage("rounded_square.tga"); + mRoundedRectImage = LLUI::getUIImage("Rounded_Square"); } } diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index 84c196a054..3cbdc6d3ee 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -78,7 +78,7 @@ class LLScrollListCell visible("visible", true), value("value"), tool_tip("tool_tip", ""), - format("format", ""), + format("format", "%D %T"), font("font"/*, LLFontGL::getFontSansSerifSmall()*/), font_color("font_color", LLColor4::black), font_style("font-style"), diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index 59c991512c..72d4b3d01a 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -249,8 +249,8 @@ void LLScrollColumnHeader::handleReshape(const LLRect& new_rect, bool by_user) // tell scroll list to layout columns again // do immediate update to get proper feedback to resize handle // which needs to know how far the resize actually went - mColumn->mParentCtrl->dirtyColumns(); //Must flag as dirty, else updateColumns will probably be a noop. - mColumn->mParentCtrl->updateColumns(); + const bool force_update = true; + mColumn->mParentCtrl->updateColumns(force_update); } } diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 915833bd00..4b8844d33e 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -54,15 +54,15 @@ #include "llsdparam.h" #include "llmenugl.h" +#include -static LLRegisterWidget r("scroll_list"); -LLMenuGL* sScrollListMenus[1] = {}; // List menus that recur, such as general avatars or groups menus +static LLRegisterWidget r("scroll_list"); // local structures & classes. struct SortScrollListItem { - SortScrollListItem(const std::vector >& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal) + SortScrollListItem(const std::vector& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal) : mSortOrders(sort_orders) , mSortSignal(sort_signal) {} @@ -102,7 +102,7 @@ struct SortScrollListItem } - typedef std::vector > sort_order_t; + typedef std::vector sort_order_t; const LLScrollListCtrl::sort_signal_t* mSortSignal; const sort_order_t& mSortOrders; }; @@ -125,6 +125,7 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, mNeedsScroll(false), mCanSelect(true), mColumnsDirty(false), + mSortEnabled(true), mMaxItemCount(INT_MAX), mMaxContentWidth(0), mBorderThickness( 2 ), @@ -156,6 +157,7 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, mFgUnselectedColor(LLUI::sColorsGroup->getColor("ScrollUnselectedColor")), mFgDisabledColor(LLUI::sColorsGroup->getColor("ScrollDisabledColor")), mHighlightedColor(LLUI::sColorsGroup->getColor("ScrollHighlightedColor")), + mFilter(), mSearchColumn(0), mColumnPadding(5) { @@ -194,7 +196,8 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, addChild(mBorder); } - LLTextBox* textBox = new LLTextBox("comment_text",mItemListRect,std::string()); + LLTextBox* textBox = new LLTextBox("comment_text",mItemListRect, LLStringUtil::null); + mCommentTextView = textBox; textBox->setBorderVisible(false); textBox->setFollows(FOLLOWS_ALL); textBox->setFontShadow(LLFontGL::NO_SHADOW); @@ -309,14 +312,14 @@ std::vector LLScrollListCtrl::getAllSelected() const return ret; } -uuid_vec_t LLScrollListCtrl::getSelectedIDs() +uuid_vec_t LLScrollListCtrl::getSelectedIDs() const { - LLUUID selected_id; uuid_vec_t ids; - std::vector selected = this->getAllSelected(); - for(std::vector::iterator itr = selected.begin(); itr != selected.end(); ++itr) + if (!getCanSelect()) return ids; + + for(const auto& item : mItemList) { - ids.push_back((*itr)->getUUID()); + if (item->getSelected()) ids.push_back(item->getUUID()); } return ids; } @@ -399,6 +402,17 @@ std::vector LLScrollListCtrl::getAllData() const return ret; } +uuid_vec_t LLScrollListCtrl::getAllIDs() const +{ + uuid_vec_t ret; + ret.reserve(mItemList.size()); //Optimization + for(const auto& item : mItemList) + { + ret.push_back(item->getUUID()); + } + return ret; +} + // returns first matching item LLScrollListItem* LLScrollListCtrl::getItem(const LLSD& sd) const { @@ -442,23 +456,27 @@ void LLScrollListCtrl::updateLayout() mCommentTextView->setShape(mItemListRect); + adjustScrollbar(mFilter.empty() ? getItemCount() : mScrollbar->getDocSize()); // Doc size is the item count without a filter, otherwise it's calculated whenever filter is updated + dirtyColumns(); +} + +void LLScrollListCtrl::adjustScrollbar(S32 doc_size) +{ // how many lines of content in a single "page" - S32 page_lines = getLinesPerPage(); + S32 page_lines = getLinesPerPage(); - BOOL scrollbar_visible = mLineHeight * getItemCount() > mItemListRect.getHeight(); + bool scrollbar_visible = mLineHeight * doc_size > mItemListRect.getHeight(); if (scrollbar_visible) { // provide space on the right for scrollbar mItemListRect.mRight = getRect().getWidth() - mBorderThickness - SCROLLBAR_SIZE; + mScrollbar->setOrigin(mItemListRect.mRight, mItemListRect.mBottom); + mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0)); } - mScrollbar->setOrigin(getRect().getWidth() - mBorderThickness - SCROLLBAR_SIZE, mItemListRect.mBottom); - mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0)); mScrollbar->setPageSize(page_lines); - mScrollbar->setDocSize( getItemCount() ); + mScrollbar->setDocSize(doc_size); mScrollbar->setVisible(scrollbar_visible); - - dirtyColumns(); } // Attempt to size the control to show all items. @@ -492,6 +510,9 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r BOOL not_too_big = getItemCount() < mMaxItemCount; if (not_too_big) { + if (!mFilter.empty() && !filterItem(item)) // If we're filtering, filter this item if needed, if not, bump the document size. + mScrollbar->setDocSize(mScrollbar->getDocSize()+1); + switch( pos ) { case ADD_TOP: @@ -501,12 +522,14 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r case ADD_SORTED: { - // sort by column 0, in ascending order - std::vector single_sort_column; - single_sort_column.push_back(std::make_pair(0, TRUE)); - mItemList.push_back(item); - std::stable_sort(mItemList.begin(), mItemList.end(), SortScrollListItem(single_sort_column,mSortCallback)); + // std::stable_sort is expensive. Only do this if the user sort criteria is not column 0, otherwise + // setNeedsSort does what we want. + if (mSortColumns.empty() || mSortColumns[0].first != 0) + { + // sort by column 0, in ascending order + std::stable_sort(mItemList.begin(), mItemList.end(), SortScrollListItem({ {0,true} }, mSortCallback)); + } // ADD_SORTED just sorts by first column... // this might not match user sort criteria, so flag list as being in unsorted state @@ -570,13 +593,13 @@ S32 LLScrollListCtrl::calcMaxContentWidth() if (mColumnWidthsDirty) { - mColumnWidthsDirty = false; // update max content width for this column, by looking at all items column->mMaxContentWidth = column->mHeader ? LLFontGL::getFontSansSerifSmall()->getWidth(column->mLabel.getWString()) + mColumnPadding + HEADING_TEXT_PADDING : 0; - item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (auto& item : mItemList) { - LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); + if (item->getFiltered()) continue; + + LLScrollListCell* cellp = item->getColumn(column->mIndex); if (!cellp) continue; column->mMaxContentWidth = llmax(LLFontGL::getFontSansSerifSmall()->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); @@ -584,6 +607,7 @@ S32 LLScrollListCtrl::calcMaxContentWidth() } max_item_width += column->mMaxContentWidth; } + mColumnWidthsDirty = false; mMaxContentWidth = max_item_width; return max_item_width; @@ -599,7 +623,7 @@ bool LLScrollListCtrl::updateColumnWidths() if (!column) continue; // update column width - S32 new_width = column->getWidth(); + S32 new_width = 0; if (column->mRelWidth >= 0) { new_width = (S32)ll_round(column->mRelWidth*mItemListRect.getWidth()); @@ -608,6 +632,10 @@ bool LLScrollListCtrl::updateColumnWidths() { new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns; } + else + { + new_width = column->getWidth(); + } if (column->getWidth() != new_width) { @@ -625,10 +653,8 @@ const S32 SCROLL_LIST_ROW_PAD = 2; void LLScrollListCtrl::updateLineHeight() { mLineHeight = 0; - item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (auto& itemp : mItemList) { - LLScrollListItem *itemp = *iter; S32 num_cols = itemp->getNumColumns(); S32 i = 0; for (const LLScrollListCell* cell = itemp->getColumn(i); i < num_cols; cell = itemp->getColumn(++i)) @@ -650,9 +676,9 @@ void LLScrollListCtrl::updateLineHeightInsert(LLScrollListItem* itemp) } -void LLScrollListCtrl::updateColumns() +void LLScrollListCtrl::updateColumns(bool force_update) { - if (!mColumnsDirty) + if (!mColumnsDirty && !force_update) return; mColumnsDirty = false; @@ -706,7 +732,7 @@ void LLScrollListCtrl::updateColumns() } // propagate column widths to individual cells - if (columns_changed_width) + if (columns_changed_width || force_update) { item_list::iterator iter; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) @@ -749,6 +775,7 @@ BOOL LLScrollListCtrl::selectFirstItem() for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem *itemp = *iter; + if (itemp->getFiltered()) continue; if( first_item && itemp->getEnabled() ) { if (!itemp->getSelected()) @@ -807,13 +834,13 @@ BOOL LLScrollListCtrl::selectItemRange( S32 first_index, S32 last_index ) iter = mItemList.erase(iter); continue ; } - - if( index >= first_index && index <= last_index ) + + if (index >= first_index && index <= last_index) { - if( itemp->getEnabled() ) + if (itemp->getEnabled()) { selectItem(itemp, FALSE); - success = TRUE; + success = TRUE; } } else @@ -956,6 +983,8 @@ S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids ) for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; + if (item->getFiltered()) continue; + uuid_vec_t::iterator iditr; for(iditr = ids.begin(); iditr != ids.end(); ++iditr) { @@ -981,15 +1010,14 @@ S32 LLScrollListCtrl::getItemIndex( LLScrollListItem* target_item ) const updateSort(); S32 index = 0; - item_list::const_iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (LLScrollListItem* itemp : mItemList) { - LLScrollListItem *itemp = *iter; + if (itemp->getFiltered()) continue; if (target_item == itemp) { return index; } - index++; + ++index; } return -1; } @@ -999,15 +1027,14 @@ S32 LLScrollListCtrl::getItemIndex( const LLUUID& target_id ) const updateSort(); S32 index = 0; - item_list::const_iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (LLScrollListItem* itemp : mItemList) { - LLScrollListItem *itemp = *iter; + if (itemp->getFiltered()) continue; if (target_id == itemp->getUUID()) { return index; } - index++; + ++index; } return -1; } @@ -1029,6 +1056,7 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection) for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* cur_item = *iter; + if (cur_item->getFiltered()) continue; if (cur_item->getSelected()) { @@ -1073,6 +1101,7 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection) for (iter = mItemList.rbegin(); iter != mItemList.rend(); iter++) { LLScrollListItem* cur_item = *iter; + if (cur_item->getFiltered()) continue; if (cur_item->getSelected()) { @@ -1122,7 +1151,7 @@ void LLScrollListCtrl::deselectAllItems(BOOL no_commit_on_change) void LLScrollListCtrl::setCommentText(const std::string& comment_text) { - getChild("comment_text")->setWrappedText(comment_text); + static_cast(mCommentTextView)->setWrappedText(comment_text); } LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos) @@ -1177,6 +1206,7 @@ LLScrollListItem* LLScrollListCtrl::getItemByLabel(const std::string& label, BOO for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; + std::string item_text = item->getColumn(column)->getValue().asString(); // Only select enabled items with matching names if (!case_sensitive) { @@ -1212,6 +1242,8 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; + if (item->getFiltered()) continue; + // Only select enabled items with matching names LLScrollListCell* cellp = item->getColumn(getSearchColumn()); BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE; @@ -1235,6 +1267,9 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen { LLScrollListItem* item = *iter; + // Don't select filtered items + if (item->getFiltered()) continue; + // Only select enabled items with matching names LLScrollListCell* cellp = item->getColumn(getSearchColumn()); if (!cellp) @@ -1319,6 +1354,8 @@ BOOL LLScrollListCtrl::setSelectedByValue(const LLSD& value, BOOL selected) for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; + if (item->getFiltered()) continue; + if (item->getEnabled() && (item->getValue().asString() == value.asString())) { if (selected) @@ -1348,7 +1385,7 @@ BOOL LLScrollListCtrl::isSelected(const LLSD& value) const for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; - if (item->getValue().asString() == value.asString()) + if (!item->getFiltered() && item->getValue().asString() == value.asString()) { return item->getSelected(); } @@ -1387,9 +1424,6 @@ void LLScrollListCtrl::drawItems() S32 x = mItemListRect.mLeft; S32 y = mItemListRect.mTop - mLineHeight; - // allow for partial line at bottom - S32 num_page_lines = getLinesPerPage(); - LLRect item_rect; LLGLSUIDefault gls_ui; @@ -1397,70 +1431,102 @@ void LLScrollListCtrl::drawItems() { LLLocalClipRect clip(mItemListRect); - S32 cur_y = y; - - S32 max_columns = 0; - - LLColor4 highlight_color = LLColor4::white; - F32 type_ahead_timeout = LLUI::sConfigGroup->getF32("TypeAheadTimeout"); - highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout, 0.4f, 0.f); + LLRect clip_rect = LLUI::getRootView()->getRect(); + if (LLGLState::isEnabled()) + { + LLRect scissor = gGL.getScissor(); + scissor.mLeft /= LLUI::getScaleFactor().mV[VX]; + scissor.mTop /= LLUI::getScaleFactor().mV[VY]; + scissor.mRight /= LLUI::getScaleFactor().mV[VX]; + scissor.mBottom /= LLUI::getScaleFactor().mV[VY]; + clip_rect.intersectWith(scissor); + } S32 first_line = mScrollLines; - S32 last_line = llmin((S32)mItemList.size() - 1, mScrollLines + getLinesPerPage()); - if ((item_list::size_type)first_line >= mItemList.size()) { return; } - item_list::iterator iter; - for (S32 line = first_line; line <= last_line; line++) - { - LLScrollListItem* item = mItemList[line]; - - item_rect.setOriginAndSize( - x, - cur_y, - mItemListRect.getWidth(), - mLineHeight ); - item->setRect(item_rect); + S32 list_size = mItemList.size() - 1; - //LL_INFOS() << item_rect.getWidth() << LL_ENDL; + // allow for partial line at bottom + S32 num_page_lines = mFilter.empty() ? getLinesPerPage() : mScrollbar->getDocSize() + 1; + S32 last_line = llmin(list_size, mScrollLines + num_page_lines); - max_columns = llmax(max_columns, item->getNumColumns()); + S32 max_columns = 0; - LLColor4 fg_color; - LLColor4 bg_color(LLColor4::transparent); + LLColor4 highlight_color = LLColor4::white; + static const LLUICachedControl type_ahead_timeout("TypeAheadTimeout"); + highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout, 0.4f, 0.f); - if( mScrollLines <= line && line < mScrollLines + num_page_lines ) + bool done = false; + for (S32 pass = 0; !done; ++pass) + { + bool should_continue = false; // False until all passes are done for all row cells. + S32 cur_y = y; + for (S32 index = first_line, line = first_line; index <= list_size; ++index) { - fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor); - if( item->getSelected() && mCanSelect) - { - bg_color = mBgSelectedColor; - fg_color = (item->getEnabled() ? mFgSelectedColor : mFgDisabledColor); - } - else if (mHighlightedItem == line && mCanSelect) - { - bg_color = mHighlightedColor; - } - else + LLScrollListItem* item = mItemList[index]; + if (item->getFiltered()) continue; // Skip filtered + + item_rect.setOriginAndSize( + x, + cur_y, + mItemListRect.getWidth(), + mLineHeight); + item->setRect(item_rect); + + //LL_INFOS() << item_rect.getWidth() << LL_ENDL; + + max_columns = llmax(max_columns, item->getNumColumns()); + + LLColor4 fg_color; + LLColor4 bg_color(LLColor4::transparent); + { - if (mDrawStripes && (line % 2 == 0) && (max_columns > 1)) + cur_y -= mLineHeight; + + // Do not draw if not on screen. + LLRect screen_rect = item_rect; + screen_rect.translate(LLFontGL::sCurOrigin.mX, LLFontGL::sCurOrigin.mY); + if (!clip_rect.overlaps(screen_rect)) { - bg_color = mBgStripeColor; + continue; } - } - if (!item->getEnabled()) - { - bg_color = mBgReadOnlyColor; - } + fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor); + if (item->getSelected() && mCanSelect) + { + bg_color = mBgSelectedColor; + fg_color = (item->getEnabled() ? mFgSelectedColor : mFgDisabledColor); + } + else if (mHighlightedItem == line && mCanSelect) + { + bg_color = mHighlightedColor; + } + else + { + if (mDrawStripes && (line % 2 == 0) && (max_columns > 1)) + { + bg_color = mBgStripeColor; + } + } - item->draw(item_rect, fg_color, bg_color, highlight_color, mColumnPadding); + if (!item->getEnabled()) + { + bg_color = mBgReadOnlyColor; + } - cur_y -= mLineHeight; + should_continue |= item->draw(pass, item_rect, fg_color, bg_color, highlight_color, mColumnPadding); + if (++line > last_line) + { + break; // Don't draw any more than needed. + } + } } + done = !should_continue; } + } } @@ -1488,7 +1554,7 @@ void LLScrollListCtrl::draw() updateColumns(); - getChildView("comment_text")->setVisible(mItemList.empty()); + mCommentTextView->setVisible(mItemList.empty()); drawItems(); @@ -1606,9 +1672,10 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) // meaning that we never stop selecting until hitting max or // the end of the list. LLScrollListItem* lastSelected = mLastSelected; + auto selected_count = getAllSelected().size(); for (itor = mItemList.begin(); itor != mItemList.end(); ++itor) { - if(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable) + if(mMaxSelectable > 0 && selected_count >= mMaxSelectable) { if(mOnMaximumSelectCallback) { @@ -1617,6 +1684,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) break; } LLScrollListItem *item = *itor; + if (item->getFiltered()) continue; if (item == hit_item || item == lastSelected) { selectItem(item, FALSE); @@ -1631,6 +1699,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) { selectItem(item, FALSE); } + ++selected_count; } } } @@ -1742,10 +1811,7 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) if (col->mHeader && col->mHeader->getRect().pointInRect(x,y)) // Right clicking a column header shouldn't bring up a menu return FALSE; } - gFocusMgr.setKeyboardFocus(this); // Menu listeners rely on this - mPopupMenu->buildDrawLabels(); - mPopupMenu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, mPopupMenu, x, y); + showMenu(this, mPopupMenu, x, y); return TRUE; } @@ -1758,17 +1824,19 @@ BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask) { // Offer the click to the children, even if we aren't enabled // so the scroll bars will work. - if (NULL == LLView::childrenHandleDoubleClick(x, y, mask)) + handled = LLView::childrenHandleDoubleClick(x, y, mask) != nullptr; + if (!handled) { // Run the callback only if an item is being double-clicked. - if( mCanSelect && hitItem(x, y) && mOnDoubleClickCallback ) + if (mCanSelect && mOnDoubleClickCallback && hitItem(x, y)) { mOnDoubleClickCallback(); + handled = true; } } } - return TRUE; + return handled; } BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask) @@ -1841,15 +1909,16 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y ) // allow for partial line at bottom S32 num_page_lines = getLinesPerPage(); + S32 list_size = mItemList.size() - 1; + S32 last_line = llmin(list_size, mScrollLines + num_page_lines); - S32 line = 0; - item_list::iterator iter; - for(iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (S32 index = mScrollLines, line = mScrollLines; index <= list_size; ++index) { - LLScrollListItem* item = *iter; - if( mScrollLines <= line && line < mScrollLines + num_page_lines ) + LLScrollListItem* item = mItemList[index]; + if (item->getFiltered()) continue; + { - if( item->getEnabled() && item_rect.pointInRect( x, y ) ) + if (item->getEnabled() && item_rect.pointInRect( x, y )) { hit_item = item; break; @@ -1857,7 +1926,7 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y ) item_rect.translate(0, -mLineHeight); } - line++; + if (++line > last_line) break; // Don't try to hit any undrawn items } return hit_item; @@ -1915,6 +1984,63 @@ S32 LLScrollListCtrl::getRowOffsetFromIndex(S32 index) return row_bottom; } +bool LLScrollListCtrl::filterItem(LLScrollListItem* item) +{ + for (const auto& column : item->mColumns) + { + // Only filter text, search tooltip because it'll usually be the text anyway. + if (column->isText() && boost::icontains(column->getToolTip(), mFilter)) + { + item->setFiltered(false); + return false; + } + } + item->setFiltered(true); + return true; +} + +void LLScrollListCtrl::setFilter(const std::string& filter) +{ + if (filter == mFilter) return; + + bool no_filter = filter.empty(); + // If our filter string has been expanded, we can skip already filtered items + bool expanded = !no_filter && !mFilter.empty() && boost::icontains(filter, mFilter); + // If our filter string has been contracted, we can skip already unfiltered items + bool contracted = !no_filter && !mFilter.empty() && !expanded && boost::icontains(mFilter, filter); + bool unique = !expanded && !contracted; + + mFilter = filter; + S32 unfiltered_count = no_filter ? mItemList.size() // No filter, doc size is all items + : !unique ? mScrollbar->getDocSize() // Expanded/contracted filter, start with the current doc size and remove/add respectively + : 0; // Different filter, count up from 0; + for (auto& item : mItemList) + { + if (no_filter) item->setFiltered(false); + else if (expanded && !item->getFiltered()) // Filter has been expanded and we are not yet filtered + { + if (filterItem(item)) --unfiltered_count; // We are now filtered, lower the count + } + else if (unique || // Filter isn't expanded, find out if we should be filtered or + (contracted && item->getFiltered())) // Filter has contracted and we were filtered before, should we still be? + { + if (!filterItem(item)) ++unfiltered_count; // Wasn't filltered, bump count + } + } + + if (mLastSelected && mLastSelected->getFiltered()) // Remove selection if filtered. + mLastSelected = nullptr; + + // Scrollbar needs adjusted + setScrollPos(0); // Changing the filter resets scroll position + adjustScrollbar(unfiltered_count); +} + +void LLScrollListCtrl::setContextMenu(const std::string& menu) +{ + setContextMenu(LLUICtrlFactory::instance().buildMenu(menu, LLMenuGL::sMenuContainer)); +} + BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) { @@ -2144,26 +2270,28 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char) while(iter != start_iter) { LLScrollListItem* item = *iter; - - LLScrollListCell* cellp = item->getColumn(getSearchColumn()); - if (cellp) + if (!item->getFiltered()) { - // Only select enabled items with matching first characters - LLWString item_label = utf8str_to_wstring(cellp->getValue().asString()); - if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char) + LLScrollListCell* cellp = item->getColumn(getSearchColumn()); + if (cellp) { - selectItem(item); - mNeedsScroll = true; - cellp->highlightText(0, 1); - mSearchTimer.reset(); - - if (mCommitOnKeyboardMovement - && !mCommitOnSelectionChange) + // Only select enabled items with matching first characters + LLWString item_label = utf8str_to_wstring(cellp->getValue().asString()); + if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char) { - onCommit(); - } + selectItem(item); + mNeedsScroll = true; + cellp->highlightText(0, 1); + mSearchTimer.reset(); - break; + if (mCommitOnKeyboardMovement + && !mCommitOnSelectionChange) + { + onCommit(); + } + + break; + } } } @@ -2264,7 +2392,7 @@ struct SameSortColumn SameSortColumn(S32 column) : mColumn(column) {} S32 mColumn; - bool operator()(std::pair sort_column) { return sort_column.first == mColumn; } + bool operator()(LLScrollListCtrl::sort_column_t sort_column) { return sort_column.first == mColumn; } }; BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending) @@ -2298,6 +2426,16 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending) } } +void LLScrollListCtrl::setSortEnabled(bool sort) +{ + bool update = sort && !mSortEnabled; + mSortEnabled = sort; + if (update) + { + updateSort(); + } +} + S32 LLScrollListCtrl::getLinesPerPage() { //if mPageLines is NOT provided display all item @@ -2319,6 +2457,12 @@ void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar ) } +void LLScrollListCtrl::setSortOrder(const sort_order_t& order) +{ + mSortColumns = order; + updateSort(); +} + void LLScrollListCtrl::sortByColumn(const std::string& name, BOOL ascending) { column_map_t::iterator itor = mColumns.find(name); @@ -2352,7 +2496,7 @@ void LLScrollListCtrl::updateSort() const // for one-shot sorts, does not save sort column/order void LLScrollListCtrl::sortOnce(S32 column, BOOL ascending) { - std::vector > sort_column; + std::vector sort_column; sort_column.push_back(std::make_pair(column, ascending)); // do stable sort to preserve any previous sorts @@ -2556,61 +2700,43 @@ void LLScrollListCtrl::setScrollListParameters(LLXMLNodePtr node) if (node->hasAttribute("menu_num")) { - // Some scroll lists use common menus identified by number - // 0 is menu_avs_list.xml, 1 will be for groups, 2 could be for lists of objects + // Some UI uses common menus identified by number + // 0 is avatars, 1 will be for groups, others could be for lists of objects or locations or experiences S32 menu_num; node->getAttributeS32("menu_num", menu_num); - mPopupMenu = sScrollListMenus[menu_num]; + mPopupMenu = sMenus[menu_num]; } else if (node->hasAttribute("menu_file")) { - std::string menu_file; - node->getAttributeString("menu_file", menu_file); - mPopupMenu = LLUICtrlFactory::getInstance()->buildMenu(menu_file, LLMenuGL::sMenuContainer); + std::string menu; + node->getAttributeString("menu_file", menu); + if (!menu.empty()) setContextMenu(menu); } -} - -// static -LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - LLRect rect; - createRect(node, rect, parent, LLRect()); - - BOOL multi_select = false; - node->getAttributeBOOL("multi_select", multi_select); - BOOL draw_border = true; - node->getAttributeBOOL("draw_border", draw_border); - BOOL draw_heading = false; - node->getAttributeBOOL("draw_heading", draw_heading); - S32 search_column = 0; - node->getAttributeS32("search_column", search_column); - S32 sort_column = -1; - node->getAttributeS32("sort_column", sort_column); - BOOL sort_ascending = true; - node->getAttributeBOOL("sort_ascending", sort_ascending); - - LLScrollListCtrl* scroll_list = new LLScrollListCtrl("scroll_list", rect, NULL, multi_select, draw_border, draw_heading); if (node->hasAttribute("heading_height")) { S32 heading_height; node->getAttributeS32("heading_height", heading_height); - scroll_list->setHeadingHeight(heading_height); + setHeadingHeight(heading_height); } - scroll_list->setScrollListParameters(node); - scroll_list->initFromXML(node, parent); - scroll_list->setSearchColumn(search_column); + S32 search_column = 0; + node->getAttributeS32("search_column", search_column); + BOOL sort_ascending = true; + node->getAttributeBOOL("sort_ascending", sort_ascending); + + setSearchColumn(search_column); LLSD columns; S32 index = 0; const std::string nodename(std::string(node->getName()->mString) + '.'); - const std::string kidcolumn(nodename + "columns"); + const std::string kidcolumns(nodename + "columns"); + const std::string kidcolumn(nodename + "column"); for (LLXMLNodePtr child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) { - if (child->hasName("column") || child->hasName(kidcolumn)) + if (child->hasName("column") || child->hasName("columns") || child->hasName(kidcolumn) || child->hasName(kidcolumns)) { - std::string labelname(""); + std::string labelname; if (child->getAttributeString("label", labelname)) columns[index]["label"] = labelname; else if (child->getAttributeString("image", labelname)) @@ -2633,9 +2759,9 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac } else // Singu Note: if a scroll list does not provide sort_direction, provide sort_ascending to sort as expected { - bool sort_ascending = true; - child->getAttribute_bool("sort_ascending", sort_ascending); - columns[index]["sort_ascending"] = sort_ascending; + bool col_sort_ascending = sort_ascending; + child->getAttribute_bool("sort_ascending", col_sort_ascending); + columns[index]["sort_ascending"] = col_sort_ascending; } S32 columnwidth = -1; @@ -2661,12 +2787,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac ++index; } } - scroll_list->setColumnHeadings(columns); - - if (sort_column >= 0) - { - scroll_list->sortByColumnIndex(sort_column, sort_ascending); - } + setColumnHeadings(columns); const std::string kidrow(nodename + "row"); const std::string kidrows(nodename + "rows"); @@ -2688,20 +2809,21 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac bool explicit_column = false; for (LLXMLNodePtr row_child = child->getFirstChild(); row_child.notNull(); row_child = row_child->getNextSibling()) { - if (row_child->hasName("column")) + if (row_child->hasName("column") || row_child->hasName("columns")) { std::string value = row_child->getTextContents(); + row_child->getAttributeString("value", value); row["columns"][column_idx]["value"] = value; - std::string columnname(""); + std::string columnname; if (row_child->getAttributeString("name", columnname)) row["columns"][column_idx]["column"] = columnname; - std::string font(""); + std::string font; if (row_child->getAttributeString("font", font)) row["columns"][column_idx]["font"] = font; - std::string font_style(""); + std::string font_style; if (row_child->getAttributeString("font-style", font_style)) row["columns"][column_idx]["font-style"] = font_style; @@ -2710,33 +2832,58 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac } } if(explicit_column) - scroll_list->addElement(row); + addElement(row); else { LLSD entry_id; if(id_found) entry_id = id; - scroll_list->addSimpleElement(value,ADD_BOTTOM,entry_id); + addSimpleElement(value,ADD_BOTTOM,entry_id); } } } - scroll_list->setCommentText(node->getTextContents()); + S32 sort_column = -1; + node->getAttributeS32("sort_column", sort_column); + if (sort_column >= 0) + { + sortByColumnIndex(sort_column, sort_ascending); + } + + setCommentText(node->getTextContents()); +} + +// static +LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +{ + LLRect rect; + createRect(node, rect, parent, LLRect()); + + BOOL multi_select = false; + node->getAttributeBOOL("multi_select", multi_select); + + BOOL draw_border = true; + node->getAttributeBOOL("draw_border", draw_border); + + BOOL draw_heading = false; + node->getAttributeBOOL("draw_heading", draw_heading); + + LLScrollListCtrl* scroll_list = new LLScrollListCtrl("scroll_list", rect, NULL, multi_select, draw_border, draw_heading); + + scroll_list->setScrollListParameters(node); + scroll_list->initFromXML(node, parent); return scroll_list; } // LLEditMenuHandler functions // virtual -void LLScrollListCtrl::copy() +void LLScrollListCtrl::copy() const { std::string buffer; - - std::vector items = getAllSelected(); - std::vector::iterator itor; - for (itor = items.begin(); itor != items.end(); ++itor) + for (auto item : getAllSelected()) { - buffer += (*itor)->getContentsCSV() + "\n"; + buffer += item->getContentsCSV() + '\n'; } gClipboard.copyFromSubstring(utf8str_to_wstring(buffer), 0, buffer.length()); } @@ -2768,7 +2915,7 @@ void LLScrollListCtrl::selectAll() for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem *itemp = *iter; - if( itemp->getEnabled() ) + if (itemp->getEnabled() && !itemp->getFiltered()) { selectItem(itemp, FALSE); } @@ -2939,7 +3086,7 @@ std::string LLScrollListCtrl::getSortColumnName() BOOL LLScrollListCtrl::hasSortOrder() const { - return !mSortColumns.empty(); + return mSortEnabled && !mSortColumns.empty(); } void LLScrollListCtrl::clearSortOrder() @@ -3017,10 +3164,10 @@ void LLScrollListCtrl::setColumnHeadings(const LLSD& headings) "width" "dynamic_width" */ -LLFastTimer::DeclareTimer FTM_ADD_SCROLLLIST_ELEMENT("Add Scroll List Item"); +LLTrace::BlockTimerStatHandle FTM_ADD_SCROLLLIST_ELEMENT("Add Scroll List Item"); LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata) { - LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT); + LL_RECORD_BLOCK_TIME(FTM_ADD_SCROLLLIST_ELEMENT); LLScrollListItem::Params item_params; LLParamSDParser parser; parser.readSD(element, item_params); @@ -3030,14 +3177,14 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos) { - LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT); + LL_RECORD_BLOCK_TIME(FTM_ADD_SCROLLLIST_ELEMENT); LLScrollListItem *new_item = new LLScrollListItem(item_p); return addRow(new_item, item_p, pos); } LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos) { - LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT); + LL_RECORD_BLOCK_TIME(FTM_ADD_SCROLLLIST_ELEMENT); if (!item_p.validateBlock() || !new_item) return NULL; new_item->setNumColumns(mColumns.size()); @@ -3054,7 +3201,7 @@ LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLS // empty columns strings index by ordinal if (column.empty()) { - column = llformat("%d", col_index); + column = fmt::to_string(col_index); } LLScrollListColumn* columnp = getColumn(column); diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 96df91b80c..c1dcf8eed6 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -32,6 +32,7 @@ #include #include +#include "lfidbearer.h" #include "lluictrl.h" #include "llctrlselectioninterface.h" #include "llfontgl.h" @@ -48,6 +49,7 @@ class LLMenuGL; class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, public LLCtrlListInterface, public LLCtrlScrollInterface +, public LFIDBearer { public: typedef boost::function callback_t; @@ -194,12 +196,12 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, // "StringUUID" interface: use this when you're creating a list that contains non-unique strings each of which // has an associated, unique UUID, and only one of which can be selected at a time. LLScrollListItem* addStringUUIDItem(const std::string& item_text, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); - LLUUID getStringUUIDSelectedItem() const; + LLUUID getStringUUIDSelectedItem() const override final; LLScrollListItem* getFirstSelected() const; virtual S32 getFirstSelectedIndex() const; std::vector getAllSelected() const; - uuid_vec_t getSelectedIDs(); //Helper. Much like getAllSelected, but just provides a LLUUID vec + uuid_vec_t getSelectedIDs() const override final; //Helper. Much like getAllSelected, but just provides a LLUUID vec S32 getNumSelected() const; LLScrollListItem* getLastSelectedItem() const { return mLastSelected; } @@ -207,6 +209,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, LLScrollListItem* getFirstData() const; LLScrollListItem* getLastData() const; std::vector getAllData() const; + uuid_vec_t getAllIDs() const; //Helper. Much like getAllData, but just provides a LLUUID vec LLScrollListItem* getItem(const LLSD& sd) const; @@ -248,8 +251,21 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, void clearSearchString() { mSearchString.clear(); } - // support right-click context menus for avatar/group lists + bool filterItem(LLScrollListItem* item); + void setFilter(const std::string& filter); + + // Context Menus void setContextMenu(LLMenuGL* menu) { mPopupMenu = menu; } + void setContextMenu(U8 index) { mPopupMenu = sMenus[index]; } + void setContextMenu(const std::string& menu); + + Type getSelectedType() const override + { + for (auto i = 0; mPopupMenu && i < COUNT; ++i) + if (sMenus[i] == mPopupMenu) + return (Type)i; + return LFIDBearer::getSelectedType(); + } // Overridden from LLView /*virtual*/ void draw(); @@ -273,6 +289,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, virtual void resetDirty(); // Clear dirty state virtual void updateLayout(); + void adjustScrollbar(S32 doc_size); virtual void fitContents(S32 max_width, S32 max_height); virtual LLRect getRequiredRect(); @@ -288,7 +305,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, static void onClickColumn(void *userdata); - virtual void updateColumns(); + virtual void updateColumns(bool force_update = false); S32 calcMaxContentWidth(); bool updateColumnWidths(); S32 getMaxContentWidth() { return mMaxContentWidth; } @@ -305,7 +322,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, virtual void scrollToShowSelected(); // LLEditMenuHandler functions - virtual void copy(); + void copy() const override final; virtual BOOL canCopy() const; virtual void cut(); virtual BOOL canCut() const; @@ -318,10 +335,15 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, void updateStaticColumnWidth(LLScrollListColumn* col, S32 new_width); S32 getTotalStaticColumnWidth() { return mTotalStaticColumnWidth; } + typedef std::pair sort_column_t; + typedef std::vector sort_order_t; + const sort_order_t& getSortOrder() const { return mSortColumns; } std::string getSortColumnName(); BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; } BOOL hasSortOrder() const; + void setSortOrder(const sort_order_t& order); void clearSortOrder(); + void setSortEnabled(bool sort); template S32 selectMultiple(const std::vector& vec) { @@ -351,7 +373,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, void setNeedsSortColumn(S32 col) { if(!isSorted())return; - for(std::vector >::iterator it=mSortColumns.begin();it!=mSortColumns.end();++it) + for(auto it=mSortColumns.begin();it!=mSortColumns.end();++it) { if((*it).first == col) { @@ -368,6 +390,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, return mSortCallback->connect(cb); } + S32 getLinesPerPage(); protected: // "Full" interface: use this when you're creating a list that has one or more of the following: @@ -404,7 +427,6 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, void deselectItem(LLScrollListItem* itemp); void commitIfChanged(); BOOL setSort(S32 column, BOOL ascending); - S32 getLinesPerPage(); S32 mLineHeight; // the max height of a single line S32 mScrollLines; // how many lines we've scrolled down @@ -423,6 +445,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, bool mDisplayColumnHeaders; bool mColumnsDirty; bool mColumnWidthsDirty; + bool mSortEnabled; mutable item_list mItemList; @@ -454,11 +477,13 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, S32 mHighlightedItem; class LLViewBorder* mBorder; LLMenuGL *mPopupMenu; - + LLView *mCommentTextView; LLWString mSearchString; LLFrameTimer mSearchTimer; + + std::string mFilter; S32 mSearchColumn; S32 mNumDynamicWidthColumns; @@ -476,8 +501,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, typedef std::vector ordered_columns_t; ordered_columns_t mColumnsIndexed; - typedef std::pair sort_column_t; - std::vector mSortColumns; + sort_order_t mSortColumns; sort_signal_t* mSortCallback; }; // end class LLScrollListCtrl diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp index 3abe322a91..d6d3cf2aa3 100644 --- a/indra/llui/llscrolllistitem.cpp +++ b/indra/llui/llscrolllistitem.cpp @@ -28,6 +28,7 @@ #include "linden_common.h" #include "llscrolllistitem.h" +#include "llview.h" //--------------------------------------------------------------------------- @@ -37,6 +38,7 @@ LLScrollListItem::LLScrollListItem( const Params& p ) : mSelected(FALSE), mEnabled(p.enabled), + mFiltered(false), mUserdata(p.userdata), mItemValue(p.value), mColumns() @@ -116,32 +118,73 @@ std::string LLScrollListItem::getContentsCSV() const } -void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) +bool LLScrollListItem::draw(const U32 pass, const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) { - // draw background rect - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLRect bg_rect = rect; - gl_rect_2d( bg_rect, bg_color ); - - S32 cur_x = rect.mLeft; - S32 num_cols = getNumColumns(); - S32 cur_col = 0; + const U32 num_cols = (U32)getNumColumns(); - for (LLScrollListCell* cell = getColumn(0); cur_col < num_cols; cell = getColumn(++cur_col)) + // draw background rect + if (pass == 0) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(rect, bg_color); + return true; + } + // Draw column (pass - 1) + else if (pass <= num_cols) { + LLScrollListCell* cur_cell = getColumn(pass - 1); + if (!cur_cell) + { + return false; + } // Two ways a cell could be hidden - if (cell->getWidth() < 0 - || !cell->getVisible()) continue; - - LLUI::pushMatrix(); + else if (cur_cell->getWidth() && cur_cell->getVisible()) { - LLUI::translate((F32) cur_x, (F32) rect.mBottom); - - cell->draw( fg_color, highlight_color ); + // Iterate over cells to the left and calculate offset. + S32 offset = rect.mLeft; + for (U32 i = 0; i < (pass - 1); ++i) + { + LLScrollListCell* cell = getColumn(i); + if (!cell) + { + return false; // Shouldn't happen. + } + if (cell->getVisible() && cell->getWidth()) + { + // Only apply padding if cell is visible and has width. + offset += cell->getWidth() + column_padding; + } + } + // Do not draw if not on screen. + // Only care about horizontal bounds. This draw call wont even occur if this row is entirely off screen. + LLRect clip_rect = LLUI::getRootView()->getRect(); + if (LLGLState::isEnabled()) + { + LLRect scissor = gGL.getScissor(); + scissor.mLeft /= LLUI::getScaleFactor().mV[VX]; + scissor.mTop /= LLUI::getScaleFactor().mV[VY]; + scissor.mRight /= LLUI::getScaleFactor().mV[VX]; + scissor.mBottom /= LLUI::getScaleFactor().mV[VY]; + clip_rect.intersectWith(scissor); + } + if (offset + LLFontGL::sCurOrigin.mX >= clip_rect.mRight) + { + // Went off the right edge of the screen. Don't bother with any more columns. + return false; + } + // Draw if not off the left edge of screen. If it is off the left edge, still return true if other colums remain. + if (offset + LLFontGL::sCurOrigin.mX + cur_cell->getWidth() > clip_rect.mLeft) + { + LLUI::pushMatrix(); + { + LLUI::translate((F32)offset, (F32)rect.mBottom); + cur_cell->draw(fg_color, highlight_color); + } + LLUI::popMatrix(); + } } - LLUI::popMatrix(); - - cur_x += cell->getWidth() + column_padding; + return pass != getNumColumns(); } + return false; } diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h index 0d87a0fbf5..f291b7cf25 100644 --- a/indra/llui/llscrolllistitem.h +++ b/indra/llui/llscrolllistitem.h @@ -71,6 +71,9 @@ class LLScrollListItem void setEnabled( BOOL b ) { mEnabled = b; } BOOL getEnabled() const { return mEnabled; } + void setFiltered(bool b) { if (mFiltered = b) mSelected = false; } + bool getFiltered() const { return mFiltered; } + void setUserdata( void* userdata ) { mUserdata = userdata; } void* getUserdata() const { return mUserdata; } @@ -92,7 +95,7 @@ class LLScrollListItem std::string getContentsCSV() const; - virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding); + virtual bool draw(const U32 pass, const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding); protected: LLScrollListItem( const Params& ); @@ -100,6 +103,7 @@ class LLScrollListItem private: BOOL mSelected; BOOL mEnabled; + bool mFiltered; void* mUserdata; LLSD mItemValue; std::vector mColumns; diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp index 14fa0cd0f8..10beb24773 100644 --- a/indra/llui/llslider.cpp +++ b/indra/llui/llslider.cpp @@ -54,7 +54,6 @@ LLSlider::LLSlider( F32 min_value, F32 max_value, F32 increment, - BOOL volume, const std::string& control_name) : LLUICtrl( name, rect, TRUE, commit_callback, @@ -64,7 +63,6 @@ LLSlider::LLSlider( mMinValue( min_value ), mMaxValue( max_value ), mIncrement( increment ), - mVolumeSlider( volume ), mMouseOffset( 0 ), mTrackColor( LLUI::sColorsGroup->getColor( "SliderTrackColor" ) ), mThumbOutlineColor( LLUI::sColorsGroup->getColor( "SliderThumbOutlineColor" ) ), @@ -72,9 +70,9 @@ LLSlider::LLSlider( mMouseDownSignal( NULL ), mMouseUpSignal( NULL ) { - mThumbImage = LLUI::getUIImage("icn_slide-thumb_dark.tga"); - mTrackImage = LLUI::getUIImage("icn_slide-groove_dark.tga"); - mTrackHighlightImage = LLUI::getUIImage("icn_slide-highlight.tga"); + mThumbImage = LLUI::getUIImage("SliderThumb_Off"); + mTrackImage = LLUI::getUIImage("SliderTrack_Horiz"); + mTrackHighlightImage = LLUI::getUIImage("SliderTrack_Horiz_Highlight"); // properly handle setting the starting thumb rect // do it this way to handle both the operating-on-settings @@ -172,7 +170,7 @@ BOOL LLSlider::handleMouseUp(S32 x, S32 y, MASK mask) if( hasMouseCapture() ) { - gFocusMgr.setMouseCapture( NULL ); + gFocusMgr.setMouseCapture(nullptr ); if (mMouseUpSignal) (*mMouseUpSignal)( this, getValueF32() ); @@ -229,15 +227,12 @@ BOOL LLSlider::handleKeyHere(KEY key, MASK mask) BOOL handled = FALSE; switch(key) { - case KEY_UP: case KEY_DOWN: - // eat up and down keys to be consistent - handled = TRUE; - break; case KEY_LEFT: setValueAndCommit(getValueF32() - getIncrement()); handled = TRUE; break; + case KEY_UP: case KEY_RIGHT: setValueAndCommit(getValueF32() + getIncrement()); handled = TRUE; @@ -248,6 +243,16 @@ BOOL LLSlider::handleKeyHere(KEY key, MASK mask) return handled; } +BOOL LLSlider::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + F32 old_val = getValueF32(); + F32 new_val = old_val - clicks * getIncrement(); + setValueAndCommit(new_val); + // Singu Note: We have to tell the viewer we're done dragging if it cares + if (mMouseUpSignal && old_val != new_val) (*mMouseUpSignal)(this, new_val); + return TRUE; +} + void LLSlider::draw() { F32 alpha = getDrawContext().mAlpha; @@ -276,7 +281,7 @@ void LLSlider::draw() mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor() % alpha, gFocusMgr.getFocusFlashWidth()); } - if( hasMouseCapture() ) + if( hasMouseCapture() ) // currently clicking on slider { // Show ghost where thumb was before dragging began. if (mThumbImage.notNull()) @@ -310,20 +315,11 @@ LLXMLNodePtr LLSlider::getXML(bool save_children) const { LLXMLNodePtr node = LLUICtrl::getXML(); - if (mVolumeSlider) - { - node->setName(LL_VOLUME_SLIDER_CTRL_TAG); - } - else - { - node->setName(LL_SLIDER_TAG); - } - + node->setName(LL_SLIDER_TAG); node->createChild("initial_val", TRUE)->setFloatValue(getInitialValue()); node->createChild("min_val", TRUE)->setFloatValue(getMinValue()); node->createChild("max_val", TRUE)->setFloatValue(getMaxValue()); node->createChild("increment", TRUE)->setFloatValue(getIncrement()); - node->createChild("volume", TRUE)->setBoolValue(mVolumeSlider); return node; } @@ -358,17 +354,13 @@ LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFacto F32 increment = 0.1f; node->getAttributeF32("increment", increment); - BOOL volume = node->hasName("volume_slider") ? TRUE : FALSE; - node->getAttributeBOOL("volume", volume); - LLSlider* slider = new LLSlider("slider_bar", rect, NULL, initial_value, min_value, max_value, - increment, - volume); + increment); slider->initFromXML(node, parent); diff --git a/indra/llui/llslider.h b/indra/llui/llslider.h index 59bda673fa..4fe90193ee 100644 --- a/indra/llui/llslider.h +++ b/indra/llui/llslider.h @@ -48,7 +48,6 @@ class LLSlider : public LLUICtrl F32 min_value, F32 max_value, F32 increment, - BOOL volume, //TODO: create a "volume" slider sub-class or just use image art, no? -MG const std::string& control_name = LLStringUtil::null ); virtual LLXMLNodePtr getXML(bool save_children = true) const; @@ -75,12 +74,12 @@ class LLSlider : public LLUICtrl boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); - - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual void draw(); + BOOL handleHover(S32 x, S32 y, MASK mask) override; + BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + BOOL handleKeyHere(KEY key, MASK mask) override; + BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override; + void draw() override; private: void setValueAndCommit(F32 value); @@ -92,7 +91,6 @@ class LLSlider : public LLUICtrl F32 mMaxValue; F32 mIncrement; - BOOL mVolumeSlider; S32 mMouseOffset; LLRect mDragStartThumbRect; diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index be2562e6d2..0f164711ee 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -59,7 +59,6 @@ LLSliderCtrl::LLSliderCtrl(const std::string& name, const LLRect& rect, S32 text_left, BOOL show_text, BOOL can_edit_text, - BOOL volume, commit_callback_t commit_callback, F32 initial_value, F32 min_value, F32 max_value, F32 increment, const std::string& control_which) @@ -67,7 +66,6 @@ LLSliderCtrl::LLSliderCtrl(const std::string& name, const LLRect& rect, mFont(font), mShowText( show_text ), mCanEditText( can_edit_text ), - mVolumeSlider( volume ), mPrecision( 3 ), mLabelBox( NULL ), mLabelWidth( label_width ), @@ -105,7 +103,7 @@ LLSliderCtrl::LLSliderCtrl(const std::string& name, const LLRect& rect, mSlider = new LLSlider(std::string("slider"), slider_rect, boost::bind(&LLSliderCtrl::onSliderCommit,_1,_2), - initial_value, min_value, max_value, increment, volume, + initial_value, min_value, max_value, increment, control_which ); addChild( mSlider ); @@ -387,8 +385,6 @@ LLXMLNodePtr LLSliderCtrl::getXML(bool save_children) const node->createChild("show_text", TRUE)->setBoolValue(mShowText); node->createChild("can_edit_text", TRUE)->setBoolValue(mCanEditText); - - node->createChild("volume", TRUE)->setBoolValue(mVolumeSlider); node->createChild("decimal_digits", TRUE)->setIntValue(mPrecision); @@ -438,9 +434,6 @@ LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory BOOL can_edit_text = FALSE; node->getAttributeBOOL("can_edit_text", can_edit_text); - BOOL volume = FALSE; - node->getAttributeBOOL("volume", volume); - F32 initial_value = 0.f; node->getAttributeF32("initial_val", initial_value); @@ -497,7 +490,6 @@ LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory rect.getWidth() - text_left, show_text, can_edit_text, - volume, NULL, initial_value, min_value, diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h index a5bc3488c2..0b173a5319 100644 --- a/indra/llui/llsliderctrl.h +++ b/indra/llui/llsliderctrl.h @@ -57,7 +57,6 @@ class LLSliderCtrl : public LLUICtrl S32 text_left, BOOL show_text, BOOL can_edit_text, - BOOL volume, //TODO: create a "volume" slider sub-class or just use image art, no? -MG commit_callback_t commit_callback, F32 initial_value, F32 min_value, F32 max_value, F32 increment, const std::string& control_which = LLStringUtil::null ); @@ -125,8 +124,7 @@ class LLSliderCtrl : public LLUICtrl const LLFontGL* mFont; BOOL mShowText; BOOL mCanEditText; - BOOL mVolumeSlider; - + S32 mPrecision; LLTextBox* mLabelBox; S32 mLabelWidth; diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index 9c50c54027..57c9f3aa6b 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -264,6 +264,7 @@ void LLSpinCtrl::forceSetValue(const LLSD& value ) mValue = v; updateEditor(); + mEditor->resetScrollPosition(); } } @@ -329,7 +330,9 @@ void LLSpinCtrl::onEditorCommit( const LLSD& data ) if( success ) { - updateEditor(); + // We committed and clamped value + // try to display as much as possible + mEditor->resetScrollPosition(); } else { @@ -461,6 +464,7 @@ BOOL LLSpinCtrl::handleKeyHere(KEY key, MASK mask) // text editors don't support revert normally (due to user confusion) // but not allowing revert on a spinner seems dangerous updateEditor(); + mEditor->resetScrollPosition(); mEditor->setFocus(FALSE); return TRUE; } diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp index 751156a31e..b13dbd907d 100644 --- a/indra/llui/llstatbar.cpp +++ b/indra/llui/llstatbar.cpp @@ -45,23 +45,17 @@ /////////////////////////////////////////////////////////////////////////////////// -LLStatBar::LLStatBar(const std::string& name, const LLRect& rect, const std::string& setting, +LLStatBar::LLStatBar(const std::string& name, const LLRect& rect, LLStat* stat, const Parameters& parameters, const std::string& setting, BOOL default_bar, BOOL default_history) : LLView(name, rect, TRUE), mSetting(setting), mLabel(name), - mMinBar(0.f), - mMaxBar(50.f), - mStatp(NULL), - mTickSpacing(10.f), - mLabelSpacing(10.f), - mPrecision(0), - mUpdatesPerSec(5), - mPerSec(true), - mDisplayMean(true) + mParameters(parameters), + mStatp(stat), + mValue(0.f), + mMinShift(0), + mMaxShift(0) { - mValue = 0.f; - S32 mode = -1; if (mSetting.length() > 0) { @@ -133,7 +127,7 @@ void LLStatBar::draw() // Get the values. F32 current, min, max, mean; - if (mPerSec) + if (mParameters.mPerSec) { current = mStatp->getCurrentPerSec(); min = mStatp->getMinPerSec(); @@ -149,9 +143,9 @@ void LLStatBar::draw() } - if ((mUpdatesPerSec == 0.f) || (mUpdateTimer.getElapsedTimeF32() > 1.f/mUpdatesPerSec) || (mValue == 0.f)) + if ((mParameters.mUpdatesPerSec == 0.f) || (mUpdateTimer.getElapsedTimeF32() > 1.f/mParameters.mUpdatesPerSec) || (mValue == 0.f)) { - if (mDisplayMean) + if (mParameters.mDisplayMean) { mValue = mean; } @@ -170,22 +164,20 @@ void LLStatBar::draw() S32 tick_width = 1; S32 left, top, right, bottom; - F32 value_scale = max_width/(mMaxBar - mMinBar); + F32 value_scale = max_width/((mParameters.mMaxBar + mMaxShift) - (mParameters.mMinBar + mMinShift)); LLFontGL::getFontMonospace()->renderUTF8(mLabel, 0, 0, getRect().getHeight(), LLColor4(1.f, 1.f, 1.f, 1.f), LLFontGL::LEFT, LLFontGL::TOP); - std::string value_format; + std::string value_str; - if (!mUnitLabel.empty()) + if (!mParameters.mUnitLabel.empty()) { - value_format = llformat( "%%.%df%%s", mPrecision); - value_str = llformat( value_format.c_str(), mValue, mUnitLabel.c_str()); + value_str = llformat( "%.*f%s", mParameters.mPrecision, mValue, mParameters.mUnitLabel.c_str()); } else { - value_format = llformat( "%%.%df", mPrecision); - value_str = llformat( value_format.c_str(), mValue); + value_str = llformat("%.*f", mParameters.mPrecision, mValue); } // Draw the value. @@ -193,11 +185,8 @@ void LLStatBar::draw() LLColor4(1.f, 1.f, 1.f, 0.5f), LLFontGL::RIGHT, LLFontGL::TOP); - value_format = llformat( "%%.%df", mPrecision); if (mDisplayBar) { - std::string tick_label; - // Draw the tick marks. F32 tick_value; top = bar_top; @@ -205,24 +194,23 @@ void LLStatBar::draw() LLGLSUIDefault gls_ui; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - for (tick_value = mMinBar; tick_value <= mMaxBar; tick_value += mTickSpacing) + for (tick_value = mParameters.mMinBar + mMinShift; tick_value <= (mParameters.mMaxBar + mMaxShift); tick_value += mParameters.mTickSpacing) { - left = llfloor((tick_value - mMinBar)*value_scale); + left = llfloor((tick_value - (mParameters.mMinBar + mMinShift))*value_scale); right = left + tick_width; gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.1f)); } // Draw the tick labels (and big ticks). bottom = bar_top - bar_height - tick_height; - for (tick_value = mMinBar; tick_value <= mMaxBar; tick_value += mLabelSpacing) + for (tick_value = mParameters.mMinBar + mMinShift; tick_value <= (mParameters.mMaxBar + mMaxShift); tick_value += mParameters.mLabelSpacing) { - left = llfloor((tick_value - mMinBar)*value_scale); + left = llfloor((tick_value - (mParameters.mMinBar + mMinShift))*value_scale); right = left + tick_width; gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.25f)); - tick_label = llformat( value_format.c_str(), tick_value); // draw labels for the tick marks - LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, left - 1, bar_top - bar_height - tick_height, + LLFontGL::getFontMonospace()->renderUTF8(llformat("%.*f", mParameters.mPrecision, tick_value), 0, left - 1, bar_top - bar_height - tick_height, LLColor4(1.f, 1.f, 1.f, 0.5f), LLFontGL::LEFT, LLFontGL::TOP); } @@ -242,7 +230,7 @@ void LLStatBar::draw() return; } // draw min and max - left = (S32) ((min - mMinBar) * value_scale); + left = (S32) ((min - (mParameters.mMinBar + mMinShift)) * value_scale); if (left < 0) { @@ -250,7 +238,7 @@ void LLStatBar::draw() LL_WARNS() << "Min:" << min << LL_ENDL; } - right = (S32) ((max - mMinBar) * value_scale); + right = (S32) ((max - (mParameters.mMinBar + mMinShift)) * value_scale); gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 0.f, 0.f, 0.25f)); S32 num_values = mStatp->getNumValues() - 1; @@ -263,44 +251,35 @@ void LLStatBar::draw() { continue; } - if (mPerSec) + if (mParameters.mPerSec) { - left = (S32)((mStatp->getPrevPerSec(i) - mMinBar) * value_scale); - right = (S32)((mStatp->getPrevPerSec(i) - mMinBar) * value_scale) + 1; - gl_rect_2d(left, bottom+i+1, right, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f)); + left = (S32)((mStatp->getPrevPerSec(i) - (mParameters.mMinBar + mMinShift)) * value_scale); + gl_rect_2d(left, bottom+i+1, left+1, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f)); } else { - left = (S32)((mStatp->getPrev(i) - mMinBar) * value_scale); - right = (S32)((mStatp->getPrev(i) - mMinBar) * value_scale) + 1; - gl_rect_2d(left, bottom+i+1, right, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f)); + left = (S32)((mStatp->getPrev(i) - (mParameters.mMinBar + mMinShift)) * value_scale); + gl_rect_2d(left, bottom+i+1, left + 1, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f)); } } } else { // draw current - left = (S32) ((current - mMinBar) * value_scale) - 1; - right = (S32) ((current - mMinBar) * value_scale) + 1; - gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 0.f, 0.f, 1.f)); + left = (S32) ((current - (mParameters.mMinBar + mMinShift)) * value_scale) - 1; + gl_rect_2d(left, top, left + 2, bottom, LLColor4(1.f, 0.f, 0.f, 1.f)); } // draw mean bar top = bar_top + 2; bottom = bar_top - bar_height - 2; - left = (S32) ((mean - mMinBar) * value_scale) - 1; - right = (S32) ((mean - mMinBar) * value_scale) + 1; - gl_rect_2d(left, top, right, bottom, LLColor4(0.f, 1.f, 0.f, 1.f)); + left = (S32)((mean - (mParameters.mMinBar + mMinShift)) * value_scale) - 1; + gl_rect_2d(left, top, left + 2, bottom, LLColor4(0.f, 1.f, 0.f, 1.f)); } LLView::draw(); } -void LLStatBar::setUnitLabel(const std::string& unit_label) -{ - mUnitLabel = unit_label; -} - LLRect LLStatBar::getRequiredRect() { LLRect rect; diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h index 8c1ef3ecd6..8d04c79526 100644 --- a/indra/llui/llstatbar.h +++ b/indra/llui/llstatbar.h @@ -47,33 +47,60 @@ class LLStatBar : public LLView }; public: - LLStatBar(const std::string& name, const LLRect& rect, const std::string& setting = std::string(), + struct Parameters { + Parameters() : + mMinBar(0.f), + mMaxBar(50.f), + mTickSpacing(10.f), + mLabelSpacing(10.f), + mPrecision(0), + mUpdatesPerSec(5), + mPerSec(true), + mDisplayMean(true), + mUnitLabel("") + {} + F32 mMinBar; + F32 mMaxBar; + F32 mTickSpacing; + F32 mLabelSpacing; + U32 mPrecision; + F32 mUpdatesPerSec; + BOOL mPerSec; // Use the per sec stats. + BOOL mDisplayMean; // If true, display mean, if false, display current value + std::string mUnitLabel; + }; + + LLStatBar(const std::string& name, const LLRect& rect, LLStat* stat, const LLStatBar::Parameters& parameters, const std::string& setting = std::string(), BOOL default_bar = FALSE, BOOL default_history = FALSE); virtual void draw(); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + void fit(F32 value) { + if (mParameters.mMinBar + mMinShift > value) + { + mMinShift = value - mParameters.mMinBar; + } + if (mParameters.mMaxBar + mMaxShift < value) + { + mMaxShift = value - mParameters.mMaxBar; + } + } - void setUnitLabel(const std::string& unit_label); /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options. - F32 mMinBar; - F32 mMaxBar; - F32 mTickSpacing; - F32 mLabelSpacing; - U32 mPrecision; - F32 mUpdatesPerSec; - BOOL mPerSec; // Use the per sec stats. +private: + const Parameters mParameters; BOOL mDisplayBar; // Display the bar graph. BOOL mDisplayHistory; - BOOL mDisplayMean; // If true, display mean, if false, display current value - LLStat *mStatp; -private: + const LLStat* mStatp; + const LLUIString mLabel; + const std::string mSetting; + LLFrameTimer mUpdateTimer; - LLUIString mLabel; - std::string mUnitLabel; F32 mValue; - std::string mSetting; + F32 mMinShift; + F32 mMaxShift; }; #endif diff --git a/indra/llui/llstatview.cpp b/indra/llui/llstatview.cpp index 9cd5ceb7eb..178c830de3 100644 --- a/indra/llui/llstatview.cpp +++ b/indra/llui/llstatview.cpp @@ -66,7 +66,7 @@ LLStatView::~LLStatView() } } -LLStatBar *LLStatView::addStat(const std::string& name, LLStat *statp, +LLStatBar *LLStatView::addStat(const std::string& name, LLStat *statp, const LLStatBar::Parameters& parameters, const std::string& setting, BOOL default_bar, BOOL default_history) { LLStatBar *stat_barp; @@ -74,8 +74,7 @@ LLStatBar *LLStatView::addStat(const std::string& name, LLStat *statp, mNumStatBars++; - stat_barp = new LLStatBar(name, r, setting, default_bar, default_history); - stat_barp->mStatp = statp; + stat_barp = new LLStatBar(name, r, statp, parameters, setting, default_bar, default_history); stat_barp->setVisible(mDisplayChildren); addChildInBack(stat_barp); diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h index 397c73ba56..cfd4c6576c 100644 --- a/indra/llui/llstatview.h +++ b/indra/llui/llstatview.h @@ -58,9 +58,10 @@ class LLStatView : public LLContainerView friend class LLUICtrlFactory; public: - LLStatBar *addStat(const std::string& name, LLStat *statp, + LLStatBar *addStat(const std::string& name, LLStat *statp, const LLStatBar::Parameters& parameters, const std::string& setting = std::string(), BOOL default_bar = FALSE, BOOL default_history = FALSE); LLStatView *addStatView(LLStatView::Params& p); + protected: typedef std::vector sb_vector_t; sb_vector_t mStatBars; diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index fde1550ba3..6de7511979 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1,11 +1,11 @@ -/** +/** * @file lltabcontainer.cpp * @brief LLTabContainer class * * $LicenseInfo:firstyear=2001&license=viewergpl$ - * + * * Copyright (c) 2001-2009, Linden Research, Inc. - * + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 @@ -13,17 +13,17 @@ * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. @@ -40,6 +40,7 @@ #include "llresmgr.h" #include "llresizehandle.h" #include "lltextbox.h" +#include "lltrans.h" #include "llcriticaldamp.h" #include "lluictrlfactory.h" #include "llrender.h" @@ -92,7 +93,7 @@ class LLTabTuple LLTabContainer::LLTabContainer(const std::string& name, const LLRect& rect, TabPosition pos, BOOL bordered, BOOL is_vertical ) - : + : LLPanel(name, rect, bordered), mCurrentTabIdx(-1), mTabsHidden(FALSE), @@ -114,7 +115,7 @@ LLTabContainer::LLTabContainer(const std::string& name, const LLRect& rect, TabP mJumpNextArrowBtn(NULL), mRightTabBtnOffset(0), mTotalTabWidth(0) -{ +{ //RN: HACK to support default min width for legacy vertical tab containers if (mIsVertical) { @@ -214,7 +215,7 @@ void LLTabContainer::draw() } } - setScrollPosPixels(mIsVertical ? target_pixel_scroll : lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f))); + setScrollPosPixels(mIsVertical ? target_pixel_scroll : lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLSmoothInterpolation::getInterpolant(0.08f))); BOOL has_scroll_arrows = !getTabsHidden() && ((mMaxScrollPos > 0) || (mScrollPosPixels > 0)); if (!mIsVertical) @@ -237,7 +238,7 @@ void LLTabContainer::draw() left = LLPANEL_BORDER_WIDTH + (has_scroll_arrows ? (TABCNTR_ARROW_BTN_SIZE * 2) : TABCNTR_TAB_H_PAD); left -= getScrollPosPixels(); } - + // Hide all the buttons if (getTabsHidden() || mIsVertical) { @@ -507,7 +508,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect ) { BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect ); - if (!handled && getTabCount() > 0 && !getTabsHidden()) + if (!handled && getTabCount() > 0 && !getTabsHidden()) { LLTabTuple* firsttuple = getTab(0); @@ -700,7 +701,7 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag mDragAndDropDelayTimer.stop(); } } - else + else { // Start a timer so we don't open tabs as soon as we hover on them mDragAndDropDelayTimer.start(); @@ -710,9 +711,9 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag return LLView::handleDragAndDrop(x, y, mask, drop, type, cargo_data, accept, tooltip); } -void LLTabContainer::addTabPanel(LLPanel* child, - const std::string& label, - BOOL select, +void LLTabContainer::addTabPanel(LLPanel* child, + const std::string& label, + BOOL select, S32 indent, BOOL placeholder, eInsertionPoint insertion_point) @@ -735,16 +736,16 @@ void LLTabContainer::addTabPanel(LLPanel* child, { button_width = llclamp(font->getWidth(trimmed_label) + TAB_PADDING, mMinTabWidth, mMaxTabWidth); } - + // Tab panel S32 tab_panel_top; S32 tab_panel_bottom; - if (!getTabsHidden()) + if (!getTabsHidden()) { if( getTabPosition() == LLTabContainer::TOP ) { S32 tab_height = mIsVertical ? BTN_HEIGHT : TABCNTR_TAB_HEIGHT; - tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - TABCNTR_BUTTON_PANEL_OVERLAP); + tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - TABCNTR_BUTTON_PANEL_OVERLAP); tab_panel_bottom = LLPANEL_BORDER_WIDTH; } else @@ -769,7 +770,7 @@ void LLTabContainer::addTabPanel(LLPanel* child, } else { - tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH, + tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH, tab_panel_top, getRect().getWidth()-LLPANEL_BORDER_WIDTH, tab_panel_bottom ); @@ -811,12 +812,12 @@ void LLTabContainer::addTabPanel(LLPanel* child, LLTextBox* textbox = NULL; LLButton* btn = NULL; - + if (placeholder) { btn_rect.translate(0, -LLBUTTON_V_PAD-2); textbox = new LLTextBox(trimmed_label, btn_rect, trimmed_label, font); - + btn = new LLButton(LLStringUtil::null); } else @@ -826,8 +827,8 @@ void LLTabContainer::addTabPanel(LLPanel* child, btn = new LLButton(std::string("vert tab button"), btn_rect, LLStringUtil::null, - LLStringUtil::null, - LLStringUtil::null, + LLStringUtil::null, + LLStringUtil::null, NULL, font, trimmed_label, trimmed_label); @@ -843,18 +844,13 @@ void LLTabContainer::addTabPanel(LLPanel* child, } else { - std::string tooltip = trimmed_label; - tooltip += "\nAlt-Left arrow for previous tab"; - tooltip += "\nAlt-Right arrow for next tab"; - btn = new LLButton(std::string(child->getName()) + " tab", - btn_rect, + btn_rect, LLStringUtil::null, LLStringUtil::null, LLStringUtil::null, NULL, // set userdata below font, trimmed_label, trimmed_label ); btn->setVisible( FALSE ); - btn->setToolTip( tooltip ); btn->setScaleImage(TRUE); btn->setImages(tab_img, tab_selected_img); @@ -877,8 +873,20 @@ void LLTabContainer::addTabPanel(LLPanel* child, btn->setFollowsBottom(); } } + std::string tooltip = trimmed_label; + LLStringUtil::format_map_t args; + args["[ALT]"] = LLTrans::getString( +#ifdef LL_DARWIN + "accel-mac-option" +#else + "accel-win-alt" +#endif + ); + tooltip += '\n' + LLTrans::getString("tab_tooltip_prev", args); + tooltip += '\n' + LLTrans::getString("tab_tooltip_next", args); + btn->setToolTip( tooltip ); } - + LLTabTuple* tuple = new LLTabTuple( this, child, btn, textbox ); insertTuple( tuple, insertion_point ); @@ -906,7 +914,7 @@ void LLTabContainer::addTabPanel(LLPanel* child, sendChildToFront(mNextArrowBtn); sendChildToFront(mJumpPrevArrowBtn); sendChildToFront(mJumpNextArrowBtn); - + if( select ) { selectLastTab(); @@ -958,7 +966,7 @@ void LLTabContainer::removeTabPanel(LLPanel* child) } } } - + BOOL has_focus = gFocusMgr.childHasKeyboardFocus(this); // If the tab being deleted is the selected one, select a different tab. @@ -972,7 +980,7 @@ void LLTabContainer::removeTabPanel(LLPanel* child) removeChild( tuple->mTabPanel ); // delete tuple->mTabPanel; - + mTabList.erase( iter ); delete tuple; @@ -1041,7 +1049,7 @@ void LLTabContainer::deleteAllTabs() // Actually delete the tuples themselves std::for_each(mTabList.begin(), mTabList.end(), DeletePointer()); mTabList.clear(); - + // And there isn't a current tab any more mCurrentTabIdx = -1; } @@ -1173,7 +1181,7 @@ void LLTabContainer::selectPrevTab() { mTabList[idx]->mButton->setFocus(TRUE); } -} +} BOOL LLTabContainer::selectTabPanel(LLPanel* child) { @@ -1205,7 +1213,7 @@ BOOL LLTabContainer::selectTab(S32 which) { return FALSE; } - + LLSD cbdata; if (selected_tuple->mTabPanel) cbdata = selected_tuple->mTabPanel->getName(); @@ -1219,7 +1227,7 @@ BOOL LLTabContainer::selectTab(S32 which) (*mCommitSignal)(this, cbdata); } } - + return res; } @@ -1247,7 +1255,7 @@ BOOL LLTabContainer::setTab(S32 which) tuple->mButton->setToggleState( is_selected ); // RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs tuple->mButton->setTabStop( is_selected ); - + if (is_selected) { // Make sure selected tab is within scroll region @@ -1391,7 +1399,7 @@ void LLTabContainer::reshapeTuple(LLTabTuple* tuple) { const LLFontGL* fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ); S32 image_overlay_width = 0; - image_overlay_width = tuple->mButton->getImageOverlay().notNull() ? + image_overlay_width = tuple->mButton->getImageOverlay().notNull() ? tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : 0; // remove current width from total tab strip width mTotalTabWidth -= tuple->mButton->getRect().getWidth(); @@ -1401,7 +1409,7 @@ void LLTabContainer::reshapeTuple(LLTabTuple* tuple) tuple->mPadding = image_overlay_width; tuple->mButton->setRightHPad(6); - tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), + tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tuple->mButton->getRect().getHeight()); // add back in button width to total tab strip width mTotalTabWidth += tuple->mButton->getRect().getWidth(); @@ -1412,7 +1420,7 @@ void LLTabContainer::reshapeTuple(LLTabTuple* tuple) } void LLTabContainer::setTitle(const std::string& title) -{ +{ if (mTitleBox) { mTitleBox->setText( title ); @@ -1452,10 +1460,18 @@ void LLTabContainer::setPanelTitle(S32 index, const std::string& title) { LLTabTuple* tuple = getTab(index); LLButton* tab_button = tuple->mButton; - const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall(); - mTotalTabWidth -= tab_button->getRect().getWidth(); - tab_button->reshape(llclamp(fontp->getWidth(title) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight()); - mTotalTabWidth += tab_button->getRect().getWidth(); + if (!mIsVertical) + { + const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall(); + mTotalTabWidth -= tab_button->getRect().getWidth(); + tab_button->reshape(llclamp(fontp->getWidth(title) + + TAB_PADDING + + tuple->mPadding, + mMinTabWidth, + mMaxTabWidth), + tab_button->getRect().getHeight()); + mTotalTabWidth += tab_button->getRect().getWidth(); + } tab_button->setLabelSelected(title); tab_button->setLabelUnselected(title); } @@ -1556,7 +1572,7 @@ LLView* LLTabContainer::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto node->getAttributeBOOL("border", border); LLTabContainer* tab_container = new LLTabContainer(name, LLRect::null, tab_position, border, is_vertical); - + S32 tab_min_width = tab_container->mMinTabWidth; if (node->hasAttribute("tab_width")) { @@ -1573,9 +1589,9 @@ LLView* LLTabContainer::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto node->getAttributeS32("tab_max_width", tab_max_width); } - tab_container->setMinTabWidth(tab_min_width); - tab_container->setMaxTabWidth(tab_max_width); - + tab_container->setMinTabWidth(tab_min_width); + tab_container->setMaxTabWidth(tab_max_width); + BOOL hidden(tab_container->getTabsHidden()); node->getAttributeBOOL("hide_tabs", hidden); tab_container->setTabsHidden(hidden); @@ -1614,7 +1630,7 @@ LLView* LLTabContainer::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto tab_container->postBuild(); tab_container->initButtons(); // now that we have the correct rect - + return tab_container; } @@ -1627,7 +1643,7 @@ void LLTabContainer::initButtons() { return; // Don't have a rect yet or already got called } - + std::string out_id; std::string in_id; @@ -1650,7 +1666,7 @@ void LLTabContainer::initButtons() mPrevArrowBtn->setFollowsTop(); mPrevArrowBtn->setFollowsLeft(); mPrevArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onPrevBtnHeld, this, _2)); - + out_id = "UIImgBtnScrollDownOutUUID"; in_id = "UIImgBtnScrollDownInUUID"; mNextArrowBtn = new LLButton(std::string("Down Arrow"), down_arrow_btn_rect, @@ -1661,7 +1677,7 @@ void LLTabContainer::initButtons() } else // Horizontal { - S32 arrow_fudge = 1; // match new art better + S32 arrow_fudge = 1; // match new art better // tabs on bottom reserve room for resize handle (just in case) if (getTabPosition() == BOTTOM) @@ -1705,7 +1721,7 @@ void LLTabContainer::initButtons() boost::bind(&LLTabContainer::onPrevBtn, this, _2), LLFontGL::getFontSansSerif() ); mPrevArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onPrevBtnHeld, this, _2)); mPrevArrowBtn->setFollowsLeft(); - + out_id = "UIImgBtnJumpRightOutUUID"; in_id = "UIImgBtnJumpRightInUUID"; mJumpNextArrowBtn = new LLButton(std::string("Jump Right Arrow"), jump_right_arrow_btn_rect, @@ -1740,7 +1756,7 @@ void LLTabContainer::initButtons() mPrevArrowBtn->setSaveToXML(false); mPrevArrowBtn->setTabStop(FALSE); addChild(mPrevArrowBtn); - + mNextArrowBtn->setSaveToXML(false); mNextArrowBtn->setTabStop(FALSE); addChild(mNextArrowBtn); @@ -1758,7 +1774,7 @@ void LLTabContainer::initButtons() mJumpNextArrowBtn->setTabStop(FALSE); addChild(mJumpNextArrowBtn); } - + // set default tab group to be panel contents setDefaultTabGroup(1); } @@ -1880,3 +1896,8 @@ void LLTabContainer::commitHoveredButton(S32 x, S32 y) } } +S32 LLTabContainer::getTotalTabWidth() const +{ + return mTotalTabWidth; +} + diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index de5a51639e..311e14b305 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -98,6 +98,7 @@ class LLTabContainer : public LLPanel S32 getIndexForPanel(LLPanel* panel); S32 getPanelIndexByTitle(const std::string& title); LLPanel* getPanelByName(const std::string& name); + S32 getTotalTabWidth() const; void setCurrentTabName(const std::string& name); void selectFirstTab(); diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index 738ec3b066..27215a20cf 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -113,6 +113,7 @@ class LLTextBox void setLineLengths(); void drawText(S32 x, S32 y, const LLColor4& color ); +protected: LLUIString mText; const LLFontGL* mFontGL; LLColor4 mTextColor; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 0412c302ea..d3eea88621 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -43,6 +43,7 @@ #include "lluictrlfactory.h" #include "lluiimage.h" #include "llurlaction.h" +#include "llurlregistry.h" #include "llrect.h" #include "llfocusmgr.h" #include "lltimer.h" @@ -64,6 +65,7 @@ #include "lltextparser.h" #include "lldir.h" #include +#include "llmemberlistener.h" #include "llmenugl.h" #include "../newview/lgghunspell_wrapper.h" @@ -95,9 +97,6 @@ const S32 PREEDIT_STANDOUT_GAP = 1; const S32 PREEDIT_STANDOUT_POSITION = 2; const S32 PREEDIT_STANDOUT_THICKNESS = 2; - -LLColor4 LLTextEditor::mLinkColor = LLColor4::blue; - /////////////////////////////////////////////////////////////////// class LLTextEditor::LLTextCmdInsert : public LLTextEditor::LLTextCmd @@ -246,50 +245,54 @@ class LLTextEditor::LLTextCmdRemove : public LLTextEditor::LLTextCmd /////////////////////////////////////////////////////////////////// -LLTextEditor::LLTextEditor( - const std::string& name, - const LLRect& rect, +LLTextEditor::LLTextEditor( + const std::string& name, + const LLRect& rect, S32 max_length, // In bytes - const std::string &default_text, + const std::string &default_text, const LLFontGL* font, - BOOL allow_embedded_items) - : - LLUICtrl( name, rect, TRUE, NULL, FOLLOWS_TOP | FOLLOWS_LEFT ), + BOOL allow_embedded_items, + bool parse_html) + : + LLUICtrl(name, rect, TRUE, NULL, FOLLOWS_TOP | FOLLOWS_LEFT), mTextIsUpToDate(TRUE), - mMaxTextByteLength( max_length ), + mMaxTextByteLength(max_length), mPopupMenuHandle(), mBaseDocIsPristine(TRUE), - mPristineCmd( NULL ), - mLastCmd( NULL ), - mCursorPos( 0 ), - mIsSelecting( FALSE ), - mSelectionStart( 0 ), - mSelectionEnd( 0 ), - mScrolledToBottom( TRUE ), - mOnScrollEndCallback( NULL ), - mOnScrollEndData( NULL ), - mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ), - mFgColor( LLUI::sColorsGroup->getColor( "TextFgColor" ) ), - mDefaultColor( LLUI::sColorsGroup->getColor( "TextDefaultColor" ) ), - mReadOnlyFgColor( LLUI::sColorsGroup->getColor( "TextFgReadOnlyColor" ) ), - mWriteableBgColor( LLUI::sColorsGroup->getColor( "TextBgWriteableColor" ) ), - mReadOnlyBgColor( LLUI::sColorsGroup->getColor( "TextBgReadOnlyColor" ) ), - mFocusBgColor( LLUI::sColorsGroup->getColor( "TextBgFocusColor" ) ), - mReadOnly(FALSE), - mWordWrap( FALSE ), - mShowLineNumbers ( FALSE ), - mTabsToNextField( TRUE ), - mCommitOnFocusLost( FALSE ), - mHideScrollbarForShortDocs( FALSE ), - mTakesNonScrollClicks( TRUE ), - mTrackBottom( FALSE ), - mAllowEmbeddedItems( allow_embedded_items ), + mPristineCmd(NULL), + mLastCmd(NULL), + mCursorPos(0), + mIsSelecting(FALSE), + mSelectionStart(0), + mSelectionEnd(0), + mScrolledToBottom(TRUE), + mOnScrollEndCallback(NULL), + mOnScrollEndData(NULL), + mCursorColor(LLUI::sColorsGroup->getColor("TextCursorColor")), + mFgColor(LLUI::sColorsGroup->getColor("TextFgColor")), + mDefaultColor(LLUI::sColorsGroup->getColor("TextDefaultColor")), + mReadOnlyFgColor(LLUI::sColorsGroup->getColor("TextFgReadOnlyColor")), + mWriteableBgColor(LLUI::sColorsGroup->getColor("TextBgWriteableColor")), + mReadOnlyBgColor(LLUI::sColorsGroup->getColor("TextBgReadOnlyColor")), + mFocusBgColor(LLUI::sColorsGroup->getColor("TextBgFocusColor")), + mLinkColor(nullptr), + mReadOnly(parse_html), + mWordWrap(FALSE), + mShowLineNumbers(FALSE), + mTabsToNextField(TRUE), + mCommitOnFocusLost(FALSE), + mHideScrollbarForShortDocs(FALSE), + mTakesNonScrollClicks(TRUE), + mTrackBottom(FALSE), + mAllowEmbeddedItems(allow_embedded_items), mAcceptCallingCardNames(FALSE), - mHandleEditKeysDirectly( FALSE ), + mHandleEditKeysDirectly(FALSE), mMouseDownX(0), mMouseDownY(0), mLastSelectionX(-1), mLastSelectionY(-1), + mParseHTML(parse_html), + mParseHighlights(false), mLastContextMenuX(-1), mLastContextMenuY(-1), mReflowNeeded(FALSE), @@ -312,105 +315,166 @@ LLTextEditor::LLTextEditor( updateTextRect(); - S32 line_height = ll_round( mGLFont->getLineHeight() ); + S32 line_height = ll_round(mGLFont->getLineHeight()); S32 page_size = mTextRect.getHeight() / line_height; // Init the scrollbar LLRect scroll_rect; - scroll_rect.setOriginAndSize( + scroll_rect.setOriginAndSize( getRect().getWidth() - SCROLLBAR_SIZE, 1, SCROLLBAR_SIZE, getRect().getHeight() - 1); S32 lines_in_doc = getLineCount(); - mScrollbar = new LLScrollbar( std::string("Scrollbar"), scroll_rect, + mScrollbar = new LLScrollbar(std::string("Scrollbar"), scroll_rect, LLScrollbar::VERTICAL, - lines_in_doc, - 0, + lines_in_doc, + 0, page_size, NULL); mScrollbar->setFollowsRight(); mScrollbar->setFollowsTop(); mScrollbar->setFollowsBottom(); - mScrollbar->setEnabled( TRUE ); - mScrollbar->setVisible( TRUE ); + mScrollbar->setEnabled(TRUE); + mScrollbar->setVisible(TRUE); mScrollbar->setOnScrollEndCallback(mOnScrollEndCallback, mOnScrollEndData); addChild(mScrollbar); - mBorder = new LLViewBorder( std::string("text ed border"), LLRect(0, getRect().getHeight(), getRect().getWidth(), 0), LLViewBorder::BEVEL_IN, LLViewBorder::STYLE_LINE, UI_TEXTEDITOR_BORDER ); - addChild( mBorder ); + mBorder = new LLViewBorder(std::string("text ed border"), LLRect(0, getRect().getHeight(), getRect().getWidth(), 0), LLViewBorder::BEVEL_IN, LLViewBorder::STYLE_LINE, UI_TEXTEDITOR_BORDER); + addChild(mBorder); appendText(default_text, FALSE, FALSE); - + resetDirty(); // Update saved text state - mParseHTML=FALSE; - mHTML.clear(); - // make the popup menu available - //LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_texteditor.xml", parent_view); - LLMenuGL* menu = new LLMenuGL("rclickmenu"); - /*if (!menu) - { - menu = new LLMenuGL(LLStringUtil::null); - }*/ - menu->addChild(new LLMenuItemCallGL("Cut", context_cut, NULL, this)); - menu->addChild(new LLMenuItemCallGL("Copy", context_copy, NULL, this)); - menu->addChild(new LLMenuItemCallGL("Paste", context_paste, NULL, this)); - menu->addChild(new LLMenuItemCallGL("Delete", context_delete, NULL, this)); - menu->addChild(new LLMenuItemCallGL("Select All", context_selectall, NULL, this)); - menu->addSeparator(); - menu->setCanTearOff(FALSE); - menu->setVisible(FALSE); - mPopupMenuHandle = menu->getHandle(); + setCommitCallback(boost::bind(&LLTextEditor::setControlValue, this, _2)); } LLTextEditor::~LLTextEditor() { gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() + if (mLinkColor) + { + delete mLinkColor; + mLinkColor = nullptr; + } // Scrollbar is deleted by LLView std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); - //LLView::deleteViewByHandle(mPopupMenuHandle); + mSegments.clear(); + auto menu = mPopupMenuHandle.get(); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } } -void LLTextEditor::context_cut(void* data) + +const std::string& LLTextEditor::getMenuSegmentUrl() const { - LLTextEditor* line = (LLTextEditor*)data; - if(line)line->cut(); + auto segment = getSegmentAtLocalPos(mLastContextMenuX, mLastContextMenuY); + auto style = segment ? segment->getStyle() : nullptr; + return style ? style->getLinkHREF() : LLStringUtil::null; } -void LLTextEditor::context_copy(void* data) + +static LFIDBearer::Type get_type_from_url(const std::string& url) { - LLTextEditor* line = (LLTextEditor*)data; - if(line)line->copy(); + auto pos = url.find("/app/"); + if (pos != std::string::npos && pos + 10 <= url.size()) + { + auto type = url.substr(pos + 5, 5); + return type == "agent" ? LFIDBearer::AVATAR + : type == "group" ? LFIDBearer::GROUP + : type == "experience" ? LFIDBearer::EXPERIENCE + : LFIDBearer::OBJECT; + } + return LFIDBearer::NONE; } +LLUUID LLTextEditor::getStringUUIDSelectedItem() const +{ + const auto& url = getMenuSegmentUrl(); + const auto& type = get_type_from_url(url); + return type == LFIDBearer::NONE ? LLUUID::null : LLUUID(type == OBJECT ? LLUrlAction::getObjectId(url) : LLUrlAction::getUserID(url)); +} -void LLTextEditor::spell_correct(void* data) +LFIDBearer::Type LLTextEditor::getSelectedType() const +{ + return get_type_from_url(getMenuSegmentUrl()); +} + +class CopyRawText : public LLMemberListener { - SpellMenuBind* tempBind = (SpellMenuBind*)data; - LLTextEditor* line = tempBind->origin; - if(tempBind && line) + bool handleEvent(LLPointer, const LLSD& userdata) override { - LL_INFOS() << tempBind->menuItem->getName() << " : " << tempBind->origin->getName() << " : " << tempBind->word << LL_ENDL; - if(line)line->spellReplace(tempBind); + LFIDBearer::getActive()->copyRaw(); + return true; } -} +}; +class TextEditorVisible : public LLMemberListener +{ + bool handleEvent(LLPointer, const LLSD& userdata) override + { + LLMenuGL::sMenuContainer->findControl(userdata["control"].asString())->setValue(!!dynamic_cast(gFocusMgr.getKeyboardFocus())); + return true; + } +}; -void LLTextEditor::spell_show(void * data) +class ContextUrl : public LLMemberListener { - SpellMenuBind* tempBind = (SpellMenuBind*)data; - LLTextEditor* line = tempBind->origin; + bool handleEvent(LLPointer, const LLSD& userdata) override + { + const auto& url = LFIDBearer::getActive()->getMenuSegmentUrl(); + const auto& op = userdata.asStringRef(); + if (op == "Open") LLUrlAction::openURL(url); + else if (op == "OpenInternal") LLUrlAction::openURLInternal(url); + else if (op == "OpenExternal") LLUrlAction::openURLExternal(url); + else if (op == "Execute") LLUrlAction::executeSLURL(url, true); + else if (op == "Block") LLUrlAction::blockObject(url); + else if (op == "Unblock") LLUrlAction::unblockObject(url); + else if (op == "Teleport") LLUrlAction::teleportToLocation(url); + else if (op == "ShowOnMap") LLUrlAction::showLocationOnMap(url); + else if (op == "CopyLabel") LLUrlAction::copyLabelToClipboard(url); + else if (op == "CopyUrl") LLUrlAction::copyURLToClipboard(url); + return true; + } +}; + +class ContextUrlCopy : public LLMemberListener +{ + bool handleEvent(LLPointer, const LLSD& userdata) override + { + LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(LFIDBearer::getActiveSelectedID().asString())); + return true; + } +}; - if(tempBind && line) + +void LLTextEditor::spell_correct(void* data) +{ + auto self = static_cast(data); + S32 wordStart = 0, wordLen = 0; + if (self->getWordBoundriesAt(self->getCursorPosFromLocalCoord(self->mLastContextMenuX, self->mLastContextMenuY, TRUE), &wordStart, &wordLen)) { - BOOL show = (tempBind->word == "Show Misspellings"); - glggHunSpell->setSpellCheckHighlight(show); + const auto& word = utf8str_to_wstring(LLMenuGL::sMenuContainer->getActivatedItem()->getLabel()); + + self->remove(wordStart, wordLen, TRUE); + self->insert(wordStart, word, FALSE); + self->mCursorPos += word.length() - wordLen; + self->needsReflow(); } } +void LLTextEditor::spell_show(void* show) +{ + glggHunSpell->setSpellCheckHighlight(!!show); +} + + std::vector LLTextEditor::getMisspelledWordsPositions() { resetSpellDirty(); @@ -454,29 +518,22 @@ std::vector LLTextEditor::getMisspelledWordsPositions() void LLTextEditor::spell_add(void* data) { - SpellMenuBind* tempBind = (SpellMenuBind*)data; - if(tempBind) + auto self = static_cast(data); + S32 wordStart = 0, wordLen = 0; + if (self->getWordBoundriesAt(self->getCursorPosFromLocalCoord(self->mLastContextMenuX, self->mLastContextMenuY, TRUE), &wordStart, &wordLen)) { - glggHunSpell->addWordToCustomDictionary(tempBind->word); - tempBind->origin->mPrevSpelledText.erase();//make it update + glggHunSpell->addWordToCustomDictionary(wstring_to_utf8str(self->getWText().substr(wordStart, wordLen))); + self->mPrevSpelledText.erase(); //make it update } } - -void LLTextEditor::context_paste(void* data) -{ - LLTextEditor* line = (LLTextEditor*)data; - if(line)line->paste(); -} -void LLTextEditor::context_delete(void* data) -{ - LLTextEditor* line = (LLTextEditor*)data; - if(line)line->doDelete(); -} -void LLTextEditor::context_selectall(void* data) +//static +void LLTextEditor::addMenuListeners() { - LLTextEditor* line = (LLTextEditor*)data; - if(line)line->selectAll(); + (new CopyRawText)->registerListener(LLMenuGL::sMenuContainer, "CopyRawText"); + (new TextEditorVisible)->registerListener(LLMenuGL::sMenuContainer, "TextEditorVisible"); + (new ContextUrl)->registerListener(LLMenuGL::sMenuContainer, "Text.Url"); + (new ContextUrlCopy)->registerListener(LLMenuGL::sMenuContainer, "Text.Url.CopyUUID"); } void LLTextEditor::setTrackColor( const LLColor4& color ) @@ -551,8 +608,17 @@ void LLTextEditor::updateLineStartList(S32 startpos) } } else - { - const llwchar* str = mWText.c_str() + start_idx; + { + //Scratch buffer. Avoid needless realloc. + static LLWString buf; + + if(start_idx) + { + buf.resize(end_idx - start_idx); + std::copy(mWText.begin() + start_idx, mWText.begin() + end_idx, buf.begin()); + } + const LLWString& str = start_idx ? buf : mWText; + S32 drawn = mGLFont->maxDrawableChars(str, (F32)abs(mTextRect.getWidth()) - line_width, end_idx - start_idx, mWordWrap ? LLFontGL::WORD_BOUNDARY_IF_POSSIBLE : LLFontGL::ANYWHERE, mAllowEmbeddedItems ); if( 0 == drawn && line_width == start_x) @@ -627,40 +693,56 @@ BOOL LLTextEditor::truncate() return did_truncate; } -void LLTextEditor::setText(const LLStringExplicit &utf8str) +LLMenuGL* LLTextEditor::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) { - // LLStringUtil::removeCRLF(utf8str); - mUTF8Text = utf8str_removeCRLF(utf8str); - // mUTF8Text = utf8str; - mWText = utf8str_to_wstring(mUTF8Text); - mTextIsUpToDate = TRUE; - - truncate(); - blockUndo(); - - setCursorPos(0); - deselect(); + // work out the XUI menu file to use for this url + LLUrlMatch match; + std::string url = in_url; + if (!LLUrlRegistry::instance().findUrl(url, match)) + { + return nullptr; + } - needsReflow(); + std::string xui_file = match.getMenuName(); + if (xui_file.empty()) + { + return nullptr; + } - resetDirty(); + // create and return the context menu from the XUI file + llassert(LLMenuGL::sMenuContainer != NULL); + auto menu = LLUICtrlFactory::instance().buildMenu(xui_file, LLMenuGL::sMenuContainer); + return menu; } -void LLTextEditor::setWText(const LLWString &wtext) +void LLTextEditor::setText(const LLStringExplicit &utf8str, bool force_replace_links) { - mWText = wtext; - mUTF8Text.clear(); - mTextIsUpToDate = FALSE; + // clear out the existing text and segments + mWText.clear(); - truncate(); - blockUndo(); + clearSegments(); +// createDefaultSegment(); - setCursorPos(0); deselect(); - needsReflow(); + // append the new text (supports Url linking) + std::string text(utf8str); + //LLStringUtil::removeCRLF(text); + + // appendText modifies mCursorPos... + appendText(utf8str, false, false, nullptr, force_replace_links); + // ...so move cursor to top after appending text + setCursorPos(0); resetDirty(); + + mUTF8Text = text; + mTextIsUpToDate = true; +} + +void LLTextEditor::setWText(const LLWString& text, bool force_replace_links) +{ + setText(wstring_to_utf8str(text), force_replace_links); } // virtual @@ -756,7 +838,7 @@ void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insen } // If still -1, then search_text just isn't found. - if (-1 == loc) + if (-1 == loc) { mIsSelecting = FALSE; mSelectionEnd = 0; @@ -879,9 +961,9 @@ S32 LLTextEditor::getLineStart( S32 line ) const { S32 num_lines = getLineCount(); if (num_lines == 0) - { + { return 0; - } + } line = llclamp(line, 0, num_lines-1); S32 segidx = mLineStartList[line].mSegment; @@ -1366,93 +1448,51 @@ BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask ) { setFocus(TRUE); - //setCursorAtLocalPos( x, y, TRUE ); - S32 wordStart = 0; - S32 wordLen = 0; - S32 pos = getCursorPosFromLocalCoord(x,y,TRUE); - - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + auto segment = getSegmentAtLocalPos(x, y); + const LLStyleSP style = segment ? segment->getStyle() : nullptr; + auto submenu = (style && style->isLink()) ? createUrlContextMenu(x, y, style->getLinkHREF()) : nullptr; + // Add url menu to base menu if we have a selection, otherwise make it the menu. + auto menu = (submenu && !hasSelection()) ? submenu : LLUICtrlFactory::instance().buildMenu("menu_texteditor.xml", LLMenuGL::sMenuContainer); + mPopupMenuHandle = menu->getHandle(); if (menu) { - for(int i = 0;i<(int)suggestionMenuItems.size();i++) + if (submenu && submenu != menu) { - SpellMenuBind * tempBind = suggestionMenuItems[i]; - if(tempBind) - { - menu->removeChild(tempBind->menuItem); - tempBind->menuItem->die(); - //delete tempBind->menuItem; - //tempBind->menuItem = NULL; - delete tempBind; - } + submenu->removeChild(submenu->getChild("Select All")); // There can be only one! + menu->appendMenu(submenu); } - suggestionMenuItems.clear(); // spell_check="true" in xui - menu->setItemVisible("Spelsep", !mReadOnly && mSpellCheckable); if (!mReadOnly && mSpellCheckable) { - bool is_word_part = getWordBoundriesAt(pos, &wordStart, &wordLen); - if (is_word_part) + S32 wordStart = 0; + S32 wordLen = 0; + S32 pos = getCursorPosFromLocalCoord(x, y, TRUE); + if (getWordBoundriesAt(pos, &wordStart, &wordLen)) { - const LLWString &text = mWText; - std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart,wordLen)); + const auto selectedWord = wstring_to_utf8str(getWText().substr(wordStart, wordLen)); if (!glggHunSpell->isSpelledRight(selectedWord)) { //misspelled word here, and you have just right clicked on it! - std::vector suggs = glggHunSpell->getSuggestionList(selectedWord); - for (int i = 0; i<(int)suggs.size(); i++) + menu->addSeparator(); + for (const auto& word : glggHunSpell->getSuggestionList(selectedWord)) { - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - tempStruct->word = suggs[i]; - tempStruct->wordPositionEnd = wordStart + wordLen; - tempStruct->wordPositionStart=wordStart; - tempStruct->wordY=y; - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - tempStruct->word, spell_correct, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); + menu->addChild(new LLMenuItemCallGL(word, spell_correct, nullptr, this)); } - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - tempStruct->word = selectedWord; - tempStruct->wordPositionEnd = wordStart + wordLen; - tempStruct->wordPositionStart=wordStart; - tempStruct->wordY=y; - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - "Add Word", spell_add, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); + menu->addChild(new LLMenuItemCallGL("Add Word", spell_add, nullptr, this)); } } - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - if (glggHunSpell->getSpellCheckHighlight()) - { - tempStruct->word = "Hide Misspellings"; - } - else - { - tempStruct->word = "Show Misspellings"; - } - - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - tempStruct->word, spell_show, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); + bool show = !glggHunSpell->getSpellCheckHighlight(); + auto word = show ? "Show Misspellings" : "Hide Misspellings"; + menu->addChild(new LLMenuItemCallGL(word, spell_show, nullptr, show ? &show : nullptr)); } + mLastContextMenuX = x; mLastContextMenuY = y; - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, menu, x, y); + showMenu(this, menu, x, y); } return TRUE; } @@ -1469,11 +1509,17 @@ BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask) return TRUE; } +bool always_underline_links() +{ + static const LLUICachedControl always_underline("SinguAlwaysUnderlineLinks"); + return always_underline; +} BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; + auto old_hover = mHoverSegment; mHoverSegment = NULL; if(hasMouseCapture() ) { @@ -1558,6 +1604,14 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask) } } + if (old_hover != mHoverSegment) + { + if (old_hover && !always_underline_links()) + old_hover->underlineOnHover(false); + if (mHoverSegment) + mHoverSegment->underlineOnHover(true); + } + if (mOnScrollEndCallback && mOnScrollEndData && (mScrollbar->getDocPos() == mScrollbar->getDocPosMax())) { mOnScrollEndCallback(mOnScrollEndData); @@ -1565,6 +1619,14 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask) return handled; } +void LLTextEditor::onMouseLeave(S32 x, S32 y, MASK mask) +{ + if (mHoverSegment && !always_underline_links()) + { + mHoverSegment->underlineOnHover(false); + mHoverSegment = nullptr; + } +} BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask) { @@ -1723,11 +1785,6 @@ S32 LLTextEditor::remove(const S32 pos, const S32 length, const BOOL group_with_ return execute( new LLTextCmdRemove( pos, group_with_next_op, length ) ); } -S32 LLTextEditor::append(const LLWString &wstr, const BOOL group_with_next_op) -{ - return insert(mWText.length(), wstr, group_with_next_op); -} - S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc) { if ((S32)mWText.length() == pos) @@ -2160,7 +2217,7 @@ BOOL LLTextEditor::canCopy() const } // copy selection to clipboard -void LLTextEditor::copy() +void LLTextEditor::copy(bool raw) const { if( !canCopy() ) { @@ -2168,7 +2225,54 @@ void LLTextEditor::copy() } S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); S32 length = llabs( mSelectionStart - mSelectionEnd ); - gClipboard.copyFromSubstring(mWText, left_pos, length, mSourceID); + // Does our selection include any Segments with links? + if (mParseHTML && raw) + { + auto begin = std::find_if(mSegments.begin(), mSegments.end(), [left_pos](const LLTextSegmentPtr& ptr) { + return ptr->getEnd() > left_pos; + }); + auto last = mSegments.end(); + if (begin == last || begin->isNull()) + { + gClipboard.copyFromSubstring(mWText, left_pos, length, mSourceID); + return; + } + S32 right_pos = left_pos + length, offset = 0; + { + // If our selection starts in the middle of a link, set our left_pos to the beginning of its segment. + auto segment = **begin; + if (auto style = segment.getStyle()) + if (style->isLink()) + left_pos = llmin(segment.getStart(), left_pos); + } + auto text = mWText.substr(left_pos, length); + for (; begin->notNull() && begin != last && (*begin)->getStart() <= right_pos; ++begin) + { + auto segment = **begin; + //llassert(segment->getStyle()); // If someone is stores the result of the S32 constructor, they're in so much trouble!! + const auto& link = segment.getStyle()->getLinkHREF(); + if (!link.empty()) + { + const S32 label_length = (segment.getEnd() - segment.getStart()); + const S32 start = (segment.getStart()+offset)-left_pos; + const auto label = text.substr(start, label_length); + const auto wlink = utf8str_to_wstring(link); + const auto pos = wlink.find(label); + // Do not replace if normal link, or contains normal link (but may omit protocol) but ends the same way + // (i.e. [http://foo.bar/baz foo.bar] should still be restored here but not foo.bar/baz or foo.bar + if (pos == std::string::npos // Label is not (part of) the url + || (pos != 0 && wlink[pos-1] != '/') || pos+label.size() != wlink.size()) // Label is part of the url but there's more on either side of the url after the protocol + { + constexpr llwchar startchar = '[', space = ' ', endchar = ']'; + const auto raw_html = startchar + wlink + space + label + endchar; + text.replace(start, label_length, raw_html); + offset += raw_html.size() - label_length; // Track how much we've offset the string by replacing labels with their raw html and thus adding characters + } + } + } + gClipboard.copyFromSubstring(text, 0, text.length(), mSourceID); + } + else gClipboard.copyFromSubstring(mWText, left_pos, length, mSourceID); } BOOL LLTextEditor::canPaste() const @@ -2177,17 +2281,6 @@ BOOL LLTextEditor::canPaste() const } -void LLTextEditor::spellReplace(SpellMenuBind* spellData) -{ - remove( spellData->wordPositionStart, - spellData->wordPositionEnd - spellData->wordPositionStart, TRUE ); - LLWString clean_string = utf8str_to_wstring(spellData->word); - insert(spellData->wordPositionStart, clean_string, FALSE); - mCursorPos+=clean_string.length() - (spellData->wordPositionEnd-spellData->wordPositionStart); - needsReflow(); -} - - // paste from clipboard void LLTextEditor::paste() { @@ -2406,6 +2499,17 @@ BOOL LLTextEditor::handleEditKey(const KEY key, const MASK mask) } handled = TRUE; } + else if ((mask & (MASK_CONTROL|MASK_SHIFT)) == (MASK_CONTROL|MASK_SHIFT)) + { + if (key == 'C') + { + if (canCopy()) + copy(true); + else + reportBadKeystroke(); + handled = TRUE; + } + } else if( MASK_CONTROL & mask ) { @@ -3019,7 +3123,7 @@ void LLTextEditor::drawSelectionBackground() { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); const LLColor4& color = mReadOnly ? mReadOnlyBgColor : mWriteableBgColor; - F32 alpha = hasFocus() ? 1.f : 0.5f; + F32 alpha = hasFocus() ? 1.f : 0.8f; gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha ); S32 margin_offset = mShowLineNumbers ? UI_TEXTEDITOR_LINE_NUMBER_MARGIN : 0; @@ -3436,12 +3540,14 @@ void LLTextEditor::drawText() F32 text_y = (F32)(mTextRect.mTop - line_height); while((mTextRect.mBottom <= text_y) && (cur_line < num_lines)) { + S32 next_line = cur_line + 1; + S32 next_start = -1; S32 line_end = text_len; - if ((cur_line + 1) < num_lines) + if (next_line < num_lines) { - next_start = getLineStart(cur_line + 1); + next_start = getLineStart(next_line); line_end = next_start; } line_wraps = text[line_end-1] != '\n'; @@ -3477,6 +3583,7 @@ void LLTextEditor::drawText() NULL); // max pixels } + // draw a single line of text S32 seg_start = line_start; while( seg_start < line_end ) { @@ -3511,13 +3618,6 @@ void LLTextEditor::drawText() style->mUnderline = TRUE; } - S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); - - if ( (mParseHTML) && (left_pos > seg_start) && (left_pos < clipped_end) && mIsSelecting && (mSelectionStart == mSelectionEnd) ) - { - mHTML = style->getLinkHREF(); - } - drawClippedSegment( text, seg_start, clipped_end, text_x, text_y, selection_left, selection_right, style, &text_x ); if( text_x == text_start && mShowLineNumbers ) @@ -4067,31 +4167,76 @@ void LLTextEditor::appendColoredText(const std::string &new_text, style->setVisible(true); style->setColor(lcolor); style->setFontName(font_name); - appendStyledText(new_text, allow_undo, prepend_newline, style); + appendText(new_text, allow_undo, prepend_newline, style); } -void LLTextEditor::appendStyledText(const std::string &new_text, - bool allow_undo, - bool prepend_newline, - LLStyleSP stylep) +static LLTrace::BlockTimerStatHandle FTM_APPEND_TEXT("Append Text"); + +void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool prepend_newline, + const LLStyleSP style, bool force_replace_links) { - S32 part = (S32)LLTextParser::WHOLE; - if(mParseHTML) + LL_RECORD_BLOCK_TIME(FTM_APPEND_TEXT); + if (new_text.empty()) + return; + + std::string text = prepend_newline && !mWText.empty() ? ('\n' + new_text) : new_text; + appendTextImpl(text, style, force_replace_links); + + if (!allow_undo) { + blockUndo(); + } +} + +static LLTrace::BlockTimerStatHandle FTM_PARSE_HTML("Parse HTML"); - S32 start=0,end=0; - std::string text = new_text; - while ( findHTML(text, &start, &end) ) +// Appends new text to end of document +void LLTextEditor::appendTextImpl(const std::string &new_text, const LLStyleSP style, bool force_replace_links) +{ + std::string text = new_text; + static const LLUICachedControl replace_links("SinguReplaceLinks"); + force_replace_links = force_replace_links || replace_links; + bool is_link = style && style->isLink(); // Don't search for URLs inside a link segment (STORM-358). + + S32 part = (S32)LLTextParser::WHOLE; + if (mReadOnly && mParseHTML && !is_link) // Singu Note: Do not replace html if the user is going to edit it. (Like in profiles) + { + LL_RECORD_BLOCK_TIME(FTM_PARSE_HTML); + size_t start=0, end=0; + LLUrlMatch match; + auto append_substr = [&](const size_t& pos, const size_t& count) { - LLStyleSP html(new LLStyle); - html->setVisible(true); - html->setColor(mLinkColor); - if (stylep) + appendAndHighlightText(text.substr(pos, count), part, style); + }; + auto append_link = [&](const std::string& link, LLStyleSP link_style) + { + if (!link_style->isLink()) + { + appendAndHighlightText(link, part, style); + return; + } + + if (style) // Respect styling { - html->setFontName(stylep->getFontString()); + const auto& text_style = *style; + link_style->mItalic = text_style.mItalic; + link_style->mBold = text_style.mBold; + link_style->mUnderline = text_style.mUnderline; } - html->mUnderline = TRUE; + // Hack around colors looking bad on some backgrounds by allowing setting link color for this editor + if (mLinkColor) link_style->setColor(*mLinkColor); + const auto always_underline(always_underline_links()); + if (always_underline) link_style->mUnderline = true; + appendAndHighlightText(link, part, link_style, !always_underline/*match.underlineOnHoverOnly()*/); + }; + const auto&& cb = force_replace_links ? boost::bind(&LLTextEditor::replaceUrl, this, _1, _2, _3) : static_cast(LLUrlRegistryNullCallback); + auto& urlr = LLUrlRegistry::instance(); + while (!text.empty() && urlr.findUrl(text, match, cb)) + { + start = match.getStart(); + end = match.getEnd()+1; + // output the text before the Url if (start > 0) { if (part == (S32)LLTextParser::WHOLE || @@ -4103,15 +4248,69 @@ void LLTextEditor::appendStyledText(const std::string &new_text, { part = (S32)LLTextParser::MIDDLE; } - std::string subtext=text.substr(0,start); - appendHighlightedText(subtext,allow_undo, prepend_newline, part, stylep); + append_substr(0, start); } - - html->setLinkHREF(text.substr(start,end-start)); - appendText(text.substr(start, end-start),allow_undo, prepend_newline, html); - if (end < (S32)text.length()) + + auto url = match.getUrl(); + const auto& label = match.getLabel(); + if (force_replace_links || url == label) + { + // add icon before url if need + /* Singu TODO: Icons next to links? + LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted()); + if ((isContentTrusted() || match.isTrusted()) && !match.getIcon().empty() ) + { + link_style->setImage(match.getIcon()); + setLastSegmentToolTip(LLTrans::getString("TooltipSLIcon")); + }*/ + + // output the styled url + append_link(label + match.getQuery(), match.getStyle()); + bool tooltip_required = !match.getTooltip().empty(); + + // set the tooltip for the Url label + if (tooltip_required) + { + setLastSegmentToolTip(match.getTooltip()); + } + + /* Singu Note: Upstream uses hardcoded Grey here, they have no care for skins, this could be awful! + Also it splits up the link! For now just make it append it to the same segment with its label above. + // show query part of url with gray color only for LLUrlEntryHTTP and LLUrlEntryHTTPNoProtocol url entries + std::string label = match.getQuery(); + if (!label.empty()) + { + link_params.color = LLColor4::grey; + link_params.readonly_color = LLColor4::grey; + appendAndHighlightTextImpl(label, part, link_params, match.underlineOnHoverOnly()); + append_link(label); + + // set the tooltip for the query part of url + if (tooltip_required) + { + setLastSegmentToolTip(match.getTooltip()); + } + }*/ + } + else // Still link the link itself { - text = text.substr(end,text.length() - end); + const auto pos = text.find(url); + bool fallback(pos == std::string::npos); // In special cases like no protocol and brackets + bool brackets(fallback && text.find('[') == start); // Brackets + if (fallback == brackets && start < pos) // Leading text, only in special case if brackets present + append_substr(start, brackets ? 1 : pos-start); + // In the special cases, only link exactly the url, this might not have a protocol so calculate the exact string + if (fallback) url = brackets ? text.substr(start+1, text.find(' ', start+2)-start) : text.substr(start, end-start); + append_link(url, match.getStyle()); // Append the link + const auto url_end = pos + url.size(); + if (fallback == brackets && end > url_end) // Ending text, only in special case if brackets present + append_substr(url_end, end-url_end); + } + + // move on to the rest of the text after the Url + if (end < (S32)text.length()) + { + text = text.substr(end, text.length() - end); end=0; part=(S32)LLTextParser::END; } @@ -4120,51 +4319,135 @@ void LLTextEditor::appendStyledText(const std::string &new_text, break; } } - if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END; - if (end < (S32)text.length()) appendHighlightedText(text,allow_undo, prepend_newline, part, stylep); + if (part != (S32)LLTextParser::WHOLE) + part=(S32)LLTextParser::END; + if (end < (S32)text.length()) + appendAndHighlightText(text, part, style); } else { - appendHighlightedText(new_text, allow_undo, prepend_newline, part, stylep); + appendAndHighlightText(text, part, style); } } -void LLTextEditor::appendHighlightedText(const std::string &new_text, - bool allow_undo, - bool prepend_newline, - S32 highlight_part, - LLStyleSP stylep) +void LLTextEditor::setLastSegmentToolTip(const std::string &tooltip) { - // If LindenUserDir is empty then we didn't login yet. - // In that case we can't instantiate LLTextParser, which - // is initialized per user. - if (mParseHighlights && !gDirUtilp->getLindenUserDir(true).empty()) + LLTextSegmentPtr segment = mSegments.back(); + segment->setToolTip(tooltip); +} + +void LLTextEditor::appendLineBreakSegment(/*const LLStyle::Params& style_params*/) +{ + /* + segment_vec_t segments; + LLStyleSP sp(new LLStyle(style_params)); + const auto& length = getLength(); + segments.push_back(new LLTextSegment(sp, length, length + 1));*/ + + insertStringNoUndo(getLength(), LLWString(1, '\n')); +} + +void LLTextEditor::appendAndHighlightText(const std::string& new_text, S32 highlight_part, const LLStyleSP stylep, bool underline_on_hover) +{ + if (new_text.empty()) return; + + std::string::size_type start = 0; + /*std::string::size_type pos = new_text.find('\n',start); + + while(pos != std::string::npos) { - LLTextParser* highlight = LLTextParser::getInstance(); - - if (highlight && stylep) + if(pos!=start) + { + std::string str = std::string(new_text,start,pos-start); + appendAndHighlightTextImpl(str,highlight_part, stylep); + } + appendLineBreakSegment(); + start = pos+1; + pos = new_text.find('\n',start); + }*/ + + std::string str = std::string(new_text,start,new_text.length()-start); + appendAndHighlightTextImpl(str,highlight_part, stylep, underline_on_hover); +} + + +void LLTextEditor::replaceUrl(const std::string &url, + const std::string &label, + const std::string &icon) +{ + // get the full (wide) text for the editor so we can change it + LLWString text = getWText(); + LLWString wlabel = utf8str_to_wstring(label); + bool modified = false; + S32 seg_start = 0; + + // iterate through each segment looking for ones styled as links + for (auto it = mSegments.begin(); it != mSegments.end(); ++it) + { + LLTextSegment *seg = *it; + LLStyleSP style = seg->getStyle(); + + // update segment start/end length in case we replaced text earlier + S32 seg_length = seg->getEnd() - seg->getStart(); + seg->setStart(seg_start); + seg->setEnd(seg_start + seg_length); + + // if we find a link with our Url, then replace the label + if (style->getLinkHREF() == url) + { + S32 start = seg->getStart(); + S32 end = seg->getEnd(); + const auto& old_label = text.substr(start, end - start); + if (wlabel != old_label) + { + const auto difference = std::abs((S32)wlabel.length() - (S32)old_label.length()); + if (mSelectionEnd >= end) // Selection stays at/after end + { + mSelectionEnd += difference; + if (mSelectionStart >= end) + mSelectionStart += difference; + } + if (mCursorPos >= end) // Cursor stays at/after end + mCursorPos += difference; + text.replace(start, end - start, wlabel); + seg->setEnd(start + wlabel.size()); + modified = true; + } + } + + /* Singu TODO: Icons with Urls? + // Icon might be updated when more avatar or group info + // becomes available + if (style->isImage() && style->getLinkHREF() == url) { - LLSD pieces = highlight->parsePartialLineHighlights(new_text, stylep->getColor(), (LLTextParser::EHighlightPosition)highlight_part); - bool lprepend=prepend_newline; - for (S32 i=0;isetColor(lcolor); - if (i != 0 && (pieces.size() > 1) ) lprepend=FALSE; - appendText((std::string)pieces[i]["text"], allow_undo, lprepend, lstylep); + LLStyle::Params icon_params; + icon_params.image = image; + LLStyleConstSP new_style(new LLStyle(icon_params)); + seg->setStyle(new_style); + modified = true; } - return; } + */ + + // work out the character offset for the next segment + seg_start = seg->getEnd(); + } + + // update the editor with the new (wide) text string + if (modified) + { + mWText = text; + mTextIsUpToDate = FALSE; + setCursorPos(mCursorPos); + needsReflow(); } - appendText(new_text, allow_undo, prepend_newline, stylep); } -// Appends new text to end of document -void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool prepend_newline, - const LLStyleSP stylep) + +void LLTextEditor::appendAndHighlightTextImpl(const std::string& new_text, S32 highlight_part, const LLStyleSP stylep, bool underline_on_hover) { // Save old state BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()); @@ -4179,29 +4462,61 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool setCursorPos(old_length); - // Add carriage return if not first line - if (getLength() != 0 - && prepend_newline) + // This is where we appendHighlightedText + // If LindenUserDir is empty then we didn't login yet. + // In that case we can't instantiate LLTextParser, which is initialized per user. + LLTextParser* highlight = mParseHighlights && stylep && !gDirUtilp->getLindenUserDir(true).empty() ? LLTextParser::getInstance() : nullptr; + if (highlight) { - std::string final_text = "\n"; - final_text += new_text; - append(utf8str_to_wstring(final_text), TRUE); + const LLSD pieces = highlight->parsePartialLineHighlights(new_text, stylep->getColor(), (LLTextParser::EHighlightPosition)highlight_part); + auto cur_length = getLength(); + for (auto i = pieces.beginArray(), end = pieces.endArray(); i < end; ++i) + { + const auto& piece = *i; + LLWString wide_text = utf8str_to_wstring(piece["text"].asString()); + + insertStringNoUndo(cur_length, wide_text); + LLStyleSP sp(new LLStyle(*stylep)); + sp->setColor(piece["color"]); + auto wide_size = wide_text.size(); + LLTextSegmentPtr segmentp = new LLTextSegment(sp, cur_length, cur_length + wide_size); + cur_length += wide_size; + if (underline_on_hover) segmentp->setUnderlineOnHover(true); + mSegments.push_back(segmentp); + } } else { - append(utf8str_to_wstring(new_text), TRUE ); - } + LLWString wide_text = utf8str_to_wstring(new_text); - if (stylep) - { - S32 segment_start = old_length; - S32 segment_end = getLength(); - LLTextSegmentPtr segment = new LLTextSegment(stylep, segment_start, segment_end ); - mSegments.push_back(segment); + auto length = getLength(); + auto insert_len = length + insertStringNoUndo(length, utf8str_to_wstring(new_text)); + + if (stylep) + { + S32 segment_start = old_length; + S32 segment_end = old_length + wide_text.size(); + LLTextSegmentPtr segment = new LLTextSegment(stylep, segment_start, segment_end); + if (underline_on_hover) segment->setUnderlineOnHover(true); + mSegments.push_back(segment); + } + else // If no style, still make a segment, + { + auto segment = mSegments.empty() ? nullptr : mSegments.back(); + if (!segment || !segment->getIsDefault()) + { + LLColor4& text_color = (mReadOnly ? mReadOnlyFgColor : mFgColor); + LLTextSegmentPtr segment = new LLTextSegment(text_color, length, insert_len); + segment->setIsDefault(true); // call it a default segment so we can consolidate later. + mSegments.push_back(segment); + } + else // It's later! + { + segment->setEnd(insert_len); + } + } } - - needsReflow(); - + // Set the cursor and scroll position // Maintain the scroll position unless the scroll was at the end of the doc (in which // case, move it to the new end of the doc) or unless the user was doing actively selecting @@ -4215,14 +4530,11 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool } endOfDoc(); } - else if( selection_start != selection_end ) + else if (was_selecting || selection_start != selection_end) { mSelectionStart = selection_start; mSelectionEnd = selection_end; - - - mIsSelecting = was_selecting; setCursorPos(cursor_pos); } @@ -4234,11 +4546,6 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool { setCursorPos(cursor_pos); } - - if( !allow_undo ) - { - blockUndo(); - } } void LLTextEditor::removeTextFromEnd(S32 num_chars) @@ -4271,20 +4578,76 @@ S32 LLTextEditor::insertStringNoUndo(const S32 pos, const LLWString &wstr) mWText.insert(pos, wstr); mTextIsUpToDate = FALSE; - if ( truncate() ) + //HACK: If we are readonly we shouldn't need to truncate + if (!mReadOnly && truncate()) { // The user's not getting everything he's hoping for make_ui_sound("UISndBadKeystroke"); insert_len = mWText.length() - old_len; } + needsReflow(/*pos*/); + return insert_len; } S32 LLTextEditor::removeStringNoUndo(S32 pos, S32 length) { + auto seg_iter = getSegIterContaining(pos); + S32 end = pos + length; + while(seg_iter != mSegments.end()) + { + LLTextSegmentPtr segmentp = *seg_iter; + if (segmentp->getStart() < pos) + { + // deleting from middle of segment + if (segmentp->getEnd() > end) + { + segmentp->setEnd(segmentp->getEnd() - length); + } + // truncating segment + else + { + segmentp->setEnd(pos); + } + } + else if (segmentp->getStart() < end) + { + // deleting entire segment + if (segmentp->getEnd() <= end) + { + // remove segment + seg_iter = mSegments.erase(seg_iter); + continue; + } + // deleting head of segment + else + { + segmentp->setStart(pos); + segmentp->setEnd(segmentp->getEnd() - length); + } + } + else + { + // shifting segments backward to fill deleted portion + segmentp->setStart(segmentp->getStart() - length); + segmentp->setEnd(segmentp->getEnd() - length); + } + ++seg_iter; + } + mWText.erase(pos, length); + + // recreate default segment in case we erased everything + createDefaultSegment(); + mTextIsUpToDate = FALSE; + + /*needsReflow(pos);*/ + // Singu Note: This kinda sucks for performance of delete, fix this later (with LLTextBase merge?) + updateLineStartList(); + mReflowNeeded = false; + return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length } @@ -4396,13 +4759,32 @@ void LLTextEditor::loadKeywords(const std::string& filename, } } -static LLFastTimer::DeclareTimer FTM_SYNTAX_HIGHLIGHTING("Syntax Highlighting"); -static LLFastTimer::DeclareTimer FTM_UPDATE_TEXT_SEGMENTS("Update Text Segments"); +static LLTrace::BlockTimerStatHandle FTM_SYNTAX_HIGHLIGHTING("Syntax Highlighting"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_TEXT_SEGMENTS("Update Text Segments"); + + +void LLTextEditor::createDefaultSegment() +{ + if (mSegments.empty()) + { + LLColor4& text_color = (mReadOnly ? mReadOnlyFgColor : mFgColor); + LLTextSegmentPtr default_segment = new LLTextSegment(text_color, 0, mWText.length()); + default_segment->setIsDefault(TRUE); + mSegments.push_back(default_segment); + } +} + +void LLTextEditor::clearSegments() +{ + mLineStartList.clear(); + mSegments.clear(); + createDefaultSegment(); +} void LLTextEditor::updateSegments() { { - LLFastTimer ft(FTM_SYNTAX_HIGHLIGHTING); + LL_RECORD_BLOCK_TIME(FTM_SYNTAX_HIGHLIGHTING); if (mKeywords.isLoaded()) { // HACK: No non-ascii keywords for now @@ -4414,19 +4796,13 @@ void LLTextEditor::updateSegments() } } - LLFastTimer ft(FTM_UPDATE_TEXT_SEGMENTS); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_TEXT_SEGMENTS); // Make sure we have at least one segment if (mSegments.size() == 1 && mSegments[0]->getIsDefault()) { - mSegments.clear(); // create default segment - } - if (mSegments.empty()) - { - LLColor4& text_color = ( mReadOnly ? mReadOnlyFgColor : mFgColor ); - LLTextSegmentPtr default_segment = new LLTextSegment( text_color, 0, mWText.length() ); - default_segment->setIsDefault(TRUE); - mSegments.push_back(default_segment); + clearSegments(); // create default segment } + else createDefaultSegment(); } // Only effective if text was removed from the end of the editor @@ -4529,10 +4905,16 @@ BOOL LLTextEditor::handleMouseUpOverSegment(S32 x, S32 y, MASK mask) // This mouse up was part of a click. // Regardless of where the cursor is, see if we recently touched a link // and launch it if we did. - if (mParseHTML && mHTML.length() > 0) + if (mParseHTML) { - LLUrlAction::clickAction(mHTML); - mHTML.clear(); + if (auto segment = getSegmentAtLocalPos(x, y)) + { + if (auto style = segment->getStyle()) + { + if (style->isLink()) + LLUrlAction::clickAction(style->getLinkHREF(), true); + } + } } } @@ -4540,6 +4922,34 @@ BOOL LLTextEditor::handleMouseUpOverSegment(S32 x, S32 y, MASK mask) } +LLTextEditor::segment_list_t::iterator LLTextEditor::getSegIterContaining(S32 index) +{ + S32 text_len = getLength(); + + if (index > text_len) { return mSegments.end(); } + + // when there are no segments, we return the end iterator, which must be checked by caller + if (mSegments.size() <= 1) { return mSegments.begin(); } + + LLPointer index_segment = new LLTextSegment(index); + auto it = std::lower_bound(mSegments.begin(), mSegments.end(), index_segment, LLTextSegment::compare()); + return it; +} + +LLTextEditor::segment_list_t::const_iterator LLTextEditor::getSegIterContaining(S32 index) const +{ + S32 text_len = getLength(); + + if (index > text_len) { return mSegments.end(); } + + // when there are no segments, we return the end iterator, which must be checked by caller + if (mSegments.size() <= 1) { return mSegments.begin(); } + + LLPointer index_segment = new LLTextSegment(index); + auto it = std::lower_bound(mSegments.begin(), mSegments.end(), index_segment, LLTextSegment::compare()); + return it; +} + // Finds the text segment (if any) at the give local screen position LLTextSegment* LLTextEditor::getSegmentAtLocalPos( S32 x, S32 y ) const { @@ -4581,110 +4991,6 @@ void LLTextEditor::setOnScrollEndCallback(void (*callback)(void*), void* userdat mScrollbar->setOnScrollEndCallback(callback, userdata); } -/////////////////////////////////////////////////////////////////// -// Hack for Notecards - -BOOL LLTextEditor::importBuffer(const char* buffer, S32 length ) -{ - std::istringstream instream(buffer); - - // Version 1 format: - // Linden text version 1\n - // {\n - // - // Text length \n - // (text may contain ext_char_values) - // }\n - - char tbuf[MAX_STRING]; /* Flawfinder: ignore */ - - S32 version = 0; - instream.getline(tbuf, MAX_STRING); - if( 1 != sscanf(tbuf, "Linden text version %d", &version) ) - { - LL_WARNS() << "Invalid Linden text file header " << LL_ENDL; - return FALSE; - } - - if( 1 != version ) - { - LL_WARNS() << "Invalid Linden text file version: " << version << LL_ENDL; - return FALSE; - } - - instream.getline(tbuf, MAX_STRING); - if( 0 != sscanf(tbuf, "{") ) - { - LL_WARNS() << "Invalid Linden text file format" << LL_ENDL; - return FALSE; - } - - S32 text_len = 0; - instream.getline(tbuf, MAX_STRING); - if( 1 != sscanf(tbuf, "Text length %d", &text_len) ) - { - LL_WARNS() << "Invalid Linden text length field" << LL_ENDL; - return FALSE; - } - - if( text_len > mMaxTextByteLength ) - { - LL_WARNS() << "Invalid Linden text length: " << text_len << LL_ENDL; - return FALSE; - } - - BOOL success = TRUE; - - char* text = new char[ text_len + 1]; - if (text == NULL) - { - LL_ERRS() << "Memory allocation failure." << LL_ENDL; - return FALSE; - } - instream.get(text, text_len + 1, '\0'); - text[text_len] = '\0'; - if( text_len != (S32)strlen(text) )/* Flawfinder: ignore */ - { - LL_WARNS() << llformat("Invalid text length: %d != %d ",strlen(text),text_len) << LL_ENDL;/* Flawfinder: ignore */ - success = FALSE; - } - - instream.getline(tbuf, MAX_STRING); - if( success && (0 != sscanf(tbuf, "}")) ) - { - LL_WARNS() << "Invalid Linden text file format: missing terminal }" << LL_ENDL; - success = FALSE; - } - - if( success ) - { - // Actually set the text - setText( LLStringExplicit(text) ); - } - - delete[] text; - - setCursorPos(0); - deselect(); - - needsReflow(); - return success; -} - -BOOL LLTextEditor::exportBuffer(std::string &buffer ) -{ - std::ostringstream outstream(buffer); - - outstream << "Linden text version 1\n"; - outstream << "{\n"; - - outstream << llformat("Text length %d\n", mWText.length() ); - outstream << getText(); - outstream << "}\n"; - - return TRUE; -} - ////////////////////////////////////////////////////////////////////////// // LLTextSegment @@ -4730,15 +5036,34 @@ LLTextSegment::LLTextSegment( const LLColor3& color, S32 start, S32 end ) : BOOL LLTextSegment::getToolTip(std::string& msg) const { + // do we have a tooltip for a loaded keyword (for script editor)? if (mToken && !mToken->getToolTip().empty()) { const LLWString& wmsg = mToken->getToolTip(); msg = wstring_to_utf8str(wmsg); return TRUE; } + // or do we have an explicitly set tooltip (e.g., for Urls) + if (!mTooltip.empty()) + { + msg = mTooltip; + return TRUE; + } + return FALSE; } +void LLTextSegment::setToolTip(const std::string& tooltip) +{ + // we cannot replace a keyword tooltip that's loaded from a file + if (mToken) + { + LL_WARNS() << "LLTextSegment::setToolTip: cannot replace keyword tooltip." << LL_ENDL; + return; + } + mTooltip = tooltip; +} + void LLTextSegment::dump() const @@ -4767,6 +5092,7 @@ LLXMLNodePtr LLTextEditor::getXML(bool save_children) const node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont)); node->createChild("word_wrap", TRUE)->setBoolValue(mWordWrap); node->createChild("hide_scrollbar", TRUE)->setBoolValue(mHideScrollbarForShortDocs); + node->createChild("hide_border", TRUE)->setBoolValue(!mBorder->getVisible()); addColorXML(node, mCursorColor, "cursor_color", "TextCursorColor"); addColorXML(node, mFgColor, "text_color", "TextFgColor"); @@ -4782,40 +5108,6 @@ LLXMLNodePtr LLTextEditor::getXML(bool save_children) const return node; } -// static -LLView* LLTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - LLRect rect; - createRect(node, rect, parent, LLRect()); - - U32 max_text_length = 255; - node->getAttributeU32("max_length", max_text_length); - - BOOL allow_embedded_items; - node->getAttributeBOOL("embedded_items", allow_embedded_items); - - LLFontGL* font = LLView::selectFont(node); - - std::string text = node->getTextContents().substr(0, max_text_length - 1); - - LLTextEditor* text_editor = new LLTextEditor("text_editor", - rect, - max_text_length, - text, - font, - allow_embedded_items); - - text_editor->setTextEditorParameters(node); - - BOOL hide_scrollbar = FALSE; - node->getAttributeBOOL("hide_scrollbar",hide_scrollbar); - text_editor->setHideScrollbarForShortDocs(hide_scrollbar); - - text_editor->initFromXML(node, parent); - - return text_editor; -} - void LLTextEditor::setTextEditorParameters(LLXMLNodePtr node) { BOOL word_wrap = FALSE; @@ -4851,173 +5143,6 @@ void LLTextEditor::setTextEditorParameters(LLXMLNodePtr node) } } -/////////////////////////////////////////////////////////////////// -// Refactoring note: We may eventually want to replace this with boost::regex or -// boost::tokenizer capabilities since we've already fixed at least two JIRAs -// concerning logic issues associated with this function. -S32 LLTextEditor::findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const -{ - std::string openers=" \t\n('\"[{<>"; - std::string closers=" \t\n)'\"]}><;"; - - if (reverse) - { - for (int index=pos; index >= 0; index--) - { - char c = line[index]; - S32 m2 = openers.find(c); - if (m2 >= 0) - { - return index+1; - } - } - return 0; // index is -1, don't want to return that. - } - else - { - // adjust the search slightly, to allow matching parenthesis inside the URL - S32 paren_count = 0; - for (int index=pos; index<(S32)line.length(); index++) - { - char c = line[index]; - - if (c == '(') - { - paren_count++; - } - else if (c == ')') - { - if (paren_count <= 0) - { - return index; - } - else - { - paren_count--; - } - } - else - { - S32 m2 = closers.find(c); - if (m2 >= 0) - { - return index; - } - } - } - return line.length(); - } -} - -BOOL LLTextEditor::findHTML(const std::string &line, S32 *begin, S32 *end) const -{ - - S32 m1,m2,m3; - BOOL matched = FALSE; - - m1=line.find("://",*end); - - if (m1 >= 0) //Easy match. - { - *begin = findHTMLToken(line, m1, TRUE); - *end = findHTMLToken(line, m1, FALSE); - - //Load_url only handles http and https so don't hilite ftp, smb, etc. - m2 = line.substr(*begin,(m1 - *begin)).find("http"); - m3 = line.substr(*begin,(m1 - *begin)).find("secondlife"); - - std::string badneighbors=".,<>?';\"][}{=-+_)(*&^%$#@!~`\t\r\n\\"; - - if (m2 >= 0 || m3>=0) - { - S32 bn = badneighbors.find(line.substr(m1+3,1)); - - if (bn < 0) - { - matched = TRUE; - } - } - } -/* matches things like secondlife.com (no http://) needs a whitelist to really be effective. - else //Harder match. - { - m1 = line.find(".",*end); - - if (m1 >= 0) - { - *end = findHTMLToken(line, m1, FALSE); - *begin = findHTMLToken(line, m1, TRUE); - - m1 = line.rfind(".",*end); - - if ( ( *end - m1 ) > 2 && m1 > *begin) - { - std::string badneighbors=".,<>/?';\"][}{=-+_)(*&^%$#@!~`"; - m2 = badneighbors.find(line.substr(m1+1,1)); - m3 = badneighbors.find(line.substr(m1-1,1)); - if (m3<0 && m2<0) - { - matched = TRUE; - } - } - } - } - */ - - if (matched) - { - S32 strpos, strpos2; - - std::string url = line.substr(*begin,*end - *begin); - std::string slurlID = "slurl.com/secondlife/"; - strpos = url.find(slurlID); - - if (strpos < 0) - { - slurlID="maps.secondlife.com/secondlife/"; - strpos = url.find(slurlID); - } - - if (strpos < 0) - { - slurlID="secondlife://"; - strpos = url.find(slurlID); - } - - if (strpos < 0) - { - slurlID="sl://"; - strpos = url.find(slurlID); - } - - if (strpos >= 0) - { - strpos+=slurlID.length(); - - while ( ( strpos2=url.find("/",strpos) ) == -1 ) - { - if ((*end+2) >= (S32)line.length() || line.substr(*end,1) != " " ) - { - matched=FALSE; - break; - } - - strpos = (*end + 1) - *begin; - - *end = findHTMLToken(line,(*begin + strpos),FALSE); - url = line.substr(*begin,*end - *begin); - } - } - - } - - if (!matched) - { - *begin=*end=0; - } - return matched; -} - void LLTextEditor::updateAllowingLanguageInput() diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 7f68c41f89..09defc0495 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -43,16 +43,15 @@ #include "lleditmenuhandler.h" #include "llpreeditor.h" -#include "llmenugl.h" +#include "lfidbearer.h" class LLFontGL; -class LLScrollbar; -class LLViewBorder; class LLKeywordToken; +class LLMenuGL; class LLTextCmd; -class LLUICtrlFactory; class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor +, public LFIDBearer { public: // @@ -65,18 +64,25 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor LLTextEditor(const std::string& name, const LLRect& rect, S32 max_length, - const std::string &default_text, + const std::string &default_text, const LLFontGL* glfont = NULL, - BOOL allow_embedded_items = FALSE); + BOOL allow_embedded_items = FALSE, + bool parse_html = false); virtual ~LLTextEditor(); + const std::string& getMenuSegmentUrl() const; + + LLUUID getStringUUIDSelectedItem() const override final; + Type getSelectedType() const override final; + typedef boost::signals2::signal keystroke_signal_t; + static void addMenuListeners(); + void setKeystrokeCallback(const keystroke_signal_t::slot_type& callback); virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory); void setTextEditorParameters(LLXMLNodePtr node); void setParseHTML(BOOL parsing) {mParseHTML=parsing;} void setParseHighlights(BOOL parsing) {mParseHighlights=parsing;} @@ -85,6 +91,7 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask) override; virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask ); virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); @@ -114,16 +121,6 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor virtual BOOL isDirty() const { return( mLastCmd != NULL || (mPristineCmd && (mPristineCmd != mLastCmd)) ); } BOOL isSpellDirty() const { return mWText != mPrevSpelledText; } // Returns TRUE if user changed value at all void resetSpellDirty() { mPrevSpelledText = mWText; } // Clear dirty state - - struct SpellMenuBind - { - LLTextEditor* origin; - LLMenuItemCallGL * menuItem; - std::string word; - S32 wordPositionStart; - S32 wordPositionEnd; - S32 wordY; - }; // LLEditMenuHandler interface virtual void undo(); @@ -132,13 +129,13 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor virtual BOOL canRedo() const; virtual void cut(); virtual BOOL canCut() const; - virtual void copy(); + void copy(bool raw) const; + void copyRaw() const { copy(true); } + void copy() const override final { copy(false); } virtual BOOL canCopy() const; virtual void paste(); virtual BOOL canPaste() const; - virtual void spellReplace(SpellMenuBind* spellData); - virtual void updatePrimary(); virtual void copyPrimary(); virtual void pastePrimary(); @@ -150,12 +147,6 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor virtual BOOL canSelectAll() const; virtual void deselect(); virtual BOOL canDeselect() const; - static void context_cut(void* data); - - static void context_copy(void* data); - static void context_paste(void* data); - static void context_delete(void* data); - static void context_selectall(void* data); static void spell_correct(void* data); static void spell_add(void* data); static void spell_show(void* data); @@ -177,20 +168,24 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor void insertText(const std::string &text, BOOL deleteSelection = TRUE); // appends text at end void appendText(const std::string &wtext, bool allow_undo, bool prepend_newline, - const LLStyleSP stylep = NULL); + const LLStyleSP stylep = NULL, bool force_replace_links = true); + void appendTextImpl(const std::string& new_text, const LLStyleSP style, bool force_replace_links = true); + + void setLastSegmentToolTip(const std::string& tooltip); + + void appendLineBreakSegment(); + + void appendAndHighlightText(const std::string& new_text, S32 highlight_part, const LLStyleSP stylep, bool underline_on_hover = false); + + void replaceUrl(const std::string& url, const std::string& label, const std::string& icon); void appendColoredText(const std::string &wtext, bool allow_undo, bool prepend_newline, const LLColor4 &color, const std::string& font_name = LLStringUtil::null); - // if styled text starts a line, you need to prepend a newline. - void appendStyledText(const std::string &new_text, bool allow_undo, - bool prepend_newline, - LLStyleSP stylep = NULL); - void appendHighlightedText(const std::string &new_text, bool allow_undo, - bool prepend_newline, S32 highlight_part, - LLStyleSP stylep); + void appendAndHighlightTextImpl(const std::string& new_text, S32 highlight_part, const LLStyleSP stylep, bool underline_on_hover = false); + // Removes text from the end of document // Does not change highlight or cursor position. void removeTextFromEnd(S32 num_chars); @@ -241,8 +236,8 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor void setCommitOnFocusLost(BOOL b) { mCommitOnFocusLost = b; } // Hack to handle Notecards - virtual BOOL importBuffer(const char* buffer, S32 length ); - virtual BOOL exportBuffer(std::string& buffer ); + virtual BOOL importBuffer(const char* buffer, S32 length) { return false; } + virtual BOOL exportBuffer(std::string& buffer) { return false; } // If takes focus, will take keyboard focus on click. void setTakesFocus(BOOL b) { mTakesFocus = b; } @@ -254,8 +249,8 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor void setHandleEditKeysDirectly( BOOL b ) { mHandleEditKeysDirectly = b; } - // Callbacks - static void setLinkColor(LLColor4 color) { mLinkColor = color; } + // Use for when the link color needs to be changed to avoid looking awful + void setLinkColor(LLColor4* color) { if (mLinkColor) delete mLinkColor; mLinkColor = color; } void setOnScrollEndCallback(void (*callback)(void*), void* userdata); @@ -264,10 +259,12 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor LLSD getValue() const; const std::string& getText() const; - + + LLMenuGL* createUrlContextMenu(S32 x, S32 y, const std::string &url); // create a popup context menu for the given Url + // Non-undoable - void setText(const LLStringExplicit &utf8str); - void setWText(const LLWString &wtext); + void setText(const LLStringExplicit &utf8str, bool force_replace_links = true); + void setWText(const LLWString &wtext, bool force_replace_links = true); // Returns byte length limit S32 getMaxLength() const { return mMaxTextByteLength; } @@ -285,6 +282,7 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor llwchar getWChar(S32 pos) const { return mWText[pos]; } LLWString getWSubString(S32 pos, S32 len) const { return mWText.substr(pos, len); } + const LLTextSegment* getLastSegment() const { return mSegments.empty() ? nullptr : mSegments.back(); } const LLTextSegment* getCurrentSegment() const { return getSegmentAtOffset(mCursorPos); } const LLTextSegment* getPreviousSegment() const; void getSelectedSegments(std::vector& segments) const; @@ -299,17 +297,16 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor LLHandle mPopupMenuHandle; - S32 getLength() const { return mWText.length(); } void getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp ) const; void drawPreeditMarker(); public: + S32 getLength() const { return mWText.length(); } void updateLineStartList(S32 startpos = 0); protected: void updateScrollFromCursor(); void updateTextRect(); const LLRect& getTextRect() const { return mTextRect; } - void assignEmbedded(const std::string &s); BOOL truncate(); // Returns true if truncation occurs void removeCharOrTab(); @@ -365,9 +362,6 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; } virtual void bindEmbeddedChars(const LLFontGL* font) const {} virtual void unbindEmbeddedChars(const LLFontGL* font) const {} - - S32 findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const; - BOOL findHTML(const std::string &line, S32 *begin, S32 *end) const; // Abstract inner base class representing an undoable editor command. // Concrete sub-classes can be defined for operations such as insert, remove, etc. @@ -408,9 +402,10 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor S32 removeChar(S32 pos); void removeWord(bool prev); S32 insert(const S32 pos, const LLWString &wstr, const BOOL group_with_next_op); +public: S32 remove(const S32 pos, const S32 length, const BOOL group_with_next_op); - S32 append(const LLWString &wstr, const BOOL group_with_next_op); - +protected: + // Direct operations S32 insertStringNoUndo(S32 pos, const LLWString &wstr); // returns num of chars actually inserted S32 removeStringNoUndo(S32 pos, S32 length); @@ -455,9 +450,12 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor BOOL mParseHTML; BOOL mParseHighlights; - std::string mHTML; typedef std::vector segment_list_t; + + segment_list_t::iterator getSegIterContaining(S32 index); + segment_list_t::const_iterator getSegIterContaining(S32 index) const; + segment_list_t mSegments; LLTextSegmentPtr mHoverSegment; @@ -481,6 +479,8 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor void pasteHelper(bool is_primary); void onKeyStroke(); + void createDefaultSegment(); + void clearSegments(); void updateSegments(); void pruneSegments(); @@ -503,7 +503,7 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor // Data // LLKeywords mKeywords; - static LLColor4 mLinkColor; + LLColor4* mLinkColor; // Concrete LLTextCmd sub-classes used by the LLTextEditor base class class LLTextCmdInsert; @@ -559,7 +559,6 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor typedef std::vector line_list_t; //to keep track of what we have to remove before showing menu - std::vector suggestionMenuItems; S32 mLastContextMenuX; S32 mLastContextMenuY; @@ -616,6 +615,7 @@ class LLTextSegment : public LLRefCount LLTextSegment( const LLColor3& color, S32 start, S32 end ); S32 getStart() const { return mStart; } + void setStart(S32 start) { mStart = start; } S32 getEnd() const { return mEnd; } void setEnd( S32 end ) { mEnd = end; } const LLColor4& getColor() const { return mStyle->getColor(); } @@ -624,9 +624,12 @@ class LLTextSegment : public LLRefCount void setStyle(const LLStyleSP &style) { mStyle = style; } void setIsDefault(BOOL b) { mIsDefault = b; } BOOL getIsDefault() const { return mIsDefault; } + void setUnderlineOnHover(bool b) { mUnderlineOnHover = b; } + void underlineOnHover(bool hover) { if (mUnderlineOnHover) mStyle->mUnderline = hover; } void setToken( LLKeywordToken* token ) { mToken = token; } LLKeywordToken* getToken() const { return mToken; } BOOL getToolTip( std::string& msg ) const; + void setToolTip(const std::string& tooltip); void dump() const; @@ -644,6 +647,8 @@ class LLTextSegment : public LLRefCount S32 mEnd; LLKeywordToken* mToken; BOOL mIsDefault; + bool mUnderlineOnHover = false; + std::string mTooltip; }; diff --git a/indra/llui/lltrans.h b/indra/llui/lltrans.h index b997d69547..a5743660d9 100644 --- a/indra/llui/lltrans.h +++ b/indra/llui/lltrans.h @@ -34,6 +34,7 @@ #define LL_TRANS_H #include +#include /** * @brief String template loaded from strings.xml diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 42f617b217..f29dc3dcb1 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -158,8 +158,8 @@ void LLUI::cleanupClass() void LLUI::setMousePositionScreen(S32 x, S32 y) { S32 screen_x, screen_y; - screen_x = ll_round((F32)x * getScaleFactor().mV[VX]); - screen_y = ll_round((F32)y * getScaleFactor().mV[VY]); + screen_x = ll_pos_round((F32)x * getScaleFactor().mV[VX]); + screen_y = ll_pos_round((F32)y * getScaleFactor().mV[VY]); LLView::getWindow()->setCursorPosition(LLCoordGL(screen_x, screen_y).convert()); } @@ -170,8 +170,8 @@ void LLUI::getMousePositionScreen(S32 *x, S32 *y) LLCoordWindow cursor_pos_window; getWindow()->getCursorPosition(&cursor_pos_window); LLCoordGL cursor_pos_gl(cursor_pos_window.convert()); - *x = ll_round((F32)cursor_pos_gl.mX / getScaleFactor().mV[VX]); - *y = ll_round((F32)cursor_pos_gl.mY / getScaleFactor().mV[VX]); + *x = ll_pos_round((F32)cursor_pos_gl.mX / getScaleFactor().mV[VX]); + *y = ll_pos_round((F32)cursor_pos_gl.mY / getScaleFactor().mV[VX]); } //static @@ -223,32 +223,33 @@ std::string LLUI::getLanguage() //static std::string LLUI::locateSkin(const std::string& filename) { - std::string slash = gDirUtilp->getDirDelimiter(); std::string found_file = filename; - if (!gDirUtilp->fileExists(found_file)) + if (gDirUtilp->fileExists(found_file)) { - found_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); // Should be CUSTOM_SKINS? + return found_file; } - if (sConfigGroup && sConfigGroup->controlExists("Language")) + + found_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); // Should be CUSTOM_SKINS? + if (gDirUtilp->fileExists(found_file)) { - if (!gDirUtilp->fileExists(found_file)) - { - std::string localization = getLanguage(); - std::string local_skin = "xui" + slash + localization + slash + filename; - found_file = gDirUtilp->findSkinnedFilename(local_skin); - } + return found_file; } - if (!gDirUtilp->fileExists(found_file)) + + found_file = gDirUtilp->findSkinnedFilename(LLDir::XUI, filename); + if (! found_file.empty()) { - std::string local_skin = "xui" + slash + "en-us" + slash + filename; - found_file = gDirUtilp->findSkinnedFilename(local_skin); + return found_file; } - if (!gDirUtilp->fileExists(found_file)) + + found_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename); + if (gDirUtilp->fileExists(found_file)) { - found_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename); + return found_file; } - return found_file; -} + LL_WARNS("LLUI") << "Can't find '" << filename + << "' in user settings, any skin directory or app_settings" << LL_ENDL; + return ""; +} //static LLVector2 LLUI::getWindowSize() diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 0ccf748681..26acc25da7 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -38,6 +38,9 @@ static LLRegisterWidget r("ui_ctrl"); +F32 LLUICtrl::sActiveControlTransparency = 1.0f; +F32 LLUICtrl::sInactiveControlTransparency = 1.0f; + LLUICtrl::CallbackParam::CallbackParam() : name("name"), function_name("function"), @@ -94,25 +97,26 @@ const LLUICtrl::Params& LLUICtrl::getDefaultParams() LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel) : LLView(p), + mCommitSignal(nullptr), + mValidateSignal(nullptr), + mMouseEnterSignal(nullptr), + mMouseLeaveSignal(nullptr), + mMouseDownSignal(nullptr), + mMouseUpSignal(nullptr), + mRightMouseDownSignal(nullptr), + mRightMouseUpSignal(nullptr), + mDoubleClickSignal(nullptr), + mViewModel(viewmodel), + mEnabledControlVariable(nullptr), + mDisabledControlVariable(nullptr), + mMakeVisibleControlVariable(nullptr), + mMakeInvisibleControlVariable(nullptr), mIsChrome(FALSE), mRequestsFront(p.requests_front), mTabStop(TRUE), mTentative(FALSE), - mViewModel(viewmodel), - mEnabledControlVariable(NULL), - mDisabledControlVariable(NULL), - mMakeVisibleControlVariable(NULL), - mMakeInvisibleControlVariable(NULL), - mCommitSignal(NULL), - mValidateSignal(NULL), - mMouseEnterSignal(NULL), - mMouseLeaveSignal(NULL), - mMouseDownSignal(NULL), - mMouseUpSignal(NULL), - mRightMouseDownSignal(NULL), - mRightMouseUpSignal(NULL), - mDoubleClickSignal(NULL), - mCommitOnReturn(FALSE) + mCommitOnReturn(FALSE), + mTransparencyType(TT_DEFAULT) { } @@ -210,20 +214,21 @@ LLUICtrl::LLUICtrl(const std::string& name, const LLRect rect, BOOL mouse_opaque mTabStop( TRUE ), mTentative( FALSE ), mViewModel(LLViewModelPtr(new LLViewModel)), - mEnabledControlVariable(NULL), - mDisabledControlVariable(NULL), - mMakeVisibleControlVariable(NULL), - mMakeInvisibleControlVariable(NULL), - mCommitSignal(NULL), - mValidateSignal(NULL), - mMouseEnterSignal(NULL), - mMouseLeaveSignal(NULL), - mMouseDownSignal(NULL), - mMouseUpSignal(NULL), - mRightMouseDownSignal(NULL), - mRightMouseUpSignal(NULL), - mDoubleClickSignal(NULL), - mCommitOnReturn(FALSE) + mEnabledControlVariable(nullptr), + mDisabledControlVariable(nullptr), + mMakeVisibleControlVariable(nullptr), + mMakeInvisibleControlVariable(nullptr), + mCommitSignal(nullptr), + mValidateSignal(nullptr), + mMouseEnterSignal(nullptr), + mMouseLeaveSignal(nullptr), + mMouseDownSignal(nullptr), + mMouseUpSignal(nullptr), + mRightMouseDownSignal(nullptr), + mRightMouseUpSignal(nullptr), + mDoubleClickSignal(nullptr), + mCommitOnReturn(FALSE), + mTransparencyType(TT_DEFAULT) { if(commit_callback) setCommitCallback(commit_callback); @@ -338,6 +343,8 @@ BOOL LLUICtrl::handleMouseDown(S32 x, S32 y, MASK mask) { (*mMouseDownSignal)(this,x,y,mask); } + LL_DEBUGS() << "LLUICtrl::handleMousedown - handled is returning as: " << handled << " " << LL_ENDL; + return handled; } @@ -349,6 +356,7 @@ BOOL LLUICtrl::handleMouseUp(S32 x, S32 y, MASK mask) { (*mMouseUpSignal)(this,x,y,mask); } + return handled; } @@ -466,7 +474,7 @@ void LLUICtrl::setEnabledControlVariable(LLControlVariable* control) if (mEnabledControlVariable) { mEnabledControlConnection.disconnect(); // disconnect current signal - mEnabledControlVariable = NULL; + mEnabledControlVariable = nullptr; } if (control) { @@ -481,7 +489,7 @@ void LLUICtrl::setDisabledControlVariable(LLControlVariable* control) if (mDisabledControlVariable) { mDisabledControlConnection.disconnect(); // disconnect current signal - mDisabledControlVariable = NULL; + mDisabledControlVariable = nullptr; } if (control) { @@ -496,7 +504,7 @@ void LLUICtrl::setMakeVisibleControlVariable(LLControlVariable* control) if (mMakeVisibleControlVariable) { mMakeVisibleControlConnection.disconnect(); // disconnect current signal - mMakeVisibleControlVariable = NULL; + mMakeVisibleControlVariable = nullptr; } if (control) { @@ -511,7 +519,7 @@ void LLUICtrl::setMakeInvisibleControlVariable(LLControlVariable* control) if (mMakeInvisibleControlVariable) { mMakeInvisibleControlConnection.disconnect(); // disconnect current signal - mMakeInvisibleControlVariable = NULL; + mMakeInvisibleControlVariable = nullptr; } if (control) { @@ -526,7 +534,12 @@ bool LLUICtrl::controlListener(const LLSD& newvalue, LLHandle handle, LLUICtrl* ctrl = handle.get(); if (ctrl) { - if (type == "enabled") + if (type == "value") + { + ctrl->setValue(newvalue); + return true; + } + else if (type == "enabled") { ctrl->setEnabled(newvalue.asBoolean()); return true; @@ -565,19 +578,19 @@ BOOL LLUICtrl::setLabelArg( const std::string& key, const LLStringExplicit& text // virtual LLCtrlSelectionInterface* LLUICtrl::getSelectionInterface() { - return NULL; + return nullptr; } // virtual LLCtrlListInterface* LLUICtrl::getListInterface() { - return NULL; + return nullptr; } // virtual LLCtrlScrollInterface* LLUICtrl::getScrollInterface() { - return NULL; + return nullptr; } BOOL LLUICtrl::hasFocus() const @@ -603,7 +616,7 @@ void LLUICtrl::setFocus(BOOL b) { if( gFocusMgr.childHasKeyboardFocus(this)) { - gFocusMgr.setKeyboardFocus( NULL ); + gFocusMgr.setKeyboardFocus(nullptr ); } } } @@ -712,11 +725,11 @@ class LLUICtrl::DefaultTabGroupFirstSorter : public LLQuerySorter, public LLSing } }; -LLFastTimer::DeclareTimer FTM_FOCUS_FIRST_ITEM("Focus First Item"); +LLTrace::BlockTimerStatHandle FTM_FOCUS_FIRST_ITEM("Focus First Item"); BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields, BOOL focus_flash) { - LLFastTimer _(FTM_FOCUS_FIRST_ITEM); + LL_RECORD_BLOCK_TIME(FTM_FOCUS_FIRST_ITEM); // try to select default tab group child LLCtrlQuery query = getTabOrderQuery(); // sort things such that the default tab group is at the front @@ -1008,11 +1021,11 @@ LLUICtrl* LLUICtrl::getParentUICtrl() const } // *TODO: Deprecate; for backwards compatability only: -boost::signals2::connection LLUICtrl::setCommitCallback( boost::function cb, void* data) +boost::signals2::connection LLUICtrl::setCommitCallback( std::function cb, void* data) { return setCommitCallback( boost::bind(cb, _1, data)); } -boost::signals2::connection LLUICtrl::setValidateBeforeCommit( boost::function cb ) +boost::signals2::connection LLUICtrl::setValidateBeforeCommit( std::function cb ) { if (!mValidateSignal) mValidateSignal = new enable_signal_t(); return mValidateSignal->connect(boost::bind(cb, _2)); @@ -1030,7 +1043,6 @@ BOOL LLUICtrl::getTentative() const return mTentative; } - // virtual void LLUICtrl::setColor(const LLColor4& color) { } @@ -1047,6 +1059,37 @@ void LLUICtrl::setMinValue(LLSD min_value) void LLUICtrl::setMaxValue(LLSD max_value) { } +F32 LLUICtrl::getCurrentTransparency() +{ + F32 alpha = 0; + + switch(mTransparencyType) + { + case TT_DEFAULT: + alpha = getDrawContext().mAlpha; + break; + + case TT_ACTIVE: + alpha = sActiveControlTransparency; + break; + + case TT_INACTIVE: + alpha = sInactiveControlTransparency; + break; + + case TT_FADING: + alpha = sInactiveControlTransparency / 2.f; + break; + } + + return alpha; +} + +void LLUICtrl::setTransparencyType(ETypeTransparency type) +{ + mTransparencyType = type; +} + boost::signals2::connection LLUICtrl::setCommitCallback(const CommitCallbackParam& cb) { return setCommitCallback(initCommitCallback(cb)); diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index ca0e11d160..ff28f25195 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -34,16 +34,11 @@ #ifndef LL_LLUICTRL_H #define LL_LLUICTRL_H +//#include "llboost.h" #include "llrect.h" #include "llsd.h" #include "llregistry.h" -#ifndef BOOST_FUNCTION_HPP_INCLUDED -#include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif -#include - #include "llinitparam.h" #include "llview.h" #include "llviewmodel.h" // *TODO move dependency to .cpp file @@ -128,6 +123,13 @@ class LLUICtrl Params(); }; + enum ETypeTransparency + { + TT_DEFAULT, + TT_ACTIVE, // focused floater + TT_INACTIVE, // other floaters + TT_FADING, // fading toast + }; /*virtual*/ ~LLUICtrl(); void initFromParams(const Params& p); @@ -147,26 +149,26 @@ class LLUICtrl // We shouldn't ever need to set this directly //virtual void setViewModel(const LLViewModelPtr&); - virtual BOOL postBuild(); + BOOL postBuild() override; public: // LLView interface /*virtual*/ void initFromXML(LLXMLNodePtr node, LLView* parent); /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const; - /*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - /*virtual*/ BOOL isCtrl() const; - /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); - /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL canFocusChildren() const; - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ) override; + /*virtual*/ BOOL isCtrl() const override; + /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask) override; + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL canFocusChildren() const override; + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override; // From LLFocusableElement - /*virtual*/ void setFocus( BOOL b ); - /*virtual*/ BOOL hasFocus() const; + /*virtual*/ void setFocus( BOOL b ) override; + /*virtual*/ BOOL hasFocus() const override; // New virtuals @@ -207,11 +209,17 @@ class LLUICtrl // Clear any user-provided input (text in a text editor, checked checkbox, // selected radio button, etc.). Defaults to no-op. virtual void clear(); + virtual void setColor(const LLColor4& color); virtual void setAlpha(F32 alpha); virtual void setMinValue(LLSD min_value); virtual void setMaxValue(LLSD max_value); + F32 getCurrentTransparency(); + + void setTransparencyType(ETypeTransparency type); + ETypeTransparency getTransparencyType() const {return mTransparencyType;} + BOOL focusNextItem(BOOL text_entry_only); BOOL focusPrevItem(BOOL text_entry_only); virtual // Singu Note: focusFirstItem is overridden for our old chat ui to prevent focusing on topmost uictrls. @@ -248,8 +256,8 @@ class LLUICtrl boost::signals2::connection setDoubleClickCallback( const mouse_signal_t::slot_type& cb ); // *TODO: Deprecate; for backwards compatability only: - boost::signals2::connection setCommitCallback( boost::function cb, void* data); - boost::signals2::connection setValidateBeforeCommit( boost::function cb ); + boost::signals2::connection setCommitCallback( std::function cb, void* data); + boost::signals2::connection setValidateBeforeCommit( std::function cb ); static LLView* fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFactory* factory); @@ -266,9 +274,13 @@ class LLUICtrl template class CallbackRegistry : public LLRegistrySingleton {}; - class CommitCallbackRegistry : public CallbackRegistry{}; + class CommitCallbackRegistry : public CallbackRegistry + { + }; // the enable callback registry is also used for visiblity callbacks - class EnableCallbackRegistry : public CallbackRegistry{}; + class EnableCallbackRegistry : public CallbackRegistry + { + }; protected: @@ -297,6 +309,10 @@ class LLUICtrl boost::signals2::connection mMakeVisibleControlConnection; LLControlVariable* mMakeInvisibleControlVariable; boost::signals2::connection mMakeInvisibleControlConnection; + + static F32 sActiveControlTransparency; + static F32 sInactiveControlTransparency; + private: BOOL mIsChrome; @@ -304,6 +320,8 @@ class LLUICtrl BOOL mTabStop; BOOL mTentative; + ETypeTransparency mTransparencyType; + bool mCommitOnReturn; class DefaultTabGroupFirstSorter; diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index e980ecec20..d753b40e1a 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -71,9 +71,9 @@ #include "lluiimage.h" #include "llviewborder.h" -LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION("Widget Construction"); -LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS("Widget InitFromParams"); -LLFastTimer::DeclareTimer FTM_WIDGET_SETUP("Widget Setup"); +LLTrace::BlockTimerStatHandle FTM_WIDGET_CONSTRUCTION("Widget Construction"); +LLTrace::BlockTimerStatHandle FTM_INIT_FROM_PARAMS("Widget InitFromParams"); +LLTrace::BlockTimerStatHandle FTM_WIDGET_SETUP("Widget Setup"); const char XML_HEADER[] = "\n"; @@ -174,7 +174,7 @@ const std::vector& LLUICtrlFactory::getXUIPaths() //----------------------------------------------------------------------------- bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root) { - std::string full_filename = gDirUtilp->findSkinnedFilename(sXUIPaths.front(), xui_filename); + std::string full_filename = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, xui_filename); if (full_filename.empty()) { // try filename as passed in since sometimes we load an xml file from a user-supplied path @@ -194,29 +194,21 @@ bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNo LL_WARNS() << "Problem reading UI description file: " << full_filename << LL_ENDL; return false; } + + std::vector paths = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, xui_filename); - LLXMLNodePtr updateRoot; - - std::vector::const_iterator itor; - - for (itor = sXUIPaths.begin(), ++itor; itor != sXUIPaths.end(); ++itor) + for ( auto& layer_filename : paths ) { - std::string nodeName; - std::string updateName; - - std::string layer_filename = gDirUtilp->findSkinnedFilename((*itor), xui_filename); - if(layer_filename.empty()) - { - // no localized version of this file, that's ok, keep looking - continue; - } - + LLXMLNodePtr updateRoot; if (!LLXMLNode::parseFile(layer_filename, updateRoot, NULL)) { - LL_WARNS() << "Problem reading localized UI description file: " << (*itor) + gDirUtilp->getDirDelimiter() + xui_filename << LL_ENDL; + LL_WARNS() << "Problem reading localized UI description file: " << layer_filename << LL_ENDL; return false; } + std::string updateName; + std::string nodeName; updateRoot->getAttributeString("name", updateName); root->getAttributeString("name", nodeName); @@ -414,19 +406,19 @@ LLMenuGL *LLUICtrlFactory::buildMenu(const std::string &filename, LLView* parent LLXMLNodePtr root; LLMenuGL* menu; - if (!LLUICtrlFactory::getLayeredXMLNode(filename, root)) + if (!getLayeredXMLNode(filename, root)) { - return NULL; + return nullptr; } // root must be called panel - if( !root->hasName( "menu_bar" ) && !root->hasName( "menu" )) + if (!root->hasName("menu_bar") && !root->hasName("menu") && !root->hasName("context_menu")) { - LL_WARNS() << "Root node should be named menu bar or menu in : " << filename << LL_ENDL; - return NULL; + LL_WARNS() << "Root node should be named menu bar or menu in: " << filename << LL_ENDL; + return nullptr; } - if (root->hasName("menu")) + if (root->hasName("menu") || root->hasName("context_menu")) { menu = (LLMenuGL*)LLMenuGL::fromXML(root, parentp, this); } @@ -504,7 +496,7 @@ void LLUICtrlFactory::rebuild() panelp->setFocus(FALSE); panelp->deleteAllChildren(); - buildPanel(panelp, filename.c_str(), &panelp->getFactoryMap()); + buildPanel(panelp, filename, &panelp->getFactoryMap()); panelp->setVisible(visible); } diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 970d7c0b01..ee6abb8267 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -43,9 +43,9 @@ class LLView; -extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP; -extern LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION; -extern LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS; +extern LLTrace::BlockTimerStatHandle FTM_WIDGET_SETUP; +extern LLTrace::BlockTimerStatHandle FTM_WIDGET_CONSTRUCTION; +extern LLTrace::BlockTimerStatHandle FTM_INIT_FROM_PARAMS; // Build time optimization, generate this once in .cpp file #ifndef LLUICTRLFACTORY_CPP @@ -161,10 +161,10 @@ class LLUICtrlFactory : public LLSingleton //return NULL; } - { LLFastTimer _(FTM_WIDGET_CONSTRUCTION); + { LL_RECORD_BLOCK_TIME(FTM_WIDGET_CONSTRUCTION); widget = new T(params); } - { LLFastTimer _(FTM_INIT_FROM_PARAMS); + { LL_RECORD_BLOCK_TIME(FTM_INIT_FROM_PARAMS); widget->initFromParams(params); } diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp index 0332765f1d..74b1da1b5c 100644 --- a/indra/llui/lluistring.cpp +++ b/indra/llui/lluistring.cpp @@ -32,10 +32,11 @@ #include "linden_common.h" #include "lluistring.h" +#include "llfasttimer.h" #include "llsd.h" #include "lltrans.h" -LLFastTimer::DeclareTimer FTM_UI_STRING("UI String"); +LLTrace::BlockTimerStatHandle FTM_UI_STRING("UI String"); LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args) @@ -60,7 +61,7 @@ void LLUIString::setArgList(const LLStringUtil::format_map_t& args) void LLUIString::setArgs(const LLSD& sd) { - LLFastTimer timer(FTM_UI_STRING); + LL_RECORD_BLOCK_TIME(FTM_UI_STRING); if (!sd.isMap()) return; for(LLSD::map_const_iterator sd_it = sd.beginMap(); @@ -123,7 +124,7 @@ void LLUIString::updateResult() const { mNeedsResult = false; - LLFastTimer timer(FTM_UI_STRING); + LL_RECORD_BLOCK_TIME(FTM_UI_STRING); // optimize for empty strings (don't attempt string replacement) if (mOrig.empty()) diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index fd9b3d9a6d..74ce67e88c 100644 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com /** * @file llurlaction.cpp * @author Martin Reddy @@ -24,7 +26,6 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - #include "linden_common.h" #include "llurlaction.h" @@ -32,6 +33,7 @@ #include "llwindow.h" #include "llurlregistry.h" + // global state for the callback functions LLUrlAction::url_callback_t LLUrlAction::sOpenURLCallback; LLUrlAction::url_callback_t LLUrlAction::sOpenURLInternalCallback; @@ -83,18 +85,19 @@ void LLUrlAction::openURLExternal(std::string url) } } -void LLUrlAction::executeSLURL(std::string url) +bool LLUrlAction::executeSLURL(std::string url, bool trusted_content) { if (sExecuteSLURLCallback) { - sExecuteSLURLCallback(url); + return sExecuteSLURLCallback(url, trusted_content); } + return false; } -void LLUrlAction::clickAction(std::string url) +void LLUrlAction::clickAction(std::string url, bool trusted_content) { // Try to handle as SLURL first, then http Url - if ( (sExecuteSLURLCallback) && !sExecuteSLURLCallback(url) ) + if ( (sExecuteSLURLCallback) && !sExecuteSLURLCallback(url, trusted_content) ) { if (sOpenURLCallback) { @@ -157,3 +160,86 @@ void LLUrlAction::showProfile(std::string url) } } } + +std::string LLUrlAction::getUserID(std::string url) +{ + LLURI uri(url); + LLSD path_array = uri.pathArray(); + std::string id_str; + if (path_array.size() == 4) + { + id_str = path_array.get(2).asString(); + } + return id_str; +} + +std::string LLUrlAction::getObjectId(std::string url) +{ + LLURI uri(url); + LLSD path_array = uri.pathArray(); + std::string id_str; + if (path_array.size() >= 3) + { + id_str = path_array.get(2).asString(); + } + return id_str; +} + +std::string LLUrlAction::getObjectName(std::string url) +{ + LLURI uri(url); + LLSD query_map = uri.queryMap(); + std::string name; + if (query_map.has("name")) + { + name = query_map["name"].asString(); + } + return name; +} + +void LLUrlAction::sendIM(std::string url) +{ + std::string id_str = getUserID(url); + if (LLUUID::validate(id_str)) + { + executeSLURL("secondlife:///app/agent/" + id_str + "/im"); + } +} + +void LLUrlAction::addFriend(std::string url) +{ + std::string id_str = getUserID(url); + if (LLUUID::validate(id_str)) + { + executeSLURL("secondlife:///app/agent/" + id_str + "/requestfriend"); + } +} + +void LLUrlAction::removeFriend(std::string url) +{ + std::string id_str = getUserID(url); + if (LLUUID::validate(id_str)) + { + executeSLURL("secondlife:///app/agent/" + id_str + "/removefriend"); + } +} + +void LLUrlAction::blockObject(std::string url) +{ + std::string object_id = getObjectId(url); + std::string object_name = getObjectName(url); + if (LLUUID::validate(object_id)) + { + executeSLURL("secondlife:///app/agent/" + object_id + "/block/" + LLURI::escape(object_name)); + } +} + +void LLUrlAction::unblockObject(std::string url) +{ + std::string object_id = getObjectId(url); + std::string object_name = getObjectName(url); + if (LLUUID::validate(object_id)) + { + executeSLURL("secondlife:///app/agent/" + object_id + "/unblock/" + object_name); + } +} diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index 0747829b77..51ab8261b8 100644 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -28,11 +28,7 @@ #ifndef LL_LLURLACTION_H #define LL_LLURLACTION_H -#include -#ifndef BOOST_FUNCTION_HPP_INCLUDED -#include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif +#include /// /// The LLUrlAction class provides a number of static functions that @@ -60,7 +56,7 @@ class LLUrlAction static void openURLExternal(std::string url); /// execute the given secondlife: SLURL - static void executeSLURL(std::string url); + static bool executeSLURL(std::string url, bool trusted_content = true); /// if the Url specifies an SL location, teleport there static void teleportToLocation(std::string url); @@ -69,7 +65,7 @@ class LLUrlAction static void showLocationOnMap(std::string url); /// perform the appropriate action for left-clicking on a Url - static void clickAction(std::string url); + static void clickAction(std::string url, bool trusted_content); /// copy the label for a Url to the clipboard static void copyLabelToClipboard(std::string url); @@ -79,10 +75,18 @@ class LLUrlAction /// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile static void showProfile(std::string url); + static std::string getUserID(std::string url); + static std::string getObjectName(std::string url); + static std::string getObjectId(std::string url); + static void sendIM(std::string url); + static void addFriend(std::string url); + static void removeFriend(std::string url); + static void blockObject(std::string url); + static void unblockObject(std::string url); /// specify the callbacks to enable this class's functionality - typedef boost::function url_callback_t; - typedef boost::function execute_url_callback_t; + typedef std::function url_callback_t; + typedef std::function execute_url_callback_t; static void setOpenURLCallback(url_callback_t cb); static void setOpenURLInternalCallback(url_callback_t cb); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 54dc1819c8..a68f4df9f3 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -31,21 +31,28 @@ #include "lluri.h" #include "llurlmatch.h" #include "llurlregistry.h" +#include "lluriparser.h" #include "llavatarnamecache.h" #include "llcachename.h" #include "lltrans.h" //#include "lluicolortable.h" #include "message.h" +#include "llexperiencecache.h" -#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))" +#include +#include // + +#define APP_HEADER_REGEX "((((x-grid-info://)|(x-grid-location-info://))[-\\w\\.]+(:\\d+)?/app)|(secondlife:///app))" +#define X_GRID_OR_SECONDLIFE_HEADER_REGEX "((((x-grid-info://)|(x-grid-location-info://))[-\\w\\.]+(:\\d+)?/)|(secondlife://))" // Utility functions std::string localize_slapp_label(const std::string& url, const std::string& full_name); LLUrlEntryBase::LLUrlEntryBase() -{} +{ +} LLUrlEntryBase::~LLUrlEntryBase() { @@ -62,14 +69,13 @@ std::string LLUrlEntryBase::getIcon(const std::string &url) return mIcon; } -/*LLStyle::Params LLUrlEntryBase::getStyle() const +LLStyleSP LLUrlEntryBase::getStyle() const { - LLStyle::Params style_params; - style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); - style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); - style_params.font.style = "UNDERLINE"; + static const LLUICachedControl color("HTMLLinkColor"); + LLStyleSP style_params(new LLStyle(true, color, LLStringUtil::null)); + //style_params->mUnderline = true; // Singu Note: We're not gonna bother here, underlining on hover return style_params; -}*/ +} std::string LLUrlEntryBase::getIDStringFromUrl(const std::string &url) const @@ -111,14 +117,14 @@ std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url) const { // return the label part from [http://www.example.org Label] const char *text = url.c_str(); - S32 start = 0; + size_t start = 0; while (! isspace(text[start])) { - start++; + ++start; } while (text[start] == ' ' || text[start] == '\t') { - start++; + ++start; } return unescapeUrl(url.substr(start, url.size()-start-1)); } @@ -127,10 +133,10 @@ std::string LLUrlEntryBase::getUrlFromWikiLink(const std::string &string) const { // return the url part from [http://www.example.org Label] const char *text = string.c_str(); - S32 end = 0; + size_t end = 0; while (! isspace(text[end])) { - end++; + ++end; } return escapeUrl(string.substr(1, end-1)); } @@ -142,11 +148,14 @@ void LLUrlEntryBase::addObserver(const std::string &id, // add a callback to be notified when we have a label for the uuid LLUrlEntryObserver observer; observer.url = url; - observer.signal = new LLUrlLabelSignal(); - if (observer.signal) + try { + observer.signal = new LLUrlLabelSignal(); observer.signal->connect(cb); - mObservers.insert(std::pair(id, observer)); + mObservers.emplace(id, observer); + } + catch (...) + { } } @@ -178,13 +187,50 @@ bool LLUrlEntryBase::isLinkDisabled() const return globally_disabled; } -static std::string getStringAfterToken(const std::string str, const std::string token) +bool LLUrlEntryBase::isWikiLinkCorrect(const std::string& url) { - size_t pos = str.find(token); + LLWString label = utf8str_to_wstring(getLabelFromWikiLink(url)); + label.erase(std::remove(label.begin(), label.end(), L'\u200B'), label.end()); + return (LLUrlRegistry::instance().hasUrl(wstring_to_utf8str(label))) ? false : true; +} + +std::string LLUrlEntryBase::urlToLabelWithGreyQuery(const std::string &url) const +{ + LLUriParser up(unescapeUrl(url)); + up.normalize(); + + std::string label; + up.extractParts(); + up.glueFirst(label); + + return label; +} + +std::string LLUrlEntryBase::urlToGreyQuery(const std::string &url) const +{ + LLUriParser up(unescapeUrl(url)); + + std::string label; + up.extractParts(); + up.glueFirst(label, false); + + size_t pos = url.find(label); if (pos == std::string::npos) { return ""; } + pos += label.size(); + return url.substr(pos); +} + + +static std::string getStringAfterToken(const std::string& str, const std::string& token) +{ + size_t pos = str.find(token); + if (pos == std::string::npos) + { + return LLStringUtil::null; + } pos += token.size(); return str.substr(pos, str.size() - pos); @@ -194,8 +240,9 @@ static std::string getStringAfterToken(const std::string str, const std::string // LLUrlEntryHTTP Describes generic http: and https: Urls // LLUrlEntryHTTP::LLUrlEntryHTTP() + : LLUrlEntryBase() { - mPattern = boost::regex("https?://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*", + mPattern = boost::regex("https?://([^\\s/?\\.#]+\\.?)+\\.\\w+(:\\d+)?(/\\S*)?", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_http.xml"; mTooltip = LLTrans::getString("TooltipHttpUrl"); @@ -206,13 +253,27 @@ std::string LLUrlEntryHTTP::getLabel(const std::string &url, const LLUrlLabelCal return unescapeUrl(url); } +std::string LLUrlEntryHTTP::getUrl(const std::string &string) const +{ + if (string.find("://") == std::string::npos) + { + return "http://" + escapeUrl(string); + } + return escapeUrl(string); +} + +std::string LLUrlEntryHTTP::getTooltip(const std::string &url) const +{ + return mTooltip;; +} + // // LLUrlEntryHTTP Describes generic http: and https: Urls with custom label // We use the wikipedia syntax of [http://www.example.org Text] // LLUrlEntryHTTPLabel::LLUrlEntryHTTPLabel() { - mPattern = boost::regex("\\[https?://\\S+[ \t]+[^\\]]+\\]", + mPattern = boost::regex("\\[(https?://\\S+|\\S+\\.([^\\s<]*)?)[ \t]+[^\\]]+\\]", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_http.xml"; mTooltip = LLTrans::getString("TooltipHttpUrl"); @@ -231,27 +292,32 @@ std::string LLUrlEntryHTTPLabel::getTooltip(const std::string &string) const std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string) const { - return getUrlFromWikiLink(string); + auto url = getUrlFromWikiLink(string); + if (!boost::istarts_with(url, "http")) + return "http://" + url; + return url; } // // LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com // LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol() + : LLUrlEntryBase() { - mPattern = boost::regex("(" - "\\bwww\\.\\S+\\.\\S+" // i.e. www.FOO.BAR - "|" // or - "(?]+\\.(?:com|net|edu|org)([/:][^[:space:]<]*)?\\b" // i.e. FOO.net - ")", - boost::regex::perl|boost::regex::icase); + mPattern = boost::regex("\\bwww\\.\\S+\\.([^\\s<]*)?\\b", // i.e. www.FOO.BAR + boost::regex::perl | boost::regex::icase); mMenuName = "menu_url_http.xml"; mTooltip = LLTrans::getString("TooltipHttpUrl"); } std::string LLUrlEntryHTTPNoProtocol::getLabel(const std::string &url, const LLUrlLabelCallback &cb) { - return unescapeUrl(url); + return urlToLabelWithGreyQuery(url); +} + +std::string LLUrlEntryHTTPNoProtocol::getQuery(const std::string &url) const +{ + return urlToGreyQuery(url); } std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string) const @@ -263,14 +329,104 @@ std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string) const return escapeUrl(string); } +std::string LLUrlEntryHTTPNoProtocol::getTooltip(const std::string &url) const +{ + return unescapeUrl(url); +} + +LLUrlEntryInvalidSLURL::LLUrlEntryInvalidSLURL() + : LLUrlEntryBase() +{ + mPattern = boost::regex("(https?://(maps.secondlife.com|slurl.com)/secondlife/|secondlife://(/app/(worldmap|teleport)/)?)[^ /]+(/-?[0-9]+){1,3}(/?(\\?\\S*)?)?", + boost::regex::perl|boost::regex::icase); + mMenuName = "menu_url_http.xml"; + mTooltip = LLTrans::getString("TooltipHttpUrl"); +} + +std::string LLUrlEntryInvalidSLURL::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + + return escapeUrl(url); +} + +std::string LLUrlEntryInvalidSLURL::getUrl(const std::string &string) const +{ + return escapeUrl(string); +} + +std::string LLUrlEntryInvalidSLURL::getTooltip(const std::string &url) const +{ + return unescapeUrl(url); +} + +bool LLUrlEntryInvalidSLURL::isSLURLvalid(const std::string &url) const +{ + S32 actual_parts; + + if(url.find(".com/secondlife/") != std::string::npos) + { + actual_parts = 5; + } + else if(url.find("/app/") != std::string::npos) + { + actual_parts = 6; + } + else + { + actual_parts = 3; + } + + LLURI uri(url); + LLSD path_array = uri.pathArray(); + S32 path_parts = path_array.size(); + S32 x,y,z; + + if (path_parts == actual_parts) + { + // handle slurl with (X,Y,Z) coordinates + LLStringUtil::convertToS32(path_array[path_parts-3].asString(),x); + LLStringUtil::convertToS32(path_array[path_parts-2].asString(),y); + LLStringUtil::convertToS32(path_array[path_parts-1].asString(),z); + + if((x>= 0 && x<= 256) && (y>= 0 && y<= 256) && (z>= 0)) + { + return TRUE; + } + } + else if (path_parts == (actual_parts-1)) + { + // handle slurl with (X,Y) coordinates + + LLStringUtil::convertToS32(path_array[path_parts-2].asString(),x); + LLStringUtil::convertToS32(path_array[path_parts-1].asString(),y); + ; + if((x>= 0 && x<= 256) && (y>= 0 && y<= 256)) + { + return TRUE; + } + } + else if (path_parts == (actual_parts-2)) + { + // handle slurl with (X) coordinate + LLStringUtil::convertToS32(path_array[path_parts-1].asString(),x); + if(x>= 0 && x<= 256) + { + return TRUE; + } + } + + return FALSE; +} + // // LLUrlEntrySLURL Describes generic http: and https: Urls // LLUrlEntrySLURL::LLUrlEntrySLURL() { // see http://slurl.com/about.php for details on the SLURL format - mPattern = boost::regex("http://(maps.secondlife.com|slurl.com)/secondlife/[^ /]+(/\\d+){0,3}(/?(\\?title|\\?img|\\?msg)=\\S*)?/?", + mPattern = boost::regex("https?://(maps.secondlife.com|slurl.com)/secondlife/[^ /]+(/\\d+){0,3}(/?(\\?\\S*)?)?", boost::regex::perl|boost::regex::icase); + mIcon = "Hand"; mMenuName = "menu_url_slurl.xml"; mTooltip = LLTrans::getString("TooltipSLURL"); } @@ -284,6 +440,7 @@ std::string LLUrlEntrySLURL::getLabel(const std::string &url, const LLUrlLabelCa // - http://slurl.com/secondlife/Place/X // - http://slurl.com/secondlife/Place // + LLURI uri(url); LLSD path_array = uri.pathArray(); S32 path_parts = path_array.size(); @@ -335,13 +492,62 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const return url.substr(pos, url.size() - pos); } +// +// LLUrlEntrySeconlifeURL Describes *secondlife.com/ and *lindenlab.com/ urls to substitute icon 'hand.png' before link +// +LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL() +{ + mPattern = boost::regex("\\b(https?://)?([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?(/\\S*)?", + boost::regex::perl|boost::regex::icase); + + mIcon = "Hand"; + mMenuName = "menu_url_http.xml"; + mTooltip = LLTrans::getString("TooltipHttpUrl"); +} + +/// Return the url from a string that matched the regex +std::string LLUrlEntrySecondlifeURL::getUrl(const std::string &string) const +{ + if (string.find("://") == std::string::npos) + { + return "https://" + escapeUrl(string); + } + return escapeUrl(string); +} + +std::string LLUrlEntrySecondlifeURL::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + return urlToLabelWithGreyQuery(url); +} + +std::string LLUrlEntrySecondlifeURL::getQuery(const std::string &url) const +{ + return urlToGreyQuery(url); +} + +std::string LLUrlEntrySecondlifeURL::getTooltip(const std::string &url) const +{ + return url; +} + +// +// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com and *lindenlab.com urls to substitute icon 'hand.png' before link +// +LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL() + { + mPattern = boost::regex("(https?://)?([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(?!\\S)", + boost::regex::perl|boost::regex::icase); + + mIcon = "Hand"; + mMenuName = "menu_url_http.xml"; +} + // // LLUrlEntryAgent Describes a Second Life agent Url, e.g., // secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about -// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about +// x-grid-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about // -LLUrlEntryAgent::LLUrlEntryAgent() : - mAvatarNameCacheConnection() +LLUrlEntryAgent::LLUrlEntryAgent() { mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/\\w+", boost::regex::perl|boost::regex::icase); @@ -372,9 +578,17 @@ void LLUrlEntryAgent::callObservers(const std::string &id, void LLUrlEntryAgent::onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name) { - mAvatarNameCacheConnection.disconnect(); + auto range = mAvatarNameCacheConnections.equal_range(id); + for (auto it = range.first; it != range.second; ++it) + { + if (it->second.connected()) + { + it->second.disconnect(); + } + } + mAvatarNameCacheConnections.erase(range.first, range.second); - std::string label = av_name.getCompleteName(); + std::string label = av_name.getNSName(); // received the agent name from the server - tell our observers callObservers(id.asString(), label, mIcon); @@ -429,10 +643,11 @@ bool LLUrlEntryAgent::underlineOnHoverOnly(const std::string &string) const std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb) { + static std::string name_wait_str = LLTrans::getString("LoadingData"); if (!gCacheName) { // probably at the login screen, use short string for layout - return LLTrans::getString("LoadingData"); + return name_wait_str; } std::string agent_id_string = getIDStringFromUrl(url); @@ -451,7 +666,7 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa LLAvatarName av_name; if (LLAvatarNameCache::get(agent_id, &av_name)) { - std::string label = av_name.getCompleteName(); + std::string label = av_name.getNSName(); // handle suffixes like /mute or /offerteleport label = localize_slapp_label(url, label); @@ -459,23 +674,19 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa } else { - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgent::onAvatarNameCache, this, _1, _2)); + auto connection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgent::onAvatarNameCache, this, _1, _2)); + mAvatarNameCacheConnections.emplace(agent_id, connection); addObserver(agent_id_string, url, cb); - return LLTrans::getString("LoadingData"); + return name_wait_str; } } -/*LLStyle::Params LLUrlEntryAgent::getStyle() const +LLStyleSP LLUrlEntryAgent::getStyle() const { - LLStyle::Params style_params = LLUrlEntryBase::getStyle(); - style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); - style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); + static const LLUICachedControl color("HTMLAgentColor"); + LLStyleSP style_params(new LLStyle(true, color, LLStringUtil::null)); return style_params; -}*/ +} std::string localize_slapp_label(const std::string& url, const std::string& full_name) { @@ -522,16 +733,25 @@ std::string LLUrlEntryAgent::getIcon(const std::string &url) // // LLUrlEntryAgentName describes a Second Life agent name Url, e.g., // secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username) -// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username) +// x-grid-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username) // -LLUrlEntryAgentName::LLUrlEntryAgentName() : - mAvatarNameCacheConnection() -{} +LLUrlEntryAgentName::LLUrlEntryAgentName() +{ + mMenuName = "menu_url_agent.xml"; +} void LLUrlEntryAgentName::onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name) { - mAvatarNameCacheConnection.disconnect(); + auto range = mAvatarNameCacheConnections.equal_range(id); + for (auto it = range.first; it != range.second; ++it) + { + if (it->second.connected()) + { + it->second.disconnect(); + } + } + mAvatarNameCacheConnections.erase(range.first, range.second); std::string label = getName(av_name); // received the agent name from the server - tell our observers @@ -540,10 +760,11 @@ void LLUrlEntryAgentName::onAvatarNameCache(const LLUUID& id, std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLabelCallback &cb) { + static std::string name_wait_str = LLTrans::getString("LoadingData"); if (!gCacheName) { // probably at the login screen, use short string for layout - return LLTrans::getString("LoadingData"); + return name_wait_str; } std::string agent_id_string = getIDStringFromUrl(url); @@ -566,26 +787,24 @@ std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLab } else { - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgentName::onAvatarNameCache, this, _1, _2)); + auto connection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgentName::onAvatarNameCache, this, _1, _2)); + mAvatarNameCacheConnections.emplace(agent_id, connection); addObserver(agent_id_string, url, cb); - return LLTrans::getString("LoadingData"); + return name_wait_str; } } -/*LLStyle::Params LLUrlEntryAgentName::getStyle() const +LLStyleSP LLUrlEntryAgentName::getStyle() const { - // don't override default colors - return LLStyle::Params().is_link(false); -}*/ + static const LLUICachedControl color("HTMLAgentColor"); + LLStyleSP style_params(new LLStyle(true, color, LLStringUtil::null)); + return style_params; +} // // LLUrlEntryAgentCompleteName describes a Second Life agent complete name Url, e.g., // secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename -// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename +// x-grid-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename // LLUrlEntryAgentCompleteName::LLUrlEntryAgentCompleteName() { @@ -598,10 +817,26 @@ std::string LLUrlEntryAgentCompleteName::getName(const LLAvatarName& avatar_name return avatar_name.getCompleteName(); } +// +// LLUrlEntryAgentLegacyName describes a Second Life agent legacy name Url, e.g., +// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/legacyname +// x-grid-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/legacyname +// +LLUrlEntryAgentLegacyName::LLUrlEntryAgentLegacyName() +{ + mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/legacyname", + boost::regex::perl|boost::regex::icase); +} + +std::string LLUrlEntryAgentLegacyName::getName(const LLAvatarName& avatar_name) +{ + return avatar_name.getLegacyName(); +} + // // LLUrlEntryAgentDisplayName describes a Second Life agent display name Url, e.g., // secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname -// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname +// x-grid-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname // LLUrlEntryAgentDisplayName::LLUrlEntryAgentDisplayName() { @@ -617,7 +852,7 @@ std::string LLUrlEntryAgentDisplayName::getName(const LLAvatarName& avatar_name) // // LLUrlEntryAgentUserName describes a Second Life agent user name Url, e.g., // secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username -// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username +// x-grid-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username // LLUrlEntryAgentUserName::LLUrlEntryAgentUserName() { @@ -634,7 +869,7 @@ std::string LLUrlEntryAgentUserName::getName(const LLAvatarName& avatar_name) // LLUrlEntryGroup Describes a Second Life group Url, e.g., // secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about // secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect -// x-grid-location-info://lincoln.lindenlab.com/app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect +// x-grid-info://lincoln.lindenlab.com/app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect // LLUrlEntryGroup::LLUrlEntryGroup() { @@ -696,13 +931,12 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa } } -/*LLStyle::Params LLUrlEntryGroup::getStyle() const +LLStyleSP LLUrlEntryGroup::getStyle() const { - LLStyle::Params style_params = LLUrlEntryBase::getStyle(); - style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); - style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); + LLStyleSP style_params = LLUrlEntryBase::getStyle(); + //style_params->mUnderline = false; // Singu Note: We're not gonna bother here, underlining on hover return style_params; -}*/ +} // @@ -714,7 +948,7 @@ LLUrlEntryInventory::LLUrlEntryInventory() //*TODO: add supporting of inventory item names with whitespaces //this pattern cann't parse for example //secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select?name=name with spaces¶m2=value - //x-grid-location-info://lincoln.lindenlab.com/app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select?name=name with spaces¶m2=value + //x-grid-info://lincoln.lindenlab.com/app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select?name=name with spaces¶m2=value mPattern = boost::regex(APP_HEADER_REGEX "/inventory/[\\da-f-]+/\\w+\\S*", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_inventory.xml"; @@ -732,7 +966,7 @@ std::string LLUrlEntryInventory::getLabel(const std::string &url, const LLUrlLab // LLUrlEntryObjectIM::LLUrlEntryObjectIM() { - mPattern = boost::regex("secondlife:///app/objectim/[\\da-f-]+\?.*", + mPattern = boost::regex(APP_HEADER_REGEX "/objectim/[\\da-f-]+\?\\S*\\w", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_objectim.xml"; } @@ -765,7 +999,7 @@ std::set LLUrlEntryParcel::sParcelInfoObservers; /// /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g., /// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about -/// x-grid-location-info://lincoln.lindenlab.com/app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about +/// x-grid-info://lincoln.lindenlab.com/app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about /// LLUrlEntryParcel::LLUrlEntryParcel() { @@ -843,11 +1077,8 @@ void LLUrlEntryParcel::processParcelInfo(const LLParcelData& parcel_data) parcel_data.sim_name.c_str(), region_x, region_y, region_z); } - for (std::set::iterator iter = sParcelInfoObservers.begin(); - iter != sParcelInfoObservers.end(); - ++iter) + for (auto url_entry : sParcelInfoObservers) { - LLUrlEntryParcel* url_entry = *iter; if (url_entry) { url_entry->onParcelInfoReceived(parcel_data.parcel_id.asString(), label); @@ -860,7 +1091,7 @@ void LLUrlEntryParcel::processParcelInfo(const LLParcelData& parcel_data) // LLUrlEntryPlace::LLUrlEntryPlace() { - mPattern = boost::regex("((x-grid-location-info://[-\\w\\.]+/region/)|(secondlife://))\\S+/?(\\d+/\\d+/\\d+|\\d+/\\d+)/?", + mPattern = boost::regex("((((x-grid-info://)|(x-grid-location-info://))[-\\w\\.]+(:\\d+)?/region/)|(secondlife://))\\S+/?(\\d+/\\d+/\\d+|\\d+/\\d+)/?", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_slurl.xml"; mTooltip = LLTrans::getString("TooltipSLURL"); @@ -892,6 +1123,15 @@ std::string LLUrlEntryPlace::getLabel(const std::string &url, const LLUrlLabelCa std::string y = path_array[1]; return location + " (" + x + "," + y + ")"; } + else if (path_parts > 3) // xgrid, show as grid: place(x, y, z) + { + auto place = unescapeUrl(path_array[1].asStringRef()); + const auto& x = path_array[2].asStringRef(); + const auto& y = path_array[3].asStringRef(); + location += ": " + place + " (" + x + ',' + y; + if (path_parts == 5) location += ',' + path_array[4].asStringRef(); + return location + ')'; + } return url; } @@ -899,6 +1139,12 @@ std::string LLUrlEntryPlace::getLabel(const std::string &url, const LLUrlLabelCa std::string LLUrlEntryPlace::getLocation(const std::string &url) const { // return the part of the Url after secondlife:// part + const auto uri = LLURI(url); + bool xgrid = boost::algorithm::starts_with(uri.scheme(), "x-grid"); + if (xgrid) + { + return ::getStringAfterToken(url, "region/"); + } return ::getStringAfterToken(url, "://"); } @@ -908,7 +1154,7 @@ std::string LLUrlEntryPlace::getLocation(const std::string &url) const // LLUrlEntryRegion::LLUrlEntryRegion() { - mPattern = boost::regex("secondlife:///app/region/[^/\\s]+(/\\d+)?(/\\d+)?(/\\d+)?/?", + mPattern = boost::regex(X_GRID_OR_SECONDLIFE_HEADER_REGEX"//app/region/[^/\\s]+(/\\d+)?(/\\d+)?(/\\d+)?/?", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_slurl.xml"; mTooltip = LLTrans::getString("TooltipSLURL"); @@ -924,30 +1170,37 @@ std::string LLUrlEntryRegion::getLabel(const std::string &url, const LLUrlLabelC // - secondlife:///app/region/Place // - LLSD path_array = LLURI(url).pathArray(); + const auto uri = LLURI(url); + LLSD path_array = uri.pathArray(); S32 path_parts = path_array.size(); - if (path_parts < 3) // no region name + bool xgrid = boost::algorithm::starts_with(uri.scheme(), "x-grid"); + auto i = xgrid ? 3 : 2; + + if (path_parts < i+1) // no region name { LL_WARNS() << "Failed to parse url [" << url << "]" << LL_ENDL; return url; } - std::string label = unescapeUrl(path_array[2]); // region name + std::string label = + xgrid ? unescapeUrl(path_array[0].asStringRef()) + ": " + unescapeUrl(path_array[i].asStringRef()) : // grid and region name + unescapeUrl(path_array[i].asStringRef()); // region name - if (path_parts > 3) // secondlife:///app/region/Place/X + ++i; + if (path_parts > i+1) // secondlife:///app/region/Place/X { - std::string x = path_array[3]; + std::string x = path_array[i++]; label += " (" + x; - if (path_parts > 4) // secondlife:///app/region/Place/X/Y + if (path_parts > i+1) // secondlife:///app/region/Place/X/Y { - std::string y = path_array[4]; + std::string y = path_array[i++]; label += "," + y; - if (path_parts > 5) // secondlife:///app/region/Place/X/Y/Z + if (path_parts > i+1) // secondlife:///app/region/Place/X/Y/Z { - std::string z = path_array[5]; + std::string z = path_array[i]; label = label + "," + z; } } @@ -960,15 +1213,17 @@ std::string LLUrlEntryRegion::getLabel(const std::string &url, const LLUrlLabelC std::string LLUrlEntryRegion::getLocation(const std::string &url) const { - LLSD path_array = LLURI(url).pathArray(); - std::string region_name = unescapeUrl(path_array[2]); + const auto uri = LLURI(url); + LLSD path_array = uri.pathArray(); + bool xgrid = boost::algorithm::starts_with(uri.scheme(), "x-grid"); + std::string region_name = unescapeUrl(path_array[xgrid ? 3 : 2]); return region_name; } // // LLUrlEntryTeleport Describes a Second Life teleport Url, e.g., // secondlife:///app/teleport/Ahern/50/50/50/ -// x-grid-location-info://lincoln.lindenlab.com/app/teleport/Ahern/50/50/50/ +// x-grid-info://lincoln.lindenlab.com/app/teleport/Ahern/50/50/50/ // LLUrlEntryTeleport::LLUrlEntryTeleport() { @@ -1042,7 +1297,7 @@ std::string LLUrlEntryTeleport::getLocation(const std::string &url) const // LLUrlEntrySL::LLUrlEntrySL() { - mPattern = boost::regex("secondlife://(\\w+)?(:\\d+)?/\\S+", + mPattern = boost::regex(X_GRID_OR_SECONDLIFE_HEADER_REGEX "(\\w+)?(:\\d+)?/\\S+", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_slapp.xml"; mTooltip = LLTrans::getString("TooltipSLAPP"); @@ -1059,7 +1314,7 @@ std::string LLUrlEntrySL::getLabel(const std::string &url, const LLUrlLabelCallb // LLUrlEntrySLLabel::LLUrlEntrySLLabel() { - mPattern = boost::regex("\\[secondlife://\\S+[ \t]+[^\\]]+\\]", + mPattern = boost::regex("\\[" X_GRID_OR_SECONDLIFE_HEADER_REGEX "\\S+[ \t]+[^\\]]+\\]", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_slapp.xml"; mTooltip = LLTrans::getString("TooltipSLAPP"); @@ -1164,11 +1419,13 @@ std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelC return getUrl(url); } -/*LLStyle::Params LLUrlEntryNoLink::getStyle() const +LLStyleSP LLUrlEntryNoLink::getStyle() const { // Don't render as URL (i.e. no context menu or hand cursor). - return LLStyle::Params().is_link(false); -}*/ + LLStyleSP style(new LLStyle()); + style->setLinkHREF(" "); + return style; +} // @@ -1201,3 +1458,126 @@ std::string LLUrlEntryIcon::getIcon(const std::string &url) LLStringUtil::trim(mIcon); return mIcon; } + +// +// LLUrlEntryEmail Describes a generic mailto: Urls +// +LLUrlEntryEmail::LLUrlEntryEmail() + : LLUrlEntryBase() +{ + mPattern = boost::regex("(mailto:)?[\\w\\.\\-]+@[\\w\\.\\-]+\\.[a-z]{2,63}", + boost::regex::perl | boost::regex::icase); + mMenuName = "menu_url_email.xml"; + mTooltip = LLTrans::getString("TooltipEmail"); +} + +std::string LLUrlEntryEmail::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + size_t pos = url.find("mailto:"); + + if (pos == std::string::npos) + { + return escapeUrl(url); + } + + std::string ret = escapeUrl(url.substr(pos + 7, url.length() - pos + 8)); + return ret; +} + +std::string LLUrlEntryEmail::getUrl(const std::string &string) const +{ + if (string.find("mailto:") == std::string::npos) + { + return "mailto:" + escapeUrl(string); + } + return escapeUrl(string); +} + +LLUrlEntryExperienceProfile::LLUrlEntryExperienceProfile() +{ + mPattern = boost::regex(APP_HEADER_REGEX "/experience/[\\da-f-]+/\\w+\\S*", + boost::regex::perl|boost::regex::icase); + mIcon = "Generic_Experience"; + mMenuName = "menu_url_experience.xml"; +} + +std::string LLUrlEntryExperienceProfile::getLabel(const std::string& url, const LLUrlLabelCallback& cb) +{ + if (!gCacheName) + { + // probably at the login screen, use short string for layout + return LLTrans::getString("LoadingData"); + } + + std::string experience_id_string = getIDStringFromUrl(url); + if (experience_id_string.empty()) + { + // something went wrong, just give raw url + return unescapeUrl(url); + } + + LLUUID experience_id(experience_id_string); + if (experience_id.isNull()) + { + return LLTrans::getString("ExperienceNameNull"); + } + + const LLSD& experience_details = LLExperienceCache::instance().get(experience_id); + if (!experience_details.isUndefined()) + { + std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString(); + return experience_name_string.empty() ? LLTrans::getString("ExperienceNameUntitled") : experience_name_string; + } + + addObserver(experience_id_string, url, cb); + LLExperienceCache::instance().get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); + return LLTrans::getString("LoadingData"); + +} + +void LLUrlEntryExperienceProfile::onExperienceDetails(const LLSD& experience_details) +{ + std::string name = experience_details[LLExperienceCache::NAME].asString(); + if(name.empty()) + { + name = LLTrans::getString("ExperienceNameUntitled"); + } + callObservers(experience_details[LLExperienceCache::EXPERIENCE_ID].asString(), name, LLStringUtil::null); +} + +// +// +// LLUrlEntryJIRA describes a Jira Issue Tracker entry +// +LLUrlEntryJira::LLUrlEntryJira() +{ + mPattern = boost::regex("(\\b(?:ALCH|SV|BUG|CHOP|FIRE|MAINT|OPEN|SCR|STORM|SVC|VWR|WEB)-\\d+)", + boost::regex::perl); + mMenuName = "menu_url_http.xml"; + mTooltip = LLTrans::getString("TooltipHttpUrl"); +} + +std::string LLUrlEntryJira::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + return unescapeUrl(url); +} + +std::string LLUrlEntryJira::getTooltip(const std::string &string) const +{ + return getUrl(string); +} + +std::string LLUrlEntryJira::getUrl(const std::string &url) const +{ + return (boost::format( + (url.find("ALCH") != std::string::npos) ? + "http://alchemy.atlassian.net/browse/%1%" : + (url.find("SV") != std::string::npos) ? + "https://singularityviewer.atlassian.net/browse/%1%" : + (url.find("FIRE") != std::string::npos) ? + "https://jira.firestormviewer.com/browse/%1%" : + "http://jira.secondlife.com/browse/%1%" + ) % url).str(); +} +// + diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index e52fe8040f..6c382aa26d 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -35,10 +35,7 @@ #include "llavatarname.h" #include "llhost.h" // for resolving parcel name by parcel id -#include #include -#include -#include class LLAvatarName; @@ -78,11 +75,14 @@ class LLUrlEntryBase /// Given a matched Url, return a label for the Url virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; } + /// Return port, query and fragment parts for the Url + virtual std::string getQuery(const std::string &url) const { return ""; } + /// Return an icon that can be displayed next to Urls of this type virtual std::string getIcon(const std::string &url); /// Return the style to render the displayed text - //virtual LLStyle::Params getStyle() const; + virtual LLStyleSP getStyle() const; /// Given a matched Url, return a tooltip string for the hyperlink virtual std::string getTooltip(const std::string &string) const { return mTooltip; } @@ -96,10 +96,16 @@ class LLUrlEntryBase /// Should this link text be underlined only when mouse is hovered over it? virtual bool underlineOnHoverOnly(const std::string &string) const { return true; } // + virtual bool isTrusted() const { return false; } + virtual LLUUID getID(const std::string &string) const { return LLUUID::null; } bool isLinkDisabled() const; + bool isWikiLinkCorrect(const std::string& url); + + virtual bool isSLURLvalid(const std::string &url) const { return TRUE; }; + protected: std::string getIDStringFromUrl(const std::string &url) const; std::string escapeUrl(const std::string &url) const; @@ -107,6 +113,8 @@ class LLUrlEntryBase std::string getLabelFromWikiLink(const std::string &url) const; std::string getUrlFromWikiLink(const std::string &string) const; void addObserver(const std::string &id, const std::string &url, const LLUrlLabelCallback &cb); + std::string urlToLabelWithGreyQuery(const std::string &url) const; + std::string urlToGreyQuery(const std::string &url) const; virtual void callObservers(const std::string &id, const std::string &label, const std::string& icon); typedef struct { @@ -124,45 +132,83 @@ class LLUrlEntryBase /// /// LLUrlEntryHTTP Describes generic http: and https: Urls /// -class LLUrlEntryHTTP : public LLUrlEntryBase +class LLUrlEntryHTTP final : public LLUrlEntryBase { public: LLUrlEntryHTTP(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getUrl(const std::string &string) const override; + /*virtual*/ std::string getTooltip(const std::string &url) const override; }; /// /// LLUrlEntryHTTPLabel Describes generic http: and https: Urls with custom labels /// -class LLUrlEntryHTTPLabel : public LLUrlEntryBase +class LLUrlEntryHTTPLabel final : public LLUrlEntryBase { public: LLUrlEntryHTTPLabel(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getTooltip(const std::string &string) const; - /*virtual*/ std::string getUrl(const std::string &string) const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getTooltip(const std::string &string) const override; + /*virtual*/ std::string getUrl(const std::string &string) const override; }; /// /// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com /// -class LLUrlEntryHTTPNoProtocol : public LLUrlEntryBase +class LLUrlEntryHTTPNoProtocol final : public LLUrlEntryBase { public: LLUrlEntryHTTPNoProtocol(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getUrl(const std::string &string) const; + std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + std::string getQuery(const std::string &url) const override; + std::string getUrl(const std::string &string) const override; + std::string getTooltip(const std::string &url) const override; +}; + +class LLUrlEntryInvalidSLURL final : public LLUrlEntryBase +{ +public: + LLUrlEntryInvalidSLURL(); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getUrl(const std::string &string) const override; + /*virtual*/ std::string getTooltip(const std::string &url) const override; + + bool isSLURLvalid(const std::string &url) const override; }; /// /// LLUrlEntrySLURL Describes http://slurl.com/... Urls /// -class LLUrlEntrySLURL : public LLUrlEntryBase +class LLUrlEntrySLURL final : public LLUrlEntryBase { public: LLUrlEntrySLURL(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getLocation(const std::string &url) const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getLocation(const std::string &url) const override; +}; + +/// +/// LLUrlEntrySeconlifeURLs Describes *secondlife.com and *lindenlab.com Urls +/// +class LLUrlEntrySecondlifeURL : public LLUrlEntryBase +{ +public: + LLUrlEntrySecondlifeURL(); + /*virtual*/ bool isTrusted() const override { return true; } + /*virtual*/ std::string getUrl(const std::string &string) const override; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getQuery(const std::string &url) const override; + /*virtual*/ std::string getTooltip(const std::string &url) const override; +}; + +/// +/// LLUrlEntrySeconlifeURLs Describes *secondlife.com and *lindenlab.com Urls +/// +class LLUrlEntrySimpleSecondlifeURL final : public LLUrlEntrySecondlifeURL +{ +public: + LLUrlEntrySimpleSecondlifeURL(); }; /// @@ -174,22 +220,27 @@ class LLUrlEntryAgent : public LLUrlEntryBase LLUrlEntryAgent(); ~LLUrlEntryAgent() { - if (mAvatarNameCacheConnection.connected()) + for(const auto& conn_pair : mAvatarNameCacheConnections) { - mAvatarNameCacheConnection.disconnect(); + if (conn_pair.second.connected()) + { + conn_pair.second.disconnect(); + } } + mAvatarNameCacheConnections.clear(); } - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getIcon(const std::string &url); - /*virtual*/ std::string getTooltip(const std::string &string) const; - //*virtual*/ LLStyle::Params getStyle() const; - /*virtual*/ LLUUID getID(const std::string &string) const; - /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getIcon(const std::string &url) override; + /*virtual*/ std::string getTooltip(const std::string &string) const override; + /*virtual*/ LLStyleSP getStyle() const override; + /*virtual*/ LLUUID getID(const std::string &string) const override; + /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const override; protected: - /*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon); + /*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon) override; private: void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name); - boost::signals2::connection mAvatarNameCacheConnection; + using avatar_name_cache_connection_map_t = std::multimap; + avatar_name_cache_connection_map_t mAvatarNameCacheConnections; }; /// @@ -203,19 +254,25 @@ class LLUrlEntryAgentName : public LLUrlEntryBase, public boost::signals2::track LLUrlEntryAgentName(); ~LLUrlEntryAgentName() { - if (mAvatarNameCacheConnection.connected()) + for (const auto& conn_pair : mAvatarNameCacheConnections) { - mAvatarNameCacheConnection.disconnect(); + if (conn_pair.second.connected()) + { + conn_pair.second.disconnect(); + } } + mAvatarNameCacheConnections.clear(); + } - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - //*virtual*/ LLStyle::Params getStyle() const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ LLStyleSP getStyle() const override; protected: // override this to pull out relevant name fields virtual std::string getName(const LLAvatarName& avatar_name) = 0; private: void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name); - boost::signals2::connection mAvatarNameCacheConnection; + using avatar_name_cache_connection_map_t = std::multimap; + avatar_name_cache_connection_map_t mAvatarNameCacheConnections; }; @@ -224,12 +281,20 @@ class LLUrlEntryAgentName : public LLUrlEntryBase, public boost::signals2::track /// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename /// that displays the full display name + user name for an avatar /// such as "James Linden (james.linden)" -class LLUrlEntryAgentCompleteName : public LLUrlEntryAgentName +class LLUrlEntryAgentCompleteName final : public LLUrlEntryAgentName { public: LLUrlEntryAgentCompleteName(); private: - /*virtual*/ std::string getName(const LLAvatarName& avatar_name); + /*virtual*/ std::string getName(const LLAvatarName& avatar_name) override; +}; + +class LLUrlEntryAgentLegacyName final : public LLUrlEntryAgentName +{ +public: + LLUrlEntryAgentLegacyName(); +private: + /*virtual*/ std::string getName(const LLAvatarName& avatar_name) override; }; /// @@ -237,12 +302,12 @@ class LLUrlEntryAgentCompleteName : public LLUrlEntryAgentName /// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname /// that displays the just the display name for an avatar /// such as "James Linden" -class LLUrlEntryAgentDisplayName : public LLUrlEntryAgentName +class LLUrlEntryAgentDisplayName final : public LLUrlEntryAgentName { public: LLUrlEntryAgentDisplayName(); private: - /*virtual*/ std::string getName(const LLAvatarName& avatar_name); + /*virtual*/ std::string getName(const LLAvatarName& avatar_name) override; }; /// @@ -250,25 +315,39 @@ class LLUrlEntryAgentDisplayName : public LLUrlEntryAgentName /// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username /// that displays the just the display name for an avatar /// such as "james.linden" -class LLUrlEntryAgentUserName : public LLUrlEntryAgentName +class LLUrlEntryAgentUserName final : public LLUrlEntryAgentName { public: LLUrlEntryAgentUserName(); private: - /*virtual*/ std::string getName(const LLAvatarName& avatar_name); + /*virtual*/ std::string getName(const LLAvatarName& avatar_name) override; +}; + +/// +/// LLUrlEntryExperienceProfile Describes a Second Life experience profile Url, e.g., +/// secondlife:///app/experience/0e346d8b-4433-4d66-a6b0-fd37083abc4c/profile +/// that displays the experience name +class LLUrlEntryExperienceProfile final : public LLUrlEntryBase +{ +public: + LLUrlEntryExperienceProfile(); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; +private: + void onExperienceDetails(const LLSD& experience_details); }; + /// /// LLUrlEntryGroup Describes a Second Life group Url, e.g., /// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about /// -class LLUrlEntryGroup : public LLUrlEntryBase +class LLUrlEntryGroup final : public LLUrlEntryBase { public: LLUrlEntryGroup(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - //*virtual*/ LLStyle::Params getStyle() const; - /*virtual*/ LLUUID getID(const std::string &string) const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ LLStyleSP getStyle() const override; + /*virtual*/ LLUUID getID(const std::string &string) const override; private: void onGroupNameReceived(const LLUUID& id, const std::string& name, bool is_group); }; @@ -277,11 +356,11 @@ class LLUrlEntryGroup : public LLUrlEntryBase /// LLUrlEntryInventory Describes a Second Life inventory Url, e.g., /// secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select /// -class LLUrlEntryInventory : public LLUrlEntryBase +class LLUrlEntryInventory final : public LLUrlEntryBase { public: LLUrlEntryInventory(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; private: }; @@ -289,12 +368,12 @@ class LLUrlEntryInventory : public LLUrlEntryBase /// LLUrlEntryObjectIM Describes a Second Life inspector for the object Url, e.g., /// secondlife:///app/objectim/7bcd7864-da6b-e43f-4486-91d28a28d95b?name=Object&owner=3de548e1-57be-cfea-2b78-83ae3ad95998&slurl=Danger!%20Danger!/200/200/30/&groupowned=1 /// -class LLUrlEntryObjectIM : public LLUrlEntryBase +class LLUrlEntryObjectIM final : public LLUrlEntryBase { public: LLUrlEntryObjectIM(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getLocation(const std::string &url) const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getLocation(const std::string &url) const override; private: }; @@ -302,7 +381,7 @@ class LLUrlEntryObjectIM : public LLUrlEntryBase /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g., /// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about /// -class LLUrlEntryParcel : public LLUrlEntryBase +class LLUrlEntryParcel final : public LLUrlEntryBase { public: struct LLParcelData @@ -317,7 +396,7 @@ class LLUrlEntryParcel : public LLUrlEntryBase LLUrlEntryParcel(); ~LLUrlEntryParcel(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; // Sends a parcel info request to sim. void sendParcelInfoRequest(const LLUUID& parcel_id); @@ -349,98 +428,123 @@ class LLUrlEntryParcel : public LLUrlEntryBase /// LLUrlEntryPlace Describes a Second Life location Url, e.g., /// secondlife://Ahern/50/50/50 /// -class LLUrlEntryPlace : public LLUrlEntryBase +class LLUrlEntryPlace final : public LLUrlEntryBase { public: LLUrlEntryPlace(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getLocation(const std::string &url) const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getLocation(const std::string &url) const override; }; /// /// LLUrlEntryRegion Describes a Second Life location Url, e.g., /// secondlife:///app/region/Ahern/128/128/0 /// -class LLUrlEntryRegion : public LLUrlEntryBase +class LLUrlEntryRegion final : public LLUrlEntryBase { public: LLUrlEntryRegion(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getLocation(const std::string &url) const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getLocation(const std::string &url) const override; }; /// /// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g., /// secondlife:///app/teleport/Ahern/50/50/50/ /// -class LLUrlEntryTeleport : public LLUrlEntryBase +class LLUrlEntryTeleport final : public LLUrlEntryBase { public: LLUrlEntryTeleport(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getLocation(const std::string &url) const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getLocation(const std::string &url) const override; }; /// /// LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts /// with secondlife:// (used as a catch-all for cases not matched above) /// -class LLUrlEntrySL : public LLUrlEntryBase +class LLUrlEntrySL final : public LLUrlEntryBase { public: LLUrlEntrySL(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; }; /// /// LLUrlEntrySLLabel Describes a generic SLURL, e.g., a Url that starts /// with secondlife:// with the ability to specify a custom label. /// -class LLUrlEntrySLLabel : public LLUrlEntryBase +class LLUrlEntrySLLabel final : public LLUrlEntryBase { public: LLUrlEntrySLLabel(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getUrl(const std::string &string) const; - /*virtual*/ std::string getTooltip(const std::string &string) const; - /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getUrl(const std::string &string) const override; + /*virtual*/ std::string getTooltip(const std::string &string) const override; + /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const override; }; /// /// LLUrlEntryWorldMap Describes a Second Life worldmap Url, e.g., /// secondlife:///app/worldmap/Ahern/50/50/50 /// -class LLUrlEntryWorldMap : public LLUrlEntryBase +class LLUrlEntryWorldMap final : public LLUrlEntryBase { public: LLUrlEntryWorldMap(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getLocation(const std::string &url) const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getLocation(const std::string &url) const override; }; /// /// LLUrlEntryNoLink lets us turn of URL detection with ... tags /// -class LLUrlEntryNoLink : public LLUrlEntryBase +class LLUrlEntryNoLink final : public LLUrlEntryBase { public: LLUrlEntryNoLink(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getUrl(const std::string &string) const; - //*virtual*/ LLStyle::Params getStyle() const; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getUrl(const std::string &string) const override; + /*virtual*/ LLStyleSP getStyle() const override; }; /// /// LLUrlEntryIcon describes an icon with ... tags /// -class LLUrlEntryIcon : public LLUrlEntryBase +class LLUrlEntryIcon final : public LLUrlEntryBase { public: LLUrlEntryIcon(); - /*virtual*/ std::string getUrl(const std::string &string) const; - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getIcon(const std::string &url); + /*virtual*/ std::string getUrl(const std::string &string) const override; + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getIcon(const std::string &url) override; }; +/// +/// LLUrlEntryEmail Describes a generic mailto: Urls +/// +class LLUrlEntryEmail final : public LLUrlEntryBase +{ +public: + LLUrlEntryEmail(); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getUrl(const std::string &string) const override; +}; + +// +/// +/// LLUrlEntryJira describes a Jira Issue +/// +class LLUrlEntryJira final : public LLUrlEntryBase +{ +public: + LLUrlEntryJira(); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override; + /*virtual*/ std::string getTooltip(const std::string &string) const override; + /*virtual*/ std::string getUrl(const std::string &string) const override; + +}; +// #endif diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp index af4955ac4e..240e04ef0a 100644 --- a/indra/llui/llurlmatch.cpp +++ b/indra/llui/llurlmatch.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com /** * @file llurlmatch.cpp * @author Martin Reddy @@ -37,26 +39,29 @@ LLUrlMatch::LLUrlMatch() : mIcon(""), mMenuName(""), mLocation(""), - mUnderlineOnHoverOnly(false) + mUnderlineOnHoverOnly(false), + mTrusted(false) { } -void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url, - const std::string &label, const std::string &tooltip, - const std::string &icon, /*const LLStyle::Params& style,*/ +void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url, const std::string &label, + const std::string& query, const std::string &tooltip, + const std::string &icon, const LLStyleSP& style, const std::string &menu, const std::string &location, - const LLUUID& id, bool underline_on_hover_only) + const LLUUID& id, bool underline_on_hover_only, bool trusted) { mStart = start; mEnd = end; mUrl = url; mLabel = label; + mQuery = query; mTooltip = tooltip; mIcon = icon; - //mStyle = style; - //mStyle.link_href = url; + mStyle = style; + mStyle->setLinkHREF(mStyle->isLink() ? LLStringUtil::null : url); // Singu Note: This hack exists in lieu of no link flag mMenuName = menu; mLocation = location; mID = id; mUnderlineOnHoverOnly = underline_on_hover_only; + mTrusted = trusted; } diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h index af36e69255..fc0b505ecb 100644 --- a/indra/llui/llurlmatch.h +++ b/indra/llui/llurlmatch.h @@ -30,8 +30,6 @@ //#include "linden_common.h" -#include -#include #include "llstyle.h" /// @@ -62,6 +60,9 @@ class LLUrlMatch /// return a label that can be used for the display of this Url std::string getLabel() const { return mLabel; } + /// return a right part of url which should be drawn in grey + std::string getQuery() const { return mQuery; } + /// return a message that could be displayed in a tooltip or status bar std::string getTooltip() const { return mTooltip; } @@ -69,7 +70,7 @@ class LLUrlMatch std::string getIcon() const { return mIcon; } /// Return the color to render the displayed text - //LLStyle::Params getStyle() const { return mStyle; } + LLStyleSP getStyle() const { return mStyle; } /// Return the name of a XUI file containing the context menu items std::string getMenuName() const { return mMenuName; } @@ -80,12 +81,15 @@ class LLUrlMatch /// Should this link text be underlined only when mouse is hovered over it? bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; } + /// Return true if Url is trusted. + bool isTrusted() const { return mTrusted; } + /// Change the contents of this match object (used by LLUrlRegistry) void setValues(U32 start, U32 end, const std::string &url, const std::string &label, - const std::string &tooltip, const std::string &icon, - /*const LLStyle::Params& style, */const std::string &menu, + const std::string& query, const std::string &tooltip, const std::string &icon, + const LLStyleSP& style, const std::string &menu, const std::string &location, const LLUUID& id, - bool underline_on_hover_only = false ); + bool underline_on_hover_only = false, bool trusted = false); const LLUUID& getID() const { return mID; } private: @@ -93,13 +97,15 @@ class LLUrlMatch U32 mEnd; std::string mUrl; std::string mLabel; + std::string mQuery; std::string mTooltip; std::string mIcon; std::string mMenuName; std::string mLocation; LLUUID mID; - //LLStyle::Params mStyle; + LLStyleSP mStyle; bool mUnderlineOnHoverOnly; + bool mTrusted; }; #endif diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 235b002d0d..c7dba05e4b 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com /** * @file llurlregistry.cpp * @author Martin Reddy @@ -27,6 +29,7 @@ #include "linden_common.h" #include "llurlregistry.h" +#include "lluriparser.h" #include @@ -37,15 +40,26 @@ void LLUrlRegistryNullCallback(const std::string &url, const std::string &label, LLUrlRegistry::LLUrlRegistry() { - mUrlEntry.reserve(20); + mUrlEntry.reserve(23); // // Urls are matched in the order that they were registered registerUrl(new LLUrlEntryNoLink()); - registerUrl(new LLUrlEntryIcon()); + mUrlEntryIcon = new LLUrlEntryIcon(); + registerUrl(mUrlEntryIcon); + mLLUrlEntryInvalidSLURL = new LLUrlEntryInvalidSLURL(); + registerUrl(mLLUrlEntryInvalidSLURL); registerUrl(new LLUrlEntrySLURL()); + + // decorated links for host names like: secondlife.com and lindenlab.com + mUrlEntryTrusted = new LLUrlEntrySecondlifeURL(); + registerUrl(mUrlEntryTrusted); + registerUrl(new LLUrlEntrySimpleSecondlifeURL()); + registerUrl(new LLUrlEntryHTTP()); - registerUrl(new LLUrlEntryHTTPLabel()); + mUrlEntryHTTPLabel = new LLUrlEntryHTTPLabel(); + registerUrl(mUrlEntryHTTPLabel); registerUrl(new LLUrlEntryAgentCompleteName()); + registerUrl(new LLUrlEntryAgentLegacyName()); registerUrl(new LLUrlEntryAgentDisplayName()); registerUrl(new LLUrlEntryAgentUserName()); // LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since @@ -59,14 +73,18 @@ LLUrlRegistry::LLUrlRegistry() registerUrl(new LLUrlEntryObjectIM()); registerUrl(new LLUrlEntryPlace()); registerUrl(new LLUrlEntryInventory()); - registerUrl(new LLUrlEntryObjectIM()); + registerUrl(new LLUrlEntryExperienceProfile()); //LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern, //so it should be registered in the end of list registerUrl(new LLUrlEntrySL()); - registerUrl(new LLUrlEntrySLLabel()); - // most common pattern is a URL without any protocol, - // e.g., "secondlife.com" - registerUrl(new LLUrlEntryHTTPNoProtocol()); + mUrlEntrySLLabel = new LLUrlEntrySLLabel(); + registerUrl(mUrlEntrySLLabel); + registerUrl(new LLUrlEntryEmail()); + // Parse teh jiras! + registerUrl(new LLUrlEntryJira()); // + // most common pattern is a URL without any protocol starting with "www", + // e.g., "www.secondlife.com" + registerUrl(new LLUrlEntryHTTPNoProtocol()); } LLUrlRegistry::~LLUrlRegistry() @@ -90,7 +108,7 @@ void LLUrlRegistry::registerUrl(LLUrlEntryBase *url, bool force_front) } } -static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &end) +static bool matchRegex(const char *text, const boost::regex& regex, U32 &start, U32 &end) { boost::cmatch result; bool found; @@ -100,7 +118,7 @@ static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &en { found = boost::regex_search(text, result, regex); } - catch (std::runtime_error &) + catch (const std::runtime_error &) { return false; } @@ -127,6 +145,11 @@ static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &en end--; } + else if (text[end] == ']' && std::string(text+start, end-start).find('[') == std::string::npos) + { + end--; + } + return true; } @@ -142,32 +165,77 @@ static bool stringHasUrl(const std::string &text) text.find(".edu") != std::string::npos || text.find(".org") != std::string::npos || text.find("") != std::string::npos || - text.find(" +static bool stringHasJira(const std::string &text) +{ + // fast heuristic test for a URL in a string. This is used + // to avoid lots of costly regex calls, BUT it needs to be + // kept in sync with the LLUrlEntry regexes we support. + return (text.find("ALCH") != std::string::npos || + text.find("SV") != std::string::npos || + text.find("BUG") != std::string::npos || + text.find("CHOP") != std::string::npos || + text.find("FIRE") != std::string::npos || + text.find("MAINT") != std::string::npos || + text.find("OPEN") != std::string::npos || + text.find("SCR") != std::string::npos || + text.find("STORM") != std::string::npos || + text.find("SVC") != std::string::npos || + text.find("VWR") != std::string::npos || + text.find("WEB") != std::string::npos); } +// -bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb) +bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted) { // avoid costly regexes if there is clearly no URL in the text - if (! stringHasUrl(text)) + if (!(stringHasUrl(text) || stringHasJira(text))) // { return false; } // find the first matching regex from all url entries in the registry U32 match_start = 0, match_end = 0; - LLUrlEntryBase *match_entry = NULL; + LLUrlEntryBase *match_entry = nullptr; std::vector::iterator it; for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it) { + //Skip for url entry icon if content is not trusted + if(!is_content_trusted && (mUrlEntryIcon == *it)) + { + continue; + } + LLUrlEntryBase *url_entry = *it; U32 start = 0, end = 0; if (matchRegex(text.c_str(), url_entry->getPattern(), start, end)) { // does this match occur in the string before any other match - if (start < match_start || match_entry == NULL) + if (start < match_start || match_entry == nullptr) { + + if (mLLUrlEntryInvalidSLURL == *it) + { + if(url_entry && url_entry->isSLURLvalid(text.substr(start, end - start + 1))) + { + continue; + } + } + + if((mUrlEntryHTTPLabel == *it) || (mUrlEntrySLLabel == *it)) + { + if(url_entry && !url_entry->isWikiLinkCorrect(text.substr(start, end - start + 1))) + { + continue; + } + } + match_start = start; match_end = end; match_entry = url_entry; @@ -178,18 +246,32 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL // did we find a match? if so, return its details in the match object if (match_entry) { + // Skip if link is an email with an empty username (starting with @). See MAINT-5371. + if (match_start > 0 && text.substr(match_start - 1, 1) == "@") + return false; + // fill in the LLUrlMatch object and return it std::string url = text.substr(match_start, match_end - match_start + 1); + + if (match_entry == mUrlEntryTrusted) + { + LLUriParser up(url); + up.normalize(); + url = up.normalizedUri(); + } + match.setValues(match_start, match_end, match_entry->getUrl(url), match_entry->getLabel(url, cb), + match_entry->getQuery(url), match_entry->getTooltip(url), match_entry->getIcon(url), - //match_entry->getStyle(), + match_entry->getStyle(), match_entry->getMenuName(), match_entry->getLocation(url), match_entry->getID(url), - match_entry->underlineOnHoverOnly(url)); + match_entry->underlineOnHoverOnly(url), + match_entry->isTrusted()); return true; } @@ -209,7 +291,7 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr // character encoding, so we need to update the start // and end values to be correct for the wide string. LLWString wurl = utf8str_to_wstring(match.getUrl()); - S32 start = text.find(wurl); + size_t start = text.find(wurl); if (start == std::string::npos) { return false; @@ -218,9 +300,10 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr match.setValues(start, end, match.getUrl(), match.getLabel(), + match.getQuery(), match.getTooltip(), match.getIcon(), - //match.getStyle(), + match.getStyle(), match.getMenuName(), match.getLocation(), match.getID(), diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index da16171a97..90099c6d1a 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -33,9 +33,6 @@ #include "llsingleton.h" #include "llstring.h" -#include -#include - /// This default callback for findUrl() simply ignores any label updates void LLUrlRegistryNullCallback(const std::string &url, const std::string &label, @@ -73,7 +70,8 @@ class LLUrlRegistry : public LLSingleton /// get the next Url in an input string, starting at a given character offset /// your callback is invoked if the matched Url's label changes in the future bool findUrl(const std::string &text, LLUrlMatch &match, - const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback); + const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback, + bool is_content_trusted = false); /// a slightly less efficient version of findUrl for wide strings bool findUrl(const LLWString &text, LLUrlMatch &match, @@ -92,6 +90,11 @@ class LLUrlRegistry : public LLSingleton friend class LLSingleton; std::vector mUrlEntry; + LLUrlEntryBase* mUrlEntryTrusted; + LLUrlEntryBase* mUrlEntryIcon; + LLUrlEntryBase* mLLUrlEntryInvalidSLURL; + LLUrlEntryBase* mUrlEntryHTTPLabel; + LLUrlEntryBase* mUrlEntrySLLabel; }; #endif diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index d7a11ad00a..78602df941 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -38,7 +38,6 @@ #include #include -#include #include "llrender.h" #include "llevent.h" @@ -372,7 +371,7 @@ void LLView::removeChild(LLView* child) // if we are removing an item we are currently iterating over, that would be bad llassert(child->mInDraw == false); mChildList.remove( child ); - for(boost::unordered_map::iterator it=mChildHashMap.begin(); it != mChildHashMap.end(); ++it) + for(boost::container::flat_map::iterator it=mChildHashMap.begin(); it != mChildHashMap.end(); ++it) { if(it->second == child) { @@ -400,7 +399,7 @@ void LLView::removeChild(LLView* child) LLView::ctrl_list_t LLView::getCtrlList() const { ctrl_list_t controls; - BOOST_FOREACH(LLView* viewp, mChildList) + for (LLView* viewp : mChildList) { if(viewp->isCtrl()) { @@ -613,12 +612,12 @@ void LLView::deleteAllChildren() LLView* viewp = mChildList.front(); delete viewp; // will remove the child from mChildList } - mChildHashMap.clear(); + mChildHashMap.clear(); // } void LLView::setAllChildrenEnabled(BOOL b) { - BOOST_FOREACH(LLView* viewp, mChildList) + for (LLView* viewp : mChildList) { viewp->setEnabled(b); } @@ -644,7 +643,7 @@ void LLView::setVisible(BOOL visible) // virtual void LLView::handleVisibilityChange ( BOOL new_visibility ) { - BOOST_FOREACH(LLView* viewp, mChildList) + for (LLView* viewp : mChildList) { // only views that are themselves visible will have their overall visibility affected by their ancestors if (viewp->getVisible()) @@ -722,7 +721,7 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_s std::string tool_tip; - BOOST_FOREACH(LLView* viewp, mChildList) + for(LLView* viewp : mChildList) { S32 local_x = x - viewp->mRect.mLeft; S32 local_y = y - viewp->mRect.mBottom; @@ -804,7 +803,7 @@ LLView* LLView::childrenHandleCharEvent(const std::string& desc, const METHOD& m { if ( getVisible() && getEnabled() ) { - BOOST_FOREACH(LLView* viewp, mChildList) + for (LLView* viewp : mChildList) { if ((viewp->*method)(c, mask, TRUE)) { @@ -823,7 +822,7 @@ LLView* LLView::childrenHandleCharEvent(const std::string& desc, const METHOD& m template LLView* LLView::childrenHandleMouseEvent(const METHOD& method, S32 x, S32 y, XDATA extra, bool allow_mouse_block) { - BOOST_FOREACH(LLView* viewp, mChildList) + for (LLView* viewp : mChildList) { S32 local_x = x - viewp->getRect().mLeft; S32 local_y = y - viewp->getRect().mBottom; @@ -853,7 +852,7 @@ LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask, // default to not accepting drag and drop, will be overridden by handler *accept = ACCEPT_NO; - BOOST_FOREACH(LLView* viewp, mChildList) + for (LLView* viewp : mChildList) { S32 local_x = x - viewp->getRect().mLeft; S32 local_y = y - viewp->getRect().mBottom; @@ -879,7 +878,7 @@ LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask, LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask) { - BOOST_FOREACH(LLView* viewp, mChildList) + for (LLView* viewp : mChildList) { S32 local_x = x - viewp->getRect().mLeft; S32 local_y = y - viewp->getRect().mBottom; @@ -904,9 +903,9 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask) LLView* LLView::childFromPoint(S32 x, S32 y, bool recur) { if (!getVisible()) - return NULL; + return NULL; // - BOOST_FOREACH(LLView* viewp, mChildList) + for (LLView* viewp : mChildList) { S32 local_x = x - viewp->getRect().mLeft; S32 local_y = y - viewp->getRect().mBottom; @@ -930,7 +929,7 @@ LLView* LLView::childFromPoint(S32 x, S32 y, bool recur) return viewp; } - return 0; + return NULL; // } BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent) @@ -947,8 +946,10 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent) if (!handled) { + // For event logging we don't care which widget handles it + // So we capture the key at the end of this function once we know if it was handled handled = handleKeyHere( key, mask ); - if (handled && LLView::sDebugKeys) + if (handled && LLView::sDebugKeys) // - AHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH { LL_INFOS() << "Key handled by " << getName() << LL_ENDL; } @@ -963,6 +964,38 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent) return handled; } +BOOL LLView::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent) +{ + BOOL handled = FALSE; + + if (getVisible() && getEnabled()) + { + if (called_from_parent) + { + // Downward traversal + handled = childrenHandleKeyUp(key, mask) != NULL; + } + + if (!handled) + { + // For event logging we don't care which widget handles it + // So we capture the key at the end of this function once we know if it was handled + handled = handleKeyUpHere(key, mask); + if (handled) + { + LL_DEBUGS() << "Key handled by " << getName() << LL_ENDL; + } + } + } + + if (!handled && !called_from_parent && mParentView) + { + // Upward traversal + handled = mParentView->handleKeyUp(key, mask, FALSE); + } + return handled; +} + // Called from handleKey() // Handles key in this object. Checking parents and children happens in handleKey() BOOL LLView::handleKeyHere(KEY key, MASK mask) @@ -970,6 +1003,13 @@ BOOL LLView::handleKeyHere(KEY key, MASK mask) return FALSE; } +// Called from handleKey() +// Handles key in this object. Checking parents and children happens in handleKey() +BOOL LLView::handleKeyUpHere(KEY key, MASK mask) +{ + return FALSE; +} + BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) { BOOL handled = FALSE; @@ -1095,6 +1135,12 @@ LLView* LLView::childrenHandleKey(KEY key, MASK mask) return childrenHandleCharEvent("Key", &LLView::handleKey, key, mask); } +// Called during downward traversal +LLView* LLView::childrenHandleKeyUp(KEY key, MASK mask) +{ + return childrenHandleCharEvent("Key Up", &LLView::handleKeyUp, key, mask); +} + // Called during downward traversal LLView* LLView::childrenHandleUnicodeChar(llwchar uni_char) { @@ -1137,7 +1183,7 @@ LLView* LLView::childrenHandleMiddleMouseUp(S32 x, S32 y, MASK mask) LLView* handled_view = NULL; if( getVisible() && getEnabled() ) { - BOOST_FOREACH(LLView* viewp, mChildList) + for (LLView* viewp : mChildList) { S32 local_x = x - viewp->getRect().mLeft; S32 local_y = y - viewp->getRect().mBottom; @@ -1175,7 +1221,16 @@ void LLView::drawChildren() }*/ if (!mChildList.empty()) { - LLView* rootp = LLUI::getRootView(); + LLRect clip_rect = LLUI::getRootView()->getRect(); + if (LLGLState::isEnabled()) + { + LLRect scissor = gGL.getScissor(); + scissor.mLeft /= LLUI::getScaleFactor().mV[VX]; + scissor.mTop /= LLUI::getScaleFactor().mV[VY]; + scissor.mRight /= LLUI::getScaleFactor().mV[VX]; + scissor.mBottom /= LLUI::getScaleFactor().mV[VY]; + clip_rect.intersectWith(scissor); + } ++sDepth; for (child_list_const_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter) @@ -1189,10 +1244,13 @@ void LLView::drawChildren() if (viewp->getVisible() && /*viewp != focus_view && */viewp->getRect().isValid()) { // Only draw views that are within the root view - LLRect screen_rect = viewp->calcScreenRect(); - if ( rootp->getRect().overlaps(screen_rect) ) + // LLView::calcScreenRect not used due to scrolllist cells containing views that aren't inserted into the view heirarchy. + // Render-time offset is stored in LLFontGL::sCurOrigin, which is valid during the draw call chain (which this method is part of) + // Bonus: Reading LLFontGL::sCurOrigin is way (way way way) faster than calling LLView::calcScreenRect. + LLRect screen_rect = viewp->getRect(); + screen_rect.translate(LLFontGL::sCurOrigin.mX, LLFontGL::sCurOrigin.mY); + if ( clip_rect.overlaps(screen_rect) ) { - //gGL.matrixMode(LLRender::MM_MODELVIEW); LLUI::pushMatrix(); { LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); @@ -1217,7 +1275,6 @@ void LLView::drawChildren() LLUI::popMatrix(); } } - } --sDepth; } @@ -1332,8 +1389,10 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent) mRect.mTop = getRect().mBottom + height; // move child views according to reshape flags - BOOST_FOREACH(LLView* viewp, mChildList) + for (LLView* viewp : mChildList) { + if (viewp != NULL) + { LLRect child_rect( viewp->mRect ); if (viewp->followsRight() && viewp->followsLeft()) @@ -1383,6 +1442,7 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent) } } } + } if (!called_from_parent) { @@ -1399,7 +1459,7 @@ LLRect LLView::calcBoundingRect() { LLRect local_bounding_rect = LLRect::null; - BOOST_FOREACH(LLView* childp, mChildList) + for (LLView* childp : mChildList) { // ignore invisible and "top" children when calculating bounding rect // such as combobox popups @@ -1552,16 +1612,16 @@ BOOL LLView::hasChild(const std::string& childname, BOOL recurse) const //----------------------------------------------------------------------------- // getChildView() //----------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_FIND_VIEWS("Find Widgets"); +static LLTrace::BlockTimerStatHandle FTM_FIND_VIEWS("Find Widgets"); LLView* LLView::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const { - LLFastTimer ft(FTM_FIND_VIEWS); + LL_RECORD_BLOCK_TIME(FTM_FIND_VIEWS); //richard: should we allow empty names? //if(name.empty()) // return NULL; // Look for direct children *first* - /*BOOST_FOREACH(LLView* childp, mChildList) + /*for (LLView* childp : mChildList) { llassert(childp); if (childp->getName() == name) @@ -1569,7 +1629,7 @@ LLView* LLView::getChildView(const std::string& name, BOOL recurse, BOOL create_ return childp; } }*/ - boost::unordered_map::const_iterator it = mChildHashMap.find(name); + boost::container::flat_map::const_iterator it = mChildHashMap.find(name); if(it != mChildHashMap.end()) { return it->second; @@ -1577,7 +1637,7 @@ LLView* LLView::getChildView(const std::string& name, BOOL recurse, BOOL create_ if (recurse) { // Look inside each child as well. - BOOST_FOREACH(LLView* childp, mChildList) + for (LLView* childp : mChildList) { llassert(childp); LLView* viewp = childp->getChildView(name, recurse, FALSE); @@ -2771,6 +2831,10 @@ void LLView::initFromXML(LLXMLNodePtr node, LLView* parent) node->getAttributeBOOL("mouse_opaque", mMouseOpaque); node->getAttributeS32("default_tab_group", mDefaultTabGroup); + if (node->hasAttribute("sound_flags")) + { + node->getAttributeU8("sound_flags", mSoundFlags); + } reshape(view_rect.getWidth(), view_rect.getHeight()); } @@ -3013,7 +3077,7 @@ S32 LLView::notifyParent(const LLSD& info) bool LLView::notifyChildren(const LLSD& info) { bool ret = false; - BOOST_FOREACH(LLView* childp, mChildList) + for (LLView* childp : mChildList) { ret = ret || childp->notifyChildren(info); } diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 89d2fc33ce..7cfce62c4e 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -57,7 +57,7 @@ #include "llinitparam.h" #include "lltreeiterators.h" #include "llfocusmgr.h" -#include +#include // #include "ailist.h" const U32 FOLLOWS_NONE = 0x00; @@ -235,7 +235,7 @@ class LLView private: // widgets in general are not copyable - LLView(const LLView& other) {}; + LLView(const LLView& other) = delete; public: #if LL_DEBUG static BOOL sIsDrawing; @@ -452,6 +452,7 @@ class LLView // inherited from LLFocusableElement /* virtual */ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + /* virtual */ BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent); /* virtual */ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, @@ -517,7 +518,7 @@ class LLView const child_list_t* getChildList() const { return &mChildList; } child_list_const_iter_t beginChild() const { return mChildList.begin(); } child_list_const_iter_t endChild() const { return mChildList.end(); } - boost::unordered_map mChildHashMap; + boost::container::flat_map mChildHashMap; // // LLMouseHandler functions // Default behavior is to pass events to children @@ -657,6 +658,7 @@ class LLView virtual void handleReshape(const LLRect& rect, bool by_user); virtual BOOL handleKeyHere(KEY key, MASK mask); + virtual BOOL handleKeyUpHere(KEY key, MASK mask); virtual BOOL handleUnicodeCharHere(llwchar uni_char); @@ -681,6 +683,7 @@ class LLView void logMouseEvent(); LLView* childrenHandleKey(KEY key, MASK mask); + LLView* childrenHandleKeyUp(KEY key, MASK mask); LLView* childrenHandleUnicodeChar(llwchar uni_char); LLView* childrenHandleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp index 9cf5bb03e6..1d367abfca 100644 --- a/indra/llui/llxuiparser.cpp +++ b/indra/llui/llxuiparser.cpp @@ -38,8 +38,6 @@ #include #include -#include -//#include #include #include "lluicolor.h" @@ -679,12 +677,12 @@ LLXUIParser::LLXUIParser() } } -LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing"); +static LLTrace::BlockTimerStatHandle FTM_PARSE_XUI("XUI Parsing"); const LLXMLNodePtr DUMMY_NODE = new LLXMLNode(); void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename, bool silent) { - LLFastTimer ft(FTM_PARSE_XUI); + LL_RECORD_BLOCK_TIME(FTM_PARSE_XUI); mNameStack.clear(); mRootNodeName = node->getName()->mString; mCurFileName = filename; @@ -759,7 +757,7 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block) // and if not, treat as a child element of the current node // e.g. will interpret as "button.rect" // since there is no widget named "rect" - if (child_name.find(".") == std::string::npos) + if (child_name.find('.') == std::string::npos) { mNameStack.push_back(std::make_pair(child_name, true)); num_tokens_pushed++; @@ -1353,9 +1351,9 @@ struct ScopedFile { if (!isOpen()) return 0; - S32 cur_pos = ftell(mFile); + size_t cur_pos = ftell(mFile); fseek(mFile, 0L, SEEK_END); - S32 file_size = ftell(mFile); + size_t file_size = ftell(mFile); fseek(mFile, cur_pos, SEEK_SET); return file_size - cur_pos; } @@ -1366,7 +1364,9 @@ struct ScopedFile }; LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t element_cb) : Parser(sSimpleXUIReadFuncs, sSimpleXUIWriteFuncs, sSimpleXUIInspectFuncs), + mParser(nullptr), mCurReadDepth(0), + mCurAttributeValueBegin(nullptr), mElementCB(element_cb) { if (sSimpleXUIReadFuncs.empty()) @@ -1396,7 +1396,7 @@ LLSimpleXUIParser::~LLSimpleXUIParser() bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent) { - LLFastTimer ft(FTM_PARSE_XUI); + LL_RECORD_BLOCK_TIME(FTM_PARSE_XUI); mParser = XML_ParserCreate(NULL); XML_SetUserData(mParser, this); @@ -1500,7 +1500,7 @@ void LLSimpleXUIParser::startElement(const char *name, const char **atts) } else { // compound attribute - if (child_name.find(".") == std::string::npos) + if (child_name.find('.') == std::string::npos) { mNameStack.push_back(std::make_pair(child_name, true)); num_tokens_pushed++; diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h index 6ada48d055..b24e07cc35 100644 --- a/indra/llui/llxuiparser.h +++ b/indra/llui/llxuiparser.h @@ -31,10 +31,6 @@ #include "llregistry.h" #include "llxmlnode.h" -#ifndef BOOST_FUNCTION_HPP_INCLUDED -#include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif #include #include #include @@ -63,7 +59,7 @@ class LLXSDWriter : public LLInitParam::Parser void writeXSD(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } - + /*virtual*/ std::string getCurrentFileName() { return LLStringUtil::null; } LLXSDWriter(); ~LLXSDWriter(); @@ -101,6 +97,7 @@ LOG_CLASS(LLXUIParser); typedef LLInitParam::Parser::name_stack_t name_stack_t; /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ std::string getCurrentFileName() { return mCurFileName; } /*virtual*/ void parserWarning(const std::string& message); /*virtual*/ void parserError(const std::string& message); @@ -199,10 +196,11 @@ LOG_CLASS(LLSimpleXUIParser); typedef LLInitParam::Parser::name_stack_t name_stack_t; typedef LLInitParam::BaseBlock* (*element_start_callback_t)(LLSimpleXUIParser&, const char* block_name); - LLSimpleXUIParser(element_start_callback_t element_cb = NULL); + LLSimpleXUIParser(element_start_callback_t element_cb = nullptr); virtual ~LLSimpleXUIParser(); /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ std::string getCurrentFileName() { return mCurFileName; } /*virtual*/ void parserWarning(const std::string& message); /*virtual*/ void parserError(const std::string& message); diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt index ca491529b1..aa60e08ddd 100644 --- a/indra/llvfs/CMakeLists.txt +++ b/indra/llvfs/CMakeLists.txt @@ -60,9 +60,10 @@ set_source_files_properties(${llvfs_HEADER_FILES} list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES}) add_library (llvfs ${llvfs_SOURCE_FILES}) -add_dependencies(llvfs prepare) target_link_libraries(llvfs + PUBLIC + llcommon ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ) diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index def50c85b6..84b173c3f1 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -71,8 +71,15 @@ LLDir_Linux gDirUtil; LLDir *gDirUtilp = (LLDir *)&gDirUtil; +/// Values for findSkinnedFilenames(subdir) parameter +const char + *LLDir::XUI = "xui", + *LLDir::TEXTURES = "textures", + *LLDir::SKINBASE = ""; + static const char* const empty = ""; std::string LLDir::sDumpDir = ""; + LLDir::LLDir() : mAppName(""), mExecutablePathAndName(""), @@ -85,7 +92,9 @@ LLDir::LLDir() mOSCacheDir(""), mCAFile(""), mTempDir(""), - mDirDelimiter("/") // fallback to forward slash if not overridden + mDirDelimiter("/"), // fallback to forward slash if not overridden + mLanguage("en"), + mUserName("undefined") { } @@ -97,7 +106,11 @@ std::vector LLDir::getFilesInDir(const std::string &dirname) { //Returns a vector of fullpath filenames. +#if LL_WINDOWS + boost::filesystem::path p (utf8str_to_utf16str(dirname).c_str()); +#else boost::filesystem::path p (dirname); +#endif std::vector v; if (exists(p)) @@ -188,19 +201,33 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) U32 LLDir::deleteDirAndContents(const std::string& dir_name) { //Removes the directory and its contents. Returns number of files removed. - // Singu Note: boost::filesystem throws exceptions - S32 res = 0; + + U32 num_deleted = 0; - try - { - res = boost::filesystem::remove_all(dir_name); - } - catch(const boost::filesystem::filesystem_error& e) + try { - LL_WARNS() << "boost::filesystem::remove_all(\"" + dir_name + "\") failed: '" + e.code().message() + "'" << LL_ENDL; +#if LL_WINDOWS + boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name).c_str()); +#else + boost::filesystem::path dir_path(dir_name); +#endif + if (boost::filesystem::exists (dir_path)) + { + if (!boost::filesystem::is_empty (dir_path)) + { // Directory has content + num_deleted = boost::filesystem::remove_all (dir_path); + } + else + { // Directory is empty + boost::filesystem::remove (dir_path); + } + } } - - return res; + catch (boost::filesystem::filesystem_error &er) + { + LL_WARNS() << "Failed to delete " << dir_name << " with error " << er.code().message() << LL_ENDL; + } + return num_deleted; } const std::string LLDir::findFile(const std::string &filename, @@ -346,6 +373,12 @@ const std::string LLDir::getCacheDir(bool get_default) const } } +#if (defined(_WIN64) || defined(__amd64__) || defined(__x86_64__)) +#define OS_CACHE_DIR "SingularityViewer64" +#else +#define OS_CACHE_DIR "SingularityViewer" +#endif + // Return the default cache directory std::string LLDir::buildSLOSCacheDir() const { @@ -363,11 +396,7 @@ std::string LLDir::buildSLOSCacheDir() const } else { -#if defined(_WIN64) - res = add(getOSCacheDir(), "SingularityViewer64"); -#else - res = add(getOSCacheDir(), "SingularityViewer"); -#endif + res = add(getOSCacheDir(), OS_CACHE_DIR); } return res; } @@ -390,21 +419,27 @@ const std::string &LLDir::getDirDelimiter() const return mDirDelimiter; } +const std::string& LLDir::getDefaultSkinDir() const +{ + return mDefaultSkinDir; +} + const std::string &LLDir::getSkinDir() const { return mSkinDir; } -const std::string &LLDir::getUserSkinDir() const +const std::string& LLDir::getUserDefaultSkinDir() const { - return mUserSkinDir; + return mUserDefaultSkinDir; } -const std::string& LLDir::getDefaultSkinDir() const +const std::string &LLDir::getUserSkinDir() const { - return mDefaultSkinDir; + return mUserSkinDir; } + const std::string LLDir::getSkinBaseDir() const { return mSkinBaseDir; @@ -415,6 +450,11 @@ const std::string &LLDir::getLLPluginDir() const return mLLPluginDir; } +const std::string &LLDir::getUserName() const +{ + return mUserName; +} + static std::string ELLPathToString(ELLPath location) { typedef std::map ELLPathMap; @@ -602,7 +642,7 @@ std::string LLDir::getBaseFileName(const std::string& filepath, bool strip_exten std::string LLDir::getDirName(const std::string& filepath) const { std::size_t offset = filepath.find_last_of(getDirDelimiter()); - S32 len = (offset == std::string::npos) ? 0 : offset; + size_t len = (offset == std::string::npos) ? 0 : offset; std::string dirname = filepath.substr(0, len); return dirname; } @@ -618,31 +658,214 @@ std::string LLDir::getExtension(const std::string& filepath) const return exten; } -std::string LLDir::findSkinnedFilename(const std::string &filename) const +std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint) const { - return findSkinnedFilename("", "", filename); + // This implementation is basically just as described in the declaration comments. + std::vector found(findSkinnedFilenames(subdir, filename, constraint)); + if (found.empty()) + { + return ""; + } + return found.front(); } -std::string LLDir::findSkinnedFilename(const std::string &subdir, const std::string &filename) const +std::string LLDir::findSkinnedFilename(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint) const { - return findSkinnedFilename("", subdir, filename); + // This implementation is basically just as described in the declaration comments. + std::vector found(findSkinnedFilenames(subdir, filename, constraint)); + if (found.empty()) + { + return ""; + } + return found.back(); } -std::string LLDir::findSkinnedFilename(const std::string &subdir1, const std::string &subdir2, const std::string &filename) const +// This method exists because the two code paths for +// findSkinnedFilenames(ALL_SKINS) and findSkinnedFilenames(CURRENT_SKIN) must +// generate the list of candidate pathnames in identical ways. The only +// difference is in the body of the inner loop. +template +void LLDir::walkSearchSkinDirs(const std::string& subdir, + const std::vector& subsubdirs, + const std::string& filename, + const FUNCTION& function) const { - // generate subdirectory path fragment, e.g. "/foo/bar", "/foo", "" - std::string subdirs = ((subdir1.empty() ? "" : mDirDelimiter) + subdir1) - + ((subdir2.empty() ? "" : mDirDelimiter) + subdir2); + BOOST_FOREACH(std::string skindir, mSearchSkinDirs) + { + std::string subdir_path(add(skindir, subdir)); + BOOST_FOREACH(std::string subsubdir, subsubdirs) + { + std::string full_path(add(add(subdir_path, subsubdir), filename)); + if (fileExists(full_path)) + { + function(subsubdir, full_path); + } + } + } +} - std::vector search_paths; - - search_paths.push_back(getUserSkinDir() + subdirs); // first look in user skin override - search_paths.push_back(getSkinDir() + subdirs); // then in current skin - search_paths.push_back(getDefaultSkinDir() + subdirs); // then default skin - search_paths.push_back(getCacheDir() + subdirs); // and last in preload directory +// ridiculous little helper function that should go away when we can use lambda +inline void push_back(std::vector& vector, const std::string& value) +{ + vector.push_back(value); +} + +typedef std::map StringMap; +// ridiculous little helper function that should go away when we can use lambda +inline void store_in_map(StringMap& map, const std::string& key, const std::string& value) +{ + map[key] = value; +} + +std::vector LLDir::findSkinnedFilenames(const std::string& subdir, + const std::string& filename, + ESkinConstraint constraint) const +{ + // Recognize subdirs that have no localization. + static const std::set sUnlocalized = list_of + ("") // top-level directory not localized + ("textures") // textures not localized + ; + + LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename + << "', constraint " + << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS") + << LL_ENDL; + + // Build results vector. + std::vector results; + // Disallow filenames that may escape subdir + if (filename.find("..") != std::string::npos) + { + LL_WARNS("LLDir") << "Ignoring potentially relative filename '" << filename << "'" << LL_ENDL; + return results; + } + + // Cache the default language directory for each subdir we've encountered. + // A cache entry whose value is the empty string means "not localized, + // don't bother checking again." + static StringMap sLocalized; + + // Check whether we've already discovered if this subdir is localized. + StringMap::const_iterator found = sLocalized.find(subdir); + if (found == sLocalized.end()) + { + // We have not yet determined that. Is it one of the subdirs "known" + // to be unlocalized? + if (sUnlocalized.find(subdir) != sUnlocalized.end()) + { + // This subdir is known to be unlocalized. Remember that. + found = sLocalized.insert(StringMap::value_type(subdir, "")).first; + } + else + { + // We do not recognize this subdir. Investigate. + std::string subdir_path(add(getDefaultSkinDir(), subdir)); + if (fileExists(add(subdir_path, "en"))) + { + // defaultSkinDir/subdir contains subdir "en". That's our + // default language; this subdir is localized. + found = sLocalized.insert(StringMap::value_type(subdir, "en")).first; + } + else if (fileExists(add(subdir_path, "en-us"))) + { + // defaultSkinDir/subdir contains subdir "en-us" but not "en". + // Set as default language; this subdir is localized. + found = sLocalized.insert(StringMap::value_type(subdir, "en-us")).first; + } + else + { + // defaultSkinDir/subdir contains neither "en" nor "en-us". + // Assume it's not localized. Remember that assumption. + found = sLocalized.insert(StringMap::value_type(subdir, "")).first; + } + } + } + // Every code path above should have resulted in 'found' becoming a valid + // iterator to an entry in sLocalized. + llassert(found != sLocalized.end()); + + // Now -- is this subdir localized, or not? The answer determines what + // subdirectories we check (under subdir) for the requested filename. + std::vector subsubdirs; + if (found->second.empty()) + { + // subdir is not localized. filename should be located directly within it. + subsubdirs.push_back(""); + } + else + { + // subdir is localized, and found->second is the default language + // directory within it. Check both the default language and the + // current language -- if it differs from the default, of course. + subsubdirs.push_back(found->second); + if (mLanguage != found->second) + { + subsubdirs.push_back(mLanguage); + } + } + + // The process we use depends on 'constraint'. + if (constraint != CURRENT_SKIN) // meaning ALL_SKINS + { + // ALL_SKINS is simpler: just return every pathname generated by + // walkSearchSkinDirs(). Tricky bit: walkSearchSkinDirs() passes its + // FUNCTION the subsubdir as well as the full pathname. We just want + // the full pathname. + walkSearchSkinDirs(subdir, subsubdirs, filename, + boost::bind(push_back, boost::ref(results), _2)); + } + else // CURRENT_SKIN + { + // CURRENT_SKIN turns out to be a bit of a misnomer because we might + // still return files from two different skins. In any case, this + // value of 'constraint' means we will return at most two paths: one + // for the default language, one for the current language (supposing + // those differ). + // It is important to allow a user to override only the localization + // for a particular file, for all viewer installs, without also + // overriding the default-language file. + // It is important to allow a user to override only the default- + // language file, for all viewer installs, without also overriding the + // applicable localization of that file. + // Therefore, treat the default language and the current language as + // two separate cases. For each, capture the most-specialized file + // that exists. + // Use a map keyed by subsubdir (i.e. language code). This allows us + // to handle the case of a single subsubdirs entry with the same logic + // that handles two. For every real file path generated by + // walkSearchSkinDirs(), update the map entry for its subsubdir. + StringMap path_for; + walkSearchSkinDirs(subdir, subsubdirs, filename, + boost::bind(store_in_map, boost::ref(path_for), _1, _2)); + // Now that we have a path for each of the default language and the + // current language, copy them -- in proper order -- into results. + // Don't drive this by walking the map itself: it matters that we + // generate results in the same order as subsubdirs. + BOOST_FOREACH(std::string subsubdir, subsubdirs) + { + StringMap::const_iterator found(path_for.find(subsubdir)); + if (found != path_for.end()) + { + results.push_back(found->second); + } + } + } + + LL_DEBUGS("LLDir") << empty; + const char* comma = ""; + BOOST_FOREACH(std::string path, results) + { + LL_CONT << comma << "'" << path << "'"; + comma = ", "; + } + LL_CONT << LL_ENDL; - std::string found_file = findFile(filename, search_paths); - return found_file; + return results; } std::string LLDir::getTempFilename() const @@ -657,7 +880,7 @@ std::string LLDir::getTempFilename() const } // static -std::string LLDir::getScrubbedFileName(const std::string uncleanFileName) +std::string LLDir::getScrubbedFileName(const std::string& uncleanFileName) { std::string name(uncleanFileName); std::string illegalChars(getForbiddenFileChars()); @@ -668,8 +891,8 @@ std::string LLDir::getScrubbedFileName(const std::string uncleanFileName) // replace any illegal file chars with and underscore '_' for( unsigned int i = 0; i < illegalChars.length(); i++ ) { - int j = -1; - while((j = name.find(illegalChars[i])) > -1) + size_t j = std::string::npos; + while ((j = name.find(illegalChars[i])) != std::string::npos) { name[j] = '_'; } @@ -683,6 +906,19 @@ std::string LLDir::getForbiddenFileChars() return "\\/:*?\"<>|"; } +// static +std::string LLDir::getGridSpecificDir( const std::string& in, const std::string& grid ) +{ + std::string ret = in; + if (!grid.empty()) + { + std::string gridlower(grid); + LLStringUtil::toLower(gridlower); + ret += '@' + gridlower; + } + return ret; +} + void LLDir::setLindenUserDir(const std::string &grid, const std::string &first, const std::string &last) { // if both first and last aren't set, assume we're grabbing the cached dir @@ -692,15 +928,7 @@ void LLDir::setLindenUserDir(const std::string &grid, const std::string &first, // utterly consistent with our firstname/lastname case. std::string userlower(first+"_"+last); LLStringUtil::toLower(userlower); - mLindenUserDir = add(getOSUserAppDir(), userlower); - - if (!grid.empty()) - { - std::string gridlower(grid); - LLStringUtil::toLower(gridlower); - mLindenUserDir += "@"; - mLindenUserDir += gridlower; - } + mLindenUserDir = getGridSpecificDir(add(getOSUserAppDir(), userlower), grid); } else { @@ -737,7 +965,7 @@ void LLDir::makePortable() initAppDirs(mAppName); // This is kinda lazy, but it's probably the quickest, most uniform way. } -void LLDir::setChatLogsDir(const std::string &path) +void LLDir::setChatLogsDir( const std::string& path) { if (!path.empty() ) { @@ -749,6 +977,11 @@ void LLDir::setChatLogsDir(const std::string &path) } } +void LLDir::updatePerAccountChatLogsDir(const std::string &grid) +{ + mPerAccountChatLogsDir = getGridSpecificDir(add(getChatLogsDir(), mUserName), grid); +} + void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string &first, const std::string &last) { // if both first and last aren't set, assume we're grabbing the cached dir @@ -758,14 +991,9 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string // utterly consistent with our firstname/lastname case. std::string userlower(first+"_"+last); LLStringUtil::toLower(userlower); - mPerAccountChatLogsDir = add(getChatLogsDir(), userlower); - if (!grid.empty()) - { - std::string gridlower(grid); - LLStringUtil::toLower(gridlower); - mPerAccountChatLogsDir += "@"; - mPerAccountChatLogsDir += gridlower; - } + + mUserName = userlower; + updatePerAccountChatLogsDir(grid); } else { @@ -773,21 +1001,59 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string } } -void LLDir::setSkinFolder(const std::string &skin_folder) +void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language) { + LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'" + << LL_ENDL; + mSkinName = skin_folder; + mLanguage = language; + + // This method is called multiple times during viewer initialization. Each + // time it's called, reset mSearchSkinDirs. + mSearchSkinDirs.clear(); + + // base skin which is used as fallback for all skinned files + // e.g. c:\program files\secondlife\skins\default + mDefaultSkinDir = getSkinBaseDir(); + append(mDefaultSkinDir, "default"); + // This is always the most general of the search skin directories. + addSearchSkinDir(mDefaultSkinDir); + mSkinDir = getSkinBaseDir(); append(mSkinDir, skin_folder); + // Next level of generality is a skin installed with the viewer. + addSearchSkinDir(mSkinDir); - // user modifications to current skin + // user modifications to skins, current and default // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle mUserSkinDir = getOSUserAppDir(); append(mUserSkinDir, "skins_sg1"); + mUserDefaultSkinDir = mUserSkinDir; + append(mUserDefaultSkinDir, "default"); append(mUserSkinDir, skin_folder); + // Next level of generality is user modifications to default skin... + addSearchSkinDir(mUserDefaultSkinDir); + // then user-defined skins. + addSearchSkinDir(mUserSkinDir); +} - // base skin which is used as fallback for all skinned files - // e.g. c:\program files\secondlife\skins\default - mDefaultSkinDir = getSkinBaseDir(); - append(mDefaultSkinDir, "default"); +void LLDir::addSearchSkinDir(const std::string& skindir) +{ + if (std::find(mSearchSkinDirs.begin(), mSearchSkinDirs.end(), skindir) == mSearchSkinDirs.end()) + { + LL_DEBUGS("LLDir") << "search skin: '" << skindir << "'" << LL_ENDL; + mSearchSkinDirs.push_back(skindir); + } +} + +std::string LLDir::getSkinFolder() const +{ + return mSkinName; +} + +std::string LLDir::getLanguage() const +{ + return mLanguage; } bool LLDir::setCacheDir(const std::string &path) @@ -878,7 +1144,7 @@ LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) c { // But if BOTH path and name bring a separator, we need not add one. // Moreover, we should actually skip the leading separator of 'name'. - return SepOff(false, seplen); + return SepOff(false, static_cast(seplen)); } // Here we know that either path_ends_sep or name_starts_sep is true -- // but not both. So don't add a separator, and don't skip any characters: diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 2be6dd3ec3..34b5ebf559 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -78,7 +78,7 @@ class LLDir virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0; virtual std::string getCurPath() = 0; - virtual BOOL fileExists(const std::string &filename) const = 0; + virtual bool fileExists(const std::string &filename) const = 0; const std::string findFile(const std::string& filename, const std::vector filenames) const; const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const; @@ -103,11 +103,13 @@ class LLDir const std::string &getOSCacheDir() const; // location of OS-specific cache folder (may be empty string) const std::string &getCAFile() const; // File containing TLS certificate authorities const std::string &getDirDelimiter() const; // directory separator for platform (ie. '\' or '/' or ':') + const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default const std::string &getSkinDir() const; // User-specified skin folder. + const std::string &getUserDefaultSkinDir() const; // dir with user modifications to default skin const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin - const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell + const std::string &getUserName() const; // Expanded filename std::string getExpandedFilename(ELLPath location, const std::string &filename) const; @@ -120,25 +122,80 @@ class LLDir std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav" // these methods search the various skin paths for the specified file in the following order: - // getUserSkinDir(), getSkinDir(), getDefaultSkinDir() - std::string findSkinnedFilename(const std::string &filename) const; - std::string findSkinnedFilename(const std::string &subdir, const std::string &filename) const; - std::string findSkinnedFilename(const std::string &subdir1, const std::string &subdir2, const std::string &filename) const; + // getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir() + /// param value for findSkinnedFilenames(), explained below + enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS }; + /** + * Given a filename within skin, return an ordered sequence of paths to + * search. Nonexistent files will be filtered out -- which means that the + * vector might be empty. + * + * @param subdir Identify top-level skin subdirectory by passing one of + * LLDir::XUI (file lives under "xui" subtree), LLDir::TEXTURES (file + * lives under "textures" subtree), LLDir::SKINBASE (file lives at top + * level of skin subdirectory). + * @param filename Desired filename within subdir within skin, e.g. + * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language. + * @param constraint Callers perform two different kinds of processing. + * When fetching a XUI file, for instance, the existence of @a filename in + * the specified skin completely supercedes any @a filename in the default + * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The + * returned vector will contain only + * ".../current_skin/xui/en/filename", + * ".../current_skin/xui/current_language/filename". + * But for (e.g.) "strings.xml", we want a given skin to be able to + * override only specific entries from the default skin. Any string not + * defined in the specified skin will be sought in the default skin. For + * that case, pass @a constraint=ALL_SKINS. The returned vector will + * contain at least ".../default/xui/en/strings.xml", + * ".../default/xui/current_language/strings.xml", + * ".../current_skin/xui/en/strings.xml", + * ".../current_skin/xui/current_language/strings.xml". + */ + std::vector findSkinnedFilenames(const std::string& subdir, + const std::string& filename, + ESkinConstraint constraint=CURRENT_SKIN) const; + /// Values for findSkinnedFilenames(subdir) parameter + static const char *XUI, *TEXTURES, *SKINBASE; + /** + * Return the base-language pathname from findSkinnedFilenames(), or + * the empty string if no such file exists. Parameters are identical to + * findSkinnedFilenames(). This is shorthand for capturing the vector + * returned by findSkinnedFilenames(), checking for empty() and then + * returning front(). + */ + std::string findSkinnedFilenameBaseLang(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint=CURRENT_SKIN) const; + /** + * Return the "most localized" pathname from findSkinnedFilenames(), or + * the empty string if no such file exists. Parameters are identical to + * findSkinnedFilenames(). This is shorthand for capturing the vector + * returned by findSkinnedFilenames(), checking for empty() and then + * returning back(). + */ + std::string findSkinnedFilename(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint=CURRENT_SKIN) const; // random filename in common temporary directory std::string getTempFilename() const; // For producing safe download file names from potentially unsafe ones - static std::string getScrubbedFileName(const std::string uncleanFileName); + static std::string getScrubbedFileName(const std::string& uncleanFileName); static std::string getForbiddenFileChars(); + static std::string getGridSpecificDir( const std::string& in, const std::string& grid ); void setDumpDir( const std::string& path ); void makePortable(); virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir - virtual void setPerAccountChatLogsDir(const std::string &grid, const std::string &first, const std::string &last); // Set the per user chat log directory. + virtual void setPerAccountChatLogsDir(const std::string &grid, const std::string &first, const std::string& last); // Set the per user chat log directory. virtual void setLindenUserDir(const std::string& grid, const std::string& first, const std::string& last); // Set the linden user dir to this user's dir - virtual void setSkinFolder(const std::string &skin_folder); + virtual void setSkinFolder(const std::string &skin_folder, const std::string& language); + virtual std::string getSkinFolder() const; + virtual std::string getLanguage() const; virtual bool setCacheDir(const std::string &path); + virtual void updatePerAccountChatLogsDir(const std::string &grid); virtual void dumpCurrentDirectories(); @@ -156,6 +213,16 @@ class LLDir // Does an add() or append() call need a directory delimiter? typedef std::pair SepOff; SepOff needSep(const std::string& path, const std::string& name) const; + // build mSearchSkinDirs without adding duplicates + void addSearchSkinDir(const std::string& skindir); + + // Internal to findSkinnedFilenames() + template + void walkSearchSkinDirs(const std::string& subdir, + const std::vector& subsubdirs, + const std::string& filename, + const FUNCTION& function) const; + std::string mAppName; // install directory under progams/ ie "SecondLife" std::string mExecutablePathAndName; // full path + Filename of .exe std::string mExecutableFilename; // Filename of .exe @@ -173,12 +240,21 @@ class LLDir std::string mDefaultCacheDir; // default cache diretory std::string mOSCacheDir; // operating system cache dir std::string mDirDelimiter; + std::string mSkinName; // caller-specified skin name std::string mSkinBaseDir; // Base for skins paths. - std::string mSkinDir; // Location for current skin info. std::string mDefaultSkinDir; // Location for default skin info. + std::string mSkinDir; // Location for current skin info. + std::string mUserDefaultSkinDir; // Location for default skin info. std::string mUserSkinDir; // Location for user-modified skin info. + // Skin directories to search, most general to most specific. This order + // works well for composing fine-grained files, in which an individual item + // in a specific file overrides the corresponding item in more general + // files. Of course, for a file-level search, iterate backwards. + std::vector mSearchSkinDirs; + std::string mLanguage; // Current viewer language std::string mLLPluginDir; // Location for plugins and plugin shell static std::string sDumpDir; // Per-run crash report subdir of log directory. + std::string mUserName; // Current user name }; void dir_exists_or_crash(const std::string &dir_name); diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index d677c75a88..6e70c2235e 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -93,22 +93,7 @@ LLDir_Linux::LLDir_Linux() #else mAppRODataDir = tmp_str; #endif - std::string::size_type build_dir_pos = mExecutableDir.rfind("/build-linux-"); - if (build_dir_pos != std::string::npos) - { - // ...we're in a dev checkout - mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + "/indra/newview/skins"; - if (LLFile::isdir(mSkinBaseDir)) - LL_INFOS() << "Running in dev checkout with mSkinBaseDir " - << mSkinBaseDir << LL_ENDL; - else - mSkinBaseDir = ""; - } - if (mSkinBaseDir.empty()) - { - // ...normal installation running - mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; - } + mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; mOSUserDir = getCurrentUserHome(tmp_str); mOSUserAppDir = ""; @@ -223,7 +208,7 @@ void LLDir_Linux::initAppDirs(const std::string &app_name, } } - mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem"); + mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "ca-bundle.crt"); } U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string &mask) @@ -257,7 +242,7 @@ std::string LLDir_Linux::getCurPath() } -BOOL LLDir_Linux::fileExists(const std::string &filename) const +bool LLDir_Linux::fileExists(const std::string &filename) const { struct stat stat_data; // Check the age of the file @@ -277,7 +262,7 @@ BOOL LLDir_Linux::fileExists(const std::string &filename) const /*virtual*/ std::string LLDir_Linux::getLLPluginLauncher() { return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + - "SLPlugin"; + "llplugin/SLPlugin"; } /*virtual*/ std::string LLDir_Linux::getLLPluginFilename(std::string base_name) diff --git a/indra/llvfs/lldir_linux.h b/indra/llvfs/lldir_linux.h index 46bf91c69d..58f488da68 100644 --- a/indra/llvfs/lldir_linux.h +++ b/indra/llvfs/lldir_linux.h @@ -53,7 +53,7 @@ class LLDir_Linux : public LLDir virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ BOOL fileExists(const std::string &filename) const; + /*virtual*/ bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp index 73d8b677a4..1127614aa5 100644 --- a/indra/llvfs/lldir_mac.cpp +++ b/indra/llvfs/lldir_mac.cpp @@ -149,21 +149,8 @@ LLDir_Mac::LLDir_Mac() CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef); CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true); - - size_t build_dir_pos = mExecutableDir.rfind("/indra/build-darwin-"); - if (build_dir_pos != std::string::npos) - { - // ...we're in a dev checkout - mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) - + "/indra/newview/skins"; - LL_INFOS() << "Running in dev checkout with mSkinBaseDir " - << mSkinBaseDir << LL_ENDL; - } - else - { - // ...normal installation running - mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; - } + + mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; // mOSUserDir error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef); @@ -267,7 +254,7 @@ std::string LLDir_Mac::getCurPath() -BOOL LLDir_Mac::fileExists(const std::string &filename) const +bool LLDir_Mac::fileExists(const std::string &filename) const { struct stat stat_data; // Check the age of the file diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h index d99f9e39e0..5e3fab3fa0 100644 --- a/indra/llvfs/lldir_mac.h +++ b/indra/llvfs/lldir_mac.h @@ -52,7 +52,7 @@ class LLDir_Mac : public LLDir virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - virtual BOOL fileExists(const std::string &filename) const; + virtual bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp index 532ba67d42..a6e1289a09 100644 --- a/indra/llvfs/lldir_solaris.cpp +++ b/indra/llvfs/lldir_solaris.cpp @@ -278,7 +278,7 @@ std::string LLDir_Solaris::getCurPath() } -BOOL LLDir_Solaris::fileExists(const std::string &filename) const +bool LLDir_Solaris::fileExists(const std::string &filename) const { struct stat stat_data; // Check the age of the file diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h index 88da8500d8..c2d660554c 100644 --- a/indra/llvfs/lldir_solaris.h +++ b/indra/llvfs/lldir_solaris.h @@ -53,7 +53,7 @@ class LLDir_Solaris : public LLDir virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ BOOL fileExists(const std::string &filename) const; + /*virtual*/ bool fileExists(const std::string &filename) const; private: DIR *mDirp; diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index 4dc078babb..8547f14080 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -48,60 +48,28 @@ LLDir_Win32::LLDir_Win32() WCHAR w_str[MAX_PATH]; - HRESULT (WINAPI* pSHGetKnownFolderPath)(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath) = NULL; - HMODULE shell = LoadLibrary(L"shell32"); - if(shell) //SHGetSpecialFolderPath is deprecated from Vista an onwards. Try to use SHGetKnownFolderPath if it's available - { - pSHGetKnownFolderPath = (HRESULT (WINAPI *)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *))GetProcAddress(shell, "SHGetKnownFolderPath"); - } + WCHAR* pPath = NULL; + if(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &pPath) == S_OK) + wcscpy_s(w_str, pPath); - // Application Data is where user settings go - if(pSHGetKnownFolderPath) - { - WCHAR* pPath = NULL; - if((*pSHGetKnownFolderPath)(FOLDERID_RoamingAppData, 0, NULL, &pPath) == S_OK) - wcscpy_s(w_str,pPath); - else - SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str ); - if(pPath) - CoTaskMemFree(pPath); - } - else //XP doesn't support SHGetKnownFolderPath - { - SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str ); - } + CoTaskMemFree(pPath); + pPath = NULL; mOSUserDir = utf16str_to_utf8str(llutf16string(w_str)); // We want cache files to go on the local disk, even if the // user is on a network with a "roaming profile". // - // On XP this is: - // C:\Docments and Settings\James\Local Settings\Application Data - // On Vista this is: - // C:\Users\James\AppData\Local + // On Vista and above this is: + // C:\Users\\AppData\Local // // We used to store the cache in AppData\Roaming, and the installer // cleans up that version on upgrade. JC + if(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pPath) == S_OK) + wcscpy_s(w_str, pPath); - - if(pSHGetKnownFolderPath) - { - WCHAR* pPath = NULL; - if((*pSHGetKnownFolderPath)(FOLDERID_LocalAppData, 0, NULL, &pPath) == S_OK) - wcscpy_s(w_str,pPath); - else - SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str ); - if(pPath) - CoTaskMemFree(pPath); - } - else //XP doesn't support SHGetKnownFolderPath - { - SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str ); - } - - if(shell) - FreeLibrary(shell); + CoTaskMemFree(pPath); + pPath = NULL; mOSCacheDir = utf16str_to_utf8str(llutf16string(w_str)); @@ -249,7 +217,7 @@ void LLDir_Win32::initAppDirs(const std::string &app_name, } } - mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem"); + mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "ca-bundle.crt"); } U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &mask) @@ -288,7 +256,7 @@ std::string LLDir_Win32::getCurPath() } -BOOL LLDir_Win32::fileExists(const std::string &filename) const +bool LLDir_Win32::fileExists(const std::string &filename) const { llstat stat_data; // Check the age of the file diff --git a/indra/llvfs/lldir_win32.h b/indra/llvfs/lldir_win32.h index 4421b87f06..ed2f916d43 100644 --- a/indra/llvfs/lldir_win32.h +++ b/indra/llvfs/lldir_win32.h @@ -50,7 +50,7 @@ class LLDir_Win32 : public LLDir /*virtual*/ std::string getCurPath(); /*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ BOOL fileExists(const std::string &filename) const; + /*virtual*/ bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp index 471d956e9b..0cdf456234 100644 --- a/indra/llvfs/lldiriterator.cpp +++ b/indra/llvfs/lldiriterator.cpp @@ -49,7 +49,11 @@ class LLDirIterator::Impl LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) : mIsValid(false) { +#if LL_WINDOWS + fs::path dir_path(utf8str_to_utf16str(dirname).c_str()); +#else fs::path dir_path(dirname); +#endif bool is_dir = false; @@ -58,11 +62,7 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) { is_dir = fs::is_directory(dir_path); } -#if BOOST_FILESYSTEM_VERSION >= 3 - catch (fs::filesystem_error& e) -#else - catch (fs::basic_filesystem_error& e) -#endif + catch (const fs::filesystem_error& e) { LL_WARNS() << e.what() << LL_ENDL; return; @@ -79,13 +79,9 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) { mIter = fs::directory_iterator(dir_path); } -#if BOOST_FILESYSTEM_VERSION >= 3 - catch (fs::filesystem_error& e) -#else - catch (fs::basic_filesystem_error& e) -#endif + catch (const fs::filesystem_error& e) { - LL_ERRS() << e.what() << LL_ENDL; + LL_WARNS() << e.what() << LL_ENDL; return; } @@ -101,7 +97,7 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) } catch (boost::regex_error& e) { - LL_ERRS() << "\"" << exp << "\" is not a valid regular expression: " + LL_WARNS() << "\"" << exp << "\" is not a valid regular expression: " << e.what() << LL_ENDL; return; } @@ -125,20 +121,26 @@ bool LLDirIterator::Impl::next(std::string &fname) fs::directory_iterator end_itr; // default construction yields past-the-end bool found = false; - while (mIter != end_itr && !found) + + // Check if path is a directory. + try { - boost::smatch match; -#if BOOST_FILESYSTEM_VERSION >= 3 - std::string name = mIter->path().filename().string(); -#else - std::string name = mIter->path().filename(); -#endif - if ((found = boost::regex_match(name, match, mFilterExp))) + while (mIter != end_itr && !found) { - fname = name; + boost::smatch match; + std::string name = mIter->path().filename().string(); + found = boost::regex_match(name, match, mFilterExp); + if (found) + { + fname = name; + } + + ++mIter; } - - ++mIter; + } + catch (const fs::filesystem_error& e) + { + LL_WARNS() << e.what() << LL_ENDL; } return found; diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp index d84c03e93e..af6d7da2df 100644 --- a/indra/llvfs/llvfile.cpp +++ b/indra/llvfs/llvfile.cpp @@ -39,7 +39,7 @@ const S32 LLVFile::WRITE = 0x00000002; const S32 LLVFile::READ_WRITE = 0x00000003; // LLVFile::READ & LLVFile::WRITE const S32 LLVFile::APPEND = 0x00000006; // 0x00000004 & LLVFile::WRITE -static LLFastTimer::DeclareTimer FTM_VFILE_WAIT("VFile Wait"); +static LLTrace::BlockTimerStatHandle FTM_VFILE_WAIT("VFile Wait"); //---------------------------------------------------------------------------- LLVFSThread* LLVFile::sVFSThread = NULL; @@ -315,7 +315,7 @@ BOOL LLVFile::setMaxSize(S32 size) if (!mVFS->checkAvailable(size)) { - //LLFastTimer t(FTM_VFILE_WAIT); + //LL_RECORD_BLOCK_TIME(FTM_VFILE_WAIT); S32 count = 0; while (sVFSThread->getPending() > 1000) { @@ -423,7 +423,7 @@ bool LLVFile::isLocked(EVFSLock lock) void LLVFile::waitForLock(EVFSLock lock) { - //LLFastTimer t(FTM_VFILE_WAIT); + //LL_RECORD_BLOCK_TIME(FTM_VFILE_WAIT); // spin until the lock clears while (isLocked(lock)) { diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index ec0a7e21e1..8d21a65dc2 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -1586,8 +1586,8 @@ LLVFSBlock *LLVFS::findFreeBlock(S32 size, LLVFSFileBlock *immune) } - LL_INFOS() << "VFS: LRU: Aggressive: " << (S32)lru_list.size() << " files remain" << LL_ENDL; - dumpLockCounts(); + //LL_INFOS() << "VFS: LRU: Aggressive: " << (S32)lru_list.size() << " files remain" << LL_ENDL; + //dumpLockCounts(); // Now it's time to aggressively make more space // Delete the oldest 5MB of the vfs or enough to hold the file, which ever is larger diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 34c4a8d53d..73a7aa59b4 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -11,7 +11,6 @@ project(llwindow) include(00-Common) -include(DirectX) include(LLCommon) include(LLImage) include(LLMath) @@ -144,11 +143,9 @@ if (llwindow_HEADER_FILES) endif (llwindow_HEADER_FILES) list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES}) -add_library (llwindow + add_library (llwindow ${llwindow_SOURCE_FILES} ${viewer_SOURCE_FILES} ) -add_dependencies(llwindow prepare) -target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES}) - +target_link_libraries (llwindow PUBLIC llcommon ${llwindow_LINK_LIBRARIES}) diff --git a/indra/llwindow/GL/glh_extensions.h b/indra/llwindow/GL/glh_extensions.h deleted file mode 100644 index 554cb1731f..0000000000 --- a/indra/llwindow/GL/glh_extensions.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * glh_extensions.h - * $LicenseInfo:firstyear=2006&license=mit$ (mit used here to satisfy validity checker) - * Copyright (C) 2006, NVIDIA - * From nVidia Corporation, downloaded 2006-12-18 from: - * http://developer.nvidia.com/attach/8196 - * ("NVParse Library with Source (.zip) (2390 KB)") - * - * License (quoted from license_info.txt in aforementioned file): - * "The files bison.exe, bison.simple, and flex.exe are covered by - * the GPL. All other files in this distribution can be used however - * you want." - * $/LicenseInfo$ - - */ - -#ifndef GLH_EXTENSIONS -#define GLH_EXTENSIONS - -#include -#include - -#ifdef _WIN32 -# include -#endif - -#ifndef __APPLE__ -#include -#endif - -#ifdef _WIN32 -# include "GL/wglext.h" -#endif - -#define CHECK_MEMORY(ptr) \ - if (NULL == ptr) { \ - printf("Error allocating memory in file %s, line %d\n", __FILE__, __LINE__); \ - exit(-1); \ - } - -#ifdef GLH_EXT_SINGLE_FILE -# define GLH_EXTENSIONS_SINGLE_FILE // have to do this because glh_genext.h unsets GLH_EXT_SINGLE_FILE -#endif - -#include "glh_genext.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef GLH_EXTENSIONS_SINGLE_FILE - -class GLHExts -{ -public: - GLHExts() - { - mSysExts = NULL; -// mUnsupportedExts = NULL; - } - ~GLHExts() - { - if (mSysExts) - { - free(mSysExts); - } -// if (mUnsupportedExts) -// { -// free(mUnsupportedExts); -// } - } - char *mSysExts; -// char *mUnsupportedExts; -}; - -GLHExts gGLHExts; - -static int ExtensionExists(const char* extName, const char* sysExts) -{ - char *padExtName = (char*)malloc(strlen(extName) + 2); - strcat(strcpy(padExtName, extName), " "); - - if (0 == strcmp(extName, "GL_VERSION_1_2")) { - const char *version = (const char*)glGetString(GL_VERSION); - if (strstr(version, "1.0") == version || strstr(version, "1.1") == version) { - return FALSE; - } else { - return TRUE; - } - } - if (strstr(sysExts, padExtName)) { - free(padExtName); - return TRUE; - } else { - free(padExtName); - return FALSE; - } -} - -static const char* EatWhiteSpace(const char *str) -{ - for (; *str && (' ' == *str || '\t' == *str || '\n' == *str); str++); - return str; -} - -static const char* EatNonWhiteSpace(const char *str) -{ - for (; *str && (' ' != *str && '\t' != *str && '\n' != *str); str++); - return str; -} - - -int glh_init_extensions(const char *origReqExts) -{ - // Length of requested extensions string - //unsigned reqExtsLen; - char *reqExts; - // Ptr for individual extensions within reqExts - char *reqExt; - int success = TRUE; - - // build space-padded extension string - if (NULL == gGLHExts.mSysExts) { - const char *extensions = (const char*)glGetString(GL_EXTENSIONS); - int sysExtsLen = (int)strlen(extensions); - const char *winsys_extensions = 0; - int winsysExtsLen = 0; -#ifdef _WIN32 - { - PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0; - wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); - if(wglGetExtensionsStringARB) - { - winsys_extensions = wglGetExtensionsStringARB(wglGetCurrentDC()); - winsysExtsLen = (S32)strlen(winsys_extensions); - } - } -#endif - // Add 2 bytes, one for padding space, one for terminating NULL - gGLHExts.mSysExts = (char*)malloc(sysExtsLen + winsysExtsLen + 3); - CHECK_MEMORY(gGLHExts.mSysExts); - strcpy(gGLHExts.mSysExts, extensions); - gGLHExts.mSysExts[sysExtsLen] = ' '; - gGLHExts.mSysExts[sysExtsLen + 1] = 0; - if (winsysExtsLen) - { - strcat(gGLHExts.mSysExts, winsys_extensions); - } - gGLHExts.mSysExts[sysExtsLen + 1 + winsysExtsLen] = ' '; - gGLHExts.mSysExts[sysExtsLen + 1 + winsysExtsLen + 1] = 0; - } - - if (NULL == origReqExts) - { - return TRUE; - } - reqExts = strdup(origReqExts); - /* - reqExtsLen = (S32)strlen(reqExts); - if (NULL == gGLHExts.mUnsupportedExts) - { - gGLHExts.mUnsupportedExts = (char*)malloc(reqExtsLen + 1); - } - else if (reqExtsLen > strlen(gGLHExts.mUnsupportedExts)) - { - gGLHExts.mUnsupportedExts = (char*)realloc(gGLHExts.mUnsupportedExts, reqExtsLen + 1); - } - CHECK_MEMORY(gGLHExts.mUnsupportedExts); - *gGLHExts.mUnsupportedExts = 0; - */ - - // Parse requested extension list - for (reqExt = reqExts; - (reqExt = (char*)EatWhiteSpace(reqExt)) && *reqExt; - reqExt = (char*)EatNonWhiteSpace(reqExt)) - { - char *extEnd = (char*)EatNonWhiteSpace(reqExt); - char saveChar = *extEnd; - *extEnd = (char)0; - - if (!ExtensionExists(reqExt, gGLHExts.mSysExts) || - !glh_init_extension(reqExt)) { - /* - // add reqExt to end of unsupportedExts - strcat(gGLHExts.mUnsupportedExts, reqExt); - strcat(gGLHExts.mUnsupportedExts, " "); - */ - success = FALSE; - } - *extEnd = saveChar; - } - free(reqExts); - return success; -} - -const char* glh_get_unsupported_extensions() -{ - return ""; -// return (const char*)gGLHExts.mUnsupportedExts; -} - -#else -int glh_init_extensions(const char *origReqExts); -const char* glh_get_unsupported_extensions(); -#endif /* GLH_EXT_SINGLE_FILE */ - -#ifdef __cplusplus -} -#endif - -#endif /* GLH_EXTENSIONS */ diff --git a/indra/llwindow/GL/glh_genext.h b/indra/llwindow/GL/glh_genext.h deleted file mode 100644 index 8d42025198..0000000000 --- a/indra/llwindow/GL/glh_genext.h +++ /dev/null @@ -1,1671 +0,0 @@ -/* - * glh_genext.h - * From nVidia Corporation, downloaded 2006-12-18 from: - * http://developer.nvidia.com/attach/8196 - * ("NVParse Library with Source (.zip) (2390 KB)") - * - * License (quoted from license_info.txt in aforementioned file): - * "The files bison.exe, bison.simple, and flex.exe are covered by - * the GPL. All other files in this distribution can be used however - * you want." - */ - -/* File generated by extgen.cpp -- do not modify */ -#ifndef GLH_GENEXT_H -#define GLH_GENEXT_H - -// MBW -- None of this is necessary on Mac OS. -#ifndef __APPLE__ - -#include -#include - -#ifdef _WIN32 /* supports windows, x -- need to generalize */ -# include -# define GLH_EXT_GET_PROC_ADDRESS(p) wglGetProcAddress(p) -#else if GLX_VERSION_1_3 -# include -# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB(p) -#endif - -#ifdef GLH_EXT_SINGLE_FILE - #define GLH_EXTERN - #define GLH_INITIALIZER = 0 -#else - #define GLH_EXTERN extern - #define GLH_INITIALIZER -#endif - -#define GLH__PREPROCESSOR_GYMNASTICS2(a,b) a##b -#define GLH__PREPROCESSOR_GYMNASTICS(a,b) GLH__PREPROCESSOR_GYMNASTICS2(a,b) - -#ifndef GLH_EXT_PREFIX -# define GLH_EXT_NAME(a) a -#else -# define GLH_EXT_NAME(a) GLH__PREPROCESSOR_GYMNASTICS(GLH_EXT_PREFIX,a) -#endif - -#ifndef _WIN32 -# ifndef GLH_CORE_1_2_PREFIX -# define GLH_CORE_1_2_PREFIX _ -# endif -#endif - -#ifndef GLH_CORE_1_2_PREFIX -# define GLH_CORE_1_2_NAME(a) a -#else -# define GLH_CORE_1_2_NAME(a) GLH__PREPROCESSOR_GYMNASTICS(GLH_CORE_1_2_PREFIX,a) -#endif - -#ifdef GL_ARB_multitexture - GLH_EXTERN PFNGLMULTITEXCOORD1DARBPROC GLH_EXT_NAME(glMultiTexCoord1dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1DVARBPROC GLH_EXT_NAME(glMultiTexCoord1dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1FARBPROC GLH_EXT_NAME(glMultiTexCoord1fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1FVARBPROC GLH_EXT_NAME(glMultiTexCoord1fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1IARBPROC GLH_EXT_NAME(glMultiTexCoord1iARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1IVARBPROC GLH_EXT_NAME(glMultiTexCoord1ivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1SARBPROC GLH_EXT_NAME(glMultiTexCoord1sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1SVARBPROC GLH_EXT_NAME(glMultiTexCoord1svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2DARBPROC GLH_EXT_NAME(glMultiTexCoord2dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2DVARBPROC GLH_EXT_NAME(glMultiTexCoord2dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2FARBPROC GLH_EXT_NAME(glMultiTexCoord2fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2FVARBPROC GLH_EXT_NAME(glMultiTexCoord2fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2IARBPROC GLH_EXT_NAME(glMultiTexCoord2iARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2IVARBPROC GLH_EXT_NAME(glMultiTexCoord2ivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2SARBPROC GLH_EXT_NAME(glMultiTexCoord2sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2SVARBPROC GLH_EXT_NAME(glMultiTexCoord2svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3DARBPROC GLH_EXT_NAME(glMultiTexCoord3dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3DVARBPROC GLH_EXT_NAME(glMultiTexCoord3dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3FARBPROC GLH_EXT_NAME(glMultiTexCoord3fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3FVARBPROC GLH_EXT_NAME(glMultiTexCoord3fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3IARBPROC GLH_EXT_NAME(glMultiTexCoord3iARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3IVARBPROC GLH_EXT_NAME(glMultiTexCoord3ivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3SARBPROC GLH_EXT_NAME(glMultiTexCoord3sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3SVARBPROC GLH_EXT_NAME(glMultiTexCoord3svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4DARBPROC GLH_EXT_NAME(glMultiTexCoord4dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4DVARBPROC GLH_EXT_NAME(glMultiTexCoord4dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4FARBPROC GLH_EXT_NAME(glMultiTexCoord4fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4FVARBPROC GLH_EXT_NAME(glMultiTexCoord4fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4IARBPROC GLH_EXT_NAME(glMultiTexCoord4iARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4IVARBPROC GLH_EXT_NAME(glMultiTexCoord4ivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4SARBPROC GLH_EXT_NAME(glMultiTexCoord4sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4SVARBPROC GLH_EXT_NAME(glMultiTexCoord4svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLACTIVETEXTUREARBPROC GLH_EXT_NAME(glActiveTextureARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCLIENTACTIVETEXTUREARBPROC GLH_EXT_NAME(glClientActiveTextureARB) GLH_INITIALIZER; -#endif - -#ifdef GL_ARB_texture_border_clamp -#endif - -#ifdef GL_ARB_texture_compression - GLH_EXTERN PFNGLCOMPRESSEDTEXIMAGE3DARBPROC GLH_EXT_NAME(glCompressedTexImage3DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMPRESSEDTEXIMAGE2DARBPROC GLH_EXT_NAME(glCompressedTexImage2DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMPRESSEDTEXIMAGE1DARBPROC GLH_EXT_NAME(glCompressedTexImage1DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC GLH_EXT_NAME(glCompressedTexSubImage3DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC GLH_EXT_NAME(glCompressedTexSubImage2DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC GLH_EXT_NAME(glCompressedTexSubImage1DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMPRESSEDTEXIMAGEARBPROC GLH_EXT_NAME(glGetCompressedTexImageARB) GLH_INITIALIZER; -#endif - -#ifdef GL_ARB_texture_cube_map -#endif - -#ifdef GL_ARB_transpose_matrix - GLH_EXTERN PFNGLLOADTRANSPOSEMATRIXFARBPROC GLH_EXT_NAME(glLoadTransposeMatrixfARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLLOADTRANSPOSEMATRIXDARBPROC GLH_EXT_NAME(glLoadTransposeMatrixdARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTTRANSPOSEMATRIXFARBPROC GLH_EXT_NAME(glMultTransposeMatrixfARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTTRANSPOSEMATRIXDARBPROC GLH_EXT_NAME(glMultTransposeMatrixdARB) GLH_INITIALIZER; -#endif - -#ifdef GL_ARB_vertex_program - GLH_EXTERN PFNGLVERTEXATTRIB1SARBPROC GLH_EXT_NAME(glVertexAttrib1sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1FARBPROC GLH_EXT_NAME(glVertexAttrib1fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1DARBPROC GLH_EXT_NAME(glVertexAttrib1dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2SARBPROC GLH_EXT_NAME(glVertexAttrib2sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2FARBPROC GLH_EXT_NAME(glVertexAttrib2fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2DARBPROC GLH_EXT_NAME(glVertexAttrib2dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3SARBPROC GLH_EXT_NAME(glVertexAttrib3sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3FARBPROC GLH_EXT_NAME(glVertexAttrib3fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3DARBPROC GLH_EXT_NAME(glVertexAttrib3dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4SARBPROC GLH_EXT_NAME(glVertexAttrib4sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4FARBPROC GLH_EXT_NAME(glVertexAttrib4fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4DARBPROC GLH_EXT_NAME(glVertexAttrib4dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NUBARBPROC GLH_EXT_NAME(glVertexAttrib4NubARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1SVARBPROC GLH_EXT_NAME(glVertexAttrib1svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1FVARBPROC GLH_EXT_NAME(glVertexAttrib1fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1DVARBPROC GLH_EXT_NAME(glVertexAttrib1dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2SVARBPROC GLH_EXT_NAME(glVertexAttrib2svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2FVARBPROC GLH_EXT_NAME(glVertexAttrib2fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2DVARBPROC GLH_EXT_NAME(glVertexAttrib2dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3SVARBPROC GLH_EXT_NAME(glVertexAttrib3svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3FVARBPROC GLH_EXT_NAME(glVertexAttrib3fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3DVARBPROC GLH_EXT_NAME(glVertexAttrib3dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4BVARBPROC GLH_EXT_NAME(glVertexAttrib4bvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4SVARBPROC GLH_EXT_NAME(glVertexAttrib4svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4IVARBPROC GLH_EXT_NAME(glVertexAttrib4ivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4UBVARBPROC GLH_EXT_NAME(glVertexAttrib4ubvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4USVARBPROC GLH_EXT_NAME(glVertexAttrib4usvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4UIVARBPROC GLH_EXT_NAME(glVertexAttrib4uivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4FVARBPROC GLH_EXT_NAME(glVertexAttrib4fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4DVARBPROC GLH_EXT_NAME(glVertexAttrib4dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NBVARBPROC GLH_EXT_NAME(glVertexAttrib4NbvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NSVARBPROC GLH_EXT_NAME(glVertexAttrib4NsvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NIVARBPROC GLH_EXT_NAME(glVertexAttrib4NivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NUBVARBPROC GLH_EXT_NAME(glVertexAttrib4NubvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NUSVARBPROC GLH_EXT_NAME(glVertexAttrib4NusvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NUIVARBPROC GLH_EXT_NAME(glVertexAttrib4NuivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBPOINTERARBPROC GLH_EXT_NAME(glVertexAttribPointerARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLENABLEVERTEXATTRIBARRAYARBPROC GLH_EXT_NAME(glEnableVertexAttribArrayARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLDISABLEVERTEXATTRIBARRAYARBPROC GLH_EXT_NAME(glDisableVertexAttribArrayARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMSTRINGARBPROC GLH_EXT_NAME(glProgramStringARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLBINDPROGRAMARBPROC GLH_EXT_NAME(glBindProgramARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLDELETEPROGRAMSARBPROC GLH_EXT_NAME(glDeleteProgramsARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGENPROGRAMSARBPROC GLH_EXT_NAME(glGenProgramsARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMENVPARAMETER4DARBPROC GLH_EXT_NAME(glProgramEnvParameter4dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMENVPARAMETER4DVARBPROC GLH_EXT_NAME(glProgramEnvParameter4dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMENVPARAMETER4FARBPROC GLH_EXT_NAME(glProgramEnvParameter4fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMENVPARAMETER4FVARBPROC GLH_EXT_NAME(glProgramEnvParameter4fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMLOCALPARAMETER4DARBPROC GLH_EXT_NAME(glProgramLocalParameter4dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMLOCALPARAMETER4DVARBPROC GLH_EXT_NAME(glProgramLocalParameter4dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMLOCALPARAMETER4FARBPROC GLH_EXT_NAME(glProgramLocalParameter4fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMLOCALPARAMETER4FVARBPROC GLH_EXT_NAME(glProgramLocalParameter4fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMENVPARAMETERDVARBPROC GLH_EXT_NAME(glGetProgramEnvParameterdvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMENVPARAMETERFVARBPROC GLH_EXT_NAME(glGetProgramEnvParameterfvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC GLH_EXT_NAME(glGetProgramLocalParameterdvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC GLH_EXT_NAME(glGetProgramLocalParameterfvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMIVARBPROC GLH_EXT_NAME(glGetProgramivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMSTRINGARBPROC GLH_EXT_NAME(glGetProgramStringARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBDVARBPROC GLH_EXT_NAME(glGetVertexAttribdvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBFVARBPROC GLH_EXT_NAME(glGetVertexAttribfvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBIVARBPROC GLH_EXT_NAME(glGetVertexAttribivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBPOINTERVARBPROC GLH_EXT_NAME(glGetVertexAttribPointervARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLISPROGRAMARBPROC GLH_EXT_NAME(glIsProgramARB) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_abgr -#endif - -#ifdef GL_EXT_bgra -#endif - -#ifdef GL_EXT_blend_color - GLH_EXTERN PFNGLBLENDCOLOREXTPROC GLH_EXT_NAME(glBlendColorEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_blend_minmax - GLH_EXTERN PFNGLBLENDEQUATIONEXTPROC GLH_EXT_NAME(glBlendEquationEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_blend_subtract -#endif - -#ifdef GL_EXT_compiled_vertex_array - GLH_EXTERN PFNGLLOCKARRAYSEXTPROC GLH_EXT_NAME(glLockArraysEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLUNLOCKARRAYSEXTPROC GLH_EXT_NAME(glUnlockArraysEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_fog_coord - GLH_EXTERN PFNGLFOGCOORDDEXTPROC GLH_EXT_NAME(glFogCoorddEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLFOGCOORDDVEXTPROC GLH_EXT_NAME(glFogCoorddvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLFOGCOORDFEXTPROC GLH_EXT_NAME(glFogCoordfEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLFOGCOORDFVEXTPROC GLH_EXT_NAME(glFogCoordfvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLFOGCOORDPOINTEREXTPROC GLH_EXT_NAME(glFogCoordPointerEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_light_max_exponent -#endif - -#ifdef GL_EXT_packed_pixels -#endif - -#ifdef GL_EXT_paletted_texture - GLH_EXTERN PFNGLCOLORSUBTABLEEXTPROC GLH_EXT_NAME(glColorSubTableEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOLORTABLEEXTPROC GLH_EXT_NAME(glColorTableEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEEXTPROC GLH_EXT_NAME(glGetColorTableEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEPARAMETERFVEXTPROC GLH_EXT_NAME(glGetColorTableParameterfvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEPARAMETERIVEXTPROC GLH_EXT_NAME(glGetColorTableParameterivEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_point_parameters - GLH_EXTERN PFNGLPOINTPARAMETERFEXTPROC GLH_EXT_NAME(glPointParameterfEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLPOINTPARAMETERFVEXTPROC GLH_EXT_NAME(glPointParameterfvEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_rescale_normal -#endif - -#ifdef GL_EXT_secondary_color - GLH_EXTERN PFNGLSECONDARYCOLOR3BEXTPROC GLH_EXT_NAME(glSecondaryColor3bEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3BVEXTPROC GLH_EXT_NAME(glSecondaryColor3bvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3DEXTPROC GLH_EXT_NAME(glSecondaryColor3dEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3DVEXTPROC GLH_EXT_NAME(glSecondaryColor3dvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3FEXTPROC GLH_EXT_NAME(glSecondaryColor3fEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3FVEXTPROC GLH_EXT_NAME(glSecondaryColor3fvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3IEXTPROC GLH_EXT_NAME(glSecondaryColor3iEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3IVEXTPROC GLH_EXT_NAME(glSecondaryColor3ivEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3SEXTPROC GLH_EXT_NAME(glSecondaryColor3sEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3SVEXTPROC GLH_EXT_NAME(glSecondaryColor3svEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3UBEXTPROC GLH_EXT_NAME(glSecondaryColor3ubEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3UBVEXTPROC GLH_EXT_NAME(glSecondaryColor3ubvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3UIEXTPROC GLH_EXT_NAME(glSecondaryColor3uiEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3UIVEXTPROC GLH_EXT_NAME(glSecondaryColor3uivEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3USEXTPROC GLH_EXT_NAME(glSecondaryColor3usEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3USVEXTPROC GLH_EXT_NAME(glSecondaryColor3usvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLORPOINTEREXTPROC GLH_EXT_NAME(glSecondaryColorPointerEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_separate_specular_color -#endif - -#ifdef GL_EXT_shared_texture_palette -#endif - -#ifdef GL_EXT_stencil_wrap -#endif - -#ifdef GL_EXT_texture_compression_s3tc -#endif - -#ifdef GL_EXT_texture_cube_map -#endif - -#ifdef GL_EXT_texture_edge_clamp -#endif - -#ifdef GL_EXT_texture_env_add -#endif - -#ifdef GL_EXT_texture_env_combine -#endif - -#ifdef GL_EXT_texture_filter_anisotropic -#endif - -#ifdef GL_EXT_texture_lod_bias -#endif - -#ifdef GL_EXT_texture_object - GLH_EXTERN PFNGLARETEXTURESRESIDENTEXTPROC GLH_EXT_NAME(glAreTexturesResidentEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLBINDTEXTUREEXTPROC GLH_EXT_NAME(glBindTextureEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLDELETETEXTURESEXTPROC GLH_EXT_NAME(glDeleteTexturesEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLGENTEXTURESEXTPROC GLH_EXT_NAME(glGenTexturesEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLISTEXTUREEXTPROC GLH_EXT_NAME(glIsTextureEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLPRIORITIZETEXTURESEXTPROC GLH_EXT_NAME(glPrioritizeTexturesEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_texture3D - GLH_EXTERN PFNGLTEXIMAGE3DEXTPROC GLH_EXT_NAME(glTexImage3DEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_vertex_array - GLH_EXTERN PFNGLARRAYELEMENTEXTPROC GLH_EXT_NAME(glArrayElementEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOLORPOINTEREXTPROC GLH_EXT_NAME(glColorPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLEDGEFLAGPOINTEREXTPROC GLH_EXT_NAME(glEdgeFlagPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPOINTERVEXTPROC GLH_EXT_NAME(glGetPointervEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLINDEXPOINTEREXTPROC GLH_EXT_NAME(glIndexPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLNORMALPOINTEREXTPROC GLH_EXT_NAME(glNormalPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLTEXCOORDPOINTEREXTPROC GLH_EXT_NAME(glTexCoordPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXPOINTEREXTPROC GLH_EXT_NAME(glVertexPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLDRAWARRAYSEXTPROC GLH_EXT_NAME(glDrawArraysEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_vertex_weighting - GLH_EXTERN PFNGLVERTEXWEIGHTFEXTPROC GLH_EXT_NAME(glVertexWeightfEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXWEIGHTFVEXTPROC GLH_EXT_NAME(glVertexWeightfvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXWEIGHTPOINTEREXTPROC GLH_EXT_NAME(glVertexWeightPointerEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_NV_blend_square -#endif - -#ifdef GL_NV_evaluators - GLH_EXTERN PFNGLMAPCONTROLPOINTSNVPROC GLH_EXT_NAME(glMapControlPointsNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLMAPPARAMETERIVNVPROC GLH_EXT_NAME(glMapParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLMAPPARAMETERFVNVPROC GLH_EXT_NAME(glMapParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETMAPCONTROLPOINTSNVPROC GLH_EXT_NAME(glGetMapControlPointsNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETMAPPARAMETERIVNVPROC GLH_EXT_NAME(glGetMapParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETMAPPARAMETERFVNVPROC GLH_EXT_NAME(glGetMapParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETMAPATTRIBPARAMETERIVNVPROC GLH_EXT_NAME(glGetMapAttribParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETMAPATTRIBPARAMETERFVNVPROC GLH_EXT_NAME(glGetMapAttribParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLEVALMAPSNVPROC GLH_EXT_NAME(glEvalMapsNV) GLH_INITIALIZER; -#endif - -#ifdef GL_NV_fence - GLH_EXTERN PFNGLGENFENCESNVPROC GLH_EXT_NAME(glGenFencesNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLDELETEFENCESNVPROC GLH_EXT_NAME(glDeleteFencesNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLSETFENCENVPROC GLH_EXT_NAME(glSetFenceNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLTESTFENCENVPROC GLH_EXT_NAME(glTestFenceNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLFINISHFENCENVPROC GLH_EXT_NAME(glFinishFenceNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLISFENCENVPROC GLH_EXT_NAME(glIsFenceNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETFENCEIVNVPROC GLH_EXT_NAME(glGetFenceivNV) GLH_INITIALIZER; -#endif - -#ifdef GL_NV_fog_distance -#endif - -#ifdef GL_NV_packed_depth_stencil -#endif - -#ifdef GL_NV_register_combiners - GLH_EXTERN PFNGLCOMBINERPARAMETERFVNVPROC GLH_EXT_NAME(glCombinerParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMBINERPARAMETERFNVPROC GLH_EXT_NAME(glCombinerParameterfNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMBINERPARAMETERIVNVPROC GLH_EXT_NAME(glCombinerParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMBINERPARAMETERINVPROC GLH_EXT_NAME(glCombinerParameteriNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMBINERINPUTNVPROC GLH_EXT_NAME(glCombinerInputNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMBINEROUTPUTNVPROC GLH_EXT_NAME(glCombinerOutputNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLFINALCOMBINERINPUTNVPROC GLH_EXT_NAME(glFinalCombinerInputNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC GLH_EXT_NAME(glGetCombinerInputParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC GLH_EXT_NAME(glGetCombinerInputParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC GLH_EXT_NAME(glGetCombinerOutputParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC GLH_EXT_NAME(glGetCombinerOutputParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC GLH_EXT_NAME(glGetFinalCombinerInputParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC GLH_EXT_NAME(glGetFinalCombinerInputParameterivNV) GLH_INITIALIZER; -#endif - -#ifdef GL_NV_register_combiners2 - GLH_EXTERN PFNGLCOMBINERSTAGEPARAMETERFVNVPROC GLH_EXT_NAME(glCombinerStageParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC GLH_EXT_NAME(glGetCombinerStageParameterfvNV) GLH_INITIALIZER; -#endif - -#ifdef GL_NV_texgen_reflection -#endif - -#ifdef GL_NV_texture_env_combine4 -#endif - -#ifdef GL_NV_texture_rectangle -#endif - -#ifdef GL_NV_texture_shader -#endif - -#ifdef GL_NV_vertex_array_range - GLH_EXTERN PFNGLFLUSHVERTEXARRAYRANGENVPROC GLH_EXT_NAME(glFlushVertexArrayRangeNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXARRAYRANGENVPROC GLH_EXT_NAME(glVertexArrayRangeNV) GLH_INITIALIZER; -# ifdef _WIN32 - GLH_EXTERN PFNWGLALLOCATEMEMORYNVPROC GLH_EXT_NAME(wglAllocateMemoryNV) GLH_INITIALIZER; -# endif -# ifdef GLX_VERSION_1_3 - GLH_EXTERN PFNGLXALLOCATEMEMORYNVPROC GLH_EXT_NAME(glXAllocateMemoryNV) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLFREEMEMORYNVPROC GLH_EXT_NAME(wglFreeMemoryNV) GLH_INITIALIZER; -# endif -# ifdef GLX_VERSION_1_3 - GLH_EXTERN PFNGLXFREEMEMORYNVPROC GLH_EXT_NAME(glXFreeMemoryNV) GLH_INITIALIZER; -# endif -#endif - -#ifdef GL_NV_vertex_program - GLH_EXTERN PFNGLAREPROGRAMSRESIDENTNVPROC GLH_EXT_NAME(glAreProgramsResidentNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLBINDPROGRAMNVPROC GLH_EXT_NAME(glBindProgramNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLDELETEPROGRAMSNVPROC GLH_EXT_NAME(glDeleteProgramsNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLEXECUTEPROGRAMNVPROC GLH_EXT_NAME(glExecuteProgramNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGENPROGRAMSNVPROC GLH_EXT_NAME(glGenProgramsNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMPARAMETERDVNVPROC GLH_EXT_NAME(glGetProgramParameterdvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMPARAMETERFVNVPROC GLH_EXT_NAME(glGetProgramParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMIVNVPROC GLH_EXT_NAME(glGetProgramivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMSTRINGNVPROC GLH_EXT_NAME(glGetProgramStringNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETTRACKMATRIXIVNVPROC GLH_EXT_NAME(glGetTrackMatrixivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBDVNVPROC GLH_EXT_NAME(glGetVertexAttribdvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBFVNVPROC GLH_EXT_NAME(glGetVertexAttribfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBIVNVPROC GLH_EXT_NAME(glGetVertexAttribivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBPOINTERVNVPROC GLH_EXT_NAME(glGetVertexAttribPointervNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLISPROGRAMNVPROC GLH_EXT_NAME(glIsProgramNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLLOADPROGRAMNVPROC GLH_EXT_NAME(glLoadProgramNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETER4DNVPROC GLH_EXT_NAME(glProgramParameter4dNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETER4DVNVPROC GLH_EXT_NAME(glProgramParameter4dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETER4FNVPROC GLH_EXT_NAME(glProgramParameter4fNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETER4FVNVPROC GLH_EXT_NAME(glProgramParameter4fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETERS4DVNVPROC GLH_EXT_NAME(glProgramParameters4dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETERS4FVNVPROC GLH_EXT_NAME(glProgramParameters4fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLREQUESTRESIDENTPROGRAMSNVPROC GLH_EXT_NAME(glRequestResidentProgramsNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLTRACKMATRIXNVPROC GLH_EXT_NAME(glTrackMatrixNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBPOINTERNVPROC GLH_EXT_NAME(glVertexAttribPointerNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1DNVPROC GLH_EXT_NAME(glVertexAttrib1dNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1DVNVPROC GLH_EXT_NAME(glVertexAttrib1dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1FNVPROC GLH_EXT_NAME(glVertexAttrib1fNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1FVNVPROC GLH_EXT_NAME(glVertexAttrib1fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1SNVPROC GLH_EXT_NAME(glVertexAttrib1sNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1SVNVPROC GLH_EXT_NAME(glVertexAttrib1svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2DNVPROC GLH_EXT_NAME(glVertexAttrib2dNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2DVNVPROC GLH_EXT_NAME(glVertexAttrib2dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2FNVPROC GLH_EXT_NAME(glVertexAttrib2fNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2FVNVPROC GLH_EXT_NAME(glVertexAttrib2fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2SNVPROC GLH_EXT_NAME(glVertexAttrib2sNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2SVNVPROC GLH_EXT_NAME(glVertexAttrib2svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3DNVPROC GLH_EXT_NAME(glVertexAttrib3dNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3DVNVPROC GLH_EXT_NAME(glVertexAttrib3dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3FNVPROC GLH_EXT_NAME(glVertexAttrib3fNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3FVNVPROC GLH_EXT_NAME(glVertexAttrib3fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3SNVPROC GLH_EXT_NAME(glVertexAttrib3sNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3SVNVPROC GLH_EXT_NAME(glVertexAttrib3svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4DNVPROC GLH_EXT_NAME(glVertexAttrib4dNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4DVNVPROC GLH_EXT_NAME(glVertexAttrib4dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4FNVPROC GLH_EXT_NAME(glVertexAttrib4fNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4FVNVPROC GLH_EXT_NAME(glVertexAttrib4fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4SNVPROC GLH_EXT_NAME(glVertexAttrib4sNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4SVNVPROC GLH_EXT_NAME(glVertexAttrib4svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4UBVNVPROC GLH_EXT_NAME(glVertexAttrib4ubvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS1DVNVPROC GLH_EXT_NAME(glVertexAttribs1dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS1FVNVPROC GLH_EXT_NAME(glVertexAttribs1fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS1SVNVPROC GLH_EXT_NAME(glVertexAttribs1svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS2DVNVPROC GLH_EXT_NAME(glVertexAttribs2dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS2FVNVPROC GLH_EXT_NAME(glVertexAttribs2fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS2SVNVPROC GLH_EXT_NAME(glVertexAttribs2svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS3DVNVPROC GLH_EXT_NAME(glVertexAttribs3dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS3FVNVPROC GLH_EXT_NAME(glVertexAttribs3fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS3SVNVPROC GLH_EXT_NAME(glVertexAttribs3svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS4DVNVPROC GLH_EXT_NAME(glVertexAttribs4dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS4FVNVPROC GLH_EXT_NAME(glVertexAttribs4fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS4SVNVPROC GLH_EXT_NAME(glVertexAttribs4svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS4UBVNVPROC GLH_EXT_NAME(glVertexAttribs4ubvNV) GLH_INITIALIZER; -#endif - -#ifdef GL_SGIS_generate_mipmap -#endif - -#ifdef GL_SGIS_texture_lod -#endif - -#ifdef GL_SGIX_depth_texture -#endif - -#ifdef GL_SGIX_shadow -#endif - -#ifdef GL_VERSION_1_2 - /* These routines are prefixed by the preprocessor constant - GLH_CORE_1_2_PREFIX to avoid colliding with the OpenGL 1.2 namespace. */ - GLH_EXTERN PFNGLBLENDCOLORPROC GLH_CORE_1_2_NAME(glBlendColor) GLH_INITIALIZER; - GLH_EXTERN PFNGLBLENDEQUATIONPROC GLH_CORE_1_2_NAME(glBlendEquation) GLH_INITIALIZER; - GLH_EXTERN PFNGLDRAWRANGEELEMENTSPROC GLH_CORE_1_2_NAME(glDrawRangeElements) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOLORTABLEPROC GLH_CORE_1_2_NAME(glColorTable) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOLORTABLEPARAMETERFVPROC GLH_CORE_1_2_NAME(glColorTableParameterfv) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOLORTABLEPARAMETERIVPROC GLH_CORE_1_2_NAME(glColorTableParameteriv) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOPYCOLORTABLEPROC GLH_CORE_1_2_NAME(glCopyColorTable) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEPROC GLH_CORE_1_2_NAME(glGetColorTable) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEPARAMETERFVPROC GLH_CORE_1_2_NAME(glGetColorTableParameterfv) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEPARAMETERIVPROC GLH_CORE_1_2_NAME(glGetColorTableParameteriv) GLH_INITIALIZER; - GLH_EXTERN PFNGLTEXIMAGE3DPROC GLH_CORE_1_2_NAME(glTexImage3D) GLH_INITIALIZER; - GLH_EXTERN PFNGLTEXSUBIMAGE3DPROC GLH_CORE_1_2_NAME(glTexSubImage3D) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOPYTEXSUBIMAGE3DPROC GLH_CORE_1_2_NAME(glCopyTexSubImage3D) GLH_INITIALIZER; -#endif - -#ifdef GL_WIN_swap_hint - GLH_EXTERN PFNGLADDSWAPHINTRECTWINPROC GLH_EXT_NAME(glAddSwapHintRectWIN) GLH_INITIALIZER; -#endif - -#ifdef WGL_ARB_pbuffer -# ifdef _WIN32 - GLH_EXTERN PFNWGLCREATEPBUFFERARBPROC GLH_EXT_NAME(wglCreatePbufferARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLGETPBUFFERDCARBPROC GLH_EXT_NAME(wglGetPbufferDCARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLRELEASEPBUFFERDCARBPROC GLH_EXT_NAME(wglReleasePbufferDCARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLDESTROYPBUFFERARBPROC GLH_EXT_NAME(wglDestroyPbufferARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLQUERYPBUFFERARBPROC GLH_EXT_NAME(wglQueryPbufferARB) GLH_INITIALIZER; -# endif -#endif - -#ifdef WGL_ARB_render_texture -# ifdef _WIN32 - GLH_EXTERN PFNWGLBINDTEXIMAGEARBPROC GLH_EXT_NAME(wglBindTexImageARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLRELEASETEXIMAGEARBPROC GLH_EXT_NAME(wglReleaseTexImageARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLSETPBUFFERATTRIBARBPROC GLH_EXT_NAME(wglSetPbufferAttribARB) GLH_INITIALIZER; -# endif -#endif - -#ifdef WGL_ARB_pixel_format -# ifdef _WIN32 - GLH_EXTERN PFNWGLGETPIXELFORMATATTRIBIVARBPROC GLH_EXT_NAME(wglGetPixelFormatAttribivARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLGETPIXELFORMATATTRIBFVARBPROC GLH_EXT_NAME(wglGetPixelFormatAttribfvARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLCHOOSEPIXELFORMATARBPROC GLH_EXT_NAME(wglChoosePixelFormatARB) GLH_INITIALIZER; -# endif -#endif - - -#ifdef GLH_EXT_SINGLE_FILE - -int glh_init_extension(const char* extension) -{ - if (NULL == extension) { - return FALSE; -#ifdef GL_ARB_multitexture - } else if (0 == strcmp(extension, "GL_ARB_multitexture")) { - GLH_EXT_NAME(glMultiTexCoord1dARB) = (PFNGLMULTITEXCOORD1DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1dARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1dARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1dvARB) = (PFNGLMULTITEXCOORD1DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1dvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1dvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1fARB) = (PFNGLMULTITEXCOORD1FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1fARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1fARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1fvARB) = (PFNGLMULTITEXCOORD1FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1fvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1fvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1iARB) = (PFNGLMULTITEXCOORD1IARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1iARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1iARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1ivARB) = (PFNGLMULTITEXCOORD1IVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1ivARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1ivARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1sARB) = (PFNGLMULTITEXCOORD1SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1sARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1sARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1svARB) = (PFNGLMULTITEXCOORD1SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1svARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1svARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2dARB) = (PFNGLMULTITEXCOORD2DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2dARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2dARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2dvARB) = (PFNGLMULTITEXCOORD2DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2dvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2dvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2fARB) = (PFNGLMULTITEXCOORD2FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2fARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2fARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2fvARB) = (PFNGLMULTITEXCOORD2FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2fvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2fvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2iARB) = (PFNGLMULTITEXCOORD2IARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2iARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2iARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2ivARB) = (PFNGLMULTITEXCOORD2IVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2ivARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2ivARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2sARB) = (PFNGLMULTITEXCOORD2SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2sARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2sARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2svARB) = (PFNGLMULTITEXCOORD2SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2svARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2svARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3dARB) = (PFNGLMULTITEXCOORD3DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3dARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3dARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3dvARB) = (PFNGLMULTITEXCOORD3DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3dvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3dvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3fARB) = (PFNGLMULTITEXCOORD3FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3fARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3fARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3fvARB) = (PFNGLMULTITEXCOORD3FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3fvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3fvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3iARB) = (PFNGLMULTITEXCOORD3IARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3iARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3iARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3ivARB) = (PFNGLMULTITEXCOORD3IVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3ivARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3ivARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3sARB) = (PFNGLMULTITEXCOORD3SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3sARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3sARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3svARB) = (PFNGLMULTITEXCOORD3SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3svARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3svARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4dARB) = (PFNGLMULTITEXCOORD4DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4dARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4dARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4dvARB) = (PFNGLMULTITEXCOORD4DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4dvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4dvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4fARB) = (PFNGLMULTITEXCOORD4FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4fARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4fARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4fvARB) = (PFNGLMULTITEXCOORD4FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4fvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4fvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4iARB) = (PFNGLMULTITEXCOORD4IARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4iARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4iARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4ivARB) = (PFNGLMULTITEXCOORD4IVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4ivARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4ivARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4sARB) = (PFNGLMULTITEXCOORD4SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4sARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4sARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4svARB) = (PFNGLMULTITEXCOORD4SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4svARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4svARB)) - return FALSE; - GLH_EXT_NAME(glActiveTextureARB) = (PFNGLACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveTextureARB"); - if (NULL == GLH_EXT_NAME(glActiveTextureARB)) - return FALSE; - GLH_EXT_NAME(glClientActiveTextureARB) = (PFNGLCLIENTACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glClientActiveTextureARB"); - if (NULL == GLH_EXT_NAME(glClientActiveTextureARB)) - return FALSE; -#endif - -#ifdef GL_ARB_texture_border_clamp - } else if (0 == strcmp(extension, "GL_ARB_texture_border_clamp")) { -#endif - -#ifdef GL_ARB_texture_compression - } else if (0 == strcmp(extension, "GL_ARB_texture_compression")) { - GLH_EXT_NAME(glCompressedTexImage3DARB) = (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage3DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexImage3DARB)) - return FALSE; - GLH_EXT_NAME(glCompressedTexImage2DARB) = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage2DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexImage2DARB)) - return FALSE; - GLH_EXT_NAME(glCompressedTexImage1DARB) = (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage1DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexImage1DARB)) - return FALSE; - GLH_EXT_NAME(glCompressedTexSubImage3DARB) = (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage3DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexSubImage3DARB)) - return FALSE; - GLH_EXT_NAME(glCompressedTexSubImage2DARB) = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage2DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexSubImage2DARB)) - return FALSE; - GLH_EXT_NAME(glCompressedTexSubImage1DARB) = (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage1DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexSubImage1DARB)) - return FALSE; - GLH_EXT_NAME(glGetCompressedTexImageARB) = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCompressedTexImageARB"); - if (NULL == GLH_EXT_NAME(glGetCompressedTexImageARB)) - return FALSE; -#endif - -#ifdef GL_ARB_texture_cube_map - } else if (0 == strcmp(extension, "GL_ARB_texture_cube_map")) { -#endif - -#ifdef GL_ARB_transpose_matrix - } else if (0 == strcmp(extension, "GL_ARB_transpose_matrix")) { - GLH_EXT_NAME(glLoadTransposeMatrixfARB) = (PFNGLLOADTRANSPOSEMATRIXFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glLoadTransposeMatrixfARB"); - if (NULL == GLH_EXT_NAME(glLoadTransposeMatrixfARB)) - return FALSE; - GLH_EXT_NAME(glLoadTransposeMatrixdARB) = (PFNGLLOADTRANSPOSEMATRIXDARBPROC)GLH_EXT_GET_PROC_ADDRESS("glLoadTransposeMatrixdARB"); - if (NULL == GLH_EXT_NAME(glLoadTransposeMatrixdARB)) - return FALSE; - GLH_EXT_NAME(glMultTransposeMatrixfARB) = (PFNGLMULTTRANSPOSEMATRIXFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultTransposeMatrixfARB"); - if (NULL == GLH_EXT_NAME(glMultTransposeMatrixfARB)) - return FALSE; - GLH_EXT_NAME(glMultTransposeMatrixdARB) = (PFNGLMULTTRANSPOSEMATRIXDARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultTransposeMatrixdARB"); - if (NULL == GLH_EXT_NAME(glMultTransposeMatrixdARB)) - return FALSE; -#endif - -#ifdef GL_ARB_vertex_program - } else if (0 == strcmp(extension, "GL_ARB_vertex_program")) { - GLH_EXT_NAME(glVertexAttrib1sARB) = (PFNGLVERTEXATTRIB1SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1sARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib1fARB) = (PFNGLVERTEXATTRIB1FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1fARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib1dARB) = (PFNGLVERTEXATTRIB1DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1dARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2sARB) = (PFNGLVERTEXATTRIB2SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2sARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2fARB) = (PFNGLVERTEXATTRIB2FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2fARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2dARB) = (PFNGLVERTEXATTRIB2DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2dARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3sARB) = (PFNGLVERTEXATTRIB3SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3sARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3fARB) = (PFNGLVERTEXATTRIB3FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3fARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3dARB) = (PFNGLVERTEXATTRIB3DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3dARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4sARB) = (PFNGLVERTEXATTRIB4SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4sARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4fARB) = (PFNGLVERTEXATTRIB4FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4fARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4dARB) = (PFNGLVERTEXATTRIB4DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4dARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NubARB) = (PFNGLVERTEXATTRIB4NUBARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NubARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NubARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib1svARB) = (PFNGLVERTEXATTRIB1SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1svARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib1fvARB) = (PFNGLVERTEXATTRIB1FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib1dvARB) = (PFNGLVERTEXATTRIB1DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2svARB) = (PFNGLVERTEXATTRIB2SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2svARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2fvARB) = (PFNGLVERTEXATTRIB2FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2dvARB) = (PFNGLVERTEXATTRIB2DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3svARB) = (PFNGLVERTEXATTRIB3SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3svARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3fvARB) = (PFNGLVERTEXATTRIB3FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3dvARB) = (PFNGLVERTEXATTRIB3DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4bvARB) = (PFNGLVERTEXATTRIB4BVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4bvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4svARB) = (PFNGLVERTEXATTRIB4SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4svARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4ivARB) = (PFNGLVERTEXATTRIB4IVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ivARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4ivARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4ubvARB) = (PFNGLVERTEXATTRIB4UBVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4ubvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4usvARB) = (PFNGLVERTEXATTRIB4USVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4usvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4uivARB) = (PFNGLVERTEXATTRIB4UIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4uivARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4fvARB) = (PFNGLVERTEXATTRIB4FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4dvARB) = (PFNGLVERTEXATTRIB4DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NbvARB) = (PFNGLVERTEXATTRIB4NBVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NbvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NbvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NsvARB) = (PFNGLVERTEXATTRIB4NSVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NsvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NsvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NivARB) = (PFNGLVERTEXATTRIB4NIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NivARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NivARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NubvARB) = (PFNGLVERTEXATTRIB4NUBVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NubvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NubvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NusvARB) = (PFNGLVERTEXATTRIB4NUSVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NusvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NusvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NuivARB) = (PFNGLVERTEXATTRIB4NUIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NuivARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NuivARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttribPointerARB) = (PFNGLVERTEXATTRIBPOINTERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB"); - if (NULL == GLH_EXT_NAME(glVertexAttribPointerARB)) - return GL_FALSE; - GLH_EXT_NAME(glEnableVertexAttribArrayARB) = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB"); - if (NULL == GLH_EXT_NAME(glEnableVertexAttribArrayARB)) - return GL_FALSE; - GLH_EXT_NAME(glDisableVertexAttribArrayARB) = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB"); - if (NULL == GLH_EXT_NAME(glDisableVertexAttribArrayARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramStringARB) = (PFNGLPROGRAMSTRINGARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB"); - if (NULL == GLH_EXT_NAME(glProgramStringARB)) - return GL_FALSE; - GLH_EXT_NAME(glBindProgramARB) = (PFNGLBINDPROGRAMARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBindProgramARB"); - if (NULL == GLH_EXT_NAME(glBindProgramARB)) - return GL_FALSE; - GLH_EXT_NAME(glDeleteProgramsARB) = (PFNGLDELETEPROGRAMSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsARB"); - if (NULL == GLH_EXT_NAME(glDeleteProgramsARB)) - return GL_FALSE; - GLH_EXT_NAME(glGenProgramsARB) = (PFNGLGENPROGRAMSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenProgramsARB"); - if (NULL == GLH_EXT_NAME(glGenProgramsARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramEnvParameter4dARB) = (PFNGLPROGRAMENVPARAMETER4DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dARB"); - if (NULL == GLH_EXT_NAME(glProgramEnvParameter4dARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramEnvParameter4dvARB) = (PFNGLPROGRAMENVPARAMETER4DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dvARB"); - if (NULL == GLH_EXT_NAME(glProgramEnvParameter4dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramEnvParameter4fARB) = (PFNGLPROGRAMENVPARAMETER4FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fARB"); - if (NULL == GLH_EXT_NAME(glProgramEnvParameter4fARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramEnvParameter4fvARB) = (PFNGLPROGRAMENVPARAMETER4FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fvARB"); - if (NULL == GLH_EXT_NAME(glProgramEnvParameter4fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramLocalParameter4dARB) = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dARB"); - if (NULL == GLH_EXT_NAME(glProgramLocalParameter4dARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramLocalParameter4dvARB) = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dvARB"); - if (NULL == GLH_EXT_NAME(glProgramLocalParameter4dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramLocalParameter4fARB) = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fARB"); - if (NULL == GLH_EXT_NAME(glProgramLocalParameter4fARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramLocalParameter4fvARB) = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fvARB"); - if (NULL == GLH_EXT_NAME(glProgramLocalParameter4fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramEnvParameterdvARB) = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterdvARB"); - if (NULL == GLH_EXT_NAME(glGetProgramEnvParameterdvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramEnvParameterfvARB) = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterfvARB"); - if (NULL == GLH_EXT_NAME(glGetProgramEnvParameterfvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramLocalParameterdvARB) = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterdvARB"); - if (NULL == GLH_EXT_NAME(glGetProgramLocalParameterdvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramLocalParameterfvARB) = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterfvARB"); - if (NULL == GLH_EXT_NAME(glGetProgramLocalParameterfvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramivARB) = (PFNGLGETPROGRAMIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramivARB"); - if (NULL == GLH_EXT_NAME(glGetProgramivARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramStringARB) = (PFNGLGETPROGRAMSTRINGARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringARB"); - if (NULL == GLH_EXT_NAME(glGetProgramStringARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetVertexAttribdvARB) = (PFNGLGETVERTEXATTRIBDVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvARB"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribdvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetVertexAttribfvARB) = (PFNGLGETVERTEXATTRIBFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvARB"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribfvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetVertexAttribivARB) = (PFNGLGETVERTEXATTRIBIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivARB"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribivARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetVertexAttribPointervARB) = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribPointervARB"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribPointervARB)) - return GL_FALSE; - GLH_EXT_NAME(glIsProgramARB) = (PFNGLISPROGRAMARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsProgramARB"); - if (NULL == GLH_EXT_NAME(glIsProgramARB)) - return GL_FALSE; -#endif - -#ifdef GL_EXT_abgr - } else if (0 == strcmp(extension, "GL_EXT_abgr")) { -#endif - -#ifdef GL_EXT_bgra - } else if (0 == strcmp(extension, "GL_EXT_bgra")) { -#endif - -#ifdef GL_EXT_blend_color - } else if (0 == strcmp(extension, "GL_EXT_blend_color")) { - GLH_EXT_NAME(glBlendColorEXT) = (PFNGLBLENDCOLOREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendColorEXT"); - if (NULL == GLH_EXT_NAME(glBlendColorEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_blend_minmax - } else if (0 == strcmp(extension, "GL_EXT_blend_minmax")) { - GLH_EXT_NAME(glBlendEquationEXT) = (PFNGLBLENDEQUATIONEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendEquationEXT"); - if (NULL == GLH_EXT_NAME(glBlendEquationEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_blend_subtract - } else if (0 == strcmp(extension, "GL_EXT_blend_subtract")) { -#endif - -#ifdef GL_EXT_compiled_vertex_array - } else if (0 == strcmp(extension, "GL_EXT_compiled_vertex_array")) { - GLH_EXT_NAME(glLockArraysEXT) = (PFNGLLOCKARRAYSEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glLockArraysEXT"); - if (NULL == GLH_EXT_NAME(glLockArraysEXT)) - return FALSE; - GLH_EXT_NAME(glUnlockArraysEXT) = (PFNGLUNLOCKARRAYSEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glUnlockArraysEXT"); - if (NULL == GLH_EXT_NAME(glUnlockArraysEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_fog_coord - } else if (0 == strcmp(extension, "GL_EXT_fog_coord")) { - GLH_EXT_NAME(glFogCoorddEXT) = (PFNGLFOGCOORDDEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoorddEXT"); - if (NULL == GLH_EXT_NAME(glFogCoorddEXT)) - return FALSE; - GLH_EXT_NAME(glFogCoorddvEXT) = (PFNGLFOGCOORDDVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoorddvEXT"); - if (NULL == GLH_EXT_NAME(glFogCoorddvEXT)) - return FALSE; - GLH_EXT_NAME(glFogCoordfEXT) = (PFNGLFOGCOORDFEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordfEXT"); - if (NULL == GLH_EXT_NAME(glFogCoordfEXT)) - return FALSE; - GLH_EXT_NAME(glFogCoordfvEXT) = (PFNGLFOGCOORDFVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordfvEXT"); - if (NULL == GLH_EXT_NAME(glFogCoordfvEXT)) - return FALSE; - GLH_EXT_NAME(glFogCoordPointerEXT) = (PFNGLFOGCOORDPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordPointerEXT"); - if (NULL == GLH_EXT_NAME(glFogCoordPointerEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_light_max_exponent - } else if (0 == strcmp(extension, "GL_EXT_light_max_exponent")) { -#endif - -#ifdef GL_EXT_packed_pixels - } else if (0 == strcmp(extension, "GL_EXT_packed_pixels")) { -#endif - -#ifdef GL_EXT_paletted_texture - } else if (0 == strcmp(extension, "GL_EXT_paletted_texture")) { - GLH_EXT_NAME(glColorSubTableEXT) = (PFNGLCOLORSUBTABLEEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glColorSubTableEXT"); - if (NULL == GLH_EXT_NAME(glColorSubTableEXT)) - return FALSE; - GLH_EXT_NAME(glColorTableEXT) = (PFNGLCOLORTABLEEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glColorTableEXT"); - if (NULL == GLH_EXT_NAME(glColorTableEXT)) - return FALSE; - GLH_EXT_NAME(glGetColorTableEXT) = (PFNGLGETCOLORTABLEEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTableEXT"); - if (NULL == GLH_EXT_NAME(glGetColorTableEXT)) - return FALSE; - GLH_EXT_NAME(glGetColorTableParameterfvEXT) = (PFNGLGETCOLORTABLEPARAMETERFVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTableParameterfvEXT"); - if (NULL == GLH_EXT_NAME(glGetColorTableParameterfvEXT)) - return FALSE; - GLH_EXT_NAME(glGetColorTableParameterivEXT) = (PFNGLGETCOLORTABLEPARAMETERIVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTableParameterivEXT"); - if (NULL == GLH_EXT_NAME(glGetColorTableParameterivEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_point_parameters - } else if (0 == strcmp(extension, "GL_EXT_point_parameters")) { - GLH_EXT_NAME(glPointParameterfEXT) = (PFNGLPOINTPARAMETERFEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfEXT"); - if (NULL == GLH_EXT_NAME(glPointParameterfEXT)) - return FALSE; - GLH_EXT_NAME(glPointParameterfvEXT) = (PFNGLPOINTPARAMETERFVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvEXT"); - if (NULL == GLH_EXT_NAME(glPointParameterfvEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_rescale_normal - } else if (0 == strcmp(extension, "GL_EXT_rescale_normal")) { -#endif - -#ifdef GL_EXT_secondary_color - } else if (0 == strcmp(extension, "GL_EXT_secondary_color")) { - GLH_EXT_NAME(glSecondaryColor3bEXT) = (PFNGLSECONDARYCOLOR3BEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3bEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3bEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3bvEXT) = (PFNGLSECONDARYCOLOR3BVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3bvEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3bvEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3dEXT) = (PFNGLSECONDARYCOLOR3DEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3dEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3dEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3dvEXT) = (PFNGLSECONDARYCOLOR3DVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3dvEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3dvEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3fEXT) = (PFNGLSECONDARYCOLOR3FEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3fEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3fEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3fvEXT) = (PFNGLSECONDARYCOLOR3FVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3fvEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3fvEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3iEXT) = (PFNGLSECONDARYCOLOR3IEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3iEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3iEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3ivEXT) = (PFNGLSECONDARYCOLOR3IVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ivEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3ivEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3sEXT) = (PFNGLSECONDARYCOLOR3SEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3sEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3sEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3svEXT) = (PFNGLSECONDARYCOLOR3SVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3svEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3svEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3ubEXT) = (PFNGLSECONDARYCOLOR3UBEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ubEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3ubEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3ubvEXT) = (PFNGLSECONDARYCOLOR3UBVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ubvEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3ubvEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3uiEXT) = (PFNGLSECONDARYCOLOR3UIEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3uiEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3uiEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3uivEXT) = (PFNGLSECONDARYCOLOR3UIVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3uivEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3uivEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3usEXT) = (PFNGLSECONDARYCOLOR3USEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3usEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3usEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3usvEXT) = (PFNGLSECONDARYCOLOR3USVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3usvEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3usvEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColorPointerEXT) = (PFNGLSECONDARYCOLORPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColorPointerEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColorPointerEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_separate_specular_color - } else if (0 == strcmp(extension, "GL_EXT_separate_specular_color")) { -#endif - -#ifdef GL_EXT_shared_texture_palette - } else if (0 == strcmp(extension, "GL_EXT_shared_texture_palette")) { -#endif - -#ifdef GL_EXT_stencil_wrap - } else if (0 == strcmp(extension, "GL_EXT_stencil_wrap")) { -#endif - -#ifdef GL_EXT_texture_compression_s3tc - } else if (0 == strcmp(extension, "GL_EXT_texture_compression_s3tc")) { -#endif - -#ifdef GL_EXT_texture_cube_map - } else if (0 == strcmp(extension, "GL_EXT_texture_cube_map")) { -#endif - -#ifdef GL_EXT_texture_edge_clamp - } else if (0 == strcmp(extension, "GL_EXT_texture_edge_clamp")) { -#endif - -#ifdef GL_EXT_texture_env_add - } else if (0 == strcmp(extension, "GL_EXT_texture_env_add")) { -#endif - -#ifdef GL_EXT_texture_env_combine - } else if (0 == strcmp(extension, "GL_EXT_texture_env_combine")) { -#endif - -#ifdef GL_EXT_texture_filter_anisotropic - } else if (0 == strcmp(extension, "GL_EXT_texture_filter_anisotropic")) { -#endif - -#ifdef GL_EXT_texture_lod_bias - } else if (0 == strcmp(extension, "GL_EXT_texture_lod_bias")) { -#endif - -#ifdef GL_EXT_texture_object - } else if (0 == strcmp(extension, "GL_EXT_texture_object")) { - GLH_EXT_NAME(glAreTexturesResidentEXT) = (PFNGLARETEXTURESRESIDENTEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glAreTexturesResidentEXT"); - if (NULL == GLH_EXT_NAME(glAreTexturesResidentEXT)) - return FALSE; - GLH_EXT_NAME(glBindTextureEXT) = (PFNGLBINDTEXTUREEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glBindTextureEXT"); - if (NULL == GLH_EXT_NAME(glBindTextureEXT)) - return FALSE; - GLH_EXT_NAME(glDeleteTexturesEXT) = (PFNGLDELETETEXTURESEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteTexturesEXT"); - if (NULL == GLH_EXT_NAME(glDeleteTexturesEXT)) - return FALSE; - GLH_EXT_NAME(glGenTexturesEXT) = (PFNGLGENTEXTURESEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGenTexturesEXT"); - if (NULL == GLH_EXT_NAME(glGenTexturesEXT)) - return FALSE; - GLH_EXT_NAME(glIsTextureEXT) = (PFNGLISTEXTUREEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glIsTextureEXT"); - if (NULL == GLH_EXT_NAME(glIsTextureEXT)) - return FALSE; - GLH_EXT_NAME(glPrioritizeTexturesEXT) = (PFNGLPRIORITIZETEXTURESEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glPrioritizeTexturesEXT"); - if (NULL == GLH_EXT_NAME(glPrioritizeTexturesEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_texture3D - } else if (0 == strcmp(extension, "GL_EXT_texture3D")) { - GLH_EXT_NAME(glTexImage3DEXT) = (PFNGLTEXIMAGE3DEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage3DEXT"); - if (NULL == GLH_EXT_NAME(glTexImage3DEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_vertex_array - } else if (0 == strcmp(extension, "GL_EXT_vertex_array")) { - GLH_EXT_NAME(glArrayElementEXT) = (PFNGLARRAYELEMENTEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glArrayElementEXT"); - if (NULL == GLH_EXT_NAME(glArrayElementEXT)) - return FALSE; - GLH_EXT_NAME(glColorPointerEXT) = (PFNGLCOLORPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glColorPointerEXT"); - if (NULL == GLH_EXT_NAME(glColorPointerEXT)) - return FALSE; - GLH_EXT_NAME(glEdgeFlagPointerEXT) = (PFNGLEDGEFLAGPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glEdgeFlagPointerEXT"); - if (NULL == GLH_EXT_NAME(glEdgeFlagPointerEXT)) - return FALSE; - GLH_EXT_NAME(glGetPointervEXT) = (PFNGLGETPOINTERVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGetPointervEXT"); - if (NULL == GLH_EXT_NAME(glGetPointervEXT)) - return FALSE; - GLH_EXT_NAME(glIndexPointerEXT) = (PFNGLINDEXPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glIndexPointerEXT"); - if (NULL == GLH_EXT_NAME(glIndexPointerEXT)) - return FALSE; - GLH_EXT_NAME(glNormalPointerEXT) = (PFNGLNORMALPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glNormalPointerEXT"); - if (NULL == GLH_EXT_NAME(glNormalPointerEXT)) - return FALSE; - GLH_EXT_NAME(glTexCoordPointerEXT) = (PFNGLTEXCOORDPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordPointerEXT"); - if (NULL == GLH_EXT_NAME(glTexCoordPointerEXT)) - return FALSE; - GLH_EXT_NAME(glVertexPointerEXT) = (PFNGLVERTEXPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexPointerEXT"); - if (NULL == GLH_EXT_NAME(glVertexPointerEXT)) - return FALSE; - GLH_EXT_NAME(glDrawArraysEXT) = (PFNGLDRAWARRAYSEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawArraysEXT"); - if (NULL == GLH_EXT_NAME(glDrawArraysEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_vertex_weighting - } else if (0 == strcmp(extension, "GL_EXT_vertex_weighting")) { - GLH_EXT_NAME(glVertexWeightfEXT) = (PFNGLVERTEXWEIGHTFEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexWeightfEXT"); - if (NULL == GLH_EXT_NAME(glVertexWeightfEXT)) - return FALSE; - GLH_EXT_NAME(glVertexWeightfvEXT) = (PFNGLVERTEXWEIGHTFVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexWeightfvEXT"); - if (NULL == GLH_EXT_NAME(glVertexWeightfvEXT)) - return FALSE; - GLH_EXT_NAME(glVertexWeightPointerEXT) = (PFNGLVERTEXWEIGHTPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexWeightPointerEXT"); - if (NULL == GLH_EXT_NAME(glVertexWeightPointerEXT)) - return FALSE; -#endif - -#ifdef GL_NV_blend_square - } else if (0 == strcmp(extension, "GL_NV_blend_square")) { -#endif - -#ifdef GL_NV_evaluators - } else if (0 == strcmp(extension, "GL_NV_evaluators")) { - GLH_EXT_NAME(glMapControlPointsNV) = (PFNGLMAPCONTROLPOINTSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glMapControlPointsNV"); - if (NULL == GLH_EXT_NAME(glMapControlPointsNV)) - return FALSE; - GLH_EXT_NAME(glMapParameterivNV) = (PFNGLMAPPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glMapParameterivNV"); - if (NULL == GLH_EXT_NAME(glMapParameterivNV)) - return FALSE; - GLH_EXT_NAME(glMapParameterfvNV) = (PFNGLMAPPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glMapParameterfvNV"); - if (NULL == GLH_EXT_NAME(glMapParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetMapControlPointsNV) = (PFNGLGETMAPCONTROLPOINTSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMapControlPointsNV"); - if (NULL == GLH_EXT_NAME(glGetMapControlPointsNV)) - return FALSE; - GLH_EXT_NAME(glGetMapParameterivNV) = (PFNGLGETMAPPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMapParameterivNV"); - if (NULL == GLH_EXT_NAME(glGetMapParameterivNV)) - return FALSE; - GLH_EXT_NAME(glGetMapParameterfvNV) = (PFNGLGETMAPPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMapParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetMapParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetMapAttribParameterivNV) = (PFNGLGETMAPATTRIBPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMapAttribParameterivNV"); - if (NULL == GLH_EXT_NAME(glGetMapAttribParameterivNV)) - return FALSE; - GLH_EXT_NAME(glGetMapAttribParameterfvNV) = (PFNGLGETMAPATTRIBPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMapAttribParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetMapAttribParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glEvalMapsNV) = (PFNGLEVALMAPSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glEvalMapsNV"); - if (NULL == GLH_EXT_NAME(glEvalMapsNV)) - return FALSE; -#endif - -#ifdef GL_NV_fence - } else if (0 == strcmp(extension, "GL_NV_fence")) { - GLH_EXT_NAME(glGenFencesNV) = (PFNGLGENFENCESNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGenFencesNV"); - if (NULL == GLH_EXT_NAME(glGenFencesNV)) - return FALSE; - GLH_EXT_NAME(glDeleteFencesNV) = (PFNGLDELETEFENCESNVPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteFencesNV"); - if (NULL == GLH_EXT_NAME(glDeleteFencesNV)) - return FALSE; - GLH_EXT_NAME(glSetFenceNV) = (PFNGLSETFENCENVPROC)GLH_EXT_GET_PROC_ADDRESS("glSetFenceNV"); - if (NULL == GLH_EXT_NAME(glSetFenceNV)) - return FALSE; - GLH_EXT_NAME(glTestFenceNV) = (PFNGLTESTFENCENVPROC)GLH_EXT_GET_PROC_ADDRESS("glTestFenceNV"); - if (NULL == GLH_EXT_NAME(glTestFenceNV)) - return FALSE; - GLH_EXT_NAME(glFinishFenceNV) = (PFNGLFINISHFENCENVPROC)GLH_EXT_GET_PROC_ADDRESS("glFinishFenceNV"); - if (NULL == GLH_EXT_NAME(glFinishFenceNV)) - return FALSE; - GLH_EXT_NAME(glIsFenceNV) = (PFNGLISFENCENVPROC)GLH_EXT_GET_PROC_ADDRESS("glIsFenceNV"); - if (NULL == GLH_EXT_NAME(glIsFenceNV)) - return FALSE; - GLH_EXT_NAME(glGetFenceivNV) = (PFNGLGETFENCEIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFenceivNV"); - if (NULL == GLH_EXT_NAME(glGetFenceivNV)) - return FALSE; -#endif - -#ifdef GL_NV_fog_distance - } else if (0 == strcmp(extension, "GL_NV_fog_distance")) { -#endif - -#ifdef GL_NV_packed_depth_stencil - } else if (0 == strcmp(extension, "GL_NV_packed_depth_stencil")) { -#endif - -#ifdef GL_NV_register_combiners - } else if (0 == strcmp(extension, "GL_NV_register_combiners")) { - GLH_EXT_NAME(glCombinerParameterfvNV) = (PFNGLCOMBINERPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerParameterfvNV"); - if (NULL == GLH_EXT_NAME(glCombinerParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glCombinerParameterfNV) = (PFNGLCOMBINERPARAMETERFNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerParameterfNV"); - if (NULL == GLH_EXT_NAME(glCombinerParameterfNV)) - return FALSE; - GLH_EXT_NAME(glCombinerParameterivNV) = (PFNGLCOMBINERPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerParameterivNV"); - if (NULL == GLH_EXT_NAME(glCombinerParameterivNV)) - return FALSE; - GLH_EXT_NAME(glCombinerParameteriNV) = (PFNGLCOMBINERPARAMETERINVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerParameteriNV"); - if (NULL == GLH_EXT_NAME(glCombinerParameteriNV)) - return FALSE; - GLH_EXT_NAME(glCombinerInputNV) = (PFNGLCOMBINERINPUTNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerInputNV"); - if (NULL == GLH_EXT_NAME(glCombinerInputNV)) - return FALSE; - GLH_EXT_NAME(glCombinerOutputNV) = (PFNGLCOMBINEROUTPUTNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerOutputNV"); - if (NULL == GLH_EXT_NAME(glCombinerOutputNV)) - return FALSE; - GLH_EXT_NAME(glFinalCombinerInputNV) = (PFNGLFINALCOMBINERINPUTNVPROC)GLH_EXT_GET_PROC_ADDRESS("glFinalCombinerInputNV"); - if (NULL == GLH_EXT_NAME(glFinalCombinerInputNV)) - return FALSE; - GLH_EXT_NAME(glGetCombinerInputParameterfvNV) = (PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCombinerInputParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetCombinerInputParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetCombinerInputParameterivNV) = (PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCombinerInputParameterivNV"); - if (NULL == GLH_EXT_NAME(glGetCombinerInputParameterivNV)) - return FALSE; - GLH_EXT_NAME(glGetCombinerOutputParameterfvNV) = (PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCombinerOutputParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetCombinerOutputParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetCombinerOutputParameterivNV) = (PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCombinerOutputParameterivNV"); - if (NULL == GLH_EXT_NAME(glGetCombinerOutputParameterivNV)) - return FALSE; - GLH_EXT_NAME(glGetFinalCombinerInputParameterfvNV) = (PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFinalCombinerInputParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetFinalCombinerInputParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetFinalCombinerInputParameterivNV) = (PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFinalCombinerInputParameterivNV"); - if (NULL == GLH_EXT_NAME(glGetFinalCombinerInputParameterivNV)) - return FALSE; -#endif - -#ifdef GL_NV_register_combiners2 - } else if (0 == strcmp(extension, "GL_NV_register_combiners2")) { - GLH_EXT_NAME(glCombinerStageParameterfvNV) = (PFNGLCOMBINERSTAGEPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerStageParameterfvNV"); - if (NULL == GLH_EXT_NAME(glCombinerStageParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetCombinerStageParameterfvNV) = (PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCombinerStageParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetCombinerStageParameterfvNV)) - return FALSE; -#endif - -#ifdef GL_NV_texgen_reflection - } else if (0 == strcmp(extension, "GL_NV_texgen_reflection")) { -#endif - -#ifdef GL_NV_texture_env_combine4 - } else if (0 == strcmp(extension, "GL_NV_texture_env_combine4")) { -#endif - -#ifdef GL_NV_texture_rectangle - } else if (0 == strcmp(extension, "GL_NV_texture_rectangle")) { -#endif - -#ifdef GL_NV_texture_shader - } else if (0 == strcmp(extension, "GL_NV_texture_shader")) { -#endif - -#ifdef GL_NV_vertex_array_range - } else if (0 == strcmp(extension, "GL_NV_vertex_array_range")) { - GLH_EXT_NAME(glFlushVertexArrayRangeNV) = (PFNGLFLUSHVERTEXARRAYRANGENVPROC)GLH_EXT_GET_PROC_ADDRESS("glFlushVertexArrayRangeNV"); - if (NULL == GLH_EXT_NAME(glFlushVertexArrayRangeNV)) - return FALSE; - GLH_EXT_NAME(glVertexArrayRangeNV) = (PFNGLVERTEXARRAYRANGENVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayRangeNV"); - if (NULL == GLH_EXT_NAME(glVertexArrayRangeNV)) - return FALSE; -# ifdef _WIN32 - GLH_EXT_NAME(wglAllocateMemoryNV) = (PFNWGLALLOCATEMEMORYNVPROC)GLH_EXT_GET_PROC_ADDRESS("wglAllocateMemoryNV"); - if (NULL == GLH_EXT_NAME(wglAllocateMemoryNV)) - return FALSE; -# endif -# ifdef GLX_VERSION_1_3 - GLH_EXT_NAME(glXAllocateMemoryNV) = (PFNGLXALLOCATEMEMORYNVPROC)GLH_EXT_GET_PROC_ADDRESS("glXAllocateMemoryNV"); - if (NULL == GLH_EXT_NAME(glXAllocateMemoryNV)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglFreeMemoryNV) = (PFNWGLFREEMEMORYNVPROC)GLH_EXT_GET_PROC_ADDRESS("wglFreeMemoryNV"); - if (NULL == GLH_EXT_NAME(wglFreeMemoryNV)) - return FALSE; -# endif -# ifdef GLX_VERSION_1_3 - GLH_EXT_NAME(glXFreeMemoryNV) = (PFNGLXFREEMEMORYNVPROC)GLH_EXT_GET_PROC_ADDRESS("glXFreeMemoryNV"); - if (NULL == GLH_EXT_NAME(glXFreeMemoryNV)) - return FALSE; -# endif -#endif - -#ifdef GL_NV_vertex_program - } else if (0 == strcmp(extension, "GL_NV_vertex_program")) { - GLH_EXT_NAME(glAreProgramsResidentNV) = (PFNGLAREPROGRAMSRESIDENTNVPROC)GLH_EXT_GET_PROC_ADDRESS("glAreProgramsResidentNV"); - if (NULL == GLH_EXT_NAME(glAreProgramsResidentNV)) - return FALSE; - GLH_EXT_NAME(glBindProgramNV) = (PFNGLBINDPROGRAMNVPROC)GLH_EXT_GET_PROC_ADDRESS("glBindProgramNV"); - if (NULL == GLH_EXT_NAME(glBindProgramNV)) - return FALSE; - GLH_EXT_NAME(glDeleteProgramsNV) = (PFNGLDELETEPROGRAMSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsNV"); - if (NULL == GLH_EXT_NAME(glDeleteProgramsNV)) - return FALSE; - GLH_EXT_NAME(glExecuteProgramNV) = (PFNGLEXECUTEPROGRAMNVPROC)GLH_EXT_GET_PROC_ADDRESS("glExecuteProgramNV"); - if (NULL == GLH_EXT_NAME(glExecuteProgramNV)) - return FALSE; - GLH_EXT_NAME(glGenProgramsNV) = (PFNGLGENPROGRAMSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGenProgramsNV"); - if (NULL == GLH_EXT_NAME(glGenProgramsNV)) - return FALSE; - GLH_EXT_NAME(glGetProgramParameterdvNV) = (PFNGLGETPROGRAMPARAMETERDVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramParameterdvNV"); - if (NULL == GLH_EXT_NAME(glGetProgramParameterdvNV)) - return FALSE; - GLH_EXT_NAME(glGetProgramParameterfvNV) = (PFNGLGETPROGRAMPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetProgramParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetProgramivNV) = (PFNGLGETPROGRAMIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramivNV"); - if (NULL == GLH_EXT_NAME(glGetProgramivNV)) - return FALSE; - GLH_EXT_NAME(glGetProgramStringNV) = (PFNGLGETPROGRAMSTRINGNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringNV"); - if (NULL == GLH_EXT_NAME(glGetProgramStringNV)) - return FALSE; - GLH_EXT_NAME(glGetTrackMatrixivNV) = (PFNGLGETTRACKMATRIXIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTrackMatrixivNV"); - if (NULL == GLH_EXT_NAME(glGetTrackMatrixivNV)) - return FALSE; - GLH_EXT_NAME(glGetVertexAttribdvNV) = (PFNGLGETVERTEXATTRIBDVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvNV"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribdvNV)) - return FALSE; - GLH_EXT_NAME(glGetVertexAttribfvNV) = (PFNGLGETVERTEXATTRIBFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvNV"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribfvNV)) - return FALSE; - GLH_EXT_NAME(glGetVertexAttribivNV) = (PFNGLGETVERTEXATTRIBIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivNV"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribivNV)) - return FALSE; - GLH_EXT_NAME(glGetVertexAttribPointervNV) = (PFNGLGETVERTEXATTRIBPOINTERVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribPointervNV"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribPointervNV)) - return FALSE; - GLH_EXT_NAME(glIsProgramNV) = (PFNGLISPROGRAMNVPROC)GLH_EXT_GET_PROC_ADDRESS("glIsProgramNV"); - if (NULL == GLH_EXT_NAME(glIsProgramNV)) - return FALSE; - GLH_EXT_NAME(glLoadProgramNV) = (PFNGLLOADPROGRAMNVPROC)GLH_EXT_GET_PROC_ADDRESS("glLoadProgramNV"); - if (NULL == GLH_EXT_NAME(glLoadProgramNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameter4dNV) = (PFNGLPROGRAMPARAMETER4DNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameter4dNV"); - if (NULL == GLH_EXT_NAME(glProgramParameter4dNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameter4dvNV) = (PFNGLPROGRAMPARAMETER4DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameter4dvNV"); - if (NULL == GLH_EXT_NAME(glProgramParameter4dvNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameter4fNV) = (PFNGLPROGRAMPARAMETER4FNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameter4fNV"); - if (NULL == GLH_EXT_NAME(glProgramParameter4fNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameter4fvNV) = (PFNGLPROGRAMPARAMETER4FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameter4fvNV"); - if (NULL == GLH_EXT_NAME(glProgramParameter4fvNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameters4dvNV) = (PFNGLPROGRAMPARAMETERS4DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameters4dvNV"); - if (NULL == GLH_EXT_NAME(glProgramParameters4dvNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameters4fvNV) = (PFNGLPROGRAMPARAMETERS4FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameters4fvNV"); - if (NULL == GLH_EXT_NAME(glProgramParameters4fvNV)) - return FALSE; - GLH_EXT_NAME(glRequestResidentProgramsNV) = (PFNGLREQUESTRESIDENTPROGRAMSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glRequestResidentProgramsNV"); - if (NULL == GLH_EXT_NAME(glRequestResidentProgramsNV)) - return FALSE; - GLH_EXT_NAME(glTrackMatrixNV) = (PFNGLTRACKMATRIXNVPROC)GLH_EXT_GET_PROC_ADDRESS("glTrackMatrixNV"); - if (NULL == GLH_EXT_NAME(glTrackMatrixNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribPointerNV) = (PFNGLVERTEXATTRIBPOINTERNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribPointerNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1dNV) = (PFNGLVERTEXATTRIB1DNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1dNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1dvNV) = (PFNGLVERTEXATTRIB1DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1fNV) = (PFNGLVERTEXATTRIB1FNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1fNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1fvNV) = (PFNGLVERTEXATTRIB1FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1sNV) = (PFNGLVERTEXATTRIB1SNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1sNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1svNV) = (PFNGLVERTEXATTRIB1SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2dNV) = (PFNGLVERTEXATTRIB2DNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2dNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2dvNV) = (PFNGLVERTEXATTRIB2DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2fNV) = (PFNGLVERTEXATTRIB2FNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2fNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2fvNV) = (PFNGLVERTEXATTRIB2FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2sNV) = (PFNGLVERTEXATTRIB2SNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2sNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2svNV) = (PFNGLVERTEXATTRIB2SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3dNV) = (PFNGLVERTEXATTRIB3DNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3dNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3dvNV) = (PFNGLVERTEXATTRIB3DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3fNV) = (PFNGLVERTEXATTRIB3FNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3fNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3fvNV) = (PFNGLVERTEXATTRIB3FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3sNV) = (PFNGLVERTEXATTRIB3SNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3sNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3svNV) = (PFNGLVERTEXATTRIB3SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4dNV) = (PFNGLVERTEXATTRIB4DNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4dNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4dvNV) = (PFNGLVERTEXATTRIB4DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4fNV) = (PFNGLVERTEXATTRIB4FNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4fNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4fvNV) = (PFNGLVERTEXATTRIB4FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4sNV) = (PFNGLVERTEXATTRIB4SNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4sNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4svNV) = (PFNGLVERTEXATTRIB4SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4ubvNV) = (PFNGLVERTEXATTRIB4UBVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4ubvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs1dvNV) = (PFNGLVERTEXATTRIBS1DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs1dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs1dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs1fvNV) = (PFNGLVERTEXATTRIBS1FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs1fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs1fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs1svNV) = (PFNGLVERTEXATTRIBS1SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs1svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs1svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs2dvNV) = (PFNGLVERTEXATTRIBS2DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs2dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs2dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs2fvNV) = (PFNGLVERTEXATTRIBS2FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs2fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs2fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs2svNV) = (PFNGLVERTEXATTRIBS2SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs2svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs2svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs3dvNV) = (PFNGLVERTEXATTRIBS3DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs3dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs3dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs3fvNV) = (PFNGLVERTEXATTRIBS3FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs3fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs3fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs3svNV) = (PFNGLVERTEXATTRIBS3SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs3svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs3svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs4dvNV) = (PFNGLVERTEXATTRIBS4DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs4dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs4dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs4fvNV) = (PFNGLVERTEXATTRIBS4FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs4fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs4fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs4svNV) = (PFNGLVERTEXATTRIBS4SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs4svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs4svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs4ubvNV) = (PFNGLVERTEXATTRIBS4UBVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs4ubvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs4ubvNV)) - return FALSE; -#endif - -#ifdef GL_SGIS_generate_mipmap - } else if (0 == strcmp(extension, "GL_SGIS_generate_mipmap")) { -#endif - -#ifdef GL_SGIS_texture_lod - } else if (0 == strcmp(extension, "GL_SGIS_texture_lod")) { -#endif - -#ifdef GL_SGIX_depth_texture - } else if (0 == strcmp(extension, "GL_SGIX_depth_texture")) { -#endif - -#ifdef GL_SGIX_shadow - } else if (0 == strcmp(extension, "GL_SGIX_shadow")) { -#endif - -#ifdef GL_VERSION_1_2 - } else if (0 == strcmp(extension, "GL_VERSION_1_2")) { - GLH_CORE_1_2_NAME(glBlendColor) = (PFNGLBLENDCOLORPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendColor"); - if (NULL == GLH_CORE_1_2_NAME(glBlendColor)) - return FALSE; - GLH_CORE_1_2_NAME(glBlendEquation) = (PFNGLBLENDEQUATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendEquation"); - if (NULL == GLH_CORE_1_2_NAME(glBlendEquation)) - return FALSE; - GLH_CORE_1_2_NAME(glDrawRangeElements) = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements"); - if (NULL == GLH_CORE_1_2_NAME(glDrawRangeElements)) - return FALSE; - GLH_CORE_1_2_NAME(glColorTable) = (PFNGLCOLORTABLEPROC)GLH_EXT_GET_PROC_ADDRESS("glColorTable"); - if (NULL == GLH_CORE_1_2_NAME(glColorTable)) - return FALSE; - GLH_CORE_1_2_NAME(glColorTableParameterfv) = (PFNGLCOLORTABLEPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glColorTableParameterfv"); - if (NULL == GLH_CORE_1_2_NAME(glColorTableParameterfv)) - return FALSE; - GLH_CORE_1_2_NAME(glColorTableParameteriv) = (PFNGLCOLORTABLEPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glColorTableParameteriv"); - if (NULL == GLH_CORE_1_2_NAME(glColorTableParameteriv)) - return FALSE; - GLH_CORE_1_2_NAME(glCopyColorTable) = (PFNGLCOPYCOLORTABLEPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyColorTable"); - if (NULL == GLH_CORE_1_2_NAME(glCopyColorTable)) - return FALSE; - GLH_CORE_1_2_NAME(glGetColorTable) = (PFNGLGETCOLORTABLEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTable"); - if (NULL == GLH_CORE_1_2_NAME(glGetColorTable)) - return FALSE; - GLH_CORE_1_2_NAME(glGetColorTableParameterfv) = (PFNGLGETCOLORTABLEPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTableParameterfv"); - if (NULL == GLH_CORE_1_2_NAME(glGetColorTableParameterfv)) - return FALSE; - GLH_CORE_1_2_NAME(glGetColorTableParameteriv) = (PFNGLGETCOLORTABLEPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTableParameteriv"); - if (NULL == GLH_CORE_1_2_NAME(glGetColorTableParameteriv)) - return FALSE; - GLH_CORE_1_2_NAME(glTexImage3D) = (PFNGLTEXIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage3D"); - if (NULL == GLH_CORE_1_2_NAME(glTexImage3D)) - return FALSE; - GLH_CORE_1_2_NAME(glTexSubImage3D) = (PFNGLTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexSubImage3D"); - if (NULL == GLH_CORE_1_2_NAME(glTexSubImage3D)) - return FALSE; - GLH_CORE_1_2_NAME(glCopyTexSubImage3D) = (PFNGLCOPYTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTexSubImage3D"); - if (NULL == GLH_CORE_1_2_NAME(glCopyTexSubImage3D)) - return FALSE; -#endif - -#ifdef GL_WIN_swap_hint - } else if (0 == strcmp(extension, "GL_WIN_swap_hint")) { - GLH_EXT_NAME(glAddSwapHintRectWIN) = (PFNGLADDSWAPHINTRECTWINPROC)GLH_EXT_GET_PROC_ADDRESS("glAddSwapHintRectWIN"); - if (NULL == GLH_EXT_NAME(glAddSwapHintRectWIN)) - return FALSE; -#endif - -#ifdef WGL_ARB_pbuffer - } else if (0 == strcmp(extension, "WGL_ARB_pbuffer")) { -# ifdef _WIN32 - GLH_EXT_NAME(wglCreatePbufferARB) = (PFNWGLCREATEPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreatePbufferARB"); - if (NULL == GLH_EXT_NAME(wglCreatePbufferARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglGetPbufferDCARB) = (PFNWGLGETPBUFFERDCARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetPbufferDCARB"); - if (NULL == GLH_EXT_NAME(wglGetPbufferDCARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglReleasePbufferDCARB) = (PFNWGLRELEASEPBUFFERDCARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglReleasePbufferDCARB"); - if (NULL == GLH_EXT_NAME(wglReleasePbufferDCARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglDestroyPbufferARB) = (PFNWGLDESTROYPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglDestroyPbufferARB"); - if (NULL == GLH_EXT_NAME(wglDestroyPbufferARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglQueryPbufferARB) = (PFNWGLQUERYPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglQueryPbufferARB"); - if (NULL == GLH_EXT_NAME(wglQueryPbufferARB)) - return FALSE; -# endif -#endif - -#ifdef WGL_ARB_render_texture -# ifdef _WIN32 - GLH_EXT_NAME(wglBindTexImageARB) = (PFNWGLBINDTEXIMAGEARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglBindTexImageARB"); - if (NULL == GLH_EXT_NAME(wglBindTexImageARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglReleaseTexImageARB) = (PFNWGLRELEASETEXIMAGEARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglReleaseTexImageARB"); - if (NULL == GLH_EXT_NAME(wglReleaseTexImageARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglSetPbufferAttribARB) = (PFNWGLSETPBUFFERATTRIBARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglSetPbufferAttribARB"); - if (NULL == GLH_EXT_NAME(wglSetPbufferAttribARB)) - return FALSE; -# endif -#endif - -#ifdef WGL_ARB_pixel_format - } else if (0 == strcmp(extension, "WGL_ARB_pixel_format")) { -# ifdef _WIN32 - GLH_EXT_NAME(wglGetPixelFormatAttribivARB) = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetPixelFormatAttribivARB"); - if (NULL == GLH_EXT_NAME(wglGetPixelFormatAttribivARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglGetPixelFormatAttribfvARB) = (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetPixelFormatAttribfvARB"); - if (NULL == GLH_EXT_NAME(wglGetPixelFormatAttribfvARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglChoosePixelFormatARB) = (PFNWGLCHOOSEPIXELFORMATARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglChoosePixelFormatARB"); - if (NULL == GLH_EXT_NAME(wglChoosePixelFormatARB)) - return FALSE; -# endif -#endif - - } else { - return FALSE; - } - return TRUE; -} -#endif - -#else // defined(__APPLE__) - -#ifdef GLH_EXT_SINGLE_FILE - -int glh_init_extension(const char* extension) -{ - // MBW -- XXX -- Should this check for extension availability? - return TRUE; -} -#endif // GLH_EXT_SINGLE_FILE - -#endif // defined(__APPLE__) - -#undef GLH_EXT_SINGLE_FILE - -#endif /* GLH_GENEXT_H */ diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp index 40d0a22122..f9ec9c21b1 100644 --- a/indra/llwindow/lldxhardware.cpp +++ b/indra/llwindow/lldxhardware.cpp @@ -183,11 +183,11 @@ HRESULT GetVideoMemoryViaWMI( WCHAR* strInputDeviceID, DWORD* pdwAdapterRam ) SAFE_RELEASE( pVideoControllers[iController] ); } } - SAFE_RELEASE(pEnumVideoControllers); } if( pClassName ) SysFreeString( pClassName ); + SAFE_RELEASE( pEnumVideoControllers ); } if( pNamespace ) @@ -206,7 +206,7 @@ HRESULT GetVideoMemoryViaWMI( WCHAR* strInputDeviceID, DWORD* pdwAdapterRam ) return E_FAIL; } -void get_wstring(IDxDiagContainer* containerp, WCHAR* wszPropName, WCHAR* wszPropValue, int outputSize) +void get_wstring(IDxDiagContainer* containerp, const WCHAR* wszPropName, WCHAR* wszPropValue, int outputSize) { HRESULT hr; VARIANT var; @@ -219,10 +219,10 @@ void get_wstring(IDxDiagContainer* containerp, WCHAR* wszPropName, WCHAR* wszPro switch( var.vt ) { case VT_UI4: - swprintf( wszPropValue, L"%d", var.ulVal ); /* Flawfinder: ignore */ + swprintf(wszPropValue, outputSize, L"%d", var.ulVal); /* Flawfinder: ignore */ break; case VT_I4: - swprintf( wszPropValue, L"%d", var.lVal ); /* Flawfinder: ignore */ + swprintf(wszPropValue, outputSize, L"%d", var.lVal); /* Flawfinder: ignore */ break; case VT_BOOL: wcscpy( wszPropValue, (var.boolVal) ? L"true" : L"false" ); /* Flawfinder: ignore */ @@ -237,7 +237,7 @@ void get_wstring(IDxDiagContainer* containerp, WCHAR* wszPropName, WCHAR* wszPro VariantClear( &var ); } -std::string get_string(IDxDiagContainer *containerp, WCHAR *wszPropName) +std::string get_string(IDxDiagContainer *containerp, const WCHAR *wszPropName) { WCHAR wszPropValue[256]; get_wstring(containerp, wszPropName, wszPropValue, 256); @@ -443,7 +443,7 @@ LLDXDevice *LLDXHardware::findDevice(const std::string &vendor, const std::strin } */ -BOOL LLDXHardware::getInfo(BOOL vram_only) +BOOL LLDXHardware::getInfo(BOOL vram_only, S32Megabytes system_ram) { LLTimer hw_timer; BOOL ok = FALSE; @@ -452,9 +452,9 @@ BOOL LLDXHardware::getInfo(BOOL vram_only) hr = CoInitialize(NULL); if (FAILED(hr)) { - LL_WARNS("AppInit") << "COM library initialization failed!" << LL_ENDL; - gWriteDebug("COM library initialization failed!\n"); - return FALSE; + LL_WARNS() << "COM initialization failure!" << LL_ENDL; + gWriteDebug("COM initialization failure!\n"); + return ok; } IDxDiagProvider *dx_diag_providerp = NULL; @@ -479,75 +479,113 @@ BOOL LLDXHardware::getInfo(BOOL vram_only) gWriteDebug("No DXDiag provider found! DirectX 9 not installed!\n"); goto LCleanup; } - if (SUCCEEDED(hr)) // if FAILED(hr) then dx9 is not installed - { - // Fill out a DXDIAG_INIT_PARAMS struct and pass it to IDxDiagContainer::Initialize - // Passing in TRUE for bAllowWHQLChecks, allows dxdiag to check if drivers are - // digital signed as logo'd by WHQL which may connect via internet to update - // WHQL certificates. - DXDIAG_INIT_PARAMS dx_diag_init_params; - ZeroMemory(&dx_diag_init_params, sizeof(DXDIAG_INIT_PARAMS)); - - dx_diag_init_params.dwSize = sizeof(DXDIAG_INIT_PARAMS); - dx_diag_init_params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION; - dx_diag_init_params.bAllowWHQLChecks = TRUE; - dx_diag_init_params.pReserved = NULL; + if (SUCCEEDED(hr)) // if FAILED(hr) then dx9 is not installed + { + // Fill out a DXDIAG_INIT_PARAMS struct and pass it to IDxDiagContainer::Initialize + // Passing in TRUE for bAllowWHQLChecks, allows dxdiag to check if drivers are + // digital signed as logo'd by WHQL which may connect via internet to update + // WHQL certificates. + DXDIAG_INIT_PARAMS dx_diag_init_params; + ZeroMemory(&dx_diag_init_params, sizeof(DXDIAG_INIT_PARAMS)); + + dx_diag_init_params.dwSize = sizeof(DXDIAG_INIT_PARAMS); + dx_diag_init_params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION; + dx_diag_init_params.bAllowWHQLChecks = TRUE; + dx_diag_init_params.pReserved = NULL; LL_DEBUGS("AppInit") << "dx_diag_providerp->Initialize" << LL_ENDL; - hr = dx_diag_providerp->Initialize(&dx_diag_init_params); - if(FAILED(hr)) + hr = dx_diag_providerp->Initialize(&dx_diag_init_params); + if (FAILED(hr)) { - goto LCleanup; + goto LCleanup; } LL_DEBUGS("AppInit") << "dx_diag_providerp->GetRootContainer" << LL_ENDL; - hr = dx_diag_providerp->GetRootContainer( &dx_diag_rootp ); - if(FAILED(hr) || !dx_diag_rootp) + hr = dx_diag_providerp->GetRootContainer(&dx_diag_rootp); + if (FAILED(hr) || !dx_diag_rootp) { - goto LCleanup; + goto LCleanup; } - HRESULT hr; - // Get display driver information LL_DEBUGS("AppInit") << "dx_diag_rootp->GetChildContainer" << LL_ENDL; hr = dx_diag_rootp->GetChildContainer(L"DxDiag_DisplayDevices", &devices_containerp); - if(FAILED(hr) || !devices_containerp) + if (FAILED(hr) || !devices_containerp) { - goto LCleanup; + goto LCleanup; } - // Get device 0 + DWORD device_count; + devices_containerp->GetNumberOfChildContainers(&device_count); + + // Get devices LL_DEBUGS("AppInit") << "devices_containerp->GetChildContainer" << LL_ENDL; - hr = devices_containerp->GetChildContainer(L"0", &device_containerp); - if(FAILED(hr) || !device_containerp) + + S32 vram_max = -1; + std::string gpu_string_max; + for (DWORD i = 0; i < device_count; ++i) { - goto LCleanup; - } - - DWORD vram = 0; + std::wstring str = L""; + str += std::to_wstring(i); + hr = devices_containerp->GetChildContainer(str.data(), &device_containerp); + if (FAILED(hr) || !device_containerp) + { + continue; + } + + DWORD vram = 0; + S32 detected_ram; + std::string ram_str; + + WCHAR deviceID[512]; + + get_wstring(device_containerp, L"szDeviceID", deviceID, 512); + + if (SUCCEEDED(GetVideoMemoryViaWMI(deviceID, &vram))) + { + detected_ram = vram / (1024 * 1024); + LL_INFOS("AppInit") << "VRAM for device[" << i << "]: " << detected_ram << " WMI" << LL_ENDL; + } + else + { + // Get the English VRAM string + ram_str = get_string(device_containerp, L"szDisplayMemoryEnglish"); + + // We don't need the device any more + SAFE_RELEASE(device_containerp); + + // Dump the string as an int into the structure + char* stopstring; + detected_ram = strtol(ram_str.c_str(), &stopstring, 10); + detected_ram = llmax(0, detected_ram - ((S32)(system_ram / (2 * device_count)) + 1)); // Ignore shared memory pool. - WCHAR deviceID[512]; + LL_INFOS("AppInit") << "VRAM for device[" << i << "]: " << detected_ram << " DX9 string: " << ram_str << LL_ENDL; + } - get_wstring(device_containerp, L"szDeviceID", deviceID, 512); + if (detected_ram > vram_max) + { + gpu_string_max = ram_str; + vram_max = detected_ram; + } + } - if (SUCCEEDED(GetVideoMemoryViaWMI(deviceID, &vram))) + if (vram_max <= 0) { - mVRAM = vram/(1024*1024); + gpu_string_max = ""; + LL_INFOS("AppInit") << "No dedicated VRAM. Using system memory instead." << LL_ENDL; + vram_max = (S32)system_ram / 2; // Integrated graphics perhaps? Use half system ram. } - else - { // Get the English VRAM string - std::string ram_str = get_string(device_containerp, L"szDisplayMemoryEnglish"); - // We don't need the device any more - SAFE_RELEASE(device_containerp); + LL_INFOS("AppInit") << "VRAM Detected: " << vram_max << " DX9 string: " << gpu_string_max << LL_ENDL; - // Dump the string as an int into the structure - char *stopstring; - mVRAM = strtol(ram_str.c_str(), &stopstring, 10); - LL_INFOS("AppInit") << "VRAM Detected: " << mVRAM << " DX9 string: " << ram_str << LL_ENDL; + if (vram_max == -1) + { + goto LCleanup; } + + mVRAM = vram_max; + if (vram_only) { ok = TRUE; @@ -555,15 +593,17 @@ BOOL LLDXHardware::getInfo(BOOL vram_only) } + + /* for now, we ONLY do vram_only the rest of this is commented out, to ensure no-one is tempted to use it - + // Now let's get device and driver information // Get the IDxDiagContainer object called "DxDiag_SystemDevices". // This call may take some time while dxdiag gathers the info. DWORD num_devices = 0; - WCHAR wszContainer[256]; + WCHAR wszContainer[256]; LL_DEBUGS("AppInit") << "dx_diag_rootp->GetChildContainer DxDiag_SystemDevices" << LL_ENDL; hr = dx_diag_rootp->GetChildContainer(L"DxDiag_SystemDevices", &system_device_containerp); if (FAILED(hr)) @@ -686,7 +726,7 @@ BOOL LLDXHardware::getInfo(BOOL vram_only) SAFE_RELEASE(device_containerp); } */ - } + } // dumpDevices(); ok = TRUE; @@ -718,8 +758,8 @@ LLSD LLDXHardware::getDisplayInfo() hr = CoInitialize(NULL); if (FAILED(hr)) { - LL_WARNS("AppInit") << "COM library initialization failed!" << LL_ENDL; - gWriteDebug("COM library initialization failed!\n"); + LL_WARNS() << "COM initialization failure!" << LL_ENDL; + gWriteDebug("COM initialization failure!\n"); return ret; } @@ -772,8 +812,6 @@ LLSD LLDXHardware::getDisplayInfo() goto LCleanup; } - HRESULT hr; - // Get display driver information LL_INFOS() << "dx_diag_rootp->GetChildContainer" << LL_ENDL; hr = dx_diag_rootp->GetChildContainer(L"DxDiag_DisplayDevices", &devices_containerp); diff --git a/indra/llwindow/lldxhardware.h b/indra/llwindow/lldxhardware.h index 0ce218b080..4e92d7a2f4 100644 --- a/indra/llwindow/lldxhardware.h +++ b/indra/llwindow/lldxhardware.h @@ -92,7 +92,7 @@ class LLDXHardware // Returns TRUE on success. // vram_only TRUE does a "light" probe. - BOOL getInfo(BOOL vram_only); + BOOL getInfo(BOOL vram_only, S32Megabytes sytem_ram); S32 getVRAM() const { return mVRAM; } diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp index 2740fce59a..47992c0e71 100644 --- a/indra/llwindow/llkeyboardwin32.cpp +++ b/indra/llwindow/llkeyboardwin32.cpp @@ -28,9 +28,7 @@ #include "linden_common.h" -#define WIN32_LEAN_AND_MEAN -#include -#include +#include "llwin32headerslean.h" #include "llkeyboardwin32.h" @@ -261,7 +259,7 @@ void LLKeyboardWin32::scanKeyboard() // *TODO: I KNOW there must be a better way of // interrogating the key state than this, using async key // state can cause ALL kinds of bugs - Doug - if (key < KEY_BUTTON0) + if ((key < KEY_BUTTON0) && ((key < '0') || (key > '9'))) { // ...under windows make sure the key actually still is down. // ...translate back to windows key diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 762155d8f9..756660716f 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -49,15 +49,18 @@ LLSplashScreen *gSplashScreenp = NULL; BOOL gDebugClicks = FALSE; BOOL gDebugWindowProc = FALSE; -const S32 gURLProtocolWhitelistCount = 4; -const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:"/*, "file:"*/ }; - +bool isWhitelistedProtocol(const std::string& escaped_url) { // CP: added a handler list - this is what's used to open the protocol and is based on registry entry // only meaningful difference currently is that file: protocols are opened using http: // since no protocol handler exists in registry for file: // Important - these lists should match - protocol to handler // Maestro: This list isn't referenced anywhere that I could find //const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" }; + for (const auto& protocol : { "secondlife:", "http:", "https:", "data:", "mailto:" }) + if (escaped_url.find(protocol) != std::string::npos) + return true; + return false; +} S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type) @@ -73,7 +76,7 @@ S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type) S32 result = 0; #if LL_MESA_HEADLESS // !!! *FIX: (???) LL_WARNS() << "OSMessageBox: " << text << LL_ENDL; - return OSBTN_OK; + result = OSBTN_OK; #elif LL_WINDOWS result = OSMessageBoxWin32(text, caption, type); #elif LL_DARWIN @@ -249,6 +252,48 @@ BOOL LLWindow::copyTextToPrimary(const LLWString &src) return FALSE; // fail } +#if LL_WINDOWS +#include +#endif + +int LLWindow::ShellEx(const std::string& command) +{ +#if LL_WINDOWS + llutf16string url_utf16 = L'"' + utf8str_to_utf16str(command) + L'"'; + SHELLEXECUTEINFO sei = { sizeof( sei ) }; + sei.fMask = SEE_MASK_NOASYNC; + sei.nShow = SW_SHOWNORMAL; + sei.lpVerb = L"open"; + sei.lpFile = url_utf16.c_str(); + const auto& code = ShellExecuteEx(&sei) ? 0 : GetLastError(); +#elif LL_DARWIN + CFURLRef urlRef; + CFStringRef stringRef = CFStringCreateWithCString(NULL, command.c_str(), kCFStringEncodingUTF8); + if (stringRef) + { + // This will succeed if the string is a full URL, including the http:// + // Note that URLs specified this way need to be properly percent-escaped. + urlRef = CFURLCreateWithString(NULL, stringRef, NULL); + + // Don't use CRURLCreateWithFileSystemPath -- only want valid URLs + CFRelease(stringRef); + } + + OSStatus code; + if (urlRef) + { + code = LSOpenCFURLRef(urlRef, NULL); + CFRelease(urlRef); + } + else code = -1; +#else // LL_LINUX or other modern unix, pray it has xdg-open + const auto& code = std::system(("xdg-open \"" + command + '"').c_str()); +#endif + + if (code) LL_WARNS() << "Failed to open \"" << command << "\" return code: " << code << LL_ENDL; + return code; +} + // static std::vector LLWindow::getDynamicFallbackFontList() { diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 0d53f5951b..2305b69e12 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -32,6 +32,7 @@ #include "llstring.h" #include "llcursortypes.h" #include "llsd.h" +#include "llinstancetracker.h" class LLSplashScreen; @@ -65,7 +66,8 @@ class LLWindow : public LLInstanceTracker // currently unused }; public: - virtual void show() = 0; + virtual void postInitialized() {} + virtual void show(bool focus = true) = 0; virtual void hide() = 0; virtual void close() = 0; virtual BOOL getVisible() = 0; @@ -82,7 +84,7 @@ class LLWindow : public LLInstanceTracker BOOL setSize(LLCoordScreen size); BOOL setSize(LLCoordWindow size); virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true); - virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL) = 0; + virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = NULL) = 0; virtual BOOL setCursorPosition(LLCoordWindow position) = 0; virtual BOOL getCursorPosition(LLCoordWindow *position) = 0; virtual void showCursor() = 0; @@ -167,7 +169,7 @@ class LLWindow : public LLInstanceTracker virtual void updateLanguageTextInputArea() {} virtual void interruptLanguageTextInput() {} virtual void spawnWebBrowser(const std::string& escaped_url, bool async) {}; - virtual void ShellEx(const std::string& command) {}; + static int ShellEx(const std::string& command); static std::vector getDynamicFallbackFontList(); @@ -289,11 +291,7 @@ class LLWindowManager // extern BOOL gDebugWindowProc; -// Protocols, like "http" and "https" we support in URLs -extern const S32 gURLProtocolWhitelistCount; -extern const std::string gURLProtocolWhitelist[]; -//extern const std::string gURLProtocolWhitelistHandler[]; - +bool isWhitelistedProtocol(const std::string& escaped_url); void simpleEscapeString ( std::string& stringIn ); #endif // _LL_window_h_ diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index 9712ae1d91..5b2e2f7952 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -185,6 +185,11 @@ void LLWindowCallbacks::handleResumeWatchdog(LLWindow *window) } +bool LLWindowCallbacks::handleDPIScaleChange(LLWindow *window, float xDPIScale, float yDPIScale, U32 width, U32 height) +{ + return false; +} + std::string LLWindowCallbacks::translateString(const char* tag) { return std::string(); diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index 7da5959700..aa349d29f3 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -79,7 +79,8 @@ class LLWindowCallbacks DND_LINK // Drop accepted would result in a "link" operation }; virtual DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, DragNDropAction action, std::string data); - + virtual bool handleDPIScaleChange(LLWindow *window, float xDPIScale, float yDPIScale, U32 width = 0, U32 height = 0); + virtual void handlePingWatchdog(LLWindow *window, const char * msg); virtual void handlePauseWatchdog(LLWindow *window); virtual void handleResumeWatchdog(LLWindow *window); diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h index 491f9afd2e..0364c5340d 100644 --- a/indra/llwindow/llwindowheadless.h +++ b/indra/llwindow/llwindowheadless.h @@ -32,7 +32,7 @@ class LLWindowHeadless : public LLWindow { public: - /*virtual*/ void show() {}; + /*virtual*/ void show(bool) {}; /*virtual*/ void hide() {}; /*virtual*/ void close() {}; /*virtual*/ BOOL getVisible() {return FALSE;}; @@ -48,7 +48,7 @@ class LLWindowHeadless : public LLWindow /*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;}; /*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;}; /*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;}; - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL) {return FALSE;}; + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = NULL) {return FALSE;}; /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;}; /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;}; /*virtual*/ void showCursor() {}; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 72c9f7628c..9be125958d 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com /** * @file llwindowmacosx.cpp * @brief Platform-dependent implementation of llwindow @@ -30,7 +32,6 @@ #include "llkeyboardmacosx.h" #include "llwindowcallbacks.h" -#include "llwindowmacosx-objc.h" #include "llpreeditor.h" #include "llerror.h" @@ -39,27 +40,28 @@ #include "lldir.h" #include "indra_constants.h" -#include #include +#include +#include extern BOOL gDebugWindowProc; +extern BOOL gUseMultGL; // culled from winuser.h //const S32 WHEEL_DELTA = 120; /* Value for rolling one detent */ // On the Mac, the scroll wheel reports a delta of 1 for each detent. // There's also acceleration for faster scrolling, based on a slider in the system preferences. -const S32 WHEEL_DELTA = 1; /* Value for rolling one detent */ const S32 BITS_PER_PIXEL = 32; const S32 MAX_NUM_RESOLUTIONS = 32; - +namespace +{ + NSKeyEventRef mRawKeyEvent = NULL; +} // // LLWindowMacOSX // -BOOL LLWindowMacOSX::sUseMultGL = FALSE; -WindowRef LLWindowMacOSX::sMediaWindow = NULL; - // Cross-platform bits: BOOL check_for_card(const char* RENDERER, const char* bad_card) @@ -67,17 +69,17 @@ BOOL check_for_card(const char* RENDERER, const char* bad_card) if (!strnicmp(RENDERER, bad_card, strlen(bad_card))) { std::string buffer = llformat( - "Your video card appears to be a %s, which Second Life does not support.\n" + "Your video card appears to be a %s, which Singularity does not support.\n" "\n" - "Second Life requires a video card with 32 Mb of memory or more, as well as\n" + "Singularity requires a video card with 32 Mb of memory or more, as well as\n" "multitexture support. We explicitly support nVidia GeForce 2 or better, \n" - "and ATI Radeon 8500 or better.\n" + "and ATI Radeon 8500 or better... A LOT better. lol\n" "\n" "If you own a supported card and continue to receive this message, try \n" "updating to the latest video card drivers. Otherwise look in the\n" "secondlife.com support section or e-mail technical support\n" "\n" - "You can try to run Second Life, but it will probably crash or run\n" + "You can try to run Singularity, but it will probably crash or run\n" "very slowly. Try anyway?", bad_card); S32 button = OSMessageBox(buffer.c_str(), "Unsupported video card", OSMB_YESNO); @@ -98,105 +100,9 @@ BOOL check_for_card(const char* RENDERER, const char* bad_card) // We may want to base this on the setting of _DEBUG... #define CAPTURE_ALL_DISPLAYS 0 -static double getDictDouble (CFDictionaryRef refDict, CFStringRef key); +//static double getDictDouble (CFDictionaryRef refDict, CFStringRef key); static long getDictLong (CFDictionaryRef refDict, CFStringRef key); - - - -// CarbonEvents we're interested in. -static EventTypeSpec WindowHandlerEventList[] = -{ - // Window-related events - { kEventClassWindow, kEventWindowActivated }, - { kEventClassWindow, kEventWindowDeactivated }, - { kEventClassWindow, kEventWindowShown }, - { kEventClassWindow, kEventWindowHidden }, - { kEventClassWindow, kEventWindowCollapsed }, - { kEventClassWindow, kEventWindowExpanded }, - { kEventClassWindow, kEventWindowGetClickActivation }, - { kEventClassWindow, kEventWindowClose }, - { kEventClassWindow, kEventWindowBoundsChanging }, - { kEventClassWindow, kEventWindowBoundsChanged }, - { kEventClassWindow, kEventWindowGetIdealSize }, - - // Mouse events - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseWheelMoved }, - { kEventClassMouse, kEventMouseMoved }, - - // Keyboard events - // No longer handle raw key down events directly. - // When text input events come in, extract the raw key events from them and process at that point. - // This allows input methods to eat keystrokes the way they're supposed to. -// { kEventClassKeyboard, kEventRawKeyDown }, -// { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - - // Text input events - { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, - { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, - { kEventClassTextInput, kEventTextInputOffsetToPos }, - { kEventClassTextInput, kEventTextInputPosToOffset }, - { kEventClassTextInput, kEventTextInputShowHideBottomWindow }, - { kEventClassTextInput, kEventTextInputGetSelectedText }, - { kEventClassTextInput, kEventTextInputFilterText }, - - // TSM Document Access events (advanced input method support) - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetLength }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetSelectedRange }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetCharacters }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetFont }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetGlyphInfo }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessLockDocument }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessUnlockDocument } -}; - -static EventTypeSpec GlobalHandlerEventList[] = -{ - // Mouse events - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseWheelMoved }, - { kEventClassMouse, kEventMouseMoved }, - - // Keyboard events - // No longer handle raw key down events directly. - // When text input events come in, extract the raw key events from them and process at that point. - // This allows input methods to eat keystrokes the way they're supposed to. -// { kEventClassKeyboard, kEventRawKeyDown }, -// { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - - // Text input events - { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, - { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, - { kEventClassTextInput, kEventTextInputOffsetToPos }, - { kEventClassTextInput, kEventTextInputPosToOffset }, - { kEventClassTextInput, kEventTextInputShowHideBottomWindow }, - { kEventClassTextInput, kEventTextInputGetSelectedText }, - { kEventClassTextInput, kEventTextInputFilterText }, - - // TSM Document Access events (advanced input method support) - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetLength }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetSelectedRange }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetCharacters }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetFont }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetGlyphInfo }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessLockDocument }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessUnlockDocument } -}; - -static EventTypeSpec CommandHandlerEventList[] = -{ - { kEventClassCommand, kEventCommandProcess } -}; - // MBW -- HACK ALERT // On the Mac, to put up an OS dialog in full screen mode, we must first switch OUT of full screen mode. // The proper way to do this is to bracket the dialog with calls to beforeDialog() and afterDialog(), but these @@ -204,13 +110,11 @@ static EventTypeSpec CommandHandlerEventList[] = // This assumes that there will be only one object of this class at any time. Hopefully this is true. static LLWindowMacOSX *gWindowImplementation = NULL; - - LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, - const S32 vsync_mode, + S32 vsync_setting, BOOL ignore_pixel_depth, U32 fsaa_samples) : LLWindow(NULL, fullscreen, flags) @@ -233,8 +137,6 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mContext = NULL; mPixelFormat = NULL; mDisplay = CGMainDisplayID(); - mOldDisplayMode = NULL; - mTimer = NULL; mSimulatedRightClick = FALSE; mLastModifiers = 0; mHandsOffEvents = FALSE; @@ -246,70 +148,40 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mOverrideAspectRatio = 0.f; mMaximized = FALSE; mMinimized = FALSE; - mTSMDocument = NULL; // Just in case. mLanguageTextInputAllowed = FALSE; - mTSMScriptCode = 0; - mTSMLangCode = 0; mPreeditor = NULL; - mRawKeyEvent = NULL; mFSAASamples = fsaa_samples; - mVsyncMode = vsync_mode; mForceRebuild = FALSE; - // For reasons that aren't clear to me, LLTimers seem to be created in the "started" state. - // Since the started state of this one is used to track whether the NMRec has been installed, it wants to start out in the "stopped" state. - mBounceTimer.stop(); - // Get the original aspect ratio of the main device. mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay); // Stash the window title - strcpy((char*)mWindowTitle + 1, title.c_str()); /* Flawfinder: ignore */ - mWindowTitle[0] = title.length(); - - mEventHandlerUPP = NewEventHandlerUPP(staticEventHandler); - mMoveEventCampartorUPP = NewEventComparatorUPP(staticMoveEventComparator); - mGlobalHandlerRef = NULL; - mWindowHandlerRef = NULL; + mWindowTitle = title; + //mWindowTitle[0] = title.length(); mDragOverrideCursor = -1; - // We're not clipping yet - SetRect( &mOldMouseClip, 0, 0, 0, 0 ); - // Set up global event handlers (the fullscreen case needs this) - InstallStandardEventHandler(GetApplicationEventTarget()); + //InstallStandardEventHandler(GetApplicationEventTarget()); // Stash an object pointer for OSMessageBox() gWindowImplementation = this; - // Create the GL context and set it up for windowed or fullscreen, as appropriate. - if(createContext(x, y, width, height, 32, fullscreen, vsync_mode)) + if(createContext(x, y, width, height, 32, fullscreen, vsync_setting)) { if(mWindow != NULL) { - // MBW -- XXX -- I think we can now do this here? - // Constrain the window to the screen it's mostly on, resizing if necessary. - ConstrainWindowToScreen( - mWindow, - kWindowStructureRgn, - kWindowConstrainMayResize | - // kWindowConstrainStandardOptions | - 0, - NULL, - NULL); - - MacShowWindow(mWindow); - BringToFront(mWindow); + makeWindowOrderFront(mWindow); } if (!gGLManager.initGL()) { setupFailure( - "Second Life is unable to run because your video card drivers\n" + "Singularity is unable to run because your video card drivers\n" "are out of date or unsupported. Please make sure you have\n" "the latest video card drivers installed.\n" - "If you continue to receive this message, contact customer service.", + "If you continue to receive this message, contact support.", "Error", OSMB_OK); return; @@ -318,483 +190,452 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, //start with arrow cursor initCursors(); setCursor( UI_CURSOR_ARROW ); + + allowLanguageTextInput(NULL, FALSE); } mCallbacks = callbacks; stop_glerror(); + + } -BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, const S32 vsync_mode) -{ - OSStatus err; - BOOL glNeedsInit = FALSE; - - if(mGlobalHandlerRef == NULL) - { - InstallApplicationEventHandler(mEventHandlerUPP, GetEventTypeCount (CommandHandlerEventList), CommandHandlerEventList, (void*)this, &mGlobalHandlerRef); - } - - mFullscreen = fullscreen; - - if (mFullscreen && (mOldDisplayMode == NULL)) - { - LL_INFOS("Window") << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL; - - // NOTE: The refresh rate will be REPORTED AS 0 for many DVI and notebook displays. Plan accordingly. - double refresh = getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate); +// These functions are used as wrappers for our internal event handling callbacks. +// It's a good idea to wrap these to avoid reworking more code than we need to within LLWindow. - // If the requested width or height is 0, find the best default for the monitor. - if((width == 0) || (height == 0)) - { - // Scan through the list of modes, looking for one which has: - // height between 700 and 800 - // aspect ratio closest to the user's original mode - S32 resolutionCount = 0; - LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount); +bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask) +{ + mRawKeyEvent = event; + bool retVal = gKeyboard->handleKeyUp(key, mask); + mRawKeyEvent = NULL; + return retVal; +} - if(resolutionList != NULL) - { - F32 closestAspect = 0; - U32 closestHeight = 0; - U32 closestWidth = 0; - int i; +bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask) +{ + mRawKeyEvent = event; + bool retVal = gKeyboard->handleKeyDown(key, mask); + mRawKeyEvent = NULL; + return retVal; +} - LL_DEBUGS("Window") << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL; +void callResetKeys() +{ + gKeyboard->resetKeys(); +} - for(i=0; i < resolutionCount; i++) - { - F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight; +bool callUnicodeCallback(wchar_t character, unsigned int mask) +{ + NativeKeyEventData eventData; + + memset(&eventData, 0, sizeof(NativeKeyEventData)); + + eventData.mKeyEvent = NativeKeyEventData::KEYCHAR; + eventData.mEventType = 0; + eventData.mEventModifiers = mask; + eventData.mEventKeyCode = 0; + eventData.mEventChars = character; + eventData.mEventUnmodChars = character; + eventData.mEventRepeat = false; + + mRawKeyEvent = &eventData; + + bool result = gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask); + mRawKeyEvent = NULL; + return result; +} - LL_DEBUGS("Window") << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL; +void callFocus() +{ + if (gWindowImplementation) + { + gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); + } +} - if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) && - (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio))) - { - LL_DEBUGS("Window") << " (new closest mode) " << LL_ENDL; +void callFocusLost() +{ + if (gWindowImplementation) + { + gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); + } +} - // This is the closest mode we've seen yet. - closestWidth = resolutionList[i].mWidth; - closestHeight = resolutionList[i].mHeight; - closestAspect = aspect; - } - } +void callRightMouseDown(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + gWindowImplementation->getCallbacks()->handleRightMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - width = closestWidth; - height = closestHeight; - } - } +void callRightMouseUp(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + gWindowImplementation->getCallbacks()->handleRightMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - if((width == 0) || (height == 0)) - { - // Mode search failed for some reason. Use the old-school default. - width = 1024; - height = 768; - } +void callLeftMouseDown(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + gWindowImplementation->getCallbacks()->handleMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - if (true) - { - // Fullscreen support - CFDictionaryRef refDisplayMode = 0; - boolean_t exactMatch = false; - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - CGCaptureAllDisplays (); -#else - // Capture only the main display (useful for debugging) - CGDisplayCapture (mDisplay); -#endif +void callLeftMouseUp(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + gWindowImplementation->getCallbacks()->handleMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); + +} - // Switch the display to the desired resolution and refresh - refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate( - mDisplay, - BITS_PER_PIXEL, - width, - height, - refresh, - &exactMatch); +void callDoubleClick(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + gWindowImplementation->getCallbacks()->handleDoubleClick(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - if (refDisplayMode) - { - LL_DEBUGS("Window") << "createContext: switching display resolution" << LL_ENDL; - mOldDisplayMode = CGDisplayCurrentMode (mDisplay); - CGDisplaySwitchToMode (mDisplay, refDisplayMode); - // CFRelease(refDisplayMode); +void callResize(unsigned int width, unsigned int height) +{ + if (gWindowImplementation != NULL) + { + gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height); + } +} - AddEventTypesToHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList); - } +void callMouseMoved(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + S32 deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} +void callScrollMoved(float delta) +{ + gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, delta); +} - mFullscreen = TRUE; - mFullscreenWidth = CGDisplayPixelsWide(mDisplay); - mFullscreenHeight = CGDisplayPixelsHigh(mDisplay); - mFullscreenBits = CGDisplayBitsPerPixel(mDisplay); - mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate)); +void callMouseExit() +{ + gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation); +} - LL_INFOS("Window") << "Running at " << mFullscreenWidth - << "x" << mFullscreenHeight - << "x" << mFullscreenBits - << " @ " << mFullscreenRefresh - << LL_ENDL; - } - else - { - // No fullscreen support - mFullscreen = FALSE; - mFullscreenWidth = -1; - mFullscreenHeight = -1; - mFullscreenBits = -1; - mFullscreenRefresh = -1; - - std::string error= llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height); - OSMessageBox(error, "Error", OSMB_OK); - } +void callWindowFocus() +{ + if ( gWindowImplementation && gWindowImplementation->getCallbacks() ) + { + gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); + // Reset badge count + updateBadge(0); } - - if(!mFullscreen && (mWindow == NULL)) + else { - //int displayWidth = CGDisplayPixelsWide(mDisplay); - //int displayHeight = CGDisplayPixelsHigh(mDisplay); - //const int menuBarPlusTitleBar = 44; // Ugly magic number. - - LL_DEBUGS("Window") << "createContext: creating window" << LL_ENDL; - - mPreviousWindowRect.left = (long) x; - mPreviousWindowRect.right = (long) x + width; - mPreviousWindowRect.top = (long) y; - mPreviousWindowRect.bottom = (long) y + height; - - //----------------------------------------------------------------------- - // Create the window - //----------------------------------------------------------------------- - mWindow = NewCWindow( - NULL, - &mPreviousWindowRect, - mWindowTitle, - false, // Create the window invisible. Whoever calls createContext() should show it after any moving/resizing. - // noGrowDocProc, // Window with no grow box and no zoom box - zoomDocProc, // Window with a grow box and a zoom box - // zoomNoGrow, // Window with a zoom box but no grow box - kFirstWindowOfClass, - true, - (long)this); + LL_WARNS("COCOA") << "Window Implementation or callbacks not yet initialized." << LL_ENDL; + } - if (!mWindow) - { - setupFailure("Window creation error", "Error", OSMB_OK); - return FALSE; - } - // Turn on live resize. - // For this to work correctly, we need to be able to call LLViewerWindow::draw from - // the event handler for kEventWindowBoundsChanged. It's not clear that we have access from here. - // err = ChangeWindowAttributes(mWindow, kWindowLiveResizeAttribute, 0); +} - // Set up window event handlers (some window-related events ONLY go to window handlers.) - InstallStandardEventHandler(GetWindowEventTarget(mWindow)); - InstallWindowEventHandler(mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler -#if LL_OS_DRAGDROP_ENABLED - InstallTrackingHandler( dragTrackingHandler, mWindow, (void*)this ); - InstallReceiveHandler( dragReceiveHandler, mWindow, (void*)this ); -#endif // LL_OS_DRAGDROP_ENABLED - } +void callWindowUnfocus() +{ + gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); +} +void callWindowHide() +{ + if ( gWindowImplementation && gWindowImplementation->getCallbacks() ) { - // Create and initialize our TSM document for language text input. - // If an error occured, we can do nothing better than simply ignore it. - // mTSMDocument will be kept NULL in case. - if (mTSMDocument) - { - DeactivateTSMDocument(mTSMDocument); - DeleteTSMDocument(mTSMDocument); - mTSMDocument = NULL; - } - static InterfaceTypeList types = { kUnicodeDocument }; - err = NewTSMDocument(1, types, &mTSMDocument, 0); - if (err != noErr) - { - LL_WARNS("Window") << "createContext: couldn't create a TSMDocument (" << err << ")" << LL_ENDL; - } - if (mTSMDocument) - { - ActivateTSMDocument(mTSMDocument); - allowLanguageTextInput(NULL, FALSE); - } + gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, false); } +} - if(mContext == NULL) +void callWindowUnhide() +{ + if ( gWindowImplementation && gWindowImplementation->getCallbacks() ) { - AGLRendererInfo rendererInfo = NULL; + gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, true); + } +} - //----------------------------------------------------------------------- - // Create GL drawing context - //----------------------------------------------------------------------- +void callDeltaUpdate(double *delta, MASK mask) +{ + gWindowImplementation->updateMouseDeltas(delta); +} - if(mPixelFormat == NULL) - { - if(mFullscreen) - { - GLint fullscreenAttrib[] = - { - AGL_RGBA, - AGL_FULLSCREEN, - AGL_NO_RECOVERY, - AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0, - AGL_SAMPLES_ARB, mFSAASamples, - AGL_DOUBLEBUFFER, - AGL_CLOSEST_POLICY, - AGL_ACCELERATED, - AGL_RED_SIZE, 8, - AGL_GREEN_SIZE, 8, - AGL_BLUE_SIZE, 8, - AGL_ALPHA_SIZE, 8, - AGL_DEPTH_SIZE, 24, - AGL_STENCIL_SIZE, 8, - AGL_NONE - }; - - LL_DEBUGS("Window") << "createContext: creating fullscreen pixelformat" << LL_ENDL; - - GDHandle gdhDisplay = NULL; - err = DMGetGDeviceByDisplayID ((DisplayIDType)mDisplay, &gdhDisplay, false); - - mPixelFormat = aglChoosePixelFormat(&gdhDisplay, 1, fullscreenAttrib); - rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1); - } - else - { - // NOTE from Leslie: - // - // AGL_NO_RECOVERY, when combined with AGL_ACCELERATED prevents software rendering - // fallback which means we won't hvae shaders that compile and link but then don't - // work. The drawback is that our shader compilation will be a bit more finicky though. +void callMiddleMouseDown(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + S32 deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMiddleMouseDown(gWindowImplementation, outCoords, mask); +} - GLint windowedAttrib[] = - { - AGL_RGBA, - AGL_NO_RECOVERY, - AGL_DOUBLEBUFFER, - AGL_CLOSEST_POLICY, - AGL_ACCELERATED, - AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0, - AGL_SAMPLES_ARB, mFSAASamples, - AGL_RED_SIZE, 8, - AGL_GREEN_SIZE, 8, - AGL_BLUE_SIZE, 8, - AGL_ALPHA_SIZE, 8, - AGL_DEPTH_SIZE, 24, - AGL_STENCIL_SIZE, 8, - AGL_NONE - }; - - LL_DEBUGS("Window") << "createContext: creating windowed pixelformat" << LL_ENDL; - - mPixelFormat = aglChoosePixelFormat(NULL, 0, windowedAttrib); - - GDHandle gdhDisplay = GetMainDevice(); - rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1); - } +void callMiddleMouseUp(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + S32 deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask); +} - // May want to get the real error text like this: - // (char *) aglErrorString(aglGetError()); +void callModifier(MASK mask) +{ + gKeyboard->handleModifier(mask); +} - if(aglGetError() != AGL_NO_ERROR) - { - setupFailure("Can't find suitable pixel format", "Error", OSMB_OK); - return FALSE; - } - } +void callHandleDragEntered(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING); +} - if(mPixelFormat) - { - LL_DEBUGS("Window") << "createContext: creating GL context" << LL_ENDL; - mContext = aglCreateContext(mPixelFormat, NULL); - } +void callHandleDragExited(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING); +} - if(mContext == NULL) - { - setupFailure("Can't make GL context", "Error", OSMB_OK); - return FALSE; - } +void callHandleDragUpdated(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK); +} - gGLManager.mVRAM = 0; +void callHandleDragDropped(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED); +} - if(rendererInfo != NULL) +void callQuitHandler() +{ + if (gWindowImplementation) + { + if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation)) { - GLint result; - - if(aglDescribeRenderer(rendererInfo, AGL_VIDEO_MEMORY, &result)) - { - // LL_INFOS() << "createContext: aglDescribeRenderer(AGL_VIDEO_MEMORY) returned " << result << LL_ENDL; - gGLManager.mVRAM = result / (1024 * 1024); - } - else - { - // LL_INFOS() << "createContext: aglDescribeRenderer(AGL_VIDEO_MEMORY) failed." << LL_ENDL; - } - - // This could be useful at some point, if it takes into account the memory already used by screen buffers, etc... - if(aglDescribeRenderer(rendererInfo, AGL_TEXTURE_MEMORY, &result)) - { - // LL_INFOS() << "createContext: aglDescribeRenderer(AGL_TEXTURE_MEMORY) returned " << result << LL_ENDL; - } - else - { - // LL_INFOS() << "createContext: aglDescribeRenderer(AGL_TEXTURE_MEMORY) failed." << LL_ENDL; - } - - aglDestroyRendererInfo(rendererInfo); + gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation); } - - // Since we just created the context, it needs to be set up. - glNeedsInit = TRUE; } +} - // Hook up the context to a drawable - if (mFullscreen && (mOldDisplayMode != NULL)) +void getPreeditSelectionRange(int *position, int *length) +{ + if (gWindowImplementation->getPreeditor()) { - // We successfully captured the display. Use a fullscreen drawable - - LL_DEBUGS("Window") << "createContext: attaching fullscreen drawable" << LL_ENDL; - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - aglDisable (mContext, AGL_FS_CAPTURE_SINGLE); -#else - // Capture only the main display (useful for debugging) - aglEnable (mContext, AGL_FS_CAPTURE_SINGLE); -#endif - - if (!aglSetFullScreen (mContext, 0, 0, 0, 0)) - { - setupFailure("Can't set GL fullscreen", "Error", OSMB_OK); - return FALSE; - } + gWindowImplementation->getPreeditor()->getSelectionRange(position, length); } - else if(!mFullscreen && (mWindow != NULL)) +} + +void getPreeditMarkedRange(int *position, int *length) +{ + if (gWindowImplementation->getPreeditor()) { - LL_DEBUGS("Window") << "createContext: attaching windowed drawable" << LL_ENDL; + gWindowImplementation->getPreeditor()->getPreeditRange(position, length); + } +} - // We created a window. Use it as the drawable. - if(!aglSetDrawable(mContext, GetWindowPort (mWindow))) - { - setupFailure("Can't set GL drawable", "Error", OSMB_OK); - return FALSE; - } +void setPreeditMarkedRange(int position, int length) +{ + if (gWindowImplementation->getPreeditor()) + { + gWindowImplementation->getPreeditor()->markAsPreedit(position, length); } - else +} + +bool handleUnicodeCharacter(wchar_t c) +{ + bool success = false; + if (gWindowImplementation->getPreeditor()) { - setupFailure("Can't get fullscreen or windowed drawable.", "Error", OSMB_OK); - return FALSE; + success = gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c); } + + return success; +} - if(mContext != NULL) +void resetPreedit() +{ + if (gWindowImplementation->getPreeditor()) { - LL_DEBUGS("Window") << "createContext: setting current context" << LL_ENDL; + gWindowImplementation->getPreeditor()->resetPreedit(); + } +} - if (!aglSetCurrentContext(mContext)) +// For reasons of convenience, handle IME updates here. +// This largely mirrors the old implementation, only sans the carbon parameters. +void setMarkedText(unsigned short *unitext, unsigned int *replacementRange, long text_len, attributedStringInfo segments) +{ + if (gWindowImplementation->getPreeditor()) + { + LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); + preeditor->resetPreedit(); + // This should be a viable replacement for the kEventParamTextInputSendReplaceRange parameter. + if (replacementRange[0] < replacementRange[1]) { - setupFailure("Can't activate GL rendering context", "Error", OSMB_OK); - return FALSE; + const LLWString& text = preeditor->getPreeditString(); + const S32 location = wstring_wstring_length_from_utf16_length(text, 0, replacementRange[0]); + const S32 length = wstring_wstring_length_from_utf16_length(text, location, replacementRange[1]); + preeditor->markAsPreedit(location, length); } + + LLWString fix_str = utf16str_to_wstring(llutf16string(unitext, text_len)); + + S32 caret_position = fix_str.length(); + + preeditor->updatePreedit(fix_str, segments.seg_lengths, segments.seg_standouts, caret_position); } +} - if(glNeedsInit) +void getPreeditLocation(float *location, unsigned int length) +{ + if (gWindowImplementation->getPreeditor()) { - // Check for some explicitly unsupported cards. - const char* RENDERER = (const char*) glGetString(GL_RENDERER); - - const char* CARD_LIST[] = - { "RAGE 128", - "RIVA TNT2", - "Intel 810", - "3Dfx/Voodoo3", - "Radeon 7000", - "Radeon 7200", - "Radeon 7500", - "Radeon DDR", - "Radeon VE", - "GDI Generic" }; - const S32 CARD_COUNT = LL_ARRAY_SIZE(CARD_LIST); - - // Future candidates: - // ProSavage/Twister - // SuperSavage + LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); + LLCoordGL coord; + LLCoordScreen screen; + LLRect rect; + + preeditor->getPreeditLocation(length, &coord, &rect, NULL); + + float c[4] = {static_cast(coord.mX), + static_cast(coord.mY), 0, 0}; + + convertRectToScreen(gWindowImplementation->getWindow(), c); + + location[0] = c[0]; + location[1] = c[1]; + } +} - S32 i; - for (i = 0; i < CARD_COUNT; i++) +void LLWindowMacOSX::updateMouseDeltas(double* deltas) +{ + if (mCursorDecoupled) + { + mCursorLastEventDeltaX = ll_round(deltas[0]); + mCursorLastEventDeltaY = ll_round(-deltas[1]); + + if (mCursorIgnoreNextDelta) { - if (check_for_card(RENDERER, CARD_LIST[i])) - { - close(); - return FALSE; - } + mCursorLastEventDeltaX = 0; + mCursorLastEventDeltaY = 0; + mCursorIgnoreNextDelta = FALSE; } + } else { + mCursorLastEventDeltaX = 0; + mCursorLastEventDeltaY = 0; } +} - GLint colorBits, alphaBits, depthBits, stencilBits; +void LLWindowMacOSX::getMouseDeltas(S32* delta) +{ + delta[0] = mCursorLastEventDeltaX; + delta[1] = mCursorLastEventDeltaY; +} - if( !aglDescribePixelFormat(mPixelFormat, AGL_BUFFER_SIZE, &colorBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_ALPHA_SIZE, &alphaBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_DEPTH_SIZE, &depthBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_STENCIL_SIZE, &stencilBits)) +BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, S32 vsync_setting) +{ + mFullscreen = fullscreen; + + if (mWindow == NULL) { - close(); - setupFailure("Can't get pixel format description", "Error", OSMB_OK); - return FALSE; + mWindow = getMainAppWindow(); } - LL_INFOS("GLInit") << "GL buffer: Color Bits " << S32(colorBits) - << " Alpha Bits " << S32(alphaBits) - << " Depth Bits " << S32(depthBits) - << " Stencil Bits" << S32(stencilBits) - << LL_ENDL; - - if (colorBits < 32) + // Disable vertical sync for swap + bool vsync_enabled; + GLint frames_per_swap; + switch (vsync_setting) { - close(); - setupFailure( - "Second Life requires True Color (32-bit) to run in a window.\n" - "Please go to Control Panels -> Display -> Settings and\n" - "set the screen to 32-bit color.\n" - "Alternately, if you choose to run fullscreen, Second Life\n" - "will automatically adjust the screen each time it runs.", - "Error", - OSMB_OK); - return FALSE; + //default: + case 0: //E_VSYNC_DISABLED: + { + LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL; + vsync_enabled = false; + frames_per_swap = 0; + break; } - - if (alphaBits < 8) + case -1: //E_VSYNC_ADAPTIVE: + default: //case E_VSYNC_NORMAL: { - close(); - setupFailure( - "Second Life is unable to run because it can't get an 8 bit alpha\n" - "channel. Usually this is due to video card driver issues.\n" - "Please make sure you have the latest video card drivers installed.\n" - "Also be sure your monitor is set to True Color (32-bit) in\n" - "Control Panels -> Display -> Settings.\n" - "If you continue to receive this message, contact customer service.", - "Error", - OSMB_OK); - return FALSE; + LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL; + vsync_enabled = true; + frames_per_swap = 1; + break; + } } - // Disable vertical sync for swap - GLint frames_per_swap = 0; - if (vsync_mode != 1) + if(mContext == NULL) { - LL_DEBUGS("GLInit") << "Disabling vertical sync" << LL_ENDL; - frames_per_swap = 0; + // Our OpenGL view is already defined within SecondLife.xib. + // Get the view instead. + mGLView = createOpenGLView(mWindow, mFSAASamples, vsync_enabled); + mContext = getCGLContextObj(mGLView); + + gGLManager.mVRAM = getVramSize(mGLView); } - else + + // This sets up our view to recieve text from our non-inline text input window. + setupInputWindow(mWindow, mGLView); + + // Hook up the context to a drawable + + if(mContext != NULL) { - LL_DEBUGS("GLinit") << "Keeping vertical sync" << LL_ENDL; - frames_per_swap = 1; + + + CGLError err = CGLSetCurrentContext(mContext); + if (err != kCGLNoError) + { + setupFailure("Can't activate GL rendering context", "Error", OSMB_OK); + return FALSE; + } } - aglSetInteger(mContext, AGL_SWAP_INTERVAL, &frames_per_swap); + + CGLSetParameter(mContext, kCGLCPSwapInterval, &frames_per_swap); //enable multi-threaded OpenGL - if (sUseMultGL) + if (gUseMultGL) { CGLError cgl_err; CGLContextObj ctx = CGLGetCurrentContext(); @@ -810,114 +651,22 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL; } } - - // Don't need to get the current gamma, since there's a call that restores it to the system defaults. + makeFirstResponder(mWindow, mGLView); + return TRUE; } -// changing fullscreen resolution, or switching between windowed and fullscreen mode. -BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp) +// We only support OS X 10.7's fullscreen app mode which is literally a full screen window that fills a virtual desktop. +// This makes this method obsolete. +BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp) { - BOOL needsRebuild = FALSE; - BOOL result = true; + return FALSE; +} - if(fullscreen) - { - if(mFullscreen) - { - // Switching resolutions in fullscreen mode. Don't need to rebuild for this. - // Fullscreen support - CFDictionaryRef refDisplayMode = 0; - boolean_t exactMatch = false; - - // Switch the display to the desired resolution and refresh - refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate( - mDisplay, - BITS_PER_PIXEL, - size.mX, - size.mY, - getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate), - &exactMatch); - - if (refDisplayMode) - { - CGDisplaySwitchToMode (mDisplay, refDisplayMode); - // CFRelease(refDisplayMode); - } - - mFullscreenWidth = CGDisplayPixelsWide(mDisplay); - mFullscreenHeight = CGDisplayPixelsHigh(mDisplay); - mFullscreenBits = CGDisplayBitsPerPixel(mDisplay); - mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate)); - - LL_INFOS("Window") << "Switched resolution to " << mFullscreenWidth - << "x" << mFullscreenHeight - << "x" << mFullscreenBits - << " @ " << mFullscreenRefresh - << LL_ENDL; - - // Update the GL context to the new screen size - if (!aglUpdateContext(mContext)) - { - setupFailure("Can't set GL fullscreen", "Error", OSMB_OK); - result = FALSE; - } - } - else - { - // Switching from windowed to fullscreen - needsRebuild = TRUE; - } - } - else - { - if(mFullscreen) - { - // Switching from fullscreen to windowed - needsRebuild = TRUE; - } - else - { - // Windowed to windowed -- not sure why we would be called like this. Just change the window size. - // The bounds changed event handler will do the rest. - if(mWindow != NULL) - { - ::SizeWindow(mWindow, size.mX, size.mY, true); - } - } - } - - stop_glerror(); - if(needsRebuild || mForceRebuild) - { - mForceRebuild = FALSE; - destroyContext(); - result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, vsync_mode); - if (result) - { - if(mWindow != NULL) - { - MacShowWindow(mWindow); - BringToFront(mWindow); - } - - llverify(gGLManager.initGL()); - - //start with arrow cursor - initCursors(); - setCursor( UI_CURSOR_ARROW ); - } - } - - stop_glerror(); - - return result; -} - -void LLWindowMacOSX::destroyContext() -{ - if (!mContext) +void LLWindowMacOSX::destroyContext() +{ + if (!mContext) { // We don't have a context return; @@ -926,32 +675,7 @@ void LLWindowMacOSX::destroyContext() if(mContext != NULL) { LL_DEBUGS("Window") << "destroyContext: unhooking drawable " << LL_ENDL; - - aglSetCurrentContext (NULL); - aglSetDrawable(mContext, NULL); - } - - // Make sure the display resolution gets restored - if(mOldDisplayMode != NULL) - { - LL_DEBUGS("Window") << "destroyContext: restoring display resolution " << LL_ENDL; - - CGDisplaySwitchToMode (mDisplay, mOldDisplayMode); - -#if CAPTURE_ALL_DISPLAYS - // Uncapture all displays (may want to do this for final build) - CGReleaseAllDisplays (); -#else - // Uncapture only the main display (useful for debugging) - CGDisplayRelease (mDisplay); -#endif - - // CFRelease(mOldDisplayMode); - - mOldDisplayMode = NULL; - - // Remove the global event handlers the fullscreen case needed - RemoveEventTypesFromHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList); + CGLSetCurrentContext(NULL); } // Clean up remaining GL state before blowing away window @@ -960,49 +684,29 @@ void LLWindowMacOSX::destroyContext() // Clean up the pixel format if(mPixelFormat != NULL) { - LL_DEBUGS("Window") << "destroyContext: destroying pixel format " << LL_ENDL; - aglDestroyPixelFormat(mPixelFormat); + CGLDestroyPixelFormat(mPixelFormat); mPixelFormat = NULL; } - // Remove any Carbon Event handlers we installed - if(mGlobalHandlerRef != NULL) - { - LL_DEBUGS("Window") << "destroyContext: removing global event handler" << LL_ENDL; - RemoveEventHandler(mGlobalHandlerRef); - mGlobalHandlerRef = NULL; - } - - if(mWindowHandlerRef != NULL) + // Destroy our LLOpenGLView + if(mGLView != NULL) { - LL_DEBUGS("Window") << "destroyContext: removing window event handler" << LL_ENDL; - RemoveEventHandler(mWindowHandlerRef); - mWindowHandlerRef = NULL; + removeGLView(mGLView); + mGLView = NULL; } - - // Cleanup any TSM document we created. - if(mTSMDocument != NULL) + + // Clean up the GL context + if(mContext != NULL) { - LL_DEBUGS("Window") << "destroyContext: deleting TSM document" << LL_ENDL; - DeactivateTSMDocument(mTSMDocument); - DeleteTSMDocument(mTSMDocument); - mTSMDocument = NULL; + CGLDestroyContext(mContext); } - + // Close the window if(mWindow != NULL) { - LL_DEBUGS("Window") << "destroyContext: disposing window" << LL_ENDL; - DisposeWindow(mWindow); - mWindow = NULL; - } - - // Clean up the GL context - if(mContext != NULL) - { - LL_DEBUGS("Window") << "destroyContext: destroying GL context" << LL_ENDL; - aglDestroyContext(mContext); - mContext = NULL; + NSWindowRef dead_window = mWindow; + mWindow = NULL; + closeWindow(dead_window); } } @@ -1021,19 +725,13 @@ LLWindowMacOSX::~LLWindowMacOSX() } -void LLWindowMacOSX::show() +void LLWindowMacOSX::show(bool) { - if(IsWindowCollapsed(mWindow)) - CollapseWindow(mWindow, false); - - MacShowWindow(mWindow); - BringToFront(mWindow); } void LLWindowMacOSX::hide() { setMouseClipping(FALSE); - HideWindow(mWindow); } //virtual @@ -1041,7 +739,6 @@ void LLWindowMacOSX::minimize() { setMouseClipping(FALSE); showCursor(); - CollapseWindow(mWindow, true); } //virtual @@ -1070,7 +767,7 @@ void LLWindowMacOSX::close() BOOL LLWindowMacOSX::isValid() { - if(mFullscreen) + if (mFullscreen) { return(TRUE); } @@ -1082,12 +779,12 @@ BOOL LLWindowMacOSX::getVisible() { BOOL result = FALSE; - if(mFullscreen) + if (mFullscreen) { result = TRUE; - }if (mWindow) + } + if (mWindow) { - if(MacIsWindowVisible(mWindow)) result = TRUE; } @@ -1108,7 +805,6 @@ BOOL LLWindowMacOSX::maximize() { if (mWindow && !mMaximized) { - ZoomWindow(mWindow, inContent, true); } return mMaximized; @@ -1121,60 +817,15 @@ BOOL LLWindowMacOSX::getFullscreen() void LLWindowMacOSX::gatherInput() { - // stop bouncing icon after fixed period of time - if (mBounceTimer.getStarted() && mBounceTimer.getElapsedTimeF32() > mBounceTime) - { - stopDockTileBounce(); - } - - // Use the old-school version so we get AppleEvent handler dispatch and menuselect handling. - // Anything that has an event handler will get processed inside WaitNextEvent, so we only need to handle - // the odd stuff here. - EventRecord evt; - while(WaitNextEvent(everyEvent, &evt, 0, NULL)) - { - // printf("WaitNextEvent returned true, event is %d.\n", evt.what); - switch(evt.what) - { - case mouseDown: - { - short part; - WindowRef window; - long selectResult; - part = FindWindow(evt.where, &window); - switch ( part ) - { - case inMenuBar: - selectResult = MenuSelect(evt.where); - - HiliteMenu(0); - break; - } - } - break; - - case kHighLevelEvent: - AEProcessAppleEvent (&evt); - break; - - case updateEvt: - // We shouldn't be getting these regularly (since our window will be buffered), but we need to handle them correctly... - BeginUpdate((WindowRef)evt.message); - EndUpdate((WindowRef)evt.message); - break; - - } - } - updateCursor(); } BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) { - Rect window_rect; - OSStatus err = -1; + float rect[4]; + S32 err = -1; - if(mFullscreen) + if (mFullscreen) { position->mX = 0; position->mY = 0; @@ -1182,10 +833,10 @@ BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); + getContentViewBounds(mWindow, rect); - position->mX = window_rect.left; - position->mY = window_rect.top; + position->mX = rect[0]; + position->mY = rect[1]; } else { @@ -1197,10 +848,10 @@ BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) { - Rect window_rect; - OSStatus err = -1; + float rect[4]; + S32 err = -1; - if(mFullscreen) + if (mFullscreen) { size->mX = mFullscreenWidth; size->mY = mFullscreenHeight; @@ -1208,10 +859,10 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); + getScaledContentViewBounds(mWindow, mGLView, rect); - size->mX = window_rect.right - window_rect.left; - size->mY = window_rect.bottom - window_rect.top; + size->mX = rect[2]; + size->mY = rect[3]; } else { @@ -1223,10 +874,10 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) BOOL LLWindowMacOSX::getSize(LLCoordWindow *size) { - Rect window_rect; - OSStatus err = -1; - - if(mFullscreen) + float rect[4]; + S32 err = -1; + + if (mFullscreen) { size->mX = mFullscreenWidth; size->mY = mFullscreenHeight; @@ -1234,72 +885,69 @@ BOOL LLWindowMacOSX::getSize(LLCoordWindow *size) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); - - size->mX = window_rect.right - window_rect.left; - size->mY = window_rect.bottom - window_rect.top; + getScaledContentViewBounds(mWindow, mGLView, rect); + + size->mX = rect[2]; + size->mY = rect[3]; } else { LL_ERRS() << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << LL_ENDL; } - + return (err == noErr); } -BOOL LLWindowMacOSX::setPosition(const LLCoordScreen position) +BOOL LLWindowMacOSX::setPosition(LLCoordScreen position) { if(mWindow) { - MacMoveWindow(mWindow, position.mX, position.mY, false); + float pos[2] = {static_cast(position.mX), + static_cast(position.mY)}; + setWindowPos(mWindow, pos); } return TRUE; } -BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size) +BOOL LLWindowMacOSX::setSizeImpl(LLCoordScreen size) { if(mWindow) { - SizeWindow(mWindow, size.mX, size.mY, true); + LLCoordWindow to; + convertCoords(size, &to); + setWindowSize(mWindow, to.mX, to.mY); + return TRUE; } - return TRUE; + return FALSE; } -BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size) +BOOL LLWindowMacOSX::setSizeImpl(LLCoordWindow size) { - Rect client_rect; if (mWindow) { - OSStatus err = GetWindowBounds(mWindow, kWindowContentRgn, &client_rect); - if (err == noErr) - { - client_rect.right = client_rect.left + size.mX; - client_rect.bottom = client_rect.top + size.mY; - err = SetWindowBounds(mWindow, kWindowContentRgn, &client_rect); - } - if (err == noErr) - { - return TRUE; - } - else - { - LL_INFOS() << "Error setting size" << err << LL_ENDL; - return FALSE; - } + const int titlePadding = 22; + setWindowSize(mWindow, size.mX, size.mY + titlePadding); + return TRUE; } + return FALSE; } void LLWindowMacOSX::swapBuffers() { - aglSwapBuffers(mContext); + CGLFlushDrawable(mContext); +} + +void LLWindowMacOSX::restoreGLContext() +{ + CGLSetCurrentContext(mContext); } F32 LLWindowMacOSX::getGamma() { - F32 result = 1.8; // Default to something sane + F32 result = 2.2; // Default to something sane CGGammaValue redMin; CGGammaValue redMax; @@ -1342,16 +990,6 @@ void LLWindowMacOSX::setFSAASamples(const U32 samples) mForceRebuild = TRUE; } -S32 LLWindowMacOSX::getVsyncMode() -{ - return mVsyncMode; -} -void LLWindowMacOSX::setVsyncMode(const S32 vsync_mode) -{ - mVsyncMode = vsync_mode; - mForceRebuild = TRUE; -} - BOOL LLWindowMacOSX::restoreGamma() { CGDisplayRestoreColorSyncSettings(); @@ -1431,7 +1069,7 @@ void LLWindowMacOSX::setMouseClipping( BOOL b ) adjustCursorDecouple(); } -BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) +BOOL LLWindowMacOSX::setCursorPosition(LLCoordWindow position) { BOOL result = FALSE; LLCoordScreen screen_pos; @@ -1448,11 +1086,13 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) newPosition.x = screen_pos.mX; newPosition.y = screen_pos.mY; - CGSetLocalEventsSuppressionInterval(0.0); + CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventSourceSetLocalEventsSuppressionInterval(src, 0.0); if(CGWarpMouseCursorPosition(newPosition) == noErr) { result = TRUE; } + CFRelease(src); // Under certain circumstances, this will trigger us to decouple the cursor. adjustCursorDecouple(true); @@ -1465,39 +1105,15 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) return result; } -static void fixOrigin(void) -{ - GrafPtr port; - Rect portrect; - - ::GetPort(&port); - ::GetPortBounds(port, &portrect); - if((portrect.left != 0) || (portrect.top != 0)) - { - // Mozilla sometimes changes our port origin. - ::SetOrigin(0,0); - } -} - BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position) { - Point cursor_point; + float cursor_point[2]; LLCoordScreen screen_pos; - GrafPtr save; if(mWindow == NULL) return FALSE; - - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - // gets the mouse location in local coordinates - ::GetMouse(&cursor_point); - -// LL_DEBUGS() << "getCursorPosition(): cursor is at " << cursor_point.h << ", " << cursor_point.v << " port origin: " << portrect.left << ", " << portrect.top << LL_ENDL; - - ::SetPort(save); + + getCursorPos(mWindow, cursor_point); if(mCursorDecoupled) { @@ -1510,12 +1126,12 @@ BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position) // CGGetLastMouseDelta may behave strangely when the cursor's first captured. // Stash in the event handler instead. - cursor_point.h += mCursorLastEventDeltaX; - cursor_point.v += mCursorLastEventDeltaY; + cursor_point[0] += mCursorLastEventDeltaX; + cursor_point[1] += mCursorLastEventDeltaY; } - - position->mX = cursor_point.h; - position->mY = cursor_point.v; + float scale = getScaleFactor(); + position->mX = cursor_point[0] * scale; + position->mY = cursor_point[1] * scale; return TRUE; } @@ -1532,7 +1148,6 @@ void LLWindowMacOSX::adjustCursorDecouple(bool warpingMouse) // LL_INFOS() << "adjustCursorDecouple: decoupling cursor" << LL_ENDL; CGAssociateMouseAndMouseCursorPosition(false); mCursorDecoupled = true; - FlushSpecificEventsFromQueue(GetCurrentEventQueue(), mMoveEventCampartorUPP, NULL); mCursorIgnoreNextDelta = TRUE; } } @@ -1579,183 +1194,56 @@ F32 LLWindowMacOSX::getPixelAspectRatio() // MBW -- XXX -- There's got to be a better way than this. Find it, please... +// Since we're no longer supporting the "typical" fullscreen mode with CGL or NSOpenGL anymore, these are unnecessary. -Geenz void LLWindowMacOSX::beforeDialog() { - if(mFullscreen) - { - -#if CAPTURE_ALL_DISPLAYS - // Uncapture all displays (may want to do this for final build) - CGReleaseAllDisplays (); -#else - // Uncapture only the main display (useful for debugging) - CGDisplayRelease (mDisplay); -#endif - // kDocumentWindowClass - // kMovableModalWindowClass - // kAllWindowClasses - - // GLint order = 0; - // aglSetInteger(mContext, AGL_ORDER_CONTEXT_TO_FRONT, &order); - aglSetDrawable(mContext, NULL); - // GetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), &oldWindowLevel); - // SetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), CGShieldingWindowLevel()); - - mHandsOffEvents = TRUE; - - } } void LLWindowMacOSX::afterDialog() { - if(mFullscreen) - { - mHandsOffEvents = FALSE; - - // SetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), oldWindowLevel); - aglSetFullScreen(mContext, 0, 0, 0, 0); - // GLint order = 1; - // aglSetInteger(mContext, AGL_ORDER_CONTEXT_TO_FRONT, &order); - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - CGCaptureAllDisplays (); -#else - // Capture only the main display (useful for debugging) - CGDisplayCapture (mDisplay); -#endif - } + //For fix problem with Core Flow view on OSX + restoreGLContext(); } void LLWindowMacOSX::flashIcon(F32 seconds) { - // Don't do this if we're already started, since this would try to install the NMRec twice. - if(!mBounceTimer.getStarted()) - { - OSErr err; - - mBounceTime = seconds; - memset(&mBounceRec, 0, sizeof(mBounceRec)); - mBounceRec.qType = nmType; - mBounceRec.nmMark = 1; - err = NMInstall(&mBounceRec); - if(err == noErr) - { - mBounceTimer.start(); - } - else - { - // This is very not-fatal (only problem is the icon will not bounce), but we'd like to find out about it somehow... - LL_INFOS() << "NMInstall failed with error code " << err << LL_ENDL; - } - } + // For consistency with OS X conventions, the number of seconds given is ignored and + // left up to the OS (which will actually bounce it for one second). + requestUserAttention(); } BOOL LLWindowMacOSX::isClipboardTextAvailable() { - OSStatus err; - ScrapRef scrap; - ScrapFlavorFlags flags; - BOOL result = false; - - err = GetCurrentScrap(&scrap); - - if(err == noErr) - { - err = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &flags); - } - - if(err == noErr) - result = true; - - return result; + return pasteBoardAvailable(); } BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst) -{ - OSStatus err; - ScrapRef scrap; - Size len; - BOOL result = false; - - err = GetCurrentScrap(&scrap); - - if(err == noErr) +{ + llutf16string str(copyFromPBoard()); + dst = utf16str_to_wstring(str); + if (dst != L"") { - err = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &len); - } - - if((err == noErr) && (len > 0)) - { - int u16len = len / sizeof(U16); - U16 *temp = new U16[u16len + 1]; - if (temp) - { - memset(temp, 0, (u16len + 1) * sizeof(temp[0])); - err = GetScrapFlavorData(scrap, kScrapFlavorTypeUnicode, &len, temp); - if (err == noErr) - { - // convert \r\n to \n and \r to \n in the incoming text. - U16 *s, *d; - for(s = d = temp; s[0] != '\0'; s++, d++) - { - if(s[0] == '\r') - { - if(s[1] == '\n') - { - // CRLF, a.k.a. DOS newline. Collapse to a single '\n'. - s++; - } - - d[0] = '\n'; - } - else - { - d[0] = s[0]; - } - } - - d[0] = '\0'; - - dst = utf16str_to_wstring(temp); - - result = true; - } - delete[] temp; - } + return true; + } else { + return false; } - - return result; } BOOL LLWindowMacOSX::copyTextToClipboard(const LLWString &s) { - OSStatus err; - ScrapRef scrap; - //Size len; - //char *temp; BOOL result = false; - - if (!s.empty()) - { - err = GetCurrentScrap(&scrap); - if (err == noErr) - err = ClearScrap(&scrap); - - if (err == noErr) - { - llutf16string utf16str = wstring_to_utf16str(s); - size_t u16len = utf16str.length() * sizeof(U16); - err = PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone, u16len, utf16str.data()); - if (err == noErr) - result = true; - } - } + llutf16string utf16str = wstring_to_utf16str(s); + + result = copyToPBoard(utf16str.data(), utf16str.length()); return result; } +void LLWindowMacOSX::setWindowTitle(const std::string& title) +{ + setTitle(title); +} // protected BOOL LLWindowMacOSX::resetDisplayResolution() @@ -1769,7 +1257,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r { if (!mSupportedResolutions) { - CFArrayRef modes = CGDisplayAvailableModes(mDisplay); + CFArrayRef modes = CGDisplayCopyAllDisplayModes(mDisplay, NULL); if(modes != NULL) { @@ -1797,1025 +1285,102 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r if (mSupportedResolutions[i].mWidth == width && mSupportedResolutions[i].mHeight == height) { - resolution_exists = TRUE; - } - } - if (!resolution_exists) - { - mSupportedResolutions[mNumSupportedResolutions].mWidth = width; - mSupportedResolutions[mNumSupportedResolutions].mHeight = height; - mNumSupportedResolutions++; - } - } - } - } - } - - num_resolutions = mNumSupportedResolutions; - return mSupportedResolutions; -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to) -{ - S32 client_height; - Rect client_rect; - - if(mFullscreen) - { - // In the fullscreen case, the "window" is the entire screen. - client_rect.left = 0; - client_rect.top = 0; - client_rect.right = mFullscreenWidth; - client_rect.bottom = mFullscreenHeight; - } - else if (!mWindow || - (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) || - NULL == to) - { - return FALSE; - } - - to->mX = from.mX; - client_height = client_rect.bottom - client_rect.top; - to->mY = client_height - from.mY - 1; - - return TRUE; -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to) -{ - S32 client_height; - Rect client_rect; - - if(mFullscreen) - { - // In the fullscreen case, the "window" is the entire screen. - client_rect.left = 0; - client_rect.top = 0; - client_rect.right = mFullscreenWidth; - client_rect.bottom = mFullscreenHeight; - } - else if (!mWindow || - (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) || - NULL == to) - { - return FALSE; - } - - to->mX = from.mX; - client_height = client_rect.bottom - client_rect.top; - to->mY = client_height - from.mY - 1; - - return TRUE; -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) -{ - if(mFullscreen) - { - // In the fullscreen case, window and screen coordinates are the same. - to->mX = from.mX; - to->mY = from.mY; - return TRUE; - } - else if(mWindow) - { - GrafPtr save; - Point mouse_point; - - mouse_point.h = from.mX; - mouse_point.v = from.mY; - - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - ::GlobalToLocal(&mouse_point); - - to->mX = mouse_point.h; - to->mY = mouse_point.v; - - ::SetPort(save); - - return TRUE; - } - - return FALSE; -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) -{ - if(mFullscreen) - { - // In the fullscreen case, window and screen coordinates are the same. - to->mX = from.mX; - to->mY = from.mY; - return TRUE; - } - else if(mWindow) - { - GrafPtr save; - Point mouse_point; - - mouse_point.h = from.mX; - mouse_point.v = from.mY; - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - LocalToGlobal(&mouse_point); - - to->mX = mouse_point.h; - to->mY = mouse_point.v; - - ::SetPort(save); - - return TRUE; - } - - return FALSE; -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL *to) -{ - LLCoordWindow window_coord; - - return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to) -{ - LLCoordWindow window_coord; - - return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); -} - - - - -void LLWindowMacOSX::setupFailure(const std::string& text, const std::string& caption, U32 type) -{ - destroyContext(); - - OSMessageBox(text, caption, type); -} - -pascal Boolean LLWindowMacOSX::staticMoveEventComparator( EventRef event, void* data) -{ - UInt32 evtClass = GetEventClass (event); - UInt32 evtKind = GetEventKind (event); - - if ((evtClass == kEventClassMouse) && ((evtKind == kEventMouseDragged) || (evtKind == kEventMouseMoved))) - { - return true; - } - - else - { - return false; - } -} - - -pascal OSStatus LLWindowMacOSX::staticEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData) -{ - LLWindowMacOSX *self = (LLWindowMacOSX*)userData; - - return(self->eventHandler(myHandler, event)); -} - -OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef event) -{ - OSStatus result = eventNotHandledErr; - UInt32 evtClass = GetEventClass (event); - UInt32 evtKind = GetEventKind (event); - - // Always handle command events, even in hands-off mode. - if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess)) - { - HICommand command; - GetEventParameter (event, kEventParamDirectObject, typeHICommand, NULL, sizeof(command), NULL, &command); - - switch(command.commandID) - { - case kHICommandQuit: - if(mCallbacks->handleCloseRequest(this)) - { - // Get the app to initiate cleanup. - mCallbacks->handleQuit(this); - // The app is responsible for calling destroyWindow when done with GL - } - result = noErr; - break; - - default: - // MBW -- XXX -- Should we handle other events here? - break; - } - } - - if(mHandsOffEvents) - { - return(result); - } - - switch (evtClass) - { - case kEventClassTextInput: - { - switch (evtKind) - { - case kEventTextInputUpdateActiveInputArea: - { - EventParamType param_type; - - long fix_len; - UInt32 text_len; - if (mPreeditor - && (result = GetEventParameter(event, kEventParamTextInputSendFixLen, - typeLongInteger, ¶m_type, sizeof(fix_len), NULL, &fix_len)) == noErr - && typeLongInteger == param_type - && (result = GetEventParameter(event, kEventParamTextInputSendText, - typeUnicodeText, ¶m_type, 0, &text_len, NULL)) == noErr - && typeUnicodeText == param_type) - { - // Handle an optional (but essential to facilitate TSMDA) ReplaceRange param. - CFRange range; - if (GetEventParameter(event, kEventParamTextInputSendReplaceRange, - typeCFRange, ¶m_type, sizeof(range), NULL, &range) == noErr - && typeCFRange == param_type) - { - // Although the spec. is unclear, replace range should - // not present when there is an active preedit. We just - // ignore the case. markAsPreedit will detect the case and warn it. - const LLWString & text = mPreeditor->getPreeditString(); - const S32 location = wstring_wstring_length_from_utf16_length(text, 0, range.location); - const S32 length = wstring_wstring_length_from_utf16_length(text, location, range.length); - mPreeditor->markAsPreedit(location, length); - } - mPreeditor->resetPreedit(); - - // Receive the text from input method. - U16 *const text = new U16[text_len / sizeof(U16)]; - GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText, NULL, text_len, NULL, text); - if (fix_len < 0) - { - // Do we still need this? Seems obsolete... - fix_len = text_len; - } - const LLWString fix_string - = utf16str_to_wstring(llutf16string(text, fix_len / sizeof(U16))); - const LLWString preedit_string - = utf16str_to_wstring(llutf16string(text + fix_len / sizeof(U16), (text_len - fix_len) / sizeof(U16))); - delete[] text; - - // Handle fixed (comitted) string. - if (fix_string.length() > 0) - { - for (LLWString::const_iterator i = fix_string.begin(); i != fix_string.end(); i++) - { - mPreeditor->handleUnicodeCharHere(*i); - } - } - - // Receive the segment info and caret position. - LLPreeditor::segment_lengths_t preedit_segment_lengths; - LLPreeditor::standouts_t preedit_standouts; - S32 caret_position = preedit_string.length(); - UInt32 text_range_array_size; - if (GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, - ¶m_type, 0, &text_range_array_size, NULL) == noErr - && typeTextRangeArray == param_type - && text_range_array_size > sizeof(TextRangeArray)) - { - // TextRangeArray is a variable-length struct. - TextRangeArray * const text_range_array = (TextRangeArray *) new char[text_range_array_size]; - GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, - NULL, text_range_array_size, NULL, text_range_array); - - // WARNING: We assume ranges are in ascending order, - // although the condition is undocumented. It seems - // OK to assume this. I also assumed - // the ranges are contiguous in previous versions, but I - // have heard a rumore that older versions os ATOK may - // return ranges with some _gap_. I don't know whether - // it is true, but I'm preparing my code for the case. - - const S32 ranges = text_range_array->fNumOfRanges; - preedit_segment_lengths.reserve(ranges); - preedit_standouts.reserve(ranges); - - S32 last_bytes = 0; - S32 last_utf32 = 0; - for (S32 i = 0; i < ranges; i++) - { - const TextRange &range = text_range_array->fRange[i]; - if (range.fStart > last_bytes) - { - const S32 length_utf16 = (range.fStart - last_bytes) / sizeof(U16); - const S32 length_utf32 = wstring_wstring_length_from_utf16_length(preedit_string, last_utf32, length_utf16); - preedit_segment_lengths.push_back(length_utf32); - preedit_standouts.push_back(FALSE); - last_utf32 += length_utf32; - } - if (range.fEnd > range.fStart) - { - const S32 length_utf16 = (range.fEnd - range.fStart) / sizeof(U16); - const S32 length_utf32 = wstring_wstring_length_from_utf16_length(preedit_string, last_utf32, length_utf16); - preedit_segment_lengths.push_back(length_utf32); - preedit_standouts.push_back( - kTSMHiliteSelectedRawText == range.fHiliteStyle - || kTSMHiliteSelectedConvertedText == range.fHiliteStyle - || kTSMHiliteSelectedText == range.fHiliteStyle); - last_utf32 += length_utf32; - } - if (kTSMHiliteCaretPosition == range.fHiliteStyle) - { - caret_position = last_utf32; - } - last_bytes = range.fEnd; - } - if (preedit_string.length() > last_utf32) - { - preedit_segment_lengths.push_back(preedit_string.length() - last_utf32); - preedit_standouts.push_back(FALSE); - } - - delete[] (char *) text_range_array; - } - - // Handle preedit string. - if (preedit_string.length() == 0) - { - preedit_segment_lengths.clear(); - preedit_standouts.clear(); - } - else if (preedit_segment_lengths.size() == 0) - { - preedit_segment_lengths.push_back(preedit_string.length()); - preedit_standouts.push_back(FALSE); - } - mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position); - - result = noErr; - } - } - break; - - case kEventTextInputUnicodeForKeyEvent: - { - UInt32 modifiers = 0; - - - // First, process the raw event. - { - EventRef rawEvent = NULL; - - // Get the original event and extract the modifier keys, so we can ignore command-key events. - if (GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent) == noErr) - { - // Grab the modifiers for later use in this function... - GetEventParameter (rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - - // and call this function recursively to handle the raw key event. - eventHandler (myHandler, rawEvent); - - // save the raw event until we're done processing the unicode input as well. - mRawKeyEvent = rawEvent; - } - } - - OSStatus err = noErr; - EventParamType actualType = typeUnicodeText; - UInt32 actualSize = 0; - size_t actualCount = 0; - U16 *buffer = NULL; - - // Get the size of the unicode data - err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, 0, &actualSize, NULL); - if(err == noErr) - { - // allocate a buffer and get the actual data. - actualCount = actualSize / sizeof(U16); - buffer = new U16[actualCount]; - err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, actualSize, &actualSize, buffer); - } - - if(err == noErr) - { - if(modifiers & (cmdKey | controlKey)) - { - // This was a menu key equivalent. Ignore it. - } - else - { - MASK mask = LLWindowMacOSX::modifiersToMask(modifiers); - - llassert( actualType == typeUnicodeText ); - - // The result is a UTF16 buffer. Pass the characters in turn to handleUnicodeChar. - - // Convert to UTF32 and go character-by-character. - llutf16string utf16(buffer, actualCount); - LLWString utf32 = utf16str_to_wstring(utf16); - LLWString::iterator iter; - - for(iter = utf32.begin(); iter != utf32.end(); iter++) - { - mCallbacks->handleUnicodeChar(*iter, mask); - } - } - } - - if(buffer != NULL) - { - delete[] buffer; - } - - mRawKeyEvent = NULL; - result = err; - } - break; - - case kEventTextInputOffsetToPos: - { - EventParamType param_type; - long offset; - if (mPreeditor - && GetEventParameter(event, kEventParamTextInputSendTextOffset, typeLongInteger, - ¶m_type, sizeof(offset), NULL, &offset) == noErr - && typeLongInteger == param_type) - { - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - LLCoordGL caret_coord; - LLRect preedit_bounds; - if (0 <= offset - && mPreeditor->getPreeditLocation(wstring_wstring_length_from_utf16_length(text, preedit, offset / sizeof(U16)), - &caret_coord, &preedit_bounds, NULL)) - { - LLCoordGL caret_base_coord(caret_coord.mX, preedit_bounds.mBottom); - LLCoordScreen caret_base_coord_screen; - convertCoords(caret_base_coord, &caret_base_coord_screen); - Point qd_point; - qd_point.h = caret_base_coord_screen.mX; - qd_point.v = caret_base_coord_screen.mY; - SetEventParameter(event, kEventParamTextInputReplyPoint, typeQDPoint, sizeof(qd_point), &qd_point); - - short line_height = (short) preedit_bounds.getHeight(); - SetEventParameter(event, kEventParamTextInputReplyLineHeight, typeShortInteger, sizeof(line_height), &line_height); - - result = noErr; - } - else - { - result = errOffsetInvalid; - } - } - } - break; - - case kEventTextInputGetSelectedText: - { - if (mPreeditor) - { - S32 selection, selection_length; - mPreeditor->getSelectionRange(&selection, &selection_length); - if (selection_length) - { - const LLWString text = mPreeditor->getPreeditString().substr(selection, selection_length); - const llutf16string text_utf16 = wstring_to_utf16str(text); - result = SetEventParameter(event, kEventParamTextInputReplyText, typeUnicodeText, - text_utf16.length() * sizeof(U16), text_utf16.c_str()); - } - } - } - break; - } - } - break; - - case kEventClassKeyboard: - { - UInt32 keyCode = 0; - char charCode = 0; - UInt32 modifiers = 0; - - // Some of these may fail for some event types. That's fine. - GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode); - GetEventParameter (event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - - // save the raw event so getNativeKeyData can use it. - mRawKeyEvent = event; - - // printf("key event, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", keyCode, charCode, (char)charCode, modifiers); - // fflush(stdout); - - switch (evtKind) - { - case kEventRawKeyDown: - case kEventRawKeyRepeat: - if (gDebugWindowProc) - { - printf("key down, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", - (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers); - fflush(stdout); - } - gKeyboard->handleKeyDown(keyCode, modifiers); - result = eventNotHandledErr; - break; - - case kEventRawKeyUp: - if (gDebugWindowProc) - { - printf("key up, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", - (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers); - fflush(stdout); - } - gKeyboard->handleKeyUp(keyCode, modifiers); - result = eventNotHandledErr; - break; - - case kEventRawKeyModifiersChanged: - // The keyboard input system wants key up/down events for modifier keys. - // Mac OS doesn't supply these directly, but can supply events when the collective modifier state changes. - // Use these events to generate up/down events for the modifiers. - - if((modifiers & shiftKey) && !(mLastModifiers & shiftKey)) - { - if (gDebugWindowProc) printf("Shift key down event\n"); - gKeyboard->handleKeyDown(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000)); - } - else if(!(modifiers & shiftKey) && (mLastModifiers & shiftKey)) - { - if (gDebugWindowProc) printf("Shift key up event\n"); - gKeyboard->handleKeyUp(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000)); - } - - if((modifiers & alphaLock) && !(mLastModifiers & alphaLock)) - { - if (gDebugWindowProc) printf("Caps lock down event\n"); - gKeyboard->handleKeyDown(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000)); - } - else if(!(modifiers & alphaLock) && (mLastModifiers & alphaLock)) - { - if (gDebugWindowProc) printf("Caps lock up event\n"); - gKeyboard->handleKeyUp(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000)); - } - - if((modifiers & controlKey) && !(mLastModifiers & controlKey)) - { - if (gDebugWindowProc) printf("Control key down event\n"); - gKeyboard->handleKeyDown(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000)); - } - else if(!(modifiers & controlKey) && (mLastModifiers & controlKey)) - { - if (gDebugWindowProc) printf("Control key up event\n"); - gKeyboard->handleKeyUp(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000)); - } - - if((modifiers & optionKey) && !(mLastModifiers & optionKey)) - { - if (gDebugWindowProc) printf("Option key down event\n"); - gKeyboard->handleKeyDown(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000)); - } - else if(!(modifiers & optionKey) && (mLastModifiers & optionKey)) - { - if (gDebugWindowProc) printf("Option key up event\n"); - gKeyboard->handleKeyUp(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000)); - } - - // When the state of the 'Fn' key (the one that changes some of the mappings on a powerbook/macbook keyboard - // to an embedded keypad) changes, it may subsequently cause a key up event to be lost, which may lead to - // a movement key getting "stuck" down. This is bad. - // This is an OS bug -- even the GetKeys() API doesn't tell you the key has been released. - // This workaround causes all held-down keys to be reset whenever the state of the Fn key changes. This isn't - // exactly what we want, but it does avoid the case where you get stuck running forward. - if((modifiers & kEventKeyModifierFnMask) != (mLastModifiers & kEventKeyModifierFnMask)) - { - if (gDebugWindowProc) printf("Fn key state change event\n"); - gKeyboard->resetKeys(); - } - - if (gDebugWindowProc) fflush(stdout); - - mLastModifiers = modifiers; - result = eventNotHandledErr; - break; - } - - mRawKeyEvent = NULL; - } - break; - - case kEventClassMouse: - { - result = CallNextEventHandler(myHandler, event); - if (eventNotHandledErr == result) - { // only handle events not already handled (prevents wierd resize interaction) - EventMouseButton button = kEventMouseButtonPrimary; - HIPoint location = {0.0f, 0.0f}; - UInt32 modifiers = 0; - UInt32 clickCount = 1; - long wheelDelta = 0; - LLCoordScreen inCoords; - LLCoordGL outCoords; - MASK mask = 0; - - GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); - GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(location), NULL, &location); - GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); - GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(wheelDelta), NULL, &wheelDelta); - GetEventParameter(event, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount); - - inCoords.mX = llround(location.x); - inCoords.mY = llround(location.y); - - if(modifiers & shiftKey) { mask |= MASK_SHIFT; } - if(modifiers & controlKey) { mask |= MASK_CONTROL; } - if(modifiers & optionKey) { mask |= MASK_ALT; } - - if(mCursorDecoupled) - { - CGMouseDelta x, y; - - // If the cursor's decoupled, we need to read the latest movement delta as well. - CGGetLastMouseDelta( &x, &y ); - mCursorLastEventDeltaX = x; - mCursorLastEventDeltaY = y; - - if(mCursorIgnoreNextDelta) - { - mCursorLastEventDeltaX = 0; - mCursorLastEventDeltaY = 0; - mCursorIgnoreNextDelta = FALSE; - } - } - else - { - mCursorLastEventDeltaX = 0; - mCursorLastEventDeltaY = 0; - } - - inCoords.mX += mCursorLastEventDeltaX; - inCoords.mY += mCursorLastEventDeltaY; - - convertCoords(inCoords, &outCoords); - - // printf("coords in: %d, %d; coords out: %d, %d\n", inCoords.mX, inCoords.mY, outCoords.mX, outCoords.mY); - // fflush(stdout); - - - switch (evtKind) - { - case kEventMouseDown: - if (mLanguageTextInputAllowed) - { - // We need to interrupt before handling mouse events, - // so that the fixed string from IM are delivered to - // the currently focused UI component. - interruptLanguageTextInput(); - } - switch(button) - { - case kEventMouseButtonPrimary: - if(modifiers & cmdKey) - { - // Simulate a right click - mSimulatedRightClick = true; - mCallbacks->handleRightMouseDown(this, outCoords, mask); - } - else if(clickCount == 2) - { - // Windows double-click events replace the second mousedown event in a double-click. - mCallbacks->handleDoubleClick(this, outCoords, mask); - } - else - { - mCallbacks->handleMouseDown(this, outCoords, mask); - } - break; - case kEventMouseButtonSecondary: - mCallbacks->handleRightMouseDown(this, outCoords, mask); - break; - - case kEventMouseButtonTertiary: - mCallbacks->handleMiddleMouseDown(this, outCoords, mask); - break; - } - result = noErr; - break; - case kEventMouseUp: - - switch(button) - { - case kEventMouseButtonPrimary: - if(mSimulatedRightClick) - { - // End of simulated right click - mSimulatedRightClick = false; - mCallbacks->handleRightMouseUp(this, outCoords, mask); - } - else - { - mCallbacks->handleMouseUp(this, outCoords, mask); - } - break; - case kEventMouseButtonSecondary: - mCallbacks->handleRightMouseUp(this, outCoords, mask); - break; - - case kEventMouseButtonTertiary: - mCallbacks->handleMiddleMouseUp(this, outCoords, mask); - break; - } - result = noErr; - break; - - case kEventMouseWheelMoved: - { - static S32 z_delta = 0; - - z_delta += wheelDelta; - - if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) - { - mCallbacks->handleScrollWheel(this, -z_delta / WHEEL_DELTA); - z_delta = 0; - } - } - result = noErr; - break; - - case kEventMouseDragged: - case kEventMouseMoved: - mCallbacks->handleMouseMove(this, outCoords, mask); - result = noErr; - break; - - } - } - } - break; - - case kEventClassWindow: - switch(evtKind) - { - case kEventWindowActivated: - if (mTSMDocument) - { - ActivateTSMDocument(mTSMDocument); - } - mCallbacks->handleFocus(this); - break; - case kEventWindowDeactivated: - if (mTSMDocument) - { - DeactivateTSMDocument(mTSMDocument); - } - mCallbacks->handleFocusLost(this); - break; - - case kEventWindowBoundsChanging: - { - // This is where we would constrain move/resize to a particular screen - - const S32 MIN_WIDTH = mMinWindowWidth; - const S32 MIN_HEIGHT = mMinWindowHeight; - - Rect currentBounds; - Rect previousBounds; - - GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds); - GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &previousBounds); - - // Put an offset into window un-maximize operation since the kEventWindowGetIdealSize - // event only allows the specification of size and not position. - if (mMaximized) - { - short leftOffset = mPreviousWindowRect.left - currentBounds.left; - currentBounds.left += leftOffset; - currentBounds.right += leftOffset; - - short topOffset = mPreviousWindowRect.top - currentBounds.top; - currentBounds.top += topOffset; - currentBounds.bottom += topOffset; - } - else - { - // Store off the size for future un-maximize operations - mPreviousWindowRect = previousBounds; - } - - if ((currentBounds.right - currentBounds.left) < MIN_WIDTH) - { - currentBounds.right = currentBounds.left + MIN_WIDTH; - } - - if ((currentBounds.bottom - currentBounds.top) < MIN_HEIGHT) - { - currentBounds.bottom = currentBounds.top + MIN_HEIGHT; + resolution_exists = TRUE; + } + } + if (!resolution_exists) + { + mSupportedResolutions[mNumSupportedResolutions].mWidth = width; + mSupportedResolutions[mNumSupportedResolutions].mHeight = height; + mNumSupportedResolutions++; + } } - - SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), ¤tBounds); - result = noErr; } - break; + CFRelease(modes); + } + } - case kEventWindowBoundsChanged: - { - // Get new window bounds - Rect newBounds; - GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &newBounds); + num_resolutions = mNumSupportedResolutions; + return mSupportedResolutions; +} - // Get previous window bounds - Rect oldBounds; - GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &oldBounds); +BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to) +{ + to->mX = from.mX; + to->mY = from.mY; + return TRUE; +} - // Determine if the new size is larger than the old - bool newBoundsLarger = ((newBounds.right - newBounds.left) >= (oldBounds.right - oldBounds.left)); - newBoundsLarger &= ((newBounds.bottom - newBounds.top) >= (oldBounds.bottom - oldBounds.top)); +BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to) +{ + to->mX = from.mX; + to->mY = from.mY; + return TRUE; +} - // Check to see if this is a zoom event (+ button on window pane) - unsigned int eventParams; - GetEventParameter(event, kEventParamAttributes, typeUInt32, NULL, sizeof(int), NULL, &eventParams); - bool isZoomEvent = ((eventParams & kWindowBoundsChangeZoom) != 0); +BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) +{ + if(mWindow) + { + float mouse_point[2]; + float scale_factor = getScaleFactor(); + mouse_point[0] = from.mX; + mouse_point[1] = from.mY; + + convertScreenToWindow(mWindow, mouse_point); - // Maximized flag is if zoom event and increasing window size - mMaximized = (isZoomEvent && newBoundsLarger); + to->mX = mouse_point[0] * scale_factor; + to->mY = mouse_point[1] * scale_factor; - aglUpdateContext(mContext); + return TRUE; + } + return FALSE; +} - mCallbacks->handleResize(this, newBounds.right - newBounds.left, newBounds.bottom - newBounds.top); - } - break; +BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) +{ + if(mWindow) + { + float mouse_point[2]; + float scale_factor = getScaleFactor(); + mouse_point[0] = from.mX / scale_factor; + mouse_point[1] = from.mY / scale_factor; + convertWindowToScreen(mWindow, mouse_point); - case kEventWindowGetIdealSize: - // Only recommend a new ideal size when un-maximizing - if (mMaximized == TRUE) - { - Point nonMaximizedSize; + to->mX = mouse_point[0]; + to->mY = mouse_point[1]; - nonMaximizedSize.v = mPreviousWindowRect.bottom - mPreviousWindowRect.top; - nonMaximizedSize.h = mPreviousWindowRect.right - mPreviousWindowRect.left; + return TRUE; + } + return FALSE; +} - SetEventParameter(event, kEventParamDimensions, typeQDPoint, sizeof(Point), &nonMaximizedSize); - result = noErr; - } - break; +BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL *to) +{ + LLCoordWindow window_coord; - case kEventWindowClose: - if(mCallbacks->handleCloseRequest(this)) - { - // Get the app to initiate cleanup. - mCallbacks->handleQuit(this); - // The app is responsible for calling destroyWindow when done with GL - } - result = noErr; - break; - - case kEventWindowHidden: - // LL_INFOS() << "LLWindowMacOSX: Deactivating on hide" << LL_ENDL; - mMinimized = TRUE; - mCallbacks->handleActivate(this, false); - // result = noErr; - break; - - case kEventWindowShown: - // LL_INFOS() << "LLWindowMacOSX: Activating on show" << LL_ENDL; - mMinimized = FALSE; - mCallbacks->handleActivate(this, true); - // result = noErr; - break; - - case kEventWindowCollapsed: - // LL_INFOS() << "LLWindowMacOSX: Deactivating on collapse" << LL_ENDL; - mMinimized = TRUE; - mCallbacks->handleActivate(this, false); - // result = noErr; - break; - - case kEventWindowExpanded: - // LL_INFOS() << "LLWindowMacOSX: Activating on expand" << LL_ENDL; - mMinimized = FALSE; - mCallbacks->handleActivate(this, true); - // result = noErr; - break; - - case kEventWindowGetClickActivation: - // BringToFront(mWindow); - // result = noErr; - break; - } - break; + return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); +} - case kEventClassTSMDocumentAccess: - if (mPreeditor) - { - switch(evtKind) - { +BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to) +{ + LLCoordWindow window_coord; - case kEventTSMDocumentAccessGetLength: - { - // Return the number of UTF-16 units in the text, excluding those for preedit. - - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - const CFIndex length = wstring_utf16_length(text, 0, preedit) - + wstring_utf16_length(text, preedit + preedit_length, text.length()); - result = SetEventParameter(event, kEventParamTSMDocAccessCharacterCount, typeCFIndex, sizeof(length), &length); - } - break; + return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); +} - case kEventTSMDocumentAccessGetSelectedRange: - { - // Return the selected range, excluding preedit. - // In our preeditor, preedit and selection are exclusive, so, - // when it has a preedit, there is no selection and the - // insertion point is on the preedit that corrupses into the - // beginning of the preedit when the preedit was removed. - - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - CFRange range; - if (preedit_length) - { - range.location = wstring_utf16_length(text, 0, preedit); - range.length = 0; - } - else - { - S32 selection, selection_length; - mPreeditor->getSelectionRange(&selection, &selection_length); - range.location = wstring_utf16_length(text, 0, selection); - range.length = wstring_utf16_length(text, selection, selection_length); - } - result = SetEventParameter(event, kEventParamTSMDocAccessReplyCharacterRange, typeCFRange, sizeof(range), &range); - } - break; - case kEventTSMDocumentAccessGetCharacters: - { - UniChar *target_pointer; - CFRange range; - EventParamType param_type; - if ((result = GetEventParameter(event, kEventParamTSMDocAccessSendCharacterRange, - typeCFRange, ¶m_type, sizeof(range), NULL, &range)) == noErr - && typeCFRange == param_type - && (result = GetEventParameter(event, kEventParamTSMDocAccessSendCharactersPtr, - typePtr, ¶m_type, sizeof(target_pointer), NULL, &target_pointer)) == noErr - && typePtr == param_type) - { - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - // The GetCharacters event of TSMDA has a fundamental flaw; - // An input method need to decide the starting offset and length - // *before* it actually see the contents, so it is impossible - // to guarantee the character-aligned access. The event reply - // has no way to indicate a condition something like "Request - // was not fulfilled due to unaligned access. Please retry." - // Any error sent back to the input method stops use of TSMDA - // entirely during the session... - // We need to simulate very strictly the behaviour as if the - // underlying *text engine* holds the contents in UTF-16. - // I guess this is the reason why Apple repeats saying "all - // text handling application should use UTF-16." They are - // trying to _fix_ the flaw by changing the appliations... - // ... or, domination of UTF-16 in the industry may be a part - // of the company vision, and Apple is trying to force third - // party developers to obey their vision. Remember that use - // of 16 bits per _a_character_ was one of the very fundamental - // Unicode design policy on its early days (during late 80s) - // and the original Unicode design was by two Apple employees... - - const llutf16string text_utf16 - = wstring_to_utf16str(text, preedit) - + wstring_to_utf16str(text.substr(preedit + preedit_length)); - - llassert_always(sizeof(U16) == sizeof(UniChar)); - llassert(0 <= range.location && 0 <= range.length && range.location + range.length <= text_utf16.length()); - memcpy(target_pointer, text_utf16.c_str() + range.location, range.length * sizeof(UniChar)); - - // Note that result has already been set above. - } - } - break; - } - } - break; - } - return result; +void LLWindowMacOSX::setupFailure(const std::string& text, const std::string& caption, U32 type) +{ + destroyContext(); + + OSMessageBox(text, caption, type); } + // Note on event recording - QUIT is a known special case and we are choosing NOT to record it for the record and playback feature + // it is handled at a very low-level const char* cursorIDToName(int id) { switch (id) @@ -2855,8 +1420,14 @@ const char* cursorIDToName(int id) case UI_CURSOR_PIPETTE: return "UI_CURSOR_PIPETTE"; case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT"; case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY"; - case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN"; case UI_CURSOR_TOOLPAY: return "UI_CURSOR_TOOLPAY"; + case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN"; + /*case UI_CURSOR_TOOLPATHFINDING: return "UI_CURSOR_PATHFINDING"; + case UI_CURSOR_TOOLPATHFINDING_PATH_START: return "UI_CURSOR_PATHFINDING_START"; + case UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD: return "UI_CURSOR_PATHFINDING_START_ADD"; + case UI_CURSOR_TOOLPATHFINDING_PATH_END: return "UI_CURSOR_PATHFINDING_END"; + case UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD: return "UI_CURSOR_PATHFINDING_END_ADD"; + case UI_CURSOR_TOOLNO: return "UI_CURSOR_NO";*/ } LL_ERRS() << "cursorIDToName: unknown cursor id" << id << LL_ENDL; @@ -2882,7 +1453,7 @@ static void initPixmapCursor(int cursorid, int hotspotX, int hotspotY) void LLWindowMacOSX::updateCursor() { - OSStatus result = noErr; + S32 result = 0; if (mDragOverrideCursor != -1) { @@ -2898,8 +1469,10 @@ void LLWindowMacOSX::updateCursor() mNextCursor = UI_CURSOR_WORKING; } - if(mCurrentCursor == mNextCursor) - return; + if(mCurrentCursor == mNextCursor) + { + return; + } // RN: replace multi-drag cursors with single versions if (mNextCursor == UI_CURSOR_ARROWDRAGMULTI) @@ -2915,11 +1488,11 @@ void LLWindowMacOSX::updateCursor() { default: case UI_CURSOR_ARROW: - InitCursor(); + setArrowCursor(); if(mCursorHidden) { // Since InitCursor resets the hide level, correct for it here. - ::HideCursor(); + hideNSCursor(); } break; @@ -2927,12 +1500,12 @@ void LLWindowMacOSX::updateCursor() // Find out what they look like and replicate them. // These are essentially correct - case UI_CURSOR_WAIT: SetThemeCursor(kThemeWatchCursor); break; - case UI_CURSOR_IBEAM: SetThemeCursor(kThemeIBeamCursor); break; - case UI_CURSOR_CROSS: SetThemeCursor(kThemeCrossCursor); break; - case UI_CURSOR_HAND: SetThemeCursor(kThemePointingHandCursor); break; + case UI_CURSOR_WAIT: /* Apple purposely doesn't allow us to set the beachball cursor manually. Let NSApp figure out when to do this. */ break; + case UI_CURSOR_IBEAM: setIBeamCursor(); break; + case UI_CURSOR_CROSS: setCrossCursor(); break; + case UI_CURSOR_HAND: setPointingHandCursor(); break; // case UI_CURSOR_NO: SetThemeCursor(kThemeNotAllowedCursor); break; - case UI_CURSOR_ARROWCOPY: SetThemeCursor(kThemeCopyArrowCursor); break; + case UI_CURSOR_ARROWCOPY: setCopyCursor(); break; // Double-check these case UI_CURSOR_NO: @@ -2949,6 +1522,7 @@ void LLWindowMacOSX::updateCursor() case UI_CURSOR_NOLOCKED: case UI_CURSOR_ARROWLOCKED: case UI_CURSOR_GRABLOCKED: + case UI_CURSOR_PIPETTE: case UI_CURSOR_TOOLTRANSLATE: case UI_CURSOR_TOOLROTATE: case UI_CURSOR_TOOLSCALE: @@ -2961,8 +1535,14 @@ void LLWindowMacOSX::updateCursor() case UI_CURSOR_TOOLMEDIAOPEN: case UI_CURSOR_TOOLSIT: case UI_CURSOR_TOOLBUY: - case UI_CURSOR_TOOLOPEN: case UI_CURSOR_TOOLPAY: + case UI_CURSOR_TOOLOPEN: + /*case UI_CURSOR_TOOLPATHFINDING: + case UI_CURSOR_TOOLPATHFINDING_PATH_START: + case UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD: + case UI_CURSOR_TOOLPATHFINDING_PATH_END: + case UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD: + case UI_CURSOR_TOOLNO:*/ result = setImageCursor(gCursors[mNextCursor]); break; @@ -2970,7 +1550,7 @@ void LLWindowMacOSX::updateCursor() if(result != noErr) { - InitCursor(); + setArrowCursor(); } mCurrentCursor = mNextCursor; @@ -2994,6 +1574,7 @@ void LLWindowMacOSX::initCursors() initPixmapCursor(UI_CURSOR_NOLOCKED, 8, 8); initPixmapCursor(UI_CURSOR_ARROWLOCKED, 1, 1); initPixmapCursor(UI_CURSOR_GRABLOCKED, 2, 14); + initPixmapCursor(UI_CURSOR_PIPETTE, 3, 29); initPixmapCursor(UI_CURSOR_TOOLTRANSLATE, 1, 1); initPixmapCursor(UI_CURSOR_TOOLROTATE, 1, 1); initPixmapCursor(UI_CURSOR_TOOLSCALE, 1, 1); @@ -3006,8 +1587,14 @@ void LLWindowMacOSX::initCursors() initPixmapCursor(UI_CURSOR_TOOLMEDIAOPEN, 1, 1); initPixmapCursor(UI_CURSOR_TOOLSIT, 20, 15); initPixmapCursor(UI_CURSOR_TOOLBUY, 20, 15); + initPixmapCursor(UI_CURSOR_TOOLPAY, 20, 15); initPixmapCursor(UI_CURSOR_TOOLOPEN, 20, 15); - initPixmapCursor(UI_CURSOR_TOOLPAY, 1, 1); + /*initPixmapCursor(UI_CURSOR_TOOLPATHFINDING, 16, 16); + initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START, 16, 16); + initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD, 16, 16); + initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_END, 16, 16); + initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD, 16, 16); + initPixmapCursor(UI_CURSOR_TOOLNO, 8, 8);*/ initPixmapCursor(UI_CURSOR_SIZENWSE, 10, 10); initPixmapCursor(UI_CURSOR_SIZENESW, 10, 10); @@ -3035,7 +1622,7 @@ void LLWindowMacOSX::hideCursor() // LL_INFOS() << "hideCursor: hiding" << LL_ENDL; mCursorHidden = TRUE; mHideCursorPermanent = TRUE; - ::HideCursor(); + hideNSCursor(); } else { @@ -3052,7 +1639,7 @@ void LLWindowMacOSX::showCursor() // LL_INFOS() << "showCursor: showing" << LL_ENDL; mCursorHidden = FALSE; mHideCursorPermanent = FALSE; - ::ShowCursor(); + showNSCursor(); } else { @@ -3096,53 +1683,18 @@ LLSplashScreenMacOSX::~LLSplashScreenMacOSX() void LLSplashScreenMacOSX::showImpl() { // This code _could_ be used to display a spash screen... -#if 0 - IBNibRef nib = NULL; - OSStatus err; - - err = CreateNibReference(CFSTR("SecondLife"), &nib); - - if(err == noErr) - { - CreateWindowFromNib(nib, CFSTR("Splash Screen"), &mWindow); - - DisposeNibReference(nib); - } - - if(mWindow != NULL) - { - ShowWindow(mWindow); - } -#endif } void LLSplashScreenMacOSX::updateImpl(const std::string& mesg) { +#if 0 if(mWindow != NULL) { CFStringRef string = NULL; string = CFStringCreateWithCString(NULL, mesg.c_str(), kCFStringEncodingUTF8); - - if(string != NULL) - { - ControlRef progressText = NULL; - ControlID id; - OSStatus err; - - id.signature = 'what'; - id.id = 0; - - err = GetControlByID(mWindow, &id, &progressText); - if(err == noErr) - { - err = SetControlData(progressText, kControlEntireControl, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&string); - Draw1Control(progressText); - } - - CFRelease(string); - } } +#endif } @@ -3150,134 +1702,32 @@ void LLSplashScreenMacOSX::hideImpl() { if(mWindow != NULL) { - DisposeWindow(mWindow); mWindow = NULL; } } - - S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption, U32 type) { - S32 result = OSBTN_CANCEL; - SInt16 retval_mac = 1; - AlertStdCFStringAlertParamRec params; - CFStringRef errorString = NULL; - CFStringRef explanationString = NULL; - DialogRef alert = NULL; - AlertType alertType = kAlertCautionAlert; - OSStatus err; - - explanationString = CFStringCreateWithCString(NULL, text.c_str(), kCFStringEncodingUTF8); - errorString = CFStringCreateWithCString(NULL, caption.c_str(), kCFStringEncodingUTF8); - - params.version = kStdCFStringAlertVersionOne; - params.movable = false; - params.helpButton = false; - params.defaultText = (CFStringRef)kAlertDefaultOKText; - params.cancelText = 0; - params.otherText = 0; - params.defaultButton = 1; - params.cancelButton = 0; - params.position = kWindowDefaultPosition; - params.flags = 0; - - switch(type) - { - case OSMB_OK: - default: - break; - case OSMB_OKCANCEL: - params.cancelText = (CFStringRef)kAlertDefaultCancelText; - params.cancelButton = 2; - break; - case OSMB_YESNO: - alertType = kAlertNoteAlert; - params.defaultText = CFSTR("Yes"); - params.cancelText = CFSTR("No"); - params.cancelButton = 2; - break; - } - - if(gWindowImplementation != NULL) - gWindowImplementation->beforeDialog(); - - err = CreateStandardAlert( - alertType, - errorString, - explanationString, - ¶ms, - &alert); - - if(err == noErr) - { - err = RunStandardAlert( - alert, - NULL, - &retval_mac); - } - - if(gWindowImplementation != NULL) - gWindowImplementation->afterDialog(); - - switch(type) - { - case OSMB_OK: - case OSMB_OKCANCEL: - default: - if(retval_mac == 1) - result = OSBTN_OK; - else - result = OSBTN_CANCEL; - break; - case OSMB_YESNO: - if(retval_mac == 1) - result = OSBTN_YES; - else - result = OSBTN_NO; - break; - } - - if(errorString != NULL) - { - CFRelease(errorString); - } - - if(explanationString != NULL) - { - CFRelease(explanationString); - } - - return result; + return showAlert(text, caption, type); } // Open a URL with the user's default web browser. // Must begin with protocol identifier. void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) { - bool found = false; - S32 i; - for (i = 0; i < gURLProtocolWhitelistCount; i++) - { - if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos) - { - found = true; - break; - } - } - - if (!found) + // I'm fairly certain that this is all legitimate under Apple's currently supported APIs. + if (!isWhitelistedProtocol(escaped_url)) { LL_WARNS() << "spawn_web_browser called for url with protocol not on whitelist: " << escaped_url << LL_ENDL; return; } - OSStatus result = noErr; + S32 result = 0; CFURLRef urlRef = NULL; LL_INFOS() << "Opening URL " << escaped_url << LL_ENDL; - CFStringRef stringRef = CFStringCreateWithBytes(NULL, (UInt8 *)escaped_url.c_str(), strlen(escaped_url.c_str()), kCFStringEncodingUTF8, false); + CFStringRef stringRef = CFStringCreateWithCString(NULL, escaped_url.c_str(), kCFStringEncodingUTF8); if (stringRef) { // This will succeed if the string is a full URL, including the http:// @@ -3306,105 +1756,39 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) } } -void LLWindowMacOSX::setTitle(const std::string &title) -{ - /*strncpy((char*)mWindowTitle + 1, title.c_str(), 253); - mWindowTitle[0] = title.length();*/ - - CFStringRef title_str = CFStringCreateWithCString(NULL, title.c_str(), kCFStringEncodingUTF8); - SetWindowTitleWithCFString(mWindow, title_str); -} - -// virtual -void LLWindowMacOSX::ShellEx(const std::string& command) -{ - char * path = NULL; - asprintf(&path, "%s %s", (char*)"file://", command.c_str()); - CFURLRef url = CFURLCreateAbsoluteURLWithBytes(NULL, (UInt8 *)path, strlen(path), - kCFURLPOSIXPathStyle, NULL, true); - if (url != NULL) - { - LSOpenCFURLRef(url, NULL); - CFRelease(url); - } - free(path); -} - LLSD LLWindowMacOSX::getNativeKeyData() { LLSD result = LLSD::emptyMap(); if(mRawKeyEvent) { - char char_code = 0; - UInt32 key_code = 0; - UInt32 modifiers = 0; - UInt32 keyboard_type = 0; - - GetEventParameter (mRawKeyEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &char_code); - GetEventParameter (mRawKeyEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &key_code); - GetEventParameter (mRawKeyEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - GetEventParameter (mRawKeyEvent, kEventParamKeyboardType, typeUInt32, NULL, sizeof(UInt32), NULL, &keyboard_type); - - result["char_code"] = (S32)char_code; - result["key_code"] = (S32)key_code; - result["modifiers"] = (S32)modifiers; - result["keyboard_type"] = (S32)keyboard_type; - -#if 0 - // This causes trouble for control characters -- apparently character codes less than 32 (escape, control-A, etc) - // cause llsd serialization to create XML that the llsd deserializer won't parse! - std::string unicode; - OSStatus err = noErr; - EventParamType actualType = typeUTF8Text; - UInt32 actualSize = 0; - char *buffer = NULL; - - err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, 0, &actualSize, NULL); - if(err == noErr) - { - // allocate a buffer and get the actual data. - buffer = new char[actualSize]; - err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, actualSize, &actualSize, buffer); - if(err == noErr) - { - unicode.assign(buffer, actualSize); - } - delete[] buffer; - } - - result["unicode"] = unicode; -#endif - + result["event_type"] = LLSD::Integer(mRawKeyEvent->mEventType); + result["event_modifiers"] = LLSD::Integer(mRawKeyEvent->mEventModifiers); + result["event_keycode"] = LLSD::Integer(mRawKeyEvent->mEventKeyCode); + result["event_chars"] = (mRawKeyEvent->mEventChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventChars)) : LLSD(); + result["event_umodchars"] = (mRawKeyEvent->mEventUnmodChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventUnmodChars)) : LLSD(); + result["event_isrepeat"] = LLSD::Boolean(mRawKeyEvent->mEventRepeat); } - LL_DEBUGS() << "native key data is: " << result << LL_ENDL; return result; } - BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b) { BOOL retval = FALSE; OSErr error = noErr; NColorPickerInfo info; - + memset(&info, 0, sizeof(info)); info.theColor.color.rgb.red = (UInt16)(*r * 65535.f); info.theColor.color.rgb.green = (UInt16)(*g * 65535.f); info.theColor.color.rgb.blue = (UInt16)(*b * 65535.f); info.placeWhere = kCenterOnMainScreen; - if(gWindowImplementation != NULL) - gWindowImplementation->beforeDialog(); - error = NPickColor(&info); - - if(gWindowImplementation != NULL) - gWindowImplementation->afterDialog(); - + if (error == noErr) { retval = info.newColorChosen; @@ -3415,54 +1799,18 @@ BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b) *b = ((float) info.theColor.color.rgb.blue) / 65535.0; } } + return (retval); } - void *LLWindowMacOSX::getPlatformWindow() { // NOTE: this will be NULL in fullscreen mode. Plan accordingly. return (void*)mWindow; } -void *LLWindowMacOSX::getMediaWindow() -{ - /* - Mozilla needs to be initialized with a WindowRef to function properly. - (There's no good reason for this, since it shouldn't be interacting with our window in any way, but that's another issue.) - If we're in windowed mode, we _could_ hand it our actual window pointer, but a subsequent switch to fullscreen will destroy that window, - which trips up Mozilla. - Instead of using our actual window, we create an invisible window which will persist for the lifetime of the application and pass that to Mozilla. - This satisfies its deep-seated need to latch onto a WindowRef and solves the issue with switching between fullscreen and windowed modes. - - Note that we will never destroy this window (by design!), but since only one will ever be created per run of the application, that's okay. - */ - - if(sMediaWindow == NULL) - { - Rect window_rect = {100, 100, 200, 200}; - - sMediaWindow = NewCWindow( - NULL, - &window_rect, - (ConstStr255Param) "\p", - false, // Create the window invisible. - zoomDocProc, // Window with a grow box and a zoom box - kLastWindowOfClass, // create it behind other windows - false, // no close box - 0); - } - - return (void*)sMediaWindow; -} - -void LLWindowMacOSX::stopDockTileBounce() -{ - NMRemove(&mBounceRec); - mBounceTimer.stop(); -} - // get a double value from a dictionary +/* static double getDictDouble (CFDictionaryRef refDict, CFStringRef key) { double double_value; @@ -3472,7 +1820,7 @@ static double getDictDouble (CFDictionaryRef refDict, CFStringRef key) if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &double_value)) // or if cant convert it return -1; // fail return double_value; // otherwise return the long value -} +}*/ // get a long value from a dictionary static long getDictLong (CFDictionaryRef refDict, CFStringRef key) @@ -3488,8 +1836,6 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key) void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) { - ScriptLanguageRecord script_language; - if (preeditor != mPreeditor && !b) { // This condition may occur by a call to @@ -3500,9 +1846,7 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) // is not disturbed. return; } - - UseInputWindow(mTSMDocument, !b); - + // Take care of old and new preeditors. if (preeditor != mPreeditor || !b) { @@ -3515,44 +1859,18 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) } mPreeditor = (b ? preeditor : NULL); } - + if (b == mLanguageTextInputAllowed) { return; } mLanguageTextInputAllowed = b; - - if (b) - { - if (mTSMScriptCode != smRoman) - { - script_language.fScript = mTSMScriptCode; - script_language.fLanguage = mTSMLangCode; - SetTextServiceLanguage(&script_language); - } - } - else - { - GetTextServiceLanguage(&script_language); - mTSMScriptCode = script_language.fScript; - mTSMLangCode = script_language.fLanguage; - if (mTSMScriptCode != smRoman) - { - script_language.fScript = smRoman; - script_language.fLanguage = langEnglish; - SetTextServiceLanguage(&script_language); - } - } + allowDirectMarkedTextInput(b, mGLView); // mLanguageTextInputAllowed and mMarkedTextAllowed should be updated at once (by Pell Smit } void LLWindowMacOSX::interruptLanguageTextInput() { - if (mTSMDocument) - { - FixTSMDocument(mTSMDocument); - } - // Don't we need to call resetPreedit here? - // Well, if Apple's TSM document is correct, we don't. + commitCurrentPreedit(mGLView); } //static @@ -3563,21 +1881,32 @@ std::vector LLWindowMacOSX::getDynamicFallbackFontList() } // static -MASK LLWindowMacOSX::modifiersToMask(SInt16 modifiers) +MASK LLWindowMacOSX::modifiersToMask(S16 modifiers) { MASK mask = 0; - if(modifiers & shiftKey) { mask |= MASK_SHIFT; } - if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; } - if(modifiers & optionKey) { mask |= MASK_ALT; } + if(modifiers & MAC_SHIFT_KEY) { mask |= MASK_SHIFT; } + if(modifiers & (MAC_CMD_KEY | MAC_CTRL_KEY)) { mask |= MASK_CONTROL; } + if(modifiers & MAC_ALT_KEY) { mask |= MASK_ALT; } return mask; } -#if LL_OS_DRAGDROP_ENABLED +//[CR:Retina] +F32 LLWindowMacOSX::getScaleFactor() +{ + return ::getScaleFactor(mGLView); +} + +void LLWindowMacOSX::updateUnreadCount(S32 num_conversations) +{ + updateBadge(num_conversations); +} -OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, +#if LL_OS_DRAGDROP_ENABLED +/* +S16 LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef drag) { - OSErr result = noErr; + S16 result = 0; LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon; LL_DEBUGS() << "drag tracking handler, message = " << message << LL_ENDL; @@ -3602,7 +1931,6 @@ OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef return result; } - OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef drag) { @@ -3610,126 +1938,69 @@ OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefC return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED); } - -OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDropAction action) +*/ +void LLWindowMacOSX::handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action) { - OSErr result = dragNotAcceptedErr; // overall function result - OSErr err = noErr; // for local error handling + MASK mask = LLWindowMacOSX::modifiersToMask(getModifiers()); - // Get the mouse position and modifiers of this drag. - SInt16 modifiers, mouseDownModifiers, mouseUpModifiers; - ::GetDragModifiers(drag, &modifiers, &mouseDownModifiers, &mouseUpModifiers); - MASK mask = LLWindowMacOSX::modifiersToMask(modifiers); - - Point mouse_point; - // This will return the mouse point in global screen coords - ::GetDragMouse(drag, &mouse_point, NULL); - LLCoordScreen screen_coords(mouse_point.h, mouse_point.v); + float mouse_point[2]; + // This will return the mouse point in window coords + getCursorPos(mWindow, mouse_point); + LLCoordWindow window_coords(mouse_point[0], mouse_point[1]); LLCoordGL gl_pos; - convertCoords(screen_coords, &gl_pos); - - // Look at the pasteboard and try to extract an URL from it - PasteboardRef pasteboard; - if(GetDragPasteboard(drag, &pasteboard) == noErr) + convertCoords(window_coords, &gl_pos); + + if(!url.empty()) { - ItemCount num_items = 0; - // Treat an error here as an item count of 0 - (void)PasteboardGetItemCount(pasteboard, &num_items); - - // Only deal with single-item drags. - if(num_items == 1) - { - PasteboardItemID item_id = NULL; - CFArrayRef flavors = NULL; - CFDataRef data = NULL; - - err = PasteboardGetItemIdentifier(pasteboard, 1, &item_id); // Yes, this really is 1-based. - - // Try to extract an URL from the pasteboard - if(err == noErr) - { - err = PasteboardCopyItemFlavors( pasteboard, item_id, &flavors); - } - - if(err == noErr) - { - if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeURL)) - { - // This is an URL. - err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeURL, &data); - } - else if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeUTF8PlainText)) + LLWindowCallbacks::DragNDropResult res = + mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url); + + switch (res) { + case LLWindowCallbacks::DND_NONE: // No drop allowed + if (action == LLWindowCallbacks::DNDA_TRACK) { - // This is a string that might be an URL. - err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data); + mDragOverrideCursor = 0; } - - } - - if(flavors != NULL) - { - CFRelease(flavors); - } - - if(data != NULL) - { - std::string url; - url.assign((char*)CFDataGetBytePtr(data), CFDataGetLength(data)); - CFRelease(data); - - if(!url.empty()) - { - LLWindowCallbacks::DragNDropResult res = - mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url); - - switch (res) { - case LLWindowCallbacks::DND_NONE: // No drop allowed - if (action == LLWindowCallbacks::DNDA_TRACK) - { - mDragOverrideCursor = kThemeNotAllowedCursor; - } - else { - mDragOverrideCursor = -1; - } - break; - case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation - mDragOverrideCursor = kThemePointingHandCursor; - result = noErr; - break; - case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation - mDragOverrideCursor = kThemeCopyArrowCursor; - result = noErr; - break; - case LLWindowCallbacks::DND_LINK: // Drop accepted would result in a "link" operation: - mDragOverrideCursor = kThemeAliasArrowCursor; - result = noErr; - break; - default: - mDragOverrideCursor = -1; - break; - } - // This overrides the cursor being set by setCursor. - // This is a bit of a hack workaround because lots of areas - // within the viewer just blindly set the cursor. - if (mDragOverrideCursor == -1) - { - // Restore the cursor - ECursorType temp_cursor = mCurrentCursor; - // get around the "setting the same cursor" code in setCursor() - mCurrentCursor = UI_CURSOR_COUNT; - setCursor(temp_cursor); - } - else { - // Override the cursor - SetThemeCursor(mDragOverrideCursor); - } - + else { + mDragOverrideCursor = -1; } - } + break; + case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation + mDragOverrideCursor = UI_CURSOR_NO; + break; + case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation + mDragOverrideCursor = UI_CURSOR_ARROWCOPY; + break; + default: + mDragOverrideCursor = -1; + break; + } + // This overrides the cursor being set by setCursor. + // This is a bit of a hack workaround because lots of areas + // within the viewer just blindly set the cursor. + if (mDragOverrideCursor == -1) + { + // Restore the cursor + ECursorType temp_cursor = mCurrentCursor; + // get around the "setting the same cursor" code in setCursor() + mCurrentCursor = UI_CURSOR_COUNT; + setCursor(temp_cursor); + } + else { + // Override the cursor + switch (mDragOverrideCursor) { + case 0: + setArrowCursor(); + break; + case UI_CURSOR_NO: + setNotAllowedCursor(); + case UI_CURSOR_ARROWCOPY: + setCopyCursor(); + default: + break; + }; } } - - return result; } #endif // LL_OS_DRAGDROP_ENABLED diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index d8d46edb94..581a445634 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -29,22 +29,23 @@ #include "llwindow.h" #include "llwindowcallbacks.h" +#include "llwindowmacosx-objc.h" #include "lltimer.h" -#include -#include +#include +#include // AssertMacros.h does bad things. +#include "fix_macros.h" #undef verify -#undef check #undef require class LLWindowMacOSX : public LLWindow { public: - /*virtual*/ void show(); + /*virtual*/ void show(bool focus = true); /*virtual*/ void hide(); /*virtual*/ void close(); /*virtual*/ BOOL getVisible(); @@ -60,7 +61,7 @@ class LLWindowMacOSX : public LLWindow /*virtual*/ BOOL setPosition(LLCoordScreen position); /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL); + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = nullptr); /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); /*virtual*/ void showCursor(); @@ -76,19 +77,18 @@ class LLWindowMacOSX : public LLWindow /*virtual*/ BOOL isClipboardTextAvailable(); /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst); /*virtual*/ BOOL copyTextToClipboard(const LLWString & src); + /*virtual*/ void setWindowTitle(const std::string& title); /*virtual*/ void flashIcon(F32 seconds); /*virtual*/ F32 getGamma(); /*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma /*virtual*/ U32 getFSAASamples(); /*virtual*/ void setFSAASamples(const U32 fsaa_samples); - /*virtual*/ void setVsyncMode(const S32 vsync_mode); - /*virtual*/ S32 getVsyncMode(); /*virtual*/ BOOL restoreGamma(); // Restore original gamma table (before updating gamma) /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; } /*virtual*/ void gatherInput(); /*virtual*/ void delayInputProcessing() {}; /*virtual*/ void swapBuffers(); - + // handy coordinate space conversion routines /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to); /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to); @@ -108,26 +108,34 @@ class LLWindowMacOSX : public LLWindow /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b); /*virtual*/ void *getPlatformWindow(); - /*virtual*/ void *getMediaWindow(); /*virtual*/ void bringToFront() {}; /*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b); /*virtual*/ void interruptLanguageTextInput(); /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); - - /*virtual*/ void setTitle(const std::string &title); - /*virtual*/ void ShellEx(const std::string& command); + /*virtual*/ F32 getScaleFactor(); + /*virtual*/ void updateUnreadCount(S32 num_conversations); static std::vector getDynamicFallbackFontList(); // Provide native key event data /*virtual*/ LLSD getNativeKeyData(); - + + void* getWindow() { return mWindow; } + LLWindowCallbacks* getCallbacks() { return mCallbacks; } + LLPreeditor* getPreeditor() { return mPreeditor; } + + void updateMouseDeltas(double* deltas); + void getMouseDeltas(S32* delta); + + void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action); + + bool allowsLanguageInput() { return mLanguageTextInputAllowed; } protected: LLWindowMacOSX(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags, - BOOL fullscreen, BOOL clearBg, const S32 vsync_mode, + BOOL fullscreen, BOOL clearBg, S32 vsync_setting, BOOL ignore_pixel_depth, U32 fsaa_samples); ~LLWindowMacOSX(); @@ -148,6 +156,8 @@ class LLWindowMacOSX : public LLWindow BOOL shouldPostQuit() { return mPostQuit; } +private: + void restoreGLContext(); protected: // @@ -155,43 +165,36 @@ class LLWindowMacOSX : public LLWindow // // create or re-create the GL context/window. Called from the constructor and switchContext(). - BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, const S32 vsync_mode); + BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, S32 vsync_setting); void destroyContext(); void setupFailure(const std::string& text, const std::string& caption, U32 type); - static pascal OSStatus staticEventHandler (EventHandlerCallRef myHandler, EventRef event, void* userData); - static pascal Boolean staticMoveEventComparator( EventRef event, void* data); - OSStatus eventHandler (EventHandlerCallRef myHandler, EventRef event); void adjustCursorDecouple(bool warpingMouse = false); - void stopDockTileBounce(); - static MASK modifiersToMask(SInt16 modifiers); + static MASK modifiersToMask(S16 modifiers); #if LL_OS_DRAGDROP_ENABLED - static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, - void * handlerRefCon, DragRef theDrag); - static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag); - OSErr handleDragNDrop(DragRef theDrag, LLWindowCallbacks::DragNDropAction action); + + //static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef theDrag); + //static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag); + + #endif // LL_OS_DRAGDROP_ENABLED // // Platform specific variables // - WindowRef mWindow; - AGLContext mContext; - AGLPixelFormat mPixelFormat; + + // Use generic pointers here. This lets us do some funky Obj-C interop using Obj-C objects without having to worry about any compilation problems that may arise. + NSWindowRef mWindow; + GLViewRef mGLView; + CGLContextObj mContext; + CGLPixelFormatObj mPixelFormat; CGDirectDisplayID mDisplay; - CFDictionaryRef mOldDisplayMode; - EventLoopTimerRef mTimer; - EventHandlerUPP mEventHandlerUPP; - EventHandlerRef mGlobalHandlerRef; - EventHandlerRef mWindowHandlerRef; - EventComparatorUPP mMoveEventCampartorUPP; - Rect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse() - Rect mPreviousWindowRect; // Save previous window for un-maximize event - Str255 mWindowTitle; + LLRect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse() + std::string mWindowTitle; double mOriginalAspectRatio; BOOL mSimulatedRightClick; - UInt32 mLastModifiers; + U32 mLastModifiers; BOOL mHandsOffEvents; // When true, temporarially disable CarbonEvent processing. // Used to allow event processing when putting up dialogs in fullscreen mode. BOOL mCursorDecoupled; @@ -204,28 +207,18 @@ class LLWindowMacOSX : public LLWindow BOOL mMaximized; BOOL mMinimized; U32 mFSAASamples; - S32 mVsyncMode; BOOL mForceRebuild; - S32 mDragOverrideCursor; - - F32 mBounceTime; - NMRec mBounceRec; - LLTimer mBounceTimer; + S32 mDragOverrideCursor; // Input method management through Text Service Manager. - TSMDocumentID mTSMDocument; BOOL mLanguageTextInputAllowed; - ScriptCode mTSMScriptCode; - LangCode mTSMLangCode; LLPreeditor* mPreeditor; static BOOL sUseMultGL; friend class LLWindowManager; - static WindowRef sMediaWindow; - EventRef mRawKeyEvent; - + }; diff --git a/indra/llwindow/llwindowmesaheadless.h b/indra/llwindow/llwindowmesaheadless.h index 6c0e872e21..e116225769 100644 --- a/indra/llwindow/llwindowmesaheadless.h +++ b/indra/llwindow/llwindowmesaheadless.h @@ -35,7 +35,7 @@ class LLWindowMesaHeadless : public LLWindow { public: - /*virtual*/ void show() {}; + /*virtual*/ void show(bool) {}; /*virtual*/ void hide() {}; /*virtual*/ void close() {}; /*virtual*/ BOOL getVisible() {return FALSE;}; @@ -51,7 +51,7 @@ class LLWindowMesaHeadless : public LLWindow /*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;}; /*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;}; /*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;}; - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL) {return FALSE;}; + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = NULL) {return FALSE;}; /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;}; /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;}; /*virtual*/ void showCursor() {}; diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 36bcd266bd..4502a57903 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -45,9 +45,13 @@ #if LL_GTK extern "C" { -# include "gtk/gtk.h" +#include +#include +#if GTK_CHECK_VERSION(2, 24, 0) +#include +#endif } -#include +#include #endif // LL_GTK extern "C" { @@ -86,23 +90,6 @@ static bool ATIbug = false; // be only one object of this class at any time. Currently this is true. static LLWindowSDL *gWindowImplementation = NULL; - -void maybe_lock_display(void) -{ - if (gWindowImplementation && gWindowImplementation->Lock_Display) { - gWindowImplementation->Lock_Display(); - } -} - - -void maybe_unlock_display(void) -{ - if (gWindowImplementation && gWindowImplementation->Unlock_Display) { - gWindowImplementation->Unlock_Display(); - } -} - - #if LL_GTK // Lazily initialize and check the runtime GTK version for goodness. // static @@ -116,9 +103,7 @@ bool LLWindowSDL::ll_try_gtk_init(void) if (!done_setlocale) { LL_INFOS() << "Starting GTK Initialization." << LL_ENDL; - maybe_lock_display(); gtk_disable_setlocale(); - maybe_unlock_display(); done_setlocale = TRUE; } @@ -128,9 +113,7 @@ bool LLWindowSDL::ll_try_gtk_init(void) #if !GLIB_CHECK_VERSION(2, 32, 0) if (!g_thread_supported ()) g_thread_init (NULL); #endif - maybe_lock_display(); gtk_is_good = gtk_init_check(NULL, NULL); - maybe_unlock_display(); if (!gtk_is_good) LL_WARNS() << "GTK Initialization failed." << LL_ENDL; } @@ -146,12 +129,10 @@ bool LLWindowSDL::ll_try_gtk_init(void) << gtk_major_version << "." << gtk_minor_version << "." << gtk_micro_version << LL_ENDL; - maybe_lock_display(); const gchar* gtk_warning = gtk_check_version( GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); - maybe_unlock_display(); if (gtk_warning) { LL_WARNS() << "- GTK COMPATIBILITY WARNING: " << @@ -197,14 +178,14 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, const S32 vsync_mode, BOOL ignore_pixel_depth, U32 fsaa_samples) : LLWindow(callbacks, fullscreen, flags), - Lock_Display(NULL), - Unlock_Display(NULL), mGamma(1.0f) + mGamma(1.0f) { // Initialize the keyboard gKeyboard = new LLKeyboardSDL(); gKeyboard->setCallbacks(callbacks); // Note that we can't set up key-repeat until after SDL has init'd video + // Ignore use_gl for now, only used for drones on PC mWindow = NULL; mNeedsResize = FALSE; mOverrideAspectRatio = 0.f; @@ -230,7 +211,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, mOriginalAspectRatio = 1024.0 / 768.0; if (title.empty()) - mWindowTitle = "SDL Window"; // *FIX: (???) + mWindowTitle = "SDL Window"; // *FIX: (?) else mWindowTitle = title; @@ -315,7 +296,7 @@ static int x11_detect_VRAM_kb() #if LL_SOLARIS && defined(__sparc) // NOTE: there's no Xorg server on SPARC so just return 0 // and allow SDL to attempt to get the amount of VRAM - return(0); + return 0; #else std::string x_log_location("/var/log/"); @@ -423,7 +404,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B // Set the application icon. SDL_Surface *bmpsurface; - bmpsurface = Load_BMP_Resource("singularity_icon.BMP"); + bmpsurface = Load_BMP_Resource("viewer_icon.BMP"); if (bmpsurface) { // This attempts to give a black-keyed mask to the icon. @@ -594,7 +575,6 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B mWindow = SDL_SetVideoMode(width, height, bits, sdlflags); } - if (!mWindow) { LL_WARNS() << "createContext: window creation failure. SDL: " << SDL_GetError() << LL_ENDL; @@ -607,13 +587,14 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B } // Detect video memory size. -# if LL_X11 +#if LL_X11 gGLManager.mVRAM = x11_detect_VRAM_kb() / 1024; if (gGLManager.mVRAM != 0) { LL_INFOS() << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL; - } else -# endif // LL_X11 + } + else +#endif // LL_X11 { // fallback to letting SDL detect VRAM. // note: I've not seen SDL's detection ever actually find @@ -677,23 +658,6 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B return FALSE; } -#if 0 // *FIX: we're going to brave it for now... - if (alphaBits < 8) - { - close(); - setupFailure( - "Second Life is unable to run because it can't get an 8 bit alpha\n" - "channel. Usually this is due to video card driver issues.\n" - "Please make sure you have the latest video card drivers installed.\n" - "Also be sure your monitor is set to True Color (32-bit) in\n" - "Control Panels -> Display -> Settings.\n" - "If you continue to receive this message, contact customer service.", - "Error", - OSMB_OK); - return FALSE; - } -#endif - #if LL_X11 /* Grab the window manager specific information */ SDL_SysWMinfo info; @@ -705,8 +669,6 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B { mSDL_Display = info.info.x11.display; mSDL_XWindowID = info.info.x11.wmwindow; - Lock_Display = info.info.x11.lock_func; - Unlock_Display = info.info.x11.unlock_func; } else { @@ -773,7 +735,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B // changing fullscreen resolution, or switching between windowed and fullscreen mode. -BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp) +BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp) { const BOOL needsRebuild = TRUE; // Just nuke the context and start over. BOOL result = true; @@ -782,6 +744,7 @@ BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, cons stop_glerror(); if(needsRebuild) { + if (stopFn) stopFn(); destroyContext(); result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, vsync_mode); if (result) @@ -790,6 +753,7 @@ BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, cons initCursors(); setCursor( UI_CURSOR_ARROW ); } + if (restoreFn) restoreFn(true); } stop_glerror(); @@ -804,8 +768,6 @@ void LLWindowSDL::destroyContext() #if LL_X11 mSDL_Display = NULL; mSDL_XWindowID = None; - Lock_Display = NULL; - Unlock_Display = NULL; #endif // LL_X11 // Clean up remaining GL state before blowing away window @@ -831,7 +793,7 @@ LLWindowSDL::~LLWindowSDL() } -void LLWindowSDL::show() +void LLWindowSDL::show(bool focus) { // *FIX: What to do with SDL? } @@ -960,7 +922,7 @@ BOOL LLWindowSDL::setPosition(const LLCoordScreen position) { if(mWindow) { - // *FIX: (???) + // *FIX: (?) //MacMoveWindow(mWindow, position.mX, position.mY, false); } @@ -1206,9 +1168,7 @@ void LLWindowSDL::beforeDialog() { // Everything that we/SDL asked for should happen before we // potentially hand control over to GTK. - maybe_lock_display(); XSync(mSDL_Display, False); - maybe_unlock_display(); } #endif // LL_X11 @@ -1217,8 +1177,6 @@ void LLWindowSDL::beforeDialog() // diagnostics, if not already done. ll_try_gtk_init(); #endif // LL_GTK - - maybe_lock_display(); } void LLWindowSDL::afterDialog() @@ -1230,8 +1188,6 @@ void LLWindowSDL::afterDialog() LL_INFOS() << "LLWindowSDL::afterDialog()" << LL_ENDL; - maybe_unlock_display(); - if (mFullscreen) { // need to restore fullscreen mode after dialog - only works @@ -1254,7 +1210,6 @@ void LLWindowSDL::x11_set_urgent(BOOL urgent) LL_INFOS() << "X11 hint for urgency, " << urgent << LL_ENDL; - maybe_lock_display(); wm_hints = XGetWMHints(mSDL_Display, mSDL_XWindowID); if (!wm_hints) wm_hints = XAllocWMHints(); @@ -1267,7 +1222,6 @@ void LLWindowSDL::x11_set_urgent(BOOL urgent) XSetWMHints(mSDL_Display, mSDL_XWindowID, wm_hints); XFree(wm_hints); XSync(mSDL_Display, False); - maybe_unlock_display(); } } #endif // LL_X11 @@ -1432,18 +1386,25 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso { modes--; SDL_Rect *r = *modes; - int w = r->w; - int h = r->h; + S32 w = r->w; + S32 h = r->h; if ((w >= 800) && (h >= 600)) { // make sure we don't add the same resolution multiple times! - if ( (mNumSupportedResolutions == 0) || - ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) && - (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) ) + bool resolution_exists = false; + for (S32 i = 0; i < mNumSupportedResolutions; ++i) + { + if (mSupportedResolutions[i].mWidth == w && + mSupportedResolutions[i].mHeight == h) + { + resolution_exists = true; + break; + } + } + if (!resolution_exists) { mSupportedResolutions[mNumSupportedResolutions].mWidth = w; - mSupportedResolutions[mNumSupportedResolutions].mHeight = h; - mNumSupportedResolutions++; + mSupportedResolutions[mNumSupportedResolutions++].mHeight = h; } } } @@ -1567,12 +1528,10 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture) { //LL_INFOS() << "X11 POINTER GRABBY" << LL_ENDL; //newmode = SDL_WM_GrabInput(wantmode); - maybe_lock_display(); result = XGrabPointer(mSDL_Display, mSDL_XWindowID, True, 0, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - maybe_unlock_display(); if (GrabSuccess == result) newmode = SDL_GRAB_ON; else @@ -1583,11 +1542,9 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture) newmode = SDL_GRAB_OFF; //newmode = SDL_WM_GrabInput(SDL_GRAB_OFF); - maybe_lock_display(); XUngrabPointer(mSDL_Display, CurrentTime); // Make sure the ungrab happens RIGHT NOW. - XSync(mSDL_Display, False); - maybe_unlock_display(); + XSync(mSDL_Display, FALSE); } else { newmode = SDL_GRAB_QUERY; // neutral @@ -1784,6 +1741,7 @@ void LLWindowSDL::gatherInput() mKeyScanCode = event.key.keysym.scancode; mKeyVirtualKey = event.key.keysym.unicode; mKeyModifiers = event.key.keysym.mod; + mKeySym = event.key.keysym.sym; gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod); // part of the fix for SL-13243 @@ -1801,6 +1759,7 @@ void LLWindowSDL::gatherInput() mKeyScanCode = event.key.keysym.scancode; mKeyVirtualKey = event.key.keysym.unicode; mKeyModifiers = event.key.keysym.mod; + mKeySym = event.key.keysym.sym; if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0) SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243 @@ -2311,9 +2270,12 @@ S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 typ gWindowImplementation->mSDL_XWindowID != None) { gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin - GdkWindow *gdkwin = gdk_window_foreign_new(gWindowImplementation->mSDL_XWindowID); - gdk_window_set_transient_for(GTK_WIDGET(win)->window, - gdkwin); +#if GTK_CHECK_VERSION(2, 24, 0) + GdkWindow* gdkwin = gdk_x11_window_foreign_new_for_display(gdk_display_get_default(), static_cast(gWindowImplementation->mSDL_XWindowID)); +#else + GdkWindow* gdkwin = gdk_window_foreign_new(static_cast(gWindowImplementation->mSDL_XWindowID)); +#endif + gdk_window_set_transient_for(gtk_widget_get_window(GTK_WIDGET(win)), gdkwin); } # endif //LL_X11 @@ -2402,6 +2364,7 @@ LLSD LLWindowSDL::getNativeKeyData() result["scan_code"] = (S32)mKeyScanCode; result["virtual_key"] = (S32)mKeyVirtualKey; result["modifiers"] = (S32)modifiers; + result[ "sdl_sym" ] = (S32)mKeySym; return result; } @@ -2426,13 +2389,16 @@ BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) if (mSDL_XWindowID != None) { gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin - GdkWindow *gdkwin = gdk_window_foreign_new(mSDL_XWindowID); - gdk_window_set_transient_for(GTK_WIDGET(win)->window, - gdkwin); +#if GTK_CHECK_VERSION(2, 24, 0) + GdkWindow* gdkwin = gdk_x11_window_foreign_new_for_display(gdk_display_get_default(), static_cast(mSDL_XWindowID)); +#else + GdkWindow* gdkwin = gdk_window_foreign_new(static_cast(mSDL_XWindowID)); +#endif + gdk_window_set_transient_for(gtk_widget_get_window(GTK_WIDGET(win)), gdkwin); } -# endif //LL_X11 +#endif //LL_X11 - GtkColorSelection *colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG(win)->colorsel); + GtkColorSelection *colorsel = GTK_COLOR_SELECTION (gtk_color_selection_dialog_get_color_selection (GTK_COLOR_SELECTION_DIALOG(win))); GdkColor color, orig_color; orig_color.pixel = 0; @@ -2458,8 +2424,6 @@ BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) gtk_window_set_modal(GTK_WINDOW(win), TRUE); gtk_widget_show_all(win); - // hide the help button - we don't service it. - gtk_widget_hide(GTK_COLOR_SELECTION_DIALOG(win)->help_button); gtk_main(); if (response == GTK_RESPONSE_OK && @@ -2528,18 +2492,7 @@ void exec_cmd(const std::string& cmd, const std::string& arg) // Must begin with protocol identifier. void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) { - bool found = false; - S32 i; - for (i = 0; i < gURLProtocolWhitelistCount; i++) - { - if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos) - { - found = true; - break; - } - } - - if (!found) + if (!isWhitelistedProtocol(escaped_url)) { LL_WARNS() << "spawn_web_browser called for url with protocol not on whitelist: " << escaped_url << LL_ENDL; return; @@ -2551,10 +2504,8 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) # if LL_X11 if (mSDL_Display) { - maybe_lock_display(); // Just in case - before forking. - XSync(mSDL_Display, False); - maybe_unlock_display(); + XSync(mSDL_Display, FALSE); } # endif // LL_X11 @@ -2571,19 +2522,12 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) LL_INFOS() << "spawn_web_browser returning." << LL_ENDL; } -void LLWindowSDL::setTitle(const std::string &title) -{ - mWindowTitle = title; - SDL_WM_SetCaption(mWindowTitle.c_str(),mWindowTitle.c_str()); -} void *LLWindowSDL::getPlatformWindow() { #if LL_GTK && LL_LLMOZLIB_ENABLED if (LLWindowSDL::ll_try_gtk_init()) { - maybe_lock_display(); - GtkWidget *owin = gtk_window_new(GTK_WINDOW_POPUP); // Why a layout widget? A MozContainer would be ideal, but // it involves exposing Mozilla headers to mozlib-using apps. @@ -2595,8 +2539,6 @@ void *LLWindowSDL::getPlatformWindow() gtk_widget_realize(rtnw); GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(rtnw), GTK_NO_WINDOW); - maybe_unlock_display(); - return rtnw; } #endif // LL_GTK && LL_LLMOZLIB_ENABLED @@ -2612,10 +2554,8 @@ void LLWindowSDL::bringToFront() #if LL_X11 if (mSDL_Display && !mFullscreen) { - maybe_lock_display(); XRaiseWindow(mSDL_Display, mSDL_XWindowID); - XSync(mSDL_Display, False); - maybe_unlock_display(); + XSync(mSDL_Display, FALSE); } #endif // LL_X11 } @@ -2626,7 +2566,7 @@ std::vector LLWindowSDL::getDynamicFallbackFontList() // Use libfontconfig to find us a nice ordered list of fallback fonts // specific to this system. std::string final_fallback("/usr/share/fonts/truetype/kochi/kochi-gothic.ttf"); - const int max_font_count_cutoff = 100; // fonts are expensive in the current system, don't enumerate an arbitrary number of them + const int max_font_count_cutoff = 40; // fonts are expensive in the current system, don't enumerate an arbitrary number of them // Our 'ideal' font properties which define the sorting results. // slant=0 means Roman, index=0 means the first face in a font file // (the one we actually use), weight=80 means medium weight, @@ -2721,4 +2661,10 @@ std::vector LLWindowSDL::getDynamicFallbackFontList() return rtns; } +void LLWindowSDL::setTitle(const std::string& title) +{ + mWindowTitle = title; + SDL_WM_SetCaption(mWindowTitle.c_str(),mWindowTitle.c_str()); +} + #endif // LL_SDL diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 3334fcb986..3117821805 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -49,7 +49,7 @@ class LLWindowSDL : public LLWindow { public: - /*virtual*/ void show(); + /*virtual*/ void show(bool focus); /*virtual*/ void hide(); /*virtual*/ void close(); /*virtual*/ BOOL getVisible(); @@ -65,7 +65,7 @@ class LLWindowSDL : public LLWindow /*virtual*/ BOOL setPosition(LLCoordScreen position); /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL); + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = NULL); /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); /*virtual*/ void showCursor(); @@ -135,8 +135,6 @@ class LLWindowSDL : public LLWindow Window mSDL_XWindowID; Display *mSDL_Display; #endif - void (*Lock_Display)(void); - void (*Unlock_Display)(void); #if LL_GTK // Lazily initialize and check the runtime GTK version for goodness. @@ -216,6 +214,7 @@ class LLWindowSDL : public LLWindow U32 mKeyScanCode; U32 mKeyVirtualKey; SDLMod mKeyModifiers; + U32 mKeySym; }; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index fab15ea71b..ded2d827ae 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -42,6 +42,7 @@ #include "llgl.h" #include "llstring.h" #include "lldir.h" +#include "llsdutil.h" #include "llglslshader.h" // System includes @@ -52,6 +53,7 @@ #include #include #include +#include // Require DirectInput version 8 #define DIRECTINPUT_VERSION 0x0800 @@ -73,6 +75,27 @@ const F32 ICON_FLASH_TIME = 0.5f; extern BOOL gDebugWindowProc; +#ifndef WM_DPICHANGED +#define WM_DPICHANGED 0x02E0 +#endif + +#ifndef DPI_ENUMS_DECLARED + +typedef enum PROCESS_DPI_AWARENESS { + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE = 1, + PROCESS_PER_MONITOR_DPI_AWARE = 2 +} PROCESS_DPI_AWARENESS; + +typedef enum MONITOR_DPI_TYPE { + MDT_EFFECTIVE_DPI = 0, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, + MDT_DEFAULT = MDT_EFFECTIVE_DPI +} MONITOR_DPI_TYPE; + +#endif + LPWSTR gIconResource = IDI_APPLICATION; LLW32MsgCallback gAsyncMsgCallback = NULL; @@ -394,9 +417,15 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, mKeyVirtualKey = 0; mhDC = NULL; mhRC = NULL; + mUser32Lib = nullptr; + mSHCoreLib = nullptr; LL_INFOS() << "Desired FSAA Samples = " << mFSAASamples << LL_ENDL; + memset(mCurrentGammaRamp, 0, sizeof(mCurrentGammaRamp)); + memset(mPrevGammaRamp, 0, sizeof(mPrevGammaRamp)); + mCustomGammaSet = FALSE; + // Initialize the keyboard gKeyboard = new LLKeyboardWin32(); gKeyboard->setCallbacks(callbacks); @@ -628,16 +657,15 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, } } - // TODO: add this after resolving _WIN32_WINNT issue - // if (!fullscreen) - // { - // TRACKMOUSEEVENT track_mouse_event; - // track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT ); - // track_mouse_event.dwFlags = TME_LEAVE; - // track_mouse_event.hwndTrack = mWindowHandle; - // track_mouse_event.dwHoverTime = HOVER_DEFAULT; - // TrackMouseEvent( &track_mouse_event ); - // } + if (!fullscreen) + { + TRACKMOUSEEVENT track_mouse_event; + track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT ); + track_mouse_event.dwFlags = TME_LEAVE; + track_mouse_event.hwndTrack = mWindowHandle; + track_mouse_event.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent( &track_mouse_event ); + } //----------------------------------------------------------------------- @@ -646,7 +674,11 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, LLCoordScreen windowPos(x,y); LLCoordScreen windowSize(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top); - if (!switchContext(mFullscreen, windowSize, vsync_mode, &windowPos)) + + initDPIAwareness(); + + + if (!switchContext(mFullscreen, windowSize, vsync_mode, nullptr, nullptr, &windowPos)) { return; } @@ -673,11 +705,22 @@ LLWindowWin32::~LLWindowWin32() delete [] mWindowClassName; mWindowClassName = NULL; + + FreeLibrary(mUser32Lib); + FreeLibrary(mSHCoreLib); +} + +void LLWindowWin32::postInitialized() +{ + float xDPIScale, yDPIScale; + getDPIScales(xDPIScale, yDPIScale); + mCallbacks->handleDPIScaleChange(this, xDPIScale, yDPIScale); } -void LLWindowWin32::show() +void LLWindowWin32::show(bool take_focus) { ShowWindow(mWindowHandle, SW_SHOW); + if (!take_focus) return; SetForegroundWindow(mWindowHandle); SetFocus(mWindowHandle); } @@ -914,7 +957,7 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size) } // changing fullscreen resolution -BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp) +BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp) { GLuint pixel_format; DEVMODE dev_mode; @@ -944,20 +987,25 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, co } gGLManager.shutdownGL(); - //destroy gl context + class ContextHandle + { + public: + ContextHandle(HGLRC context) : mOldContext(context) + {} + ~ContextHandle() + { + wglDeleteContext(mOldContext); + } + operator HGLRC() const { return mOldContext; } + private: + HGLRC mOldContext; + } oldContext = mhRC; if (mhRC) { if (!wglMakeCurrent(NULL, NULL)) { LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL; } - - if (!wglDeleteContext(mhRC)) - { - LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL; - } - - mhRC = NULL; } if (fullscreen) @@ -1467,13 +1515,14 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, co } mhRC = 0; + bool sharedContext = false; if (wglCreateContextAttribsARB) { //attempt to create a specific versioned context S32 attribs[] = { //start at 4.2 WGL_CONTEXT_MAJOR_VERSION_ARB, 4, WGL_CONTEXT_MINOR_VERSION_ARB, 2, - WGL_CONTEXT_PROFILE_MASK_ARB, LLRender::sGLCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + WGL_CONTEXT_PROFILE_MASK_ARB, /*LLRender::sGLCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB :*/ WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, WGL_CONTEXT_FLAGS_ARB, gDebugGL ? WGL_CONTEXT_DEBUG_BIT_ARB : 0, 0 }; @@ -1481,8 +1530,11 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, co bool done = false; while (!done) { - mhRC = wglCreateContextAttribsARB(mhDC, mhRC, attribs); - + sharedContext = oldContext && (mhRC = wglCreateContextAttribsARB(mhDC, oldContext, attribs)) != nullptr; + if (!sharedContext) + { + mhRC = wglCreateContextAttribsARB(mhDC, nullptr, attribs); + } if (!mhRC) { if (attribs[3] > 0) @@ -1513,7 +1565,11 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, co } } - if (!mhRC && !(mhRC = wglCreateContext(mhDC))) + bool abort = !mhRC && !(mhRC = wglCreateContext(mhDC)); + + if (!sharedContext && stopFn) stopFn(); + + if (abort) { close(); OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); @@ -1575,6 +1631,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, co { show(); glClearColor(0.0f, 0.0f, 0.0f, 0.f); + gGL.syncContextState(); glClear(GL_COLOR_BUFFER_BIT); swapBuffers(); } @@ -1583,6 +1640,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, co glGetIntegerv(GL_SAMPLES, &buf); LL_INFOS() << "Acquired FSAA Samples = " << buf << LL_ENDL; + if(restoreFn) restoreFn(!sharedContext); + return TRUE; } @@ -1773,7 +1832,50 @@ void LLWindowWin32::initCursors() } } +void LLWindowWin32::initDPIAwareness() +{ + mUser32Lib = LoadLibrary(L"user32.dll"); + mSHCoreLib = LoadLibrary(L"Shcore.dll"); + + if (mUser32Lib && mSHCoreLib) + { + MonitorFromWindowFn = reinterpret_cast(GetProcAddress(mUser32Lib, "MonitorFromWindow")); + GetDpiForMonitorFn = reinterpret_cast(GetProcAddress(mSHCoreLib, "GetDpiForMonitor")); + + if (MonitorFromWindowFn && GetDpiForMonitorFn) + { + HRESULT(WINAPI* SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); + SetProcessDpiAwareness = reinterpret_cast(GetProcAddress(mSHCoreLib, "SetProcessDpiAwareness")); + if (SetProcessDpiAwareness && SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE) == S_OK) + return; + + BOOL(WINAPI* SetProcessDPIAware)(void); + SetProcessDPIAware = reinterpret_cast(GetProcAddress(mUser32Lib, "SetProcessDPIAware")); + if (SetProcessDPIAware && SetProcessDPIAware()) + return; + } + } + + FreeLibrary(mUser32Lib); + FreeLibrary(mSHCoreLib); + mUser32Lib = nullptr; + mSHCoreLib = nullptr; +} +void LLWindowWin32::getDPIScales(float &xDPIScale, float& yDPIScale) +{ + xDPIScale = yDPIScale = 1.f; + if (mUser32Lib) + { + uint32_t xDPI, yDPI; + auto window = MonitorFromWindowFn(mWindowHandle, MONITOR_DEFAULTTONEAREST); + if (GetDpiForMonitorFn(window, MDT_EFFECTIVE_DPI, &xDPI, &yDPI) == S_OK) + { + xDPIScale = (float)xDPI / (float)USER_DEFAULT_SCREEN_DPI; + yDPIScale = (float)yDPI / (float)USER_DEFAULT_SCREEN_DPI; + } + } +} void LLWindowWin32::updateCursor() { @@ -1873,8 +1975,8 @@ void LLWindowWin32::gatherInput() mMousePositionModified = FALSE; } -static LLFastTimer::DeclareTimer FTM_KEYHANDLER("Handle Keyboard"); -static LLFastTimer::DeclareTimer FTM_MOUSEHANDLER("Handle Mouse"); +static LLTrace::BlockTimerStatHandle FTM_KEYHANDLER("Handle Keyboard"); +static LLTrace::BlockTimerStatHandle FTM_MOUSEHANDLER("Handle Mouse"); LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param) { @@ -2105,6 +2207,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ window_imp->mKeyCharCode = 0; // don't know until wm_char comes in next window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff; window_imp->mKeyVirtualKey = w_param; + window_imp->mRawMsg = u_msg; + window_imp->mRawWParam = w_param; + window_imp->mRawLParam = l_param; window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYDOWN"); { @@ -2127,9 +2232,12 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ { window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff; window_imp->mKeyVirtualKey = w_param; + window_imp->mRawMsg = u_msg; + window_imp->mRawWParam = w_param; + window_imp->mRawLParam = l_param; window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP"); - LLFastTimer t2(FTM_KEYHANDLER); + LL_RECORD_BLOCK_TIME(FTM_KEYHANDLER); if (gDebugWindowProc) { @@ -2214,6 +2322,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_CHAR: window_imp->mKeyCharCode = w_param; + window_imp->mRawMsg = u_msg; + window_imp->mRawWParam = w_param; + window_imp->mRawLParam = l_param; // Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need // to figure out how that works. - Doug @@ -2249,7 +2360,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_LBUTTONDOWN: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN"); - LLFastTimer t2(FTM_MOUSEHANDLER); + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); sHandleLeftMouseUp = true; if (LLWinImm::isAvailable() && window_imp->mPreeditor) @@ -2322,7 +2433,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_LBUTTONUP: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP"); - LLFastTimer t2(FTM_MOUSEHANDLER); + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); if (!sHandleLeftMouseUp) { @@ -2363,7 +2474,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_RBUTTONDOWN: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONDOWN"); - LLFastTimer t2(FTM_MOUSEHANDLER); + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); if (LLWinImm::isAvailable() && window_imp->mPreeditor) { window_imp->interruptLanguageTextInput(); @@ -2397,7 +2508,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_RBUTTONUP: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONUP"); - LLFastTimer t2(FTM_MOUSEHANDLER); + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); // Because we move the cursor position in the app, we need to query // to find out where the cursor at the time the event is handled. // If we don't do this, many clicks could get buffered up, and if the @@ -2427,7 +2538,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // case WM_MBUTTONDBLCLK: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN"); - LLFastTimer t2(FTM_MOUSEHANDLER); + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); if (LLWinImm::isAvailable() && window_imp->mPreeditor) { window_imp->interruptLanguageTextInput(); @@ -2461,7 +2572,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_MBUTTONUP: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP"); - LLFastTimer t2(FTM_MOUSEHANDLER); + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); // Because we move the cursor position in the llviewer app, we need to query // to find out where the cursor at the time the event is handled. // If we don't do this, many clicks could get buffered up, and if the @@ -2528,21 +2639,11 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } return 0; } - /* - // TODO: add this after resolving _WIN32_WINNT issue - case WM_MOUSELEAVE: + case WM_MOUSELEAVE: { - window_imp->mCallbacks->handleMouseLeave(window_imp); - - // TRACKMOUSEEVENT track_mouse_event; - // track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT ); - // track_mouse_event.dwFlags = TME_LEAVE; - // track_mouse_event.hwndTrack = h_wnd; - // track_mouse_event.dwHoverTime = HOVER_DEFAULT; - // TrackMouseEvent( &track_mouse_event ); - return 0; + window_imp->mCallbacks->handleMouseLeave(window_imp); + return 0; } - */ // Handle mouse movement within the window case WM_MOUSEMOVE: { @@ -2647,6 +2748,26 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ }; return 0; + case WM_DPICHANGED: + { + window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DPICHANGED"); + if (gDebugWindowProc) + { + LL_INFOS("Window") << "WM_DPICHANGED " << LOWORD(w_param) << " " << HIWORD(w_param) << LL_ENDL; + } + LPRECT rect = (LPRECT)l_param; + S32 width = ((LPRECT)l_param)->right - ((LPRECT)l_param)->left; + S32 height = ((LPRECT)l_param)->bottom - ((LPRECT)l_param)->top; + LL_INFOS() << "rect: " << width << "x" << height << LL_ENDL; + if(window_imp->mCallbacks->handleDPIScaleChange(window_imp, + (F32)LOWORD(w_param) / (F32)USER_DEFAULT_SCREEN_DPI, + (F32)HIWORD(w_param) / (F32)USER_DEFAULT_SCREEN_DPI, + width, + height)) + SetWindowPos(h_wnd, HWND_TOP, rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top, SWP_NOZORDER | SWP_NOACTIVATE); + } + return 0; + break; } @@ -2910,13 +3031,26 @@ F32 LLWindowWin32::getGamma() BOOL LLWindowWin32::restoreGamma() { - return SetDeviceGammaRamp(mhDC, mPrevGammaRamp); + if (mCustomGammaSet != FALSE) + { + mCustomGammaSet = FALSE; + return SetDeviceGammaRamp(mhDC, mPrevGammaRamp); + } + return TRUE; } BOOL LLWindowWin32::setGamma(const F32 gamma) { mCurrentGamma = gamma; + //Get the previous gamma ramp to restore later. + if (mCustomGammaSet == FALSE) + { + if (GetDeviceGammaRamp(mhDC, mPrevGammaRamp) == FALSE) + return FALSE; + mCustomGammaSet = TRUE; + } + LL_DEBUGS("Window") << "Setting gamma to " << gamma << LL_ENDL; for ( int i = 0; i < 256; ++i ) @@ -2928,9 +3062,9 @@ BOOL LLWindowWin32::setGamma(const F32 gamma) if ( value > 0xffff ) value = 0xffff; - mCurrentGammaRamp [ 0 * 256 + i ] = - mCurrentGammaRamp [ 1 * 256 + i ] = - mCurrentGammaRamp [ 2 * 256 + i ] = ( WORD )value; + mCurrentGammaRamp[0][i] = + mCurrentGammaRamp[1][i] = + mCurrentGammaRamp[2][i] = (WORD) value; }; return SetDeviceGammaRamp ( mhDC, mCurrentGammaRamp ); @@ -3232,34 +3366,9 @@ S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 t return retval; } -void LLWindowWin32::ShellEx(const std::string& command) -{ - LLWString url_wstring = utf8str_to_wstring( "\"" + command + "\"" ); - llutf16string url_utf16 = wstring_to_utf16str( url_wstring ); - - SHELLEXECUTEINFO sei = { sizeof( sei ) }; - sei.fMask = SEE_MASK_FLAG_DDEWAIT; - sei.nShow = SW_SHOWNORMAL; - sei.lpVerb = L"open"; - sei.lpFile = url_utf16.c_str(); - ShellExecuteEx( &sei ); -} - - void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async) { - bool found = false; - S32 i; - for (i = 0; i < gURLProtocolWhitelistCount; i++) - { - if (escaped_url.find(gURLProtocolWhitelist[i]) == 0) - { - found = true; - break; - } - } - - if (!found) + if (!isWhitelistedProtocol(escaped_url)) { LL_WARNS("Window") << "spawn_web_browser() called for url with protocol not on whitelist: " << escaped_url << LL_ENDL; return; @@ -3271,25 +3380,8 @@ void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async) // reliablly on Vista. // this is madness.. no, this is.. - LLWString url_wstring = utf8str_to_wstring( escaped_url ); - llutf16string url_utf16 = wstring_to_utf16str( url_wstring ); - // let the OS decide what to use to open the URL - SHELLEXECUTEINFO sei = { sizeof( sei ) }; - // NOTE: this assumes that SL will stick around long enough to complete the DDE message exchange - // necessary for ShellExecuteEx to complete - if (async) - { - sei.fMask = SEE_MASK_ASYNCOK; - } - else - { - sei.fMask = SEE_MASK_FLAG_DDEWAIT; - } - sei.nShow = SW_SHOWNORMAL; - sei.lpVerb = L"open"; - sei.lpFile = url_utf16.c_str(); - ShellExecuteEx( &sei ); + ShellEx(escaped_url); } void LLWindowWin32::setTitle(const std::string &title) @@ -3310,6 +3402,9 @@ LLSD LLWindowWin32::getNativeKeyData() result["scan_code"] = (S32)mKeyScanCode; result["virtual_key"] = (S32)mKeyVirtualKey; + result["msg"] = ll_sd_from_U32(mRawMsg); + result["w_param"] = ll_sd_from_U32(mRawWParam); + result["l_param"] = ll_sd_from_U32(mRawLParam); return result; } diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 9ef2b206ed..63c31a4d5c 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -27,10 +27,7 @@ #ifndef LL_LLWINDOWWIN32_H #define LL_LLWINDOWWIN32_H -// Limit Windows API to small and manageable set. -#define WIN32_LEAN_AND_MEAN -#include -#include +#include "llwin32headerslean.h" #include "llwindow.h" #include "llwindowcallbacks.h" @@ -43,7 +40,8 @@ typedef void (*LLW32MsgCallback)(const MSG &msg); class LLWindowWin32 : public LLWindow { public: - /*virtual*/ void show(); + /*virtual*/ void postInitialized(); + /*virtual*/ void show(bool focus = true); /*virtual*/ void hide(); /*virtual*/ void close(); /*virtual*/ BOOL getVisible(); @@ -59,7 +57,7 @@ class LLWindowWin32 : public LLWindow /*virtual*/ BOOL setPosition(LLCoordScreen position); /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL); + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = NULL); /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); /*virtual*/ void showCursor(); @@ -111,7 +109,6 @@ class LLWindowWin32 : public LLWindow /*virtual*/ void setLanguageTextInput( const LLCoordGL & pos ); /*virtual*/ void updateLanguageTextInputArea(); /*virtual*/ void interruptLanguageTextInput(); - void ShellEx(const std::string& command); /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); /*virtual*/ void setTitle(const std::string &title); @@ -129,10 +126,12 @@ class LLWindowWin32 : public LLWindow void initCursors(); void initInputDevices(); + void initDPIAwareness(); + void getDPIScales(float& xDPIScale, float& yDPIScale); HCURSOR loadColorCursor(LPCTSTR name); BOOL isValid(); void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size); - LLSD getNativeKeyData(); + virtual LLSD getNativeKeyData(); // Changes display resolution. Returns true if successful BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh); @@ -189,8 +188,9 @@ class LLWindowWin32 : public LLWindow F32 mCurrentGamma; U32 mFSAASamples; S32 mVsyncMode; - WORD mPrevGammaRamp[256*3]; - WORD mCurrentGammaRamp[256*3]; + WORD mPrevGammaRamp[3][256]; + WORD mCurrentGammaRamp[3][256]; + BOOL mCustomGammaSet; LPWSTR mIconResource; BOOL mMousePositionModified; @@ -215,6 +215,14 @@ class LLWindowWin32 : public LLWindow U32 mKeyCharCode; U32 mKeyScanCode; U32 mKeyVirtualKey; + U32 mRawMsg; + U32 mRawWParam; + U32 mRawLParam; + + HMODULE mUser32Lib; + HMODULE mSHCoreLib; + HMONITOR(WINAPI *MonitorFromWindowFn)(HWND, DWORD); + HRESULT(WINAPI *GetDpiForMonitorFn)(HMONITOR, INT, UINT *, UINT *); friend class LLWindowManager; }; diff --git a/indra/llxml/CMakeLists.txt b/indra/llxml/CMakeLists.txt index be0a510b42..576fb0ffec 100644 --- a/indra/llxml/CMakeLists.txt +++ b/indra/llxml/CMakeLists.txt @@ -37,8 +37,10 @@ set_source_files_properties(${llxml_HEADER_FILES} list(APPEND llxml_SOURCE_FILES ${llxml_HEADER_FILES}) add_library (llxml ${llxml_SOURCE_FILES}) -add_dependencies(llxml prepare) + target_link_libraries( llxml + PUBLIC + llcommon ${EXPAT_LIBRARIES} ) diff --git a/indra/llxml/aixml.cpp b/indra/llxml/aixml.cpp index d7592c4315..02b972e806 100644 --- a/indra/llxml/aixml.cpp +++ b/indra/llxml/aixml.cpp @@ -32,7 +32,6 @@ #include "aixml.h" #include "llmd5.h" #include -#include "aifile.h" //============================================================================= // Overview @@ -263,7 +262,7 @@ void AIXMLElement::close_child(void) mIndentation -= 2; } -AIXMLElement::~AIXMLElement() +AIXMLElement::~AIXMLElement() noexcept(false) { if (mHasChildren) { @@ -311,11 +310,10 @@ void AIXMLElement::child(LLDate const& element) //----------------------------------------------------------------------------- // AIXMLStream -AIXMLStream::AIXMLStream(LLFILE* fp, bool standalone) : mOfs(fp) +AIXMLStream::AIXMLStream(const std::string& filename, bool standalone) : mOfs(filename) { - char const* sp = standalone ? " standalone=\"yes\"" : ""; - int rc = fprintf(fp, "\n", sp); - if (rc < 0 || ferror(fp)) + mOfs << "\n"; + if (!mOfs) { // I don't think that errno is set to anything else but EBADF here, // so there is not really any informative message to add here. @@ -342,7 +340,6 @@ AIXMLParser::AIXMLParser(std::string const& filename, char const* file_desc, std AIArgs args; if (!mXmlTree.parseFile(filename, TRUE)) { - AIFile dummy(filename, "rb"); // Check if the file can be opened at all (throws with a more descriptive error if not). error = "AIXMLParser_Cannot_parse_FILEDESC_FILENAME"; } else diff --git a/indra/llxml/aixml.h b/indra/llxml/aixml.h index 9bfb783f42..358eed7561 100644 --- a/indra/llxml/aixml.h +++ b/indra/llxml/aixml.h @@ -64,7 +64,7 @@ class AIXMLElement public: AIXMLElement(std::ostream& os, char const* name, int indentation); - ~AIXMLElement(); + ~AIXMLElement() noexcept(false); template void attribute(char const* name, T const& attribute); @@ -151,7 +151,7 @@ void AIXMLElement::child(FWD_ITERATOR i1, FWD_ITERATOR const& i2) class AIXMLStream { protected: llofstream mOfs; - AIXMLStream(LLFILE* fp, bool standalone); + AIXMLStream(const std::string& filename, bool standalone); ~AIXMLStream(); }; @@ -159,7 +159,7 @@ class AIXMLStream { class AIXMLRootElement : public AIXMLStream, public AIXMLElement { public: - AIXMLRootElement(LLFILE* fp, char const* name, bool standalone = true) : AIXMLStream(fp, standalone), AIXMLElement(mOfs, name, 0) { } + AIXMLRootElement(const std::string& filename, char const* name, bool standalone = true) : AIXMLStream(filename, standalone), AIXMLElement(mOfs, name, 0) { } }; class AIXMLElementParser diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index f3c207aa6a..1b8b5a42e3 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -756,7 +756,7 @@ bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXML return false; } fseek(fp, 0, SEEK_END); - U32 length = ftell(fp); + size_t length = ftell(fp); fseek(fp, 0, SEEK_SET); U8* buffer = new U8[length+1]; diff --git a/indra/llxml/llxmlparser.cpp b/indra/llxml/llxmlparser.cpp index 67993065ed..cc5399efe1 100644 --- a/indra/llxml/llxmlparser.cpp +++ b/indra/llxml/llxmlparser.cpp @@ -89,7 +89,7 @@ BOOL LLXmlParser::parseFile(const std::string &path) S32 bytes_read = 0; fseek(file, 0L, SEEK_END); - S32 buffer_size = ftell(file); + size_t buffer_size = ftell(file); fseek(file, 0L, SEEK_SET); void* buffer = XML_GetBuffer(mParser, buffer_size); diff --git a/indra/lscript/lscript_byteconvert.h b/indra/lscript/lscript_byteconvert.h index aa8c7ffb45..4cc118fab2 100644 --- a/indra/lscript/lscript_byteconvert.h +++ b/indra/lscript/lscript_byteconvert.h @@ -136,7 +136,7 @@ inline F32 bytestream2float(const U8 *stream, S32 &offset) { S32 value = bytestream2integer(stream, offset); F32 fpvalue = *(F32 *)&value; - if (!llfinite(fpvalue)) + if (!std::isfinite(fpvalue)) { fpvalue = 0; set_fault(stream, LSRF_MATH); @@ -155,7 +155,7 @@ inline void bytestream_int2float(U8 *stream, S32 &offset) S32 value = bytestream2integer(stream, offset); offset -= 4; F32 fpvalue = (F32)value; - if (!llfinite(fpvalue)) + if (!std::isfinite(fpvalue)) { fpvalue = 0; set_fault(stream, LSRF_MATH); @@ -230,21 +230,21 @@ inline void bytestream2vector(LLVector3 &vector, const U8 *stream, S32 &offset) { S32 value = bytestream2integer(stream, offset); vector.mV[VZ] = *(F32 *)&value; - if (!llfinite(vector.mV[VZ])) + if (!std::isfinite(vector.mV[VZ])) { vector.mV[VZ] = 0; set_fault(stream, LSRF_MATH); } value = bytestream2integer(stream, offset); vector.mV[VY] = *(F32 *)&value; - if (!llfinite(vector.mV[VY])) + if (!std::isfinite(vector.mV[VY])) { vector.mV[VY] = 0; set_fault(stream, LSRF_MATH); } value = bytestream2integer(stream, offset); vector.mV[VX] = *(F32 *)&value; - if (!llfinite(vector.mV[VX])) + if (!std::isfinite(vector.mV[VX])) { vector.mV[VX] = 0; set_fault(stream, LSRF_MATH); @@ -265,28 +265,28 @@ inline void bytestream2quaternion(LLQuaternion &quat, const U8 *stream, S32 &off { S32 value = bytestream2integer(stream, offset); quat.mQ[VS] = *(F32 *)&value; - if (!llfinite(quat.mQ[VS])) + if (!std::isfinite(quat.mQ[VS])) { quat.mQ[VS] = 0; set_fault(stream, LSRF_MATH); } value = bytestream2integer(stream, offset); quat.mQ[VZ] = *(F32 *)&value; - if (!llfinite(quat.mQ[VZ])) + if (!std::isfinite(quat.mQ[VZ])) { quat.mQ[VZ] = 0; set_fault(stream, LSRF_MATH); } value = bytestream2integer(stream, offset); quat.mQ[VY] = *(F32 *)&value; - if (!llfinite(quat.mQ[VY])) + if (!std::isfinite(quat.mQ[VY])) { quat.mQ[VY] = 0; set_fault(stream, LSRF_MATH); } value = bytestream2integer(stream, offset); quat.mQ[VX] = *(F32 *)&value; - if (!llfinite(quat.mQ[VX])) + if (!std::isfinite(quat.mQ[VX])) { quat.mQ[VX] = 0; set_fault(stream, LSRF_MATH); @@ -315,7 +315,7 @@ inline F32 get_register_fp(U8 *stream, LSCRIPTRegisters reg) { S32 offset = gLSCRIPTRegisterAddresses[reg]; F32 value = bytestream2float(stream, offset); - if (!llfinite(value)) + if (!std::isfinite(value)) { value = 0; set_fault(stream, LSRF_MATH); @@ -390,7 +390,7 @@ inline F32 add_register_fp(U8 *stream, LSCRIPTRegisters reg, F32 value) S32 offset = gLSCRIPTRegisterAddresses[reg]; F32 newvalue = bytestream2float(stream, offset); newvalue += value; - if (!llfinite(newvalue)) + if (!std::isfinite(newvalue)) { newvalue = 0; set_fault(stream, LSRF_MATH); @@ -587,7 +587,7 @@ inline F32 lscript_pop_float(U8 *stream) { S32 sp = get_register(stream, LREG_SP); F32 value = bytestream2float(stream, sp); - if (!llfinite(value)) + if (!std::isfinite(value)) { value = 0; set_fault(stream, LSRF_MATH); @@ -727,7 +727,7 @@ inline void lscript_local_get(U8 *stream, S32 address, F32 &value) { if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_FLOATINGPOINT])) value = bytestream2float(stream, address); - if (!llfinite(value)) + if (!std::isfinite(value)) { value = 0; set_fault(stream, LSRF_MATH); @@ -757,7 +757,7 @@ inline void lscript_global_get(U8 *stream, S32 address, F32 &value) { if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_FLOATINGPOINT])) value = bytestream2float(stream, address); - if (!llfinite(value)) + if (!std::isfinite(value)) { value = 0; set_fault(stream, LSRF_MATH); @@ -1058,7 +1058,7 @@ inline F32 safe_instruction_bytestream2float(U8 *stream, S32 &offset) if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_INTEGER])) { F32 value = bytestream2float(stream, offset); - if (!llfinite(value)) + if (!std::isfinite(value)) { value = 0; set_fault(stream, LSRF_MATH); diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h index 49e78e7176..679714e590 100644 --- a/indra/lscript/lscript_byteformat.h +++ b/indra/lscript/lscript_byteformat.h @@ -355,6 +355,10 @@ typedef enum e_lscript_state_event_type LSTT_REMOTE_DATA, LSTT_HTTP_RESPONSE, LSTT_HTTP_REQUEST, + LSTT_EXPERMISSIONS, + LSTT_TRANSACTION_RESULT, + LSTT_PATH_UPDATE, + LSTT_EXPERMISSIONS_DENIED, LSTT_EOF, LSTT_STATE_BEGIN = LSTT_STATE_ENTRY, @@ -397,7 +401,11 @@ const U64 LSCRIPTStateBitField[LSTT_EOF] = 0x0000000040000000, // LSTT_OBJECT_REZ 0x0000000080000000, // LSTT_REMOTE_DATA 0x0000000100000000LL, // LSTT_HTTP_RESPOSE - 0x0000000200000000LL // LSTT_HTTP_REQUEST + 0x0000000200000000LL, // LSTT_HTTP_REQUEST + 0x0000000400000000LL, // LSTT_EXPERMISSIONS + 0x0000000800000000LL, // LSTT_TRANSACTION_RESULT + 0x0000001000000000LL, // LSTT_PATH_UPDATE + 0x0000002000000000LL, //LSTT_EXPERMISSIONS_DENIED }; inline S32 get_event_handler_jump_position(U64 bit_field, LSCRIPTStateEventType type) @@ -511,6 +519,7 @@ typedef enum e_lscript_runtime_faults LSRF_TOO_MANY_LISTENS, LSRF_NESTING_LISTS, LSRF_CLI, + LSRF_INVALID_STATE, LSRF_EOF } LSCRIPTRunTimeFaults; @@ -551,10 +560,10 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] = (0x1 << 10),// SCRIPT_PERMISSION_TRACK_CAMERA (0x1 << 11),// SCRIPT_PERMISSION_CONTROL_CAMERA (0x1 << 12),// SCRIPT_PERMISSION_TELEPORT - (0x1 << 13),// SCRIPT_PERMISSION_EXPERIENCE, - (0x1 << 14),// SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT, - (0x1 << 15),// SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS, - (0x1 << 16),// SCRIPT_PERMISSION_RETURN_OBJECTS, + (0x1 << 13),// SCRIPT_PERMISSION_EXPERIENCE + (0x1 << 14),// SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT + (0x1 << 15),// SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS + (0x1 << 16),// SCRIPT_PERMISSION_RETURN_OBJECTS }; // http_request string constants diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l index f7e592afb4..3fb834d17e 100644 --- a/indra/lscript/lscript_compile/indra.l +++ b/indra/lscript/lscript_compile/indra.l @@ -685,6 +685,23 @@ void parse_string(); "STATUS_INTERNAL_ERROR" { count(); yylval.ival = LSL_STATUS_INTERNAL_ERROR; return(INTEGER_CONSTANT); } "STATUS_WHITELIST_FAILED" { count(); yylval.ival = LSL_STATUS_WHITELIST_FAILED; return(INTEGER_CONSTANT); } +"XP_ERROR_NONE" { const char* sval= "no error"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_THROTTLED" { const char* sval= "exceeded throttle"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_EXPERIENCES_DISABLED" { const char* sval= "experiences are disabled"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_INVALID_PARAMETERS" { const char* sval= "invalid parameters"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_NOT_PERMITTED" { const char* sval= "operation not permitted"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_NO_EXPERIENCE" { const char* sval= "script not associated with an experience";yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_NOT_FOUND" { const char* sval= "not found"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_INVALID_EXPERIENCE" { const char* sval= "invalid experience"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_EXPERIENCE_DISABLED" { const char* sval= "experience is disabled"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_EXPERIENCE_SUSPENDED" { const char* sval= "experience is suspended"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_UNKNOWN_ERROR" { const char* sval= "unknown error"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_QUOTA_EXCEEDED" { const char* sval= "experience data quota exceeded"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_STORE_DISABLED" { const char* sval= "key-value store is disabled"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_STORAGE_EXCEPTION" { const char* sval= "key-value store communication failed"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_KEY_NOT_FOUND" { const char* sval= "key doesn't exist"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } +"XP_ERROR_RETRY_UPDATE" { const char* sval= "retry update"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); } + "PROFILE_SCRIPT_NONE" { count(); yylval.ival = LSL_PROFILE_SCRIPT_NONE; return(INTEGER_CONSTANT); } "PROFILE_SCRIPT_MEMORY" { count(); yylval.ival = LSL_PROFILE_SCRIPT_MEMORY; return(INTEGER_CONSTANT); } diff --git a/indra/lscript/lscript_compile/indra.y b/indra/lscript/lscript_compile/indra.y index febf5f6751..3e4b6c6cea 100644 --- a/indra/lscript/lscript_compile/indra.y +++ b/indra/lscript/lscript_compile/indra.y @@ -179,6 +179,8 @@ %type money %type email %type run_time_permissions +%type experience_permissions +%type experience_permissions_denied %type inventory %type attach %type dataserver @@ -787,6 +789,16 @@ event $$ = new LLScriptEventHandler(gLine, gColumn, $1, $2); gAllocationManager->addAllocation($$); } + | experience_permissions compound_statement + { + $$ = new LLScriptEventHandler(gLine, gColumn, $1, $2); + gAllocationManager->addAllocation($$); + } + | experience_permissions_denied compound_statement + { + $$ = new LLScriptEventHandler(gLine, gColumn, $1, $2); + gAllocationManager->addAllocation($$); + } | inventory compound_statement { $$ = new LLScriptEventHandler(gLine, gColumn, $1, $2); @@ -1039,6 +1051,28 @@ run_time_permissions } ; +experience_permissions + : EXPERIENCE_PERMISSIONS '(' LLKEY IDENTIFIER ')' + { + LLScriptIdentifier *id1 = new LLScriptIdentifier(gLine, gColumn, $4); + gAllocationManager->addAllocation(id1); + $$ = new LLScriptEXPEvent(gLine, gColumn, id1); + gAllocationManager->addAllocation($$); + } + ; + +experience_permissions_denied + : EXPERIENCE_PERMISSIONS_DENIED '(' LLKEY IDENTIFIER ',' INTEGER IDENTIFIER ')' + { + LLScriptIdentifier *id1 = new LLScriptIdentifier(gLine, gColumn, $4); + gAllocationManager->addAllocation(id1); + LLScriptIdentifier *id2 = new LLScriptIdentifier(gLine, gColumn, $7); + gAllocationManager->addAllocation(id2); + $$ = new LLScriptEXPDeniedEvent(gLine, gColumn, id1, id2); + gAllocationManager->addAllocation($$); + } + ; + inventory : INVENTORY '(' INTEGER IDENTIFIER ')' { diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp index b737bff75f..e5e7bb3d05 100644 --- a/indra/lscript/lscript_compile/lscript_tree.cpp +++ b/indra/lscript/lscript_compile/lscript_tree.cpp @@ -3712,6 +3712,155 @@ S32 LLScriptNoSensorEvent::getSize() return 0; } +void LLScriptEXPEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata) +{ + if (gErrorToText.getErrors()) + { + return; + } + switch(pass) + { + case LSCP_PRETTY_PRINT: + case LSCP_EMIT_ASSEMBLY: + fdotabs(fp, tabs, tabsize); + fprintf(fp, "experience_permissions( key "); + mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + fprintf(fp, " )\n"); + break; + case LSCP_SCOPE_PASS1: + checkForDuplicateHandler(fp, this, scope, "experience_permissions"); + if (scope->checkEntry(mName->mName)) + { + gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); + } + else + { + mName->mScopeEntry = scope->addEntry(mName->mName, LIT_VARIABLE, LST_KEY); + } + break; + case LSCP_RESOURCE: + { + // we're just tryng to determine how much space the variable needs + if (mName->mScopeEntry) + { + mName->mScopeEntry->mOffset = (S32)count; + mName->mScopeEntry->mSize = 4; + count += mName->mScopeEntry->mSize; + } + } + break; + + case LSCP_EMIT_BYTE_CODE: + { +#ifdef LSL_INCLUDE_DEBUG_INFO + char name[] = "experience_permissions"; + chunk->addBytes(name, strlen(name) + 1); + chunk->addBytes(mName->mName, strlen(mName->mName) + 1); +#endif + } + break; + case LSCP_EMIT_CIL_ASSEMBLY: + fdotabs(fp, tabs, tabsize); + fprintf(fp, "experience_permissions( valuetype [ScriptTypes]LindenLab.SecondLife.Key "); + mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + fprintf(fp, " )"); + break; + default: + mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + break; + } +} + +S32 LLScriptEXPEvent::getSize() +{ + // key = 4 + return 4; +} + + +void LLScriptEXPDeniedEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata) +{ + if (gErrorToText.getErrors()) + { + return; + } + switch(pass) + { + case LSCP_PRETTY_PRINT: + case LSCP_EMIT_ASSEMBLY: + fdotabs(fp, tabs, tabsize); + fprintf(fp, "experience_permissions_denied( key "); + mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + fprintf(fp, ", integer "); + mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + fprintf(fp, " )\n"); + break; + case LSCP_SCOPE_PASS1: + checkForDuplicateHandler(fp, this, scope, "experience_permissions_denied"); + if (scope->checkEntry(mName->mName)) + { + gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); + } + else + { + mName->mScopeEntry = scope->addEntry(mName->mName, LIT_VARIABLE, LST_KEY); + } + if (scope->checkEntry(mReason->mName)) + { + gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); + } + else + { + mReason->mScopeEntry = scope->addEntry(mReason->mName, LIT_VARIABLE, LST_INTEGER); + } + break; + case LSCP_RESOURCE: + { + // we're just trying to determine how much space the variable needs + if (mName->mScopeEntry) + { + mName->mScopeEntry->mOffset = (S32)count; + mName->mScopeEntry->mSize = 4; + count += mName->mScopeEntry->mSize; + + mReason->mScopeEntry->mOffset = (S32)count; + mReason->mScopeEntry->mSize = 4; + count += mReason->mScopeEntry->mSize; + } + } + break; + + case LSCP_EMIT_BYTE_CODE: + { +#ifdef LSL_INCLUDE_DEBUG_INFO + char name[] = "experience_permissions_denied"; + chunk->addBytes(name, strlen(name) + 1); + chunk->addBytes(mName->mName, strlen(mName->mName) + 1); + chunk->addBytes(mReason->mName, strlen(mReason->mName) + 1); +#endif + } + break; + case LSCP_EMIT_CIL_ASSEMBLY: + fdotabs(fp, tabs, tabsize); + fprintf(fp, "experience_permissions_denied( valuetype [ScriptTypes]LindenLab.SecondLife.Key "); + mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + fprintf(fp, ", int32 "); + mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + fprintf(fp, " )"); + break; + default: + mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + break; + } +} + +S32 LLScriptEXPDeniedEvent::getSize() +{ + // key = 4 + integer + return LSCRIPTDataSize[LST_KEY]+LSCRIPTDataSize[LST_INTEGER]; +} + void LLScriptAtTarget::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata) { if (gErrorToText.getErrors()) @@ -8577,6 +8726,7 @@ void LLScriptReturn::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa } } prunearg = TRUE; + break; case LSCP_TYPE: // if there is a return expression, it must be promotable to the return type of the function if (mExpression) @@ -9775,7 +9925,13 @@ void LLScriptEventHandler::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom mScopeEntry->mFunctionArgs.addType(LST_STRING); mScopeEntry->mFunctionArgs.addType(LST_STRING); break; - + case LSTT_EXPERMISSIONS: + mScopeEntry->mFunctionArgs.addType(LST_KEY); + break; + case LSTT_EXPERMISSIONS_DENIED: + mScopeEntry->mFunctionArgs.addType(LST_KEY); + mScopeEntry->mFunctionArgs.addType(LST_INTEGER); + break; default: break; } diff --git a/indra/lscript/lscript_compile/lscript_tree.h b/indra/lscript/lscript_compile/lscript_tree.h index 8131003c3f..c7be5396a1 100644 --- a/indra/lscript/lscript_compile/lscript_tree.h +++ b/indra/lscript/lscript_compile/lscript_tree.h @@ -633,6 +633,39 @@ class LLScriptRTPEvent : public LLScriptEvent LLScriptIdentifier *mRTPermissions; }; +class LLScriptEXPEvent : public LLScriptEvent +{ +public: + LLScriptEXPEvent(S32 line, S32 col, LLScriptIdentifier *name) + : LLScriptEvent(line, col, LSTT_EXPERMISSIONS), mName(name) + { + } + + ~LLScriptEXPEvent() {} + + void recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata); + S32 getSize(); + + LLScriptIdentifier *mName; +}; + +class LLScriptEXPDeniedEvent : public LLScriptEvent +{ +public: + LLScriptEXPDeniedEvent(S32 line, S32 col, LLScriptIdentifier *name, LLScriptIdentifier *reason) + : LLScriptEvent(line, col, LSTT_EXPERMISSIONS_DENIED), mName(name), mReason(reason) + { + } + + ~LLScriptEXPDeniedEvent() {} + + void recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata); + S32 getSize(); + + LLScriptIdentifier *mName; + LLScriptIdentifier *mReason; +}; + class LLScriptChatEvent : public LLScriptEvent { public: diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp index 5da6890f4e..2a9292dfff 100644 --- a/indra/lscript/lscript_library/lscript_library.cpp +++ b/indra/lscript/lscript_library/lscript_library.cpp @@ -199,6 +199,8 @@ void LLScriptLibrary::init() addFunction(10.f, 0.f, dummy_func, "llStringLength", "i", "s"); addFunction(10.f, 0.f, dummy_func, "llStartAnimation", NULL, "s"); addFunction(10.f, 0.f, dummy_func, "llStopAnimation", NULL, "s"); + addFunction(10.f, 0.f, dummy_func, "llStartObjectAnimation", NULL, "s"); + addFunction(10.f, 0.f, dummy_func, "llStopObjectAnimation", NULL, "s"); addFunction(10.f, 0.f, dummy_func, "llPointAt", NULL, "v"); addFunction(10.f, 0.f, dummy_func, "llStopPointAt", NULL, NULL); addFunction(10.f, 0.f, dummy_func, "llTargetOmega", NULL, "vff"); diff --git a/indra/newview/Ascent.icns b/indra/newview/Ascent.icns deleted file mode 100644 index b2d2aa3b83..0000000000 Binary files a/indra/newview/Ascent.icns and /dev/null differ diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0d697432dc..60d8e0ad99 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -3,21 +3,23 @@ project(viewer) include(00-Common) +# DON'T move Linking.cmake to its place in the alphabetized list below: it +# sets variables on which the 3p .cmake files depend. +include(Linking) + include(Boost) +include(BuildPackagesInfo) +include(BuildVersion) +include(BuildBranding) +include(CMakeCopyIfDifferent) +include(CrashPad) include(DBusGlib) -include(DirectX) -include(ELFIO) -if(FMODSTUDIO) - include(FMODSTUDIO) -endif(FMODSTUDIO) -if(FMODEX) - include(FMODEX) -endif(FMODEX) -include(OPENAL) -include(FindOpenGL) +include(FMODSTUDIO) +include(GeneratePrecompiledHeader) +include(GLOD) include(Hunspell) -include(JsonCpp) include(LLAddBuildTest) +include(LLAppearance) include(LLAudio) include(LLCharacter) include(LLCommon) @@ -34,38 +36,41 @@ include(LLUI) include(LLVFS) include(LLWindow) include(LLXML) -#include(LScript) -include(Linking) include(NDOF) include(NVAPI) +include(OPENAL) +include(OpenGL) +include(OpenSSL) include(StateMachine) include(TemplateCheck) include(UI) include(ViewerMiscLibs) -include(GLOD) -include(LLAppearance) +include(WinManifest) +include(ZLIB) +include(URIPARSER) -if (WINDOWS) - set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP) - include(InstallRequiredSystemLibraries) -endif (WINDOWS) + +if(USE_FMODSTUDIO) + include_directories(${FMODSTUDIO_INCLUDE_DIR}) +endif(USE_FMODSTUDIO) + +if(USE_CRASHPAD) + include_directories(${CRASHPAD_INCLUDE_DIRS}) +endif(USE_CRASHPAD) include_directories( - ${CMAKE_SOURCE_DIR}/newview ${STATEMACHINE_INCLUDE_DIRS} ${DBUSGLIB_INCLUDE_DIRS} - ${HUNSPELL_INCLUDE_DIR} - ${ELFIO_INCLUDE_DIR} - ${JSONCPP_INCLUDE_DIR} - ${GLOD_INCLUDE_DIRS} + ${ZLIB_INCLUDE_DIRS} + ${GLOD_INCLUDE_DIR} ${LLAUDIO_INCLUDE_DIRS} ${LLCHARACTER_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS} + ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS} ${LLINVENTORY_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} - ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} ${LLPLUGIN_INCLUDE_DIRS} ${LLPRIMITIVE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} @@ -73,9 +78,10 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} + ${HUNSPELL_INCLUDE_DIR} + ${OPENAL_LIB_INCLUDE_DIRS} ${LLAPPEARANCE_INCLUDE_DIRS} -# ${LSCRIPT_INCLUDE_DIRS} -# ${LSCRIPT_INCLUDE_DIRS}/lscript_compile + ${CMAKE_CURRENT_SOURCE_DIR} ) set(viewer_SOURCE_FILES @@ -84,6 +90,7 @@ set(viewer_SOURCE_FILES aixmllindengenepool.cpp alfloaterregiontracker.cpp aoremotectrl.cpp + aosystem.cpp ascentfloatercontactgroups.cpp ascentkeyword.cpp ascentprefschat.cpp @@ -94,7 +101,6 @@ set(viewer_SOURCE_FILES daeexport.cpp floaterao.cpp floaterlocalassetbrowse.cpp - floatervoicelicense.cpp generichandlers.cpp groupchatlistener.cpp hbfloatergrouptitles.cpp @@ -112,6 +118,7 @@ set(viewer_SOURCE_FILES llaisapi.cpp llagent.cpp llagentaccess.cpp + llagentbenefits.cpp llagentcamera.cpp llagentdata.cpp llagentlanguage.cpp @@ -129,6 +136,7 @@ set(viewer_SOURCE_FILES llautoreplace.cpp llavataractions.cpp llavatarpropertiesprocessor.cpp + llavatarrenderinfoaccountant.cpp llbox.cpp llcallbacklist.cpp llcallingcard.cpp @@ -145,7 +153,7 @@ set(viewer_SOURCE_FILES llcompilequeue.cpp llconfirmationmanager.cpp llconsole.cpp - llcrashlogger.cpp + llcontrolavatar.cpp llcurrencyuimanager.cpp llcylinder.cpp lldaycyclemanager.cpp @@ -173,9 +181,11 @@ set(viewer_SOURCE_FILES lleventinfo.cpp lleventnotifier.cpp lleventpoll.cpp + llexperiencelog.cpp llexternaleditor.cpp llface.cpp llfasttimerview.cpp + llfavoritesbar.cpp llfeaturemanager.cpp llfirstuse.cpp llflexibleobject.cpp @@ -188,6 +198,7 @@ set(viewer_SOURCE_FILES llfloateravatarlist.cpp llfloateravatarpicker.cpp llfloateravatartextures.cpp + llfloaterbanduration.cpp llfloaterbeacons.cpp llfloaterblacklist.cpp llfloaterbuildoptions.cpp @@ -211,6 +222,9 @@ set(viewer_SOURCE_FILES llfloatereditui.cpp llfloaterenvsettings.cpp llfloaterevent.cpp + llfloaterexperiencepicker.cpp + llfloaterexperienceprofile.cpp + llfloaterexperiences.cpp llfloaterexploreanimations.cpp llfloaterexploresounds.cpp llfloaterfeed.cpp @@ -229,11 +243,11 @@ set(viewer_SOURCE_FILES llfloaterimagepreview.cpp llfloaterinspect.cpp llfloaterjoystick.cpp - llfloaterlagmeter.cpp llfloaterland.cpp llfloaterlandholdings.cpp llfloaterlandmark.cpp llfloatermap.cpp + llfloatermarketplacelistings.cpp llfloatermediafilter.cpp llfloatermediasettings.cpp llfloatermemleak.cpp @@ -246,7 +260,6 @@ set(viewer_SOURCE_FILES llfloaterobjectiminfo.cpp llfloaterobjectweights.cpp llfloateropenobject.cpp - llfloateroutbox.cpp llfloaterparcel.cpp llfloaterpathfindingcharacters.cpp llfloaterpathfindinglinksets.cpp @@ -311,6 +324,7 @@ set(viewer_SOURCE_FILES llhudtext.cpp llhudview.cpp llimpanel.cpp + llimprocessing.cpp llimview.cpp llinventoryactions.cpp llinventorybridge.cpp @@ -323,6 +337,7 @@ set(viewer_SOURCE_FILES llinventoryobserver.cpp llinventorypanel.cpp lljoystickbutton.cpp + lllandmarkactions.cpp lllandmarklist.cpp lllogchat.cpp llloginhandler.cpp @@ -350,6 +365,7 @@ set(viewer_SOURCE_FILES llnamebox.cpp llnameeditor.cpp llnamelistctrl.cpp + llnameui.cpp llnetmap.cpp llnotify.cpp lloutfitobserver.cpp @@ -371,11 +387,16 @@ set(viewer_SOURCE_FILES llpaneldisplay.cpp llpaneleditwearable.cpp llpanelevent.cpp + llpanelexperiencelisteditor.cpp + llpanelexperiencelog.cpp + llpanelexperiencepicker.cpp + llpanelexperiences.cpp llpanelface.cpp llpanelgeneral.cpp llpanelgroup.cpp llpanelgroupbulk.cpp llpanelgroupbulkban.cpp + llpanelgroupexperiences.cpp llpanelgroupgeneral.cpp llpanelgroupinvite.cpp llpanelgrouplandmoney.cpp @@ -390,7 +411,6 @@ set(viewer_SOURCE_FILES llpanellandoptions.cpp llpanellogin.cpp llpanelmaininventory.cpp - llpanelmarketplaceoutboxinventory.cpp llpanelmediasettingsgeneral.cpp llpanelmediasettingspermissions.cpp llpanelmediasettingssecurity.cpp @@ -444,8 +464,10 @@ set(viewer_SOURCE_FILES llsavedsettingsglue.cpp llscrollingpanelparam.cpp llscrollingpanelparambase.cpp + llsculptidsize.cpp llselectmgr.cpp llshareavatarhandler.cpp + llskinningutil.cpp llsky.cpp llslurl.cpp llspatialpartition.cpp @@ -485,6 +507,7 @@ set(viewer_SOURCE_FILES lltoolselectrect.cpp lltoolview.cpp lltracker.cpp + lluiavatar.cpp lluploaddialog.cpp lluploadfloaterobservers.cpp llurl.cpp @@ -493,6 +516,7 @@ set(viewer_SOURCE_FILES llurlwhitelist.cpp lluserauth.cpp llvectorperfoptions.cpp + llversioninfo.cpp llvelocitybar.cpp llviewchildren.cpp llviewerassetstats.cpp @@ -597,16 +621,12 @@ set(viewer_SOURCE_FILES rlvui.cpp scriptcounter.cpp sgmemstat.cpp - sgversion.cpp shcommandhandler.cpp + shupdatechecker.cpp shfloatermediaticker.cpp wlfPanel_AdvSettings.cpp ) -# This gets renamed in the packaging step -set(VIEWER_BINARY_NAME "secondlife-bin" CACHE STRING - "The name of the viewer executable to create.") - set(viewer_HEADER_FILES CMakeLists.txt ViewerInstall.cmake @@ -616,6 +636,8 @@ set(viewer_HEADER_FILES aixmllindengenepool.h alfloaterregiontracker.h aoremotectrl.h + aostate.h + aosystem.h ascentfloatercontactgroups.h ascentkeyword.h ascentprefschat.h @@ -626,7 +648,6 @@ set(viewer_HEADER_FILES daeexport.h floaterao.h floaterlocalassetbrowse.h - floatervoicelicense.h generichandlers.h groupchatlistener.h hbfloatergrouptitles.h @@ -644,6 +665,7 @@ set(viewer_HEADER_FILES llaisapi.h llagent.h llagentaccess.h + llagentbenefits.h llagentcamera.h llagentdata.h llagentlanguage.h @@ -662,8 +684,8 @@ set(viewer_HEADER_FILES llautoreplace.h llavataractions.h llavatarpropertiesprocessor.h + llavatarrenderinfoaccountant.h llbox.h - llcallbacklist.h llcallingcard.h llcapabilitylistener.h llcaphttpsender.h @@ -678,7 +700,7 @@ set(viewer_HEADER_FILES llcompilequeue.h llconfirmationmanager.h llconsole.h - llcrashlogger.h + llcontrolavatar.h llcurrencyuimanager.h llcylinder.h lldaycyclemanager.h @@ -706,9 +728,11 @@ set(viewer_HEADER_FILES lleventinfo.h lleventnotifier.h lleventpoll.h + llexperiencelog.h llexternaleditor.h llface.h llfasttimerview.h + llfavoritesbar.h llfeaturemanager.h llfirstuse.h llflexibleobject.h @@ -721,6 +745,7 @@ set(viewer_HEADER_FILES llfloateravatarlist.h llfloateravatarpicker.h llfloateravatartextures.h + llfloaterbanduration.h llfloaterbeacons.h llfloaterblacklist.h llfloaterbuildoptions.h @@ -744,6 +769,9 @@ set(viewer_HEADER_FILES llfloatereditui.h llfloaterenvsettings.h llfloaterevent.h + llfloaterexperiencepicker.h + llfloaterexperienceprofile.h + llfloaterexperiences.h llfloaterexploreanimations.h llfloaterexploresounds.h llfloaterfeed.h @@ -762,11 +790,11 @@ set(viewer_HEADER_FILES llfloaterimagepreview.h llfloaterinspect.h llfloaterjoystick.h - llfloaterlagmeter.h llfloaterland.h llfloaterlandholdings.h llfloaterlandmark.h llfloatermap.h + llfloatermarketplacelistings.h llfloatermediafilter.h llfloatermediasettings.h llfloatermemleak.h @@ -779,7 +807,6 @@ set(viewer_HEADER_FILES llfloaterobjectiminfo.h llfloaterobjectweights.h llfloateropenobject.h - llfloateroutbox.h llfloaterparcel.h llfloaterpathfindingcharacters.h llfloaterpathfindinglinksets.h @@ -844,6 +871,7 @@ set(viewer_HEADER_FILES llhudtext.h llhudview.h llimpanel.h + llimprocessing.h llimview.h llinventorybridge.h llinventoryclipboard.h @@ -855,6 +883,7 @@ set(viewer_HEADER_FILES llinventoryobserver.h llinventorypanel.h lljoystickbutton.h + lllandmarkactions.h lllandmarklist.h lllightconstants.h lllogchat.h @@ -883,6 +912,7 @@ set(viewer_HEADER_FILES llnamebox.h llnameeditor.h llnamelistctrl.h + llnameui.h llnetmap.h llnotify.h lloutfitobserver.h @@ -904,12 +934,17 @@ set(viewer_HEADER_FILES llpaneldisplay.h llpaneleditwearable.h llpanelevent.h + llpanelexperiencelisteditor.h + llpanelexperiencelog.h + llpanelexperiencepicker.h + llpanelexperiences.h llpanelface.h llpanelgeneral.h llpanelgroup.h llpanelgroupbulk.h llpanelgroupbulkban.h llpanelgroupbulkimpl.h + llpanelgroupexperiences.h llpanelgroupgeneral.h llpanelgroupinvite.h llpanelgrouplandmoney.h @@ -924,7 +959,6 @@ set(viewer_HEADER_FILES llpanellandoptions.h llpanellogin.h llpanelmaininventory.h - llpanelmarketplaceoutboxinventory.h llpanelmediasettingsgeneral.h llpanelmediasettingspermissions.h llpanelmediasettingssecurity.h @@ -979,8 +1013,10 @@ set(viewer_HEADER_FILES llsavedsettingsglue.h llscrollingpanelparam.h llscrollingpanelparambase.h + llsculptidsize.h llselectmgr.h llsimplestat.h + llskinningutil.h llsky.h llslurl.h llspatialpartition.h @@ -1023,6 +1059,7 @@ set(viewer_HEADER_FILES lltracker.h lltranslate.h lluiconstants.h + lluiavatar.h lluploaddialog.h lluploadfloaterobservers.h llurl.h @@ -1032,6 +1069,7 @@ set(viewer_HEADER_FILES lluserauth.h llvectorperfoptions.h llvelocitybar.h + llversioninfo.h llviewchildren.h llviewerassetstats.h llviewerassetstorage.h @@ -1139,14 +1177,31 @@ set(viewer_HEADER_FILES roles_constants.h scriptcounter.h sgmemstat.h - sgversion.h shcommandhandler.h shfloatermediaticker.h + shupdatechecker.h wlfPanel_AdvSettings.h ) source_group("CMake Rules" FILES ViewerInstall.cmake) +#build_data.json creation moved to viewer_manifest.py MAINT-6413 +# the viewer_version.txt file created here is for passing to viewer_manifest and autobuild +# the summary.json file is created for the benefit of the TeamCity builds, where +# it is used to provide descriptive information to the build results page +add_custom_target(generate_viewer_version ALL + COMMAND ${CMAKE_COMMAND} -E echo ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION} > ${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt + COMMENT "Generating viewer_version.txt for manifest processing" + ) + +set_source_files_properties( + llimpanel.cpp + llversioninfo.cpp + PROPERTIES + DEPENDS generate_viewer_version # dummy dependency to force recompile every time + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake + ) + if (DARWIN) LIST(APPEND viewer_SOURCE_FILES llappviewermacosx.cpp) @@ -1163,7 +1218,6 @@ if (DARWIN) # Add resource files to the project. set(viewer_RESOURCE_FILES - ${VIEWER_BRANDING_ID}_icon.icns macview.r gpu_table.txt SecondLife.nib/ @@ -1205,24 +1259,34 @@ if (WINDOWS) llwindebug.h ) - # precompiled header configuration - # llviewerprecompiledheaders.cpp generates - # the .pch file. - # All sources added to viewer_SOURCE_FILES - # at this point use it. - set_source_files_properties(llviewerprecompiledheaders.cpp - PROPERTIES - COMPILE_FLAGS "/Ycllviewerprecompiledheaders.h" - ) - foreach( src_file ${viewer_SOURCE_FILES} ) - set_source_files_properties( - ${src_file} - PROPERTIES - COMPILE_FLAGS "/Yullviewerprecompiledheaders.h" - ) - endforeach( src_file ${viewer_SOURCE_FILES} ) - list(APPEND viewer_SOURCE_FILES llviewerprecompiledheaders.cpp) - + if (USE_NVAPI) + set(APPVWRW32_COMPILE_FLAGS "${APPVWRW32_COMPILE_FLAGS} -DUSE_NVAPI=1") + else (USE_NVAPI) + set(APPVWRW32_COMPILE_FLAGS "${APPVWRW32_COMPILE_FLAGS} -UUSE_NVAPI") + endif (USE_NVAPI) + set_source_files_properties(llappviewerwin32.cpp PROPERTIES COMPILE_FLAGS "${APPVWRW32_COMPILE_FLAGS}") + + # Replace the icons with the appropriate ones for the channel + # ('test' is the default) + set(ICON_PATH "default") + set(VIEWER_MACOSX_PHASE "d") + message("Copying icons for ${ICON_PATH}") + execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/icons/${ICON_PATH}/viewer.ico" + "${CMAKE_CURRENT_SOURCE_DIR}/res/viewer_icon.ico" + ) + execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/icons/${ICON_PATH}/viewer_256.BMP" + "${CMAKE_CURRENT_SOURCE_DIR}/res/viewer_icon.BMP" + ) + execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/icons/${ICON_PATH}/viewer_256.BMP" + "${CMAKE_CURRENT_SOURCE_DIR}/res-sdl/viewer_icon.BMP" + ) + # Add resource files to the project. # viewerRes.rc is the only buildable file, but # the rest are all dependencies of it. @@ -1251,7 +1315,9 @@ if (WINDOWS) res/lltooltranslate.cur res/lltoolzoomin.cur res/lltoolzoomout.cur - res/${VIEWER_BRANDING_ID}_icon.ico + res-sdl/viewer_icon.BMP + res/viewer_icon.BMP + res/viewer_icon.ico res/resource.h res/toolpickobject.cur res/toolpickobject2.cur @@ -1266,30 +1332,26 @@ if (WINDOWS) set_source_files_properties(${viewer_RESOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) - set(viewer_RESOURCE_FILES - res/resource.h - res/viewerRes.rc - ${viewer_RESOURCE_FILES} + + list(APPEND viewer_RESOURCE_FILES + ${CMAKE_CURRENT_BINARY_DIR}/viewerRes.rc ) - SOURCE_GROUP("Resource Files" FILES ${viewer_RESOURCE_FILES}) + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/viewerRes.rc + PROPERTIES COMPILE_FLAGS "-I${CMAKE_CURRENT_SOURCE_DIR}/res" + ) - list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES}) + source_group("Resource Files" FILES ${viewer_RESOURCE_FILES}) - find_library(DINPUT_LIBRARY dinput8 ${DIRECTX_LIBRARY_DIR}) - find_library(DXGUID_LIBRARY dxguid ${DIRECTX_LIBRARY_DIR}) - mark_as_advanced( - DINPUT_LIBRARY - DXGUID_LIBRARY - ) + list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES}) # see EXP-1765 - theory is opengl32.lib needs to be included before gdi32.lib (windows libs) set(viewer_LIBRARIES opengl32 advapi32 comdlg32 - ${DINPUT_LIBRARY} - ${DXGUID_LIBRARY} + dinput8 + dxguid gdi32 kernel32 odbc32 @@ -1299,30 +1361,11 @@ if (WINDOWS) shell32 user32 Vfw32 + wer Wbemuuid winspool + Normaliz ) - - find_library(DEBUG_INTEL_MEMOPS_LIBRARY ll_intel_memops - PATHS - ${LIBS_PREBUILT_DIR}/lib/debug - ${LIBS_PREBUILT_LEGACY_DIR}/lib/debug - "${QUICKTIME_SDK_DIR}\\libraries" - ) - - find_library(RELEASE_INTEL_MEMOPS_LIBRARY ll_intel_memops - PATHS - ${LIBS_PREBUILT_DIR}/lib/release - ${LIBS_PREBUILT_LEGACY_DIR}/lib/release - "${QUICKTIME_SDK_DIR}\\libraries" - ) - - if (DEBUG_INTEL_MEMOPS_LIBRARY AND RELEASE_INTEL_MEMOPS_LIBRARY) - list(APPEND viewer_LIBRARIES optimized ${RELEASE_INTEL_MEMOPS_LIBRARY}) - list(APPEND viewer_LIBRARIES debug ${DEBUG_INTEL_MEMOPS_LIBRARY}) - mark_as_advanced(RELEASE_INTEL_MEMOPS_LIBRARY) - mark_as_advanced(DEBUG_INTEL_MEMOPS_LIBRARY) - endif (DEBUG_INTEL_MEMOPS_LIBRARY AND RELEASE_INTEL_MEMOPS_LIBRARY) endif (WINDOWS) # Add the xui files. This is handy for searching for xui elements @@ -1361,7 +1404,6 @@ set(viewer_APPSETTINGS_FILES app_settings/settings.xml app_settings/settings_ascent.xml app_settings/settings_ascent_coa.xml - app_settings/settings_crash_behavior.xml app_settings/settings_files.xml app_settings/settings_per_account.xml app_settings/settings_sh.xml @@ -1372,6 +1414,7 @@ set(viewer_APPSETTINGS_FILES app_settings/viewerart.xml ${CMAKE_SOURCE_DIR}/../etc/message.xml ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg + packages-info.txt ) source_group("App Settings" FILES ${viewer_APPSETTINGS_FILES}) @@ -1407,7 +1450,22 @@ if (WINDOWS) list(APPEND viewer_SOURCE_FILES ${viewer_INSTALLER_FILES}) endif (WINDOWS) -set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") +if (OPENAL) + list(APPEND LLSTARTUP_COMPILE_DEFINITIONS "LL_OPENAL=1") +endif (OPENAL) + +if (USE_FMODSTUDIO) + list(APPEND LLSTARTUP_COMPILE_DEFINITIONS "LL_FMODSTUDIO=1") + set_source_files_properties(llpanellogin.cpp PROPERTIES COMPILE_DEFINITIONS "LL_FMODSTUDIO=1") +endif (USE_FMODSTUDIO) + +set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_DEFINITIONS "${LLSTARTUP_COMPILE_DEFINITIONS}") + +if (LIBVLCPLUGIN) + set_source_files_properties(llfloaterabout.cpp PROPERTIES COMPILE_DEFINITIONS "VLCPLUGIN=1") +else (LIBVLCPLUGIN) + set_source_files_properties(llfloaterabout.cpp PROPERTIES COMPILE_DEFINITIONS "VLCPLUGIN=0") +endif (LIBVLCPLUGIN) list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES}) @@ -1420,42 +1478,13 @@ add_executable(${VIEWER_BINARY_NAME} ${viewer_SOURCE_FILES} ) -if (!DISABLE_TEMPLATE_CHECK) - check_message_template(${VIEWER_BINARY_NAME}) -endif (!DISABLE_TEMPLATE_CHECK) - -set(PACKAGE OFF CACHE BOOL - "Add a package_viewer target that builds an installer package.") - -if(FMOD_LIBRARY_RELEASE) - get_filename_component(fmod_lib_rel_name ${FMOD_LIBRARY_RELEASE} NAME) - get_filename_component(fmod_lib_deb_name ${FMOD_LIBRARY_DEBUG} NAME) - add_custom_command(OUTPUT fmod_lib.marker - COMMENT "Copying fmod library to executable directory" - COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<$>:${FMOD_LIBRARY_RELEASE}>$<$:${FMOD_LIBRARY_DEBUG}>" "${CMAKE_CFG_INTDIR}/$<$>:${fmod_lib_rel_name}>$<$:${fmod_lib_deb_name}>" - DEPENDS "${FMOD_LIBRARY_RELEASE}") - add_custom_target(fmod_lib_copy DEPENDS fmod_lib.marker prepare) - if(DARWIN AND FMOD_EXTERNAL_LIB) - add_custom_command(OUTPUT fmod_lib_install.marker - COMMAND install_name_tool -id "@executable_path/../Resources/$<$>:${fmod_lib_rel_name}>$<$:${FMOD_LIBRARY_DEBUG}>" "${CMAKE_CFG_INTDIR}/$<$>:${fmod_lib_rel_name}>$<$:${fmod_lib_deb_name}>" - DEPENDS fmod_lib.marker) - add_dependencies(fmod_lib_copy fmod_lib_install.marker) - endif(DARWIN AND FMOD_EXTERNAL_LIB) - add_dependencies(${VIEWER_BINARY_NAME} fmod_lib_copy) - - #viewer_manifest.py needs these libraries (for now its all dylib) - if(MANIFEST_LIBRARIES) - set(MANIFEST_LIBRARIES ${MANIFEST_LIBRARIES}|optimized ${fmod_lib_rel_name}|debug ${fmod_lib_deb_name}) - else(MANIFEST_LIBRARIES) - set(MANIFEST_LIBRARIES optimized ${fmod_lib_rel_name}|debug ${fmod_lib_deb_name}) - endif(MANIFEST_LIBRARIES) - - if(WINDOWS) #If windows, fmod_lib_ points to a dll. The correct .lib needs to be linked (but copying is not necessary) - set(EXTRA_LINKER_FLAGS_RELEASE "/DELAYLOAD:${fmod_lib_rel_name}") - set(EXTRA_LINKER_FLAGS_DEBUG "/DELAYLOAD:${fmod_lib_deb_name}") - endif(WINDOWS) - list(APPEND viewer_LIBRARIES optimized "${FMOD_LINK_LIBRARY_RELEASE}" debug "${FMOD_LINK_LIBRARY_DEBUG}" ) -endif(FMOD_LIBRARY_RELEASE) +if(USE_PRECOMPILED_HEADERS) + target_precompiled_header(${VIEWER_BINARY_NAME} + ${CMAKE_CURRENT_SOURCE_DIR}/llviewerprecompiledheaders.h + ${CMAKE_CURRENT_SOURCE_DIR}/llviewerprecompiledheaders.cpp) +endif(USE_PRECOMPILED_HEADERS) + +option(PACKAGE "Add a package target that builds an installer package." ON) if (WINDOWS) set(release_flags "/MAP") @@ -1468,112 +1497,170 @@ if (WINDOWS) LINK_FLAGS_RELWITHDEBINFO "${release_flags} ${EXTRA_LINKER_FLAGS_RELEASE}" ) - # sets the 'working directory' for debugging from visual studio. - if (NOT UNATTENDED) - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} PRE_BUILD - COMMAND ${CMAKE_SOURCE_DIR}/tools/vstool/vstool.exe - ARGS - --solution - ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.sln - --workingdir - ${VIEWER_BINARY_NAME} - "${CMAKE_CURRENT_SOURCE_DIR}" - COMMENT "Setting the ${VIEWER_BINARY_NAME} working directory for debugging." + if(GEN_IS_MULTI_CONFIG) + set(VIEWER_BUILD_DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") + set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES + VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") + else() + set(VIEWER_BUILD_DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/package") + set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${VIEWER_BUILD_DEST_DIR}") + endif() + + add_dependencies(${VIEWER_BINARY_NAME} generate_viewer_version) + + # If adding a file to viewer_manifest.py in the WindowsManifest.construct() method, be sure to add the dependency + # here. + # *NOTE:Mani - This is a crappy hack to have important dependencies for the viewer_manifest copy action + # be met. I'm looking forward to a source-code split-up project next year that will address this kind of thing. + # In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py + # and have the build deps get tracked *please* tell me about it. + + if(NOT DISABLE_TCMALLOC) + # Configure a var for tcmalloc location, if used. + # Note the need to specify multiple names explicitly. + set(GOOGLE_PERF_TOOLS_SOURCE + ${SHARED_LIB_STAGING_DIR}/Release/libtcmalloc_minimal.dll + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll + ) + endif(NOT DISABLE_TCMALLOC) + + set(COPY_INPUT_DEPENDENCIES + # The following commented dependencies are determined at variably at build time. Can't do this here. + #${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libtcmalloc_minimal.dll => None ... Skipping libtcmalloc_minimal.dll + ${CMAKE_SOURCE_DIR}/../etc/message.xml + ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg + ${SHARED_LIB_STAGING_DIR}/Release/glod.dll + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/glod.dll + ${SHARED_LIB_STAGING_DIR}/Release/SLVoice.exe + ${SHARED_LIB_STAGING_DIR}/Release/vivoxplatform.dll + ${GOOGLE_PERF_TOOLS_SOURCE} + ${CMAKE_CURRENT_SOURCE_DIR}/licenses-win32.txt + ${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt + SLPlugin + media_plugin_libvlc + media_plugin_cef + basic_plugin_filepicker + ) + + if (ADDRESS_SIZE EQUAL 64) + list(APPEND COPY_INPUT_DEPENDENCIES + ${SHARED_LIB_STAGING_DIR}/Release/vivoxsdk_x64.dll + ${SHARED_LIB_STAGING_DIR}/Release/ortp_x64.dll + ) + else (ADDRESS_SIZE EQUAL 64) + list(APPEND COPY_INPUT_DEPENDENCIES + ${SHARED_LIB_STAGING_DIR}/Release/vivoxsdk.dll + ${SHARED_LIB_STAGING_DIR}/Release/ortp.dll + ) + endif (ADDRESS_SIZE EQUAL 64) + + if (USE_FMODSTUDIO) + if (ADDRESS_SIZE EQUAL 64) + list(APPEND COPY_INPUT_DEPENDENCIES + ${SHARED_LIB_STAGING_DIR}/Release/fmod64.dll + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod64.dll + ${SHARED_LIB_STAGING_DIR}/Debug/fmodL64.dll ) - endif (NOT UNATTENDED) + else (ADDRESS_SIZE EQUAL 64) + list(APPEND COPY_INPUT_DEPENDENCIES + ${SHARED_LIB_STAGING_DIR}/Release/fmod.dll + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll + ) + endif (ADDRESS_SIZE EQUAL 64) + endif (USE_FMODSTUDIO) - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} PRE_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/messages/message_template.msg - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings/message_template.msg - COMMENT "Copying message_template.msg to the runtime folder." - ) + if(MSVC_IDE) + set(VIEWER_BUILD_DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") + else() + set(VIEWER_BUILD_DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/packaged") + endif() add_custom_command( - TARGET ${VIEWER_BINARY_NAME} PRE_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${CMAKE_CURRENT_SOURCE_DIR}/../../etc/message.xml - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings/message.xml - COMMENT "Copying message.xml to the runtime folder." - ) + OUTPUT ${VIEWER_BUILD_DEST_DIR}/copy_touched.bat + COMMAND ${PYTHON_EXECUTABLE} + ARGS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + --actions=copy + --arch=${ARCH} + --artwork=${ARTWORK_DIR} + --branding_id=${VIEWER_BRANDING_ID} + --build=${CMAKE_CURRENT_BINARY_DIR} + --buildtype=${CMAKE_BUILD_TYPE} + --configuration=${VIEWER_BUILD_DEST_DIR} + --dest=${VIEWER_BUILD_DEST_DIR} + --grid=${GRID} + --channel=${VIEWER_CHANNEL} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt + --source=${CMAKE_CURRENT_SOURCE_DIR} + --touch=${VIEWER_BUILD_DEST_DIR}/copy_touched.bat + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + generate_viewer_version + stage_third_party_libs + llcommon + ${COPY_INPUT_DEPENDENCIES} + COMMENT "Performing viewer_manifest copy" + ) + + add_custom_target(copy_w_viewer_manifest ALL DEPENDS ${VIEWER_BUILD_DEST_DIR}/copy_touched.bat) + + add_dependencies(${VIEWER_BINARY_NAME} stage_third_party_libs llcommon copy_w_viewer_manifest) if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts) add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts) endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts) - add_custom_command( - OUTPUT ${CMAKE_CFG_INTDIR}/touched.bat - COMMAND ${PYTHON_EXECUTABLE} - ARGS - ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py - --arch=${ARCH} - --artwork=${ARTWORK_DIR} - --branding_id=${VIEWER_BRANDING_ID} - --build=${CMAKE_CURRENT_BINARY_DIR} - --channel=${VIEWER_CHANNEL} - --configuration=${CMAKE_CFG_INTDIR} - --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} - --grid=${GRID} - --login_channel=${VIEWER_LOGIN_CHANNEL} - --source=${CMAKE_CURRENT_SOURCE_DIR} - --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/touched.bat - --extra_libraries="${MANIFEST_LIBRARIES}" - DEPENDS - ${VIEWER_BINARY_NAME} - ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py - ) + add_dependencies(${VIEWER_BINARY_NAME} + SLPlugin + ) + + EMBED_MANIFEST(${VIEWER_BINARY_NAME} 1) + + if (PACKAGE) add_custom_command( - OUTPUT ${CMAKE_CFG_INTDIR}/copy_touched.bat + OUTPUT ${VIEWER_BUILD_DEST_DIR}/touched.bat COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py --arch=${ARCH} --artwork=${ARTWORK_DIR} - --actions=copy --branding_id=${VIEWER_BRANDING_ID} --build=${CMAKE_CURRENT_BINARY_DIR} + --buildtype=${CMAKE_BUILD_TYPE} --channel=${VIEWER_CHANNEL} - --configuration=${CMAKE_CFG_INTDIR} - --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt + --configuration=${VIEWER_BUILD_DEST_DIR} + --dest=${VIEWER_BUILD_DEST_DIR} --grid=${GRID} - --login_channel=${VIEWER_LOGIN_CHANNEL} --source=${CMAKE_CURRENT_SOURCE_DIR} - --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/copy_touched.bat - --extra_libraries="${MANIFEST_LIBRARIES}" + --touch=${VIEWER_BUILD_DEST_DIR}/touched.bat DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py - COMMENT "Performing viewer_manifest copy" + ${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt + ${COPY_INPUT_DEPENDENCIES} ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit basic_plugin_filepicker) - - if(WORD_SIZE EQUAL 32) - add_dependencies(${VIEWER_BINARY_NAME} winmm_shim) - endif(WORD_SIZE EQUAL 32) - - if (PACKAGE) - add_custom_target(package_viewer ALL DEPENDS ${CMAKE_CFG_INTDIR}/touched.bat) + add_custom_target(llpackage ALL DEPENDS + ${VIEWER_BUILD_DEST_DIR}/touched.bat + windows-setup-build-all + ) endif (PACKAGE) endif (WINDOWS) -# *NOTE - this list is very sensitive to ordering, test carefully on all +# *NOTE: - this list is very sensitive to ordering, test carefully on all # platforms if you change the releative order of the entries here. # In particular, cmake 2.6.4 (when buidling with linux/makefile generators) # appears to sometimes de-duplicate redundantly listed dependencies improperly. # To work around this, higher level modules should be listed before the modules # that they depend upon. -brad target_link_libraries(${VIEWER_BINARY_NAME} + ${PNG_PRELOAD_ARCHIVES} + ${ZLIB_PRELOAD_ARCHIVES} ${GOOGLE_PERFTOOLS_LIBRARIES} + ${CRASHPAD_LIBRARIES} ${LLAUDIO_LIBRARIES} ${LLAUDIO_VORBIS_LIBRARIES} ${LLCHARACTER_LIBRARIES} @@ -1590,11 +1677,11 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLVFS_LIBRARIES} ${LLWINDOW_LIBRARIES} ${LLXML_LIBRARIES} -# ${LSCRIPT_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${NDOF_LIBRARY} ${NVAPI_LIBRARY} + ${URIPARSER_LIBRARY} ${viewer_LIBRARIES} ${Boost_CONTEXT_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} @@ -1604,33 +1691,42 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${Boost_DATE_TIME_LIBRARY} ${DBUSGLIB_LIBRARIES} ${OPENGL_LIBRARIES} + ${FMOD_LIBRARY} # must come after LLAudio ${GLOD_LIBRARIES} ${APRUTIL_LIBRARIES} ${OPENGL_LIBRARIES} - ${JSONCPP_LIBRARIES} ${SDL_LIBRARY} ${SMARTHEAP_LIBRARY} ${UI_LIBRARIES} ${WINDOWS_LIBRARIES} ${XMLRPCEPI_LIBRARIES} - ${ELFIO_LIBRARIES} + ${CRYPTO_LIBRARIES} + ${OPENSSL_LIBRARIES} + ${CRYPTO_LIBRARIES} ${HUNSPELL_LIBRARY} ${LLPHYSICSEXTENSIONS_LIBRARIES} ${LLAPPEARANCE_LIBRARIES} + absl::flat_hash_map + absl::node_hash_map + nlohmann_json::nlohmann_json + fmt::fmt ) if (LINUX) - add_custom_command( - OUTPUT secondlife-stripped - COMMAND strip - ARGS --strip-debug -o secondlife-stripped ${VIEWER_BINARY_NAME} - DEPENDS ${VIEWER_BINARY_NAME} - ) + set(product ${VIEWER_CHANNEL_NOSPACE}-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}) - set(product ${VIEWER_BRANDING_NAME_CAMELCASE}-${ARCH}-${${ROOT_PROJECT_NAME}_VERSION}) + # These are the generated targets that are copied to package/ + set(COPY_INPUT_DEPENDENCIES + ${VIEWER_BINARY_NAME} + SLPlugin + media_plugin_gstreamer010 + llcommon + ) + + add_dependencies(${VIEWER_BINARY_NAME} generate_viewer_version) add_custom_command( - OUTPUT ${product}.tar.bz2 + OUTPUT ${product}.tar.xz COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py @@ -1640,17 +1736,16 @@ if (LINUX) --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} --channel=${VIEWER_CHANNEL} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt + --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged --grid=${GRID} - --installer_name=${product} - --login_channel=${VIEWER_LOGIN_CHANNEL} --source=${CMAKE_CURRENT_SOURCE_DIR} --standalone=${STANDALONE} --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched - --extra_libraries="${MANIFEST_LIBRARIES}" DEPENDS - secondlife-stripped ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ${COPY_INPUT_DEPENDENCIES} ) add_custom_command( @@ -1664,44 +1759,54 @@ if (LINUX) --branding_id=${VIEWER_BRANDING_ID} --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} - --channel=${VIEWER_CHANNEL} + --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged --grid=${GRID} - --installer_name=${product} - --login_channel=${VIEWER_LOGIN_CHANNEL} + --channel=${VIEWER_CHANNEL} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --source=${CMAKE_CURRENT_SOURCE_DIR} - --standalone=${STANDALONE} - --extra_libraries="${MANIFEST_LIBRARIES}" DEPENDS - secondlife-stripped ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ${COPY_INPUT_DEPENDENCIES} + COMMENT "Performing viewer_manifest copy" ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer010 media_plugin_webkit basic_plugin_filepicker) - add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer010 basic_plugin_filepicker) if (PACKAGE) - add_custom_target(package_viewer ALL DEPENDS ${product}.tar.bz2) - add_dependencies(package_viewer copy_l_viewer_manifest) + add_custom_target(llpackage ALL DEPENDS ${product}.tar.xz) + check_message_template(llpackage) + else (PACKAGE) + add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched) endif (PACKAGE) endif (LINUX) if (DARWIN) set(product ${VIEWER_BRANDING_NAME}) + set(MACOSX_BUNDLE_INFO_STRING "A stable third-party Second Life viewer.") + set(MACOSX_BUNDLE_ICON_FILE "viewer.icns") + set(MACOSX_BUNDLE_GUI_IDENTIFIER "${VIEWER_BRANDING_NAME}") + set(MACOSX_BUNDLE_LONG_VERSION_STRING "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}") + set(MACOSX_BUNDLE_BUNDLE_NAME "${VIEWER_BRANDING_NAME}") + set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}") + set(MACOSX_BUNDLE_BUNDLE_VERSION "${${ROOT_PROJECT_NAME}_VERSION}") + set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2010-2016 Siana Gearz") + set_target_properties( ${VIEWER_BINARY_NAME} PROPERTIES OUTPUT_NAME "${product}" - MACOSX_BUNDLE_INFO_STRING "A stable third-party Second Life viewer." - MACOSX_BUNDLE_ICON_FILE "${VIEWER_BRANDING_ID}_icon.icns" - MACOSX_BUNDLE_GUI_IDENTIFIER "${VIEWER_BRANDING_NAME}" - MACOSX_BUNDLE_LONG_VERSION_STRING "${${ROOT_PROJECT_NAME}_VERSION}" - MACOSX_BUNDLE_BUNDLE_NAME "${VIEWER_BRANDING_NAME}" - MACOSX_BUNDLE_SHORT_VERSION_STRING "${${ROOT_PROJECT_NAME}_VERSION}" - MACOSX_BUNDLE_BUNDLE_VERSION "${${ROOT_PROJECT_NAME}_VERSION}" - MACOSX_BUNDLE_COPYRIGHT "Copyright 2013 Siana Gearz" + MACOSX_BUNDLE_INFO_PLIST + "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist" + ) + + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist" + "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app/Contents/Info.plist" ) + add_dependencies(${VIEWER_BINARY_NAME} generate_viewer_version) + add_custom_command( TARGET ${VIEWER_BINARY_NAME} POST_BUILD COMMAND ${PYTHON_EXECUTABLE} @@ -1718,31 +1823,32 @@ if (DARWIN) --source=${CMAKE_CURRENT_SOURCE_DIR} --extra_libraries="${MANIFEST_LIBRARIES}" DEPENDS - ${VIEWER_BINARY_NAME} - ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ${VIEWER_BINARY_NAME} + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit basic_plugin_filepicker) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_libvlc media_plugin_cef basic_plugin_filepicker) if (PACKAGE) - add_custom_target(package_viewer ALL DEPENDS ${VIEWER_BINARY_NAME}) + add_custom_target(llpackage ALL DEPENDS ${VIEWER_BINARY_NAME}) + add_dependencies(llpackage generate_viewer_version) add_custom_command( - TARGET package_viewer POST_BUILD + TARGET llpackage POST_BUILD COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + --arch=${ARCH} --artwork=${ARTWORK_DIR} - --branding_id=${VIEWER_BRANDING_ID} --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} --channel=${VIEWER_CHANNEL} --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app --grid=${GRID} - --login_channel=${VIEWER_LOGIN_CHANNEL} + --channel=${VIEWER_CHANNEL} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --source=${CMAKE_CURRENT_SOURCE_DIR} - --extra_libraries="${MANIFEST_LIBRARIES}" --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched DEPENDS ${VIEWER_BINARY_NAME} @@ -1755,18 +1861,19 @@ if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) +if (FALSE) + # Breakpad symbol-file generation + set(SYMBOL_NAME ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${VIEWER_CHANNEL_NOSPACE}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}-symbols) -if (PACKAGE) - set(SYMBOL_NAME ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${VIEWER_BRANDING_NAME_CAMELCASE}-${${ROOT_PROJECT_NAME}_VERSION}-symbols) set(SYMBOL_SEARCH_DIRS "") if (WINDOWS) list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") - set(VIEWER_SYMBOL_FILE "${SYMBOL_NAME}-${PREBUILT_TYPE}.tar.bz2") + set(VIEWER_SYMBOL_FILE "${SYMBOL_NAME}-${AUTOBUILD_PLATFORM_NAME}.tar.bz2") # slplugin.exe failing symbols dump - need to debug, might have to do with updated version of google breakpad # set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe") set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX}") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") - set(VIEWER_DUMP_SYMS dump_syms.exe) + set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest) endif (WINDOWS) if (DARWIN) list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") @@ -1775,28 +1882,25 @@ if (PACKAGE) list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/plugins/gstreamer010/${CMAKE_CFG_INTDIR}") list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/plugins/quicktime/${CMAKE_CFG_INTDIR}") list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/plugins/webkit/${CMAKE_CFG_INTDIR}") - set(VIEWER_SYMBOL_FILE "${SYMBOL_NAME}-darwin.tar.bz2") + set(VIEWER_SYMBOL_FILE "${SYMBOL_NAME}-darwin.tar.bz2") set(VIEWER_EXE_GLOBS "'${VIEWER_BRANDING_NAME}' SLPlugin") set(VIEWER_LIB_GLOB "*.dylib") - set(VIEWER_DUMP_SYMS dump_syms) endif (DARWIN) if (LINUX) list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/packaged") - set(VIEWER_SYMBOL_FILE "${SYMBOL_NAME}-linux-${ARCH}.tar.bz2") - set(VIEWER_EXE_GLOBS "${VIEWER_BRANDING_ID}-do-not-run-directly SLPlugin") + set(VIEWER_SYMBOL_FILE "${SYMBOL_NAME}-${AUTOBUILD_PLATFORM_NAME}.tar.bz2") + set(VIEWER_EXE_GLOBS "do-not-directly-run-${VIEWER_BINARY_NAME} SLPlugin") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) - set(VIEWER_DUMP_SYMS dump_syms) endif (LINUX) - if(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) - if(CMAKE_CFG_INTDIR STREQUAL ".") + if(GEN_IS_MULTI_CONFIG) set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE}) - else(CMAKE_CFG_INTDIR STREQUAL ".") + else() # set LLBUILD_CONFIG to be a shell variable evaluated at build time # reflecting the configuration we are currently building. set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR}) - endif(CMAKE_CFG_INTDIR STREQUAL ".") + endif() add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" COMMAND "${PYTHON_EXECUTABLE}" ARGS @@ -1805,153 +1909,23 @@ if (PACKAGE) "${SYMBOL_SEARCH_DIRS}" "${VIEWER_EXE_GLOBS}" "${VIEWER_LIB_GLOB}" - "${LIBS_PREBUILT_DIR}/bin/${VIEWER_DUMP_SYMS}|${LIBS_PREBUILT_LEGACY_DIR}/bin/${VIEWER_DUMP_SYMS}" + "${AUTOBUILD_INSTALL_DIR}/bin/dump_syms" "${VIEWER_SYMBOL_FILE}" DEPENDS generate_breakpad_symbols.py VERBATIM) - add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}") - add_dependencies(generate_breakpad_symbols ${VIEWER_BINARY_NAME}) -if(VIEWER_COPY_MANIFEST) - add_dependencies(generate_breakpad_symbols ${VIEWER_COPY_MANIFEST}) -endif(VIEWER_COPY_MANIFEST) - add_dependencies(package_viewer generate_breakpad_symbols) - endif(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) -endif (PACKAGE) + add_custom_target(generate_symbols DEPENDS "${VIEWER_SYMBOL_FILE}" ${VIEWER_BINARY_NAME} "${VIEWER_COPY_MANIFEST}") + add_dependencies(generate_symbols ${VIEWER_BINARY_NAME}) + if (WINDOWS OR LINUX) + add_dependencies(generate_symbols "${VIEWER_COPY_MANIFEST}") + endif (WINDOWS OR LINUX) + + add_dependencies(llpackage generate_symbols) +endif () # Add tests if (LL_TESTS) - ADD_VIEWER_BUILD_TEST(llagentaccess viewer) - #ADD_VIEWER_BUILD_TEST(llworldmap viewer) - #ADD_VIEWER_BUILD_TEST(llworldmipmap viewer) - ADD_VIEWER_BUILD_TEST(lltextureinfo viewer) - ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer) - ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer) - #ADD_VIEWER_COMM_BUILD_TEST(lltranslate viewer "") endif (LL_TESTS) -# Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py -if (WINDOWS) - - IF(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS) - FOREACH(RUNTIME_LIB ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}) - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${RUNTIME_LIB} - ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Copying ${RUNTIME_LIB} to the runtime folder." - ) - ENDFOREACH(RUNTIME_LIB ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}) - ENDIF(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS) - - SET(BUILT_LLCOMMON $) - - set_target_properties(llcommon - PROPERTIES - LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT" - LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\"" - LINK_FLAGS_RELEASE "${release_flags} /LTCG" - LINK_FLAGS_RELWITHDEBINFO "${release_flags}" - ) - - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${BUILT_LLCOMMON} - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} - COMMENT "Copying llcommon.dll to the runtime folder." - ) +check_message_template(${VIEWER_BINARY_NAME}) - SET(BUILT_SLPLUGIN $) - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${BUILT_SLPLUGIN} - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} - COMMENT "Copying SLPlugin executable to the runtime folder." - ) - - SET(BUILT_WEBKIT_PLUGIN $) - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${BUILT_WEBKIT_PLUGIN} - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin - COMMENT "Copying WebKit Plugin to the runtime folder." - ) - - SET(BUILT_QUICKTIME_PLUGIN $) - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${BUILT_QUICKTIME_PLUGIN} - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin - COMMENT "Copying Quicktime Plugin to the runtime folder." - ) - - SET(BUILT_FILEPICKER_PLUGIN $) - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${BUILT_FILEPICKER_PLUGIN} - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin - COMMENT "Copying filepicker Plugin to the runtime folder." - ) - -# winmm doesn't build on windows 64 - if(WORD_SIZE EQUAL 32) - SET(BUILT_WINMM_SHIM_PLUGIN $) - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${BUILT_WINMM_SHIM_PLUGIN} - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} - COMMENT "Copying winmm.dll to the runtime folder." - ) - endif(WORD_SIZE EQUAL 32) - - # Copying the mime_types.xml file to app_settings - set(mime_types_source "${CMAKE_SOURCE_DIR}/newview/skins/default/xui/en-us") - set(mime_types_dest "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings") - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${mime_types_source}/mime_types_windows.xml - ${mime_types_dest}/mime_types.xml - COMMENT "Copying mime_types_windows.xml to mime_types.xml." - ) - -endif (WINDOWS) - -if (DARWIN) -# Don't do this here -- it's taken care of by viewer_manifest.py -# add_custom_command(TARGET ${VIEWER_BINARY_NAME} POST_BUILD -# COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib/release/libllqtwebkit.dylib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin/ -# DEPENDS ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib/release/libllqtwebkit.dylib -# ) -endif (DARWIN) diff --git a/indra/newview/English.lproj/InfoPlist.strings.in b/indra/newview/English.lproj/InfoPlist.strings.in index e10c863356..8a2f3a3811 100644 --- a/indra/newview/English.lproj/InfoPlist.strings.in +++ b/indra/newview/English.lproj/InfoPlist.strings.in @@ -1,6 +1,6 @@ /* Localized versions of Info.plist keys */ -CFBundleName = "${VIEWER_CHANNEL_ONE_WORD}"; +CFBundleName = "${VIEWER_CHANNEL_NOSPACE}"; CFBundleShortVersionString = "${VIEWER_CHANNEL} Viewer ${vMAJOR}.${vMINOR}.${vPATCH}.${vBUILD}"; CFBundleGetInfoString = "${VIEWER_CHANNEL} Viewer ${vMAJOR}.${vMINOR}.${vPATCH}.${vBUILD}, Copyright 2012 Siana Gearz"; diff --git a/indra/newview/NACLantispam.cpp b/indra/newview/NACLantispam.cpp index bcdab08695..2ad788a255 100644 --- a/indra/newview/NACLantispam.cpp +++ b/indra/newview/NACLantispam.cpp @@ -14,457 +14,299 @@ */ #include "llviewerprecompiledheaders.h" + #include "NACLantispam.h" -#include "llviewercontrol.h" -#include "llnotificationsutil.h" -#include "llviewerobjectlist.h" #include "llagent.h" +#include "llavataractions.h" +#include "llcallbacklist.h" // For idle cleaning +#include "llnotificationsutil.h" #include "lltrans.h" -#include -#include - -bool can_block(const LLUUID& id) -{ - if (id.isNull() || gAgent.getID() == id) return false; //Can't block system or self. - if (const LLViewerObject* obj = gObjectList.findObject(id)) //From an object, - return !obj->permYouOwner(); //not own object. - return true; -} - -U32 NACLAntiSpamRegistry::globalAmount; -U32 NACLAntiSpamRegistry::globalTime; -bool NACLAntiSpamRegistry::bGlobalQueue; -NACLAntiSpamQueue* NACLAntiSpamRegistry::queues[NACLAntiSpamRegistry::QUEUE_MAX] = {0}; -std::tr1::unordered_map NACLAntiSpamRegistry::globalEntries; -std::tr1::unordered_map::iterator NACLAntiSpamRegistry::it2; - -// The following sounds will be ignored for purposes of spam protection. They have been gathered from wiki documentation of frequent official sounds. -const std::string COLLISION_SOUNDS[] ={"dce5fdd4-afe4-4ea1-822f-dd52cac46b08","51011582-fbca-4580-ae9e-1a5593f094ec","68d62208-e257-4d0c-bbe2-20c9ea9760bb","75872e8c-bc39-451b-9b0b-042d7ba36cba","6a45ba0b-5775-4ea8-8513-26008a17f873","992a6d1b-8c77-40e0-9495-4098ce539694","2de4da5a-faf8-46be-bac6-c4d74f1e5767","6e3fb0f7-6d9c-42ca-b86b-1122ff562d7d","14209133-4961-4acc-9649-53fc38ee1667","bc4a4348-cfcc-4e5e-908e-8a52a8915fe6","9e5c1297-6eed-40c0-825a-d9bcd86e3193","e534761c-1894-4b61-b20c-658a6fb68157","8761f73f-6cf9-4186-8aaa-0948ed002db1","874a26fd-142f-4173-8c5b-890cd846c74d","0e24a717-b97e-4b77-9c94-b59a5a88b2da","75cf3ade-9a5b-4c4d-bb35-f9799bda7fb2","153c8bf7-fb89-4d89-b263-47e58b1b4774","55c3e0ce-275a-46fa-82ff-e0465f5e8703","24babf58-7156-4841-9a3f-761bdbb8e237","aca261d8-e145-4610-9e20-9eff990f2c12","0642fba6-5dcf-4d62-8e7b-94dbb529d117","25a863e8-dc42-4e8a-a357-e76422ace9b5","9538f37c-456e-4047-81be-6435045608d4","8c0f84c3-9afd-4396-b5f5-9bca2c911c20","be582e5d-b123-41a2-a150-454c39e961c8","c70141d4-ba06-41ea-bcbc-35ea81cb8335","7d1826f4-24c4-4aac-8c2e-eff45df37783","063c97d3-033a-4e9b-98d8-05c8074922cb","00000000-0000-0000-0000-000000000120"}; -const int COLLISION_SOUNDS_SIZE=29; - -// NaClAntiSpamQueueEntry - -NACLAntiSpamQueueEntry::NACLAntiSpamQueueEntry() -{ - entryTime=0; - entryAmount=0; - blocked=false; -} -void NACLAntiSpamQueueEntry::clearEntry() -{ - entryTime=0; - entryAmount=0; - blocked=false; -} -U32 NACLAntiSpamQueueEntry::getEntryAmount() const -{ - return entryAmount; -} -U32 NACLAntiSpamQueueEntry::getEntryTime() const -{ - return entryTime; -} -void NACLAntiSpamQueueEntry::updateEntryAmount() -{ - entryAmount++; -} -void NACLAntiSpamQueueEntry::updateEntryTime() -{ - entryTime=time(0); -} -void NACLAntiSpamQueueEntry::setBlocked() -{ - blocked=true; -} -bool NACLAntiSpamQueueEntry::getBlocked() const -{ - return blocked; -} +#include "llviewerobjectlist.h" -// NaClAntiSpamQueue +#include -NACLAntiSpamQueue::NACLAntiSpamQueue(U32 time, U32 amount) -{ - queueTime=time; - queueAmount=amount; -} -void NACLAntiSpamQueue::setAmount(U32 amount) -{ - queueAmount=amount; -} -void NACLAntiSpamQueue::setTime(U32 time) -{ - queueTime=time; -} -U32 NACLAntiSpamQueue::getAmount() const -{ - return queueAmount; -} -U32 NACLAntiSpamQueue::getTime() const -{ - return queueTime; -} -void NACLAntiSpamQueue::clearEntries() -{ - for(it = entries.begin(); it != entries.end(); it++) +class NACLAntiSpamQueue +{ + friend class NACLAntiSpamRegistry; +public: + const U32& getAmount() const { return mAmount; } + const U32& getTime() const { return mTime; } +protected: + NACLAntiSpamQueue(const U32& time, const U32& amount) : mTime(time), mAmount(amount) {} + void setAmount(const U32& amount) { mAmount = amount; } + void setTime(const U32& time) { mTime = time; } + void block(const LLUUID& source) { mEntries[source.asString()].block(); } + void reset() { mEntries.clear(); } + // Returns 0 if unblocked/disabled, 1 if check results in a new block, 2 if by an existing block + U8 check(const LLUUID& source, const U32& multiplier) { - it->second->clearEntry(); + const auto key = source.asString(); + auto it = mEntries.find(key); + if (it != mEntries.end()) + return it->second.blockIfNeeded(mAmount * multiplier, mTime); + mEntries[key]; // Default construct an Entry + return 0U; } -} -void NACLAntiSpamQueue::purgeEntries() -{ - for(it = entries.begin(); it != entries.end(); it++) + void idle() { - delete it->second; - } - entries.clear(); -} -void NACLAntiSpamQueue::blockEntry(LLUUID& source) -{ - it=entries.find(source.asString()); - if(it == entries.end()) - { - entries[source.asString()]=new NACLAntiSpamQueueEntry(); + // Clean out old unblocked entries + const auto time_limit = mTime + 1; // One second after time has gone up, the next offense would reset anyway + for (auto it = mEntries.begin(); it != mEntries.end();) + { + const auto& entry = it->second; + if (entry.getBlocked() || entry.withinBlockTime(time_limit)) + ++it; + else it = mEntries.erase(it); + } } - entries[source.asString()]->setBlocked(); -} -int NACLAntiSpamQueue::checkEntry(LLUUID& name, U32 multiplier) -// Returns 0 if unblocked/disabled, 1 if check results in a new block, 2 if by an existing block -{ - static LLCachedControl enabled(gSavedSettings,"AntiSpamEnabled",false); - if(!enabled) return 0; - it=entries.find(name.asString()); - if(it != entries.end()) + +private: + class Entry { - if(it->second->getBlocked()) return 2; - U32 eTime=it->second->getEntryTime(); - U32 currentTime=time(0); - if((currentTime-eTime) <= queueTime) + friend class NACLAntiSpamQueue; + protected: + void reset() { updateTime(); mAmount = 1; mBlocked = false; } + const U32& getAmount() const { return mAmount; } + const std::time_t& getTime() const { return mTime; } + void updateTime() { mTime = time(nullptr); } + void block() { mBlocked = true; } + bool withinBlockTime(const U32& time_limit) const { return (time(nullptr) - mTime) <= time_limit; } + U8 blockIfNeeded(const U32& amount, const U32& time_limit) { - it->second->updateEntryAmount(); - U32 eAmount=it->second->getEntryAmount(); - if(eAmount > (queueAmount*multiplier)) + if (mBlocked) return 2U; // Already blocked + if (withinBlockTime(time_limit)) { - it->second->setBlocked(); - return 1; + if (++mAmount > amount) + { + block(); + return 1U; + } } - else - return 0; - } - else - { - it->second->clearEntry(); - it->second->updateEntryAmount(); - it->second->updateEntryTime(); - return 0; + else reset(); // Enough time has passed to forgive or not already in list + return 0U; } - } - else - { - //LL_DEBUGS() << "[antispam] New queue entry:" << name.asString() << LL_ENDL; - entries[name.asString()]=new NACLAntiSpamQueueEntry(); - entries[name.asString()]->updateEntryAmount(); - entries[name.asString()]->updateEntryTime(); - return 0; - } + bool getBlocked() const { return mBlocked; } + private: + U32 mAmount = 1; + std::time_t mTime = time(nullptr); + bool mBlocked = false; + }; + boost::unordered_map mEntries; + U32 mAmount, mTime; +}; + +bool can_block(const LLUUID& id) +{ + if (id.isNull() || gAgentID == id) return false; // Can't block system or self. + if (const LLViewerObject* obj = gObjectList.findObject(id)) // From an object, + return !obj->permYouOwner(); // not own object. + return true; } +bool is_collision_sound(const std::string& sound) +{ + // The following sounds will be ignored for purposes of spam protection. They have been gathered from wiki documentation of frequent official sounds. + const std::array COLLISION_SOUNDS = { + "dce5fdd4-afe4-4ea1-822f-dd52cac46b08", + "51011582-fbca-4580-ae9e-1a5593f094ec", + "68d62208-e257-4d0c-bbe2-20c9ea9760bb", + "75872e8c-bc39-451b-9b0b-042d7ba36cba", + "6a45ba0b-5775-4ea8-8513-26008a17f873", + "992a6d1b-8c77-40e0-9495-4098ce539694", + "2de4da5a-faf8-46be-bac6-c4d74f1e5767", + "6e3fb0f7-6d9c-42ca-b86b-1122ff562d7d", + "14209133-4961-4acc-9649-53fc38ee1667", + "bc4a4348-cfcc-4e5e-908e-8a52a8915fe6", + "9e5c1297-6eed-40c0-825a-d9bcd86e3193", + "e534761c-1894-4b61-b20c-658a6fb68157", + "8761f73f-6cf9-4186-8aaa-0948ed002db1", + "874a26fd-142f-4173-8c5b-890cd846c74d", + "0e24a717-b97e-4b77-9c94-b59a5a88b2da", + "75cf3ade-9a5b-4c4d-bb35-f9799bda7fb2", + "153c8bf7-fb89-4d89-b263-47e58b1b4774", + "55c3e0ce-275a-46fa-82ff-e0465f5e8703", + "24babf58-7156-4841-9a3f-761bdbb8e237", + "aca261d8-e145-4610-9e20-9eff990f2c12", + "0642fba6-5dcf-4d62-8e7b-94dbb529d117", + "25a863e8-dc42-4e8a-a357-e76422ace9b5", + "9538f37c-456e-4047-81be-6435045608d4", + "8c0f84c3-9afd-4396-b5f5-9bca2c911c20", + "be582e5d-b123-41a2-a150-454c39e961c8", + "c70141d4-ba06-41ea-bcbc-35ea81cb8335", + "7d1826f4-24c4-4aac-8c2e-eff45df37783", + "063c97d3-033a-4e9b-98d8-05c8074922cb", + "00000000-0000-0000-0000-000000000120" + }; + + for (const auto& collision : COLLISION_SOUNDS) + if (collision == sound) + return true; + return false; +} // NaClAntiSpamRegistry -static const char* QUEUE_NAME[NACLAntiSpamRegistry::QUEUE_MAX] = { -"Chat", -"Inventory", -"Instant Message", -"calling card", -"sound", -"Sound Preload", -"Script Dialog", -"Teleport"}; +constexpr std::array QUEUE_NAME = { + "Chat", + "Inventory", + "Instant Message", + "calling card", + "sound", + "Sound Preload", + "Script Dialog", + "Teleport" +}; -NACLAntiSpamRegistry::NACLAntiSpamRegistry(U32 time, U32 amount) +NACLAntiSpamRegistry::NACLAntiSpamRegistry() { - globalTime=time; - globalAmount=amount; - static LLCachedControl _NACL_AntiSpamGlobalQueue(gSavedSettings,"_NACL_AntiSpamGlobalQueue"); - bGlobalQueue=_NACL_AntiSpamGlobalQueue; - for(int queue = 0; queue < QUEUE_MAX; ++queue) - { - queues[queue] = new NACLAntiSpamQueue(time,amount); - } -} -//static -const char* NACLAntiSpamRegistry::getQueueName(U32 queue_id) -{ - if(queue_id >= QUEUE_MAX) - return "Unknown"; - return QUEUE_NAME[queue_id]; -} -//static -void NACLAntiSpamRegistry::registerQueues(U32 time, U32 amount) -{ - globalTime=time; - globalAmount=amount; - static LLCachedControl _NACL_AntiSpamGlobalQueue(gSavedSettings,"_NACL_AntiSpamGlobalQueue"); - bGlobalQueue=_NACL_AntiSpamGlobalQueue; - for(int queue = 0; queue < QUEUE_MAX; ++queue) - { - queues[queue] = new NACLAntiSpamQueue(time,amount); - } + auto control = gSavedSettings.getControl("_NACL_AntiSpamTime"); + const U32 time = control->get().asInteger(); + mConnections[0] = control->getSignal()->connect(boost::bind(&NACLAntiSpamRegistry::handleNaclAntiSpamTimeChanged, _2)); + + control = gSavedSettings.getControl("_NACL_AntiSpamAmount"); + const U32 amount = control->get().asInteger(); + mConnections[1] = control->getSignal()->connect(boost::bind(&NACLAntiSpamRegistry::handleNaclAntiSpamAmountChanged, _2)); + + control = gSavedSettings.getControl("_NACL_AntiSpamGlobalQueue"); + mConnections[2] = control->getSignal()->connect(boost::bind(&NACLAntiSpamRegistry::handleNaclAntiSpamGlobalQueueChanged, _2)); + initializeQueues(control->get(), time, amount); } -//static -/*void NACLAntiSpamRegistry::registerQueue(U32 name, U32 time, U32 amount) -{ - it=queues.find(name); - if(it == queues.end()) - { - queues[name]=new NACLAntiSpamQueue(time,amount); - } -}*/ -//static -void NACLAntiSpamRegistry::setRegisteredQueueTime(U32 name, U32 time) + +void NACLAntiSpamRegistry::initializeQueues(bool global, const U32& time, const U32& amount) { - if(name >= QUEUE_MAX || queues[name] == 0) + if (global) // If Global, initialize global queue + mGlobalQueue.reset(new NACLAntiSpamQueue(time, amount)); + else { - LL_ERRS("AntiSpam") << "CODE BUG: Attempting to set time of antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL; - return; + mQueues.reset(new std::array{{ + NACLAntiSpamQueue(time, amount), // QUEUE_CHAT + NACLAntiSpamQueue(time, amount), // QUEUE_INVENTORY + NACLAntiSpamQueue(time, amount), // QUEUE_IM + NACLAntiSpamQueue(time, amount), // QUEUE_CALLING_CARD + NACLAntiSpamQueue(time, amount), // QUEUE_SOUND + NACLAntiSpamQueue(time, amount), // QUEUE_SOUND_PRELOAD + NACLAntiSpamQueue(time, amount), // QUEUE_SCRIPT_DIALOG + NACLAntiSpamQueue(time, amount) // QUEUE_TELEPORT + }}); } - - queues[name]->setTime(time); } -//static -void NACLAntiSpamRegistry::setRegisteredQueueAmount(U32 name, U32 amount) + +constexpr const char* getQueueName(const NACLAntiSpamRegistry::Type& name) { - if(name >= QUEUE_MAX || queues[name] == 0) - { - LL_ERRS("AntiSpam") << "CODE BUG: Attempting to set amount for antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL; - return; - } - - queues[name]->setAmount(amount); + return name >= QUEUE_NAME.size() ? "Unknown" : QUEUE_NAME[name]; } -//static + void NACLAntiSpamRegistry::setAllQueueTimes(U32 time) { - globalTime=time; - for(int queue = 0; queue < QUEUE_MAX; ++queue) - if( queues[queue] ) - queues[queue]->setTime(time); + if (mGlobalQueue) mGlobalQueue->setTime(time); + else for(auto& queue : *mQueues) queue.setTime(time); } -//static + void NACLAntiSpamRegistry::setAllQueueAmounts(U32 amount) { - globalAmount=amount; - for(int queue = 0; queue < QUEUE_MAX; ++queue) + if (mGlobalQueue) mGlobalQueue->setAmount(amount); + else for (U8 queue = 0U; queue < QUEUE_MAX; ++queue) { - if(!queues[queue]) continue; - if(queue == QUEUE_SOUND || queue == QUEUE_SOUND_PRELOAD) - queues[queue]->setAmount(amount*5); + auto& q = (*mQueues)[queue]; + if (queue == QUEUE_SOUND || queue == QUEUE_SOUND_PRELOAD) + q.setAmount(amount*5); else - queues[queue]->setAmount(amount); - } -} -//static -void NACLAntiSpamRegistry::clearRegisteredQueue(U32 name) -{ - if(name >= QUEUE_MAX || queues[name] == 0) - { - LL_ERRS("AntiSpam") << "CODE BUG: Attempting to clear antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL; - return; - } - - queues[name]->clearEntries(); -} -//static -void NACLAntiSpamRegistry::purgeRegisteredQueue(U32 name) -{ - if(name >= QUEUE_MAX || queues[name] == 0) - { - LL_ERRS("AntiSpam") << "CODE BUG: Attempting to purge antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL; - return; - } - - queues[name]->purgeEntries(); -} -//static -void NACLAntiSpamRegistry::blockOnQueue(U32 name, LLUUID& source) -{ - if(bGlobalQueue) - { - NACLAntiSpamRegistry::blockGlobalEntry(source); - } - else - { - if(name >= QUEUE_MAX || queues[name] == 0) - { - LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL; - return; - } - queues[name]->blockEntry(source); + q.setAmount(amount); } } -//static -void NACLAntiSpamRegistry::blockGlobalEntry(LLUUID& source) + +void NACLAntiSpamRegistry::blockOnQueue(const Type& name, const LLUUID& source) { - it2=globalEntries.find(source.asString()); - if(it2 == globalEntries.end()) - { - globalEntries[source.asString()]=new NACLAntiSpamQueueEntry(); - } - globalEntries[source.asString()]->setBlocked(); + if (name >= QUEUE_MAX) + LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was outside of the reasonable range of queues. Queue: " << getQueueName(name) << LL_ENDL; + else (mGlobalQueue ? *mGlobalQueue : (*mQueues)[name]).block(source); } -//static -bool NACLAntiSpamRegistry::checkQueue(U32 name, LLUUID& source, U32 multiplier) + +bool NACLAntiSpamRegistry::checkQueue(const Type& name, const LLUUID& source, const LFIDBearer::Type& type, const U32& multiplier) //returns true if blocked { - if (!can_block(source)) return false; - - int result; - if(bGlobalQueue) - { - result=NACLAntiSpamRegistry::checkGlobalEntry(source,multiplier); - } - else + if (name >= QUEUE_MAX) { - if(name >= QUEUE_MAX || queues[name] == 0) - { - LL_ERRS("AntiSpam") << "CODE BUG: Attempting to check antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL; - return false; - } - result=queues[name]->checkEntry(source,multiplier); - } - if(result == 0) //Safe + LL_ERRS("AntiSpam") << "CODE BUG: Attempting to check antispam queue that was outside of the reasonable range of queues. Queue: " << getQueueName(name) << LL_ENDL; return false; - else if(result == 2) //Previously blocked - { - return true; } - else //Just blocked! + + if (!can_block(source)) return false; + + auto& queue = mGlobalQueue ? *mGlobalQueue : (*mQueues)[name]; + const auto result = queue.check(source, multiplier); + if (!result) return false; // Safe + + if (result != 2 // Not previously blocked + && gSavedSettings.getBOOL("AntiSpamNotify")) // and Just blocked! { - if(gSavedSettings.getBOOL("AntiSpamNotify")) - { - LLSD args; - args["SOURCE"] = source.asString().c_str(); - args["TYPE"] = LLTrans::getString(getQueueName(name)); - args["AMOUNT"] = boost::lexical_cast(multiplier * queues[name]->getAmount()); - args["TIME"] = boost::lexical_cast(queues[name]->getTime()); - LLNotificationsUtil::add("AntiSpamBlock", args); - } - return true; + const std::string get_slurl_for(const LLUUID& id, const LFIDBearer::Type& type); + const auto slurl = get_slurl_for(source, type); + LLSD args; + args["SOURCE"] = slurl.empty() ? source.asString() : slurl; + args["TYPE"] = LLTrans::getString(getQueueName(name)); + args["AMOUNT"] = (LLSD::Integer)(multiplier * queue.getAmount()); + args["TIME"] = (LLSD::Integer)queue.getTime(); + LLNotificationsUtil::add("AntiSpamBlock", args); } + return true; } -// Global queue stoof -//static -void NACLAntiSpamRegistry::setGlobalQueue(bool value) -{ - NACLAntiSpamRegistry::purgeAllQueues(); - bGlobalQueue=value; -} -//static -void NACLAntiSpamRegistry::setGlobalAmount(U32 amount) -{ - globalAmount=amount; -} -//static -void NACLAntiSpamRegistry::setGlobalTime(U32 time) +void NACLAntiSpamRegistry::idle() { - globalTime=time; + if (mGlobalQueue) mGlobalQueue->idle(); + else for (auto& queue : *mQueues) queue.idle(); } -//static -void NACLAntiSpamRegistry::clearAllQueues() + +void NACLAntiSpamRegistry::resetQueues() { - if(bGlobalQueue) - NACLAntiSpamRegistry::clearGlobalEntries(); - else - for(int queue = 0; queue < QUEUE_MAX; ++queue) - { - if(queues[queue]) queues[queue]->clearEntries(); - } + if (mGlobalQueue) mGlobalQueue->reset(); + else for (auto& queue : *mQueues) queue.reset(); + + LL_INFOS() << "AntiSpam Queues Reset" << LL_ENDL; } -//static + void NACLAntiSpamRegistry::purgeAllQueues() { - if(bGlobalQueue) - NACLAntiSpamRegistry::purgeGlobalEntries(); + // Note: These resets are upon the unique_ptr, not the Queue itself! + if (mGlobalQueue) + mGlobalQueue.reset(); else - for(int queue = 0; queue < QUEUE_MAX; ++queue) - { - if(queues[queue]) queues[queue]->purgeEntries(); - } - LL_INFOS() << "AntiSpam Queues Purged" << LL_ENDL; + mQueues.reset(); } -//static -int NACLAntiSpamRegistry::checkGlobalEntry(LLUUID& name, U32 multiplier) -{ - static LLCachedControl enabled(gSavedSettings,"AntiSpamEnabled",false); - if(!enabled) return 0; - it2=globalEntries.find(name.asString()); - if(it2 != globalEntries.end()) - { - if(it2->second->getBlocked()) return 2; - U32 eTime=it2->second->getEntryTime(); - U32 currentTime=time(0); - if((currentTime-eTime) <= globalTime) - { - it2->second->updateEntryAmount(); - U32 eAmount=it2->second->getEntryAmount(); - if(eAmount > (globalAmount*multiplier)) - return 1; - else - return 0; - } - else - { - it2->second->clearEntry(); - it2->second->updateEntryAmount(); - it2->second->updateEntryTime(); - return 0; - } - } - else - { - globalEntries[name.asString()]=new NACLAntiSpamQueueEntry(); - globalEntries[name.asString()]->updateEntryAmount(); - globalEntries[name.asString()]->updateEntryTime(); - return 0; - } -} -//static -void NACLAntiSpamRegistry::clearGlobalEntries() -{ - for(it2 = globalEntries.begin(); it2 != globalEntries.end(); it2++) - { - it2->second->clearEntry(); - } -} -//static -void NACLAntiSpamRegistry::purgeGlobalEntries() -{ - for(it2 = globalEntries.begin(); it2 != globalEntries.end(); it2++) - { - delete it2->second; - it2->second = 0; - } - globalEntries.clear(); + +// Handlers +// static +void NACLAntiSpamRegistry::startup() +{ + auto onAntiSpamToggle = [](const LLControlVariable*, const LLSD& value) { + if (value.asBoolean()) instance(); + else deleteSingleton(); + }; + auto control = gSavedSettings.getControl("AntiSpamEnabled"); + control->getSignal()->connect(onAntiSpamToggle); + onAntiSpamToggle(control, control->get()); } -//Handlers -//static +// static bool NACLAntiSpamRegistry::handleNaclAntiSpamGlobalQueueChanged(const LLSD& newvalue) { - setGlobalQueue(newvalue.asBoolean()); + if (instanceExists()) + { + auto& inst = instance(); + inst.purgeAllQueues(); + inst.initializeQueues(newvalue.asBoolean(), gSavedSettings.getU32("_NACL_AntiSpamTime"), gSavedSettings.getU32("_NACL_AntiSpamAmount")); + } return true; } //static bool NACLAntiSpamRegistry::handleNaclAntiSpamTimeChanged(const LLSD& newvalue) { - setAllQueueTimes(newvalue.asInteger()); + if (auto inst = getIfExists()) inst->setAllQueueTimes(newvalue.asInteger()); return true; } //static bool NACLAntiSpamRegistry::handleNaclAntiSpamAmountChanged(const LLSD& newvalue) { - setAllQueueAmounts(newvalue.asInteger()); + if (auto inst = getIfExists()) inst->setAllQueueAmounts(newvalue.asInteger()); return true; -} - +} \ No newline at end of file diff --git a/indra/newview/NACLantispam.h b/indra/newview/NACLantispam.h index e0476e267e..33c6d39d7c 100644 --- a/indra/newview/NACLantispam.h +++ b/indra/newview/NACLantispam.h @@ -13,72 +13,22 @@ * 0. You just DO WHAT THE FUCK YOU WANT TO. */ -#ifndef NACLANTISPAM_H -#define NACLANTISPAM_H -#include +#pragma once +#include +#include #include "stdtypes.h" +#include "lfidbearer.h" #include "lluuid.h" -class NACLAntiSpamQueueEntry -{ - friend class NACLAntiSpamQueue; - friend class NACLAntiSpamRegistry; -protected: - NACLAntiSpamQueueEntry(); - void clearEntry(); - U32 getEntryAmount() const; - U32 getEntryTime() const; - void updateEntryAmount(); - void updateEntryTime(); - bool getBlocked() const; - void setBlocked(); -private: - U32 entryAmount; - U32 entryTime; - bool blocked; -}; -class NACLAntiSpamQueue -{ - friend class NACLAntiSpamRegistry; -public: - U32 getAmount() const; - U32 getTime() const; -protected: - NACLAntiSpamQueue(U32 time, U32 amount); - void setAmount(U32 amount); - void setTime(U32 time); - void clearEntries(); - void purgeEntries(); - void blockEntry(LLUUID& source); - int checkEntry(LLUUID& source, U32 multiplier); -private: - std::tr1::unordered_map entries; - std::tr1::unordered_map::iterator it; - U32 queueAmount; - U32 queueTime; -}; -class NACLAntiSpamRegistry + +class NACLAntiSpamQueue; +class NACLAntiSpamRegistry final : public LLSingleton { + friend class LLSingleton; + NACLAntiSpamRegistry(); public: - NACLAntiSpamRegistry(U32 time=2, U32 amount=10); - static void registerQueues(U32 time=2, U32 amount=10); -// static void registerQueue(U32 name, U32 time, U32 amount); - static void setRegisteredQueueTime(U32 name, U32 time); - static void setRegisteredQueueAmount(U32 name,U32 amount); - static void setAllQueueTimes(U32 amount); - static void setAllQueueAmounts(U32 time); - static bool checkQueue(U32 name, LLUUID& source, U32 multiplier=1); - static bool handleNaclAntiSpamGlobalQueueChanged(const LLSD& newvalue); - static bool handleNaclAntiSpamTimeChanged(const LLSD& newvalue); - static bool handleNaclAntiSpamAmountChanged(const LLSD& newvalue); - static void clearRegisteredQueue(U32 name); - static void purgeRegisteredQueue(U32 name); - static void clearAllQueues(); - static void purgeAllQueues(); - static void setGlobalQueue(bool value); - static void setGlobalAmount(U32 amount); - static void setGlobalTime(U32 time); - static void blockOnQueue(U32 name,LLUUID& owner_id); - enum { + static void startup(); + + enum Type : U8 { QUEUE_CHAT, QUEUE_INVENTORY, QUEUE_IM, @@ -89,22 +39,19 @@ class NACLAntiSpamRegistry QUEUE_TELEPORT, QUEUE_MAX }; + bool checkQueue(const Type& name, const LLUUID& source, const LFIDBearer::Type& type = LFIDBearer::AVATAR, const U32& multiplier = 1); + void blockOnQueue(const Type& name, const LLUUID& owner_id); + void idle(); + void resetQueues(); private: - static const char* getQueueName(U32 queue_id); - static NACLAntiSpamQueue* queues[QUEUE_MAX]; - static std::tr1::unordered_map globalEntries; - static std::tr1::unordered_map::iterator it2; - static U32 globalTime; - static U32 globalAmount; - static bool bGlobalQueue; - - static int checkGlobalEntry(LLUUID& source, U32 multiplier); - static void clearGlobalEntries(); - static void purgeGlobalEntries(); - static void blockGlobalEntry(LLUUID& source); + void setAllQueueTimes(U32 amount); + void setAllQueueAmounts(U32 time); + void purgeAllQueues(); + void initializeQueues(bool global, const U32& time, const U32& amount); + static bool handleNaclAntiSpamGlobalQueueChanged(const LLSD& newvalue); + static bool handleNaclAntiSpamTimeChanged(const LLSD& newvalue); + static bool handleNaclAntiSpamAmountChanged(const LLSD& newvalue); + std::unique_ptr> mQueues; + std::unique_ptr mGlobalQueue; + std::array mConnections; }; - -extern const std::string COLLISION_SOUNDS[]; -extern const int COLLISION_SOUNDS_SIZE; - -#endif //NACLANTISPAM_H diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt new file mode 100644 index 0000000000..53ed4ba51e --- /dev/null +++ b/indra/newview/VIEWER_VERSION.txt @@ -0,0 +1 @@ +1.8.9 diff --git a/indra/newview/aixmllindengenepool.cpp b/indra/newview/aixmllindengenepool.cpp index 2e62a79558..c9d0b37aa2 100644 --- a/indra/newview/aixmllindengenepool.cpp +++ b/indra/newview/aixmllindengenepool.cpp @@ -49,12 +49,11 @@ #include "llviewerprecompiledheaders.h" #include "aixmllindengenepool.h" #include "hippogridmanager.h" +#include "llinventorymodel.h" #include "llvisualparam.h" #include "llviewerwearable.h" #include "llquantize.h" -extern void append_path_short(LLUUID const& id, std::string& path); - void AIXMLLindenGenepool::MetaData::toXML(std::ostream& os, int indentation) const { AIXMLElement tag(os, "meta", indentation); @@ -68,7 +67,7 @@ AIXMLLindenGenepool::MetaData::MetaData(AIXMLElementParser const& parser) parser.attribute(DEFAULT_LLDATE_NAME, mDate); } -AIXMLLindenGenepool::AIXMLLindenGenepool(LLFILE* fp) : AIXMLRootElement(fp, "linden_genepool") +AIXMLLindenGenepool::AIXMLLindenGenepool(const std::string& filename) : AIXMLRootElement(filename, "linden_genepool") { attribute("version", "1.0"); attribute("metaversion", "1.0"); @@ -145,7 +144,20 @@ AIArchetype::MetaData::MetaData(AIXMLElementParser const& parser) AIArchetype::MetaData::MetaData(LLViewerWearable const* wearable) : mName(wearable->getName()), mDescription(wearable->getDescription()) { - append_path_short(wearable->getItemID(), mPath); + // Path should already end on '/' if it is not empty. + const LLUUID& root_id = gInventory.getRootFolderID(); + LLUUID id = wearable->getItemID(); + for(const LLInventoryObject* obj = gInventory.getObject(id); obj && id != root_id; obj = gInventory.getCategory(id)) + { + std::string temp(mPath); + mPath = obj->getName(); + if (!temp.empty()) + { + mPath.append(1, '/'); + mPath.append(temp); + } + id = obj->getParentUUID(); + } } AIArchetype::AIArchetype(void) : mType(LLWearableType::WT_NONE) diff --git a/indra/newview/aixmllindengenepool.h b/indra/newview/aixmllindengenepool.h index c3a5a65d6e..42aa5d35c2 100644 --- a/indra/newview/aixmllindengenepool.h +++ b/indra/newview/aixmllindengenepool.h @@ -53,7 +53,7 @@ class AIXMLLindenGenepool : public AIXMLRootElement MetaData(AIXMLElementParser const& parser); }; - AIXMLLindenGenepool(LLFILE* fp); + AIXMLLindenGenepool(const std::string& filename); }; class AIVisualParamIDValuePair diff --git a/indra/newview/alfloaterregiontracker.cpp b/indra/newview/alfloaterregiontracker.cpp index c192959247..f95967367a 100644 --- a/indra/newview/alfloaterregiontracker.cpp +++ b/indra/newview/alfloaterregiontracker.cpp @@ -48,17 +48,11 @@ #include "llworldmap.h" #include "llworldmapmessage.h" -#include - const std::string TRACKER_FILE = "tracked_regions.json"; ALFloaterRegionTracker::ALFloaterRegionTracker(const LLSD&) : LLFloater(), - LLEventTimer(5.f), - mRefreshRegionListBtn(NULL), - mRemoveRegionBtn(NULL), - mOpenMapBtn(NULL), - mRegionScrollList(NULL) + LLEventTimer(5.f) { LLUICtrlFactory::instance().buildFloater(this, "floater_region_tracker.xml"); loadFromJSON(); @@ -119,10 +113,13 @@ void ALFloaterRegionTracker::refresh() } std::vector saved_selected_values; - BOOST_FOREACH(const LLScrollListItem* item, mRegionScrollList->getAllSelected()) + for(const auto* item : mRegionScrollList->getAllSelected()) { saved_selected_values.push_back(item->getValue().asString()); } + S32 saved_scroll_pos = mRegionScrollList->getScrollPos(); + auto sort_column_name = mRegionScrollList->getSortColumnName(); + auto sort_asending = mRegionScrollList->getSortAscending(); mRegionScrollList->deleteAllItems(); const std::string& cur_region_name = gAgent.getRegion()->getName(); @@ -178,8 +175,11 @@ void ALFloaterRegionTracker::refresh() mRegionScrollList->addRow(row); } } + + mRegionScrollList->sortByColumn(sort_column_name, sort_asending); if (!saved_selected_values.empty()) mRegionScrollList->selectMultiple(saved_selected_values); + mRegionScrollList->setScrollPos(saved_scroll_pos); } BOOL ALFloaterRegionTracker::tick() @@ -195,7 +195,7 @@ void ALFloaterRegionTracker::requestRegionData() for (LLSD::map_const_iterator it = mRegionMap.beginMap(); it != mRegionMap.endMap(); it++) { - const std::string& name = it->first; + const auto& name = it->first; if (LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromName(name)) { info->updateAgentCount(LLTimer::getElapsedSeconds()); @@ -210,7 +210,7 @@ void ALFloaterRegionTracker::requestRegionData() void ALFloaterRegionTracker::removeRegions() { - BOOST_FOREACH(const LLScrollListItem* item, mRegionScrollList->getAllSelected()) + for (const auto* item : mRegionScrollList->getAllSelected()) { mRegionMap.erase(item->getValue().asString()); } diff --git a/indra/newview/alfloaterregiontracker.h b/indra/newview/alfloaterregiontracker.h index bf7db79a1c..230973f6aa 100644 --- a/indra/newview/alfloaterregiontracker.h +++ b/indra/newview/alfloaterregiontracker.h @@ -41,11 +41,11 @@ class ALFloaterRegionTracker : public LLFloater, public LLEventTimer ALFloaterRegionTracker(const LLSD& key); virtual ~ALFloaterRegionTracker(); public: - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(/*const LLSD& key*/); - /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ void refresh(); - /*virtual*/ BOOL tick(); + BOOL postBuild() override; + void onOpen(/*const LLSD& key*/) override; + void onClose(bool app_quitting) override; + void refresh() override; + BOOL tick() override; using LLFloaterSingleton::getInstance; private: @@ -62,8 +62,8 @@ class ALFloaterRegionTracker : public LLFloater, public LLEventTimer private: LLSD mRegionMap; - LLButton* mRefreshRegionListBtn; - LLButton* mRemoveRegionBtn; - LLButton* mOpenMapBtn; - LLScrollListCtrl* mRegionScrollList; + LLButton* mRefreshRegionListBtn = nullptr; + LLButton* mRemoveRegionBtn = nullptr; + LLButton* mOpenMapBtn = nullptr; + LLScrollListCtrl* mRegionScrollList = nullptr; }; diff --git a/indra/newview/aoremotectrl.cpp b/indra/newview/aoremotectrl.cpp index d9b782fca3..5f57bcd206 100644 --- a/indra/newview/aoremotectrl.cpp +++ b/indra/newview/aoremotectrl.cpp @@ -33,7 +33,6 @@ #include "aoremotectrl.h" #include "floaterao.h" -#include "llbutton.h" #include "lloverlaybar.h" #include "lluictrlfactory.h" #include "llviewercontrol.h" @@ -46,80 +45,23 @@ AORemoteCtrl::AORemoteCtrl() setFocusRoot(TRUE); } -AORemoteCtrl::~AORemoteCtrl() -{ -} - -void AORemoteCtrl::draw() -{ - LLButton* expand_button = getChild("popup_btn"); - if (expand_button) - { - if (expand_button->getToggleState()) - { - expand_button->setImageOverlay("arrow_down.tga"); - } - else - { - expand_button->setImageOverlay("arrow_up.tga"); - } - } - - LLPanel::draw(); -} - void AORemoteCtrl::build() { - if (gSavedSettings.getBOOL("ShowAOSitPopup")) - { - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_ao_remote_expanded.xml"); - } - else - { - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_ao_remote.xml"); - } + LLUICtrlFactory::getInstance()->buildPanel(this, gSavedSettings.getBOOL("ShowAOSitPopup") ? "panel_ao_remote_expanded.xml" : "panel_ao_remote.xml"); } BOOL AORemoteCtrl::postBuild() { - - childSetAction("ao_btn", onClickToggleAO, this); - if (gSavedSettings.getBOOL("ShowAOSitPopup")) - { - childSetAction("ao_sit_btn", onClickToggleAOSit, this); - //childSetAction("ao_show_btn", onClickShowAO, this); - } - childSetAction("popup_btn", onClickPopupBtn, this); + /*if (LLUICtrl* ctrl = findChild("ao_show_btn")) + ctrl->setCommitCallback(boost::bind(&LLFloaterAO::showInstance, LLSD()));*/ + getChild("popup_btn")->setCommitCallback(boost::bind(&AORemoteCtrl::onClickPopupBtn, this)); return TRUE; } -// static -void AORemoteCtrl::onClickToggleAO(void* data) -{ - BOOL ao_enable = gSavedSettings.getBOOL("AOEnabled"); - gSavedSettings.setBOOL("AOEnabled", !ao_enable); -} - -//static -void AORemoteCtrl::onClickToggleAOSit(void* data) +void AORemoteCtrl::onClickPopupBtn() { - BOOL sit_enable = gSavedSettings.getBOOL("AOSitsEnabled"); - gSavedSettings.setBOOL("AOSitsEnabled", !sit_enable); -} - -//static -void AORemoteCtrl::onClickShowAO(void* data) -{ - LLFloaterAO::show(NULL); -} - -//static -void AORemoteCtrl::onClickPopupBtn(void* data) -{ - AORemoteCtrl* remotep = (AORemoteCtrl*)data; - - remotep->deleteAllChildren(); - remotep->build(); + deleteAllChildren(); + build(); gOverlayBar->layoutButtons(); } diff --git a/indra/newview/aoremotectrl.h b/indra/newview/aoremotectrl.h index ca74e0de66..417f7b3292 100644 --- a/indra/newview/aoremotectrl.h +++ b/indra/newview/aoremotectrl.h @@ -37,18 +37,12 @@ class AORemoteCtrl : public LLPanel { public: AORemoteCtrl(); - virtual ~AORemoteCtrl(); - /*virtual*/ BOOL postBuild(); - /*virtual*/ void draw(); + BOOL postBuild() override; private: void build(); - - static void onClickToggleAO(void* data); - static void onClickToggleAOSit(void* data); - static void onClickShowAO(void* data); - static void onClickPopupBtn(void* data); + void onClickPopupBtn(); }; #endif // AOREMOTECTRL_H diff --git a/indra/newview/aostate.h b/indra/newview/aostate.h new file mode 100644 index 0000000000..8f8fbc6350 --- /dev/null +++ b/indra/newview/aostate.h @@ -0,0 +1,37 @@ +#pragma once + +enum AOState : U8 +{ + STATE_AGENT_IDLE, + STATE_AGENT_WALK, + STATE_AGENT_RUN, + + STATE_AGENT_PRE_JUMP, + STATE_AGENT_JUMP, + STATE_AGENT_TURNLEFT, + STATE_AGENT_TURNRIGHT, + + STATE_AGENT_SIT, + STATE_AGENT_SIT_GROUND, + + STATE_AGENT_HOVER, + STATE_AGENT_HOVER_DOWN, + STATE_AGENT_HOVER_UP, + + STATE_AGENT_CROUCH, + STATE_AGENT_CROUCHWALK, + STATE_AGENT_FALLDOWN, + STATE_AGENT_STANDUP, + STATE_AGENT_LAND, + + STATE_AGENT_FLY, + STATE_AGENT_FLYSLOW, + + STATE_AGENT_TYPE, + + STATE_AGENT_SWIM_DOWN, + STATE_AGENT_SWIM_UP, + STATE_AGENT_SWIM, + STATE_AGENT_FLOAT, + STATE_AGENT_END +}; diff --git a/indra/newview/aosystem.cpp b/indra/newview/aosystem.cpp new file mode 100644 index 0000000000..49650acf4a --- /dev/null +++ b/indra/newview/aosystem.cpp @@ -0,0 +1,596 @@ +/** + * @file aosystem.cpp + * @brief clientside animation overrider + * by Skills Hak & Liru Færs + */ + +#include "llviewerprecompiledheaders.h" + +#include "aosystem.h" + +#include "floaterao.h" +#include "llagent.h" +#include "llagentcamera.h" +#include "llanimationstates.h" +#include "llinventoryfunctions.h" +#include "llinventorypanel.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llmemorystream.h" +#include "llnotecard.h" +#include "llstartup.h" +#include "llvoavatarself.h" +#include "llviewerregion.h" +#include "roles_constants.h" + +#include + +// Uncomment and use instead if we ever add the chatbar as a command line - MC +void cmdline_printchat(const std::string& message); + +namespace +{ + bool sSwimming = false; + bool enable_swim() + { + static const LLCachedControl swim(gSavedSettings, "AOSwimEnabled", false); + return swim; + } + bool is_underwater() { return enable_swim() && gAgentAvatarp && gAgentAvatarp->mBelowWater; } +} + +// ------------------------------------------------------- +void AOSystem::AOStandTimer::reset() +{ + mPeriod = gSavedSettings.getF32("AOStandInterval"); + mEventTimer.reset(); +// LL_INFOS() << "reset" << LL_ENDL; +} + +// ------------------------------------------------------- +class AOInvTimer final : public LLEventTimer, public LLSingleton +{ + friend class LLSingleton; + friend class AOSystem; + AOInvTimer() : LLEventTimer(1.0f) {} + ~AOInvTimer() {} + static void createIfNeeded() + { + if (needed()) LLSingleton::getInstance(); + else AOSystem::getInstance(); + } +public: + static bool needed() + { + return LLStartUp::getStartupState() < STATE_INVENTORY_SEND // Haven't done inventory transfer yet + || !LLInventoryModelBackgroundFetch::instance().isEverythingFetched(); // Everything hasn't been fetched yet + } + BOOL tick() override + { + if (!gSavedSettings.getBOOL("AOEnabled")) return true; // If disabled on a tick, we don't care anymore + if (!needed()) + { +// cmdline_printchat("Inventory fetched, loading AO."); + AOSystem::getInstance(); // Initializes everything + return true; + } + return false; + } +}; + +class ObjectNameMatches final : public LLInventoryCollectFunctor +{ +public: + ObjectNameMatches(const std::string& name, const LLUUID& folder) : mName(name), mFolder(folder) {} + virtual ~ObjectNameMatches() {} + bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override + { + return item && item->getParentUUID() == mFolder && item->getName() == mName; + } +private: + const std::string& mName; + const LLUUID& mFolder; +}; + +static LLUUID invfolderid; +LLUUID getAssetIDByName(const std::string& name) +{ + if (name.empty()) return LLUUID::null; + + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + ObjectNameMatches matches(name, invfolderid); + gInventory.collectDescendentsIf(LLUUID::null, cats, items, false, matches, true); + + return items.empty() ? LLUUID(name) : items[0]->getAssetUUID(); +}; + +void AOSystem::start() +{ + llassert(!instanceExists() && !AOInvTimer::instanceExists()); // This should only be run once! + + auto control(gSavedSettings.getControl("AOEnabled")); + if (control->get()) AOInvTimer::createIfNeeded(); // Start the clock + + control->getSignal()->connect([](LLControlVariable*, const LLSD& enabled) { + if (enabled.asBoolean()) AOInvTimer::createIfNeeded(); // Start the clock + else deleteSingleton(); + }); +} + +// STUFF ------------------------------------------------------- + +AOSystem::overrides::overrides(const char* setting_name) + : setting(setting_name ? gSavedPerAccountSettings.getControl("AODefault" + std::string(setting_name)) : nullptr) + , playing(false) +{ +} + +bool AOSystem::overrides::play_condition() const +{ + // Stop stand first then play + instance().stopCurrentStand(); + return false; +} + +void AOSystem::overrides::play(bool start) +{ + if (playing == start) return; +// LL_INFOS() << "st" << (start ? "art" : "op") << " override: " << aop->getOverride() << LL_ENDL; + // We can always stop, but starting is particular + if (start) + { + if (play_condition()) + return; + } + else if (playing && !isLowPriority()) // Stands were turned off if this isn't a low priority overrides + { + if (!isAgentAvatarValid() && !gAgentAvatarp->isSitting() && !gAgent.getFlying()) // check if sitting or hovering + instance().stand().play(); + } + playing = start; + gAgent.sendAnimationRequest(ao_id, start ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); +} + +struct override_low_priority final : public AOSystem::overrides +{ + override_low_priority(const LLUUID& id, const char* setting_name = nullptr) + : overrides(setting_name), orig_id(id) {} + bool overrideAnim(bool swimming, const LLUUID& anim) const override { return orig_id == anim; } + bool play_condition() const override { return false; } + bool isLowPriority() const override { return true; } +private: + const LLUUID orig_id; +}; + +struct override_single final : public AOSystem::overrides +{ + override_single(const LLUUID& id, const char* setting_name = nullptr, U8 swim = 2) + : overrides(setting_name), orig_id(id), swim(swim) {} + bool overrideAnim(bool swimming, const LLUUID& anim) const override { return (swim == 2 || !!swim == swimming) && orig_id == anim; } +private: + const LLUUID orig_id; + const U8 swim; // 2 = irrelevant, 0 = flying, 1 = swimming +}; + +struct override_sit final : public AOSystem::overrides +{ + override_sit(const uuid_set_t& ids, const char* setting_name = nullptr) + : overrides(setting_name) + , orig_ids(ids) + {} + bool overrideAnim(bool swimming, const LLUUID& anim) const override { return orig_ids.find(anim) != orig_ids.end(); } + bool play_condition() const override + { + overrides::play_condition(); + return !gSavedSettings.getBOOL("AOSitsEnabled"); + } +private: + const uuid_set_t orig_ids; +}; + +bool AOSystem::override_stand::play_condition() const +{ + // Do not call base, stands do their own thing + // stands have lowest priority + return (!isAgentAvatarValid() || gAgentAvatarp->isSitting()) + && (gAgentCamera.cameraMouselook() && gSavedSettings.getBOOL("AONoStandsInMouselook")); +} + +bool AOSystem::override_stand::overrideAnim(bool swimming, const LLUUID& anim) const +{ + return anim == ANIM_AGENT_STAND; +} + +AOSystem::AOSystem() +: stand_iterator(0) +, mAOOverrides({}) +{ +// TODO: When we move to C++20 and when GCC and MSVC support it (at the time of writing, neither fully do), use __VA_OPT__ here instead. +#define ANY_OVERRIDE(which, state, ...) mAOOverrides[STATE_AGENT_##state] = new which(ANIM_AGENT_##state, ##__VA_ARGS__) +#define BASIC_OVERRIDE(state, ...) ANY_OVERRIDE(override_single, state, ##__VA_ARGS__) + mAOOverrides[STATE_AGENT_IDLE] = new override_stand(); + BASIC_OVERRIDE(WALK, "Walk"); + BASIC_OVERRIDE(RUN, "Run"); + BASIC_OVERRIDE(PRE_JUMP, "PreJump"); + BASIC_OVERRIDE(JUMP, "Jump"); + BASIC_OVERRIDE(TURNLEFT); + BASIC_OVERRIDE(TURNRIGHT); + +#define SIT_OVERRIDE(control, state, ...) mAOOverrides[STATE_AGENT_##state] = new override_sit(uuid_set_t{ANIM_AGENT_##state, __VA_ARGS__}, control) + SIT_OVERRIDE("Sit", SIT, ANIM_AGENT_SIT_FEMALE, ANIM_AGENT_SIT_GENERIC); + SIT_OVERRIDE("GroundSit", SIT_GROUND, ANIM_AGENT_SIT_GROUND_CONSTRAINED); +#undef SIT_OVERRIDE + + BASIC_OVERRIDE(HOVER, "Hover", false); + BASIC_OVERRIDE(HOVER_DOWN, "FlyDown", false); + BASIC_OVERRIDE(HOVER_UP, "FlyUp", false); + + BASIC_OVERRIDE(CROUCH, "Crouch"); + BASIC_OVERRIDE(CROUCHWALK, "CrouchWalk"); + BASIC_OVERRIDE(FALLDOWN, "Fall"); + BASIC_OVERRIDE(STANDUP, "StandUp"); + BASIC_OVERRIDE(LAND, "Land"); + + BASIC_OVERRIDE(FLY, "Fly", false); + BASIC_OVERRIDE(FLYSLOW, "FlySlow", false); + + ANY_OVERRIDE(override_low_priority, TYPE, "Typing"); + + mAOOverrides[STATE_AGENT_SWIM_DOWN] = new override_single(ANIM_AGENT_HOVER_DOWN, "SwimDown", true); + mAOOverrides[STATE_AGENT_SWIM_UP] = new override_single(ANIM_AGENT_HOVER_UP, "SwimUp", true); + mAOOverrides[STATE_AGENT_SWIM] = new override_single(ANIM_AGENT_FLY, "Swim", true); + mAOOverrides[STATE_AGENT_FLOAT] = new override_single(ANIM_AGENT_HOVER, "Float", true); +#undef BASIC_OVERRIDE +#undef ANY_OVERRIDE + + auto swim_forced = gSavedSettings.getControl("AOSwimForced"); + sSwimming = swim_forced->get().asBoolean() || is_underwater(); + mConnections[0] = gSavedSettings.getControl("AOSitsEnabled")->getSignal()->connect([this](LLControlVariable*, const LLSD& val) { + if (!isAgentAvatarValid() || !gAgentAvatarp->isSitting()) return; + gAgent.sendAnimationRequest(mAOOverrides[gAgentAvatarp->getParent() ? STATE_AGENT_SIT : STATE_AGENT_SIT_GROUND]->ao_id, val.asBoolean() ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); + }); + const auto& swim_cb = [=](LLControlVariable*, const LLSD&){ toggleSwim(swim_forced->get().asBoolean() || is_underwater()); }; + auto swim_enabled = gSavedSettings.getControl("AOSwimEnabled"); + mConnections[1] = swim_enabled->getSignal()->connect(swim_cb); + mConnections[2] = swim_forced->getSignal()->connect([swim_cb, swim_enabled](LLControlVariable*, const LLSD& val) { + if (val.asBoolean()) // Automatically enable Swim AO. + swim_enabled->set(true); + swim_cb(nullptr, LLSD()); + }); +} + +AOSystem::~AOSystem() +{ + stopAllOverrides(); + for (auto& ao : mAOOverrides) + { + if (ao) + { + delete ao; + ao = nullptr; + } + } +} + +void AOSystem::requestConfigNotecard(bool reload) +{ + LLUUID configncitem = (LLUUID)gSavedPerAccountSettings.getString("AOConfigNotecardID"); + if (configncitem.notNull()) + { + bool success = false; + if (const LLInventoryItem* item = gInventory.getItem(configncitem)) + { + if (gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE) || gAgent.isGodlike()) + { + if (item->getAssetUUID().notNull()) + { + invfolderid = item->getParentUUID(); + gAssetStorage->getInvItemAsset(LLHost::invalid, + gAgentID, + gAgentSessionID, + item->getPermissions().getOwner(), + LLUUID::null, + item->getUUID(), + item->getAssetUUID(), + item->getType(), + [reload](LLVFS* vfs, const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status) + { + parseNotecard(vfs, asset_uuid, type, status, reload); + }, + nullptr, + true); + success = true; + } + } + } + if (!success) cmdline_printchat("Could not read the specified Config Notecard"); + } +} + +void AOSystem::initSingleton() +{ + mAOStands.clear(); + requestConfigNotecard(); +} + +void AOSystem::typing(bool start) +{ + uuid_vec_t anims; + // If we're stopping, stop regardless, just in case the setting was toggled during (e.g.: keyboard shortcut) + if (!start || gSavedSettings.getBOOL("PlayTypingAnim")) // Linden typing + anims.push_back(ANIM_AGENT_TYPE); + if (const auto& ao = getIfExists()) // Typing override + anims.push_back(ao->mAOOverrides[STATE_AGENT_TYPE]->getOverride()); + if (anims.empty()) return; + gAgent.sendAnimationRequests(anims, start ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); +} + +AOState GetStateFromToken(const std::string& strtoken) +{ + if (strtoken == "[ Sitting On Ground ]") return STATE_AGENT_SIT_GROUND; + if (strtoken == "[ Sitting ]") return STATE_AGENT_SIT; + if (strtoken == "[ Crouching ]") return STATE_AGENT_CROUCH; + if (strtoken == "[ Crouch Walking ]") return STATE_AGENT_CROUCHWALK; + if (strtoken == "[ Standing Up ]") return STATE_AGENT_STANDUP; + if (strtoken == "[ Falling ]") return STATE_AGENT_FALLDOWN; + if (strtoken == "[ Flying Down ]") return STATE_AGENT_HOVER_DOWN; + if (strtoken == "[ Flying Up ]") return STATE_AGENT_HOVER_UP; + if (strtoken == "[ Flying Slow ]") return STATE_AGENT_FLYSLOW; + if (strtoken == "[ Flying ]") return STATE_AGENT_FLY; + if (strtoken == "[ Hovering ]") return STATE_AGENT_HOVER; + if (strtoken == "[ Jumping ]") return STATE_AGENT_JUMP; + if (strtoken == "[ Pre Jumping ]") return STATE_AGENT_PRE_JUMP; + if (strtoken == "[ Running ]") return STATE_AGENT_RUN; + if (strtoken == "[ Turning Right ]") return STATE_AGENT_TURNRIGHT; + if (strtoken == "[ Turning Left ]") return STATE_AGENT_TURNLEFT; + if (strtoken == "[ Walking ]") return STATE_AGENT_WALK; + if (strtoken == "[ Landing ]") return STATE_AGENT_LAND; + if (strtoken == "[ Standing ]") return STATE_AGENT_IDLE; + if (strtoken == "[ Swimming Down ]") return STATE_AGENT_SWIM_DOWN; + if (strtoken == "[ Swimming Up ]") return STATE_AGENT_SWIM_UP; + if (strtoken == "[ Swimming Forward ]") return STATE_AGENT_SWIM; + if (strtoken == "[ Floating ]") return STATE_AGENT_FLOAT; + if (strtoken == "[ Typing ]") return STATE_AGENT_TYPE; + return STATE_AGENT_END; +} + +void AOSystem::updateStand() +{ + auto& stand_ao = stand(); + bool is_standing = stand_ao.playing; + if (is_standing) stand_ao.play(false); // Stop stand first + stand_ao.update(mAOStands, stand_iterator); // Now update stand + if (is_standing && !mAOStands.empty()) // Play stand if needed + stand_ao.play(); +} + +int AOSystem::cycleStand(bool next, bool random) +{ + if (mAOStands.empty()) return -1; + const int size = mAOStands.size(); + if (size > 1) + { + if (random && gSavedSettings.getBOOL("AOStandRandomize")) + for (auto previous = stand_iterator; previous == stand_iterator; + stand_iterator = ll_rand(size)); + else + { + stand_iterator += next ? 1 : -1; + // Wrap around + if (stand_iterator == size) stand_iterator = 0; + else if (stand_iterator == -1) stand_iterator = size - 1; + } + if (auto floater = LLFloaterAO::findInstance()) + if (auto combo = floater->getComboFromState(STATE_AGENT_IDLE)) + combo->selectNthItem(stand_iterator); +// LL_INFOS() << "changing stand to " << mAOStands[stand_iterator].anim_name << LL_ENDL; + } + updateStand(); + return stand_iterator; +} + +void AOSystem::toggleSwim(bool underwater) +{ + sSwimming = underwater && enable_swim(); + + if (isStanding()) return; // Don't bother if we're just standing (Who pushed us?!) + + typedef std::array flies_t; + // Stop all of the previous states +#define AOO(state) mAOOverrides[STATE_AGENT_##state] + const flies_t swims = { AOO(FLOAT), AOO(SWIM), AOO(SWIM_UP), AOO(SWIM_DOWN) }; + const flies_t flies = { AOO(HOVER), AOO(FLY), AOO(HOVER_UP), AOO(HOVER_DOWN) }; +#undef AOO + const auto& oldaos = sSwimming ? flies : swims; + const auto& newaos = sSwimming ? swims : flies; + + for (auto i = 0; i < oldaos.size(); ++i) + { + auto& old = *oldaos[i]; + if (old.playing) + { + old.play(false); + newaos[i]->play(); + } + } +} + +void AOSystem::doMotion(const LLUUID& id, bool start) +{ + if (id.isNull() || !gAgentAvatarp) return; + + overrides* aop = nullptr; + AOState state = STATE_AGENT_IDLE; + for (U8 i = STATE_AGENT_IDLE; !aop && i < STATE_AGENT_END; ++i) + { + auto& ao = mAOOverrides[i]; + if (ao && ao->overrideAnim(sSwimming, id)) + { + aop = ao; + state = (AOState)i; + } + } + if (aop) + { +// LL_INFOS() << "st" << (start ? "art" : "op") << " anim " << id << " state " << state << LL_ENDL; + aop->play(start); + } +} + +void AOSystem::stopAllOverrides() const +{ + if (!isAgentAvatarValid()) return; + uuid_vec_t anims; + for (auto& ao : mAOOverrides) + { + if (ao->playing) + { + anims.push_back(ao->getOverride()); + ao->playing = false; + } + } + for (const auto& stand : mAOStands) + anims.push_back(stand.ao_id); + gAgent.sendAnimationRequests(anims, ANIM_REQUEST_STOP); +} + +void AOSystem::parseNotecard(LLVFS *vfs, const LLUUID& asset_uuid, LLAssetType::EType type, S32 status, bool reload) +{ + if (status == LL_ERR_NOERR) + { + if (type == LLAssetType::AT_NOTECARD) + { + AOSystem* self = getIfExists(); + S32 size = vfs->getSize(asset_uuid, LLAssetType::AT_NOTECARD); + U8* buffer = new U8[size]; + vfs->getData(asset_uuid, type, buffer, 0, size); + LLMemoryStream str(buffer, size); + LLNotecard nc; + if (nc.importStream(str)) + { + LL_INFOS() << "ao nc decode success" << LL_ENDL; + + if (self && reload) self->stopAllOverrides(); + + auto floater = LLFloaterAO::findInstance(); + if (floater) + for (auto& combo : floater->mCombos) + { + if (combo) + { + combo->clear(); + combo->removeall(); + } + } + + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("\n"); + tokenizer tokline(nc.getText(), sep); + + for (const auto& strline : tokline) + { +// LL_INFOS() << "uncommented line: " << strline << LL_ENDL; + boost::regex type("^(\\s*)(\\[ )(.*)( \\])"); + boost::smatch what; + if (boost::regex_search(strline, what, type)) + { + const std::string strtoken(what[0]); + const AOState state = GetStateFromToken(strtoken); + if (state == STATE_AGENT_END) + { + LL_WARNS() << "Invalid token: " << strtoken << LL_ENDL; + continue; + } +// LL_INFOS() << "type: " << strtoken << LL_ENDL; + LLComboBox* combo = floater ? floater->getComboFromState(state) : nullptr; + auto aop = (reload && self) ? self->mAOOverrides[state] : nullptr; +// LL_INFOS() << "anims in type: " << boost::regex_replace(strline, type, "") << LL_ENDL; + + boost::char_separator sep("|,"); + std::string stranimnames(boost::regex_replace(strline, type, "")); + tokenizer tokanimnames(stranimnames, sep); + for (const auto& stranim : tokanimnames) + { + if (stranim.empty()) continue; + const auto& animid(getAssetIDByName(stranim)); + +// LL_INFOS() << invfolderid.asString().c_str() << LL_ENDL; +// LL_INFOS() << "anim: " << stranim.c_str() << " assetid: " << animid << LL_ENDL; + if (animid.notNull()) + { + if (aop) // If we're reloading + { + if (state == STATE_AGENT_IDLE) + self->mAOStands.push_back({ animid, stranim }); + else + aop->ao_id = animid; + } + + if (combo && !combo->selectByValue(stranim)) // check if exists + combo->add(stranim, ADD_BOTTOM, true); + } + else cmdline_printchat("Warning: animation '" + stranim + "' could not be found (Section: " + strtoken + ")."); + } + } + } + LL_INFOS() << "ao nc read sucess" << LL_ENDL; + + if (self) + { + if (auto combo = floater ? floater->getComboFromState(STATE_AGENT_IDLE) : nullptr) + combo->selectNthItem(self->stand_iterator); + + for (U8 i = STATE_AGENT_IDLE+1; i < STATE_AGENT_END; ++i) + { + auto& aop = self->mAOOverrides[i]; + if (!aop) continue; + auto& ao = *aop; + const auto& setting = ao.setting; + if (!setting && ao.ao_id.isNull()) continue; + const auto& defaultanim = setting ? setting->get().asStringRef() : ao.ao_id.asString(); + if (defaultanim.empty()) continue; + const LLUUID& ao_id = getAssetIDByName(defaultanim); + if (reload && ao_id.notNull()) ao.ao_id = ao_id; + if (LLComboBox* combo = floater ? floater->getComboFromState(i) : nullptr) + if (!combo->selectByValue(defaultanim)) + combo->add(defaultanim, ADD_BOTTOM, true); + } + + if (reload && isAgentAvatarValid()) + { + // Fix the stand iter, container size may have changed + auto& iter = self->stand_iterator; + const auto& stands = self->mAOStands; + iter = llmin(iter, (int)stands.size()-1); + // Update the current stand + self->stand().update(stands, iter); + self->mAOStandTimer.reset(); + + const auto& anims = gAgentAvatarp->mPlayingAnimations; + bool playing = false; + for (auto& aop : self->mAOOverrides) + { + for (const auto& anim : anims) + { + if (aop && aop->overrideAnim(sSwimming, anim.first)) + { + if (!aop->isLowPriority()) playing = true; + aop->play(); + break; + } + } + } + + if (!playing) self->stand().play(); // Play stand if nothing was being played, this sometimes happens + + // Toggle typing AO the moment we toggle AO + typing(gAgent.getRenderState() & AGENT_STATE_TYPING); + } + } + } + else LL_INFOS() << "ao nc decode error" << LL_ENDL; + delete[] buffer; + } + } + else LL_INFOS() << "ao nc read error" << LL_ENDL; +} diff --git a/indra/newview/aosystem.h b/indra/newview/aosystem.h new file mode 100644 index 0000000000..8dbfc6c78a --- /dev/null +++ b/indra/newview/aosystem.h @@ -0,0 +1,101 @@ +#pragma once + +#include "aostate.h" +#include "llcontrol.h" +#include "lleventtimer.h" + +class AOSystem final : public LLSingleton +{ + friend class LLSingleton; + friend class AOInvTimer; + friend class LLFloaterAO; + AOSystem(); + ~AOSystem(); +public: + static void start(); // Runs the necessary actions to get the AOSystem ready, then initializes it. + void initSingleton() override; + + static void typing(bool start); + + int stand_iterator; + bool isStanding() const { return stand().playing; } + void updateStand(); + int cycleStand(bool next = true, bool random = true); + void toggleSwim(bool underwater); + + void doMotion(const LLUUID& id, bool start); + void startMotion(const LLUUID& id) { doMotion(id, true); } + void stopMotion(const LLUUID& id) { doMotion(id, false); } + void stopCurrentStand() const { stand().play(false); } + void stopAllOverrides() const; + +protected: + struct struct_stands + { + LLUUID ao_id; + std::string anim_name; + }; + typedef std::vector stands_vec; + stands_vec mAOStands; + + struct overrides + { + virtual bool overrideAnim(bool swimming, const LLUUID& anim) const = 0; + virtual const LLUUID& getOverride() const { return ao_id; } + virtual bool play_condition() const; // True if prevented from playing + virtual bool isLowPriority() const { return false; } + void play(bool start = true); + LLUUID ao_id; + LLPointer setting; + bool playing; + virtual ~overrides() {} + protected: + overrides(const char* setting_name); + }; + friend struct override_low_priority; + friend struct override_single; + friend struct override_sit; + struct override_stand final : public overrides + { + override_stand() : overrides(nullptr) {} + bool overrideAnim(bool swimming, const LLUUID& anim) const override; + bool play_condition() const override; + bool isLowPriority() const override { return true; } + void update(const stands_vec& stands, const int& iter) + { + if (stands.empty()) ao_id.setNull(); + else ao_id = stands[iter].ao_id; + } + }; + std::array mAOOverrides; + + override_stand& stand() const { return static_cast(*mAOOverrides[STATE_AGENT_IDLE]); } + +private: + std::array mConnections; + + + class AOStandTimer final : public LLEventTimer + { + friend class AOSystem; + public: + AOStandTimer() : LLEventTimer(F32_MAX) {} + ~AOStandTimer() + { +// LL_INFOS() << "dead" << LL_ENDL; + } + BOOL tick() override + { +// LL_INFOS() << "tick" << LL_ENDL; + if (auto ao = AOSystem::getIfExists()) + ao->cycleStand(); + return false; + } + void reset(); + }; + AOStandTimer mAOStandTimer; + + static void requestConfigNotecard(bool reload = true); + static void parseNotecard(LLVFS* vfs, const LLUUID& asset_uuid, LLAssetType::EType type, S32 status, bool reload); +}; + diff --git a/indra/newview/app_settings/CA.pem b/indra/newview/app_settings/CA.pem deleted file mode 100644 index 8c1b9a1f37..0000000000 --- a/indra/newview/app_settings/CA.pem +++ /dev/null @@ -1,5573 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT -MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0 -aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw -WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE -AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m -OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu -T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c -JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR -Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz -PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm -aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM -TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g -LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO -BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv -dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB -AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL -NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W -b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul -F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC -ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w -ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk -aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 -YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg -c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 -d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG -CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF -wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS -Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst -0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc -pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl -CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF -P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK -1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm -KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE -JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ -8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm -fyWl8kgAwKQB2j8= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy -MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA -vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G -CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA -WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo -oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ -h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 -f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN -B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy -vUxFnmG6v4SBkgPR0ml8xQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy -c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE -BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 -IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV -VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 -cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT -QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh -F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v -c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w -mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd -VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX -teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ -f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe -Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ -nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB -/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY -MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG -9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc -aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX -IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn -ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z -uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN -Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja -QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW -koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 -ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt -DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm -bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt -YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu -Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT -AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa -MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp -b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG -cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh -d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY -DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E -rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq -uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN -BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP -MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa -/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei -gQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn -MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL -ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg -b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa -MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB -ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw -IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B -AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb -unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d -BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq -7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 -0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX -roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG -A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j -aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p -26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA -BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud -EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN -BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz -aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB -AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd -p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi -1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc -XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 -eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu -tGWaIZDgqtCYvDi1czyL+Nw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID/TCCA2agAwIBAgIEP4/gkTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQgLSBD -QSBLbGFzYSAxMB4XDTAzMTAxNzEyMjkwMloXDTExMDkyMzExMTgxN1owdjELMAkG -A1UEBhMCUEwxHzAdBgNVBAoTFlRQIEludGVybmV0IFNwLiB6IG8uby4xJDAiBgNV -BAsTG0NlbnRydW0gQ2VydHlmaWthY2ppIFNpZ25ldDEgMB4GA1UEAxMXQ0MgU2ln -bmV0IC0gVFNBIEtsYXNhIDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOJY -rISEtSsduHajROh5/n7NGrkpYTT9NEaPe9+ucuQ37KxIbfJwXJjgUc1dw4wCkcQ1 -2FJarD1X6mSQ4cfN/60vLfKI5ZD4nhJTMKlAj1pX9ScQ/MuyvKStCbn5WTkjPhjR -AM0tdwXSnzuTEunfw0Oup559y3Iqxg1cExflB6cfAgMBAAGjggGXMIIBkzBBBgNV -HR8EOjA4MDagNKAyhjBodHRwOi8vd3d3LnNpZ25ldC5wbC9yZXBvenl0b3JpdW0v -Y3JsL2tsYXNhMS5jcmwwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsG -AQUFBwMIMIHaBgNVHSAEgdIwgc8wgcwGDSsGAQQBvj8CZAoRAgEwgbowbwYIKwYB -BQUHAgIwYxphQ2VydHlmaWthdCB3eXN0YXdpb255IHpnb2RuaWUgeiBkb2t1bWVu -dGVtICJQb2xpdHlrYSBDZXJ0eWZpa2FjamkgQ0MgU2lnbmV0IC0gWm5ha293YW5p -ZSBjemFzZW0iLjBHBggrBgEFBQcCARY7aHR0cDovL3d3dy5zaWduZXQucGwvcmVw -b3p5dG9yaXVtL2Rva3VtZW50eS9wY190c2ExXzJfMS5wZGYwHwYDVR0jBBgwFoAU -w4Me1Vl3VPtN+1dH+cQjXNHnieMwHQYDVR0OBBYEFJdDwEqtcavOYd9u9tej53vW -XwNBMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADgYEAnpiQkqLCJQYXUrqMHUEz -+z3rOqS0XzSFnVVLhkVssvXc8S3FkJIiQTUrkScjI4CToCzujj3EyfNxH6yiLlMb -skF8I31JxIeBvueqV+s+o76CZm3ycu9hb0I4lswuxoT+q5ZzPR8Irrb51rZXlolR -+7KtwMg4sFDJZ8RNgOf7tbA= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDlDCCAnygAwIBAgIQWAsFbFMk27JQVxhf+eWmUDANBgkqhkiG9w0BAQUFADAn -MQswCQYDVQQGEwJCRTEYMBYGA1UEAxMPQmVsZ2l1bSBSb290IENBMB4XDTAzMDEy -NjIzMDAwMFoXDTE0MDEyNjIzMDAwMFowJzELMAkGA1UEBhMCQkUxGDAWBgNVBAMT -D0JlbGdpdW0gUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AMihcekcRkJ5eHFvna6pqKsot03HIOswkVp19eLSz8hMFJhCWK3HEcVAQGpa+XQS -J4fpnOVxTiIs0RIYqjBeoiG52bv/9nTrMQHnO35YD5EWTXaJqAFPrSJmcPpLHZXB -MFjqvNll2Jq0iOtJRlLf0lMVdssUXRlJsW9q09P9vMIt7EU/CT9YvvzU7wCMgTVy -v/cY6pZifSsofxVsY9LKyn0FrMhtB20yvmi4BUCuVJhWPmbxMOjvxKuTXgfeMo8S -dKpbNCNUwOpszv42kqgJF+qhLc9s44Qd3ocuMws8dOIhUDiVLlzg5cYx+dtA+mqh -pIqTm6chBocdJ9PEoclMsG8CAwEAAaOBuzCBuDAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zBCBgNVHSAEOzA5MDcGBWA4AQEBMC4wLAYIKwYBBQUHAgEW -IGh0dHA6Ly9yZXBvc2l0b3J5LmVpZC5iZWxnaXVtLmJlMB0GA1UdDgQWBBQQ8AxW -m2HqVzq2NZdtn925FI7b5jARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAU -EPAMVpth6lc6tjWXbZ/duRSO2+YwDQYJKoZIhvcNAQEFBQADggEBAMhtIlGKYfgP -lm7VILKB+MbcoxYA2s1q52sq+llIp0xJN9dzoWoBZV4yveeX09AuPHPTjHuD79ZC -wT+oqV0PN7p20kC9zC0/00RBSZz9Wyn0AiMiW3Ebv1jZKE4tRfTa57VjRUQRDSp/ -M382SbTObqkCMa5c/ciJv0J71/Fg8teH9lcuen5qE4Ad3OPQYx49cTGxYNSeCMqr -8JTHSHVUgfMbrXec6LKP24OsjzRr6L/D2fVDw2RV6xq9NoY2uiGMlxoh1OotO6y6 -7Kcdq765Sps1LxxcHVGnH1TtEpf/8m6HfUbJdNbv6z195lluBpQE5KJVhzgoaiJe -4r50ErAEQyo= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH8jCCB1ugAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl -SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl -SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 -DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIzMTExMTEwM1oXDTI1MTIyOTEx -MTEwM1owggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD -VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n -IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g -IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA55+R7+voFuF0vIkTodduR8ZfPxKU5u/h -M+GrgqufAwHmdG+KF5fPVy8Mdi7mbqfK2veLFBVADbNq2e2+s2q8Ai0chS3vl//P -l9rrR10eU79dVN4ndGMZfpXUMZblz0/Kq3Uvk5AsWUwfv1YokIhi4RMeBtOCVv3j -LSV1rDsiap8CAwEAAaOCBFIwggROMB0GA1UdDgQWBBRtW6MBjmE3nQR4tq+blh0C -QeXbeTCCAUQGA1UdIwSCATswggE3gBRtW6MBjmE3nQR4tq+blh0CQeXbeaGCARqk -ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE -BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT -ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC -LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD -VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr -BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB -FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC -AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB -D2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0UxIENBIENlcnRp -ZmljYXRlIGlzc3VlZCBieSBodHRwczovL3d3dy5pcHMuZXMvMCoGCWCGSAGG+EIB -AgQdFhtodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi8wOwYJYIZIAYb4QgEEBC4W -LGh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEuY3JsMEAG -CWCGSAGG+EIBAwQzFjFodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0 -aW9uQ0xBU0UxLmh0bWw/MD0GCWCGSAGG+EIBBwQwFi5odHRwczovL3d3dy5pcHMu -ZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0UxLmh0bWw/MDsGCWCGSAGG+EIBCAQuFixo -dHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTEuaHRtbDB1BgNV -HR8EbjBsMDKgMKAuhixodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy -Q0xBU0UxLmNybDA2oDSgMoYwaHR0cHM6Ly93d3diYWNrLmlwcy5lcy9pcHMyMDAy -L2lwczIwMDJDTEFTRTEuY3JsMC8GCCsGAQUFBwEBBCMwITAfBggrBgEFBQcwAYYT -aHR0cDovL29jc3AuaXBzLmVzLzANBgkqhkiG9w0BAQUFAAOBgQBacEdMbCU0z2bO -X+iyJafrUbjPE+5KzJz2jB1YXC2d7kMy2Hhbp8gVyfUFQpd+F2IgBBj9z3IRNkDN -foHhdse5j2cUUH+fno9jj8EPE2GPhXVmCjIP6KuPp8yzz89gC+ry+bkfSFzjHUQt -K15I/jRAHfyJywwUrwtmklZIX0E5Og== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIEO8rJUjANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJE -SzEMMAoGA1UEChMDS01EMQ8wDQYDVQQLEwZLTUQtQ0ExFjAUBgNVBAMTDUtNRC1D -QSBTZXJ2ZXIxIDAeBgoJkiaJk/IsZAEDFBBpbmZvY2FAa21kLWNhLmRrMB4XDTk4 -MTAxNjE5MTkyMVoXDTE4MTAxMjE5MTkyMVowZjELMAkGA1UEBhMCREsxDDAKBgNV -BAoTA0tNRDEPMA0GA1UECxMGS01ELUNBMRYwFAYDVQQDEw1LTUQtQ0EgU2VydmVy -MSAwHgYKCZImiZPyLGQBAxQQaW5mb2NhQGttZC1jYS5kazCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAJsLpbSgFxQ7IhFgf5f+RfBxnbCkx5C7yTjfCZvp -/BP2LBD3OKjgLRwvASoCU3I5NMhccho6uhZVf1HC+Ac5HmXUUd+v92a7gDnohPPy -Rgv8c6f/+R2fFen37SBemYFDtZveamVXZ2To7xAxNiMKgPTPs/Rl7F6LDsYgv1bD -36FrjahNoSTmTbYRoK21eIOVwrZeNSzo9w3W8fj0n+V2IB1jsOh+AvjXkjbvAVky -0/57GMlyBNKP7JIGP7LXqwWfrBXuAph1DUMz467KlHZOMkPwCjTZOab7CcLQXCCY -12s5c5QAkwpf35hQRuOaNo6d/XFM6J9mofiWlGTT3Px1EX0CAwEAAaMQMA4wDAYD -VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAPlA6VZ2C2cJbsI0SBIe9v+M9 -GxI45QI7P0D7QGyrqM7oNqGq7hJdN6NFb0LyPcF3/pVzmtYVJzaGKF6spaxOEveB -9ki1xRoXUKpaCxSweBpTzEktWa43OytRy0sbryEmHJCQkz8MPufWssf2yXHzgFFo -XMQpcMyT7JwxPlfYVvab9Kp+nW7fIyDOG0wdmBerZ+GEQJxJEkri1HskjigxhGze -ziocJatBuOWgqw5KRylgGIQjUGRTCbODVta+Kmqb9d+cB7FStbYtt2HebOXzBIY3 -XUM5KtGC++We7DqgU5Firek7brw8i2XsHPLKJTceb6Xo6DsSxLfBAWV6+8DCkQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOc -UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx -c8SxMQswCQYDVQQGDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykg -MjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 -dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAz -MjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2Vy -dGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYD -VQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kg -xLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu -xZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7 -XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2k -heiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35J -YbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5C -urKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1 -JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51 -b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV -9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd82YCdAR7 -kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh -fEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy -B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdA -aLX/7KfS0zgYnNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKS -RGQDJereW26fyfJOrN3H ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT -ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw -MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j -LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ -KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo -RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu -WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw -Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD -AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK -eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM -zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ -WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN -/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFajCCBFKgAwIBAgIEPLU9RjANBgkqhkiG9w0BAQUFADBmMRIwEAYDVQQKEwli -ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEzMDEGA1UEAxMq -YmVUUlVTVGVkIFJvb3QgQ0EtQmFsdGltb3JlIEltcGxlbWVudGF0aW9uMB4XDTAy -MDQxMTA3Mzg1MVoXDTIyMDQxMTA3Mzg1MVowZjESMBAGA1UEChMJYmVUUlVTVGVk -MRswGQYDVQQLExJiZVRSVVNUZWQgUm9vdCBDQXMxMzAxBgNVBAMTKmJlVFJVU1Rl -ZCBSb290IENBLUJhbHRpbW9yZSBJbXBsZW1lbnRhdGlvbjCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBALx+xDmcjOPWHIb/ymKt4H8wRXqOGrO4x/nRNv8i -805qX4QQ+2aBw5R5MdKR4XeOGCrDFN5R9U+jK7wYFuK13XneIviCfsuBH/0nLI/6 -l2Qijvj/YaOcGx6Sj8CoCd8JEey3fTGaGuqDIQY8n7pc/5TqarjDa1U0Tz0yH92B -FODEPM2dMPgwqZfT7syj0B9fHBOB1BirlNFjw55/NZKeX0Tq7PQiXLfoPX2k+Ymp -kbIq2eszh+6l/ePazIjmiSZuxyuC0F6dWdsU7JGDBcNeDsYq0ATdcT0gTlgn/FP7 -eHgZFLL8kFKJOGJgB7Sg7KxrUNb9uShr71ItOrL/8QFArDcCAwEAAaOCAh4wggIa -MA8GA1UdEwEB/wQFMAMBAf8wggG1BgNVHSAEggGsMIIBqDCCAaQGDysGAQQBsT4A -AAEJKIORMTCCAY8wggFIBggrBgEFBQcCAjCCAToaggE2UmVsaWFuY2Ugb24gb3Ig -dXNlIG9mIHRoaXMgQ2VydGlmaWNhdGUgY3JlYXRlcyBhbiBhY2tub3dsZWRnbWVu -dCBhbmQgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJk -IHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgdGhlIENlcnRpZmljYXRpb24g -UHJhY3RpY2UgU3RhdGVtZW50IGFuZCB0aGUgUmVseWluZyBQYXJ0eSBBZ3JlZW1l -bnQsIHdoaWNoIGNhbiBiZSBmb3VuZCBhdCB0aGUgYmVUUlVTVGVkIHdlYiBzaXRl -LCBodHRwOi8vd3d3LmJldHJ1c3RlZC5jb20vcHJvZHVjdHNfc2VydmljZXMvaW5k -ZXguaHRtbDBBBggrBgEFBQcCARY1aHR0cDovL3d3dy5iZXRydXN0ZWQuY29tL3By -b2R1Y3RzX3NlcnZpY2VzL2luZGV4Lmh0bWwwHQYDVR0OBBYEFEU9w6nR3D8kVpgc -cxiIav+DR+22MB8GA1UdIwQYMBaAFEU9w6nR3D8kVpgccxiIav+DR+22MA4GA1Ud -DwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEASZK8o+6svfoNyYt5hhwjdrCA -WXf82n+0S9/DZEtqTg6t8n1ZdwWtColzsPq8y9yNAIiPpqCy6qxSJ7+hSHyXEHu6 -7RMdmgduyzFiEuhjA6p9beP4G3YheBufS0OM00mG9htc9i5gFdPp43t1P9ACg9AY -gkHNZTfqjjJ+vWuZXTARyNtIVBw74acT02pIk/c9jH8F6M7ziCpjBLjqflh8AXtb -4cV97yHgjQ5dUX2xZ/2jvTg2xvI4hocalmhgRvsoFEdV4aeADGvi6t9NfJBIoDa9 -CReJf8Py05yc493EG931t3GzUwWJBtDLSoDByFOQtTwxiBdQn8nEDovYqAJjDQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE -BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is -I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G -CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do -lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc -AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ -MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT -DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O -rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq -OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b -xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw -7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD -aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG -SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 -ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr -AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz -R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 -JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo -Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd -MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg -Q2xhc3MgMiBDQSAxMB4XDTA2MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzEL -MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD -VQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7McXA0 -ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLX -l18xoS830r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVB -HfCuuCkslFJgNJQ72uA40Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B -5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/RuFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3 -WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNCMEAwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0PAQH/BAQD -AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLP -gcIV1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+ -DKhQ7SLHrQVMdvvt7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKu -BctN518fV4bVIJwo+28TOPX2EZL2fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHs -h7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5wwDX3OaJdZtB7WZ+oRxKaJyOk -LY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV -BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 -Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1 -OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i -SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc -VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW -Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q -Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2 -1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq -ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1 -Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX -XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy -dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6 -Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz -JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 -Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN -irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8 -TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6 -g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB -95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj -S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV -UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL -EwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJ -BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x -ETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/ -k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvso -LeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3o -TQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCG -SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx -JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI -RFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3 -MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6C -TShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5 -WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG -SIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR -xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL -B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz -dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG -A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U -cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf -qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ -JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ -+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS -s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 -HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 -70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG -V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S -qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S -5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia -C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX -OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE -FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 -KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B -8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ -MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc -0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ -u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF -u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH -YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 -GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO -RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e -KeC2uAloGRwYQw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6 -MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp -dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX -BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy -MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp -eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg -/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl -wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh -AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2 -PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu -AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR -MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc -HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/ -Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+ -f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO -rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch -6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3 -7CAFYd4= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy -dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t -MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB -MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG -A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp -b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl -cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv -bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE -VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ -ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR -uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG -9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI -hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM -pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy -dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 -MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx -dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f -BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A -cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ -MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm -aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw -ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj -IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y -7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh -1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl -MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh -U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz -MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N -IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11 -bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE -RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO -zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5 -bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF -MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1 -VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC -OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G -CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW -tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ -q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb -EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+ -Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O -VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEAq6HgBiMui0NiZdH3zNiWYwDQYJKoZIhvcNAQEFBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh -YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 -FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G -CSqGSIb3DQEBBQUAA4GBAIDToA+IyeVoW4R7gB+nt+MjWBEc9RTwWBKMi99x2ZAk -EXyge8N6GRm9cr0gvwA63/rVeszC42JFi8tJg5jBcGnQnl6CjDVHjk8btB9jAa3k -ltax7nosZm4XNq8afjgGhixrTcsnkm54vwDVAcCxB8MJqmSFKPKdc57PYDoKHUpI ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx -ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 -b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD -EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X -DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw -DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u -c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr -TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA -OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC -2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW -RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P -AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW -ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0 -YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz -b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO -ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB -IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs -b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs -ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s -YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg -a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g -SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0 -aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg -YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg -Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY -ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g -pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4 -Fp1hBWeAyNDYpQcCNJgEjTME1A== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw -PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz -cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 -MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz -IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ -ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR -VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL -kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd -EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas -H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 -HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud -DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 -QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu -Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ -AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 -yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR -FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA -ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB -kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 -l7+ijrRU ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICoTCCAgqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzAN -BgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAd -BgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNOTcwMTAxMDAwMDAwWhcN -MjAxMjMxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4g -Q2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsG -A1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1l -c3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYrWHhhRYZT -6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u6TqFJBU820cEY8OexJQa -Wt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522FOMjhdepQeBMpHmwKxqL -8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB -Af8wDQYJKoZIhvcNAQEEBQADgYEAZ9viwuaHPUCDhjc1fR/OmsMMZiCouqoEiYbC -9RAIDb/LogWK0E02PvTX72nGXuSwlG9KuefeW4i2e9vjJ+V2w/A1wcu1J5szedyQ -pgCed/r8zSeUQhac0xxo7L9c3eWpexAKMnRUEzGLhQOEkbdYATAUOK8oyvyxUBkZ -CayJSdM= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi -MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu -MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV -UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO -ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz -c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP -OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl -mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF -BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 -qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw -gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu -bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp -dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 -6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ -h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH -/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv -wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN -pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDgDCCAmigAwIBAgICAx4wDQYJKoZIhvcNAQEFBQAwYTELMAkGA1UEBhMCVVMx -DTALBgNVBAoTBFZJU0ExLzAtBgNVBAsTJlZpc2EgSW50ZXJuYXRpb25hbCBTZXJ2 -aWNlIEFzc29jaWF0aW9uMRIwEAYDVQQDEwlHUCBSb290IDIwHhcNMDAwODE2MjI1 -MTAwWhcNMjAwODE1MjM1OTAwWjBhMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklT -QTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRp -b24xEjAQBgNVBAMTCUdQIFJvb3QgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAKkBcLWqxEDwq2omYXkZAPy/mzdZDK9vZBv42pWUJGkzEXDK41Z0ohdX -ZFwgBuHW73G3O/erwWnQSaSxBNf0V2KJXLB1LRckaeNCYOTudNargFbYiCjh+20i -/SN8RnNPflRzHqgsVVh1t0zzWkWlAhr62p3DRcMiXvOL8WAp0sdftAw6UYPvMPjU -58fy+pmjIlC++QU3o63tmsPm7IgbthknGziLgE3sucfFicv8GjLtI/C1AVj59o/g -halMCXI5Etuz9c9OYmTaxhkVOmMd6RdVoUwiPDQyRvhlV7or7zaMavrZ2UT0qt2E -1w0cslSsMoW0ZA3eQbuxNMYBhjJk1Z8CAwEAAaNCMEAwHQYDVR0OBBYEFJ59SzS/ -ca3CBfYDdYDOqU8axCRMMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQAhpXYUVfmtJ3CPPPTVbMjMCqujmAuKBiPFyWHb -mQdpNSYx/scuhMKZYdQN6X0uEyt8joW2hcdLzzW2LEc9zikv2G+fiRxkk78IvXbQ -kIqUs38oW26sTTMs7WXcFsziza6kPWKSBpUmv9+55CCmc2rBvveURNZNbyoLaxhN -dBA2aGpawWqn3TYpjLgwi08hPwAuVDAHOrqK5MOeyti12HvOdUVmB/RtLdh6yumJ -ivIj2C/LbgA2T/vwLwHMD8AiZfSr4k5hLQOCfZEWtTDVFN5ex5D8ofyrEK9ca3Cn -B+8phuiyJccg/ybdd+95RBTEvd07xQObdyPsoOy7Wjm1zK0G ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEajCCA1KgAwIBAgIBATANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJKUDEN -MAsGA1UECgwESlBLSTEpMCcGA1UECwwgUHJlZmVjdHVyYWwgQXNzb2NpYXRpb24g -Rm9yIEpQS0kxETAPBgNVBAsMCEJyaWRnZUNBMB4XDTAzMTIyNzA1MDgxNVoXDTEz -MTIyNjE0NTk1OVowWjELMAkGA1UEBhMCSlAxDTALBgNVBAoMBEpQS0kxKTAnBgNV -BAsMIFByZWZlY3R1cmFsIEFzc29jaWF0aW9uIEZvciBKUEtJMREwDwYDVQQLDAhC -cmlkZ2VDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANTnUmg7K3m8 -52vd77kwkq156euwoWm5no8E8kmaTSc7x2RABPpqNTlMKdZ6ttsyYrqREeDkcvPL -yF7yf/I8+innasNtsytcTAy8xY8Avsbd4JkCGW9dyPjk9pzzc3yLQ64Rx2fujRn2 -agcEVdPCr/XpJygX8FD5bbhkZ0CVoiASBmlHOcC3YpFlfbT1QcpOSOb7o+VdKVEi -MMfbBuU2IlYIaSr/R1nO7RPNtkqkFWJ1/nKjKHyzZje7j70qSxb+BTGcNgTHa1YA -UrogKB+UpBftmb4ds+XlkEJ1dvwokiSbCDaWFKD+YD4B2s0bvjCbw8xuZFYGhNyR -/2D5XfN1s2MCAwEAAaOCATkwggE1MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MG0GA1UdHwRmMGQwYqBgoF6kXDBaMQswCQYDVQQGEwJKUDENMAsGA1UE -CgwESlBLSTEpMCcGA1UECwwgUHJlZmVjdHVyYWwgQXNzb2NpYXRpb24gRm9yIEpQ -S0kxETAPBgNVBAsMCEJyaWRnZUNBMIGDBgNVHREEfDB6pHgwdjELMAkGA1UEBhMC -SlAxJzAlBgNVBAoMHuWFrOeahOWAi+S6uuiqjeiovOOCteODvOODk+OCuTEeMBwG -A1UECwwV6YO96YGT5bqc55yM5Y2U6K2w5LyaMR4wHAYDVQQLDBXjg5bjg6rjg4Pj -grjoqo3oqLzlsYAwHQYDVR0OBBYEFNQXMiCqQNkR2OaZmQgLtf8mR8p8MA0GCSqG -SIb3DQEBBQUAA4IBAQATjJo4reTNPC5CsvAKu1RYT8PyXFVYHbKsEpGt4GR8pDCg -HEGAiAhHSNrGh9CagZMXADvlG0gmMOnXowriQQixrtpkmx0TB8tNAlZptZWkZC+R -8TnjOkHrk2nFAEC3ezbdK0R7MR4tJLDQCnhEWbg50rf0wZ/aF8uAaVeEtHXa6W0M -Xq3dSe0XAcrLbX4zZHQTaWvdpLAIjl6DZ3SCieRMyoWUL+LXaLFdTP5WBCd+No58 -IounD9X4xxze2aeRVaiV/WnQ0OSPNS7n7YXy6xQdnaOU4KRW/Lne1EDf5IfWC/ih -bVAmhZMbcrkWWcsR6aCPG+2mV3zTD6AUzuKPal8Y ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJB -VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp -bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5R -dWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5RdWFsLTAzMB4XDTA1MDgxNzIyMDAw -MFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgwRgYDVQQKDD9BLVRy -dXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0ZW52 -ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMM -EEEtVHJ1c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCtPWFuA/OQO8BBC4SAzewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUj -lUC5B3ilJfYKvUWG6Nm9wASOhURh73+nyfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZ -znF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPESU7l0+m0iKsMrmKS1GWH -2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4iHQF63n1 -k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs -2e3Vcuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYD -VR0OBAoECERqlWdVeRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC -AQEAVdRU0VlIXLOThaq/Yy/kgM40ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fG -KOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmrsQd7TZjTXLDR8KdCoLXEjq/+ -8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZdJXDRZslo+S4R -FGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS -mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmE -DNuxUCAKGkq6ahq97BvIxYSazQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT -EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp -ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz -NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH -EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE -AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD -E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH -/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy -DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh -GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR -tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA -AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX -WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu -9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr -gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo -2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO -LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI -4uJEvlz36hz1 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 -MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL -v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 -eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq -tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd -C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa -zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB -mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH -V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n -bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG -3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs -J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO -291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS -ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd -AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 -MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 -RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT -gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm -KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd -QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ -XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o -LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU -RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp -jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK -6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX -mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs -Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH -WD9f ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILAgAAAAAA1ni3lAUwDQYJKoZIhvcNAQEEBQAwVzELMAkG -A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -MDBaFw0xNDAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIABjAdBgNVHQ4EFgQU -YHtmGkUNl8qJUC99BM00qP/8/UswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B -AQQFAAOCAQEArqqf/LfSyx9fOSkoGJ40yWxPbxrwZKJwSk8ThptgKJ7ogUmYfQq7 -5bCdPTbbjwVR/wkxKh/diXeeDy5slQTthsu0AD+EAk2AaioteAuubyuig0SDH81Q -gkwkr733pbTIWg/050deSY43lv6aiAU62cDbKYfmGZZHpzqmjIs8d/5GY6dT2iHR -rH5Jokvmw2dZL7OKDrssvamqQnw1wdh/1acxOk5jQzmvCLBhNIzTmKlDNPYPhyk7 -ncJWWJh3w/cbrPad+D6qp1RF8PX51TFl/mtYnHGzHtdS6jIX/EBgHcl5JLL2bP2o -Zg6C3ZjL2sJETy6ge/L3ayx2EYRGinij4w== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIETTCCAzWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBtMQswCQYDVQQGEwJDSDEO -MAwGA1UEChMFYWRtaW4xETAPBgNVBAsTCFNlcnZpY2VzMSIwIAYDVQQLExlDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0aWVzMRcwFQYDVQQDEw5BZG1pbkNBLUNELVQwMTAe -Fw0wNjAxMjUxMzM2MTlaFw0xNjAxMjUxMjM2MTlaMG0xCzAJBgNVBAYTAkNIMQ4w -DAYDVQQKEwVhZG1pbjERMA8GA1UECxMIU2VydmljZXMxIjAgBgNVBAsTGUNlcnRp -ZmljYXRpb24gQXV0aG9yaXRpZXMxFzAVBgNVBAMTDkFkbWluQ0EtQ0QtVDAxMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0jQlMZmpLDhV+GNR9TAoSNle -JgQB4xAXJELQf5/ySMfoFA4MmjKqYXQkB6MGPuQKwR9XRRSPf61vqb8YPsdjRmgp -byHBcUd5t0N8RX6wRZUnPMW+bCCo2VqAU4XFbnlc2gHKaam0wdTtbBTXEkv0ieIH -fxCfFxXqSsSr60IkF/2/xbrAgV/QD5yHk6Ie8feAVWwi5UtaFqtu4LiFEh2QMyxs -Oyz1OcvKzkM2g873tyiE7jzMgZP+Ww3tibk2F9+e6ZeiB37TLOmVtvgpmrws4fiI -rFNXEYSWBVrUTbn81U47yWzOgf5fEHP07bRV5QOCzCm99qNimsbL6CG7nT78CQID -AQABo4H3MIH0MBIGA1UdEwEB/wQIMAYBAf8CAQAwga4GA1UdIASBpjCBozCBoAYI -YIV0AREDFQEwgZMwSAYIKwYBBQUHAgIwPBo6VGhpcyBpcyB0aGUgQWRtaW5DQS1D -RC1UMDEgQ2VydGlmaWNhdGUgUHJhY3RpY2UgU3RhdGVtZW50LjBHBggrBgEFBQcC -ARY7aHR0cDovL3d3dy5wa2kuYWRtaW4uY2gvcG9saWN5L0NQU18yXzE2Xzc1Nl8x -XzE3XzNfMjFfMS5wZGYwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQqxGkKocZV -xgNucM6GgbOkD6oZ2zANBgkqhkiG9w0BAQUFAAOCAQEAn356bbusjI5glGXRQ1DR -v21qQf0S4s3GHyZm7cqdOkFleM70ArBT+kOP5Nm7rlSAFyVgEkmBdOg7s9tlXClU -yeZFnp6UEYRUcijPN8D1VaNRK6PIUObpDBQT0C+kAfxG9z4v29T0SxT4sgAdC/xQ -Fyv58Fp9bPn7owuKwKcyCH1XSyi/Bp4XFELlLOaigBZO/w+dPBz4FcJSdZjU+BaJ -0E3nKAjHlShO5ouBSZnaJz3p+nkw2Wyo36s6GxCK0XbkSP45iniIG4FmwwZkonYF -ypQntHbx2oL7tUQQY0PDo8bGBMcPy/G2j+dciqZRlsnfgMy10SCzQ9MUx92xUG2V -eg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG -EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 -MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl -cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR -dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB -pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM -b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm -aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz -IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT -lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz -AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 -VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG -ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 -BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG -AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M -U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh -bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C -+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC -bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F -uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 -XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM -MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D -ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU -cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 -WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg -Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw -IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH -UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM -TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU -BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM -kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x -AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV -HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y -sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL -I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 -J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY -VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI -03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNV -BAMML0VCRyBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx -c8SxMTcwNQYDVQQKDC5FQkcgQmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXpt -ZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAeFw0wNjA4MTcwMDIxMDlaFw0xNjA4 -MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25payBTZXJ0aWZpa2Eg -SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2ltIFRl -a25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h -4fuXd7hxlugTlkaDT7byX3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAk -tiHq6yOU/im/+4mRDGSaBUorzAzu8T2bgmmkTPiab+ci2hC6X5L8GCcKqKpE+i4s -tPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfreYteIAbTdgtsApWjluTL -dlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZTqNGFav4 -c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8Um -TDGyY5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z -+kI2sSXFCjEmN1ZnuqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0O -Lna9XvNRiYuoP1Vzv9s6xiQFlpJIqkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMW -OeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vmExH8nYQKE3vwO9D8owrXieqW -fo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0Nokb+Clsi7n2 -l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB -/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgw -FoAU587GT/wWZ5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+ -8ygjdsZs93/mQJ7ANtyVDR2tFcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI -6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgmzJNSroIBk5DKd8pNSe/iWtkqvTDO -TLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64kXPBfrAowzIpAoHME -wfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqTbCmY -Iai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJn -xk1Gj7sURT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4Q -DgZxGhBM/nV+/x5XOULK1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9q -Kd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11t -hie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQY9iJSrSq3RZj9W6+YKH4 -7ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9AahH3eU7 -QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 -MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub -j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo -U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf -zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b -u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ -bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er -fF6adulZkMV8gzURZVE= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGJDCCBY2gAwIBAgIEQoaroDANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u -ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc -KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u -ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjA3 -MTQxNzEwMjhaFw0xNDA3MTQxNzQwMjhaMFwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK -EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xGzAZBgNV -BAMTEkRpZ2lDZXJ0IEdsb2JhbCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAMQ8vMy66mLmnkIjr7SyEa5ijdmh04/MFHIZ7Zn2/d5du1nAsMKvaplS -lVcLNf/hhvqvosPBBWUnIHYvClQlfOor3ZVBV5sPO89H6AEGjMVESPwHLvNygzBR -lJ5pOoOph5AU2V7EoniPwT7UGWEOGufcGpUgQb5vF9q4HEHumLD61x01PxanBCgT -XT0FdZouhp4ssBeHIFhX7+HqVWC4LHAhrCljDBD8YLz51Rw3ZNW0+x6rJjlGiKTL -zTBnwCZ55cpo+SLX5dKxu0hMmwuYW0KS5dLtDkcw+t0nVmNqpQHHjq/wTjsbVRVE -1T5NVx7hkeq4oI/OOmNflom6CD7+RLsCAwEAAaOCAwUwggMBMBIGA1UdEwEB/wQI -MAYBAf8CAQAwggEyBgNVHSAEggEpMIIBJTCCASEGCSqGSIb2fQdLAjCCARIwJgYI -KwYBBQUHAgEWGmh0dHA6Ly93d3cuZW50cnVzdC5uZXQvY3BzMIHnBggrBgEFBQcC -AjCB2hqB10ZvciB1c2Ugc29sZWx5IHdpdGggU1NMIGFuZCBTL01JTUUgY2VydGlm -aWNhdGVzIGlzc3VlZCBieSBEaWdpY2VydCwgSW5jLiB0byBhdXRob3JpemVkIHN1 -YnNjcmliZXJzLg0KRE9FUyBOT1QgcmVwcmVzZW50IGFueSBlbmRvcnNlbWVudCBi -eSBFbnRydXN0IEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMgYXMgdG8gdGhlIGlkZW50 -aXR5IG9mIGFueSBjZXJ0aWZpY2F0ZSBob2xkZXIuMDEGA1UdJQQqMCgGCCsGAQUF -BwMBBggrBgEFBQcDAgYIKwYBBQUHAwQGCCsGAQUFBwMJMIIBGAYDVR0fBIIBDzCC -AQswKKAmoCSGImh0dHA6Ly9jcmwuZW50cnVzdC5uZXQvc2VydmVyMS5jcmwwgd6g -gduggdikgdUwgdIxCzAJBgNVBAYTAlVTMRQwEgYDVQQKEwtFbnRydXN0Lm5ldDE7 -MDkGA1UECxMyd3d3LmVudHJ1c3QubmV0L0NQUyBpbmNvcnAuIGJ5IHJlZi4gKGxp -bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0 -ZWQxOjA4BgNVBAMTMUVudHJ1c3QubmV0IFNlY3VyZSBTZXJ2ZXIgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEwCwYDVR0PBAQDAgEGMB8GA1Ud -IwQYMBaAFPAXYhNVPbP/CgBr+1CEl/PtYtAaMB0GA1UdDgQWBBSnxxOgegE8ne+C -SIJI1XNRthJWKjAZBgkqhkiG9n0HQQAEDDAKGwRWNy4xAwIAgTANBgkqhkiG9w0B -AQUFAAOBgQBK8bPOaGnjWKNh7bYWyJOxGDA+4HLfTz3iTeG4/D/ByeNFqV2pwdqj -5TbXjtYPrTavbLxE5ppGlKYRoNBS59pVsPYchftjUnu2mY8f4stHZKLrCGXmUdsc -S21/U58eDTGT1DBdHm4BBydgXbvT9ONsHSAPdSozEKe3idepFxQyAw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOc -UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx -c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xS -S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg -SGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcNMDUxMTA3MTAwNzU3 -WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVrdHJv -bmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJU -UjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSw -bGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe -LiAoYykgS2FzxLFtIDIwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqeLCDe2JAOCtFp0if7qnef -J1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKIx+XlZEdh -R3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJ -Qv2gQrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGX -JHpsmxcPbe9TmJEr5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1p -zpwACPI2/z7woQ8arBT9pmAPAgMBAAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58S -Fq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8GA1UdEwEB/wQFMAMBAf8wDQYJ -KoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/nttRbj2hWyfIvwq -ECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 -Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFz -gw2lGh1uEpJ+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotH -uFEJjOp9zYhys2AzsfAKRO8P9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LS -y3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5UrbnBEI= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh -YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 -FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G -CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg -J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc -r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIETzCCAzegAwIBAgIEO63vKTANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBS -b290Q0EwHhcNMDEwOTIzMTQxODE3WhcNMTEwOTIzMTMxODE3WjB1MQswCQYDVQQG -EwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMb -Q2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQg -LSBDQSBLbGFzYSAxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4SRW9Q58g -5DY1Hw7hgCRKBEdPdGn0MFHsfw7rlu/oQm7IChI/uWd9q5wwo77YojtTDjRnpgZs -jqBeynX8T90vFILqsY2K5CF1OESalwvVr3sZiQX79lisuFKat92u6hBFikFIVxfH -HB67Af+g7u0dEHdDW7lwy81MwFYxBTRy9wIDAQABo4IBbTCCAWkwDwYDVR0TAQH/ -BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwggEEBgNVHSAEgfwwgfkwgfYGDSsGAQQB -vj8CAQoBAQAwgeQwgZoGCCsGAQUFBwICMIGNGoGKQ2VydHlmaWthdCB3eXN0YXdp -b255IHpnb2RuaWUgeiBkb2t1bWVudGVtOiAiUG9saXR5a2EgQ2VydHlmaWthY2pp -IGRsYSBSb290Q0EiLiBDZXJ0eWZpa2F0IHd5c3Rhd2lvbnkgcHJ6ZXogUm9vdENB -IHcgaGllcmFyY2hpaSBDQyBTaWduZXQuMEUGCCsGAQUFBwIBFjlodHRwOi8vd3d3 -LnNpZ25ldC5wbC9yZXBvenl0b3JpdW0vZG9rdW1lbnR5L3BjX3Jvb3RjYS50eHQw -HwYDVR0jBBgwFoAUwJvFIw0C4aZOSGsfAOnjmhQbsa8wHQYDVR0OBBYEFMODHtVZ -d1T7TftXR/nEI1zR54njMA0GCSqGSIb3DQEBBQUAA4IBAQBRIHQBFIGh8Jpxt87A -gSLwIEEk4+oGy769u3NtoaR0R3WNMdmt7fXTi0tyTQ9V4AIszxVjhnUPaKnF1KYy -f8Tl+YTzk9ZfFkZ3kCdSaILZAOIrmqWNLPmjUQ5/JiMGho0e1YmWUcMci84+pIis -TsytFzVP32/W+sz2H4FQAvOIMmxB7EJX9AdbnXn9EXZ+4nCqi0ft5z96ZqOJJiCB -3vSaoYg+wdkcvb6souMJzuc2uptXtR1Xf3ihlHaGW+hmnpcwFA6AoNrom6Vgzk6U -1ienx0Cw28BhRSKqzKkyXkuK8gRflZUx84uftXncwKJrMiE3lvgOOBITRzcahirL -er4c ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx -FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg -Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG -A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr -b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ -jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn -PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh -ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 -nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h -q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED -MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC -mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 -7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB -oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs -EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO -fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi -AmvZWg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB -lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt -SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG -A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe -MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v -d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh -cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn -0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ -M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a -MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd -oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI -DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy -oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 -dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy -bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF -BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM -//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli -CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE -CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t -3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS -KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx -ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w -MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD -VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx -FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu -ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7 -gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH -fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a -ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT -ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk -c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto -dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt -aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI -hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk -QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/ -h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq -nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR -rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2 -9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARwxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEzMDEGA1UECxMq -SVBTIENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTMwMQYD -VQQDEypJUFMgQ0EgQ2hhaW5lZCBDQXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx -HjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczAeFw0wMTEyMjkwMDUzNTha -Fw0yNTEyMjcwMDUzNThaMIIBHDELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNl -bG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQg -cHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMu -ZXMgQy5JLkYuICBCLTYwOTI5NDUyMTMwMQYDVQQLEypJUFMgQ0EgQ2hhaW5lZCBD -QXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMzAxBgNVBAMTKklQUyBDQSBDaGFp -bmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3DQEJARYP -aXBzQG1haWwuaXBzLmVzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcVpJJ -spQgvJhPUOtopKdJC7/SMejHT8KGC/po/UNaivNgkjWZOLtNA1IhW/A3mTXhQSCB -hYEFcYGdtJUZqV92NC5jNzVXjrQfQj8VXOF6wV8TGDIxya2+o8eDZh65nAQTy2nB -Bt4wBrszo7Uf8I9vzv+W6FS+ZoCua9tBhDaiPQIDAQABo4IEQzCCBD8wHQYDVR0O -BBYEFKGtMbH5PuEXpsirNPxShwkeYlJBMIIBTgYDVR0jBIIBRTCCAUGAFKGtMbH5 -PuEXpsirNPxShwkeYlJBoYIBJKSCASAwggEcMQswCQYDVQQGEwJFUzESMBAGA1UE -CBMJQmFyY2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJ -bnRlcm5ldCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0Bt -YWlsLmlwcy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxMzAxBgNVBAsTKklQUyBDQSBD -aGFpbmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEzMDEGA1UEAxMqSVBT -IENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI -hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8E -BQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMG -CCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYB -BAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMw -EYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlwcy5lczBC -BglghkgBhvhCAQ0ENRYzQ2hhaW5lZCBDQSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkg -aHR0cDovL3d3dy5pcHMuZXMvMCkGCWCGSAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlw -cy5lcy9pcHMyMDAyLzA3BglghkgBhvhCAQQEKhYoaHR0cDovL3d3dy5pcHMuZXMv -aXBzMjAwMi9pcHMyMDAyQ0FDLmNybDA8BglghkgBhvhCAQMELxYtaHR0cDovL3d3 -dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0aW9uQ0FDLmh0bWw/MDkGCWCGSAGG+EIB -BwQsFipodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3JlbmV3YWxDQUMuaHRtbD8w -NwYJYIZIAYb4QgEIBCoWKGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5 -Q0FDLmh0bWwwbQYDVR0fBGYwZDAuoCygKoYoaHR0cDovL3d3dy5pcHMuZXMvaXBz -MjAwMi9pcHMyMDAyQ0FDLmNybDAyoDCgLoYsaHR0cDovL3d3d2JhY2suaXBzLmVz -L2lwczIwMDIvaXBzMjAwMkNBQy5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF -BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAERyMJ1W -WKJBGyi3leGmGpVfp3hAK+/blkr8THFj2XOVvQLiogbHvpcqk4A0hgP63Ng9HgfN -HnNDJGD1HWHc3JagvPsd4+cSACczAsDAK1M92GsDgaPb1pOVIO/Tln4mkImcJpvN -b2ar7QMiRDjMWb2f2/YHogF/JsRj9SVCXmK9 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr -MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl -cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv -bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw -CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h -dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l -cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h -2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E -lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV -ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq -299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t -vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL -dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF -AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR -zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 -LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd -7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw -++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt -398znM/jra6O1I7mT1GvFpLgXPYHDw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH8jCCB1ugAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl -SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl -SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 -DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIzMTExMTkzMVoXDTI1MTIyOTEx -MTkzMVowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD -VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n -IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g -IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAve2QhYLxoN2P3DVo4Xw+6Gyb2vDjfzvB -JRvH+WFIXO3KItC1dJk2W7iFnsZJnb65Q6NDKxhwfQ4XnLuBSPqMVJ6EHB++I1p2 -pg0j7YOtec++o3ysS6zf1r01HSh8i85+AcGcgLO4Z79w9jtEGlSdrFhCLUjJJSEs -XdzSbkEFrkMCAwEAAaOCBFIwggROMB0GA1UdDgQWBBT7o4z3Z4tAqk02rzCA6po7 -4C9o6DCCAUQGA1UdIwSCATswggE3gBT7o4z3Z4tAqk02rzCA6po74C9o6KGCARqk -ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE -BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT -ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC -LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD -VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr -BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB -FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC -AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB -D2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0UzIENBIENlcnRp -ZmljYXRlIGlzc3VlZCBieSBodHRwczovL3d3dy5pcHMuZXMvMCoGCWCGSAGG+EIB -AgQdFhtodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi8wOwYJYIZIAYb4QgEEBC4W -LGh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMuY3JsMEAG -CWCGSAGG+EIBAwQzFjFodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0 -aW9uQ0xBU0UzLmh0bWw/MD0GCWCGSAGG+EIBBwQwFi5odHRwczovL3d3dy5pcHMu -ZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0UzLmh0bWw/MDsGCWCGSAGG+EIBCAQuFixo -dHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTMuaHRtbDB1BgNV -HR8EbjBsMDKgMKAuhixodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy -Q0xBU0UzLmNybDA2oDSgMoYwaHR0cHM6Ly93d3diYWNrLmlwcy5lcy9pcHMyMDAy -L2lwczIwMDJDTEFTRTMuY3JsMC8GCCsGAQUFBwEBBCMwITAfBggrBgEFBQcwAYYT -aHR0cDovL29jc3AuaXBzLmVzLzANBgkqhkiG9w0BAQUFAAOBgQAiu2FuR8MoQlYw -3QtFc/BI7DgkUUeSIM49JoMU0H3a4Y+JbQxQ4q/n6yAbEuMETUyqob/HmS/NkLJq -ur3RvGBseDXgxNyePGjFc97ITNWf5X1+4CXtBf+TTKNEMg1UpPbCz+9EkjzTcYj1 -5tjLbAp/mmLLZmCOV7cCGuXGSTBNzA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIG0zCCBbugAwIBAgIBADANBgkqhkiG9w0BAQUFADCBzDELMAkGA1UEBhMCQVQx -EDAOBgNVBAgTB0F1c3RyaWExDzANBgNVBAcTBlZpZW5uYTE6MDgGA1UEChMxQVJH -RSBEQVRFTiAtIEF1c3RyaWFuIFNvY2lldHkgZm9yIERhdGEgUHJvdGVjdGlvbjEl -MCMGA1UECxMcQS1DRVJUIENlcnRpZmljYXRpb24gU2VydmljZTEYMBYGA1UEAxMP -QS1DRVJUIEFEVkFOQ0VEMR0wGwYJKoZIhvcNAQkBFg5pbmZvQGEtY2VydC5hdDAe -Fw0wNDEwMjMxNDE0MTRaFw0xMTEwMjMxNDE0MTRaMIHMMQswCQYDVQQGEwJBVDEQ -MA4GA1UECBMHQXVzdHJpYTEPMA0GA1UEBxMGVmllbm5hMTowOAYDVQQKEzFBUkdF -IERBVEVOIC0gQXVzdHJpYW4gU29jaWV0eSBmb3IgRGF0YSBQcm90ZWN0aW9uMSUw -IwYDVQQLExxBLUNFUlQgQ2VydGlmaWNhdGlvbiBTZXJ2aWNlMRgwFgYDVQQDEw9B -LUNFUlQgQURWQU5DRUQxHTAbBgkqhkiG9w0BCQEWDmluZm9AYS1jZXJ0LmF0MIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3euXIy+mnf6BYKbK+QH5k679 -tUFqeT8jlZxMew8eNiHuw9KoxWBzL6KksK+5uK7Gatw+sbAYntEGE80P+Jg1hADM -e+Fr5V0bc6QS3gkVtfUCW/RIvfMM39oxvmqJmOgPnJU7H6+nmLtsq61tv9kVJi/2 -4Y5wXW3odet72sF57EoG6s78w0BUVLNcMngS9bZZzmdG3/d6JbkGgoNF/8DcgCBJ -W/t0JrcIzyppXIOVtUzzOrrU86zuUgT3Rtkl5kjG7DEHpFb9H0fTOY1v8+gRoaO6 -2gA0PCiysgVZjwgVeYe3KAg11nznyleDv198uK3Dc1oXIGYjJx2FpKWUvAuAEwID -AQABo4ICvDCCArgwHQYDVR0OBBYEFDd/Pj6ZcWDKJNSRE3nQdCm0qCTYMIH5BgNV -HSMEgfEwge6AFDd/Pj6ZcWDKJNSRE3nQdCm0qCTYoYHSpIHPMIHMMQswCQYDVQQG -EwJBVDEQMA4GA1UECBMHQXVzdHJpYTEPMA0GA1UEBxMGVmllbm5hMTowOAYDVQQK -EzFBUkdFIERBVEVOIC0gQXVzdHJpYW4gU29jaWV0eSBmb3IgRGF0YSBQcm90ZWN0 -aW9uMSUwIwYDVQQLExxBLUNFUlQgQ2VydGlmaWNhdGlvbiBTZXJ2aWNlMRgwFgYD -VQQDEw9BLUNFUlQgQURWQU5DRUQxHTAbBgkqhkiG9w0BCQEWDmluZm9AYS1jZXJ0 -LmF0ggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgHmMEcGA1UdJQRAMD4G -CCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcD -CAYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAP8wUQYDVR0gBEowSDBGBggq -KAAYAQEBAzA6MDgGCCsGAQUFBwIBFixodHRwOi8vd3d3LmEtY2VydC5hdC9jZXJ0 -aWZpY2F0ZS1wb2xpY3kuaHRtbDA7BglghkgBhvhCAQgELhYsaHR0cDovL3d3dy5h -LWNlcnQuYXQvY2VydGlmaWNhdGUtcG9saWN5Lmh0bWwwGQYDVR0RBBIwEIEOaW5m -b0BhLWNlcnQuYXQwLwYDVR0SBCgwJoEOaW5mb0BhLWNlcnQuYXSGFGh0dHA6Ly93 -d3cuYS1jZXJ0LmF0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHBzOi8vc2VjdXJlLmEt -Y2VydC5hdC9jZ2ktYmluL2EtY2VydC1hZHZhbmNlZC5jZ2kwDQYJKoZIhvcNAQEF -BQADggEBACX1IvgfdG2rvfv35O48vSEvcVaEdlN8USFBHWz3JRAozgzvaBtwHkjK -Zwt5l/BWOtjbvHfRjDt7ijlBEcxOOrNC1ffyMHwHrXpvff6YpQ5wnxmIYEQcURiG -HMqruEX0WkuDNgSKwefsgXs27eeBauHgNGVcTYH1rmHu/ZyLpLxOyJQ2PCzA1DzW -3rWkIX92ogJ7lTRdWrbxwUL1XGinxnnaQ74+/y0pI9JNEv7ic2tpkweRMpkedaLW -msC1+orfKTebsg69aMaCx7o6jNONRmR/7TVaPf8/k6g52cHZ9YWjQvup22b5rWxG -J5r5LZ4vCPmF4+T4lutjUYAa/lGuQTg= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM -MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD -QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM -MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD -QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E -jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo -ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI -ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu -Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg -AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 -HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA -uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa -TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg -xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q -CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x -O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs -6GAqm4VKQPNriiTsBhYscw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -+OkuE6N36B9K ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV -MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe -TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0 -dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB -KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0 -N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC -dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu -MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL -b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD -zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi -3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8 -WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY -Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi -NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC -ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4 -QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0 -YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz -aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu -IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm -ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg -ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs -amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv -IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3 -Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6 -ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1 -YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg -dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs -b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G -CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO -xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP -0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ -QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk -f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK -8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK -VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm -Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J -h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul -uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68 -DzFc6PLZ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFGjCCBAKgAwIBAgIEPV0tNDANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBS -b290Q0EwHhcNMDIwODE2MTY0OTU2WhcNMjYwOTIxMTU0MjE5WjB2MQswCQYDVQQG -EwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMb -Q2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MSAwHgYDVQQDExdDQyBTaWduZXQg -LSBQQ0EgS2xhc2EgMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALN3 -LanJtdueNe6geWUTFENa+lEuzqELcoqhYB+a/tJcPEkc6TX/bYPzalRRjqs+quMP -6KZTU0DixOrV+K7iWaqAiQ913HX5IBLmKDCrTVW/ZvSDpiBKbxlHfSNuJxAuVT6H -dbzK7yAW38ssX+yS2tZYHZ5FhZcfqzPEOpO94mAKcBUhk6T/ki0evXX/ZvvktwmF -3hKattzwtM4JMLurAEl8SInyEYULw5JdlfcBez2Tg6Dbw34hA1A+ckTwhxzecrB8 -TUe2BnQKOs9vr2cCACpFFcOmPkM0Drtjctr1QHm1tYSqRFRf9VcV5tfC3P8QqoK4 -ONjtLPHc9x5NE1uK/FMCAwEAAaOCAbMwggGvMA8GA1UdEwEB/wQFMAMBAf8wDgYD -VR0PAQH/BAQDAgEGMIIBBAYDVR0gBIH8MIH5MIH2Bg0rBgEEAb4/AgEKAQECMIHk -MIGaBggrBgEFBQcCAjCBjRqBikNlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmll -IHogZG9rdW1lbnRlbTogIlBvbGl0eWthIENlcnR5ZmlrYWNqaSBkbGEgUm9vdENB -Ii4gQ2VydHlmaWthdCB3eXN0YXdpb255IHByemV6IFJvb3RDQSB3IGhpZXJhcmNo -aWkgQ0MgU2lnbmV0LjBFBggrBgEFBQcCARY5aHR0cDovL3d3dy5zaWduZXQucGwv -cmVwb3p5dG9yaXVtL2Rva3VtZW50eS9wY19yb290Y2EudHh0MEQGA1UdHwQ9MDsw -OaA3oDWGM2h0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9yb290Y2Ev -cm9vdGNhLmNybDAfBgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAdBgNV -HQ4EFgQUXvthcPHlH5BgGhlMErJNXWlhlgAwDQYJKoZIhvcNAQEFBQADggEBACIc -e95Mvn710KCAISA0CuHD4aznTU6pLoCDShW47OR+GTpJUm1coTcUqlBHV9mra4VF -rBcBuOkHZoBLq/jmE0QJWnpSEULDcH9J3mF0nqO9SM+mWyJGdsJF/XU/7smummgj -MNQXwzQTtWORF+6v5KUbWX85anO2wR+M6YTBWC55zWpWi4RG3vkHFs5Ze2oFJTlp -uxw9ZgxTnWlwI9QR2MvEhYIUMKMOWxw1nt0kKj+5TCNQQGh/VJJ1dsiroGh/io1D -OcePEhKz1Ag52y6Wf0nJJB9yk0sFakqZH18F7eQecQImgZyyeRtsG95leNugB3BX -WCW+KxwiBrtQTXv4dTE= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYT -AkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQ -TS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG -9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMB4XDTAyMTIxMzE0MjkyM1oXDTIw -MTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAM -BgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEO -MAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2 -LmZyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaI -s9z4iPf930Pfeo2aSVz2TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2 -xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCWSo7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4 -u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYyHF2fYPepraX/z9E0+X1b -F8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNdfrGoRpAx -Vs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGd -PDPQtQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNV -HSAEDjAMMAoGCCqBegF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAx -NjAfBgNVHSMEGDAWgBSjBS8YYFDCiQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUF -AAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RKq89toB9RlPhJy3Q2FLwV3duJ -L92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3QMZsyK10XZZOY -YLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg -Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2a -NjSaTFR+FwNIlQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R -0982gaEbeC9xs/FZTEYYKKuF0mBWWg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH/zCCB2igAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARwxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEzMDEGA1UECxMq -SVBTIENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTMwMQYD -VQQDEypJUFMgQ0EgQ2hhaW5lZCBDQXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx -HjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczAeFw0wMTEyMzExMTE0NTRa -Fw0yNTEyMjkxMTE0NTRaMIIBHDELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNl -bG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQg -cHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMu -ZXMgQy5JLkYuICBCLTYwOTI5NDUyMTMwMQYDVQQLEypJUFMgQ0EgQ2hhaW5lZCBD -QXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMzAxBgNVBAMTKklQUyBDQSBDaGFp -bmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3DQEJARYP -aXBzQG1haWwuaXBzLmVzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpOZZJ -iHAzKHzoV9xIki3eLXp56UjxFehnY+c+Dh1nUiVO0t//vmGMP6B2LTFfx9FBKRBi -kYcW7raIcSDi62Or0sAG5UUgG4ruGLE7XtCnnx4xjgbFZ4tTjdgi5Wh9GVhfP7Oo -9ahi8Eqao+alFbhvB6LD3xZZqM2j9cmD8GzYAQIDAQABo4IESzCCBEcwHQYDVR0O -BBYEFAeUqHBsCqTumbhV3S5MRXf2Nq+5MIIBTgYDVR0jBIIBRTCCAUGAFAeUqHBs -CqTumbhV3S5MRXf2Nq+5oYIBJKSCASAwggEcMQswCQYDVQQGEwJFUzESMBAGA1UE -CBMJQmFyY2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJ -bnRlcm5ldCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0Bt -YWlsLmlwcy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxMzAxBgNVBAsTKklQUyBDQSBD -aGFpbmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEzMDEGA1UEAxMqSVBT -IENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI -hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8E -BQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMG -CCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYB -BAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMw -EYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlwcy5lczBD -BglghkgBhvhCAQ0ENhY0Q2hhaW5lZCBDQSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkg -aHR0cHM6Ly93d3cuaXBzLmVzLzAqBglghkgBhvhCAQIEHRYbaHR0cHM6Ly93d3cu -aXBzLmVzL2lwczIwMDIvMDgGCWCGSAGG+EIBBAQrFilodHRwczovL3d3dy5pcHMu -ZXMvaXBzMjAwMi9pcHMyMDAyQ0FDLmNybDA9BglghkgBhvhCAQMEMBYuaHR0cHM6 -Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2b2NhdGlvbkNBQy5odG1sPzA6BglghkgB -hvhCAQcELRYraHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmVuZXdhbENBQy5o -dG1sPzA4BglghkgBhvhCAQgEKxYpaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIv -cG9saWN5Q0FDLmh0bWwwbwYDVR0fBGgwZjAvoC2gK4YpaHR0cHM6Ly93d3cuaXBz -LmVzL2lwczIwMDIvaXBzMjAwMkNBQy5jcmwwM6AxoC+GLWh0dHBzOi8vd3d3YmFj -ay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0FDLmNybDAvBggrBgEFBQcBAQQjMCEw -HwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQAD -gYEATiRvY2nro9B6QNgTOgojWSrXMKpXHa6hLRxL2GZPEFg059x2ERs3pw7RlJJZ -ctupZam06zvBnGfQL4ZhevXl6ST6RAAmOikuj8kbiFSgujjCJY1wv5/7zzgBWzdL -NzqKC18p1T2KZa8B2qKfQCqzV/J3fgI/725+9ekqKNLiE5Q= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc -MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj -IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB -IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE -RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl -U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 -IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU -ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC -QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr -rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S -NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc -QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH -txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP -BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC -AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp -tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa -IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl -6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ -xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU -Cm26OWMohpLzGITY+9HPBVZkVw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFaDCCBFCgAwIBAgIQO1nHe81bV569N1KsdrSqGjANBgkqhkiG9w0BAQUFADBi -MRIwEAYDVQQKEwliZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENB -czEvMC0GA1UEAxMmYmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1wbGVtZW50YXRp -b24wHhcNMDIwNDExMTExODEzWhcNMjIwNDEyMTEwNzI1WjBiMRIwEAYDVQQKEwli -ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEvMC0GA1UEAxMm -YmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1wbGVtZW50YXRpb24wggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkujQwCY5X0LkGLG9uJIAiv11DpvpPrILn -HGhwhRujbrWqeNluB0s/6d/16uhUoWGKDi9pdRi3DOUUjXFumLhV/AyV0Jtu4S2I -1DpAa5LxmZZk3tv/ePTulh1HiXzUvrmIdyM6CeYEnm2qXtLIvZpOGd+J6lsOfsPk -tPDgaTuID0GQ+NRxQyTBjyZLO1bp/4xsN+lFrYWMU8NghpBKlsmzVLC7F/AcRdnU -GxlkVgoZ98zh/4avflherHqQH8koOUV7orbHnB/ahdQhhlkwk75TMzf270HPM8er -cmsl9fNTGwxMLvF1S++gh/f+ihXQbNXL+WhTuXAVE8L1LvtDNXUtAgMBAAGjggIY -MIICFDAMBgNVHRMEBTADAQH/MIIBtQYDVR0gBIIBrDCCAagwggGkBg8rBgEEAbE+ -AAADCSiDkTEwggGPMEEGCCsGAQUFBwIBFjVodHRwOi8vd3d3LmJldHJ1c3RlZC5j -b20vcHJvZHVjdHNfc2VydmljZXMvaW5kZXguaHRtbDCCAUgGCCsGAQUFBwICMIIB -OhqCATZSZWxpYW5jZSBvbiBvciB1c2Ugb2YgdGhpcyBDZXJ0aWZpY2F0ZSBjcmVh -dGVzIGFuIGFja25vd2xlZGdtZW50IGFuZCBhY2NlcHRhbmNlIG9mIHRoZSB0aGVu -IGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNl -LCB0aGUgQ2VydGlmaWNhdGlvbiBQcmFjdGljZSBTdGF0ZW1lbnQgYW5kIHRoZSBS -ZWx5aW5nIFBhcnR5IEFncmVlbWVudCwgd2hpY2ggY2FuIGJlIGZvdW5kIGF0IHRo -ZSBiZVRSVVNUZWQgd2ViIHNpdGUsIGh0dHA6Ly93d3cuYmV0cnVzdGVkLmNvbS9w -cm9kdWN0c19zZXJ2aWNlcy9pbmRleC5odG1sMAsGA1UdDwQEAwIBBjAfBgNVHSME -GDAWgBSp7BR++dlDzFMrFK3P9/BZiUHNGTAdBgNVHQ4EFgQUqewUfvnZQ8xTKxSt -z/fwWYlBzRkwDQYJKoZIhvcNAQEFBQADggEBANuXsHXqDMTBmMpWBcCorSZIry0g -6IHHtt9DwSwddUvUQo3neqh03GZCWYez9Wlt2ames30cMcH1VOJZJEnl7r05pmuK -mET7m9cqg5c0Lcd9NUwtNLg+DcTsiCevnpL9UGGCqGAHFFPMZRPB9kdEadIxyKbd -LrML3kqNWz2rDcI1UqJWN8wyiyiFQpyRQHpwKzg21eFzGh/l+n5f3NacOzDq28Bb -J1zTcwfBwvNMm2+fG8oeqqg4MwlYsq78B+g23FW6L09A/nq9BqaBwZMifIYRCgZ3 -SK41ty8ymmFei74pnykkiFY5LKjSq5YDWtRIn7lAhAuYaPsBQ9Yb4gmxlxw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u -ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc -KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u -ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 -MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE -ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j -b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF -bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg -U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA -A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ -I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 -wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC -AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb -oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 -BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p -dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk -MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp -b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu -dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 -MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi -E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa -MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI -hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN -95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd -2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEUzCCAzugAwIBAgIDAOJDMA0GCSqGSIb3DQEBBQUAMIHPMQswCQYDVQQGEwJB -VDGBizCBiAYDVQQKHoGAAEEALQBUAHIAdQBzAHQAIABHAGUAcwAuACAAZgD8AHIA -IABTAGkAYwBoAGUAcgBoAGUAaQB0AHMAcwB5AHMAdABlAG0AZQAgAGkAbQAgAGUA -bABlAGsAdAByAC4AIABEAGEAdABlAG4AdgBlAHIAawBlAGgAcgAgAEcAbQBiAEgx -GDAWBgNVBAsTD0EtVHJ1c3QtUXVhbC0wMTEYMBYGA1UEAxMPQS1UcnVzdC1RdWFs -LTAxMB4XDTA0MTEzMDIzMDAwMFoXDTE0MTEzMDIzMDAwMFowgc8xCzAJBgNVBAYT -AkFUMYGLMIGIBgNVBAoegYAAQQAtAFQAcgB1AHMAdAAgAEcAZQBzAC4AIABmAPwA -cgAgAFMAaQBjAGgAZQByAGgAZQBpAHQAcwBzAHkAcwB0AGUAbQBlACAAaQBtACAA -ZQBsAGUAawB0AHIALgAgAEQAYQB0AGUAbgB2AGUAcgBrAGUAaAByACAARwBtAGIA -SDEYMBYGA1UECxMPQS1UcnVzdC1RdWFsLTAxMRgwFgYDVQQDEw9BLVRydXN0LVF1 -YWwtMDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmhgdxIbxTGEOH -fXGiewI3NFldAWKFWfLofO+5I1UbvA5avt7IgsGXz/tI/f5HGUbascI0i7xG0tqV -lA5ctQgLRqxgxHtgTkMcqsAEYdsz3LZsCdXO1QrvEBGLTSABdxiL/gSWJ6z77CSw -x7Xg02HwxPV82cjGkSF3ENGJntuIAAnRDWn/ORHjFatNRymoMbHaOEZXSGhf7Y5F -rrHEqGyi9E6sv784De/T1aTvskn8cWeUmDzv//omiG/a/V9KQex/61XN8OthUQVn -X+u/liL2NKx74I2C/GgHX5B0WkPNqsSOgmlvJ/cKuT0PveUgVFDAA0oYBgcE1KDM -lBbN0kmPAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECEs8jB2F -6W+tMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAIUusmJzMJRiQ -8TAHrJAOelfuWoTGcqdIv7Tys/fNl2yF2fjvHT8J01aKialFVpbVeQ2XKb1O2bHO -QYAKgsdZ2jZ/sdL2UVFRTHmidLu6PdgWCBRhJYQELQophO9QVvfhAA0TwbESYqTz -+nlI5Gr7CZe8f6HEmhJmCtUQsdQCufGglRh4T+tIGiNGcnyVEHZ93mSVepFr1VA2 -9CTRPteuGjA81jeAz9peYiFE1CXvxK9cJiv0BcALFLWmADCoRLzIRZhA+sAwYUmw -M1rqVCPA3kBQvIC95tyQvNy2dG0Vs+O6PwLaNX/suSlElQ06X2l1VwMaYb4vZKFq -N0bOhBXEVg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC -VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ -cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ -BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt -VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D -0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 -ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G -A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs -aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I -flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV -BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln -biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF -MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT -d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 -76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ -bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c -6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE -emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd -MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt -MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y -MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y -FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi -aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM -gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB -qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 -lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn -8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov -L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 -45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO -UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 -O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC -bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv -GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a -77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC -hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 -92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp -Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w -ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt -Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl -MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe -U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX -DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy -dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj -YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV -OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr -zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM -VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ -hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO -ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw -awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs -OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 -DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF -coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc -okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 -t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy -1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ -SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDyzCCArOgAwIBAgIDAOJIMA0GCSqGSIb3DQEBBQUAMIGLMQswCQYDVQQGEwJB -VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp -bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRgwFgYDVQQLDA9BLVRydXN0LVF1 -YWwtMDIxGDAWBgNVBAMMD0EtVHJ1c3QtUXVhbC0wMjAeFw0wNDEyMDIyMzAwMDBa -Fw0xNDEyMDIyMzAwMDBaMIGLMQswCQYDVQQGEwJBVDFIMEYGA1UECgw/QS1UcnVz -dCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy -a2VociBHbWJIMRgwFgYDVQQLDA9BLVRydXN0LVF1YWwtMDIxGDAWBgNVBAMMD0Et -VHJ1c3QtUXVhbC0wMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJaR -q9eOsFm4Ab20Hq2Z/aH86gyWa48uSUjY6eQkguHYuszr3gdcSMYZggFHQgnhfLmf -ro/27l5rqKhWiDhWs+b+yZ1PNDhRPJy+86ycHMg9XJqErveULBSyZDdgjhSwOyrN -ibUir/fkf+4sKzP5jjytTKJXD/uCxY4fAd9TjMEVpN3umpIS0ijpYhclYDHvzzGU -833z5Dwhq5D8bc9jp8YSAHFJ1xzIoO1jmn3jjyjdYPnY5harJtHQL73nDQnfbtTs -5ThT9GQLulrMgLU4WeyAWWWEMWpfVZFMJOUkmoOEer6A8e5fIAeqdxdsC+JVqpZ4 -CAKel/Arrlj1gFA//jsCAwEAAaM2MDQwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4E -CgQIQj0rJKbBRc4wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBG -yxFjUA2bPkXUSC2SfJ29tmrbiLKal+g6a9M8Xwd+Ejo+oYkNP6F4GfeDtAXpm7xb -9Ly8lhdbHcpRhzCUQHJ1tBCiGdLgmhSx7TXjhhanKOdDgkdsC1T+++piuuYL72TD -gUy2Sb1GHlJ1Nc6rvB4fpxSDAOHqGpUq9LWsc3tFkXqRqmQVtqtR77npKIFBioc6 -2jTBwDMPX3hDJDR1DSPc6BnZliaNw2IHdiMQ0mBoYeRnFdq+TyDKsjmJOOQPLzzL -/saaw6F891+gBjLFEFquDyR73lAPJS279R3csi8WWk4ZYUC/1V8H3Ktip/J6ac8e -qhLCbmJ81Lo92JGHz/ot ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEXzCCA0egAwIBAgIBATANBgkqhkiG9w0BAQUFADCB0DELMAkGA1UEBhMCRVMx -SDBGBgNVBAoTP0laRU5QRSBTLkEuIC0gQ0lGIEEtMDEzMzcyNjAtUk1lcmMuVml0 -b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFCMEAGA1UEBxM5QXZkYSBkZWwgTWVk -aXRlcnJhbmVvIEV0b3JiaWRlYSAzIC0gMDEwMTAgVml0b3JpYS1HYXN0ZWl6MRMw -EQYDVQQDEwpJemVucGUuY29tMR4wHAYJKoZIhvcNAQkBFg9JbmZvQGl6ZW5wZS5j -b20wHhcNMDMwMTMwMjMwMDAwWhcNMTgwMTMwMjMwMDAwWjCB0DELMAkGA1UEBhMC -RVMxSDBGBgNVBAoTP0laRU5QRSBTLkEuIC0gQ0lGIEEtMDEzMzcyNjAtUk1lcmMu -Vml0b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFCMEAGA1UEBxM5QXZkYSBkZWwg -TWVkaXRlcnJhbmVvIEV0b3JiaWRlYSAzIC0gMDEwMTAgVml0b3JpYS1HYXN0ZWl6 -MRMwEQYDVQQDEwpJemVucGUuY29tMR4wHAYJKoZIhvcNAQkBFg9JbmZvQGl6ZW5w -ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1btoCXXhp3xIW -D+Bxl8nUCxkyiazWfpt0e68t+Qt9+lZjKZSdEw2Omj4qvr+ovRmDXO3iWpWVOWDl -3JHJjAzFCe8ZEBNDH+QNYwZHmPBaMYFOYFdbAFVHWvys152C308hcFJ6xWWGmjvl -2eMiEl9P2nR2LWue368DCu+ak7j3gjAXaCOdP1a7Bfr+RW3X2SC5R4Xyp8iHlL5J -PHJD/WBkLrezwzQPdACw8m9EG7q9kUwlNpL32mROujS3ZkT6mQTzJieLiE3X04s0 -uIUqVkk5MhjcHFf7al0N5CzjtTcnXYJKN2Z9EDVskk4olAdGi46eSoZXbjUOP5gk -Ej6wVZAXAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG -MB0GA1UdDgQWBBTqVk/sPIOhFIh4gbIrBSLAB0FbQjANBgkqhkiG9w0BAQUFAAOC -AQEAYp7mEzzhw6o5Hf5+T5kcI+t4BJyiIWy7vHlLs/G8dLYXO81aN/Mzg928eMTR -TxxYZL8dd9uwsJ50TVfX6L0R4Dyw6wikh3fHRrat9ufXi63j5K91Ysr7aXqnF38d -iAgHYkrwC3kuxHBb9C0KBz6h8Q45/KCyN7d37wWAq38yyhPDlaOvyoE6bdUuK5hT -m5EYA5JmPyrhQ1moDOyueWBAjxzMEMj+OAY1H90cLv6wszsqerxRrdTOHBdv7MjB -EIpvEEQkXUxVXAzFuuT6m2t91Lfnwfl/IvljHaVC7DlyyhRYHD6D4Rx+4QKp4tWL -vpw6LkI+gKNJ/YdMCsRZQzEEFA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh -MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE -YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 -MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo -ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg -MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN -ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA -PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w -wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi -EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY -avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ -YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE -sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h -/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 -IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy -OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P -TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ -HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER -dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf -ReYNnyicsbkqWletNw+vHX/bvZ8= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUx -ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 -b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQD -EylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikgVGFudXNpdHZhbnlraWFkbzAeFw05 -OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYDVQQGEwJIVTERMA8G -A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh -Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5l -dExvY2sgVXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqG -SIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xK -gZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX -iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvc -Q7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8E -BAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1G -SUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFu -b3MgU3pvbGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBh -bGFwamFuIGtlc3p1bHQuIEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExv -Y2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGln -aXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0 -IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh -c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGph -biBhIGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJo -ZXRvIGF6IGVsbGVub3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBP -UlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmlj -YXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBo -dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNA -bmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06 -sPgzTEdM43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXa -n3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKS -NitjrFgBazMpUIaD8QFI ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICZzCCAdCgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJVUzEY -MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT -A1BLSTEcMBoGA1UEAxMTRG9EIENMQVNTIDMgUm9vdCBDQTAeFw0wMDA1MTkxMzEz -MDBaFw0yMDA1MTQxMzEzMDBaMGExCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMu -IEdvdmVybm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRwwGgYDVQQD -ExNEb0QgQ0xBU1MgMyBSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB -gQC1MP5kvurMbe2BLPd/6Rm6DmlqKOGpqcuVWB/x5pppU+CIP5HFUbljl6jmIYwT -XjY8qFf6+HAsTGrLvzCnTBbkMlz4ErBR+BZXjS+0TfouqJToKmHUVw1Hzm4sL36Y -Z8wACKu2lhY1woWR5VugCsdmUmLzYXWVF668KlYppeArUwIDAQABoy8wLTAdBgNV -HQ4EFgQUbJyl8FyPbUGNxBc7kFfCD6PNbf4wDAYDVR0TBAUwAwEB/zANBgkqhkiG -9w0BAQUFAAOBgQCvcUT5lyPMaGmMQwdBuoggsyIAQciYoFUczT9usZNcrfoYmrsc -c2/9JEKPh59Rz76Gn+nXikhPCNlplKw/5g8tlw8ok3ZPYt//oM1h+KaGDDE0INx/ -L6j7Ob6V7jhZAmLB3mwVT+DfnbvkeXMk/WNklfdKqJkfSGWVx3u/eDLneg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs -IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 -MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h -bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v -dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt -H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 -uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX -mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX -a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN -E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 -WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD -VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 -Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU -cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx -IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN -AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH -YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 -6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC -Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX -c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a -mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDNjCCAp+gAwIBAgIQNhIilsXjOKUgodJfTNcJVDANBgkqhkiG9w0BAQUFADCB -zjELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ -Q2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UE -CxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhh -d3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNl -cnZlckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIxMDEwMTIzNTk1OVow -gc4xCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcT -CUNhcGUgVG93bjEdMBsGA1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNV -BAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRo -YXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1z -ZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2 -aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560 -ZXUCTe/LCaIhUdib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j -+ao6hnO2RlNYyIkFvYMRuHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/ -BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBlkKyID1bZ5jA01CbH0FDxkt5r1DmI -CSLGpmODA/eZd9iy5Ri4XWPz1HP7bJyZePFLeH0ZJMMrAoT4vCLZiiLXoPxx7JGH -IPG47LHlVYCsPVLIOQ7C8MAFT9aCdYy9X9LcdpoFEsmvcsPcJX6kTY4XpeCHf+Ga -WuFg3GQjPEIuTQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICXDCCAcWgAwIBAgIQCgEBAQAAAnwAAAALAAAAAjANBgkqhkiG9w0BAQUFADA6 -MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp -dHkgMTAyNCBWMzAeFw0wMTAyMjIyMTAxNDlaFw0yNjAyMjIyMDAxNDlaMDoxGTAX -BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAx -MDI0IFYzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDV3f5mCc8kPD6ugU5O -isRpgFtZO9+5TUzKtS3DJy08rwBCbbwoppbPf9dYrIMKo1W1exeQFYRMiu4mmdxY -78c4pqqv0I5CyGLXq6yp+0p9v+r+Ek3d/yYtbzZUaMjShFbuklNhCbM/OZuoyZu9 -zp9+1BlqFikYvtc6adwlWzMaUQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBTEwBykB5T9zU0B1FTapQxf3q4FWjAd -BgNVHQ4EFgQUxMAcpAeU/c1NAdRU2qUMX96uBVowDQYJKoZIhvcNAQEFBQADgYEA -Py1q4yZDlX2Jl2X7deRyHUZXxGFraZ8SmyzVWujAovBDleMf6XbN3Ou8k6BlCsdN -T1+nr6JGFLkM88y9am63nd4lQtBU/55oc2PcJOsiv6hy8l4A4Q1OOkNumU4/iXgD -mMrzVcydro7BqkWY+o8aoI2II/EVQQ2lRj6RP4vr93E= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV -BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1 -c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx -MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg -R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD -VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR -JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T -fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu -jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z -wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ -fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD -VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G -CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1 -7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn -8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs -ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT -ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/ -2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH/zCCB2igAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm -SVBTIENBIENMQVNFQTMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT -JklQUyBDQSBDTEFTRUEzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI -hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjMxMTEyMzU5WhcNMjUxMjI5 -MTEyMzU5WjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw -gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMFh+lWUEmnBK5F6da6IALvvPO6f -MWYw9LFAmwJsjcdKTVElPugUKLwgPLHxjO19kdmXIqPVzGOxq9krIwvdppffBYRU -Fro6y8xja40gpdaeBXFGdVj19mR7C2adPoeVPTy1OTdSVLsWF8W/rdiLMy/p+PrV -gTP/t56Fpu9MOeDjAgMBAAGjggRbMIIEVzAdBgNVHQ4EFgQU/J6FGtwGJXEh8C+L -ElXQxYDuBq4wggFGBgNVHSMEggE9MIIBOYAU/J6FGtwGJXEh8C+LElXQxYDuBq6h -ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC -AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF -BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB -BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg -hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud -EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBDBglghkgBhvhCAQ0ENhY0Q0xBU0VBMyBD -QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cHM6Ly93d3cuaXBzLmVzLzAqBglg -hkgBhvhCAQIEHRYbaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDwGCWCGSAGG -+EIBBAQvFi1odHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VB -My5jcmwwQQYJYIZIAYb4QgEDBDQWMmh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAy -L3Jldm9jYXRpb25DTEFTRUEzLmh0bWw/MD4GCWCGSAGG+EIBBwQxFi9odHRwczov -L3d3dy5pcHMuZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0VBMy5odG1sPzA8BglghkgB -hvhCAQgELxYtaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VB -My5odG1sMHcGA1UdHwRwMG4wM6AxoC+GLWh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMy -MDAyL2lwczIwMDJDTEFTRUEzLmNybDA3oDWgM4YxaHR0cHM6Ly93d3diYWNrLmlw -cy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRUEzLmNybDAvBggrBgEFBQcBAQQjMCEw -HwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQAD -gYEAGG8JN0Ca0pQR0X/Lg33qtKfi2JPe2iRqdRswDoL3CTn+bRN20V/wbKDAwyxc -7eJOroysytPkEF4wZhipaKCjaWJROZGCeU1jM7mZe9pQPzeofT//VLi8zKaUA4lZ -BvYI44gntZQoaFxJna5NHHde+mbbPYlHb8c6g0mf9S3tODs= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDXTCCAkWgAwIBAgIDAOJCMA0GCSqGSIb3DQEBBQUAMFUxCzAJBgNVBAYTAkFU -MRAwDgYDVQQKEwdBLVRydXN0MRkwFwYDVQQLExBBLVRydXN0LW5RdWFsLTAxMRkw -FwYDVQQDExBBLVRydXN0LW5RdWFsLTAxMB4XDTA0MTEzMDIzMDAwMFoXDTE0MTEz -MDIzMDAwMFowVTELMAkGA1UEBhMCQVQxEDAOBgNVBAoTB0EtVHJ1c3QxGTAXBgNV -BAsTEEEtVHJ1c3QtblF1YWwtMDExGTAXBgNVBAMTEEEtVHJ1c3QtblF1YWwtMDEw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD/9RyAEZ6eHmhYzNJ328f0 -jmdSUFi6EqRqOxb3jHNPTIpK82CR6z5lmSnZQNUuCPD+htbNZffd2DKVB06NOyZ1 -2zcOMCgj4GtkZoqE0zPpPT3bpoE55nkZZe/qWEX/64wz/L/4EdkvKDSKG/UsP75M -tmCVY5m2Eg73RVFRz4ccBIMpHel4lzEqSkdDtZOY5fnkrE333hx67nxq21vY8Eyf -8O4fPQ5RtN8eohQCcPQ1z6ypU1R7N9jPRpnI+yzMOiwd3+QcKhHi1miCzo0pkOaB -1CwmfsTyNl8qU0NJUL9Ta6cea7WThwTiWol2yD88cd2cy388xpbNkfrCPmZNGLoV -AgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECE5ZzscCMocwMA4G -A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEA69I9R1hU9Gbl9vV7W7AH -QpUJAlFAvv2It/eY8p2ouQUPVaSZikaKtAYrCD/arzfXB43Qet+dM6CpHsn8ikYR -vQKePjXv3Evf+C1bxwJAimcnZV6W+bNOTpdo8lXljxkmfN+Z5S+XzvK2ttUtP4Et -YOVaxHw2mPMNbvDeY+foJkiBn3KYjGabMaR8moZqof5ofj4iS/WyamTZti6v/fKx -n1vII+/uWkcxV5DT5+r9HLon0NYF0Vg317Wh+gWDV59VZo+dcwJDb+keYqMFYoqp -77SGkZGu41S8NGYkQY3X9rNHRkDbLfpKYDmy6NanpOE1EHW1/sNSFAs43qZZKJEQ -xg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDMDCCApmgAwIBAgIQDY4VEuGsu3eNOOMk34ww8jANBgkqhkiG9w0BAQUFADCB -yzELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ -Q2FwZSBUb3duMRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3Rl -IFBlcnNvbmFsIEJhc2ljIENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNp -Y0B0aGF3dGUuY29tMB4XDTk2MDEwMTAwMDAwMFoXDTIxMDEwMTIzNTk1OVowgcsx -CzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNh -cGUgVG93bjEaMBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0Nl -cnRpZmljYXRpb24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQ -ZXJzb25hbCBCYXNpYyBDQTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNA -dGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+C -FeZIlDWmWr5vQvoPR+53dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeV -oQxN2jSQHReJl+A1OFdKwPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlW -Cy4cgNrx454p7xS9CkT7G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB -/zANBgkqhkiG9w0BAQUFAAOBgQCIO/64+XpCRhGgpKJkhc1IHJzVilHNL8F9sQfP -1wHeMj+W5IT+0V6tDH4OY0lqDhDkl9A/xacp2aZTHkseP1T6wIQ1c+qRqdxdk1cF -BgwHua8LRDmIIaDugnOpRi9pbCV0qc3fp9f9hTAElDVKpxszJCxEFu0KxN+AqmUa -v3Em8A== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs -ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw -MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 -b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj -aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp -Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg -nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 -HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N -Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN -dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 -HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G -CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU -sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 -4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg -8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K -pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 -mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEgzCCA+ygAwIBAgIEOJ725DANBgkqhkiG9w0BAQQFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9HQ0NBX0NQUyBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVu -dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDcxNjE2NDBaFw0yMDAy -MDcxNjQ2NDBaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0dDQ0FfQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDIwMDAgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCTdLS25MVL1qFof2LV7PdRV7Ny -Spj10InJrWPNTTVRaoTUrcloeW+46xHbh65cJFET8VQlhK8pK5/jgOLZy93GRUk0 -iJBeAZfv6lOm3fzB3ksqJeTpNfpVBQbliXrqpBFXO/x8PTbNZzVtpKklWb1m9fkn -5JVn1j+SgF7yNH0rhQIDAQABo4IBnjCCAZowEQYJYIZIAYb4QgEBBAQDAgAHMIHd -BgNVHR8EgdUwgdIwgc+ggcyggcmkgcYwgcMxFDASBgNVBAoTC0VudHJ1c3QubmV0 -MUAwPgYDVQQLFDd3d3cuZW50cnVzdC5uZXQvR0NDQV9DUFMgaW5jb3JwLiBieSBy -ZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5l -dCBMaW1pdGVkMTMwMQYDVQQDEypFbnRydXN0Lm5ldCBDbGllbnQgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMDAy -MDcxNjE2NDBagQ8yMDIwMDIwNzE2NDY0MFowCwYDVR0PBAQDAgEGMB8GA1UdIwQY -MBaAFISLdP3FjcD/J20gN0V8/i3OutN9MB0GA1UdDgQWBBSEi3T9xY3A/ydtIDdF -fP4tzrrTfTAMBgNVHRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4w -AwIEkDANBgkqhkiG9w0BAQQFAAOBgQBObzWAO9GK9Q6nIMstZVXQkvTnhLUGJoMS -hAusO7JE7r3PQNsgDrpuFOow4DtifH+La3xKp9U1PL6oXOpLu5OOgGarDyn9TS2/ -GpsKkMWr2tGzhtQvJFJcem3G8v7lTRowjJDyutdKPkN+1MhQGof4T4HHdguEOnKd -zmVml64mXg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV -UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL -EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ -BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x -ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg -bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ -j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV -Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG -SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx -JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI -RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw -MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5 -fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i -+DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG -SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN -QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+ -gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 -nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex -t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz -SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG -BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ -rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ -NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH -BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv -MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE -p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y -5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK -WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ -4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N -hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIESzCCAzOgAwIBAgIJAJigUTEEXRQpMA0GCSqGSIb3DQEBBQUAMHYxCzAJBgNV -BAYTAkRFMQ8wDQYDVQQIEwZIZXNzZW4xDjAMBgNVBAcTBUZ1bGRhMRAwDgYDVQQK -EwdEZWJjb25mMRMwEQYDVQQDEwpEZWJjb25mIENBMR8wHQYJKoZIhvcNAQkBFhBq -b2VyZ0BkZWJpYW4ub3JnMB4XDTA1MTEwNTE3NTUxNFoXDTE1MTEwMzE3NTUxNFow -djELMAkGA1UEBhMCREUxDzANBgNVBAgTBkhlc3NlbjEOMAwGA1UEBxMFRnVsZGEx -EDAOBgNVBAoTB0RlYmNvbmYxEzARBgNVBAMTCkRlYmNvbmYgQ0ExHzAdBgkqhkiG -9w0BCQEWEGpvZXJnQGRlYmlhbi5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQCvbOo0SrIwI5IMlsshH8WF3dHB9r9JlSKhMPaybawa1EyvZspMQ3wa -F5qxNf3Sj+NElEmjseEqvCZiIIzqwerHu0Qw62cDYCdCd2+Wb5m0bPYB5CGHiyU1 -eNP0je42O0YeXG2BvUujN8AviocVo39X2YwNQ0ryy4OaqYgm2pRlbtT2ESbF+SfV -Y2iqQj/f8ymF+lHo/pz8tbAqxWcqaSiHFAVQJrdqtFhtoodoNiE3q76zJoUkZTXB -k60Yc3MJSnatZCpnsSBr/D7zpntl0THrUjjtdRWCjQVhqfhM1yZJV+ApbLdheFh0 -ZWlSxdnp25p0q0XYw/7G92ELyFDfBUUNAgMBAAGjgdswgdgwHQYDVR0OBBYEFMuV -dFNb4mCWUFbcP5LOtxFLrEVTMIGoBgNVHSMEgaAwgZ2AFMuVdFNb4mCWUFbcP5LO -txFLrEVToXqkeDB2MQswCQYDVQQGEwJERTEPMA0GA1UECBMGSGVzc2VuMQ4wDAYD -VQQHEwVGdWxkYTEQMA4GA1UEChMHRGViY29uZjETMBEGA1UEAxMKRGViY29uZiBD -QTEfMB0GCSqGSIb3DQEJARYQam9lcmdAZGViaWFuLm9yZ4IJAJigUTEEXRQpMAwG -A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGZXxHg4mnkvilRIM1EQfGdY -S5b/WcyF2MYSTeTvK4aIB6VHwpZoZCnDGj2m2D3CkHT0upAD9o0zM1tdsfncLzV+ -mDT/jNmBtYo4QXx5vEPwvEIcgrWjwk7SyaEUhZjtolTkHB7ACl0oD0r71St4iEPR -qTUCEXk2E47bg1Fz58wNt/yo2+4iqiRjg1XCH4evkQuhpW+dTZnDyFNqwSYZapOE -TBA+9zBb6xD1KM2DdY7r4GiyYItN0BKLfuWbh9LXGbl1C+f4P11g+m2MPiavIeCe -1iazG5pcS3KoTLACsYlEX24TINtg4kcuS81XdllcnsV3Kdts0nIqPj6uhTTZD0k= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh -c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 -NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD -VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp -bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB -jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N -H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR -4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN -BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo -EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5 -FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx -lA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD -VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv -bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv -b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV -UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU -cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds -b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH -iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS -r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 -04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r -GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 -3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P -lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY -MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t -dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 -WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD -VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 -9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ -DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 -Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N -QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ -xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G -A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG -kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr -Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 -Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU -JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot -RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID2TCCAsGgAwIBAgIDAjbQMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMTAwMjE5MjIzOTI2WhcNMjAwMjE4MjIzOTI2WjBAMQswCQYDVQQG -EwJVUzEXMBUGA1UEChMOR2VvVHJ1c3QsIEluYy4xGDAWBgNVBAMTD0dlb1RydXN0 -IFNTTCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJCzgMHk5Uat -cGA9uuUU3Z6KXot1WubKbUGlI+g5hSZ6p1V3mkihkn46HhrxJ6ujTDnMyz1Hr4Gu -FmpcN+9FQf37mpc8oEOdxt8XIdGKolbCA0mEEoE+yQpUYGa5jFTk+eb5lPHgX3UR -8im55IaisYmtph6DKWOy8FQchQt65+EuDa+kvc3nsVrXjAVaDktzKIt1XTTYdwvh -dGLicTBi2LyKBeUxY0pUiWozeKdOVSQdl+8a5BLGDzAYtDRN4dgjOyFbLTAZJQ50 -96QhS6CkIMlszZhWwPKoXz4mdaAN+DaIiixafWcwqQ/RmXAueOFRJq9VeiS+jDkN -d53eAsMMvR8CAwEAAaOB2TCB1jAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFEJ5 -VBthzVUrPmPVPEhX9Z/7Rc5KMB8GA1UdIwQYMBaAFMB6mGiNifurBWQMEX2qfWW4 -ysxOMBIGA1UdEwEB/wQIMAYBAf8CAQAwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDov -L2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwNAYIKwYBBQUHAQEE -KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5nZW90cnVzdC5jb20wDQYJKoZI -hvcNAQEFBQADggEBANTvU4ToGr2hiwTAqfVfoRB4RV2yV2pOJMtlTjGXkZrUJPji -J2ZwMZzBYlQG55cdOprApClICq8kx6jEmlTBfEx4TCtoLF0XplR4TEbigMMfOHES -0tdT41SFULgCy+5jOvhWiU1Vuy7AyBh3hjELC3DwfjWDpCoTZFZnNF0WX3OsewYk -2k9QbSqr0E1TQcKOu3EDSSmGGM8hQkx0YlEVxW+o78Qn5Rsz3VqI138S0adhJR/V -4NwdzxoQ2KDLX4z6DOW/cf/lXUQdpj6HR/oaToODEj+IZpWYeZqF6wJHzSXj8gYE -TpnKXKBuervdo5AaRTPvvz7SBMS24CqFZUE+ENQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDdjCCAl6gAwIBAgIEOhsEBTANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJE -SzEMMAoGA1UEChMDS01EMQ8wDQYDVQQLEwZLTUQtQ0ExIzAhBgNVBAMTGktNRC1D -QSBLdmFsaWZpY2VyZXQgUGVyc29uMB4XDTAwMTEyMTIzMjQ1OVoXDTE1MTEyMjIz -MjQ1OVowUTELMAkGA1UEBhMCREsxDDAKBgNVBAoTA0tNRDEPMA0GA1UECxMGS01E -LUNBMSMwIQYDVQQDExpLTUQtQ0EgS3ZhbGlmaWNlcmV0IFBlcnNvbjCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBANriF4Xd6yD7ZlBE317UBDObn+vRMVc6 -p3wNQODdEDJe2z1ncCz9NJvhoLGdOJhyg7VVPh0P2c+KZ9WI9mWOKZI2bp2WkLju -jCcxbhTrurY3Wfc6gwLBqqFV8wWgaZKmvVWizjw9Kyi25f3yX4fOho6Qq2lvVbub -tvVFXAd51GJ+/2Yed+a4Or2bz2RcqHS81B3pywsD4mgJR5xREv5jqPfwNP+V7bkc -X+pfO4kVhZ/V+8MSPdQHgcV/iB3wP2mwgWyIBNc1reBidGTiz8unnWu55hcNfsvt -LJbTs9OHhsR7naRuy+S402nDnD5vnONOFEsiHn46w+T0rtu7h6j4OvkCAwEAAaNW -MFQwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUeWLqmhI42Jxj7DifDsW+ -DlQhKD0wHwYDVR0jBBgwFoAUeWLqmhI42Jxj7DifDsW+DlQhKD0wDQYJKoZIhvcN -AQEFBQADggEBANML/P42OuJ9aUV/0fItuIyc1JhqWvSqn5bXj+9eyEegcp8bHLHY -42D1O+z0lNipdjYPSdMJ0wZOEUhr+150SdDQ1P/zQL8AUaLEBkRt7ZdzXPVH3PER -qnf9IrpYBknZKfCAoVchA6Rr9WU3Sd8bMoRfMLKg8c0M8G6EPwCTcOFriSkbtvNG -zd8r8I+WfUYIN/p8DI9JT9qfjVODnYPRMUm6KPvq27TsrGruKrqyaV94kWc8co8A -v3zFLeCtghvUiRBdx+8Q7m5t4CkuSr0WINrqjIPFW2QrM1r82y09Fd16RkqL4LOg -Lh6vB5KnTApv62rWdw7zWwYnjY6/vXYY1Aw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGCDCCA/CgAwIBAgIBATANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 -IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB -IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA -Y2FjZXJ0Lm9yZzAeFw0wNTEwMTQwNzM2NTVaFw0zMzAzMjgwNzM2NTVaMFQxFDAS -BgNVBAoTC0NBY2VydCBJbmMuMR4wHAYDVQQLExVodHRwOi8vd3d3LkNBY2VydC5v -cmcxHDAaBgNVBAMTE0NBY2VydCBDbGFzcyAzIFJvb3QwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCrSTURSHzSJn5TlM9Dqd0o10Iqi/OHeBlYfA+e2ol9 -4fvrcpANdKGWZKufoCSZc9riVXbHF3v1BKxGuMO+f2SNEGwk82GcwPKQ+lHm9WkB -Y8MPVuJKQs/iRIwlKKjFeQl9RrmK8+nzNCkIReQcn8uUBByBqBSzmGXEQ+xOgo0J -0b2qW42S0OzekMV/CsLj6+YxWl50PpczWejDAz1gM7/30W9HxM3uYoNSbi4ImqTZ -FRiRpoWSR7CuSOtttyHshRpocjWr//AQXcD0lKdq1TuSfkyQBX6TwSyLpI5idBVx -bgtxA+qvFTia1NIFcm+M+SvrWnIl+TlG43IbPgTDZCciECqKT1inA62+tC4T7V2q -SNfVfdQqe1z6RgRQ5MwOQluM7dvyz/yWk+DbETZUYjQ4jwxgmzuXVjit89Jbi6Bb -6k6WuHzX1aCGcEDTkSm3ojyt9Yy7zxqSiuQ0e8DYbF/pCsLDpyCaWt8sXVJcukfV -m+8kKHA4IC/VfynAskEDaJLM4JzMl0tF7zoQCqtwOpiVcK01seqFK6QcgCExqa5g -eoAmSAC4AcCTY1UikTxW56/bOiXzjzFU6iaLgVn5odFTEcV7nQP2dBHgbbEsPyyG -kZlxmqZ3izRg0RS0LKydr4wQ05/EavhvE/xzWfdmQnQeiuP43NJvmJzLR5iVQAX7 -6QIDAQABo4G/MIG8MA8GA1UdEwEB/wQFMAMBAf8wXQYIKwYBBQUHAQEEUTBPMCMG -CCsGAQUFBzABhhdodHRwOi8vb2NzcC5DQWNlcnQub3JnLzAoBggrBgEFBQcwAoYc -aHR0cDovL3d3dy5DQWNlcnQub3JnL2NhLmNydDBKBgNVHSAEQzBBMD8GCCsGAQQB -gZBKMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuQ0FjZXJ0Lm9yZy9pbmRleC5w -aHA/aWQ9MTAwDQYJKoZIhvcNAQEEBQADggIBAH8IiKHaGlBJ2on7oQhy84r3HsQ6 -tHlbIDCxRd7CXdNlafHCXVRUPIVfuXtCkcKZ/RtRm6tGpaEQU55tiKxzbiwzpvD0 -nuB1wT6IRanhZkP+VlrRekF490DaSjrxC1uluxYG5sLnk7mFTZdPsR44Q4Dvmw2M -77inYACHV30eRBzLI++bPJmdr7UpHEV5FpZNJ23xHGzDwlVks7wU4vOkHx4y/CcV -Bc/dLq4+gmF78CEQGPZE6lM5+dzQmiDgxrvgu1pPxJnIB721vaLbLmINQjRBvP+L -ivVRIqqIMADisNS8vmW61QNXeZvo3MhN+FDtkaVSKKKs+zZYPumUK5FQhxvWXtaM -zPcPEAxSTtAWYeXlCmy/F8dyRlecmPVsYGN6b165Ti/Iubm7aoW8mA3t+T6XhDSU -rgCvoeXnkm5OvfPi2RSLXNLrAWygF6UtEOucekq9ve7O/e0iQKtwOIj1CodqwqsF -YMlIBdpTwd5Ed2qz8zw87YC8pjhKKSRf/lk7myV6VmMAZLldpGJ9VzZPrYPvH5JT -oI53V93lYRE9IwCQTDz6o2CTBKOvNfYOao9PSmCnhQVsRqGP9Md246FZV/dxssRu -FFxtbUFm3xuTsdQAw+7Lzzw9IYCpX2Nl/N3gX6T0K/CFcUHUZyX7GrGXrtaZghNB -0m6lG5kngOcLqagA ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF8DCCA9igAwIBAgIPBuhGJy8fCo/RhFzjafbVMA0GCSqGSIb3DQEBBQUAMDgx -CzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXpl -bnBlLmNvbTAeFw0wNzEyMTMxMzA4MjdaFw0zNzEyMTMwODI3MjVaMDgxCzAJBgNV -BAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNv -bTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMnTesoPHqynhugWZWqx -whtFMnGV2f4QW8yv56V5AY+Jw8ryVXH3d753lPNypCxE2J6SmxQ6oeckkAoKVo7F -2CaU4dlI4S0+2gpy3aOZFdqBoof0e24md4lYrdbrDLJBenNubdt6eEHpCIgSfocu -ZhFjbFT7PJ1ywLwu/8K33Q124zrX97RovqL144FuwUZvXY3gTcZUVYkaMzEKsVe5 -o4qYw+w7NMWVQWl+dcI8IMVhulFHoCCQk6GQS/NOfIVFVJrRBSZBsLVNHTO+xAPI -JXzBcNs79AktVCdIrC/hxKw+yMuSTFM5NyPs0wH54AlETU1kwOENWocivK0bo/4m -tRXzp/yEGensoYi0RGmEg/OJ0XQGqcwL1sLeJ4VQJsoXuMl6h1YsGgEebL4TrRCs -tST1OJGh1kva8bvS3ke18byB9llrzxlT6Y0Vy0rLqW9E5RtBz+GGp8rQap+8TI0G -M1qiheWQNaBiXBZO8OOi+gMatCxxs1gs3nsL2xoP694hHwZ3BgOwye+Z/MC5TwuG -KP7Suerj2qXDR2kS4Nvw9hmL7Xtw1wLW7YcYKCwEJEx35EiKGsY7mtQPyvp10gFA -Wo15v4vPS8+qFsGV5K1Mij4XkdSxYuWC5YAEpAN+jb/af6IPl08M0w3719Hlcn4c -yHf/W5oPt64FRuXxqBbsR6QXAgMBAAGjgfYwgfMwgbAGA1UdEQSBqDCBpYEPaW5m -b0BpemVucGUuY29tpIGRMIGOMUcwRQYDVQQKDD5JWkVOUEUgUy5BLiAtIENJRiBB -MDEzMzcyNjAtUk1lcmMuVml0b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFDMEEG -A1UECQw6QXZkYSBkZWwgTWVkaXRlcnJhbmVvIEV0b3JiaWRlYSAxNCAtIDAxMDEw -IFZpdG9yaWEtR2FzdGVpejAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUHRxlDqjyJXu0kc/ksbHmvVV0bAUwDQYJKoZIhvcNAQEFBQAD -ggIBAMeBRm8hGE+gBe/n1bqXUKJg7aWSFBpSm/nxiEqg3Hh10dUflU7F57dp5iL0 -+CmoKom+z892j+Mxc50m0xwbRxYpB2iEitL7sRskPtKYGCwkjq/2e+pEFhsqxPqg -l+nqbFik73WrAGLRne0TNtsiC7bw0fRue0aHwp28vb5CO7dz0JoqPLRbEhYArxk5 -ja2DUBzIgU+9Ag89njWW7u/kwgN8KRwCfr00J16vU9adF79XbOnQgxCvv11N75B7 -XSus7Op9ACYXzAJcY9cZGKfsK8eKPlgOiofmg59OsjQerFQJTx0CCzl+gQgVuaBp -E8gyK+OtbBPWg50jLbJtooiGfqgNASYJQNntKE6MkyQP2/EeTXp6WuKlWPHcj1+Z -ggwuz7LdmMySlD/5CbOlliVbN/UShUHiGUzGigjB3Bh6Dx4/glmimj4/+eAJn/3B -kUtdyXvWton83x18hqrNA/ILUpLxYm9/h+qrdslsUMIZgq+qHfUgKGgu1fxkN0/P -pUTEvnK0jHS0bKf68r10OEMr3q/53NjgnZ/cPcqlY0S/kqJPTIAcuxrDmkoEVU3K -7iYLHL8CxWTTnn7S05EcS6L1HOUXHA0MUqORH5zwIe0ClG+poEnK6EOMxPQ02nwi -o8ZmPrgbBYhdurz3vOXcFD2nhqi2WVIhA16L4wTtSyoeo09Q ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICsDCCAhmgAwIBAgIQZ8jh6OO+HL38kTuOpiOHSTANBgkqhkiG9w0BAQUFADCB -izELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxML -RHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENl -cnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcN -OTcwMTAxMDAwMDAwWhcNMjEwMTAxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTAT -BgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNV -BAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNV -BAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0A -MIGJAoGBANYrWHhhRYZT6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u -6TqFJBU820cEY8OexJQaWt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522 -FOMjhdepQeBMpHmwKxqL8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzAR -MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAS+mqF4EF+3kKMZ/F -QfRWVKvpwuWXjhj+kckMPiZkyaFMJ2SnvQGTVXFuF0853BvcSTUQOSP/ypvIz2Y/ -3Ewa1IEGQlIf4SaxFhe65nByMUToTo1b5NP50OOPJWQx5yr4GIg2GlLFDUE1G2m3 -JvUXzMEZXkt8XOKDgJH6L/uatxY= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDtDCCApygAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJKUDEc -MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEOMAwGA1UECxMFTVBIUFQxJjAk -BgNVBAsTHU1QSFBUIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTAyMDMxNDA3 -NTAyNloXDTEyMDMxMzE0NTk1OVowYzELMAkGA1UEBhMCSlAxHDAaBgNVBAoTE0ph -cGFuZXNlIEdvdmVybm1lbnQxDjAMBgNVBAsTBU1QSFBUMSYwJAYDVQQLEx1NUEhQ -VCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAI3GUWlK9G9FVm8DhpKu5t37oxZbj6lZcFvEZY07YrYojWO657ub -z56WE7q/PI/6Sm7i7qYE+Vp80r6thJvfmn7SS3BENrRqiapSenhooYD12jIe3iZQ -2SXqx7WgYwyBGdQwGaYTijzbRFpgc0K8o4a99fIoHhz9J8AKqXasddMCqfJRaH30 -YJ7HnOvRYGL6HBrGhJ7X4Rzijyk9a9+3VOBsYcnIlx9iODoiYhA6r0ojuIu8/JA1 -oTTZrS0MyU/SLdFdJze2O1wnqTULXQybzJz3ad6oC/F5a69c0m92akYd9nGBrPxj -EhucaQynC/QoCLs3aciLgioAnEJqy7i3EgUCAwEAAaNzMHEwHwYDVR0jBBgwFoAU -YML3pLoA0h93Yngl8Gb/UgAh73owHQYDVR0OBBYEFGDC96S6ANIfd2J4JfBm/1IA -Ie96MAwGA1UdEwQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQE -AwIABTANBgkqhkiG9w0BAQUFAAOCAQEANPR8DN66iWZBs/lSm1vOzhqRkXDLT6xL -LvJtjPLqmE469szGyFSKzsof6y+/8YgZlOoeX1inF4ox/SH1ATnwdIIsPbXuRLjt -axboXvBh5y2ffC3hmzJVvJ87tb6mVWQeL9VFUhNhAI0ib+9OIZVEYI/64MFkDk4e -iWG5ts6oqIJH1V7dVZg6pQ1Tc0Ckhn6N1m1hD30S0/zoPn/20Wq6OCF3he8VJrRG -dcW9BD/Bkesko1HKhMBDjHVrJ8cFwbnDSoo+Ki47eJWaz/cOzaSsaMVUsR5POava -/abhhgHn/eOJdXiVslyK0DYscjsdB3aBUfwZlomxYOzG6CgjQPhJdw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEejCCA2KgAwIBAgIEP4vk6TANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQgLSBD -QSBLbGFzYSAyMB4XDTAzMTAxNDExNTgyMloXDTE3MDQxODEyNTMwN1owdzELMAkG -A1UEBhMCUEwxHzAdBgNVBAoTFlRQIEludGVybmV0IFNwLiB6IG8uby4xJDAiBgNV -BAsTG0NlbnRydW0gQ2VydHlmaWthY2ppIFNpZ25ldDEhMB8GA1UEAxMYQ0MgU2ln -bmV0IC0gT0NTUCBLbGFzYSAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCo -VCsaBStblXQYVNthe3dvaCrfvKpPXngh4almm988iIlEv9CVTaAdCfaJNihvA+Vs -Qw8++ix1VqteMQE474/MV/YaXigP0Zr0QB+g+/7PWVlv+5U9Gzp9+Xx4DJay8AoI -iB7Iy5Qf9iZiHm5BiPRIuUXT4ZRbZRYPh0/76vgRsQIDAQABo4IBkjCCAY4wDgYD -VR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMJMEEGA1UdHwQ6MDgwNqA0 -oDKGMGh0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9jcmwva2xhc2Ey -LmNybDCB2AYDVR0gBIHQMIHNMIHKBg4rBgEEAb4/AoFICgwBADCBtzBsBggrBgEF -BQcCAjBgGl5DZXJ0eWZpa2F0IHd5ZGFueSB6Z29kbmllIHogZG9rdW1lbnRlbSAi -UG9saXR5a2EgQ2VydHlmaWthY2ppIC0gQ2VydHlmaWthdHkgcmVzcG9uZGVyb3cg -T0NTUCIuMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnNpZ25ldC5wbC9yZXBvenl0 -b3JpdW0vZG9rdW1lbnR5L3BjX29jc3BfMV8wLnBkZjAfBgNVHSMEGDAWgBS7RQZS -C8uBzSlUs7x8QUzNBw6MJTAdBgNVHQ4EFgQUKEVrOY7cEHvsVgvoyZdytlbtgwEw -CQYDVR0TBAIwADANBgkqhkiG9w0BAQUFAAOCAQEAQrRg5MV6dxr0HU2IsLInxhvt -iUVmSFkIUsBCjzLoewOXA16d2oDyHhI/eE+VgAsp+2ANjZu4xRteHIHoYMsN218M -eD2MLRsYS0U9xxAFK9gDj/KscPbrrdoqLvtPSMhUb4adJS9HLhvUe6BicvBf3A71 -iCNe431axGNDWKnpuj2KUpj4CFHYsWCXky847YtTXDjri9NIwJJauazsrSjK+oXp -ngRS506mdQ7vWrtApkh8zhhWp7duCkjcCo1O8JxqYr2qEW1fXmgOISe010v2mmuv -hHxPyVwoAU4KkOw0nbXZn53yak0is5+XmAjh0wWue44AssHrjC9nUh3mkLt6eQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz -MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv -cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz -Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO -0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao -wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj -7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS -8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT -BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg -JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC -NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 -6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ -3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm -D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS -CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR -3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIIODCCB6GgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCAR4xCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjE0MDIGA1UECxMr -SVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE0MDIG -A1UEAxMrSVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eTEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAxMTAx -OFoXDTI1MTIyNzAxMTAxOFowggEeMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFy -Y2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5l -dCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlw -cy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxNDAyBgNVBAsTK0lQUyBDQSBUaW1lc3Rh -bXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxNDAyBgNVBAMTK0lQUyBDQSBU -aW1lc3RhbXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHjAcBgkqhkiG9w0B -CQEWD2lwc0BtYWlsLmlwcy5lczCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA -vLjuVqWajOY2ycJioGaBjRrVetJznw6EZLqVtJCneK/K/lRhW86yIFcBrkSSQxA4 -Efdo/BdApWgnMjvEp+ZCccWZ73b/K5Uk9UmSGGjKALWkWi9uy9YbLA1UZ2t6KaFY -q6JaANZbuxjC3/YeE1Z2m6Vo4pjOxgOKNNtMg0GmqaMCAwEAAaOCBIAwggR8MB0G -A1UdDgQWBBSL0BBQCYHynQnVDmB4AyKiP8jKZjCCAVAGA1UdIwSCAUcwggFDgBSL -0BBQCYHynQnVDmB4AyKiP8jKZqGCASakggEiMIIBHjELMAkGA1UEBhMCRVMxEjAQ -BgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJ -UFMgSW50ZXJuZXQgcHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJp -cHNAbWFpbC5pcHMuZXMgQy5JLkYuICBCLTYwOTI5NDUyMTQwMgYDVQQLEytJUFMg -Q0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTQwMgYDVQQD -EytJUFMgQ0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4w -HAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAM -BgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYB -BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIB -FgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYD -VR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlw -cy5lczBHBglghkgBhvhCAQ0EOhY4VGltZXN0YW1waW5nIENBIENlcnRpZmljYXRl -IGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgECBBwWGmh0 -dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMEAGCWCGSAGG+EIBBAQzFjFodHRwOi8v -d3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMEUGCWCG -SAGG+EIBAwQ4FjZodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25U -aW1lc3RhbXBpbmcuaHRtbD8wQgYJYIZIAYb4QgEHBDUWM2h0dHA6Ly93d3cuaXBz -LmVzL2lwczIwMDIvcmVuZXdhbFRpbWVzdGFtcGluZy5odG1sPzBABglghkgBhvhC -AQgEMxYxaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lUaW1lc3RhbXBp -bmcuaHRtbDB/BgNVHR8EeDB2MDegNaAzhjFodHRwOi8vd3d3Lmlwcy5lcy9pcHMy -MDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMDugOaA3hjVodHRwOi8vd3d3YmFj -ay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyVGltZXN0YW1waW5nLmNybDAvBggrBgEF -BQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZI -hvcNAQEFBQADgYEAZbrBzAAalZHK6Ww6vzoeFAh8+4Pua2JR0zORtWB5fgTYXXk3 -6MNbsMRnLWhasl8OCvrNPzpFoeo2zyYepxEoxZSPhExTCMWTs/zif/WN87GphV+I -3pGW7hdbrqXqcGV4LCFkAZXOzkw+UPS2Wctjjba9GNSHSl/c7+lW8AoM6HU= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFujCCBKKgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhjELMAkGA1UEBhMCVVMx -HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMS0wKwYDVQQLEyRBcHBsZSBD -b21wdXRlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIEFwcGxlIFJv -b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA1MDIxMDAwMTgxNFoXDTI1MDIx -MDAwMTgxNFowgYYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBcHBsZSBDb21wdXRl -ciwgSW5jLjEtMCsGA1UECxMkQXBwbGUgQ29tcHV0ZXIgQ2VydGlmaWNhdGUgQXV0 -aG9yaXR5MSkwJwYDVQQDEyBBcHBsZSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 -eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOSRqQkfkdseR1DrBe1e -eYQt6zaiV0xV7IsZid75S2z1B6siMALoGD74UAnTf0GomPnRymacJGsR0KO75Bsq -wx+VnnoMpEeLW9QWNzPLxA9NzhRp0ckZcvVdDtV/X5vyJQO6VY9NXQ3xZDUjFUsV -WR2zlPf2nJ7PULrBWFBnjwi0IPfLrCwgb3C2PwEwjLdDzw+dPfMrSSgayP7OtbkO -2V4c1ss9tTqt9A8OAJILsSEWLnTVPA3bYharo3GSR1NVwa8vQbP4++NwzeajTEV+ -H0xrUJZBicR0YgsQg0GHM4qBsTBY7FoEMoxos48d3mVz/2deZbxJ2HafMxRloXeU -yS0CAwEAAaOCAi8wggIrMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ -MB0GA1UdDgQWBBQr0GlHlHYJ/vRrjS5ApvdHTX8IXjAfBgNVHSMEGDAWgBQr0GlH -lHYJ/vRrjS5ApvdHTX8IXjCCASkGA1UdIASCASAwggEcMIIBGAYJKoZIhvdjZAUB -MIIBCTBBBggrBgEFBQcCARY1aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmlj -YXRlYXV0aG9yaXR5L3Rlcm1zLmh0bWwwgcMGCCsGAQUFBwICMIG2GoGzUmVsaWFu -Y2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkgcGFydHkgYXNzdW1lcyBhY2Nl -cHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5k -IGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRp -ZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4wRAYDVR0fBD0wOzA5oDegNYYz -aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L3Jvb3Qu -Y3JsMFUGCCsGAQUFBwEBBEkwRzBFBggrBgEFBQcwAoY5aHR0cHM6Ly93d3cuYXBw -bGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L2Nhc2lnbmVycy5odG1sMA0GCSqG -SIb3DQEBBQUAA4IBAQCd2i0oWC99dgS5BNM+zrdmY06PL9T+S61yvaM5xlJNBZhS -9YlRASR5vhoy9+VEi0tEBzmC1lrKtCBe2a4VXR2MHTK/ODFiSF3H4ZCx+CRA+F9Y -m1FdV53B5f88zHIhbsTp6aF31ywXJsM/65roCwO66bNKcuszCVut5mIxauivL9Wv -Hld2j383LS4CXN1jyfJxuCZA3xWNdUQ/eb3mHZnhQyw+rW++uaT+DjUZUWOxw961 -kj5ReAFziqQjyqSI8R5cH0EWLX6VCqrpiUGYGxrdyyC/R14MJsVVNU3GMIuZZxTH -CR+6R8faAQmHJEKVvRNgGQrv6n8Obs3BREM6StXj ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV -BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1 -c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAeFw0wOTA5MDkwODE1MjdaFw0yOTEy -MzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRl -ciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAm -BgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF -5+cvAqBNLaT6hdqbJYUtQCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYv -DIRlzg9uwliT6CwLOunBjvvya8o84pxOjuT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8v -zArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+EutCHnNaYlAJ/Uqwa1D7KRT -yGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1M4BDj5yj -dipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBh -MB8GA1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI -4jANBgkqhkiG9w0BAQUFAAOCAQEAg8ev6n9NCjw5sWi+e22JLumzCecYV42Fmhfz -dkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+KGwWaODIl0YgoGhnYIg5IFHY -aAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhKBgePxLcHsU0G -DeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV -CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPH -LQNjO9Po5KIqwoIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDvjCCA3ygAwIBAgIFJQaThoEwCwYHKoZIzjgEAwUAMIGFMQswCQYDVQQGEwJG -UjEPMA0GA1UECBMGRnJhbmNlMQ4wDAYDVQQHEwVQYXJpczEQMA4GA1UEChMHUE0v -U0dETjEOMAwGA1UECxMFRENTU0kxDjAMBgNVBAMTBUlHQy9BMSMwIQYJKoZIhvcN -AQkBFhRpZ2NhQHNnZG4ucG0uZ291di5mcjAeFw0wMjEyMTMxNDM5MTVaFw0yMDEw -MTcxNDM5MTRaMIGFMQswCQYDVQQGEwJGUjEPMA0GA1UECBMGRnJhbmNlMQ4wDAYD -VQQHEwVQYXJpczEQMA4GA1UEChMHUE0vU0dETjEOMAwGA1UECxMFRENTU0kxDjAM -BgNVBAMTBUlHQy9BMSMwIQYJKoZIhvcNAQkBFhRpZ2NhQHNnZG4ucG0uZ291di5m -cjCCAbYwggErBgcqhkjOOAQBMIIBHgKBgQCFkMImdk9zDzJfTO4XPdAAmLbAdWws -ZiEMZh19RyTo3CyhFqO77OIXrwY6vc1pcc3MgWJ0dgQpAgrDMtmFFxpUu4gmjVsx -8GpxQC+4VOgLY8Cvmcd/UDzYg07EIRto8BwCpPJ/JfUxwzV2V3N713aAX+cEoKZ/ -s+kgxC6nZCA7oQIVALME/JYjkdW2uKIGngsEPbXAjdhDAoGADh/uqWJx94UBm31c -9d8ZTBfRGRnmSSRVFDgPWgA69JD4BR5da8tKz+1HjfMhDXljbMH86ixpD5Ka1Z0V -pRYUPbyAoB37tsmXMJY7kjyD19d5VdaZboUjVvhH6UJy5lpNNNGSvFl4fqkxyvw+ -pq1QV0N5RcvK120hlXdfHUX+YKYDgYQAAoGAQGr7IuKJcYIvJRMjxwl43KxXY2xC -aoCiM/bv117MfI94aNf1UusGhp7CbYAY9CXuL60P0oPMAajbaTE5Z34AuITeHq3Y -CNMHwxalip8BHqSSGmGiQsXeK7T+r1rPXsccZ1c5ikGDZ4xn5gUaCyy2rCmb+fOJ -6VAfCbAbAjmNKwejdzB1MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgFGMBUG -A1UdIAQOMAwwCgYIKoF6AXkBAQEwHQYDVR0OBBYEFPkeNRcUf8idzpKblYbLNxs0 -MQhSMB8GA1UdIwQYMBaAFPkeNRcUf8idzpKblYbLNxs0MQhSMAsGByqGSM44BAMF -AAMvADAsAhRVh+CJA5eVyEYU5AO9Tm7GxX0rmQIUBCqsU5u1WxoZ5lEXicDX5/Ob -sRQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl -MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp -U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw -NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE -ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp -ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 -DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf -8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN -+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 -X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa -K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA -1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G -A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR -zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 -YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD -bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w -DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 -L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D -eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl -xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp -VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY -WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 -pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 -13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk -U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i -F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY -oJ2daZH9 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV -BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X -DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ -BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 -QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny -gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw -zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q -130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 -JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw -ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT -AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj -AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG -9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h -bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc -fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu -HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w -t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw -WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG -A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B -AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz -yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE -38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP -AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad -DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME -HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAx -MDQwNjEwNDkxM1oXDTIxMDQwNjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMSBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H887dF+2rDNbS82rDTG -29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9EJUk -oVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk -3w0LBUXl0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBL -qdReLjVQCfOAl/QMF6452F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIIN -nvmLVz5MxxftLItyM19yejhW1ebZrgUaHXVFsculJRwSVzb9IjcCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZTiFIwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE928Jj2VuX -ZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0H -DjxVyhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VO -TzF2nBBhjrZTOqMRvq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2Uv -kVrCqIexVmiUefkl98HVrhq4uz2PqYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4w -zMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9ZIRlXvVWa ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF5jCCA86gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx -HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh -IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyOTA2MDAwMFoXDTM3MDkyODIz -NDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg -SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M -IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALQ3WggWmRToVbEbJGv8x4vmh6mJ -7ouZzU9AhqS2TcnZsdw8TQ2FTBVsRotSeJ/4I/1n9SQ6aF3Q92RhQVSji6UI0ilb -m2BPJoPRYxJWSXakFsKlnUWsi4SVqBax7J/qJBrvuVdcmiQhLE0OcR+mrF1FdAOY -xFSMFkpBd4aVdQxHAWZg/BXxD+r1FHjHDtdugRxev17nOirYlxcwfACtCJ0zr7iZ -YYCLqJV+FNwSbKTQ2O9ASQI2+W6p1h2WVgSysy0WVoaP2SBXgM1nEG2wTPDaRrbq -JS5Gr42whTg0ixQmgiusrpkLjhTXUr2eacOGAgvqdnUxCc4zGSGFQ+aJLZ8lN2fx -I2rSAG2X+Z/nKcrdH9cG6rjJuQkhn8g/BsXS6RJGAE57COtCPStIbp1n3UsC5ETz -kxmlJ85per5n0/xQpCyrw2u544BMzwVhSyvcG7mm0tCq9Stz+86QNZ8MUhy/XCFh -EVsVS6kkUfykXPcXnbDS+gfpj1bkGoxoigTTfFrjnqKhynFbotSg5ymFXQNoKk/S -Btc9+cMDLz9l+WceR0DTYw/j1Y75hauXTLPXJuuWCpTehTacyH+BCQJJKg71ZDIM -gtG6aoIbs0t0EfOMd9afv9w3pKdVBC/UMejTRrkDfNoSTllkt1ExMVCgyhwn2RAu -rda9EGYrw7AiShJbAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE -FE9pbQN+nZ8HGEO8txBO1b+pxCAoMB8GA1UdIwQYMBaAFE9pbQN+nZ8HGEO8txBO -1b+pxCAoMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAO/Ouyugu -h4X7ZVnnrREUpVe8WJ8kEle7+z802u6teio0cnAxa8cZmIDJgt43d15Ui47y6mdP -yXSEkVYJ1eV6moG2gcKtNuTxVBFT8zRFASbI5Rq8NEQh3q0l/HYWdyGQgJhXnU7q -7C+qPBR7V8F+GBRn7iTGvboVsNIYvbdVgaxTwOjdaRITQrcCtQVBynlQboIOcXKT -RuidDV29rs4prWPVVRaAMCf/drr3uNZK49m1+VLQTkCpx+XCMseqdiThawVQ68W/ -ClTluUI8JPu3B5wwn3la5uBAUhX0/Kr0VvlEl4ftDmVyXr4m+02kLQgH3thcoNyB -M5kYJRF3p+v9WAksmWsbivNSPxpNSGDxoPYzAlOL7SUJuA0t7Zdz7NeWH45gDtoQ -my8YJPamTQr5O8t1wswvziRpyQoijlmn94IM19drNZxDAGrElWe6nEXLuA4399xO -AU++CrYD062KRffaJ00psUjf5BHklka9bAI+1lHIlRcBFanyqqryvy9lG2/QuRqT -9Y41xICHPpQvZuTpqP9BnHAqTyo5GJUefvthATxRCC4oGKQWDzH9OmwjkyB24f0H -hdFbP9IcczLd+rn4jM8Ch3qaluTtT4mNU0OrDhPAARW0eTjb/G49nlG2uBOLZ8/5 -fNkiHfZdxRwBL5joeiQYvITX+txyW/fBOmg= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj -dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 -NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD -VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G -vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ -BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX -MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl -IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw -NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq -y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy -0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 -E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe -MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 -ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw -IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL -SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH -SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh -ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X -DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 -TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ -fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA -sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU -WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS -nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH -dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip -NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC -AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF -MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH -ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB -uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl -PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP -JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ -gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 -j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 -5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB -o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS -/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z -Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE -W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D -hNQ+IIX3Sj0rnP0qCglN6oH4EZw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF3zCCA8egAwIBAgIOGTMAAQACKBqaBLzyVUUwDQYJKoZIhvcNAQEFBQAwejEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV -BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEnMCUGA1UEAxMeVEMgVHJ1 -c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJMB4XDTA2MDMyMjE1NTgzNFoXDTMwMTIz -MTIyNTk1OVowejELMAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVy -IEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEnMCUG -A1UEAxMeVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJMIICIjANBgkqhkiG -9w0BAQEFAAOCAg8AMIICCgKCAgEAi9R3azRs5TbYalxeOO781R15Azt7g2JEgk6I -7d6D/+7MUGIFBZWZdpj2ufJf2AaRksL2LWYXH/1TA+iojWOpbuHWG4y8mLOLO9Tk -Lsp9hUkmW3m4GotAnn+7yT9jLM/RWny6KCJBElpN+Rd3/IX9wkngKhh/6aAsnPlE -/AxoOUL1JwW+jhV6YJ3wO8c85j4WvK923mq3ouGrRkXrjGV90ZfzlxElq1nroCLZ -gt2Y7X7i+qBhCkoy3iwX921E6oFHWZdXNwM53V6CItQzuPomCba8OYgvURVOm8M7 -3xOCiN1LNPIz1pDp81PcNXzAw9l8eLPNcD+NauCjgUjkKa1juPD8KGQ7mbN9/pqd -iPaZIgiRRxaJNXhdd6HPv0nh/SSUK2k2e+gc5iqQilvVOzRZQtxtz7sPQRxVzfUN -Wy4WIibvYR6X/OJTyM9bo8ep8boOhhLLE8oVx+zkNo3aXBM9ZdIOXXB03L+PemrB -Lg/Txl4PK1lszGFs/sBhTtnmT0ayWuIZFHCE+CAA7QGnl37DvRJckiMXoKUdRRcV -I5qSCLUiiI3cKyTr4LEXaNOvYb3ZhXj2jbp4yjeNY77nrB/fpUcJucglMVRGURFV -DYlcjdrSGC1z8rjVJ/VIIjfRYvd7Dcg4i6FKsPzQ8eu3hmPn4A5zf/1yUbXpfeJV -BWR4Z38CAwEAAaNjMGEwHwYDVR0jBBgwFoAUzdeQoW6jv9sw1toyJZAM5jkegGUw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFM3XkKFu -o7/bMNbaMiWQDOY5HoBlMA0GCSqGSIb3DQEBBQUAA4ICAQB+FojoEw42zG4qhQc4 -xlaJeuNHIWZMUAgxWlHQ/KZeFHXeTDvs8e3MfhEHSmHu6rOOOqQzxu2KQmZP8Tx7 -yaUFQZmx7Cxb7tyW0ohTS3g0uW7muw/FeqZ8Dhjfbw90TNGp8aHp2FRkzF6WeKJW -GsFzshXGVwXf2vdIJIqOf2qp+U3pPmrOYCx9LZAI9mOPFdAtnIz/8f38DBZQVhT7 -upeG7rRJA1TuG1l/MDoCgoYhrv7wFfLfToPmmcW6NfcgkIw47XXP4S73BDD7Ua2O -giRAyn0pXdXZ92Vk/KqfdLh9kl3ShCngE+qK99CrxK7vFcXCifJ7tjtJmGHzTnKR -N4xJkunI7Cqg90lufA0kxmts8jgvynAF5X/fxisrgIDV2m/LQLvYG/AkyRDIRAJ+ -LtOYqqIN8SvQ2vqOHP9U6OFKbt2o1ni1N6WsZNUUI8cOpevhCTjXwHxgpV2Yj4wC -1dxWqPNNWKkL1HxkdAEy8t8PSoqpAqKiHYR3wvHMl700GXRd4nQ+dSf3r7/ufA5t -VIimVuImrTESPB5BeW0X6hNeH/Vcn0lZo7Ivo0LD+qh+v6WfSMlgYmIK371F3uNC -tVGW/cT1Gpm4UqJEzS1hjBWPgdVdotSQPYxuQGHDWV3Y2eH2dEcieXR92sqjbzcV -NvAsGnE8EXbfXRo+VGN4a2V+Hw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIHqTCCBZGgAwIBAgIQYwaGp8U3ZaVDkKhqWMzUMjANBgkqhkiG9w0BAQUFADCB -jzELMAkGA1UEBhMCTFYxNTAzBgNVBAoTLFZBUyBMYXR2aWphcyBQYXN0cyAtIFZp -ZW4ucmVnLk5yLjQwMDAzMDUyNzkwMSMwIQYDVQQLExpTZXJ0aWZpa2FjaWphcyBw -YWthbHBvanVtaTEkMCIGA1UEAxMbVkFTIExhdHZpamFzIFBhc3RzIFNTSShSQ0Ep -MB4XDTA2MDkxMzA5MjIxMFoXDTI0MDkxMzA5Mjc1N1owgY8xCzAJBgNVBAYTAkxW -MTUwMwYDVQQKEyxWQVMgTGF0dmlqYXMgUGFzdHMgLSBWaWVuLnJlZy5Oci40MDAw -MzA1Mjc5MDEjMCEGA1UECxMaU2VydGlmaWthY2lqYXMgcGFrYWxwb2p1bWkxJDAi -BgNVBAMTG1ZBUyBMYXR2aWphcyBQYXN0cyBTU0koUkNBKTCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBAJu4+f1hVS9PpKUUtS6OuSSPrPuxVD9A/0/F5YZo -e1OT+zWCNahQLpRSoNuDPnXaFXCsCc/ugkmtNkm5tHGLtAChQgbKCApjl7YI/O60 -3Jh4GYLJ+H9kPqrJ/rGN67Bk9bzzxD46kOpOjj8bGbxqg8ORPGxV+wpSwOjhXXeF -M8VJ3+xqv79sN/6OSaIVGM6LjmseOKMwb4iBfnJWRBrEejkP9sSPltSy6wBOXN67 -5zu35iQFk2tN5pFEv+6YG8eFGxFBeyI2p74+6Ho33BjekJ2PzbLXmj/iF39bDOHv -P2Y9biTksM7DDIhslNo4JXxSOeNzFLMARWOaDEJAXgTG93JkzsluM7Pk020klTeT -fvIAXRmLH/NDc6ifRdIGqey0Qrv67gzHTz9RH9Gv0KwYf4eBIv6p3QeWbXz4TtlN -OlBp1UF+xdp02I5z5X6D4cMZgbe9v0COvi6aogyqTgIuuyrhCF0xA8msJ7Cv3NXI -FH1AnVWJIfmQzNTJYEFzq+jN2DpVOQqCmf6b9fU8HJHLwPpGVK4h/CqsXHveepdx -/WxrzUiapNuBfBg3L5B9YZS9F8lctlQWd8oJSqrpvE+UdQFaVryS0o+515feVnQB -9xZxSbH1GEaZQe5i4bMsZXVpKXJDA/ibH/o49J7sQBCOrJfVsDO+nxjcLfdBeFRK -YkTnAgMBAAGjggH9MIIB+TAOBgNVHQ8BAf8EBAMCAQYwGAYIKwYBBQUHAQMEDDAK -MAgGBgQAjkYBATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTMw/Vm/3OsOFqW -GyGJuIFMH8teJTAQBgkrBgEEAYI3FQEEAwIBADCCAYkGA1UdIASCAYAwggF8MIIB -eAYLKwYBBAGBxFkBAQIwggFnMIIBOAYIKwYBBQUHAgIwggEqHoIBJgBTAGkAcwAg -AGkAcgAgAHMAZQByAHQAaQBmAGkAawBhAHQAcwAsACAAawBvACAAaQB6AGQAZQB2 -AGkAcwAgAFYAQQBTACAATABhAHQAdgBpAGoAYQBzACAAUABhAHMAdABzACwAIABu -AG8AZAByAG8AcwBpAG4AbwB0ACAAYQB0AGIAaQBsAHMAdABpAGIAdQAgAEUAbABl -AGsAdAByAG8AbgBpAHMAawBvACAAZABvAGsAdQBtAGUAbgB0AHUAIABsAGkAawB1 -AG0AYQBtACAAdQBuACAARQBpAHIAbwBwAGEAcwAgAFAAYQByAGwAYQBtAGUAbgB0 -AGEAIABkAGkAcgBlAGsAdABpAHYAYQBpACAAMQA5ADkAOQAvADkAMwAvAEUASzAp -BggrBgEFBQcCARYdaHR0cDovL3d3dy5lLW1lLmx2L3JlcG9zaXRvcnkwDQYJKoZI -hvcNAQEFBQADggIBAB8oSjWQIWNoCi94r6MegiaXoz8nGdJLo0J6BhNlW8EEy+t9 -fO+U8vGJ9bffUgIhadLqljTloM+XuJxVDhCFoxReLAX4tTp28/l6uN62DCdp8suU -kQsdudWOb5kvzfIZVjk6SFbwAf+Cdbay/dHU9fJjV0xNoX7MELoEae/0FPyzlx9F -7m9KKH/Rxie8x6Opa3vtghNvq94P+3HrXBEaqSzQMJ/8NjdW75XpurcTtq6fAmGt -nuxrBG82nw+Z98LJyEwouSjUIdeeVNXAzvSO5FWUe48kxjj8q3qkVnc9qEXvZJKk -0Ep+u3OL9A1Sc7g6SF5DgNOpcHdi/8coHHMeQ+YnJFtJueY2pI79xS0veqV5EnrX -IbIlbcgPosNhS+VI4le6n/KKId3bZPDaGd/OwJuAOcJ3d2MVU3KE+qSPBzeGIX1Q -+j1qN9uRDjez/c4Lynth0Jx0nH04aG3pex3W8Sq07ztgUncF5gLCX4xbvPB9t3PH -kWuyKrNjozTVq60lcUf/Gj56to2VdsPups0DCWzuRWeYz5lIdsHOinSaaFIBNCLI -7eIUC4S9bhCMsXKbvugI11fVf+q0AT1O5OLoZ+eMfunnQhHvlUbIkda+JxeAGTSY -58bfHvwhX56GPbx+8Jy9cp70R4JbcWfz+txUTKhc2FnH0AcOEzMnvPRp8Gsh ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDtTCCAp2gAwIBAgIIBhDCeat3PfIwDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UE -BhMCQ0gxEjAQBgNVBAoTCVN3aXNzU2lnbjEyMDAGA1UEAxMpU3dpc3NTaWduIENB -IChSU0EgSUsgTWF5IDYgMTk5OSAxODowMDo1OCkxHzAdBgkqhkiG9w0BCQEWEGNh -QFN3aXNzU2lnbi5jb20wHhcNMDAxMTI2MjMyNzQxWhcNMzExMTI2MjMyNzQxWjB2 -MQswCQYDVQQGEwJDSDESMBAGA1UEChMJU3dpc3NTaWduMTIwMAYDVQQDEylTd2lz -c1NpZ24gQ0EgKFJTQSBJSyBNYXkgNiAxOTk5IDE4OjAwOjU4KTEfMB0GCSqGSIb3 -DQEJARYQY2FAU3dpc3NTaWduLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAKw5fjnmNneLQlUCQG8jQLwwfbrOZoUwNX8cbNqhxK03/xUloFVgAt+S -Te2RxNXaCAXLBPn5ZST35TLV57aLmbHCtifv3YZqaaQGvjedltIBMJihJhZ+h3LY -SKsUb+xEJ3x5ZUf8jP+Q1g57y1s8SnBFWN/ni5NkF1Y1y31VwOi9wiOf/VISL+uu -SC4i1CP1Kbz3BDs6Hht1GpRYCbJ/K0bc9oJSpWpT5PGONsGIawqMbJuyoDghsXQ1 -pbn2e8K64BSscGZVZTNooSGgNiHmACNJBYXiWVWrwXPF4l6SddmC3Rj0aKXjgECc -FkHLDQcsM5JsK2ZLryTDUsQFbxVP2ikCAwEAAaNHMEUwCwYDVR0PBAQDAgEGMAwG -A1UdEwQFMAMBAf8wHQYDVR0OBBYEFJbXcc05KtT8iLGKq1N4ae+PR34WMAkGA1Ud -IwQCMAAwDQYJKoZIhvcNAQEFBQADggEBAKMy6W8HvZdS1fBpEUzl6Lvw50bgE1Xc -HU1JypSBG9mhdcXZo5AlPB4sCvx9Dmfwhyrdsshc0TP2V3Vh6eQqnEF5qB4lVziT -Bko9mW6Ot+pPnwsy4SHpx3rw6jCYnOqfUcZjWqqqRrq/3P1waz+Mn4cLMVEg3Xaz -qYov/khvSqS0JniwjRlo2H6f/1oVUKZvP+dUhpQepfZrOqMAWZW4otp6FolyQyeU -NN6UCRNiUKl5vTijbKwUUwfER/1Vci3M1/O1QCfttQ4vRN4Buc0xqYtGL3cd5WiO -vWzyhlTzAI6VUdNkQhhHJSAyTpj6dmXDRzrryoFGa2PjgESxz7XBaSI= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx -MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg -Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ -iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa -/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ -jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI -HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 -sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w -gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw -KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG -AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L -URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO -H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm -I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY -iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc -f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG -EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD -VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu -dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 -E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ -D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK -4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq -lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW -bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB -o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT -MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js -LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr -BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB -AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj -j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH -KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv -2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 -mfnGV/TJVTl4uix5yaaIK/QI ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV -BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM -V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB -4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr -H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd -8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv -vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT -mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe -btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc -T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt -WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ -c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A -4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD -VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG -CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 -aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 -aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu -dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw -czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G -A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg -Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 -7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem -d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd -+LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B -4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN -t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x -DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 -k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s -zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j -Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT -mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK -4SVhM7JZG+Ju1zdXtg2pEto= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzET -MBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UE -AxMIQ0EgRGlzaWcwHhcNMDYwMzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQsw -CQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcg -YS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgmGErE -Nx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnX -mjxUizkDPw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYD -XcDtab86wYqg6I7ZuUUohwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhW -S8+2rT+MitcE5eN4TPWGqvWP+j1scaMtymfraHtuM6kMgiioTGohQBUgDCZbg8Kp -FhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8wgfwwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0PAQH/BAQD -AgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cu -ZGlzaWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5z -ay9jYS9jcmwvY2FfZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2sv -Y2EvY3JsL2NhX2Rpc2lnLmNybDAaBgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEw -DQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59tWDYcPQuBDRIrRhCA/ec8J9B6 -yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3mkkp7M5+cTxq -EEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ -CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeB -EicTXxChds6KezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFN -PGO+I++MzVpQuGhU+QqZMxEA4Z7CRneC9VkGjCFMhwnN5ag= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw -MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD -VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA -A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul -CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n -tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl -dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch -PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC -+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O -BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl -MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk -ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB -IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X -7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz -43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY -eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl -pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA -WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJE -SzEMMAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEw -ODM5MzBaFw0zNzAyMTEwOTA5MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNU -REMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuHnEz9pPPEXyG9VhDr -2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0zY0s -2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItU -GBxIYXvViGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKj -dGqPqcNiKXEx5TukYBdedObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+r -TpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/ -BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB5DCB4TCB3gYIKoFQgSkB -AQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5kay9yZXBv -c2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRl -ciBmcmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEu -MS4xLiBDZXJ0aWZpY2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIg -T0lEIDEuMi4yMDguMTY5LjEuMS4xLjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1Ud -HwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMRQwEgYD -VQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYmaHR0cDovL2Ny -bC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy -MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZ -J2cdUBVLc647+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqG -SIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACrom -JkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4A9G28kNBKWKnctj7fAXmMXAnVBhO -inxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYscA+UYyAFMP8uXBV2Y -caaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9AOoB -mbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQ -YqbsFbS1AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9 -BKNDLdr8C2LqL19iUw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUx -ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 -b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQD -EzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVneXpvaSAoQ2xhc3MgUUEpIFRhbnVz -aXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0bG9jay5odTAeFw0w -MzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTERMA8G -A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh -Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5l -dExvY2sgTWlub3NpdGV0dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZh -bnlraWFkbzEeMBwGCSqGSIb3DQEJARYPaW5mb0BuZXRsb2NrLmh1MIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRVCacbvWy5FPSKAtt2/Goq -eKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e8ia6AFQe -r7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO5 -3Lhbm+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWd -vLrqOU+L73Sa58XQ0uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0l -mT+1fMptsK6ZmfoIYOcZwvK9UdPM0wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4IC -wDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAQYwggJ1Bglg -hkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2YW55IGEgTmV0 -TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh -biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQg -ZWxla3Ryb25pa3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywg -dmFsYW1pbnQgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6 -b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwgYXogQWx0YWxhbm9zIFN6ZXJ6b2Rl -c2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kgZWxqYXJhcyBtZWd0 -ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczovL3d3 -dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0Bu -ZXRsb2NrLm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBh -bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRo -ZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMgYXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3 -Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0IGluZm9AbmV0bG9jay5u -ZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3DQEBBQUA -A4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQ -MznNwNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+ -NFAwLvt/MpqNPfMgW/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCR -VCHnpgu0mfVRQdzNo0ci2ccBgcTcR08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY -83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR5qq5aKrN9p2QdRLqOBrKROi3 -macqaJVmlaut74nLYKkGEsaUR+ko ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICmDCCAgGgAwIBAgIBDjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEY -MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNFQ0ExFDASBgNVBAMT -C0VDQSBSb290IENBMB4XDTA0MDYxNDEwMjAwOVoXDTQwMDYxNDEwMjAwOVowSzEL -MAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMD -RUNBMRQwEgYDVQQDEwtFQ0EgUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEArkr2eXIS6oAKIpDkOlcQZdMGdncoygCEIU+ktqY3of5SVVXU7/it7kJ1 -EUzR4ii2vthQtbww9aAnpQxcEmXZk8eEyiGEPy+cCQMllBY+efOtKgjbQNDZ3lB9 -19qzUJwBl2BMxslU1XsJQw9SK10lPbQm4asa8E8e5zTUknZBWnECAwEAAaOBizCB -iDAfBgNVHSMEGDAWgBT2uAQnDlYW2blj2f2hVGVBoAhILzAdBgNVHQ4EFgQU9rgE -Jw5WFtm5Y9n9oVRlQaAISC8wDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB -Af8wJQYDVR0gBB4wHDAMBgpghkgBZQMCAQwBMAwGCmCGSAFlAwIBDAIwDQYJKoZI -hvcNAQEFBQADgYEAHh0EQY2cZ209aBb5q0wW1ER0dc4OGzsLyqjHfaQ4TEaMmUwL -AJRta/c4KVWLiwbODsvgJk+CaWmSL03gRW/ciVb/qDV7qh9Pyd1cOlanZTAnPog2 -i82yL3i2fK9DCC84uoxEQbgqK2jx9bIjFTwlAqITk9fGAm5mdT84IEwq1Gw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB -rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt -Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa -Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV -BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l -dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE -AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B -YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9 -hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l -L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm -SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM -1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws -6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw -Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50 -aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH -AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u -7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0 -xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ -rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim -eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk -USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIjCCAougAwIBAgIQNKT/9jCvTKU8MxdCoZRmdTANBgkqhkiG9w0BAQUFADCB -xDELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ -Q2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UE -CxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhh -d3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0 -ZS5jb20wHhcNOTYwODAxMDAwMDAwWhcNMjEwMTAxMjM1OTU5WjCBxDELMAkGA1UE -BhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3du -MR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlm -aWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZl -ciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8w -DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl -/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF -/rFrKbYvScg71CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982 -OsK1ZiIS1ocNAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEF -BQADgYEAvkBpQW/G28GnvwfAReTQtUMeTJUzNelewj4o9qgNUNX/4gwP/FACjq6R -ua00io2fJ3GqGcxL6ATK1BdrEhrWxl/WzV7/iXa/2EjYWb0IiokdV81FHlK6EpqE -+hiJX+j5MDVqAWC5mYCDhQpu2vTJj15zLTFKY6B08h+LItIpPus= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj -IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X -DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw -EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE -ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy -dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD -QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53 -dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK -wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7 -G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF -AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7 -c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P -9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB -gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk -MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY -UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx -NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 -dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy -dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 -38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP -KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q -DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 -qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa -JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi -PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P -BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs -jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 -eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD -ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR -vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt -qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa -IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy -i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ -O+7ETPTsJ3xCwnR8gooJybQDJbw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP -bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2 -MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft -ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC -206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci -KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2 -JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9 -BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e -Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B -PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67 -Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq -Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ -o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3 -+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj -YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj -FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE -AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn -xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2 -LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc -obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8 -CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe -IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA -DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F -AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX -Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb -AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl -Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw -RY8mkaKO/qk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMx -IDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxs -cyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9v -dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcxMjEzMTcwNzU0WhcNMjIxMjE0 -MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdl -bGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQD -DC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+r -WxxTkqxtnt3CxC5FlAM1iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjU -Dk/41itMpBb570OYj7OeUt9tkTmPOL13i0Nj67eT/DBMHAGTthP796EfvyXhdDcs -HqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8bJVhHlfXBIEyg1J55oNj -z7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiBK0HmOFaf -SZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/Slwxl -AgMBAAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqG -KGh0dHA6Ly9jcmwucGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0P -AQH/BAQDAgHGMB0GA1UdDgQWBBQmlRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0j -BIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGBi6SBiDCBhTELMAkGA1UEBhMC -VVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNX -ZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg -Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEB -ALkVsUSRzCPIK0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd -/ZDJPHV3V3p9+N701NX3leZ0bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pB -A4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSljqHyita04pO2t/caaH/+Xc/77szWn -k4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+esE2fDbbFwRnzVlhE9 -iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJtylv -2G0xffX8oRAHh84vWdw+WNs= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDczCCAlugAwIBAgIQMDAwMDk3Mzc1NzM4NjAwMDANBgkqhkiG9w0BAQUFADBV -MQswCQYDVQQGEwJGUjETMBEGA1UEChMKQ2VydGlOb21pczEcMBoGA1UECxMTQUMg -UmFjaW5lIC0gUm9vdCBDQTETMBEGA1UEAxMKQ2VydGlOb21pczAeFw0wMDExMDkw -MDAwMDBaFw0xMjExMDkwMDAwMDBaMFUxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpD -ZXJ0aU5vbWlzMRwwGgYDVQQLExNBQyBSYWNpbmUgLSBSb290IENBMRMwEQYDVQQD -EwpDZXJ0aU5vbWlzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8SWb -4mS5RXB3ENSIcfrEzCj/TRUQuT1tMCU0YUfXFSgcPdWglIzCv3kvh07QoB+8xMl+ -fQHvSSduAxnNewz0GBY9rApCPKlP6CcnJr74OSVZIiWt9wLfl4wwhNhZOiikIpZp -EdOXWqRc84P5cUlN3Lwmr1sjCWmHfTSS4cAKxfDbFLfE61etosyoFZUTQbIhb1Bf -JL5xRXAUZudQiU42n/yAoSUrN4FLUfPQNlOe1AB81pIgX8g2ojwxDjfgqSs1JmBF -uLKJ45uVLEenQBPmQCGjL3maV86IRmR3a9UGlgvKAk0NBdh8mrQyQvcUlLBIQBCm -l7wppt6maQHUNEPQSwIDAQABoz8wPTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQU+F4ho6ijFeb4tRG7/kIEXU2OgnowDQYJKoZIhvcNAQEF -BQADggEBACe9FJayK6bXkJQrilBFMh75QPdFOks9PJuo86OMUlBDZGYFTCh9Arex -N3KYCnAEzazYIALwr7eASJJDIQMu1Q+pkx/7ACde4kP47F27M2rm+v5HnGooCLz2 -s7Fe/WUycTQqgwF5lNp03m1ce/TvovgkEZeVN5wM/7+SsZLJGDigXGeq48j2g2hn -8OckX9Ciyo0U3/1IVeigNBisiaOlsHSZOEPBZQRiZULob+NVbXVPo8nM1OyP3aHI -LQex1yYcCr9m93nOiZyKkur3Uedf1yMTBe+fflnPFKGYnVqvTGXCKVdHzQBfpILA -AuaC+5ykZhSiSMf8nmL2oPMcLO7YQw4= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF -MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL -ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx -MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc -MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ -AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH -iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj -vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA -0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB -OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ -BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E -FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 -GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW -zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 -1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE -f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F -jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN -ZetX2fNXlrtIzYE= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGUTCCBTmgAwIBAgIEPLVPQDANBgkqhkiG9w0BAQUFADBmMRIwEAYDVQQKEwli -ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEzMDEGA1UEAxMq -YmVUUlVTVGVkIFJvb3QgQ0EgLSBFbnRydXN0IEltcGxlbWVudGF0aW9uMB4XDTAy -MDQxMTA4MjQyN1oXDTIyMDQxMTA4NTQyN1owZjESMBAGA1UEChMJYmVUUlVTVGVk -MRswGQYDVQQLExJiZVRSVVNUZWQgUm9vdCBDQXMxMzAxBgNVBAMTKmJlVFJVU1Rl -ZCBSb290IENBIC0gRW50cnVzdCBJbXBsZW1lbnRhdGlvbjCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBALr0RAOqEmq1Q+xVkrYwfTVXDNvzDSduTPdQqJtO -K2/b9a0cS12zqcH+e0TrW6MFDR/FNCswACnxeECypP869AGIF37m1CbTukzqMvtD -d5eHI8XbQ6P1KqNRXuE70mVpflUVm3rnafdE4Fe1FehmYA8NA/uCjqPoEXtsvsdj -DheT389Lrm5zdeDzqrmkwAkbhepxKYhBMvnwKg5sCfJ0a2ZsUhMfGLzUPvfYbiCe -yv78IZTuEyhL11xeDGbu6bsPwTSxfwh28z0mcMmLJR1iJAzqHHVOwBLkuhMdMCkt -VjMFu5dZfsZJT4nXLySotohAtWSSU1Yk5KKghbNekLQSM80CAwEAAaOCAwUwggMB -MIIBtwYDVR0gBIIBrjCCAaowggGmBg8rBgEEAbE+AAACCSiDkTEwggGRMIIBSQYI -KwYBBQUHAgIwggE7GoIBN1JlbGlhbmNlIG9uIG9yIHVzZSBvZiB0aGlzIENlcnRp -ZmljYXRlIGNyZWF0ZXMgYW4gYWNrbm93bGVkZ21lbnQgYW5kIGFjY2VwdGFuY2Ug -b2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0 -aW9ucyBvZiB1c2UsIHRoZSBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu -dCBhbmQgdGhlIFJlbHlpbmcgUGFydHkgQWdyZWVtZW50LCB3aGljaCBjYW4gYmUg -Zm91bmQgYXQgdGhlIGJlVFJVU1RlZCB3ZWIgc2l0ZSwgaHR0cHM6Ly93d3cuYmV0 -cnVzdGVkLmNvbS9wcm9kdWN0c19zZXJ2aWNlcy9pbmRleC5odG1sMEIGCCsGAQUF -BwIBFjZodHRwczovL3d3dy5iZXRydXN0ZWQuY29tL3Byb2R1Y3RzX3NlcnZpY2Vz -L2luZGV4Lmh0bWwwEQYJYIZIAYb4QgEBBAQDAgAHMIGJBgNVHR8EgYEwfzB9oHug -eaR3MHUxEjAQBgNVBAoTCWJlVFJVU1RlZDEbMBkGA1UECxMSYmVUUlVTVGVkIFJv -b3QgQ0FzMTMwMQYDVQQDEypiZVRSVVNUZWQgUm9vdCBDQSAtIEVudHJ1c3QgSW1w -bGVtZW50YXRpb24xDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMjA0MTEw -ODI0MjdagQ8yMDIyMDQxMTA4NTQyN1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaA -FH1w5a44iwY/qhwaj/nPJDCqhIQWMB0GA1UdDgQWBBR9cOWuOIsGP6ocGo/5zyQw -qoSEFjAMBgNVHRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIE -kDANBgkqhkiG9w0BAQUFAAOCAQEAKrgXzh8QlOu4mre5X+za95IkrNySO8cgjfKZ -5V04ocI07cUTWVwFtStPYZuR+0H8/NU8TZh2BvWBfevdkObRVlTa4y0MnxEylCIB -evZsLHRnBMylj44ss0O1lKLQfelifwa+JwGDnjr9iu6YQ0pr17WXOzq/T220Y/oz -ADQuLW2WyXvKmWO6vvT2MKAtmJbpVkQFqUSjYRDrgqFnXbxdJ3Wqiig2KjiS2d2k -XgClzMx8KSreKJCrt+G2/30lC0DYqjSjLd4H61/OCt3Kfjp9JsFiaDrmLzfzgYYh -xKlkqu9FNtEaZnz46TfW1mG+oq1I59/mdP7TbX3SJdysYlep9w== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEuzCCA6OgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzET -MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDYwNDI1MjE0 -MDM2WhcNMzUwMjA5MjE0MDM2WjBiMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBw -bGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx -FjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQDkkakJH5HbHkdQ6wXtXnmELes2oldMVeyLGYne+Uts9QerIjAC6Bg+ -+FAJ039BqJj50cpmnCRrEdCju+QbKsMflZ56DKRHi1vUFjczy8QPTc4UadHJGXL1 -XQ7Vf1+b8iUDulWPTV0N8WQ1IxVLFVkds5T39pyez1C6wVhQZ48ItCD3y6wsIG9w -tj8BMIy3Q88PnT3zK0koGsj+zrW5DtleHNbLPbU6rfQPDgCSC7EhFi501TwN22IW -q6NxkkdTVcGvL0Gz+PvjcM3mo0xFfh9Ma1CWQYnEdGILEINBhzOKgbEwWOxaBDKM -aLOPHd5lc/9nXmW8Sdh2nzMUZaF3lMktAgMBAAGjggF6MIIBdjAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUK9BpR5R2Cf70a40uQKb3 -R01/CF4wHwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wggERBgNVHSAE -ggEIMIIBBDCCAQAGCSqGSIb3Y2QFATCB8jAqBggrBgEFBQcCARYeaHR0cHM6Ly93 -d3cuYXBwbGUuY29tL2FwcGxlY2EvMIHDBggrBgEFBQcCAjCBthqBs1JlbGlhbmNl -IG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0 -YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBj -b25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZp -Y2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMA0GCSqGSIb3DQEBBQUAA4IBAQBc -NplMLXi37Yyb3PN3m/J20ncwT8EfhYOFG5k9RzfyqZtAjizUsZAS2L70c5vu0mQP -y3lPNNiiPvl4/2vIB+x9OYOLUyDTOMSxv5pPCmv/K/xZpwUJfBdAVhEedNO3iyM7 -R6PVbyTi69G3cN8PReEnyvFteO3ntRcXqNx+IjXKJdXZD9Zr1KIkIxH3oayPc4Fg -xhtbCS+SsvhESPBgOJ4V9T0mZyCKM2r3DYLP3uujL/lTaltkwGMzd/c6ByxW69oP -IQ7aunMZT7XZNn/Bh1XZp5m5MkL72NVxnn6hUrcbvZNCJBIqxw8dtk2cXmPIS4AX -UKqK1drk/NAJBzewdXUh ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCB -lTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAbBgNVBAMTFFVUTi1VU0VSRmlyc3Qt -T2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAzNlowgZUxCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxHjAc -BgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3 -dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicP -HxzfOpuCaDDASmEd8S8O+r5596Uj71VRloTN2+O5bj4x2AogZ8f02b+U60cEPgLO -KqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQw5ujm9M89RKZd7G3CeBo -5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vulBe3/IW+ -pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehb -kkj7RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUC -AwEAAaOBrzCBrDALBgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -FgQU2u1kdBScFDyr3ZmpvVsoTYs8ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov -L2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0LmNybDApBgNV -HSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQwDQYJKoZIhvcN -AQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw -NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXB -mMiKVl0+7kNOPmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU -4U3GDZlDAQ0Slox4nb9QorFEqmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK5 -81OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCGhU3IfdeLA/5u1fedFqySLKAj5ZyR -Uh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm -SVBTIENBIENMQVNFQTMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT -JklQUyBDQSBDTEFTRUEzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI -hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjI5MDEwNzUwWhcNMjUxMjI3 -MDEwNzUwWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw -gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO6AAPYaZC6tasiDsYun7o/ZttvN -G7uGBiJ2MwwSbUhWYdLcgiViL5/SaTBlA0IjWLxH3GvWdV0XPOH/8lhneaDBgbHU -VqLyjRGZ/fZ98cfEXgIqmuJKtROKAP2Md4bm15T1IHUuDky/dMQ/gT6DtKM4Ninn -6Cr1jIhBqoCm42zvAgMBAAGjggRTMIIETzAdBgNVHQ4EFgQUHp9XUEe2YZM50yz8 -2l09BXW3mQIwggFGBgNVHSMEggE9MIIBOYAUHp9XUEe2YZM50yz82l09BXW3mQKh -ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC -AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF -BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB -BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg -hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud -EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0VBMyBD -QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cDovL3d3dy5pcHMuZXMvMCkGCWCG -SAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyLzA7BglghkgBhvhC -AQQELhYsaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VBMy5j -cmwwQAYJYIZIAYb4QgEDBDMWMWh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2 -b2NhdGlvbkNMQVNFQTMuaHRtbD8wPQYJYIZIAYb4QgEHBDAWLmh0dHA6Ly93d3cu -aXBzLmVzL2lwczIwMDIvcmVuZXdhbENMQVNFQTMuaHRtbD8wOwYJYIZIAYb4QgEI -BC4WLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VBMy5odG1s -MHUGA1UdHwRuMGwwMqAwoC6GLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvaXBz -MjAwMkNMQVNFQTMuY3JsMDagNKAyhjBodHRwOi8vd3d3YmFjay5pcHMuZXMvaXBz -MjAwMi9pcHMyMDAyQ0xBU0VBMy5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF -BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAEo9IEca -2on0eisxeewBwMwB9dbB/MjD81ACUZBYKp/nNQlbMAqBACVHr9QPDp5gJqiVp4MI -3y2s6Q73nMify5NF8bpqxmdRSmlPa/59Cy9SKcJQrSRE7SOzSMtEQMEDlQwKeAYS -AfWRMS1Jjbs/RU4s4OjNtckUFQzjB4ObJnXv ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV -BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa -GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg -Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J -WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB -rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp -+ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 -ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i -Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz -PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og -/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH -oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI -yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud -EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 -A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL -MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT -ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f -BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn -g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl -fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K -WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha -B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc -hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR -TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD -mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z -ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y -4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza -8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDPDCCAqWgAwIBAgIQEj3w59oqIkekOIngiu7JZzANBgkqhkiG9w0BAQUFADCB -0TELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ -Q2FwZSBUb3duMRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3Rl -IFBlcnNvbmFsIEZyZWVtYWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1m -cmVlbWFpbEB0aGF3dGUuY29tMB4XDTk2MDEwMTAwMDAwMFoXDTIxMDEwMTIzNTk1 -OVowgdExCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNV -BAcTCUNhcGUgVG93bjEaMBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNV -BAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1Ro -YXd0ZSBQZXJzb25hbCBGcmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29u -YWwtZnJlZW1haWxAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC -gYEA1GnX1LCUZFtx6UfYDFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Z -hx2G6qPduc6WZBrCFG5ErHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56 -fAylS1V/Bhkpf56aJtVquzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYD -VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAemGDU5fJUYLA9GoFkR/db -o9lvwykLp9KpgUn2w22FFChFRAH0cVyVLhQPGivRqWvBX2c9FvFyIK++FsoOMF/J -y6WTLMNnVB5yIoojdmyUHVFSbJ3E4EcC18y/8IB7GG4l3GJh1qb+wR1/2bP9jVxF -EFrGZWSa6yz1A0/WSGL7Lg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y -YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua -kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL -QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp -6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG -yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i -QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO -tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu -QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ -Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u -olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 -x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm -MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx -MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT -DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 -dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl -cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 -DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD -gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 -yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX -L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj -EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG -7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e -QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ -qdq5snUb9kLy78fyGPmJvKP/iiMucEc= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEUDCCA7mgAwIBAgIJAN4ppNGwj6yIMA0GCSqGSIb3DQEBBAUAMIHMMQswCQYD -VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j -aXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5jLjEpMCcGA1UECxMgTGluZGVu -IExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIExpbmRlbiBMYWIg -Q2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZIhvcNAQkBFhBjYUBsaW5kZW5s -YWIuY29tMB4XDTA1MDQyMTAyNDAzMVoXDTI1MDQxNjAyNDAzMVowgcwxCzAJBgNV -BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp -c2NvMRkwFwYDVQQKExBMaW5kZW4gTGFiLCBJbmMuMSkwJwYDVQQLEyBMaW5kZW4g -TGFiIENlcnRpZmljYXRlIEF1dGhvcml0eTEpMCcGA1UEAxMgTGluZGVuIExhYiBD -ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgkqhkiG9w0BCQEWEGNhQGxpbmRlbmxh -Yi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKXh1MThucdTbMg9bYBO -rAm8yWns32YojB0PRfbq8rUjepEhTm3/13s0u399Uc202v4ejcGhkIDWJZd2NZMF -oKrhmRfxGHSKPCuFaXC3jh0lRECj7k8FoPkcmaPjSyodrDFDUUuv+C06oYJoI+rk -8REyal9NwgHvqCzOrZtiTXAdAgMBAAGjggE2MIIBMjAdBgNVHQ4EFgQUO1zK2e1f -1wO1fHAjq6DTJobKDrcwggEBBgNVHSMEgfkwgfaAFDtcytntX9cDtXxwI6ug0yaG -yg63oYHSpIHPMIHMMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW -MBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5j -LjEpMCcGA1UECxMgTGluZGVuIExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAn -BgNVBAMTIExpbmRlbiBMYWIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZI -hvcNAQkBFhBjYUBsaW5kZW5sYWIuY29tggkA3imk0bCPrIgwDAYDVR0TBAUwAwEB -/zANBgkqhkiG9w0BAQQFAAOBgQA/ZkgfvwHYqk1UIAKZS3kMCxz0HvYuEQtviwnu -xA39CIJ65Zozs28Eg1aV9/Y+Of7TnWhW+U3J3/wD/GghaAGiKK6vMn9gJBIdBX/9 -e6ef37VGyiOEFFjnUIbuk0RWty0orN76q/lI/xjCi15XSA/VSq2j4vmnwfZcPTDu -glmQ1A== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c -JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP -mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ -wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 -VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ -AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB -AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun -pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC -dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf -fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm -NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx -H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEuDCCA6CgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMCQlIx -EzARBgNVBAoTCklDUC1CcmFzaWwxPTA7BgNVBAsTNEluc3RpdHV0byBOYWNpb25h -bCBkZSBUZWNub2xvZ2lhIGRhIEluZm9ybWFjYW8gLSBJVEkxETAPBgNVBAcTCEJy -YXNpbGlhMQswCQYDVQQIEwJERjExMC8GA1UEAxMoQXV0b3JpZGFkZSBDZXJ0aWZp -Y2Fkb3JhIFJhaXogQnJhc2lsZWlyYTAeFw0wMTExMzAxMjU4MDBaFw0xMTExMzAy -MzU5MDBaMIG0MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE9MDsG -A1UECxM0SW5zdGl0dXRvIE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3Jt -YWNhbyAtIElUSTERMA8GA1UEBxMIQnJhc2lsaWExCzAJBgNVBAgTAkRGMTEwLwYD -VQQDEyhBdXRvcmlkYWRlIENlcnRpZmljYWRvcmEgUmFpeiBCcmFzaWxlaXJhMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwPMudwX/hvm+Uh2b/lQAcHVA -isamaLkWdkwP9/S/tOKIgRrL6Oy+ZIGlOUdd6uYtk9Ma/3pUpgcfNAj0vYm5gsyj -Qo9emsc+x6m4VWwk9iqMZSCK5EQkAq/Ut4n7KuLE1+gdftwdIgxfUsPt4CyNrY50 -QV57KM2UT8x5rrmzEjr7TICGpSUAl2gVqe6xaii+bmYR1QrmWaBSAG59LrkrjrYt -bRhFboUDe1DK+6T8s5L6k8c8okpbHpa9veMztDVC9sPJ60MWXh6anVKo1UcLcbUR -yEeNvZneVRKAAU6ouwdjDvwlsaKydFKwed0ToQ47bmUKgcm+wV3eTRk36UOnTwID -AQABo4HSMIHPME4GA1UdIARHMEUwQwYFYEwBAQAwOjA4BggrBgEFBQcCARYsaHR0 -cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0RQQ2FjcmFpei5wZGYwPQYDVR0f -BDYwNDAyoDCgLoYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0xDUmFj -cmFpei5jcmwwHQYDVR0OBBYEFIr68VeEERM1kEL6V0lUaQ2kxPA3MA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAZA5c1 -U/hgIh6OcgLAfiJgFWpvmDZWqlV30/bHFpj8iBobJSm5uDpt7TirYh1Uxe3fQaGl -YjJe+9zd+izPRbBqXPVQA34EXcwk4qpWuf1hHriWfdrx8AcqSqr6CuQFwSr75Fos -SzlwDADa70mT7wZjAmQhnZx2xJ6wfWlT9VQfS//JYeIc7Fue2JNLd00UOSMMaiK/ -t79enKNHEA2fupH3vEigf5Eh4bVAN5VohrTm6MY53x7XQZZr1ME7a55lFEnSeT0u -mlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5nmPb -K+9A46sd33oqK8n8 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJKUDEO -MAwGA1UEChMFTEdQS0kxGjAYBgNVBAsTEUFwcGxpY2F0aW9uIENBIEcyMB4XDTA2 -MDMzMTE1MDAwMFoXDTE2MDMzMTE0NTk1OVowOTELMAkGA1UEBhMCSlAxDjAMBgNV -BAoTBUxHUEtJMRowGAYDVQQLExFBcHBsaWNhdGlvbiBDQSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBALk1xhD422jbB8RATLAdHjbcw0H2z1UVbQh/ -XMZoVeXnV/GWUebhTXgPbkAVcDtl/hHf59PWWDU74Z8C/JRSRi6znmCbAp7JgtL2 -464JT4REtmKbAFFouDqt7GTRMkvplESDtA7OIYlrsDbAmMZLnMI+W2AqCTErLatM -3rGg/VhWwoMdILzEhAmHe6iVl8YljoPgPpMN0cd9c6mo/BkAQC4iuHozQfV4/Vpx -54LZSIhc7KiFhy1tgIlnGmm+EMBaju2IfT5vLDhrN85H2KIxMN5+U2Vsi4ZTQSBs -vUilfq8AWlYSWIHR3IlZ+bXu+E2a2EQpi3mn9yKq6nxctBaIIA0CAwEAAaOBsjCB -rzAdBgNVHQ4EFgQUf7hdjsQYa8Z9zC7prs405xdd4KEwDgYDVR0PAQH/BAQDAgEG -MEwGA1UdHwRFMEMwQaA/oD2kOzA5MQswCQYDVQQGEwJKUDEOMAwGA1UEChMFTEdQ -S0kxGjAYBgNVBAsTEUFwcGxpY2F0aW9uIENBIEcyMA8GA1UdEwEB/wQFMAMBAf8w -HwYDVR0jBBgwFoAUf7hdjsQYa8Z9zC7prs405xdd4KEwDQYJKoZIhvcNAQEFBQAD -ggEBADzYczZABkhKVBn1J0g5JaVuQue2zRvLOTS3m+xPKr535MqE/B3rmyJA1fT7 -aIdy/Eddag5SSuO1XUjGIpbmM21tq/bN18skWoyoRZ4+YYJ9lNUF8Bo1X3EvLlS1 -QQXvhg1S75yYG/EsTDrR84bTjD56L4ZFjoMyJlu/U8oOUVbcmsJaMBkNp57Vqpsg -OWl4IfSXbdEOEUwu0xtasPmXeFwqj1Jl7kxCJcI3MA5tKzWUgwbor0U7BGanMLv5 -4CE7Y259RF06alPvERck/VSyWmxzViHJbC2XpEKzJ2EFIWNt6ii8TxpvQtyYq1XT -HhvAkj+bweY7F1bixJhDJe62ywA= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsx -CzAJBgNVBAYTAkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRp -ZmljYWNpw7NuIERpZ2l0YWwgLSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwa -QUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4wHhcNMDYxMTI3MjA0NjI5WhcNMzAw -NDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+U29jaWVkYWQgQ2Ft -ZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJhIFMu -QS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkq -hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeG -qentLhM0R7LQcNzJPNCNyu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzL -fDe3fezTf3MZsGqy2IiKLUV0qPezuMDU2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQ -Y5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU34ojC2I+GdV75LaeHM/J4 -Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP2yYe68yQ -54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+b -MMCm8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48j -ilSH5L887uvDdUhfHjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++Ej -YfDIJss2yKHzMI+ko6Kh3VOz3vCaMh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/zt -A/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK5lw1omdMEWux+IBkAC1vImHF -rEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1bczwmPS9KvqfJ -pxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCB -lTCBkgYEVR0gADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFy -YS5jb20vZHBjLzBaBggrBgEFBQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW50 -7WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2UgcHVlZGVuIGVuY29udHJhciBlbiBs -YSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEfAygPU3zmpFmps4p6 -xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuXEpBc -unvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/ -Jre7Ir5v/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dp -ezy4ydV/NgIlqmjCMRW3MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42 -gzmRkBDI8ck1fj+404HGIGQatlDCIaR43NAvO2STdPCWkPHv+wlaNECW8DYSwaN0 -jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wkeZBWN7PGKX6jD/EpOe9+ -XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f/RWmnkJD -W2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/ -RL5hRqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35r -MDOhYil/SrnhLecUIw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxk -BYn8eNZcLCZDqQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy -NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y -LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ -TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y -TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 -LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW -I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw -nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p -dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv -bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa -QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY -BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u -IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl -bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu -Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs -Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI -Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD -ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG -SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH -b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh -KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj -YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM -GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua -BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe -3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 -YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR -rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm -ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU -oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v -QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t -b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF -AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q -GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 -G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi -l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 -smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0f -zGVuDLDQVoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHi -TkVWaR94AoDa3EeRKbs2yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0G -CSqGSIb3DQEBBQUAA4GBAFgVKTk8d6PaXCUDfGD67gmZPCcQcMgMCeazh88K4hiW -NWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n0a3hUKw8fGJLj7qE1xIV -Gx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZRjXZ+Hxb ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJD -TjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2 -MDcwOTE0WhcNMjcwNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMF -Q05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IB -DwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwh -IhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tizVHa6 -dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZO -V/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrC -GHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN -v7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIB -AQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMB -Af8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO -76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnK -OOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvH -ugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7Hgvi -yJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fL -buXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8yGnLRUhj -2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP -Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr -ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL -MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 -yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr -VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ -nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG -XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj -vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt -Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g -N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC -nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg -R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 -9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq -fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv -iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU -1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ -bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW -MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA -ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l -uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn -Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS -tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF -PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un -hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV -5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEc -MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRp -b25DQTAeFw0wNzEyMTIxNTAwMDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYT -AkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zlcm5tZW50MRYwFAYDVQQLEw1BcHBs -aWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp23gdE6H -j6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4fl+K -f5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55 -IrmTwcrNwVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cw -FO5cjFW6WY2H/CPek9AEjP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDiht -QWEjdnjDuGWk81quzMKq2edY3rZ+nYVunyoKb58DKTCXKB28t89UKU5RMfkntigm -/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRUWssmP3HMlEYNllPqa0jQ -k/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNVBAYTAkpQ -MRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOC -seODvOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -ggEBADlqRHZ3ODrso2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJ -hyzjVOGjprIIC8CFqMjSnHH2HZ9g/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+ -eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYDio+nEhEMy/0/ecGc/WLuo89U -DNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmWdupwX3kSa+Sj -B1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL -rosot4LKGAfmt1t06SAZf7IbiVQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs -IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg -R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A -PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8 -Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL -TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL -5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7 -S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe -2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE -FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap -EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td -EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv -/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN -A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0 -abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF -I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz -4iIprn2DQKi6bA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE9zCCA9+gAwIBAgIEPL/xoTANBgkqhkiG9w0BAQUFADB2MQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MSAwHgYDVQQDExdDQyBTaWduZXQgLSBQ -Q0EgS2xhc2EgMjAeFw0wMjA0MTkxMDI5NTNaFw0xNzA0MTgxMjUzMDdaMHUxCzAJ -BgNVBAYTAlBMMR8wHQYDVQQKExZUUCBJbnRlcm5ldCBTcC4geiBvLm8uMSQwIgYD -VQQLExtDZW50cnVtIENlcnR5ZmlrYWNqaSBTaWduZXQxHzAdBgNVBAMTFkNDIFNp -Z25ldCAtIENBIEtsYXNhIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCqgLJuQqY4yavbSgHg8CyfKTx4BokNSDOVz4eD9vptUr11Kqd06ED1hlH7Sg0g -oBFAfntNU/QTKwSBaNuime7C4sSEdgsKrPoAhGb4Mq8y7Ty7RqZz7mkzNMqzL2L2 -U4yQ2QjvpH8MH0IBqOWEcpSkpwnrCDImRoTfd+YlZWKi2JceQixUUYIQ45Ox8+x8 -hHbvvZdgqtcvo8PW27qoHkp/7hMuJ44kDAGrmxffBXl/OBRZp0uO1CSLcMcVJzyr -2phKhy406MYdWrtNPEluGs0GFDzd0nrIctiWAO4cmct4S72S9Q6e//0GO9f3/Ca5 -Kb2I1xYLj/xE+HgjHX9aD2MhAgMBAAGjggGMMIIBiDAPBgNVHRMBAf8EBTADAQH/ -MA4GA1UdDwEB/wQEAwIBBjCB4wYDVR0gBIHbMIHYMIHVBg0rBgEEAb4/AhQKAQEA -MIHDMHUGCCsGAQUFBwICMGkaZ0NlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmll -IHogZG9rdW1lbnRlbTogIlBvbGl0eWthIENlcnR5ZmlrYWNqaSBQQ0EyIC0gQ2Vy -dHlmaWthdHkgVXJ6ZWRvdyBLbGFzeSAyIi4wSgYIKwYBBQUHAgEWPmh0dHA6Ly93 -d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9kb2t1bWVudHkva2xhc2EyL3BjX3Bj -YTIudHh0MD8GA1UdHwQ4MDYwNKAyoDCGLmh0dHA6Ly93d3cuc2lnbmV0LnBsL3Jl -cG96eXRvcml1bS9jcmwvcGNhMi5jcmwwHwYDVR0jBBgwFoAUwGxGyl2CfpYHRonE -82AVXO08kMIwHQYDVR0OBBYEFLtFBlILy4HNKVSzvHxBTM0HDowlMA0GCSqGSIb3 -DQEBBQUAA4IBAQBWTsCbqXrXhBBev5v5cIuc6gJM8ww7oR0uMQRZoFSqvQUPWBYM -2/TLI/f8UM9hSShUVj3zEsSj/vFHagUVmzuVXo5u0WK8iaqATSyEVBhADHrPG6wY -cLKJlagge/ILA0m+SieyP2sjYD9MUB9KZIEyBKv0429UuDTw6P7pslxMWJBSNyQx -aLIs0SRKsqZZWkc7ZYAj2apSkBMX2Is1oHA+PwkF6jQMwCao/+CndXPUzfCF6caa -9WwW31W26MlXCvSmJgfiTPwGvm4PkPmOnmWZ3CczzhHl4q7ztHFzshJH3sZWDnrW -wBFjzz5ePr3WHV1wA7EY6oT4zBx+2gT9XBTB ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC+TCCAmKgAwIBAgIENvEbGTANBgkqhkiG9w0BAQUFADA2MQswCQYDVQQGEwJF -UzENMAsGA1UEChMERk5NVDEYMBYGA1UECxMPRk5NVCBDbGFzZSAyIENBMB4XDTk5 -MDMxODE0NTYxOVoXDTE5MDMxODE1MjYxOVowNjELMAkGA1UEBhMCRVMxDTALBgNV -BAoTBEZOTVQxGDAWBgNVBAsTD0ZOTVQgQ2xhc2UgMiBDQTCBnTANBgkqhkiG9w0B -AQEFAAOBiwAwgYcCgYEAmD+tGTaTPT7+dkIU/TVv8fqtInpY40bQXcZa+WItjzFe -/rQw/lB0rNadHeBixkndFBJ9cQusBsE/1waH4JCJ1uXjA7LyJ7GfM8iqazZKo8Q/ -eUGdiUYvKz5j1DhWkaodsQ1CdU3zh07jD03MtGy/YhOH6tCbjrbi/xn0lAnVlmEC -AQOjggEUMIIBEDARBglghkgBhvhCAQEEBAMCAAcwWAYDVR0fBFEwTzBNoEugSaRH -MEUxCzAJBgNVBAYTAkVTMQ0wCwYDVQQKEwRGTk1UMRgwFgYDVQQLEw9GTk1UIENs -YXNlIDIgQ0ExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5OTAzMTgxNDU2 -MTlagQ8yMDE5MDMxODE0NTYxOVowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFECa -dkSXdAfErBTLHo1POkV8MNdhMB0GA1UdDgQWBBRAmnZEl3QHxKwUyx6NTzpFfDDX -YTAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG -SIb3DQEBBQUAA4GBAGFMoHxZY1tm+O5lE85DgEe5sjXJyITHa3NgReSdN531jiW5 -+aqqyuP4Q5wvoIkFsUUylCoeA41dpt7PV5Xa3yZgX8vflR64zgjY+IrJT6lodZPj -LwVMZGACokIeb4ZoZVUO2ENv8pExPqNHPCgFr0W2nSJMJntLfVsV+RlG3whd ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX -DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl -ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv -b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 -qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp -uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU -Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE -pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp -5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M -UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN -GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy -5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv -6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK -eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 -B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ -BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov -L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG -SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS -CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen -5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 -IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK -gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL -+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL -vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm -bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk -N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC -Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z -ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDcDCCAligAwIBAgIBBTANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQGEwJVUzEY -MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT -A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMjAeFw0wNDEyMTMxNTAwMTBaFw0y -OTEyMDUxNTAwMTBaMFsxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy -bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRYwFAYDVQQDEw1Eb0Qg -Um9vdCBDQSAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwCzB9o07 -rP8/PNZxvrh0IgfscEEV/KtA4weqwcPYn/7aTDq/P8jYKHtLNgHArEUlw9IOCo+F -GGQQPRoTcCpvjtfcjZOzQQ84Ic2tq8I9KgXTVxE3Dc2MUfmT48xGSSGOFLTNyxQ+ -OM1yMe6rEvJl6jQuVl3/7mN1y226kTT8nvP0LRy+UMRC31mI/2qz+qhsPctWcXEF -lrufgOWARVlnQbDrw61gpIB1BhecDvRD4JkOG/t/9bPMsoGCsf0ywbi+QaRktWA6 -WlEwjM7eQSwZR1xJEGS5dKmHQa99brrBuKG/ZTE6BGf5tbuOkooAY7ix5ow4X4P/ -UNU7ol1rshDMYwIDAQABoz8wPTAdBgNVHQ4EFgQUSXS7DF66ev4CVO97oMaVxgmA -cJYwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -ggEBAJiRjT+JyLv1wGlzKTs1rLqzCHY9cAmS6YREIQF9FHYb7lFsHY0VNy17MWn0 -mkS4r0bMNPojywMnGdKDIXUr5+AbmSbchECV6KjSzPZYXGbvP0qXEIIdugqi3VsG -K52nZE7rLgE1pLQ/E61V5NVzqGmbEfGY8jEeb0DU+HifjpGgb3AEkGaqBivO4XqS -tX3h4NGW56E6LcyxnR8FRO2HmdNNGnA5wQQM5X7Z8a/XIA7xInolpHOZzD+kByeW -qKKV7YK5FtOeC4fCwfKI9WLfaN/HvGlR7bFc3FRUKQ8JOZqsA8HbDE2ubwp6Fknx -v5HSOJTT9pUst2zJQraNypCNhdk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDczCCAlugAwIBAgIBBDANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJLUjEN -MAsGA1UECgwES0lTQTEuMCwGA1UECwwlS29yZWEgQ2VydGlmaWNhdGlvbiBBdXRo -b3JpdHkgQ2VudHJhbDEWMBQGA1UEAwwNS0lTQSBSb290Q0EgMTAeFw0wNTA4MjQw -ODA1NDZaFw0yNTA4MjQwODA1NDZaMGQxCzAJBgNVBAYTAktSMQ0wCwYDVQQKDARL -SVNBMS4wLAYDVQQLDCVLb3JlYSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDZW50 -cmFsMRYwFAYDVQQDDA1LSVNBIFJvb3RDQSAxMIIBIDANBgkqhkiG9w0BAQEFAAOC -AQ0AMIIBCAKCAQEAvATk+hM58DSWIGtsaLv623f/J/es7C/n/fB/bW+MKs0lCVsk -9KFo/CjsySXirO3eyDOE9bClCTqnsUdIxcxPjHmc+QZXfd3uOPbPFLKc6tPAXXdi -8EcNuRpAU1xkcK8IWsD3z3X5bI1kKB4g/rcbGdNaZoNy4rCbvdMlFQ0yb2Q3lIVG -yHK+d9VuHygvx2nt54OJM1jT3qC/QOhDUO7cTWu8peqmyGGO9cNkrwYV3CmLP3WM -vHFE2/yttRcdbYmDz8Yzvb9Fov4Kn6MRXw+5H5wawkbMnChmn3AmPC7fqoD+jMUE -CSVPzZNHPDfqAmeS/vwiJFys0izgXAEzisEZ2wIBA6MyMDAwHQYDVR0OBBYEFL+2 -J9gDWnZlTGEBQVYx5Yt7OtnMMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEF -BQADggEBABOvUQveimpb5poKyLGQSk6hAp3MiNKrZr097LuxQpVqslxa/6FjZJap -aBV/JV6K+KRzwYCKhQoOUugy50X4TmWAkZl0Q+VFnUkq8JSV3enhMNITbslOsXfl -BM+tWh6UCVrXPAgcrnrpFDLBRa3SJkhyrKhB2vAhhzle3/xk/2F0KpzZm4tfwjeT -2KM3LzuTa7IbB6d/CVDv0zq+IWuKkDsnSlFOa56ch534eJAx7REnxqhZvvwYC/uO -fi5C4e3nCSG9uRPFVmf0JqZCQ5BEVLRxm3bkGhKsGigA35vB1fjbXKP4krG9tNT5 -UNkAAk/bg9ART6RCVmE6fhMy04Qfybo= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs -ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 -MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD -VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy -ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy -dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p -OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 -8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K -Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe -hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk -6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q -AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI -bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB -ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z -qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd -iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn -0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN -sSi6 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB -ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly -aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl -ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w -NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G -A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD -VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX -SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR -VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 -w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF -mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg -4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 -4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw -EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx -SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 -ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 -vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa -hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi -Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ -/L7fCg0= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEzzCCA7egAwIBAgIEO6ocGTANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBS -b290Q0EwHhcNMDEwOTIwMTY0MjE5WhcNMjYwOTIxMTU0MjE5WjBxMQswCQYDVQQG -EwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMb -Q2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQg -LSBSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrr2vydnNp -ELfGW3KsARiDhJvwDtUe4AbWev+OfMc3+vA29nX8ZmIwno3gmItjo5DbUCCRiCMq -5c9epcGu+kg4a3BJChVXREl8gVh0ST15rr3RKrSc4VgsvQzl0ZUraeQLl8JoRT5P -LsUj3qwF78jUCQVckiiLVcnGfZtFCm+DCJXliQBDMB9XFAUEiO/DtEBs0B7wJGx7 -lgJeJpQUcGiaOPjcJDYOk7rNAYmmD2gWeSlepufO8luUYG/YDxTC4mqhRqfa4MnV -O5dqy+ICj2UvUpHbZDB0KfGRibgBYeQP1kuqgIzJN4UqknVAJb0aMBSPl+9k2fAU -dchx1njlbdcbAgMBAAGjggFtMIIBaTAPBgNVHRMBAf8EBTADAQH/MIIBBAYDVR0g -BIH8MIH5MIH2Bg0rBgEEAb4/AgEKAQEAMIHkMIGaBggrBgEFBQcCAjCBjRqBikNl -cnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmllIHogZG9rdW1lbnRlbTogIlBvbGl0 -eWthIENlcnR5ZmlrYWNqaSBkbGEgUm9vdENBIi4gQ2VydHlmaWthdCB3eXN0YXdp -b255IHByemV6IFJvb3RDQSB3IGhpZXJhcmNoaWkgQ0MgU2lnbmV0LjBFBggrBgEF -BQcCARY5aHR0cDovL3d3dy5zaWduZXQucGwvcmVwb3p5dG9yaXVtL2Rva3VtZW50 -eS9wY19yb290Y2EudHh0MB0GA1UdDgQWBBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAf -BgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAOBgNVHQ8BAf8EBAMCAQYw -DQYJKoZIhvcNAQEFBQADggEBAGnY5QmYqnnO9OqFOWZxxb25UHRnaRF6IV9aaGit -5BZufZj2Tq3v8L3SgE34GOoIcdRMMG5JEpEU4mN/Ef3oY6Eo+7HfqaPHI4KFmbDS -PiK5s+wmf+bQSm0Yq5/h4ZOdcAESlLQeLSt1CQk2JoKQJ6pyAf6xJBgWEIlm4RXE -4J3324PUiOp83kW6MDvaa1xY976WyInr4rwoLgxVl11LZeKWha0RJJxJgw/NyWpK -G7LWCm1fglF8JH51vZNndGYq1iKtfnrIOvLZq6bzaCiZm1EurD8HE6P7pmABKK6o -3C2OXlNfNIgwkDN/cDqk5TYsTkrpfriJPdxXBH8hQOkW89g= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM -HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK -qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj -cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y -cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP -T8qAkbYp ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE -BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is -I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G -CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i -2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ -2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH/zCCB2igAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm -SVBTIENBIENMQVNFQTEgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT -JklQUyBDQSBDTEFTRUExIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI -hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjMxMTEyMTQxWhcNMjUxMjI5 -MTEyMTQxWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw -gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM8g89BgSKoCxBXZ5C+NnlURLSnM -UWZoAGXaFFWf6q7f69uN1nXaUfTEzPstvTUfE7fpZmF8lEDz+2AvjBg086hVnra0 -b0APA0VnanJyW2ZIlkKFGMCB4WJqh7JB7i45jITVXthPV2vsjlKM97Pnnhimz8Fb -r+RZcsz69vRptMqxAgMBAAGjggRbMIIEVzAdBgNVHQ4EFgQUL8zsbGe+T/iqPIiN -EvvHnUxb9F4wggFGBgNVHSMEggE9MIIBOYAUL8zsbGe+T/iqPIiNEvvHnUxb9F6h -ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC -AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF -BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB -BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg -hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud -EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBDBglghkgBhvhCAQ0ENhY0Q0xBU0VBMSBD -QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cHM6Ly93d3cuaXBzLmVzLzAqBglg -hkgBhvhCAQIEHRYbaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDwGCWCGSAGG -+EIBBAQvFi1odHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VB -MS5jcmwwQQYJYIZIAYb4QgEDBDQWMmh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAy -L3Jldm9jYXRpb25DTEFTRUExLmh0bWw/MD4GCWCGSAGG+EIBBwQxFi9odHRwczov -L3d3dy5pcHMuZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0VBMS5odG1sPzA8BglghkgB -hvhCAQgELxYtaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VB -MS5odG1sMHcGA1UdHwRwMG4wM6AxoC+GLWh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMy -MDAyL2lwczIwMDJDTEFTRUExLmNybDA3oDWgM4YxaHR0cHM6Ly93d3diYWNrLmlw -cy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRUExLmNybDAvBggrBgEFBQcBAQQjMCEw -HwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQAD -gYEAGY2khC4v4mlenqRcy8Mn8mcWca88t4CY9LCJMqlIt7i559BNkMMB66tXsNp9 -N2QhnTordKOjkdgZJmCb7DUdMJEQQT0Y5W7JA6WvHatAFu8feRJ4ImaTjI0Xz3Dd -Jbz6O++igCw0l4EY5gayn2BFpAm+7ZpEcdpR/OCOH80lNDo= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJE -SzEVMBMGA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQg -Um9vdCBDQTAeFw0wMTA0MDUxNjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNV -BAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJuZXQxHTAbBgNVBAsTFFREQyBJbnRl -cm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLhA -vJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20jxsNu -Zp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a -0vnRrEvLznWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc1 -4izbSysseLlJ28TQx5yc5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGN -eGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcD -R0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZIAYb4QgEBBAQDAgAHMGUG -A1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMMVERDIElu -dGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxME -Q1JMMTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3 -WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAw -HQYDVR0OBBYEFGxkAcf9hW2syNqeUAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJ -KoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQBO -Q8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540mgwV5dOy0uaOX -wTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ -2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm89 -9qNLPg7kbWzbO0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0 -jUNAE4z9mQNUecYu6oah9jrUCbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38 -aQNiuJkFBT1reBK9sG9l ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 -GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ -+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd -U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm -NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY -ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ -ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 -CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq -g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm -fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c -2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ -bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 -MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK -EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh -BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq -xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G -87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i -2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U -WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 -0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G -A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr -pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL -ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm -aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv -hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm -hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X -dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 -P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y -iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no -xqE= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT -ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw -MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj -dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l -c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC -UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc -58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ -o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH -MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr -aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA -A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA -Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv -8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp -IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi -BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw -MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh -d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig -YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v -dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ -BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 -papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K -DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 -KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox -XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFUjCCBDqgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJLUjEN -MAsGA1UEChMES0lTQTEuMCwGA1UECxMlS29yZWEgQ2VydGlmaWNhdGlvbiBBdXRo -b3JpdHkgQ2VudHJhbDEWMBQGA1UEAxMNS0lTQSBSb290Q0EgMzAeFw0wNDExMTkw -NjM5NTFaFw0xNDExMTkwNjM5NTFaMGQxCzAJBgNVBAYTAktSMQ0wCwYDVQQKEwRL -SVNBMS4wLAYDVQQLEyVLb3JlYSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDZW50 -cmFsMRYwFAYDVQQDEw1LSVNBIFJvb3RDQSAzMIIBIDANBgkqhkiG9w0BAQEFAAOC -AQ0AMIIBCAKCAQEA3rrtF2Wu0b1KPazbgHLMWOHn4ZPazDB6z+8Lri2nQ6u/p0LP -CFYIpEcdffqG79gwlyY0YTyADvjU65/8IjAboW0+40zSVU4WQDfC9gdu2we1pYyW -geKbXH6UYcjOhDyx+gDmctMJhXfp3F4hT7TkTvTiF6tQrxz/oTlYdVsSspa5jfBw -YkhbVigqpYeRNrkeJPW5unu2UlFbF1pgBWycwubGjD756t08jP+J3kNwrB248XXN -OMpTDUdoasY8GMq94bS+DvTQ49IT+rBRERHUQavo9DmO4TSETwuTqmo4/OXGeEeu -dhf6oYA3BgAVCP1rI476cg2V1ktisWjC3TSbXQIBA6OCAg8wggILMB8GA1UdIwQY -MBaAFI+B8NqmzXQ8vmb0FWtGpP4GKMyqMB0GA1UdDgQWBBSPgfDaps10PL5m9BVr -RqT+BijMqjAOBgNVHQ8BAf8EBAMCAQYwggEuBgNVHSAEggElMIIBITCCAR0GBFUd -IAAwggETMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LnJvb3RjYS5vci5rci9yY2Ev -Y3BzLmh0bWwwgd4GCCsGAQUFBwICMIHRHoHOx3QAIMd4yZ3BHLKUACCs9cd4x3jJ -ncEcx4WyyLLkACgAVABoAGkAcwAgAGMAZQByAHQAaQBmAGkAYwBhAHQAZQAgAGkA -cwAgAGEAYwBjAHIAZQBkAGkAdABlAGQAIAB1AG4AZABlAHIAIABFAGwAZQBjAHQA -cgBvAG4AaQBjACAAUwBpAGcAbgBhAHQAdQByAGUAIABBAGMAdAAgAG8AZgAgAHQA -aABlACAAUgBlAHAAdQBiAGwAaQBjACAAbwBmACAASwBvAHIAZQBhACkwMwYDVR0R -BCwwKqQoMCYxJDAiBgNVBAMMG+2VnOq1reygleuztOuztO2YuOynhO2dpeybkDAz -BgNVHRIELDAqpCgwJjEkMCIGA1UEAwwb7ZWc6rWt7KCV67O067O07Zi47KeE7Z2l -7JuQMA8GA1UdEwEB/wQFMAMBAf8wDAYDVR0kBAUwA4ABADANBgkqhkiG9w0BAQUF -AAOCAQEAz9b3Dv2wjG4FFY6oXCuyWtEeV6ZeGKqCEQj8mbdbp+PI0qLT+SQ09+Pk -rolUR9NpScmAwRHr4inH9gaLX7riXs+rw87P7pIl3J85Hg4D9N6QW6FwmVzHc07J -pHVJeyWhn4KSjU3sYcUMMqfHODiAVToqgx2cZHm5Dac1Smjvj/8F2LpOVmHY+Epw -mAiWk9hgxzrsX58dKzVPSBShmrtv7tIDhlPxEMcHVGJeNo7iHCsdF03m9VrvirqC -6HfZKBF+N4dKlArJQOk1pTr7ZD7yXxZ683bXzu4/RB1Fql8RqlMcOh9SUWJUD6OQ -Nc9Nb7rHviwJ8TX4Absk3TC8SA/u2Q== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDoTCCAomgAwIBAgIQKTZHquOKrIZKI1byyrdhrzANBgkqhkiG9w0BAQUFADBO -MQswCQYDVQQGEwJ1czEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQ0wCwYDVQQL -EwRGQkNBMRYwFAYDVQQDEw1Db21tb24gUG9saWN5MB4XDTA3MTAxNTE1NTgwMFoX -DTI3MTAxNTE2MDgwMFowTjELMAkGA1UEBhMCdXMxGDAWBgNVBAoTD1UuUy4gR292 -ZXJubWVudDENMAsGA1UECxMERkJDQTEWMBQGA1UEAxMNQ29tbW9uIFBvbGljeTCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJeNvTMn5K1b+3i9L0dHbsd4 -6ZOcpN7JHP0vGzk4rEcXwH53KQA7Ax9oD81Npe53uCxiazH2+nIJfTApBnznfKM9 -hBiKHa4skqgf6F5PjY7rPxr4nApnnbBnTfAu0DDew5SwoM8uCjR/VAnTNr2kSVdS -c+md/uRIeUYbW40y5KVIZPMiDZKdCBW/YDyD90ciJSKtKXG3d+8XyaK2lF7IMJCk -FEhcVlcLQUwF1CpMP64Sm1kRdXAHImktLNMxzJJ+zM2kfpRHqpwJCPZLr1LoakCR -xVW9QLHIbVeGlRfmH3O+Ry4+i0wXubklHKVSFzYIWcBCvgortFZRPBtVyYyQd+sC -AwEAAaN7MHkwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -BBYEFC9Yl9ipBZilVh/72at17wI8NjTHMBIGCSsGAQQBgjcVAQQFAgMBAAEwIwYJ -KwYBBAGCNxUCBBYEFHa3YJbdFFYprHWF03BjwbxHhhyLMA0GCSqGSIb3DQEBBQUA -A4IBAQBgrvNIFkBypgiIybxHLCRLXaCRc+1leJDwZ5B6pb8KrbYq+Zln34PFdx80 -CTj5fp5B4Ehg/uKqXYeI6oj9XEWyyWrafaStsU+/HA2fHprA1RRzOCuKeEBuMPdi -4c2Z/FFpZ2wR3bgQo2jeJqVW/TZsN5hs++58PGxrcD/3SDcJjwtCga1GRrgLgwb0 -Gzigf0/NC++DiYeXHIowZ9z9VKEDfgHLhUyxCynDvux84T8PCVI8L6eaSP436REG -WOE2QYrEtr+O3c5Ks7wawM36GpnScZv6z7zyxFSjiDV2zBssRm8MtNHDYXaSdBHq -S4CNHIkRi+xb/xfJSPzn4AYR4oRe ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOc -UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx -c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xS -S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg -SGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4XDTA3MTIyNTE4Mzcx -OVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxla3Ry -b25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMC -VFIxDzANBgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDE -sGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7F -ni4gKGMpIEFyYWzEsWsgMjAwNzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9NYvDdE3ePYakqtdTyuTFY -KTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQvKUmi8wUG -+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveG -HtyaKhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6P -IzdezKKqdfcYbwnTrqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M -733WB2+Y8a+xwXrXgTW4qhe04MsCAwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHk -Yb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G -CSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/sPx+EnWVUXKgW -AkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I -aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5 -mxRZNTZPz/OOXl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsa -XRik7r4EW5nVcV9VZWRi1aKbBFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZ -qxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAKpoRq0Tl9 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB -gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw -MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl -YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P -RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 -UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI -2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 -Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp -+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ -DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O -nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW -/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g -PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u -QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY -SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv -IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 -zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd -BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB -ZQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIIQTCCB6qgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCAR4xCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjE0MDIGA1UECxMr -SVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE0MDIG -A1UEAxMrSVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eTEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIzMTExMjY0 -M1oXDTI1MTIyOTExMjY0M1owggEeMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFy -Y2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5l -dCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlw -cy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxNDAyBgNVBAsTK0lQUyBDQSBUaW1lc3Rh -bXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxNDAyBgNVBAMTK0lQUyBDQSBU -aW1lc3RhbXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHjAcBgkqhkiG9w0B -CQEWD2lwc0BtYWlsLmlwcy5lczCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA -0umTdn+FPP2gAb0RL0ZCDyt/BZvGa/VRcayaUh8flSfMkO+WP45RNv0WAM43pSGU -Rmvt5P+hfuqf0aKbOPMTxLmYumVFQ/nXvRWdlC4AYN6YGrk8yfXh/NbEJN/n48iE -GRK0HFyz9eIWYSdg8vAt5PDzrPigeYSdReL2AfBE5ZECAwEAAaOCBIkwggSFMB0G -A1UdDgQWBBSR2UK8nKnK0Bw3E1JXFqANHikdPjCCAVAGA1UdIwSCAUcwggFDgBSR -2UK8nKnK0Bw3E1JXFqANHikdPqGCASakggEiMIIBHjELMAkGA1UEBhMCRVMxEjAQ -BgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJ -UFMgSW50ZXJuZXQgcHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJp -cHNAbWFpbC5pcHMuZXMgQy5JLkYuICBCLTYwOTI5NDUyMTQwMgYDVQQLEytJUFMg -Q0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTQwMgYDVQQD -EytJUFMgQ0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4w -HAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAM -BgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYB -BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIB -FgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYD -VR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlw -cy5lczBIBglghkgBhvhCAQ0EOxY5VGltZXN0YW1waW5nIENBIENlcnRpZmljYXRl -IGlzc3VlZCBieSBodHRwczovL3d3dy5pcHMuZXMvMCoGCWCGSAGG+EIBAgQdFhto -dHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi8wQQYJYIZIAYb4QgEEBDQWMmh0dHBz -Oi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMEYG -CWCGSAGG+EIBAwQ5FjdodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0 -aW9uVGltZXN0YW1waW5nLmh0bWw/MEMGCWCGSAGG+EIBBwQ2FjRodHRwczovL3d3 -dy5pcHMuZXMvaXBzMjAwMi9yZW5ld2FsVGltZXN0YW1waW5nLmh0bWw/MEEGCWCG -SAGG+EIBCAQ0FjJodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lUaW1l -c3RhbXBpbmcuaHRtbDCBgQYDVR0fBHoweDA4oDagNIYyaHR0cHM6Ly93d3cuaXBz -LmVzL2lwczIwMDIvaXBzMjAwMlRpbWVzdGFtcGluZy5jcmwwPKA6oDiGNmh0dHBz -Oi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyVGltZXN0YW1waW5nLmNy -bDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5l -cy8wDQYJKoZIhvcNAQEFBQADgYEAxKMCdGABCUwYXU900W1zDCfTSDC1TxFVGRnH -I4soqfp4D34sJ/adkgD2GMgkAMVf+C1MY/yQFV4nmOal9K7SNrG1JR8OeDoRjpM4 -rtO9qYbuHD3TW47/y/aZSZxP4ccocGpPOkvqfrnndKRKY0WUk/7Qg5aqpIXni2Gg -olkTZbQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC -Q04xMjAwBgNVBAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24g -Q2VudGVyMUcwRQYDVQQDDD5DaGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0 -aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMgUm9vdDAeFw0xMDA4MzEwNzExMjVa -Fw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEg -SW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNo -aW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRp -ZmljYXRlcyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z -7r07eKpkQ0H1UN+U8i6yjUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA// -DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV98YPjUesWgbdYavi7NifFy2cyjw1l1Vx -zUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2HklY0bBoQCxfVWhyXWIQ8 -hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23KzhmBsUs -4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54u -gQEC7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oY -NJKiyoOCWTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E -FgQUfHJLOcfA22KlT5uqGDSSosqDglkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3 -j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd50XPFtQO3WKwMVC/GVhMPMdoG -52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM7+czV0I664zB -echNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws -ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrI -zo9uoV1/A3U05K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATy -wy39FCqQmbkHzJ8= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP -bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2 -MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft -ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk -hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym -1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW -OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb -2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko -O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU -AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF -Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb -LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir -oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C -MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds -sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy -NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD -cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs -2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY -JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE -Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ -n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A -PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCB -ozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3Qt -TmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5WhcNMTkwNzA5MTg1 -NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0 -IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD -VQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VS -Rmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB -DwAwggEKAoIBAQCz+5Gh5DZVhawGNFugmliy+LUPBXeDrjKxdpJo7CNKyXY/45y2 -N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4CjDUeJT1FxL+78P/m4FoCH -iZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXuOzr0hARe -YFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1 -axwiP8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6g -yN7igEL66S/ozjIEj3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQD -AgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPh -ahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9V -VE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0GCSqGSIb3DQEB -BQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y -IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6Lzs -QCv4AdRWOOTKRIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4 -ZSfP1FMa8Kxun08FDAOBp4QpxFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qM -YEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAqDbUMo2s/rn9X9R+WfN9v3YIwLGUb -QErNaLly7HF27FSOH4UMAWr6pjisH8SE ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy -c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD -VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 -c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 -WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG -FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq -XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL -se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb -KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd -IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 -y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt -hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc -QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 -Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV -HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ -KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z -dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ -L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr -Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo -ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY -T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz -GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m -1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV -OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH -6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX -QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE -BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu -IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw -WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD -ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y -IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn -IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+ -6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob -jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw -izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl -+zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY -zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP -pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF -KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW -ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB -AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0 -ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW -IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA -A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0 -uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+ -FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7 -jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/ -u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D -YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1 -puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa -icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG -DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x -kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z -Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE -FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j -ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js -LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM -BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 -Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy -dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh -cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh -YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg -dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp -bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ -YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT -TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ -9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 -jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW -FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz -ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 -ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L -EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu -L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq -yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC -O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V -um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh -NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm -SVBTIENBIENMQVNFQTEgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT -JklQUyBDQSBDTEFTRUExIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI -hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjI5MDEwNTMyWhcNMjUxMjI3 -MDEwNTMyWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw -gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALsw19zQVL01Tp/FTILq0VA8R5j8 -m2mdd81u4D/u6zJfX5/S0HnllXNEITLgCtud186Nq1KLK3jgm1t99P1tCeWu4Wwd -ByOgF9H5fahGRpEiqLJpxq339fWUoTCUvQDMRH/uxJ7JweaPCjbB/SQ9AaD1e+J8 -eGZDi09Z8pvZ+kmzAgMBAAGjggRTMIIETzAdBgNVHQ4EFgQUZyaW56G/2LUDnf47 -3P7yiuYV3TAwggFGBgNVHSMEggE9MIIBOYAUZyaW56G/2LUDnf473P7yiuYV3TCh -ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC -AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF -BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB -BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg -hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud -EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0VBMSBD -QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cDovL3d3dy5pcHMuZXMvMCkGCWCG -SAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyLzA7BglghkgBhvhC -AQQELhYsaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VBMS5j -cmwwQAYJYIZIAYb4QgEDBDMWMWh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2 -b2NhdGlvbkNMQVNFQTEuaHRtbD8wPQYJYIZIAYb4QgEHBDAWLmh0dHA6Ly93d3cu -aXBzLmVzL2lwczIwMDIvcmVuZXdhbENMQVNFQTEuaHRtbD8wOwYJYIZIAYb4QgEI -BC4WLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VBMS5odG1s -MHUGA1UdHwRuMGwwMqAwoC6GLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvaXBz -MjAwMkNMQVNFQTEuY3JsMDagNKAyhjBodHRwOi8vd3d3YmFjay5pcHMuZXMvaXBz -MjAwMi9pcHMyMDAyQ0xBU0VBMS5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF -BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAH66iqyA -AIQVCtWYUQxkxZwCWINmyq0eB81+atqAB98DNEock8RLWCA1NnHtogo1EqWmZaeF -aQoO42Hu6r4okzPV7Oi+xNtff6j5YzHIa5biKcJboOeXNp13XjFr/tOn2yrb25aL -H2betgPAK7N41lUH5Y85UN4HI3LmvSAUS7SG ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGjCCAwKgAwIBAgIDAYagMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYDVQQGEwJG -STEQMA4GA1UECBMHRmlubGFuZDEhMB8GA1UEChMYVmFlc3RvcmVraXN0ZXJpa2Vz -a3VzIENBMSkwJwYDVQQLEyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBTZXJ2aWNl -czEZMBcGA1UECxMQVmFybWVubmVwYWx2ZWx1dDEZMBcGA1UEAxMQVlJLIEdvdi4g -Um9vdCBDQTAeFw0wMjEyMTgxMzUzMDBaFw0yMzEyMTgxMzUxMDhaMIGjMQswCQYD -VQQGEwJGSTEQMA4GA1UECBMHRmlubGFuZDEhMB8GA1UEChMYVmFlc3RvcmVraXN0 -ZXJpa2Vza3VzIENBMSkwJwYDVQQLEyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBT -ZXJ2aWNlczEZMBcGA1UECxMQVmFybWVubmVwYWx2ZWx1dDEZMBcGA1UEAxMQVlJL -IEdvdi4gUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALCF -FdrIAzfQo0Y3bBseljDCWoUSZyPyu5/nioFgJ/gTqTy894aqqvTzJSm0/nWuHoGG -igWyHWWyOOi0zCia+xc28ZPVec7Bg4shT8MNrUHfeJ1I4x9CRPw8bSEga60ihCRC -jxdNwlAfZM0tOSJWiP2yY51U2kJpwMhP1xjiPshphJQ9LIDGfM6911Mf64i5psu7 -hVfvV3ZdDIvTXhJBnyHAOfQmbQj6OLOhd7HuFtjQaNq0mKWgZUZKa41+qk1guPjI -DfxxPu45h4G02fhukO4/DmHXHSto5i7hQkQmeCxY8n0Wf2HASSQqiYe2XS8pGfim -545SnkFLWg6quMJmQlMCAwEAAaNVMFMwDwYDVR0TAQH/BAUwAwEB/zARBglghkgB -hvhCAQEEBAMCAAcwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBTb6eGb0tEkC/yr -46Bn6q6cS3f0sDANBgkqhkiG9w0BAQUFAAOCAQEArX1ID1QRnljurw2bEi8hpM2b -uoRH5sklVSPj3xhYKizbXvfNVPVRJHtiZ+GxH0mvNNDrsczZog1Sf0JLiGCXzyVy -t08pLWKfT6HAVVdWDsRol5EfnGTCKTIB6dTI2riBmCguGMcs/OubUpbf9MiQGS0j -8/G7cdqehSO9Gu8u5Hp5t8OdhkktY7ktdM9lDzJmid87Ie4pbzlj2RXBbvbfgD5Q -eBmK3QOjFKU3p7UsfLYRh+cF8ry23tT/l4EohP7+bEaFEEGfTXWMB9SZZ291im/k -UJL2mdUQuMSpe/cXjUu/15WfCdxEDx4yw8DP03kN5Mc7h/CQNIghYkmSBAQfvA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE -BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu -IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow -RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY -U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv -Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br -YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF -nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH -6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt -eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ -c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ -MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH -HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf -jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 -5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB -rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU -F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c -wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 -cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB -AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp -WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 -xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ -2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ -IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 -aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X -em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR -dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ -OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ -hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy -tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk -MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 -YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg -Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT -AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp -Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN -BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9 -m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih -FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/ -TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F -EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco -kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu -HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF -vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo -19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC -L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW -bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX -JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw -FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j -BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc -K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf -ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik -Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB -sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e -3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR -ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip -mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH -b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf -rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms -hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y -zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6 -MBr1mmz0DlP5OlvRHA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDQzCCAiugAwIBAgIQX/h7KCtU3I1CoxW1aMmt/zANBgkqhkiG9w0BAQUFADA1 -MRYwFAYDVQQKEw1DaXNjbyBTeXN0ZW1zMRswGQYDVQQDExJDaXNjbyBSb290IENB -IDIwNDgwHhcNMDQwNTE0MjAxNzEyWhcNMjkwNTE0MjAyNTQyWjA1MRYwFAYDVQQK -Ew1DaXNjbyBTeXN0ZW1zMRswGQYDVQQDExJDaXNjbyBSb290IENBIDIwNDgwggEg -MA0GCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQCwmrmrp68Kd6ficba0ZmKUeIhH -xmJVhEAyv8CrLqUccda8bnuoqrpu0hWISEWdovyD0My5jOAmaHBKeN8hF570YQXJ -FcjPFto1YYmUQ6iEqDGYeJu5Tm8sUxJszR2tKyS7McQr/4NEb7Y9JHcJ6r8qqB9q -VvYgDxFUl4F1pyXOWWqCZe+36ufijXWLbvLdT6ZeYpzPEApk0E5tzivMW/VgpSdH -jWn0f84bcN5wGyDWbs2mAag8EtKpP6BrXruOIIt6keO1aO6g58QBdKhTCytKmg9l -Eg6CTY5j/e/rmxrbU6YTYK/CfdfHbBcl1HP7R2RQgYCUTOG/rksc35LtLgXfAgED -o1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUJ/PI -FR5umgIJFq0roIlgX9p7L6owEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEF -BQADggEBAJ2dhISjQal8dwy3U8pORFBi71R803UXHOjgxkhLtv5MOhmBVrBW7hmW -Yqpao2TB9k5UM8Z3/sUcuuVdJcr18JOagxEu5sv4dEX+5wW4q+ffy0vhN4TauYuX -cB7w4ovXsNgOnbFp1iqRe6lJT37mjpXYgyc81WhJDtSd9i7rp77rMKSsH0T8lasz -Bvt9YAretIpjsJyp8qS5UwGH0GikJ3+r/+n6yUA4iGe0OcaEb1fJU9u6ju7AQ7L4 -CYNu/2bPPu8Xs1gYJQk0XuPL1hS27PKSb3TkL4Eq1ZKR4OCXPDJoBYVL0fdX4lId -kxpUnwVwwEpxYB5DC2Ae/qPOgRnhCzU= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ -MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow -PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR -IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q -gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy -yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts -F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 -jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx -ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC -VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK -YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH -EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN -Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud -DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE -MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK -UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ -TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf -qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK -ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE -JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 -hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 -EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm -nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX -udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz -ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe -LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl -pYYsfPQS ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 -Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW -KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw -NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw -NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy -ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV -BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo -Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 -4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 -KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI -rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi -94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB -sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi -gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo -kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE -vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t -O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua -AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP -9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ -eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m -0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY -MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo -R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx -MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK -Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 -AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA -ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 -7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W -kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI -mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ -KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 -6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl -4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K -oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj -UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU -AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz -MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw -IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR -dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp -li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D -rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ -WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug -F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU -xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC -Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv -dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw -ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl -IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh -c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy -ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh -Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI -KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T -KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq -y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p -dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD -VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL -MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk -fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 -7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R -cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y -mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW -xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK -SnQ2+Q== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMx -IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 -dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 -MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w -HhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTELMAkGA1UEBhMCRVMx -IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 -dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 -MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5u -Cp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5Vj1H5WuretXDE7aTt/6MNbg9kUDGvASdY -rv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJHlShbz++AbOCQl4oBPB3z -hxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf3H5idPay -BQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcL -iam8NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcb -AgMBAAGjgZ8wgZwwKgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lv -bmFsLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0 -MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E -FgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQADggEBAEdz/o0n -VPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq -u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36m -hoEyIwOdyPdfwUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzfl -ZKG+TQyTmAyX9odtsz/ny4Cm7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBp -QWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YGVM+h4k0460tQtcsm9MracEpqoeJ5 -quGnM/b9Sh/22WA= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 -aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla -MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO -BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD -VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW -fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt -TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL -fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW -1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 -kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G -A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v -ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo -dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu -Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ -HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 -pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS -jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ -xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn -dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 -nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO -8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV -ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb -PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 -6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr -n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a -qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 -wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 -ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs -pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 -E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV -BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 -Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1 -OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i -SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc -VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf -tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg -uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J -XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK -8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99 -5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3 -kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy -dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6 -Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz -JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 -Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS -GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt -ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8 -au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV -hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI -dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB -qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV -BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw -NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j -LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG -A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs -W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta -3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk -6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 -Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J -NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP -r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU -DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz -YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX -xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 -/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ -LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 -jVaMaA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx -MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o -Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt -5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s -3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej -vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu -8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil -zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ -3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD -FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 -Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 -ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx -MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB -ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV -BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV -6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX -GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP -dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH -1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF -62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW -BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw -AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL -MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU -cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv -b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 -IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ -iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao -GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh -4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm -XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH6jCCB1OgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl -SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl -SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 -DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAxMDE0NFoXDTI1MTIyNzAx -MDE0NFowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD -VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n -IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g -IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxf+DrDGaBtT8FK+n/ra+osTBLsBjzLZ -H49NzjaY2uQARIwo2BNEKqRrThckQpzTiKRBgtYj+4vJhuW5qYIF3PHeH+AMmVWY -8jjsbJ0gA8DvqqPGZARRLXgNo9KoOtYkTOmWehisEyMiG3zoMRGzXwmqMHBxRiVr -SXGAK5UBsh8CAwEAAaOCBEowggRGMB0GA1UdDgQWBBS4k/8uy9wsjqLnev42USGj -mFsMNDCCAUQGA1UdIwSCATswggE3gBS4k/8uy9wsjqLnev42USGjmFsMNKGCARqk -ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE -BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT -ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC -LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD -VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr -BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB -FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC -AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB -D2lwc0BtYWlsLmlwcy5lczBBBglghkgBhvhCAQ0ENBYyQ0xBU0UzIENBIENlcnRp -ZmljYXRlIGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgEC -BBwWGmh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDoGCWCGSAGG+EIBBAQtFito -dHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMuY3JsMD8GCWCG -SAGG+EIBAwQyFjBodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25D -TEFTRTMuaHRtbD8wPAYJYIZIAYb4QgEHBC8WLWh0dHA6Ly93d3cuaXBzLmVzL2lw -czIwMDIvcmVuZXdhbENMQVNFMy5odG1sPzA6BglghkgBhvhCAQgELRYraHR0cDov -L3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTMuaHRtbDBzBgNVHR8EbDBq -MDGgL6AthitodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMu -Y3JsMDWgM6Axhi9odHRwOi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy -Q0xBU0UzLmNybDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9v -Y3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQADgYEAF2VcmZVDAyevJuXr0LMXI/dD -qsfwfewPxqmurpYPdikc4gYtfibFPPqhwYHOU7BC0ZdXGhd+pFFhxu7pXu8Fuuu9 -D6eSb9ijBmgpjnn1/7/5p6/ksc7C0YBCJwUENPjDfxZ4IwwHJPJGR607VNCv1TGy -r33I6unUVtkOE7LFRVA= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES -MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU -V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz -WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO -LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE -AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH -K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX -RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z -rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx -3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq -hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC -MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls -XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D -lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn -aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ -YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDODCCAqGgAwIBAgIQQAWyU6AaRkNQCYGPEhB27DANBgkqhkiG9w0BAQUFADCB -zzELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ -Q2FwZSBUb3duMRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3Rl -IFBlcnNvbmFsIFByZW1pdW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXBy -ZW1pdW1AdGhhd3RlLmNvbTAeFw05NjAxMDEwMDAwMDBaFw0yMTAxMDEyMzU5NTla -MIHPMQswCQYDVQQGEwJaQTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQH -EwlDYXBlIFRvd24xGjAYBgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQL -Ex9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3 -dGUgUGVyc29uYWwgUHJlbWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwt -cHJlbWl1bUB0aGF3dGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ -Ztn4B0TPuYwu8KHvE0VsBd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O -0DI3lIi1DbbZ8/JE2dWIEt12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8f -AHB8Zs8QJQi6+u4A6UYDZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMB -Af8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBALpkCujztDHJJ2+idqAtNnHHhsAI -wk7t2pokGYf8WiOcck0I361cwzskgR1Xj7YSpSID7xK90S1elo8mJk9LG3w7oFIa -pag3hsRHKsrdQfho9cITQSma8AyozaH8FSMC23or1GJRQkfEox/00sVNVBDr2vDM -p083DL08yxDjGugV ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH6jCCB1OgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl -SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl -SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 -DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAwNTkzOFoXDTI1MTIyNzAw -NTkzOFowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD -VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n -IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g -IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4FEnpwvdr9G5Q1uCN0VWcu+atsIS7ywS -zHb5BlmvXSHU0lq4oNTzav3KaY1mSPd05u42veiWkXWmcSjK5yISMmmwPh5r9FBS -YmL9Yzt9fuzuOOpi9GyocY3h6YvJP8a1zZRCb92CRTzo3wno7wpVqVZHYUxJZHMQ -KD/Kvwn/xi8CAwEAAaOCBEowggRGMB0GA1UdDgQWBBTrsxl588GlHKzcuh9morKb -adB4CDCCAUQGA1UdIwSCATswggE3gBTrsxl588GlHKzcuh9morKbadB4CKGCARqk -ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE -BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT -ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC -LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD -VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr -BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB -FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC -AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB -D2lwc0BtYWlsLmlwcy5lczBBBglghkgBhvhCAQ0ENBYyQ0xBU0UxIENBIENlcnRp -ZmljYXRlIGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgEC -BBwWGmh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDoGCWCGSAGG+EIBBAQtFito -dHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEuY3JsMD8GCWCG -SAGG+EIBAwQyFjBodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25D -TEFTRTEuaHRtbD8wPAYJYIZIAYb4QgEHBC8WLWh0dHA6Ly93d3cuaXBzLmVzL2lw -czIwMDIvcmVuZXdhbENMQVNFMS5odG1sPzA6BglghkgBhvhCAQgELRYraHR0cDov -L3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTEuaHRtbDBzBgNVHR8EbDBq -MDGgL6AthitodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEu -Y3JsMDWgM6Axhi9odHRwOi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy -Q0xBU0UxLmNybDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9v -Y3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQADgYEAK9Dr/drIyllq2tPMMi7JVBuK -Yn4VLenZMdMu9Ccj/1urxUq2ckCuU3T0vAW0xtnIyXf7t/k0f3gA+Nak5FI/LEpj -V4F1Wo7ojPsCwJTGKbqz3Bzosq/SLmJbGqmODszFV0VRFOlOHIilkfSj945RyKm+ -hjM+5i9Ibq9UkE6tsSU= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b -N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t -KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu -kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm -CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ -Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu -imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te -2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe -DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p -F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt -TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFVTCCBD2gAwIBAgIEO/OB0DANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJj -aDEOMAwGA1UEChMFYWRtaW4xETAPBgNVBAsTCFNlcnZpY2VzMSIwIAYDVQQLExlD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMRYwFAYDVQQDEw1BZG1pbi1Sb290LUNB -MB4XDTAxMTExNTA4NTEwN1oXDTIxMTExMDA3NTEwN1owbDELMAkGA1UEBhMCY2gx -DjAMBgNVBAoTBWFkbWluMREwDwYDVQQLEwhTZXJ2aWNlczEiMCAGA1UECxMZQ2Vy -dGlmaWNhdGlvbiBBdXRob3JpdGllczEWMBQGA1UEAxMNQWRtaW4tUm9vdC1DQTCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMvgr0QUIv5qF0nyXZ3PXAJi -C4C5Wr+oVTN7oxIkXkxvO0GJToM9n7OVJjSmzBL0zJ2HXj0MDRcvhSY+KiZZc6Go -vDvr5Ua481l7ILFeQAFtumeza+vvxeL5Nd0Maga2miiacLNAKXbAcUYRa0Ov5VZB -++YcOYNNt/aisWbJqA2y8He+NsEgJzK5zNdayvYXQTZN+7tVgWOck16Da3+4FXdy -fH1NCWtZlebtMKtERtkVAaVbiWW24CjZKAiVfggjsiLo3yVMPGj3budLx5D9hEEm -vlyDOtcjebca+AcZglppWMX/iHIrx7740y0zd6cWEqiLIcZCrnpkr/KzwO135GkC -AwEAAaOCAf0wggH5MA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIASBkTCBjjCBiwYI -YIV0AREDAQAwfzArBggrBgEFBQcCAjAfGh1UaGlzIGlzIHRoZSBBZG1pbi1Sb290 -LUNBIENQUzBQBggrBgEFBQcCARZEaHR0cDovL3d3dy5pbmZvcm1hdGlrLmFkbWlu -LmNoL1BLSS9saW5rcy9DUFNfMl8xNl83NTZfMV8xN18zXzFfMC5wZGYwfwYDVR0f -BHgwdjB0oHKgcKRuMGwxFjAUBgNVBAMTDUFkbWluLVJvb3QtQ0ExIjAgBgNVBAsT -GUNlcnRpZmljYXRpb24gQXV0aG9yaXRpZXMxETAPBgNVBAsTCFNlcnZpY2VzMQ4w -DAYDVQQKEwVhZG1pbjELMAkGA1UEBhMCY2gwHQYDVR0OBBYEFIKf+iNzIPGXi7JM -Tb5CxX9mzWToMIGZBgNVHSMEgZEwgY6AFIKf+iNzIPGXi7JMTb5CxX9mzWTooXCk -bjBsMQswCQYDVQQGEwJjaDEOMAwGA1UEChMFYWRtaW4xETAPBgNVBAsTCFNlcnZp -Y2VzMSIwIAYDVQQLExlDZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMRYwFAYDVQQD -Ew1BZG1pbi1Sb290LUNBggQ784HQMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0B -AQUFAAOCAQEAeE96XCYRpy6umkPKXDWCRn7INo96ZrWpMggcDORuofHIwdTkgOeM -vWOxDN/yuT7CC3FAaUajbPRbDw0hRMcqKz0aC8CgwcyIyhw/rFK29mfNTG3EviP9 -QSsEbnelFnjpm1wjz4EaBiFjatwpUbI6+Zv3XbEt9QQXBn+c6DeFLe4xvC4B+MTr -a440xTk59pSYux8OHhEvqIwHCkiijGqZhTS3KmGFeBopaR+dJVBRBMoXwzk4B3Hn -0Zib1dEYFZa84vPJZyvxCbLOnPRDJgH6V2uQqbG+6DXVaf/wORVOvF/wzzv0viM/ -RWbEtJZdvo8N3sdtCULzifnxP/V0T9+4ZQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDOzCCAiOgAwIBAgIRANAeRlAAACmMAAAAAgAAAAIwDQYJKoZIhvcNAQEFBQAw -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYNDAeFw0wMDA5MTMwNjIyNTBaFw0yMDA5MTMwNjIyNTBa -MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UE -AxMORFNUIFJvb3QgQ0EgWDQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCthX3OFEYY8gSeIYur0O4ypOT68HnDrjLfIutL5PZHRwQGjzCPb9PFo/ihboJ8 -RvfGhBAqpQCo47zwYEhpWm1jB+L/OE/dBBiyn98krfU2NiBKSom2J58RBeAwHGEy -cO+lewyjVvbDDLUy4CheY059vfMjPAftCRXjqSZIolQb9FdPcAoa90mFwB7rKniE -J7vppdrUScSS0+eBrHSUPLdvwyn4RGp+lSwbWYcbg5EpSpE0GRJdchic0YDjvIoC -YHpe7Rkj93PYRTQyU4bhC88ck8tMqbvRYqMRqR+vobbkrj5LLCOQCHV5WEoxWh+0 -E2SpIFe7RkV++MmpIAc0h1tZAgMBAAGjMjAwMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFPCD6nPIP1ubWzdf9UyPWvf0hki9MA0GCSqGSIb3DQEBBQUAA4IBAQCE -G85wl5eEWd7adH6XW/ikGN5salvpq/Fix6yVTzE6CrhlP5LBdkf6kx1bSPL18M45 -g0rw2zA/MWOhJ3+S6U+BE0zPGCuu8YQaZibR7snm3HiHUaZNMu5c8D0x0bcMxDjY -AVVcHCoNiL53Q4PLW27nbY6wwG0ffFKmgV3blxrYWfuUDgGpyPwHwkfVFvz9qjaV -mf12VJffL6W8omBPtgteb6UaT/k1oJ7YI0ldGf+ngpVbRhD+LC3cUtT6GO/BEPZu -8YTV/hbiDH5v3khVqMIeKT6o8IuXGG7F6a6vKwP1F1FwTXf4UC/ivhme7vdUH7B/ -Vv4AEbT8dNfEeFxrkDbh ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns -YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH -MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y -aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe -Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj -IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx -KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM -HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw -DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC -AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji -nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX -rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn -jBJ7xUS0rg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFGjCCBAKgAwIBAgIEPL7eEDANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBS -b290Q0EwHhcNMDIwNDE4MTQ1NDA4WhcNMjYwOTIxMTU0MjE5WjB2MQswCQYDVQQG -EwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMb -Q2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MSAwHgYDVQQDExdDQyBTaWduZXQg -LSBQQ0EgS2xhc2EgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM7B -rBlbN5maM5eg0BOTqoZ+9NBDvU8Lm5rTdrMswFTCathzpVVLK/JD4K3+4oCZ9SRA -spEXE4gvwb08ASY6w5s+HpRkeJw8YzMFR5kDZD5adgnCAy4vDfIXYZgppXPaTQ8w -nfUZ7BZ7Zfa7QBemUIcJIzJBB0UqgtxWCeol9IekpBRVmuuSA6QG0Jkm+pGDJ05y -j2eQG8jTcBENM7sVA8rGRMyFA4skSZ+D0OG6FS2xC1i9JyN0ag1yII/LPx8HK5J4 -W9MaPRNjAEeaa2qI9EpchwrOxnyVbQfSedCG1VRJfAsE/9tT9CMUPZ3xW20QjQcS -ZJqVcmGW9gVsXKQOVLsCAwEAAaOCAbMwggGvMA8GA1UdEwEB/wQFMAMBAf8wDgYD -VR0PAQH/BAQDAgEGMIIBBAYDVR0gBIH8MIH5MIH2Bg0rBgEEAb4/AgEKAQEBMIHk -MIGaBggrBgEFBQcCAjCBjRqBikNlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmll -IHogZG9rdW1lbnRlbTogIlBvbGl0eWthIENlcnR5ZmlrYWNqaSBkbGEgUm9vdENB -Ii4gQ2VydHlmaWthdCB3eXN0YXdpb255IHByemV6IFJvb3RDQSB3IGhpZXJhcmNo -aWkgQ0MgU2lnbmV0LjBFBggrBgEFBQcCARY5aHR0cDovL3d3dy5zaWduZXQucGwv -cmVwb3p5dG9yaXVtL2Rva3VtZW50eS9wY19yb290Y2EudHh0MEQGA1UdHwQ9MDsw -OaA3oDWGM2h0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9yb290Y2Ev -cm9vdGNhLmNybDAfBgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAdBgNV -HQ4EFgQUwGxGyl2CfpYHRonE82AVXO08kMIwDQYJKoZIhvcNAQEFBQADggEBABp1 -TAUsa+BeVWg4cjowc8yTJ5XN3GvN96GObMkxUGY7U9kVrLI71xBgoNVyzXTiMNDB -vjh7vdPWjpl5SDiRpnnKiOFXA43HvNWzUaOkTu1mxjJsZsanot1Xt6j0ZDC+03Fj -LHdYMyM9kSWp6afb4980EPYZCcSzgM5TOGfJmNii5Tq468VFKrX+52Aou1G22Ohu -+EEOlOrG7ylKv1hHUJJCjwN0ZVEIn1nDbrU9FeGCz8J9ihVUvnENEBbBkU37PWqW -uHitKQDVtcwTwJJdR8cmKq3NmkwAm9fPacidQLpaw0WkuGrS+fEDhu1Nhy9xELP6 -NA9GRTCNxm/dXlcwnmY= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIElTCCA/6gAwIBAgIEOJsRPDANBgkqhkiG9w0BAQQFADCBujEUMBIGA1UEChML -RW50cnVzdC5uZXQxPzA9BgNVBAsUNnd3dy5lbnRydXN0Lm5ldC9TU0xfQ1BTIGlu -Y29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDIwMDAg -RW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJl -IFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDQxNzIwMDBa -Fw0yMDAyMDQxNzUwMDBaMIG6MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDE/MD0GA1UE -CxQ2d3d3LmVudHJ1c3QubmV0L1NTTF9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p -dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5ldCBMaW1pdGVk -MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp -b24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHwV9OcfHO -8GCGD9JYf9Mzly0XonUwtZZkJi9ow0SrqHXmAGc0V55lxyKbc+bT3QgON1WqJUaB -bL3+qPZ1V1eMkGxKwz6LS0MKyRFWmponIpnPVZ5h2QLifLZ8OAfc439PmrkDQYC2 -dWcTC5/oVzbIXQA23mYU2m52H083jIITiQIDAQABo4IBpDCCAaAwEQYJYIZIAYb4 -QgEBBAQDAgAHMIHjBgNVHR8EgdswgdgwgdWggdKggc+kgcwwgckxFDASBgNVBAoT -C0VudHJ1c3QubmV0MT8wPQYDVQQLFDZ3d3cuZW50cnVzdC5uZXQvU1NMX0NQUyBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw -IEVudHJ1c3QubmV0IExpbWl0ZWQxOjA4BgNVBAMTMUVudHJ1c3QubmV0IFNlY3Vy -ZSBTZXJ2ZXIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEw -KwYDVR0QBCQwIoAPMjAwMDAyMDQxNzIwMDBagQ8yMDIwMDIwNDE3NTAwMFowCwYD -VR0PBAQDAgEGMB8GA1UdIwQYMBaAFMtswGvjuz7L/CKc/vuLkpyw8m4iMB0GA1Ud -DgQWBBTLbMBr47s+y/winP77i5KcsPJuIjAMBgNVHRMEBTADAQH/MB0GCSqGSIb2 -fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQQFAAOBgQBi24GRzsia -d0Iv7L0no1MPUBvqTpLwqa+poLpIYcvvyQbvH9X07t9WLebKahlzqlO+krNQAraF -JnJj2HVQYnUUt7NQGj/KEQALhUVpbbalrlHhStyCP2yMNLJ3a9kC9n8O6mUE8c1U -yrrJzOCE98g+EZfTYAkYvAX/bIkz8OwVDw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn -MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL -ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo -YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 -MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy -NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G -A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA -A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 -Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s -QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV -eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 -B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh -z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T -AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i -ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w -TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH -MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD -VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE -VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh -bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B -AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM -bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi -ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG -VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c -ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ -AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50cnVzdC5u -ZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBsaW1pdHMgbGlh -Yi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV -BAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBaMIHJMQswCQYDVQQGEwJVUzEU -MBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9D -bGllbnRfQ0FfSW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjEl -MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMq -RW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0G -CSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo -6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux -5zDeg7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zm -AqTmT173iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSC -ARkwggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50 -cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5m -by9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMp -IDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQg -Q2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCyg -KqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9DbGllbnQxLmNybDArBgNV -HRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkxMDEyMTkyNDMwWjALBgNVHQ8E -BAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW/O5bs8qZdIuV6kwwHQYDVR0OBBYE -FMT7nCl7l81MlvzuW7PKmXSLlepMMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA -BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7 -pFuPeJoSSJn59DXeDDYHAmsQOokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzz -wy5E97BnRqqS5TvaHBkUODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/a -EkP/TOYGJqibGapEPHayXOw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy -aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s -IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp -Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV -BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp -Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu -Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g -Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt -IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU -J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO -JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY -wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o -koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN -qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E -Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe -xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u -7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU -sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI -sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP -cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9v -dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDAxMDExMTY0MTI4WhcNMjEwMTE0 -MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSww -KgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0G -A1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n13 -5zHCLielTWi5MbqNQ1mXx3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHE -SxP9cMIlrCL1dQu3U+SlK93OvRw6esP3E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4O -JgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5OEL8pahbSCOz6+MlsoCu -ltQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4jsNtlAHCE -AQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMB -AAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcB -CzAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRw -b2xpY3kwDQYJKoZIhvcNAQEFBQADggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo -7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrvm+0fazbuSCUlFLZWohDo7qd/ -0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0ROhPs7fpvcmR7 -nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx -x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ -33ZwmVxwQ023tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDtjCCAp6gAwIBAgIOBcAAAQACQdAGCk3OdRAwDQYJKoZIhvcNAQEFBQAwdjEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV -BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDQgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 -Q2VudGVyIENsYXNzIDQgQ0EgSUkwHhcNMDYwMzIzMTQxMDIzWhcNMjUxMjMxMjI1 -OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i -SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgNCBDQTElMCMGA1UEAxMc -VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgNCBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBALXNTJytrlG7fEjFDSmGehSt2VA9CXIgDRS2Y8b+WJ7gIV7z -jyIZ3E6RIM1viCmis8GsKnK6i1S4QF/yqvhDhsIwXMynXX/GCEnkDjkvjhjWkd0j -FnmA22xIHbzB3ygQY9GB493fL3l1oht48pQB5hBiecugfQLANIJ7x8CtHUzXapZ2 -W78mhEj9h/aECqqSB5lIPGG8ToVYx5ct/YFKocabEvVCUNFkPologiJw3fX64yhC -L04y87OjNopq1mJcrPoBbbTgci6VaLTxkwzGioLSHVPqfOA/QrcSWrjN2qUGZ8uh -d32llvCSHmcOHUJG5vnt+0dTf1cERh9GX8eu4I8CAwEAAaNCMEAwDwYDVR0TAQH/ -BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFB/quz4lGwa9pd1iBX7G -TFq/6A9DMA0GCSqGSIb3DQEBBQUAA4IBAQBYpCubTPfkpJKknGWYGWIi/HIy6QRd -xMRwLVpG3kxHiiW5ot3u6hKvSI3vK2fbO8w0mCr3CEf/Iq978fTr4jgCMxh1KBue -dmWsiANy8jhHHYz1nwqIUxAUu4DlDLNdjRfuHhkcho0UZ3iMksseIUn3f9MYv5x5 -+F0IebWqak2SNmy8eesOPXmK2PajVnBd3ttPedJ60pVchidlvqDTB4FAVd0Qy+BL -iILAkH0457+W4Ze6mqtCD9Of2J4VMxHL94J59bXAQVaS4d9VA61Iz9PyLrHHLVZM -ZHQqMc7cdalUR6SnQnIJ5+ECpkeyBM1CE+FhDOB4OiIgohxgQoaH96Xm ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd -MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg -Q2xhc3MgMyBDQSAxMB4XDTA1MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzEL -MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD -VQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKxifZg -isRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//z -NIqeKNc0n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI -+MkcVyzwPX6UvCWThOiaAJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2R -hzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+ -mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNCMEAwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0PAQH/BAQD -AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFP -Bdy7pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27s -EzNxZy5p+qksP2bAEllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2 -mSlf56oBzKwzqBwKu5HEA6BvtjT5htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yC -e/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQjel/wroQk5PMr+4okoyeYZdow -dXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIIDjCCBfagAwIBAgIJAOiOtsn4KhQoMA0GCSqGSIb3DQEBBQUAMIG8MQswCQYD -VQQGEwJVUzEQMA4GA1UECBMHSW5kaWFuYTEVMBMGA1UEBxMMSW5kaWFuYXBvbGlz -MSgwJgYDVQQKEx9Tb2Z0d2FyZSBpbiB0aGUgUHVibGljIEludGVyZXN0MRMwEQYD -VQQLEwpob3N0bWFzdGVyMR4wHAYDVQQDExVDZXJ0aWZpY2F0ZSBBdXRob3JpdHkx -JTAjBgkqhkiG9w0BCQEWFmhvc3RtYXN0ZXJAc3BpLWluYy5vcmcwHhcNMDgwNTEz -MDgwNzU2WhcNMTgwNTExMDgwNzU2WjCBvDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT -B0luZGlhbmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UEChMfU29mdHdh -cmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9zdG1hc3RlcjEe -MBwGA1UEAxMVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSUwIwYJKoZIhvcNAQkBFhZo -b3N0bWFzdGVyQHNwaS1pbmMub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -CgKCAgEA3DbmR0LCxFF1KYdAw9iOIQbSGE7r7yC9kDyFEBOMKVuUY/b0LfEGQpG5 -GcRCaQi/izZF6igFM0lIoCdDkzWKQdh4s/Dvs24t3dHLfer0dSbTPpA67tfnLAS1 -fOH1fMVO73e9XKKTM5LOfYFIz2u1IiwIg/3T1c87Lf21SZBb9q1NE8re06adU1Fx -Y0b4ShZcmO4tbZoWoXaQ4mBDmdaJ1mwuepiyCwMs43pPx93jzONKao15Uvr0wa8u -jyoIyxspgpJyQ7zOiKmqp4pRQ1WFmjcDeJPI8L20QcgHQprLNZd6ioFl3h1UCAHx -ZFy3FxpRvB7DWYd2GBaY7r/2Z4GLBjXFS21ZGcfSxki+bhQog0oQnBv1b7ypjvVp -/rLBVcznFMn5WxRTUQfqzj3kTygfPGEJ1zPSbqdu1McTCW9rXRTunYkbpWry9vjQ -co7qch8vNGopCsUK7BxAhRL3pqXTT63AhYxMfHMgzFMY8bJYTAH1v+pk1Vw5xc5s -zFNaVrpBDyXfa1C2x4qgvQLCxTtVpbJkIoRRKFauMe5e+wsWTUYFkYBE7axt8Feo -+uthSKDLG7Mfjs3FIXcDhB78rKNDCGOM7fkn77SwXWfWT+3Qiz5dW8mRvZYChD3F -TbxCP3T9PF2sXEg2XocxLxhsxGjuoYvJWdAY4wCAs1QnLpnwFVMCAwEAAaOCAg8w -ggILMB0GA1UdDgQWBBQ0cdE41xU2g0dr1zdkQjuOjVKdqzCB8QYDVR0jBIHpMIHm -gBQ0cdE41xU2g0dr1zdkQjuOjVKdq6GBwqSBvzCBvDELMAkGA1UEBhMCVVMxEDAO -BgNVBAgTB0luZGlhbmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UEChMf -U29mdHdhcmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9zdG1h -c3RlcjEeMBwGA1UEAxMVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSUwIwYJKoZIhvcN -AQkBFhZob3N0bWFzdGVyQHNwaS1pbmMub3JnggkA6I62yfgqFCgwDwYDVR0TAQH/ -BAUwAwEB/zARBglghkgBhvhCAQEEBAMCAAcwCQYDVR0SBAIwADAuBglghkgBhvhC -AQ0EIRYfU29mdHdhcmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDAwBglghkgBhvhC -AQQEIxYhaHR0cHM6Ly9jYS5zcGktaW5jLm9yZy9jYS1jcmwucGVtMDIGCWCGSAGG -+EIBAwQlFiNodHRwczovL2NhLnNwaS1pbmMub3JnL2NlcnQtY3JsLnBlbTAhBgNV -HREEGjAYgRZob3N0bWFzdGVyQHNwaS1pbmMub3JnMA4GA1UdDwEB/wQEAwIBBjAN -BgkqhkiG9w0BAQUFAAOCAgEAtM294LnqsgMrfjLp3nI/yUuCXp3ir1UJogxU6M8Y -PCggHam7AwIvUjki+RfPrWeQswN/2BXja367m1YBrzXU2rnHZxeb1NUON7MgQS4M -AcRb+WU+wmHo0vBqlXDDxm/VNaSsWXLhid+hoJ0kvSl56WEq2dMeyUakCHhBknIP -qxR17QnwovBc78MKYiC3wihmrkwvLo9FYyaW8O4x5otVm6o6+YI5HYg84gd1GuEP -sTC8cTLSOv76oYnzQyzWcsR5pxVIBcDYLXIC48s9Fmq6ybgREOJJhcyWR2AFJS7v -dVkz9UcZFu/abF8HyKZQth3LZjQl/GaD68W2MEH4RkRiqMEMVObqTFoo5q7Gt/5/ -O5aoLu7HaD7dAD0prypjq1/uSSotxdz70cbT0ZdWUoa2lOvUYFG3/B6bzAKb1B+P -+UqPti4oOxfMxaYF49LTtcYDyeFIQpvLP+QX4P4NAZUJurgNceQJcHdC2E3hQqlg -g9cXiUPS1N2nGLar1CQlh7XU4vwuImm9rWgs/3K1mKoGnOcqarihk3bOsPN/nOHg -T7jYhkalMwIsJWE3KpLIrIF0aGOHM3a9BX9e1dUCbb2v/ypaqknsmHlHU5H2DjRa -yaXG67Ljxay2oHA1u8hRadDytaIybrw/oDc5fHE2pgXfDBLkFqfF1stjo5VwP+YE -o2A= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 -IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB -IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA -Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO -BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi -MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ -ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ -8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6 -zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y -fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7 -w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc -G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k -epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q -laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ -QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU -fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826 -YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w -ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY -gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe -MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0 -IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy -dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw -czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0 -dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl -aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC -AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg -b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB -ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc -nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg -18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c -gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl -Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY -sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T -SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF -CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum -GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk -zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW -omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx -HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh -IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyOTA2MDAwMFoXDTM3MTEyMDE1 -MDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg -SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M -IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnej8Mlo2k06AX3dLm/WpcZuS+U -0pPlLYnKhHw/EEMbjIt8hFj4JHxIzyr9wBXZGH6EGhfT257XyuTZ16pYUYfw8ItI -TuLCxFlpMGK2MKKMCxGZYTVtfu/FsRkGIBKOQuHfD5YQUqjPnF+VFNivO3ULMSAf -RC+iYkGzuxgh28pxPIzstrkNn+9R7017EvILDOGsQI93f7DKeHEMXRZxcKLXwjqF -zQ6axOAAsNUl6twr5JQtOJyJQVdkKGUZHLZEtMgxa44Be3ZZJX8VHIQIfHNlIAqh -BC4aMqiaILGcLCFZ5/vP7nAtCMpjPiybkxlqpMKX/7eGV4iFbJ4VFitNLLMCAwEA -AaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoTYwFsuGkABFgFOxj8jY -PXy+XxIwHwYDVR0jBBgwFoAUoTYwFsuGkABFgFOxj8jYPXy+XxIwDgYDVR0PAQH/ -BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQCKIBilvrMvtKaEAEAwKfq0FHNMeUWn -9nDg6H5kHgqVfGphwu9OH77/yZkfB2FK4V1Mza3u0FIy2VkyvNp5ctZ7CegCgTXT -Ct8RHcl5oIBN/lrXVtbtDyqvpxh1MwzqwWEFT2qaifKNuZ8u77BfWgDrvq2g+EQF -Z7zLBO+eZMXpyD8Fv8YvBxzDNnGGyjhmSs3WuEvGbKeXO/oTLW4jYYehY0KswsuX -n2Fozy1MBJ3XJU8KDk2QixhWqJNIV9xvrr2eZ1d3iVCzvhGbRWeDhhmH05i9CBoW -H1iCC+GWaQVLjuyDUTEH1dSf/1l7qG6Fz9NLqUmwX7A5KGgOc90lmt4S ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT -MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0 -aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw -WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE -AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m -OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu -T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c -JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR -Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz -PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm -aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM -TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g -LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO -BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv -dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB -AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL -NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W -b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp -ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow -fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV -BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM -cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S -HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 -CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk -3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz -6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV -HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud -EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv -Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw -Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww -DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 -5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj -Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI -gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ -aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl -izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy -NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY -dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 -WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS -v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v -UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu -IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC -W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFFjCCBH+gAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsDELMAkGA1UEBhMCSUwx -DzANBgNVBAgTBklzcmFlbDEOMAwGA1UEBxMFRWlsYXQxFjAUBgNVBAoTDVN0YXJ0 -Q29tIEx0ZC4xGjAYBgNVBAsTEUNBIEF1dGhvcml0eSBEZXAuMSkwJwYDVQQDEyBG -cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYS -YWRtaW5Ac3RhcnRjb20ub3JnMB4XDTA1MDMxNzE3Mzc0OFoXDTM1MDMxMDE3Mzc0 -OFowgbAxCzAJBgNVBAYTAklMMQ8wDQYDVQQIEwZJc3JhZWwxDjAMBgNVBAcTBUVp -bGF0MRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMRowGAYDVQQLExFDQSBBdXRob3Jp -dHkgRGVwLjEpMCcGA1UEAxMgRnJlZSBTU0wgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkxITAfBgkqhkiG9w0BCQEWEmFkbWluQHN0YXJ0Y29tLm9yZzCBnzANBgkqhkiG -9w0BAQEFAAOBjQAwgYkCgYEA7YRgACOeyEpRKSfeOqE5tWmrCbIvNP1h3D3TsM+x -18LEwrHkllbEvqoUDufMOlDIOmKdw6OsWXuO7lUaHEe+o5c5s7XvIywI6Nivcy+5 -yYPo7QAPyHWlLzRMGOh2iCNJitu27Wjaw7ViKUylS7eYtAkUEKD4/mJ2IhULpNYI -LzUCAwEAAaOCAjwwggI4MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgHmMB0G -A1UdDgQWBBQcicOWzL3+MtUNjIExtpidjShkjTCB3QYDVR0jBIHVMIHSgBQcicOW -zL3+MtUNjIExtpidjShkjaGBtqSBszCBsDELMAkGA1UEBhMCSUwxDzANBgNVBAgT -BklzcmFlbDEOMAwGA1UEBxMFRWlsYXQxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4x -GjAYBgNVBAsTEUNBIEF1dGhvcml0eSBEZXAuMSkwJwYDVQQDEyBGcmVlIFNTTCBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYSYWRtaW5Ac3Rh -cnRjb20ub3JnggEAMB0GA1UdEQQWMBSBEmFkbWluQHN0YXJ0Y29tLm9yZzAdBgNV -HRIEFjAUgRJhZG1pbkBzdGFydGNvbS5vcmcwEQYJYIZIAYb4QgEBBAQDAgAHMC8G -CWCGSAGG+EIBDQQiFiBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAy -BglghkgBhvhCAQQEJRYjaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL2NhLWNybC5j -cmwwKAYJYIZIAYb4QgECBBsWGWh0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy8wOQYJ -YIZIAYb4QgEIBCwWKmh0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9pbmRleC5waHA/ -YXBwPTExMTANBgkqhkiG9w0BAQQFAAOBgQBscSXhnjSRIe/bbL0BCFaPiNhBOlP1 -ct8nV0t2hPdopP7rPwl+KLhX6h/BquL/lp9JmeaylXOWxkjHXo0Hclb4g4+fd68p -00UOpO6wNnQt8M2YI3s3S9r+UZjEHjQ8iP2ZO1CnwYszx8JSFhKVU2Ui77qLzmLb -cCOxgN8aIDjnfg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcN -AQkBFglwa2lAc2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZp -dHNlZXJpbWlza2Vza3VzMRAwDgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMw -MVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMQsw -CQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEQ -MA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOB -SvZiF3tfTQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkz -ABpTpyHhOEvWgxutr2TC+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvH -LCu3GFH+4Hv2qEivbDtPL+/40UceJlfwUR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMP -PbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDaTpxt4brNj3pssAki14sL -2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQFMAMBAf8w -ggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwIC -MIHDHoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDk -AGwAagBhAHMAdABhAHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0 -AHMAZQBlAHIAaQBtAGkAcwBrAGUAcwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABz -AGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABrAGkAbgBuAGkAdABhAG0AaQBz -AGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nwcy8wKwYDVR0f -BCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE -FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcY -P2/v6X2+MA4GA1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOi -CfP+JmeaUOTDBS8rNXiRTHyoERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+g -kcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyLabVAyJRld/JXIWY7zoVAtjNjGr95 -HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678IIbsSt4beDI3poHS -na9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkhMp6q -qIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0Z -TbvGRNs2yyqcjg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO -TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy -MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk -ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn -ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71 -9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO -hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U -tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o -BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh -SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww -OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv -cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA -7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k -/rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm -eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6 -u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy -7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR -iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== ------END CERTIFICATE----- diff --git a/indra/newview/app_settings/ao_template.ini b/indra/newview/app_settings/ao_template.ini index 03f02e3059..ab4c68cac2 100644 --- a/indra/newview/app_settings/ao_template.ini +++ b/indra/newview/app_settings/ao_template.ini @@ -63,6 +63,7 @@ [ Running ] [ Turning Right ] [ Turning Left ] +[ Typing ] [ Floating ] [ Swimming Forward ] [ Swimming Up ] diff --git a/indra/newview/app_settings/ca-bundle.crt b/indra/newview/app_settings/ca-bundle.crt new file mode 100644 index 0000000000..e049f41fb0 --- /dev/null +++ b/indra/newview/app_settings/ca-bundle.crt @@ -0,0 +1,14600 @@ +## +## Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Wed Jan 17 21:18:08 2018 GMT +## +## This is a bundle of X.509 certificates of public Certificate Authorities +## (CA). These were automatically extracted from Mozilla's root certificates +## file (certdata.txt). This file can be found in the mozilla source tree: +## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt +## +## It contains the certificates in plain text and PEM format and therefore +## can be directly used with curl / libcurl / php_curl, or with +## an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## +## Conversion done with mk-ca-bundle.pl version 1.27. +## SHA256: a3ac15b98179dd2f3c5de076d10b1d53048754372f7207c2f327510cdd78fbd8 +## +LetsEncrypt Root CA2 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 03:74:f1:c1:0b:b8:be:e9:c5:30:d3:e4:43:db:f8:ff:05:0d + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 + Validity + Not Before: Mar 10 21:26:03 2019 GMT + Not After : Jun 8 21:26:03 2019 GMT + Subject: CN = login.virtual-nexus.xyz + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (4096 bit) + Modulus: + 00:aa:ea:b2:94:3e:9e:bf:08:c7:9a:3b:93:9d:4a: + a4:8e:18:f1:60:a1:26:d1:78:c1:72:11:8e:da:3e: + fa:16:3a:f4:a4:b2:de:ee:ec:eb:86:f1:88:2e:78: + 1a:04:90:44:e4:c2:72:c3:85:cf:8e:3b:9a:cd:f6: + 2c:4e:cb:39:06:18:2a:b9:70:dd:a5:d0:d6:71:01: + e8:e6:cc:f4:86:dd:88:2b:d5:de:28:a4:6c:a2:c9: + ab:dd:8b:0f:12:2a:1d:67:0f:fe:02:f9:33:1e:0c: + 84:be:16:d2:f2:b0:4d:b3:54:3d:db:df:83:8d:9a: + 1e:16:46:0b:f5:42:fb:91:4b:6a:95:7e:6b:48:e3: + 86:d8:60:5d:4d:9a:4e:a6:82:e7:05:02:83:78:72: + b4:62:8b:27:30:3a:20:8f:72:95:58:56:45:43:db: + 4e:e3:4a:87:0a:c9:58:f9:ec:63:65:d4:eb:f7:1d: + cc:2b:5c:8d:7d:61:54:0f:83:78:9a:b3:bf:db:87: + 45:b9:99:9b:54:75:e8:1c:52:29:f8:37:ad:24:5a: + ca:2b:1a:b2:11:8e:d4:34:bb:00:a8:e2:ae:ed:34: + 14:30:13:e1:06:c5:ee:d4:b2:9b:94:8d:f5:dc:2b: + a0:d3:ab:35:32:8b:e5:cf:d5:44:68:69:5d:3f:22: + 86:c9:2d:14:b6:b1:82:0c:fe:87:4d:a0:0a:76:1d: + c3:be:b9:ff:6e:c4:9e:f7:2d:d2:f5:ad:4d:aa:7f: + 4e:44:d6:7b:b4:6a:d0:71:52:48:2c:30:bf:11:b5: + df:70:40:30:cc:1a:e4:c0:a0:90:86:56:bf:36:92: + 2a:00:a5:0d:3b:2d:42:29:c1:4c:d6:9f:47:83:ff: + c1:c4:cc:04:08:9f:8b:2c:ca:4c:f5:d4:a5:38:81: + 6a:d0:4d:68:d9:fb:fa:1e:de:a1:c2:47:ea:d4:a8: + a3:b2:ba:47:50:b4:0e:15:a7:a7:ac:e2:a4:21:7c: + 20:c3:6b:ef:4f:3d:57:d0:91:ce:19:b2:da:4d:cd: + 7f:2d:2e:12:9d:e8:55:fc:02:ad:ea:57:68:d6:f9: + 96:9f:85:98:56:10:a2:bb:b6:7b:24:34:ab:9d:d7: + c9:56:47:40:b5:b1:22:80:b1:ae:37:73:6c:94:93: + 6c:db:97:47:b1:86:3c:87:5d:ad:52:2a:44:16:ce: + 0c:5c:94:1d:c2:cd:17:76:89:9a:ec:80:78:b9:a9: + c7:90:d2:c6:de:22:bb:95:1e:f6:ad:04:a0:46:c9: + 4b:12:2e:8d:ff:89:6c:c8:69:91:78:a0:f3:cf:f2: + 22:7d:68:4e:ee:32:0f:61:17:09:ba:94:bd:88:6d: + a8:65:cd + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Subject Key Identifier: + 2D:36:69:83:B8:E4:7D:38:D1:8F:8B:92:9E:A8:FD:6B:E9:25:29:97 + X509v3 Authority Key Identifier: + keyid:A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1 + + Authority Information Access: + OCSP - URI:http://ocsp.int-x3.letsencrypt.org + CA Issuers - URI:http://cert.int-x3.letsencrypt.org/ + + X509v3 Subject Alternative Name: + DNS:login.virtual-nexus.xyz + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + Policy: 1.3.6.1.4.1.44947.1.1.1 + CPS: http://cps.letsencrypt.org + + CT Precertificate SCTs: + Signed Certificate Timestamp: + Version : v1 (0x0) + Log ID : 74:7E:DA:83:31:AD:33:10:91:21:9C:CE:25:4F:42:70: + C2:BF:FD:5E:42:20:08:C6:37:35:79:E6:10:7B:CC:56 + Timestamp : Mar 10 22:26:03.415 2019 GMT + Extensions: none + Signature : ecdsa-with-SHA256 + 30:45:02:21:00:98:49:3F:B0:C4:66:2D:CF:CE:91:36: + 15:AF:75:94:5B:FD:C2:CB:8F:F1:E2:8D:FA:C0:61:8E: + E6:F3:7B:A8:05:02:20:62:39:0F:66:B2:79:48:A8:49: + 41:2A:D4:59:86:C3:FA:AC:C1:5D:26:02:AC:E3:D8:C8: + 0F:40:34:64:F1:D1:36 + Signed Certificate Timestamp: + Version : v1 (0x0) + Log ID : 29:3C:51:96:54:C8:39:65:BA:AA:50:FC:58:07:D4:B7: + 6F:BF:58:7A:29:72:DC:A4:C3:0C:F4:E5:45:47:F4:78 + Timestamp : Mar 10 22:26:03.442 2019 GMT + Extensions: none + Signature : ecdsa-with-SHA256 + 30:46:02:21:00:C7:09:49:5A:96:E5:B5:15:2A:F1:EA: + 03:A4:7D:10:89:23:9A:C2:C9:9F:35:85:AD:87:11:58: + A8:95:5C:0A:C6:02:21:00:88:14:C8:48:C7:6B:96:DB: + A2:AB:91:BD:F7:3D:AD:FA:37:F6:AD:BF:D7:24:DC:F0: + 11:CF:0C:D4:42:E0:72:A5 + Signature Algorithm: sha256WithRSAEncryption + 42:55:9f:ea:ae:79:1d:9d:e9:06:23:a1:d0:a9:0f:d2:bc:08: + 92:b6:05:30:29:c2:00:fc:96:6e:b1:ff:9b:00:d7:c3:7b:34: + 47:02:81:2a:44:46:85:6c:7a:f5:c3:09:e2:9c:fd:1d:d3:2c: + a4:e9:a5:99:ec:47:bd:fe:39:d2:c9:d6:ac:dd:48:40:0b:9a: + 24:f1:0b:4e:02:62:aa:63:e4:dd:8f:ad:9a:6c:5a:0a:de:d0: + a2:67:b2:ea:fa:68:ff:18:ea:e1:73:35:89:45:dd:b7:ac:2d: + 58:8a:a3:6d:eb:41:f6:fa:60:8f:39:38:33:a0:d5:fd:56:5d: + 02:08:80:40:f6:f0:c1:68:e1:15:c8:fc:c3:64:a5:43:85:18: + ed:44:5d:f8:b9:20:43:9f:3d:8b:20:e0:55:cd:78:89:d4:db: + 80:23:88:0e:6f:f5:ef:66:52:a9:c6:b1:f1:5e:6c:d6:8e:18: + 7a:93:14:65:4b:1b:a7:55:7d:9d:a5:d2:15:a8:7d:a1:aa:dd: + ef:93:94:d5:3e:2f:ce:4b:bf:ac:e5:61:da:66:61:bd:42:08: + 53:58:73:a7:80:64:78:17:60:11:71:7f:75:17:bc:24:2f:57: + 8c:61:37:87:4e:0a:41:82:74:b0:69:14:5c:89:58:55:32:1f: + 06:1b:e2:24 +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1 +WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg +RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX +NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf +89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl +Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc +Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz +uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB +AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU +BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB +FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo +SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js +LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF +BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG +AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD +VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB +ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx +A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM +UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2 +DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1 +eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu +OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw +p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY +2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0 +ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR +PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b +rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt +-----END CERTIFICATE----- + +LetsEncrypt Root CA + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 03:74:f1:c1:0b:b8:be:e9:c5:30:d3:e4:43:db:f8:ff:05:0d + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 + Validity + Not Before: Mar 10 21:26:03 2019 GMT + Not After : Jun 8 21:26:03 2019 GMT + Subject: CN = login.virtual-nexus.xyz + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (4096 bit) + Modulus: + 00:aa:ea:b2:94:3e:9e:bf:08:c7:9a:3b:93:9d:4a: + a4:8e:18:f1:60:a1:26:d1:78:c1:72:11:8e:da:3e: + fa:16:3a:f4:a4:b2:de:ee:ec:eb:86:f1:88:2e:78: + 1a:04:90:44:e4:c2:72:c3:85:cf:8e:3b:9a:cd:f6: + 2c:4e:cb:39:06:18:2a:b9:70:dd:a5:d0:d6:71:01: + e8:e6:cc:f4:86:dd:88:2b:d5:de:28:a4:6c:a2:c9: + ab:dd:8b:0f:12:2a:1d:67:0f:fe:02:f9:33:1e:0c: + 84:be:16:d2:f2:b0:4d:b3:54:3d:db:df:83:8d:9a: + 1e:16:46:0b:f5:42:fb:91:4b:6a:95:7e:6b:48:e3: + 86:d8:60:5d:4d:9a:4e:a6:82:e7:05:02:83:78:72: + b4:62:8b:27:30:3a:20:8f:72:95:58:56:45:43:db: + 4e:e3:4a:87:0a:c9:58:f9:ec:63:65:d4:eb:f7:1d: + cc:2b:5c:8d:7d:61:54:0f:83:78:9a:b3:bf:db:87: + 45:b9:99:9b:54:75:e8:1c:52:29:f8:37:ad:24:5a: + ca:2b:1a:b2:11:8e:d4:34:bb:00:a8:e2:ae:ed:34: + 14:30:13:e1:06:c5:ee:d4:b2:9b:94:8d:f5:dc:2b: + a0:d3:ab:35:32:8b:e5:cf:d5:44:68:69:5d:3f:22: + 86:c9:2d:14:b6:b1:82:0c:fe:87:4d:a0:0a:76:1d: + c3:be:b9:ff:6e:c4:9e:f7:2d:d2:f5:ad:4d:aa:7f: + 4e:44:d6:7b:b4:6a:d0:71:52:48:2c:30:bf:11:b5: + df:70:40:30:cc:1a:e4:c0:a0:90:86:56:bf:36:92: + 2a:00:a5:0d:3b:2d:42:29:c1:4c:d6:9f:47:83:ff: + c1:c4:cc:04:08:9f:8b:2c:ca:4c:f5:d4:a5:38:81: + 6a:d0:4d:68:d9:fb:fa:1e:de:a1:c2:47:ea:d4:a8: + a3:b2:ba:47:50:b4:0e:15:a7:a7:ac:e2:a4:21:7c: + 20:c3:6b:ef:4f:3d:57:d0:91:ce:19:b2:da:4d:cd: + 7f:2d:2e:12:9d:e8:55:fc:02:ad:ea:57:68:d6:f9: + 96:9f:85:98:56:10:a2:bb:b6:7b:24:34:ab:9d:d7: + c9:56:47:40:b5:b1:22:80:b1:ae:37:73:6c:94:93: + 6c:db:97:47:b1:86:3c:87:5d:ad:52:2a:44:16:ce: + 0c:5c:94:1d:c2:cd:17:76:89:9a:ec:80:78:b9:a9: + c7:90:d2:c6:de:22:bb:95:1e:f6:ad:04:a0:46:c9: + 4b:12:2e:8d:ff:89:6c:c8:69:91:78:a0:f3:cf:f2: + 22:7d:68:4e:ee:32:0f:61:17:09:ba:94:bd:88:6d: + a8:65:cd + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Subject Key Identifier: + 2D:36:69:83:B8:E4:7D:38:D1:8F:8B:92:9E:A8:FD:6B:E9:25:29:97 + X509v3 Authority Key Identifier: + keyid:A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1 + + Authority Information Access: + OCSP - URI:http://ocsp.int-x3.letsencrypt.org + CA Issuers - URI:http://cert.int-x3.letsencrypt.org/ + + X509v3 Subject Alternative Name: + DNS:login.virtual-nexus.xyz + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + Policy: 1.3.6.1.4.1.44947.1.1.1 + CPS: http://cps.letsencrypt.org + + CT Precertificate SCTs: + Signed Certificate Timestamp: + Version : v1 (0x0) + Log ID : 74:7E:DA:83:31:AD:33:10:91:21:9C:CE:25:4F:42:70: + C2:BF:FD:5E:42:20:08:C6:37:35:79:E6:10:7B:CC:56 + Timestamp : Mar 10 22:26:03.415 2019 GMT + Extensions: none + Signature : ecdsa-with-SHA256 + 30:45:02:21:00:98:49:3F:B0:C4:66:2D:CF:CE:91:36: + 15:AF:75:94:5B:FD:C2:CB:8F:F1:E2:8D:FA:C0:61:8E: + E6:F3:7B:A8:05:02:20:62:39:0F:66:B2:79:48:A8:49: + 41:2A:D4:59:86:C3:FA:AC:C1:5D:26:02:AC:E3:D8:C8: + 0F:40:34:64:F1:D1:36 + Signed Certificate Timestamp: + Version : v1 (0x0) + Log ID : 29:3C:51:96:54:C8:39:65:BA:AA:50:FC:58:07:D4:B7: + 6F:BF:58:7A:29:72:DC:A4:C3:0C:F4:E5:45:47:F4:78 + Timestamp : Mar 10 22:26:03.442 2019 GMT + Extensions: none + Signature : ecdsa-with-SHA256 + 30:46:02:21:00:C7:09:49:5A:96:E5:B5:15:2A:F1:EA: + 03:A4:7D:10:89:23:9A:C2:C9:9F:35:85:AD:87:11:58: + A8:95:5C:0A:C6:02:21:00:88:14:C8:48:C7:6B:96:DB: + A2:AB:91:BD:F7:3D:AD:FA:37:F6:AD:BF:D7:24:DC:F0: + 11:CF:0C:D4:42:E0:72:A5 + Signature Algorithm: sha256WithRSAEncryption + 42:55:9f:ea:ae:79:1d:9d:e9:06:23:a1:d0:a9:0f:d2:bc:08: + 92:b6:05:30:29:c2:00:fc:96:6e:b1:ff:9b:00:d7:c3:7b:34: + 47:02:81:2a:44:46:85:6c:7a:f5:c3:09:e2:9c:fd:1d:d3:2c: + a4:e9:a5:99:ec:47:bd:fe:39:d2:c9:d6:ac:dd:48:40:0b:9a: + 24:f1:0b:4e:02:62:aa:63:e4:dd:8f:ad:9a:6c:5a:0a:de:d0: + a2:67:b2:ea:fa:68:ff:18:ea:e1:73:35:89:45:dd:b7:ac:2d: + 58:8a:a3:6d:eb:41:f6:fa:60:8f:39:38:33:a0:d5:fd:56:5d: + 02:08:80:40:f6:f0:c1:68:e1:15:c8:fc:c3:64:a5:43:85:18: + ed:44:5d:f8:b9:20:43:9f:3d:8b:20:e0:55:cd:78:89:d4:db: + 80:23:88:0e:6f:f5:ef:66:52:a9:c6:b1:f1:5e:6c:d6:8e:18: + 7a:93:14:65:4b:1b:a7:55:7d:9d:a5:d2:15:a8:7d:a1:aa:dd: + ef:93:94:d5:3e:2f:ce:4b:bf:ac:e5:61:da:66:61:bd:42:08: + 53:58:73:a7:80:64:78:17:60:11:71:7f:75:17:bc:24:2f:57: + 8c:61:37:87:4e:0a:41:82:74:b0:69:14:5c:89:58:55:32:1f: + 06:1b:e2:24 +-----BEGIN CERTIFICATE----- +MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow +SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT +GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF +q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8 +SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0 +Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA +a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj +/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T +AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG +CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv +bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k +c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw +VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC +ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz +MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu +Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF +AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo +uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/ +wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu +X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG +PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 +KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== +-----END CERTIFICATE----- + + + + +GlobalSign Root CA +# Issuer: CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE +# Serial Number:04:00:00:00:00:01:15:4b:5a:c3:94 +# Subject: CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE +# Not Valid Before: Tue Sep 01 12:00:00 1998 +# Not Valid After : Fri Jan 28 12:00:00 2028 +# Fingerprint (MD5): 3E:45:52:15:09:51:92:E1:B7:5D:37:9F:B1:87:29:8A +# Fingerprint (SHA1): B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=3E:45:52:15:09:51:92:E1:B7:5D:37:9F:B1:87:29:8A +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 04:00:00:00:00:01:15:4b:5a:c3:94 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Sep 1 12:00:00 1998 GMT + Not After : Jan 28 12:00:00 2028 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:da:0e:e6:99:8d:ce:a3:e3:4f:8a:7e:fb:f1:8b: + 83:25:6b:ea:48:1f:f1:2a:b0:b9:95:11:04:bd:f0: + 63:d1:e2:67:66:cf:1c:dd:cf:1b:48:2b:ee:8d:89: + 8e:9a:af:29:80:65:ab:e9:c7:2d:12:cb:ab:1c:4c: + 70:07:a1:3d:0a:30:cd:15:8d:4f:f8:dd:d4:8c:50: + 15:1c:ef:50:ee:c4:2e:f7:fc:e9:52:f2:91:7d:e0: + 6d:d5:35:30:8e:5e:43:73:f2:41:e9:d5:6a:e3:b2: + 89:3a:56:39:38:6f:06:3c:88:69:5b:2a:4d:c5:a7: + 54:b8:6c:89:cc:9b:f9:3c:ca:e5:fd:89:f5:12:3c: + 92:78:96:d6:dc:74:6e:93:44:61:d1:8d:c7:46:b2: + 75:0e:86:e8:19:8a:d5:6d:6c:d5:78:16:95:a2:e9: + c8:0a:38:eb:f2:24:13:4f:73:54:93:13:85:3a:1b: + bc:1e:34:b5:8b:05:8c:b9:77:8b:b1:db:1f:20:91: + ab:09:53:6e:90:ce:7b:37:74:b9:70:47:91:22:51: + 63:16:79:ae:b1:ae:41:26:08:c8:19:2b:d1:46:aa: + 48:d6:64:2a:d7:83:34:ff:2c:2a:c1:6c:19:43:4a: + 07:85:e7:d3:7c:f6:21:68:ef:ea:f2:52:9f:7f:93: + 90:cf + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + Signature Algorithm: sha1WithRSAEncryption + d6:73:e7:7c:4f:76:d0:8d:bf:ec:ba:a2:be:34:c5:28:32:b5: + 7c:fc:6c:9c:2c:2b:bd:09:9e:53:bf:6b:5e:aa:11:48:b6:e5: + 08:a3:b3:ca:3d:61:4d:d3:46:09:b3:3e:c3:a0:e3:63:55:1b: + f2:ba:ef:ad:39:e1:43:b9:38:a3:e6:2f:8a:26:3b:ef:a0:50: + 56:f9:c6:0a:fd:38:cd:c4:0b:70:51:94:97:98:04:df:c3:5f: + 94:d5:15:c9:14:41:9c:c4:5d:75:64:15:0d:ff:55:30:ec:86: + 8f:ff:0d:ef:2c:b9:63:46:f6:aa:fc:df:bc:69:fd:2e:12:48: + 64:9a:e0:95:f0:a6:ef:29:8f:01:b1:15:b5:0c:1d:a5:fe:69: + 2c:69:24:78:1e:b3:a7:1c:71:62:ee:ca:c8:97:ac:17:5d:8a: + c2:f8:47:86:6e:2a:c4:56:31:95:d0:67:89:85:2b:f9:6c:a6: + 5d:46:9d:0c:aa:82:e4:99:51:dd:70:b7:db:56:3d:61:e4:6a: + e1:5c:d6:f6:fe:3d:de:41:cc:07:ae:63:52:bf:53:53:f4:2b: + e9:c7:fd:b6:f7:82:5f:85:d2:41:18:db:81:b3:04:1c:c5:1f: + a4:80:6f:15:20:c9:de:0c:88:0a:1d:d6:66:55:e2:fc:48:c9: + 29:26:69:e0 +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +GlobalSign Root CA - R2 +# Issuer: CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R2 +# Serial Number:04:00:00:00:00:01:0f:86:26:e6:0d +# Subject: CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R2 +# Not Valid Before: Fri Dec 15 08:00:00 2006 +# Not Valid After : Wed Dec 15 08:00:00 2021 +# Fingerprint (MD5): 94:14:77:7E:3E:5E:FD:8F:30:BD:41:B0:CF:E7:D0:30 +# Fingerprint (SHA1): 75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=94:14:77:7E:3E:5E:FD:8F:30:BD:41:B0:CF:E7:D0:30 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 04:00:00:00:00:01:0f:86:26:e6:0d + Signature Algorithm: sha1WithRSAEncryption + Issuer: OU=GlobalSign Root CA - R2, O=GlobalSign, CN=GlobalSign + Validity + Not Before: Dec 15 08:00:00 2006 GMT + Not After : Dec 15 08:00:00 2021 GMT + Subject: OU=GlobalSign Root CA - R2, O=GlobalSign, CN=GlobalSign + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:a6:cf:24:0e:be:2e:6f:28:99:45:42:c4:ab:3e: + 21:54:9b:0b:d3:7f:84:70:fa:12:b3:cb:bf:87:5f: + c6:7f:86:d3:b2:30:5c:d6:fd:ad:f1:7b:dc:e5:f8: + 60:96:09:92:10:f5:d0:53:de:fb:7b:7e:73:88:ac: + 52:88:7b:4a:a6:ca:49:a6:5e:a8:a7:8c:5a:11:bc: + 7a:82:eb:be:8c:e9:b3:ac:96:25:07:97:4a:99:2a: + 07:2f:b4:1e:77:bf:8a:0f:b5:02:7c:1b:96:b8:c5: + b9:3a:2c:bc:d6:12:b9:eb:59:7d:e2:d0:06:86:5f: + 5e:49:6a:b5:39:5e:88:34:ec:bc:78:0c:08:98:84: + 6c:a8:cd:4b:b4:a0:7d:0c:79:4d:f0:b8:2d:cb:21: + ca:d5:6c:5b:7d:e1:a0:29:84:a1:f9:d3:94:49:cb: + 24:62:91:20:bc:dd:0b:d5:d9:cc:f9:ea:27:0a:2b: + 73:91:c6:9d:1b:ac:c8:cb:e8:e0:a0:f4:2f:90:8b: + 4d:fb:b0:36:1b:f6:19:7a:85:e0:6d:f2:61:13:88: + 5c:9f:e0:93:0a:51:97:8a:5a:ce:af:ab:d5:f7:aa: + 09:aa:60:bd:dc:d9:5f:df:72:a9:60:13:5e:00:01: + c9:4a:fa:3f:a4:ea:07:03:21:02:8e:82:ca:03:c2: + 9b:8f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 9B:E2:07:57:67:1C:1E:C0:6A:06:DE:59:B4:9A:2D:DF:DC:19:86:2E + X509v3 CRL Distribution Points: + + Full Name: + URI:http://crl.globalsign.net/root-r2.crl + + X509v3 Authority Key Identifier: + keyid:9B:E2:07:57:67:1C:1E:C0:6A:06:DE:59:B4:9A:2D:DF:DC:19:86:2E + + Signature Algorithm: sha1WithRSAEncryption + 99:81:53:87:1c:68:97:86:91:ec:e0:4a:b8:44:0b:ab:81:ac: + 27:4f:d6:c1:b8:1c:43:78:b3:0c:9a:fc:ea:2c:3c:6e:61:1b: + 4d:4b:29:f5:9f:05:1d:26:c1:b8:e9:83:00:62:45:b6:a9:08: + 93:b9:a9:33:4b:18:9a:c2:f8:87:88:4e:db:dd:71:34:1a:c1: + 54:da:46:3f:e0:d3:2a:ab:6d:54:22:f5:3a:62:cd:20:6f:ba: + 29:89:d7:dd:91:ee:d3:5c:a2:3e:a1:5b:41:f5:df:e5:64:43: + 2d:e9:d5:39:ab:d2:a2:df:b7:8b:d0:c0:80:19:1c:45:c0:2d: + 8c:e8:f8:2d:a4:74:56:49:c5:05:b5:4f:15:de:6e:44:78:39: + 87:a8:7e:bb:f3:79:18:91:bb:f4:6f:9d:c1:f0:8c:35:8c:5d: + 01:fb:c3:6d:b9:ef:44:6d:79:46:31:7e:0a:fe:a9:82:c1:ff: + ef:ab:6e:20:c4:50:c9:5f:9d:4d:9b:17:8c:0c:e5:01:c9:a0: + 41:6a:73:53:fa:a5:50:b4:6e:25:0f:fb:4c:18:f4:fd:52:d9: + 8e:69:b1:e8:11:0f:de:88:d8:fb:1d:49:f7:aa:de:95:cf:20: + 78:c2:60:12:db:25:40:8c:6a:fc:7e:42:38:40:64:12:f7:9e: + 81:e1:93:2e +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G3 +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3,OU="(c) 1999 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US +# Serial Number:00:9b:7e:06:49:a3:3e:62:b9:d5:ee:90:48:71:29:ef:57 +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3,OU="(c) 1999 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US +# Not Valid Before: Fri Oct 01 00:00:00 1999 +# Not Valid After : Wed Jul 16 23:59:59 2036 +# Fingerprint (MD5): CD:68:B6:A7:C7:C4:CE:75:E0:1D:4F:57:44:61:92:09 +# Fingerprint (SHA1): 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +============================================================ +MD5 Fingerprint=CD:68:B6:A7:C7:C4:CE:75:E0:1D:4F:57:44:61:92:09 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 9b:7e:06:49:a3:3e:62:b9:d5:ee:90:48:71:29:ef:57 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:cb:ba:9c:52:fc:78:1f:1a:1e:6f:1b:37:73:bd: + f8:c9:6b:94:12:30:4f:f0:36:47:f5:d0:91:0a:f5: + 17:c8:a5:61:c1:16:40:4d:fb:8a:61:90:e5:76:20: + c1:11:06:7d:ab:2c:6e:a6:f5:11:41:8e:fa:2d:ad: + 2a:61:59:a4:67:26:4c:d0:e8:bc:52:5b:70:20:04: + 58:d1:7a:c9:a4:69:bc:83:17:64:ad:05:8b:bc:d0: + 58:ce:8d:8c:f5:eb:f0:42:49:0b:9d:97:27:67:32: + 6e:e1:ae:93:15:1c:70:bc:20:4d:2f:18:de:92:88: + e8:6c:85:57:11:1a:e9:7e:e3:26:11:54:a2:45:96: + 55:83:ca:30:89:e8:dc:d8:a3:ed:2a:80:3f:7f:79: + 65:57:3e:15:20:66:08:2f:95:93:bf:aa:47:2f:a8: + 46:97:f0:12:e2:fe:c2:0a:2b:51:e6:76:e6:b7:46: + b7:e2:0d:a6:cc:a8:c3:4c:59:55:89:e6:e8:53:5c: + 1c:ea:9d:f0:62:16:0b:a7:c9:5f:0c:f0:de:c2:76: + ce:af:f7:6a:f2:fa:41:a6:a2:33:14:c9:e5:7a:63: + d3:9e:62:37:d5:85:65:9e:0e:e6:53:24:74:1b:5e: + 1d:12:53:5b:c7:2c:e7:83:49:3b:15:ae:8a:68:b9: + 57:97 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 11:14:96:c1:ab:92:08:f7:3f:2f:c9:b2:fe:e4:5a:9f:64:de: + db:21:4f:86:99:34:76:36:57:dd:d0:15:2f:c5:ad:7f:15:1f: + 37:62:73:3e:d4:e7:5f:ce:17:03:db:35:fa:2b:db:ae:60:09: + 5f:1e:5f:8f:6e:bb:0b:3d:ea:5a:13:1e:0c:60:6f:b5:c0:b5: + 23:22:2e:07:0b:cb:a9:74:cb:47:bb:1d:c1:d7:a5:6b:cc:2f: + d2:42:fd:49:dd:a7:89:cf:53:ba:da:00:5a:28:bf:82:df:f8: + ba:13:1d:50:86:82:fd:8e:30:8f:29:46:b0:1e:3d:35:da:38: + 62:16:18:4a:ad:e6:b6:51:6c:de:af:62:eb:01:d0:1e:24:fe: + 7a:8f:12:1a:12:68:b8:fb:66:99:14:14:45:5c:ae:e7:ae:69: + 17:81:2b:5a:37:c9:5e:2a:f4:c6:e2:a1:5c:54:9b:a6:54:00: + cf:f0:f1:c1:c7:98:30:1a:3b:36:16:db:a3:6e:ea:fd:ad:b2: + c2:da:ef:02:47:13:8a:c0:f1:b3:31:ad:4f:1c:e1:4f:9c:af: + 0f:0c:9d:f7:78:0d:d8:f4:35:56:80:da:b7:6d:17:8f:9d:1e: + 81:64:e1:fe:c5:45:ba:ad:6b:b9:0a:7a:4e:4f:4b:84:ee:4b: + f1:7d:dd:11 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +# Issuer: CN=Entrust.net Certification Authority (2048),OU=(c) 1999 Entrust.net Limited,OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.),O=Entrust.net +# Serial Number: 946069240 (0x3863def8) +# Subject: CN=Entrust.net Certification Authority (2048),OU=(c) 1999 Entrust.net Limited,OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.),O=Entrust.net +# Not Valid Before: Fri Dec 24 17:50:51 1999 +# Not Valid After : Tue Jul 24 14:15:12 2029 +# Fingerprint (MD5): EE:29:31:BC:32:7E:9A:E6:E8:B5:F7:51:B4:34:71:90 +# Fingerprint (SHA1): 50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=EE:29:31:BC:32:7E:9A:E6:E8:B5:F7:51:B4:34:71:90 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 946069240 (0x3863def8) + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048) + Validity + Not Before: Dec 24 17:50:51 1999 GMT + Not After : Jul 24 14:15:12 2029 GMT + Subject: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048) + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ad:4d:4b:a9:12:86:b2:ea:a3:20:07:15:16:64: + 2a:2b:4b:d1:bf:0b:4a:4d:8e:ed:80:76:a5:67:b7: + 78:40:c0:73:42:c8:68:c0:db:53:2b:dd:5e:b8:76: + 98:35:93:8b:1a:9d:7c:13:3a:0e:1f:5b:b7:1e:cf: + e5:24:14:1e:b1:81:a9:8d:7d:b8:cc:6b:4b:03:f1: + 02:0c:dc:ab:a5:40:24:00:7f:74:94:a1:9d:08:29: + b3:88:0b:f5:87:77:9d:55:cd:e4:c3:7e:d7:6a:64: + ab:85:14:86:95:5b:97:32:50:6f:3d:c8:ba:66:0c: + e3:fc:bd:b8:49:c1:76:89:49:19:fd:c0:a8:bd:89: + a3:67:2f:c6:9f:bc:71:19:60:b8:2d:e9:2c:c9:90: + 76:66:7b:94:e2:af:78:d6:65:53:5d:3c:d6:9c:b2: + cf:29:03:f9:2f:a4:50:b2:d4:48:ce:05:32:55:8a: + fd:b2:64:4c:0e:e4:98:07:75:db:7f:df:b9:08:55: + 60:85:30:29:f9:7b:48:a4:69:86:e3:35:3f:1e:86: + 5d:7a:7a:15:bd:ef:00:8e:15:22:54:17:00:90:26: + 93:bc:0e:49:68:91:bf:f8:47:d3:9d:95:42:c1:0e: + 4d:df:6f:26:cf:c3:18:21:62:66:43:70:d6:d5:c0: + 07:e1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70 + Signature Algorithm: sha1WithRSAEncryption + 3b:9b:8f:56:9b:30:e7:53:99:7c:7a:79:a7:4d:97:d7:19:95: + 90:fb:06:1f:ca:33:7c:46:63:8f:96:66:24:fa:40:1b:21:27: + ca:e6:72:73:f2:4f:fe:31:99:fd:c8:0c:4c:68:53:c6:80:82: + 13:98:fa:b6:ad:da:5d:3d:f1:ce:6e:f6:15:11:94:82:0c:ee: + 3f:95:af:11:ab:0f:d7:2f:de:1f:03:8f:57:2c:1e:c9:bb:9a: + 1a:44:95:eb:18:4f:a6:1f:cd:7d:57:10:2f:9b:04:09:5a:84: + b5:6e:d8:1d:3a:e1:d6:9e:d1:6c:79:5e:79:1c:14:c5:e3:d0: + 4c:93:3b:65:3c:ed:df:3d:be:a6:e5:95:1a:c3:b5:19:c3:bd: + 5e:5b:bb:ff:23:ef:68:19:cb:12:93:27:5c:03:2d:6f:30:d0: + 1e:b6:1a:ac:de:5a:f7:d1:aa:a8:27:a6:fe:79:81:c4:79:99: + 33:57:ba:12:b0:a9:e0:42:6c:93:ca:56:de:fe:6d:84:0b:08: + 8b:7e:8d:ea:d7:98:21:c6:f3:e7:3c:79:2f:5e:9c:d1:4c:15: + 8d:e1:ec:22:37:cc:9a:43:0b:97:dc:80:90:8d:b3:67:9b:6f: + 48:08:15:56:cf:bf:f1:2b:7c:5e:9a:76:e9:59:90:c5:7c:83: + 35:11:65:51 +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 +MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub +j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo +U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b +u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ +bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er +fF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +Baltimore CyberTrust Root +# Issuer: CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE +# Serial Number: 33554617 (0x20000b9) +# Subject: CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE +# Not Valid Before: Fri May 12 18:46:00 2000 +# Not Valid After : Mon May 12 23:59:00 2025 +# Fingerprint (MD5): AC:B6:94:A5:9C:17:E0:D7:91:52:9B:B1:97:06:A6:E4 +# Fingerprint (SHA1): D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=AC:B6:94:A5:9C:17:E0:D7:91:52:9B:B1:97:06:A6:E4 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 33554617 (0x20000b9) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root + Validity + Not Before: May 12 18:46:00 2000 GMT + Not After : May 12 23:59:00 2025 GMT + Subject: C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:a3:04:bb:22:ab:98:3d:57:e8:26:72:9a:b5:79: + d4:29:e2:e1:e8:95:80:b1:b0:e3:5b:8e:2b:29:9a: + 64:df:a1:5d:ed:b0:09:05:6d:db:28:2e:ce:62:a2: + 62:fe:b4:88:da:12:eb:38:eb:21:9d:c0:41:2b:01: + 52:7b:88:77:d3:1c:8f:c7:ba:b9:88:b5:6a:09:e7: + 73:e8:11:40:a7:d1:cc:ca:62:8d:2d:e5:8f:0b:a6: + 50:d2:a8:50:c3:28:ea:f5:ab:25:87:8a:9a:96:1c: + a9:67:b8:3f:0c:d5:f7:f9:52:13:2f:c2:1b:d5:70: + 70:f0:8f:c0:12:ca:06:cb:9a:e1:d9:ca:33:7a:77: + d6:f8:ec:b9:f1:68:44:42:48:13:d2:c0:c2:a4:ae: + 5e:60:fe:b6:a6:05:fc:b4:dd:07:59:02:d4:59:18: + 98:63:f5:a5:63:e0:90:0c:7d:5d:b2:06:7a:f3:85: + ea:eb:d4:03:ae:5e:84:3e:5f:ff:15:ed:69:bc:f9: + 39:36:72:75:cf:77:52:4d:f3:c9:90:2c:b9:3d:e5: + c9:23:53:3f:1f:24:98:21:5c:07:99:29:bd:c6:3a: + ec:e7:6e:86:3a:6b:97:74:63:33:bd:68:18:31:f0: + 78:8d:76:bf:fc:9e:8e:5d:2a:86:a7:4d:90:dc:27: + 1a:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + E5:9D:59:30:82:47:58:CC:AC:FA:08:54:36:86:7B:3A:B5:04:4D:F0 + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:3 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 85:0c:5d:8e:e4:6f:51:68:42:05:a0:dd:bb:4f:27:25:84:03: + bd:f7:64:fd:2d:d7:30:e3:a4:10:17:eb:da:29:29:b6:79:3f: + 76:f6:19:13:23:b8:10:0a:f9:58:a4:d4:61:70:bd:04:61:6a: + 12:8a:17:d5:0a:bd:c5:bc:30:7c:d6:e9:0c:25:8d:86:40:4f: + ec:cc:a3:7e:38:c6:37:11:4f:ed:dd:68:31:8e:4c:d2:b3:01: + 74:ee:be:75:5e:07:48:1a:7f:70:ff:16:5c:84:c0:79:85:b8: + 05:fd:7f:be:65:11:a3:0f:c0:02:b4:f8:52:37:39:04:d5:a9: + 31:7a:18:bf:a0:2a:f4:12:99:f7:a3:45:82:e3:3c:5e:f5:9d: + 9e:b5:c8:9e:7c:2e:c8:a4:9e:4e:08:14:4b:6d:fd:70:6d:6b: + 1a:63:bd:64:e6:1f:b7:ce:f0:f2:9f:2e:bb:1b:b7:f2:50:88: + 73:92:c2:e2:e3:16:8d:9a:32:02:ab:8e:18:dd:e9:10:11:ee: + 7e:35:ab:90:af:3e:30:94:7a:d0:33:3d:a7:65:0f:f5:fc:8e: + 9e:62:cf:47:44:2c:01:5d:bb:1d:b5:32:d2:47:d2:38:2e:d0: + fe:81:dc:32:6a:1e:b5:ee:3c:d5:fc:e7:81:1d:19:c3:24:42: + ea:63:39:a9 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +AddTrust External Root +# Issuer: CN=AddTrust External CA Root,OU=AddTrust External TTP Network,O=AddTrust AB,C=SE +# Serial Number: 1 (0x1) +# Subject: CN=AddTrust External CA Root,OU=AddTrust External TTP Network,O=AddTrust AB,C=SE +# Not Valid Before: Tue May 30 10:48:38 2000 +# Not Valid After : Sat May 30 10:48:38 2020 +# Fingerprint (MD5): 1D:35:54:04:85:78:B0:3F:42:42:4D:BF:20:73:0A:3F +# Fingerprint (SHA1): 02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=1D:35:54:04:85:78:B0:3F:42:42:4D:BF:20:73:0A:3F +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=SE, O=AddTrust AB, OU=AddTrust External TTP Network, CN=AddTrust External CA Root + Validity + Not Before: May 30 10:48:38 2000 GMT + Not After : May 30 10:48:38 2020 GMT + Subject: C=SE, O=AddTrust AB, OU=AddTrust External TTP Network, CN=AddTrust External CA Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b7:f7:1a:33:e6:f2:00:04:2d:39:e0:4e:5b:ed: + 1f:bc:6c:0f:cd:b5:fa:23:b6:ce:de:9b:11:33:97: + a4:29:4c:7d:93:9f:bd:4a:bc:93:ed:03:1a:e3:8f: + cf:e5:6d:50:5a:d6:97:29:94:5a:80:b0:49:7a:db: + 2e:95:fd:b8:ca:bf:37:38:2d:1e:3e:91:41:ad:70: + 56:c7:f0:4f:3f:e8:32:9e:74:ca:c8:90:54:e9:c6: + 5f:0f:78:9d:9a:40:3c:0e:ac:61:aa:5e:14:8f:9e: + 87:a1:6a:50:dc:d7:9a:4e:af:05:b3:a6:71:94:9c: + 71:b3:50:60:0a:c7:13:9d:38:07:86:02:a8:e9:a8: + 69:26:18:90:ab:4c:b0:4f:23:ab:3a:4f:84:d8:df: + ce:9f:e1:69:6f:bb:d7:42:d7:6b:44:e4:c7:ad:ee: + 6d:41:5f:72:5a:71:08:37:b3:79:65:a4:59:a0:94: + 37:f7:00:2f:0d:c2:92:72:da:d0:38:72:db:14:a8: + 45:c4:5d:2a:7d:b7:b4:d6:c4:ee:ac:cd:13:44:b7: + c9:2b:dd:43:00:25:fa:61:b9:69:6a:58:23:11:b7: + a7:33:8f:56:75:59:f5:cd:29:d7:46:b7:0a:2b:65: + b6:d3:42:6f:15:b2:b8:7b:fb:ef:e9:5d:53:d5:34: + 5a:27 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + AD:BD:98:7A:34:B4:26:F7:FA:C4:26:54:EF:03:BD:E0:24:CB:54:1A + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:AD:BD:98:7A:34:B4:26:F7:FA:C4:26:54:EF:03:BD:E0:24:CB:54:1A + DirName:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root + serial:01 + + Signature Algorithm: sha1WithRSAEncryption + b0:9b:e0:85:25:c2:d6:23:e2:0f:96:06:92:9d:41:98:9c:d9: + 84:79:81:d9:1e:5b:14:07:23:36:65:8f:b0:d8:77:bb:ac:41: + 6c:47:60:83:51:b0:f9:32:3d:e7:fc:f6:26:13:c7:80:16:a5: + bf:5a:fc:87:cf:78:79:89:21:9a:e2:4c:07:0a:86:35:bc:f2: + de:51:c4:d2:96:b7:dc:7e:4e:ee:70:fd:1c:39:eb:0c:02:51: + 14:2d:8e:bd:16:e0:c1:df:46:75:e7:24:ad:ec:f4:42:b4:85: + 93:70:10:67:ba:9d:06:35:4a:18:d3:2b:7a:cc:51:42:a1:7a: + 63:d1:e6:bb:a1:c5:2b:c2:36:be:13:0d:e6:bd:63:7e:79:7b: + a7:09:0d:40:ab:6a:dd:8f:8a:c3:f6:f6:8c:1a:42:05:51:d4: + 45:f5:9f:a7:62:21:68:15:20:43:3c:99:e7:7c:bd:24:d8:a9: + 91:17:73:88:3f:56:1b:31:38:18:b4:71:0f:9a:cd:c8:0e:9e: + 8e:2e:1b:e1:8c:98:83:cb:1f:31:f1:44:4c:c6:04:73:49:76: + 60:0f:c7:f8:bd:17:80:6b:2e:e9:cc:4c:0e:5a:9a:79:0f:20: + 0a:2e:d5:9e:63:26:1e:55:92:94:d8:82:17:5a:7b:d0:bc:c7: + 8f:4e:86:04 +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- + +Entrust Root Certification Authority +# Issuer: CN=Entrust Root Certification Authority,OU="(c) 2006 Entrust, Inc.",OU=www.entrust.net/CPS is incorporated by reference,O="Entrust, Inc.",C=US +# Serial Number: 1164660820 (0x456b5054) +# Subject: CN=Entrust Root Certification Authority,OU="(c) 2006 Entrust, Inc.",OU=www.entrust.net/CPS is incorporated by reference,O="Entrust, Inc.",C=US +# Not Valid Before: Mon Nov 27 20:23:42 2006 +# Not Valid After : Fri Nov 27 20:53:42 2026 +# Fingerprint (MD5): D6:A5:C3:ED:5D:DD:3E:00:C1:3D:87:92:1F:1D:3F:E4 +# Fingerprint (SHA1): B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=D6:A5:C3:ED:5D:DD:3E:00:C1:3D:87:92:1F:1D:3F:E4 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1164660820 (0x456b5054) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Entrust, Inc., OU=www.entrust.net/CPS is incorporated by reference, OU=(c) 2006 Entrust, Inc., CN=Entrust Root Certification Authority + Validity + Not Before: Nov 27 20:23:42 2006 GMT + Not After : Nov 27 20:53:42 2026 GMT + Subject: C=US, O=Entrust, Inc., OU=www.entrust.net/CPS is incorporated by reference, OU=(c) 2006 Entrust, Inc., CN=Entrust Root Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b6:95:b6:43:42:fa:c6:6d:2a:6f:48:df:94:4c: + 39:57:05:ee:c3:79:11:41:68:36:ed:ec:fe:9a:01: + 8f:a1:38:28:fc:f7:10:46:66:2e:4d:1e:1a:b1:1a: + 4e:c6:d1:c0:95:88:b0:c9:ff:31:8b:33:03:db:b7: + 83:7b:3e:20:84:5e:ed:b2:56:28:a7:f8:e0:b9:40: + 71:37:c5:cb:47:0e:97:2a:68:c0:22:95:62:15:db: + 47:d9:f5:d0:2b:ff:82:4b:c9:ad:3e:de:4c:db:90: + 80:50:3f:09:8a:84:00:ec:30:0a:3d:18:cd:fb:fd: + 2a:59:9a:23:95:17:2c:45:9e:1f:6e:43:79:6d:0c: + 5c:98:fe:48:a7:c5:23:47:5c:5e:fd:6e:e7:1e:b4: + f6:68:45:d1:86:83:5b:a2:8a:8d:b1:e3:29:80:fe: + 25:71:88:ad:be:bc:8f:ac:52:96:4b:aa:51:8d:e4: + 13:31:19:e8:4e:4d:9f:db:ac:b3:6a:d5:bc:39:54: + 71:ca:7a:7a:7f:90:dd:7d:1d:80:d9:81:bb:59:26: + c2:11:fe:e6:93:e2:f7:80:e4:65:fb:34:37:0e:29: + 80:70:4d:af:38:86:2e:9e:7f:57:af:9e:17:ae:eb: + 1c:cb:28:21:5f:b6:1c:d8:e7:a2:04:22:f9:d3:da: + d8:cb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Private Key Usage Period: + Not Before: Nov 27 20:23:42 2006 GMT, Not After: Nov 27 20:53:42 2026 GMT + X509v3 Authority Key Identifier: + keyid:68:90:E4:67:A4:A6:53:80:C7:86:66:A4:F1:F7:4B:43:FB:84:BD:6D + + X509v3 Subject Key Identifier: + 68:90:E4:67:A4:A6:53:80:C7:86:66:A4:F1:F7:4B:43:FB:84:BD:6D + 1.2.840.113533.7.65.0: + 0...V7.1:4.0.... + Signature Algorithm: sha1WithRSAEncryption + 93:d4:30:b0:d7:03:20:2a:d0:f9:63:e8:91:0c:05:20:a9:5f: + 19:ca:7b:72:4e:d4:b1:db:d0:96:fb:54:5a:19:2c:0c:08:f7: + b2:bc:85:a8:9d:7f:6d:3b:52:b3:2a:db:e7:d4:84:8c:63:f6: + 0f:cb:26:01:91:50:6c:f4:5f:14:e2:93:74:c0:13:9e:30:3a: + 50:e3:b4:60:c5:1c:f0:22:44:8d:71:47:ac:c8:1a:c9:e9:9b: + 9a:00:60:13:ff:70:7e:5f:11:4d:49:1b:b3:15:52:7b:c9:54: + da:bf:9d:95:af:6b:9a:d8:9e:e9:f1:e4:43:8d:e2:11:44:3a: + bf:af:bd:83:42:73:52:8b:aa:bb:a7:29:cf:f5:64:1c:0a:4d: + d1:bc:aa:ac:9f:2a:d0:ff:7f:7f:da:7d:ea:b1:ed:30:25:c1: + 84:da:34:d2:5b:78:83:56:ec:9c:36:c3:26:e2:11:f6:67:49: + 1d:92:ab:8c:fb:eb:ff:7a:ee:85:4a:a7:50:80:f0:a7:5c:4a: + 94:2e:5f:05:99:3c:52:41:e0:cd:b4:63:cf:01:43:ba:9c:83: + dc:8f:60:3b:f3:5a:b4:b4:7b:ae:da:0b:90:38:75:ef:81:1d: + 66:d2:f7:57:70:36:b3:bf:fc:28:af:71:25:85:5b:13:fe:1e: + 7f:5a:b4:3c +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 +Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW +KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw +NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw +NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy +ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV +BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo +Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 +4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 +KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI +rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi +94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB +sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi +gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo +kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE +vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t +O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua +AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP +9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ +eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m +0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +GeoTrust Global CA +# Issuer: CN=GeoTrust Global CA,O=GeoTrust Inc.,C=US +# Serial Number: 144470 (0x23456) +# Subject: CN=GeoTrust Global CA,O=GeoTrust Inc.,C=US +# Not Valid Before: Tue May 21 04:00:00 2002 +# Not Valid After : Sat May 21 04:00:00 2022 +# Fingerprint (MD5): F7:75:AB:29:FB:51:4E:B7:77:5E:FF:05:3C:99:8E:F5 +# Fingerprint (SHA1): DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=F7:75:AB:29:FB:51:4E:B7:77:5E:FF:05:3C:99:8E:F5 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 144470 (0x23456) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA + Validity + Not Before: May 21 04:00:00 2002 GMT + Not After : May 21 04:00:00 2022 GMT + Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:da:cc:18:63:30:fd:f4:17:23:1a:56:7e:5b:df: + 3c:6c:38:e4:71:b7:78:91:d4:bc:a1:d8:4c:f8:a8: + 43:b6:03:e9:4d:21:07:08:88:da:58:2f:66:39:29: + bd:05:78:8b:9d:38:e8:05:b7:6a:7e:71:a4:e6:c4: + 60:a6:b0:ef:80:e4:89:28:0f:9e:25:d6:ed:83:f3: + ad:a6:91:c7:98:c9:42:18:35:14:9d:ad:98:46:92: + 2e:4f:ca:f1:87:43:c1:16:95:57:2d:50:ef:89:2d: + 80:7a:57:ad:f2:ee:5f:6b:d2:00:8d:b9:14:f8:14: + 15:35:d9:c0:46:a3:7b:72:c8:91:bf:c9:55:2b:cd: + d0:97:3e:9c:26:64:cc:df:ce:83:19:71:ca:4e:e6: + d4:d5:7b:a9:19:cd:55:de:c8:ec:d2:5e:38:53:e5: + 5c:4f:8c:2d:fe:50:23:36:fc:66:e6:cb:8e:a4:39: + 19:00:b7:95:02:39:91:0b:0e:fe:38:2e:d1:1d:05: + 9a:f6:4d:3e:6f:0f:07:1d:af:2c:1e:8f:60:39:e2: + fa:36:53:13:39:d4:5e:26:2b:db:3d:a8:14:bd:32: + eb:18:03:28:52:04:71:e5:ab:33:3d:e1:38:bb:07: + 36:84:62:9c:79:ea:16:30:f4:5f:c0:2b:e8:71:6b: + e4:f9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + C0:7A:98:68:8D:89:FB:AB:05:64:0C:11:7D:AA:7D:65:B8:CA:CC:4E + X509v3 Authority Key Identifier: + keyid:C0:7A:98:68:8D:89:FB:AB:05:64:0C:11:7D:AA:7D:65:B8:CA:CC:4E + + Signature Algorithm: sha1WithRSAEncryption + 35:e3:29:6a:e5:2f:5d:54:8e:29:50:94:9f:99:1a:14:e4:8f: + 78:2a:62:94:a2:27:67:9e:d0:cf:1a:5e:47:e9:c1:b2:a4:cf: + dd:41:1a:05:4e:9b:4b:ee:4a:6f:55:52:b3:24:a1:37:0a:eb: + 64:76:2a:2e:2c:f3:fd:3b:75:90:bf:fa:71:d8:c7:3d:37:d2: + b5:05:95:62:b9:a6:de:89:3d:36:7b:38:77:48:97:ac:a6:20: + 8f:2e:a6:c9:0c:c2:b2:99:45:00:c7:ce:11:51:22:22:e0:a5: + ea:b6:15:48:09:64:ea:5e:4f:74:f7:05:3e:c7:8a:52:0c:db: + 15:b4:bd:6d:9b:e5:c6:b1:54:68:a9:e3:69:90:b6:9a:a5:0f: + b8:b9:3f:20:7d:ae:4a:b5:b8:9c:e4:1d:b6:ab:e6:94:a5:c1: + c7:83:ad:db:f5:27:87:0e:04:6c:d5:ff:dd:a0:5d:ed:87:52: + b7:2b:15:02:ae:39:a6:6a:74:e9:da:c4:e7:bc:4d:34:1e:a9: + 5c:4d:33:5f:92:09:2f:88:66:5d:77:97:c7:1d:76:13:a9:d5: + e5:f1:16:09:11:35:d5:ac:db:24:71:70:2c:98:56:0b:d9:17: + b4:d1:e3:51:2b:5e:75:e8:d5:d0:dc:4f:34:ed:c2:05:66:80: + a1:cb:e6:33 +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- + +GeoTrust Universal CA +# Issuer: CN=GeoTrust Universal CA,O=GeoTrust Inc.,C=US +# Serial Number: 1 (0x1) +# Subject: CN=GeoTrust Universal CA,O=GeoTrust Inc.,C=US +# Not Valid Before: Thu Mar 04 05:00:00 2004 +# Not Valid After : Sun Mar 04 05:00:00 2029 +# Fingerprint (MD5): 92:65:58:8B:A2:1A:31:72:73:68:5C:B4:A5:7A:07:48 +# Fingerprint (SHA1): E6:21:F3:35:43:79:05:9A:4B:68:30:9D:8A:2F:74:22:15:87:EC:79 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=92:65:58:8B:A2:1A:31:72:73:68:5C:B4:A5:7A:07:48 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Universal CA + Validity + Not Before: Mar 4 05:00:00 2004 GMT + Not After : Mar 4 05:00:00 2029 GMT + Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Universal CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:a6:15:55:a0:a3:c6:e0:1f:8c:9d:21:50:d7:c1: + be:2b:5b:b5:a4:9e:a1:d9:72:58:bd:00:1b:4c:bf: + 61:c9:14:1d:45:82:ab:c6:1d:80:d6:3d:eb:10:9c: + 3a:af:6d:24:f8:bc:71:01:9e:06:f5:7c:5f:1e:c1: + 0e:55:ca:83:9a:59:30:ae:19:cb:30:48:95:ed:22: + 37:8d:f4:4a:9a:72:66:3e:ad:95:c0:e0:16:00:e0: + 10:1f:2b:31:0e:d7:94:54:d3:42:33:a0:34:1d:1e: + 45:76:dd:4f:ca:18:37:ec:85:15:7a:19:08:fc:d5: + c7:9c:f0:f2:a9:2e:10:a9:92:e6:3d:58:3d:a9:16: + 68:3c:2f:75:21:18:7f:28:77:a5:e1:61:17:b7:a6: + e9:f8:1e:99:db:73:6e:f4:0a:a2:21:6c:ee:da:aa: + 85:92:66:af:f6:7a:6b:82:da:ba:22:08:35:0f:cf: + 42:f1:35:fa:6a:ee:7e:2b:25:cc:3a:11:e4:6d:af: + 73:b2:76:1d:ad:d0:b2:78:67:1a:a4:39:1c:51:0b: + 67:56:83:fd:38:5d:0d:ce:dd:f0:bb:2b:96:1f:de: + 7b:32:52:fd:1d:bb:b5:06:a1:b2:21:5e:a5:d6:95: + 68:7f:f0:99:9e:dc:45:08:3e:e7:d2:09:0d:35:94: + dd:80:4e:53:97:d7:b5:09:44:20:64:16:17:03:02: + 4c:53:0d:68:de:d5:aa:72:4d:93:6d:82:0e:db:9c: + bd:cf:b4:f3:5c:5d:54:7a:69:09:96:d6:db:11:c1: + 8d:75:a8:b4:cf:39:c8:ce:3c:bc:24:7c:e6:62:ca: + e1:bd:7d:a7:bd:57:65:0b:e4:fe:25:ed:b6:69:10: + dc:28:1a:46:bd:01:1d:d0:97:b5:e1:98:3b:c0:37: + 64:d6:3d:94:ee:0b:e1:f5:28:ae:0b:56:bf:71:8b: + 23:29:41:8e:86:c5:4b:52:7b:d8:71:ab:1f:8a:15: + a6:3b:83:5a:d7:58:01:51:c6:4c:41:d9:7f:d8:41: + 67:72:a2:28:df:60:83:a9:9e:c8:7b:fc:53:73:72: + 59:f5:93:7a:17:76:0e:ce:f7:e5:5c:d9:0b:55:34: + a2:aa:5b:b5:6a:54:e7:13:ca:57:ec:97:6d:f4:5e: + 06:2f:45:8b:58:d4:23:16:92:e4:16:6e:28:63:59: + 30:df:50:01:9c:63:89:1a:9f:db:17:94:82:70:37: + c3:24:9e:9a:47:d6:5a:ca:4e:a8:69:89:72:1f:91: + 6c:db:7e:9e:1b:ad:c7:1f:73:dd:2c:4f:19:65:fd: + 7f:93:40:10:2e:d2:f0:ed:3c:9e:2e:28:3e:69:26: + 33:c5:7b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + DA:BB:2E:AA:B0:0C:B8:88:26:51:74:5C:6D:03:D3:C0:D8:8F:7A:D6 + X509v3 Authority Key Identifier: + keyid:DA:BB:2E:AA:B0:0C:B8:88:26:51:74:5C:6D:03:D3:C0:D8:8F:7A:D6 + + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 31:78:e6:c7:b5:df:b8:94:40:c9:71:c4:a8:35:ec:46:1d:c2: + 85:f3:28:58:86:b0:0b:fc:8e:b2:39:8f:44:55:ab:64:84:5c: + 69:a9:d0:9a:38:3c:fa:e5:1f:35:e5:44:e3:80:79:94:68:a4: + bb:c4:9f:3d:e1:34:cd:30:46:8b:54:2b:95:a5:ef:f7:3f:99: + 84:fd:35:e6:cf:31:c6:dc:6a:bf:a7:d7:23:08:e1:98:5e:c3: + 5a:08:76:a9:a6:af:77:2f:b7:60:bd:44:46:6a:ef:97:ff:73: + 95:c1:8e:e8:93:fb:fd:31:b7:ec:57:11:11:45:9b:30:f1:1a: + 88:39:c1:4f:3c:a7:00:d5:c7:fc:ab:6d:80:22:70:a5:0c:e0: + 5d:04:29:02:fb:cb:a0:91:d1:7c:d6:c3:7e:50:d5:9d:58:be: + 41:38:eb:b9:75:3c:15:d9:9b:c9:4a:83:59:c0:da:53:fd:33: + bb:36:18:9b:85:0f:15:dd:ee:2d:ac:76:93:b9:d9:01:8d:48: + 10:a8:fb:f5:38:86:f1:db:0a:c6:bd:84:a3:23:41:de:d6:77: + 6f:85:d4:85:1c:50:e0:ae:51:8a:ba:8d:3e:76:e2:b9:ca:27: + f2:5f:9f:ef:6e:59:0d:06:d8:2b:17:a4:d2:7c:6b:bb:5f:14: + 1a:48:8f:1a:4c:e7:b3:47:1c:8e:4c:45:2b:20:ee:48:df:e7: + dd:09:8e:18:a8:da:40:8d:92:26:11:53:61:73:5d:eb:bd:e7: + c4:4d:29:37:61:eb:ac:39:2d:67:2e:16:d6:f5:00:83:85:a1: + cc:7f:76:c4:7d:e4:b7:4b:66:ef:03:45:60:69:b6:0c:52:96: + 92:84:5e:a6:a3:b5:a4:3e:2b:d9:cc:d8:1b:47:aa:f2:44:da: + 4f:f9:03:e8:f0:14:cb:3f:f3:83:de:d0:c1:54:e3:b7:e8:0a: + 37:4d:8b:20:59:03:30:19:a1:2c:c8:bd:11:1f:df:ae:c9:4a: + c5:f3:27:66:66:86:ac:68:91:ff:d9:e6:53:1c:0f:8b:5c:69: + 65:0a:26:c8:1e:34:c3:5d:51:7b:d7:a9:9c:06:a1:36:dd:d5: + 89:94:bc:d9:e4:2d:0c:5e:09:6c:08:97:7c:a3:3d:7c:93:ff: + 3f:a1:14:a7:cf:b5:5d:eb:db:db:1c:c4:76:df:88:b9:bd:45: + 05:95:1b:ae:fc:46:6a:4c:af:48:e3:ce:ae:0f:d2:7e:eb:e6: + 6c:9c:4f:81:6a:7a:64:ac:bb:3e:d5:e7:cb:76:2e:c5:a7:48: + c1:5c:90:0f:cb:c8:3f:fa:e6:32:e1:8d:1b:6f:a4:e6:8e:d8: + f9:29:48:8a:ce:73:fe:2c +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy +c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 +IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV +VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 +cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT +QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh +F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v +c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w +mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd +VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX +teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ +f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe +Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ +nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY +MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG +9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX +IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn +ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z +uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN +Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja +QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW +koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 +ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt +DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm +bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +GeoTrust Universal CA 2 +# Issuer: CN=GeoTrust Universal CA 2,O=GeoTrust Inc.,C=US +# Serial Number: 1 (0x1) +# Subject: CN=GeoTrust Universal CA 2,O=GeoTrust Inc.,C=US +# Not Valid Before: Thu Mar 04 05:00:00 2004 +# Not Valid After : Sun Mar 04 05:00:00 2029 +# Fingerprint (MD5): 34:FC:B8:D0:36:DB:9E:14:B3:C2:F2:DB:8F:E4:94:C7 +# Fingerprint (SHA1): 37:9A:19:7B:41:85:45:35:0C:A6:03:69:F3:3C:2E:AF:47:4F:20:79 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=34:FC:B8:D0:36:DB:9E:14:B3:C2:F2:DB:8F:E4:94:C7 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Universal CA 2 + Validity + Not Before: Mar 4 05:00:00 2004 GMT + Not After : Mar 4 05:00:00 2029 GMT + Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Universal CA 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:b3:54:52:c1:c9:3e:f2:d9:dc:b1:53:1a:59:29: + e7:b1:c3:45:28:e5:d7:d1:ed:c5:c5:4b:a1:aa:74: + 7b:57:af:4a:26:fc:d8:f5:5e:a7:6e:19:db:74:0c: + 4f:35:5b:32:0b:01:e3:db:eb:7a:77:35:ea:aa:5a: + e0:d6:e8:a1:57:94:f0:90:a3:74:56:94:44:30:03: + 1e:5c:4e:2b:85:26:74:82:7a:0c:76:a0:6f:4d:ce: + 41:2d:a0:15:06:14:5f:b7:42:cd:7b:8f:58:61:34: + dc:2a:08:f9:2e:c3:01:a6:22:44:1c:4c:07:82:e6: + 5b:ce:d0:4a:7c:04:d3:19:73:27:f0:aa:98:7f:2e: + af:4e:eb:87:1e:24:77:6a:5d:b6:e8:5b:45:ba:dc: + c3:a1:05:6f:56:8e:8f:10:26:a5:49:c3:2e:d7:41: + 87:22:e0:4f:86:ca:60:b5:ea:a1:63:c0:01:97:10: + 79:bd:00:3c:12:6d:2b:15:b1:ac:4b:b1:ee:18:b9: + 4e:96:dc:dc:76:ff:3b:be:cf:5f:03:c0:fc:3b:e8: + be:46:1b:ff:da:40:c2:52:f7:fe:e3:3a:f7:6a:77: + 35:d0:da:8d:eb:5e:18:6a:31:c7:1e:ba:3c:1b:28: + d6:6b:54:c6:aa:5b:d7:a2:2c:1b:19:cc:a2:02:f6: + 9b:59:bd:37:6b:86:b5:6d:82:ba:d8:ea:c9:56:bc: + a9:36:58:fd:3e:19:f3:ed:0c:26:a9:93:38:f8:4f: + c1:5d:22:06:d0:97:ea:e1:ad:c6:55:e0:81:2b:28: + 83:3a:fa:f4:7b:21:51:00:be:52:38:ce:cd:66:79: + a8:f4:81:56:e2:d0:83:09:47:51:5b:50:6a:cf:db: + 48:1a:5d:3e:f7:cb:f6:65:f7:6c:f1:95:f8:02:3b: + 32:56:82:39:7a:5b:bd:2f:89:1b:bf:a1:b4:e8:ff: + 7f:8d:8c:df:03:f1:60:4e:58:11:4c:eb:a3:3f:10: + 2b:83:9a:01:73:d9:94:6d:84:00:27:66:ac:f0:70: + 40:09:42:92:ad:4f:93:0d:61:09:51:24:d8:92:d5: + 0b:94:61:b2:87:b2:ed:ff:9a:35:ff:85:54:ca:ed: + 44:43:ac:1b:3c:16:6b:48:4a:0a:1c:40:88:1f:92: + c2:0b:00:05:ff:f2:c8:02:4a:a4:aa:a9:cc:99:96: + 9c:2f:58:e0:7d:e1:be:bb:07:dc:5f:04:72:5c:31: + 34:c3:ec:5f:2d:e0:3d:64:90:22:e6:d1:ec:b8:2e: + dd:59:ae:d9:a1:37:bf:54:35:dc:73:32:4f:8c:04: + 1e:33:b2:c9:46:f1:d8:5c:c8:55:50:c9:68:bd:a8: + ba:36:09 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 76:F3:55:E1:FA:A4:36:FB:F0:9F:5C:62:71:ED:3C:F4:47:38:10:2B + X509v3 Authority Key Identifier: + keyid:76:F3:55:E1:FA:A4:36:FB:F0:9F:5C:62:71:ED:3C:F4:47:38:10:2B + + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 66:c1:c6:23:f3:d9:e0:2e:6e:5f:e8:cf:ae:b0:b0:25:4d:2b: + f8:3b:58:9b:40:24:37:5a:cb:ab:16:49:ff:b3:75:79:33:a1: + 2f:6d:70:17:34:91:fe:67:7e:8f:ec:9b:e5:5e:82:a9:55:1f: + 2f:dc:d4:51:07:12:fe:ac:16:3e:2c:35:c6:63:fc:dc:10:eb: + 0d:a3:aa:d0:7c:cc:d1:d0:2f:51:2e:c4:14:5a:de:e8:19:e1: + 3e:c6:cc:a4:29:e7:2e:84:aa:06:30:78:76:54:73:28:98:59: + 38:e0:00:0d:62:d3:42:7d:21:9f:ae:3d:3a:8c:d5:fa:77:0d: + 18:2b:16:0e:5f:36:e1:fc:2a:b5:30:24:cf:e0:63:0c:7b:58: + 1a:fe:99:ba:42:12:b1:91:f4:7c:68:e2:c8:e8:af:2c:ea:c9: + 7e:ae:bb:2a:3d:0d:15:dc:34:95:b6:18:74:a8:6a:0f:c7:b4: + f4:13:c4:e4:5b:ed:0a:d2:a4:97:4c:2a:ed:2f:6c:12:89:3d: + f1:27:70:aa:6a:03:52:21:9f:40:a8:67:50:f2:f3:5a:1f:df: + df:23:f6:dc:78:4e:e6:98:4f:55:3a:53:e3:ef:f2:f4:9f:c7: + 7c:d8:58:af:29:22:97:b8:e0:bd:91:2e:b0:76:ec:57:11:cf: + ef:29:44:f3:e9:85:7a:60:63:e4:5d:33:89:17:d9:31:aa:da: + d6:f3:18:35:72:cf:87:2b:2f:63:23:84:5d:84:8c:3f:57:a0: + 88:fc:99:91:28:26:69:99:d4:8f:97:44:be:8e:d5:48:b1:a4: + 28:29:f1:15:b4:e1:e5:9e:dd:f8:8f:a6:6f:26:d7:09:3c:3a: + 1c:11:0e:a6:6c:37:f7:ad:44:87:2c:28:c7:d8:74:82:b3:d0: + 6f:4a:57:bb:35:29:27:a0:8b:e8:21:a7:87:64:36:5d:cc:d8: + 16:ac:c7:b2:27:40:92:55:38:28:8d:51:6e:dd:14:67:53:6c: + 71:5c:26:84:4d:75:5a:b6:7e:60:56:a9:4d:ad:fb:9b:1e:97: + f3:0d:d9:d2:97:54:77:da:3d:12:b7:e0:1e:ef:08:06:ac:f9: + 85:87:e9:a2:dc:af:7e:18:12:83:fd:56:17:41:2e:d5:29:82: + 7d:99:f4:31:f6:71:a9:cf:2c:01:27:a5:05:b9:aa:b2:48:4e: + 2a:ef:9f:93:52:51:95:3c:52:73:8e:56:4c:17:40:c0:09:28: + e4:8b:6a:48:53:db:ec:cd:55:55:f1:c6:f8:e9:a2:2c:4c:a6: + d1:26:5f:7e:af:5a:4c:da:1f:a6:f2:1c:2c:7e:ae:02:16:d2: + 56:d0:2f:57:53:47:e8:92 +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy +c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD +VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 +c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 +WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG +FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq +XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL +se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb +KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd +IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 +y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt +hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc +QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 +Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV +HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ +KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ +L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr +Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo +ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY +T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz +GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m +1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV +OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH +6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX +QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +Visa eCommerce Root +# Issuer: CN=Visa eCommerce Root,OU=Visa International Service Association,O=VISA,C=US +# Serial Number:13:86:35:4d:1d:3f:06:f2:c1:f9:65:05:d5:90:1c:62 +# Subject: CN=Visa eCommerce Root,OU=Visa International Service Association,O=VISA,C=US +# Not Valid Before: Wed Jun 26 02:18:36 2002 +# Not Valid After : Fri Jun 24 00:16:12 2022 +# Fingerprint (MD5): FC:11:B8:D8:08:93:30:00:6D:23:F9:7E:EB:52:1E:02 +# Fingerprint (SHA1): 70:17:9B:86:8C:00:A4:FA:60:91:52:22:3F:9F:3E:32:BD:E0:05:62 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=FC:11:B8:D8:08:93:30:00:6D:23:F9:7E:EB:52:1E:02 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 13:86:35:4d:1d:3f:06:f2:c1:f9:65:05:d5:90:1c:62 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VISA, OU=Visa International Service Association, CN=Visa eCommerce Root + Validity + Not Before: Jun 26 02:18:36 2002 GMT + Not After : Jun 24 00:16:12 2022 GMT + Subject: C=US, O=VISA, OU=Visa International Service Association, CN=Visa eCommerce Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:af:57:de:56:1e:6e:a1:da:60:b1:94:27:cb:17: + db:07:3f:80:85:4f:c8:9c:b6:d0:f4:6f:4f:cf:99: + d8:e1:db:c2:48:5c:3a:ac:39:33:c7:1f:6a:8b:26: + 3d:2b:35:f5:48:b1:91:c1:02:4e:04:96:91:7b:b0: + 33:f0:b1:14:4e:11:6f:b5:40:af:1b:45:a5:4a:ef: + 7e:b6:ac:f2:a0:1f:58:3f:12:46:60:3c:8d:a1:e0: + 7d:cf:57:3e:33:1e:fb:47:f1:aa:15:97:07:55:66: + a5:b5:2d:2e:d8:80:59:b2:a7:0d:b7:46:ec:21:63: + ff:35:ab:a5:02:cf:2a:f4:4c:fe:7b:f5:94:5d:84: + 4d:a8:f2:60:8f:db:0e:25:3c:9f:73:71:cf:94:df: + 4a:ea:db:df:72:38:8c:f3:96:bd:f1:17:bc:d2:ba: + 3b:45:5a:c6:a7:f6:c6:17:8b:01:9d:fc:19:a8:2a: + 83:16:b8:3a:48:fe:4e:3e:a0:ab:06:19:e9:53:f3: + 80:13:07:ed:2d:bf:3f:0a:3c:55:20:39:2c:2c:00: + 69:74:95:4a:bc:20:b2:a9:79:e5:18:89:91:a8:dc: + 1c:4d:ef:bb:7e:37:0b:5d:fe:39:a5:88:52:8c:00: + 6c:ec:18:7c:41:bd:f6:8b:75:77:ba:60:9d:84:e7: + fe:2d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 15:38:83:0F:3F:2C:3F:70:33:1E:CD:46:FE:07:8C:20:E0:D7:C3:B7 + Signature Algorithm: sha1WithRSAEncryption + 5f:f1:41:7d:7c:5c:08:b9:2b:e0:d5:92:47:fa:67:5c:a5:13: + c3:03:21:9b:2b:4c:89:46:cf:59:4d:c9:fe:a5:40:b6:63:cd: + dd:71:28:95:67:11:cc:24:ac:d3:44:6c:71:ae:01:20:6b:03: + a2:8f:18:b7:29:3a:7d:e5:16:60:53:78:3c:c0:af:15:83:f7: + 8f:52:33:24:bd:64:93:97:ee:8b:f7:db:18:a8:6d:71:b3:f7: + 2c:17:d0:74:25:69:f7:fe:6b:3c:94:be:4d:4b:41:8c:4e:e2: + 73:d0:e3:90:22:73:43:cd:f3:ef:ea:73:ce:45:8a:b0:a6:49: + ff:4c:7d:9d:71:88:c4:76:1d:90:5b:1d:ee:fd:cc:f7:ee:fd: + 60:a5:b1:7a:16:71:d1:16:d0:7c:12:3c:6c:69:97:db:ae:5f: + 39:9a:70:2f:05:3c:19:46:04:99:20:36:d0:60:6e:61:06:bb: + 16:42:8c:70:f7:30:fb:e0:db:66:a3:00:01:bd:e6:2c:da:91: + 5f:a0:46:8b:4d:6a:9c:3d:3d:dd:05:46:fe:76:bf:a0:0a:3c: + e4:00:e6:27:b7:ff:84:2d:de:ba:22:27:96:10:71:eb:22:ed: + df:df:33:9c:cf:e3:ad:ae:8e:d4:8e:e6:4f:51:af:16:92:e0: + 5c:f6:07:0f +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr +MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl +cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw +CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h +dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l +cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h +2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E +lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV +ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq +299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t +vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL +dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF +AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR +zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 +LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd +7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw +++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----END CERTIFICATE----- + +Comodo AAA Services root +# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Serial Number: 1 (0x1) +# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Not Valid Before: Thu Jan 01 00:00:00 2004 +# Not Valid After : Sun Dec 31 23:59:59 2028 +# Fingerprint (MD5): 49:79:04:B0:EB:87:19:AC:47:B0:BC:11:51:9B:74:D0 +# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=49:79:04:B0:EB:87:19:AC:47:B0:BC:11:51:9B:74:D0 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services + Validity + Not Before: Jan 1 00:00:00 2004 GMT + Not After : Dec 31 23:59:59 2028 GMT + Subject: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:be:40:9d:f4:6e:e1:ea:76:87:1c:4d:45:44:8e: + be:46:c8:83:06:9d:c1:2a:fe:18:1f:8e:e4:02:fa: + f3:ab:5d:50:8a:16:31:0b:9a:06:d0:c5:70:22:cd: + 49:2d:54:63:cc:b6:6e:68:46:0b:53:ea:cb:4c:24: + c0:bc:72:4e:ea:f1:15:ae:f4:54:9a:12:0a:c3:7a: + b2:33:60:e2:da:89:55:f3:22:58:f3:de:dc:cf:ef: + 83:86:a2:8c:94:4f:9f:68:f2:98:90:46:84:27:c7: + 76:bf:e3:cc:35:2c:8b:5e:07:64:65:82:c0:48:b0: + a8:91:f9:61:9f:76:20:50:a8:91:c7:66:b5:eb:78: + 62:03:56:f0:8a:1a:13:ea:31:a3:1e:a0:99:fd:38: + f6:f6:27:32:58:6f:07:f5:6b:b8:fb:14:2b:af:b7: + aa:cc:d6:63:5f:73:8c:da:05:99:a8:38:a8:cb:17: + 78:36:51:ac:e9:9e:f4:78:3a:8d:cf:0f:d9:42:e2: + 98:0c:ab:2f:9f:0e:01:de:ef:9f:99:49:f1:2d:df: + ac:74:4d:1b:98:b5:47:c5:e5:29:d1:f9:90:18:c7: + 62:9c:be:83:c7:26:7b:3e:8a:25:c7:c0:dd:9d:e6: + 35:68:10:20:9d:8f:d8:de:d2:c3:84:9c:0d:5e:e8: + 2f:c9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A0:11:0A:23:3E:96:F1:07:EC:E2:AF:29:EF:82:A5:7F:D0:30:A4:B4 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 CRL Distribution Points: + + Full Name: + URI:http://crl.comodoca.com/AAACertificateServices.crl + + Full Name: + URI:http://crl.comodo.net/AAACertificateServices.crl + + Signature Algorithm: sha1WithRSAEncryption + 08:56:fc:02:f0:9b:e8:ff:a4:fa:d6:7b:c6:44:80:ce:4f:c4: + c5:f6:00:58:cc:a6:b6:bc:14:49:68:04:76:e8:e6:ee:5d:ec: + 02:0f:60:d6:8d:50:18:4f:26:4e:01:e3:e6:b0:a5:ee:bf:bc: + 74:54:41:bf:fd:fc:12:b8:c7:4f:5a:f4:89:60:05:7f:60:b7: + 05:4a:f3:f6:f1:c2:bf:c4:b9:74:86:b6:2d:7d:6b:cc:d2:f3: + 46:dd:2f:c6:e0:6a:c3:c3:34:03:2c:7d:96:dd:5a:c2:0e:a7: + 0a:99:c1:05:8b:ab:0c:2f:f3:5c:3a:cf:6c:37:55:09:87:de: + 53:40:6c:58:ef:fc:b6:ab:65:6e:04:f6:1b:dc:3c:e0:5a:15: + c6:9e:d9:f1:59:48:30:21:65:03:6c:ec:e9:21:73:ec:9b:03: + a1:e0:37:ad:a0:15:18:8f:fa:ba:02:ce:a7:2c:a9:10:13:2c: + d4:e5:08:26:ab:22:97:60:f8:90:5e:74:d4:a2:9a:53:bd:f2: + a9:68:e0:a2:6e:c2:d7:6c:b1:a3:0f:9e:bf:eb:68:e7:56:f2: + ae:f2:e3:2b:38:3a:09:81:b5:6b:85:d7:be:2d:ed:3f:1a:b7: + b2:63:e2:f5:62:2c:82:d4:6a:00:41:50:f1:39:83:9f:95:e9: + 36:96:98:6e +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +QuoVadis Root CA +# Issuer: CN=QuoVadis Root Certification Authority,OU=Root Certification Authority,O=QuoVadis Limited,C=BM +# Serial Number: 985026699 (0x3ab6508b) +# Subject: CN=QuoVadis Root Certification Authority,OU=Root Certification Authority,O=QuoVadis Limited,C=BM +# Not Valid Before: Mon Mar 19 18:33:33 2001 +# Not Valid After : Wed Mar 17 18:33:33 2021 +# Fingerprint (MD5): 27:DE:36:FE:72:B7:00:03:00:9D:F4:F0:1E:6C:04:24 +# Fingerprint (SHA1): DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=27:DE:36:FE:72:B7:00:03:00:9D:F4:F0:1E:6C:04:24 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 985026699 (0x3ab6508b) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=BM, O=QuoVadis Limited, OU=Root Certification Authority, CN=QuoVadis Root Certification Authority + Validity + Not Before: Mar 19 18:33:33 2001 GMT + Not After : Mar 17 18:33:33 2021 GMT + Subject: C=BM, O=QuoVadis Limited, OU=Root Certification Authority, CN=QuoVadis Root Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:bf:61:b5:95:53:ba:57:fc:fa:f2:67:0b:3a:1a: + df:11:80:64:95:b4:d1:bc:cd:7a:cf:f6:29:96:2e: + 24:54:40:24:38:f7:1a:85:dc:58:4c:cb:a4:27:42: + 97:d0:9f:83:8a:c3:e4:06:03:5b:00:a5:51:1e:70: + 04:74:e2:c1:d4:3a:ab:d7:ad:3b:07:18:05:8e:fd: + 83:ac:ea:66:d9:18:1b:68:8a:f5:57:1a:98:ba:f5: + ed:76:3d:7c:d9:de:94:6a:3b:4b:17:c1:d5:8f:bd: + 65:38:3a:95:d0:3d:55:36:4e:df:79:57:31:2a:1e: + d8:59:65:49:58:20:98:7e:ab:5f:7e:9f:e9:d6:4d: + ec:83:74:a9:c7:6c:d8:ee:29:4a:85:2a:06:14:f9: + 54:e6:d3:da:65:07:8b:63:37:12:d7:d0:ec:c3:7b: + 20:41:44:a3:ed:cb:a0:17:e1:71:65:ce:1d:66:31: + f7:76:01:19:c8:7d:03:58:b6:95:49:1d:a6:12:26: + e8:c6:0c:76:e0:e3:66:cb:ea:5d:a6:26:ee:e5:cc: + 5f:bd:67:a7:01:27:0e:a2:ca:54:c5:b1:7a:95:1d: + 71:1e:4a:29:8a:03:dc:6a:45:c1:a4:19:5e:6f:36: + cd:c3:a2:b0:b7:fe:5c:38:e2:52:bc:f8:44:43:e6: + 90:bb + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:https://ocsp.quovadisoffshore.com + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.8024.0.1 + User Notice: + Explicit Text: Reliance on the QuoVadis Root Certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certification practices, and the QuoVadis Certificate Policy. + CPS: http://www.quovadis.bm + + X509v3 Subject Key Identifier: + 8B:4B:6D:ED:D3:29:B9:06:19:EC:39:39:A9:F0:97:84:6A:CB:EF:DF + X509v3 Authority Key Identifier: + keyid:8B:4B:6D:ED:D3:29:B9:06:19:EC:39:39:A9:F0:97:84:6A:CB:EF:DF + DirName:/C=BM/O=QuoVadis Limited/OU=Root Certification Authority/CN=QuoVadis Root Certification Authority + serial:3A:B6:50:8B + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 8a:d4:14:b5:fe:f4:9a:92:a7:19:d4:a4:7e:72:18:8f:d9:68: + 7c:52:24:dd:67:6f:39:7a:c4:aa:5e:3d:e2:58:b0:4d:70:98: + 84:61:e8:1b:e3:69:18:0e:ce:fb:47:50:a0:4e:ff:f0:24:1f: + bd:b2:ce:f5:27:fc:ec:2f:53:aa:73:7b:03:3d:74:6e:e6:16: + 9e:eb:a5:2e:c4:bf:56:27:50:2b:62:ba:be:4b:1c:3c:55:5c: + 41:1d:24:be:82:20:47:5d:d5:44:7e:7a:16:68:df:7d:4d:51: + 70:78:57:1d:33:1e:fd:02:99:9c:0c:cd:0a:05:4f:c7:bb:8e: + a4:75:fa:4a:6d:b1:80:8e:09:56:b9:9c:1a:60:fe:5d:c1:d7: + 7a:dc:11:78:d0:d6:5d:c1:b7:d5:ad:32:99:03:3a:8a:cc:54: + 25:39:31:81:7b:13:22:51:ba:46:6c:a1:bb:9e:fa:04:6c:49: + 26:74:8f:d2:73:eb:cc:30:a2:e6:ea:59:22:87:f8:97:f5:0e: + fd:ea:cc:92:a4:16:c4:52:18:ea:21:ce:b1:f1:e6:84:81:e5: + ba:a9:86:28:f2:43:5a:5d:12:9d:ac:1e:d9:a8:e5:0a:6a:a7: + 7f:a0:87:29:cf:f2:89:4d:d4:ec:c5:e2:e6:7a:d0:36:23:8a: + 4a:74:36:f9 +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz +MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw +IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR +dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp +li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D +rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ +WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug +F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU +xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC +Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv +dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw +ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl +IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh +c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy +ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI +KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T +KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq +y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p +dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD +VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL +MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk +fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 +7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R +cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y +mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW +xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK +SnQ2+Q== +-----END CERTIFICATE----- + +QuoVadis Root CA 2 +# Issuer: CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM +# Serial Number: 1289 (0x509) +# Subject: CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM +# Not Valid Before: Fri Nov 24 18:27:00 2006 +# Not Valid After : Mon Nov 24 18:23:33 2031 +# Fingerprint (MD5): 5E:39:7B:DD:F8:BA:EC:82:E9:AC:62:BA:0C:54:00:2B +# Fingerprint (SHA1): CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=5E:39:7B:DD:F8:BA:EC:82:E9:AC:62:BA:0C:54:00:2B +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1289 (0x509) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 2 + Validity + Not Before: Nov 24 18:27:00 2006 GMT + Not After : Nov 24 18:23:33 2031 GMT + Subject: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:9a:18:ca:4b:94:0d:00:2d:af:03:29:8a:f0:0f: + 81:c8:ae:4c:19:85:1d:08:9f:ab:29:44:85:f3:2f: + 81:ad:32:1e:90:46:bf:a3:86:26:1a:1e:fe:7e:1c: + 18:3a:5c:9c:60:17:2a:3a:74:83:33:30:7d:61:54: + 11:cb:ed:ab:e0:e6:d2:a2:7e:f5:6b:6f:18:b7:0a: + 0b:2d:fd:e9:3e:ef:0a:c6:b3:10:e9:dc:c2:46:17: + f8:5d:fd:a4:da:ff:9e:49:5a:9c:e6:33:e6:24:96: + f7:3f:ba:5b:2b:1c:7a:35:c2:d6:67:fe:ab:66:50: + 8b:6d:28:60:2b:ef:d7:60:c3:c7:93:bc:8d:36:91: + f3:7f:f8:db:11:13:c4:9c:77:76:c1:ae:b7:02:6a: + 81:7a:a9:45:83:e2:05:e6:b9:56:c1:94:37:8f:48: + 71:63:22:ec:17:65:07:95:8a:4b:df:8f:c6:5a:0a: + e5:b0:e3:5f:5e:6b:11:ab:0c:f9:85:eb:44:e9:f8: + 04:73:f2:e9:fe:5c:98:8c:f5:73:af:6b:b4:7e:cd: + d4:5c:02:2b:4c:39:e1:b2:95:95:2d:42:87:d7:d5: + b3:90:43:b7:6c:13:f1:de:dd:f6:c4:f8:89:3f:d1: + 75:f5:92:c3:91:d5:8a:88:d0:90:ec:dc:6d:de:89: + c2:65:71:96:8b:0d:03:fd:9c:bf:5b:16:ac:92:db: + ea:fe:79:7c:ad:eb:af:f7:16:cb:db:cd:25:2b:e5: + 1f:fb:9a:9f:e2:51:cc:3a:53:0c:48:e6:0e:bd:c9: + b4:76:06:52:e6:11:13:85:72:63:03:04:e0:04:36: + 2b:20:19:02:e8:74:a7:1f:b6:c9:56:66:f0:75:25: + dc:67:c1:0e:61:60:88:b3:3e:d1:a8:fc:a3:da:1d: + b0:d1:b1:23:54:df:44:76:6d:ed:41:d8:c1:b2:22: + b6:53:1c:df:35:1d:dc:a1:77:2a:31:e4:2d:f5:e5: + e5:db:c8:e0:ff:e5:80:d7:0b:63:a0:ff:33:a1:0f: + ba:2c:15:15:ea:97:b3:d2:a2:b5:be:f2:8c:96:1e: + 1a:8f:1d:6c:a4:61:37:b9:86:73:33:d7:97:96:9e: + 23:7d:82:a4:4c:81:e2:a1:d1:ba:67:5f:95:07:a3: + 27:11:ee:16:10:7b:bc:45:4a:4c:b2:04:d2:ab:ef: + d5:fd:0c:51:ce:50:6a:08:31:f9:91:da:0c:8f:64: + 5c:03:c3:3a:8b:20:3f:6e:8d:67:3d:3a:d6:fe:7d: + 5b:88:c9:5e:fb:cc:61:dc:8b:33:77:d3:44:32:35: + 09:62:04:92:16:10:d8:9e:27:47:fb:3b:21:e3:f8: + eb:1d:5b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 1A:84:62:BC:48:4C:33:25:04:D4:EE:D0:F6:03:C4:19:46:D1:94:6B + X509v3 Authority Key Identifier: + keyid:1A:84:62:BC:48:4C:33:25:04:D4:EE:D0:F6:03:C4:19:46:D1:94:6B + DirName:/C=BM/O=QuoVadis Limited/CN=QuoVadis Root CA 2 + serial:05:09 + + Signature Algorithm: sha1WithRSAEncryption + 3e:0a:16:4d:9f:06:5b:a8:ae:71:5d:2f:05:2f:67:e6:13:45: + 83:c4:36:f6:f3:c0:26:0c:0d:b5:47:64:5d:f8:b4:72:c9:46: + a5:03:18:27:55:89:78:7d:76:ea:96:34:80:17:20:dc:e7:83: + f8:8d:fc:07:b8:da:5f:4d:2e:67:b2:84:fd:d9:44:fc:77:50: + 81:e6:7c:b4:c9:0d:0b:72:53:f8:76:07:07:41:47:96:0c:fb: + e0:82:26:93:55:8c:fe:22:1f:60:65:7c:5f:e7:26:b3:f7:32: + 90:98:50:d4:37:71:55:f6:92:21:78:f7:95:79:fa:f8:2d:26: + 87:66:56:30:77:a6:37:78:33:52:10:58:ae:3f:61:8e:f2:6a: + b1:ef:18:7e:4a:59:63:ca:8d:a2:56:d5:a7:2f:bc:56:1f:cf: + 39:c1:e2:fb:0a:a8:15:2c:7d:4d:7a:63:c6:6c:97:44:3c:d2: + 6f:c3:4a:17:0a:f8:90:d2:57:a2:19:51:a5:2d:97:41:da:07: + 4f:a9:50:da:90:8d:94:46:e1:3e:f0:94:fd:10:00:38:f5:3b: + e8:40:e1:b4:6e:56:1a:20:cc:6f:58:8d:ed:2e:45:8f:d6:e9: + 93:3f:e7:b1:2c:df:3a:d6:22:8c:dc:84:bb:22:6f:d0:f8:e4: + c6:39:e9:04:88:3c:c3:ba:eb:55:7a:6d:80:99:24:f5:6c:01: + fb:f8:97:b0:94:5b:eb:fd:d2:6f:f1:77:68:0d:35:64:23:ac: + b8:55:a1:03:d1:4d:42:19:dc:f8:75:59:56:a3:f9:a8:49:79: + f8:af:0e:b9:11:a0:7c:b7:6a:ed:34:d0:b6:26:62:38:1a:87: + 0c:f8:e8:fd:2e:d3:90:7f:07:91:2a:1d:d6:7e:5c:85:83:99: + b0:38:08:3f:e9:5e:f9:35:07:e4:c9:62:6e:57:7f:a7:50:95: + f7:ba:c8:9b:e6:8e:a2:01:c5:d6:66:bf:79:61:f3:3c:1c:e1: + b9:82:5c:5d:a0:c3:e9:d8:48:bd:19:a2:11:14:19:6e:b2:86: + 1b:68:3e:48:37:1a:88:b7:5d:96:5e:9c:c7:ef:27:62:08:e2: + 91:19:5c:d2:f1:21:dd:ba:17:42:82:97:71:81:53:31:a9:9f: + f6:7d:62:bf:72:e1:a3:93:1d:cc:8a:26:5a:09:38:d0:ce:d7: + 0d:80:16:b4:78:a5:3a:87:4c:8d:8a:a5:d5:46:97:f2:2c:10: + b9:bc:54:22:c0:01:50:69:43:9e:f4:b2:ef:6d:f8:ec:da:f1: + e3:b1:ef:df:91:8f:54:2a:0b:25:c1:26:19:c4:52:10:05:65: + d5:82:10:ea:c2:31:cd:2e +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa +GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg +Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J +WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB +rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp ++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 +ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i +Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz +PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og +/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH +oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI +yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud +EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 +A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL +MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f +BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn +g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl +fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K +WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha +B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc +hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR +TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD +mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z +ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y +4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza +8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +# Issuer: CN=QuoVadis Root CA 3,O=QuoVadis Limited,C=BM +# Serial Number: 1478 (0x5c6) +# Subject: CN=QuoVadis Root CA 3,O=QuoVadis Limited,C=BM +# Not Valid Before: Fri Nov 24 19:11:23 2006 +# Not Valid After : Mon Nov 24 19:06:44 2031 +# Fingerprint (MD5): 31:85:3C:62:94:97:63:B9:AA:FD:89:4E:AF:6F:E0:CF +# Fingerprint (SHA1): 1F:49:14:F7:D8:74:95:1D:DD:AE:02:C0:BE:FD:3A:2D:82:75:51:85 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=31:85:3C:62:94:97:63:B9:AA:FD:89:4E:AF:6F:E0:CF +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1478 (0x5c6) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 3 + Validity + Not Before: Nov 24 19:11:23 2006 GMT + Not After : Nov 24 19:06:44 2031 GMT + Subject: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:cc:57:42:16:54:9c:e6:98:d3:d3:4d:ee:fe:ed: + c7:9f:43:39:4a:65:b3:e8:16:88:34:db:0d:59:91: + 74:cf:92:b8:04:40:ad:02:4b:31:ab:bc:8d:91:68: + d8:20:0e:1a:01:e2:1a:7b:4e:17:5d:e2:8a:b7:3f: + 99:1a:cd:eb:61:ab:c2:65:a6:1f:b7:b7:bd:b7:8f: + fc:fd:70:8f:0b:a0:67:be:01:a2:59:cf:71:e6:0f: + 29:76:ff:b1:56:79:45:2b:1f:9e:7a:54:e8:a3:29: + 35:68:a4:01:4f:0f:a4:2e:37:ef:1b:bf:e3:8f:10: + a8:72:ab:58:57:e7:54:86:c8:c9:f3:5b:da:2c:da: + 5d:8e:6e:3c:a3:3e:da:fb:82:e5:dd:f2:5c:b2:05: + 33:6f:8a:36:ce:d0:13:4e:ff:bf:4a:0c:34:4c:a6: + c3:21:bd:50:04:55:eb:b1:bb:9d:fb:45:1e:64:15: + de:55:01:8c:02:76:b5:cb:a1:3f:42:69:bc:2f:bd: + 68:43:16:56:89:2a:37:61:91:fd:a6:ae:4e:c0:cb: + 14:65:94:37:4b:92:06:ef:04:d0:c8:9c:88:db:0b: + 7b:81:af:b1:3d:2a:c4:65:3a:78:b6:ee:dc:80:b1: + d2:d3:99:9c:3a:ee:6b:5a:6b:b3:8d:b7:d5:ce:9c: + c2:be:a5:4b:2f:16:b1:9e:68:3b:06:6f:ae:7d:9f: + f8:de:ec:cc:29:a7:98:a3:25:43:2f:ef:f1:5f:26: + e1:88:4d:f8:5e:6e:d7:d9:14:6e:19:33:69:a7:3b: + 84:89:93:c4:53:55:13:a1:51:78:40:f8:b8:c9:a2: + ee:7b:ba:52:42:83:9e:14:ed:05:52:5a:59:56:a7: + 97:fc:9d:3f:0a:29:d8:dc:4f:91:0e:13:bc:de:95: + a4:df:8b:99:be:ac:9b:33:88:ef:b5:81:af:1b:c6: + 22:53:c8:f6:c7:ee:97:14:b0:c5:7c:78:52:c8:f0: + ce:6e:77:60:84:a6:e9:2a:76:20:ed:58:01:17:30: + 93:e9:1a:8b:e0:73:63:d9:6a:92:94:49:4e:b4:ad: + 4a:85:c4:a3:22:30:fc:09:ed:68:22:73:a6:88:0c: + 55:21:58:c5:e1:3a:9f:2a:dd:ca:e1:90:e0:d9:73: + ab:6c:80:b8:e8:0b:64:93:a0:9c:8c:19:ff:b3:d2: + 0c:ec:91:26:87:8a:b3:a2:e1:70:8f:2c:0a:e5:cd: + 6d:68:51:eb:da:3f:05:7f:8b:32:e6:13:5c:6b:fe: + 5f:40:e2:22:c8:b4:b4:64:4f:d6:ba:7d:48:3e:a8: + 69:0c:d7:bb:86:71:c9:73:b8:3f:3b:9d:25:4b:da: + ff:40:eb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.8024.0.3 + User Notice: + Explicit Text: Any use of this Certificate constitutes acceptance of the QuoVadis Root CA 3 Certificate Policy / Certification Practice Statement. + CPS: http://www.quovadisglobal.com/cps + + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + F2:C0:13:E0:82:43:3E:FB:EE:2F:67:32:96:35:5C:DB:B8:CB:02:D0 + X509v3 Authority Key Identifier: + keyid:F2:C0:13:E0:82:43:3E:FB:EE:2F:67:32:96:35:5C:DB:B8:CB:02:D0 + DirName:/C=BM/O=QuoVadis Limited/CN=QuoVadis Root CA 3 + serial:05:C6 + + Signature Algorithm: sha1WithRSAEncryption + 4f:ad:a0:2c:4c:fa:c0:f2:6f:f7:66:55:ab:23:34:ee:e7:29: + da:c3:5b:b6:b0:83:d9:d0:d0:e2:21:fb:f3:60:a7:3b:5d:60: + 53:27:a2:9b:f6:08:22:2a:e7:bf:a0:72:e5:9c:24:6a:31:b1: + 90:7a:27:db:84:11:89:27:a6:77:5a:38:d7:bf:ac:86:fc:ee: + 5d:83:bc:06:c6:d1:77:6b:0f:6d:24:2f:4b:7a:6c:a7:07:96: + ca:e3:84:9f:ad:88:8b:1d:ab:16:8d:5b:66:17:d9:16:f4:8b: + 80:d2:dd:f8:b2:76:c3:fc:38:13:aa:0c:de:42:69:2b:6e:f3: + 3c:eb:80:27:db:f5:a6:44:0d:9f:5a:55:59:0b:d5:0d:52:48: + c5:ae:9f:f2:2f:80:c5:ea:32:50:35:12:97:2e:c1:e1:ff:f1: + 23:88:51:38:9f:f2:66:56:76:e7:0f:51:97:a5:52:0c:4d:49: + 51:95:36:3d:bf:a2:4b:0c:10:1d:86:99:4c:aa:f3:72:11:93: + e4:ea:f6:9b:da:a8:5d:a7:4d:b7:9e:02:ae:73:00:c8:da:23: + 03:e8:f9:ea:19:74:62:00:94:cb:22:20:be:94:a7:59:b5:82: + 6a:be:99:79:7a:a9:f2:4a:24:52:f7:74:fd:ba:4e:e6:a8:1d: + 02:6e:b1:0d:80:44:c1:ae:d3:23:37:5f:bb:85:7c:2b:92:2e: + e8:7e:a5:8b:dd:99:e1:bf:27:6f:2d:5d:aa:7b:87:fe:0a:dd: + 4b:fc:8e:f5:26:e4:6e:70:42:6e:33:ec:31:9e:7b:93:c1:e4: + c9:69:1a:3d:c0:6b:4e:22:6d:ee:ab:58:4d:c6:d0:41:c1:2b: + ea:4f:12:87:5e:eb:45:d8:6c:f5:98:02:d3:a0:d8:55:8a:06: + 99:19:a2:a0:77:d1:30:9e:ac:cc:75:ee:83:f5:b0:62:39:cf: + 6c:57:e2:4c:d2:91:0b:0e:75:28:1b:9a:bf:fd:1a:43:f1:ca: + 77:fb:3b:8f:61:b8:69:28:16:42:04:5e:70:2a:1c:21:d8:8f: + e1:bd:23:5b:2d:74:40:92:d9:63:19:0d:73:dd:69:bc:62:47: + bc:e0:74:2b:b2:eb:7d:be:41:1b:b5:c0:46:c5:a1:22:cb:5f: + 4e:c1:28:92:de:18:ba:d5:2a:28:bb:11:8b:17:93:98:99:60: + 94:5c:23:cf:5a:27:97:5e:0b:05:06:93:37:1e:3b:69:36:eb: + a9:9e:61:1d:8f:32:da:8e:0c:d6:74:3e:7b:09:24:da:01:77: + 47:c4:3b:cd:34:8c:99:f5:ca:e1:25:61:33:b2:59:1b:e2:6e: + d7:37:57:b6:0d:a9:12:da +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM +V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB +4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr +H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd +8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv +vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT +mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe +btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc +T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt +WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ +c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A +4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD +VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG +CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 +aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw +czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G +A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg +Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 +7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem +d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd ++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B +4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN +t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x +DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 +k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s +zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j +Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT +mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK +4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +Security Communication Root CA +# Issuer: OU=Security Communication RootCA1,O=SECOM Trust.net,C=JP +# Serial Number: 0 (0x0) +# Subject: OU=Security Communication RootCA1,O=SECOM Trust.net,C=JP +# Not Valid Before: Tue Sep 30 04:20:49 2003 +# Not Valid After : Sat Sep 30 04:20:49 2023 +# Fingerprint (MD5): F1:BC:63:6A:54:E0:B5:27:F5:CD:E7:1A:E3:4D:6E:4A +# Fingerprint (SHA1): 36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=F1:BC:63:6A:54:E0:B5:27:F5:CD:E7:1A:E3:4D:6E:4A +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=JP, O=SECOM Trust.net, OU=Security Communication RootCA1 + Validity + Not Before: Sep 30 04:20:49 2003 GMT + Not After : Sep 30 04:20:49 2023 GMT + Subject: C=JP, O=SECOM Trust.net, OU=Security Communication RootCA1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b3:b3:fe:7f:d3:6d:b1:ef:16:7c:57:a5:0c:6d: + 76:8a:2f:4b:bf:64:fb:4c:ee:8a:f0:f3:29:7c:f5: + ff:ee:2a:e0:e9:e9:ba:5b:64:22:9a:9a:6f:2c:3a: + 26:69:51:05:99:26:dc:d5:1c:6a:71:c6:9a:7d:1e: + 9d:dd:7c:6c:c6:8c:67:67:4a:3e:f8:71:b0:19:27: + a9:09:0c:a6:95:bf:4b:8c:0c:fa:55:98:3b:d8:e8: + 22:a1:4b:71:38:79:ac:97:92:69:b3:89:7e:ea:21: + 68:06:98:14:96:87:d2:61:36:bc:6d:27:56:9e:57: + ee:c0:c0:56:fd:32:cf:a4:d9:8e:c2:23:d7:8d:a8: + f3:d8:25:ac:97:e4:70:38:f4:b6:3a:b4:9d:3b:97: + 26:43:a3:a1:bc:49:59:72:4c:23:30:87:01:58:f6: + 4e:be:1c:68:56:66:af:cd:41:5d:c8:b3:4d:2a:55: + 46:ab:1f:da:1e:e2:40:3d:db:cd:7d:b9:92:80:9c: + 37:dd:0c:96:64:9d:dc:22:f7:64:8b:df:61:de:15: + 94:52:15:a0:7d:52:c9:4b:a8:21:c9:c6:b1:ed:cb: + c3:95:60:d1:0f:f0:ab:70:f8:df:cb:4d:7e:ec:d6: + fa:ab:d9:bd:7f:54:f2:a5:e9:79:fa:d9:d6:76:24: + 28:73 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A0:73:49:99:68:DC:85:5B:65:E3:9B:28:2F:57:9F:BD:33:BC:07:48 + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 68:40:a9:a8:bb:e4:4f:5d:79:b3:05:b5:17:b3:60:13:eb:c6: + 92:5d:e0:d1:d3:6a:fe:fb:be:9b:6d:bf:c7:05:6d:59:20:c4: + 1c:f0:b7:da:84:58:02:63:fa:48:16:ef:4f:a5:0b:f7:4a:98: + f2:3f:9e:1b:ad:47:6b:63:ce:08:47:eb:52:3f:78:9c:af:4d: + ae:f8:d5:4f:cf:9a:98:2a:10:41:39:52:c4:dd:d9:9b:0e:ef: + 93:01:ae:b2:2e:ca:68:42:24:42:6c:b0:b3:3a:3e:cd:e9:da: + 48:c4:15:cb:e9:f9:07:0f:92:50:49:8a:dd:31:97:5f:c9:e9: + 37:aa:3b:59:65:97:94:32:c9:b3:9f:3e:3a:62:58:c5:49:ad: + 62:0e:71:a5:32:aa:2f:c6:89:76:43:40:13:13:67:3d:a2:54: + 25:10:cb:f1:3a:f2:d9:fa:db:49:56:bb:a6:fe:a7:41:35:c3: + e0:88:61:c9:88:c7:df:36:10:22:98:59:ea:b0:4a:fb:56:16: + 73:6e:ac:4d:f7:22:a1:4f:ad:1d:7a:2d:45:27:e5:30:c1:5e: + f2:da:13:cb:25:42:51:95:47:03:8c:6c:21:cc:74:42:ed:53: + ff:33:8b:8f:0f:57:01:16:2f:cf:a6:ee:c9:70:22:14:bd:fd: + be:6c:0b:03 +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY +MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t +dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 +WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD +VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 +9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ +DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 +Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N +QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ +xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G +A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG +kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr +Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 +Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU +JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot +RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== +-----END CERTIFICATE----- + +Sonera Class 2 Root CA +# Issuer: CN=Sonera Class2 CA,O=Sonera,C=FI +# Serial Number: 29 (0x1d) +# Subject: CN=Sonera Class2 CA,O=Sonera,C=FI +# Not Valid Before: Fri Apr 06 07:29:40 2001 +# Not Valid After : Tue Apr 06 07:29:40 2021 +# Fingerprint (MD5): A3:EC:75:0F:2E:88:DF:FA:48:01:4E:0B:5C:48:6F:FB +# Fingerprint (SHA1): 37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=A3:EC:75:0F:2E:88:DF:FA:48:01:4E:0B:5C:48:6F:FB +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 29 (0x1d) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=FI, O=Sonera, CN=Sonera Class2 CA + Validity + Not Before: Apr 6 07:29:40 2001 GMT + Not After : Apr 6 07:29:40 2021 GMT + Subject: C=FI, O=Sonera, CN=Sonera Class2 CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:90:17:4a:35:9d:ca:f0:0d:96:c7:44:fa:16:37: + fc:48:bd:bd:7f:80:2d:35:3b:e1:6f:a8:67:a9:bf: + 03:1c:4d:8c:6f:32:47:d5:41:68:a4:13:04:c1:35: + 0c:9a:84:43:fc:5c:1d:ff:89:b3:e8:17:18:cd:91: + 5f:fb:89:e3:ea:bf:4e:5d:7c:1b:26:d3:75:79:ed: + e6:84:e3:57:e5:ad:29:c4:f4:3a:28:e7:a5:7b:84: + 36:69:b3:fd:5e:76:bd:a3:2d:99:d3:90:4e:23:28: + 7d:18:63:f1:54:3b:26:9d:76:5b:97:42:b2:ff:ae: + f0:4e:ec:dd:39:95:4e:83:06:7f:e7:49:40:c8:c5: + 01:b2:54:5a:66:1d:3d:fc:f9:e9:3c:0a:9e:81:b8: + 70:f0:01:8b:e4:23:54:7c:c8:ae:f8:90:1e:00:96: + 72:d4:54:cf:61:23:bc:ea:fb:9d:02:95:d1:b6:b9: + 71:3a:69:08:3f:0f:b4:e1:42:c7:88:f5:3f:98:a8: + a7:ba:1c:e0:71:71:ef:58:57:81:50:7a:5c:6b:74: + 46:0e:83:03:98:c3:8e:a8:6e:f2:76:32:6e:27:83: + c2:73:f3:dc:18:e8:b4:93:ea:75:44:6b:04:60:20: + 71:57:87:9d:f3:be:a0:90:23:3d:8a:24:e1:da:21: + db:c3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 4A:A0:AA:58:84:D3:5E:3C + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 5a:ce:87:f9:16:72:15:57:4b:1d:d9:9b:e7:a2:26:30:ec:93: + 67:df:d6:2d:d2:34:af:f7:38:a5:ce:ab:16:b9:ab:2f:7c:35: + cb:ac:d0:0f:b4:4c:2b:fc:80:ef:6b:8c:91:5f:36:76:f7:db: + b3:1b:19:ea:f4:b2:11:fd:61:71:44:bf:28:b3:3a:1d:bf:b3: + 43:e8:9f:bf:dc:31:08:71:b0:9d:8d:d6:34:47:32:90:c6:65: + 24:f7:a0:4a:7c:04:73:8f:39:6f:17:8c:72:b5:bd:4b:c8:7a: + f8:7b:83:c3:28:4e:9c:09:ea:67:3f:b2:67:04:1b:c3:14:da: + f8:e7:49:24:91:d0:1d:6a:fa:61:39:ef:6b:e7:21:75:06:07: + d8:12:b4:21:20:70:42:71:81:da:3c:9a:36:be:a6:5b:0d:6a: + 6c:9a:1f:91:7b:f9:f9:ef:42:ba:4e:4e:9e:cc:0c:8d:94:dc: + d9:45:9c:5e:ec:42:50:63:ae:f4:5d:c4:b1:12:dc:ca:3b:a8: + 2e:9d:14:5a:05:75:b7:ec:d7:63:e2:ba:35:b6:04:08:91:e8: + da:9d:9c:f6:66:b5:18:ac:0a:a6:54:26:34:33:d2:1b:c1:d4: + 7f:1a:3a:8e:0b:aa:32:6e:db:fc:4f:25:9f:d9:32:c7:96:5a: + 70:ac:df:4c +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx +MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o +Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt +5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s +3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej +vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu +8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil +zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ +3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD +FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 +Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 +ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M +-----END CERTIFICATE----- + +Camerfirma Chambers of Commerce Root +# Issuer: CN=Chambers of Commerce Root,OU=http://www.chambersign.org,O=AC Camerfirma SA CIF A82743287,C=EU +# Serial Number: 0 (0x0) +# Subject: CN=Chambers of Commerce Root,OU=http://www.chambersign.org,O=AC Camerfirma SA CIF A82743287,C=EU +# Not Valid Before: Tue Sep 30 16:13:43 2003 +# Not Valid After : Wed Sep 30 16:13:44 2037 +# Fingerprint (MD5): B0:01:EE:14:D9:AF:29:18:94:76:8E:F1:69:33:2A:84 +# Fingerprint (SHA1): 6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=B0:01:EE:14:D9:AF:29:18:94:76:8E:F1:69:33:2A:84 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=EU, O=AC Camerfirma SA CIF A82743287, OU=http://www.chambersign.org, CN=Chambers of Commerce Root + Validity + Not Before: Sep 30 16:13:43 2003 GMT + Not After : Sep 30 16:13:44 2037 GMT + Subject: C=EU, O=AC Camerfirma SA CIF A82743287, OU=http://www.chambersign.org, CN=Chambers of Commerce Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b7:36:55:e5:a5:5d:18:30:e0:da:89:54:91:fc: + c8:c7:52:f8:2f:50:d9:ef:b1:75:73:65:47:7d:1b: + 5b:ba:75:c5:fc:a1:88:24:fa:2f:ed:ca:08:4a:39: + 54:c4:51:7a:b5:da:60:ea:38:3c:81:b2:cb:f1:bb: + d9:91:23:3f:48:01:70:75:a9:05:2a:ad:1f:71:f3: + c9:54:3d:1d:06:6a:40:3e:b3:0c:85:ee:5c:1b:79: + c2:62:c4:b8:36:8e:35:5d:01:0c:23:04:47:35:aa: + 9b:60:4e:a0:66:3d:cb:26:0a:9c:40:a1:f4:5d:98: + bf:71:ab:a5:00:68:2a:ed:83:7a:0f:a2:14:b5:d4: + 22:b3:80:b0:3c:0c:5a:51:69:2d:58:18:8f:ed:99: + 9e:f1:ae:e2:95:e6:f6:47:a8:d6:0c:0f:b0:58:58: + db:c3:66:37:9e:9b:91:54:33:37:d2:94:1c:6a:48: + c9:c9:f2:a5:da:a5:0c:23:f7:23:0e:9c:32:55:5e: + 71:9c:84:05:51:9a:2d:fd:e6:4e:2a:34:5a:de:ca: + 40:37:67:0c:54:21:55:77:da:0a:0c:cc:97:ae:80: + dc:94:36:4a:f4:3e:ce:36:13:1e:53:e4:ac:4e:3a: + 05:ec:db:ae:72:9c:38:8b:d0:39:3b:89:0a:3e:77: + fe:75 + Exponent: 3 (0x3) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:12 + X509v3 CRL Distribution Points: + + Full Name: + URI:http://crl.chambersign.org/chambersroot.crl + + X509v3 Subject Key Identifier: + E3:94:F5:B1:4D:E9:DB:A1:29:5B:57:8B:4D:76:06:76:E1:D1:A2:8A + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Subject Alternative Name: + email:chambersroot@chambersign.org + X509v3 Issuer Alternative Name: + email:chambersroot@chambersign.org + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.17326.10.3.1 + CPS: http://cps.chambersign.org/cps/chambersroot.html + + Signature Algorithm: sha1WithRSAEncryption + 0c:41:97:c2:1a:86:c0:22:7c:9f:fb:90:f3:1a:d1:03:b1:ef: + 13:f9:21:5f:04:9c:da:c9:a5:8d:27:6c:96:87:91:be:41:90: + 01:72:93:e7:1e:7d:5f:f6:89:c6:5d:a7:40:09:3d:ac:49:45: + 45:dc:2e:8d:30:68:b2:09:ba:fb:c3:2f:cc:ba:0b:df:3f:77: + 7b:46:7d:3a:12:24:8e:96:8f:3c:05:0a:6f:d2:94:28:1d:6d: + 0c:c0:2e:88:22:d5:d8:cf:1d:13:c7:f0:48:d7:d7:05:a7:cf: + c7:47:9e:3b:3c:34:c8:80:4f:d4:14:bb:fc:0d:50:f7:fa:b3: + ec:42:5f:a9:dd:6d:c8:f4:75:cf:7b:c1:72:26:b1:01:1c:5c: + 2c:fd:7a:4e:b4:01:c5:05:57:b9:e7:3c:aa:05:d9:88:e9:07: + 46:41:ce:ef:41:81:ae:58:df:83:a2:ae:ca:d7:77:1f:e7:00: + 3c:9d:6f:8e:e4:32:09:1d:4d:78:34:78:34:3c:94:9b:26:ed: + 4f:71:c6:19:7a:bd:20:22:48:5a:fe:4b:7d:03:b7:e7:58:be: + c6:32:4e:74:1e:68:dd:a8:68:5b:b3:3e:ee:62:7d:d9:80:e8: + 0a:75:7a:b7:ee:b4:65:9a:21:90:e0:aa:d0:98:bc:38:b5:73: + 3c:8b:f8:dc +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg +b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa +MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB +ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw +IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B +AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb +unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d +BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq +7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 +0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX +roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG +A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j +aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p +26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA +BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud +EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN +BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB +AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd +p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi +1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc +XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 +eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu +tGWaIZDgqtCYvDi1czyL+Nw= +-----END CERTIFICATE----- + +Camerfirma Global Chambersign Root +# Issuer: CN=Global Chambersign Root,OU=http://www.chambersign.org,O=AC Camerfirma SA CIF A82743287,C=EU +# Serial Number: 0 (0x0) +# Subject: CN=Global Chambersign Root,OU=http://www.chambersign.org,O=AC Camerfirma SA CIF A82743287,C=EU +# Not Valid Before: Tue Sep 30 16:14:18 2003 +# Not Valid After : Wed Sep 30 16:14:18 2037 +# Fingerprint (MD5): C5:E6:7B:BF:06:D0:4F:43:ED:C4:7A:65:8A:FB:6B:19 +# Fingerprint (SHA1): 33:9B:6B:14:50:24:9B:55:7A:01:87:72:84:D9:E0:2F:C3:D2:D8:E9 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=C5:E6:7B:BF:06:D0:4F:43:ED:C4:7A:65:8A:FB:6B:19 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=EU, O=AC Camerfirma SA CIF A82743287, OU=http://www.chambersign.org, CN=Global Chambersign Root + Validity + Not Before: Sep 30 16:14:18 2003 GMT + Not After : Sep 30 16:14:18 2037 GMT + Subject: C=EU, O=AC Camerfirma SA CIF A82743287, OU=http://www.chambersign.org, CN=Global Chambersign Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:a2:70:a2:d0:9f:42:ae:5b:17:c7:d8:7d:cf:14: + 83:fc:4f:c9:a1:b7:13:af:8a:d7:9e:3e:04:0a:92: + 8b:60:56:fa:b4:32:2f:88:4d:a1:60:08:f4:b7:09: + 4e:a0:49:2f:49:d6:d3:df:9d:97:5a:9f:94:04:70: + ec:3f:59:d9:b7:cc:66:8b:98:52:28:09:02:df:c5: + 2f:84:8d:7a:97:77:bf:ec:40:9d:25:72:ab:b5:3f: + 32:98:fb:b7:b7:fc:72:84:e5:35:87:f9:55:fa:a3: + 1f:0e:6f:2e:28:dd:69:a0:d9:42:10:c6:f8:b5:44: + c2:d0:43:7f:db:bc:e4:a2:3c:6a:55:78:0a:77:a9: + d8:ea:19:32:b7:2f:fe:5c:3f:1b:ee:b1:98:ec:ca: + ad:7a:69:45:e3:96:0f:55:f6:e6:ed:75:ea:65:e8: + 32:56:93:46:89:a8:25:8a:65:06:ee:6b:bf:79:07: + d0:f1:b7:af:ed:2c:4d:92:bb:c0:a8:5f:a7:67:7d: + 04:f2:15:08:70:ac:92:d6:7d:04:d2:33:fb:4c:b6: + 0b:0b:fb:1a:c9:c4:8d:03:a9:7e:5c:f2:50:ab:12: + a5:a1:cf:48:50:a5:ef:d2:c8:1a:13:fa:b0:7f:b1: + 82:1c:77:6a:0f:5f:dc:0b:95:8f:ef:43:7e:e6:45: + 09:25 + Exponent: 3 (0x3) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:12 + X509v3 CRL Distribution Points: + + Full Name: + URI:http://crl.chambersign.org/chambersignroot.crl + + X509v3 Subject Key Identifier: + 43:9C:36:9F:B0:9E:30:4D:C6:CE:5F:AD:10:AB:E5:03:A5:FA:A9:14 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Subject Alternative Name: + email:chambersignroot@chambersign.org + X509v3 Issuer Alternative Name: + email:chambersignroot@chambersign.org + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.17326.10.1.1 + CPS: http://cps.chambersign.org/cps/chambersignroot.html + + Signature Algorithm: sha1WithRSAEncryption + 3c:3b:70:91:f9:04:54:27:91:e1:ed:ed:fe:68:7f:61:5d:e5: + 41:65:4f:32:f1:18:05:94:6a:1c:de:1f:70:db:3e:7b:32:02: + 34:b5:0c:6c:a1:8a:7c:a5:f4:8f:ff:d4:d8:ad:17:d5:2d:04: + d1:3f:58:80:e2:81:59:88:be:c0:e3:46:93:24:fe:90:bd:26: + a2:30:2d:e8:97:26:57:35:89:74:96:18:f6:15:e2:af:24:19: + 56:02:02:b2:ba:0f:14:ea:c6:8a:66:c1:86:45:55:8b:be:92: + be:9c:a4:04:c7:49:3c:9e:e8:29:7a:89:d7:fe:af:ff:68:f5: + a5:17:90:bd:ac:99:cc:a5:86:57:09:67:46:db:d6:16:c2:46: + f1:e4:a9:50:f5:8f:d1:92:15:d3:5f:3e:c6:00:49:3a:6e:58: + b2:d1:d1:27:0d:25:c8:32:f8:20:11:cd:7d:32:33:48:94:54: + 4c:dd:dc:79:c4:30:9f:eb:8e:b8:55:b5:d7:88:5c:c5:6a:24: + 3d:b2:d3:05:03:51:c6:07:ef:cc:14:72:74:3d:6e:72:ce:18: + 28:8c:4a:a0:77:e5:09:2b:45:44:47:ac:b7:67:7f:01:8a:05: + 5a:93:be:a1:c1:ff:f8:e7:0e:67:a4:47:49:76:5d:75:90:1a: + f5:26:8f:f0 +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo +YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 +MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy +NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G +A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA +A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 +Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s +QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV +eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 +B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh +z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T +AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i +ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w +TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH +MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD +VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE +VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B +AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM +bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi +ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG +VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c +ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ +AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- + +XRamp Global CA Root +# Issuer: CN=XRamp Global Certification Authority,O=XRamp Security Services Inc,OU=www.xrampsecurity.com,C=US +# Serial Number:50:94:6c:ec:18:ea:d5:9c:4d:d5:97:ef:75:8f:a0:ad +# Subject: CN=XRamp Global Certification Authority,O=XRamp Security Services Inc,OU=www.xrampsecurity.com,C=US +# Not Valid Before: Mon Nov 01 17:14:04 2004 +# Not Valid After : Mon Jan 01 05:37:19 2035 +# Fingerprint (MD5): A1:0B:44:B3:CA:10:D8:00:6E:9D:0F:D8:0F:92:0A:D1 +# Fingerprint (SHA1): B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=A1:0B:44:B3:CA:10:D8:00:6E:9D:0F:D8:0F:92:0A:D1 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 50:94:6c:ec:18:ea:d5:9c:4d:d5:97:ef:75:8f:a0:ad + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, OU=www.xrampsecurity.com, O=XRamp Security Services Inc, CN=XRamp Global Certification Authority + Validity + Not Before: Nov 1 17:14:04 2004 GMT + Not After : Jan 1 05:37:19 2035 GMT + Subject: C=US, OU=www.xrampsecurity.com, O=XRamp Security Services Inc, CN=XRamp Global Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:98:24:1e:bd:15:b4:ba:df:c7:8c:a5:27:b6:38: + 0b:69:f3:b6:4e:a8:2c:2e:21:1d:5c:44:df:21:5d: + 7e:23:74:fe:5e:7e:b4:4a:b7:a6:ad:1f:ae:e0:06: + 16:e2:9b:5b:d9:67:74:6b:5d:80:8f:29:9d:86:1b: + d9:9c:0d:98:6d:76:10:28:58:e4:65:b0:7f:4a:98: + 79:9f:e0:c3:31:7e:80:2b:b5:8c:c0:40:3b:11:86: + d0:cb:a2:86:36:60:a4:d5:30:82:6d:d9:6e:d0:0f: + 12:04:33:97:5f:4f:61:5a:f0:e4:f9:91:ab:e7:1d: + 3b:bc:e8:cf:f4:6b:2d:34:7c:e2:48:61:1c:8e:f3: + 61:44:cc:6f:a0:4a:a9:94:b0:4d:da:e7:a9:34:7a: + 72:38:a8:41:cc:3c:94:11:7d:eb:c8:a6:8c:b7:86: + cb:ca:33:3b:d9:3d:37:8b:fb:7a:3e:86:2c:e7:73: + d7:0a:57:ac:64:9b:19:eb:f4:0f:04:08:8a:ac:03: + 17:19:64:f4:5a:25:22:8d:34:2c:b2:f6:68:1d:12: + 6d:d3:8a:1e:14:da:c4:8f:a6:e2:23:85:d5:7a:0d: + bd:6a:e0:e9:ec:ec:17:bb:42:1b:67:aa:25:ed:45: + 83:21:fc:c1:c9:7c:d5:62:3e:fa:f2:c5:2d:d3:fd: + d4:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + 1.3.6.1.4.1.311.20.2: + ...C.A + X509v3 Key Usage: + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + C6:4F:A2:3D:06:63:84:09:9C:CE:62:E4:04:AC:8D:5C:B5:E9:B6:1B + X509v3 CRL Distribution Points: + + Full Name: + URI:http://crl.xrampsecurity.com/XGCA.crl + + 1.3.6.1.4.1.311.21.1: + ... + Signature Algorithm: sha1WithRSAEncryption + 91:15:39:03:01:1b:67:fb:4a:1c:f9:0a:60:5b:a1:da:4d:97: + 62:f9:24:53:27:d7:82:64:4e:90:2e:c3:49:1b:2b:9a:dc:fc: + a8:78:67:35:f1:1d:f0:11:bd:b7:48:e3:10:f6:0d:df:3f:d2: + c9:b6:aa:55:a4:48:ba:02:db:de:59:2e:15:5b:3b:9d:16:7d: + 47:d7:37:ea:5f:4d:76:12:36:bb:1f:d7:a1:81:04:46:20:a3: + 2c:6d:a9:9e:01:7e:3f:29:ce:00:93:df:fd:c9:92:73:89:89: + 64:9e:e7:2b:e4:1c:91:2c:d2:b9:ce:7d:ce:6f:31:99:d3:e6: + be:d2:1e:90:f0:09:14:79:5c:23:ab:4d:d2:da:21:1f:4d:99: + 79:9d:e1:cf:27:9f:10:9b:1c:88:0d:b0:8a:64:41:31:b8:0e: + 6c:90:24:a4:9b:5c:71:8f:ba:bb:7e:1c:1b:db:6a:80:0f:21: + bc:e9:db:a6:b7:40:f4:b2:8b:a9:b1:e4:ef:9a:1a:d0:3d:69: + 99:ee:a8:28:a3:e1:3c:b3:f0:b2:11:9c:cf:7c:40:e6:dd:e7: + 43:7d:a2:d8:3a:b5:a9:8d:f2:34:99:c4:d4:10:e1:06:fd:09: + 84:10:3b:ee:c4:4c:f4:ec:27:7c:42:c2:74:7c:82:8a:09:c9: + b4:03:25:bc +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +Go Daddy Class 2 CA +# Issuer: OU=Go Daddy Class 2 Certification Authority,O="The Go Daddy Group, Inc.",C=US +# Serial Number: 0 (0x0) +# Subject: OU=Go Daddy Class 2 Certification Authority,O="The Go Daddy Group, Inc.",C=US +# Not Valid Before: Tue Jun 29 17:06:20 2004 +# Not Valid After : Thu Jun 29 17:06:20 2034 +# Fingerprint (MD5): 91:DE:06:25:AB:DA:FD:32:17:0C:BB:25:17:2A:84:67 +# Fingerprint (SHA1): 27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=91:DE:06:25:AB:DA:FD:32:17:0C:BB:25:17:2A:84:67 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority + Validity + Not Before: Jun 29 17:06:20 2004 GMT + Not After : Jun 29 17:06:20 2034 GMT + Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:de:9d:d7:ea:57:18:49:a1:5b:eb:d7:5f:48:86: + ea:be:dd:ff:e4:ef:67:1c:f4:65:68:b3:57:71:a0: + 5e:77:bb:ed:9b:49:e9:70:80:3d:56:18:63:08:6f: + da:f2:cc:d0:3f:7f:02:54:22:54:10:d8:b2:81:d4: + c0:75:3d:4b:7f:c7:77:c3:3e:78:ab:1a:03:b5:20: + 6b:2f:6a:2b:b1:c5:88:7e:c4:bb:1e:b0:c1:d8:45: + 27:6f:aa:37:58:f7:87:26:d7:d8:2d:f6:a9:17:b7: + 1f:72:36:4e:a6:17:3f:65:98:92:db:2a:6e:5d:a2: + fe:88:e0:0b:de:7f:e5:8d:15:e1:eb:cb:3a:d5:e2: + 12:a2:13:2d:d8:8e:af:5f:12:3d:a0:08:05:08:b6: + 5c:a5:65:38:04:45:99:1e:a3:60:60:74:c5:41:a5: + 72:62:1b:62:c5:1f:6f:5f:1a:42:be:02:51:65:a8: + ae:23:18:6a:fc:78:03:a9:4d:7f:80:c3:fa:ab:5a: + fc:a1:40:a4:ca:19:16:fe:b2:c8:ef:5e:73:0d:ee: + 77:bd:9a:f6:79:98:bc:b1:07:67:a2:15:0d:dd:a0: + 58:c6:44:7b:0a:3e:62:28:5f:ba:41:07:53:58:cf: + 11:7e:38:74:c5:f8:ff:b5:69:90:8f:84:74:ea:97: + 1b:af + Exponent: 3 (0x3) + X509v3 extensions: + X509v3 Subject Key Identifier: + D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3 + X509v3 Authority Key Identifier: + keyid:D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3 + DirName:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 32:4b:f3:b2:ca:3e:91:fc:12:c6:a1:07:8c:8e:77:a0:33:06: + 14:5c:90:1e:18:f7:08:a6:3d:0a:19:f9:87:80:11:6e:69:e4: + 96:17:30:ff:34:91:63:72:38:ee:cc:1c:01:a3:1d:94:28:a4: + 31:f6:7a:c4:54:d7:f6:e5:31:58:03:a2:cc:ce:62:db:94:45: + 73:b5:bf:45:c9:24:b5:d5:82:02:ad:23:79:69:8d:b8:b6:4d: + ce:cf:4c:ca:33:23:e8:1c:88:aa:9d:8b:41:6e:16:c9:20:e5: + 89:9e:cd:3b:da:70:f7:7e:99:26:20:14:54:25:ab:6e:73:85: + e6:9b:21:9d:0a:6c:82:0e:a8:f8:c2:0c:fa:10:1e:6c:96:ef: + 87:0d:c4:0f:61:8b:ad:ee:83:2b:95:f8:8e:92:84:72:39:eb: + 20:ea:83:ed:83:cd:97:6e:08:bc:eb:4e:26:b6:73:2b:e4:d3: + f6:4c:fe:26:71:e2:61:11:74:4a:ff:57:1a:87:0f:75:48:2e: + cf:51:69:17:a0:02:12:61:95:d5:d1:40:b2:10:4c:ee:c4:ac: + 10:43:a6:a5:9e:0a:d5:95:62:9a:0d:cf:88:82:c5:32:0c:e4: + 2b:9f:45:e6:0d:9f:28:9c:b1:b9:2a:5a:57:ad:37:0f:af:1d: + 7f:db:bd:9f +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- + +Starfield Class 2 CA +# Issuer: OU=Starfield Class 2 Certification Authority,O="Starfield Technologies, Inc.",C=US +# Serial Number: 0 (0x0) +# Subject: OU=Starfield Class 2 Certification Authority,O="Starfield Technologies, Inc.",C=US +# Not Valid Before: Tue Jun 29 17:39:16 2004 +# Not Valid After : Thu Jun 29 17:39:16 2034 +# Fingerprint (MD5): 32:4A:4B:BB:C8:63:69:9B:BE:74:9A:C6:DD:1D:46:24 +# Fingerprint (SHA1): AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=32:4A:4B:BB:C8:63:69:9B:BE:74:9A:C6:DD:1D:46:24 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority + Validity + Not Before: Jun 29 17:39:16 2004 GMT + Not After : Jun 29 17:39:16 2034 GMT + Subject: C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b7:32:c8:fe:e9:71:a6:04:85:ad:0c:11:64:df: + ce:4d:ef:c8:03:18:87:3f:a1:ab:fb:3c:a6:9f:f0: + c3:a1:da:d4:d8:6e:2b:53:90:fb:24:a4:3e:84:f0: + 9e:e8:5f:ec:e5:27:44:f5:28:a6:3f:7b:de:e0:2a: + f0:c8:af:53:2f:9e:ca:05:01:93:1e:8f:66:1c:39: + a7:4d:fa:5a:b6:73:04:25:66:eb:77:7f:e7:59:c6: + 4a:99:25:14:54:eb:26:c7:f3:7f:19:d5:30:70:8f: + af:b0:46:2a:ff:ad:eb:29:ed:d7:9f:aa:04:87:a3: + d4:f9:89:a5:34:5f:db:43:91:82:36:d9:66:3c:b1: + b8:b9:82:fd:9c:3a:3e:10:c8:3b:ef:06:65:66:7a: + 9b:19:18:3d:ff:71:51:3c:30:2e:5f:be:3d:77:73: + b2:5d:06:6c:c3:23:56:9a:2b:85:26:92:1c:a7:02: + b3:e4:3f:0d:af:08:79:82:b8:36:3d:ea:9c:d3:35: + b3:bc:69:ca:f5:cc:9d:e8:fd:64:8d:17:80:33:6e: + 5e:4a:5d:99:c9:1e:87:b4:9d:1a:c0:d5:6e:13:35: + 23:5e:df:9b:5f:3d:ef:d6:f7:76:c2:ea:3e:bb:78: + 0d:1c:42:67:6b:04:d8:f8:d6:da:6f:8b:f2:44:a0: + 01:ab + Exponent: 3 (0x3) + X509v3 extensions: + X509v3 Subject Key Identifier: + BF:5F:B7:D1:CE:DD:1F:86:F4:5B:55:AC:DC:D7:10:C2:0E:A9:88:E7 + X509v3 Authority Key Identifier: + keyid:BF:5F:B7:D1:CE:DD:1F:86:F4:5B:55:AC:DC:D7:10:C2:0E:A9:88:E7 + DirName:/C=US/O=Starfield Technologies, Inc./OU=Starfield Class 2 Certification Authority + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 05:9d:3f:88:9d:d1:c9:1a:55:a1:ac:69:f3:f3:59:da:9b:01: + 87:1a:4f:57:a9:a1:79:09:2a:db:f7:2f:b2:1e:cc:c7:5e:6a: + d8:83:87:a1:97:ef:49:35:3e:77:06:41:58:62:bf:8e:58:b8: + 0a:67:3f:ec:b3:dd:21:66:1f:c9:54:fa:72:cc:3d:4c:40:d8: + 81:af:77:9e:83:7a:bb:a2:c7:f5:34:17:8e:d9:11:40:f4:fc: + 2c:2a:4d:15:7f:a7:62:5d:2e:25:d3:00:0b:20:1a:1d:68:f9: + 17:b8:f4:bd:8b:ed:28:59:dd:4d:16:8b:17:83:c8:b2:65:c7: + 2d:7a:a5:aa:bc:53:86:6d:dd:57:a4:ca:f8:20:41:0b:68:f0: + f4:fb:74:be:56:5d:7a:79:f5:f9:1d:85:e3:2d:95:be:f5:71: + 90:43:cc:8d:1f:9a:00:0a:87:29:e9:55:22:58:00:23:ea:e3: + 12:43:29:5b:47:08:dd:8c:41:6a:65:06:a8:e5:21:aa:41:b4: + 95:21:95:b9:7d:d1:34:ab:13:d6:ad:bc:dc:e2:3d:39:cd:bd: + 3e:75:70:a1:18:59:03:c9:22:b4:8f:9c:d5:5e:2a:d7:a5:b6: + d4:0a:6d:f8:b7:40:11:46:9a:1f:79:0e:62:bf:0f:97:ec:e0: + 2f:1f:17:94 +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +Taiwan GRCA +# Issuer: O=Government Root Certification Authority,C=TW +# Serial Number:1f:9d:59:5a:d7:2f:c2:06:44:a5:80:08:69:e3:5e:f6 +# Subject: O=Government Root Certification Authority,C=TW +# Not Valid Before: Thu Dec 05 13:23:33 2002 +# Not Valid After : Sun Dec 05 13:23:33 2032 +# Fingerprint (MD5): 37:85:44:53:32:45:1F:20:F0:F3:95:E1:25:C4:43:4E +# Fingerprint (SHA1): F4:8B:11:BF:DE:AB:BE:94:54:20:71:E6:41:DE:6B:BE:88:2B:40:B9 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=37:85:44:53:32:45:1F:20:F0:F3:95:E1:25:C4:43:4E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 1f:9d:59:5a:d7:2f:c2:06:44:a5:80:08:69:e3:5e:f6 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=TW, O=Government Root Certification Authority + Validity + Not Before: Dec 5 13:23:33 2002 GMT + Not After : Dec 5 13:23:33 2032 GMT + Subject: C=TW, O=Government Root Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:9a:25:b8:ec:cc:a2:75:a8:7b:f7:ce:5b:59:8a: + c9:d1:86:12:08:54:ec:9c:f2:e7:46:f6:88:f3:7c: + e9:a5:df:4c:47:36:a4:1b:01:1c:7f:1e:57:8a:8d: + c3:c5:d1:21:e3:da:24:3f:48:2b:fb:9f:2e:a1:94: + e7:2c:1c:93:d1:bf:1b:01:87:53:99:ce:a7:f5:0a: + 21:76:77:ff:a9:b7:c6:73:94:4f:46:f7:10:49:37: + fa:a8:59:49:5d:6a:81:07:56:f2:8a:f9:06:d0:f7: + 70:22:4d:b4:b7:41:b9:32:b8:b1:f0:b1:c3:9c:3f: + 70:fd:53:dd:81:aa:d8:63:78:f6:d8:53:6e:a1:ac: + 6a:84:24:72:54:86:c6:d2:b2:ca:1c:0e:79:81:d6: + b5:70:62:08:01:2e:4e:4f:0e:d5:11:af:a9:af:e5: + 9a:bf:dc:cc:87:6d:26:e4:c9:57:a2:fb:96:f9:cc: + e1:3f:53:8c:6c:4c:7e:9b:53:08:0b:6c:17:fb:67: + c8:c2:ad:b1:cd:80:b4:97:dc:76:01:16:15:e9:6a: + d7:a4:e1:78:47:ce:86:d5:fb:31:f3:fa:31:be:34: + aa:28:fb:70:4c:1d:49:c7:af:2c:9d:6d:66:a6:b6: + 8d:64:7e:b5:20:6a:9d:3b:81:b6:8f:40:00:67:4b: + 89:86:b8:cc:65:fe:15:53:e9:04:c1:d6:5f:1d:44: + d7:0a:2f:27:9a:46:7d:a1:0d:75:ad:54:86:15:dc: + 49:3b:f1:96:ce:0f:9b:a0:ec:a3:7a:5d:be:d5:2a: + 75:42:e5:7b:de:a5:b6:aa:af:28:ac:ac:90:ac:38: + b7:d5:68:35:26:7a:dc:f7:3b:f3:fd:45:9b:d1:bb: + 43:78:6e:6f:f1:42:54:6a:98:f0:0d:ad:97:e9:52: + 5e:e9:d5:6a:72:de:6a:f7:1b:60:14:f4:a5:e4:b6: + 71:67:aa:1f:ea:e2:4d:c1:42:40:fe:67:46:17:38: + 2f:47:3f:71:9c:ae:e5:21:ca:61:2d:6d:07:a8:84: + 7c:2d:ee:51:25:f1:63:90:9e:fd:e1:57:88:6b:ef: + 8a:23:6d:b1:e6:bd:3f:ad:d1:3d:96:0b:85:8d:cd: + 6b:27:bb:b7:05:9b:ec:bb:91:a9:0a:07:12:02:97: + 4e:20:90:f0:ff:0d:1e:e2:41:3b:d3:40:3a:e7:8d: + 5d:da:66:e4:02:b0:07:52:98:5c:0e:8e:33:9c:c2: + a6:95:fb:55:19:6e:4c:8e:ae:4b:0f:bd:c1:38:4d: + 5e:8f:84:1d:66:cd:c5:60:96:b4:52:5a:05:89:8e: + 95:7a:98:c1:91:3c:95:23:b2:0e:f4:79:b4:c9:7c: + c1:4a:21 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + CC:CC:EF:CC:29:60:A4:3B:B1:92:B6:3C:FA:32:62:8F:AC:25:15:3B + X509v3 Basic Constraints: + CA:TRUE + setCext-hashedRoot: + 0/0-...0...+......0...g*........"...(6....2.1:.Qe + Signature Algorithm: sha1WithRSAEncryption + 40:80:4a:fa:26:c9:ce:5e:30:dd:4f:86:74:76:58:f5:ae:b3: + 83:33:78:a4:7a:74:17:19:4e:e9:52:b5:b9:e0:0a:74:62:aa: + 68:ca:78:a0:4c:9a:8e:2c:23:2e:d5:6a:12:24:bf:d4:68:d3: + 8a:d0:d8:9c:9f:b4:1f:0c:de:38:7e:57:38:fc:8d:e2:4f:5e: + 0c:9f:ab:3b:d2:ff:75:97:cb:a4:e3:67:08:ff:e5:c0:16:b5: + 48:01:7d:e9:f9:0a:ff:1b:e5:6a:69:bf:78:21:a8:c2:a7:23: + a9:86:ab:76:56:e8:0e:0c:f6:13:dd:2a:66:8a:64:49:3d:1a: + 18:87:90:04:9f:42:52:b7:4f:cb:fe:47:41:76:35:ef:ff:00: + 76:36:45:32:9b:c6:46:85:5d:e2:24:b0:1e:e3:48:96:98:57: + 47:94:55:7a:0f:41:b1:44:24:f3:c1:fe:1a:6b:bf:88:fd:c1: + a6:da:93:60:5e:81:4a:99:20:9c:48:66:19:b5:00:79:54:0f: + b8:2c:2f:4b:bc:a9:5d:5b:60:7f:8c:87:a5:e0:52:63:2a:be: + d8:3b:85:40:15:fe:1e:b6:65:3f:c5:4b:da:7e:b5:7a:35:29: + a3:2e:7a:98:60:22:a3:f4:7d:27:4e:2d:ea:b4:74:3c:e9:0f: + a4:33:0f:10:11:bc:13:01:d6:e5:0e:d3:bf:b5:12:a2:e1:45: + 23:c0:cc:08:6e:61:b7:89:ab:83:e3:24:1e:e6:5d:07:e7:1f: + 20:3e:cf:67:c8:e7:ac:30:6d:27:4b:68:6e:4b:2a:5c:02:08: + 34:db:f8:76:e4:67:a3:26:9c:3f:a2:32:c2:4a:c5:81:18:31: + 10:56:aa:84:ef:2d:0a:ff:b8:1f:77:d2:bf:a5:58:a0:62:e4: + d7:4b:91:75:8d:89:80:98:7e:6d:cb:53:4e:5e:af:f6:b2:97: + 85:97:b9:da:55:06:b9:24:ee:d7:c6:38:1e:63:1b:12:3b:95: + e1:58:ac:f2:df:84:d5:5f:99:2f:0d:55:5b:e6:38:db:2e:3f: + 72:e9:48:85:cb:bb:29:13:8f:1e:38:55:b9:f3:b2:c4:30:99: + 23:4e:5d:f2:48:a1:12:0c:dc:12:90:09:90:54:91:03:3c:47: + e5:d5:c9:65:e0:b7:4b:7d:ec:47:d3:b3:0b:3e:ad:9e:d0:74: + 00:0e:eb:bd:51:ad:c0:de:2c:c0:c3:6a:fe:ef:dc:0b:a7:fa: + 46:df:60:db:9c:a6:59:50:75:23:69:73:93:b2:f9:fc:02:d3: + 47:e6:71:ce:10:02:ee:27:8c:84:ff:ac:45:0d:13:5c:83:32: + e0:25:a5:86:2c:7c:f4:12 +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ +MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow +PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR +IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q +gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy +yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts +F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 +jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx +ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC +VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK +YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH +EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN +Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud +DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE +MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK +UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf +qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK +ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE +JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 +hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 +EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm +nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX +udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz +ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe +LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl +pYYsfPQS +-----END CERTIFICATE----- + +DigiCert Assured ID Root CA +# Issuer: CN=DigiCert Assured ID Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US +# Serial Number:0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39 +# Subject: CN=DigiCert Assured ID Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US +# Not Valid Before: Fri Nov 10 00:00:00 2006 +# Not Valid After : Mon Nov 10 00:00:00 2031 +# Fingerprint (MD5): 87:CE:0B:7B:2A:0E:49:00:E1:58:71:9B:37:A8:93:72 +# Fingerprint (SHA1): 05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=87:CE:0B:7B:2A:0E:49:00:E1:58:71:9B:37:A8:93:72 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA + Validity + Not Before: Nov 10 00:00:00 2006 GMT + Not After : Nov 10 00:00:00 2031 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ad:0e:15:ce:e4:43:80:5c:b1:87:f3:b7:60:f9: + 71:12:a5:ae:dc:26:94:88:aa:f4:ce:f5:20:39:28: + 58:60:0c:f8:80:da:a9:15:95:32:61:3c:b5:b1:28: + 84:8a:8a:dc:9f:0a:0c:83:17:7a:8f:90:ac:8a:e7: + 79:53:5c:31:84:2a:f6:0f:98:32:36:76:cc:de:dd: + 3c:a8:a2:ef:6a:fb:21:f2:52:61:df:9f:20:d7:1f: + e2:b1:d9:fe:18:64:d2:12:5b:5f:f9:58:18:35:bc: + 47:cd:a1:36:f9:6b:7f:d4:b0:38:3e:c1:1b:c3:8c: + 33:d9:d8:2f:18:fe:28:0f:b3:a7:83:d6:c3:6e:44: + c0:61:35:96:16:fe:59:9c:8b:76:6d:d7:f1:a2:4b: + 0d:2b:ff:0b:72:da:9e:60:d0:8e:90:35:c6:78:55: + 87:20:a1:cf:e5:6d:0a:c8:49:7c:31:98:33:6c:22: + e9:87:d0:32:5a:a2:ba:13:82:11:ed:39:17:9d:99: + 3a:72:a1:e6:fa:a4:d9:d5:17:31:75:ae:85:7d:22: + ae:3f:01:46:86:f6:28:79:c8:b1:da:e4:57:17:c4: + 7e:1c:0e:b0:b4:92:a6:56:b3:bd:b2:97:ed:aa:a7: + f0:b7:c5:a8:3f:95:16:d0:ff:a1:96:eb:08:5f:18: + 77:4f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 45:EB:A2:AF:F4:92:CB:82:31:2D:51:8B:A7:A7:21:9D:F3:6D:C8:0F + X509v3 Authority Key Identifier: + keyid:45:EB:A2:AF:F4:92:CB:82:31:2D:51:8B:A7:A7:21:9D:F3:6D:C8:0F + + Signature Algorithm: sha1WithRSAEncryption + a2:0e:bc:df:e2:ed:f0:e3:72:73:7a:64:94:bf:f7:72:66:d8: + 32:e4:42:75:62:ae:87:eb:f2:d5:d9:de:56:b3:9f:cc:ce:14: + 28:b9:0d:97:60:5c:12:4c:58:e4:d3:3d:83:49:45:58:97:35: + 69:1a:a8:47:ea:56:c6:79:ab:12:d8:67:81:84:df:7f:09:3c: + 94:e6:b8:26:2c:20:bd:3d:b3:28:89:f7:5f:ff:22:e2:97:84: + 1f:e9:65:ef:87:e0:df:c1:67:49:b3:5d:eb:b2:09:2a:eb:26: + ed:78:be:7d:3f:2b:f3:b7:26:35:6d:5f:89:01:b6:49:5b:9f: + 01:05:9b:ab:3d:25:c1:cc:b6:7f:c2:f1:6f:86:c6:fa:64:68: + eb:81:2d:94:eb:42:b7:fa:8c:1e:dd:62:f1:be:50:67:b7:6c: + bd:f3:f1:1f:6b:0c:36:07:16:7f:37:7c:a9:5b:6d:7a:f1:12: + 46:60:83:d7:27:04:be:4b:ce:97:be:c3:67:2a:68:11:df:80: + e7:0c:33:66:bf:13:0d:14:6e:f3:7f:1f:63:10:1e:fa:8d:1b: + 25:6d:6c:8f:a5:b7:61:01:b1:d2:a3:26:a1:10:71:9d:ad:e2: + c3:f9:c3:99:51:b7:2b:07:08:ce:2e:e6:50:b2:a7:fa:0a:45: + 2f:a2:f0:f2 +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +DigiCert Global Root CA +# Issuer: CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US +# Serial Number:08:3b:e0:56:90:42:46:b1:a1:75:6a:c9:59:91:c7:4a +# Subject: CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US +# Not Valid Before: Fri Nov 10 00:00:00 2006 +# Not Valid After : Mon Nov 10 00:00:00 2031 +# Fingerprint (MD5): 79:E4:A9:84:0D:7D:3A:96:D7:C0:4F:E2:43:4C:89:2E +# Fingerprint (SHA1): A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=79:E4:A9:84:0D:7D:3A:96:D7:C0:4F:E2:43:4C:89:2E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 08:3b:e0:56:90:42:46:b1:a1:75:6a:c9:59:91:c7:4a + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA + Validity + Not Before: Nov 10 00:00:00 2006 GMT + Not After : Nov 10 00:00:00 2031 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:e2:3b:e1:11:72:de:a8:a4:d3:a3:57:aa:50:a2: + 8f:0b:77:90:c9:a2:a5:ee:12:ce:96:5b:01:09:20: + cc:01:93:a7:4e:30:b7:53:f7:43:c4:69:00:57:9d: + e2:8d:22:dd:87:06:40:00:81:09:ce:ce:1b:83:bf: + df:cd:3b:71:46:e2:d6:66:c7:05:b3:76:27:16:8f: + 7b:9e:1e:95:7d:ee:b7:48:a3:08:da:d6:af:7a:0c: + 39:06:65:7f:4a:5d:1f:bc:17:f8:ab:be:ee:28:d7: + 74:7f:7a:78:99:59:85:68:6e:5c:23:32:4b:bf:4e: + c0:e8:5a:6d:e3:70:bf:77:10:bf:fc:01:f6:85:d9: + a8:44:10:58:32:a9:75:18:d5:d1:a2:be:47:e2:27: + 6a:f4:9a:33:f8:49:08:60:8b:d4:5f:b4:3a:84:bf: + a1:aa:4a:4c:7d:3e:cf:4f:5f:6c:76:5e:a0:4b:37: + 91:9e:dc:22:e6:6d:ce:14:1a:8e:6a:cb:fe:cd:b3: + 14:64:17:c7:5b:29:9e:32:bf:f2:ee:fa:d3:0b:42: + d4:ab:b7:41:32:da:0c:d4:ef:f8:81:d5:bb:8d:58: + 3f:b5:1b:e8:49:28:a2:70:da:31:04:dd:f7:b2:16: + f2:4c:0a:4e:07:a8:ed:4a:3d:5e:b5:7f:a3:90:c3: + af:27 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 03:DE:50:35:56:D1:4C:BB:66:F0:A3:E2:1B:1B:C3:97:B2:3D:D1:55 + X509v3 Authority Key Identifier: + keyid:03:DE:50:35:56:D1:4C:BB:66:F0:A3:E2:1B:1B:C3:97:B2:3D:D1:55 + + Signature Algorithm: sha1WithRSAEncryption + cb:9c:37:aa:48:13:12:0a:fa:dd:44:9c:4f:52:b0:f4:df:ae: + 04:f5:79:79:08:a3:24:18:fc:4b:2b:84:c0:2d:b9:d5:c7:fe: + f4:c1:1f:58:cb:b8:6d:9c:7a:74:e7:98:29:ab:11:b5:e3:70: + a0:a1:cd:4c:88:99:93:8c:91:70:e2:ab:0f:1c:be:93:a9:ff: + 63:d5:e4:07:60:d3:a3:bf:9d:5b:09:f1:d5:8e:e3:53:f4:8e: + 63:fa:3f:a7:db:b4:66:df:62:66:d6:d1:6e:41:8d:f2:2d:b5: + ea:77:4a:9f:9d:58:e2:2b:59:c0:40:23:ed:2d:28:82:45:3e: + 79:54:92:26:98:e0:80:48:a8:37:ef:f0:d6:79:60:16:de:ac: + e8:0e:cd:6e:ac:44:17:38:2f:49:da:e1:45:3e:2a:b9:36:53: + cf:3a:50:06:f7:2e:e8:c4:57:49:6c:61:21:18:d5:04:ad:78: + 3c:2c:3a:80:6b:a7:eb:af:15:14:e9:d8:89:c1:b9:38:6c:e2: + 91:6c:8a:ff:64:b9:77:25:57:30:c0:1b:24:a3:e1:dc:e9:df: + 47:7c:b5:b4:24:08:05:30:ec:2d:bd:0b:bf:45:bf:50:b9:a9: + f3:eb:98:01:12:ad:c8:88:c6:98:34:5f:8d:0a:3c:c6:e9:d5: + 95:95:6d:de +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +DigiCert High Assurance EV Root CA +# Issuer: CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US +# Serial Number:02:ac:5c:26:6a:0b:40:9b:8f:0b:79:f2:ae:46:25:77 +# Subject: CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US +# Not Valid Before: Fri Nov 10 00:00:00 2006 +# Not Valid After : Mon Nov 10 00:00:00 2031 +# Fingerprint (MD5): D4:74:DE:57:5C:39:B2:D3:9C:85:83:C5:C0:65:49:8A +# Fingerprint (SHA1): 5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=D4:74:DE:57:5C:39:B2:D3:9C:85:83:C5:C0:65:49:8A +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 02:ac:5c:26:6a:0b:40:9b:8f:0b:79:f2:ae:46:25:77 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA + Validity + Not Before: Nov 10 00:00:00 2006 GMT + Not After : Nov 10 00:00:00 2031 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c6:cc:e5:73:e6:fb:d4:bb:e5:2d:2d:32:a6:df: + e5:81:3f:c9:cd:25:49:b6:71:2a:c3:d5:94:34:67: + a2:0a:1c:b0:5f:69:a6:40:b1:c4:b7:b2:8f:d0:98: + a4:a9:41:59:3a:d3:dc:94:d6:3c:db:74:38:a4:4a: + cc:4d:25:82:f7:4a:a5:53:12:38:ee:f3:49:6d:71: + 91:7e:63:b6:ab:a6:5f:c3:a4:84:f8:4f:62:51:be: + f8:c5:ec:db:38:92:e3:06:e5:08:91:0c:c4:28:41: + 55:fb:cb:5a:89:15:7e:71:e8:35:bf:4d:72:09:3d: + be:3a:38:50:5b:77:31:1b:8d:b3:c7:24:45:9a:a7: + ac:6d:00:14:5a:04:b7:ba:13:eb:51:0a:98:41:41: + 22:4e:65:61:87:81:41:50:a6:79:5c:89:de:19:4a: + 57:d5:2e:e6:5d:1c:53:2c:7e:98:cd:1a:06:16:a4: + 68:73:d0:34:04:13:5c:a1:71:d3:5a:7c:55:db:5e: + 64:e1:37:87:30:56:04:e5:11:b4:29:80:12:f1:79: + 39:88:a2:02:11:7c:27:66:b7:88:b7:78:f2:ca:0a: + a8:38:ab:0a:64:c2:bf:66:5d:95:84:c1:a1:25:1e: + 87:5d:1a:50:0b:20:12:cc:41:bb:6e:0b:51:38:b8: + 4b:cb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3 + X509v3 Authority Key Identifier: + keyid:B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3 + + Signature Algorithm: sha1WithRSAEncryption + 1c:1a:06:97:dc:d7:9c:9f:3c:88:66:06:08:57:21:db:21:47: + f8:2a:67:aa:bf:18:32:76:40:10:57:c1:8a:f3:7a:d9:11:65: + 8e:35:fa:9e:fc:45:b5:9e:d9:4c:31:4b:b8:91:e8:43:2c:8e: + b3:78:ce:db:e3:53:79:71:d6:e5:21:94:01:da:55:87:9a:24: + 64:f6:8a:66:cc:de:9c:37:cd:a8:34:b1:69:9b:23:c8:9e:78: + 22:2b:70:43:e3:55:47:31:61:19:ef:58:c5:85:2f:4e:30:f6: + a0:31:16:23:c8:e7:e2:65:16:33:cb:bf:1a:1b:a0:3d:f8:ca: + 5e:8b:31:8b:60:08:89:2d:0c:06:5c:52:b7:c4:f9:0a:98:d1: + 15:5f:9f:12:be:7c:36:63:38:bd:44:a4:7f:e4:26:2b:0a:c4: + 97:69:0d:e9:8c:e2:c0:10:57:b8:c8:76:12:91:55:f2:48:69: + d8:bc:2a:02:5b:0f:44:d4:20:31:db:f4:ba:70:26:5d:90:60: + 9e:bc:4b:17:09:2f:b4:cb:1e:43:68:c9:07:27:c1:d2:5c:f7: + ea:21:b9:68:12:9c:3c:9c:bf:9e:fc:80:5c:9b:63:cd:ec:47: + aa:25:27:67:a0:37:f3:00:82:7d:54:d7:a9:f8:e9:2e:13:a3: + 77:e8:1f:4a +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- + +Certplus Class 2 Primary CA +# Issuer: CN=Class 2 Primary CA,O=Certplus,C=FR +# Serial Number:00:85:bd:4b:f3:d8:da:e3:69:f6:94:d7:5f:c3:a5:44:23 +# Subject: CN=Class 2 Primary CA,O=Certplus,C=FR +# Not Valid Before: Wed Jul 07 17:05:00 1999 +# Not Valid After : Sat Jul 06 23:59:59 2019 +# Fingerprint (MD5): 88:2C:8C:52:B8:A2:3C:F3:F7:BB:03:EA:AE:AC:42:0B +# Fingerprint (SHA1): 74:20:74:41:72:9C:DD:92:EC:79:31:D8:23:10:8D:C2:81:92:E2:BB +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=88:2C:8C:52:B8:A2:3C:F3:F7:BB:03:EA:AE:AC:42:0B +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 85:bd:4b:f3:d8:da:e3:69:f6:94:d7:5f:c3:a5:44:23 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=FR, O=Certplus, CN=Class 2 Primary CA + Validity + Not Before: Jul 7 17:05:00 1999 GMT + Not After : Jul 6 23:59:59 2019 GMT + Subject: C=FR, O=Certplus, CN=Class 2 Primary CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:dc:50:96:d0:12:f8:35:d2:08:78:7a:b6:52:70: + fd:6f:ee:cf:b9:11:cb:5d:77:e1:ec:e9:7e:04:8d: + d6:cc:6f:73:43:57:60:ac:33:0a:44:ec:03:5f:1c: + 80:24:91:e5:a8:91:56:12:82:f7:e0:2b:f4:db:ae: + 61:2e:89:10:8d:6b:6c:ba:b3:02:bd:d5:36:c5:48: + 37:23:e2:f0:5a:37:52:33:17:12:e2:d1:60:4d:be: + 2f:41:11:e3:f6:17:25:0c:8b:91:c0:1b:99:7b:99: + 56:0d:af:ee:d2:bc:47:57:e3:79:49:7b:34:89:27: + 24:84:de:b1:ec:e9:58:4e:fe:4e:df:5a:be:41:ad: + ac:08:c5:18:0e:ef:d2:53:ee:6c:d0:9d:12:01:13: + 8d:dc:80:62:f7:95:a9:44:88:4a:71:4e:60:55:9e: + db:23:19:79:56:07:0c:3f:63:0b:5c:b0:e2:be:7e: + 15:fc:94:33:58:41:38:74:c4:e1:8f:8b:df:26:ac: + 1f:b5:8b:3b:b7:43:59:6b:b0:24:a6:6d:90:8b:c4: + 72:ea:5d:33:98:b7:cb:de:5e:7b:ef:94:f1:1b:3e: + ca:c9:21:c1:c5:98:02:aa:a2:f6:5b:77:9b:f5:7e: + 96:55:34:1c:67:69:c0:f1:42:e3:47:ac:fc:28:1c: + 66:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE, pathlen:10 + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + E3:73:2D:DF:CB:0E:28:0C:DE:DD:B3:A4:CA:79:B8:8E:BB:E8:30:89 + Netscape Cert Type: + SSL CA, S/MIME CA + X509v3 CRL Distribution Points: + + Full Name: + URI:http://www.certplus.com/CRL/class2.crl + + Signature Algorithm: sha1WithRSAEncryption + a7:54:cf:88:44:19:cb:df:d4:7f:00:df:56:33:62:b5:f7:51: + 01:90:eb:c3:3f:d1:88:44:e9:24:5d:ef:e7:14:bd:20:b7:9a: + 3c:00:fe:6d:9f:db:90:dc:d7:f4:62:d6:8b:70:5d:e7:e5:04: + 48:a9:68:7c:c9:f1:42:f3:6c:7f:c5:7a:7c:1d:51:88:ba:d2: + 0a:3e:27:5d:de:2d:51:4e:d3:13:64:69:e4:2e:e3:d3:e7:9b: + 09:99:a6:e0:95:9b:ce:1a:d7:7f:be:3c:ce:52:b3:11:15:c1: + 0f:17:cd:03:bb:9c:25:15:ba:a2:76:89:fc:06:f1:18:d0:93: + 4b:0e:7c:82:b7:a5:f4:f6:5f:fe:ed:40:a6:9d:84:74:39:b9: + dc:1e:85:16:da:29:1b:86:23:00:c9:bb:89:7e:6e:80:88:1e: + 2f:14:b4:03:24:a8:32:6f:03:9a:47:2c:30:be:56:c6:a7:42: + 02:70:1b:ea:40:d8:ba:05:03:70:07:a4:96:ff:fd:48:33:0a: + e1:dc:a5:81:90:9b:4d:dd:7d:e7:e7:b2:cd:5c:c8:6a:95:f8: + a5:f6:8d:c4:5d:78:08:be:7b:06:d6:49:cf:19:36:50:23:2e: + 08:e6:9e:05:4d:47:18:d5:16:e9:b1:d6:b6:10:d5:bb:97:bf: + a2:8e:b4:54 +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw +PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz +cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 +MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz +IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ +ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR +VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL +kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd +EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas +H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 +HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud +DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 +QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu +Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ +AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 +yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR +FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA +ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB +kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 +l7+ijrRU +-----END CERTIFICATE----- + +DST Root CA X3 +# Issuer: CN=DST Root CA X3,O=Digital Signature Trust Co. +# Serial Number:44:af:b0:80:d6:a3:27:ba:89:30:39:86:2e:f8:40:6b +# Subject: CN=DST Root CA X3,O=Digital Signature Trust Co. +# Not Valid Before: Sat Sep 30 21:12:19 2000 +# Not Valid After : Thu Sep 30 14:01:15 2021 +# Fingerprint (MD5): 41:03:52:DC:0F:F7:50:1B:16:F0:02:8E:BA:6F:45:C5 +# Fingerprint (SHA1): DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=41:03:52:DC:0F:F7:50:1B:16:F0:02:8E:BA:6F:45:C5 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 44:af:b0:80:d6:a3:27:ba:89:30:39:86:2e:f8:40:6b + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=Digital Signature Trust Co., CN=DST Root CA X3 + Validity + Not Before: Sep 30 21:12:19 2000 GMT + Not After : Sep 30 14:01:15 2021 GMT + Subject: O=Digital Signature Trust Co., CN=DST Root CA X3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:df:af:e9:97:50:08:83:57:b4:cc:62:65:f6:90: + 82:ec:c7:d3:2c:6b:30:ca:5b:ec:d9:c3:7d:c7:40: + c1:18:14:8b:e0:e8:33:76:49:2a:e3:3f:21:49:93: + ac:4e:0e:af:3e:48:cb:65:ee:fc:d3:21:0f:65:d2: + 2a:d9:32:8f:8c:e5:f7:77:b0:12:7b:b5:95:c0:89: + a3:a9:ba:ed:73:2e:7a:0c:06:32:83:a2:7e:8a:14: + 30:cd:11:a0:e1:2a:38:b9:79:0a:31:fd:50:bd:80: + 65:df:b7:51:63:83:c8:e2:88:61:ea:4b:61:81:ec: + 52:6b:b9:a2:e2:4b:1a:28:9f:48:a3:9e:0c:da:09: + 8e:3e:17:2e:1e:dd:20:df:5b:c6:2a:8a:ab:2e:bd: + 70:ad:c5:0b:1a:25:90:74:72:c5:7b:6a:ab:34:d6: + 30:89:ff:e5:68:13:7b:54:0b:c8:d6:ae:ec:5a:9c: + 92:1e:3d:64:b3:8c:c6:df:bf:c9:41:70:ec:16:72: + d5:26:ec:38:55:39:43:d0:fc:fd:18:5c:40:f1:97: + eb:d5:9a:9b:8d:1d:ba:da:25:b9:c6:d8:df:c1:15: + 02:3a:ab:da:6e:f1:3e:2e:f5:5c:08:9c:3c:d6:83: + 69:e4:10:9b:19:2a:b6:29:57:e3:e5:3d:9b:9f:f0: + 02:5d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + C4:A7:B1:A4:7B:2C:71:FA:DB:E1:4B:90:75:FF:C4:15:60:85:89:10 + Signature Algorithm: sha1WithRSAEncryption + a3:1a:2c:9b:17:00:5c:a9:1e:ee:28:66:37:3a:bf:83:c7:3f: + 4b:c3:09:a0:95:20:5d:e3:d9:59:44:d2:3e:0d:3e:bd:8a:4b: + a0:74:1f:ce:10:82:9c:74:1a:1d:7e:98:1a:dd:cb:13:4b:b3: + 20:44:e4:91:e9:cc:fc:7d:a5:db:6a:e5:fe:e6:fd:e0:4e:dd: + b7:00:3a:b5:70:49:af:f2:e5:eb:02:f1:d1:02:8b:19:cb:94: + 3a:5e:48:c4:18:1e:58:19:5f:1e:02:5a:f0:0c:f1:b1:ad:a9: + dc:59:86:8b:6e:e9:91:f5:86:ca:fa:b9:66:33:aa:59:5b:ce: + e2:a7:16:73:47:cb:2b:cc:99:b0:37:48:cf:e3:56:4b:f5:cf: + 0f:0c:72:32:87:c6:f0:44:bb:53:72:6d:43:f5:26:48:9a:52: + 67:b7:58:ab:fe:67:76:71:78:db:0d:a2:56:14:13:39:24:31: + 85:a2:a8:02:5a:30:47:e1:dd:50:07:bc:02:09:90:00:eb:64: + 63:60:9b:16:bc:88:c9:12:e6:d2:7d:91:8b:f9:3d:32:8d:65: + b4:e9:7c:b1:57:76:ea:c5:b6:28:39:bf:15:65:1c:c8:f6:77: + 96:6a:0a:8d:77:0b:d8:91:0b:04:8e:07:db:29:b6:0a:ee:9d: + 82:35:35:10 +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + +SwissSign Gold CA - G2 +# Issuer: CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH +# Serial Number:00:bb:40:1c:43:f5:5e:4f:b0 +# Subject: CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH +# Not Valid Before: Wed Oct 25 08:30:35 2006 +# Not Valid After : Sat Oct 25 08:30:35 2036 +# Fingerprint (MD5): 24:77:D9:A8:91:D1:3B:FA:88:2D:C2:FF:F8:CD:33:93 +# Fingerprint (SHA1): D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=24:77:D9:A8:91:D1:3B:FA:88:2D:C2:FF:F8:CD:33:93 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + bb:40:1c:43:f5:5e:4f:b0 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=CH, O=SwissSign AG, CN=SwissSign Gold CA - G2 + Validity + Not Before: Oct 25 08:30:35 2006 GMT + Not After : Oct 25 08:30:35 2036 GMT + Subject: C=CH, O=SwissSign AG, CN=SwissSign Gold CA - G2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:af:e4:ee:7e:8b:24:0e:12:6e:a9:50:2d:16:44: + 3b:92:92:5c:ca:b8:5d:84:92:42:13:2a:bc:65:57: + 82:40:3e:57:24:cd:50:8b:25:2a:b7:6f:fc:ef:a2: + d0:c0:1f:02:24:4a:13:96:8f:23:13:e6:28:58:00: + a3:47:c7:06:a7:84:23:2b:bb:bd:96:2b:7f:55:cc: + 8b:c1:57:1f:0e:62:65:0f:dd:3d:56:8a:73:da:ae: + 7e:6d:ba:81:1c:7e:42:8c:20:35:d9:43:4d:84:fa: + 84:db:52:2c:f3:0e:27:77:0b:6b:bf:11:2f:72:78: + 9f:2e:d8:3e:e6:18:37:5a:2a:72:f9:da:62:90:92: + 95:ca:1f:9c:e9:b3:3c:2b:cb:f3:01:13:bf:5a:cf: + c1:b5:0a:60:bd:dd:b5:99:64:53:b8:a0:96:b3:6f: + e2:26:77:91:8c:e0:62:10:02:9f:34:0f:a4:d5:92: + 33:51:de:be:8d:ba:84:7a:60:3c:6a:db:9f:2b:ec: + de:de:01:3f:6e:4d:e5:50:86:cb:b4:af:ed:44:40: + c5:ca:5a:8c:da:d2:2b:7c:a8:ee:be:a6:e5:0a:aa: + 0e:a5:df:05:52:b7:55:c7:22:5d:32:6a:97:97:63: + 13:db:c9:db:79:36:7b:85:3a:4a:c5:52:89:f9:24: + e7:9d:77:a9:82:ff:55:1c:a5:71:69:2b:d1:02:24: + f2:b3:26:d4:6b:da:04:55:e5:c1:0a:c7:6d:30:37: + 90:2a:e4:9e:14:33:5e:16:17:55:c5:5b:b5:cb:34: + 89:92:f1:9d:26:8f:a1:07:d4:c6:b2:78:50:db:0c: + 0c:0b:7c:0b:8c:41:d7:b9:e9:dd:8c:88:f7:a3:4d: + b2:32:cc:d8:17:da:cd:b7:ce:66:9d:d4:fd:5e:ff: + bd:97:3e:29:75:e7:7e:a7:62:58:af:25:34:a5:41: + c7:3d:bc:0d:50:ca:03:03:0f:08:5a:1f:95:73:78: + 62:bf:af:72:14:69:0e:a5:e5:03:0e:78:8e:26:28: + 42:f0:07:0b:62:20:10:67:39:46:fa:a9:03:cc:04: + 38:7a:66:ef:20:83:b5:8c:4a:56:8e:91:00:fc:8e: + 5c:82:de:88:a0:c3:e2:68:6e:7d:8d:ef:3c:dd:65: + f4:5d:ac:51:ef:24:80:ae:aa:56:97:6f:f9:ad:7d: + da:61:3f:98:77:3c:a5:91:b6:1c:8c:26:da:65:a2: + 09:6d:c1:e2:54:e3:b9:ca:4c:4c:80:8f:77:7b:60: + 9a:1e:df:b6:f2:48:1e:0e:ba:4e:54:6d:98:e0:e1: + a2:1a:a2:77:50:cf:c4:63:92:ec:47:19:9d:eb:e6: + 6b:ce:c1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 5B:25:7B:96:A4:65:51:7E:B8:39:F3:C0:78:66:5E:E8:3A:E7:F0:EE + X509v3 Authority Key Identifier: + keyid:5B:25:7B:96:A4:65:51:7E:B8:39:F3:C0:78:66:5E:E8:3A:E7:F0:EE + + X509v3 Certificate Policies: + Policy: 2.16.756.1.89.1.2.1.1 + CPS: http://repository.swisssign.com/ + + Signature Algorithm: sha1WithRSAEncryption + 27:ba:e3:94:7c:f1:ae:c0:de:17:e6:e5:d8:d5:f5:54:b0:83: + f4:bb:cd:5e:05:7b:4f:9f:75:66:af:3c:e8:56:7e:fc:72:78: + 38:03:d9:2b:62:1b:00:b9:f8:e9:60:cd:cc:ce:51:8a:c7:50: + 31:6e:e1:4a:7e:18:2f:69:59:b6:3d:64:81:2b:e3:83:84:e6: + 22:87:8e:7d:e0:ee:02:99:61:b8:1e:f4:b8:2b:88:12:16:84: + c2:31:93:38:96:31:a6:b9:3b:53:3f:c3:24:93:56:5b:69:92: + ec:c5:c1:bb:38:00:e3:ec:17:a9:b8:dc:c7:7c:01:83:9f:32: + 47:ba:52:22:34:1d:32:7a:09:56:a7:7c:25:36:a9:3d:4b:da: + c0:82:6f:0a:bb:12:c8:87:4b:27:11:f9:1e:2d:c7:93:3f:9e: + db:5f:26:6b:52:d9:2e:8a:f1:14:c6:44:8d:15:a9:b7:bf:bd: + de:a6:1a:ee:ae:2d:fb:48:77:17:fe:bb:ec:af:18:f5:2a:51: + f0:39:84:97:95:6c:6e:1b:c3:2b:c4:74:60:79:25:b0:0a:27: + df:df:5e:d2:39:cf:45:7d:42:4b:df:b3:2c:1e:c5:c6:5d:ca: + 55:3a:a0:9c:69:9a:8f:da:ef:b2:b0:3c:9f:87:6c:12:2b:65: + 70:15:52:31:1a:24:cf:6f:31:23:50:1f:8c:4f:8f:23:c3:74: + 41:63:1c:55:a8:14:dd:3e:e0:51:50:cf:f1:1b:30:56:0e:92: + b0:82:85:d8:83:cb:22:64:bc:2d:b8:25:d5:54:a2:b8:06:ea: + ad:92:a4:24:a0:c1:86:b5:4a:13:6a:47:cf:2e:0b:56:95:54: + cb:ce:9a:db:6a:b4:a6:b2:db:41:08:86:27:77:f7:6a:a0:42: + 6c:0b:38:ce:d7:75:50:32:92:c2:df:2b:30:22:48:d0:d5:41: + 38:25:5d:a4:e9:5d:9f:c6:94:75:d0:45:fd:30:97:43:8f:90: + ab:0a:c7:86:73:60:4a:69:2d:de:a5:78:d7:06:da:6a:9e:4b: + 3e:77:3a:20:13:22:01:d0:bf:68:9e:63:60:6b:35:4d:0b:6d: + ba:a1:3d:c0:93:e0:7f:23:b3:55:ad:72:25:4e:46:f9:d2:16: + ef:b0:64:c1:01:9e:e9:ca:a0:6a:98:0e:cf:d8:60:f2:2f:49: + b8:e4:42:e1:38:35:16:f4:c8:6e:4f:f7:81:56:e8:ba:a3:be: + 23:af:ae:fd:6f:03:e0:02:3b:30:76:fa:1b:6d:41:cf:01:b1: + e9:b8:c9:66:f4:db:26:f3:3a:a4:74:f2:49:24:5b:c9:b0:d0: + 57:c1:fa:3e:7a:e1:97:c9 +-----BEGIN CERTIFICATE----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln +biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF +MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT +d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 +76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ +bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c +6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE +emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd +MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt +MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y +MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y +FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi +aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM +gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB +qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 +lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn +8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 +45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO +UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 +O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC +bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv +GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a +77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC +hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 +92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp +Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w +ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt +Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +# Issuer: CN=SwissSign Silver CA - G2,O=SwissSign AG,C=CH +# Serial Number:4f:1b:d4:2f:54:bb:2f:4b +# Subject: CN=SwissSign Silver CA - G2,O=SwissSign AG,C=CH +# Not Valid Before: Wed Oct 25 08:32:46 2006 +# Not Valid After : Sat Oct 25 08:32:46 2036 +# Fingerprint (MD5): E0:06:A1:C9:7D:CF:C9:FC:0D:C0:56:75:96:D8:62:13 +# Fingerprint (SHA1): 9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=E0:06:A1:C9:7D:CF:C9:FC:0D:C0:56:75:96:D8:62:13 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 5700383053117599563 (0x4f1bd42f54bb2f4b) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=CH, O=SwissSign AG, CN=SwissSign Silver CA - G2 + Validity + Not Before: Oct 25 08:32:46 2006 GMT + Not After : Oct 25 08:32:46 2036 GMT + Subject: C=CH, O=SwissSign AG, CN=SwissSign Silver CA - G2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:c4:f1:87:7f:d3:78:31:f7:38:c9:f8:c3:99:43: + bc:c7:f7:bc:37:e7:4e:71:ba:4b:8f:a5:73:1d:5c: + 6e:98:ae:03:57:ae:38:37:43:2f:17:3d:1f:c8:ce: + 68:10:c1:78:ae:19:03:2b:10:fa:2c:79:83:f6:e8: + b9:68:b9:55:f2:04:44:a7:39:f9:fc:04:8b:1e:f1: + a2:4d:27:f9:61:7b:ba:b7:e5:a2:13:b6:eb:61:3e: + d0:6c:d1:e6:fb:fa:5e:ed:1d:b4:9e:a0:35:5b:a1: + 92:cb:f0:49:92:fe:85:0a:05:3e:e6:d9:0b:e2:4f: + bb:dc:95:37:fc:91:e9:32:35:22:d1:1f:3a:4e:27: + 85:9d:b0:15:94:32:da:61:0d:47:4d:60:42:ae:92: + 47:e8:83:5a:50:58:e9:8a:8b:b9:5d:a1:dc:dd:99: + 4a:1f:36:67:bb:48:e4:83:b6:37:eb:48:3a:af:0f: + 67:8f:17:07:e8:04:ca:ef:6a:31:87:d4:c0:b6:f9: + 94:71:7b:67:64:b8:b6:91:4a:42:7b:65:2e:30:6a: + 0c:f5:90:ee:95:e6:f2:cd:82:ec:d9:a1:4a:ec:f6: + b2:4b:e5:45:85:e6:6d:78:93:04:2e:9c:82:6d:36: + a9:c4:31:64:1f:86:83:0b:2a:f4:35:0a:78:c9:55: + cf:41:b0:47:e9:30:9f:99:be:61:a8:06:84:b9:28: + 7a:5f:38:d9:1b:a9:38:b0:83:7f:73:c1:c3:3b:48: + 2a:82:0f:21:9b:b8:cc:a8:35:c3:84:1b:83:b3:3e: + be:a4:95:69:01:3a:89:00:78:04:d9:c9:f4:99:19: + ab:56:7e:5b:8b:86:39:15:91:a4:10:2c:09:32:80: + 60:b3:93:c0:2a:b6:18:0b:9d:7e:8d:49:f2:10:4a: + 7f:f9:d5:46:2f:19:92:a3:99:a7:26:ac:bb:8c:3c: + e6:0e:bc:47:07:dc:73:51:f1:70:64:2f:08:f9:b4: + 47:1d:30:6c:44:ea:29:37:85:92:68:66:bc:83:38: + fe:7b:39:2e:d3:50:f0:1f:fb:5e:60:b6:a9:a6:fa: + 27:41:f1:9b:18:72:f2:f5:84:74:4a:c9:67:c4:54: + ae:48:64:df:8c:d1:6e:b0:1d:e1:07:8f:08:1e:99: + 9c:71:e9:4c:d8:a5:f7:47:12:1f:74:d1:51:9e:86: + f3:c2:a2:23:40:0b:73:db:4b:a6:e7:73:06:8c:c1: + a0:e9:c1:59:ac:46:fa:e6:2f:f8:cf:71:9c:46:6d: + b9:c4:15:8d:38:79:03:45:48:ef:c4:5d:d7:08:ee: + 87:39:22:86:b2:0d:0f:58:43:f7:71:a9:48:2e:fd: + ea:d6:1f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 17:A0:CD:C1:E4:41:B6:3A:5B:3B:CB:45:9D:BD:1C:C2:98:FA:86:58 + X509v3 Authority Key Identifier: + keyid:17:A0:CD:C1:E4:41:B6:3A:5B:3B:CB:45:9D:BD:1C:C2:98:FA:86:58 + + X509v3 Certificate Policies: + Policy: 2.16.756.1.89.1.3.1.1 + CPS: http://repository.swisssign.com/ + + Signature Algorithm: sha1WithRSAEncryption + 73:c6:81:e0:27:d2:2d:0f:e0:95:30:e2:9a:41:7f:50:2c:5f: + 5f:62:61:a9:86:6a:69:18:0c:74:49:d6:5d:84:ea:41:52:18: + 6f:58:ad:50:56:20:6a:c6:bd:28:69:58:91:dc:91:11:35:a9: + 3a:1d:bc:1a:a5:60:9e:d8:1f:7f:45:91:69:d9:7e:bb:78:72: + c1:06:0f:2a:ce:8f:85:70:61:ac:a0:cd:0b:b8:39:29:56:84: + 32:4e:86:bb:3d:c4:2a:d9:d7:1f:72:ee:fe:51:a1:22:41:b1: + 71:02:63:1a:82:b0:62:ab:5e:57:12:1f:df:cb:dd:75:a0:c0: + 5d:79:90:8c:1b:e0:50:e6:de:31:fe:98:7b:70:5f:a5:90:d8: + ad:f8:02:b6:6f:d3:60:dd:40:4b:22:c5:3d:ad:3a:7a:9f:1a: + 1a:47:91:79:33:ba:82:dc:32:69:03:96:6e:1f:4b:f0:71:fe: + e3:67:72:a0:b1:bf:5c:8b:e4:fa:99:22:c7:84:b9:1b:8d:23: + 97:3f:ed:25:e0:cf:65:bb:f5:61:04:ef:dd:1e:b2:5a:41:22: + 5a:a1:9f:5d:2c:e8:5b:c9:6d:a9:0c:0c:78:aa:60:c6:56:8f: + 01:5a:0c:68:bc:69:19:79:c4:1f:7e:97:05:bf:c5:e9:24:51: + 5e:d4:d5:4b:53:ed:d9:23:5a:36:03:65:a3:c1:03:ad:41:30: + f3:46:1b:85:90:af:65:b5:d5:b1:e4:16:5b:78:75:1d:97:7a: + 6d:59:a9:2a:8f:7b:de:c3:87:89:10:99:49:73:78:c8:3d:bd: + 51:35:74:2a:d5:f1:7e:69:1b:2a:bb:3b:bd:25:b8:9a:5a:3d: + 72:61:90:66:87:ee:0c:d6:4d:d4:11:74:0b:6a:fe:0b:03:fc: + a3:55:57:89:fe:4a:cb:ae:5b:17:05:c8:f2:8d:23:31:53:38: + d2:2d:6a:3f:82:b9:8d:08:6a:f7:5e:41:74:6e:c3:11:7e:07: + ac:29:60:91:3f:38:ca:57:10:0d:bd:30:2f:c7:a5:e6:41:a0: + da:ae:05:87:9a:a0:a4:65:6c:4c:09:0c:89:ba:b8:d3:b9:c0: + 93:8a:30:fa:8d:e5:9a:6b:15:01:4e:67:aa:da:62:56:3e:84: + 08:66:d2:c4:36:7d:a7:3e:10:fc:88:e0:d4:80:e5:00:bd:aa: + f3:4e:06:a3:7a:6a:f9:62:72:e3:09:4f:eb:9b:0e:01:23:f1: + 9f:bb:7c:dc:dc:6c:11:97:25:b2:f2:b4:63:14:d2:06:2a:67: + 8c:83:f5:ce:ea:07:d8:9a:6a:1e:ec:e4:0a:bb:2a:4c:eb:09: + 60:39:ce:ca:62:d8:2e:6e +-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE +BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu +IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow +RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY +U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv +Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br +YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF +nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH +6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt +eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ +c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ +MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH +HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf +jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 +5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB +rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU +F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c +wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB +AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp +WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 +xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ +2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ +IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 +aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X +em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR +dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ +OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ +hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy +tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority +# Issuer: CN=GeoTrust Primary Certification Authority,O=GeoTrust Inc.,C=US +# Serial Number:18:ac:b5:6a:fd:69:b6:15:3a:63:6c:af:da:fa:c4:a1 +# Subject: CN=GeoTrust Primary Certification Authority,O=GeoTrust Inc.,C=US +# Not Valid Before: Mon Nov 27 00:00:00 2006 +# Not Valid After : Wed Jul 16 23:59:59 2036 +# Fingerprint (MD5): 02:26:C3:01:5E:08:30:37:43:A9:D0:7D:CF:37:E6:BF +# Fingerprint (SHA1): 32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=02:26:C3:01:5E:08:30:37:43:A9:D0:7D:CF:37:E6:BF +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 18:ac:b5:6a:fd:69:b6:15:3a:63:6c:af:da:fa:c4:a1 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Primary Certification Authority + Validity + Not Before: Nov 27 00:00:00 2006 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:be:b8:15:7b:ff:d4:7c:7d:67:ad:83:64:7b:c8: + 42:53:2d:df:f6:84:08:20:61:d6:01:59:6a:9c:44: + 11:af:ef:76:fd:95:7e:ce:61:30:bb:7a:83:5f:02: + bd:01:66:ca:ee:15:8d:6f:a1:30:9c:bd:a1:85:9e: + 94:3a:f3:56:88:00:31:cf:d8:ee:6a:96:02:d9:ed: + 03:8c:fb:75:6d:e7:ea:b8:55:16:05:16:9a:f4:e0: + 5e:b1:88:c0:64:85:5c:15:4d:88:c7:b7:ba:e0:75: + e9:ad:05:3d:9d:c7:89:48:e0:bb:28:c8:03:e1:30: + 93:64:5e:52:c0:59:70:22:35:57:88:8a:f1:95:0a: + 83:d7:bc:31:73:01:34:ed:ef:46:71:e0:6b:02:a8: + 35:72:6b:97:9b:66:e0:cb:1c:79:5f:d8:1a:04:68: + 1e:47:02:e6:9d:60:e2:36:97:01:df:ce:35:92:df: + be:67:c7:6d:77:59:3b:8f:9d:d6:90:15:94:bc:42: + 34:10:c1:39:f9:b1:27:3e:7e:d6:8a:75:c5:b2:af: + 96:d3:a2:de:9b:e4:98:be:7d:e1:e9:81:ad:b6:6f: + fc:d7:0e:da:e0:34:b0:0d:1a:77:e7:e3:08:98:ef: + 58:fa:9c:84:b7:36:af:c2:df:ac:d2:f4:10:06:70: + 71:35 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 2C:D5:50:41:97:15:8B:F0:8F:36:61:5B:4A:FB:6B:D9:99:C9:33:92 + Signature Algorithm: sha1WithRSAEncryption + 5a:70:7f:2c:dd:b7:34:4f:f5:86:51:a9:26:be:4b:b8:aa:f1: + 71:0d:dc:61:c7:a0:ea:34:1e:7a:77:0f:04:35:e8:27:8f:6c: + 90:bf:91:16:24:46:3e:4a:4e:ce:2b:16:d5:0b:52:1d:fc:1f: + 67:a2:02:45:31:4f:ce:f3:fa:03:a7:79:9d:53:6a:d9:da:63: + 3a:f8:80:d7:d3:99:e1:a5:e1:be:d4:55:71:98:35:3a:be:93: + ea:ae:ad:42:b2:90:6f:e0:fc:21:4d:35:63:33:89:49:d6:9b: + 4e:ca:c7:e7:4e:09:00:f7:da:c7:ef:99:62:99:77:b6:95:22: + 5e:8a:a0:ab:f4:b8:78:98:ca:38:19:99:c9:72:9e:78:cd:4b: + ac:af:19:a0:73:12:2d:fc:c2:41:ba:81:91:da:16:5a:31:b7: + f9:b4:71:80:12:48:99:72:73:5a:59:53:c1:63:52:33:ed:a7: + c9:d2:39:02:70:fa:e0:b1:42:66:29:aa:9b:51:ed:30:54:22: + 14:5f:d9:ab:1d:c1:e4:94:f0:f8:f5:2b:f7:ea:ca:78:46:d6: + b8:91:fd:a6:0d:2b:1a:14:01:3e:80:f0:42:a0:95:07:5e:6d: + cd:cc:4b:a4:45:8d:ab:12:e8:b3:de:5a:e5:a0:7c:e8:0f:22: + 1d:5a:e9:59 +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY +MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo +R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx +MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 +AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA +ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 +7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W +kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI +mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ +KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 +6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl +4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K +oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj +UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU +AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +thawte Primary Root CA +# Issuer: CN=thawte Primary Root CA,OU="(c) 2006 thawte, Inc. - For authorized use only",OU=Certification Services Division,O="thawte, Inc.",C=US +# Serial Number:34:4e:d5:57:20:d5:ed:ec:49:f4:2f:ce:37:db:2b:6d +# Subject: CN=thawte Primary Root CA,OU="(c) 2006 thawte, Inc. - For authorized use only",OU=Certification Services Division,O="thawte, Inc.",C=US +# Not Valid Before: Fri Nov 17 00:00:00 2006 +# Not Valid After : Wed Jul 16 23:59:59 2036 +# Fingerprint (MD5): 8C:CA:DC:0B:22:CE:F5:BE:72:AC:41:1A:11:A8:D8:12 +# Fingerprint (SHA1): 91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=8C:CA:DC:0B:22:CE:F5:BE:72:AC:41:1A:11:A8:D8:12 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 34:4e:d5:57:20:d5:ed:ec:49:f4:2f:ce:37:db:2b:6d + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=thawte, Inc., OU=Certification Services Division, OU=(c) 2006 thawte, Inc. - For authorized use only, CN=thawte Primary Root CA + Validity + Not Before: Nov 17 00:00:00 2006 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=thawte, Inc., OU=Certification Services Division, OU=(c) 2006 thawte, Inc. - For authorized use only, CN=thawte Primary Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ac:a0:f0:fb:80:59:d4:9c:c7:a4:cf:9d:a1:59: + 73:09:10:45:0c:0d:2c:6e:68:f1:6c:5b:48:68:49: + 59:37:fc:0b:33:19:c2:77:7f:cc:10:2d:95:34:1c: + e6:eb:4d:09:a7:1c:d2:b8:c9:97:36:02:b7:89:d4: + 24:5f:06:c0:cc:44:94:94:8d:02:62:6f:eb:5a:dd: + 11:8d:28:9a:5c:84:90:10:7a:0d:bd:74:66:2f:6a: + 38:a0:e2:d5:54:44:eb:1d:07:9f:07:ba:6f:ee:e9: + fd:4e:0b:29:f5:3e:84:a0:01:f1:9c:ab:f8:1c:7e: + 89:a4:e8:a1:d8:71:65:0d:a3:51:7b:ee:bc:d2:22: + 60:0d:b9:5b:9d:df:ba:fc:51:5b:0b:af:98:b2:e9: + 2e:e9:04:e8:62:87:de:2b:c8:d7:4e:c1:4c:64:1e: + dd:cf:87:58:ba:4a:4f:ca:68:07:1d:1c:9d:4a:c6: + d5:2f:91:cc:7c:71:72:1c:c5:c0:67:eb:32:fd:c9: + 92:5c:94:da:85:c0:9b:bf:53:7d:2b:09:f4:8c:9d: + 91:1f:97:6a:52:cb:de:09:36:a4:77:d8:7b:87:50: + 44:d5:3e:6e:29:69:fb:39:49:26:1e:09:a5:80:7b: + 40:2d:eb:e8:27:85:c9:fe:61:fd:7e:e6:7c:97:1d: + d5:9d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 7B:5B:45:CF:AF:CE:CB:7A:FD:31:92:1A:6A:B6:F3:46:EB:57:48:50 + Signature Algorithm: sha1WithRSAEncryption + 79:11:c0:4b:b3:91:b6:fc:f0:e9:67:d4:0d:6e:45:be:55:e8: + 93:d2:ce:03:3f:ed:da:25:b0:1d:57:cb:1e:3a:76:a0:4c:ec: + 50:76:e8:64:72:0c:a4:a9:f1:b8:8b:d6:d6:87:84:bb:32:e5: + 41:11:c0:77:d9:b3:60:9d:eb:1b:d5:d1:6e:44:44:a9:a6:01: + ec:55:62:1d:77:b8:5c:8e:48:49:7c:9c:3b:57:11:ac:ad:73: + 37:8e:2f:78:5c:90:68:47:d9:60:60:e6:fc:07:3d:22:20:17: + c4:f7:16:e9:c4:d8:72:f9:c8:73:7c:df:16:2f:15:a9:3e:fd: + 6a:27:b6:a1:eb:5a:ba:98:1f:d5:e3:4d:64:0a:9d:13:c8:61: + ba:f5:39:1c:87:ba:b8:bd:7b:22:7f:f6:fe:ac:40:79:e5:ac: + 10:6f:3d:8f:1b:79:76:8b:c4:37:b3:21:18:84:e5:36:00:eb: + 63:20:99:b9:e9:fe:33:04:bb:41:c8:c1:02:f9:44:63:20:9e: + 81:ce:42:d3:d6:3f:2c:76:d3:63:9c:59:dd:8f:a6:e1:0e:a0: + 2e:41:f7:2e:95:47:cf:bc:fd:33:f3:f6:0b:61:7e:7e:91:2b: + 81:47:c2:27:30:ee:a7:10:5d:37:8f:5c:39:2b:e4:04:f0:7b: + 8d:56:8c:68 +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB +qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV +BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw +NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j +LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG +A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs +W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta +3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk +6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 +Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J +NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP +r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU +DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz +YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 +/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ +LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 +jVaMaA== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G5 +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU="(c) 2006 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US +# Serial Number:18:da:d1:9e:26:7d:e8:bb:4a:21:58:cd:cc:6b:3b:4a +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU="(c) 2006 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US +# Not Valid Before: Wed Nov 08 00:00:00 2006 +# Not Valid After : Wed Jul 16 23:59:59 2036 +# Fingerprint (MD5): CB:17:E4:31:67:3E:E2:09:FE:45:57:93:F3:0A:FA:1C +# Fingerprint (SHA1): 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +============================================================ +MD5 Fingerprint=CB:17:E4:31:67:3E:E2:09:FE:45:57:93:F3:0A:FA:1C +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 18:da:d1:9e:26:7d:e8:bb:4a:21:58:cd:cc:6b:3b:4a + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2006 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G5 + Validity + Not Before: Nov 8 00:00:00 2006 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2006 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:af:24:08:08:29:7a:35:9e:60:0c:aa:e7:4b:3b: + 4e:dc:7c:bc:3c:45:1c:bb:2b:e0:fe:29:02:f9:57: + 08:a3:64:85:15:27:f5:f1:ad:c8:31:89:5d:22:e8: + 2a:aa:a6:42:b3:8f:f8:b9:55:b7:b1:b7:4b:b3:fe: + 8f:7e:07:57:ec:ef:43:db:66:62:15:61:cf:60:0d: + a4:d8:de:f8:e0:c3:62:08:3d:54:13:eb:49:ca:59: + 54:85:26:e5:2b:8f:1b:9f:eb:f5:a1:91:c2:33:49: + d8:43:63:6a:52:4b:d2:8f:e8:70:51:4d:d1:89:69: + 7b:c7:70:f6:b3:dc:12:74:db:7b:5d:4b:56:d3:96: + bf:15:77:a1:b0:f4:a2:25:f2:af:1c:92:67:18:e5: + f4:06:04:ef:90:b9:e4:00:e4:dd:3a:b5:19:ff:02: + ba:f4:3c:ee:e0:8b:eb:37:8b:ec:f4:d7:ac:f2:f6: + f0:3d:af:dd:75:91:33:19:1d:1c:40:cb:74:24:19: + 21:93:d9:14:fe:ac:2a:52:c7:8f:d5:04:49:e4:8d: + 63:47:88:3c:69:83:cb:fe:47:bd:2b:7e:4f:c5:95: + ae:0e:9d:d4:d1:43:c0:67:73:e3:14:08:7e:e5:3f: + 9f:73:b8:33:0a:cf:5d:3f:34:87:96:8a:ee:53:e8: + 25:15 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + 1.3.6.1.5.5.7.1.12: + 0_.].[0Y0W0U..image/gif0!0.0...+..............k...j.H.,{..0%.#http://logo.verisign.com/vslogo.gif + X509v3 Subject Key Identifier: + 7F:D3:65:A7:C2:DD:EC:BB:F0:30:09:F3:43:39:FA:02:AF:33:31:33 + Signature Algorithm: sha1WithRSAEncryption + 93:24:4a:30:5f:62:cf:d8:1a:98:2f:3d:ea:dc:99:2d:bd:77: + f6:a5:79:22:38:ec:c4:a7:a0:78:12:ad:62:0e:45:70:64:c5: + e7:97:66:2d:98:09:7e:5f:af:d6:cc:28:65:f2:01:aa:08:1a: + 47:de:f9:f9:7c:92:5a:08:69:20:0d:d9:3e:6d:6e:3c:0d:6e: + d8:e6:06:91:40:18:b9:f8:c1:ed:df:db:41:aa:e0:96:20:c9: + cd:64:15:38:81:c9:94:ee:a2:84:29:0b:13:6f:8e:db:0c:dd: + 25:02:db:a4:8b:19:44:d2:41:7a:05:69:4a:58:4f:60:ca:7e: + 82:6a:0b:02:aa:25:17:39:b5:db:7f:e7:84:65:2a:95:8a:bd: + 86:de:5e:81:16:83:2d:10:cc:de:fd:a8:82:2a:6d:28:1f:0d: + 0b:c4:e5:e7:1a:26:19:e1:f4:11:6f:10:b5:95:fc:e7:42:05: + 32:db:ce:9d:51:5e:28:b6:9e:85:d3:5b:ef:a5:7d:45:40:72: + 8e:b7:0e:6b:0e:06:fb:33:35:48:71:b8:9d:27:8b:c4:65:5f: + 0d:86:76:9c:44:7a:f6:95:5c:f6:5d:32:08:33:a4:54:b6:18: + 3f:68:5c:f2:42:4a:85:38:54:83:5f:d1:e8:2c:f2:ac:11:d6: + a8:ed:63:6a +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 +nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex +t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz +SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG +BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ +rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ +NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH +BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv +MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE +p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y +5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK +WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ +4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N +hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- + +SecureTrust CA +# Issuer: CN=SecureTrust CA,O=SecureTrust Corporation,C=US +# Serial Number:0c:f0:8e:5c:08:16:a5:ad:42:7f:f0:eb:27:18:59:d0 +# Subject: CN=SecureTrust CA,O=SecureTrust Corporation,C=US +# Not Valid Before: Tue Nov 07 19:31:18 2006 +# Not Valid After : Mon Dec 31 19:40:55 2029 +# Fingerprint (MD5): DC:32:C3:A7:6D:25:57:C7:68:09:9D:EA:2D:A9:A2:D1 +# Fingerprint (SHA1): 87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=DC:32:C3:A7:6D:25:57:C7:68:09:9D:EA:2D:A9:A2:D1 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0c:f0:8e:5c:08:16:a5:ad:42:7f:f0:eb:27:18:59:d0 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=SecureTrust Corporation, CN=SecureTrust CA + Validity + Not Before: Nov 7 19:31:18 2006 GMT + Not After : Dec 31 19:40:55 2029 GMT + Subject: C=US, O=SecureTrust Corporation, CN=SecureTrust CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:a4:81:e5:95:cd:f5:f6:14:8e:c2:4f:ca:d4: + e2:78:95:58:9c:41:e1:0d:99:40:24:17:39:91:33: + 66:e9:be:e1:83:af:62:5c:89:d1:fc:24:5b:61:b3: + e0:11:11:41:1c:1d:6e:f0:b8:bb:f8:de:a7:81:ba: + a6:48:c6:9f:1d:bd:be:8e:a9:41:3e:b8:94:ed:29: + 1a:d4:8e:d2:03:1d:03:ef:6d:0d:67:1c:57:d7:06: + ad:ca:c8:f5:fe:0e:af:66:25:48:04:96:0b:5d:a3: + ba:16:c3:08:4f:d1:46:f8:14:5c:f2:c8:5e:01:99: + 6d:fd:88:cc:86:a8:c1:6f:31:42:6c:52:3e:68:cb: + f3:19:34:df:bb:87:18:56:80:26:c4:d0:dc:c0:6f: + df:de:a0:c2:91:16:a0:64:11:4b:44:bc:1e:f6:e7: + fa:63:de:66:ac:76:a4:71:a3:ec:36:94:68:7a:77: + a4:b1:e7:0e:2f:81:7a:e2:b5:72:86:ef:a2:6b:8b: + f0:0f:db:d3:59:3f:ba:72:bc:44:24:9c:e3:73:b3: + f7:af:57:2f:42:26:9d:a9:74:ba:00:52:f2:4b:cd: + 53:7c:47:0b:36:85:0e:66:a9:08:97:16:34:57:c1: + 66:f7:80:e3:ed:70:54:c7:93:e0:2e:28:15:59:87: + ba:bb + Exponent: 65537 (0x10001) + X509v3 extensions: + 1.3.6.1.4.1.311.20.2: + ...C.A + X509v3 Key Usage: + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 42:32:B6:16:FA:04:FD:FE:5D:4B:7A:C3:FD:F7:4C:40:1D:5A:43:AF + X509v3 CRL Distribution Points: + + Full Name: + URI:http://crl.securetrust.com/STCA.crl + + 1.3.6.1.4.1.311.21.1: + ... + Signature Algorithm: sha1WithRSAEncryption + 30:ed:4f:4a:e1:58:3a:52:72:5b:b5:a6:a3:65:18:a6:bb:51: + 3b:77:e9:9d:ea:d3:9f:5c:e0:45:65:7b:0d:ca:5b:e2:70:50: + b2:94:05:14:ae:49:c7:8d:41:07:12:73:94:7e:0c:23:21:fd: + bc:10:7f:60:10:5a:72:f5:98:0e:ac:ec:b9:7f:dd:7a:6f:5d: + d3:1c:f4:ff:88:05:69:42:a9:05:71:c8:b7:ac:26:e8:2e:b4: + 8c:6a:ff:71:dc:b8:b1:df:99:bc:7c:21:54:2b:e4:58:a2:bb: + 57:29:ae:9e:a9:a3:19:26:0f:99:2e:08:b0:ef:fd:69:cf:99: + 1a:09:8d:e3:a7:9f:2b:c9:36:34:7b:24:b3:78:4c:95:17:a4: + 06:26:1e:b6:64:52:36:5f:60:67:d9:9c:c5:05:74:0b:e7:67: + 23:d2:08:fc:88:e9:ae:8b:7f:e1:30:f4:37:7e:fd:c6:32:da: + 2d:9e:44:30:30:6c:ee:07:de:d2:34:fc:d2:ff:40:f6:4b:f4: + 66:46:06:54:a6:f2:32:0a:63:26:30:6b:9b:d1:dc:8b:47:ba: + e1:b9:d5:62:d0:a2:a0:f4:67:05:78:29:63:1a:6f:04:d6:f8: + c6:4c:a3:9a:b1:37:b4:8d:e5:28:4b:1d:9e:2c:c2:b8:68:bc: + ed:02:ee:31 +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz +MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv +cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz +Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO +0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao +wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj +7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS +8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT +BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg +JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 +6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ +3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm +D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS +CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +Secure Global CA +# Issuer: CN=Secure Global CA,O=SecureTrust Corporation,C=US +# Serial Number:07:56:22:a4:e8:d4:8a:89:4d:f4:13:c8:f0:f8:ea:a5 +# Subject: CN=Secure Global CA,O=SecureTrust Corporation,C=US +# Not Valid Before: Tue Nov 07 19:42:28 2006 +# Not Valid After : Mon Dec 31 19:52:06 2029 +# Fingerprint (MD5): CF:F4:27:0D:D4:ED:DC:65:16:49:6D:3D:DA:BF:6E:DE +# Fingerprint (SHA1): 3A:44:73:5A:E5:81:90:1F:24:86:61:46:1E:3B:9C:C4:5F:F5:3A:1B +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=CF:F4:27:0D:D4:ED:DC:65:16:49:6D:3D:DA:BF:6E:DE +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 07:56:22:a4:e8:d4:8a:89:4d:f4:13:c8:f0:f8:ea:a5 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=SecureTrust Corporation, CN=Secure Global CA + Validity + Not Before: Nov 7 19:42:28 2006 GMT + Not After : Dec 31 19:52:06 2029 GMT + Subject: C=US, O=SecureTrust Corporation, CN=Secure Global CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:af:35:2e:d8:ac:6c:55:69:06:71:e5:13:68:24: + b3:4f:d8:cc:21:47:f8:f1:60:38:89:89:03:e9:bd: + ea:5e:46:53:09:dc:5c:f5:5a:e8:f7:45:2a:02:eb: + 31:61:d7:29:33:4c:ce:c7:7c:0a:37:7e:0f:ba:32: + 98:e1:1d:97:af:8f:c7:dc:c9:38:96:f3:db:1a:fc: + 51:ed:68:c6:d0:6e:a4:7c:24:d1:ae:42:c8:96:50: + 63:2e:e0:fe:75:fe:98:a7:5f:49:2e:95:e3:39:33: + 64:8e:1e:a4:5f:90:d2:67:3c:b2:d9:fe:41:b9:55: + a7:09:8e:72:05:1e:8b:dd:44:85:82:42:d0:49:c0: + 1d:60:f0:d1:17:2c:95:eb:f6:a5:c1:92:a3:c5:c2: + a7:08:60:0d:60:04:10:96:79:9e:16:34:e6:a9:b6: + fa:25:45:39:c8:1e:65:f9:93:f5:aa:f1:52:dc:99: + 98:3d:a5:86:1a:0c:35:33:fa:4b:a5:04:06:15:1c: + 31:80:ef:aa:18:6b:c2:7b:d7:da:ce:f9:33:20:d5: + f5:bd:6a:33:2d:81:04:fb:b0:5c:d4:9c:a3:e2:5c: + 1d:e3:a9:42:75:5e:7b:d4:77:ef:39:54:ba:c9:0a: + 18:1b:12:99:49:2f:88:4b:fd:50:62:d1:73:e7:8f: + 7a:43 + Exponent: 65537 (0x10001) + X509v3 extensions: + 1.3.6.1.4.1.311.20.2: + ...C.A + X509v3 Key Usage: + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + AF:44:04:C2:41:7E:48:83:DB:4E:39:02:EC:EC:84:7A:E6:CE:C9:A4 + X509v3 CRL Distribution Points: + + Full Name: + URI:http://crl.securetrust.com/SGCA.crl + + 1.3.6.1.4.1.311.21.1: + ... + Signature Algorithm: sha1WithRSAEncryption + 63:1a:08:40:7d:a4:5e:53:0d:77:d8:7a:ae:1f:0d:0b:51:16: + 03:ef:18:7c:c8:e3:af:6a:58:93:14:60:91:b2:84:dc:88:4e: + be:39:8a:3a:f3:e6:82:89:5d:01:37:b3:ab:24:a4:15:0e:92: + 35:5a:4a:44:5e:4e:57:fa:75:ce:1f:48:ce:66:f4:3c:40:26: + 92:98:6c:1b:ee:24:46:0c:17:b3:52:a5:db:a5:91:91:cf:37: + d3:6f:e7:27:08:3a:4e:19:1f:3a:a7:58:5c:17:cf:79:3f:8b: + e4:a7:d3:26:23:9d:26:0f:58:69:fc:47:7e:b2:d0:8d:8b:93: + bf:29:4f:43:69:74:76:67:4b:cf:07:8c:e6:02:f7:b5:e1:b4: + 43:b5:4b:2d:14:9f:f9:dc:26:0d:bf:a6:47:74:06:d8:88:d1: + 3a:29:30:84:ce:d2:39:80:62:1b:a8:c7:57:49:bc:6a:55:51: + 67:15:4a:be:35:07:e4:d5:75:98:37:79:30:14:db:29:9d:6c: + c5:69:cc:47:55:a2:30:f7:cc:5c:7f:c2:c3:98:1c:6b:4e:16: + 80:eb:7a:78:65:45:a2:00:1a:af:0c:0d:55:64:34:48:b8:92: + b9:f1:b4:50:29:f2:4f:23:1f:da:6c:ac:1f:44:e1:dd:23:78: + 51:5b:c7:16 +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx +MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg +Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ +iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa +/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ +jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI +HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 +sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w +gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw +KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG +AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L +URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO +H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm +I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY +iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +COMODO Certification Authority +# Issuer: CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Serial Number:4e:81:2d:8a:82:65:e0:0b:02:ee:3e:35:02:46:e5:3d +# Subject: CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Not Valid Before: Fri Dec 01 00:00:00 2006 +# Not Valid After : Mon Dec 31 23:59:59 2029 +# Fingerprint (MD5): 5C:48:DC:F7:42:72:EC:56:94:6D:1C:CC:71:35:80:75 +# Fingerprint (SHA1): 66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=5C:48:DC:F7:42:72:EC:56:94:6D:1C:CC:71:35:80:75 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 4e:81:2d:8a:82:65:e0:0b:02:ee:3e:35:02:46:e5:3d + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO Certification Authority + Validity + Not Before: Dec 1 00:00:00 2006 GMT + Not After : Dec 31 23:59:59 2029 GMT + Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d0:40:8b:8b:72:e3:91:1b:f7:51:c1:1b:54:04: + 98:d3:a9:bf:c1:e6:8a:5d:3b:87:fb:bb:88:ce:0d: + e3:2f:3f:06:96:f0:a2:29:50:99:ae:db:3b:a1:57: + b0:74:51:71:cd:ed:42:91:4d:41:fe:a9:c8:d8:6a: + 86:77:44:bb:59:66:97:50:5e:b4:d4:2c:70:44:cf: + da:37:95:42:69:3c:30:c4:71:b3:52:f0:21:4d:a1: + d8:ba:39:7c:1c:9e:a3:24:9d:f2:83:16:98:aa:16: + 7c:43:9b:15:5b:b7:ae:34:91:fe:d4:62:26:18:46: + 9a:3f:eb:c1:f9:f1:90:57:eb:ac:7a:0d:8b:db:72: + 30:6a:66:d5:e0:46:a3:70:dc:68:d9:ff:04:48:89: + 77:de:b5:e9:fb:67:6d:41:e9:bc:39:bd:32:d9:62: + 02:f1:b1:a8:3d:6e:37:9c:e2:2f:e2:d3:a2:26:8b: + c6:b8:55:43:88:e1:23:3e:a5:d2:24:39:6a:47:ab: + 00:d4:a1:b3:a9:25:fe:0d:3f:a7:1d:ba:d3:51:c1: + 0b:a4:da:ac:38:ef:55:50:24:05:65:46:93:34:4f: + 2d:8d:ad:c6:d4:21:19:d2:8e:ca:05:61:71:07:73: + 47:e5:8a:19:12:bd:04:4d:ce:4e:9c:a5:48:ac:bb: + 26:f7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 0B:58:E5:8B:C6:4C:15:37:A4:40:A9:30:A9:21:BE:47:36:5A:56:FF + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 CRL Distribution Points: + + Full Name: + URI:http://crl.comodoca.com/COMODOCertificationAuthority.crl + + Signature Algorithm: sha1WithRSAEncryption + 3e:98:9e:9b:f6:1b:e9:d7:39:b7:78:ae:1d:72:18:49:d3:87: + e4:43:82:eb:3f:c9:aa:f5:a8:b5:ef:55:7c:21:52:65:f9:d5: + 0d:e1:6c:f4:3e:8c:93:73:91:2e:02:c4:4e:07:71:6f:c0:8f: + 38:61:08:a8:1e:81:0a:c0:2f:20:2f:41:8b:91:dc:48:45:bc: + f1:c6:de:ba:76:6b:33:c8:00:2d:31:46:4c:ed:e7:9d:cf:88: + 94:ff:33:c0:56:e8:24:86:26:b8:d8:38:38:df:2a:6b:dd:12: + cc:c7:3f:47:17:4c:a2:c2:06:96:09:d6:db:fe:3f:3c:46:41: + df:58:e2:56:0f:3c:3b:c1:1c:93:35:d9:38:52:ac:ee:c8:ec: + 2e:30:4e:94:35:b4:24:1f:4b:78:69:da:f2:02:38:cc:95:52: + 93:f0:70:25:59:9c:20:67:c4:ee:f9:8b:57:61:f4:92:76:7d: + 3f:84:8d:55:b7:e8:e5:ac:d5:f1:f5:19:56:a6:5a:fb:90:1c: + af:93:eb:e5:1c:d4:67:97:5d:04:0e:be:0b:83:a6:17:83:b9: + 30:12:a0:c5:33:15:05:b9:0d:fb:c7:05:76:e3:d8:4a:8d:fc: + 34:17:a3:c6:21:28:be:30:45:31:1e:c7:78:be:58:61:38:ac: + 3b:e2:01:65 +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE----- + +Network Solutions Certificate Authority +# Issuer: CN=Network Solutions Certificate Authority,O=Network Solutions L.L.C.,C=US +# Serial Number:57:cb:33:6f:c2:5c:16:e6:47:16:17:e3:90:31:68:e0 +# Subject: CN=Network Solutions Certificate Authority,O=Network Solutions L.L.C.,C=US +# Not Valid Before: Fri Dec 01 00:00:00 2006 +# Not Valid After : Mon Dec 31 23:59:59 2029 +# Fingerprint (MD5): D3:F3:A6:16:C0:FA:6B:1D:59:B1:2D:96:4D:0E:11:2E +# Fingerprint (SHA1): 74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=D3:F3:A6:16:C0:FA:6B:1D:59:B1:2D:96:4D:0E:11:2E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 57:cb:33:6f:c2:5c:16:e6:47:16:17:e3:90:31:68:e0 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Network Solutions L.L.C., CN=Network Solutions Certificate Authority + Validity + Not Before: Dec 1 00:00:00 2006 GMT + Not After : Dec 31 23:59:59 2029 GMT + Subject: C=US, O=Network Solutions L.L.C., CN=Network Solutions Certificate Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:e4:bc:7e:92:30:6d:c6:d8:8e:2b:0b:bc:46:ce: + e0:27:96:de:de:f9:fa:12:d3:3c:33:73:b3:04:2f: + bc:71:8c:e5:9f:b6:22:60:3e:5f:5d:ce:09:ff:82: + 0c:1b:9a:51:50:1a:26:89:dd:d5:61:5d:19:dc:12: + 0f:2d:0a:a2:43:5d:17:d0:34:92:20:ea:73:cf:38: + 2c:06:26:09:7a:72:f7:fa:50:32:f8:c2:93:d3:69: + a2:23:ce:41:b1:cc:e4:d5:1f:36:d1:8a:3a:f8:8c: + 63:e2:14:59:69:ed:0d:d3:7f:6b:e8:b8:03:e5:4f: + 6a:e5:98:63:69:48:05:be:2e:ff:33:b6:e9:97:59: + 69:f8:67:19:ae:93:61:96:44:15:d3:72:b0:3f:bc: + 6a:7d:ec:48:7f:8d:c3:ab:aa:71:2b:53:69:41:53: + 34:b5:b0:b9:c5:06:0a:c4:b0:45:f5:41:5d:6e:89: + 45:7b:3d:3b:26:8c:74:c2:e5:d2:d1:7d:b2:11:d4: + fb:58:32:22:9a:80:c9:dc:fd:0c:e9:7f:5e:03:97: + ce:3b:00:14:87:27:70:38:a9:8e:6e:b3:27:76:98: + 51:e0:05:e3:21:ab:1a:d5:85:22:3c:29:b5:9a:16: + c5:80:a8:f4:bb:6b:30:8f:2f:46:02:a2:b1:0c:22: + e0:d3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 21:30:C9:FB:00:D7:4E:98:DA:87:AA:2A:D0:A7:2E:B1:40:31:A7:4C + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 CRL Distribution Points: + + Full Name: + URI:http://crl.netsolssl.com/NetworkSolutionsCertificateAuthority.crl + + Signature Algorithm: sha1WithRSAEncryption + bb:ae:4b:e7:b7:57:eb:7f:aa:2d:b7:73:47:85:6a:c1:e4:a5: + 1d:e4:e7:3c:e9:f4:59:65:77:b5:7a:5b:5a:8d:25:36:e0:7a: + 97:2e:38:c0:57:60:83:98:06:83:9f:b9:76:7a:6e:50:e0:ba: + 88:2c:fc:45:cc:18:b0:99:95:51:0e:ec:1d:b8:88:ff:87:50: + 1c:82:c2:e3:e0:32:80:bf:a0:0b:47:c8:c3:31:ef:99:67:32: + 80:4f:17:21:79:0c:69:5c:de:5e:34:ae:02:b5:26:ea:50:df: + 7f:18:65:2c:c9:f2:63:e1:a9:07:fe:7c:71:1f:6b:33:24:6a: + 1e:05:f7:05:68:c0:6a:12:cb:2e:5e:61:cb:ae:28:d3:7e:c2: + b4:66:91:26:5f:3c:2e:24:5f:cb:58:0f:eb:28:ec:af:11:96: + f3:dc:7b:6f:c0:a7:88:f2:53:77:b3:60:5e:ae:ae:28:da:35: + 2c:6f:34:45:d3:26:e1:de:ec:5b:4f:27:6b:16:7c:bd:44:04: + 18:82:b3:89:79:17:10:71:3d:7a:a2:16:4e:f5:01:cd:a4:6c: + 65:68:a1:49:76:5c:43:c9:d8:bc:36:67:6c:a5:94:b5:d4:cc: + b9:bd:6a:35:56:21:de:d8:c3:eb:fb:cb:a4:60:4c:b0:55:a0: + a0:7b:57:b2 +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi +MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV +UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO +ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz +c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP +OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl +mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF +BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 +qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw +gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu +bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp +dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 +6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ +h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH +/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN +pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +COMODO ECC Certification Authority +# Issuer: CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Serial Number:1f:47:af:aa:62:00:70:50:54:4c:01:9e:9b:63:99:2a +# Subject: CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Not Valid Before: Thu Mar 06 00:00:00 2008 +# Not Valid After : Mon Jan 18 23:59:59 2038 +# Fingerprint (MD5): 7C:62:FF:74:9D:31:53:5E:68:4A:D5:78:AA:1E:BF:23 +# Fingerprint (SHA1): 9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=7C:62:FF:74:9D:31:53:5E:68:4A:D5:78:AA:1E:BF:23 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 1f:47:af:aa:62:00:70:50:54:4c:01:9e:9b:63:99:2a + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO ECC Certification Authority + Validity + Not Before: Mar 6 00:00:00 2008 GMT + Not After : Jan 18 23:59:59 2038 GMT + Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO ECC Certification Authority + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:03:47:7b:2f:75:c9:82:15:85:fb:75:e4:91:16: + d4:ab:62:99:f5:3e:52:0b:06:ce:41:00:7f:97:e1: + 0a:24:3c:1d:01:04:ee:3d:d2:8d:09:97:0c:e0:75: + e4:fa:fb:77:8a:2a:f5:03:60:4b:36:8b:16:23:16: + ad:09:71:f4:4a:f4:28:50:b4:fe:88:1c:6e:3f:6c: + 2f:2f:09:59:5b:a5:5b:0b:33:99:e2:c3:3d:89:f9: + 6a:2c:ef:b2:d3:06:e9 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Subject Key Identifier: + 75:71:A7:19:48:19:BC:9D:9D:EA:41:47:DF:94:C4:48:77:99:D3:79 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:31:00:ef:03:5b:7a:ac:b7:78:0a:72:b7:88:df:ff: + b5:46:14:09:0a:fa:a0:e6:7d:08:c6:1a:87:bd:18:a8:73:bd: + 26:ca:60:0c:9d:ce:99:9f:cf:5c:0f:30:e1:be:14:31:ea:02: + 30:14:f4:93:3c:49:a7:33:7a:90:46:47:b3:63:7d:13:9b:4e: + b7:6f:18:37:80:53:fe:dd:20:e0:35:9a:36:d1:c7:01:b9:e6: + dc:dd:f3:ff:1d:2c:3a:16:57:d9:92:39:d6 +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT +IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw +MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy +ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N +T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR +FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J +cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW +BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm +fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv +GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +Security Communication EV RootCA1 +# Issuer: OU=Security Communication EV RootCA1,O="SECOM Trust Systems CO.,LTD.",C=JP +# Serial Number: 0 (0x0) +# Subject: OU=Security Communication EV RootCA1,O="SECOM Trust Systems CO.,LTD.",C=JP +# Not Valid Before: Wed Jun 06 02:12:32 2007 +# Not Valid After : Sat Jun 06 02:12:32 2037 +# Fingerprint (MD5): 22:2D:A6:01:EA:7C:0A:F7:F0:6C:56:43:3F:77:76:D3 +# Fingerprint (SHA1): FE:B8:C4:32:DC:F9:76:9A:CE:AE:3D:D8:90:8F:FD:28:86:65:64:7D +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=22:2D:A6:01:EA:7C:0A:F7:F0:6C:56:43:3F:77:76:D3 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=JP, O=SECOM Trust Systems CO.,LTD., OU=Security Communication EV RootCA1 + Validity + Not Before: Jun 6 02:12:32 2007 GMT + Not After : Jun 6 02:12:32 2037 GMT + Subject: C=JP, O=SECOM Trust Systems CO.,LTD., OU=Security Communication EV RootCA1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:bc:7f:ec:57:9b:24:e0:fe:9c:ba:42:79:a9:88: + 8a:fa:80:e0:f5:07:29:43:ea:8e:0a:34:36:8d:1c: + fa:a7:b5:39:78:ff:97:75:f7:2f:e4:aa:6b:04:84: + 44:ca:a6:e2:68:8e:fd:55:50:62:0f:a4:71:0e:ce: + 07:38:2d:42:85:50:ad:3c:96:6f:8b:d5:a2:0e:cf: + de:49:89:3d:d6:64:2e:38:e5:1e:6c:b5:57:8a:9e: + ef:48:0e:cd:7a:69:16:87:44:b5:90:e4:06:9d:ae: + a1:04:97:58:79:ef:20:4a:82:6b:8c:22:bf:ec:1f: + 0f:e9:84:71:ed:f1:0e:e4:b8:18:13:cc:56:36:5d: + d1:9a:1e:51:6b:39:6e:60:76:88:34:0b:f3:b3:d1: + b0:9d:ca:61:e2:64:1d:c1:46:07:b8:63:dd:1e:33: + 65:b3:8e:09:55:52:3d:b5:bd:ff:07:eb:ad:61:55: + 18:2c:a9:69:98:4a:aa:40:c5:33:14:65:74:00:f9: + 91:de:af:03:48:c5:40:54:dc:0f:84:90:68:20:c5: + 92:96:dc:2e:e5:02:45:aa:c0:5f:54:f8:6d:ea:49: + cf:5d:6c:4b:af:ef:9a:c2:56:5c:c6:35:56:42:6a: + 30:5f:c2:ab:f6:e2:3d:3f:b3:c9:11:8f:31:4c:d7: + 9f:49 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 35:4A:F5:4D:AF:3F:D7:82:38:AC:AB:71:65:17:75:8C:9D:55:93:E6 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + a8:87:e9:ec:f8:40:67:5d:c3:c1:66:c7:40:4b:97:fc:87:13: + 90:5a:c4:ef:a0:ca:5f:8b:b7:a7:b7:f1:d6:b5:64:b7:8a:b3: + b8:1b:cc:da:fb:ac:66:88:41:ce:e8:fc:e4:db:1e:88:a6:ed: + 27:50:1b:02:30:24:46:79:fe:04:87:70:97:40:73:d1:c0:c1: + 57:19:9a:69:a5:27:99:ab:9d:62:84:f6:51:c1:2c:c9:23:15: + d8:28:b7:ab:25:13:b5:46:e1:86:02:ff:26:8c:c4:88:92:1d: + 56:fe:19:67:f2:55:e4:80:a3:6b:9c:ab:77:e1:51:71:0d:20: + db:10:9a:db:bd:76:79:07:77:99:28:ad:9a:5e:da:b1:4f:44: + 2c:35:8e:a5:96:c7:fd:83:f0:58:c6:79:d6:98:7c:a8:8d:fe: + 86:3e:07:16:92:e1:7b:e7:1d:ec:33:76:7e:42:2e:4a:85:f9: + 91:89:68:84:03:81:a5:9b:9a:be:e3:37:c5:54:ab:56:3b:18: + 2d:41:a4:0c:f8:42:db:99:a0:e0:72:6f:bb:5d:e1:16:4f:53: + 0a:64:f9:4e:f4:bf:4e:54:bd:78:6c:88:ea:bf:9c:13:24:c2: + 70:69:a2:7f:0f:c8:3c:ad:08:c9:b0:98:40:a3:2a:e7:88:83: + ed:77:8f:74 +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz +MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N +IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11 +bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE +RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO +zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5 +bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF +MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1 +VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC +OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW +tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ +q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb +EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+ +Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O +VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GA CA +# Issuer: CN=OISTE WISeKey Global Root GA CA,OU=OISTE Foundation Endorsed,OU=Copyright (c) 2005,O=WISeKey,C=CH +# Serial Number:41:3d:72:c7:f4:6b:1f:81:43:7d:f1:d2:28:54:df:9a +# Subject: CN=OISTE WISeKey Global Root GA CA,OU=OISTE Foundation Endorsed,OU=Copyright (c) 2005,O=WISeKey,C=CH +# Not Valid Before: Sun Dec 11 16:03:44 2005 +# Not Valid After : Fri Dec 11 16:09:51 2037 +# Fingerprint (MD5): BC:6C:51:33:A7:E9:D3:66:63:54:15:72:1B:21:92:93 +# Fingerprint (SHA1): 59:22:A1:E1:5A:EA:16:35:21:F8:98:39:6A:46:46:B0:44:1B:0F:A9 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=BC:6C:51:33:A7:E9:D3:66:63:54:15:72:1B:21:92:93 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 41:3d:72:c7:f4:6b:1f:81:43:7d:f1:d2:28:54:df:9a + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=CH, O=WISeKey, OU=Copyright (c) 2005, OU=OISTE Foundation Endorsed, CN=OISTE WISeKey Global Root GA CA + Validity + Not Before: Dec 11 16:03:44 2005 GMT + Not After : Dec 11 16:09:51 2037 GMT + Subject: C=CH, O=WISeKey, OU=Copyright (c) 2005, OU=OISTE Foundation Endorsed, CN=OISTE WISeKey Global Root GA CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:cb:4f:b3:00:9b:3d:36:dd:f9:d1:49:6a:6b:10: + 49:1f:ec:d8:2b:b2:c6:f8:32:81:29:43:95:4c:9a: + 19:23:21:15:45:de:e3:c8:1c:51:55:5b:ae:93:e8: + 37:ff:2b:6b:e9:d4:ea:be:2a:dd:a8:51:2b:d7:66: + c3:61:5c:60:02:c8:f5:ce:72:7b:3b:b8:f2:4e:65: + 08:9a:cd:a4:6a:19:c1:01:bb:73:a6:d7:f6:c3:dd: + cd:bc:a4:8b:b5:99:61:b8:01:a2:a3:d4:4d:d4:05: + 3d:91:ad:f8:b4:08:71:64:af:70:f1:1c:6b:7e:f6: + c3:77:9d:24:73:7b:e4:0c:8c:e1:d9:36:e1:99:8b: + 05:99:0b:ed:45:31:09:ca:c2:00:db:f7:72:a0:96: + aa:95:87:d0:8e:c7:b6:61:73:0d:76:66:8c:dc:1b: + b4:63:a2:9f:7f:93:13:30:f1:a1:27:db:d9:ff:2c: + 55:88:91:a0:e0:4f:07:b0:28:56:8c:18:1b:97:44: + 8e:89:dd:e0:17:6e:e7:2a:ef:8f:39:0a:31:84:82: + d8:40:14:49:2e:7a:41:e4:a7:fe:e3:64:cc:c1:59: + 71:4b:2c:21:a7:5b:7d:e0:1d:d1:2e:81:9b:c3:d8: + 68:f7:bd:96:1b:ac:70:b1:16:14:0b:db:60:b9:26: + 01:05 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + B3:03:7E:AE:36:BC:B0:79:D1:DC:94:26:B6:11:BE:21:B2:69:86:94 + 1.3.6.1.4.1.311.21.1: + ... + Signature Algorithm: sha1WithRSAEncryption + 4b:a1:ff:0b:87:6e:b3:f9:c1:43:b1:48:f3:28:c0:1d:2e:c9: + 09:41:fa:94:00:1c:a4:a4:ab:49:4f:8f:3d:1e:ef:4d:6f:bd: + bc:a4:f6:f2:26:30:c9:10:ca:1d:88:fb:74:19:1f:85:45:bd: + b0:6c:51:f9:36:7e:db:f5:4c:32:3a:41:4f:5b:47:cf:e8:0b: + 2d:b6:c4:19:9d:74:c5:47:c6:3b:6a:0f:ac:14:db:3c:f4:73: + 9c:a9:05:df:00:dc:74:78:fa:f8:35:60:59:02:13:18:7c:bc: + fb:4d:b0:20:6d:43:bb:60:30:7a:67:33:5c:c5:99:d1:f8:2d: + 39:52:73:fb:8c:aa:97:25:5c:72:d9:08:1e:ab:4e:3c:e3:81: + 31:9f:03:a6:fb:c0:fe:29:88:55:da:84:d5:50:03:b6:e2:84: + a3:a6:36:aa:11:3a:01:e1:18:4b:d6:44:68:b3:3d:f9:53:74: + 84:b3:46:91:46:96:00:b7:80:2c:b6:e1:e3:10:e2:db:a2:e7: + 28:8f:01:96:62:16:3e:00:e3:1c:a5:36:81:18:a2:4c:52:76: + c0:11:a3:6e:e6:1d:ba:e3:5a:be:36:53:c5:3e:75:8f:86:69: + 29:58:53:b5:9c:bb:6f:9f:5c:c5:18:ec:dd:2f:e1:98:c9:fc: + be:df:0a:0d +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB +ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly +aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w +NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G +A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX +SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR +VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 +w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF +mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg +4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 +4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw +EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx +SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 +ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 +vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi +Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ +/L7fCg0= +-----END CERTIFICATE----- + +Certigna +# Issuer: CN=Certigna,O=Dhimyotis,C=FR +# Serial Number:00:fe:dc:e3:01:0f:c9:48:ff +# Subject: CN=Certigna,O=Dhimyotis,C=FR +# Not Valid Before: Fri Jun 29 15:13:05 2007 +# Not Valid After : Tue Jun 29 15:13:05 2027 +# Fingerprint (MD5): AB:57:A6:5B:7D:42:82:19:B5:D8:58:26:28:5E:FD:FF +# Fingerprint (SHA1): B1:2E:13:63:45:86:A4:6F:1A:B2:60:68:37:58:2D:C4:AC:FD:94:97 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=AB:57:A6:5B:7D:42:82:19:B5:D8:58:26:28:5E:FD:FF +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + fe:dc:e3:01:0f:c9:48:ff + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=FR, O=Dhimyotis, CN=Certigna + Validity + Not Before: Jun 29 15:13:05 2007 GMT + Not After : Jun 29 15:13:05 2027 GMT + Subject: C=FR, O=Dhimyotis, CN=Certigna + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c8:68:f1:c9:d6:d6:b3:34:75:26:82:1e:ec:b4: + be:ea:5c:e1:26:ed:11:47:61:e1:a2:7c:16:78:40: + 21:e4:60:9e:5a:c8:63:e1:c4:b1:96:92:ff:18:6d: + 69:23:e1:2b:62:f7:dd:e2:36:2f:91:07:b9:48:cf: + 0e:ec:79:b6:2c:e7:34:4b:70:08:25:a3:3c:87:1b: + 19:f2:81:07:0f:38:90:19:d3:11:fe:86:b4:f2:d1: + 5e:1e:1e:96:cd:80:6c:ce:3b:31:93:b6:f2:a0:d0: + a9:95:12:7d:a5:9a:cc:6b:c8:84:56:8a:33:a9:e7: + 22:15:53:16:f0:cc:17:ec:57:5f:e9:a2:0a:98:09: + de:e3:5f:9c:6f:dc:48:e3:85:0b:15:5a:a6:ba:9f: + ac:48:e3:09:b2:f7:f4:32:de:5e:34:be:1c:78:5d: + 42:5b:ce:0e:22:8f:4d:90:d7:7d:32:18:b3:0b:2c: + 6a:bf:8e:3f:14:11:89:20:0e:77:14:b5:3d:94:08: + 87:f7:25:1e:d5:b2:60:00:ec:6f:2a:28:25:6e:2a: + 3e:18:63:17:25:3f:3e:44:20:16:f6:26:c8:25:ae: + 05:4a:b4:e7:63:2c:f3:8c:16:53:7e:5c:fb:11:1a: + 08:c1:46:62:9f:22:b8:f1:c2:8d:69:dc:fa:3a:58: + 06:df + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 1A:ED:FE:41:39:90:B4:24:59:BE:01:F2:52:D5:45:F6:5A:39:DC:11 + X509v3 Authority Key Identifier: + keyid:1A:ED:FE:41:39:90:B4:24:59:BE:01:F2:52:D5:45:F6:5A:39:DC:11 + DirName:/C=FR/O=Dhimyotis/CN=Certigna + serial:FE:DC:E3:01:0F:C9:48:FF + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: sha1WithRSAEncryption + 85:03:1e:92:71:f6:42:af:e1:a3:61:9e:eb:f3:c0:0f:f2:a5: + d4:da:95:e6:d6:be:68:36:3d:7e:6e:1f:4c:8a:ef:d1:0f:21: + 6d:5e:a5:52:63:ce:12:f8:ef:2a:da:6f:eb:37:fe:13:02:c7: + cb:3b:3e:22:6b:da:61:2e:7f:d4:72:3d:dd:30:e1:1e:4c:40: + 19:8c:0f:d7:9c:d1:83:30:7b:98:59:dc:7d:c6:b9:0c:29:4c: + a1:33:a2:eb:67:3a:65:84:d3:96:e2:ed:76:45:70:8f:b5:2b: + de:f9:23:d6:49:6e:3c:14:b5:c6:9f:35:1e:50:d0:c1:8f:6a: + 70:44:02:62:cb:ae:1d:68:41:a7:aa:57:e8:53:aa:07:d2:06: + f6:d5:14:06:0b:91:03:75:2c:6c:72:b5:61:95:9a:0d:8b:b9: + 0d:e7:f5:df:54:cd:de:e6:d8:d6:09:08:97:63:e5:c1:2e:b0: + b7:44:26:c0:26:c0:af:55:30:9e:3b:d5:36:2a:19:04:f4:5c: + 1e:ff:cf:2c:b7:ff:d0:fd:87:40:11:d5:11:23:bb:48:c0:21: + a9:a4:28:2d:fd:15:f8:b0:4e:2b:f4:30:5b:21:fc:11:91:34: + be:41:ef:7b:9d:97:75:ff:97:95:c0:96:58:2f:ea:bb:46:d7: + bb:e4:d9:2e +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X +DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ +BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 +QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny +gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw +zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q +130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 +JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw +ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj +AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG +9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h +bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc +fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu +HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w +t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +Deutsche Telekom Root CA 2 +# Issuer: CN=Deutsche Telekom Root CA 2,OU=T-TeleSec Trust Center,O=Deutsche Telekom AG,C=DE +# Serial Number: 38 (0x26) +# Subject: CN=Deutsche Telekom Root CA 2,OU=T-TeleSec Trust Center,O=Deutsche Telekom AG,C=DE +# Not Valid Before: Fri Jul 09 12:11:00 1999 +# Not Valid After : Tue Jul 09 23:59:00 2019 +# Fingerprint (MD5): 74:01:4A:91:B1:08:C4:58:CE:47:CD:F0:DD:11:53:08 +# Fingerprint (SHA1): 85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=74:01:4A:91:B1:08:C4:58:CE:47:CD:F0:DD:11:53:08 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 38 (0x26) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 2 + Validity + Not Before: Jul 9 12:11:00 1999 GMT + Not After : Jul 9 23:59:00 2019 GMT + Subject: C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:0b:a3:35:e0:8b:29:14:b1:14:85:af:3c:10: + e4:39:6f:35:5d:4a:ae:dd:ea:61:8d:95:49:f4:6f: + 64:a3:1a:60:66:a4:a9:40:22:84:d9:d4:a5:e5:78: + 93:0e:68:01:ad:b9:4d:5c:3a:ce:d3:b8:a8:42:40: + df:cf:a3:ba:82:59:6a:92:1b:ac:1c:9a:da:08:2b: + 25:27:f9:69:23:47:f1:e0:eb:2c:7a:9b:f5:13:02: + d0:7e:34:7c:c2:9e:3c:00:59:ab:f5:da:0c:f5:32: + 3c:2b:ac:50:da:d6:c3:de:83:94:ca:a8:0c:99:32: + 0e:08:48:56:5b:6a:fb:da:e1:58:58:01:49:5f:72: + 41:3c:15:06:01:8e:5d:ad:aa:b8:93:b4:cd:9e:eb: + a7:e8:6a:2d:52:34:db:3a:ef:5c:75:51:da:db:f3: + 31:f9:ee:71:98:32:c4:54:15:44:0c:f9:9b:55:ed: + ad:df:18:08:a0:a3:86:8a:49:ee:53:05:8f:19:4c: + d5:de:58:79:9b:d2:6a:1c:42:ab:c5:d5:a7:cf:68: + 0f:96:e4:e1:61:98:76:61:c8:91:7c:d6:3e:00:e2: + 91:50:87:e1:9d:0a:e6:ad:97:d2:1d:c6:3a:7d:cb: + bc:da:03:34:d5:8e:5b:01:f5:6a:07:b7:16:b6:6e: + 4a:7f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 31:C3:79:1B:BA:F5:53:D7:17:E0:89:7A:2D:17:6C:0A:B3:2B:9D:33 + X509v3 Basic Constraints: + CA:TRUE, pathlen:5 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 94:64:59:ad:39:64:e7:29:eb:13:fe:5a:c3:8b:13:57:c8:04: + 24:f0:74:77:c0:60:e3:67:fb:e9:89:a6:83:bf:96:82:7c:6e: + d4:c3:3d:ef:9e:80:6e:bb:29:b4:98:7a:b1:3b:54:eb:39:17: + 47:7e:1a:8e:0b:fc:1f:31:59:31:04:b2:ce:17:f3:2c:c7:62: + 36:55:e2:22:d8:89:55:b4:98:48:aa:64:fa:d6:1c:36:d8:44: + 78:5a:5a:23:3a:57:97:f5:7a:30:4f:ae:9f:6a:4c:4b:2b:8e: + a0:03:e3:3e:e0:a9:d4:d2:7b:d2:b3:a8:e2:72:3c:ad:9e:ff: + 80:59:e4:9b:45:b4:f6:3b:b0:cd:39:19:98:32:e5:ea:21:61: + 90:e4:31:21:8e:34:b1:f7:2f:35:4a:85:10:da:e7:8a:37:21: + be:59:63:e0:f2:85:88:31:53:d4:54:14:85:70:79:f4:2e:06: + 77:27:75:2f:1f:b8:8a:f9:fe:c5:ba:d8:36:e4:83:ec:e7:65: + b7:bf:63:5a:f3:46:af:81:94:37:d4:41:8c:d6:23:d6:1e:cf: + f5:68:1b:44:63:a2:5a:ba:a7:35:59:a1:e5:70:05:9b:0e:23: + 57:99:94:0a:6d:ba:39:63:28:86:92:f3:18:84:d8:fb:d1:cf: + 05:56:64:57 +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc +MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj +IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB +IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE +RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl +U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 +IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU +ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC +QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr +rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S +NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc +QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH +txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP +BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC +AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp +tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa +IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl +6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ +xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== +-----END CERTIFICATE----- + +Cybertrust Global Root +# Issuer: CN=Cybertrust Global Root,O="Cybertrust, Inc" +# Serial Number:04:00:00:00:00:01:0f:85:aa:2d:48 +# Subject: CN=Cybertrust Global Root,O="Cybertrust, Inc" +# Not Valid Before: Fri Dec 15 08:00:00 2006 +# Not Valid After : Wed Dec 15 08:00:00 2021 +# Fingerprint (MD5): 72:E4:4A:87:E3:69:40:80:77:EA:BC:E3:F4:FF:F0:E1 +# Fingerprint (SHA1): 5F:43:E5:B1:BF:F8:78:8C:AC:1C:C7:CA:4A:9A:C6:22:2B:CC:34:C6 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=72:E4:4A:87:E3:69:40:80:77:EA:BC:E3:F4:FF:F0:E1 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 04:00:00:00:00:01:0f:85:aa:2d:48 + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=Cybertrust, Inc, CN=Cybertrust Global Root + Validity + Not Before: Dec 15 08:00:00 2006 GMT + Not After : Dec 15 08:00:00 2021 GMT + Subject: O=Cybertrust, Inc, CN=Cybertrust Global Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:f8:c8:bc:bd:14:50:66:13:ff:f0:d3:79:ec:23: + f2:b7:1a:c7:8e:85:f1:12:73:a6:19:aa:10:db:9c: + a2:65:74:5a:77:3e:51:7d:56:f6:dc:23:b6:d4:ed: + 5f:58:b1:37:4d:d5:49:0e:6e:f5:6a:87:d6:d2:8c: + d2:27:c6:e2:ff:36:9f:98:65:a0:13:4e:c6:2a:64: + 9b:d5:90:12:cf:14:06:f4:3b:e3:d4:28:be:e8:0e: + f8:ab:4e:48:94:6d:8e:95:31:10:5c:ed:a2:2d:bd: + d5:3a:6d:b2:1c:bb:60:c0:46:4b:01:f5:49:ae:7e: + 46:8a:d0:74:8d:a1:0c:02:ce:ee:fc:e7:8f:b8:6b: + 66:f3:7f:44:00:bf:66:25:14:2b:dd:10:30:1d:07: + 96:3f:4d:f6:6b:b8:8f:b7:7b:0c:a5:38:eb:de:47: + db:d5:5d:39:fc:88:a7:f3:d7:2a:74:f1:e8:5a:a2: + 3b:9f:50:ba:a6:8c:45:35:c2:50:65:95:dc:63:82: + ef:dd:bf:77:4d:9c:62:c9:63:73:16:d0:29:0f:49: + a9:48:f0:b3:aa:b7:6c:c5:a7:30:39:40:5d:ae:c4: + e2:5d:26:53:f0:ce:1c:23:08:61:a8:94:19:ba:04: + 62:40:ec:1f:38:70:77:12:06:71:a7:30:18:5d:25: + 27:a5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + B6:08:7B:0D:7A:CC:AC:20:4C:86:56:32:5E:CF:AB:6E:85:2D:70:57 + X509v3 CRL Distribution Points: + + Full Name: + URI:http://www2.public-trust.com/crl/ct/ctroot.crl + + X509v3 Authority Key Identifier: + keyid:B6:08:7B:0D:7A:CC:AC:20:4C:86:56:32:5E:CF:AB:6E:85:2D:70:57 + + Signature Algorithm: sha1WithRSAEncryption + 56:ef:0a:23:a0:54:4e:95:97:c9:f8:89:da:45:c1:d4:a3:00: + 25:f4:1f:13:ab:b7:a3:85:58:69:c2:30:ad:d8:15:8a:2d:e3: + c9:cd:81:5a:f8:73:23:5a:a7:7c:05:f3:fd:22:3b:0e:d1:06: + c4:db:36:4c:73:04:8e:e5:b0:22:e4:c5:f3:2e:a5:d9:23:e3: + b8:4e:4a:20:a7:6e:02:24:9f:22:60:67:7b:8b:1d:72:09:c5: + 31:5c:e9:79:9f:80:47:3d:ad:a1:0b:07:14:3d:47:ff:03:69: + 1a:0c:0b:44:e7:63:25:a7:7f:b2:c9:b8:76:84:ed:23:f6:7d: + 07:ab:45:7e:d3:df:b3:bf:e9:8a:b6:cd:a8:a2:67:2b:52:d5: + b7:65:f0:39:4c:63:a0:91:79:93:52:0f:54:dd:83:bb:9f:d1: + 8f:a7:53:73:c3:cb:ff:30:ec:7c:04:b8:d8:44:1f:93:5f:71: + 09:22:b7:6e:3e:ea:1c:03:4e:9d:1a:20:61:fb:81:37:ec:5e: + fc:0a:45:ab:d7:e7:17:55:d0:a0:ea:60:9b:a6:f6:e3:8c:5b: + 29:c2:06:60:14:9d:2d:97:4c:a9:93:15:9d:61:c4:01:5f:48: + d6:58:bd:56:31:12:4e:11:c8:21:e0:b3:11:91:65:db:b4:a6: + 88:38:ce:55 +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG +A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh +bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE +ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS +b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 +7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS +J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y +HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP +t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz +FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY +XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ +MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw +hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js +MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA +A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj +Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx +XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o +omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc +A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +ePKI Root Certification Authority +# Issuer: OU=ePKI Root Certification Authority,O="Chunghwa Telecom Co., Ltd.",C=TW +# Serial Number:15:c8:bd:65:47:5c:af:b8:97:00:5e:e4:06:d2:bc:9d +# Subject: OU=ePKI Root Certification Authority,O="Chunghwa Telecom Co., Ltd.",C=TW +# Not Valid Before: Mon Dec 20 02:31:27 2004 +# Not Valid After : Wed Dec 20 02:31:27 2034 +# Fingerprint (MD5): 1B:2E:00:CA:26:06:90:3D:AD:FE:6F:15:68:D3:6B:B3 +# Fingerprint (SHA1): 67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=1B:2E:00:CA:26:06:90:3D:AD:FE:6F:15:68:D3:6B:B3 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 15:c8:bd:65:47:5c:af:b8:97:00:5e:e4:06:d2:bc:9d + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=TW, O=Chunghwa Telecom Co., Ltd., OU=ePKI Root Certification Authority + Validity + Not Before: Dec 20 02:31:27 2004 GMT + Not After : Dec 20 02:31:27 2034 GMT + Subject: C=TW, O=Chunghwa Telecom Co., Ltd., OU=ePKI Root Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:e1:25:0f:ee:8d:db:88:33:75:67:cd:ad:1f:7d: + 3a:4e:6d:9d:d3:2f:14:f3:63:74:cb:01:21:6a:37: + ea:84:50:07:4b:26:5b:09:43:6c:21:9e:6a:c8:d5: + 03:f5:60:69:8f:cc:f0:22:e4:1f:e7:f7:6a:22:31: + b7:2c:15:f2:e0:fe:00:6a:43:ff:87:65:c6:b5:1a: + c1:a7:4c:6d:22:70:21:8a:31:f2:97:74:89:09:12: + 26:1c:9e:ca:d9:12:a2:95:3c:da:e9:67:bf:08:a0: + 64:e3:d6:42:b7:45:ef:97:f4:f6:f5:d7:b5:4a:15: + 02:58:7d:98:58:4b:60:bc:cd:d7:0d:9a:13:33:53: + d1:61:f9:7a:d5:d7:78:b3:9a:33:f7:00:86:ce:1d: + 4d:94:38:af:a8:ec:78:51:70:8a:5c:10:83:51:21: + f7:11:3d:34:86:5e:e5:48:cd:97:81:82:35:4c:19: + ec:65:f6:6b:c5:05:a1:ee:47:13:d6:b3:21:27:94: + 10:0a:d9:24:3b:ba:be:44:13:46:30:3f:97:3c:d8: + d7:d7:6a:ee:3b:38:e3:2b:d4:97:0e:b9:1b:e7:07: + 49:7f:37:2a:f9:77:78:cf:54:ed:5b:46:9d:a3:80: + 0e:91:43:c1:d6:5b:5f:14:ba:9f:a6:8d:24:47:40: + 59:bf:72:38:b2:36:6c:37:ff:99:d1:5d:0e:59:0a: + ab:69:f7:c0:b2:04:45:7a:54:00:ae:be:53:f6:b5: + e7:e1:f8:3c:a3:31:d2:a9:fe:21:52:64:c5:a6:67: + f0:75:07:06:94:14:81:55:c6:27:e4:01:8f:17:c1: + 6a:71:d7:be:4b:fb:94:58:7d:7e:11:33:b1:42:f7: + 62:6c:18:d6:cf:09:68:3e:7f:6c:f6:1e:8f:62:ad: + a5:63:db:09:a7:1f:22:42:41:1e:6f:99:8a:3e:d7: + f9:3f:40:7a:79:b0:a5:01:92:d2:9d:3d:08:15:a5: + 10:01:2d:b3:32:76:a8:95:0d:b3:7a:9a:fb:07:10: + 78:11:6f:e1:8f:c7:ba:0f:25:1a:74:2a:e5:1c:98: + 41:99:df:21:87:e8:95:06:6a:0a:b3:6a:47:76:65: + f6:3a:cf:8f:62:17:19:7b:0a:28:cd:1a:d2:83:1e: + 21:c7:2c:bf:be:ff:61:68:b7:67:1b:bb:78:4d:8d: + ce:67:e5:e4:c1:8e:b7:23:66:e2:9d:90:75:34:98: + a9:36:2b:8a:9a:94:b9:9d:ec:cc:8a:b1:f8:25:89: + 5c:5a:b6:2f:8c:1f:6d:79:24:a7:52:68:c3:84:35: + e2:66:8d:63:0e:25:4d:d5:19:b2:e6:79:37:a7:22: + 9d:54:31 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1E:0C:F7:B6:67:F2:E1:92:26:09:45:C0:55:39:2E:77:3F:42:4A:A2 + X509v3 Basic Constraints: + CA:TRUE + setCext-hashedRoot: + 0/0-...0...+......0...g*.....E... +V|.[x....S..... + Signature Algorithm: sha1WithRSAEncryption + 09:b3:83:53:59:01:3e:95:49:b9:f1:81:ba:f9:76:20:23:b5: + 27:60:74:d4:6a:99:34:5e:6c:00:53:d9:9f:f2:a6:b1:24:07: + 44:6a:2a:c6:a5:8e:78:12:e8:47:d9:58:1b:13:2a:5e:79:9b: + 9f:0a:2a:67:a6:25:3f:06:69:56:73:c3:8a:66:48:fb:29:81: + 57:74:06:ca:9c:ea:28:e8:38:67:26:2b:f1:d5:b5:3f:65:93: + f8:36:5d:8e:8d:8d:40:20:87:19:ea:ef:27:c0:3d:b4:39:0f: + 25:7b:68:50:74:55:9c:0c:59:7d:5a:3d:41:94:25:52:08:e0: + 47:2c:15:31:19:d5:bf:07:55:c6:bb:12:b5:97:f4:5f:83:85: + ba:71:c1:d9:6c:81:11:76:0a:0a:b0:bf:82:97:f7:ea:3d:fa: + fa:ec:2d:a9:28:94:3b:56:dd:d2:51:2e:ae:c0:bd:08:15:8c: + 77:52:34:96:d6:9b:ac:d3:1d:8e:61:0f:35:7b:9b:ae:39:69: + 0b:62:60:40:20:36:8f:af:fb:36:ee:2d:08:4a:1d:b8:bf:9b: + 5c:f8:ea:a5:1b:a0:73:a6:d8:f8:6e:e0:33:04:5f:68:aa:27: + 87:ed:d9:c1:90:9c:ed:bd:e3:6a:35:af:63:df:ab:18:d9:ba: + e6:e9:4a:ea:50:8a:0f:61:93:1e:e2:2d:19:e2:30:94:35:92: + 5d:0e:b6:07:af:19:80:8f:47:90:51:4b:2e:4d:dd:85:e2:d2: + 0a:52:0a:17:9a:fc:1a:b0:50:02:e5:01:a3:63:37:21:4c:44: + c4:9b:51:99:11:0e:73:9c:06:8f:54:2e:a7:28:5e:44:39:87: + 56:2d:37:bd:85:44:94:e1:0c:4b:2c:9c:c3:92:85:34:61:cb: + 0f:b8:9b:4a:43:52:fe:34:3a:7d:b8:e9:29:dc:76:a9:c8:30: + f8:14:71:80:c6:1e:36:48:74:22:41:5c:87:82:e8:18:71:8b: + 41:89:44:e7:7e:58:5b:a8:b8:8d:13:e9:a7:6c:c3:47:ed:b3: + 1a:9d:62:ae:8d:82:ea:94:9e:dd:59:10:c3:ad:dd:e2:4d:e3: + 31:d5:c7:ec:e8:f2:b0:fe:92:1e:16:0a:1a:fc:d9:f3:f8:27: + b6:c9:be:1d:b4:6c:64:90:7f:f4:e4:c4:5b:d7:37:ae:42:0e: + dd:a4:1a:6f:7c:88:54:c5:16:6e:e1:7a:68:2e:f8:3a:bf:0d: + a4:3c:89:3b:78:a7:4e:63:83:04:21:08:67:8d:f2:82:49:d0: + 5b:fd:b1:cd:0f:83:84:d4:3e:20:85:f7:4a:3d:2b:9c:fd:2a: + 0a:09:4d:ea:81:f8:11:9c +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw +IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL +SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH +SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh +ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X +DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 +TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ +fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA +sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU +WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS +nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH +dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip +NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC +AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF +MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB +uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl +PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP +JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ +gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 +j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 +5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB +o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS +/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z +Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE +W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D +hNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +certSIGN ROOT CA +# Issuer: OU=certSIGN ROOT CA,O=certSIGN,C=RO +# Serial Number:20:06:05:16:70:02 +# Subject: OU=certSIGN ROOT CA,O=certSIGN,C=RO +# Not Valid Before: Tue Jul 04 17:20:04 2006 +# Not Valid After : Fri Jul 04 17:20:04 2031 +# Fingerprint (MD5): 18:98:C0:D6:E9:3A:FC:F9:B0:F5:0C:F7:4B:01:44:17 +# Fingerprint (SHA1): FA:B7:EE:36:97:26:62:FB:2D:B0:2A:F6:BF:03:FD:E8:7C:4B:2F:9B +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=18:98:C0:D6:E9:3A:FC:F9:B0:F5:0C:F7:4B:01:44:17 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 35210227249154 (0x200605167002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=RO, O=certSIGN, OU=certSIGN ROOT CA + Validity + Not Before: Jul 4 17:20:04 2006 GMT + Not After : Jul 4 17:20:04 2031 GMT + Subject: C=RO, O=certSIGN, OU=certSIGN ROOT CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b7:33:b9:7e:c8:25:4a:8e:b5:db:b4:28:1b:aa: + 57:90:e8:d1:22:d3:64:ba:d3:93:e8:d4:ac:86:61: + 40:6a:60:57:68:54:84:4d:bc:6a:54:02:05:ff:df: + 9b:9a:2a:ae:5d:07:8f:4a:c3:28:7f:ef:fb:2b:fa: + 79:f1:c7:ad:f0:10:53:24:90:8b:66:c9:a8:88:ab: + af:5a:a3:00:e9:be:ba:46:ee:5b:73:7b:2c:17:82: + 81:5e:62:2c:a1:02:65:b3:bd:c5:2b:00:7e:c4:fc: + 03:33:57:0d:ed:e2:fa:ce:5d:45:d6:38:cd:35:b6: + b2:c1:d0:9c:81:4a:aa:e4:b2:01:5c:1d:8f:5f:99: + c4:b1:ad:db:88:21:eb:90:08:82:80:f3:30:a3:43: + e6:90:82:ae:55:28:49:ed:5b:d7:a9:10:38:0e:fe: + 8f:4c:5b:9b:46:ea:41:f5:b0:08:74:c3:d0:88:33: + b6:7c:d7:74:df:dc:84:d1:43:0e:75:39:a1:25:40: + 28:ea:78:cb:0e:2c:2e:39:9d:8c:8b:6e:16:1c:2f: + 26:82:10:e2:e3:65:94:0a:04:c0:5e:f7:5d:5b:f8: + 10:e2:d0:ba:7a:4b:fb:de:37:00:00:1a:5b:28:e3: + d2:9c:73:3e:32:87:98:a1:c9:51:2f:d7:de:ac:33: + b3:4f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Non Repudiation, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + E0:8C:9B:DB:25:49:B3:F1:7C:86:D6:B2:42:87:0B:D0:6B:A0:D9:E4 + Signature Algorithm: sha1WithRSAEncryption + 3e:d2:1c:89:2e:35:fc:f8:75:dd:e6:7f:65:88:f4:72:4c:c9: + 2c:d7:32:4e:f3:dd:19:79:47:bd:8e:3b:5b:93:0f:50:49:24: + 13:6b:14:06:72:ef:09:d3:a1:a1:e3:40:84:c9:e7:18:32:74: + 3c:48:6e:0f:9f:4b:d4:f7:1e:d3:93:86:64:54:97:63:72:50: + d5:55:cf:fa:20:93:02:a2:9b:c3:23:93:4e:16:55:76:a0:70: + 79:6d:cd:21:1f:cf:2f:2d:bc:19:e3:88:31:f8:59:1a:81:09: + c8:97:a6:74:c7:60:c4:5b:cc:57:8e:b2:75:fd:1b:02:09:db: + 59:6f:72:93:69:f7:31:41:d6:88:38:bf:87:b2:bd:16:79:f9: + aa:e4:be:88:25:dd:61:27:23:1c:b5:31:07:04:36:b4:1a:90: + bd:a0:74:71:50:89:6d:bc:14:e3:0f:86:ae:f1:ab:3e:c7:a0: + 09:cc:a3:48:d1:e0:db:64:e7:92:b5:cf:af:72:43:70:8b:f9: + c3:84:3c:13:aa:7e:92:9b:57:53:93:fa:70:c2:91:0e:31:f9: + 9b:67:5d:e9:96:38:5e:5f:b3:73:4e:88:15:67:de:9e:76:10: + 62:20:be:55:69:95:43:00:39:4d:f6:ee:b0:5a:4e:49:44:54: + 58:5f:42:83 +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT +AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD +QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP +MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do +0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ +UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d +RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ +OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv +JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C +AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O +BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ +LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY +MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ +44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I +Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw +i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN +9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G3 +# Issuer: CN=GeoTrust Primary Certification Authority - G3,OU=(c) 2008 GeoTrust Inc. - For authorized use only,O=GeoTrust Inc.,C=US +# Serial Number:15:ac:6e:94:19:b2:79:4b:41:f6:27:a9:c3:18:0f:1f +# Subject: CN=GeoTrust Primary Certification Authority - G3,OU=(c) 2008 GeoTrust Inc. - For authorized use only,O=GeoTrust Inc.,C=US +# Not Valid Before: Wed Apr 02 00:00:00 2008 +# Not Valid After : Tue Dec 01 23:59:59 2037 +# Fingerprint (MD5): B5:E8:34:36:C9:10:44:58:48:70:6D:2E:83:D4:B8:05 +# Fingerprint (SHA1): 03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=B5:E8:34:36:C9:10:44:58:48:70:6D:2E:83:D4:B8:05 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 15:ac:6e:94:19:b2:79:4b:41:f6:27:a9:c3:18:0f:1f + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=GeoTrust Inc., OU=(c) 2008 GeoTrust Inc. - For authorized use only, CN=GeoTrust Primary Certification Authority - G3 + Validity + Not Before: Apr 2 00:00:00 2008 GMT + Not After : Dec 1 23:59:59 2037 GMT + Subject: C=US, O=GeoTrust Inc., OU=(c) 2008 GeoTrust Inc. - For authorized use only, CN=GeoTrust Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:dc:e2:5e:62:58:1d:33:57:39:32:33:fa:eb:cb: + 87:8c:a7:d4:4a:dd:06:88:ea:64:8e:31:98:a5:38: + 90:1e:98:cf:2e:63:2b:f0:46:bc:44:b2:89:a1:c0: + 28:0c:49:70:21:95:9f:64:c0:a6:93:12:02:65:26: + 86:c6:a5:89:f0:fa:d7:84:a0:70:af:4f:1a:97:3f: + 06:44:d5:c9:eb:72:10:7d:e4:31:28:fb:1c:61:e6: + 28:07:44:73:92:22:69:a7:03:88:6c:9d:63:c8:52: + da:98:27:e7:08:4c:70:3e:b4:c9:12:c1:c5:67:83: + 5d:33:f3:03:11:ec:6a:d0:53:e2:d1:ba:36:60:94: + 80:bb:61:63:6c:5b:17:7e:df:40:94:1e:ab:0d:c2: + 21:28:70:88:ff:d6:26:6c:6c:60:04:25:4e:55:7e: + 7d:ef:bf:94:48:de:b7:1d:dd:70:8d:05:5f:88:a5: + 9b:f2:c2:ee:ea:d1:40:41:6d:62:38:1d:56:06:c5: + 03:47:51:20:19:fc:7b:10:0b:0e:62:ae:76:55:bf: + 5f:77:be:3e:49:01:53:3d:98:25:03:76:24:5a:1d: + b4:db:89:ea:79:e5:b6:b3:3b:3f:ba:4c:28:41:7f: + 06:ac:6a:8e:c1:d0:f6:05:1d:7d:e6:42:86:e3:a5: + d5:47 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + C4:79:CA:8E:A1:4E:03:1D:1C:DC:6B:DB:31:5B:94:3E:3F:30:7F:2D + Signature Algorithm: sha256WithRSAEncryption + 2d:c5:13:cf:56:80:7b:7a:78:bd:9f:ae:2c:99:e7:ef:da:df: + 94:5e:09:69:a7:e7:6e:68:8c:bd:72:be:47:a9:0e:97:12:b8: + 4a:f1:64:d3:39:df:25:34:d4:c1:cd:4e:81:f0:0f:04:c4:24: + b3:34:96:c6:a6:aa:30:df:68:61:73:d7:f9:8e:85:89:ef:0e: + 5e:95:28:4a:2a:27:8f:10:8e:2e:7c:86:c4:02:9e:da:0c:77: + 65:0e:44:0d:92:fd:fd:b3:16:36:fa:11:0d:1d:8c:0e:07:89: + 6a:29:56:f7:72:f4:dd:15:9c:77:35:66:57:ab:13:53:d8:8e: + c1:40:c5:d7:13:16:5a:72:c7:b7:69:01:c4:7a:b1:83:01:68: + 7d:8d:41:a1:94:18:c1:25:5c:fc:f0:fe:83:02:87:7c:0d:0d: + cf:2e:08:5c:4a:40:0d:3e:ec:81:61:e6:24:db:ca:e0:0e:2d: + 07:b2:3e:56:dc:8d:f5:41:85:07:48:9b:0c:0b:cb:49:3f:7d: + ec:b7:fd:cb:8d:67:89:1a:ab:ed:bb:1e:a3:00:08:08:17:2a: + 82:5c:31:5d:46:8a:2d:0f:86:9b:74:d9:45:fb:d4:40:b1:7a: + aa:68:2d:86:b2:99:22:e1:c1:2b:c7:9c:f8:f3:5f:a8:82:12: + eb:19:11:2d +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB +mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT +MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ +BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 +BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz ++uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm +hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn +5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W +JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL +DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC +huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB +AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB +zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN +kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH +SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G +spki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +thawte Primary Root CA - G2 +# Issuer: CN=thawte Primary Root CA - G2,OU="(c) 2007 thawte, Inc. - For authorized use only",O="thawte, Inc.",C=US +# Serial Number:35:fc:26:5c:d9:84:4f:c9:3d:26:3d:57:9b:ae:d7:56 +# Subject: CN=thawte Primary Root CA - G2,OU="(c) 2007 thawte, Inc. - For authorized use only",O="thawte, Inc.",C=US +# Not Valid Before: Mon Nov 05 00:00:00 2007 +# Not Valid After : Mon Jan 18 23:59:59 2038 +# Fingerprint (MD5): 74:9D:EA:60:24:C4:FD:22:53:3E:CC:3A:72:D9:29:4F +# Fingerprint (SHA1): AA:DB:BC:22:23:8F:C4:01:A1:27:BB:38:DD:F4:1D:DB:08:9E:F0:12 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=74:9D:EA:60:24:C4:FD:22:53:3E:CC:3A:72:D9:29:4F +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 35:fc:26:5c:d9:84:4f:c9:3d:26:3d:57:9b:ae:d7:56 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=thawte, Inc., OU=(c) 2007 thawte, Inc. - For authorized use only, CN=thawte Primary Root CA - G2 + Validity + Not Before: Nov 5 00:00:00 2007 GMT + Not After : Jan 18 23:59:59 2038 GMT + Subject: C=US, O=thawte, Inc., OU=(c) 2007 thawte, Inc. - For authorized use only, CN=thawte Primary Root CA - G2 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:a2:d5:9c:82:7b:95:9d:f1:52:78:87:fe:8a:16: + bf:05:e6:df:a3:02:4f:0d:07:c6:00:51:ba:0c:02: + 52:2d:22:a4:42:39:c4:fe:8f:ea:c9:c1:be:d4:4d: + ff:9f:7a:9e:e2:b1:7c:9a:ad:a7:86:09:73:87:d1: + e7:9a:e3:7a:a5:aa:6e:fb:ba:b3:70:c0:67:88:a2: + 35:d4:a3:9a:b1:fd:ad:c2:ef:31:fa:a8:b9:f3:fb: + 08:c6:91:d1:fb:29:95 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 9A:D8:00:30:00:E7:6B:7F:85:18:EE:8B:B6:CE:8A:0C:F8:11:E1:BB + Signature Algorithm: ecdsa-with-SHA384 + 30:66:02:31:00:dd:f8:e0:57:47:5b:a7:e6:0a:c3:bd:f5:80: + 8a:97:35:0d:1b:89:3c:54:86:77:28:ca:a1:f4:79:de:b5:e6: + 38:b0:f0:65:70:8c:7f:02:54:c2:bf:ff:d8:a1:3e:d9:cf:02: + 31:00:c4:8d:94:fc:dc:53:d2:dc:9d:78:16:1f:15:33:23:53: + 52:e3:5a:31:5d:9d:ca:ae:bd:13:29:44:0d:27:5b:a8:e7:68: + 9c:12:f7:58:3f:2e:72:02:57:a3:8f:a1:14:2e +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp +IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi +BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw +MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig +YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v +dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ +BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 +papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K +DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 +KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox +XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +thawte Primary Root CA - G3 +# Issuer: CN=thawte Primary Root CA - G3,OU="(c) 2008 thawte, Inc. - For authorized use only",OU=Certification Services Division,O="thawte, Inc.",C=US +# Serial Number:60:01:97:b7:46:a7:ea:b4:b4:9a:d6:4b:2f:f7:90:fb +# Subject: CN=thawte Primary Root CA - G3,OU="(c) 2008 thawte, Inc. - For authorized use only",OU=Certification Services Division,O="thawte, Inc.",C=US +# Not Valid Before: Wed Apr 02 00:00:00 2008 +# Not Valid After : Tue Dec 01 23:59:59 2037 +# Fingerprint (MD5): FB:1B:5D:43:8A:94:CD:44:C6:76:F2:43:4B:47:E7:31 +# Fingerprint (SHA1): F1:8B:53:8D:1B:E9:03:B6:A6:F0:56:43:5B:17:15:89:CA:F3:6B:F2 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=FB:1B:5D:43:8A:94:CD:44:C6:76:F2:43:4B:47:E7:31 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 60:01:97:b7:46:a7:ea:b4:b4:9a:d6:4b:2f:f7:90:fb + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=thawte, Inc., OU=Certification Services Division, OU=(c) 2008 thawte, Inc. - For authorized use only, CN=thawte Primary Root CA - G3 + Validity + Not Before: Apr 2 00:00:00 2008 GMT + Not After : Dec 1 23:59:59 2037 GMT + Subject: C=US, O=thawte, Inc., OU=Certification Services Division, OU=(c) 2008 thawte, Inc. - For authorized use only, CN=thawte Primary Root CA - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b2:bf:27:2c:fb:db:d8:5b:dd:78:7b:1b:9e:77: + 66:81:cb:3e:bc:7c:ae:f3:a6:27:9a:34:a3:68:31: + 71:38:33:62:e4:f3:71:66:79:b1:a9:65:a3:a5:8b: + d5:8f:60:2d:3f:42:cc:aa:6b:32:c0:23:cb:2c:41: + dd:e4:df:fc:61:9c:e2:73:b2:22:95:11:43:18:5f: + c4:b6:1f:57:6c:0a:05:58:22:c8:36:4c:3a:7c:a5: + d1:cf:86:af:88:a7:44:02:13:74:71:73:0a:42:59: + 02:f8:1b:14:6b:42:df:6f:5f:ba:6b:82:a2:9d:5b: + e7:4a:bd:1e:01:72:db:4b:74:e8:3b:7f:7f:7d:1f: + 04:b4:26:9b:e0:b4:5a:ac:47:3d:55:b8:d7:b0:26: + 52:28:01:31:40:66:d8:d9:24:bd:f6:2a:d8:ec:21: + 49:5c:9b:f6:7a:e9:7f:55:35:7e:96:6b:8d:93:93: + 27:cb:92:bb:ea:ac:40:c0:9f:c2:f8:80:cf:5d:f4: + 5a:dc:ce:74:86:a6:3e:6c:0b:53:ca:bd:92:ce:19: + 06:72:e6:0c:5c:38:69:c7:04:d6:bc:6c:ce:5b:f6: + f7:68:9c:dc:25:15:48:88:a1:e9:a9:f8:98:9c:e0: + f3:d5:31:28:61:11:6c:67:96:8d:39:99:cb:c2:45: + 24:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + AD:6C:AA:94:60:9C:ED:E4:FF:FA:3E:0A:74:2B:63:03:F7:B6:59:BF + Signature Algorithm: sha256WithRSAEncryption + 1a:40:d8:95:65:ac:09:92:89:c6:39:f4:10:e5:a9:0e:66:53: + 5d:78:de:fa:24:91:bb:e7:44:51:df:c6:16:34:0a:ef:6a:44: + 51:ea:2b:07:8a:03:7a:c3:eb:3f:0a:2c:52:16:a0:2b:43:b9: + 25:90:3f:70:a9:33:25:6d:45:1a:28:3b:27:cf:aa:c3:29:42: + 1b:df:3b:4c:c0:33:34:5b:41:88:bf:6b:2b:65:af:28:ef:b2: + f5:c3:aa:66:ce:7b:56:ee:b7:c8:cb:67:c1:c9:9c:1a:18:b8: + c4:c3:49:03:f1:60:0e:50:cd:46:c5:f3:77:79:f7:b6:15:e0: + 38:db:c7:2f:28:a0:0c:3f:77:26:74:d9:25:12:da:31:da:1a: + 1e:dc:29:41:91:22:3c:69:a7:bb:02:f2:b6:5c:27:03:89:f4: + 06:ea:9b:e4:72:82:e3:a1:09:c1:e9:00:19:d3:3e:d4:70:6b: + ba:71:a6:aa:58:ae:f4:bb:e9:6c:b6:ef:87:cc:9b:bb:ff:39: + e6:56:61:d3:0a:a7:c4:5c:4c:60:7b:05:77:26:7a:bf:d8:07: + 52:2c:62:f7:70:63:d9:39:bc:6f:1c:c2:79:dc:76:29:af:ce: + c5:2c:64:04:5e:88:36:6e:31:d4:40:1a:62:34:36:3f:35:01: + ae:ac:63:a0 +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB +rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV +BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa +Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl +LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u +MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm +gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 +YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf +b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 +9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S +zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk +OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA +2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW +oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c +KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM +m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu +MdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G2 +# Issuer: CN=GeoTrust Primary Certification Authority - G2,OU=(c) 2007 GeoTrust Inc. - For authorized use only,O=GeoTrust Inc.,C=US +# Serial Number:3c:b2:f4:48:0a:00:e2:fe:eb:24:3b:5e:60:3e:c3:6b +# Subject: CN=GeoTrust Primary Certification Authority - G2,OU=(c) 2007 GeoTrust Inc. - For authorized use only,O=GeoTrust Inc.,C=US +# Not Valid Before: Mon Nov 05 00:00:00 2007 +# Not Valid After : Mon Jan 18 23:59:59 2038 +# Fingerprint (MD5): 01:5E:D8:6B:BD:6F:3D:8E:A1:31:F8:12:E0:98:73:6A +# Fingerprint (SHA1): 8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=01:5E:D8:6B:BD:6F:3D:8E:A1:31:F8:12:E0:98:73:6A +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 3c:b2:f4:48:0a:00:e2:fe:eb:24:3b:5e:60:3e:c3:6b + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=GeoTrust Inc., OU=(c) 2007 GeoTrust Inc. - For authorized use only, CN=GeoTrust Primary Certification Authority - G2 + Validity + Not Before: Nov 5 00:00:00 2007 GMT + Not After : Jan 18 23:59:59 2038 GMT + Subject: C=US, O=GeoTrust Inc., OU=(c) 2007 GeoTrust Inc. - For authorized use only, CN=GeoTrust Primary Certification Authority - G2 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:15:b1:e8:fd:03:15:43:e5:ac:eb:87:37:11:62: + ef:d2:83:36:52:7d:45:57:0b:4a:8d:7b:54:3b:3a: + 6e:5f:15:02:c0:50:a6:cf:25:2f:7d:ca:48:b8:c7: + 50:63:1c:2a:21:08:7c:9a:36:d8:0b:fe:d1:26:c5: + 58:31:30:28:25:f3:5d:5d:a3:b8:b6:a5:b4:92:ed: + 6c:2c:9f:eb:dd:43:89:a2:3c:4b:48:91:1d:50:ec: + 26:df:d6:60:2e:bd:21 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 15:5F:35:57:51:55:FB:25:B2:AD:03:69:FC:01:A3:FA:BE:11:55:D5 + Signature Algorithm: ecdsa-with-SHA384 + 30:64:02:30:64:96:59:a6:e8:09:de:8b:ba:fa:5a:88:88:f0: + 1f:91:d3:46:a8:f2:4a:4c:02:63:fb:6c:5f:38:db:2e:41:93: + a9:0e:e6:9d:dc:31:1c:b2:a0:a7:18:1c:79:e1:c7:36:02:30: + 3a:56:af:9a:74:6c:f6:fb:83:e0:33:d3:08:5f:a1:9c:c2:5b: + 9f:46:d6:b6:cb:91:06:63:a2:06:e7:33:ac:3e:a8:81:12:d0: + cb:ba:d0:92:0b:b6:9e:96:aa:04:0f:8a +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL +MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj +KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 +MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw +NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV +BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL +So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal +tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG +CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT +qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz +rD6ogRLQy7rQkgu2npaqBA+K +-----END CERTIFICATE----- + +VeriSign Universal Root Certification Authority +# Issuer: CN=VeriSign Universal Root Certification Authority,OU="(c) 2008 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US +# Serial Number:40:1a:c4:64:21:b3:13:21:03:0e:bb:e4:12:1a:c5:1d +# Subject: CN=VeriSign Universal Root Certification Authority,OU="(c) 2008 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US +# Not Valid Before: Wed Apr 02 00:00:00 2008 +# Not Valid After : Tue Dec 01 23:59:59 2037 +# Fingerprint (MD5): 8E:AD:B5:01:AA:4D:81:E4:8C:1D:D1:E1:14:00:95:19 +# Fingerprint (SHA1): 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=8E:AD:B5:01:AA:4D:81:E4:8C:1D:D1:E1:14:00:95:19 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 40:1a:c4:64:21:b3:13:21:03:0e:bb:e4:12:1a:c5:1d + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2008 VeriSign, Inc. - For authorized use only, CN=VeriSign Universal Root Certification Authority + Validity + Not Before: Apr 2 00:00:00 2008 GMT + Not After : Dec 1 23:59:59 2037 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2008 VeriSign, Inc. - For authorized use only, CN=VeriSign Universal Root Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c7:61:37:5e:b1:01:34:db:62:d7:15:9b:ff:58: + 5a:8c:23:23:d6:60:8e:91:d7:90:98:83:7a:e6:58: + 19:38:8c:c5:f6:e5:64:85:b4:a2:71:fb:ed:bd:b9: + da:cd:4d:00:b4:c8:2d:73:a5:c7:69:71:95:1f:39: + 3c:b2:44:07:9c:e8:0e:fa:4d:4a:c4:21:df:29:61: + 8f:32:22:61:82:c5:87:1f:6e:8c:7c:5f:16:20:51: + 44:d1:70:4f:57:ea:e3:1c:e3:cc:79:ee:58:d8:0e: + c2:b3:45:93:c0:2c:e7:9a:17:2b:7b:00:37:7a:41: + 33:78:e1:33:e2:f3:10:1a:7f:87:2c:be:f6:f5:f7: + 42:e2:e5:bf:87:62:89:5f:00:4b:df:c5:dd:e4:75: + 44:32:41:3a:1e:71:6e:69:cb:0b:75:46:08:d1:ca: + d2:2b:95:d0:cf:fb:b9:40:6b:64:8c:57:4d:fc:13: + 11:79:84:ed:5e:54:f6:34:9f:08:01:f3:10:25:06: + 17:4a:da:f1:1d:7a:66:6b:98:60:66:a4:d9:ef:d2: + 2e:82:f1:f0:ef:09:ea:44:c9:15:6a:e2:03:6e:33: + d3:ac:9f:55:00:c7:f6:08:6a:94:b9:5f:dc:e0:33: + f1:84:60:f9:5b:27:11:b4:fc:16:f2:bb:56:6a:80: + 25:8d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + 1.3.6.1.5.5.7.1.12: + 0_.].[0Y0W0U..image/gif0!0.0...+..............k...j.H.,{..0%.#http://logo.verisign.com/vslogo.gif + X509v3 Subject Key Identifier: + B6:77:FA:69:48:47:9F:53:12:D5:C2:EA:07:32:76:07:D1:97:07:19 + Signature Algorithm: sha256WithRSAEncryption + 4a:f8:f8:b0:03:e6:2c:67:7b:e4:94:77:63:cc:6e:4c:f9:7d: + 0e:0d:dc:c8:b9:35:b9:70:4f:63:fa:24:fa:6c:83:8c:47:9d: + 3b:63:f3:9a:f9:76:32:95:91:b1:77:bc:ac:9a:be:b1:e4:31: + 21:c6:81:95:56:5a:0e:b1:c2:d4:b1:a6:59:ac:f1:63:cb:b8: + 4c:1d:59:90:4a:ef:90:16:28:1f:5a:ae:10:fb:81:50:38:0c: + 6c:cc:f1:3d:c3:f5:63:e3:b3:e3:21:c9:24:39:e9:fd:15:66: + 46:f4:1b:11:d0:4d:73:a3:7d:46:f9:3d:ed:a8:5f:62:d4:f1: + 3f:f8:e0:74:57:2b:18:9d:81:b4:c4:28:da:94:97:a5:70:eb: + ac:1d:be:07:11:f0:d5:db:dd:e5:8c:f0:d5:32:b0:83:e6:57: + e2:8f:bf:be:a1:aa:bf:3d:1d:b5:d4:38:ea:d7:b0:5c:3a:4f: + 6a:3f:8f:c0:66:6c:63:aa:e9:d9:a4:16:f4:81:d1:95:14:0e: + 7d:cd:95:34:d9:d2:8f:70:73:81:7b:9c:7e:bd:98:61:d8:45: + 87:98:90:c5:eb:86:30:c6:35:bf:f0:ff:c3:55:88:83:4b:ef: + 05:92:06:71:f2:b8:98:93:b7:ec:cd:82:61:f1:38:e6:4f:97: + 98:2a:5a:8d +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB +vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W +ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 +IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y +IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh +bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF +9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH +H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H +LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN +/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT +rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw +WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs +exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 +sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ +seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz +4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ +BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR +lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 +7M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G4 +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4,OU="(c) 2007 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US +# Serial Number:2f:80:fe:23:8c:0e:22:0f:48:67:12:28:91:87:ac:b3 +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4,OU="(c) 2007 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US +# Not Valid Before: Mon Nov 05 00:00:00 2007 +# Not Valid After : Mon Jan 18 23:59:59 2038 +# Fingerprint (MD5): 3A:52:E1:E7:FD:6F:3A:E3:6F:F3:6F:99:1B:F9:22:41 +# Fingerprint (SHA1): 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +============================================================ +MD5 Fingerprint=3A:52:E1:E7:FD:6F:3A:E3:6F:F3:6F:99:1B:F9:22:41 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 2f:80:fe:23:8c:0e:22:0f:48:67:12:28:91:87:ac:b3 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2007 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G4 + Validity + Not Before: Nov 5 00:00:00 2007 GMT + Not After : Jan 18 23:59:59 2038 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2007 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G4 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:a7:56:7a:7c:52:da:64:9b:0e:2d:5c:d8:5e:ac: + 92:3d:fe:01:e6:19:4a:3d:14:03:4b:fa:60:27:20: + d9:83:89:69:fa:54:c6:9a:18:5e:55:2a:64:de:06: + f6:8d:4a:3b:ad:10:3c:65:3d:90:88:04:89:e0:30: + 61:b3:ae:5d:01:a7:7b:de:7c:b2:be:ca:65:61:00: + 86:ae:da:8f:7b:d0:89:ad:4d:1d:59:9a:41:b1:bc: + 47:80:dc:9e:62:c3:f9 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + 1.3.6.1.5.5.7.1.12: + 0_.].[0Y0W0U..image/gif0!0.0...+..............k...j.H.,{..0%.#http://logo.verisign.com/vslogo.gif + X509v3 Subject Key Identifier: + B3:16:91:FD:EE:A6:6E:E4:B5:2E:49:8F:87:78:81:80:EC:E5:B1:B5 + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:30:66:21:0c:18:26:60:5a:38:7b:56:42:e0:a7:fc: + 36:84:51:91:20:2c:76:4d:43:3d:c4:1d:84:23:d0:ac:d6:7c: + 35:06:ce:cd:69:bd:90:0d:db:6c:48:42:1d:0e:aa:42:02:31: + 00:9c:3d:48:39:23:39:58:1a:15:12:59:6a:9e:ef:d5:59:b2: + 1d:52:2c:99:71:cd:c7:29:df:1b:2a:61:7b:71:d1:de:f3:c0: + e5:0d:3a:4a:aa:2d:a7:d8:86:2a:dd:2e:10 +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp +U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg +SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln +biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm +GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve +fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ +aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj +aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW +kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC +4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga +FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----END CERTIFICATE----- + +NetLock Arany (Class Gold) Főtanúsítvány +# Issuer: CN=NetLock Arany (Class Gold) F..tan..s..tv..ny,OU=Tan..s..tv..nykiad..k (Certification Services),O=NetLock Kft.,L=Budapest,C=HU +# Serial Number:49:41:2c:e4:00:10 +# Subject: CN=NetLock Arany (Class Gold) F..tan..s..tv..ny,OU=Tan..s..tv..nykiad..k (Certification Services),O=NetLock Kft.,L=Budapest,C=HU +# Not Valid Before: Thu Dec 11 15:08:21 2008 +# Not Valid After : Wed Dec 06 15:08:21 2028 +# Fingerprint (MD5): C5:A1:B7:FF:73:DD:D6:D7:34:32:18:DF:FC:3C:AD:88 +# Fingerprint (SHA1): 06:08:3F:59:3F:15:A1:04:A0:69:A4:6B:A9:03:D0:06:B7:97:09:91 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=C5:A1:B7:FF:73:DD:D6:D7:34:32:18:DF:FC:3C:AD:88 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 80544274841616 (0x49412ce40010) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=HU, L=Budapest, O=NetLock Kft., OU=Tan\xC3\xBAs\xC3\xADtv\xC3\xA1nykiad\xC3\xB3k (Certification Services), CN=NetLock Arany (Class Gold) F\xC5\x91tan\xC3\xBAs\xC3\xADtv\xC3\xA1ny + Validity + Not Before: Dec 11 15:08:21 2008 GMT + Not After : Dec 6 15:08:21 2028 GMT + Subject: C=HU, L=Budapest, O=NetLock Kft., OU=Tan\xC3\xBAs\xC3\xADtv\xC3\xA1nykiad\xC3\xB3k (Certification Services), CN=NetLock Arany (Class Gold) F\xC5\x91tan\xC3\xBAs\xC3\xADtv\xC3\xA1ny + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c4:24:5e:73:be:4b:6d:14:c3:a1:f4:e3:97:90: + 6e:d2:30:45:1e:3c:ee:67:d9:64:e0:1a:8a:7f:ca: + 30:ca:83:e3:20:c1:e3:f4:3a:d3:94:5f:1a:7c:5b: + 6d:bf:30:4f:84:27:f6:9f:1f:49:bc:c6:99:0a:90: + f2:0f:f5:7f:43:84:37:63:51:8b:7a:a5:70:fc:7a: + 58:cd:8e:9b:ed:c3:46:6c:84:70:5d:da:f3:01:90: + 23:fc:4e:30:a9:7e:e1:27:63:e7:ed:64:3c:a0:b8: + c9:33:63:fe:16:90:ff:b0:b8:fd:d7:a8:c0:c0:94: + 43:0b:b6:d5:59:a6:9e:56:d0:24:1f:70:79:af:db: + 39:54:0d:65:75:d9:15:41:94:01:af:5e:ec:f6:8d: + f1:ff:ad:64:fe:20:9a:d7:5c:eb:fe:a6:1f:08:64: + a3:8b:76:55:ad:1e:3b:28:60:2e:87:25:e8:aa:af: + 1f:c6:64:46:20:b7:70:7f:3c:de:48:db:96:53:b7: + 39:77:e4:1a:e2:c7:16:84:76:97:5b:2f:bb:19:15: + 85:f8:69:85:f5:99:a7:a9:f2:34:a7:a9:b6:a6:03: + fc:6f:86:3d:54:7c:76:04:9b:6b:f9:40:5d:00:34: + c7:2e:99:75:9d:e5:88:03:aa:4d:f8:03:d2:42:76: + c0:1b + Exponent: 43147 (0xa88b) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:4 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + CC:FA:67:93:F0:B6:B8:D0:A5:C0:1E:F3:53:FD:8C:53:DF:83:D7:96 + Signature Algorithm: sha256WithRSAEncryption + ab:7f:ee:1c:16:a9:9c:3c:51:00:a0:c0:11:08:05:a7:99:e6: + 6f:01:88:54:61:6e:f1:b9:18:ad:4a:ad:fe:81:40:23:94:2f: + fb:75:7c:2f:28:4b:62:24:81:82:0b:f5:61:f1:1c:6e:b8:61: + 38:eb:81:fa:62:a1:3b:5a:62:d3:94:65:c4:e1:e6:6d:82:f8: + 2f:25:70:b2:21:26:c1:72:51:1f:8c:2c:c3:84:90:c3:5a:8f: + ba:cf:f4:a7:65:a5:eb:98:d1:fb:05:b2:46:75:15:23:6a:6f: + 85:63:30:80:f0:d5:9e:1f:29:1c:c2:6c:b0:50:59:5d:90:5b: + 3b:a8:0d:30:cf:bf:7d:7f:ce:f1:9d:83:bd:c9:46:6e:20:a6: + f9:61:51:ba:21:2f:7b:be:a5:15:63:a1:d4:95:87:f1:9e:b9: + f3:89:f3:3d:85:b8:b8:db:be:b5:b9:29:f9:da:37:05:00:49: + 94:03:84:44:e7:bf:43:31:cf:75:8b:25:d1:f4:a6:64:f5:92: + f6:ab:05:eb:3d:e9:a5:0b:36:62:da:cc:06:5f:36:8b:b6:5e: + 31:b8:2a:fb:5e:f6:71:df:44:26:9e:c4:e6:0d:91:b4:2e:75: + 95:80:51:6a:4b:30:a6:b0:62:a1:93:f1:9b:d8:ce:c4:63:75: + 3f:59:47:b1 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG +EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 +MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR +dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB +pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM +b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm +aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz +IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT +lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz +AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 +VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG +ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 +BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG +AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M +U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh +bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C ++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F +uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 +XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA - G2 +# Issuer: CN=Staat der Nederlanden Root CA - G2,O=Staat der Nederlanden,C=NL +# Serial Number: 10000012 (0x98968c) +# Subject: CN=Staat der Nederlanden Root CA - G2,O=Staat der Nederlanden,C=NL +# Not Valid Before: Wed Mar 26 11:18:17 2008 +# Not Valid After : Wed Mar 25 11:03:10 2020 +# Fingerprint (MD5): 7C:A5:0F:F8:5B:9A:7D:6D:30:AE:54:5A:E3:42:A2:8A +# Fingerprint (SHA1): 59:AF:82:79:91:86:C7:B4:75:07:CB:CF:03:57:46:EB:04:DD:B7:16 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=7C:A5:0F:F8:5B:9A:7D:6D:30:AE:54:5A:E3:42:A2:8A +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 10000012 (0x98968c) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Root CA - G2 + Validity + Not Before: Mar 26 11:18:17 2008 GMT + Not After : Mar 25 11:03:10 2020 GMT + Subject: C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Root CA - G2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:c5:59:e7:6f:75:aa:3e:4b:9c:b5:b8:ac:9e:0b: + e4:f9:d9:ca:ab:5d:8f:b5:39:10:82:d7:af:51:e0: + 3b:e1:00:48:6a:cf:da:e1:06:43:11:99:aa:14:25: + 12:ad:22:e8:00:6d:43:c4:a9:b8:e5:1f:89:4b:67: + bd:61:48:ef:fd:d2:e0:60:88:e5:b9:18:60:28:c3: + 77:2b:ad:b0:37:aa:37:de:64:59:2a:46:57:e4:4b: + b9:f8:37:7c:d5:36:e7:80:c1:b6:f3:d4:67:9b:96: + e8:ce:d7:c6:0a:53:d0:6b:49:96:f3:a3:0b:05:77: + 48:f7:25:e5:70:ac:30:14:20:25:e3:7f:75:5a:e5: + 48:f8:4e:7b:03:07:04:fa:82:61:87:6e:f0:3b:c4: + a4:c7:d0:f5:74:3e:a5:5d:1a:08:f2:9b:25:d2:f6: + ac:04:26:3e:55:3a:62:28:a5:7b:b2:30:af:f8:37: + c2:d1:ba:d6:38:fd:f4:ef:49:30:37:99:26:21:48: + 85:01:a9:e5:16:e7:dc:90:55:df:0f:e8:38:cd:99: + 37:21:4f:5d:f5:22:6f:6a:c5:12:16:60:17:55:f2: + 65:66:a6:a7:30:91:38:c1:38:1d:86:04:84:ba:1a: + 25:78:5e:9d:af:cc:50:60:d6:13:87:52:ed:63:1f: + 6d:65:7d:c2:15:18:74:ca:e1:7e:64:29:8c:72:d8: + 16:13:7d:0b:49:4a:f1:28:1b:20:74:6b:c5:3d:dd: + b0:aa:48:09:3d:2e:82:94:cd:1a:65:d9:2b:88:9a: + 99:bc:18:7e:9f:ee:7d:66:7c:3e:bd:94:b8:81:ce: + cd:98:30:78:c1:6f:67:d0:be:5f:e0:68:ed:de:e2: + b1:c9:2c:59:78:92:aa:df:2b:60:63:f2:e5:5e:b9: + e3:ca:fa:7f:50:86:3e:a2:34:18:0c:09:68:28:11: + 1c:e4:e1:b9:5c:3e:47:ba:32:3f:18:cc:5b:84:f5: + f3:6b:74:c4:72:74:e1:e3:8b:a0:4a:bd:8d:66:2f: + ea:ad:35:da:20:d3:88:82:61:f0:12:22:b6:bc:d0: + d5:a4:ec:af:54:88:25:24:3c:a7:6d:b1:72:29:3f: + 3e:57:a6:7f:55:af:6e:26:c6:fe:e7:cc:40:5c:51: + 44:81:0a:78:de:4a:ce:55:bf:1d:d5:d9:b7:56:ef: + f0:76:ff:0b:79:b5:af:bd:fb:a9:69:91:46:97:68: + 80:14:36:1d:b3:7f:bb:29:98:36:a5:20:fa:82:60: + 62:33:a4:ec:d6:ba:07:a7:6e:c5:cf:14:a6:e7:d6: + 92:34:d8:81:f5:fc:1d:5d:aa:5c:1e:f6:a3:4d:3b: + b8:f7:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Certificate Policies: + Policy: X509v3 Any Policy + CPS: http://www.pkioverheid.nl/policies/root-policy-G2 + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 91:68:32:87:15:1D:89:E2:B5:F1:AC:36:28:34:8D:0B:7C:62:88:EB + Signature Algorithm: sha256WithRSAEncryption + a8:41:4a:67:2a:92:81:82:50:6e:e1:d7:d8:b3:39:3b:f3:02: + 15:09:50:51:ef:2d:bd:24:7b:88:86:3b:f9:b4:bc:92:09:96: + b9:f6:c0:ab:23:60:06:79:8c:11:4e:51:d2:79:80:33:fb:9d: + 48:be:ec:41:43:81:1f:7e:47:40:1c:e5:7a:08:ca:aa:8b:75: + ad:14:c4:c2:e8:66:3c:82:07:a7:e6:27:82:5b:18:e6:0f:6e: + d9:50:3e:8a:42:18:29:c6:b4:56:fc:56:10:a0:05:17:bd:0c: + 23:7f:f4:93:ed:9c:1a:51:be:dd:45:41:bf:91:24:b4:1f:8c: + e9:5f:cf:7b:21:99:9f:95:9f:39:3a:46:1c:6c:f9:cd:7b:9c: + 90:cd:28:a9:c7:a9:55:bb:ac:62:34:62:35:13:4b:14:3a:55: + 83:b9:86:8d:92:a6:c6:f4:07:25:54:cc:16:57:12:4a:82:78: + c8:14:d9:17:82:26:2d:5d:20:1f:79:ae:fe:d4:70:16:16:95: + 83:d8:35:39:ff:52:5d:75:1c:16:c5:13:55:cf:47:cc:75:65: + 52:4a:de:f0:b0:a7:e4:0a:96:0b:fb:ad:c2:e2:25:84:b2:dd: + e4:bd:7e:59:6c:9b:f0:f0:d8:e7:ca:f2:e9:97:38:7e:89:be: + cc:fb:39:17:61:3f:72:db:3a:91:d8:65:01:19:1d:ad:50:a4: + 57:0a:7c:4b:bc:9c:71:73:2a:45:51:19:85:cc:8e:fd:47:a7: + 74:95:1d:a8:d1:af:4e:17:b1:69:26:c2:aa:78:57:5b:c5:4d: + a7:e5:9e:05:17:94:ca:b2:5f:a0:49:18:8d:34:e9:26:6c:48: + 1e:aa:68:92:05:e1:82:73:5a:9b:dc:07:5b:08:6d:7d:9d:d7: + 8d:21:d9:fc:14:20:aa:c2:45:df:3f:e7:00:b2:51:e4:c2:f8: + 05:b9:79:1a:8c:34:f3:9e:5b:e4:37:5b:6b:4a:df:2c:57:8a: + 40:5a:36:ba:dd:75:44:08:37:42:70:0c:fe:dc:5e:21:a0:a3: + 8a:c0:90:9c:68:da:50:e6:45:10:47:78:b6:4e:d2:65:c9:c3: + 37:df:e1:42:63:b0:57:37:45:2d:7b:8a:9c:bf:05:ea:65:55: + 33:f7:39:10:c5:28:2a:21:7a:1b:8a:c4:24:f9:3f:15:c8:9a: + 15:20:f5:55:62:96:ed:6d:93:50:bc:e4:aa:78:ad:d9:cb:0a: + 65:87:a6:66:c1:c4:81:a3:77:3a:58:1e:0b:ee:83:8b:9d:1e: + d2:52:a4:cc:1d:6f:b0:98:6d:94:31:b5:f8:71:0a:dc:b9:fc: + 7d:32:60:e6:eb:af:8a:01 +-----BEGIN CERTIFICATE----- +MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX +DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 +qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp +uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU +Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE +pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp +5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M +UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN +GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy +5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv +6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK +eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 +B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ +BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov +L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG +SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS +CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen +5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 +IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK +gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL ++63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL +vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm +bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk +N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC +Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z +ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== +-----END CERTIFICATE----- + +Hongkong Post Root CA 1 +# Issuer: CN=Hongkong Post Root CA 1,O=Hongkong Post,C=HK +# Serial Number: 1000 (0x3e8) +# Subject: CN=Hongkong Post Root CA 1,O=Hongkong Post,C=HK +# Not Valid Before: Thu May 15 05:13:14 2003 +# Not Valid After : Mon May 15 04:52:29 2023 +# Fingerprint (MD5): A8:0D:6F:39:78:B9:43:6D:77:42:6D:98:5A:CC:23:CA +# Fingerprint (SHA1): D6:DA:A8:20:8D:09:D2:15:4D:24:B5:2F:CB:34:6E:B2:58:B2:8A:58 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=A8:0D:6F:39:78:B9:43:6D:77:42:6D:98:5A:CC:23:CA +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1000 (0x3e8) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=HK, O=Hongkong Post, CN=Hongkong Post Root CA 1 + Validity + Not Before: May 15 05:13:14 2003 GMT + Not After : May 15 04:52:29 2023 GMT + Subject: C=HK, O=Hongkong Post, CN=Hongkong Post Root CA 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ac:ff:38:b6:e9:66:02:49:e3:a2:b4:e1:90:f9: + 40:8f:79:f9:e2:bd:79:fe:02:bd:ee:24:92:1d:22: + f6:da:85:72:69:fe:d7:3f:09:d4:dd:91:b5:02:9c: + d0:8d:5a:e1:55:c3:50:86:b9:29:26:c2:e3:d9:a0: + f1:69:03:28:20:80:45:22:2d:56:a7:3b:54:95:56: + 22:59:1f:28:df:1f:20:3d:6d:a2:36:be:23:a0:b1: + 6e:b5:b1:27:3f:39:53:09:ea:ab:6a:e8:74:b2:c2: + 65:5c:8e:bf:7c:c3:78:84:cd:9e:16:fc:f5:2e:4f: + 20:2a:08:9f:77:f3:c5:1e:c4:9a:52:66:1e:48:5e: + e3:10:06:8f:22:98:e1:65:8e:1b:5d:23:66:3b:b8: + a5:32:51:c8:86:aa:a1:a9:9e:7f:76:94:c2:a6:6c: + b7:41:f0:d5:c8:06:38:e6:d4:0c:e2:f3:3b:4c:6d: + 50:8c:c4:83:27:c1:13:84:59:3d:9e:75:74:b6:d8: + 02:5e:3a:90:7a:c0:42:36:72:ec:6a:4d:dc:ef:c4: + 00:df:13:18:57:5f:26:78:c8:d6:0a:79:77:bf:f7: + af:b7:76:b9:a5:0b:84:17:5d:10:ea:6f:e1:ab:95: + 11:5f:6d:3c:a3:5c:4d:83:5b:f2:b3:19:8a:80:8b: + 0b:87 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:3 + X509v3 Key Usage: critical + Digital Signature, Non Repudiation, Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 0e:46:d5:3c:ae:e2:87:d9:5e:81:8b:02:98:41:08:8c:4c:bc: + da:db:ee:27:1b:82:e7:6a:45:ec:16:8b:4f:85:a0:f3:b2:70: + bd:5a:96:ba:ca:6e:6d:ee:46:8b:6e:e7:2a:2e:96:b3:19:33: + eb:b4:9f:a8:b2:37:ee:98:a8:97:b6:2e:b6:67:27:d4:a6:49: + fd:1c:93:65:76:9e:42:2f:dc:22:6c:9a:4f:f2:5a:15:39:b1: + 71:d7:2b:51:e8:6d:1c:98:c0:d9:2a:f4:a1:82:7b:d5:c9:41: + a2:23:01:74:38:55:8b:0f:b9:2e:67:a2:20:04:37:da:9c:0b: + d3:17:21:e0:8f:97:79:34:6f:84:48:02:20:33:1b:e6:34:44: + 9f:91:70:f4:80:5e:84:43:c2:29:d2:6c:12:14:e4:61:8d:ac: + 10:90:9e:84:50:bb:f0:96:6f:45:9f:8a:f3:ca:6c:4f:fa:11: + 3a:15:15:46:c3:cd:1f:83:5b:2d:41:12:ed:50:67:41:13:3d: + 21:ab:94:8a:aa:4e:7c:c1:b1:fb:a7:d6:b5:27:2f:97:ab:6e: + e0:1d:e2:d1:1c:2c:1f:44:e2:fc:be:91:a1:9c:fb:d6:29:53: + 73:86:9f:53:d8:43:0e:5d:d6:63:82:71:1d:80:74:ca:f6:e2: + 02:6b:d9:5a +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx +FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg +Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG +A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr +b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ +jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn +PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh +ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 +nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h +q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED +MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC +mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 +7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB +oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs +EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO +fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi +AmvZWg== +-----END CERTIFICATE----- + +SecureSign RootCA11 +# Issuer: CN=SecureSign RootCA11,O="Japan Certification Services, Inc.",C=JP +# Serial Number: 1 (0x1) +# Subject: CN=SecureSign RootCA11,O="Japan Certification Services, Inc.",C=JP +# Not Valid Before: Wed Apr 08 04:56:47 2009 +# Not Valid After : Sun Apr 08 04:56:47 2029 +# Fingerprint (MD5): B7:52:74:E2:92:B4:80:93:F2:75:E4:CC:D7:F2:EA:26 +# Fingerprint (SHA1): 3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=B7:52:74:E2:92:B4:80:93:F2:75:E4:CC:D7:F2:EA:26 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA11 + Validity + Not Before: Apr 8 04:56:47 2009 GMT + Not After : Apr 8 04:56:47 2029 GMT + Subject: C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA11 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:fd:77:aa:a5:1c:90:05:3b:cb:4c:9b:33:8b:5a: + 14:45:a4:e7:90:16:d1:df:57:d2:21:10:a4:17:fd: + df:ac:d6:1f:a7:e4:db:7c:f7:ec:df:b8:03:da:94: + 58:fd:5d:72:7c:8c:3f:5f:01:67:74:15:96:e3:02: + 3c:87:db:ae:cb:01:8e:c2:f3:66:c6:85:45:f4:02: + c6:3a:b5:62:b2:af:fa:9c:bf:a4:e6:d4:80:30:98: + f3:0d:b6:93:8f:a9:d4:d8:36:f2:b0:fc:8a:ca:2c: + a1:15:33:95:31:da:c0:1b:f2:ee:62:99:86:63:3f: + bf:dd:93:2a:83:a8:76:b9:13:1f:b7:ce:4e:42:85: + 8f:22:e7:2e:1a:f2:95:09:b2:05:b5:44:4e:77:a1: + 20:bd:a9:f2:4e:0a:7d:50:ad:f5:05:0d:45:4f:46: + 71:fd:28:3e:53:fb:04:d8:2d:d7:65:1d:4a:1b:fa: + cf:3b:b0:31:9a:35:6e:c8:8b:06:d3:00:91:f2:94: + 08:65:4c:b1:34:06:00:7a:89:e2:f0:c7:03:59:cf: + d5:d6:e8:a7:32:b3:e6:98:40:86:c5:cd:27:12:8b: + cc:7b:ce:b7:11:3c:62:60:07:23:3e:2b:40:6e:94: + 80:09:6d:b6:b3:6f:77:6f:35:08:50:fb:02:87:c5: + 3e:89 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 5B:F8:4D:4F:B2:A5:86:D4:3A:D2:F1:63:9A:A0:BE:09:F6:57:B7:DE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + a0:a1:38:16:66:2e:a7:56:1f:21:9c:06:fa:1d:ed:b9:22:c5: + 38:26:d8:4e:4f:ec:a3:7f:79:de:46:21:a1:87:77:8f:07:08: + 9a:b2:a4:c5:af:0f:32:98:0b:7c:66:29:b6:9b:7d:25:52:49: + 43:ab:4c:2e:2b:6e:7a:70:af:16:0e:e3:02:6c:fb:42:e6:18: + 9d:45:d8:55:c8:e8:3b:dd:e7:e1:f4:2e:0b:1c:34:5c:6c:58: + 4a:fb:8c:88:50:5f:95:1c:bf:ed:ab:22:b5:65:b3:85:ba:9e: + 0f:b8:ad:e5:7a:1b:8a:50:3a:1d:bd:0d:bc:7b:54:50:0b:b9: + 42:af:55:a0:18:81:ad:65:99:ef:be:e4:9c:bf:c4:85:ab:41: + b2:54:6f:dc:25:cd:ed:78:e2:8e:0c:8d:09:49:dd:63:7b:5a: + 69:96:02:21:a8:bd:52:59:e9:7d:35:cb:c8:52:ca:7f:81:fe: + d9:6b:d3:f7:11:ed:25:df:f8:e7:f9:a4:fa:72:97:84:53:0d: + a5:d0:32:18:51:76:59:14:6c:0f:eb:ec:5f:80:8c:75:43:83: + c3:85:98:ff:4c:9e:2d:0d:e4:77:83:93:4e:b5:96:07:8b:28: + 13:9b:8c:19:8d:41:27:49:40:ee:de:e6:23:44:39:dc:a1:22: + d6:ba:03:f2 +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr +MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG +A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 +MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp +Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD +QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz +i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 +h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV +MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 +UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni +8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC +h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB +AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm +KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ +X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr +QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 +pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN +QSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA 2009 +# Issuer: E=info@e-szigno.hu,CN=Microsec e-Szigno Root CA 2009,O=Microsec Ltd.,L=Budapest,C=HU +# Serial Number:00:c2:7e:43:04:4e:47:3f:19 +# Subject: E=info@e-szigno.hu,CN=Microsec e-Szigno Root CA 2009,O=Microsec Ltd.,L=Budapest,C=HU +# Not Valid Before: Tue Jun 16 11:30:18 2009 +# Not Valid After : Sun Dec 30 11:30:18 2029 +# Fingerprint (MD5): F8:49:F4:03:BC:44:2D:83:BE:48:69:7D:29:64:FC:B1 +# Fingerprint (SHA1): 89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=F8:49:F4:03:BC:44:2D:83:BE:48:69:7D:29:64:FC:B1 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c2:7e:43:04:4e:47:3f:19 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=HU, L=Budapest, O=Microsec Ltd., CN=Microsec e-Szigno Root CA 2009/emailAddress=info@e-szigno.hu + Validity + Not Before: Jun 16 11:30:18 2009 GMT + Not After : Dec 30 11:30:18 2029 GMT + Subject: C=HU, L=Budapest, O=Microsec Ltd., CN=Microsec e-Szigno Root CA 2009/emailAddress=info@e-szigno.hu + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:e9:f8:8f:f3:63:ad:da:86:d8:a7:e0:42:fb:cf: + 91:de:a6:26:f8:99:a5:63:70:ad:9b:ae:ca:33:40: + 7d:6d:96:6e:a1:0e:44:ee:e1:13:9d:94:42:52:9a: + bd:75:85:74:2c:a8:0e:1d:93:b6:18:b7:8c:2c:a8: + cf:fb:5c:71:b9:da:ec:fe:e8:7e:8f:e4:2f:1d:b2: + a8:75:87:d8:b7:a1:e5:3b:cf:99:4a:46:d0:83:19: + 7d:c0:a1:12:1c:95:6d:4a:f4:d8:c7:a5:4d:33:2e: + 85:39:40:75:7e:14:7c:80:12:98:50:c7:41:67:b8: + a0:80:61:54:a6:6c:4e:1f:e0:9d:0e:07:e9:c9:ba: + 33:e7:fe:c0:55:28:2c:02:80:a7:19:f5:9e:dc:55: + 53:03:97:7b:07:48:ff:99:fb:37:8a:24:c4:59:cc: + 50:10:63:8e:aa:a9:1a:b0:84:1a:86:f9:5f:bb:b1: + 50:6e:a4:d1:0a:cc:d5:71:7e:1f:a7:1b:7c:f5:53: + 6e:22:5f:cb:2b:e6:d4:7c:5d:ae:d6:c2:c6:4c:e5: + 05:01:d9:ed:57:fc:c1:23:79:fc:fa:c8:24:83:95: + f3:b5:6a:51:01:d0:77:d6:e9:12:a1:f9:1a:83:fb: + 82:1b:b9:b0:97:f4:76:06:33:43:49:a0:ff:0b:b5: + fa:b5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + CB:0F:C6:DF:42:43:CC:3D:CB:B5:48:23:A1:1A:7A:A6:2A:BB:34:68 + X509v3 Authority Key Identifier: + keyid:CB:0F:C6:DF:42:43:CC:3D:CB:B5:48:23:A1:1A:7A:A6:2A:BB:34:68 + + X509v3 Subject Alternative Name: + email:info@e-szigno.hu + Signature Algorithm: sha256WithRSAEncryption + c9:d1:0e:5e:2e:d5:cc:b3:7c:3e:cb:fc:3d:ff:0d:28:95:93: + 04:c8:bf:da:cd:79:b8:43:90:f0:a4:be:ef:f2:ef:21:98:bc: + d4:d4:5d:06:f6:ee:42:ec:30:6c:a0:aa:a9:ca:f1:af:8a:fa: + 3f:0b:73:6a:3e:ea:2e:40:7e:1f:ae:54:61:79:eb:2e:08:37: + d7:23:f3:8c:9f:be:1d:b1:e1:a4:75:db:a0:e2:54:14:b1:ba: + 1c:29:a4:18:f6:12:ba:a2:14:14:e3:31:35:c8:40:ff:b7:e0: + 05:76:57:c1:1c:59:f2:f8:bf:e4:ed:25:62:5c:84:f0:7e:7e: + 1f:b3:be:f9:b7:21:11:cc:03:01:56:70:a7:10:92:1e:1b:34: + 81:1e:ad:9c:1a:c3:04:3c:ed:02:61:d6:1e:06:f3:5f:3a:87: + f2:2b:f1:45:87:e5:3d:ac:d1:c7:57:84:bd:6b:ae:dc:d8:f9: + b6:1b:62:70:0b:3d:36:c9:42:f2:32:d7:7a:61:e6:d2:db:3d: + cf:c8:a9:c9:9b:dc:db:58:44:d7:6f:38:af:7f:78:d3:a3:ad: + 1a:75:ba:1c:c1:36:7c:8f:1e:6d:1c:c3:75:46:ae:35:05:a6: + f6:5c:3d:21:ee:56:f0:c9:82:22:2d:7a:54:ab:70:c3:7d:22: + 65:82:70:96 +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 +ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G +CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y +OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx +FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp +Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP +kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc +cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U +fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 +N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC +xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 ++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM +Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG +SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h +mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk +ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c +2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t +HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +GlobalSign Root CA - R3 +# Issuer: CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R3 +# Serial Number:04:00:00:00:00:01:21:58:53:08:a2 +# Subject: CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R3 +# Not Valid Before: Wed Mar 18 10:00:00 2009 +# Not Valid After : Sun Mar 18 10:00:00 2029 +# Fingerprint (MD5): C5:DF:B8:49:CA:05:13:55:EE:2D:BA:1A:C3:3E:B0:28 +# Fingerprint (SHA1): D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=C5:DF:B8:49:CA:05:13:55:EE:2D:BA:1A:C3:3E:B0:28 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 04:00:00:00:00:01:21:58:53:08:a2 + Signature Algorithm: sha256WithRSAEncryption + Issuer: OU=GlobalSign Root CA - R3, O=GlobalSign, CN=GlobalSign + Validity + Not Before: Mar 18 10:00:00 2009 GMT + Not After : Mar 18 10:00:00 2029 GMT + Subject: OU=GlobalSign Root CA - R3, O=GlobalSign, CN=GlobalSign + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:cc:25:76:90:79:06:78:22:16:f5:c0:83:b6:84: + ca:28:9e:fd:05:76:11:c5:ad:88:72:fc:46:02:43: + c7:b2:8a:9d:04:5f:24:cb:2e:4b:e1:60:82:46:e1: + 52:ab:0c:81:47:70:6c:dd:64:d1:eb:f5:2c:a3:0f: + 82:3d:0c:2b:ae:97:d7:b6:14:86:10:79:bb:3b:13: + 80:77:8c:08:e1:49:d2:6a:62:2f:1f:5e:fa:96:68: + df:89:27:95:38:9f:06:d7:3e:c9:cb:26:59:0d:73: + de:b0:c8:e9:26:0e:83:15:c6:ef:5b:8b:d2:04:60: + ca:49:a6:28:f6:69:3b:f6:cb:c8:28:91:e5:9d:8a: + 61:57:37:ac:74:14:dc:74:e0:3a:ee:72:2f:2e:9c: + fb:d0:bb:bf:f5:3d:00:e1:06:33:e8:82:2b:ae:53: + a6:3a:16:73:8c:dd:41:0e:20:3a:c0:b4:a7:a1:e9: + b2:4f:90:2e:32:60:e9:57:cb:b9:04:92:68:68:e5: + 38:26:60:75:b2:9f:77:ff:91:14:ef:ae:20:49:fc: + ad:40:15:48:d1:02:31:61:19:5e:b8:97:ef:ad:77: + b7:64:9a:7a:bf:5f:c1:13:ef:9b:62:fb:0d:6c:e0: + 54:69:16:a9:03:da:6e:e9:83:93:71:76:c6:69:85: + 82:17 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 8F:F0:4B:7F:A8:2E:45:24:AE:4D:50:FA:63:9A:8B:DE:E2:DD:1B:BC + Signature Algorithm: sha256WithRSAEncryption + 4b:40:db:c0:50:aa:fe:c8:0c:ef:f7:96:54:45:49:bb:96:00: + 09:41:ac:b3:13:86:86:28:07:33:ca:6b:e6:74:b9:ba:00:2d: + ae:a4:0a:d3:f5:f1:f1:0f:8a:bf:73:67:4a:83:c7:44:7b:78: + e0:af:6e:6c:6f:03:29:8e:33:39:45:c3:8e:e4:b9:57:6c:aa: + fc:12:96:ec:53:c6:2d:e4:24:6c:b9:94:63:fb:dc:53:68:67: + 56:3e:83:b8:cf:35:21:c3:c9:68:fe:ce:da:c2:53:aa:cc:90: + 8a:e9:f0:5d:46:8c:95:dd:7a:58:28:1a:2f:1d:de:cd:00:37: + 41:8f:ed:44:6d:d7:53:28:97:7e:f3:67:04:1e:15:d7:8a:96: + b4:d3:de:4c:27:a4:4c:1b:73:73:76:f4:17:99:c2:1f:7a:0e: + e3:2d:08:ad:0a:1c:2c:ff:3c:ab:55:0e:0f:91:7e:36:eb:c3: + 57:49:be:e1:2e:2d:7c:60:8b:c3:41:51:13:23:9d:ce:f7:32: + 6b:94:01:a8:99:e7:2c:33:1f:3a:3b:25:d2:86:40:ce:3b:2c: + 86:78:c9:61:2f:14:ba:ee:db:55:6f:df:84:ee:05:09:4d:bd: + 28:d8:72:ce:d3:62:50:65:1e:eb:92:97:83:31:d9:b3:b5:ca: + 47:58:3f:5f +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES +# Serial Number:53:ec:3b:ee:fb:b2:48:5f +# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES +# Not Valid Before: Wed May 20 08:38:15 2009 +# Not Valid After : Tue Dec 31 08:38:15 2030 +# Fingerprint (MD5): 73:3A:74:7A:EC:BB:A3:96:A6:C2:E4:E2:C8:9B:C0:C3 +# Fingerprint (SHA1): AE:C5:FB:3F:C8:E1:BF:C4:E5:4F:03:07:5A:9A:E8:00:B7:F7:B6:FA +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +========================================================= +MD5 Fingerprint=73:3A:74:7A:EC:BB:A3:96:A6:C2:E4:E2:C8:9B:C0:C3 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 6047274297262753887 (0x53ec3beefbb2485f) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=ES, CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 + Validity + Not Before: May 20 08:38:15 2009 GMT + Not After : Dec 31 08:38:15 2030 GMT + Subject: C=ES, CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:ca:96:6b:8e:ea:f8:fb:f1:a2:35:e0:7f:4c:da: + e0:c3:52:d7:7d:b6:10:c8:02:5e:b3:43:2a:c4:4f: + 6a:b2:ca:1c:5d:28:9a:78:11:1a:69:59:57:af:b5: + 20:42:e4:8b:0f:e6:df:5b:a6:03:92:2f:f5:11:e4: + 62:d7:32:71:38:d9:04:0c:71:ab:3d:51:7e:0f:07: + df:63:05:5c:e9:bf:94:6f:c1:29:82:c0:b4:da:51: + b0:c1:3c:bb:ad:37:4a:5c:ca:f1:4b:36:0e:24:ab: + bf:c3:84:77:fd:a8:50:f4:b1:e7:c6:2f:d2:2d:59: + 8d:7a:0a:4e:96:69:52:02:aa:36:98:ec:fc:fa:14: + 83:0c:37:1f:c9:92:37:7f:d7:81:2d:e5:c4:b9:e0: + 3e:34:fe:67:f4:3e:66:d1:d3:f4:40:cf:5e:62:34: + 0f:70:06:3e:20:18:5a:ce:f7:72:1b:25:6c:93:74: + 14:93:a3:73:b1:0e:aa:87:10:23:59:5f:20:05:19: + 47:ed:68:8e:92:12:ca:5d:fc:d6:2b:b2:92:3c:20: + cf:e1:5f:af:20:be:a0:76:7f:76:e5:ec:1a:86:61: + 33:3e:e7:7b:b4:3f:a0:0f:8e:a2:b9:6a:6f:b9:87: + 26:6f:41:6c:88:a6:50:fd:6a:63:0b:f5:93:16:1b: + 19:8f:b2:ed:9b:9b:c9:90:f5:01:0c:df:19:3d:0f: + 3e:38:23:c9:2f:8f:0c:d1:02:fe:1b:55:d6:4e:d0: + 8d:3c:af:4f:a4:f3:fe:af:2a:d3:05:9d:79:08:a1: + cb:57:31:b4:9c:c8:90:b2:67:f4:18:16:93:3a:fc: + 47:d8:d1:78:96:31:1f:ba:2b:0c:5f:5d:99:ad:63: + 89:5a:24:20:76:d8:df:fd:ab:4e:a6:22:aa:9d:5e: + e6:27:8a:7d:68:29:a3:e7:8a:b8:da:11:bb:17:2d: + 99:9d:13:24:46:f7:c5:e2:d8:9f:8e:7f:c7:8f:74: + 6d:5a:b2:e8:72:f5:ac:ee:24:10:ad:2f:14:da:ff: + 2d:9a:46:71:47:be:42:df:bb:01:db:f4:7f:d3:28: + 8f:31:59:5b:d3:c9:02:a6:b4:52:ca:6e:97:fb:43: + c5:08:26:6f:8a:f4:bb:fd:9f:28:aa:0d:d5:45:f3: + 13:3a:1d:d8:c0:78:8f:41:67:3c:1e:94:64:ae:7b: + 0b:c5:e8:d9:01:88:39:1a:97:86:64:41:d5:3b:87: + 0c:6e:fa:0f:c6:bd:48:14:bf:39:4d:d4:9e:41:b6: + 8f:96:1d:63:96:93:d9:95:06:78:31:68:9e:37:06: + 3b:80:89:45:61:39:23:c7:1b:44:a3:15:e5:1c:f8: + 92:30:bb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:1 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 65:CD:EB:AB:35:1E:00:3E:7E:D5:74:C0:1C:B4:73:47:0E:1A:64:2F + X509v3 Certificate Policies: + Policy: X509v3 Any Policy + CPS: http://www.firmaprofesional.com/cps + User Notice: + Explicit Text: + + Signature Algorithm: sha1WithRSAEncryption + 17:7d:a0:f9:b4:dd:c5:c5:eb:ad:4b:24:b5:a1:02:ab:dd:a5: + 88:4a:b2:0f:55:4b:2b:57:8c:3b:e5:31:dd:fe:c4:32:f1:e7: + 5b:64:96:36:32:18:ec:a5:32:77:d7:e3:44:b6:c0:11:2a:80: + b9:3d:6a:6e:7c:9b:d3:ad:fc:c3:d6:a3:e6:64:29:7c:d1:e1: + 38:1e:82:2b:ff:27:65:af:fb:16:15:c4:2e:71:84:e5:b5:ff: + fa:a4:47:bd:64:32:bb:f6:25:84:a2:27:42:f5:20:b0:c2:13: + 10:11:cd:10:15:ba:42:90:2a:d2:44:e1:96:26:eb:31:48:12: + fd:2a:da:c9:06:cf:74:1e:a9:4b:d5:87:28:f9:79:34:92:3e: + 2e:44:e8:f6:8f:4f:8f:35:3f:25:b3:39:dc:63:2a:90:6b:20: + 5f:c4:52:12:4e:97:2c:2a:ac:9d:97:de:48:f2:a3:66:db:c2: + d2:83:95:a6:66:a7:9e:25:0f:e9:0b:33:91:65:0a:5a:c3:d9: + 54:12:dd:af:c3:4e:0e:1f:26:5e:0d:dc:b3:8d:ec:d5:81:70: + de:d2:4f:24:05:f3:6c:4e:f5:4c:49:66:8d:d1:ff:d2:0b:25: + 41:48:fe:51:84:c6:42:af:80:04:cf:d0:7e:64:49:e4:f2:df: + a2:ec:b1:4c:c0:2a:1d:e7:b4:b1:65:a2:c4:bc:f1:98:f4:aa: + 70:07:63:b4:b8:da:3b:4c:fa:40:22:30:5b:11:a6:f0:05:0e: + c6:02:03:48:ab:86:9b:85:dd:db:dd:ea:a2:76:80:73:7d:f5: + 9c:04:c4:45:8d:e7:b9:1c:8b:9e:ea:d7:75:d1:72:b1:de:75: + 44:e7:42:7d:e2:57:6b:7d:dc:99:bc:3d:83:28:ea:80:93:8d: + c5:4c:65:c1:70:81:b8:38:fc:43:31:b2:f6:03:34:47:b2:ac: + fb:22:06:cb:1e:dd:17:47:1c:5f:66:b9:d3:1a:a2:da:11:b1: + a4:bc:23:c9:e4:be:87:ff:b9:94:b6:f8:5d:20:4a:d4:5f:e7: + bd:68:7b:65:f2:15:1e:d2:3a:a9:2d:e9:d8:6b:24:ac:97:58: + 44:47:ad:59:18:f1:21:65:70:de:ce:34:60:a8:40:f1:f3:3c: + a4:c3:28:23:8c:fe:27:33:43:40:a0:17:3c:eb:ea:3b:b0:72: + a6:a3:b9:4a:4b:5e:16:48:f4:b2:bc:c8:8c:92:c5:9d:9f:ac: + 72:36:bc:34:80:34:6b:a9:8b:92:c0:b8:17:ed:ec:76:53:f5: + 24:01:8c:b3:22:e8:4b:7c:55:c6:9d:fa:a3:14:bb:65:85:6e: + 6e:4f:12:7e:0a:3c:9d:95 +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE +BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy +MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 +thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM +cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG +L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i +NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h +X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b +m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy +Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja +EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T +KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF +6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD +VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv +ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl +AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF +661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 +am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 +ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 +PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS +3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k +SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF +3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM +ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g +StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz +Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB +jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +Izenpe.com +# Issuer: CN=Izenpe.com,O=IZENPE S.A.,C=ES +# Serial Number:00:b0:b7:5a:16:48:5f:bf:e1:cb:f5:8b:d7:19:e6:7d +# Subject: CN=Izenpe.com,O=IZENPE S.A.,C=ES +# Not Valid Before: Thu Dec 13 13:08:28 2007 +# Not Valid After : Sun Dec 13 08:27:25 2037 +# Fingerprint (MD5): A6:B0:CD:85:80:DA:5C:50:34:A3:39:90:2F:55:67:73 +# Fingerprint (SHA1): 2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=A6:B0:CD:85:80:DA:5C:50:34:A3:39:90:2F:55:67:73 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + b0:b7:5a:16:48:5f:bf:e1:cb:f5:8b:d7:19:e6:7d + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=ES, O=IZENPE S.A., CN=Izenpe.com + Validity + Not Before: Dec 13 13:08:28 2007 GMT + Not After : Dec 13 08:27:25 2037 GMT + Subject: C=ES, O=IZENPE S.A., CN=Izenpe.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:c9:d3:7a:ca:0f:1e:ac:a7:86:e8:16:65:6a:b1: + c2:1b:45:32:71:95:d9:fe:10:5b:cc:af:e7:a5:79: + 01:8f:89:c3:ca:f2:55:71:f7:77:be:77:94:f3:72: + a4:2c:44:d8:9e:92:9b:14:3a:a1:e7:24:90:0a:0a: + 56:8e:c5:d8:26:94:e1:d9:48:e1:2d:3e:da:0a:72: + dd:a3:99:15:da:81:a2:87:f4:7b:6e:26:77:89:58: + ad:d6:eb:0c:b2:41:7a:73:6e:6d:db:7a:78:41:e9: + 08:88:12:7e:87:2e:66:11:63:6c:54:fb:3c:9d:72: + c0:bc:2e:ff:c2:b7:dd:0d:76:e3:3a:d7:f7:b4:68: + be:a2:f5:e3:81:6e:c1:46:6f:5d:8d:e0:4d:c6:54: + 55:89:1a:33:31:0a:b1:57:b9:a3:8a:98:c3:ec:3b: + 34:c5:95:41:69:7e:75:c2:3c:20:c5:61:ba:51:47: + a0:20:90:93:a1:90:4b:f3:4e:7c:85:45:54:9a:d1: + 05:26:41:b0:b5:4d:1d:33:be:c4:03:c8:25:7c:c1: + 70:db:3b:f4:09:2d:54:27:48:ac:2f:e1:c4:ac:3e: + c8:cb:92:4c:53:39:37:23:ec:d3:01:f9:e0:09:44: + 4d:4d:64:c0:e1:0d:5a:87:22:bc:ad:1b:a3:fe:26: + b5:15:f3:a7:fc:84:19:e9:ec:a1:88:b4:44:69:84: + 83:f3:89:d1:74:06:a9:cc:0b:d6:c2:de:27:85:50: + 26:ca:17:b8:c9:7a:87:56:2c:1a:01:1e:6c:be:13: + ad:10:ac:b5:24:f5:38:91:a1:d6:4b:da:f1:bb:d2: + de:47:b5:f1:bc:81:f6:59:6b:cf:19:53:e9:8d:15: + cb:4a:cb:a9:6f:44:e5:1b:41:cf:e1:86:a7:ca:d0: + 6a:9f:bc:4c:8d:06:33:5a:a2:85:e5:90:35:a0:62: + 5c:16:4e:f0:e3:a2:fa:03:1a:b4:2c:71:b3:58:2c: + de:7b:0b:db:1a:0f:eb:de:21:1f:06:77:06:03:b0: + c9:ef:99:fc:c0:b9:4f:0b:86:28:fe:d2:b9:ea:e3: + da:a5:c3:47:69:12:e0:db:f0:f6:19:8b:ed:7b:70: + d7:02:d6:ed:87:18:28:2c:04:24:4c:77:e4:48:8a: + 1a:c6:3b:9a:d4:0f:ca:fa:75:d2:01:40:5a:8d:79: + bf:8b:cf:4b:cf:aa:16:c1:95:e4:ad:4c:8a:3e:17: + 91:d4:b1:62:e5:82:e5:80:04:a4:03:7e:8d:bf:da: + 7f:a2:0f:97:4f:0c:d3:0d:fb:d7:d1:e5:72:7e:1c: + c8:77:ff:5b:9a:0f:b7:ae:05:46:e5:f1:a8:16:ec: + 47:a4:17 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + email:info@izenpe.com, DirName:/O=IZENPE S.A. - CIF A01337260-RMerc.Vitoria-Gasteiz T1055 F62 S8/street=Avda del Mediterraneo Etorbidea 14 - 01010 Vitoria-Gasteiz + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 1D:1C:65:0E:A8:F2:25:7B:B4:91:CF:E4:B1:B1:E6:BD:55:74:6C:05 + Signature Algorithm: sha256WithRSAEncryption + 78:a6:0c:16:4a:9f:4c:88:3a:c0:cb:0e:a5:16:7d:9f:b9:48: + 5f:18:8f:0d:62:36:f6:cd:19:6b:ac:ab:d5:f6:91:7d:ae:71: + f3:3f:b3:0e:78:85:9b:95:a4:27:21:47:42:4a:7c:48:3a:f5: + 45:7c:b3:0c:8e:51:78:ac:95:13:de:c6:fd:7d:b8:1a:90:4c: + ab:92:03:c7:ed:42:01:ce:0f:d8:b1:fa:a2:92:e1:60:6d:ae: + 7a:6b:09:aa:c6:29:ee:68:49:67:30:80:24:7a:31:16:39:5b: + 7e:f1:1c:2e:dd:6c:09:ad:f2:31:c1:82:4e:b9:bb:f9:be:bf: + 2a:85:3f:c0:40:a3:3a:59:fc:59:4b:3c:28:24:db:b4:15:75: + ae:0d:88:ba:2e:73:c0:bd:58:87:e5:42:f2:eb:5e:ee:1e:30: + 22:99:cb:37:d1:c4:21:6c:81:ec:be:6d:26:e6:1c:e4:42:20: + 9e:47:b0:ac:83:59:70:2c:35:d6:af:36:34:b4:cd:3b:f8:32: + a8:ef:e3:78:89:fb:8d:45:2c:da:9c:b8:7e:40:1c:61:e7:3e: + a2:92:2c:4b:f2:cd:fa:98:b6:29:ff:f3:f2:7b:a9:1f:2e:a0: + 93:57:2b:de:85:03:f9:69:37:cb:9e:78:6a:05:b4:c5:31:78: + 89:ec:7a:a7:85:e1:b9:7b:3c:de:be:1e:79:84:ce:9f:70:0e: + 59:c2:35:2e:90:2a:31:d9:e4:45:7a:41:a4:2e:13:9b:34:0e: + 66:7b:49:ab:64:97:d0:46:c3:79:9d:72:50:63:a6:98:5b:06: + bd:48:6d:d8:39:83:70:e8:35:f0:05:d1:aa:bc:e3:db:c8:02: + ea:7c:fd:82:da:c2:5b:52:35:ae:98:3a:ad:ba:35:93:23:a7: + 1f:48:dd:35:46:98:b2:10:68:e4:a5:31:c2:0a:58:2e:19:81: + 10:c9:50:75:fc:ea:5a:16:ce:11:d7:ee:ef:50:88:2d:61:ff: + 3f:42:73:05:94:43:d5:8e:3c:4e:01:3a:19:a5:1f:46:4e:77: + d0:5d:e5:81:22:21:87:fe:94:7d:84:d8:93:ad:d6:68:43:48: + b2:db:eb:73:24:e7:91:7f:54:a4:b6:80:3e:9d:a3:3c:4c:72: + c2:57:c4:a0:d4:cc:38:27:ce:d5:06:9e:a2:48:d9:e9:9f:ce: + 82:70:36:93:9a:3b:df:96:21:e3:59:b7:0c:da:91:37:f0:fd: + 59:5a:b3:99:c8:69:6c:43:26:01:35:63:60:55:89:03:3a:75: + d8:ba:4a:d9:54:ff:ee:de:80:d8:2d:d1:38:d5:5e:2d:0b:98: + 7d:3e:6c:db:fc:26:88:c7 +-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 +MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 +ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD +VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j +b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq +scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO +xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H +LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX +uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD +yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ +JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q +rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN +BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L +hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB +QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ +HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu +Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg +QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB +BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA +A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb +laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 +awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo +JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw +LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT +VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk +LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb +UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ +QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ +naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls +QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE----- + +Chambers of Commerce Root - 2008 +# Issuer: CN=Chambers of Commerce Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU +# Serial Number:00:a3:da:42:7e:a4:b1:ae:da +# Subject: CN=Chambers of Commerce Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU +# Not Valid Before: Fri Aug 01 12:29:50 2008 +# Not Valid After : Sat Jul 31 12:29:50 2038 +# Fingerprint (MD5): 5E:80:9E:84:5A:0E:65:0B:17:02:F3:55:18:2A:3E:D7 +# Fingerprint (SHA1): 78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=5E:80:9E:84:5A:0E:65:0B:17:02:F3:55:18:2A:3E:D7 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + a3:da:42:7e:a4:b1:ae:da + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=EU, L=Madrid (see current address at www.camerfirma.com/address)/serialNumber=A82743287, O=AC Camerfirma S.A., CN=Chambers of Commerce Root - 2008 + Validity + Not Before: Aug 1 12:29:50 2008 GMT + Not After : Jul 31 12:29:50 2038 GMT + Subject: C=EU, L=Madrid (see current address at www.camerfirma.com/address)/serialNumber=A82743287, O=AC Camerfirma S.A., CN=Chambers of Commerce Root - 2008 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:af:00:cb:70:37:2b:80:5a:4a:3a:6c:78:94:7d: + a3:7f:1a:1f:f6:35:d5:bd:db:cb:0d:44:72:3e:26: + b2:90:52:ba:63:3b:28:58:6f:a5:b3:6d:94:a6:f3: + dd:64:0c:55:f6:f6:e7:f2:22:22:80:5e:e1:62:c6: + b6:29:e1:81:6c:f2:bf:e5:7d:32:6a:54:a0:32:19: + 59:fe:1f:8b:d7:3d:60:86:85:24:6f:e3:11:b3:77: + 3e:20:96:35:21:6b:b3:08:d9:70:2e:64:f7:84:92: + 53:d6:0e:b0:90:8a:8a:e3:87:8d:06:d3:bd:90:0e: + e2:99:a1:1b:86:0e:da:9a:0a:bb:0b:61:50:06:52: + f1:9e:7f:76:ec:cb:0f:d0:1e:0d:cf:99:30:3d:1c: + c4:45:10:58:ac:d6:d3:e8:d7:e5:ea:c5:01:07:77: + d6:51:e6:03:7f:8a:48:a5:4d:68:75:b9:e9:bc:9e: + 4e:19:71:f5:32:4b:9c:6d:60:19:0b:fb:cc:9d:75: + dc:bf:26:cd:8f:93:78:39:79:73:5e:25:0e:ca:5c: + eb:77:12:07:cb:64:41:47:72:93:ab:50:c3:eb:09: + 76:64:34:d2:39:b7:76:11:09:0d:76:45:c4:a9:ae: + 3d:6a:af:b5:7d:65:2f:94:58:10:ec:5c:7c:af:7e: + e2:b6:18:d9:d0:9b:4e:5a:49:df:a9:66:0b:cc:3c: + c6:78:7c:a7:9c:1d:e3:ce:8e:53:be:05:de:60:0f: + 6b:e5:1a:db:3f:e3:e1:21:c9:29:c1:f1:eb:07:9c: + 52:1b:01:44:51:3c:7b:25:d7:c4:e5:52:54:5d:25: + 07:ca:16:20:b8:ad:e4:41:ee:7a:08:fe:99:6f:83: + a6:91:02:b0:6c:36:55:6a:e7:7d:f5:96:e6:ca:81: + d6:97:f1:94:83:e9:ed:b0:b1:6b:12:69:1e:ac:fb: + 5d:a9:c5:98:e9:b4:5b:58:7a:be:3d:a2:44:3a:63: + 59:d4:0b:25:de:1b:4f:bd:e5:01:9e:cd:d2:29:d5: + 9f:17:19:0a:6f:bf:0c:90:d3:09:5f:d9:e3:8a:35: + cc:79:5a:4d:19:37:92:b7:c4:c1:ad:af:f4:79:24: + 9a:b2:01:0b:b1:af:5c:96:f3:80:32:fb:5c:3d:98: + f1:a0:3f:4a:de:be:af:94:2e:d9:55:9a:17:6e:60: + 9d:63:6c:b8:63:c9:ae:81:5c:18:35:e0:90:bb:be: + 3c:4f:37:22:b9:7e:eb:cf:9e:77:21:a6:3d:38:81: + fb:48:da:31:3d:2b:e3:89:f5:d0:b5:bd:7e:e0:50: + c4:12:89:b3:23:9a:10:31:85:db:ae:6f:ef:38:33: + 18:76:11 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:12 + X509v3 Subject Key Identifier: + F9:24:AC:0F:B2:B5:F8:79:C0:FA:60:88:1B:C4:D9:4D:02:9E:17:19 + X509v3 Authority Key Identifier: + keyid:F9:24:AC:0F:B2:B5:F8:79:C0:FA:60:88:1B:C4:D9:4D:02:9E:17:19 + DirName:/C=EU/L=Madrid (see current address at www.camerfirma.com/address)/serialNumber=A82743287/O=AC Camerfirma S.A./CN=Chambers of Commerce Root - 2008 + serial:A3:DA:42:7E:A4:B1:AE:DA + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Certificate Policies: + Policy: X509v3 Any Policy + CPS: http://policy.camerfirma.com + + Signature Algorithm: sha1WithRSAEncryption + 90:12:af:22:35:c2:a3:39:f0:2e:de:e9:b5:e9:78:7c:48:be: + 3f:7d:45:92:5e:e9:da:b1:19:fc:16:3c:9f:b4:5b:66:9e:6a: + e7:c3:b9:5d:88:e8:0f:ad:cf:23:0f:de:25:3a:5e:cc:4f:a5: + c1:b5:2d:ac:24:d2:58:07:de:a2:cf:69:84:60:33:e8:10:0d: + 13:a9:23:d0:85:e5:8e:7b:a6:9e:3d:72:13:72:33:f5:aa:7d: + c6:63:1f:08:f4:fe:01:7f:24:cf:2b:2c:54:09:de:e2:2b:6d: + 92:c6:39:4f:16:ea:3c:7e:7a:46:d4:45:6a:46:a8:eb:75:82: + 56:a7:ab:a0:7c:68:13:33:f6:9d:30:f0:6f:27:39:24:23:2a: + 90:fd:90:29:35:f2:93:df:34:a5:c6:f7:f8:ef:8c:0f:62:4a: + 7c:ae:d3:f5:54:f8:8d:b6:9a:56:87:16:82:3a:33:ab:5a:22: + 08:f7:82:ba:ea:2e:e0:47:9a:b4:b5:45:a3:05:3b:d9:dc:2e: + 45:40:3b:ea:dc:7f:e8:3b:eb:d1:ec:26:d8:35:a4:30:c5:3a: + ac:57:9e:b3:76:a5:20:7b:f9:1e:4a:05:62:01:a6:28:75:60: + 97:92:0d:6e:3e:4d:37:43:0d:92:15:9c:18:22:cd:51:99:a0: + 29:1a:3c:5f:8a:32:33:5b:30:c7:89:2f:47:98:0f:a3:03:c6: + f6:f1:ac:df:32:f0:d9:81:1a:e4:9c:bd:f6:80:14:f0:d1:2c: + b9:85:f5:d8:a3:b1:c8:a5:21:e5:1c:13:97:ee:0e:bd:df:29: + a9:ef:34:53:5b:d3:e4:6a:13:84:06:b6:32:02:c4:52:ae:22: + d2:dc:b2:21:42:1a:da:40:f0:29:c9:ec:0a:0c:5c:e2:d0:ba: + cc:48:d3:37:0a:cc:12:0a:8a:79:b0:3d:03:7f:69:4b:f4:34: + 20:7d:b3:34:ea:8e:4b:64:f5:3e:fd:b3:23:67:15:0d:04:b8: + f0:2d:c1:09:51:3c:b2:6c:15:f0:a5:23:d7:83:74:e4:e5:2e: + c9:fe:98:27:42:c6:ab:c6:9e:b0:d0:5b:38:a5:9b:50:de:7e: + 18:98:b5:45:3b:f6:79:b4:e8:f7:1a:7b:06:83:fb:d0:8b:da: + bb:c7:bd:18:ab:08:6f:3c:80:6b:40:3f:19:19:ba:65:8a:e6: + be:d5:5c:d3:36:d7:ef:40:52:24:60:38:67:04:31:ec:8f:f3: + 82:c6:de:b9:55:f3:3b:31:91:5a:dc:b5:08:15:ad:76:25:0a: + 0d:7b:2e:87:e2:0c:a6:06:bc:26:10:6d:37:9d:ec:dd:78:8c: + 7c:80:c5:f0:d9:77:48:d0 +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz +IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz +MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj +dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw +EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp +MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 +28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq +VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q +DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR +5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL +ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a +Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl +UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s ++12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 +Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx +hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV +HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 ++HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN +YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t +L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy +ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt +IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV +HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w +DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW +PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF +5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 +glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH +FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 +pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD +xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG +tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq +jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De +fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ +d0jQ +-----END CERTIFICATE----- + +Global Chambersign Root - 2008 +# Issuer: CN=Global Chambersign Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU +# Serial Number:00:c9:cd:d3:e9:d5:7d:23:ce +# Subject: CN=Global Chambersign Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU +# Not Valid Before: Fri Aug 01 12:31:40 2008 +# Not Valid After : Sat Jul 31 12:31:40 2038 +# Fingerprint (MD5): 9E:80:FF:78:01:0C:2E:C1:36:BD:FE:96:90:6E:08:F3 +# Fingerprint (SHA1): 4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=9E:80:FF:78:01:0C:2E:C1:36:BD:FE:96:90:6E:08:F3 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c9:cd:d3:e9:d5:7d:23:ce + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=EU, L=Madrid (see current address at www.camerfirma.com/address)/serialNumber=A82743287, O=AC Camerfirma S.A., CN=Global Chambersign Root - 2008 + Validity + Not Before: Aug 1 12:31:40 2008 GMT + Not After : Jul 31 12:31:40 2038 GMT + Subject: C=EU, L=Madrid (see current address at www.camerfirma.com/address)/serialNumber=A82743287, O=AC Camerfirma S.A., CN=Global Chambersign Root - 2008 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:c0:df:56:d3:e4:3a:9b:76:45:b4:13:db:ff:c1: + b6:19:8b:37:41:18:95:52:47:eb:17:9d:29:88:8e: + 35:6c:06:32:2e:47:62:f3:49:04:bf:7d:44:36:b1: + 71:cc:bd:5a:09:73:d5:d9:85:44:ff:91:57:25:df: + 5e:36:8e:70:d1:5c:71:43:1d:d9:da:ef:5c:d2:fb: + 1b:bd:3a:b5:cb:ad:a3:cc:44:a7:0d:ae:21:15:3f: + b9:7a:5b:92:75:d8:a4:12:38:89:19:8a:b7:80:d2: + e2:32:6f:56:9c:91:d6:88:10:0b:b3:74:64:92:74: + 60:f3:f6:cf:18:4f:60:b2:23:d0:c7:3b:ce:61:4b: + 99:8f:c2:0c:d0:40:b2:98:dc:0d:a8:4e:a3:b9:0a: + ae:60:a0:ad:45:52:63:ba:66:bd:68:e0:f9:be:1a: + a8:81:bb:1e:41:78:75:d3:c1:fe:00:55:b0:87:54: + e8:27:90:35:1d:4c:33:ad:97:fc:97:2e:98:84:bf: + 2c:c9:a3:bf:d1:98:11:14:ed:63:f8:ca:98:88:58: + 17:99:ed:45:03:97:7e:3c:86:1e:88:8c:be:f2:91: + 84:8f:65:34:d8:00:4c:7d:b7:31:17:5a:29:7a:0a: + 18:24:30:a3:37:b5:7a:a9:01:7d:26:d6:f9:0e:8e: + 59:f1:fd:1b:33:b5:29:3b:17:3b:41:b6:21:dd:d4: + c0:3d:a5:9f:9f:1f:43:50:c9:bb:bc:6c:7a:97:98: + ee:cd:8c:1f:fb:9c:51:ae:8b:70:bd:27:9f:71:c0: + 6b:ac:7d:90:66:e8:d7:5d:3a:0d:b0:d5:c2:8d:d5: + c8:9d:9d:c1:6d:d0:d0:bf:51:e4:e3:f8:c3:38:36: + ae:d6:a7:75:e6:af:84:43:5d:93:92:0c:6a:07:de: + 3b:1d:98:22:d6:ac:c1:35:db:a3:a0:25:ff:72:b5: + 76:1d:de:6d:e9:2c:66:2c:52:84:d0:45:92:ce:1c: + e5:e5:33:1d:dc:07:53:54:a3:aa:82:3b:9a:37:2f: + dc:dd:a0:64:e9:e6:dd:bd:ae:fc:64:85:1d:3c:a7: + c9:06:de:84:ff:6b:e8:6b:1a:3c:c5:a2:b3:42:fb: + 8b:09:3e:5f:08:52:c7:62:c4:d4:05:71:bf:c4:64: + e4:f8:a1:83:e8:3e:12:9b:a8:1e:d4:36:4d:2f:71: + f6:8d:28:f6:83:a9:13:d2:61:c1:91:bb:48:c0:34: + 8f:41:8c:4b:4c:db:69:12:ff:50:94:9c:20:83:59: + 73:ed:7c:a1:f2:f1:fd:dd:f7:49:d3:43:58:a0:56: + 63:ca:3d:3d:e5:35:56:59:e9:0e:ca:20:cc:2b:4b: + 93:29:0f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:12 + X509v3 Subject Key Identifier: + B9:09:CA:9C:1E:DB:D3:6C:3A:6B:AE:ED:54:F1:5B:93:06:35:2E:5E + X509v3 Authority Key Identifier: + keyid:B9:09:CA:9C:1E:DB:D3:6C:3A:6B:AE:ED:54:F1:5B:93:06:35:2E:5E + DirName:/C=EU/L=Madrid (see current address at www.camerfirma.com/address)/serialNumber=A82743287/O=AC Camerfirma S.A./CN=Global Chambersign Root - 2008 + serial:C9:CD:D3:E9:D5:7D:23:CE + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Certificate Policies: + Policy: X509v3 Any Policy + CPS: http://policy.camerfirma.com + + Signature Algorithm: sha1WithRSAEncryption + 80:88:7f:70:de:92:28:d9:05:94:46:ff:90:57:a9:f1:2f:df: + 1a:0d:6b:fa:7c:0e:1c:49:24:79:27:d8:46:aa:6f:29:59:52: + 88:70:12:ea:dd:3d:f5:9b:53:54:6f:e1:60:a2:a8:09:b9:ec: + eb:59:7c:c6:35:f1:dc:18:e9:f1:67:e5:af:ba:45:e0:09:de: + ca:44:0f:c2:17:0e:77:91:45:7a:33:5f:5f:96:2c:68:8b:c1: + 47:8f:98:9b:3d:c0:ec:cb:f5:d5:82:92:84:35:d1:be:36:38: + 56:72:31:5b:47:2d:aa:17:a4:63:51:eb:0a:01:ad:7f:ec:75: + 9e:cb:a1:1f:f1:7f:12:b1:b9:e4:64:7f:67:d6:23:2a:f4:b8: + 39:5d:98:e8:21:a7:e1:bd:3d:42:1a:74:9a:70:af:68:6c:50: + 5d:49:cf:ff:fb:0e:5d:e6:2c:47:d7:81:3a:59:00:b5:73:6b: + 63:20:f6:31:45:08:39:0e:f4:70:7e:40:70:5a:3f:d0:6b:42: + a9:74:3d:28:2f:02:6d:75:72:95:09:8d:48:63:c6:c6:23:57: + 92:93:5e:35:c1:8d:f9:0a:f7:2c:9d:62:1c:f6:ad:7c:dd:a6: + 31:1e:b6:b1:c7:7e:85:26:fa:a4:6a:b5:da:63:30:d1:ef:93: + 37:b2:66:2f:7d:05:f7:e7:b7:4b:98:94:35:c0:d9:3a:29:c1: + 9d:b2:50:33:1d:4a:a9:5a:a6:c9:03:ef:ed:f4:e7:a8:6e:8a: + b4:57:84:eb:a4:3f:d0:ee:aa:aa:87:5b:63:e8:93:e2:6b:a8: + d4:b8:72:78:6b:1b:ed:39:e4:5d:cb:9b:aa:87:d5:4f:4e:00: + fe:d9:6a:9f:3c:31:0f:28:02:01:7d:98:e8:a7:b0:a2:64:9e: + 79:f8:48:f2:15:a9:cc:e6:c8:44:eb:3f:78:99:f2:7b:71:3e: + 3c:f1:98:a7:c5:18:12:3f:e6:bb:28:33:42:e9:45:0a:7c:6d: + f2:86:79:2f:c5:82:19:7d:09:89:7c:b2:54:76:88:ae:de:c1: + f3:cc:e1:6e:db:31:d6:93:ae:99:a0:ef:25:6a:73:98:89:5b: + 3a:2e:13:88:1e:bf:c0:92:94:34:1b:e3:27:b7:8b:1e:6f:42: + ff:e7:e9:37:9b:50:1d:2d:a2:f9:02:ee:cb:58:58:3a:71:bc: + 68:e3:aa:c1:af:1c:28:1f:a2:dc:23:65:3f:81:ea:ae:99:d3: + d8:30:cf:13:0d:4f:15:c9:84:bc:a7:48:2d:f8:30:23:77:d8: + 46:4b:79:6d:f6:8c:ed:3a:7f:60:11:78:f4:e9:9b:ae:d5:54: + c0:74:80:d1:0b:42:9f:c1 +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx +MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy +cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG +A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl +BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed +KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 +G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 +zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 +ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG +HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 +Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V +yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e +beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r +6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog +zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW +BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr +ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp +ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk +cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt +YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC +CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow +KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI +hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ +UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz +X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x +fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz +a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd +Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd +SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O +AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso +M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge +v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----END CERTIFICATE----- + +Go Daddy Root Certificate Authority - G2 +# Issuer: CN=Go Daddy Root Certificate Authority - G2,O="GoDaddy.com, Inc.",L=Scottsdale,ST=Arizona,C=US +# Serial Number: 0 (0x0) +# Subject: CN=Go Daddy Root Certificate Authority - G2,O="GoDaddy.com, Inc.",L=Scottsdale,ST=Arizona,C=US +# Not Valid Before: Tue Sep 01 00:00:00 2009 +# Not Valid After : Thu Dec 31 23:59:59 2037 +# Fingerprint (MD5): 80:3A:BC:22:C1:E6:FB:8D:9B:3B:27:4A:32:1B:9A:01 +# Fingerprint (SHA1): 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=80:3A:BC:22:C1:E6:FB:8D:9B:3B:27:4A:32:1B:9A:01 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., CN=Go Daddy Root Certificate Authority - G2 + Validity + Not Before: Sep 1 00:00:00 2009 GMT + Not After : Dec 31 23:59:59 2037 GMT + Subject: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., CN=Go Daddy Root Certificate Authority - G2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:bf:71:62:08:f1:fa:59:34:f7:1b:c9:18:a3:f7: + 80:49:58:e9:22:83:13:a6:c5:20:43:01:3b:84:f1: + e6:85:49:9f:27:ea:f6:84:1b:4e:a0:b4:db:70:98: + c7:32:01:b1:05:3e:07:4e:ee:f4:fa:4f:2f:59:30: + 22:e7:ab:19:56:6b:e2:80:07:fc:f3:16:75:80:39: + 51:7b:e5:f9:35:b6:74:4e:a9:8d:82:13:e4:b6:3f: + a9:03:83:fa:a2:be:8a:15:6a:7f:de:0b:c3:b6:19: + 14:05:ca:ea:c3:a8:04:94:3b:46:7c:32:0d:f3:00: + 66:22:c8:8d:69:6d:36:8c:11:18:b7:d3:b2:1c:60: + b4:38:fa:02:8c:ce:d3:dd:46:07:de:0a:3e:eb:5d: + 7c:c8:7c:fb:b0:2b:53:a4:92:62:69:51:25:05:61: + 1a:44:81:8c:2c:a9:43:96:23:df:ac:3a:81:9a:0e: + 29:c5:1c:a9:e9:5d:1e:b6:9e:9e:30:0a:39:ce:f1: + 88:80:fb:4b:5d:cc:32:ec:85:62:43:25:34:02:56: + 27:01:91:b4:3b:70:2a:3f:6e:b1:e8:9c:88:01:7d: + 9f:d4:f9:db:53:6d:60:9d:bf:2c:e7:58:ab:b8:5f: + 46:fc:ce:c4:1b:03:3c:09:eb:49:31:5c:69:46:b3: + e0:47 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 3A:9A:85:07:10:67:28:B6:EF:F6:BD:05:41:6E:20:C1:94:DA:0F:DE + Signature Algorithm: sha256WithRSAEncryption + 99:db:5d:79:d5:f9:97:59:67:03:61:f1:7e:3b:06:31:75:2d: + a1:20:8e:4f:65:87:b4:f7:a6:9c:bc:d8:e9:2f:d0:db:5a:ee: + cf:74:8c:73:b4:38:42:da:05:7b:f8:02:75:b8:fd:a5:b1:d7: + ae:f6:d7:de:13:cb:53:10:7e:8a:46:d1:97:fa:b7:2e:2b:11: + ab:90:b0:27:80:f9:e8:9f:5a:e9:37:9f:ab:e4:df:6c:b3:85: + 17:9d:3d:d9:24:4f:79:91:35:d6:5f:04:eb:80:83:ab:9a:02: + 2d:b5:10:f4:d8:90:c7:04:73:40:ed:72:25:a0:a9:9f:ec:9e: + ab:68:12:99:57:c6:8f:12:3a:09:a4:bd:44:fd:06:15:37:c1: + 9b:e4:32:a3:ed:38:e8:d8:64:f3:2c:7e:14:fc:02:ea:9f:cd: + ff:07:68:17:db:22:90:38:2d:7a:8d:d1:54:f1:69:e3:5f:33: + ca:7a:3d:7b:0a:e3:ca:7f:5f:39:e5:e2:75:ba:c5:76:18:33: + ce:2c:f0:2f:4c:ad:f7:b1:e7:ce:4f:a8:c4:9b:4a:54:06:c5: + 7f:7d:d5:08:0f:e2:1c:fe:7e:17:b8:ac:5e:f6:d4:16:b2:43: + 09:0c:4d:f6:a7:6b:b4:99:84:65:ca:7a:88:e2:e2:44:be:5c: + f7:ea:1c:f5 +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz +NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE +AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD +E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH +/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy +DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh +GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR +tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA +AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX +WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu +9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr +gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo +2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI +4uJEvlz36hz1 +-----END CERTIFICATE----- + +Starfield Root Certificate Authority - G2 +# Issuer: CN=Starfield Root Certificate Authority - G2,O="Starfield Technologies, Inc.",L=Scottsdale,ST=Arizona,C=US +# Serial Number: 0 (0x0) +# Subject: CN=Starfield Root Certificate Authority - G2,O="Starfield Technologies, Inc.",L=Scottsdale,ST=Arizona,C=US +# Not Valid Before: Tue Sep 01 00:00:00 2009 +# Not Valid After : Thu Dec 31 23:59:59 2037 +# Fingerprint (MD5): D6:39:81:C6:52:7E:96:69:FC:FC:CA:66:ED:05:F2:96 +# Fingerprint (SHA1): B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=D6:39:81:C6:52:7E:96:69:FC:FC:CA:66:ED:05:F2:96 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Root Certificate Authority - G2 + Validity + Not Before: Sep 1 00:00:00 2009 GMT + Not After : Dec 31 23:59:59 2037 GMT + Subject: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Root Certificate Authority - G2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:bd:ed:c1:03:fc:f6:8f:fc:02:b1:6f:5b:9f:48: + d9:9d:79:e2:a2:b7:03:61:56:18:c3:47:b6:d7:ca: + 3d:35:2e:89:43:f7:a1:69:9b:de:8a:1a:fd:13:20: + 9c:b4:49:77:32:29:56:fd:b9:ec:8c:dd:22:fa:72: + dc:27:61:97:ee:f6:5a:84:ec:6e:19:b9:89:2c:dc: + 84:5b:d5:74:fb:6b:5f:c5:89:a5:10:52:89:46:55: + f4:b8:75:1c:e6:7f:e4:54:ae:4b:f8:55:72:57:02: + 19:f8:17:71:59:eb:1e:28:07:74:c5:9d:48:be:6c: + b4:f4:a4:b0:f3:64:37:79:92:c0:ec:46:5e:7f:e1: + 6d:53:4c:62:af:cd:1f:0b:63:bb:3a:9d:fb:fc:79: + 00:98:61:74:cf:26:82:40:63:f3:b2:72:6a:19:0d: + 99:ca:d4:0e:75:cc:37:fb:8b:89:c1:59:f1:62:7f: + 5f:b3:5f:65:30:f8:a7:b7:4d:76:5a:1e:76:5e:34: + c0:e8:96:56:99:8a:b3:f0:7f:a4:cd:bd:dc:32:31: + 7c:91:cf:e0:5f:11:f8:6b:aa:49:5c:d1:99:94:d1: + a2:e3:63:5b:09:76:b5:56:62:e1:4b:74:1d:96:d4: + 26:d4:08:04:59:d0:98:0e:0e:e6:de:fc:c3:ec:1f: + 90:f1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 7C:0C:32:1F:A7:D9:30:7F:C4:7D:68:A3:62:A8:A1:CE:AB:07:5B:27 + Signature Algorithm: sha256WithRSAEncryption + 11:59:fa:25:4f:03:6f:94:99:3b:9a:1f:82:85:39:d4:76:05: + 94:5e:e1:28:93:6d:62:5d:09:c2:a0:a8:d4:b0:75:38:f1:34: + 6a:9d:e4:9f:8a:86:26:51:e6:2c:d1:c6:2d:6e:95:20:4a:92: + 01:ec:b8:8a:67:7b:31:e2:67:2e:8c:95:03:26:2e:43:9d:4a: + 31:f6:0e:b5:0c:bb:b7:e2:37:7f:22:ba:00:a3:0e:7b:52:fb: + 6b:bb:3b:c4:d3:79:51:4e:cd:90:f4:67:07:19:c8:3c:46:7a: + 0d:01:7d:c5:58:e7:6d:e6:85:30:17:9a:24:c4:10:e0:04:f7: + e0:f2:7f:d4:aa:0a:ff:42:1d:37:ed:94:e5:64:59:12:20:77: + 38:d3:32:3e:38:81:75:96:73:fa:68:8f:b1:cb:ce:1f:c5:ec: + fa:9c:7e:cf:7e:b1:f1:07:2d:b6:fc:bf:ca:a4:bf:d0:97:05: + 4a:bc:ea:18:28:02:90:bd:54:78:09:21:71:d3:d1:7d:1d:d9: + 16:b0:a9:61:3d:d0:0a:00:22:fc:c7:7b:cb:09:64:45:0b:3b: + 40:81:f7:7d:7c:32:f5:98:ca:58:8e:7d:2a:ee:90:59:73:64: + f9:36:74:5e:25:a1:f5:66:05:2e:7f:39:15:a9:2a:fb:50:8b: + 8e:85:69:f4 +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs +ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw +MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj +aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg +nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 +HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N +Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN +dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 +HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G +CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU +sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 +4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg +8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 +mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +Starfield Services Root Certificate Authority - G2 +# Issuer: CN=Starfield Services Root Certificate Authority - G2,O="Starfield Technologies, Inc.",L=Scottsdale,ST=Arizona,C=US +# Serial Number: 0 (0x0) +# Subject: CN=Starfield Services Root Certificate Authority - G2,O="Starfield Technologies, Inc.",L=Scottsdale,ST=Arizona,C=US +# Not Valid Before: Tue Sep 01 00:00:00 2009 +# Not Valid After : Thu Dec 31 23:59:59 2037 +# Fingerprint (MD5): 17:35:74:AF:7B:61:1C:EB:F4:F9:3C:E2:EE:40:F9:A2 +# Fingerprint (SHA1): 92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================== +MD5 Fingerprint=17:35:74:AF:7B:61:1C:EB:F4:F9:3C:E2:EE:40:F9:A2 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Services Root Certificate Authority - G2 + Validity + Not Before: Sep 1 00:00:00 2009 GMT + Not After : Dec 31 23:59:59 2037 GMT + Subject: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Services Root Certificate Authority - G2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d5:0c:3a:c4:2a:f9:4e:e2:f5:be:19:97:5f:8e: + 88:53:b1:1f:3f:cb:cf:9f:20:13:6d:29:3a:c8:0f: + 7d:3c:f7:6b:76:38:63:d9:36:60:a8:9b:5e:5c:00: + 80:b2:2f:59:7f:f6:87:f9:25:43:86:e7:69:1b:52: + 9a:90:e1:71:e3:d8:2d:0d:4e:6f:f6:c8:49:d9:b6: + f3:1a:56:ae:2b:b6:74:14:eb:cf:fb:26:e3:1a:ba: + 1d:96:2e:6a:3b:58:94:89:47:56:ff:25:a0:93:70: + 53:83:da:84:74:14:c3:67:9e:04:68:3a:df:8e:40: + 5a:1d:4a:4e:cf:43:91:3b:e7:56:d6:00:70:cb:52: + ee:7b:7d:ae:3a:e7:bc:31:f9:45:f6:c2:60:cf:13: + 59:02:2b:80:cc:34:47:df:b9:de:90:65:6d:02:cf: + 2c:91:a6:a6:e7:de:85:18:49:7c:66:4e:a3:3a:6d: + a9:b5:ee:34:2e:ba:0d:03:b8:33:df:47:eb:b1:6b: + 8d:25:d9:9b:ce:81:d1:45:46:32:96:70:87:de:02: + 0e:49:43:85:b6:6c:73:bb:64:ea:61:41:ac:c9:d4: + 54:df:87:2f:c7:22:b2:26:cc:9f:59:54:68:9f:fc: + be:2a:2f:c4:55:1c:75:40:60:17:85:02:55:39:8b: + 7f:05 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 9C:5F:00:DF:AA:01:D7:30:2B:38:88:A2:B8:6D:4A:9C:F2:11:91:83 + Signature Algorithm: sha256WithRSAEncryption + 4b:36:a6:84:77:69:dd:3b:19:9f:67:23:08:6f:0e:61:c9:fd: + 84:dc:5f:d8:36:81:cd:d8:1b:41:2d:9f:60:dd:c7:1a:68:d9: + d1:6e:86:e1:88:23:cf:13:de:43:cf:e2:34:b3:04:9d:1f:29: + d5:bf:f8:5e:c8:d5:c1:bd:ee:92:6f:32:74:f2:91:82:2f:bd: + 82:42:7a:ad:2a:b7:20:7d:4d:bc:7a:55:12:c2:15:ea:bd:f7: + 6a:95:2e:6c:74:9f:cf:1c:b4:f2:c5:01:a3:85:d0:72:3e:ad: + 73:ab:0b:9b:75:0c:6d:45:b7:8e:94:ac:96:37:b5:a0:d0:8f: + 15:47:0e:e3:e8:83:dd:8f:fd:ef:41:01:77:cc:27:a9:62:85: + 33:f2:37:08:ef:71:cf:77:06:de:c8:19:1d:88:40:cf:7d:46: + 1d:ff:1e:c7:e1:ce:ff:23:db:c6:fa:8d:55:4e:a9:02:e7:47: + 11:46:3e:f4:fd:bd:7b:29:26:bb:a9:61:62:37:28:b6:2d:2a: + f6:10:86:64:c9:70:a7:d2:ad:b7:29:70:79:ea:3c:da:63:25: + 9f:fd:68:b7:30:ec:70:fb:75:8a:b7:6d:60:67:b2:1e:c8:b9: + e9:d8:a8:6f:02:8b:67:0d:4d:26:57:71:da:20:fc:c1:4a:50: + 8d:b1:28:ba +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs +ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy +ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy +dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p +OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 +8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K +Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe +hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk +6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q +AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI +bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB +ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z +qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn +0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN +sSi6 +-----END CERTIFICATE----- + +AffirmTrust Commercial +# Issuer: CN=AffirmTrust Commercial,O=AffirmTrust,C=US +# Serial Number:77:77:06:27:26:a9:b1:7c +# Subject: CN=AffirmTrust Commercial,O=AffirmTrust,C=US +# Not Valid Before: Fri Jan 29 14:06:06 2010 +# Not Valid After : Tue Dec 31 14:06:06 2030 +# Fingerprint (MD5): 82:92:BA:5B:EF:CD:8A:6F:A6:3D:55:F9:84:F6:D6:B7 +# Fingerprint (SHA1): F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=82:92:BA:5B:EF:CD:8A:6F:A6:3D:55:F9:84:F6:D6:B7 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8608355977964138876 (0x7777062726a9b17c) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Commercial + Validity + Not Before: Jan 29 14:06:06 2010 GMT + Not After : Dec 31 14:06:06 2030 GMT + Subject: C=US, O=AffirmTrust, CN=AffirmTrust Commercial + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:f6:1b:4f:67:07:2b:a1:15:f5:06:22:cb:1f:01: + b2:e3:73:45:06:44:49:2c:bb:49:25:14:d6:ce:c3: + b7:ab:2c:4f:c6:41:32:94:57:fa:12:a7:5b:0e:e2: + 8f:1f:1e:86:19:a7:aa:b5:2d:b9:5f:0d:8a:c2:af: + 85:35:79:32:2d:bb:1c:62:37:f2:b1:5b:4a:3d:ca: + cd:71:5f:e9:42:be:94:e8:c8:de:f9:22:48:64:c6: + e5:ab:c6:2b:6d:ad:05:f0:fa:d5:0b:cf:9a:e5:f0: + 50:a4:8b:3b:47:a5:23:5b:7a:7a:f8:33:3f:b8:ef: + 99:97:e3:20:c1:d6:28:89:cf:94:fb:b9:45:ed:e3: + 40:17:11:d4:74:f0:0b:31:e2:2b:26:6a:9b:4c:57: + ae:ac:20:3e:ba:45:7a:05:f3:bd:9b:69:15:ae:7d: + 4e:20:63:c4:35:76:3a:07:02:c9:37:fd:c7:47:ee: + e8:f1:76:1d:73:15:f2:97:a4:b5:c8:7a:79:d9:42: + aa:2b:7f:5c:fe:ce:26:4f:a3:66:81:35:af:44:ba: + 54:1e:1c:30:32:65:9d:e6:3c:93:5e:50:4e:7a:e3: + 3a:d4:6e:cc:1a:fb:f9:d2:37:ae:24:2a:ab:57:03: + 22:28:0d:49:75:7f:b7:28:da:75:bf:8e:e3:dc:0e: + 79:31 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 9D:93:C6:53:8B:5E:CA:AF:3F:9F:1E:0F:E5:99:95:BC:24:F6:94:8F + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 58:ac:f4:04:0e:cd:c0:0d:ff:0a:fd:d4:ba:16:5f:29:bd:7b: + 68:99:58:49:d2:b4:1d:37:4d:7f:27:7d:46:06:5d:43:c6:86: + 2e:3e:73:b2:26:7d:4f:93:a9:b6:c4:2a:9a:ab:21:97:14:b1: + de:8c:d3:ab:89:15:d8:6b:24:d4:f1:16:ae:d8:a4:5c:d4:7f: + 51:8e:ed:18:01:b1:93:63:bd:bc:f8:61:80:9a:9e:b1:ce:42: + 70:e2:a9:7d:06:25:7d:27:a1:fe:6f:ec:b3:1e:24:da:e3:4b: + 55:1a:00:3b:35:b4:3b:d9:d7:5d:30:fd:81:13:89:f2:c2:06: + 2b:ed:67:c4:8e:c9:43:b2:5c:6b:15:89:02:bc:62:fc:4e:f2: + b5:33:aa:b2:6f:d3:0a:a2:50:e3:f6:3b:e8:2e:44:c2:db:66: + 38:a9:33:56:48:f1:6d:1b:33:8d:0d:8c:3f:60:37:9d:d3:ca: + 6d:7e:34:7e:0d:9f:72:76:8b:1b:9f:72:fd:52:35:41:45:02: + 96:2f:1c:b2:9a:73:49:21:b1:49:47:45:47:b4:ef:6a:34:11: + c9:4d:9a:cc:59:b7:d6:02:9e:5a:4e:65:b5:94:ae:1b:df:29: + b0:16:f1:bf:00:9e:07:3a:17:64:b5:04:b5:23:21:99:0a:95: + 3b:97:7c:ef +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP +Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr +ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL +MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 +yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr +VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ +nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG +XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj +vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt +Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g +N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC +nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +AffirmTrust Networking +# Issuer: CN=AffirmTrust Networking,O=AffirmTrust,C=US +# Serial Number:7c:4f:04:39:1c:d4:99:2d +# Subject: CN=AffirmTrust Networking,O=AffirmTrust,C=US +# Not Valid Before: Fri Jan 29 14:08:24 2010 +# Not Valid After : Tue Dec 31 14:08:24 2030 +# Fingerprint (MD5): 42:65:CA:BE:01:9A:9A:4C:A9:8C:41:49:CD:C0:D5:7F +# Fingerprint (SHA1): 29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=42:65:CA:BE:01:9A:9A:4C:A9:8C:41:49:CD:C0:D5:7F +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8957382827206547757 (0x7c4f04391cd4992d) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Networking + Validity + Not Before: Jan 29 14:08:24 2010 GMT + Not After : Dec 31 14:08:24 2030 GMT + Subject: C=US, O=AffirmTrust, CN=AffirmTrust Networking + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b4:84:cc:33:17:2e:6b:94:6c:6b:61:52:a0:eb: + a3:cf:79:94:4c:e5:94:80:99:cb:55:64:44:65:8f: + 67:64:e2:06:e3:5c:37:49:f6:2f:9b:84:84:1e:2d: + f2:60:9d:30:4e:cc:84:85:e2:2c:cf:1e:9e:fe:36: + ab:33:77:35:44:d8:35:96:1a:3d:36:e8:7a:0e:d8: + d5:47:a1:6a:69:8b:d9:fc:bb:3a:ae:79:5a:d5:f4: + d6:71:bb:9a:90:23:6b:9a:b7:88:74:87:0c:1e:5f: + b9:9e:2d:fa:ab:53:2b:dc:bb:76:3e:93:4c:08:08: + 8c:1e:a2:23:1c:d4:6a:ad:22:ba:99:01:2e:6d:65: + cb:be:24:66:55:24:4b:40:44:b1:1b:d7:e1:c2:85: + c0:de:10:3f:3d:ed:b8:fc:f1:f1:23:53:dc:bf:65: + 97:6f:d9:f9:40:71:8d:7d:bd:95:d4:ce:be:a0:5e: + 27:23:de:fd:a6:d0:26:0e:00:29:eb:3c:46:f0:3d: + 60:bf:3f:50:d2:dc:26:41:51:9e:14:37:42:04:a3: + 70:57:a8:1b:87:ed:2d:fa:7b:ee:8c:0a:e3:a9:66: + 89:19:cb:41:f9:dd:44:36:61:cf:e2:77:46:c8:7d: + f6:f4:92:81:36:fd:db:34:f1:72:7e:f3:0c:16:bd: + b4:15 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 07:1F:D2:E7:9C:DA:C2:6E:A2:40:B4:B0:7A:50:10:50:74:C4:C8:BD + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 89:57:b2:16:7a:a8:c2:fd:d6:d9:9b:9b:34:c2:9c:b4:32:14: + 4d:a7:a4:df:ec:be:a7:be:f8:43:db:91:37:ce:b4:32:2e:50: + 55:1a:35:4e:76:43:71:20:ef:93:77:4e:15:70:2e:87:c3:c1: + 1d:6d:dc:cb:b5:27:d4:2c:56:d1:52:53:3a:44:d2:73:c8:c4: + 1b:05:65:5a:62:92:9c:ee:41:8d:31:db:e7:34:ea:59:21:d5: + 01:7a:d7:64:b8:64:39:cd:c9:ed:af:ed:4b:03:48:a7:a0:99: + 01:80:dc:65:a3:36:ae:65:59:48:4f:82:4b:c8:65:f1:57:1d: + e5:59:2e:0a:3f:6c:d8:d1:f5:e5:09:b4:6c:54:00:0a:e0:15: + 4d:87:75:6d:b7:58:96:5a:dd:6d:d2:00:a0:f4:9b:48:be:c3: + 37:a4:ba:36:e0:7c:87:85:97:1a:15:a2:de:2e:a2:5b:bd:af: + 18:f9:90:50:cd:70:59:f8:27:67:47:cb:c7:a0:07:3a:7d:d1: + 2c:5d:6c:19:3a:66:b5:7d:fd:91:6f:82:b1:be:08:93:db:14: + 47:f1:a2:37:c7:45:9e:3c:c7:77:af:64:a8:93:df:f6:69:83: + 82:60:f2:49:42:34:ed:5a:00:54:85:1c:16:36:92:0c:5c:fa: + a6:ad:bf:db +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y +YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua +kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL +QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp +6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG +yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i +QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO +tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu +QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ +Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u +olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 +x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +AffirmTrust Premium +# Issuer: CN=AffirmTrust Premium,O=AffirmTrust,C=US +# Serial Number:6d:8c:14:46:b1:a6:0a:ee +# Subject: CN=AffirmTrust Premium,O=AffirmTrust,C=US +# Not Valid Before: Fri Jan 29 14:10:36 2010 +# Not Valid After : Mon Dec 31 14:10:36 2040 +# Fingerprint (MD5): C4:5D:0E:48:B6:AC:28:30:4E:0A:BC:F9:38:16:87:57 +# Fingerprint (SHA1): D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=C4:5D:0E:48:B6:AC:28:30:4E:0A:BC:F9:38:16:87:57 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7893706540734352110 (0x6d8c1446b1a60aee) + Signature Algorithm: sha384WithRSAEncryption + Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Premium + Validity + Not Before: Jan 29 14:10:36 2010 GMT + Not After : Dec 31 14:10:36 2040 GMT + Subject: C=US, O=AffirmTrust, CN=AffirmTrust Premium + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:c4:12:df:a9:5f:fe:41:dd:dd:f5:9f:8a:e3:f6: + ac:e1:3c:78:9a:bc:d8:f0:7f:7a:a0:33:2a:dc:8d: + 20:5b:ae:2d:6f:e7:93:d9:36:70:6a:68:cf:8e:51: + a3:85:5b:67:04:a0:10:24:6f:5d:28:82:c1:97:57: + d8:48:29:13:b6:e1:be:91:4d:df:85:0c:53:18:9a: + 1e:24:a2:4f:8f:f0:a2:85:0b:cb:f4:29:7f:d2:a4: + 58:ee:26:4d:c9:aa:a8:7b:9a:d9:fa:38:de:44:57: + 15:e5:f8:8c:c8:d9:48:e2:0d:16:27:1d:1e:c8:83: + 85:25:b7:ba:aa:55:41:cc:03:22:4b:2d:91:8d:8b: + e6:89:af:66:c7:e9:ff:2b:e9:3c:ac:da:d2:b3:c3: + e1:68:9c:89:f8:7a:00:56:de:f4:55:95:6c:fb:ba: + 64:dd:62:8b:df:0b:77:32:eb:62:cc:26:9a:9b:bb: + aa:62:83:4c:b4:06:7a:30:c8:29:bf:ed:06:4d:97: + b9:1c:c4:31:2b:d5:5f:bc:53:12:17:9c:99:57:29: + 66:77:61:21:31:07:2e:25:49:9d:18:f2:ee:f3:2b: + 71:8c:b5:ba:39:07:49:77:fc:ef:2e:92:90:05:8d: + 2d:2f:77:7b:ef:43:bf:35:bb:9a:d8:f9:73:a7:2c: + f2:d0:57:ee:28:4e:26:5f:8f:90:68:09:2f:b8:f8: + dc:06:e9:2e:9a:3e:51:a7:d1:22:c4:0a:a7:38:48: + 6c:b3:f9:ff:7d:ab:86:57:e3:ba:d6:85:78:77:ba: + 43:ea:48:7f:f6:d8:be:23:6d:1e:bf:d1:36:6c:58: + 5c:f1:ee:a4:19:54:1a:f5:03:d2:76:e6:e1:8c:bd: + 3c:b3:d3:48:4b:e2:c8:f8:7f:92:a8:76:46:9c:42: + 65:3e:a4:1e:c1:07:03:5a:46:2d:b8:97:f3:b7:d5: + b2:55:21:ef:ba:dc:4c:00:97:fb:14:95:27:33:bf: + e8:43:47:46:d2:08:99:16:60:3b:9a:7e:d2:e6:ed: + 38:ea:ec:01:1e:3c:48:56:49:09:c7:4c:37:00:9e: + 88:0e:c0:73:e1:6f:66:e9:72:47:30:3e:10:e5:0b: + 03:c9:9a:42:00:6c:c5:94:7e:61:c4:8a:df:7f:82: + 1a:0b:59:c4:59:32:77:b3:bc:60:69:56:39:fd:b4: + 06:7b:2c:d6:64:36:d9:bd:48:ed:84:1f:7e:a5:22: + 8f:2a:b8:42:f4:82:b7:d4:53:90:78:4e:2d:1a:fd: + 81:6f:44:d7:3b:01:74:96:42:e0:00:e2:2e:6b:ea: + c5:ee:72:ac:bb:bf:fe:ea:aa:a8:f8:dc:f6:b2:79: + 8a:b6:67 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 9D:C0:67:A6:0C:22:D9:26:F5:45:AB:A6:65:52:11:27:D8:45:AC:63 + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha384WithRSAEncryption + b3:57:4d:10:62:4e:3a:e4:ac:ea:b8:1c:af:32:23:c8:b3:49: + 5a:51:9c:76:28:8d:79:aa:57:46:17:d5:f5:52:f6:b7:44:e8: + 08:44:bf:18:84:d2:0b:80:cd:c5:12:fd:00:55:05:61:87:41: + dc:b5:24:9e:3c:c4:d8:c8:fb:70:9e:2f:78:96:83:20:36:de: + 7c:0f:69:13:88:a5:75:36:98:08:a6:c6:df:ac:ce:e3:58:d6: + b7:3e:de:ba:f3:eb:34:40:d8:a2:81:f5:78:3f:2f:d5:a5:fc: + d9:a2:d4:5e:04:0e:17:ad:fe:41:f0:e5:b2:72:fa:44:82:33: + 42:e8:2d:58:f7:56:8c:62:3f:ba:42:b0:9c:0c:5c:7e:2e:65: + 26:5c:53:4f:00:b2:78:7e:a1:0d:99:2d:8d:b8:1d:8e:a2:c4: + b0:fd:60:d0:30:a4:8e:c8:04:62:a9:c4:ed:35:de:7a:97:ed: + 0e:38:5e:92:2f:93:70:a5:a9:9c:6f:a7:7d:13:1d:7e:c6:08: + 48:b1:5e:67:eb:51:08:25:e9:e6:25:6b:52:29:91:9c:d2:39: + 73:08:57:de:99:06:b4:5b:9d:10:06:e1:c2:00:a8:b8:1c:4a: + 02:0a:14:d0:c1:41:ca:fb:8c:35:21:7d:82:38:f2:a9:54:91: + 19:35:93:94:6d:6a:3a:c5:b2:d0:bb:89:86:93:e8:9b:c9:0f: + 3a:a7:7a:b8:a1:f0:78:46:fa:fc:37:2f:e5:8a:84:f3:df:fe: + 04:d9:a1:68:a0:2f:24:e2:09:95:06:d5:95:ca:e1:24:96:eb: + 7c:f6:93:05:bb:ed:73:e9:2d:d1:75:39:d7:e7:24:db:d8:4e: + 5f:43:8f:9e:d0:14:39:bf:55:70:48:99:57:31:b4:9c:ee:4a: + 98:03:96:30:1f:60:06:ee:1b:23:fe:81:60:23:1a:47:62:85: + a5:cc:19:34:80:6f:b3:ac:1a:e3:9f:f0:7b:48:ad:d5:01:d9: + 67:b6:a9:72:93:ea:2d:66:b5:b2:b8:e4:3d:3c:b2:ef:4c:8c: + ea:eb:07:bf:ab:35:9a:55:86:bc:18:a6:b5:a8:5e:b4:83:6c: + 6b:69:40:d3:9f:dc:f1:c3:69:6b:b9:e1:6d:09:f4:f1:aa:50: + 76:0a:7a:7d:7a:17:a1:55:96:42:99:31:09:dd:60:11:8d:05: + 30:7e:e6:8e:46:d1:9d:14:da:c7:17:e4:05:96:8c:c4:24:b5: + 1b:cf:14:07:b2:40:f8:a3:9e:41:86:bc:04:d0:6b:96:c8:2a: + 80:34:fd:bf:ef:06:a3:dd:58:c5:85:3d:3e:8f:fe:9e:29:e0: + b6:b8:09:68:19:1c:18:43 +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz +dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG +A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U +cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf +qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ +JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ ++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS +s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 +HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 +70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG +V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S +qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S +5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia +C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX +OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE +FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 +KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B +8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ +MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc +0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ +u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF +u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH +YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 +GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO +RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e +KeC2uAloGRwYQw== +-----END CERTIFICATE----- + +AffirmTrust Premium ECC +# Issuer: CN=AffirmTrust Premium ECC,O=AffirmTrust,C=US +# Serial Number:74:97:25:8a:c7:3f:7a:54 +# Subject: CN=AffirmTrust Premium ECC,O=AffirmTrust,C=US +# Not Valid Before: Fri Jan 29 14:20:24 2010 +# Not Valid After : Mon Dec 31 14:20:24 2040 +# Fingerprint (MD5): 64:B0:09:55:CF:B1:D5:99:E2:BE:13:AB:A6:5D:EA:4D +# Fingerprint (SHA1): B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=64:B0:09:55:CF:B1:D5:99:E2:BE:13:AB:A6:5D:EA:4D +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8401224907861490260 (0x7497258ac73f7a54) + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Premium ECC + Validity + Not Before: Jan 29 14:20:24 2010 GMT + Not After : Dec 31 14:20:24 2040 GMT + Subject: C=US, O=AffirmTrust, CN=AffirmTrust Premium ECC + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:0d:30:5e:1b:15:9d:03:d0:a1:79:35:b7:3a:3c: + 92:7a:ca:15:1c:cd:62:f3:9c:26:5c:07:3d:e5:54: + fa:a3:d6:cc:12:ea:f4:14:5f:e8:8e:19:ab:2f:2e: + 48:e6:ac:18:43:78:ac:d0:37:c3:bd:b2:cd:2c:e6: + 47:e2:1a:e6:63:b8:3d:2e:2f:78:c4:4f:db:f4:0f: + a4:68:4c:55:72:6b:95:1d:4e:18:42:95:78:cc:37: + 3c:91:e2:9b:65:2b:29 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Subject Key Identifier: + 9A:AF:29:7A:C0:11:35:35:26:51:30:00:C3:6A:FE:40:D5:AE:D6:3C + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: ecdsa-with-SHA384 + 30:64:02:30:17:09:f3:87:88:50:5a:af:c8:c0:42:bf:47:5f: + f5:6c:6a:86:e0:c4:27:74:e4:38:53:d7:05:7f:1b:34:e3:c6: + 2f:b3:ca:09:3c:37:9d:d7:e7:b8:46:f1:fd:a1:e2:71:02:30: + 42:59:87:43:d4:51:df:ba:d3:09:32:5a:ce:88:7e:57:3d:9c: + 5f:42:6b:f5:07:2d:b5:f0:82:93:f9:59:6f:ae:64:fa:58:e5: + 8b:1e:e3:63:be:b5:81:cd:6f:02:8c:79 +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ +cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ +BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt +VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D +0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 +ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G +A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs +aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I +flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== +-----END CERTIFICATE----- + +Certum Trusted Network CA +# Issuer: CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL +# Serial Number: 279744 (0x444c0) +# Subject: CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL +# Not Valid Before: Wed Oct 22 12:07:37 2008 +# Not Valid After : Mon Dec 31 12:07:37 2029 +# Fingerprint (MD5): D5:E9:81:40:C5:18:69:FC:46:2C:89:75:62:0F:AA:78 +# Fingerprint (SHA1): 07:E0:32:E0:20:B7:2C:3F:19:2F:06:28:A2:59:3A:19:A7:0F:06:9E +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=D5:E9:81:40:C5:18:69:FC:46:2C:89:75:62:0F:AA:78 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 279744 (0x444c0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=PL, O=Unizeto Technologies S.A., OU=Certum Certification Authority, CN=Certum Trusted Network CA + Validity + Not Before: Oct 22 12:07:37 2008 GMT + Not After : Dec 31 12:07:37 2029 GMT + Subject: C=PL, O=Unizeto Technologies S.A., OU=Certum Certification Authority, CN=Certum Trusted Network CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:e3:fb:7d:a3:72:ba:c2:f0:c9:14:87:f5:6b:01: + 4e:e1:6e:40:07:ba:6d:27:5d:7f:f7:5b:2d:b3:5a: + c7:51:5f:ab:a4:32:a6:61:87:b6:6e:0f:86:d2:30: + 02:97:f8:d7:69:57:a1:18:39:5d:6a:64:79:c6:01: + 59:ac:3c:31:4a:38:7c:d2:04:d2:4b:28:e8:20:5f: + 3b:07:a2:cc:4d:73:db:f3:ae:4f:c7:56:d5:5a:a7: + 96:89:fa:f3:ab:68:d4:23:86:59:27:cf:09:27:bc: + ac:6e:72:83:1c:30:72:df:e0:a2:e9:d2:e1:74:75: + 19:bd:2a:9e:7b:15:54:04:1b:d7:43:39:ad:55:28: + c5:e2:1a:bb:f4:c0:e4:ae:38:49:33:cc:76:85:9f: + 39:45:d2:a4:9e:f2:12:8c:51:f8:7c:e4:2d:7f:f5: + ac:5f:eb:16:9f:b1:2d:d1:ba:cc:91:42:77:4c:25: + c9:90:38:6f:db:f0:cc:fb:8e:1e:97:59:3e:d5:60: + 4e:e6:05:28:ed:49:79:13:4b:ba:48:db:2f:f9:72: + d3:39:ca:fe:1f:d8:34:72:f5:b4:40:cf:31:01:c3: + ec:de:11:2d:17:5d:1f:b8:50:d1:5e:19:a7:69:de: + 07:33:28:ca:50:95:f9:a7:54:cb:54:86:50:45:a9: + f9:49 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 08:76:CD:CB:07:FF:24:F6:C5:CD:ED:BB:90:BC:E2:84:37:46:75:F7 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + a6:a8:ad:22:ce:01:3d:a6:a3:ff:62:d0:48:9d:8b:5e:72:b0: + 78:44:e3:dc:1c:af:09:fd:23:48:fa:bd:2a:c4:b9:55:04:b5: + 10:a3:8d:27:de:0b:82:63:d0:ee:de:0c:37:79:41:5b:22:b2: + b0:9a:41:5c:a6:70:e0:d4:d0:77:cb:23:d3:00:e0:6c:56:2f: + e1:69:0d:0d:d9:aa:bf:21:81:50:d9:06:a5:a8:ff:95:37:d0: + aa:fe:e2:b3:f5:99:2d:45:84:8a:e5:42:09:d7:74:02:2f:f7: + 89:d8:99:e9:bc:27:d4:47:8d:ba:0d:46:1c:77:cf:14:a4:1c: + b9:a4:31:c4:9c:28:74:03:34:ff:33:19:26:a5:e9:0d:74:b7: + 3e:97:c6:76:e8:27:96:a3:66:dd:e1:ae:f2:41:5b:ca:98:56: + 83:73:70:e4:86:1a:d2:31:41:ba:2f:be:2d:13:5a:76:6f:4e: + e8:4e:81:0e:3f:5b:03:22:a0:12:be:66:58:11:4a:cb:03:c4: + b4:2a:2a:2d:96:17:e0:39:54:bc:48:d3:76:27:9d:9a:2d:06: + a6:c9:ec:39:d2:ab:db:9f:9a:0b:27:02:35:29:b1:40:95:e7: + f9:e8:9c:55:88:19:46:d6:b7:34:f5:7e:ce:39:9a:d9:38:f1: + 51:f7:4f:2c +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM +MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D +ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU +cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 +WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg +Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw +IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH +UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM +TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU +BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM +kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x +AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y +sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL +I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 +J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY +VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +TWCA Root Certification Authority +# Issuer: CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW +# Serial Number: 1 (0x1) +# Subject: CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW +# Not Valid Before: Thu Aug 28 07:24:33 2008 +# Not Valid After : Tue Dec 31 15:59:59 2030 +# Fingerprint (MD5): AA:08:8F:F6:F9:7B:B7:F2:B1:A7:1E:9B:EA:EA:BD:79 +# Fingerprint (SHA1): CF:9E:87:6D:D3:EB:FC:42:26:97:A3:B5:A3:7A:A0:76:A9:06:23:48 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=AA:08:8F:F6:F9:7B:B7:F2:B1:A7:1E:9B:EA:EA:BD:79 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Root Certification Authority + Validity + Not Before: Aug 28 07:24:33 2008 GMT + Not After : Dec 31 15:59:59 2030 GMT + Subject: C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Root Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b0:7e:72:b8:a4:03:94:e6:a7:de:09:38:91:4a: + 11:40:87:a7:7c:59:64:14:7b:b5:11:10:dd:fe:bf: + d5:c0:bb:56:e2:85:25:f4:35:72:0f:f8:53:d0:41: + e1:44:01:c2:b4:1c:c3:31:42:16:47:85:33:22:76: + b2:0a:6f:0f:e5:25:50:4f:85:86:be:bf:98:2e:10: + 67:1e:be:11:05:86:05:90:c4:59:d0:7c:78:10:b0: + 80:5c:b7:e1:c7:2b:75:cb:7c:9f:ae:b5:d1:9d:23: + 37:63:a7:dc:42:a2:2d:92:04:1b:50:c1:7b:b8:3e: + 1b:c9:56:04:8b:2f:52:9b:ad:a9:56:e9:c1:ff:ad: + a9:58:87:30:b6:81:f7:97:45:fc:19:57:3b:2b:6f: + e4:47:f4:99:45:fe:1d:f1:f8:97:a3:88:1d:37:1c: + 5c:8f:e0:76:25:9a:50:f8:a0:54:ff:44:90:76:23: + d2:32:c6:c3:ab:06:bf:fc:fb:bf:f3:ad:7d:92:62: + 02:5b:29:d3:35:a3:93:9a:43:64:60:5d:b2:fa:32: + ff:3b:04:af:4d:40:6a:f9:c7:e3:ef:23:fd:6b:cb: + e5:0f:8b:38:0d:ee:0a:fc:fe:0f:98:9f:30:31:dd: + 6c:52:65:f9:8b:81:be:22:e1:1c:58:03:ba:91:1b: + 89:07 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 6A:38:5B:26:8D:DE:8B:5A:F2:4F:7A:54:83:19:18:E3:08:35:A6:BA + Signature Algorithm: sha1WithRSAEncryption + 3c:d5:77:3d:da:df:89:ba:87:0c:08:54:6a:20:50:92:be:b0: + 41:3d:b9:26:64:83:0a:2f:e8:40:c0:97:28:27:82:30:4a:c9: + 93:ff:6a:e7:a6:00:7f:89:42:9a:d6:11:e5:53:ce:2f:cc:f2: + da:05:c4:fe:e2:50:c4:3a:86:7d:cc:da:7e:10:09:3b:92:35: + 2a:53:b2:fe:eb:2b:05:d9:6c:5d:e6:d0:ef:d3:6a:66:9e:15: + 28:85:7a:e8:82:00:ac:1e:a7:09:69:56:42:d3:68:51:18:be: + 54:9a:bf:44:41:ba:49:be:20:ba:69:5c:ee:b8:77:cd:ce:6c: + 1f:ad:83:96:18:7d:0e:b5:14:39:84:f1:28:e9:2d:a3:9e:7b: + 1e:7a:72:5a:83:b3:79:6f:ef:b4:fc:d0:0a:a5:58:4f:46:df: + fb:6d:79:59:f2:84:22:52:ae:0f:cc:fb:7c:3b:e7:6a:ca:47: + 61:c3:7a:f8:d3:92:04:1f:b8:20:84:e1:36:54:16:c7:40:de: + 3b:8a:73:dc:df:c6:09:4c:df:ec:da:ff:d4:53:42:a1:c9:f2: + 62:1d:22:83:3c:97:c5:f9:19:62:27:ac:65:22:d7:d3:3c:c6: + e5:8e:b2:53:cc:49:ce:bc:30:fe:7b:0e:33:90:fb:ed:d2:14: + 91:1f:07:af +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES +MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU +V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz +WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO +LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE +AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH +K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX +RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z +rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx +3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq +hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC +MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls +XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D +lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn +aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ +YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +Security Communication RootCA2 +# Issuer: OU=Security Communication RootCA2,O="SECOM Trust Systems CO.,LTD.",C=JP +# Serial Number: 0 (0x0) +# Subject: OU=Security Communication RootCA2,O="SECOM Trust Systems CO.,LTD.",C=JP +# Not Valid Before: Fri May 29 05:00:39 2009 +# Not Valid After : Tue May 29 05:00:39 2029 +# Fingerprint (MD5): 6C:39:7D:A4:0E:55:59:B2:3F:D6:41:B1:12:50:DE:43 +# Fingerprint (SHA1): 5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=6C:39:7D:A4:0E:55:59:B2:3F:D6:41:B1:12:50:DE:43 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=JP, O=SECOM Trust Systems CO.,LTD., OU=Security Communication RootCA2 + Validity + Not Before: May 29 05:00:39 2009 GMT + Not After : May 29 05:00:39 2029 GMT + Subject: C=JP, O=SECOM Trust Systems CO.,LTD., OU=Security Communication RootCA2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d0:15:39:52:b1:52:b3:ba:c5:59:82:c4:5d:52: + ae:3a:43:65:80:4b:c7:f2:96:bc:db:36:97:d6:a6: + 64:8c:a8:5e:f0:e3:0a:1c:f7:df:97:3d:4b:ae:f6: + 5d:ec:21:b5:41:ab:cd:b9:7e:76:9f:be:f9:3e:36: + 34:a0:3b:c1:f6:31:11:45:74:93:3d:57:80:c5:f9: + 89:99:ca:e5:ab:6a:d4:b5:da:41:90:10:c1:d6:d6: + 42:89:c2:bf:f4:38:12:95:4c:54:05:f7:36:e4:45: + 83:7b:14:65:d6:dc:0c:4d:d1:de:7e:0c:ab:3b:c4: + 15:be:3a:56:a6:5a:6f:76:69:52:a9:7a:b9:c8:eb: + 6a:9a:5d:52:d0:2d:0a:6b:35:16:09:10:84:d0:6a: + ca:3a:06:00:37:47:e4:7e:57:4f:3f:8b:eb:67:b8: + 88:aa:c5:be:53:55:b2:91:c4:7d:b9:b0:85:19:06: + 78:2e:db:61:1a:fa:85:f5:4a:91:a1:e7:16:d5:8e: + a2:39:df:94:b8:70:1f:28:3f:8b:fc:40:5e:63:83: + 3c:83:2a:1a:99:6b:cf:de:59:6a:3b:fc:6f:16:d7: + 1f:fd:4a:10:eb:4e:82:16:3a:ac:27:0c:53:f1:ad: + d5:24:b0:6b:03:50:c1:2d:3c:16:dd:44:34:27:1a: + 75:fb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 0A:85:A9:77:65:05:98:7C:40:81:F8:0F:97:2C:38:F1:0A:EC:3C:CF + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 4c:3a:a3:44:ac:b9:45:b1:c7:93:7e:c8:0b:0a:42:df:64:ea: + 1c:ee:59:6c:08:ba:89:5f:6a:ca:4a:95:9e:7a:8f:07:c5:da: + 45:72:82:71:0e:3a:d2:cc:6f:a7:b4:a1:23:bb:f6:24:9f:cb: + 17:fe:8c:a6:ce:c2:d2:db:cc:8d:fc:71:fc:03:29:c1:6c:5d: + 33:5f:64:b6:65:3b:89:6f:18:76:78:f5:dc:a2:48:1f:19:3f: + 8e:93:eb:f1:fa:17:ee:cd:4e:e3:04:12:55:d6:e5:e4:dd:fb: + 3e:05:7c:e2:1d:5e:c6:a7:bc:97:4f:68:3a:f5:e9:2e:0a:43: + b6:af:57:5c:62:68:7c:b7:fd:a3:8a:84:a0:ac:62:be:2b:09: + 87:34:f0:6a:01:bb:9b:29:56:3c:fe:00:37:cf:23:6c:f1:4e: + aa:b6:74:46:12:6c:91:ee:34:d5:ec:9a:91:e7:44:be:90:31: + 72:d5:49:02:f6:02:e5:f4:1f:eb:7c:d9:96:55:a9:ff:ec:8a: + f9:99:47:ff:35:5a:02:aa:04:cb:8a:5b:87:71:29:91:bd:a4: + b4:7a:0d:bd:9a:f5:57:23:00:07:21:17:3f:4a:39:d1:05:49: + 0b:a7:b6:37:81:a5:5d:8c:aa:33:5e:81:28:7c:a7:7d:27:eb: + 00:ae:8d:37 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX +DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy +dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj +YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV +OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr +zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM +VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ +hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO +ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw +awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs +OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF +coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc +okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 +t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy +1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ +SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +EC-ACC +# Issuer: CN=EC-ACC,OU=Jerarquia Entitats de Certificacio Catalanes,OU=Vegeu https://www.catcert.net/verarrel (c)03,OU=Serveis Publics de Certificacio,O=Agencia Catalana de Certificacio (NIF Q-0801176-I),C=ES +# Serial Number:ee:2b:3d:eb:d4:21:de:14:a8:62:ac:04:f3:dd:c4:01 +# Subject: CN=EC-ACC,OU=Jerarquia Entitats de Certificacio Catalanes,OU=Vegeu https://www.catcert.net/verarrel (c)03,OU=Serveis Publics de Certificacio,O=Agencia Catalana de Certificacio (NIF Q-0801176-I),C=ES +# Not Valid Before: Tue Jan 07 23:00:00 2003 +# Not Valid After : Tue Jan 07 22:59:59 2031 +# Fingerprint (MD5): EB:F5:9D:29:0D:61:F9:42:1F:7C:C2:BA:6D:E3:15:09 +# Fingerprint (SHA1): 28:90:3A:63:5B:52:80:FA:E6:77:4C:0B:6D:A7:D6:BA:A6:4A:F2:E8 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=EB:F5:9D:29:0D:61:F9:42:1F:7C:C2:BA:6D:E3:15:09 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + (Negative)11:d4:c2:14:2b:de:21:eb:57:9d:53:fb:0c:22:3b:ff + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=ES, O=Agencia Catalana de Certificacio (NIF Q-0801176-I), OU=Serveis Publics de Certificacio, OU=Vegeu https://www.catcert.net/verarrel (c)03, OU=Jerarquia Entitats de Certificacio Catalanes, CN=EC-ACC + Validity + Not Before: Jan 7 23:00:00 2003 GMT + Not After : Jan 7 22:59:59 2031 GMT + Subject: C=ES, O=Agencia Catalana de Certificacio (NIF Q-0801176-I), OU=Serveis Publics de Certificacio, OU=Vegeu https://www.catcert.net/verarrel (c)03, OU=Jerarquia Entitats de Certificacio Catalanes, CN=EC-ACC + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b3:22:c7:4f:e2:97:42:95:88:47:83:40:f6:1d: + 17:f3:83:73:24:1e:51:f3:98:8a:c3:92:b8:ff:40: + 90:05:70:87:60:c9:00:a9:b5:94:65:19:22:15:17: + c2:43:6c:66:44:9a:0d:04:3e:39:6f:a5:4b:7a:aa: + 63:b7:8a:44:9d:d9:63:91:84:66:e0:28:0f:ba:42: + e3:6e:8e:f7:14:27:93:69:ee:91:0e:a3:5f:0e:b1: + eb:66:a2:72:4f:12:13:86:65:7a:3e:db:4f:07:f4: + a7:09:60:da:3a:42:99:c7:b2:7f:b3:16:95:1c:c7: + f9:34:b5:94:85:d5:99:5e:a0:48:a0:7e:e7:17:65: + b8:a2:75:b8:1e:f3:e5:42:7d:af:ed:f3:8a:48:64: + 5d:82:14:93:d8:c0:e4:ff:b3:50:72:f2:76:f6:b3: + 5d:42:50:79:d0:94:3e:6b:0c:00:be:d8:6b:0e:4e: + 2a:ec:3e:d2:cc:82:a2:18:65:33:13:77:9e:9a:5d: + 1a:13:d8:c3:db:3d:c8:97:7a:ee:70:ed:a7:e6:7c: + db:71:cf:2d:94:62:df:6d:d6:f5:38:be:3f:a5:85: + 0a:19:b8:a8:d8:09:75:42:70:c4:ea:ef:cb:0e:c8: + 34:a8:12:22:98:0c:b8:13:94:b6:4b:ec:f0:d0:90: + e7:27 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + email:ec_acc@catcert.net + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + A0:C3:8B:44:AA:37:A5:45:BF:97:80:5A:D1:F1:78:A2:9B:E9:5D:8D + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.15096.1.3.1.10 + CPS: https://www.catcert.net/verarrel + User Notice: + Explicit Text: Vegeu https://www.catcert.net/verarrel + + Signature Algorithm: sha1WithRSAEncryption + a0:48:5b:82:01:f6:4d:48:b8:39:55:35:9c:80:7a:53:99:d5: + 5a:ff:b1:71:3b:cc:39:09:94:5e:d6:da:ef:be:01:5b:5d:d3: + 1e:d8:fd:7d:4f:cd:a0:41:e0:34:93:bf:cb:e2:86:9c:37:92: + 90:56:1c:dc:eb:29:05:e5:c4:9e:c7:35:df:8a:0c:cd:c5:21: + 43:e9:aa:88:e5:35:c0:19:42:63:5a:02:5e:a4:48:18:3a:85: + 6f:dc:9d:bc:3f:9d:9c:c1:87:b8:7a:61:08:e9:77:0b:7f:70: + ab:7a:dd:d9:97:2c:64:1e:85:bf:bc:74:96:a1:c3:7a:12:ec: + 0c:1a:6e:83:0c:3c:e8:72:46:9f:fb:48:d5:5e:97:e6:b1:a1: + f8:e4:ef:46:25:94:9c:89:db:69:38:be:ec:5c:0e:56:c7:65: + 51:e5:50:88:88:bf:42:d5:2b:3d:e5:f9:ba:9e:2e:b3:ca:f4: + 73:92:02:0b:be:4c:66:eb:20:fe:b9:cb:b5:99:7f:e6:b6:13: + fa:ca:4b:4d:d9:ee:53:46:06:3b:c6:4e:ad:93:5a:81:7e:6c: + 2a:4b:6a:05:45:8c:f2:21:a4:31:90:87:6c:65:9c:9d:a5:60: + 95:3a:52:7f:f5:d1:ab:08:6e:f3:ee:5b:f9:88:3d:7e:b8:6f: + 6e:03:e4:42 +-----BEGIN CERTIFICATE----- +MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB +8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy +dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1 +YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3 +dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh +IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD +LUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQG +EwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8g +KE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBD +ZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQu +bmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMg +ZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUNDMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R +85iKw5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm +4CgPukLjbo73FCeTae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaV +HMf5NLWUhdWZXqBIoH7nF2W4onW4HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNd +QlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0aE9jD2z3Il3rucO2n5nzbcc8t +lGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw0JDnJwIDAQAB +o4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4 +opvpXY0wfwYDVR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBo +dHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidW +ZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAwDQYJKoZIhvcN +AQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJlF7W2u++AVtd0x7Y +/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNaAl6k +SBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhy +Rp/7SNVel+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOS +Agu+TGbrIP65y7WZf+a2E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xl +nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI= +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2011 +# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2011,O=Hellenic Academic and Research Institutions Cert. Authority,C=GR +# Serial Number: 0 (0x0) +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2011,O=Hellenic Academic and Research Institutions Cert. Authority,C=GR +# Not Valid Before: Tue Dec 06 13:49:52 2011 +# Not Valid After : Mon Dec 01 13:49:52 2031 +# Fingerprint (MD5): 73:9F:4C:4B:73:5B:79:E9:FA:BA:1C:EF:6E:CB:D5:C9 +# Fingerprint (SHA1): FE:45:65:9B:79:03:5B:98:A1:61:B5:51:2E:AC:DA:58:09:48:22:4D +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +======================================================= +MD5 Fingerprint=73:9F:4C:4B:73:5B:79:E9:FA:BA:1C:EF:6E:CB:D5:C9 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=GR, O=Hellenic Academic and Research Institutions Cert. Authority, CN=Hellenic Academic and Research Institutions RootCA 2011 + Validity + Not Before: Dec 6 13:49:52 2011 GMT + Not After : Dec 1 13:49:52 2031 GMT + Subject: C=GR, O=Hellenic Academic and Research Institutions Cert. Authority, CN=Hellenic Academic and Research Institutions RootCA 2011 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:a9:53:00:e3:2e:a6:f6:8e:fa:60:d8:2d:95:3e: + f8:2c:2a:54:4e:cd:b9:84:61:94:58:4f:8f:3d:8b: + e4:43:f3:75:89:8d:51:e4:c3:37:d2:8a:88:4d:79: + 1e:b7:12:dd:43:78:4a:8a:92:e6:d7:48:d5:0f:a4: + 3a:29:44:35:b8:07:f6:68:1d:55:cd:38:51:f0:8c: + 24:31:85:af:83:c9:7d:e9:77:af:ed:1a:7b:9d:17: + f9:b3:9d:38:50:0f:a6:5a:79:91:80:af:37:ae:a6: + d3:31:fb:b5:26:09:9d:3c:5a:ef:51:c5:2b:df:96: + 5d:eb:32:1e:02:da:70:49:ec:6e:0c:c8:9a:37:8d: + f7:f1:36:60:4b:26:2c:82:9e:d0:78:f3:0d:0f:63: + a4:51:30:e1:f9:2b:27:12:07:d8:ea:bd:18:62:98: + b0:59:37:7d:be:ee:f3:20:51:42:5a:83:ef:93:ba: + 69:15:f1:62:9d:9f:99:39:82:a1:b7:74:2e:8b:d4: + c5:0b:7b:2f:f0:c8:0a:da:3d:79:0a:9a:93:1c:a5: + 28:72:73:91:43:9a:a7:d1:4d:85:84:b9:a9:74:8f: + 14:40:c7:dc:de:ac:41:64:6c:b4:19:9b:02:63:6d: + 24:64:8f:44:b2:25:ea:ce:5d:74:0c:63:32:5c:8d: + 87:e5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + A6:91:42:FD:13:61:4A:23:9E:08:A4:29:E5:D8:13:04:23:EE:41:25 + X509v3 Name Constraints: + Permitted: + DNS:.gr + DNS:.eu + DNS:.edu + DNS:.org + email:.gr + email:.eu + email:.edu + email:.org + + Signature Algorithm: sha1WithRSAEncryption + 1f:ef:79:41:e1:7b:6e:3f:b2:8c:86:37:42:4a:4e:1c:37:1e: + 8d:66:ba:24:81:c9:4f:12:0f:21:c0:03:97:86:25:6d:5d:d3: + 22:29:a8:6c:a2:0d:a9:eb:3d:06:5b:99:3a:c7:cc:c3:9a:34: + 7f:ab:0e:c8:4e:1c:e1:fa:e4:dc:cd:0d:be:bf:24:fe:6c:e7: + 6b:c2:0d:c8:06:9e:4e:8d:61:28:a6:6a:fd:e5:f6:62:ea:18: + 3c:4e:a0:53:9d:b2:3a:9c:eb:a5:9c:91:16:b6:4d:82:e0:0c: + 05:48:a9:6c:f5:cc:f8:cb:9d:49:b4:f0:02:a5:fd:70:03:ed: + 8a:21:a5:ae:13:86:49:c3:33:73:be:87:3b:74:8b:17:45:26: + 4c:16:91:83:fe:67:7d:cd:4d:63:67:fa:f3:03:12:96:78:06: + 8d:b1:67:ed:8e:3f:be:9f:4f:02:f5:b3:09:2f:f3:4c:87:df: + 2a:cb:95:7c:01:cc:ac:36:7a:bf:a2:73:7a:f7:8f:c1:b5:9a: + a1:14:b2:8f:33:9f:0d:ef:22:dc:66:7b:84:bd:45:17:06:3d: + 3c:ca:b9:77:34:8f:ca:ea:cf:3f:31:3e:e3:88:e3:80:49:25: + c8:97:b5:9d:9a:99:4d:b0:3c:f8:4a:00:9b:64:dd:9f:39:4b: + d1:27:d7:b8 +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix +RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p +YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw +NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK +EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl +cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz +dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ +fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns +bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD +75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP +FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV +HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp +5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu +b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA +A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p +6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 +dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys +Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI +l7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- + +Actalis Authentication Root CA +# Issuer: CN=Actalis Authentication Root CA,O=Actalis S.p.A./03358520967,L=Milan,C=IT +# Serial Number:57:0a:11:97:42:c4:e3:cc +# Subject: CN=Actalis Authentication Root CA,O=Actalis S.p.A./03358520967,L=Milan,C=IT +# Not Valid Before: Thu Sep 22 11:22:02 2011 +# Not Valid After : Sun Sep 22 11:22:02 2030 +# Fingerprint (MD5): 69:C1:0D:4F:07:A3:1B:C3:FE:56:3D:04:BC:11:F6:A6 +# Fingerprint (SHA1): F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=69:C1:0D:4F:07:A3:1B:C3:FE:56:3D:04:BC:11:F6:A6 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 6271844772424770508 (0x570a119742c4e3cc) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=IT, L=Milan, O=Actalis S.p.A./03358520967, CN=Actalis Authentication Root CA + Validity + Not Before: Sep 22 11:22:02 2011 GMT + Not After : Sep 22 11:22:02 2030 GMT + Subject: C=IT, L=Milan, O=Actalis S.p.A./03358520967, CN=Actalis Authentication Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:a7:c6:c4:a5:29:a4:2c:ef:e5:18:c5:b0:50:a3: + 6f:51:3b:9f:0a:5a:c9:c2:48:38:0a:c2:1c:a0:18: + 7f:91:b5:87:b9:40:3f:dd:1d:68:1f:08:83:d5:2d: + 1e:88:a0:f8:8f:56:8f:6d:99:02:92:90:16:d5:5f: + 08:6c:89:d7:e1:ac:bc:20:c2:b1:e0:83:51:8a:69: + 4d:00:96:5a:6f:2f:c0:44:7e:a3:0e:e4:91:cd:58: + ee:dc:fb:c7:1e:45:47:dd:27:b9:08:01:9f:a6:21: + 1d:f5:41:2d:2f:4c:fd:28:ad:e0:8a:ad:22:b4:56: + 65:8e:86:54:8f:93:43:29:de:39:46:78:a3:30:23: + ba:cd:f0:7d:13:57:c0:5d:d2:83:6b:48:4c:c4:ab: + 9f:80:5a:5b:3a:bd:c9:a7:22:3f:80:27:33:5b:0e: + b7:8a:0c:5d:07:37:08:cb:6c:d2:7a:47:22:44:35: + c5:cc:cc:2e:8e:dd:2a:ed:b7:7d:66:0d:5f:61:51: + 22:55:1b:e3:46:e3:e3:3d:d0:35:62:9a:db:af:14: + c8:5b:a1:cc:89:1b:e1:30:26:fc:a0:9b:1f:81:a7: + 47:1f:04:eb:a3:39:92:06:9f:99:d3:bf:d3:ea:4f: + 50:9c:19:fe:96:87:1e:3c:65:f6:a3:18:24:83:86: + 10:e7:54:3e:a8:3a:76:24:4f:81:21:c5:e3:0f:02: + f8:93:94:47:20:bb:fe:d4:0e:d3:68:b9:dd:c4:7a: + 84:82:e3:53:54:79:dd:db:9c:d2:f2:07:9b:2e:b6: + bc:3e:ed:85:6d:ef:25:11:f2:97:1a:42:61:f7:4a: + 97:e8:8b:b1:10:07:fa:65:81:b2:a2:39:cf:f7:3c: + ff:18:fb:c6:f1:5a:8b:59:e2:02:ac:7b:92:d0:4e: + 14:4f:59:45:f6:0c:5e:28:5f:b0:e8:3f:45:cf:cf: + af:9b:6f:fb:84:d3:77:5a:95:6f:ac:94:84:9e:ee: + bc:c0:4a:8f:4a:93:f8:44:21:e2:31:45:61:50:4e: + 10:d8:e3:35:7c:4c:19:b4:de:05:bf:a3:06:9f:c8: + b5:cd:e4:1f:d7:17:06:0d:7a:95:74:55:0d:68:1a: + fc:10:1b:62:64:9d:6d:e0:95:a0:c3:94:07:57:0d: + 14:e6:bd:05:fb:b8:9f:e6:df:8b:e2:c6:e7:7e:96: + f6:53:c5:80:34:50:28:58:f0:12:50:71:17:30:ba: + e6:78:63:bc:f4:b2:ad:9b:2b:b2:fe:e1:39:8c:5e: + ba:0b:20:94:de:7b:83:b8:ff:e3:56:8d:b7:11:e9: + 3b:8c:f2:b1:c1:5d:9d:a4:0b:4c:2b:d9:b2:18:f5: + b5:9f:4b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 52:D8:88:3A:C8:9F:78:66:ED:89:F3:7B:38:70:94:C9:02:02:36:D0 + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:52:D8:88:3A:C8:9F:78:66:ED:89:F3:7B:38:70:94:C9:02:02:36:D0 + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 0b:7b:72:87:c0:60:a6:49:4c:88:58:e6:1d:88:f7:14:64:48: + a6:d8:58:0a:0e:4f:13:35:df:35:1d:d4:ed:06:31:c8:81:3e: + 6a:d5:dd:3b:1a:32:ee:90:3d:11:d2:2e:f4:8e:c3:63:2e:23: + 66:b0:67:be:6f:b6:c0:13:39:60:aa:a2:34:25:93:75:52:de: + a7:9d:ad:0e:87:89:52:71:6a:16:3c:19:1d:83:f8:9a:29:65: + be:f4:3f:9a:d9:f0:f3:5a:87:21:71:80:4d:cb:e0:38:9b:3f: + bb:fa:e0:30:4d:cf:86:d3:65:10:19:18:d1:97:02:b1:2b:72: + 42:68:ac:a0:bd:4e:5a:da:18:bf:6b:98:81:d0:fd:9a:be:5e: + 15:48:cd:11:15:b9:c0:29:5c:b4:e8:88:f7:3e:36:ae:b7:62: + fd:1e:62:de:70:78:10:1c:48:5b:da:bc:a4:38:ba:67:ed:55: + 3e:5e:57:df:d4:03:40:4c:81:a4:d2:4f:63:a7:09:42:09:14: + fc:00:a9:c2:80:73:4f:2e:c0:40:d9:11:7b:48:ea:7a:02:c0: + d3:eb:28:01:26:58:74:c1:c0:73:22:6d:93:95:fd:39:7d:bb: + 2a:e3:f6:82:e3:2c:97:5f:4e:1f:91:94:fa:fe:2c:a3:d8:76: + 1a:b8:4d:b2:38:4f:9b:fa:1d:48:60:79:26:e2:f3:fd:a9:d0: + 9a:e8:70:8f:49:7a:d6:e5:bd:0a:0e:db:2d:f3:8d:bf:eb:e3: + a4:7d:cb:c7:95:71:e8:da:a3:7c:c5:c2:f8:74:92:04:1b:86: + ac:a4:22:53:40:b6:ac:fe:4c:76:cf:fb:94:32:c0:35:9f:76: + 3f:6e:e5:90:6e:a0:a6:26:a2:b8:2c:be:d1:2b:85:fd:a7:68: + c8:ba:01:2b:b1:6c:74:1d:b8:73:95:e7:ee:b7:c7:25:f0:00: + 4c:00:b2:7e:b6:0b:8b:1c:f3:c0:50:9e:25:b9:e0:08:de:36: + 66:ff:37:a5:d1:bb:54:64:2c:c9:27:b5:4b:92:7e:65:ff:d3: + 2d:e1:b9:4e:bc:7f:a4:41:21:90:41:77:a6:39:1f:ea:9e:e3: + 9f:d0:66:6f:05:ec:aa:76:7e:bf:6b:16:a0:eb:b5:c7:fc:92: + 54:2f:2b:11:27:25:37:78:4c:51:6a:b0:f3:cc:58:5d:14:f1: + 6a:48:15:ff:c2:07:b6:b1:8d:0f:8e:5c:50:46:b3:3d:bf:01: + 98:4f:b2:59:54:47:3e:34:7b:78:6d:56:93:2e:73:ea:66:28: + 78:cd:1d:14:bf:a0:8f:2f:2e:b8:2e:8e:f2:14:8a:cc:e9:b5: + 7c:fb:6c:9d:0c:a5:e1:96 +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE +BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w +MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC +SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 +ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv +UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX +4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 +KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ +gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb +rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ +51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F +be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe +KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F +v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn +fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 +jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz +ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL +e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 +jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz +WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V +SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j +pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX +X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok +fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R +K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU +ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU +LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT +LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- + +Trustis FPS Root CA +# Issuer: OU=Trustis FPS Root CA,O=Trustis Limited,C=GB +# Serial Number:1b:1f:ad:b6:20:f9:24:d3:36:6b:f7:c7:f1:8c:a0:59 +# Subject: OU=Trustis FPS Root CA,O=Trustis Limited,C=GB +# Not Valid Before: Tue Dec 23 12:14:06 2003 +# Not Valid After : Sun Jan 21 11:36:54 2024 +# Fingerprint (MD5): 30:C9:E7:1E:6B:E6:14:EB:65:B2:16:69:20:31:67:4D +# Fingerprint (SHA1): 3B:C0:38:0B:33:C3:F6:A6:0C:86:15:22:93:D9:DF:F5:4B:81:C0:04 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=30:C9:E7:1E:6B:E6:14:EB:65:B2:16:69:20:31:67:4D +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 1b:1f:ad:b6:20:f9:24:d3:36:6b:f7:c7:f1:8c:a0:59 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=GB, O=Trustis Limited, OU=Trustis FPS Root CA + Validity + Not Before: Dec 23 12:14:06 2003 GMT + Not After : Jan 21 11:36:54 2024 GMT + Subject: C=GB, O=Trustis Limited, OU=Trustis FPS Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c5:50:7b:9e:3b:35:d0:df:c4:8c:cd:8e:9b:ed: + a3:c0:36:99:f4:42:ea:a7:3e:80:83:0f:a6:a7:59: + 87:c9:90:45:43:7e:00:ea:86:79:2a:03:bd:3d:37: + 99:89:66:b7:e5:8a:56:86:93:9c:68:4b:68:04:8c: + 93:93:02:3e:30:d2:37:3a:22:61:89:1c:85:4e:7d: + 8f:d5:af:7b:35:f6:7e:28:47:89:31:dc:0e:79:64: + 1f:99:d2:5b:ba:fe:7f:60:bf:ad:eb:e7:3c:38:29: + 6a:2f:e5:91:0b:55:ff:ec:6f:58:d5:2d:c9:de:4c: + 66:71:8f:0c:d7:04:da:07:e6:1e:18:e3:bd:29:02: + a8:fa:1c:e1:5b:b9:83:a8:41:48:bc:1a:71:8d:e7: + 62:e5:2d:b2:eb:df:7c:cf:db:ab:5a:ca:31:f1:4c: + 22:f3:05:13:f7:82:f9:73:79:0c:be:d7:4b:1c:c0: + d1:15:3c:93:41:64:d1:e6:be:23:17:22:00:89:5e: + 1f:6b:a5:ac:6e:a7:4b:8c:ed:a3:72:e6:af:63:4d: + 2f:85:d2:14:35:9a:2e:4e:8c:ea:32:98:28:86:a1: + 91:09:41:3a:b4:e1:e3:f2:fa:f0:c9:0a:a2:41:dd: + a9:e3:03:c7:88:15:3b:1c:d4:1a:94:d7:9f:64:59: + 12:6d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:BA:FA:71:25:79:8B:57:41:25:21:86:0B:71:EB:B2:64:0E:8B:21:67 + + X509v3 Subject Key Identifier: + BA:FA:71:25:79:8B:57:41:25:21:86:0B:71:EB:B2:64:0E:8B:21:67 + Signature Algorithm: sha1WithRSAEncryption + 7e:58:ff:fd:35:19:7d:9c:18:4f:9e:b0:2b:bc:8e:8c:14:ff: + 2c:a0:da:47:5b:c3:ef:81:2d:af:05:ea:74:48:5b:f3:3e:4e: + 07:c7:6d:c5:b3:93:cf:22:35:5c:b6:3f:75:27:5f:09:96:cd: + a0:fe:be:40:0c:5c:12:55:f8:93:82:ca:29:e9:5e:3f:56:57: + 8b:38:36:f7:45:1a:4c:28:cd:9e:41:b8:ed:56:4c:84:a4:40: + c8:b8:b0:a5:2b:69:70:04:6a:c3:f8:d4:12:32:f9:0e:c3:b1: + dc:32:84:44:2c:6f:cb:46:0f:ea:66:41:0f:4f:f1:58:a5:a6: + 0d:0d:0f:61:de:a5:9e:5d:7d:65:a1:3c:17:e7:a8:55:4e:ef: + a0:c7:ed:c6:44:7f:54:f5:a3:e0:8f:f0:7c:55:22:8f:29:b6: + 81:a3:e1:6d:4e:2c:1b:80:67:ec:ad:20:9f:0c:62:61:d5:97: + ff:43:ed:2d:c1:da:5d:29:2a:85:3f:ac:65:ee:86:0f:05:8d: + 90:5f:df:ee:9f:f4:bf:ee:1d:fb:98:e4:7f:90:2b:84:78:10: + 0e:6c:49:53:ef:15:5b:65:46:4a:5d:af:ba:fb:3a:72:1d:cd: + f6:25:88:1e:97:cc:21:9c:29:01:0d:65:eb:57:d9:f3:57:96: + bb:48:cd:81 +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL +ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx +MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc +MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ +AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH +iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj +vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA +0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB +OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ +BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E +FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 +GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW +zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 +1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE +f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F +jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN +ZetX2fNXlrtIzYE= +-----END CERTIFICATE----- + +Buypass Class 2 Root CA +# Issuer: CN=Buypass Class 2 Root CA,O=Buypass AS-983163327,C=NO +# Serial Number: 2 (0x2) +# Subject: CN=Buypass Class 2 Root CA,O=Buypass AS-983163327,C=NO +# Not Valid Before: Tue Oct 26 08:38:03 2010 +# Not Valid After : Fri Oct 26 08:38:03 2040 +# Fingerprint (MD5): 46:A7:D2:FE:45:FB:64:5A:A8:59:90:9B:78:44:9B:29 +# Fingerprint (SHA1): 49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=46:A7:D2:FE:45:FB:64:5A:A8:59:90:9B:78:44:9B:29 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=NO, O=Buypass AS-983163327, CN=Buypass Class 2 Root CA + Validity + Not Before: Oct 26 08:38:03 2010 GMT + Not After : Oct 26 08:38:03 2040 GMT + Subject: C=NO, O=Buypass AS-983163327, CN=Buypass Class 2 Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:d7:c7:5e:f7:c1:07:d4:77:fb:43:21:f4:f4:f5: + 69:e4:ee:32:01:db:a3:86:1f:e4:59:0d:ba:e7:75: + 83:52:eb:ea:1c:61:15:48:bb:1d:07:ca:8c:ae:b0: + dc:96:9d:ea:c3:60:92:86:82:28:73:9c:56:06:ff: + 4b:64:f0:0c:2a:37:49:b5:e5:cf:0c:7c:ee:f1:4a: + bb:73:30:65:f3:d5:2f:83:b6:7e:e3:e7:f5:9e:ab: + 60:f9:d3:f1:9d:92:74:8a:e4:1c:96:ac:5b:80:e9: + b5:f4:31:87:a3:51:fc:c7:7e:a1:6f:8e:53:77:d4: + 97:c1:55:33:92:3e:18:2f:75:d4:ad:86:49:cb:95: + af:54:06:6c:d8:06:13:8d:5b:ff:e1:26:19:59:c0: + 24:ba:81:71:79:90:44:50:68:24:94:5f:b8:b3:11: + f1:29:41:61:a3:41:cb:23:36:d5:c1:f1:32:50:10: + 4e:7f:f4:86:93:ec:84:d3:8e:bc:4b:bf:5c:01:4e: + 07:3d:dc:14:8a:94:0a:a4:ea:73:fb:0b:51:e8:13: + 07:18:fa:0e:f1:2b:d1:54:15:7d:3c:e1:f7:b4:19: + 42:67:62:5e:77:e0:a2:55:ec:b6:d9:69:17:d5:3a: + af:44:ed:4a:c5:9e:e4:7a:27:7c:e5:75:d7:aa:cb: + 25:e7:df:6b:0a:db:0f:4d:93:4e:a8:a0:cd:7b:2e: + f2:59:01:6a:b7:0d:b8:07:81:7e:8b:38:1b:38:e6: + 0a:57:99:3d:ee:21:e8:a3:f5:0c:16:dd:8b:ec:34: + 8e:9c:2a:1c:00:15:17:8d:68:83:d2:70:9f:18:08: + cd:11:68:d5:c9:6b:52:cd:c4:46:8f:dc:b5:f3:d8: + 57:73:1e:e9:94:39:04:bf:d3:de:38:de:b4:53:ec: + 69:1c:a2:7e:c4:8f:e4:1b:70:ad:f2:a2:f9:fb:f7: + 16:64:66:69:9f:49:51:a2:e2:15:18:67:06:4a:7f: + d5:6c:b5:4d:b3:33:e0:61:eb:5d:be:e9:98:0f:32: + d7:1d:4b:3c:2e:5a:01:52:91:09:f2:df:ea:8d:d8: + 06:40:63:aa:11:e4:fe:c3:37:9e:14:52:3f:f4:e2: + cc:f2:61:93:d1:fd:67:6b:d7:52:ae:bf:68:ab:40: + 43:a0:57:35:53:78:f0:53:f8:61:42:07:64:c6:d7: + 6f:9b:4c:38:0d:63:ac:62:af:36:8b:a2:73:0a:0d: + f5:21:bd:74:aa:4d:ea:72:03:49:db:c7:5f:1d:62: + 63:c7:fd:dd:91:ec:33:ee:f5:6d:b4:6e:30:68:de: + c8:d6:26:b0:75:5e:7b:b4:07:20:98:a1:76:32:b8: + 4d:6c:4f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + C9:80:77:E0:62:92:82:F5:46:9C:F3:BA:F7:4C:C3:DE:B8:A3:AD:39 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 53:5f:21:f5:ba:b0:3a:52:39:2c:92:b0:6c:00:c9:ef:ce:20: + ef:06:f2:96:9e:e9:a4:74:7f:7a:16:fc:b7:f5:b6:fb:15:1b: + 3f:ab:a6:c0:72:5d:10:b1:71:ee:bc:4f:e3:ad:ac:03:6d:2e: + 71:2e:af:c4:e3:ad:a3:bd:0c:11:a7:b4:ff:4a:b2:7b:10:10: + 1f:a7:57:41:b2:c0:ae:f4:2c:59:d6:47:10:88:f3:21:51:29: + 30:ca:60:86:af:46:ab:1d:ed:3a:5b:b0:94:de:44:e3:41:08: + a2:c1:ec:1d:d6:fd:4f:b6:d6:47:d0:14:0b:ca:e6:ca:b5:7b: + 77:7e:41:1f:5e:83:c7:b6:8c:39:96:b0:3f:96:81:41:6f:60: + 90:e2:e8:f9:fb:22:71:d9:7d:b3:3d:46:bf:b4:84:af:90:1c: + 0f:8f:12:6a:af:ef:ee:1e:7a:ae:02:4a:8a:17:2b:76:fe:ac: + 54:89:24:2c:4f:3f:b6:b2:a7:4e:8c:a8:91:97:fb:29:c6:7b: + 5c:2d:b9:cb:66:b6:b7:a8:5b:12:51:85:b5:09:7e:62:78:70: + fe:a9:6a:60:b6:1d:0e:79:0c:fd:ca:ea:24:80:72:c3:97:3f: + f2:77:ab:43:22:0a:c7:eb:b6:0c:84:82:2c:80:6b:41:8a:08: + c0:eb:a5:6b:df:99:12:cb:8a:d5:5e:80:0c:91:e0:26:08:36: + 48:c5:fa:38:11:35:ff:25:83:2d:f2:7a:bf:da:fd:8e:fe:a5: + cb:45:2c:1f:c4:88:53:ae:77:0e:d9:9a:76:c5:8e:2c:1d:a3: + ba:d5:ec:32:ae:c0:aa:ac:f7:d1:7a:4d:eb:d4:07:e2:48:f7: + 22:8e:b0:a4:9f:6a:ce:8e:b2:b2:60:f4:a3:22:d0:23:eb:94: + 5a:7a:69:dd:0f:bf:40:57:ac:6b:59:50:d9:a3:99:e1:6e:fe: + 8d:01:79:27:23:15:de:92:9d:7b:09:4d:5a:e7:4b:48:30:5a: + 18:e6:0a:6d:e6:8f:e0:d2:bb:e6:df:7c:6e:21:82:c1:68:39: + 4d:b4:98:58:66:62:cc:4a:90:5e:c3:fa:27:04:b1:79:15:74: + 99:cc:be:ad:20:de:26:60:1c:eb:56:51:a6:a3:ea:e4:a3:3f: + a7:ff:61:dc:f1:5a:4d:6c:32:23:43:ee:ac:a8:ee:ee:4a:12: + 09:3c:5d:71:c2:be:79:fa:c2:87:68:1d:0b:fd:5c:69:cc:06: + d0:9a:7d:54:99:2a:c9:39:1a:19:af:4b:2a:43:f3:63:5d:5a: + 58:e2:2f:e3:1d:e4:a9:d6:d0:0a:d0:9e:bf:d7:81:09:f1:c9: + c7:26:0d:ac:98:16:56:a0 +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr +6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV +L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 +1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx +MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ +QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB +arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr +Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi +FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS +P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN +9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz +uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h +9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t +OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo ++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 +KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 +DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us +H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ +I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 +5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h +3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz +Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= +-----END CERTIFICATE----- + +Buypass Class 3 Root CA +# Issuer: CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO +# Serial Number: 2 (0x2) +# Subject: CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO +# Not Valid Before: Tue Oct 26 08:28:58 2010 +# Not Valid After : Fri Oct 26 08:28:58 2040 +# Fingerprint (MD5): 3D:3B:18:9E:2C:64:5A:E8:D5:88:CE:0E:F9:37:C2:EC +# Fingerprint (SHA1): DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=3D:3B:18:9E:2C:64:5A:E8:D5:88:CE:0E:F9:37:C2:EC +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=NO, O=Buypass AS-983163327, CN=Buypass Class 3 Root CA + Validity + Not Before: Oct 26 08:28:58 2010 GMT + Not After : Oct 26 08:28:58 2040 GMT + Subject: C=NO, O=Buypass AS-983163327, CN=Buypass Class 3 Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:a5:da:0a:95:16:50:e3:95:f2:5e:9d:76:31:06: + 32:7a:9b:f1:10:76:b8:00:9a:b5:52:36:cd:24:47: + b0:9f:18:64:bc:9a:f6:fa:d5:79:d8:90:62:4c:22: + 2f:de:38:3d:d6:e0:a8:e9:1c:2c:db:78:11:e9:8e: + 68:51:15:72:c7:f3:33:87:e4:a0:5d:0b:5c:e0:57: + 07:2a:30:f5:cd:c4:37:77:28:4d:18:91:e6:bf:d5: + 52:fd:71:2d:70:3e:e7:c6:c4:8a:e3:f0:28:0b:f4: + 76:98:a1:8b:87:55:b2:3a:13:fc:b7:3e:27:37:8e: + 22:e3:a8:4f:2a:ef:60:bb:3d:b7:39:c3:0e:01:47: + 99:5d:12:4f:db:43:fa:57:a1:ed:f9:9d:be:11:47: + 26:5b:13:98:ab:5d:16:8a:b0:37:1c:57:9d:45:ff: + 88:96:36:bf:bb:ca:07:7b:6f:87:63:d7:d0:32:6a: + d6:5d:6c:0c:f1:b3:6e:39:e2:6b:31:2e:39:00:27: + 14:de:38:c0:ec:19:66:86:12:e8:9d:72:16:13:64: + 52:c7:a9:37:1c:fd:82:30:ed:84:18:1d:f4:ae:5c: + ff:70:13:00:eb:b1:f5:33:7a:4b:d6:55:f8:05:8d: + 4b:69:b0:f5:b3:28:36:5c:14:c4:51:73:4d:6b:0b: + f1:34:07:db:17:39:d7:dc:28:7b:6b:f5:9f:f3:2e: + c1:4f:17:2a:10:f3:cc:ca:e8:eb:fd:6b:ab:2e:9a: + 9f:2d:82:6e:04:d4:52:01:93:2d:3d:86:fc:7e:fc: + df:ef:42:1d:a6:6b:ef:b9:20:c6:f7:bd:a0:a7:95: + fd:a7:e6:89:24:d8:cc:8c:34:6c:e2:23:2f:d9:12: + 1a:21:b9:55:91:6f:0b:91:79:19:0c:ad:40:88:0b: + 70:e2:7a:d2:0e:d8:68:48:bb:82:13:39:10:58:e9: + d8:2a:07:c6:12:db:58:db:d2:3b:55:10:47:05:15: + 67:62:7e:18:63:a6:46:3f:09:0e:54:32:5e:bf:0d: + 62:7a:27:ef:80:e8:db:d9:4b:06:5a:37:5a:25:d0: + 08:12:77:d4:6f:09:50:97:3d:c8:1d:c3:df:8c:45: + 30:56:c6:d3:64:ab:66:f3:c0:5e:96:9c:c3:c4:ef: + c3:7c:6b:8b:3a:79:7f:b3:49:cf:3d:e2:89:9f:a0: + 30:4b:85:b9:9c:94:24:79:8f:7d:6b:a9:45:68:0f: + 2b:d0:f1:da:1c:cb:69:b8:ca:49:62:6d:c8:d0:63: + 62:dd:60:0f:58:aa:8f:a1:bc:05:a5:66:a2:cf:1b: + 76:b2:84:64:b1:4c:39:52:c0:30:ba:f0:8c:4b:02: + b0:b6:b7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 47:B8:CD:FF:E5:6F:EE:F8:B2:EC:2F:4E:0E:F9:25:B0:8E:3C:6B:C3 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 00:20:23:41:35:04:90:c2:40:62:60:ef:e2:35:4c:d7:3f:ac: + e2:34:90:b8:a1:6f:76:fa:16:16:a4:48:37:2c:e9:90:c2:f2: + 3c:f8:0a:9f:d8:81:e5:bb:5b:da:25:2c:a4:a7:55:71:24:32: + f6:c8:0b:f2:bc:6a:f8:93:ac:b2:07:c2:5f:9f:db:cc:c8:8a: + aa:be:6a:6f:e1:49:10:cc:31:d7:80:bb:bb:c8:d8:a2:0e:64: + 57:ea:a2:f5:c2:a9:31:15:d2:20:6a:ec:fc:22:01:28:cf:86: + b8:80:1e:a9:cc:11:a5:3c:f2:16:b3:47:9d:fc:d2:80:21:c4: + cb:d0:47:70:41:a1:ca:83:19:08:2c:6d:f2:5d:77:9c:8a:14: + 13:d4:36:1c:92:f0:e5:06:37:dc:a6:e6:90:9b:38:8f:5c:6b: + 1b:46:86:43:42:5f:3e:01:07:53:54:5d:65:7d:f7:8a:73:a1: + 9a:54:5a:1f:29:43:14:27:c2:85:0f:b5:88:7b:1a:3b:94:b7: + 1d:60:a7:b5:9c:e7:29:69:57:5a:9b:93:7a:43:30:1b:03:d7: + 62:c8:40:a6:aa:fc:64:e4:4a:d7:91:53:01:a8:20:88:6e:9c: + 5f:44:b9:cb:60:81:34:ec:6f:d3:7d:da:48:5f:eb:b4:90:bc: + 2d:a9:1c:0b:ac:1c:d5:a2:68:20:80:04:d6:fc:b1:8f:2f:bb: + 4a:31:0d:4a:86:1c:eb:e2:36:29:26:f5:da:d8:c4:f2:75:61: + cf:7e:ae:76:63:4a:7a:40:65:93:87:f8:1e:80:8c:86:e5:86: + d6:8f:0e:fc:53:2c:60:e8:16:61:1a:a2:3e:43:7b:cd:39:60: + 54:6a:f5:f2:89:26:01:68:83:48:a2:33:e8:c9:04:91:b2:11: + 34:11:3e:ea:d0:43:19:1f:03:93:90:0c:ff:51:3d:57:f4:41: + 6e:e1:cb:a0:be:eb:c9:63:cd:6d:cc:e4:f8:36:aa:68:9d:ed: + bd:5d:97:70:44:0d:b6:0e:35:dc:e1:0c:5d:bb:a0:51:94:cb: + 7e:16:eb:11:2f:a3:92:45:c8:4c:71:d9:bc:c9:99:52:57:46: + 2f:50:cf:bd:35:69:f4:3d:15:ce:06:a5:2c:0f:3e:f6:81:ba: + 94:bb:c3:bb:bf:65:78:d2:86:79:ff:49:3b:1a:83:0c:f0:de: + 78:ec:c8:f2:4d:4c:1a:de:82:29:f8:c1:5a:da:ed:ee:e6:27: + 5e:e8:45:d0:9d:1c:51:a8:68:ab:44:e3:d0:8b:6a:e3:f8:3b: + bb:dc:4d:d7:64:f2:51:be:e6:aa:ab:5a:e9:31:ee:06:bc:73: + bf:13:62:0a:9f:c7:b9:97 +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y +ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E +N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 +tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX +0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c +/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X +KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY +zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS +O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D +34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP +K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv +Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj +QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS +IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 +HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa +O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv +033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u +dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE +kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 +3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD +u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq +4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 3 +# Issuer: CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE +# Serial Number: 1 (0x1) +# Subject: CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE +# Not Valid Before: Wed Oct 01 10:29:56 2008 +# Not Valid After : Sat Oct 01 23:59:59 2033 +# Fingerprint (MD5): CA:FB:40:A8:4E:39:92:8A:1D:FE:8E:2F:C4:27:EA:EF +# Fingerprint (SHA1): 55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=CA:FB:40:A8:4E:39:92:8A:1D:FE:8E:2F:C4:27:EA:EF +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=DE, O=T-Systems Enterprise Services GmbH, OU=T-Systems Trust Center, CN=T-TeleSec GlobalRoot Class 3 + Validity + Not Before: Oct 1 10:29:56 2008 GMT + Not After : Oct 1 23:59:59 2033 GMT + Subject: C=DE, O=T-Systems Enterprise Services GmbH, OU=T-Systems Trust Center, CN=T-TeleSec GlobalRoot Class 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:bd:75:93:f0:62:22:6f:24:ae:e0:7a:76:ac:7d: + bd:d9:24:d5:b8:b7:fc:cd:f0:42:e0:eb:78:88:56: + 5e:9b:9a:54:1d:4d:0c:8a:f6:d3:cf:70:f4:52:b5: + d8:93:04:e3:46:86:71:41:4a:2b:f0:2a:2c:55:03: + d6:48:c3:e0:39:38:ed:f2:5c:3c:3f:44:bc:93:3d: + 61:ab:4e:cd:0d:be:f0:20:27:58:0e:44:7f:04:1a: + 87:a5:d7:96:14:36:90:d0:49:7b:a1:75:fb:1a:6b: + 73:b1:f8:ce:a9:09:2c:f2:53:d5:c3:14:44:b8:86: + a5:f6:8b:2b:39:da:a3:33:54:d9:fa:72:1a:f7:22: + 15:1c:88:91:6b:7f:66:e5:c3:6a:80:b0:24:f3:df: + 86:45:88:fd:19:7f:75:87:1f:1f:b1:1b:0a:73:24: + 5b:b9:65:e0:2c:54:c8:60:d3:66:17:3f:e1:cc:54: + 33:73:91:02:3a:a6:7f:7b:76:39:a2:1f:96:b6:38: + ae:b5:c8:93:74:1d:9e:b9:b4:e5:60:9d:2f:56:d1: + e0:eb:5e:5b:4c:12:70:0c:6c:44:20:ab:11:d8:f4: + 19:f6:d2:9c:52:37:e7:fa:b6:c2:31:3b:4a:d4:14: + 99:ad:c7:1a:f5:5d:5f:fa:07:b8:7c:0d:1f:d6:83: + 1e:b3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + B5:03:F7:76:3B:61:82:6A:12:AA:18:53:EB:03:21:94:BF:FE:CE:CA + Signature Algorithm: sha256WithRSAEncryption + 56:3d:ef:94:d5:bd:da:73:b2:58:be:ae:90:ad:98:27:97:fe: + 01:b1:b0:52:00:b8:4d:e4:1b:21:74:1b:7e:c0:ee:5e:69:2a: + 25:af:5c:d6:1d:da:d2:79:c9:f3:97:29:e0:86:87:de:04:59: + 0f:f1:59:d4:64:85:4b:99:af:25:04:1e:c9:46:a9:97:de:82: + b2:1b:70:9f:9c:f6:af:71:31:dd:7b:05:a5:2c:d3:b9:ca:47: + f6:ca:f2:f6:e7:ad:b9:48:3f:bc:16:b7:c1:6d:f4:ea:09:af: + ec:f3:b5:e7:05:9e:a6:1e:8a:53:51:d6:93:81:cc:74:93:f6: + b9:da:a6:25:05:74:79:5a:7e:40:3e:82:4b:26:11:30:6e:e1: + 3f:41:c7:47:00:35:d5:f5:d3:f7:54:3e:81:3d:da:49:6a:9a: + b3:ef:10:3d:e6:eb:6f:d1:c8:22:47:cb:cc:cf:01:31:92:d9: + 18:e3:22:be:09:1e:1a:3e:5a:b2:e4:6b:0c:54:7a:7d:43:4e: + b8:89:a5:7b:d7:a2:3d:96:86:cc:f2:26:34:2d:6a:92:9d:9a: + 1a:d0:30:e2:5d:4e:04:b0:5f:8b:20:7e:77:c1:3d:95:82:d1: + 46:9a:3b:3c:78:b8:6f:a1:d0:0d:64:a2:78:1e:29:4e:93:c3: + a4:54:14:5b +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN +8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ +RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 +hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 +ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM +EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 +A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy +WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ +1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 +6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT +91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p +TpPDpFQUWw== +-----END CERTIFICATE----- + +EE Certification Centre Root CA +# Issuer: E=pki@sk.ee,CN=EE Certification Centre Root CA,O=AS Sertifitseerimiskeskus,C=EE +# Serial Number:54:80:f9:a0:73:ed:3f:00:4c:ca:89:d8:e3:71:e6:4a +# Subject: E=pki@sk.ee,CN=EE Certification Centre Root CA,O=AS Sertifitseerimiskeskus,C=EE +# Not Valid Before: Sat Oct 30 10:10:30 2010 +# Not Valid After : Tue Dec 17 23:59:59 2030 +# Fingerprint (MD5): 43:5E:88:D4:7D:1A:4A:7E:FD:84:2E:52:EB:01:D4:6F +# Fingerprint (SHA1): C9:A8:B9:E7:55:80:5E:58:E3:53:77:A7:25:EB:AF:C3:7B:27:CC:D7 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=43:5E:88:D4:7D:1A:4A:7E:FD:84:2E:52:EB:01:D4:6F +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 54:80:f9:a0:73:ed:3f:00:4c:ca:89:d8:e3:71:e6:4a + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=EE, O=AS Sertifitseerimiskeskus, CN=EE Certification Centre Root CA/emailAddress=pki@sk.ee + Validity + Not Before: Oct 30 10:10:30 2010 GMT + Not After : Dec 17 23:59:59 2030 GMT + Subject: C=EE, O=AS Sertifitseerimiskeskus, CN=EE Certification Centre Root CA/emailAddress=pki@sk.ee + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c8:20:c0:ec:e0:c5:4b:ab:07:78:95:f3:44:ee: + fb:0b:0c:ff:74:8e:61:bb:b1:62:ea:23:d8:ab:a1: + 65:32:7a:eb:8e:17:4f:96:d8:0a:7b:91:a2:63:6c: + c7:8c:4c:2e:79:bf:a9:05:fc:69:5c:95:8d:62:f9: + b9:70:ed:c3:51:7d:d0:93:e6:6c:eb:30:4b:e1:bc: + 7d:bf:52:9b:ce:6e:7b:65:f2:38:b1:c0:a2:32:ef: + 62:b2:68:e0:61:53:c1:36:95:ff:ec:94:ba:36:ae: + 9c:1c:a7:32:0f:e5:7c:b4:c6:6f:74:fd:7b:18:e8: + ac:57:ed:06:20:4b:32:30:58:5b:fd:cd:a8:e6:a1: + fc:70:bc:8e:92:73:db:97:a7:7c:21:ae:3d:c1:f5: + 48:87:6c:27:bd:9f:25:74:81:55:b0:f7:75:f6:3d: + a4:64:6b:d6:4f:e7:ce:40:ad:0f:dd:32:d3:bc:8a: + 12:53:98:c9:89:fb:10:1d:4d:7e:cd:7e:1f:56:0d: + 21:70:85:f6:20:83:1f:f6:ba:1f:04:8f:ea:77:88: + 35:c4:ff:ea:4e:a1:8b:4d:3f:63:1b:44:c3:44:d4: + 25:76:ca:b7:8d:d7:1e:4a:66:64:cd:5c:c5:9c:83: + e1:c2:08:88:9a:ec:4e:a3:f1:3e:1c:2c:d9:6c:1d: + a1:4b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 12:F2:5A:3E:EA:56:1C:BF:CD:06:AC:F1:F1:25:C9:A9:4B:D4:14:99 + X509v3 Extended Key Usage: + TLS Web Client Authentication, TLS Web Server Authentication, Code Signing, E-mail Protection, Time Stamping, OCSP Signing + Signature Algorithm: sha1WithRSAEncryption + 7b:f6:e4:c0:0d:aa:19:47:b7:4d:57:a3:fe:ad:bb:b1:6a:d5: + 0f:9e:db:e4:63:c5:8e:a1:50:56:93:96:b8:38:c0:24:22:66: + bc:53:14:61:95:bf:d0:c7:2a:96:39:3f:7d:28:b3:10:40:21: + 6a:c4:af:b0:52:77:18:e1:96:d8:56:5d:e3:dd:36:5e:1d:a7: + 50:54:a0:c5:2a:e4:aa:8c:94:8a:4f:9d:35:ff:76:a4:06:13: + 91:a2:a2:7d:00:44:3f:55:d3:82:3c:1a:d5:5b:bc:56:4c:22: + 2e:46:43:8a:24:40:2d:f3:12:b8:3b:70:1a:a4:96:b9:1a:af: + 87:41:1a:6a:18:0d:06:4f:c7:3e:6e:b9:29:4d:0d:49:89:11: + 87:32:5b:e6:4b:04:c8:e4:5c:e6:74:73:94:5d:16:98:13:95: + fe:fb:db:b1:44:e5:3a:70:ac:37:6b:e6:b3:33:72:28:c9:b3: + 57:a0:f6:02:16:88:06:0b:b6:a6:4b:20:28:d4:de:3d:8b:ad: + 37:05:53:74:fe:6e:cc:bc:43:17:71:5e:f9:c5:cc:1a:a9:61: + ee:f7:76:0c:f3:72:f4:72:ad:cf:72:02:36:07:47:cf:ef:19: + 50:89:60:cc:e9:24:95:0f:c2:cb:1d:f2:6f:76:90:c7:cc:75: + c1:96:c5:9d +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 +MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 +czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG +CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy +MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl +ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS +b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy +euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO +bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw +WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d +MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE +1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ +zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB +BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF +BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV +v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG +E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW +iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v +GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 2009 +# Issuer: CN=D-TRUST Root Class 3 CA 2 2009,O=D-Trust GmbH,C=DE +# Serial Number: 623603 (0x983f3) +# Subject: CN=D-TRUST Root Class 3 CA 2 2009,O=D-Trust GmbH,C=DE +# Not Valid Before: Thu Nov 05 08:35:58 2009 +# Not Valid After : Mon Nov 05 08:35:58 2029 +# Fingerprint (MD5): CD:E0:25:69:8D:47:AC:9C:89:35:90:F7:FD:51:3D:2F +# Fingerprint (SHA1): 58:E8:AB:B0:36:15:33:FB:80:F7:9B:1B:6D:29:D3:FF:8D:5F:00:F0 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=CD:E0:25:69:8D:47:AC:9C:89:35:90:F7:FD:51:3D:2F +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 623603 (0x983f3) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=DE, O=D-Trust GmbH, CN=D-TRUST Root Class 3 CA 2 2009 + Validity + Not Before: Nov 5 08:35:58 2009 GMT + Not After : Nov 5 08:35:58 2029 GMT + Subject: C=DE, O=D-Trust GmbH, CN=D-TRUST Root Class 3 CA 2 2009 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d3:b2:4a:cf:7a:47:ef:75:9b:23:fa:3a:2f:d6: + 50:45:89:35:3a:c6:6b:db:fe:db:00:68:a8:e0:03: + 11:1d:37:50:08:9f:4d:4a:68:94:35:b3:53:d1:94: + 63:a7:20:56:af:de:51:78:ec:2a:3d:f3:48:48:50: + 3e:0a:df:46:55:8b:27:6d:c3:10:4d:0d:91:52:43: + d8:87:e0:5d:4e:36:b5:21:ca:5f:39:40:04:5f:5b: + 7e:cc:a3:c6:2b:a9:40:1e:d9:36:84:d6:48:f3:92: + 1e:34:46:20:24:c1:a4:51:8e:4a:1a:ef:50:3f:69: + 5d:19:7f:45:c3:c7:01:8f:51:c9:23:e8:72:ae:b4: + bc:56:09:7f:12:cb:1c:b1:af:29:90:0a:c9:55:cc: + 0f:d3:b4:1a:ed:47:35:5a:4a:ed:9c:73:04:21:d0: + aa:bd:0c:13:b5:00:ca:26:6c:c4:6b:0c:94:5a:95: + 94:da:50:9a:f1:ff:a5:2b:66:31:a4:c9:38:a0:df: + 1d:1f:b8:09:2e:f3:a7:e8:67:52:ab:95:1f:e0:46: + 3e:d8:a4:c3:ca:5a:c5:31:80:e8:48:9a:9f:94:69: + fe:19:dd:d8:73:7c:81:ca:96:de:8e:ed:b3:32:05: + 65:84:34:e6:e6:fd:57:10:b5:5f:76:bf:2f:b0:10: + 0d:c5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + FD:DA:14:C4:9F:30:DE:21:BD:1E:42:39:FC:AB:63:23:49:E0:F1:84 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 CRL Distribution Points: + + Full Name: + URI:ldap://directory.d-trust.net/CN=D-TRUST%20Root%20Class%203%20CA%202%202009,O=D-Trust%20GmbH,C=DE?certificaterevocationlist + + Full Name: + URI:http://www.d-trust.net/crl/d-trust_root_class_3_ca_2_2009.crl + + Signature Algorithm: sha256WithRSAEncryption + 7f:97:db:30:c8:df:a4:9c:7d:21:7a:80:70:ce:14:12:69:88: + 14:95:60:44:01:ac:b2:e9:30:4f:9b:50:c2:66:d8:7e:8d:30: + b5:70:31:e9:e2:69:c7:f3:70:db:20:15:86:d0:0d:f0:be:ac: + 01:75:84:ce:7e:9f:4d:bf:b7:60:3b:9c:f3:ca:1d:e2:5e:68: + d8:a3:9d:97:e5:40:60:d2:36:21:fe:d0:b4:b8:17:da:74:a3: + 7f:d4:df:b0:98:02:ac:6f:6b:6b:2c:25:24:72:a1:65:ee:25: + 5a:e5:e6:32:e7:f2:df:ab:49:fa:f3:90:69:23:db:04:d9:e7: + 5c:58:fc:65:d4:97:be:cc:fc:2e:0a:cc:25:2a:35:04:f8:60: + 91:15:75:3d:41:ff:23:1f:19:c8:6c:eb:82:53:04:a6:e4:4c: + 22:4d:8d:8c:ba:ce:5b:73:ec:64:54:50:6d:d1:9c:55:fb:69: + c3:36:c3:8c:bc:3c:85:a6:6b:0a:26:0d:e0:93:98:60:ae:7e: + c6:24:97:8a:61:5f:91:8e:66:92:09:87:36:cd:8b:9b:2d:3e: + f6:51:d4:50:d4:59:28:bd:83:f2:cc:28:7b:53:86:6d:d8:26: + 88:70:d7:ea:91:cd:3e:b9:ca:c0:90:6e:5a:c6:5e:74:65:d7: + 5c:fe:a3:e2 +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha +ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM +HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 +UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 +tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R +ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM +lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp +/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G +A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy +MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl +cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js +L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL +BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni +acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K +zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 +PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y +Johw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 EV 2009 +# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE +# Serial Number: 623604 (0x983f4) +# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE +# Not Valid Before: Thu Nov 05 08:50:46 2009 +# Not Valid After : Mon Nov 05 08:50:46 2029 +# Fingerprint (MD5): AA:C6:43:2C:5E:2D:CD:C4:34:C0:50:4F:11:02:4F:B6 +# Fingerprint (SHA1): 96:C9:1B:0B:95:B4:10:98:42:FA:D0:D8:22:79:FE:60:FA:B9:16:83 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=AA:C6:43:2C:5E:2D:CD:C4:34:C0:50:4F:11:02:4F:B6 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 623604 (0x983f4) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=DE, O=D-Trust GmbH, CN=D-TRUST Root Class 3 CA 2 EV 2009 + Validity + Not Before: Nov 5 08:50:46 2009 GMT + Not After : Nov 5 08:50:46 2029 GMT + Subject: C=DE, O=D-Trust GmbH, CN=D-TRUST Root Class 3 CA 2 EV 2009 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:99:f1:84:34:70:ba:2f:b7:30:a0:8e:bd:7c:04: + cf:be:62:bc:99:fd:82:97:d2:7a:0a:67:96:38:09: + f6:10:4e:95:22:73:99:8d:da:15:2d:e7:05:fc:19: + 73:22:b7:8e:98:00:bc:3c:3d:ac:a1:6c:fb:d6:79: + 25:4b:ad:f0:cc:64:da:88:3e:29:b8:0f:09:d3:34: + dd:33:f5:62:d1:e1:cd:19:e9:ee:18:4f:4c:58:ae: + e2:1e:d6:0c:5b:15:5a:d8:3a:b8:c4:18:64:1e:e3: + 33:b2:b5:89:77:4e:0c:bf:d9:94:6b:13:97:6f:12: + a3:fe:99:a9:04:cc:15:ec:60:68:36:ed:08:7b:b7: + f5:bf:93:ed:66:31:83:8c:c6:71:34:87:4e:17:ea: + af:8b:91:8d:1c:56:41:ae:22:37:5e:37:f2:1d:d9: + d1:2d:0d:2f:69:51:a7:be:66:a6:8a:3a:2a:bd:c7: + 1a:b1:e1:14:f0:be:3a:1d:b9:cf:5b:b1:6a:fe:b4: + b1:46:20:a2:fb:1e:3b:70:ef:93:98:7d:8c:73:96: + f2:c5:ef:85:70:ad:29:26:fc:1e:04:3e:1c:a0:d8: + 0f:cb:52:83:62:7c:ee:8b:53:95:90:a9:57:a2:ea: + 61:05:d8:f9:4d:c4:27:fa:6e:ad:ed:f9:d7:51:f7: + 6b:a5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + D3:94:8A:4C:62:13:2A:19:2E:CC:AF:72:8A:7D:36:D7:9A:1C:DC:67 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 CRL Distribution Points: + + Full Name: + URI:ldap://directory.d-trust.net/CN=D-TRUST%20Root%20Class%203%20CA%202%20EV%202009,O=D-Trust%20GmbH,C=DE?certificaterevocationlist + + Full Name: + URI:http://www.d-trust.net/crl/d-trust_root_class_3_ca_2_ev_2009.crl + + Signature Algorithm: sha256WithRSAEncryption + 34:ed:7b:5a:3c:a4:94:88:ef:1a:11:75:07:2f:b3:fe:3c:fa: + 1e:51:26:eb:87:f6:29:de:e0:f1:d4:c6:24:09:e9:c1:cf:55: + 1b:b4:30:d9:ce:1a:fe:06:51:a6:15:a4:2d:ef:b2:4b:bf:20: + 28:25:49:d1:a6:36:77:34:e8:64:df:52:b1:11:c7:73:7a:cd: + 39:9e:c2:ad:8c:71:21:f2:5a:6b:af:df:3c:4e:55:af:b2:84: + 65:14:89:b9:77:cb:2a:31:be:cf:a3:6d:cf:6f:48:94:32:46: + 6f:e7:71:8c:a0:a6:84:19:37:07:f2:03:45:09:2b:86:75:7c: + df:5f:69:57:00:db:6e:d8:a6:72:22:4b:50:d4:75:98:56:df: + b7:18:ff:43:43:50:ae:7a:44:7b:f0:79:51:d7:43:3d:a7:d3: + 81:d3:f0:c9:4f:b9:da:c6:97:86:d0:82:c3:e4:42:6d:fe:b0: + e2:64:4e:0e:26:e7:40:34:26:b5:08:89:d7:08:63:63:38:27: + 75:1e:33:ea:6e:a8:dd:9f:99:4f:74:4d:81:89:80:4b:dd:9a: + 97:29:5c:2f:be:81:41:b9:8c:ff:ea:7d:60:06:9e:cd:d7:3d: + d3:2e:a3:15:bc:a8:e6:26:e5:6f:c3:dc:b8:03:21:ea:9f:16: + f1:2c:54:b5 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw +NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV +BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn +ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 +3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z +qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR +p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 +HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw +ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea +HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw +Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh +c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E +RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt +dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku +Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp +3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF +CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na +xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX +KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +CA Disig Root R1 +# Issuer: CN=CA Disig Root R1,O=Disig a.s.,L=Bratislava,C=SK +# Serial Number:00:c3:03:9a:ee:50:90:6e:28 +# Subject: CN=CA Disig Root R1,O=Disig a.s.,L=Bratislava,C=SK +# Not Valid Before: Thu Jul 19 09:06:56 2012 +# Not Valid After : Sat Jul 19 09:06:56 2042 +# Fingerprint (MD5): BE:EC:11:93:9A:F5:69:21:BC:D7:C1:C0:67:89:CC:2A +# Fingerprint (SHA1): 8E:1C:74:F8:A6:20:B9:E5:8A:F4:61:FA:EC:2B:47:56:51:1A:52:C6 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=BE:EC:11:93:9A:F5:69:21:BC:D7:C1:C0:67:89:CC:2A +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c3:03:9a:ee:50:90:6e:28 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig Root R1 + Validity + Not Before: Jul 19 09:06:56 2012 GMT + Not After : Jul 19 09:06:56 2042 GMT + Subject: C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig Root R1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:aa:c3:78:f7:dc:98:a3:a7:5a:5e:77:18:b2:dd: + 04:64:0f:63:fd:9b:96:09:80:d5:e8:aa:a5:e2:9c: + 26:94:3a:e8:99:73:8c:9d:df:d7:df:83:f3:78:4f: + 40:e1:7f:d2:a7:d2:e5:ca:13:93:e7:ed:c6:77:5f: + 36:b5:94:af:e8:38:8e:db:9b:e5:7c:bb:cc:8d:eb: + 75:73:e1:24:cd:e6:a7:2d:19:2e:d8:d6:8a:6b:14: + eb:08:62:0a:d8:dc:b3:00:4d:c3:23:7c:5f:43:08: + 23:32:12:dc:ed:0c:ad:c0:7d:0f:a5:7a:42:d9:5a: + 70:d9:bf:a7:d7:01:1c:f6:9b:ab:8e:b7:4a:86:78: + a0:1e:56:31:ae:ef:82:0a:80:41:f7:1b:c9:ae:ab: + 32:26:d4:2c:6b:ed:7d:6b:e4:e2:5e:22:0a:45:cb: + 84:31:4d:ac:fe:db:d1:47:ba:f9:60:97:39:b1:65: + c7:de:fb:99:e4:0a:22:b1:2d:4d:e5:48:26:69:ab: + e2:aa:f3:fb:fc:92:29:32:e9:b3:3e:4d:1f:27:a1: + cd:8e:b9:17:fb:25:3e:c9:6e:f3:77:da:0d:12:f6: + 5d:c7:bb:36:10:d5:54:d6:f3:e0:e2:47:48:e6:de: + 14:da:61:52:af:26:b4:f5:71:4f:c9:d7:d2:06:df: + 63:ca:ff:21:e8:59:06:e0:08:d5:84:15:53:f7:43: + e5:7c:c5:a0:89:98:6b:73:c6:68:ce:65:de:bd:7f: + 05:f7:b1:ee:f6:57:a1:60:95:c5:cc:ea:93:3a:be: + 99:ae:9b:02:a3:ad:c9:16:b5:ce:dd:5e:99:78:7e: + 1a:39:7e:b2:c0:05:a4:c0:82:a5:a3:47:9e:8c:ea: + 5c:b6:bc:67:db:e6:2a:4d:d2:04:dc:a3:ae:45:f7: + bc:8b:9c:1c:a7:d6:d5:03:dc:08:cb:2e:16:ca:5c: + 40:33:e8:67:c3:2e:e7:a6:44:ea:11:45:1c:35:65: + 2d:1e:45:61:24:1b:82:2e:a5:9d:33:5d:65:f8:41: + f9:2e:cb:94:3f:1f:a3:0c:31:24:44:ed:c7:5e:ad: + 50:ba:c6:41:9b:ac:f0:17:65:c0:f8:5d:6f:5b:a0: + 0a:34:3c:ee:d7:ea:88:9f:98:f9:af:4e:24:fa:97: + b2:64:76:da:ab:f4:ed:e3:c3:60:ef:d5:f9:02:c8: + 2d:9f:83:af:67:69:06:a7:31:55:d5:cf:4b:6f:ff: + 04:05:c7:58:ac:5f:16:1b:e5:d2:a3:eb:31:db:1f: + 33:15:4d:d0:f2:a5:53:f5:cb:e1:3d:4e:68:2d:d8: + 12:dd:aa:f2:e6:4d:9b:49:e5:c5:28:a1:ba:b0:5a: + c6:a0:b5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 89:0A:B4:38:93:1A:E6:AB:EE:9B:91:18:F9:F5:3C:3E:35:D0:D3:82 + Signature Algorithm: sha1WithRSAEncryption + 32:8b:f6:9d:4a:c9:be:14:e5:8c:ac:38:ca:3a:09:d4:1b:ce: + 86:b3:dd:eb:d4:ba:28:be:12:ae:45:2c:04:74:ac:13:51:c5: + 58:18:66:4d:82:da:d5:dc:93:c0:27:e1:be:7c:9f:52:9e:12: + 56:f6:d5:9c:a9:f4:75:9c:fa:37:12:8f:1c:93:ec:57:fe:07: + 0f:ab:d5:12:f7:0f:ae:61:5e:56:80:49:f5:fc:30:f5:9b:4f: + 1f:41:2f:1c:84:d3:89:c7:e2:da:02:76:ed:09:cf:6c:c1:b8: + 1c:83:1c:16:fa:94:cd:7d:a0:c8:18:d2:c8:9d:6e:f5:bd:69: + d4:6d:3d:35:e8:1e:a2:4f:60:d7:07:29:fc:b2:a3:a4:9d:6e: + 15:92:56:19:4c:0a:b0:e9:7c:d2:19:4d:42:46:ec:bd:fd:f6: + 57:5b:dd:98:7e:a4:4d:cc:72:03:83:58:5d:ef:93:3a:41:7a: + 63:aa:7c:3a:a8:f5:ac:a4:d1:dd:a2:2d:b6:2a:fc:9f:01:8e: + e2:10:b1:c4:ca:e4:67:db:55:25:19:3f:fd:e8:36:7e:b3:e1: + e1:81:af:11:16:8b:50:97:60:19:82:00:c0:6b:4d:73:b8:d1: + 13:07:3e:ea:b6:31:4f:f0:42:9a:6d:e2:11:74:e5:94:ac:8d: + 84:95:3c:21:af:c5:da:47:c8:df:39:62:62:cb:5b:50:0b:d7: + 81:40:05:9c:9b:ed:ba:b6:8b:1e:04:6f:96:20:39:ed:a4:7d: + 29:db:48:ce:82:dc:d4:02:8d:1d:04:31:5a:c7:4b:f0:6c:61: + 52:d7:b4:51:c2:81:6c:cd:e1:fb:a7:a1:d2:92:76:cf:b1:0f: + 37:58:a4:f2:52:71:67:3f:0c:88:78:80:89:c1:c8:b5:1f:92: + 63:be:a7:7a:8a:56:2c:1a:a8:a6:9c:b5:5d:b3:63:d0:13:20: + a1:eb:91:6c:d0:8d:7d:af:df:0b:e4:17:b9:86:9e:38:b1:94: + 0c:58:8c:e0:55:aa:3b:63:6d:9a:89:60:b8:64:2a:92:c6:37: + f4:7e:43:43:b7:73:e8:01:e7:7f:97:0f:d7:f2:7b:19:fd:1a: + d7:8f:c9:fa:85:6b:7a:9d:9e:89:b6:a6:28:99:93:88:40:f7: + 3e:cd:51:a3:ca:ea:ef:79:47:21:b5:fe:32:e2:c7:c3:51:6f: + be:80:74:f0:a4:c3:3a:f2:4f:e9:5f:df:19:0a:f2:3b:13:43: + ac:31:a4:b3:e7:eb:fc:18:d6:01:a9:f3:2a:8f:36:0e:eb:b4: + b1:bc:b7:4c:c9:6b:bf:a1:f3:d9:f4:ed:e2:f0:e3:ed:64:9e: + 3d:2f:96:52:4f:80:53:8b +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQy +MDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjEw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy3QRk +D2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/o +OI7bm+V8u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3A +fQ+lekLZWnDZv6fXARz2m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJe +IgpFy4QxTaz+29FHuvlglzmxZcfe+5nkCiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8n +oc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTaYVKvJrT1cU/J19IG32PK +/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6vpmumwKj +rckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD +3AjLLhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE +7cderVC6xkGbrPAXZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkC +yC2fg69naQanMVXVz0tv/wQFx1isXxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLd +qvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ04IwDQYJKoZI +hvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR +xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaA +SfX8MPWbTx9BLxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXo +HqJPYNcHKfyyo6SdbhWSVhlMCrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpB +emOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5GfbVSUZP/3oNn6z4eGBrxEWi1CXYBmC +AMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85YmLLW1AL14FABZyb +7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKSds+x +DzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvk +F7mGnjixlAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqF +a3qdnom2piiZk4hA9z7NUaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsT +Q6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJa7+h89n07eLw4+1knj0vllJPgFOL +-----END CERTIFICATE----- + +CA Disig Root R2 +# Issuer: CN=CA Disig Root R2,O=Disig a.s.,L=Bratislava,C=SK +# Serial Number:00:92:b8:88:db:b0:8a:c1:63 +# Subject: CN=CA Disig Root R2,O=Disig a.s.,L=Bratislava,C=SK +# Not Valid Before: Thu Jul 19 09:15:30 2012 +# Not Valid After : Sat Jul 19 09:15:30 2042 +# Fingerprint (MD5): 26:01:FB:D8:27:A7:17:9A:45:54:38:1A:43:01:3B:03 +# Fingerprint (SHA1): B5:61:EB:EA:A4:DE:E4:25:4B:69:1A:98:A5:57:47:C2:34:C7:D9:71 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=26:01:FB:D8:27:A7:17:9A:45:54:38:1A:43:01:3B:03 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 92:b8:88:db:b0:8a:c1:63 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig Root R2 + Validity + Not Before: Jul 19 09:15:30 2012 GMT + Not After : Jul 19 09:15:30 2042 GMT + Subject: C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig Root R2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:a2:a3:c4:00:09:d6:85:5d:2d:6d:14:f6:c2:c3: + 73:9e:35:c2:71:55:7e:81:fb:ab:46:50:e0:c1:7c: + 49:78:e6:ab:79:58:3c:da:ff:7c:1c:9f:d8:97:02: + 78:3e:6b:41:04:e9:41:bd:be:03:2c:45:f6:2f:64: + d4:ab:5d:a3:47:3d:64:9b:e9:68:9a:c6:cc:1b:3f: + ba:be:b2:8b:34:02:2e:98:55:19:fc:8c:6f:aa:5f: + da:4c:ce:4d:03:21:a3:d8:d2:34:93:56:96:cb:4c: + 0c:00:16:3c:5f:1a:cd:c8:c7:6c:a6:ad:d3:31:a7: + bc:e8:e5:e1:66:d6:d2:fb:03:b4:41:65:c9:10:ae: + 0e:05:63:c6:80:6a:69:30:fd:d2:ee:90:ef:0d:27: + df:9f:95:73:f4:e1:25:da:6c:16:de:41:38:34:ea: + 8b:fc:d1:e8:04:14:61:2d:41:7e:ac:c7:77:4e:cb: + 51:54:fb:5e:92:18:1b:04:5a:68:c6:c9:c4:fa:b7: + 13:a0:98:b7:11:2b:b7:d6:57:cc:7c:9e:17:d1:cb: + 25:fe:86:4e:24:2e:56:0c:78:4d:9e:01:12:a6:2b: + a7:01:65:6e:7c:62:1d:84:84:df:ea:c0:6b:b5:a5: + 2a:95:83:c3:53:11:0c:73:1d:0b:b2:46:90:d1:42: + 3a:ce:40:6e:95:ad:ff:c6:94:ad:6e:97:84:8e:7d: + 6f:9e:8a:80:0d:49:6d:73:e2:7b:92:1e:c3:f3:c1: + f3:eb:2e:05:6f:d9:1b:cf:37:76:04:c8:b4:5a:e4: + 17:a7:cb:dd:76:1f:d0:19:76:e8:2c:05:b3:d6:9c: + 34:d8:96:dc:61:87:91:05:e4:44:08:33:c1:da:b9: + 08:65:d4:ae:b2:36:0d:eb:ba:38:ba:0c:e5:9b:9e: + eb:8d:66:dd:99:cf:d6:89:41:f6:04:92:8a:29:29: + 6d:6b:3a:1c:e7:75:7d:02:71:0e:f3:c0:e7:bd:cb: + 19:dd:9d:60:b2:c2:66:60:b6:b1:04:ee:c9:e6:86: + b9:9a:66:40:a8:e7:11:ed:81:45:03:8b:f6:67:59: + e8:c1:06:11:bd:dd:cf:80:02:4f:65:40:78:5c:47: + 50:c8:9b:e6:1f:81:7b:e4:44:a8:5b:85:9a:e2:de: + 5a:d5:c7:f9:3a:44:66:4b:e4:32:54:7c:e4:6c:9c: + b3:0e:3d:17:a2:b2:34:12:d6:7e:b2:a8:49:bb:d1: + 7a:28:40:be:a2:16:1f:df:e4:37:1f:11:73:fb:90: + 0a:65:43:a2:0d:7c:f8:06:01:55:33:7d:b0:0d:b8: + f4:f5:ae:a5:42:57:7c:36:11:8c:7b:5e:c4:03:9d: + 8c:79:9d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + B5:99:F8:AF:B0:94:F5:E3:20:D6:0A:AD:CE:4E:56:A4:2E:6E:42:ED + Signature Algorithm: sha256WithRSAEncryption + 26:06:5e:70:e7:65:33:c8:82:6e:d9:9c:17:3a:1b:7a:66:b2: + 01:f6:78:3b:69:5e:2f:ea:ff:4e:f9:28:c3:98:2a:61:4c:b4: + 24:12:8a:7d:6d:11:14:f7:9c:b5:ca:e6:bc:9e:27:8e:4c:19: + c8:a9:bd:7a:c0:d7:36:0e:6d:85:72:6e:a8:c6:a2:6d:f6:fa: + 73:63:7f:bc:6e:79:08:1c:9d:8a:9f:1a:8a:53:a6:d8:bb:d9: + 35:55:b1:11:c5:a9:03:b3:56:3b:b9:84:93:22:5e:7e:c1:f6: + 12:52:8b:ea:2c:67:bc:fe:36:4c:f5:b8:cf:d1:b3:49:92:3b: + d3:29:0e:99:1b:96:f7:61:b8:3b:c4:2b:b6:78:6c:b4:23:6f: + f0:fd:d3:b2:5e:75:1f:99:95:a8:ac:f6:da:e1:c5:31:7b:fb: + d1:46:b3:d2:bc:67:b4:62:54:ba:09:f7:63:b0:93:a2:9a:f9: + e9:52:2e:8b:60:12:ab:fc:f5:60:56:ef:10:5c:8b:c4:1a:42: + dc:83:5b:64:0e:cb:b5:bc:d6:4f:c1:7c:3c:6e:8d:13:6d:fb: + 7b:eb:30:d0:dc:4d:af:c5:d5:b6:a5:4c:5b:71:c9:e8:31:be: + e8:38:06:48:a1:1a:e2:ea:d2:de:12:39:58:1a:ff:80:0e:82: + 75:e6:b7:c9:07:6c:0e:ef:ff:38:f1:98:71:c4:b7:7f:0e:15: + d0:25:69:bd:22:9d:2b:ed:05:f6:46:47:ac:ed:c0:f0:d4:3b: + e2:ec:ee:96:5b:90:13:4e:1e:56:3a:eb:b0:ef:96:bb:96:23: + 11:ba:f2:43:86:74:64:95:c8:28:75:df:1d:35:ba:d2:37:83: + 38:53:38:36:3b:cf:6c:e9:f9:6b:0e:d0:fb:04:e8:4f:77:d7: + 65:01:78:86:0c:7a:3e:21:62:f1:7f:63:71:0c:c9:9f:44:db: + a8:27:a2:75:be:6e:81:3e:d7:c0:eb:1b:98:0f:70:5c:34:b2: + 8a:cc:c0:85:18:eb:6e:7a:b3:f7:5a:a1:07:bf:a9:42:92:f3: + 60:22:97:e4:14:a1:07:9b:4e:76:c0:8e:7d:fd:a4:25:c7:47: + ed:ff:1f:73:ac:cc:c3:a5:e9:6f:0a:8e:9b:65:c2:50:85:b5: + a3:a0:53:12:cc:55:87:61:f3:81:ae:10:46:61:bd:44:21:b8: + c2:3d:74:cf:7e:24:35:fa:1c:07:0e:9b:3d:22:ca:ef:31:2f: + 8c:ac:12:bd:ef:40:28:fc:29:67:9f:b2:13:4f:66:24:c4:53: + 19:e9:1e:29:15:ef:e6:6d:b0:7f:2d:67:fd:f3:6c:1b:75:46: + a3:e5:4a:17:e9:a4:d7:0b +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy +MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe +NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH +PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I +x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe +QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR +yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO +QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 +H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ +QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD +i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs +nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 +rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI +hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf +GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb +lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka ++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal +TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i +nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 +gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr +G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os +zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x +L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +ACCVRAIZ1 +# Issuer: C=ES,O=ACCV,OU=PKIACCV,CN=ACCVRAIZ1 +# Serial Number:5e:c3:b7:a6:43:7f:a4:e0 +# Subject: C=ES,O=ACCV,OU=PKIACCV,CN=ACCVRAIZ1 +# Not Valid Before: Thu May 05 09:37:37 2011 +# Not Valid After : Tue Dec 31 09:37:37 2030 +# Fingerprint (MD5): D0:A0:5A:EE:05:B6:09:94:21:A1:7D:F1:B2:29:82:02 +# Fingerprint (SHA1): 93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=D0:A0:5A:EE:05:B6:09:94:21:A1:7D:F1:B2:29:82:02 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 6828503384748696800 (0x5ec3b7a6437fa4e0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=ACCVRAIZ1, OU=PKIACCV, O=ACCV, C=ES + Validity + Not Before: May 5 09:37:37 2011 GMT + Not After : Dec 31 09:37:37 2030 GMT + Subject: CN=ACCVRAIZ1, OU=PKIACCV, O=ACCV, C=ES + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:9b:a9:ab:bf:61:4a:97:af:2f:97:66:9a:74:5f: + d0:d9:96:fd:cf:e2:e4:66:ef:1f:1f:47:33:c2:44: + a3:df:9a:de:1f:b5:54:dd:15:7c:69:35:11:6f:bb: + c8:0c:8e:6a:18:1e:d8:8f:d9:16:bc:10:48:36:5c: + f0:63:b3:90:5a:5c:24:37:d7:a3:d6:cb:09:71:b9: + f1:01:72:84:b0:7d:db:4d:80:cd:fc:d3:6f:c9:f8: + da:b6:0e:82:d2:45:85:a8:1b:68:a8:3d:e8:f4:44: + 6c:bd:a1:c2:cb:03:be:8c:3e:13:00:84:df:4a:48: + c0:e3:22:0a:e8:e9:37:a7:18:4c:b1:09:0d:23:56: + 7f:04:4d:d9:17:84:18:a5:c8:da:40:94:73:eb:ce: + 0e:57:3c:03:81:3a:9d:0a:a1:57:43:69:ac:57:6d: + 79:90:78:e5:b5:b4:3b:d8:bc:4c:8d:28:a1:a7:a3: + a7:ba:02:4e:25:d1:2a:ae:ed:ae:03:22:b8:6b:20: + 0f:30:28:54:95:7f:e0:ee:ce:0a:66:9d:d1:40:2d: + 6e:22:af:9d:1a:c1:05:19:d2:6f:c0:f2:9f:f8:7b: + b3:02:42:fb:50:a9:1d:2d:93:0f:23:ab:c6:c1:0f: + 92:ff:d0:a2:15:f5:53:09:71:1c:ff:45:13:84:e6: + 26:5e:f8:e0:88:1c:0a:fc:16:b6:a8:73:06:b8:f0: + 63:84:02:a0:c6:5a:ec:e7:74:df:70:ae:a3:83:25: + ea:d6:c7:97:87:93:a7:c6:8a:8a:33:97:60:37:10: + 3e:97:3e:6e:29:15:d6:a1:0f:d1:88:2c:12:9f:6f: + aa:a4:c6:42:eb:41:a2:e3:95:43:d3:01:85:6d:8e: + bb:3b:f3:23:36:c7:fe:3b:e0:a1:25:07:48:ab:c9: + 89:74:ff:08:8f:80:bf:c0:96:65:f3:ee:ec:4b:68: + bd:9d:88:c3:31:b3:40:f1:e8:cf:f6:38:bb:9c:e4: + d1:7f:d4:e5:58:9b:7c:fa:d4:f3:0e:9b:75:91:e4: + ba:52:2e:19:7e:d1:f5:cd:5a:19:fc:ba:06:f6:fb: + 52:a8:4b:99:04:dd:f8:f9:b4:8b:50:a3:4e:62:89: + f0:87:24:fa:83:42:c1:87:fa:d5:2d:29:2a:5a:71: + 7a:64:6a:d7:27:60:63:0d:db:ce:49:f5:8d:1f:90: + 89:32:17:f8:73:43:b8:d2:5a:93:86:61:d6:e1:75: + 0a:ea:79:66:76:88:4f:71:eb:04:25:d6:0a:5a:7a: + 93:e5:b9:4b:17:40:0f:b1:b6:b9:f5:de:4f:dc:e0: + b3:ac:3b:11:70:60:84:4a:43:6e:99:20:c0:29:71: + 0a:c0:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + CA Issuers - URI:http://www.accv.es/fileadmin/Archivos/certificados/raizaccv1.crt + OCSP - URI:http://ocsp.accv.es + + X509v3 Subject Key Identifier: + D2:87:B4:E3:DF:37:27:93:55:F6:56:EA:81:E5:36:CC:8C:1E:3F:BD + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:D2:87:B4:E3:DF:37:27:93:55:F6:56:EA:81:E5:36:CC:8C:1E:3F:BD + + X509v3 Certificate Policies: + Policy: X509v3 Any Policy + User Notice: + Explicit Text: + CPS: http://www.accv.es/legislacion_c.htm + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://www.accv.es/fileadmin/Archivos/certificados/raizaccv1_der.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Alternative Name: + email:accv@accv.es + Signature Algorithm: sha1WithRSAEncryption + 97:31:02:9f:e7:fd:43:67:48:44:14:e4:29:87:ed:4c:28:66: + d0:8f:35:da:4d:61:b7:4a:97:4d:b5:db:90:e0:05:2e:0e:c6: + 79:d0:f2:97:69:0f:bd:04:47:d9:be:db:b5:29:da:9b:d9:ae: + a9:99:d5:d3:3c:30:93:f5:8d:a1:a8:fc:06:8d:44:f4:ca:16: + 95:7c:33:dc:62:8b:a8:37:f8:27:d8:09:2d:1b:ef:c8:14:27: + 20:a9:64:44:ff:2e:d6:75:aa:6c:4d:60:40:19:49:43:54:63: + da:e2:cc:ba:66:e5:4f:44:7a:5b:d9:6a:81:2b:40:d5:7f:f9: + 01:27:58:2c:c8:ed:48:91:7c:3f:a6:00:cf:c4:29:73:11:36: + de:86:19:3e:9d:ee:19:8a:1b:d5:b0:ed:8e:3d:9c:2a:c0:0d: + d8:3d:66:e3:3c:0d:bd:d5:94:5c:e2:e2:a7:35:1b:04:00:f6: + 3f:5a:8d:ea:43:bd:5f:89:1d:a9:c1:b0:cc:99:e2:4d:00:0a: + da:c9:27:5b:e7:13:90:5c:e4:f5:33:a2:55:6d:dc:e0:09:4d: + 2f:b1:26:5b:27:75:00:09:c4:62:77:29:08:5f:9e:59:ac:b6: + 7e:ad:9f:54:30:22:03:c1:1e:71:64:fe:f9:38:0a:96:18:dd: + 02:14:ac:23:cb:06:1c:1e:a4:7d:8d:0d:de:27:41:e8:ad:da: + 15:b7:b0:23:dd:2b:a8:d3:da:25:87:ed:e8:55:44:4d:88:f4: + 36:7e:84:9a:78:ac:f7:0e:56:49:0e:d6:33:25:d6:84:50:42: + 6c:20:12:1d:2a:d5:be:bc:f2:70:81:a4:70:60:be:05:b5:9b: + 9e:04:44:be:61:23:ac:e9:a5:24:8c:11:80:94:5a:a2:a2:b9: + 49:d2:c1:dc:d1:a7:ed:31:11:2c:9e:19:a6:ee:e1:55:e1:c0: + ea:cf:0d:84:e4:17:b7:a2:7c:a5:de:55:25:06:ee:cc:c0:87: + 5c:40:da:cc:95:3f:55:e0:35:c7:b8:84:be:b4:5d:cd:7a:83: + 01:72:ee:87:e6:5f:1d:ae:b5:85:c6:26:df:e6:c1:9a:e9:1e: + 02:47:9f:2a:a8:6d:a9:5b:cf:ec:45:77:7f:98:27:9a:32:5d: + 2a:e3:84:ee:c5:98:66:2f:96:20:1d:dd:d8:c3:27:d7:b0:f9: + fe:d9:7d:cd:d0:9f:8f:0b:14:58:51:9f:2f:8b:c3:38:2d:de: + e8:8f:d6:8d:87:a4:f5:56:43:16:99:2c:f4:a4:56:b4:34:b8: + 61:37:c9:c2:58:80:1b:a0:97:a1:fc:59:8d:e9:11:f6:d1:0f: + 4b:55:34:46:2a:8b:86:3b +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE +AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw +CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ +BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND +VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb +qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY +HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo +G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA +lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr +IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ +0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH +k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 +4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO +m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa +cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl +uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI +KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls +ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG +AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT +VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG +CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA +cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA +QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA +7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA +cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA +QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA +czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu +aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt +aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud +DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF +BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp +D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU +JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m +AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD +vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms +tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH +7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA +h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF +d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H +pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +TWCA Global Root CA +# Issuer: CN=TWCA Global Root CA,OU=Root CA,O=TAIWAN-CA,C=TW +# Serial Number: 3262 (0xcbe) +# Subject: CN=TWCA Global Root CA,OU=Root CA,O=TAIWAN-CA,C=TW +# Not Valid Before: Wed Jun 27 06:28:33 2012 +# Not Valid After : Tue Dec 31 15:59:59 2030 +# Fingerprint (MD5): F9:03:7E:CF:E6:9E:3C:73:7A:2A:90:07:69:FF:2B:96 +# Fingerprint (SHA1): 9C:BB:48:53:F6:A4:F6:D3:52:A4:E8:32:52:55:60:13:F5:AD:AF:65 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=F9:03:7E:CF:E6:9E:3C:73:7A:2A:90:07:69:FF:2B:96 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3262 (0xcbe) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Global Root CA + Validity + Not Before: Jun 27 06:28:33 2012 GMT + Not After : Dec 31 15:59:59 2030 GMT + Subject: C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Global Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:b0:05:db:c8:eb:8c:c4:6e:8a:21:ef:8e:4d:9c: + 71:0a:1f:52:70:ed:6d:82:9c:97:c5:d7:4c:4e:45: + 49:cb:40:42:b5:12:34:6c:19:c2:74:a4:31:5f:85: + 02:97:ec:43:33:0a:53:d2:9c:8c:8e:b7:b8:79:db: + 2b:d5:6a:f2:8e:66:c4:ee:2b:01:07:92:d4:b3:d0: + 02:df:50:f6:55:af:66:0e:cb:e0:47:60:2f:2b:32: + 39:35:52:3a:28:83:f8:7b:16:c6:18:b8:62:d6:47: + 25:91:ce:f0:19:12:4d:ad:63:f5:d3:3f:75:5f:29: + f0:a1:30:1c:2a:a0:98:a6:15:bd:ee:fd:19:36:f0: + e2:91:43:8f:fa:ca:d6:10:27:49:4c:ef:dd:c1:f1: + 85:70:9b:ca:ea:a8:5a:43:fc:6d:86:6f:73:e9:37: + 45:a9:f0:36:c7:cc:88:75:1e:bb:6c:06:ff:9b:6b: + 3e:17:ec:61:aa:71:7c:c6:1d:a2:f7:49:e9:15:b5: + 3c:d6:a1:61:f5:11:f7:05:6f:1d:fd:11:be:d0:30: + 07:c2:29:b0:09:4e:26:dc:e3:a2:a8:91:6a:1f:c2: + 91:45:88:5c:e5:98:b8:71:a5:15:19:c9:7c:75:11: + cc:70:74:4f:2d:9b:1d:91:44:fd:56:28:a0:fe:bb: + 86:6a:c8:fa:5c:0b:58:dc:c6:4b:76:c8:ab:22:d9: + 73:0f:a5:f4:5a:02:89:3f:4f:9e:22:82:ee:a2:74: + 53:2a:3d:53:27:69:1d:6c:8e:32:2c:64:00:26:63: + 61:36:4e:a3:46:b7:3f:7d:b3:2d:ac:6d:90:a2:95: + a2:ce:cf:da:82:e7:07:34:19:96:e9:b8:21:aa:29: + 7e:a6:38:be:8e:29:4a:21:66:79:1f:b3:c3:b5:09: + 67:de:d6:d4:07:46:f3:2a:da:e6:22:37:60:cb:81: + b6:0f:a0:0f:e9:c8:95:7f:bf:55:91:05:7a:cf:3d: + 15:c0:6f:de:09:94:01:83:d7:34:1b:cc:40:a5:f0: + b8:9b:67:d5:98:91:3b:a7:84:78:95:26:a4:5a:08: + f8:2b:74:b4:00:04:3c:df:b8:14:8e:e8:df:a9:8d: + 6c:67:92:33:1d:c0:b7:d2:ec:92:c8:be:09:bf:2c: + 29:05:6f:02:6b:9e:ef:bc:bf:2a:bc:5b:c0:50:8f: + 41:70:71:87:b2:4d:b7:04:a9:84:a3:32:af:ae:ee: + 6b:17:8b:b2:b1:fe:6c:e1:90:8c:88:a8:97:48:ce: + c8:4d:cb:f3:06:cf:5f:6a:0a:42:b1:1e:1e:77:2f: + 8e:a0:e6:92:0e:06:fc:05:22:d2:26:e1:31:51:7d: + 32:dc:0f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 5f:34:81:76:ef:96:1d:d5:e5:b5:d9:02:63:84:16:c1:ae:a0: + 70:51:a7:f7:4c:47:35:c8:0b:d7:28:3d:89:71:d9:aa:33:41: + ea:14:1b:6c:21:00:c0:6c:42:19:7e:9f:69:5b:20:42:df:a2: + d2:da:c4:7c:97:4b:8d:b0:e8:ac:c8:ee:a5:69:04:99:0a:92: + a6:ab:27:2e:1a:4d:81:bf:84:d4:70:1e:ad:47:fe:fd:4a:9d: + 33:e0:f2:b9:c4:45:08:21:0a:da:69:69:73:72:0d:be:34:fe: + 94:8b:ad:c3:1e:35:d7:a2:83:ef:e5:38:c7:a5:85:1f:ab:cf: + 34:ec:3f:28:fe:0c:f1:57:86:4e:c9:55:f7:1c:d4:d8:a5:7d: + 06:7a:6f:d5:df:10:df:81:4e:21:65:b1:b6:e1:17:79:95:45: + 06:ce:5f:cc:dc:46:89:63:68:44:8d:93:f4:64:70:a0:3d:9d: + 28:05:c3:39:70:b8:62:7b:20:fd:e4:db:e9:08:a1:b8:9e:3d: + 09:c7:4f:fb:2c:f8:93:76:41:de:52:e0:e1:57:d2:9d:03:bc: + 77:9e:fe:9e:29:5e:f7:c1:51:60:1f:de:da:0b:b2:2d:75:b7: + 43:48:93:e7:f6:79:c6:84:5d:80:59:60:94:fc:78:98:8f:3c: + 93:51:ed:40:90:07:df:64:63:24:cb:4e:71:05:a1:d7:94:1a: + 88:32:f1:22:74:22:ae:a5:a6:d8:12:69:4c:60:a3:02:ee:2b: + ec:d4:63:92:0b:5e:be:2f:76:6b:a3:b6:26:bc:8f:03:d8:0a: + f2:4c:64:46:bd:39:62:e5:96:eb:34:63:11:28:cc:95:f1:ad: + ef:ef:dc:80:58:48:e9:4b:b8:ea:65:ac:e9:fc:80:b5:b5:c8: + 45:f9:ac:c1:9f:d9:b9:ea:62:88:8e:c4:f1:4b:83:12:ad:e6: + 8b:84:d6:9e:c2:eb:83:18:9f:6a:bb:1b:24:60:33:70:cc:ec: + f7:32:f3:5c:d9:79:7d:ef:9e:a4:fe:c9:23:c3:24:ee:15:92: + b1:3d:91:4f:26:86:bd:66:73:24:13:ea:a4:ae:63:c1:ad:7d: + 84:03:3c:10:78:86:1b:79:e3:c4:f3:f2:04:95:20:ae:23:82: + c4:b3:3a:00:62:bf:e6:36:24:e1:57:ba:c7:1e:90:75:d5:5f: + 3f:95:61:2b:c1:3b:cd:e5:b3:68:61:d0:46:26:a9:21:52:69: + 2d:eb:2e:c7:eb:77:ce:a6:3a:b5:03:33:4f:76:d1:e7:5c:54: + 01:5d:cb:78:f4:c9:0c:bf:cf:12:8e:17:2d:23:68:94:e7:ab: + fe:a9:b2:2b:06:d0:04:cd +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx +EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT +VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 +NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT +B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF +10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz +0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh +MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH +zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc +46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 +yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi +laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP +oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA +BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE +qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm +4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL +1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF +H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo +RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ +nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh +15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW +6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW +nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j +wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz +aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy +KwbQBM0= +-----END CERTIFICATE----- + +TeliaSonera Root CA v1 +# Issuer: CN=TeliaSonera Root CA v1,O=TeliaSonera +# Serial Number:00:95:be:16:a0:f7:2e:46:f1:7b:39:82:72:fa:8b:cd:96 +# Subject: CN=TeliaSonera Root CA v1,O=TeliaSonera +# Not Valid Before: Thu Oct 18 12:00:50 2007 +# Not Valid After : Mon Oct 18 12:00:50 2032 +# Fingerprint (MD5): 37:41:49:1B:18:56:9A:26:F5:AD:C2:66:FB:40:A5:4C +# Fingerprint (SHA1): 43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=37:41:49:1B:18:56:9A:26:F5:AD:C2:66:FB:40:A5:4C +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 95:be:16:a0:f7:2e:46:f1:7b:39:82:72:fa:8b:cd:96 + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=TeliaSonera, CN=TeliaSonera Root CA v1 + Validity + Not Before: Oct 18 12:00:50 2007 GMT + Not After : Oct 18 12:00:50 2032 GMT + Subject: O=TeliaSonera, CN=TeliaSonera Root CA v1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:c2:be:eb:27:f0:21:a3:f3:69:26:55:7e:9d:c5: + 55:16:91:5c:fd:ef:21:bf:53:80:7a:2d:d2:91:8c: + 63:31:f0:ec:24:f0:c3:a5:d2:72:7c:10:6d:f4:37: + b7:e5:e6:7c:79:ea:8c:b5:82:8b:ae:48:b6:ac:00: + dc:65:75:ec:2a:4d:5f:c1:87:f5:20:65:2b:81:a8: + 47:3e:89:23:95:30:16:90:7f:e8:57:07:48:e7:19: + ae:bf:45:67:b1:37:1b:06:2a:fe:de:f9:ac:7d:83: + fb:5e:ba:e4:8f:97:67:be:4b:8e:8d:64:07:57:38: + 55:69:34:36:3d:13:48:ef:4f:e2:d3:66:1e:a4:cf: + 1a:b7:5e:36:33:d4:b4:06:bd:18:01:fd:77:84:50: + 00:45:f5:8c:5d:e8:23:bc:7e:fe:35:e1:ed:50:7b: + a9:30:8d:19:d3:09:8e:68:67:5d:bf:3c:97:18:53: + bb:29:62:c5:ca:5e:72:c1:c7:96:d4:db:2d:a0:b4: + 1f:69:03:ec:ea:e2:50:f1:0c:3c:f0:ac:f3:53:2d: + f0:1c:f5:ed:6c:39:39:73:80:16:c8:52:b0:23:cd: + e0:3e:dc:dd:3c:47:a0:bb:35:8a:e2:98:68:8b:be: + e5:bf:72:ee:d2:fa:a5:ed:12:ed:fc:98:18:a9:26: + 76:dc:28:4b:10:20:1c:d3:7f:16:77:2d:ed:6f:80: + f7:49:bb:53:05:bb:5d:68:c7:d4:c8:75:16:3f:89: + 5a:8b:f7:17:47:d4:4c:f1:d2:89:79:3e:4d:3d:98: + a8:61:de:3a:1e:d2:f8:5e:03:e0:c1:c9:1c:8c:d3: + 8d:4d:d3:95:36:b3:37:5f:63:63:9b:33:14:f0:2d: + 26:6b:53:7c:89:8c:32:c2:6e:ec:3d:21:00:39:c9: + a1:68:e2:50:83:2e:b0:3a:2b:f3:36:a0:ac:2f:e4: + 6f:61:c2:51:09:39:3e:8b:53:b9:bb:67:da:dc:53: + b9:76:59:36:9d:43:e5:20:e0:3d:32:60:85:22:51: + b7:c7:33:bb:dd:15:2f:a4:78:a6:07:7b:81:46:36: + 04:86:dd:79:35:c7:95:2c:3b:b0:a3:17:35:e5:73: + 1f:b4:5c:59:ef:da:ea:10:65:7b:7a:d0:7f:9f:b3: + b4:2a:37:3b:70:8b:9b:5b:b9:2b:b7:ec:b2:51:12: + 97:53:29:5a:d4:f0:12:10:dc:4f:02:bb:12:92:2f: + 62:d4:3f:69:43:7c:0d:d6:fc:58:75:01:88:9d:58: + 16:4b:de:ba:90:ff:47:01:89:06:6a:f6:5f:b2:90: + 6a:b3:02:a6:02:88:bf:b3:47:7e:2a:d9:d5:fa:68: + 78:35:4d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + F0:8F:59:38:00:B3:F5:8F:9A:96:0C:D5:EB:FA:7B:AA:17:E8:13:12 + Signature Algorithm: sha1WithRSAEncryption + be:e4:5c:62:4e:24:f4:0c:08:ff:f0:d3:0c:68:e4:93:49:22: + 3f:44:27:6f:bb:6d:de:83:66:ce:a8:cc:0d:fc:f5:9a:06:e5: + 77:14:91:eb:9d:41:7b:99:2a:84:e5:ff:fc:21:c1:5d:f0:e4: + 1f:57:b7:75:a9:a1:5f:02:26:ff:d7:c7:f7:4e:de:4f:f8:f7: + 1c:46:c0:7a:4f:40:2c:22:35:f0:19:b1:d0:6b:67:2c:b0:a8: + e0:c0:40:37:35:f6:84:5c:5c:e3:af:42:78:fe:a7:c9:0d:50: + ea:0d:84:76:f6:51:ef:83:53:c6:7a:ff:0e:56:49:2e:8f:7a: + d6:0c:e6:27:54:e3:4d:0a:60:72:62:cd:91:07:d6:a5:bf:c8: + 99:6b:ed:c4:19:e6:ab:4c:11:38:c5:6f:31:e2:6e:49:c8:3f: + 76:80:26:03:26:29:e0:36:f6:f6:20:53:e3:17:70:34:17:9d: + 63:68:1e:6b:ec:c3:4d:86:b8:13:30:2f:5d:46:0d:47:43:d5: + 1b:aa:59:0e:b9:5c:8d:06:48:ad:74:87:5f:c7:fc:31:54:41: + 13:e2:c7:21:0e:9e:e0:1e:0d:e1:c0:7b:43:85:90:c5:8a:58: + c6:65:0a:78:57:f2:c6:23:0f:01:d9:20:4b:de:0f:fb:92:85: + 75:2a:5c:73:8d:6d:7b:25:91:ca:ee:45:ae:06:4b:00:cc:d3: + b1:59:50:da:3a:88:3b:29:43:46:5e:97:2b:54:ce:53:6f:8d: + 4a:e7:96:fa:bf:71:0e:42:8b:7c:fd:28:a0:d0:48:ca:da:c4: + 81:4c:bb:a2:73:93:26:c8:eb:0c:d6:26:88:b6:c0:24:cf:bb: + bd:5b:eb:75:7d:e9:08:8e:86:33:2c:79:77:09:69:a5:89:fc: + b3:70:90:87:76:8f:d3:22:bb:42:ce:bd:73:0b:20:26:2a:d0: + 9b:3d:70:1e:24:6c:cd:87:76:a9:17:96:b7:cf:0d:92:fb:8e: + 18:a9:98:49:d1:9e:fe:60:44:72:21:b9:19:ed:c2:f5:31:f1: + 39:48:88:90:24:75:54:16:ad:ce:f4:f8:69:14:64:39:fb:a3: + b8:ba:70:40:c7:27:1c:bf:c4:56:53:fa:63:65:d0:f3:1c:0e: + 16:f5:6b:86:58:4d:18:d4:e4:0d:8e:a5:9d:5b:91:dc:76:24: + 50:3f:c6:2a:fb:d9:b7:9c:b5:d6:e6:d0:d9:e8:19:8b:15:71: + 48:ad:b7:ea:d8:59:88:d4:90:bf:16:b3:d9:e9:ac:59:61:54: + c8:1c:ba:ca:c1:ca:e1:b9:20:4c:8f:3a:93:89:a5:a0:cc:bf: + d3:f6:75:a4:75:96:6d:56 +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw +NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv +b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD +VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F +VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 +7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X +Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ +/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs +81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm +dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe +Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu +sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 +pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs +slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ +arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD +VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG +9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl +dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj +TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed +Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 +Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI +OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 +vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW +t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn +HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx +SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +E-Tugra Certification Authority +# Issuer: CN=E-Tugra Certification Authority,OU=E-Tugra Sertifikasyon Merkezi,O=E-Tu..ra EBG Bili..im Teknolojileri ve Hizmetleri A....,L=Ankara,C=TR +# Serial Number:6a:68:3e:9c:51:9b:cb:53 +# Subject: CN=E-Tugra Certification Authority,OU=E-Tugra Sertifikasyon Merkezi,O=E-Tu..ra EBG Bili..im Teknolojileri ve Hizmetleri A....,L=Ankara,C=TR +# Not Valid Before: Tue Mar 05 12:09:48 2013 +# Not Valid After : Fri Mar 03 12:09:48 2023 +# Fingerprint (MD5): B8:A1:03:63:B0:BD:21:71:70:8A:6F:13:3A:BB:79:49 +# Fingerprint (SHA1): 51:C6:E7:08:49:06:6E:F3:92:D4:5C:A0:0D:6D:A3:62:8F:C3:52:39 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=B8:A1:03:63:B0:BD:21:71:70:8A:6F:13:3A:BB:79:49 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7667447206703254355 (0x6a683e9c519bcb53) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=TR, L=Ankara, O=E-Tu\xC4\x9Fra EBG Bili\xC5\x9Fim Teknolojileri ve Hizmetleri A.\xC5\x9E., OU=E-Tugra Sertifikasyon Merkezi, CN=E-Tugra Certification Authority + Validity + Not Before: Mar 5 12:09:48 2013 GMT + Not After : Mar 3 12:09:48 2023 GMT + Subject: C=TR, L=Ankara, O=E-Tu\xC4\x9Fra EBG Bili\xC5\x9Fim Teknolojileri ve Hizmetleri A.\xC5\x9E., OU=E-Tugra Sertifikasyon Merkezi, CN=E-Tugra Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:e2:f5:3f:93:05:51:1e:85:62:54:5e:7a:0b:f5: + 18:07:83:ae:7e:af:7c:f7:d4:8a:6b:a5:63:43:39: + b9:4b:f7:c3:c6:64:89:3d:94:2e:54:80:52:39:39: + 07:4b:4b:dd:85:07:76:87:cc:bf:2f:95:4c:cc:7d: + a7:3d:bc:47:0f:98:70:f8:8c:85:1e:74:8e:92:6d: + 1b:40:d1:99:0d:bb:75:6e:c8:a9:6b:9a:c0:84:31: + af:ca:43:cb:eb:2b:34:e8:8f:97:6b:01:9b:d5:0e: + 4a:08:aa:5b:92:74:85:43:d3:80:ae:a1:88:5b:ae: + b3:ea:5e:cb:16:9a:77:44:c8:a1:f6:54:68:ce:de: + 8f:97:2b:ba:5b:40:02:0c:64:17:c0:b5:93:cd:e1: + f1:13:66:ce:0c:79:ef:d1:91:28:ab:5f:a0:12:52: + 30:73:19:8e:8f:e1:8c:07:a2:c3:bb:4a:f0:ea:1f: + 15:a8:ee:25:cc:a4:46:f8:1b:22:ef:b3:0e:43:ba: + 2c:24:b8:c5:2c:5c:d4:1c:f8:5d:64:bd:c3:93:5e: + 28:a7:3f:27:f1:8e:1e:d3:2a:50:05:a3:55:d9:cb: + e7:39:53:c0:98:9e:8c:54:62:8b:26:b0:f7:7d:8d: + 7c:e4:c6:9e:66:42:55:82:47:e7:b2:58:8d:66:f7: + 07:7c:2e:36:e6:50:1c:3f:db:43:24:c5:bf:86:47: + 79:b3:79:1c:f7:5a:f4:13:ec:6c:f8:3f:e2:59:1f: + 95:ee:42:3e:b9:ad:a8:32:85:49:97:46:fe:4b:31: + 8f:5a:cb:ad:74:47:1f:e9:91:b7:df:28:04:22:a0: + d4:0f:5d:e2:79:4f:ea:6c:85:86:bd:a8:a6:ce:e4: + fa:c3:e1:b3:ae:de:3c:51:ee:cb:13:7c:01:7f:84: + 0e:5d:51:94:9e:13:0c:b6:2e:a5:4c:f9:39:70:36: + 6f:96:ca:2e:0c:44:55:c5:ca:fa:5d:02:a3:df:d6: + 64:8c:5a:b3:01:0a:a9:b5:0a:47:17:ff:ef:91:40: + 2a:8e:a1:46:3a:31:98:e5:11:fc:cc:bb:49:56:8a: + fc:b9:d0:61:9a:6f:65:6c:e6:c3:cb:3e:75:49:fe: + 8f:a7:e2:89:c5:67:d7:9d:46:13:4e:31:76:3b:24: + b3:9e:11:65:86:ab:7f:ef:1d:d4:f8:bc:e7:ac:5a: + 5c:b7:5a:47:5c:55:ce:55:b4:22:71:5b:5b:0b:f0: + cf:dc:a0:61:64:ea:a9:d7:68:0a:63:a7:e0:0d:3f: + a0:af:d3:aa:d2:7e:ef:51:a0:e6:51:2b:55:92:15: + 17:53:cb:b7:66:0e:66:4c:f8:f9:75:4c:90:e7:12: + 70:c7:45 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 2E:E3:DB:B2:49:D0:9C:54:79:5C:FA:27:2A:FE:CC:4E:D2:E8:4E:54 + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:2E:E3:DB:B2:49:D0:9C:54:79:5C:FA:27:2A:FE:CC:4E:D2:E8:4E:54 + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 05:37:3a:f4:4d:b7:45:e2:45:75:24:8f:b6:77:52:e8:1c:d8: + 10:93:65:f3:f2:59:06:a4:3e:1e:29:ec:5d:d1:d0:ab:7c:e0: + 0a:90:48:78:ed:4e:98:03:99:fe:28:60:91:1d:30:1d:b8:63: + 7c:a8:e6:35:b5:fa:d3:61:76:e6:d6:07:4b:ca:69:9a:b2:84: + 7a:77:93:45:17:15:9f:24:d0:98:13:12:ff:bb:a0:2e:fd:4e: + 4c:87:f8:ce:5c:aa:98:1b:05:e0:00:46:4a:82:80:a5:33:8b: + 28:dc:ed:38:d3:df:e5:3e:e9:fe:fb:59:dd:61:84:4f:d2:54: + 96:13:61:13:3e:8f:80:69:be:93:47:b5:35:43:d2:5a:bb:3d: + 5c:ef:b3:42:47:cd:3b:55:13:06:b0:09:db:fd:63:f6:3a:88: + 0a:99:6f:7e:e1:ce:1b:53:6a:44:66:23:51:08:7b:bc:5b:52: + a2:fd:06:37:38:40:61:8f:4a:96:b8:90:37:f8:66:c7:78:90: + 00:15:2e:8b:ad:51:35:53:07:a8:6b:68:ae:f9:4e:3c:07:26: + cd:08:05:70:cc:39:3f:76:bd:a5:d3:67:26:01:86:a6:53:d2: + 60:3b:7c:43:7f:55:8a:bc:95:1a:c1:28:39:4c:1f:43:d2:91: + f4:72:59:8a:b9:56:fc:3f:b4:9d:da:70:9c:76:5a:8c:43:50: + ee:8e:30:72:4d:df:ff:49:f7:c6:a9:67:d9:6d:ac:02:11:e2: + 3a:16:25:a7:58:08:cb:6f:53:41:9c:48:38:47:68:33:d1:d7: + c7:8f:d4:74:21:d4:c3:05:90:7a:ff:ce:96:88:b1:15:29:5d: + 23:ab:d0:60:a1:12:4f:de:f4:17:cd:32:e5:c9:bf:c8:43:ad: + fd:2e:8e:f1:af:e2:f4:98:fa:12:1f:20:d8:c0:a7:0c:85:c5: + 90:f4:3b:2d:96:26:b1:2c:be:4c:ab:eb:b1:d2:8a:c9:db:78: + 13:0f:1e:09:9d:6d:8f:00:9f:02:da:c1:fa:1f:7a:7a:09:c4: + 4a:e6:88:2a:97:9f:89:8b:fd:37:5f:5f:3a:ce:38:59:86:4b: + af:71:0b:b4:d8:f2:70:4f:9f:32:13:e3:b0:a7:57:e5:da:da: + 43:cb:84:34:f2:28:c4:ea:6d:f4:2a:ef:c1:6b:76:da:fb:7e: + bb:85:3c:d2:53:c2:4d:be:71:e1:45:d1:fd:23:67:0d:13:75: + fb:cf:65:67:22:9d:ae:b0:09:d1:09:ff:1d:34:bf:fe:23:97: + 37:d2:39:fa:3d:0d:06:0b:b4:db:3b:a3:ab:6f:5c:1d:b6:7e: + e8:b3:82:34:ed:06:5c:24 +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC +aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV +BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 +Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz +MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ +BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp +em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY +B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH +D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF +Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo +q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D +k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH +fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut +dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM +ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 +zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX +U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 +Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 +XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF +Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR +HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY +GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c +77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 ++GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK +vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 +FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl +yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P +AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD +y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d +NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 2 +# Issuer: CN=T-TeleSec GlobalRoot Class 2,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE +# Serial Number: 1 (0x1) +# Subject: CN=T-TeleSec GlobalRoot Class 2,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE +# Not Valid Before: Wed Oct 01 10:40:14 2008 +# Not Valid After : Sat Oct 01 23:59:59 2033 +# Fingerprint (MD5): 2B:9B:9E:E4:7B:6C:1F:00:72:1A:CC:C1:77:79:DF:6A +# Fingerprint (SHA1): 59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=2B:9B:9E:E4:7B:6C:1F:00:72:1A:CC:C1:77:79:DF:6A +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=DE, O=T-Systems Enterprise Services GmbH, OU=T-Systems Trust Center, CN=T-TeleSec GlobalRoot Class 2 + Validity + Not Before: Oct 1 10:40:14 2008 GMT + Not After : Oct 1 23:59:59 2033 GMT + Subject: C=DE, O=T-Systems Enterprise Services GmbH, OU=T-Systems Trust Center, CN=T-TeleSec GlobalRoot Class 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:aa:5f:da:1b:5f:e8:73:91:e5:da:5c:f4:a2:e6: + 47:e5:f3:68:55:60:05:1d:02:a4:b3:9b:59:f3:1e: + 8a:af:34:ad:fc:0d:c2:d9:48:19:ee:69:8f:c9:20: + fc:21:aa:07:19:ed:b0:5c:ac:65:c7:5f:ed:02:7c: + 7b:7c:2d:1b:d6:ba:b9:80:c2:18:82:16:84:fa:66: + b0:08:c6:54:23:81:e4:cd:b9:49:3f:f6:4f:6e:37: + 48:28:38:0f:c5:be:e7:68:70:fd:39:97:4d:d2:c7: + 98:91:50:aa:c4:44:b3:23:7d:39:47:e9:52:62:d6: + 12:93:5e:b7:31:96:42:05:fb:76:a7:1e:a3:f5:c2: + fc:e9:7a:c5:6c:a9:71:4f:ea:cb:78:bc:60:af:c7: + de:f4:d9:cb:be:7e:33:a5:6e:94:83:f0:34:fa:21: + ab:ea:8e:72:a0:3f:a4:de:30:5b:ef:86:4d:6a:95: + 5b:43:44:a8:10:15:1c:e5:01:57:c5:98:f1:e6:06: + 28:91:aa:20:c5:b7:53:26:51:43:b2:0b:11:95:58: + e1:c0:0f:76:d9:c0:8d:7c:81:f3:72:70:9e:6f:fe: + 1a:8e:d9:5f:35:c6:b2:6f:34:7c:be:48:4f:e2:5a: + 39:d7:d8:9d:78:9e:9f:86:3e:03:5e:19:8b:44:a2: + d5:c7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + BF:59:20:36:00:79:A0:A0:22:6B:8C:D5:F2:61:D2:B8:2C:CB:82:4A + Signature Algorithm: sha256WithRSAEncryption + 31:03:a2:61:0b:1f:74:e8:72:36:c6:6d:f9:4d:9e:fa:22:a8: + e1:81:56:cf:cd:bb:9f:ea:ab:91:19:38:af:aa:7c:15:4d:f3: + b6:a3:8d:a5:f4:8e:f6:44:a9:a7:e8:21:95:ad:3e:00:62:16: + 88:f0:02:ba:fc:61:23:e6:33:9b:30:7a:6b:36:62:7b:ad:04: + 23:84:58:65:e2:db:2b:8a:e7:25:53:37:62:53:5f:bc:da:01: + 62:29:a2:a6:27:71:e6:3a:22:7e:c1:6f:1d:95:70:20:4a:07: + 34:df:ea:ff:15:80:e5:ba:d7:7a:d8:5b:75:7c:05:7a:29:47: + 7e:40:a8:31:13:77:cd:40:3b:b4:51:47:7a:2e:11:e3:47:11: + de:9d:66:d0:8b:d5:54:66:fa:83:55:ea:7c:c2:29:89:1b:e9: + 6f:b3:ce:e2:05:84:c9:2f:3e:78:85:62:6e:c9:5f:c1:78:63: + 74:58:c0:48:18:0c:99:39:eb:a4:cc:1a:b5:79:5a:8d:15:9c: + d8:14:0d:f6:7a:07:57:c7:22:83:05:2d:3c:9b:25:26:3d:18: + b3:a9:43:7c:c8:c8:ab:64:8f:0e:a3:bf:9c:1b:9d:30:db:da: + d0:19:2e:aa:3c:f1:fb:33:80:76:e4:cd:ad:19:4f:05:27:8e: + 13:a1:6e:c2 +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd +AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC +FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi +1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq +jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ +wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ +WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy +NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC +uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw +IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 +g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP +BSeOE6Fuwg== +-----END CERTIFICATE----- + +Atos TrustedRoot 2011 +# Issuer: C=DE,O=Atos,CN=Atos TrustedRoot 2011 +# Serial Number:5c:33:cb:62:2c:5f:b3:32 +# Subject: C=DE,O=Atos,CN=Atos TrustedRoot 2011 +# Not Valid Before: Thu Jul 07 14:58:30 2011 +# Not Valid After : Tue Dec 31 23:59:59 2030 +# Fingerprint (MD5): AE:B9:C4:32:4B:AC:7F:5D:66:CC:77:94:BB:2A:77:56 +# Fingerprint (SHA1): 2B:B1:F5:3E:55:0C:1D:C5:F1:D4:E6:B7:6A:46:4B:55:06:02:AC:21 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=AE:B9:C4:32:4B:AC:7F:5D:66:CC:77:94:BB:2A:77:56 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 6643877497813316402 (0x5c33cb622c5fb332) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Atos TrustedRoot 2011, O=Atos, C=DE + Validity + Not Before: Jul 7 14:58:30 2011 GMT + Not After : Dec 31 23:59:59 2030 GMT + Subject: CN=Atos TrustedRoot 2011, O=Atos, C=DE + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:95:85:3b:97:6f:2a:3b:2e:3b:cf:a6:f3:29:35: + be:cf:18:ac:3e:aa:d9:f8:4d:a0:3e:1a:47:b9:bc: + 9a:df:f2:fe:cc:3e:47:e8:7a:96:c2:24:8e:35:f4: + a9:0c:fc:82:fd:6d:c1:72:62:27:bd:ea:6b:eb:e7: + 8a:cc:54:3e:90:50:cf:80:d4:95:fb:e8:b5:82:d4: + 14:c5:b6:a9:55:25:57:db:b1:50:f6:b0:60:64:59: + 7a:69:cf:03:b7:6f:0d:be:ca:3e:6f:74:72:ea:aa: + 30:2a:73:62:be:49:91:61:c8:11:fe:0e:03:2a:f7: + 6a:20:dc:02:15:0d:5e:15:6a:fc:e3:82:c1:b5:c5: + 9d:64:09:6c:a3:59:98:07:27:c7:1b:96:2b:61:74: + 71:6c:43:f1:f7:35:89:10:e0:9e:ec:55:a1:37:22: + a2:87:04:05:2c:47:7d:b4:1c:b9:62:29:66:28:ca: + b7:e1:93:f5:a4:94:03:99:b9:70:85:b5:e6:48:ea: + 8d:50:fc:d9:de:cc:6f:07:0e:dd:0b:72:9d:80:30: + 16:07:95:3f:28:0e:fd:c5:75:4f:53:d6:74:9a:b4: + 24:2e:8e:02:91:cf:76:c5:9b:1e:55:74:9c:78:21: + b1:f0:2d:f1:0b:9f:c2:d5:96:18:1f:f0:54:22:7a: + 8c:07 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A7:A5:06:B1:2C:A6:09:60:EE:D1:97:E9:70:AE:BC:3B:19:6C:DB:21 + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:A7:A5:06:B1:2C:A6:09:60:EE:D1:97:E9:70:AE:BC:3B:19:6C:DB:21 + + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.6189.3.4.1.1 + + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 26:77:34:db:94:48:86:2a:41:9d:2c:3e:06:90:60:c4:8c:ac: + 0b:54:b8:1f:b9:7b:d3:07:39:e4:fa:3e:7b:b2:3d:4e:ed:9f: + 23:bd:97:f3:6b:5c:ef:ee:fd:40:a6:df:a1:93:a1:0a:86:ac: + ef:20:d0:79:01:bd:78:f7:19:d8:24:31:34:04:01:a6:ba:15: + 9a:c3:27:dc:d8:4f:0f:cc:18:63:ff:99:0f:0e:91:6b:75:16: + e1:21:fc:d8:26:c7:47:b7:a6:cf:58:72:71:7e:ba:e1:4d:95: + 47:3b:c9:af:6d:a1:b4:c1:ec:89:f6:b4:0f:38:b5:e2:64:dc: + 25:cf:a6:db:eb:9a:5c:99:a1:c5:08:de:fd:e6:da:d5:d6:5a: + 45:0c:c4:b7:c2:b5:14:ef:b4:11:ff:0e:15:b5:f5:f5:db:c6: + bd:eb:5a:a7:f0:56:22:a9:3c:65:54:c6:15:a8:bd:86:9e:cd: + 83:96:68:7a:71:81:89:e1:0b:e1:ea:11:1b:68:08:cc:69:9e: + ec:9e:41:9e:44:32:26:7a:e2:87:0a:71:3d:eb:e4:5a:a4:d2: + db:c5:cd:c6:de:60:7f:b9:f3:4f:44:92:ef:2a:b7:18:3e:a7: + 19:d9:0b:7d:b1:37:41:42:b0:ba:60:1d:f2:fe:09:11:b0:f0: + 87:7b:a7:9d +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +QuoVadis Root CA 1 G3 +# Fingerprint (SHA1): 1B:8E:EA:57:96:29:1A:C9:39:EA:B8:0A:81:1A:73:73:C0:93:79:67 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=A4:BC:5B:3F:FE:37:9A:FA:64:F0:E2:FA:05:3D:0B:AB +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 78:58:5f:2e:ad:2c:19:4b:e3:37:07:35:34:13:28:b5:96:d4:65:93 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 1 G3 + Validity + Not Before: Jan 12 17:27:44 2012 GMT + Not After : Jan 12 17:27:44 2042 GMT + Subject: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 1 G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:a0:be:50:10:8e:e9:f2:6c:40:b4:04:9c:85:b9: + 31:ca:dc:2d:e4:11:a9:04:3c:1b:55:c1:e7:58:30: + 1d:24:b4:c3:ef:85:de:8c:2c:e1:c1:3d:df:82:e6: + 4f:ad:47:87:6c:ec:5b:49:c1:4a:d5:bb:8f:ec:87: + ac:7f:82:9a:86:ec:3d:03:99:52:01:d2:35:9e:ac: + da:f0:53:c9:66:3c:d4:ac:02:01:da:24:d3:3b:a8: + 02:46:af:a4:1c:e3:f8:73:58:76:b7:f6:0e:90:0d: + b5:f0:cf:cc:fa:f9:c6:4c:e5:c3:86:30:0a:8d:17: + 7e:35:eb:c5:df:bb:0e:9c:c0:8d:87:e3:88:38:85: + 67:fa:3e:c7:ab:e0:13:9c:05:18:98:cf:93:f5:b1: + 92:b4:fc:23:d3:cf:d5:c4:27:49:e0:9e:3c:9b:08: + a3:8b:5d:2a:21:e0:fc:39:aa:53:da:7d:7e:cf:1a: + 09:53:bc:5d:05:04:cf:a1:4a:8f:8b:76:82:0d:a1: + f8:d2:c7:14:77:5b:90:36:07:81:9b:3e:06:fa:52: + 5e:63:c5:a6:00:fe:a5:e9:52:1b:52:b5:92:39:72: + 03:09:62:bd:b0:60:16:6e:a6:dd:25:c2:03:66:dd: + f3:04:d1:40:e2:4e:8b:86:f4:6f:e5:83:a0:27:84: + 5e:04:c1:f5:90:bd:30:3d:c4:ef:a8:69:bc:38:9b: + a4:a4:96:d1:62:da:69:c0:01:96:ae:cb:c4:51:34: + ea:0c:aa:ff:21:8e:59:8f:4a:5c:e4:61:9a:a7:d2: + e9:2a:78:8d:51:3d:3a:15:ee:a2:59:8e:a9:5c:de: + c5:f9:90:22:e5:88:45:71:dd:91:99:6c:7a:9f:3d: + 3d:98:7c:5e:f6:be:16:68:a0:5e:ae:0b:23:fc:5a: + 0f:aa:22:76:2d:c9:a1:10:1d:e4:d3:44:23:90:88: + 9f:c6:2a:e6:d7:f5:9a:b3:58:1e:2f:30:89:08:1b: + 54:a2:b5:98:23:ec:08:77:1c:95:5d:61:d1:cb:89: + 9c:5f:a2:4a:91:9a:ef:21:aa:49:16:08:a8:bd:61: + 28:31:c9:74:ad:85:f6:d9:c5:b1:8b:d1:e5:10:32: + 4d:5f:8b:20:3a:3c:49:1f:33:85:59:0d:db:cb:09: + 75:43:69:73:fb:6b:71:7d:f0:df:c4:4c:7d:c6:a3: + 2e:c8:95:79:cb:73:a2:8e:4e:4d:24:fb:5e:e4:04: + be:72:1b:a6:27:2d:49:5a:99:7a:d7:5c:09:20:b7: + 7f:94:b9:4f:f1:0d:1c:5e:88:42:1b:11:b7:e7:91: + db:9e:6c:f4:6a:df:8c:06:98:03:ad:cc:28:ef:a5: + 47:f3:53 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + A3:97:D6:F3:5E:A2:10:E1:AB:45:9F:3C:17:64:3C:EE:01:70:9C:CC + Signature Algorithm: sha256WithRSAEncryption + 18:fa:5b:75:fc:3e:7a:c7:5f:77:c7:ca:df:cf:5f:c3:12:c4: + 40:5d:d4:32:aa:b8:6a:d7:d5:15:15:46:98:23:a5:e6:90:5b: + 18:99:4c:e3:ad:42:a3:82:31:36:88:cd:e9:fb:c4:04:96:48: + 8b:01:c7:8d:01:cf:5b:33:06:96:46:66:74:1d:4f:ed:c1:b6: + b9:b4:0d:61:cc:63:7e:d7:2e:77:8c:96:1c:2a:23:68:6b:85: + 57:76:70:33:13:fe:e1:4f:a6:23:77:18:fa:1a:8c:e8:bd:65: + c9:cf:3f:f4:c9:17:dc:eb:c7:bc:c0:04:2e:2d:46:2f:69:66: + c3:1b:8f:fe:ec:3e:d3:ca:94:bf:76:0a:25:0d:a9:7b:02:1c: + a9:d0:3b:5f:0b:c0:81:3a:3d:64:e1:bf:a7:2d:4e:bd:4d:c4: + d8:29:c6:22:18:d0:c5:ac:72:02:82:3f:aa:3a:a2:3a:22:97: + 31:dd:08:63:c3:75:14:b9:60:28:2d:5b:68:e0:16:a9:66:82: + 23:51:f5:eb:53:d8:31:9b:7b:e9:b7:9d:4b:eb:88:16:cf:f9: + 5d:38:8a:49:30:8f:ed:f1:eb:19:f4:77:1a:31:18:4d:67:54: + 6c:2f:6f:65:f9:db:3d:ec:21:ec:5e:f4:f4:8b:ca:60:65:54: + d1:71:64:f4:f9:a6:a3:81:33:36:33:71:f0:a4:78:5f:4e:ad: + 83:21:de:34:49:8d:e8:59:ac:9d:f2:76:5a:36:f2:13:f4:af: + e0:09:c7:61:2a:6c:f7:e0:9d:ae:bb:86:4a:28:6f:2e:ee:b4: + 79:cd:90:33:c3:b3:76:fa:f5:f0:6c:9d:01:90:fa:9e:90:f6: + 9c:72:cf:47:da:c3:1f:e4:35:20:53:f2:54:d1:df:61:83:a6: + 02:e2:25:38:de:85:32:2d:5e:73:90:52:5d:42:c4:ce:3d:4b: + e1:f9:19:84:1d:d5:a2:50:cc:41:fb:41:14:c3:bd:d6:c9:5a: + a3:63:66:02:80:bd:05:3a:3b:47:9c:ec:00:26:4c:f5:88:51: + bf:a8:23:7f:18:07:b0:0b:ed:8b:26:a1:64:d3:61:4a:eb:5c: + 9f:de:b3:af:67:03:b3:1f:dd:6d:5d:69:68:69:ab:5e:3a:ec: + 7c:69:bc:c7:3b:85:4e:9e:15:b9:b4:15:4f:c3:95:7a:58:d7: + c9:6c:e9:6c:b9:f3:29:63:5e:b4:2c:f0:2d:3d:ed:5a:65:e0: + a9:5b:40:c2:48:99:81:6d:9e:1f:06:2a:3c:12:b4:8b:0f:9b: + a2:24:f0:a6:8d:d6:7a:e0:4b:b6:64:96:63:95:84:c2:4a:cd: + 1c:2e:24:87:33:60:e5:c3 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 +MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV +wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe +rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 +68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh +4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp +UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o +abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc +3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G +KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt +hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO +Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt +zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD +ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 +cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN +qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 +YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv +b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 +8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k +NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj +ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp +q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt +nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +QuoVadis Root CA 2 G3 +# Fingerprint (SHA1): 09:3C:61:F3:8B:8B:DC:7D:55:DF:75:38:02:05:00:E1:25:F5:C8:36 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=AF:0C:86:6E:BF:40:2D:7F:0B:3E:12:50:BA:12:3D:06 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 44:57:34:24:5b:81:89:9b:35:f2:ce:b8:2b:3b:5b:a7:26:f0:75:28 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 2 G3 + Validity + Not Before: Jan 12 18:59:32 2012 GMT + Not After : Jan 12 18:59:32 2042 GMT + Subject: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 2 G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:a1:ae:25:b2:01:18:dc:57:88:3f:46:eb:f9:af: + e2:eb:23:71:e2:9a:d1:61:66:21:5f:aa:af:27:51: + e5:6e:1b:16:d4:2d:7d:50:b0:53:77:bd:78:3a:60: + e2:64:02:9b:7c:86:9b:d6:1a:8e:ad:ff:1f:15:7f: + d5:95:1e:12:cb:e6:14:84:04:c1:df:36:b3:16:9f: + 8a:e3:c9:db:98:34:ce:d8:33:17:28:46:fc:a7:c9: + f0:d2:b4:d5:4d:09:72:49:f9:f2:87:e3:a9:da:7d: + a1:7d:6b:b2:3a:25:a9:6d:52:44:ac:f8:be:6e:fb: + dc:a6:73:91:90:61:a6:03:14:20:f2:e7:87:a3:88: + ad:ad:a0:8c:ff:a6:0b:25:52:25:e7:16:01:d5:cb: + b8:35:81:0c:a3:3b:f0:e1:e1:fc:5a:5d:ce:80:71: + 6d:f8:49:ab:3e:3b:ba:b8:d7:80:01:fb:a5:eb:5b: + b3:c5:5e:60:2a:31:a0:af:37:e8:20:3a:9f:a8:32: + 2c:0c:cc:09:1d:d3:9e:8e:5d:bc:4c:98:ee:c5:1a: + 68:7b:ec:53:a6:e9:14:35:a3:df:cd:80:9f:0c:48: + fb:1c:f4:f1:bf:4a:b8:fa:d5:8c:71:4a:c7:1f:ad: + fe:41:9a:b3:83:5d:f2:84:56:ef:a5:57:43:ce:29: + ad:8c:ab:55:bf:c4:fb:5b:01:dd:23:21:a1:58:00: + 8e:c3:d0:6a:13:ed:13:e3:12:2b:80:dc:67:e6:95: + b2:cd:1e:22:6e:2a:f8:41:d4:f2:ca:14:07:8d:8a: + 55:12:c6:69:f5:b8:86:68:2f:53:5e:b0:d2:aa:21: + c1:98:e6:30:e3:67:55:c7:9b:6e:ac:19:a8:55:a6: + 45:06:d0:23:3a:db:eb:65:5d:2a:11:11:f0:3b:4f: + ca:6d:f4:34:c4:71:e4:ff:00:5a:f6:5c:ae:23:60: + 85:73:f1:e4:10:b1:25:ae:d5:92:bb:13:c1:0c:e0: + 39:da:b4:39:57:b5:ab:35:aa:72:21:3b:83:35:e7: + 31:df:7a:21:6e:b8:32:08:7d:1d:32:91:15:4a:62: + 72:cf:e3:77:a1:bc:d5:11:1b:76:01:67:08:e0:41: + 0b:c3:eb:15:6e:f8:a4:19:d9:a2:ab:af:e2:27:52: + 56:2b:02:8a:2c:14:24:f9:bf:42:02:bf:26:c8:c6: + 8f:e0:6e:38:7d:53:2d:e5:ed:98:b3:95:63:68:7f: + f9:35:f4:df:88:c5:60:35:92:c0:7c:69:1c:61:95: + 16:d0:eb:de:0b:af:3e:04:10:45:65:58:50:38:af: + 48:f2:59:b6:16:f2:3c:0d:90:02:c6:70:2e:01:ad: + 3c:15:d7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + ED:E7:6F:76:5A:BF:60:EC:49:5B:C6:A5:77:BB:72:16:71:9B:C4:3D + Signature Algorithm: sha256WithRSAEncryption + 91:df:80:3f:43:09:7e:71:c2:f7:eb:b3:88:8f:e1:51:b2:bc: + 3d:75:f9:28:5d:c8:bc:99:9b:7b:5d:aa:e5:ca:e1:0a:f7:e8: + b2:d3:9f:dd:67:31:7e:ba:01:aa:c7:6a:41:3b:90:d4:08:5c: + b2:60:6a:90:f0:c8:ce:03:62:f9:8b:ed:fb:6e:2a:dc:06:4d: + 3c:29:0f:89:16:8a:58:4c:48:0f:e8:84:61:ea:3c:72:a6:77: + e4:42:ae:88:a3:43:58:79:7e:ae:ca:a5:53:0d:a9:3d:70:bd: + 20:19:61:a4:6c:38:fc:43:32:e1:c1:47:ff:f8:ec:f1:11:22: + 32:96:9c:c2:f6:5b:69:96:7b:20:0c:43:41:9a:5b:f6:59:19: + 88:de:55:88:37:51:0b:78:5c:0a:1e:a3:42:fd:c7:9d:88:0f: + c0:f2:78:02:24:54:93:af:89:87:88:c9:4a:80:1d:ea:d0:6e: + 3e:61:2e:36:bb:35:0e:27:96:fd:66:34:3b:61:72:73:f1:16: + 5c:47:06:54:49:00:7a:58:12:b0:0a:ef:85:fd:b1:b8:33:75: + 6a:93:1c:12:e6:60:5e:6f:1d:7f:c9:1f:23:cb:84:61:9f:1e: + 82:44:f9:5f:ad:62:55:24:9a:52:98:ed:51:e7:a1:7e:97:3a: + e6:2f:1f:11:da:53:80:2c:85:9e:ab:35:10:db:22:5f:6a:c5: + 5e:97:53:f2:32:02:09:30:a3:58:f0:0d:01:d5:72:c6:b1:7c: + 69:7b:c3:f5:36:45:cc:61:6e:5e:4c:94:c5:5e:ae:e8:0e:5e: + 8b:bf:f7:cd:e0:ed:a1:0e:1b:33:ee:54:18:fe:0f:be:ef:7e: + 84:6b:43:e3:70:98:db:5d:75:b2:0d:59:07:85:15:23:39:d6: + f1:df:a9:26:0f:d6:48:c7:b3:a6:22:f5:33:37:5a:95:47:9f: + 7b:ba:18:15:6f:ff:d6:14:64:83:49:d2:0a:67:21:db:0f:35: + 63:60:28:22:e3:b1:95:83:cd:85:a6:dd:2f:0f:e7:67:52:6e: + bb:2f:85:7c:f5:4a:73:e7:c5:3e:c0:bd:21:12:05:3f:fc:b7: + 03:49:02:5b:c8:25:e6:e2:54:38:f5:79:87:8c:1d:53:b2:4e: + 85:7b:06:38:c7:2c:f8:f8:b0:72:8d:25:e5:77:52:f4:03:1c: + 48:a6:50:5f:88:20:30:6e:f2:82:43:ab:3d:97:84:e7:53:fb: + 21:c1:4f:0f:22:9a:86:b8:59:2a:f6:47:3d:19:88:2d:e8:85: + e1:9e:ec:85:08:6a:b1:6c:34:c9:1d:ec:48:2b:3b:78:ed:66: + c4:8e:79:69:83:de:7f:8c +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 +MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf +qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW +n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym +c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ +O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 +o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j +IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq +IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz +8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh +vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l +7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG +cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD +ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC +roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga +W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n +lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE ++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV +csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd +dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg +KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM +HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 +WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +QuoVadis Root CA 3 G3 +# Fingerprint (SHA1): 48:12:BD:92:3C:A8:C4:39:06:E7:30:6D:27:96:E6:A4:CF:22:2E:7D +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=DF:7D:B9:AD:54:6F:68:A1:DF:89:57:03:97:43:B0:D7 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 2e:f5:9b:02:28:a7:db:7a:ff:d5:a3:a9:ee:bd:03:a0:cf:12:6a:1d + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 3 G3 + Validity + Not Before: Jan 12 20:26:32 2012 GMT + Not After : Jan 12 20:26:32 2042 GMT + Subject: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 3 G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:b3:cb:0e:10:67:8e:ea:14:97:a7:32:2a:0a:56: + 36:7f:68:4c:c7:b3:6f:3a:23:14:91:ff:19:7f:a5: + ca:ac:ee:b3:76:9d:7a:e9:8b:1b:ab:6b:31:db:fa: + 0b:53:4c:af:c5:a5:1a:79:3c:8a:4c:ff:ac:df:25: + de:4e:d9:82:32:0b:44:de:ca:db:8c:ac:a3:6e:16: + 83:3b:a6:64:4b:32:89:fb:16:16:38:7e:eb:43:e2: + d3:74:4a:c2:62:0a:73:0a:dd:49:b3:57:d2:b0:0a: + 85:9d:71:3c:de:a3:cb:c0:32:f3:01:39:20:43:1b: + 35:d1:53:b3:b1:ee:c5:93:69:82:3e:16:b5:28:46: + a1:de:ea:89:09:ed:43:b8:05:46:8a:86:f5:59:47: + be:1b:6f:01:21:10:b9:fd:a9:d2:28:ca:10:39:09: + ca:13:36:cf:9c:ad:ad:40:74:79:2b:02:3f:34:ff: + fa:20:69:7d:d3:ee:61:f5:ba:b3:e7:30:d0:37:23: + 86:72:61:45:29:48:59:68:6f:77:a6:2e:81:be:07: + 4d:6f:af:ce:c4:45:13:91:14:70:06:8f:1f:9f:f8: + 87:69:b1:0e:ef:c3:89:19:eb:ea:1c:61:fc:7a:6c: + 8a:dc:d6:03:0b:9e:26:ba:12:dd:d4:54:39:ab:26: + a3:33:ea:75:81:da:2d:cd:0f:4f:e4:03:d1:ef:15: + 97:1b:6b:90:c5:02:90:93:66:02:21:b1:47:de:8b: + 9a:4a:80:b9:55:8f:b5:a2:2f:c0:d6:33:67:da:7e: + c4:a7:b4:04:44:eb:47:fb:e6:58:b9:f7:0c:f0:7b: + 2b:b1:c0:70:29:c3:40:62:2d:3b:48:69:dc:23:3c: + 48:eb:7b:09:79:a9:6d:da:a8:30:98:cf:80:72:03: + 88:a6:5b:46:ae:72:79:7c:08:03:21:65:ae:b7:e1: + 1c:a5:b1:2a:a2:31:de:66:04:f7:c0:74:e8:71:de: + ff:3d:59:cc:96:26:12:8b:85:95:57:1a:ab:6b:75: + 0b:44:3d:11:28:3c:7b:61:b7:e2:8f:67:4f:e5:ec: + 3c:4c:60:80:69:57:38:1e:01:5b:8d:55:e8:c7:df: + c0:cc:77:23:34:49:75:7c:f6:98:11:eb:2d:de:ed: + 41:2e:14:05:02:7f:e0:fe:20:eb:35:e7:11:ac:22: + ce:57:3d:de:c9:30:6d:10:03:85:cd:f1:ff:8c:16: + b5:c1:b2:3e:88:6c:60:7f:90:4f:95:f7:f6:2d:ad: + 01:39:07:04:fa:75:80:7d:bf:49:50:ed:ef:c9:c4: + 7c:1c:eb:80:7e:db:b6:d0:dd:13:fe:c9:d3:9c:d7: + b2:97:a9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + C6:17:D0:BC:A8:EA:02:43:F2:1B:06:99:5D:2B:90:20:B9:D7:9C:E4 + Signature Algorithm: sha256WithRSAEncryption + 34:61:d9:56:b5:12:87:55:4d:dd:a3:35:31:46:bb:a4:07:72: + bc:5f:61:62:e8:a5:fb:0b:37:b1:3c:b6:b3:fa:29:9d:7f:02: + f5:a4:c9:a8:93:b7:7a:71:28:69:8f:73:e1:52:90:da:d5:be: + 3a:e5:b7:76:6a:56:80:21:df:5d:e6:e9:3a:9e:e5:3e:f6:a2: + 69:c7:2a:0a:b0:18:47:dc:20:70:7d:52:a3:3e:59:7c:c1:ba: + c9:c8:15:40:61:ca:72:d6:70:ac:d2:b7:f0:1c:e4:86:29:f0: + ce:ef:68:63:d0:b5:20:8a:15:61:9a:7e:86:98:b4:c9:c2:76: + fb:cc:ba:30:16:cc:a3:61:c6:74:13:e5:6b:ef:a3:15:ea:03: + fe:13:8b:64:e4:d3:c1:d2:e8:84:fb:49:d1:10:4d:79:66:eb: + aa:fd:f4:8d:31:1e:70:14:ad:dc:de:67:13:4c:81:15:61:bc: + b7:d9:91:77:71:19:81:60:bb:f0:58:a5:b5:9c:0b:f7:8f:22: + 55:27:c0:4b:01:6d:3b:99:0d:d4:1d:9b:63:67:2f:d0:ee:0d: + ca:66:bc:94:4f:a6:ad:ed:fc:ee:63:ac:57:3f:65:25:cf:b2: + 86:8f:d0:08:ff:b8:76:14:6e:de:e5:27:ec:ab:78:b5:53:b9: + b6:3f:e8:20:f9:d2:a8:be:61:46:ca:87:8c:84:f3:f9:f1:a0: + 68:9b:22:1e:81:26:9b:10:04:91:71:c0:06:1f:dc:a0:d3:b9: + 56:a7:e3:98:2d:7f:83:9d:df:8c:2b:9c:32:8e:32:94:f0:01: + 3c:22:2a:9f:43:c2:2e:c3:98:39:07:38:7b:fc:5e:00:42:1f: + f3:32:26:79:83:84:f6:e5:f0:c1:51:12:c0:0b:1e:04:23:0c: + 54:a5:4c:2f:49:c5:4a:d1:b6:6e:60:0d:6b:fc:6b:8b:85:24: + 64:b7:89:0e:ab:25:47:5b:3c:cf:7e:49:bd:c7:e9:0a:c6:da: + f7:7e:0e:17:08:d3:48:97:d0:71:92:f0:0f:39:3e:34:6a:1c: + 7d:d8:f2:22:ae:bb:69:f4:33:b4:a6:48:55:d1:0f:0e:26:e8: + ec:b6:0b:2d:a7:85:35:cd:fd:59:c8:9f:d1:cd:3e:5a:29:34: + b9:3d:84:ce:b1:65:d4:59:91:91:56:75:21:c1:77:9e:f9:7a: + e1:60:9d:d3:ad:04:18:f4:7c:eb:5e:93:8f:53:4a:22:29:f8: + 48:2b:3e:4d:86:ac:5b:7f:cb:06:99:59:60:d8:58:65:95:8d: + 44:d1:f7:7f:7e:27:7f:7d:ae:80:f5:07:4c:b6:3e:9c:71:54: + 99:04:4b:fd:58:f9:98:f4 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 +MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR +/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu +FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR +U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c +ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR +FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k +A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw +eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl +sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp +VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q +A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ +ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD +ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI +FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv +oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg +u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP +0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf +3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl +8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ +DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN +PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ +ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +DigiCert Assured ID Root G2 +# Fingerprint (SHA1): A1:4B:48:D9:43:EE:0A:0E:40:90:4F:3C:E0:A4:C0:91:93:51:5D:3F +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=92:38:B9:F8:63:24:82:65:2C:57:33:E6:FE:81:8F:9D +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0b:93:1c:3a:d6:39:67:ea:67:23:bf:c3:af:9a:f4:4b + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root G2 + Validity + Not Before: Aug 1 12:00:00 2013 GMT + Not After : Jan 15 12:00:00 2038 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root G2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d9:e7:28:2f:52:3f:36:72:49:88:93:34:f3:f8: + 6a:1e:31:54:80:9f:ad:54:41:b5:47:df:96:a8:d4: + af:80:2d:b9:0a:cf:75:fd:89:a5:7d:24:fa:e3:22: + 0c:2b:bc:95:17:0b:33:bf:19:4d:41:06:90:00:bd: + 0c:4d:10:fe:07:b5:e7:1c:6e:22:55:31:65:97:bd: + d3:17:d2:1e:62:f3:db:ea:6c:50:8c:3f:84:0c:96: + cf:b7:cb:03:e0:ca:6d:a1:14:4c:1b:89:dd:ed:00: + b0:52:7c:af:91:6c:b1:38:13:d1:e9:12:08:c0:00: + b0:1c:2b:11:da:77:70:36:9b:ae:ce:79:87:dc:82: + 70:e6:09:74:70:55:69:af:a3:68:9f:bf:dd:b6:79: + b3:f2:9d:70:29:55:f4:ab:ff:95:61:f3:c9:40:6f: + 1d:d1:be:93:bb:d3:88:2a:bb:9d:bf:72:5a:56:71: + 3b:3f:d4:f3:d1:0a:fe:28:ef:a3:ee:d9:99:af:03: + d3:8f:60:b7:f2:92:a1:b1:bd:89:89:1f:30:cd:c3: + a6:2e:62:33:ae:16:02:77:44:5a:e7:81:0a:3c:a7: + 44:2e:79:b8:3f:04:bc:5c:a0:87:e1:1b:af:51:8e: + cd:ec:2c:fa:f8:fe:6d:f0:3a:7c:aa:8b:e4:67:95: + 31:8d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + CE:C3:4A:B9:99:55:F2:B8:DB:60:BF:A9:7E:BD:56:B5:97:36:A7:D6 + Signature Algorithm: sha256WithRSAEncryption + ca:a5:55:8c:e3:c8:41:6e:69:27:a7:75:11:ef:3c:86:36:6f: + d2:9d:c6:78:38:1d:69:96:a2:92:69:2e:38:6c:9b:7d:04:d4: + 89:a5:b1:31:37:8a:c9:21:cc:ab:6c:cd:8b:1c:9a:d6:bf:48: + d2:32:66:c1:8a:c0:f3:2f:3a:ef:c0:e3:d4:91:86:d1:50:e3: + 03:db:73:77:6f:4a:39:53:ed:de:26:c7:b5:7d:af:2b:42:d1: + 75:62:e3:4a:2b:02:c7:50:4b:e0:69:e2:96:6c:0e:44:66:10: + 44:8f:ad:05:eb:f8:79:ac:a6:1b:e8:37:34:9d:53:c9:61:aa: + a2:52:af:4a:70:16:86:c2:3a:c8:b1:13:70:36:d8:cf:ee:f4: + 0a:34:d5:5b:4c:fd:07:9c:a2:ba:d9:01:72:5c:f3:4d:c1:dd: + 0e:b1:1c:0d:c4:63:be:ad:f4:14:fb:89:ec:a2:41:0e:4c:cc: + c8:57:40:d0:6e:03:aa:cd:0c:8e:89:99:99:6c:f0:3c:30:af: + 38:df:6f:bc:a3:be:29:20:27:ab:74:ff:13:22:78:de:97:52: + 55:1e:83:b5:54:20:03:ee:ae:c0:4f:56:de:37:cc:c3:7f:aa: + 04:27:bb:d3:77:b8:62:db:17:7c:9c:28:22:13:73:6c:cf:26: + f5:8a:29:e7 +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA +n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc +biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp +EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA +bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu +YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB +AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW +BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI +QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I +0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni +lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 +B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv +ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +DigiCert Assured ID Root G3 +# Fingerprint (SHA1): F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=7C:7F:65:31:0C:81:DF:8D:BA:3E:99:E2:5C:AD:6E:FB +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0b:a1:5a:fa:1d:df:a0:b5:49:44:af:cd:24:a0:6c:ec + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root G3 + Validity + Not Before: Aug 1 12:00:00 2013 GMT + Not After : Jan 15 12:00:00 2038 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root G3 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:19:e7:bc:ac:44:65:ed:cd:b8:3f:58:fb:8d:b1: + 57:a9:44:2d:05:15:f2:ef:0b:ff:10:74:9f:b5:62: + 52:5f:66:7e:1f:e5:dc:1b:45:79:0b:cc:c6:53:0a: + 9d:8d:5d:02:d9:a9:59:de:02:5a:f6:95:2a:0e:8d: + 38:4a:8a:49:c6:bc:c6:03:38:07:5f:55:da:7e:09: + 6e:e2:7f:5e:d0:45:20:0f:59:76:10:d6:a0:24:f0: + 2d:de:36:f2:6c:29:39 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + CB:D0:BD:A9:E1:98:05:51:A1:4D:37:A2:83:79:CE:8D:1D:2A:E4:84 + Signature Algorithm: ecdsa-with-SHA384 + 30:64:02:30:25:a4:81:45:02:6b:12:4b:75:74:4f:c8:23:e3: + 70:f2:75:72:de:7c:89:f0:cf:91:72:61:9e:5e:10:92:59:56: + b9:83:c7:10:e7:38:e9:58:26:36:7d:d5:e4:34:86:39:02:30: + 7c:36:53:f0:30:e5:62:63:3a:99:e2:b6:a3:3b:9b:34:fa:1e: + da:10:92:71:5e:91:13:a7:dd:a4:6e:92:cc:32:d6:f5:21:66: + c7:2f:ea:96:63:6a:65:45:92:95:01:b4 +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg +RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf +Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q +RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD +AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY +JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv +6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +DigiCert Global Root G2 +# Fingerprint (SHA1): DF:3C:24:F9:BF:D6:66:76:1B:26:80:73:FE:06:D1:CC:8D:4F:82:A4 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=E4:A6:8A:C8:54:AC:52:42:46:0A:FD:72:48:1B:2A:44 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 03:3a:f1:e6:a7:11:a9:a0:bb:28:64:b1:1d:09:fa:e5 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2 + Validity + Not Before: Aug 1 12:00:00 2013 GMT + Not After : Jan 15 12:00:00 2038 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:bb:37:cd:34:dc:7b:6b:c9:b2:68:90:ad:4a:75: + ff:46:ba:21:0a:08:8d:f5:19:54:c9:fb:88:db:f3: + ae:f2:3a:89:91:3c:7a:e6:ab:06:1a:6b:cf:ac:2d: + e8:5e:09:24:44:ba:62:9a:7e:d6:a3:a8:7e:e0:54: + 75:20:05:ac:50:b7:9c:63:1a:6c:30:dc:da:1f:19: + b1:d7:1e:de:fd:d7:e0:cb:94:83:37:ae:ec:1f:43: + 4e:dd:7b:2c:d2:bd:2e:a5:2f:e4:a9:b8:ad:3a:d4: + 99:a4:b6:25:e9:9b:6b:00:60:92:60:ff:4f:21:49: + 18:f7:67:90:ab:61:06:9c:8f:f2:ba:e9:b4:e9:92: + 32:6b:b5:f3:57:e8:5d:1b:cd:8c:1d:ab:95:04:95: + 49:f3:35:2d:96:e3:49:6d:dd:77:e3:fb:49:4b:b4: + ac:55:07:a9:8f:95:b3:b4:23:bb:4c:6d:45:f0:f6: + a9:b2:95:30:b4:fd:4c:55:8c:27:4a:57:14:7c:82: + 9d:cd:73:92:d3:16:4a:06:0c:8c:50:d1:8f:1e:09: + be:17:a1:e6:21:ca:fd:83:e5:10:bc:83:a5:0a:c4: + 67:28:f6:73:14:14:3d:46:76:c3:87:14:89:21:34: + 4d:af:0f:45:0c:a6:49:a1:ba:bb:9c:c5:b1:33:83: + 29:85 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 4E:22:54:20:18:95:E6:E3:6E:E6:0F:FA:FA:B9:12:ED:06:17:8F:39 + Signature Algorithm: sha256WithRSAEncryption + 60:67:28:94:6f:0e:48:63:eb:31:dd:ea:67:18:d5:89:7d:3c: + c5:8b:4a:7f:e9:be:db:2b:17:df:b0:5f:73:77:2a:32:13:39: + 81:67:42:84:23:f2:45:67:35:ec:88:bf:f8:8f:b0:61:0c:34: + a4:ae:20:4c:84:c6:db:f8:35:e1:76:d9:df:a6:42:bb:c7:44: + 08:86:7f:36:74:24:5a:da:6c:0d:14:59:35:bd:f2:49:dd:b6: + 1f:c9:b3:0d:47:2a:3d:99:2f:bb:5c:bb:b5:d4:20:e1:99:5f: + 53:46:15:db:68:9b:f0:f3:30:d5:3e:31:e2:8d:84:9e:e3:8a: + da:da:96:3e:35:13:a5:5f:f0:f9:70:50:70:47:41:11:57:19: + 4e:c0:8f:ae:06:c4:95:13:17:2f:1b:25:9f:75:f2:b1:8e:99: + a1:6f:13:b1:41:71:fe:88:2a:c8:4f:10:20:55:d7:f3:14:45: + e5:e0:44:f4:ea:87:95:32:93:0e:fe:53:46:fa:2c:9d:ff:8b: + 22:b9:4b:d9:09:45:a4:de:a4:b8:9a:58:dd:1b:7d:52:9f:8e: + 59:43:88:81:a4:9e:26:d5:6f:ad:dd:0d:c6:37:7d:ed:03:92: + 1b:e5:77:5f:76:ee:3c:8d:c4:5d:56:5b:a2:d9:66:6e:b3:35: + 37:e5:32:b6 +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH +MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI +2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx +1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ +q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz +tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ +vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV +5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY +1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 +NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG +Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 +8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe +pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +DigiCert Global Root G3 +# Fingerprint (SHA1): 7E:04:DE:89:6A:3E:66:6D:00:E6:87:D3:3F:FA:D9:3B:E8:3D:34:9E +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=F5:5D:A4:50:A5:FB:28:7E:1E:0F:0D:CC:96:57:56:CA +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 05:55:56:bc:f2:5e:a4:35:35:c3:a4:0f:d5:ab:45:72 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G3 + Validity + Not Before: Aug 1 12:00:00 2013 GMT + Not After : Jan 15 12:00:00 2038 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G3 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:dd:a7:d9:bb:8a:b8:0b:fb:0b:7f:21:d2:f0:be: + be:73:f3:33:5d:1a:bc:34:ea:de:c6:9b:bc:d0:95: + f6:f0:cc:d0:0b:ba:61:5b:51:46:7e:9e:2d:9f:ee: + 8e:63:0c:17:ec:07:70:f5:cf:84:2e:40:83:9c:e8: + 3f:41:6d:3b:ad:d3:a4:14:59:36:78:9d:03:43:ee: + 10:13:6c:72:de:ae:88:a7:a1:6b:b5:43:ce:67:dc: + 23:ff:03:1c:a3:e2:3e + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + B3:DB:48:A4:F9:A1:C5:D8:AE:36:41:CC:11:63:69:62:29:BC:4B:C6 + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:31:00:ad:bc:f2:6c:3f:12:4a:d1:2d:39:c3:0a:09: + 97:73:f4:88:36:8c:88:27:bb:e6:88:8d:50:85:a7:63:f9:9e: + 32:de:66:93:0f:f1:cc:b1:09:8f:dd:6c:ab:fa:6b:7f:a0:02: + 30:39:66:5b:c2:64:8d:b8:9e:50:dc:a8:d5:49:a2:ed:c7:dc: + d1:49:7f:17:01:b8:c8:86:8f:4e:8c:88:2b:a8:9a:a9:8a:c5: + d1:00:bd:f8:54:e2:9a:e5:5b:7c:b3:27:17 +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe +Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw +EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x +IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG +fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO +Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd +BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx +AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ +oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 +sycX +-----END CERTIFICATE----- + +DigiCert Trusted Root G4 +# Fingerprint (SHA1): DD:FB:16:CD:49:31:C9:73:A2:03:7D:3F:C8:3A:4D:7D:77:5D:05:E4 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=78:F2:FC:AA:60:1F:2F:B4:EB:C9:37:BA:53:2E:75:49 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 05:9b:1b:57:9e:8e:21:32:e2:39:07:bd:a7:77:75:5c + Signature Algorithm: sha384WithRSAEncryption + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Trusted Root G4 + Validity + Not Before: Aug 1 12:00:00 2013 GMT + Not After : Jan 15 12:00:00 2038 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Trusted Root G4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:bf:e6:90:73:68:de:bb:e4:5d:4a:3c:30:22:30: + 69:33:ec:c2:a7:25:2e:c9:21:3d:f2:8a:d8:59:c2: + e1:29:a7:3d:58:ab:76:9a:cd:ae:7b:1b:84:0d:c4: + 30:1f:f3:1b:a4:38:16:eb:56:c6:97:6d:1d:ab:b2: + 79:f2:ca:11:d2:e4:5f:d6:05:3c:52:0f:52:1f:c6: + 9e:15:a5:7e:be:9f:a9:57:16:59:55:72:af:68:93: + 70:c2:b2:ba:75:99:6a:73:32:94:d1:10:44:10:2e: + df:82:f3:07:84:e6:74:3b:6d:71:e2:2d:0c:1b:ee: + 20:d5:c9:20:1d:63:29:2d:ce:ec:5e:4e:c8:93:f8: + 21:61:9b:34:eb:05:c6:5e:ec:5b:1a:bc:eb:c9:cf: + cd:ac:34:40:5f:b1:7a:66:ee:77:c8:48:a8:66:57: + 57:9f:54:58:8e:0c:2b:b7:4f:a7:30:d9:56:ee:ca: + 7b:5d:e3:ad:c9:4f:5e:e5:35:e7:31:cb:da:93:5e: + dc:8e:8f:80:da:b6:91:98:40:90:79:c3:78:c7:b6: + b1:c4:b5:6a:18:38:03:10:8d:d8:d4:37:a4:2e:05: + 7d:88:f5:82:3e:10:91:70:ab:55:82:41:32:d7:db: + 04:73:2a:6e:91:01:7c:21:4c:d4:bc:ae:1b:03:75: + 5d:78:66:d9:3a:31:44:9a:33:40:bf:08:d7:5a:49: + a4:c2:e6:a9:a0:67:dd:a4:27:bc:a1:4f:39:b5:11: + 58:17:f7:24:5c:46:8f:64:f7:c1:69:88:76:98:76: + 3d:59:5d:42:76:87:89:97:69:7a:48:f0:e0:a2:12: + 1b:66:9a:74:ca:de:4b:1e:e7:0e:63:ae:e6:d4:ef: + 92:92:3a:9e:3d:dc:00:e4:45:25:89:b6:9a:44:19: + 2b:7e:c0:94:b4:d2:61:6d:eb:33:d9:c5:df:4b:04: + 00:cc:7d:1c:95:c3:8f:f7:21:b2:b2:11:b7:bb:7f: + f2:d5:8c:70:2c:41:60:aa:b1:63:18:44:95:1a:76: + 62:7e:f6:80:b0:fb:e8:64:a6:33:d1:89:07:e1:bd: + b7:e6:43:a4:18:b8:a6:77:01:e1:0f:94:0c:21:1d: + b2:54:29:25:89:6c:e5:0e:52:51:47:74:be:26:ac: + b6:41:75:de:7a:ac:5f:8d:3f:c9:bc:d3:41:11:12: + 5b:e5:10:50:eb:31:c5:ca:72:16:22:09:df:7c:4c: + 75:3f:63:ec:21:5f:c4:20:51:6b:6f:b1:ab:86:8b: + 4f:c2:d6:45:5f:9d:20:fc:a1:1e:c5:c0:8f:a2:b1: + 7e:0a:26:99:f5:e4:69:2f:98:1d:2d:f5:d9:a9:b2: + 1d:e5:1b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + EC:D7:E3:82:D2:71:5D:64:4C:DF:2E:67:3F:E7:BA:98:AE:1C:0F:4F + Signature Algorithm: sha384WithRSAEncryption + bb:61:d9:7d:a9:6c:be:17:c4:91:1b:c3:a1:a2:00:8d:e3:64: + 68:0f:56:cf:77:ae:70:f9:fd:9a:4a:99:b9:c9:78:5c:0c:0c: + 5f:e4:e6:14:29:56:0b:36:49:5d:44:63:e0:ad:9c:96:18:66: + 1b:23:0d:3d:79:e9:6d:6b:d6:54:f8:d2:3c:c1:43:40:ae:1d: + 50:f5:52:fc:90:3b:bb:98:99:69:6b:c7:c1:a7:a8:68:a4:27: + dc:9d:f9:27:ae:30:85:b9:f6:67:4d:3a:3e:8f:59:39:22:53: + 44:eb:c8:5d:03:ca:ed:50:7a:7d:62:21:0a:80:c8:73:66:d1: + a0:05:60:5f:e8:a5:b4:a7:af:a8:f7:6d:35:9c:7c:5a:8a:d6: + a2:38:99:f3:78:8b:f4:4d:d2:20:0b:de:04:ee:8c:9b:47:81: + 72:0d:c0:14:32:ef:30:59:2e:ae:e0:71:f2:56:e4:6a:97:6f: + 92:50:6d:96:8d:68:7a:9a:b2:36:14:7a:06:f2:24:b9:09:11: + 50:d7:08:b1:b8:89:7a:84:23:61:42:29:e5:a3:cd:a2:20:41: + d7:d1:9c:64:d9:ea:26:a1:8b:14:d7:4c:19:b2:50:41:71:3d: + 3f:4d:70:23:86:0c:4a:dc:81:d2:cc:32:94:84:0d:08:09:97: + 1c:4f:c0:ee:6b:20:74:30:d2:e0:39:34:10:85:21:15:01:08: + e8:55:32:de:71:49:d9:28:17:50:4d:e6:be:4d:d1:75:ac:d0: + ca:fb:41:b8:43:a5:aa:d3:c3:05:44:4f:2c:36:9b:e2:fa:e2: + 45:b8:23:53:6c:06:6f:67:55:7f:46:b5:4c:3f:6e:28:5a:79: + 26:d2:a4:a8:62:97:d2:1e:e2:ed:4a:8b:bc:1b:fd:47:4a:0d: + df:67:66:7e:b2:5b:41:d0:3b:e4:f4:3b:f4:04:63:e9:ef:c2: + 54:00:51:a0:8a:2a:c9:ce:78:cc:d5:ea:87:04:18:b3:ce:af: + 49:88:af:f3:92:99:b6:b3:e6:61:0f:d2:85:00:e7:50:1a:e4: + 1b:95:9d:19:a1:b9:9c:b1:9b:b1:00:1e:ef:d0:0f:4f:42:6c: + c9:0a:bc:ee:43:fa:3a:71:a5:c8:4d:26:a5:35:fd:89:5d:bc: + 85:62:1d:32:d2:a0:2b:54:ed:9a:57:c1:db:fa:10:cf:19:b7: + 8b:4a:1b:8f:01:b6:27:95:53:e8:b6:89:6d:5b:bc:68:d4:23: + e8:8b:51:a2:56:f9:f0:a6:80:a0:d6:1e:b3:bc:0f:0f:53:75: + 29:aa:ea:13:77:e4:de:8c:81:21:ad:07:10:47:11:ad:87:3d: + 07:d1:75:bc:cf:f3:66:7e +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg +RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y +ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If +xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV +ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO +DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ +jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ +CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi +EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM +fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY +uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK +chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t +9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 +SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd ++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc +fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa +sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N +cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N +0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie +4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI +r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 +/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm +gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ +-----END CERTIFICATE----- + +COMODO RSA Certification Authority +# Fingerprint (SHA1): AF:E5:D2:44:A8:D1:19:42:30:FF:47:9F:E2:F8:97:BB:CD:7A:8C:B4 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=1B:31:B0:71:40:36:CC:14:36:91:AD:C4:3E:FD:EC:18 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 4c:aa:f9:ca:db:63:6f:e0:1f:f7:4e:d8:5b:03:86:9d + Signature Algorithm: sha384WithRSAEncryption + Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Certification Authority + Validity + Not Before: Jan 19 00:00:00 2010 GMT + Not After : Jan 18 23:59:59 2038 GMT + Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:91:e8:54:92:d2:0a:56:b1:ac:0d:24:dd:c5:cf: + 44:67:74:99:2b:37:a3:7d:23:70:00:71:bc:53:df: + c4:fa:2a:12:8f:4b:7f:10:56:bd:9f:70:72:b7:61: + 7f:c9:4b:0f:17:a7:3d:e3:b0:04:61:ee:ff:11:97: + c7:f4:86:3e:0a:fa:3e:5c:f9:93:e6:34:7a:d9:14: + 6b:e7:9c:b3:85:a0:82:7a:76:af:71:90:d7:ec:fd: + 0d:fa:9c:6c:fa:df:b0:82:f4:14:7e:f9:be:c4:a6: + 2f:4f:7f:99:7f:b5:fc:67:43:72:bd:0c:00:d6:89: + eb:6b:2c:d3:ed:8f:98:1c:14:ab:7e:e5:e3:6e:fc: + d8:a8:e4:92:24:da:43:6b:62:b8:55:fd:ea:c1:bc: + 6c:b6:8b:f3:0e:8d:9a:e4:9b:6c:69:99:f8:78:48: + 30:45:d5:ad:e1:0d:3c:45:60:fc:32:96:51:27:bc: + 67:c3:ca:2e:b6:6b:ea:46:c7:c7:20:a0:b1:1f:65: + de:48:08:ba:a4:4e:a9:f2:83:46:37:84:eb:e8:cc: + 81:48:43:67:4e:72:2a:9b:5c:bd:4c:1b:28:8a:5c: + 22:7b:b4:ab:98:d9:ee:e0:51:83:c3:09:46:4e:6d: + 3e:99:fa:95:17:da:7c:33:57:41:3c:8d:51:ed:0b: + b6:5c:af:2c:63:1a:df:57:c8:3f:bc:e9:5d:c4:9b: + af:45:99:e2:a3:5a:24:b4:ba:a9:56:3d:cf:6f:aa: + ff:49:58:be:f0:a8:ff:f4:b8:ad:e9:37:fb:ba:b8: + f4:0b:3a:f9:e8:43:42:1e:89:d8:84:cb:13:f1:d9: + bb:e1:89:60:b8:8c:28:56:ac:14:1d:9c:0a:e7:71: + eb:cf:0e:dd:3d:a9:96:a1:48:bd:3c:f7:af:b5:0d: + 22:4c:c0:11:81:ec:56:3b:f6:d3:a2:e2:5b:b7:b2: + 04:22:52:95:80:93:69:e8:8e:4c:65:f1:91:03:2d: + 70:74:02:ea:8b:67:15:29:69:52:02:bb:d7:df:50: + 6a:55:46:bf:a0:a3:28:61:7f:70:d0:c3:a2:aa:2c: + 21:aa:47:ce:28:9c:06:45:76:bf:82:18:27:b4:d5: + ae:b4:cb:50:e6:6b:f4:4c:86:71:30:e9:a6:df:16: + 86:e0:d8:ff:40:dd:fb:d0:42:88:7f:a3:33:3a:2e: + 5c:1e:41:11:81:63:ce:18:71:6b:2b:ec:a6:8a:b7: + 31:5c:3a:6a:47:e0:c3:79:59:d6:20:1a:af:f2:6a: + 98:aa:72:bc:57:4a:d2:4b:9d:bb:10:fc:b0:4c:41: + e5:ed:1d:3d:5e:28:9d:9c:cc:bf:b3:51:da:a7:47: + e5:84:53 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + BB:AF:7E:02:3D:FA:A6:F1:3C:84:8E:AD:EE:38:98:EC:D9:32:32:D4 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha384WithRSAEncryption + 0a:f1:d5:46:84:b7:ae:51:bb:6c:b2:4d:41:14:00:93:4c:9c: + cb:e5:c0:54:cf:a0:25:8e:02:f9:fd:b0:a2:0d:f5:20:98:3c: + 13:2d:ac:56:a2:b0:d6:7e:11:92:e9:2e:ba:9e:2e:9a:72:b1: + bd:19:44:6c:61:35:a2:9a:b4:16:12:69:5a:8c:e1:d7:3e:a4: + 1a:e8:2f:03:f4:ae:61:1d:10:1b:2a:a4:8b:7a:c5:fe:05:a6: + e1:c0:d6:c8:fe:9e:ae:8f:2b:ba:3d:99:f8:d8:73:09:58:46: + 6e:a6:9c:f4:d7:27:d3:95:da:37:83:72:1c:d3:73:e0:a2:47: + 99:03:38:5d:d5:49:79:00:29:1c:c7:ec:9b:20:1c:07:24:69: + 57:78:b2:39:fc:3a:84:a0:b5:9c:7c:8d:bf:2e:93:62:27:b7: + 39:da:17:18:ae:bd:3c:09:68:ff:84:9b:3c:d5:d6:0b:03:e3: + 57:9e:14:f7:d1:eb:4f:c8:bd:87:23:b7:b6:49:43:79:85:5c: + ba:eb:92:0b:a1:c6:e8:68:a8:4c:16:b1:1a:99:0a:e8:53:2c: + 92:bb:a1:09:18:75:0c:65:a8:7b:cb:23:b7:1a:c2:28:85:c3: + 1b:ff:d0:2b:62:ef:a4:7b:09:91:98:67:8c:14:01:cd:68:06: + 6a:63:21:75:03:80:88:8a:6e:81:c6:85:f2:a9:a4:2d:e7:f4: + a5:24:10:47:83:ca:cd:f4:8d:79:58:b1:06:9b:e7:1a:2a:d9: + 9d:01:d7:94:7d:ed:03:4a:ca:f0:db:e8:a9:01:3e:f5:56:99: + c9:1e:8e:49:3d:bb:e5:09:b9:e0:4f:49:92:3d:16:82:40:cc: + cc:59:c6:e6:3a:ed:12:2e:69:3c:6c:95:b1:fd:aa:1d:7b:7f: + 86:be:1e:0e:32:46:fb:fb:13:8f:75:7f:4c:8b:4b:46:63:fe: + 00:34:40:70:c1:c3:b9:a1:dd:a6:70:e2:04:b3:41:bc:e9:80: + 91:ea:64:9c:7a:e1:22:03:a9:9c:6e:6f:0e:65:4f:6c:87:87: + 5e:f3:6e:a0:f9:75:a5:9b:40:e8:53:b2:27:9d:4a:b9:c0:77: + 21:8d:ff:87:f2:de:bc:8c:ef:17:df:b7:49:0b:d1:f2:6e:30: + 0b:1a:0e:4e:76:ed:11:fc:f5:e9:56:b2:7d:bf:c7:6d:0a:93: + 8c:a5:d0:c0:b6:1d:be:3a:4e:94:a2:d7:6e:6c:0b:c2:8a:7c: + fa:20:f3:c4:e4:e5:cd:0d:a8:cb:91:92:b1:7c:85:ec:b5:14: + 69:66:0e:82:e7:cd:ce:c8:2d:a6:51:7f:21:c1:35:53:85:06: + 4a:5d:9f:ad:bb:1b:5f:74 +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR +6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X +pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC +9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV +/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf +Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z ++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w +qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah +SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC +u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf +Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq +crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl +wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM +4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV +2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna +FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ +CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK +boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke +jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL +S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb +QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl +0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB +NVOFBkpdn627G190 +-----END CERTIFICATE----- + +USERTrust RSA Certification Authority +# Fingerprint (SHA1): 2B:8F:1B:57:33:0D:BB:A2:D0:7A:6C:51:F7:0E:E9:0D:DA:B9:AD:8E +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=1B:FE:69:D1:91:B7:19:33:A3:72:A8:0F:E1:55:E5:B5 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 01:fd:6d:30:fc:a3:ca:51:a8:1b:bc:64:0e:35:03:2d + Signature Algorithm: sha384WithRSAEncryption + Issuer: C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority + Validity + Not Before: Feb 1 00:00:00 2010 GMT + Not After : Jan 18 23:59:59 2038 GMT + Subject: C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:80:12:65:17:36:0e:c3:db:08:b3:d0:ac:57:0d: + 76:ed:cd:27:d3:4c:ad:50:83:61:e2:aa:20:4d:09: + 2d:64:09:dc:ce:89:9f:cc:3d:a9:ec:f6:cf:c1:dc: + f1:d3:b1:d6:7b:37:28:11:2b:47:da:39:c6:bc:3a: + 19:b4:5f:a6:bd:7d:9d:a3:63:42:b6:76:f2:a9:3b: + 2b:91:f8:e2:6f:d0:ec:16:20:90:09:3e:e2:e8:74: + c9:18:b4:91:d4:62:64:db:7f:a3:06:f1:88:18:6a: + 90:22:3c:bc:fe:13:f0:87:14:7b:f6:e4:1f:8e:d4: + e4:51:c6:11:67:46:08:51:cb:86:14:54:3f:bc:33: + fe:7e:6c:9c:ff:16:9d:18:bd:51:8e:35:a6:a7:66: + c8:72:67:db:21:66:b1:d4:9b:78:03:c0:50:3a:e8: + cc:f0:dc:bc:9e:4c:fe:af:05:96:35:1f:57:5a:b7: + ff:ce:f9:3d:b7:2c:b6:f6:54:dd:c8:e7:12:3a:4d: + ae:4c:8a:b7:5c:9a:b4:b7:20:3d:ca:7f:22:34:ae: + 7e:3b:68:66:01:44:e7:01:4e:46:53:9b:33:60:f7: + 94:be:53:37:90:73:43:f3:32:c3:53:ef:db:aa:fe: + 74:4e:69:c7:6b:8c:60:93:de:c4:c7:0c:df:e1:32: + ae:cc:93:3b:51:78:95:67:8b:ee:3d:56:fe:0c:d0: + 69:0f:1b:0f:f3:25:26:6b:33:6d:f7:6e:47:fa:73: + 43:e5:7e:0e:a5:66:b1:29:7c:32:84:63:55:89:c4: + 0d:c1:93:54:30:19:13:ac:d3:7d:37:a7:eb:5d:3a: + 6c:35:5c:db:41:d7:12:da:a9:49:0b:df:d8:80:8a: + 09:93:62:8e:b5:66:cf:25:88:cd:84:b8:b1:3f:a4: + 39:0f:d9:02:9e:eb:12:4c:95:7c:f3:6b:05:a9:5e: + 16:83:cc:b8:67:e2:e8:13:9d:cc:5b:82:d3:4c:b3: + ed:5b:ff:de:e5:73:ac:23:3b:2d:00:bf:35:55:74: + 09:49:d8:49:58:1a:7f:92:36:e6:51:92:0e:f3:26: + 7d:1c:4d:17:bc:c9:ec:43:26:d0:bf:41:5f:40:a9: + 44:44:f4:99:e7:57:87:9e:50:1f:57:54:a8:3e:fd: + 74:63:2f:b1:50:65:09:e6:58:42:2e:43:1a:4c:b4: + f0:25:47:59:fa:04:1e:93:d4:26:46:4a:50:81:b2: + de:be:78:b7:fc:67:15:e1:c9:57:84:1e:0f:63:d6: + e9:62:ba:d6:5f:55:2e:ea:5c:c6:28:08:04:25:39: + b8:0e:2b:a9:f2:4c:97:1c:07:3f:0d:52:f5:ed:ef: + 2f:82:0f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 53:79:BF:5A:AA:2B:4A:CF:54:80:E1:D8:9B:C0:9D:F2:B2:03:66:CB + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha384WithRSAEncryption + 5c:d4:7c:0d:cf:f7:01:7d:41:99:65:0c:73:c5:52:9f:cb:f8: + cf:99:06:7f:1b:da:43:15:9f:9e:02:55:57:96:14:f1:52:3c: + 27:87:94:28:ed:1f:3a:01:37:a2:76:fc:53:50:c0:84:9b:c6: + 6b:4e:ba:8c:21:4f:a2:8e:55:62:91:f3:69:15:d8:bc:88:e3: + c4:aa:0b:fd:ef:a8:e9:4b:55:2a:06:20:6d:55:78:29:19:ee: + 5f:30:5c:4b:24:11:55:ff:24:9a:6e:5e:2a:2b:ee:0b:4d:9f: + 7f:f7:01:38:94:14:95:43:07:09:fb:60:a9:ee:1c:ab:12:8c: + a0:9a:5e:a7:98:6a:59:6d:8b:3f:08:fb:c8:d1:45:af:18:15: + 64:90:12:0f:73:28:2e:c5:e2:24:4e:fc:58:ec:f0:f4:45:fe: + 22:b3:eb:2f:8e:d2:d9:45:61:05:c1:97:6f:a8:76:72:8f:8b: + 8c:36:af:bf:0d:05:ce:71:8d:e6:a6:6f:1f:6c:a6:71:62:c5: + d8:d0:83:72:0c:f1:67:11:89:0c:9c:13:4c:72:34:df:bc:d5: + 71:df:aa:71:dd:e1:b9:6c:8c:3c:12:5d:65:da:bd:57:12:b6: + 43:6b:ff:e5:de:4d:66:11:51:cf:99:ae:ec:17:b6:e8:71:91: + 8c:de:49:fe:dd:35:71:a2:15:27:94:1c:cf:61:e3:26:bb:6f: + a3:67:25:21:5d:e6:dd:1d:0b:2e:68:1b:3b:82:af:ec:83:67: + 85:d4:98:51:74:b1:b9:99:80:89:ff:7f:78:19:5c:79:4a:60: + 2e:92:40:ae:4c:37:2a:2c:c9:c7:62:c8:0e:5d:f7:36:5b:ca: + e0:25:25:01:b4:dd:1a:07:9c:77:00:3f:d0:dc:d5:ec:3d:d4: + fa:bb:3f:cc:85:d6:6f:7f:a9:2d:df:b9:02:f7:f5:97:9a:b5: + 35:da:c3:67:b0:87:4a:a9:28:9e:23:8e:ff:5c:27:6b:e1:b0: + 4f:f3:07:ee:00:2e:d4:59:87:cb:52:41:95:ea:f4:47:d7:ee: + 64:41:55:7c:8d:59:02:95:dd:62:9d:c2:b9:ee:5a:28:74:84: + a5:9b:b7:90:c7:0c:07:df:f5:89:36:74:32:d6:28:c1:b0:b0: + 0b:e0:9c:4c:c3:1c:d6:fc:e3:69:b5:47:46:81:2f:a2:82:ab: + d3:63:44:70:c4:8d:ff:2d:33:ba:ad:8f:7b:b5:70:88:ae:3e: + 19:cf:40:28:d8:fc:c8:90:bb:5d:99:22:f5:52:e6:58:c5:1f: + 88:31:43:ee:88:1d:d7:c6:8e:3c:43:6a:1d:a7:18:de:7d:3d: + 16:f1:62:f9:ca:90:a8:fd +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB +iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl +cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV +BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw +MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV +BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B +3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY +tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ +Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 +VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT +79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 +c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT +Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l +c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee +UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE +Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF +Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO +VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 +ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs +8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR +iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze +Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ +XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ +qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB +VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB +L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG +jjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + +USERTrust ECC Certification Authority +# Fingerprint (SHA1): D1:CB:CA:5D:B2:D5:2A:7F:69:3B:67:4D:E5:F0:5A:1D:0C:95:7D:F0 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=FA:68:BC:D9:B5:7F:AD:FD:C9:1D:06:83:28:CC:24:C1 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 5c:8b:99:c5:5a:94:c5:d2:71:56:de:cd:89:80:cc:26 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust ECC Certification Authority + Validity + Not Before: Feb 1 00:00:00 2010 GMT + Not After : Jan 18 23:59:59 2038 GMT + Subject: C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust ECC Certification Authority + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:1a:ac:54:5a:a9:f9:68:23:e7:7a:d5:24:6f:53: + c6:5a:d8:4b:ab:c6:d5:b6:d1:e6:73:71:ae:dd:9c: + d6:0c:61:fd:db:a0:89:03:b8:05:14:ec:57:ce:ee: + 5d:3f:e2:21:b3:ce:f7:d4:8a:79:e0:a3:83:7e:2d: + 97:d0:61:c4:f1:99:dc:25:91:63:ab:7f:30:a3:b4: + 70:e2:c7:a1:33:9c:f3:bf:2e:5c:53:b1:5f:b3:7d: + 32:7f:8a:34:e3:79:79 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Subject Key Identifier: + 3A:E1:09:86:D4:CF:19:C2:96:76:74:49:76:DC:E0:35:C6:63:63:9A + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:30:36:67:a1:16:08:dc:e4:97:00:41:1d:4e:be:e1: + 63:01:cf:3b:aa:42:11:64:a0:9d:94:39:02:11:79:5c:7b:1d: + fa:64:b9:ee:16:42:b3:bf:8a:c2:09:c4:ec:e4:b1:4d:02:31: + 00:e9:2a:61:47:8c:52:4a:4b:4e:18:70:f6:d6:44:d6:6e:f5: + 83:ba:6d:58:bd:24:d9:56:48:ea:ef:c4:a2:46:81:88:6a:3a: + 46:d1:a9:9b:4d:c9:61:da:d1:5d:57:6a:18 +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl +eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT +JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT +Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg +VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo +I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng +o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G +A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB +zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW +RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R4 +# Fingerprint (SHA1): 69:69:56:2E:40:80:F4:24:A1:E7:19:9F:14:BA:F3:EE:58:AB:6A:BB +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=20:F0:27:68:D1:7E:A0:9D:0E:E6:2A:CA:DF:5C:89:8E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 2a:38:a4:1c:96:0a:04:de:42:b2:28:a5:0b:e8:34:98:02 + Signature Algorithm: ecdsa-with-SHA256 + Issuer: OU=GlobalSign ECC Root CA - R4, O=GlobalSign, CN=GlobalSign + Validity + Not Before: Nov 13 00:00:00 2012 GMT + Not After : Jan 19 03:14:07 2038 GMT + Subject: OU=GlobalSign ECC Root CA - R4, O=GlobalSign, CN=GlobalSign + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:b8:c6:79:d3:8f:6c:25:0e:9f:2e:39:19:1c:03: + a4:ae:9a:e5:39:07:09:16:ca:63:b1:b9:86:f8:8a: + 57:c1:57:ce:42:fa:73:a1:f7:65:42:ff:1e:c1:00: + b2:6e:73:0e:ff:c7:21:e5:18:a4:aa:d9:71:3f:a8: + d4:b9:ce:8c:1d + ASN1 OID: prime256v1 + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 54:B0:7B:AD:45:B8:E2:40:7F:FB:0A:6E:FB:BE:33:C9:3C:A3:84:D5 + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:21:00:dc:92:a1:a0:13:a6:cf:03:b0:e6:c4:21:97: + 90:fa:14:57:2d:03:ec:ee:3c:d3:6e:ca:a8:6c:76:bc:a2:de: + bb:02:20:27:a8:85:27:35:9b:56:c6:a3:f2:47:d2:b7:6e:1b: + 02:00:17:aa:67:a6:15:91:de:fa:94:ec:7b:0b:f8:9f:84 +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ +FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F +uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX +kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs +ewv4n4Q= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R5 +# Fingerprint (SHA1): 1F:24:C6:30:CD:A4:18:EF:20:69:FF:AD:4F:DD:5F:46:3A:1B:69:AA +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=9F:AD:3B:1C:02:1E:8A:BA:17:74:38:81:0C:A2:BC:08 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 60:59:49:e0:26:2e:bb:55:f9:0a:77:8a:71:f9:4a:d8:6c + Signature Algorithm: ecdsa-with-SHA384 + Issuer: OU=GlobalSign ECC Root CA - R5, O=GlobalSign, CN=GlobalSign + Validity + Not Before: Nov 13 00:00:00 2012 GMT + Not After : Jan 19 03:14:07 2038 GMT + Subject: OU=GlobalSign ECC Root CA - R5, O=GlobalSign, CN=GlobalSign + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:47:45:0e:96:fb:7d:5d:bf:e9:39:d1:21:f8:9f: + 0b:b6:d5:7b:1e:92:3a:48:59:1c:f0:62:31:2d:c0: + 7a:28:fe:1a:a7:5c:b3:b6:cc:97:e7:45:d4:58:fa: + d1:77:6d:43:a2:c0:87:65:34:0a:1f:7a:dd:eb:3c: + 33:a1:c5:9d:4d:a4:6f:41:95:38:7f:c9:1e:84:eb: + d1:9e:49:92:87:94:87:0c:3a:85:4a:66:9f:9d:59: + 93:4d:97:61:06:86:4a + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 3D:E6:29:48:9B:EA:07:CA:21:44:4A:26:DE:6E:DE:D2:83:D0:9F:59 + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:31:00:e5:69:12:c9:6e:db:c6:31:ba:09:41:e1:97: + f8:fb:fd:9a:e2:7d:12:c9:ed:7c:64:d3:cb:05:25:8b:56:d9: + a0:e7:5e:5d:4e:0b:83:9c:5b:76:29:a0:09:26:21:6a:62:02: + 30:71:d2:b5:8f:5c:ea:3b:e1:78:09:85:a8:75:92:3b:c8:5c: + fd:48:ef:0d:74:22:a8:08:e2:6e:c5:49:ce:c7:0c:bc:a7:61: + 69:f1:f7:3b:e1:2a:cb:f9:2b:f3:66:90:37 +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc +8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke +hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI +KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg +515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO +xwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA - G3 +# Fingerprint (SHA1): D8:EB:6B:41:51:92:59:E0:F3:E7:85:00:C0:3D:B6:88:97:C9:EE:FC +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=0B:46:67:07:DB:10:2F:19:8C:35:50:60:D1:0B:F4:37 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 10003001 (0x98a239) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Root CA - G3 + Validity + Not Before: Nov 14 11:28:42 2013 GMT + Not After : Nov 13 23:00:00 2028 GMT + Subject: C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Root CA - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:be:32:a2:54:0f:70:fb:2c:5c:59:eb:6c:c4:a4: + 51:e8:85:2a:b3:cc:4a:34:f2:b0:5f:f3:0e:c7:1c: + 3d:53:1e:88:08:68:d8:6f:3d:ad:c2:9e:cc:82:67: + 07:27:87:68:71:3a:9f:75:96:22:46:05:b0:ed:ad: + c7:5b:9e:2a:de:9c:fc:3a:c6:95:a7:f5:17:67:18: + e7:2f:49:08:0c:5c:cf:e6:cc:34:ed:78:fb:50:b1: + dc:6b:32:f0:a2:fe:b6:3c:e4:ec:5a:97:c7:3f:1e: + 70:08:30:a0:dc:c5:b3:6d:6f:d0:82:72:11:ab:d2: + 81:68:59:82:17:b7:78:92:60:fa:cc:de:3f:84:eb: + 8d:38:33:90:0a:72:23:fa:35:cc:26:71:31:d1:72: + 28:92:d9:5b:23:6d:66:b5:6d:07:42:eb:a6:33:ce: + 92:db:c0:f6:6c:63:78:cd:ca:4e:3d:b5:e5:52:9b: + f1:be:3b:e6:54:60:b0:66:1e:09:ab:07:fe:54:89: + 11:42:d1:f7:24:ba:60:78:1a:98:f7:c9:11:fd:16: + c1:35:1a:54:75:ef:43:d3:e5:ae:4e:ce:e7:7b:c3: + c6:4e:61:51:4b:ab:9a:45:4b:a1:1f:41:bd:48:53: + 15:71:64:0b:86:b3:e5:2e:be:ce:a4:1b:c1:29:84: + a2:b5:cb:08:23:76:43:22:24:1f:17:04:d4:6e:9c: + c6:fc:7f:2b:66:1a:ec:8a:e5:d6:cf:4d:f5:63:09: + b7:15:39:d6:7b:ac:eb:e3:7c:e9:4e:fc:75:42:c8: + ed:58:95:0c:06:42:a2:9c:f7:e4:70:b3:df:72:6f: + 5a:37:40:89:d8:85:a4:d7:f1:0b:de:43:19:d4:4a: + 58:2c:8c:8a:39:9e:bf:84:87:f1:16:3b:36:0c:e9: + d3:b4:ca:6c:19:41:52:09:a1:1d:b0:6a:bf:82:ef: + 70:51:21:32:dc:05:76:8c:cb:f7:64:e4:03:50:af: + 8c:91:67:ab:c5:f2:ee:58:d8:de:be:f7:e7:31:cf: + 6c:c9:3b:71:c1:d5:88:b5:65:bc:c0:e8:17:17:07: + 12:b5:5c:d2:ab:20:93:b4:e6:82:83:70:36:c5:cd: + a3:8d:ad:8b:ec:a3:c1:43:87:e6:43:e2:34:be:95: + 8b:35:ed:07:39:da:a8:1d:7a:9f:36:9e:12:b0:0c: + 65:12:90:15:60:d9:26:40:44:e3:56:60:a5:10:d4: + 6a:3c:fd:41:dc:0e:5a:47:b6:ef:97:61:75:4f:d9: + fe:c7:b2:1d:d4:ed:5d:49:b3:a9:6a:cb:66:84:13: + d5:5c:a0:dc:df:6e:77:06:d1:71:75:c8:57:6f:af: + 0f:77:5b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 54:AD:FA:C7:92:57:AE:CA:35:9C:2E:12:FB:E4:BA:5D:20:DC:94:57 + Signature Algorithm: sha256WithRSAEncryption + 30:99:9d:05:32:c8:5e:0e:3b:98:01:3a:8a:a4:e7:07:f7:7a: + f8:e7:9a:df:50:43:53:97:2a:3d:ca:3c:47:98:2e:e1:15:7b: + f1:92:f3:61:da:90:25:16:65:c0:9f:54:5d:0e:03:3b:5b:77: + 02:9c:84:b6:0d:98:5f:34:dd:3b:63:c2:c3:28:81:c2:9c:29: + 2e:29:e2:c8:c3:01:f2:33:ea:2a:aa:cc:09:08:f7:65:67:c6: + cd:df:d3:b6:2b:a7:bd:cc:d1:0e:70:5f:b8:23:d1:cb:91:4e: + 0a:f4:c8:7a:e5:d9:63:36:c1:d4:df:fc:22:97:f7:60:5d:ea: + 29:2f:58:b2:bd:58:bd:8d:96:4f:10:75:bf:48:7b:3d:51:87: + a1:3c:74:22:c2:fc:07:7f:80:dc:c4:ac:fe:6a:c1:70:30:b0: + e9:8e:69:e2:2c:69:81:94:09:ba:dd:fe:4d:c0:83:8c:94:58: + c0:46:20:af:9c:1f:02:f8:35:55:49:2f:46:d4:c0:f0:a0:96: + 02:0f:33:c5:71:f3:9e:23:7d:94:b7:fd:3a:d3:09:83:06:21: + fd:60:3d:ae:32:c0:d2:ee:8d:a6:f0:e7:b4:82:7c:0a:cc:70: + c9:79:80:f8:fe:4c:f7:35:84:19:8a:31:fb:0a:d9:d7:7f:9b: + f0:a2:9a:6b:c3:05:4a:ed:41:60:14:30:d1:aa:11:42:6e:d3: + 23:02:04:0b:c6:65:dd:dd:52:77:da:81:6b:b2:a8:fa:01:38: + b9:96:ea:2a:6c:67:97:89:94:9e:bc:e1:54:d5:e4:6a:78:ef: + 4a:bd:2b:9a:3d:40:7e:c6:c0:75:d2:6e:fb:68:30:ec:ec:8b: + 9d:f9:49:35:9a:1a:2c:d9:b3:95:39:d5:1e:92:f7:a6:b9:65: + 2f:e5:3d:6d:3a:48:4c:08:dc:e4:28:12:28:be:7d:35:5c:ea: + e0:16:7e:13:1b:6a:d7:3e:d7:9e:fc:2d:75:b2:c1:14:d5:23: + 03:db:5b:6f:0b:3e:78:2f:0d:de:33:8d:16:b7:48:e7:83:9a: + 81:0f:7b:c1:43:4d:55:04:17:38:4a:51:d5:59:a2:89:74:d3: + 9f:be:1e:4b:d7:c6:6d:b7:88:24:6f:60:91:a4:82:85:5b:56: + 41:bc:d0:44:ab:6a:13:be:d1:2c:58:b7:12:33:58:b2:37:63: + dc:13:f5:94:1d:3f:40:51:f5:4f:f5:3a:ed:c8:c5:eb:c2:1e: + 1d:16:95:7a:c7:7e:42:71:93:6e:4b:15:b7:30:df:aa:ed:57: + 85:48:ac:1d:6a:dd:39:69:e4:e1:79:78:be:ce:05:bf:a1:0c: + f7:80:7b:21:67:27:30:59 +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX +DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP +cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW +IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX +xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy +KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR +9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az +5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 +6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 +Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP +bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt +BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt +XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd +INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD +U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp +LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 +Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp +gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh +/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw +0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A +fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq +4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR +1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ +QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM +94B7IWcnMFk= +-----END CERTIFICATE----- + +Staat der Nederlanden EV Root CA +# Fingerprint (SHA1): 76:E2:7E:C1:4F:DB:82:C1:C0:A6:75:B5:05:BE:3D:29:B4:ED:DB:BB +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=FC:06:AF:7B:E8:1A:F1:9A:B4:E8:D2:70:1F:C0:F5:BA +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 10000013 (0x98968d) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden EV Root CA + Validity + Not Before: Dec 8 11:19:29 2010 GMT + Not After : Dec 8 11:10:28 2022 GMT + Subject: C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden EV Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:e3:c7:7e:89:f9:24:4b:3a:d2:33:83:35:2c:69: + ec:dc:09:a4:e3:51:a8:25:2b:79:b8:08:3d:e0:91: + ba:84:85:c6:85:a4:ca:e6:c9:2e:53:a4:c9:24:1e: + fd:55:66:71:5d:2c:c5:60:68:04:b7:d9:c2:52:26: + 38:88:a4:d6:3b:40:a6:c2:cd:3f:cd:98:93:b3:54: + 14:58:96:55:d5:50:fe:86:ad:a4:63:7f:5c:87:f6: + 8e:e6:27:92:67:17:92:02:03:2c:dc:d6:66:74:ed: + dd:67:ff:c1:61:8d:63:4f:0f:9b:6d:17:30:26:ef: + ab:d2:1f:10:a0:f9:c5:7f:16:69:81:03:47:ed:1e: + 68:8d:72:a1:4d:b2:26:c6:ba:6c:5f:6d:d6:af:d1: + b1:13:8e:a9:ad:f3:5e:69:75:26:18:3e:41:2b:21: + 7f:ee:8b:5d:07:06:9d:43:c4:29:0a:2b:fc:2a:3e: + 86:cb:3c:83:3a:f9:c9:0d:da:c5:99:e2:bc:78:41: + 33:76:e1:bf:2f:5d:e5:a4:98:50:0c:15:dd:e0:fa: + 9c:7f:38:68:d0:b2:a6:7a:a7:d1:31:bd:7e:8a:58: + 27:43:b3:ba:33:91:d3:a7:98:15:5c:9a:e6:d3:0f: + 75:d9:fc:41:98:97:3e:aa:25:db:8f:92:2e:b0:7b: + 0c:5f:f1:63:a9:37:f9:9b:75:69:4c:28:26:25:da: + d5:f2:12:70:45:55:e3:df:73:5e:37:f5:21:6c:90: + 8e:35:5a:c9:d3:23:eb:d3:c0:be:78:ac:42:28:58: + 66:a5:46:6d:70:02:d7:10:f9:4b:54:fc:5d:86:4a: + 87:cf:7f:ca:45:ac:11:5a:b5:20:51:8d:2f:88:47: + 97:39:c0:cf:ba:c0:42:01:40:99:48:21:0b:6b:a7: + d2:fd:96:d5:d1:be:46:9d:49:e0:0b:a6:a0:22:4e: + 38:d0:c1:3c:30:bc:70:8f:2c:75:cc:d0:c5:8c:51: + 3b:3d:94:08:64:26:61:7d:b9:c3:65:8f:14:9c:21: + d0:aa:fd:17:72:03:8f:bd:9b:8c:e6:5e:53:9e:b9: + 9d:ef:82:bb:e1:bc:e2:72:41:5b:21:94:d3:45:37: + 94:d1:df:09:39:5d:e7:23:aa:9a:1d:ca:6d:a8:0a: + 86:85:8a:82:be:42:07:d6:f2:38:82:73:da:87:5b: + e5:3c:d3:9e:3e:a7:3b:9e:f4:03:b3:f9:f1:7d:13: + 74:02:ff:bb:a1:e5:fa:00:79:1c:a6:66:41:88:5c: + 60:57:a6:2e:09:c4:ba:fd:9a:cf:a7:1f:40:c3:bb: + cc:5a:0a:55:4b:3b:38:76:51:b8:63:8b:84:94:16: + e6:56:f3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + FE:AB:00:90:98:9E:24:FC:A9:CC:1A:8A:FB:27:B8:BF:30:6E:A8:3B + Signature Algorithm: sha256WithRSAEncryption + cf:77:2c:6e:56:be:4e:b3:b6:84:00:94:ab:47:c9:0d:d2:76: + c7:86:9f:1d:07:d3:b6:b4:bb:08:78:af:69:d2:0b:49:de:33: + c5:ac:ad:c2:88:02:7d:06:b7:35:02:c1:60:c9:bf:c4:e8:94: + de:d4:d3:a9:13:25:5a:fe:6e:a2:ae:7d:05:dc:7d:f3:6c:f0: + 7e:a6:8d:ee:d9:d7:ce:58:17:e8:a9:29:ae:73:48:87:e7:9b: + ca:6e:29:a1:64:5f:19:13:f7:ae:06:10:ff:51:c6:9b:4d:55: + 25:4f:93:99:10:01:53:75:f1:13:ce:c7:a6:41:41:d2:bf:88: + a5:7f:45:fc:ac:b8:a5:b5:33:0c:82:c4:fb:07:f6:6a:e5:25: + 84:5f:06:ca:c1:86:39:11:db:58:cd:77:3b:2c:c2:4c:0f:5e: + 9a:e3:f0:ab:3e:61:1b:50:24:c2:c0:f4:f1:19:f0:11:29:b6: + a5:18:02:9b:d7:63:4c:70:8c:47:a3:03:43:5c:b9:5d:46:a0: + 0d:6f:ff:59:8e:be:dd:9f:72:c3:5b:2b:df:8c:5b:ce:e5:0c: + 46:6c:92:b2:0a:a3:4c:54:42:18:15:12:18:bd:da:fc:ba:74: + 6e:ff:c1:b6:a0:64:d8:a9:5f:55:ae:9f:5c:6a:76:96:d8:73: + 67:87:fb:4d:7f:5c:ee:69:ca:73:10:fb:8a:a9:fd:9e:bd:36: + 38:49:49:87:f4:0e:14:f0:e9:87:b8:3f:a7:4f:7a:5a:8e:79: + d4:93:e4:bb:68:52:84:ac:6c:e9:f3:98:70:55:72:32:f9:34: + ab:2b:49:b5:cd:20:62:e4:3a:7a:67:63:ab:96:dc:6d:ae:97: + ec:fc:9f:76:56:88:2e:66:cf:5b:b6:c9:a4:b0:d7:05:ba:e1: + 27:2f:93:bb:26:2a:a2:93:b0:1b:f3:8e:be:1d:40:a3:b9:36: + 8f:3e:82:1a:1a:5e:88:ea:50:f8:59:e2:83:46:29:0b:e3:44: + 5c:e1:95:b6:69:90:9a:14:6f:97:ae:81:cf:68:ef:99:9a:be: + b5:e7:e1:7f:f8:fa:13:47:16:4c:cc:6d:08:40:e7:8b:78:6f: + 50:82:44:50:3f:66:06:8a:ab:43:84:56:4a:0f:20:2d:86:0e: + f5:d2:db:d2:7a:8a:4b:cd:a5:e8:4e:f1:5e:26:25:01:59:23: + a0:7e:d2:f6:7e:21:57:d7:27:bc:15:57:4c:a4:46:c1:e0:83: + 1e:0c:4c:4d:1f:4f:06:19:e2:f9:a8:f4:3a:82:a1:b2:79:43: + 79:d6:ad:6f:7a:27:90:03:a4:ea:24:87:3f:d9:bd:d9:e9:f2: + 5f:50:49:1c:ee:ec:d7:2e +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y +MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg +TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS +b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS +M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC +UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d +Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p +rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l +pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb +j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC +KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS +/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X +cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH +1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP +px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 +MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI +eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u +2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS +v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC +wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy +CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e +vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 +Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa +Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL +eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 +FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc +7uzXLg== +-----END CERTIFICATE----- + +IdenTrust Commercial Root CA 1 +# Fingerprint (SHA1): DF:71:7E:AA:4A:D9:4E:C9:55:84:99:60:2D:48:DE:5F:BC:F0:3A:25 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=B3:3E:77:73:75:EE:A0:D3:E3:7E:49:63:49:59:BB:C7 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0a:01:42:80:00:00:01:45:23:c8:44:b5:00:00:00:02 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=IdenTrust, CN=IdenTrust Commercial Root CA 1 + Validity + Not Before: Jan 16 18:12:23 2014 GMT + Not After : Jan 16 18:12:23 2034 GMT + Subject: C=US, O=IdenTrust, CN=IdenTrust Commercial Root CA 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:a7:50:19:de:3f:99:3d:d4:33:46:f1:6f:51:61: + 82:b2:a9:4f:8f:67:89:5d:84:d9:53:dd:0c:28:d9: + d7:f0:ff:ae:95:43:72:99:f9:b5:5d:7c:8a:c1:42: + e1:31:50:74:d1:81:0d:7c:cd:9b:21:ab:43:e2:ac: + ad:5e:86:6e:f3:09:8a:1f:5a:32:bd:a2:eb:94:f9: + e8:5c:0a:ec:ff:98:d2:af:71:b3:b4:53:9f:4e:87: + ef:92:bc:bd:ec:4f:32:30:88:4b:17:5e:57:c4:53: + c2:f6:02:97:8d:d9:62:2b:bf:24:1f:62:8d:df:c3: + b8:29:4b:49:78:3c:93:60:88:22:fc:99:da:36:c8: + c2:a2:d4:2c:54:00:67:35:6e:73:bf:02:58:f0:a4: + dd:e5:b0:a2:26:7a:ca:e0:36:a5:19:16:f5:fd:b7: + ef:ae:3f:40:f5:6d:5a:04:fd:ce:34:ca:24:dc:74: + 23:1b:5d:33:13:12:5d:c4:01:25:f6:30:dd:02:5d: + 9f:e0:d5:47:bd:b4:eb:1b:a1:bb:49:49:d8:9f:5b: + 02:f3:8a:e4:24:90:e4:62:4f:4f:c1:af:8b:0e:74: + 17:a8:d1:72:88:6a:7a:01:49:cc:b4:46:79:c6:17: + b1:da:98:1e:07:59:fa:75:21:85:65:dd:90:56:ce: + fb:ab:a5:60:9d:c4:9d:f9:52:b0:8b:bd:87:f9:8f: + 2b:23:0a:23:76:3b:f7:33:e1:c9:00:f3:69:f9:4b: + a2:e0:4e:bc:7e:93:39:84:07:f7:44:70:7e:fe:07: + 5a:e5:b1:ac:d1:18:cc:f2:35:e5:49:49:08:ca:56: + c9:3d:fb:0f:18:7d:8b:3b:c1:13:c2:4d:8f:c9:4f: + 0e:37:e9:1f:a1:0e:6a:df:62:2e:cb:35:06:51:79: + 2c:c8:25:38:f4:fa:4b:a7:89:5c:9c:d2:e3:0d:39: + 86:4a:74:7c:d5:59:87:c2:3f:4e:0c:5c:52:f4:3d: + f7:52:82:f1:ea:a3:ac:fd:49:34:1a:28:f3:41:88: + 3a:13:ee:e8:de:ff:99:1d:5f:ba:cb:e8:1e:f2:b9: + 50:60:c0:31:d3:73:e5:ef:be:a0:ed:33:0b:74:be: + 20:20:c4:67:6c:f0:08:03:7a:55:80:7f:46:4e:96: + a7:f4:1e:3e:e1:f6:d8:09:e1:33:64:2b:63:d7:32: + 5e:9f:f9:c0:7b:0f:78:6f:97:bc:93:9a:f9:9c:12: + 90:78:7a:80:87:15:d7:72:74:9c:55:74:78:b1:ba: + e1:6e:70:04:ba:4f:a0:ba:68:c3:7b:ff:31:f0:73: + 3d:3d:94:2a:b1:0b:41:0e:a0:fe:4d:88:65:6b:79: + 33:b4:d7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + ED:44:19:C0:D3:F0:06:8B:EE:A4:7B:BE:42:E7:26:54:C8:8E:36:76 + Signature Algorithm: sha256WithRSAEncryption + 0d:ae:90:32:f6:a6:4b:7c:44:76:19:61:1e:27:28:cd:5e:54: + ef:25:bc:e3:08:90:f9:29:d7:ae:68:08:e1:94:00:58:ef:2e: + 2e:7e:53:52:8c:b6:5c:07:ea:88:ba:99:8b:50:94:d7:82:80: + df:61:09:00:93:ad:0d:14:e6:ce:c1:f2:37:94:78:b0:5f:9c: + b3:a2:73:b8:8f:05:93:38:cd:8d:3e:b0:b8:fb:c0:cf:b1:f2: + ec:2d:2d:1b:cc:ec:aa:9a:b3:aa:60:82:1b:2d:3b:c3:84:3d: + 57:8a:96:1e:9c:75:b8:d3:30:cd:60:08:83:90:d3:8e:54:f1: + 4d:66:c0:5d:74:03:40:a3:ee:85:7e:c2:1f:77:9c:06:e8:c1: + a7:18:5d:52:95:ed:c9:dd:25:9e:6d:fa:a9:ed:a3:3a:34:d0: + 59:7b:da:ed:50:f3:35:bf:ed:eb:14:4d:31:c7:60:f4:da:f1: + 87:9c:e2:48:e2:c6:c5:37:fb:06:10:fa:75:59:66:31:47:29: + da:76:9a:1c:e9:82:ae:ef:9a:b9:51:f7:88:23:9a:69:95:62: + 3c:e5:55:80:36:d7:54:02:ff:f1:b9:5d:ce:d4:23:6f:d8:45: + 84:4a:5b:65:ef:89:0c:dd:14:a7:20:cb:18:a5:25:b4:0d:f9: + 01:f0:a2:d2:f4:00:c8:74:8e:a1:2a:48:8e:65:db:13:c4:e2: + 25:17:7d:eb:be:87:5b:17:20:54:51:93:4a:53:03:0b:ec:5d: + ca:33:ed:62:fd:45:c7:2f:5b:dc:58:a0:80:39:e6:fa:d7:fe: + 13:14:a6:ed:3d:94:4a:42:74:d4:c3:77:59:73:cd:8f:46:be: + 55:38:ef:fa:e8:91:32:ea:97:58:04:22:de:38:c3:cc:bc:6d: + c9:33:3a:6a:0a:69:3f:a0:c8:ea:72:8f:8c:63:86:23:bd:6d: + 3c:96:9e:95:e0:49:4c:aa:a2:b9:2a:1b:9c:36:81:78:ed:c3: + e8:46:e2:26:59:44:75:1e:d9:75:89:51:cd:10:84:9d:61:60: + cb:5d:f9:97:22:4d:8e:98:e6:e3:7f:f6:5b:bb:ae:cd:ca:4a: + 81:6b:5e:0b:f3:51:e1:74:2b:e9:7e:27:a7:d9:99:49:4e:f8: + a5:80:db:25:0f:1c:63:62:8a:c9:33:67:6b:3c:10:83:c6:ad: + de:a8:cd:16:8e:8d:f0:07:37:71:9f:f2:ab:fc:41:f5:c1:8b: + ec:00:37:5d:09:e5:4e:80:ef:fa:b1:5c:38:06:a5:1b:4a:e1: + dc:38:2d:3c:dc:ab:1f:90:1a:d5:4a:9c:ee:d1:70:6c:cc:ee: + f4:57:f8:18:ba:84:6e:87 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu +VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw +MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw +JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT +3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU ++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp +S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 +bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi +T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL +vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK +Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK +dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT +c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv +l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N +iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD +ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt +LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 +nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 ++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK +W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT +AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq +l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG +4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ +mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A +7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +IdenTrust Public Sector Root CA 1 +# Fingerprint (SHA1): BA:29:41:60:77:98:3F:F4:F3:EF:F2:31:05:3B:2E:EA:6D:4D:45:FD +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=37:06:A5:B0:FC:89:9D:BA:F4:6B:8C:1A:64:CD:D5:BA +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0a:01:42:80:00:00:01:45:23:cf:46:7c:00:00:00:02 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=IdenTrust, CN=IdenTrust Public Sector Root CA 1 + Validity + Not Before: Jan 16 17:53:32 2014 GMT + Not After : Jan 16 17:53:32 2034 GMT + Subject: C=US, O=IdenTrust, CN=IdenTrust Public Sector Root CA 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:b6:22:94:fc:a4:48:af:e8:47:6b:0a:fb:27:76: + e4:f2:3f:8a:3b:7a:4a:2c:31:2a:8c:8d:b0:a9:c3: + 31:6b:a8:77:76:84:26:b6:ac:81:42:0d:08:eb:55: + 58:bb:7a:f8:bc:65:7d:f2:a0:6d:8b:a8:47:e9:62: + 76:1e:11:ee:08:14:d1:b2:44:16:f4:ea:d0:fa:1e: + 2f:5e:db:cb:73:41:ae:bc:00:b0:4a:2b:40:b2:ac: + e1:3b:4b:c2:2d:9d:e4:a1:9b:ec:1a:3a:1e:f0:08: + b3:d0:e4:24:35:07:9f:9c:b4:c9:52:6d:db:07:ca: + 8f:b5:5b:f0:83:f3:4f:c7:2d:a5:c8:ad:cb:95:20: + a4:31:28:57:58:5a:e4:8d:1b:9a:ab:9e:0d:0c:f2: + 0a:33:39:22:39:0a:97:2e:f3:53:77:b9:44:45:fd: + 84:cb:36:20:81:59:2d:9a:6f:6d:48:48:61:ca:4c: + df:53:d1:af:52:bc:44:9f:ab:2f:6b:83:72:ef:75: + 80:da:06:33:1b:5d:c8:da:63:c6:4d:cd:ac:66:31: + cd:d1:de:3e:87:10:36:e1:b9:a4:7a:ef:60:50:b2: + cb:ca:a6:56:e0:37:af:ab:34:13:39:25:e8:39:66: + e4:98:7a:aa:12:98:9c:59:66:86:3e:ad:f1:b0:ca: + 3e:06:0f:7b:f0:11:4b:37:a0:44:6d:7b:cb:a8:8c: + 71:f4:d5:b5:91:36:cc:f0:15:c6:2b:de:51:17:b1: + 97:4c:50:3d:b1:95:59:7c:05:7d:2d:21:d5:00:bf: + 01:67:a2:5e:7b:a6:5c:f2:f7:22:f1:90:0d:93:db: + aa:44:51:66:cc:7d:76:03:eb:6a:a8:2a:38:19:97: + 76:0d:6b:8a:61:f9:bc:f6:ee:76:fd:70:2b:dd:29: + 3c:f8:0a:1e:5b:42:1c:8b:56:2f:55:1b:1c:a1:2e: + b5:c7:16:e6:f8:aa:3c:92:8e:69:b6:01:c1:b5:86: + 9d:89:0f:0b:38:94:54:e8:ea:dc:9e:3d:25:bc:53: + 26:ed:d5:ab:39:aa:c5:40:4c:54:ab:b2:b4:d9:d9: + f8:d7:72:db:1c:bc:6d:bd:65:5f:ef:88:35:2a:66: + 2f:ee:f6:b3:65:f0:33:8d:7c:98:41:69:46:0f:43: + 1c:69:fa:9b:b5:d0:61:6a:cd:ca:4b:d9:4c:90:46: + ab:15:59:a1:47:54:29:2e:83:28:5f:1c:c2:a2:ab: + 72:17:00:06:8e:45:ec:8b:e2:33:3d:7f:da:19:44: + e4:62:72:c3:df:22:c6:f2:56:d4:dd:5f:95:72:ed: + 6d:5f:f7:48:03:5b:fd:c5:2a:a0:f6:73:23:84:10: + 1b:01:e7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + E3:71:E0:9E:D8:A7:42:D9:DB:71:91:6B:94:93:EB:C3:A3:D1:14:A3 + Signature Algorithm: sha256WithRSAEncryption + 47:fa:dd:0a:b0:11:91:38:ad:4d:5d:f7:e5:0e:97:54:19:82: + 48:87:54:8c:aa:64:99:d8:5a:fe:88:01:c5:58:a5:99:b1:23: + 54:23:b7:6a:1d:20:57:e5:01:62:41:17:d3:09:db:75:cb:6e: + 54:90:75:fe:1a:9f:81:0a:c2:dd:d7:f7:09:d0:5b:72:15:e4: + 1e:09:6a:3d:33:f3:21:9a:e6:15:7e:ad:51:d5:0d:10:ed:7d: + 42:c0:8f:ee:c0:9a:08:d5:41:d6:5c:0e:21:69:6e:80:61:0e: + 15:c0:b8:cf:c5:49:12:52:cc:be:3a:cc:d4:2e:38:05:de:35: + fd:1f:6f:b8:80:68:98:3d:4d:a0:ca:40:65:d2:73:7c:f5:8b: + d9:0a:95:3f:d8:3f:23:6d:1a:d1:2a:24:19:d9:85:b3:17:ef: + 78:6e:a9:58:d1:23:d3:c7:13:ed:72:25:7f:5d:b1:73:70:d0: + 7f:06:97:09:84:29:80:61:1d:fa:5e:ff:73:ac:a0:e3:89:b8: + 1c:71:15:c6:de:31:7f:12:dc:e1:6d:9b:af:e7:e8:9f:75:78: + 4c:ab:46:3b:9a:ce:bf:05:18:5d:4d:15:3c:16:9a:19:50:04: + 9a:b2:9a:6f:65:8b:52:5f:3c:58:04:28:25:c0:66:61:31:7e: + b9:e0:75:b9:1a:a8:81:d6:72:17:b3:c5:03:31:35:11:78:78: + a2:e0:e9:30:8c:7f:80:df:58:df:3c:ba:27:96:e2:80:34:6d: + e3:98:d3:64:27:ac:48:7e:28:77:5c:c6:25:61:25:f8:85:0c: + 65:fa:c4:32:2f:a5:98:05:e4:f8:0b:67:16:16:c6:82:b8:32: + 19:f9:f9:b9:79:dc:1f:cd:eb:af:ab:0e:dd:1b:db:45:e4:7a: + e7:02:e2:95:5d:fc:69:f0:53:69:61:95:75:79:0b:5e:55:e6: + 38:1c:94:a9:59:33:9e:c8:71:74:79:7f:51:89:b6:c8:6a:b8: + 30:c8:6a:38:c3:6e:9e:e1:37:16:ea:05:62:4c:5b:12:47:ed: + a7:b4:b3:58:56:c7:49:f3:7f:12:68:09:31:71:f0:6d:f8:4e: + 47:fb:d6:85:ee:c5:58:40:19:a4:1d:a7:f9:4b:43:37:dc:68: + 5a:4f:cf:eb:c2:64:74:de:b4:15:d9:f4:54:54:1a:2f:1c:d7: + 97:71:54:90:8e:d9:20:9d:53:2b:7f:ab:8f:e2:ea:30:bc:50: + 37:ef:f1:47:b5:7d:7c:2c:04:ec:68:9d:b4:49:44:10:f4:72: + 4b:1c:64:e7:fc:e6:6b:90:dd:69:7d:69:fd:00:56:a5:b7:ac: + b6:ad:b7:ca:3e:01:ef:9c +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu +VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN +MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 +MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 +ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy +RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS +bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF +/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R +3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw +EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy +9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V +GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ +2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV +WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD +W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN +AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV +DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 +TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G +lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW +mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df +WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 ++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ +tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA +GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv +8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G2 +# Fingerprint (SHA1): 8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=4B:E2:C9:91:96:65:0C:F4:0E:5A:93:92:A0:0A:FE:B2 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1246989352 (0x4a538c28) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2009 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - G2 + Validity + Not Before: Jul 7 17:25:54 2009 GMT + Not After : Dec 7 17:55:54 2030 GMT + Subject: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2009 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - G2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ba:84:b6:72:db:9e:0c:6b:e2:99:e9:30:01:a7: + 76:ea:32:b8:95:41:1a:c9:da:61:4e:58:72:cf:fe: + f6:82:79:bf:73:61:06:0a:a5:27:d8:b3:5f:d3:45: + 4e:1c:72:d6:4e:32:f2:72:8a:0f:f7:83:19:d0:6a: + 80:80:00:45:1e:b0:c7:e7:9a:bf:12:57:27:1c:a3: + 68:2f:0a:87:bd:6a:6b:0e:5e:65:f3:1c:77:d5:d4: + 85:8d:70:21:b4:b3:32:e7:8b:a2:d5:86:39:02:b1: + b8:d2:47:ce:e4:c9:49:c4:3b:a7:de:fb:54:7d:57: + be:f0:e8:6e:c2:79:b2:3a:0b:55:e2:50:98:16:32: + 13:5c:2f:78:56:c1:c2:94:b3:f2:5a:e4:27:9a:9f: + 24:d7:c6:ec:d0:9b:25:82:e3:cc:c2:c4:45:c5:8c: + 97:7a:06:6b:2a:11:9f:a9:0a:6e:48:3b:6f:db:d4: + 11:19:42:f7:8f:07:bf:f5:53:5f:9c:3e:f4:17:2c: + e6:69:ac:4e:32:4c:62:77:ea:b7:e8:e5:bb:34:bc: + 19:8b:ae:9c:51:e7:b7:7e:b5:53:b1:33:22:e5:6d: + cf:70:3c:1a:fa:e2:9b:67:b6:83:f4:8d:a5:af:62: + 4c:4d:e0:58:ac:64:34:12:03:f8:b6:8d:94:63:24: + a4:71 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 6A:72:26:7A:D0:1E:EF:7D:E7:3B:69:51:D4:6C:8D:9F:90:12:66:AB + Signature Algorithm: sha256WithRSAEncryption + 79:9f:1d:96:c6:b6:79:3f:22:8d:87:d3:87:03:04:60:6a:6b: + 9a:2e:59:89:73:11:ac:43:d1:f5:13:ff:8d:39:2b:c0:f2:bd: + 4f:70:8c:a9:2f:ea:17:c4:0b:54:9e:d4:1b:96:98:33:3c:a8: + ad:62:a2:00:76:ab:59:69:6e:06:1d:7e:c4:b9:44:8d:98:af: + 12:d4:61:db:0a:19:46:47:f3:eb:f7:63:c1:40:05:40:a5:d2: + b7:f4:b5:9a:36:bf:a9:88:76:88:04:55:04:2b:9c:87:7f:1a: + 37:3c:7e:2d:a5:1a:d8:d4:89:5e:ca:bd:ac:3d:6c:d8:6d:af: + d5:f3:76:0f:cd:3b:88:38:22:9d:6c:93:9a:c4:3d:bf:82:1b: + 65:3f:a6:0f:5d:aa:fc:e5:b2:15:ca:b5:ad:c6:bc:3d:d0:84: + e8:ea:06:72:b0:4d:39:32:78:bf:3e:11:9c:0b:a4:9d:9a:21: + f3:f0:9b:0b:30:78:db:c1:dc:87:43:fe:bc:63:9a:ca:c5:c2: + 1c:c9:c7:8d:ff:3b:12:58:08:e6:b6:3d:ec:7a:2c:4e:fb:83: + 96:ce:0c:3c:69:87:54:73:a4:73:c2:93:ff:51:10:ac:15:54: + 01:d8:fc:05:b1:89:a1:7f:74:83:9a:49:d7:dc:4e:7b:8a:48: + 6f:8b:45:f6 +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 +cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs +IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz +dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy +NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu +dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt +dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 +aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T +RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN +cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW +wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 +U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 +jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN +BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ +jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v +1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R +nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH +VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== +-----END CERTIFICATE----- + +Entrust Root Certification Authority - EC1 +# Fingerprint (SHA1): 20:D8:06:40:DF:9B:25:F5:12:25:3A:11:EA:F7:59:8A:EB:14:B5:47 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=B6:7E:1D:F0:58:C5:49:6C:24:3B:3D:ED:98:18:ED:BC +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + a6:8b:79:29:00:00:00:00:50:d0:91:f9 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2012 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - EC1 + Validity + Not Before: Dec 18 15:25:36 2012 GMT + Not After : Dec 18 15:55:36 2037 GMT + Subject: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2012 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - EC1 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:84:13:c9:d0:ba:6d:41:7b:e2:6c:d0:eb:55:5f: + 66:02:1a:24:f4:5b:89:69:47:e3:b8:c2:7d:f1:f2: + 02:c5:9f:a0:f6:5b:d5:8b:06:19:86:4f:53:10:6d: + 07:24:27:a1:a0:f8:d5:47:19:61:4c:7d:ca:93:27: + ea:74:0c:ef:6f:96:09:fe:63:ec:70:5d:36:ad:67: + 77:ae:c9:9d:7c:55:44:3a:a2:63:51:1f:f5:e3:62: + d4:a9:47:07:3e:cc:20 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + B7:63:E7:1A:DD:8D:E9:08:A6:55:83:A4:E0:6A:50:41:65:11:42:49 + Signature Algorithm: ecdsa-with-SHA384 + 30:64:02:30:61:79:d8:e5:42:47:df:1c:ae:53:99:17:b6:6f: + 1c:7d:e1:bf:11:94:d1:03:88:75:e4:8d:89:a4:8a:77:46:de: + 6d:61:ef:02:f5:fb:b5:df:cc:fe:4e:ff:fe:a9:e6:a7:02:30: + 5b:99:d7:85:37:06:b5:7b:08:fd:eb:27:8b:4a:94:f9:e1:fa: + a7:8e:26:08:e8:7c:92:68:6d:73:d8:6f:26:ac:21:02:b8:99: + b7:26:41:5b:25:60:ae:d0:48:1a:ee:06 +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG +A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 +d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu +dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq +RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy +MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD +VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g +Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt +ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH +Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC +R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX +hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +CFCA EV ROOT +# Fingerprint (SHA1): E2:B8:29:4B:55:84:AB:6B:58:C2:90:46:6C:AC:3F:B8:39:8F:84:83 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=74:E1:B6:ED:26:7A:7A:44:30:33:94:AB:7B:27:81:30 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 407555286 (0x184accd6) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=CN, O=China Financial Certification Authority, CN=CFCA EV ROOT + Validity + Not Before: Aug 8 03:07:01 2012 GMT + Not After : Dec 31 03:07:01 2029 GMT + Subject: C=CN, O=China Financial Certification Authority, CN=CFCA EV ROOT + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:d7:5d:6b:cd:10:3f:1f:05:59:d5:05:4d:37:b1: + 0e:ec:98:2b:8e:15:1d:fa:93:4b:17:82:21:71:10: + 52:d7:51:64:70:16:c2:55:69:4d:8e:15:6d:9f:bf: + 0c:1b:c2:e0:a3:67:d6:0c:ac:cf:22:ae:af:77:54: + 2a:4b:4c:8a:53:52:7a:c3:ee:2e:de:b3:71:25:c1: + e9:5d:3d:ee:a1:2f:a3:f7:2a:3c:c9:23:1d:6a:ab: + 1d:a1:a7:f1:f3:ec:a0:d5:44:cf:15:cf:72:2f:1d: + 63:97:e8:99:f9:fd:93:a4:54:80:4c:52:d4:52:ab: + 2e:49:df:90:cd:b8:5f:be:3f:de:a1:ca:4d:20:d4: + 25:e8:84:29:53:b7:b1:88:1f:ff:fa:da:90:9f:0a: + a9:2d:41:3f:b1:f1:18:29:ee:16:59:2c:34:49:1a: + a8:06:d7:a8:88:d2:03:72:7a:32:e2:ea:68:4d:6e: + 2c:96:65:7b:ca:59:fa:f2:e2:dd:ee:30:2c:fb:cc: + 46:ac:c4:63:eb:6f:7f:36:2b:34:73:12:94:7f:df: + cc:26:9e:f1:72:5d:50:65:59:8f:69:b3:87:5e:32: + 6f:c3:18:8a:b5:95:8f:b0:7a:37:de:5a:45:3b:c7: + 36:e1:ef:67:d1:39:d3:97:5b:73:62:19:48:2d:87: + 1c:06:fb:74:98:20:49:73:f0:05:d2:1b:b1:a0:a3: + b7:1b:70:d3:88:69:b9:5a:d6:38:f4:62:dc:25:8b: + 78:bf:f8:e8:7e:b8:5c:c9:95:4f:5f:a7:2d:b9:20: + 6b:cf:6b:dd:f5:0d:f4:82:b7:f4:b2:66:2e:10:28: + f6:97:5a:7b:96:16:8f:01:19:2d:6c:6e:7f:39:58: + 06:64:83:01:83:83:c3:4d:92:dd:32:c6:87:a4:37: + e9:16:ce:aa:2d:68:af:0a:81:65:3a:70:c1:9b:ad: + 4d:6d:54:ca:2a:2d:4b:85:1b:b3:80:e6:70:45:0d: + 6b:5e:35:f0:7f:3b:b8:9c:e4:04:70:89:12:25:93: + da:0a:99:22:60:6a:63:60:4e:76:06:98:4e:bd:83: + ad:1d:58:8a:25:85:d2:c7:65:1e:2d:8e:c6:df:b6: + c6:e1:7f:8a:04:21:15:29:74:f0:3e:9c:90:9d:0c: + 2e:f1:8a:3e:5a:aa:0c:09:1e:c7:d5:3c:a3:ed:97: + c3:1e:34:fa:38:f9:08:0e:e3:c0:5d:2b:83:d1:56: + 6a:c9:b6:a8:54:53:2e:78:32:67:3d:82:7f:74:d0: + fb:e1:b6:05:60:b9:70:db:8e:0b:f9:13:58:6f:71: + 60:10:52:10:b9:c1:41:09:ef:72:1f:67:31:78:ff: + 96:05:8d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Authority Key Identifier: + keyid:E3:FE:2D:FD:28:D0:0B:B5:BA:B6:A2:C4:BF:06:AA:05:8C:93:FB:2F + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + E3:FE:2D:FD:28:D0:0B:B5:BA:B6:A2:C4:BF:06:AA:05:8C:93:FB:2F + Signature Algorithm: sha256WithRSAEncryption + 25:c6:ba:6b:eb:87:cb:de:82:39:96:3d:f0:44:a7:6b:84:73: + 03:de:9d:2b:4f:ba:20:7f:bc:78:b2:cf:97:b0:1b:9c:f3:d7: + 79:2e:f5:48:b6:d2:fb:17:88:e6:d3:7a:3f:ed:53:13:d0:e2: + 2f:6a:79:cb:00:23:28:e6:1e:37:57:35:89:84:c2:76:4f:34: + 36:ad:67:c3:ce:41:06:88:c5:f7:ee:d8:1a:b8:d6:0b:7f:50: + ff:93:aa:17:4b:8c:ec:ed:52:60:b2:a4:06:ea:4e:eb:f4:6b: + 19:fd:eb:f5:1a:e0:25:2a:9a:dc:c7:41:36:f7:c8:74:05:84: + 39:95:39:d6:0b:3b:a4:27:fa:08:d8:5c:1e:f8:04:60:52:11: + 28:28:03:ff:ef:53:66:00:a5:4a:34:16:66:7c:fd:09:a4:ae: + 9e:67:1a:6f:41:0b:6b:06:13:9b:8f:86:71:05:b4:2f:8d:89: + 66:33:29:76:54:9a:11:f8:27:fa:b2:3f:91:e0:ce:0d:1b:f3: + 30:1a:ad:bf:22:5d:1b:d3:bf:25:05:4d:e1:92:1a:7f:99:9f: + 3c:44:93:ca:d4:40:49:6c:80:87:d7:04:3a:c3:32:52:35:0e: + 56:f8:a5:dd:7d:c4:8b:0d:11:1f:53:cb:1e:b2:17:b6:68:77: + 5a:e0:d4:cb:c8:07:ae:f5:3a:2e:8e:37:b7:d0:01:4b:43:29: + 77:8c:39:97:8f:82:5a:f8:51:e5:89:a0:18:e7:68:7f:5d:0a: + 2e:fb:a3:47:0e:3d:a6:23:7a:c6:01:c7:8f:c8:5e:bf:6d:80: + 56:be:8a:24:ba:33:ea:9f:e1:32:11:9e:f1:d2:4f:80:f6:1b: + 40:af:38:9e:11:50:79:73:12:12:cd:e6:6c:9d:2c:88:72:3c: + 30:81:06:91:22:ea:59:ad:da:19:2e:22:c2:8d:b9:8c:87:e0: + 66:bc:73:23:5f:21:64:63:80:48:f5:a0:3c:18:3d:94:c8:48: + 41:1d:40:ba:5e:fe:fe:56:39:a1:c8:cf:5e:9e:19:64:46:10: + da:17:91:b7:05:80:ac:8b:99:92:7d:e7:a2:d8:07:0b:36:27: + e7:48:79:60:8a:c3:d7:13:5c:f8:72:40:df:4a:cb:cf:99:00: + 0a:00:0b:11:95:da:56:45:03:88:0a:9f:67:d0:d5:79:b1:a8: + 8d:40:6d:0d:c2:7a:40:fa:f3:5f:64:47:92:cb:53:b9:bb:59: + ce:4f:fd:d0:15:53:01:d8:df:eb:d9:e6:76:ef:d0:23:bb:3b: + a9:79:b3:d5:02:29:cd:89:a3:96:0f:4a:35:e7:4e:42:c0:75: + cd:07:cf:e6:2c:eb:7b:2e +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD +TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx +MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j +aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP +T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 +sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL +TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 +/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp +7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz +EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt +hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP +a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot +aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg +TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV +PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv +cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL +tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT +ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL +jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS +ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy +P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 +xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d +Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN +5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe +/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z +AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ +5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5 +# Fingerprint (SHA1): C4:18:F6:4D:46:D1:DF:00:3D:27:30:13:72:43:A9:12:11:C6:75:FB +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +==================================================== +MD5 Fingerprint=DA:70:8E:F0:22:DF:93:26:F6:5F:9F:D3:15:06:52:4E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 156233699172481 (0x8e17fe242081) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=TR, L=Ankara, O=T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve Bili\xC5\x9Fim G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E., CN=T\xC3\x9CRKTRUST Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xC4\xB1c\xC4\xB1s\xC4\xB1 H5 + Validity + Not Before: Apr 30 08:07:01 2013 GMT + Not After : Apr 28 08:07:01 2023 GMT + Subject: C=TR, L=Ankara, O=T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve Bili\xC5\x9Fim G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E., CN=T\xC3\x9CRKTRUST Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xC4\xB1c\xC4\xB1s\xC4\xB1 H5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:a4:25:19:e1:65:9e:eb:48:21:50:4a:08:e5:11: + f0:5a:ba:26:ff:83:59:ce:44:2a:2f:fe:e1:ce:60: + 03:fc:8d:03:a5:ed:ff:6b:a8:ba:cc:34:06:9f:59: + 35:f6:ec:2c:bb:9d:fb:8d:52:69:e3:9c:27:10:53: + f3:a4:02:c5:a7:f9:11:1a:69:75:6e:c3:1d:8b:d1: + 98:8d:93:87:a7:71:97:0d:21:c7:99:f9:52:d3:2c: + 63:5d:55:bc:e8:1f:01:48:b9:60:fe:42:4a:f6:c8: + 80:ae:cd:66:7a:9e:45:8a:68:77:e2:48:68:9f:a2: + da:f1:e1:c1:10:9f:eb:3c:29:81:a7:e1:32:08:d4: + a0:05:b1:8c:fb:8d:96:00:0e:3e:25:df:53:86:22: + 3b:fc:f4:bd:f3:09:7e:77:ec:86:eb:0f:33:e5:43: + 4f:f4:54:75:6d:29:99:2e:66:5a:43:df:cb:5c:ca: + c8:e5:38:f1:7e:3b:35:9d:0f:f4:c5:5a:a1:cc:f3: + 20:80:24:d3:57:ec:15:ba:75:25:9b:e8:64:4b:b3: + 34:84:ef:04:b8:f6:c9:6c:aa:02:3e:b6:55:e2:32: + 37:5f:fc:66:97:5f:cd:d6:9e:c7:20:bf:4d:c6:ac: + 3f:75:5f:1c:ed:32:9c:7c:69:00:69:91:e3:23:18: + 53:e9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 56:99:07:1E:D3:AC:0C:69:64:B4:0C:50:47:DE:43:2C:BE:20:C0:FB + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 9e:45:76:7b:17:48:32:f2:38:8b:29:bd:ee:96:4a:4e:81:18: + b1:51:47:20:cd:d0:64:b1:0e:c9:d9:01:d9:09:ce:c8:99:dc: + 68:25:13:d4:5c:f2:a3:e8:04:fe:72:09:c7:0b:aa:1d:25:55: + 7e:96:9a:57:b7:ba:c5:11:7a:19:e6:a7:7e:3d:85:0e:f5:f9: + 2e:29:2f:e7:f9:6c:58:16:57:50:25:f6:3e:2e:3e:aa:ed:77: + 71:aa:aa:99:96:46:0a:ae:8e:ec:2a:51:16:b0:5e:cd:ea:67: + 04:1c:58:30:f5:60:8a:bd:a6:bd:4d:e5:96:b4:fc:42:89:01: + 6b:f6:70:c8:50:39:0c:2d:d5:66:d9:c8:d2:b3:32:b7:1b:19: + 6d:cb:33:f9:df:a5:e6:15:84:37:f0:c2:f2:65:96:92:90:77: + f0:ad:f4:90:e9:11:78:d7:93:89:c0:3d:0b:ba:29:f4:e8:99: + 9d:72:8e:ed:9d:2f:ee:92:7d:a1:f1:ff:5d:ba:33:60:85:62: + fe:07:02:a1:84:56:46:be:96:0a:9a:13:d7:21:4c:b7:7c:07: + 9f:4e:4e:3f:91:74:fb:27:9d:11:cc:dd:e6:b1:ca:71:4d:13: + 17:39:26:c5:29:21:2b:93:29:6a:96:fa:ab:41:e1:4b:b6:35: + 0b:c0:9b:15 +-----BEGIN CERTIFICATE----- +MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UE +BhMCVFIxDzANBgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxn +aSDEsGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkg +QS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1QgRWxla3Ryb25payBTZXJ0aWZpa2Eg +SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAwODA3MDFaFw0yMzA0 +MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYD +VQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 +dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApCUZ4WWe60ghUEoI5RHwWrom +/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537jVJp45wnEFPzpALFp/kR +Gml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1mep5Fimh3 +4khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z +5UNP9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0 +hO8EuPbJbKoCPrZV4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QID +AQABo0IwQDAdBgNVHQ4EFgQUVpkHHtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ5FdnsX +SDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPoBP5yCccLqh0l +VX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq +URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nf +peYVhDfwwvJllpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CF +Yv4HAqGEVka+lgqaE9chTLd8B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW ++qtB4Uu2NQvAmxU= +-----END CERTIFICATE----- + +Certinomis - Root CA +# Fingerprint (SHA1): 9D:70:BB:01:A5:A4:A0:18:11:2E:F7:1C:01:B9:32:C5:34:E7:88:A8 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=14:0A:FD:8D:A8:28:B5:38:69:DB:56:7E:61:22:03:3F +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FR, O=Certinomis, OU=0002 433998903, CN=Certinomis - Root CA + Validity + Not Before: Oct 21 09:17:18 2013 GMT + Not After : Oct 21 09:17:18 2033 GMT + Subject: C=FR, O=Certinomis, OU=0002 433998903, CN=Certinomis - Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:d4:cc:09:0a:2c:3f:92:f6:7f:14:9e:0b:9c:9a: + 6a:1d:40:30:64:fd:aa:df:0e:1e:06:5b:9f:50:85: + ea:cd:8d:ab:43:67:de:b0:fa:7e:80:96:9e:84:78: + 92:48:d6:e3:39:ee:ce:e4:59:58:97:e5:2e:27:98: + ea:93:a8:77:9b:4a:f0:ef:74:80:2d:eb:30:1f:b5: + d9:c7:80:9c:62:27:91:88:f0:4a:89:dd:dc:88:e6: + 14:f9:d5:03:2f:ff:95:db:bd:9f:ec:2c:fa:14:15: + 59:95:0a:c6:47:7c:69:18:b9:a7:03:f9:ca:76:a9: + cf:c7:6f:b4:5e:05:fe:ee:c1:52:b2:75:32:87:ec: + ed:29:66:3b:f3:4a:16:82:f6:d6:9a:db:72:98:e9: + de:f0:c5:4c:a5:ab:b5:ea:01:e2:8c:2e:64:7f:64: + 6f:fd:a3:25:93:8b:c8:a2:0e:49:8d:34:f0:1f:ec: + 58:45:2e:34:aa:84:50:bd:e7:b2:4a:13:b8:b0:0f: + ae:38:5d:b0:a9:1b:e6:73:c9:5a:a1:d9:66:40:aa: + a9:4d:a6:34:02:ad:84:7e:b2:23:c1:fb:2a:c6:67: + f4:34:b6:b0:95:6a:33:4f:71:44:b5:ad:c0:79:33: + 88:e0:bf:ed:a3:a0:14:b4:9c:09:b0:0a:e3:60:be: + f8:f8:66:88:cd:5b:f1:77:05:e0:b5:73:6e:c1:7d: + 46:2e:8e:4b:27:a6:cd:35:0a:fd:e5:4d:7d:aa:2a: + a3:29:c7:5a:68:04:e8:e5:d6:93:a4:62:c2:c5:e6: + f4:4f:c6:f9:9f:1a:8d:82:49:19:8a:ca:59:43:3a: + e8:0d:32:c1:f4:4c:13:03:6f:6e:a6:3f:91:73:cb: + ca:73:6f:12:20:8b:ee:c0:82:78:de:4b:2e:c2:49: + c3:1d:ed:16:f6:24:f4:27:1b:5c:57:31:dc:55:ee: + a8:1e:6f:6c:ac:e2:45:cc:57:57:8a:75:57:19:e0: + b5:58:99:49:36:31:3c:33:01:6d:16:4a:cd:b8:2a: + 83:84:86:9b:f9:60:d2:1f:6d:91:03:d3:60:a6:d5: + 3d:9a:dd:77:90:3d:35:a4:9f:0f:5e:f5:52:44:69: + b9:c0:ba:dc:cf:7d:df:7c:d9:c4:ac:86:22:32:bc: + 7b:6b:91:ef:7a:f8:17:68:b0:e2:53:55:60:2d:af: + 3e:c2:83:d8:d9:09:2b:f0:c0:64:db:87:8b:91:cc: + 91:eb:04:fd:76:b4:95:9a:e6:14:06:1b:d5:34:1d: + be:d8:ff:74:1c:53:85:99:e0:59:52:4a:61:ed:88: + 9e:6b:49:89:46:7e:20:5a:d9:e7:4a:e5:6a:ee:d2: + 65:11:43 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + EF:91:4C:F5:A5:C3:30:E8:2F:08:EA:D3:71:22:A4:92:68:78:74:D9 + X509v3 Authority Key Identifier: + keyid:EF:91:4C:F5:A5:C3:30:E8:2F:08:EA:D3:71:22:A4:92:68:78:74:D9 + + Signature Algorithm: sha256WithRSAEncryption + 7e:3d:54:da:22:5d:1a:58:3e:3b:54:27:ba:ba:cc:c8:e3:1a: + 6a:ea:3e:f9:12:eb:56:5f:3d:50:ce:e0:ea:48:26:26:cf:79: + 56:7e:91:1c:99:3f:d0:a1:91:1c:2c:0f:4f:98:95:59:53:bd: + d0:22:d8:88:5d:9c:37:fc:fb:64:c1:78:8c:8b:9a:60:09:ea: + d5:fa:21:5f:d0:74:65:e7:50:c5:bf:2e:b9:0b:0b:ad:b5:b0: + 17:a6:12:8c:d4:62:78:ea:56:6a:ec:0a:d2:40:c3:3c:05:30: + 3e:4d:94:b7:9f:4a:03:d3:7d:27:4b:b6:fe:44:ce:fa:19:33: + 1a:6d:a4:42:d1:dd:cc:c8:c8:d7:16:52:83:4f:35:94:b3:12: + 55:7d:e5:e2:42:eb:e4:9c:93:09:c0:4c:5b:07:ab:c7:6d:11: + a0:50:17:94:23:a8:b5:0a:92:0f:b2:7a:c1:60:2c:38:cc:1a: + a6:5b:ff:f2:0c:e3:aa:1f:1c:dc:b8:a0:93:27:de:63:e3:7f: + 21:9f:3a:e5:9e:fa:e0:13:6a:75:eb:96:5c:62:91:94:8e:67: + 53:b6:89:f8:12:09:cb:6f:52:5b:03:72:86:50:95:08:d4:8d: + 87:86:15:1f:95:24:d8:a4:6f:9a:ce:a4:9d:9b:6d:d2:b2:76: + 06:86:c6:56:08:c5:eb:09:da:36:c2:1b:5b:41:be:61:2a:e3: + 70:e6:b8:a6:f8:b6:5a:c4:bd:21:f7:ff:aa:5f:a1:6c:76:39: + 66:d6:ea:4c:55:e1:00:33:9b:13:98:63:c9:6f:d0:01:20:09: + 37:52:e7:0c:4f:3e:cd:bc:f5:5f:96:27:a7:20:02:95:e0:2e: + e8:07:41:05:1f:15:6e:d6:b0:e4:19:e0:0f:02:93:00:27:72: + c5:8b:d1:54:1f:5d:4a:c3:40:97:7e:55:a6:7c:c1:33:04:14: + 01:1d:49:20:69:0b:19:93:9d:6e:58:22:f7:40:0c:46:0c:23: + 63:f3:39:d2:7f:76:51:a7:f4:c8:a1:f1:0c:76:22:23:46:52: + 29:2d:e2:a3:41:07:56:69:98:d2:05:09:bc:69:c7:5a:61:cd: + 8f:81:60:15:4d:80:dd:90:e2:7d:c4:50:f2:8c:3b:6e:4a:c7: + c6:e6:80:2b:3c:81:bc:11:80:16:10:27:d7:f0:cd:3f:79:cc: + 73:2a:c3:7e:53:91:d6:6e:f8:f5:f3:c7:d0:51:4d:8e:4b:a5: + 5b:e6:19:17:3b:d6:81:09:dc:22:dc:ee:8e:b9:c4:8f:53:e1: + 67:bb:33:b8:88:15:46:cf:ed:69:35:ff:75:0d:46:f3:ce:71: + e1:c5:6b:86:42:06:b9:41 +-----BEGIN CERTIFICATE----- +MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET +MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb +BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz +MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx +FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g +Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2 +fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl +LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV +WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF +TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb +5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc +CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri +wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ +wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG +m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4 +F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng +WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0 +2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF +AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/ +0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw +F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS +g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj +qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN +h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/ +ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V +btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj +Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ +8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW +gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE= +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GB CA +# Fingerprint (SHA1): 0F:F9:40:76:18:D3:D7:6A:4B:98:F0:A8:35:9E:0C:FD:27:AC:CC:ED +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=A4:EB:B9:61:28:2E:B7:2F:98:B0:35:26:90:99:51:1D +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 76:b1:20:52:74:f0:85:87:46:b3:f8:23:1a:f6:c2:c0 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=CH, O=WISeKey, OU=OISTE Foundation Endorsed, CN=OISTE WISeKey Global Root GB CA + Validity + Not Before: Dec 1 15:00:32 2014 GMT + Not After : Dec 1 15:10:31 2039 GMT + Subject: C=CH, O=WISeKey, OU=OISTE Foundation Endorsed, CN=OISTE WISeKey Global Root GB CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d8:17:b7:1c:4a:24:2a:d6:97:b1:ca:e2:1e:fb: + 7d:38:ef:98:f5:b2:39:98:4e:27:b8:11:5d:7b:d2: + 25:94:88:82:15:26:6a:1b:31:bb:a8:5b:21:21:2b: + d8:0f:4e:9f:5a:f1:b1:5a:e4:79:d6:32:23:2b:e1: + 53:cc:99:45:5c:7b:4f:ad:bc:bf:87:4a:0b:4b:97: + 5a:a8:f6:48:ec:7d:7b:0d:cd:21:06:df:9e:15:fd: + 41:8a:48:b7:20:f4:a1:7a:1b:57:d4:5d:50:ff:ba: + 67:d8:23:99:1f:c8:3f:e3:de:ff:6f:5b:77:b1:6b: + 6e:b8:c9:64:f7:e1:ca:41:46:0e:29:71:d0:b9:23: + fc:c9:81:5f:4e:f7:6f:df:bf:84:ad:73:64:bb:b7: + 42:8e:69:f6:d4:76:1d:7e:9d:a7:b8:57:8a:51:67: + 72:d7:d4:a8:b8:95:54:40:73:03:f6:ea:f4:eb:fe: + 28:42:77:3f:9d:23:1b:b2:b6:3d:80:14:07:4c:2e: + 4f:f7:d5:0a:16:0d:bd:66:43:37:7e:23:43:79:c3: + 40:86:f5:4c:29:da:8e:9a:ad:0d:a5:04:87:88:1e: + 85:e3:e9:53:d5:9b:c8:8b:03:63:78:eb:e0:19:4a: + 6e:bb:2f:6b:33:64:58:93:ad:69:bf:8f:1b:ef:82: + 48:c7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 35:0F:C8:36:63:5E:E2:A3:EC:F9:3B:66:15:CE:51:52:E3:91:9A:3D + 1.3.6.1.4.1.311.21.1: + ... + Signature Algorithm: sha256WithRSAEncryption + 40:4c:fb:87:b2:99:81:90:7e:9d:c5:b0:b0:26:cd:88:7b:2b: + 32:8d:6e:b8:21:71:58:97:7d:ae:37:14:af:3e:e7:f7:9a:e2: + 7d:f6:71:98:99:04:aa:43:74:78:a3:e3:49:61:3e:73:8c:4d: + 94:e0:f9:71:c4:b6:16:0e:53:78:1f:d6:a2:87:2f:02:39:81: + 29:3c:af:15:98:21:30:fe:28:90:00:8c:d1:e1:cb:fa:5e:c8: + fd:f8:10:46:3b:a2:78:42:91:17:74:55:0a:de:50:67:4d:66: + d1:a7:ff:fd:d9:c0:b5:a8:a3:8a:ce:66:f5:0f:43:cd:a7:2b: + 57:7b:63:46:6a:aa:2e:52:d8:f4:ed:e1:6d:ad:29:90:78:48: + ba:e1:23:aa:a3:89:ec:b5:ab:96:c0:b4:4b:a2:1d:97:9e:7a: + f2:6e:40:71:df:68:f1:65:4d:ce:7c:05:df:53:65:a9:a5:f0: + b1:97:04:70:15:46:03:98:d4:d2:bf:54:b4:a0:58:7d:52:6f: + da:56:26:62:d4:d8:db:89:31:6f:1c:f0:22:c2:d3:62:1c:35: + cd:4c:69:15:54:1a:90:98:de:eb:1e:5f:ca:77:c7:cb:8e:3d: + 43:69:9c:9a:58:d0:24:3b:df:1b:40:96:7e:35:ad:81:c7:4e: + 71:ba:88:13 +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt +MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg +Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i +YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x +CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG +b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 +HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx +WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX +1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk +u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P +99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r +M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB +BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh +cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 +gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO +ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf +aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +SZAFIR ROOT CA2 +# Fingerprint (SHA1): E2:52:FA:95:3F:ED:DB:24:60:BD:6E:28:F3:9C:CC:CF:5E:B3:3F:DE +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=11:64:C1:89:B0:24:B1:8C:B1:07:7E:89:9E:51:9E:99 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 3e:8a:5d:07:ec:55:d2:32:d5:b7:e3:b6:5f:01:eb:2d:dc:e4:d6:e4 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=PL, O=Krajowa Izba Rozliczeniowa S.A., CN=SZAFIR ROOT CA2 + Validity + Not Before: Oct 19 07:43:30 2015 GMT + Not After : Oct 19 07:43:30 2035 GMT + Subject: C=PL, O=Krajowa Izba Rozliczeniowa S.A., CN=SZAFIR ROOT CA2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b7:bc:3e:50:a8:4b:cd:40:b5:ce:61:e7:96:ca: + b4:a1:da:0c:22:b0:fa:b5:7b:76:00:77:8c:0b:cf: + 7d:a8:86:cc:26:51:e4:20:3d:85:0c:d6:58:e3:e7: + f4:2a:18:9d:da:d1:ae:26:ee:eb:53:dc:f4:90:d6: + 13:4a:0c:90:3c:c3:f4:da:d2:8e:0d:92:3a:dc:b1: + b1:ff:38:de:c3:ba:2d:5f:80:b9:02:bd:4a:9d:1b: + 0f:b4:c3:c2:c1:67:03:dd:dc:1b:9c:3d:b3:b0:de: + 00:1e:a8:34:47:bb:9a:eb:fe:0b:14:bd:36:84:da: + 0d:20:bf:fa:5b:cb:a9:16:20:ad:39:60:ee:2f:75: + b6:e7:97:9c:f9:3e:fd:7e:4d:6f:4d:2f:ef:88:0d: + 6a:fa:dd:f1:3d:6e:20:a5:a0:12:b4:4d:70:b9:ce: + d7:72:3b:89:93:a7:80:84:1c:27:49:72:49:b5:ff: + 3b:95:9e:c1:cc:c8:01:ec:e8:0e:8a:0a:96:e7:b3: + a6:87:e5:d6:f9:05:2b:0d:97:40:70:3c:ba:ac:75: + 5a:9c:d5:4d:9d:02:0a:d2:4b:9b:66:4b:46:07:17: + 65:ad:9f:6c:88:00:dc:22:89:e0:e1:64:d4:67:bc: + 31:79:61:3c:bb:ca:41:cd:5c:6a:00:c8:3c:38:8e: + 58:af + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 2E:16:A9:4A:18:B5:CB:CC:F5:6F:50:F3:23:5F:F8:5D:E7:AC:F0:C8 + Signature Algorithm: sha256WithRSAEncryption + b5:73:f8:03:dc:59:5b:1d:76:e9:a3:2a:7b:90:28:b2:4d:c0: + 33:4f:aa:9a:b1:d4:b8:e4:27:ff:a9:96:99:ce:46:e0:6d:7c: + 4c:a2:38:a4:06:70:f0:f4:41:11:ec:3f:47:8d:3f:72:87:f9: + 3b:fd:a4:6f:2b:53:00:e0:ff:39:b9:6a:07:0e:eb:1d:1c:f6: + a2:72:90:cb:82:3d:11:82:8b:d2:bb:9f:2a:af:21:e6:63:86: + 9d:79:19:ef:f7:bb:0c:35:90:c3:8a:ed:4f:0f:f5:cc:12:d9: + a4:3e:bb:a0:fc:20:95:5f:4f:26:2f:11:23:83:4e:75:07:0f: + bf:9b:d1:b4:1d:e9:10:04:fe:ca:60:8f:a2:4c:b8:ad:cf:e1: + 90:0f:cd:ae:0a:c7:5d:7b:b7:50:d2:d4:61:fa:d5:15:db:d7: + 9f:87:51:54:eb:a5:e3:eb:c9:85:a0:25:20:37:fb:8e:ce:0c: + 34:84:e1:3c:81:b2:77:4e:43:a5:88:5f:86:67:a1:3d:e6:b4: + 5c:61:b6:3e:db:fe:b7:28:c5:a2:07:ae:b5:ca:ca:8d:2a:12: + ef:97:ed:c2:30:a4:c9:2a:7a:fb:f3:4d:23:1b:99:33:34:a0: + 2e:f5:a9:0b:3f:d4:5d:e1:cf:84:9f:e2:19:c2:5f:8a:d6:20: + 1e:e3:73:b7 +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL +BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 +ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw +NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L +cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg +Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN +QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT +3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw +3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 +3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 +BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN +XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF +AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw +8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG +nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP +oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy +d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg +LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +Certum Trusted Network CA 2 +# Fingerprint (SHA1): D3:DD:48:3E:2B:BF:4C:05:E8:AF:10:F5:FA:76:26:CF:D3:DC:30:92 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=6D:46:9E:D9:25:6D:08:23:5B:5E:74:7D:1E:27:DB:F2 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 21:d6:d0:4a:4f:25:0f:c9:32:37:fc:aa:5e:12:8d:e9 + Signature Algorithm: sha512WithRSAEncryption + Issuer: C=PL, O=Unizeto Technologies S.A., OU=Certum Certification Authority, CN=Certum Trusted Network CA 2 + Validity + Not Before: Oct 6 08:39:56 2011 GMT + Not After : Oct 6 08:39:56 2046 GMT + Subject: C=PL, O=Unizeto Technologies S.A., OU=Certum Certification Authority, CN=Certum Trusted Network CA 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:bd:f9:78:f8:e6:d5:80:0c:64:9d:86:1b:96:64: + 67:3f:22:3a:1e:75:01:7d:ef:fb:5c:67:8c:c9:cc: + 5c:6b:a9:91:e6:b9:42:e5:20:4b:9b:da:9b:7b:b9: + 99:5d:d9:9b:80:4b:d7:84:40:2b:27:d3:e8:ba:30: + bb:3e:09:1a:a7:49:95:ef:2b:40:24:c2:97:c7:a7: + ee:9b:25:ef:a8:0a:00:97:85:5a:aa:9d:dc:29:c9: + e2:35:07:eb:70:4d:4a:d6:c1:b3:56:b8:a1:41:38: + 9b:d1:fb:31:7f:8f:e0:5f:e1:b1:3f:0f:8e:16:49: + 60:d7:06:8d:18:f9:aa:26:10:ab:2a:d3:d0:d1:67: + 8d:1b:46:be:47:30:d5:2e:72:d1:c5:63:da:e7:63: + 79:44:7e:4b:63:24:89:86:2e:34:3f:29:4c:52:8b: + 2a:a7:c0:e2:91:28:89:b9:c0:5b:f9:1d:d9:e7:27: + ad:ff:9a:02:97:c1:c6:50:92:9b:02:2c:bd:a9:b9: + 34:59:0a:bf:84:4a:ff:df:fe:b3:9f:eb:d9:9e:e0: + 98:23:ec:a6:6b:77:16:2a:db:cc:ad:3b:1c:a4:87: + dc:46:73:5e:19:62:68:45:57:e4:90:82:42:bb:42: + d6:f0:61:e0:c1:a3:3d:66:a3:5d:f4:18:ee:88:c9: + 8d:17:45:29:99:32:75:02:31:ee:29:26:c8:6b:02: + e6:b5:62:45:7f:37:15:5a:23:68:89:d4:3e:de:4e: + 27:b0:f0:40:0c:bc:4d:17:cb:4d:a2:b3:1e:d0:06: + 5a:dd:f6:93:cf:57:75:99:f5:fa:86:1a:67:78:b3: + bf:96:fe:34:dc:bd:e7:52:56:e5:b3:e5:75:7b:d7: + 41:91:05:dc:5d:69:e3:95:0d:43:b9:fc:83:96:39: + 95:7b:6c:80:5a:4f:13:72:c6:d7:7d:29:7a:44:ba: + 52:a4:2a:d5:41:46:09:20:fe:22:a0:b6:5b:30:8d: + bc:89:0c:d5:d7:70:f8:87:52:fd:da:ef:ac:51:2e: + 07:b3:4e:fe:d0:09:da:70:ef:98:fa:56:e6:6d:db: + b5:57:4b:dc:e5:2c:25:15:c8:9e:2e:78:4e:f8:da: + 9c:9e:86:2c:ca:57:f3:1a:e5:c8:92:8b:1a:82:96: + 7a:c3:bc:50:12:69:d8:0e:5a:46:8b:3a:eb:26:fa: + 23:c9:b6:b0:81:be:42:00:a4:f8:d6:fe:30:2e:c7: + d2:46:f6:e5:8e:75:fd:f2:cc:b9:d0:87:5b:cc:06: + 10:60:bb:83:35:b7:5e:67:de:47:ec:99:48:f1:a4: + a1:15:fe:ad:8c:62:8e:39:55:4f:39:16:b9:b1:63: + 9d:ff:b7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + B6:A1:54:39:02:C3:A0:3F:8E:8A:BC:FA:D4:F8:1C:A6:D1:3A:0E:FD + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha512WithRSAEncryption + 71:a5:0e:ce:e4:e9:bf:3f:38:d5:89:5a:c4:02:61:fb:4c:c5: + 14:17:2d:8b:4f:53:6b:10:17:fc:65:84:c7:10:49:90:de:db: + c7:26:93:88:26:6f:70:d6:02:5e:39:a0:f7:8f:ab:96:b5:a5: + 13:5c:81:14:6d:0e:81:82:11:1b:8a:4e:c6:4f:a5:dd:62:1e: + 44:df:09:59:f4:5b:77:0b:37:e9:8b:20:c6:f8:0a:4e:2e:58: + 1c:eb:33:d0:cf:86:60:c9:da:fb:80:2f:9e:4c:60:84:78:3d: + 21:64:d6:fb:41:1f:18:0f:e7:c9:75:71:bd:bd:5c:de:34:87: + 3e:41:b0:0e:f6:b9:d6:3f:09:13:96:14:2f:de:9a:1d:5a:b9: + 56:ce:35:3a:b0:5f:70:4d:5e:e3:29:f1:23:28:72:59:b6:ab: + c2:8c:66:26:1c:77:2c:26:76:35:8b:28:a7:69:a0:f9:3b:f5: + 23:dd:85:10:74:c9:90:03:56:91:e7:af:ba:47:d4:12:97:11: + 22:e3:a2:49:94:6c:e7:b7:94:4b:ba:2d:a4:da:33:8b:4c:a6: + 44:ff:5a:3c:c6:1d:64:d8:b5:31:e4:a6:3c:7a:a8:57:0b:db: + ed:61:1a:cb:f1:ce:73:77:63:a4:87:6f:4c:51:38:d6:e4:5f: + c7:9f:b6:81:2a:e4:85:48:79:58:5e:3b:f8:db:02:82:67:c1: + 39:db:c3:74:4b:3d:36:1e:f9:29:93:88:68:5b:a8:44:19:21: + f0:a7:e8:81:0d:2c:e8:93:36:b4:37:b2:ca:b0:1b:26:7a:9a: + 25:1f:9a:9a:80:9e:4b:2a:3f:fb:a3:9a:fe:73:32:71:c2:9e: + c6:72:e1:8a:68:27:f1:e4:0f:b4:c4:4c:a5:61:93:f8:97:10: + 07:2a:30:25:a9:b9:c8:71:b8:ef:68:cc:2d:7e:f5:e0:7e:0f: + 82:a8:6f:b6:ba:6c:83:43:77:cd:8a:92:17:a1:9e:5b:78:16: + 3d:45:e2:33:72:dd:e1:66:ca:99:d3:c9:c5:26:fd:0d:68:04: + 46:ae:b6:d9:9b:8c:be:19:be:b1:c6:f2:19:e3:5c:02:ca:2c: + d8:6f:4a:07:d9:c9:35:da:40:75:f2:c4:a7:19:6f:9e:42:10: + 98:75:e6:95:8b:60:bc:ed:c5:12:d7:8a:ce:d5:98:5c:56:96: + 03:c5:ee:77:06:35:ff:cf:e4:ee:3f:13:61:ee:db:da:2d:85: + f0:cd:ae:9d:b2:18:09:45:c3:92:a1:72:17:fc:47:b6:a0:0b: + 2c:f1:c4:de:43:68:08:6a:5f:3b:f0:76:63:fb:cc:06:2c:a6: + c6:e2:0e:b5:b9:be:24:8f +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB +gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu +QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG +A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz +OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ +VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 +b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA +DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn +0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB +OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE +fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E +Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m +o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i +sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW +OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez +Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS +adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n +3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ +F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf +CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 +XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm +djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ +WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb +AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq +P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko +b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj +XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P +5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi +DrW5viSP +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2015 +# Fingerprint (SHA1): 01:0C:06:95:A6:98:19:14:FF:BF:5F:C6:B0:B6:95:EA:29:E9:12:A6 +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +======================================================= +MD5 Fingerprint=CA:FF:E2:DB:03:D9:CB:4B:E9:0F:AD:84:FD:7B:18:CE +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=GR, L=Athens, O=Hellenic Academic and Research Institutions Cert. Authority, CN=Hellenic Academic and Research Institutions RootCA 2015 + Validity + Not Before: Jul 7 10:11:21 2015 GMT + Not After : Jun 30 10:11:21 2040 GMT + Subject: C=GR, L=Athens, O=Hellenic Academic and Research Institutions Cert. Authority, CN=Hellenic Academic and Research Institutions RootCA 2015 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:c2:f8:a9:3f:1b:89:fc:3c:3c:04:5d:3d:90:36: + b0:91:3a:79:3c:66:5a:ef:6d:39:01:49:1a:b4:b7: + cf:7f:4d:23:53:b7:90:00:e3:13:2a:28:a6:31:f1: + 91:00:e3:28:ec:ae:21:41:ce:1f:da:fd:7d:12:5b: + 01:83:0f:b9:b0:5f:99:e1:f2:12:83:80:4d:06:3e: + df:ac:af:e7:a1:88:6b:31:af:f0:8b:d0:18:33:b8: + db:45:6a:34:f4:02:80:24:28:0a:02:15:95:5e:76: + 2a:0d:99:3a:14:5b:f6:cb:cb:53:bc:13:4d:01:88: + 37:94:25:1b:42:bc:22:d8:8e:a3:96:5e:3a:d9:32: + db:3e:e8:f0:10:65:ed:74:e1:2f:a7:7c:af:27:34: + bb:29:7d:9b:b6:cf:09:c8:e5:d3:0a:fc:88:65:65: + 74:0a:dc:73:1c:5c:cd:40:b1:1c:d4:b6:84:8c:4c: + 50:cf:68:8e:a8:59:ae:c2:27:4e:82:a2:35:dd:14: + f4:1f:ff:b2:77:d5:87:2f:aa:6e:7d:24:27:e7:c6: + cb:26:e6:e5:fe:67:07:63:d8:45:0d:dd:3a:59:65: + 39:58:7a:92:99:72:3d:9c:84:5e:88:21:b8:d5:f4: + 2c:fc:d9:70:52:4f:78:b8:bd:3c:2b:8b:95:98:f5: + b3:d1:68:cf:20:14:7e:4c:5c:5f:e7:8b:e5:f5:35: + 81:19:37:d7:11:08:b7:66:be:d3:4a:ce:83:57:00: + 3a:c3:81:f8:17:cb:92:36:5d:d1:a3:d8:75:1b:e1: + 8b:27:ea:7a:48:41:fd:45:19:06:ad:27:99:4e:c1: + 70:47:dd:b5:9f:81:53:12:e5:b1:8c:48:5d:31:43: + 17:e3:8c:c6:7a:63:96:4b:29:30:4e:84:4e:62:19: + 5e:3c:ce:97:90:a5:7f:01:eb:9d:e0:f8:8b:89:dd: + 25:98:3d:92:b6:7e:ef:d9:f1:51:51:7d:2d:26:c8: + 69:59:61:e0:ac:6a:b8:2a:36:11:04:7a:50:bd:32: + 84:be:2f:dc:72:d5:d7:1d:16:47:e4:47:66:20:3f: + f4:96:c5:af:8e:01:7a:a5:0f:7a:64:f5:0d:18:87: + d9:ae:88:d5:fa:84:c1:3a:c0:69:28:2d:f2:0d:68: + 51:aa:e3:a5:77:c6:a4:90:0e:a1:37:8b:31:23:47: + c1:09:08:eb:6e:f7:78:9b:d7:82:fc:84:20:99:49: + 19:b6:12:46:b1:fb:45:55:16:a9:a3:65:ac:9c:07: + 0f:ea:6b:dc:1f:2e:06:72:ec:86:88:12:e4:2d:db: + 5f:05:2f:e4:f0:03:d3:26:33:e7:80:c2:cd:42:a1: + 17:34:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 71:15:67:C8:C8:C9:BD:75:5D:72:D0:38:18:6A:9D:F3:71:24:54:0B + Signature Algorithm: sha256WithRSAEncryption + 75:bb:6d:54:4b:aa:10:58:46:34:f2:62:d7:16:36:5d:08:5e: + d5:6c:c8:87:bd:b4:2e:46:f2:31:f8:7c:ea:42:b5:93:16:55: + dc:a1:0c:12:a0:da:61:7e:0f:58:58:73:64:72:c7:e8:45:8e: + dc:a9:f2:26:3f:c6:79:8c:b1:53:08:33:81:b0:56:13:be:e6: + 51:5c:d8:9b:0a:4f:4b:9c:56:53:02:e9:4f:f6:0d:60:ea:4d: + 42:55:e8:7c:1b:21:21:d3:1b:3a:cc:77:f2:b8:90:f1:68:c7: + f9:5a:fe:fa:2d:f4:bf:c9:f5:45:1b:ce:38:10:2a:37:8a:79: + a3:b4:e3:09:6c:85:86:93:ff:89:96:27:78:81:8f:67:e3:46: + 74:54:8e:d9:0d:69:e2:4a:f4:4d:74:03:ff:b2:77:ed:95:67: + 97:e4:b1:c5:ab:bf:6a:23:e8:d4:94:e2:44:28:62:c4:4b:e2: + f0:d8:e2:29:6b:1a:70:7e:24:61:93:7b:4f:03:32:25:0d:45: + 24:2b:96:b4:46:6a:bf:4a:0b:f7:9a:8f:c1:ac:1a:c5:67:f3: + 6f:34:d2:fa:73:63:8c:ef:16:b0:a8:a4:46:2a:f8:eb:12:ec: + 72:b4:ef:f8:2b:7e:8c:52:c0:8b:84:54:f9:2f:3e:e3:55:a8: + dc:66:b1:d9:e1:5f:d8:b3:8c:59:34:59:a4:ab:4f:6c:bb:1f: + 18:db:75:ab:d8:cb:92:cd:94:38:61:0e:07:06:1f:4b:46:10: + f1:15:be:8d:85:5c:3b:4a:2b:81:79:0f:b4:69:9f:49:50:97: + 4d:f7:0e:56:5d:c0:95:6a:c2:36:c3:1b:68:c9:f5:2a:dc:47: + 9a:be:b2:ce:c5:25:e8:fa:03:b9:da:f9:16:6e:91:84:f5:1c: + 28:c8:fc:26:cc:d7:1c:90:56:a7:5f:6f:3a:04:bc:cd:78:89: + 0b:8e:0f:2f:a3:aa:4f:a2:1b:12:3d:16:08:40:0f:f1:46:4c: + d7:aa:7b:08:c1:0a:f5:6d:27:de:02:8f:ca:c3:b5:2b:ca:e9: + eb:c8:21:53:38:a5:cc:3b:d8:77:37:30:a2:4f:d9:6f:d1:f2: + 40:ad:41:7a:17:c5:d6:4a:35:89:b7:41:d5:7c:86:7f:55:4d: + 83:4a:a5:73:20:c0:3a:af:90:f1:9a:24:8e:d9:8e:71:ca:7b: + b8:86:da:b2:8f:99:3e:1d:13:0d:12:11:ee:d4:ab:f0:e9:15: + 76:02:e4:e0:df:aa:20:1e:5b:61:85:64:40:a9:90:97:0d:ad: + 53:d2:5a:1d:87:6a:00:97:65:62:b4:be:6f:6a:a7:f5:2c:42: + ed:32:ad:b6:21:9e:be:bc +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix +DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k +IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT +N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v +dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG +A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh +ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx +QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA +4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 +AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 +4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C +ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV +9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD +gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 +Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq +NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko +LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd +ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I +XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI +M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot +9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V +Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea +j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh +X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ +l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf +bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 +pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK +e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 +vm9qp/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions ECC RootCA 2015 +# Fingerprint (SHA1): 9F:F1:71:8D:92:D5:9A:F3:7D:74:97:B4:BC:6F:84:68:0B:BA:B6:66 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +=========================================================== +MD5 Fingerprint=81:E5:B4:17:EB:C2:F5:E1:4B:0D:41:7B:49:92:FE:EF +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C=GR, L=Athens, O=Hellenic Academic and Research Institutions Cert. Authority, CN=Hellenic Academic and Research Institutions ECC RootCA 2015 + Validity + Not Before: Jul 7 10:37:12 2015 GMT + Not After : Jun 30 10:37:12 2040 GMT + Subject: C=GR, L=Athens, O=Hellenic Academic and Research Institutions Cert. Authority, CN=Hellenic Academic and Research Institutions ECC RootCA 2015 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:92:a0:41:e8:4b:82:84:5c:e2:f8:31:11:99:86: + 64:4e:09:25:2f:9d:41:2f:0a:ae:35:4f:74:95:b2: + 51:64:6b:8d:6b:e6:3f:70:95:f0:05:44:47:a6:72: + 38:50:76:95:02:5a:8e:ae:28:9e:f9:2d:4e:99:ef: + 2c:48:6f:4c:25:29:e8:d1:71:5b:df:1d:c1:75:37: + b4:d7:fa:7b:7a:42:9c:6a:0a:56:5a:7c:69:0b:aa: + 80:09:24:6c:7e:c1:46 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + B4:22:0B:82:99:24:01:0E:9C:BB:E4:0E:FD:BF:FB:97:20:93:99:2A + Signature Algorithm: ecdsa-with-SHA256 + 30:64:02:30:67:ce:16:62:38:a2:ac:62:45:a7:a9:95:24:c0: + 1a:27:9c:32:3b:c0:c0:d5:ba:a9:e7:f8:04:43:53:85:ee:52: + 21:de:9d:f5:25:83:3e:9e:58:4b:2f:d7:67:13:0e:21:02:30: + 05:e1:75:01:de:68:ed:2a:1f:4d:4c:09:08:0d:ec:4b:ad:64: + 17:28:e7:75:ce:45:65:72:21:17:cb:22:41:0e:8c:13:98:38: + 9a:54:6d:9b:ca:e2:7c:ea:02:58:22:91 +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN +BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl +bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv +b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ +BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj +YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 +MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 +dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg +QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa +jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi +C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep +lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof +TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +Certplus Root CA G1 +# Fingerprint (SHA1): 22:FD:D0:B7:FD:A2:4E:0D:AC:49:2C:A0:AC:A6:7B:6A:1F:E3:F7:66 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=7F:09:9C:F7:D9:B9:5C:69:69:56:D5:37:3E:14:0D:42 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 11:20:55:83:e4:2d:3e:54:56:85:2d:83:37:b7:2c:dc:46:11 + Signature Algorithm: sha512WithRSAEncryption + Issuer: C=FR, O=Certplus, CN=Certplus Root CA G1 + Validity + Not Before: May 26 00:00:00 2014 GMT + Not After : Jan 15 00:00:00 2038 GMT + Subject: C=FR, O=Certplus, CN=Certplus Root CA G1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:da:50:87:b6:da:b8:a9:3e:9d:64:fa:56:33:9a: + 56:3d:16:e5:03:95:b2:34:1c:9a:6d:62:05:d4:d8: + 8f:e7:89:64:9f:ba:db:64:8b:64:e6:79:2a:61:cd: + af:8f:5a:89:91:65:b9:58:fc:b4:03:5f:91:3f:2d: + 10:15:e0:7e:cf:bc:fc:7f:43:67:a8:ad:5e:36:23: + d8:98:b3:4d:f3:43:9e:39:7c:2a:fc:ec:88:d5:88: + ee:70:bd:85:16:2d:ea:4b:89:3c:a3:71:42:fe:1c: + fd:d3:1c:2d:10:b8:86:54:ea:43:b8:db:c6:87:da: + a8:ae:80:25:cf:7a:26:1d:aa:91:b0:48:6f:ae:b5: + de:9e:d8:d7:fa:00:fd:c6:8f:d0:51:bb:62:7d:a4: + b1:8c:b2:ff:20:11:ba:35:63:05:86:47:60:43:33: + 90:f6:47:a2:03:4f:96:4d:9d:4f:c1:ea:ea:9c:a2: + fe:34:2e:de:b7:ca:1b:76:a4:b7:ad:9f:e9:a8:d4: + 78:3f:78:fe:f2:38:09:36:1d:d2:16:02:c8:ec:2a: + 68:af:f5:8e:94:ef:2d:13:7a:1e:42:4a:1d:15:31: + ae:0c:04:57:fc:61:73:f3:31:56:86:31:80:a0:c4: + 11:6e:30:76:e3:94:f0:5f:04:c4:ac:87:72:89:98: + c5:9d:cc:57:08:9a:f4:0c:fc:7d:7a:05:3a:fa:47: + 80:39:b6:cf:84:13:77:6f:27:ea:ff:96:67:17:08: + 6d:e9:0d:d6:23:50:30:b0:15:74:13:3e:e5:2f:ff: + 0e:cd:c4:0b:4a:5d:f0:d8:00:33:49:66:eb:a1:18: + 7c:59:2e:3d:28:b9:61:71:cb:b5:a5:ba:b8:ea:dc: + e2:70:6f:08:6a:dc:87:67:34:ef:df:30:72:dd:f3: + c9:3f:23:ff:35:e1:be:21:29:20:30:81:e4:19:a5: + 20:e9:25:ca:73:31:74:29:be:e2:42:d5:f3:b2:26: + 66:c7:68:fd:19:b3:e7:20:93:99:e8:5d:e0:5e:87: + e7:46:e8:25:9c:0a:29:24:d4:cd:58:86:52:40:24: + b2:7b:0f:98:12:20:24:f6:90:6c:47:c8:0d:bb:18: + 20:2e:d9:fd:fc:8b:f2:29:ea:87:74:95:e0:42:50: + 78:84:04:41:61:b0:f4:21:23:8f:2d:cb:28:21:f2: + 6a:6c:f4:1a:a6:c5:14:b4:37:65:4f:95:fd:80:c8: + f8:72:e5:25:6b:c4:60:b1:7b:6d:8e:4a:8a:73:ce: + 59:fb:70:7a:73:06:13:d9:d3:74:37:24:41:0a:11: + 6f:97:dc:e7:e4:7e:a1:bd:15:f2:ba:87:0f:3d:68: + 8a:16:07 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + A8:C1:C0:9B:91:A8:43:15:7C:5D:06:27:B4:2A:51:D8:97:0B:81:B1 + X509v3 Authority Key Identifier: + keyid:A8:C1:C0:9B:91:A8:43:15:7C:5D:06:27:B4:2A:51:D8:97:0B:81:B1 + + Signature Algorithm: sha512WithRSAEncryption + 9c:56:6f:01:7e:d1:bd:4c:f5:8a:c6:f0:26:1f:e4:e0:38:18: + cc:32:c3:29:3b:9d:41:29:34:61:c6:d7:f0:00:a1:eb:a4:72: + 8f:94:17:bc:13:2c:75:b4:57:ee:0a:7c:09:7a:dc:d5:ca:a1: + d0:34:13:f8:77:ab:9f:e5:fe:d8:1e:74:8a:85:07:8f:7f:cc: + 79:7a:ca:96:cd:cd:fd:4f:fb:fd:23:0d:90:f5:f4:5e:d3:c6: + 61:7d:9e:11:e0:02:ee:09:04:d9:07:dd:a6:8a:b7:0c:83:24: + bb:83:50:92:fe:60:75:11:3e:d8:9d:b0:8a:7a:b5:e0:9d:9b: + cb:90:52:4b:b0:93:2a:d4:3e:16:33:e5:9e:c6:65:15:3e:64: + 3b:04:3f:db:0c:8f:5f:5c:1d:69:1f:af:f3:e9:21:8c:f3:ef: + 97:f6:9a:b7:19:b6:84:74:9c:a3:54:b5:70:4e:63:d8:57:5d: + 53:21:9b:40:92:43:fa:d6:77:55:33:4f:64:d5:fb:d0:2c:6a: + 8e:6d:25:a6:ef:85:e8:02:c4:53:3e:b9:9e:87:bc:cc:35:1a: + de:a1:e9:8a:63:87:65:1e:11:2a:db:63:77:97:14:be:9a:14: + 99:11:b2:c0:ee:b0:4f:f8:14:21:32:43:4f:9f:ab:a2:cb:a8: + 0f:aa:3b:06:55:c6:12:29:57:08:d4:37:d7:87:27:ad:49:59: + a7:91:ab:44:7a:5e:8d:70:db:97:ce:48:50:b1:73:93:f6:f0: + 83:60:f9:cd:f1:e1:31:fd:5b:7c:71:21:63:14:14:aa:af:c5: + de:93:7e:68:b1:ec:22:a2:aa:90:75:9e:b5:43:72:ea:64:a3: + 84:4b:fd:0c:a8:26:6b:71:97:ee:56:63:66:e8:42:54:f9:c7: + 1d:df:d0:8f:5b:df:c8:30:6f:88:fe:0d:c4:33:1c:53:a8:a3: + fd:48:10:f2:e4:0a:4e:e1:15:57:fc:6e:64:30:c2:55:11:dc: + ea:a9:cd:4a:54:ac:29:63:44:cf:4a:40:a0:d6:68:59:1b:33: + f9:ef:3a:8b:db:20:92:dc:42:84:bf:01:ab:87:c0:d5:20:82: + db:c6:b9:83:85:42:5c:0f:43:3b:6a:49:35:d5:98:f4:15:bf: + fa:61:81:0c:09:20:18:d2:d0:17:0c:cb:48:00:50:e9:76:82: + 8c:64:d7:3a:a0:07:55:cc:1e:31:c0:ef:3a:b4:65:fb:e3:bf: + 42:6b:9e:0f:a8:bd:6b:98:dc:d8:db:cb:8b:a4:dd:d7:59:f4: + 6e:dd:fe:aa:c3:91:d0:2e:42:07:c0:0c:4d:53:cd:24:b1:4c: + 5b:1e:51:f4:df:e9:92:fa +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA +MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy +dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa +MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy +dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a +iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt +6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP +0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f +6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE +EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN +1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc +h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT +mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV +4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO +WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud +DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd +Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq +hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh +66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7 +/SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS +S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j +2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R +Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr +RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy +6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV +V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5 +g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl +++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= +-----END CERTIFICATE----- + +Certplus Root CA G2 +# Fingerprint (SHA1): 4F:65:8E:1F:E9:06:D8:28:02:E9:54:47:41:C9:54:25:5D:69:CC:1A +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=A7:EE:C4:78:2D:1B:EE:2D:B9:29:CE:D6:A7:96:32:31 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 11:20:d9:91:ce:ae:a3:e8:c5:e7:ff:e9:02:af:cf:73:bc:55 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=FR, O=Certplus, CN=Certplus Root CA G2 + Validity + Not Before: May 26 00:00:00 2014 GMT + Not After : Jan 15 00:00:00 2038 GMT + Subject: C=FR, O=Certplus, CN=Certplus Root CA G2 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:cd:0f:5b:56:82:df:f0:45:1a:d6:ad:f7:79:f0: + 1d:c9:ac:96:d6:9e:4e:9c:1f:b4:42:11:ca:86:bf: + 6d:fb:85:a3:c5:e5:19:5c:d7:ee:a6:3f:69:67:d8: + 78:e2:a6:c9:c4:db:2d:79:2e:e7:8b:8d:02:6f:31: + 22:4d:06:e3:60:72:45:9d:0e:42:77:9e:ce:cf:e5: + 7f:85:9b:18:e4:fc:cc:2e:72:d3:16:93:4e:ca:99: + 63:5c:a1:05:2a:6c:06 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + DA:83:63:02:79:8E:DA:4C:C6:3C:23:14:D8:8F:C3:20:AB:28:60:59 + X509v3 Authority Key Identifier: + keyid:DA:83:63:02:79:8E:DA:4C:C6:3C:23:14:D8:8F:C3:20:AB:28:60:59 + + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:30:70:fe:b0:0b:d9:f7:83:97:ec:f3:55:1d:d4:dc: + b3:06:0e:fe:33:98:9d:8b:39:90:6b:94:21:ed:b6:d7:5d:d6: + 4c:d7:21:a7:e7:bf:21:0f:2b:cd:f7:2a:dc:85:07:9d:02:31: + 00:86:14:16:e5:dc:b0:65:c2:c0:8e:14:9f:bf:24:16:68:e5: + bc:f9:79:69:dc:ad:45:2b:f7:b6:31:73:cc:06:a5:53:93:91: + 1a:93:ae:70:6a:67:ba:d7:9e:e5:61:1a:5f +-----BEGIN CERTIFICATE----- +MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x +CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs +dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x +CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs +dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat +93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x +Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P +AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj +FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG +SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch +p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal +U5ORGpOucGpnutee5WEaXw== +-----END CERTIFICATE----- + +OpenTrust Root CA G1 +# Fingerprint (SHA1): 79:91:E8:34:F7:E2:EE:DD:08:95:01:52:E9:55:2D:14:E9:58:D5:7E +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=76:00:CC:81:29:CD:55:5E:88:6A:7A:2E:F7:4D:39:DA +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 11:20:b3:90:55:39:7d:7f:36:6d:64:c2:a7:9f:6b:63:8e:67 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FR, O=OpenTrust, CN=OpenTrust Root CA G1 + Validity + Not Before: May 26 08:45:50 2014 GMT + Not After : Jan 15 00:00:00 2038 GMT + Subject: C=FR, O=OpenTrust, CN=OpenTrust Root CA G1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:f8:79:46:da:96:c5:30:5e:8a:71:03:2d:70:a4: + bb:b0:c5:08:dc:cd:e6:35:c0:80:a4:11:2d:dd:e6: + 87:ae:5d:3d:91:d2:87:6c:37:b7:da:62:9e:9b:c2: + 24:d7:8f:f1:db:a6:a6:df:46:6f:51:a6:71:cb:3e: + 1b:31:67:62:f7:11:5b:34:27:d5:79:4e:8c:9b:58: + bd:22:10:0d:5c:27:0c:dd:30:e5:a8:d3:5d:21:38: + 74:17:fe:e3:1f:b6:4f:3b:6b:2d:db:7d:60:1f:8c: + 7d:4c:05:c2:eb:01:16:15:98:14:8e:d1:90:77:22: + 3f:ec:c2:39:b8:79:3a:f0:49:24:e2:95:91:dc:61: + 34:92:8c:54:74:ef:b1:7d:8c:01:e2:38:7d:c1:5f: + 6a:5f:24:b2:8e:62:17:ad:79:20:ad:ab:1d:b7:e0: + b4:96:48:4f:66:43:10:06:16:24:03:e1:e0:9c:8e: + c6:46:4f:8e:1a:99:e1:8f:b9:8e:33:6c:69:de:58: + ad:a0:0e:a7:64:54:11:69:44:66:4f:4c:12:a7:8e: + 2c:7d:c4:d4:5b:c5:00:34:30:c1:d9:99:fe:32:ce: + 07:84:b4:4e:cd:0a:ff:36:4d:62:f1:a7:63:57:e4: + db:6a:a7:ae:bf:2b:b9:c9:e6:b2:27:89:e5:7e:9a: + 1c:4d:68:c6:c1:18:de:33:2b:51:46:4b:1c:8e:f7: + 3d:0c:f9:8a:34:14:c4:fb:33:35:23:f1:cc:f1:2a: + c7:a5:bb:b0:a2:ce:fe:53:6b:4d:41:1b:66:28:b2: + 96:fa:a7:ae:0a:4e:b9:39:33:44:9c:74:c1:93:1c: + f8:e0:9e:24:25:43:f1:9b:23:82:aa:df:2c:20:b0: + dc:36:4e:03:b3:7c:02:d4:e6:7b:1a:aa:87:13:bf: + 3e:a1:74:bb:9b:0e:e1:c0:93:9f:d7:a4:66:ca:bb: + 1b:3b:e3:30:f4:33:59:8a:07:72:03:55:e7:73:6a: + 03:31:6e:6f:96:1b:e3:a2:9f:af:92:c7:ed:f5:42: + b7:25:4c:3b:13:04:cf:1c:96:af:1c:22:a3:d0:ab: + 05:b2:4c:12:23:52:dc:fd:19:5b:27:9c:1e:3b:7a: + fd:42:23:db:23:80:13:f0:bc:51:15:54:94:a6:77: + 3e:d0:74:51:bd:51:14:08:39:37:cb:1f:34:a9:30: + 9d:52:84:2e:55:90:b1:ba:df:55:00:0b:d8:56:2d: + b1:49:49:72:80:a9:62:d7:c0:f6:18:11:04:55:cd: + 74:7b:cf:61:70:79:f4:7b:2c:5c:5c:92:fc:e5:b8: + 5a:ab:4c:93:95:a1:27:ee:a5:be:cf:71:23:42:ba: + 9b:76:2d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 97:46:21:57:21:35:DA:36:55:C7:F3:F1:37:70:E5:08:F6:93:29:B6 + X509v3 Authority Key Identifier: + keyid:97:46:21:57:21:35:DA:36:55:C7:F3:F1:37:70:E5:08:F6:93:29:B6 + + Signature Algorithm: sha256WithRSAEncryption + 1d:dd:02:60:7c:e0:35:a7:e6:98:7b:ea:44:ce:67:40:4f:f2: + 93:6e:66:d4:39:89:26:ac:d3:4d:04:3c:bb:87:21:3f:37:f4: + 71:25:da:4b:ba:ab:96:82:81:91:b6:ed:d9:b1:a4:65:97:e2: + 6f:64:59:a4:96:ee:60:ca:1f:23:fb:45:ba:ff:8f:24:f0:ca: + a9:31:7f:79:1f:80:b3:2d:32:ba:64:67:60:af:b9:59:cd:df: + 9a:49:d3:a8:82:b1:f9:98:94:8a:cc:e0:bb:e0:04:1b:99:60: + b1:46:65:dc:08:a2:b2:46:9e:44:88:ea:93:7e:57:16:d2:15: + 72:5f:2e:4b:ab:d4:9d:63:b8:e3:48:e5:fe:84:2e:58:0a:9f: + 43:1d:fe:b7:18:92:86:43:4b:0e:9c:32:86:2c:60:f5:e9:48: + ea:95:ed:70:29:f1:d5:2f:fd:35:b4:57:cf:db:85:48:99:b9: + c2:6f:6c:8f:cd:78:95:ac:64:28:fd:56:b0:c3:6f:c3:be:59: + 52:e1:5f:84:8f:80:f2:f4:0d:36:ad:76:b3:a3:b5:e1:64:76: + 3a:58:dc:7d:4f:5e:56:6c:e5:55:59:57:a5:df:f1:8a:66:30: + 8c:d4:52:62:38:77:b4:be:28:d7:ca:36:c4:9b:05:f0:f8:15: + db:db:f1:ef:34:9d:1d:78:4a:88:56:67:6e:60:ff:8f:c8:8b: + e1:8e:bd:42:a9:33:0a:59:42:12:12:2a:fa:b1:9d:43:8e:05: + 9b:99:da:62:ad:57:36:b3:1d:b6:0d:79:2d:96:b8:eb:f2:0c: + 4b:0c:a5:94:c6:30:a7:26:19:2d:ed:4c:06:50:30:f1:fd:58: + 3d:b9:4b:17:5f:19:b4:6a:84:54:b4:38:4f:39:a2:0d:96:68: + c3:28:94:fd:ed:2d:1f:4a:6b:43:96:2e:90:01:10:fb:38:a6: + 81:0b:d0:bf:75:d3:d4:b9:ce:f1:3f:6f:0e:1c:1e:37:71:e5: + 18:87:75:19:3f:50:b9:5e:a4:45:34:ad:b0:ca:e6:e5:13:76: + 0f:31:14:a9:8e:2d:94:d6:d5:85:4d:73:15:4f:4b:f2:b2:3e: + ed:6c:bd:fd:0e:9d:66:73:b0:3d:b4:f7:bf:a8:e0:11:a4:c4: + ae:75:09:4a:63:00:48:20:a6:c6:9d:0b:09:8a:b4:e0:e6:ce: + 3e:c7:3e:26:38:e9:2b:de:a6:08:49:03:04:90:8a:e9:8f:bf: + e8:b6:b4:2a:a3:23:8d:1c:1c:b2:39:92:a8:8f:02:5c:40:39: + 75:d4:73:41:02:77:de:cd:e0:43:87:d6:e4:ba:4a:c3:6c:12: + 7f:fe:2a:e6:23:d6:8c:71 +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA +MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w +ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw +MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU +T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b +wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX +/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0 +77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP +uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx +p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx +Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2 +TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W +G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw +vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY +EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1 +2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw +DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E +PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf +gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS +FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0 +V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P +XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I +i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t +TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91 +09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky +Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ +AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj +1oxx +-----END CERTIFICATE----- + +OpenTrust Root CA G2 +# Fingerprint (SHA1): 79:5F:88:60:C5:AB:7C:3D:92:E6:CB:F4:8D:E1:45:CD:11:EF:60:0B +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=57:24:B6:59:24:6B:AE:C8:FE:1C:0C:20:F2:C0:4E:EB +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 11:20:a1:69:1b:bf:bd:b9:bd:52:96:8f:23:e8:48:bf:26:11 + Signature Algorithm: sha512WithRSAEncryption + Issuer: C=FR, O=OpenTrust, CN=OpenTrust Root CA G2 + Validity + Not Before: May 26 00:00:00 2014 GMT + Not After : Jan 15 00:00:00 2038 GMT + Subject: C=FR, O=OpenTrust, CN=OpenTrust Root CA G2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:cc:b6:57:a5:33:94:10:81:32:53:df:61:7e:0f: + 76:39:cf:5c:c2:53:75:1d:49:7a:96:38:dd:a2:73: + 6a:f1:6f:de:5e:a2:5a:b9:71:21:be:36:d9:a1:fc: + bc:ee:6c:a8:7c:34:1a:71:1a:e8:1a:d8:5f:0e:44: + 06:ed:a7:e0:f3:d2:61:0b:e0:32:a2:96:d1:38:f0: + c2:da:01:17:fc:e4:ac:4f:e8:ee:89:1e:74:ab:4f: + bf:1e:09:b6:36:6a:56:f3:e1:ee:96:89:66:24:06: + e4:cd:42:3a:4a:dd:e0:9a:b0:c4:82:45:b3:fe:c9: + ab:5c:7c:3e:c9:eb:17:2f:0c:7d:6e:ae:a5:8f:c8: + ac:25:0a:6f:fa:d5:45:98:d2:35:09:f6:03:43:94: + fe:d9:bf:20:95:79:80:98:8a:d9:89:35:bb:51:1b: + a4:37:7d:fc:99:3b:ab:ff:bf:ac:0d:8f:43:b1:99: + 7b:16:10:7e:1d:6f:47:c4:15:8f:04:96:08:06:42: + 04:f8:84:d6:1d:bc:91:a6:42:be:49:d5:6a:88:3f: + bc:2d:51:d1:9e:8d:e0:52:cc:57:dd:35:35:58:db: + b4:8f:24:88:e4:8b:df:dc:6b:54:d2:81:2b:b2:ce: + 92:4b:1c:1f:46:fa:1d:d8:92:cb:76:67:b5:09:99: + 09:e5:ac:17:14:55:70:c6:3c:a0:56:0a:03:b3:dc: + 62:19:df:c8:b5:30:7f:f5:3c:26:75:11:bd:d7:1b: + b3:87:9e:07:af:65:71:e5:a0:cf:1a:a7:09:10:1d: + 93:89:66:5b:e8:3c:62:32:b5:b5:3a:6e:e9:85:01: + 8b:9e:43:8c:67:73:28:59:5b:eb:e3:dc:2c:cc:a5: + 26:72:62:12:b4:e6:9c:83:44:f6:51:a4:e2:c0:7a: + 24:57:ca:0e:a5:3f:3a:b5:3b:8b:e5:76:ee:70:e6: + 92:de:16:5c:28:5b:97:19:27:92:fe:7a:92:54:ce: + 93:39:0a:16:87:bc:63:b3:f5:b1:93:5c:e0:6e:b7: + d0:ea:f9:62:32:88:44:fb:bf:27:28:b6:30:95:5d: + 12:28:b9:95:be:8f:53:18:e5:a2:18:16:e2:56:a4: + b2:2c:10:f5:1d:37:a6:f8:b7:f6:d0:59:5c:89:f7: + c2:d5:b5:94:74:d1:d5:fe:1b:b6:f0:e6:d6:1e:7b: + d2:3c:cb:a8:e3:f5:18:f3:21:1f:6e:ef:4d:68:06: + 7b:2d:5d:6e:43:89:a6:c0:f9:a0:bf:82:1e:cf:53: + 7f:b4:eb:2c:db:5d:f6:6a:7d:40:24:05:72:89:38: + 01:93:cb:71:c2:39:5d:06:11:f6:6f:78:f8:37:0d: + 39:84:27 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 6A:39:FA:42:22:F7:E6:89:00:4D:5E:7D:33:83:CB:B8:6E:77:86:AF + X509v3 Authority Key Identifier: + keyid:6A:39:FA:42:22:F7:E6:89:00:4D:5E:7D:33:83:CB:B8:6E:77:86:AF + + Signature Algorithm: sha512WithRSAEncryption + 98:cb:ab:40:3c:e5:33:02:97:7f:2d:87:a6:8f:d4:5e:4a:af: + b8:1e:e7:bb:71:fb:80:64:25:a9:b3:1a:3e:68:5d:27:26:a7: + ba:2a:e1:f0:57:83:0a:64:4f:1e:22:74:1b:e9:90:5f:f0:ac: + cf:ff:4f:68:7a:38:a4:10:6c:0d:b1:c7:a4:77:80:18:b6:a2: + 28:44:76:a7:34:9d:71:84:2f:ca:59:d2:47:88:99:41:22:c9: + 30:98:61:6e:3d:a8:a8:05:6d:d1:1f:c0:51:44:56:7f:27:35: + 02:dd:5e:98:0a:42:eb:30:bf:8d:a1:9b:51:aa:3b:ea:93:46: + 64:c5:00:79:de:21:6b:f6:57:a0:86:d7:06:72:ec:70:46:4b: + 8b:73:dd:a0:21:75:3e:dc:1d:c0:8f:d3:4f:73:1c:85:d9:fe: + 7f:62:c8:95:6f:b6:d3:7b:8c:ba:53:c2:6f:9b:44:4c:79:d0: + 1d:70:b3:d7:9f:02:f4:b2:07:b0:c7:e5:f8:ad:23:0e:a6:56: + c9:29:12:77:48:d9:2f:46:fd:3b:f0:fc:74:70:92:a5:8e:38: + 08:1f:64:30:b6:b7:4b:fb:36:ac:10:8e:a0:52:33:63:9d:03: + 35:56:c5:69:bd:c6:23:5a:27:94:f6:a4:12:f8:2d:33:3c:a1: + 56:a5:5f:d6:19:e9:ed:7c:08:bd:77:cd:27:64:cc:94:da:4e: + 46:50:87:e0:f9:c1:53:80:1e:bb:ad:fb:47:52:8b:1b:fd:a2: + f9:de:0e:22:b7:3d:33:59:6c:d4:de:f5:95:06:32:0d:51:19: + 41:5c:3e:4f:06:f7:b9:2b:80:27:f6:a3:aa:7a:7c:06:e1:43: + c3:13:39:62:1a:36:bd:e0:28:2e:94:02:e4:29:2e:60:55:ae: + 40:3d:b0:74:92:5e:f0:20:64:96:3f:5f:45:5d:88:b5:8a:da: + 02:a0:5b:45:54:de:38:3d:09:c0:a8:4a:65:46:16:fc:aa:bf: + 54:4e:4d:5b:be:38:43:b7:28:ca:8b:33:aa:1a:25:ba:25:5c: + 29:2f:5b:4a:6e:8c:ea:2d:9c:2a:f6:05:76:e0:77:97:80:88: + dd:67:13:6f:1d:68:24:8b:4f:b7:74:81:e5:f4:60:9f:7a:55: + d7:3e:37:da:16:6b:3e:77:ac:ae:18:70:95:08:79:29:03:8a: + fe:c1:3b:b3:3f:1a:0f:a4:3b:5e:1f:58:a1:95:c9:ab:2f:73: + 4a:d0:2d:6e:9a:59:0f:55:18:78:2d:3c:51:a6:97:8b:e6:bb: + b2:70:aa:4c:11:de:ff:7c:2b:37:d4:7a:d1:77:34:8f:e7:f9: + 42:f7:3c:81:0c:4b:52:0a +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA +MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w +ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw +MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU +T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh +/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e +CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6 +1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE +FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS +gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X +G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy +YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH +vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4 +t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/ +gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3 +5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w +DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz +Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0 +nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT +RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT +wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2 +t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa +TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2 +o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU +3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA +iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f +WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM +S1IK +-----END CERTIFICATE----- + +OpenTrust Root CA G3 +# Fingerprint (SHA1): 6E:26:64:F3:56:BF:34:55:BF:D1:93:3F:7C:01:DE:D8:13:DA:8A:A6 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=21:37:B4:17:16:92:7B:67:46:70:A9:96:D7:A8:13:24 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 11:20:e6:f8:4c:fc:24:b0:be:05:40:ac:da:83:1b:34:60:3f + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=FR, O=OpenTrust, CN=OpenTrust Root CA G3 + Validity + Not Before: May 26 00:00:00 2014 GMT + Not After : Jan 15 00:00:00 2038 GMT + Subject: C=FR, O=OpenTrust, CN=OpenTrust Root CA G3 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:4a:ee:58:ae:4d:ca:66:de:06:3a:a3:11:fc:e0: + 18:f0:6e:1c:ba:2d:30:0c:89:d9:d6:ee:9b:73:83: + a9:23:15:8c:2f:59:8a:5a:dd:14:ea:9d:59:2b:43: + b7:06:ec:32:b6:ba:ee:41:b5:ad:5d:a1:85:cc:ea: + 1d:14:66:a3:67:7e:46:e2:94:f3:e7:b6:56:a1:15: + 59:a1:4f:37:97:b9:22:1e:bd:11:eb:f4:b2:1f:5e: + c3:14:9a:e5:d9:97:99 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 47:77:C3:14:8B:62:39:0C:C9:6F:E1:50:4D:D0:10:58:DC:95:88:6D + X509v3 Authority Key Identifier: + keyid:47:77:C3:14:8B:62:39:0C:C9:6F:E1:50:4D:D0:10:58:DC:95:88:6D + + Signature Algorithm: ecdsa-with-SHA384 + 30:66:02:31:00:8f:a8:dc:9d:ba:0c:04:17:fa:15:e9:3d:2f: + 29:01:97:bf:81:16:33:40:93:6c:fc:f9:ed:80:70:6f:aa:8f: + db:84:c2:8b:f5:35:ca:06:dc:64:6f:68:16:e1:8f:91:b9:02: + 31:00:d8:4b:a5:cb:c2:d0:08:6c:e9:18:fb:5a:dd:4d:5f:24: + 0b:b0:00:21:25:ef:8f:a7:04:26:71:e2:7c:69:e5:5d:9a:f8: + 41:1f:3b:39:93:93:9d:55:ea:cd:8d:f1:fb:c1 +-----BEGIN CERTIFICATE----- +MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx +CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U +cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow +QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl +blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm +3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d +oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G +A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5 +DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK +BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q +j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx +4nxp5V2a+EEfOzmTk51V6s2N8fvB +-----END CERTIFICATE----- + +ISRG Root X1 +# Fingerprint (SHA1): CA:BD:2A:79:A1:07:6A:31:F2:1D:25:36:35:CB:03:9D:43:29:A5:E8 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=0C:D2:F9:E0:DA:17:73:E9:ED:86:4D:A5:E3:70:E7:4E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 82:10:cf:b0:d2:40:e3:59:44:63:e0:bb:63:82:8b:00 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=Internet Security Research Group, CN=ISRG Root X1 + Validity + Not Before: Jun 4 11:04:38 2015 GMT + Not After : Jun 4 11:04:38 2035 GMT + Subject: C=US, O=Internet Security Research Group, CN=ISRG Root X1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:ad:e8:24:73:f4:14:37:f3:9b:9e:2b:57:28:1c: + 87:be:dc:b7:df:38:90:8c:6e:3c:e6:57:a0:78:f7: + 75:c2:a2:fe:f5:6a:6e:f6:00:4f:28:db:de:68:86: + 6c:44:93:b6:b1:63:fd:14:12:6b:bf:1f:d2:ea:31: + 9b:21:7e:d1:33:3c:ba:48:f5:dd:79:df:b3:b8:ff: + 12:f1:21:9a:4b:c1:8a:86:71:69:4a:66:66:6c:8f: + 7e:3c:70:bf:ad:29:22:06:f3:e4:c0:e6:80:ae:e2: + 4b:8f:b7:99:7e:94:03:9f:d3:47:97:7c:99:48:23: + 53:e8:38:ae:4f:0a:6f:83:2e:d1:49:57:8c:80:74: + b6:da:2f:d0:38:8d:7b:03:70:21:1b:75:f2:30:3c: + fa:8f:ae:dd:da:63:ab:eb:16:4f:c2:8e:11:4b:7e: + cf:0b:e8:ff:b5:77:2e:f4:b2:7b:4a:e0:4c:12:25: + 0c:70:8d:03:29:a0:e1:53:24:ec:13:d9:ee:19:bf: + 10:b3:4a:8c:3f:89:a3:61:51:de:ac:87:07:94:f4: + 63:71:ec:2e:e2:6f:5b:98:81:e1:89:5c:34:79:6c: + 76:ef:3b:90:62:79:e6:db:a4:9a:2f:26:c5:d0:10: + e1:0e:de:d9:10:8e:16:fb:b7:f7:a8:f7:c7:e5:02: + 07:98:8f:36:08:95:e7:e2:37:96:0d:36:75:9e:fb: + 0e:72:b1:1d:9b:bc:03:f9:49:05:d8:81:dd:05:b4: + 2a:d6:41:e9:ac:01:76:95:0a:0f:d8:df:d5:bd:12: + 1f:35:2f:28:17:6c:d2:98:c1:a8:09:64:77:6e:47: + 37:ba:ce:ac:59:5e:68:9d:7f:72:d6:89:c5:06:41: + 29:3e:59:3e:dd:26:f5:24:c9:11:a7:5a:a3:4c:40: + 1f:46:a1:99:b5:a7:3a:51:6e:86:3b:9e:7d:72:a7: + 12:05:78:59:ed:3e:51:78:15:0b:03:8f:8d:d0:2f: + 05:b2:3e:7b:4a:1c:4b:73:05:12:fc:c6:ea:e0:50: + 13:7c:43:93:74:b3:ca:74:e7:8e:1f:01:08:d0:30: + d4:5b:71:36:b4:07:ba:c1:30:30:5c:48:b7:82:3b: + 98:a6:7d:60:8a:a2:a3:29:82:cc:ba:bd:83:04:1b: + a2:83:03:41:a1:d6:05:f1:1b:c2:b6:f0:a8:7c:86: + 3b:46:a8:48:2a:88:dc:76:9a:76:bf:1f:6a:a5:3d: + 19:8f:eb:38:f3:64:de:c8:2b:0d:0a:28:ff:f7:db: + e2:15:42:d4:22:d0:27:5d:e1:79:fe:18:e7:70:88: + ad:4e:e6:d9:8b:3a:c6:dd:27:51:6e:ff:bc:64:f5: + 33:43:4f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 79:B4:59:E6:7B:B6:E5:E4:01:73:80:08:88:C8:1A:58:F6:E9:9B:6E + Signature Algorithm: sha256WithRSAEncryption + 55:1f:58:a9:bc:b2:a8:50:d0:0c:b1:d8:1a:69:20:27:29:08: + ac:61:75:5c:8a:6e:f8:82:e5:69:2f:d5:f6:56:4b:b9:b8:73: + 10:59:d3:21:97:7e:e7:4c:71:fb:b2:d2:60:ad:39:a8:0b:ea: + 17:21:56:85:f1:50:0e:59:eb:ce:e0:59:e9:ba:c9:15:ef:86: + 9d:8f:84:80:f6:e4:e9:91:90:dc:17:9b:62:1b:45:f0:66:95: + d2:7c:6f:c2:ea:3b:ef:1f:cf:cb:d6:ae:27:f1:a9:b0:c8:ae: + fd:7d:7e:9a:fa:22:04:eb:ff:d9:7f:ea:91:2b:22:b1:17:0e: + 8f:f2:8a:34:5b:58:d8:fc:01:c9:54:b9:b8:26:cc:8a:88:33: + 89:4c:2d:84:3c:82:df:ee:96:57:05:ba:2c:bb:f7:c4:b7:c7: + 4e:3b:82:be:31:c8:22:73:73:92:d1:c2:80:a4:39:39:10:33: + 23:82:4c:3c:9f:86:b2:55:98:1d:be:29:86:8c:22:9b:9e:e2: + 6b:3b:57:3a:82:70:4d:dc:09:c7:89:cb:0a:07:4d:6c:e8:5d: + 8e:c9:ef:ce:ab:c7:bb:b5:2b:4e:45:d6:4a:d0:26:cc:e5:72: + ca:08:6a:a5:95:e3:15:a1:f7:a4:ed:c9:2c:5f:a5:fb:ff:ac: + 28:02:2e:be:d7:7b:bb:e3:71:7b:90:16:d3:07:5e:46:53:7c: + 37:07:42:8c:d3:c4:96:9c:d5:99:b5:2a:e0:95:1a:80:48:ae: + 4c:39:07:ce:cc:47:a4:52:95:2b:ba:b8:fb:ad:d2:33:53:7d: + e5:1d:4d:6d:d5:a1:b1:c7:42:6f:e6:40:27:35:5c:a3:28:b7: + 07:8d:e7:8d:33:90:e7:23:9f:fb:50:9c:79:6c:46:d5:b4:15: + b3:96:6e:7e:9b:0c:96:3a:b8:52:2d:3f:d6:5b:e1:fb:08:c2: + 84:fe:24:a8:a3:89:da:ac:6a:e1:18:2a:b1:a8:43:61:5b:d3: + 1f:dc:3b:8d:76:f2:2d:e8:8d:75:df:17:33:6c:3d:53:fb:7b: + cb:41:5f:ff:dc:a2:d0:61:38:e1:96:b8:ac:5d:8b:37:d7:75: + d5:33:c0:99:11:ae:9d:41:c1:72:75:84:be:02:41:42:5f:67: + 24:48:94:d1:9b:27:be:07:3f:b9:b8:4f:81:74:51:e1:7a:b7: + ed:9d:23:e2:be:e0:d5:28:04:13:3c:31:03:9e:dd:7a:6c:8f: + c6:07:18:c6:7f:de:47:8e:3f:28:9e:04:06:cf:a5:54:34:77: + bd:ec:89:9b:e9:17:43:df:5b:db:5f:fe:8e:1e:57:a2:cd:40: + 9d:7e:62:22:da:de:18:27 +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM +# Fingerprint (SHA1): EC:50:35:07:B2:15:C4:95:62:19:E2:A8:9A:5B:42:99:2C:4C:2C:20 +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=E2:09:04:B4:D3:BD:D1:A0:14:FD:1A:D2:47:C4:57:1D +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 5d:93:8d:30:67:36:c8:06:1d:1a:c7:54:84:69:07 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=ES, O=FNMT-RCM, OU=AC RAIZ FNMT-RCM + Validity + Not Before: Oct 29 15:59:56 2008 GMT + Not After : Jan 1 00:00:00 2030 GMT + Subject: C=ES, O=FNMT-RCM, OU=AC RAIZ FNMT-RCM + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:ba:71:80:7a:4c:86:6e:7f:c8:13:6d:c0:c6:7d: + 1c:00:97:8f:2c:0c:23:bb:10:9a:40:a9:1a:b7:87: + 88:f8:9b:56:6a:fb:e6:7b:8e:8b:92:8e:a7:25:5d: + 59:11:db:36:2e:b7:51:17:1f:a9:08:1f:04:17:24: + 58:aa:37:4a:18:df:e5:39:d4:57:fd:d7:c1:2c:91: + 01:91:e2:22:d4:03:c0:58:fc:77:47:ec:8f:3e:74: + 43:ba:ac:34:8d:4d:38:76:67:8e:b0:c8:6f:30:33: + 58:71:5c:b4:f5:6b:6e:d4:01:50:b8:13:7e:6c:4a: + a3:49:d1:20:19:ee:bc:c0:29:18:65:a7:de:fe:ef: + dd:0a:90:21:e7:1a:67:92:42:10:98:5f:4f:30:bc: + 3e:1c:45:b4:10:d7:68:40:14:c0:40:fa:e7:77:17: + 7a:e6:0b:8f:65:5b:3c:d9:9a:52:db:b5:bd:9e:46: + cf:3d:eb:91:05:02:c0:96:b2:76:4c:4d:10:96:3b: + 92:fa:9c:7f:0f:99:df:be:23:35:45:1e:02:5c:fe: + b5:a8:9b:99:25:da:5e:f3:22:c3:39:f5:e4:2a:2e: + d3:c6:1f:c4:6c:aa:c5:1c:6a:01:05:4a:2f:d2:c5: + c1:a8:34:26:5d:66:a5:d2:02:21:f9:18:b7:06:f5: + 4e:99:6f:a8:ab:4c:51:e8:cf:50:18:c5:77:c8:39: + 09:2c:49:92:32:99:a8:bb:17:17:79:b0:5a:c5:e6: + a3:c4:59:65:47:35:83:5e:a9:e8:35:0b:99:bb:e4: + cd:20:c6:9b:4a:06:39:b5:68:fc:22:ba:ee:55:8c: + 2b:4e:ea:f3:b1:e3:fc:b6:99:9a:d5:42:fa:71:4d: + 08:cf:87:1e:6a:71:7d:f9:d3:b4:e9:a5:71:81:7b: + c2:4e:47:96:a5:f6:76:85:a3:28:8f:e9:80:6e:81: + 53:a5:6d:5f:b8:48:f9:c2:f9:36:a6:2e:49:ff:b8: + 96:c2:8c:07:b3:9b:88:58:fc:eb:1b:1c:de:2d:70: + e2:97:92:30:a1:89:e3:bc:55:a8:27:d6:4b:ed:90: + ad:8b:fa:63:25:59:2d:a8:35:dd:ca:97:33:bc:e5: + cd:c7:9d:d1:ec:ef:5e:0e:4a:90:06:26:63:ad:b9: + d9:35:2d:07:ba:76:65:2c:ac:57:8f:7d:f4:07:94: + d7:81:02:96:5d:a3:07:49:d5:7a:d0:57:f9:1b:e7: + 53:46:75:aa:b0:79:42:cb:68:71:08:e9:60:bd:39: + 69:ce:f4:af:c3:56:40:c7:ad:52:a2:09:e4:6f:86: + 47:8a:1f:eb:28:27:5d:83:20:af:04:c9:6c:56:9a: + 8b:46:f5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + F7:7D:C5:FD:C4:E8:9A:1B:77:64:A7:F5:1D:A0:CC:BF:87:60:9A:6D + X509v3 Certificate Policies: + Policy: X509v3 Any Policy + CPS: http://www.cert.fnmt.es/dpcs/ + + Signature Algorithm: sha256WithRSAEncryption + 07:90:4a:df:f3:23:4e:f0:c3:9c:51:65:9b:9c:22:a2:8a:0c: + 85:f3:73:29:6b:4d:fe:01:e2:a9:0c:63:01:bf:04:67:a5:9d: + 98:5f:fd:01:13:fa:ec:9a:62:e9:86:fe:b6:62:d2:6e:4c:94: + fb:c0:75:45:7c:65:0c:f8:b2:37:cf:ac:0f:cf:8d:6f:f9:19: + f7:8f:ec:1e:f2:70:9e:f0:ca:b8:ef:b7:ff:76:37:76:5b:f6: + 6e:88:f3:af:62:32:22:93:0d:3a:6a:8e:14:66:0c:2d:53:74: + 57:65:1e:d5:b2:dd:23:81:3b:a5:66:23:27:67:09:8f:e1:77: + aa:43:cd:65:51:08:ed:51:58:fe:e6:39:f9:cb:47:84:a4:15: + f1:76:bb:a4:ee:a4:3b:c4:5f:ef:b2:33:96:11:18:b7:c9:65: + be:18:e1:a3:a4:dc:fa:18:f9:d3:bc:13:9b:39:7a:34:ba:d3: + 41:fb:fa:32:8a:2a:b7:2b:86:0b:69:83:38:be:cd:8a:2e:0b: + 70:ad:8d:26:92:ee:1e:f5:01:2b:0a:d9:d6:97:9b:6e:e0:a8: + 19:1c:3a:21:8b:0c:1e:40:ad:03:e7:dd:66:7e:f5:b9:20:0d: + 03:e8:96:f9:82:45:d4:39:e0:a0:00:5d:d7:98:e6:7d:9e:67: + 73:c3:9a:2a:f7:ab:8b:a1:3a:14:ef:34:bc:52:0e:89:98:9a: + 04:40:84:1d:7e:45:69:93:57:ce:eb:ce:f8:50:7c:4f:1c:6e: + 04:43:9b:f9:d6:3b:23:18:e9:ea:8e:d1:4d:46:8d:f1:3b:e4: + 6a:ca:ba:fb:23:b7:9b:fa:99:01:29:5a:58:5a:2d:e3:f9:d4: + 6d:0e:26:ad:c1:6e:34:bc:32:f8:0c:05:fa:65:a3:db:3b:37: + 83:22:e9:d6:dc:72:33:fd:5d:f2:20:bd:76:3c:23:da:28:f7: + f9:1b:eb:59:64:d5:dc:5f:72:7e:20:fc:cd:89:b5:90:67:4d: + 62:7a:3f:4e:ad:1d:c3:39:fe:7a:f4:28:16:df:41:f6:48:80: + 05:d7:0f:51:79:ac:10:ab:d4:ec:03:66:e6:6a:b0:ba:31:92: + 42:40:6a:be:3a:d3:72:e1:6a:37:55:bc:ac:1d:95:b7:69:61: + f2:43:91:74:e6:a0:d3:0a:24:46:a1:08:af:d6:da:45:19:96: + d4:53:1d:5b:84:79:f0:c0:f7:47:ef:8b:8f:c5:06:ae:9d:4c: + 62:9d:ff:46:04:f8:d3:c9:b6:10:25:40:75:fe:16:aa:c9:4a: + 60:86:2f:ba:ef:30:77:e4:54:e2:b8:84:99:58:80:aa:13:8b: + 51:3a:4f:48:f6:8b:b6:b3 +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx +CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ +WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ +BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG +Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ +yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf +BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz +WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF +tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z +374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC +IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL +mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 +wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS +MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 +ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet +UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H +YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 +LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 +RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM +LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf +77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N +JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm +fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp +6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp +1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B +9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok +RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv +uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +Amazon Root CA 1 +# Fingerprint (SHA1): 8D:A7:F9:65:EC:5E:FC:37:91:0F:1C:6E:59:FD:C1:CC:6A:6E:DE:16 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=43:C6:BF:AE:EC:FE:AD:2F:18:C6:88:68:30:FC:C8:E6 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 06:6c:9f:cf:99:bf:8c:0a:39:e2:f0:78:8a:43:e6:96:36:5b:ca + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=Amazon, CN=Amazon Root CA 1 + Validity + Not Before: May 26 00:00:00 2015 GMT + Not After : Jan 17 00:00:00 2038 GMT + Subject: C=US, O=Amazon, CN=Amazon Root CA 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b2:78:80:71:ca:78:d5:e3:71:af:47:80:50:74: + 7d:6e:d8:d7:88:76:f4:99:68:f7:58:21:60:f9:74: + 84:01:2f:ac:02:2d:86:d3:a0:43:7a:4e:b2:a4:d0: + 36:ba:01:be:8d:db:48:c8:07:17:36:4c:f4:ee:88: + 23:c7:3e:eb:37:f5:b5:19:f8:49:68:b0:de:d7:b9: + 76:38:1d:61:9e:a4:fe:82:36:a5:e5:4a:56:e4:45: + e1:f9:fd:b4:16:fa:74:da:9c:9b:35:39:2f:fa:b0: + 20:50:06:6c:7a:d0:80:b2:a6:f9:af:ec:47:19:8f: + 50:38:07:dc:a2:87:39:58:f8:ba:d5:a9:f9:48:67: + 30:96:ee:94:78:5e:6f:89:a3:51:c0:30:86:66:a1: + 45:66:ba:54:eb:a3:c3:91:f9:48:dc:ff:d1:e8:30: + 2d:7d:2d:74:70:35:d7:88:24:f7:9e:c4:59:6e:bb: + 73:87:17:f2:32:46:28:b8:43:fa:b7:1d:aa:ca:b4: + f2:9f:24:0e:2d:4b:f7:71:5c:5e:69:ff:ea:95:02: + cb:38:8a:ae:50:38:6f:db:fb:2d:62:1b:c5:c7:1e: + 54:e1:77:e0:67:c8:0f:9c:87:23:d6:3f:40:20:7f: + 20:80:c4:80:4c:3e:3b:24:26:8e:04:ae:6c:9a:c8: + aa:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 84:18:CC:85:34:EC:BC:0C:94:94:2E:08:59:9C:C7:B2:10:4E:0A:08 + Signature Algorithm: sha256WithRSAEncryption + 98:f2:37:5a:41:90:a1:1a:c5:76:51:28:20:36:23:0e:ae:e6: + 28:bb:aa:f8:94:ae:48:a4:30:7f:1b:fc:24:8d:4b:b4:c8:a1: + 97:f6:b6:f1:7a:70:c8:53:93:cc:08:28:e3:98:25:cf:23:a4: + f9:de:21:d3:7c:85:09:ad:4e:9a:75:3a:c2:0b:6a:89:78:76: + 44:47:18:65:6c:8d:41:8e:3b:7f:9a:cb:f4:b5:a7:50:d7:05: + 2c:37:e8:03:4b:ad:e9:61:a0:02:6e:f5:f2:f0:c5:b2:ed:5b: + b7:dc:fa:94:5c:77:9e:13:a5:7f:52:ad:95:f2:f8:93:3b:de: + 8b:5c:5b:ca:5a:52:5b:60:af:14:f7:4b:ef:a3:fb:9f:40:95: + 6d:31:54:fc:42:d3:c7:46:1f:23:ad:d9:0f:48:70:9a:d9:75: + 78:71:d1:72:43:34:75:6e:57:59:c2:02:5c:26:60:29:cf:23: + 19:16:8e:88:43:a5:d4:e4:cb:08:fb:23:11:43:e8:43:29:72: + 62:a1:a9:5d:5e:08:d4:90:ae:b8:d8:ce:14:c2:d0:55:f2:86: + f6:c4:93:43:77:66:61:c0:b9:e8:41:d7:97:78:60:03:6e:4a: + 72:ae:a5:d1:7d:ba:10:9e:86:6c:1b:8a:b9:59:33:f8:eb:c4: + 90:be:f1:b9 +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +Amazon Root CA 2 +# Fingerprint (SHA1): 5A:8C:EF:45:D7:A6:98:59:76:7A:8C:8B:44:96:B5:78:CF:47:4B:1A +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=C8:E5:8D:CE:A8:42:E2:7A:C0:2A:5C:7C:9E:26:BF:66 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 06:6c:9f:d2:96:35:86:9f:0a:0f:e5:86:78:f8:5b:26:bb:8a:37 + Signature Algorithm: sha384WithRSAEncryption + Issuer: C=US, O=Amazon, CN=Amazon Root CA 2 + Validity + Not Before: May 26 00:00:00 2015 GMT + Not After : May 26 00:00:00 2040 GMT + Subject: C=US, O=Amazon, CN=Amazon Root CA 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:ad:96:9f:2d:9c:4a:4c:4a:81:79:51:99:ec:8a: + cb:6b:60:51:13:bc:4d:6d:06:fc:b0:08:8d:dd:19: + 10:6a:c7:26:0c:35:d8:c0:6f:20:84:e9:94:b1:9b: + 85:03:c3:5b:db:4a:e8:c8:f8:90:76:d9:5b:4f:e3: + 4c:e8:06:36:4d:cc:9a:ac:3d:0c:90:2b:92:d4:06: + 19:60:ac:37:44:79:85:81:82:ad:5a:37:e0:0d:cc: + 9d:a6:4c:52:76:ea:43:9d:b7:04:d1:50:f6:55:e0: + d5:d2:a6:49:85:e9:37:e9:ca:7e:ae:5c:95:4d:48: + 9a:3f:ae:20:5a:6d:88:95:d9:34:b8:52:1a:43:90: + b0:bf:6c:05:b9:b6:78:b7:ea:d0:e4:3a:3c:12:53: + 62:ff:4a:f2:7b:be:35:05:a9:12:34:e3:f3:64:74: + 62:2c:3d:00:49:5a:28:fe:32:44:bb:87:dd:65:27: + 02:71:3b:da:4a:f7:1f:da:cd:f7:21:55:90:4f:0f: + ec:ae:82:e1:9f:6b:d9:45:d3:bb:f0:5f:87:ed:3c: + 2c:39:86:da:3f:de:ec:72:55:eb:79:a3:ad:db:dd: + 7c:b0:ba:1c:ce:fc:de:4f:35:76:cf:0f:f8:78:1f: + 6a:36:51:46:27:61:5b:e9:9e:cf:f0:a2:55:7d:7c: + 25:8a:6f:2f:b4:c5:cf:84:2e:2b:fd:0d:51:10:6c: + fb:5f:1b:bc:1b:7e:c5:ae:3b:98:01:31:92:ff:0b: + 57:f4:9a:b2:b9:57:e9:ab:ef:0d:76:d1:f0:ee:f4: + ce:86:a7:e0:6e:e9:b4:69:a1:df:69:f6:33:c6:69: + 2e:97:13:9e:a5:87:b0:57:10:81:37:c9:53:b3:bb: + 7f:f6:92:d1:9c:d0:18:f4:92:6e:da:83:4f:a6:63: + 99:4c:a5:fb:5e:ef:21:64:7a:20:5f:6c:64:85:15: + cb:37:e9:62:0c:0b:2a:16:dc:01:2e:32:da:3e:4b: + f5:9e:3a:f6:17:40:94:ef:9e:91:08:86:fa:be:63: + a8:5a:33:ec:cb:74:43:95:f9:6c:69:52:36:c7:29: + 6f:fc:55:03:5c:1f:fb:9f:bd:47:eb:e7:49:47:95: + 0b:4e:89:22:09:49:e0:f5:61:1e:f1:bf:2e:8a:72: + 6e:80:59:ff:57:3a:f9:75:32:a3:4e:5f:ec:ed:28: + 62:d9:4d:73:f2:cc:81:17:60:ed:cd:eb:dc:db:a7: + ca:c5:7e:02:bd:f2:54:08:54:fd:b4:2d:09:2c:17: + 54:4a:98:d1:54:e1:51:67:08:d2:ed:6e:7e:6f:3f: + d2:2d:81:59:29:66:cb:90:39:95:11:1e:74:27:fe: + dd:eb:af + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + B0:0C:F0:4C:30:F4:05:58:02:48:FD:33:E5:52:AF:4B:84:E3:66:52 + Signature Algorithm: sha384WithRSAEncryption + aa:a8:80:8f:0e:78:a3:e0:a2:d4:cd:e6:f5:98:7a:3b:ea:00: + 03:b0:97:0e:93:bc:5a:a8:f6:2c:8c:72:87:a9:b1:fc:7f:73: + fd:63:71:78:a5:87:59:cf:30:e1:0d:10:b2:13:5a:6d:82:f5: + 6a:e6:80:9f:a0:05:0b:68:e4:47:6b:c7:6a:df:b6:fd:77:32: + 72:e5:18:fa:09:f4:a0:93:2c:5d:d2:8c:75:85:76:65:90:0c: + 03:79:b7:31:23:63:ad:78:83:09:86:68:84:ca:ff:f9:cf:26: + 9a:92:79:e7:cd:4b:c5:e7:61:a7:17:cb:f3:a9:12:93:93:6b: + a7:e8:2f:53:92:c4:60:58:b0:cc:02:51:18:5b:85:8d:62:59: + 63:b6:ad:b4:de:9a:fb:26:f7:00:27:c0:5d:55:37:74:99:c9: + 50:7f:e3:59:2e:44:e3:2c:25:ee:ec:4c:32:77:b4:9f:1a:e9: + 4b:5d:20:c5:da:fd:1c:87:16:c6:43:e8:d4:bb:26:9a:45:70: + 5e:a9:0b:37:53:e2:46:7b:27:fd:e0:46:f2:89:b7:cc:42:b6: + cb:28:26:6e:d9:a5:c9:3a:c8:41:13:60:f7:50:8c:15:ae:b2: + 6d:1a:15:1a:57:78:e6:92:2a:d9:65:90:82:3f:6c:02:af:ae: + 12:3a:27:96:36:04:d7:1d:a2:80:63:a9:9b:f1:e5:ba:b4:7c: + 14:b0:4e:c9:b1:1f:74:5f:38:f6:51:ea:9b:fa:2c:a2:11:d4: + a9:2d:27:1a:45:b1:af:b2:4e:71:0d:c0:58:46:d6:69:06:cb: + 53:cb:b3:fe:6b:41:cd:41:7e:7d:4c:0f:7c:72:79:7a:59:cd: + 5e:4a:0e:ac:9b:a9:98:73:79:7c:b4:f4:cc:b9:b8:07:0c:b2: + 74:5c:b8:c7:6f:88:a1:90:a7:f4:aa:f9:bf:67:3a:f4:1a:15: + 62:1e:b7:9f:be:3d:b1:29:af:67:a1:12:f2:58:10:19:53:03: + 30:1b:b8:1a:89:f6:9c:bd:97:03:8e:a3:09:f3:1d:8b:21:f1: + b4:df:e4:1c:d1:9f:65:02:06:ea:5c:d6:13:b3:84:ef:a2:a5: + 5c:8c:77:29:a7:68:c0:6b:ae:40:d2:a8:b4:ea:cd:f0:8d:4b: + 38:9c:19:9a:1b:28:54:b8:89:90:ef:ca:75:81:3e:1e:f2:64: + 24:c7:18:af:4e:ff:47:9e:07:f6:35:65:a4:d3:0a:56:ff:f5: + 17:64:6c:ef:a8:22:25:49:93:b6:df:00:17:da:58:7e:5d:ee: + c5:1b:b0:d1:d1:5f:21:10:c7:f9:f3:ba:02:0a:27:07:c5:f1: + d6:c7:d3:e0:fb:09:60:6c +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK +gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ +W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg +1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K +8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r +2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me +z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR +8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj +mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz +7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 ++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI +0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm +UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 +LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS +k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl +7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm +btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl +urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ +fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 +n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE +76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H +9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT +4PsJYGw= +-----END CERTIFICATE----- + +Amazon Root CA 3 +# Fingerprint (SHA1): 0D:44:DD:8C:3C:8C:1A:1A:58:75:64:81:E9:0F:2E:2A:FF:B3:D2:6E +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=A0:D4:EF:0B:F7:B5:D8:49:95:2A:EC:F5:C4:FC:81:87 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 06:6c:9f:d5:74:97:36:66:3f:3b:0b:9a:d9:e8:9e:76:03:f2:4a + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C=US, O=Amazon, CN=Amazon Root CA 3 + Validity + Not Before: May 26 00:00:00 2015 GMT + Not After : May 26 00:00:00 2040 GMT + Subject: C=US, O=Amazon, CN=Amazon Root CA 3 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:29:97:a7:c6:41:7f:c0:0d:9b:e8:01:1b:56:c6: + f2:52:a5:ba:2d:b2:12:e8:d2:2e:d7:fa:c9:c5:d8: + aa:6d:1f:73:81:3b:3b:98:6b:39:7c:33:a5:c5:4e: + 86:8e:80:17:68:62:45:57:7d:44:58:1d:b3:37:e5: + 67:08:eb:66:de + ASN1 OID: prime256v1 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + AB:B6:DB:D7:06:9E:37:AC:30:86:07:91:70:C7:9C:C4:19:B1:78:C0 + Signature Algorithm: ecdsa-with-SHA256 + 30:46:02:21:00:e0:85:92:a3:17:b7:8d:f9:2b:06:a5:93:ac: + 1a:98:68:61:72:fa:e1:a1:d0:fb:1c:78:60:a6:43:99:c5:b8: + c4:02:21:00:9c:02:ef:f1:94:9c:b3:96:f9:eb:c6:2a:f8:b6: + 2c:fe:3a:90:14:16:d7:8c:63:24:48:1c:df:30:7d:d5:68:3b +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl +ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr +ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr +BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM +YyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +Amazon Root CA 4 +# Fingerprint (SHA1): F6:10:84:07:D6:F8:BB:67:98:0C:C2:E2:44:C2:EB:AE:1C:EF:63:BE +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=89:BC:27:D5:EB:17:8D:06:6A:69:D5:FD:89:47:B4:CD +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 06:6c:9f:d7:c1:bb:10:4c:29:43:e5:71:7b:7b:2c:c8:1a:c1:0e + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=Amazon, CN=Amazon Root CA 4 + Validity + Not Before: May 26 00:00:00 2015 GMT + Not After : May 26 00:00:00 2040 GMT + Subject: C=US, O=Amazon, CN=Amazon Root CA 4 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:d2:ab:8a:37:4f:a3:53:0d:fe:c1:8a:7b:4b:a8: + 7b:46:4b:63:b0:62:f6:2d:1b:db:08:71:21:d2:00: + e8:63:bd:9a:27:fb:f0:39:6e:5d:ea:3d:a5:c9:81: + aa:a3:5b:20:98:45:5d:16:db:fd:e8:10:6d:e3:9c: + e0:e3:bd:5f:84:62:f3:70:64:33:a0:cb:24:2f:70: + ba:88:a1:2a:a0:75:f8:81:ae:62:06:c4:81:db:39: + 6e:29:b0:1e:fa:2e:5c + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + D3:EC:C7:3A:65:6E:CC:E1:DA:76:9A:56:FB:9C:F3:86:6D:57:E5:81 + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:30:3a:8b:21:f1:bd:7e:11:ad:d0:ef:58:96:2f:d6: + eb:9d:7e:90:8d:2b:cf:66:55:c3:2c:e3:28:a9:70:0a:47:0e: + f0:37:59:12:ff:2d:99:94:28:4e:2a:4f:35:4d:33:5a:02:31: + 00:ea:75:00:4e:3b:c4:3a:94:12:91:c9:58:46:9d:21:13:72: + a7:88:9c:8a:e4:4c:4a:db:96:d4:ac:8b:6b:6b:49:12:53:33: + ad:d7:e4:be:24:fc:b5:0a:76:d4:a5:bc:10 +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi +9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk +M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB +MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw +CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW +1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +LuxTrust Global Root 2 +# Fingerprint (SHA1): 1E:0E:56:19:0A:D1:8B:25:98:B2:04:44:FF:66:8A:04:17:99:5F:3F +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=B2:E1:09:00:61:AF:F7:F1:91:6F:C4:AD:8D:5E:3B:7C +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0a:7e:a6:df:4b:44:9e:da:6a:24:85:9e:e6:b8:15:d3:16:7f:bb:b1 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=LU, O=LuxTrust S.A., CN=LuxTrust Global Root 2 + Validity + Not Before: Mar 5 13:21:57 2015 GMT + Not After : Mar 5 13:21:57 2035 GMT + Subject: C=LU, O=LuxTrust S.A., CN=LuxTrust Global Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:d7:85:97:bf:11:98:e9:f0:62:83:4c:3c:87:f9: + 53:6a:37:0b:f2:0f:3c:87:ce:6f:dc:26:29:bd:c5: + 89:ba:c9:83:3d:f7:ee:ca:5b:c6:6d:49:73:b4:c9: + 46:a3:1b:34:13:3f:c1:89:45:57:f4:d9:b1:fb:36: + 65:4b:fb:08:e2:48:71:11:c8:6e:3b:9e:9d:df:89: + 65:37:a6:85:f6:3b:44:18:b6:c6:37:30:62:44:92: + 97:69:7d:42:30:24:e4:0d:0c:89:6b:63:de:c5:e1: + df:4e:a9:14:6c:53:e0:61:ce:f6:17:2f:1d:3c:bd: + e6:22:4c:1d:93:f5:10:c4:a1:76:ec:6a:de:c5:6c: + df:96:b4:56:40:42:c0:62:92:30:a1:2d:15:94:a0: + d2:20:06:09:6e:6a:6d:e5:eb:b7:be:d4:f0:f1:15: + 7c:8b:e6:4e:ba:13:cc:4b:27:5e:99:3c:17:5d:8f: + 81:7f:33:3d:4f:d3:3f:1b:ec:5c:3f:f0:3c:4c:75: + 6e:f2:a6:d5:9d:da:2d:07:63:02:c6:72:e9:94:bc: + 4c:49:95:4f:88:52:c8:db:e8:69:82:f8:cc:34:5b: + 22:f0:86:a7:89:bd:48:0a:6d:66:81:6d:c8:c8:64: + fb:01:e1:f4:e1:de:d9:9e:dd:db:5b:d4:2a:99:26: + 15:1b:1e:4c:92:29:82:9e:d5:92:81:92:41:70:19: + f7:a4:e5:93:4b:bc:77:67:31:dd:1c:fd:31:70:0d: + 17:99:0c:f9:0c:39:19:2a:17:b5:30:71:55:d5:0f: + ae:58:e1:3d:2f:34:9b:cf:9f:f6:78:85:c2:93:7a: + 72:3e:66:8f:9c:16:11:60:8f:9e:89:6f:67:be:e0: + 47:5a:3b:0c:9a:67:8b:cf:46:c6:ae:38:a3:f2:a7: + bc:e6:d6:85:6b:33:24:70:22:4b:cb:08:9b:bb:c8: + f8:02:29:1d:be:20:0c:46:bf:6b:87:9b:b3:2a:66: + 42:35:46:6c:aa:ba:ad:f9:98:7b:e9:50:55:14:31: + bf:b1:da:2d:ed:80:ad:68:24:fb:69:ab:d8:71:13: + 30:e6:67:b3:87:40:fd:89:7e:f2:43:d1:11:df:2f: + 65:2f:64:ce:5f:14:b9:b1:bf:31:bd:87:78:5a:59: + 65:88:aa:fc:59:32:48:86:d6:4c:b9:29:4b:95:d3: + 76:f3:77:25:6d:42:1c:38:83:4d:fd:a3:5f:9b:7f: + 2d:ac:79:1b:0e:42:31:97:63:a4:fb:8a:69:d5:22: + 0d:34:90:30:2e:a8:b4:e0:6d:b6:94:ac:bc:8b:4e: + d7:70:fc:c5:38:8e:64:25:e1:4d:39:90:ce:c9:87: + 84:58:71 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Certificate Policies: + Policy: 1.3.171.1.1.1.10 + CPS: https://repository.luxtrust.lu + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:FF:18:28:76:F9:48:05:2C:A1:AE:F1:2B:1B:2B:B2:53:F8:4B:7C:B3 + + X509v3 Subject Key Identifier: + FF:18:28:76:F9:48:05:2C:A1:AE:F1:2B:1B:2B:B2:53:F8:4B:7C:B3 + Signature Algorithm: sha256WithRSAEncryption + 6a:19:14:ed:6e:79:c1:2c:87:d4:0d:70:7e:d7:f6:78:c9:0b: + 04:4e:c4:b1:ce:93:70:fe:b0:54:c0:32:cd:99:30:64:17:bf: + 0f:e5:e2:33:fd:07:36:40:72:0e:1a:b6:6a:59:d6:00:e5:68: + 20:dd:2e:72:0d:1f:6a:64:31:20:84:7d:49:a6:5a:37:eb:45: + c9:85:f5:d4:c7:17:99:07:e6:9b:55:e4:0c:e8:a9:b4:ce:8c: + 5b:b5:11:5c:cf:8a:0e:0d:d6:ac:77:81:fe:32:9c:24:9e:72: + ce:54:f3:d0:6f:a2:56:d6:ec:c3:37:2c:65:58:be:57:00:1a: + f2:35:fa:eb:7b:31:5d:c2:c1:12:3d:96:81:88:96:89:c1:59: + 5c:7a:e6:7f:70:34:e7:83:e2:b1:e1:e1:b8:58:ef:d4:95:e4: + 60:9c:f0:96:97:72:8c:eb:84:02:2e:65:8f:a4:b7:d2:7f:67: + dd:c8:d3:9e:5c:aa:a9:a4:a0:25:14:06:9b:ec:4f:7e:2d:0b: + 7f:1d:75:f1:33:d8:ed:ce:b8:75:6d:3e:5b:b9:98:1d:31:0d: + 56:d8:43:0f:30:91:b2:04:6b:dd:56:be:95:80:55:67:be:d8: + cd:83:d9:18:ee:2e:0f:86:2d:92:9e:70:13:ec:de:51:c9:43: + 78:02:a5:4d:c8:f9:5f:c4:91:58:46:16:77:5a:74:aa:40:bc: + 07:9f:30:b9:b1:f7:12:17:dd:e3:ff:24:40:1d:7a:6a:d1:4f: + 18:0a:aa:90:1d:eb:40:1e:df:a1:1e:44:92:10:9a:f2:8d:e1: + d1:4b:46:9e:e8:45:42:97:ea:45:99:f3:ec:66:d5:02:fa:f2: + a6:4a:24:aa:de:ce:b9:ca:f9:3f:93:6f:f9:a3:ba:ea:a5:3e: + 99:ad:fd:ff:7b:99:f5:65:ee:f0:59:28:67:d7:90:95:a4:13: + 84:a9:84:c1:e8:ce:ce:75:93:63:1a:bc:3c:ea:d5:64:1f:2d: + 2a:12:39:c6:c3:5a:32:ed:47:91:16:0e:bc:38:c1:50:de:8f: + ca:2a:90:34:1c:ee:41:94:9c:5e:19:2e:f8:45:49:99:74:91: + b0:04:6f:e3:04:5a:b1:ab:2a:ab:fe:c7:d0:96:b6:da:e1:4a: + 64:06:6e:60:4d:bd:42:4e:ff:78:da:24:ca:1b:b4:d7:96:39: + 6c:ae:f1:0e:aa:a7:7d:48:8b:20:4c:cf:64:d6:b8:97:46:b0: + 4e:d1:2a:56:3a:a0:93:bd:af:80:24:e0:0a:7e:e7:ca:d5:ca: + e8:85:55:dc:36:2a:e1:94:68:93:c7:66:72:44:0f:80:21:32: + 6c:25:c7:23:80:83:0a:eb +-----BEGIN CERTIFICATE----- +MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQEL +BQAwRjELMAkGA1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNV +BAMMFkx1eFRydXN0IEdsb2JhbCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUw +MzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEWMBQGA1UECgwNTHV4VHJ1c3QgUy5B +LjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wmKb3F +ibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTem +hfY7RBi2xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1 +EMShduxq3sVs35a0VkBCwGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsn +Xpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4 +zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkmFRseTJIpgp7VkoGSQXAZ +96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niFwpN6cj5m +j5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4g +DEa/a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+ +8kPREd8vZS9kzl8UubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2j +X5t/Lax5Gw5CMZdjpPuKadUiDTSQMC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmH +hFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB/zBCBgNVHSAEOzA5MDcGByuB +KwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5Lmx1eHRydXN0 +Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT ++Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQEL +BQADggIBAGoZFO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9 +BzZAcg4atmpZ1gDlaCDdLnINH2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTO +jFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW7MM3LGVYvlcAGvI1+ut7MV3CwRI9 +loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIuZY+kt9J/Z93I055c +qqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWAVWe+ +2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/ +JEAdemrRTxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKre +zrnK+T+Tb/mjuuqlPpmt/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQf +LSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+ +x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31IiyBMz2TWuJdGsE7RKlY6 +oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr +-----END CERTIFICATE----- + +TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 +# Fingerprint (SHA1): 31:43:64:9B:EC:CE:27:EC:ED:3A:3F:0B:8F:0D:E4:E8:91:DD:EE:CA +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=DC:00:81:DC:69:2F:3E:2F:B0:3B:F6:3D:5A:91:8E:49 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=TR, L=Gebze - Kocaeli, O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK, OU=Kamu Sertifikasyon Merkezi - Kamu SM, CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 + Validity + Not Before: Nov 25 08:25:55 2013 GMT + Not After : Oct 25 08:25:55 2043 GMT + Subject: C=TR, L=Gebze - Kocaeli, O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK, OU=Kamu Sertifikasyon Merkezi - Kamu SM, CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:af:75:30:33:aa:bb:6b:d3:99:2c:12:37:84:d9: + 8d:7b:97:80:d3:6e:e7:ff:9b:50:95:3e:90:95:56: + 42:d7:19:7c:26:84:8d:92:fa:01:1d:3a:0f:e2:64: + 38:b7:8c:bc:e8:88:f9:8b:24:ab:2e:a3:f5:37:e4: + 40:8e:18:25:79:83:75:1f:3b:ff:6c:a8:c5:c6:56: + f8:b4:ed:8a:44:a3:ab:6c:4c:fc:1d:d0:dc:ef:68: + bd:cf:e4:aa:ce:f0:55:f7:a2:34:d4:83:6b:37:7c: + 1c:c2:fe:b5:03:ec:57:ce:bc:b4:b5:c5:ed:00:0f: + 53:37:2a:4d:f4:4f:0c:83:fb:86:cf:cb:fe:8c:4e: + bd:87:f9:a7:8b:21:57:9c:7a:df:03:67:89:2c:9d: + 97:61:a7:10:b8:55:90:7f:0e:2d:27:38:74:df:e7: + fd:da:4e:12:e3:4d:15:22:02:c8:e0:e0:fc:0f:ad: + 8a:d7:c9:54:50:cc:3b:0f:ca:16:80:84:d0:51:56: + c3:8e:56:7f:89:22:33:2f:e6:85:0a:bd:a5:a8:1b: + 36:de:d3:dc:2c:6d:3b:c7:13:bd:59:23:2c:e6:e5: + a4:f7:d8:0b:ed:ea:90:40:44:a8:95:bb:93:d5:d0: + 80:34:b6:46:78:0e:1f:00:93:46:e1:ee:e9:f9:ec: + 4f:17 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 65:3F:C7:8A:86:C6:3C:DD:3C:54:5C:35:F8:3A:ED:52:0C:47:57:C8 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 2a:3f:e1:f1:32:8e:ae:e1:98:5c:4b:5e:cf:6b:1e:6a:09:d2: + 22:a9:12:c7:5e:57:7d:73:56:64:80:84:7a:93:e4:09:b9:10: + cd:9f:2a:27:e1:00:77:be:48:c8:35:a8:81:9f:e4:b8:2c:c9: + 7f:0e:b0:d2:4b:37:5d:ea:b9:d5:0b:5e:34:bd:f4:73:29:c3: + ed:26:15:9c:7e:08:53:8a:58:8d:d0:4b:28:df:c1:b3:df:20: + f3:f9:e3:e3:3a:df:cc:9c:94:d8:4e:4f:c3:6b:17:b7:f7:72: + e8:ad:66:33:b5:25:53:ab:e0:f8:4c:a9:9d:fd:f2:0d:ba:ae: + b9:d9:aa:c6:6b:f9:93:bb:ae:ab:b8:97:3c:03:1a:ba:43:c6: + 96:b9:45:72:38:b3:a7:a1:96:3d:91:7b:7e:c0:21:53:4c:87: + ed:f2:0b:54:95:51:93:d5:22:a5:0d:8a:f1:93:0e:3e:54:0e: + b0:d8:c9:4e:dc:f2:31:32:56:ea:64:f9:ea:b5:9d:16:66:42: + 72:f3:7f:d3:b1:31:43:fc:a4:8e:17:f1:6d:23:ab:94:66:f8: + ad:fb:0f:08:6e:26:2d:7f:17:07:09:b2:8c:fb:50:c0:9f:96: + 8d:cf:b6:fd:00:9d:5a:14:9a:bf:02:44:f5:c1:c2:9f:22:5e: + a2:0f:a1:e3 +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx +GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp +bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w +KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 +BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy +dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG +EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll +IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU +QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT +TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg +LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 +a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr +LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr +N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X +YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ +iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f +AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH +V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf +IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 +lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c +8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf +lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- + +GDCA TrustAUTH R5 ROOT +# Fingerprint (SHA1): 0F:36:38:5B:81:1A:25:C3:9B:31:4E:83:CA:E9:34:66:70:CC:74:B4 +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=63:CC:D9:3D:34:35:5C:6F:53:A3:E2:08:70:48:1F:B4 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 9009899650740120186 (0x7d0997fef047ea7a) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=CN, O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD., CN=GDCA TrustAUTH R5 ROOT + Validity + Not Before: Nov 26 05:13:15 2014 GMT + Not After : Dec 31 15:59:59 2040 GMT + Subject: C=CN, O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD., CN=GDCA TrustAUTH R5 ROOT + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:d9:a3:16:f0:c8:74:74:77:9b:ef:33:0d:3b:06: + 7e:55:fc:b5:60:8f:76:86:12:42:7d:56:66:3e:88: + 82:ed:72:63:0e:9e:8b:dd:34:2c:02:51:51:c3:19: + fd:59:54:84:c9:f1:6b:b3:4c:b0:e9:e8:46:5d:38: + c6:a2:a7:2e:11:57:ba:82:15:a2:9c:8f:6d:b0:99: + 4a:0a:f2:eb:89:70:63:4e:79:c4:b7:5b:bd:a2:5d: + b1:f2:41:02:2b:ad:a9:3a:a3:ec:79:0a:ec:5f:3a: + e3:fd:ef:80:3c:ad:34:9b:1a:ab:88:26:7b:56:a2: + 82:86:1f:eb:35:89:83:7f:5f:ae:29:4e:3d:b6:6e: + ec:ae:c1:f0:27:9b:ae:e3:f4:ec:ef:ae:7f:f7:86: + 3d:72:7a:eb:a5:fb:59:4e:a7:eb:95:8c:22:39:79: + e1:2d:08:8f:cc:bc:91:b8:41:f7:14:c1:23:a9:c3: + ad:9a:45:44:b3:b2:d7:2c:cd:c6:29:e2:50:10:ae: + 5c:cb:82:8e:17:18:36:7d:97:e6:88:9a:b0:4d:34: + 09:f4:2c:b9:5a:66:2a:b0:17:9b:9e:1e:76:9d:4a: + 66:31:41:df:3f:fb:c5:06:ef:1b:b6:7e:1a:46:36: + f7:64:63:3b:e3:39:18:23:e7:67:75:14:d5:75:57: + 92:37:bd:be:6a:1b:26:50:f2:36:26:06:90:c5:70: + 01:64:6d:76:66:e1:91:db:6e:07:c0:61:80:2e:b2: + 2e:2f:8c:70:a7:d1:3b:3c:b3:91:e4:6e:b6:c4:3b: + 70:f2:6c:92:97:09:cd:47:7d:18:c0:f3:bb:9e:0f: + d6:8b:ae:07:b6:5a:0f:ce:0b:0c:47:a7:e5:3e:b8: + bd:7d:c7:9b:35:a0:61:97:3a:41:75:17:cc:2b:96: + 77:2a:92:21:1e:d9:95:76:20:67:68:cf:0d:bd:df: + d6:1f:09:6a:9a:e2:cc:73:71:a4:2f:7d:12:80:b7: + 53:30:46:5e:4b:54:99:0f:67:c9:a5:c8:f2:20:c1: + 82:ec:9d:11:df:c2:02:fb:1a:3b:d1:ed:20:9a:ef: + 65:64:92:10:0d:2a:e2:de:70:f1:18:67:82:8c:61: + de:b8:bc:d1:2f:9c:fb:0f:d0:2b:ed:1b:76:b9:e4: + 39:55:f8:f8:a1:1d:b8:aa:80:00:4c:82:e7:b2:7f: + 09:b8:bc:30:a0:2f:0d:f5:52:9e:8e:f7:92:b3:0a: + 00:1d:00:54:97:06:e0:b1:07:d9:c7:0f:5c:65:7d: + 3c:6d:59:57:e4:ed:a5:8d:e9:40:53:9f:15:4b:a0: + 71:f6:1a:21:e3:da:70:06:21:58:14:87:85:77:79: + aa:82:79 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + E2:C9:40:9F:4D:CE:E8:9A:A1:7C:CF:0E:3F:65:C5:29:88:6A:19:51 + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + d1:49:57:e0:a7:cc:68:58:ba:01:0f:2b:19:cd:8d:b0:61:45: + ac:11:ed:63:50:69:f8:1f:7f:be:16:8f:fd:9d:eb:0b:aa:32: + 47:76:d2:67:24:ed:bd:7c:33:32:97:2a:c7:05:86:66:0d:17: + 7d:14:15:1b:d4:eb:fd:1f:9a:f6:5e:97:69:b7:1a:25:a4:0a: + b3:91:3f:5f:36:ac:8b:ec:57:a8:3e:e7:81:8a:18:57:39:85: + 74:1a:42:c7:e9:5b:13:5f:8f:f9:08:e9:92:74:8d:f5:47:d2: + ab:3b:d6:fb:78:66:4e:36:7d:f9:e9:92:e9:04:de:fd:49:63: + fc:6d:fb:14:71:93:67:2f:47:4a:b7:b9:ff:1e:2a:73:70:46: + 30:bf:5a:f2:2f:79:a5:e1:8d:0c:d9:f9:b2:63:37:8c:37:65: + 85:70:6a:5c:5b:09:72:b9:ad:63:3c:b1:dd:f8:fc:32:bf:37: + 86:e4:bb:8e:98:27:7e:ba:1f:16:e1:70:11:f2:03:df:25:62: + 32:27:26:18:32:84:9f:ff:00:3a:13:ba:9a:4d:f4:4f:b8:14: + 70:22:b1:ca:2b:90:ce:29:c1:70:f4:2f:9d:7f:f2:90:1e:d6: + 5a:df:b7:46:fc:e6:86:fa:cb:e0:20:76:7a:ba:a6:cb:f5:7c: + de:62:a5:b1:8b:ee:de:82:66:8a:4e:3a:30:1f:3f:80:cb:ad: + 27:ba:0c:5e:d7:d0:b1:56:ca:77:71:b2:b5:75:a1:50:a9:40: + 43:17:c2:28:d9:cf:52:8b:5b:c8:63:d4:42:3e:a0:33:7a:46: + 2e:f7:0a:20:46:54:7e:6a:4f:31:f1:81:7e:42:74:38:65:73: + 27:ee:c6:7c:b8:8e:d7:a5:3a:d7:98:a1:9c:8c:10:55:d3:db: + 4b:ec:40:90:f2:cd:6e:57:d2:62:0e:7c:57:93:b1:a7:6d:cd: + 9d:83:bb:2a:e7:e5:b6:3b:71:58:ad:fd:d1:45:bc:5a:91:ee: + 53:15:6f:d3:45:09:75:6e:ba:90:5d:1e:04:cf:37:df:1e:a8: + 66:b1:8c:e6:20:6a:ef:fc:48:4e:74:98:42:af:29:6f:2e:6a: + c7:fb:7d:d1:66:31:22:cc:86:00:7e:66:83:0c:42:f4:bd:34: + 92:c3:1a:ea:4f:ca:7e:72:4d:0b:70:8c:a6:48:bb:a6:a1:14: + f6:fb:58:44:99:14:ae:aa:0b:93:69:a0:29:25:4a:a5:cb:2b: + dd:8a:66:07:16:78:15:57:71:1b:ec:f5:47:84:f3:9e:31:37: + 7a:d5:7f:24:ad:e4:bc:fd:fd:cc:6e:83:e8:0c:a8:b7:41:6c: + 07:dd:bd:3c:86:97:2f:d2 +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE +BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 +MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV +BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w +HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj +Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj +TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u +KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj +qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm +MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 +ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP +zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk +L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC +jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA +HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC +AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm +DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 +COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry +L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf +JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg +IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io +2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV +09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ +XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq +T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe +MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- + +TrustCor RootCert CA-1 +# Fingerprint (SHA1): FF:BD:CD:E7:82:C8:43:5E:3C:6F:26:86:5C:CA:A8:3A:45:5B:C3:0A +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=6E:85:F1:DC:1A:00:D3:22:D5:B2:B2:AC:6B:37:05:45 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + da:9b:ec:71:f3:03:b0:19 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=PA, ST=Panama, L=Panama City, O=TrustCor Systems S. de R.L., OU=TrustCor Certificate Authority, CN=TrustCor RootCert CA-1 + Validity + Not Before: Feb 4 12:32:16 2016 GMT + Not After : Dec 31 17:23:16 2029 GMT + Subject: C=PA, ST=Panama, L=Panama City, O=TrustCor Systems S. de R.L., OU=TrustCor Certificate Authority, CN=TrustCor RootCert CA-1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:bf:8e:b7:95:e2:c2:26:12:6b:33:19:c7:40:58: + 0a:ab:59:aa:8d:00:a3:fc:80:c7:50:7b:8e:d4:20: + 26:ba:32:12:d8:23:54:49:25:10:22:98:9d:46:d2: + c1:c9:9e:4e:1b:2e:2c:0e:38:f3:1a:25:68:1c:a6: + 5a:05:e6:1e:8b:48:bf:98:96:74:3e:69:ca:e9:b5: + 78:a5:06:bc:d5:00:5e:09:0a:f2:27:7a:52:fc:2d: + d5:b1:ea:b4:89:61:24:f3:1a:13:db:a9:cf:52:ed: + 0c:24:ba:b9:9e:ec:7e:00:74:fa:93:ad:6c:29:92: + ae:51:b4:bb:d3:57:bf:b3:f3:a8:8d:9c:f4:24:4b: + 2a:d6:99:9e:f4:9e:fe:c0:7e:42:3a:e7:0b:95:53: + da:b7:68:0e:90:4c:fb:70:3f:8f:4a:2c:94:f3:26: + dd:63:69:a9:94:d8:10:4e:c5:47:08:90:99:1b:17: + 4d:b9:6c:6e:ef:60:95:11:8e:21:80:b5:bd:a0:73: + d8:d0:b2:77:c4:45:ea:5a:26:fb:66:76:76:f8:06: + 1f:61:6d:0f:55:c5:83:b7:10:56:72:06:07:a5:f3: + b1:1a:03:05:64:0e:9d:5a:8a:d6:86:70:1b:24:de: + fe:28:8a:2b:d0:6a:b0:fc:7a:a2:dc:b2:79:0e:8b: + 65:0f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EE:6B:49:3C:7A:3F:0D:E3:B1:09:B7:8A:C8:AB:19:9F:73:33:50:E7 + X509v3 Authority Key Identifier: + keyid:EE:6B:49:3C:7A:3F:0D:E3:B1:09:B7:8A:C8:AB:19:9F:73:33:50:E7 + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 25:18:d4:91:8f:13:ee:8f:1e:1d:11:53:da:2d:44:29:19:a0: + 1e:6b:31:9e:4d:0e:9e:ad:3d:5c:41:6f:95:2b:24:a1:79:98: + 3a:38:36:fb:bb:66:9e:48:ff:90:90:ef:3d:d4:b8:9b:b4:87: + 75:3f:20:9b:ce:72:cf:a1:55:c1:4d:64:a2:19:06:a1:07:33: + 0c:0b:29:e5:f1:ea:ab:a3:ec:b5:0a:74:90:c7:7d:72:f2:d7: + 5c:9f:91:ef:91:8b:b7:dc:ed:66:a2:cf:8e:66:3b:bc:9f:3a: + 02:e0:27:dd:16:98:c0:95:d4:0a:a4:e4:81:9a:75:94:35:9c: + 90:5f:88:37:06:ad:59:95:0a:b0:d1:67:d3:19:ca:89:e7:32: + 5a:36:1c:3e:82:a8:5a:93:be:c6:d0:64:91:b6:cf:d9:b6:18: + cf:db:7e:d2:65:a3:a6:c4:8e:17:31:c1:fb:7e:76:db:d3:85: + e3:58:b2:77:7a:76:3b:6c:2f:50:1c:e7:db:f6:67:79:1f:f5: + 82:95:9a:07:a7:14:af:8f:dc:28:21:67:09:d2:d6:4d:5a:1c: + 19:1c:8e:77:5c:c3:94:24:3d:32:6b:4b:7e:d4:78:94:83:be: + 37:4d:ce:5f:c7:1e:4e:3c:e0:89:33:95:0b:0f:a5:32:d6:3c: + 5a:79:2c:19 +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y +IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB +pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h +IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG +A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU +cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid +RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V +seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme +9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV +EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW +hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/ +DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD +ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I +/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf +ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ +yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts +L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN +zl/HHk484IkzlQsPpTLWPFp5LBk= +-----END CERTIFICATE----- + +TrustCor RootCert CA-2 +# Fingerprint (SHA1): B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=A2:E1:F8:18:0B:BA:45:D5:C7:41:2A:BB:37:52:45:64 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2711694510199101698 (0x25a1dfca33cb5902) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=PA, ST=Panama, L=Panama City, O=TrustCor Systems S. de R.L., OU=TrustCor Certificate Authority, CN=TrustCor RootCert CA-2 + Validity + Not Before: Feb 4 12:32:23 2016 GMT + Not After : Dec 31 17:26:39 2034 GMT + Subject: C=PA, ST=Panama, L=Panama City, O=TrustCor Systems S. de R.L., OU=TrustCor Certificate Authority, CN=TrustCor RootCert CA-2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:a7:20:6e:c2:2a:a2:62:24:95:90:76:c8:38:7e: + 80:d2:ab:c1:9b:65:05:94:f4:c1:0a:10:d5:02:ac: + ed:9f:93:c7:87:c8:b0:27:2b:42:0c:3d:0a:3e:41: + 5a:9e:75:dd:8d:ca:e0:9b:ec:68:32:a4:69:92:68: + 8c:0b:81:0e:56:a0:3e:1a:dd:2c:25:14:82:2f:97: + d3:64:46:f4:54:a9:dc:3a:54:2d:31:2b:99:82:f2: + d9:2a:d7:ef:71:00:b8:31:a4:be:7a:24:07:c3:42: + 20:f2:8a:d4:92:04:1b:65:56:4c:6c:d4:fb:b6:61: + 5a:47:23:b4:d8:69:b4:b7:3a:d0:74:3c:0c:75:a1: + 8c:4e:76:a1:e9:db:2a:a5:3b:fa:ce:b0:ff:7e:6a: + 28:fd:27:1c:c8:b1:e9:29:f1:57:6e:64:b4:d0:c1: + 15:6d:0e:be:2e:0e:46:c8:5e:f4:51:fe:ef:0e:63: + 3a:3b:71:ba:cf:6f:59:ca:0c:e3:9b:5d:49:b8:4c: + e2:57:b1:98:8a:42:57:9c:76:ef:ef:bd:d1:68:a8: + d2:f4:09:bb:77:35:be:25:82:08:c4:16:2c:44:20: + 56:a9:44:11:77:ef:5d:b4:1d:aa:5e:6b:3e:8b:32: + f6:07:2f:57:04:92:ca:f5:fe:9d:c2:e9:e8:b3:8e: + 4c:4b:02:31:d9:e4:3c:48:82:27:f7:18:82:76:48: + 3a:71:b1:13:a1:39:d5:2e:c5:34:c2:1d:62:85:df: + 03:fe:4d:f4:af:3d:df:5c:5b:8d:fa:70:e1:a5:7e: + 27:c7:86:2e:6a:8f:12:c6:84:5e:43:51:50:9c:19: + 9b:78:e6:fc:f6:ed:47:7e:7b:3d:66:ef:13:13:88: + 5f:3c:a1:63:fb:f9:ac:87:35:9f:f3:82:9e:a4:3f: + 0a:9c:31:69:8b:99:a4:88:4a:8e:6e:66:4d:ef:16: + c4:0f:79:28:21:60:0d:85:16:7d:d7:54:38:f1:92: + 56:fd:b5:33:4c:83:dc:d7:10:9f:4b:fd:c6:f8:42: + bd:ba:7c:73:02:e0:ff:7d:cd:5b:e1:d4:ac:61:7b: + 57:d5:4a:7b:5b:d4:85:58:27:5d:bf:f8:2b:60:ac: + a0:26:ae:14:21:27:c6:77:9a:33:80:3c:5e:46:3f: + f7:c3:b1:a3:86:33:c6:e8:5e:0d:b9:35:2c:aa:46: + c1:85:02:75:80:a0:eb:24:fb:15:aa:e4:67:7f:6e: + 77:3f:f4:04:8a:2f:7c:7b:e3:17:61:f0:dd:09:a9: + 20:c8:be:09:a4:d0:7e:44:c3:b2:30:4a:38:aa:a9: + ec:18:9a:07:82:2b:db:b8:9c:18:ad:da:e0:46:17: + ac:cf:5d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D9:FE:21:40:6E:94:9E:BC:9B:3D:9C:7D:98:20:19:E5:8C:30:62:B2 + X509v3 Authority Key Identifier: + keyid:D9:FE:21:40:6E:94:9E:BC:9B:3D:9C:7D:98:20:19:E5:8C:30:62:B2 + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 9e:45:9e:0c:3b:b6:ef:e1:3a:c8:7c:d1:00:3d:cf:e2:ea:06: + b5:b2:3a:bb:06:4b:68:7a:d0:23:97:74:a7:2c:f0:08:d8:79: + 5a:d7:5a:84:8a:d8:12:9a:1b:d9:7d:5c:4d:70:c5:a5:f9:ab: + e5:a3:89:89:dd:01:fa:ec:dd:f9:e9:92:97:db:b0:46:42:f3: + d3:62:aa:95:fe:31:67:14:69:58:90:0a:aa:0b:ee:37:23:c7: + 50:51:b4:f5:7e:9e:e3:7b:f7:e4:cc:42:32:2d:49:0c:cb:ff: + 49:0c:9b:1e:34:fd:6e:6e:96:8a:79:03:b6:6f:db:09:cb:fd: + 5f:65:14:37:e1:38:f5:f3:61:16:58:e4:b5:6d:0d:0b:04:1b: + 3f:50:2d:7f:b3:c7:7a:1a:16:80:60:f8:8a:1f:e9:1b:2a:c6: + f9:ba:01:1a:69:bf:d2:58:c7:54:57:08:8f:e1:39:60:77:4b: + ac:59:84:1a:88:f1:dd:cb:4f:78:d7:e7:e1:33:2d:fc:ee:41: + fa:20:b0:be:cb:f7:38:94:c0:e1:d0:85:0f:bb:ed:2c:73:ab: + ed:fe:92:76:1a:64:7f:5b:0d:33:09:07:33:7b:06:3f:11:a4: + 5c:70:3c:85:c0:cf:e3:90:a8:83:77:fa:db:e6:c5:8c:68:67: + 10:67:a5:52:2d:f0:c4:99:8f:7f:bf:d1:6b:e2:b5:47:d6:d9: + d0:85:99:4d:94:9b:0f:4b:8d:ee:00:5a:47:1d:11:03:ac:41: + 18:af:87:b7:6f:0c:3a:8f:ca:cf:dc:03:c1:a2:09:c8:e5:fd: + 80:5e:c8:60:42:01:1b:1a:53:5a:bb:37:a6:b7:bc:ba:84:e9: + 1e:6c:1a:d4:64:da:d4:43:fe:93:8b:4b:f2:2c:79:16:10:d4: + 93:0b:88:8f:a1:d8:86:14:46:91:47:9b:28:24:ef:57:52:4e: + 5c:42:9c:aa:f7:49:ec:27:e8:40:1e:b3:a6:89:22:72:9c:f5: + 0d:33:b4:58:a3:30:3b:dd:d4:6a:54:93:be:1a:4d:f3:93:94: + f7:fc:84:0b:3f:84:20:5c:34:03:44:c5:da:ad:bc:0a:c1:02: + cf:1e:e5:94:d9:f3:8e:5b:d8:4c:f0:9d:ec:61:17:bb:14:32: + 54:0c:02:29:93:1e:92:86:f6:7f:ef:e7:92:05:0e:59:dd:99: + 08:2e:2e:fa:9c:00:52:d3:c5:66:29:e4:a7:97:44:a4:0e:28: + 81:13:35:c5:f6:6f:64:e6:41:c4:d5:2f:cc:34:45:25:cf:41: + 00:96:3d:4a:2e:c2:96:98:4f:4e:4a:9c:97:b7:db:1f:92:32: + c8:ff:0f:51:6e:d6:ec:09 +-----BEGIN CERTIFICATE----- +MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig +Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk +MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg +Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD +VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy +dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ +QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq +1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp +2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK +DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape +az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF +3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 +oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM +g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 +mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh +8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd +BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U +nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw +DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX +dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ +MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL +/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX +CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa +ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW +2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 +N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 +Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB +As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp +5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu +1uwJ +-----END CERTIFICATE----- + +TrustCor ECA-1 +# Fingerprint (SHA1): 58:D1:DF:95:95:67:6B:63:C0:F0:5B:1C:17:4D:8B:84:0B:C8:78:BD +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=27:92:23:1D:0A:F5:40:7C:E9:E6:6B:9D:D8:F5:E7:6C +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 84:82:2c:5f:1c:62:d0:40 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=PA, ST=Panama, L=Panama City, O=TrustCor Systems S. de R.L., OU=TrustCor Certificate Authority, CN=TrustCor ECA-1 + Validity + Not Before: Feb 4 12:32:33 2016 GMT + Not After : Dec 31 17:28:07 2029 GMT + Subject: C=PA, ST=Panama, L=Panama City, O=TrustCor Systems S. de R.L., OU=TrustCor Certificate Authority, CN=TrustCor ECA-1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:cf:8f:e0:11:b5:9f:a8:76:76:db:df:0f:54:ef: + 73:63:29:82:ad:47:c6:a3:6b:ed:fe:5f:33:f8:43: + 51:e9:1a:33:91:31:17:a0:74:c4:d4:a7:01:e6:b2: + 92:3e:6a:9d:ed:0e:f9:74:98:40:d3:3f:03:80:06: + 82:40:e8:b1:e2:a7:51:a7:1d:83:26:6b:ab:de:fa: + 17:91:2b:d8:c6:ac:1e:b1:9e:19:01:d5:97:a6:ea: + 0d:b7:c4:55:1f:27:7c:d2:08:d5:76:1f:29:15:87: + 40:39:dd:38:45:11:75:d0:9a:a7:34:e0:bf:cd:c8: + 52:1d:b9:47:7e:0d:b8:bb:c6:0c:f6:73:57:16:5a: + 7e:43:91:1f:55:3a:c6:6d:44:04:aa:9c:a9:9c:a7: + 4c:89:17:83:ae:a3:04:5e:52:80:8b:1e:12:25:11: + 19:d7:0c:7d:7d:31:44:41:ea:db:af:b0:1c:ef:81: + d0:2c:c5:9a:21:9b:3d:ed:42:3b:50:26:f2:ec:ce: + 71:61:06:62:21:54:4e:7f:c1:9d:3e:7f:20:8c:80: + cb:2a:d8:97:62:c8:83:33:91:7d:b0:a2:5a:0f:57: + e8:3b:cc:f2:25:b2:d4:7c:2f:ec:4d:c6:a1:3a:15: + 7a:e7:b6:5d:35:f5:f6:48:4a:36:45:66:d4:ba:98: + 58:c1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 44:9E:48:F5:CC:6D:48:D4:A0:4B:7F:FE:59:24:2F:83:97:99:9A:86 + X509v3 Authority Key Identifier: + keyid:44:9E:48:F5:CC:6D:48:D4:A0:4B:7F:FE:59:24:2F:83:97:99:9A:86 + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 05:3e:35:5c:15:70:9b:c9:c7:73:61:6f:72:2b:d4:c2:8f:f2: + 43:5d:02:ce:c4:94:b9:94:11:83:67:5d:e2:67:6c:75:76:bf: + bb:0c:aa:36:c6:ad:47:93:63:dc:1e:7e:d6:de:2e:fe:e9:19: + 32:38:03:7f:14:f6:00:73:2c:59:b1:21:06:e1:fb:ac:18:95: + 0c:a3:ff:99:96:f7:2b:27:9b:d5:24:cc:1d:dd:c1:3a:e0:98: + 44:b0:c4:e4:3e:77:b1:73:a9:64:2c:f6:1c:01:7c:3f:5d:45: + 85:c0:85:e7:25:8f:95:dc:17:f3:3c:9f:1a:6e:b0:ca:e3:1d: + 2a:e9:4c:63:fa:24:61:62:d6:da:7e:b6:1c:6c:f5:02:1d:d4: + 2a:dd:55:90:eb:2a:11:47:3c:2e:5e:74:b2:82:22:a5:7d:53: + 1f:45:ec:27:91:7d:e7:22:16:e8:c0:68:36:d8:c6:f1:4f:80: + 44:32:f9:e1:d1:d1:1d:aa:de:a8:ab:9c:04:af:ad:20:0e:64: + 98:4d:a5:6b:c0:48:58:96:69:4d:dc:07:8c:51:93:a2:df:9f: + 0f:3d:8b:60:b4:82:8d:aa:08:4e:62:45:e0:f9:0b:d2:e0:e0: + 3c:5b:de:5c:71:27:25:c2:e6:03:81:8b:10:53:e3:c7:55:a2: + b4:9f:d7:e6 +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y +IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig +RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb +3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA +BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5 +3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou +owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/ +wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF +ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf +BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv +civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2 +AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F +hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50 +soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI +WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi +tJ/X5g== +-----END CERTIFICATE----- + +SSL.com Root Certification Authority RSA +# Fingerprint (SHA1): B7:AB:33:08:D1:EA:44:77:BA:14:80:12:5A:6F:BD:A9:36:49:0C:BB +MUST_VERIFY_TRUST: CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +================================================ +MD5 Fingerprint=86:69:12:C0:70:F1:EC:AC:AC:C2:D5:BC:A5:5B:A1:29 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8875640296558310041 (0x7b2c9bd316803299) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com Root Certification Authority RSA + Validity + Not Before: Feb 12 17:39:39 2016 GMT + Not After : Feb 12 17:39:39 2041 GMT + Subject: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com Root Certification Authority RSA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:f9:0f:dd:a3:2b:7d:cb:d0:2a:fe:ec:67:85:a6: + e7:2e:1b:ba:77:e1:e3:f5:af:a4:ec:fa:4a:5d:91: + c4:57:47:6b:18:77:6b:76:f2:fd:93:e4:3d:0f:c2: + 16:9e:0b:66:c3:56:94:9e:17:83:85:ce:56:ef:f2: + 16:fd:00:62:f5:22:09:54:e8:65:17:4e:41:b9:e0: + 4f:46:97:aa:1b:c8:b8:6e:62:5e:69:b1:5f:db:2a: + 02:7e:fc:6c:ca:f3:41:d8:ed:d0:e8:fc:3f:61:48: + ed:b0:03:14:1d:10:0e:4b:19:e0:bb:4e:ec:86:65: + ff:36:f3:5e:67:02:0b:9d:86:55:61:fd:7a:38:ed: + fe:e2:19:00:b7:6f:a1:50:62:75:74:3c:a0:fa:c8: + 25:92:b4:6e:7a:22:c7:f8:1e:a1:e3:b2:dd:91:31: + ab:2b:1d:04:ff:a5:4a:04:37:e9:85:a4:33:2b:fd: + e2:d6:55:34:7c:19:a4:4a:68:c7:b2:a8:d3:b7:ca: + a1:93:88:eb:c1:97:bc:8c:f9:1d:d9:22:84:24:74: + c7:04:3d:6a:a9:29:93:cc:eb:b8:5b:e1:fe:5f:25: + aa:34:58:c8:c1:23:54:9d:1b:98:11:c3:38:9c:7e: + 3d:86:6c:a5:0f:40:86:7c:02:f4:5c:02:4f:28:cb: + ae:71:9f:0f:3a:c8:33:fe:11:25:35:ea:fc:ba:c5: + 60:3d:d9:7c:18:d5:b2:a9:d3:75:78:03:72:22:ca: + 3a:c3:1f:ef:2c:e5:2e:a9:fa:9e:2c:b6:51:46:fd: + af:03:d6:ea:60:68:ea:85:16:36:6b:85:e9:1e:c0: + b3:dd:c4:24:dc:80:2a:81:41:6d:94:3e:c8:e0:c9: + 81:41:00:9e:5e:bf:7f:c5:08:98:a2:18:2c:42:40: + b3:f9:6f:38:27:4b:4e:80:f4:3d:81:47:e0:88:7c: + ea:1c:ce:b5:75:5c:51:2e:1c:2b:7f:1a:72:28:e7: + 00:b5:d1:74:c6:d7:e4:9f:ad:07:93:b6:53:35:35: + fc:37:e4:c3:f6:5d:16:be:21:73:de:92:0a:f8:a0: + 63:6a:bc:96:92:6a:3e:f8:bc:65:55:9b:de:f5:0d: + 89:26:04:fc:25:1a:a6:25:69:cb:c2:6d:ca:7c:e2: + 59:5f:97:ac:eb:ef:2e:c8:bc:d7:1b:59:3c:2b:cc: + f2:19:c8:93:6b:27:63:19:cf:fc:e9:26:f8:ca:71: + 9b:7f:93:fe:34:67:84:4e:99:eb:fc:b3:78:09:33: + 70:ba:66:a6:76:ed:1b:73:eb:1a:a5:0d:c4:22:13: + 20:94:56:0a:4e:2c:6c:4e:b1:fd:cf:9c:09:ba:a2: + 33:ed:87 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + DD:04:09:07:A2:F5:7A:7D:52:53:12:92:95:EE:38:80:25:0D:A6:59 + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:DD:04:09:07:A2:F5:7A:7D:52:53:12:92:95:EE:38:80:25:0D:A6:59 + + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 20:18:11:94:29:fb:26:9d:1c:1e:1e:70:61:f1:95:72:93:71: + 24:ad:68:93:58:8e:32:af:1b:b3:70:03:fc:25:2b:74:85:90: + 3d:78:6a:f4:b9:8b:a5:97:3b:b5:18:91:bb:1e:a7:f9:40:5b: + 91:f9:55:99:af:1e:11:d0:5c:1d:a7:66:e3:b1:94:07:0c:32: + 39:a6:ea:1b:b0:79:d8:1d:9c:70:44:e3:8a:dd:c4:f9:95:1f: + 8a:38:43:3f:01:85:a5:47:a7:3d:46:b2:bc:e5:22:68:f7:7b: + 9c:d8:2c:3e:0a:21:c8:2d:33:ac:bf:c5:81:99:31:74:c1:75: + 71:c5:be:b1:f0:23:45:f4:9d:6b:fc:19:63:9d:a3:bc:04:c6: + 18:0b:25:bb:53:89:0f:b3:80:50:de:45:ee:44:7f:ab:94:78: + 64:98:d3:f6:28:dd:87:d8:70:65:74:fb:0e:b9:13:eb:a7:0f: + 61:a9:32:96:cc:de:bb:ed:63:4c:18:bb:a9:40:f7:a0:54:6e: + 20:88:71:75:18:ea:7a:b4:34:72:e0:23:27:77:5c:b6:90:ea: + 86:25:40:ab:ef:33:0f:cb:9f:82:be:a2:20:fb:f6:b5:2d:1a: + e6:c2:85:b1:74:0f:fb:c8:65:02:a4:52:01:47:dd:49:22:c1: + bf:d8:eb:6b:ac:7e:de:ec:63:33:15:b7:23:08:8f:c6:0f:8d: + 41:5a:dd:8e:c5:b9:8f:e5:45:3f:78:db:ba:d2:1b:40:b1:fe: + 71:4d:3f:e0:81:a2:ba:5e:b4:ec:15:e0:93:dd:08:1f:7e:e1: + 55:99:0b:21:de:93:9e:0a:fb:e6:a3:49:bd:36:30:fe:e7:77: + b2:a0:75:97:b5:2d:81:88:17:65:20:f7:da:90:00:9f:c9:52: + cc:32:ca:35:7c:f5:3d:0f:d8:2b:d7:f5:26:6c:c9:06:34:96: + 16:ea:70:59:1a:32:79:79:0b:b6:88:7f:0f:52:48:3d:bf:6c: + d8:a2:44:2e:d1:4e:b7:72:58:d3:89:13:95:fe:44:ab:f8:d7: + 8b:1b:6e:9c:bc:2c:a0:5b:d5:6a:00:af:5f:37:e1:d5:fa:10: + 0b:98:9c:86:e7:26:8f:ce:f0:ec:6e:8a:57:0b:80:e3:4e:b2: + c0:a0:63:61:90:ba:55:68:37:74:6a:b6:92:db:9f:a1:86:22: + b6:65:27:0e:ec:b6:9f:42:60:e4:67:c2:b5:da:41:0b:c4:d3: + 8b:61:1b:bc:fa:1f:91:2b:d7:44:07:5e:ba:29:ac:d9:c5:e9: + ef:53:48:5a:eb:80:f1:28:58:21:cd:b0:06:55:fb:27:3f:53: + 90:70:a9:04:1e:57:27:b9 +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE +BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK +DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz +OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R +xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX +qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC +C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 +6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh +/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF +YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E +JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc +US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 +ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm ++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi +M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G +A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV +cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc +Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs +PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ +q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 +cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr +a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I +H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y +K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu +nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf +oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY +Ic2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- + +SSL.com Root Certification Authority ECC +# Fingerprint (SHA1): C3:19:7C:39:24:E6:54:AF:1B:C4:AB:20:95:7A:E2:C3:0E:13:02:6A +TRUSTED_DELEGATOR: SERVER_AUTH, EMAIL_PROTECTION +MUST_VERIFY_TRUST: CODE_SIGNING +================================================ +MD5 Fingerprint=2E:DA:E4:39:7F:9C:8F:37:D1:70:9F:26:17:51:3A:8E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8495723813297216424 (0x75e6dfcbc1685ba8) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com Root Certification Authority ECC + Validity + Not Before: Feb 12 18:14:03 2016 GMT + Not After : Feb 12 18:14:03 2041 GMT + Subject: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com Root Certification Authority ECC + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:45:6e:a9:50:c4:a6:23:36:9e:5f:28:8d:17:cb: + 96:22:64:3f:dc:7a:8e:1d:cc:08:b3:a2:71:24:ba: + 8e:49:b9:04:1b:47:96:58:ab:2d:95:c8:ed:9e:08: + 35:c8:27:eb:89:8c:53:58:eb:62:8a:fe:f0:5b:0f: + 6b:31:52:63:41:3b:89:cd:ec:ec:b6:8d:19:d3:34: + 07:dc:bb:c6:06:7f:c2:45:95:ec:cb:7f:a8:23:e0: + 09:e9:81:fa:f3:47:d3 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Subject Key Identifier: + 82:D1:85:73:30:E7:35:04:D3:8E:02:92:FB:E5:A4:D1:C4:21:E8:CD + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:82:D1:85:73:30:E7:35:04:D3:8E:02:92:FB:E5:A4:D1:C4:21:E8:CD + + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: ecdsa-with-SHA256 + 30:64:02:30:6f:e7:eb:59:11:a4:60:cf:61:b0:96:7b:ed:05: + f9:2f:13:91:dc:ed:e5:fc:50:6b:11:46:46:b3:1c:21:00:62: + bb:be:c3:e7:e8:cd:07:99:f9:0d:0b:5d:72:3e:c4:aa:02:30: + 1f:bc:ba:0b:e2:30:24:fb:7c:6d:80:55:0a:99:3e:80:0d:33: + e5:66:a3:b3:a3:bb:a5:d5:8b:8f:09:2c:a6:5d:7e:e2:f0:07: + 08:68:6d:d2:7c:69:6e:5f:df:e5:6a:65 +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz +WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 +b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS +b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI +7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg +CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD +VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T +kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ +gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority RSA R2 +# Fingerprint (SHA1): 74:3A:F0:52:9B:D0:32:A0:F4:4A:83:CD:D4:BA:A9:7B:7C:2E:C4:9A +TRUSTED_DELEGATOR: SERVER_AUTH +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +================================================= +MD5 Fingerprint=E1:1E:31:58:1A:AE:54:53:02:F6:17:6A:11:7B:4D:95 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 6248227494352943350 (0x56b629cd34bc78f6) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com EV Root Certification Authority RSA R2 + Validity + Not Before: May 31 18:14:37 2017 GMT + Not After : May 30 18:14:37 2042 GMT + Subject: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com EV Root Certification Authority RSA R2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:8f:36:65:40:e1:d6:4d:c0:d7:b4:e9:46:da:6b: + ea:33:47:cd:4c:f9:7d:7d:be:bd:2d:3d:f0:db:78: + e1:86:a5:d9:ba:09:57:68:ed:57:3e:a0:d0:08:41: + 83:e7:28:41:24:1f:e3:72:15:d0:01:1a:fb:5e:70: + 23:b2:cb:9f:39:e3:cf:c5:4e:c6:92:6d:26:c6:7b: + bb:b3:da:27:9d:0a:86:e9:81:37:05:fe:f0:71:71: + ec:c3:1c:e9:63:a2:17:14:9d:ef:1b:67:d3:85:55: + 02:02:d6:49:c9:cc:5a:e1:b1:f7:6f:32:9f:c9:d4: + 3b:88:41:a8:9c:bd:cb:ab:db:6d:7b:09:1f:a2:4c: + 72:90:da:2b:08:fc:cf:3c:54:ce:67:0f:a8:cf:5d: + 96:19:0b:c4:e3:72:eb:ad:d1:7d:1d:27:ef:92:eb: + 10:bf:5b:eb:3b:af:cf:80:dd:c1:d2:96:04:5b:7a: + 7e:a4:a9:3c:38:76:a4:62:8e:a0:39:5e:ea:77:cf: + 5d:00:59:8f:66:2c:3e:07:a2:a3:05:26:11:69:97: + ea:85:b7:0f:96:0b:4b:c8:40:e1:50:ba:2e:8a:cb: + f7:0f:9a:22:e7:7f:9a:37:13:cd:f2:4d:13:6b:21: + d1:c0:cc:22:f2:a1:46:f6:44:69:9c:ca:61:35:07: + 00:6f:d6:61:08:11:ea:ba:b8:f6:e9:b3:60:e5:4d: + b9:ec:9f:14:66:c9:57:58:db:cd:87:69:f8:8a:86: + 12:03:47:bf:66:13:76:ac:77:7d:34:24:85:83:cd: + d7:aa:9c:90:1a:9f:21:2c:7f:78:b7:64:b8:d8:e8: + a6:f4:78:b3:55:cb:84:d2:32:c4:78:ae:a3:8f:61: + dd:ce:08:53:ad:ec:88:fc:15:e4:9a:0d:e6:9f:1a: + 77:ce:4c:8f:b8:14:15:3d:62:9c:86:38:06:00:66: + 12:e4:59:76:5a:53:c0:02:98:a2:10:2b:68:44:7b: + 8e:79:ce:33:4a:76:aa:5b:81:16:1b:b5:8a:d8:d0: + 00:7b:5e:62:b4:09:d6:86:63:0e:a6:05:95:49:ba: + 28:8b:88:93:b2:34:1c:d8:a4:55:6e:b7:1c:d0:de: + 99:55:3b:23:f4:22:e0:f9:29:66:26:ec:20:50:77: + db:4a:0b:8f:be:e5:02:60:70:41:5e:d4:ae:50:39: + 22:14:26:cb:b2:3b:73:74:55:47:07:79:81:39:a8: + 30:13:44:e5:04:8a:ae:96:13:25:42:0f:b9:53:c4: + 9b:fc:cd:e4:1c:de:3c:fa:ab:d6:06:4a:1f:67:a6: + 98:30:1c:dd:2c:db:dc:18:95:57:66:c6:ff:5c:8b: + 56:f5:77 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:F9:60:BB:D4:E3:D5:34:F6:B8:F5:06:80:25:A7:73:DB:46:69:A8:9E + + X509v3 Subject Key Identifier: + F9:60:BB:D4:E3:D5:34:F6:B8:F5:06:80:25:A7:73:DB:46:69:A8:9E + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 56:b3:8e:cb:0a:9d:49:8e:bf:a4:c4:91:bb:66:17:05:51:98: + 75:fb:e5:50:2c:7a:9e:f1:14:fa:ab:d3:8a:3e:ff:91:29:8f: + 63:8b:d8:b4:a9:54:01:0d:be:93:86:2f:f9:4a:6d:c7:5e:f5: + 57:f9:ca:55:1c:12:be:47:0f:36:c5:df:6a:b7:db:75:c2:47: + 25:7f:b9:f1:63:f8:68:2d:55:04:d1:f2:8d:b0:a4:cf:bc:3c: + 5e:1f:78:e7:a5:a0:20:70:b0:04:c5:b7:f7:72:a7:de:22:0d: + bd:33:25:46:8c:64:92:26:e3:3e:2e:63:96:da:9b:8c:3d:f8: + 18:09:d7:03:cc:7d:86:82:e0:ca:04:07:51:50:d7:ff:92:d5: + 0c:ef:da:86:9f:99:d7:eb:b7:af:68:e2:39:26:94:ba:68:b7: + bf:83:d3:ea:7a:67:3d:62:67:ae:25:e5:72:e8:e2:e4:ec:ae: + 12:f6:4b:2b:3c:9f:e9:b0:40:f3:38:54:b3:fd:b7:68:c8:da: + c6:8f:51:3c:b2:fb:91:dc:1c:e7:9b:9d:e1:b7:0d:72:8f:e2: + a4:c4:a9:78:f9:eb:14:ac:c6:43:05:c2:65:39:28:18:02:c3: + 82:b2:9d:05:be:65:ed:96:5f:65:74:3c:fb:09:35:2e:7b:9c: + 13:fd:1b:0f:5d:c7:6d:81:3a:56:0f:cc:3b:e1:af:02:2f:22: + ac:46:ca:46:3c:a0:1c:4c:d6:44:b4:5e:2e:5c:15:66:09:e1: + 26:29:fe:c6:52:61:ba:b1:73:ff:c3:0c:9c:e5:6c:6a:94:3f: + 14:ca:40:16:95:84:f3:59:a9:ac:5f:4c:61:93:6d:d1:3b:cc: + a2:95:0c:22:a6:67:67:44:2e:b9:d9:d2:8a:41:b3:66:0b:5a: + fb:7d:23:a5:f2:1a:b0:ff:de:9b:83:94:2e:d1:3f:df:92:b7: + 91:af:05:3b:65:c7:a0:6c:b1:cd:62:12:c3:90:1b:e3:25:ce: + 34:bc:6f:77:76:b1:10:c3:f7:05:1a:c0:d6:af:74:62:48:17: + 77:92:69:90:61:1c:de:95:80:74:54:8f:18:1c:c3:f3:03:d0: + bf:a4:43:75:86:53:18:7a:0a:2e:09:1c:36:9f:91:fd:82:8a: + 22:4b:d1:0e:50:25:dd:cb:03:0c:17:c9:83:00:08:4e:35:4d: + 8a:8b:ed:f0:02:94:66:2c:44:7f:cb:95:27:96:17:ad:09:30: + ac:b6:71:17:6e:8b:17:f6:1c:09:d4:2d:3b:98:a5:71:d3:54: + 13:d9:60:f3:f5:4b:66:4f:fa:f1:ee:20:12:8d:b4:ac:57:b1: + 45:63:a1:ac:76:a9:c2:fb +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV +BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE +CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy +MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G +A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD +DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq +M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf +OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa +4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 +HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR +aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA +b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ +Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV +PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO +pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu +UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY +MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 +9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW +s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 +Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg +cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM +79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz +/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt +ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm +Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK +QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ +w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi +S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 +mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority ECC +# Fingerprint (SHA1): 4C:DD:51:A3:D1:F5:20:32:14:B0:C6:C5:32:23:03:91:C7:46:42:6D +MUST_VERIFY_TRUST: EMAIL_PROTECTION, CODE_SIGNING +TRUSTED_DELEGATOR: SERVER_AUTH +================================================= +MD5 Fingerprint=59:53:22:65:83:42:01:54:C0:CE:42:B9:5A:7C:F2:90 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3182246526754555285 (0x2c299c5b16ed0595) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com EV Root Certification Authority ECC + Validity + Not Before: Feb 12 18:15:23 2016 GMT + Not After : Feb 12 18:15:23 2041 GMT + Subject: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com EV Root Certification Authority ECC + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:aa:12:47:90:98:1b:fb:ef:c3:40:07:83:20:4e: + f1:30:82:a2:06:d1:f2:92:86:61:f2:f6:21:68:ca: + 00:c4:c7:ea:43:00:54:86:dc:fd:1f:df:00:b8:41: + 62:5c:dc:70:16:32:de:1f:99:d4:cc:c5:07:c8:08: + 1f:61:16:07:51:3d:7d:5c:07:53:e3:35:38:8c:df: + cd:9f:d9:2e:0d:4a:b6:19:2e:5a:70:5a:06:ed:be: + f0:a1:b0:ca:d0:09:29 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Subject Key Identifier: + 5B:CA:5E:E5:DE:D2:81:AA:CD:A8:2D:64:51:B6:D9:72:9B:97:E6:4F + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:5B:CA:5E:E5:DE:D2:81:AA:CD:A8:2D:64:51:B6:D9:72:9B:97:E6:4F + + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: ecdsa-with-SHA256 + 30:65:02:31:00:8a:e6:40:89:37:eb:e9:d5:13:d9:ca:d4:6b: + 24:f3:b0:3d:87:46:58:1a:ec:b1:df:6f:fb:56:ba:70:6b:c7: + 38:cc:e8:b1:8c:4f:0f:f7:f1:67:76:0e:83:d0:1e:51:8f:02: + 30:3d:f6:23:28:26:4c:c6:60:87:93:26:9b:b2:35:1e:ba:d6: + f7:3c:d1:1c:ce:fa:25:3c:a6:1a:81:15:5b:f3:12:0f:6c:ee: + 65:8a:c9:87:a8:f9:07:e0:62:9a:8c:5c:4a +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx +NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv +bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA +VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku +WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX +5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ +ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg +h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + de:29:a4:d1:b0:8f:ac:88 + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=California, L=San Francisco, O=Linden Lab, Inc., OU=Linden Lab Certificate Authority, CN=Linden Lab Certificate Authority/emailAddress=ca@lindenlab.com + Validity + Not Before: Apr 21 02:40:31 2005 GMT + Not After : Apr 16 02:40:31 2025 GMT + Subject: C=US, ST=California, L=San Francisco, O=Linden Lab, Inc., OU=Linden Lab Certificate Authority, CN=Linden Lab Certificate Authority/emailAddress=ca@lindenlab.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:a5:e1:d4:c4:e1:b9:c7:53:6c:c8:3d:6d:80:4e: + ac:09:bc:c9:69:ec:df:66:28:8c:1d:0f:45:f6:ea: + f2:b5:23:7a:91:21:4e:6d:ff:d7:7b:34:bb:7f:7d: + 51:cd:b4:da:fe:1e:8d:c1:a1:90:80:d6:25:97:76: + 35:93:05:a0:aa:e1:99:17:f1:18:74:8a:3c:2b:85: + 69:70:b7:8e:1d:25:44:40:a3:ee:4f:05:a0:f9:1c: + 99:a3:e3:4b:2a:1d:ac:31:43:51:4b:af:f8:2d:3a: + a1:82:68:23:ea:e4:f1:11:32:6a:5f:4d:c2:01:ef: + a8:2c:ce:ad:9b:62:4d:70:1d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 3B:5C:CA:D9:ED:5F:D7:03:B5:7C:70:23:AB:A0:D3:26:86:CA:0E:B7 + X509v3 Authority Key Identifier: + keyid:3B:5C:CA:D9:ED:5F:D7:03:B5:7C:70:23:AB:A0:D3:26:86:CA:0E:B7 + DirName:/C=US/ST=California/L=San Francisco/O=Linden Lab, Inc./OU=Linden Lab Certificate Authority/CN=Linden Lab Certificate Authority/emailAddress=ca@lindenlab.com + serial:DE:29:A4:D1:B0:8F:AC:88 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 3f:66:48:1f:bf:01:d8:aa:4d:54:20:02:99:4b:79:0c:0b:1c: + f4:1e:f6:2e:11:0b:6f:8b:09:ee:c4:0d:fd:08:82:7a:e5:9a: + 33:b3:6f:04:83:56:95:f7:f6:3e:39:fe:d3:9d:68:56:f9:4d: + c9:df:fc:03:fc:68:21:68:01:a2:28:ae:af:32:7f:60:24:12: + 1d:05:7f:fd:7b:a7:9f:df:b5:46:ca:23:84:14:58:e7:50:86: + ee:93:44:56:b7:2d:28:ac:de:fa:ab:f9:48:ff:18:c2:8b:5e: + 57:48:0f:d5:4a:ad:a3:e2:f9:a7:c1:f6:5c:3d:30:ee:82:59: + 90:d4 +-----BEGIN CERTIFICATE----- +MIIEUDCCA7mgAwIBAgIJAN4ppNGwj6yIMA0GCSqGSIb3DQEBBAUAMIHMMQswCQYD +VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j +aXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5jLjEpMCcGA1UECxMgTGluZGVu +IExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIExpbmRlbiBMYWIg +Q2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZIhvcNAQkBFhBjYUBsaW5kZW5s +YWIuY29tMB4XDTA1MDQyMTAyNDAzMVoXDTI1MDQxNjAyNDAzMVowgcwxCzAJBgNV +BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp +c2NvMRkwFwYDVQQKExBMaW5kZW4gTGFiLCBJbmMuMSkwJwYDVQQLEyBMaW5kZW4g +TGFiIENlcnRpZmljYXRlIEF1dGhvcml0eTEpMCcGA1UEAxMgTGluZGVuIExhYiBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgkqhkiG9w0BCQEWEGNhQGxpbmRlbmxh +Yi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKXh1MThucdTbMg9bYBO +rAm8yWns32YojB0PRfbq8rUjepEhTm3/13s0u399Uc202v4ejcGhkIDWJZd2NZMF +oKrhmRfxGHSKPCuFaXC3jh0lRECj7k8FoPkcmaPjSyodrDFDUUuv+C06oYJoI+rk +8REyal9NwgHvqCzOrZtiTXAdAgMBAAGjggE2MIIBMjAdBgNVHQ4EFgQUO1zK2e1f +1wO1fHAjq6DTJobKDrcwggEBBgNVHSMEgfkwgfaAFDtcytntX9cDtXxwI6ug0yaG +yg63oYHSpIHPMIHMMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW +MBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5j +LjEpMCcGA1UECxMgTGluZGVuIExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAn +BgNVBAMTIExpbmRlbiBMYWIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZI +hvcNAQkBFhBjYUBsaW5kZW5sYWIuY29tggkA3imk0bCPrIgwDAYDVR0TBAUwAwEB +/zANBgkqhkiG9w0BAQQFAAOBgQA/ZkgfvwHYqk1UIAKZS3kMCxz0HvYuEQtviwnu +xA39CIJ65Zozs28Eg1aV9/Y+Of7TnWhW+U3J3/wD/GghaAGiKK6vMn9gJBIdBX/9 +e6ef37VGyiOEFFjnUIbuk0RWty0orN76q/lI/xjCi15XSA/VSq2j4vmnwfZcPTDu +glmQ1A== +-----END CERTIFICATE----- diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 253b0ad6e3..fbb2bb10f5 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -211,12 +211,6 @@ NoHardwareProbe - noquicktime - - map-to - NoQuickTime - - nosound map-to diff --git a/indra/newview/app_settings/default_grids.xml b/indra/newview/app_settings/default_grids.xml index f258b23d39..78c82ebdb6 100644 --- a/indra/newview/app_settings/default_grids.xml +++ b/indra/newview/app_settings/default_grids.xml @@ -2,7 +2,7 @@ - default_grids_version22 + default_grids_version23 @@ -11,7 +11,7 @@ gridnameSecond Life platformSecondLife loginurihttps://login.agni.lindenlab.com/cgi-bin/login.cgi - loginpagehttp://viewer-login.agni.lindenlab.com/ + loginpagehttps://viewer-splash.secondlife.com/ helperurihttps://secondlife.com/helpers/ websitehttp://secondlife.com/ supporthttp://secondlife.com/support/ @@ -26,7 +26,7 @@ gridnicksecondlife_beta gridnameSecond Life BETA helperurihttp://aditi-secondlife.webdev.lindenlab.com/helpers/ - loginpagehttp://viewer-login.agni.lindenlab.com/ + loginpagehttps://viewer-splash.secondlife.com/ loginurihttps://login.aditi.lindenlab.com/cgi-bin/login.cgi passwordhttp://secondlife.com/account/request.php platformSecondLife diff --git a/indra/newview/app_settings/dictionaries/en_sl.dic b/indra/newview/app_settings/dictionaries/en_sl.dic index 0f25bd2335..c2ab720884 100644 --- a/indra/newview/app_settings/dictionaries/en_sl.dic +++ b/indra/newview/app_settings/dictionaries/en_sl.dic @@ -730,6 +730,8 @@ llRotLookAt llStringLength llStartAnimation llStopAnimation +llStartObjectAnimation +llStopObjectAnimation llPointAt llStopPointAt llTargetOmega diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index d880d48f3f..3efc914cda 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -54,6 +54,9 @@ http_response http_response(key request_id, integer status, list metad http_request http_request(key id, string method, string body):Triggered when task receives an http request against a public URL transaction_result transaction_result(key id, integer success, string data): Triggered when currency is given to task path_update path_update(integer type, list reserved):Triggered when the state of a pathfinder character changes. Note; "list reserved" is not currently used +experience_permissions experience_permissions(key agent): Triggered when agent has approved an experience permissions request. This may be through interaction with the experience permission dialog or the experience profile, or automatically if the agent has previously approved the experience. +experience_permissions_denied experience_permissions_denied(key agent, integer reason): Triggered when agent has denied experience permission. reason is the reason for denial; one of the Experience Tools XP_ERROR_* errors flags. + # integer constants [word .1, .1, .5] @@ -65,11 +68,11 @@ STATUS_ROTATE_X Passed in the llSetStatus library function. If FALSE, o STATUS_ROTATE_Y Passed in the llSetStatus library function. If FALSE, object doesn't rotate around local Y axis STATUS_ROTATE_Z Passed in the llSetStatus library function. If FALSE, object doesn't rotate around local Z axis STATUS_SANDBOX Passed in the llSetStatus library function. If TRUE, object can't cross region boundaries or move more than 10 meters from its start location -STATUS_BLOCK_GRAB Passed in the llSetStatus library function. If TRUE, object can't be grabbed and physically dragged -STATUS_BLOCK_GRAB_OBJECT This status flag keeps the object from being moved by grabs. This flag applies to the entire linkset +STATUS_BLOCK_GRAB Passed in the llSetStatus library function. If TRUE, root prim of linkset (or unlinked prim) can't be grabbed and physically dragged STATUS_DIE_AT_EDGE Passed in the llSetStatus library function. If TRUE, objects that reach the edge of the world just die:rather than teleporting back to the owner STATUS_RETURN_AT_EDGE Passed in the llSetStatus library function. If TRUE, script rezzed objects that reach the edge of the world:are returned rather than killed:STATUS_RETURN_AT_EDGE trumps STATUS_DIE_AT_EDGE if both are set STATUS_CAST_SHADOWS Passed in the llSetStatus library function. If TRUE, object casts shadows on other objects +STATUS_BLOCK_GRAB_OBJECT Passed in the llSetStatus library function. If TRUE, no prims in linkset can be grabbed or physically dragged AGENT Passed in llSensor library function to look for other Agents; DEPRECATED: Use AGENT_BY_LEGACY_NAME AGENT_BY_LEGACY_NAME Passed in llSensor library function to look for other Agents by legacy name @@ -150,15 +153,6 @@ PSYS_PART_EMISSIVE_MASK PSYS_PART_TARGET_LINEAR_MASK PSYS_PART_RIBBON_MASK -PSYS_PART_BF_ONE -PSYS_PART_BF_ZERO -PSYS_PART_BF_DEST_COLOR -PSYS_PART_BF_SOURCE_COLOR -PSYS_PART_BF_ONE_MINUS_DEST_COLOR -PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR -PSYS_PART_BF_SOURCE_ALPHA -PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA - PSYS_SRC_PATTERN PSYS_SRC_INNERANGLE Deprecated -- Use PSYS_SRC_ANGLE_BEGIN PSYS_SRC_OUTERANGLE Deprecated -- Use PSYS_SRC_ANGLE_END @@ -180,8 +174,18 @@ PSYS_SRC_PATTERN_EXPLODE PSYS_SRC_PATTERN_ANGLE PSYS_SRC_PATTERN_ANGLE_CONE PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY +PSYS_PART_BF_ONE +PSYS_PART_BF_ZERO +PSYS_PART_BF_DEST_COLOR +PSYS_PART_BF_SOURCE_COLOR +PSYS_PART_BF_ONE_MINUS_DEST_COLOR +PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR +PSYS_PART_BF_SOURCE_ALPHA +PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA OBJECT_UNKNOWN_DETAIL Returned by llGetObjectDetails when passed an invalid object parameter type +OBJECT_HOVER_HEIGHT This is a flag used with llGetObjectDetails to get hover height of the avatar. If no data is available, 0.0 is returned. +OBJECT_LAST_OWNER_ID Gets the object's last owner ID. OBJECT_NAME Used with llGetObjectDetails to get an object's name OBJECT_DESC Used with llGetObjectDetails to get an object's description OBJECT_POS Used with llGetObjectDetails to get an object's position @@ -189,6 +193,7 @@ OBJECT_ROT Used with llGetObjectDetails to get an o OBJECT_VELOCITY Used with llGetObjectDetails to get an object's velocity OBJECT_OWNER Used with llGetObjectDetails to get an object's owner's key. Will be NULL_KEY if group owned OBJECT_GROUP Used with llGetObjectDetails to get an object's group's key +OBJECT_CLICK_ACTION This is a flag used with llGetObjectDetails to get the click action. The default is 0. OBJECT_CREATOR Used with llGetObjectDetails to get an object's creator's key OBJECT_RUNNING_SCRIPT_COUNT Gets the number of running scripts attached to the object or agent OBJECT_TOTAL_SCRIPT_COUNT Gets the number of scripts, both running and stopped, attached to the object or agent. @@ -199,6 +204,7 @@ OBJECT_SERVER_COST Used with llGetObjectDetails to get the OBJECT_STREAMING_COST Used with llGetObjectDetails to get the streaming (download) cost. OBJECT_PHYSICS_COST Used with llGetObjectDetails to get the physics cost. OBJECT_PATHFINDING_TYPE Used with llGetObjectDetails to get an object's pathfinding settings. +OBJECT_BODY_SHAPE_TYPE This is a flag used with llGetObjectDetails to get the body type of the avatar, based on shape data. If no data is available, -1.0 is returned. This is normally between 0 and 1.0, with 0.5 and larger considered 'male' OBJECT_CHARACTER_TIME Used with llGetObjectDetails to get an object's average CPU time (in seconds) used by the object for navigation, if the object is a pathfinding character. Returns 0 for non-characters. OBJECT_ROOT Used with llGetObjectDetails to get an object's root prim ID. OBJECT_ATTACHED_POINT Used with llGetObjectDetails to get an object's attachment point. @@ -400,8 +406,6 @@ REMOTE_DATA_REQUEST Value of event_type in remote_event if X REMOTE_DATA_REPLY Value of event_type in remote_event if XML-RPC reply is received -PRIM_NAME Sets the prim's name -PRIM_DESC Sets the prim's description PRIM_TYPE Followed by PRIM_TYPE_BOX, PRIM_TYPE_CYLINDER, PRIM_TYPE_PRISM, PRIM_TYPE_SPHERE, PRIM_TYPE_TORUS, PRIM_TYPE_TUBE, or PRIM_TYPE_SCULPT and their arguments PRIM_MATERIAL Followed by PRIM_MATERIAL_STONE, PRIM_MATERIAL_METAL, PRIM_MATERIAL_GLASS, PRIM_MATERIAL_WOOD, PRIM_MATERIAL_FLESH, PRIM_MATERIAL_PLASTIC, or PRIM_MATERIAL_RUBBER PRIM_PHYSICS Sets physics to TRUE or FALSE @@ -413,19 +417,26 @@ PRIM_CAST_SHADOWS DEPRECATED. Takes 1 parameter, an intege PRIM_POSITION Sets primitive position to a vector position PRIM_SIZE Sets primitive size to a vector size PRIM_ROTATION Sets primitive rotation -PRIM_TEXT Used to get or set the object's floating text. PRIM_TEXTURE Followed by an integer face, key id, vector repeats, vector offsets,:and float rotation in radians PRIM_COLOR Followed by an integer face, vector color, and float alpha PRIM_BUMP_SHINY Followed by an integer face, one of PRIM_SHINY_NONE, PRIM_SHINY_LOW,:PRIM_SHINY_MEDIUM, or PRIM_SHINY_HIGH,:and one of PRIM_BUMP_NONE, PRIM_BUMP_BRIGHT, PRIM_BUMP_DARK, etc PRIM_FULLBRIGHT Followed by an integer face, and TRUE or FALSE PRIM_TEXGEN Followed by an integer face, and one of PRIM_TEXGEN_DEFAULT or PRIM_TEXGEN_PLANAR PRIM_GLOW Followed by an integer face, and a float from 0.0 to 1.0 specifying glow amount -PRIM_POS_LOCAL Sets the prim's local position +PRIM_TEXT Used to get or set the object's floating text. +PRIM_NAME Sets the prim's name +PRIM_DESC Sets the prim's description PRIM_ROT_LOCAL Sets the prim's local rotation +PRIM_PHYSICS_SHAPE_TYPE For primitive physics shape type. Followed with either PRIM_PHYSICS_SHAPE_PRIM, PRIM_PHYSICS_SHAPE_NONE or PRIM_PHYSICS_SHAPE_CONVEX. PRIM_OMEGA Makes the object spin at the specified axis and rate +PRIM_POS_LOCAL Sets the prim's local position PRIM_LINK_TARGET Used to get or set multiple links with a single PrimParameters call. PRIM_SLICE Get and set the 'slice' parameter of all shapes. Takes a vector parameter of the form +PRIM_PHYSICS_SHAPE_PRIM Use the normal prim shape for physics (this is the default for all non-mesh objects) +PRIM_PHYSICS_SHAPE_NONE Use the convex hull of the prim shape for physics (this is the default for mesh objects) +PRIM_PHYSICS_SHAPE_CONVEX Ignore this prim in the physics shape. This cannot be applied to the root prim. + PRIM_TYPE_BOX Followed by integer hole shape, vector cut, float hollow, vector twist,:vector top size, and vector top shear PRIM_TYPE_CYLINDER Followed by integer hole shape, vector cut, float hollow, vector twist,:vector top size, and vector top shear PRIM_TYPE_PRISM Followed by integer hole shape, vector cut, float hollow, vector twist,:vector top size, and vector top shear @@ -454,6 +465,7 @@ PRIM_SHINY_LOW Low shininess PRIM_SHINY_MEDIUM Medium shininess PRIM_SHINY_HIGH High shininess + PRIM_BUMP_NONE No bump map PRIM_BUMP_BRIGHT Generate bump map from highlights PRIM_BUMP_DARK Generate bump map from lowlights @@ -484,11 +496,6 @@ PRIM_SCULPT_TYPE_MASK Mask used to determine stitching type PRIM_SCULPT_FLAG_INVERT Flag to specify that the surface normals should be inverted PRIM_SCULPT_FLAG_MIRROR Flag to specify that the prim should be reflected along X axis -PRIM_PHYSICS_SHAPE_TYPE For primitive physics shape type. Followed with either PRIM_PHYSICS_SHAPE_PRIM, PRIM_PHYSICS_SHAPE_NONE or PRIM_PHYSICS_SHAPE_CONVEX. -PRIM_PHYSICS_SHAPE_PRIM Use the normal prim shape for physics (this is the default for all non-mesh objects) -PRIM_PHYSICS_SHAPE_NONE Use the convex hull of the prim shape for physics (this is the default for mesh objects) -PRIM_PHYSICS_SHAPE_CONVEX Ignore this prim in the physics shape. This cannot be applied to the root prim. - PRIM_SPECULAR Used to get or set the specular map texture settings of a prim's face. PRIM_NORMAL Used to get or set the normal map texture settings of a prim's face. @@ -514,7 +521,7 @@ PARCEL_MEDIA_COMMAND_STOP Stop media stream PARCEL_MEDIA_COMMAND_PAUSE Pause media stream PARCEL_MEDIA_COMMAND_PLAY Play media stream PARCEL_MEDIA_COMMAND_LOOP Loop media stream -PARCEL_MEDIA_COMMAND_LOOP_SET Used to get or set the parcel's media loop duration +PARCEL_MEDIA_COMMAND_LOOP_SET Used to get or set the parcel's media loop duration. PARCEL_MEDIA_COMMAND_TEXTURE Get or set the parcel's media texture PARCEL_MEDIA_COMMAND_URL Get or set the parcel's media url PARCEL_MEDIA_COMMAND_TYPE Get or set the parcel's media mimetype @@ -667,12 +674,12 @@ RCERR_CAST_TIME_EXCEEDED Returned by llCastRay() when the raycast f RCERR_SIM_PERF_LOW Returned by llCastRay() when the raycast failed because simulator performance is low. RCERR_UNKNOWN Returned by llCastRay() when the raycast failed for an unspecified reason. -ESTATE_ACCESS_ALLOWED_AGENT_ADD Used with llManageEstateAccess to add an agent to this estate's allowed residents list. -ESTATE_ACCESS_ALLOWED_AGENT_REMOVE Used with llManageEstateAccess to remove an agent from this estate's allowed residents list. -ESTATE_ACCESS_ALLOWED_GROUP_ADD Used with llManageEstateAccess to add a group to this estate's allowed groups list. -ESTATE_ACCESS_ALLOWED_GROUP_REMOVE Used with llManageEstateAccess to remove a group from this estate's allowed groups list. -ESTATE_ACCESS_BANNED_AGENT_ADD Used with llManageEstateAccess to add an agent to this estate's banned residents list. -ESTATE_ACCESS_BANNED_AGENT_REMOVE Used with llManageEstateAccess to remove an agent from this estate's banned residents list. +ESTATE_ACCESS_ALLOWED_AGENT_ADD Passed to llManageEstateAccess to add the agent to this estate's Allowed Residents list +ESTATE_ACCESS_ALLOWED_AGENT_REMOVE Passed to llManageEstateAccess to remove the agent from this estate's Allowed Residents list +ESTATE_ACCESS_ALLOWED_GROUP_ADD Passed to llManageEstateAccess to add the group to this estate's Allowed groups list +ESTATE_ACCESS_ALLOWED_GROUP_REMOVE Passed to llManageEstateAccess to remove the group from this estate's Allowed groups list +ESTATE_ACCESS_BANNED_AGENT_ADD Passed to llManageEstateAccess to add the agent to this estate's Banned residents list +ESTATE_ACCESS_BANNED_AGENT_REMOVE Passed to llManageEstateAccess to remove the agent from this estate's Banned residents list DENSITY For use with llSetPhysicsMaterial() as a bitwise value in its material_bits parameter, to set the density. FRICTION For use with llSetPhysicsMaterial() as a bitwise value in its material_bits parameter, to set the friction. @@ -685,6 +692,7 @@ KFM_COMMAND Option for llSetKeyframedMotion(), followe KFM_CMD_PLAY Option for llSetKeyframedMotion(), used after KFM_COMMAND to play the motion. KFM_CMD_STOP Option for llSetKeyframedMotion(), used after KFM_COMMAND to stop the motion. KFM_CMD_PAUSE Option for llSetKeyframedMotion(), used after KFM_COMMAND to pause the motion. +#KFM_CMD_SET_MODE TODO: add documentation KFM_MODE Option for llSetKeyframedMotion(), used to specify the playback mode, followed by one of KFM_FORWARD, KFM_LOOP, KFM_PING_PONG or KFM_REVERSE. KFM_FORWARD Option for llSetKeyframedMotion(), used after KFM_MODE to specify the forward playback mode. KFM_LOOP Option for llSetKeyframedMotion(), used after KFM_MODE to specify the loop playback mode. @@ -730,7 +738,7 @@ PU_FAILURE_NO_NAVMESH Triggered if no navmesh is available for the re PU_FAILURE_DYNAMIC_PATHFINDING_DISABLED Triggered when a character enters a region with dynamic pathfinding disabled. PU_FAILURE_PARCEL_UNREACHABLE Triggered when a character failed to enter a parcel because it is not allowed to enter, e.g. because the parcel is already full or because object entry was disabled after the navmesh was baked. -CHARACTER_TYPE Specifies which walkability coefficient will be used by this character. +CHARACTER_TYPE Specifies which walkability coefficient will be used by this character. Used in combination with one of the character type flags. CHARACTER_TYPE_A Used for character types that you prefer move in a way consistent with humanoids. CHARACTER_TYPE_B Used for character types that you prefer move in a way consistent with wild animals or off road vehicles. CHARACTER_TYPE_C Used for mechanical character types or road going vehicles. @@ -915,6 +923,26 @@ TEXTURE_TRANSPARENT UUID for the "White - Transparent" texture URL_REQUEST_GRANTED Used with http_request when a public URL is successfully granted URL_REQUEST_DENIED Used with http_request when a public URL is not available +XP_ERROR_NONE No error was detected +XP_ERROR_THROTTLED The call failed due to too many recent calls. +XP_ERROR_EXPERIENCES_DISABLED The region currently has experiences disabled. +XP_ERROR_INVALID_PARAMETERS One of the string arguments was too big to fit in the key-value store. +XP_ERROR_NOT_PERMITTED This experience is not allowed to run on the current region. +XP_ERROR_NO_EXPERIENCE This script is not associated with an experience. +XP_ERROR_NOT_FOUND The sim was unable to verify the validity of the experience. Retrying after a short wait is advised. +XP_ERROR_INVALID_EXPERIENCE The script is associated with an experience that no longer exists. +XP_ERROR_EXPERIENCE_DISABLED The experience owner has temporarily disabled the experience. +XP_ERROR_EXPERIENCE_SUSPENDED The experience has been suspended by Linden Customer Support. +XP_ERROR_QUOTA_EXCEEDED An attempted write data to the key-value store failed due to the data quota being met. +XP_ERROR_STORE_DISABLED The key-value store is currently disabled on this region. +XP_ERROR_STORAGE_EXCEPTION Unable to communicate with the key-value store. +XP_ERROR_KEY_NOT_FOUND The requested key does not exist. +XP_ERROR_RETRY_UPDATE A checked update failed due to an out of date request. +XP_ERROR_MATURITY_EXCEEDED The request failed due to agent content preferences. +XP_ERROR_UNKNOWN_ERROR Other unknown error. +XP_ERROR_INVALID_PARAMETERS One of the string arguments was too big to fit in the key-value store. + + # float constants [word .3, .1, .5] PI 3.1415926535897932384626433832795 diff --git a/indra/newview/app_settings/lsl_functions_sl.xml b/indra/newview/app_settings/lsl_functions_sl.xml index 8780e774c4..7bb14209c5 100644 --- a/indra/newview/app_settings/lsl_functions_sl.xml +++ b/indra/newview/app_settings/lsl_functions_sl.xml @@ -305,6 +305,10 @@ llStopAnimation + llStartObjectAnimation + + llStopObjectAnimation + llPointAt llStopPointAt @@ -1048,5 +1052,28 @@ llGetMaxScaleFactor + + llAgentInExperience + + llGetExperienceDetails + + llRequestExperiencePermissions + + llReadKeyValue + + llCreateKeyValue + + llUpdateKeyValue + + llDeleteKeyValue + + llDataSizeKeyValue + + llKeysKeyValue + + llKeyCountKeyValue + + llGetExperienceErrorMessage +
    diff --git a/indra/newview/app_settings/mime_types.xml b/indra/newview/app_settings/mime_types.xml index 61067da063..9182f5742b 100644 --- a/indra/newview/app_settings/mime_types.xml +++ b/indra/newview/app_settings/mime_types.xml @@ -7,7 +7,7 @@ none - media_plugin_webkit + media_plugin_cef + + + + none/none + + + icn_media_web.tga + + + No media here + + + + false + + + false + + + + + + movie + + + media_plugin_example - + + + + movie + + + media_plugin_libvlc + + + @@ -120,7 +163,7 @@ none - media_plugin_webkit + media_plugin_cef @@ -131,7 +174,7 @@ none - media_plugin_webkit + media_plugin_cef @@ -142,7 +185,7 @@ audio - media_plugin_quicktime + media_plugin_libvlc @@ -153,7 +196,7 @@ movie - media_plugin_quicktime + media_plugin_libvlc @@ -164,7 +207,7 @@ image - media_plugin_webkit + media_plugin_cef @@ -175,8 +218,8 @@ movie - media_plugin_quicktime - + media_plugin_libvlc + @@ -197,7 +240,7 @@ audio - media_plugin_quicktime + media_plugin_cef @@ -208,7 +251,7 @@ image - media_plugin_webkit + media_plugin_cef @@ -219,7 +262,7 @@ image - media_plugin_webkit + media_plugin_cef @@ -230,18 +273,18 @@ image - media_plugin_webkit + media_plugin_cef movie - media_plugin_webkit + media_plugin_cef @@ -252,7 +295,7 @@ web - media_plugin_webkit + media_plugin_cef @@ -263,7 +306,7 @@ image - media_plugin_webkit + media_plugin_cef @@ -274,7 +317,7 @@ audio - media_plugin_quicktime + media_plugin_cef @@ -285,7 +328,7 @@ audio - media_plugin_quicktime + media_plugin_libvlc @@ -296,7 +339,7 @@ audio - media_plugin_quicktime + media_plugin_libvlc @@ -307,7 +350,7 @@ audio - media_plugin_quicktime + media_plugin_libvlc @@ -318,7 +361,7 @@ image - media_plugin_webkit + media_plugin_cef @@ -329,7 +372,7 @@ image - media_plugin_webkit + media_plugin_cef @@ -340,7 +383,7 @@ image - media_plugin_webkit + media_plugin_cef @@ -351,7 +394,7 @@ image - media_plugin_webkit + media_plugin_cef @@ -362,7 +405,7 @@ image - media_plugin_webkit + media_plugin_cef @@ -373,7 +416,7 @@ image - media_plugin_webkit + media_plugin_cef @@ -384,8 +427,8 @@ web - media_plugin_webkit - + media_plugin_cef + @@ -406,7 +449,7 @@ text - media_plugin_webkit + media_plugin_cef @@ -417,8 +460,8 @@ movie - media_plugin_quicktime - + media_plugin_libvlc + + + + + movie + + + media_plugin_libvlc - + @@ -439,8 +493,8 @@ movie - media_plugin_quicktime - + media_plugin_libvlc + diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a264b810c4..dfc144343d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -55,11 +55,14 @@ SGAllowRiggedMeshSelection Comment - Allow selection of worn rigged meshes in build or inspect mode + Rigged mesh selection behavior: +0 = Never select, +1 = Hold shift to select, +2 = Hold shift or have build or inspect floater open Persist 1 Type - Boolean + S32 Value 0 @@ -86,18 +89,6 @@ 0
    - SianaRenderDeferredInvisiprim - - Comment - Support invisiprims in deferred mode - Persist - 1 - Type - Boolean - Value - 1 - - SianaVoidWaterSubdivision Comment @@ -466,6 +457,8 @@ Boolean Value 0 + IsCOA + 1 AOAdvanced @@ -488,6 +481,34 @@ Boolean Value 1 + IsCOA + 1 + + AOSwimEnabled + + Comment + Overrides fly animations with swims when underwater. + Persist + 1 + Type + Boolean + Value + 1 + IsCOA + 1 + + AOSwimForced + + Comment + Sets AOSwimEnabled to true, and plays swims instead of flies, even if not underwater. + Persist + 1 + Type + Boolean + Value + 0 + IsCOA + 1 AONoStandsInMouselook @@ -808,17 +829,6 @@ Value 1 - LiruResizeRootWithScreen - - Comment - When false, the ui view won't resize when the screen does (floaters won't move around without user interaction, but they also might be restricted from moving everywhere). - Persist - 1 - Type - Boolean - Value - 1 - LiruLegacyScrollToEnd Comment @@ -850,7 +860,7 @@ Type Boolean Value - 0 + 1 LiruMiniBuildFloater @@ -990,6 +1000,17 @@ Value 0 + LiruOnlineNotificationBehavior + + Comment + Determines if Friend is Online notifications will do anything when clicked. (0 does nothing, 1 starts an IM (default), 2 opens profile. + Persist + 1 + Type + S32 + Value + 1 + LiruRegionRestartMinimized Comment @@ -1003,6 +1024,17 @@ IsCOA 1 + LiruResizeRootWithScreen + + Comment + When false, the ui view won't resize when the screen does (floaters won't move around without user interaction, but they also might be restricted from moving everywhere). + Persist + 1 + Type + Boolean + Value + 1 + LiruScriptErrorsStealFocus Comment @@ -1024,7 +1056,7 @@ Found in Advanced->Rendering->Info Displays
    Type Boolean Value - 1 + 0
    LiruShowLastNameResident @@ -1160,17 +1192,6 @@ Found in Advanced->Rendering->Info Displays
    Value 0
    - FloaterUnfocusedBackgroundOpaque - - Comment - Disables floaters going transparent when not in focus, may conflict with some skins, though. - Persist - 1 - Type - Boolean - Value - 0 - FSSynchronizeTextureMaps Comment @@ -1191,7 +1212,7 @@ Found in Advanced->Rendering->Info Displays
    Type Boolean Value - 0 + 1
    InstantMessageLogPathAnyAccount @@ -1274,6 +1295,17 @@ Found in Advanced->Rendering->Info Displays
    Value 1 + ShowMutedText + + Comment + Whether or not to show chat from muted people in local chat. + Persist + 1 + Type + Boolean + Value + 0 + OtherChatsTornOff Comment @@ -1522,15 +1554,6 @@ This should be as low as possible, but too low may break functionality
    Value 0 - InventorySortOrder - - Comment - Specifies sort key for inventory items (+0 = name, +1 = date, +2 = folders always by name, +4 = system folders to top) - Type - U32 - Value - 3 - Blacklist.Settings Comment @@ -1775,6 +1798,17 @@ This should be as low as possible, but too low may break functionality Value 0 + AntiSpamItemOffersLandmarks + + Comment + When AntiSpamItemOffers is false but this is true, dialogs from inventory item offers of landmarks will be blocked. + Persist + 1 + Type + Boolean + Value + 0 + AntiSpamNotFriend Comment @@ -2058,6 +2092,24 @@ This should be as low as possible, but too low may break functionality IsCOA 1 + LogChatColor + + Comment + Color of chat messages loaded from your log + Persist + 1 + Type + Color4 + Value + + 0.5 + 0.5 + 0.5 + 1.0 + + IsCOA + 1 + UISndAlert Comment @@ -2517,7 +2569,7 @@ This should be as low as possible, but too low may break functionality 1 - CrashHostUrl + CrashHostUrl Comment A URL pointing to a crash report handler; overrides cluster negotiation to locate crash handler. @@ -2526,7 +2578,7 @@ This should be as low as possible, but too low may break functionality Type String Value - http://crash.singularityviewer.org/report.php> + AFKTimeout @@ -2539,6 +2591,17 @@ This should be as low as possible, but too low may break functionality Value 300.0 + ActiveFloaterTransparency + + Comment + Transparency of active floaters (floaters that have focus) + Persist + 1 + Type + F32 + Value + 1 + AdvanceSnapshot Comment @@ -3445,6 +3508,39 @@ This should be as low as possible, but too low may break functionality Value 3128 + BrowserProxyType + + Comment + Type of proxy for Web Browser + Persist + 1 + Type + S32 + Value + 0 + + BrowserProxyUsername + + Comment + Username for Web Proxy authentication + Persist + 1 + Type + String + Value + + + BrowserProxyPassword + + Comment + Password for Web Proxy authentication + Persist + 1 + Type + String + Value + + BrowserProxySocks45 Comment @@ -5326,6 +5422,72 @@ This should be as low as possible, but too low may break functionality Value + AnimatedObjectsIgnoreLimits + + Comment + Ignore server-enforced limits on animated objects. This is only useful for server testing. + Persist + 1 + Type + Boolean + Value + 0 + + AnimatedObjectsAllowLeftClick + + Comment + Allow left-click interaction with animated objects. Uncertain how much performance impact this will have. + Persist + 1 + Type + Boolean + Value + 0 + + AnimatedObjectsGlobalScale + + Comment + Temporary testing: allow an extra scale factor to be forced on animated objects. + Persist + 1 + Type + F32 + Value + 1.00 + + AnimatedObjectsMaxLegalOffset + + Comment + Max visual offset between object position and rendered position + Persist + 1 + Type + F32 + Value + 3.0 + + AnimatedObjectsMaxLegalSize + + Comment + Max bounding box size for animated object's rendered position + Persist + 1 + Type + F32 + Value + 64.0 + + AvatarBoundingBoxComplexity + + Comment + How many aspects to consider for avatar bounding box + Persist + 1 + Type + S32 + Value + 3 + DebugAvatarAppearanceMessage Comment @@ -5381,6 +5543,17 @@ This should be as low as possible, but too low may break functionality Value 1 + DebugHideEmptySystemFolders + + Comment + Hide empty system folders when on + Persist + 1 + Type + Boolean + Value + 1 + DebugInventoryFilters Comment @@ -6936,7 +7109,7 @@ This should be as low as possible, but too low may break functionality Type String Value - %Y-%m-%d + %F ShortTimeFormat @@ -6947,7 +7120,7 @@ This should be as low as possible, but too low may break functionality Type String Value - %H:%M + %R LongTimeFormat @@ -6958,7 +7131,7 @@ This should be as low as possible, but too low may break functionality Type String Value - %H:%M:%S + %T TimestampFormat @@ -6969,7 +7142,7 @@ This should be as low as possible, but too low may break functionality Type String Value - %a %d %b %Y %H:%M:%S + %a %d %b %Y %T SecondsInChatAndIMs @@ -6991,7 +7164,7 @@ This should be as low as possible, but too low may break functionality Type Boolean Value - 0 + 1 FloaterAboutRect @@ -7351,20 +7524,52 @@ This should be as low as possible, but too low may break functionality 0 - FloaterFavoritesRect + FloaterExperiencePickerRect Comment - Rectangle for favorites window + Rectangle for experience picker floater Persist 1 Type Rect Value - 0 - 400 - 250 - 0 + 300 + 600 + 800 + 700 + + + FloaterExperienceProfileRect + + Comment + Rectangle for experience profile floaters + Persist + 1 + Type + Rect + Value + + 377 + 650 + 345 + 128 + + + FloaterExperiencesRect + + Comment + Rectangle for experiences floater + Persist + 1 + Type + Rect + Value + + 300 + 600 + 700 + 700 FloaterFindRect2 @@ -7482,22 +7687,6 @@ This should be as low as possible, but too low may break functionality 0 - FloaterInvPanelRect - - Comment - Rectangle for new inventory windows a folder is opened in - Persist - 1 - Type - Rect - Value - - 0 - 400 - 300 - 0 - - FloaterJoystickRect Comment @@ -7514,22 +7703,6 @@ This should be as low as possible, but too low may break functionality 0 - FloaterLagMeter - - Comment - Rectangle for lag meter - Persist - 1 - Type - Rect - Value - - 0 - 142 - 350 - 0 - - ShowRadar Comment @@ -7612,6 +7785,17 @@ This should be as low as possible, but too low may break functionality Value 24 + RadarColumnNotesWidth + + Comment + Width for radar's notes column + Persist + 1 + Type + S32 + Value + 24 + RadarColumnAgeWidth Comment @@ -7700,6 +7884,17 @@ This should be as low as possible, but too low may break functionality Value 0 + RadarColumnNotesHidden + + Comment + Hide radar's notes column + Persist + 1 + Type + Boolean + Value + 1 + RadarColumnAgeHidden Comment @@ -7760,13 +7955,35 @@ This should be as low as possible, but too low may break functionality Comment When false, pauses the radar until further notice, good for banning someone who just left. Persist - 0 - HideFromEditor + 0 + HideFromEditor + 1 + Type + Boolean + Value + 1 + + RadarAlertFlood + + Comment + Show the flood of people arriving and (if RadarAlertFloodLeaving) leaving when you login and when you open/close the Radar with RadarKeepOpen off. + Persist + 1 + Type + Boolean + Value + 0 + + RadarAlertFloodLeaving + + Comment + When activated along with RadarAlertFlood shows the flood of people leaving when you close the Radar with RadarKeepOpen off. + Persist 1 Type Boolean Value - 1 + 0 RadarAlertShowDist @@ -7878,6 +8095,20 @@ This should be as low as possible, but too low may break functionality Value 0 + RadarSortOrder + + Comment + Sort order for the radar, map of column names to ascending boolean + Persist + 1 + Type + LLSD + Value + + distance + 1 + + FloaterLandRect5 Comment @@ -7990,10 +8221,10 @@ This should be as low as possible, but too low may break functionality 0 - FloaterMyOutfitsRect + FloaterObjectIMInfo Comment - Rectangle for My Outfits window + Rectangle for floater object im info windows Persist 1 Type @@ -8001,15 +8232,15 @@ This should be as low as possible, but too low may break functionality Value 0 - 400 - 250 + 300 + 300 0 - FloaterObjectIMInfo + FloaterOpenObjectRect Comment - Rectangle for floater object im info windows + Rectangle for Open Object window Persist 1 Type @@ -8017,31 +8248,31 @@ This should be as low as possible, but too low may break functionality Value 0 - 300 + 350 300 0 - FloaterOpenObjectRect + FloaterMarketplaceListingsRect Comment - Rectangle for Open Object window + Rectangle for Marketplace Listings window Persist 1 Type Rect Value - 0 - 350 - 300 - 0 + 0 + 342 + 310 + 52 - FloaterOutboxRect + FloaterMarketplaceValidationRect Comment - Rectangle for merchant outbox window + Rectangle for Marketplace Validation window Persist 1 Type @@ -8098,7 +8329,7 @@ This should be as low as possible, but too low may break functionality 0 512 - 480 + 500 0 @@ -9028,6 +9259,22 @@ This should be as low as possible, but too low may break functionality Value 400 + HTMLAgentColor + + Comment + Color of hyperlinked user/object names + Persist + 1 + Type + Color4 + Value + + 0.600000023842 + 0.600000023842 + 1.0 + 1.0 + + HTMLLinkColor Comment @@ -9169,6 +9416,50 @@ This should be as low as possible, but too low may break functionality 128 + ImporterDebug + + Comment + Enable debug output to more precisely identify sources of import errors. Warning: the output can slow down import on many machines. + Persist + 1 + Type + Boolean + Value + 0 + + ImporterLegacyMatching + + Comment + Enable index based model matching. + Persist + 1 + Type + Boolean + Value + 0 + + ImporterModelLimit + + Comment + Limits amount of importer generated models for dae files + Persist + 1 + Type + U32 + Value + 768 + + ImporterPreprocessDAE + + Comment + Enable preprocessing for DAE files to fix some ColladaDOM related problems (like support for space characters within names and ids). + Persist + 1 + Type + Boolean + Value + 1 + IMInChatConsole Comment @@ -9224,6 +9515,17 @@ This should be as low as possible, but too low may break functionality Value 1 + InactiveFloaterTransparency + + Comment + Transparency of inactive floaters (floaters that have no focus) + Persist + 1 + Type + F32 + Value + 1 + InBandwidth Comment @@ -9301,12 +9603,12 @@ This should be as low as possible, but too low may break functionality Value 0 - InventoryDisplayOutbox + InventoryOutboxDisplayBoth Comment - Override merchant inventory outbox display + Show the legacy Merchant Outbox UI as well as the Marketplace Listings UI Persist - 0 + 1 Type Boolean Value @@ -9323,6 +9625,17 @@ This should be as low as possible, but too low may break functionality Value 0 + InventoryOutboxMakeVisible + + Comment + Enable making the Merchant Outbox and Inbox visible in the inventory for debug purposes. + Persist + 1 + Type + Boolean + Value + 1 + InventoryOutboxMaxFolderCount Comment @@ -9332,7 +9645,7 @@ This should be as low as possible, but too low may break functionality Type U32 Value - 21 + 20 InventoryOutboxMaxFolderDepth @@ -9356,6 +9669,17 @@ This should be as low as possible, but too low may break functionality Value 200 + InventoryOutboxMaxStockItemCount + + Comment + Maximum number of items allowed in a stock folder. + Persist + 0 + Type + U32 + Value + 200 + InventorySortOrder Comment @@ -9367,6 +9691,17 @@ This should be as low as possible, but too low may break functionality Value 7 + MarketplaceListingsSortOrder + + Comment + Specifies sort for marketplace listings + Persist + 1 + Type + U32 + Value + 2 + InvertMouse Comment @@ -9614,17 +9949,6 @@ This should be as low as possible, but too low may break functionality Value http://wiki.secondlife.com/wiki/[LSL_STRING] - LagMeterShrunk - - Comment - Last large/small state for lag meter - Persist - 1 - Type - Boolean - Value - 0 - Language Comment @@ -10219,6 +10543,17 @@ This should be as low as possible, but too low may break functionality Value + MarketplaceListingsLogging + + Comment + Enable debug output associated with the Marketplace Listings (SLM) API. + Persist + 1 + Type + Boolean + Value + 0 + MaxDragDistance Comment @@ -10241,6 +10576,17 @@ This should be as low as possible, but too low may break functionality Value 1.6 + MaxPersistentNotifications + + Comment + Maximum amount of persistent notifications + Persist + 1 + Type + S32 + Value + 250 + MaxSelectDistance Comment @@ -10494,17 +10840,6 @@ This should be as low as possible, but too low may break functionality Value 18 - MenuBarWidth - - Comment - - Persist - 0 - Type - S32 - Value - 410 - MeshEnabled Comment @@ -11425,17 +11760,6 @@ This should be as low as possible, but too low may break functionality Value 344 - RevokePermsOnStandUp - - Comment - When enabled, revokes any permission granted to an object you don't own and from which your avatar is standing up - Persist - 1 - Type - Boolean - Value - 0 - PickerContextOpacity Comment @@ -12315,6 +12639,18 @@ This should be as low as possible, but too low may break functionality 128 + OctreeMinimumNodeSize + + Comment + Minimum size of any octree node + Persist + 1 + Type + F32 + Value + 0.01 + + OctreeReserveNodeCapacity Comment @@ -12426,6 +12762,20 @@ This should be as low as possible, but too low may break functionality Value 1 + AlwaysRenderFriends + + Comment + 0 - Render avatars with complexity below RenderAvatarMaxComplexity +1 - Always renders friends, regardless of max complexity +2 - Only renders friends +3 - Only renders self + Persist + 1 + Type + S32 + Value + 0 + RenderAvatarCloth Comment @@ -12577,7 +12927,7 @@ This should be as low as possible, but too low may break functionality RenderCompressTextures Comment - Enable texture compression on OpenGL 3.0 and later implementations (EXPERIMENTAL, requires restart) + Enable texture compression on OpenGL 2.1 and later implementations (requires restart) Persist 1 Type @@ -12741,7 +13091,7 @@ This should be as low as possible, but too low may break functionality RenderSSAOEffect Comment - Multiplier for (1) value for areas which are totally occluded. Blends with original color for partly-occluded areas. (Third component is unused.) + Multiplier for (1) value and (2) saturation (HSV definition), for areas which are totally occluded. Blends with original color for partly-occluded areas. (Third component is unused.) Persist 1 Type @@ -12795,7 +13145,7 @@ This should be as low as possible, but too low may break functionality Type Boolean Value - 0 + 1 RenderDebugGL @@ -13229,13 +13579,13 @@ This should be as low as possible, but too low may break functionality Type F32 Value - 384 + 368.0 RenderDeferred Comment - Use deferred rendering pipeline. + Use deferred rendering pipeline (Advanced Lighting Model). Persist 1 Type @@ -13373,7 +13723,7 @@ This should be as low as possible, but too low may break functionality Type U32 Value - 4 + 4 RenderShadowBlurDistFactor @@ -13723,7 +14073,7 @@ This should be as low as possible, but too low may break functionality Type Boolean Value - 1 + 0 RenderHideGroupTitle @@ -14136,7 +14486,30 @@ This should be as low as possible, but too low may break functionality RenderAutoMuteByteLimit Comment - Maximum bytes of attachments before an avatar is automatically visually muted (0 for no limit). + If avatar attachment size exceed this value (in bytes) attachment will not be rendered. Excludes attachments worn by own avatar. + Persist + 1 + Type + U32 + Value + 0 + + MaxAttachmentComplexity + + Comment + Attachment's render weight limit + Persist + 1 + Type + F32 + Value + 1.0E6 + + RenderAvatarMaxComplexity + + Comment + Maximum Avatar Complexity; above this value, the avatar is + rendered as a solid color outline (0 to disable this limit). Persist 1 Type @@ -14147,15 +14520,27 @@ This should be as low as possible, but too low may break functionality RenderAutoMuteSurfaceAreaLimit Comment - Maximum surface area of attachments before an avatar is automatically visually muted (0 for no limit). + Maximum surface area of attachments before an avatar is + rendered as a simple impostor (to not use this limit, set to zero + or set RenderAvatarMaxComplexity to zero). Persist 1 Type F32 Value + 0 + + RenderAutoMuteLogging + + Comment + Show extra information in viewer logs about avatar rendering costs + Persist + 1 + Type + Boolean + Value 0 - RenderAutoHideSurfaceAreaLimit Comment @@ -14278,6 +14663,17 @@ This should be as low as possible, but too low may break functionality Value 1 + RevokePermsOnStandUp + + Comment + When enabled, revokes any permission granted to an object you don't own and from which your avatar is standing up + Persist + 1 + Type + Boolean + Value + 0 + RevokePermsOnStopAnimation Comment @@ -17565,17 +17961,6 @@ This should be as low as possible, but too low may break functionality Value 1 - WarnQuickTimeInstalled - - Comment - Enables QuickTimeInstalled warning dialog - Persist - 1 - Type - Boolean - Value - 1 - WarnReturnToOwner Comment @@ -18688,24 +19073,13 @@ This should be as low as possible, but too low may break functionality CrashSubmitBehavior Comment - Controls behavior when viewer crashes (0 = ask before sending crash report, 1 = always send crash report, 2 = never send crash report) - Persist - 1 - Type - S32 - Value - 0 - - CrashReportID - - Comment - ID of the last crash report sent. Zero indicates that no crash report has been sent. Non-zero value can be useful infermation for developers to track a specific issue + Controls behavior when viewer crashes (0 = never send crash report, 1 = always send crash report) Persist 1 Type S32 Value - 0 + -1 EveryoneCopy diff --git a/indra/newview/app_settings/settings_ascent.xml b/indra/newview/app_settings/settings_ascent.xml index 1146bfc16b..564e797c3c 100644 --- a/indra/newview/app_settings/settings_ascent.xml +++ b/indra/newview/app_settings/settings_ascent.xml @@ -91,6 +91,17 @@ Value 1 + ProfileNameSystem + + Comment + For a name displayed on its profile. 0 = Old Style, 1 = Display Names and Username, 2 = Displayname only, 3 = Old Style (Display Name) + Persist + 1 + Type + S32 + Value + 1 + RadarNameSystem Comment @@ -135,6 +146,28 @@ Value /resync + AlchemyChatCommandSetChatChannel + + Comment + Command to set nearby chat channel + Persist + 1 + Type + String + Value + /setchannel + + AlchemyChatCommandSetHome + + Comment + Command to set the avatar home + Persist + 1 + Type + String + Value + /sethome + AlchemyConnectToNeighbors Comment @@ -201,6 +234,17 @@ Value 1 + AlchemyNearbyChatChannel + + Comment + Chat channel used for sending nearby chat from the viewer + Persist + 0 + Type + S32 + Value + 0 + AlchemyRainbowEffects Comment @@ -243,7 +287,7 @@ Type String Value - Default.tga + Altocumulus.tga AscentPowerfulWizard @@ -521,6 +565,17 @@ Value 1 + AlchemyDisableSimCamConstraint + + Comment + Disable the push the simulator applies when camera collides with objects + Persist + 1 + Type + Boolean + Value + 0 + AscentFlyAlwaysEnabled Comment @@ -763,6 +818,17 @@ Value key2name + AscentCmdLineKeyToNameNameSystem + + Comment + For key to name command defined by AscentCmdLineKeyToName, the format to show the key's name in. 0 = Old Style, 1 = Display Names and Username, 2 = Displayname only, 3 = Old Style (Display Name) + Persist + 1 + Type + S32 + Value + 1 + AscentCmdLineOfferTp Comment @@ -818,27 +884,27 @@ Value /regionsay - SinguCmdLineURL + SinguCmdLineSetting Comment - Open SLURLS and URLs from chatbar. + Set or toggle debug settings from the chatbar. Persist 1 Type String Value - /open + /setdebug - SinguCompleteNameProfiles + SinguCmdLineURL Comment - Use the complete name "Display Name (legacy.name)" in profiles, instead of following the choice set by PhoenixNameSystem. + Open SLURLS and URLs from chatbar. Persist 1 Type - Boolean + String Value - 0 + /open SinguDefaultEaseIn @@ -862,6 +928,39 @@ Value 0 + SinguFollowDistance + + Comment + Distance at which to follow objects and avatars at, from menus that offer follow (minimum 0.5) + Persist + 1 + Type + F32 + Value + 1.0 + + SinguLastKnownReleaseBuild + + Comment + Latest known available verson. + Persist + 1 + Type + S32 + Value + 0 + + SinguLastKnownAlphaBuild + + Comment + Latest known available verson. + Persist + 1 + Type + S32 + Value + 0 + SinguMotionResetsCamera Comment @@ -873,6 +972,98 @@ Value 1 + SinguMotionResetsCameraReset + + Comment + Disable for the behavior Liru intended SinguMotionResetsCamera to have, wherein it doesn't reset every time you press escape, teleport, or whatever else! So you can walk around and your camera won't reset at all like it was meant to be. +RIP Latif Khalifa. + Persist + 1 + Type + Boolean + Value + 1 + + SinguOwnerSayAsErrors + + Comment + llOwnerSay will show up in the script error console instead of in chat. + Persist + 1 + Type + Boolean + Value + 0 + + SinguPostProcessDefault + + Comment + Default post process preset, changing this will change your active preset + Persist + 1 + Type + String + Value + Default + + SinguReplaceLinks + + Comment + Whether or not to visually replace special links like SLURLs with labels where applicable. +While having this on allows people to mislead you with links that look like other links, it also allows you to use SLURLs that appear as people's names and increasingly more scripts use this to run faster. +You can always select the text, right click and select Copy Raw to copy the hidden contents of the link. +Changing this setting only affects new text. + Persist + 1 + Type + Boolean + Value + 1 + + SupportChatDisplayBuild + + Comment + Whether or not to display your current build (and its channel indicator) when you speak in identified support group chats + Persist + 1 + Type + S32 + Value + -1 + + WarnRecommendedUpdate + + Comment + Enables recommended update notification dialog + Persist + 1 + Type + Boolean + Value + 1 + + WarnUrgentUpdate + + Comment + Enables critical update notification dialog + Persist + 1 + Type + Boolean + Value + 1 + + WarnUrgentUpdateModal + + Comment + Enables critical update modal dialog + Persist + 1 + Type + Boolean + Value + 1 + UseWebProfiles Comment @@ -951,6 +1142,61 @@ Value 3.5 + EmergencyTeleportSeconds + + Comment + The remaining time left in seconds when to execute an emergency teleport out of a restarting region. + Persist + 1 + Type + U32 + Value + 20 + + LiruEnableWIPUI + + Comment + Whether or not to enable UI components that probably don't work yet. + Persist + 1 + Type + Boolean + Value + 0 + + LiruFlashWhenMinimized + + Comment + Whether or not to flash the taskbar when a message comes in while minimized. + Persist + 1 + Type + Boolean + Value + 1 + + LiruReceivedItemsNotify + + Comment + Whether or not to spawn a notification in addition to the chat message when you receive items from the marketplace. + Persist + 1 + Type + Boolean + Value + 1 + + LiruUseMarkedColor + + Comment + Whether or not to use the color of marks done on radar and minimap to color tags and chat from those individuals + Persist + 1 + Type + Boolean + Value + 1 + OBJExportNotifyFailed Comment @@ -984,6 +1230,17 @@ Value 0 + SinguAlwaysUnderlineLinks + + Comment + Enable to always underline new links in text editors (and any you hover over after enabling this) + Persist + 1 + Type + Boolean + Value + 0 + SingularitySplashPagePrefix Comment @@ -993,7 +1250,7 @@ Type String Value - http://singularity-viewer.github.io + SingularitySplashPagePath @@ -1018,6 +1275,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleAboutLand @@ -1029,6 +1288,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleAboutRegion @@ -1040,6 +1301,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleActiveSpeakers @@ -1051,6 +1314,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleAlwaysRun @@ -1062,6 +1327,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleAnimsExplorer @@ -1073,6 +1340,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleAO @@ -1084,6 +1353,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleAppearance @@ -1095,6 +1366,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleAreaSearch @@ -1106,6 +1379,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleAssetBlacklist @@ -1117,6 +1392,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleAutoReplace @@ -1128,6 +1405,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleAvatar @@ -1139,6 +1418,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleBeacons @@ -1150,6 +1431,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleBuild @@ -1161,6 +1444,8 @@ Boolean Value 1 + IsCOA + 1 ToolbarVisibleBuyCurrency @@ -1172,6 +1457,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleBuyLand @@ -1183,6 +1470,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleCameraControls @@ -1194,6 +1483,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleChatbar @@ -1205,6 +1496,8 @@ Boolean Value 1 + IsCOA + 1 ToolbarVisibleChatHistory @@ -1216,6 +1509,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleCommunicate @@ -1227,6 +1522,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleCommunicateIM @@ -1238,6 +1535,8 @@ Boolean Value 1 + IsCOA + 1 ToolbarVisibleComplaintReporter @@ -1249,6 +1548,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleDayCycle @@ -1260,6 +1561,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleDebugAvatar @@ -1271,6 +1574,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleDebugConsole @@ -1282,6 +1587,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleDebugSettings @@ -1293,6 +1600,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleDestinations @@ -1304,6 +1613,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleDisplayName @@ -1315,6 +1626,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleEditUI @@ -1326,6 +1639,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleEnvSettings @@ -1337,6 +1652,21 @@ Boolean Value 0 + IsCOA + 1 + + ToolbarVisibleExperiences + + Comment + Whether or not the button for the experiences floater is on the toolbar + Persist + 1 + Type + Boolean + Value + 0 + IsCOA + 1 ToolbarVisibleFastTimers @@ -1348,6 +1678,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleFly @@ -1359,6 +1691,8 @@ Boolean Value 1 + IsCOA + 1 ToolbarVisibleFontTest @@ -1370,6 +1704,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleFrameConsole @@ -1381,6 +1717,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleFriends @@ -1392,6 +1730,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleGestures @@ -1403,6 +1743,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleGodTools @@ -1414,6 +1756,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleGridOptions @@ -1425,6 +1769,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleGroups @@ -1436,6 +1782,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleGroupTitles @@ -1447,6 +1795,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleHelpTutorial @@ -1471,6 +1823,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleHTTPConsole @@ -1482,6 +1836,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleInspect @@ -1493,6 +1849,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleInventory @@ -1504,6 +1862,8 @@ Boolean Value 1 + IsCOA + 1 ToolbarVisibleInventoryFavs @@ -1515,6 +1875,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleInventoryOutfits @@ -1526,28 +1888,34 @@ Boolean Value 0 + IsCOA + 1 - ToolbarVisibleJoystick + ToolbarVisibleInventoryReceivedItems Comment - Whether or not the button for joystick configuration is on the toolbar + Whether or not the button for received items is on the toolbar Persist 1 Type Boolean Value 0 + IsCOA + 1 - ToolbarVisibleLagMeter + ToolbarVisibleJoystick Comment - Whether or not the button for lag meter is on the toolbar + Whether or not the button for joystick configuration is on the toolbar Persist 1 Type Boolean Value 0 + IsCOA + 1 ToolbarVisibleLocalAssets @@ -1559,6 +1927,34 @@ Boolean Value 0 + IsCOA + 1 + + ToolbarVisibleMarketplace + + Comment + Whether or not the button for marketplace is on the toolbar + Persist + 1 + Type + Boolean + Value + 0 + IsCOA + 1 + + ToolbarVisibleMarketplaceListings + + Comment + Whether or not the button for marketplace listings is on the toolbar + Persist + 1 + Type + Boolean + Value + 0 + IsCOA + 1 ToolbarVisibleMeanEvents @@ -1570,6 +1966,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleMediaFilter @@ -1581,6 +1979,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleMediaTicker @@ -1592,6 +1992,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleMemLeak @@ -1603,6 +2005,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleMessageLog @@ -1614,6 +2018,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleMiniMap @@ -1625,6 +2031,8 @@ Boolean Value 1 + IsCOA + 1 ToolbarVisibleMouselook @@ -1636,6 +2044,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleMovementControls @@ -1647,6 +2057,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleMuteList @@ -1658,6 +2070,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleMyLand @@ -1669,17 +2083,8 @@ Boolean Value 0 - - ToolbarVisibleOutbox - - Comment - Whether or not the button for outbox is on the toolbar - Persist + IsCOA 1 - Type - Boolean - Value - 0 ToolbarVisibleNotificationsConsole @@ -1691,17 +2096,8 @@ Boolean Value 0 - - ToolbarVisibleOutbox - - Comment - Whether or not the button for the merchant outbox is on the toolbar - Persist + IsCOA 1 - Type - Boolean - Value - 0 ToolbarVisibleOutfit @@ -1713,6 +2109,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisiblePathfindingCharacters @@ -1724,6 +2122,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisiblePathfindingLinksets @@ -1735,6 +2135,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisiblePermPrefs @@ -1746,6 +2148,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisiblePostProcess @@ -1757,6 +2161,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisiblePreferences @@ -1768,6 +2174,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleQuit @@ -1779,6 +2187,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleRadar @@ -1790,6 +2200,8 @@ Boolean Value 1 + IsCOA + 1 ToolbarVisibleRegionDebugConsole @@ -1801,6 +2213,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleRegionTracker @@ -1812,6 +2226,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleScriptErrors @@ -1823,6 +2239,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleScriptInfo @@ -1834,6 +2252,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleSearch @@ -1845,6 +2265,8 @@ Boolean Value 1 + IsCOA + 1 ToolbarVisibleSit @@ -1856,6 +2278,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleSnapshot @@ -1867,6 +2291,8 @@ Boolean Value 1 + IsCOA + 1 ToolbarVisibleSoundExplorer @@ -1878,6 +2304,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleStatBar @@ -1889,6 +2317,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleTeleportHistory @@ -1900,6 +2330,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleTest @@ -1911,6 +2343,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleTextureCategoryConsole @@ -1922,6 +2356,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleTextureConsole @@ -1933,6 +2369,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleTextureSizeConsole @@ -1944,6 +2382,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleToolbarPrefs @@ -1955,6 +2395,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleVelocity @@ -1966,6 +2408,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleVoiceEffect @@ -1977,6 +2421,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleWaterSettings @@ -1988,6 +2434,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleWeb @@ -1999,6 +2447,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleWindlight @@ -2010,6 +2460,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleWorldMap @@ -2021,6 +2473,8 @@ Boolean Value 1 + IsCOA + 1 ToolbarVisibleRLVLocks @@ -2033,6 +2487,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleRLVRestrictions @@ -2044,6 +2500,8 @@ Boolean Value 0 + IsCOA + 1 ToolbarVisibleRLVStrings @@ -2055,6 +2513,8 @@ Boolean Value 0 + IsCOA + 1 diff --git a/indra/newview/app_settings/settings_crash_behavior.xml b/indra/newview/app_settings/settings_crash_behavior.xml deleted file mode 100644 index 74704f8adb..0000000000 --- a/indra/newview/app_settings/settings_crash_behavior.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - CrashSubmitBehavior - - Comment - Controls behavior when viewer crashes (0 = ask before sending crash report, 1 = always send crash report, 2 = never send crash report) - Persist - 2 - Type - S32 - Value - 1 - - - diff --git a/indra/newview/app_settings/settings_files.xml b/indra/newview/app_settings/settings_files.xml index ac304f7593..cfb4504f2d 100644 --- a/indra/newview/app_settings/settings_files.xml +++ b/indra/newview/app_settings/settings_files.xml @@ -43,13 +43,6 @@ Requirement 1 - CrashSettings - - Name - settings_crash_behavior.xml - Requirement - 1 - User @@ -65,11 +58,6 @@ NameFromSetting ClientSettingsFile - CrashSettings - - Name - settings_crash_behavior.xml - Account diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 2dd4904f47..27a01079cb 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -186,6 +186,61 @@ Value + AODefaultTyping + + Comment + Default typing anim + Persist + 1 + Type + String + Value + + + AODefaultFloat + + Comment + Default float anim + Persist + 1 + Type + String + Value + + + AODefaultSwim + + Comment + Default swim anim + Persist + 1 + Type + String + Value + + + AODefaultSwimUp + + Comment + Default swimup anim + Persist + 1 + Type + String + Value + + + AODefaultSwimDown + + Comment + Default swimdown anim + Persist + 1 + Type + String + Value + + AODefaultStandUp Comment @@ -715,6 +770,17 @@ Value -%Y-%m + ShowFavoritesOnLogin + + Comment + Determines whether favorites of last logged in user will be saved on exit from viewer and shown on login screen + Persist + 1 + Type + Boolean + Value + 1 + KeywordsChangeColor diff --git a/indra/newview/app_settings/settings_sh.xml b/indra/newview/app_settings/settings_sh.xml index c06a6f7106..f9b11e704f 100644 --- a/indra/newview/app_settings/settings_sh.xml +++ b/indra/newview/app_settings/settings_sh.xml @@ -216,7 +216,18 @@ Type F32 Value - 0.09 + 0.18 + + SHAutoMaskMaxMid + + Comment + Sets the maximum percent of mid-range alpha pixels textures for alphamasking. (SHUseRMSEAutoMask must be TRUE for this to have any effect) + Persist + 1 + Type + F32 + Value + 0.25 SHAlwaysSoftenShadows @@ -262,5 +273,16 @@ Value 0 + SHSkipResetVBOsOnTeleport + + Comment + Skip VBO auto-recreation upon teleport. Setting to true may help avoid attachments dissipearing on teleport. + Persist + 1 + Type + Boolean + Value + 0 + diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index 2bd85f88b3..adcb92a98a 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -26,7 +26,7 @@ ATTRIBUTE vec4 weight4; -uniform mat3x4 matrixPalette[52]; +uniform mat3x4 matrixPalette[MAX_JOINTS_PER_MESH_OBJECT]; uniform float maxWeight; mat4 getObjectSkinnedTransform() diff --git a/indra/newview/app_settings/shaders/class1/deferred/SSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/SSAOF.glsl index 64c4e41cfc..acb2f173ed 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/SSAOF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/SSAOF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -33,42 +33,20 @@ out vec4 frag_color; VARYING vec2 vary_fragcoord; -uniform sampler2DRect depthMapDownsampled; -uniform sampler2DRect normalMap; +uniform sampler2D depthMapDownsampled; +uniform sampler2D normalMap; uniform sampler2D noiseMap; -uniform vec2 screen_res; uniform mat4 inv_proj; -uniform float downsampled_depth_scale; - uniform float ssao_radius; uniform float ssao_max_radius; uniform float ssao_factor; +uniform vec2 kern_scale; +uniform vec2 noise_scale; -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMapDownsampled, pos_screen.xy*downsampled_depth_scale).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +vec3 decode_normal(vec2 enc); +vec4 getPosition(vec2 pos_screen); vec2 getKern(int i) { @@ -90,7 +68,7 @@ vec2 getKern(int i) float calcAmbientOcclusion(vec4 pos, vec3 norm) { vec2 pos_screen = vary_fragcoord.xy; - vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; + vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy * noise_scale).xy; // We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place. float points = 1.0; @@ -98,13 +76,13 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) // use a kernel scale that diminishes with distance. // a scale of less than 32 is just wasting good samples, though. - float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius)); + vec2 scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius)) * kern_scale; // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) for (int i = 0; i < 8; i++) { vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect); - vec3 samppos_world = getPosition(samppos_screen).xyz; + vec3 samppos_world = getPosition(samppos_screen).xyz; vec3 diff = samppos_world - pos.xyz; @@ -119,8 +97,9 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) points += 1.0; } } - + angle_hidden /= points; + float rtn = (1.0 - angle_hidden); return (rtn * rtn) * (rtn * rtn); //Pow2 to increase darkness to match previous behavior. } @@ -133,7 +112,7 @@ void main() vec4 pos = getPosition(pos_screen); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + vec3 norm = texture2D(normalMap, pos_screen).xyz; norm = decode_normal(norm.xy); frag_color = vec4(calcAmbientOcclusion(pos,norm),0,0,0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index 8ca317cce4..334c3e0dbf 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #define INDEXED 1 #define NON_INDEXED 2 @@ -93,66 +93,16 @@ vec3 vary_AdditiveColor; vec3 vary_AtmosAttenuation; uniform mat4 inv_proj; -uniform vec2 screen_res; uniform vec4 light_position[8]; uniform vec3 light_direction[8]; uniform vec3 light_attenuation[8]; uniform vec3 light_diffuse[8]; -vec3 srgb_to_linear(vec3 cs) -{ - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lte.r ? low_range.r : high_range.r; - result.g = lte.g ? low_range.g : high_range.g; - result.b = lte.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lte); -#endif - -} - -vec3 linear_to_srgb(vec3 cl) -{ - cl = clamp(cl, vec3(0), vec3(1)); - vec3 low_range = cl * 12.92; - vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; - bvec3 lt = lessThan(cl,vec3(0.0031308)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lt.r ? low_range.r : high_range.r; - result.g = lt.g ? low_range.g : high_range.g; - result.b = lt.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lt); -#endif - -} - -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} +vec2 encode_normal(vec3 n); +vec3 decode_normal(vec2 enc); +vec3 srgb_to_linear(vec3 cs); +vec3 linear_to_srgb(vec3 cl); vec3 calcDirectionalLight(vec3 n, vec3 l) { @@ -486,7 +436,6 @@ void main() #if HAS_SHADOW vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; vec4 spos = pos; if (spos.z > -shadow_clip.w) diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index 662c762bca..e52ff0e22f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -36,11 +36,7 @@ uniform float minimum_alpha; VARYING vec3 vary_normal; VARYING vec2 vary_texcoord0; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} +vec2 encode_normal(vec3 n); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 80c0c6e7bc..27d2991b17 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,20 +31,21 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform sampler2DRect lightMap; +uniform sampler2D depthMap; +uniform sampler2D normalMap; +uniform sampler2D lightMap; uniform float dist_factor; uniform float blur_size; uniform vec2 delta; -//uniform vec3 kern[4]; -uniform float kern_scale; +uniform vec2 kern_scale; VARYING vec2 vary_fragcoord; uniform mat4 inv_proj; -uniform vec2 screen_res; + +vec3 decode_normal(vec2 enc); +vec4 getPosition(vec2 pos_screen); vec2 getKern(int i) { @@ -57,46 +58,16 @@ vec2 getKern(int i) return kern[i]; } -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} - void main() { - vec2 tc = vary_fragcoord.xy; - vec3 norm = texture2DRect(normalMap, tc).xyz; + vec2 tc = vary_fragcoord.xy; + vec3 norm = texture2D(normalMap, tc).xyz; norm = decode_normal(norm.xy); // unpack norm vec3 pos = getPosition(tc).xyz; - vec4 ccol = texture2DRect(lightMap, tc).rgba; - - vec2 dlt = kern_scale * delta / (vec2(1.0)+norm.xy*norm.xy); + vec4 ccol = texture2D(lightMap, tc).rgba; + + vec2 dlt = delta / (vec2(1.0)+norm.xy*norm.xy); dlt /= max(-pos.z*dist_factor, 1.0); vec2 defined_weight = getKern(0).xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' @@ -106,20 +77,20 @@ void main() float pointplanedist_tolerance_pow2 = pos.z*-0.001; // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large - vec2 tc_v = fract(0.5 * tc.xy); // we now have floor(mod(tc,2.0))*0.5 + vec2 tc_v = fract(0.5 * tc.xy / kern_scale); // we now have floor(mod(tc,2.0))*0.5 float tc_mod = 2.0 * abs(tc_v.x - tc_v.y); // diff of x,y makes checkerboard - tc += ( (tc_mod - 0.5) * dlt * 0.5 ); + tc += ( (tc_mod - 0.5) * dlt * 0.5 ) * kern_scale; for (int i = 1; i < 4; i++) { vec2 samptc = (tc + i * dlt); - vec3 samppos = getPosition(samptc).xyz; + vec3 samppos = getPosition(samptc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane if (d*d <= pointplanedist_tolerance_pow2) { vec4 weight = getKern(i).xyxx; - col += texture2DRect(lightMap, samptc)*weight; + col += texture2D(lightMap, samptc)*weight; defined_weight += weight.xy; } } @@ -132,7 +103,7 @@ void main() if (d*d <= pointplanedist_tolerance_pow2) { vec4 weight = getKern(i).xyxx; - col += texture2DRect(lightMap, samptc)*weight; + col += texture2D(lightMap, samptc)*weight; defined_weight += weight.xy; } } diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl deleted file mode 100644 index 212f7e56ad..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @file blurLightF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; - -VARYING vec2 vary_fragcoord; -uniform vec2 screen_res; - -void main() -{ - //transform vertex - vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); - gl_Position = pos; - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 595c11fae2..3827f4759c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -39,11 +39,7 @@ VARYING vec3 vary_mat2; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} +vec2 encode_normal(vec3 n); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl index bf04caba57..16117acb3d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,8 +31,8 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect diffuseRect; -uniform sampler2DRect depthMap; +uniform sampler2D diffuseRect; +uniform sampler2D depthMap; uniform sampler2D bloomMap; uniform float depth_cutoff; @@ -44,13 +44,12 @@ uniform float magnification; uniform float max_cof; uniform mat4 inv_proj; -uniform vec2 screen_res; VARYING vec2 vary_fragcoord; float getDepth(vec2 pos_screen) { - float z = texture2DRect(depthMap, pos_screen.xy).r; + float z = texture2D(depthMap, pos_screen.xy).r; z = z*2.0-1.0; vec4 ndc = vec4(0.0, 0.0, z, 1.0); vec4 p = inv_proj*ndc; @@ -78,13 +77,13 @@ void main() float depth = getDepth(tc); - vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); + vec4 diff = texture2D(diffuseRect, vary_fragcoord.xy); float sc = calc_cof(depth); sc = min(sc, max_cof); sc = max(sc, -max_cof); - vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res); + vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy); frag_color.rgb = diff.rgb + bloom.rgb; frag_color.a = sc/max_cof*0.5+0.5; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/components/utilityFuncF.glsl b/indra/newview/app_settings/shaders/class1/deferred/components/utilityFuncF.glsl new file mode 100644 index 0000000000..806e651697 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/components/utilityFuncF.glsl @@ -0,0 +1,104 @@ +/** + * @file utilityFuncF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat4 inv_proj; +uniform vec2 screen_res; +uniform sampler2D depthMap; + +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal(vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2D(depthMap, pos_screen.xy).r; + vec2 sc = pos_screen.xy*2.0; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + vec3 result; +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lte); +#endif +} + +vec4 srgb_to_linear(vec4 cs) +{ + return vec4(srgb_to_linear(cs.rgb), cs.a); +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + + bvec3 lt = lessThan(cl,vec3(0.0031308)); +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + +vec4 linear_to_srgb(vec4 cl) +{ + return vec4(linear_to_srgb(cl.rgb), cl.a); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl index 7930b5d18b..7310f1ebbd 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl @@ -37,11 +37,7 @@ VARYING vec3 vary_normal; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} +vec2 encode_normal(vec3 n); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl index 8525e13333..08ce605258 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl @@ -36,11 +36,7 @@ uniform float minimum_alpha; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} +vec2 encode_normal(vec3 n); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl index 37d70a2412..e6de9bcf03 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl @@ -37,11 +37,7 @@ uniform sampler2D diffuseMap; VARYING vec3 vary_normal; VARYING vec2 vary_texcoord0; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} +vec2 encode_normal(vec3 n); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 6befb1bd8b..d104c7d025 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -35,11 +35,7 @@ VARYING vec3 vary_normal; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} +vec2 encode_normal(vec3 n); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl index adc361d7a2..4a195bbb34 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl @@ -33,12 +33,7 @@ VARYING vec3 vary_normal; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - +vec2 encode_normal(vec3 n); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl index 9ddeae18d8..550d2fa073 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,34 +31,34 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect diffuseRect; -uniform sampler2DRect lightMap; +uniform sampler2D diffuseRect; +uniform sampler2D lightMap; uniform mat4 inv_proj; -uniform vec2 screen_res; uniform float max_cof; uniform float res_scale; uniform float dof_width; uniform float dof_height; +uniform vec2 kern_scale; VARYING vec2 vary_fragcoord; -vec4 dofSample(sampler2DRect tex, vec2 tc) +vec4 dofSample(sampler2D tex, vec2 tc) { tc.x = min(tc.x, dof_width); tc.y = min(tc.y, dof_height); - return texture2DRect(tex, tc); + return texture2D(tex, tc); } void main() { - vec2 tc = vary_fragcoord.xy; + vec2 tc = vary_fragcoord.xy * res_scale; - vec4 dof = dofSample(diffuseRect, vary_fragcoord.xy*res_scale); + vec4 dof = dofSample(diffuseRect, tc); - vec4 diff = texture2DRect(lightMap, vary_fragcoord.xy); + vec4 diff = texture2D(lightMap, vary_fragcoord.xy); float a = min(abs(diff.a*2.0-1.0) * max_cof*res_scale*res_scale, 1.0); @@ -67,10 +67,10 @@ void main() float sc = a/res_scale; vec4 col; - col = texture2DRect(lightMap, vary_fragcoord.xy+vec2(sc,sc)); - col += texture2DRect(lightMap, vary_fragcoord.xy+vec2(-sc,sc)); - col += texture2DRect(lightMap, vary_fragcoord.xy+vec2(sc,-sc)); - col += texture2DRect(lightMap, vary_fragcoord.xy+vec2(-sc,-sc)); + col = texture2D(lightMap, vary_fragcoord.xy+vec2(sc,sc)*kern_scale); + col += texture2D(lightMap, vary_fragcoord.xy+vec2(-sc,sc)*kern_scale); + col += texture2D(lightMap, vary_fragcoord.xy+vec2(sc,-sc)*kern_scale); + col += texture2D(lightMap, vary_fragcoord.xy+vec2(-sc,-sc)*kern_scale); diff = mix(diff, col*0.25, a); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/downsampleDepthNearestF.glsl b/indra/newview/app_settings/shaders/class1/deferred/downsampleDepthNearestF.glsl index 9b6355fb9f..89eff19785 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/downsampleDepthNearestF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/downsampleDepthNearestF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,11 +31,11 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect depthMap; +uniform sampler2D depthMap; VARYING vec2 vary_fragcoord; void main() { - gl_FragDepth = texture2DRect(depthMap, vary_fragcoord.xy).r; + gl_FragDepth = texture2D(depthMap, vary_fragcoord.xy).r; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl b/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl index 34efdb10a2..4fa5f7a9bd 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -39,16 +39,10 @@ VARYING vec2 vary_texcoord0; void main() { - float shadow = 1.0; - - vec4 color = diffuseLookup(vary_texcoord0.xy)*vertex_color; - if(color.a < .01) + float alpha = diffuseLookup(vary_texcoord0.xy).a*vertex_color.a; + if(alpha < .01) discard; - color.rgb = pow(color.rgb, vec3(2.2)); - color.rgb = fullbrightAtmosTransport(color.rgb); - - color.rgb = fullbrightScaleSoftClip(color.rgb); - frag_color = color; + frag_color = vec4(0,0,0,alpha); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl b/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl index 115b04797f..3252b441ff 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl @@ -46,17 +46,12 @@ VARYING vec2 vary_texcoord0; void main() { - //transform vertex - vec4 vert = vec4(position.xyz, 1.0); - vec4 pos = (modelview_matrix * vert); passTextureIndex(); gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - calcAtmospherics(pos.xyz); - vertex_color = emissive; diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index 167c2ae732..5e73b8be0b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -39,43 +39,8 @@ VARYING vec3 vary_position; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; - -vec3 srgb_to_linear(vec3 cs) -{ - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lte.r ? low_range.r : high_range.r; - result.g = lte.g ? low_range.g : high_range.g; - result.b = lte.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lte); -#endif - -} - -vec3 linear_to_srgb(vec3 cl) -{ - cl = clamp(cl, vec3(0), vec3(1)); - vec3 low_range = cl * 12.92; - vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; - bvec3 lt = lessThan(cl,vec3(0.0031308)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lt.r ? low_range.r : high_range.r; - result.g = lt.g ? low_range.g : high_range.g; - result.b = lt.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lt); -#endif - -} +vec3 srgb_to_linear(vec3 cs); +vec3 linear_to_srgb(vec3 cl); vec3 fullbrightAtmosTransportDeferred(vec3 light) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl index 13409832ab..aa914aa030 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl @@ -22,9 +22,6 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - -//#extension GL_ARB_texture_rectangle : enable -//#extension GL_ARB_shader_texture_lod : enable #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -34,7 +31,9 @@ out vec4 frag_color; #define FXAA_PC 1 //#define FXAA_GLSL_130 1 +#ifndef FXAA_QUALITY_M_PRESET #define FXAA_QUALITY_M_PRESET 12 +#endif /*============================================================================ @@ -258,6 +257,10 @@ A. Or use FXAA_GREEN_AS_LUMA. #define FXAA_GLSL_130 0 #endif /*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_400 + #define FXAA_GLSL_400 0 +#endif +/*--------------------------------------------------------------------------*/ #ifndef FXAA_HLSL_3 #define FXAA_HLSL_3 0 #endif @@ -344,8 +347,8 @@ A. Or use FXAA_GREEN_AS_LUMA. // 1 = API supports gather4 on alpha channel. // 0 = API does not support gather4 on alpha channel. // - #if (FXAA_GLSL_130 == 0) - #define FXAA_GATHER4_ALPHA 0 + #if (FXAA_GLSL_400 == 1) + #define FXAA_GATHER4_ALPHA 1 #endif #if (FXAA_HLSL_5 == 1) #define FXAA_GATHER4_ALPHA 1 @@ -654,7 +657,7 @@ NOTE the other tuning knobs are now in the shader function inputs! API PORTING ============================================================================*/ -#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) +#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) || (FXAA_GLSL_400 == 1) #define FxaaBool bool #define FxaaDiscard discard #define FxaaFloat float @@ -716,6 +719,16 @@ NOTE the other tuning knobs are now in the shader function inputs! #endif #endif /*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_400 == 1) + // Requires "#version 400" or better + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) +#endif +/*--------------------------------------------------------------------------*/ #if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) #define FxaaInt2 float2 #define FxaaTex sampler2D @@ -2095,11 +2108,10 @@ uniform vec2 rcp_screen_res; uniform vec4 rcp_frame_opt; uniform vec4 rcp_frame_opt2; VARYING vec2 vary_fragcoord; -VARYING vec2 vary_tc; void main() { - vec4 diff = FxaaPixelShader(vary_tc, //pos + vec4 diff = FxaaPixelShader(vary_fragcoord, //pos vec4(vary_fragcoord.xy, 0, 0), //fxaaConsolePosPos diffuseMap, //tex diffuseMap, diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index f8fdde43f9..5062858496 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -38,41 +38,7 @@ uniform sampler2D specularMap; VARYING vec2 vary_texcoord0; -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} - -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - -vec3 linear_to_srgb(vec3 cl) -{ - cl = clamp(cl, vec3(0), vec3(1)); - vec3 low_range = cl * 12.92; - vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; - bvec3 lt = lessThan(cl,vec3(0.0031308)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lt.r ? low_range.r : high_range.r; - result.g = lt.g ? low_range.g : high_range.g; - result.b = lt.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lt); -#endif - -} +vec3 linear_to_srgb(vec3 cs); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl deleted file mode 100644 index dcf474824d..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @file luminanceF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform sampler2DRect diffuseMap; - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -VARYING vec2 vary_fragcoord; - -void main() -{ - frag_color = texture2DRect(diffuseMap, vary_fragcoord.xy); -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl deleted file mode 100644 index f2dc60aa5d..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file giV.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; -ATTRIBUTE vec4 diffuse_color; - -VARYING vec2 vary_fragcoord; -VARYING vec4 vertex_color; - -uniform vec2 screen_res; - -void main() -{ - //transform vertex - vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); - gl_Position = pos; - - vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; - - vertex_color = diffuse_color; -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index 91e16af4b9..2484c9cd4e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -29,44 +29,11 @@ #define DIFFUSE_ALPHA_MODE_EMISSIVE 3 uniform float emissive_brightness; -//uniform float display_gamma; -vec3 srgb_to_linear(vec3 cs) -{ - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lte.r ? low_range.r : high_range.r; - result.g = lte.g ? low_range.g : high_range.g; - result.b = lte.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lte); -#endif - -} - -vec3 linear_to_srgb(vec3 cl) -{ - cl = clamp(cl, vec3(0), vec3(1)); - vec3 low_range = cl * 12.92; - vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; - bvec3 lt = lessThan(cl,vec3(0.0031308)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lt.r ? low_range.r : high_range.r; - result.g = lt.g ? low_range.g : high_range.g; - result.b = lt.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lt); -#endif - -} +vec2 encode_normal(vec3 n); +vec3 decode_normal(vec2 enc); +vec3 srgb_to_linear(vec3 cs); +vec3 linear_to_srgb(vec3 cl); #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) @@ -147,7 +114,6 @@ vec3 vary_AdditiveColor; vec3 vary_AtmosAttenuation; uniform mat4 inv_proj; -uniform vec2 screen_res; uniform vec4 light_position[8]; uniform vec3 light_direction[8]; @@ -273,18 +239,6 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe } -vec4 getPosition_d(vec2 pos_screen, float depth) -{ - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - #ifndef WATER_FOG vec3 getPositionEye() { @@ -507,23 +461,6 @@ VARYING vec3 vary_normal; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} - void main() { vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy); @@ -537,10 +474,12 @@ void main() #endif #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) + #if (HAS_SPECULAR_MAP == 0) if(diffcol.a < .01) { discard; } + #endif vec3 gamma_diff = diffcol.rgb; diffcol.rgb = srgb_to_linear(diffcol.rgb); #endif @@ -761,7 +700,7 @@ void main() col.rgb += light.rgb; - glare = min(glare, 1.0); + glare = min(glare, 1.0)/* * diffcol.a*/; float al = max(diffcol.a,glare)*vertex_color.a; //convert to gamma space for display on screen diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl index 5b977924ec..e4d3994f50 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl @@ -46,7 +46,6 @@ uniform mat4 modelview_matrix; VARYING vec3 vary_position; #if HAS_SUN_SHADOW VARYING vec2 vary_fragcoord; -uniform vec2 screen_res; #endif #endif @@ -126,7 +125,6 @@ vary_normal = n; #if HAS_NORMAL_MAP vec3 t = normalize(normal_matrix * tangent.xyz); vec3 b = cross(n,t)*tangent.w; - //vec3 t = cross(b,n) * binormal.w; vary_mat0 = vec3(t.x, b.x, n.x); vary_mat1 = vec3(t.y, b.y, n.y); @@ -144,7 +142,7 @@ vary_normal = n; vary_position = pos; #endif #if HAS_SUN_SHADOW - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; + vary_fragcoord = (pos.xy*0.5+0.5); #endif #endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index d45d41f8ed..4e84d38b7d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,10 +31,10 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect depthMap; -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect normalMap; +uniform sampler2D depthMap; +uniform sampler2D diffuseRect; +uniform sampler2D specularRect; +uniform sampler2D normalMap; uniform samplerCube environmentMap; uniform sampler2D noiseMap; uniform sampler2D lightFunc; @@ -49,58 +49,31 @@ uniform vec4 light[LIGHT_COUNT]; uniform vec4 light_col[LIGHT_COUNT]; VARYING vec4 vary_fragcoord; -uniform vec2 screen_res; uniform float far_z; uniform mat4 inv_proj; +uniform vec2 noise_scale; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +vec3 decode_normal(vec2 enc); +vec4 getPosition(vec2 pos_screen); void main() { - vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res; + vec2 frag = (vary_fragcoord.xy*0.5+0.5); vec3 pos = getPosition(frag.xy).xyz; if (pos.z < far_z) { discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + vec3 norm = texture2D(normalMap, frag.xy).xyz; norm = decode_normal(norm.xy); // unpack norm norm = normalize(norm); - vec4 spec = texture2DRect(specularRect, frag.xy); - vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb; + vec4 spec = texture2D(specularRect, frag.xy); + vec3 diff = texture2D(diffuseRect, frag.xy).rgb; - float noise = texture2D(noiseMap, frag.xy/128.0).b; + float noise = texture2D(noiseMap, frag.xy*noise_scale).b; vec3 out_col = vec3(0,0,0); vec3 npos = normalize(-pos); diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index 2d6a69cf6e..65d6e1a802 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -31,13 +31,10 @@ out vec4 frag_color; //class 1 -- no shadows -//#extension GL_ARB_texture_rectangle : enable -//#extension GL_ARB_shader_texture_lod : enable - -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; +uniform sampler2D diffuseRect; +uniform sampler2D specularRect; +uniform sampler2D depthMap; +uniform sampler2D normalMap; uniform samplerCube environmentMap; uniform sampler2D noiseMap; uniform sampler2D projectionMap; @@ -64,65 +61,34 @@ uniform float falloff; uniform float size; VARYING vec4 vary_fragcoord; -uniform vec2 screen_res; uniform mat4 inv_proj; +uniform vec2 noise_scale; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} -vec3 srgb_to_linear(vec3 cs) -{ - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lte.r ? low_range.r : high_range.r; - result.g = lte.g ? low_range.g : high_range.g; - result.b = lte.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lte); -#endif - -} +vec3 decode_normal(vec2 enc); +vec4 getPosition(vec2 pos_screen); +vec4 srgb_to_linear(vec4 cs); vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret.rgb = srgb_to_linear(ret.rgb); - - vec2 dist = tc-vec2(0.5); - - float det = max(1.0-lod/(proj_lod*0.5), 0.0); - - float d = dot(dist,dist); - - ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); - + + ret = srgb_to_linear(ret); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + float det = min(lod/(proj_lod*0.5), 1.0); + float d = min(dist.x, dist.y); + d *= min(1, d * (proj_lod - lod)); + float edge = 0.25*det; + ret *= clamp(d/edge, 0.0, 1.0); + return ret; } vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret.rgb = srgb_to_linear(ret.rgb); - + ret = srgb_to_linear(ret); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); float det = min(lod/(proj_lod*0.5), 1.0); @@ -139,7 +105,7 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret.rgb = srgb_to_linear(ret.rgb); + ret = srgb_to_linear(ret); vec2 dist = tc-vec2(0.5); @@ -150,26 +116,11 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) return ret; } - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - void main() { vec4 frag = vary_fragcoord; frag.xyz /= frag.w; frag.xyz = frag.xyz*0.5+0.5; - frag.xy *= screen_res; vec3 pos = getPosition(frag.xy).xyz; vec3 lv = center.xyz-pos.xyz; @@ -179,8 +130,9 @@ void main() { discard; } - - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + + vec3 norm = texture2D(normalMap, frag.xy).xyz; + float envIntensity = norm.z; norm = decode_normal(norm.xy); @@ -209,13 +161,13 @@ void main() lv = proj_origin-pos.xyz; lv = normalize(lv); float da = dot(norm, lv); - + vec3 col = vec3(0,0,0); - - vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + + vec3 diff_tex = texture2D(diffuseRect, frag.xy).rgb; vec3 dlit = vec3(0, 0, 0); - - float noise = texture2D(noiseMap, frag.xy/128.0).b; + + float noise = texture2D(noiseMap, frag.xy*noise_scale).b; if (proj_tc.z > 0.0 && proj_tc.x < 1.0 && proj_tc.y < 1.0 && @@ -227,32 +179,34 @@ void main() if (da > 0.0) { + lit = da * dist_atten * noise; + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); - + dlit = color.rgb * plcol.rgb * plcol.a; - - lit = da * dist_atten * noise; - + col = dlit*lit*diff_tex; amb_da += (da*0.5)*proj_ambiance; } + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); - + amb_da += (da*da*0.5+0.5)*proj_ambiance; - + amb_da *= dist_atten * noise; - + amb_da = min(amb_da, 1.0-lit); - col += amb_da*color.rgb*diff_tex*amb_plcol.rgb*amb_plcol.a; + + col += amb_da*color*diff_tex*amb_plcol.rgb*amb_plcol.a; } - - - vec4 spec = texture2DRect(specularRect, frag.xy); - + + + vec4 spec = texture2D(specularRect, frag.xy); + if (spec.a > 0.0) { dlit *= min(da*6.0, 1.0) * dist_atten; @@ -289,26 +243,27 @@ void main() if (ds < 0.0) { vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); - stc /= stc.w; + if (stc.z > 0.0) { - float fatten = clamp(envIntensity*envIntensity+envIntensity*0.25, 0.25, 1.0); - - stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); - + stc /= stc.w; + if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod).rgb*spec.rgb; + col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * envIntensity; } } } } - + + //not sure why, but this line prevents MATBUG-194 + col = max(col, vec3(0.0)); + frag_color.rgb = col; frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl b/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl index 1291cfe97a..4152ad0246 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 4d6cfa487b..664595a92d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,13 +31,13 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect normalMap; +uniform sampler2D diffuseRect; +uniform sampler2D specularRect; +uniform sampler2D normalMap; uniform samplerCube environmentMap; uniform sampler2D noiseMap; uniform sampler2D lightFunc; -uniform sampler2DRect depthMap; +uniform sampler2D depthMap; uniform vec3 env_mat[3]; uniform float sun_wash; @@ -49,47 +49,18 @@ uniform float size; VARYING vec4 vary_fragcoord; VARYING vec3 trans_center; -uniform vec2 screen_res; - uniform mat4 inv_proj; uniform vec4 viewport; +uniform vec2 noise_scale; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = (pos_screen.xy-viewport.xy)*2.0; - sc /= viewport.zw; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +vec3 decode_normal(vec2 enc); +vec4 getPosition(vec2 pos_screen); void main() { vec4 frag = vary_fragcoord; frag.xyz /= frag.w; frag.xyz = frag.xyz*0.5+0.5; - frag.xy *= screen_res; vec3 pos = getPosition(frag.xy).xyz; vec3 lv = trans_center.xyz-pos; @@ -100,7 +71,7 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + vec3 norm = texture2D(normalMap, frag.xy).xyz; norm = decode_normal(norm.xy); // unpack norm float da = dot(norm, lv); if (da < 0.0) @@ -112,9 +83,9 @@ void main() lv = normalize(lv); da = dot(norm, lv); - float noise = texture2D(noiseMap, frag.xy/128.0).b; + float noise = texture2D(noiseMap, frag.xy*noise_scale).b; - vec3 col = texture2DRect(diffuseRect, frag.xy).rgb; + vec3 col = texture2D(diffuseRect, frag.xy).rgb; float fa = falloff+1.0; float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); dist_atten *= dist_atten; @@ -124,7 +95,7 @@ void main() col = color.rgb*lit*col; - vec4 spec = texture2DRect(specularRect, frag.xy); + vec4 spec = texture2D(specularRect, frag.xy); if (spec.a > 0.0) { lit = min(da*6.0, 1.0) * dist_atten; diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl index 46ab281fd7..0a89597b35 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,18 +31,18 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect diffuseRect; +uniform sampler2D diffuseRect; uniform mat4 inv_proj; -uniform vec2 screen_res; uniform float max_cof; uniform float res_scale; +uniform vec2 kern_scale; VARYING vec2 vary_fragcoord; void dofSample(inout vec4 diff, inout float w, float min_sc, vec2 tc) { - vec4 s = texture2DRect(diffuseRect, tc); + vec4 s = texture2D(diffuseRect, tc); float sc = abs(s.a*2.0-1.0)*max_cof; @@ -61,7 +61,7 @@ void dofSample(inout vec4 diff, inout float w, float min_sc, vec2 tc) void dofSampleNear(inout vec4 diff, inout float w, float min_sc, vec2 tc) { - vec4 s = texture2DRect(diffuseRect, tc); + vec4 s = texture2D(diffuseRect, tc); float wg = 0.25; @@ -77,7 +77,7 @@ void main() { vec2 tc = vary_fragcoord.xy; - vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); + vec4 diff = texture2D(diffuseRect, tc); { float w = 1.0; @@ -98,7 +98,7 @@ void main() float samp_x = sc*sin(ang); float samp_y = sc*cos(ang); // you could test sample coords against an interesting non-circular aperture shape here, if desired. - dofSampleNear(diff, w, sc, vary_fragcoord.xy + vec2(samp_x,samp_y)); + dofSampleNear(diff, w, sc, tc + vec2(samp_x,samp_y) * kern_scale); } sc -= 1.0; } @@ -115,7 +115,7 @@ void main() float samp_x = sc*sin(ang); float samp_y = sc*cos(ang); // you could test sample coords against an interesting non-circular aperture shape here, if desired. - dofSample(diff, w, sc, vary_fragcoord.xy + vec2(samp_x,samp_y)); + dofSample(diff, w, sc, tc + vec2(samp_x,samp_y) * kern_scale); } sc -= 1.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl deleted file mode 100644 index 690744352c..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file postDeferredGammaCorrect.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//#extension GL_ARB_texture_rectangle : enable - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -uniform sampler2DRect diffuseRect; - -uniform vec2 screen_res; -VARYING vec2 vary_fragcoord; - -//uniform float display_gamma; - -vec3 linear_to_srgb(vec3 cl) -{ - cl = clamp(cl, vec3(0), vec3(1)); - vec3 low_range = cl * 12.92; - vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; - bvec3 lt = lessThan(cl,vec3(0.0031308)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lt.r ? low_range.r : high_range.r; - result.g = lt.g ? low_range.g : high_range.g; - result.b = lt.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lt); -#endif - -} - - -void main() -{ - vec4 diff = texture2DRect(diffuseRect, vary_fragcoord); - diff.rgb = linear_to_srgb(diff.rgb); - frag_color = diff; -} - diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrectF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrectF.glsl new file mode 100644 index 0000000000..db80130546 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrectF.glsl @@ -0,0 +1,48 @@ +/** + * @file postDeferredGammaCorrect.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform sampler2D diffuseRect; + +VARYING vec2 vary_fragcoord; + +//uniform float display_gamma; + +vec3 linear_to_srgb(vec3 cl); + +void main() +{ + vec4 diff = texture2D(diffuseRect, vary_fragcoord); + diff.rgb = linear_to_srgb(diff.rgb); + frag_color = diff; +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl index b4e2ecfcc1..47b6774f90 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,17 +31,16 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect diffuseRect; +uniform sampler2D diffuseRect; uniform sampler2D bloomMap; -uniform vec2 screen_res; VARYING vec2 vary_fragcoord; void main() { - vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); + vec4 diff = texture2D(diffuseRect, vary_fragcoord.xy); - vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res); + vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy); frag_color = diff + bloom; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoTCV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoTCV.glsl index bd0cb50464..a8465d61bb 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoTCV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoTCV.glsl @@ -29,12 +29,10 @@ ATTRIBUTE vec3 position; VARYING vec2 vary_fragcoord; -uniform vec2 screen_res; - void main() { //transform vertex vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); gl_Position = pos; - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; + vary_fragcoord = (pos.xy*0.5+0.5); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl deleted file mode 100644 index 8edf5b2723..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file postDeferredV.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; - -VARYING vec2 vary_fragcoord; -VARYING vec2 vary_tc; - -uniform vec2 tc_scale; - -uniform vec2 screen_res; - -void main() -{ - //transform vertex - vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); - gl_Position = pos; - vary_tc = (pos.xy*0.5+0.5)*tc_scale; - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl index 96f9628424..3c035ef7bf 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl @@ -47,18 +47,7 @@ VARYING vec2 vary_fragcoord; uniform mat4 inv_proj; uniform vec2 screen_res; -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +vec4 getPosition(vec2 pos_screen); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index a0e5958eb4..06c5097084 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -23,8 +23,6 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable -//#extension GL_ARB_shader_texture_lod : enable #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -32,12 +30,11 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect positionMap; -uniform sampler2DRect normalMap; -uniform sampler2DRect lightMap; -uniform sampler2DRect depthMap; +uniform sampler2D diffuseRect; +uniform sampler2D specularRect; +uniform sampler2D normalMap; +uniform sampler2D lightMap; +uniform sampler2D depthMap; uniform samplerCube environmentMap; uniform sampler2D lightFunc; @@ -76,60 +73,14 @@ vec3 vary_AdditiveColor; vec3 vary_AtmosAttenuation; uniform mat4 inv_proj; -uniform vec2 screen_res; -vec3 srgb_to_linear(vec3 cs) -{ - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lte.r ? low_range.r : high_range.r; - result.g = lte.g ? low_range.g : high_range.g; - result.b = lte.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lte); -#endif - -} - -vec3 linear_to_srgb(vec3 cl) -{ - vec3 low_range = cl * 12.92; - vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; - bvec3 lt = lessThan(cl,vec3(0.0031308)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lt.r ? low_range.r : high_range.r; - result.g = lt.g ? low_range.g : high_range.g; - result.b = lt.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lt); -#endif - -} - - -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} +vec3 decode_normal(vec2 enc); +vec3 srgb_to_linear(vec3 cs); +vec3 linear_to_srgb(vec3 cl); vec4 getPosition_d(vec2 pos_screen, float depth) { vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; sc -= vec2(1.0,1.0); vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); vec4 pos = inv_proj * ndc; @@ -138,12 +89,6 @@ vec4 getPosition_d(vec2 pos_screen, float depth) return pos; } -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).a; - return getPosition_d(pos_screen, depth); -} - vec3 getPositionEye() { return vary_PositionEye; @@ -381,13 +326,13 @@ float luminance(vec3 color) void main() { vec2 tc = vary_fragcoord.xy; - float depth = texture2DRect(depthMap, tc.xy).r; + float depth = texture2D(depthMap, tc.xy).r; vec3 pos = getPosition_d(tc, depth).xyz; - vec4 norm = texture2DRect(normalMap, tc); + vec4 norm = texture2D(normalMap, tc); float envIntensity = norm.z; norm.xyz = decode_normal(norm.xy); // unpack norm - vec4 diffuse = texture2DRect(diffuseRect, tc); + vec4 diffuse = texture2D(diffuseRect, tc); //convert to gamma space diffuse.rgb = linear_to_srgb(diffuse.rgb); @@ -395,7 +340,7 @@ void main() vec3 col; float bloom = 0.0; { - vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + vec4 spec = texture2D(specularRect, vary_fragcoord.xy); bloom = spec.r*norm.w; if (norm.w < 0.5) { @@ -470,7 +415,7 @@ void main() //col.g = envIntensity; } - frag_color.rgb = col.rgb; + frag_color.rgb = col; frag_color.a = bloom; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl deleted file mode 100644 index c6031fc45a..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file softenLightF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; - -uniform vec2 screen_res; - -VARYING vec2 vary_fragcoord; -void main() -{ - //transform vertex - vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); - gl_Position = pos; - - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index 44d6b9f2be..1cecb30e69 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -23,9 +23,6 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable -//#extension GL_ARB_shader_texture_lod : enable - #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; #else @@ -34,10 +31,10 @@ out vec4 frag_color; //class 1 -- no shadows -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; +uniform sampler2D diffuseRect; +uniform sampler2D specularRect; +uniform sampler2D depthMap; +uniform sampler2D normalMap; uniform samplerCube environmentMap; uniform sampler2D noiseMap; uniform sampler2D projectionMap; @@ -58,77 +55,41 @@ uniform float far_clip; uniform vec3 proj_origin; //origin of projection to be used for angular attenuation uniform float sun_wash; -uniform float size; + uniform vec3 color; uniform float falloff; +uniform float size; VARYING vec3 trans_center; VARYING vec4 vary_fragcoord; -uniform vec2 screen_res; uniform mat4 inv_proj; +uniform vec2 noise_scale; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} - -vec3 srgb_to_linear(vec3 cs) -{ - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lte.r ? low_range.r : high_range.r; - result.g = lte.g ? low_range.g : high_range.g; - result.b = lte.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lte); -#endif - -} - -vec4 correctWithGamma(vec4 col) -{ - return vec4(srgb_to_linear(col.rgb), col.a); -} +vec3 decode_normal(vec2 enc); +vec4 getPosition(vec2 pos_screen); +vec4 srgb_to_linear(vec4 cs); vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); - - vec2 dist = tc-vec2(0.5); - - float det = max(1.0-lod/(proj_lod*0.5), 0.0); - - float d = dot(dist,dist); - - ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); - + + ret = srgb_to_linear(ret); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + float det = min(lod/(proj_lod*0.5), 1.0); + float d = min(dist.x, dist.y); + d *= min(1, d * (proj_lod - lod)); + float edge = 0.25*det; + ret *= clamp(d/edge, 0.0, 1.0); + return ret; } vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); - + ret = srgb_to_linear(ret); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); float det = min(lod/(proj_lod*0.5), 1.0); @@ -145,7 +106,7 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); + ret = srgb_to_linear(ret); vec2 dist = tc-vec2(0.5); @@ -156,26 +117,11 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) return ret; } - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - void main() { vec4 frag = vary_fragcoord; frag.xyz /= frag.w; frag.xyz = frag.xyz*0.5+0.5; - frag.xy *= screen_res; vec3 pos = getPosition(frag.xy).xyz; vec3 lv = trans_center.xyz-pos.xyz; @@ -185,10 +131,11 @@ void main() { discard; } - - - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + + vec3 norm = texture2D(normalMap, frag.xy).xyz; + float envIntensity = norm.z; + norm = decode_normal(norm.xy); norm = normalize(norm); @@ -215,26 +162,21 @@ void main() lv = proj_origin-pos.xyz; lv = normalize(lv); float da = dot(norm, lv); - - vec3 col = vec3(0,0,0); - - vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - - vec4 spec = texture2DRect(specularRect, frag.xy); - + vec3 col = vec3(0,0,0); - float noise = texture2D(noiseMap, frag.xy/128.0).b; + vec3 diff_tex = texture2D(diffuseRect, frag.xy).rgb; vec3 dlit = vec3(0, 0, 0); - + + float noise = texture2D(noiseMap, frag.xy*noise_scale).b; if (proj_tc.z > 0.0 && proj_tc.x < 1.0 && proj_tc.y < 1.0 && proj_tc.x > 0.0 && proj_tc.y > 0.0) { - float amb_da = proj_ambiance; float lit = 0.0; + float amb_da = proj_ambiance; if (da > 0.0) { @@ -242,28 +184,34 @@ void main() float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); + dlit = color.rgb * plcol.rgb * plcol.a; - + col = dlit*lit*diff_tex; - //amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; + amb_da += (da*0.5)*proj_ambiance; } + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); - + amb_da += (da*da*0.5+0.5)*proj_ambiance; - + amb_da *= dist_atten * noise; - + amb_da = min(amb_da, 1.0-lit); - col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a*diff_tex.rgb; + + col += amb_da*color*diff_tex*amb_plcol.rgb*amb_plcol.a; } - + + + vec4 spec = texture2D(specularRect, frag.xy); if (spec.a > 0.0) { dlit *= min(da*6.0, 1.0) * dist_atten; + vec3 npos = -normalize(pos); //vec3 ref = dot(pos+lv, norm); @@ -276,17 +224,15 @@ void main() float gtdenom = 2 * nh; float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); - + if (nh > 0.0) { - float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); col += dlit*scol*spec.rgb; //col += spec.rgb; } } - if (envIntensity > 0.0) { vec3 ref = reflect(normalize(pos), norm); @@ -298,29 +244,27 @@ void main() if (ds < 0.0) { vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); if (stc.z > 0.0) { - stc.xy /= stc.w; + stc /= stc.w; - float fatten = clamp(envIntensity*envIntensity+envIntensity*0.5, 0.25, 1.0); - - //stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); - stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); - if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod-envIntensity*proj_lod).rgb*spec.rgb; + col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * envIntensity; } } } } - + + //not sure why, but this line prevents MATBUG-194 + col = max(col, vec3(0.0)); + frag_color.rgb = col; frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl index bc7837291b..5177d71a08 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -25,7 +25,7 @@ //class 1, no shadow, no SSAO, should never be called -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightNoFragCoordV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightNoFragCoordV.glsl index 47e9d15fbc..e872dbf50d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightNoFragCoordV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightNoFragCoordV.glsl @@ -27,8 +27,6 @@ uniform mat4 modelview_projection_matrix; ATTRIBUTE vec3 position; -uniform vec2 screen_res; - void main() { //transform vertex diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl index a0e1af4396..cca0fa80f9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -23,7 +23,7 @@ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -33,17 +33,16 @@ out vec4 frag_color; VARYING vec2 vary_fragcoord; -uniform sampler2DRect depthMapDownsampled; -uniform sampler2DRect depthMap; +uniform sampler2D depthMap; + +uniform sampler2D diffuseRect; -uniform sampler2DRect diffuseRect; -uniform float downsampled_depth_scale; -uniform vec2 screen_res; +uniform vec2 ssao_scale; void main() { frag_color[0] = 1.0; - frag_color[1] = texture2DRect(diffuseRect,vary_fragcoord.xy*downsampled_depth_scale).r; + frag_color[1] = texture2D(diffuseRect,vary_fragcoord.xy * ssao_scale).r; // Scales to handle lower-res ssao. frag_color[2] = 1.0; frag_color[3] = 1.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl deleted file mode 100644 index 473d6df8fa..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file sunLightF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; - -VARYING vec2 vary_fragcoord; - -uniform vec2 screen_res; - -void main() -{ - //transform vertex - vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); - gl_Position = pos; - - vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 52a429465f..0474086bd1 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -39,11 +39,7 @@ VARYING vec3 vary_normal; VARYING vec4 vary_texcoord0; VARYING vec4 vary_texcoord1; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} +vec2 encode_normal(vec3 n); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index 808750496f..c5bb8ddc88 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -37,11 +37,7 @@ VARYING vec2 vary_texcoord0; uniform float minimum_alpha; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} +vec2 encode_normal(vec3 n); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl index 692df8b100..77126bd0d6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl @@ -56,48 +56,8 @@ VARYING vec4 refCoord; VARYING vec4 littleWave; VARYING vec4 view; -vec3 srgb_to_linear(vec3 cs) -{ - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lte.r ? low_range.r : high_range.r; - result.g = lte.g ? low_range.g : high_range.g; - result.b = lte.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lte); -#endif - -} - -vec3 linear_to_srgb(vec3 cl) -{ - cl = clamp(cl, vec3(0), vec3(1)); - vec3 low_range = cl * 12.92; - vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; - bvec3 lt = lessThan(cl,vec3(0.0031308)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lt.r ? low_range.r : high_range.r; - result.g = lt.g ? low_range.g : high_range.g; - result.b = lt.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lt); -#endif - -} - -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} +vec2 encode_normal(vec3 n); +vec3 encode_diffuse(vec3 color); vec4 applyWaterFog(vec4 color, vec3 viewVec) { @@ -151,7 +111,7 @@ void main() vec4 fb = texture2D(screenTex, distort); - frag_data[0] = vec4(/*linear_to_srgb*/(fb.rgb), 1.0); // diffuse + frag_data[0] = vec4(fb.rgb, 1.0); // diffuse frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, displace } diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index cb83ac8e06..6a24c1bd43 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_data[3]; @@ -37,10 +37,6 @@ vec3 atmosTransport(vec3 inColor); uniform sampler2D bumpMap; uniform sampler2D screenTex; uniform sampler2D refTex; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; uniform sampler2D noiseMap; uniform mat4 shadow_matrix[6]; @@ -58,7 +54,6 @@ uniform vec3 normScale; uniform float fresnelScale; uniform float fresnelOffset; uniform float blurMultiplier; -uniform vec2 screen_res; uniform mat4 norm_mat; //region space to screen space //bigWave is (refCoord.w, view.w); @@ -67,29 +62,7 @@ VARYING vec4 littleWave; VARYING vec4 view; VARYING vec4 vary_position; -vec3 srgb_to_linear(vec3 cs) -{ - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lte.r ? low_range.r : high_range.r; - result.g = lte.g ? low_range.g : high_range.g; - result.b = lte.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lte); -#endif - -} - -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} +vec2 encode_normal(vec3 n); void main() { diff --git a/indra/newview/app_settings/shaders/class1/effects/MotionBlurF.glsl b/indra/newview/app_settings/shaders/class1/effects/MotionBlurF.glsl index f2b4900b4a..6e523a8d5e 100644 --- a/indra/newview/app_settings/shaders/class1/effects/MotionBlurF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/MotionBlurF.glsl @@ -5,7 +5,7 @@ * $License$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -13,11 +13,10 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect tex0; -uniform sampler2DRect tex1; +uniform sampler2D tex0; +uniform sampler2D tex1; uniform mat4 inv_proj; uniform mat4 prev_proj; -uniform vec2 screen_res; uniform int blur_strength; VARYING vec2 vary_texcoord0; @@ -26,9 +25,8 @@ VARYING vec2 vary_texcoord0; vec4 getPosition(vec2 pos_screen, out vec4 ndc) { - float depth = texture2DRect(tex1, pos_screen.xy).r; + float depth = texture2D(tex1, pos_screen.xy).r; vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; sc -= vec2(1.0,1.0); ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); vec4 pos = inv_proj * ndc; @@ -44,14 +42,14 @@ void main(void) vec4 prev_pos = prev_proj * pos; prev_pos/=prev_pos.w; prev_pos.w = 1.0; - vec2 vel = ((ndc.xy-prev_pos.xy) * .5) * screen_res * .01 * blur_strength * 1.0/SAMPLE_COUNT; + vec2 vel = ((ndc.xy-prev_pos.xy) * .5) * .01 * blur_strength * 1.0/SAMPLE_COUNT; float len = length(vel); vel = normalize(vel) * min(len, 50); - vec3 color = texture2DRect(tex0, vary_texcoord0.st).rgb; + vec3 color = texture2D(tex0, vary_texcoord0.st).rgb; vec2 texcoord = vary_texcoord0 + vel; for(int i = 1; i < SAMPLE_COUNT; ++i, texcoord += vel) { - color += texture2DRect(tex0, texcoord.st).rgb; + color += texture2D(tex0, texcoord.st).rgb; } frag_color = vec4(color / SAMPLE_COUNT, 1.0); } diff --git a/indra/newview/app_settings/shaders/class1/effects/PosterizeF.glsl b/indra/newview/app_settings/shaders/class1/effects/PosterizeF.glsl index fe983c258a..3da995dc0e 100644 --- a/indra/newview/app_settings/shaders/class1/effects/PosterizeF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/PosterizeF.glsl @@ -5,7 +5,7 @@ * $License$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -13,13 +13,13 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect tex0; +uniform sampler2D tex0; uniform int layerCount; VARYING vec2 vary_texcoord0; void main(void) { - vec3 color = pow(floor(pow(vec3(texture2DRect(tex0, vary_texcoord0.st)),vec3(.6)) * layerCount)/layerCount,vec3(1.66666)); + vec3 color = pow(floor(pow(vec3(texture2D(tex0, vary_texcoord0.st)),vec3(.6)) * layerCount)/layerCount,vec3(1.66666)); frag_color = vec4(color, 1.0); } diff --git a/indra/newview/app_settings/shaders/class1/effects/VignetteF.glsl b/indra/newview/app_settings/shaders/class1/effects/VignetteF.glsl index f3a6f43245..8a1e58a1cc 100644 --- a/indra/newview/app_settings/shaders/class1/effects/VignetteF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/VignetteF.glsl @@ -5,7 +5,7 @@ * $License$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -13,13 +13,12 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect tex0; +uniform sampler2D tex0; uniform float vignette_strength; //0 - 1 uniform float vignette_radius; //0 - 8 uniform float vignette_darkness; //0 - 1 uniform float vignette_desaturation; //0 - 10 uniform float vignette_chromatic_aberration; //0 - .1 -uniform vec2 screen_res; VARYING vec2 vary_texcoord0; @@ -32,16 +31,15 @@ float luminance(vec3 color) void main(void) { - vec3 color = texture2DRect(tex0, vary_texcoord0).rgb; - vec2 norm_texcood = (vary_texcoord0/screen_res); - vec2 offset = norm_texcood-vec2(.5); + vec3 color = texture2D(tex0, vary_texcoord0).rgb; + vec2 offset = vary_texcoord0-vec2(.5); float vignette = clamp(pow(1 - dot(offset,offset),vignette_radius) + 1-vignette_strength, 0.0, 1.0); float inv_vignette = 1-vignette; //vignette chromatic aberration (g - vec2 shift = screen_res * offset * vignette_chromatic_aberration * inv_vignette; - float g = texture2DRect(tex0,vary_texcoord0-shift).g; - float b = texture2DRect(tex0,vary_texcoord0-2*shift).b; + vec2 shift = offset * vignette_chromatic_aberration * inv_vignette; + float g = texture2D(tex0,vary_texcoord0-shift).g; + float b = texture2D(tex0,vary_texcoord0-2*shift).b; color.gb = vec2(g,b); //vignette 'black' overlay. diff --git a/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl b/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl index 8a948b1192..29485bf98f 100644 --- a/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -14,7 +14,7 @@ out vec4 frag_color; #endif -uniform sampler2DRect tex0; +uniform sampler2D tex0; uniform float brightness; uniform float contrast; uniform vec3 contrastBase; @@ -34,7 +34,7 @@ float luminance(vec3 color) void main(void) { - vec3 color = vec3(texture2DRect(tex0, vary_texcoord0.st)); + vec3 color = vec3(texture2D(tex0, vary_texcoord0.st)); /// Apply gamma color = pow(color, vec3(1.0/gamma)); diff --git a/indra/newview/app_settings/shaders/class1/effects/gaussBlurF.glsl b/indra/newview/app_settings/shaders/class1/effects/gaussBlurF.glsl index db12800a33..012b5c83c0 100644 --- a/indra/newview/app_settings/shaders/class1/effects/gaussBlurF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/gaussBlurF.glsl @@ -1,4 +1,4 @@ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -6,32 +6,22 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect tex0; +uniform sampler2D tex0; uniform int horizontalPass; VARYING vec2 vary_texcoord0; -vec2 offset = vec2( 1.3846153846, 3.2307692308 ); +uniform vec4 kern[2]; vec3 weight = vec3( 0.2270270270, 0.3162162162, 0.0702702703 ); - + void main(void) { - vec3 color = vec3(texture2DRect(tex0, vary_texcoord0))*weight.x; + vec3 color = vec3(texture2D(tex0, vary_texcoord0))*weight.x; - if(horizontalPass == 1) - { - color += weight.y * vec3(texture2DRect(tex0, vec2(vary_texcoord0.s+offset.s,vary_texcoord0.t))); - color += weight.y * vec3(texture2DRect(tex0, vec2(vary_texcoord0.s-offset.s,vary_texcoord0.t))); - color += weight.z * vec3(texture2DRect(tex0, vec2(vary_texcoord0.s+offset.t,vary_texcoord0.t))); - color += weight.z * vec3(texture2DRect(tex0, vec2(vary_texcoord0.s-offset.t,vary_texcoord0.t))); - - } - else - { - color += weight.y * vec3(texture2DRect(tex0, vec2(vary_texcoord0.s,vary_texcoord0.t+offset.s))); - color += weight.y * vec3(texture2DRect(tex0, vec2(vary_texcoord0.s,vary_texcoord0.t-offset.s))); - color += weight.z * vec3(texture2DRect(tex0, vec2(vary_texcoord0.s,vary_texcoord0.t+offset.t))); - color += weight.z * vec3(texture2DRect(tex0, vec2(vary_texcoord0.s,vary_texcoord0.t-offset.t))); - } + color += weight.y * vec3(texture2D(tex0, vec2(vary_texcoord0.s+kern[horizontalPass].s,vary_texcoord0.t+kern[horizontalPass].s))); + color += weight.y * vec3(texture2D(tex0, vec2(vary_texcoord0.s-kern[horizontalPass].s,vary_texcoord0.t-kern[horizontalPass].s))); + color += weight.z * vec3(texture2D(tex0, vec2(vary_texcoord0.s+kern[horizontalPass].t,vary_texcoord0.t+kern[horizontalPass].t))); + color += weight.z * vec3(texture2D(tex0, vec2(vary_texcoord0.s-kern[horizontalPass].t,vary_texcoord0.t-kern[horizontalPass].t))); + frag_color = vec4(color.xyz,1.0); } diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl index 4f3690383f..48886d40da 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,7 +31,7 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect diffuseMap; +uniform sampler2D diffuseMap; uniform float minLuminance; uniform float maxExtractAlpha; uniform vec3 lumWeights; @@ -42,7 +42,7 @@ VARYING vec2 vary_texcoord0; void main() { - vec4 col = texture2DRect(diffuseMap, vary_texcoord0.xy); + vec4 col = texture2D(diffuseMap, vary_texcoord0.xy); /// CALCULATING LUMINANCE (Using NTSC lum weights) /// http://en.wikipedia.org/wiki/Luma_%28video%29 float lum = smoothstep(minLuminance, minLuminance+1.0, dot(col.rgb, lumWeights ) ); diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl index 1396dc6973..3e6a469226 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl @@ -26,13 +26,12 @@ uniform mat4 modelview_projection_matrix; ATTRIBUTE vec3 position; -ATTRIBUTE vec2 texcoord0; VARYING vec2 vary_texcoord0; void main() { - gl_Position = modelview_projection_matrix * vec4(position, 1.0); - - vary_texcoord0.xy = texcoord0; + vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); + gl_Position = pos; + vary_texcoord0 = (pos.xy*0.5+0.5); } diff --git a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl index bde9a45370..b83c1c0074 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl @@ -26,7 +26,6 @@ uniform mat4 modelview_projection_matrix; ATTRIBUTE vec3 position; -ATTRIBUTE vec2 texcoord1; uniform vec2 glowDelta; @@ -37,14 +36,16 @@ VARYING vec4 vary_texcoord3; void main() { - gl_Position = modelview_projection_matrix * vec4(position, 1.0); + vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); + gl_Position = pos; + vec2 texcoord = (pos.xy*0.5+0.5); - vary_texcoord0.xy = texcoord1 + glowDelta*(-3.5); - vary_texcoord1.xy = texcoord1 + glowDelta*(-2.5); - vary_texcoord2.xy = texcoord1 + glowDelta*(-1.5); - vary_texcoord3.xy = texcoord1 + glowDelta*(-0.5); - vary_texcoord0.zw = texcoord1 + glowDelta*(0.5); - vary_texcoord1.zw = texcoord1 + glowDelta*(1.5); - vary_texcoord2.zw = texcoord1 + glowDelta*(2.5); - vary_texcoord3.zw = texcoord1 + glowDelta*(3.5); + vary_texcoord0.xy = texcoord + glowDelta*(-3.5); + vary_texcoord1.xy = texcoord + glowDelta*(-2.5); + vary_texcoord2.xy = texcoord + glowDelta*(-1.5); + vary_texcoord3.xy = texcoord + glowDelta*(-0.5); + vary_texcoord0.zw = texcoord + glowDelta*(0.5); + vary_texcoord1.zw = texcoord + glowDelta*(1.5); + vary_texcoord2.zw = texcoord + glowDelta*(2.5); + vary_texcoord3.zw = texcoord + glowDelta*(3.5); } diff --git a/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl b/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl index 998d8eb18b..8987e8e7cd 100644 --- a/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl @@ -5,7 +5,7 @@ * $License$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -13,7 +13,7 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect tex0; +uniform sampler2D tex0; uniform sampler2D tex1; uniform float brightMult; uniform float noiseStrength; @@ -32,7 +32,7 @@ float luminance(vec3 color) void main(void) { /// Get scene color - vec3 color = vec3(texture2DRect(tex0, vary_texcoord0)); + vec3 color = vec3(texture2D(tex0, vary_texcoord0)); /// Extract luminance and scale up by night vision brightness float lum = luminance(color) * brightMult; diff --git a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl deleted file mode 100644 index e7a59af2f2..0000000000 --- a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file debugF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2011, 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$ - */ - -//#extension GL_ARB_texture_rectangle : enable - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -uniform sampler2DRect depthMap; - -VARYING vec2 tc0; -VARYING vec2 tc1; -VARYING vec2 tc2; -VARYING vec2 tc3; -VARYING vec2 tc4; -VARYING vec2 tc5; -VARYING vec2 tc6; -VARYING vec2 tc7; -VARYING vec2 tc8; - -void main() -{ - vec4 depth1 = - vec4(texture2DRect(depthMap, tc0).r, - texture2DRect(depthMap, tc1).r, - texture2DRect(depthMap, tc2).r, - texture2DRect(depthMap, tc3).r); - - vec4 depth2 = - vec4(texture2DRect(depthMap, tc4).r, - texture2DRect(depthMap, tc5).r, - texture2DRect(depthMap, tc6).r, - texture2DRect(depthMap, tc7).r); - - depth1 = min(depth1, depth2); - float depth = min(depth1.x, depth1.y); - depth = min(depth, depth1.z); - depth = min(depth, depth1.w); - depth = min(depth, texture2DRect(depthMap, tc8).r); - - gl_FragDepth = depth; -} diff --git a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl index 71d80911d6..44b6c3c855 100644 --- a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl @@ -27,8 +27,6 @@ uniform mat4 modelview_projection_matrix; ATTRIBUTE vec3 position; -uniform vec2 screen_res; - uniform vec2 delta; VARYING vec2 tc0; @@ -45,7 +43,7 @@ void main() { gl_Position = vec4(position, 1.0); - vec2 tc = (position.xy*0.5+0.5)*screen_res; + vec2 tc = (position.xy*0.5+0.5); tc0 = tc+vec2(-delta.x,-delta.y); tc1 = tc+vec2(0,-delta.y); tc2 = tc+vec2(delta.x,-delta.y); diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl index f76a90158a..7765b30ca7 100644 --- a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl @@ -29,16 +29,15 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -//#extension GL_ARB_texture_rectangle : enable + uniform sampler2D glowMap; -uniform sampler2DRect screenMap; +uniform sampler2D screenMap; VARYING vec2 vary_texcoord0; -VARYING vec2 vary_texcoord1; void main() { - frag_color = texture2D(glowMap, vary_texcoord1.xy) + - texture2DRect(screenMap, vary_texcoord0.xy); + frag_color = texture2D(glowMap, vary_texcoord0.xy) + + texture2D(screenMap, vary_texcoord0.xy); } diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl index 147de39c45..98b2a3bf0f 100644 --- a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,14 +31,13 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect diffuseRect; +uniform sampler2D diffuseRect; -uniform vec2 screen_res; -VARYING vec2 vary_tc; +VARYING vec2 vary_texcoord0; void main() { - vec3 col = texture2DRect(diffuseRect, vary_tc*screen_res).rgb; + vec3 col = texture2D(diffuseRect, vary_texcoord0).rgb; frag_color = vec4(col.rgb, dot(col.rgb, vec3(0.299, 0.587, 0.144))); } diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAV.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAV.glsl index 058f3b1b82..867a2d4407 100644 --- a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAV.glsl @@ -27,13 +27,13 @@ uniform mat4 modelview_projection_matrix; ATTRIBUTE vec3 position; -VARYING vec2 vary_tc; +VARYING vec2 vary_texcoord0; void main() { vec4 pos = modelview_projection_matrix*vec4(position.xyz, 1.0); gl_Position = pos; - vary_tc = pos.xy*0.5+0.5; + vary_texcoord0 = pos.xy*0.5+0.5; } diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl index f7970b7f78..83e728ce3b 100644 --- a/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl @@ -26,16 +26,13 @@ uniform mat4 modelview_projection_matrix; ATTRIBUTE vec3 position; -ATTRIBUTE vec2 texcoord0; -ATTRIBUTE vec2 texcoord1; VARYING vec2 vary_texcoord0; -VARYING vec2 vary_texcoord1; void main() { - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - vary_texcoord0 = texcoord0; - vary_texcoord1 = texcoord1; + vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); + gl_Position = pos; + vary_texcoord0 = (pos.xy*0.5+0.5); } diff --git a/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl b/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl index 2e47c00233..468cf480dd 100644 --- a/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,12 +31,12 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect screenMap; +uniform sampler2D screenMap; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; void main() { - frag_color = texture2DRect(screenMap, vary_texcoord0.xy) * vertex_color; + frag_color = texture2D(screenMap, vary_texcoord0.xy) * vertex_color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl index a9288b3df6..7d493d74cc 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl @@ -43,16 +43,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa //normalize light vector lv *= 1.0/d; + //lv = normalize(lv); //distance attenuation float da = clamp(1.0/(la * d), 0.0, 1.0); // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); + float spot = max(dot(normalize(-ln), lv), is_pointlight); da *= spot*spot; // GL_SPOT_EXPONENT=2 //angular attenuation - da *= calcDirectionalLight(n, lv); + da = max(lp.w * da * calcDirectionalLight(n, lv), (1.0 - lp.w) * calcDirectionalLight(n, lp.xyz)); return da; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl index 7059ff31ae..4e86aa1799 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl @@ -22,35 +22,40 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - - + float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); +vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol); + vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 atmosGetDiffuseSunlightColor(); vec3 scaleDownLight(vec3 light); uniform vec4 light_position[8]; +uniform vec3 light_attenuation[8]; uniform vec3 light_diffuse[8]; vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol) { - vec4 col = vec4(0,0,0, color.a); + vec4 col = vec4(0.0, 0.0, 0.0, color.a); vec3 view = normalize(pos); /// collect all the specular values from each calcXXXLightSpecular() function vec4 specularSum = vec4(0.0); - col.rgb += light_diffuse[1].rgb * calcDirectionalLightSpecular(specularColor, view, norm, light_position[1].xyz,light_diffuse[1].rgb, 1.0); + // Collect normal lights (need to be divided by two, as we later multiply by 2) + col.rgb += calcPointLightSpecular(specularSum, view, pos, norm, light_position[1].xyz, light_attenuation[1].x, light_attenuation[1].y, light_diffuse[1].rgb); col.rgb = scaleDownLight(col.rgb); + + // Add windlight lights col.rgb += atmosAmbient(baseCol.rgb); col.rgb += atmosAffectDirectionalLight(calcDirectionalLightSpecular(specularSum, view, norm, light_position[0].xyz,atmosGetDiffuseSunlightColor()*baseCol.a, 1.0)); col.rgb = min(col.rgb * color.rgb, 1.0); specularColor.rgb = min(specularColor.rgb * specularSum.rgb, 1.0); - + col.rgb += specularColor.rgb; return col; diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl index 41288c21c1..752becf788 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl @@ -23,28 +23,36 @@ * $/LicenseInfo$ */ -uniform vec4 light_position[8]; -uniform vec3 light_diffuse[8]; float calcDirectionalLight(vec3 n, vec3 l); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); + +uniform vec4 light_position[8]; +uniform vec3 light_direction[8]; +uniform vec3 light_attenuation[8]; +uniform vec3 light_diffuse[8]; + vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) { - vec4 col; - col.a = color.a; - - col.rgb = light_diffuse[1].rgb * calcDirectionalLight(norm, light_position[1].xyz); + vec4 col = vec4(0.0, 0.0, 0.0, color.a); + + // Collect normal lights (need to be divided by two, as we later multiply by 2) + + // Collect normal lights + col.rgb += light_diffuse[1].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[1], light_direction[1], light_attenuation[1].x, light_attenuation[1].z); col.rgb = scaleDownLight(col.rgb); + + // Add windlight lights col.rgb += atmosAmbient(baseLight.rgb); col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, light_position[0].xyz)); - + col.rgb = min(col.rgb*color.rgb, 1.0); - - return col; -} + return col; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl index 7f3f84398b..3ad9d61f70 100644 --- a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl @@ -90,7 +90,7 @@ void main() vec4 col = vec4(0,0,0,1); // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += light_diffuse[1].rgb * calcDirectionalLight(norm, light_position[1].xyz); + col.rgb += light_diffuse[1].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[1], light_direction[1], light_attenuation[1].x, light_attenuation[1].z); col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].z); col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].z); diff --git a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl deleted file mode 100644 index 5af9f5c902..0000000000 --- a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @file eyeballV.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat3 normal_matrix; -uniform mat4 texture_matrix0; -uniform mat4 modelview_matrix; -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; -ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec3 normal; -ATTRIBUTE vec2 texcoord0; - -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; - - -vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol); -void calcAtmospherics(vec3 inPositionEye); - -void main() -{ - //transform vertex - vec3 pos = (modelview_matrix * vec4(position.xyz, 1.0)).xyz; - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - - vec3 norm = normalize(normal_matrix * normal); - - calcAtmospherics(pos.xyz); - - // vec4 specular = specularColor; - vec4 specular = vec4(1.0); - vec4 color = calcLightingSpecular(pos, norm, diffuse_color, specular, vec4(0.0)); - - vertex_color = color; - - -} - diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index ce069fbc8c..ed1065cd3c 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -22,9 +22,6 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - -//#extension GL_ARB_texture_rectangle : enable -//#extension GL_ARB_shader_texture_lod : enable #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -32,12 +29,11 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; +uniform sampler2D diffuseRect; +uniform sampler2D specularRect; +uniform sampler2D depthMap; +uniform sampler2D normalMap; uniform samplerCube environmentMap; -uniform sampler2DRect lightMap; uniform sampler2D noiseMap; uniform sampler2D projectionMap; uniform sampler2D lightFunc; @@ -56,71 +52,37 @@ uniform float far_clip; uniform vec3 proj_origin; //origin of projection to be used for angular attenuation uniform float sun_wash; + +// Shadows +uniform sampler2D lightMap; uniform int proj_shadow_idx; uniform float shadow_fade; uniform vec3 center; -uniform float size; uniform vec3 color; uniform float falloff; +uniform float size; VARYING vec4 vary_fragcoord; -uniform vec2 screen_res; uniform mat4 inv_proj; +uniform vec2 noise_scale; -vec3 srgb_to_linear(vec3 cs) -{ - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lte.r ? low_range.r : high_range.r; - result.g = lte.g ? low_range.g : high_range.g; - result.b = lte.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lte); -#endif - -} - -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} - -vec4 correctWithGamma(vec4 col) -{ - return vec4(srgb_to_linear(col.rgb), col.a); -} +vec3 decode_normal(vec2 enc); +vec4 getPosition(vec2 pos_screen); +vec4 srgb_to_linear(vec4 cs); vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); - - vec2 dist = tc-vec2(0.5); - - float det = max(1.0-lod/(proj_lod*0.5), 0.0); - float d = dot(dist,dist); - - ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + ret = srgb_to_linear(ret); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + float det = min(lod/(proj_lod*0.5), 1.0); + float d = min(dist.x, dist.y); + d *= min(1, d * (proj_lod - lod)); + float edge = 0.25*det; + ret *= clamp(d/edge, 0.0, 1.0); return ret; } @@ -128,7 +90,7 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); + ret = srgb_to_linear(ret); vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); @@ -146,7 +108,7 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); + ret = srgb_to_linear(ret); vec2 dist = tc-vec2(0.5); @@ -157,26 +119,11 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) return ret; } - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - void main() { vec4 frag = vary_fragcoord; frag.xyz /= frag.w; frag.xyz = frag.xyz*0.5+0.5; - frag.xy *= screen_res; vec3 pos = getPosition(frag.xy).xyz; vec3 lv = center.xyz-pos.xyz; @@ -186,20 +133,20 @@ void main() { discard; } - + float shadow = 1.0; - + if (proj_shadow_idx >= 0) { - vec4 shd = texture2DRect(lightMap, frag.xy); + vec4 shd = texture2D(lightMap, frag.xy); float sh[2]; sh[0] = shd.b; sh[1] = shd.a; shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); } - - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; - + + vec3 norm = texture2D(normalMap, frag.xy).xyz; + float envIntensity = norm.z; norm = decode_normal(norm.xy); @@ -219,6 +166,7 @@ void main() float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0); dist_atten *= dist_atten; dist_atten *= 2.0; + if (dist_atten <= 0.0) { discard; @@ -229,56 +177,56 @@ void main() float da = dot(norm, lv); vec3 col = vec3(0,0,0); - - vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - - vec4 spec = texture2DRect(specularRect, frag.xy); + vec3 diff_tex = texture2D(diffuseRect, frag.xy).rgb; vec3 dlit = vec3(0, 0, 0); - float noise = texture2D(noiseMap, frag.xy/128.0).b; + float noise = texture2D(noiseMap, frag.xy*noise_scale).b; if (proj_tc.z > 0.0 && proj_tc.x < 1.0 && proj_tc.y < 1.0 && proj_tc.x > 0.0 && proj_tc.y > 0.0) { - float amb_da = proj_ambiance; float lit = 0.0; - + float amb_da = proj_ambiance; + if (da > 0.0) { lit = da * dist_atten * noise; float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); - + dlit = color.rgb * plcol.rgb * plcol.a; - + col = dlit*lit*diff_tex*shadow; amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; } - + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); - + amb_da += (da*da*0.5+0.5)*proj_ambiance; - + amb_da *= dist_atten * noise; - + amb_da = min(amb_da, 1.0-lit); - - col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + + col += amb_da*color*diff_tex*amb_plcol.rgb*amb_plcol.a; } - + + + vec4 spec = texture2D(specularRect, frag.xy); if (spec.a > 0.0) { - vec3 npos = -normalize(pos); dlit *= min(da*6.0, 1.0) * dist_atten; + vec3 npos = -normalize(pos); + //vec3 ref = dot(pos+lv, norm); vec3 h = normalize(lv+npos); float nh = dot(norm, h); @@ -289,7 +237,7 @@ void main() float gtdenom = 2 * nh; float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); - + if (nh > 0.0) { float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); @@ -297,10 +245,6 @@ void main() //col += spec.rgb; } } - - - - if (envIntensity > 0.0) { @@ -313,27 +257,23 @@ void main() if (ds < 0.0) { vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); - stc /= stc.w; if (stc.z > 0.0) { - float fatten = clamp(envIntensity*envIntensity+envIntensity*0.25, 0.25, 1.0); + stc /= stc.w; - stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); - if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod).rgb*shadow*spec.rgb; + col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity; } } } } - //not sure why, but this line prevents MATBUG-194 col = max(col, vec3(0.0)); diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index bcb66dc4c5..b9184655fc 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,11 +31,11 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect normalMap; -uniform sampler2DRect lightMap; -uniform sampler2DRect depthMap; +uniform sampler2D diffuseRect; +uniform sampler2D specularRect; +uniform sampler2D normalMap; +uniform sampler2D lightMap; +uniform sampler2D depthMap; uniform samplerCube environmentMap; uniform sampler2D lightFunc; @@ -76,66 +76,14 @@ vec3 vary_AdditiveColor; vec3 vary_AtmosAttenuation; uniform mat4 inv_proj; -uniform vec2 screen_res; - -vec3 srgb_to_linear(vec3 cs) -{ - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lte.r ? low_range.r : high_range.r; - result.g = lte.g ? low_range.g : high_range.g; - result.b = lte.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lte); -#endif - -} - -vec3 linear_to_srgb(vec3 cl) -{ - cl = clamp(cl, vec3(0), vec3(1)); - vec3 low_range = cl * 12.92; - vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; - bvec3 lt = lessThan(cl,vec3(0.0031308)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lt.r ? low_range.r : high_range.r; - result.g = lt.g ? low_range.g : high_range.g; - result.b = lt.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lt); -#endif - -} - -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} +vec3 decode_normal(vec2 enc); +vec3 srgb_to_linear(vec3 cs); +vec3 linear_to_srgb(vec3 cl); vec4 getPosition_d(vec2 pos_screen, float depth) { vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; sc -= vec2(1.0,1.0); vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); vec4 pos = inv_proj * ndc; @@ -144,12 +92,6 @@ vec4 getPosition_d(vec2 pos_screen, float depth) return pos; } -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).r; - return getPosition_d(pos_screen, depth); -} - vec3 getPositionEye() { return vary_PositionEye; @@ -196,6 +138,52 @@ void setAtmosAttenuation(vec3 v) vary_AtmosAttenuation = v; } +#ifdef WATER_FOG +uniform vec4 waterPlane; +uniform vec4 waterFogColor; +uniform float waterFogDensity; +uniform float waterFogKS; + +vec4 applyWaterFogDeferred(vec3 pos, vec4 color) +{ + //normalize view vector + vec3 view = normalize(pos); + float es = -(dot(view, waterPlane.xyz)); + + //find intersection point with water plane and eye vector + + //get eye depth + float e0 = max(-waterPlane.w, 0.0); + + vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0); + + //get object depth + float depth = length(pos - int_v); + + //get "thickness" of water + float l = max(depth, 0.1); + + float kd = waterFogDensity; + float ks = waterFogKS; + vec4 kc = waterFogColor; + + float F = 0.98; + + float t1 = -kd * pow(F, ks * e0); + float t2 = kd + ks * es; + float t3 = pow(F, t2*l) - 1.0; + + float L = min(t1/t2*t3, 1.0); + + float D = pow(0.98, l*kd); + + color.rgb = color.rgb * D + kc.rgb * L; + color.a = kc.a + color.a; + + return color; +} +#endif + void calcAtmospherics(vec3 inPositionEye, float ambFactor) { vec3 P = inPositionEye; @@ -276,52 +264,6 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); } -#ifdef WATER_FOG -uniform vec4 waterPlane; -uniform vec4 waterFogColor; -uniform float waterFogDensity; -uniform float waterFogKS; - -vec4 applyWaterFogDeferred(vec3 pos, vec4 color) -{ - //normalize view vector - vec3 view = normalize(pos); - float es = -(dot(view, waterPlane.xyz)); - - //find intersection point with water plane and eye vector - - //get eye depth - float e0 = max(-waterPlane.w, 0.0); - - vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0); - - //get object depth - float depth = length(pos - int_v); - - //get "thickness" of water - float l = max(depth, 0.1); - - float kd = waterFogDensity; - float ks = waterFogKS; - vec4 kc = waterFogColor; - - float F = 0.98; - - float t1 = -kd * pow(F, ks * e0); - float t2 = kd + ks * es; - float t3 = pow(F, t2*l) - 1.0; - - float L = min(t1/t2*t3, 1.0); - - float D = pow(0.98, l*kd); - - color.rgb = color.rgb * D + kc.rgb * L; - color.a = kc.a + color.a; - - return color; -} -#endif - vec3 atmosLighting(vec3 light) { light *= getAtmosAttenuation().r; @@ -394,13 +336,13 @@ float luminance(vec3 color) void main() { vec2 tc = vary_fragcoord.xy; - float depth = texture2DRect(depthMap, tc.xy).r; + float depth = texture2D(depthMap, tc.xy).r; vec3 pos = getPosition_d(tc, depth).xyz; - vec4 norm = texture2DRect(normalMap, tc); + vec4 norm = texture2D(normalMap, tc); float envIntensity = norm.z; norm.xyz = decode_normal(norm.xy); // unpack norm - vec4 diffuse = texture2DRect(diffuseRect, tc); + vec4 diffuse = texture2D(diffuseRect, tc); //convert to gamma space diffuse.rgb = linear_to_srgb(diffuse.rgb); @@ -408,7 +350,7 @@ void main() vec3 col; float bloom = 0.0; { - vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + vec4 spec = texture2D(specularRect, vary_fragcoord.xy); bloom = spec.r*norm.w; if (norm.w < 0.5) @@ -419,7 +361,7 @@ void main() float light_gamma = 1.0/1.3; da = pow(da, light_gamma); - vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; + vec2 scol_ambocc = texture2D(lightMap, vary_fragcoord.xy).rg; scol_ambocc = pow(scol_ambocc, vec2(light_gamma)); float scol = max(scol_ambocc.r, diffuse.a); diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl deleted file mode 100644 index c840d72784..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file softenLightF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; - -uniform vec2 screen_res; - -VARYING vec2 vary_fragcoord; - -void main() -{ - //transform vertex - vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); - gl_Position = pos; - - - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; -} diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index 9fbd1e9dcf..add148bd02 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -22,9 +22,6 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - -//#extension GL_ARB_texture_rectangle : enable -//#extension GL_ARB_shader_texture_lod : enable #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -32,12 +29,11 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; +uniform sampler2D diffuseRect; +uniform sampler2D specularRect; +uniform sampler2D depthMap; +uniform sampler2D normalMap; uniform samplerCube environmentMap; -uniform sampler2DRect lightMap; uniform sampler2D noiseMap; uniform sampler2D projectionMap; uniform sampler2D lightFunc; @@ -56,71 +52,37 @@ uniform float far_clip; uniform vec3 proj_origin; //origin of projection to be used for angular attenuation uniform float sun_wash; + +// Shadow +uniform sampler2D lightMap; uniform int proj_shadow_idx; uniform float shadow_fade; -uniform float size; uniform vec3 color; uniform float falloff; +uniform float size; VARYING vec3 trans_center; VARYING vec4 vary_fragcoord; -uniform vec2 screen_res; uniform mat4 inv_proj; +uniform vec2 noise_scale; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - -vec3 decode_normal (vec2 enc) -{ - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} - -vec3 srgb_to_linear(vec3 cs) -{ - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - -#ifdef OLD_SELECT - vec3 result; - result.r = lte.r ? low_range.r : high_range.r; - result.g = lte.g ? low_range.g : high_range.g; - result.b = lte.b ? low_range.b : high_range.b; - return result; -#else - return mix(high_range, low_range, lte); -#endif - -} - -vec4 correctWithGamma(vec4 col) -{ - return vec4(srgb_to_linear(col.rgb), col.a); -} +vec3 decode_normal(vec2 enc); +vec4 getPosition(vec2 pos_screen); +vec4 srgb_to_linear(vec4 cs); vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); - vec2 dist = tc-vec2(0.5); - - float det = max(1.0-lod/(proj_lod*0.5), 0.0); - - float d = dot(dist,dist); - - ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + ret = srgb_to_linear(ret); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + float det = min(lod/(proj_lod*0.5), 1.0); + float d = min(dist.x, dist.y); + d *= min(1, d * (proj_lod - lod)); + float edge = 0.25*det; + ret *= clamp(d/edge, 0.0, 1.0); return ret; } @@ -128,8 +90,8 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); - + ret = srgb_to_linear(ret); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); float det = min(lod/(proj_lod*0.5), 1.0); @@ -146,7 +108,7 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); + ret = srgb_to_linear(ret); vec2 dist = tc-vec2(0.5); @@ -157,26 +119,11 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) return ret; } - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - void main() { vec4 frag = vary_fragcoord; frag.xyz /= frag.w; frag.xyz = frag.xyz*0.5+0.5; - frag.xy *= screen_res; vec3 pos = getPosition(frag.xy).xyz; vec3 lv = trans_center.xyz-pos.xyz; @@ -186,20 +133,22 @@ void main() { discard; } - + float shadow = 1.0; if (proj_shadow_idx >= 0) { - vec4 shd = texture2DRect(lightMap, frag.xy); + vec4 shd = texture2D(lightMap, frag.xy); float sh[2]; sh[0] = shd.b; sh[1] = shd.a; shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); } - - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + + vec3 norm = texture2D(normalMap, frag.xy).xyz; + float envIntensity = norm.z; + norm = decode_normal(norm.xy); norm = normalize(norm); @@ -226,24 +175,21 @@ void main() lv = proj_origin-pos.xyz; lv = normalize(lv); float da = dot(norm, lv); - + vec3 col = vec3(0,0,0); - - vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - - vec4 spec = texture2DRect(specularRect, frag.xy); + vec3 diff_tex = texture2D(diffuseRect, frag.xy).rgb; vec3 dlit = vec3(0, 0, 0); - float noise = texture2D(noiseMap, frag.xy/128.0).b; + float noise = texture2D(noiseMap, frag.xy*noise_scale).b; if (proj_tc.z > 0.0 && proj_tc.x < 1.0 && proj_tc.y < 1.0 && proj_tc.x > 0.0 && proj_tc.y > 0.0) { - float amb_da = proj_ambiance; float lit = 0.0; + float amb_da = proj_ambiance; if (da > 0.0) { @@ -251,31 +197,34 @@ void main() float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); - + dlit = color.rgb * plcol.rgb * plcol.a; - + col = dlit*lit*diff_tex*shadow; amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; } - + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); - + amb_da += (da*da*0.5+0.5)*proj_ambiance; - + amb_da *= dist_atten * noise; - + amb_da = min(amb_da, 1.0-lit); - - col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + + col += amb_da*color*diff_tex*amb_plcol.rgb*amb_plcol.a; } - + + + vec4 spec = texture2D(specularRect, frag.xy); if (spec.a > 0.0) { dlit *= min(da*6.0, 1.0) * dist_atten; + vec3 npos = -normalize(pos); //vec3 ref = dot(pos+lv, norm); @@ -288,7 +237,7 @@ void main() float gtdenom = 2 * nh; float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); - + if (nh > 0.0) { float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); @@ -296,10 +245,6 @@ void main() //col += spec.rgb; } } - - - - if (envIntensity > 0.0) { @@ -312,29 +257,24 @@ void main() if (ds < 0.0) { vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); if (stc.z > 0.0) { - stc.xy /= stc.w; + stc /= stc.w; - float fatten = clamp(envIntensity*envIntensity+envIntensity*0.5, 0.25, 1.0); - - //stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); - stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); - if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod-envIntensity*proj_lod).rgb*shadow*spec.rgb; + col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity; } } } } - + //not sure why, but this line prevents MATBUG-194 col = max(col, vec3(0.0)); diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 043859894a..becff8506a 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -33,8 +33,8 @@ out vec4 frag_color; //class 2, shadows, no SSAO -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; +uniform sampler2D depthMap; +uniform sampler2D normalMap; uniform sampler2DShadow shadowMap0; uniform sampler2DShadow shadowMap1; uniform sampler2DShadow shadowMap2; @@ -52,9 +52,9 @@ uniform float ssao_factor; uniform float ssao_factor_inv; VARYING vec2 vary_fragcoord; +uniform vec2 kern_scale; uniform mat4 inv_proj; -uniform vec2 screen_res; uniform vec2 proj_shadow_res; uniform vec3 sun_dir; @@ -65,34 +65,24 @@ uniform float shadow_offset; uniform float spot_shadow_bias; uniform float spot_shadow_offset; -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} +vec3 decode_normal(vec2 enc); +vec4 getPosition(vec2 pos_screen); -vec3 decode_normal (vec2 enc) +float calcShadow( sampler2DShadow shadowMap, vec4 stc, vec2 res, vec2 pos_screen ) { - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} + //stc.x += (((texture2D(noiseMap, pos_screen/128.0).x)-.5)/shadow_res.x); //Random dither. -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; + vec2 off = vec2(1,1.5)/res; + stc.x = floor(stc.x*res.x + fract(pos_screen.y*(1.0/kern_scale.y)*0.5))*off.x; + + + float shadow = shadow2D(shadowMap, stc.xyz).x; // cs + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x; + + return shadow; } float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) @@ -100,41 +90,15 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) stc.xyz /= stc.w; stc.z += shadow_bias; - //stc.x += (((texture2D(noiseMap, pos_screen/128.0).x)-.5)/shadow_res.x); //Random dither. - stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*0.666666666))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here - - float cs = shadow2D(shadowMap, stc.xyz).x; - - float shadow = cs; - - shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; - - - return shadow*0.2; + return calcShadow(shadowMap, stc, shadow_res, pos_screen)*0.2; } float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; - //stc.x += (((texture2D(noiseMap, pos_screen/128.0).x)-.5)/proj_shadow_res.x); //Random dither. - stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap - - float cs = shadow2D(shadowMap, stc.xyz).x; - float shadow = cs; - - vec2 off = 1.0/proj_shadow_res; - off.y *= 1.5; - - shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x; - return shadow*0.2; + return calcShadow(shadowMap, stc, proj_shadow_res, pos_screen)*0.2; } void main() @@ -145,7 +109,7 @@ void main() vec4 pos = getPosition(pos_screen); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + vec3 norm = texture2D(normalMap, pos_screen).xyz; norm = decode_normal(norm.xy); // unpack norm /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index 04b1d1d4a2..61519639fe 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -22,7 +22,7 @@ * $/LicenseInfo$ */ -//#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -32,9 +32,9 @@ out vec4 frag_color; //class 2 -- shadows and SSAO -uniform sampler2DRect diffuseRect; -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; +uniform sampler2D diffuseRect; +uniform sampler2D depthMap; +uniform sampler2D normalMap; uniform sampler2DShadow shadowMap0; uniform sampler2DShadow shadowMap1; uniform sampler2DShadow shadowMap2; @@ -50,8 +50,10 @@ uniform vec4 shadow_clip; VARYING vec2 vary_fragcoord; +uniform vec2 ssao_scale; +uniform vec2 kern_scale; + uniform mat4 inv_proj; -uniform vec2 screen_res; uniform vec2 proj_shadow_res; uniform vec3 sun_dir; @@ -63,36 +65,25 @@ uniform float shadow_offset; uniform float spot_shadow_bias; uniform float spot_shadow_offset; -uniform float downsampled_depth_scale; +vec3 decode_normal(vec2 enc); +vec4 getPosition(vec2 pos_screen); -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} -vec3 decode_normal (vec2 enc) +float calcShadow( sampler2DShadow shadowMap, vec4 stc, vec2 res, vec2 pos_screen ) { - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} + //stc.x += (((texture2D(noiseMap, pos_screen/128.0).x)-.5)/shadow_res.x); //Random dither. -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; + vec2 off = vec2(1,1.5)/res; + stc.x = floor(stc.x*res.x + fract(pos_screen.y*(1.0/kern_scale.y)*0.5))*off.x; + + + float shadow = shadow2D(shadowMap, stc.xyz).x; // cs + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x; + + return shadow; } float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) @@ -100,42 +91,18 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) stc.xyz /= stc.w; stc.z += shadow_bias; - //stc.x += (((texture2D(noiseMap, pos_screen/128.0).x)-.5)/shadow_res.x); //Random dither. - stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*0.666666666))/shadow_res.x; - - float cs = shadow2D(shadowMap, stc.xyz).x; - - float shadow = cs; - - shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; - - return shadow*0.2; + return calcShadow(shadowMap, stc, shadow_res, pos_screen)*0.2; } float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; - //stc.x += (((texture2D(noiseMap, pos_screen/128.0).x)-.5)/proj_shadow_res.x); //Random dither. - stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap - - float cs = shadow2D(shadowMap, stc.xyz).x; - float shadow = cs; - vec2 off = 1.0/proj_shadow_res; - off.y *= 1.5; - - shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x; - - return shadow*0.2; + return calcShadow(shadowMap, stc, proj_shadow_res, pos_screen)*0.2; } + void main() { vec2 pos_screen = vary_fragcoord.xy; @@ -144,7 +111,7 @@ void main() vec4 pos = getPosition(pos_screen); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + vec3 norm = texture2D(normalMap, pos_screen).xyz; norm = decode_normal(norm.xy); // unpack norm /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL @@ -245,7 +212,7 @@ void main() } frag_color[0] = shadow; - frag_color[1] = texture2DRect(diffuseRect,vary_fragcoord*downsampled_depth_scale).r; + frag_color[1] = texture2D(diffuseRect,vary_fragcoord.xy * ssao_scale).r; spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0); diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl deleted file mode 100644 index bc5eb5181d..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file sunLightV.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; - -VARYING vec2 vary_fragcoord; - -uniform vec2 screen_res; - -void main() -{ - //transform vertex - vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); - gl_Position = pos; - - vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; -} diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl index 3acf9fe883..d956a18f73 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl @@ -1,5 +1,5 @@ /** - * @file sumLightsV.glsl + * @file sumLightsSpecularV.glsl * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,7 +24,6 @@ */ - float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol); @@ -47,9 +46,9 @@ vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor vec4 specularSum = vec4(0.0); // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += light_diffuse[1].rgb * calcDirectionalLightSpecular(specularColor, view, norm, light_position[1].xyz,light_diffuse[1].rgb, 1.0); + col.rgb += calcPointLightSpecular(specularSum, view, pos, norm, light_position[1].xyz, light_attenuation[1].x, light_attenuation[1].y, light_diffuse[1].rgb); col.rgb += calcPointLightSpecular(specularSum, view, pos, norm, light_position[2].xyz, light_attenuation[2].x, light_attenuation[2].y, light_diffuse[2].rgb); - col.rgb += calcPointLightSpecular(specularSum, view, pos, norm, light_position[3].xyz, light_attenuation[3].x, light_attenuation[3].y, light_diffuse[3].rgb); + col.rgb += calcPointLightSpecular(specularSum, view, pos, norm, light_position[3].xyz, light_attenuation[3].x, light_attenuation[3].y, light_diffuse[3].rgb); col.rgb = scaleDownLight(col.rgb); // Add windlight lights @@ -58,6 +57,7 @@ vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor col.rgb = min(col.rgb*color.rgb, 1.0); specularColor.rgb = min(specularColor.rgb*specularSum.rgb, 1.0); + col.rgb += specularColor.rgb; return col; diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl index c9987ef3b9..13af09c25a 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl @@ -23,6 +23,7 @@ * $/LicenseInfo$ */ + float calcDirectionalLight(vec3 n, vec3 l); float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); @@ -30,29 +31,30 @@ vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); + uniform vec4 light_position[8]; uniform vec3 light_direction[8]; -uniform vec3 light_attenuation[8]; +uniform vec3 light_attenuation[8]; uniform vec3 light_diffuse[8]; vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) { vec4 col = vec4(0.0, 0.0, 0.0, color.a); - + // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += light_diffuse[1].rgb * calcDirectionalLight(norm, light_position[1].xyz); + // Collect normal lights + col.rgb += light_diffuse[1].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[1], light_direction[1], light_attenuation[1].x, light_attenuation[1].z); col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].z); col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].z); - col.rgb = scaleDownLight(col.rgb); // Add windlight lights col.rgb += atmosAmbient(baseLight.rgb); col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, light_position[0].xyz)); - + col.rgb = min(col.rgb*color.rgb, 1.0); - - return col; + + return col; } diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl index e043ac873e..66a127a59e 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl @@ -1,5 +1,5 @@ /** - * @file sumLightsV.glsl + * @file sumLightsSpecularV.glsl * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code @@ -23,6 +23,7 @@ * $/LicenseInfo$ */ + float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol); @@ -45,7 +46,7 @@ vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor vec4 specularSum = vec4(0.0); // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += light_diffuse[1].rgb * calcDirectionalLightSpecular(specularColor, view, norm, light_position[1].xyz,light_diffuse[1].rgb, 1.0); + col.rgb += calcPointLightSpecular(specularSum, view, pos, norm, light_position[1].xyz, light_attenuation[1].x, light_attenuation[1].y, light_diffuse[1].rgb); col.rgb += calcPointLightSpecular(specularSum, view, pos, norm, light_position[2].xyz, light_attenuation[2].x, light_attenuation[2].y, light_diffuse[2].rgb); col.rgb += calcPointLightSpecular(specularSum, view, pos, norm, light_position[3].xyz, light_attenuation[3].x, light_attenuation[3].y, light_diffuse[3].rgb); col.rgb += calcPointLightSpecular(specularSum, view, pos, norm, light_position[4].xyz, light_attenuation[4].x, light_attenuation[4].y, light_diffuse[4].rgb); @@ -62,5 +63,6 @@ vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor specularColor.rgb = min(specularColor.rgb*specularSum.rgb, 1.0); col.rgb += specularColor.rgb; + return col; } diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl index dadff40933..f6f2ad574b 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl @@ -30,35 +30,35 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); -vec3 scaleUpLight(vec3 light); + uniform vec4 light_position[8]; uniform vec3 light_direction[8]; -uniform vec3 light_attenuation[8]; +uniform vec3 light_attenuation[8]; uniform vec3 light_diffuse[8]; vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) { vec4 col = vec4(0.0, 0.0, 0.0, color.a); - + // Collect normal lights (need to be divided by two, as we later multiply by 2) - + // Collect normal lights + col.rgb += light_diffuse[1].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[1], light_direction[1], light_attenuation[1].x, light_attenuation[1].z); col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].z); col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].z); col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].z); col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].z); col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].z); col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].z); - col.rgb += light_diffuse[1].rgb*calcDirectionalLight(norm, light_position[1].xyz); col.rgb = scaleDownLight(col.rgb); // Add windlight lights - col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, light_position[0].xyz)); col.rgb += atmosAmbient(baseLight.rgb); + col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, light_position[0].xyz)); col.rgb = min(col.rgb*color.rgb, 1.0); - - return col; + + return col; } diff --git a/indra/newview/app_settings/windlight/postprocesseffects.xml b/indra/newview/app_settings/windlight/postprocesseffects.xml index 5a498009cd..afabea4aa0 100644 --- a/indra/newview/app_settings/windlight/postprocesseffects.xml +++ b/indra/newview/app_settings/windlight/postprocesseffects.xml @@ -1,12 +1,13 @@ - - + Asi Weird bloom_strength 4.5799999237060547 bloom_width 12.539999961853027 + gamma + 1.0 brightness 0.89999997615814209 brightness_multiplier @@ -43,6 +44,8 @@ 1.5 bloom_width 2.25 + gamma + 1.0 brightness 1 brightness_multiplier @@ -145,7 +148,7 @@ saturation 1 - default + Default bloom_strength 1.5 @@ -174,12 +177,12 @@ 0 enable_gauss_blur 0 - enable_posterize - 0 - enable_motionblur - 0 - enable_vignette - 0 + enable_posterize + 0 + enable_motionblur + 0 + enable_vignette + 0 gauss_blur_passes 2 extract_high @@ -192,20 +195,1632 @@ 0.40000000000000002 saturation 1 - posterize_layers - 10 - blur_strength - 10 - vignette_strength - 0.85 - vignette_radius - 0.7 - vignette_darkness - 1.0 - vignette_desaturation - 1.0 - vignette_chromatic_aberration - 0.01 + posterize_layers + 10 + blur_strength + 10 + vignette_strength + 0.85 + vignette_radius + 0.7 + vignette_darkness + 1.0 + vignette_desaturation + 1.0 + vignette_chromatic_aberration + 0.01 + + PyFX CatVision v1 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 4 + brightness_multiplier + 3 + contrast + 3 + contrast_base + + 1 + 0 + 0.25 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 1 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 2 + gauss_blur_passes + 1 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.0499999523162841796875 + vignette_chromatic_aberration + 0.1000000014901161193847656 + vignette_darkness + 1 + vignette_desaturation + 1 + vignette_radius + 3.9999997615814208984375 + vignette_strength + 1 + + PyFX CatVision v1 Dark + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 2 + brightness_multiplier + 3 + contrast + 3 + contrast_base + + 1 + 0 + 0.25 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 1 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 2.5 + gauss_blur_passes + 1 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.0499999523162841796875 + vignette_chromatic_aberration + 0.1000000014901161193847656 + vignette_darkness + 1 + vignette_desaturation + 1 + vignette_radius + 3.9999997615814208984375 + vignette_strength + 1 + + PyFX GrimDark v1 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 15 + brightness + 4 + brightness_multiplier + 1 + contrast + 1.25 + contrast_base + + 0.699999988079071044921875 + 0.7999999523162841796875 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 1.25 + gauss_blur_passes + 2 + noise_size + 52.5 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.5 + vignette_chromatic_aberration + 0.009500000625848770141601563 + vignette_darkness + 1 + vignette_desaturation + 0 + vignette_radius + 2 + vignette_strength + 1 + + PyFX GrimDark v2 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 4 + brightness_multiplier + 3 + contrast + 1 + contrast_base + + 1 + 1 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 1 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.599999904632568359375 + vignette_chromatic_aberration + 0.009500000625848770141601563 + vignette_darkness + 1 + vignette_desaturation + 0.4000000059604644775390625 + vignette_radius + 2.9999997615814208984375 + vignette_strength + 1 + + PyFX Last Summer + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 20 + brightness + 1.19999992847442626953125 + brightness_multiplier + 3 + contrast + 1.19999992847442626953125 + contrast_base + + 0.5 + 1 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 2 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 1.6699998378753662109375 + vignette_chromatic_aberration + 0.001500000013038516044616699 + vignette_darkness + 0.25 + vignette_desaturation + 0 + vignette_radius + 7.999999523162841796875 + vignette_strength + 1 + + PyFX Last Winter + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 20 + brightness + 1.19999992847442626953125 + brightness_multiplier + 3 + contrast + 1.19999992847442626953125 + contrast_base + + 1 + 0.75 + 0.5 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 2 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.7999999523162841796875 + vignette_chromatic_aberration + 0.001500000013038516044616699 + vignette_darkness + 0.25 + vignette_desaturation + 0 + vignette_radius + 7.999999523162841796875 + vignette_strength + 1 + + PyFX Memory v1 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 1.5 + brightness_multiplier + 3 + contrast + 1.25 + contrast_base + + 0 + 0.66999995708465576171875 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 1.5 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.5 + vignette_chromatic_aberration + 0.005000000353902578353881836 + vignette_darkness + 1 + vignette_desaturation + 0.4000000059604644775390625 + vignette_radius + 5 + vignette_strength + 1 + + PyFX Memory v1 Cold + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 1.5 + brightness_multiplier + 3 + contrast + 1.25 + contrast_base + + 1 + 0.329999983310699462890625 + 0 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 1.5 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.5 + vignette_chromatic_aberration + 0.005000000353902578353881836 + vignette_darkness + 1 + vignette_desaturation + 0.4000000059604644775390625 + vignette_radius + 5 + vignette_strength + 1 + + PyFX Memory v2 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 20 + brightness + 1 + brightness_multiplier + 3 + contrast + 1.2400000095367431640625 + contrast_base + + 0 + 0.62000000476837158203125 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 2 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 1.3299999237060546875 + vignette_chromatic_aberration + 0.003000000026077032089233398 + vignette_darkness + 0.5 + vignette_desaturation + 0.5 + vignette_radius + 7.999999523162841796875 + vignette_strength + 1 + + PyFX Memory v2 Cold + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 20 + brightness + 1 + brightness_multiplier + 3 + contrast + 1.2400000095367431640625 + contrast_base + + 1 + 0.319999992847442626953125 + 0 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 2 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 1.3299999237060546875 + vignette_chromatic_aberration + 0.003000000026077032089233398 + vignette_darkness + 0.5 + vignette_desaturation + 0.5 + vignette_radius + 7.999999523162841796875 + vignette_strength + 1 + + PyFX Mono v1 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 1 + brightness_multiplier + 3 + contrast + 4 + contrast_base + + 1 + 1 + 1 + 0 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 1 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 1 + gauss_blur_passes + 1 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 3 + saturation + 0 + vignette_chromatic_aberration + 0 + vignette_darkness + 1 + vignette_desaturation + 1 + vignette_radius + 1 + vignette_strength + 1 + + PyFX Neo v1 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 15 + brightness + 1.5 + brightness_multiplier + 1 + contrast + 1.25 + contrast_base + + 1 + 1 + 0.75 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 1.25 + gauss_blur_passes + 2 + noise_size + 52.5 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.849999904632568359375 + vignette_chromatic_aberration + 0.009500000625848770141601563 + vignette_darkness + 1 + vignette_desaturation + 0 + vignette_radius + 2 + vignette_strength + 1 + + PyFX Neo v1 Bright + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 15 + brightness + 2.5 + brightness_multiplier + 1 + contrast + 1.25 + contrast_base + + 1 + 1 + 0.75 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 1.25 + gauss_blur_passes + 2 + noise_size + 52.5 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.849999904632568359375 + vignette_chromatic_aberration + 0.009500000625848770141601563 + vignette_darkness + 1 + vignette_desaturation + 0 + vignette_radius + 2 + vignette_strength + 1 + + PyFX Retrowave + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 20 + brightness + 1 + brightness_multiplier + 3 + contrast + 1.2400000095367431640625 + contrast_base + + 0.2999999821186065673828125 + 1 + 0 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 1.5 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 1.5 + vignette_chromatic_aberration + 0.003000000026077032089233398 + vignette_darkness + 0.5 + vignette_desaturation + 0 + vignette_radius + 7.999999523162841796875 + vignette_strength + 1 + + PyFX Twilight v1 Cold + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 1.25 + brightness_multiplier + 3 + contrast + 1.0299999713897705078125 + contrast_base + + 1 + 0.329999983310699462890625 + 0 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 1.5 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.5 + vignette_chromatic_aberration + 0.005000000353902578353881836 + vignette_darkness + 1 + vignette_desaturation + 0.4000000059604644775390625 + vignette_radius + 5 + vignette_strength + 1 + + PyFX Twilight v1 Warm + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 1.25 + brightness_multiplier + 3 + contrast + 1.0299999713897705078125 + contrast_base + + 0 + 0.66999995708465576171875 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 1.5 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.5 + vignette_chromatic_aberration + 0.005000000353902578353881836 + vignette_darkness + 1 + vignette_desaturation + 0.4000000059604644775390625 + vignette_radius + 5 + vignette_strength + 1 + + PyFX Underwater + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 1.14999997615814208984375 + brightness_multiplier + 3 + contrast + 0.89999997615814208984375 + contrast_base + + 0 + 0.5 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 1 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 0.75 + gauss_blur_passes + 1 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.75 + vignette_chromatic_aberration + 0.01000000070780515670776367 + vignette_darkness + 0.5 + vignette_desaturation + 0 + vignette_radius + 7.999999523162841796875 + vignette_strength + 1 + + PyFX Underwater Murky + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 0.829999983310699462890625 + brightness_multiplier + 3 + contrast + 0.89999997615814208984375 + contrast_base + + 0.64999997615814208984375 + 1 + 0 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 1 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 0.7999999523162841796875 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.3999998569488525390625 + vignette_chromatic_aberration + 0.01000000070780515670776367 + vignette_darkness + 0.5 + vignette_desaturation + 0 + vignette_radius + 7.999999523162841796875 + vignette_strength + 1 + + PyFX Vivid v1 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 1.19999992847442626953125 + brightness_multiplier + 3 + contrast + 1.25 + contrast_base + + 0.7999999523162841796875 + 0.89999997615814208984375 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 2 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 1.19999980926513671875 + vignette_chromatic_aberration + 0.004500000271946191787719727 + vignette_darkness + 1 + vignette_desaturation + 0 + vignette_radius + 2.9999997615814208984375 + vignette_strength + 1 + + PyFX Vivid v1 Cold + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 1.19999992847442626953125 + brightness_multiplier + 3 + contrast + 1.25 + contrast_base + + 1 + 0.89999997615814208984375 + 0.7999999523162841796875 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 2 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 1.19999980926513671875 + vignette_chromatic_aberration + 0.004500000271946191787719727 + vignette_darkness + 1 + vignette_desaturation + 0 + vignette_radius + 2.9999997615814208984375 + vignette_strength + 1 + + PyFX Vivid v2 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 20 + brightness + 1 + brightness_multiplier + 3 + contrast + 1.5 + contrast_base + + 1 + 1 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 3 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 1.5 + vignette_chromatic_aberration + 0.002000000094994902610778809 + vignette_darkness + 0.2999999821186065673828125 + vignette_desaturation + 0 + vignette_radius + 7.999999523162841796875 + vignette_strength + 1 + + PyFX Vivid v2 Bright + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 15 + brightness + 1.25 + brightness_multiplier + 3 + contrast + 1.5 + contrast_base + + 1 + 1 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 3 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 1.5 + vignette_chromatic_aberration + 0.01000000000000000020816682 + vignette_darkness + 1 + vignette_desaturation + 1 + vignette_radius + 1 + vignette_strength + 1 + + PyFX Vivid v2 Dark + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 15 + brightness + 1 + brightness_multiplier + 3 + contrast + 1.5 + contrast_base + + 1 + 1 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 3 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 1.5 + vignette_chromatic_aberration + 0.01000000000000000020816682 + vignette_darkness + 1 + vignette_desaturation + 1 + vignette_radius + 1 + vignette_strength + 1 + + PyFX v1 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 1.19999992847442626953125 + brightness_multiplier + 3 + contrast + 1.25 + contrast_base + + 0.7999999523162841796875 + 0.89999997615814208984375 + 1 + 1 + + enable_bloom + 0 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 2 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 0.7999999523162841796875 + vignette_chromatic_aberration + 0.004500000271946191787719727 + vignette_darkness + 1 + vignette_desaturation + 0 + vignette_radius + 1.5 + vignette_strength + 1 + + PyFX v2 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 1 + brightness_multiplier + 3 + contrast + 2 + contrast_base + + 0.949999988079071044921875 + 0.969999969005584716796875 + 1 + 1 + + enable_bloom + 1 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 5 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 1 + vignette_chromatic_aberration + 0.004500000271946191787719727 + vignette_darkness + 1 + vignette_desaturation + 0 + vignette_radius + 1.5 + vignette_strength + 1 + + PyFX v3 + + bloom_strength + 1.5 + bloom_width + 2.25 + blur_strength + 30 + brightness + 1 + brightness_multiplier + 3 + contrast + 1.75 + contrast_base + + 0.949999988079071044921875 + 0.969999969005584716796875 + 1 + 1 + + enable_bloom + 1 + enable_color_filter + 1 + enable_gauss_blur + 0 + enable_motionblur + 1 + enable_night_vision + 0 + enable_posterize + 0 + enable_vignette + 1 + extract_high + 1 + extract_low + 0.949999999999999955591079 + gamma + 4 + gauss_blur_passes + 2 + noise_size + 25 + noise_strength + 0.4000000000000000222044605 + posterize_layers + 10 + saturation + 1.099999904632568359375 + vignette_chromatic_aberration + 0.004500000271946191787719727 + vignette_darkness + 0.66999995708465576171875 + vignette_desaturation + 0 + vignette_radius + 2.9999997615814208984375 + vignette_strength + 1 + - - \ No newline at end of file + diff --git a/indra/newview/app_settings/windlight/skies/%252ACanimod.xml b/indra/newview/app_settings/windlight/skies/%252ACanimod.xml deleted file mode 100644 index d4e69e6226..0000000000 --- a/indra/newview/app_settings/windlight/skies/%252ACanimod.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - ambient - - 1.4699999094009399 - 1.4699999094009399 - 1.4699999094009399 - 0.48999997973442078 - - blue_density - - 0.099999994039535522 - 0.037499997764825821 - 0.067499987781047821 - 0.049999997019767761 - - blue_horizon - - 0.15130999684333801 - 0.30000001192092896 - 0.35131001472473145 - 1 - - cloud_color - - 0.22999998927116394 - 0.22999998927116394 - 0.22999998927116394 - 0.22999998927116394 - - cloud_pos_density1 - - 0.88419097661972046 - 0.53047597408294678 - 0.52999997138977051 - 1 - - cloud_pos_density2 - - 0.2800000011920929 - 0.19999998807907104 - 0.31999999284744263 - 1 - - cloud_scale - - 0.0099999997764825821 - 0 - 0 - 1 - - cloud_scroll_rate - - 0 - 15.329999446868896 - - cloud_shadow - - 0 - 0 - 0 - 1 - - density_multiplier - - 0.00022000000171829015 - 0 - 0 - 1 - - distance_multiplier - - 16.200000762939453 - 0 - 0 - 1 - - east_angle - 6.2831854820251465 - enable_cloud_scroll - - 1 - 1 - - gamma - - 1.4199999570846558 - 0 - 0 - 1 - - glow - - 18.599998474121094 - 0.0012815999798476696 - 0 - 1 - - haze_density - - 0 - 0 - 0 - 1 - - haze_horizon - - 1 - 0.21744099259376526 - 0.21744099259376526 - 1 - - lightnorm - - -1.7484555314695172e-007 - 0 - 1 - 0 - - max_y - - 403 - 0 - 0 - 1 - - preset_num - 2 - star_brightness - 0 - sun_angle - 0 - sunlight_color - - 0 - 0 - 0 - 0 - - - diff --git a/indra/newview/app_settings/windlight/skies/%252AStarley%252A%20Settings%202.xml b/indra/newview/app_settings/windlight/skies/%252AStarley%252A%20Settings%202.xml deleted file mode 100644 index 6d1c09d30a..0000000000 --- a/indra/newview/app_settings/windlight/skies/%252AStarley%252A%20Settings%202.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - ambient - - 1.4699999094009399 - 1.4699999094009399 - 1.4699999094009399 - 0.48999997973442078 - - blue_density - - 0.14000000059604645 - 0.14000000059604645 - 0.14000000059604645 - 0.070000000298023224 - - blue_horizon - - 0.83809572458267212 - 1.0735483169555664 - 1.2799999713897705 - 0.63999998569488525 - - cloud_color - - 0.12862999737262726 - 0.12862999737262726 - 0.12862999737262726 - 1 - - cloud_pos_density1 - - 0.70999997854232788 - 0.53047597408294678 - 0.4270470142364502 - 1 - - cloud_pos_density2 - - 0.38419300317764282 - 0.5 - 0.125 - 1 - - cloud_scale - - 0.72999995946884155 - 0 - 0 - 1 - - cloud_scroll_rate - - 10 - 10 - - cloud_shadow - - 0.2199999988079071 - 0 - 0 - 1 - - density_multiplier - - 0.00017999998817685992 - 0 - 0 - 1 - - distance_multiplier - - 11.40000057220459 - 0 - 0 - 1 - - east_angle - 0 - enable_cloud_scroll - - 1 - 1 - - gamma - - 1.6899999380111694 - 0 - 0 - 1 - - glow - - 6.4079799652099609 - 0.0012815999798476696 - -0.39999997615814209 - 1 - - haze_density - - 1.4900000095367432 - 0 - 0 - 1 - - haze_horizon - - 0 - 0.21744099259376526 - 0.21744099259376526 - 1 - - lightnorm - - 0 - 0 - 1 - 0 - - max_y - - 805 - 0 - 0 - 1 - - preset_num - 2 - star_brightness - 1.5699999332427979 - sun_angle - 0 - sunlight_color - - 3 - 3 - 3 - 1 - - - diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Black.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Black.xml new file mode 100644 index 0000000000..cea6b11522 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Black.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0.23999999567946317 + 0.23999999579784967 + 0.23999999583870221 + 1 + + cloud_color + + 0.22615400241575034 + 0.22615400241575034 + 0.22615400241575034 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511475 + 0 + 0 + 1 + + density_multiplier + + 0.0010000000474974513 + 0 + 0 + 1 + + distance_multiplier + + 10 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600437467304 + 0.19915600437467304 + 1 + + lightnorm + + -0 + 1 + 1.1483815569590661e-006 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 0 + sun_angle + 1.5707951784133911 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Dark%20Blue.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Dark%20Blue.xml new file mode 100644 index 0000000000..340ffe6e3c --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Dark%20Blue.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0.1499999910593032836914063 + 0.2999999821186065673828125 + 0.0999999940395355224609375 + + blue_density + + 0.89999997615814208984375 + 0.89999997615814208984375 + 0.89999997615814208984375 + 0.449999988079071044921875 + + blue_horizon + + 0.2999999821186065673828125 + 0.5 + 0.599999964237213134765625 + 0.2999999821186065673828125 + + cloud_color + + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.4199999868869781494140625 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511474609375 + 0 + 0 + 1 + + density_multiplier + + 0.0008999999845400452613830566 + 0 + 0 + 1 + + distance_multiplier + + 15 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.001000000047497451305389404 + -0 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.1991560043746730401803546 + 0.1991560043746730401803546 + 1 + + lightnorm + + 0 + 1 + -4.371138828673792886547744e-08 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 1 + sun_angle + 1.57079637050628662109375 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Dark.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Dark.xml new file mode 100644 index 0000000000..36023d958f --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Dark.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0.23999999567946317 + 0.23999999579784967 + 0.23999999583870221 + 1 + + cloud_color + + 0.22615400241575034 + 0.22615400241575034 + 0.22615400241575034 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511475 + 0 + 0 + 1 + + density_multiplier + + 0.0010000000474974513 + 0 + 0 + 1 + + distance_multiplier + + 10 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 5 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600437467304 + 0.19915600437467304 + 1 + + lightnorm + + -0 + 1 + 1.1483815569590661e-006 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 0 + sun_angle + 1.5707951784133911 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Gray%20Blue.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Gray%20Blue.xml new file mode 100644 index 0000000000..329f0e11ca --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Gray%20Blue.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.5 + 1.5 + 1.5 + 0.5 + + blue_density + + 1 + 1.5058819055557251 + 2 + 1 + + blue_horizon + + 0.23999999567946317 + 0.23999999579784967 + 0.23999999583870221 + 1 + + cloud_color + + 0.22615400241575034 + 0.22615400241575034 + 0.22615400241575034 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511475 + 0 + 0 + 1 + + density_multiplier + + 0.00089999998454004526 + 0 + 0 + 1 + + distance_multiplier + + 4 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600437467304 + 0.19915600437467304 + 1 + + lightnorm + + -0 + 1 + 1.1483815569590661e-006 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 0 + sun_angle + 1.5707951784133911 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Gray.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Gray.xml new file mode 100644 index 0000000000..ff2099f9fb --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Gray.xml @@ -0,0 +1,141 @@ + + + ambient + + 2.2499997615814209 + 2.2499997615814209 + 2.2499997615814209 + 0.75 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0.23999999567946317 + 0.23999999579784967 + 0.23999999583870221 + 1 + + cloud_color + + 0.22615400241575034 + 0.22615400241575034 + 0.22615400241575034 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511475 + 0 + 0 + 1 + + density_multiplier + + 0.00089999998454004526 + 0 + 0 + 1 + + distance_multiplier + + 12.5 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600437467304 + 0.19915600437467304 + 1 + + lightnorm + + -0 + 1 + 1.1483815569590661e-006 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 0 + sun_angle + 1.5707951784133911 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Underwater.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Underwater.xml new file mode 100644 index 0000000000..8203071d1b --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20Underwater.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0.2100000083446502685546875 + 0.08999999612569808959960938 + 0.2100000083446502685546875 + + blue_density + + 0.89999997615814208984375 + 0.89999997615814208984375 + 0.89999997615814208984375 + 0.449999988079071044921875 + + blue_horizon + + 0.2999999821186065673828125 + 0.5 + 0.599999964237213134765625 + 0.2999999821186065673828125 + + cloud_color + + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.4199999868869781494140625 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511474609375 + 0 + 0 + 1 + + density_multiplier + + 0.0008999999845400452613830566 + 0 + 0 + 1 + + distance_multiplier + + 15 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.001000000047497451305389404 + -0 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.1991560043746730401803546 + 0.1991560043746730401803546 + 1 + + lightnorm + + 0 + 1 + -4.371138828673792886547744e-08 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 1 + sun_angle + 1.57079637050628662109375 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20White%20Wash.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20White%20Wash.xml new file mode 100644 index 0000000000..351c83361e --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20White%20Wash.xml @@ -0,0 +1,141 @@ + + + ambient + + 3 + 3 + 3 + 1 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.199999988079071044921875 + + cloud_color + + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.4199999868869781494140625 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511474609375 + 0 + 0 + 1 + + density_multiplier + + 0.0008999999845400452613830566 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.001000000047497451305389404 + -0 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.1991560043746730401803546 + 0.1991560043746730401803546 + 1 + + lightnorm + + -0 + 1 + 1.148381556959066074341536e-06 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 0 + sun_angle + 1.57079517841339111328125 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20White.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20White.xml new file mode 100644 index 0000000000..c915884666 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20%2BFog%20White.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.5 + 1.5 + 1.5 + 0.5 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.199999988079071044921875 + + cloud_color + + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.4199999868869781494140625 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511474609375 + 0 + 0 + 1 + + density_multiplier + + 0.0008999999845400452613830566 + 0 + 0 + 1 + + distance_multiplier + + 1 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.001000000047497451305389404 + -0 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.1991560043746730401803546 + 0.1991560043746730401803546 + 1 + + lightnorm + + -0 + 1 + 1.148381556959066074341536e-06 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 0 + sun_angle + 1.57079517841339111328125 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Black.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Black.xml new file mode 100644 index 0000000000..04c9713ed3 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Black.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0.44999999369830818 + 0.44999999398335949 + 0.4499999944309046 + 1 + + blue_horizon + + 0.23999999567946317 + 0.23999999579784967 + 0.23999999583870221 + 1 + + cloud_color + + 0.22615400241575034 + 0.22615400241575034 + 0.22615400241575034 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511475 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 3.0208916693946743e-009 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600437467304 + 0.19915600437467304 + 1 + + lightnorm + + -0 + 1 + 1.1483815569590661e-006 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 2 + sun_angle + 1.5707951784133911 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Dark%20H%2DBomb.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Dark%20H%2DBomb.xml new file mode 100644 index 0000000000..c2ceef4d01 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Dark%20H%2DBomb.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.5 + 0 + 0 + 1.5 + + blue_density + + 0.449999993698308176082179 + 0.4499999939833594919669224 + 0.4499999944309046040480382 + 1 + + blue_horizon + + 0.2399999956794631739143142 + 0.2399999957978496689658954 + 0.2399999958387022125361199 + 1 + + cloud_color + + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.4199999868869781494140625 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511474609375 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 3.02089166939467428676299e-09 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.39999997615814208984375 + 0 + 0 + 1 + + glow + + 5 + 0.001000000047497451305389404 + -0 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.1991560043746730401803546 + 0.1991560043746730401803546 + 1 + + lightnorm + + -0 + 1 + 1.148381556959066074341536e-06 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 2 + sun_angle + 1.57079517841339111328125 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Dark.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Dark.xml new file mode 100644 index 0000000000..83bd660b64 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Dark.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 2 + 2 + 2 + 1 + + cloud_color + + 0.22615400241575034 + 0.22615400241575034 + 0.22615400241575034 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511475 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 3.0208916693946743e-009 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 4 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600437467304 + 0.19915600437467304 + 1 + + lightnorm + + -0 + 1 + 1.1483815569590661e-006 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 2 + sun_angle + 1.5707951784133911 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Gray%20Background.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Gray%20Background.xml new file mode 100644 index 0000000000..fe1c9f8c0a --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Gray%20Background.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.5 + 1.5 + 1.5 + 0.5 + + blue_density + + 0.449999993698308176082179 + 0.4499999939833594919669224 + 0.4499999944309046040480382 + 1 + + blue_horizon + + 0.89999997615814208984375 + 0.89999997615814208984375 + 0.89999997615814208984375 + 0.449999988079071044921875 + + cloud_color + + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 0.2261540024157503436796901 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.4199999868869781494140625 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511474609375 + 0 + 0 + 1 + + density_multiplier + + 0.0004499999922700226306915283 + 0 + 0 + 1 + + distance_multiplier + + 0 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.001000000047497451305389404 + -0 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.1991560043746730401803546 + 0.1991560043746730401803546 + 1 + + lightnorm + + -0 + 1 + 1.148381556959066074341536e-06 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 0 + sun_angle + 1.57079517841339111328125 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Gray.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Gray.xml new file mode 100644 index 0000000000..2ab736ee46 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20Gray.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.5 + 1.5 + 1.5 + 0.5 + + blue_density + + 0.44999999369830818 + 0.44999999398335949 + 0.4499999944309046 + 1 + + blue_horizon + + 0.23999999567946317 + 0.23999999579784967 + 0.23999999583870221 + 1 + + cloud_color + + 0.22615400241575034 + 0.22615400241575034 + 0.22615400241575034 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511475 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 3.0208916693946743e-009 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600437467304 + 0.19915600437467304 + 1 + + lightnorm + + -0 + 1 + 1.1483815569590661e-006 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 2 + sun_angle + 1.5707951784133911 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20White.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20White.xml new file mode 100644 index 0000000000..6321311a4c --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Ambient%20White.xml @@ -0,0 +1,141 @@ + + + ambient + + 3 + 3 + 2.9999997615814209 + 1 + + blue_density + + 0.44999999369830818 + 0.44999999398335949 + 0.4499999944309046 + 1 + + blue_horizon + + 0.23999999567946317 + 0.23999999579784967 + 0.23999999583870221 + 1 + + cloud_color + + 0.22615400241575034 + 0.22615400241575034 + 0.22615400241575034 + 1 + + cloud_pos_density1 + + 0 + 0 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.36000001430511475 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 3.0208916693946743e-009 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600437467304 + 0.19915600437467304 + 1 + + lightnorm + + -0 + 1 + 1.1483815569590661e-006 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 26 + star_brightness + 2 + sun_angle + 1.5707951784133911 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Afternoon.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Afternoon.xml new file mode 100644 index 0000000000..233a3b354f --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Afternoon.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.449999988079071044921875 + 0.89999997615814208984375 + 1.0499999523162841796875 + 0.3499999940395355224609375 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0.5 + 0.5 + 0.5 + 0.25 + + cloud_color + + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + + cloud_pos_density1 + + 1 + 1 + 0.2999999821186065673828125 + 1 + + cloud_pos_density2 + + 1 + 1 + 0 + 1 + + cloud_scale + + 0.2000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.3999996185302734375 + 10 + + cloud_shadow + + 0.75 + 0 + 0 + 1 + + density_multiplier + + 4.999999873689375817775726e-05 + 0 + 0 + 1 + + distance_multiplier + + 7 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.599999964237213134765625 + 0 + 0 + 1 + + glow + + 0.200002193450927734375 + 0.001000000047497451305389404 + -0.199999988079071044921875 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.1499999910593032836914063 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.876306593418121337890625 + -0.4817537963390350341796875 + 0 + + max_y + + 1 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.0734512805938720703125 + sunlight_color + + 1.0499999523162841796875 + 1.0499999523162841796875 + 1.0499999523162841796875 + 0.3499999940395355224609375 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Dusk.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Dusk.xml new file mode 100644 index 0000000000..8fe71abd14 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Dusk.xml @@ -0,0 +1,106 @@ + + + ambient + + 0 + 0.05999999865889549255371094 + 0.1499999910593032836914063 + 0.04999999701976776123046875 + + blue_density + + 1.99999988079071044921875 + 1.99999988079071044921875 + 1.99999988079071044921875 + 1 + + blue_horizon + + 0.680000007152557373046875 + 0.680000007152557373046875 + 0.680000007152557373046875 + 0.3400000035762786865234375 + + cloud_color + + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + + cloud_pos_density1 + + 1 + 1 + 0.0999999940395355224609375 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 1 + 0.0999999940395355224609375 + 1 + + cloud_scale + 0.2000000029802322387695313 + cloud_scroll_rate + + 10.1499996185302734375 + 10 + + cloud_shadow + 0.5 + density_multiplier + 5.999999848427250981330872e-05 + distance_multiplier + 3 + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.75 + 0 + 0 + 1 + + glow + + 10 + 0.001000000047497451305389404 + -0.449999988079071044921875 + 1 + + haze_density + 4 + haze_horizon + 0 + lightnorm + + 0 + 0 + -1 + 0 + + max_y + 500 + preset_num + 22 + star_brightness + 0 + sun_angle + 3.1415927410125732421875 + sunlight_color + + 0.2999999821186065673828125 + 0.38999998569488525390625 + 0.4500000178813934326171875 + 0.1499999910593032836914063 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Evening.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Evening.xml new file mode 100644 index 0000000000..4039d2ee5b --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Evening.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.2999999821186065673828125 + 0.449999988079071044921875 + 0.599999964237213134765625 + 0.199999988079071044921875 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0.5 + 0.5 + 0.5 + 0.25 + + cloud_color + + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + + cloud_pos_density1 + + 1 + 1 + 0.25 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 1 + 0 + 1 + + cloud_scale + + 0.2000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.3999996185302734375 + 10 + + cloud_shadow + + 0.75 + 0 + 0 + 1 + + density_multiplier + + 4.999999873689375817775726e-05 + 0 + 0 + 1 + + distance_multiplier + + 7 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.89999997615814208984375 + 0 + 0 + 1 + + glow + + 10 + 0.001000000047497451305389404 + -0.449999988079071044921875 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.1873810738325119018554688 + -0.98228728771209716796875 + 0 + + max_y + + 1 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.95309734344482421875 + sunlight_color + + 1.0499999523162841796875 + 0.75 + 0.599999964237213134765625 + 1.0499999523162841796875 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Noon.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Noon.xml new file mode 100644 index 0000000000..60882441d9 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Noon.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.2999999821186065673828125 + 0.44999992847442626953125 + 0.599999964237213134765625 + 0.199999988079071044921875 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0.599999964237213134765625 + 0.599999964237213134765625 + 0.599999964237213134765625 + 0.2999999821186065673828125 + + cloud_color + + 0.329999983310699462890625 + 0.329999983310699462890625 + 0.329999983310699462890625 + 0.329999983310699462890625 + + cloud_pos_density1 + + 1 + 1 + 0.25 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 1 + 0 + 1 + + cloud_scale + + 0.2000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.3999996185302734375 + 10 + + cloud_shadow + + 0.75 + 0 + 0 + 1 + + density_multiplier + + 9.999999747378751635551453e-05 + 0 + 0 + 1 + + distance_multiplier + + 5 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.89999997615814208984375 + 0 + 0 + 1 + + glow + + 0.200002193450927734375 + 0.001000000047497451305389404 + -0.199999988079071044921875 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.2099999934434890747070313 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 1 + -4.371138828673792886547744e-08 + 0 + + max_y + + 1 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 1.57079637050628662109375 + sunlight_color + + 1.0499999523162841796875 + 1.0499999523162841796875 + 1.0499999523162841796875 + 0.3499999940395355224609375 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Rainy%20Bright.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Rainy%20Bright.xml new file mode 100644 index 0000000000..409cea7e39 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Rainy%20Bright.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 2 + + blue_horizon + + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.199999988079071044921875 + + cloud_color + + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.1700000017881393432617188 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 1 + 0 + 1 + + cloud_scale + + 0.2000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.3999996185302734375 + 10 + + cloud_shadow + + 0.75 + 0 + 0 + 1 + + density_multiplier + + 0.0005999999702908098697662354 + 0 + 0 + 1 + + distance_multiplier + + 3.5 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.599999904632568359375 + 0 + 0 + 1 + + glow + + 0.200002193450927734375 + 0.001000000047497451305389404 + -0.1499999910593032836914063 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.04999999701976776123046875 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.876306593418121337890625 + -0.4817537963390350341796875 + 0 + + max_y + + 26 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.0734512805938720703125 + sunlight_color + + 0.599999964237213134765625 + 0.75 + 0.749999940395355224609375 + 0.75 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Rainy%20HalfBright.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Rainy%20HalfBright.xml new file mode 100644 index 0000000000..eee6373888 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Rainy%20HalfBright.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 2 + + blue_horizon + + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.199999988079071044921875 + + cloud_color + + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.1700000017881393432617188 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 1 + 0 + 1 + + cloud_scale + + 0.2000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.3999996185302734375 + 10 + + cloud_shadow + + 0.75 + 0 + 0 + 1 + + density_multiplier + + 0.0005999999702908098697662354 + 0 + 0 + 1 + + distance_multiplier + + 3.5 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.19999992847442626953125 + 0 + 0 + 1 + + glow + + 0.200002193450927734375 + 0.001000000047497451305389404 + -0.1499999910593032836914063 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.04999999701976776123046875 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.876306593418121337890625 + -0.4817537963390350341796875 + 0 + + max_y + + 100 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.0734512805938720703125 + sunlight_color + + 0.599999964237213134765625 + 0.75 + 0.749999940395355224609375 + 0.75 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Rainy.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Rainy.xml new file mode 100644 index 0000000000..1b1fd7488f --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Cloudy%20Rainy.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 2 + + blue_horizon + + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.199999988079071044921875 + + cloud_color + + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.1700000017881393432617188 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 1 + 0 + 1 + + cloud_scale + + 0.2000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.3999996185302734375 + 10 + + cloud_shadow + + 0.75 + 0 + 0 + 1 + + density_multiplier + + 0.0005999999702908098697662354 + 0 + 0 + 1 + + distance_multiplier + + 3.5 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.599999964237213134765625 + 0 + 0 + 1 + + glow + + 0.200002193450927734375 + 0.001000000047497451305389404 + -0.1499999910593032836914063 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.04999999701976776123046875 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.876306593418121337890625 + -0.4817537963390350341796875 + 0 + + max_y + + 100 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.0734512805938720703125 + sunlight_color + + 0.599999964237213134765625 + 0.75 + 0.749999940395355224609375 + 0.75 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Default%20.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Default%20.xml new file mode 100644 index 0000000000..b26c41ae13 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Default%20.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.2880000174045562744140625 + 0.449999988079071044921875 + 0.599999964237213134765625 + 0.599999964237213134765625 + + blue_density + + 0.199999988079071044921875 + 0.2999999821186065673828125 + 0.599999964237213134765625 + 0.2999999821186065673828125 + + blue_horizon + + 0 + 0.199999988079071044921875 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 1 + 1 + 0.08999999612569808959960938 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 0 + 0.75 + 1 + + cloud_scale + + 0.4999999701976776123046875 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.19999980926513671875 + 10.0109996795654296875 + + cloud_shadow + + 0.5 + 0 + 0 + 1 + + density_multiplier + + 0.0002500000118743628263473511 + 0 + 0 + 1 + + distance_multiplier + + 1 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.75 + 0 + 0 + 1 + + glow + + 10 + 0.001000000047497451305389404 + -0.4999999701976776123046875 + 1 + + haze_density + + 0.199999988079071044921875 + 0 + 0 + 1 + + haze_horizon + + 0.4699999988079071044921875 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.867070615291595458984375 + -0.49818527698516845703125 + 0 + + max_y + + 2000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.092300891876220703125 + sunlight_color + + 1.5 + 1.5 + 1.5 + 0.5 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Fine%20Afternoon.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Fine%20Afternoon.xml new file mode 100644 index 0000000000..438cfe90b7 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Fine%20Afternoon.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.599999964237213134765625 + 1.049999237060546875 + 1.19999992847442626953125 + 0.39999997615814208984375 + + blue_density + + 0.0999999940395355224609375 + 0.2999999821186065673828125 + 0.39999997615814208984375 + 0.560000002384185791015625 + + blue_horizon + + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.7999999523162841796875 + 0.39999997615814208984375 + + cloud_color + + 0.39999997615814208984375 + 0.2800000011920928955078125 + 0.1999999433755874633789063 + 0.39999997615814208984375 + + cloud_pos_density1 + + 1 + 1 + 0.0999999940395355224609375 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 0 + 0.0999999940395355224609375 + 1 + + cloud_scale + + 0.05999999493360519409179688 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.5 + 10.0109996795654296875 + + cloud_shadow + + 0.5 + 0 + 0 + 1 + + density_multiplier + + 9.999999747378751635551453e-05 + 0 + 0 + 1 + + distance_multiplier + + 6 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.599999964237213134765625 + 0 + 0 + 1 + + glow + + 20 + 0.001000000047497451305389404 + -1.25 + 1 + + haze_density + + 0.5 + 0 + 0 + 1 + + haze_horizon + + 0.2999999821186065673828125 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.587785184383392333984375 + -0.80901706218719482421875 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.51327419281005859375 + sunlight_color + + 1.5 + 1.19999992847442626953125 + 0.89999997615814208984375 + 1.5 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Flamesight.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Flamesight.xml new file mode 100644 index 0000000000..aafbc189f9 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Flamesight.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0 + 0 + 1.5 + 1.5 + + blue_horizon + + 0 + 0 + 2 + 2 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 1.6884100437164306640625 + 0 + 0.5 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 0.526096999645233154296875 + 0 + 1 + + cloud_scale + + 0.0999999940395355224609375 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.19999980926513671875 + 10.0109996795654296875 + + cloud_shadow + + 0.5 + 0 + 0 + 1 + + density_multiplier + + 0.0003299999807495623826980591 + 0 + 0 + 1 + + distance_multiplier + + 50 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.329999983310699462890625 + 0 + 0 + 1 + + glow + + 30 + 0.001000000047497451305389404 + -0.4999999701976776123046875 + 1 + + haze_density + + 1 + 0 + 0 + 1 + + haze_horizon + + 0.5 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.867070615291595458984375 + -0.49818527698516845703125 + 0 + + max_y + + 2000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.092300891876220703125 + sunlight_color + + 3 + 0.990000188350677490234375 + 0 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Bright.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Bright.xml new file mode 100644 index 0000000000..16ce75e17b --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Bright.xml @@ -0,0 +1,141 @@ + + + ambient + + 2.25 + 2.25 + 2.25 + 0.75 + + blue_density + + 2 + 2 + 2 + 2 + + blue_horizon + + 0.1999999731779098510742188 + 0.1999999731779098510742188 + 0.1999999731779098510742188 + 0.0999999940395355224609375 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 1 + 1 + 0.08999999612569808959960938 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 0 + 0.75 + 1 + + cloud_scale + + 0.4999999701976776123046875 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.19999980926513671875 + 10.0109996795654296875 + + cloud_shadow + + 1 + 0 + 0 + 1 + + density_multiplier + + 9.999999747378751635551453e-06 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.66999995708465576171875 + 0 + 0 + 1 + + glow + + 10 + 0.001000000047497451305389404 + -0.4999999701976776123046875 + 1 + + haze_density + + 1 + 0 + 0 + 1 + + haze_horizon + + 1 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.867070615291595458984375 + -0.49818527698516845703125 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.092300891876220703125 + sunlight_color + + 3 + 2.4000003337860107421875 + 2.099999904632568359375 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Cloudy.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Cloudy.xml new file mode 100644 index 0000000000..40bbf3b88e --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Cloudy.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.5 + 1.7999999523162841796875 + 2.099999904632568359375 + 2.099999904632568359375 + + blue_density + + 2 + 2 + 2 + 2 + + blue_horizon + + 0.1999999731779098510742188 + 0.1999999731779098510742188 + 0.1999999731779098510742188 + 0.0999999940395355224609375 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 1 + 1 + 0.08999999612569808959960938 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 0 + 0.75 + 1 + + cloud_scale + + 0.4999999701976776123046875 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.19999980926513671875 + 10.0109996795654296875 + + cloud_shadow + + 1 + 0 + 0 + 1 + + density_multiplier + + 1.999999949475750327110291e-05 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.66999995708465576171875 + 0 + 0 + 1 + + glow + + 10 + 0.001000000047497451305389404 + -0.4999999701976776123046875 + 1 + + haze_density + + 1 + 0 + 0 + 1 + + haze_horizon + + 1 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.867070615291595458984375 + -0.49818527698516845703125 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.092300891876220703125 + sunlight_color + + 1.230000019073486328125 + 1.230000019073486328125 + 1.230000019073486328125 + 0.4099999964237213134765625 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Evening.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Evening.xml new file mode 100644 index 0000000000..c10d7dc873 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Evening.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.2999999821186065673828125 + 0.599999964237213134765625 + 0.89999997615814208984375 + 0.89999997615814208984375 + + blue_density + + 2 + 2 + 2 + 2 + + blue_horizon + + 0.1999999731779098510742188 + 0.1999999731779098510742188 + 0.1999999731779098510742188 + 0.0999999940395355224609375 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 1 + 1 + 0.08999999612569808959960938 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 0 + 0.75 + 1 + + cloud_scale + + 0.4999999701976776123046875 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.19999980926513671875 + 10.0109996795654296875 + + cloud_shadow + + 1 + 0 + 0 + 1 + + density_multiplier + + 1.999999949475750327110291e-05 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.66999995708465576171875 + 0 + 0 + 1 + + glow + + 10 + 0.001000000047497451305389404 + -0.4999999701976776123046875 + 1 + + haze_density + + 1 + 0 + 0 + 1 + + haze_horizon + + 1 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0 + -1 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 3.1415927410125732421875 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Night.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Night.xml new file mode 100644 index 0000000000..2958cad7e9 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Indoors%20Night.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.599999964237213134765625 + 0.75 + 1.19999992847442626953125 + 0.39999997615814208984375 + + blue_density + + 1.99999988079071044921875 + 1.99999988079071044921875 + 1.99999988079071044921875 + 1 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 1 + 1 + 0.08999999612569808959960938 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 0 + 0.75 + 1 + + cloud_scale + + 0.4999999701976776123046875 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.19999980926513671875 + 10.0109996795654296875 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.0002500000118743628263473511 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.66999995708465576171875 + 0 + 0 + 1 + + glow + + 10 + 0.001000000047497451305389404 + -0.4999999701976776123046875 + 1 + + haze_density + + 1 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0 + -1 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 3.1415927410125732421875 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20Bright.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20Bright.xml new file mode 100644 index 0000000000..7b4cebdb97 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20Bright.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0.1499999910593032836914063 + 0.4500000178813934326171875 + 0.1499999910593032836914063 + + blue_density + + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.199999988079071044921875 + + blue_horizon + + 0.4000000059604644775390625 + 0.599999725818634033203125 + 0.800000011920928955078125 + 0.39999997615814208984375 + + cloud_color + + 0.329999983310699462890625 + 0.329999983310699462890625 + 0.329999983310699462890625 + 0.329999983310699462890625 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.0999999940395355224609375 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0 + 1 + + cloud_scale + + 0.07000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.1399993896484375 + 10.0109996795654296875 + + cloud_shadow + + 0.39999997615814208984375 + 0 + 0 + 1 + + density_multiplier + + 4.999999873689375817775726e-05 + 0 + 0 + 1 + + distance_multiplier + + 10 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2 + 0 + 0 + 1 + + glow + + 20 + 0.001000000047497451305389404 + -1.25 + 1 + + haze_density + + 2 + 0 + 0 + 1 + + haze_horizon + + 0.04999999701976776123046875 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + -0 + 0.3090172111988067626953125 + 0.951056420803070068359375 + 1 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 10 + star_brightness + 0.5 + sun_angle + 3.4557521343231201171875 + sunlight_color + + 0.08999999612569808959960938 + 0.1799999922513961791992188 + 0.2999999821186065673828125 + 0.0999999940395355224609375 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20City%20Bright.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20City%20Bright.xml new file mode 100644 index 0000000000..19951bad6b --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20City%20Bright.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0.1499999910593032836914063 + 0.449999988079071044921875 + 0.449999988079071044921875 + + blue_density + + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.199999988079071044921875 + + blue_horizon + + 0.7999999523162841796875 + 0.599999964237213134765625 + 0.39999997615814208984375 + 0.39999997615814208984375 + + cloud_color + + 0.699999988079071044921875 + 0.39999997615814208984375 + 0.2999999821186065673828125 + 0.699999988079071044921875 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.04999999701976776123046875 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0 + 1 + + cloud_scale + + 0.07000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.1399993896484375 + 10.0109996795654296875 + + cloud_shadow + + 0.5 + 0 + 0 + 1 + + density_multiplier + + 4.999999873689375817775726e-05 + 0 + 0 + 1 + + distance_multiplier + + 10 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2 + 0 + 0 + 1 + + glow + + 20 + 0.001000000047497451305389404 + -1.25 + 1 + + haze_density + + 2 + 0 + 0 + 1 + + haze_horizon + + 0.04999999701976776123046875 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + -0 + 0.3090172111988067626953125 + 0.951056420803070068359375 + 1 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 10 + star_brightness + 0.5 + sun_angle + 3.4557521343231201171875 + sunlight_color + + 0.1799999922513961791992188 + 0.1799999922513961791992188 + 0.1799999922513961791992188 + 0.1799999922513961791992188 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20City.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20City.xml new file mode 100644 index 0000000000..8fa2e039f5 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20City.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0.1499999910593032836914063 + 0.449999988079071044921875 + 0.449999988079071044921875 + + blue_density + + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.199999988079071044921875 + + blue_horizon + + 0.7999999523162841796875 + 0.599999964237213134765625 + 0.39999997615814208984375 + 0.39999997615814208984375 + + cloud_color + + 0.699999988079071044921875 + 0.39999997615814208984375 + 0.2999999821186065673828125 + 0.699999988079071044921875 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.04999999701976776123046875 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0 + 1 + + cloud_scale + + 0.07000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.1399993896484375 + 10.0109996795654296875 + + cloud_shadow + + 0.5 + 0 + 0 + 1 + + density_multiplier + + 4.999999873689375817775726e-05 + 0 + 0 + 1 + + distance_multiplier + + 10 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 20 + 0.001000000047497451305389404 + -1.25 + 1 + + haze_density + + 2 + 0 + 0 + 1 + + haze_horizon + + 0.04999999701976776123046875 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + -0 + 0.3090172111988067626953125 + 0.951056420803070068359375 + 1 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 10 + star_brightness + 0.5 + sun_angle + 3.4557521343231201171875 + sunlight_color + + 0.1799999922513961791992188 + 0.1799999922513961791992188 + 0.1799999922513961791992188 + 0.1799999922513961791992188 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20Cloudy.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20Cloudy.xml new file mode 100644 index 0000000000..92c786b825 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20Cloudy.xml @@ -0,0 +1,106 @@ + + + ambient + + 0.04499999806284904479980469 + 0.06749998778104782104492188 + 0.08999999612569808959960938 + 0.02999999932944774627685547 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0.5 + 0.5 + 0.5 + 0.25 + + cloud_color + + 0.1400000005960464477539063 + 0.1400000005960464477539063 + 0.1400000005960464477539063 + 0.1400000005960464477539063 + + cloud_pos_density1 + + 1 + 1 + 0.25 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 1 + 0 + 1 + + cloud_scale + 0.2000000029802322387695313 + cloud_scroll_rate + + 10.3999996185302734375 + 10 + + cloud_shadow + 0.599999964237213134765625 + density_multiplier + 4.999999873689375817775726e-05 + distance_multiplier + 7 + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.75 + 0 + 0 + 1 + + glow + + 10 + 0.001000000047497451305389404 + -0.449999988079071044921875 + 1 + + haze_density + 4 + haze_horizon + 0 + lightnorm + + 0 + 0 + -1 + 0 + + max_y + 1 + preset_num + 22 + star_brightness + 0 + sun_angle + 3.1415927410125732421875 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20Rainy.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20Rainy.xml new file mode 100644 index 0000000000..522c661095 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night%20Rainy.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0.1999999731779098510742188 + 0.1999999731779098510742188 + 0.1999999731779098510742188 + 0.0999999940395355224609375 + + cloud_color + + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + + cloud_pos_density1 + + 1 + 1 + 0.2999999821186065673828125 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 1 + 0 + 1 + + cloud_scale + + 0.07000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 11 + 10 + + cloud_shadow + + 0.66999995708465576171875 + 0 + 0 + 1 + + density_multiplier + + 0.0008999999845400452613830566 + 0 + 0 + 1 + + distance_multiplier + + 32.200000762939453125 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.39999997615814208984375 + 0 + 0 + 1 + + glow + + 0.200002193450927734375 + 0.001000000047497451305389404 + -0.2499999850988388061523438 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0.0999999940395355224609375 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.876306593418121337890625 + -0.4817537963390350341796875 + 0 + + max_y + + 314 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.0734512805938720703125 + sunlight_color + + 0.08999998867511749267578125 + 0.1799999773502349853515625 + 0.269999980926513671875 + 0.08999999612569808959960938 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night.xml new file mode 100644 index 0000000000..a1be61d2f9 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Night.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0.1499999910593032836914063 + 0.4500000178813934326171875 + 0.1499999910593032836914063 + + blue_density + + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.39999997615814208984375 + 0.199999988079071044921875 + + blue_horizon + + 0.4000000059604644775390625 + 0.599999725818634033203125 + 0.800000011920928955078125 + 0.39999997615814208984375 + + cloud_color + + 0.329999983310699462890625 + 0.329999983310699462890625 + 0.329999983310699462890625 + 0.329999983310699462890625 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.0999999940395355224609375 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0 + 1 + + cloud_scale + + 0.07000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.1399993896484375 + 10.0109996795654296875 + + cloud_shadow + + 0.39999997615814208984375 + 0 + 0 + 1 + + density_multiplier + + 4.999999873689375817775726e-05 + 0 + 0 + 1 + + distance_multiplier + + 10 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 20 + 0.001000000047497451305389404 + -1.25 + 1 + + haze_density + + 2 + 0 + 0 + 1 + + haze_horizon + + 0.04999999701976776123046875 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + -0 + 0.3090172111988067626953125 + 0.951056420803070068359375 + 1 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 10 + star_brightness + 0.5 + sun_angle + 3.4557521343231201171875 + sunlight_color + + 0.08999999612569808959960938 + 0.1799999922513961791992188 + 0.2999999821186065673828125 + 0.0999999940395355224609375 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Studio%201.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Studio%201.xml new file mode 100644 index 0000000000..b299d5c02b --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Studio%201.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.599999964237213134765625 + 0.599999964237213134765625 + 0.599999964237213134765625 + 0.199999988079071044921875 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0.599999964237213134765625 + 0.599999964237213134765625 + 0.599999964237213134765625 + 0.2999999821186065673828125 + + cloud_color + + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + + cloud_pos_density1 + + 1 + 1 + 0.25 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 1 + 0 + 1 + + cloud_scale + + 0.07000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.3999996185302734375 + 10 + + cloud_shadow + + 0.61000001430511474609375 + 0 + 0 + 1 + + density_multiplier + + 9.999999747378751635551453e-05 + 0 + 0 + 1 + + distance_multiplier + + 5 + 0 + 0 + 1 + + east_angle + 1.06814157962799072265625 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 0.200002193450927734375 + 0.001000000047497451305389404 + -0.199999988079071044921875 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.2099999934434890747070313 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0.38304769992828369140625 + 0.89940512180328369140625 + -0.2105822265148162841796875 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.0231859683990478515625 + sunlight_color + + 1.5 + 1.5 + 1.5 + 0.5 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Studio%20Spotlight.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Studio%20Spotlight.xml new file mode 100644 index 0000000000..7e919afff1 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Studio%20Spotlight.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + 0.2999999821186065673828125 + + cloud_pos_density1 + + 1 + 1 + 0.25 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 1 + 0 + 1 + + cloud_scale + + 0.07000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.3999996185302734375 + 10 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 0.200002193450927734375 + 0.001000000047497451305389404 + -0.199999988079071044921875 + 1 + + haze_density + + 1 + 0 + 0 + 1 + + haze_horizon + + 0.2099999934434890747070313 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.587785184383392333984375 + -0.80901706218719482421875 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.51327419281005859375 + sunlight_color + + 2.009999752044677734375 + 2.009999752044677734375 + 2.009999752044677734375 + 0.66999995708465576171875 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Sunrise.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Sunrise.xml new file mode 100644 index 0000000000..1145640848 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Sunrise.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0.449999988079071044921875 + 0.89999997615814208984375 + 0.2999999821186065673828125 + + blue_density + + 0 + 0.2999999821186065673828125 + 0.39999997615814208984375 + 0.39999997615814208984375 + + blue_horizon + + 0 + 0.39999997615814208984375 + 0.7999999523162841796875 + 0.7999999523162841796875 + + cloud_color + + 0.25 + 0.25 + 0.25 + 0.25 + + cloud_pos_density1 + + 1 + 1 + 0.189999997615814208984375 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 0 + 0.04999999701976776123046875 + 1 + + cloud_scale + + 0.07000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.19999980926513671875 + 10.0109996795654296875 + + cloud_shadow + + 0.5 + 0 + 0 + 1 + + density_multiplier + + 9.999999747378751635551453e-05 + 0 + 0 + 1 + + distance_multiplier + + 6 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.5 + 0 + 0 + 1 + + glow + + 38 + 0.001000000047497451305389404 + -0.2499999850988388061523438 + 1 + + haze_density + + 0.199999988079071044921875 + 0 + 0 + 1 + + haze_horizon + + 0.5 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + -0 + 0.309017002582550048828125 + 0.951056540012359619140625 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.31415927410125732421875 + sunlight_color + + 2.9999997615814208984375 + 1.19999992847442626953125 + 0.449999988079071044921875 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Sunset.xml b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Sunset.xml new file mode 100644 index 0000000000..3fe84a5050 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/%5BPyFX%5D%20Sunset.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0.269999980926513671875 + 0.4500000178813934326171875 + 0.1499999910593032836914063 + + blue_density + + 0.0999999940395355224609375 + 0.0999999940395355224609375 + 0.0999999940395355224609375 + 0.04999999701976776123046875 + + blue_horizon + + 0 + 0.199999988079071044921875 + 0.5 + 0.5 + + cloud_color + + 0 + 0.02999999932944774627685547 + 0.05999999865889549255371094 + 0.05999999865889549255371094 + + cloud_pos_density1 + + 1 + 1 + 0.1199999973177909851074219 + 1 + + cloud_pos_density2 + + 1.6884100437164306640625 + 0 + 0.04999999701976776123046875 + 1 + + cloud_scale + + 0.07000000029802322387695313 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.19999980926513671875 + 10.0109996795654296875 + + cloud_shadow + + 0.5 + 0 + 0 + 1 + + density_multiplier + + 9.999999747378751635551453e-05 + 0 + 0 + 1 + + distance_multiplier + + 6 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 10 + 0.001000000047497451305389404 + -0.4999999701976776123046875 + 1 + + haze_density + + 0.75 + 0 + 0 + 1 + + haze_horizon + + 0.199999988079071044921875 + 0.1991560012102127075195313 + 0.1991560012102127075195313 + 1 + + lightnorm + + 0 + 0.1253329664468765258789063 + -0.992114722728729248046875 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.66999995708465576171875 + sun_angle + 3.01592922210693359375 + sunlight_color + + 3 + 1.19999992847442626953125 + 0.2999999821186065673828125 + 3 + + + diff --git a/indra/newview/app_settings/windlight/skies/AnaLu%20%252Astudio%252A%205.xml b/indra/newview/app_settings/windlight/skies/AnaLu%20%252Astudio%252A%205.xml deleted file mode 100644 index b7c6d047f6..0000000000 --- a/indra/newview/app_settings/windlight/skies/AnaLu%20%252Astudio%252A%205.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - ambient - - 2.0099997520446777 - 1.9199999570846558 - 1.8899999856948853 - 2.0099997520446777 - - blue_density - - 0.63999998569488525 - 1.1799999475479126 - 2 - 2 - - blue_horizon - - 0.23999999463558197 - 0.23999999463558197 - 0.31999999284744263 - 0.31999999284744263 - - cloud_color - - 0.39050509865536398 - 0.39050509865536398 - 0.39050509865536398 - 0.39050509865536398 - - cloud_pos_density1 - - 1.6884100437164307 - 0.52609699964523315 - 1 - 1 - - cloud_pos_density2 - - 1.6884100437164307 - 0.52609699964523315 - 0.125 - 1 - - cloud_scale - - 0.41999998254906856 - 0 - 0 - 1 - - cloud_scroll_rate - - 10.199999735331062 - 10.010999579794088 - - cloud_shadow - - 0.12999999523162842 - 0 - 0 - 1 - - density_multiplier - - 0.00017999998391111764 - 0 - 0 - 1 - - distance_multiplier - - 2 - 0 - 0 - 1 - - east_angle - 0 - enable_cloud_scroll - - 1 - 1 - - gamma - - 1.1499999761581421 - 0 - 0 - 1 - - glow - - 4.9999998807907104 - 0.0010000000478643939 - -0.47999998436731417 - 1 - - haze_density - - 0.64999997615814209 - 0 - 0 - 1 - - haze_horizon - - 0.08999999612569809 - 0.19915600121021271 - 0.19915600121021271 - 1 - - lightnorm - - 0 - 0 - 1 - 0 - - max_y - - 188 - 0 - 0 - 1 - - preset_num - 22 - star_brightness - 0 - sun_angle - 0 - sunlight_color - - 2.5799999237060547 - 2.5799999237060547 - 2.5799999237060547 - 2.5799999237060547 - - - diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Afternoon.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Afternoon.xml new file mode 100644 index 0000000000..f454c065ed --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Afternoon.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.77999997138977051 + 0.77999997138977051 + 0.77999997138977051 + 0.25999999046325684 + + blue_density + + 0 + 2 + 2 + 2 + + blue_horizon + + 0.2800000011920929 + 0.44679245352745056 + 0.56000000238418579 + 0.56000000238418579 + + cloud_color + + 0.14424242079257965 + 0.14424242079257965 + 0.17000000178813934 + 0.17000000178813934 + + cloud_pos_density1 + + 1 + 1 + 0.76999998092651367 + 1 + + cloud_pos_density2 + + 1 + 1 + 0.08999999612569809 + 1 + + cloud_scale + + 0.14000000059604645 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.949999809265137 + 10.659999847412109 + + cloud_shadow + + 0.25 + 0 + 0 + 1 + + density_multiplier + + 2.9999999242136255e-005 + 0 + 0 + 1 + + distance_multiplier + + 2 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.5 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 2 + 0 + 0 + 1 + + haze_horizon + + 0.23999999463558197 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 1 + -4.3711388286737929e-008 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0.22999998927116394 + sun_angle + 1.5707963705062866 + sunlight_color + + 0.29999998211860657 + 0.29999998211860657 + 0.14999999105930328 + 0.099999994039535522 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Dawn.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Dawn.xml new file mode 100644 index 0000000000..e04ce021c0 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Dawn.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.44999998807907104 + 0.44999998807907104 + 0.44999998807907104 + 0.14999999105930328 + + blue_density + + 0.19999998807907104 + 1 + 2 + 2 + + blue_horizon + + 1.8600000143051147 + 0.44679245352745056 + 0.3139621913433075 + 1.8600000143051147 + + cloud_color + + 0.14000000059604645 + 0.070000000298023224 + 0 + 0.14000000059604645 + + cloud_pos_density1 + + 1 + 1 + 1 + 1 + + cloud_pos_density2 + + 1 + 1 + 0.08999999612569809 + 1 + + cloud_scale + + 0.14000000059604645 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.949999809265137 + 10.659999847412109 + + cloud_shadow + + 0.19999998807907104 + 0 + 0 + 1 + + density_multiplier + + 7.9999997979030013e-005 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.5 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 1.5699999332427979 + 0 + 0 + 1 + + haze_horizon + + 0.23999999463558197 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.32094338536262512 + -0.94709837436676025 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0.22999998927116394 + sun_angle + 2.8148672580718994 + sunlight_color + + 0.08999999612569809 + 0.08999999612569809 + 0.044999998062849045 + 0.029999999329447746 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Day%20Mood.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Day%20Mood.xml new file mode 100644 index 0000000000..6aee8d6143 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Day%20Mood.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.44999998807907104 + 0.44999998807907104 + 0.44999998807907104 + 0.14999999105930328 + + blue_density + + 0.23999999463558197 + 1 + 2 + 2 + + blue_horizon + + 0.63999998569488525 + 0.44679245352745056 + 0.3139621913433075 + 0.31999999284744263 + + cloud_color + + 0.14000000059604645 + 0.070000000298023224 + 0 + 0.14000000059604645 + + cloud_pos_density1 + + 1 + 1 + 1 + 1 + + cloud_pos_density2 + + 1 + 1 + 0.08999999612569809 + 1 + + cloud_scale + + 0.14000000059604645 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.949999809265137 + 10.659999847412109 + + cloud_shadow + + 0.17999999225139618 + 0 + 0 + 1 + + density_multiplier + + 2.9999999242136255e-005 + 0 + 0 + 1 + + distance_multiplier + + 2 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.5 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 2 + 0 + 0 + 1 + + haze_horizon + + 0.23999999463558197 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.62769138813018799 + 0.77846229076385498 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0.22999998927116394 + sun_angle + 0.67858403921127319 + sunlight_color + + 0.08999999612569809 + 0.08999999612569809 + 0.044999998062849045 + 0.029999999329447746 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Day%20Mood2.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Day%20Mood2.xml new file mode 100644 index 0000000000..89ab499a32 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Day%20Mood2.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.44999998807907104 + 0.44999998807907104 + 0.44999998807907104 + 0.14999999105930328 + + blue_density + + 0.23999999463558197 + 1 + 2 + 2 + + blue_horizon + + 0.63999998569488525 + 0.44679245352745056 + 0.3139621913433075 + 0.31999999284744263 + + cloud_color + + 0.14000000059604645 + 0.070000000298023224 + 0 + 0.14000000059604645 + + cloud_pos_density1 + + 1 + 1 + 0.45999997854232788 + 1 + + cloud_pos_density2 + + 1 + 1 + 0.08999999612569809 + 1 + + cloud_scale + + 0.14000000059604645 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.949999809265137 + 10.659999847412109 + + cloud_shadow + + 0.25 + 0 + 0 + 1 + + density_multiplier + + 2.9999999242136255e-005 + 0 + 0 + 1 + + distance_multiplier + + 2 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.5 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 2 + 0 + 0 + 1 + + haze_horizon + + 0.23999999463558197 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.53051102161407471 + -0.84767806529998779 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0.22999998927116394 + sun_angle + 2.5823893547058105 + sunlight_color + + 0.08999999612569809 + 0.08999999612569809 + 0.044999998062849045 + 0.029999999329447746 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Fog.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Fog.xml new file mode 100644 index 0000000000..8036eaf893 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Fog.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.17999999225139618 + 0.23999999463558197 + 0.31000000238418579 + 0.31000000238418579 + + blue_density + + 1 + 0.81000000238418579 + 0.62000000476837158 + 1 + + blue_horizon + + 0 + 0.2199999988079071 + 0.45999997854232788 + 0.45999997854232788 + + cloud_color + + 0.69999998807907104 + 0.69999998807907104 + 0.69999998807907104 + 0.69999998807907104 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.53999996185302734 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.29999998211860657 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.39999997615814209 + 0 + 0 + 1 + + density_multiplier + + 0.00075000000651925802 + 0 + 0 + 1 + + distance_multiplier + + 30.200000762939453 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.1800000667572021 + 0 + 0 + 1 + + glow + + 3.7999999523162842 + 0.0010000000474974513 + -0.5 + 1 + + haze_density + + 2.7200000286102295 + 0 + 0 + 1 + + haze_horizon + + 0.63999998569488525 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.99361127614974976 + -0.11285652220249176 + 0 + + max_y + + 3447 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 1.6838937997817993 + sunlight_color + + 1.1399999856948853 + 1.1399999856948853 + 1.1399999856948853 + 0.37999999523162842 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Ghost.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Ghost.xml new file mode 100644 index 0000000000..ea3ce7f4e3 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Ghost.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.32999998331069946 + 0.32999998331069946 + 0.32999998331069946 + 0.10999999940395355 + + blue_density + + 0.079873383045196533 + 0.21999761462211609 + 0.43999999761581421 + 0.2199999988079071 + + blue_horizon + + 0.21535232663154602 + 0.42697387933731079 + 0.5 + 0.25 + + cloud_color + + 0.2199999988079071 + 0.2199999988079071 + 0.2199999988079071 + 0.2199999988079071 + + cloud_pos_density1 + + 1 + 1 + 0.070000000298023224 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.14000000059604645 + 0 + 0 + 1 + + cloud_scroll_rate + + 11.539999961853027 + 10.01099967956543 + + cloud_shadow + + 0.44999998807907104 + 0 + 0 + 1 + + density_multiplier + + 0.00042999998549930751 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.51999998092651367 + 1 + + haze_density + + 0.75 + 0 + 0 + 1 + + haze_horizon + + 0.18000000715255737 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.99992102384567261 + -0.012566247954964638 + 1 + + max_y + + 718.70001220703125 + 0 + 0 + 1 + + preset_num + 23 + star_brightness + 2 + sun_angle + 4.7249555587768555 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Morning.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Morning.xml new file mode 100644 index 0000000000..a7f4e06cf5 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Morning.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.69999998807907104 + 0.57749998569488525 + 0.4987500011920929 + 0.69999998807907104 + + blue_density + + 0.45999997854232788 + 0.77999997138977051 + 1 + 1 + + blue_horizon + + 0.08999999612569809 + 0.039999999105930328 + 0 + 0.099999994039535522 + + cloud_color + + 0.50999999046325684 + 0.50999999046325684 + 0.50999999046325684 + 1 + + cloud_pos_density1 + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.37000000476837158 + 0 + 0 + 1 + + density_multiplier + + 7.0000001869630069e-005 + 0 + 0 + 1 + + distance_multiplier + + 15.5 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.6100000143051147 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.33000001311302185 + 1 + + haze_density + + 3.5099999904632568 + 0 + 0 + 1 + + haze_horizon + + 0.26999998092651367 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.062790460884571075 + -0.99802672863006592 + 0 + + max_y + + 2842 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 3.0787608623504639 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Morning2.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Morning2.xml new file mode 100644 index 0000000000..6d92b7628f --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Morning2.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.69999997394426039 + 0.57749997886164373 + 0.49874999905271622 + 0.69999995555196648 + + blue_density + + 0.45999996583802716 + 0.77999998620579447 + 1.0000000630106456 + 1.0000000630106456 + + blue_horizon + + 0.09000002999817136 + 0.040000024113538313 + 1.9248282967510022e-008 + 0.10000000769751693 + + cloud_color + + 0.50999996864795882 + 0.5099999643564237 + 0.50999996006488857 + 0.99999994897842548 + + cloud_pos_density1 + + 0.5 + 0.5 + 1.0000000017030004 + 1.0000000017030004 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.12499999806710704 + 1.0000000017030004 + + cloud_scale + + 0.41999997043609838 + 0 + 0 + 1.0000000017030004 + + cloud_scroll_rate + + 10.499400184360695 + 10.010999736402823 + + cloud_shadow + + 0.37000000476837158 + 0 + 0 + 1.0000000017030004 + + density_multiplier + + 6.9999999536534113e-005 + 0 + 0 + 1.0000000017030004 + + distance_multiplier + + 15.499999198743296 + 0 + 0 + 1.0000000017030004 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.6100000716107488 + 0 + 0 + 1.0000000017030004 + + glow + + 4.9999997142382933 + 0.0010000000492004502 + -0.33000003022807256 + 1.0000000017030004 + + haze_density + + 3.5099999038662446 + 0 + 0 + 1.0000000017030004 + + haze_horizon + + 0.26999997954709531 + 0.19915600154937518 + 0.19915600154937518 + 1.0000000017030004 + + lightnorm + + 0 + 0.069060027599334717 + 0.99761247634887695 + 0 + + max_y + + 2842.0000758341921 + 0 + 0 + 1.0000000017030004 + + preset_num + 21 + star_brightness + 1.4100757894652816e-008 + sun_angle + 0.069115042686462402 + sunlight_color + + 2.9999998267037533 + 2.9999998267037533 + 2.9999998239449095 + 0.99999994223458455 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%2010am.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%2010am.xml new file mode 100644 index 0000000000..48f1ef09a1 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%2010am.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.77999997138977051 + 0.77999997138977051 + 0.77999997138977051 + 0.25999999046325684 + + blue_density + + 0 + 2 + 2 + 2 + + blue_horizon + + 0.2800000011920929 + 0.44679245352745056 + 0.56000000238418579 + 0.56000000238418579 + + cloud_color + + 0.12999999523162842 + 0.14424242079257965 + 0.11999999731779099 + 0.14999999105930328 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.099999994039535522 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 2.9999999242136255e-005 + 0 + 0 + 1 + + distance_multiplier + + 2 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 2.5 + 0 + 0 + 1 + + glow + + 1.1999988555908203 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 2 + 0 + 0 + 1 + + haze_horizon + + 0.23999999463558197 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.49818512797355652 + 0.86707067489624023 + 0 + + max_y + + 1400 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0.22999998927116394 + sun_angle + 0.52150440216064453 + sunlight_color + + 0.29999998211860657 + 0.29999998211860657 + 0.14999999105930328 + 0.099999994039535522 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%204%3A30am.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%204%3A30am.xml new file mode 100644 index 0000000000..9746250a36 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%204%3A30am.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.84000003337860107 + 0.84000003337860107 + 0.84000003337860107 + 0.2800000011920929 + + blue_density + + 1.2600002288818359 + 2 + 2 + 1 + + blue_horizon + + 0 + 0.022568579763174057 + 0.039999999105930328 + 0.019999999552965164 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.099999994039535522 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.62000000476837158 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.29999998211860657 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -1.1000000238418579 + 1 + + haze_density + + 0.31999999284744263 + 0 + 0 + 1 + + haze_horizon + + 0.41999998688697815 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.36227512359619141 + -0.93207120895385742 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0.63999998569488525 + sun_angle + 2.7708849906921387 + sunlight_color + + 0.32999998331069946 + 0.83719938993453979 + 0.84000003337860107 + 0.2800000011920929 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%205am%20END.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%205am%20END.xml new file mode 100644 index 0000000000..3cfff6d793 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%205am%20END.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.84000003337860107 + 0.84000003337860107 + 0.84000003337860107 + 0.2800000011920929 + + blue_density + + 1.2600002288818359 + 2 + 2 + 1 + + blue_horizon + + 0 + 0.022568579763174057 + 0.039999999105930328 + 0.019999999552965164 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.099999994039535522 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.62000000476837158 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.29999998211860657 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -1.1000000238418579 + 1 + + haze_density + + 0.31999999284744263 + 0 + 0 + 1 + + haze_horizon + + 0.41999998688697815 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 1.7484555314695172e-007 + 1 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0.63999998569488525 + sun_angle + 6.2831854820251465 + sunlight_color + + 0.029999999329447746 + 0.83719938993453979 + 0.84000003337860107 + 0.2800000011920929 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%205am%20START.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%205am%20START.xml new file mode 100644 index 0000000000..44eb1a54a1 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%205am%20START.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.42000001668930054 + 0.42000001668930054 + 0.42000001668930054 + 0.14000000059604645 + + blue_density + + 1.2600002288818359 + 2 + 2 + 1 + + blue_horizon + + 0 + 0.022568579763174057 + 0.039999999105930328 + 0.019999999552965164 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.099999994039535522 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.62000000476837158 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.29999998211860657 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -1.1000000238418579 + 1 + + haze_density + + 0.31999999284744263 + 0 + 0 + 1 + + haze_horizon + + 0.41999998688697815 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0 + 1 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0.63999998569488525 + sun_angle + 0 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%205am.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%205am.xml new file mode 100644 index 0000000000..7a312df503 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%205am.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.84000003337860107 + 0.84000003337860107 + 0.84000003337860107 + 0.2800000011920929 + + blue_density + + 1.2600002288818359 + 2 + 2 + 1 + + blue_horizon + + 0 + 0.022568579763174057 + 0.039999999105930328 + 0.019999999552965164 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.099999994039535522 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.62000000476837158 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.29999998211860657 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -1.1000000238418579 + 1 + + haze_density + + 0.31999999284744263 + 0 + 0 + 1 + + haze_horizon + + 0.41999998688697815 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0 + -1 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0.63999998569488525 + sun_angle + 3.1415927410125732 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%207%3A30pm.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%207%3A30pm.xml new file mode 100644 index 0000000000..1d46458322 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%207%3A30pm.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.84000003337860107 + 0.84000003337860107 + 0.84000003337860107 + 0.2800000011920929 + + blue_density + + 1.2600002288818359 + 2 + 2 + 1 + + blue_horizon + + 0 + 0.022568579763174057 + 0.039999999105930328 + 0.019999999552965164 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.099999994039535522 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.62000000476837158 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.29999998211860657 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -1.1000000238418579 + 1 + + haze_density + + 0.31999999284744263 + 0 + 0 + 1 + + haze_horizon + + 0.41999998688697815 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.33873793482780457 + 0.94088077545166016 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0.63999998569488525 + sun_angle + 0.34557521343231201 + sunlight_color + + 0.32999998331069946 + 0.83719938993453979 + 0.84000003337860107 + 0.2800000011920929 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%208%3A30am.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%208%3A30am.xml new file mode 100644 index 0000000000..87d406bc0a --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%208%3A30am.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.22411763608017388 + 0.25058822535416658 + 0.19764705338022287 + 0.18941175678197075 + + blue_density + + 0.21314870774677197 + 1.011764702165828 + 1.0647058807138134 + 1.0647058807138134 + + blue_horizon + + 0.032941176733549904 + 0.61014069170411545 + 1.0541176513012718 + 1.0541176513012718 + + cloud_color + + 0.12999999523162842 + 0.14000000059604645 + 0.11999999731779099 + 0.14000000059604645 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.13529411745422026 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 2.9999999242136255e-005 + 0 + 0 + 1 + + distance_multiplier + + 1.1176470592617989 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 1.661764664224842 + 0 + 0 + 1 + + glow + + 0.31764675632995676 + 0.0010000000474974513 + -0.37941175534882965 + 1 + + haze_density + + 1.8764706009188119 + 0 + 0 + 1 + + haze_horizon + + 0.41647058541283888 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.53738623857498169 + 0.84333628416061401 + 0 + + max_y + + 1678.5294129177928 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0.02705882303416729 + sun_angle + 0.56733471155166626 + sunlight_color + + 0.4588235177625628 + 0.67058820565833765 + 0.38823530767332104 + 0.64705879520844012 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%208am.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%208am.xml new file mode 100644 index 0000000000..f30eb0d2d5 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%208am.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.77999997138977051 + 0.77999997138977051 + 0.77999997138977051 + 0.25999999046325684 + + blue_density + + 0 + 2 + 2 + 2 + + blue_horizon + + 0.2800000011920929 + 0.44679245352745056 + 0.56000000238418579 + 0.56000000238418579 + + cloud_color + + 0.12999999523162842 + 0.14424242079257965 + 0.11999999731779099 + 0.14999999105930328 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.099999994039535522 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 10 + 10 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 2.9999999242136255e-005 + 0 + 0 + 1 + + distance_multiplier + + 2 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 2.5 + 0 + 0 + 1 + + glow + + 1.1999988555908203 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 2 + 0 + 0 + 1 + + haze_horizon + + 0.23999999463558197 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.49818512797355652 + 0.86707067489624023 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0.22999998927116394 + sun_angle + 0.52150440216064453 + sunlight_color + + 0.29999998211860657 + 0.29999998211860657 + 0.14999999105930328 + 0.099999994039535522 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Dark%20START.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Dark%20START.xml new file mode 100644 index 0000000000..310d08424e --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Dark%20START.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1.2600002288818359 + 2 + 2 + 1 + + blue_horizon + + 0 + 0.022568579763174057 + 0.039999999105930328 + 0.019999999552965164 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.099999994039535522 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.62000000476837158 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.61000001430511475 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -1.1000000238418579 + 1 + + haze_density + + 0.31999999284744263 + 0 + 0 + 1 + + haze_horizon + + 0.41999998688697815 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0 + 1 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 2 + sun_angle + 0 + sunlight_color + + 0.029999999329447746 + 0.83719938993453979 + 0.84000003337860107 + 0.2800000011920929 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Midnight.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Midnight.xml new file mode 100644 index 0000000000..7802c595c7 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Midnight.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.84000003337860107 + 0.84000003337860107 + 0.84000003337860107 + 0.2800000011920929 + + blue_density + + 1.2600002288818359 + 2 + 2 + 1 + + blue_horizon + + 0 + 0.022568579763174057 + 0.039999999105930328 + 0.019999999552965164 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.099999994039535522 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.62000000476837158 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.29999998211860657 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -0.85000002384185791 + 1 + + haze_density + + 0.31999999284744263 + 0 + 0 + 1 + + haze_horizon + + 0.41999998688697815 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 1 + -4.3711388286737929e-008 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0.63999998569488525 + sun_angle + 1.5707963705062866 + sunlight_color + + 0.59999996423721313 + 0.83719938993453979 + 0.84000003337860107 + 0.2800000011920929 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Night.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Night.xml new file mode 100644 index 0000000000..60f35bad3d --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Night.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.84000003337860107 + 0.84000003337860107 + 0.84000003337860107 + 0.2800000011920929 + + blue_density + + 1.2600002288818359 + 2 + 2 + 1 + + blue_horizon + + 0 + 0.022568579763174057 + 0.039999999105930328 + 0.019999999552965164 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.099999994039535522 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.62000000476837158 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.29999998211860657 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -0.99999994039535522 + 1 + + haze_density + + 0.31999999284744263 + 0 + 0 + 1 + + haze_horizon + + 0.41999998688697815 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.43711560964584351 + -0.89940536022186279 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0.63999998569488525 + sun_angle + 2.6892035007476807 + sunlight_color + + 0.35999998450279236 + 0.83719938993453979 + 0.84000003337860107 + 0.2800000011920929 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Noon.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Noon.xml new file mode 100644 index 0000000000..8c3d29e3f4 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Noon.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.77999997138977051 + 0.77999997138977051 + 0.77999997138977051 + 0.25999999046325684 + + blue_density + + 0 + 2 + 2 + 2 + + blue_horizon + + 0.2800000011920929 + 0.44679245352745056 + 0.56000000238418579 + 0.56000000238418579 + + cloud_color + + 0.12999999523162842 + 0.14424242079257965 + 0.11999999731779099 + 0.14999999105930328 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 2.9999999242136255e-005 + 0 + 0 + 1 + + distance_multiplier + + 1.2000000476837158 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 2.5 + 0 + 0 + 1 + + glow + + 1.1999988555908203 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 2 + 0 + 0 + 1 + + haze_horizon + + 0.23999999463558197 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 1 + -4.3711388286737929e-008 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0.22999998927116394 + sun_angle + 1.5707963705062866 + sunlight_color + + 0.29999998211860657 + 0.29999998211860657 + 0.14999999105930328 + 0.099999994039535522 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20%2DA.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20%2DA.xml new file mode 100644 index 0000000000..2cceb65df7 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20%2DA.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.14999997615814209 + 0.17999999225139618 + 0 + 0.059999998658895493 + + blue_density + + 0.37999999523162842 + 0.45999997854232788 + 0.2199999988079071 + 0.45999997854232788 + + blue_horizon + + 0.14000000059604645 + 0 + 0 + 0.17999999225139618 + + cloud_color + + 1 + 0 + 0 + 1 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.12999999523162842 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -0.74999994039535522 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.43999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.031410761177539825 + 0.99950653314590454 + 0 + + max_y + + 1826 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 1.5 + sun_angle + 0.031415928155183792 + sunlight_color + + 2.1299998760223389 + 2.0448005199432373 + 1.0735198259353638 + 0.70999997854232788 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20A.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20A.xml new file mode 100644 index 0000000000..e4a260f7d7 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20A.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.14999997615814209 + 0.17999999225139618 + 0 + 0.059999998658895493 + + blue_density + + 0.2199999988079071 + 0.71999996900558472 + 0.93999999761581421 + 1 + + blue_horizon + + 0 + 0.6319204568862915 + 2 + 2 + + cloud_color + + 1 + 0 + 0 + 1 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.12999999523162842 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -0.74999994039535522 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.43999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.062790520489215851 + 0.99802672863006592 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 1 + sun_angle + 0.062831856310367584 + sunlight_color + + 2.1299998760223389 + 2.0448005199432373 + 1.0735198259353638 + 0.70999997854232788 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20B.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20B.xml new file mode 100644 index 0000000000..8cf2190c43 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20B.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.074999995529651642 + 0.08999999612569809 + 0 + 0.029999999329447746 + + blue_density + + 0.19191493093967438 + 0.62808448076248169 + 0.81999999284744263 + 0.40999999642372131 + + blue_horizon + + 2 + 0 + 2 + 2 + + cloud_color + + 0 + 0.021999998018145561 + 0.039999999105930328 + 0.039999999105930328 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14999999105930328 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.53999996185302734 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -0.69999998807907104 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.48999997973442078 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.069060027599334717 + 0.99761247634887695 + 0 + + max_y + + 1101 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0.5 + sun_angle + 0.069115042686462402 + sunlight_color + + 1.619999885559082 + 1.5551999807357788 + 0.81647992134094238 + 0.53999996185302734 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20C.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20C.xml new file mode 100644 index 0000000000..bde09ec69f --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20C.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.26999998092651367 + 0.14999999105930328 + 0 + 0.26999998092651367 + + blue_density + + 0.24156853556632996 + 0.71999996900558472 + 0.93999999761581421 + 0.93999999761581421 + + blue_horizon + + 0 + 0.6319204568862915 + 1.1200000047683716 + 1.1200000047683716 + + cloud_color + + 0.17999999225139618 + 0 + 0 + 0.17999999225139618 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 11.679999351501465 + 10 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.81000000238418579 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 1.8600000143051147 + 0 + 0 + 1 + + haze_horizon + + 0.43999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.075326807796955109 + 0.99715888500213623 + 0 + + max_y + + 1074 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 0.07539822906255722 + sunlight_color + + 0.75 + 0.62999999523162842 + 0.84000003337860107 + 0.84000003337860107 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20D.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20D.xml new file mode 100644 index 0000000000..9f990c4da7 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20D.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.26999998092651367 + 0.14999999105930328 + 0 + 0.26999998092651367 + + blue_density + + 0.24156853556632996 + 0.71999996900558472 + 0.93999999761581421 + 0.93999999761581421 + + blue_horizon + + 0 + 0.6319204568862915 + 1.1200000047683716 + 1.1200000047683716 + + cloud_color + + 0.18999999761581421 + 0 + 0 + 0.18999999761581421 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 11.679999351501465 + 10 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 1.3500000238418579 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 1.8600000143051147 + 0 + 0 + 1 + + haze_horizon + + 0.43999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.081590615212917328 + 0.99666595458984375 + 0 + + max_y + + 859 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 0.081681415438652039 + sunlight_color + + 0.75 + 0.62999999523162842 + 0.71999996900558472 + 0.75 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20E.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20E.xml new file mode 100644 index 0000000000..651d9e79f4 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20E.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.14999999105930328 + 0.17999999225139618 + 0 + 0.17999999225139618 + + blue_density + + 0.24156853556632996 + 0.71999996900558472 + 0.93999999761581421 + 0.93999999761581421 + + blue_horizon + + 0 + 0.6319204568862915 + 1.1200000047683716 + 1.1200000047683716 + + cloud_color + + 0.4699999988079071 + 0 + 0 + 0.4699999988079071 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 1.5399999618530273 + 0 + 0 + 1 + + glow + + 0.39999961853027344 + 0.0010000000474974513 + -0.49999997019767761 + 1 + + haze_density + + 1.8600000143051147 + 0 + 0 + 1 + + haze_horizon + + 0.43999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.087851203978061676 + 0.99613362550735474 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 0.087964601814746857 + sunlight_color + + 0.75 + 0.71999996900558472 + 0.37800011038780212 + 0.80999994277954102 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20F.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20F.xml new file mode 100644 index 0000000000..3efde332e8 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunrise%3A%20F.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.14999999105930328 + 0.17999999225139618 + 0.11999999731779099 + 0.17999999225139618 + + blue_density + + 0.24156853556632996 + 0.87999999523162842 + 0.93999999761581421 + 0.93999999761581421 + + blue_horizon + + 0 + 0.6319204568862915 + 1.1200000047683716 + 1.1200000047683716 + + cloud_color + + 0.28999999165534973 + 0.14000000059604645 + 0.11999999731779099 + 0.28999999165534973 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 1 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 2 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.34999999403953552 + 1 + + haze_density + + 1.8600000143051147 + 0 + 0 + 1 + + haze_horizon + + 0.43999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.42008578777313232 + 0.90748441219329834 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 0.43353983759880066 + sunlight_color + + 0.47999998927116394 + 0.71999996900558472 + 0.42000001668930054 + 0.71999996900558472 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20A.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20A.xml new file mode 100644 index 0000000000..6c14c1b947 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20A.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.14999999105930328 + 0.17999999225139618 + 0.11999999731779099 + 0.17999999225139618 + + blue_density + + 0.24156853556632996 + 0.87999999523162842 + 0.93999999761581421 + 0.93999999761581421 + + blue_horizon + + 0 + 0.6319204568862915 + 1.1200000047683716 + 1.1200000047683716 + + cloud_color + + 0.28999999165534973 + 0.14000000059604645 + 0.11999999731779099 + 0.28999999165534973 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 1 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 2 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.34999999403953552 + 1 + + haze_density + + 1.8600000143051147 + 0 + 0 + 1 + + haze_horizon + + 0.43999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.36227512359619141 + -0.93207120895385742 + 0 + + max_y + + 3007 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 2.7708849906921387 + sunlight_color + + 0.47999998927116394 + 0.71999996900558472 + 0.42000001668930054 + 0.71999996900558472 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20B.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20B.xml new file mode 100644 index 0000000000..b3d7cbc364 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20B.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.29999998211860657 + 0.17999999225139618 + 0 + 0.099999994039535522 + + blue_density + + 0.14000000059604645 + 0.56000000238418579 + 0 + 0.56000000238418579 + + blue_horizon + + 0.47999998927116394 + 0.27082312107086182 + 0 + 0.23999999463558197 + + cloud_color + + 0.41999998688697815 + 0.20999999344348907 + 0 + 0.41999998688697815 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00045999998110346496 + 0 + 0 + 1 + + distance_multiplier + + 1.3999999761581421 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 1.1499999761581421 + 0 + 0 + 1 + + glow + + 0.39999961853027344 + 0.0010000000474974513 + -0.39999997615814209 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.17999999225139618 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.14401055872440338 + -0.98957616090774536 + 0 + + max_y + + 805 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 2.997079610824585 + sunlight_color + + 3 + 2.7300000190734863 + 0.41666662693023682 + 3 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20C.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20C.xml new file mode 100644 index 0000000000..dbd79a4cb2 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20C.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.14999997615814209 + 0.17999999225139618 + 0 + 0.059999998658895493 + + blue_density + + 0.2199999988079071 + 0.71999996900558472 + 0.93999999761581421 + 1 + + blue_horizon + + 0 + 0.42970588803291321 + 1.3600000143051147 + 0.68000000715255737 + + cloud_color + + 1 + 0 + 0 + 1 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.34000000357627869 + 0 + 0 + 1 + + glow + + 10.199999809265137 + 0.0010000000474974513 + -0.74999994039535522 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.43999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.062790460884571075 + -0.99802672863006592 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 1 + sun_angle + 3.0787608623504639 + sunlight_color + + 2.1299998760223389 + 2.0448005199432373 + 1.0735198259353638 + 0.70999997854232788 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20D.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20D.xml new file mode 100644 index 0000000000..061c1c0a17 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Natural%20Sunset%3A%20D.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.14999997615814209 + 0.17999999225139618 + 0 + 0.059999998658895493 + + blue_density + + 0.37999999523162842 + 0.45999997854232788 + 0.2199999988079071 + 0.45999997854232788 + + blue_horizon + + 0.14000000059604645 + 0 + 0 + 0.17999999225139618 + + cloud_color + + 1 + 0 + 0 + 1 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 0.12999999523162842 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -0.74999994039535522 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.43999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.031410444527864456 + -0.99950659275054932 + 0 + + max_y + + 1826 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 1.5 + sun_angle + 3.1101770401000977 + sunlight_color + + 2.1299998760223389 + 2.0448005199432373 + 1.0735198259353638 + 0.70999997854232788 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Nighty%20Fog.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Nighty%20Fog.xml new file mode 100644 index 0000000000..a197c83ead --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Nighty%20Fog.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.079999998211860657 + 0.079999998211860657 + 0.079999998211860657 + 0.079999998211860657 + + blue_density + + 1 + 0.81000000238418579 + 0.62000000476837158 + 1 + + blue_horizon + + 0 + 0.2199999988079071 + 0.45999997854232788 + 0.45999997854232788 + + cloud_color + + 0.69999998807907104 + 0.69999998807907104 + 0.69999998807907104 + 0.69999998807907104 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.53999996185302734 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.29999998211860657 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.39999997615814209 + 0 + 0 + 1 + + density_multiplier + + 0.00075000000651925802 + 0 + 0 + 1 + + distance_multiplier + + 30.200000762939453 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.1800000667572021 + 0 + 0 + 1 + + glow + + 4.2000007629394531 + 0.0010000000474974513 + -0.64999997615814209 + 1 + + haze_density + + 2.7200000286102295 + 0 + 0 + 1 + + haze_horizon + + 0.19999998807907104 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.99361127614974976 + -0.11285652220249176 + 0 + + max_y + + 3447 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 1.6838937997817993 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20O%2D6am.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20O%2D6am.xml new file mode 100644 index 0000000000..59c4852168 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20O%2D6am.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.33054998638431243 + 0.33054998638431243 + 0.33054998638431243 + 0.11018333371629296 + + blue_density + + 0.080423966373246003 + 0.2235726453915845 + 0.44715003729959335 + 0.22815837741444511 + + blue_horizon + + 0.22289033702560346 + 0.427064714973028 + 0.49914732197913736 + 0.25737920767664946 + + cloud_color + + 0.21963333011493091 + 0.21931249500003958 + 0.21899165988514824 + 0.21963333011493091 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.12483958242547999 + 1 + + cloud_scale + + 0.14000000059604645 + 0 + 0 + 1 + + cloud_scroll_rate + + 11.53729577948252 + 10.013974280172988 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00042839580998887961 + 0 + 0 + 1 + + distance_multiplier + + 8.5212110501925054 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.0068750381469727 + 0 + 0 + 1 + + glow + + 4.9779998770554812 + 0.0010000000474974513 + -0.52036664955119249 + 1 + + haze_density + + 0.75375835388103951 + 0 + 0 + 1 + + haze_horizon + + 0.18027500862106649 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.9999927282333374 + -0.0038118390366435051 + 1 + + max_y + + 733.73938726552296 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 1.9918874502182007 + sun_angle + 4.7162008285522461 + sunlight_color + + 0.00041250227106104376 + 0.00041250227106104376 + 0.00020625113553052188 + 0.00013750075986607158 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Rise.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Rise.xml new file mode 100644 index 0000000000..105ab5d5cf --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Rise.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.38999998569488525 + 0.19687503576278687 + 0.11999999731779099 + 0.38999998569488525 + + blue_density + + 0.0072000003419816494 + 0.029999999329447746 + 0.059999998658895493 + 0.029999999329447746 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.14000000059604645 + 0.070000000298023224 + 0 + 0.14000000059604645 + + cloud_pos_density1 + + 1 + 1 + 0.2800000011920929 + 1 + + cloud_pos_density2 + + 1 + 1 + 0.08999999612569809 + 1 + + cloud_scale + + 0.14000000059604645 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.949999809265137 + 10.659999847412109 + + cloud_shadow + + 0.22999998927116394 + 0 + 0 + 1 + + density_multiplier + + 0.00025000001187436283 + 0 + 0 + 1 + + distance_multiplier + + 57.400001525878906 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.5 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 0.34999999403953552 + 0 + 0 + 1 + + haze_horizon + + 0.28999999165534973 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.29704159498214722 + 0.95486456155776978 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0.22999998927116394 + sun_angle + 0.30159291625022888 + sunlight_color + + 0.059999998658895493 + 0.029999999329447746 + 0.011249998584389687 + 0.059999998658895493 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Rosy%20Morning.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Rosy%20Morning.xml new file mode 100644 index 0000000000..651d9e79f4 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Rosy%20Morning.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.14999999105930328 + 0.17999999225139618 + 0 + 0.17999999225139618 + + blue_density + + 0.24156853556632996 + 0.71999996900558472 + 0.93999999761581421 + 0.93999999761581421 + + blue_horizon + + 0 + 0.6319204568862915 + 1.1200000047683716 + 1.1200000047683716 + + cloud_color + + 0.4699999988079071 + 0 + 0 + 0.4699999988079071 + + cloud_pos_density1 + + 0.53999996185302734 + 0.50999999046325684 + 0.14000000059604645 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.50999999046325684 + 1 + + cloud_scale + + 0.62000000476837158 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0.70999997854232788 + 0 + 0 + 1 + + density_multiplier + + 0.00032999998074956238 + 0 + 0 + 1 + + distance_multiplier + + 8.1000003814697266 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 1.5399999618530273 + 0 + 0 + 1 + + glow + + 0.39999961853027344 + 0.0010000000474974513 + -0.49999997019767761 + 1 + + haze_density + + 1.8600000143051147 + 0 + 0 + 1 + + haze_horizon + + 0.43999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0 + 0.087851203978061676 + 0.99613362550735474 + 0 + + max_y + + 1369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 0.087964601814746857 + sunlight_color + + 0.75 + 0.71999996900558472 + 0.37800011038780212 + 0.80999994277954102 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Sweet%20Dawn.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Sweet%20Dawn.xml new file mode 100644 index 0000000000..db8af4aac8 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Sweet%20Dawn.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.19999998807907104 + 0.17128434777259827 + 0.11999999731779099 + 0.19999998807907104 + + blue_density + + 0.35999998450279236 + 0.0099999997764825821 + 1 + 1 + + blue_horizon + + 0.37000000476837158 + 0.31000000238418579 + 0 + 0.37000000476837158 + + cloud_color + + 0.37000000476837158 + 0.2800000011920929 + 0.17999999225139618 + 0.43999999761581421 + + cloud_pos_density1 + + 0.90999996662139893 + 0.81000000238418579 + 0.059999998658895493 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.38999998569488525 + 0 + 0 + 1 + + cloud_scroll_rate + + 11.170000076293945 + 8.4099998474121094 + + cloud_shadow + + 0.68999999761581421 + 0 + 0 + 1 + + density_multiplier + + 0.00014000000373926014 + 0 + 0 + 1 + + distance_multiplier + + 7.4000000953674316 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 4.0999999046325684 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.94999998807907104 + 1 + + haze_density + + 0.68999999761581421 + 0 + 0 + 1 + + haze_horizon + + 0.099999994039535522 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.7459409236907959 + -0.66601210832595825 + 0 + + max_y + + 3158 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 2.2996461391448975 + sunlight_color + + 0.17999999225139618 + 0.14000000059604645 + 0.11999999731779099 + 0.17999999225139618 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Sweet%20Morning.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Sweet%20Morning.xml new file mode 100644 index 0000000000..42761fe052 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Sweet%20Morning.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.14117646217346191 + 0.17128434777259827 + 0.19999998807907104 + 0.19999998807907104 + + blue_density + + 0.17000000178813934 + 0.35999998450279236 + 1 + 1 + + blue_horizon + + 0 + 0.37000000476837158 + 0.29089650511741638 + 0.37000000476837158 + + cloud_color + + 0.12210001051425934 + 0.27379998564720154 + 0.37000000476837158 + 0.37000000476837158 + + cloud_pos_density1 + + 0.90999996662139893 + 0.81000000238418579 + 0.059999998658895493 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.38999998569488525 + 0 + 0 + 1 + + cloud_scroll_rate + + 11.170000076293945 + 8.4099998474121094 + + cloud_shadow + + 0.68999999761581421 + 0 + 0 + 1 + + density_multiplier + + 0.00014000000373926014 + 0 + 0 + 1 + + distance_multiplier + + 7.4000000953674316 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 4.0999999046325684 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.94999998807907104 + 1 + + haze_density + + 0.68999999761581421 + 0 + 0 + 1 + + haze_horizon + + 0.099999994039535522 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.7459409236907959 + -0.66601210832595825 + 0 + + max_y + + 3158 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 2.2996461391448975 + sunlight_color + + 0.17999999225139618 + 0.14000000059604645 + 0.12000000476837158 + 0.059999998658895493 + + + diff --git a/indra/newview/app_settings/windlight/skies/Nacon%27s%20Test.xml b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Test.xml new file mode 100644 index 0000000000..c5a355777c --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Nacon%27s%20Test.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.14117646217346191 + 0.17128434777259827 + 0.19999998807907104 + 0.19999998807907104 + + blue_density + + 0.17000000178813934 + 0.35999998450279236 + 1 + 1 + + blue_horizon + + 0 + 0.37000000476837158 + 0.29089650511741638 + 0.37000000476837158 + + cloud_color + + 0.12210001051425934 + 0.27379998564720154 + 0.37000000476837158 + 0.37000000476837158 + + cloud_pos_density1 + + 0.90999996662139893 + 0.81000000238418579 + 0.059999998658895493 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.38999998569488525 + 0 + 0 + 1 + + cloud_scroll_rate + + 11.170000076293945 + 8.4099998474121094 + + cloud_shadow + + 0.68999999761581421 + 0 + 0 + 1 + + density_multiplier + + 0.00014000000373926014 + 0 + 0 + 1 + + distance_multiplier + + 7.4000000953674316 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 4.0999999046325684 + 0 + 0 + 1 + + glow + + 0.59999942779541016 + 0.0010000000474974513 + -0.94999998807907104 + 1 + + haze_density + + 0.68999999761581421 + 0 + 0 + 1 + + haze_horizon + + 0.099999994039535522 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.22427062690258026 + -0.97452688217163086 + 0 + + max_y + + 3158 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 2.915398120880127 + sunlight_color + + 0.17999999225139618 + 0.14000000059604645 + 0.12000000476837158 + 0.059999998658895493 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Absinthe%20Light%20.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Absinthe%20Light%20.xml new file mode 100644 index 0000000000..31eb39ac29 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Absinthe%20Light%20.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.0799999237060547 + 0.98999994993209839 + 0.77999997138977051 + 1.0799999237060547 + + blue_density + + 0.64736837148666382 + 0.48414888978004456 + 0.81999999284744263 + 0.40999999642372131 + + blue_horizon + + 0.5 + 0.49548381567001343 + 0.45999997854232788 + 0.51999998092651367 + + cloud_color + + 0.4100000062111997 + 0.4100000062111997 + 0.4100000062111997 + 0.4100000062111997 + + cloud_pos_density1 + + 0.14000000059604645 + 0.62000000476837158 + 1 + 1 + + cloud_pos_density2 + + 0.35999998450279236 + 0.56999999284744263 + 0.12999999523162842 + 1 + + cloud_scale + + 0.35999998450279236 + 0 + 0 + 1.0000000149011612 + + cloud_scroll_rate + + 10.199999791580112 + 10.010999679880427 + + cloud_shadow + + 0.29999998211860657 + 0 + 0 + 1.0000000149011612 + + density_multiplier + + 7.9999997979030013e-005 + 0 + 0 + 1.0000000149011612 + + distance_multiplier + + 5.4000000953674316 + 0 + 0 + 1.0000000149011612 + + east_angle + 1.0932743549346924 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.1699998378753662 + 0 + 0 + 1.0000000149011612 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.55000001192092896 + 1 + + haze_density + + 0.31999999284744263 + 0 + 0 + 1 + + haze_horizon + + 0.17999999225139618 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.39627334475517273 + 0.89494067430496216 + -0.20505768060684204 + 0 + + max_y + + 805 + 0 + 0 + 1.0000000149011612 + + preset_num + 28 + star_brightness + 0.25999999046325684 + sun_angle + 2.0332944393157959 + sunlight_color + + 0.69882339239120483 + 0.8258824348449707 + 1.0799999237060547 + 0.35999998450279236 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Andi%20Light%20.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Andi%20Light%20.xml new file mode 100644 index 0000000000..654652b52a --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Andi%20Light%20.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1 + 2 + 2 + 1 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.99999994039535522 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 5.1599996368167922e-005 + 0 + 0 + 1 + + distance_multiplier + + 0.80000001192092896 + 0 + 0 + 1 + + east_angle + 3.091327428817749 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.69569998979568481 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -2.5 + 1 + + haze_density + + 3 + 0 + 0 + 1 + + haze_horizon + + 0.59999996423721313 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.0098020657896995544 + 0.9807855486869812 + 0.1948426365852356 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 1.7671445608139038 + sunlight_color + + 1.5 + 1.5 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Angles%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Angles%20Light%2001.xml new file mode 100644 index 0000000000..fbb2272ff6 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Angles%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.8235294818878174 + 1.2352941036224365 + 1.5411765575408936 + 0.60784316062927246 + + blue_density + + 1.2000000476837158 + 1.4039216041564941 + 1.6392157077789307 + 0.81960785388946533 + + blue_horizon + + 1.2000000476837158 + 1.4039216041564941 + 1.6392157077789307 + 0.81960785388946533 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.96579998731613159 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 1 + 0 + 0 + 1 + + density_multiplier + + 0.00020660000154748559 + 0 + 0 + 1 + + distance_multiplier + + 6.2000002861022949 + 0 + 0 + 1 + + east_angle + 0.29530972242355347 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.95649999380111694 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 2.059999942779541 + 0 + 0 + 1 + + haze_horizon + + 0.5 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.268882155418396 + 0.38268527388572693 + -0.88388597965240479 + 0 + + max_y + + 788 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 2.7488915920257568 + sunlight_color + + 1.5 + 1.5 + 1.5 + 0.5 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%20%2008.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%20%2008.xml new file mode 100644 index 0000000000..268ea125f5 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%20%2008.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1 + 1 + 1 + 0.5 + + blue_horizon + + 1 + 1 + 1 + 0.5 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.76829999685287476 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.059000000357627869 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940033104544 + 10.011000058908452 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00025079998886212707 + 0 + 0 + 1 + + distance_multiplier + + 14 + 0 + 0 + 1 + + east_angle + 0.19477875530719757 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 16.80000114440918 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 1.1499999761581421 + 0 + 0 + 1 + + haze_horizon + + 0.17000000178813934 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.14745019376277924 + 0.64778679609298706 + 0.74741601943969727 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 1.7856996059417725 + sun_angle + 0.70467567443847656 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2001.xml new file mode 100644 index 0000000000..268ea125f5 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1 + 1 + 1 + 0.5 + + blue_horizon + + 1 + 1 + 1 + 0.5 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.76829999685287476 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.059000000357627869 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940033104544 + 10.011000058908452 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00025079998886212707 + 0 + 0 + 1 + + distance_multiplier + + 14 + 0 + 0 + 1 + + east_angle + 0.19477875530719757 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 16.80000114440918 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 1.1499999761581421 + 0 + 0 + 1 + + haze_horizon + + 0.17000000178813934 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.14745019376277924 + 0.64778679609298706 + 0.74741601943969727 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 1.7856996059417725 + sun_angle + 0.70467567443847656 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2002.xml new file mode 100644 index 0000000000..130571e2a0 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1 + 1 + 1 + 0.5 + + blue_horizon + + 1 + 1 + 1 + 0.5 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.76829999685287476 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.059000000357627869 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940033104544 + 10.011000058908452 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00025079998886212707 + 0 + 0 + 1 + + distance_multiplier + + 14 + 0 + 0 + 1 + + east_angle + 0.19477875530719757 + enable_cloud_scroll + + 1 + 1 + + gamma + + 3.3912999629974365 + 0 + 0 + 1 + + glow + + 16.80000114440918 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 1.1499999761581421 + 0 + 0 + 1 + + haze_horizon + + 0.17000000178813934 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.14745019376277924 + 0.64778679609298706 + 0.74741601943969727 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 1.7856996059417725 + sun_angle + 0.70467567443847656 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2003.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2003.xml new file mode 100644 index 0000000000..676f1a7802 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2003.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.15000000596046448 + 0.15000000596046448 + 0.15000000596046448 + 0.05000000074505806 + + blue_density + + 1 + 1 + 1 + 0.5 + + blue_horizon + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.93999999761581421 + 0.22999998927116394 + 0.38409999012947083 + 1 + + cloud_pos_density2 + + 1 + 0.50999999046325684 + 1 + 1 + + cloud_scale + + 0.31279999017715454 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0.43999999761581421 + 0 + 0 + 1 + + density_multiplier + + 7.3799994424916804e-005 + 0 + 0 + 1 + + distance_multiplier + + 13.199999809265137 + 0 + 0 + 1 + + east_angle + 1.9477875232696533 + enable_cloud_scroll + + 0 + 0 + + gamma + + 1.3999999761581421 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.69999998807907104 + 0 + 0 + 1 + + haze_horizon + + 0.26999998092651367 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.51655691862106323 + 0.83146905899047852 + -0.20451940596103668 + 0 + + max_y + + 242 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.98174667358398438 + sunlight_color + + 2.6999998092651367 + 2.6999998092651367 + 2.6999998092651367 + 0.89999997615814209 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2004.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2004.xml new file mode 100644 index 0000000000..fa71d78f4a --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2004.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + blue_horizon + + 2 + 2 + 2 + 1 + + cloud_color + + 0.22615529217625469 + 0.22615529217625469 + 0.22615529217625469 + 0.99999702096404042 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.88000003558816353 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940033104544 + 10.011000058908452 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.0003761999832931906 + 0 + 0 + 1 + + distance_multiplier + + 31.80000114440918 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.3999996185302734 + 0.0010000000474974513 + -0.74999994039535522 + 1 + + haze_density + + 3.6292644654378239 + 0 + 0 + 1 + + haze_horizon + + 0.017144030545153739 + 0.19915600403562983 + 0.19915600403562983 + 1 + + lightnorm + + 0 + 0.29445916414260864 + -0.95566403865814209 + 0 + + max_y + + 869.42607640502217 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 1.7856996059417725 + sun_angle + 2.842703104019165 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2005.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2005.xml new file mode 100644 index 0000000000..df9427703a --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2005.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.1875 + 0.1875 + 0.1875 + 0.0625 + + blue_density + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + blue_horizon + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0.44999998807907104 + 0 + 0 + 1 + + density_multiplier + + 0.00013000000035390258 + 0 + 0 + 1 + + distance_multiplier + + 21.700000762939453 + 0 + 0 + 1 + + east_angle + 1.9477875232696533 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3999999761581421 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.69999998807907104 + 0 + 0 + 1 + + haze_horizon + + 0.20999999344348907 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.51655691862106323 + 0.83146905899047852 + -0.20451940596103668 + 0 + + max_y + + 242 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.98174667358398438 + sunlight_color + + 2.6999998092651367 + 2.6999998092651367 + 2.6999998092651367 + 0.89999997615814209 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2006.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2006.xml new file mode 100644 index 0000000000..d0ba4bb023 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2006.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.1875 + 0.1875 + 0.1875 + 0.0625 + + blue_density + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + blue_horizon + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 0.99409997463226318 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.49579998850822449 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.70001220703125 + 10.01099967956543 + + cloud_shadow + + 0.29999998211860657 + 0 + 0 + 1 + + density_multiplier + + 0.00015750000602565706 + 0 + 0 + 1 + + distance_multiplier + + 4.5999999046325684 + 0 + 0 + 1 + + east_angle + 1.9477875232696533 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3999999761581421 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 1.7400000095367432 + 0 + 0 + 1 + + haze_horizon + + 0.070000000298023224 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.51655691862106323 + 0.83146905899047852 + -0.20451940596103668 + 0 + + max_y + + 11 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.98174667358398438 + sunlight_color + + 2.6999998092651367 + 2.6999998092651367 + 2.6999998092651367 + 0.89999997615814209 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2007.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2007.xml new file mode 100644 index 0000000000..f62fe8cd04 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2007.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.76829999685287476 + 1 + + cloud_pos_density2 + + 1 + 1 + 0 + 1 + + cloud_scale + + 0.00039999998989515007 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940033104544 + 10.011000058908452 + + cloud_shadow + + 0.19999998807907104 + 0 + 0 + 1 + + density_multiplier + + 0.0010865998920053244 + 0 + 0 + 1 + + distance_multiplier + + 1000 + 0 + 0 + 1 + + east_angle + 1.5016813278198242 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.17999999225139618 + 0 + 0 + 1 + + glow + + 40 + 0.0010000000474974513 + -10 + 1 + + haze_density + + 5 + 0 + 0 + 1 + + haze_horizon + + 5 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.97396135330200195 + 0.21645671129226685 + -0.067422725260257721 + 0 + + max_y + + 2077 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 2.9234089851379395 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2008.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2008.xml new file mode 100644 index 0000000000..4ecf8c2a69 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2008.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0.39999997615814209 + 0.39999997615814209 + 0.39999997615814209 + 0.19999998807907104 + + blue_horizon + + 1 + 1 + 1 + 0.5 + + cloud_color + + 0.22617273092134837 + 0.2261830306064212 + 0.22618354559006093 + 1 + + cloud_pos_density1 + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.12499716758729562 + 1 + + cloud_scale + + 0.22999998927116394 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.499370784775238 + 10.011009025563908 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00089999998454004526 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + 0 + 1 + + haze_density + + 0.5 + 0 + 0 + 1 + + haze_horizon + + 0.32999998331069946 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 1 + -4.3711388286737929e-008 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 1.5707963705062866 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2009.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2009.xml new file mode 100644 index 0000000000..1a9ebda49b --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2009.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1.5 + 1.5 + 1.5 + 0.75 + + blue_horizon + + 1.5 + 1.5 + 1.5 + 0.75 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.95999997854232788 + 0.31000000238418579 + 0.34149998426437378 + 1 + + cloud_pos_density2 + + 1 + 1 + 0 + 1 + + cloud_scale + + 0.026399999856948853 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940033104544 + 10.011000058908452 + + cloud_shadow + + 0.29999998211860657 + 0 + 0 + 1 + + density_multiplier + + 0.00018439999257680029 + 0 + 0 + 1 + + distance_multiplier + + 9.3000001907348633 + 0 + 0 + 1 + + east_angle + 0.78539818525314331 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 15.799999237060547 + 0.0010000000474974513 + -0.74999994039535522 + 1 + + haze_density + + 1.5299999713897705 + 0 + 0 + 1 + + haze_horizon + + 0.12999999523162842 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.64968371391296387 + 0.39474311470985413 + 0.64968371391296387 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 2 + sun_angle + 0.40578824281692505 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2010.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2010.xml new file mode 100644 index 0000000000..0dac493550 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2010.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.76829999685287476 + 1 + + cloud_pos_density2 + + 1 + 1 + 0 + 1 + + cloud_scale + + 0.00039999998989515007 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940033104544 + 10.011000058908452 + + cloud_shadow + + 0.18999999761581421 + 0 + 0 + 1 + + density_multiplier + + 0.001574800000526011 + 0 + 0 + 1 + + distance_multiplier + + 1083.300048828125 + 0 + 0 + 1 + + east_angle + 1.5016813278198242 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.20999999344348907 + 0 + 0 + 1 + + glow + + 100 + 0.0010000000474974513 + -25 + 1 + + haze_density + + 1.0070000886917114 + 0 + 0 + 1 + + haze_horizon + + 5.0410003662109375 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.97396135330200195 + 0.21645671129226685 + -0.067422725260257721 + 0 + + max_y + + 100000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 2.9234089851379395 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2011.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2011.xml new file mode 100644 index 0000000000..491a9eeb64 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2011.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00036219999310560524 + 0 + 0 + 1 + + distance_multiplier + + 9.3000001907348633 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.1599998474121094 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 1.3799999952316284 + 0 + 0 + 1 + + haze_horizon + + 0.11999999731779099 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 1 + -4.3711388286737929e-008 + 0 + + max_y + + 45 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 1.5707963705062866 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2012.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2012.xml new file mode 100644 index 0000000000..4e10ae8a97 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2012.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00074019999010488391 + 0 + 0 + 1 + + distance_multiplier + + 10.199999809265137 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 10 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.64999938011169434 + 1 + + haze_density + + 1.4499999284744263 + 0 + 0 + 1 + + haze_horizon + + 0.11999999731779099 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.81158280372619629 + -0.58423745632171631 + 0 + + max_y + + 1846 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.1947364807128906 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2013.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2013.xml new file mode 100644 index 0000000000..6555024384 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20B%2FW%20Light%2013.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 0 + 1 + + cloud_pos_density2 + + 1 + 1 + 0 + 1 + + cloud_scale + + 0 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940033104544 + 10.011000058908452 + + cloud_shadow + + 0.1983799934387207 + 0 + 0 + 1 + + density_multiplier + + 0.00074799999129027128 + 0 + 0 + 1 + + distance_multiplier + + 163.80000305175781 + 0 + 0 + 1 + + east_angle + 1.5016813278198242 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.17999999225139618 + 0 + 0 + 1 + + glow + + 100 + 0.0010000000474974513 + -25 + 1 + + haze_density + + 0.33600002527236938 + 0 + 0 + 1 + + haze_horizon + + 5.0370001792907715 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.97396135330200195 + 0.21645671129226685 + -0.067422725260257721 + 0 + + max_y + + 100000 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 2.9234089851379395 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Boken%20Lines%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Boken%20Lines%20Light%2001.xml new file mode 100644 index 0000000000..8b1a001b18 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Boken%20Lines%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 2 + 2 + 2 + 1 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.5 + 0.5 + 0 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.34000000357627869 + 1 + + cloud_scale + + 0 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940033104544 + 10.011000058908452 + + cloud_shadow + + -0.485443115234375 + 0 + 0 + 1 + + density_multiplier + + 3.9400001696776599e-005 + 0 + 0 + 1 + + distance_multiplier + + 10000 + 0 + 0 + 1 + + east_angle + 0.19477875530719757 + enable_cloud_scroll + + 0 + 0 + + gamma + + 9.25 + 0 + 0 + 1 + + glow + + 16.80000114440918 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.14745019376277924 + 0.64778679609298706 + 0.74741601943969727 + 0 + + max_y + + 4 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 0.70467567443847656 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Breakwave%20Building%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Breakwave%20Building%20Light.xml new file mode 100644 index 0000000000..0fadd9c759 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Breakwave%20Building%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1 + 1 + 1 + 0.5 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.37000000476837158 + 0.79999995231628418 + 0.12429999560117722 + 1 + + cloud_pos_density2 + + 0.97999995946884155 + 0.70999997854232788 + 0.049999997019767761 + 1 + + cloud_scale + + 0.17359998822212219 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0.47300004959106445 + 0 + 0 + 1 + + density_multiplier + + 9.4499999249819666e-005 + 0 + 0 + 1 + + distance_multiplier + + 39.400001525878906 + 0 + 0 + 1 + + east_angle + 5.4852209091186523 + enable_cloud_scroll + + 0 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.070000000298023224 + 0 + 0 + 1 + + haze_horizon + + 0.17999999225139618 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.47905999422073364 + 0.74313849210739136 + 0.46716883778572083 + 0 + + max_y + + 3615 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 0.83774858713150024 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20002%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20002%20Light.xml new file mode 100644 index 0000000000..de207f503f --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20002%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.15000000596046448 + 0.15000000596046448 + 0.15000000596046448 + 0.05000000074505806 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.75 + 0.75 + 0.75 + 0.75 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 0 + 0 + 0 + 1 + + east_angle + 3.0473451614379883 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.4199999570846558 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + 2.4000000953674316 + 1 + + haze_density + + 5 + 0 + 0 + 1 + + haze_horizon + + 5 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.083091713488101959 + 0.46948650479316711 + 0.87902116775512695 + 0 + + max_y + + 6538 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 500 + sun_angle + 2.6528835296630859 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20003%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20003%20Light.xml new file mode 100644 index 0000000000..5f4bc38dd3 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20003%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1 + 1 + 1 + 0.5 + + blue_horizon + + 0.45819997787475586 + 0.51910001039505005 + 0.70179998874664307 + 0.35089999437332153 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.78999996185302734 + 0.85999995470046997 + 0.76330000162124634 + 1 + + cloud_pos_density2 + + 0.97999995946884155 + 0.70999997854232788 + 0 + 1 + + cloud_scale + + 0.39659997820854187 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0.43999999761581421 + 0 + 0 + 1 + + density_multiplier + + 9.4499999249819666e-005 + 0 + 0 + 1 + + distance_multiplier + + 39.400001525878906 + 0 + 0 + 1 + + east_angle + 2.670353889465332 + enable_cloud_scroll + + 0 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.070000000298023224 + 0 + 0 + 1 + + haze_horizon + + 0.17999999225139618 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.30378204584121704 + 0.74313849210739136 + -0.59620606899261475 + 0 + + max_y + + 3615 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 0.83774858713150024 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20005%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20005%20Light.xml new file mode 100644 index 0000000000..7d11023464 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20005%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.2899999618530273 + 1.2899999618530273 + 1.2899999618530273 + 0.43000000715255737 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.75 + 0.75 + 0.75 + 0.75 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 0 + 0 + 0 + 1 + + east_angle + 0.60946899652481079 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + 2.4000000953674316 + 1 + + haze_density + + 5 + 0 + 0 + 1 + + haze_horizon + + 5 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.36985558271408081 + 0.76324218511581421 + -0.5297812819480896 + 0 + + max_y + + 6538 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 500 + sun_angle + 2.2732763290405273 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20007%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20007%20Light.xml new file mode 100644 index 0000000000..06034997f9 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Build%20007%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.17999999225139618 + 0.17999999225139618 + 0.17999999225139618 + 0.059999998658895493 + + blue_density + + 1.5 + 1.5 + 1.5 + 0.75 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.93999999761581421 + 0.22999998927116394 + 0.38409999012947083 + 1 + + cloud_pos_density2 + + 1 + 0.50999999046325684 + 1 + 1 + + cloud_scale + + 0.31279999017715454 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 0 + 0 + 0 + 1 + + east_angle + 4.3416814804077148 + enable_cloud_scroll + + 0 + 0 + + gamma + + 2.6099998950958252 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.6760907769203186 + 0.68836575746536255 + 0.26278114318847656 + 0 + + max_y + + 242 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.3823590278625488 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Cafe%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Cafe%20Light%2001.xml new file mode 100644 index 0000000000..7c10c0df46 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Cafe%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0.12089811412885521 + 0.33770671695460663 + 0.67541757891583387 + 0.76708334654569654 + + blue_horizon + + 0.13497034943045882 + 0.26690842067701936 + 0.4016666400432598 + 0.74541666984558219 + + cloud_color + + 0.625 + 0.625 + 0.875 + 0.875 + + cloud_pos_density1 + + 0.47999998927116394 + 0.97999995946884155 + 0.14630000293254852 + 1 + + cloud_pos_density2 + + 1 + 1 + 0.070000000298023224 + 1 + + cloud_scale + + 0.22280000150203705 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0.5 + 0 + 0 + 1 + + density_multiplier + + 0.00028125001798306321 + 0 + 0 + 1 + + distance_multiplier + + 6.3874998847643383 + 0 + 0 + 1 + + east_angle + 3.5185837745666504 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.0900000333786011 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.51583333298563971 + 0 + 0 + 1 + + haze_horizon + + 0.13833333183079954 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.28709480166435242 + 0.6259227991104126 + -0.72511875629425049 + 0 + + max_y + + 685.18749099969864 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 2 + sun_angle + 0.67631423473358154 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Calima%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Calima%20Light%2001.xml new file mode 100644 index 0000000000..8cdc45ec0a --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Calima%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.21000000834465027 + 0.21000000834465027 + 0.21000000834465027 + 0.070000000298023224 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 2 + 2 + 2 + 1 + + cloud_color + + 0.28666070103645325 + 0.28666070103645325 + 0.28666070103645325 + 0.28666070103645325 + + cloud_pos_density1 + + 0.17999999225139618 + 0.50999999046325684 + 0.91949393667753065 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 1.437999963760376 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.400862650389627 + 10.01099967956543 + + cloud_shadow + + -0.27299976348876953 + 0 + 0 + 1 + + density_multiplier + + 0.011666699312627316 + 0 + 0 + 1 + + distance_multiplier + + 0.10000000149011612 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 10 + 0 + 0 + 1 + + glow + + 22.000003814697266 + 0.0010000000474974513 + -7.5 + 1 + + haze_density + + 0.33600002527236938 + 0 + 0 + 1 + + haze_horizon + + 11.530000686645508 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.35022372007369995 + -0.93666607141494751 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 2.7837827205657959 + sunlight_color + + 0.32999998331069946 + 0.32999998331069946 + 0.32999998331069946 + 0.10999999940395355 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Charolotte%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Charolotte%20Light.xml new file mode 100644 index 0000000000..623c258f50 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Charolotte%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 2 + 2 + 2 + 1 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.0006399999838322401 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 2.6515045166015625 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3042999505996704 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -2.5 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 1 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.063475340604782104 + 0.99086576700210571 + -0.11897877603769302 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 1.4355322122573853 + sunlight_color + + 3 + 0 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Cloud%20Credit%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Cloud%20Credit%20Light.xml new file mode 100644 index 0000000000..baab0d39e7 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Cloud%20Credit%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 3 + 3 + 3 + 1 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.95999997854232788 + 0.17999999225139618 + 0.12429999560117722 + 1 + + cloud_pos_density2 + + 1 + 0.5899999737739563 + 0 + 1 + + cloud_scale + + 0.074400000274181366 + 0 + 0 + 1 + + cloud_scroll_rate + + 76.100006103515625 + 10.70001220703125 + + cloud_shadow + + 0.29999998211860657 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 0 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 7.8399996757507324 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + 0.64999997615814209 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.8508676290512085 + -0.52538013458251953 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.1239581108093262 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Cloud%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Cloud%20Light%2001.xml new file mode 100644 index 0000000000..d0456f444a --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Cloud%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density1 + + 0.95999997854232788 + 0.31000000238418579 + 3 + 1 + + cloud_pos_density2 + + 1 + 1 + 0.71999996900558472 + 1 + + cloud_scale + + 0.2231999933719635 + 0 + 0 + 1 + + cloud_scroll_rate + + 18.5 + -3 + + cloud_shadow + + 0.15999999642372131 + 0 + 0 + 1 + + density_multiplier + + 3.299999889350147e-006 + 0 + 0 + 1 + + distance_multiplier + + 0 + 0 + 0 + 1 + + east_angle + 3.1855752468109131 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 15.799999237060547 + 0.0010000000474974513 + -0.74999994039535522 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 4.8899998664855957 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.040397927165031433 + 0.39473667740821838 + -0.91790574789047241 + 0 + + max_y + + 385 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 500 + sun_angle + 0.40578123927116394 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dead%20End%20Sky%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dead%20End%20Sky%2001.xml new file mode 100644 index 0000000000..53a9cad037 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dead%20End%20Sky%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.83636385202407837 + 1.0036364793777466 + 1.3799998760223389 + 0.45999997854232788 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 2 + 0 + 0 + 1 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 0.87999999523162842 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.0099999997764825821 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.510000228881836 + 10.01099967956543 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00018999999156221747 + 0 + 0 + 1 + + distance_multiplier + + 56.700000762939453 + 0 + 0 + 1 + + east_angle + 4.7123889923095703 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.1499999761581421 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.11999999731779099 + 0 + 0 + 1 + + haze_horizon + + 0.25 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.98078560829162598 + 0.19508861005306244 + 1.1695751034324076e-008 + 1 + + max_y + + 906 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 2 + sun_angle + 3.3379404544830322 + sunlight_color + + 0.59999996423721313 + 0.59999996423721313 + 1.1399999856948853 + 1.1399999856948853 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dorm%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dorm%20Light%2001.xml new file mode 100644 index 0000000000..f4a22b8a2f --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dorm%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.26250001788139343 + 0.3031250536441803 + 0.75 + 0.25 + + blue_density + + 1 + 0.5 + 0 + 0.5 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.23999999463558197 + 0.4699999988079071 + 0.31999999284744263 + 0.4699999988079071 + + cloud_pos_density1 + + 0.48999997973442078 + 0.50999999046325684 + 0.74000000953674316 + 1 + + cloud_pos_density2 + + 0.44999998807907104 + 0.5 + 0.14000000059604645 + 1 + + cloud_scale + + 0.32999998331069946 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.37999999523162842 + 0 + 0 + 1 + + density_multiplier + + 7.3799994424916804e-005 + 0 + 0 + 1 + + distance_multiplier + + 41.100002288818359 + 0 + 0 + 1 + + east_angle + 2.4064600467681885 + enable_cloud_scroll + + 0 + 0 + + gamma + + 3.2173998355865479 + 0 + 0 + 1 + + glow + + 12 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 1.3500000238418579 + 0 + 0 + 1 + + haze_horizon + + 0.15999999642372131 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.67022424936294556 + 0.037081710994243622 + 0.74123167991638184 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 1.0099999904632568 + sun_angle + 3.1045024394989014 + sunlight_color + + 2.5799999237060547 + 2.4411697387695313 + 2.4411697387695313 + 0.86000001430511475 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2001.xml new file mode 100644 index 0000000000..278ce095da --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.031499996781349182 + 0.15789999067783356 + 0.26850000023841858 + 0.089500002562999725 + + blue_density + + 0 + 1.3200000524520874 + 1.3199996948242188 + 0.6600000262260437 + + blue_horizon + + 0 + 0.79687511920928955 + 0.79687494039535522 + 0.39843755960464478 + + cloud_color + + 0.2481999397277832 + 0.60211998224258423 + 0.91180002689361572 + 0.91180002689361572 + + cloud_pos_density1 + + 0.69999998807907104 + 0.19999998807907104 + 1.2249000072479248 + 1 + + cloud_pos_density2 + + 0.70999997854232788 + 0.84999996423721313 + 0.35999998450279236 + 1 + + cloud_scale + + 0.29760000109672546 + 0 + 0 + 1 + + cloud_scroll_rate + + 11.70001220703125 + 10.01099967956543 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00014170000213198364 + 0 + 0 + 1 + + distance_multiplier + + 6.5 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 32.599998474121094 + 0.0010000000474974513 + -5.0500001907348633 + 1 + + haze_density + + 1.5999999046325684 + 0 + 0 + 1 + + haze_horizon + + 0.38999998569488525 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 1 + -4.8876205482883961e-007 + 1 + + max_y + + 2769 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 500 + sun_angle + 4.7123894691467285 + sunlight_color + + 0.34876692295074463 + 0.35574248433113098 + 0.65999996662139893 + 0.2199999988079071 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2002.xml new file mode 100644 index 0000000000..d0ef3494cb --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.99101096746882478 + 0.90569759047448506 + 0.94676920768410944 + 0.33033699762952112 + + blue_density + + 0.15949166061381881 + 0.44534921175553777 + 0.78703662568265287 + 0.78703662568265287 + + blue_horizon + + 0.45808683258190275 + 0.46276614028103857 + 0.64592672496531911 + 0.38195237578970165 + + cloud_color + + 0.33464740594394182 + 0.33464740594394182 + 0.33464740594394182 + 0.52483933184657472 + + cloud_pos_density1 + + 0.17999999225139618 + 0.50999999046325684 + 0.97050554401449818 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999997879515621 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.273588712934393 + 10.010999679568112 + + cloud_shadow + + 0.34000000357627869 + 0 + 0 + 1 + + density_multiplier + + 0.00028814651401716849 + 0 + 0 + 1 + + distance_multiplier + + 16.30000114440918 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.0002455048624084 + 0.001 + -0.4800002433233434 + 1 + + haze_density + + 0.6606740078475033 + 0 + 0 + 1 + + haze_horizon + + 0.18262636689842734 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.99904829263687134 + -0.043617993593215942 + 0 + + max_y + + 1348.8893615007401 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 1.6144281625747681 + sunlight_color + + 1.1362672142439687 + 1.1719930547447106 + 1.2613076522878659 + 0.42043587660352916 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2003.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2003.xml new file mode 100644 index 0000000000..d484dbf8f3 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2003.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.0298734564795637 + 0.88898782567135015 + 0.88898782567135015 + 0.79949215426478126 + + blue_density + + 0.17798297054824247 + 0.41603360580930904 + 0.78683667783050026 + 0.79594799064391797 + + blue_horizon + + 0.23530982264376704 + 0.30629670960041322 + 0.37835530224478614 + 0.77620100618916932 + + cloud_color + + 0.2866606875510479 + 0.2866606875510479 + 0.2866606875510479 + 0.80582145952723883 + + cloud_pos_density1 + + 0.17999999225139618 + 0.50999999046325684 + 0.91949393667753065 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999998688697698 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.400862650389627 + 10.01099967956543 + + cloud_shadow + + 0.34000000357627869 + 0 + 0 + 1 + + density_multiplier + + 0.00036784747657809082 + 0 + 0 + 1 + + distance_multiplier + + 0.93417677079577877 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.69999998807907104 + 0 + 0 + 1 + + haze_horizon + + 0.16987348178519687 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.30417308211326599 + -0.95261681079864502 + 0 + + max_y + + 905.60360267758369 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 2.8325223922729492 + sunlight_color + + 2.1459913660813905 + 2.1615810746477075 + 2.2005553460635001 + 0.76961867816836427 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2004.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2004.xml new file mode 100644 index 0000000000..2de71161f1 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Dream%20Book%20Light%2004.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.99101096746882478 + 0.90569759047448506 + 0.94676920768410944 + 0.33033699762952112 + + blue_density + + 0.15949166061381881 + 0.44534921175553777 + 0.78703662568265287 + 0.78703662568265287 + + blue_horizon + + 0.45808683258190275 + 0.46276614028103857 + 0.64592672496531911 + 0.38195237578970165 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.17999999225139618 + 0.50999999046325684 + 0.97050554401449818 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999997879515621 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.273588712934393 + 10.010999679568112 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00033999999868683517 + 0 + 0 + 1 + + distance_multiplier + + 31 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.0002455711364746 + 0.0010000000474974513 + -0.74999994039535522 + 1 + + haze_density + + 1.059999942779541 + 0 + 0 + 1 + + haze_horizon + + 0.42999997735023499 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.99904829263687134 + -0.043617993593215942 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 1.6144281625747681 + sunlight_color + + 1.1362672142439687 + 1.1719930547447106 + 1.2613076522878659 + 0.42043587660352916 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Epi%20Vintage%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Epi%20Vintage%20Light.xml new file mode 100644 index 0000000000..1bb93ec236 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Epi%20Vintage%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.29999998211860657 + 0.17999999225139618 + 0 + 0.099999994039535522 + + blue_density + + 0.97999995946884155 + 0.97999995946884155 + 0.97999995946884155 + 0.48999997973442078 + + blue_horizon + + 0.31999999284744263 + 0.31999999284744263 + 0.31999999284744263 + 0.15999999642372131 + + cloud_color + + 0.50999999046325684 + 0.50999999046325684 + 0.50999999046325684 + 1 + + cloud_pos_density1 + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.079999998211860657 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.25999999046325684 + 0 + 0 + 1 + + density_multiplier + + 0.00031000000308267772 + 0 + 0 + 1 + + distance_multiplier + + 40.299999237060547 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.33000001311302185 + 1 + + haze_density + + 2.2100000381469727 + 0 + 0 + 1 + + haze_horizon + + 0.56999999284744263 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.36227512359619141 + -0.93207120895385742 + 0 + + max_y + + 752 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 2.7708849906921387 + sunlight_color + + 1.3799998760223389 + 1.3799998760223389 + 1.3799998760223389 + 0.45999997854232788 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Fashion%20Path%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Fashion%20Path%20Light%2001.xml new file mode 100644 index 0000000000..14d6ab9b3d --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Fashion%20Path%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.5 + 1.5 + 3 + 1 + + blue_density + + 2 + 2 + 1 + 1 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.43948723673439005 + 0.49764935046544778 + 0.50246442938400904 + 1 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.18000000715255737 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00028125001798306321 + 0 + 0 + 1 + + distance_multiplier + + 62.700000762939453 + 0 + 0 + 1 + + east_angle + 3.5185837745666504 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.0900000333786011 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.42999997735023499 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.28709480166435242 + 0.6259227991104126 + -0.72511875629425049 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 0.67631423473358154 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Got%20It%20Light%20.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Got%20It%20Light%20.xml new file mode 100644 index 0000000000..718bd1ab5f --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Got%20It%20Light%20.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.56099998950958252 + 0.37620007991790771 + 0.099000021815299988 + 0.18699999153614044 + + blue_density + + 0.97999995946884155 + 0.97999995946884155 + 0.97999995946884155 + 0.48999997973442078 + + blue_horizon + + 0.31999999284744263 + 0.31999999284744263 + 0.31999999284744263 + 0.15999999642372131 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.12459999322891235 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.0004881999921053648 + 0 + 0 + 1 + + distance_multiplier + + 3.9000000953674316 + 0 + 0 + 1 + + east_angle + 2.2870795726776123 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3042999505996704 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.04999995231628418 + 1 + + haze_density + + 3.4800000190734863 + 0 + 0 + 1 + + haze_horizon + + 0.37000000476837158 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.70532232522964478 + 0.35430732369422913 + 0.61399251222610474 + 0 + + max_y + + 385 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 2.7794194221496582 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Horizon%20Building%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Horizon%20Building%20Light%2001.xml new file mode 100644 index 0000000000..8b6adaae25 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Horizon%20Building%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1.7200000286102295 + 1.3424379825592041 + 0.83542799949645996 + 0.86000001430511475 + + blue_horizon + + 1.4582855701446533 + 1.3041387796401978 + 1.0971424579620361 + 0.72914278507232666 + + cloud_color + + 0 + 0.39843800663948059 + 0.39843699336051941 + 0.39843800663948059 + + cloud_pos_density1 + + 0.47999998927116394 + 0.87000000476837158 + 1.4378999471664429 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.87000000476837158 + 1 + + cloud_scale + + 0.37199997901916504 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0.55000001192092896 + 0 + 0 + 1 + + density_multiplier + + 0.00058270001318305731 + 0 + 0 + 1 + + distance_multiplier + + 63 + 0 + 0 + 1 + + east_angle + 3.5185837745666504 + enable_cloud_scroll + + 0 + 0 + + gamma + + 1.0900000333786011 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -10 + 1 + + haze_density + + 0.039999999105930328 + 0 + 0 + 1 + + haze_horizon + + 0.52999997138977051 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.28709480166435242 + 0.6259227991104126 + -0.72511875629425049 + 0 + + max_y + + 5615 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.67631423473358154 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Horizon%20Building%20Light%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Horizon%20Building%20Light%2002.xml new file mode 100644 index 0000000000..0fadd9c759 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Horizon%20Building%20Light%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1 + 1 + 1 + 0.5 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.37000000476837158 + 0.79999995231628418 + 0.12429999560117722 + 1 + + cloud_pos_density2 + + 0.97999995946884155 + 0.70999997854232788 + 0.049999997019767761 + 1 + + cloud_scale + + 0.17359998822212219 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0.47300004959106445 + 0 + 0 + 1 + + density_multiplier + + 9.4499999249819666e-005 + 0 + 0 + 1 + + distance_multiplier + + 39.400001525878906 + 0 + 0 + 1 + + east_angle + 5.4852209091186523 + enable_cloud_scroll + + 0 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.070000000298023224 + 0 + 0 + 1 + + haze_horizon + + 0.17999999225139618 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.47905999422073364 + 0.74313849210739136 + 0.46716883778572083 + 0 + + max_y + + 3615 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 0.83774858713150024 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Horizon%20Building%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Horizon%20Building%20Light.xml new file mode 100644 index 0000000000..0fadd9c759 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Horizon%20Building%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1 + 1 + 1 + 0.5 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.37000000476837158 + 0.79999995231628418 + 0.12429999560117722 + 1 + + cloud_pos_density2 + + 0.97999995946884155 + 0.70999997854232788 + 0.049999997019767761 + 1 + + cloud_scale + + 0.17359998822212219 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0.47300004959106445 + 0 + 0 + 1 + + density_multiplier + + 9.4499999249819666e-005 + 0 + 0 + 1 + + distance_multiplier + + 39.400001525878906 + 0 + 0 + 1 + + east_angle + 5.4852209091186523 + enable_cloud_scroll + + 0 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.070000000298023224 + 0 + 0 + 1 + + haze_horizon + + 0.17999999225139618 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.47905999422073364 + 0.74313849210739136 + 0.46716883778572083 + 0 + + max_y + + 3615 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 0.83774858713150024 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hospital%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hospital%20Light%2001.xml new file mode 100644 index 0000000000..e615890c93 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hospital%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.84000003337860107 + 0.84000003337860107 + 0.84000003337860107 + 0.2800000011920929 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 2 + 2 + 2 + 1 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.17999999225139618 + 0.50999999046325684 + 0.97050554401449818 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.41999997879515621 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.273588712934393 + 10.010999679568112 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00017699999443721026 + 0 + 0 + 1 + + distance_multiplier + + 26.399999618530273 + 0 + 0 + 1 + + east_angle + 1.9163715839385986 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.0002455711364746 + 0.0010000000474974513 + -0.94999998807907104 + 1 + + haze_density + + 0.96999996900558472 + 0 + 0 + 1 + + haze_horizon + + 0.37999999523162842 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.88343405723571777 + 0.34407094120979309 + 0.3180558979511261 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 2.7903435230255127 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hufflepuff%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hufflepuff%20Light%2001.xml new file mode 100644 index 0000000000..c5b090d137 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hufflepuff%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.56250005960464478 + 0.26250001788139343 + 0.75 + 0.25 + + blue_density + + 0 + 0.40999585390090942 + 0.81999999284744263 + 0.85999995470046997 + + blue_horizon + + 0.43999999761581421 + 0.22910800576210022 + 0.26829266548156738 + 0.2199999988079071 + + cloud_color + + 0.23999999463558197 + 0.4699999988079071 + 0.31999999284744263 + 0.4699999988079071 + + cloud_pos_density1 + + 0.48999997973442078 + 0.50999999046325684 + 0.74000000953674316 + 1 + + cloud_pos_density2 + + 0.44999998807907104 + 0.5 + 0.14000000059604645 + 1 + + cloud_scale + + 0.32999998331069946 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.37999999523162842 + 0 + 0 + 1 + + density_multiplier + + 0.00035999997635371983 + 0 + 0 + 1 + + distance_multiplier + + 2 + 0 + 0 + 1 + + east_angle + 0.12566371262073517 + enable_cloud_scroll + + 0 + 0 + + gamma + + 2.0299999713897705 + 0 + 0 + 1 + + glow + + 12 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 0.77999997138977051 + 0 + 0 + 1 + + haze_horizon + + 0.15999999642372131 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.12524418532848358 + 0.037689968943595886 + -0.9914097785949707 + 0 + + max_y + + 591 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 1.0099999904632568 + sun_angle + 3.1038937568664551 + sunlight_color + + 2.5799999237060547 + 2.4411697387695313 + 2.4411697387695313 + 0.85999995470046997 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hufflepuff%20Light%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hufflepuff%20Light%2002.xml new file mode 100644 index 0000000000..aaff835ebe --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hufflepuff%20Light%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.26250001788139343 + 0.3031250536441803 + 0.75 + 0.25 + + blue_density + + 1 + 0.5 + 0 + 0.5 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.23999999463558197 + 0.4699999988079071 + 0.31999999284744263 + 0.4699999988079071 + + cloud_pos_density1 + + 0.48999997973442078 + 0.50999999046325684 + 0.74000000953674316 + 1 + + cloud_pos_density2 + + 0.44999998807907104 + 0.5 + 0.14000000059604645 + 1 + + cloud_scale + + 0.32999998331069946 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.37999999523162842 + 0 + 0 + 1 + + density_multiplier + + 0.00031719999969936907 + 0 + 0 + 1 + + distance_multiplier + + 39.5 + 0 + 0 + 1 + + east_angle + 2.4064600467681885 + enable_cloud_scroll + + 0 + 0 + + gamma + + 2.4347999095916748 + 0 + 0 + 1 + + glow + + 12 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 1.559999942779541 + 0 + 0 + 1 + + haze_horizon + + 0.15999999642372131 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.67022424936294556 + 0.037081710994243622 + 0.74123167991638184 + 0 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 1.0099999904632568 + sun_angle + 3.1045024394989014 + sunlight_color + + 2.5799999237060547 + 2.4411697387695313 + 2.4411697387695313 + 0.86000001430511475 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hufflepuff%20Light%2003.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hufflepuff%20Light%2003.xml new file mode 100644 index 0000000000..82c8766966 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Hufflepuff%20Light%2003.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.56250005960464478 + 0.26250001788139343 + 0.75 + 0.25 + + blue_density + + 0 + 0.40999585390090942 + 0.81999999284744263 + 0.85999995470046997 + + blue_horizon + + 0.43999999761581421 + 0.22910800576210022 + 0.26829266548156738 + 0.2199999988079071 + + cloud_color + + 0.23999999463558197 + 0.4699999988079071 + 0.31999999284744263 + 0.4699999988079071 + + cloud_pos_density1 + + 0.48999997973442078 + 0.50999999046325684 + 0.74000000953674316 + 1 + + cloud_pos_density2 + + 0.44999998807907104 + 0.5 + 0.14000000059604645 + 1 + + cloud_scale + + 0.32999998331069946 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.37999999523162842 + 0 + 0 + 1 + + density_multiplier + + 0.00049000000581145287 + 0 + 0 + 1 + + distance_multiplier + + 35.700000762939453 + 0 + 0 + 1 + + east_angle + 0.12566371262073517 + enable_cloud_scroll + + 0 + 0 + + gamma + + 2.0299999713897705 + 0 + 0 + 1 + + glow + + 12 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 1.5899999141693115 + 0 + 0 + 1 + + haze_horizon + + 0.15999999642372131 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.12524418532848358 + 0.037689968943595886 + -0.9914097785949707 + 0 + + max_y + + 591 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 1.0099999904632568 + sun_angle + 3.1038937568664551 + sunlight_color + + 2.5799999237060547 + 2.4411697387695313 + 2.4411697387695313 + 0.85999995470046997 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2001.xml new file mode 100644 index 0000000000..768f4f7a8c --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.0499999523162842 + 1.0499999523162842 + 1.0499999523162842 + 0.34999999403953552 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0.6171875 + 0.6171875 + 0.6171875 + 0.30859375 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00017999998817685992 + 0 + 0 + 1 + + distance_multiplier + + 70.900001525878906 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.1999998092651367 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.69999998807907104 + 0 + 0 + 1 + + haze_horizon + + 0.18999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 1 + -4.3711388286737929e-008 + 0 + + max_y + + 1605 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 1.5707963705062866 + sunlight_color + + 0.7342105507850647 + 0.78157901763916016 + 0.90000003576278687 + 0.30000001192092896 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2002.xml new file mode 100644 index 0000000000..c75320eeaa --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.0499999523162842 + 1.0499999523162842 + 1.0499999523162842 + 0.34999999403953552 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0.6171875 + 0.6171875 + 0.6171875 + 0.30859375 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00017999998817685992 + 0 + 0 + 1 + + distance_multiplier + + 70.599998474121094 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.1999998092651367 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.69999998807907104 + 0 + 0 + 1 + + haze_horizon + + 0.18999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 1 + -4.3711388286737929e-008 + 0 + + max_y + + 2923 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 1.5707963705062866 + sunlight_color + + 0.7342105507850647 + 0.78157901763916016 + 0.90000003576278687 + 0.30000001192092896 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2003.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2003.xml new file mode 100644 index 0000000000..6384398370 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2003.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.62999999523162842 + 0.62999999523162842 + 0.62999999523162842 + 0.20999999344348907 + + blue_density + + 1.5 + 1.5 + 1.5 + 0.75 + + blue_horizon + + 0.6171875 + 0.6171875 + 0.6171875 + 0.30859375 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00012599999899975955 + 0 + 0 + 1 + + distance_multiplier + + 70.599998474121094 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.1999998092651367 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.98999994993209839 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 1 + -4.3711388286737929e-008 + 0 + + max_y + + 2923 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 1.5707963705062866 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2004.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2004.xml new file mode 100644 index 0000000000..fcec7085f9 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jessica%20Light%2004.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.62999999523162842 + 0.62999999523162842 + 0.62999999523162842 + 0.20999999344348907 + + blue_density + + 1.5 + 1.5 + 1.5 + 0.75 + + blue_horizon + + 0.6171875 + 0.6171875 + 0.6171875 + 0.30859375 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 4.7199999244185165e-005 + 0 + 0 + 1 + + distance_multiplier + + 70.900001525878906 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 27.200000762939453 + 0.0010000000474974513 + -7.3500003814697266 + 1 + + haze_density + + 1.1699999570846558 + 0 + 0 + 1 + + haze_horizon + + 0.81999999284744263 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 1 + -4.3711388286737929e-008 + 0 + + max_y + + 10000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 1.5707963705062866 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jim%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jim%20Light%2001.xml new file mode 100644 index 0000000000..57538798bb --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jim%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.43948723673439005 + 0.49764935046544778 + 0.50246442938400904 + 1 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.18000000715255737 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00028125001798306321 + 0 + 0 + 1 + + distance_multiplier + + 6.3874998847643383 + 0 + 0 + 1 + + east_angle + 2.8274335861206055 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.0900000333786011 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.51583333298563971 + 0 + 0 + 1 + + haze_horizon + + 0.13833333183079954 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.30801057815551758 + 0.080633237957954407 + -0.94795984029769897 + 0 + + max_y + + 685.18749099969864 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 0.080720871686935425 + sunlight_color + + 0 + 3 + 1.5 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jim%20Light%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jim%20Light%2002.xml new file mode 100644 index 0000000000..11772b4f05 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Jim%20Light%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.43948723673439005 + 0.49764935046544778 + 0.50246442938400904 + 1 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.18000000715255737 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00028125001798306321 + 0 + 0 + 1 + + distance_multiplier + + 6.3874998847643383 + 0 + 0 + 1 + + east_angle + 2.6515045166015625 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.4347999095916748 + 0 + 0 + 1 + + glow + + 20 + 0.0010000000474974513 + -0 + 1 + + haze_density + + 0.51583333298563971 + 0 + 0 + 1 + + haze_horizon + + 0.13833333183079954 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.46225041151046753 + 0.18866632878780365 + -0.86644649505615234 + 0 + + max_y + + 685.18749099969864 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 0.18980391323566437 + sunlight_color + + 0 + 3 + 1.5 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20July%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20July%20Light%2001.xml new file mode 100644 index 0000000000..88205d15c6 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20July%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.0448951721191406 + 1.0375124216079712 + 1.0410666465759277 + 0.34829840064048767 + + blue_density + + 0.15995600819587708 + 0.44843131303787231 + 0.76233971118927002 + 0.38116985559463501 + + blue_horizon + + 0.53291136026382446 + 0.47850862145423889 + 0.69532060623168945 + 0.34766030311584473 + + cloud_color + + 0.36694067716598511 + 0.36694067716598511 + 0.36694067716598511 + 0.36694067716598511 + + cloud_pos_density1 + + 0.59999996423721313 + 0.4699999988079071 + 0.99744760127569754 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999997638634312 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.206368064503224 + 10.010999679565662 + + cloud_shadow + + 0.48999997973442078 + 0 + 0 + 1 + + density_multiplier + + 0.00018935874525381486 + 0 + 0 + 1 + + distance_multiplier + + 0.84041139239945806 + 0 + 0 + 1 + + east_angle + 0.32672566175460815 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.0000211801171162 + 0.0010000000474974277 + -0.48000001234523038 + 1 + + haze_density + + 0.69659684739417083 + 0 + 0 + 1 + + haze_horizon + + 0.1893618953990921 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.27510377764701843 + 0.51503080129623413 + 0.81182581186294556 + 0 + + max_y + + 1582.8367459774017 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.54104357957839966 + sunlight_color + + 0.76900362968444824 + 0.8153645396232605 + 0.93126672506332397 + 0.31042224168777466 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20July%20Light%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20July%20Light%2002.xml new file mode 100644 index 0000000000..d385af5666 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20July%20Light%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.45899999141693115 + 0.3078000545501709 + 0.081000030040740967 + 0.15299999713897705 + + blue_density + + 0.97999995946884155 + 0.97999995946884155 + 0.97999995946884155 + 0.48999997973442078 + + blue_horizon + + 0.31999999284744263 + 0.31999999284744263 + 0.31999999284744263 + 0.15999999642372131 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.12459999322891235 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00040939997415989637 + 0 + 0 + 1 + + distance_multiplier + + 3.9000000953674316 + 0 + 0 + 1 + + east_angle + 2.2870795726776123 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3042999505996704 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.04999995231628418 + 1 + + haze_density + + 2.869999885559082 + 0 + 0 + 1 + + haze_horizon + + 0.5 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.71421909332275391 + 0.32145592570304871 + 0.62173730134963989 + 0 + + max_y + + 385 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 2.8143260478973389 + sunlight_color + + 2.0099999904632568 + 2.0099999904632568 + 2.0099999904632568 + 0.67000001668930054 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20July%20Light%2003.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20July%20Light%2003.xml new file mode 100644 index 0000000000..40ffdc4cdc --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20July%20Light%2003.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.56099998950958252 + 0.37620007991790771 + 0.099000021815299988 + 0.18699999153614044 + + blue_density + + 0.97999995946884155 + 0.97999995946884155 + 0.97999995946884155 + 0.48999997973442078 + + blue_horizon + + 0.31999999284744263 + 0.31999999284744263 + 0.31999999284744263 + 0.15999999642372131 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.12459999322891235 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.0004881999921053648 + 0 + 0 + 1 + + distance_multiplier + + 3.9000000953674316 + 0 + 0 + 1 + + east_angle + 2.2556638717651367 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3042999505996704 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.04999995231628418 + 1 + + haze_density + + 3.4800000190734863 + 0 + 0 + 1 + + haze_horizon + + 0.37000000476837158 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.72426009178161621 + 0.35430732369422913 + 0.59153497219085693 + 0 + + max_y + + 385 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 2.7794194221496582 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Landar%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Landar%20Light%2001.xml new file mode 100644 index 0000000000..30cdcd0a59 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Landar%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1.5 + 1.5 + 1.5 + 0.75 + + blue_horizon + + 1 + 1 + 1 + 0.5 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.95999997854232788 + 0.31000000238418579 + 0.34149998426437378 + 1 + + cloud_pos_density2 + + 1 + 1 + 0 + 1 + + cloud_scale + + 0.049599997699260712 + 0 + 0 + 1 + + cloud_scroll_rate + + 93.100006103515625 + -25.899993896484375 + + cloud_shadow + + 0.25999999046325684 + 0 + 0 + 1 + + density_multiplier + + 0.00018439999257680029 + 0 + 0 + 1 + + distance_multiplier + + 2.2000000476837158 + 0 + 0 + 1 + + east_angle + 3.1855752468109131 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 15.799999237060547 + 0.0010000000474974513 + -0.74999994039535522 + 1 + + haze_density + + 0.66999995708465576 + 0 + 0 + 1 + + haze_horizon + + 0.12999999523162842 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.040397927165031433 + 0.39473667740821838 + -0.91790574789047241 + 0 + + max_y + + 2231 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 500 + sun_angle + 0.40578123927116394 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20%20Gun%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20%20Gun%20Light.xml new file mode 100644 index 0000000000..add7359675 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20%20Gun%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.5 + 1.8999999761581421 + 3 + 1 + + blue_density + + 1.4579999446868896 + 0 + 0.82620006799697876 + 0.72899997234344482 + + blue_horizon + + 1.4579999446868896 + 0 + 0.7047005295753479 + 0.72899997234344482 + + cloud_color + + 0.37840613487830987 + 0.37840613487830987 + 0.37840613487830987 + 0.37840613487830987 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 0.99999998870089368 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999997841284203 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999837455794 + 10.01099967956543 + + cloud_shadow + + 0.48999997973442078 + 0 + 0 + 1 + + density_multiplier + + 3.6899997212458402e-005 + 0 + 0 + 1 + + distance_multiplier + + 75.200004577636719 + 0 + 0 + 1 + + east_angle + 6.2266373634338379 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.0434999465942383 + 0 + 0 + 1 + + glow + + 4.9999999435054558 + 0.0010000000474974513 + -0.4799999902127477 + 1 + + haze_density + + 0.34999999403953552 + 0 + 0 + 1 + + haze_horizon + + 1 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.045796267688274384 + 0.58601820468902588 + 0.80900269746780396 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.62613606452941895 + sunlight_color + + 1.4099999666213989 + 1.4099999666213989 + 1.4099999666213989 + 0.4699999988079071 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2001.xml new file mode 100644 index 0000000000..2a395d8bb0 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 2 + 2 + 2 + 1 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.0006399999838322401 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 3.1415927410125732 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.0199999809265137 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -2.5 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 1 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 4.8569567923095747e-008 + 0.83146905899047852 + -0.55557107925415039 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.98174667358398438 + sunlight_color + + 1.5 + 1.5 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2002.xml new file mode 100644 index 0000000000..dbb8405061 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 3 + 3 + 3 + 1 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density1 + + 0.29999998211860657 + 0.93999999761581421 + 0.75 + 1 + + cloud_pos_density2 + + 0.44999998807907104 + 0.35999998450279236 + 0.019999999552965164 + 1 + + cloud_scale + + 0.45999997854232788 + 0 + 0 + 1 + + cloud_scroll_rate + + 20 + 20 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00089999998454004526 + 0 + 0 + 1 + + distance_multiplier + + 0 + 0 + 0 + 1 + + east_angle + 6.2831854820251465 + enable_cloud_scroll + + 0 + 0 + + gamma + + 1.0099999904632568 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -2.5 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 1 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 6.3370464431500295e-008 + 0.93200832605361938 + -0.36243680119514465 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 24 + star_brightness + 2 + sun_angle + 1.941677451133728 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2003.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2003.xml new file mode 100644 index 0000000000..3b32f8dcf2 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2003.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.41796875 + 1.41796875 + 1.41796875 + 0.47265625 + + blue_density + + 0.12089811412885521 + 0.33770671695460663 + 0.67541757891583387 + 0.76708334654569654 + + blue_horizon + + 0.13497034943045882 + 0.26690842067701936 + 0.4016666400432598 + 0.74541666984558219 + + cloud_color + + 0.43948723673439005 + 0.49764935046544778 + 0.50246442938400904 + 1 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.15000000596046448 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0.12999999523162842 + 0 + 0 + 1 + + density_multiplier + + 0.00028125001798306321 + 0 + 0 + 1 + + distance_multiplier + + 6.3874998847643383 + 0 + 0 + 1 + + east_angle + 3.5185837745666504 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.0900000333786011 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.51583333298563971 + 0 + 0 + 1 + + haze_horizon + + 0.13833333183079954 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.28709480166435242 + 0.6259227991104126 + -0.72511875629425049 + 0 + + max_y + + 685.18749099969864 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 0.67631423473358154 + sunlight_color + + 2.44921875 + 2.44921875 + 2.44921875 + 0.81640625 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2004.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2004.xml new file mode 100644 index 0000000000..21cf058bf2 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2004.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.41796875 + 1.41796875 + 1.41796875 + 0.47265625 + + blue_density + + 0.12089811412885521 + 0.33770671695460663 + 0.67541757891583387 + 0.76708334654569654 + + blue_horizon + + 0.13497034943045882 + 0.26690842067701936 + 0.4016666400432598 + 0.74541666984558219 + + cloud_color + + 0.43948723673439005 + 0.49764935046544778 + 0.50246442938400904 + 1 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.15000000596046448 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0.12999999523162842 + 0 + 0 + 1 + + density_multiplier + + 0.00028125001798306321 + 0 + 0 + 1 + + distance_multiplier + + 6.3874998847643383 + 0 + 0 + 1 + + east_angle + 3.5185837745666504 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.0900000333786011 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.51583333298563971 + 0 + 0 + 1 + + haze_horizon + + 0.13833333183079954 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.28709480166435242 + 0.6259227991104126 + -0.72511875629425049 + 0 + + max_y + + 685.18749099969864 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 0.67631423473358154 + sunlight_color + + 1.078125 + 1.078125 + 1.078125 + 0.359375 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2005.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2005.xml new file mode 100644 index 0000000000..bb863523a0 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Light%2005.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 2 + 2 + 2 + 1 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00089999998454004526 + 0 + 0 + 1 + + distance_multiplier + + 22.5 + 0 + 0 + 1 + + east_angle + 3.1415927410125732 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.0199999809265137 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -2.5 + 1 + + haze_density + + 1.8199999332427979 + 0 + 0 + 1 + + haze_horizon + + 1 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 4.8569567923095747e-008 + 0.83146905899047852 + -0.55557107925415039 + 0 + + max_y + + 3533 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.98174667358398438 + sunlight_color + + 1.5 + 1.5 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Moves%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Moves%20Light.xml new file mode 100644 index 0000000000..38ca17aa60 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Moves%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0.39999997615814209 + 0.39999997615814209 + 0.39999997615814209 + 0.19999998807907104 + + blue_horizon + + 1 + 1 + 1 + 0.5 + + cloud_color + + 1 + 0.5 + 0 + 1 + + cloud_pos_density1 + + 1 + 0.65999996662139893 + 0.31099998950958252 + 1 + + cloud_pos_density2 + + 1 + 1 + 0 + 1 + + cloud_scale + + 0.042800001800060272 + 0 + 0 + 1 + + cloud_scroll_rate + + 15.309999465942383 + 14.079999923706055 + + cloud_shadow + + 0.40999999642372131 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 3.7824780941009521 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.26089999079704285 + 0 + 0 + 1 + + glow + + 0.59999942779541016 + 0.0010000000474974513 + -1.75 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 1 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.065092690289020538 + 0.99405622482299805 + -0.087264858186244965 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 2 + sun_angle + 1.4617122411727905 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Music%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Music%20Light%2001.xml new file mode 100644 index 0000000000..db2ba2d168 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Lo%20Music%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.15000000596046448 + 0.15000000596046448 + 0.15000000596046448 + 0.05000000074505806 + + blue_density + + 1 + 1 + 1 + 0.5 + + blue_horizon + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + cloud_color + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density1 + + 0.15999999642372131 + 0.50999999046325684 + 1 + 1 + + cloud_pos_density2 + + 1 + 0.50999999046325684 + 1 + 1 + + cloud_scale + + 0.059000000357627869 + 0 + 0 + 1 + + cloud_scroll_rate + + 14.409999847412109 + 4.7999997138977051 + + cloud_shadow + + 0.18999999761581421 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 51.200000762939453 + 0 + 0 + 1 + + east_angle + 1.9477875232696533 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.69569998979568481 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -2.5 + 1 + + haze_density + + 0.69999998807907104 + 0 + 0 + 1 + + haze_horizon + + 0.26999998092651367 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.62063354253768921 + 0.74460232257843018 + -0.24572627246379852 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 2 + sun_angle + 0.83993887901306152 + sunlight_color + + 1.5 + 1.5 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Mavi%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Mavi%20Light%2001.xml new file mode 100644 index 0000000000..ecae129257 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Mavi%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.1875 + 0.1875 + 0.1875 + 0.0625 + + blue_density + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + blue_horizon + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.70001220703125 + 10.01099967956543 + + cloud_shadow + + 0.44999998807907104 + 0 + 0 + 1 + + density_multiplier + + 0.00014170000213198364 + 0 + 0 + 1 + + distance_multiplier + + 7.9000000953674316 + 0 + 0 + 1 + + east_angle + 1.9477875232696533 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3999999761581421 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.66999995708465576 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.51655691862106323 + 0.83146905899047852 + -0.20451940596103668 + 0 + + max_y + + 21 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.98174667358398438 + sunlight_color + + 2.6999998092651367 + 2.6999998092651367 + 2.6999998092651367 + 0.89999997615814209 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Mavi%20Light%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Mavi%20Light%2002.xml new file mode 100644 index 0000000000..d0ba4bb023 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Mavi%20Light%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.1875 + 0.1875 + 0.1875 + 0.0625 + + blue_density + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + blue_horizon + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 0.99409997463226318 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.49579998850822449 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.70001220703125 + 10.01099967956543 + + cloud_shadow + + 0.29999998211860657 + 0 + 0 + 1 + + density_multiplier + + 0.00015750000602565706 + 0 + 0 + 1 + + distance_multiplier + + 4.5999999046325684 + 0 + 0 + 1 + + east_angle + 1.9477875232696533 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3999999761581421 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 1.7400000095367432 + 0 + 0 + 1 + + haze_horizon + + 0.070000000298023224 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.51655691862106323 + 0.83146905899047852 + -0.20451940596103668 + 0 + + max_y + + 11 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.98174667358398438 + sunlight_color + + 2.6999998092651367 + 2.6999998092651367 + 2.6999998092651367 + 0.89999997615814209 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Mavi%20Light%2003.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Mavi%20Light%2003.xml new file mode 100644 index 0000000000..ecae129257 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Mavi%20Light%2003.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.1875 + 0.1875 + 0.1875 + 0.0625 + + blue_density + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + blue_horizon + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.70001220703125 + 10.01099967956543 + + cloud_shadow + + 0.44999998807907104 + 0 + 0 + 1 + + density_multiplier + + 0.00014170000213198364 + 0 + 0 + 1 + + distance_multiplier + + 7.9000000953674316 + 0 + 0 + 1 + + east_angle + 1.9477875232696533 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3999999761581421 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.66999995708465576 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.51655691862106323 + 0.83146905899047852 + -0.20451940596103668 + 0 + + max_y + + 21 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.98174667358398438 + sunlight_color + + 2.6999998092651367 + 2.6999998092651367 + 2.6999998092651367 + 0.89999997615814209 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Me%20Love%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Me%20Love%20Light.xml new file mode 100644 index 0000000000..838e394cbe --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Me%20Love%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0.39999997615814209 + 0.39999997615814209 + 0.39999997615814209 + 0.19999998807907104 + + blue_horizon + + 1 + 1 + 1 + 0.5 + + cloud_color + + 1 + 0.5 + 0 + 1 + + cloud_pos_density1 + + 0.2800000011920929 + 0.31999999284744263 + 0.14019998908042908 + 1 + + cloud_pos_density2 + + 0.019999999552965164 + 0.45999997854232788 + 0 + 1 + + cloud_scale + + 0.018199998885393143 + 0 + 0 + 1 + + cloud_scroll_rate + + 15.309999465942383 + 14.079999923706055 + + cloud_shadow + + 1 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 3.7824780941009521 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.69569993019104 + 0 + 0 + 1 + + glow + + 0.59999942779541016 + 0.0010000000474974513 + -1.75 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 1 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.032595228403806686 + 0.99851292371749878 + -0.043697964400053024 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 2 + sun_angle + 1.5162535905838013 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Me%20Mine%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Me%20Mine%20Light.xml new file mode 100644 index 0000000000..155a8b9e47 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Me%20Mine%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.0799999237060547 + 0.98999994993209839 + 0.77999997138977051 + 1.0799999237060547 + + blue_density + + 0.64736837148666382 + 0.48414888978004456 + 0.81999999284744263 + 0.40999999642372131 + + blue_horizon + + 0.5 + 0.49548381567001343 + 0.45999997854232788 + 0.51999998092651367 + + cloud_color + + 0.4100000062111997 + 0.4100000062111997 + 0.4100000062111997 + 0.4100000062111997 + + cloud_pos_density1 + + 0.14000000059604645 + 0.62000000476837158 + 1 + 1 + + cloud_pos_density2 + + 0.35999998450279236 + 0.56999999284744263 + 0.12999999523162842 + 1 + + cloud_scale + + 0.35999998450279236 + 0 + 0 + 1.0000000149011612 + + cloud_scroll_rate + + 10.199999791580112 + 10.010999679880427 + + cloud_shadow + + 0.29999998211860657 + 0 + 0 + 1.0000000149011612 + + density_multiplier + + 7.9999997979030013e-005 + 0 + 0 + 1.0000000149011612 + + distance_multiplier + + 5.4000000953674316 + 0 + 0 + 1.0000000149011612 + + east_angle + 1.0932743549346924 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.1699998378753662 + 0 + 0 + 1.0000000149011612 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.55000001192092896 + 1 + + haze_density + + 0.31999999284744263 + 0 + 0 + 1 + + haze_horizon + + 0.17999999225139618 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.39627334475517273 + 0.89494067430496216 + -0.20505768060684204 + 0 + + max_y + + 805 + 0 + 0 + 1.0000000149011612 + + preset_num + 28 + star_brightness + 0.25999999046325684 + sun_angle + 2.0332944393157959 + sunlight_color + + 3 + 0 + 0 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Meni%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Meni%20Light%2001.xml new file mode 100644 index 0000000000..f308d292e8 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Meni%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.28464806749374816 + 0.45923502031814678 + 0.7409173846244812 + 0.7409173846244812 + + blue_density + + 0.25613615825332658 + 0.41819368084009056 + 0.6726322016895665 + 1 + + blue_horizon + + 2 + 1 + 0 + 1 + + cloud_color + + 0.52756190160579308 + 0.52756190160579308 + 0.52756190160579308 + 1 + + cloud_pos_density1 + + 0.72999995946884155 + 0.34000000357627869 + 0.32999998331069946 + 1 + + cloud_pos_density2 + + 0.28999999165534973 + 0.84999996423721313 + 0.019999999552965164 + 1 + + cloud_scale + + 0.32999998058761548 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.499399946934318 + 10.010999746491507 + + cloud_shadow + + 0.37000000476837158 + 0 + 0 + 1 + + density_multiplier + + 2.9999999242136255e-005 + 0 + 0 + 1 + + distance_multiplier + + 100 + 0 + 0 + 1 + + east_angle + 2.9530971050262451 + enable_cloud_scroll + + 0 + 0 + + gamma + + 3.0199999809265137 + 0 + 0 + 1 + + glow + + 0.79999923706054688 + 0.0010000000474974513 + -1.1999999284744263 + 1 + + haze_density + + 2.1499998569488525 + 0 + 0 + 1 + + haze_horizon + + 0.23999999463558197 + 0.19915598630905151 + 0.19915598630905151 + 1 + + lightnorm + + 0.12659277021884918 + 0.7372782826423645 + 0.66362255811691284 + 0 + + max_y + + 711.42973550362512 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 0 + sun_angle + 2.3125598430633545 + sunlight_color + + 0.62994743245872087 + 0.69737775977682759 + 0.86806544391379248 + 0.28935515608276319 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Miaa%20light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Miaa%20light%2001.xml new file mode 100644 index 0000000000..eedc74c889 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Miaa%20light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1 + 1 + 1 + 0.5 + + blue_horizon + + 1 + 1 + 1 + 0.5 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.76829999685287476 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.059000000357627869 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940033104544 + 10.011000058908452 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00025079998886212707 + 0 + 0 + 1 + + distance_multiplier + + 77.400001525878906 + 0 + 0 + 1 + + east_angle + 0.19477875530719757 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.5699999332427979 + 0 + 0 + 1 + + glow + + 16.80000114440918 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 1.1190000772476196 + 0 + 0 + 1 + + haze_horizon + + 0.17000000178813934 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.14745019376277924 + 0.64778679609298706 + 0.74741601943969727 + 0 + + max_y + + 2353 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 1.7856996059417725 + sun_angle + 0.70467567443847656 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2001.xml new file mode 100644 index 0000000000..e7fa44c7ee --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.20632287859916687 + 0.24516719579696655 + 0.33367714285850525 + 0.11122571676969528 + + blue_density + + 0.44999827251961821 + 0.44999970758411817 + 0.45000196070835302 + 1 + + blue_horizon + + 0.23999924952063895 + 0.23999984552653461 + 0.24000005119478959 + 1 + + cloud_color + + 0.22615400012094211 + 0.22615400012094211 + 0.22615400012094211 + 1 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 0.87999999801324269 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.0099999997764825821 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.499400180710069 + 10.01099976217745 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 8.9999994088429958e-005 + 0 + 0 + 1 + + distance_multiplier + + 41.100002288818359 + 0 + 0 + 1 + + east_angle + 1.5707963705062866 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.0000000000004476 + 0.0010000000424271499 + -0.47999998973471036 + 1 + + haze_density + + 0.20999999344348907 + 0 + 0 + 1 + + haze_horizon + + 0.20999999344348907 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.83147060871124268 + 0.55556869506835938 + -3.6344733445048405e-008 + 1 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 1.9999886751174927 + sun_angle + 3.7306394577026367 + sunlight_color + + 0.45637205243110657 + 0.46549969911575317 + 0.86362791061401367 + 0.28787598013877869 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2002.xml new file mode 100644 index 0000000000..99d59e5108 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.20405027270317078 + 0.24246673285961151 + 0.32999998331069946 + 0.10999999940395355 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density1 + + 0.12999999523162842 + 0.31999999284744263 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.74000000953674316 + 0.17999999225139618 + 1 + + cloud_scale + + 0.99999994039535522 + 0 + 0 + 1 + + cloud_scroll_rate + + 16.869998931884766 + 16.760000228881836 + + cloud_shadow + + 0.2199999988079071 + 0 + 0 + 1 + + density_multiplier + + 0.00032459996873512864 + 0 + 0 + 1 + + distance_multiplier + + 85.300003051757813 + 0 + 0 + 1 + + east_angle + 1.0807079076766968 + enable_cloud_scroll + + 0 + 0 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.1999998092651367 + 0.0010000000474974513 + -0.39999997615814209 + 1 + + haze_density + + 4 + 0 + 0 + 1 + + haze_horizon + + 0.019999999552965164 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.79044967889785767 + 0.44424447417259216 + -0.42170625925064087 + 1 + + max_y + + 303 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 2 + sun_angle + 5.8228545188903809 + sunlight_color + + 1.390916109085083 + 1.4052181243896484 + 2.0290837287902832 + 0.67636126279830933 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2003.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2003.xml new file mode 100644 index 0000000000..f6b4ddab89 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2003.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.38972097635269165 + 0.46309363842010498 + 0.63027900457382202 + 0.21009300649166107 + + blue_density + + 0.44999827251961821 + 0.44999970758411817 + 0.45000196070835302 + 1 + + blue_horizon + + 0.23999924952063895 + 0.23999984552653461 + 0.24000005119478959 + 1 + + cloud_color + + 0.22615400012094211 + 0.22615400012094211 + 0.22615400012094211 + 1 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 0.87999999801324269 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 3 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.499400180710069 + 10.01099976217745 + + cloud_shadow + + 0.22999998927116394 + 0 + 0 + 1 + + density_multiplier + + 8.9999994088429958e-005 + 0 + 0 + 1 + + distance_multiplier + + 41.100002288818359 + 0 + 0 + 1 + + east_angle + 2.8588495254516602 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.0000000000004476 + 0.0010000000424271499 + -0.47999998973471036 + 1 + + haze_density + + 0.20999999344348907 + 0 + 0 + 1 + + haze_horizon + + 0.20999999344348907 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.23529607057571411 + 0.53731352090835571 + 0.80989503860473633 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 500 + sun_angle + 2.5743441581726074 + sunlight_color + + 0.5808371901512146 + 0.59245419502258301 + 1.0991628170013428 + 0.36638760566711426 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2004.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2004.xml new file mode 100644 index 0000000000..76c2aed13d --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2004.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.20405027270317078 + 0.24246673285961151 + 0.32999998331069946 + 0.10999999940395355 + + blue_density + + 0.23251199722290039 + 0.23716199398040771 + 0.43999999761581421 + 0.2199999988079071 + + blue_horizon + + 0.23999999463558197 + 0.23999999463558197 + 0.23999999463558197 + 1 + + cloud_color + + 0.625 + 0.625 + 0.875 + 0.875 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 0.87999999523162842 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.17359998822212219 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.11999999731779099 + 0 + 0 + 1 + + density_multiplier + + 0.00033069998607970774 + 0 + 0 + 1 + + distance_multiplier + + 70.900001525878906 + 0 + 0 + 1 + + east_angle + 1.9666372537612915 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 1.5999999046325684 + 0 + 0 + 1 + + haze_horizon + + 0.019999999552965164 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.41169273853302002 + 0.89493530988693237 + 0.17204611003398895 + 1 + + max_y + + 308 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 2 + sun_angle + 5.1748991012573242 + sunlight_color + + 0.93348866701126099 + 0.95215761661529541 + 1.7665112018585205 + 0.58883708715438843 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2005.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2005.xml new file mode 100644 index 0000000000..496ab40eba --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2005.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.20405027270317078 + 0.24246673285961151 + 0.32999998331069946 + 0.10999999940395355 + + blue_density + + 0.23251199722290039 + 0.23716199398040771 + 0.43999999761581421 + 0.2199999988079071 + + blue_horizon + + 0.23999999463558197 + 0.23999999463558197 + 0.23999999463558197 + 1 + + cloud_color + + 0.625 + 0.625 + 0.875 + 0.875 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 0.87999999523162842 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.17359998822212219 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.11999999731779099 + 0 + 0 + 1 + + density_multiplier + + 0.00033069998607970774 + 0 + 0 + 1 + + distance_multiplier + + 70.900001525878906 + 0 + 0 + 1 + + east_angle + 2.3499114513397217 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.0899999141693115 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 1.5999999046325684 + 0 + 0 + 1 + + haze_horizon + + 0.019999999552965164 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.37705510854721069 + 0.84804928302764893 + 0.37234652042388916 + 1 + + max_y + + 308 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 2 + sun_angle + 5.2708921432495117 + sunlight_color + + 0.34876799583435059 + 0.50438410043716431 + 0.65999996662139893 + 0.2199999988079071 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2006.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2006.xml new file mode 100644 index 0000000000..7152527870 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2006.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.20632287859916687 + 0.24516719579696655 + 0.33367714285850525 + 0.11122571676969528 + + blue_density + + 0 + 0 + 1 + 0.5 + + blue_horizon + + 1 + 0.5 + 0 + 0.5 + + cloud_color + + 0.22615400012094211 + 0.22615400012094211 + 0.22615400012094211 + 1 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 0.87999999801324269 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.0099999997764825821 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.499400180710069 + 10.01099976217745 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00013000000035390258 + 0 + 0 + 1 + + distance_multiplier + + 20.200000762939453 + 0 + 0 + 1 + + east_angle + 1.5707963705062866 + enable_cloud_scroll + + 1 + 1 + + gamma + + 2.0199999809265137 + 0 + 0 + 1 + + glow + + 6.8000006675720215 + 0.0010000000474974513 + -0.69999998807907104 + 1 + + haze_density + + 1 + 0 + 0 + 1 + + haze_horizon + + 0.48999997973442078 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.85491305589675903 + 0.51877129077911377 + -3.7369435545997476e-008 + 1 + + max_y + + 1333 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 3.6870057582855225 + sunlight_color + + 0.45637205243110657 + 0.46549969911575317 + 0.86362791061401367 + 0.28787598013877869 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2007.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2007.xml new file mode 100644 index 0000000000..739c63c993 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2007.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.32094669342041016 + 0.38137125968933105 + 0.51905333995819092 + 0.17301777005195618 + + blue_density + + 0.44999827251961821 + 0.44999970758411817 + 0.45000196070835302 + 1 + + blue_horizon + + 0.23999924952063895 + 0.23999984552653461 + 0.24000005119478959 + 1 + + cloud_color + + 0.22615400012094211 + 0.22615400012094211 + 0.22615400012094211 + 1 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 0.87999999801324269 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 3 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.20001220703125 + 10.01099976217745 + + cloud_shadow + + 0.15999999642372131 + 0 + 0 + 1 + + density_multiplier + + 8.9999994088429958e-005 + 0 + 0 + 1 + + distance_multiplier + + 41.100002288818359 + 0 + 0 + 1 + + east_angle + 2.7646017074584961 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.0000000000004476 + 0.0010000000424271499 + -0.47999998973471036 + 1 + + haze_density + + 0.20999999344348907 + 0 + 0 + 1 + + haze_horizon + + 0.20999999344348907 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.31046971678733826 + 0.53731352090835571 + 0.78415733575820923 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 500 + sun_angle + 2.5743441581726074 + sunlight_color + + 0.6015813946723938 + 0.61361336708068848 + 1.1384185552597046 + 0.37947285175323486 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2008.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2008.xml new file mode 100644 index 0000000000..b0fad0999f --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Moon%20Light%2008.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.32094669342041016 + 0.38137125968933105 + 0.51905333995819092 + 0.17301777005195618 + + blue_density + + 0.44999827251961821 + 0.44999970758411817 + 0.45000196070835302 + 1 + + blue_horizon + + 0.23999924952063895 + 0.23999984552653461 + 0.24000005119478959 + 1 + + cloud_color + + 0.22615400012094211 + 0.22615400012094211 + 0.22615400012094211 + 1 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 0.87999999801324269 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 3 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.20001220703125 + 10.01099976217745 + + cloud_shadow + + 0.15999999642372131 + 0 + 0 + 1 + + density_multiplier + + 8.9999994088429958e-005 + 0 + 0 + 1 + + distance_multiplier + + 41.100002288818359 + 0 + 0 + 1 + + east_angle + 2.8588495254516602 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 5.0000000000004476 + 0.0010000000424271499 + -0.47999998973471036 + 1 + + haze_density + + 0.20999999344348907 + 0 + 0 + 1 + + haze_horizon + + 0.20999999344348907 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.23529607057571411 + 0.53731352090835571 + 0.80989503860473633 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 500 + sun_angle + 2.5743441581726074 + sunlight_color + + 0.6015813946723938 + 0.6136133074760437 + 1.1384185552597046 + 0.37947285175323486 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Never%20Night%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Never%20Night%20Light.xml new file mode 100644 index 0000000000..cc3e252454 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Never%20Night%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0.30000001192092896 + 0.10000000149011612 + + blue_density + + 0.12089811412885521 + 0.33770671695460663 + 0.67541757891583387 + 0.76708334654569654 + + blue_horizon + + 0.13497034943045882 + 0.26690842067701936 + 0.4016666400432598 + 0.74541666984558219 + + cloud_color + + 0.43948723673439005 + 0.49764935046544778 + 0.50246442938400904 + 1 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.18000000715255737 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 1 + 0 + 0 + 1 + + density_multiplier + + 0.00028125001798306321 + 0 + 0 + 1 + + distance_multiplier + + 6.3874998847643383 + 0 + 0 + 1 + + east_angle + 3.5185837745666504 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.12999999523162842 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.51583333298563971 + 0 + 0 + 1 + + haze_horizon + + 0.13833333183079954 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.28709480166435242 + 0.6259227991104126 + -0.72511875629425049 + 0 + + max_y + + 685.18749099969864 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 0.67631423473358154 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20No%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20No%20Light.xml new file mode 100644 index 0000000000..2ca2ef77b0 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20No%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0.12089811412885521 + 0.33770671695460663 + 0.67541757891583387 + 0.76708334654569654 + + blue_horizon + + 0.13497034943045882 + 0.26690842067701936 + 0.4016666400432598 + 0.74541666984558219 + + cloud_color + + 0.43948723673439005 + 0.49764935046544778 + 0.50246442938400904 + 1 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.18000000715255737 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00028125001798306321 + 0 + 0 + 1 + + distance_multiplier + + 6.3874998847643383 + 0 + 0 + 1 + + east_angle + 3.5185837745666504 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.0900000333786011 + 0 + 0 + 1 + + glow + + 9.4000005722045898 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.51583333298563971 + 0 + 0 + 1 + + haze_horizon + + 0.13833333183079954 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.28709480166435242 + 0.6259227991104126 + -0.72511875629425049 + 0 + + max_y + + 685.18749099969864 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0.1029166579246521 + sun_angle + 0.67631423473358154 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Owlery%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Owlery%20Light.xml new file mode 100644 index 0000000000..dca43b27f0 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Owlery%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.56250005960464478 + 0.26250001788139343 + 0.75 + 0.25 + + blue_density + + 0 + 0.40999585390090942 + 0.81999999284744263 + 0.85999995470046997 + + blue_horizon + + 0.43999999761581421 + 0.22910800576210022 + 0.26829266548156738 + 0.2199999988079071 + + cloud_color + + 0.23999999463558197 + 0.4699999988079071 + 0.31999999284744263 + 0.4699999988079071 + + cloud_pos_density1 + + 0.48999997973442078 + 0.50999999046325684 + 0.74000000953674316 + 1 + + cloud_pos_density2 + + 0.44999998807907104 + 0.5 + 0.14000000059604645 + 1 + + cloud_scale + + 0.0835999995470047 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00035999997635371983 + 0 + 0 + 1 + + distance_multiplier + + 2 + 0 + 0 + 1 + + east_angle + 1.3257522583007813 + enable_cloud_scroll + + 0 + 0 + + gamma + + 2.0299999713897705 + 0 + 0 + 1 + + glow + + 0.39999961853027344 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 0.77999997138977051 + 0 + 0 + 1 + + haze_horizon + + 0.15999999642372131 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.9694594144821167 + 0.037081710994243622 + -0.24243222177028656 + 0 + + max_y + + 591 + 0 + 0 + 1 + + preset_num + 18 + star_brightness + 1.0099999904632568 + sun_angle + 3.1045024394989014 + sunlight_color + + 2.5799999237060547 + 2.4411697387695313 + 2.4411697387695313 + 0.85999995470046997 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Puppy%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Puppy%20Light.xml new file mode 100644 index 0000000000..19151d34b5 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Puppy%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0.75 + 1.5 + 0.5 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0 + 0.79687601327896118 + 0.79687398672103882 + 0.39843800663948059 + + cloud_color + + 0.43948723673439005 + 0.49764935046544778 + 0.50246442938400904 + 1 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0 + 0 + 0 + 1 + + distance_multiplier + + 31.5 + 0 + 0 + 1 + + east_angle + 6.0507078170776367 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.4900000095367432 + 0 + 0 + 1 + + glow + + 4.8000001907348633 + 0.0010000000474974513 + -4.1499996185302734 + 1 + + haze_density + + 0.42999997735023499 + 0 + 0 + 1 + + haze_horizon + + 0.70999997854232788 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.15858890116214752 + 0.72537636756896973 + -0.66983485221862793 + 1 + + max_y + + 0 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 500 + sun_angle + 5.4716043472290039 + sunlight_color + + 0 + 1.5058825016021729 + 1.5058825016021729 + 0.50196081399917603 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Queen%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Queen%20Light%2001.xml new file mode 100644 index 0000000000..6db5852e70 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Queen%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.1875 + 0.1875 + 0.1875 + 0.0625 + + blue_density + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + blue_horizon + + 1.7999999523162842 + 1.7999999523162842 + 1.7999999523162842 + 0.89999997615814209 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.70001220703125 + 10.01099967956543 + + cloud_shadow + + 0.44999998807907104 + 0 + 0 + 1 + + density_multiplier + + 0.00014170000213198364 + 0 + 0 + 1 + + distance_multiplier + + 7.9000000953674316 + 0 + 0 + 1 + + east_angle + 1.9477875232696533 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3999999761581421 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.69999998807907104 + 0 + 0 + 1 + + haze_horizon + + 0.20999999344348907 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.51655691862106323 + 0.83146905899047852 + -0.20451940596103668 + 0 + + max_y + + 77 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.98174667358398438 + sunlight_color + + 2.6999998092651367 + 2.6999998092651367 + 2.6999998092651367 + 0.89999997615814209 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Quidditch%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Quidditch%20Light.xml new file mode 100644 index 0000000000..1e756c8f5e --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Quidditch%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.35999998450279236 + 0.21600005030632019 + 0 + 0.11999999731779099 + + blue_density + + 0.97999995946884155 + 0.97999995946884155 + 0.97999995946884155 + 0.48999997973442078 + + blue_horizon + + 0.31999999284744263 + 0.31999999284744263 + 0.31999999284744263 + 0.15999999642372131 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.12459999322891235 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.23999999463558197 + 0 + 0 + 1 + + density_multiplier + + 0.00031000000308267772 + 0 + 0 + 1 + + distance_multiplier + + 6.8000001907348633 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3042999505996704 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.33000001311302185 + 1 + + haze_density + + 1.8899999856948853 + 0 + 0 + 1 + + haze_horizon + + 0.23999999463558197 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.36227512359619141 + -0.93207120895385742 + 0 + + max_y + + 752 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 2.7708849906921387 + sunlight_color + + 1.3499999046325684 + 1.3499999046325684 + 1.3499999046325684 + 0.44999998807907104 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Save%20Me%20Light%20.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Save%20Me%20Light%20.xml new file mode 100644 index 0000000000..50fd94c0c0 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Save%20Me%20Light%20.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density1 + + 0.95999997854232788 + 0.31000000238418579 + 3 + 1 + + cloud_pos_density2 + + 1 + 1 + 0.5 + 1 + + cloud_scale + + 0.79339998960494995 + 0 + 0 + 1 + + cloud_scroll_rate + + 18.5 + -3 + + cloud_shadow + + 0.15999999642372131 + 0 + 0 + 1 + + density_multiplier + + 3.299999889350147e-006 + 0 + 0 + 1 + + distance_multiplier + + 0 + 0 + 0 + 1 + + east_angle + 3.1855752468109131 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1 + 0 + 0 + 1 + + glow + + 15.799999237060547 + 0.0010000000474974513 + -0.74999994039535522 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 4.8899998664855957 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.040397927165031433 + 0.39473667740821838 + -0.91790574789047241 + 0 + + max_y + + 385 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 500 + sun_angle + 0.40578123927116394 + sunlight_color + + 0 + 0 + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Shadow%20Testing%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Shadow%20Testing%20Light.xml new file mode 100644 index 0000000000..5b10b3dbea --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Shadow%20Testing%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0.24475815892219543 + 0.44872328639030457 + 0.75999999046325684 + 0.37999999523162842 + + blue_horizon + + 0.49548381567001343 + 0.49548381567001343 + 0.63999998569488525 + 0.31999999284744263 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00017999998817685992 + 0 + 0 + 1 + + distance_multiplier + + 0.80000001192092896 + 0 + 0 + 1 + + east_angle + 3.1415927410125732 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.3912999629974365 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.69999998807907104 + 0 + 0 + 1 + + haze_horizon + + 0.18999999761581421 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 7.923197387071923e-008 + 0.42261755466461182 + -0.90630811452865601 + 0 + + max_y + + 1605 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 0.43633154034614563 + sunlight_color + + 0 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Still%20Life.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Still%20Life.xml new file mode 100644 index 0000000000..f6d948d242 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Still%20Life.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.21000000834465027 + 0.21000000834465027 + 0.21000000834465027 + 0.070000000298023224 + + blue_density + + 0.97999995946884155 + 0.97999995946884155 + 0.97999995946884155 + 0.48999997973442078 + + blue_horizon + + 0.31999999284744263 + 0.31999999284744263 + 0.31999999284744263 + 0.15999999642372131 + + cloud_color + + 0.13600000739097595 + 0.17000001668930054 + 0.20399999618530273 + 0.20399999618530273 + + cloud_pos_density1 + + 0.42999997735023499 + 0.55000001192092896 + 0.83429998159408569 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.14000000059604645 + 1 + + cloud_scale + + 0.052799999713897705 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.21725988388061523 + 0 + 0 + 1 + + density_multiplier + + 0.00011869999434566125 + 0 + 0 + 1 + + distance_multiplier + + 25.700000762939453 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 0 + 0 + + gamma + + 2.2999999523162842 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + 0.39999961853027344 + 1 + + haze_density + + 0.1120000034570694 + 0 + 0 + 1 + + haze_horizon + + 0.44800001382827759 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.54830676317214966 + -0.8362773060798645 + 0 + + max_y + + 813 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 2.5612545013427734 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Thalia%20Light%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Thalia%20Light%2001.xml new file mode 100644 index 0000000000..099c6d4a1c --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Thalia%20Light%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1 + 1 + 1 + 0.5 + + blue_horizon + + 2 + 2 + 2 + 1 + + cloud_color + + 0.5 + 0.5 + 0.5 + 0.5 + + cloud_pos_density1 + + 0.5 + 0.5 + 0.76829999685287476 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.059000000357627869 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940033104544 + 10.011000058908452 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00020469998707994819 + 0 + 0 + 1 + + distance_multiplier + + 2.5 + 0 + 0 + 1 + + east_angle + 2.060884952545166 + enable_cloud_scroll + + 1 + 1 + + gamma + + 4.4000000953674316 + 0 + 0 + 1 + + glow + + 16.80000114440918 + 0.0010000000474974513 + -0.59999996423721313 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0.81999999284744263 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.77900981903076172 + 0.46948650479316711 + 0.41560328006744385 + 0 + + max_y + + 2538 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 1.7856996059417725 + sun_angle + 2.6528835296630859 + sunlight_color + + 3 + 3 + 3 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Thalia%20Light%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Thalia%20Light%2002.xml new file mode 100644 index 0000000000..9e05253dd1 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Thalia%20Light%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.54000002145767212 + 0.54000002145767212 + 0.54000002145767212 + 0.18000000715255737 + + blue_density + + 0.24475815892219543 + 0.44872328639030457 + 0.75999999046325684 + 0.37999999523162842 + + blue_horizon + + 0.49548381567001343 + 0.49548381567001343 + 0.63999998569488525 + 0.31999999284744263 + + cloud_color + + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + 0.40999999642372131 + + cloud_pos_density1 + + 1.6884100437164307 + 0.52609699964523315 + 1 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.125 + 1 + + cloud_scale + + 0.41999998688697815 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.199999809265137 + 10.01099967956543 + + cloud_shadow + + 0.26999998092651367 + 0 + 0 + 1 + + density_multiplier + + 0.00014999999257270247 + 0 + 0 + 1 + + distance_multiplier + + 0 + 0 + 0 + 1 + + east_angle + 0.9424777626991272 + enable_cloud_scroll + + 1 + 1 + + gamma + + 5.6700000762939453 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.47999998927116394 + 1 + + haze_density + + 0.28999999165534973 + 0 + 0 + 1 + + haze_horizon + + 0.20999999344348907 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.67267239093780518 + 0.55557155609130859 + -0.48872512578964233 + 0 + + max_y + + 1605 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 2.5525424480438232 + sunlight_color + + 0.81000006198883057 + 0.81000006198883057 + 0.81000006198883057 + 0.27000001072883606 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Trilogy%20Rain%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Trilogy%20Rain%2001.xml new file mode 100644 index 0000000000..cd69112074 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Trilogy%20Rain%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0.13497035205364227 + 0.26690840721130371 + 0.40166664123535156 + 0.20083332061767578 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.99999994039535522 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0.59999996423721313 + 0 + 0 + 1 + + density_multiplier + + 0.00011999999696854502 + 0 + 0 + 1 + + distance_multiplier + + 20.899999618530273 + 0 + 0 + 1 + + east_angle + 3.5185837745666504 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.2400000095367432 + 0 + 0 + 1 + + glow + + 1.399998664855957 + 0.0010000000474974513 + -0.44999998807907104 + 1 + + haze_density + + 0.84999996423721313 + 0 + 0 + 1 + + haze_horizon + + 0.40999999642372131 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.071817018091678619 + 0.9807855486869812 + 0.18138909339904785 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 1.7671444416046143 + sunlight_color + + 0.014999985694885254 + 1.0545001029968262 + 2.9850001335144043 + 0.99500000476837158 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Trilogy%20Rain%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Trilogy%20Rain%2002.xml new file mode 100644 index 0000000000..9b3f6d522d --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Trilogy%20Rain%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 0 + 0 + 0 + 0 + + blue_horizon + + 0.13497035205364227 + 0.26690840721130371 + 0.40166664123535156 + 0.20083332061767578 + + cloud_color + + 0 + 0 + 0 + 0 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.99999994039535522 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00014999999257270247 + 0 + 0 + 1 + + distance_multiplier + + 14 + 0 + 0 + 1 + + east_angle + 3.5185837745666504 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.2400000095367432 + 0 + 0 + 1 + + glow + + 1.399998664855957 + 0.0010000000474974513 + -2.2999999523162842 + 1 + + haze_density + + 3.6499998569488525 + 0 + 0 + 1 + + haze_horizon + + 0.75999999046325684 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.071817018091678619 + 0.9807855486869812 + 0.18138909339904785 + 0 + + max_y + + 4000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 0 + sun_angle + 1.7671444416046143 + sunlight_color + + 0.014999985694885254 + 1.0545001029968262 + 2.9850001335144043 + 0.99500000476837158 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20White%20Fire%20Sky%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20White%20Fire%20Sky%2001.xml new file mode 100644 index 0000000000..df2feee226 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20White%20Fire%20Sky%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.38999998569488525 + 0.38999998569488525 + 0.38999998569488525 + 0.12999999523162842 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.78999996185302734 + 0.90999996662139893 + 0.11589999496936798 + 1 + + cloud_pos_density2 + + 1 + 1 + 0 + 1 + + cloud_scale + + 0.026499999687075615 + 0 + 0 + 1 + + cloud_scroll_rate + + 17.770000457763672 + 4.4699997901916504 + + cloud_shadow + + 1 + 0 + 0 + 1 + + density_multiplier + + 0.00033199999597854912 + 0 + 0 + 1 + + distance_multiplier + + 0 + 0 + 0 + 1 + + east_angle + 2.7457520961761475 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.057900000363588333 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.14999999105930328 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.18987095355987549 + 0.87035512924194336 + -0.45434671640396118 + 0 + + max_y + + 2758 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 2 + sun_angle + 1.0559231042861938 + sunlight_color + + 2.6999998092651367 + 2.6999998092651367 + 2.6999998092651367 + 0.89999997615814209 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20White%20Fire%20Sky%2002.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20White%20Fire%20Sky%2002.xml new file mode 100644 index 0000000000..85dd157571 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20White%20Fire%20Sky%2002.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.38999998569488525 + 0.38999998569488525 + 0.38999998569488525 + 0.12999999523162842 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.78999996185302734 + 0.90999996662139893 + 0.23999999463558197 + 1 + + cloud_pos_density2 + + 1 + 1 + 0 + 1 + + cloud_scale + + 0.4681999683380127 + 0 + 0 + 1 + + cloud_scroll_rate + + 17.770000457763672 + 4.4699997901916504 + + cloud_shadow + + 0.75 + 0 + 0 + 1 + + density_multiplier + + 0.00033199999597854912 + 0 + 0 + 1 + + distance_multiplier + + 0 + 0 + 0 + 1 + + east_angle + 2.7457520961761475 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.057900000363588333 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.14999999105930328 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.18987095355987549 + 0.87035512924194336 + -0.45434671640396118 + 0 + + max_y + + 2758 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 2 + sun_angle + 1.0559231042861938 + sunlight_color + + 2.6999998092651367 + 2.6999998092651367 + 2.6999998092651367 + 0.89999997615814209 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20White%20Fire%20Sky%2003.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20White%20Fire%20Sky%2003.xml new file mode 100644 index 0000000000..9dbfd2a7d3 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20White%20Fire%20Sky%2003.xml @@ -0,0 +1,141 @@ + + + ambient + + 1.4399999380111694 + 1.4399999380111694 + 1.4399999380111694 + 0.47999998927116394 + + blue_density + + 2 + 2 + 2 + 1 + + blue_horizon + + 0 + 0 + 0 + 0 + + cloud_color + + 1 + 1 + 1 + 1 + + cloud_pos_density1 + + 0.78999996185302734 + 0.90999996662139893 + 0.11589999496936798 + 1 + + cloud_pos_density2 + + 1 + 1 + 0 + 1 + + cloud_scale + + 0.024799998849630356 + 0 + 0 + 1 + + cloud_scroll_rate + + 17.770000457763672 + 4.4699997901916504 + + cloud_shadow + + 1 + 0 + 0 + 1 + + density_multiplier + + 0.00033069998607970774 + 0 + 0 + 1 + + distance_multiplier + + 31.5 + 0 + 0 + 1 + + east_angle + 2.7457520961761475 + enable_cloud_scroll + + 1 + 1 + + gamma + + 0.18999999761581421 + 0 + 0 + 1 + + glow + + 0.19999980926513672 + 0.0010000000474974513 + -0.14999999105930328 + 1 + + haze_density + + 0 + 0 + 0 + 1 + + haze_horizon + + 0 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + -0.18987095355987549 + 0.87035512924194336 + -0.45434671640396118 + 0 + + max_y + + 3000 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 500 + sun_angle + 1.0559231042861938 + sunlight_color + + 2.6999998092651367 + 2.6999998092651367 + 2.6999998092651367 + 0.89999997615814209 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20Yellow%20Stars%2001.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Yellow%20Stars%2001.xml new file mode 100644 index 0000000000..778c1c58b1 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20Yellow%20Stars%2001.xml @@ -0,0 +1,141 @@ + + + ambient + + 0 + 0 + 0 + 0 + + blue_density + + 1 + 1 + 2 + 1 + + blue_horizon + + 1.2800000905990601 + 1.2799999713897705 + 0 + 0.64000004529953003 + + cloud_color + + 0.43948723673439005 + 0.49764935046544778 + 0.50246442938400904 + 1 + + cloud_pos_density1 + + 0.57999998331069946 + 0.87000000476837158 + 0.75 + 1 + + cloud_pos_density2 + + 1.6884100437164307 + 0.52609699964523315 + 0.073541670078411725 + 1 + + cloud_scale + + 0.18000000715255737 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.088005410620646 + 10.010458310484864 + + cloud_shadow + + 0 + 0 + 0 + 1 + + density_multiplier + + 0.00033069998607970774 + 0 + 0 + 1 + + distance_multiplier + + -13761.5 + 0 + 0 + 1 + + east_angle + 3.5185837745666504 + enable_cloud_scroll + + 1 + 1 + + gamma + + 1.0900000333786011 + 0 + 0 + 1 + + glow + + 3.0000019073486328 + 0.0010000000474974513 + 10 + 1 + + haze_density + + 4.7799997329711914 + 0 + 0 + 1 + + haze_horizon + + 0.34999999403953552 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0.26703047752380371 + 0.68834781646728516 + -0.67444199323654175 + 0 + + max_y + + 5691 + 0 + 0 + 1 + + preset_num + 22 + star_brightness + 500 + sun_angle + 0.75920891761779785 + sunlight_color + + 3 + 3 + 1.5 + 1 + + + diff --git a/indra/newview/app_settings/windlight/skies/Phototools%2D%20rara%20Fall%20Home%20Light.xml b/indra/newview/app_settings/windlight/skies/Phototools%2D%20rara%20Fall%20Home%20Light.xml new file mode 100644 index 0000000000..466de5aae8 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/Phototools%2D%20rara%20Fall%20Home%20Light.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.42000001668930054 + 0.42000001668930054 + 0.42000001668930054 + 0.14000000059604645 + + blue_density + + 0.97999995946884155 + 0.97999995946884155 + 0.97999995946884155 + 0.48999997973442078 + + blue_horizon + + 0.31999999284744263 + 0.31999999284744263 + 0.31999999284744263 + 0.15999999642372131 + + cloud_color + + 0.50999999046325684 + 0.50999999046325684 + 0.50999999046325684 + 1 + + cloud_pos_density1 + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.079999998211860657 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.25999999046325684 + 0 + 0 + 1 + + density_multiplier + + 7.8699995356146246e-005 + 0 + 0 + 1 + + distance_multiplier + + 79.5 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 3.809999942779541 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + 0.39999961853027344 + 1 + + haze_density + + 0.22400000691413879 + 0 + 0 + 1 + + haze_horizon + + 0.67200005054473877 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.17796146869659424 + -0.98403745889663696 + 0 + + max_y + + 813 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 2.9626781940460205 + sunlight_color + + 1.3799998760223389 + 1.3799998760223389 + 1.3799998760223389 + 0.45999997854232788 + + + diff --git a/indra/newview/app_settings/windlight/skies/wastelands%20bright.xml b/indra/newview/app_settings/windlight/skies/wastelands%20bright.xml new file mode 100644 index 0000000000..b9cfd7dfb9 --- /dev/null +++ b/indra/newview/app_settings/windlight/skies/wastelands%20bright.xml @@ -0,0 +1,141 @@ + + + ambient + + 0.29999998211860657 + 0.17999999225139618 + 0 + 0.29999998211860657 + + blue_density + + 0.97999995946884155 + 0.97999995946884155 + 0.97999995946884155 + 0.48999997973442078 + + blue_horizon + + 0.31999999284744263 + 0.31999999284744263 + 0.31999999284744263 + 0.15999999642372131 + + cloud_color + + 0.50999999046325684 + 0.50999999046325684 + 0.50999999046325684 + 1 + + cloud_pos_density1 + + 0.5 + 0.5 + 1 + 1 + + cloud_pos_density2 + + 0.5 + 0.5 + 0.125 + 1 + + cloud_scale + + 0.079999998211860657 + 0 + 0 + 1 + + cloud_scroll_rate + + 10.49940013885498 + 10.01099967956543 + + cloud_shadow + + 0.25999999046325684 + 0 + 0 + 1 + + density_multiplier + + 0.00031000000308267772 + 0 + 0 + 1 + + distance_multiplier + + 6.8000001907348633 + 0 + 0 + 1 + + east_angle + 0 + enable_cloud_scroll + + 1 + 1 + + gamma + + 3 + 0 + 0 + 1 + + glow + + 5 + 0.0010000000474974513 + -0.33000001311302185 + 1 + + haze_density + + 1.8899999856948853 + 0 + 0 + 1 + + haze_horizon + + 0.23999999463558197 + 0.19915600121021271 + 0.19915600121021271 + 1 + + lightnorm + + 0 + 0.36227512359619141 + -0.93207120895385742 + 0 + + max_y + + 752 + 0 + 0 + 1 + + preset_num + 21 + star_brightness + 0 + sun_angle + 2.7708849906921387 + sunlight_color + + 1.3799998760223389 + 1.3799998760223389 + 1.3799998760223389 + 0.45999997854232788 + + + diff --git a/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Default%20%2B%20Texture.xml b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Default%20%2B%20Texture.xml new file mode 100644 index 0000000000..b945a41d83 --- /dev/null +++ b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Default%20%2B%20Texture.xml @@ -0,0 +1,43 @@ + + + blurMultiplier + 0.01000000070780515670776367 + fresnelOffset + 0.5 + fresnelScale + 0.5 + normScale + + 4 + 4 + 1 + + normalMap + 7f132b94-6c9c-5af3-5a17-3412ad653da0 + scaleAbove + 0.02999999932944774627685547 + scaleBelow + 0.2000000029802322387695313 + underWaterFogMod + 0.66999995708465576171875 + waterFogColor + + 0.1960784494876861572265625 + 0.2196078598499298095703125 + 0.1764705926179885864257813 + 1 + + waterFogDensity + 103.96833038330078125 + wave1Dir + + -0.25 + 0 + + wave2Dir + + -1 + 0 + + + diff --git a/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Default.xml b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Default.xml new file mode 100644 index 0000000000..1c443156c8 --- /dev/null +++ b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Default.xml @@ -0,0 +1,43 @@ + + + blurMultiplier + 0.04500000178813934326171875 + fresnelOffset + 0.5 + fresnelScale + 0.5 + normScale + + 1.10000002384185791015625 + 1 + 1 + + normalMap + 822ded49-9a6c-f61c-cb89-6df54f42cdf4 + scaleAbove + 0.02999999932944774627685547 + scaleBelow + 0.2000000029802322387695313 + underWaterFogMod + 0.66999995708465576171875 + waterFogColor + + 0.199999988079071044921875 + 0.2199999988079071044921875 + 0.1799999773502349853515625 + 1 + + waterFogDensity + 103.96833038330078125 + wave1Dir + + -1 + 0 + + wave2Dir + + -1 + 0 + + + diff --git a/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ice.xml b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ice.xml new file mode 100644 index 0000000000..a5cdf76ae2 --- /dev/null +++ b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ice.xml @@ -0,0 +1,43 @@ + + + blurMultiplier + 0.1600000113248825073242188 + fresnelOffset + 0.5 + fresnelScale + 1 + normScale + + 5 + 5 + 5 + + normalMap + f92da839-f302-c813-668d-601ab1957af1 + scaleAbove + 0.199999988079071044921875 + scaleBelow + 0.2000000029802322387695313 + underWaterFogMod + 1 + waterFogColor + + 0.02851562201976776123046875 + 0.07148437201976776123046875 + 0.06242064759135246276855469 + 1 + + waterFogDensity + 2 + wave1Dir + + 0 + 0 + + wave2Dir + + 0 + 0 + + + diff --git a/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ocean%20%2B%20Texture.xml b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ocean%20%2B%20Texture.xml new file mode 100644 index 0000000000..edd3e9a97a --- /dev/null +++ b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ocean%20%2B%20Texture.xml @@ -0,0 +1,43 @@ + + + blurMultiplier + 0.05000000074505805969238281 + fresnelOffset + 0.5 + fresnelScale + 0.5 + normScale + + 5 + 5 + 5 + + normalMap + 7f132b94-6c9c-5af3-5a17-3412ad653da0 + scaleAbove + 0.04999999701976776123046875 + scaleBelow + 0.2000000029802322387695313 + underWaterFogMod + 1 + waterFogColor + + 0.194549560546875 + 0.602325439453125 + 0.50675296783447265625 + 1 + + waterFogDensity + 8 + wave1Dir + + -0.1000001430511474609375 + -0.1000001430511474609375 + + wave2Dir + + -0.5 + -0.5 + + + diff --git a/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ocean%202%20%2B%20Texture.xml b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ocean%202%20%2B%20Texture.xml new file mode 100644 index 0000000000..5eaa008459 --- /dev/null +++ b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ocean%202%20%2B%20Texture.xml @@ -0,0 +1,43 @@ + + + blurMultiplier + 0.005000000353902578353881836 + fresnelOffset + 0.599999964237213134765625 + fresnelScale + 0.2999999821186065673828125 + normScale + + 1 + 1 + 1 + + normalMap + 7f132b94-6c9c-5af3-5a17-3412ad653da0 + scaleAbove + 0.02999999932944774627685547 + scaleBelow + 0.2000000029802322387695313 + underWaterFogMod + 0.5 + waterFogColor + + 0.1882353127002716064453125 + 0.2509804069995880126953125 + 0.3137255012989044189453125 + 1 + + waterFogDensity + 32 + wave1Dir + + -0.5 + 0 + + wave2Dir + + -2 + 0 + + + diff --git a/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ocean%202.xml b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ocean%202.xml new file mode 100644 index 0000000000..6866eacad7 --- /dev/null +++ b/indra/newview/app_settings/windlight/water/%5BPyFX%5D%20Ocean%202.xml @@ -0,0 +1,43 @@ + + + blurMultiplier + 0.04500000178813934326171875 + fresnelOffset + 0.599999964237213134765625 + fresnelScale + 0.2999999821186065673828125 + normScale + + 1 + 1 + 1 + + normalMap + 822ded49-9a6c-f61c-cb89-6df54f42cdf4 + scaleAbove + 0.02999999932944774627685547 + scaleBelow + 0.2000000029802322387695313 + underWaterFogMod + 0.5 + waterFogColor + + 0.1882353127002716064453125 + 0.2509804069995880126953125 + 0.3137255012989044189453125 + 1 + + waterFogDensity + 32 + wave1Dir + + -2 + 0 + + wave2Dir + + -4 + 0 + + + diff --git a/indra/newview/app_settings/windlight/water/Phototools%2D%20Black%20Default%20.xml b/indra/newview/app_settings/windlight/water/Phototools%2D%20Black%20Default%20.xml new file mode 100644 index 0000000000..31cc985809 --- /dev/null +++ b/indra/newview/app_settings/windlight/water/Phototools%2D%20Black%20Default%20.xml @@ -0,0 +1,43 @@ + + + blurMultiplier + 0.060000002384185791 + fresnelOffset + 0.56000000238418579 + fresnelScale + 1 + normScale + + 10 + 10 + 10 + + normalMap + 822ded49-9a6c-f61c-cb89-6df54f42cdf4 + scaleAbove + 0.029999999329447746 + scaleBelow + 0.20000000298023224 + underWaterFogMod + 0.25 + waterFogColor + + 0 + 0 + 0 + 1 + + waterFogDensity + 16 + wave1Dir + + 1.0499997138977051 + -0.42000007629394531 + + wave2Dir + + 1.1099996566772461 + -1.1600000858306885 + + + diff --git a/indra/newview/app_settings/windlight/water/Phototools%2D%20Breakwave%20Building%20Water.xml b/indra/newview/app_settings/windlight/water/Phototools%2D%20Breakwave%20Building%20Water.xml new file mode 100644 index 0000000000..2c5596edb1 --- /dev/null +++ b/indra/newview/app_settings/windlight/water/Phototools%2D%20Breakwave%20Building%20Water.xml @@ -0,0 +1,43 @@ + + + blurMultiplier + 0.040000002831220627 + fresnelOffset + 0.5 + fresnelScale + 0.39999997615814209 + normScale + + 2 + 2 + 2 + + normalMap + 822ded49-9a6c-f61c-cb89-6df54f42cdf4 + scaleAbove + 0.029999999329447746 + scaleBelow + 0.20000000298023224 + underWaterFogMod + 0.25 + waterFogColor + + 0 + 0 + 0 + 1 + + waterFogDensity + 16 + wave1Dir + + 1.0499997138977051 + -0.42000007629394531 + + wave2Dir + + 1.1099996566772461 + -1.1600000858306885 + + + diff --git a/indra/newview/app_settings/windlight/water/Phototools%2D%20Chandra%20Sea.xml b/indra/newview/app_settings/windlight/water/Phototools%2D%20Chandra%20Sea.xml new file mode 100644 index 0000000000..93989f25b4 --- /dev/null +++ b/indra/newview/app_settings/windlight/water/Phototools%2D%20Chandra%20Sea.xml @@ -0,0 +1,43 @@ + + + blurMultiplier + 0.040000002831220627 + fresnelOffset + 0.55000001192092896 + fresnelScale + 0.62999999523162842 + normScale + + 0 + 0.60000002384185791 + 4.7000002861022949 + + normalMap + 822ded49-9a6c-f61c-cb89-6df54f42cdf4 + scaleAbove + 0 + scaleBelow + 0 + underWaterFogMod + 0.5 + waterFogColor + + 0.19140625 + 0.19140625 + 0.19140625 + 1 + + waterFogDensity + 6.9644041061401367 + wave1Dir + + -0.34000015258789063 + -0.19000005722045898 + + wave2Dir + + -1.4000000953674316 + -0.98000001907348633 + + + diff --git a/indra/newview/app_settings/windlight/water/Phototools%2D%20Gallery%20Water%2001.xml b/indra/newview/app_settings/windlight/water/Phototools%2D%20Gallery%20Water%2001.xml new file mode 100644 index 0000000000..d3cf6f6d8f --- /dev/null +++ b/indra/newview/app_settings/windlight/water/Phototools%2D%20Gallery%20Water%2001.xml @@ -0,0 +1,43 @@ + + + blurMultiplier + 0.040000002831220627 + fresnelOffset + 0.5 + fresnelScale + 0.39999997615814209 + normScale + + 2 + 2 + 2 + + normalMap + 822ded49-9a6c-f61c-cb89-6df54f42cdf4 + scaleAbove + 0.029999999329447746 + scaleBelow + 0.20000000298023224 + underWaterFogMod + 0.25 + waterFogColor + + 0 + 0 + 0 + 1 + + waterFogDensity + 16 + wave1Dir + + 0.529998779296875 + -0.21000099182128906 + + wave2Dir + + 0.55999946594238281 + -0.57999992370605469 + + + diff --git a/indra/newview/app_settings/windlight/water/Phototools%2D%20Ship%20Light.xml b/indra/newview/app_settings/windlight/water/Phototools%2D%20Ship%20Light.xml new file mode 100644 index 0000000000..6a4708dac9 --- /dev/null +++ b/indra/newview/app_settings/windlight/water/Phototools%2D%20Ship%20Light.xml @@ -0,0 +1,43 @@ + + + blurMultiplier + 0.040000002831220627 + fresnelOffset + 0.5899999737739563 + fresnelScale + 0.22999998927116394 + normScale + + 1.3000000715255737 + 5.0999999046325684 + 2.2999999523162842 + + normalMap + 822ded49-9a6c-f61c-cb89-6df54f42cdf4 + scaleAbove + 0 + scaleBelow + 0 + underWaterFogMod + 0.5 + waterFogColor + + 0 + 0 + 0 + 1 + + waterFogDensity + 6.9644041061401367 + wave1Dir + + -0.34000015258789063 + -0.19000005722045898 + + wave2Dir + + -1.4000000953674316 + -0.98000001907348633 + + + diff --git a/indra/newview/ascentprefschat.cpp b/indra/newview/ascentprefschat.cpp index aacfe68267..25d1964352 100644 --- a/indra/newview/ascentprefschat.cpp +++ b/indra/newview/ascentprefschat.cpp @@ -69,27 +69,11 @@ LLPrefsAscentChat::LLPrefsAscentChat() autoresponse->setToolTip(LLTrans::getString("NotLoggedIn")); } - // Saved per account settings aren't detected by control_name, therefore autoresponse controls get their values here and have them saved during apply. - childSetValue("AscentInstantMessageResponseRepeat", gSavedPerAccountSettings.getBOOL("AscentInstantMessageResponseRepeat")); - childSetValue("AutoresponseAnyone", gSavedPerAccountSettings.getBOOL("AutoresponseAnyone")); - childSetValue("AutoresponseAnyoneFriendsOnly", gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneFriendsOnly")); - childSetValue("AutoresponseAnyoneItem", gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneItem")); - childSetValue("AutoresponseAnyoneMessage", gSavedPerAccountSettings.getString("AutoresponseAnyoneMessage")); - childSetValue("AutoresponseAnyoneShow", gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneShow")); - childSetValue("AutoresponseNonFriends", gSavedPerAccountSettings.getBOOL("AutoresponseNonFriends")); - childSetValue("AutoresponseNonFriendsItem", gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsItem")); - childSetValue("AutoresponseNonFriendsMessage", gSavedPerAccountSettings.getString("AutoresponseNonFriendsMessage")); - childSetValue("AutoresponseNonFriendsShow", gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsShow")); - childSetValue("AutoresponseMuted", gSavedPerAccountSettings.getBOOL("AutoresponseMuted")); - childSetValue("AutoresponseMutedItem", gSavedPerAccountSettings.getBOOL("AutoresponseMutedItem")); - childSetValue("AutoresponseMutedMessage", gSavedPerAccountSettings.getString("AutoresponseMutedMessage")); - childSetValue("AutoresponseMutedShow", gSavedPerAccountSettings.getBOOL("AutoresponseMutedShow")); - childSetValue("BusyModeResponse", gSavedPerAccountSettings.getString("BusyModeResponse")); - childSetValue("BusyModeResponseItem", gSavedPerAccountSettings.getBOOL("BusyModeResponseItem")); - childSetValue("BusyModeResponseShow", gSavedPerAccountSettings.getBOOL("BusyModeResponseShow")); - childSetEnabled("reset_antispam", started); - getChild("reset_antispam")->setCommitCallback(boost::bind(NACLAntiSpamRegistry::purgeAllQueues)); + getChild("reset_antispam")->setCommitCallback([](LLUICtrl* ctrl, const LLSD& param) { + if (auto inst = NACLAntiSpamRegistry::getIfExists()) + inst->resetQueues(); + }); getChild("autoreplace")->setCommitCallback(boost::bind(LLFloaterAutoReplaceSettings::showInstance, LLSD())); getChild("KeywordsOn")->setCommitCallback(boost::bind(&LLPrefsAscentChat::onCommitKeywords, this, _1)); @@ -131,57 +115,75 @@ void LLPrefsAscentChat::onSpellBaseComboBoxCommit(const LLSD& value) glggHunSpell->newDictSelection(value.asString()); } +void setTimeDateFormats(const S8& tempTimeFormat, const S8& tempDateFormat) +{ + std::string short_date, long_date, short_time, long_time, timestamp; + + if (tempDateFormat != -1) + { + if (tempDateFormat < 3) + { + short_date = !tempDateFormat ? "%F" : + tempDateFormat == 1 ? "%Y/%m/%d" : + "%d/%m/%Y"; + long_date = "%A, %d %B %Y"; + timestamp = "%a %d %b %Y"; + } + else + { + short_date = "%m/%d/%Y"; + long_date = "%A, %B %d %Y"; + timestamp = "%a %b %d %Y"; + } + } + + if (tempTimeFormat != -1) + { + if (tempTimeFormat == 0) + { + short_time = "%R"; + long_time = "%T"; + if (!timestamp.empty()) timestamp += " %T"; + } + else + { + short_time = "%I:%M %p"; + long_time = "%I:%M:%S %p"; + if (!timestamp.empty()) timestamp += " %I:%M %p"; + } + } + else if (!timestamp.empty()) + { + timestamp += ' ' + gSavedSettings.getString("ShortTimeFormat"); + } + + if (!short_date.empty()) + { + gSavedSettings.setString("ShortDateFormat", short_date); + gSavedSettings.setString("LongDateFormat", long_date); + } + if (!short_time.empty()) + { + gSavedSettings.setString("ShortTimeFormat", short_time); + gSavedSettings.setString("LongTimeFormat", long_time); + } + if (!timestamp.empty()) + gSavedSettings.setString("TimestampFormat", timestamp); +} + void LLPrefsAscentChat::onCommitTimeDate(LLUICtrl* ctrl) { LLComboBox* combo = static_cast(ctrl); - if (ctrl->getName() == "time_format_combobox") - { + if (ctrl->getName() == "time_format_combobox") + { tempTimeFormat = combo->getCurrentIndex(); - } - else if (ctrl->getName() == "date_format_combobox") - { + } + else if (ctrl->getName() == "date_format_combobox") + { tempDateFormat = combo->getCurrentIndex(); - } - - std::string short_date, long_date, short_time, long_time, timestamp; - - if (tempTimeFormat == 0) - { - short_time = "%H:%M"; - long_time = "%H:%M:%S"; - timestamp = " %H:%M:%S"; - } - else - { - short_time = "%I:%M %p"; - long_time = "%I:%M:%S %p"; - timestamp = " %I:%M %p"; - } - - if (tempDateFormat == 0) - { - short_date = "%Y-%m-%d"; - long_date = "%A %d %B %Y"; - timestamp = "%a %d %b %Y" + timestamp; - } - else if (tempDateFormat == 1) - { - short_date = "%d/%m/%Y"; - long_date = "%A %d %B %Y"; - timestamp = "%a %d %b %Y" + timestamp; - } - else - { - short_date = "%m/%d/%Y"; - long_date = "%A, %B %d %Y"; - timestamp = "%a %b %d %Y" + timestamp; - } + } - gSavedSettings.setString("ShortDateFormat", short_date); - gSavedSettings.setString("LongDateFormat", long_date); - gSavedSettings.setString("ShortTimeFormat", short_time); - gSavedSettings.setString("LongTimeFormat", long_time); - gSavedSettings.setString("TimestampFormat", timestamp); + setTimeDateFormats(tempTimeFormat, tempDateFormat); } void LLPrefsAscentChat::onCommitKeywords(LLUICtrl* ctrl) @@ -227,28 +229,16 @@ void LLPrefsAscentChat::refreshValues() mSecondsInLog = gSavedSettings.getBOOL("SecondsInLog"); std::string format = gSavedSettings.getString("ShortTimeFormat"); - if (format.find("%p") == std::string::npos) - { - mTimeFormat = 0; - } - else - { - mTimeFormat = 1; - } + mTimeFormat = format == "%R" ? 0 + : format == "%I:%M %p" ? 1 + : -1; format = gSavedSettings.getString("ShortDateFormat"); - if (format.find("%m/%d/%") != std::string::npos) - { - mDateFormat = 2; - } - else if (format.find("%d/%m/%") != -1) - { - mDateFormat = 1; - } - else - { - mDateFormat = 0; - } + mDateFormat = format == "%F" ? 0 : + format == "%Y/%m/%d" ? 1 : + format == "%d/%m/%Y" ? 2 : + format == "%m/%d/%Y" ? 3 : + -1; tempTimeFormat = mTimeFormat; tempDateFormat = mDateFormat; @@ -270,32 +260,33 @@ void LLPrefsAscentChat::refreshValues() mFriendNames = gSavedSettings.getS32("FriendNameSystem"); mGroupMembersNames = gSavedSettings.getS32("GroupMembersNameSystem"); mLandManagementNames = gSavedSettings.getS32("LandManagementNameSystem"); + mProfileNames = gSavedSettings.getS32("ProfileNameSystem"); mRadarNames = gSavedSettings.getS32("RadarNameSystem"); mSpeakerNames = gSavedSettings.getS32("SpeakerNameSystem"); //Autoresponse ------------------------------------------------------------------------ - mIMResponseAnyoneItemID = gSavedPerAccountSettings.getString("AutoresponseAnyoneItemID"); - mIMResponseNonFriendsItemID = gSavedPerAccountSettings.getString("AutoresponseNonFriendsItemID"); - mIMResponseMutedItemID = gSavedPerAccountSettings.getString("AutoresponseMutedItemID"); - mIMResponseBusyItemID = gSavedPerAccountSettings.getString("BusyModeResponseItemID"); - - gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseRepeat", childGetValue("AscentInstantMessageResponseRepeat")); - gSavedPerAccountSettings.setBOOL("AutoresponseAnyone", childGetValue("AutoresponseAnyone")); - gSavedPerAccountSettings.setBOOL("AutoresponseAnyoneFriendsOnly", childGetValue("AutoresponseAnyoneFriendsOnly")); - gSavedPerAccountSettings.setBOOL("AutoresponseAnyoneItem", childGetValue("AutoresponseAnyoneItem")); - gSavedPerAccountSettings.setString("AutoresponseAnyoneMessage", childGetValue("AutoresponseAnyoneMessage")); - gSavedPerAccountSettings.setBOOL("AutoresponseAnyoneShow", childGetValue("AutoresponseAnyoneShow")); - gSavedPerAccountSettings.setBOOL("AutoresponseNonFriends", childGetValue("AutoresponseNonFriends")); - gSavedPerAccountSettings.setBOOL("AutoresponseNonFriendsItem", childGetValue("AutoresponseNonFriendsItem")); - gSavedPerAccountSettings.setString("AutoresponseNonFriendsMessage", childGetValue("AutoresponseNonFriendsMessage")); - gSavedPerAccountSettings.setBOOL("AutoresponseNonFriendsShow", childGetValue("AutoresponseNonFriendsShow")); - gSavedPerAccountSettings.setBOOL("AutoresponseMuted", childGetValue("AutoresponseMuted")); - gSavedPerAccountSettings.setBOOL("AutoresponseMutedItem", childGetValue("AutoresponseMutedItem")); - gSavedPerAccountSettings.setString("AutoresponseMutedMessage", childGetValue("AutoresponseMutedMessage")); - gSavedPerAccountSettings.setBOOL("AutoresponseMutedShow", childGetValue("AutoresponseMutedShow")); - gSavedPerAccountSettings.setString("BusyModeResponse", childGetValue("BusyModeResponse")); - gSavedPerAccountSettings.setBOOL("BusyModeResponseItem", childGetValue("BusyModeResponseItem")); - gSavedPerAccountSettings.setBOOL("BusyModeResponseShow", childGetValue("BusyModeResponseShow")); + mIMResponseRepeat = gSavedPerAccountSettings.getBOOL("AscentInstantMessageResponseRepeat"); + mIMResponseAway = gSavedPerAccountSettings.getBOOL("AutoresponseOnlyIfAway"); + mIMResponseAnyone = gSavedPerAccountSettings.getBOOL("AutoresponseAnyone"); + mIMResponseAnyoneFriends = gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneFriendsOnly"); + mIMResponseAnyoneItem = gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneItem"); + mIMResponseAnyoneItemID = gSavedPerAccountSettings.getString("AutoresponseAnyoneItemID"); + mIMResponseAnyoneMessage = gSavedPerAccountSettings.getString("AutoresponseAnyoneMessage"); + mIMResponseAnyoneShow = gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneShow"); + mIMResponseNonFriends = gSavedPerAccountSettings.getBOOL("AutoresponseNonFriends"); + mIMResponseNonFriendsItem = gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsItem"); + mIMResponseNonFriendsItemID = gSavedPerAccountSettings.getString("AutoresponseNonFriendsItemID"); + mIMResponseNonFriendsMessage = gSavedPerAccountSettings.getString("AutoresponseNonFriendsMessage"); + mIMResponseNonFriendsShow = gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsShow"); + mIMResponseMuted = gSavedPerAccountSettings.getBOOL("AutoresponseMuted"); + mIMResponseMutedItem = gSavedPerAccountSettings.getBOOL("AutoresponseMutedItem"); + mIMResponseMutedItemID = gSavedPerAccountSettings.getString("AutoresponseMutedItemID"); + mIMResponseMutedMessage = gSavedPerAccountSettings.getString("AutoresponseMutedMessage"); + mIMResponseMutedShow = gSavedPerAccountSettings.getBOOL("AutoresponseMutedShow"); + mIMResponseBusyItem = gSavedPerAccountSettings.getBOOL("BusyModeResponseItem"); + mIMResponseBusyItemID = gSavedPerAccountSettings.getString("BusyModeResponseItemID"); + mIMResponseBusyMessage = gSavedPerAccountSettings.getString("BusyModeResponse"); + mIMResponseBusyShow = gSavedPerAccountSettings.getBOOL("BusyModeResponseShow"); //Spam -------------------------------------------------------------------------------- mEnableAS = gSavedSettings.getBOOL("AntiSpamEnabled"); @@ -335,83 +326,78 @@ void LLPrefsAscentChat::refreshValues() // Update controls based on current settings void LLPrefsAscentChat::refresh() { - //Chat -------------------------------------------------------------------------------- - // time format combobox - LLComboBox* combo = getChild("time_format_combobox"); - if (combo) - { - combo->setCurrentByIndex(mTimeFormat); - } + //Chat -------------------------------------------------------------------------------- + // time format combobox + if (mTimeFormat != -1) + { + if (auto combo = getChild("time_format_combobox")) + { + combo->setCurrentByIndex(mTimeFormat); + } + } - // date format combobox - combo = getChild("date_format_combobox"); - if (combo) - { - combo->setCurrentByIndex(mDateFormat); - } + // date format combobox + if (mDateFormat != -1) + { + if (auto combo = getChild("date_format_combobox")) + { + combo->setCurrentByIndex(mDateFormat); + } + } //Chat UI ----------------------------------------------------------------------------- - if (combo = getChild("chat_tabs_namesystem_combobox")) + if (auto combo = getChild("chat_tabs_namesystem_combobox")) combo->setCurrentByIndex(mChatTabNames); - if (combo = getChild("friends_namesystem_combobox")) + if (auto combo = getChild("friends_namesystem_combobox")) combo->setCurrentByIndex(mFriendNames); - if (combo = getChild("group_members_namesystem_combobox")) + if (auto combo = getChild("group_members_namesystem_combobox")) combo->setCurrentByIndex(mGroupMembersNames); - if (combo = getChild("land_management_namesystem_combobox")) + if (auto combo = getChild("land_management_namesystem_combobox")) combo->setCurrentByIndex(mLandManagementNames); - if (combo = getChild("radar_namesystem_combobox")) + if (auto combo = getChild("radar_namesystem_combobox")) combo->setCurrentByIndex(mRadarNames); - if (combo = getChild("speaker_namesystem_combobox")) + if (auto combo = getChild("speaker_namesystem_combobox")) combo->setCurrentByIndex(mSpeakerNames); //Text Options ------------------------------------------------------------------------ - combo = getChild("SpellBase"); - - if (combo != NULL) + if (auto combo = getChild("SpellBase")) { combo->removeall(); - std::vector names = glggHunSpell->getDicts(); - for (int i = 0; i < (int)names.size(); i++) + for (const auto& name : glggHunSpell->getDicts()) { - combo->add(names[i]); + combo->add(name); } combo->setSimple(gSavedSettings.getString("SpellBase")); } - combo = getChild("EmSpell_Avail"); - - if (combo != NULL) + if (auto combo = getChild("EmSpell_Avail")) { combo->removeall(); - combo->add(""); - std::vector names = glggHunSpell->getAvailDicts(); + combo->add(LLStringUtil::null); - for (int i = 0; i < (int)names.size(); i++) + for (const auto& name : glggHunSpell->getAvailDicts()) { - combo->add(names[i]); + combo->add(name); } - combo->setSimple(std::string("")); + combo->setSimple(LLStringUtil::null); } - combo = getChild("EmSpell_Installed"); - - if (combo != NULL) + if (auto combo = getChild("EmSpell_Installed")) { combo->removeall(); - combo->add(""); - std::vector names = glggHunSpell->getInstalledDicts(); + combo->add(LLStringUtil::null); - for (int i = 0; i < (int)names.size(); i++) + for (const auto& name : glggHunSpell->getInstalledDicts()) { - combo->add(names[i]); + combo->add(name); } - combo->setSimple(std::string("")); + combo->setSimple(LLStringUtil::null); } childSetEnabled("KeywordsList", mKeywordsOn); @@ -453,45 +439,7 @@ void LLPrefsAscentChat::cancel() gSavedSettings.setBOOL("SecondsInChatAndIMs", mSecondsInChatAndIMs); gSavedSettings.setBOOL("SecondsInLog", mSecondsInLog); - std::string short_date, long_date, short_time, long_time, timestamp; - - if (mTimeFormat == 0) - { - short_time = "%H:%M"; - long_time = "%H:%M:%S"; - timestamp = " %H:%M:%S"; - } - else - { - short_time = "%I:%M %p"; - long_time = "%I:%M:%S %p"; - timestamp = " %I:%M %p"; - } - - if (mDateFormat == 0) - { - short_date = "%Y-%m-%d"; - long_date = "%A %d %B %Y"; - timestamp = "%a %d %b %Y" + timestamp; - } - else if (mDateFormat == 1) - { - short_date = "%d/%m/%Y"; - long_date = "%A %d %B %Y"; - timestamp = "%a %d %b %Y" + timestamp; - } - else - { - short_date = "%m/%d/%Y"; - long_date = "%A, %B %d %Y"; - timestamp = "%a %b %d %Y" + timestamp; - } - - gSavedSettings.setString("ShortDateFormat", short_date); - gSavedSettings.setString("LongDateFormat", long_date); - gSavedSettings.setString("ShortTimeFormat", short_time); - gSavedSettings.setString("LongTimeFormat", long_time); - gSavedSettings.setString("TimestampFormat", timestamp); + setTimeDateFormats(mTimeFormat, mDateFormat); //Chat UI ----------------------------------------------------------------------------- gSavedSettings.setBOOL("WoLfVerticalIMTabs", mWoLfVerticalIMTabs); @@ -510,16 +458,35 @@ void LLPrefsAscentChat::cancel() gSavedSettings.setS32("FriendNameSystem", mFriendNames); gSavedSettings.setS32("GroupMembersNameSystem", mGroupMembersNames); gSavedSettings.setS32("LandManagementNameSystem", mLandManagementNames); + gSavedSettings.setS32("ProfileNameSystem", mProfileNames); gSavedSettings.setS32("RadarNameSystem", mRadarNames); gSavedSettings.setS32("SpeakerNameSystem", mSpeakerNames); //Autoresponse ------------------------------------------------------------------------ - gSavedPerAccountSettings.setString("AutoresponseAnyoneItemID", mIMResponseAnyoneItemID); - gSavedPerAccountSettings.setString("AutoresponseNonFriendsItemID", mIMResponseNonFriendsItemID); - gSavedPerAccountSettings.setString("AutoresponseMutedItemID", mIMResponseMutedItemID); - gSavedPerAccountSettings.setString("BusyModeResponseItemID", mIMResponseBusyItemID); - - //Spam -------------------------------------------------------------------------------- + gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseRepeat", mIMResponseRepeat); + gSavedPerAccountSettings.setBOOL("AutoresponseOnlyIfAway", mIMResponseAway); + gSavedPerAccountSettings.setBOOL("AutoresponseAnyone", mIMResponseAnyone); + gSavedPerAccountSettings.setBOOL("AutoresponseAnyoneFriendsOnly", mIMResponseAnyoneFriends); + gSavedPerAccountSettings.setBOOL("AutoresponseAnyoneItem", mIMResponseAnyoneItem); + gSavedPerAccountSettings.setString("AutoresponseAnyoneItemID", mIMResponseAnyoneItemID); + gSavedPerAccountSettings.setString("AutoresponseAnyoneMessage", mIMResponseAnyoneMessage); + gSavedPerAccountSettings.setBOOL("AutoresponseAnyoneShow", mIMResponseAnyoneShow); + gSavedPerAccountSettings.setBOOL("AutoresponseNonFriends", mIMResponseNonFriends); + gSavedPerAccountSettings.setBOOL("AutoresponseNonFriendsItem", mIMResponseNonFriendsItem); + gSavedPerAccountSettings.setString("AutoresponseNonFriendsItemID", mIMResponseNonFriendsItemID); + gSavedPerAccountSettings.setString("AutoresponseNonFriendsMessage", mIMResponseNonFriendsMessage); + gSavedPerAccountSettings.setBOOL("AutoresponseNonFriendsShow", mIMResponseNonFriendsShow); + gSavedPerAccountSettings.setBOOL("AutoresponseMuted", mIMResponseMuted); + gSavedPerAccountSettings.setBOOL("AutoresponseMutedItem", mIMResponseMutedItem); + gSavedPerAccountSettings.setString("AutoresponseMutedItemID", mIMResponseMutedItemID); + gSavedPerAccountSettings.setString("AutoresponseMutedMessage", mIMResponseMutedMessage); + gSavedPerAccountSettings.setBOOL("AutoresponseMutedShow", mIMResponseMutedShow); + gSavedPerAccountSettings.setBOOL("BusyModeResponseItem", mIMResponseBusyItem); + gSavedPerAccountSettings.setString("BusyModeResponseItemID", mIMResponseBusyItemID); + gSavedPerAccountSettings.setString("BusyModeResponse", mIMResponseBusyMessage); + gSavedPerAccountSettings.setBOOL("BusyModeResponseShow", mIMResponseBusyShow); + + //Spam -------------------------------------------------------------------------------- gSavedSettings.setBOOL("AntiSpamEnabled", mEnableAS); gSavedSettings.setBOOL("_NACL_AntiSpamGlobalQueue", mGlobalQueue); gSavedSettings.setU32("_NACL_AntiSpamAmount", mChatSpamCount); diff --git a/indra/newview/ascentprefschat.h b/indra/newview/ascentprefschat.h index 709635d4f1..0f0dc9baaa 100644 --- a/indra/newview/ascentprefschat.h +++ b/indra/newview/ascentprefschat.h @@ -67,10 +67,10 @@ class LLPrefsAscentChat : public LLPanel bool mEnableMUPose; bool mEnableOOCAutoClose; U32 mLinksForChattingObjects; - U32 mTimeFormat; - U32 mDateFormat; - U32 tempTimeFormat; - U32 tempDateFormat; + S8 mTimeFormat; + S8 mDateFormat; + S8 tempTimeFormat; + S8 tempDateFormat; bool mSecondsInChatAndIMs; bool mSecondsInLog; @@ -91,14 +91,33 @@ class LLPrefsAscentChat : public LLPanel S32 mFriendNames; S32 mGroupMembersNames; S32 mLandManagementNames; + S32 mProfileNames; S32 mRadarNames; S32 mSpeakerNames; //Autoresponse ------------------------------------------------------------------------ + bool mIMResponseRepeat; + bool mIMResponseAway; + bool mIMResponseAnyone; + bool mIMResponseAnyoneFriends; + bool mIMResponseAnyoneItem; std::string mIMResponseAnyoneItemID; + std::string mIMResponseAnyoneMessage; + bool mIMResponseAnyoneShow; + bool mIMResponseNonFriends; + bool mIMResponseNonFriendsItem; std::string mIMResponseNonFriendsItemID; + std::string mIMResponseNonFriendsMessage; + bool mIMResponseNonFriendsShow; + bool mIMResponseMuted; + bool mIMResponseMutedItem; std::string mIMResponseMutedItemID; + std::string mIMResponseMutedMessage; + bool mIMResponseMutedShow; + bool mIMResponseBusyItem; std::string mIMResponseBusyItemID; + std::string mIMResponseBusyMessage; + bool mIMResponseBusyShow; //Spam -------------------------------------------------------------------------------- bool mEnableAS; diff --git a/indra/newview/ascentprefssys.cpp b/indra/newview/ascentprefssys.cpp index 278084f6e2..2b530ad727 100644 --- a/indra/newview/ascentprefssys.cpp +++ b/indra/newview/ascentprefssys.cpp @@ -77,7 +77,6 @@ LLPrefsAscentSys::LLPrefsAscentSys() getChild("AlchemyChatCommandHoverHeight")->setCommitCallback(lineEditorControl); //Security ---------------------------------------------------------------------------- - getChild("UISndRestart")->setCommitCallback(lineEditorControl); //Build ------------------------------------------------------------------------------- getChild("next_owner_copy")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCheckBox, this, _1, _2)); @@ -144,6 +143,7 @@ void LLPrefsAscentSys::refreshValues() { //General ----------------------------------------------------------------------------- mDoubleClickTeleport = gSavedSettings.getBOOL("DoubleClickTeleport"); + mDoubleClickAutoPilot = gSavedSettings.getBOOL("DoubleClickAutoPilot"); mResetCameraAfterTP = gSavedSettings.getBOOL("OptionRotateCamAfterLocalTP"); mOffsetTPByUserHeight = gSavedSettings.getBOOL("OptionOffsetTPByAgentHeight"); mClearBeaconAfterTeleport = gSavedSettings.getBOOL("ClearBeaconAfterTeleport"); @@ -206,8 +206,8 @@ void LLPrefsAscentSys::refreshValues() mDisableClickSitOtherOwner = gSavedSettings.getBOOL("DisableClickSitOtherOwner"); mDisplayScriptJumps = gSavedSettings.getBOOL("AscentDisplayTotalScriptJumps"); mNumScriptDiff = gSavedSettings.getF32("Ascentnumscriptdiff"); - mRestartMinimized = gSavedSettings.getBOOL("LiruRegionRestartMinimized"); - mRestartSound = gSavedSettings.getString("UISndRestart"); + mReplaceLinks = gSavedSettings.getBOOL("SinguReplaceLinks"); + mEmergencySeconds = gSavedPerAccountSettings.getU32("EmergencyTeleportSeconds"); mLandmark = gSavedPerAccountSettings.getString("EmergencyTeleportLandmark"); mLandmarkBackup = gSavedPerAccountSettings.getString("EmergencyTeleportLandmarkBackup"); @@ -265,8 +265,6 @@ void LLPrefsAscentSys::refresh() childSetValue("AlchemyChatCommandHoverHeight", mCmdLineHover); //Security ---------------------------------------------------------------------------- - getChildView("UISndRestart")->setValue(mRestartSound); - if (LLComboBox* combo = getChild("lookat_namesystem_combobox")) combo->setValue(mLookAtNames); @@ -293,6 +291,7 @@ void LLPrefsAscentSys::cancel() { //General ----------------------------------------------------------------------------- gSavedSettings.setBOOL("DoubleClickTeleport", mDoubleClickTeleport); + gSavedSettings.setBOOL("DoubleClickAutoPilot", mDoubleClickAutoPilot); gSavedSettings.setBOOL("OptionRotateCamAfterLocalTP", mResetCameraAfterTP); gSavedSettings.setBOOL("OptionOffsetTPByAgentHeight", mOffsetTPByUserHeight); gSavedSettings.setBOOL("ClearBeaconAfterTeleport", mClearBeaconAfterTeleport); @@ -354,8 +353,8 @@ void LLPrefsAscentSys::cancel() gSavedSettings.setBOOL("DisableClickSitOtherOwner", mDisableClickSitOtherOwner); gSavedSettings.setBOOL("AscentDisplayTotalScriptJumps", mDisplayScriptJumps); gSavedSettings.setF32("Ascentnumscriptdiff", mNumScriptDiff); - gSavedSettings.setBOOL("LiruRegionRestartMinimized", mRestartMinimized); - gSavedSettings.setString("UISndRestart", mRestartSound); + gSavedSettings.setBOOL("SinguReplaceLinks", mReplaceLinks); + gSavedPerAccountSettings.setU32("EmergencyTeleportSeconds", mEmergencySeconds); gSavedPerAccountSettings.setString("EmergencyTeleportLandmark", mLandmark); gSavedPerAccountSettings.setString("EmergencyTeleportLandmarkBackup", mLandmarkBackup); diff --git a/indra/newview/ascentprefssys.h b/indra/newview/ascentprefssys.h index c23023447d..1c357750e5 100644 --- a/indra/newview/ascentprefssys.h +++ b/indra/newview/ascentprefssys.h @@ -54,6 +54,7 @@ class LLPrefsAscentSys : public LLPanel private: //General ----------------------------------------------------------------------------- bool mDoubleClickTeleport; + bool mDoubleClickAutoPilot; bool mResetCameraAfterTP; bool mOffsetTPByUserHeight; bool mClearBeaconAfterTeleport; @@ -115,9 +116,9 @@ class LLPrefsAscentSys : public LLPanel bool mDisableClickSit; bool mDisableClickSitOtherOwner; bool mDisplayScriptJumps; - bool mRestartMinimized; + bool mReplaceLinks; F32 mNumScriptDiff; - std::string mRestartSound; + U32 mEmergencySeconds; std::string mLandmark; std::string mLandmarkBackup; diff --git a/indra/newview/ascentprefsvan.cpp b/indra/newview/ascentprefsvan.cpp index 6a51b580f6..0bb200636d 100644 --- a/indra/newview/ascentprefsvan.cpp +++ b/indra/newview/ascentprefsvan.cpp @@ -62,6 +62,8 @@ LLPrefsAscentVan::LLPrefsAscentVan() getChild("tag_spoofing_combobox")->setCommitCallback(boost::bind(&LLPrefsAscentVan::onCommitClientTag, this, _1)); getChild("custom_tag_label_box")->setCommitCallback(boost::bind(&LLControlGroup::setString, boost::ref(gSavedSettings), "AscentCustomTagLabel", _2)); + commit_callback_t lineEditorControl(boost::bind(&LLControlGroup::setString, boost::ref(gSavedSettings), boost::bind(&LLUICtrl::getName, _1), _2)); + getChild("UISndRestart")->setCommitCallback(lineEditorControl); getChild("update_clientdefs")->setCommitCallback(boost::bind(LLPrefsAscentVan::onManualClientUpdate)); @@ -126,10 +128,12 @@ void LLPrefsAscentVan::refreshValues() mCustomizeAnim = gSavedSettings.getBOOL("LiruCustomizeAnim"); mAnnounceSnapshots = gSavedSettings.getBOOL("AnnounceSnapshots"); mAnnounceStreamMetadata = gSavedSettings.getBOOL("AnnounceStreamMetadata"); - mUnfocusedFloatersOpaque = gSavedSettings.getBOOL("FloaterUnfocusedBackgroundOpaque"); - mCompleteNameProfiles = gSavedSettings.getBOOL("SinguCompleteNameProfiles"); + mInactiveFloaterTransparency = gSavedSettings.getF32("InactiveFloaterTransparency"); + mActiveFloaterTransparency = gSavedSettings.getF32("ActiveFloaterTransparency"); mScriptErrorsStealFocus = gSavedSettings.getBOOL("LiruScriptErrorsStealFocus"); mConnectToNeighbors = gSavedSettings.getBOOL("AlchemyConnectToNeighbors"); + mRestartMinimized = gSavedSettings.getBOOL("LiruRegionRestartMinimized"); + mRestartSound = gSavedSettings.getString("UISndRestart"); //Tags\Colors ---------------------------------------------------------------------------- mAscentBroadcastTag = gSavedSettings.getBOOL("AscentBroadcastTag"); @@ -169,6 +173,7 @@ void LLPrefsAscentVan::refreshValues() void LLPrefsAscentVan::refresh() { //Main ----------------------------------------------------------------------------------- + getChildView("UISndRestart")->setValue(mRestartSound); //Tags\Colors ---------------------------------------------------------------------------- LLComboBox* combo = getChild("tag_spoofing_combobox"); @@ -197,10 +202,12 @@ void LLPrefsAscentVan::cancel() gSavedSettings.setBOOL("LiruCustomizeAnim", mCustomizeAnim); gSavedSettings.setBOOL("AnnounceSnapshots", mAnnounceSnapshots); gSavedSettings.setBOOL("AnnounceStreamMetadata", mAnnounceStreamMetadata); - gSavedSettings.setBOOL("FloaterUnfocusedBackgroundOpaque", mUnfocusedFloatersOpaque); - gSavedSettings.setBOOL("SinguCompleteNameProfiles", mCompleteNameProfiles); + gSavedSettings.setF32("InactiveFloaterTransparency", mInactiveFloaterTransparency); + gSavedSettings.setF32("ActiveFloaterTransparency", mActiveFloaterTransparency); gSavedSettings.setBOOL("LiruScriptErrorsStealFocus", mScriptErrorsStealFocus); gSavedSettings.setBOOL("AlchemyConnectToNeighbors", mConnectToNeighbors); + gSavedSettings.setBOOL("LiruRegionRestartMinimized", mRestartMinimized); + gSavedSettings.setString("UISndRestart", mRestartSound); //Tags\Colors ---------------------------------------------------------------------------- gSavedSettings.setBOOL("AscentBroadcastTag", mAscentBroadcastTag); diff --git a/indra/newview/ascentprefsvan.h b/indra/newview/ascentprefsvan.h index b45adf6526..b29f5147d9 100644 --- a/indra/newview/ascentprefsvan.h +++ b/indra/newview/ascentprefsvan.h @@ -62,10 +62,11 @@ class LLPrefsAscentVan : public LLPanel bool mCustomizeAnim; bool mAnnounceSnapshots; bool mAnnounceStreamMetadata; - bool mUnfocusedFloatersOpaque; - bool mCompleteNameProfiles; + F32 mInactiveFloaterTransparency, mActiveFloaterTransparency; bool mScriptErrorsStealFocus; bool mConnectToNeighbors; + bool mRestartMinimized; + std::string mRestartSound; //Tags\Colors bool mAscentBroadcastTag; std::string mReportClientUUID; diff --git a/indra/newview/awavefront.cpp b/indra/newview/awavefront.cpp index 2c6e0127e3..5e94a43e41 100644 --- a/indra/newview/awavefront.cpp +++ b/indra/newview/awavefront.cpp @@ -163,10 +163,11 @@ Wavefront::Wavefront(LLFace* face, LLPolyMesh* mesh, const LLXform* transform, c if (transform_normals) Transform(normals, transform_normals); const U32 pcount = mesh ? mesh->getNumFaces() : (vb->getNumIndices()/3); //indices - const U16 offset = face->getIndicesStart(); //indices + const U32 offset = face->getIndicesStart(); //indices for (U32 i = 0; i < pcount; ++i) { - triangles.push_back(tri(getIndices[i * 3 + offset] + start, getIndices[i * 3 + 1 + offset] + start, getIndices[i * 3 + 2 + offset] + start)); + const auto off = i * 3 + offset; + triangles.push_back(tri(getIndices[off] + start, getIndices[off + 1] + start, getIndices[off + 2] + start)); } } @@ -174,9 +175,9 @@ void Wavefront::Transform(vert_t& v, const LLXform* x) //recursive { LLMatrix4 m; x->getLocalMat4(m); - for (vert_t::iterator iterv = v.begin(); iterv != v.end(); ++iterv) + for (auto& i : v) { - iterv->first = iterv->first * m; + i.first = i.first * m; } if (const LLXform* xp = x->getParent()) Transform(v, xp); @@ -186,9 +187,9 @@ void Wavefront::Transform(vec3_t& v, const LLXform* x) //recursive { LLMatrix4 m; x->getLocalMat4(m); - for (vec3_t::iterator iterv = v.begin(); iterv != v.end(); ++iterv) + for (auto& i : v) { - *iterv = *iterv * m; + i = i * m; } if (const LLXform* xp = x->getParent()) Transform(v, xp); @@ -238,7 +239,7 @@ namespace LLViewerObject* obj = node->getObject(); if (obj->isSculpted() && !obj->isMesh()) { - LLSculptParams *sculpt_params = (LLSculptParams *)obj->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = obj->getSculptParams(); LLUUID sculpt_id = sculpt_params->getSculptTexture(); // Find inventory items with asset id of the sculpt map @@ -252,9 +253,9 @@ namespace asset_id_matches); // See if any of the inventory items matching this sculpt id are exportable - for (U32 i = 0; i < items.size(); i++) + for (const auto& item : items) { - const LLPermissions item_permissions = items[i]->getPermissions(); + const LLPermissions item_permissions = item->getPermissions(); if (item_permissions.allowExportBy(gAgentID, LFSimFeatureHandler::instance().exportPolicy())) { return true; @@ -269,9 +270,9 @@ namespace } } - class LFSaveSelectedObjects : public view_listener_t + class LFSaveSelectedObjects final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if (LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection()) { @@ -288,10 +289,10 @@ namespace S32 included = 0; for (LLObjectSelection::iterator iter = selection->begin(); iter != selection->end(); ++iter) { - total++; + ++total; LLSelectNode* node = *iter; if (!can_export_node(node)) continue; - included++; + ++included; wfsaver->Add(node->getObject()); } if (wfsaver->obj_v.empty()) @@ -322,12 +323,12 @@ void WavefrontSaver::Add(const LLVOAvatar* av_vo) //adds attachments, too! { offset = -av_vo->getRenderPosition(); avatar_joint_list_t vjv = av_vo->mMeshLOD; - for (avatar_joint_list_t::const_iterator itervj = vjv.begin(); itervj != vjv.end(); ++itervj) + for (const auto& itervj : vjv) { - const LLViewerJoint* vj = dynamic_cast(*itervj); + const auto* vj = dynamic_cast(itervj); if (!vj || vj->mMeshParts.empty()) continue; - LLViewerJointMesh* vjm = dynamic_cast(vj->mMeshParts[0]); //highest LOD + auto* vjm = dynamic_cast(vj->mMeshParts[0]); //highest LOD if (!vjm) continue; vjm->updateJointGeometry(); @@ -355,21 +356,19 @@ void WavefrontSaver::Add(const LLVOAvatar* av_vo) //adds attachments, too! Add(Wavefront(face, pm, NULL, &normfix)); } - for (LLVOAvatar::attachment_map_t::const_iterator iter = av_vo->mAttachmentPoints.begin(); iter != av_vo->mAttachmentPoints.end(); ++iter) + for (const auto& ap : av_vo->mAttachmentPoints) { - LLViewerJointAttachment* ja = iter->second; + LLViewerJointAttachment* ja = ap.second; if (!ja) continue; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator itero = ja->mAttachedObjects.begin(); itero != ja->mAttachedObjects.end(); ++itero) + for (const auto& o : ja->mAttachedObjects) { - LLViewerObject* o = *itero; if (!o) continue; std::vector prims; o->addThisAndAllChildren(prims); - for (std::vector::iterator iterc = prims.begin(); iterc != prims.end(); ++iterc) + for (const auto& c : prims) { - const LLViewerObject* c = *iterc; if (!c) continue; if (LLSelectNode* n = LLSelectMgr::getInstance()->getSelection()->findNode(const_cast(c))) { @@ -400,9 +399,9 @@ void WavefrontSaver::Add(const LLVOAvatar* av_vo) //adds attachments, too! } namespace { - class LFSaveSelectedAvatar : public view_listener_t + class LFSaveSelectedAvatar final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if (const LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())) { @@ -446,49 +445,48 @@ bool WavefrontSaver::saveFile(LLFILE* fp) int num = 0; int index = 0; - for (std::vector::iterator w_iter = obj_v.begin(); w_iter != obj_v.end(); ++w_iter) + for (const auto& obj : obj_v) { int count = 0; - std::string name = (*w_iter).name; + std::string name = obj.name; if (name.empty()) name = llformat("%d", num++); - vert_t vertices = (*w_iter).vertices; - vec3_t normals = (*w_iter).normals; - tri_t triangles = (*w_iter).triangles; + auto& vertices = obj.vertices; + auto& normals = obj.normals; + auto& triangles = obj.triangles; //Write Object - write_or_bust(fp, "o " + name + "\n"); + write_or_bust(fp, "o " + name + '\n'); //Write vertices; swap axes if necessary static const LLCachedControl swapYZ("OBJExportSwapYZ", false); const double xm = swapYZ ? -1.0 : 1.0; const int y = swapYZ ? 2 : 1; const int z = swapYZ ? 1 : 2; - for (vert_t::iterator v_iter = vertices.begin(); v_iter != vertices.end(); ++v_iter) + for (const auto& vert : vertices) { ++count; - const LLVector3 v = v_iter->first + offset; + const LLVector3 v = vert.first + offset; write_or_bust(fp, llformat("v %f %f %f\n",v[0] * xm, v[y], v[z])); } - for (vec3_t::iterator n_iter = normals.begin(); n_iter != normals.end(); ++n_iter) + for (const auto& n : normals) { - const LLVector3 n = *n_iter; write_or_bust(fp, llformat("vn %f %f %f\n",n[0] * xm, n[y], n[z])); } - for (vert_t::iterator v_iter = vertices.begin(); v_iter != vertices.end(); ++v_iter) + for (const auto& vert : vertices) { - write_or_bust(fp, llformat("vt %f %f\n", v_iter->second[0], v_iter->second[1])); + write_or_bust(fp, llformat("vt %f %f\n", vert.second[0], vert.second[1])); } //Write triangles - for (tri_t::iterator t_iter = triangles.begin(); t_iter != triangles.end(); ++t_iter) + for (const auto& triangle : triangles) { - const int f1 = t_iter->v0 + index + 1; - const int f2 = t_iter->v1 + index + 1; - const int f3 = t_iter->v2 + index + 1; + const int f1 = triangle.v0 + index + 1; + const int f2 = triangle.v1 + index + 1; + const int f3 = triangle.v2 + index + 1; write_or_bust(fp, llformat("f %d/%d/%d %d/%d/%d %d/%d/%d\n", f1,f1,f1,f2,f2,f2,f3,f3,f3)); } diff --git a/indra/newview/character/aux_base.tga b/indra/newview/character/aux_base.tga new file mode 100644 index 0000000000..dbcaaaf2b1 Binary files /dev/null and b/indra/newview/character/aux_base.tga differ diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index 7d4fa037f6..47422d0382 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -1,6 +1,6 @@ @@ -12,6 +12,7 @@ pie_slice="2" name="Chest" joint="mChest" + location="ATTACH_CHEST" position="0.15 0 -0.1" rotation="0 90 90" visible_in_first_person="true" /> @@ -22,6 +23,7 @@ pie_slice="2" name="Skull" joint="mHead" + location="ATTACH_HEAD" position="0 0 0.15" rotation="0 0 90" visible_in_first_person="false" /> @@ -32,6 +34,7 @@ pie_slice="3" name="Left Shoulder" joint="mCollarLeft" + location="ATTACH_LSHOULDER" position="0 0 0.08" rotation="0 0 0" visible_in_first_person="true" /> @@ -42,6 +45,7 @@ pie_slice="1" name="Right Shoulder" joint="mCollarRight" + location="ATTACH_RSHOULDER" position="0 0 0.08" rotation="0 0 0" visible_in_first_person="true"/> @@ -51,6 +55,7 @@ group="4" name="Left Hand" joint="mWristLeft" + location="ATTACH_LHAND" position="0 0.08 -0.02" rotation="0 0 0" visible_in_first_person="true" @@ -61,6 +66,7 @@ group="0" name="Right Hand" joint="mWristRight" + location="ATTACH_RHAND" position="0 -0.08 -0.02" rotation="0 0 0" visible_in_first_person="true" @@ -72,6 +78,7 @@ pie_slice="6" name="Left Foot" joint="mFootLeft" + location="ATTACH_LFOOT" position="0 0.0 0.0" rotation="0 0 0" visible_in_first_person="true"/> @@ -82,6 +89,7 @@ pie_slice="6" name="Right Foot" joint="mFootRight" + location="ATTACH_RFOOT" position="0 0.0 0.0" rotation="0 0 0" visible_in_first_person="true"/> @@ -92,6 +100,7 @@ pie_slice="7" name="Spine" joint="mChest" + location="ATTACH_BACK" position="-0.15 0 -0.1" rotation="0 -90 90" visible_in_first_person="true" /> @@ -102,6 +111,7 @@ pie_slice="6" name="Pelvis" joint="mPelvis" + location="ATTACH_PELVIS" position="0 0 -0.15" rotation="0 0 0" visible_in_first_person="true" /> @@ -112,6 +122,7 @@ pie_slice="6" name="Mouth" joint="mHead" + location="ATTACH_MOUTH" position="0.12 0 0.001" rotation="0 0 0" visible_in_first_person="false"/> @@ -122,6 +133,7 @@ pie_slice="7" name="Chin" joint="mHead" + location="ATTACH_CHIN" position="0.12 0 -0.04" rotation="0 0 0" visible_in_first_person="false" /> @@ -132,6 +144,7 @@ pie_slice="4" name="Left Ear" joint="mHead" + location="ATTACH_LEAR" position="0.015 0.08 0.017" rotation="0 0 0" visible_in_first_person="false" /> @@ -142,6 +155,7 @@ pie_slice="0" name="Right Ear" joint="mHead" + location="ATTACH_REAR" position="0.015 -0.08 0.017" rotation="0 0 0" visible_in_first_person="false" /> @@ -152,6 +166,7 @@ pie_slice="3" name="Left Eyeball" joint="mEyeLeft" + location="ATTACH_LEYE" position="0 0 0" rotation="0 0 0" visible_in_first_person="false"/> @@ -162,6 +177,7 @@ pie_slice="1" name="Right Eyeball" joint="mEyeRight" + location="ATTACH_REYE" position="0 0 0" rotation="0 0 0" visible_in_first_person="false" /> @@ -172,6 +188,7 @@ pie_slice="5" name="Nose" joint="mHead" + location="ATTACH_NOSE" position="0.1 0 0.05" rotation="0 0 0" visible_in_first_person="false"/> @@ -182,6 +199,7 @@ pie_slice="0" name="R Upper Arm" joint="mShoulderRight" + location="ATTACH_RUARM" position="0.01 -0.13 0.01" rotation="0 0 0" visible_in_first_person="true" /> @@ -192,6 +210,7 @@ pie_slice="7" name="R Forearm" joint="mElbowRight" + location="ATTACH_RLARM" position="0 -0.12 0" rotation="0 0 0" visible_in_first_person="true"/> @@ -202,6 +221,7 @@ pie_slice="4" name="L Upper Arm" joint="mShoulderLeft" + location="ATTACH_LUARM" position="0.01 0.15 -0.01" rotation="0 0 0" visible_in_first_person="true" /> @@ -212,6 +232,7 @@ pie_slice="5" name="L Forearm" joint="mElbowLeft" + location="ATTACH_LLARM" position="0 0.113 0" rotation="0 0 0" visible_in_first_person="true" /> @@ -222,6 +243,7 @@ pie_slice="1" name="Right Hip" joint="mHipRight" + location="ATTACH_RHIP" position="0 0 0" rotation="0 0 0" visible_in_first_person="true" /> @@ -232,6 +254,7 @@ pie_slice="0" name="R Upper Leg" joint="mHipRight" + location="ATTACH_RULEG" position="-0.017 0.041 -0.310" rotation="0 0 0" visible_in_first_person="true" /> @@ -242,6 +265,7 @@ pie_slice="7" name="R Lower Leg" joint="mKneeRight" + location="ATTACH_RLLEG" position="-0.044 -0.007 -0.262" rotation="0 0 0" visible_in_first_person="true" /> @@ -252,6 +276,7 @@ pie_slice="3" name="Left Hip" joint="mHipLeft" + location="ATTACH_LHIP" position="0 0 0" rotation="0 0 0" visible_in_first_person="true" /> @@ -262,6 +287,7 @@ pie_slice="4" name="L Upper Leg" joint="mHipLeft" + location="ATTACH_LULEG" position="-0.019 -0.034 -0.310" rotation="0 0 0" visible_in_first_person="true"/> @@ -272,6 +298,7 @@ pie_slice="5" name="L Lower Leg" joint="mKneeLeft" + location="ATTACH_LLLEG" position="-0.044 -0.007 -0.261" rotation="0 0 0" visible_in_first_person="true" /> @@ -282,6 +309,7 @@ pie_slice="5" name="Stomach" joint="mPelvis" + location="ATTACH_BELLY" position="0.092 0.0 0.088" rotation="0 0 0" visible_in_first_person="true" /> @@ -292,6 +320,7 @@ pie_slice="3" name="Left Pec" joint="mTorso" + location="ATTACH_LEFT_PEC" position="0.104 0.082 0.247" rotation="0 0 0" visible_in_first_person="true" /> @@ -302,15 +331,17 @@ pie_slice="1" name="Right Pec" joint="mTorso" + location="ATTACH_RIGHT_PEC" position="0.104 -0.082 0.247" rotation="0 0 0" visible_in_first_person="true" /> @@ -410,10 +449,179 @@ pie_slice="4" name="Avatar Center" joint="mRoot" + location="ATTACH_AVATAR_CENTER" position="0 0 0" rotation="0 0 0" visible_in_first_person="true" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + camera_distance="2.2"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - + camera_distance="1.8"> + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + value_max="1"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -633,12 +1496,20 @@ label_max="Eyes Long Head" value_min="-1" value_max="1"> - - - - - - + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + value_max=".10"> + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -
    - - - - - - - - - - + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1038,16 +4474,17 @@ @@ -1055,28 +4492,197 @@ + camera_angle="90"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + ############# + --> + + + - - - + + + - - - + + + - - - + + + + + + + - - + id="20004" + group="1" + name="Broad_Nostrils" + value_min="-.5" + value_max="1"> + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - - + + + - - + - - - - - - - - - - - + + + - - - + + + - - + + + + + + - - - - - - - - - - - - - - - - - - - + + + - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - + value_max="1.2"> + + - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - + + - @@ -3620,7 +6885,7 @@ + pos="-0.01 0.01 -0.02"/> @@ -3646,7 +6911,7 @@ + pos="-0.02 0.01 -0.03"/> @@ -3655,6 +6920,7 @@ group="1" name="Muscular_Torso" label="Torso Muscles" + sex="male" show_simple="true" wearable="shape" edit_group="shape_torso" @@ -3692,9 +6958,52 @@ - + + + + + + + + + + + - - - + + + @@ -6667,31 +10028,123 @@ - - - - - - - + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + @@ -6805,34 +10258,127 @@ skip_if_zero="true" domain="0.6" /> - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + name="lower_tattoo"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -8928,96 +12624,1358 @@ multiply_blend="true" /> - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + max2="1" + min2="1" /> + + + + + + + + + + + @@ -9498,9 +14485,13 @@ id="29" /> - - + id="30" /> + + + + + - - + max2="1" + min2="1" /> + + + + + - - - + + + + + + + - - + id="186" /> + + - + + + - - + id="187" /> + + - + + + - - + min2="1" /> - + + + + + + + - - + id="772" /> + + + + + + + + + - - - - + - + + + + + - + - + + + + + + + + - - - + + + - + + + - - - + + + + - - - - - - + + + + + + + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/character/avatar_skeleton.xml b/indra/newview/character/avatar_skeleton.xml index 6b07bbc1d3..2241a12545 100644 --- a/indra/newview/character/avatar_skeleton.xml +++ b/indra/newview/character/avatar_skeleton.xml @@ -1,81 +1,232 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/character/checkerboard.tga b/indra/newview/character/checkerboard.tga new file mode 100644 index 0000000000..1950d7403d Binary files /dev/null and b/indra/newview/character/checkerboard.tga differ diff --git a/indra/newview/character/invisible_head.tga b/indra/newview/character/invisible_head.tga new file mode 100644 index 0000000000..2673a237d5 Binary files /dev/null and b/indra/newview/character/invisible_head.tga differ diff --git a/indra/newview/chatbar_as_cmdline.cpp b/indra/newview/chatbar_as_cmdline.cpp index 56e4cb752d..2f5da6a334 100644 --- a/indra/newview/chatbar_as_cmdline.cpp +++ b/indra/newview/chatbar_as_cmdline.cpp @@ -42,6 +42,7 @@ #include "llagentui.h" #include "llavataractions.h" #include "llnotificationsutil.h" +#include "llsdserialize.h" #include "llviewerregion.h" #include "llworld.h" #include "lleventtimer.h" @@ -198,6 +199,22 @@ void invrepair() gInventory.collectDescendents(gInventory.getRootFolderID(),cats,items,FALSE);//,objectnamematches); } +void resync_anims() +{ + for (auto* character : LLCharacter::sInstances) + { + LLVOAvatar& avatar = *static_cast(character); + if (!avatar.isDead()) + { + for (const auto& playpair : avatar.mPlayingAnimations) + { + avatar.stopMotion(playpair.first, TRUE); + avatar.startMotion(playpair.first); + } + } + } +} + #ifdef PROF_CTRL_CALLS bool sort_calls(const std::pair& left, const std::pair& right) { @@ -219,6 +236,7 @@ struct ProfCtrlListAccum : public LLControlGroup::ApplyFunctor #endif //PROF_CTRL_CALLS void spew_key_to_name(const LLUUID& targetKey, const LLAvatarName& av_name) { + static const LLCachedControl ns(gSavedSettings, "AscentCmdLineKeyToNameNameSystem"); cmdline_printchat(llformat("%s: %s", targetKey.asString().c_str(), av_name.getNSName().c_str())); } bool cmd_line_chat(std::string data, EChatType type) @@ -226,11 +244,11 @@ bool cmd_line_chat(std::string data, EChatType type) static LLCachedControl enableChatCmd(gSavedSettings, "AscentCmdLine", true); if (enableChatCmd) { - data = utf8str_tolower(data); std::istringstream input(data); std::string cmd; if (!(input >> cmd)) return true; + cmd = utf8str_tolower(cmd); static LLCachedControl sDrawDistanceCommand(gSavedSettings, "AscentCmdLineDrawDistance"); static LLCachedControl sHeightCommand(gSavedSettings, "AscentCmdLineHeight"); @@ -238,18 +256,21 @@ bool cmd_line_chat(std::string data, EChatType type) static LLCachedControl sPosCommand(gSavedSettings, "AscentCmdLinePos"); static LLCachedControl sRezPlatCommand(gSavedSettings, "AscentCmdLineRezPlatform"); static LLCachedControl sHomeCommand(gSavedSettings, "AscentCmdLineTeleportHome"); + static LLCachedControl sSetHomeCommand(gSavedSettings, "AlchemyChatCommandSetHome", "/sethome"); static LLCachedControl sCalcCommand(gSavedSettings, "AscentCmdLineCalc"); static LLCachedControl sMapToCommand(gSavedSettings, "AscentCmdLineMapTo"); static LLCachedControl sClearCommand(gSavedSettings, "AscentCmdLineClearChat"); static LLCachedControl sRegionMsgCommand(gSavedSettings, "SinguCmdLineRegionSay"); static LLCachedControl sTeleportToCam(gSavedSettings, "AscentCmdTeleportToCam"); static LLCachedControl sHoverHeight(gSavedSettings, "AlchemyChatCommandHoverHeight", "/hover"); + static LLCachedControl sSetNearbyChatChannelCmd(gSavedSettings, "AlchemyChatCommandSetChatChannel", "/setchannel"); static LLCachedControl sResyncAnimCommand(gSavedSettings, "AlchemyChatCommandResyncAnim", "/resync"); static LLCachedControl sKeyToName(gSavedSettings, "AscentCmdLineKeyToName"); static LLCachedControl sOfferTp(gSavedSettings, "AscentCmdLineOfferTp"); static LLCachedControl sTP2Command(gSavedSettings, "AscentCmdLineTP2"); static LLCachedControl sAwayCommand(gSavedSettings, "SinguCmdLineAway"); static LLCachedControl sURLCommand(gSavedSettings, "SinguCmdLineURL"); + static LLCachedControl sSettingCommand(gSavedSettings, "SinguCmdLineSetting"); if (cmd == utf8str_tolower(sDrawDistanceCommand)) // dd { @@ -328,7 +349,8 @@ bool cmd_line_chat(std::string data, EChatType type) volume_params.setTaperY(0.f); LLVolumeMessage::packVolumeParams(&volume_params, msg); - msg->addVector3Fast(_PREHASH_Scale, LLVector3(size, size, 0.25f)); + size /= 3; + msg->addVector3Fast(_PREHASH_Scale, LLVector3(0.01f, size, size)); msg->addQuatFast(_PREHASH_Rotation, LLQuaternion(90.f * DEG_TO_RAD, LLVector3::y_axis)); msg->addVector3Fast(_PREHASH_RayStart, rez_pos); msg->addVector3Fast(_PREHASH_RayEnd, rez_pos); @@ -345,6 +367,11 @@ bool cmd_line_chat(std::string data, EChatType type) gAgent.teleportHome(); return false; } + else if (cmd == utf8str_tolower(sSetHomeCommand)) // sethome + { + gAgent.setStartPosition(START_LOCATION_ID_HOME); + return false; + } else if (cmd == utf8str_tolower(sCalcCommand))//Cryogenic Blitz { if (data.length() > cmd.length() + 1) @@ -379,7 +406,7 @@ bool cmd_line_chat(std::string data, EChatType type) slurl = LLSLURL(slurl.getRegion(), LLVector3(fmod(agentPos.mdV[VX], (F64)REGION_WIDTH_METERS), fmod(agentPos.mdV[VY], (F64)REGION_WIDTH_METERS), agentPos.mdV[VZ])); } - LLUrlAction::teleportToLocation(LLWeb::escapeURL(std::string("secondlife:///app/teleport/")+slurl.getLocationString())); + LLUrlAction::teleportToLocation(LLWeb::escapeURL("secondlife:///app/teleport/"+slurl.getLocationString())); } return false; } @@ -428,6 +455,15 @@ bool cmd_line_chat(std::string data, EChatType type) } return false; } + else if (cmd == utf8str_tolower(sSetNearbyChatChannelCmd)) // Set nearby chat channel + { + S32 chan; + if (input >> chan) + { + gSavedSettings.setS32("AlchemyNearbyChatChannel", chan); + return false; + } + } else if (cmd == utf8str_tolower(sTeleportToCam)) { gAgent.teleportViaLocation(gAgentCamera.getCameraPositionGlobal()); @@ -445,20 +481,7 @@ bool cmd_line_chat(std::string data, EChatType type) } else if (cmd == utf8str_tolower(sResyncAnimCommand)) // Resync Animations { - for (S32 i = 0; i < gObjectList.getNumObjects(); i++) - { - LLViewerObject* object = gObjectList.getObject(i); - if (object && object->isAvatar()) - { - LLVOAvatar& avatarp = *(LLVOAvatar*)object; - for (LLVOAvatar::AnimIterator it = avatarp.mPlayingAnimations.begin(), end = avatarp.mPlayingAnimations.end(); it != end; ++it) - { - const std::pair& playpair = *it; - avatarp.stopMotion(playpair.first, TRUE); - avatarp.startMotion(playpair.first); - } - } - } + resync_anims(); return false; } else if (cmd == utf8str_tolower(sKeyToName)) @@ -531,7 +554,55 @@ bool cmd_line_chat(std::string data, EChatType type) LLAvatarActions::showProfile(id); return false; } - LLUrlAction::clickAction(sub); + LLUrlAction::clickAction(sub, true); + } + return false; + } + else if (cmd == utf8str_tolower(sSettingCommand)) + { + std::string control_name; + if (input >> control_name) + { + // Find out if this control even exists. + auto control = gSavedSettings.getControl(control_name); + if (!control) gSavedPerAccountSettings.getControl(control_name); + if (!control) return false; + + LLSD val; + // Toggle if we weren't given a value, + if (input.eof()) val = !control->get(); + else // otherwise use what we were given. + { + switch (control->type()) // Convert to the right type, we can't be a string forever. + { + case TYPE_U32: // Integer is Integer, sucks but whatever + case TYPE_S32: + { + LLSD::Integer i; + input >> i; + val = i; + break; + } + case TYPE_F32: + { + LLSD::Float f; + input >> f; + val = f; + break; + } + case TYPE_STRING: + { + LLSD::String str; + std::getline(input, str, '\0'); // Read the entire rest of the stream into str + LLStringUtil::trim(str); // There's no setting where a space would be necessary here. + val = str; + break; + } + default: // Just parse it like JSON (or accept one of the many boolean value options! + LLSDSerialize::fromNotation(val, input, LLSDSerialize::SIZE_UNLIMITED); + } + } + control->set(val); } return false; } @@ -578,22 +649,23 @@ bool cmd_line_chat(std::string data, EChatType type) // even if they are out of draw distance. LLUUID cmdline_partial_name2key(std::string partial_name) { - std::vector avatars; + uuid_vec_t avatars; std::string av_name; LLStringUtil::toLower(partial_name); LLWorld::getInstance()->getAvatars(&avatars); - for(std::vector::const_iterator i = avatars.begin(); i != avatars.end(); ++i) + auto radar = (LLFloaterAvatarList::instanceExists() ? LLFloaterAvatarList::getInstance() : nullptr); + for(const auto& id : avatars) { - if (LLAvatarListEntry* entry = LLFloaterAvatarList::instanceExists() ? LLFloaterAvatarList::instance().getAvatarEntry(*i) : NULL) + if (LLAvatarListEntry* entry = radar ? radar->getAvatarEntry(id) : nullptr) av_name = entry->getName(); - else if (gCacheName->getFullName(*i, av_name)); - else if (LLVOAvatar* avatarp = gObjectList.findAvatar(*i)) + else if (gCacheName->getFullName(id, av_name)); + else if (LLVOAvatar* avatarp = gObjectList.findAvatar(id)) av_name = avatarp->getFullname(); else continue; LLStringUtil::toLower(av_name); if (av_name.find(partial_name) != std::string::npos) - return *i; + return id; } return LLUUID::null; } @@ -650,7 +722,7 @@ void fake_local_chat(std::string msg) chat.mSourceType = CHAT_SOURCE_SYSTEM; if (rlv_handler_t::isEnabled()) chat.mRlvLocFiltered = chat.mRlvNamesFiltered = true; chat.mPosAgent = gAgent.getPositionAgent(); - chat.mURL = "secondlife:///app/agent/" + gAgentID.asString() + "/about"; + chat.mURL = LLAvatarActions::getSLURL(gAgentID); if (action) chat.mChatStyle = CHAT_STYLE_IRC; if (!LLAvatarNameCache::getNSName(gAgentID, chat.mFromName)) { diff --git a/indra/newview/daeexport.cpp b/indra/newview/daeexport.cpp index 71697251c3..9f7ad6d7fc 100644 --- a/indra/newview/daeexport.cpp +++ b/indra/newview/daeexport.cpp @@ -32,15 +32,18 @@ // library includes #include "aifilepicker.h" +#include "llavatarnamecache.h" #include "llnotificationsutil.h" // newview includes #include "lfsimfeaturehandler.h" -#include "llface.h" -#include "llvovolume.h" -#include "llviewerinventory.h" #include "llinventorymodel.h" #include "llinventoryfunctions.h" +#include "llface.h" +#include "llversioninfo.h" +#include "llviewerinventory.h" +#include "llviewertexturelist.h" +#include "llvovolume.h" // menu includes #include "llevent.h" @@ -73,11 +76,11 @@ typedef LLMemberListener view_listener_t; namespace DAEExportUtil { - static LLUUID LL_TEXTURE_PLYWOOD = LLUUID("89556747-24cb-43ed-920b-47caed15465f"); - static LLUUID LL_TEXTURE_BLANK = LLUUID("5748decc-f629-461c-9a36-a35a221fe21f"); - static LLUUID LL_TEXTURE_INVISIBLE = LLUUID("38b86f85-2575-52a9-a531-23108d8da837"); - static LLUUID LL_TEXTURE_TRANSPARENT = LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); - static LLUUID LL_TEXTURE_MEDIA = LLUUID("8b5fec65-8d8d-9dc5-cda8-8fdf2716e361"); + const auto LL_TEXTURE_PLYWOOD = LLUUID("89556747-24cb-43ed-920b-47caed15465f"); + const auto LL_TEXTURE_BLANK = LLUUID("5748decc-f629-461c-9a36-a35a221fe21f"); + const auto LL_TEXTURE_INVISIBLE = LLUUID("38b86f85-2575-52a9-a531-23108d8da837"); + const auto LL_TEXTURE_TRANSPARENT = LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); + const auto LL_TEXTURE_MEDIA = LLUUID("8b5fec65-8d8d-9dc5-cda8-8fdf2716e361"); enum image_format_type { @@ -104,23 +107,17 @@ namespace DAEExportUtil // See if any of the inventory items matching this texture id are exportable ExportPolicy policy = LFSimFeatureHandler::instance().exportPolicy(); - for (size_t i = 0; i < items.size(); i++) + for (const auto& item : items) { - const LLPermissions item_permissions = items[i]->getPermissions(); + const LLPermissions item_permissions = item->getPermissions(); if (item_permissions.allowExportBy(gAgentID, policy)) { - if (name != NULL) - { - (*name) = items[i]->getName(); - } + if (name) *name = item->getName(); return true; } } - if (name != NULL) - { - (*name) = id.getString(); - } + if (name) *name = id.getString(); return (policy & ep_full_perm) == ep_full_perm; } @@ -139,7 +136,7 @@ namespace DAEExportUtil LLViewerObject* obj = node->getObject(); if (obj->isSculpted() && !obj->isMesh()) { - LLSculptParams *sculpt_params = (LLSculptParams *)obj->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = obj->getSculptParams(); LLUUID sculpt_id = sculpt_params->getSculptTexture(); return canExportTexture(sculpt_id); } @@ -205,7 +202,7 @@ class ColladaExportFloater } } - BOOL postBuild() + BOOL postBuild() override { mFileName = getChildView("file name editor"); mExportBtn = getChildView("export button"); @@ -305,14 +302,9 @@ class ColladaExportFloater S32 getNumExportableTextures() { S32 res = 0; - - for (DAESaver::string_list_t::const_iterator t = mSaver.mTextureNames.begin(); t != mSaver.mTextureNames.end(); ++t) + for (const auto& name : mSaver.mTextureNames) { - std::string name = *t; - if (!name.empty()) - { - ++res; - } + if (!name.empty()) ++res; } return res; @@ -364,7 +356,7 @@ class ColladaExportFloater gIdleCallbacks.addFunction(saveTexturesWorker, this); } - class CacheReadResponder : public LLTextureCache::ReadResponder + class CacheReadResponder final : public LLTextureCache::ReadResponder { private: LLPointer mFormattedImage; @@ -412,7 +404,7 @@ class ColladaExportFloater mImageLocal = imagelocal; } - virtual void completed(bool success) + void completed(bool success) override { if (success && mFormattedImage.notNull() && mImageSize > 0) { @@ -493,7 +485,7 @@ class ColladaExportFloater } LLUUID id = me->mTexturesToSave.begin()->first; - LLViewerTexture* imagep = LLViewerTextureManager::findTexture(id); + LLViewerTexture* imagep = LLViewerTextureManager::findFetchedTexture(id, TEX_LIST_STANDARD); if (!imagep) { me->mTexturesToSave.erase(id); @@ -545,10 +537,8 @@ void DAESaver::updateTextureInfo() { LLTextureEntry* te = obj->getTE(face_num); const LLUUID id = te->getID(); - if (std::find(mTextures.begin(), mTextures.end(), id) != mTextures.end()) - { - continue; - } + if (std::find(mTextures.begin(), mTextures.end(), id) != mTextures.end()) continue; + mTextures.push_back(id); std::string name; if (id != DAEExportUtil::LL_TEXTURE_BLANK && DAEExportUtil::canExportTexture(id, &name)) @@ -565,7 +555,6 @@ void DAESaver::updateTextureInfo() } } - class v4adapt { private: @@ -578,7 +567,7 @@ class v4adapt } }; -void DAESaver::addSource(daeElement* mesh, const char* src_id, std::string params, const std::vector &vals) +void DAESaver::addSource(daeElement* mesh, const char* src_id, const std::string& params, const std::vector &vals) { daeElement* source = mesh->add("source"); source->setAttribute("id", src_id); @@ -587,9 +576,9 @@ void DAESaver::addSource(daeElement* mesh, const char* src_id, std::string param src_array->setAttribute("id", llformat("%s-%s", src_id, "array").c_str()); src_array->setAttribute("count", llformat("%d", vals.size()).c_str()); - for (U32 i = 0; i < vals.size(); i++) + for (const auto& val : vals) { - ((domFloat_array*)src_array)->getValue().append(vals[i]); + static_cast(src_array)->getValue().append(val); } domAccessor* acc = daeSafeCast(source->add("technique_common accessor")); @@ -597,10 +586,10 @@ void DAESaver::addSource(daeElement* mesh, const char* src_id, std::string param acc->setCount(vals.size() / params.size()); acc->setStride(params.size()); - for (std::string::iterator p_iter = params.begin(); p_iter != params.end(); ++p_iter) + for (const auto& param : params) { domElement* pX = acc->add("param"); - pX->setAttribute("name", llformat("%c", *p_iter).c_str()); + pX->setAttribute("name", (LLStringUtil::null + param).c_str()); pX->setAttribute("type", "float"); } } @@ -649,7 +638,7 @@ void DAESaver::addPolygons(daeElement* mesh, const char* geomID, const char* mat { for (S32 i = 0; i < face->mNumIndices; i++) { - U16 index = index_offset + face->mIndices[i]; + U32 index = index_offset + face->mIndices[i]; (p->getValue()).append(index); if (i % 3 == 0) { @@ -709,11 +698,21 @@ void DAESaver::transformTexCoord(S32 num_vert, LLVector2* coord, LLVector3* posi bool DAESaver::saveDAE(std::string filename) { + // Collada expects file and folder names to be escaped + // Note: cdom::nativePathToUri() + // Same as in LLDAELoader::OpenFile() + const char* allowed = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "%-._~:\"|\\/"; + std::string uri_filename = LLURI::escape(filename, allowed); + mAllMaterials.clear(); mTotalNumMaterials = 0; DAE dae; // First set the filename to save - daeElement* root = dae.add(filename); + daeElement* root = dae.add(uri_filename); // Obligatory elements in header daeElement* asset = root->add("asset"); @@ -733,9 +732,13 @@ bool DAESaver::saveDAE(std::string filename) up_axis->setCharData("Z_UP"); // File creator + std::string author; + if (!LLAvatarNameCache::getNSName(gAgentID, author)) + author = "Unknown"; + daeElement* contributor = asset->add("contributor"); - contributor->add("author")->setCharData(LLAppViewer::instance()->getSecondLifeTitle() + " User"); - contributor->add("authoring_tool")->setCharData(LLAppViewer::instance()->getSecondLifeTitle() + " Collada Export"); + contributor->add("author")->setCharData(author); + contributor->add("authoring_tool")->setCharData(LLVersionInfo::getChannelAndVersion() + " Collada Export"); daeElement* images = root->add("library_images"); daeElement* geomLib = root->add("library_geometries"); @@ -824,7 +827,6 @@ bool DAESaver::saveDAE(std::string filename) } } - addSource(mesh, llformat("%s-%s", geomID, "positions").c_str(), "XYZ", position_data); addSource(mesh, llformat("%s-%s", geomID, "normals").c_str(), "XYZ", normal_data); addSource(mesh, llformat("%s-%s", geomID, "map0").c_str(), "ST", uv_data); @@ -844,12 +846,11 @@ bool DAESaver::saveDAE(std::string filename) // Add triangles if (gSavedSettings.getBOOL("DAEExportConsolidateMaterials")) { - for (U32 objMaterial = 0; objMaterial < objMaterials.size(); objMaterial++) + for (const auto& objMaterial : objMaterials) { int_list_t faces; - getFacesWithMaterial(obj, objMaterials[objMaterial], &faces); - std::string matName = objMaterials[objMaterial].name; - addPolygons(mesh, geomID, (matName + "-material").c_str(), obj, &faces); + getFacesWithMaterial(obj, objMaterial, &faces); + addPolygons(mesh, geomID, (objMaterial.name + "-material").c_str(), obj, &faces); } } else @@ -887,12 +888,12 @@ bool DAESaver::saveDAE(std::string filename) // Bind materials daeElement* tq = nodeGeometry->add("bind_material technique_common"); - for (U32 objMaterial = 0; objMaterial < objMaterials.size(); objMaterial++) + for (const auto& objMaterial : objMaterials) { - std::string matName = objMaterials[objMaterial].name; daeElement* instanceMaterial = tq->add("instance_material"); - instanceMaterial->setAttribute("symbol", (matName + "-material").c_str()); - instanceMaterial->setAttribute("target", ("#" + matName + "-material").c_str()); + std::string matName = objMaterial.name + "-material"; + instanceMaterial->setAttribute("symbol", matName.c_str()); + instanceMaterial->setAttribute("target", ('#' + matName).c_str()); } nodeGeometry->setAttribute("url", llformat("#%s-%s", geomID, "mesh").c_str()); @@ -903,12 +904,12 @@ bool DAESaver::saveDAE(std::string filename) generateEffects(effects); // Materials - for (U32 objMaterial = 0; objMaterial < mAllMaterials.size(); objMaterial++) + for (const auto& objMaterial : mAllMaterials) { daeElement* mat = materials->add("material"); - mat->setAttribute("id", (mAllMaterials[objMaterial].name + "-material").c_str()); + mat->setAttribute("id", (objMaterial.name + "-material").c_str()); daeElement* matEffect = mat->add("instance_effect"); - matEffect->setAttribute("url", ("#" + mAllMaterials[objMaterial].name + "-fx").c_str()); + matEffect->setAttribute("url", ('#' + objMaterial.name + "-fx").c_str()); } root->add("scene instance_visual_scene")->setAttribute("url", "#Scene"); @@ -929,11 +930,11 @@ DAESaver::MaterialInfo DAESaver::getMaterial(LLTextureEntry* te) { if (gSavedSettings.getBOOL("DAEExportConsolidateMaterials")) { - for (U32 i=0; i < mAllMaterials.size(); i++) + for (const auto& mat : mAllMaterials) { - if (mAllMaterials[i].matches(te)) + if (mat.matches(te)) { - return mAllMaterials[i]; + return mat; } } } @@ -943,7 +944,7 @@ DAESaver::MaterialInfo DAESaver::getMaterial(LLTextureEntry* te) ret.color = te->getColor(); ret.name = llformat("Material%d", mAllMaterials.size()); mAllMaterials.push_back(ret); - return mAllMaterials[mAllMaterials.size() - 1]; + return ret; } void DAESaver::getMaterials(LLViewerObject* obj, material_list_t* ret) @@ -953,10 +954,7 @@ void DAESaver::getMaterials(LLViewerObject* obj, material_list_t* ret) { LLTextureEntry* te = obj->getTE(face_num); - if (skipFace(te)) - { - continue; - } + if (skipFace(te)) continue; MaterialInfo mat = getMaterial(te); @@ -967,7 +965,7 @@ void DAESaver::getMaterials(LLViewerObject* obj, material_list_t* ret) } } -void DAESaver::getFacesWithMaterial(LLViewerObject* obj, MaterialInfo& mat, int_list_t* ret) +void DAESaver::getFacesWithMaterial(LLViewerObject* obj, const MaterialInfo& mat, int_list_t* ret) { S32 num_faces = obj->getVolume()->getNumVolumeFaces(); for (S32 face_num = 0; face_num < num_faces; ++face_num) @@ -984,11 +982,11 @@ void DAESaver::generateEffects(daeElement *effects) // Effects (face color, alpha) bool export_textures = gSavedSettings.getBOOL("DAEExportTextures"); - for (U32 mat = 0; mat < mAllMaterials.size(); mat++) + for (const auto& mat : mAllMaterials) { - LLColor4 color = mAllMaterials[mat].color; + LLColor4 color = mat.color; domEffect* effect = (domEffect*)effects->add("effect"); - effect->setId((mAllMaterials[mat].name + "-fx").c_str()); + effect->setId((mat.name + "-fx").c_str()); daeElement* profile = effect->add("profile_COMMON"); std::string colladaName; @@ -998,7 +996,7 @@ void DAESaver::generateEffects(daeElement *effects) U32 i = 0; for (; i < mTextures.size(); i++) { - if (mAllMaterials[mat].textureID == mTextures[i]) + if (mat.textureID == mTextures[i]) { textID = mTextures[i]; break; @@ -1042,19 +1040,18 @@ void DAESaver::generateEffects(daeElement *effects) void DAESaver::generateImagesSection(daeElement* images) { - for (U32 i=0; i < mTextureNames.size(); i++) + for (const auto& name : mTextureNames) { - std::string name = mTextureNames[i]; if (name.empty()) continue; - std::string colladaName = name + "_" + mImageFormat; + std::string colladaName = name + '_' + mImageFormat; daeElement* image = images->add("image"); image->setAttribute("id", colladaName.c_str()); image->setAttribute("name", colladaName.c_str()); - image->add("init_from")->setCharData(LLURI::escape(name + "." + mImageFormat)); + image->add("init_from")->setCharData(LLURI::escape(name + '.' + mImageFormat)); } } -class DAESaveSelectedObjects : public view_listener_t +class DAESaveSelectedObjects final : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { diff --git a/indra/newview/daeexport.h b/indra/newview/daeexport.h index fbdd5b84cf..1f79aa17af 100644 --- a/indra/newview/daeexport.h +++ b/indra/newview/daeexport.h @@ -33,51 +33,30 @@ class LLViewerObject; class DAESaver { public: - class MaterialInfo + struct MaterialInfo { - public: LLUUID textureID; LLColor4 color; std::string name; - bool matches(LLTextureEntry* te) + bool matches(LLTextureEntry* te) const { return (textureID == te->getID()) && (color == te->getColor()); } - bool operator== (const MaterialInfo& rhs) + bool operator== (const MaterialInfo& rhs) const { return (textureID == rhs.textureID) && (color == rhs.color) && (name == rhs.name); } - bool operator!= (const MaterialInfo& rhs) + bool operator!= (const MaterialInfo& rhs) const { return !(*this == rhs); } - - MaterialInfo() - { - } - - MaterialInfo(const MaterialInfo& rhs) - { - textureID = rhs.textureID; - color = rhs.color; - name = rhs.name; - } - - MaterialInfo& operator= (const MaterialInfo& rhs) - { - textureID = rhs.textureID; - color = rhs.color; - name = rhs.name; - return *this; - } - }; - typedef std::vector > obj_info_t; - typedef std::vector id_list_t; + typedef std::vector> obj_info_t; + typedef uuid_vec_t id_list_t; typedef std::vector string_list_t; typedef std::vector int_list_t; typedef std::vector material_list_t; @@ -97,12 +76,12 @@ class DAESaver private: void transformTexCoord(S32 num_vert, LLVector2* coord, LLVector3* positions, LLVector3* normals, LLTextureEntry* te, LLVector3 scale); - void addSource(daeElement* mesh, const char* src_id, std::string params, const std::vector &vals); + void addSource(daeElement* mesh, const char* src_id, const std::string& params, const std::vector &vals); void addPolygons(daeElement* mesh, const char* geomID, const char* materialID, LLViewerObject* obj, int_list_t* faces_to_include); bool skipFace(LLTextureEntry *te); MaterialInfo getMaterial(LLTextureEntry* te); void getMaterials(LLViewerObject* obj, material_list_t* ret); - void getFacesWithMaterial(LLViewerObject* obj, MaterialInfo& mat, int_list_t* ret); + void getFacesWithMaterial(LLViewerObject* obj, const MaterialInfo& mat, int_list_t* ret); void generateEffects(daeElement *effects); void generateImagesSection(daeElement* images); }; diff --git a/indra/newview/floaterao.cpp b/indra/newview/floaterao.cpp index 0d584e6e59..973c4e233e 100644 --- a/indra/newview/floaterao.cpp +++ b/indra/newview/floaterao.cpp @@ -1,79 +1,61 @@ -/** +/** * @file llfloaterao.cpp - * @brief clientside animation overrider - * by Skills Hak + * @brief clientside animation overrider floater + * by Skills Hak & Liru Frs */ #include "llviewerprecompiledheaders.h" #include "floaterao.h" +#include "aosystem.h" #include "llagent.h" -#include "llagentcamera.h" -#include "llvoavatarself.h" -#include "llanimationstates.h" -#include "lluictrlfactory.h" -#include "llstartup.h" -#include "llpreviewnotecard.h" -#include "llviewertexteditor.h" -#include "llcheckboxctrl.h" #include "llcombobox.h" -#include "llspinctrl.h" -#include "chatbar_as_cmdline.h" -//#include "llfloaterchat.h" #include "llfirstuse.h" -#include "lltrans.h" - -#include "llinventory.h" -#include "llinventoryfunctions.h" #include "llinventorypanel.h" -#include "llinventorymodelbackgroundfetch.h" +#include "llmemorystream.h" +#include "llpreviewnotecard.h" +#include "lltexteditor.h" +#include "lluictrlfactory.h" #include "roles_constants.h" -#include "llviewerregion.h" - -#include "llpanelobjectinventory.h" -#include "llinventorybridge.h" - -#include "llboost.h" -#include // Uncomment and use instead if we ever add the chatbar as a command line - MC void cmdline_printchat(const std::string& message); -class AONotecardCallback : public LLInventoryCallback +class AONotecardCallback final : public LLInventoryCallback { public: - AONotecardCallback(std::string &filename) - { - mFileName = filename; - } + AONotecardCallback(const std::string& filename) : mFileName(filename) {} - void fire(const LLUUID &inv_item) + void fire(const LLUUID &inv_item) override { if (!mFileName.empty()) { - LLPreviewNotecard* nc; - nc = (LLPreviewNotecard*)LLPreview::find(inv_item); - if(nc) + auto nc = (LLPreviewNotecard*)LLPreview::show(inv_item); + if (!nc) + { + auto item = gInventory.getItem(inv_item); + open_notecard(item, "Note: " + item->getName(), LLUUID::null, false); + nc = (LLPreviewNotecard*)LLPreview::find(inv_item); + } + + if (nc) { - nc->open(); - LLTextEditor *text = nc->getEditor(); - if (text) + if (LLTextEditor *text = nc->getEditor()) { text->clear(); text->makePristine(); std::ifstream file(mFileName.c_str()); - + std::string line; while (!file.eof()) - { + { getline(file, line); - line = line + "\n"; - text->insertText(line); + text->insertText(line + '\n'); } file.close(); - + nc->saveIfNeeded(); } } @@ -84,1245 +66,169 @@ class AONotecardCallback : public LLInventoryCallback std::string mFileName; }; -AOInvTimer* gAOInvTimer = NULL; - - -// ------------------------------------------------------- -AOStandTimer* mAOStandTimer; - -AOStandTimer::AOStandTimer() : LLEventTimer( gSavedSettings.getF32("AOStandInterval") ) -{ - AOStandTimer::tick(); -} -AOStandTimer::~AOStandTimer() -{ -// LL_INFOS() << "dead" << LL_ENDL; -} -void AOStandTimer::reset() +LLFloaterAO::LLFloaterAO(const LLSD&) : LLFloater("floater_ao") +, mCombos({}) { - mPeriod = gSavedSettings.getF32("AOStandInterval"); - mEventTimer.reset(); -// LL_INFOS() << "reset" << LL_ENDL; + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_ao.xml", nullptr, false); } -BOOL AOStandTimer::tick() -{ - LLFloaterAO::stand_iterator++; -// LL_INFOS() << "tick" << LL_ENDL; - LLFloaterAO::ChangeStand(); - return FALSE; -// return LLFloaterAO::ChangeStand(); //timer is always active now .. -} - -// ------------------------------------------------------- - -AOInvTimer::AOInvTimer() : LLEventTimer( (F32)1.0 ) -{ -} -AOInvTimer::~AOInvTimer() -{ -} -BOOL AOInvTimer::tick() -{ - if (!(gSavedSettings.getBOOL("AOEnabled"))) return TRUE; - if(LLStartUp::getStartupState() >= STATE_INVENTORY_SEND) - { - if(LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) - { -// cmdline_printchat("Inventory fetched, loading AO."); - LLFloaterAO::init(); - return TRUE; - } - } - return FALSE; -} - -// STUFF ------------------------------------------------------- - -int LLFloaterAO::mAnimationState = 0; -int LLFloaterAO::stand_iterator = 0; - -LLUUID LLFloaterAO::invfolderid = LLUUID::null; -LLUUID LLFloaterAO::mCurrentStandId = LLUUID::null; - -LLComboBox* mcomboBox_stands; -LLComboBox* mcomboBox_walks; -LLComboBox* mcomboBox_runs; -LLComboBox* mcomboBox_jumps; -LLComboBox* mcomboBox_sits; -LLComboBox* mcomboBox_gsits; -LLComboBox* mcomboBox_crouchs; -LLComboBox* mcomboBox_cwalks; -LLComboBox* mcomboBox_falls; -LLComboBox* mcomboBox_hovers; -LLComboBox* mcomboBox_flys; -LLComboBox* mcomboBox_flyslows; -LLComboBox* mcomboBox_flyups; -LLComboBox* mcomboBox_flydowns; -LLComboBox* mcomboBox_lands; -LLComboBox* mcomboBox_standups; -LLComboBox* mcomboBox_prejumps; - -struct struct_overrides -{ - LLUUID orig_id; - LLUUID ao_id; - int state; -}; -std::vector mAOOverrides; -struct struct_stands +void LLFloaterAO::onOpen() { - LLUUID ao_id; - std::string anim_name; -}; -std::vector mAOStands; - -struct struct_tokens -{ - std::string token; - int state; -}; -std::vector mAOTokens; - -LLFloaterAO* LLFloaterAO::sInstance = NULL; - -LLFloaterAO::LLFloaterAO() -:LLFloater(std::string("floater_ao")) -{ -// init(); - llassert_always(sInstance == NULL); - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_ao.xml"); - sInstance = this; + LLFirstUse::useAO(); } LLFloaterAO::~LLFloaterAO() { - sInstance=NULL; - mcomboBox_stands = 0; - mcomboBox_walks = 0; - mcomboBox_runs = 0; - mcomboBox_jumps = 0; - mcomboBox_sits = 0; - mcomboBox_gsits = 0; - mcomboBox_crouchs = 0; - mcomboBox_cwalks = 0; - mcomboBox_falls = 0; - mcomboBox_hovers = 0; - mcomboBox_flys = 0; - mcomboBox_flyslows = 0; - mcomboBox_flyups = 0; - mcomboBox_flydowns = 0; - mcomboBox_lands = 0; - mcomboBox_standups = 0; - mcomboBox_prejumps = 0; // LL_INFOS() << "floater destroyed" << LL_ENDL; } -void LLFloaterAO::show(void*) -{ - if (!sInstance) - { - sInstance = new LLFloaterAO(); - updateLayout(sInstance); - init(); - - sInstance->open(); - } - else - { - sInstance->close(); - } - LLFirstUse::useAO(); -} - -bool LLFloaterAO::getInstance() -{ - if (sInstance) - return true; - else - return false; -} - BOOL LLFloaterAO::postBuild() { - childSetAction("more_btn", onClickMore, this); - childSetAction("less_btn", onClickLess, this); - - childSetAction("reloadcard",onClickReloadCard,this); - childSetAction("opencard",onClickOpenCard,this); - childSetAction("newcard",onClickNewCard,this); - childSetAction("prevstand",onClickPrevStand,this); - childSetAction("nextstand",onClickNextStand,this); - getChild("AOEnabled")->setCommitCallback(boost::bind(&LLFloaterAO::onClickToggleAO)); - getChild("AOSitsEnabled")->setCommitCallback(boost::bind(&LLFloaterAO::onClickToggleSits)); - getChild("standtime")->setCommitCallback(boost::bind(&LLFloaterAO::onSpinnerCommit,_1)); - mcomboBox_stands = getChild("stands"); - mcomboBox_walks = getChild("walks"); - mcomboBox_runs = getChild("runs"); - mcomboBox_jumps = getChild("jumps"); - mcomboBox_sits = getChild("sits"); - mcomboBox_gsits = getChild("gsits"); - mcomboBox_crouchs = getChild("crouchs"); - mcomboBox_cwalks = getChild("cwalks"); - mcomboBox_falls = getChild("falls"); - mcomboBox_hovers = getChild("hovers"); - mcomboBox_flys = getChild("flys"); - mcomboBox_flyslows = getChild("flyslows"); - mcomboBox_flyups = getChild("flyups"); - mcomboBox_flydowns = getChild("flydowns"); - mcomboBox_lands = getChild("lands"); - mcomboBox_standups = getChild("standups"); - mcomboBox_prejumps = getChild("prejumps"); - getChild("stands")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("walks")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("runs")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("jumps")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("sits")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("gsits")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("crouchs")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("cwalks")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("falls")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("hovers")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("flys")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("flyslows")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("flyups")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("flydowns")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("lands")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("standups")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - getChild("prejumps")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - - return TRUE; -} - -void LLFloaterAO::onSpinnerCommit(LLUICtrl* ctrl) -{ - LLSpinCtrl* spin = (LLSpinCtrl*) ctrl; - if(spin) - { - if (spin->getName() == "standtime") - { - if (mAOStandTimer) mAOStandTimer->reset(); - } - } -} - -void LLFloaterAO::onComboBoxCommit(LLUICtrl* ctrl) -{ - LLComboBox* box = (LLComboBox*)ctrl; - if(box) - { - if (box->getName() == "stands") - { - stand_iterator = box->getCurrentIndex(); - cmdline_printchat(llformat("Changing stand to %s.",mAOStands[stand_iterator].anim_name.c_str())); - ChangeStand(); - } - else - { - int state = STATE_AGENT_IDLE; - std::string stranim = box->getValue().asString(); -// LL_INFOS() << "state " << (gAgentAvatarp->isSitting()) << " - " << getAnimationState() << LL_ENDL; - if (box->getName() == "walks") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_WALK), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultWalk",stranim); - state = STATE_AGENT_WALK; - } - else if (box->getName() == "runs") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_RUN), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultRun",stranim); - state = STATE_AGENT_RUN; - } - else if (box->getName() == "jumps") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_JUMP), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultJump",stranim); - state = STATE_AGENT_JUMP; - } - else if (box->getName() == "sits") - { - if (gAgentAvatarp && (gSavedSettings.getBOOL("AOEnabled")) && (gSavedSettings.getBOOL("AOSitsEnabled"))) - { - if ((gAgentAvatarp->isSitting()) && (getAnimationState() == STATE_AGENT_SIT)) - { -// LL_INFOS() << "sitting " << GetAnimID(ANIM_AGENT_SIT) << " " << getAssetIDByName(stranim) << LL_ENDL; - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_SIT), ANIM_REQUEST_STOP); - gAgent.sendAnimationRequest(getAssetIDByName(stranim), ANIM_REQUEST_START); - } - } - gSavedPerAccountSettings.setString("AODefaultSit",stranim); - state = STATE_AGENT_SIT; - } - else if (box->getName() == "gsits") - { -// LL_INFOS() << "gsitting " << GetAnimID(ANIM_AGENT_SIT_GROUND) << " " << getAssetIDByName(stranim) << LL_ENDL; - if (gAgentAvatarp) - { - if ((gAgentAvatarp->isSitting()) && (getAnimationState() == STATE_AGENT_GROUNDSIT)) - { -// LL_INFOS() << "gsitting " << GetAnimID(ANIM_AGENT_SIT_GROUND) << " " << getAssetIDByName(stranim) << LL_ENDL; - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_SIT_GROUND), ANIM_REQUEST_STOP); - gAgent.sendAnimationRequest(getAssetIDByName(stranim), ANIM_REQUEST_START); - } - } - gSavedPerAccountSettings.setString("AODefaultGroundSit",stranim); - state = STATE_AGENT_GROUNDSIT; - } - else if (box->getName() == "crouchs") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_CROUCH), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultCrouch",stranim); - state = STATE_AGENT_CROUCH; - } - else if (box->getName() == "cwalks") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_CROUCHWALK), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultCrouchWalk",stranim); - state = STATE_AGENT_CROUCHWALK; - } - else if (box->getName() == "falls") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_FALLDOWN), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultFall",stranim); - state = STATE_AGENT_FALLDOWN; - } - else if (box->getName() == "hovers") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_HOVER), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultHover",stranim); - state = STATE_AGENT_HOVER; - } - else if (box->getName() == "flys") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_FLY), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultFly",stranim); - state = STATE_AGENT_FLY; - } - else if (box->getName() == "flyslows") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_FLYSLOW), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultFlySlow",stranim); - state = STATE_AGENT_FLYSLOW; + gSavedSettings.getControl("AOAdvanced")->getSignal()->connect(boost::bind(&LLFloaterAO::updateLayout, this, _2)); + + getChild("reloadcard")->setCommitCallback(boost::bind(&LLFloaterAO::onClickReloadCard, this)); + getChild("opencard")->setCommitCallback(boost::bind(&LLFloaterAO::onClickOpenCard, this)); + getChild("newcard")->setCommitCallback(boost::bind(&LLFloaterAO::onClickNewCard, this)); + getChild("prevstand")->setCommitCallback(boost::bind(&LLFloaterAO::onClickCycleStand, this, false)); + getChild("nextstand")->setCommitCallback(boost::bind(&LLFloaterAO::onClickCycleStand, this, true)); + getChild("standtime")->setCommitCallback(boost::bind(&LLFloaterAO::onSpinnerCommit, this)); + + auto ao = AOSystem::getIfExists(); + const auto& cb = boost::bind(&LLFloaterAO::onComboBoxCommit, this, _1); + const auto& setup_combo = [&](const std::string& name, const AOState& state) { + if (auto combo = findChild(name)) + { + combo->setCommitCallback(cb); + LLControlVariablePtr setting = nullptr; + if (auto aop = ao ? ao->mAOOverrides[state] : nullptr) + setting = aop->setting; + else // AO is down or missing override struct(why?), try getting from UI + setting = combo->getControl(combo->getControlName()); + if (setting) combo->add(setting->get().asStringRef(), ADD_BOTTOM, true); + mCombos[state] = combo; + } + }; + setup_combo("stands", STATE_AGENT_IDLE); + setup_combo("walks", STATE_AGENT_WALK); + setup_combo("runs", STATE_AGENT_RUN); + setup_combo("prejumps", STATE_AGENT_PRE_JUMP); + setup_combo("jumps", STATE_AGENT_JUMP); + setup_combo("turnlefts", STATE_AGENT_TURNLEFT); + setup_combo("turnrights", STATE_AGENT_TURNRIGHT); + setup_combo("sits", STATE_AGENT_SIT); + setup_combo("gsits", STATE_AGENT_SIT_GROUND); + setup_combo("hovers", STATE_AGENT_HOVER); + setup_combo("flydowns", STATE_AGENT_HOVER_DOWN); + setup_combo("flyups", STATE_AGENT_HOVER_UP); + setup_combo("crouchs", STATE_AGENT_CROUCH); + setup_combo("cwalks", STATE_AGENT_CROUCHWALK); + setup_combo("falls", STATE_AGENT_FALLDOWN); + setup_combo("standups", STATE_AGENT_STANDUP); + setup_combo("lands", STATE_AGENT_LAND); + setup_combo("flys", STATE_AGENT_FLY); + setup_combo("flyslows", STATE_AGENT_FLYSLOW); + setup_combo("typings", STATE_AGENT_TYPE); + setup_combo("swimdowns", STATE_AGENT_SWIM_DOWN); + setup_combo("swimups", STATE_AGENT_SWIM_UP); + setup_combo("swims", STATE_AGENT_SWIM); + setup_combo("floats", STATE_AGENT_FLOAT); + + updateLayout(gSavedSettings.getBOOL("AOAdvanced")); + AOSystem::requestConfigNotecard(false); + + return true; +} + +void LLFloaterAO::updateLayout(bool advanced) +{ + reshape(advanced ? 800 : 200, getRect().getHeight()); + childSetVisible("tabcontainer", advanced); +} + +void LLFloaterAO::onSpinnerCommit() const +{ + if (auto ao = AOSystem::getIfExists()) + ao->mAOStandTimer.reset(); +} + +void LLFloaterAO::onComboBoxCommit(LLUICtrl* ctrl) const +{ + if (LLComboBox* box = (LLComboBox*)ctrl) + { + std::string stranim = box->getValue().asString(); + if (auto ao = AOSystem::getIfExists()) + { + if (box == mCombos[STATE_AGENT_IDLE]) + { + ao->stand_iterator = box->getCurrentIndex(); + llassert(ao->stand_iterator < ao->mAOStands.size()); + const auto& name = ao->mAOStands[ao->stand_iterator].anim_name; + llassert(name == box->getValue().asStringRef()); + cmdline_printchat("Changing stand to " + name + '.'); + ao->updateStand(); + ao->mAOStandTimer.reset(); } - else if (box->getName() == "flyups") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_HOVER_UP), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultFlyUp",stranim); - state = STATE_AGENT_HOVER_UP; - } - else if (box->getName() == "flydowns") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_HOVER_DOWN), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultFlyDown",stranim); - state = STATE_AGENT_HOVER_DOWN; - } - else if (box->getName() == "lands") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_LAND), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultLand",stranim); - state = STATE_AGENT_LAND; - } - else if (box->getName() == "standups") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_STAND), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultStandUp",stranim); - state = STATE_AGENT_STAND; - } - else if (box->getName() == "prejumps") - { - gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_PRE_JUMP), ANIM_REQUEST_STOP); - gSavedPerAccountSettings.setString("AODefaultPreJump",stranim); - state = STATE_AGENT_PRE_JUMP; - } - for (std::vector::iterator iter = mAOOverrides.begin(); iter != mAOOverrides.end(); ++iter) - { - if (state == iter->state) - { - iter->ao_id = getAssetIDByName(stranim); - } - } - } - } -} - -void LLFloaterAO::updateLayout(LLFloaterAO* floater) -{ - if (floater) - { - BOOL advanced = gSavedSettings.getBOOL( "AOAdvanced"); - if (advanced) - { - floater->reshape(610,380); //view->getRect().getWidth(), view->getUIWinHeightLong()); - } - else - { - floater->reshape(200,380); //view->getRect().getWidth(), view->getUIWinHeightShort()); - } - - floater->childSetVisible("more_btn", !advanced); - floater->childSetVisible("less_btn", advanced); - - floater->childSetVisible("tabcontainer", advanced); - floater->childSetVisible("tabdefaultanims", advanced); - - floater->childSetVisible("textdefaultwalk", advanced); - floater->childSetVisible("textdefaultrun", advanced); - floater->childSetVisible("textdefaultjump", advanced); - floater->childSetVisible("textdefaultsit", advanced); - floater->childSetVisible("textdefaultgsit", advanced); - floater->childSetVisible("textdefaultcrouch", advanced); - floater->childSetVisible("textdefaultcrouchwalk", advanced); - floater->childSetVisible("textdefaultfall", advanced); - floater->childSetVisible("textdefaulthover", advanced); - floater->childSetVisible("textdefaultfly", advanced); - floater->childSetVisible("textdefaultflyslow", advanced); - floater->childSetVisible("textdefaultflyup", advanced); - floater->childSetVisible("textdefaultflydown", advanced); - floater->childSetVisible("textdefaultland", advanced); - floater->childSetVisible("textdefaultstandup", advanced); - floater->childSetVisible("textdefaultprejump", advanced); - - - floater->childSetVisible("walks", advanced); - floater->childSetVisible("runs", advanced); - floater->childSetVisible("jumps", advanced); - floater->childSetVisible("sits", advanced); - floater->childSetVisible("gsits", advanced); - floater->childSetVisible("crouchs", advanced); - floater->childSetVisible("falls", advanced); - floater->childSetVisible("hovers", advanced); - floater->childSetVisible("flys", advanced); - floater->childSetVisible("flyslows", advanced); - floater->childSetVisible("flyups", advanced); - floater->childSetVisible("flydowns", advanced); - floater->childSetVisible("lands", advanced); - floater->childSetVisible("standups", advanced); - floater->childSetVisible("prejumps", advanced); - } -} - -void LLFloaterAO::init() -{ - mAOStands.clear(); - mAOTokens.clear(); - mAOOverrides.clear(); - - struct_tokens tokenloader; - tokenloader.token = - tokenloader.token = "[ Sitting On Ground ]"; tokenloader.state = STATE_AGENT_GROUNDSIT; mAOTokens.push_back(tokenloader); // 0 - tokenloader.token = "[ Sitting ]"; tokenloader.state = STATE_AGENT_SIT; mAOTokens.push_back(tokenloader); // 1 - tokenloader.token = "[ Crouching ]"; tokenloader.state = STATE_AGENT_CROUCH; mAOTokens.push_back(tokenloader); // 3 - tokenloader.token = "[ Crouch Walking ]"; tokenloader.state = STATE_AGENT_CROUCHWALK; mAOTokens.push_back(tokenloader); // 4 - tokenloader.token = "[ Standing Up ]"; tokenloader.state = STATE_AGENT_STANDUP; mAOTokens.push_back(tokenloader); // 6 - tokenloader.token = "[ Falling ]"; tokenloader.state = STATE_AGENT_FALLDOWN; mAOTokens.push_back(tokenloader); // 7 - tokenloader.token = "[ Flying Down ]"; tokenloader.state = STATE_AGENT_HOVER_DOWN; mAOTokens.push_back(tokenloader); // 8 - tokenloader.token = "[ Flying Up ]"; tokenloader.state = STATE_AGENT_HOVER_UP; mAOTokens.push_back(tokenloader); // 9 - tokenloader.token = "[ Flying Slow ]"; tokenloader.state = STATE_AGENT_FLYSLOW; mAOTokens.push_back(tokenloader); // 10 - tokenloader.token = "[ Flying ]"; tokenloader.state = STATE_AGENT_FLY; mAOTokens.push_back(tokenloader); // 11 - tokenloader.token = "[ Hovering ]"; tokenloader.state = STATE_AGENT_HOVER; mAOTokens.push_back(tokenloader); // 12 - tokenloader.token = "[ Jumping ]"; tokenloader.state = STATE_AGENT_JUMP; mAOTokens.push_back(tokenloader); // 13 - tokenloader.token = "[ Pre Jumping ]"; tokenloader.state = STATE_AGENT_PRE_JUMP; mAOTokens.push_back(tokenloader); // 14 - tokenloader.token = "[ Running ]"; tokenloader.state = STATE_AGENT_RUN; mAOTokens.push_back(tokenloader); // 15 - tokenloader.token = "[ Turning Right ]"; tokenloader.state = STATE_AGENT_TURNRIGHT; mAOTokens.push_back(tokenloader); // 16 - tokenloader.token = "[ Turning Left ]"; tokenloader.state = STATE_AGENT_TURNLEFT; mAOTokens.push_back(tokenloader); // 17 - tokenloader.token = "[ Walking ]"; tokenloader.state = STATE_AGENT_WALK; mAOTokens.push_back(tokenloader); // 18 - tokenloader.token = "[ Landing ]"; tokenloader.state = STATE_AGENT_LAND; mAOTokens.push_back(tokenloader); // 19 - tokenloader.token = "[ Standing ]"; tokenloader.state = STATE_AGENT_STAND; mAOTokens.push_back(tokenloader); // 20 - tokenloader.token = "[ Swimming Down ]"; tokenloader.state = 999; mAOTokens.push_back(tokenloader); // 21 - tokenloader.token = "[ Swimming Up ]"; tokenloader.state = 999; mAOTokens.push_back(tokenloader); // 22 - tokenloader.token = "[ Swimming Forward ]"; tokenloader.state = 999; mAOTokens.push_back(tokenloader); // 23 - tokenloader.token = "[ Floating ]"; tokenloader.state = 999; mAOTokens.push_back(tokenloader); // 24 - - struct_overrides overrideloader; - overrideloader.orig_id = ANIM_AGENT_WALK; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_WALK; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_RUN; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_RUN; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_PRE_JUMP; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_PRE_JUMP; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_JUMP; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_JUMP; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_TURNLEFT; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_TURNLEFT; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_TURNRIGHT; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_TURNRIGHT; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_SIT; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_SIT; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_SIT_FEMALE; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_SIT; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_SIT_GENERIC; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_SIT; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_SIT_GROUND; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_GROUNDSIT; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_SIT_GROUND_CONSTRAINED; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_GROUNDSIT; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_HOVER; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_HOVER; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_HOVER_DOWN; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_HOVER_DOWN; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_HOVER_UP; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_HOVER_UP; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_CROUCH; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_CROUCH; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_CROUCHWALK; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_CROUCHWALK; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_FALLDOWN; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_FALLDOWN; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_STANDUP; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_STANDUP; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_LAND; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_LAND; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_FLY; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_FLY; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_FLYSLOW; overrideloader.ao_id = LLUUID::null; overrideloader.state = STATE_AGENT_FLYSLOW; mAOOverrides.push_back(overrideloader); - - BOOL success = TRUE; - - if(LLStartUp::getStartupState() >= STATE_INVENTORY_SEND) - { - if(LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) - { - LLUUID configncitem = (LLUUID)gSavedPerAccountSettings.getString("AOConfigNotecardID"); - if (configncitem.notNull()) + else { - success = FALSE; - const LLInventoryItem* item = gInventory.getItem(configncitem); - if(item) + auto end = mCombos.end(); + auto it = std::find(mCombos.begin(), end, box); + llassert(it != end); + const auto state = std::distance(mCombos.begin(), it); + if (auto aop = ao->mAOOverrides[state]) { - if (gAgent.allowOperation(PERM_COPY, item->getPermissions(),GP_OBJECT_MANIPULATE) || gAgent.isGodlike()) - { - if(!item->getAssetUUID().isNull()) - { - LLUUID* new_uuid = new LLUUID(configncitem); - LLHost source_sim = LLHost::invalid; - invfolderid = item->getParentUUID(); - gAssetStorage->getInvItemAsset(source_sim, - gAgent.getID(), - gAgent.getSessionID(), - item->getPermissions().getOwner(), - LLUUID::null, - item->getUUID(), - item->getAssetUUID(), - item->getType(), - &onNotecardLoadComplete, - (void*)new_uuid, - TRUE); - success = TRUE; - } - } + LLUUID getAssetIDByName(const std::string & name); +// LL_INFOS() << "state " << state << " - " << aop->playing() << LL_ENDL; + bool was_playing = aop->playing; + if (was_playing) aop->play(false); + aop->ao_id = getAssetIDByName(stranim); + if (was_playing) aop->play(); } } } + gSavedPerAccountSettings.setString(ctrl->getControlName(), stranim); } - - if (!success) - { - cmdline_printchat("Could not read the specified Config Notecard"); - } - -// mAnimationState = 0; -// mCurrentStandId = LLUUID::null; -// setAnimationState(STATE_AGENT_IDLE); - -} - -void LLFloaterAO::onClickMore(void* data) -{ - gSavedSettings.setBOOL( "AOAdvanced", TRUE ); - updateLayout(sInstance); -} -void LLFloaterAO::onClickLess(void* data) -{ - gSavedSettings.setBOOL( "AOAdvanced", FALSE ); - updateLayout(sInstance); -} - -void LLFloaterAO::onClickToggleAO() -{ - run(); -} - -void LLFloaterAO::onClickToggleSits() -{ - run(); -} - - -void LLFloaterAO::run() -{ - setAnimationState(STATE_AGENT_IDLE); // reset state - int state = getAnimationState(); // check if sitting or hovering - if ((state == STATE_AGENT_IDLE) || (state == STATE_AGENT_STAND)) - { - if (gSavedSettings.getBOOL("AOEnabled")) - { - if (mAOStandTimer) - { - mAOStandTimer->reset(); - ChangeStand(); - } - else - { - mAOStandTimer = new AOStandTimer(); - } - } - else - { - stopMotion(getCurrentStandId(), FALSE, TRUE); //stop stand first then set state - setAnimationState(STATE_AGENT_IDLE); - } - } - else - { - if (state == STATE_AGENT_SIT) gAgent.sendAnimationRequest(GetAnimIDFromState(state), (gSavedSettings.getBOOL("AOEnabled") && gSavedSettings.getBOOL("AOSitsEnabled")) ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); - else gAgent.sendAnimationRequest(GetAnimIDFromState(state), gSavedSettings.getBOOL("AOEnabled") ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); - } -} - -int LLFloaterAO::getAnimationState() -{ - if (gAgentAvatarp) - { - if (gAgentAvatarp->isSitting()) setAnimationState(STATE_AGENT_SIT); - else if (gAgent.getFlying()) setAnimationState(STATE_AGENT_HOVER); - } - return mAnimationState; -} - -void LLFloaterAO::setAnimationState(const int state) -{ - mAnimationState = state; -} - -LLUUID LLFloaterAO::getCurrentStandId() -{ - return mCurrentStandId; -} - -void LLFloaterAO::setCurrentStandId(const LLUUID& id) -{ - mCurrentStandId = id; -} - -LLUUID LLFloaterAO::GetAnimID(const LLUUID& id) -{ - for (std::vector::iterator iter = mAOOverrides.begin(); iter != mAOOverrides.end(); ++iter) - { - if (iter->orig_id == id) return iter->ao_id; - } - return LLUUID::null; -} - -int LLFloaterAO::GetStateFromAnimID(const LLUUID& id) -{ - for (std::vector::iterator iter = mAOOverrides.begin(); iter != mAOOverrides.end(); ++iter) - { - if (iter->orig_id == id) return iter->state; - } - return STATE_AGENT_IDLE; -} - -LLUUID LLFloaterAO::GetAnimIDFromState(const int state) -{ - for (std::vector::iterator iter = mAOOverrides.begin(); iter != mAOOverrides.end(); ++iter) - { - if (iter->state == state) return iter->ao_id; - } - return LLUUID::null; -} - -int LLFloaterAO::GetStateFromToken(std::string strtoken) -{ - for (std::vector::iterator iter = mAOTokens.begin(); iter != mAOTokens.end(); ++iter) - { - if (iter->token == strtoken) return iter->state; - } - return STATE_AGENT_IDLE; -} - -void LLFloaterAO::onClickPrevStand(void* user_data) -{ - if (!(mAOStands.size() > 0)) return; - stand_iterator=stand_iterator-1; - if (stand_iterator < 0) stand_iterator = int( mAOStands.size()-stand_iterator); - if (stand_iterator > int( mAOStands.size()-1)) stand_iterator = 0; - cmdline_printchat(llformat("Changing stand to %s.",mAOStands[stand_iterator].anim_name.c_str())); - ChangeStand(); -} - -void LLFloaterAO::onClickNextStand(void* user_data) -{ - if (!(mAOStands.size() > 0)) return; - stand_iterator=stand_iterator+1; - if (stand_iterator < 0) stand_iterator = int( mAOStands.size()-stand_iterator); - if (stand_iterator > int( mAOStands.size()-1)) stand_iterator = 0; - cmdline_printchat(llformat("Changing stand to %s.",mAOStands[stand_iterator].anim_name.c_str())); - ChangeStand(); -} - -BOOL LLFloaterAO::ChangeStand() -{ - if (gSavedSettings.getBOOL("AOEnabled")) - { - if (gAgentAvatarp) - { - if (gSavedSettings.getBOOL("AONoStandsInMouselook") && gAgentCamera.cameraMouselook()) return FALSE; - - if (gAgentAvatarp->isSitting()) - { -// stopMotion(getCurrentStandId(), FALSE, TRUE); //stop stand first then set state -// if (getAnimationState() != STATE_AGENT_GROUNDSIT) setAnimationState(STATE_AGENT_SIT); -// setCurrentStandId(LLUUID::null); - return FALSE; - } - } - if ((getAnimationState() == STATE_AGENT_IDLE) || (getAnimationState() == STATE_AGENT_STAND))// stands have lowest priority - { - if (!(mAOStands.size() > 0)) return TRUE; - if (gSavedSettings.getBOOL("AOStandRandomize")) - { - stand_iterator = ll_rand(mAOStands.size()-1); - } - if (stand_iterator < 0) stand_iterator = int( mAOStands.size()-stand_iterator); - if (stand_iterator > int( mAOStands.size()-1)) stand_iterator = 0; - - int stand_iterator_previous = stand_iterator -1; - - if (stand_iterator_previous < 0) stand_iterator_previous = int( mAOStands.size()-1); - - if (mAOStands[stand_iterator].ao_id.notNull()) - { - stopMotion(getCurrentStandId(), FALSE, TRUE); //stop stand first then set state - startMotion(mAOStands[stand_iterator].ao_id, 0, TRUE); - - setAnimationState(STATE_AGENT_STAND); - setCurrentStandId(mAOStands[stand_iterator].ao_id); - if ((sInstance)&&(mcomboBox_stands)) mcomboBox_stands->selectNthItem(stand_iterator); -// LL_INFOS() << "changing stand to " << mAOStands[stand_iterator].anim_name << LL_ENDL; - return FALSE; - } - } - } - else - { - stopMotion(getCurrentStandId(), FALSE, TRUE); - return TRUE; //stop if ao is off - } - return TRUE; } - -BOOL LLFloaterAO::startMotion(const LLUUID& id, F32 time_offset, BOOL stand) +void LLFloaterAO::onClickCycleStand(bool next) const { - if (stand) - { - if (id.notNull()) - { - BOOL sitting = FALSE; - if (gAgentAvatarp) - { - sitting = gAgentAvatarp->isSitting(); - } - if (sitting) return FALSE; - gAgent.sendAnimationRequest(id, ANIM_REQUEST_START); - return TRUE; - } - } - else - { - if (GetAnimID(id).notNull() && gSavedSettings.getBOOL("AOEnabled")) - { - stopMotion(getCurrentStandId(), FALSE, TRUE); //stop stand first then set state - setAnimationState(GetStateFromAnimID(id)); - -// LL_INFOS() << " state " << getAnimationState() << " start anim " << id << " overriding with " << GetAnimID(id) << LL_ENDL; - if ((GetStateFromAnimID(id) == STATE_AGENT_SIT) && !(gSavedSettings.getBOOL("AOSitsEnabled"))) return TRUE; - gAgent.sendAnimationRequest(GetAnimID(id), ANIM_REQUEST_START); - return TRUE; - } - } - return FALSE; + auto ao = AOSystem::getIfExists(); + if (!ao) return; + auto stand = ao->cycleStand(next, false); + ao->mAOStandTimer.reset(); + if (stand < 0) return; + cmdline_printchat("Changed stand to " + ao->mAOStands[stand].anim_name + '.'); } -BOOL LLFloaterAO::stopMotion(const LLUUID& id, BOOL stop_immediate, BOOL stand) -{ - if (stand) - { - setAnimationState(STATE_AGENT_IDLE); - gAgent.sendAnimationRequest(id, ANIM_REQUEST_STOP); - return TRUE; - } - else - { - if (GetAnimID(id).notNull() && gSavedSettings.getBOOL("AOEnabled")) - { -// LL_INFOS() << " state " << getAnimationState() << "/" << GetStateFromAnimID(id) << "(now 0) stop anim " << id << " overriding with " << GetAnimID(id) << LL_ENDL; - if (getAnimationState() == GetStateFromAnimID(id)) - { - setAnimationState(STATE_AGENT_IDLE); - } - ChangeStand(); // startMotion(getCurrentStandId(), 0, TRUE); - gAgent.sendAnimationRequest(GetAnimID(id), ANIM_REQUEST_STOP); - return TRUE; - } - } - return FALSE; -} - -void LLFloaterAO::onClickReloadCard(void* user_data) +void LLFloaterAO::onClickReloadCard() const { - if(LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) - { - LLFloaterAO::init(); - } + AOSystem::instance().initSingleton(); } -void LLFloaterAO::onClickOpenCard(void* user_data) +void LLFloaterAO::onClickOpenCard() const { - if(LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) - { - LLUUID configncitem = (LLUUID)gSavedPerAccountSettings.getString("AOConfigNotecardID"); - if (configncitem.notNull()) - { - const LLInventoryItem* item = gInventory.getItem(configncitem); - if(item) - { - if (gAgent.allowOperation(PERM_COPY, item->getPermissions(),GP_OBJECT_MANIPULATE) || gAgent.isGodlike()) - { - if(!item->getAssetUUID().isNull()) - open_notecard((LLViewerInventoryItem*)item, std::string("Note: ") + item->getName(), LLUUID::null, FALSE); - // open_notecard((LLViewerInventoryItem*)item, std::string("Note: ") + item->getName(), LLUUID::null, FALSE, LLUUID::null, FALSE); - } - } - } - } + auto config_nc_id = (LLUUID)gSavedPerAccountSettings.getString("AOConfigNotecardID"); + if (config_nc_id.notNull()) + if (LLViewerInventoryItem* item = gInventory.getItem(config_nc_id)) + if (gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE) || gAgent.isGodlike()) + if(!item->getAssetUUID().isNull()) + open_notecard(item, "Note: " + item->getName(), LLUUID::null, false); } -void LLFloaterAO::onClickNewCard(void* user_data) +void LLFloaterAO::onClickNewCard() const { // load the template file from app_settings/ao_template.ini then // create a new properly-formatted notecard in the user's inventory std::string ao_template = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "ao_template.ini"); - if (!ao_template.empty()) - { - LLPointer cb = new AONotecardCallback(ao_template); - create_inventory_item(gAgent.getID(), gAgent.getSessionID(), - LLUUID::null, LLTransactionID::tnull, "New AO Notecard", - "Drop this notecard in your AO window to use", LLAssetType::AT_NOTECARD, - LLInventoryType::IT_NOTECARD, NOT_WEARABLE, PERM_ALL, cb); - } - else - { - LL_WARNS() << "Can't find ao_template.ini in app_settings!" << LL_ENDL; - } -} - -struct AOAssetInfo -{ - std::string path; - std::string name; -}; - -void LLFloaterAO::onNotecardLoadComplete(LLVFS *vfs,const LLUUID& asset_uuid,LLAssetType::EType type,void* user_data, S32 status, LLExtStat ext_status) -{ - if(status == LL_ERR_NOERR) - { - S32 size = vfs->getSize(asset_uuid, type); - U8* buffer = new U8[size]; - vfs->getData(asset_uuid, type, buffer, 0, size); - - if(type == LLAssetType::AT_NOTECARD) - { - LLViewerTextEditor* edit = new LLViewerTextEditor("",LLRect(0,0,0,0),S32_MAX,""); - if(edit->importBuffer((char*)buffer, (S32)size)) - { - LL_INFOS() << "ao nc decode success" << LL_ENDL; - std::string card = edit->getText(); - edit->die(); - - if (mcomboBox_stands) - { - mcomboBox_stands->clear(); - mcomboBox_stands->removeall(); - } - if (mcomboBox_walks) mcomboBox_walks->clear(); - if (mcomboBox_runs) mcomboBox_runs->clear(); - if (mcomboBox_jumps) mcomboBox_jumps->clear(); - if (mcomboBox_sits) mcomboBox_sits->clear(); - if (mcomboBox_gsits) mcomboBox_gsits->clear(); - if (mcomboBox_crouchs) mcomboBox_cwalks->clear(); - if (mcomboBox_cwalks) mcomboBox_cwalks->clear(); - if (mcomboBox_falls) mcomboBox_falls->clear(); - if (mcomboBox_hovers) mcomboBox_hovers->clear(); - if (mcomboBox_flys) mcomboBox_flys->clear(); - if (mcomboBox_flyslows) mcomboBox_flyslows->clear(); - if (mcomboBox_flyups) mcomboBox_flyups->clear(); - if (mcomboBox_flydowns) mcomboBox_flydowns->clear(); - if (mcomboBox_lands) mcomboBox_lands->clear(); - if (mcomboBox_standups) mcomboBox_standups->clear(); - if (mcomboBox_prejumps) mcomboBox_prejumps->clear(); - - - struct_stands loader; - - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("\n"); - tokenizer tokline(card, sep); - - for (tokenizer::iterator line = tokline.begin(); line != tokline.end(); ++line) - { -// LL_INFOS() << *line << LL_ENDL; - std::string strline(*line); -// LL_INFOS() << "uncommented line: " << strline << LL_ENDL; - - boost::regex type("^(\\s*)(\\[ )(.*)( \\])"); - boost::smatch what; - if (boost::regex_search(strline, what, type)) - { -// LL_INFOS() << "type: " << what[0] << LL_ENDL; -// LL_INFOS() << "anims in type: " << boost::regex_replace(strline, type, "") << LL_ENDL; - - boost::char_separator sep("|,"); - std::string stranimnames(boost::regex_replace(strline, type, "")); - tokenizer tokanimnames(stranimnames, sep); - for (tokenizer::iterator anim = tokanimnames.begin(); anim != tokanimnames.end(); ++anim) - { - std::string strtoken(what[0]); - std::string stranim(*anim); - LLUUID animid(getAssetIDByName(stranim)); - -// LL_INFOS() << invfolderid.asString().c_str() << LL_ENDL; -// LL_INFOS() << "anim: " << stranim.c_str() << " assetid: " << animid << LL_ENDL; - if (!(animid.notNull())) - { - cmdline_printchat(llformat("Warning: animation '%s' could not be found (Section: %s).",stranim.c_str(),strtoken.c_str())); - } - else - { - switch(GetStateFromToken(strtoken.c_str())) - { - case STATE_AGENT_STAND: - loader.ao_id = animid; loader.anim_name = stranim.c_str(); mAOStands.push_back(loader); - if(mcomboBox_stands != NULL) mcomboBox_stands->add(stranim.c_str(), ADD_BOTTOM, TRUE); - break; - case STATE_AGENT_WALK: - { - if (sInstance && (mcomboBox_walks != NULL)) - { - //LL_INFOS() << "1 anim: " << stranim.c_str() << " assetid: " << animid << LL_ENDL; - if (!(mcomboBox_walks->selectByValue(stranim.c_str()))) mcomboBox_walks->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_RUN: - { - if (sInstance && (mcomboBox_runs != NULL)) - { - if (!(mcomboBox_runs->selectByValue(stranim.c_str()))) mcomboBox_runs->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_JUMP: - { - if (sInstance && (mcomboBox_jumps != NULL)) - { - if (!(mcomboBox_jumps->selectByValue(stranim.c_str()))) mcomboBox_jumps->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_SIT: - { - if (sInstance && (mcomboBox_sits != NULL)) - { - if (!(mcomboBox_sits->selectByValue(stranim.c_str()))) mcomboBox_sits->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_GROUNDSIT: - { - if (sInstance && (mcomboBox_gsits != NULL)) - { - if (!(mcomboBox_gsits->selectByValue(stranim.c_str()))) mcomboBox_gsits->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_CROUCH: - { - if (sInstance && (mcomboBox_crouchs != NULL)) - { - if (!(mcomboBox_crouchs->selectByValue(stranim.c_str()))) mcomboBox_crouchs->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_CROUCHWALK: - { - if (sInstance && (mcomboBox_cwalks != NULL)) - { - if (!(mcomboBox_cwalks->selectByValue(stranim.c_str()))) mcomboBox_cwalks->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_FALLDOWN: - { - if (sInstance && (mcomboBox_falls != NULL)) - { - if (!(mcomboBox_falls->selectByValue(stranim.c_str()))) mcomboBox_falls->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_HOVER: - { - if (sInstance && (mcomboBox_hovers != NULL)) - { - if (!(mcomboBox_hovers->selectByValue(stranim.c_str()))) mcomboBox_hovers->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_FLY: - { - if (sInstance && (mcomboBox_flys != NULL)) - { - if (!(mcomboBox_flys->selectByValue(stranim.c_str()))) mcomboBox_flys->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_FLYSLOW: - { - if (sInstance && (mcomboBox_flyslows != NULL)) - { - if (!(mcomboBox_flyslows->selectByValue(stranim.c_str()))) mcomboBox_flyslows->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_HOVER_UP: - { - if (sInstance && (mcomboBox_flyups != NULL)) - { - if (!(mcomboBox_flyups->selectByValue(stranim.c_str()))) mcomboBox_flyups->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_HOVER_DOWN: - { - if (sInstance && (mcomboBox_flydowns != NULL)) - { - if (!(mcomboBox_flydowns->selectByValue(stranim.c_str()))) mcomboBox_flydowns->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_LAND: - { - if (sInstance && (mcomboBox_lands != NULL)) - { - if (!(mcomboBox_lands->selectByValue(stranim.c_str()))) mcomboBox_lands->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_STANDUP: - { - if (sInstance && (mcomboBox_standups != NULL)) - { - if (!(mcomboBox_standups->selectByValue(stranim.c_str()))) mcomboBox_standups->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - case STATE_AGENT_PRE_JUMP: - { - if (sInstance && (mcomboBox_prejumps != NULL)) - { - if (!(mcomboBox_prejumps->selectByValue(stranim.c_str()))) mcomboBox_prejumps->add(stranim.c_str(), ADD_BOTTOM, TRUE); //check if exist - } - } - break; - } - for (std::vector::iterator iter = mAOOverrides.begin(); iter != mAOOverrides.end(); ++iter) - { - if (GetStateFromToken(strtoken.c_str()) == iter->state) - { - iter->ao_id = animid; - } - } - } - } - } - } - LL_INFOS() << "ao nc read sucess" << LL_ENDL; - - for (std::vector::iterator iter = mAOOverrides.begin(); iter != mAOOverrides.end(); ++iter) - { - switch(iter->state) - { - - case STATE_AGENT_WALK: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultWalk"); - SetDefault(mcomboBox_walks,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_RUN: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultRun"); - SetDefault(mcomboBox_runs,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_JUMP: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultJump"); - SetDefault(mcomboBox_jumps,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_SIT: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultSit"); - SetDefault(mcomboBox_sits,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_CROUCH: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultCrouch"); - SetDefault(mcomboBox_crouchs,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_GROUNDSIT: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultGroundSit"); - SetDefault(mcomboBox_gsits,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_CROUCHWALK: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultCrouchWalk"); - SetDefault(mcomboBox_cwalks,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_FALLDOWN: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultFall"); - SetDefault(mcomboBox_falls,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_HOVER: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultHover"); - SetDefault(mcomboBox_hovers,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_FLY: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultFly"); - SetDefault(mcomboBox_flys,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_HOVER_UP: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultFlyUp"); - SetDefault(mcomboBox_flyups,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_FLYSLOW: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultFlySlow"); - SetDefault(mcomboBox_flyslows,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_HOVER_DOWN: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultFlyDown"); - SetDefault(mcomboBox_flydowns,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_LAND: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultLand"); - SetDefault(mcomboBox_lands,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_STANDUP: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultStandUp"); - SetDefault(mcomboBox_standups,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - case STATE_AGENT_PRE_JUMP: - { - std::string defaultanim = gSavedPerAccountSettings.getString("AODefaultPreJump"); - SetDefault(mcomboBox_prejumps,iter->ao_id,defaultanim); - if (getAssetIDByName(defaultanim) != LLUUID::null) iter->ao_id = getAssetIDByName(defaultanim); - } - break; - } - } - run(); - } - else - { - LL_INFOS() << "ao nc decode error" << LL_ENDL; - } - } - } - else + if (ao_template.empty()) { - LL_INFOS() << "ao nc read error" << LL_ENDL; + ao_template = "#Can't find ao_template.ini in app_settings!"; + LL_WARNS() << ao_template << LL_ENDL; + ao_template += "\n#ZHAO II Style Notecards are supported."; } -} -BOOL LLFloaterAO::SetDefault(void* userdata, LLUUID ao_id, std::string defaultanim) -{ - if (sInstance && (userdata)) - { - LLComboBox *box = (LLComboBox *) userdata; - if (ao_id.isNull()) - { - box->clear(); - box->removeall(); - } - else - { - box->selectByValue(defaultanim); - } - } - return TRUE; + create_inventory_item(gAgentID, gAgentSessionID, + LLUUID::null, LLTransactionID::tnull, "New AO Notecard", + "Drop this notecard in your AO window to use", LLAssetType::AT_NOTECARD, + LLInventoryType::IT_NOTECARD, NOT_WEARABLE, PERM_ALL, new AONotecardCallback(ao_template)); } - -class ObjectNameMatches : public LLInventoryCollectFunctor -{ -public: - ObjectNameMatches(std::string name) - { - sName = name; - } - virtual ~ObjectNameMatches() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item) - { - if(item) - { - if (item->getParentUUID() == LLFloaterAO::invfolderid) - { - return (item->getName() == sName); - } - return false; - } - return false; - } -private: - std::string sName; -}; - -const LLUUID& LLFloaterAO::getAssetIDByName(const std::string& name) -{ - if (name.empty() || !(LLInventoryModelBackgroundFetch::instance().isEverythingFetched())) return LLUUID::null; - - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - ObjectNameMatches objectnamematches(name); - gInventory.collectDescendentsIf(LLUUID::null,cats,items,FALSE,objectnamematches); - - if (items.size()) - { - return items[0]->getAssetUUID(); - } - return LLUUID::null; -}; diff --git a/indra/newview/floaterao.h b/indra/newview/floaterao.h index b8a63f0da2..187493e340 100644 --- a/indra/newview/floaterao.h +++ b/indra/newview/floaterao.h @@ -1,128 +1,30 @@ +#pragma once -#ifndef LL_LLFLOATERAO_H -#define LL_LLFLOATERAO_H - +#include "aostate.h" #include "llfloater.h" -#include "llviewercontrol.h" -#include "llagent.h" -#include "lleventtimer.h" - - -const int STATE_AGENT_IDLE = 0; -const int STATE_AGENT_WALK = 1; -const int STATE_AGENT_RUN = 2; -const int STATE_AGENT_STAND = 3; - -const int STATE_AGENT_PRE_JUMP = 4; -const int STATE_AGENT_JUMP = 5; -const int STATE_AGENT_TURNLEFT = 6; -const int STATE_AGENT_TURNRIGHT = 7; - -const int STATE_AGENT_SIT = 8; -const int STATE_AGENT_GROUNDSIT = 9; - -const int STATE_AGENT_HOVER = 10; -const int STATE_AGENT_HOVER_DOWN = 11; -const int STATE_AGENT_HOVER_UP = 12; - -const int STATE_AGENT_CROUCH = 13; -const int STATE_AGENT_CROUCHWALK = 14; -const int STATE_AGENT_FALLDOWN = 15; -const int STATE_AGENT_STANDUP = 16; -const int STATE_AGENT_LAND = 17; - -const int STATE_AGENT_FLY = 18; -const int STATE_AGENT_FLYSLOW = 19; - - - - - -class AOStandTimer : public LLEventTimer -{ -public: - AOStandTimer(); - ~AOStandTimer(); - virtual BOOL tick(); - virtual void reset(); -}; - -class AOInvTimer : public LLEventTimer -{ -public: - AOInvTimer(); - ~AOInvTimer(); - BOOL tick(); -}; -class LLFloaterAO : public LLFloater +class LLFloaterAO final : public LLFloater, public LLFloaterSingleton { + friend class AOSystem; public: - LLFloaterAO(); - virtual BOOL postBuild(); - virtual ~LLFloaterAO(); - - static void show(void*); - static void init(); - - static void onClickToggleAO(); - static void onClickToggleSits(); - static void run(); - static void updateLayout(LLFloaterAO* floater); - - static BOOL loadAnims(); - - static int getAnimationState(); - static void setAnimationState(int state); - static void setStates(const LLUUID& id, BOOL start); - - static LLUUID getCurrentStandId(); - static void setCurrentStandId(const LLUUID& id); - static int stand_iterator; - static BOOL ChangeStand(); - - static BOOL startMotion(const LLUUID& id, F32 time_offset = 0.f, BOOL stand = FALSE); - static BOOL stopMotion(const LLUUID& id, BOOL stop_immediate, BOOL stand = FALSE); - - static LLUUID GetAnimID(const LLUUID& id); + LLFloaterAO(const LLSD&); + BOOL postBuild() override; + void onOpen() override; + virtual ~LLFloaterAO(); + void updateLayout(bool advanced); - static int GetStateFromAnimID(const LLUUID& id); - static LLUUID GetAnimIDFromState(const int state); - static int GetStateFromToken(std::string strtoken); + void onClickCycleStand(bool next) const; + void onClickReloadCard() const; + void onClickOpenCard() const; + void onClickNewCard() const; - static void onClickLess(void* data) ; - static void onClickMore(void* data) ; - - static void onClickPrevStand(void* userdata); - static void onClickNextStand(void* userdata); - static void onClickReloadCard(void* userdata); - static void onClickOpenCard(void* userdata); - static void onClickNewCard(void* userdata); - - static LLUUID invfolderid; - static const LLUUID& getAssetIDByName(const std::string& name); - - static bool getInstance(); - private: - - static LLFloaterAO* sInstance; - static int mAnimationState; - static LLUUID mCurrentStandId; - - static void onSpinnerCommit(LLUICtrl* ctrl); - static void onComboBoxCommit(LLUICtrl* ctrl); - static BOOL SetDefault(void *userdata, LLUUID ao_id, std::string defaultanim); - - BOOL mDirty; + void onSpinnerCommit() const; + void onComboBoxCommit(LLUICtrl* ctrl) const; + std::array mCombos; protected: - static void onNotecardLoadComplete(LLVFS *vfs,const LLUUID& asset_uuid,LLAssetType::EType type,void* user_data, S32 status, LLExtStat ext_status); - + LLComboBox* getComboFromState(const U8& state) const { return mCombos[state]; } }; - -extern AOInvTimer* gAOInvTimer; - -#endif diff --git a/indra/newview/floaterlocalassetbrowse.cpp b/indra/newview/floaterlocalassetbrowse.cpp index b7a404e2f0..8a700593a3 100644 --- a/indra/newview/floaterlocalassetbrowse.cpp +++ b/indra/newview/floaterlocalassetbrowse.cpp @@ -64,6 +64,8 @@ this feature is still a work in progress. #include "llviewermenufile.h" #include "llfloaterimagepreview.h" #include "llfile.h" +#include "llsdparam.h" +#include "llsdserialize.h" /* including to force rebakes when needed */ #include "llvoavatarself.h" @@ -93,21 +95,29 @@ bool LocalAssetBrowser::mSculptUpdated; containing one loaded local texture. */ -LocalBitmap::LocalBitmap(std::string fullpath) +LocalBitmap::Params::Params(const std::string& path) +: fullpath("path", path) +, keep_updating("update", gSavedSettings.getBOOL("LocalBitmapUpdate")) +, type("type", TYPE_TEXTURE) +, id("id", LLUUID::generateNewID()) { +} + +LocalBitmap::LocalBitmap(const Params& p) +{ + llassert(!p.fullpath().empty()); valid = false; - if ( gDirUtilp->fileExists(fullpath) ) + if ( gDirUtilp->fileExists(p.fullpath) ) { /* taking care of basic properties */ - id.generate(); - filename = fullpath; - keep_updating = gSavedSettings.getBOOL("LocalBitmapUpdate"); + id = p.id; + filename = p.fullpath; + keep_updating = p.keep_updating; linkstatus = keep_updating ? LINK_ON : LINK_OFF; shortname = gDirUtilp->getBaseFileName(filename, true); - bitmap_type = TYPE_TEXTURE; + bitmap_type = p.type; sculpt_dirty = false; volume_dirty = false; - valid = false; /* taking care of extension type now to avoid switch madness */ std::string temp_exten = gDirUtilp->getExtension(filename); @@ -131,7 +141,7 @@ LocalBitmap::LocalBitmap(std::string fullpath) if (decodeSelf(raw_image)) { /* creating a shell LLViewerTexture and fusing raw image into it */ - LLViewerFetchedTexture* viewer_image = new LLViewerFetchedTexture( "file://"+filename, id, LOCAL_USE_MIPMAPS ); + LLViewerFetchedTexture* viewer_image = new LLViewerFetchedTexture( "file://"+filename, FTT_LOCAL_FILE, id, LOCAL_USE_MIPMAPS ); viewer_image->createGLTexture( LOCAL_DISCARD_LEVEL, raw_image ); viewer_image->setCachedRawImage(-1,raw_image); @@ -139,10 +149,11 @@ LocalBitmap::LocalBitmap(std::string fullpath) viewer_image->ref(); /* finalizing by adding LLViewerTexture instance into gTextureList */ - gTextureList.addImage(viewer_image); + gTextureList.addImage(viewer_image, TEX_LIST_STANDARD); /* filename is valid, bitmap is decoded and valid, i can haz liftoff! */ valid = true; + LocalAssetBrowser::add(*this); } } } @@ -183,7 +194,7 @@ void LocalBitmap::updateSelf() linkstatus = LINK_ON; } - LLViewerFetchedTexture* image = gTextureList.findImage(id); + LLViewerFetchedTexture* image = gTextureList.findImage(id, TEX_LIST_STANDARD); if (!image->forSculpt()) image->createGLTexture(LOCAL_DISCARD_LEVEL, new_imgraw); else @@ -293,64 +304,64 @@ void LocalBitmap::setType( S32 type ) bitmap_type = type; } +void LocalBitmap::setID(const LLUUID& uuid) +{ + LLViewerFetchedTexture* image = gTextureList.findImage(id, TEX_LIST_STANDARD); + gTextureList.deleteImage(image); + id = uuid; + image->setID(id); + gTextureList.addImage(image, TEX_LIST_STANDARD); +} + /* [information query functions] */ -std::string LocalBitmap::getShortName() +std::string LocalBitmap::getShortName() const { return shortname; } -std::string LocalBitmap::getFileName() +std::string LocalBitmap::getFileName() const { return filename; } -LLUUID LocalBitmap::getID() +LLUUID LocalBitmap::getID() const { return id; } -LLSD LocalBitmap::getLastModified() +LLSD LocalBitmap::getLastModified() const { return last_modified; } -std::string LocalBitmap::getLinkStatus() +std::string LocalBitmap::getLinkStatus() const { switch(linkstatus) { - case LINK_ON: - return "On"; - - case LINK_OFF: - return "Off"; - - case LINK_BROKEN: - return "Broken"; - - case LINK_UPDATING: - return "Updating"; - - default: - return "Unknown"; + case LINK_ON: return "On"; + case LINK_OFF: return "Off"; + case LINK_BROKEN: return "Broken"; + case LINK_UPDATING: return "Updating"; + default: return "Unknown"; } } -bool LocalBitmap::getUpdateBool() +bool LocalBitmap::getUpdateBool() const { return keep_updating; } -bool LocalBitmap::getIfValidBool() +bool LocalBitmap::getIfValidBool() const { return valid; } -S32 LocalBitmap::getType() +S32 LocalBitmap::getType() const { return bitmap_type; } -std::vector LocalBitmap::getFaceUsesThis(LLDrawable* drawable) +std::vector LocalBitmap::getFaceUsesThis(LLDrawable* drawable) const { std::vector matching_faces; @@ -365,7 +376,7 @@ std::vector LocalBitmap::getFaceUsesThis(LLDrawable* drawable) return matching_faces; } -std::vector LocalBitmap::getUsingObjects(bool seek_by_type, bool seek_textures, bool seek_sculptmaps) +std::vector LocalBitmap::getUsingObjects(bool seek_by_type, bool seek_textures, bool seek_sculptmaps) const { std::vector affected_vector; @@ -413,21 +424,29 @@ std::vector LocalBitmap::getUsingObjects(bool seek_by_type, boo return affected_vector; } -void LocalBitmap::getDebugInfo() +void LocalBitmap::getDebugInfo() const { /* debug function: dumps everything human readable into llinfos */ - LL_INFOS() << "===[local bitmap debug]===" << "\n" - << "path: " << filename << "\n" - << "name: " << shortname << "\n" - << "extension: " << extension << "\n" - << "uuid: " << id << "\n" - << "last modified: " << last_modified << "\n" - << "link status: " << getLinkStatus() << "\n" - << "keep updated: " << keep_updating << "\n" - << "type: " << bitmap_type << "\n" - << "is valid: " << valid << "\n" + LL_INFOS() << "===[local bitmap debug]===" << '\n' + << "path: " << filename << '\n' + << "name: " << shortname << '\n' + << "extension: " << extension << '\n' + << "uuid: " << id << '\n' + << "last modified: " << last_modified << '\n' + << "link status: " << getLinkStatus() << '\n' + << "keep updated: " << keep_updating << '\n' + << "type: " << bitmap_type << '\n' + << "is valid: " << valid << '\n' << "==========================" << LL_ENDL; - +} + +LLSD LocalBitmap::asLLSD() const +{ + return LLSD() + .with("path", filename) + .with("id", id) + .with("update", keep_updating) + .with("type", bitmap_type); } /*=======================================*/ @@ -439,15 +458,47 @@ void LocalBitmap::getDebugInfo() Sits in memory until the viewer is closed. */ +const std::string LocalAssetBrowser::getFileName() const +{ + return gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "local_assets.xml"); +} + LocalAssetBrowser::LocalAssetBrowser() { + gLocalBrowser = this; mLayerUpdated = false; mSculptUpdated = false; + + // Load bitmaps + llifstream file(getFileName()); + if (!file) return; + LLSD saved_assets; + LLSDSerialize::fromXML(saved_assets, file); + file.close(); + for (auto it = saved_assets.beginArray(), end = saved_assets.endArray(); it < end; ++it) + { + const auto&& p = LLSDParamAdapter(*it); + LocalBitmap bm(p); // Creating one adds it to the list + } + + if (!loaded_bitmaps.empty()) PingTimer(); } LocalAssetBrowser::~LocalAssetBrowser() { - + // Save bitmaps + llofstream file(getFileName()); + if (!file) + { + LL_WARNS() << "Could not open file " << getFileName() << " for saving." << LL_ENDL; + return; + } + LLSD saved_assets(LLSD::emptyArray()); + for (const auto& bitmap : loaded_bitmaps) + saved_assets.append(bitmap.asLLSD()); + LLSDSerialize::toPrettyXML(saved_assets, file); + file.close(); + gLocalBrowser = nullptr; } void LocalAssetBrowser::AddBitmap() @@ -463,20 +514,13 @@ void LocalAssetBrowser::AddBitmap_continued(AIFilePicker* filepicker) return; bool change_happened = false; - std::vector const& filenames(filepicker->getFilenames()); - for(std::vector::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) - { - LocalBitmap unit(*filename); - if (unit.getIfValidBool()) - { - loaded_bitmaps.push_back(unit); + + for(const auto& filename : filepicker->getFilenames()) + if (LocalBitmap(filename).getIfValidBool()) change_happened = true; - } - } if (change_happened) onChangeHappened(); } - void LocalAssetBrowser::DelBitmap( std::vector delete_vector, S32 column ) { bool change_happened = false; @@ -492,7 +536,7 @@ void LocalAssetBrowser::DelBitmap( std::vector delete_vector, { if ((*iter).getID() == id) { - LLViewerFetchedTexture* image = gTextureList.findImage(id); + LLViewerFetchedTexture* image = gTextureList.findImage(id, TEX_LIST_STANDARD); gTextureList.deleteImage( image ); image->unref(); iter = loaded_bitmaps.erase(iter); @@ -592,21 +636,21 @@ void LocalAssetBrowser::UpdateTextureCtrlList(LLScrollListCtrl* ctrl) if (ctrl) // checking again in case called externally for some silly reason. { ctrl->clearRows(); - if ( !loaded_bitmaps.empty() ) + for (const auto& bitmap : loaded_bitmaps) { - for (local_list_iter iter = loaded_bitmaps.begin(); iter != loaded_bitmaps.end(); ++iter) - { - LLSD element; - element["columns"][0]["column"] = "unit_name"; - element["columns"][0]["type"] = "text"; - element["columns"][0]["value"] = (*iter).shortname; - - element["columns"][1]["column"] = "unit_id_HIDDEN"; - element["columns"][1]["type"] = "text"; - element["columns"][1]["value"] = (*iter).id; - - ctrl->addElement(element); - } + auto row = LLScrollListItem::Params(); + row.value(bitmap.id); + row.columns.add(LLScrollListCell::Params() + .column("unit_name") + .type("text") + .value(bitmap.shortname)); + + row.columns.add(LLScrollListCell::Params() + .column("unit_id_HIDDEN") + .type("text") + .value(bitmap.id)); + + ctrl->addRow(row); } } } @@ -651,9 +695,9 @@ void LocalAssetBrowser::PerformSculptUpdates(LocalBitmap& unit) // update code [begin] if (unit.volume_dirty) { - LLImageRaw* rawimage = gTextureList.findImage(unit.getID())->getCachedRawImage(); + LLImageRaw* rawimage = gTextureList.findImage(unit.getID(), TEX_LIST_STANDARD)->getCachedRawImage(); - aobj.object->getVolume()->sculpt(rawimage->getWidth(), rawimage->getHeight(), rawimage->getComponents(), rawimage->getData(), 0); + aobj.object->getVolume()->sculpt(rawimage->getWidth(), rawimage->getHeight(), rawimage->getComponents(), rawimage->getData(), 0, true); unit.volume_dirty = false; } @@ -731,6 +775,11 @@ FloaterLocalAssetBrowser::FloaterLocalAssetBrowser() // checkbox callbacks mUpdateChkBox->setCommitCallback(boost::bind(&FloaterLocalAssetBrowser::onClickUpdateChkbox,this)); + + // Allow changing the ID! + mUUIDTxt->setCommitCallback(boost::bind(&FloaterLocalAssetBrowser::onUpdateID, this, _2)); + mUUIDTxt->setCommitOnReturn(true); + mUUIDTxt->setCommitOnFocusLost(true); } void FloaterLocalAssetBrowser::show(void*) @@ -798,6 +847,21 @@ void FloaterLocalAssetBrowser::onCommitTypeCombo() } } +void FloaterLocalAssetBrowser::onUpdateID(const LLSD& val) +{ + const auto& id = val.asUUID(); + const auto& col = mBitmapList->getFirstSelected()->getColumn(BITMAPLIST_COL_ID); + const auto& old_id = col->getValue().asString(); + if (id.isNull() && id.asString() != old_id) // Just reset if invalid or unchanged + mUUIDTxt->setValue(old_id); + else + { + gLocalBrowser->GetBitmapUnit(LLUUID(old_id))->setID(id); + mTextureView->setImageAssetID(id); + col->setValue(id); + } +} + void FloaterLocalAssetBrowser::FloaterResize(bool expand) { mMoreBtn->setVisible(!expand); @@ -855,10 +919,9 @@ void FloaterLocalAssetBrowser::UpdateRightSide() */ if (!mTextureView->getVisible()) return; - if (!mBitmapList->getAllSelected().empty()) + if (const auto& selected = mBitmapList->getFirstSelected()) { - LocalBitmap* unit = gLocalBrowser->GetBitmapUnit( LLUUID(mBitmapList->getSelectedItemLabel(BITMAPLIST_COL_ID)) ); - + LocalBitmap* unit = gLocalBrowser->GetBitmapUnit(LLUUID(selected->getColumn(BITMAPLIST_COL_ID)->getValue().asString())); if ( unit ) { mTextureView->setImageAssetID(unit->getID()); @@ -873,6 +936,7 @@ void FloaterLocalAssetBrowser::UpdateRightSide() mTextureView->setEnabled(true); mUpdateChkBox->setEnabled(true); mTypeComboBox->setEnabled(true); + mUUIDTxt->setEnabled(true); } } else @@ -884,12 +948,14 @@ void FloaterLocalAssetBrowser::UpdateRightSide() mTypeComboBox->selectFirstItem(); mTypeComboBox->setEnabled(false); - - mPathTxt->setText(LLStringExplicit("None")); - mUUIDTxt->setText(LLStringExplicit("None")); - mNameTxt->setText(LLStringExplicit("None")); - mLinkTxt->setText(LLStringExplicit("None")); - mTimeTxt->setText(LLStringExplicit("None")); + mUUIDTxt->setEnabled(false); + + const auto none = LLStringExplicit("None"); + mPathTxt->setText(none); + mUUIDTxt->setText(none); + mNameTxt->setText(none); + mLinkTxt->setText(none); + mTimeTxt->setText(none); } } @@ -931,7 +997,7 @@ void LocalAssetBrowserTimer::stop() mEventTimer.stop(); } -bool LocalAssetBrowserTimer::isRunning() +bool LocalAssetBrowserTimer::isRunning() const { return mEventTimer.getStarted(); } diff --git a/indra/newview/floaterlocalassetbrowse.h b/indra/newview/floaterlocalassetbrowse.h index dd7e618ea6..290fbe4e35 100644 --- a/indra/newview/floaterlocalassetbrowse.h +++ b/indra/newview/floaterlocalassetbrowse.h @@ -97,7 +97,15 @@ struct affected_object class LocalBitmap { public: - LocalBitmap(std::string filename); + struct Params : public LLInitParam::Block + { + Mandatory fullpath; + Optional keep_updating; + Optional type; + Optional id; + Params(const std::string& path = LLStringUtil::null); + }; + LocalBitmap(const Params& p); virtual ~LocalBitmap(); friend class LocalAssetBrowser; @@ -127,25 +135,28 @@ class LocalBitmap }; public: /* [information query functions] */ - std::string getShortName(); - std::string getFileName(); - LLUUID getID(); - LLSD getLastModified(); - std::string getLinkStatus(); - bool getUpdateBool(); + std::string getShortName() const; + std::string getFileName() const; + LLUUID getID() const; + void setID(const LLUUID&); + LLSD getLastModified() const; + std::string getLinkStatus() const; + bool getUpdateBool() const; void setType( S32 ); - bool getIfValidBool(); - S32 getType(); - void getDebugInfo(); + bool getIfValidBool() const; + S32 getType() const; + void getDebugInfo() const; + LLSD asLLSD() const; + private: /* [maintenence functions] */ void updateSelf(); bool decodeSelf(LLImageRaw* rawimg); void setUpdateBool(); - std::vector getFaceUsesThis(LLDrawable*); + std::vector getFaceUsesThis(LLDrawable*) const; std::vector getUsingObjects(bool seek_by_type = true, - bool seek_textures = false, bool seek_sculptmaps = false); + bool seek_textures = false, bool seek_sculptmaps = false) const; protected: /* [basic properties] */ std::string shortname; @@ -173,9 +184,10 @@ class LocalBitmap class AIFilePicker; -class LocalAssetBrowser +class LocalAssetBrowser : public LLSingleton { public: + const std::string getFileName() const; LocalAssetBrowser(); virtual ~LocalAssetBrowser(); friend class FloaterLocalAssetBrowser; @@ -183,6 +195,7 @@ class LocalAssetBrowser static void UpdateTextureCtrlList(LLScrollListCtrl*); static void setLayerUpdated(bool toggle) { mLayerUpdated = toggle; } static void setSculptUpdated(bool toggle) { mSculptUpdated = toggle; } + static void add(const LocalBitmap& unit) { loaded_bitmaps.push_back(unit); } static void AddBitmap(); static void AddBitmap_continued(AIFilePicker* filepicker); static void DelBitmap( std::vector, S32 column = BITMAPLIST_COL_ID ); @@ -241,6 +254,8 @@ class FloaterLocalAssetBrowser : public LLFloater // Combobox type select void onCommitTypeCombo(); + void onUpdateID(const LLSD& val); + // Widgets LLButton* mAddBtn; LLButton* mDelBtn; @@ -289,10 +304,10 @@ class LocalAssetBrowserTimer : public LLEventTimer public: LocalAssetBrowserTimer(); ~LocalAssetBrowserTimer(); - virtual BOOL tick(); + BOOL tick() override; void start(); void stop(); - bool isRunning(); + bool isRunning() const; }; #endif diff --git a/indra/newview/floatervoicelicense.cpp b/indra/newview/floatervoicelicense.cpp deleted file mode 100644 index 4250e62118..0000000000 --- a/indra/newview/floatervoicelicense.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/** -* @file floatervoicelicense.cpp -* @brief prompts user to agree to the Vivox license in order to enable voice -* -* $LicenseInfo:firstyear=2009&license=viewergpl$ -* -* Copyright (c) 2010, McCabe Maxsted -* -* Imprudence Viewer Source Code -* The source code in this file ("Source Code") is provided to you -* under the terms of the GNU General Public License, version 2.0 -* ("GPL"). Terms of the GPL can be found in doc/GPL-license.txt in -* this distribution, or online at -* http://secondlifegrid.net/programs/open_source/licensing/gplv2 -* -* There are special exceptions to the terms and conditions of the GPL as -* it is applied to this Source Code. View the full text of the exception -* in the file doc/FLOSS-exception.txt in this software distribution, or -* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception -* -* By copying, modifying or distributing this software, you acknowledge -* that you have read and understood your obligations described above, -* and agree to abide by those obligations. -* -* ALL SOURCE CODE IS PROVIDED "AS IS." THE AUTHOR MAKES NO -* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, -* COMPLETENESS OR PERFORMANCE. -* $/LicenseInfo$ -*/ - -#include "llviewerprecompiledheaders.h" - -#include "floatervoicelicense.h" - -// viewer includes -#include "llagent.h" -#include "llappviewer.h" -#include "llstartup.h" -#include "llviewercontrol.h" -#include "llviewerstats.h" -#include "llviewertexteditor.h" -#include "llviewerwindow.h" - -// linden library includes -#include "llbutton.h" -#include "llhttpclient.h" -#include "llhttpstatuscodes.h" // for HTTP_FOUND -#include "llradiogroup.h" -#include "lltextbox.h" -#include "llui.h" -#include "lluictrlfactory.h" -#include "llvfile.h" -#include "message.h" - -class AIHTTPTimeoutPolicy; -extern AIHTTPTimeoutPolicy iamHereVoice_timeout; - -FloaterVoiceLicense::FloaterVoiceLicense(const LLSD& key) -: LLModalDialog( std::string(" "), 100, 100 ), - mLoadCompleteCount( 0 ) -{ - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_voice_license.xml"); -} - -// helper class that trys to download a URL from a web site and calls a method -// on parent class indicating if the web server is working or not -class LLIamHereVoice : public LLHTTPClient::ResponderWithResult -{ - private: - LLIamHereVoice( FloaterVoiceLicense* parent ) : - mParent( parent ) - {} - - FloaterVoiceLicense* mParent; - - public: - static boost::intrusive_ptr< LLIamHereVoice > build( FloaterVoiceLicense* parent ) - { - return boost::intrusive_ptr< LLIamHereVoice >( new LLIamHereVoice( parent ) ); - }; - - virtual void setParent( FloaterVoiceLicense* parentIn ) - { - mParent = parentIn; - }; - - /*virtual*/ void httpSuccess(void) - { - if ( mParent ) - mParent->setSiteIsAlive( true ); - }; - - /*virtual*/ void httpFailure(void) - { - if ( mParent ) - { - // *HACK: For purposes of this alive check, 302 Found - // (aka Moved Temporarily) is considered alive. The web site - // redirects this link to a "cache busting" temporary URL. JC - bool alive = (mStatus == HTTP_FOUND); - mParent->setSiteIsAlive( alive ); - } - }; - - /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return iamHereVoice_timeout; } - /*virtual*/ bool pass_redirect_status(void) const { return true; } - /*virtual*/ char const* getName(void) const { return "LLIamHereVoice"; } -}; - -// this is global and not a class member to keep crud out of the header file -namespace { - boost::intrusive_ptr< LLIamHereVoice > gResponsePtr = 0; -}; - -BOOL FloaterVoiceLicense::postBuild() -{ - childSetAction("Continue", onContinue, this); - childSetAction("Cancel", onCancel, this); - childSetCommitCallback("agree_chk", updateAgree, this); - - // disable Agree to License radio button until the page has fully loaded - LLCheckBoxCtrl* license_agreement = getChild("agree_chk"); - license_agreement->setEnabled( false ); - - // hide the SL text widget if we're displaying license with using a browser widget. - LLTextEditor *editor = getChild("license_text"); - editor->setVisible( FALSE ); - - LLMediaCtrl* web_browser = getChild("license_html"); - if ( web_browser ) - { - // start to observe it so we see navigate complete events - web_browser->addObserver( this ); - std::string url = getString( "real_url" ); - if(url.substr(0,4) == "http") { - gResponsePtr = LLIamHereVoice::build( this ); - LLHTTPClient::get( url, gResponsePtr ); - } else { - setSiteIsAlive(false); - } - } - - return TRUE; -} - -void FloaterVoiceLicense::setSiteIsAlive( bool alive ) -{ - LLMediaCtrl* web_browser = getChild("license_html"); - // if the contents of the site was retrieved - if ( alive ) - { - if ( web_browser ) - { - // navigate to the "real" page - std::string real_url = getString( "real_url" ); - web_browser->navigateTo(real_url); - } - } - else - { - web_browser->navigateToLocalPage("license", getString("fallback_html")); - // normally this is set when navigation to license page completes (so you can't accept before it loads) - // but if the page is unavailable, we need to do this now - LLCheckBoxCtrl* license_agreement = getChild("agree_chk"); - license_agreement->setEnabled( true ); - } -} - -FloaterVoiceLicense::~FloaterVoiceLicense() -{ - - // tell the responder we're not here anymore - if ( gResponsePtr ) - { - gResponsePtr->setParent( 0 ); - } -} - -// virtual -void FloaterVoiceLicense::draw() -{ - // draw children - LLModalDialog::draw(); -} - -// static -void FloaterVoiceLicense::updateAgree(LLUICtrl*, void* userdata ) -{ - FloaterVoiceLicense* self = (FloaterVoiceLicense*) userdata; - bool agree = self->childGetValue("agree_chk").asBoolean(); - self->childSetEnabled("Continue", agree); -} - -// static -void FloaterVoiceLicense::onContinue( void* userdata ) -{ - FloaterVoiceLicense* self = (FloaterVoiceLicense*) userdata; - LL_INFOS() << "User agreed to the Vivox personal license" << LL_ENDL; - - // enabling voice by default here seems like the best behavior - gSavedSettings.setBOOL("EnableVoiceChat", TRUE); - gSavedSettings.setBOOL("VivoxLicenseAccepted", TRUE); - - // save these settings in case something bad happens later - gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); - - if (LLStartUp::getStartupState() == STATE_LOGIN_VOICE_LICENSE) - { - LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); // Go back and finish authentication - } - self->close(); // destroys this object -} - -// static -void FloaterVoiceLicense::onCancel( void* userdata ) -{ - FloaterVoiceLicense* self = (FloaterVoiceLicense*) userdata; - LL_INFOS() << "User disagreed with the vivox personal license" << LL_ENDL; - gSavedSettings.setBOOL("EnableVoiceChat", FALSE); - gSavedSettings.setBOOL("VivoxLicenseAccepted", FALSE); - - if (LLStartUp::getStartupState() == STATE_LOGIN_VOICE_LICENSE) - { - LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); // Go back and finish authentication - } - self->mLoadCompleteCount = 0; // reset counter for next time we come here - self->close(); // destroys this object -} - -//virtual -void FloaterVoiceLicense::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event) -{ - if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) - { - // skip past the loading screen navigate complete - if ( ++mLoadCompleteCount == 2 ) - { - LL_INFOS() << "NAVIGATE COMPLETE" << LL_ENDL; - // enable Agree to License radio button now that page has loaded - LLCheckBoxCtrl * license_agreement = getChild("agree_chk"); - license_agreement->setEnabled( true ); - } - } -} diff --git a/indra/newview/floatervoicelicense.h b/indra/newview/floatervoicelicense.h deleted file mode 100644 index 10aaa1979d..0000000000 --- a/indra/newview/floatervoicelicense.h +++ /dev/null @@ -1,72 +0,0 @@ -/** -* @file floatervoicelicense.h -* @brief prompts user to agree to the Vivox license in order to enable voice -* -* $LicenseInfo:firstyear=2009&license=viewergpl$ -* -* Copyright (c) 2010, McCabe Maxsted -* -* Imprudence Viewer Source Code -* The source code in this file ("Source Code") is provided to you -* under the terms of the GNU General Public License, version 2.0 -* ("GPL"). Terms of the GPL can be found in doc/GPL-license.txt in -* this distribution, or online at -* http://secondlifegrid.net/programs/open_source/licensing/gplv2 -* -* There are special exceptions to the terms and conditions of the GPL as -* it is applied to this Source Code. View the full text of the exception -* in the file doc/FLOSS-exception.txt in this software distribution, or -* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception -* -* By copying, modifying or distributing this software, you acknowledge -* that you have read and understood your obligations described above, -* and agree to abide by those obligations. -* -* ALL SOURCE CODE IS PROVIDED "AS IS." THE AUTHOR MAKES NO -* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, -* COMPLETENESS OR PERFORMANCE. -* $/LicenseInfo$ -*/ - -#ifndef FLOATERVOICELICENSE_H -#define FLOATERVOICELICENSE_H - -#include "llfloater.h" - -#include "llmodaldialog.h" -#include "llassetstorage.h" -#include "llmediactrl.h" - -class LLButton; -class LLRadioGroup; -class LLVFS; -class LLTextEditor; -class LLUUID; - -class FloaterVoiceLicense : - public LLModalDialog, - public LLViewerMediaObserver, - public LLFloaterSingleton -{ -public: - FloaterVoiceLicense(const LLSD& key); - virtual ~FloaterVoiceLicense(); - - BOOL postBuild(); - - virtual void draw(); - - static void updateAgree( LLUICtrl *, void* userdata ); - static void onContinue( void* userdata ); - static void onCancel( void* userdata ); - - void setSiteIsAlive( bool alive ); - - // inherited from LLViewerMediaObserver - /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); - -private: - int mLoadCompleteCount; -}; - -#endif // FLOATERVOICELICENSE_H diff --git a/indra/newview/fonts/DejaVuSansCondensed-Bold.ttf b/indra/newview/fonts/DejaVuSansCondensed-Bold.ttf deleted file mode 100644 index 9edd89c3dc..0000000000 Binary files a/indra/newview/fonts/DejaVuSansCondensed-Bold.ttf and /dev/null differ diff --git a/indra/newview/fonts/DejaVuSansCondensed.ttf b/indra/newview/fonts/DejaVuSansCondensed.ttf deleted file mode 100644 index 826e619b78..0000000000 Binary files a/indra/newview/fonts/DejaVuSansCondensed.ttf and /dev/null differ diff --git a/indra/newview/fonts/DejaVuSansMono.ttf b/indra/newview/fonts/DejaVuSansMono.ttf deleted file mode 100644 index 19d188832b..0000000000 Binary files a/indra/newview/fonts/DejaVuSansMono.ttf and /dev/null differ diff --git a/indra/newview/fonts/DroidSans-Bold.ttf b/indra/newview/fonts/DroidSans-Bold.ttf deleted file mode 100644 index d065b64eb1..0000000000 Binary files a/indra/newview/fonts/DroidSans-Bold.ttf and /dev/null differ diff --git a/indra/newview/fonts/DroidSans.ttf b/indra/newview/fonts/DroidSans.ttf deleted file mode 100644 index ad1efca88a..0000000000 Binary files a/indra/newview/fonts/DroidSans.ttf and /dev/null differ diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py index c1fd05935b..2fc5abe8ba 100644 --- a/indra/newview/generate_breakpad_symbols.py +++ b/indra/newview/generate_breakpad_symbols.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """\ @file generate_breakpad_symbols.py @author Brad Kittenbrink @@ -31,7 +31,6 @@ import collections import fnmatch import itertools -import operator import os import re import sys @@ -83,15 +82,10 @@ def list_files(): def dump_module(m): print "dumping module '%s' with '%s'..." % (m, dump_syms_tool) dsym_full_path = m - - tools = dump_syms_tool.split('|') - for tool in tools: - if tool: - if os.path.isfile(tool): - child = subprocess.Popen([tool, dsym_full_path] , stdout=subprocess.PIPE) - out, err = child.communicate() - return (m,child.returncode, out, err) - raise IOError('Failed to find dump_syms tool!') + child = subprocess.Popen([dump_syms_tool, dsym_full_path] , stdout=subprocess.PIPE) + out, err = child.communicate() + return (m,child.returncode, out, err) + modules = {} @@ -154,7 +148,7 @@ def match_module_basename(m): == os.path.splitext(os.path.basename(m))[0].lower() # there must be at least one .sym file in tarfile_members that matches # each required module (ignoring file extensions) - if not reduce(operator.or_, itertools.imap(match_module_basename, tarfile_members)): + if not any(itertools.imap(match_module_basename, tarfile_members)): print >> sys.stderr, "failed to find required %s in generated %s" \ % (required_module, viewer_symbol_file) os.remove(viewer_symbol_file) diff --git a/indra/newview/gpu_table.txt b/indra/newview/gpu_table.txt index 45beb85a53..af5aa6a125 100644 --- a/indra/newview/gpu_table.txt +++ b/indra/newview/gpu_table.txt @@ -217,7 +217,6 @@ ATI Radeon RX700 .*ATI.*RX70.* 1 1 ATI Radeon RX800 .*ATI.*Radeon *RX80.* 2 1 ATI RS880M .*ATI.*RS880M 1 1 ATI Radeon RX9550 .*ATI.*RX9550.* 1 1 -ATI Radeon VE .*ATI.*Radeon.*VE.* 0 0 ATI Radeon X1000 .*ATI.*Radeon *X10.* 0 1 ATI Radeon X1200 .*ATI.*Radeon *X12.* 0 1 ATI Radeon X1300 .*ATI.*Radeon *X13.* 1 1 @@ -276,6 +275,9 @@ AMD RV730 (HD 4600) .*RV730.* 3 1 AMD RV740 (HD 4700) .*RV740.* 3 1 AMD RV770 (HD 4800) .*RV770.* 3 1 AMD RV790 (HD 4800) .*RV790.* 3 1 +AMD Vega .*(AMD|ATI).*Vega.* 3 1 +AMD Radeon VII .*AMD.*Radeon ?VII.* 3 1 +AMD Radeon RX Series .*ATI.*(Radeon|ASUS).* RX.* 3 1 ATI 760G/Radeon 3000 .*ATI.*AMD 760G.* 1 1 ATI 780L/Radeon 3000 .*ATI.*AMD 780L.* 1 1 ATI Radeon DDR .*ATI.*Radeon ?DDR.* 0 1 @@ -286,6 +288,7 @@ ATI FirePro 5000 .*ATI.*FirePro V5.* 3 1 ATI FirePro 7000 .*ATI.*FirePro V7.* 3 1 ATI FirePro M .*ATI.*FirePro M.* 3 1 ATI Technologies .*ATI *Technologies.* 0 1 +ATI Radeon VE .*ATI.*Radeon.*VE.* 0 0 // This entry is last to work around the "R300" driver problem. ATI R300 (9700) .*R300.* 1 1 ATI Radeon .*ATI.*(Diamond|Radeon).* 0 1 @@ -433,7 +436,17 @@ NVIDIA GTX 750 .*NVIDIA .*GTX *75.* 3 1 NVIDIA GTX 760 .*NVIDIA .*GTX *76.* 3 1 NVIDIA GTX 770 .*NVIDIA .*GTX *77.* 3 1 NVIDIA GTX 780 .*NVIDIA .*GTX *78.* 3 1 +NVIDIA GTX 970 .*NVIDIA .*GTX *97.* 3 1 +NVIDIA GTX 980 .*NVIDIA .*GTX *98.* 3 1 +NVIDIA GTX 1050 .*NVIDIA.*GTX 105.* 3 1 +NVIDIA GTX 1060 .*NVIDIA.*GTX 106.* 3 1 +NVIDIA GTX 1070 .*NVIDIA.*GTX 107.* 3 1 +NVIDIA GTX 1080 .*NVIDIA.*GTX 108.* 3 1 +NVIDIA GTX 1650 .*NVIDIA.*GTX 165.* 3 1 +NVIDIA GTX 1660 .*NVIDIA.*GTX 166.* 3 1 NVIDIA GTX TITAN .*NVIDIA .*GTX *TITAN.* 3 1 +NVIDIA GeForce/Quadro RTX .*(GeForce|Quadro) .*RTX.* 3 1 +NVIDIA RTX TITAN .*NVIDIA .*RTX.*TITAN.* 3 1 NVIDIA GT 7xxM .*NVIDIA .*GT *7.* 3 1 NVIDIA C51 .*NVIDIA .*C51.* 0 1 NVIDIA G72 .*NVIDIA .*G72.* 1 1 diff --git a/indra/newview/hippogridmanager.cpp b/indra/newview/hippogridmanager.cpp index 5295aac957..f6cff71b96 100644 --- a/indra/newview/hippogridmanager.cpp +++ b/indra/newview/hippogridmanager.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -48,6 +47,7 @@ HippoGridInfo::HippoGridInfo(const std::string& gridName) : mWebSite(LLStringUtil::null), mSupportUrl(LLStringUtil::null), mRegisterUrl(LLStringUtil::null), + mPartnerUrl(LLStringUtil::null), mPasswordUrl(LLStringUtil::null), mSearchUrl(LLStringUtil::null), mGridMessage(""), @@ -58,7 +58,6 @@ HippoGridInfo::HippoGridInfo(const std::string& gridName) : mRenderCompat(true), mAutoUpdate(false), mLocked(false), - mMaxAgentGroups(-1), mCurrencySymbol("OS$"), mCurrencyText("OS Dollars"), mRealCurrencySymbol("US$"), @@ -81,7 +80,7 @@ const std::string& HippoGridInfo::getGridOwner() const } else { - return this->getGridName(); + return getGridName(); } } @@ -102,14 +101,13 @@ void HippoGridInfo::setPlatform(Platform platform) void HippoGridInfo::setPlatform(const std::string& platform) { std::string tmp = platform; - for (unsigned i=0; imXmlState = XML_SUPPORT; else if ((strcasecmp(name, "register") == 0) || (strcasecmp(name, "account") == 0)) self->mXmlState = XML_REGISTER; + else if (strcasecmp(name, "partner") == 0) + self->mXmlState = XML_PARTNER; else if (strcasecmp(name, "password") == 0) self->mXmlState = XML_PASSWORD; else if (strcasecmp(name, "search") == 0) @@ -337,7 +342,7 @@ void HippoGridInfo::onXmlCharacterData(void* userData, const XML_Char* s, int le case XML_GRIDNAME: { - if (self->mGridName == "") + if (self->mGridName.empty()) { self->mGridName.assign(s, len); } @@ -348,6 +353,7 @@ void HippoGridInfo::onXmlCharacterData(void* userData, const XML_Char* s, int le case XML_WEBSITE: self->mWebSite.assign(s, len); break; case XML_SUPPORT: self->mSupportUrl.assign(s, len); break; case XML_REGISTER: self->mRegisterUrl.assign(s, len); break; + case XML_PARTNER: self->mPartnerUrl.assign(s, len); break; case XML_PASSWORD: self->mPasswordUrl.assign(s, len); break; case XML_MESSAGE: self->mGridMessage.assign(s, len); break; @@ -366,7 +372,7 @@ void HippoGridInfo::getGridInfo() // Make sure the uri ends on a '/'. std::string uri = mLoginUri; - if (uri.compare(uri.length() - 1, 1, "/") != 0) + if (uri.back() != '/') { uri += '/'; } @@ -406,37 +412,22 @@ void HippoGridInfo::getGridInfo() XML_ParserFree(parser); } -std::string HippoGridInfo::getUploadFee() const -{ - std::string fee; - formatFee(fee, LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(), true); - return fee; -} - -std::string HippoGridInfo::getGroupCreationFee() const -{ - std::string fee; - formatFee(fee, LLGlobalEconomy::Singleton::getInstance()->getPriceGroupCreate(), false); - return fee; -} - std::string HippoGridInfo::getDirectoryFee() const { - std::string fee; - formatFee(fee, mDirectoryFee, true); + std::string fee = formatFee(mDirectoryFee, true); if (mDirectoryFee != 0) fee += "/" + LLTrans::getString("hippo_label_week"); return fee; } -void HippoGridInfo::formatFee(std::string &fee, int cost, bool showFree) const +std::string HippoGridInfo::formatFee(int cost, bool showFree) const { - if (showFree && (cost == 0)) + if (showFree && (cost < 0)) { - fee = LLTrans::getString("hippo_label_free"); + return LLTrans::getString("hippo_label_free"); } else { - fee = llformat("%s%d", getCurrencySymbol().c_str(), cost); + return llformat("%s%d", getCurrencySymbol().c_str(), cost); } } @@ -482,9 +473,9 @@ std::string HippoGridInfo::getGridNick() const // static const char* HippoGridInfo::getPlatformString(Platform platform) { - static const char* platformStrings[PLATFORM_LAST] = + constexpr const char* platformStrings[PLATFORM_LAST] = { - "Other", "Aurora", "OpenSim", "SecondLife" + "Other", "WhiteCore", "OpenSim", "SecondLife" }; if ((platform < PLATFORM_OTHER) || (platform >= PLATFORM_LAST)) @@ -894,6 +885,7 @@ void HippoGridManager::parseData(LLSD &gridInfo, bool mergeIfNewer) if (gridMap.has("website")) grid->setWebSite(gridMap["website"]); if (gridMap.has("support")) grid->setSupportUrl(gridMap["support"]); if (gridMap.has("register")) grid->setRegisterUrl(gridMap["register"]); + if (gridMap.has("partner")) grid->setPartnerUrl(gridMap["partner"]); if (gridMap.has("password")) grid->setPasswordUrl(gridMap["password"]); if (gridMap.has("search")) grid->setSearchUrl(gridMap["search"]); if (gridMap.has("render_compat")) grid->setRenderCompat(gridMap["render_compat"]); @@ -929,6 +921,7 @@ void HippoGridManager::saveFile() gridInfo[i]["website"] = grid->getWebSite(); gridInfo[i]["support"] = grid->getSupportUrl(); gridInfo[i]["register"] = grid->getRegisterUrl(); + gridInfo[i]["partner"] = grid->getPartnerUrl(); gridInfo[i]["password"] = grid->getPasswordUrl(); gridInfo[i]["search"] = grid->getSearchUrl(); diff --git a/indra/newview/hippogridmanager.h b/indra/newview/hippogridmanager.h index 450cc35f70..f7bbdfe870 100644 --- a/indra/newview/hippogridmanager.h +++ b/indra/newview/hippogridmanager.h @@ -26,7 +26,7 @@ class HippoGridInfo public: enum Platform { PLATFORM_OTHER = 0, - PLATFORM_AURORA, + PLATFORM_WHITECORE, PLATFORM_OPENSIM, PLATFORM_SECONDLIFE, PLATFORM_LAST @@ -35,8 +35,8 @@ class HippoGridInfo explicit HippoGridInfo(const std::string& gridName); Platform getPlatform() { return mPlatform; } - bool isOpenSimulator() const { return (mPlatform == PLATFORM_OPENSIM || mPlatform == PLATFORM_AURORA); } - bool isAurora() const { return (mPlatform == PLATFORM_AURORA); } + bool isOpenSimulator() const { return (mPlatform == PLATFORM_OPENSIM || mPlatform == PLATFORM_WHITECORE); } + bool isWhiteCore() const { return (mPlatform == PLATFORM_WHITECORE); } bool isSecondLife() const { return (mPlatform == PLATFORM_SECONDLIFE); } bool isAvination() const { return mIsInAvination; } bool isInProductionGrid() const { llassert(mPlatform == PLATFORM_SECONDLIFE); return mIsInProductionGrid; } // Should only be called if isSecondLife() returns true. @@ -48,6 +48,7 @@ class HippoGridInfo const std::string& getWebSite() const { return mWebSite; } const std::string& getSupportUrl() const { return mSupportUrl; } const std::string& getRegisterUrl() const { return mRegisterUrl; } + const std::string& getPartnerUrl() const { return mPartnerUrl; } const std::string& getPasswordUrl() const { return mPasswordUrl; } // Returns the url base used for the Web Search tab const std::string& getSearchUrl() const { return mSearchUrl; } @@ -55,15 +56,13 @@ class HippoGridInfo const std::string& getVoiceConnector() const { return mVoiceConnector; } bool isRenderCompat() const { return mRenderCompat; } std::string getGridNick() const; - int getMaxAgentGroups() const { return mMaxAgentGroups; } const std::string& getCurrencySymbol() const { return mCurrencySymbol; } const std::string& getCurrencyText() const { return mCurrencyText; } const std::string& getRealCurrencySymbol() const { return mRealCurrencySymbol; } - std::string getUploadFee() const; - std::string getGroupCreationFee() const; const int& getClassifiedFee() const { return mClassifiedFee; } std::string getDirectoryFee() const; + std::string formatFee(S32 cost, bool showFree = true) const; void setPlatform (const std::string& platform); void setPlatform (Platform platform); @@ -75,12 +74,12 @@ class HippoGridInfo void setWebSite (const std::string& website); void setSupportUrl(const std::string& url); void setRegisterUrl(const std::string& url); + void setPartnerUrl(const std::string& url); void setPasswordUrl(const std::string& url); // sets the url base used for the Web Search tab void setSearchUrl(const std::string& url); void setGridMessage(const std::string& message); void setRenderCompat(bool compat); - void setMaxAgentGroups(int max) { mMaxAgentGroups = max; } void setVoiceConnector(const std::string& vc) { mVoiceConnector = vc; } void setUPCSupported(bool on); bool getUPCSupported(); @@ -111,6 +110,7 @@ class HippoGridInfo std::string mWebSite; std::string mSupportUrl; std::string mRegisterUrl; + std::string mPartnerUrl; std::string mPasswordUrl; std::string mSearchUrl; std::string mVoiceConnector; @@ -120,7 +120,6 @@ class HippoGridInfo bool mAutoUpdate; bool mLocked; bool mUPCSupported; - int mMaxAgentGroups; std::string mCurrencySymbol; std::string mCurrencyText; @@ -134,13 +133,12 @@ class HippoGridInfo { XML_VOID, XML_PLATFORM, XML_GRIDNAME, XML_GRIDNICK, XML_LOGINURI, XML_LOGINPAGE, XML_HELPERURI, - XML_WEBSITE, XML_SUPPORT, XML_REGISTER, XML_PASSWORD, XML_SEARCH, XML_MESSAGE + XML_WEBSITE, XML_SUPPORT, XML_REGISTER, XML_PARTNER, XML_PASSWORD, XML_SEARCH, XML_MESSAGE }; XmlState mXmlState; static std::string sanitizeUri(std::string const& uri_in); void useHttps(void); - void formatFee(std::string &fee, int cost, bool showFree) const; static void onXmlElementStart(void* userData, const XML_Char* name, const XML_Char** atts); static void onXmlElementEnd(void* userData, const XML_Char* name); diff --git a/indra/newview/hippolimits.cpp b/indra/newview/hippolimits.cpp index c67cef7bba..346e72267f 100644 --- a/indra/newview/hippolimits.cpp +++ b/indra/newview/hippolimits.cpp @@ -21,37 +21,31 @@ void HippoLimits::setLimits() { if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_SECONDLIFE) { setSecondLifeLimits(); - } else if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_AURORA) { - setAuroraLimits(); + } else if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_WHITECORE) { + setWhiteCoreLimits(); } else { setOpenSimLimits(); } } - void HippoLimits::setOpenSimLimits() { - mMaxAgentGroups = gHippoGridManager->getConnectedGrid()->getMaxAgentGroups(); - if (mMaxAgentGroups < 0) mMaxAgentGroups = 50; mMaxPrimScale = 8192.0f; mMaxHeight = 10000.0f; + mMinPrimScale = 0.001f; if (gHippoGridManager->getConnectedGrid()->isRenderCompat()) { LL_INFOS() << "Using rendering compatible OpenSim limits." << LL_ENDL; - mMinPrimScale = 0.01f; mMinHoleSize = 0.05f; mMaxHollow = 0.95f; } else { LL_INFOS() << "Using Hippo OpenSim limits." << LL_ENDL; - mMinPrimScale = 0.001f; mMinHoleSize = 0.01f; mMaxHollow = 0.99f; } } -void HippoLimits::setAuroraLimits() +void HippoLimits::setWhiteCoreLimits() { - mMaxAgentGroups = gHippoGridManager->getConnectedGrid()->getMaxAgentGroups(); - if (mMaxAgentGroups < 0) mMaxAgentGroups = 50; mMaxPrimScale = 8192.0f; mMinPrimScale = 0.001f; mMaxHeight = 10000.0f; @@ -62,16 +56,7 @@ void HippoLimits::setAuroraLimits() void HippoLimits::setSecondLifeLimits() { LL_INFOS() << "Using Second Life limits." << LL_ENDL; - - if (gHippoGridManager->getConnectedGrid()) - - //KC: new server defined max groups - mMaxAgentGroups = gHippoGridManager->getConnectedGrid()->getMaxAgentGroups(); - if (mMaxAgentGroups <= 0) - { - mMaxAgentGroups = DEFAULT_MAX_AGENT_GROUPS; - } - + mMinPrimScale = 0.01f; mMaxHeight = 4096.0f; mMinHoleSize = 0.05f; diff --git a/indra/newview/hippolimits.h b/indra/newview/hippolimits.h index 91625276b0..3ddfec165f 100644 --- a/indra/newview/hippolimits.h +++ b/indra/newview/hippolimits.h @@ -8,7 +8,6 @@ class HippoLimits public: HippoLimits(); - int getMaxAgentGroups() const { return mMaxAgentGroups; } float getMaxHeight() const { return mMaxHeight; } float getMinHoleSize() const { return mMinHoleSize; } float getMaxHollow() const { return mMaxHollow; } @@ -18,7 +17,6 @@ class HippoLimits void setLimits(); private: - int mMaxAgentGroups; float mMaxHeight; float mMinHoleSize; float mMaxHollow; @@ -26,7 +24,7 @@ class HippoLimits float mMinPrimScale; void setOpenSimLimits(); - void setAuroraLimits(); + void setWhiteCoreLimits(); void setSecondLifeLimits(); }; diff --git a/indra/newview/hippopanelgrids.cpp b/indra/newview/hippopanelgrids.cpp index d5570e84ab..53446f17c6 100644 --- a/indra/newview/hippopanelgrids.cpp +++ b/indra/newview/hippopanelgrids.cpp @@ -130,6 +130,7 @@ BOOL HippoPanelGridsImpl::postBuild() requires("website"); requires("support"); requires("register"); + requires("partner"); requires("password"); requires("search"); requires("btn_delete"); @@ -172,7 +173,7 @@ void HippoPanelGridsImpl::refresh() LLComboBox *grids = getChild("grid_selector"); S32 selectIndex = -1, i = 0; grids->removeall(); - if (defaultGrid != "") { + if (!defaultGrid.empty()) { grids->add(defaultGrid); selectIndex = i++; } @@ -192,10 +193,10 @@ void HippoPanelGridsImpl::refresh() if (selectIndex >= 0) { grids->setCurrentByIndex(selectIndex); } else { - grids->setLabel(LLStringExplicit("")); // LLComboBox::removeall() does not clear the label + grids->setLabel(LLStringUtil::null); // LLComboBox::removeall() does not clear the label } - childSetTextArg("default_grid", "[DEFAULT]", (defaultGrid != "")? defaultGrid: " "); + childSetTextArg("default_grid", "[DEFAULT]", !defaultGrid.empty() ? defaultGrid : " "); childSetEnabled("btn_delete", (selectIndex >= 0) && mIsEditable ); childSetEnabled("btn_copy", (mState == NORMAL) && (selectIndex >= 0)); @@ -244,11 +245,12 @@ void HippoPanelGridsImpl::loadCurGrid() childSetText("support", gridInfo->getSupportUrl()); childSetText("search", gridInfo->getSearchUrl()); childSetText("register", gridInfo->getRegisterUrl()); + childSetText("partner", gridInfo->getPartnerUrl()); childSetText("password", gridInfo->getPasswordUrl()); childSetValue("render_compat", gridInfo->isRenderCompat()); enableEditing(!gridInfo->getLocked()); } else { - std::string empty = ""; + const std::string& empty = LLStringUtil::null; LLComboBox *platform = getChild("platform"); if (platform) platform->setCurrentByIndex(HippoGridInfo::PLATFORM_OTHER); childSetText("gridname", empty); @@ -259,6 +261,7 @@ void HippoPanelGridsImpl::loadCurGrid() childSetText("support", empty); childSetText("search", empty); childSetText("register", empty); + childSetText("partner", empty); childSetText("password", empty); childSetValue("render_compat", true); enableEditing(true); @@ -288,9 +291,9 @@ bool HippoPanelGridsImpl::saveCurGrid() refresh(); std::string gridname = childGetValue("gridname"); - if (gridname == "") gridname = ""; + if (gridname == "") gridname.clear(); std::string loginuri = childGetValue("loginuri"); - if (loginuri == "") loginuri = ""; + if (loginuri == "") loginuri.clear(); if (gridname.empty() && !loginuri.empty()) this->retrieveGridInfo(); @@ -299,8 +302,8 @@ bool HippoPanelGridsImpl::saveCurGrid() // check nickname std::string gridname = childGetValue("gridname"); - childSetValue("gridname", (gridname != "")? gridname: ""); - if (gridname == "") { + childSetValue("gridname", !gridname.empty() ? gridname : ""); + if (gridname.empty()) { LLNotificationsUtil::add("GridsNoNick"); return false; } @@ -312,7 +315,7 @@ bool HippoPanelGridsImpl::saveCurGrid() } // check login URI - if (loginuri == "") { + if (loginuri.empty()) { LLSD args; args["NAME"] = gridname; LLNotificationsUtil::add("GridsNoLoginUri", args); @@ -361,6 +364,7 @@ bool HippoPanelGridsImpl::saveCurGrid() gridInfo->setWebSite(childGetValue("website")); gridInfo->setSupportUrl(childGetValue("support")); gridInfo->setRegisterUrl(childGetValue("register")); + gridInfo->setPartnerUrl(childGetValue("partner")); gridInfo->setPasswordUrl(childGetValue("password")); gridInfo->setSearchUrl(childGetValue("search")); gridInfo->setRenderCompat(childGetValue("render_compat")); @@ -384,7 +388,7 @@ void HippoPanelGridsImpl::reset() void HippoPanelGridsImpl::retrieveGridInfo() { std::string loginuri = childGetValue("loginuri"); - if ((loginuri == "") || (loginuri == "")) { + if ((loginuri.empty()) || (loginuri == "")) { LLNotificationsUtil::add("GridInfoNoLoginUri"); return; } @@ -394,7 +398,7 @@ void HippoPanelGridsImpl::retrieveGridInfo() if (mState == NORMAL) { grid = gHippoGridManager->getGrid(mCurGrid); } else if ((mState == ADD_NEW) || (mState == ADD_COPY)) { - grid = new HippoGridInfo(""); + grid = new HippoGridInfo(LLStringUtil::null); cleanupGrid = true; } else { LL_ERRS() << "Illegal state " << mState << '.' << LL_ENDL; @@ -412,16 +416,17 @@ void HippoPanelGridsImpl::retrieveGridInfo() if (grid->getPlatform() != HippoGridInfo::PLATFORM_OTHER) getChild("platform")->setCurrentByIndex(grid->getPlatform()); - if (grid->getGridName() != "") childSetText("gridname", grid->getGridName()); - if (grid->getLoginUri() != "") childSetText("loginuri", grid->getLoginUri()); - if (grid->getLoginPage() != "") childSetText("loginpage", grid->getLoginPage()); - if (grid->getHelperUri() != "") childSetText("helperuri", grid->getHelperUri()); - if (grid->getWebSite() != "") childSetText("website", grid->getWebSite()); - if (grid->getSupportUrl() != "") childSetText("support", grid->getSupportUrl()); - if (grid->getRegisterUrl() != "") childSetText("register", grid->getRegisterUrl()); - if (grid->getPasswordUrl() != "") childSetText("password", grid->getPasswordUrl()); - if (grid->getSearchUrl() != "") childSetText("search", grid->getSearchUrl()); - if (grid->getGridMessage() != "") childSetText("gridmessage", grid->getGridMessage()); + if (!grid->getGridName().empty()) childSetText("gridname", grid->getGridName()); + if (!grid->getLoginUri().empty()) childSetText("loginuri", grid->getLoginUri()); + if (!grid->getLoginPage().empty()) childSetText("loginpage", grid->getLoginPage()); + if (!grid->getHelperUri().empty()) childSetText("helperuri", grid->getHelperUri()); + if (!grid->getWebSite().empty()) childSetText("website", grid->getWebSite()); + if (!grid->getSupportUrl().empty()) childSetText("support", grid->getSupportUrl()); + if (!grid->getRegisterUrl().empty()) childSetText("register", grid->getRegisterUrl()); + if (!grid->getPartnerUrl().empty()) childSetText("partner", grid->getPartnerUrl()); + if (!grid->getPasswordUrl().empty()) childSetText("password", grid->getPasswordUrl()); + if (!grid->getSearchUrl().empty()) childSetText("search", grid->getSearchUrl()); + if (!grid->getGridMessage().empty()) childSetText("gridmessage", grid->getGridMessage()); } catch(AIAlert::ErrorCode const& error) { @@ -532,6 +537,8 @@ void HippoPanelGridsImpl::onClickAdvanced(void *data) self->childSetVisible("support", false); self->childSetVisible("register_label", false); self->childSetVisible("register", false); + self->childSetVisible("partner_label", false); + self->childSetVisible("partner", false); self->childSetVisible("password_label", false); self->childSetVisible("password", false); self->childSetVisible("search_label", false); @@ -551,6 +558,8 @@ void HippoPanelGridsImpl::onClickAdvanced(void *data) self->childSetVisible("support", true); self->childSetVisible("register_label", true); self->childSetVisible("register", true); + self->childSetVisible("partner_label", true); + self->childSetVisible("partner", true); self->childSetVisible("password_label", true); self->childSetVisible("password", true); self->childSetVisible("search_label", true); @@ -578,6 +587,7 @@ void HippoPanelGridsImpl::enableEditing(bool b) "website", "support", "register", + "partner", "password", "search", "btn_delete", diff --git a/indra/newview/icons/alpha/viewer.icns b/indra/newview/icons/alpha/viewer.icns new file mode 100644 index 0000000000..0b5d5c626a Binary files /dev/null and b/indra/newview/icons/alpha/viewer.icns differ diff --git a/indra/newview/icons/alpha/viewer.ico b/indra/newview/icons/alpha/viewer.ico new file mode 100644 index 0000000000..e15813d24c Binary files /dev/null and b/indra/newview/icons/alpha/viewer.ico differ diff --git a/indra/newview/icons/alpha/viewer.png b/indra/newview/icons/alpha/viewer.png new file mode 100644 index 0000000000..8d7619f958 Binary files /dev/null and b/indra/newview/icons/alpha/viewer.png differ diff --git a/indra/newview/icons/alpha/viewer_256.BMP b/indra/newview/icons/alpha/viewer_256.BMP new file mode 100644 index 0000000000..b42ed064fd Binary files /dev/null and b/indra/newview/icons/alpha/viewer_256.BMP differ diff --git a/indra/newview/icons/default/viewer.icns b/indra/newview/icons/default/viewer.icns new file mode 100644 index 0000000000..28e5a4f446 Binary files /dev/null and b/indra/newview/icons/default/viewer.icns differ diff --git a/indra/newview/installers/windows/install_icon_singularity.ico b/indra/newview/icons/default/viewer.ico similarity index 100% rename from indra/newview/installers/windows/install_icon_singularity.ico rename to indra/newview/icons/default/viewer.ico diff --git a/indra/newview/icons/default/viewer.png b/indra/newview/icons/default/viewer.png new file mode 100644 index 0000000000..ae3d64aa33 Binary files /dev/null and b/indra/newview/icons/default/viewer.png differ diff --git a/indra/newview/icons/default/viewer_256.BMP b/indra/newview/icons/default/viewer_256.BMP new file mode 100644 index 0000000000..32bf37e5cb Binary files /dev/null and b/indra/newview/icons/default/viewer_256.BMP differ diff --git a/indra/newview/importtracker.cpp b/indra/newview/importtracker.cpp index 5975948f6c..284327d170 100644 --- a/indra/newview/importtracker.cpp +++ b/indra/newview/importtracker.cpp @@ -17,7 +17,7 @@ //#include "llsdserialize.h" #include "lltooldraganddrop.h" //#include "llassetuploadresponders.h" -//#include "lleconomy.h" +//#include "llagentbenefits.h" //#include "llfloaterperms.h" @@ -635,7 +635,7 @@ void ImportTracker::send_inventory(LLSD& prim) body["next_owner_mask"] = LLSD::Integer(U32_MAX); body["group_mask"] = LLSD::Integer(U32_MAX); body["everyone_mask"] = LLSD::Integer(U32_MAX); - body["expected_upload_cost"] = LLSD::Integer(LLGlobalEconomy::Singleton::getInstance()->getPriceUpload()); + body["expected_upload_cost"] = LLAgentBenefits::current().getTextureUploadCost(); //cmdline_printchat("posting "+ data->assetid.asString()); LLHTTPClient::post(url, body, new JCImportInventoryResponder(body, data->assetid, data->type,data)); //error = TRUE; diff --git a/indra/newview/installers/darwin/firstlook-dmg/background.jpg b/indra/newview/installers/darwin/firstlook-dmg/background.jpg index 55294dcc9a..3962e2fb31 100644 Binary files a/indra/newview/installers/darwin/firstlook-dmg/background.jpg and b/indra/newview/installers/darwin/firstlook-dmg/background.jpg differ diff --git a/indra/newview/installers/darwin/publicnightly-dmg/background.jpg b/indra/newview/installers/darwin/publicnightly-dmg/background.jpg index 55294dcc9a..3962e2fb31 100644 Binary files a/indra/newview/installers/darwin/publicnightly-dmg/background.jpg and b/indra/newview/installers/darwin/publicnightly-dmg/background.jpg differ diff --git a/indra/newview/installers/darwin/release-dmg/background.jpg b/indra/newview/installers/darwin/release-dmg/background.jpg index 55294dcc9a..3962e2fb31 100644 Binary files a/indra/newview/installers/darwin/release-dmg/background.jpg and b/indra/newview/installers/darwin/release-dmg/background.jpg differ diff --git a/indra/newview/installers/darwin/releasecandidate-dmg/background.jpg b/indra/newview/installers/darwin/releasecandidate-dmg/background.jpg index 55294dcc9a..3962e2fb31 100644 Binary files a/indra/newview/installers/darwin/releasecandidate-dmg/background.jpg and b/indra/newview/installers/darwin/releasecandidate-dmg/background.jpg differ diff --git a/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt b/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt deleted file mode 100644 index 30f9349111..0000000000 --- a/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt +++ /dev/null @@ -1,6 +0,0 @@ -The language files in this directory are Unicode (Little-Endian) format, also known as UTF-16 LE. - -This is the format required for NSIS Unicode. See http://www.scratchpaper.com/ for details. - -James Cook -September 2008 diff --git a/indra/newview/installers/windows/install_icon.ico b/indra/newview/installers/windows/install_icon.ico index 1e00530c90..84a455a226 100644 Binary files a/indra/newview/installers/windows/install_icon.ico and b/indra/newview/installers/windows/install_icon.ico differ diff --git a/indra/newview/installers/windows/install_icon_singularity.BMP b/indra/newview/installers/windows/install_icon_singularity.BMP deleted file mode 100644 index 09df573870..0000000000 Binary files a/indra/newview/installers/windows/install_icon_singularity.BMP and /dev/null differ diff --git a/indra/newview/installers/windows/install_icon_snowglobe.BMP b/indra/newview/installers/windows/install_icon_snowglobe.BMP deleted file mode 100644 index 86817c5411..0000000000 Binary files a/indra/newview/installers/windows/install_icon_snowglobe.BMP and /dev/null differ diff --git a/indra/newview/installers/windows/install_icon_snowglobe.ico b/indra/newview/installers/windows/install_icon_snowglobe.ico deleted file mode 100644 index e866e91a29..0000000000 Binary files a/indra/newview/installers/windows/install_icon_snowglobe.ico and /dev/null differ diff --git a/indra/newview/installers/windows/install_welcome.bmp b/indra/newview/installers/windows/install_welcome.bmp new file mode 100644 index 0000000000..196a5b7a7e Binary files /dev/null and b/indra/newview/installers/windows/install_welcome.bmp differ diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 5ec4a4274b..e44ff819b5 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -1,207 +1,335 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; secondlife setup.nsi -;; Copyright 2004-2008, Linden Research, Inc. +;; Copyright 2004-2011, Linden Research, Inc. +;; Copyright 2013-2015 Alchemy Viewer Project ;; -;; NSIS Unicode 2.38.1 or higher required -;; http://www.scratchpaper.com/ +;; 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. ;; -;; Author: James Cook, Don Kjer, Callum Prentice -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Compiler flags -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -SetOverwrite on ; overwrite files -SetCompress auto ; compress iff saves space -SetCompressor /solid /final lzma ; compress whole installer as one block -SetDatablockOptimize off ; only saves us 0.1%, not worth it -XPStyle on ; add an XP manifest to the installer -RequestExecutionLevel admin ; on Vista we must be admin because we write to Program Files - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Project flags -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -%%VERSION%% +;; 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 +;; +;; NSIS 3 or higher required for Unicode support +;; +;; Author: James Cook, Don Kjer, Callum Prentice, Drake Arconis +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;-------------------------------- +;Unicode + Unicode true + +;-------------------------------- +;Include Modern UI + + !include "LogicLib.nsh" + !include "StdUtils.nsh" + !include "FileFunc.nsh" + !insertmacro GetParameters + !insertmacro GetOptions + !include "x64.nsh" + !include "WinVer.nsh" + !include "MUI2.nsh" + +;------------------------------- +;Global Variables + ; These will be replaced by manifest scripts + %%INST_VARS%% + %%WIN64_BIN_BUILD%% + + Var INSTEXE + Var INSTPROG + Var INSTSHORTCUT + Var AUTOSTART + Var COMMANDLINE ; command line passed to this installer, set in .onInit + Var SHORTCUT_LANG_PARAM ; "--set InstallLanguage de", passes language to viewer + Var SKIP_DIALOGS ; set from command line in .onInit. autoinstall + ; GUI and the defaults. + Var SKIP_AUTORUN ; skip automatic launch of viewer after install + Var STARTMENUFOLDER + +;-------------------------------- +;Registry Keys + !define ALCHEMY_KEY "SOFTWARE\${VENDORSTR}" + !define INSTNAME_KEY "${ALCHEMY_KEY}\${APPNAMEONEWORD}" + !define MSCURRVER_KEY "SOFTWARE\Microsoft\Windows\CurrentVersion" + !define MSNTCURRVER_KEY "SOFTWARE\Microsoft\Windows NT\CurrentVersion" + !define MSUNINSTALL_KEY "${MSCURRVER_KEY}\Uninstall\${APPNAMEONEWORD}" + +;-------------------------------- +;General + + ;Name and file + Name "${APPNAME}" + OutFile "${INSTOUTFILE}" + Caption "${CAPTIONSTR}" + BrandingText "${VENDORSTR}" + + ;Default installation folder +!ifdef WIN64_BIN_BUILD + InstallDir "$PROGRAMFILES64\${APPNAMEONEWORD}" +!else + InstallDir "$PROGRAMFILES\${APPNAMEONEWORD}" +!endif -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tweak for different servers/builds (this placeholder is replaced by viewer_manifest.py) -;; For example: -;; !define INSTFLAGS "%(flags)s" -;; !define INSTNAME "SecondLife%(grid_caps)s" -;; !define SHORTCUT "Second Life (%(grid_caps)s)" -;; !define URLNAME "secondlife%(grid)s" -;; !define AUTHOR "Linden Research, Inc." -;; !define UNINSTALL_SETTINGS 1 + ;Get installation folder from registry if available and 32bit otherwise do it in init +!ifndef WIN64_BIN_BUILD + InstallDirRegKey HKLM "${INSTNAME_KEY}" "" +!endif -%%GRID_VARS%% + ;Request application privileges for Windows UAC + RequestExecutionLevel admin + + ;Compression + SetCompress auto ; compress to saves space + SetCompressor /solid /final lzma ; compress whole installer as one block + + ;File Handling + SetOverwrite on + + ;Verify CRC + CRCCheck on + +;-------------------------------- +;Interface Settings + + ;Show Details + ShowInstDetails hide + ShowUninstDetails hide + + !define MUI_ICON "%%SOURCE%%\installers\windows\install_icon.ico" + !define MUI_UNICON "%%SOURCE%%\installers\windows\uninstall_icon.ico" + !define MUI_WELCOMEFINISHPAGE_BITMAP "%%SOURCE%%\installers\windows\install_welcome.bmp" + !define MUI_UNWELCOMEFINISHPAGE_BITMAP "%%SOURCE%%\installers\windows\uninstall_welcome.bmp" + !define MUI_ABORTWARNING + +;-------------------------------- +;Language Selection Dialog Settings + + ;Show all languages, despite user's codepage + !define MUI_LANGDLL_ALLLANGUAGES + + ;Remember the installer language + !define MUI_LANGDLL_REGISTRY_ROOT "HKLM" + !define MUI_LANGDLL_REGISTRY_KEY "${INSTNAME_KEY}" + !define MUI_LANGDLL_REGISTRY_VALUENAME "InstallerLanguage" + + ;Always show the dialog + !define MUI_LANGDLL_ALWAYSSHOW + +;-------------------------------- +;Install Pages + + !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip + !insertmacro MUI_PAGE_WELCOME + + ;License Page + !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip + !insertmacro MUI_PAGE_LICENSE "%%SOURCE%%\..\..\doc\GPL-license.txt" + + ;Directory Page + !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip + !insertmacro MUI_PAGE_DIRECTORY + + ;Start Menu Folder Page + !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM" + !define MUI_STARTMENUPAGE_REGISTRY_KEY "${INSTNAME_KEY}" + !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" + !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip +!ifdef WIN64_BIN_BUILD + !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${APPNAME} (64 bit) Viewer" +!else + !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${APPNAME} Viewer" +!endif + !insertmacro MUI_PAGE_STARTMENU Application $STARTMENUFOLDER + + ;Install Progress Page + !define MUI_PAGE_CUSTOMFUNCTION_LEAVE CheckWindowsServPack + !insertmacro MUI_PAGE_INSTFILES + + ; Finish Page + !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip_finish + !define MUI_FINISHPAGE_RUN + !define MUI_FINISHPAGE_RUN_FUNCTION launch_viewer + !define MUI_FINISHPAGE_SHOWREADME + !define MUI_FINISHPAGE_SHOWREADME_TEXT "Create Desktop Shortcut" + !define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED + !define MUI_FINISHPAGE_SHOWREADME_FUNCTION create_desktop_shortcut + !define MUI_FINISHPAGE_NOREBOOTSUPPORT + !insertmacro MUI_PAGE_FINISH + +;-------------------------------- +;Uninstall Pages + + !insertmacro MUI_UNPAGE_WELCOME + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + !insertmacro MUI_UNPAGE_FINISH + +;-------------------------------- +;Languages + + !include "%%SOURCE%%\installers\windows\lang_en-us.nsi" + !include "%%SOURCE%%\installers\windows\lang_de.nsi" + !include "%%SOURCE%%\installers\windows\lang_es.nsi" + !include "%%SOURCE%%\installers\windows\lang_fr.nsi" + !include "%%SOURCE%%\installers\windows\lang_ja.nsi" + !include "%%SOURCE%%\installers\windows\lang_pl.nsi" + !include "%%SOURCE%%\installers\windows\lang_it.nsi" + !include "%%SOURCE%%\installers\windows\lang_pt-br.nsi" + !include "%%SOURCE%%\installers\windows\lang_da.nsi" + !include "%%SOURCE%%\installers\windows\lang_ru.nsi" + !include "%%SOURCE%%\installers\windows\lang_tr.nsi" + !include "%%SOURCE%%\installers\windows\lang_zh.nsi" + +;-------------------------------- +;Version Information + + VIProductVersion "${VERSION_LONG}" + VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "Singularity Viewer Installer" + VIAddVersionKey /LANG=${LANG_ENGLISH} "Comments" "A viewer for the meta-verse!" + VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "${VENDORSTR}" + VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "Copyright © 2010-2020, ${VENDORSTR}" + VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "${APPNAME} Installer" + VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductVersion" "${VERSION_LONG}" + VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${VERSION_LONG}" + +;-------------------------------- +;Reserve Files + + ;If you are using solid compression, files that are required before + ;the actual installation should be stored first in the data block, + ;because this will make your installer start faster. + + !insertmacro MUI_RESERVEFILE_LANGDLL + ReserveFile "${NSISDIR}\Plugins\x86-unicode\INetC.dll" + ReserveFile "${NSISDIR}\Plugins\x86-unicode\nsDialogs.dll" + ReserveFile "${NSISDIR}\Plugins\x86-unicode\nsis7z.dll" + ReserveFile "${NSISDIR}\Plugins\x86-unicode\StartMenu.dll" + ReserveFile "${NSISDIR}\Plugins\x86-unicode\StdUtils.dll" + ReserveFile "${NSISDIR}\Plugins\x86-unicode\System.dll" + ReserveFile "${NSISDIR}\Plugins\x86-unicode\UserInfo.dll" + +;-------------------------------- +; Local Functions + +;Page pre-checks for skip conditions +Function check_skip + StrCmp $SKIP_DIALOGS "true" 0 +2 + Abort +FunctionEnd -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Alows us to determine if we're running on 64 bit OS; ${If} macros -!include "x64.nsh" -!include "LogicLib.nsh" +Function check_skip_finish + StrCmp $SKIP_DIALOGS "true" 0 +4 + StrCmp $AUTOSTART "true" 0 +3 + Call launch_viewer + Abort +FunctionEnd -;; are 64 bit binaries packaged in this installer -%%WIN64_BIN_BUILD%% +Function launch_viewer + ${StdUtils.ExecShellAsUser} $0 "$INSTDIR\$INSTEXE" "open" "$SHORTCUT_LANG_PARAM" +FunctionEnd -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; - language files - one for each language (or flavor thereof) -;; (these files are in the same place as the nsi template but the python script generates a new nsi file in the -;; application directory so we have to add a path to these include files) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -!include "%%SOURCE%%\installers\windows\lang_de.nsi" -!include "%%SOURCE%%\installers\windows\lang_en-us.nsi" -!include "%%SOURCE%%\installers\windows\lang_es.nsi" -!include "%%SOURCE%%\installers\windows\lang_fr.nsi" -!include "%%SOURCE%%\installers\windows\lang_ja.nsi" -!include "%%SOURCE%%\installers\windows\lang_it.nsi" -!include "%%SOURCE%%\installers\windows\lang_ko.nsi" -!include "%%SOURCE%%\installers\windows\lang_nl.nsi" -!include "%%SOURCE%%\installers\windows\lang_pt-br.nsi" -!include "%%SOURCE%%\installers\windows\lang_zh.nsi" - -# *TODO: Move these into the language files themselves -LangString LanguageCode ${LANG_GERMAN} "de" -LangString LanguageCode ${LANG_ENGLISH} "en" -LangString LanguageCode ${LANG_SPANISH} "es" -LangString LanguageCode ${LANG_FRENCH} "fr" -LangString LanguageCode ${LANG_JAPANESE} "ja" -LangString LanguageCode ${LANG_ITALIAN} "it" -LangString LanguageCode ${LANG_KOREAN} "ko" -LangString LanguageCode ${LANG_DUTCH} "nl" -LangString LanguageCode ${LANG_PORTUGUESEBR} "pt" -LangString LanguageCode ${LANG_SIMPCHINESE} "zh" - -Name "${VIEWERNAME}" - -SubCaption 0 $(LicenseSubTitleSetup) ; override "license agreement" text - -BrandingText "Prepare to Implode!" ; bottom of window text -Icon "%%SOURCE%%\installers\windows\${INSTALL_ICON}" -UninstallIcon "%%SOURCE%%\installers\windows\${UNINSTALL_ICON}" -WindowIcon off ; show our icon in left corner -# BGGradient 9090b0 000000 notext -CRCCheck on ; make sure CRC is OK -#InstProgressFlags smooth colored ; new colored smooth look -InstProgressFlags -InstallColors /windows -ShowInstDetails show ; no details, no "show" button -SetOverwrite on ; stomp files by default -AutoCloseWindow true ; after all files install, close window - -InstallDir "%%INSTALLDIR%%" -InstallDirRegKey HKEY_LOCAL_MACHINE "SOFTWARE\${AUTHOR}\${INSTNAME}" "" -DirText $(DirectoryChooseTitle) $(DirectoryChooseSetup) +Function create_desktop_shortcut +!ifdef WIN64_BIN_BUILD + CreateShortCut "$DESKTOP\$INSTSHORTCUT x64.lnk" "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$INSTEXE" +!else + CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$INSTEXE" +!endif +FunctionEnd -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Variables -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Var INSTPROG -Var INSTEXE -Var INSTFLAGS -Var INSTSHORTCUT -Var COMMANDLINE ; command line passed to this installer, set in .onInit -Var SHORTCUT_LANG_PARAM ; "--set InstallLanguage de", passes language to viewer - -;;; Function definitions should go before file includes, because calls to -;;; DLLs like LangDLL trigger an implicit file include, so if that call is at -;;; the end of this script NSIS has to decompress the whole installer before -;;; it can call the DLL function. JC - -!include "FileFunc.nsh" ; For GetParameters, GetOptions -!insertmacro GetParameters -!insertmacro GetOptions +;Check version compatibility +Function CheckWindowsVersion +!ifdef WIN64_BIN_BUILD + ${IfNot} ${RunningX64} + MessageBox MB_OK|MB_ICONSTOP "This version requires a 64 bit operating system." + Quit + ${EndIf} +!endif -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; After install completes, launch app -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function .onInstSuccess - Push $R0 # Option value, unused - ${GetOptions} $COMMANDLINE "/AUTOSTART" $R0 - # If parameter was there (no error) just launch - # Otherwise ask - IfErrors label_ask_launch label_launch - -label_ask_launch: - # Don't launch by default when silent - IfSilent label_no_launch - MessageBox MB_YESNO $(InstSuccesssQuestion) \ - IDYES label_launch IDNO label_no_launch - -label_launch: - # Assumes SetOutPath $INSTDIR - Exec '"$INSTDIR\$INSTEXE" $INSTFLAGS $SHORTCUT_LANG_PARAM' -label_no_launch: - Pop $R0 + ${If} ${AtMostWinVista} + MessageBox MB_OK $(CheckWindowsVersionMB) + Quit + ${EndIf} FunctionEnd +;Check service pack compatibility and suggest upgrade +Function CheckWindowsServPack + ${If} ${IsWin7} + ${AndIfNot} ${IsServicePack} 1 + MessageBox MB_OK $(CheckWindowsServPackMB) + DetailPrint $(UseLatestServPackDP) + Return + ${EndIf} -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Make sure we're not on Windows 98 / ME -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function CheckWindowsVersion - DetailPrint "Checking Windows version..." - Call GetWindowsVersion - Pop $R0 - ; Just get first two characters, ignore 4.0 part of "NT 4.0" - StrCpy $R0 $R0 2 - ; Blacklist certain OS versions - StrCmp $R0 "95" win_ver_bad - StrCmp $R0 "98" win_ver_bad - StrCmp $R0 "ME" win_ver_bad - StrCmp $R0 "NT" win_ver_bad - Return -win_ver_bad: - MessageBox MB_YESNO $(CheckWindowsVersionMB) IDNO win_ver_abort - Return -win_ver_abort: - Quit + ${If} ${IsWin2008R2} + ${AndIfNot} ${IsServicePack} 1 + MessageBox MB_OK $(CheckWindowsServPackMB) + DetailPrint $(UseLatestServPackDP) + Return + ${EndIf} FunctionEnd -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Make sure the user can install/uninstall -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;Make sure the user can install/uninstall Function CheckIfAdministrator - DetailPrint $(CheckAdministratorInstDP) - UserInfo::GetAccountType - Pop $R0 - StrCmp $R0 "Admin" lbl_is_admin - MessageBox MB_OK $(CheckAdministratorInstMB) - Quit + DetailPrint $(CheckAdministratorInstDP) + UserInfo::GetAccountType + Pop $R0 + StrCmp $R0 "Admin" lbl_is_admin + MessageBox MB_OK $(CheckAdministratorInstMB) + Quit lbl_is_admin: - Return + Return FunctionEnd -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function un.CheckIfAdministrator - DetailPrint $(CheckAdministratorUnInstDP) - UserInfo::GetAccountType - Pop $R0 - StrCmp $R0 "Admin" lbl_is_admin - MessageBox MB_OK $(CheckAdministratorUnInstMB) - Quit + DetailPrint $(CheckAdministratorUnInstDP) + UserInfo::GetAccountType + Pop $R0 + StrCmp $R0 "Admin" lbl_is_admin + MessageBox MB_OK $(CheckAdministratorUnInstMB) + Quit lbl_is_admin: - Return + Return FunctionEnd -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Checks to see if the current version has already been installed (according to the registry). -; If it has, allow user to bail out of install process. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;Checks for CPU compatibility +Function CheckCPUFlags + Push $1 + System::Call 'kernel32::IsProcessorFeaturePresent(i) i(10) .r1' + IntCmp $1 1 OK_SSE2 + MessageBox MB_OKCANCEL $(MissingSSE2) /SD IDOK IDOK OK_SSE2 + Quit + + OK_SSE2: + Pop $1 + Return +FunctionEnd + +;Checks if installed version is same as installer and offers to cancel Function CheckIfAlreadyCurrent +!ifdef WIN64_BIN_BUILD + SetRegView 64 +!endif Push $0 - ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\${AUTHOR}\$INSTPROG" "Version" - StrCmp $0 ${VERSION_LONG} 0 DONE - MessageBox MB_OKCANCEL $(CheckIfCurrentMB) /SD IDOK IDOK DONE - Quit - - DONE: - Pop $0 - Return + ReadRegStr $0 HKLM "SOFTWARE\${VENDORSTR}\$INSTPROG" "Version" + StrCmp $0 ${VERSION_LONG} 0 continue_install + StrCmp $SKIP_DIALOGS "true" continue_install + MessageBox MB_OKCANCEL $(CheckIfCurrentMB) /SD IDOK IDOK continue_install + Quit +continue_install: + Pop $0 + Return FunctionEnd - + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Close the program, if running. Modifies no variables. ; Allows user to bail out of install process. @@ -210,225 +338,28 @@ Function CloseSecondLife Push $0 FindWindow $0 "Second Life" "" IntCmp $0 0 DONE - MessageBox MB_YESNOCANCEL $(CloseSecondLifeInstMB) IDYES CLOSE IDNO DONE - Goto CANCEL_INSTALL ; IDCANCEL + + StrCmp $SKIP_DIALOGS "true" CLOSE + MessageBox MB_YESNOCANCEL $(CloseSecondLifeInstMB) IDYES CLOSE IDNO DONE - CANCEL_INSTALL: - Quit +; CANCEL_INSTALL: + Quit CLOSE: DetailPrint $(CloseSecondLifeInstDP) SendMessage $0 16 0 0 LOOP: - FindWindow $0 "Second Life" "" - IntCmp $0 0 DONE - Sleep 500 - Goto LOOP + FindWindow $0 "Second Life" "" + IntCmp $0 0 DONE + Sleep 500 + Goto LOOP DONE: Pop $0 Return FunctionEnd -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Test our connection to secondlife.com -; Also allows us to count attempted installs by examining web logs. -; *TODO: Return current SL version info and have installer check -; if it is up to date. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function CheckNetworkConnection - Push $0 - Push $1 - Push $2 # Option value for GetOptions - DetailPrint $(CheckNetworkConnectionDP) - ; Look for a tag value from the stub installer, used for statistics - ; to correlate installs. Default to "" if not found on command line. - StrCpy $2 "" - ${GetOptions} $COMMANDLINE "/STUBTAG=" $2 - GetTempFileName $0 - !define HTTP_TIMEOUT 5000 ; milliseconds - ; Don't show secondary progress bar, this will be quick. - NSISdl::download_quiet \ - /TIMEOUT=${HTTP_TIMEOUT} \ - "http://install.secondlife.com/check/?stubtag=$2&version=${VERSION_LONG}" \ - $0 - Pop $1 ; Return value, either "success", "cancel" or an error message - ; MessageBox MB_OK "Download result: $1" - ; Result ignored for now - ; StrCmp $1 "success" +2 - ; DetailPrint "Connection failed: $1" - Delete $0 ; temporary file - Pop $2 - Pop $1 - Pop $0 - Return -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Delete files in Documents and Settings\\SecondLife\cache -; Delete files in Documents and Settings\All Users\SecondLife\cache -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;Function RemoveCacheFiles -; -;; Delete files in Documents and Settings\\SecondLife -;Push $0 -;Push $1 -;Push $2 -; DetailPrint $(RemoveCacheFilesDP) -; -; StrCpy $0 0 ; Index number used to iterate via EnumRegKey -; -; LOOP: -; EnumRegKey $1 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" $0 -; StrCmp $1 "" DONE ; no more users -; -; ReadRegStr $2 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$1" "ProfileImagePath" -; StrCmp $2 "" CONTINUE 0 ; "ProfileImagePath" value is missing -; -; ; Required since ProfileImagePath is of type REG_EXPAND_SZ -; ExpandEnvStrings $2 $2 -; -; ; When explicitly uninstalling, everything goes away -; RMDir /r "$2\Application Data\SecondLife\cache" -; -; CONTINUE: -; IntOp $0 $0 + 1 -; Goto LOOP -; DONE: -;Pop $2 -;Pop $1 -;Pop $0 -; -;; Delete files in Documents and Settings\All Users\SecondLife -;Push $0 -; ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" "Common AppData" -; StrCmp $0 "" +2 -; RMDir /r "$0\SecondLife\cache" -;Pop $0 -; -;; Delete filse in C:\Windows\Application Data\SecondLife -;; If the user is running on a pre-NT system, Application Data lives here instead of -;; in Documents and Settings. -;RMDir /r "$WINDIR\Application Data\SecondLife\cache" -; -;FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Delete the installed shader files -;;; Since shaders are in active development, we'll likely need to shuffle them -;;; around a bit from build to build. This ensures that shaders that we move -;;; or rename in the dev tree don't get left behind in the install. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function RemoveOldShaders - -;; Remove old shader files first so fallbacks will work. see DEV-5663 -RMDir /r "$INSTDIR\app_settings\shaders\*" - -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Delete the installed XUI files -;;; We've changed the directory hierarchy for skins, putting all XUI and texture -;;; files under a specific skin directory, i.e. skins/default/xui/en-us as opposed -;;; to skins/xui/en-us. Need to clean up the old path when upgrading -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function RemoveOldXUI - -;; remove old XUI and texture files -RmDir /r "$INSTDIR\skins\html" -RmDir /r "$INSTDIR\skins\xui" -RmDir /r "$INSTDIR\skins\textures" -Delete "$INSTDIR\skins\*.txt" - -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Remove any releasenotes files. -;;; We are no longer including release notes with the viewer. This will delete -;;; any that were left behind by an older installer. Delete will not fail if -;;; the files do not exist -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function RemoveOldReleaseNotes - -;; remove releasenotes.txt file from application directory, and the shortcut -;; from the start menu. -Delete "$SMPROGRAMS\$INSTSHORTCUT\SL Release Notes.lnk" -Delete "$INSTDIR\releasenotes.txt" - -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Delete a xui file that causes crash in Silver skin in cases where it was -;;; left behind by an older installer. -;;; See SNOW-348 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function RemoveOldAboutLandSilver - -Delete "$INSTDIR\skins\silver\xui\en-us\floater_about_land.xml" - -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Delete files in Documents and Settings\\SecondLife -; Delete files in Documents and Settings\All Users\SecondLife -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function un.DocumentsAndSettingsFolder - -; Delete files in Documents and Settings\\SecondLife -Push $0 -Push $1 -Push $2 - - DetailPrint "Deleting files in Documents and Settings folder" - - StrCpy $0 0 ; Index number used to iterate via EnumRegKey - - LOOP: - EnumRegKey $1 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" $0 - StrCmp $1 "" DONE ; no more users - - ReadRegStr $2 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$1" "ProfileImagePath" - StrCmp $2 "" CONTINUE 0 ; "ProfileImagePath" value is missing - - ; Required since ProfileImagePath is of type REG_EXPAND_SZ - ExpandEnvStrings $2 $2 - - ; If uninstalling a normal install remove everything - ; Otherwise (preview/dmz etc) just remove cache - StrCmp $INSTFLAGS "" RM_ALL RM_CACHE - RM_ALL: - RMDir /r "$2\Application Data\SecondLife" - RM_CACHE: - # Local Settings directory is the cache, there is no "cache" subdir - RMDir /r "$2\Local Settings\Application Data\SecondLife" - # Vista version of the same - RMDir /r "$2\AppData\Local\SecondLife" - Delete "$2\Application Data\SecondLife\user_settings\settings_windlight.xml" - - CONTINUE: - IntOp $0 $0 + 1 - Goto LOOP - DONE: - -Pop $2 -Pop $1 -Pop $0 - -; Delete files in Documents and Settings\All Users\SecondLife -Push $0 - ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" "Common AppData" - StrCmp $0 "" +2 - RMDir /r "$0\SecondLife" -Pop $0 - -; Delete filse in C:\Windows\Application Data\SecondLife -; If the user is running on a pre-NT system, Application Data lives here instead of -; in Documents and Settings. -RMDir /r "$WINDIR\Application Data\SecondLife" - -FunctionEnd - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Close the program, if running. Modifies no variables. ; Allows user to bail out of uninstall process. @@ -437,21 +368,20 @@ Function un.CloseSecondLife Push $0 FindWindow $0 "Second Life" "" IntCmp $0 0 DONE - MessageBox MB_YESNOCANCEL $(CloseSecondLifeUnInstMB) IDYES CLOSE IDNO DONE - Goto CANCEL_UNINSTALL ; IDCANCEL + MessageBox MB_OKCANCEL $(CloseSecondLifeUnInstMB) IDOK CLOSE IDCANCEL CANCEL_UNINSTALL CANCEL_UNINSTALL: - Quit + Quit CLOSE: DetailPrint $(CloseSecondLifeUnInstDP) SendMessage $0 16 0 0 LOOP: - FindWindow $0 "Second Life" "" - IntCmp $0 0 DONE - Sleep 500 - Goto LOOP + FindWindow $0 "Second Life" "" + IntCmp $0 0 DONE + Sleep 500 + Goto LOOP DONE: Pop $0 @@ -459,384 +389,301 @@ Function un.CloseSecondLife FunctionEnd -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; -; Delete the stored password for the current Windows user -; DEV-10821 -- Unauthorised user can gain access to an SL account after a real user has uninstalled -; -Function un.RemovePassword - -DetailPrint "Removing Second Life password" -SetShellVarContext current -Delete "$APPDATA\SecondLife\user_settings\password.dat" -SetShellVarContext all +;-------------------------------- +;Installer Sections -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Delete the installed files -;;; This deletes the uninstall executable, but it works -;;; because it is copied to temp directory before running -;;; -;;; Note: You must list all files here, because we only -;;; want to delete our files, not things users left in the -;;; application directories. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function un.ProgramFiles - -;; Remove mozilla file first so recursive directory deletion doesn't get hung up -Delete "$INSTDIR\app_settings\mozilla\components" - -;; This placeholder is replaced by the complete list of files to uninstall by viewer_manifest.py -%%DELETE_FILES%% - -;; Optional/obsolete files. Delete won't fail if they don't exist. -Delete "$INSTDIR\dronesettings.ini" -Delete "$INSTDIR\message_template.msg" -Delete "$INSTDIR\newview.pdb" -Delete "$INSTDIR\newview.map" -Delete "$INSTDIR\SecondLife.pdb" -Delete "$INSTDIR\SecondLife.map" -Delete "$INSTDIR\comm.dat" -Delete "$INSTDIR\*.glsl" -Delete "$INSTDIR\motions\*.lla" -Delete "$INSTDIR\trial\*.html" -Delete "$INSTDIR\newview.exe" -;; Remove entire help directory -Delete "$INSTDIR\help\Advanced\*" -RMDir "$INSTDIR\help\Advanced" -Delete "$INSTDIR\help\basics\*" -RMDir "$INSTDIR\help\basics" -Delete "$INSTDIR\help\Concepts\*" -RMDir "$INSTDIR\help\Concepts" -Delete "$INSTDIR\help\welcome\*" -RMDir "$INSTDIR\help\welcome" -Delete "$INSTDIR\help\*" -RMDir "$INSTDIR\help" - -Delete "$INSTDIR\uninst.exe" -RMDir "$INSTDIR" - -IfFileExists "$INSTDIR" FOLDERFOUND NOFOLDER - -FOLDERFOUND: - MessageBox MB_YESNO $(DeleteProgramFilesMB) IDNO NOFOLDER - RMDir /r "$INSTDIR" - -NOFOLDER: - -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Uninstall settings -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -UninstallText $(UninstallTextMsg) -ShowUninstDetails show - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Uninstall section -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Section Uninstall - -; Start with some default values. -StrCpy $INSTFLAGS "" -StrCpy $INSTPROG "${INSTNAME}" -StrCpy $INSTEXE "${INSTEXE}" -StrCpy $INSTSHORTCUT "${SHORTCUT}" -Call un.CheckIfAdministrator ; Make sure the user can install/uninstall - -; uninstall for all users (if you change this, change it in the install as well) -SetShellVarContext all - -; Make sure we're not running -Call un.CloseSecondLife - -; Clean up registry keys and subkeys (these should all be !defines somewhere) -DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\${AUTHOR}\$INSTPROG" -DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" - -; Clean up shortcuts -Delete "$SMPROGRAMS\$INSTSHORTCUT\*.*" -RMDir "$SMPROGRAMS\$INSTSHORTCUT" +Section "Viewer" + SectionIn RO + SetShellVarContext all +!ifdef WIN64_BIN_BUILD + SetRegView 64 +!endif + ;Start with some default values. + StrCpy $INSTPROG "${APPNAMEONEWORD}" + StrCpy $INSTEXE "${INSTEXE}" + StrCpy $INSTSHORTCUT "${APPNAME}" + + Call CheckIfAlreadyCurrent + Call CloseSecondLife ; Make sure we're not running + + SetOutPath "$INSTDIR" + ;Remove old shader files first so fallbacks will work. + RMDir /r "$INSTDIR\app_settings\shaders\*" + ;Remove old Microsoft DLLs, reboot if needed + Delete /REBOOTOK "$INSTDIR\api-ms-win-*.dll" + Delete /REBOOTOK "$INSTDIR\concrt*.dll" + Delete /REBOOTOK "$INSTDIR\msvcp*.dll" + Delete /REBOOTOK "$INSTDIR\ucrtbase.dll" + Delete /REBOOTOK "$INSTDIR\vccorlib*.dll" + Delete /REBOOTOK "$INSTDIR\vcruntime*.dll" + + ;This placeholder is replaced by the complete list of all the files in the installer, by viewer_manifest.py + %%INSTALL_FILES%% + + ;Create temp dir and set out dir to it + CreateDirectory "$TEMP\AlchemyInst" + SetOutPath "$TEMP\AlchemyInst" + + ;Download LibVLC +!ifdef WIN64_BIN_BUILD + inetc::get /RESUME "Failed to download VLC media package. Retry?" "https://download.videolan.org/pub/videolan/vlc/3.0.8/win64/vlc-3.0.8-win64.7z" "$TEMP\AlchemyInst\libvlc.7z" /END +!else + inetc::get /RESUME "Failed to download VLC media package. Retry?" "https://download.videolan.org/pub/videolan/vlc/3.0.8/win32/vlc-3.0.8-win32.7z" "$TEMP\AlchemyInst\libvlc.7z" /END +!endif + Nsis7z::ExtractWithDetails "$TEMP\AlchemyInst\libvlc.7z" "Unpacking media plugins %s..." + Rename "$TEMP\AlchemyInst\vlc-3.0.8\libvlc.dll" "$INSTDIR\llplugin\libvlc.dll" + Rename "$TEMP\AlchemyInst\vlc-3.0.8\libvlccore.dll" "$INSTDIR\llplugin\libvlccore.dll" + Rename "$TEMP\AlchemyInst\vlc-3.0.8\plugins" "$INSTDIR\llplugin\plugins" -Delete "$DESKTOP\$INSTSHORTCUT.lnk" -Delete "$INSTDIR\$INSTSHORTCUT.lnk" -Delete "$INSTDIR\$INSTSHORTCUT Portable.lnk" -Delete "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" + ;Download and install VC redist +!ifdef WIN64_BIN_BUILD + inetc::get /RESUME "Failed to download VS2019 redistributable package. Retry?" "https://aka.ms/vs/16/release/vc_redist.x64.exe" "$TEMP\AlchemyInst\vc_redist_16.x64.exe" /END + ExecWait "$TEMP\AlchemyInst\vc_redist_16.x64.exe /install /passive /norestart" -; Clean up cache and log files. -; Leave them in-place for non AGNI installs. + inetc::get /RESUME "Failed to download VS2013 redistributable package. Retry?" "https://aka.ms/highdpimfc2013x64enu" "$TEMP\AlchemyInst\vc_redist_12.x64.exe" /END + ExecWait "$TEMP\AlchemyInst\vc_redist_12.x64.exe /install /passive /norestart" +!else + inetc::get /RESUME "Failed to download VS2019 redistributable package. Retry?" "https://aka.ms/vs/16/release/vc_redist.x86.exe" "$TEMP\AlchemyInst\vc_redist_16.x86.exe" /END + ExecWait "$TEMP\AlchemyInst\vc_redist_16.x86.exe /install /passive /norestart" -!ifdef UNINSTALL_SETTINGS -Call un.DocumentsAndSettingsFolder + inetc::get /RESUME "Failed to download VS2013 redistributable package. Retry?" "https://aka.ms/highdpimfc2013x86enu" "$TEMP\AlchemyInst\vc_redist_12.x86.exe" /END + ExecWait "$TEMP\AlchemyInst\vc_redist_12.x86.exe /install /passive /norestart" !endif -; remove stored password on uninstall -Call un.RemovePassword - -Call un.ProgramFiles - -SectionEnd ; end of uninstall section + ;Remove temp dir and reset out to inst dir + RMDir /r "$TEMP\AlchemyInst\" + SetOutPath "$INSTDIR" + ;Pass the installer's language to the client to use as a default + StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)" + + ;Create startmenu shortcuts + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + CreateDirectory "$SMPROGRAMS\$STARTMENUFOLDER" +!ifdef WIN64_BIN_BUILD + CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\$INSTSHORTCUT (64 bit) Viewer.lnk" "$\"$INSTDIR\$INSTEXE$\"" "$SHORTCUT_LANG_PARAM" + CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\Uninstall $INSTSHORTCUT (64 bit) Viewer.lnk" "$\"$INSTDIR\uninst.exe$\"" "" +!else + CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\$INSTSHORTCUT.lnk" "$\"$INSTDIR\$INSTEXE$\"" "$SHORTCUT_LANG_PARAM" + CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\Uninstall $INSTSHORTCUT.lnk" "$\"$INSTDIR\uninst.exe$\"" "" +!endif + WriteINIStr "$SMPROGRAMS\$STARTMENUFOLDER\SL Create Account.url" "InternetShortcut" "URL" "https://join.secondlife.com/" + WriteINIStr "$SMPROGRAMS\$STARTMENUFOLDER\SL Your Account.url" "InternetShortcut" "URL" "https://www.secondlife.com/account/" + WriteINIStr "$SMPROGRAMS\$STARTMENUFOLDER\SL Scripting Language Help.url" "InternetShortcut" "URL" "https://wiki.secondlife.com/wiki/LSL_Portal" -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; (From the NSIS documentation, JC) -; GetWindowsVersion -; -; Based on Yazno's function, http://yazno.tripod.com/powerpimpit/ -; Updated by Joost Verburg -; -; Returns on top of stack -; -; Windows Version (95, 98, ME, NT x.x, 2000, XP, 2003) -; or -; '' (Unknown Windows Version) -; -; Usage: -; Call GetWindowsVersion -; Pop $R0 -; ; at this point $R0 is "NT 4.0" or whatnot -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function GetWindowsVersion - - Push $R0 - Push $R1 - - ReadRegStr $R0 HKLM \ - "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion - - IfErrors 0 lbl_winnt - - ; we are not NT - ReadRegStr $R0 HKLM \ - "SOFTWARE\Microsoft\Windows\CurrentVersion" VersionNumber - - StrCpy $R1 $R0 1 - StrCmp $R1 '4' 0 lbl_error - - StrCpy $R1 $R0 3 - - StrCmp $R1 '4.0' lbl_win32_95 - StrCmp $R1 '4.9' lbl_win32_ME lbl_win32_98 - - lbl_win32_95: - StrCpy $R0 '95' - Goto lbl_done - - lbl_win32_98: - StrCpy $R0 '98' - Goto lbl_done - - lbl_win32_ME: - StrCpy $R0 'ME' - Goto lbl_done - - lbl_winnt: - - StrCpy $R1 $R0 1 - - StrCmp $R1 '3' lbl_winnt_x - StrCmp $R1 '4' lbl_winnt_x - - StrCpy $R1 $R0 3 - - StrCmp $R1 '5.0' lbl_winnt_2000 - StrCmp $R1 '5.1' lbl_winnt_XP - StrCmp $R1 '5.2' lbl_winnt_2003 lbl_error - - lbl_winnt_x: - StrCpy $R0 "NT $R0" 6 - Goto lbl_done - - lbl_winnt_2000: - Strcpy $R0 '2000' - Goto lbl_done - - lbl_winnt_XP: - Strcpy $R0 'XP' - Goto lbl_done - - lbl_winnt_2003: - Strcpy $R0 '2003' - Goto lbl_done - - lbl_error: - Strcpy $R0 '' - lbl_done: - - Pop $R1 - Exch $R0 - -FunctionEnd + !insertmacro MUI_STARTMENU_WRITE_END -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Note: to add new languages, add a language file include to the list -;; at the top of this file, add an entry to the menu and then add an -;; entry to the language ID selector below -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function .onInit + ;Other shortcuts + SetOutPath "$INSTDIR" !ifdef WIN64_BIN_BUILD - ${IfNot} ${RunningX64} - MessageBox MB_OK|MB_ICONSTOP "This version requires 64 bit operating sytem." - Quit - ${EndIf} + ;CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" + CreateShortCut "$INSTDIR\$INSTSHORTCUT (64 bit) Viewer.lnk" "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" + CreateShortCut "$INSTDIR\$INSTSHORTCUT (64 bit) Viewer Portable.lnk" "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM --portable" + CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT (64 bit) Viewer.lnk" "$INSTDIR\uninst.exe" "" +!else + ;CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" + CreateShortCut "$INSTDIR\$INSTSHORTCUT Viewer.lnk" "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" + CreateShortCut "$INSTDIR\$INSTSHORTCUT Viewer Portable.lnk" "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM --portable" + CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT Viewer.lnk" "$INSTDIR\uninst.exe" "" !endif - Push $0 - ${GetParameters} $COMMANDLINE ; get our command line - ${GetOptions} $COMMANDLINE "/LANGID=" $0 ; /LANGID=1033 implies US English - ; If no language (error), then proceed - IfErrors lbl_check_silent - ; No error means we got a language, so use it - StrCpy $LANGUAGE $0 - Goto lbl_return - -lbl_check_silent: - ; For silent installs, no language prompt, use default - IfSilent lbl_return - - ; If we currently have a version of SL installed, default to the language of that install - ; Otherwise don't change $LANGUAGE and it will default to the OS UI language. - ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\${AUTHOR}\${INSTNAME}" "InstallerLanguage" - IfErrors lbl_build_menu - StrCpy $LANGUAGE $0 - -lbl_build_menu: - Push "" - # Use separate file so labels can be UTF-16 but we can still merge changes - # into this ASCII file. JC - !include "%%SOURCE%%\installers\windows\language_menu.nsi" - Push A ; A means auto count languages for the auto count to work the first empty push (Push "") must remain - LangDLL::LangDialog $(InstallerLanguageTitle) $(SelectInstallerLanguage) - Pop $0 - StrCmp $0 "cancel" 0 +2 - Abort - StrCpy $LANGUAGE $0 - - ; save language in registry - WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\${AUTHOR}\${INSTNAME}" "InstallerLanguage" $LANGUAGE -lbl_return: - Pop $0 - Return -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function un.onInit - ; read language from registry and set for uninstaller - ; Key will be removed on successful uninstall - ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\${AUTHOR}\${INSTNAME}" "InstallerLanguage" - IfErrors lbl_end - StrCpy $LANGUAGE $0 -lbl_end: - Return -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; MAIN SECTION -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Section "" ; (default section) - -SetShellVarContext all ; install for all users (if you change this, change it in the uninstall as well) - -; Start with some default values. -StrCpy $INSTFLAGS "${INSTFLAGS}" -StrCpy $INSTPROG "${INSTNAME}" -StrCpy $INSTEXE "${INSTEXE}" -StrCpy $INSTSHORTCUT "${SHORTCUT}" + ;Write registry + WriteRegStr HKLM "${INSTNAME_KEY}" "" "$INSTDIR" + WriteRegStr HKLM "${INSTNAME_KEY}" "Version" "${VERSION_LONG}" + WriteRegStr HKLM "${INSTNAME_KEY}" "Shortcut" "$INSTSHORTCUT" + WriteRegStr HKLM "${INSTNAME_KEY}" "Exe" "$INSTEXE" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "Comments" "A viewer for the meta-verse!" +!ifdef WIN64_BIN_BUILD + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayName" "$INSTSHORTCUT (64 bit) Viewer" +!else + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayName" "$INSTSHORTCUT Viewer" +!endif + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayIcon" "$INSTDIR\$INSTEXE" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayVersion" "${VERSION_LONG}" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "InstallLocation" "$INSTDIR" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "InstallSource" "$EXEDIR\" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "HelpLink" "http://www.singularityviewer.org" + WriteRegDWORD HKLM "${MSUNINSTALL_KEY}" "NoModify" 1 + WriteRegDWORD HKLM "${MSUNINSTALL_KEY}" "NoRepair" 1 + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "Publisher" "${VENDORSTR}" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "URLInfoAbout" "http://www.singularityviewer.org" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "URLUpdateInfo" "http://www.singularityviewer.org/downloads" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "UninstallString" "$\"$INSTDIR\uninst.exe$\"" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninst.exe$\" /S" + ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 + IntFmt $0 "0x%08X" $0 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "EstimatedSize" "$0" + + + ;Write URL registry info + DeleteRegKey HKEY_CLASSES_ROOT "${URLNAME}" + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "" "URL:Second Life" + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "URL Protocol" "" + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\DefaultIcon" "" "$INSTDIR\$INSTEXE" + ;; URL param must be last item passed to viewer, it ignores subsequent params + ;; to avoid parameter injection attacks. + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\shell" "" "open" +!ifdef WIN64_BIN_BUILD + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open" "FriendlyAppName" "$INSTSHORTCUT (64 bit) Viewer" +!else + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open" "FriendlyAppName" "$INSTSHORTCUT Viewer" +!endif + WriteRegExpandStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open\command" "" "$\"$INSTDIR\$INSTEXE$\" -url $\"%1$\"" + + DeleteRegKey HKEY_CLASSES_ROOT "x-grid-info" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info" "" "URL:Hypergrid" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info" "URL Protocol" "" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\DefaultIcon" "" "$INSTDIR\$INSTEXE" + ;; URL param must be last item passed to viewer, it ignores subsequent params + ;; to avoid parameter injection attacks. + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\shell" "" "open" +!ifdef WIN64_BIN_BUILD + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT (64 bit) Viewer" +!else + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT Viewer" +!endif + WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-info\shell\open\command" "" "$\"$INSTDIR\$INSTEXE$\" -url $\"%1$\"" -Call CheckWindowsVersion ; warn if on Windows 98/ME -Call CheckIfAdministrator ; Make sure the user can install/uninstall -Call CheckIfAlreadyCurrent ; Make sure that we haven't already installed this version -Call CloseSecondLife ; Make sure we're not running -#Call CheckNetworkConnection ; ping secondlife.com + DeleteRegKey HKEY_CLASSES_ROOT "x-grid-location-info" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info" "" "URL:Hypergrid legacy" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info" "URL Protocol" "" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\DefaultIcon" "" "$\"$INSTDIR\$INSTEXE$\"" -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Don't remove cache files during a regular install, removing the inventory cache on upgrades results in lots of damage to the servers. -;Call RemoveCacheFiles ; Installing over removes potentially corrupted - ; VFS and cache files. + ;; URL param must be last item passed to viewer, it ignores subsequent params + ;; to avoid parameter injection attacks. + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\shell" "" "open" +!ifdef WIN64_BIN_BUILD + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT (64 bit) Viewer" +!else + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT Viewer" +!endif + WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" "$\"$INSTDIR\$INSTEXE$\" -url $\"%1$\"" + + ;Create uninstaller + SetOutPath "$INSTDIR" + WriteUninstaller "$INSTDIR\uninst.exe" + +SectionEnd -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Need to clean out shader files from previous installs to fix DEV-5663 -Call RemoveOldShaders +;-------------------------------- +;Installer Functions +Function .onInit +!ifdef WIN64_BIN_BUILD + SetRegView 64 +!endif + ;Don't install on unsupported operating systems + Call CheckWindowsVersion + ;Don't install if not administator + Call CheckIfAdministrator + ;Don't install if we lack required cpu support + Call CheckCPUFlags -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Need to clean out old XUI files that predate skinning -Call RemoveOldXUI + Push $0 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Clear out old releasenotes.txt files. These are now on the public wiki. -Call RemoveOldReleaseNotes + ;Get installation folder from registry if available for 64bit +!ifdef WIN64_BIN_BUILD + ReadRegStr $0 HKLM "SOFTWARE\${VENDORSTR}\${APPNAMEONEWORD}" "" + IfErrors +2 0 ; If error jump past setting SKIP_AUTORUN + StrCpy $INSTDIR $0 +!endif -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Remove an old xui file that should not be in Silver skin -Call RemoveOldAboutLandSilver + ${GetParameters} $COMMANDLINE ; get our command line + + ${GetOptions} $COMMANDLINE "/SKIP_DIALOGS" $0 + IfErrors +2 0 ; If error jump past setting SKIP_DIALOGS + StrCpy $SKIP_DIALOGS "true" + + ${GetOptions} $COMMANDLINE "/SKIP_AUTORUN" $0 + IfErrors +2 0 ; If error jump past setting SKIP_AUTORUN + StrCpy $SKIP_AUTORUN "true" + + ${GetOptions} $COMMANDLINE "/AUTOSTART" $0 + IfErrors +2 0 ; If error jump past setting AUTOSTART + StrCpy $AUTOSTART "true" + + + ${GetOptions} $COMMANDLINE "/LANGID=" $0 ; /LANGID=1033 implies US English + ; If no language (error), then proceed + IfErrors lbl_configure_default_lang + ; No error means we got a language, so use it + StrCpy $LANGUAGE $0 + Goto lbl_return + +lbl_configure_default_lang: + ;For silent installs, no language prompt, use default + IfSilent lbl_return + StrCmp $SKIP_DIALOGS "true" lbl_return + + !insertmacro MUI_LANGDLL_DISPLAY -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Files -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; This placeholder is replaced by the complete list of all the files in the installer, by viewer_manifest.py -%%INSTALL_FILES%% +lbl_return: + Pop $0 + Return +FunctionEnd -# Pass the installer's language to the client to use as a default -StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)" +;-------------------------------- +;Uninstaller Section -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Shortcuts in start menu -CreateDirectory "$SMPROGRAMS\$INSTSHORTCUT" -SetOutPath "$INSTDIR" -CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\$INSTSHORTCUT.lnk" \ - "$INSTDIR\$INSTEXE" "$INSTFLAGS $SHORTCUT_LANG_PARAM" - - -WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Create Account.url" \ - "InternetShortcut" "URL" \ - "http://www.secondlife.com/registration/" -WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Your Account.url" \ - "InternetShortcut" "URL" \ - "http://www.secondlife.com/account/" -WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Scripting Language Help.url" \ - "InternetShortcut" "URL" \ - "http://wiki.secondlife.com/wiki/LSL_Portal" -CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\Uninstall $INSTSHORTCUT.lnk" \ - '"$INSTDIR\uninst.exe"' '' +Section "Uninstall" + SectionIn RO + SetShellVarContext all +!ifdef WIN64_BIN_BUILD + SetRegView 64 +!endif + + StrCpy $INSTPROG "${APPNAMEONEWORD}" + StrCpy $INSTSHORTCUT "${APPNAME}" + + Call un.CloseSecondLife + + !insertmacro MUI_STARTMENU_GETFOLDER Application $STARTMENUFOLDER + RMDir /r "$SMPROGRAMS\$STARTMENUFOLDER" + + ;This placeholder is replaced by the complete list of all the files in the installer, by viewer_manifest.py + %%DELETE_FILES%% + + ;Optional/obsolete files. Delete won't fail if they don't exist. + Delete "$INSTDIR\message_template.msg" + Delete "$INSTDIR\VivoxVoiceService-*.log" + + ;Shortcuts in install directory +!ifdef WIN64_BIN_BUILD + Delete "$INSTDIR\$INSTSHORTCUT (64 bit) Viewer.lnk" + Delete "$INSTDIR\$INSTSHORTCUT (64 bit) Viewer Portable.lnk" + Delete "$INSTDIR\Uninstall $INSTSHORTCUT (64 bit) Viewer.lnk" +!else + Delete "$INSTDIR\$INSTSHORTCUT Viewer.lnk" + Delete "$INSTDIR\$INSTSHORTCUT Viewer Portable.lnk" + Delete "$INSTDIR\Uninstall $INSTSHORTCUT Viewer.lnk" +!endif + + Delete "$INSTDIR\uninst.exe" + RMDir "$INSTDIR" + + IfFileExists "$INSTDIR" FOLDERFOUND NOFOLDER -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Other shortcuts -SetOutPath "$INSTDIR" -CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" \ - "$INSTDIR\$INSTEXE" "$INSTFLAGS $SHORTCUT_LANG_PARAM" -CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" \ - "$INSTDIR\$INSTEXE" "$INSTFLAGS $SHORTCUT_LANG_PARAM" -CreateShortCut "$INSTDIR\$INSTSHORTCUT Portable.lnk" \ - "$INSTDIR\$INSTEXE" "$INSTFLAGS $SHORTCUT_LANG_PARAM --portable" -CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \ - '"$INSTDIR\uninst.exe"' '' +FOLDERFOUND: + ;Silent uninstall always removes all files (/SD IDYES) + MessageBox MB_YESNO $(DeleteProgramFilesMB) /SD IDYES IDNO NOFOLDER + RMDir /r "$INSTDIR" +NOFOLDER: + DeleteRegKey HKLM "SOFTWARE\${VENDORSTR}\$INSTPROG" + DeleteRegKey /ifempty HKLM "SOFTWARE\${VENDORSTR}" + DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" + +SectionEnd -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Write registry -WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\${AUTHOR}\$INSTPROG" "" "$INSTDIR" -WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\${AUTHOR}\$INSTPROG" "Version" "${VERSION_LONG}" -WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\${AUTHOR}\$INSTPROG" "Flags" "$INSTFLAGS" -WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\${AUTHOR}\$INSTPROG" "Shortcut" "$INSTSHORTCUT" -WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\${AUTHOR}\$INSTPROG" "Exe" "$INSTEXE" -WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "DisplayName" "$INSTPROG (remove only)" -WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "UninstallString" '"$INSTDIR\uninst.exe"' +;-------------------------------- +;Uninstaller Functions -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Write URL registry info -WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "(default)" "URL:Second Life" -WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "URL Protocol" "" -WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\DefaultIcon" "" '"$INSTDIR\$INSTEXE"' -;; URL param must be last item passed to viewer, it ignores subsequent params -;; to avoid parameter injection attacks. -WriteRegExpandStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open\command" "" '"$INSTDIR\$INSTEXE" $INSTFLAGS -url "%1"' - -; write out uninstaller -WriteUninstaller "$INSTDIR\uninst.exe" - -; end of default section -SectionEnd +Function un.onInit +!ifdef WIN64_BIN_BUILD + SetRegView 64 +!endif + Call un.CheckIfAdministrator -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EOF ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + !insertmacro MUI_UNGETLANGUAGE + +FunctionEnd diff --git a/indra/newview/installers/windows/lang_da.nsi b/indra/newview/installers/windows/lang_da.nsi new file mode 100644 index 0000000000..87e88492e8 --- /dev/null +++ b/indra/newview/installers/windows/lang_da.nsi @@ -0,0 +1,56 @@ +; First is default +!insertmacro MUI_LANGUAGE "Danish" + +; Language string +LangString LanguageCode ${LANG_DANISH} "da" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_DANISH} "Vælg venligst sprog til installation" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_DANISH} "Installationsmappe" +LangString DirectoryChooseUpdate ${LANG_DANISH} "Vælg ${APPNAME} mappe til opdatering til version ${VERSION_LONG}.(XXX):" +LangString DirectoryChooseSetup ${LANG_DANISH} "Vælg mappe hvor ${APPNAME} skal installeres:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_DANISH} "Kunne ikke finde programmet '$INSTPROG'. Baggrundsopdatering fejlede." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_DANISH} "Checker Windows version..." +LangString CheckWindowsVersionMB ${LANG_DANISH} '${APPNAME} supporterer kun Windows XP.$\n$\nForsøg på installation på Windows $R0 kan resultere i nedbrud og datatab.$\n$\n' +LangString CheckWindowsServPackMB ${LANG_DANISH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_DANISH} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_DANISH} "Checker rettigheder til installation..." +LangString CheckAdministratorInstMB ${LANG_DANISH} 'Det ser ud til at du benytter en konto med begrænsninger.$\nDu skal have "administrator" rettigheder for at installere ${APPNAME}.' + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_DANISH} "Checker rettigheder til at afinstallere..." +LangString CheckAdministratorUnInstMB ${LANG_DANISH} 'Det ser ud til at du benytter en konto med begrænsninger.$\nDu skal have "administrator" rettigheder for at afinstallere ${APPNAME}.' + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_DANISH} "Det ser ud til at ${APPNAME} ${VERSION_LONG} allerede er installeret.$\n$\nØnsker du at installere igen?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_DANISH} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_DANISH} "Venter på at ${APPNAME} skal lukke ned..." +LangString CloseSecondLifeInstMB ${LANG_DANISH} "${APPNAME} kan ikke installeres mens programmet kører.$\n$\nAfslut programmet for at fortsætte.$\nVælg ANNULÉR for at afbryde installation." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_DANISH} "Venter på at ${APPNAME} skal lukke ned..." +LangString CloseSecondLifeUnInstMB ${LANG_DANISH} "${APPNAME} kan ikke afinstalleres mens programmet kører.$\n$\nAfslut programmet for at fortsætte.$\nVælg ANNULÉR for at afbryde installation." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_DANISH} "Checker netværksforbindelse..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_DANISH} "Sletter cache filer i dokument mappen" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_DANISH} "Der er stadig filer i ${APPNAME} program mappen.$\n$\nDette er sandsynligvis filer du har oprettet eller flyttet til :$\n$INSTDIR$\n$\nØnsker du at fjerne disse filer?" + +; uninstall text +LangString UninstallTextMsg ${LANG_DANISH} "Dette vil afinstallere ${APPNAME} ${VERSION_LONG} fra dit system." diff --git a/indra/newview/installers/windows/lang_de.nsi b/indra/newview/installers/windows/lang_de.nsi index b717a4d3a5..a9d99fb749 100644 Binary files a/indra/newview/installers/windows/lang_de.nsi and b/indra/newview/installers/windows/lang_de.nsi differ diff --git a/indra/newview/installers/windows/lang_en-us.nsi b/indra/newview/installers/windows/lang_en-us.nsi index 9ff4820756..9b0b64a7a5 100644 Binary files a/indra/newview/installers/windows/lang_en-us.nsi and b/indra/newview/installers/windows/lang_en-us.nsi differ diff --git a/indra/newview/installers/windows/lang_es.nsi b/indra/newview/installers/windows/lang_es.nsi index c6a7f38f3f..f4dd51a595 100644 Binary files a/indra/newview/installers/windows/lang_es.nsi and b/indra/newview/installers/windows/lang_es.nsi differ diff --git a/indra/newview/installers/windows/lang_fr.nsi b/indra/newview/installers/windows/lang_fr.nsi index 008c240ed7..6e11ffa6d8 100644 Binary files a/indra/newview/installers/windows/lang_fr.nsi and b/indra/newview/installers/windows/lang_fr.nsi differ diff --git a/indra/newview/installers/windows/lang_it.nsi b/indra/newview/installers/windows/lang_it.nsi index 1208ec4eb8..465b137099 100644 Binary files a/indra/newview/installers/windows/lang_it.nsi and b/indra/newview/installers/windows/lang_it.nsi differ diff --git a/indra/newview/installers/windows/lang_ja.nsi b/indra/newview/installers/windows/lang_ja.nsi index f564291f7d..f4cf3c75cf 100644 Binary files a/indra/newview/installers/windows/lang_ja.nsi and b/indra/newview/installers/windows/lang_ja.nsi differ diff --git a/indra/newview/installers/windows/lang_pl.nsi b/indra/newview/installers/windows/lang_pl.nsi new file mode 100644 index 0000000000..5e6c183b1f --- /dev/null +++ b/indra/newview/installers/windows/lang_pl.nsi @@ -0,0 +1,56 @@ +; First is default +!insertmacro MUI_LANGUAGE "Polish" + +; Language string +LangString LanguageCode ${LANG_POLISH} "pl" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_POLISH} "Proszę wybrać język instalatora" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_POLISH} "Katalog instalacji" +LangString DirectoryChooseUpdate ${LANG_POLISH} "Wybierz katalog instalacji ${APPNAME} w celu aktualizacji wersji ${VERSION_LONG}.(XXX):" +LangString DirectoryChooseSetup ${LANG_POLISH} "Wybierz katalog instalacji ${APPNAME} w:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_POLISH} "Nie można odnaleźć programu '$INSTPROG'. Cicha aktualizacja zakończyła się niepowodzeniem." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_POLISH} "Sprawdzanie wersji Windows..." +LangString CheckWindowsVersionMB ${LANG_POLISH} '${APPNAME} obsługuje tylko Windows XP.$\n$\nPróba zainstalowania na Windows $R0 może spowodować awarie i utratę danych.$\n$\n' +LangString CheckWindowsServPackMB ${LANG_POLISH} "Zalecane jest uruchamianie ${APPNAME} z najnowszym dostępnym Service Packiem zainstalowanym w systemie.$\nPomaga on w podniesieniu wydajności i stabilności programu." +LangString UseLatestServPackDP ${LANG_POLISH} "Użyj usługi Windows Update, aby zainstalować najnowszy Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_POLISH} "Sprawdzanie zezwolenia na instalację..." +LangString CheckAdministratorInstMB ${LANG_POLISH} 'Używasz "ograniczonego" konta.$\nMusisz być zalogowany jako "administrator" aby zainstalować ${APPNAME}.' + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_POLISH} "Sprawdzanie zezwolenia na odinstalowanie..." +LangString CheckAdministratorUnInstMB ${LANG_POLISH} 'Używasz "ograniczonego" konta.$\nMusisz być być zalogowany jako "administrator" aby zainstalować ${APPNAME}.' + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_POLISH} "${APPNAME} ${VERSION_LONG} jest już zainstalowane.$\n$\nCzy chcesz zainstalować ${APPNAME} ponownie?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_POLISH} "Ten komputer może nie mieć procesora z obsługą SSE2, który jest wymagany aby uruchomić ${APPNAME} w wersji ${VERSION_LONG}. Chcesz kontynuować?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_POLISH} "Oczekiwanie na zamknięcie ${APPNAME}..." +LangString CloseSecondLifeInstMB ${LANG_POLISH} "${APPNAME} nie może zostać zainstalowane, ponieważ jest już włączone.$\n$\nZakończ swoje działania i wybierz OK aby zamknąć ${APPNAME} i kontynuować.$\nWybierz CANCEL aby anulować instalację." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_POLISH} "Oczekiwanie na zamknięcie ${APPNAME}..." +LangString CloseSecondLifeUnInstMB ${LANG_POLISH} "${APPNAME} nie może zostać zainstalowane, ponieważ jest już włączone.$\n$\nZakończ swoje działania i wybierz OK aby zamknąć ${APPNAME} i kontynuować.$\nWybierz CANCEL aby anulować." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_POLISH} "Sprawdzanie połączenia sieciowego..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_POLISH} "Kasowanie plików pamięci podręcznej (cache) w folderze Documents and Settings" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_POLISH} "Nadal istnieją pliki w katalogu instalacyjnym ${APPNAME}.$\n$\nMożliwe, że są to pliki, które stworzyłeś/stworzyłaś lub przeniosłeś/przeniosłaś do:$\n$INSTDIR$\n$\nCzy chcesz je usunąć?" + +; uninstall text +LangString UninstallTextMsg ${LANG_POLISH} "To spowoduje odinstalowanie ${APPNAME} ${VERSION_LONG} z Twojego systemu." diff --git a/indra/newview/installers/windows/lang_pt-br.nsi b/indra/newview/installers/windows/lang_pt-br.nsi index da56a3c336..6ddbadab59 100644 Binary files a/indra/newview/installers/windows/lang_pt-br.nsi and b/indra/newview/installers/windows/lang_pt-br.nsi differ diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsi new file mode 100644 index 0000000000..ed4cd47c68 --- /dev/null +++ b/indra/newview/installers/windows/lang_ru.nsi @@ -0,0 +1,56 @@ +; First is default +!insertmacro MUI_LANGUAGE "Russian" + +; Language string +LangString LanguageCode ${LANG_RUSSIAN} "ru" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_RUSSIAN} "Выберите язык программы установки" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_RUSSIAN} "Каталог установки" +LangString DirectoryChooseUpdate ${LANG_RUSSIAN} "Выберите каталог ${APPNAME} для обновления до версии ${VERSION_LONG}.(XXX):" +LangString DirectoryChooseSetup ${LANG_RUSSIAN} "Выберите каталог для установки ${APPNAME}:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_RUSSIAN} "Не удалось найти программу «$INSTPROG». Автоматическое обновление не выполнено." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_RUSSIAN} "Проверка версии Windows..." +LangString CheckWindowsVersionMB ${LANG_RUSSIAN} '${APPNAME} может работать только в Windows XP.$\n$\nПопытка установки в Windows $R0 может привести к сбою и потере данных.$\n$\n' +LangString CheckWindowsServPackMB ${LANG_RUSSIAN} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_RUSSIAN} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_RUSSIAN} "Проверка разрешений на установку..." +LangString CheckAdministratorInstMB ${LANG_RUSSIAN} 'Вероятно, у вас ограниченный аккаунт.$\nДля установки ${APPNAME} необходимы права администратора.' + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_RUSSIAN} "Проверка разрешений на удаление..." +LangString CheckAdministratorUnInstMB ${LANG_RUSSIAN} 'Вероятно, у вас ограниченный аккаунт.$\nДля удаления ${APPNAME} необходимы права администратора.' + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_RUSSIAN} "Вероятно, версия ${APPNAME} ${VERSION_LONG} уже установлена.$\n$\nУстановить ее снова?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_RUSSIAN} "Возможно, на этом компьютере нет ЦП с поддержкой SSE2, которая необходима для работы ${APPNAME} ${VERSION_LONG}. Продолжить?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_RUSSIAN} "Ожидаю завершения работы ${APPNAME}..." +LangString CloseSecondLifeInstMB ${LANG_RUSSIAN} "${APPNAME} уже работает, выполнить установку невозможно.$\n$\nЗавершите текущую операцию и нажмите кнопку «OK», чтобы закрыть ${APPNAME} и продолжить установку.$\nНажмите кнопку «ОТМЕНА» для отказа от установки." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_RUSSIAN} "Ожидаю завершения работы ${APPNAME}..." +LangString CloseSecondLifeUnInstMB ${LANG_RUSSIAN} "${APPNAME} уже работает, выполнить удаление невозможно.$\n$\nЗавершите текущую операцию и нажмите кнопку «OK», чтобы закрыть ${APPNAME} и продолжить удаление.$\nНажмите кнопку «ОТМЕНА» для отказа от удаления." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_RUSSIAN} "Проверка подключения к сети..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_RUSSIAN} "Удаление файлов кэша из папки «Documents and Settings»" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_RUSSIAN} "В каталоге программы ${APPNAME} остались файлы.$\n$\nВероятно, это файлы, созданные или перемещенные вами в $\n$INSTDIR$\n$\nУдалить их?" + +; uninstall text +LangString UninstallTextMsg ${LANG_RUSSIAN} "Программа ${APPNAME} ${VERSION_LONG} будет удалена из вашей системы." diff --git a/indra/newview/installers/windows/lang_tr.nsi b/indra/newview/installers/windows/lang_tr.nsi new file mode 100644 index 0000000000..262c327487 --- /dev/null +++ b/indra/newview/installers/windows/lang_tr.nsi @@ -0,0 +1,56 @@ +; First is default +!insertmacro MUI_LANGUAGE "Turkish" + +; Language string +LangString LanguageCode ${LANG_TURKISH} "tr" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_TURKISH} "Lütfen yükleyicinin dilini seçin" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_TURKISH} "Yükleme Dizini" +LangString DirectoryChooseUpdate ${LANG_TURKISH} "${VERSION_LONG}.(XXX) sürümüne güncelleştirme yapmak için ${APPNAME} dizinini seçin:" +LangString DirectoryChooseSetup ${LANG_TURKISH} "${APPNAME}'ın yükleneceği dizini seçin:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_TURKISH} "'$INSTPROG' programı bulunamadı. Sessiz güncelleştirme başarılamadı." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_TURKISH} "Windows sürümü kontrol ediliyor..." +LangString CheckWindowsVersionMB ${LANG_TURKISH} "${APPNAME} sadece Windows XP'i destekler.$\n$\nWindows $R0 üzerine yüklemeye çalışmak sistem çökmelerine ve veri kaybına neden olabilir.$\n$\n" +LangString CheckWindowsServPackMB ${LANG_TURKISH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_TURKISH} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_TURKISH} "Yükleme izni kontrol ediliyor..." +LangString CheckAdministratorInstMB ${LANG_TURKISH} "'Sınırlı' bir hesap kullanıyor görünüyorsunuz.$\n${APPNAME}'ı yüklemek için bir 'yönetici' olmalısınız." + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_TURKISH} "Kaldırma izni kontrol ediliyor..." +LangString CheckAdministratorUnInstMB ${LANG_TURKISH} "'Sınırlı' bir hesap kullanıyor görünüyorsunuz.$\n${APPNAME}'ı kaldırmak için bir 'yönetici' olmalısınız." + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_TURKISH} "${APPNAME} ${VERSION_LONG} zaten yüklü.$\n$\nTekrar yüklemek ister misiniz?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_TURKISH} "Bu makinede SSE2 desteğine sahip bir CPU bulunmayabilir, ${APPNAME} ${VERSION_LONG} çalıştırmak için bu gereklidir. Devam etmek istiyor musunuz?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_TURKISH} "${APPNAME}'ın kapatılması bekleniyor..." +LangString CloseSecondLifeInstMB ${LANG_TURKISH} "${APPNAME} zaten çalışırken kapatılamaz.$\n$\nYaptığınız işi bitirdikten sonra ${APPNAME}'ı kapatmak ve devam etmek için Tamam seçimini yapın.$\nYüklemeyi iptal etmek için İPTAL seçimini yapın." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_TURKISH} "${APPNAME}'ın kapatılması bekleniyor..." +LangString CloseSecondLifeUnInstMB ${LANG_TURKISH} "${APPNAME} zaten çalışırken kaldırılamaz.$\n$\nYaptığınız işi bitirdikten sonra ${APPNAME}'ı kapatmak ve devam etmek için Tamam seçimini yapın.$\nİptal etmek için İPTAL seçimini yapın." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_TURKISH} "Ağ bağlantısı kontrol ediliyor..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_TURKISH} "Belgeler ve Ayarlar klasöründeki önbellek dosyaları siliniyor" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_TURKISH} "${APPNAME} program dizininizde hala dosyalar var.$\n$\nBunlar muhtemelen sizin oluşturduğunuz veya şuraya taşıdığınız dosyalar:$\n$INSTDIR$\n$\nBunları kaldırmak istiyor musunuz?" + +; uninstall text +LangString UninstallTextMsg ${LANG_TURKISH} "Bu adımla ${APPNAME} ${VERSION_LONG} sisteminizden kaldırılacaktır." diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi index d17e860df9..10b9303c6a 100644 Binary files a/indra/newview/installers/windows/lang_zh.nsi and b/indra/newview/installers/windows/lang_zh.nsi differ diff --git a/indra/newview/installers/windows/uninstall_icon.BMP b/indra/newview/installers/windows/uninstall_icon.BMP index 562b56676a..e7291fcc35 100644 Binary files a/indra/newview/installers/windows/uninstall_icon.BMP and b/indra/newview/installers/windows/uninstall_icon.BMP differ diff --git a/indra/newview/installers/windows/uninstall_icon.ico b/indra/newview/installers/windows/uninstall_icon.ico index c4ec6c70bd..290b1dc2b8 100644 Binary files a/indra/newview/installers/windows/uninstall_icon.ico and b/indra/newview/installers/windows/uninstall_icon.ico differ diff --git a/indra/newview/installers/windows/uninstall_icon_singularity.BMP b/indra/newview/installers/windows/uninstall_icon_singularity.BMP deleted file mode 100644 index e7291fcc35..0000000000 Binary files a/indra/newview/installers/windows/uninstall_icon_singularity.BMP and /dev/null differ diff --git a/indra/newview/installers/windows/uninstall_icon_singularity.ico b/indra/newview/installers/windows/uninstall_icon_singularity.ico deleted file mode 100644 index 290b1dc2b8..0000000000 Binary files a/indra/newview/installers/windows/uninstall_icon_singularity.ico and /dev/null differ diff --git a/indra/newview/installers/windows/uninstall_icon_snowglobe.BMP b/indra/newview/installers/windows/uninstall_icon_snowglobe.BMP deleted file mode 100644 index e7291fcc35..0000000000 Binary files a/indra/newview/installers/windows/uninstall_icon_snowglobe.BMP and /dev/null differ diff --git a/indra/newview/installers/windows/uninstall_icon_snowglobe.ico b/indra/newview/installers/windows/uninstall_icon_snowglobe.ico deleted file mode 100644 index 290b1dc2b8..0000000000 Binary files a/indra/newview/installers/windows/uninstall_icon_snowglobe.ico and /dev/null differ diff --git a/indra/newview/installers/windows/uninstall_welcome.bmp b/indra/newview/installers/windows/uninstall_welcome.bmp new file mode 100644 index 0000000000..097d094292 Binary files /dev/null and b/indra/newview/installers/windows/uninstall_welcome.bmp differ diff --git a/indra/newview/jcfloaterareasearch.cpp b/indra/newview/jcfloaterareasearch.cpp index 9fb8a58dce..ae970ebc33 100644 --- a/indra/newview/jcfloaterareasearch.cpp +++ b/indra/newview/jcfloaterareasearch.cpp @@ -80,13 +80,21 @@ BOOL JCFloaterAreaSearch::postBuild() mResultList = getChild("result_list"); mResultList->setDoubleClickCallback(boost::bind(&JCFloaterAreaSearch::onDoubleClick,this)); mResultList->sortByColumn("Name", TRUE); + auto tp = getChild("TP"); + auto look = getChild("Look"); + mResultList->setCommitOnSelectionChange(true); + mResultList->setCommitCallback([=](LLUICtrl* ctrl, const LLSD& param){ + bool enabled = mResultList->getNumSelected() == 1; + tp->setEnabled(enabled); + look->setEnabled(enabled); + }); mCounterText = getChild("counter"); getChild("Refresh")->setClickedCallback(boost::bind(&JCFloaterAreaSearch::onRefresh,this)); getChild("Stop")->setClickedCallback(boost::bind(&JCFloaterAreaSearch::onStop,this)); - getChild("TP")->setClickedCallback(boost::bind(&JCFloaterAreaSearch::teleportToSelected, this)); - getChild("Look")->setClickedCallback(boost::bind(&JCFloaterAreaSearch::lookAtSelected, this)); + tp->setClickedCallback(boost::bind(&JCFloaterAreaSearch::teleportToSelected, this)); + look->setClickedCallback(boost::bind(&JCFloaterAreaSearch::lookAtSelected, this)); getChild("Name query chunk")->setCommitCallback(boost::bind(&JCFloaterAreaSearch::onCommitLine,this,_1,_2,LIST_OBJECT_NAME)); getChild("Description query chunk")->setCommitCallback(boost::bind(&JCFloaterAreaSearch::onCommitLine,this,_1,_2,LIST_OBJECT_DESC)); @@ -217,7 +225,7 @@ void JCFloaterAreaSearch::results() LLUUID object_id = objectp->getID(); if(!requestIfNeeded(object_id)) { - std::map::iterator it = mCachedObjects.find(object_id); + auto it = mCachedObjects.find(object_id); if(it != mCachedObjects.end()) { //LL_INFOS() << "all entries are \"\" or we have data" << LL_ENDL; @@ -281,7 +289,7 @@ void JCFloaterAreaSearch::processObjectPropertiesFamily(LLMessageSystem* msg, vo LLUUID object_id; msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, object_id); - std::set::iterator it = floater->mPendingObjects.find(object_id); + auto it = floater->mPendingObjects.find(object_id); if(it != floater->mPendingObjects.end()) floater->mPendingObjects.erase(it); //else if(floater->mCachedObjects.count(object_id)) //Let entries update. @@ -291,6 +299,7 @@ void JCFloaterAreaSearch::processObjectPropertiesFamily(LLMessageSystem* msg, vo // We cache unknown objects (to avoid having to request them later) // and requested objects. msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, data->owner_id); + if (auto obj = gObjectList.findObject(object_id)) obj->mOwnerID = data->owner_id; // Singu Note: Try to get Owner whenever possible msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID, data->group_id); msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, data->name); msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, data->desc); diff --git a/indra/newview/jcfloaterareasearch.h b/indra/newview/jcfloaterareasearch.h index 413dbab998..033dc22ad4 100644 --- a/indra/newview/jcfloaterareasearch.h +++ b/indra/newview/jcfloaterareasearch.h @@ -38,6 +38,7 @@ #include "lluuid.h" #include "llstring.h" #include "llframetimer.h" +#include class LLTextBox; class LLScrollListCtrl; @@ -55,6 +56,20 @@ class JCFloaterAreaSearch : public LLFloater, public LLFloaterSingletonsecond : nullptr; + } private: @@ -83,16 +98,8 @@ class JCFloaterAreaSearch : public LLFloater, public LLFloaterSingleton mPendingObjects; - std::map mCachedObjects; + uuid_set_t mPendingObjects; + boost::unordered_map mCachedObjects; std::string mFilterStrings[LIST_OBJECT_COUNT]; }; diff --git a/indra/newview/lffloaterinvpanel.cpp b/indra/newview/lffloaterinvpanel.cpp index 5fde1fa107..b687100a0e 100644 --- a/indra/newview/lffloaterinvpanel.cpp +++ b/indra/newview/lffloaterinvpanel.cpp @@ -22,35 +22,55 @@ #include "lffloaterinvpanel.h" +#include + #include "llinventorypanel.h" #include "lluictrlfactory.h" -LFFloaterInvPanel::LFFloaterInvPanel(const LLUUID& cat_id, LLInventoryModel* model, const std::string& name) -: LLInstanceTracker(cat_id) +LFFloaterInvPanel::LFFloaterInvPanel(const LLSD& cat, const std::string& name, LLInventoryModel* model) +: LLInstanceTracker(cat) { - mCommitCallbackRegistrar.add("InvPanel.Search", boost::bind(&LLInventoryPanel::setFilterSubString, boost::ref(mPanel), _2)); + // Setup the floater first + auto mPanel = new LLInventoryPanel("inv_panel", LLInventoryPanel::DEFAULT_SORT_ORDER, cat, LLRect(), model ? model : &gInventory, true); + + // Load from XUI + mCommitCallbackRegistrar.add("InvPanel.Search", boost::bind(&LLInventoryPanel::setFilterSubString, mPanel, _2)); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inv_panel.xml"); + + // Now set the title + const auto& title = name.empty() ? gInventory.getCategory(mPanel->getRootFolderID())->getName() : name; + setTitle(title); + + // Figure out a unique name for our rect control + const auto rect_control = llformat("FloaterInv%sRect", boost::algorithm::erase_all_copy(title, " ").data()); + if (!gSavedSettings.controlExists(rect_control)) // If we haven't existed before, create it + { + S32 left, top; + gFloaterView->getNewFloaterPosition(&left, &top); + LLRect rect = getRect(); + rect.translate(left - rect.mLeft, top - rect.mTop); + gSavedSettings.declareRect(rect_control, rect, "Rectangle for " + title + " window"); + } + setRectControl(rect_control); + applyRectControl(); // Set our initial rect to the stored (or just created) control + + // Now take care of the children LLPanel* panel = getChild("placeholder_panel"); - mPanel = new LLInventoryPanel("inv_panel", LLInventoryPanel::DEFAULT_SORT_ORDER, cat_id.asString(), panel->getRect(), model, true); + mPanel->setRect(panel->getRect()); + mPanel->setOrigin(0, 0); mPanel->postBuild(); mPanel->setFollows(FOLLOWS_ALL); mPanel->setEnabled(true); - addChild(mPanel); - removeChild(panel); - setTitle(name); -} - -LFFloaterInvPanel::~LFFloaterInvPanel() -{ - delete mPanel; + mPanel->removeBorder(); + panel->addChild(mPanel); } // static -void LFFloaterInvPanel::show(const LLUUID& cat_id, LLInventoryModel* model, const std::string& name) +void LFFloaterInvPanel::show(const LLSD& cat, const std::string& name, LLInventoryModel* model) { - LFFloaterInvPanel* floater = LFFloaterInvPanel::getInstance(cat_id); - if (!floater) floater = new LFFloaterInvPanel(cat_id, model, name); + LFFloaterInvPanel* floater = LFFloaterInvPanel::getInstance(cat); + if (!floater) floater = new LFFloaterInvPanel(cat, name, model); floater->open(); } @@ -63,22 +83,25 @@ void LFFloaterInvPanel::closeAll() { cache.push_back(&*i); } - // Now close all panels, without using instance_iter iterators. - for (std::vector::iterator i = cache.begin(); i != cache.end(); ++i) + // Now close all, without using instance_iter iterators. + for (auto& floater : cache) { - (*i)->close(); + floater->close(); } } -// virtual BOOL LFFloaterInvPanel::handleKeyHere(KEY key, MASK mask) { - if (!mPanel->hasFocus() && mask == MASK_NONE && (key == KEY_RETURN || key == KEY_DOWN)) + if (mask == MASK_NONE && (key == KEY_RETURN || key == KEY_DOWN)) { - mPanel->setFocus(true); - if (LLFolderView* root = mPanel->getRootFolder()) - root->scrollToShowSelection(); - return true; + auto& mPanel = *getChild("inv_panel"); + if (!mPanel.hasFocus()) + { + mPanel.setFocus(true); + if (LLFolderView* root = mPanel.getRootFolder()) + root->scrollToShowSelection(); + return true; + } } return LLFloater::handleKeyHere(key, mask); diff --git a/indra/newview/lffloaterinvpanel.h b/indra/newview/lffloaterinvpanel.h index 3c9104db16..c65763cdd2 100644 --- a/indra/newview/lffloaterinvpanel.h +++ b/indra/newview/lffloaterinvpanel.h @@ -18,26 +18,27 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ -#ifndef LFFLOATERINVPANEL_H -#define LFFLOATERINVPANEL_H +#pragma once #include "llfloater.h" #include "llinstancetracker.h" +#include "llsdutil.h" -class LFFloaterInvPanel : public LLFloater, public LLInstanceTracker +class LFFloaterInvPanel final : public LLFloater, public LLInstanceTracker { - LFFloaterInvPanel(const LLUUID& cat_id, class LLInventoryModel* model, const std::string& name); - ~LFFloaterInvPanel(); + LFFloaterInvPanel(const LLSD& cat, const std::string& name = LLStringUtil::null, class LLInventoryModel* model = nullptr); public: - static void show(const LLUUID& cat_id, LLInventoryModel* model, const std::string& name); // Show the floater for cat_id (create with other params if necessary) + static void show(const LLSD& cat, const std::string& name = LLStringUtil::null, LLInventoryModel* model = nullptr); // Show the floater for cat (create with other params if necessary) + static void toggle(const LLSD& cat) + { + if (auto instance = getInstance(cat)) + instance->close(); + else + show(cat); + } static void closeAll(); // Called when not allowed to have inventory open - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); - -private: - class LLInventoryPanel* mPanel; + BOOL handleKeyHere(KEY key, MASK mask) override; }; - -#endif //LFFLOATERINVPANEL_H diff --git a/indra/newview/lfsimfeaturehandler.cpp b/indra/newview/lfsimfeaturehandler.cpp index 65d1e6e559..e9fa957b0d 100644 --- a/indra/newview/lfsimfeaturehandler.cpp +++ b/indra/newview/lfsimfeaturehandler.cpp @@ -34,7 +34,7 @@ LFSimFeatureHandler::LFSimFeatureHandler() { if (!gHippoGridManager->getCurrentGrid()->isSecondLife()) // Remove this line if we ever handle SecondLife sim features gAgent.addRegionChangedCallback(boost::bind(&LFSimFeatureHandler::handleRegionChange, this)); - LLMuteList::instance().mGodLastNames.insert("Linden"); + LLMuteList::instance().mGodLastNames = { "Linden", "ProductEngine" }; } ExportPolicy LFSimFeatureHandler::exportPolicy() const @@ -92,6 +92,7 @@ void LFSimFeatureHandler::setSupportedFeatures() mGridName = gHippoGridManager->getConnectedGrid()->getGridName() != grid_name ? grid_name : LLStringUtil::null; } } + has_feature_or_default(mEventsURL, extras, "EventsURL"); has_feature_or_default(mSayRange, extras, "say-range"); has_feature_or_default(mShoutRange, extras, "shout-range"); has_feature_or_default(mWhisperRange, extras, "whisper-range"); @@ -105,6 +106,7 @@ void LFSimFeatureHandler::setSupportedFeatures() mMapServerURL = LLStringUtil::null; mSearchURL.reset(); mGridName.reset(); + mEventsURL.reset(); } mSayRange.reset(); mShoutRange.reset(); @@ -136,7 +138,7 @@ void LFSimFeatureHandler::setSupportedFeatures() } else { - mute_list.mGodLastNames.insert("Linden"); + mute_list.mGodLastNames = { "Linden", "ProductEngine" }; } } } diff --git a/indra/newview/lfsimfeaturehandler.h b/indra/newview/lfsimfeaturehandler.h index 893edb5a0f..9b7554e32f 100644 --- a/indra/newview/lfsimfeaturehandler.h +++ b/indra/newview/lfsimfeaturehandler.h @@ -65,6 +65,7 @@ class LFSimFeatureHandler : public LLSingleton boost::signals2::connection setSupportsExportCallback(const SignaledType::slot_t& slot) { return mSupportsExport.connect(slot); } boost::signals2::connection setDestinationGuideURLCallback(const SignaledType::slot_t& slot) { return mDestinationGuideURL.connect(slot); } boost::signals2::connection setSearchURLCallback(const SignaledType::slot_t& slot) { return mSearchURL.connect(slot); } + boost::signals2::connection setEventsURLCallback(const SignaledType::slot_t& slot) { return mEventsURL.connect(slot); } boost::signals2::connection setSayRangeCallback(const SignaledType::slot_t& slot) { return mSayRange.connect(slot); } boost::signals2::connection setShoutRangeCallback(const SignaledType::slot_t& slot) { return mShoutRange.connect(slot); } boost::signals2::connection setWhisperRangeCallback(const SignaledType::slot_t& slot) { return mWhisperRange.connect(slot); } @@ -74,6 +75,7 @@ class LFSimFeatureHandler : public LLSingleton std::string destinationGuideURL() const { return mDestinationGuideURL; } std::string mapServerURL() const { return mMapServerURL; } std::string searchURL() const { return mSearchURL; } + const std::string& getEventsURL() const { return mEventsURL.ref(); } const std::string& gridName() const { return mGridName.ref(); } U32 sayRange() const { return mSayRange; } U32 shoutRange() const { return mShoutRange; } @@ -87,6 +89,7 @@ class LFSimFeatureHandler : public LLSingleton std::string mMapServerURL; SignaledType mSearchURL; SignaledType mGridName; + SignaledType mEventsURL; SignaledType mSayRange; SignaledType mShoutRange; SignaledType mWhisperRange; diff --git a/indra/newview/lgghunspell_wrapper.cpp b/indra/newview/lgghunspell_wrapper.cpp index c28f83a0c6..d19e91485a 100644 --- a/indra/newview/lgghunspell_wrapper.cpp +++ b/indra/newview/lgghunspell_wrapper.cpp @@ -948,7 +948,7 @@ void lggHunSpell_Wrapper::editCustomButton() //glggHunSpell->addWordToCustomDictionary("temp"); } - gViewerWindow->getWindow()->ShellEx(dicdicpath); + LLWindow::ShellEx(dicdicpath); } void lggHunSpell_Wrapper::setSpellCheckHighlight(BOOL highlight) diff --git a/indra/newview/lgghunspell_wrapper.h b/indra/newview/lgghunspell_wrapper.h index 51c1f37a71..df55ece365 100644 --- a/indra/newview/lgghunspell_wrapper.h +++ b/indra/newview/lgghunspell_wrapper.h @@ -19,9 +19,14 @@ #define ASPELL_WRAPPER 1 #if LL_WINDOWS -#include "hunspell/hunspelldll.h" +#pragma push_macro("near") +#ifdef near +#undef near +#endif +#include +#pragma pop_macro("near") #else -#include "hunspell/hunspell.hxx" +#include #endif class lggHunSpell_Wrapper diff --git a/indra/newview/linux_tools/handle_secondlifeprotocol.sh.in b/indra/newview/linux_tools/handle_secondlifeprotocol.sh.in index 770f7ae37f..078cee2ed3 100755 --- a/indra/newview/linux_tools/handle_secondlifeprotocol.sh.in +++ b/indra/newview/linux_tools/handle_secondlifeprotocol.sh.in @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Send a URL of the form secondlife://... to Second Life. # diff --git a/indra/newview/linux_tools/install.sh.in b/indra/newview/linux_tools/install.sh.in index 2d42c13ddd..2136c38083 100755 --- a/indra/newview/linux_tools/install.sh.in +++ b/indra/newview/linux_tools/install.sh.in @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Install @VIEWER_CHANNEL@. This script can install the viewer both # system-wide and for an individual user. diff --git a/indra/newview/linux_tools/launch_url.sh b/indra/newview/linux_tools/launch_url.sh index c528ee762c..c1effc1883 100755 --- a/indra/newview/linux_tools/launch_url.sh +++ b/indra/newview/linux_tools/launch_url.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script loads a web page in the 'default' graphical web browser. # It MUST return immediately (or soon), so the browser should be diff --git a/indra/newview/linux_tools/refresh_desktop_app_entry.sh.in b/indra/newview/linux_tools/refresh_desktop_app_entry.sh.in index 66b8b90aa2..109dfe38ff 100755 --- a/indra/newview/linux_tools/refresh_desktop_app_entry.sh.in +++ b/indra/newview/linux_tools/refresh_desktop_app_entry.sh.in @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash SCRIPTSRC=`readlink -f "$0" || echo "$0"` RUN_PATH=`dirname "${SCRIPTSRC}" || echo .` @@ -15,7 +15,7 @@ function install_desktop_entry() Name=@VIEWER_BRANDING_ID@\n\ Comment=Client for Online Virtual Worlds, such as Second Life\n\ Exec=${installation_prefix}/@VIEWER_BRANDING_ID@\n\ -Icon=${installation_prefix}/@VIEWER_BRANDING_ID@_icon.png\n\ +Icon=${installation_prefix}/viewer_icon.png\n\ Terminal=false\n\ Type=Application\n\ Categories=Application;Network;\n\ diff --git a/indra/newview/linux_tools/register_secondlifeprotocol.sh b/indra/newview/linux_tools/register_secondlifeprotocol.sh index f4af742fa4..d7ce56c49b 100755 --- a/indra/newview/linux_tools/register_secondlifeprotocol.sh +++ b/indra/newview/linux_tools/register_secondlifeprotocol.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Register a protocol handler (default: handle_secondlifeprotocol.sh) for # URLs of the form secondlife://... @@ -7,10 +7,10 @@ HANDLER="$1" RUN_PATH=`dirname "$0" || echo .` -cd "${RUN_PATH}" +cd "${RUN_PATH}/.." if [ -z "$HANDLER" ]; then - HANDLER=`pwd`/handle_secondlifeprotocol.sh + HANDLER=`pwd`/etc/handle_secondlifeprotocol.sh fi # Register handler for GNOME-aware apps diff --git a/indra/newview/linux_tools/wrapper.sh.in b/indra/newview/linux_tools/wrapper.sh.in index 60c92485db..7ccee7eaba 100755 --- a/indra/newview/linux_tools/wrapper.sh.in +++ b/indra/newview/linux_tools/wrapper.sh.in @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash ## Here are some configuration options for Linux Client Testers. ## These options are for self-assisted troubleshooting during this beta @@ -55,9 +55,8 @@ ## - For advanced debugging cases, you can run the viewer under the ## control of another program, such as strace, gdb, or valgrind. If -## you're building your own viewer, bear in mind that the executable -## in the bin directory will be stripped: you should replace it with -## an unstripped binary before you run. +## you're building your own viewer, run the configure step with +## -DPACKAGE:BOOL=OFF to produce an unstripped binary for debugging. if [ -n "$ASCENDED_DEVELOPER" ]; then if [ "$ASCENDED_DEVELOPER" = "1" ]; then export LL_WRAPPER='gdb --args' @@ -142,7 +141,7 @@ if [ -n "$LL_TCMALLOC" ]; then fi fi -export VIEWER_BINARY='@VIEWER_BRANDING_ID@-do-not-run-directly' +export VIEWER_BINARY='do-not-directly-run-@VIEWER_BRANDING_ID@-bin' BINARY_TYPE=$(expr match "$(file -b bin/$VIEWER_BINARY)" '\(.*executable\)' | sed -e 's/ / /g') if [ "${BINARY_TYPE}" == "ELF 32-bit LSB executable" ]; then SL_ENV+='LD_LIBRARY_PATH="`pwd`/lib:$LD_LIBRARY_PATH"' @@ -151,15 +150,9 @@ else fi export SL_CMD='$LL_WRAPPER bin/$VIEWER_BINARY' -if [ -n "$AITESTPLUGIN" ]; then - SL_CMD="$LL_WRAPPER bin/SLPlugin" - SL_OPT="TESTPLUGIN" -else - SL_OPT="`cat gridargs.dat` $@" -fi # Run the program. -eval ${SL_ENV} ${SL_CMD} ${SL_OPT} || LL_RUN_ERR=runerr +eval ${SL_ENV} ${SL_CMD} || LL_RUN_ERR=runerr # Handle any resulting errors if [ "$LL_RUN_ERR" = "runerr" ]; then diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h index 731705288d..9b6b80e6c9 100644 --- a/indra/newview/llaccountingcostmanager.h +++ b/indra/newview/llaccountingcostmanager.h @@ -64,11 +64,11 @@ class LLAccountingCostManager : public LLSingleton private: //Set of objects that will be used to generate a cost - std::set mObjectList; + uuid_set_t mObjectList; //During fetchCosts we move object into a the pending set to signify that //a fetch has been instigated. - std::set mPendingObjectQuota; - typedef std::set::iterator IDIt; + uuid_set_t mPendingObjectQuota; + typedef uuid_set_t::iterator IDIt; }; //=============================================================================== diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 4f421318da..ac8b94b9f1 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -31,6 +31,7 @@ #include "pipeline.h" #include "llagentaccess.h" +#include "llagentbenefits.h" #include "llagentcamera.h" #include "llagentwearables.h" #include "llagentui.h" @@ -38,11 +39,14 @@ #include "llanimationstates.h" #include "llcallingcard.h" #include "llcapabilitylistener.h" +#include "llcororesponder.h" #include "llconsole.h" #include "llenvmanager.h" #include "llfirstuse.h" #include "llfloatercamera.h" #include "llfloatertools.h" +#include "llfloaterpostcard.h" +#include "llfloaterpreference.h" #include "llgroupactions.h" #include "llgroupmgr.h" #include "llhomelocationresponder.h" @@ -103,6 +107,7 @@ #include "lluictrlfactory.h" //For LLUICtrlFactory::getLayeredXMLNode +#include "aosystem.h" // for Typing override #include "hippolimits.h" // for getMaxAgentGroups // [RLVa:KB] - Checked: 2011-11-04 (RLVa-1.4.4a) #include "rlvactions.h" @@ -183,10 +188,10 @@ class LLTeleportRequestViaLandmark : public LLTeleportRequest LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId); virtual ~LLTeleportRequestViaLandmark(); - virtual bool canRestartTeleport(); + bool canRestartTeleport() override; - virtual void startTeleport(); - virtual void restartTeleport(); + void startTeleport() override; + void restartTeleport() override; protected: inline const LLUUID &getLandmarkId() const {return mLandmarkId;}; @@ -195,15 +200,15 @@ class LLTeleportRequestViaLandmark : public LLTeleportRequest LLUUID mLandmarkId; }; -class LLTeleportRequestViaLure : public LLTeleportRequestViaLandmark +class LLTeleportRequestViaLure final : public LLTeleportRequestViaLandmark { public: LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL pIsLureGodLike); virtual ~LLTeleportRequestViaLure(); - virtual bool canRestartTeleport(); + bool canRestartTeleport() override; - virtual void startTeleport(); + void startTeleport() override; protected: inline BOOL isLureGodLike() const {return mIsLureGodLike;}; @@ -218,10 +223,10 @@ class LLTeleportRequestViaLocation : public LLTeleportRequest LLTeleportRequestViaLocation(const LLVector3d &pPosGlobal); virtual ~LLTeleportRequestViaLocation(); - virtual bool canRestartTeleport(); + bool canRestartTeleport() override; - virtual void startTeleport(); - virtual void restartTeleport(); + void startTeleport() override; + void restartTeleport() override; protected: inline const LLVector3d &getPosGlobal() const {return mPosGlobal;}; @@ -231,16 +236,16 @@ class LLTeleportRequestViaLocation : public LLTeleportRequest }; -class LLTeleportRequestViaLocationLookAt : public LLTeleportRequestViaLocation +class LLTeleportRequestViaLocationLookAt final : public LLTeleportRequestViaLocation { public: LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal); virtual ~LLTeleportRequestViaLocationLookAt(); - virtual bool canRestartTeleport(); + bool canRestartTeleport() override; - virtual void startTeleport(); - virtual void restartTeleport(); + void startTeleport() override; + void restartTeleport() override; protected: @@ -257,12 +262,12 @@ const F32 LLAgent::TYPING_TIMEOUT_SECS = 5.f; std::map LLAgent::sTeleportErrorMessages; std::map LLAgent::sTeleportProgressMessages; -class LLAgentFriendObserver : public LLFriendObserver +class LLAgentFriendObserver final : public LLFriendObserver { public: - LLAgentFriendObserver() {} - virtual ~LLAgentFriendObserver() {} - virtual void changed(U32 mask); + LLAgentFriendObserver() = default; + virtual ~LLAgentFriendObserver() = default; + void changed(U32 mask) override; }; void LLAgentFriendObserver::changed(U32 mask) @@ -290,9 +295,24 @@ bool LLAgent::isActionAllowed(const LLSD& sdname) if (param == "speak") { - if ( gAgent.isVoiceConnected() && - LLViewerParcelMgr::getInstance()->allowAgentVoice() && - ! LLVoiceClient::getInstance()->inTuningMode() ) + bool allow_agent_voice = false; + LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel(); + if (channel != nullptr) + { + if (channel->getSessionName().empty() && channel->getSessionID().isNull()) + { + // default channel + allow_agent_voice = LLViewerParcelMgr::getInstance()->allowAgentVoice(); + } + else + { + allow_agent_voice = channel->isActive() && channel->callStarted(); + } + } + + if (gAgent.isVoiceConnected() && + allow_agent_voice && + !LLVoiceClient::getInstance()->inTuningMode()) { retval = true; } @@ -365,6 +385,7 @@ LLAgent::LLAgent() : mAgentAccess(new LLAgentAccess(gSavedSettings)), mGodLevelChangeSignal(), + mIsCrossingRegion(false), mCanEditParcel(false), mTeleportSourceSLURL(new LLSLURL), mTeleportRequest(), @@ -405,6 +426,7 @@ LLAgent::LLAgent() : mAutoPilot(FALSE), mAutoPilotFlyOnStop(FALSE), + mAutoPilotAllowFlying(TRUE), mAutoPilotTargetGlobal(), mAutoPilotStopDistance(1.f), mAutoPilotUseRotation(FALSE), @@ -415,6 +437,8 @@ LLAgent::LLAgent() : mAutoPilotFinishedCallback(NULL), mAutoPilotCallbackData(NULL), + mMovementKeysLocked(FALSE), + mEffectColor(new LLColor4(0.f, 1.f, 1.f, 1.f)), mHaveHomePosition(FALSE), @@ -425,12 +449,14 @@ LLAgent::LLAgent() : mCurrentFidget(0), mCrouch(false), mFirstLogin(FALSE), - mGenderChosen(FALSE), + mOutfitChosen(FALSE), + mAppearanceSerialNum(0), mMouselookModeInSignal(NULL), mMouselookModeOutSignal(NULL), - mPendingLure(NULL) + mPendingLure(NULL), + mFriendObserver(nullptr) { for (U32 i = 0; i < TOTAL_CONTROLS; i++) { @@ -886,7 +912,7 @@ void LLAgent::setRegion(LLViewerRegion *regionp) if (mRegionp) { // NaCl - Antispam Registry - NACLAntiSpamRegistry::purgeAllQueues(); + if (auto antispam = NACLAntiSpamRegistry::getIfExists()) antispam->resetQueues(); // NaCl End // We've changed regions, we're now going to change our agent coordinate frame. @@ -914,6 +940,16 @@ void LLAgent::setRegion(LLViewerRegion *regionp) { gSky.mVOGroundp->setRegion(regionp); } + + if (regionp->capabilitiesReceived()) + { + regionp->requestSimulatorFeatures(); + } + else + { + regionp->setCapabilitiesReceivedCallback(boost::bind(&LLViewerRegion::requestSimulatorFeatures, regionp)); + } + } else { @@ -994,6 +1030,15 @@ BOOL LLAgent::inPrelude() } +std::string LLAgent::getRegionCapability(const std::string &name) +{ + if (!mRegionp) + return std::string(); + + return mRegionp->getCapability(name); +} + + //----------------------------------------------------------------------------- // canManageEstate() //----------------------------------------------------------------------------- @@ -1489,7 +1534,7 @@ BOOL LLAgent::getAFK() const //----------------------------------------------------------------------------- void LLAgent::setDoNotDisturb(bool pIsDoNotDisturb) { - sendAnimationRequest(ANIM_AGENT_BUSY, pIsDoNotDisturb ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); + sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, pIsDoNotDisturb ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); mIsDoNotDisturb = pIsDoNotDisturb; if (gBusyMenu) { @@ -1517,17 +1562,25 @@ void LLAgent::startAutoPilotGlobal( void (*finish_callback)(BOOL, void *), void *callback_data, F32 stop_distance, - F32 rot_threshold) + F32 rot_threshold, + BOOL allow_flying) { if (!isAgentAvatarValid()) { return; } + // Are there any pending callbacks from previous auto pilot requests? + if (mAutoPilotFinishedCallback) + { + mAutoPilotFinishedCallback(dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData); + } + mAutoPilotFinishedCallback = finish_callback; mAutoPilotCallbackData = callback_data; mAutoPilotRotationThreshold = rot_threshold; mAutoPilotBehaviorName = behavior_name; + mAutoPilotAllowFlying = allow_flying; LLVector3d delta_pos( target_global ); delta_pos -= getPositionGlobal(); @@ -1555,14 +1608,25 @@ void LLAgent::startAutoPilotGlobal( } } - mAutoPilotFlyOnStop = getFlying(); + if (mAutoPilotAllowFlying) + { + mAutoPilotFlyOnStop = getFlying(); + } + else + { + mAutoPilotFlyOnStop = FALSE; + } + + bool follow = mAutoPilotBehaviorName == "Follow"; - if (distance > 30.0) + if (!follow && distance > 30.0 && mAutoPilotAllowFlying) { setFlying(TRUE); } - if ( distance > 1.f && heightDelta > (sqrtf(mAutoPilotStopDistance) + 1.f)) + if (!follow && distance > 1.f && + mAutoPilotAllowFlying && + heightDelta > (sqrtf(mAutoPilotStopDistance) + 1.f)) { setFlying(TRUE); // Do not force flying for "Sit" behavior to prevent flying after pressing "Stand" @@ -1619,10 +1683,8 @@ void LLAgent::setAutoPilotTargetGlobal(const LLVector3d &target_global) //----------------------------------------------------------------------------- // startFollowPilot() //----------------------------------------------------------------------------- -void LLAgent::startFollowPilot(const LLUUID &leader_id) +void LLAgent::startFollowPilot(const LLUUID &leader_id, BOOL allow_flying, F32 stop_distance) { - if (!mAutoPilot) return; - mLeaderID = leader_id; if ( mLeaderID.isNull() ) return; @@ -1633,7 +1695,14 @@ void LLAgent::startFollowPilot(const LLUUID &leader_id) return; } - startAutoPilotGlobal(object->getPositionGlobal()); + startAutoPilotGlobal(object->getPositionGlobal(), + "Follow", // behavior_name + NULL, // target_rotation + NULL, // finish_callback + NULL, // callback_data + stop_distance, + 0.03f, // rotation_threshold + allow_flying); } @@ -1644,6 +1713,9 @@ void LLAgent::stopAutoPilot(BOOL user_cancel) { if (mAutoPilot) { + if (!user_cancel && mAutoPilotBehaviorName == "Follow") + return; // Follow means actually follow + mAutoPilot = FALSE; if (mAutoPilotUseRotation && !user_cancel) { @@ -1662,7 +1734,16 @@ void LLAgent::stopAutoPilot(BOOL user_cancel) mAutoPilotFinishedCallback(!user_cancel && dist_vec_squared(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < (mAutoPilotStopDistance * mAutoPilotStopDistance), mAutoPilotCallbackData); mAutoPilotFinishedCallback = NULL; } + + // Sit response during follow pilot, now complete, resume follow + if (!user_cancel && mAutoPilotBehaviorName == "Sit" && mLeaderID.notNull()) + { + startFollowPilot(mLeaderID, true, gSavedSettings.getF32("SinguFollowDistance")); + return; + } + mLeaderID = LLUUID::null; + mAutoPilotNoProgressFrameCount = 0; setControlFlags(AGENT_CONTROL_STOP); @@ -1672,6 +1753,8 @@ void LLAgent::stopAutoPilot(BOOL user_cancel) LLNotificationsUtil::add("CancelledSit"); else if (mAutoPilotBehaviorName == "Attach") LLNotificationsUtil::add("CancelledAttach"); + else if (mAutoPilotBehaviorName == "Follow") + LLNotificationsUtil::add("CancelledFollow"); else LLNotificationsUtil::add("Cancelled"); } @@ -1679,28 +1762,105 @@ void LLAgent::stopAutoPilot(BOOL user_cancel) } +bool LLAgent::getAutoPilotNoProgress() const +{ + return mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped; +} + // Returns necessary agent pitch and yaw changes, radians. //----------------------------------------------------------------------------- // autoPilot() //----------------------------------------------------------------------------- void LLAgent::autoPilot(F32 *delta_yaw) { - if (mAutoPilot) + if (mAutoPilot && isAgentAvatarValid()) { - if (!mLeaderID.isNull()) + U8 follow = mAutoPilotBehaviorName == "Follow"; + if (follow) { - LLViewerObject* object = gObjectList.findObject(mLeaderID); - if (!object) + llassert(mLeaderID.notNull()); + const auto old_pos = mAutoPilotTargetGlobal; + if (auto object = gObjectList.findObject(mLeaderID)) { - stopAutoPilot(); - return; + mAutoPilotTargetGlobal = object->getPositionGlobal(); + if (const auto& av = object->asAvatar()) // Fly/sit if avatar target is flying + { + const auto& our_pos_global = getPositionGlobal(); + setFlying(av->mInAir && (getFlying() || mAutoPilotTargetGlobal[VZ] > our_pos_global[VZ])); // If they're in air, fly if they're higher or we were already (follow) flying + if (av->isSitting() && (!rlv_handler_t::isEnabled() || !gRlvHandler.hasBehaviour(RLV_BHVR_SIT))) + { + if (auto seat = av->getParent()) + { + if (gAgentAvatarp->getParent() == seat) + { + mAutoPilotNoProgressFrameCount = 0; // We may have incremented this before making it here, reset it + return; // We're seated with them, nothing more to do + } + else if (!getAutoPilotNoProgress()) + { + void handle_object_sit(LLViewerObject*, const LLVector3&); + handle_object_sit(static_cast(seat), LLVector3::zero); + follow = 2; // Indicate ground sitting is okay if we can't make it + } + else return; // If the server just wouldn't let us sit there, we won't be moving, exit here + } + else // Ground sit, but only if near enough + { + if (dist_vec(mAutoPilotTargetGlobal, our_pos_global) <= mAutoPilotStopDistance) // We're close enough, sit. + { + if (!gAgentAvatarp->isSittingAvatarOnGround()) + setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); + mAutoPilotNoProgressFrameCount = 0; // Ground Sit may have incremented this, reset it now + return; // We're already sitting on the ground, we have nothing to do + } + else // We're not close enough yet + { + if (/*!gAgentAvatarp->isSitting() && */ // RLV takes care of sitting check for us inside standUp + getAutoPilotNoProgress()) // Only stand up if we haven't exhausted our no progress frames + standUp(); // Unsit if need be, so we can move + follow = 2; // Indicate we want to groundsit + } + } + } + else + { + if (dist_vec(mAutoPilotTargetGlobal, our_pos_global) <= mAutoPilotStopDistance) + { + follow = 3; // We're close enough, indicate no walking + } + + if (gAgentAvatarp->isSitting()) // Leader isn't sitting, standUp if needed + { + standUp(); + mAutoPilotNoProgressFrameCount = 0; // Ground Sit may have incremented this, reset it + } + } + } } - mAutoPilotTargetGlobal = object->getPositionGlobal(); + else // We might still have a valid avatar pos + { + const LLVector3d& get_av_pos(const LLUUID & id); + auto pos = get_av_pos(mLeaderID); + if (pos.isExactlyZero()) // Default constructed or invalid from server + { + // Wait for them for more follow pilot + return; + } + standUp(); // Leader not rendered, we mustn't be sitting + mAutoPilotNoProgressFrameCount = 0; // Ground Sit may have incremented this, reset it + mAutoPilotTargetGlobal = pos; + setFlying(true); // Should we fly here? Altitude is often invalid... + + if (dist_vec(mAutoPilotTargetGlobal, getPositionGlobal()) <= mAutoPilotStopDistance) + { + follow = 3; // We're close enough, indicate no walking + } + } + if (old_pos != mAutoPilotTargetGlobal) // Reset if position changes + mAutoPilotNoProgressFrameCount = 0; } - - if (!isAgentAvatarValid()) return; - if (gAgentAvatarp->mInAir) + if (follow % 2 == 0 && gAgentAvatarp->mInAir && mAutoPilotAllowFlying) { setFlying(TRUE); } @@ -1712,12 +1872,15 @@ void LLAgent::autoPilot(F32 *delta_yaw) F32 target_dist = direction.magVec(); - if (target_dist >= mAutoPilotTargetDist) + if (follow % 2 == 0 && target_dist >= mAutoPilotTargetDist) { mAutoPilotNoProgressFrameCount++; - if (mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped) + if (getAutoPilotNoProgress()) { - stopAutoPilot(); + if (follow) // Well, we tried to reach them, let's just ground sit for now. + setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); + else + stopAutoPilot(); return; } } @@ -1759,8 +1922,9 @@ void LLAgent::autoPilot(F32 *delta_yaw) } *delta_yaw = yaw; + if (follow == 3) return; // We're close enough, all we need to do is turn - // Compute when to start slowing down and when to stop + // Compute when to start slowing down F32 slow_distance; if (getFlying()) { @@ -1920,7 +2084,7 @@ BOOL LLAgent::needsRenderAvatar() return FALSE; } - return mShowAvatar && mGenderChosen; + return mShowAvatar && mOutfitChosen; } // TRUE if we need to render your own avatar's head. @@ -1953,10 +2117,7 @@ void LLAgent::startTyping() } } - if (gSavedSettings.getBOOL("PlayTypingAnim")) - { - sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START); - } + AOSystem::typing(true); // Singu Note: Typing anims handled by AO/settings. gChatBar-> sendChatFromViewer("", CHAT_TYPE_START, FALSE); } @@ -1969,7 +2130,7 @@ void LLAgent::stopTyping() if (mRenderState & AGENT_STATE_TYPING) { clearRenderState(AGENT_STATE_TYPING); - sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); + AOSystem::typing(false); // Singu Note: Typing anims handled by AO/settings. gChatBar-> sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); } @@ -2433,15 +2594,11 @@ void LLAgent::onAnimStop(const LLUUID& id) } else if (id == ANIM_AGENT_AWAY) { -// clearAFK(); // [RLVa:KB] - Checked: 2010-05-03 (RLVa-1.2.0g) | Added: RLVa-1.1.0g -#ifdef RLV_EXTENSION_CMD_ALLOWIDLE if (!gRlvHandler.hasBehaviour(RLV_BHVR_ALLOWIDLE)) clearAFK(); -#else - clearAFK(); -#endif // RLV_EXTENSION_CMD_ALLOWIDLE // [/RLVa:KB] +// clearAFK(); } else if (id == ANIM_AGENT_STANDUP) { @@ -2512,7 +2669,7 @@ bool LLAgent::canAccessMaturityInRegion( U64 region_handle ) const return true; } -bool LLAgent::canAccessMaturityAtGlobal( LLVector3d pos_global ) const +bool LLAgent::canAccessMaturityAtGlobal(const LLVector3d& pos_global ) const { U64 region_handle = to_region_handle_global( pos_global.mdV[0], pos_global.mdV[1] ); return canAccessMaturityInRegion( region_handle ); @@ -2559,7 +2716,7 @@ int LLAgent::convertTextToMaturity(char text) return LLAgentAccess::convertTextToMaturity(text); } -class LLMaturityPreferencesResponder : public LLHTTPClient::ResponderWithResult +class LLMaturityPreferencesResponder final : public LLHTTPClient::ResponderWithResult { LOG_CLASS(LLMaturityPreferencesResponder); public: @@ -2567,12 +2724,10 @@ class LLMaturityPreferencesResponder : public LLHTTPClient::ResponderWithResult virtual ~LLMaturityPreferencesResponder(); protected: - virtual void httpSuccess(); - virtual void httpFailure(); - - /*virtual*/ char const* getName(void) const { return "LLMaturityPreferencesResponder"; } -protected: + void httpSuccess() override; + void httpFailure() override; + char const* getName() const override { return "LLMaturityPreferencesResponder"; } private: U8 parseMaturityFromServerResponse(const LLSD &pContent) const; @@ -2773,7 +2928,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) boost::intrusive_ptr responderPtr = boost::intrusive_ptr(new LLMaturityPreferencesResponder(this, pPreferredMaturity, mLastKnownResponseMaturity)); // If we don't have a region, report it as an error - if (getRegion() == NULL) + if (getRegion() == nullptr) { responderPtr->failureResult(0U, "region is not defined", LLSD()); } @@ -2830,11 +2985,6 @@ LLAgent::god_level_change_slot_t LLAgent::registerGodLevelChanageListener(god_le return mGodLevelChangeSignal.connect(pGodLevelChangeCallback); } -void LLAgent::setAOTransition() -{ - mAgentAccess->setTransition(); -} - const LLAgentAccess& LLAgent::getAgentAccess() { return *mAgentAccess; @@ -2852,11 +3002,7 @@ void LLAgent::handleMaturity(const LLSD &pNewValue) //---------------------------------------------------------------------------- -void LLAgent::buildFullname(std::string& name) const -{ - if (isAgentAvatarValid()) name = gAgentAvatarp->getFullname(); -} - +//*TODO remove, is not used anywhere as of August 20, 2009 void LLAgent::buildFullnameAndTitle(std::string& name) const { if (isGroupMember()) @@ -3015,7 +3161,7 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO BOOL LLAgent::canJoinGroups() const { - return (S32)mGroups.size() < gHippoLimits->getMaxAgentGroups(); + return (S32)mGroups.size() < LLAgentBenefitsMgr::current().getGroupMembershipLimit(); } LLQuaternion LLAgent::getHeadRotation() @@ -3044,7 +3190,7 @@ LLQuaternion LLAgent::getHeadRotation() return rot; } -void LLAgent::sendAnimationRequests(const std::vector &anim_ids, EAnimRequest request) +void LLAgent::sendAnimationRequests(const uuid_vec_t &anim_ids, EAnimRequest request) { if (gAgentID.isNull()) { @@ -3059,24 +3205,27 @@ void LLAgent::sendAnimationRequests(const std::vector &anim_ids, EAnimRe msg->addUUIDFast(_PREHASH_AgentID, getID()); msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - for (U32 i = 0; i < anim_ids.size(); i++) + for (auto anim_id : anim_ids) { - if (anim_ids[i].isNull()) + if (anim_id.isNull()) { continue; } msg->nextBlockFast(_PREHASH_AnimationList); - msg->addUUIDFast(_PREHASH_AnimID, (anim_ids[i]) ); + msg->addUUIDFast(_PREHASH_AnimID, anim_id); msg->addBOOLFast(_PREHASH_StartAnim, (request == ANIM_REQUEST_START) ? TRUE : FALSE); num_valid_anims++; } - - msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList); - msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0); - if (num_valid_anims) + if (!num_valid_anims) { - sendReliableMessage(); + msg->clearMessage(); + return; } + + msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList); + msg->addBinaryDataFast(_PREHASH_TypeData, nullptr, 0); + + sendReliableMessage(); } void LLAgent::sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request) @@ -3097,7 +3246,7 @@ void LLAgent::sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request) msg->addBOOLFast(_PREHASH_StartAnim, (request == ANIM_REQUEST_START) ? TRUE : FALSE); msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList); - msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0); + msg->addBinaryDataFast(_PREHASH_TypeData, nullptr, 0); sendReliableMessage(); } @@ -3121,7 +3270,7 @@ void LLAgent::sendAnimationStateReset() msg->addBOOLFast(_PREHASH_StartAnim, FALSE); msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList); - msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0); + msg->addBinaryDataFast(_PREHASH_TypeData, nullptr, 0); sendReliableMessage(); } @@ -3260,29 +3409,6 @@ BOOL LLAgent::allowOperation(PermissionBit op, return perm.allowOperationBy(op, agent_proxy, group_proxy); } -void LLAgent::getName(std::string& name) -{ - name.clear(); - - if (gAgentAvatarp) - { - LLNameValue *first_nv = gAgentAvatarp->getNVPair("FirstName"); - LLNameValue *last_nv = gAgentAvatarp->getNVPair("LastName"); - if (first_nv && last_nv) - { - name = first_nv->printData() + " " + last_nv->printData(); - } - else - { - LL_WARNS() << "Agent is missing FirstName and/or LastName nv pair." << LL_ENDL; - } - } - else - { - name = gSavedSettings.getString("FirstName") + " " + gSavedSettings.getString("LastName"); - } -} - const LLColor4 LLAgent::getEffectColor() { LLColor4 effect_color = *mEffectColor; @@ -3317,6 +3443,13 @@ BOOL LLAgent::leftButtonGrabbed() const || (camera_mouse_look && mControlsTakenPassedOnCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0); } +BOOL LLAgent::leftButtonBlocked() const +{ + const BOOL camera_mouse_look = gAgentCamera.cameraMouselook(); + return (!camera_mouse_look && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0) + || (camera_mouse_look && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0); +} + BOOL LLAgent::rotateGrabbed() const { return (mControlsTakenCount[CONTROL_YAW_POS_INDEX] > 0) @@ -3376,8 +3509,8 @@ void LLAgent::processAgentDropGroup(LLMessageSystem *msg, void **) // Remove the group if it already exists remove it and add the new data to pick up changes. LLGroupData gd; gd.mID = group_id; - std::vector::iterator found_it = std::find(gAgent.mGroups.begin(), gAgent.mGroups.end(), gd); - if (found_it != gAgent.mGroups.end()) + auto found_it = std::find(gAgent.mGroups.cbegin(), gAgent.mGroups.cend(), gd); + if (found_it != gAgent.mGroups.cend()) { gAgent.mGroups.erase(found_it); if (gAgent.getGroupID() == group_id) @@ -3403,12 +3536,12 @@ void LLAgent::processAgentDropGroup(LLMessageSystem *msg, void **) } } -class LLAgentDropGroupViewerNode : public LLHTTPNode +class LLAgentDropGroupViewerNode final : public LLHTTPNode { - virtual void post( + void post( LLHTTPNode::ResponsePtr response, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { if ( @@ -3435,11 +3568,8 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode //there is only one set of data in the AgentData block LLSD agent_data = body["AgentData"][0]; - LLUUID agent_id; - LLUUID group_id; - - agent_id = agent_data["AgentID"].asUUID(); - group_id = agent_data["GroupID"].asUUID(); + LLUUID agent_id = agent_data["AgentID"].asUUID(); + LLUUID group_id = agent_data["GroupID"].asUUID(); if (agent_id != gAgentID) { @@ -3454,8 +3584,8 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode // and add the new data to pick up changes. LLGroupData gd; gd.mID = group_id; - std::vector::iterator found_it = std::find(gAgent.mGroups.begin(), gAgent.mGroups.end(), gd); - if (found_it != gAgent.mGroups.end()) + auto found_it = std::find(gAgent.mGroups.cbegin(), gAgent.mGroups.cend(), gd); + if (found_it != gAgent.mGroups.cend()) { gAgent.mGroups.erase(found_it); if (gAgent.getGroupID() == group_id) @@ -3526,8 +3656,8 @@ void LLAgent::processAgentGroupDataUpdate(LLMessageSystem *msg, void **) { need_floater_update = true; // Remove the group if it already exists remove it and add the new data to pick up changes. - std::vector::iterator found_it = std::find(gAgent.mGroups.begin(), gAgent.mGroups.end(), group); - if (found_it != gAgent.mGroups.end()) + auto found_it = std::find(gAgent.mGroups.cbegin(), gAgent.mGroups.cend(), group); + if (found_it != gAgent.mGroups.cend()) { gAgent.mGroups.erase(found_it); } @@ -3541,12 +3671,12 @@ void LLAgent::processAgentGroupDataUpdate(LLMessageSystem *msg, void **) } -class LLAgentGroupDataUpdateViewerNode : public LLHTTPNode +class LLAgentGroupDataUpdateViewerNode final : public LLHTTPNode { - virtual void post( + void post( LLHTTPNode::ResponsePtr response, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { LLSD body = input["body"]; if(body.has("body")) @@ -3586,8 +3716,8 @@ class LLAgentGroupDataUpdateViewerNode : public LLHTTPNode { need_floater_update = true; // Remove the group if it already exists remove it and add the new data to pick up changes. - std::vector::iterator found_it = std::find(gAgent.mGroups.begin(), gAgent.mGroups.end(), group); - if (found_it != gAgent.mGroups.end()) + auto found_it = std::find(gAgent.mGroups.cbegin(), gAgent.mGroups.cend(), group); + if (found_it != gAgent.mGroups.cend()) { gAgent.mGroups.erase(found_it); } @@ -3788,7 +3918,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * return; } - if (gAgentAvatarp->isEditingAppearance()) + if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance()) { // ignore baked textures when in customize mode return; @@ -3862,6 +3992,13 @@ BOOL LLAgent::anyControlGrabbed() const } BOOL LLAgent::isControlGrabbed(S32 control_index) const +{ + if (gAgent.mControlsTakenCount[control_index] > 0) + return TRUE; + return gAgent.mControlsTakenPassedOnCount[control_index] > 0; +} + +BOOL LLAgent::isControlBlocked(S32 control_index) const { return mControlsTakenCount[control_index] > 0; } @@ -3912,6 +4049,7 @@ void LLAgent::clearVisualParams(void *data) // protected bool LLAgent::teleportCore(bool is_local) { + LL_INFOS("Teleport") << "In teleport core!" << LL_ENDL; if ((TELEPORT_NONE != mTeleportState) && (mTeleportState != TELEPORT_PENDING)) { LL_WARNS() << "Attempt to teleport when already teleporting." << LL_ENDL; @@ -3929,7 +4067,7 @@ bool LLAgent::teleportCore(bool is_local) // Stop all animation before actual teleporting if (isAgentAvatarValid()) { - for ( LLVOAvatar::AnimIterator anim_it= gAgentAvatarp->mPlayingAnimations.begin(); + for ( auto anim_it= gAgentAvatarp->mPlayingAnimations.begin(); anim_it != gAgentAvatarp->mPlayingAnimations.end(); ++anim_it) { @@ -3948,8 +4086,7 @@ bool LLAgent::teleportCore(bool is_local) LLFloaterWorldMap::hide(); // hide land floater too - it'll be out of date - if (LLFloaterLand::findInstance()) - LLFloaterLand::hideInstance(); + if (LLFloaterLand::findInstance()) LLFloaterLand::hideInstance(); LLViewerParcelMgr::getInstance()->deselectLand(); LLViewerMediaFocus::getInstance()->clearFocus(); @@ -3972,12 +4109,16 @@ bool LLAgent::teleportCore(bool is_local) gTeleportDisplay = TRUE; gAgent.setTeleportState( LLAgent::TELEPORT_START ); - /*static const LLCachedControl hide_tp_screen("AscentDisableTeleportScreens",false); - if(!hide_tp_screen) + static const LLCachedControl hide_tp_screen("AscentDisableTeleportScreens",false); + static const LLCachedControl skip_reset_objects_on_teleport("SHSkipResetVBOsOnTeleport", false); + if(!hide_tp_screen && !skip_reset_objects_on_teleport) { + // AscentDisableTeleportScreens TRUE might be broken..*/ + //release geometry from old location gPipeline.resetVertexBuffers(); - }*/ + LLSpatialPartition::sTeleportRequested = TRUE; + } if (gSavedSettings.getBOOL("SpeedRez")) { @@ -4076,6 +4217,12 @@ void LLAgent::handleTeleportFinished() LLNotificationsUtil::add("PreferredMaturityChanged", args); mIsMaturityRatingChangingDuringTeleport = false; } + + // Init SLM Marketplace connection so we know which UI should be used for the user as a merchant + // Note: Eventually, all merchant will be migrated to the new SLM system and there will be no reason to show the old UI at all. + // Note: Some regions will not support the SLM cap for a while so we need to do that check for each teleport. + // *TODO : Suppress that line from here once the whole grid migrated to SLM and move it to idle_startup() (llstartup.cpp) + check_merchant_status(); } void LLAgent::handleTeleportFailed() @@ -4214,11 +4361,24 @@ void LLAgent::teleportCancel() msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); sendReliableMessage(); } + mTeleportCanceled = mTeleportRequest; } clearTeleportRequest(); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + gPipeline.resetVertexBuffers(); } +void LLAgent::restoreCanceledTeleportRequest() +{ + if (mTeleportCanceled != NULL) + { + gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); + mTeleportRequest = mTeleportCanceled; + mTeleportCanceled.reset(); + gTeleportDisplay = TRUE; + gTeleportDisplayTimer.reset(); + } +} void LLAgent::teleportViaLocation(const LLVector3d& pos_global) { @@ -4323,7 +4483,11 @@ void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global) void LLAgent::doTeleportViaLocationLookAt(const LLVector3d& pos_global) { mbTeleportKeepsLookAt = true; - gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction + + if(!gAgentCamera.isfollowCamLocked()) + { + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction + } U64 region_handle = to_region_handle(pos_global); // Aurora-sim var region teleports LLSimInfo* simInfo = LLWorldMap::instance().simInfoFromHandle(region_handle); @@ -4336,8 +4500,22 @@ void LLAgent::doTeleportViaLocationLookAt(const LLVector3d& pos_global) teleportRequest(region_handle, pos_local, getTeleportKeepsLookAt()); } +LLAgent::ETeleportState LLAgent::getTeleportState() const +{ + return (mTeleportRequest && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed)) ? + TELEPORT_NONE : mTeleportState; +} + + void LLAgent::setTeleportState(ETeleportState state) { + if (mTeleportRequest && (state != TELEPORT_NONE) && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed)) + { // A late message has come in regarding a failed teleport. + // We have already decided that it failed so should not reinitiate the teleport sequence in the viewer. + LL_WARNS("Teleport") << "Attempt to set teleport state to " << state << + " for previously failed teleport. Ignore!" << LL_ENDL; + return; + } mTeleportState = state; static const LLCachedControl freeze_time("FreezeTime",false); if (mTeleportState > TELEPORT_NONE && freeze_time) @@ -4349,6 +4527,7 @@ void LLAgent::setTeleportState(ETeleportState state) { case TELEPORT_NONE: mbTeleportKeepsLookAt = false; + mIsCrossingRegion = false; // Attachments getting lost on TP; finished TP break; case TELEPORT_MOVING: @@ -4375,7 +4554,7 @@ void LLAgent::stopCurrentAnimations() // avatar, propagating this change back to the server. if (isAgentAvatarValid()) { - std::vector anim_ids; + uuid_vec_t anim_ids; for ( LLVOAvatar::AnimIterator anim_it = gAgentAvatarp->mPlayingAnimations.begin(); @@ -4417,8 +4596,7 @@ void LLAgent::stopCurrentAnimations() // re-assert at least the default standing animation, because // viewers get confused by avs with no associated anims. - sendAnimationRequest(ANIM_AGENT_STAND, - ANIM_REQUEST_START); + sendAnimationRequest(ANIM_AGENT_STAND, ANIM_REQUEST_START); } } @@ -4475,12 +4653,12 @@ void LLAgent::fidget() void LLAgent::stopFidget() { - std::vector anims; - anims.reserve(4); - anims.push_back(ANIM_AGENT_STAND_1); - anims.push_back(ANIM_AGENT_STAND_2); - anims.push_back(ANIM_AGENT_STAND_3); - anims.push_back(ANIM_AGENT_STAND_4); + const uuid_vec_t anims { + ANIM_AGENT_STAND_1, + ANIM_AGENT_STAND_2, + ANIM_AGENT_STAND_3, + ANIM_AGENT_STAND_4, + }; gAgent.sendAnimationRequests(anims, ANIM_REQUEST_STOP); } @@ -4516,7 +4694,7 @@ void LLAgent::requestLeaveGodMode() sendReliableMessage(); } -extern void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value); +extern void dump_visual_param(apr_file_t* file, LLVisualParam const* viewer_param, F32 value); extern std::string get_sequential_numbered_file_name(const std::string& prefix, const std::string& suffix); @@ -4542,7 +4720,7 @@ void LLAgent::dumpSentAppearance(const std::string& dump_prefix) if (appearance_version_param) { F32 value = appearance_version_param->getWeight(); - dump_visual_param(outfile, appearance_version_param, value); + dump_visual_param(file, appearance_version_param, value); } for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); @@ -4682,24 +4860,18 @@ void LLAgent::sendAgentSetAppearance() // This means the baked texture IDs on the server will be untouched. // Once all textures are baked, another AvatarAppearance message will be sent to update the TEs msg->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addBinaryDataFast(_PREHASH_TextureEntry, NULL, 0); + gMessageSystem->addBinaryDataFast(_PREHASH_TextureEntry, nullptr, 0); } - static bool send_physics_params = false; - send_physics_params |= !!gAgentWearables.selfHasWearable(LLWearableType::WT_PHYSICS); S32 transmitted_params = 0; for (LLViewerVisualParam* param = (LLViewerVisualParam*)gAgentAvatarp->getFirstVisualParam(); param; param = (LLViewerVisualParam*)gAgentAvatarp->getNextVisualParam()) { - if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) // do not transmit params of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT + if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE || + param->getGroup() == VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE) // do not transmit params of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT { - //A hack to prevent ruthing on older viewers when phys wearables aren't being worn. - if(!send_physics_params && param->getID() >= 10000) - { - break; - } msg->nextBlockFast(_PREHASH_VisualParam ); // We don't send the param ids. Instead, we assume that the receiver has the same params in the same sequence. @@ -4711,9 +4883,7 @@ void LLAgent::sendAgentSetAppearance() } LL_INFOS() << "Avatar XML num VisualParams transmitted = " << transmitted_params << LL_ENDL; - if(transmitted_params < 218) { - LLNotificationsUtil::add("SGIncompleteAppearance"); - } + if (transmitted_params < 218) LLNotificationsUtil::add("SGIncompleteAppearance"); sendReliableMessage(); } @@ -4728,8 +4898,96 @@ void LLAgent::sendAgentDataUpdateRequest() void LLAgent::sendAgentUserInfoRequest() { - if(getID().isNull()) + std::string cap; + + if (getID().isNull()) return; // not logged in + + if (mRegionp) + cap = mRegionp->getCapability("UserInfo"); + + if (!cap.empty()) + { + LLHTTPClient::get(cap, new LLCoroResponder( + boost::bind(&LLAgent::requestAgentUserInfoCoro, this, _1))); + } + else + { + sendAgentUserInfoRequestMessage(); + } +} + +void LLAgent::requestAgentUserInfoCoro(const LLCoroResponder& responder) +{ + const auto& result = responder.getContent(); + const auto& status = responder.getStatus(); + + if (!responder.isGoodStatus(status)) + { + LL_WARNS("UserInfo") << "Failed to get user information: " << result["message"] << "Status " << status << " Reason: " << responder.getReason() << LL_ENDL; + return; + } + + bool im_via_email; + bool is_verified_email; + std::string email; + std::string dir_visibility; + + im_via_email = result["im_via_email"].asBoolean(); + is_verified_email = result["is_verified"].asBoolean(); + email = result["email"].asString(); + dir_visibility = result["directory_visibility"].asString(); + + // TODO: This should probably be changed. I'm not entirely comfortable + // having LLAgent interact directly with the UI in this way. + LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, email, is_verified_email); + LLFloaterPostcard::updateUserInfo(email); +} + +void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& directory_visibility) +{ + std::string cap; + + if (getID().isNull()) + return; // not logged in + + if (mRegionp) + cap = mRegionp->getCapability("UserInfo"); + + if (!cap.empty()) + { + LLSD body(LLSDMap + ("dir_visibility", LLSD::String(directory_visibility)) + ("im_via_email", LLSD::Boolean(im_via_email))); + LLHTTPClient::post(cap, body, new LLCoroResponder( + boost::bind(&LLAgent::updateAgentUserInfoCoro, this, _1))); + } + else + { + sendAgentUpdateUserInfoMessage(im_via_email, directory_visibility); + } +} + + +void LLAgent::updateAgentUserInfoCoro(const LLCoroResponder& responder) +{ + const auto& result = responder.getContent(); + const auto& status = responder.getStatus(); + + if (!responder.isGoodStatus(status)) + { + LL_WARNS("UserInfo") << "Failed to set user information." << LL_ENDL; + } + else if (!result["success"].asBoolean()) + { + LL_WARNS("UserInfo") << "Failed to set user information: " << result["message"] << LL_ENDL; + } +} + +// deprecated: +// May be removed when UserInfo cap propagates to all simhosts in grid +void LLAgent::sendAgentUserInfoRequestMessage() +{ gMessageSystem->newMessageFast(_PREHASH_UserInfoRequest); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID()); @@ -4737,6 +4995,21 @@ void LLAgent::sendAgentUserInfoRequest() sendReliableMessage(); } +void LLAgent::sendAgentUpdateUserInfoMessage(bool im_via_email, const std::string& directory_visibility) +{ + gMessageSystem->newMessageFast(_PREHASH_UpdateUserInfo); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_UserData); + gMessageSystem->addBOOLFast(_PREHASH_IMViaEMail, im_via_email); + gMessageSystem->addString("DirectoryVisibility", directory_visibility); + gAgent.sendReliableMessage(); + +} +// end deprecated +//------ + void LLAgent::observeFriends() { if(!mFriendObserver) @@ -4804,18 +5077,6 @@ const void LLAgent::getTeleportSourceSLURL(LLSLURL& slurl) const slurl = *mTeleportSourceSLURL; } -void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& directory_visibility ) -{ - gMessageSystem->newMessageFast(_PREHASH_UpdateUserInfo); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_UserData); - gMessageSystem->addBOOLFast(_PREHASH_IMViaEMail, im_via_email); - gMessageSystem->addString("DirectoryVisibility", directory_visibility); - gAgent.sendReliableMessage(); -} - void LLAgent::dumpGroupInfo() { LL_INFOS() << "group " << mGroupName << LL_ENDL; @@ -4898,6 +5159,7 @@ void LLAgent::onFoundLureDestination(LLSimInfo *siminfo) msg.append(llformat(" (%s)", maturity.c_str())); } LLChat chat(msg); + chat.mSourceType = CHAT_SOURCE_SYSTEM; LLFloaterChat::addChat(chat); } else diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 261e70acca..6fd97b679c 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -33,8 +33,6 @@ #ifndef LL_LLAGENT_H #define LL_LLAGENT_H -#include - #include "indra_constants.h" #include "llevent.h" // LLObservable base class #include "llagentconstants.h" @@ -46,10 +44,6 @@ #include "llinventorymodel.h" #include "v3dmath.h" -#ifndef BOOST_FUNCTION_HPP_INCLUDED -#include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif #include #include @@ -73,6 +67,7 @@ class LLAgentAccess; class LLSLURL; class LLSimInfo; class LLTeleportRequest; +struct LLCoroResponder; typedef boost::shared_ptr LLTeleportRequestPtr; @@ -103,7 +98,7 @@ struct LLGroupData //------------------------------------------------------------------------ // LLAgent //------------------------------------------------------------------------ -class LLAgent : public LLOldEvents::LLObservable +class LLAgent final : public LLOldEvents::LLObservable { LOG_CLASS(LLAgent); @@ -124,6 +119,8 @@ class LLAgent : public LLOldEvents::LLObservable void init(); void cleanup(); +private: + //-------------------------------------------------------------------- // Login //-------------------------------------------------------------------- @@ -165,8 +162,6 @@ class LLAgent : public LLOldEvents::LLObservable // Name //-------------------------------------------------------------------- public: - void getName(std::string& name); //Legacy - void buildFullname(std::string &name) const; //Legacy //*TODO remove, is not used as of August 20, 2009 void buildFullnameAndTitle(std::string &name) const; @@ -174,12 +169,13 @@ class LLAgent : public LLOldEvents::LLObservable // Gender //-------------------------------------------------------------------- public: - // On the very first login, gender isn't chosen until the user clicks - // in a dialog. We don't render the avatar until they choose. - BOOL isGenderChosen() const { return mGenderChosen; } - void setGenderChosen(BOOL b) { mGenderChosen = b; } + // On the very first login, outfit needs to be chosen by some + // mechanism, usually by loading the requested initial outfit. We + // don't render the avatar until the choice is made. + BOOL isOutfitChosen() const { return mOutfitChosen; } + void setOutfitChosen(BOOL b) { mOutfitChosen = b; } private: - BOOL mGenderChosen; + BOOL mOutfitChosen; /** Identity ** ** @@ -250,7 +246,7 @@ class LLAgent : public LLOldEvents::LLObservable void changeParcels(); // called by LLViewerParcelMgr when we cross a parcel boundary // Register a boost callback to be called when the agent changes parcels - typedef boost::function parcel_changed_callback_t; + typedef std::function parcel_changed_callback_t; boost::signals2::connection addParcelChangedCallback(parcel_changed_callback_t); private: @@ -266,6 +262,9 @@ class LLAgent : public LLOldEvents::LLObservable const LLHost& getRegionHost() const; BOOL inPrelude(); + // Capability + std::string getRegionCapability(const std::string &name); // short hand for if (getRegion()) { getRegion()->getCapability(name) } + /** * Register a boost callback to be called when the agent changes regions * Note that if you need to access a capability for the region, you may need to wait @@ -485,6 +484,7 @@ class LLAgent : public LLOldEvents::LLObservable //-------------------------------------------------------------------- public: BOOL leftButtonGrabbed() const; + BOOL leftButtonBlocked() const; BOOL rotateGrabbed() const; BOOL forwardGrabbed() const; BOOL backwardGrabbed() const; @@ -496,13 +496,14 @@ class LLAgent : public LLOldEvents::LLObservable //-------------------------------------------------------------------- public: U32 getControlFlags(); - void setControlFlags(U32 mask); // performs bitwise mControlFlags |= mask - void clearControlFlags(U32 mask); // performs bitwise mControlFlags &= ~mask + void setControlFlags(U32 mask); // Performs bitwise mControlFlags |= mask + void clearControlFlags(U32 mask); // Performs bitwise mControlFlags &= ~mask BOOL controlFlagsDirty() const; void enableControlFlagReset(); void resetControlFlags(); - BOOL anyControlGrabbed() const; // True iff a script has taken over a control - BOOL isControlGrabbed(S32 control_index) const; + BOOL anyControlGrabbed() const; // True if a script has taken over any control + BOOL isControlGrabbed(S32 control_index) const; // True if a script has taken over a control + BOOL isControlBlocked(S32 control_index) const; // Control should be ignored or won't be passed // Send message to simulator to force grabbed controls to be // released, in case of a poorly written script. void forceReleaseControls(); @@ -522,7 +523,7 @@ class LLAgent : public LLOldEvents::LLObservable void stopCurrentAnimations(); void requestStopMotion(LLMotion* motion); void onAnimStop(const LLUUID& id); - void sendAnimationRequests(const std::vector &anim_ids, EAnimRequest request); + void sendAnimationRequests(const uuid_vec_t &anim_ids, EAnimRequest request); void sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request); void sendAnimationStateReset(); void sendRevokePermissions(const LLUUID & target, U32 permissions); @@ -567,6 +568,9 @@ class LLAgent : public LLOldEvents::LLObservable void moveYaw(F32 mag, bool reset_view = true); void movePitch(F32 mag); + BOOL isMovementLocked() const { return mMovementKeysLocked; } + void setMovementLocked(BOOL set_locked) { mMovementKeysLocked = set_locked; } + //-------------------------------------------------------------------- // Move the avatar's frame //-------------------------------------------------------------------- @@ -587,20 +591,22 @@ class LLAgent : public LLOldEvents::LLObservable public: BOOL getAutoPilot() const { return mAutoPilot; } LLVector3d getAutoPilotTargetGlobal() const { return mAutoPilotTargetGlobal; } - LLUUID getAutoPilotLeaderID() const { return mLeaderID; } + const LLUUID& getAutoPilotLeaderID() const { return mLeaderID; } F32 getAutoPilotStopDistance() const { return mAutoPilotStopDistance; } F32 getAutoPilotTargetDist() const { return mAutoPilotTargetDist; } BOOL getAutoPilotUseRotation() const { return mAutoPilotUseRotation; } LLVector3 getAutoPilotTargetFacing() const { return mAutoPilotTargetFacing; } F32 getAutoPilotRotationThreshold() const { return mAutoPilotRotationThreshold; } - std::string getAutoPilotBehaviorName() const { return mAutoPilotBehaviorName; } + const std::string& getAutoPilotBehaviorName() const { return mAutoPilotBehaviorName; } + bool getAutoPilotNoProgress() const; void startAutoPilotGlobal(const LLVector3d &pos_global, const std::string& behavior_name = std::string(), const LLQuaternion *target_rotation = NULL, void (*finish_callback)(BOOL, void *) = NULL, void *callback_data = NULL, - F32 stop_distance = 0.f, F32 rotation_threshold = 0.03f); - void startFollowPilot(const LLUUID &leader_id); + F32 stop_distance = 0.f, F32 rotation_threshold = 0.03f, + BOOL allow_flying = TRUE); + void startFollowPilot(const LLUUID &leader_id, BOOL allow_flying = TRUE, F32 stop_distance = 0.5f); void stopAutoPilot(BOOL user_cancel = FALSE); void setAutoPilotTargetGlobal(const LLVector3d &target_global); void autoPilot(F32 *delta_yaw); // Autopilot walking action, angles in radians @@ -608,17 +614,19 @@ class LLAgent : public LLOldEvents::LLObservable private: BOOL mAutoPilot; BOOL mAutoPilotFlyOnStop; + BOOL mAutoPilotAllowFlying; LLVector3d mAutoPilotTargetGlobal; F32 mAutoPilotStopDistance; BOOL mAutoPilotUseRotation; LLVector3 mAutoPilotTargetFacing; F32 mAutoPilotTargetDist; - S32 mAutoPilotNoProgressFrameCount; + U64 mAutoPilotNoProgressFrameCount; F32 mAutoPilotRotationThreshold; std::string mAutoPilotBehaviorName; void (*mAutoPilotFinishedCallback)(BOOL, void *); void* mAutoPilotCallbackData; LLUUID mLeaderID; + BOOL mMovementKeysLocked; /** Movement ** ** @@ -662,6 +670,7 @@ class LLAgent : public LLOldEvents::LLObservable void teleportViaLocation(const LLVector3d& pos_global); // To a global location - this will probably need to be deprecated void teleportViaLocationLookAt(const LLVector3d& pos_global);// To a global location, preserving camera rotation void teleportCancel(); // May or may not be allowed by server + void restoreCanceledTeleportRequest(); bool getTeleportKeepsLookAt() { return mbTeleportKeepsLookAt; } // Whether look-at reset after teleport protected: bool teleportCore(bool is_local = false); // Stuff for all teleports; returns true if the teleport can proceed @@ -684,6 +693,7 @@ class LLAgent : public LLOldEvents::LLObservable friend class LLTeleportRequestViaLocationLookAt; LLTeleportRequestPtr mTeleportRequest; + LLTeleportRequestPtr mTeleportCanceled; boost::signals2::connection mTeleportFinishedSlot; boost::signals2::connection mTeleportFailedSlot; @@ -710,7 +720,7 @@ class LLAgent : public LLOldEvents::LLObservable // Teleport State //-------------------------------------------------------------------- public: - ETeleportState getTeleportState() const { return mTeleportState; } + ETeleportState getTeleportState() const; void setTeleportState(ETeleportState state); private: ETeleportState mTeleportState; @@ -728,6 +738,13 @@ class LLAgent : public LLOldEvents::LLObservable ** ** *******************************************************************************/ + // Attachments getting lost on TP +public: + void setIsCrossingRegion(bool is_crossing) { mIsCrossingRegion = is_crossing; } + bool isCrossingRegion() const { return mIsCrossingRegion; } +private: + bool mIsCrossingRegion; + // Build public: bool canEditParcel() const { return mCanEditParcel; } @@ -752,8 +769,6 @@ class LLAgent : public LLOldEvents::LLObservable const LLAgentAccess& getAgentAccess(); BOOL canManageEstate() const; BOOL getAdminOverride() const; - // ! BACKWARDS COMPATIBILITY ! This function can go away after the AO transition (see llstartup.cpp). - void setAOTransition(); private: LLAgentAccess * mAgentAccess; @@ -769,7 +784,7 @@ class LLAgent : public LLOldEvents::LLObservable void requestEnterGodMode(); void requestLeaveGodMode(); - typedef boost::function god_level_change_callback_t; + typedef std::function god_level_change_callback_t; typedef boost::signals2::signal god_level_change_signal_t; typedef boost::signals2::connection god_level_change_slot_t; @@ -791,7 +806,7 @@ class LLAgent : public LLOldEvents::LLObservable bool canAccessMature() const; bool canAccessAdult() const; bool canAccessMaturityInRegion( U64 region_handle ) const; - bool canAccessMaturityAtGlobal( LLVector3d pos_global ) const; + bool canAccessMaturityAtGlobal( const LLVector3d& pos_global ) const; bool prefersPG() const; bool prefersMature() const; bool prefersAdult() const; @@ -927,7 +942,7 @@ class LLAgent : public LLOldEvents::LLObservable void friendsChanged(); private: LLFriendObserver* mFriendObserver; - std::set mProxyForAgents; + uuid_set_t mProxyForAgents; /** Groups ** ** @@ -948,9 +963,17 @@ class LLAgent : public LLOldEvents::LLObservable void sendAgentSetAppearance(); void sendAgentDataUpdateRequest(); void sendAgentUserInfoRequest(); - // IM to Email and Online visibility + +// IM to Email and Online visibility void sendAgentUpdateUserInfo(bool im_to_email, const std::string& directory_visibility); +private: + void requestAgentUserInfoCoro(const LLCoroResponder& responder); + void updateAgentUserInfoCoro(const LLCoroResponder& responder); + // DEPRECATED: may be removed when User Info cap propagates + void sendAgentUserInfoRequestMessage(); + void sendAgentUpdateUserInfoMessage(bool im_via_email, const std::string& directory_visibility); + //-------------------------------------------------------------------- // Receive //-------------------------------------------------------------------- diff --git a/indra/newview/llagentbenefits.cpp b/indra/newview/llagentbenefits.cpp new file mode 100644 index 0000000000..7a92dff359 --- /dev/null +++ b/indra/newview/llagentbenefits.cpp @@ -0,0 +1,260 @@ +/** +* @file llagentbenefits.cpp +* +* $LicenseInfo:firstyear=2019&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2019, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" +#include "llagentbenefits.h" + +LLAgentBenefits::LLAgentBenefits(): + m_initalized(false), + m_animated_object_limit(-1), + m_animation_upload_cost(-1), + m_attachment_limit(-1), + m_group_membership_limit(-1), + m_picks_limit(-1), + m_sound_upload_cost(-1), + m_texture_upload_cost(-1) +{ +} + +LLAgentBenefits::~LLAgentBenefits() +{ +} + +// This could be extended to a template scheme or otherwise modified +// to support other types, if and when needed. Currently all fields +// the viewer cares about are integer. +bool get_required_S32(const LLSD& sd, const LLSD::String& key, S32& value) +{ + value = -1; + if (sd.has(key)) + { + value = sd[key].asInteger(); + return true; + } + + LL_WARNS("Benefits") << "Missing required benefit field " << key << LL_ENDL; + return false; +} + +bool LLAgentBenefits::init(const LLSD& benefits_sd) +{ + LL_DEBUGS("Benefits") << "initializing benefits from " << benefits_sd << LL_ENDL; + + if (!get_required_S32(benefits_sd, "animated_object_limit", m_animated_object_limit)) + { + return false; + } + if (!get_required_S32(benefits_sd, "animation_upload_cost", m_animation_upload_cost)) + { + return false; + } + if (!get_required_S32(benefits_sd, "attachment_limit", m_attachment_limit)) + { + return false; + } + if (!get_required_S32(benefits_sd, "create_group_cost", m_create_group_cost)) + { + return false; + } + if (!get_required_S32(benefits_sd, "group_membership_limit", m_group_membership_limit)) + { + return false; + } + if (!get_required_S32(benefits_sd, "picks_limit", m_picks_limit)) + { + return false; + } + if (!get_required_S32(benefits_sd, "sound_upload_cost", m_sound_upload_cost)) + { + return false; + } + if (!get_required_S32(benefits_sd, "texture_upload_cost", m_texture_upload_cost)) + { + return false; + } + + // FIXME PREMIUM - either use this field or get rid of it + m_initalized = true; + return true; +} + +void LLAgentBenefits::initNonSL(const LLSD& benefits_sd) +{ + if (!get_required_S32(benefits_sd, "max_groups", m_group_membership_limit) + && !get_required_S32(benefits_sd, "max-agent-groups", m_group_membership_limit)) + m_group_membership_limit = S32_MAX; + m_picks_limit = m_animated_object_limit = m_attachment_limit = S32_MAX; + m_texture_upload_cost = m_sound_upload_cost = m_create_group_cost = m_animation_upload_cost = 0; +} + +void LLAgentBenefits::processEconomyData(LLMessageSystem* msg) +{ + msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceUpload, m_texture_upload_cost); + m_sound_upload_cost = m_animation_upload_cost = m_texture_upload_cost; + msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceGroupCreate, m_create_group_cost); + + LL_INFOS_ONCE("Messaging") << "EconomyData message arrived; upload cost is L$" << m_texture_upload_cost << " group cost is " << m_create_group_cost << LL_ENDL; +} + +S32 LLAgentBenefits::getAnimatedObjectLimit() const +{ + return m_animated_object_limit; +} + +S32 LLAgentBenefits::getAnimationUploadCost() const +{ + return m_animation_upload_cost; +} + +S32 LLAgentBenefits::getAttachmentLimit() const +{ + return m_attachment_limit; +} + +S32 LLAgentBenefits::getCreateGroupCost() const +{ + return m_create_group_cost; +} + +S32 LLAgentBenefits::getGroupMembershipLimit() const +{ + return m_group_membership_limit; +} + +S32 LLAgentBenefits::getPicksLimit() const +{ + return m_picks_limit; +} + +S32 LLAgentBenefits::getSoundUploadCost() const +{ + return m_sound_upload_cost; +} + +S32 LLAgentBenefits::getTextureUploadCost() const +{ + return m_texture_upload_cost; +} + +bool LLAgentBenefits::findUploadCost(LLAssetType::EType& asset_type, S32& cost) const +{ + bool succ = false; + if (asset_type == LLAssetType::AT_TEXTURE) + { + cost = getTextureUploadCost(); + succ = true; + } + else if (asset_type == LLAssetType::AT_SOUND) + { + cost = getSoundUploadCost(); + succ = true; + } + else if (asset_type == LLAssetType::AT_ANIMATION) + { + cost = getAnimationUploadCost(); + succ = true; + } + return succ; +} + +LLAgentBenefitsMgr::LLAgentBenefitsMgr() +{ +} + +LLAgentBenefitsMgr::~LLAgentBenefitsMgr() +{ +} + +// static +LLAgentBenefits& LLAgentBenefitsMgr::current() +{ + return instance().mCurrent; +} + +// static +const LLAgentBenefits& LLAgentBenefitsMgr::get(const std::string& package) +{ + if (instance().mPackageMap.find(package) != instance().mPackageMap.end()) + { + return instance().mPackageMap[package]; + } + else + { + return instance().mDefault; + } +} + +// static +bool LLAgentBenefitsMgr::init(const std::string& package, const LLSD& benefits_sd) +{ + LLAgentBenefits benefits; + if (!benefits.init(benefits_sd)) + { + LL_WARNS("Benefits") << "Unable to initialize package " << package << " from sd " << benefits_sd << LL_ENDL; + return false; + } + else + { + instance().mPackageMap[package] = benefits; + } + return true; + +} + +// static +bool LLAgentBenefitsMgr::initCurrent(const std::string& package, const LLSD& benefits_sd) +{ + LLAgentBenefits benefits; + if (!benefits.init(benefits_sd)) + { + LL_WARNS("Benefits") << "Unable to initialize package " << package << " from sd " << benefits_sd << LL_ENDL; + return false; + } + else + { + instance().mCurrent = benefits; + instance().mCurrentName = package; + } + return true; + +} + +void LLAgentBenefitsMgr::initNonSL(const LLSD& benefits_sd) +{ + mCurrent.initNonSL(benefits_sd); + mCurrentName = "NonSL"; +} + +// static +bool LLAgentBenefitsMgr::has(const std::string& package) +{ + return instance().mPackageMap.find(package) != instance().mPackageMap.end(); +} + +//static +bool LLAgentBenefitsMgr::isCurrent(const std::string& package) +{ + return instance().mCurrentName == package; +} diff --git a/indra/newview/llagentbenefits.h b/indra/newview/llagentbenefits.h new file mode 100644 index 0000000000..b121e33893 --- /dev/null +++ b/indra/newview/llagentbenefits.h @@ -0,0 +1,92 @@ +/** +* @file llagentbenefits.h +* +* $LicenseInfo:firstyear=2019&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2019, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_AGENTBENEFITS_H +#define LL_AGENTBENEFITS_H + +#include "llsingleton.h" +#include "llsd.h" +#include "llassettype.h" + +class LLAgentBenefits +{ +public: + LLAgentBenefits(); + ~LLAgentBenefits(); + LOG_CLASS(LLAgentBenefits); + + bool init(const LLSD& benefits_sd); + void initNonSL(const LLSD& benefits_sd); + void processEconomyData(LLMessageSystem*); + + S32 getAnimatedObjectLimit() const; + S32 getAnimationUploadCost() const; + S32 getAttachmentLimit() const; + S32 getCreateGroupCost() const; + S32 getGroupMembershipLimit() const; + S32 getPicksLimit() const; + S32 getSoundUploadCost() const; + S32 getTextureUploadCost() const; + + bool findUploadCost(LLAssetType::EType& asset_type, S32& cost) const; + +private: + S32 m_animated_object_limit; + S32 m_animation_upload_cost; + S32 m_attachment_limit; + S32 m_create_group_cost; + S32 m_group_membership_limit; + S32 m_picks_limit; + S32 m_sound_upload_cost; + S32 m_texture_upload_cost; + + bool m_initalized; +}; + +class LLAgentBenefitsMgr : public LLSingleton +{ + friend class LLSingleton; + LLAgentBenefitsMgr(); + ~LLAgentBenefitsMgr(); + LOG_CLASS(LLAgentBenefitsMgr); + +public: + static LLAgentBenefits& current(); + static const LLAgentBenefits& get(const std::string& package); + static bool init(const std::string& package, const LLSD& benefits_sd); + static bool initCurrent(const std::string& package, const LLSD& benefits_sd); + void initNonSL(const LLSD& benefits_sd); + static bool has(const std::string& package); + static bool isCurrent(const std::string& package); + +private: + std::string mCurrentName; + LLAgentBenefits mCurrent; + LLAgentBenefits mDefault; + std::map mPackageMap; +}; + + +#endif diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 56099a084e..c08751edac 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -29,6 +29,7 @@ #include "pipeline.h" +#include "aosystem.h" //For AOSystem #include "llagent.h" #include "llanimationstates.h" #include "llfloatercamera.h" @@ -49,7 +50,6 @@ #include "llwindow.h" #include "llworld.h" #include "llfloatertools.h" //For gFloaterTools -#include "floaterao.h" //For LLFloaterAO #include "llfloatercustomize.h" //For gFloaterCustomize // [RLVa:KB] - Checked: 2010-05-10 (RLVa-1.2.0g) #include "rlvhandler.h" @@ -155,12 +155,14 @@ LLAgentCamera::LLAgentCamera() : mCameraUpVector(LLVector3::z_axis), // default is straight up mFocusOnAvatar(TRUE), + mAllowChangeToFollow(FALSE), mFocusGlobal(), mFocusTargetGlobal(), mFocusObject(NULL), mFocusObjectDist(0.f), mFocusObjectOffset(), mFocusDotRadius( 0.1f ), // meters + mTrackFocusObject(TRUE), mUIOffset(0.f), mAtKey(0), // Either 1, 0, or -1... indicates that movement-key is pressed @@ -224,6 +226,7 @@ void LLAgentCamera::init() mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale"); mTargetCameraDistance = mCurrentCameraDistance; mCameraZoomFraction = 1.f; + mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject"); mInitialized = true; } @@ -286,30 +289,22 @@ LLAgentCamera::~LLAgentCamera() //----------------------------------------------------------------------------- void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera) { - if (gAgent.getAutoPilot()) + LLSelectMgr::getInstance()->unhighlightAll(); + + // By popular request, keep land selection while walking around. JC + // LLViewerParcelMgr::getInstance()->deselectLand(); + + // force deselect when walking and attachment is selected + // this is so people don't wig out when their avatar moves without animating + if (LLSelectMgr::getInstance()->getSelection()->isAttachment()) { - gAgent.stopAutoPilot(TRUE); + LLSelectMgr::getInstance()->deselectAll(); } - if (!gNoRender) + if (gMenuHolder != NULL) { - LLSelectMgr::getInstance()->unhighlightAll(); - - // By popular request, keep land selection while walking around. JC - // LLViewerParcelMgr::getInstance()->deselectLand(); - - // force deselect when walking and attachment is selected - // this is so people don't wig out when their avatar moves without animating - if (LLSelectMgr::getInstance()->getSelection()->isAttachment()) - { - LLSelectMgr::getInstance()->deselectAll(); - } - - if (gMenuHolder != NULL) - { - // Hide all popup menus - gMenuHolder->hideMenus(); - } + // Hide all popup menus + gMenuHolder->hideMenus(); } static const LLCachedControl freeze_time("FreezeTime",false); @@ -352,7 +347,7 @@ void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera) LLVector3 agent_at_axis = gAgent.getAtAxis(); agent_at_axis -= projected_vec(agent_at_axis, gAgent.getReferenceUpVector()); agent_at_axis.normalize(); - gAgent.resetAxes(lerp(gAgent.getAtAxis(), agent_at_axis, LLCriticalDamp::getInterpolant(0.3f))); + gAgent.resetAxes(lerp(gAgent.getAtAxis(), agent_at_axis, LLSmoothInterpolation::getInterpolant(0.3f))); } setFocusOnAvatar(TRUE, ANIMATE); @@ -790,6 +785,7 @@ void LLAgentCamera::setCameraZoomFraction(F32 fraction) // 0.f -> camera zoomed all the way out // 1.f -> camera zoomed all the way in LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) { mHUDTargetZoom = fraction; @@ -830,6 +826,7 @@ void LLAgentCamera::setCameraZoomFraction(F32 fraction) { min_zoom = 0.f; } + LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; camera_offset_dir.normalize(); //mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom); @@ -912,7 +909,8 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction) LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); - F32 min_zoom = 0.f;//LAND_MIN_ZOOM; + // Still limit min zoom to something sane, otherwise the camera normal starts flaking out. + F32 min_zoom = 0.02f;//LAND_MIN_ZOOM; F32 current_distance = (F32)camera_offset_unit.normalize(); F32 new_distance = current_distance * fraction; @@ -933,9 +931,8 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction) min_zoom = OBJECT_MIN_ZOOM; } } - - new_distance = llmax(new_distance, min_zoom); } + new_distance = llmax(new_distance, min_zoom); // Don't zoom too far back const F32 DIST_FUDGE = 16.f; // meters @@ -1190,8 +1187,8 @@ void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y) //----------------------------------------------------------------------------- void LLAgentCamera::updateCamera() { - //static LLFastTimer::DeclareTimer ftm("Camera"); - //LLFastTimer t(ftm); + //static LLTrace::BlockTimerStatHandle ftm("Camera"); + //LL_RECORD_BLOCK_TIME(ftm); // - changed camera_skyward to the new global "mCameraUpVector" mCameraUpVector = LLVector3::z_axis; @@ -1211,8 +1208,10 @@ void LLAgentCamera::updateCamera() mCameraUpVector = mCameraUpVector * gAgentAvatarp->getRenderRotation(); } - if (cameraThirdPerson() && mFocusOnAvatar && LLFollowCamMgr::getActiveFollowCamParams()) + if (cameraThirdPerson() && (mFocusOnAvatar || mAllowChangeToFollow) && LLFollowCamMgr::getActiveFollowCamParams()) { + mAllowChangeToFollow = FALSE; + mFocusOnAvatar = TRUE; changeCameraToFollow(); } @@ -1295,7 +1294,7 @@ void LLAgentCamera::updateCamera() gAgentCamera.clearPanKeys(); // lerp camera focus offset - mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLCriticalDamp::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); + mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLSmoothInterpolation::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); if ( mCameraMode == CAMERA_MODE_FOLLOW ) { @@ -1414,7 +1413,7 @@ void LLAgentCamera::updateCamera() const F32 SMOOTHING_HALF_LIFE = 0.02f; static const LLCachedControl camera_position_smoothing("CameraPositionSmoothing"); - F32 smoothing = LLCriticalDamp::getInterpolant(camera_position_smoothing * SMOOTHING_HALF_LIFE, FALSE); + F32 smoothing = LLSmoothInterpolation::getInterpolant(camera_position_smoothing * SMOOTHING_HALF_LIFE, FALSE); if (!mFocusObject) // we differentiate on avatar mode { @@ -1444,7 +1443,7 @@ void LLAgentCamera::updateCamera() } - mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLCriticalDamp::getInterpolant(FOV_ZOOM_HALF_LIFE)); + mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLSmoothInterpolation::getInterpolant(FOV_ZOOM_HALF_LIFE)); // LL_INFOS() << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << LL_ENDL; @@ -1611,7 +1610,7 @@ F32 LLAgentCamera::calcCustomizeAvatarUIOffset( const LLVector3d& camera_pos_glo } } F32 range = (F32)dist_vec(camera_pos_global, gAgentCamera.getFocusGlobal()); - mUIOffset = lerp(mUIOffset, ui_offset, LLCriticalDamp::getInterpolant(0.05f)); + mUIOffset = lerp(mUIOffset, ui_offset, LLSmoothInterpolation::getInterpolant(0.05f)); return mUIOffset * range; } @@ -1656,10 +1655,11 @@ LLVector3d LLAgentCamera::calcFocusPositionTargetGlobal() { LLDrawable* drawablep = mFocusObject->mDrawable; - static const LLCachedControl track_focus_object("TrackFocusObject"); - if (track_focus_object && drawablep) + if (mTrackFocusObject && + drawablep && + drawablep->isActive()) { - if (drawablep->isActive() && !mFocusObject->isAvatar()) + if (!mFocusObject->isAvatar()) { if (mFocusObject->isSelected()) { @@ -1919,7 +1919,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) if (mTargetCameraDistance != mCurrentCameraDistance) { - F32 camera_lerp_amt = LLCriticalDamp::getInterpolant(CAMERA_ZOOM_HALF_LIFE); + F32 camera_lerp_amt = LLSmoothInterpolation::getInterpolant(CAMERA_ZOOM_HALF_LIFE); mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt); } @@ -1936,7 +1936,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) if (isAgentAvatarValid()) { LLVector3d camera_lag_d; - F32 lag_interp = LLCriticalDamp::getInterpolant(CAMERA_LAG_HALF_LIFE); + F32 lag_interp = LLSmoothInterpolation::getInterpolant(CAMERA_LAG_HALF_LIFE); LLVector3 target_lag; LLVector3 vel = gAgent.getVelocity(); @@ -1982,7 +1982,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) } else { - mCameraLag = lerp(mCameraLag, LLVector3::zero, LLCriticalDamp::getInterpolant(0.15f)); + mCameraLag = lerp(mCameraLag, LLVector3::zero, LLSmoothInterpolation::getInterpolant(0.15f)); } camera_lag_d.setVec(mCameraLag); @@ -2264,8 +2264,9 @@ void LLAgentCamera::changeCameraToMouselook(BOOL animate) { mMouselookTimer.reset(); - gFocusMgr.setKeyboardFocus( NULL ); - if (gSavedSettings.getBOOL("AONoStandsInMouselook")) LLFloaterAO::stopMotion(LLFloaterAO::getCurrentStandId(), FALSE,TRUE); + gFocusMgr.setKeyboardFocus(NULL); + auto ao = AOSystem::getIfExists(); + if (ao && gSavedSettings.getBOOL("AONoStandsInMouselook")) ao->stopCurrentStand(); updateLastCamera(); mCameraMode = CAMERA_MODE_MOUSELOOK; @@ -2512,13 +2513,13 @@ void LLAgentCamera::changeCameraToCustomizeAvatar() gAgent.sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); gAgent.setCustomAnim(TRUE); gAgentAvatarp->startMotion(ANIM_AGENT_CUSTOMIZE); - } - LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE); + LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE); - if (turn_motion) - { - // delay camera animation long enough to play through turn animation - setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP); + if (turn_motion) + { + // delay camera animation long enough to play through turn animation + setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP); + } } } // @@ -2547,8 +2548,6 @@ void LLAgentCamera::changeCameraToCustomizeAvatar() LLVector3d focus_target_global = gAgent.getPosGlobalFromAgent(focus_target); setAnimationDuration(gSavedSettings.getF32("ZoomTime")); setCameraPosAndFocusGlobal(focus_target_global + camera_offset, focus_target_global, gAgent.getID()); - - } @@ -2860,6 +2859,7 @@ void LLAgentCamera::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate) { // keep camera focus point consistent, even though it is now unlocked setFocusGlobal(gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(), gAgent.getID()); + mAllowChangeToFollow = FALSE; } mFocusOnAvatar = focus_on_avatar; @@ -2997,6 +2997,10 @@ bool LLAgentCamera::lookAtObject(const LLUUID &object_id, bool self) return true; } +bool LLAgentCamera::isfollowCamLocked() +{ + return mFollowCam.getPositionLocked(); +} BOOL LLAgentCamera::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position) { @@ -3071,3 +3075,4 @@ S32 LLAgentCamera::directionToKey(S32 direction) // EOF + diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h index 8ba8a4f705..6d580fd450 100644 --- a/indra/newview/llagentcamera.h +++ b/indra/newview/llagentcamera.h @@ -88,11 +88,9 @@ class LLAgentCamera void changeCameraToDefault(); void changeCameraToMouselook(BOOL animate = TRUE); void changeCameraToThirdPerson(BOOL animate = TRUE); - void changeCameraToCustomizeAvatar(); // trigger transition animation + void changeCameraToCustomizeAvatar(); // Trigger transition animation F32 calcCustomizeAvatarUIOffset( const LLVector3d& camera_pos_global ); - // Ventrella - void changeCameraToFollow(BOOL animate = TRUE); - //end Ventrella + void changeCameraToFollow(BOOL animate = TRUE); // Ventrella BOOL cameraThirdPerson() const { return (mCameraMode == CAMERA_MODE_THIRD_PERSON && mLastCameraMode == CAMERA_MODE_THIRD_PERSON); } BOOL cameraMouselook() const { return (mCameraMode == CAMERA_MODE_MOUSELOOK && mLastCameraMode == CAMERA_MODE_MOUSELOOK); } BOOL cameraCustomizeAvatar() const { return (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR /*&& !mCameraAnimating*/); } @@ -162,6 +160,7 @@ class LLAgentCamera //-------------------------------------------------------------------- public: void setUsingFollowCam(bool using_follow_cam); + bool isfollowCamLocked(); private: LLFollowCam mFollowCam; // Ventrella @@ -214,18 +213,22 @@ class LLAgentCamera void setCameraPosAndFocusGlobal(const LLVector3d& pos, const LLVector3d& focus, const LLUUID &object_id); void clearFocusObject(); void setFocusObject(LLViewerObject* object); + void setAllowChangeToFollow(BOOL focus) { mAllowChangeToFollow = focus; } + void setObjectTracking(BOOL track) { mTrackFocusObject = track; } const LLVector3d &getFocusGlobal() const { return mFocusGlobal; } const LLVector3d &getFocusTargetGlobal() const { return mFocusTargetGlobal; } private: LLVector3d mCameraFocusOffset; // Offset from focus point in build mode LLVector3d mCameraFocusOffsetTarget; // Target towards which we are lerping the camera's focus offset BOOL mFocusOnAvatar; + BOOL mAllowChangeToFollow; LLVector3d mFocusGlobal; LLVector3d mFocusTargetGlobal; LLPointer mFocusObject; F32 mFocusObjectDist; LLVector3 mFocusObjectOffset; F32 mFocusDotRadius; // Meters + BOOL mTrackFocusObject; //-------------------------------------------------------------------- // Lookat / Pointat diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index dfed2502c3..30a86d723a 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -27,11 +27,14 @@ #include "llviewerprecompiledheaders.h" #include "llagentwearables.h" +#include "llattachmentsmgr.h" #include "llagent.h" #include "llagentcamera.h" #include "llagentwearablesfetch.h" #include "llappearancemgr.h" +#include "llattachmentsmgr.h" #include "llcallbacklist.h" +#include "llfloatercustomize.h" #include "llfolderview.h" #include "llgesturemgr.h" #include "llinventorybridge.h" @@ -47,11 +50,10 @@ #include "lltooldraganddrop.h" #include "llviewerregion.h" #include "llvoavatarself.h" -#include "llwearable.h" +#include "llviewerwearable.h" #include "llwearablelist.h" #include "lllocaltextureobject.h" -#include "llfloatercustomize.h" #include "llfloaterperms.h" @@ -70,11 +72,32 @@ BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE; // [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-08-14 (Catznip-2.1) bool LLAgentWearables::mInitialWearablesLoaded = false; // [/SL:KB] +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1) +bool LLAgentWearables::mInitialAttachmentsRequested = false; +// [/RLVa:KB] using namespace LLAvatarAppearanceDefines; /////////////////////////////////////////////////////////////////////////////// +void set_default_permissions(LLViewerInventoryItem* item) +{ + llassert(item); + LLPermissions perm = item->getPermissions(); + if (perm.getMaskNextOwner() != LLFloaterPerms::getNextOwnerPerms("Wearables") + || perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms("Wearables") + || perm.getMaskGroup() != LLFloaterPerms::getGroupPerms("Wearables")) + { + perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables")); + perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables")); + perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables")); + + item->setPermissions(perm); + + item->updateServer(FALSE); + } +} + // Callback to wear and start editing an item that has just been created. void wear_and_edit_cb(const LLUUID& inv_item) { @@ -83,13 +106,9 @@ void wear_and_edit_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (!item) return; - LLPermissions perm = item->getPermissions(); - perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables")); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables")); - item->setPermissions(perm); + set_default_permissions(item); - item->updateServer(FALSE); + // item was just created, update even if permissions did not changed gInventory.updateItem(item); gInventory.notifyObservers(); @@ -107,13 +126,8 @@ void wear_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables")); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables")); - item->setPermissions(perm); + set_default_permissions(item); - item->updateServer(FALSE); gInventory.updateItem(item); gInventory.notifyObservers(); } @@ -174,19 +188,12 @@ void LLAgentWearables::dump() } } - LL_INFOS() << "Total items awaiting wearable update " << mItemsAwaitingWearableUpdate.size() << LL_ENDL; - for (std::set::iterator it = mItemsAwaitingWearableUpdate.begin(); - it != mItemsAwaitingWearableUpdate.end(); - ++it) - { - LL_INFOS() << (*it).asString() << LL_ENDL; - } } struct LLAgentDumper { LLAgentDumper(std::string name): - mName(name) + mName(std::move(name)) { LL_INFOS() << LL_ENDL; LL_INFOS() << "LLAgentDumper " << mName << LL_ENDL; @@ -235,7 +242,11 @@ void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar) if(!gHippoGridManager->getConnectedGrid()->isSecondLife()) { avatar->outputRezTiming("Sending wearables request"); - sendAgentWearablesRequest(); + gMessageSystem->newMessageFast(_PREHASH_AgentWearablesRequest); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + gAgent.sendReliableMessage(); } setAvatarAppearance(avatar); } @@ -246,7 +257,7 @@ void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar) * * Would like to pass the agent in here, but we can't safely * count on it being around later. Just use gAgent directly. - * @param cb callback to execute on completion (??? unused ???) + * @param cb callback to execute on completion (? unused ?) * @param type Type for the wearable in the agent * @param wearable The wearable data. * @param todo Bitmask of actions to take on completion. @@ -257,7 +268,7 @@ LLAgentWearables::AddWearableToAgentInventoryCallback::AddWearableToAgentInvento mIndex(index), mWearable(wearable), mTodo(todo), - mCB(cb), + mCB(std::move(cb)), mDescription(description) { LL_INFOS() << "constructor" << LL_ENDL; @@ -270,15 +281,6 @@ void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& i gAgentWearables.addWearabletoAgentInventoryDone(mType, mIndex, inv_item, mWearable); - if (mTodo & CALL_UPDATE) - { - gAgentWearables.sendAgentWearablesUpdate(); - } - if (mTodo & CALL_RECOVERDONE) - { - LLAppearanceMgr::instance().addCOFItemLink(inv_item); - gAgentWearables.recoverMissingWearableDone(); - } /* * Do this for every one in the loop */ @@ -336,84 +338,9 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const LLWearableType::ETy gInventory.notifyObservers(); } -void LLAgentWearables::sendAgentWearablesUpdate() -{ - // First make sure that we have inventory items for each wearable - for (S32 type=0; type < LLWearableType::WT_COUNT; ++type) - { - for (U32 index=0; index < getWearableCount((LLWearableType::EType)type); ++index) - { - LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)type,index); - if (wearable) - { - if (wearable->getItemID().isNull()) - { - LLPointer cb = - new AddWearableToAgentInventoryCallback( - LLPointer(NULL), - (LLWearableType::EType)type, - index, - wearable, - AddWearableToAgentInventoryCallback::CALL_NONE); - addWearableToAgentInventory(cb, wearable); - } - else - { - gInventory.addChangedMask( LLInventoryObserver::LABEL, - wearable->getItemID()); - } - } - } - } - - // Then make sure the inventory is in sync with the avatar. - gInventory.notifyObservers(); - - // Send the AgentIsNowWearing - gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing); - - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - - LL_DEBUGS() << "sendAgentWearablesUpdate()" << LL_ENDL; - // MULTI-WEARABLE: DEPRECATED: HACK: index to 0- server database tables don't support concept of multiwearables. - for (S32 type=0; type < LLWearableType::WT_COUNT; ++type) - { - gMessageSystem->nextBlockFast(_PREHASH_WearableData); - - U8 type_u8 = (U8)type; - gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8 ); - - LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)type, 0); - if( wearable ) - { - //LL_INFOS() << "Sending wearable " << wearable->getName() << LL_ENDL; - LLUUID item_id = wearable->getItemID(); - const LLViewerInventoryItem *item = gInventory.getItem(item_id); - if (item && item->getIsLinkType()) - { - // Get the itemID that this item points to. i.e. make sure - // we are storing baseitems, not their links, in the database. - item_id = item->getLinkedUUID(); - } - gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id); - } - else - { - //LL_INFOS() << "Not wearing wearable type " << LLWearableType::getTypeName((LLWearableType::EType)i) << LL_ENDL; - gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null); - } - - LL_DEBUGS() << " " << LLWearableType::getTypeLabel((LLWearableType::EType)type) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << LL_ENDL; - } - gAgent.sendReliableMessage(); -} - -void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update, +void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index, const std::string new_name) { - //llassert_always(index == 0); LLViewerWearable* old_wearable = getViewerWearable(type, index); if(!old_wearable) return; bool name_changed = !new_name.empty() && (new_name != old_wearable->getName()); @@ -458,10 +385,6 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 { // Add a new inventory item (shouldn't ever happen here) U32 todo = AddWearableToAgentInventoryCallback::CALL_NONE; - if (send_update) - { - todo |= AddWearableToAgentInventoryCallback::CALL_UPDATE; - } LLPointer cb = new AddWearableToAgentInventoryCallback( LLPointer(NULL), @@ -474,11 +397,6 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 } gAgentAvatarp->wearableUpdated( type, TRUE ); - - if( send_update ) - { - sendAgentWearablesUpdate(); - } } } @@ -491,20 +409,20 @@ LLViewerWearable* LLAgentWearables::saveWearableAs(const LLWearableType::EType t if (!isWearableCopyable(type, index)) { LL_WARNS() << "LLAgent::saveWearableAs() not copyable." << LL_ENDL; - return NULL; + return nullptr; } LLViewerWearable* old_wearable = getViewerWearable(type, index); if (!old_wearable) { LL_WARNS() << "LLAgent::saveWearableAs() no old wearable." << LL_ENDL; - return NULL; + return nullptr; } LLInventoryItem* item = gInventory.getItem(getWearableItemID(type,index)); if (!item) { LL_WARNS() << "LLAgent::saveWearableAs() no inventory item." << LL_ENDL; - return NULL; + return nullptr; } std::string trunc_name(new_name); LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN); @@ -573,9 +491,8 @@ void LLAgentWearables::saveAllWearables() for (S32 i=0; i < LLWearableType::WT_COUNT; i++) { for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++) - saveWearable((LLWearableType::EType)i, j, FALSE); + saveWearable((LLWearableType::EType)i, j); } - sendAgentWearablesUpdate(); } // Called when the user changes the name of a wearable inventory item that is currently being worn. @@ -604,7 +521,6 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string& old_wearable->setName(old_name); setWearable((LLWearableType::EType)i,j,new_wearable); - sendAgentWearablesUpdate(); break; } } @@ -641,7 +557,6 @@ void LLAgentWearables::nameOrDescriptionChanged(LLUUID const& item_id) BOOL LLAgentWearables::isWearableModifiable(LLWearableType::EType type, U32 index) const { - //llassert_always(index == 0); LLUUID item_id = getWearableItemID(type, index); return item_id.notNull() ? isWearableModifiable(item_id) : FALSE; } @@ -652,7 +567,7 @@ BOOL LLAgentWearables::isWearableModifiable(const LLUUID& item_id) const if (linked_id.notNull()) { LLInventoryItem* item = gInventory.getItem(linked_id); - if(item && item->getPermissions().allowModifyBy(gAgent.getID(), + if (item && item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID())) { return TRUE; @@ -663,12 +578,11 @@ BOOL LLAgentWearables::isWearableModifiable(const LLUUID& item_id) const BOOL LLAgentWearables::isWearableCopyable(LLWearableType::EType type, U32 index) const { - //llassert_always(index == 0); LLUUID item_id = getWearableItemID(type, index); if (!item_id.isNull()) { LLInventoryItem* item = gInventory.getItem(item_id); - if(item && item->getPermissions().allowCopyBy(gAgent.getID(), + if (item && item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID())) { return TRUE; @@ -681,24 +595,23 @@ BOOL LLAgentWearables::isWearableCopyable(LLWearableType::EType type, U32 index) U32 LLAgentWearables::getWearablePermMask(LLWearableType::EType type) { LLUUID item_id = getWearableItemID(type); - if(!item_id.isNull()) + if (!item_id.isNull()) { LLInventoryItem* item = gInventory.getItem(item_id); - if(item) + if (item) { return item->getPermissions().getMaskOwner(); } } return PERM_NONE; -} + } */ LLInventoryItem* LLAgentWearables::getWearableInventoryItem(LLWearableType::EType type, U32 index) { - //llassert_always(index == 0); LLUUID item_id = getWearableItemID(type,index); LLInventoryItem* item = NULL; - if(item_id.notNull()) + if (item_id.notNull()) { item = gInventory.getItem(item_id); } @@ -755,15 +668,6 @@ LLViewerWearable* LLAgentWearables::getWearableFromAssetID(const LLUUID& asset_i return NULL; } -void LLAgentWearables::sendAgentWearablesRequest() -{ - gMessageSystem->newMessageFast(_PREHASH_AgentWearablesRequest); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - gAgent.sendReliableMessage(); -} - LLViewerWearable* LLAgentWearables::getViewerWearable(const LLWearableType::EType type, U32 index /*= 0*/) { return dynamic_cast (getWearable(type, index)); @@ -785,8 +689,7 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed) { if (isAgentAvatarValid()) { - const BOOL upload_result = removed; - gAgentAvatarp->wearableUpdated(wearable->getType(), upload_result); + gAgentAvatarp->wearableUpdated(wearable->getType(), removed); } LLWearableData::wearableUpdated(wearable, removed); @@ -808,7 +711,7 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed) { LL_INFOS() << "forcing wearable type " << wearable->getType() << " to version 22 from 24" << LL_ENDL; wearable->setDefinitionVersion(22); - saveWearable(wearable->getType(),index,TRUE); + saveWearable(wearable->getType(),index); } } @@ -821,19 +724,6 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed) checkWearableAgainstInventory(viewer_wearable); } - -} - - - -BOOL LLAgentWearables::itemUpdatePending(const LLUUID& item_id) const -{ - return mItemsAwaitingWearableUpdate.find(item_id) != mItemsAwaitingWearableUpdate.end(); -} - -U32 LLAgentWearables::itemUpdatePendingCount() const -{ - return mItemsAwaitingWearableUpdate.size(); } const LLUUID LLAgentWearables::getWearableItemID(LLWearableType::EType type, U32 index) const @@ -887,159 +777,6 @@ BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id) const return getWearableFromItemID(item_id) != NULL; } -// MULTI-WEARABLE: DEPRECATED (see backwards compatibility) -// static -// ! BACKWARDS COMPATIBILITY ! When we stop supporting viewer1.23, we can assume -// that viewers have a Current Outfit Folder and won't need this message, and thus -// we can remove/ignore this whole function. EXCEPT gAgentWearables.notifyLoadingStarted -void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data) -{ - // We should only receive this message a single time. Ignore subsequent AgentWearablesUpdates - // that may result from AgentWearablesRequest having been sent more than once. - if (mInitialWearablesUpdateReceived) - return; - - if (isAgentAvatarValid()) - { - //gAgentAvatarp->clearPhases(); // reset phase timers for outfit loading. - gAgentAvatarp->startPhase("process_initial_wearables_update"); - gAgentAvatarp->outputRezTiming("Received initial wearables update"); - } - - // notify subscribers that wearables started loading. See EXT-7777 - // *TODO: find more proper place to not be called from deprecated method. - // Seems such place is found: LLInitialWearablesFetch::processContents() - gAgentWearables.notifyLoadingStarted(); - - mInitialWearablesUpdateReceived = true; - - LLUUID agent_id; - gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); - - if (isAgentAvatarValid() && (agent_id == gAgentAvatarp->getID())) - { - gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgentQueryManager.mUpdateSerialNum); - - const S32 NUM_BODY_PARTS = 4; - S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData); - if (num_wearables < NUM_BODY_PARTS) - { - // Transitional state. Avatars should always have at least their body parts (hair, eyes, shape and skin). - // The fact that they don't have any here (only a dummy is sent) implies that either: - // 1. This account existed before we had wearables - // 2. The database has gotten messed up - // 3. This is the account's first login (i.e. the wearables haven't been generated yet). - return; - } - - // Get the UUID of the current outfit folder (will be created if it doesn't exist) - const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - LLInitialWearablesFetch* outfit = new LLInitialWearablesFetch(current_outfit_id); - - //LL_DEBUGS() << "processAgentInitialWearablesUpdate()" << LL_ENDL; - // Add wearables - // MULTI-WEARABLE: DEPRECATED: Message only supports one wearable per type, will be ignored in future. - gAgentWearables.mItemsAwaitingWearableUpdate.clear(); - for (S32 i=0; i < num_wearables; i++) - { - // Parse initial wearables data from message system - U8 type_u8 = 0; - gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i); - if (type_u8 >= LLWearableType::WT_COUNT) - { - continue; - } - LLWearableType::EType type = (LLWearableType::EType) type_u8; - - LLUUID item_id; - gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_ItemID, item_id, i ); - - LLUUID asset_id; - gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i ); - if( asset_id.isNull() ) - { - LLViewerWearable::removeFromAvatar( type, FALSE ); - } - else - { - LLAssetType::EType asset_type = LLWearableType::getAssetType( type ); - if (asset_type == LLAssetType::AT_NONE) - { - continue; - } - - // MULTI-WEARABLE: DEPRECATED: this message only supports one wearable per type. Should be ignored in future versions - - // Store initial wearables data until we know whether we have the current outfit folder or need to use the data. - LLInitialWearablesFetch::InitialWearableData wearable_data(type, item_id, asset_id); - outfit->add(wearable_data); - } - - LL_DEBUGS() << " " << LLWearableType::getTypeLabel(type) << LL_ENDL; - } - - // Get the complete information on the items in the inventory and set up an observer - // that will trigger when the complete information is fetched. - outfit->startFetch(); - if(outfit->isFinished()) - { - // everything is already here - call done. - outfit->done(); - } - else - { - // it's all on it's way - add an observer, and the inventory - // will call done for us when everything is here. - gInventory.addObserver(outfit); - } - - } -} - -// Normally, all wearables referred to "AgentWearablesUpdate" will correspond to actual assets in the -// database. If for some reason, we can't load one of those assets, we can try to reconstruct it so that -// the user isn't left without a shape, for example. (We can do that only after the inventory has loaded.) -void LLAgentWearables::recoverMissingWearable(const LLWearableType::EType type, U32 index) -{ - //llassert_always(index == 0); - // Try to recover by replacing missing wearable with a new one. - LLNotificationsUtil::add("ReplacedMissingWearable"); - LL_DEBUGS() << "Wearable " << LLWearableType::getTypeLabel( type ) << " could not be downloaded. Replaced inventory item with default wearable." << LL_ENDL; - LLViewerWearable* new_wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp); - - setWearable(type,index,new_wearable); - //new_wearable->writeToAvatar( TRUE ); - - // Add a new one in the lost and found folder. - // (We used to overwrite the "not found" one, but that could potentially - // destory content.) JC - const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - LLPointer cb = - new AddWearableToAgentInventoryCallback( - LLPointer(NULL), - type, - index, - new_wearable, - AddWearableToAgentInventoryCallback::CALL_RECOVERDONE); - addWearableToAgentInventory( cb, new_wearable, lost_and_found_id, TRUE); -} - -void LLAgentWearables::recoverMissingWearableDone() -{ - // Have all the wearables that the avatar was wearing at log-in arrived or been fabricated? - updateWearablesLoaded(); - if (areWearablesLoaded()) - { - // Make sure that the server's idea of the avatar's wearables actually match the wearables. - gAgent.sendAgentSetAppearance(); - } - else - { - gInventory.addChangedMask( LLInventoryObserver::LABEL, LLUUID::null ); - gInventory.notifyObservers(); - } -} - void LLAgentWearables::addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index) { LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)wearable_type, wearable_index); @@ -1210,29 +947,6 @@ void LLAgentWearables::sendDummyAgentWearablesUpdate() gAgent.sendReliableMessage(); } -void LLAgentWearables::createStandardWearablesDone(S32 type, U32 index) -{ - LL_INFOS() << "type " << type << " index " << index << LL_ENDL; - - if (!isAgentAvatarValid()) return; - gAgentAvatarp->updateVisualParams(); -} - -void LLAgentWearables::createStandardWearablesAllDone() -{ - // ... because sendAgentWearablesUpdate will notify inventory - // observers. - LL_INFOS() << "all done?" << LL_ENDL; - - mWearablesLoaded = TRUE; - checkWearablesLoaded(); - notifyLoadingFinished(); - - updateServer(); - - // Treat this as the first texture entry message, if none received yet - gAgentAvatarp->onFirstTEMessageReceived(); -} void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index) { @@ -1340,14 +1054,13 @@ bool LLAgentWearables::onRemoveWearableDialog(const LLSD& notification, const LL // Called by removeWearable() and onRemoveWearableDialog() to actually do the removal. void LLAgentWearables::removeWearableFinal( LLWearableType::EType type, bool do_remove_all, U32 index) { - //llassert_always(index == 0); + //LLAgentDumper dumper("removeWearable"); if (do_remove_all) { S32 max_entry = getWearableCount(type)-1; for (S32 i=max_entry; i>=0; i--) { LLViewerWearable* old_wearable = getViewerWearable(type,i); - //queryWearableCache(); // moved below if (old_wearable) { eraseWearable(old_wearable); @@ -1363,7 +1076,6 @@ void LLAgentWearables::removeWearableFinal( LLWearableType::EType type, bool do_ else { LLViewerWearable* old_wearable = getViewerWearable(type, index); - //queryWearableCache(); // moved below if (old_wearable) { @@ -1372,10 +1084,6 @@ void LLAgentWearables::removeWearableFinal( LLWearableType::EType type, bool do_ } } - queryWearableCache(); - - // Update the server - updateServer(); gInventory.notifyObservers(); } @@ -1389,9 +1097,10 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it llassert(items.size() == count); // Check for whether outfit already matches the one requested - S32 matched = 0, mismatched = 0, local_updates = 0; + S32 matched = 0, mismatched = 0; const S32 arr_size = LLWearableType::WT_COUNT; S32 type_counts[arr_size]; + BOOL update_inventory = FALSE; std::fill(type_counts,type_counts+arr_size,0); for (S32 i = 0; i < count; i++) { @@ -1408,38 +1117,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it S32 index = type_counts[type]; type_counts[type]++; - LLViewerWearable *curr_wearable = dynamic_cast(getWearable(type, index)); - - const LLUUID curr_id = curr_wearable ? curr_wearable->getItemID() : LLUUID::null; - const std::string curr_name = curr_wearable ? curr_wearable->getName() : std::string(); - - if (curr_id == new_item->getUUID()) //Nothing to do. No change.. - { - matched++; - continue; - } - - new_wearable->setName(new_item->getName()); - new_wearable->setItemID(new_item->getUUID()); - - bool matching_asset = new_wearable && curr_wearable && new_wearable->getAssetID() == curr_wearable->getAssetID(); - - if (matching_asset || LLWearableType::getAssetType(type) == LLAssetType::AT_BODYPART) - { - //Simple replacement at index. - setWearable(type, index, new_wearable); //Stomp the old wearable, but don't increment mismatched. setWearable calls wearableUpdate. - if (new_wearable == curr_wearable) //If both new and cur are the same underlying wearable, then the old id got overwritten in the setItemId call above. - //Need to manually call addChangedMasked on the prior id. - { - gInventory.addChangedMask(LLInventoryObserver::LABEL, curr_id); - } - if (matching_asset) - local_updates++; - else - mismatched++; //Need to update visual parameters and such things. - continue; - } - else + LLViewerWearable *curr_wearable = dynamic_cast(getWearable(type,index)); + if (!new_wearable || !curr_wearable || + new_wearable->getAssetID() != curr_wearable->getAssetID()) { LL_DEBUGS("Avatar") << "mismatch, type " << type << " index " << index << " names " << (curr_wearable ? curr_wearable->getName() : "NONE") << "," @@ -1448,10 +1128,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it continue; } - // Don't care about this case - ordering of wearables with the same asset id has no effect. - // Causes the two-alphas error case in MAINT-4158. + // Update only inventory in this case - ordering of wearables with the same asset id has no effect. + // Updating wearables in this case causes the two-alphas error in MAINT-4158. // We should actually disallow wearing two wearables with the same asset id. -#if 0 if (curr_wearable->getName() != new_item->getName() || curr_wearable->getItemID() != new_item->getUUID()) { @@ -1459,10 +1138,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it << curr_wearable->getName() << " vs " << new_item->getName() << " item ids " << curr_wearable->getItemID() << " vs " << new_item->getUUID() << LL_ENDL; - mismatched++; + update_inventory = TRUE; continue; } -#endif // If we got here, everything matches. matched++; } @@ -1476,18 +1154,14 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it mismatched++; } } - if (mismatched == 0) + if (mismatched == 0 && !update_inventory) { LL_DEBUGS("Avatar") << "no changes, bailing out" << LL_ENDL; - mCOFChangeInProgress = false; - if (local_updates) - { - LL_DEBUGS("Avatar") << "local_updates " << local_updates << " wearable itemIDs" << LL_ENDL; - gInventory.notifyObservers(); - } + notifyLoadingFinished(); return; } + // updating inventory // TODO: Removed check for ensuring that teens don't remove undershirt and underwear. Handle later // note: shirt is the first non-body part wearable item. Update if wearable order changes. @@ -1510,20 +1184,45 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it { const LLWearableType::EType type = new_wearable->getType(); - if (LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING) + LLUUID old_wearable_id = new_wearable->getItemID(); + new_wearable->setName(new_item->getName()); + new_wearable->setItemID(new_item->getUUID()); + + if (LLWearableType::getAssetType(type) == LLAssetType::AT_BODYPART) + { + // exactly one wearable per body part + setWearable(type,0,new_wearable); + if (old_wearable_id.notNull()) + { + // we changed id before setting wearable, update old item manually + // to complete the swap. + gInventory.addChangedMask(LLInventoryObserver::LABEL, old_wearable_id); + } + } + else { - pushWearable(type,new_wearable); //pushWearable calls wearableUpdate. + pushWearable(type,new_wearable); } + + const BOOL removed = FALSE; + wearableUpdated(new_wearable, removed); } } gInventory.notifyObservers(); + if (mismatched == 0) + { + LL_DEBUGS("Avatar") << "inventory updated, wearable assets not changed, bailing out" << LL_ENDL; + notifyLoadingFinished(); + return; + } + + // updating agent avatar + if (isAgentAvatarValid()) { gAgentAvatarp->setCompositeUpdatesEnabled(TRUE); - gAgentAvatarp->writeWearablesToAvatar(); - gAgentAvatarp->updateVisualParams(); // If we have not yet declouded, we may want to use // baked texture UUIDs sent from the first objectUpdate message @@ -1538,16 +1237,21 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it // Start rendering & update the server mWearablesLoaded = TRUE; - checkWearablesLoaded(); + // [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-09-22 (Catznip-2.2) if (!mInitialWearablesLoaded) { mInitialWearablesLoaded = true; + mInitialWearablesLoadedSignal(); } // [/SL:KB] notifyLoadingFinished(); - queryWearableCache(); - updateServer(); + + // Copy wearable params to avatar. + gAgentAvatarp->writeWearablesToAvatar(); + + // Then update the avatar based on the copied params. + gAgentAvatarp->updateVisualParams(); gAgentAvatarp->dumpAvatarTEs("setWearableOutfit"); @@ -1556,210 +1260,142 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it // User has picked "wear on avatar" from a menu. -/*void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append) -{ - //LLAgentDumper dumper("setWearableItem"); - if (isWearingItem(new_item->getUUID())) - { - LL_WARNS() << "wearable " << new_item->getUUID() << " is already worn" << LL_ENDL; - return; - } - - const LLWearableType::EType type = new_wearable->getType(); - -// [RLVa:KB] - Checked: 2010-03-19 (RLVa-1.2.0a) | Modified: RLVa-1.2.0g - // TODO-RLVa: [RLVa-1.2.1] This looks like dead code in SL-2.0.2 so we can't really check to see if it works :| - if (rlv_handler_t::isEnabled()) - { - ERlvWearMask eWear = gRlvWearableLocks.canWear(type); - if ( (RLV_WEAR_LOCKED == eWear) || ((!do_append) && (!(eWear & RLV_WEAR_REPLACE))) ) - return; - } -// [/RLVa:KB] - - if (!do_append) - { - // Remove old wearable, if any - // MULTI_WEARABLE: hardwired to 0 - LLViewerWearable* old_wearable = getViewerWearable(type,0); - if( old_wearable ) - { - const LLUUID& old_item_id = old_wearable->getItemID(); - if( (old_wearable->getAssetID() == new_wearable->getAssetID()) && - (old_item_id == new_item->getUUID()) ) - { - LL_DEBUGS() << "No change to wearable asset and item: " << LLWearableType::getTypeName( type ) << LL_ENDL; - return; - } - - if( old_wearable->isDirty() ) - { - // Bring up modal dialog: Save changes? Yes, No, Cancel - LLSD payload; - payload["item_id"] = new_item->getUUID(); - LLNotificationsUtil::add( "WearableSave", LLSD(), payload, boost::bind(onSetWearableDialog, _1, _2, new_wearable)); - return; - } - } - } - - setWearableFinal(new_item, new_wearable, do_append); -}*/ +//void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append) +//{ +// //LLAgentDumper dumper("setWearableItem"); +// if (isWearingItem(new_item->getUUID())) +// { +// LL_WARNS() << "wearable " << new_item->getUUID() << " is already worn" << LL_ENDL; +// return; +// } +// +// const LLWearableType::EType type = new_wearable->getType(); +// +// if (!do_append) +// { +// // Remove old wearable, if any +// // MULTI_WEARABLE: hardwired to 0 +// LLViewerWearable* old_wearable = getViewerWearable(type,0); +// if (old_wearable) +// { +// const LLUUID& old_item_id = old_wearable->getItemID(); +// if ((old_wearable->getAssetID() == new_wearable->getAssetID()) && +// (old_item_id == new_item->getUUID())) +// { +// LL_DEBUGS() << "No change to wearable asset and item: " << LLWearableType::getTypeName(type) << LL_ENDL; +// return; +// } +// +// if (old_wearable->isDirty()) +// { +// // Bring up modal dialog: Save changes? Yes, No, Cancel +// LLSD payload; +// payload["item_id"] = new_item->getUUID(); +// LLNotificationsUtil::add("WearableSave", LLSD(), payload, boost::bind(onSetWearableDialog, _1, _2, new_wearable)); +// return; +// } +// } +// } +// +// setWearableFinal(new_item, new_wearable, do_append); +//} // static -bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& response, LLViewerWearable* wearable) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - LLInventoryItem* new_item = gInventory.getItem( notification["payload"]["item_id"].asUUID()); - U32 index; - if (!gAgentWearables.getWearableIndex(wearable,index)) - { - LL_WARNS() << "Wearable not found" << LL_ENDL; - delete wearable; - return false; - } - if( !new_item ) - { - delete wearable; - return false; - } - - switch( option ) - { - case 0: // "Save" - gAgentWearables.saveWearable(wearable->getType(),index); - gAgentWearables.setWearableFinal( new_item, wearable ); - break; - - case 1: // "Don't Save" - gAgentWearables.setWearableFinal( new_item, wearable ); - break; - - case 2: // "Cancel" - break; - - default: - llassert(0); - break; - } - - delete wearable; - return false; -} +//bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& response, LLViewerWearable* wearable) +//{ +// S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +// LLInventoryItem* new_item = gInventory.getItem(notification["payload"]["item_id"].asUUID()); +// U32 index; +// if (!gAgentWearables.getWearableIndex(wearable,index)) +// { +// LL_WARNS() << "Wearable not found" << LL_ENDL; +// delete wearable; +// return false; +// } +// switch(option) +// { +// case 0: // "Save" +// gAgentWearables.saveWearable(wearable->getType(),index); +// gAgentWearables.setWearableFinal(new_item, wearable); +// break; +// +// case 1: // "Don't Save" +// gAgentWearables.setWearableFinal(new_item, wearable); +// break; +// +// case 2: // "Cancel" +// break; +// +// default: +// llassert(0); +// break; +// } +// +// delete wearable; +// return false; +//} // Called from setWearableItem() and onSetWearableDialog() to actually set the wearable. // MULTI_WEARABLE: unify code after null objects are gone. -void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append) -{ - const LLWearableType::EType type = new_wearable->getType(); - - if (do_append && getWearableItemID(type,0).notNull()) - { - new_wearable->setItemID(new_item->getUUID()); - const bool trigger_updated = false; - pushWearable(type, new_wearable, trigger_updated); - LL_INFOS() << "Added additional wearable for type " << type - << " size is now " << getWearableCount(type) << LL_ENDL; - checkWearableAgainstInventory(new_wearable); - } - else - { - // Replace the old wearable with a new one. - llassert(new_item->getAssetUUID() == new_wearable->getAssetID()); - - LLViewerWearable *old_wearable = getViewerWearable(type,0); - LLUUID old_item_id; - if (old_wearable) - { - old_item_id = old_wearable->getItemID(); - } - new_wearable->setItemID(new_item->getUUID()); - setWearable(type,0,new_wearable); - - if (old_item_id.notNull()) - { - gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id); - gInventory.notifyObservers(); - } - LL_INFOS() << "Replaced current element 0 for type " << type - << " size is now " << getWearableCount(type) << LL_ENDL; - } - - //LL_INFOS() << "LLVOAvatar::setWearableItem()" << LL_ENDL; - queryWearableCache(); - //new_wearable->writeToAvatar(TRUE); - - updateServer(); -} - -void LLAgentWearables::queryWearableCache() -{ - if (!areWearablesLoaded() || (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion())) - { - return; - } - - // Look up affected baked textures. - // If they exist: - // disallow updates for affected layersets (until dataserver responds with cache request.) - // If cache miss, turn updates back on and invalidate composite. - // If cache hit, modify baked texture entries. - // - // Cache requests contain list of hashes for each baked texture entry. - // Response is list of valid baked texture assets. (same message) - - gMessageSystem->newMessageFast(_PREHASH_AgentCachedTexture); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addS32Fast(_PREHASH_SerialNum, gAgentQueryManager.mWearablesCacheQueryID); - - S32 num_queries = 0; - for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ ) - { - LLUUID hash_id = computeBakedTextureHash((EBakedTextureIndex) baked_index); - if (hash_id.notNull()) - { - num_queries++; - // *NOTE: make sure at least one request gets packed - - ETextureIndex te_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); - - //LL_INFOS() << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << LL_ENDL; - gMessageSystem->nextBlockFast(_PREHASH_WearableData); - gMessageSystem->addUUIDFast(_PREHASH_ID, hash_id); - gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)te_index); - } - - gAgentQueryManager.mActiveCacheQueries[ baked_index ] = gAgentQueryManager.mWearablesCacheQueryID; - } - //VWR-22113: gAgent.getRegion() can return null if invalid, seen here on logout - if(gAgent.getRegion()) - { - if (isAgentAvatarValid()) - { - selfStartPhase("fetch_texture_cache_entries"); - gAgentAvatarp->outputRezTiming("Fetching textures from cache"); - } - - LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Requesting texture cache entry for " << num_queries << " baked textures" << LL_ENDL; - gMessageSystem->sendReliable(gAgent.getRegion()->getHost()); - gAgentQueryManager.mNumPendingQueries++; - gAgentQueryManager.mWearablesCacheQueryID++; - } -} - -// virtual -void LLAgentWearables::invalidateBakedTextureHash(LLMD5& hash) const -{ - // Add some garbage into the hash so that it becomes invalid. - if (isAgentAvatarValid()) - { - hash.update((const unsigned char*)gAgentAvatarp->getID().mData, UUID_BYTES); - } -} - -/// Given a desired set of attachments, find what objects need to be +//void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append) +//{ +// const LLWearableType::EType type = new_wearable->getType(); +// +// if (do_append && getWearableItemID(type,0).notNull()) +// { +// new_wearable->setItemID(new_item->getUUID()); +// const bool trigger_updated = false; +// pushWearable(type, new_wearable, trigger_updated); +// LL_INFOS() << "Added additional wearable for type " << type +// << " size is now " << getWearableCount(type) << LL_ENDL; +// checkWearableAgainstInventory(new_wearable); +// } +// else +// { +// // Replace the old wearable with a new one. +// llassert(new_item->getAssetUUID() == new_wearable->getAssetID()); +// +// LLViewerWearable *old_wearable = getViewerWearable(type,0); +// LLUUID old_item_id; +// if (old_wearable) +// { +// old_item_id = old_wearable->getItemID(); +// } +// new_wearable->setItemID(new_item->getUUID()); +// setWearable(type,0,new_wearable); +// +// if (old_item_id.notNull()) +// { +// gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id); +// gInventory.notifyObservers(); +// } +// LL_INFOS() << "Replaced current element 0 for type " << type +// << " size is now " << getWearableCount(type) << LL_ENDL; +// } +//} + +// User has picked "remove from avatar" from a menu. +// static +//void LLAgentWearables::userRemoveWearable(const LLWearableType::EType &type, const U32 &index) +//{ +// if (!(type==LLWearableType::WT_SHAPE || type==LLWearableType::WT_SKIN || type==LLWearableType::WT_HAIR || type==LLWearableType::WT_EYES)) //&& +// //!((!gAgent.isTeen()) && (type==LLWearableType::WT_UNDERPANTS || type==LLWearableType::WT_UNDERSHIRT))) +// { +// gAgentWearables.removeWearable(type,false,index); +// } +//} + +//static +//void LLAgentWearables::userRemoveWearablesOfType(const LLWearableType::EType &type) +//{ +// if (!(type==LLWearableType::WT_SHAPE || type==LLWearableType::WT_SKIN || type==LLWearableType::WT_HAIR || type==LLWearableType::WT_EYES)) //&& +// //!((!gAgent.isTeen()) && (type==LLWearableType::WT_UNDERPANTS || type==LLWearableType::WT_UNDERSHIRT))) +// { +// gAgentWearables.removeWearable(type,true,0); +// } +//} + +// Given a desired set of attachments, find what objects need to be // removed, and what additional inventory items need to be added. void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array_t& obj_item_array, llvo_vec_t& objects_to_remove, @@ -1773,8 +1409,8 @@ void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array if (!isAgentAvatarValid()) return; - std::set requested_item_ids; - std::set current_item_ids; + uuid_set_t requested_item_ids; + uuid_set_t current_item_ids; for (U32 i=0; igetLinkedUUID(); @@ -1859,7 +1495,7 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo itObj = objects_to_remove.erase(itObj); // Fall-back code: re-add the attachment if it got removed from COF somehow (compensates for possible bugs elsewhere) - bool fInCOF = LLAppearanceMgr::isLinkInCOF(pAttachObj->getAttachmentItemID()); + bool fInCOF = LLAppearanceMgr::instance().isLinkedInCOF(pAttachObj->getAttachmentItemID()); RLV_ASSERT(fInCOF); if (!fInCOF) { @@ -1877,6 +1513,7 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo if (objects_to_remove.empty()) return; + LL_DEBUGS("Avatar") << "ATT [ObjectDetach] removing " << objects_to_remove.size() << " objects" << LL_ENDL; gMessageSystem->newMessage("ObjectDetach"); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); @@ -1887,97 +1524,39 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo ++it) { LLViewerObject *objectp = *it; + //gAgentAvatarp->resetJointPositionsOnDetach(objectp); gMessageSystem->nextBlockFast(_PREHASH_ObjectData); gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); + const LLUUID& item_id = objectp->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT removing object, item is " << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; + LLAttachmentsMgr::instance().onDetachRequested(item_id); } gMessageSystem->sendReliable(gAgent.getRegionHost()); } void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array) { -// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1) - static bool sInitialAttachmentsRequested = false; - - // RELEASE-RLVa: [SL-3.4] Check our callers and verify that erasing elements from the passed vector won't break random things - if ( (rlv_handler_t::isEnabled()) && (sInitialAttachmentsRequested) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) ) - { - // Fall-back code: everything should really already have been pruned before we get this far - LLInventoryModel::item_array_t::size_type cntAttach = obj_item_array.size(); - obj_item_array.erase(std::remove_if(obj_item_array.begin(), obj_item_array.end(), RlvPredCanNotWearItem(RLV_WEAR)), obj_item_array.end()); - RLV_ASSERT(cntAttach == obj_item_array.size()); - } -// [/RLVa:KB] - // Build a compound message to send all the objects that need to be rezzed. S32 obj_count = obj_item_array.size(); - - // Limit number of packets to send - const S32 MAX_PACKETS_TO_SEND = 10; - const S32 OBJECTS_PER_PACKET = 4; - const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET; - if( obj_count > MAX_OBJECTS_TO_SEND ) + if (obj_count > 0) { - obj_count = MAX_OBJECTS_TO_SEND; + LL_DEBUGS("Avatar") << "ATT attaching multiple, total obj_count " << obj_count << LL_ENDL; } - - // Create an id to keep the parts of the compound message together - LLUUID compound_msg_id; - compound_msg_id.generate(); - LLMessageSystem* msg = gMessageSystem; - - for(S32 i = 0; i < obj_count; ++i) - { - if( 0 == (i % OBJECTS_PER_PACKET) ) - { - // Start a new message chunk - msg->newMessageFast(_PREHASH_RezMultipleAttachmentsFromInv); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_HeaderData); - msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id ); - msg->addU8Fast(_PREHASH_TotalObjects, obj_count ); - msg->addBOOLFast(_PREHASH_FirstDetachAll, false ); - } - const LLInventoryItem* item = obj_item_array.at(i).get(); - msg->nextBlockFast(_PREHASH_ObjectData ); - msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); - msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); - msg->addU8Fast(_PREHASH_AttachmentPt, ATTACHMENT_ADD); // Wear at the previous or default attachment point -// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1) - if ( (rlv_handler_t::isEnabled()) && (sInitialAttachmentsRequested) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) ) - { - RlvAttachmentLockWatchdog::instance().onWearAttachment(item, RLV_WEAR_ADD); - } -// [/RLVa:KB] - pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); - msg->addStringFast(_PREHASH_Name, item->getName()); - msg->addStringFast(_PREHASH_Description, item->getDescription()); - - if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) ) - { - // End of message chunk - msg->sendReliable( gAgent.getRegion()->getHost() ); - } - } + for(LLInventoryModel::item_array_t::const_iterator it = obj_item_array.begin(); + it != obj_item_array.end(); + ++it) + { + const LLInventoryItem* item = *it; + LLAttachmentsMgr::instance().addAttachmentRequest(item->getLinkedUUID(), 0, TRUE); + } // [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1) - sInitialAttachmentsRequested = true; + mInitialAttachmentsRequested = true; // [/RLVa:KB] } -void LLAgentWearables::checkWearablesLoaded() const -{ -#ifdef SHOW_ASSERT - U32 item_pend_count = itemUpdatePendingCount(); - if (mWearablesLoaded) - { - llassert(item_pend_count==0); - } -#endif -} - // Returns false if the given wearable is already topmost/bottommost // (depending on closer_to_body parameter). bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_body) const @@ -1994,20 +1573,9 @@ bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_bod BOOL LLAgentWearables::areWearablesLoaded() const { - checkWearablesLoaded(); return mWearablesLoaded; } -// MULTI-WEARABLE: DEPRECATED: item pending count relies on old messages that don't support multi-wearables. do not trust to be accurate -void LLAgentWearables::updateWearablesLoaded() -{ - mWearablesLoaded = (itemUpdatePendingCount()==0); - if (mWearablesLoaded) - { - notifyLoadingFinished(); - } -} - bool LLAgentWearables::canWearableBeRemoved(const LLViewerWearable* wearable) const { if (!wearable) return false; @@ -2088,6 +1656,12 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con { if (type == LLWearableType::WT_INVALID || type == LLWearableType::WT_NONE) return; + if (type == LLWearableType::WT_UNIVERSAL && !gAgent.getRegion()->bakesOnMeshEnabled()) + { + LL_WARNS("Inventory") << "Can't create WT_UNIVERSAL type " << LL_ENDL; + return; + } + LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp); LLAssetType::EType asset_type = wearable->getAssetType(); LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; @@ -2171,30 +1745,6 @@ void LLAgentWearables::editWearableIfRequested(const LLUUID& item_id) } } -void LLAgentWearables::updateServer() -{ - sendAgentWearablesUpdate(); - gAgent.sendAgentSetAppearance(); -} - -void LLAgentWearables::populateMyOutfitsFolder(void) -{ - LL_INFOS() << "starting outfit population" << LL_ENDL; - - const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch(my_outfits_id); - outfits->mMyOutfitsID = my_outfits_id; - - // Get the complete information on the items in the inventory and - // setup an observer that will wait for that to happen. - gInventory.addObserver(outfits); - outfits->startFetch(); - if (outfits->isFinished()) - { - outfits->done(); - } -} - boost::signals2::connection LLAgentWearables::addLoadingStartedCallback(loading_started_callback_t cb) { return mLoadingStartedSignal.connect(cb); @@ -2210,6 +1760,13 @@ bool LLAgentWearables::changeInProgress() const return mCOFChangeInProgress; } +// [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-08-14 (Catznip-2.1) +boost::signals2::connection LLAgentWearables::addInitialWearablesLoadedCallback(const loaded_callback_t& cb) +{ + return mInitialWearablesLoadedSignal.connect(cb); +} +// [/SL:KB] + void LLAgentWearables::notifyLoadingStarted() { mCOFChangeInProgress = true; diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 09284bda27..51825b9a29 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -42,7 +42,6 @@ class LLInventoryItem; class LLVOAvatarSelf; class LLViewerWearable; -class LLInitialWearablesFetch; class LLViewerObject; class LLAgentWearables : public LLInitClass, public LLWearableData @@ -62,9 +61,6 @@ class LLAgentWearables : public LLInitClass, public LLWearable // LLInitClass interface static void initClass(); -protected: - void createStandardWearablesDone(S32 type, U32 index/* = 0*/); - void createStandardWearablesAllDone(); //-------------------------------------------------------------------- // Queries @@ -76,9 +72,12 @@ class LLAgentWearables : public LLInitClass, public LLWearable BOOL isWearableCopyable(LLWearableType::EType type, U32 index /*= 0*/) const; BOOL areWearablesLoaded() const; -// [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-08-14 (Catznip-3.0.0a) | Added: Catznip-2.1.1d +// [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-08-14 (Catznip-2.1) bool areInitalWearablesLoaded() const { return mInitialWearablesLoaded; } // [/SL:KB] +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1) + bool areInitialAttachmentsRequested() const { return mInitialAttachmentsRequested; } +// [/RLVa:KB] bool isCOFChangeInProgress() const { return mCOFChangeInProgress; } F32 getCOFChangeTime() const { return mCOFChangeTimer.getElapsedTimeF32(); } void updateWearablesLoaded(); @@ -94,7 +93,7 @@ class LLAgentWearables : public LLInitClass, public LLWearable // Accessors //-------------------------------------------------------------------- public: -// [RLVa:KB] - Checked: 2011-03-31 (RLVa-1.3.0f) | Added: RLVa-1.3.0f +// [RLVa:KB] - Checked: 2011-03-31 (RLVa-1.3.0) void getWearableItemIDs(uuid_vec_t& idItems) const; void getWearableItemIDs(LLWearableType::EType eType, uuid_vec_t& idItems) const; // [/RLVa:KB] @@ -122,8 +121,8 @@ class LLAgentWearables : public LLInitClass, public LLWearable void addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index); protected: - void setWearableFinal(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append = false); - static bool onSetWearableDialog(const LLSD& notification, const LLSD& response, LLViewerWearable* wearable); +// void setWearableFinal(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append = false); +// static bool onSetWearableDialog(const LLSD& notification, const LLSD& response, LLViewerWearable* wearable); void addWearableToAgentInventory(LLPointer cb, LLViewerWearable* wearable, @@ -155,37 +154,18 @@ class LLAgentWearables : public LLInitClass, public LLWearable // Removing wearables //-------------------------------------------------------------------- public: - void removeWearable(const LLWearableType::EType type, bool do_remove_all /*= false*/, U32 index /*= 0*/); +// void removeWearable(const LLWearableType::EType type, bool do_remove_all /*= false*/, U32 index /*= 0*/); private: +// [RLVa:KB] - Checked: 2010-05-11 (RLVa-1.2.0) + void removeWearable(const LLWearableType::EType type, bool do_remove_all /*= false*/, U32 index /*= 0*/); +// [/RLVa:KB] void removeWearableFinal(const LLWearableType::EType type, bool do_remove_all /*= false*/, U32 index /*= 0*/); protected: static bool onRemoveWearableDialog(const LLSD& notification, const LLSD& response); - //-------------------------------------------------------------------- - // Server Communication - //-------------------------------------------------------------------- -public: - // Processes the initial wearables update message (if necessary, since the outfit folder makes it redundant) - static void processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data); - -protected: - - /*virtual*/ void invalidateBakedTextureHash(LLMD5& hash) const; - void sendAgentWearablesUpdate(); - void sendAgentWearablesRequest(); - void queryWearableCache(); - void updateServer(); - static void onInitialWearableAssetArrived(LLViewerWearable* wearable, void* userdata); - //-------------------------------------------------------------------- // Outfits //-------------------------------------------------------------------- -public: - - // Should only be called if we *know* we've never done so before, since users may - // not want the Library outfits to stay in their quick outfit selector and can delete them. - void populateMyOutfitsFolder(); - private: void makeNewOutfitDone(S32 type, U32 index); @@ -194,7 +174,7 @@ class LLAgentWearables : public LLInitClass, public LLWearable //-------------------------------------------------------------------- public: LLViewerWearable* saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, const std::string& description, BOOL save_in_lost_and_found); - void saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update = TRUE, + void saveWearable(const LLWearableType::EType type, const U32 index, const std::string new_name = ""); void saveAllWearables(); void revertWearable(const LLWearableType::EType type, const U32 index); @@ -220,9 +200,6 @@ class LLAgentWearables : public LLInitClass, public LLWearable static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array); static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array); - BOOL itemUpdatePending(const LLUUID& item_id) const; - U32 itemUpdatePendingCount() const; - //-------------------------------------------------------------------- // Signals //-------------------------------------------------------------------- @@ -234,6 +211,9 @@ class LLAgentWearables : public LLInitClass, public LLWearable typedef boost::function loaded_callback_t; typedef boost::signals2::signal loaded_signal_t; boost::signals2::connection addLoadedCallback(loaded_callback_t cb); +// [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-08-14 (Catznip-2.1) + boost::signals2::connection addInitialWearablesLoadedCallback(const loaded_callback_t& cb); +// [/SL:KB] bool changeInProgress() const; void notifyLoadingStarted(); @@ -242,17 +222,22 @@ class LLAgentWearables : public LLInitClass, public LLWearable private: loading_started_signal_t mLoadingStartedSignal; // should be called before wearables are changed loaded_signal_t mLoadedSignal; // emitted when all agent wearables get loaded +// [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-08-14 (Catznip-2.1) + loaded_signal_t mInitialWearablesLoadedSignal; // emitted once when the initial wearables are loaded +// [/SL:KB] //-------------------------------------------------------------------- // Member variables //-------------------------------------------------------------------- private: static BOOL mInitialWearablesUpdateReceived; -// [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-08-14 (Catznip-3.0.0a) | Added: Catznip-2.2.0a +// [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-08-14 (Catznip-2.2) static bool mInitialWearablesLoaded; // [/SL:KB] +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1) + static bool mInitialAttachmentsRequested; +// [/RLVa:KB] BOOL mWearablesLoaded; - std::set mItemsAwaitingWearableUpdate; /** * True if agent's outfit is being changed now. diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index d12d592cc8..dce3d22f61 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -267,21 +267,16 @@ void LLInitialWearablesFetch::processWearablesMessage() for (U8 i = 0; i < mAgentInitialWearables.size(); ++i) { // Populate the current outfit folder with links to the wearables passed in the message -// InitialWearableData *wearable_data = new InitialWearableData(mAgentInitialWearables[i]); // This will be deleted in the callback. -// [SL:KB] - Patch: Appearance-MixedViewers | Checked: 2010-05-02 (Catznip-3.0.0a) | Added: Catznip-2.0.0f - // Fixes minor leak: since COF is used onInitialWearableAssetArrived() will never get called and "wearable_data" leaks - InitialWearableData* wearable_data = &mAgentInitialWearables[i]; -// [/SL:KB] + const InitialWearableData& wearable_data = mAgentInitialWearables[i]; - if (wearable_data->mAssetID.notNull()) + if (wearable_data.mAssetID.notNull()) { - ids.push_back(wearable_data->mItemID); + ids.push_back(wearable_data.mItemID); } else { - LL_INFOS() << "Invalid wearable, type " << wearable_data->mType << " itemID " - << wearable_data->mItemID << " assetID " << wearable_data->mAssetID << LL_ENDL; -// delete wearable_data; + LL_INFOS() << "Invalid wearable, type " << wearable_data.mType << " itemID " + << wearable_data.mItemID << " assetID " << wearable_data.mAssetID << LL_ENDL; } } diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 257cc628c8..c786308bed 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -40,300 +40,427 @@ /// Classes for AISv3 support. ///---------------------------------------------------------------------------- -// AISCommand - base class for retry-able HTTP requests using the AISv3 cap. -AISCommand::AISCommand(LLPointer callback): - mCommandFunc(NULL), - mCallback(callback) -{ - mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10); -} +extern AIHTTPTimeoutPolicy AISAPIResponder_timeout; -bool AISCommand::run_command() +class AISCommand final : public LLHTTPClient::ResponderWithCompleted { - if (NULL == mCommandFunc) - { - // This may happen if a command failed to initiate itself. - LL_WARNS("Inventory") << "AIS command attempted with null command function" << LL_ENDL; - return false; - } - else +public: + typedef boost::function command_func_type; + // AISCommand - base class for retry-able HTTP requests using the AISv3 cap. + + // Limit max in flight requests to 2. Server was aggressively throttling otherwise. + constexpr static U8 sMaxActiveAISCommands = 4; + static U8 sActiveAISCommands; + static std::queue< boost::intrusive_ptr< AISCommand > > sPendingAISCommands; + + virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return AISAPIResponder_timeout; } + + AISCommand(AISAPI::COMMAND_TYPE type, const char* name, const LLUUID& targetId, AISAPI::completion_t callback) : + mCommandFunc(NULL), + mRetryPolicy(new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10)), + mCompletionFunc(callback), + mTargetId(targetId), + mName(name), + mType(type) + {} + virtual ~AISCommand() { - mCommandFunc(); - return true; + if (mActive) + { + --sActiveAISCommands; + while (sActiveAISCommands < sMaxActiveAISCommands && !sPendingAISCommands.empty()) + { + sPendingAISCommands.front()->dispatch(); + sPendingAISCommands.pop(); + } + } } -} -void AISCommand::setCommandFunc(command_func_type command_func) -{ - mCommandFunc = command_func; -} - -// virtual -bool AISCommand::getResponseUUID(const LLSD& content, LLUUID& id) -{ - return false; -} - -/* virtual */ -void AISCommand::httpSuccess() -{ - // Command func holds a reference to self, need to release it - // after a success or final failure. - setCommandFunc(no_op); - - const LLSD& content = getContent(); - if (!content.isMap()) + void run( command_func_type func ) { - failureResult(400, "Malformed response contents", content); - return; + mCommandFunc = func; + if (sActiveAISCommands >= sMaxActiveAISCommands) + { + sPendingAISCommands.push(this); + } + else + { + dispatch(); + } } - mRetryPolicy->onSuccess(); - - gInventory.onAISUpdateReceived("AISCommand", content); - if (mCallback) + char const* getName(void) const override { - LLUUID id; // will default to null if parse fails. - getResponseUUID(content,id); - mCallback->fire(id); + return mName; } -} -/*virtual*/ -void AISCommand::httpFailure() -{ - LL_WARNS("Inventory") << dumpResponse() << LL_ENDL; - S32 status = getStatus(); - const AIHTTPReceivedHeaders& headers = getResponseHeaders(); - mRetryPolicy->onFailure(status, headers); - F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(seconds_to_wait)) +private: + void dispatch() { - doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait); + if (LLApp::isQuitting()) + { + return; + } + ++sActiveAISCommands; + mActive = true; + (mCommandFunc)(); } - else + void markComplete() { // Command func holds a reference to self, need to release it // after a success or final failure. - // *TODO: Notify user? This seems bad. - setCommandFunc(no_op); + mCommandFunc = no_op; + mRetryPolicy->onSuccess(); } -} -//static -bool AISCommand::isAPIAvailable() -{ - if (gAgent.getRegion()) + bool onFailure() { - return gAgent.getRegion()->isCapabilityAvailable("InventoryAPIv3"); + mRetryPolicy->onFailure(mStatus, getResponseHeaders()); + F32 seconds_to_wait; + if (mRetryPolicy->shouldRetry(seconds_to_wait)) + { + if (mStatus == 503) + { + // Pad delay a bit more since we're getting throttled. + seconds_to_wait += 10.f + ll_frand(4.f); + } + LL_WARNS("Inventory") << "Retrying in " << seconds_to_wait << "seconds due to inventory error for " << getName() <<": " << dumpResponse() << LL_ENDL; + doAfterInterval(mCommandFunc,seconds_to_wait); + return true; + } + else + { + // Command func holds a reference to self, need to release it + // after a success or final failure. + // *TODO: Notify user? This seems bad. + LL_WARNS("Inventory") << "Abort due to inventory error for " << getName() <<": " << dumpResponse() << LL_ENDL; + mCommandFunc = no_op; + return false; + } } - return false; -} -//static -bool AISCommand::getInvCap(std::string& cap) -{ - if (gAgent.getRegion()) - { - cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); - } - if (!cap.empty()) +protected: + void httpCompleted() override { - return true; + // Continue through if successful or longer retrying, + if (isGoodStatus(mStatus) || !onFailure()) + { + markComplete(); + AISAPI::InvokeAISCommandCoro(this, getURL(), mTargetId, getContent(), mCompletionFunc, (AISAPI::COMMAND_TYPE)mType); + } } - return false; -} -//static -bool AISCommand::getLibCap(std::string& cap) +private: + command_func_type mCommandFunc; + LLPointer mRetryPolicy; + AISAPI::completion_t mCompletionFunc; + const LLUUID mTargetId; + const char* mName; + bool mActive = false; + AISAPI::COMMAND_TYPE mType; +}; + +U8 AISCommand::sActiveAISCommands = 0; +std::queue< boost::intrusive_ptr< AISCommand > > AISCommand::sPendingAISCommands; + +//========================================================================= +const std::string AISAPI::INVENTORY_CAP_NAME("InventoryAPIv3"); +const std::string AISAPI::LIBRARY_CAP_NAME("LibraryAPIv3"); + +//------------------------------------------------------------------------- +/*static*/ +bool AISAPI::isAvailable() { if (gAgent.getRegion()) { - cap = gAgent.getRegion()->getCapability("LibraryAPIv3"); - } - if (!cap.empty()) - { - return true; + return gAgent.getRegion()->isCapabilityAvailable(INVENTORY_CAP_NAME); } return false; } -//static -void AISCommand::getCapabilityNames(LLSD& capabilityNames) +/*static*/ +void AISAPI::getCapNames(LLSD& capNames) { - capabilityNames.append("InventoryAPIv3"); - capabilityNames.append("LibraryAPIv3"); + capNames.append(INVENTORY_CAP_NAME); + capNames.append(LIBRARY_CAP_NAME); } -RemoveItemCommand::RemoveItemCommand(const LLUUID& item_id, - LLPointer callback): - AISCommand(callback) +/*static*/ +std::string AISAPI::getInvCap() { - std::string cap; - if (!getInvCap(cap)) - { - LL_WARNS() << "No cap found" << LL_ENDL; - return; - } - std::string url = cap + std::string("/item/") + item_id.asString(); - LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; - LLHTTPClient::ResponderPtr responder = this; - command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off)); - setCommandFunc(cmd); + if (gAgent.getRegion()) + { + return gAgent.getRegion()->getCapability(INVENTORY_CAP_NAME); + } + return std::string(); } -RemoveCategoryCommand::RemoveCategoryCommand(const LLUUID& item_id, - LLPointer callback): - AISCommand(callback) +/*static*/ +std::string AISAPI::getLibCap() { - std::string cap; - if (!getInvCap(cap)) - { - LL_WARNS() << "No cap found" << LL_ENDL; - return; - } - std::string url = cap + std::string("/category/") + item_id.asString(); - LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; - LLHTTPClient::ResponderPtr responder = this; - command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off)); - setCommandFunc(cmd); + if (gAgent.getRegion()) + { + return gAgent.getRegion()->getCapability(LIBRARY_CAP_NAME); + } + return std::string(); } -PurgeDescendentsCommand::PurgeDescendentsCommand(const LLUUID& item_id, - LLPointer callback): - AISCommand(callback) +/*static*/ +void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, completion_t callback) { - std::string cap; - if (!getInvCap(cap)) - { - LL_WARNS() << "No cap found" << LL_ENDL; - return; - } - std::string url = cap + std::string("/category/") + item_id.asString() + "/children"; + std::string cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + + LLUUID tid; + tid.generate(); + + std::string url = cap + std::string("/category/") + parentId.asString() + "?tid=" + tid.asString(); LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; - LLHTTPClient::ResponderPtr responder = this; - command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off)); - setCommandFunc(cmd); + + boost::intrusive_ptr< AISCommand > responder = new AISCommand(COPYINVENTORY, "CreateInventory",parentId, callback); + responder->run(boost::bind(&LLHTTPClient::post, url, newInventory, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0)); } -UpdateItemCommand::UpdateItemCommand(const LLUUID& item_id, - const LLSD& updates, - LLPointer callback): - mUpdates(updates), - AISCommand(callback) +/*static*/ +void AISAPI::SlamFolder(const LLUUID& folderId, const LLSD& newInventory, completion_t callback) { - std::string cap; - if (!getInvCap(cap)) - { - LL_WARNS() << "No cap found" << LL_ENDL; - return; - } - std::string url = cap + std::string("/item/") + item_id.asString(); - LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; - LL_DEBUGS("Inventory") << "request: " << ll_pretty_print_sd(mUpdates) << LL_ENDL; - LLHTTPClient::ResponderPtr responder = this; + std::string cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + + LLUUID tid; + tid.generate(); + + std::string url = cap + std::string("/category/") + folderId.asString() + "/links?tid=" + tid.asString(); + AIHTTPHeaders headers; headers.addHeader("Content-Type", "application/llsd+xml"); - command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0); - setCommandFunc(cmd); + boost::intrusive_ptr< AISCommand > responder = new AISCommand(SLAMFOLDER, "SlamFolder", folderId, callback); + responder->run(boost::bind(&LLHTTPClient::put, url, newInventory, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug_off))); + } -UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& cat_id, - const LLSD& updates, - LLPointer callback): - mUpdates(updates), - AISCommand(callback) +void AISAPI::RemoveCategory(const LLUUID &categoryId, completion_t callback) { - std::string cap; - if (!getInvCap(cap)) - { - LL_WARNS() << "No cap found" << LL_ENDL; - return; - } - std::string url = cap + std::string("/category/") + cat_id.asString(); - LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; - LLHTTPClient::ResponderPtr responder = this; - AIHTTPHeaders headers; - headers.addHeader("Content-Type", "application/llsd+xml"); - command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0); - setCommandFunc(cmd); + std::string cap; + + cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + + std::string url = cap + std::string("/category/") + categoryId.asString(); + LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; + + boost::intrusive_ptr< AISCommand > responder = new AISCommand(REMOVECATEGORY, "RemoveCategory",categoryId, callback); + responder->run(boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off))); } -CreateInventoryCommand::CreateInventoryCommand(const LLUUID& parent_id, - const LLSD& new_inventory, - LLPointer callback): - mNewInventory(new_inventory), - AISCommand(callback) +/*static*/ +void AISAPI::RemoveItem(const LLUUID &itemId, completion_t callback) { - std::string cap; - if (!getInvCap(cap)) - { - LL_WARNS() << "No cap found" << LL_ENDL; - return; - } - LLUUID tid; - tid.generate(); - std::string url = cap + std::string("/category/") + parent_id.asString() + "?tid=" + tid.asString(); - LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; - LLHTTPClient::ResponderPtr responder = this; - AIHTTPHeaders headers; - headers.addHeader("Content-Type", "application/llsd+xml"); - command_func_type cmd = boost::bind(&LLHTTPClient::post, url, mNewInventory, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0); - setCommandFunc(cmd); + std::string cap; + + cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + + std::string url = cap + std::string("/item/") + itemId.asString(); + LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; + + boost::intrusive_ptr< AISCommand > responder = new AISCommand(REMOVEITEM,"RemoveItem",itemId, callback); + responder->run(boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off))); } -SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer callback): - mContents(contents), - AISCommand(callback) +void AISAPI::CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback) { - std::string cap; - if (!getInvCap(cap)) - { - LL_WARNS() << "No cap found" << LL_ENDL; - return; - } - LLUUID tid; - tid.generate(); - std::string url = cap + std::string("/category/") + folder_id.asString() + "/links?tid=" + tid.asString(); - LL_INFOS() << url << LL_ENDL; - LLHTTPClient::ResponderPtr responder = this; - AIHTTPHeaders headers; - headers.addHeader("Content-Type", "application/llsd+xml"); - command_func_type cmd = boost::bind(&LLHTTPClient::put, url, mContents, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug_off)); - setCommandFunc(cmd); + std::string cap; + + cap = getLibCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Library cap not found!" << LL_ENDL; + return; + } + + LL_DEBUGS("Inventory") << "Copying library category: " << sourceId << " => " << destId << LL_ENDL; + + LLUUID tid; + tid.generate(); + + std::string url = cap + std::string("/category/") + sourceId.asString() + "?tid=" + tid.asString(); + if (!copySubfolders) + { + url += ",depth=0"; + } + LL_INFOS() << url << LL_ENDL; + + std::string destination = destId.asString(); + + boost::intrusive_ptr< AISCommand > responder = new AISCommand(COPYLIBRARYCATEGORY, "CopyLibraryCategory",destId, callback); + responder->run(boost::bind(&LLHTTPClient::copy, url, destination, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off))); + +} + +/*static*/ +void AISAPI::PurgeDescendents(const LLUUID &categoryId, completion_t callback) +{ + std::string cap; + + cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + + std::string url = cap + std::string("/category/") + categoryId.asString() + "/children"; + LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; + + boost::intrusive_ptr< AISCommand > responder = new AISCommand(PURGEDESCENDENTS, "PurgeDescendents",categoryId, callback); + responder->run(boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off))); } -CopyLibraryCategoryCommand::CopyLibraryCategoryCommand(const LLUUID& source_id, - const LLUUID& dest_id, - LLPointer callback): - AISCommand(callback) +/*static*/ +void AISAPI::UpdateCategory(const LLUUID &categoryId, const LLSD &updates, completion_t callback) { - std::string cap; - if (!getLibCap(cap)) - { - LL_WARNS() << "No cap found" << LL_ENDL; - return; - } - LL_DEBUGS("Inventory") << "Copying library category: " << source_id << " => " << dest_id << LL_ENDL; - LLUUID tid; - tid.generate(); - std::string url = cap + std::string("/category/") + source_id.asString() + "?tid=" + tid.asString(); - LL_INFOS() << url << LL_ENDL; - LLHTTPClient::ResponderPtr responder = this; - command_func_type cmd = boost::bind(&LLHTTPClient::copy, url, dest_id.asString(), responder); - setCommandFunc(cmd); + std::string cap; + + cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + std::string url = cap + std::string("/category/") + categoryId.asString(); + + boost::intrusive_ptr< AISCommand > responder = new AISCommand(UPDATECATEGORY, "UpdateCategory",categoryId, callback); + responder->run(boost::bind(&LLHTTPClient::patch, url, updates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0)); } -bool CopyLibraryCategoryCommand::getResponseUUID(const LLSD& content, LLUUID& id) +/*static*/ +void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback) +{ + + std::string cap; + + cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + std::string url = cap + std::string("/item/") + itemId.asString(); + + boost::intrusive_ptr< AISCommand > responder = new AISCommand(UPDATEITEM, "UpdateItem",itemId, callback); + responder->run(boost::bind(&LLHTTPClient::patch, url, updates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0)); +} +void AISAPI::InvokeAISCommandCoro(LLHTTPClient::ResponderWithCompleted* responder, + std::string url, + LLUUID targetId, LLSD result, completion_t callback, COMMAND_TYPE type) { - if (content.has("category_id")) + LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; + + auto status = responder->getStatus(); + + if (!responder->isGoodStatus(status) || !result.isMap()) + { + LL_WARNS("Inventory") << "Inventory error: " << status << ": " << responder->getReason() << LL_ENDL; + if (status == 410) //GONE + { + // Item does not exist or was already deleted from server. + // parent folder is out of sync + if (type == REMOVECATEGORY) + { + LLViewerInventoryCategory *cat = gInventory.getCategory(targetId); + if (cat) + { + LL_WARNS("Inventory") << "Purge failed for '" << cat->getName() + << "' local version:" << cat->getVersion() + << " since folder no longer exists at server. Descendent count: server == " << cat->getDescendentCount() + << ", viewer == " << cat->getViewerDescendentCount() + << LL_ENDL; + gInventory.fetchDescendentsOf(cat->getParentUUID()); + // Note: don't delete folder here - contained items will be deparented (or deleted) + // and since we are clearly out of sync we can't be sure we won't get rid of something we need. + // For example folder could have been moved or renamed with items intact, let it fetch first. + } + } + else if (type == REMOVEITEM) + { + LLViewerInventoryItem *item = gInventory.getItem(targetId); + if (item) + { + LL_WARNS("Inventory") << "Purge failed for '" << item->getName() + << "' since item no longer exists at server." << LL_ENDL; + gInventory.fetchDescendentsOf(item->getParentUUID()); + // since item not on the server and exists at viewer, so it needs an update at the least, + // so delete it, in worst case item will be refetched with new params. + gInventory.onObjectDeletedFromServer(targetId); + } + } + } + if (!result.isMap()) + { + LL_WARNS("Inventory") << "Inventory error: Malformed response contents" << LL_ENDL; + } + LL_WARNS("Inventory") << ll_pretty_print_sd(result) << LL_ENDL; + } + + gInventory.onAISUpdateReceived("AISCommand", result); + + if (callback && callback != nullptr) { - id = content["category_id"]; - return true; +// [SL:KB] - Patch: Appearance-SyncAttach | Checked: Catznip-3.7 + uuid_list_t ids; + switch (type) + { + case COPYLIBRARYCATEGORY: + if (result.has("category_id")) + { + ids.insert(result["category_id"]); + } + break; + case COPYINVENTORY: + { + AISUpdate::parseUUIDArray(result, "_created_items", ids); + AISUpdate::parseUUIDArray(result, "_created_categories", ids); + } + break; + default: + break; + } + + // If we were feeling daring we'd call LLInventoryCallback::fire for every item but it would take additional work to investigate whether all LLInventoryCallback derived classes + // were designed to handle multiple fire calls (with legacy link creation only one would ever fire per link creation) so we'll be cautious and only call for the first one for now + // (note that the LL code as written below will always call fire once with the NULL UUID for anything but CopyLibraryCategoryCommand so even the above is an improvement) + callback( (!ids.empty()) ? *ids.begin() : LLUUID::null); +// [/SL:KB] +// LLUUID id(LLUUID::null); +// +// if (result.has("category_id") && (type == COPYLIBRARYCATEGORY)) +// { +// id = result["category_id"]; +// } +// +// callback(id); } - return false; + } +//------------------------------------------------------------------------- AISUpdate::AISUpdate(const LLSD& update) { parseUpdate(update); @@ -365,18 +492,17 @@ void AISUpdate::parseMeta(const LLSD& update) // parse _categories_removed -> mObjectsDeletedIds uuid_list_t cat_ids; parseUUIDArray(update,"_categories_removed",cat_ids); - for (uuid_list_t::const_iterator it = cat_ids.begin(); - it != cat_ids.end(); ++it) + for (auto cat_id : cat_ids) { - LLViewerInventoryCategory *cat = gInventory.getCategory(*it); + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); if(cat) { mCatDescendentDeltas[cat->getParentUUID()]--; - mObjectsDeletedIds.insert(*it); + mObjectsDeletedIds.insert(cat_id); } else { - LL_WARNS("Inventory") << "removed category not found " << *it << LL_ENDL; + LL_WARNS("Inventory") << "removed category not found " << cat_id << LL_ENDL; } } @@ -384,36 +510,34 @@ void AISUpdate::parseMeta(const LLSD& update) uuid_list_t item_ids; parseUUIDArray(update,"_category_items_removed",item_ids); parseUUIDArray(update,"_removed_items",item_ids); - for (uuid_list_t::const_iterator it = item_ids.begin(); - it != item_ids.end(); ++it) + for (auto item_id : item_ids) { - LLViewerInventoryItem *item = gInventory.getItem(*it); + LLViewerInventoryItem *item = gInventory.getItem(item_id); if(item) { mCatDescendentDeltas[item->getParentUUID()]--; - mObjectsDeletedIds.insert(*it); + mObjectsDeletedIds.insert(item_id); } else { - LL_WARNS("Inventory") << "removed item not found " << *it << LL_ENDL; + LL_WARNS("Inventory") << "removed item not found " << item_id << LL_ENDL; } } // parse _broken_links_removed -> mObjectsDeletedIds uuid_list_t broken_link_ids; parseUUIDArray(update,"_broken_links_removed",broken_link_ids); - for (uuid_list_t::const_iterator it = broken_link_ids.begin(); - it != broken_link_ids.end(); ++it) + for (auto broken_link_id : broken_link_ids) { - LLViewerInventoryItem *item = gInventory.getItem(*it); + LLViewerInventoryItem *item = gInventory.getItem(broken_link_id); if(item) { mCatDescendentDeltas[item->getParentUUID()]--; - mObjectsDeletedIds.insert(*it); + mObjectsDeletedIds.insert(broken_link_id); } else { - LL_WARNS("Inventory") << "broken link not found " << *it << LL_ENDL; + LL_WARNS("Inventory") << "broken link not found " << broken_link_id << LL_ENDL; } } @@ -550,13 +674,25 @@ void AISUpdate::parseCategory(const LLSD& category_map) parseDescendentCount(category_id, category_map["_embedded"]); } - LLPointer new_cat(new LLViewerInventoryCategory(category_id)); + LLPointer new_cat; LLViewerInventoryCategory *curr_cat = gInventory.getCategory(category_id); if (curr_cat) { // Default to current values where not provided. - new_cat->copyViewerCategory(curr_cat); + new_cat = new LLViewerInventoryCategory(curr_cat); } + else + { + if (category_map.has("agent_id")) + { + new_cat = new LLViewerInventoryCategory(category_map["agent_id"].asUUID()); + } + else + { + LL_DEBUGS() << "No owner provided, folder might be assigned wrong owner" << LL_ENDL; + new_cat = new LLViewerInventoryCategory(LLUUID::null); + } + } BOOL rv = new_cat->unpackMessage(category_map); // *NOTE: unpackMessage does not unpack version or descendent count. //if (category_map.has("version")) @@ -651,11 +787,9 @@ void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uui { if (content.has(name)) { - for(LLSD::array_const_iterator it = content[name].beginArray(), - end = content[name].endArray(); - it != end; ++it) + for (auto& id : content[name].array()) { - ids.insert((*it).asUUID()); + ids.insert(id.asUUID()); } } } @@ -745,11 +879,11 @@ void AISUpdate::parseEmbeddedCategories(const LLSD& categories) void AISUpdate::doUpdate() { - // Do version/descendent accounting. + // Do version/descendant accounting. for (std::map::const_iterator catit = mCatDescendentDeltas.begin(); catit != mCatDescendentDeltas.end(); ++catit) { - LL_DEBUGS("Inventory") << "descendent accounting for " << catit->first << LL_ENDL; + LL_DEBUGS("Inventory") << "descendant accounting for " << catit->first << LL_ENDL; const LLUUID cat_id(catit->first); // Don't account for update if we just created this category. @@ -766,13 +900,13 @@ void AISUpdate::doUpdate() continue; } - // If we have a known descendent count, set that now. + // If we have a known descendant count, set that now. LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); if (cat) { S32 descendent_delta = catit->second; S32 old_count = cat->getDescendentCount(); - LL_DEBUGS("Inventory") << "Updating descendent count for " + LL_DEBUGS("Inventory") << "Updating descendant count for " << cat->getName() << " " << cat_id << " with delta " << descendent_delta << " from " << old_count << " to " << (old_count+descendent_delta) << LL_ENDL; @@ -803,7 +937,7 @@ void AISUpdate::doUpdate() LLUUID category_id(update_it->first); LLPointer new_category = update_it->second; // Since this is a copy of the category *before* the accounting update, above, - // we need to transfer back the updated version/descendent count. + // we need to transfer back the updated version/descendant count. LLViewerInventoryCategory* curr_cat = gInventory.getCategory(new_category->getUUID()); if (!curr_cat) { @@ -847,28 +981,44 @@ void AISUpdate::doUpdate() } // DELETE OBJECTS - for (uuid_list_t::const_iterator del_it = mObjectsDeletedIds.begin(); - del_it != mObjectsDeletedIds.end(); ++del_it) + for (auto deleted_id : mObjectsDeletedIds) { - LL_INFOS("Inventory") << "deleted item " << *del_it << LL_ENDL; - gInventory.onObjectDeletedFromServer(*del_it, false, false, false); + LL_DEBUGS("Inventory") << "deleted item " << deleted_id << LL_ENDL; + gInventory.onObjectDeletedFromServer(deleted_id, false, false, false); } // TODO - how can we use this version info? Need to be sure all // changes are going through AIS first, or at least through // something with a reliable responder. - for (uuid_int_map_t::iterator ucv_it = mCatVersionsUpdated.begin(); - ucv_it != mCatVersionsUpdated.end(); ++ucv_it) + for (auto& ucv_it : mCatVersionsUpdated) { - const LLUUID id = ucv_it->first; - S32 version = ucv_it->second; + const LLUUID id = ucv_it.first; + S32 version = ucv_it.second; LLViewerInventoryCategory *cat = gInventory.getCategory(id); LL_DEBUGS("Inventory") << "cat version update " << cat->getName() << " to version " << cat->getVersion() << LL_ENDL; if (cat->getVersion() != version) { LL_WARNS() << "Possible version mismatch for category " << cat->getName() << ", viewer version " << cat->getVersion() - << " server version " << version << LL_ENDL; + << " AIS version " << version << " !!!Adjusting local version!!!" << LL_ENDL; + + // the AIS version should be considered the true version. Adjust + // our local category model to reflect this version number. Otherwise + // it becomes possible to get stuck with the viewer being out of + // sync with the inventory system. Under normal circumstances + // inventory COF is maintained on the viewer through calls to + // LLInventoryModel::accountForUpdate when a changing operation + // is performed. This occasionally gets out of sync however. + if (version != LLViewerInventoryCategory::VERSION_UNKNOWN) + { + cat->setVersion(version); + } + else + { + // We do not account for update if version is UNKNOWN, so we shouldn't rise version + // either or viewer will get stuck on descendants count -1, try to refetch folder instead + cat->fetch(); + } } } diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 3225630ec3..7fc247779a 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -36,118 +36,45 @@ #include "llhttpretrypolicy.h" #include "llviewerinventory.h" -class AISCommand: public LLHTTPClient::ResponderWithResult +class AISAPI { + friend class AISCommand; public: - typedef boost::function command_func_type; + typedef std::function completion_t; - AISCommand(LLPointer callback); + static bool isAvailable(); + static void getCapNames(LLSD& capNames); - virtual ~AISCommand() {} + static void CreateInventory(const LLUUID& parentId, const LLSD& newInventory, completion_t callback = completion_t()); + static void SlamFolder(const LLUUID& folderId, const LLSD& newInventory, completion_t callback = completion_t()); + static void RemoveCategory(const LLUUID &categoryId, completion_t callback = completion_t()); + static void RemoveItem(const LLUUID &itemId, completion_t callback = completion_t()); + static void PurgeDescendents(const LLUUID &categoryId, completion_t callback = completion_t()); + static void UpdateCategory(const LLUUID &categoryId, const LLSD &updates, completion_t callback = completion_t()); + static void UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback = completion_t()); + static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t()); - bool run_command(); - - void setCommandFunc(command_func_type command_func); +private: + typedef enum { + COPYINVENTORY, + SLAMFOLDER, + REMOVECATEGORY, + REMOVEITEM, + PURGEDESCENDENTS, + UPDATECATEGORY, + UPDATEITEM, + COPYLIBRARYCATEGORY + } COMMAND_TYPE; + + static const std::string INVENTORY_CAP_NAME; + static const std::string LIBRARY_CAP_NAME; - // Need to do command-specific parsing to get an id here, for - // LLInventoryCallback::fire(). May or may not need to bother, - // since most LLInventoryCallbacks do their work in the - // destructor. + static std::string getInvCap(); + static std::string getLibCap(); - /* virtual */ void httpSuccess(); - /* virtual */ void httpFailure(); - - static bool isAPIAvailable(); - static bool getInvCap(std::string& cap); - static bool getLibCap(std::string& cap); - static void getCapabilityNames(LLSD& capabilityNames); - -protected: - virtual bool getResponseUUID(const LLSD& content, LLUUID& id); - -private: - command_func_type mCommandFunc; - LLPointer mRetryPolicy; - LLPointer mCallback; -}; - -class RemoveItemCommand: public AISCommand -{ -public: - RemoveItemCommand(const LLUUID& item_id, - LLPointer callback); - /* virtual */ const char* getName() const { return "RemoveItemCommand"; } -}; - -class RemoveCategoryCommand: public AISCommand -{ -public: - RemoveCategoryCommand(const LLUUID& item_id, - LLPointer callback); - /* virtual */ const char* getName() const { return "RemoveCategoryCommand"; } -}; - -class PurgeDescendentsCommand: public AISCommand -{ -public: - PurgeDescendentsCommand(const LLUUID& item_id, - LLPointer callback); - /* virtual */ const char* getName() const { return "PurgeDescendentsCommand"; } - -}; - -class UpdateItemCommand: public AISCommand -{ -public: - UpdateItemCommand(const LLUUID& item_id, - const LLSD& updates, - LLPointer callback); - /* virtual */ const char* getName() const { return "UpdateItemCommand"; } - -private: - LLSD mUpdates; -}; - -class UpdateCategoryCommand: public AISCommand -{ -public: - UpdateCategoryCommand(const LLUUID& cat_id, - const LLSD& updates, - LLPointer callback); - /* virtual */ const char* getName() const { return "UpdateCategoryCommand"; } - -private: - LLSD mUpdates; -}; - -class SlamFolderCommand: public AISCommand -{ -public: - SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer callback); - /* virtual */ const char* getName() const { return "SlamFolderCommand"; } - -private: - LLSD mContents; -}; - -class CopyLibraryCategoryCommand: public AISCommand -{ -public: - CopyLibraryCategoryCommand(const LLUUID& source_id, const LLUUID& dest_id, LLPointer callback); - /* virtual */ const char* getName() const { return "CopyLibraryCategoryCommand"; } - -protected: - /* virtual */ bool getResponseUUID(const LLSD& content, LLUUID& id); -}; - -class CreateInventoryCommand: public AISCommand -{ -public: - CreateInventoryCommand(const LLUUID& parent_id, const LLSD& new_inventory, LLPointer callback); - /* virtual */ const char* getName() const { return "CreateInventoryCommand"; } - -private: - LLSD mNewInventory; + static void InvokeAISCommandCoro(LLHTTPClient::ResponderWithCompleted* responder, + std::string url, LLUUID targetId, LLSD body, + completion_t callback, COMMAND_TYPE type); }; class AISUpdate @@ -157,7 +84,10 @@ class AISUpdate void parseUpdate(const LLSD& update); void parseMeta(const LLSD& update); void parseContent(const LLSD& update); - void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids); +// [SL:KB] - Patch: Appearance-SyncAttach | Checked: Catznip-3.7 + static void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids); +// [/SL:KB] +// void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids); void parseLink(const LLSD& link_map); void parseItem(const LLSD& link_map); void parseCategory(const LLSD& link_map); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 3fb7073cf7..ebda2b1202 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -26,7 +26,6 @@ #include "llviewerprecompiledheaders.h" -#include #include "llagent.h" #include "llagentcamera.h" #include "llagentwearables.h" @@ -34,6 +33,7 @@ #include "llattachmentsmgr.h" #include "llcommandhandler.h" #include "lleventtimer.h" +#include "llfloatercustomize.h" #include "llgesturemgr.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" @@ -53,13 +53,18 @@ #include "llhttpretrypolicy.h" #include "llaisapi.h" #include "llinventorypanel.h" -#include "llfloatercustomize.h" -// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1) #include "rlvhandler.h" #include "rlvhelper.h" #include "rlvlocks.h" // [/RLVa:KB] +void doAppearanceCb(LLPointer cb, LLUUID id) +{ + if (cb.notNull()) + cb->fire(id); +} + std::string self_av_string() { // On logout gAgentAvatarp can already be invalid @@ -458,7 +463,7 @@ class LLWearCategoryAfterCopy: public LLInventoryCallback class LLTrackPhaseWrapper : public LLInventoryCallback { public: - LLTrackPhaseWrapper(const std::string& phase_name, LLPointer cb = NULL): + LLTrackPhaseWrapper(const std::string& phase_name, LLPointer cb = nullptr): mTrackingPhase(phase_name), mCB(cb) { @@ -526,6 +531,20 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() U32 LLUpdateAppearanceOnDestroy::sActiveCallbacks = 0; +LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id): + mItemID(item_id) +{ +} + +LLRequestServerAppearanceUpdateOnDestroy::~LLRequestServerAppearanceUpdateOnDestroy() +{ + LL_DEBUGS("Avatar") << "ATT requesting server appearance update" << LL_ENDL; + if (!LLApp::isExiting()) + { + LLAppearanceMgr::instance().requestServerAppearanceUpdate(); + } +} + void edit_wearable_and_customize_avatar(LLUUID item_id) { // Start editing the item if previously requested. @@ -537,7 +556,16 @@ void edit_wearable_and_customize_avatar(LLUUID item_id) // If we're in appearance editing mode, the current tab may need to be refreshed LLFloaterCustomize::getInstance()->switchToDefaultSubpart(); } +} +LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOnDestroy() +{ + if (!LLApp::isExiting()) + { + LLAppearanceMgr::instance().updateAppearanceFromCOF( + true,true, + boost::bind(edit_wearable_and_customize_avatar, mItemID)); + } } @@ -590,7 +618,7 @@ class LLWearableHoldingPattern bool pollMissingWearables(); bool isMissingCompleted(); void recoverMissingWearable(LLWearableType::EType type); - void clearCOFLinksForMissingWearables(); +// void clearCOFLinksForMissingWearables(); void onWearableAssetFetch(LLViewerWearable *wearable); void onAllComplete(); @@ -603,7 +631,7 @@ class LLWearableHoldingPattern found_list_t& getFoundList(); void eraseTypeToLink(LLWearableType::EType type); void eraseTypeToRecover(LLWearableType::EType type); - void setObjItems(const LLInventoryModel::item_array_t& items); +// void setObjItems(const LLInventoryModel::item_array_t& items); void setGestItems(const LLInventoryModel::item_array_t& items); bool isMostRecent(); void handleLateArrivals(); @@ -613,7 +641,7 @@ class LLWearableHoldingPattern private: found_list_t mFoundList; - LLInventoryModel::item_array_t mObjItems; +// LLInventoryModel::item_array_t mObjItems; LLInventoryModel::item_array_t mGestItems; typedef std::set type_set_t; type_set_t mTypesToRecover; @@ -820,16 +848,22 @@ void LLWearableHoldingPattern::onAllComplete() // // pre-attachment states. // gAgentAvatarp->clearAttachmentPosOverrides(); // +// if (objects_to_remove.size() || items_to_add.size()) +// { +// LL_DEBUGS("Avatar") << "ATT will remove " << objects_to_remove.size() +// << " and add " << items_to_add.size() << " items" << LL_ENDL; +// } +// // // Take off the attachments that will no longer be in the outfit. // LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove); - + // Update wearables. LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " updating agent wearables with " << mResolved << " wearable items " << LL_ENDL; LLAppearanceMgr::instance().updateAgentWearables(this); -// // Restore attachment pos overrides for the attachments that -// // are remaining in the outfit. + // Restore attachment pos overrides for the attachments that + // are remaining in the outfit. // for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_retain.begin(); // it != objects_to_retain.end(); // ++it) @@ -1010,19 +1044,19 @@ bool LLWearableHoldingPattern::isMissingCompleted() return mTypesToLink.size()==0 && mTypesToRecover.size()==0; } -void LLWearableHoldingPattern::clearCOFLinksForMissingWearables() -{ - for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it) - { - LLFoundData &data = *it; - if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable)) - { - // Wearable link that was never resolved; remove links to it from COF - LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " removing link for unresolved item " << data.mItemID.asString() << LL_ENDL; - LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID); - } - } -} +//void LLWearableHoldingPattern::clearCOFLinksForMissingWearables() +//{ +// for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it) +// { +// LLFoundData &data = *it; +// if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable)) +// { +// // Wearable link that was never resolved; remove links to it from COF +// LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " removing link for unresolved item " << data.mItemID.asString() << LL_ENDL; +// LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID); +// } +// } +//} // [SL:KB] - Patch: Appearance-COFCorruption | Checked: 2010-04-14 (Catznip-2.0) bool LLWearableHoldingPattern::pollStopped() @@ -1219,6 +1253,7 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLViewerWearable *wearable) if(wearable->getAssetID() == data.mAssetID) { // Failing this means inventory or asset server are corrupted in a way we don't handle. + // Singu Note: This code conflict exists because we correct corrupted clothing items to their correct wearable type. if (data.mWearableType >= LLWearableType::WT_COUNT || wearable->getType() >= LLWearableType::WT_UNKNOWN || (data.mWearableType != wearable->getType() && @@ -1271,7 +1306,7 @@ static void onWearableAssetFetch(LLViewerWearable* wearable, void* data) static void removeDuplicateItems(LLInventoryModel::item_array_t& items) { LLInventoryModel::item_array_t new_items; - std::set items_seen; + uuid_set_t items_seen; std::deque tmp_list; // Traverse from the front and keep the first of each item // encountered, so we actually keep the *last* of each duplicate @@ -1295,20 +1330,24 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items) items = new_items; } -// [SL:KB] - Patch: Appearance-WearableDuplicateAssets | Checked: 2011-07-24 (Catznip-2.6.0e) | Added: Catznip-2.6.0e +//========================================================================= + +// [SL:KB] - Patch: Appearance-WearableDuplicateAssets | Checked: 2015-06-30 (Catznip-3.7) static void removeDuplicateWearableItemsByAssetID(LLInventoryModel::item_array_t& items) { - std::set idsAsset; - for (S32 idxItem = items.size() - 1; idxItem >= 0; idxItem--) - { - const LLViewerInventoryItem* pItem = items.at(idxItem); - if (!pItem->isWearableType()) - continue; - if (idsAsset.end() == idsAsset.find(pItem->getAssetUUID())) - idsAsset.insert(pItem->getAssetUUID()); - else - items.erase(items.begin() + idxItem); - } + uuid_set_t idsAsset; + items.erase(std::remove_if(items.begin(), items.end(), + [&idsAsset](const LLViewerInventoryItem* pItem) + { + if (pItem->isWearableType()) + { + const LLUUID& idAsset = pItem->getAssetUUID(); + if ( (idAsset.notNull()) && (idsAsset.end() != idsAsset.find(idAsset)) ) + return true; + idsAsset.insert(idAsset); + } + return false; + }), items.end()); } // [/SL:KB] @@ -1396,7 +1435,7 @@ const LLUUID LLAppearanceMgr::getBaseOutfitUUID() return outfit_cat->getUUID(); } -void wear_on_avatar_cb(const LLUUID& inv_item, bool do_replace/*= false*/) +void wear_on_avatar_cb(const LLUUID& inv_item, bool do_replace /*= false*/) { if (inv_item.isNull()) return; @@ -1426,43 +1465,63 @@ void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear, const LLUUID& item_id_to_wear = *it; - if (item_id_to_wear.isNull()) continue; + if (item_id_to_wear.isNull()) + { + LL_DEBUGS("Avatar") << "null id " << item_id_to_wear << LL_ENDL; + continue; + } LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear); - if (!item_to_wear) continue; + if (!item_to_wear) + { + LL_DEBUGS("Avatar") << "inventory item not found for id " << item_id_to_wear << LL_ENDL; + continue; + } if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID())) { + LL_DEBUGS("Avatar") << "inventory item in library, will copy and wear " + << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL; LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(wear_on_avatar_cb,_1,replace)); - copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(), cb); + copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), + item_to_wear->getUUID(), LLUUID::null, std::string(), cb); continue; } else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID())) { - continue; // not in library and not in agent's inventory + // not in library and not in agent's inventory + LL_DEBUGS("Avatar") << "inventory item not in user inventory or library, skipping " + << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL; + continue; } else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH))) { LLNotificationsUtil::add("CannotWearTrash"); + LL_DEBUGS("Avatar") << "inventory item is in trash, skipping " + << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL; continue; } else if (isLinkedInCOF(item_to_wear->getUUID())) // EXT-84911 { + LL_DEBUGS("Avatar") << "inventory item is already in COF, skipping " + << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL; continue; } + /* Singu TODO: Find out why this was here, it wasn't in any upstream so I've commented it out. ~Liru else if (item_to_wear->isWearableType()) { LLViewerWearable* wearable = gAgentWearables.getWearableFromAssetID(item_to_wear->getAssetUUID()); if (wearable && (!replace || wearable != gAgentWearables.getTopWearable(item_to_wear->getWearableType()))) continue; } + */ // [RLVa:KB] - Checked: 2013-02-12 (RLVa-1.4.8) - replace |= (LLAssetType::AT_BODYPART == item_to_wear->getType()); // Body parts should always replace - if ( (rlv_handler_t::isEnabled()) && (!rlvPredCanWearItem(item_to_wear, (replace) ? RLV_WEAR_REPLACE : RLV_WEAR_ADD)) ) - { - continue; - } + replace |= (LLAssetType::AT_BODYPART == item_to_wear->getType()); // Body parts should always replace + if ( (rlv_handler_t::isEnabled()) && (!rlvPredCanWearItem(item_to_wear, (replace) ? RLV_WEAR_REPLACE : RLV_WEAR_ADD)) ) + { + continue; + } // [/RLVa:KB] switch (item_to_wear->getType()) @@ -1473,7 +1532,7 @@ void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear, { if (!cb && do_update) { - cb = new LLUpdateAppearanceOnDestroy(true, true, boost::bind(&edit_wearable_and_customize_avatar, item_id_to_wear)); + cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear); } LLWearableType::EType type = item_to_wear->getWearableType(); S32 wearable_count = gAgentWearables.getWearableCount(type); @@ -1498,19 +1557,21 @@ void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear, // Remove the existing wearables of the same type. // Remove existing body parts anyway because we must not be able to wear e.g. two skins. + removeCOFLinksOfType(item_to_wear->getWearableType()); if (!cb && do_update) { - cb = new LLUpdateAppearanceOnDestroy(true, true, boost::bind(&edit_wearable_and_customize_avatar, item_id_to_wear)); + cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear); } - removeCOFLinksOfType(item_to_wear->getWearableType(), NULL, true); items_to_link.push_back(item_to_wear); } break; case LLAssetType::AT_OBJECT: - { - rez_attachment(item_to_wear, NULL, replace); - } + { + LL_DEBUGS("Avatar") << "ATT wearing object. calling rez_attachment, item " << item_to_wear->getName() + << " id " << item_to_wear->getLinkedUUID() << LL_ENDL; + rez_attachment(item_to_wear, NULL, replace); + } break; default: continue; @@ -1723,12 +1784,6 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL LLInventoryModel::cat_array_t* cats; LLInventoryModel::item_array_t* items; gInventory.getDirectDescendentsOf(src_id, cats, items); - LL_INFOS() << "copying " << items->size() << " items" << LL_ENDL; - copyItems(dst_id, items, cb); -} - -void LLAppearanceMgr::copyItems(const LLUUID& dst_id, LLInventoryModel::item_array_t* items, LLPointer cb) -{ LL_INFOS() << "copying " << items->size() << " items" << LL_ENDL; LLInventoryObject::const_object_list_t link_array; for (LLInventoryModel::item_array_t::const_iterator iter = items->begin(); @@ -1761,9 +1816,7 @@ void LLAppearanceMgr::copyItems(const LLUUID& dst_id, LLInventoryModel::item_arr case LLAssetType::AT_GESTURE: { if(!item->getPermissions().allowCopyBy(gAgent.getID())) - { link_array.push_back(LLConstPointer(item)); - } else { LL_DEBUGS("Avatar") << "copying inventory item " << item->getName() << LL_ENDL; @@ -1853,9 +1906,16 @@ bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id) { return false; } - + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false); - return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn, true); + gInventory.collectDescendentsIf(outfit_cat_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_worn, + /*follow_folder_links=*/ true); + return items.size() > 0; } // static @@ -1933,9 +1993,9 @@ bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids) { ++n_clothes; } - else if (item->getType() == LLAssetType::AT_BODYPART) + else if (item->getType() == LLAssetType::AT_BODYPART || item->getType() == LLAssetType::AT_GESTURE) { - return false; //If we have a bodypart in selection we cannot use 'add'. + return isAgentAvatarValid(); } else { @@ -1977,24 +2037,6 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointergetActualType() == LLAssetType::AT_LINK_FOLDER)) - continue; - if (item->getIsLinkType()) - { - remove_inventory_item(item->getUUID(), NULL); - } - } -} - // Keep the last N wearables of each type. For viewer 2.0, N is 1 for // both body parts and clothing items. void LLAppearanceMgr::filterWearableItems( @@ -2040,13 +2082,16 @@ void LLAppearanceMgr::filterWearableItems( // [RLVa:KB] - Checked: 2010-03-05 (RLVa-1.2.0) void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) { - LLViewerInventoryCategory *pcat = gInventory.getCategory(category); - if (!pcat) - { - LL_WARNS() << "no category found for id " << category << LL_ENDL; - return; - } - LL_INFOS("Avatar") << self_av_string() << "starting, cat '" << (pcat ? pcat->getName() : "[UNKNOWN]") << "'" << LL_ENDL; +// LLViewerInventoryCategory *pcat = gInventory.getCategory(category); +// if (!pcat) +// { +// LL_WARNS() << "no category found for id " << category << LL_ENDL; +// return; +// } +// LL_INFOS("Avatar") << self_av_string() << "starting, cat '" << (pcat ? pcat->getName() : "[UNKNOWN]") << "'" << LL_ENDL; +// [RLVa:KB] - Checked: 2010-03-26 (RLVa-1.2.0) + LL_INFOS("Avatar") << "starting" << LL_ENDL; +// [/RLVa:KB] LLInventoryModel::item_array_t body_items_new, wear_items_new, obj_items_new, gest_items_new; getDescendentsOfAssetType(category, body_items_new, LLAssetType::AT_BODYPART); @@ -2063,17 +2108,6 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new, bool append /*=false*/, const LLUUID& idOutfit /*=LLUUID::null*/, LLPointer link_waiter /*= NULL*/) // [/RLVa:KB] { -// LLViewerInventoryCategory *pcat = gInventory.getCategory(category); -// if (!pcat) -// { -// LL_WARNS() << "no category found for id " << category << LL_ENDL; -// return; -// } -// LL_INFOS("Avatar") << self_av_string() << "starting, cat '" << (pcat ? pcat->getName() : "[UNKNOWN]") << "'" << LL_ENDL; -// [RLVa:KB] - Checked: 2010-03-26 (RLVa-1.2.0) - LL_INFOS("Avatar") << "starting" << LL_ENDL; -// [/RLVa:KB] - const LLUUID cof = getCOF(); // Deactivate currently active gestures in the COF, if replacing outfit @@ -2093,8 +2127,9 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new, // Collect and filter descendents to determine new COF contents. - // - Body parts: always include COF contents as a fallback in case any - // required parts are missing. + // + // - Body parts: always include COF contents as a fallback in case any required parts are missing. + // // Preserve body parts from COF if appending. LLInventoryModel::item_array_t body_items; getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART); @@ -2112,7 +2147,9 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new, removeDuplicateItems(body_items); filterWearableItems(body_items, 1, 0); + // // - Wearables: include COF contents only if appending. + // LLInventoryModel::item_array_t wear_items; if (append) getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING); @@ -2224,7 +2261,10 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new, const LLUUID& base_id = (append) ? getBaseOutfitUUID() : idOutfit; LLViewerInventoryCategory* base_cat = (base_id.notNull()) ? gInventory.getCategory(base_id) : NULL; // [/RLVa:KB] - if (base_cat) +// if (base_cat) +// [SL:KB] - Patch: Appearance-Misc | Checked: 2015-06-27 (Catznip-3.7) + if ((base_cat) && (base_cat->getPreferredType() == LLFolderType::FT_OUTFIT)) +// [/SL:KB] { LLSD base_contents; base_contents["name"] = base_cat->getName(); @@ -2233,7 +2273,8 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new, base_contents["type"] = LLAssetType::AT_LINK_FOLDER; contents.append(base_contents); } - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + static LLCachedControl debug_ava_appr_msg(gSavedSettings, "DebugAvatarAppearanceMessage"); + if (debug_ava_appr_msg) { dump_sequential_xml(gAgentAvatarp->getFullname() + "_slam_request", contents); } @@ -2244,7 +2285,8 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new, void LLAppearanceMgr::updatePanelOutfitName(const std::string& name) { - LLFloaterCustomize* panel_appearance = LLFloaterCustomize::instanceExists() ? LLFloaterCustomize::getInstance() : NULL; + LLFloaterCustomize* panel_appearance = + LLFloaterCustomize::instanceExists() ? LLFloaterCustomize::getInstance() : nullptr; if (panel_appearance) { panel_appearance->refreshCurrentOutfitName(name); @@ -2532,7 +2574,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, remove_non_link_items(obj_items); remove_non_link_items(gest_items); // [SL:KB] - Patch: Apperance-Misc | Checked: 2010-11-24 (Catznip-2.4) - // Since we're following folder links we might have picked up new duplicates, or exceeded MAX_CLOTHING_PER_TYPE + // Since we're following folder links we might have picked up new duplicates, or exceeded MAX_CLOTHING_LAYERS removeDuplicateItems(wear_items); removeDuplicateItems(obj_items); removeDuplicateItems(gest_items); @@ -2553,28 +2595,29 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, << " descendent_count " << cof->getDescendentCount() << " viewer desc count " << cof->getViewerDescendentCount() << LL_ENDL; } + // [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-2.2) // Update attachments to match those requested. if (isAgentAvatarValid()) { // Include attachments which should be in COF but don't have their link created yet - uuid_vec_t::iterator itPendingAttachLink = mPendingAttachLinks.begin(); - while (itPendingAttachLink != mPendingAttachLinks.end()) + uuid_set_t pendingAttachments; + if (LLAttachmentsMgr::instance().getPendingAttachments(pendingAttachments)) { - const LLUUID& idItem = *itPendingAttachLink; - if ( (!gAgentAvatarp->isWearingAttachment(idItem)) || (isLinkInCOF(idItem)) ) + for (const LLUUID& idAttachItem : pendingAttachments) { - itPendingAttachLink = mPendingAttachLinks.erase(itPendingAttachLink); - continue; - } + if ( (!gAgentAvatarp->isWearingAttachment(idAttachItem)) || (isLinkedInCOF(idAttachItem)) ) + { + LLAttachmentsMgr::instance().clearPendingAttachmentLink(idAttachItem); + continue; + } - LLViewerInventoryItem* pItem = gInventory.getItem(idItem); - if (pItem) - { - obj_items.push_back(pItem); + LLViewerInventoryItem* pAttachItem = gInventory.getItem(idAttachItem); + if (pAttachItem) + { + obj_items.push_back(pAttachItem); + } } - - ++itPendingAttachLink; } LL_DEBUGS("Avatar") << self_av_string() << "Updating " << obj_items.size() << " attachments" << LL_ENDL; @@ -2588,7 +2631,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, // attachments, even those that are not being removed. This is // needed to get joint positions all slammed down to their // pre-attachment states. - //gAgentAvatarp->clearAttachmentPosOverrides(); + gAgentAvatarp->clearAttachmentOverrides(); // Take off the attachments that will no longer be in the outfit. // (but don't remove attachments until avatar is fully loaded - should reduce random attaching/detaching/reattaching at log-on) @@ -2598,13 +2641,12 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove); } - // Restore attachment pos overrides for the attachments that - // are remaining in the outfit. - /*for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_retain.begin(); it != objects_to_retain.end(); ++it) + // Restore attachment pos overrides for the attachments that are remaining in the outfit. + for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_retain.begin(); it != objects_to_retain.end(); ++it) { LLViewerObject *objectp = *it; - gAgentAvatarp->addAttachmentPosOverridesForObject(objectp); - }*/ + gAgentAvatarp->addAttachmentOverridesForObject(objectp); + } // Add new attachments to match those requested. LL_DEBUGS("Avatar") << self_av_string() << "Adding " << items_to_add.size() << " attachments" << LL_ENDL; @@ -2634,19 +2676,19 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, // callback will be called (and this object deleted) // before the final getNextData(). + // Fault injection: use debug setting to test asset + // fetch failures (should be replaced by new defaults in + // lost&found). + U32 skip_type = gSavedSettings.getU32("ForceAssetFail"); +// [RLVa:KB] - Checked: 2010-12-11 (RLVa-1.2.2) + U32 missing_type = gSavedSettings.getU32("ForceMissingType"); +// [/RLVa:KB] + for(U32 i = 0; i < wear_items.size(); ++i) { LLViewerInventoryItem *item = wear_items.at(i); LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL; - // Fault injection: use debug setting to test asset - // fetch failures (should be replaced by new defaults in - // lost&found). - U32 skip_type = gSavedSettings.getU32("ForceAssetFail"); -// [RLVa:KB] - Checked: 2010-12-11 (RLVa-1.2.2) - U32 missing_type = gSavedSettings.getU32("ForceMissingType"); -// [/RLVa:KB] - if (item && item->getIsLinkType() && linked_item) { LLFoundData found(linked_item->getUUID(), @@ -2726,7 +2768,18 @@ void LLAppearanceMgr::updateAppearanceFromInitialWearables(LLInventoryObject::co const LLUUID& idCOF = getCOF(); // Remove current COF contents - purgeCategory(idCOF, false); + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(idCOF, cats, items, + LLInventoryModel::EXCLUDE_TRASH); + for (U32 i = 0; i < items.size(); ++i) + { + LLViewerInventoryItem *item = items.at(i); + if (item->getIsLinkType()) + { + remove_inventory_item(item->getUUID(), NULL); + } + } // Create links to new COF contents LLPointer link_waiter = new LLUpdateAppearanceOnDestroy(); link_inventory_array(idCOF, initial_items, link_waiter); @@ -2787,6 +2840,12 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool { if(!category) return; + // Attachments getting lost on TP: + // We'll be sending the outfit change request to our current region, + // so we'll learn them if they've been sending bad kills. + // We don't take kindly to that sorta behaviour round these parts. + gAgent.setIsCrossingRegion(false); + selfClearPhases(); selfStartPhase("wear_inventory_category"); @@ -2796,8 +2855,7 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool << " )" << LL_ENDL; // If we are copying from library, attempt to use AIS to copy the category. - bool ais_ran=false; - if (copy && AISCommand::isAPIAvailable()) + if (copy && AISAPI::isAvailable()) { LLUUID parent_id; parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); @@ -2809,11 +2867,11 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool LLPointer copy_cb = new LLWearCategoryAfterCopy(append); LLPointer track_cb = new LLTrackPhaseWrapper( std::string("wear_inventory_category_callback"), copy_cb); - boost::intrusive_ptr cmd_ptr = new CopyLibraryCategoryCommand(category->getUUID(), parent_id, track_cb); - ais_ran=cmd_ptr->run_command(); - } - if (!ais_ran) + AISAPI::completion_t cr = boost::bind(&doAppearanceCb, track_cb, _1); + AISAPI::CopyLibraryCategory(category->getUUID(), parent_id, false, cr); + } + else { selfStartPhase("wear_inventory_category_fetch"); callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal, @@ -3046,15 +3104,17 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, item_array, LLInventoryModel::EXCLUDE_TRASH); bool linked_already = false; - - LLUUID remove_id; - for (U32 i=0; igetWearableType(); + const bool is_body_part = (wearable_type == LLWearableType::WT_SHAPE) + || (wearable_type == LLWearableType::WT_HAIR) + || (wearable_type == LLWearableType::WT_EYES) + || (wearable_type == LLWearableType::WT_SKIN); + if (inv_item->getLinkedUUID() == vitem->getLinkedUUID()) { linked_already = true; @@ -3063,13 +3123,17 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, // type? If so, new item will replace old. else if ((vitem->isWearableType()) && (vitem->getWearableType() == wearable_type)) { - if (remove_id.isNull() && !gAgentWearables.canAddWearable(wearable_type)) + if (is_body_part && inv_item->getIsLinkType()) + { + remove_inventory_item(inv_item->getUUID(), cb); + } + else if (!gAgentWearables.canAddWearable(wearable_type)) { // MULTI-WEARABLES: make sure we don't go over clothing limits - remove_id = inv_item->getUUID(); + remove_inventory_item(inv_item->getUUID(), cb); } // [SL:KB] - Patch: Appearance-WearableDuplicateAssets | Checked: 2011-07-24 (Catznip-2.6.0e) | Added: Catznip-2.6.0e - else if (inv_item->getAssetUUID() == vitem->getAssetUUID()) + else if ( (vitem->getWearableType() == wearable_type) && (vitem->getAssetUUID() == inv_item->getAssetUUID()) ) { // Only allow one wearable per unique asset linked_already = true; @@ -3080,10 +3144,6 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, if (!linked_already) { - if( remove_id.notNull() ) - { - remove_inventory_item(remove_id, cb); - } LLViewerInventoryItem *copy_item = new LLViewerInventoryItem; copy_item->copyViewerItem(vitem); copy_item->setDescription(description); @@ -3093,26 +3153,21 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, LLInventoryModel::item_array_t LLAppearanceMgr::findCOFItemLinks(const LLUUID& item_id) { - LLInventoryModel::item_array_t result; - const LLViewerInventoryItem *vitem = - dynamic_cast(gInventory.getItem(item_id)); - if (vitem) + LLUUID linked_id = gInventory.getLinkedItemID(item_id); + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(LLAppearanceMgr::getCOF(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + for (U32 i=0; igetLinkedUUID() == linked_id) { - const LLViewerInventoryItem* inv_item = item_array.at(i).get(); - if (inv_item->getLinkedUUID() == vitem->getLinkedUUID()) - { - result.push_back(item_array.at(i)); - } + result.push_back(item_array.at(i)); } } return result; @@ -3711,7 +3766,7 @@ void RequestAgentUpdateAppearanceResponder::onRequestRequested() } // Actually send the request. - LL_DEBUGS("Avatar") << "Will send request for cof_version " << cof_version << LL_ENDL; + LL_DEBUGS("Avatar") << "ATT sending bake request for cof_version " << cof_version << LL_ENDL; mRetryPolicy->reset(); sendRequest(); } @@ -3756,7 +3811,7 @@ void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content) { LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger() << " ================================= " << LL_ENDL; - std::set ais_items, local_items; + uuid_set_t ais_items, local_items; const LLSD& cof_raw = content["cof_raw"]; for (LLSD::array_const_iterator it = cof_raw.beginArray(); it != cof_raw.endArray(); ++it) @@ -3795,8 +3850,8 @@ void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content) LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), - cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); - for (U32 i=0; igetUUID()); @@ -3808,7 +3863,7 @@ void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content) } LL_INFOS("Avatar") << " ================================= " << LL_ENDL; S32 local_only = 0, ais_only = 0; - for (std::set::iterator it = local_items.begin(); it != local_items.end(); ++it) + for (auto it = local_items.begin(); it != local_items.end(); ++it) { if (ais_items.find(*it) == ais_items.end()) { @@ -3816,7 +3871,7 @@ void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content) local_only++; } } - for (std::set::iterator it = ais_items.begin(); it != ais_items.end(); ++it) + for (auto it = ais_items.begin(); it != ais_items.end(); ++it) { if (local_items.find(*it) == local_items.end()) { @@ -3824,7 +3879,7 @@ void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content) ais_only++; } } - if (local_only==0 && ais_only==0) + if (local_only == 0 && ais_only == 0) { LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req " << content["observed"].asInteger() @@ -3938,7 +3993,7 @@ LLSD LLAppearanceMgr::dumpCOF() const LLUUID linked_asset_id(linked_item->getAssetUUID()); md5.update((unsigned char*)linked_asset_id.mData, 16); U32 flags = linked_item->getFlags(); - md5.update(boost::lexical_cast(flags)); + md5.update(fmt::to_string(flags)); } else if (LLAssetType::AT_LINK_FOLDER != inv_item->getActualType()) { @@ -3964,102 +4019,6 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() mAppearanceResponder->onRequestRequested(); } -extern AIHTTPTimeoutPolicy incrementCofVersionResponder_timeout; -class LLIncrementCofVersionResponder : public LLHTTPClient::ResponderWithResult -{ - LOG_CLASS(LLIncrementCofVersionResponder); -public: - LLIncrementCofVersionResponder() : LLHTTPClient::ResponderWithResult() - { - mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 16.0, 2.0, 5); - } - - virtual ~LLIncrementCofVersionResponder() - { - } - -protected: - virtual void httpSuccess() - { - LL_INFOS() << "Successfully incremented agent's COF." << LL_ENDL; - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(400, "Malformed response contents", content); - return; - } - S32 new_version = content["category"]["version"].asInteger(); - - // cof_version should have increased - llassert(new_version > gAgentAvatarp->mLastUpdateRequestCOFVersion); - - gAgentAvatarp->mLastUpdateRequestCOFVersion = new_version; - } - - virtual void httpFailure() - { - LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error " - << dumpResponse() << LL_ENDL; - F32 seconds_to_wait; - mRetryPolicy->onFailure(getStatus(), getResponseHeaders()); - if (mRetryPolicy->shouldRetry(seconds_to_wait)) - { - LL_INFOS() << "retrying" << LL_ENDL; - doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion, - LLAppearanceMgr::getInstance(), - LLHTTPClient::ResponderPtr(this)), - seconds_to_wait); - } - else - { - LL_WARNS() << "giving up after too many retries" << LL_ENDL; - } - } - -private: - LLPointer mRetryPolicy; -protected: - /*virtual*/ char const* getName(void) const { return "LLIncrementCofVersionResponder"; } - /*virtual*/ bool needsHeaders() const { return true; } -}; - -void LLAppearanceMgr::incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr) -{ - // If we don't have a region, report it as an error - if (gAgent.getRegion() == NULL) - { - LL_WARNS() << "Region not set, cannot request cof_version increment" << LL_ENDL; - return; - } - - std::string url = gAgent.getRegion()->getCapability("IncrementCofVersion"); - if (url.empty()) - { - LL_WARNS() << "No cap for IncrementCofVersion." << LL_ENDL; - return; - } - - LL_INFOS() << "Requesting cof_version be incremented via capability to: " - << url << LL_ENDL; - LLSD body = LLSD::emptyMap(); - - if (!responder_ptr.get()) - { - responder_ptr = LLHTTPClient::ResponderPtr(new LLIncrementCofVersionResponder()); - } - - LLHTTPClient::get(url, body, responder_ptr); -} - -U32 LLAppearanceMgr::getNumAttachmentsInCOF() -{ - const LLUUID cof = getCOF(); - LLInventoryModel::item_array_t obj_items; - getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT); - return obj_items.size(); -} - - std::string LLAppearanceMgr::getAppearanceServiceURL() const { if (gSavedSettings.getString("AgentAppearanceServiceURL").empty()) @@ -4077,14 +4036,15 @@ void show_created_outfit(const LLUUID& folder_id, bool show_panel = true) return; } - LL_INFOS("Avatar") << "called" << LL_ENDL; + LL_DEBUGS("Avatar") << "called" << LL_ENDL; LLSD key; - //EXT-7727. For new accounts LLShowCreatedOutfit is created during login process - // add may be processed after login process is finished + //EXT-7727. For new accounts inventory callback is created during login process + // and may be processed after login process is finished // MULTI-WEARABLES TODO - /*if (mShowPanel) + /*if (show_panel) { + LL_DEBUGS("Avatar") << "showing panel" << LL_ENDL; LLFloaterSidePanelContainer::showPanel("appearance", "panel_outfits_inventory", key); } @@ -4092,7 +4052,7 @@ void show_created_outfit(const LLUUID& folder_id, bool show_panel = true) dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance", "outfitslist_tab")); if (outfits_list) { - outfits_list->setSelectedOutfitByUUID(mFolderID); + outfits_list->setSelectedOutfitByUUID(folder_id); }*/ LLAppearanceMgr::getInstance()->updateIsDirty(); @@ -4103,7 +4063,7 @@ void show_created_outfit(const LLUUID& folder_id, bool show_panel = true) // link, since, the COF version has changed. There is a race // condition in initial outfit setup which can lead to rez // failures - SH-3860. - LL_INFOS("Avatar") << "requesting appearance update after createBaseOutfitLink" << LL_ENDL; + LL_DEBUGS("Avatar") << "requesting appearance update after createBaseOutfitLink" << LL_ENDL; LLPointer cb = new LLUpdateAppearanceOnDestroy; LLAppearanceMgr::getInstance()->createBaseOutfitLink(folder_id, cb); } @@ -4175,7 +4135,21 @@ LLUUID LLAppearanceMgr::makeNewOutfitCore(const std::string& new_folder_name, bo // First, make a folder in the My Outfits directory. const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + if (AISAPI::isAvailable()) { + // cap-based category creation was buggy until recently. use + // existence of AIS as an indicator the fix is present. Does + // not actually use AIS to create the category. + inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel); + LLUUID folder_id = gInventory.createNewCategory( + parent_id, + LLFolderType::FT_OUTFIT, + new_folder_name, + func); + return folder_id; + } + else + { LLUUID folder_id = gInventory.createNewCategory( parent_id, LLFolderType::FT_OUTFIT, @@ -4209,7 +4183,7 @@ LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, L // 2) Stuff with requests via makeLink and makeCopy // 3) Call dispatch() // 4) Let the LLPointer go out of scope. -class LLCreateLegacyOutfit : public LLBoostFuncInventoryCallbackFireOnce +class LLCreateLegacyOutfit final : public LLBoostFuncInventoryCallbackFireOnce { public: LLCreateLegacyOutfit(const LLUUID& folder_id, inventory_func_type fire_func, nullary_func_type destroy_func = no_op) : @@ -4222,36 +4196,6 @@ class LLCreateLegacyOutfit : public LLBoostFuncInventoryCallbackFireOnce if (!LLApp::isRunning() || mFailed) return; - /* Singu Note: This wasn't working when we detached copyable attachments early, changeOutfit instead - LLInventoryModel::item_array_t body_items, wear_items, obj_items, gest_items; - for(std::set::const_iterator it = mWearItems.begin(); it != mWearItems.end(); ++it) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if(item) - { - switch(item->getType()) - { - case LLAssetType::AT_BODYPART: - body_items.push_back(item); - break; - case LLAssetType::AT_CLOTHING: - wear_items.push_back(item); - break; - case LLAssetType::AT_OBJECT: - obj_items.push_back(item); - break; - case LLAssetType::AT_GESTURE: - gest_items.push_back(item); - break; - default: - break; - } - } - } - - if(!body_items.empty() || !wear_items.empty() || !obj_items.empty() || !gest_items.empty()) - LLAppearanceMgr::instance().updateCOF(body_items, wear_items, obj_items, gest_items, false); - */ LLAppearanceMgr::instance().changeOutfit(true, mFolderID, false); } @@ -4412,7 +4356,7 @@ class LLCreateLegacyOutfit : public LLBoostFuncInventoryCallbackFireOnce bool mFailed; std::vector > mPendingCopies; std::vector > mPendingLinks; - std::set mWearItems; + uuid_set_t mWearItems; std::vector mActiveRequests; }; @@ -4508,11 +4452,21 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, LLP continue; } + LLViewerInventoryItem *item = gInventory.getItem(linked_item_id); + if (item && item->getType() == LLAssetType::AT_OBJECT) + { + LL_DEBUGS("Avatar") << "ATT removing attachment " << item->getName() << " id " << item->getUUID() << LL_ENDL; + } + if (item && item->getType() == LLAssetType::AT_BODYPART) + { + continue; + } + if (!cb) cb = new LLUpdateAppearanceOnDestroy(); removeCOFItemLinks(linked_item_id, cb, immediate_delete); // [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2015-03-01 (Catznip-3.7) - clearPendingAttachment(linked_item_id); + LLAttachmentsMgr::instance().clearPendingAttachmentLink(linked_item_id); // [/SL:KB] addDoomedTempAttachment(linked_item_id); } @@ -4541,28 +4495,12 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, LLP void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove, LLPointer cb /*= NULL*/, bool immediate_delete /*= false*/) // [/SL:KB] { - LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove); - -// [RLVa:KB] - Checked: 2013-02-12 (RLVa-1.4.8) - if ( (rlv_handler_t::isEnabled()) && (!rlvPredCanRemoveItem(linked_item_id)) ) - { - return; - } -// [/RLVA:KB] - + uuid_vec_t ids_to_remove; + ids_to_remove.push_back(id_to_remove); // [SL:KB] - Patch: Appearance-Misc | Checked: 2015-05-05 (Catznip-3.7) - if (!cb) - { - cb = new LLUpdateAppearanceOnDestroy; - } - removeCOFItemLinks(linked_item_id, cb, immediate_delete); -// [/SL:KB] -// LLPointer cb = new LLUpdateAppearanceOnDestroy; -// removeCOFItemLinks(linked_item_id, cb); -// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2015-03-01 (Catznip-3.7) - clearPendingAttachment(linked_item_id); + removeItemsFromAvatar(ids_to_remove, cb, immediate_delete); // [/SL:KB] - addDoomedTempAttachment(linked_item_id); +// removeItemsFromAvatar(ids_to_remove); } @@ -4674,7 +4612,7 @@ void LLAppearanceMgr::dumpCat(const LLUUID& cat_id, const std::string& msg) S32 hitcount = 0; for(S32 i=0; igetName() <getAssetUUID(); } - LL_DEBUGS("Avatar") << self_av_string() << msg << " " << i << " " << (item ? item->getName() : "(nullitem)") << " " << asset_id.asString() << LL_ENDL; + LL_DEBUGS("Avatar") << self_av_string() << msg << " " << i <<" " << (item ? item->getName() : "(nullitem)") << " " << asset_id.asString() << LL_ENDL; } } @@ -4726,18 +4664,12 @@ void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val) { LL_DEBUGS("Avatar") << "setAttachmentInvLinkEnable => " << (int) val << LL_ENDL; mAttachmentInvLinkEnabled = val; -// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-10-05 (Catznip-2.2) - if (mAttachmentInvLinkEnabled) - { - linkPendingAttachments(); - } -// [/SL:KB] } -void dumpAttachmentSet(const std::set& atts, const std::string& msg) +void dumpAttachmentSet(const uuid_set_t& atts, const std::string& msg) { LL_INFOS() << msg << LL_ENDL; - for (std::set::const_iterator it = atts.begin(); + for (auto it = atts.begin(); it != atts.end(); ++it) { @@ -4753,93 +4685,33 @@ void dumpAttachmentSet(const std::set& atts, const std::string& msg) void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) { + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT registering attachment " + << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); -// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-10-05 (Catznip-2.2) - if (isLinkInCOF(item_id)) - { - return; - } - mPendingAttachLinks.push_back(item_id); -// [/SL:KB] - if (mAttachmentInvLinkEnabled) - { - // we have to pass do_update = true to call LLAppearanceMgr::updateAppearanceFromCOF. - // it will trigger gAgentWariables.notifyLoadingFinished() - // But it is not acceptable solution. See EXT-7777 - if (!isLinkedInCOF(item_id)) - { -// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-10-05 (Catznip-2.2) - LLPointer cb = new LLRegisterAttachmentCallback(item_id); - LLAppearanceMgr::addCOFItemLink(item_id, cb); // Add COF link for item. -// [/SL:KB] -// LLPointer cb = new LLUpdateAppearanceOnDestroy(); -// LLAppearanceMgr::addCOFItemLink(item_id, cb); // Add COF link for item. - } - } - else - { - //LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; - } + LLAttachmentsMgr::instance().onAttachmentArrived(item_id); } void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) { - gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); -// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-10-05 (Catznip-2.2) - clearPendingAttachment(item_id); -// [/SL:KB] - - if (mAttachmentInvLinkEnabled) - { - LLAppearanceMgr::removeCOFItemLinks(item_id); - } - else - { - //LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; - } -} - -// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-2.2) -void LLAppearanceMgr::linkPendingAttachments() -{ - LLPointer cb = NULL; - for (uuid_vec_t::const_iterator itPendingAttachLink = mPendingAttachLinks.begin(); itPendingAttachLink != mPendingAttachLinks.end(); ++itPendingAttachLink) - { - const LLUUID& idAttachItem = *itPendingAttachLink; - if ( (gAgentAvatarp->isWearingAttachment(idAttachItem)) && (!isLinkInCOF(idAttachItem)) ) - { -// if (!cb) -// cb = new LLRegisterAttachmentCallback(idAttachItem); - // One LLInventoryCallback instance should handle multiple items but thanks to AIS we don't currently have access to the UUIDs of the new links - // so we need one instance per needed link - yay for progress - cb = new LLRegisterAttachmentCallback(idAttachItem); - LLAppearanceMgr::addCOFItemLink(idAttachItem, cb); - } - } -} + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT unregistering attachment " + << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; + gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); -void LLAppearanceMgr::clearPendingAttachment(const LLUUID& idItem) -{ - uuid_vec_t::iterator itPendingAttachLink = std::find(mPendingAttachLinks.begin(), mPendingAttachLinks.end(), idItem); - if (itPendingAttachLink != mPendingAttachLinks.end()) + LLAttachmentsMgr::instance().onDetachCompleted(item_id); + if (mAttachmentInvLinkEnabled && isLinkedInCOF(item_id)) { - mPendingAttachLinks.erase(itPendingAttachLink); + LL_DEBUGS("Avatar") << "ATT removing COF link for attachment " + << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; + LLAppearanceMgr::removeCOFItemLinks(item_id); } -} - -void LLAppearanceMgr::onRegisterAttachmentComplete(const LLUUID& idAttachItem) -{ - // Remove the attachment from the pending list - clearPendingAttachment(idAttachItem); - - // It may have been detached already in which case we should remove the COF link - if ( (isAgentAvatarValid()) && (!gAgentAvatarp->isWearingAttachment(idAttachItem)) ) + else { - removeCOFItemLinks(idAttachItem); + //LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; } } -// [/SL:KB] BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const { @@ -4852,14 +4724,6 @@ BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const return FALSE; } -// static -bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id) -{ - const LLUUID& target_id = gInventory.getLinkedItemID(obj_id); - LLLinkedItemIDMatches find_links(target_id); - return gInventory.hasMatchingDirectDescendent(LLAppearanceMgr::instance().getCOF(), find_links); -} - BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const { if (!getIsInCOF(obj_id)) return FALSE; @@ -4978,10 +4842,56 @@ void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb) } } +void add_wearable_type_counts(const uuid_vec_t& ids, + S32& clothing_count, + S32& bodypart_count, + S32& object_count, + S32& other_count) +{ + for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + const LLUUID& item_id_to_wear = *it; + LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear); + if (item_to_wear) + { + if (item_to_wear->getType() == LLAssetType::AT_CLOTHING) + { + clothing_count++; + } + else if (item_to_wear->getType() == LLAssetType::AT_BODYPART) + { + bodypart_count++; + } + else if (item_to_wear->getType() == LLAssetType::AT_OBJECT) + { + object_count++; + } + else + { + other_count++; + } + } + else + { + other_count++; + } + } +} + void wear_multiple(const uuid_vec_t& ids, bool replace) { - LLPointer cb = new LLUpdateAppearanceOnDestroy; - LLAppearanceMgr::instance().wearItemsOnAvatar(ids, false, replace, cb); + S32 clothing_count = 0; + S32 bodypart_count = 0; + S32 object_count = 0; + S32 other_count = 0; + add_wearable_type_counts(ids, clothing_count, bodypart_count, object_count, other_count); + + LLPointer cb = NULL; + if (clothing_count > 0 || bodypart_count > 0) + { + cb = new LLUpdateAppearanceOnDestroy; + } + LLAppearanceMgr::instance().wearItemsOnAvatar(ids, true, replace, cb); } // SLapp for easy-wearing of a stock (library) avatar @@ -5020,7 +4930,7 @@ class LLWearFolderHandler : public LLCommandHandler LLAppearanceMgr::getInstance()->wearInventoryCategory(category, true, false); // *TODOw: This may not be necessary if initial outfit is chosen already -- josh - gAgent.setGenderChosen(TRUE); + gAgent.setOutfitChosen(TRUE); } } diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 70323b5264..46edd4a99f 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -58,7 +58,6 @@ class LLAppearanceMgr: public LLSingleton // [SL:KB] - Patch: Appearance-MixedViewers | Checked: 2010-04-02 (Catznip-3.0.0a) | Added: Catznip-2.0.0a void updateAppearanceFromInitialWearables(LLInventoryObject::const_object_list_t& initial_items); // [/SL:KB] - bool needToSaveCOF(); void updateCOF(const LLUUID& category, bool append = false); // [RLVa:KB] - Checked: 2010-03-05 (RLVa-1.2.0a) | Added: RLVa-1.2.0a void updateCOF(LLInventoryModel::item_array_t& body_items_new, LLInventoryModel::item_array_t& wear_items_new, @@ -115,7 +114,6 @@ class LLAppearanceMgr: public LLSingleton // Copy all items in a category. void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id, LLPointer cb); - void copyItems(const LLUUID& dst_id, LLInventoryModel::item_array_t* items, LLPointer cb); // Find the Current Outfit folder. const LLUUID getCOF() const; @@ -156,6 +154,9 @@ class LLAppearanceMgr: public LLSingleton // Attachment link management void unregisterAttachment(const LLUUID& item_id); void registerAttachment(const LLUUID& item_id); +// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2015-06-24 (Catznip-3.7) + bool getAttachmentInvLinkEnable() { return mAttachmentInvLinkEnabled; } +// [/SL:KB] void setAttachmentInvLinkEnable(bool val); // Add COF link to individual item. @@ -246,13 +247,6 @@ class LLAppearanceMgr: public LLSingleton void requestServerAppearanceUpdate(); - void incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr = NULL); - - U32 getNumAttachmentsInCOF(); - - // *HACK Remove this after server side texture baking is deployed on all sims. - void incrementCofVersionLegacy(); - void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; } std::string getAppearanceServiceURL() const; @@ -279,11 +273,8 @@ class LLAppearanceMgr: public LLSingleton LLInventoryModel::item_array_t& gest_items, bool follow_folder_links = false); - void purgeCategory(const LLUUID& category, bool keep_outfit_links); - static void onOutfitRename(const LLSD& notification, const LLSD& response); - bool mAttachmentInvLinkEnabled; bool mOutfitIsDirty; bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls. @@ -299,20 +290,11 @@ class LLAppearanceMgr: public LLSingleton std::auto_ptr mUnlockOutfitTimer; // Set of temp attachment UUIDs that should be removed - typedef std::set doomed_temp_attachments_t; + typedef uuid_set_t doomed_temp_attachments_t; doomed_temp_attachments_t mDoomedTempAttachmentIDs; void addDoomedTempAttachment(const LLUUID& id_to_remove); -// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-2.1) -public: - void linkPendingAttachments(); - void clearPendingAttachment(const LLUUID& idItem); - void onRegisterAttachmentComplete(const LLUUID& idAttachItem); -private: - uuid_vec_t mPendingAttachLinks; -// [/SL:KB] - ////////////////////////////////////////////////////////////////////////////////// // Item-specific convenience functions public: @@ -320,11 +302,6 @@ class LLAppearanceMgr: public LLSingleton BOOL getIsInCOF(const LLUUID& obj_id) const; // Is this in the COF and can the user delete it from the COF? BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const; - - /** - * Checks if COF contains link to specified object. - */ - static bool isLinkInCOF(const LLUUID& obj_id); }; class LLUpdateAppearanceOnDestroy: public LLInventoryCallback @@ -345,21 +322,29 @@ class LLUpdateAppearanceOnDestroy: public LLInventoryCallback }; // [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-08-31 (Catznip-2.1) -class LLRegisterAttachmentCallback : public LLInventoryCallback +class LLUpdateAppearanceAndEditWearableOnDestroy: public LLInventoryCallback { public: - LLRegisterAttachmentCallback(const LLUUID& idAttachItem) : m_idAttachItem(idAttachItem) {} - /*virtual*/ void fire(const LLUUID&) - { - // NOTE: AISCommand::getResponseUUID() currently returns false so the passed UUID is NULL and hence useless - LLAppearanceMgr::instance().onRegisterAttachmentComplete(m_idAttachItem); - } -protected: - LLUUID m_idAttachItem; + LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id); + + /* virtual */ void fire(const LLUUID& item_id) {} + + ~LLUpdateAppearanceAndEditWearableOnDestroy(); + +private: + LLUUID mItemID; }; -// [/SL:KB] -void edit_wearable_and_customize_avatar(LLUUID item_id); +class LLRequestServerAppearanceUpdateOnDestroy: public LLInventoryCallback +{ +public: + LLRequestServerAppearanceUpdateOnDestroy() {} + ~LLRequestServerAppearanceUpdateOnDestroy(); + + /* virtual */ void fire(const LLUUID& item_id) {} +}; + +void edit_wearable_and_customize_avatar(LLUUID item_id); LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 07a6a7244b..b058d76098 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -36,7 +36,7 @@ #include "hippogridmanager.h" #include "hippolimits.h" -#include "sgversion.h" +#include "llversioninfo.h" #include "llfeaturemanager.h" #include "lluictrlfactory.h" #include "lltexteditor.h" @@ -47,11 +47,11 @@ #include "llagent.h" #include "llagentcamera.h" #include "llagentwearables.h" +#include "llimprocessing.h" #include "llwindow.h" #include "llviewerstats.h" #include "llmarketplacefunctions.h" #include "llmarketplacenotifications.h" -#include "llmd5.h" #include "llmeshrepository.h" #include "llmodaldialog.h" #include "llpumpio.h" @@ -63,7 +63,6 @@ #include "llares.h" #include "llcurl.h" #include "llcalc.h" -#include "lltexturestats.h" #include "llviewerwindow.h" #include "llviewerdisplay.h" #include "llviewermedia.h" @@ -85,14 +84,19 @@ #include "llprogressview.h" #include "llvocache.h" #include "llvopartgroup.h" +// [SL:KB] - Patch: Appearance-Misc | Checked: 2013-02-12 (Catznip-3.4) +#include "llappearancemgr.h" +// [/SL:KB] #include "llfloaterteleporthistory.h" -#include "llcrashlogger.h" #include "llweb.h" #include "llsecondlifeurls.h" +#include "llavatarrenderinfoaccountant.h" +#include "llskinningutil.h" // Linden library includes #include "llavatarnamecache.h" #include "lldiriterator.h" +#include "llexperiencecache.h" #include "llimagej2c.h" #include "llmemory.h" #include "llprimitive.h" @@ -133,8 +137,6 @@ #include "llassetstorage.h" #include "llpolymesh.h" #include "llaudioengine.h" -#include "llstreamingaudio.h" -#include "llviewermenu.h" #include "llselectmgr.h" #include "lltrans.h" #include "lltracker.h" @@ -142,7 +144,6 @@ #include "llworldmapview.h" #include "llpostprocess.h" #include "llwlparammanager.h" -#include "llwaterparammanager.h" #include "lldebugview.h" #include "llconsole.h" @@ -158,11 +159,11 @@ // Included so that constants/settings might be initialized // in save_settings_to_globals() +#include "aosystem.h" #include "llbutton.h" #include "llcombobox.h" -#include "llstatusbar.h" +#include "floaterlocalassetbrowse.h" #include "llsurface.h" -#include "llvosky.h" #include "llvotree.h" #include "llfolderview.h" #include "lltoolbar.h" @@ -191,15 +192,13 @@ #include "llviewerthrottle.h" #include "llparcel.h" #include "llviewerassetstats.h" +#include "NACLantispam.h" #include "llmainlooprepeater.h" // [RLVa:KB] #include "rlvhandler.h" // [/RLVa:KB] -// [SL:KB] - Patch: Appearance-Misc | Checked: 2013-02-12 (Catznip-3.4) -#include "llappearancemgr.h" -// [/SL:KB] // *FIX: These extern globals should be cleaned up. // The globals either represent state/config/resource-storage of either @@ -213,6 +212,58 @@ // llviewernetwork.h #include "llviewernetwork.h" +#include + +#ifdef USE_CRASHPAD +#pragma warning(disable:4265) + +#include +#include +#include +#include +#include + +#include + +#include "llnotificationsutil.h" +#include "llversioninfo.h" + + +template +struct crashpad_annotation : public crashpad::Annotation { + std::array buffer; + crashpad_annotation(const char* name) : crashpad::Annotation(T, name, buffer.data()) + {} + void set(const std::string& src) { + //LL_INFOS() << name() << ": " << src.c_str() << LL_ENDL; + const size_t min_size = llmin(SIZE, src.size()); + memcpy(buffer.data(), src.data(), min_size); + buffer.data()[SIZE - 1] = '\0'; + SetSize(min_size); + } +}; +#define DEFINE_CRASHPAD_ANNOTATION(name, len) \ +static crashpad_annotation g_crashpad_annotation_##name##_buffer("sentry[tags]["#name"]"); +#define DEFINE_CRASHPAD_ANNOTATION_EXTRA(name, len) \ +static crashpad_annotation g_crashpad_annotation_##name##_buffer("sentry[extra]["#name"]"); +#define SET_CRASHPAD_ANNOTATION_VALUE(name, value) \ +g_crashpad_annotation_##name##_buffer.set(value); +#else +#define SET_CRASHPAD_ANNOTATION_VALUE(name, value) +#define DEFINE_CRASHPAD_ANNOTATION_EXTRA(name, len) +#define DEFINE_CRASHPAD_ANNOTATION(name, len) +#endif + +DEFINE_CRASHPAD_ANNOTATION_EXTRA(fatal_message, 512); +DEFINE_CRASHPAD_ANNOTATION(grid_name, 64); +DEFINE_CRASHPAD_ANNOTATION(region_name, 64); +DEFINE_CRASHPAD_ANNOTATION_EXTRA(cpu_string, 128); +DEFINE_CRASHPAD_ANNOTATION_EXTRA(gpu_string, 128); +DEFINE_CRASHPAD_ANNOTATION_EXTRA(gl_version, 128); +DEFINE_CRASHPAD_ANNOTATION_EXTRA(session_duration, 32); +DEFINE_CRASHPAD_ANNOTATION_EXTRA(startup_state, 32); +DEFINE_CRASHPAD_ANNOTATION_EXTRA(memory_sys, 32); +DEFINE_CRASHPAD_ANNOTATION_EXTRA(memory_alloc, 32); ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor // @@ -238,7 +289,8 @@ F32 gSimLastTime; // Used in LLAppViewer::init and send_stats() F32 gSimFrames; BOOL gShowObjectUpdates = FALSE; -BOOL gUseQuickTime = TRUE; + +S32 gLastExecDuration = -1; // (<0 indicates unknown) BOOL gAcceptTOS = FALSE; BOOL gAcceptCriticalMessage = FALSE; @@ -253,12 +305,12 @@ LLPumpIO* gServicePump = NULL; BOOL gPacificDaylightTime = FALSE; -U64 gFrameTime = 0; -F32 gFrameTimeSeconds = 0.f; -F32 gFrameIntervalSeconds = 0.f; +U64MicrosecondsImplicit gFrameTime = 0; +F32SecondsImplicit gFrameTimeSeconds = 0.f; +F32SecondsImplicit gFrameIntervalSeconds = 0.f; F32 gFPSClamped = 10.f; // Pretend we start at target rate. F32 gFrameDTClamped = 0.f; // Time between adjacent checks to network for packets -U64 gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds +U64MicrosecondsImplicit gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds U32 gFrameStalls = 0; const F64 FRAME_STALL_THRESHOLD = 1.0; @@ -279,7 +331,7 @@ BOOL gUseWireframe = FALSE; LLVFS* gStaticVFS = NULL; LLMemoryInfo gSysMemory; -U64 gMemoryAllocated = 0; // updated in display_stats() in llviewerdisplay.cpp +U64Bytes gMemoryAllocated(0); // updated in display_stats() in llviewerdisplay.cpp std::string gLastVersionChannel; @@ -300,8 +352,9 @@ BOOL gLogoutInProgress = FALSE; //////////////////////////////////////////////////////////// // Internal globals... that should be removed. static std::string gArgs; - +const int MAX_MARKER_LENGTH = 1024; const std::string MARKER_FILE_NAME("Singularity.exec_marker"); +const std::string START_MARKER_FILE_NAME("Singularity.start_marker");; const std::string ERROR_MARKER_FILE_NAME("Singularity.error_marker"); const std::string LLERROR_MARKER_FILE_NAME("Singularity.llerror_marker"); const std::string LOGOUT_MARKER_FILE_NAME("Singularity.logout_marker"); @@ -370,7 +423,6 @@ void init_default_trans_args() const char *VFS_DATA_FILE_BASE = "data.db2.x."; const char *VFS_INDEX_FILE_BASE = "index.db2.x."; -static std::string gSecondLife; std::string gWindowTitle; std::string gLoginPage; @@ -416,45 +468,6 @@ static void ui_audio_callback(const LLUUID& uuid) } } -void request_initial_instant_messages() -{ - static BOOL requested = FALSE; - if (!requested - && gMessageSystem - && LLMuteList::getInstance()->isLoaded() - && isAgentAvatarValid()) - { - // Auto-accepted inventory items may require the avatar object - // to build a correct name. Likewise, inventory offers from - // muted avatars require the mute list to properly mute. - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RetrieveInstantMessages); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gAgent.sendReliableMessage(); - requested = TRUE; - } -} - -// A settings system callback for CrashSubmitBehavior -bool handleCrashSubmitBehaviorChanged(const LLSD& newvalue) -{ - S32 cb = newvalue.asInteger(); - const S32 NEVER_SUBMIT_REPORT = 2; - if(cb == NEVER_SUBMIT_REPORT) - { -// LLWatchdog::getInstance()->cleanup(); // SJB: cleaning up a running watchdog thread is unsafe - LLAppViewer::instance()->destroyMainloopTimeout(); - } - else if(gSavedSettings.getBOOL("WatchdogEnabled") == TRUE) - { - // Don't re-enable the watchdog when we change the setting; this may get called before it's started -// LLWatchdog::getInstance()->init(); - } - return true; -} - // Use these strictly for things that are constructed at startup, // or for things that are performance critical. JC static void settings_to_globals() @@ -464,8 +477,9 @@ static void settings_to_globals() BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall"); BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight"); + extern S32 MENU_BAR_HEIGHT; MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight"); - MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth"); + extern S32 STATUS_BAR_HEIGHT; STATUS_BAR_HEIGHT = gSavedSettings.getS32("StatusBarHeight"); LLCOMBOBOX_HEIGHT = BTN_HEIGHT - 2; @@ -473,7 +487,7 @@ static void settings_to_globals() LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize")); - LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLCoreProfile"); + LLRender::sGLCoreProfile = LLGLSLShader::sNoFixedFunction = gSavedSettings.getBOOL("RenderGLCoreProfile"); LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); @@ -538,7 +552,6 @@ LLAppViewer* LLAppViewer::sInstance = NULL; const std::string LLAppViewer::sGlobalSettingsName = "Global"; const std::string LLAppViewer::sPerAccountSettingsName = "PerAccount"; -const std::string LLAppViewer::sCrashSettingsName = "CrashSettings"; LLTextureCache* LLAppViewer::sTextureCache = NULL; LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL; @@ -546,7 +559,7 @@ LLTextureFetch* LLAppViewer::sTextureFetch = NULL; LLAppViewer::LLAppViewer() : mMarkerFile(), - mLogoutMarkerFile(NULL), + mLogoutMarkerFile(), mReportedCrash(false), mNumSessions(0), mPurgeCache(false), @@ -558,17 +571,48 @@ LLAppViewer::LLAppViewer() : mMainloopTimeout(NULL), mAgentRegionLastAlive(false) { - if(NULL != sInstance) + if(nullptr != sInstance) { LL_ERRS() << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << LL_ENDL; } - mDumpPath =""; - // Need to do this initialization before we do anything else, since anything // that touches files should really go through the lldir API - gDirUtilp->initAppDirs("SecondLife"); + { + std::string newview_path; + const auto& exe_dir = gDirUtilp->getExecutableDir(); + auto build_dir_pos = exe_dir.rfind("build-"); + if (build_dir_pos != std::string::npos) + { + // ...we're in a dev checkout + newview_path = gDirUtilp->add(gDirUtilp->add(exe_dir.substr(0, build_dir_pos), "indra"), "newview"); + if (LLFile::isdir(newview_path)) + LL_INFOS() << "Running in dev checkout with newview " << newview_path << LL_ENDL; + else newview_path.clear(); + } + + gDirUtilp->initAppDirs("SecondLife", newview_path); + } + // + // IMPORTANT! Do NOT put anything that will write + // into the log files during normal startup until AFTER + // we run the "program crashed last time" error handler below. + // sInstance = this; + + + initLoggingAndGetLastDuration(); + + processMarkerFiles(); + // + // OK to write stuff to logs now, we've now crash reported if necessary + // +#if !defined(USE_CRASHPAD) + // write dump files to a per-run dump directory to avoid multiple viewer issues. + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); + + setDebugFileNames(logdir); +#endif } @@ -577,13 +621,13 @@ LLAppViewer::~LLAppViewer() destroyMainloopTimeout(); // If we got to this destructor somehow, the app didn't hang. - removeMarkerFile(); + removeMarkerFiles(); } class LLUITranslationBridge : public LLTranslationBridge { public: - virtual std::string getString(const std::string &xml_desc) + std::string getString(const std::string &xml_desc) override { return LLTrans::getString(xml_desc); } @@ -622,22 +666,168 @@ void fast_exit(int rc) } */ +#ifdef USE_CRASHPAD +base::FilePath databasePath() +{ + // Cache directory that will store crashpad information and minidumps + std::string crashpad_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashpad"); + return base::FilePath(ll_convert_string_to_wide(crashpad_path)); +} + +static void handleCrashSubmitBehaviorChanged(LLControlVariable*, const LLSD& val) +{ + if (auto db = crashpad::CrashReportDatabase::Initialize(databasePath())) + { + if (auto settings = db->GetSettings()) + { + settings->SetUploadsEnabled(val.asBoolean()); + } + } +} + +static void configureCrashUploads() +{ + auto database = databasePath(); + auto db = crashpad::CrashReportDatabase::InitializeWithoutCreating(database); + if (!db) return; + auto settings = db->GetSettings(); + if (!settings) return; + auto control = gSavedSettings.getControl("CrashSubmitBehavior"); + control->getSignal()->connect(handleCrashSubmitBehaviorChanged); + if (control->get().asInteger() == -1) + { + LLNotificationsUtil::add("SubmitCrashReports", LLSD(), LLSD(), [control](const LLSD& p, const LLSD& f) { + control->set(!LLNotificationsUtil::getSelectedOption(p, f)); + }); + } + + if (!settings->SetUploadsEnabled(control->get().asInteger() == 1)) + { + LL_WARNS() << "Failed to set enable upload of crash database." << LL_ENDL; + } +} +#endif + +void LLAppViewer::initCrashReporting() +{ +#ifdef USE_CRASHPAD + // Path to the out-of-process handler executable + std::string handler_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "crashpad_handler.exe"); + if (!gDirUtilp->fileExists(handler_path)) + { + LL_ERRS() << "Failed to initialize crashpad due to missing handler executable." << LL_ENDL; + return; + } + base::FilePath handler(ll_convert_string_to_wide(handler_path)); + + auto database = databasePath(); + + // URL used to submit minidumps to + std::string url(CRASHPAD_URL); + + // Optional annotations passed via --annotations to the handler + std::map annotations; + +#if 0 + unsigned char node_id[6]; + if (LLUUID::getNodeID(node_id) > 0) + { + char md5str[MD5HEX_STR_SIZE] = { 0 }; + LLMD5 hashed_unique_id; + hashed_unique_id.update(node_id, 6); + hashed_unique_id.finalize(); + hashed_unique_id.hex_digest((char*)md5str); + annotations.emplace("sentry[contexts][app][device_app_hash]", std::string(md5str)); + } +#endif + + annotations.emplace("sentry[contexts][app][app_name]", LLVersionInfo::getChannel()); + annotations.emplace("sentry[contexts][app][app_version]", LLVersionInfo::getVersion()); + annotations.emplace("sentry[contexts][app][app_build]", LLVersionInfo::getChannelAndVersion()); + + annotations.emplace("sentry[release]", LLVersionInfo::getChannelAndVersion()); + + annotations.emplace("sentry[tags][second_instance]", fmt::to_string(isSecondInstance())); + //annotations.emplace("sentry[tags][bitness]", fmt::to_string(ADDRESS_SIZE)); + annotations.emplace("sentry[tags][bitness]", +#if defined(_WIN64) || defined(__x86_64__) + "64" +#else + "32" +#endif + ); + + // Optional arguments to pass to the handler + std::vector arguments; + arguments.push_back("--no-rate-limit"); + arguments.push_back("--monitor-self"); + + if (isSecondInstance()) + { + arguments.push_back("--no-periodic-tasks"); + } + else + { + auto db = crashpad::CrashReportDatabase::Initialize(database); + if (db == nullptr) + { + LL_WARNS() << "Failed to initialize crashpad database at path: " << wstring_to_utf8str(database.value()) << LL_ENDL; + return; + } + + auto prune_condition = crashpad::PruneCondition::GetDefault(); + if (prune_condition != nullptr) + { + auto ret = crashpad::PruneCrashReportDatabase(db.get(), prune_condition.get()); + LL_INFOS() << "Pruned " << ret << " reports from the crashpad database." << LL_ENDL; + } + } + + crashpad::CrashpadClient client; + bool success = client.StartHandler( + handler, + database, + database, + url, + annotations, + arguments, + /* restartable */ true, + /* asynchronous_start */ false + ); + if (success) + LL_INFOS() << "Crashpad init success" << LL_ENDL; + else + LL_WARNS() << "FAILED TO INITIALIZE CRASHPAD" << LL_ENDL; +#endif +} + bool LLAppViewer::init() -{ +{ +#ifdef USE_CRASHPAD + initCrashReporting(); +#endif + + writeDebugInfo(); + setupErrorHandling(); + { + auto fn = boost::bind([](const LLSD& stateInfo) -> bool { + SET_CRASHPAD_ANNOTATION_VALUE(startup_state, stateInfo["str"].asString()); + return false; + }, _1); + LLStartUp::getStateEventPump().listen<::LLEventListener>("LLAppViewer", fn); + } + // // Start of the application // - // IMPORTANT! Do NOT put anything that will write - // into the log files during normal startup until AFTER - // we run the "program crashed last time" error handler below. - // LLFastTimer::reset(); // initialize LLWearableType translation bridge. // Memory will be cleaned up in ::cleanupClass() - LLWearableType::initClass(new LLUITranslationBridge()); + LLTranslationBridge::ptr_t trans = std::make_shared(); + LLWearableType::initClass(trans); // // We can call this early. @@ -652,17 +842,14 @@ bool LLAppViewer::init() // set skin search path to default, will be overridden later // this allows simple skinned file lookups to work - gDirUtilp->setSkinFolder("default"); + gDirUtilp->setSkinFolder("default", "en-us"); - initLogging(); +// initLoggingAndGetLastDuration(); // // Curl must be initialized before any thread is running. AICurlInterface::initCurl(); - // Logging is initialized. Now it's safe to start the error thread. - startErrorThread(); - // // OK to write stuff to logs now, we've now crash reported if necessary // @@ -673,6 +860,9 @@ bool LLAppViewer::init() LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ; + // initialize skinning util + LLSkinningUtil::initClass(); + //set the max heap size. initMaxHeapSize() ; @@ -694,25 +884,9 @@ bool LLAppViewer::init() AIHTTPTimeoutPolicy::setDefaultCurlTimeout(policy_tmp); } - // Check if we have a crash report to send - LLCrashLogger crashLogger; - crashLogger.checkCrashDump(); - - // write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues. - std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); - mDumpPath = logdir; - setMiniDumpDir(logdir); - logdir += gDirUtilp->getDirDelimiter(); - setDebugFileNames(logdir); - mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); - { - // Viewer metrics initialization - //static LLCachedControl metrics_submode(gSavedSettings, - // "QAModeMetrics", - // false, - // "Enables QA features (logging, faster cycling) for metrics collector"); + { if (gSavedSettings.getBOOL("QAModeMetrics")) { app_metrics_qa_mode = true; @@ -725,16 +899,20 @@ bool LLAppViewer::init() LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ; // Load art UUID information, don't require these strings to be declared in code. - std::string colors_base_filename = gDirUtilp->findSkinnedFilename("colors_base.xml"); - LL_DEBUGS("InitInfo") << "Loading base colors from " << colors_base_filename << LL_ENDL; - gColors.loadFromFileLegacy(colors_base_filename, FALSE, TYPE_COL4U); - + for(auto& colors_base_filename : gDirUtilp->findSkinnedFilenames(LLDir::SKINBASE, "colors_base.xml", LLDir::ALL_SKINS)) + { + LL_DEBUGS("InitInfo") << "Loading colors from " << colors_base_filename << LL_ENDL; + gColors.loadFromFileLegacy(colors_base_filename, FALSE, TYPE_COL4U); + } // Load overrides from user colors file - std::string user_colors_filename = gDirUtilp->findSkinnedFilename("colors.xml"); - LL_DEBUGS("InitInfo") << "Loading user colors from " << user_colors_filename << LL_ENDL; - if (gColors.loadFromFileLegacy(user_colors_filename, FALSE, TYPE_COL4U) == 0) + for (auto& colors_base_filename : gDirUtilp->findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", LLDir::ALL_SKINS)) { - LL_DEBUGS("InitInfo") << "Cannot load user colors from " << user_colors_filename << LL_ENDL; + gColors.loadFromFileLegacy(colors_base_filename, FALSE, TYPE_COL4U); + LL_DEBUGS("InitInfo") << "Loading user colors from " << colors_base_filename << LL_ENDL; + if (gColors.loadFromFileLegacy(colors_base_filename, FALSE, TYPE_COL4U) == 0) + { + LL_DEBUGS("InitInfo") << "Cannot load user colors from " << colors_base_filename << LL_ENDL; + } } // Widget construction depends on LLUI being initialized @@ -747,6 +925,11 @@ bool LLAppViewer::init() &LLUI::getScaleFactor()); LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; + // NOW LLUI::getLanguage() should work. gDirUtilp must know the language + // for this session ASAP so all the file-loading commands that follow, + // that use findSkinnedFilenames(), will include the localized files. + gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), LLUI::getLanguage()); + LLUICtrlFactory::getInstance()->setupPaths(); // update paths with correct language set // Setup LLTrans after LLUI::initClass has been called. @@ -755,16 +938,13 @@ bool LLAppViewer::init() // Setup notifications after LLUI::initClass() has been called. LLNotifications::instance().createDefaultChannels(); LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ; - - writeSystemInfo(); - // Build a string representing the current version number. - gCurrentVersion = llformat("%s %d.%d.%d.%d", - gVersionChannel, - gVersionMajor, - gVersionMinor, - gVersionPatch, - gVersionBuild ); +#ifdef USE_CRASHPAD + // Now that we have Settings and Notifications, we can configure crash uploads + configureCrashUploads(); +#endif + + writeSystemInfo(); ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -779,10 +959,6 @@ bool LLAppViewer::init() LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL; LL_INFOS("InitInfo") << "libcurl version is: " << LLCurl::getVersionString() << LL_ENDL; - // Get the single value from the crash settings file, if it exists - std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); - gCrashSettings.loadFromFile(crash_settings_filename); - ///////////////////////////////////////////////// // OS-specific login dialogs ///////////////////////////////////////////////// @@ -810,7 +986,14 @@ bool LLAppViewer::init() LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null)); LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null)); LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor); - + + LL_INFOS("InitInfo") << "UI initialization is done." << LL_ENDL ; + + // Load translations for tooltips + LLFloater::initClass(); + + ///////////////////////////////////////////////// + LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated ///////////////////////////////////////////////// @@ -833,7 +1016,7 @@ bool LLAppViewer::init() #endif LLMIMETypes::parseMIMETypes( mime_types_name ); - // Copy settings to globals. *TODO: Remove or move to appropriage class initializers + // Copy settings to globals. *TODO: Remove or move to appropriate class initializers settings_to_globals(); // Setup settings listeners settings_setup_listeners(); @@ -873,10 +1056,11 @@ bool LLAppViewer::init() if (!initCache()) { + LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL; std::ostringstream msg; msg << LLTrans::getString("MBUnableToAccessFile"); OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); - return 1; + return true; } LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ; @@ -901,11 +1085,13 @@ bool LLAppViewer::init() gGLManager.getGLInfo(gDebugInfo); gGLManager.printGLInfoString(); + writeDebugInfo(); + // Load Default bindings load_default_bindings(gSavedSettings.getBOOL("LiruUseZQSDKeys")); // If we don't have the right GL requirements, exit. - if (!gGLManager.mHasRequirements && !gNoRender) + if (!gGLManager.mHasRequirements) { // can't use an alert here since we're exiting and // all hell breaks lose. @@ -915,10 +1101,9 @@ bool LLAppViewer::init() msg, LLStringUtil::null, OSMB_OK); - return 0; + return false; } -#if (_M_IX86_FP > 1 || defined(__SSE2__)) // Without SSE2 support we will crash almost immediately, warn here. if (!gSysCPU.hasSSE2()) { @@ -930,23 +1115,8 @@ bool LLAppViewer::init() msg, LLStringUtil::null, OSMB_OK); - return 0; - } -#elif (_M_IX86_FP == 1 || defined(__SSE__)) - // Without SSE support we will crash almost immediately, warn here. - if (!gSysCPU.hasSSE()) - { - // can't use an alert here since we're exiting and - // all hell breaks lose. - std::string msg = LNotificationTemplates::instance().getGlobalString("UnsupportedCPUSSE2"); - LLStringUtil::format(msg,LLTrans::getDefaultArgs()); - OSMessageBox( - msg, - LLStringUtil::null, - OSMB_OK); - return 0; + return false; } -#endif // alert the user if they are using unsupported hardware if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware")) @@ -962,9 +1132,8 @@ bool LLAppViewer::init() // get RAM data from XML std::stringstream minRAMString(LLNotificationTemplates::instance().getGlobalString("UnsupportedRAMAmount")); - U64 minRAM = 0; + U64Bytes minRAM; minRAMString >> minRAM; - minRAM = minRAM * 1024 * 1024; if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN) { @@ -978,7 +1147,7 @@ bool LLAppViewer::init() minSpecs += "\n"; unsupported = true; } - if(gSysMemory.getPhysicalMemoryClamped() < minRAM) + if(gSysMemory.getPhysicalMemoryKB() < minRAM) { minSpecs += LLNotificationTemplates::instance().getGlobalString("UnsupportedRAM"); minSpecs += "\n"; @@ -1005,8 +1174,11 @@ bool LLAppViewer::init() // save the graphics card gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString(); + writeDebugInfo(); + // Save the current version to the prefs file - gSavedSettings.setString("LastRunVersion", gCurrentVersion); + gSavedSettings.setString("LastRunVersion", + LLVersionInfo::getChannelAndVersion()); gSimLastTime = gRenderStartTime.getElapsedTimeF32(); gSimFrames = (F32)gFrameCount; @@ -1021,6 +1193,8 @@ bool LLAppViewer::init() gGLActive = FALSE; LLViewerMedia::initClass(); LL_INFOS("InitInfo") << "Viewer media initialized." << LL_ENDL ; + + writeDebugInfo(); return true; } @@ -1042,9 +1216,8 @@ void LLAppViewer::initMaxHeapSize() //currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB. //F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ; - - F32 max_heap_size_gb = gSavedSettings.getF32("MaxHeapSize") ; - + F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ; + //This is all a bunch of CRAP. We run LAA on windows. 64bit windows supports LAA out of the box. 32bit does not, unless PAE is on. #if LL_WINDOWS //http://msdn.microsoft.com/en-us/library/windows/desktop/ms684139%28v=vs.85%29.aspx @@ -1057,7 +1230,7 @@ void LLAppViewer::initMaxHeapSize() if(fnIsWow64Process && fnIsWow64Process(GetCurrentProcess(), &bWow64Process) && bWow64Process) { - max_heap_size_gb = 3.7f; + max_heap_size_gb = F32Gigabytes(3.7f); } else if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"), &hKey)) { @@ -1066,13 +1239,13 @@ void LLAppViewer::initMaxHeapSize() if(ERROR_SUCCESS == RegQueryValueEx(hKey, TEXT("PhysicalAddressExtension"), NULL, NULL, (LPBYTE)&dwResult, &dwSize)) { if(dwResult) - max_heap_size_gb = 3.7f; + max_heap_size_gb = F32Gigabytes(3.7f); } RegCloseKey(hKey); } #endif - BOOL enable_mem_failure_prevention = (BOOL)gSavedSettings.getBOOL("MemoryFailurePreventionEnabled") ; + BOOL enable_mem_failure_prevention = gSavedSettings.getBOOL("MemoryFailurePreventionEnabled") ; LLMemory::initMaxHeapSizeGB(max_heap_size_gb, enable_mem_failure_prevention) ; } @@ -1107,23 +1280,23 @@ void LLAppViewer::checkMemory() } } -static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages"); -static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep"); -static LLFastTimer::DeclareTimer FTM_YIELD("Yield"); - -static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache"); -static LLFastTimer::DeclareTimer FTM_DECODE("Image Decode"); -static LLFastTimer::DeclareTimer FTM_VFS("VFS Thread"); -static LLFastTimer::DeclareTimer FTM_LFS("LFS Thread"); -static LLFastTimer::DeclareTimer FTM_PAUSE_THREADS("Pause Threads"); -static LLFastTimer::DeclareTimer FTM_IDLE("Idle"); -static LLFastTimer::DeclareTimer FTM_PUMP("Pump"); -static LLFastTimer::DeclareTimer FTM_PUMP_ARES("Ares"); -static LLFastTimer::DeclareTimer FTM_PUMP_SERVICE("Service"); -static LLFastTimer::DeclareTimer FTM_SERVICE_CALLBACK("Callback"); -static LLFastTimer::DeclareTimer FTM_AGENT_AUTOPILOT("Autopilot"); -static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE("Update"); -static LLFastTimer::DeclareTimer FTM_STATEMACHINE("State Machine"); +static LLTrace::BlockTimerStatHandle FTM_MESSAGES("System Messages"); +static LLTrace::BlockTimerStatHandle FTM_SLEEP("Sleep"); +static LLTrace::BlockTimerStatHandle FTM_YIELD("Yield"); + +static LLTrace::BlockTimerStatHandle FTM_TEXTURE_CACHE("Texture Cache"); +static LLTrace::BlockTimerStatHandle FTM_DECODE("Image Decode"); +static LLTrace::BlockTimerStatHandle FTM_VFS("VFS Thread"); +static LLTrace::BlockTimerStatHandle FTM_LFS("LFS Thread"); +static LLTrace::BlockTimerStatHandle FTM_PAUSE_THREADS("Pause Threads"); +static LLTrace::BlockTimerStatHandle FTM_IDLE("Idle"); +static LLTrace::BlockTimerStatHandle FTM_PUMP("Pump"); +static LLTrace::BlockTimerStatHandle FTM_PUMP_ARES("Ares"); +static LLTrace::BlockTimerStatHandle FTM_PUMP_SERVICE("Service"); +static LLTrace::BlockTimerStatHandle FTM_SERVICE_CALLBACK("Callback"); +static LLTrace::BlockTimerStatHandle FTM_AGENT_AUTOPILOT("Autopilot"); +static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE("Update"); +static LLTrace::BlockTimerStatHandle FTM_STATEMACHINE("State Machine"); bool LLAppViewer::mainLoop() { @@ -1164,18 +1337,24 @@ bool LLAppViewer::mainLoop() BOOL restore_rendering_masks = FALSE; // Handle messages - while (!LLApp::isExiting()) + try { - LLFastTimer::nextFrame(); // Should be outside of any timer instances + while (!LLApp::isExiting()) + { + LLFastTimer::nextFrame(); // Should be outside of any timer instances + + //clear call stack records + LL_CLEAR_CALLSTACKS(); - //clear call stack records - LL_CLEAR_CALLSTACKS(); +#ifdef USE_CRASHPAD + // Not event based. Update per frame + SET_CRASHPAD_ANNOTATION_VALUE(session_duration, fmt::to_string(LLFrameTimer::getElapsedSeconds())); + SET_CRASHPAD_ANNOTATION_VALUE(memory_alloc, fmt::to_string((LLMemory::getCurrentRSS() >> 10)/1000.f)); +#endif - //check memory availability information - checkMemory() ; + //check memory availability information + checkMemory() ; - try - { // Check if we need to restore rendering masks. if (restore_rendering_masks) { @@ -1202,7 +1381,7 @@ bool LLAppViewer::mainLoop() if (gViewerWindow) { - LLFastTimer t2(FTM_MESSAGES); + LL_RECORD_BLOCK_TIME(FTM_MESSAGES); gViewerWindow->getWindow()->processMiscNativeEvents(); } @@ -1210,7 +1389,7 @@ bool LLAppViewer::mainLoop() if (gViewerWindow) { - LLFastTimer t2(FTM_MESSAGES); + LL_RECORD_BLOCK_TIME(FTM_MESSAGES); if (!restoreErrorTrap()) { LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL; @@ -1228,12 +1407,10 @@ bool LLAppViewer::mainLoop() #endif //memory leaking simulation - LLFloaterMemLeak* mem_leak_instance = - LLFloaterMemLeak::getInstance(); - if(mem_leak_instance) + if (auto mem_leak_instance = LLFloaterMemLeak::getInstance()) { - mem_leak_instance->idle() ; - } + mem_leak_instance->idle(); + } // canonical per-frame event mainloop.post(newFrame); @@ -1256,32 +1433,31 @@ bool LLAppViewer::mainLoop() gKeyboard->scanKeyboard(); if (gAgent.isCrouching()) gAgent.moveUp(-1); - } // Update state based on messages, user input, object idle. { pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! - LLFastTimer t3(FTM_IDLE); + LL_RECORD_BLOCK_TIME(FTM_IDLE); // bad_alloc!! idle(); if (gAres != NULL && gAres->isInitialized()) { pingMainloopTimeout("Main:ServicePump"); - LLFastTimer t4(FTM_PUMP); + LL_RECORD_BLOCK_TIME(FTM_PUMP); { - LLFastTimer t(FTM_PUMP_ARES); + LL_RECORD_BLOCK_TIME(FTM_PUMP_ARES); gAres->process(); } { - LLFastTimer t(FTM_PUMP_SERVICE); + LL_RECORD_BLOCK_TIME(FTM_PUMP_SERVICE); // this pump is necessary to make the login screen show up gServicePump->pump(); { - LLFastTimer t(FTM_SERVICE_CALLBACK); + LL_RECORD_BLOCK_TIME(FTM_SERVICE_CALLBACK); gServicePump->callback(); } } @@ -1304,11 +1480,11 @@ bool LLAppViewer::mainLoop() pingMainloopTimeout("Main:Display"); gGLActive = TRUE; display(); + pingMainloopTimeout("Main:Snapshot"); LLFloaterSnapshot::update(); // take snapshots gGLActive = FALSE; } - } pingMainloopTimeout("Main:Sleep"); @@ -1317,23 +1493,24 @@ bool LLAppViewer::mainLoop() // Sleep and run background threads { - LLFastTimer t2(FTM_SLEEP); + LL_RECORD_BLOCK_TIME(FTM_SLEEP); static const LLCachedControl run_multiple_threads("RunMultipleThreads",false); static const LLCachedControl yield_time("YieldTime", -1); // yield some time to the os based on command line option if(yield_time >= 0) { - LLFastTimer t(FTM_YIELD); + LL_RECORD_BLOCK_TIME(FTM_YIELD); ms_sleep(yield_time); } // yield cooperatively when not running as foreground window if ( gNoRender || (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) - || !gFocusMgr.getAppHasFocus()) + || (!gFocusMgr.getAppHasFocus() && !AIFilePicker::activePicker) ) { // Sleep if we're not rendering, or the window is minimized. - S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000); + static LLCachedControl s_bacground_yeild_time(gSavedSettings, "BackgroundYieldTime", 40); + S32 milliseconds_to_sleep = llclamp((S32)s_bacground_yeild_time, 0, 1000); // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads // of equal priority on Windows if (milliseconds_to_sleep > 0) @@ -1360,31 +1537,31 @@ bool LLAppViewer::mainLoop() ms_sleep(500); } - const F64 max_idle_time = run_multiple_threads ? 0.0 : llmin(.005*10.0*gFrameIntervalSeconds, 0.005); // 50ms/second, no more than 5ms/frame + const F64 max_idle_time = run_multiple_threads ? 0.0 : llmin(.005*10.0*gFrameIntervalSeconds.value(), 0.005); // 50ms/second, no more than 5ms/frame idleTimer.reset(); while(1) { S32 work_pending = 0; S32 io_pending = 0; { - LLFastTimer ftm(FTM_TEXTURE_CACHE); + LL_RECORD_BLOCK_TIME(FTM_TEXTURE_CACHE); work_pending += LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread } { - LLFastTimer ftm(FTM_DECODE); + LL_RECORD_BLOCK_TIME(FTM_DECODE); work_pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread } { - LLFastTimer ftm(FTM_DECODE); + LL_RECORD_BLOCK_TIME(FTM_DECODE); work_pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread } { - LLFastTimer ftm(FTM_VFS); + LL_RECORD_BLOCK_TIME(FTM_VFS); io_pending += LLVFSThread::updateClass(1); } { - LLFastTimer ftm(FTM_LFS); + LL_RECORD_BLOCK_TIME(FTM_LFS); io_pending += LLLFSThread::updateClass(1); } @@ -1415,54 +1592,29 @@ bool LLAppViewer::mainLoop() // LLAppViewer::getTextureFetch()->pause(); // Don't pause the fetch (IO) thread } //LLVFSThread::sLocal->pause(); // Prevent the VFS thread from running while rendering. - //LLLFSThread::sLocal->pause(); // Prevent the LFS thread from running while rendering. resumeMainloopTimeout(); pingMainloopTimeout("Main:End"); } } - catch(std::bad_alloc) - { - LLMemory::logMemoryInfo(TRUE) ; - - //stop memory leaking simulation - LLFloaterMemLeak* mem_leak_instance = - LLFloaterMemLeak::getInstance(); - if(mem_leak_instance) - { - mem_leak_instance->stop() ; - LL_WARNS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ; - } - else - { - //output possible call stacks to log file. - LLError::LLCallStacks::print() ; - LL_ERRS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ; - } - } + // Save snapshot for next time, if we made it through initialization + if (STATE_STARTED == LLStartUp::getStartupState()) + saveFinalSnapshot(); } - - // Save snapshot for next time, if we made it through initialization - if (STATE_STARTED == LLStartUp::getStartupState()) + catch(std::bad_alloc) { - try - { - saveFinalSnapshot(); - } - catch(std::bad_alloc) - { - LL_WARNS() << "Bad memory allocation when saveFinalSnapshot() is called!" << LL_ENDL ; + LLMemory::logMemoryInfo(TRUE); - //stop memory leaking simulation - LLFloaterMemLeak* mem_leak_instance = - LLFloaterMemLeak::getInstance(); - if(mem_leak_instance) - { - mem_leak_instance->stop() ; - } - } + //stop memory leaking simulation + if (auto mem_leak_instance = LLFloaterMemLeak::getInstance()) + mem_leak_instance->stop(); + + //output possible call stacks to log file. + LLError::LLCallStacks::print(); + + LL_ERRS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL; } delete gServicePump; @@ -1476,7 +1628,7 @@ bool LLAppViewer::mainLoop() void LLAppViewer::flushVFSIO() { - while (1) + while (true) { S32 pending = LLVFSThread::updateClass(0); pending += LLLFSThread::updateClass(0); @@ -1494,7 +1646,8 @@ extern void cleanup_pose_stand(void); bool LLAppViewer::cleanup() { //ditch LLVOAvatarSelf instance - gAgentAvatarp = NULL; + gAgentAvatarp = nullptr; + // remove any old breakpad minidump files from the log directory if (! isError()) @@ -1519,7 +1672,7 @@ bool LLAppViewer::cleanup() release_start_screen(); // just in case - LLError::logToFixedBuffer(NULL); + LLError::logToFixedBuffer(nullptr); // stop the fixed buffer recorder LL_INFOS() << "Cleaning Up" << LL_ENDL; @@ -1550,7 +1703,7 @@ bool LLAppViewer::cleanup() } delete gAssetStorage; - gAssetStorage = NULL; + gAssetStorage = nullptr; LLPolyMesh::freeAllMeshes(); @@ -1558,10 +1711,15 @@ bool LLAppViewer::cleanup() // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted. - LLWorldMap::getInstance()->reset(); // release any images + if (LLWorldMap::instanceExists()) + { + LLWorldMap::getInstance()->reset(); // release any images + } LLCalc::cleanUp(); + AOSystem::deleteSingleton(); + LL_INFOS() << "Global stuff deleted" << LL_ENDL; // Note: this is where LLFeatureManager::getInstance()-> used to be deleted. @@ -1590,7 +1748,7 @@ bool LLAppViewer::cleanup() */ // - + void cleanup_menus(); cleanup_menus(); // Wait for any pending VFS IO @@ -1613,6 +1771,9 @@ bool LLAppViewer::cleanup() // Clean up before GL is shut down because we might be holding on to objects with texture references LLSelectMgr::cleanupGlobals(); + // Clean up before shutdownGL. + LLPostProcess::cleanupClass(); + LL_INFOS() << "Shutting down OpenGL" << LL_ENDL; // Shut down OpenGL @@ -1624,7 +1785,7 @@ bool LLAppViewer::cleanup() // This may generate window reshape and activation events. // Therefore must do this before destroying the message system. delete gViewerWindow; - gViewerWindow = NULL; + gViewerWindow = nullptr; LL_INFOS() << "ViewerWindow deleted" << LL_ENDL; } @@ -1632,7 +1793,7 @@ bool LLAppViewer::cleanup() // viewer UI relies on keyboard so keep it aound until viewer UI isa gone delete gKeyboard; - gKeyboard = NULL; + gKeyboard = nullptr; LL_INFOS() << "Cleaning up Objects" << LL_ENDL; @@ -1640,10 +1801,6 @@ bool LLAppViewer::cleanup() LLViewerObject::cleanupVOClasses(); LLAvatarAppearance::cleanupClass(); - - LLAvatarAppearance::cleanupClass(); - - LLPostProcess::cleanupClass(); LLTracker::cleanupInstance(); @@ -1713,10 +1870,6 @@ bool LLAppViewer::cleanup() LL_INFOS() << "Saved settings" << LL_ENDL; } - std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); - // save all settings, even if equals defaults - gCrashSettings.saveToFile(crash_settings_filename, FALSE); - // Save URL history file LLURLHistory::saveFile("url_history.xml"); @@ -1725,18 +1878,20 @@ bool LLAppViewer::cleanup() LLFloaterTeleportHistory::saveFile("teleport_history.xml"); + LocalAssetBrowser::deleteSingleton(); // + // save mute list. gMuteList used to also be deleted here too. LLMuteList::getInstance()->cache(gAgent.getID()); + if (mPurgeOnExit) { LL_INFOS() << "Purging all cache files on exit" << LL_ENDL; gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),"*.*"); } - removeMarkerFile(); // Any crashes from here on we'll just have to ignore // moved this stuff from above to make it conditional here... - if(!anotherInstanceRunning()) + if(!mSecondInstance) { removeCacheFiles("*.wav"); removeCacheFiles("*.tmp"); @@ -1752,12 +1907,8 @@ bool LLAppViewer::cleanup() LL_INFOS() << "Not removing cache files. Other viewer instance detected." << LL_ENDL; } // - - removeDumpDir(); - writeDebugInfo(); - if(!gDirUtilp->getLindenUserDir(true).empty()) - LLViewerMedia::saveCookieFile(); + writeDebugInfo(); // Stop the plugin read thread if it's running. LLPluginProcessParent::setUseReadThread(false); @@ -1770,7 +1921,7 @@ bool LLAppViewer::cleanup() LLTimer idleTimer; idleTimer.reset(); const F64 max_idle_time = 5.f; // 5 seconds - while(1) + while(true) { S32 pending = 0; pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread @@ -1780,7 +1931,7 @@ bool LLAppViewer::cleanup() pending += LLLFSThread::updateClass(0); if (!pending) { - break; + break ; //done } else if (idleTimer.getElapsedTimeF64() >= max_idle_time) { @@ -1794,14 +1945,16 @@ bool LLAppViewer::cleanup() sTextureFetch->shutdown(); sTextureCache->shutdown(); sImageDecodeThread->shutdown(); + sTextureFetch->shutDownTextureCacheThread(); sTextureFetch->shutDownImageDecodeThread(); delete sTextureCache; - sTextureCache = NULL; + sTextureCache = nullptr; delete sTextureFetch; - sTextureFetch = NULL; + sTextureFetch = nullptr; delete sImageDecodeThread; - sImageDecodeThread = NULL; + sImageDecodeThread = nullptr; + LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL; @@ -1834,9 +1987,9 @@ bool LLAppViewer::cleanup() // For safety, the LLVFS has to be deleted *after* LLVFSThread. This should be cleaned up. // (LLVFS doesn't know about LLVFSThread so can't kill pending requests) -Steve delete gStaticVFS; - gStaticVFS = NULL; + gStaticVFS = nullptr; delete gVFS; - gVFS = NULL; + gVFS = nullptr; LLWatchdog::getInstance()->cleanup(); @@ -1851,7 +2004,6 @@ bool LLAppViewer::cleanup() // Cleanup settings last in case other classes reference them. gSavedSettings.cleanup(); gColors.cleanup(); - gCrashSettings.cleanup(); LLViewerAssetStatsFF::cleanup(); // If we're exiting to launch an URL, do that here so the screen @@ -1861,7 +2013,7 @@ bool LLAppViewer::cleanup() LL_INFOS() << "Launch file on quit." << LL_ENDL; #if LL_WINDOWS // Indicate an application is starting. - SetCursor(LoadCursor(NULL, IDC_WAIT)); + SetCursor(LoadCursor(nullptr, IDC_WAIT)); #endif // HACK: Attempt to wait until the screen res. switch is complete. @@ -1882,6 +2034,8 @@ bool LLAppViewer::cleanup() LLError::LLCallStacks::cleanup(); + removeMarkerFiles(); + MEM_TRACK_RELEASE LL_INFOS() << "Goodbye!" << LL_ENDL; @@ -1890,13 +2044,13 @@ bool LLAppViewer::cleanup() return true; } -// A callback for llerrs to call during the watchdog error. +// A callback for LL_ERRS() to call during the watchdog error. void watchdog_llerrs_callback(const std::string &error_string) { gLLErrorActivated = true; #ifdef LL_WINDOWS - RaiseException(0,0,0,0); + RaiseException(0,0,0,nullptr); #else raise(SIGQUIT); #endif @@ -1917,9 +2071,8 @@ bool LLAppViewer::initThreads() static const bool enable_threads = true; #endif - const S32 NEVER_SUBMIT_REPORT = 2; bool use_watchdog = gSavedSettings.getBOOL("WatchdogEnabled"); - bool send_reports = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) != NEVER_SUBMIT_REPORT; + bool send_reports = gSavedSettings.getS32("CrashSubmitBehavior") == 1; if(use_watchdog && send_reports) { LLWatchdog::getInstance()->init(watchdog_killer_callback); @@ -1956,8 +2109,8 @@ void errorCallback(const std::string &error_string) static std::string last_message; if(last_message != error_string) { - U32 response = OSMessageBox(error_string, "Crash Loop?", OSMB_YESNO); - if(response) + U32 response = OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_YESNO); + if (response == OSBTN_NO) { last_message = error_string; return; @@ -1966,38 +2119,91 @@ void errorCallback(const std::string &error_string) //Set the ErrorActivated global so we know to create a marker file gLLErrorActivated = true; + gDebugInfo["FatalMessage"] = error_string; + // We're not already crashing -- we simply *intend* to crash. Since we + // haven't actually trashed anything yet, we can afford to write the whole + // static info file. + LLAppViewer::instance()->writeDebugInfo(); + LLError::crashAndLoop(error_string); } } -bool init_logging(); -bool LLAppViewer::initLogging() +void LLAppViewer::initLoggingAndGetLastDuration() { // // Set up logging defaults for the viewer // LLError::initForApplication( - gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "") + ); LLError::setFatalFunction(errorCallback); + //LLError::setTimeFunction(getRuntime); - return init_logging(); + initLoggingInternal(); } -bool init_logging() +void LLAppViewer::initLoggingInternal() { // Remove the last ".old" log file. - std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, OLD_LOG_FILE); + std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, + OLD_LOG_FILE); LLFile::remove(old_log_file); + // Get name of the log file + std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, + LOG_FILE); + /* + * Before touching any log files, compute the duration of the last run + * by comparing the ctime of the previous start marker file with the ctime + * of the last log file. + */ + std::string start_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, START_MARKER_FILE_NAME); + llstat start_marker_stat; + llstat log_file_stat; + std::ostringstream duration_log_stream; // can't log yet, so save any message for when we can below + int start_stat_result = LLFile::stat(start_marker_file_name, &start_marker_stat); + int log_stat_result = LLFile::stat(log_file, &log_file_stat); + if ( 0 == start_stat_result && 0 == log_stat_result ) + { + int elapsed_seconds = log_file_stat.st_ctime - start_marker_stat.st_ctime; + // only report a last run time if the last viewer was the same version + // because this stat will be counted against this version + if ( markerIsSameVersion(start_marker_file_name) ) + { + gLastExecDuration = elapsed_seconds; + } + else + { + duration_log_stream << "start marker from some other version; duration is not reported"; + gLastExecDuration = -1; + } + } + else + { + // at least one of the LLFile::stat calls failed, so we can't compute the run time + duration_log_stream << "duration stat failure; start: "<< start_stat_result << " log: " << log_stat_result; + gLastExecDuration = -1; // unknown + } + std::string duration_log_msg(duration_log_stream.str()); + + // Create a new start marker file for comparison with log file time for the next run + LLAPRFile start_marker_file ; + start_marker_file.open(start_marker_file_name, LL_APR_WB); + if (start_marker_file.getFileHandle()) + { + recordMarkerVersion(start_marker_file); + start_marker_file.close(); + } + // Rename current log file to ".old" - std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOG_FILE); LLFile::rename(log_file, old_log_file); - // Set the log file to Singularity.log - + // Set the log file to SecondLife.log LLError::logToFile(log_file); - - // *FIX:Mani no error handling here! - return true; + if (!duration_log_msg.empty()) + { + LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL; + } } bool LLAppViewer::loadSettingsFromDirectory(AIReadAccess const& settings_r, @@ -2117,7 +2323,6 @@ bool LLAppViewer::initConfiguration() //Set up internal pointers settings[sGlobalSettingsName] = &gSavedSettings; settings[sPerAccountSettingsName] = &gSavedPerAccountSettings; - settings[sCrashSettingsName] = &gCrashSettings; //Load settings files list std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml"); @@ -2125,7 +2330,9 @@ bool LLAppViewer::initConfiguration() LL_INFOS() << "Loading settings file list" << settings_file_list << LL_ENDL; if (0 == settings_control.loadFromFile(settings_file_list)) { - LL_ERRS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL; + OSMessageBox("Cannot load default configuration file " + settings_file_list + " The installation may be corrupted.", + LLStringUtil::null,OSMB_OK); + return false; } mSettingsLocationList = settings_control.getLLSD("Locations"); @@ -2144,9 +2351,9 @@ bool LLAppViewer::initConfiguration() bool set_defaults = true; if(!loadSettingsFromDirectory(settings_w, "Default", set_defaults)) { - std::ostringstream msg; - msg << "Unable to load default settings file. The installation may be corrupted."; - OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); + OSMessageBox( + "Unable to load default settings file. The installation may be corrupted.", + LLStringUtil::null,OSMB_OK); return false; } @@ -2158,10 +2365,11 @@ bool LLAppViewer::initConfiguration() gSavedSettings.connectCOAVars(gSavedPerAccountSettings); // - set procedural settings + // Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet gSavedSettings.setString("ClientSettingsFile", gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global"))); - gSavedSettings.setString("VersionChannelName", gVersionChannel); + gSavedSettings.setString("VersionChannelName", LLVersionInfo::getChannel()); #if 0 //#ifndef LL_RELEASE_FOR_DOWNLOAD // provide developer build only overrides for these control variables that are not @@ -2190,8 +2398,6 @@ bool LLAppViewer::initConfiguration() gSavedSettings.setBOOL("WatchdogEnabled", FALSE); #endif - gCrashSettings.getControl(CRASH_BEHAVIOR_SETTING)->getSignal()->connect(boost::bind(&handleCrashSubmitBehaviorChanged, _2)); - // These are warnings that appear on the first experience of that condition. // They are already set in the settings_default.xml file, but still need to be added to LLFirstUse // for disable/reset ability @@ -2250,7 +2456,7 @@ bool LLAppViewer::initConfiguration() const std::string log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOG_FILE); LL_INFOS() << "Attempting to use portable settings and cache!" << LL_ENDL; gDirUtilp->makePortable(); - init_logging(); // Switch to portable log file + initLoggingInternal(); // Switch to portable log file LL_INFOS() << "Portable viewer configuration initialized!" << LL_ENDL; LLFile::remove(log); LL_INFOS() << "Cleaned up local log file to keep this computer untouched." << LL_ENDL; @@ -2265,9 +2471,36 @@ bool LLAppViewer::initConfiguration() gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, clp.getOption("settings")[0]); gSavedSettings.setString("ClientSettingsFile", user_settings_filename); - LL_INFOS() << "Using command line specified settings filename: " + LL_INFOS("Settings") << "Using command line specified settings filename: " << user_settings_filename << LL_ENDL; } + else + { + std::string channel(LLVersionInfo::getChannel()); + LLStringUtil::toLower(channel); + switch (LLVersionInfo::getViewerMaturity()) + { + default: + case LLVersionInfo::TEST_VIEWER: + case LLVersionInfo::PROJECT_VIEWER: + case LLVersionInfo::ALPHA_VIEWER: + case LLVersionInfo::BETA_VIEWER: + { + channel.erase(std::remove_if(channel.begin(), channel.end(), isspace), channel.end()); + break; + } + case LLVersionInfo::RELEASE_VIEWER: + size_t pos = channel.find(' '); + if (pos != channel.npos) + channel.erase(pos, channel.npos); + break; + } + std::string settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, + llformat("settings_%s.xml", channel.c_str())); + gSavedSettings.setString("ClientSettingsFile", settings_filename); + LL_INFOS() << "Using default settings filename from channel: " + << settings_filename << LL_ENDL; + } // - load overrides from user_settings loadSettingsFromDirectory(settings_w, "User"); @@ -2281,7 +2514,7 @@ bool LLAppViewer::initConfiguration() if(clp.hasOption("disablecrashlogger")) { LL_WARNS() << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" <disableCrashlogger(); + disableCrashlogger(); } // Handle initialization from settings. @@ -2298,7 +2531,7 @@ bool LLAppViewer::initConfiguration() LL_INFOS() << msg.str() << LL_ENDL; OSMessageBox( - msg.str().c_str(), + msg.str(), LLStringUtil::null, OSMB_OK); @@ -2391,25 +2624,13 @@ bool LLAppViewer::initConfiguration() const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent"); if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString()) { - gDirUtilp->setSkinFolder(skinfolder->getValue().asString()); + // Examining "Language" may not suffice -- see LLUI::getLanguage() + // logic. Unfortunately LLUI::getLanguage() doesn't yet do us much + // good because we haven't yet called LLUI::initClass(). + gDirUtilp->setSkinFolder(skinfolder->getValue().asString(), + gSavedSettings.getString("Language")); } - // XUI:translate - gSecondLife = "Singularity Viewer"; - - // Read skin/branding settings if specified. - //if (! gDirUtilp->getSkinDir().empty() ) - //{ - // std::string skin_def_file = gDirUtilp->findSkinnedFilename("skin.xml"); - // LLXmlTree skin_def_tree; - - // if (!skin_def_tree.parseFile(skin_def_file)) - // { - // LL_ERRS() << "Failed to parse skin definition." << LL_ENDL; - // } - - //} - #if LL_DARWIN // Initialize apple menubar and various callbacks init_apple_menu(LLTrans::getString("APP_NAME").c_str()); @@ -2435,12 +2656,11 @@ bool LLAppViewer::initConfiguration() // // Set the name of the window // - gWindowTitle = LLTrans::getString("APP_NAME"); + gWindowTitle = LLTrans::getString("APP_NAME") + llformat(" (%d) ", LLVersionInfo::getBuild()) #if LL_DEBUG - gWindowTitle += std::string(" [DEBUG] ") + gArgs; -#else - gWindowTitle += std::string(" ") + gArgs; + + "[DEBUG] " #endif + + gArgs; LLStringUtil::truncate(gWindowTitle, 255); //RN: if we received a URL, hand it off to the existing instance. @@ -2458,46 +2678,29 @@ bool LLAppViewer::initConfiguration() } } - if (!gSavedSettings.getBOOL("AllowMultipleViewers")) + + // + // Check for another instance of the app running + // + if (mSecondInstance && !gSavedSettings.getBOOL("AllowMultipleViewers")) { - // - // Check for another instance of the app running - // - - mSecondInstance = anotherInstanceRunning(); - - if (mSecondInstance) - { - std::ostringstream msg; - msg << LLTrans::getString("MBAlreadyRunning"); - OSMessageBox( - msg.str(), - LLStringUtil::null, - OSMB_OK); - return false; - } - - initMarkerFile(); - + OSMessageBox( + LLTrans::getString("MBAlreadyRunning"), + LLStringUtil::null, + OSMB_OK); + return false; } - else + + if (mSecondInstance) { - mSecondInstance = anotherInstanceRunning(); - - if (mSecondInstance) + // This is the second instance of SL. Turn off voice support, + // but make sure the setting is *not* persisted. + LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice"); + if(disable_voice && !gSavedSettings.getBOOL("VoiceMultiInstance")) { - // This is the second instance of SL. Turn off voice support, - // but make sure the setting is *not* persisted. - LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice"); - if(disable_voice && !gSavedSettings.getBOOL("VoiceMultiInstance")) - { - const BOOL DO_NOT_PERSIST = FALSE; - disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST); - } + const BOOL DO_NOT_PERSIST = FALSE; + disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST); } - - initMarkerFile(); - } // need to do this here - need to have initialized global settings first @@ -2555,6 +2758,8 @@ bool LLAppViewer::initWindow() gPipeline.init(); LL_INFOS("AppInit") << "gPipeline Initialized" << LL_ENDL; stop_glerror(); + + gGL.restoreVertexBuffers(); gViewerWindow->initGLDefaults(); gSavedSettings.setBOOL("RenderInitError", FALSE); @@ -2579,25 +2784,35 @@ bool LLAppViewer::initWindow() //gViewerWindow->getWindow()->show(); LL_INFOS("AppInit") << "Window initialization done." << LL_ENDL; + return true; } void LLAppViewer::writeDebugInfo(bool isStatic) { +#if !defined(USE_CRASHPAD) //Try to do the minimum when writing data during a crash. std::string* debug_filename; debug_filename = ( isStatic ? getStaticDebugFile() : getDynamicDebugFile() ); - LL_INFOS() << "Opening debug file " << *debug_filename << LL_ENDL; - llofstream out_file(*debug_filename); + LL_INFOS() << "Writing debug file " << *debug_filename << LL_ENDL; + llofstream out_file(debug_filename->c_str()); isStatic ? LLSDSerialize::toPrettyXML(gDebugInfo, out_file) : LLSDSerialize::toPrettyXML(gDebugInfo["Dynamic"], out_file); - - - out_file.close(); +#else + SET_CRASHPAD_ANNOTATION_VALUE(fatal_message, gDebugInfo["FatalMessage"].asString()); + SET_CRASHPAD_ANNOTATION_VALUE(grid_name, gDebugInfo["GridName"].asString()); + SET_CRASHPAD_ANNOTATION_VALUE(region_name, gDebugInfo["CurrentRegion"].asString()); + SET_CRASHPAD_ANNOTATION_VALUE(cpu_string, gDebugInfo["CPUInfo"]["CPUString"].asString()); + SET_CRASHPAD_ANNOTATION_VALUE(gpu_string, gDebugInfo["GraphicsCard"].asString()); + SET_CRASHPAD_ANNOTATION_VALUE(gl_version, gDebugInfo["GLInfo"]["GLVersion"].asString()); + SET_CRASHPAD_ANNOTATION_VALUE(session_duration, fmt::to_string(LLFrameTimer::getElapsedSeconds())); + SET_CRASHPAD_ANNOTATION_VALUE(memory_alloc, fmt::to_string((LLMemory::getCurrentRSS() >> 10) / 1000.f)); + SET_CRASHPAD_ANNOTATION_VALUE(memory_sys, fmt::to_string(gDebugInfo["RAMInfo"]["Physical"].asInteger() * 0.001f)); +#endif } void LLAppViewer::cleanupSavedSettings() @@ -2638,6 +2853,8 @@ void LLAppViewer::cleanupSavedSettings() { gSavedSettings.setF32("RenderFarClip", gAgentCamera.mDrawDistance); } + + LLSpeakerVolumeStorage::deleteSingleton(); } void LLAppViewer::removeCacheFiles(const std::string& file_mask) @@ -2647,22 +2864,24 @@ void LLAppViewer::removeCacheFiles(const std::string& file_mask) void LLAppViewer::writeSystemInfo() { - + if (! gDebugInfo.has("Dynamic") ) gDebugInfo["Dynamic"] = LLSD::emptyMap(); gDebugInfo["SLLog"] = LLError::logFileName(); - gDebugInfo["ClientInfo"]["Name"] = gVersionChannel; - gDebugInfo["ClientInfo"]["MajorVersion"] = gVersionMajor; - gDebugInfo["ClientInfo"]["MinorVersion"] = gVersionMinor; - gDebugInfo["ClientInfo"]["PatchVersion"] = gVersionPatch; - gDebugInfo["ClientInfo"]["BuildVersion"] = gVersionBuild; + gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel(); + gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor(); + gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor(); + gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch(); + gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild(); + gDebugInfo["ClientInfo"]["AddressSize"] = #if defined(_WIN64) || defined(__x86_64__) - gDebugInfo["ClientInfo"]["Architecture"] = "x86_64"; + "64"; #else - gDebugInfo["ClientInfo"]["Architecture"] = "i386"; + "32"; #endif + gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString(); @@ -2672,8 +2891,8 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE(); gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2(); - gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB()); - gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated>>10); // MB -> KB + gDebugInfo["RAMInfo"]["Physical"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().value()); + gDebugInfo["RAMInfo"]["Allocated"] = LLSD::Integer(gMemoryAllocated.valueInUnits()); gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple(); // The user is not logged on yet, but record the current grid choice login url @@ -2703,9 +2922,8 @@ void LLAppViewer::writeSystemInfo() } // Dump some debugging info - LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME") - << " version " << gVersionMajor << "." << gVersionMinor << "." << gVersionPatch - << LL_ENDL; + LL_INFOS("SystemInfo") << "Application: " << LLTrans::getString("APP_NAME") << LL_ENDL; + LL_INFOS("SystemInfo") << "Version: " << LLVersionInfo::getChannelAndVersion() << LL_ENDL; // Dump the local time and time zone time_t now; @@ -2727,9 +2945,9 @@ void LLAppViewer::writeSystemInfo() void LLAppViewer::handleViewerCrash() { - LL_INFOS() << "Handle viewer crash entry." << LL_ENDL; + LL_INFOS("CRASHREPORT") << "Handle viewer crash entry." << LL_ENDL; - LL_INFOS() << "Last render pool type: " << LLPipeline::sCurRenderPoolType << LL_ENDL ; + LL_INFOS("CRASHREPORT") << "Last render pool type: " << LLPipeline::sCurRenderPoolType << LL_ENDL ; LLMemory::logMemoryInfo(true) ; @@ -2763,15 +2981,6 @@ void LLAppViewer::handleViewerCrash() gDebugInfo["Dynamic"]["CrashHostUrl"] = crashHostUrl; } - //We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version - //to check against no matter what - gDebugInfo["ClientInfo"]["Name"] = gVersionChannel; - - gDebugInfo["ClientInfo"]["MajorVersion"] = gVersionMajor; - gDebugInfo["ClientInfo"]["MinorVersion"] = gVersionMinor; - gDebugInfo["ClientInfo"]["PatchVersion"] = gVersionPatch; - gDebugInfo["ClientInfo"]["BuildVersion"] = gVersionBuild; - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if ( parcel && parcel->getMusicURL()[0]) { @@ -2781,15 +2990,14 @@ void LLAppViewer::handleViewerCrash() { gDebugInfo["Dynamic"]["ParcelMediaURL"] = parcel->getMediaURL(); } - - + gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile"); gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName(); gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath(); gDebugInfo["Dynamic"]["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds()); - gDebugInfo["StartupState"] = LLStartUp::getStartupStateString(); gDebugInfo["Dynamic"]["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10; + gDebugInfo["StartupState"] = LLStartUp::getStartupStateString(); gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); @@ -2799,7 +3007,7 @@ void LLAppViewer::handleViewerCrash() } else { - gDebugInfo["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH; + gDebugInfo["Dynamic"]["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH; } if(gAgent.getRegion()) @@ -2827,26 +3035,27 @@ void LLAppViewer::handleViewerCrash() //we're already in a crash situation if (gDirUtilp) { - std::string crash_file_name; - if(gLLErrorActivated) crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LLERROR_MARKER_FILE_NAME); - else crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,ERROR_MARKER_FILE_NAME); - LL_INFOS() << "Creating crash marker file " << crash_file_name << LL_ENDL; - - LLAPRFile crash_file(crash_file_name, LL_APR_W); - if (crash_file.getFileHandle()) + std::string crash_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, + gLLErrorActivated + ? LLERROR_MARKER_FILE_NAME + : ERROR_MARKER_FILE_NAME); + LLAPRFile crash_marker_file ; + crash_marker_file.open(crash_marker_file_name, LL_APR_WB); + if (crash_marker_file.getFileHandle()) { - LL_INFOS("MarkerFile") << "Created crash marker file " << crash_file_name << LL_ENDL; + LL_INFOS("MarkerFile") << "Created crash marker file " << crash_marker_file_name << LL_ENDL; + recordMarkerVersion(crash_marker_file); } else { - LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_file_name << LL_ENDL; + LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_marker_file_name << LL_ENDL; } } - char *minidump_file = pApp->getMiniDumpFilename(); - if(minidump_file && minidump_file[0] != 0) + else { - gDebugInfo["Dynamic"]["MinidumpPath"] = minidump_file; + LL_WARNS("MarkerFile") << "No gDirUtilp with which to create error marker file name" << LL_ENDL; } + LL_WARNS("CRASHREPORT") << "no minidump file? ah yeah, boi!" << LL_ENDL; gDebugInfo["Dynamic"]["CrashType"]="crash"; @@ -2854,13 +3063,17 @@ void LLAppViewer::handleViewerCrash() { std::string filename; filename = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "stats.log"); - llofstream file(filename, llofstream::binary); + LL_DEBUGS("CRASHREPORT") << "recording stats " << filename << LL_ENDL; + llofstream file(filename.c_str(), std::ios_base::binary); if(file.good()) { - LL_INFOS() << "Handle viewer crash generating stats log." << LL_ENDL; gMessageSystem->summarizeLogs(file); file.close(); } + else + { + LL_WARNS("CRASHREPORT") << "problem recording stats" << LL_ENDL; + } } if (gMessageSystem) @@ -2873,158 +3086,241 @@ void LLAppViewer::handleViewerCrash() // Close the debug file pApp->writeDebugInfo(false); //false answers the isStatic question with the least overhead. +} - LLError::logToFile(""); - - // Remove the marker file, since otherwise we'll spawn a process that'll keep it locked - if(gDebugInfo["Dynamic"]["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH) - { - pApp->removeMarkerFile(true); - } - else +// static +void LLAppViewer::recordMarkerVersion(LLAPRFile& marker_file) +{ + std::string marker_version(LLVersionInfo::getChannelAndVersion()); + if ( marker_version.length() > MAX_MARKER_LENGTH ) { - pApp->removeMarkerFile(false); + LL_WARNS_ONCE("MarkerFile") << "Version length ("<< marker_version.length()<< ")" + << " greater than maximum (" << MAX_MARKER_LENGTH << ")" + << ": marker matching may be incorrect" + << LL_ENDL; } - - return; + + // record the viewer version in the marker file + marker_file.write(marker_version.data(), marker_version.length()); } -bool LLAppViewer::anotherInstanceRunning() +bool LLAppViewer::markerIsSameVersion(const std::string& marker_name) const { - // We create a marker file when the program starts and remove the file when it finishes. - // If the file is currently locked, that means another process is already running. + bool sameVersion = false; - std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, MARKER_FILE_NAME); - LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL; + std::string my_version(LLVersionInfo::getChannelAndVersion()); + char marker_version[MAX_MARKER_LENGTH]; - //Freeze case checks - if (LLAPRFile::isExist(marker_file, LL_APR_RB)) + LLAPRFile marker_file; + marker_file.open(marker_name, LL_APR_RB); + if (marker_file.getFileHandle()) { - // File exists, try opening with write permissions - LLAPRFile outfile(marker_file, LL_APR_WB); - apr_file_t* fMarker = outfile.getFileHandle() ; - if (!fMarker) - { - // Another instance is running. Skip the rest of these operations. - LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL; - return true; - } - if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) //flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1) + S32 marker_version_length = marker_file.read(marker_version, sizeof(marker_version)); + std::string marker_string(marker_version, marker_version_length); + if ( 0 == my_version.compare( 0, my_version.length(), marker_version, 0, marker_version_length ) ) { - LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL; - return true; + sameVersion = true; } - // No other instances; we'll lock this file now & delete on quit. - } - LL_DEBUGS("MarkerFile") << "Marker file isn't locked." << LL_ENDL; - return false; + LL_DEBUGS("MarkerFile") << "Compare markers for '" << marker_name << "': " + << "\n mine '" << my_version << "'" + << "\n marker '" << marker_string << "'" + << "\n " << ( sameVersion ? "same" : "different" ) << " version" + << LL_ENDL; + marker_file.close(); + } + return sameVersion; } -void LLAppViewer::initMarkerFile() +void LLAppViewer::processMarkerFiles() { - //First, check for the existence of other files. - //There are marker files for two different types of crashes - - mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME); - LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL; - //We've got 4 things to test for here - // - Other Process Running (Singularity.exec_marker present, locked) - // - Freeze (Singularity.exec_marker present, not locked) - // - LLError Crash (Singularity.llerror_marker present) - // - Other Crash (Singularity.error_marker present) + // - Other Process Running (SecondLife.exec_marker present, locked) + // - Freeze (SecondLife.exec_marker present, not locked) + // - LLError Crash (SecondLife.llerror_marker present) + // - Other Crash (SecondLife.error_marker present) // These checks should also remove these files for the last 2 cases if they currently exist - //LLError/Error checks. Only one of these should ever happen at a time. - std::string logout_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME); - std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME); - std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); + 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, LL_APR_RB)) + { + // File exists... + // first, read it to see if it was created by the same version (we need this later) + marker_is_same_version = markerIsSameVersion(mMarkerFileName); + + // now test to see if this file is locked by a running process (try to open for write) + LL_DEBUGS("MarkerFile") << "Checking exec marker file for lock..." << LL_ENDL; + mMarkerFile.open(mMarkerFileName, LL_APR_WB); + apr_file_t* fMarker = mMarkerFile.getFileHandle() ; + if (!fMarker) + { + LL_INFOS("MarkerFile") << "Exec marker file open failed - assume it is locked." << LL_ENDL; + mSecondInstance = true; // lock means that instance is running. + } + else + { + // We were able to open it, now try to lock it ourselves... + if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) + { + LL_WARNS_ONCE("MarkerFile") << "Locking exec marker failed." << LL_ENDL; + mSecondInstance = true; // lost a race? be conservative + } + else + { + // No other instances; we've locked this file now, so record our version; delete on quit. + recordMarkerVersion(mMarkerFile); + LL_DEBUGS("MarkerFile") << "Exec marker file existed but was not locked; rewritten." << LL_ENDL; + } + } + + if (mSecondInstance) + { + LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' owned by another instance" << LL_ENDL; + } + else if (marker_is_same_version) + { + // the file existed, is ours, and matched our version, so we can report on what it says + LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec FROZE" << LL_ENDL; + gLastExecEvent = LAST_EXEC_FROZE; - if (LLAPRFile::isExist(mMarkerFileName, LL_APR_RB) && !anotherInstanceRunning()) + } + else + { + LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found, but versions did not match" << LL_ENDL; + } + } + else // marker did not exist... last exec (if any) did not freeze { - gLastExecEvent = LAST_EXEC_FROZE; - LL_INFOS("MarkerFile") << "Exec marker found: program froze on previous execution" << LL_ENDL; - } + // Create the marker file for this execution & lock it; it will be deleted on a clean exit + apr_status_t s; + s = mMarkerFile.open(mMarkerFileName, LL_APR_WB, TRUE); + + if (s == APR_SUCCESS && mMarkerFile.getFileHandle()) + { + LL_DEBUGS("MarkerFile") << "Exec marker file '"<< mMarkerFileName << "' created." << LL_ENDL; + if (APR_SUCCESS == apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE)) + { + recordMarkerVersion(mMarkerFile); + LL_DEBUGS("MarkerFile") << "Exec marker file locked." << LL_ENDL; + } + else + { + LL_WARNS("MarkerFile") << "Exec marker file cannot be locked." << LL_ENDL; + } + } + else + { + LL_WARNS("MarkerFile") << "Failed to create exec marker file '"<< mMarkerFileName << "'." << LL_ENDL; + } + } + + // now check for cases in which the exec marker may have been cleaned up by crash handlers + + // 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, LL_APR_RB)) { - gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; - LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; + if (markerIsSameVersion(logout_marker_file)) + { + gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; + LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "', changing LastExecEvent to LOGOUT_FROZE" << LL_ENDL; + } + else + { + LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "' found, but versions did not match" << LL_ENDL; + } LLAPRFile::remove(logout_marker_file); } + // further refine based on whether or not a marker created during an llerr crash is found + std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME); if(LLAPRFile::isExist(llerror_marker_file, LL_APR_RB)) { - LL_INFOS() << "Last exec LLError crashed, setting LastExecEvent to " << LAST_EXEC_LLERROR_CRASH << LL_ENDL; - if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; - else gLastExecEvent = LAST_EXEC_LLERROR_CRASH; - LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; + if (markerIsSameVersion(llerror_marker_file)) + { + if ( gLastExecEvent == LAST_EXEC_LOGOUT_FROZE ) + { + gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; + LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL; + } + else + { + gLastExecEvent = LAST_EXEC_LLERROR_CRASH; + LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LLERROR_CRASH" << LL_ENDL; + } + } + else + { + LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' found, but versions did not match" << LL_ENDL; + } LLAPRFile::remove(llerror_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, LL_APR_RB)) { - LL_INFOS("MarkerFile") << "Last exec crashed, setting LastExecEvent to " << LAST_EXEC_OTHER_CRASH << LL_ENDL; - if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; - else gLastExecEvent = LAST_EXEC_OTHER_CRASH; - LL_INFOS("MarkerFile") << "Last exec crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; + if (markerIsSameVersion(error_marker_file)) + { + if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) + { + gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; + LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL; + } + else + { + gLastExecEvent = LAST_EXEC_OTHER_CRASH; + LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; + } + } + else + { + LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL; + } LLAPRFile::remove(error_marker_file); } - - // No new markers if another instance is running. - if(anotherInstanceRunning()) - { - return; - } - - // Create the marker file for this execution & lock it - apr_status_t s; - s = mMarkerFile.open(mMarkerFileName, LL_APR_W, LLAPRFile::long_lived); - - if (s == APR_SUCCESS && mMarkerFile.getFileHandle()) - { - LL_DEBUGS("MarkerFile") << "Marker file created." << LL_ENDL; - } - else - { - LL_INFOS("MarkerFile") << "Failed to create marker file." << LL_ENDL; - return; - } - if (apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) - { - mMarkerFile.close() ; - LL_INFOS("MarkerFile") << "Marker file cannot be locked." << LL_ENDL; - return; - } - - LL_DEBUGS("MarkerFile") << "Marker file locked." << LL_ENDL; } -void LLAppViewer::removeMarkerFile(bool leave_logout_marker) +void LLAppViewer::removeMarkerFiles() { - LL_DEBUGS("MarkerFile") << "removeMarkerFile()" << LL_ENDL; - if (mMarkerFile.getFileHandle()) - { - mMarkerFile.close() ; - LLAPRFile::remove( mMarkerFileName ); - } - if (mLogoutMarkerFile != NULL) + if (!mSecondInstance) { - if(!leave_logout_marker) + if (mMarkerFile.getFileHandle()) + { + mMarkerFile.close() ; + LLAPRFile::remove( mMarkerFileName ); + LL_DEBUGS("MarkerFile") << "removed exec marker '"<getExpandedFilename(LL_PATH_DUMP, ""); gDirUtilp->deleteDirAndContents(dump_dir); +#endif } void LLAppViewer::forceQuit() @@ -3044,7 +3340,7 @@ void LLAppViewer::fastQuit(S32 error_code) // figure out the error code S32 final_error_code = error_code ? error_code : (S32)isError(); // this isn't a crash - removeMarkerFile(); + removeMarkerFiles(); // get outta here _exit(final_error_code); } @@ -3165,8 +3461,7 @@ void LLAppViewer::migrateCacheDirectory() { gSavedSettings.setBOOL("MigrateCacheDirectory", FALSE); - std::string delimiter = gDirUtilp->getDirDelimiter(); - std::string old_cache_dir = gDirUtilp->getOSUserAppDir() + delimiter + "cache"; + std::string old_cache_dir = gDirUtilp->add(gDirUtilp->getOSUserAppDir(), "cache"); std::string new_cache_dir = gDirUtilp->getCacheDir(true); if (gDirUtilp->fileExists(old_cache_dir)) @@ -3182,8 +3477,8 @@ void LLAppViewer::migrateCacheDirectory() while (iter.next(file_name)) { if (file_name == "." || file_name == "..") continue; - std::string source_path = old_cache_dir + delimiter + file_name; - std::string dest_path = new_cache_dir + delimiter + file_name; + std::string source_path = gDirUtilp->add(old_cache_dir, file_name); + std::string dest_path = gDirUtilp->add(new_cache_dir, file_name); if (!LLFile::rename(source_path, dest_path)) { file_count++; @@ -3233,6 +3528,7 @@ void dumpVFSCaches() gStaticVFS->dumpFiles(); SetCurrentDirectory(w_str); #endif + LL_INFOS() << "========= Dynamic VFS ====" << LL_ENDL; gVFS->listFiles(); #if LL_WINDOWS @@ -3293,6 +3589,7 @@ bool LLAppViewer::initCache() if (gSavedSettings.getBOOL("PurgeCacheOnStartup") || gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) { + LL_INFOS("AppCache") << "Startup cache purge requested: " << (gSavedSettings.getBOOL("PurgeCacheOnStartup") ? "ALWAYS" : "ONCE") << LL_ENDL; gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); mPurgeCache = true; // STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad @@ -3308,6 +3605,7 @@ bool LLAppViewer::initCache() std::string new_cache_location = gSavedSettings.getString("NewCacheLocation"); if (new_cache_location != cache_location) { + LL_INFOS("AppCache") << "Cache location changed, cache needs purging" << LL_ENDL; gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")); purgeCache(); // purge old cache gSavedSettings.setString("CacheLocation", new_cache_location); @@ -3331,20 +3629,26 @@ bool LLAppViewer::initCache() // } - LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache")); - + { + std::random_device rnddev; + std::mt19937 rng(rnddev()); + std::uniform_int_distribution<> dist(0, 4); + + LLSplashScreen::update(LLTrans::getString( + llformat("StartupInitializingTextureCache%d", dist(rng)))); + } + // Init the texture cache // Allocate 80% of the cache size for textures - const S32 MB = 1024 * 1024; - const S64 MIN_CACHE_SIZE = 64 * MB; - const S64 MAX_CACHE_SIZE = 9984ll * MB; - const S64 MAX_VFS_SIZE = 1024 * MB; // 1 GB + const U64Bytes MIN_CACHE_SIZE = U32Megabytes(64); + const U64Bytes MAX_CACHE_SIZE = U32Megabytes(9984); + const U64Bytes MAX_VFS_SIZE = U32Gigabytes(1); - S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB; + U64Bytes cache_size = U32Megabytes(gSavedSettings.getU32("CacheSize")); cache_size = llclamp(cache_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE); - S64 texture_cache_size = ((cache_size * 8) / 10); - S64 vfs_size = cache_size - texture_cache_size; + U64Bytes texture_cache_size = ((cache_size * 8) / 10); + U64Bytes vfs_size = U64Bytes(cache_size) - U64Bytes(texture_cache_size); if (vfs_size > MAX_VFS_SIZE) { @@ -3354,7 +3658,7 @@ bool LLAppViewer::initCache() texture_cache_size = cache_size - MAX_VFS_SIZE; } - S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch); + U64Bytes extra(LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch)); texture_cache_size -= extra; LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()) ; @@ -3363,19 +3667,18 @@ bool LLAppViewer::initCache() // Init the VFS vfs_size = llmin(vfs_size + extra, MAX_VFS_SIZE); - vfs_size = (vfs_size / MB) * MB; // make sure it is MB aligned - U32 vfs_size_u32 = (U32)vfs_size; - U32 old_vfs_size = gSavedSettings.getU32("VFSOldSize") * MB; - bool resize_vfs = (vfs_size_u32 != old_vfs_size); + vfs_size = U32Megabytes(vfs_size + U32Bytes(1048575)); // make sure it is MB aligned + U32Megabytes old_vfs_size(gSavedSettings.getU32("VFSOldSize")); + bool resize_vfs = (vfs_size != old_vfs_size); if (resize_vfs) { - gSavedSettings.setU32("VFSOldSize", vfs_size_u32 / MB); + gSavedSettings.setU32("VFSOldSize", U32Megabytes(vfs_size)); } - LL_INFOS("AppCache") << "VFS CACHE SIZE: " << vfs_size / (1024*1024) << " MB" << LL_ENDL; + LL_INFOS("AppCache") << "VFS CACHE SIZE: " << U32Megabytes(vfs_size) << LL_ENDL; // This has to happen BEFORE starting the vfs // time_t ltime; - srand(time(NULL)); // Flawfinder: ignore + srand(time(nullptr)); // Flawfinder: ignore U32 old_salt = gSavedSettings.getU32("VFSSalt"); U32 new_salt; std::string old_vfs_data_file; @@ -3417,10 +3720,10 @@ bool LLAppViewer::initCache() LLDirIterator iter(dir, mask); if (iter.next(found_file)) { - old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file; + old_vfs_data_file = gDirUtilp->add(dir, found_file); - S32 start_pos = found_file.find_last_of('.'); - if (start_pos > 0) + size_t start_pos = found_file.find_last_of('.'); + if (start_pos != std::string::npos && start_pos != 0) { sscanf(found_file.substr(start_pos+1).c_str(), "%d", &old_salt); } @@ -3481,7 +3784,7 @@ bool LLAppViewer::initCache() gSavedSettings.setU32("VFSSalt", new_salt); // Don't remove VFS after viewer crashes. If user has corrupt data, they can reinstall. JC - gVFS = LLVFS::createLLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false); + gVFS = LLVFS::createLLVFS(new_vfs_index_file, new_vfs_data_file, false, U32Bytes(vfs_size), false); if (!gVFS) { return false; @@ -3527,9 +3830,9 @@ void LLAppViewer::purgeCache() gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask); } -const std::string& LLAppViewer::getSecondLifeTitle() const +std::string LLAppViewer::getSecondLifeTitle() const { - return gSecondLife; + return LLTrans::getString("APP_NAME"); } const std::string& LLAppViewer::getWindowTitle() const @@ -3566,9 +3869,9 @@ void LLAppViewer::forceDisconnect(const std::string& mesg) return; } - // Translate the message if possible + // *TODO: Translate the message if possible std::string big_reason = LLAgent::sTeleportErrorMessages[mesg]; - if ( big_reason.size() == 0 ) + if (big_reason.empty()) { big_reason = mesg; } @@ -3599,26 +3902,25 @@ void LLAppViewer::badNetworkHandler() mPurgeOnExit = TRUE; - std::string grid_support_msg = ""; - if (!gHippoGridManager->getCurrentGrid()->getSupportUrl().empty()) - { - grid_support_msg = "\n\nOr visit the grid support page at: \n " - + gHippoGridManager->getCurrentGrid()->getSupportUrl(); - } std::ostringstream message; message << "The viewer has detected mangled network data indicative\n" "of a bad upstream network connection or an incomplete\n" - "local installation of " << gSecondLife << ". \n" + "local installation of " << LLAppViewer::instance()->getSecondLifeTitle() << ". \n" " \n" "Try uninstalling and reinstalling to see if this resolves \n" "the issue. \n" " \n" "If the problem continues, please report the issue at: \n" - "http://www.singularityviewer.org" << grid_support_msg; + "http://www.singularityviewer.org"; + + if (!gHippoGridManager->getCurrentGrid()->getSupportUrl().empty()) + { + message << "\n\nOr visit the grid support page at: \n" + << gHippoGridManager->getCurrentGrid()->getSupportUrl(); + } + forceDisconnect(message.str()); - - LLApp::instance()->writeMiniDump(); } // This routine may get called more than once during the shutdown process. @@ -3649,11 +3951,11 @@ void LLAppViewer::saveFinalSnapshot() void LLAppViewer::loadNameCache() { - // Phoenix: Wolfspirit: Loads the Display Name Cache. And set if we are using Display Names. + // display names cache std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml"); LL_INFOS("AvNameCache") << filename << LL_ENDL; - llifstream name_cache_stream(filename); + llifstream name_cache_stream(filename.c_str()); if(name_cache_stream.is_open()) { LLAvatarNameCache::importFile(name_cache_stream); @@ -3663,7 +3965,7 @@ void LLAppViewer::loadNameCache() std::string name_cache; name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache"); - llifstream cache_file(name_cache); + llifstream cache_file(name_cache.c_str()); if(cache_file.is_open()) { if(gCacheName->importFile(cache_file)) return; @@ -3672,26 +3974,29 @@ void LLAppViewer::loadNameCache() void LLAppViewer::saveNameCache() { - // Phoenix: Wolfspirit: Saves the Display Name Cache. + // display names cache std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml"); - llofstream name_cache_stream(filename); + llofstream name_cache_stream(filename.c_str()); if(name_cache_stream.is_open()) { LLAvatarNameCache::exportFile(name_cache_stream); } - if (!gCacheName) return; - - std::string name_cache; - name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache"); - llofstream cache_file(name_cache); - if(cache_file.is_open()) - { - gCacheName->exportFile(cache_file); + // real names cache + if (gCacheName) + { + std::string name_cache; + name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache"); + llofstream cache_file(name_cache.c_str()); + if(cache_file.is_open()) + { + gCacheName->exportFile(cache_file); + } } } + /*! @brief This class is an LLFrameTimer that can be created with an elapsed time that starts counting up from the given value rather than 0.0. @@ -3708,18 +4013,18 @@ class LLFrameStatsTimer : public LLFrameTimer } }; -static LLFastTimer::DeclareTimer FTM_AUDIO_UPDATE("Update Audio"); -static LLFastTimer::DeclareTimer FTM_CLEANUP("Cleanup"); -static LLFastTimer::DeclareTimer FTM_CLEANUP_DRAWABLES("Drawables"); -static LLFastTimer::DeclareTimer FTM_CLEANUP_OBJECTS("Objects"); -static LLFastTimer::DeclareTimer FTM_IDLE_CB("Idle Callbacks"); -static LLFastTimer::DeclareTimer FTM_LOD_UPDATE("Update LOD"); -static LLFastTimer::DeclareTimer FTM_OBJECTLIST_UPDATE("Update Objectlist"); -static LLFastTimer::DeclareTimer FTM_REGION_UPDATE("Update Region"); -static LLFastTimer::DeclareTimer FTM_WORLD_UPDATE("Update World"); -static LLFastTimer::DeclareTimer FTM_NETWORK("Network"); -static LLFastTimer::DeclareTimer FTM_AGENT_NETWORK("Agent Network"); -static LLFastTimer::DeclareTimer FTM_VLMANAGER("VL Manager"); +static LLTrace::BlockTimerStatHandle FTM_AUDIO_UPDATE("Update Audio"); +static LLTrace::BlockTimerStatHandle FTM_CLEANUP("Cleanup"); +static LLTrace::BlockTimerStatHandle FTM_CLEANUP_DRAWABLES("Drawables"); +static LLTrace::BlockTimerStatHandle FTM_CLEANUP_OBJECTS("Objects"); +static LLTrace::BlockTimerStatHandle FTM_IDLE_CB("Idle Callbacks"); +static LLTrace::BlockTimerStatHandle FTM_LOD_UPDATE("Update LOD"); +static LLTrace::BlockTimerStatHandle FTM_OBJECTLIST_UPDATE("Update Objectlist"); +static LLTrace::BlockTimerStatHandle FTM_REGION_UPDATE("Update Region"); +static LLTrace::BlockTimerStatHandle FTM_WORLD_UPDATE("Update World"); +static LLTrace::BlockTimerStatHandle FTM_NETWORK("Network"); +static LLTrace::BlockTimerStatHandle FTM_AGENT_NETWORK("Agent Network"); +static LLTrace::BlockTimerStatHandle FTM_VLMANAGER("VL Manager"); /////////////////////////////////////////////////////// // idle() @@ -3730,7 +4035,7 @@ static LLFastTimer::DeclareTimer FTM_VLMANAGER("VL Manager"); void LLAppViewer::idle() { //LAZY_FT is just temporary. -#define LAZY_FT(str) static LLFastTimer::DeclareTimer ftm(str); LLFastTimer t(ftm) +#define LAZY_FT(str) static LLTrace::BlockTimerStatHandle ftm(str); LL_RECORD_BLOCK_TIME(ftm) pingMainloopTimeout("Main:Idle"); // Update frame timers @@ -3745,8 +4050,8 @@ void LLAppViewer::idle() LLEventTimer::updateClass(); } { - LAZY_FT("LLCriticalDamp::updateInterpolants"); - LLCriticalDamp::updateInterpolants(); + LAZY_FT("LLSmoothInterpolation::updateInterpolants"); + LLSmoothInterpolation::updateInterpolants(); } { LAZY_FT("LLMortician::updateClass"); @@ -3771,11 +4076,12 @@ void LLAppViewer::idle() // Smoothly weight toward current frame gFPSClamped = (frame_rate_clamped + (4.f * gFPSClamped)) / 5.f; - F32 qas = gSavedSettings.getF32("QuitAfterSeconds"); + static LLCachedControl qas(gSavedSettings, "QuitAfterSeconds"); if (qas > 0.f) { if (gRenderStartTime.getElapsedTimeF32() > qas) { + LL_INFOS() << "Quitting after " << qas << " seconds. See setting \"QuitAfterSeconds\"." << LL_ENDL; LLAppViewer::instance()->forceQuit(); } } @@ -3787,7 +4093,7 @@ void LLAppViewer::idle() // { - LLFastTimer t(FTM_STATEMACHINE); + LL_RECORD_BLOCK_TIME(FTM_STATEMACHINE); gMainThreadEngine.mainloop(); } @@ -3795,7 +4101,7 @@ void LLAppViewer::idle() // here. { LAZY_FT("request_initial_instant_messages"); - request_initial_instant_messages(); + LLIMProcessing::requestOfflineMessages(); } /////////////////////////////////// @@ -3822,7 +4128,7 @@ void LLAppViewer::idle() if (!gDisconnected) { - LLFastTimer t(FTM_NETWORK); + LL_RECORD_BLOCK_TIME(FTM_NETWORK); // Update spaceserver timeinfo LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + (U32)(dt_raw * SEC_TO_MICROSEC)); @@ -3832,13 +4138,14 @@ void LLAppViewer::idle() // Update simulator agent state // - if (gSavedSettings.getBOOL("RotateRight")) + static LLCachedControl rotateRight(gSavedSettings, "RotateRight"); + if (rotateRight) { gAgent.moveYaw(-1.f); } { - LLFastTimer t(FTM_AGENT_AUTOPILOT); + LL_RECORD_BLOCK_TIME(FTM_AGENT_AUTOPILOT); // Handle automatic walking towards points gAgentPilot.updateTarget(); gAgent.autoPilot(&yaw); @@ -3849,11 +4156,12 @@ void LLAppViewer::idle() // When appropriate, update agent location to the simulator. F32 agent_update_time = agent_update_timer.getElapsedTimeF32(); - BOOL flags_changed = gAgent.controlFlagsDirty() || (last_control_flags != gAgent.getControlFlags()); + BOOL flags_changed = gAgent.controlFlagsDirty() + || (last_control_flags != gAgent.getControlFlags()); if (flags_changed || (agent_update_time > (1.0f / (F32)AGENT_UPDATES_PER_SECOND))) { - LLFastTimer t(FTM_AGENT_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_AGENT_UPDATE); // Send avatar and camera info last_control_flags = gAgent.getControlFlags(); send_agent_update(TRUE); @@ -3875,7 +4183,7 @@ void LLAppViewer::idle() reset_statistics(); // Update session stats every large chunk of time - // *FIX: (???) SAMANTHA + // *FIX: (?) SAMANTHA if (viewer_stats_timer.getElapsedTimeF32() >= SEND_STATS_PERIOD && !gDisconnected) { LL_INFOS() << "Transmitting sessions stats" << LL_ENDL; @@ -3914,7 +4222,7 @@ void LLAppViewer::idle() if (!gDisconnected) { - LLFastTimer t(FTM_NETWORK); + LL_RECORD_BLOCK_TIME(FTM_NETWORK); //////////////////////////////////////////////// // @@ -3924,6 +4232,7 @@ void LLAppViewer::idle() // floating throughout the various object lists. // idleNameCache(); + if (gAgent.getRegion()) LLExperienceCache::instance().idleCoro(); gFrameStats.start(LLFrameStats::IDLE_NETWORK); stop_glerror(); @@ -3945,13 +4254,14 @@ void LLAppViewer::idle() // hover callbacks // { - LLFastTimer t(FTM_IDLE_CB); + LL_RECORD_BLOCK_TIME(FTM_IDLE_CB); // Do event notifications if necessary. Yes, we may want to move this elsewhere. gEventNotifier.update(); gIdleCallbacks.callFunctions(); gInventory.idleNotifyObservers(); + if (auto antispam = NACLAntiSpamRegistry::getIfExists()) antispam->idle(); } // Metrics logging (LLViewerAssetStats, etc.) @@ -4000,15 +4310,15 @@ void LLAppViewer::idle() { // Handle pending gesture processing - static LLFastTimer::DeclareTimer ftm("Agent Position"); - LLFastTimer t(ftm); + static LLTrace::BlockTimerStatHandle ftm("Agent Position"); + LL_RECORD_BLOCK_TIME(ftm); LLGestureMgr::instance().update(); gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY); } { - LLFastTimer t(FTM_OBJECTLIST_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_OBJECTLIST_UPDATE); gFrameStats.start(LLFrameStats::OBJECT_UPDATE); if (!(logoutRequestSent() && hasSavedFinalSnapshot())) @@ -4025,13 +4335,13 @@ void LLAppViewer::idle() { gFrameStats.start(LLFrameStats::CLEAN_DEAD); - LLFastTimer t(FTM_CLEANUP); + LL_RECORD_BLOCK_TIME(FTM_CLEANUP); { - LLFastTimer t(FTM_CLEANUP_OBJECTS); + LL_RECORD_BLOCK_TIME(FTM_CLEANUP_OBJECTS); gObjectList.cleanDeadObjects(); } { - LLFastTimer t(FTM_CLEANUP_DRAWABLES); + LL_RECORD_BLOCK_TIME(FTM_CLEANUP_DRAWABLES); LLDrawable::cleanupDeadDrawables(); } } @@ -4051,8 +4361,8 @@ void LLAppViewer::idle() { gFrameStats.start(LLFrameStats::UPDATE_EFFECTS); - static LLFastTimer::DeclareTimer ftm("HUD Effects"); - LLFastTimer t(ftm); + static LLTrace::BlockTimerStatHandle ftm("HUD Effects"); + LL_RECORD_BLOCK_TIME(ftm); LLSelectMgr::getInstance()->updateEffects(); LLHUDManager::getInstance()->cleanupEffects(); LLHUDManager::getInstance()->sendEffects(); @@ -4066,7 +4376,7 @@ void LLAppViewer::idle() // { - LLFastTimer t(FTM_NETWORK); + LL_RECORD_BLOCK_TIME(FTM_NETWORK); gVLManager.unpackData(); } @@ -4081,7 +4391,7 @@ void LLAppViewer::idle() } { const F32 max_region_update_time = .001f; // 1ms - LLFastTimer t(FTM_REGION_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_REGION_UPDATE); LLWorld::getInstance()->updateRegions(max_region_update_time); } @@ -4132,7 +4442,7 @@ void LLAppViewer::idle() if (!gNoRender) { - LLFastTimer t(FTM_WORLD_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_WORLD_UPDATE); gFrameStats.start(LLFrameStats::UPDATE_MOVE); gPipeline.updateMove(); @@ -4176,10 +4486,13 @@ void LLAppViewer::idle() // objects and camera should be in sync, do LOD calculations now { - LLFastTimer t(FTM_LOD_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_LOD_UPDATE); gObjectList.updateApparentAngles(gAgent); } + // Update AV render info + LLAvatarRenderInfoAccountant::idle(); + // Execute deferred tasks. { LAZY_FT("DeferredTaskRun"); @@ -4291,13 +4604,11 @@ void LLAppViewer::sendLogoutRequest() //Set internal status variables and marker files gLogoutInProgress = TRUE; mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME); - - LLAPRFile outfile(mLogoutMarkerFileName, LL_APR_W); - mLogoutMarkerFile = outfile.getFileHandle() ; - if (mLogoutMarkerFile) + + if (mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_W) == APR_SUCCESS) { LL_INFOS() << "Created logout marker file " << mLogoutMarkerFileName << LL_ENDL; - apr_file_close(mLogoutMarkerFile); + mLogoutMarkerFile.close(); } else { @@ -4371,12 +4682,12 @@ void LLAppViewer::idleNameCache() static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; #endif -static LLFastTimer::DeclareTimer FTM_IDLE_NETWORK("Idle Network"); -static LLFastTimer::DeclareTimer FTM_MESSAGE_ACKS("Message Acks"); -static LLFastTimer::DeclareTimer FTM_RETRANSMIT("Retransmit"); -static LLFastTimer::DeclareTimer FTM_TIMEOUT_CHECK("Timeout Check"); -static LLFastTimer::DeclareTimer FTM_DYNAMIC_THROTTLE("Dynamic Throttle"); -static LLFastTimer::DeclareTimer FTM_CHECK_REGION_CIRCUIT("Check Region Circuit"); +static LLTrace::BlockTimerStatHandle FTM_IDLE_NETWORK("Idle Network"); +static LLTrace::BlockTimerStatHandle FTM_MESSAGE_ACKS("Message Acks"); +static LLTrace::BlockTimerStatHandle FTM_RETRANSMIT("Retransmit"); +static LLTrace::BlockTimerStatHandle FTM_TIMEOUT_CHECK("Timeout Check"); +static LLTrace::BlockTimerStatHandle FTM_DYNAMIC_THROTTLE("Dynamic Throttle"); +static LLTrace::BlockTimerStatHandle FTM_CHECK_REGION_CIRCUIT("Check Region Circuit"); void LLAppViewer::idleNetwork() { @@ -4388,7 +4699,7 @@ void LLAppViewer::idleNetwork() static const LLCachedControl speedTest(gSavedSettings, "SpeedTest"); if (!speedTest) { - LLFastTimer t(FTM_IDLE_NETWORK); // decode + LL_RECORD_BLOCK_TIME(FTM_IDLE_NETWORK); // decode LL_PUSH_CALLSTACKS(); LLTimer check_message_timer; @@ -4488,7 +4799,7 @@ void LLAppViewer::idleNetwork() void LLAppViewer::idleAudio() { gFrameStats.start(LLFrameStats::AUDIO); - LLFastTimer t(FTM_AUDIO_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_AUDIO_UPDATE); if (gAudiop) { @@ -4505,19 +4816,7 @@ void LLAppViewer::shutdownAudio() if (gAudiop) { // shut down the audio subsystem - - bool want_longname = false; - if (gAudiop->getDriverName(want_longname) == "FMOD") - { - // This hack exists because fmod likes to occasionally - // crash or hang forever when shutting down, for no - // apparent reason. - LL_WARNS() << "Hack, skipping FMOD audio engine cleanup" << LL_ENDL; - } - else - { - gAudiop->shutdown(); - } + gAudiop->shutdown(); delete gAudiop; gAudiop = NULL; @@ -4549,36 +4848,38 @@ void LLAppViewer::disconnectViewer() if (gFloaterView) { gFloaterView->restoreAll(); - } + std::list floaters_to_close; + for (LLView::child_list_const_iter_t it = gFloaterView->getChildList()->begin(); + it != gFloaterView->getChildList()->end(); + ++it) + { + // The following names are defined in the + // floater_image_preview.xml + // floater_sound_preview.xml + // floater_animation_preview.xml + // files. + + // A more generic mechanism would be nice.. + LLFloater* fl = static_cast(*it); + if (fl + && (fl->getName() == "Image Preview" + || fl->getName() == "Sound Preview" + || fl->getName() == "Animation Preview" + || fl->getName() == "perm prefs" + )) + { + floaters_to_close.push_back(fl); + } + } - std::list floaters_to_close; - for(LLView::child_list_const_iter_t it = gFloaterView->getChildList()->begin(); - it != gFloaterView->getChildList()->end(); - ++it) - { - // The following names are defined in the - // floater_image_preview.xml - // floater_sound_preview.xml - // floater_animation_preview.xml - // files. - LLFloater* fl = static_cast(*it); - if(fl - && (fl->getName() == "Image Preview" - || fl->getName() == "Sound Preview" - || fl->getName() == "Animation Preview" - )) + while (!floaters_to_close.empty()) { - floaters_to_close.push_back(fl); + LLFloater* fl = floaters_to_close.front(); + floaters_to_close.pop_front(); + fl->close(); } } - - while(!floaters_to_close.empty()) - { - LLFloater* fl = floaters_to_close.front(); - floaters_to_close.pop_front(); - fl->close(); - } } if (LLSelectMgr::getInstance()) @@ -4600,9 +4901,15 @@ void LLAppViewer::disconnectViewer() } saveNameCache(); + if (LLExperienceCache::instanceExists()) + { + // TODO: LLExperienceCache::cleanup() logic should be moved to + // cleanupSingleton(). + LLExperienceCache::instance().cleanup(); + } // close inventory interface, close all windows - LLInventoryView::cleanup(); + LLPanelMainInventory::cleanup(); // [SL:KB] - Patch: Appearance-Misc | Checked: 2013-02-12 (Catznip-3.4) // Destroying all objects below will trigger attachment detaching code and attempt to remove the COF links for them LLAppearanceMgr::instance().setAttachmentInvLinkEnable(false); @@ -4632,26 +4939,31 @@ void LLAppViewer::disconnectViewer() void LLAppViewer::forceErrorLLError() { - LL_ERRS() << "This is an llerror" << LL_ENDL; + LL_ERRS() << "This is a deliberate llerror" << LL_ENDL; } void LLAppViewer::forceErrorBreakpoint() { + LL_WARNS() << "Forcing a deliberate breakpoint" << LL_ENDL; #ifdef LL_WINDOWS DebugBreak(); +#else + asm ("int $3"); #endif return; } void LLAppViewer::forceErrorBadMemoryAccess() { - S32* crash = NULL; + LL_WARNS() << "Forcing a deliberate bad memory access" << LL_ENDL; + S32* crash = nullptr; *crash = 0xDEADBEEF; return; } void LLAppViewer::forceErrorInfiniteLoop() { + LL_WARNS() << "Forcing a deliberate infinite loop" << LL_ENDL; while(true) { ; @@ -4661,13 +4973,15 @@ void LLAppViewer::forceErrorInfiniteLoop() void LLAppViewer::forceErrorSoftwareException() { + LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL; // *FIX: Any way to insure it won't be handled? throw; } void LLAppViewer::forceErrorDriverCrash() { - glDeleteTextures(1, NULL); + LL_WARNS() << "Forcing a deliberate driver crash" << LL_ENDL; + glDeleteTextures(1, nullptr); } void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs) @@ -4684,7 +4998,7 @@ void LLAppViewer::destroyMainloopTimeout() if(mMainloopTimeout) { delete mMainloopTimeout; - mMainloopTimeout = NULL; + mMainloopTimeout = nullptr; } } @@ -4736,12 +5050,12 @@ void LLAppViewer::handleLoginComplete() initMainloopTimeout("Mainloop Init"); // Store some data to DebugInfo in case of a freeze. - gDebugInfo["ClientInfo"]["Name"] = gVersionChannel; + gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel(); - gDebugInfo["ClientInfo"]["MajorVersion"] = gVersionMajor; - gDebugInfo["ClientInfo"]["MinorVersion"] = gVersionMinor; - gDebugInfo["ClientInfo"]["PatchVersion"] = gVersionPatch; - gDebugInfo["ClientInfo"]["BuildVersion"] = gVersionBuild; + gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor(); + gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor(); + gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch(); + gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild(); LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if ( parcel && parcel->getMusicURL()[0]) @@ -4770,6 +5084,10 @@ void LLAppViewer::handleLoginComplete() } mOnLoginCompleted(); + + // Singu Note: This would usually be registered via mOnLoginCompleted, but that would require code in newview regardless so.. just call directly here. + LLNotifications::instance().onLoginCompleted(); + // Singu Note: Due to MAINT-4001, we must do this here, it lives in LLSidepanelInventory::updateInbox upstream. // Consolidate Received items // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention, diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index f461c259b3..9644fbe08b 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -76,6 +76,7 @@ class LLAppViewer : public LLApp bool quitRequested() { return mQuitRequested; } bool logoutRequestSent() { return mLogoutRequestSent; } + bool isSecondInstance() { return mSecondInstance; } void writeDebugInfo(bool isStatic=true); @@ -86,7 +87,7 @@ class LLAppViewer : public LLApp virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism. // return false if the error trap needed restoration. - virtual void initCrashReporting(bool reportFreeze = false) = 0; // What to do with crash report? + void initCrashReporting(); // What to do with crash report? static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon. // Thread accessors @@ -101,7 +102,7 @@ class LLAppViewer : public LLApp bool getPurgeCache() const { return mPurgeCache; } - const std::string& getSecondLifeTitle() const; // The Second Life title. + std::string getSecondLifeTitle() const; // The Second Life title. const std::string& getWindowTitle() const; // The window display name. void forceDisconnect(const std::string& msg); // Force disconnection, with a message to the user. @@ -113,7 +114,7 @@ class LLAppViewer : public LLApp void loadNameCache(); void saveNameCache(); - void removeMarkerFile(bool leave_logout_marker = false); + void removeMarkerFiles(); void removeDumpDir(); // LLAppViewer testing helpers. @@ -125,14 +126,13 @@ class LLAppViewer : public LLApp virtual void forceErrorSoftwareException(); virtual void forceErrorDriverCrash(); - // *NOTE: There are currently 3 settings files: - // "Global", "PerAccount" and "CrashSettings" + // *NOTE: There are currently 2 settings files: + // "Global", and "PerAccount" // The list is found in app_settings/settings_files.xml // but since they are used explicitly in code, // the follow consts should also do the trick. static const std::string sGlobalSettingsName; static const std::string sPerAccountSettingsName; - static const std::string sCrashSettingsName; // Load settings from the location specified by loction_key. // Key availale and rules for loading, are specified in @@ -158,6 +158,7 @@ class LLAppViewer : public LLApp void handleLoginComplete(); LLAllocator & getAllocator() { return mAlloc; } + // On LoginCompleted callback typedef boost::signals2::signal login_completed_signal_t; login_completed_signal_t mOnLoginCompleted; @@ -172,7 +173,8 @@ class LLAppViewer : public LLApp static void metricsSend(bool enable_reporting); protected: virtual bool initWindow(); // Initialize the viewer's window. - virtual bool initLogging(); // Initialize log files, logging system, return false on failure. + virtual void initLoggingAndGetLastDuration(); // Initialize log files, logging system + void initLoggingInternal(); virtual void initConsole() {}; // Initialize OS level debugging console. virtual bool initHardwareTest() { return true; } // A false result indicates the app should quit. virtual bool initSLURLHandler(); @@ -189,7 +191,6 @@ class LLAppViewer : public LLApp void initMaxHeapSize(); bool initThreads(); // Initialize viewer threads, return false on failure. bool initConfiguration(); // Initialize settings from the command line/config file. - bool initCache(); // Initialize local client cache. void checkMemory() ; @@ -202,8 +203,9 @@ class LLAppViewer : public LLApp void writeSystemInfo(); // Write system info to "debug_info.log" - bool anotherInstanceRunning(); - void initMarkerFile(); + void processMarkerFiles(); + static void recordMarkerVersion(LLAPRFile& marker_file); + bool markerIsSameVersion(const std::string& marker_name) const; void idle(); void idleShutdown(); @@ -226,8 +228,7 @@ class LLAppViewer : public LLApp LLAPRFile mMarkerFile; // A file created to indicate the app is running. std::string mLogoutMarkerFileName; - apr_file_t* mLogoutMarkerFile; // A file created to indicate the app is running. - + LLAPRFile mLogoutMarkerFile; // A file created to indicate the app is running. LLOSInfo mSysOSInfo; bool mReportedCrash; @@ -271,6 +272,7 @@ class LLAppViewer : public LLApp // consts from viewer.h const S32 AGENT_UPDATES_PER_SECOND = 10; +const S32 AGENT_FORCE_UPDATES_PER_SECOND = 1; // Globals with external linkage. From viewer.h // *NOTE:Mani - These will be removed as the Viewer App Cleanup project continues. @@ -303,13 +305,13 @@ extern LLPumpIO* gServicePump; // Is the Pacific time zone (aka server time zone) // currently in daylight savings time? extern BOOL gPacificDaylightTime; - -extern U64 gFrameTime; // The timestamp of the most-recently-processed frame -extern F32 gFrameTimeSeconds; // Loses msec precision after ~4.5 hours... -extern F32 gFrameIntervalSeconds; // Elapsed time between current and previous gFrameTimeSeconds +extern U64MicrosecondsImplicit gStartTime; +extern U64MicrosecondsImplicit gFrameTime; // The timestamp of the most-recently-processed frame +extern F32SecondsImplicit gFrameTimeSeconds; // Loses msec precision after ~4.5 hours... +extern F32SecondsImplicit gFrameIntervalSeconds; // Elapsed time between current and previous gFrameTimeSeconds extern F32 gFPSClamped; // Frames per second, smoothed, weighted toward last frame extern F32 gFrameDTClamped; -extern U64 gStartTime; + extern U32 gFrameStalls; extern LLTimer gRenderStartTime; @@ -333,7 +335,7 @@ extern BOOL gUseWireframe; extern LLVFS *gStaticVFS; extern LLMemoryInfo gSysMemory; -extern U64 gMemoryAllocated; +extern U64Bytes gMemoryAllocated; extern std::string gLastVersionChannel; diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 764d36e4d1..0f2957bc92 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -119,7 +119,6 @@ int main( int argc, char **argv ) } delete viewer_app_ptr; viewer_app_ptr = NULL; - return 0; } @@ -143,20 +142,12 @@ bool LLAppViewerLinux::init() bool success = LLAppViewer::init(); -#if LL_SEND_CRASH_REPORTS - if (success) - { - LLAppViewer* pApp = LLAppViewer::instance(); - pApp->initCrashReporting(); - } -#endif - return success; } bool LLAppViewerLinux::restoreErrorTrap() { - // *NOTE:Mani there is a case for implementing this or the mac. + // *NOTE:Mani there is a case for implementing this on the mac. // Linux doesn't need it to my knowledge. return true; } @@ -347,12 +338,6 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url) } #endif // LL_DBUS_ENABLED -void LLAppViewerLinux::initCrashReporting(bool reportFreeze) -{ - // Singu Note: this is where original code forks crash logger process. - // Singularity doesn't need it -} - bool LLAppViewerLinux::beingDebugged() { static enum {unknown, no, yes} debugged = unknown; @@ -397,7 +382,7 @@ bool LLAppViewerLinux::beingDebugged() #endif } -bool LLAppViewerLinux::initLogging() +void LLAppViewerLinux::initLoggingAndGetLastDuration() { // Remove the last stack trace, if any // This file is no longer created, since the move to Google Breakpad @@ -406,7 +391,7 @@ bool LLAppViewerLinux::initLogging() gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); LLFile::remove(old_stack_file); - return LLAppViewer::initLogging(); + LLAppViewer::initLoggingAndGetLastDuration(); } bool LLAppViewerLinux::initParseCommandLine(LLCommandLineParser& clp) diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h index 6de13b81ca..6c4020c4ce 100644 --- a/indra/newview/llappviewerlinux.h +++ b/indra/newview/llappviewerlinux.h @@ -64,9 +64,8 @@ class LLAppViewerLinux : public LLAppViewer virtual bool beingDebugged(); virtual bool restoreErrorTrap(); - virtual void initCrashReporting(bool reportFreeze); - virtual bool initLogging(); + virtual void initLoggingAndGetLastDuration(); virtual bool initParseCommandLine(LLCommandLineParser& clp); virtual bool initSLURLHandler(); diff --git a/indra/newview/llappviewerlinux_api_dbus.cpp b/indra/newview/llappviewerlinux_api_dbus.cpp index ff839b7000..f56a75c59d 100644 --- a/indra/newview/llappviewerlinux_api_dbus.cpp +++ b/indra/newview/llappviewerlinux_api_dbus.cpp @@ -47,9 +47,9 @@ extern "C" { #include "apr_dso.h" } -#define DEBUGMSG(...) LL_DEBUGS() << llformat(__VA_ARGS__) << llendl -#define INFOMSG(...) LL_INFOS() << llformat(__VA_ARGS__) << llendl -#define WARNMSG(...) LL_WARNS() << llformat(__VA_ARGS__) << llendl +#define DEBUGMSG(...) LL_DEBUGS() << llformat(__VA_ARGS__) << LL_ENDL +#define INFOMSG(...) LL_INFOS() << llformat(__VA_ARGS__) << LL_ENDL +#define WARNMSG(...) LL_WARNS() << llformat(__VA_ARGS__) << LL_ENDL #define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) RTN (*ll##DBUSSYM)(__VA_ARGS__) = NULL #include "llappviewerlinux_api_dbus_syms_raw.inc" diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 3004806343..d4eef2b2b4 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -260,12 +260,6 @@ bool LLAppViewerMacOSX::restoreErrorTrap() return reset_count == 0; } -void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze) -{ - // Singu Note: this is where original code forks crash logger process. - // Singularity doesn't need it -} - std::string LLAppViewerMacOSX::generateSerialNumber() { char serial_md5[MD5HEX_STR_SIZE]; // Flawfinder: ignore diff --git a/indra/newview/llappviewermacosx.h b/indra/newview/llappviewermacosx.h index e94b297beb..69d069d013 100644 --- a/indra/newview/llappviewermacosx.h +++ b/indra/newview/llappviewermacosx.h @@ -51,7 +51,6 @@ class LLAppViewerMacOSX : public LLAppViewer protected: virtual bool restoreErrorTrap(); - virtual void initCrashReporting(bool reportFreeze); std::string generateSerialNumber(); virtual bool initParseCommandLine(LLCommandLineParser& clp); diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 0f103fd6cc..3dc530a576 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -32,12 +32,6 @@ #include "llviewerprecompiledheaders.h" -#if defined(_DEBUG) -# if _MSC_VER >= 1400 // Visual C++ 2005 or later -# define WINDOWS_CRT_MEM_CHECKS 1 -# endif -#endif - #include "llwindowwin32.h" // *FIX: for setting gIconResource. #include "llappviewerwin32.h" @@ -47,7 +41,6 @@ #include //_O_APPEND #include //_open_osfhandle() -#include // for AddERExcludedApplicationA() #include // _spawnl() #include // For TCHAR support #include @@ -55,8 +48,10 @@ #include "llviewercontrol.h" #include "lldxhardware.h" +#ifdef USE_NVAPI #include "nvapi/nvapi.h" #include "nvapi/NvApiDriverSettings.h" +#endif #include @@ -72,35 +67,8 @@ #include "llcommandlineparser.h" #include "lltrans.h" -// *FIX:Mani - This hack is to fix a linker issue with libndofdev.lib -// The lib was compiled under VS2005 - in VS2003 we need to remap assert -#ifdef LL_DEBUG -#ifdef LL_MSVC7 -extern "C" { - void _wassert(const wchar_t * _Message, const wchar_t *_File, unsigned _Line) - { - LL_ERRS() << _Message << LL_ENDL; - } -} -#endif -#endif - const std::string LLAppViewerWin32::sWindowClass = "Second Life"; -/* - This function is used to print to the command line a text message - describing the nvapi error and quits -*/ -void nvapi_error(NvAPI_Status status) -{ - NvAPI_ShortString szDesc = {0}; - NvAPI_GetErrorMessage(status, szDesc); - LL_WARNS() << szDesc << LL_ENDL; - - //should always trigger when asserts are enabled - //llassert(status == NVAPI_OK); -} - // Create app mutex creates a unique global windows object. // If the object can be created it returns true, otherwise // it returns false. The false result can be used to determine @@ -114,7 +82,7 @@ bool create_app_mutex() bool result = true; LPCWSTR unique_mutex_name = L"SecondLifeAppMutex"; HANDLE hMutex; - hMutex = CreateMutex(NULL, TRUE, unique_mutex_name); + hMutex = CreateMutex(nullptr, TRUE, unique_mutex_name); if(GetLastError() == ERROR_ALREADY_EXISTS) { result = false; @@ -122,6 +90,23 @@ bool create_app_mutex() return result; } +#ifdef USE_NVAPI +#define NVAPI_APPNAME L"Second Life" + +/* +This function is used to print to the command line a text message +describing the nvapi error and quits +*/ +void nvapi_error(NvAPI_Status status) +{ + NvAPI_ShortString szDesc = { 0 }; + NvAPI_GetErrorMessage(status, szDesc); + LL_WARNS() << szDesc << LL_ENDL; + + //should always trigger when asserts are enabled + //llassert(status == NVAPI_OK); +} + void ll_nvapi_init(NvDRSSessionHandle hSession) { // (2) load all the system settings into the session @@ -132,12 +117,9 @@ void ll_nvapi_init(NvDRSSessionHandle hSession) return; } - NvAPI_UnicodeString profile_name; - //std::string app_name = LLTrans::getString("APP_NAME"); - std::string app_name("Second Life"); // - llutf16string w_app_name = utf8str_to_utf16str(app_name); - wsprintf(profile_name, L"%s", w_app_name.c_str()); - status = NvAPI_DRS_SetCurrentGlobalProfile(hSession, profile_name); + NvAPI_UnicodeString wsz = { 0 }; + memcpy_s(wsz, sizeof(wsz), NVAPI_APPNAME, sizeof(NVAPI_APPNAME)); + status = NvAPI_DRS_SetCurrentGlobalProfile(hSession, wsz); if (status != NVAPI_OK) { nvapi_error(status); @@ -194,6 +176,7 @@ void ll_nvapi_init(NvDRSSessionHandle hSession) return; } } +#endif //#define DEBUGGING_SEH_FILTER 1 #if DEBUGGING_SEH_FILTER @@ -238,7 +221,9 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32(lpCmdLine); +#if !defined(USE_CRASHPAD) viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); +#endif // Set a debug info flag to indicate if multiple instances are running. bool found_other_instance = !create_app_mutex(); @@ -251,6 +236,7 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, return -1; } +#ifdef USE_NVAPI NvAPI_Status status; // Initialize NVAPI @@ -271,6 +257,7 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, ll_nvapi_init(hSession); } } +#endif // Have to wait until after logging is initialized to display LFH info if (num_heaps > 0) @@ -328,7 +315,7 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, } delete viewer_app_ptr; - viewer_app_ptr = NULL; + viewer_app_ptr = nullptr; //start updater if(LLAppViewer::sUpdaterInfo) @@ -339,14 +326,14 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, LLAppViewer::sUpdaterInfo = NULL ; } - - +#ifdef USE_NVAPI // (NVAPI) (6) We clean up. This is analogous to doing a free() if (hSession) { NvAPI_DRS_DestroySession(hSession); hSession = 0; } +#endif return 0; } @@ -374,102 +361,48 @@ int APIENTRY WinMain(HINSTANCE hInstance, void LLAppViewerWin32::disableWinErrorReporting() { - const char win_xp_string[] = "Microsoft Windows XP"; - BOOL is_win_xp = ( getOSInfo().getOSString().substr(0, strlen(win_xp_string) ) == win_xp_string ); /* Flawfinder: ignore*/ - if( is_win_xp ) - { - // Note: we need to use run-time dynamic linking, because load-time dynamic linking will fail - // on systems that don't have the library installed (all non-Windows XP systems) - HINSTANCE fault_rep_dll_handle = LoadLibrary(L"faultrep.dll"); /* Flawfinder: ignore */ - if( fault_rep_dll_handle ) - { - pfn_ADDEREXCLUDEDAPPLICATIONA pAddERExcludedApplicationA = (pfn_ADDEREXCLUDEDAPPLICATIONA) GetProcAddress(fault_rep_dll_handle, "AddERExcludedApplicationA"); - if( pAddERExcludedApplicationA ) - { + std::string const& executable_name = gDirUtilp->getExecutableFilename(); - // Strip the path off the name - const char* executable_name = gDirUtilp->getExecutableFilename().c_str(); - - if( 0 == pAddERExcludedApplicationA( executable_name ) ) - { - U32 error_code = GetLastError(); - LL_INFOS() << "AddERExcludedApplication() failed with error code " << error_code << LL_ENDL; - } - else - { - LL_INFOS() << "AddERExcludedApplication() success for " << executable_name << LL_ENDL; - } - } - FreeLibrary( fault_rep_dll_handle ); - } + if( S_OK == WerAddExcludedApplication( utf8str_to_utf16str(executable_name).c_str(), FALSE ) ) + { + LL_INFOS() << "WerAddExcludedApplication() succeeded for " << executable_name << LL_ENDL; + } + else + { + LL_INFOS() << "WerAddExcludedApplication() failed for " << executable_name << LL_ENDL; } } const S32 MAX_CONSOLE_LINES = 500; -void create_console() +static bool create_console() { - int h_con_handle; - long l_std_handle; CONSOLE_SCREEN_BUFFER_INFO coninfo; - FILE *fp; // allocate a console for this app - AllocConsole(); + const bool isConsoleAllocated = AllocConsole(); // set the screen buffer to be big enough to let us scroll text GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); coninfo.dwSize.Y = MAX_CONSOLE_LINES; SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); - // redirect unbuffered STDOUT to the console - l_std_handle = (long)GetStdHandle(STD_OUTPUT_HANDLE); - h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT); - if (h_con_handle == -1) - { - LL_WARNS() << "create_console() failed to open stdout handle" << LL_ENDL; - } - else - { - fp = _fdopen( h_con_handle, "w" ); - *stdout = *fp; - setvbuf( stdout, NULL, _IONBF, 0 ); - } + // Redirect the CRT standard input, output, and error handles to the console + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); - // redirect unbuffered STDIN to the console - l_std_handle = (long)GetStdHandle(STD_INPUT_HANDLE); - h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT); - if (h_con_handle == -1) - { - LL_WARNS() << "create_console() failed to open stdin handle" << LL_ENDL; - } - else - { - fp = _fdopen( h_con_handle, "r" ); - *stdin = *fp; - setvbuf( stdin, NULL, _IONBF, 0 ); - } + setvbuf( stdin, nullptr, _IONBF, 0 ); + setvbuf( stdout, nullptr, _IONBF, 0 ); + setvbuf( stderr, nullptr, _IONBF, 0 ); - // redirect unbuffered STDERR to the console - l_std_handle = (long)GetStdHandle(STD_ERROR_HANDLE); - h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT); - if (h_con_handle == -1) - { - LL_WARNS() << "create_console() failed to open stderr handle" << LL_ENDL; - } - else - { - fp = _fdopen( h_con_handle, "w" ); - *stderr = *fp; - setvbuf( stderr, NULL, _IOFBF, 1024 ); //Assigning a buffer improves speed a LOT, esp on vista/win7 - //_IOLBF is borked. - } + return isConsoleAllocated; } - LLAppViewerWin32::LLAppViewerWin32(const char* cmd_line) : - mCmdLine(cmd_line) + mCmdLine(cmd_line), + mIsConsoleAllocated(false) { } @@ -481,7 +414,7 @@ bool LLAppViewerWin32::init() { // Platform specific initialization. - // Turn off Windows XP Error Reporting + // Turn off Windows Error Reporting // (Don't send our data to Microsoft--at least until we are Logo approved and have a way // of getting the data back from them.) // @@ -492,15 +425,6 @@ bool LLAppViewerWin32::init() LLWinDebug::instance().init(); #endif -#if LL_WINDOWS -#if LL_SEND_CRASH_REPORTS - - LLAppViewer* pApp = LLAppViewer::instance(); - pApp->initCrashReporting(); - -#endif -#endif - bool success = LLAppViewer::init(); return success; @@ -512,18 +436,24 @@ bool LLAppViewerWin32::cleanup() gDXHardware.cleanup(); + if (mIsConsoleAllocated) + { + FreeConsole(); + mIsConsoleAllocated = false; + } + return result; } -bool LLAppViewerWin32::initLogging() +void LLAppViewerWin32::initLoggingAndGetLastDuration() { - return LLAppViewer::initLogging(); + LLAppViewer::initLoggingAndGetLastDuration(); } void LLAppViewerWin32::initConsole() { // pop up debug console - create_console(); + mIsConsoleAllocated = create_console(); return LLAppViewer::initConsole(); } @@ -557,7 +487,10 @@ bool LLAppViewerWin32::initHardwareTest() LL_DEBUGS("AppInit") << "Attempting to poll DirectX for hardware info" << LL_ENDL; gDXHardware.setWriteDebugFunc(write_debug_dx); - BOOL probe_ok = gDXHardware.getInfo(vram_only); + + S32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); + + BOOL probe_ok = gDXHardware.getInfo(vram_only, system_ram); if (!probe_ok && gSavedSettings.getWarning("AboutDirectX9")) @@ -602,6 +535,7 @@ bool LLAppViewerWin32::initHardwareTest() if (gGLManager.mVRAM == 0) { gGLManager.mVRAM = gDXHardware.getVRAM(); + LL_WARNS("AppInit") << "gGLManager.mVRAM: " << gGLManager.mVRAM << LL_ENDL; } LL_INFOS("AppInit") << "Detected VRAM: " << gGLManager.mVRAM << LL_ENDL; @@ -617,7 +551,7 @@ bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp) } // Find the system language. - FL_Locale *locale = NULL; + FL_Locale *locale = nullptr; FL_Success success = FL_FindLocale(&locale, FL_MESSAGES); if (success != 0) { @@ -641,12 +575,6 @@ bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp) bool LLAppViewerWin32::restoreErrorTrap() { return true; - //return LLWinDebug::checkExceptionHandler(); -} - -void LLAppViewerWin32::initCrashReporting(bool reportFreeze) -{ - // Singu Note: we don't fork the crash logger on start } //virtual @@ -656,9 +584,9 @@ bool LLAppViewerWin32::sendURLToOtherInstance(const std::string& url) mbstowcs(window_class, sWindowClass.c_str(), 255); window_class[255] = 0; // Use the class instead of the window name. - HWND other_window = FindWindow(window_class, NULL); + HWND other_window = FindWindow(window_class, nullptr); - if (other_window != NULL) + if (other_window != nullptr) { LL_DEBUGS() << "Found other window with the name '" << getWindowTitle() << "'" << LL_ENDL; COPYDATASTRUCT cds; @@ -684,13 +612,13 @@ std::string LLAppViewerWin32::generateSerialNumber() DWORD serial = 0; DWORD flags = 0; BOOL success = GetVolumeInformation( - L"C:\\", - NULL, // volume name buffer + TEXT("C:\\"), + nullptr, // volume name buffer 0, // volume name buffer size &serial, // volume serial - NULL, // max component length + nullptr, // max component length &flags, // file system flags - NULL, // file system name buffer + nullptr, // file system name buffer 0); // file system name buffer size if (success) { diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h index 757f6ea0ca..96f8347988 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -46,22 +46,20 @@ class LLAppViewerWin32 : public LLAppViewer // // Main application logic // - virtual bool init(); // Override to do application initialization - virtual bool cleanup(); + bool init() override; // Override to do application initialization + bool cleanup() override; protected: - virtual bool initLogging(); // Override to clean stack_trace info. - virtual void initConsole(); // Initialize OS level debugging console. - virtual bool initHardwareTest(); // Win32 uses DX9 to test hardware. - virtual bool initParseCommandLine(LLCommandLineParser& clp); + void initLoggingAndGetLastDuration() override; // Override to clean stack_trace info. + void initConsole() override; // Initialize OS level debugging console. + bool initHardwareTest() override; // Win32 uses DX9 to test hardware. + bool initParseCommandLine(LLCommandLineParser& clp) override; - virtual bool restoreErrorTrap(); - virtual void initCrashReporting(bool reportFreeze); + bool restoreErrorTrap() override; - virtual bool sendURLToOtherInstance(const std::string& url); - - std::string generateSerialNumber(); + bool sendURLToOtherInstance(const std::string& url) override; + std::string generateSerialNumber() override; static const std::string sWindowClass; @@ -69,6 +67,7 @@ class LLAppViewerWin32 : public LLAppViewer void disableWinErrorReporting(); std::string mCmdLine; + bool mIsConsoleAllocated; }; #endif // LL_LLAPPVIEWERWIN32_H diff --git a/indra/newview/llassetuploadqueue.cpp b/indra/newview/llassetuploadqueue.cpp index 88695b2d14..67c7fa55c0 100644 --- a/indra/newview/llassetuploadqueue.cpp +++ b/indra/newview/llassetuploadqueue.cpp @@ -171,6 +171,7 @@ void LLAssetUploadQueue::request(LLAssetUploadQueueSupplier** supplier) body["item_id"] = data.mItemId; body["is_script_running"] = data.mIsRunning; body["target"] = data.mIsTargetMono? "mono" : "lsl2"; + body["experience"] = data.mExperienceId; std::string url = ""; LLViewerObject* object = gObjectList.findObject(data.mTaskId); @@ -194,7 +195,8 @@ void LLAssetUploadQueue::queue(const std::string& filename, const LLUUID& queue_id, U8* script_data, U32 data_size, - std::string script_name) + std::string script_name, + const LLUUID& experience_id) { UploadData data; data.mTaskId = task_id; @@ -206,6 +208,7 @@ void LLAssetUploadQueue::queue(const std::string& filename, data.mData = script_data; data.mDataSize = data_size; data.mScriptName = script_name; + data.mExperienceId = experience_id; mQueue.push_back(data); diff --git a/indra/newview/llassetuploadqueue.h b/indra/newview/llassetuploadqueue.h index 930dc72a73..bc6c11cdab 100644 --- a/indra/newview/llassetuploadqueue.h +++ b/indra/newview/llassetuploadqueue.h @@ -56,7 +56,8 @@ class LLAssetUploadQueue const LLUUID& queue_id, U8* data, U32 data_size, - std::string script_name); + std::string script_name, + const LLUUID& experience_id); bool isEmpty() const {return mQueue.empty();} @@ -75,6 +76,7 @@ class LLAssetUploadQueue U8* mData; U32 mDataSize; std::string mScriptName; + LLUUID mExperienceId; }; // Ownership of mSupplier passed to currently waiting responder diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index b7fabd8a81..b50d0202dc 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -35,6 +35,7 @@ // viewer includes #include "llagent.h" +#include "llagentbenefits.h" #include "llcompilequeue.h" #include "llfloaterbuycurrency.h" #include "statemachine/aifilepicker.h" @@ -59,7 +60,6 @@ // library includes #include "lldir.h" -#include "lleconomy.h" #include "llfocusmgr.h" #include "llnotificationsutil.h" #include "llscrolllistctrl.h" @@ -223,6 +223,27 @@ LLAssetUploadResponder::~LLAssetUploadResponder() } } +void on_failure(const LLAssetType::EType& mAssetType, const LLSD& mPostData, const LLSD& args) +{ + switch (mAssetType) + { + case LLAssetType::AT_NOTECARD: + { + if (LLPreviewNotecard* nc = (LLPreviewNotecard*)LLPreview::find(mPostData["item_id"])) + nc->setEnabled(true); + break; + } + case LLAssetType::AT_SCRIPT: + case LLAssetType::AT_LSL_TEXT: + case LLAssetType::AT_LSL_BYTECODE: + { + if (LLPreviewLSL* lsl = (LLPreviewLSL*)LLPreview::find(mPostData["item_id"])) + lsl->callbackLSLCompileFailed(LLSD().with(0, "Upload Failure:").with(1, args["REASON"])); + break; + } + default: break; + } +} // virtual void LLAssetUploadResponder::httpFailure() { @@ -245,6 +266,7 @@ void LLAssetUploadResponder::httpFailure() LLNotificationsUtil::add("CannotUploadReason", args); break; } + on_failure(mAssetType, mPostData, args); LLUploadDialog::modalUploadFinished(); } @@ -304,7 +326,11 @@ void LLAssetUploadResponder::uploadFailure(const LLSD& content) // deal with L$ errors if (reason == "insufficient funds") { - S32 price = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 price; + if (content.has("upload_price")) + price = content["upload_price"]; + else + LLAgentBenefitsMgr::current().findUploadCost(mAssetType, price); LLFloaterBuyCurrency::buyCurrency("Uploading costs", price); } else @@ -313,6 +339,7 @@ void LLAssetUploadResponder::uploadFailure(const LLSD& content) args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); args["REASON"] = content["message"].asString(); LLNotificationsUtil::add("CannotUploadReason", args); + on_failure(mAssetType, mPostData, args); } } @@ -367,13 +394,14 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) // Update L$ and ownership credit information // since it probably changed on the server - if (asset_type == LLAssetType::AT_TEXTURE || + if (content.has("upload_price")) + expected_upload_cost = content["upload_price"]; + else if (asset_type == LLAssetType::AT_TEXTURE || asset_type == LLAssetType::AT_SOUND || asset_type == LLAssetType::AT_ANIMATION || asset_type == LLAssetType::AT_MESH) { - expected_upload_cost = - LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + LLAgentBenefitsMgr::current().findUploadCost(asset_type, expected_upload_cost); } LL_INFOS() << "Adding " << content["new_inventory_item"].asUUID() << " " diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp index 6f2f4d7d27..ef533de19d 100644 --- a/indra/newview/llattachmentsmgr.cpp +++ b/indra/newview/llattachmentsmgr.cpp @@ -27,7 +27,9 @@ #include "llviewerprecompiledheaders.h" #include "llattachmentsmgr.h" +#include "llvoavatarself.h" #include "llagent.h" +#include "llappearancemgr.h" #include "llinventorymodel.h" #include "lltooldraganddrop.h" // pack_permissions_slam #include "llviewerinventory.h" @@ -37,8 +39,37 @@ #include "rlvhandler.h" #include "rlvlocks.h" // [/RLVa:KB] +#include -LLAttachmentsMgr::LLAttachmentsMgr() +const F32 COF_LINK_BATCH_TIME = 5.0F; +const F32 MAX_ATTACHMENT_REQUEST_LIFETIME = 30.0F; +const F32 MIN_RETRY_REQUEST_TIME = 5.0F; +const F32 MAX_BAD_COF_TIME = 30.0F; + +// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2015-06-24 (Catznip-3.7) +class LLRegisterAttachmentCallback : public LLRequestServerAppearanceUpdateOnDestroy +{ +public: + LLRegisterAttachmentCallback() + : LLRequestServerAppearanceUpdateOnDestroy() + { + } + + /*virtual*/ ~LLRegisterAttachmentCallback() + { + } + + /*virtual*/ void fire(const LLUUID& idItem) + { + LLAttachmentsMgr::instance().onRegisterAttachmentComplete(idItem); + } +}; +// [/SL:KB] + +LLAttachmentsMgr::LLAttachmentsMgr(): + mAttachmentRequests("attach",MIN_RETRY_REQUEST_TIME), + mDetachRequests("detach",MIN_RETRY_REQUEST_TIME) +// , mQuestionableCOFLinks("badcof",MAX_BAD_COF_TIME) { } @@ -46,20 +77,34 @@ LLAttachmentsMgr::~LLAttachmentsMgr() { } -void LLAttachmentsMgr::addAttachment(const LLUUID& item_id, - const U8 attachment_pt, +//void LLAttachmentsMgr::addAttachmentRequest(const LLUUID& item_id, +// const U8 attachment_pt, // const BOOL add) // [RLVa:KB] - Checked: 2010-09-13 (RLVa-1.2.1) +void LLAttachmentsMgr::addAttachmentRequest(const LLUUID& item_id, + const U8 attachment_pt, const BOOL add, const BOOL fRlvForce /*=FALSE*/) // [/RLVa:KB] { + LLViewerInventoryItem *item = gInventory.getItem(item_id); + + if (mAttachmentRequests.wasRequestedRecently(item_id)) + { + LL_DEBUGS("Avatar") << "ATT not adding attachment to mPendingAttachments, recent request is already pending: " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + return; + } + + LL_DEBUGS("Avatar") << "ATT adding attachment to mPendingAttachments " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + AttachmentsInfo attachment; attachment.mItemID = item_id; attachment.mAttachmentPt = attachment_pt; attachment.mAdd = add; // [RLVa:KB] - Checked: 2010-09-23 (RLVa-1.2.1) - if ( (rlv_handler_t::isEnabled()) && (!fRlvForce) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) ) + if ( (rlv_handler_t::isEnabled()) && (!fRlvForce) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) && (gAgentWearables.areInitialAttachmentsRequested()) ) { const LLInventoryItem* pItem = gInventory.getItem(item_id); if (!pItem) @@ -78,6 +123,21 @@ void LLAttachmentsMgr::addAttachment(const LLUUID& item_id, // [/RLVa:KB] mPendingAttachments.push_back(attachment); + + mAttachmentRequests.addTime(item_id); +} + +void LLAttachmentsMgr::onAttachmentRequested(const LLUUID& item_id) +{ +// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2015-06-24 (Catznip-3.7) + if (item_id.isNull()) + return; +// [/SL:KB] + + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attachment was requested " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + mAttachmentRequests.addTime(item_id); } // static @@ -88,10 +148,55 @@ void LLAttachmentsMgr::onIdle(void *) void LLAttachmentsMgr::onIdle() { - if(!gAgent.getRegion()) + // Make sure we got a region before trying anything else + if( !gAgent.getRegion() ) + { + return; + } + + if (LLApp::isExiting()) + { + return; + } + + requestPendingAttachments(); + + linkRecentlyArrivedAttachments(); + + expireOldAttachmentRequests(); + + expireOldDetachRequests(); + +// checkInvalidCOFLinks(); + + spamStatusInfo(); +} + +void LLAttachmentsMgr::requestPendingAttachments() +{ + if (mPendingAttachments.size()) + { + requestAttachments(mPendingAttachments); + } +} + +// Send request(s) for a group of attachments. As coded, this can +// request at most 40 attachments and the rest will be +// ignored. Currently the max attachments per avatar is 38, so the 40 +// limit should not be hit in practice. +void LLAttachmentsMgr::requestAttachments(attachments_vec_t& attachment_requests) +{ + // Make sure we got a region before trying anything else + if( !gAgent.getRegion() ) + { return; + } - S32 obj_count = mPendingAttachments.size(); + // For unknown reasons, requesting many attachments at once causes + // frequent server-side failures. Here we're limiting the number + // of attachments requested per idle loop. + const S32 max_objects_per_request = 5; + S32 obj_count = llmin((S32)attachment_requests.size(),max_objects_per_request); if (obj_count == 0) { return; @@ -103,18 +208,24 @@ void LLAttachmentsMgr::onIdle() const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET; if( obj_count > MAX_OBJECTS_TO_SEND ) { + LL_WARNS() << "ATT Too many attachments requested: " << obj_count + << " exceeds limit of " << MAX_OBJECTS_TO_SEND << LL_ENDL; + obj_count = MAX_OBJECTS_TO_SEND; } + LL_DEBUGS("Avatar") << "ATT [RezMultipleAttachmentsFromInv] attaching multiple from attachment_requests," + " total obj_count " << obj_count << LL_ENDL; + LLUUID compound_msg_id; compound_msg_id.generate(); LLMessageSystem* msg = gMessageSystem; + // by construction above, obj_count <= attachment_requests.size(), so no + // check against attachment_requests.empty() is needed. + llassert(obj_count <= attachment_requests.size()); - S32 i = 0; - for (attachments_vec_t::const_iterator iter = mPendingAttachments.begin(); - iter != mPendingAttachments.end(); - ++iter) + for (S32 i=0; iaddBOOLFast(_PREHASH_FirstDetachAll, false ); } - const AttachmentsInfo &attachment = (*iter); + const AttachmentsInfo& attachment = attachment_requests.front(); LLViewerInventoryItem* item = gInventory.getItem(attachment.mItemID); - if (!item) + if (item) + { + LL_DEBUGS("Avatar") << "ATT requesting from attachment_requests " << item->getName() + << " " << item->getLinkedUUID() << LL_ENDL; + S32 attachment_pt = attachment.mAttachmentPt; + if (attachment.mAdd) + attachment_pt |= ATTACHMENT_ADD; + + msg->nextBlockFast(_PREHASH_ObjectData ); + msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); + msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); + msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); + pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); + msg->addStringFast(_PREHASH_Name, item->getName()); + msg->addStringFast(_PREHASH_Description, item->getDescription()); + } + else { - LL_INFOS() << "Attempted to add non-existant item ID:" << attachment.mItemID << LL_ENDL; - continue; + LL_WARNS("Avatar") << "ATT Attempted to add non-existent item ID:" << attachment.mItemID << LL_ENDL; } - S32 attachment_pt = attachment.mAttachmentPt; - if (attachment.mAdd) - attachment_pt |= ATTACHMENT_ADD; - - msg->nextBlockFast(_PREHASH_ObjectData ); - msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); - msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); - msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); - pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); - msg->addStringFast(_PREHASH_Name, item->getName()); - msg->addStringFast(_PREHASH_Description, item->getDescription()); if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) ) { // End of message chunk msg->sendReliable( gAgent.getRegion()->getHost() ); } - i++; + attachment_requests.pop_front(); } +} + +void LLAttachmentsMgr::linkRecentlyArrivedAttachments() +{ + if (mRecentlyArrivedAttachments.size()) + { + // [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2015-06-24 (Catznip-3.7) + if (!LLAppearanceMgr::instance().getAttachmentInvLinkEnable()) + { + return; + } +// [/SL:KB] + + // One or more attachments have arrived but have not yet been + // processed for COF links + if (mAttachmentRequests.empty()) + { + // Not waiting for any more. + LL_DEBUGS("Avatar") << "ATT all pending attachments have arrived after " + << mCOFLinkBatchTimer.getElapsedTimeF32() << " seconds" << LL_ENDL; + } + else if (mCOFLinkBatchTimer.getElapsedTimeF32() > COF_LINK_BATCH_TIME) + { + LL_DEBUGS("Avatar") << "ATT " << mAttachmentRequests.size() + << " pending attachments have not arrived, but wait time exceeded" << LL_ENDL; + } + else + { + return; + } + + LL_DEBUGS("Avatar") << "ATT checking COF linkability for " << mRecentlyArrivedAttachments.size() + << " recently arrived items" << LL_ENDL; + + uuid_vec_t ids_to_link; + for (auto it = mRecentlyArrivedAttachments.begin(); + it != mRecentlyArrivedAttachments.end(); ++it) + { + if (isAgentAvatarValid() && + gAgentAvatarp->isWearingAttachment(*it) && + !LLAppearanceMgr::instance().isLinkedInCOF(*it)) + { + LLUUID item_id = *it; + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT adding COF link for attachment " + << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; + ids_to_link.push_back(item_id); + } + } + if (ids_to_link.size()) + { +// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2015-06-24 (Catznip-3.7) + LLPointer cb = new LLRegisterAttachmentCallback(); + for (const LLUUID& idAttach : ids_to_link) + { + if (std::find(mPendingAttachLinks.begin(), mPendingAttachLinks.end(), idAttach) == mPendingAttachLinks.end()) + { + LLAppearanceMgr::instance().addCOFItemLink(idAttach, cb); + mPendingAttachLinks.insert(idAttach); + } + } +// [/SL:KB] +// LLPointer cb = new LLRequestServerAppearanceUpdateOnDestroy(); +// for (uuid_vec_t::const_iterator uuid_it = ids_to_link.begin(); +// uuid_it != ids_to_link.end(); ++uuid_it) +// { +// LLAppearanceMgr::instance().addCOFItemLink(*uuid_it, cb); +// } + } + mRecentlyArrivedAttachments.clear(); + } +} + +// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-2.2) +bool LLAttachmentsMgr::getPendingAttachments(uuid_set_t& ids) const +{ + ids.clear(); + + // Returns the union of the LL maintained list of attachments that are waiting for link creation and our maintained list of attachments that are pending link creation + ids.insert(mRecentlyArrivedAttachments.begin(), mRecentlyArrivedAttachments.end()); + ids.insert(mPendingAttachLinks.begin(), mPendingAttachLinks.end()); + // Singu Note: "Expression: Sequence not ordered" using std::set_union + //set_union(mRecentlyArrivedAttachments.begin(), mRecentlyArrivedAttachments.end(), mPendingAttachLinks.begin(), mPendingAttachLinks.end(), std::inserter(ids, ids.begin())); + + return !ids.empty(); +} + +void LLAttachmentsMgr::clearPendingAttachmentLink(const LLUUID& idItem) +{ + mPendingAttachLinks.erase(idItem); +} + +void LLAttachmentsMgr::onRegisterAttachmentComplete(const LLUUID& idAttachLink) +{ + const LLViewerInventoryItem* pAttachLink = gInventory.getItem(idAttachLink); + if (!pAttachLink) + return; + + const LLUUID& idAttachBase = pAttachLink->getLinkedUUID(); + + // Remove the attachment from the pending list + clearPendingAttachmentLink(idAttachBase); + + // It may have been detached already in which case we should remove the COF link + if ( (isAgentAvatarValid()) && (!gAgentAvatarp->isWearingAttachment(idAttachBase)) ) + { + LLAppearanceMgr::instance().removeCOFItemLinks(idAttachBase, NULL, true); + } +} +// [/SL:KB] + +LLAttachmentsMgr::LLItemRequestTimes::LLItemRequestTimes(const std::string& op_name, F32 timeout): + mOpName(op_name), + mTimeout(timeout) +{ +} + +void LLAttachmentsMgr::LLItemRequestTimes::addTime(const LLUUID& inv_item_id) +{ + LLInventoryItem *item = gInventory.getItem(inv_item_id); + LL_DEBUGS("Avatar") << "ATT " << mOpName << " adding request time " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL; + LLTimer current_time; + (*this)[inv_item_id] = current_time; +} + +void LLAttachmentsMgr::LLItemRequestTimes::removeTime(const LLUUID& inv_item_id) +{ + LLInventoryItem *item = gInventory.getItem(inv_item_id); + S32 remove_count = (*this).erase(inv_item_id); + if (remove_count) + { + LL_DEBUGS("Avatar") << "ATT " << mOpName << " removing request time " + << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL; + } +} + +BOOL LLAttachmentsMgr::LLItemRequestTimes::getTime(const LLUUID& inv_item_id, LLTimer& timer) const +{ + std::map::const_iterator it = (*this).find(inv_item_id); + if (it != (*this).end()) + { + timer = it->second; + return TRUE; + } + return FALSE; +} + +BOOL LLAttachmentsMgr::LLItemRequestTimes::wasRequestedRecently(const LLUUID& inv_item_id) const +{ + LLTimer request_time; + if (getTime(inv_item_id, request_time)) + { + F32 request_time_elapsed = request_time.getElapsedTimeF32(); + return request_time_elapsed < mTimeout; + } + else + { + return FALSE; + } +} + +// If we've been waiting for an attachment a long time, we want to +// forget the request, because if the request is invalid (say the +// object does not exist), the existence of a request that never goes +// away will gum up the COF batch logic, causing it to always wait for +// the timeout. Expiring a request means if the item does show up +// late, the COF link request may not get properly batched up, but +// behavior will be no worse than before we had the batching mechanism +// in place; the COF link will still be created, but extra +// requestServerAppearanceUpdate() calls may occur. +void LLAttachmentsMgr::expireOldAttachmentRequests() +{ + for (std::map::iterator it = mAttachmentRequests.begin(); + it != mAttachmentRequests.end(); ) + { + std::map::iterator curr_it = it; + ++it; + if (curr_it->second.getElapsedTimeF32() > MAX_ATTACHMENT_REQUEST_LIFETIME) + { + LLInventoryItem *item = gInventory.getItem(curr_it->first); + LL_WARNS("Avatar") << "ATT expiring request for attachment " + << (item ? item->getName() : "UNKNOWN") << " item_id " << curr_it->first + << " after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds" << LL_ENDL; + mAttachmentRequests.erase(curr_it); + } + } +} + +void LLAttachmentsMgr::expireOldDetachRequests() +{ + for (std::map::iterator it = mDetachRequests.begin(); + it != mDetachRequests.end(); ) + { + std::map::iterator curr_it = it; + ++it; + if (curr_it->second.getElapsedTimeF32() > MAX_ATTACHMENT_REQUEST_LIFETIME) + { + LLInventoryItem *item = gInventory.getItem(curr_it->first); + LL_WARNS("Avatar") << "ATT expiring request for detach " + << (item ? item->getName() : "UNKNOWN") << " item_id " << curr_it->first + << " after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds" << LL_ENDL; + mDetachRequests.erase(curr_it); + } + } +} + +// When an attachment arrives, we want to stop waiting for it, and add +// it to the set of recently arrived items. +void LLAttachmentsMgr::onAttachmentArrived(const LLUUID& inv_item_id) +{ + LLTimer timer; + bool expected = mAttachmentRequests.getTime(inv_item_id, timer); + LLInventoryItem *item = gInventory.getItem(inv_item_id); + + if (!expected) + { + LL_WARNS() << "ATT Attachment was unexpected or arrived after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds: " + << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; + } + mAttachmentRequests.removeTime(inv_item_id); + if (expected && mAttachmentRequests.empty()) + { + // mAttachmentRequests just emptied out + LL_DEBUGS("Avatar") << "ATT all active attachment requests have completed" << LL_ENDL; + } + if (mRecentlyArrivedAttachments.empty()) + { + // Start the timer for sending off a COF link batch. + mCOFLinkBatchTimer.reset(); + } + mRecentlyArrivedAttachments.insert(inv_item_id); + + static const LLCachedControl detach_bridge("SGDetachBridge"); + if (detach_bridge && item && boost::algorithm::contains(item->getName(), " Bridge v")) + { + LL_INFOS() << "Bridge detected! detaching" << LL_ENDL; + LLVOAvatarSelf::detachAttachmentIntoInventory(item->getUUID()); + } +} + +void LLAttachmentsMgr::onDetachRequested(const LLUUID& inv_item_id) +{ + mDetachRequests.addTime(inv_item_id); +} + +void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id) +{ +// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-10-05 (Catznip-2.2) + // (mRecentlyArrivedAttachments doesn't need pruning since it'll check the attachment is actually worn before linking) + clearPendingAttachmentLink(inv_item_id); +// [/SL:KB] + + LLTimer timer; + LLInventoryItem *item = gInventory.getItem(inv_item_id); + if (mDetachRequests.getTime(inv_item_id, timer)) + { + LL_DEBUGS("Avatar") << "ATT detach completed after " << timer.getElapsedTimeF32() + << " seconds for " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL; + mDetachRequests.removeTime(inv_item_id); + if (mDetachRequests.empty()) + { + LL_DEBUGS("Avatar") << "ATT all detach requests have completed" << LL_ENDL; + } + } + else + { + LL_WARNS() << "ATT unexpected detach for " + << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; + } + +// LL_DEBUGS("Avatar") << "ATT detached item flagging as questionable for COF link checking " +// << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; +// mQuestionableCOFLinks.addTime(inv_item_id); +} + +// Check for attachments that are (a) linked in COF and (b) not +// attached to the avatar. This is a rotten function to have to +// include, because it runs the risk of either repeatedly spamming out +// COF link removals if they're failing for some reason, or getting +// into a tug of war with some other sequence of events that's in the +// process of adding the attachment in question. However, it's needed +// because we have no definitive source of authority for what things +// are actually supposed to be attached. Scripts, run on the server +// side, can remove an attachment without our expecting it. If this +// happens to an attachment that's just been added, then the COF link +// creation may still be in flight, and we will have to delete the +// link after it shows up. +// +// Note that we only flag items for possible link removal if they have +// been previously detached. This means that an attachment failure +// will leave the link in the COF, where it will hopefully resolve +// correctly on relog. +// +// See related: MAINT-5070, MAINT-4409 +// +//void LLAttachmentsMgr::checkInvalidCOFLinks() +//{ +// LLInventoryModel::cat_array_t cat_array; +// LLInventoryModel::item_array_t item_array; +// gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), +// cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); +// for (S32 i=0; igetLinkedUUID(); +// if (inv_item->getType() == LLAssetType::AT_OBJECT) +// { +// LLTimer timer; +// bool is_flagged_questionable = mQuestionableCOFLinks.getTime(item_id,timer); +// bool is_wearing_attachment = isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item_id); +// if (is_wearing_attachment && is_flagged_questionable) +// { +// LL_DEBUGS("Avatar") << "ATT was flagged questionable but is now " +// << (is_wearing_attachment ? "attached " : "") +// <<"removing flag after " +// << timer.getElapsedTimeF32() << " item " +// << inv_item->getName() << " id " << item_id << LL_ENDL; +// mQuestionableCOFLinks.removeTime(item_id); +// } +// } +// } +// +// for(LLItemRequestTimes::iterator it = mQuestionableCOFLinks.begin(); +// it != mQuestionableCOFLinks.end(); ) +// { +// LLItemRequestTimes::iterator curr_it = it; +// ++it; +// const LLUUID& item_id = curr_it->first; +// LLViewerInventoryItem *inv_item = gInventory.getItem(item_id); +// if (curr_it->second.getElapsedTimeF32() > MAX_BAD_COF_TIME) +// { +// if (LLAppearanceMgr::instance().isLinkedInCOF(item_id)) +// { +// LL_DEBUGS("Avatar") << "ATT Linked in COF but not attached or requested, deleting link after " +// << curr_it->second.getElapsedTimeF32() << " seconds for " +// << (inv_item ? inv_item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; +// LLAppearanceMgr::instance().removeCOFItemLinks(item_id); +// } +// mQuestionableCOFLinks.erase(curr_it); +// continue; +// } +// } +//} + +void LLAttachmentsMgr::spamStatusInfo() +{ +#if 0 + static LLTimer spam_timer; + const F32 spam_frequency = 100.0F; + + if (spam_timer.getElapsedTimeF32() > spam_frequency) + { + spam_timer.reset(); - mPendingAttachments.clear(); + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), + cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); + for (S32 i=0; igetType() == LLAssetType::AT_OBJECT) + { + LL_DEBUGS("Avatar") << "item_id: " << inv_item->getUUID() + << " linked_item_id: " << inv_item->getLinkedUUID() + << " name: " << inv_item->getName() + << " parent: " << inv_item->getParentUUID() + << LL_ENDL; + } + } + } +#endif } diff --git a/indra/newview/llattachmentsmgr.h b/indra/newview/llattachmentsmgr.h index 997db59d22..84fb76bbea 100644 --- a/indra/newview/llattachmentsmgr.h +++ b/indra/newview/llattachmentsmgr.h @@ -32,45 +32,120 @@ class LLViewerInventoryItem; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//-------------------------------------------------------------------------------- // LLAttachmentsMgr // -// The sole purpose of this class is to take attachment -// requests, queue them up, and send them all at once. -// This handles situations where the viewer may request -// a bunch of attachments at once in a short period of -// time, where each of the requests would normally be -// sent as a separate message versus being batched into -// one single message. +// This class manages batching up of requests at two stages of +// attachment rezzing. // -// The intent of this batching is to reduce viewer->server -// traffic. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// First, attachments requested to rez get saved in +// mPendingAttachments and sent as a single +// RezMultipleAttachmentsFromInv request. This batching is needed +// mainly because of weaknessing the UI element->inventory item +// handling, such that we don't always know when we are requesting +// multiple items. Now they just pile up and get swept into a single +// request during the idle loop. +// +// Second, after attachments arrive, we need to generate COF links for +// them. There are both efficiency and UI correctness reasons why it +// is better to request all the COF links at once and run a single +// callback after they all complete. Given the vagaries of the +// attachment system, there is no guarantee that we will get all the +// attachments we ask for, but we frequently do. So in the common case +// that all the desired attachments arrive fairly quickly, we generate +// a single batched request for COF links. If attachments arrive late +// or not at all, we will still issue COF link requests once a timeout +// value has been exceeded. +// +// To handle attachments that never arrive, we forget about requests +// that exceed a timeout value. +//-------------------------------------------------------------------------------- class LLAttachmentsMgr: public LLSingleton { public: + // Stores info for attachments that will be requested during idle. + struct AttachmentsInfo + { + LLUUID mItemID; + U8 mAttachmentPt; + BOOL mAdd; + }; + typedef std::deque attachments_vec_t; + LLAttachmentsMgr(); virtual ~LLAttachmentsMgr(); - void addAttachment(const LLUUID& item_id, +// [RLVa:KB] - Checked: 2010-09-13 (RLVa-1.2.1) + void addAttachmentRequest(const LLUUID& item_id, const U8 attachment_pt, -// const BOOL add); -// [RLVa:KB] - Checked: 2010-09-13 (RLVa-1.2.1c) | Added: RLVa-1.2.1c const BOOL add, const BOOL fRlvForce = FALSE); // [/RLVa:KB] +// void addAttachmentRequest(const LLUUID& item_id, +// const U8 attachment_pt, +// const BOOL add); + void onAttachmentRequested(const LLUUID& item_id); + void requestAttachments(attachments_vec_t& attachment_requests); static void onIdle(void *); + + void onAttachmentArrived(const LLUUID& inv_item_id); + + void onDetachRequested(const LLUUID& inv_item_id); + void onDetachCompleted(const LLUUID& inv_item_id); + +// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-2.1) +public: + void clearPendingAttachmentLink(const LLUUID& idItem); + bool getPendingAttachments(uuid_set_t& ids) const; protected: - void onIdle(); + void onRegisterAttachmentComplete(const LLUUID& idAttachLink); + friend class LLRegisterAttachmentCallback; +// [/SL:KB] + private: - struct AttachmentsInfo + + class LLItemRequestTimes: public std::map { - LLUUID mItemID; - U8 mAttachmentPt; - BOOL mAdd; + public: + LLItemRequestTimes(const std::string& op_name, F32 timeout); + void addTime(const LLUUID& inv_item_id); + void removeTime(const LLUUID& inv_item_id); + BOOL wasRequestedRecently(const LLUUID& item_id) const; + BOOL getTime(const LLUUID& inv_item_id, LLTimer& timer) const; + + private: + F32 mTimeout; + std::string mOpName; }; - typedef std::vector attachments_vec_t; + void removeAttachmentRequestTime(const LLUUID& inv_item_id); + void onIdle(); + void requestPendingAttachments(); + void linkRecentlyArrivedAttachments(); + void expireOldAttachmentRequests(); + void expireOldDetachRequests(); +// void checkInvalidCOFLinks(); + void spamStatusInfo(); + + // Attachments that we are planning to rez but haven't requested from the server yet. attachments_vec_t mPendingAttachments; + + // Attachments that have been requested from server but have not arrived yet. + LLItemRequestTimes mAttachmentRequests; + + // Attachments that have been requested to detach but have not gone away yet. + LLItemRequestTimes mDetachRequests; + + // Attachments that have arrived but have not been linked in the COF yet. + uuid_set_t mRecentlyArrivedAttachments; + LLTimer mCOFLinkBatchTimer; + +// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-2.1) + // Attachments that have pending link creation + uuid_set_t mPendingAttachLinks; +// [/SL:KB] + +// // Attachments that are linked in the COF but may be invalid. +// LLItemRequestTimes mQuestionableCOFLinks; }; #endif diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 5062fe9eb3..3685ce21b9 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -162,9 +162,7 @@ void LLAvatarActions::offerTeleport(const LLUUID& invitee) if (invitee.isNull()) return; - std::vector ids; - ids.push_back(invitee); - offerTeleport(ids); + offerTeleport(uuid_vec_t{invitee}); } // static @@ -376,8 +374,8 @@ void LLAvatarActions::showProfile(const LLUUID& id, bool web) // static void LLAvatarActions::showProfiles(const uuid_vec_t& ids, bool web) { - for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) - showProfile(*it, web); + for (const auto& id : ids) + showProfile(id, web); } //static @@ -546,20 +544,12 @@ void LLAvatarActions::csr(const LLUUID& id) if (!gCacheName->getFullName(id, name)) return; std::string url = "http://csr.lindenlab.com/agent/"; - - // slow and stupid, but it's late - S32 len = name.length(); - for (S32 i = 0; i < len; i++) + if (char* output = curl_easy_escape(nullptr, name.c_str(), name.length())) { - if (name[i] == ' ') - { - url += "%20"; - } - else - { - url += name[i]; - } + name = output; + curl_free(output); } + url += name; LLWeb::loadURL(url); } @@ -572,7 +562,7 @@ void LLAvatarActions::share(const LLUUID& id) LLFloaterSidePanelContainer::showPanel("inventory", key); LLFloaterReg::showInstance("im_container"); */ - LLInventoryView::getActiveInventory()->setVisible(true); + LLPanelMainInventory::getActiveInventory()->setVisible(true); LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, id); @@ -624,25 +614,21 @@ namespace action_give_inventory static bool is_give_inventory_acceptable() { // check selection in the panel - const std::set inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); + const auto inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); if (inventory_selected_uuids.empty()) return false; // nothing selected bool acceptable = false; - std::set::const_iterator it = inventory_selected_uuids.begin(); - const std::set::const_iterator it_end = inventory_selected_uuids.end(); - for (; it != it_end; ++it) + for (const auto& id : inventory_selected_uuids) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); // any category can be offered. - if (inv_cat) + if (gInventory.getCategory(id)) { acceptable = true; continue; } - LLViewerInventoryItem* inv_item = gInventory.getItem(*it); // check if inventory item can be given - if (LLGiveInventory::isInventoryGiveAcceptable(inv_item)) + if (LLGiveInventory::isInventoryGiveAcceptable(gInventory.getItem(id))) { acceptable = true; continue; @@ -655,29 +641,23 @@ namespace action_give_inventory return acceptable; } - static void build_items_string(const std::set& inventory_selected_uuids , std::string& items_string) + static void build_items_string(const uuid_set_t& inventory_selected_uuids, std::string& items_string) { llassert(inventory_selected_uuids.size() > 0); const std::string& separator = LLTrans::getString("words_separator"); - for (std::set::const_iterator it = inventory_selected_uuids.begin(); ; ) + for (const auto& id : inventory_selected_uuids) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); - if (NULL != inv_cat) + if (!items_string.empty()) items_string.append(separator); + if (LLViewerInventoryCategory* inv_cat = gInventory.getCategory(id)) { items_string = inv_cat->getName(); break; } - LLViewerInventoryItem* inv_item = gInventory.getItem(*it); - if (NULL != inv_item) + else if (LLViewerInventoryItem* inv_item = gInventory.getItem(id)) { items_string.append(inv_item->getName()); } - if(++it == inventory_selected_uuids.end()) - { - break; - } - items_string.append(separator); } } @@ -696,14 +676,14 @@ namespace action_give_inventory return; } - const std::set inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); + const auto inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); if (inventory_selected_uuids.empty()) { return; } S32 count = LLShareInfo::instance().mAvatarNames.size(); - bool shared = count && !inventory_selected_uuids.empty(); + bool shared = count; // iterate through avatars for(S32 i = 0; i < count; ++i) @@ -713,17 +693,13 @@ namespace action_give_inventory // We souldn't open IM session, just calculate session ID for logging purpose. See EXT-6710 const LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, avatar_uuid); - std::set::const_iterator it = inventory_selected_uuids.begin(); - const std::set::const_iterator it_end = inventory_selected_uuids.end(); - const std::string& separator = LLTrans::getString("words_separator"); std::string noncopy_item_names; LLSD noncopy_items = LLSD::emptyArray(); // iterate through selected inventory objects - for (; it != it_end; ++it) + for (const auto& id : inventory_selected_uuids) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); - if (inv_cat) + if (LLViewerInventoryCategory* inv_cat = gInventory.getCategory(id)) { if (!LLGiveInventory::doGiveInventoryCategory(avatar_uuid, inv_cat, session_id, "ItemsShared")) { @@ -731,7 +707,7 @@ namespace action_give_inventory } break; } - LLViewerInventoryItem* inv_item = gInventory.getItem(*it); + LLViewerInventoryItem* inv_item = gInventory.getItem(id); if (!inv_item->getPermissions().allowCopyBy(gAgentID)) { if (!noncopy_item_names.empty()) @@ -739,7 +715,7 @@ namespace action_give_inventory noncopy_item_names.append(separator); } noncopy_item_names.append(inv_item->getName()); - noncopy_items.append(*it); + noncopy_items.append(id); } else { @@ -783,7 +759,7 @@ namespace action_give_inventory { llassert(avatar_names.size() == avatar_uuids.size()); - const std::set inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); + const auto inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); if (inventory_selected_uuids.empty()) { return; @@ -795,23 +771,21 @@ namespace action_give_inventory std::string items; build_items_string(inventory_selected_uuids, items); - int folders_count = 0; - std::set::const_iterator it = inventory_selected_uuids.begin(); - + auto folders_count = 0; //traverse through selected inventory items and count folders among them - for ( ; it != inventory_selected_uuids.end() && folders_count <=1 ; ++it) + for (const auto& id : inventory_selected_uuids) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); - if (NULL != inv_cat) + if (gInventory.getCategory(id)) { - folders_count++; + if (++folders_count == 2) + break; } } // EXP-1599 // In case of sharing multiple folders, make the confirmation // dialog contain a warning that only one folder can be shared at a time. - std::string notification = (folders_count > 1) ? "ShareFolderConfirmation" : "ShareItemsConfirmation"; + std::string notification = folders_count == 2 ? "ShareFolderConfirmation" : "ShareItemsConfirmation"; LLSD substitutions; substitutions["RESIDENTS"] = residents; substitutions["ITEMS"] = items; @@ -862,10 +836,10 @@ void LLAvatarActions::buildResidentsString(const uuid_vec_t& avatar_uuids, std:: } //static -std::set LLAvatarActions::getInventorySelectedUUIDs() +uuid_set_t LLAvatarActions::getInventorySelectedUUIDs() { LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel(); - return active_panel ? active_panel->getRootFolder()->getSelectionList() : std::set(); + return active_panel ? active_panel->getRootFolder()->getSelectionList() : uuid_set_t(); /*std::set inventory_selected; LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel(); @@ -883,8 +857,8 @@ std::set LLAvatarActions::getInventorySelectedUUIDs() } } - std::set inventory_selected_uuids; - for (std::set::iterator it = inventory_selected.begin(), end_it = inventory_selected.end(); + uuid_set_t inventory_selected_uuids; + for (auto it = inventory_selected.begin(), end_it = inventory_selected.end(); it != end_it; ++it) { @@ -935,16 +909,13 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL { return false; } - const std::set inventory_selected = root_folder->getSelectionList(); + const auto inventory_selected = root_folder->getSelectionList(); if (inventory_selected.empty()) return false; // nothing selected bool can_share = true; const LLUUID& trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); // - std::set::const_iterator it = inventory_selected.begin(); - const std::set::const_iterator it_end = inventory_selected.end(); - for (; it != it_end; ++it) + for (const auto& id : inventory_selected) { - const LLUUID id(*it); LLViewerInventoryCategory* inv_cat = gInventory.getCategory(id); // any category can be offered. if (inv_cat && !gInventory.isObjectDescendentOf(inv_cat->getUUID(), trash_id)) // @@ -1226,7 +1197,7 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri calling_card_folder_id); LLSD args; - args["TO_NAME"] = target_name; + args["TO_NAME"] = getSLURL(target_id); LLSD payload; payload["from_id"] = target_id; @@ -1274,23 +1245,32 @@ bool LLAvatarActions::isAgentMappable(const LLUUID& agent_id) ); } -// static -void LLAvatarActions::copyUUIDs(const uuid_vec_t& ids) +void copy_from_ids(const uuid_vec_t& ids, std::function func) { std::string ids_string; const std::string& separator = LLTrans::getString("words_separator"); - for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) + for (const auto& id : ids) { - const LLUUID& id = *it; if (id.isNull()) continue; if (!ids_string.empty()) ids_string.append(separator); - ids_string.append(id.asString()); + ids_string.append(func(id)); } if (!ids_string.empty()) gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(ids_string)); } + +// static +void LLAvatarActions::copyUUIDs(const uuid_vec_t& ids) +{ + copy_from_ids(ids, [](const LLUUID& id) { return id.asString(); }); +} + +std::string LLAvatarActions::getSLURL(const LLUUID& id) +{ + return llformat("secondlife:///app/agent/%s/about", id.asString().c_str()); +} diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 57e1ddd179..9f75e793ff 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -27,6 +27,8 @@ #ifndef LL_LLAVATARACTIONS_H #define LL_LLAVATARACTIONS_H +#include + class LLAvatarName; class LLInventoryPanel; class LLFloater; @@ -232,13 +234,18 @@ class LLAvatarActions */ static void buildResidentsString(const uuid_vec_t& avatar_uuids, std::string& residents_string); - static std::set getInventorySelectedUUIDs(); + static uuid_set_t getInventorySelectedUUIDs(); /** * Copy the selected avatar's UUID to clipboard */ static void copyUUIDs(const uuid_vec_t& id); + /** + * @return slurl string from agent ID + */ + static std::string getSLURL(const LLUUID& id); + private: static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response); static bool handleRemove(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index 162fd05c45..64846dcd05 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -33,6 +33,14 @@ #include #include +// For Flags in AvatarPropertiesReply +constexpr U32 AVATAR_ALLOW_PUBLISH = 0x1 << 0; // whether profile is externally visible or not +constexpr U32 AVATAR_MATURE_PUBLISH = 0x1 << 1; // profile is "mature" +constexpr U32 AVATAR_IDENTIFIED = 0x1 << 2; // whether avatar has provided payment info +constexpr U32 AVATAR_TRANSACTED = 0x1 << 3; // whether avatar has actively used payment info +constexpr U32 AVATAR_ONLINE = 0x1 << 4; // the online status of this avatar, if known. +constexpr U32 AVATAR_AGEVERIFIED = 0x1 << 5; // whether avatar has been age-verified + /* *TODO Vadim: This needs some refactoring: - Remove EAvatarProcessorType in favor of separate observers, derived from a common parent (to get rid of void*). diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp new file mode 100644 index 0000000000..dd83d68abd --- /dev/null +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -0,0 +1,459 @@ +/** + * @file llavatarrenderinfoaccountant.cpp + * @author Dave Simmons + * @date 2013-02-28 + * @brief + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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 "llviewerprecompiledheaders.h" +// associated header +#include "llavatarrenderinfoaccountant.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llcharacter.h" +#include "llhttpclient.h" +#include "lltimer.h" +#include "llviewercontrol.h" +#include "llviewermenu.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llvoavatar.h" +#include "llworld.h" + + +static const std::string KEY_AGENTS = "agents"; // map +static const std::string KEY_WEIGHT = "weight"; // integer +static const std::string KEY_TOO_COMPLEX = "tooComplex"; // bool +static const std::string KEY_OVER_COMPLEXITY_LIMIT = "overlimit"; // integer +static const std::string KEY_REPORTING_COMPLEXITY_LIMIT = "reportinglimit"; // integer + +static const std::string KEY_IDENTIFIER = "identifier"; +static const std::string KEY_MESSAGE = "message"; +static const std::string KEY_ERROR = "error"; + + +static const F32 SECS_BETWEEN_REGION_SCANS = 5.f; // Scan the region list every 5 seconds +static const F32 SECS_BETWEEN_REGION_REQUEST = 15.0; // Look for new avs every 15 seconds +static const F32 SECS_BETWEEN_REGION_REPORTS = 60.0; // Update each region every 60 seconds + +// Send data updates about once per minute, only need per-frame resolution +LLFrameTimer LLAvatarRenderInfoAccountant::sRenderInfoReportTimer; + + +// HTTP responder class for GET request for avatar render weight information +class LLAvatarRenderInfoGetResponder : public LLHTTPClient::ResponderWithResult +{ +public: + LLAvatarRenderInfoGetResponder(U64 region_handle) : mRegionHandle(region_handle) + { + } + + virtual void httpFailure(); + + virtual void httpSuccess(); + /*virtual*/ char const* getName() const { return "This is dumb."; } + +private: + U64 mRegionHandle; +}; + + +void LLAvatarRenderInfoGetResponder::httpFailure() +{ + const S32 statusNum = getStatus(); + const std::string& reason = getReason(); + LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if (regionp) + { + LL_WARNS() << "HTTP error result for avatar weight GET: " << statusNum + << ", " << reason + << " returned by region " << regionp->getName() + << LL_ENDL; + } + else + { + LL_WARNS() << "Avatar render weight GET error recieved but region not found for " + << mRegionHandle + << ", error " << statusNum + << ", " << reason + << LL_ENDL; + } +} + + +void LLAvatarRenderInfoGetResponder::httpSuccess() +{ + LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if (!regionp) + { + LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight info received but region not found for " + << mRegionHandle << LL_ENDL; + return; + } + + if (LLAvatarRenderInfoAccountant::logRenderInfo()) + { + LL_INFOS() << "LRI: Result for avatar weights request for region " << regionp->getName() << ":" << LL_ENDL; + } + + const LLSD& result = getContent(); + if (result.isMap()) + { + if (result.has(KEY_AGENTS)) + { + const LLSD & agents = result[KEY_AGENTS]; + if (agents.isMap()) + { + for (LLSD::map_const_iterator agent_iter = agents.beginMap(); + agent_iter != agents.endMap(); + agent_iter++ + ) + { + LLUUID target_agent_id = LLUUID(agent_iter->first); + LLVOAvatar* avatarp = gObjectList.findAvatar(target_agent_id); + if (avatarp && + !avatarp->isControlAvatar() && + avatarp->isAvatar()) + + { + const LLSD & agent_info_map = agent_iter->second; + if (agent_info_map.isMap()) + { + // Extract the data for this avatar + if (LLAvatarRenderInfoAccountant::logRenderInfo()) + { + LL_INFOS() << "LRI: Agent " << target_agent_id + << ": " << agent_info_map << LL_ENDL; + } + if (agent_info_map.has(KEY_WEIGHT)) + { + avatarp->setReportedVisualComplexity(agent_info_map[KEY_WEIGHT].asInteger()); + } + } + else + { + LL_WARNS("AvatarRenderInfo") << "agent entry invalid" + << " agent " << target_agent_id + << " map " << agent_info_map + << LL_ENDL; + } + } + else + { + LL_DEBUGS("AvatarRenderInfo") << "Unknown agent " << target_agent_id << LL_ENDL; + } + } + } + else + { + LL_WARNS("AvatarRenderInfo") << "malformed get response '" << KEY_AGENTS << "' is not map" << LL_ENDL; + } + } + else + { + LL_INFOS("AvatarRenderInfo") << "no '" << KEY_AGENTS << "' key in get response" << LL_ENDL; + } + + if (result.has(KEY_REPORTING_COMPLEXITY_LIMIT) + && result.has(KEY_OVER_COMPLEXITY_LIMIT)) + { + U32 reporting = result[KEY_REPORTING_COMPLEXITY_LIMIT].asInteger(); + U32 overlimit = result[KEY_OVER_COMPLEXITY_LIMIT].asInteger(); + + LL_DEBUGS("AvatarRenderInfo") << "complexity limit: " << reporting << " reporting, " << overlimit << " over limit" << LL_ENDL; + } + if (result.has(KEY_ERROR)) + { + const LLSD & error = result[KEY_ERROR]; + LL_WARNS() << "Avatar render info GET error: " + << error[KEY_IDENTIFIER] + << ": " << error[KEY_MESSAGE] + << " from region " << regionp->getName() + << LL_ENDL; + } + } +} + + +// HTTP responder class for POST request for avatar render weight information +class LLAvatarRenderInfoPostResponder : public LLHTTPClient::ResponderWithResult +{ +public: + LLAvatarRenderInfoPostResponder(U64 region_handle) : mRegionHandle(region_handle) + { + } + + virtual void httpFailure(); + + virtual void httpSuccess(); + /*virtual*/ char const* getName() const { return "This is also dumb."; } + +private: + U64 mRegionHandle; +}; + + +// static +// Send request for one region, no timer checks +void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regionp) +{ + std::string url = regionp->getCapability("AvatarRenderInfo"); + if (!url.empty()) + { + if (logRenderInfo()) + { + LL_INFOS() << "LRI: Sending avatar render info to region " + << regionp->getName() + << " from " << url + << LL_ENDL; + } + + U32 num_avs = 0; + // Build the render info to POST to the region + LLSD agents = LLSD::emptyMap(); + + std::vector::iterator iter = LLCharacter::sInstances.begin(); + while( iter != LLCharacter::sInstances.end() ) + { + LLVOAvatar* avatar = dynamic_cast(*iter); + if (avatar && + avatar->getRezzedStatus() >= 2 && // Mostly rezzed (maybe without baked textures downloaded) + !avatar->isDead() && // Not dead yet + !avatar->isControlAvatar() && // Not part of an animated object + avatar->getObjectHost() == regionp->getHost()) // Ensure it's on the same region + { + avatar->calculateUpdateRenderComplexity(); // Make sure the numbers are up-to-date + + LLSD info = LLSD::emptyMap(); + U32 avatar_complexity = avatar->getVisualComplexity(); + if (avatar_complexity > 0) + { + // the weight/complexity is unsigned, but LLSD only stores signed integers, + // so if it's over that (which would be ridiculously high), just store the maximum signed int value + info[KEY_WEIGHT] = (S32)(avatar_complexity < S32_MAX ? avatar_complexity : S32_MAX); + info[KEY_TOO_COMPLEX] = LLSD::Boolean(avatar->isTooComplex()); + agents[avatar->getID().asString()] = info; + + if (logRenderInfo()) + { + LL_INFOS("AvatarRenderInfo") << "Sending avatar render info for " << avatar->getID() + << ": " << info << LL_ENDL; + } + num_avs++; + } + } + iter++; + } + + if (num_avs == 0) + return; // nothing to report + + LLSD report = LLSD::emptyMap(); + report[KEY_AGENTS] = agents; + if (agents.size() > 0) + { + LLHTTPClient::post(url, report, new LLAvatarRenderInfoPostResponder(regionp->getHandle())); + } + } +} + +void LLAvatarRenderInfoPostResponder::httpSuccess() +{ + LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if (!regionp) + { + LL_INFOS("AvatarRenderInfoAccountant") << "Avatar render weight POST result received but region not found for " + << mRegionHandle << LL_ENDL; + return; + } + const LLSD& result = getContent(); + if (result.isMap()) + { + if (result.has(KEY_ERROR)) + { + const LLSD & error = result[KEY_ERROR]; + LL_WARNS("AvatarRenderInfoAccountant") << "POST error: " + << error[KEY_IDENTIFIER] + << ": " << error[KEY_MESSAGE] + << " from region " << regionp->getName() + << LL_ENDL; + } + else + { + LL_DEBUGS("AvatarRenderInfoAccountant") + << "POST result for region " << regionp->getName() + << ": " << result + << LL_ENDL; + } + } + else + { + LL_WARNS("AvatarRenderInfoAccountant") << "Malformed POST response from region '" << regionp->getName() + << LL_ENDL; + } +} + +void LLAvatarRenderInfoPostResponder::httpFailure() +{ + const S32 statusNum = getStatus(); + const std::string& reason = getReason(); + LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if (regionp) + { + LL_WARNS() << "HTTP error result for avatar weight POST: " << statusNum + << ", " << reason + << " returned by region " << regionp->getName() + << LL_ENDL; + } + else + { + LL_WARNS() << "Avatar render weight POST error recieved but region not found for " + << mRegionHandle + << ", error " << statusNum + << ", " << reason + << LL_ENDL; + } +} + +// static +// Send request for one region, no timer checks +void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regionp) +{ + std::string url = regionp->getCapability("AvatarRenderInfo"); + if (!url.empty()) + { + if (logRenderInfo()) + { + LL_INFOS() << "LRI: Requesting avatar render info for region " + << regionp->getName() + << " from " << url + << LL_ENDL; + } + + // First send a request to get the latest data + LLHTTPClient::get(url, new LLAvatarRenderInfoGetResponder(regionp->getHandle())); + } +} + + +// static +// Called every frame - send render weight requests to every region +void LLAvatarRenderInfoAccountant::idle() +{ + if (sRenderInfoReportTimer.hasExpired()) + { + S32 num_avs = LLCharacter::sInstances.size(); + + if (logRenderInfo()) + { + LL_INFOS() << "LRI: Scanning all regions and checking for render info updates" + << LL_ENDL; + } + + // Check all regions and see if it's time to fetch/send data + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* regionp = *iter; + if (regionp && + regionp->isAlive() && + regionp->capabilitiesReceived() && // Region has capability URLs available + regionp->getRenderInfoRequestTimer().hasExpired()) // Time to make request + { + sendRenderInfoToRegion(regionp); + getRenderInfoFromRegion(regionp); + + // Reset this regions timer, moving to longer intervals if there are lots of avatars around + regionp->getRenderInfoRequestTimer().resetWithExpiry(SECS_BETWEEN_REGION_REQUEST + (2.f * num_avs)); + } + } + + // We scanned all the regions, reset the request timer. + sRenderInfoReportTimer.resetWithExpiry(SECS_BETWEEN_REGION_SCANS); + } + + /* Singu TODO: RenderAutoMuteFunctions + static LLCachedControl render_auto_mute_functions(gSavedSettings, "RenderAutoMuteFunctions", 0); + static U32 prev_render_auto_mute_functions = (U32) -1; + if (prev_render_auto_mute_functions != render_auto_mute_functions) + { + prev_render_auto_mute_functions = render_auto_mute_functions; + + // Adjust menus + BOOL show_items = (BOOL)(render_auto_mute_functions & 0x04); + gMenuAvatarOther->setItemVisible( std::string("Normal"), show_items); + gMenuAvatarOther->setItemVisible( std::string("Always use impostor"), show_items); + gMenuAvatarOther->setItemVisible( std::string("Never use impostor"), show_items); + gMenuAvatarOther->setItemVisible( std::string("Impostor seperator"), show_items); + + gMenuAttachmentOther->setItemVisible( std::string("Normal"), show_items); + gMenuAttachmentOther->setItemVisible( std::string("Always use impostor"), show_items); + gMenuAttachmentOther->setItemVisible( std::string("Never use impostor"), show_items); + gMenuAttachmentOther->setItemVisible( std::string("Impostor seperator"), show_items); + + if (!show_items) + { // Turning off visual muting + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { // Make sure all AVs have the setting cleared + LLVOAvatar* inst = (LLVOAvatar*) *iter; + inst->setCachedVisualMute(false); + } + } + }*/ +} + + +// static +// Make sRenderInfoReportTimer expire so the next call to idle() will scan and query a new region +// called via LLViewerRegion::setCapabilitiesReceived() boost signals when the capabilities +// are returned for a new LLViewerRegion, and is the earliest time to get render info +void LLAvatarRenderInfoAccountant::expireRenderInfoReportTimer(const LLUUID& region_id) +{ + if (logRenderInfo()) + { + LL_INFOS() << "LRI: Viewer has new region capabilities, clearing global render info timer" + << " and timer for region " << region_id + << LL_ENDL; + } + + // Reset the global timer so it will scan regions immediately + sRenderInfoReportTimer.reset(); + + LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id); + if (regionp) + { // Reset the region's timer so it will request data immediately + regionp->getRenderInfoRequestTimer().reset(); + } +} + +// static +bool LLAvatarRenderInfoAccountant::logRenderInfo() +{ + static LLCachedControl render_mute_logging_enabled(gSavedSettings, "RenderAutoMuteLogging", false); + return render_mute_logging_enabled; +} diff --git a/indra/newview/llavatarrenderinfoaccountant.h b/indra/newview/llavatarrenderinfoaccountant.h new file mode 100644 index 0000000000..d68f2dccfb --- /dev/null +++ b/indra/newview/llavatarrenderinfoaccountant.h @@ -0,0 +1,56 @@ +/** + * @file llavatarrenderinfoaccountant.h + * @author Dave Simmons + * @date 2013-02-28 + * @brief + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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$ + */ + +#if ! defined(LL_llavatarrenderinfoaccountant_H) +#define LL_llavatarrenderinfoaccountant_H + +class LLViewerRegion; + +// Class to gather avatar rendering information +// that is sent to or fetched from regions. +class LLAvatarRenderInfoAccountant +{ +public: + LLAvatarRenderInfoAccountant() {}; + ~LLAvatarRenderInfoAccountant() {}; + + static void sendRenderInfoToRegion(LLViewerRegion * regionp); + static void getRenderInfoFromRegion(LLViewerRegion * regionp); + + static void expireRenderInfoReportTimer(const LLUUID& region_id); + + static void idle(); + + static bool logRenderInfo(); + +private: + // Send data updates about once per minute, only need per-frame resolution + static LLFrameTimer sRenderInfoReportTimer; +}; + +#endif /* ! defined(LL_llavatarrenderinfoaccountant_H) */ diff --git a/indra/newview/llbox.cpp b/indra/newview/llbox.cpp index f8c0afdfda..a72c966c75 100644 --- a/indra/newview/llbox.cpp +++ b/indra/newview/llbox.cpp @@ -82,16 +82,16 @@ void LLBox::renderface(S32 which_face) {7, 4, 0, 3} }; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); //gGL.normal3fv(&normals[which_face][0]); - gGL.texCoord2f(1,0); - gGL.vertex3fv(&mVertex[ faces[which_face][0] ][0]); - gGL.texCoord2f(1,1); - gGL.vertex3fv(&mVertex[ faces[which_face][1] ][0]); gGL.texCoord2f(0,1); - gGL.vertex3fv(&mVertex[ faces[which_face][2] ][0]); + gGL.vertex3fv(&mVertex[ faces[which_face][2]][0]); gGL.texCoord2f(0,0); - gGL.vertex3fv(&mVertex[ faces[which_face][3] ][0]); + gGL.vertex3fv(&mVertex[ faces[which_face][3]][0]); + gGL.texCoord2f(1, 1); + gGL.vertex3fv(&mVertex[faces[which_face][1]][0]); + gGL.texCoord2f(1, 0); + gGL.vertex3fv(&mVertex[faces[which_face][0]][0]); gGL.end(); } diff --git a/indra/newview/llcallbacklist.cpp b/indra/newview/llcallbacklist.cpp index 59ecbdd0ea..cdc664381d 100644 --- a/indra/newview/llcallbacklist.cpp +++ b/indra/newview/llcallbacklist.cpp @@ -70,7 +70,7 @@ void LLCallbackList::addFunction( callback_t func, void *data) } -BOOL LLCallbackList::containsFunction( callback_t func, void *data) +bool LLCallbackList::containsFunction( callback_t func, void *data) { callback_pair_t t(func, data); callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t); @@ -85,7 +85,7 @@ BOOL LLCallbackList::containsFunction( callback_t func, void *data) } -BOOL LLCallbackList::deleteFunction( callback_t func, void *data) +bool LLCallbackList::deleteFunction( callback_t func, void *data) { callback_pair_t t(func, data); callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t); diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index b85cd8fad2..cfe688689d 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -745,17 +745,19 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, // Use display name only because this user is your friend LLSD args; args["NAME"] = av_name.getNSName(friend_name_system()); + args["ID"] = agent_id; args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus"); // Popup a notify box with online status of this agent LLNotificationPtr notification; - if (online) + static const LLCachedControl behavior(gSavedSettings, "LiruOnlineNotificationBehavior", 1); + if (online && behavior) { notification = LLNotifications::instance().add("FriendOnlineOffline", args, payload, - boost::bind(&LLAvatarActions::startIM, agent_id)); + behavior == 1 ? boost::bind(&LLAvatarActions::startIM, agent_id) : (LLNotificationResponder)boost::bind(LLAvatarActions::showProfile, agent_id, false)); } else { diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h index 104b5122ca..9d4948783a 100644 --- a/indra/newview/llcallingcard.h +++ b/indra/newview/llcallingcard.h @@ -165,7 +165,7 @@ class LLAvatarTracker */ void addChangedMask(U32 mask, const LLUUID& referent); - const std::set& getChangedIDs() { return mChangedBuddyIDs; } + const uuid_set_t& getChangedIDs() { return mChangedBuddyIDs; } // Apply the functor to every buddy. Do not actually modify the // buddy list in the functor or bad things will happen. @@ -201,7 +201,7 @@ class LLAvatarTracker buddy_map_t mBuddyInfo; - typedef std::set changed_buddy_t; + typedef uuid_set_t changed_buddy_t; changed_buddy_t mChangedBuddyIDs; typedef std::vector observer_list_t; @@ -229,7 +229,7 @@ class LLCollectProxyBuddies : public LLRelationshipFunctor LLCollectProxyBuddies() {} virtual ~LLCollectProxyBuddies() {} virtual bool operator()(const LLUUID& buddy_id, LLRelationship* buddy); - typedef std::set buddy_list_t; + typedef uuid_set_t buddy_list_t; buddy_list_t mProxy; }; diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 32323b8f59..7949571078 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -72,6 +72,8 @@ #include "chatbar_as_cmdline.h" // [RLVa:KB] +#include "rlvcommon.h" +#include "rlvactions.h" #include "rlvhandler.h" // [/RLVa:KB] @@ -100,25 +102,24 @@ class LLChatBarGestureObserver : public LLGestureManagerObserver { public: LLChatBarGestureObserver(LLChatBar* chat_barp) : mChatBar(chat_barp){} - virtual ~LLChatBarGestureObserver() {} - virtual void changed() { mChatBar->refreshGestures(); } + virtual ~LLChatBarGestureObserver() = default; + void changed() override { mChatBar->refreshGestures(); } private: LLChatBar* mChatBar; }; - // // Functions // LLChatBar::LLChatBar() : LLPanel(), - mInputEditor(NULL), + mInputEditor(nullptr), mGestureLabelTimer(), mLastSpecialChatChannel(0), mIsBuilt(FALSE), - mGestureCombo(NULL), - mObserver(NULL) + mGestureCombo(nullptr), + mObserver(nullptr) { setIsChrome(TRUE); @@ -132,10 +133,14 @@ LLChatBar::~LLChatBar() { LLGestureMgr::instance().removeObserver(mObserver); delete mObserver; - mObserver = NULL; + mObserver = nullptr; // LLView destructor cleans up children } +//----------------------------------------------------------------------- +// Overrides +//----------------------------------------------------------------------- + BOOL LLChatBar::postBuild() { if (LLUICtrl* history_ctrl = findChild("History")) @@ -189,7 +194,7 @@ BOOL LLChatBar::handleKeyHere( KEY key, MASK mask ) else if (mask == MASK_SHIFT) { // whisper - sendChat( CHAT_TYPE_WHISPER ); + sendChat(CHAT_TYPE_WHISPER); handled = TRUE; } else if (mask == MASK_NONE) @@ -210,6 +215,11 @@ BOOL LLChatBar::handleKeyHere( KEY key, MASK mask ) return handled; } +void LLChatBar::onFocusLost() +{ + //stopChat(); +} + void LLChatBar::refresh() { // HACK: Leave the name of the gesture in place for a few seconds. @@ -242,17 +252,16 @@ void LLChatBar::refreshGestures() //store current selection so we can maintain it std::string cur_gesture = mGestureCombo->getValue().asString(); mGestureCombo->selectFirstItem(); - std::string label = mGestureCombo->getValue().asString();; + // clear mGestureCombo->clearRows(); // collect list of unique gestures std::map unique; - LLGestureMgr::item_map_t::const_iterator it; const LLGestureMgr::item_map_t& active_gestures = LLGestureMgr::instance().getActiveGestures(); - for (it = active_gestures.begin(); it != active_gestures.end(); ++it) + for (const auto& active_gesture : active_gestures) { - LLMultiGesture* gesture = (*it).second; + LLMultiGesture* gesture = active_gesture.second; if (gesture) { if (!gesture->mTrigger.empty()) @@ -262,11 +271,9 @@ void LLChatBar::refreshGestures() } } - // add unique gestures - std::map ::iterator it2; - for (it2 = unique.begin(); it2 != unique.end(); ++it2) + for (auto& it2 : unique) { - mGestureCombo->addSimpleElement((*it2).first); + mGestureCombo->addSimpleElement(it2.first); } mGestureCombo->sortByName(); @@ -316,12 +323,12 @@ void LLChatBar::setIgnoreArrowKeys(BOOL b) } } -BOOL LLChatBar::inputEditorHasFocus() +BOOL LLChatBar::inputEditorHasFocus() const { return mInputEditor && mInputEditor->hasFocus(); } -std::string LLChatBar::getCurrentChat() +std::string LLChatBar::getCurrentChat() const { return mInputEditor ? mInputEditor->getText() : LLStringUtil::null; } @@ -390,7 +397,7 @@ LLWString LLChatBar::stripChannelNumber(const LLWString &mesg, S32* channel) pos++; } - mLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10); + mLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), nullptr, 10); // if(mesg[1] == '-') mLastSpecialChatChannel = -mLastSpecialChatChannel; @@ -524,17 +531,24 @@ void LLChatBar::sendChat( EChatType type ) // static void LLChatBar::startChat(const char* line) { + if (!gChatBar || !gChatBar->getParent()) + { + return; + } gChatBar->getParent()->setVisible(TRUE); gChatBar->setKeyboardFocus(TRUE); gSavedSettings.setBOOL("ChatVisible", TRUE); - if (line && gChatBar->mInputEditor) + if (gChatBar->mInputEditor) { - std::string line_string(line); - gChatBar->mInputEditor->setText(line_string); + if (line) + { + std::string line_string(line); + gChatBar->mInputEditor->setText(line_string); + } + // always move cursor to end so users don't obliterate chat when accidentally hitting WASD + gChatBar->mInputEditor->setCursorToEnd(); } - // always move cursor to end so users don't obliterate chat when accidentally hitting WASD - gChatBar->mInputEditor->setCursorToEnd(); } @@ -543,7 +557,8 @@ void LLChatBar::startChat(const char* line) void LLChatBar::stopChat() { // In simple UI mode, we never release focus from the chat bar - gChatBar->setKeyboardFocus(FALSE); + if (gChatBar) + gChatBar->setKeyboardFocus(FALSE); // If we typed a movement key and pressed return during the // same frame, the keyboard handlers will see the key as having @@ -555,7 +570,8 @@ void LLChatBar::stopChat() gAgent.stopTyping(); // hide chat bar so it doesn't grab focus back - gChatBar->getParent()->setVisible(FALSE); + if (gChatBar && gChatBar->getParent()) + gChatBar->getParent()->setVisible(FALSE); gSavedSettings.setBOOL("ChatVisible", FALSE); } @@ -570,9 +586,12 @@ void LLChatBar::onInputEditorKeystroke() S32 length = raw_text.length(); - //if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences -// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) - if ( (length > 0) && (raw_text[0] != '/') && (!gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT)) ) +// if( (length > 0) +// && (raw_text[0] != '/') // forward slash is used for escape (eg. emote) sequences +// && (raw_text[0] != ':') // colon is used in for MUD poses +// ) +// [RLVa:KB] - Checked: 2010-03-26 (RLVa-1.2.0b) | Modified: RLVa-1.0.0d + if ( (length > 0) && (raw_text[0] != '/') && (raw_text[0] != ':') && (!RlvActions::hasBehaviour(RLV_BHVR_REDIRCHAT)) ) // [/RLVa:KB] { gAgent.startTyping(); @@ -582,21 +601,6 @@ void LLChatBar::onInputEditorKeystroke() gAgent.stopTyping(); } - /* Doesn't work -- can't tell the difference between a backspace - that killed the selection vs. backspace at the end of line. - if (length > 1 - && text[0] == '/' - && key == KEY_BACKSPACE) - { - // the selection will already be deleted, but we need to trim - // off the character before - std::string new_text = raw_text.substr(0, length-1); - mInputEditor->setText( new_text ); - mInputEditor->setCursorToEnd(); - length = length - 1; - } - */ - KEY key = gKeyboard->currentKey(); // Ignore "special" keys, like backspace, arrows, etc. @@ -622,11 +626,6 @@ void LLChatBar::onInputEditorKeystroke() mInputEditor->setSelection(length, outlength); } } - - //LL_INFOS() << "GESTUREDEBUG " << trigger - // << " len " << length - // << " outlen " << out_str.getLength() - // << LL_ENDL; } } @@ -668,11 +667,11 @@ void LLChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) { // Look for "/20 foo" channel chats. - S32 channel = 0; + S32 channel = gSavedSettings.getS32("AlchemyNearbyChatChannel"); LLWString out_text = stripChannelNumber(wtext, &channel); std::string utf8_out_text = wstring_to_utf8str(out_text); - std::string utf8_text = wstring_to_utf8str(wtext); + utf8_text = utf8str_trim(utf8_text); if (!utf8_text.empty()) { @@ -680,17 +679,12 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL } // [RLVa:KB] - Checked: 2010-03-27 (RLVa-1.2.0b) | Modified: RLVa-1.2.0b - if ( (0 == channel) && (rlv_handler_t::isEnabled()) ) + // RELEASE-RLVa: [SL-2.0.0] This entire class appears to be dead/non-functional? + if ( (0 == channel) && (RlvActions::isRlvEnabled()) ) { // Adjust the (public) chat "volume" on chat and gestures (also takes care of playing the proper animation) - if ( ((CHAT_TYPE_SHOUT == type) || (CHAT_TYPE_NORMAL == type)) && (gRlvHandler.hasBehaviour(RLV_BHVR_CHATNORMAL)) ) - type = CHAT_TYPE_WHISPER; - else if ( (CHAT_TYPE_SHOUT == type) && (gRlvHandler.hasBehaviour(RLV_BHVR_CHATSHOUT)) ) - type = CHAT_TYPE_NORMAL; - else if ( (CHAT_TYPE_WHISPER == type) && (gRlvHandler.hasBehaviour(RLV_BHVR_CHATWHISPER)) ) - type = CHAT_TYPE_NORMAL; - - animate &= !gRlvHandler.hasBehaviour( (!RlvUtil::isEmote(utf8_text)) ? RLV_BHVR_REDIRCHAT : RLV_BHVR_REDIREMOTE ); + type = RlvActions::checkChatVolume(type); + animate &= !RlvActions::hasBehaviour( (!RlvUtil::isEmote(utf8_text)) ? RLV_BHVR_REDIRCHAT : RLV_BHVR_REDIREMOTE ); } // [/RLVa:KB] @@ -731,23 +725,19 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL send_chat_from_viewer(utf8_out_text, type, channel); } -// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.2a +//void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) +// [RLVa:KB] - Checked: 2010-02-27 (RLVa-1.2.0b) | Modified: RLVa-0.2.2a void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel) // [/RLVa:KB] { // [RLVa:KB] - Checked: 2010-02-27 (RLVa-1.2.0b) | Modified: RLVa-1.2.0a // Only process chat messages (ie not CHAT_TYPE_START, CHAT_TYPE_STOP, etc) - if ( (rlv_handler_t::isEnabled()) && ( (CHAT_TYPE_WHISPER == type) || (CHAT_TYPE_NORMAL == type) || (CHAT_TYPE_SHOUT == type) ) ) + if ( (RlvActions::isRlvEnabled()) && ( (CHAT_TYPE_WHISPER == type) || (CHAT_TYPE_NORMAL == type) || (CHAT_TYPE_SHOUT == type) ) ) { if (0 == channel) { - // (We already did this before, but LLChatHandler::handle() calls this directly) - if ( ((CHAT_TYPE_SHOUT == type) || (CHAT_TYPE_NORMAL == type)) && (gRlvHandler.hasBehaviour(RLV_BHVR_CHATNORMAL)) ) - type = CHAT_TYPE_WHISPER; - else if ( (CHAT_TYPE_SHOUT == type) && (gRlvHandler.hasBehaviour(RLV_BHVR_CHATSHOUT)) ) - type = CHAT_TYPE_NORMAL; - else if ( (CHAT_TYPE_WHISPER == type) && (gRlvHandler.hasBehaviour(RLV_BHVR_CHATWHISPER)) ) - type = CHAT_TYPE_NORMAL; + // Clamp the volume of the chat if needed + type = RlvActions::checkChatVolume(type); // Redirect chat if needed if ( ( (gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT) || (gRlvHandler.hasBehaviour(RLV_BHVR_REDIREMOTE)) ) && @@ -763,7 +753,7 @@ void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channe else { // Don't allow chat on a non-public channel if sendchannel restricted (unless the channel is an exception) - if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SENDCHANNEL)) && (!gRlvHandler.isException(RLV_BHVR_SENDCHANNEL, channel)) ) + if (!RlvActions::canSendChannel(channel)) return; // Don't allow chat on debug channel if @sendchat, @redirchat or @rediremote restricted (shows as public chat on viewers) @@ -836,33 +826,29 @@ void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channe void really_send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) { LLMessageSystem* msg = gMessageSystem; - // - if(channel >= 0) - { - // - msg->newMessageFast(_PREHASH_ChatFromViewer); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ChatData); - msg->addStringFast(_PREHASH_Message, utf8_out_text); - msg->addU8Fast(_PREHASH_Type, type); - msg->addS32("Channel", channel); - // + if (channel >= 0) + { + msg->newMessageFast(_PREHASH_ChatFromViewer); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ChatData); + msg->addStringFast(_PREHASH_Message, utf8_out_text); + msg->addU8Fast(_PREHASH_Type, type); + msg->addS32("Channel", channel); } else { - msg->newMessage("ScriptDialogReply"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("Data"); - msg->addUUID("ObjectID", gAgent.getID()); + msg->newMessageFast(_PREHASH_ScriptDialogReply); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Data); + msg->addUUIDFast(_PREHASH_ObjectID, gAgent.getID()); msg->addS32("ChatChannel", channel); - msg->addS32("ButtonIndex", 0); - msg->addString("ButtonLabel", utf8_out_text); + msg->addS32Fast(_PREHASH_ButtonIndex, 0); + msg->addStringFast(_PREHASH_ButtonLabel, utf8_out_text); } - // gAgent.sendReliableMessage(); LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); @@ -895,7 +881,7 @@ void LLChatBar::onCommitGesture(LLUICtrl* ctrl) } } mGestureLabelTimer.start(); - if (mGestureCombo != NULL) + if (mGestureCombo != nullptr) { // free focus back to chat bar mGestureCombo->setFocus(FALSE); @@ -907,24 +893,39 @@ void toggleChatHistory() LLFloaterChat::toggleInstance(LLSD()); } +// +// LLChatCommandHandler +// -class LLChatHandler : public LLCommandHandler +class LLChatCommandHandler final : public LLCommandHandler { public: // not allowed from outside the app - LLChatHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } + LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } // Your code here bool handle(const LLSD& tokens, const LLSD& query_map, - LLMediaCtrl* web) + LLMediaCtrl* web) override { - if (tokens.size() < 2) return false; - S32 channel = tokens[0].asInteger(); - std::string mesg = tokens[1].asString(); - send_chat_from_viewer(mesg, CHAT_TYPE_NORMAL, channel); - return true; + bool retval = false; + // Need at least 2 tokens to have a valid message. + if (tokens.size() < 2) + { + retval = false; + } + else + { + S32 channel = tokens[0].asInteger(); + { + retval = true; + // Send unescaped message, see EXT-6353. + std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); + send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); + } + } + return retval; } }; // Creating the object registers with the dispatcher. -LLChatHandler gChatHandler; +LLChatCommandHandler gChatHandler; diff --git a/indra/newview/llchatbar.h b/indra/newview/llchatbar.h index 71440d8bb4..656da51324 100644 --- a/indra/newview/llchatbar.h +++ b/indra/newview/llchatbar.h @@ -33,10 +33,9 @@ #ifndef LL_LLCHATBAR_H #define LL_LLCHATBAR_H -#include "llpanel.h" #include "llframetimer.h" #include "llchat.h" -#include "lllayoutstack.h" +#include "llpanel.h" class LLLineEditor; class LLMessageSystem; @@ -46,17 +45,19 @@ class LLFrameTimer; class LLChatBarGestureObserver; class LLComboBox; -class LLChatBar : public LLPanel + +class LLChatBar final +: public LLPanel { public: // constructor for inline chat-bars (e.g. hosted in chat history window) LLChatBar(); - ~LLChatBar(); - virtual BOOL postBuild(); - virtual BOOL handleKeyHere(KEY key, MASK mask); + BOOL postBuild() override; + BOOL handleKeyHere(KEY key, MASK mask) override; + void onFocusLost() override; - void refresh(); + void refresh() override; void refreshGestures(); // Move cursor into chat input field. @@ -65,8 +66,8 @@ class LLChatBar : public LLPanel // Ignore arrow keys for chat bar void setIgnoreArrowKeys(BOOL b); - BOOL inputEditorHasFocus(); - std::string getCurrentChat(); + BOOL inputEditorHasFocus() const; + std::string getCurrentChat() const; // since chat bar logic is reused for chat history // gesture combo box might not be a direct child @@ -94,10 +95,11 @@ class LLChatBar : public LLPanel static void stopChat(); protected: + ~LLChatBar(); + void sendChat(EChatType type); void updateChat(); -protected: LLLineEditor* mInputEditor; LLFrameTimer mGestureLabelTimer; diff --git a/indra/newview/llcloud.cpp b/indra/newview/llcloud.cpp index 062d190bea..0d38ecbb65 100644 --- a/indra/newview/llcloud.cpp +++ b/indra/newview/llcloud.cpp @@ -515,6 +515,10 @@ void LLCloudLayer::connectNeighbor(LLCloudLayer *cloudp, U32 direction) return; } + if (mNeighbors[direction]) + { + mNeighbors[direction]->mNeighbors[gDirOpposite[direction]] = NULL; + } mNeighbors[direction] = cloudp; if (cloudp) mNeighbors[direction]->mNeighbors[gDirOpposite[direction]] = this; diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 61fcd5d7be..3efba0c998 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -213,7 +213,7 @@ void LLColorSwatchCtrl::draw() { if (!mFallbackImageName.empty()) { - LLPointer fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE, + LLPointer fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if( fallback_image->getComponents() == 4 ) { diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index c50c328cc3..17a869e873 100644 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -181,12 +181,18 @@ class LLCLPValue : public po::value_semantic_codecvt_helper { mNotifyCallback(*value); } + } + virtual bool is_required(void) const + { + return mIsRequired; } - virtual bool is_required(void) const - { - return mIsRequired; - } + + virtual bool adjacent_tokens_only() const + { + return false; + } + protected: void xparse(boost::any& value_store, const std::vector& new_tokens) const @@ -287,19 +293,19 @@ bool LLCommandLineParser::parseAndStoreResults(po::command_line_parser& clp) po::basic_parsed_options opts = clp.run(); po::store(opts, gVariableMap); } - catch(po::error& e) + catch (const po::error& e) { LL_WARNS() << "Caught Error:" << e.what() << LL_ENDL; mErrorMsg = e.what(); return false; } - catch(LLCLPError& e) + catch (const LLCLPError& e) { LL_WARNS() << "Caught Error:" << e.what() << LL_ENDL; mErrorMsg = e.what(); return false; } - catch(LLCLPLastOption&) + catch (const LLCLPLastOption&) { // This exception means a token was read after an option // that must be the last option was reached (see url and slurl options) @@ -348,18 +354,58 @@ bool LLCommandLineParser::parseCommandLine(int argc, char **argv) return parseAndStoreResults(clp); } +// TODO: +// - Break out this funky parsing logic into separate method +// - Unit-test it with tests like LLStringUtil::getTokens() (the command-line +// overload that supports quoted tokens) +// - Unless this logic offers significant semantic benefits, replace it with +// LLStringUtil::getTokens(). This would fix a known bug: you cannot --set a +// string-valued variable to the empty string, because empty strings are +// eliminated below. + bool LLCommandLineParser::parseCommandLineString(const std::string& str) { + std::string cmd_line_string(""); + if (!str.empty()) + { + bool add_last_c = true; + S32 last_c_pos = str.size() - 1; //don't get out of bounds on pos+1, last char will be processed separately + for (S32 pos = 0; pos < last_c_pos; ++pos) + { + cmd_line_string.append(&str[pos], 1); + if (str[pos] == '\\') + { + cmd_line_string.append("\\", 1); + if (str[pos + 1] == '\\') + { + ++pos; + add_last_c = (pos != last_c_pos); + } + } + } + if (add_last_c) + { + cmd_line_string.append(&str[last_c_pos], 1); + if (str[last_c_pos] == '\\') + { + cmd_line_string.append("\\", 1); + } + } + } + // Split the string content into tokens - boost::escaped_list_separator sep("\\", "\r\n ", "\"'"); - boost::tokenizer< boost::escaped_list_separator > tok(str, sep); + const char* escape_chars = "\\"; + const char* separator_chars = "\r\n "; + const char* quote_chars = "\"'"; + boost::escaped_list_separator sep(escape_chars, separator_chars, quote_chars); + boost::tokenizer< boost::escaped_list_separator > tok(cmd_line_string, sep); std::vector tokens; // std::copy(tok.begin(), tok.end(), std::back_inserter(tokens)); for(boost::tokenizer< boost::escaped_list_separator >::iterator i = tok.begin(); i != tok.end(); ++i) { - if(0 != i->size()) + if(!i->empty()) { tokens.push_back(*i); } @@ -380,20 +426,28 @@ bool LLCommandLineParser::parseCommandLineFile(const std::basic_istream < char > void LLCommandLineParser::notify() { - po::notify(gVariableMap); + try + { + po::notify(gVariableMap); + } + catch (const LLCLPError& e) + { + LL_WARNS() << "Caught Error: " << e.what() << LL_ENDL; + mErrorMsg = e.what(); + } } void LLCommandLineParser::printOptions() const { - for(po::variables_map::iterator i = gVariableMap.begin(); i != gVariableMap.end(); ++i) + for (auto& i : gVariableMap) { - std::string name = i->first; - token_vector_t values = i->second.as(); + std::string name = i.first; + token_vector_t values = i.second.as(); std::ostringstream oss; oss << name << ": "; - for(token_vector_t::iterator t_itr = values.begin(); t_itr != values.end(); ++t_itr) + for (auto& value : values) { - oss << t_itr->c_str() << " "; + oss << value.c_str() << " "; } LL_INFOS() << oss.str() << LL_ENDL; } diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 81db452f8b..0e4a0168fd 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -50,13 +50,13 @@ #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" -//#include "lscript_rt_interface.h" #include "llviewercontrol.h" #include "llviewerobject.h" #include "llviewerregion.h" #include "llresmgr.h" #include "llbutton.h" +#include "llscrolllistctrl.h" #include "lldir.h" #include "llnotificationsutil.h" #include "llfloaterchat.h" @@ -65,6 +65,10 @@ #include "lltrans.h" #include "llselectmgr.h" +#include "llexperiencecache.h" + +// *TODO: This should be separated into the script queue, and the floater views of that queue. +// There should only be one floater class that can view any queue type ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs @@ -73,12 +77,12 @@ struct LLScriptQueueData { LLUUID mQueueID; - std::string mScriptName; + LLPointer mItemp; LLUUID mTaskId; - LLUUID mItemId; - LLScriptQueueData(const LLUUID& q_id, const std::string& name, const LLUUID& task_id, const LLUUID& item_id) : - mQueueID(q_id), mScriptName(name), mTaskId(task_id), mItemId(item_id) {} - + LLUUID mExperienceId; + LLHost mHost; + LLScriptQueueData(const LLUUID& q_id, const LLUUID& task_id, LLInventoryItem* item, const LLHost& host) : + mQueueID(q_id), mTaskId(task_id), mItemp(item), mHost(host) {} }; ///---------------------------------------------------------------------------- @@ -96,22 +100,20 @@ LLFloaterScriptQueue::LLFloaterScriptQueue(const std::string& name, const std::string& start_string) : LLFloater(name, rect, title, RESIZE_YES, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT, - DRAG_ON_TOP, MINIMIZE_YES, CLOSE_YES) + DRAG_ON_TOP, MINIMIZE_YES, CLOSE_YES), + mMessages(nullptr), + mCloseBtn(nullptr), + mDone(false), + mMono(false) { mID.generate(); LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_queue.xml"); - - childSetAction("close",onCloseBtn,this); - childSetEnabled("close",FALSE); - setTitle(title); LLRect curRect = getRect(); translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop); - mStartString = start_string; - mDone = FALSE; sInstances.addData(mID, this); } @@ -121,18 +123,20 @@ LLFloaterScriptQueue::~LLFloaterScriptQueue() sInstances.removeData(mID); } +BOOL LLFloaterScriptQueue::postBuild() +{ + childSetAction("close",onCloseBtn,this); + getChildView("close")->setEnabled(FALSE); + return TRUE; +} + // find an instance by ID. Return NULL if it does not exist. // static LLFloaterScriptQueue* LLFloaterScriptQueue::findInstance(const LLUUID& id) { - if(sInstances.checkData(id)) - { - return sInstances.getData(id); - } - return NULL; + return sInstances.checkData(id) ? sInstances.getData(id) : NULL; } - // This is the callback method for the viewer object currently being // worked on. // NOT static, virtual! @@ -188,7 +192,6 @@ void LLFloaterScriptQueue::addObject(const LLUUID& id) BOOL LLFloaterScriptQueue::start() { - //LL_INFOS() << "LLFloaterCompileQueue::start()" << LL_ENDL; std::string buffer; LLStringUtil::format_map_t args; @@ -198,7 +201,7 @@ BOOL LLFloaterScriptQueue::start() getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); - return nextObject(); + return startQueue(); } BOOL LLFloaterScriptQueue::isDone() const @@ -218,7 +221,7 @@ BOOL LLFloaterScriptQueue::nextObject() LL_INFOS() << "LLFloaterScriptQueue::nextObject() - " << count << " objects left to process." << LL_ENDL; mCurrentObjectID.setNull(); - if(count > 0) + if (count > 0) { successful_start = popNext(); } @@ -226,7 +229,7 @@ BOOL LLFloaterScriptQueue::nextObject() << (successful_start ? "successful" : "unsuccessful") << LL_ENDL; } while((mObjectIDs.size() > 0) && !successful_start); - if(isDone() && !mDone) + if (isDone() && !mDone) { mDone = true; getChild("queue output")->addSimpleElement(getString("Done"), ADD_BOTTOM); @@ -243,14 +246,14 @@ BOOL LLFloaterScriptQueue::popNext() // the inventory. BOOL rv = FALSE; S32 count = mObjectIDs.size(); - if(mCurrentObjectID.isNull() && (count > 0)) + if (mCurrentObjectID.isNull() && (count > 0)) { mCurrentObjectID = mObjectIDs.at(0); LL_INFOS() << "LLFloaterScriptQueue::popNext() - mCurrentID: " << mCurrentObjectID << LL_ENDL; mObjectIDs.erase(mObjectIDs.begin()); LLViewerObject* obj = gObjectList.findObject(mCurrentObjectID); - if(obj) + if (obj) { LL_INFOS() << "LLFloaterScriptQueue::popNext() requesting inv for " << mCurrentObjectID << LL_ENDL; @@ -263,6 +266,28 @@ BOOL LLFloaterScriptQueue::popNext() return rv; } +BOOL LLFloaterScriptQueue::startQueue() +{ + return nextObject(); +} + +class CompileQueueExperienceResponder final : public LLHTTPClient::ResponderWithResult +{ + const LLUUID mParent; +public: + CompileQueueExperienceResponder(const LLUUID& parent): mParent(parent) {} + + void httpSuccess() override { sendResult(getContent()); } + void httpFailure() override { sendResult(LLSD()); } + void sendResult(const LLSD& content) + { + if (auto queue = static_cast(LLFloaterCompileQueue::findInstance(mParent))) + queue->experienceIdsReceived(content["experience_ids"]); + } + char const* getName() const override { return "CompileQueueExperienceResponder"; } +}; + + ///---------------------------------------------------------------------------- /// Class LLFloaterCompileQueue @@ -280,7 +305,7 @@ class LLCompileFloaterUploadQueueSupplier : public LLAssetUploadQueueSupplier virtual LLAssetUploadQueue* get() const { LLFloaterCompileQueue* queue = (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId); - if(NULL == queue) + if (NULL == queue) { return NULL; } @@ -290,7 +315,7 @@ class LLCompileFloaterUploadQueueSupplier : public LLAssetUploadQueueSupplier virtual void log(std::string message) const { LLFloaterCompileQueue* queue = (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId); - if(NULL == queue) + if (NULL == queue) { return; } @@ -303,7 +328,7 @@ class LLCompileFloaterUploadQueueSupplier : public LLAssetUploadQueueSupplier }; // static -LLFloaterCompileQueue* LLFloaterCompileQueue::create(BOOL mono) +LLFloaterCompileQueue* LLFloaterCompileQueue::create(bool mono) { S32 left, top; gFloaterView->getNewFloaterPosition(&left, &top); @@ -312,7 +337,7 @@ LLFloaterCompileQueue* LLFloaterCompileQueue::create(BOOL mono) LLFloaterCompileQueue* new_queue = new LLFloaterCompileQueue("queue", rect); new_queue->mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(new_queue->getID())); - new_queue->mMono = mono; + new_queue->setMono(mono); new_queue->open(); return new_queue; } @@ -325,6 +350,21 @@ LLFloaterCompileQueue::~LLFloaterCompileQueue() { } +void LLFloaterCompileQueue::experienceIdsReceived(const LLSD& content) +{ + for(LLSD::array_const_iterator it = content.beginArray(); it != content.endArray(); ++it) + { + mExperienceIds.insert(it->asUUID()); + } + nextObject(); +} + +BOOL LLFloaterCompileQueue::hasExperience(const LLUUID& id) const +{ + return mExperienceIds.find(id) != mExperienceIds.end(); +} + + void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object, LLInventoryObject::object_list_t* inv) { @@ -338,7 +378,7 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object, LLInventoryObject::object_list_t::const_iterator end = inv->end(); for ( ; it != end; ++it) { - if((*it)->getType() == LLAssetType::AT_LSL_TEXT) + if ((*it)->getType() == LLAssetType::AT_LSL_TEXT) { LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); // Check permissions before allowing the user to retrieve data. @@ -359,31 +399,69 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object, } else { + LLViewerRegion* region = viewer_object->getRegion(); + std::string url = std::string(); + if (region) + { + url = region->getCapability("GetMetadata"); + } + + const auto& host = region->getHost(); + const auto& obj_id = viewer_object->getID(); // request all of the assets. - uuid_item_map::iterator iter; - for(iter = asset_item_map.begin(); iter != asset_item_map.end(); iter++) + for(const auto& pair : asset_item_map) { - LLInventoryItem *itemp = iter->second; + LLInventoryItem *itemp = pair.second; LLScriptQueueData* datap = new LLScriptQueueData(getID(), - itemp->getName(), - viewer_object->getID(), - itemp->getUUID()); - - //LL_INFOS() << "ITEM NAME 2: " << names.get(i) << LL_ENDL; - gAssetStorage->getInvItemAsset(viewer_object->getRegion()->getHost(), - gAgent.getID(), - gAgent.getSessionID(), - itemp->getPermissions().getOwner(), - viewer_object->getID(), - itemp->getUUID(), - itemp->getAssetUUID(), - itemp->getType(), - LLFloaterCompileQueue::scriptArrived, - (void*)datap); + obj_id, + itemp, + host); + + LLExperienceCache::instance().fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(), + boost::bind(LLFloaterCompileQueue::requestAsset, datap, _1)); + } + } +} + +void LLFloaterCompileQueue::requestAsset(LLScriptQueueData* datap, const LLSD& experience) +{ + LLFloaterCompileQueue* queue = static_cast(findInstance(datap->mQueueID)); + if (!queue) + { + delete datap; + return; + } + + if (experience.has(LLExperienceCache::EXPERIENCE_ID)) + { + datap->mExperienceId = experience[LLExperienceCache::EXPERIENCE_ID].asUUID(); + if (!queue->hasExperience(datap->mExperienceId)) + { + std::string buffer = LLTrans::getString("CompileNoExperiencePerm", LLSD::emptyMap() + .with("SCRIPT", datap->mItemp->getName()) + .with("EXPERIENCE", experience[LLExperienceCache::NAME].asString())); + + queue->getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); + queue->removeItemByItemID(datap->mItemp->getUUID()); + delete datap; + return; } } + + //LL_INFOS() << "ITEM NAME 2: " << names.get(i) << LL_ENDL; + gAssetStorage->getInvItemAsset(datap->mHost, + gAgent.getID(), + gAgent.getSessionID(), + datap->mItemp->getPermissions().getOwner(), + datap->mTaskId, + datap->mItemp->getUUID(), + datap->mItemp->getAssetUUID(), + datap->mItemp->getType(), + LLFloaterCompileQueue::scriptArrived, + (void*)datap); } + // This is the callback for when each script arrives // static void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, @@ -392,13 +470,16 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, { LL_INFOS() << "LLFloaterCompileQueue::scriptArrived()" << LL_ENDL; LLScriptQueueData* data = (LLScriptQueueData*)user_data; - if(!data) return; + if(!data) + { + return; + } LLFloaterCompileQueue* queue = static_cast (LLFloaterScriptQueue::findInstance(data->mQueueID)); std::string buffer; - if(queue && (0 == status)) + if (queue && (0 == status)) { - //LL_INFOS() << "ITEM NAME 3: " << data->mScriptName << LL_ENDL; + //LL_INFOS() << "ITEM NAME 3: " << data->mItemp->getName() << LL_ENDL; // Dump this into a file on the local disk so we can compile it. std::string filename; @@ -412,7 +493,7 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, if (object) { std::string url = object->getRegion()->getCapability("UpdateScriptTask"); - if(!url.empty()) + if (!url.empty()) { // Read script source in to buffer. U32 script_size = file.getSize(); @@ -420,166 +501,53 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, file.read(script_data, script_size); queue->mUploadQueue->queue(filename, data->mTaskId, - data->mItemId, is_running, queue->mMono, queue->getID(), - script_data, script_size, data->mScriptName); + data->mItemp->getUUID(), is_running, queue->mMono, queue->getID(), + script_data, script_size, data->mItemp->getName(), data->mExperienceId); } else { std::string text = LLTrans::getString("CompileQueueProblemUploading"); LLChat chat(text); LLFloaterChat::addChat(chat); - buffer = text + LLTrans::getString(":") + " " + data->mScriptName; + buffer = text + LLTrans::getString(":") + ' ' + data->mItemp->getName(); LL_WARNS() << "Problem uploading script asset." << LL_ENDL; - if(queue) queue->removeItemByItemID(data->mItemId); - } -#if 0 //Client side compiling disabled. - else - { - // It's now in the file, now compile it. - buffer = LLTrans::getString("CompileQueueDownloadedCompiling") + (": ") + data->mScriptName; - - // Write script to local file for compilation. - LLFILE *fp = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/ - if (fp) - { - const S32 buf_size = 65536; - U8 copy_buf[buf_size]; - - while (file.read(copy_buf, buf_size)) /*Flawfinder: ignore*/ - { - if (fwrite(copy_buf, file.getLastBytesRead(), 1, fp) < 1) - { - // return a bad file error if we can't write the whole thing - status = LL_ERR_CANNOT_OPEN_FILE; - } - } - - fclose(fp); - } - else - { - LL_ERRS() << "Unable to find object to compile" << LL_ENDL; - } - - // TODO: babbage: No compile if no cap. - queue->compile(filename, data->mItemId); - - // Delete it after we're done compiling? - LLFile::remove(filename); + if(queue) queue->removeItemByItemID(data->mItemp->getUUID()); } -#endif } } else { LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ) + if ( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ) { LLChat chat(LLTrans::getString("CompileQueueScriptNotFound")); LLFloaterChat::addChat(chat); - buffer = LLTrans::getString("CompileQueueProblemDownloading") + LLTrans::getString(":") + " " + data->mScriptName; + buffer = LLTrans::getString("CompileQueueProblemDownloading") + LLTrans::getString(":") + ' ' + data->mItemp->getName(); } else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) { LLChat chat(LLTrans::getString("CompileQueueInsufficientPermDownload")); LLFloaterChat::addChat(chat); - buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + LLTrans::getString(":") + " " + data->mScriptName; + buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + LLTrans::getString(":") + ' ' + data->mItemp->getName(); } else { - buffer = LLTrans::getString("CompileQueueUnknownFailure") + (" ") + data->mScriptName; + buffer = LLTrans::getString("CompileQueueUnknownFailure") + ' ' + data->mItemp->getName(); } LL_WARNS() << "Problem downloading script asset." << LL_ENDL; - if(queue) queue->removeItemByItemID(data->mItemId); + if(queue) queue->removeItemByItemID(data->mItemp->getUUID()); } - if(queue && (buffer.size() > 0)) + if (queue && (buffer.size() > 0)) { queue->getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); } delete data; } -#if 0 //Client side compiling disabled. -// static -void LLFloaterCompileQueue::onSaveTextComplete(const LLUUID& asset_id, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) -{ - LL_INFOS() << "LLFloaterCompileQueue::onSaveTextComplete()" << LL_ENDL; - if (status) - { - LL_WARNS() << "Unable to save text for script." << LL_ENDL; - LLSD args; - args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotificationsUtil::add("CompileQueueSaveText", args); - } -} - -// static -void LLFloaterCompileQueue::onSaveBytecodeComplete(const LLUUID& asset_id, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) -{ - LL_INFOS() << "LLFloaterCompileQueue::onSaveBytecodeComplete()" << LL_ENDL; - LLCompileQueueData* data = (LLCompileQueueData*)user_data; - LLFloaterCompileQueue* queue = static_cast (LLFloaterScriptQueue::findInstance(data->mQueueID)); - if(queue && (0 == status) && data) - { - queue->saveItemByItemID(data->mItemId); - queue->removeItemByItemID(data->mItemId); - } - else - { - LL_WARNS() << "Unable to save bytecode for script." << LL_ENDL; - LLSD args; - args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotificationsUtil::add("CompileQueueSaveBytecode", args); - } - delete data; - data = NULL; -} - -// compile the file given and save it out. -void LLFloaterCompileQueue::compile(const std::string& filename, - const LLUUID& item_id) -{ - LLUUID new_asset_id; - LLTransactionID tid; - tid.generate(); - new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - - std::string uuid_string; - new_asset_id.toString(uuid_string); - std::string dst_filename; - dst_filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string) + ".lso"; - std::string err_filename; - err_filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string) + ".out"; - - gAssetStorage->storeAssetData(filename, tid, - LLAssetType::AT_LSL_TEXT, - &onSaveTextComplete, NULL, FALSE); - - const BOOL compile_to_mono = FALSE; - if(!lscript_compile(filename.c_str(), dst_filename.c_str(), - err_filename.c_str(), compile_to_mono, - uuid_string.c_str(), gAgent.isGodlike())) - { - LL_WARNS() << "compile failed" << LL_ENDL; - removeItemByItemID(item_id); - } - else - { - LL_INFOS() << "compile successful." << LL_ENDL; - - // Save LSL bytecode - LLCompileQueueData* data = new LLCompileQueueData(mID, item_id); - gAssetStorage->storeAssetData(dst_filename, new_asset_id, - LLAssetType::AT_LSL_BYTECODE, - &LLFloaterCompileQueue::onSaveBytecodeComplete, - (void*)data, FALSE); - } -} -#endif const LLInventoryItem* LLFloaterCompileQueue::findItemByItemID(const LLUUID& asset_id) const { @@ -599,7 +567,7 @@ void LLFloaterCompileQueue::saveItemByItemID(const LLUUID& asset_id) { LL_INFOS() << "LLFloaterCompileQueue::saveItemByAssetID()" << LL_ENDL; LLViewerObject* viewer_object = gObjectList.findObject(mCurrentObjectID); - if(viewer_object) + if (viewer_object) { S32 count = mCurrentScripts.size(); for(S32 i = 0; i < count; ++i) @@ -648,13 +616,12 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj, { // find all of the lsl, leaving off duplicates. We'll remove // all matching asset uuids on compilation success. - std::vector names; LLInventoryObject::object_list_t::const_iterator it = inv->begin(); LLInventoryObject::object_list_t::const_iterator end = inv->end(); for ( ; it != end; ++it) { - if((*it)->getType() == LLAssetType::AT_LSL_TEXT) + if ((*it)->getType() == LLAssetType::AT_LSL_TEXT) { LLViewerObject* object = gObjectList.findObject(viewer_obj->getID()); @@ -662,7 +629,7 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj, { LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); std::string buffer; - buffer = getString("Resetting") + LLTrans::getString(":") + " " + item->getName(); + buffer = getString("Resetting") + LLTrans::getString(":") + ' ' + item->getName(); getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_ScriptReset); @@ -709,13 +676,11 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj, { // find all of the lsl, leaving off duplicates. We'll remove // all matching asset uuids on compilation success. - std::vector names; - LLInventoryObject::object_list_t::const_iterator it = inv->begin(); LLInventoryObject::object_list_t::const_iterator end = inv->end(); for ( ; it != end; ++it) { - if((*it)->getType() == LLAssetType::AT_LSL_TEXT) + if ((*it)->getType() == LLAssetType::AT_LSL_TEXT) { LLViewerObject* object = gObjectList.findObject(viewer_obj->getID()); @@ -724,7 +689,7 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj, LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); LLScrollListCtrl* list = getChild("queue output"); std::string buffer; - buffer = getString("Running") + LLTrans::getString(":") + " " + item->getName(); + buffer = getString("Running") + LLTrans::getString(":") + ' ' + item->getName(); list->addSimpleElement(buffer, ADD_BOTTOM); LLMessageSystem* msg = gMessageSystem; @@ -788,18 +753,33 @@ void LLFloaterCompileQueue::removeItemByItemID(const LLUUID& asset_id) } } +BOOL LLFloaterCompileQueue::startQueue() +{ + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + std::string lookup_url = region->getCapability("GetCreatorExperiences"); + if (!lookup_url.empty()) + { + LLHTTPClient::get(lookup_url, new CompileQueueExperienceResponder(mID)); + return TRUE; + } + } + return nextObject(); +} + + + void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj, LLInventoryObject::object_list_t* inv) { // find all of the lsl, leaving off duplicates. We'll remove // all matching asset uuids on compilation success. - std::vector names; - LLInventoryObject::object_list_t::const_iterator it = inv->begin(); LLInventoryObject::object_list_t::const_iterator end = inv->end(); for ( ; it != end; ++it) { - if((*it)->getType() == LLAssetType::AT_LSL_TEXT) + if ((*it)->getType() == LLAssetType::AT_LSL_TEXT) { LLViewerObject* object = gObjectList.findObject(viewer_obj->getID()); @@ -808,7 +788,7 @@ void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj, LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); LLScrollListCtrl* list = getChild("queue output"); std::string buffer; - buffer = getString("NotRunning") + LLTrans::getString(":") + " " + item->getName(); + buffer = getString("NotRunning") + LLTrans::getString(":") + ' ' + item->getName(); list->addSimpleElement(buffer, ADD_BOTTOM); LLMessageSystem* msg = gMessageSystem; diff --git a/indra/newview/llcompilequeue.h b/indra/newview/llcompilequeue.h index 281929445f..fba5d295a7 100644 --- a/indra/newview/llcompilequeue.h +++ b/indra/newview/llcompilequeue.h @@ -40,10 +40,11 @@ #include "lluuid.h" #include "llfloater.h" -#include "llscrolllistctrl.h" #include "llviewerinventory.h" +class LLScrollListCtrl; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFloaterScriptQueue // @@ -58,20 +59,23 @@ class LLFloaterScriptQueue : public LLFloater, public LLVOInventoryListener { public: + // find an instance by ID. Return NULL if it does not exist. + static LLFloaterScriptQueue* findInstance(const LLUUID& id); + LLFloaterScriptQueue(const std::string& name, const LLRect& rect, + const std::string& title, const std::string& start_string); + virtual ~LLFloaterScriptQueue(); + + /*virtual*/ BOOL postBuild(); + + void setMono(bool mono) { mMono = mono; } + // addObject() accepts an object id. void addObject(const LLUUID& id); // start() returns TRUE if the queue has started, otherwise FALSE. BOOL start(); - // find an instance by ID. Return NULL if it does not exist. - static LLFloaterScriptQueue* findInstance(const LLUUID& id); - protected: - LLFloaterScriptQueue(const std::string& name, const LLRect& rect, - const std::string& title, const std::string& start_string); - virtual ~LLFloaterScriptQueue(); - // This is the callback method for the viewer object currently // being worked on. /*virtual*/ void inventoryChanged(LLViewerObject* obj, @@ -88,21 +92,25 @@ class LLFloaterScriptQueue : public LLFloater, public LLVOInventoryListener // returns true if this is done BOOL isDone() const; + virtual BOOL startQueue(); + // go to the next object. If no objects left, it falls out // silently and waits to be killed by the deleteIfDone() callback. BOOL nextObject(); BOOL popNext(); - // Get this instances ID. + void setStartString(const std::string& s) { mStartString = s; } + + // Get this instance's ID. const LLUUID& getID() const { return mID; } - + protected: // UI LLScrollListCtrl* mMessages; LLButton* mCloseBtn; // Object Queue - std::vector mObjectIDs; + uuid_vec_t mObjectIDs; LLUUID mCurrentObjectID; bool mDone; @@ -110,6 +118,7 @@ class LLFloaterScriptQueue : public LLFloater, public LLVOInventoryListener static LLMap sInstances; std::string mStartString; + bool mMono; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -133,13 +142,16 @@ class LLFloaterCompileQueue : public LLFloaterScriptQueue public: // Use this method to create a compile queue. Once created, it // will be responsible for it's own destruction. - static LLFloaterCompileQueue* create(BOOL mono); + static LLFloaterCompileQueue* create(bool mono); // remove any object in mScriptScripts with the matching uuid. void removeItemByItemID(const LLUUID& item_id); LLAssetUploadQueue* getUploadQueue() { return mUploadQueue; } + void experienceIdsReceived(const LLSD& content); + BOOL hasExperience(const LLUUID& id) const; + protected: LLFloaterCompileQueue(const std::string& name, const LLRect& rect); virtual ~LLFloaterCompileQueue(); @@ -148,21 +160,13 @@ class LLFloaterCompileQueue : public LLFloaterScriptQueue virtual void handleInventory(LLViewerObject* viewer_obj, LLInventoryObject::object_list_t* inv); + static void requestAsset(struct LLScriptQueueData* datap, const LLSD& experience); + + // This is the callback for when each script arrives static void scriptArrived(LLVFS *vfs, const LLUUID& asset_id, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); - -#if 0 //Client side compiling disabled. - static void onSaveTextComplete(const LLUUID& asset_id, void* user_data, S32 status, LLExtStat ext_status); - - static void onSaveBytecodeComplete(const LLUUID& asset_id, - void* user_data, - S32 status, LLExtStat ext_status); - - // compile the file given and save it out. - void compile(const std::string& filename, const LLUUID& asset_id); -#endif // remove any object in mScriptScripts with the matching uuid. void removeItemByAssetID(const LLUUID& asset_id); @@ -173,12 +177,13 @@ class LLFloaterCompileQueue : public LLFloaterScriptQueue // find InventoryItem given item id. const LLInventoryItem* findItemByItemID(const LLUUID& item_id) const; + virtual BOOL startQueue(); protected: LLViewerInventoryItem::item_array_t mCurrentScripts; private: - BOOL mMono; // Compile to mono. LLAssetUploadQueue* mUploadQueue; + uuid_list_t mExperienceIds; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/newview/llconsole.cpp b/indra/newview/llconsole.cpp index dc72314fef..e4e365cefb 100644 --- a/indra/newview/llconsole.cpp +++ b/indra/newview/llconsole.cpp @@ -194,7 +194,7 @@ void LLConsole::draw() // draw remaining lines F32 y_pos = 0.f; - LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); static const LLCachedControl console_background_opacity("ConsoleBackgroundOpacity"); F32 console_opacity = llclamp(console_background_opacity.get(), 0.f, 1.f); diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp new file mode 100644 index 0000000000..31d027926a --- /dev/null +++ b/indra/newview/llcontrolavatar.cpp @@ -0,0 +1,671 @@ +/** + * @file llcontrolavatar.cpp + * @brief Implementation for special dummy avatar used to drive rigged meshes. + * + * $LicenseInfo:firstyear=2017&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2017, 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 "llviewerprecompiledheaders.h" +#include "llcontrolavatar.h" +#include "llagent.h" // Get state values from here +#include "llviewerobjectlist.h" +#include "pipeline.h" +#include "llanimationstates.h" +#include "llviewercontrol.h" +#include "llmeshrepository.h" +#include "llviewerregion.h" +#include "llskinningutil.h" + +//#pragma optimize("", off) + +const F32 LLControlAvatar::MAX_LEGAL_OFFSET = 3.0f; +const F32 LLControlAvatar::MAX_LEGAL_SIZE = 64.0f; + +//static +boost::signals2::connection LLControlAvatar::sRegionChangedSlot; + +LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp) : + LLVOAvatar(id, pcode, regionp), + mPlaying(false), + mGlobalScale(1.0f), + mRootVolp(NULL), + mMarkedForDeath(false), + mScaleConstraintFixup(1.0), + mRegionChanged(false) +{ + mIsDummy = TRUE; + mIsControlAvatar = true; + mEnableDefaultMotions = false; +} + +// virtual +LLControlAvatar::~LLControlAvatar() +{ + // Should already have been unlinked before destruction + llassert(!mRootVolp); +} + +// virtual +void LLControlAvatar::initInstance() +{ + // Potential optimizations here: avoid creating system + // avatar mesh content since it's not used. For now we just clean some + // things up after the fact in releaseMeshData(). + LLVOAvatar::initInstance(); + + createDrawable(&gPipeline); + updateJointLODs(); + updateGeometry(mDrawable); + hideSkirt(); + + mInitFlags |= 1<<4; +} + +void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_scale_fixup) const +{ + + F32 max_legal_offset = MAX_LEGAL_OFFSET; + static LLCachedControl animated_object_max_legal_offset(gSavedSettings, "AnimatedObjectsMaxLegalOffset"); + max_legal_offset = llmax(animated_object_max_legal_offset(),0.f); + + F32 max_legal_size = MAX_LEGAL_SIZE; + static LLCachedControl animated_object_max_legal_size(gSavedSettings, "AnimatedObjectsMaxLegalSize"); + max_legal_size = llmax(animated_object_max_legal_size(), 1.f); + + new_pos_fixup = LLVector3(); + new_scale_fixup = 1.0f; + LLVector3 vol_pos = mRootVolp->getRenderPosition(); + + // Fix up position if needed to prevent visual encroachment + if (box_valid_and_non_zero(getLastAnimExtents())) // wait for state to settle down + { + // The goal here is to ensure that the extent of the avatar's + // bounding box does not wander too far from the + // official position of the corresponding volume. We + // do this by tracking the distance and applying a + // correction to the control avatar position if + // needed. + const LLVector3 *extents = getLastAnimExtents(); + LLVector3 unshift_extents[2]; + unshift_extents[0] = extents[0] - mPositionConstraintFixup; + unshift_extents[1] = extents[1] - mPositionConstraintFixup; + LLVector3 box_dims = extents[1]-extents[0]; + F32 box_size = llmax(box_dims[0],box_dims[1],box_dims[2]); + + if (!mRootVolp->isAttachment()) + { + LLVector3 pos_box_offset = point_to_box_offset(vol_pos, unshift_extents); + F32 offset_dist = pos_box_offset.length(); + if (offset_dist > max_legal_offset && offset_dist > 0.f) + { + F32 target_dist = (offset_dist - max_legal_offset); + new_pos_fixup = (target_dist/offset_dist)*pos_box_offset; + } + //if (new_pos_fixup != mPositionConstraintFixup) + //{ + // LL_DEBUGS("ConstraintFix") << getFullname() << " pos fix, offset_dist " << offset_dist << " pos fixup " + // << new_pos_fixup << " was " << mPositionConstraintFixup << LL_ENDL; + // LL_DEBUGS("ConstraintFix") << "vol_pos " << vol_pos << LL_ENDL; + // LL_DEBUGS("ConstraintFix") << "extents " << extents[0] << " " << extents[1] << LL_ENDL; + // LL_DEBUGS("ConstraintFix") << "unshift_extents " << unshift_extents[0] << " " << unshift_extents[1] << LL_ENDL; + // + //} + } + if (box_size/mScaleConstraintFixup > max_legal_size) + { + new_scale_fixup = mScaleConstraintFixup*max_legal_size/box_size; + //LL_DEBUGS("ConstraintFix") << getFullname() << " scale fix, box_size " << box_size << " fixup " + // << mScaleConstraintFixup << " max legal " << max_legal_size + // << " -> new scale " << new_scale_fixup << LL_ENDL; + } + } +} + +void LLControlAvatar::matchVolumeTransform() +{ + if (mRootVolp) + { + LLVector3 new_pos_fixup; + F32 new_scale_fixup; + if (mRegionChanged) + { + new_scale_fixup = mScaleConstraintFixup; + new_pos_fixup = mPositionConstraintFixup; + mRegionChanged = false; + } + else + { + getNewConstraintFixups(new_pos_fixup, new_scale_fixup); + } + mPositionConstraintFixup = new_pos_fixup; + mScaleConstraintFixup = new_scale_fixup; + + static LLCachedControl global_scale(gSavedSettings, "AnimatedObjectsGlobalScale", 1.f); + + if (mRootVolp->isAttachment()) + { + LLVOAvatar *attached_av = mRootVolp->getAvatarAncestor(); + if (attached_av) + { + LLViewerJointAttachment *attach = attached_av->getTargetAttachmentPoint(mRootVolp); + setPositionAgent(mRootVolp->getRenderPosition()); + attach->updateWorldPRSParent(); + LLVector3 joint_pos = attach->getWorldPosition(); + LLQuaternion joint_rot = attach->getWorldRotation(); + LLVector3 obj_pos = mRootVolp->mDrawable->getPosition(); + const LLQuaternion& obj_rot = mRootVolp->mDrawable->getRotation(); + obj_pos.rotVec(joint_rot); + mRoot->setWorldPosition(obj_pos + joint_pos); + mRoot->setWorldRotation(obj_rot * joint_rot); + setRotation(mRoot->getRotation()); + + setGlobalScale(global_scale * mScaleConstraintFixup); + } + else + { + LL_WARNS_ONCE() << "can't find attached av!" << LL_ENDL; + } + } + else + { + LLVector3 vol_pos = mRootVolp->getRenderPosition(); + + // FIXME: Currently if you're doing something like playing an + // animation that moves the pelvis (on an avatar or + // animated object), the name tag and debug text will be + // left behind. Ideally setPosition() would follow the + // skeleton around in a smarter way, so name tags, + // complexity info and such line up better. Should defer + // this until avatars also get fixed. + + const LLQuaternion& obj_rot = mRootVolp->mDrawable ? mRootVolp->mDrawable->getRotation() : mRootVolp->getRotation(); + + LLQuaternion bind_rot; +#define MATCH_BIND_SHAPE +#ifdef MATCH_BIND_SHAPE + // MAINT-8671 - based on a patch from Beq Janus + const LLMeshSkinInfo* skin_info = mRootVolp->getSkinInfo(); + if (skin_info) + { + //LL_DEBUGS("BindShape") << getFullname() << " bind shape " << skin_info->mBindShapeMatrix << LL_ENDL; + bind_rot = LLSkinningUtil::getUnscaledQuaternion(skin_info->mBindShapeMatrix); + } +#endif + setRotation(bind_rot*obj_rot); + mRoot->setWorldRotation(bind_rot*obj_rot); + setPositionAgent(vol_pos); + mRoot->setPosition(vol_pos + mPositionConstraintFixup); + + setGlobalScale(global_scale * mScaleConstraintFixup); + } + } +} + +void LLControlAvatar::setGlobalScale(F32 scale) +{ + if (scale <= 0.0f) + { + LL_WARNS() << "invalid global scale " << scale << LL_ENDL; + return; + } + if (scale != mGlobalScale) + { + F32 adjust_scale = scale/mGlobalScale; + LL_INFOS() << "scale " << scale << " adjustment " << adjust_scale << LL_ENDL; + // should we be scaling from the pelvis or the root? + recursiveScaleJoint(mPelvisp,adjust_scale); + mGlobalScale = scale; + } +} + +void LLControlAvatar::recursiveScaleJoint(LLJoint* joint, F32 factor) +{ + joint->setScale(factor * joint->getScale()); + + for (auto child : joint->mChildren) + { + recursiveScaleJoint(child, factor); + } +} + +// Based on LLViewerJointAttachment::setupDrawable(), without the attaching part. +void LLControlAvatar::updateVolumeGeom() +{ + if (!mRootVolp->mDrawable) + return; + if (mRootVolp->mDrawable->isActive()) + { + mRootVolp->mDrawable->makeStatic(FALSE); + } + mRootVolp->mDrawable->makeActive(); + gPipeline.markMoved(mRootVolp->mDrawable); + gPipeline.markTextured(mRootVolp->mDrawable); // face may need to change draw pool to/from POOL_HUD + mRootVolp->mDrawable->setState(LLDrawable::USE_BACKLIGHT); + + LLViewerObject::const_child_list_t& child_list = mRootVolp->getChildren(); + for (const auto& iter : child_list) + { + LLViewerObject* childp = iter; + if (childp && childp->mDrawable.notNull()) + { + childp->mDrawable->setState(LLDrawable::USE_BACKLIGHT); + gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD + gPipeline.markMoved(childp->mDrawable); + } + } + + gPipeline.markRebuild(mRootVolp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); + mRootVolp->markForUpdate(TRUE); + + // Note that attachment overrides aren't needed here, have already + // been applied at the time the mControlAvatar was created, in + // llvovolume.cpp. + + matchVolumeTransform(); + + // Initial exploration of allowing scaling skeleton to match root + // prim bounding box. If enabled, would probably be controlled by + // an additional checkbox and default to off. Not enabled for + // initial release. + + // What should the scale be? What we really want is the ratio + // between the scale at which the object was originally designed + // and rigged, and the scale to which it has been subsequently + // modified - for example, if the object has been scaled down by a + // factor of 2 then we should use 0.5 as the global scale. But we + // don't have the original scale stored anywhere, just the current + // scale. Possibilities - 1) remember the original scale + // somewhere, 2) add another field to let the user specify the + // global scale, 3) approximate the original scale by looking at + // the proportions of the skeleton after joint positions have + // been applied + + //LLVector3 obj_scale = obj->getScale(); + //F32 obj_scale_z = llmax(obj_scale[2],0.1f); + //setGlobalScale(obj_scale_z/2.0f); // roughly fit avatar height range (2m) into object height +} + +LLControlAvatar *LLControlAvatar::createControlAvatar(LLVOVolume *obj) +{ + LLControlAvatar *cav = (LLControlAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), CO_FLAG_CONTROL_AVATAR); + + if (cav) + { + cav->mRootVolp = obj; + + // Sync up position/rotation with object + cav->matchVolumeTransform(); + } + + return cav; +} + +void LLControlAvatar::markForDeath() +{ + mMarkedForDeath = true; + mRootVolp = NULL; +} + +void LLControlAvatar::markDead() +{ + // NOTE: this can happen when the control avatar and root volume are on different regions and we're + // being called from the LLViewerRegion destructor due the region being dropped + // (due to being used as a vehicle and the move not yet being processed?) + if (mRootVolp) + { + mRootVolp->unlinkControlAvatar(); + mRootVolp = nullptr; + } + + LLVOAvatar::markDead(); +} + +void LLControlAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +{ + if (mMarkedForDeath) + { + markDead(); + mMarkedForDeath = false; + } + else + { + LLVOAvatar::idleUpdate(agent, world,time); + } +} + +BOOL LLControlAvatar::updateCharacter(LLAgent &agent) +{ + return LLVOAvatar::updateCharacter(agent); +} + +//virtual +void LLControlAvatar::updateDebugText() +{ + /*static LLCachedControl debug_animated_objects(gSavedSettings, "DebugAnimatedObjects"); + if (debug_animated_objects) + { + S32 total_linkset_count = 0; + if (mRootVolp) + { + total_linkset_count = 1 + mRootVolp->getChildren().size(); + } + std::vector volumes; + getAnimatedVolumes(volumes); + S32 animated_volume_count = volumes.size(); + std::string active_string; + std::string type_string; + std::string lod_string; + std::string animated_object_flag_string; + S32 total_tris = 0; + S32 total_verts = 0; + F32 est_tris = 0.f; + F32 est_streaming_tris = 0.f; + F32 streaming_cost = 0.f; + std::string cam_dist_string = ""; + S32 cam_dist_count = 0; + F32 lod_radius = mRootVolp->mLODRadius; + + for (auto volp : volumes) + { + if (volp) + { + S32 verts = 0; + total_tris += volp->getTriangleCount(&verts); + total_verts += verts; + est_tris += volp->getEstTrianglesMax(); + est_streaming_tris += volp->getEstTrianglesStreamingCost(); + streaming_cost += volp->getStreamingCost(); + lod_string += llformat("%d", volp->getLOD()); + if (volp->mDrawable) + { + bool is_animated_flag = volp->getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; + if (is_animated_flag) + { + animated_object_flag_string += "1"; + } + else + { + animated_object_flag_string += "0"; + } + if (volp->mDrawable->isActive()) + { + active_string += "A"; + } + else + { + active_string += "S"; + } + if (volp->isRiggedMesh()) + { + // Rigged/animatable mesh + type_string += "R"; + lod_radius = volp->mLODRadius; + } + else if (volp->isMesh()) + { + // Static mesh + type_string += "M"; + } + else + { + // Any other prim + type_string += "P"; + } + if (cam_dist_count < 4) + { + cam_dist_string += LLStringOps::getReadableNumber(volp->mLODDistance) + "/" + + LLStringOps::getReadableNumber(volp->mLODAdjustedDistance) + " "; + cam_dist_count++; + } + } + else + { + active_string += "-"; + type_string += "-"; + } + } + } + addDebugText(llformat("CAV obj %d anim %d active %s impost %d upprd %d strcst %f", + total_linkset_count, animated_volume_count, + active_string.c_str(), (S32) isImpostor(), getUpdatePeriod(), streaming_cost)); + addDebugText(llformat("types %s lods %s", type_string.c_str(), lod_string.c_str())); + addDebugText(llformat("flags %s", animated_object_flag_string.c_str())); + addDebugText(llformat("tris %d (est %.1f, streaming %.1f), verts %d", total_tris, est_tris, est_streaming_tris, total_verts)); + addDebugText(llformat("pxarea %s rank %d", LLStringOps::getReadableNumber(getPixelArea()).c_str(), getVisibilityRank())); + addDebugText(llformat("lod_radius %s dists %s", LLStringOps::getReadableNumber(lod_radius).c_str(),cam_dist_string.c_str())); + if (mPositionConstraintFixup.length() > 0.0f || mScaleConstraintFixup != 1.0f) + { + addDebugText(llformat("pos fix (%.1f %.1f %.1f) scale %f", + mPositionConstraintFixup[0], + mPositionConstraintFixup[1], + mPositionConstraintFixup[2], + mScaleConstraintFixup)); + } + +#if 0 + std::string region_name = "no region"; + if (mRootVolp->getRegion()) + { + region_name = mRootVolp->getRegion()->getName(); + } + std::string skel_region_name = "skel no region"; + if (getRegion()) + { + skel_region_name = getRegion()->getName(); + } + addDebugText(llformat("region %x %s skel %x %s", + mRootVolp->getRegion(), region_name.c_str(), + getRegion(), skel_region_name.c_str())); +#endif + + }*/ + LLVOAvatar::updateDebugText(); +} + +void LLControlAvatar::getAnimatedVolumes(std::vector& volumes) +{ + if (!mRootVolp) + { + return; + } + + volumes.push_back(mRootVolp); + + LLViewerObject::const_child_list_t& child_list = mRootVolp->getChildren(); + for (const auto& iter : child_list) + { + LLViewerObject* childp = iter; + LLVOVolume *child_volp = childp ? childp->asVolume() : nullptr; + if (child_volp && child_volp->isAnimatedObject()) + { + volumes.push_back(child_volp); + } + } +} + +// This is called after an associated object receives an animation +// message. Combine the signaled animations for all associated objects +// and process any resulting state changes. +void LLControlAvatar::updateAnimations() +{ + if (!mRootVolp) + { + LL_WARNS_ONCE("AnimatedObjectsNotify") << "No root vol" << LL_ENDL; + return; + } + + std::vector volumes; + getAnimatedVolumes(volumes); + + // Rebuild mSignaledAnimations from the associated volumes. + std::map anims; + for (auto vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it) + { + LLVOVolume *volp = *vol_it; + //LL_INFOS("AnimatedObjects") << "updating anim for vol " << volp->getID() << " root " << mRootVolp->getID() << LL_ENDL; + auto& signaled_anim_map = LLObjectSignaledAnimationMap::instance().getMap(); + signaled_animation_map_t& signaled_animations = signaled_anim_map[volp->getID()]; + for (auto anim_it = signaled_animations.begin(), anim_it_end = signaled_animations.end(); + anim_it != anim_it_end; + ++anim_it) + { + auto found_anim_it = anims.find(anim_it->first); + if (found_anim_it != anims.end()) + { + // Animation already present, use the larger sequence id + anims[anim_it->first] = llmax(found_anim_it->second, anim_it->second); + } + else + { + // Animation not already present, use this sequence id. + anims[anim_it->first] = anim_it->second; + } +#if LL_DEBUG + LL_DEBUGS("AnimatedObjectsNotify") << "found anim for vol " << volp->getID() << " anim " << anim_it->first << " root " << mRootVolp->getID() << LL_ENDL; +#endif + } + } + if (!mPlaying) + { + mPlaying = true; + //if (!mRootVolp->isAnySelected()) + { + updateVolumeGeom(); + mRootVolp->recursiveMarkForUpdate(TRUE); + } + } + + mSignaledAnimations = anims; + processAnimationStateChanges(); +} + +// virtual +LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end, + S32 face, + BOOL pick_transparent, + BOOL pick_rigged, + S32* face_hit, + LLVector4a* intersection, + LLVector2* tex_coord, + LLVector4a* normal, + LLVector4a* tangent) +{ + if (!mRootVolp) + { + return NULL; + } + + LLViewerObject* hit = NULL; + + if (lineSegmentBoundingBox(start, end)) + { + LLVector4a local_end = end; + LLVector4a local_intersection; + if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent)) + { + local_end = local_intersection; + if (intersection) + { + *intersection = local_intersection; + } + hit = mRootVolp; + } + else + { + std::vector volumes; + getAnimatedVolumes(volumes); + + for (auto volp : volumes) + { + if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent)) + { + local_end = local_intersection; + if (intersection) + { + *intersection = local_intersection; + } + hit = volp; + break; + } + } + } + } + + return hit; +} + +// virtual +std::string LLControlAvatar::getFullname() const +{ + if (mRootVolp) + { + return "AO_" + mRootVolp->getID().getString(); + } + else + { + return "AO_no_root_vol"; + } +} + +// virtual +bool LLControlAvatar::shouldRenderRigged() const +{ + if (mRootVolp && mRootVolp->isAttachment()) + { + LLVOAvatar *attached_av = mRootVolp->getAvatarAncestor(); + if (attached_av) + { + return attached_av->shouldRenderRigged(); + } + } + return true; +} + +// virtual +BOOL LLControlAvatar::isImpostor() const +{ + if (mRootVolp && mRootVolp->isAttachment()) + { + // Attached animated objects should match state of their attached av. + LLVOAvatar *attached_av = mRootVolp->getAvatarAncestor(); + if (attached_av) + { + return attached_av->isImpostor(); + } + } + return LLVOAvatar::isImpostor(); +} + +//static +void LLControlAvatar::onRegionChanged() +{ + std::vector::iterator it = LLCharacter::sInstances.begin(); + for ( ; it != LLCharacter::sInstances.end(); ++it) + { + auto avatar = static_cast(*it); + if (!avatar->isDead() && avatar->isControlAvatar()) + { + LLControlAvatar* cav = static_cast(avatar); + cav->mRegionChanged = true; + } + } +} diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h new file mode 100644 index 0000000000..c01c5c0a95 --- /dev/null +++ b/indra/newview/llcontrolavatar.h @@ -0,0 +1,115 @@ +/** + * @file llcontrolavatar.h + * @brief Special dummy avatar used to drive rigged meshes. + * + * $LicenseInfo:firstyear=2017&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2017, 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_CONTROLAVATAR_H +#define LL_CONTROLAVATAR_H + +#include "llvoavatar.h" +#include "llvovolume.h" + +class LLControlAvatar final: + public LLVOAvatar +{ + LOG_CLASS(LLControlAvatar); + +public: + LLControlAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); + void initInstance() override; // Called after construction to initialize the class. + virtual ~LLControlAvatar(); + LLControlAvatar* asControlAvatar() override { return this; } + + void getNewConstraintFixups(LLVector3& new_pos_constraint, F32& new_scale_constraint) const; + void matchVolumeTransform(); + void updateVolumeGeom(); + + void setGlobalScale(F32 scale); + void recursiveScaleJoint(LLJoint *joint, F32 factor); + static LLControlAvatar *createControlAvatar(LLVOVolume *obj); + + // Delayed kill so we don't make graphics pipeline unhappy calling + // markDead() inside other graphics pipeline operations. + void markForDeath(); + void markDead() override; + + void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) override; + BOOL updateCharacter(LLAgent &agent) override; + + void getAnimatedVolumes(std::vector& volumes); + void updateAnimations(); + + LLViewerObject* lineSegmentIntersectRiggedAttachments( + const LLVector4a& start, const LLVector4a& end, + S32 face = -1, // which face to check, -1 = ALL_SIDES + BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, + S32* face_hit = NULL, // which face was hit + LLVector4a* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector4a* normal = NULL, // return the surface normal at the intersection point + LLVector4a* tangent = NULL) override; // return the surface tangent at the intersection point + + void updateDebugText() override; + + std::string getFullname() const override; + + bool shouldRenderRigged() const override; + + BOOL isImpostor() const override; + + bool mPlaying; + + F32 mGlobalScale; + + LLVOVolume *mRootVolp; + + bool mMarkedForDeath; + + LLVector3 mPositionConstraintFixup; + F32 mScaleConstraintFixup; + + static const F32 MAX_LEGAL_OFFSET; + static const F32 MAX_LEGAL_SIZE; + + static void onRegionChanged(); + bool mRegionChanged; + static boost::signals2::connection sRegionChangedSlot; +}; + +typedef std::map signaled_animation_map_t; +typedef std::map object_signaled_animation_map_t; + +// Stores information about previously requested animations, by object id. +class LLObjectSignaledAnimationMap final : public LLSingleton +{ +public: + LLObjectSignaledAnimationMap() {} + + object_signaled_animation_map_t mMap; + + object_signaled_animation_map_t& getMap() { return mMap; } +}; + +#endif //LL_CONTROLAVATAR_H diff --git a/indra/newview/llcrashlogger.cpp b/indra/newview/llcrashlogger.cpp deleted file mode 100644 index 6a6dfa8612..0000000000 --- a/indra/newview/llcrashlogger.cpp +++ /dev/null @@ -1,418 +0,0 @@ - /** -* @file llcrashlogger.cpp -* @brief Crash logger implementation -* -* $LicenseInfo:firstyear=2003&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 "llviewerprecompiledheaders.h" - -#include "llcrashlogger.h" -#include "linden_common.h" -#include "llstring.h" -#include "indra_constants.h" // CRASH_BEHAVIOR_... -#include "llerror.h" -#include "llerrorcontrol.h" -#include "lltimer.h" -#include "lldir.h" -#include "llfile.h" -#include "llsdserialize.h" -#include "lliopipe.h" -#include "llpumpio.h" -#include "llhttpclient.h" -#include "llsdserialize.h" -#include "llproxy.h" -#include "llwindow.h" -#include "lltrans.h" -#include "aistatemachine.h" -#include "boost/filesystem.hpp" - -class AIHTTPTimeoutPolicy; -extern AIHTTPTimeoutPolicy crashLoggerResponder_timeout; -extern const std::string OLD_LOG_FILE; - -class LLCrashLoggerResponder : public LLHTTPClient::ResponderWithResult -{ -public: - LLCrashLoggerResponder() - { - } - - virtual void httpFailure(void) - { - LL_WARNS() << "Crash report sending failed: " << mReason << LL_ENDL; - } - - virtual void httpSuccess(void) - { - std::string msg = "Crash report successfully sent"; - if (mContent.has("message")) - { - msg += ": " + mContent["message"].asString(); - } - LL_INFOS() << msg << LL_ENDL; - - if (mContent.has("report_id")) - { - gSavedSettings.setS32("CrashReportID", mContent["report_id"].asInteger()); - } - - } - - virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const - { - return crashLoggerResponder_timeout; - } - - virtual char const* getName(void) const - { - return "LLCrashLoggerResponder"; - } -}; - -LLCrashLogger::LLCrashLogger() : - mCrashBehavior(CRASH_BEHAVIOR_ALWAYS_SEND), - mCrashInPreviousExec(false), - mCrashHost("") -{ -} - -LLCrashLogger::~LLCrashLogger() -{ - -} - -// TRIM_SIZE must remain larger than LINE_SEARCH_SIZE. -const int TRIM_SIZE = 128000; -const int LINE_SEARCH_DIST = 500; -const std::string SKIP_TEXT = "\n ...Skipping... \n"; -void trimSLLog(std::string& sllog) -{ - if(sllog.length() > TRIM_SIZE * 2) - { - std::string::iterator head = sllog.begin() + TRIM_SIZE; - std::string::iterator tail = sllog.begin() + sllog.length() - TRIM_SIZE; - std::string::iterator new_head = std::find(head, head - LINE_SEARCH_DIST, '\n'); - if(new_head != head - LINE_SEARCH_DIST) - { - head = new_head; - } - - std::string::iterator new_tail = std::find(tail, tail + LINE_SEARCH_DIST, '\n'); - if(new_tail != tail + LINE_SEARCH_DIST) - { - tail = new_tail; - } - - sllog.erase(head, tail); - sllog.insert(head, SKIP_TEXT.begin(), SKIP_TEXT.end()); - } -} - -std::string getStartupStateFromLog(std::string& sllog) -{ - std::string startup_state = "STATE_FIRST"; - std::string startup_token = "Startup state changing from "; - - int index = sllog.rfind(startup_token); - if (index < 0 || index + startup_token.length() > sllog.length()) { - return startup_state; - } - - // find new line - char cur_char = sllog[index + startup_token.length()]; - std::string::size_type newline_loc = index + startup_token.length(); - while(cur_char != '\n' && newline_loc < sllog.length()) - { - newline_loc++; - cur_char = sllog[newline_loc]; - } - - // get substring and find location of " to " - std::string state_line = sllog.substr(index, newline_loc - index); - std::string::size_type state_index = state_line.find(" to "); - startup_state = state_line.substr(state_index + 4, state_line.length() - state_index - 4); - - return startup_state; -} - -bool miniDumpExists(const std::string& dumpDir) -{ - bool found = false; - - try - { - if (!boost::filesystem::exists(dumpDir)) - { - return false; - } - - boost::filesystem::directory_iterator end_itr; - for (boost::filesystem::directory_iterator i(dumpDir); i != end_itr; ++i) - { - if (!boost::filesystem::is_regular_file(i->status())) continue; - if (".dmp" == i->path().extension()) - { - found = true; - break; - } - } - } - catch (const boost::filesystem::filesystem_error& e) - { - LL_WARNS() << "Failed to determine existance of the minidump file: '" + e.code().message() +"'" << LL_ENDL; - } - - return found; -} - -bool LLCrashLogger::readDebugFromXML(LLSD& dest, const std::string& filename ) -{ - std::string db_file_name = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,filename); - std::ifstream debug_log_file(db_file_name.c_str()); - - // Look for it in the debug_info.log file - if (debug_log_file.is_open()) - { - LLSDSerialize::fromXML(dest, debug_log_file); - debug_log_file.close(); - return true; - } - return false; -} - -void LLCrashLogger::mergeLogs( LLSD src_sd ) -{ - LLSD::map_iterator iter = src_sd.beginMap(); - LLSD::map_iterator end = src_sd.endMap(); - for( ; iter != end; ++iter) - { - mDebugLog[iter->first] = iter->second; - } -} - -bool LLCrashLogger::readMinidump(std::string minidump_path) -{ - size_t length=0; - - std::ifstream minidump_stream(minidump_path.c_str(), std::ios_base::in | std::ios_base::binary); - if(minidump_stream.is_open()) - { - minidump_stream.seekg(0, std::ios::end); - length = (size_t)minidump_stream.tellg(); - minidump_stream.seekg(0, std::ios::beg); - - LLSD::Binary data; - data.resize(length); - - minidump_stream.read(reinterpret_cast(&(data[0])),length); - minidump_stream.close(); - - mCrashInfo["Minidump"] = data; - } - return (length>0?true:false); -} - -void LLCrashLogger::gatherFiles() -{ - LL_INFOS() << "Gathering logs..." << LL_ENDL; - - LLSD static_sd; - LLSD dynamic_sd; - - bool has_logs = readDebugFromXML( static_sd, "static_debug_info.log" ); - has_logs |= readDebugFromXML( dynamic_sd, "dynamic_debug_info.log" ); - - if ( has_logs ) - { - mDebugLog = static_sd; - mergeLogs(dynamic_sd); - mCrashInPreviousExec = mDebugLog["CrashNotHandled"].asBoolean(); - - mFileMap["SecondLifeLog"] = mDebugLog["SLLog"].asString(); - mFileMap["SettingsXml"] = mDebugLog["SettingsFilename"].asString(); - if(mDebugLog.has("CAFilename")) - { - LLCurl::setCAFile(mDebugLog["CAFilename"].asString()); - } - else - { - LLCurl::setCAFile(gDirUtilp->getCAFile()); - } - - LL_INFOS() << "Using log file from debug log " << mFileMap["SecondLifeLog"] << LL_ENDL; - LL_INFOS() << "Using settings file from debug log " << mFileMap["SettingsXml"] << LL_ENDL; - } - else - { - // Figure out the filename of the second life log - LLCurl::setCAFile(gDirUtilp->getCAFile()); - mFileMap["SecondLifeLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.log"); - mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml"); - } - - if(mCrashInPreviousExec) - { - // Restarting after freeze. - // Replace the log file ext with .old, since the - // instance that launched this process has overwritten - // SecondLife.log - std::string log_filename = mFileMap["SecondLifeLog"]; - log_filename.replace(log_filename.size() - 4, 4, ".old"); - mFileMap["SecondLifeLog"] = log_filename; - } - - gatherPlatformSpecificFiles(); - - mCrashInfo["DebugLog"] = mDebugLog; - mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"stats.log"); - // Singu Note: we have just started again, log has been renamed - mFileMap["SecondLifeLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, OLD_LOG_FILE); - - LL_INFOS() << "Encoding files..." << LL_ENDL; - - for(std::map::iterator itr = mFileMap.begin(); itr != mFileMap.end(); ++itr) - { - std::ifstream f((*itr).second.c_str()); - if(!f.is_open()) - { - LL_INFOS() << "Can't find file " << (*itr).second << LL_ENDL; - continue; - } - std::stringstream s; - s << f.rdbuf(); - - std::string crash_info = s.str(); - if(itr->first == "SecondLifeLog") - { - if(!mCrashInfo["DebugLog"].has("StartupState")) - { - mCrashInfo["DebugLog"]["StartupState"] = getStartupStateFromLog(crash_info); - } - trimSLLog(crash_info); - } - - mCrashInfo[(*itr).first] = LLStringFn::strip_invalid_xml(rawstr_to_utf8(crash_info)); - } - - std::string minidump_path; - - // Add minidump as binary. - bool has_minidump = mDebugLog.has("MinidumpPath"); - - if (has_minidump) - minidump_path = mDebugLog["MinidumpPath"].asString(); - - - if (has_minidump) - { - has_minidump = readMinidump(minidump_path); - } - - if (!has_minidump) //Viewer was probably so hosed it couldn't write remaining data. Try brute force. - { - //Look for a filename at least 30 characters long in the dump dir which contains the characters MDMP as the first 4 characters in the file. - typedef std::vector vec; - - std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,""); - vec file_vec = gDirUtilp->getFilesInDir(pathname); - for(vec::const_iterator iter=file_vec.begin(); iter!=file_vec.end(); ++iter) - { - if ( ( iter->length() > 30 ) && (iter->rfind(".log") != (iter->length()-4) ) ) - { - std::string fullname = pathname + *iter; - std::ifstream fdat( fullname.c_str(), std::ifstream::binary); - if (fdat) - { - char buf[5]; - fdat.read(buf,4); - fdat.close(); - if (!strncmp(buf,"MDMP",4)) - { - minidump_path = *iter; - has_minidump = readMinidump(fullname); - mDebugLog["MinidumpPath"] = fullname; - } - } - } - } - } -} - -LLSD LLCrashLogger::constructPostData() -{ - return mCrashInfo; -} - - -bool LLCrashLogger::sendCrashLog(std::string dump_dir) -{ - gDirUtilp->setDumpDir( dump_dir ); - - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, - "SingularityCrashReport"); - std::string report_file = dump_path + ".log"; - - gatherFiles(); - - LLSD post_data; - post_data = constructPostData(); - - LL_INFOS() << "Sending reports..." << LL_ENDL; - - std::ofstream out_file(report_file.c_str()); - LLSDSerialize::toPrettyXML(post_data, out_file); - out_file.close(); - - LLHTTPClient::post(mCrashHost, post_data, new LLCrashLoggerResponder()); - - return true; -} - - -void LLCrashLogger::checkCrashDump() -{ -#if LL_SEND_CRASH_REPORTS - // 0 - ask, 1 - always send, 2 - never send - S32 pref = gSavedSettings.getS32("CrashSubmitBehavior"); - if (pref == 2) return; //never send - - mCrashHost = gSavedSettings.getString("CrashHostUrl"); - std::string dumpDir = gDirUtilp->getDumpDir(); - - // Do we have something to send, and somewhere to send it - if (!mCrashHost.empty() && miniDumpExists(dumpDir)) - { - if (pref == 1) // always send - { - sendCrashLog(dumpDir); - } - else // ask - { - U32 response = OSMessageBox(LLTrans::getString("MBFrozenCrashed"), LLTrans::getString("MBAlert"), OSMB_YESNO); - if (response == OSBTN_YES) - { - sendCrashLog(dumpDir); - } - } - } -#endif -} diff --git a/indra/newview/llcrashlogger.h b/indra/newview/llcrashlogger.h deleted file mode 100644 index c510acb98c..0000000000 --- a/indra/newview/llcrashlogger.h +++ /dev/null @@ -1,67 +0,0 @@ -/** -* @file llcrashlogger.h -* @brief Crash Logger Definition -* -* $LicenseInfo:firstyear=2003&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 LLCRASHLOGGER_H -#define LLCRASHLOGGER_H - -#include - -#include "linden_common.h" - -#include "llapp.h" -#include "llsd.h" -#include "llcontrol.h" - -class LLCrashLogger -{ -public: - LLCrashLogger(); - virtual ~LLCrashLogger(); - S32 loadCrashBehaviorSetting(); - bool readDebugFromXML(LLSD& dest, const std::string& filename ); - void gatherFiles(); - void mergeLogs( LLSD src_sd ); - - virtual void gatherPlatformSpecificFiles() {} - bool saveCrashBehaviorSetting(S32 crash_behavior); - bool sendCrashLog(std::string dump_dir); - LLSD constructPostData(); - void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; } - S32 getCrashBehavior() { return mCrashBehavior; } - bool readMinidump(std::string minidump_path); - void checkCrashDump(); - -protected: - S32 mCrashBehavior; - BOOL mCrashInPreviousExec; - std::map mFileMap; - std::string mGridName; - std::string mProductName; - LLSD mCrashInfo; - std::string mCrashHost; - LLSD mDebugLog; -}; - -#endif //LLCRASHLOGGER_H diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp index 7609358b5f..3320e609b9 100644 --- a/indra/newview/llcurrencyuimanager.cpp +++ b/indra/newview/llcurrencyuimanager.cpp @@ -387,6 +387,7 @@ void LLCurrencyUIManager::Impl::updateUI() } mPanel.childSetTextArg("currency_est", "[USD]", llformat("%#.2f", mSiteCurrencyEstimatedCost / 100.0)); + mPanel.childSetTextArg("currency_est", "[REALCURRENCY]", gHippoGridManager->getConnectedGrid()->getRealCurrencySymbol()); mPanel.childSetVisible("currency_est", mSiteCurrencyEstimated && mUserCurrencyBuy > 0); if (mPanel.childIsEnabled("buy_btn") diff --git a/indra/newview/lldebugmessagebox.cpp b/indra/newview/lldebugmessagebox.cpp index d485c7a9d1..7073d9b057 100644 --- a/indra/newview/lldebugmessagebox.cpp +++ b/indra/newview/lldebugmessagebox.cpp @@ -56,25 +56,25 @@ LLDebugVarMessageBox::LLDebugVarMessageBox(const std::string& title, EDebugVarTy switch(var_type) { case VAR_TYPE_F32: - mSlider1 = new LLSliderCtrl(std::string("slider 1"), LLRect(20,130,190,110), title, NULL, 70, 130, TRUE, TRUE, FALSE, NULL, *((F32*)var), -100.f, 100.f, 0.1f, LLStringUtil::null); + mSlider1 = new LLSliderCtrl(std::string("slider 1"), LLRect(20,130,190,110), title, NULL, 70, 130, TRUE, TRUE, NULL, *((F32*)var), -100.f, 100.f, 0.1f, LLStringUtil::null); mSlider1->setPrecision(3); addChild(mSlider1); mSlider2 = NULL; mSlider3 = NULL; break; case VAR_TYPE_S32: - mSlider1 = new LLSliderCtrl(std::string("slider 1"), LLRect(20,100,190,80), title, NULL, 70, 130, TRUE, TRUE, FALSE, NULL, (F32)*((S32*)var), -255.f, 255.f, 1.f, LLStringUtil::null); + mSlider1 = new LLSliderCtrl(std::string("slider 1"), LLRect(20,100,190,80), title, NULL, 70, 130, TRUE, TRUE, NULL, (F32)*((S32*)var), -255.f, 255.f, 1.f, LLStringUtil::null); mSlider1->setPrecision(0); addChild(mSlider1); mSlider2 = NULL; mSlider3 = NULL; break; case VAR_TYPE_VEC3: - mSlider1 = new LLSliderCtrl(std::string("slider 1"), LLRect(20,130,190,110), std::string("x: "), NULL, 70, 130, TRUE, TRUE, FALSE, NULL, ((LLVector3*)var)->mV[VX], -100.f, 100.f, 0.1f, LLStringUtil::null); + mSlider1 = new LLSliderCtrl(std::string("slider 1"), LLRect(20,130,190,110), std::string("x: "), NULL, 70, 130, TRUE, TRUE, NULL, ((LLVector3*)var)->mV[VX], -100.f, 100.f, 0.1f, LLStringUtil::null); mSlider1->setPrecision(3); - mSlider2 = new LLSliderCtrl(std::string("slider 2"), LLRect(20,100,190,80), std::string("y: "), NULL, 70, 130, TRUE, TRUE, FALSE, NULL, ((LLVector3*)var)->mV[VY], -100.f, 100.f, 0.1f, LLStringUtil::null); + mSlider2 = new LLSliderCtrl(std::string("slider 2"), LLRect(20,100,190,80), std::string("y: "), NULL, 70, 130, TRUE, TRUE, NULL, ((LLVector3*)var)->mV[VY], -100.f, 100.f, 0.1f, LLStringUtil::null); mSlider2->setPrecision(3); - mSlider3 = new LLSliderCtrl(std::string("slider 3"), LLRect(20,70,190,50), std::string("z: "), NULL, 70, 130, TRUE, TRUE, FALSE, NULL, ((LLVector3*)var)->mV[VZ], -100.f, 100.f, 0.1f, LLStringUtil::null); + mSlider3 = new LLSliderCtrl(std::string("slider 3"), LLRect(20,70,190,50), std::string("z: "), NULL, 70, 130, TRUE, TRUE, NULL, ((LLVector3*)var)->mV[VZ], -100.f, 100.f, 0.1f, LLStringUtil::null); mSlider3->setPrecision(3); addChild(mSlider1); addChild(mSlider2); diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 99aa79f524..becf850ab4 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -32,6 +32,7 @@ #include "material_codes.h" // viewer includes +#include "llagent.h" #include "llcriticaldamp.h" #include "llface.h" #include "lllightconstants.h" @@ -49,13 +50,15 @@ #include "llspatialpartition.h" #include "llviewerobjectlist.h" #include "llviewerwindow.h" +#include "llcontrolavatar.h" +#include "lldrawpoolavatar.h" const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f; const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f; const F32 OBJECT_DAMPING_TIME_CONSTANT = 0.06f; const F32 MIN_SHADOW_CASTER_RADIUS = 2.0f; -static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound"); +static LLTrace::BlockTimerStatHandle FTM_CULL_REBOUND("Cull Rebound"); extern bool gShiftFrame; @@ -113,6 +116,28 @@ void LLDrawable::init() initVisible(sCurVisible - 2);//invisible for the current frame and the last frame. } +void LLDrawable::unload() +{ + LLVOVolume *pVVol = getVOVolume(); + pVVol->setNoLOD(); + + for (S32 i = 0; i < getNumFaces(); i++) + { + LLFace* facep = getFace(i); + if (facep->isState(LLFace::RIGGED)) + { + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*)facep->getPool(); + if (pool) { + pool->removeRiggedFace(facep); + } + facep->setVertexBuffer(NULL); + } + facep->clearState(LLFace::RIGGED); + } + + pVVol->markForUpdate(TRUE); +} + // static void LLDrawable::initClass() { @@ -199,16 +224,16 @@ BOOL LLDrawable::isLight() const } } -static LLFastTimer::DeclareTimer FTM_CLEANUP_DRAWABLE("Cleanup Drawable"); -static LLFastTimer::DeclareTimer FTM_DEREF_DRAWABLE("Deref"); -static LLFastTimer::DeclareTimer FTM_DELETE_FACES("Faces"); +static LLTrace::BlockTimerStatHandle FTM_CLEANUP_DRAWABLE("Cleanup Drawable"); +static LLTrace::BlockTimerStatHandle FTM_DEREF_DRAWABLE("Deref"); +static LLTrace::BlockTimerStatHandle FTM_DELETE_FACES("Faces"); void LLDrawable::cleanupReferences() { - LLFastTimer t(FTM_CLEANUP_DRAWABLE); + LL_RECORD_BLOCK_TIME(FTM_CLEANUP_DRAWABLE); { - LLFastTimer t(FTM_DELETE_FACES); + LL_RECORD_BLOCK_TIME(FTM_DELETE_FACES); std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); mFaces.clear(); } @@ -220,7 +245,7 @@ void LLDrawable::cleanupReferences() removeFromOctree(); { - LLFastTimer t(FTM_DEREF_DRAWABLE); + LL_RECORD_BLOCK_TIME(FTM_DEREF_DRAWABLE); // Cleanup references to other objects mVObjp = NULL; mParent = NULL; @@ -265,14 +290,14 @@ S32 LLDrawable::findReferences(LLDrawable *drawablep) return count; } -static LLFastTimer::DeclareTimer FTM_ALLOCATE_FACE("Allocate Face", true); +static LLTrace::BlockTimerStatHandle FTM_ALLOCATE_FACE("Allocate Face", true); LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerTexture *texturep) { LLFace *face; { - LLFastTimer t(FTM_ALLOCATE_FACE); + LL_RECORD_BLOCK_TIME(FTM_ALLOCATE_FACE); face = new LLFace(this, mVObjp); } @@ -300,7 +325,7 @@ LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep) LLFace *face; { - LLFastTimer t(FTM_ALLOCATE_FACE); + LL_RECORD_BLOCK_TIME(FTM_ALLOCATE_FACE); face = new LLFace(this, mVObjp); } @@ -512,7 +537,8 @@ void LLDrawable::makeStatic(BOOL warning_enabled) if (isState(ACTIVE) && !isState(ACTIVE_CHILD) && !mVObjp->isAttachment() && - !mVObjp->isFlexible()) + !mVObjp->isFlexible() && + !mVObjp->isAnimatedObject()) { clearState(ACTIVE | ANIMATED_CHILD); @@ -581,7 +607,7 @@ F32 LLDrawable::updateXform(BOOL undamped) if (damped && isVisible()) { - F32 lerp_amt = llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f); + F32 lerp_amt = llclamp(LLSmoothInterpolation::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f); LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt); dist_squared = dist_vec_squared(new_pos, target_pos); @@ -604,6 +630,9 @@ F32 LLDrawable::updateXform(BOOL undamped) { // snap to final position (only if no target omega is applied) dist_squared = 0.0f; + //set target scale here, because of dist_squared = 0.0f remove object from move list + mCurrentScale = target_scale; // Animesh+ + if (getVOVolume() && !isRoot()) { //child prim snapping to some position, needs a rebuild gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); @@ -622,9 +651,15 @@ F32 LLDrawable::updateXform(BOOL undamped) LLVector3 vec = mCurrentScale-target_scale; + //It's a very important on each cycle on Drawable::update form(), when object remained in move + //, list update the CurrentScale member, because if do not do that, it remained in this list forever + //or when the delta time between two frames a become a sufficiently large (due to interpolation) + //for overcome the MIN_INTERPOLATE_DISTANCE_SQUARED. + mCurrentScale = target_scale; // Animesh+ + if (vec*vec > MIN_INTERPOLATE_DISTANCE_SQUARED) { //scale change requires immediate rebuild - mCurrentScale = target_scale; + //mCurrentScale = target_scale; // Animesh- gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } else if (!isRoot() && @@ -655,6 +690,10 @@ 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()) + { + mVObjp->getControlAvatar()->matchVolumeTransform(); + } if (mSpatialBridge) { @@ -724,7 +763,7 @@ BOOL LLDrawable::updateMoveUndamped() if (!isState(LLDrawable::INVISIBLE)) { - BOOL moved = (dist_squared > 0.001f); + BOOL moved = (dist_squared > 0.001f && dist_squared < 255.99f); // Animesh added 255.99f cap moveUpdatePipeline(moved); mVObjp->updateText(); } @@ -758,7 +797,7 @@ BOOL LLDrawable::updateMoveDamped() if (!isState(LLDrawable::INVISIBLE)) { - BOOL moved = (dist_squared > 0.001f); + BOOL moved = (dist_squared > 0.001f && dist_squared < 128.0f); // Animesh added 128.0f cap moveUpdatePipeline(moved); mVObjp->updateText(); } @@ -826,6 +865,28 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) } } } + + // MAINT-7926 Handle volumes in an animated object as a special case + // SL-937: add dynamic box handling for rigged mesh on regular avatars. + //if (volume->getAvatar() && volume->getAvatar()->isControlAvatar()) + if (volume->getAvatar()) + { + const LLVector3* av_box = volume->getAvatar()->getLastAnimExtents(); + LLVector3d cam_pos = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()); + LLVector3 cam_region_pos = LLVector3(cam_pos - volume->getRegion()->getOriginGlobal()); + + LLVector3 cam_to_box_offset = point_to_box_offset(cam_region_pos, av_box); + mDistanceWRTCamera = llmax(0.01f, ll_round(cam_to_box_offset.magVec(), 0.01f)); + LL_DEBUGS("DynamicBox") << volume->getAvatar()->getFullname() + << " pos (ignored) " << pos + << " cam pos " << cam_pos + << " cam region pos " << cam_region_pos + << " box " << av_box[0] << "," << av_box[1] + << " -> dist " << mDistanceWRTCamera + << LL_ENDL; + mVObjp->updateLOD(); + return; + } } else { @@ -939,9 +1000,7 @@ void LLDrawable::updateSpatialExtents() if (mVObjp) { const LLVector4a* exts = getSpatialExtents(); - LLVector4a extents[2]; - extents[0] = exts[0]; - extents[1] = exts[1]; + LLVector4a extents[2] = { exts[0], exts[1] }; mVObjp->updateSpatialExtents(extents[0], extents[1]); setSpatialExtents(extents[0], extents[1]); @@ -1080,20 +1139,28 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() retval = gPipeline.getSpatialPartition((LLViewerObject*) mVObjp); } else if (isRoot()) - { //must be an active volume + { + if (mSpatialBridge && (mSpatialBridge->asPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD) != mVObjp->isHUDAttachment()) + { + // remove obsolete bridge + mSpatialBridge->markDead(); + setSpatialBridge(NULL); + } + //must be an active volume if (!mSpatialBridge) { + // Spatial bridge ctors self-register... if (mVObjp->isHUDAttachment()) { - setSpatialBridge(new LLHUDBridge(this)); + setSpatialBridge(new LLHUDBridge(this, getRegion())); } else if (mVObjp->isAttachment()) { - setSpatialBridge(new LLAttachmentBridge(this)); + setSpatialBridge(new LLAttachmentBridge(this, getRegion())); } else { - setSpatialBridge(new LLVolumeBridge(this)); + setSpatialBridge(new LLVolumeBridge(this, getRegion())); } } return mSpatialBridge->asPartition(); @@ -1116,9 +1183,9 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() // Spatial Partition Bridging Drawable //======================================= -LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask) : +LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask, LLViewerRegion* regionp) : LLDrawable(root->getVObj()), - LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB) + LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB, regionp) { mBridge = this; mDrawable = root; @@ -1168,7 +1235,7 @@ void LLSpatialBridge::updateSpatialExtents() LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0); { - LLFastTimer ftm(FTM_CULL_REBOUND); + LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); root->rebound(); } @@ -1529,11 +1596,7 @@ void LLSpatialBridge::cleanupReferences() LLDrawable::cleanupReferences(); if (mDrawable) { - /* - - DON'T DO THIS -- this should happen through octree destruction - - mDrawable->setSpatialGroup(NULL); + mDrawable->setGroup(NULL); if (mDrawable->getVObj()) { LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); @@ -1541,17 +1604,18 @@ void LLSpatialBridge::cleanupReferences() iter != child_list.end(); iter++) { LLViewerObject* child = *iter; - LLDrawable* drawable = child->mDrawable; + LLDrawable* drawable = child->mDrawable; if (drawable) { - drawable->setSpatialGroup(NULL); + drawable->setGroup(NULL); } } - }*/ + } - LLDrawable* drawablep = mDrawable; - mDrawable = NULL; - drawablep->setSpatialBridge(NULL); + LLPointer bridgep = mDrawable->getSpatialBridge(); + mDrawable->setSpatialBridge(nullptr); + mDrawable = nullptr; + bridgep = nullptr; } } @@ -1627,8 +1691,8 @@ void LLDrawable::updateFaceSize(S32 idx) } } -LLBridgePartition::LLBridgePartition() -: LLSpatialPartition(0, FALSE, 0) +LLBridgePartition::LLBridgePartition(LLViewerRegion* regionp) +: LLSpatialPartition(0, FALSE, 0, regionp) { mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; mPartitionType = LLViewerRegion::PARTITION_BRIDGE; @@ -1636,14 +1700,14 @@ LLBridgePartition::LLBridgePartition() mSlopRatio = 0.25f; } -LLAttachmentPartition::LLAttachmentPartition() -: LLBridgePartition() +LLAttachmentPartition::LLAttachmentPartition(LLViewerRegion* regionp) +: LLBridgePartition(regionp) { mDrawableType = LLPipeline::RENDER_TYPE_AVATAR; } -LLHUDBridge::LLHUDBridge(LLDrawable* drawablep) -: LLVolumeBridge(drawablep) +LLHUDBridge::LLHUDBridge(LLDrawable* drawablep, LLViewerRegion* regionp) +: LLVolumeBridge(drawablep, regionp) { mDrawableType = LLPipeline::RENDER_TYPE_HUD; mPartitionType = LLViewerRegion::PARTITION_HUD; diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 7030356f0d..1da98e3150 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -61,7 +61,7 @@ class LLVOVolume; class LLViewerTexture; // Can have multiple silhouettes for each object -const U32 SILHOUETTE_HIGHLIGHT = 0; +constexpr U32 SILHOUETTE_HIGHLIGHT = 0; // All data for new renderer goes into this class. LL_ALIGN_PREFIX(16) @@ -98,7 +98,7 @@ class LLDrawable void markDead(); // Mark this drawable as dead BOOL isDead() const { return isState(DEAD); } BOOL isNew() const { return !isState(BUILT); } - + BOOL isUnload() const { return isState(FOR_UNLOAD); } BOOL isLight() const; virtual void setVisible(LLCamera& camera_in, std::vector* results = NULL, BOOL for_select = FALSE); @@ -155,6 +155,7 @@ class LLDrawable void mergeFaces(LLDrawable* src); void init(); + void unload(); void destroy(); void update(); @@ -296,6 +297,7 @@ class LLDrawable PARTITION_MOVE = 0x10000000, ANIMATED_CHILD = 0x20000000, ACTIVE_CHILD = 0x40000000, + FOR_UNLOAD = 0x80000000, //should be unload from memory } EDrawableFlags; public: diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index d8e9864f28..b1d393e9bb 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -75,9 +75,6 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0) case POOL_FULLBRIGHT: poolp = new LLDrawPoolFullbright(); break; - case POOL_INVISIBLE: - poolp = new LLDrawPoolInvisible(); - break; case POOL_GLOW: poolp = new LLDrawPoolGlow(); break; diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index fa8fc36750..1e4070f244 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -46,30 +46,24 @@ class LLDrawPool enum { // Correspond to LLPipeline render type - POOL_SIMPLE = 1, - POOL_GROUND, + POOL_GROUND = 1, + POOL_TERRAIN, + POOL_SIMPLE, POOL_FULLBRIGHT, POOL_BUMP, POOL_MATERIALS, - POOL_TERRAIN, POOL_TREE, // Singu Note: Before sky for zcull. POOL_ALPHA_MASK, POOL_FULLBRIGHT_ALPHA_MASK, POOL_SKY, POOL_WL_SKY, POOL_GRASS, - POOL_INVISIBLE, // see below * POOL_AVATAR, POOL_VOIDWATER, POOL_WATER, POOL_GLOW, POOL_ALPHA, NUM_POOL_TYPES, - // * invisiprims work by rendering to the depth buffer but not the color buffer, occluding anything rendered after them - // - and the LLDrawPool types enum controls what order things are rendered in - // - so, it has absolute control over what invisprims block - // ...invisiprims being rendered in pool_invisible - // ...shiny/bump mapped objects in rendered in POOL_BUMP }; LLDrawPool(const U32 type); @@ -126,8 +120,6 @@ class LLRenderPass : public LLDrawPool PASS_SIMPLE = NUM_POOL_TYPES, PASS_GRASS, PASS_FULLBRIGHT, - PASS_INVISIBLE, - PASS_INVISI_SHINY, PASS_FULLBRIGHT_SHINY, PASS_SHINY, PASS_BUMP, diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index b3897005b6..328d514d0d 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -96,7 +96,7 @@ S32 LLDrawPoolAlpha::getNumPostDeferredPasses() void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) { - LLFastTimer t(FTM_RENDER_ALPHA); + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA); if (pass == 0) { @@ -125,6 +125,7 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) //prime simple shader (loads shadow relevant uniforms) gPipeline.bindDeferredShader(*simple_shader); + gPipeline.unbindDeferredShader(*simple_shader); //simple_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); } @@ -149,12 +150,14 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) current_shader = target_shader = NULL; LLGLSLShader::bindNoShader(); - - gPipeline.enableLightsDynamic(); } void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) -{ +{ + if (current_shader) + { + gPipeline.unbindDeferredShader(*current_shader); + } if (pass == 1 && !LLPipeline::sImpostorRender) { gPipeline.mDeferredDepth.flush(); @@ -173,7 +176,7 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) void LLDrawPoolAlpha::beginRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_ALPHA); + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA); simple_shader = &gObjectSimpleProgram[1< 0) //Singu Note: Unbind if shaders are enabled at all, not just windlight atmospherics.. @@ -203,9 +204,11 @@ void LLDrawPoolAlpha::endRenderPass( S32 pass ) void LLDrawPoolAlpha::render(S32 pass) { - LLFastTimer t(FTM_RENDER_ALPHA); + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA); LLGLSPipelineAlpha gls_pipeline_alpha; + LLGLState light_state; + gPipeline.enableLightsDynamic(light_state); if (deferred_render && pass == 1) { //depth only @@ -270,13 +273,14 @@ void LLDrawPoolAlpha::render(S32 pass) if (sShowDebugAlpha) { + LLGLState light_state; if (LLGLSLShader::sNoFixedFunction) { gHighlightProgram.bind(); } else { - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + gPipeline.enableLightsFullbright(light_state); } gGL.diffuseColor4f(0.9f,0.f,0.f,0.4f); @@ -294,6 +298,10 @@ void LLDrawPoolAlpha::render(S32 pass) { gHighlightProgram.unbind(); } + else + { + gPipeline.enableLightsDynamic(light_state); + } } gGL.setSceneBlendType(LLRender::BT_ALPHA); } @@ -332,12 +340,10 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) { - BOOL initialized_lighting = FALSE; - BOOL light_enabled = TRUE; - - BOOL use_shaders = LLGLSLShader::sNoFixedFunction; - - BOOL depth_only = (pass == 1 && !LLPipeline::sImpostorRender); + LLGLState light_state; + bool light_enabled = TRUE; + bool use_shaders = LLGLSLShader::sNoFixedFunction; + bool depth_only = (pass == 1 && !LLPipeline::sImpostorRender); for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { @@ -354,11 +360,11 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) bool draw_glow_for_this_partition = !depth_only && mVertexShaderLevel > 0; // no shaders = no glow. - static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group"); - LLFastTimer t(FTM_RENDER_ALPHA_GROUP_LOOP); + static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group"); + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_GROUP_LOOP); bool disable_cull = is_particle_or_hud_particle; - LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0); + LLGLDisable cull(disable_cull); LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; @@ -400,7 +406,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) } LLMaterial* mat = deferred_render ? params.mMaterial.get() : NULL; - if (!use_shaders) { llassert_always(!target_shader); @@ -409,18 +414,17 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) llassert_always(!LLGLSLShader::sCurBoundShaderPtr); bool fullbright = depth_only || params.mFullbright; - if(fullbright == !!light_enabled || !initialized_lighting) + if(light_enabled == fullbright) { light_enabled = !fullbright; - initialized_lighting = true; - if (light_enabled) // Turn off lighting if it hasn't already been so. + if (light_enabled) // Set local lights { - gPipeline.enableLightsDynamic(); + gPipeline.enableLightsDynamic(light_state); } - else // Turn on lighting if it isn't already. + else // Set fullbright { - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + gPipeline.enableLightsFullbright(light_state); } } } @@ -437,6 +441,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) // (this way we won't rebind shaders unnecessarily). if (current_shader != target_shader) { + if(current_shader) + gPipeline.unbindDeferredShader(*current_shader); gPipeline.bindDeferredShader(*target_shader); } } @@ -448,7 +454,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) // (this way we won't rebind shaders unnecessarily). if(current_shader != target_shader) { - target_shader->bind(); + if(current_shader) + gPipeline.unbindDeferredShader(*current_shader); + gPipeline.bindDeferredShader(*target_shader); } } current_shader = target_shader; @@ -523,9 +531,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) } } - static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_PUSH("Alpha Push Verts"); + static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_PUSH("Alpha Push Verts"); { - LLFastTimer t(FTM_RENDER_ALPHA_PUSH); + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_PUSH); gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); // Singu Note: If using shaders, pull the attribute mask from it, else used passed base mask. @@ -545,20 +553,21 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow) - emissive_shader->bind(); - + //emissive_shader->bind(); + // glow doesn't use vertex colors from the mesh data // Singu Note: Pull attribs from shader, since we always have one here. - params.mVertexBuffer->setBuffer(emissive_shader->mAttributeMask); - + // Singu Note: To avoid ridiculous shader bind cost, simply re-use prior shader, but let llvertexbuffer replace the color attrib ptr with the emissive one. + params.mVertexBuffer->setBuffer(current_shader->mAttributeMask | LLVertexBuffer::MAP_EMISSIVE); + // do the actual drawing, again params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + //current_shader->bind(); + // restore our alpha blend mode gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - - current_shader->bind(); } if (tex_setup) @@ -570,13 +579,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) } } } + if (!light_enabled) + { + gPipeline.enableLightsDynamic(light_state); + } gGL.setSceneBlendType(LLRender::BT_ALPHA); LLVertexBuffer::unbind(); - - if (!light_enabled) - { - gPipeline.enableLightsDynamic(); - } } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 9831a0875f..47f55ef690 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "lldrawpoolavatar.h" +#include "llskinningutil.h" #include "llrender.h" #include "llvoavatar.h" @@ -70,6 +71,7 @@ F32 LLDrawPoolAvatar::sMinimumAlpha = 0.2f; static bool is_deferred_render = false; static bool is_post_deferred_render = false; +static bool is_mats_render = false; extern BOOL gUseGLPick; @@ -107,13 +109,39 @@ S32 normal_channel = -1; S32 specular_channel = -1; S32 cube_channel = -1; -static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_AVATAR("Avatar Shadow"); LLDrawPoolAvatar::LLDrawPoolAvatar() : LLFacePool(POOL_AVATAR) { } +LLDrawPoolAvatar::~LLDrawPoolAvatar() +{ + if (!isDead()) + { + LL_WARNS() << "Destroying avatar drawpool that still contains faces" << LL_ENDL; + } +} + +// virtual +BOOL LLDrawPoolAvatar::isDead() +{ + if (!LLFacePool::isDead()) + { + return FALSE; + } + + for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i) + { + if (mRiggedFace[i].size() > 0) + { + return FALSE; + } + } + return TRUE; +} + //----------------------------------------------------------------------------- // instancePool() //----------------------------------------------------------------------------- @@ -165,7 +193,7 @@ const LLMatrix4a& LLDrawPoolAvatar::getModelView() //----------------------------------------------------------------------------- void LLDrawPoolAvatar::beginDeferredPass(S32 pass) { - LLFastTimer t(FTM_RENDER_CHARACTERS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); sSkipTransparent = TRUE; is_deferred_render = true; @@ -200,7 +228,7 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) void LLDrawPoolAvatar::endDeferredPass(S32 pass) { - LLFastTimer t(FTM_RENDER_CHARACTERS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); sSkipTransparent = FALSE; is_deferred_render = false; @@ -290,7 +318,7 @@ void LLDrawPoolAvatar::beginDeferredRiggedAlpha() sVertexProgram = &gDeferredSkinnedAlphaProgram; gPipeline.bindDeferredShader(*sVertexProgram); sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - gPipeline.enableLightsDynamic(); + gPipeline.enableLightsDynamic(*(LLGLState*)gPipeline.pushRenderPassState()); } void LLDrawPoolAvatar::beginDeferredRiggedMaterialAlpha(S32 pass) @@ -312,7 +340,7 @@ void LLDrawPoolAvatar::beginDeferredRiggedMaterialAlpha(S32 pass) sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); - gPipeline.enableLightsDynamic(); + gPipeline.enableLightsDynamic(*(LLGLState*)gPipeline.pushRenderPassState()); } void LLDrawPoolAvatar::endDeferredRiggedAlpha() { @@ -365,7 +393,7 @@ void LLDrawPoolAvatar::endPostDeferredAlpha() void LLDrawPoolAvatar::renderPostDeferred(S32 pass) { - const S32 actual_pass[] = + static const S32 actual_pass[] = { //map post deferred pass numbers to what render() expects 2, //skinned 4, // rigged fullbright @@ -399,7 +427,7 @@ S32 LLDrawPoolAvatar::getNumShadowPasses() void LLDrawPoolAvatar::beginShadowPass(S32 pass) { - LLFastTimer t(FTM_SHADOW_AVATAR); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); if (pass == 0) { @@ -425,7 +453,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) void LLDrawPoolAvatar::endShadowPass(S32 pass) { - LLFastTimer t(FTM_SHADOW_AVATAR); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); if (pass == 0) { if (sShaderLevel > 0) @@ -444,7 +472,7 @@ void LLDrawPoolAvatar::endShadowPass(S32 pass) void LLDrawPoolAvatar::renderShadow(S32 pass) { - LLFastTimer t(FTM_SHADOW_AVATAR); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); if (mDrawFace.empty()) { @@ -458,7 +486,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) } LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); - if (avatarp->isDead() || avatarp->mIsDummy || avatarp->mDrawable.isNull()) + if (avatarp->isDead() || avatarp->isUIAvatar() || avatarp->mDrawable.isNull()) { return; } @@ -510,7 +538,7 @@ S32 LLDrawPoolAvatar::getNumDeferredPasses() void LLDrawPoolAvatar::render(S32 pass) { - LLFastTimer t(FTM_RENDER_CHARACTERS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); if (LLPipeline::sImpostorRender) { renderAvatars(NULL, pass+2); @@ -522,7 +550,7 @@ void LLDrawPoolAvatar::render(S32 pass) void LLDrawPoolAvatar::beginRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_CHARACTERS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); //reset vertex buffer mappings LLVertexBuffer::unbind(); @@ -573,7 +601,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) void LLDrawPoolAvatar::endRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_CHARACTERS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); if (LLPipeline::sImpostorRender) { @@ -629,7 +657,7 @@ void LLDrawPoolAvatar::beginImpostor() gImpostorProgram.setMinimumAlpha(0.01f); } - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + gPipeline.enableLightsFullbright(*(LLGLState*)gPipeline.pushRenderPassState()); sDiffuseChannel = 0; } @@ -639,7 +667,6 @@ void LLDrawPoolAvatar::endImpostor() { gImpostorProgram.unbind(); } - gPipeline.enableLightsDynamic(); } void LLDrawPoolAvatar::beginRigid() @@ -918,7 +945,7 @@ void LLDrawPoolAvatar::beginRiggedShinySimple() llassert_always(sVertexProgram->mProgramObject > 0); sVertexProgram->bind(); - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); } void LLDrawPoolAvatar::endRiggedShinySimple() @@ -928,7 +955,7 @@ void LLDrawPoolAvatar::endRiggedShinySimple() if(!sVertexProgram) return; - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); sVertexProgram->unbind(); sVertexProgram = NULL; } @@ -951,7 +978,7 @@ void LLDrawPoolAvatar::beginRiggedFullbrightShiny() llassert_always(sVertexProgram->mProgramObject > 0); sVertexProgram->bind(); - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred) { sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); @@ -971,7 +998,7 @@ void LLDrawPoolAvatar::endRiggedFullbrightShiny() if(!sVertexProgram) return; - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); sVertexProgram->unbind(); sVertexProgram = NULL; } @@ -1073,11 +1100,11 @@ void LLDrawPoolAvatar::endDeferredSkinned() gGL.getTexUnit(0)->activate(); } -static LLFastTimer::DeclareTimer FTM_RENDER_AVATARS("renderAvatars"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_AVATARS("renderAvatars"); void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) { - LLFastTimer t(FTM_RENDER_AVATARS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_AVATARS); if (pass == -1) { @@ -1271,7 +1298,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) renderRiggedAlpha(avatarp); if (LLPipeline::sRenderDeferred && !is_post_deferred_render) { //render transparent materials under water - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.setColorMask(true, true); gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA, @@ -1303,7 +1330,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) case 12: p = 13; break; } { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; renderDeferredRiggedMaterial(avatarp, p); } return; @@ -1402,6 +1429,16 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer } //LL_INFOS() << "Rebuilt face " << face->getTEOffset() << " of " << face->getDrawable() << " at " << gFrameTimeSeconds << LL_ENDL; + + // Let getGeometryVolume know if a texture matrix is in play + if (face->mTextureMatrix) + { + face->setState(LLFace::TEXTURE_ANIM); + } + else + { + face->clearState(LLFace::TEXTURE_ANIM); + } face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_inv_trans, offset, true); buffer->flush(); @@ -1409,16 +1446,29 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) { - LLVector4a* weight = vol_face.mWeights; - if (!weight) + LLVector4a* weights = vol_face.mWeights; + if (!weights) { return; } + // FIXME ugly const cast + LLSkinningUtil::scrubInvalidJoints(avatar, const_cast(skin)); LLPointer buffer = face->getVertexBuffer(); LLDrawable* drawable = face->getDrawable(); + if (drawable->getVOVolume() && drawable->getVOVolume()->isNoLOD()) + { + return; + } + U32 data_mask = face->getRiggedVertexBufferDataMask(); + + if (!vol_face.mWeightsScrubbed) + { + LLSkinningUtil::scrubSkinWeights(weights, vol_face.mNumVertices, skin); + vol_face.mWeightsScrubbed = TRUE; + } if (buffer.isNull() || buffer->getTypeMask() != data_mask || @@ -1451,13 +1501,16 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime()) { - avatar->updateSoftwareSkinnedVertices(skin, weight, vol_face, buffer); + avatar->updateSoftwareSkinnedVertices(skin, weights, vol_face, buffer); } } +extern int sMaxCacheHit; +extern int sCurCacheHit; + void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { - if ((avatar->isSelf() && !gAgent.needsRenderAvatar()) || !gMeshRepo.meshRezEnabled()) + if (!avatar->shouldRenderRigged() || !gMeshRepo.meshRezEnabled()) { return; } @@ -1488,13 +1541,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) continue; } - LLUUID mesh_id = volume->getParams().getSculptID(); - if (mesh_id.isNull()) - { - continue; - } - - const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, vobj); + const LLMeshSkinInfo* skin = vobj->getSkinInfo(); if (!skin) { continue; @@ -1514,59 +1561,62 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) if (buff) { if (sShaderLevel > 0) - { //upload matrix palette to shader - LLMatrix4 mat[JOINT_COUNT]; - - U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT); - - for (U32 i = 0; i < count; ++i) + { + static LLCachedControl sh_use_rigging_cache("SHUseRiggedMatrixCache", true); + auto& mesh_cache = avatar->getRiggedMatrixCache();; + auto rigged_matrix_data_iter = mesh_cache.cend(); + if (sh_use_rigging_cache) { - LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); - if(!joint) - { - joint = avatar->getJoint("mRoot"); - } - if (joint) - { - LLMatrix4a tmp; - tmp.loadu((F32*)skin->mInvBindMatrix[i].mMatrix); - tmp.setMul(joint->getWorldMatrix(),tmp); - mat[i] = LLMatrix4(tmp.getF32ptr()); - } + auto& mesh_id = skin->mMeshID; + rigged_matrix_data_iter = find_if(mesh_cache.begin(), mesh_cache.end(), [&mesh_id](decltype(mesh_cache[0]) & entry) { return entry.first == mesh_id; }); + } - - stop_glerror(); - - F32 mp[JOINT_COUNT*12]; - - for (U32 i = 0; i < count; ++i) + if (rigged_matrix_data_iter != avatar->getRiggedMatrixCache().cend()) { - F32* m = (F32*) mat[i].mMatrix; + LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + rigged_matrix_data_iter->second.first, + FALSE, + (GLfloat*)rigged_matrix_data_iter->second.second.data()); + LLDrawPoolAvatar::sVertexProgram->uniform1f(LLShaderMgr::AVATAR_MAX_WEIGHT, F32(rigged_matrix_data_iter->second.first - 1)); + } + else + { + // upload matrix palette to shader + LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; + U32 count = LLSkinningUtil::getMeshJointCount(skin); + LLSkinningUtil::initSkinningMatrixPalette(mat, count, skin, avatar); - U32 idx = i*12; + std::array mp; - mp[idx+0] = m[0]; - mp[idx+1] = m[1]; - mp[idx+2] = m[2]; - mp[idx+3] = m[12]; + for (U32 i = 0; i < count; ++i) + { + F32* m = (F32*)mat[i].getF32ptr(); - mp[idx+4] = m[4]; - mp[idx+5] = m[5]; - mp[idx+6] = m[6]; - mp[idx+7] = m[13]; + U32 idx = i * 12; - mp[idx+8] = m[8]; - mp[idx+9] = m[9]; - mp[idx+10] = m[10]; - mp[idx+11] = m[14]; - } + mp[idx + 0] = m[0]; + mp[idx + 1] = m[1]; + mp[idx + 2] = m[2]; + mp[idx + 3] = m[12]; - LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, - count, - FALSE, - (GLfloat*) mp); + mp[idx + 4] = m[4]; + mp[idx + 5] = m[5]; + mp[idx + 6] = m[6]; + mp[idx + 7] = m[13]; - LLDrawPoolAvatar::sVertexProgram->uniform1f(LLShaderMgr::AVATAR_MAX_WEIGHT, F32(count-1)); + mp[idx + 8] = m[8]; + mp[idx + 9] = m[9]; + mp[idx + 10] = m[10]; + mp[idx + 11] = m[14]; + } + if (sh_use_rigging_cache) + mesh_cache.emplace_back(std::make_pair( skin->mMeshID, std::make_pair(count, mp) ) ); + LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + count, + FALSE, + (GLfloat*)mp.data()); + LLDrawPoolAvatar::sVertexProgram->uniform1f(LLShaderMgr::AVATAR_MAX_WEIGHT, F32(count - 1)); + } stop_glerror(); } @@ -1588,14 +1638,14 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) const LLTextureEntry* te = face->getTextureEntry(); LLMaterial* mat = te->getMaterialParams().get(); - if (mat && is_deferred_render) + if (mat && is_mats_render) { gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(LLRender::DIFFUSE_MAP)); gGL.getTexUnit(normal_channel)->bind(face->getTexture(LLRender::NORMAL_MAP)); gGL.getTexUnit(specular_channel)->bind(face->getTexture(LLRender::SPECULAR_MAP)); LLColor4 col = mat->getSpecularLightColor(); - F32 spec = llmax(0.0001f, mat->getSpecularLightExponent() / 255.f); + F32 spec = llmax(0.0000f, mat->getSpecularLightExponent() / 255.f); F32 env = mat->getEnvironmentIntensity()/255.f; @@ -1616,6 +1666,10 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()/255.f); } + else if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE) + { + sVertexProgram->setMinimumAlpha(0.f); + } else { sVertexProgram->setMinimumAlpha(0.004f); @@ -1640,6 +1694,10 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()/255.f); } + else if (mat && (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE)) + { + sVertexProgram->setMinimumAlpha(0.f); + } else { sVertexProgram->setMinimumAlpha(0.004f); @@ -1654,7 +1712,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) if (face->mTextureMatrix && vobj->mTexAnimMode) { - gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.matrixMode(LLRender::MM_TEXTURE0 + sDiffuseChannel); gGL.loadMatrix(*face->mTextureMatrix); buff->setBuffer(data_mask); buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); @@ -1684,14 +1742,16 @@ void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar) void LLDrawPoolAvatar::renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass) { + is_mats_render = true; renderRigged(avatar, pass); + is_mats_render = false; } -static LLFastTimer::DeclareTimer FTM_RIGGED_VBO("Rigged VBO"); +static LLTrace::BlockTimerStatHandle FTM_RIGGED_VBO("Rigged VBO"); void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) { - LLFastTimer t(FTM_RIGGED_VBO); + LL_RECORD_BLOCK_TIME(FTM_RIGGED_VBO); //update rigged vertex buffers for (U32 type = 0; type < NUM_RIGGED_PASSES; ++type) @@ -1707,7 +1767,7 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) LLVOVolume* vobj = drawable->getVOVolume(); - if (!vobj) + if (!vobj || vobj->isNoLOD()) { continue; } @@ -1720,13 +1780,7 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) continue; } - LLUUID mesh_id = volume->getParams().getSculptID(); - if (mesh_id.isNull()) - { - continue; - } - - const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, vobj); + const LLMeshSkinInfo* skin = vobj->getSkinInfo(); if (!skin) { continue; @@ -1765,7 +1819,7 @@ void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar) { if (!mRiggedFace[RIGGED_ALPHA].empty()) { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.setColorMask(true, true); gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, @@ -1783,7 +1837,7 @@ void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar) { if (!mRiggedFace[RIGGED_FULLBRIGHT_ALPHA].empty()) { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.setColorMask(true, true); gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, @@ -1801,12 +1855,12 @@ void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) { if (!mRiggedFace[RIGGED_GLOW].empty()) { - LLGLEnable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); + LLGLEnable blend; + LLGLDisable test; gGL.flush(); - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); + LLGLEnable polyOffset; + gGL.setPolygonOffset(-1.0f, -1.0f); gGL.setSceneBlendType(LLRender::BT_ADD); LLGLDepthTest depth(GL_TRUE, GL_FALSE); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index bf4a147547..acc11a95ee 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -42,7 +42,7 @@ class LLMeshSkinInfo; class LLVolume; class LLVolumeFace; -const U32 JOINT_COUNT = 52; +constexpr U32 JOINT_COUNT = 52; class LLDrawPoolAvatar : public LLFacePool { @@ -67,6 +67,8 @@ class LLDrawPoolAvatar : public LLFacePool virtual S32 getVertexShaderLevel() const; LLDrawPoolAvatar(); + ~LLDrawPoolAvatar(); + /*virtual*/ BOOL isDead(); static const LLMatrix4a& getModelView(); diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 81cbfd0759..d9a9365cf0 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -241,7 +241,7 @@ S32 LLDrawPoolBump::getNumPasses() void LLDrawPoolBump::beginRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_BUMP); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); switch( pass ) { case 0: @@ -268,7 +268,7 @@ void LLDrawPoolBump::beginRenderPass(S32 pass) void LLDrawPoolBump::render(S32 pass) { - LLFastTimer t(FTM_RENDER_BUMP); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) { @@ -301,7 +301,7 @@ void LLDrawPoolBump::render(S32 pass) void LLDrawPoolBump::endRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_BUMP); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); switch( pass ) { case 0: @@ -330,11 +330,10 @@ void LLDrawPoolBump::endRenderPass(S32 pass) } //static -void LLDrawPoolBump::beginShiny(bool invisible) +void LLDrawPoolBump::beginShiny() { - LLFastTimer t(FTM_RENDER_SHINY); - if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| - (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) + LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); + if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)) { return; } @@ -342,7 +341,7 @@ void LLDrawPoolBump::beginShiny(bool invisible) mShiny = TRUE; sVertexMask = VERTEX_MASK_SHINY; // Second pass: environment map - if (!invisible && mVertexShaderLevel > 1) + if (mVertexShaderLevel > 1) { sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; } @@ -357,7 +356,7 @@ void LLDrawPoolBump::beginShiny(bool invisible) shader = NULL; } - bindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible); + bindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel); if (mVertexShaderLevel > 1) { //indexed texture rendering, channel 0 is always diffuse @@ -366,12 +365,12 @@ void LLDrawPoolBump::beginShiny(bool invisible) } //static -void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible) +void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel) { LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if( cube_map ) { - if (!invisible && shader ) + if (shader) { LLMatrix4 mat(gGLModelView.getF32ptr()); LLVector3 vec = LLVector3(gShinyOrigin) * mat; @@ -412,40 +411,35 @@ void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& di } } -void LLDrawPoolBump::renderShiny(bool invisible) +void LLDrawPoolBump::renderShiny() { - LLFastTimer t(FTM_RENDER_SHINY); - if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| - (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) + LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); + if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)) { return; } if( gSky.mVOSkyp->getCubeMap() ) { - LLGLEnable blend_enable(GL_BLEND); - if (!invisible && mVertexShaderLevel > 1) + LLGLEnable blend_enable; + if (mVertexShaderLevel > 1) { LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } - else if (!invisible) + else { renderGroups(LLRenderPass::PASS_SHINY, sVertexMask); } - //else // invisible (deprecated) - //{ - //renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask); - //} } } //static -void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible) +void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel) { LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if( cube_map ) { - if (!invisible && shader_level > 1) + if (shader_level > 1) { shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); @@ -473,16 +467,15 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& } } -void LLDrawPoolBump::endShiny(bool invisible) +void LLDrawPoolBump::endShiny() { - LLFastTimer t(FTM_RENDER_SHINY); - if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| - (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) + LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); + if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)) { return; } - unbindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible); + unbindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel); if (shader) { shader->unbind(); @@ -495,7 +488,7 @@ void LLDrawPoolBump::endShiny(bool invisible) void LLDrawPoolBump::beginFullbrightShiny() { - LLFastTimer t(FTM_RENDER_SHINY); + LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY)) { return; @@ -546,7 +539,7 @@ void LLDrawPoolBump::beginFullbrightShiny() void LLDrawPoolBump::renderFullbrightShiny() { - LLFastTimer t(FTM_RENDER_SHINY); + LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY)) { return; @@ -554,7 +547,7 @@ void LLDrawPoolBump::renderFullbrightShiny() if( gSky.mVOSkyp->getCubeMap() ) { - LLGLEnable blend_enable(GL_BLEND); + LLGLEnable blend_enable; gGL.setSceneBlendType(LLRender::BT_REPLACE); if (mVertexShaderLevel > 1) @@ -571,7 +564,7 @@ void LLDrawPoolBump::renderFullbrightShiny() void LLDrawPoolBump::endFullbrightShiny() { - LLFastTimer t(FTM_RENDER_SHINY); + LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY)) { return; @@ -702,7 +695,7 @@ void LLDrawPoolBump::beginBump(U32 pass) } sVertexMask = VERTEX_MASK_BUMP; - LLFastTimer t(FTM_RENDER_BUMP); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); // Optional second pass: emboss bump map stop_glerror(); @@ -754,14 +747,14 @@ void LLDrawPoolBump::renderBump(U32 pass) return; } - LLFastTimer ftm(FTM_RENDER_BUMP); - LLGLDisable fog(GL_FOG); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); + LLGLDisable fog; LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LEQUAL); - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.diffuseColor4f(1,1,1,1); /// Get rid of z-fighting with non-bump pass. - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); + LLGLEnable polyOffset; + gGL.setPolygonOffset(-1.0f, -1.0f); renderBump(pass, sVertexMask); } @@ -804,7 +797,7 @@ void LLDrawPoolBump::beginDeferredPass(S32 pass) { return; } - LLFastTimer ftm(FTM_RENDER_BUMP); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); mShiny = TRUE; gDeferredBumpProgram.bind(); diffuse_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); @@ -819,7 +812,7 @@ void LLDrawPoolBump::endDeferredPass(S32 pass) { return; } - LLFastTimer ftm(FTM_RENDER_BUMP); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); mShiny = FALSE; gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::BUMP_MAP); @@ -833,7 +826,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass) { return; } - LLFastTimer ftm(FTM_RENDER_BUMP); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); U32 type = LLRenderPass::PASS_BUMP; LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); @@ -1075,7 +1068,7 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText } -static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_STANDARD_LOADED("Bump Standard Callback"); +static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_STANDARD_LOADED("Bump Standard Callback"); // static void LLBumpImageList::onSourceBrightnessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) @@ -1099,22 +1092,22 @@ void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerFetchedTextu } } -static LLFastTimer::DeclareTimer FTM_BUMP_GEN_NORMAL("Generate Normal Map"); -static LLFastTimer::DeclareTimer FTM_BUMP_CREATE_TEXTURE("Create GL Normal Map"); +static LLTrace::BlockTimerStatHandle FTM_BUMP_GEN_NORMAL("Generate Normal Map"); +static LLTrace::BlockTimerStatHandle FTM_BUMP_CREATE_TEXTURE("Create GL Normal Map"); void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) { if (success && LLPipeline::sRenderDeferred) { - LLFastTimer t(FTM_BUMP_SOURCE_STANDARD_LOADED); + LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_STANDARD_LOADED); LLPointer nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4); { - LLFastTimer t(FTM_BUMP_GEN_NORMAL); + LL_RECORD_BLOCK_TIME(FTM_BUMP_GEN_NORMAL); generateNormalMapFromAlpha(src, nrm_image); } src_vi->setExplicitFormat(GL_RGBA, GL_RGBA); { - LLFastTimer t(FTM_BUMP_CREATE_TEXTURE); + LL_RECORD_BLOCK_TIME(FTM_BUMP_CREATE_TEXTURE); src_vi->createGLTexture(src_vi->getDiscardLevel(), nrm_image); } } @@ -1176,27 +1169,27 @@ void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nr } -static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_LOADED("Bump Source Loaded"); -static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_ENTRIES_UPDATE("Entries Update"); -static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_MIN_MAX("Min/Max"); -static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_RGB2LUM("RGB to Luminance"); -static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_RESCALE("Rescale"); -static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_GEN_NORMAL("Generate Normal"); -static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_CREATE("Bump Source Create"); +static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_LOADED("Bump Source Loaded"); +static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_ENTRIES_UPDATE("Entries Update"); +static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_MIN_MAX("Min/Max"); +static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_RGB2LUM("RGB to Luminance"); +static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_RESCALE("Rescale"); +static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_GEN_NORMAL("Generate Normal"); +static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_CREATE("Bump Source Create"); // static void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code ) { if( success ) { - LLFastTimer t(FTM_BUMP_SOURCE_LOADED); + LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_LOADED); bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries ); bump_image_map_t::iterator iter = entries_list.find(source_asset_id); { - LLFastTimer t(FTM_BUMP_SOURCE_ENTRIES_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_ENTRIES_UPDATE); if (iter == entries_list.end() || iter->second.isNull() || iter->second->getWidth() != src->getWidth() || @@ -1239,7 +1232,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI case 1: case 2: { - LLFastTimer t(FTM_BUMP_SOURCE_MIN_MAX); + LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_MIN_MAX); if( src_data_size == dst_data_size * src_components ) { for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components ) @@ -1265,7 +1258,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI case 3: case 4: { - LLFastTimer t(FTM_BUMP_SOURCE_RGB2LUM); + LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_RGB2LUM); if( src_data_size == dst_data_size * src_components ) { for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components ) @@ -1298,7 +1291,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI if( maximum > minimum ) { - LLFastTimer t(FTM_BUMP_SOURCE_RESCALE); + LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_RESCALE); U8 bias_and_scale_lut[256]; F32 twice_one_over_range = 2.f / (maximum - minimum); S32 i; @@ -1335,7 +1328,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI if (!LLPipeline::sRenderDeferred) { - LLFastTimer t(FTM_BUMP_SOURCE_CREATE); + LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_CREATE); bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); bump->createGLTexture(0, dst_image); } @@ -1346,18 +1339,18 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI bump->getGLTexture()->setAllowCompression(false); { - LLFastTimer t(FTM_BUMP_SOURCE_CREATE); + LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_CREATE); bump->setExplicitFormat(GL_RGBA8, GL_ALPHA); bump->createGLTexture(0, dst_image); } { - LLFastTimer t(FTM_BUMP_SOURCE_GEN_NORMAL); + LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_GEN_NORMAL); gPipeline.mScreen.bindTarget(); LLGLDepthTest depth(GL_FALSE); - LLGLDisable cull(GL_CULL_FACE); - LLGLDisable blend(GL_BLEND); + LLGLDisable cull; + LLGLDisable blend; gGL.setColorMask(TRUE, TRUE); gNormalMapGenProgram.bind(); @@ -1380,7 +1373,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI S32 screen_width = gPipeline.mScreen.getWidth(); S32 screen_height = gPipeline.mScreen.getHeight(); - glViewport(0, 0, screen_width, screen_height); + gGL.setViewport(0, 0, screen_width, screen_height); for (S32 left = 0; left < width; left += screen_width) { @@ -1545,76 +1538,3 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL gGL.matrixMode(LLRender::MM_MODELVIEW); } } - -void LLDrawPoolInvisible::render(S32 pass) -{ //render invisiprims - LLFastTimer t(FTM_RENDER_INVISIBLE); - - if (LLGLSLShader::sNoFixedFunction) - { - gOcclusionProgram.bind(); - } - - U32 invisi_mask = LLVertexBuffer::MAP_VERTEX; - glStencilMask(0); - gGL.setColorMask(false, false); - pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE); - gGL.setColorMask(true, false); - glStencilMask(0xFFFFFFFF); - - if (LLGLSLShader::sNoFixedFunction) - { - gOcclusionProgram.unbind(); - } - - /*if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) // invisible (deprecated) - { - beginShiny(true); - renderShiny(true); - endShiny(true); - }*/ -} - -void LLDrawPoolInvisible::beginDeferredPass(S32 pass) -{ - static const LLCachedControl enable("SianaRenderDeferredInvisiprim"); - if (!enable) - { - return; - } - beginRenderPass(pass); -} - -void LLDrawPoolInvisible::endDeferredPass( S32 pass ) -{ - endRenderPass(pass); -} - -void LLDrawPoolInvisible::renderDeferred( S32 pass ) -{ //render invisiprims; this doesn't work becaue it also blocks all the post-deferred stuff - static const LLCachedControl enable("SianaRenderDeferredInvisiprim"); - if (!enable) - { - return; - } - - LLFastTimer t(FTM_RENDER_INVISIBLE); - - gOcclusionProgram.bind(); - - U32 invisi_mask = LLVertexBuffer::MAP_VERTEX; - glStencilMask(0); - gGL.setColorMask(false, false); - pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE); - gGL.setColorMask(true, true); - glStencilMask(0xFFFFFFFF); - - gOcclusionProgram.unbind(); - - /*if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) // invisible (deprecated) - { - beginShiny(true); - renderShiny(true); - endShiny(true); - }*/ -} diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index 2611730ee9..e51e566276 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -68,9 +68,9 @@ protected : S32 numBumpPasses(); - void beginShiny(bool invisible = false); - void renderShiny(bool invisible = false); - void endShiny(bool invisible = false); + void beginShiny(); + void renderShiny(); + void endShiny(); void beginFullbrightShiny(); void renderFullbrightShiny(); @@ -80,8 +80,8 @@ protected : void renderBump(U32 pass = LLRenderPass::PASS_BUMP); void endBump(U32 pass = LLRenderPass::PASS_BUMP); - static void bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible); - static void unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible); + static void bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel); + static void unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel); virtual S32 getNumDeferredPasses(); /*virtual*/ void beginDeferredPass(S32 pass); @@ -173,30 +173,4 @@ class LLBumpImageList extern LLBumpImageList gBumpImageList; -class LLDrawPoolInvisible : public LLDrawPoolBump -{ -public: - LLDrawPoolInvisible() : LLDrawPoolBump(LLDrawPool::POOL_INVISIBLE) { } - - enum - { - VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX - }; - - virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } - - virtual void prerender() { } - - virtual void render(S32 pass = 0); - virtual void beginRenderPass( S32 pass ) { } - virtual void endRenderPass( S32 pass ) { } - virtual S32 getNumPasses() {return 1;} - - virtual S32 getNumDeferredPasses() { return 1; } - /*virtual*/ void beginDeferredPass(S32 pass); - /*virtual*/ void endDeferredPass(S32 pass); - /*virtual*/ void renderDeferred(S32 pass); -}; - - #endif // LL_LLDRAWPOOLBUMP_H diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp index 2f5849bb07..d3d63a7922 100644 --- a/indra/newview/lldrawpoolground.cpp +++ b/indra/newview/lldrawpoolground.cpp @@ -83,8 +83,6 @@ void LLDrawPoolGround::render(S32 pass) LLFace *facep = mDrawFace[0]; - gPipeline.disableLights(); - LLOverrideFaceColor col(this, gSky.mVOSkyp->getGLFogColor()); facep->renderIndexed(); diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 6b29986170..5b15f78af0 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -82,12 +82,12 @@ void LLDrawPoolMaterials::beginDeferredPass(S32 pass) diffuse_channel = mShader->enableTexture(LLShaderMgr::DIFFUSE_MAP); - LLFastTimer t(FTM_RENDER_MATERIALS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_MATERIALS); } void LLDrawPoolMaterials::endDeferredPass(S32 pass) { - LLFastTimer t(FTM_RENDER_MATERIALS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_MATERIALS); mShader->unbind(); diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index 2baf675fda..ff864fb852 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -40,8 +40,8 @@ static LLGLSLShader* simple_shader = NULL; static LLGLSLShader* fullbright_shader = NULL; -static LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE_DEFERRED("Deferred Simple"); -static LLFastTimer::DeclareTimer FTM_RENDER_GRASS_DEFERRED("Deferred Grass"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_SIMPLE_DEFERRED("Deferred Simple"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_GRASS_DEFERRED("Deferred Grass"); void LLDrawPoolGlow::beginPostDeferredPass(S32 pass) { @@ -49,24 +49,24 @@ void LLDrawPoolGlow::beginPostDeferredPass(S32 pass) gDeferredEmissiveProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); } -static LLFastTimer::DeclareTimer FTM_RENDER_GLOW_PUSH("Glow Push"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_GLOW_PUSH("Glow Push"); void LLDrawPoolGlow::renderPostDeferred(S32 pass) { - LLFastTimer t(FTM_RENDER_GLOW); - LLGLEnable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW); + LLGLEnable blend; + LLGLDisable test; gGL.flush(); /// Get rid of z-fighting with non-glow pass. - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); + LLGLEnable polyOffset; + gGL.setPolygonOffset(-1.0f, -1.0f); gGL.setSceneBlendType(LLRender::BT_ADD); LLGLDepthTest depth(GL_TRUE, GL_FALSE); gGL.setColorMask(false, true); { - LLFastTimer t(FTM_RENDER_GLOW_PUSH); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW_PUSH); pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } @@ -94,13 +94,13 @@ S32 LLDrawPoolGlow::getNumPasses() void LLDrawPoolGlow::render(S32 pass) { - LLFastTimer t(FTM_RENDER_GLOW); - LLGLEnable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW); + LLGLEnable blend; + LLGLDisable test; gGL.flush(); /// Get rid of z-fighting with non-glow pass. - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); + LLGLEnable polyOffset; + gGL.setPolygonOffset(-1.0f, -1.0f); gGL.setSceneBlendType(LLRender::BT_ADD); U32 shader_level = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); @@ -152,7 +152,7 @@ void LLDrawPoolSimple::prerender() void LLDrawPoolSimple::beginRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_SIMPLE); + LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE); simple_shader = &gObjectSimpleProgram[LLPipeline::sUnderWaterRender< blend; { //render simple - LLFastTimer t(FTM_RENDER_SIMPLE); - gPipeline.enableLightsDynamic(); + LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE); + LLGLState lighting; + gPipeline.enableLightsDynamic(lighting); if (mVertexShaderLevel > 0) { @@ -208,7 +209,7 @@ void LLDrawPoolSimple::render(S32 pass) } else { - LLGLDisable alpha_test(GL_ALPHA_TEST); + LLGLDisable alpha_test; renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); } @@ -224,7 +225,7 @@ void LLDrawPoolSimple::render(S32 pass) -static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_MASK("Alpha Mask"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK("Alpha Mask"); LLDrawPoolAlphaMask::LLDrawPoolAlphaMask() : LLRenderPass(POOL_ALPHA_MASK) @@ -238,7 +239,7 @@ void LLDrawPoolAlphaMask::prerender() void LLDrawPoolAlphaMask::beginRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_ALPHA_MASK); + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK); simple_shader = &gObjectSimpleProgram[1< blend; + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK); if (mVertexShaderLevel > 0) { @@ -286,7 +287,7 @@ void LLDrawPoolAlphaMask::render(S32 pass) } else { - LLGLEnable test(GL_ALPHA_TEST); + LLGLEnable test; pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask(), TRUE, FALSE); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK } @@ -304,7 +305,7 @@ void LLDrawPoolFullbrightAlphaMask::prerender() void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_ALPHA_MASK); + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK); simple_shader = &gObjectFullbrightProgram[1< 0) { @@ -356,10 +357,10 @@ void LLDrawPoolFullbrightAlphaMask::render(S32 pass) } else { - LLGLEnable test(GL_ALPHA_TEST); - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + LLGLEnable test; + LLGLState lighting; + gPipeline.enableLightsFullbright(lighting); pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask(), TRUE, FALSE); - gPipeline.enableLightsDynamic(); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK } } @@ -370,13 +371,13 @@ void LLDrawPoolFullbrightAlphaMask::render(S32 pass) void LLDrawPoolSimple::beginDeferredPass(S32 pass) { - LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED); + LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED); gDeferredDiffuseProgram.bind(); } void LLDrawPoolSimple::endDeferredPass(S32 pass) { - LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED); + LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED); LLRenderPass::endRenderPass(pass); gDeferredDiffuseProgram.unbind(); @@ -384,16 +385,16 @@ void LLDrawPoolSimple::endDeferredPass(S32 pass) void LLDrawPoolSimple::renderDeferred(S32 pass) { - LLGLDisable blend(GL_BLEND); - LLGLDisable alpha_test(GL_ALPHA_TEST); + LLGLDisable blend; + LLGLDisable alpha_test; { //render simple - LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED); + LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED); pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } } -static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_MASK_DEFERRED("Deferred Alpha Mask"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_DEFERRED("Deferred Alpha Mask"); void LLDrawPoolAlphaMask::beginDeferredPass(S32 pass) { @@ -407,7 +408,7 @@ void LLDrawPoolAlphaMask::endDeferredPass(S32 pass) void LLDrawPoolAlphaMask::renderDeferred(S32 pass) { - LLFastTimer t(FTM_RENDER_ALPHA_MASK_DEFERRED); + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_DEFERRED); gDeferredDiffuseAlphaMaskProgram.bind(); gDeferredDiffuseAlphaMaskProgram.setMinimumAlpha(0.33f); pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); @@ -430,7 +431,7 @@ void LLDrawPoolGrass::prerender() void LLDrawPoolGrass::beginRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_GRASS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GRASS); stop_glerror(); if (LLPipeline::sUnderWaterRender) @@ -456,7 +457,7 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass) void LLDrawPoolGrass::endRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_GRASS); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GRASS); LLRenderPass::endRenderPass(pass); if (mVertexShaderLevel > 0) @@ -471,11 +472,11 @@ void LLDrawPoolGrass::endRenderPass(S32 pass) void LLDrawPoolGrass::render(S32 pass) { - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; { - LLFastTimer t(FTM_RENDER_GRASS); - LLGLEnable test(GL_ALPHA_TEST); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GRASS); + LLGLEnable test; gGL.setSceneBlendType(LLRender::BT_ALPHA); //render grass LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); @@ -495,7 +496,7 @@ void LLDrawPoolGrass::endDeferredPass(S32 pass) void LLDrawPoolGrass::renderDeferred(S32 pass) { { - LLFastTimer t(FTM_RENDER_GRASS_DEFERRED); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GRASS_DEFERRED); gDeferredNonIndexedDiffuseAlphaMaskProgram.bind(); gDeferredNonIndexedDiffuseAlphaMaskProgram.setMinimumAlpha(0.5f); //render grass @@ -536,9 +537,9 @@ void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass) void LLDrawPoolFullbright::renderPostDeferred(S32 pass) { - LLFastTimer t(FTM_RENDER_FULLBRIGHT); + LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT); gGL.setColorMask(true, true); - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE); @@ -561,14 +562,14 @@ void LLDrawPoolFullbright::endPostDeferredPass(S32 pass) void LLDrawPoolFullbright::beginRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_FULLBRIGHT); + LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT); fullbright_shader = &gObjectFullbrightProgram[LLPipeline::sUnderWaterRender< light_state; + gPipeline.enableLightsFullbright(light_state); U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR; renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, fullbright_mask); @@ -647,9 +649,9 @@ void LLDrawPoolFullbrightAlphaMask::beginPostDeferredPass(S32 pass) void LLDrawPoolFullbrightAlphaMask::renderPostDeferred(S32 pass) { - LLFastTimer t(FTM_RENDER_FULLBRIGHT); + LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT); gGL.setColorMask(true, true); - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, fullbright_mask, TRUE, TRUE); gGL.setColorMask(true, false); diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp index eb00d11550..c66a1d3305 100644 --- a/indra/newview/lldrawpoolsky.cpp +++ b/indra/newview/lldrawpoolsky.cpp @@ -113,11 +113,9 @@ void LLDrawPoolSky::render(S32 pass) LLGLSquashToFarClip far_clip(glh_get_current_projection()); - LLGLEnable fog_enable( (mVertexShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0); - - gPipeline.disableLights(); + LLGLEnable fog_enable(mVertexShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()); - LLGLDisable clip(GL_CLIP_PLANE0); + LLGLDisable clip; gGL.pushMatrix(); LLVector3 origin = LLViewerCamera::getInstance()->getOrigin(); @@ -152,7 +150,7 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side) if (LLSkyTex::doInterpolate()) { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; mSkyTex[side].bindTexture(FALSE); gGL.diffuseColor4f(1, 1, 1, LLSkyTex::getInterpVal()); // lighting is disabled face.renderIndexed(); diff --git a/indra/newview/lldrawpoolsky.h b/indra/newview/lldrawpoolsky.h index 3da493cc92..09b77f0c17 100644 --- a/indra/newview/lldrawpoolsky.h +++ b/indra/newview/lldrawpoolsky.h @@ -68,9 +68,6 @@ class LLDrawPoolSky : public LLFacePool void setSkyTex(LLSkyTex* const st) { mSkyTex = st; } void renderSkyCubeFace(U8 side); - void renderHeavenlyBody(U8 hb, LLFace* face); - void renderSunHalo(LLFace* face); - }; #endif // LL_LLDRAWPOOLSKY_H diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 456fc3301a..b348bc6aea 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -61,7 +61,7 @@ int DebugDetailMap = 0; S32 LLDrawPoolTerrain::sDetailMode = 1; F32 LLDrawPoolTerrain::sDetailScale = DETAIL_SCALE; static LLGLSLShader* sShader = NULL; -static LLFastTimer::DeclareTimer FTM_SHADOW_TERRAIN("Terrain Shadow"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_TERRAIN("Terrain Shadow"); LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : @@ -74,20 +74,12 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : // Hack! sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale"); sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); - mAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga", - TRUE, LLGLTexture::BOOST_UI, - LLViewerTexture::FETCHED_TEXTURE, - int_format, format, - LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); - - //gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); - mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c", + FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, - int_format, format, - LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); + int_format, format); //gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -134,7 +126,7 @@ void LLDrawPoolTerrain::prerender() void LLDrawPoolTerrain::beginRenderPass( S32 pass ) { - LLFastTimer t(FTM_RENDER_TERRAIN); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); LLFacePool::beginRenderPass(pass); sShader = LLPipeline::sUnderWaterRender ? @@ -149,7 +141,7 @@ void LLDrawPoolTerrain::beginRenderPass( S32 pass ) void LLDrawPoolTerrain::endRenderPass( S32 pass ) { - LLFastTimer t(FTM_RENDER_TERRAIN); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); //LLFacePool::endRenderPass(pass); if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) { @@ -165,7 +157,7 @@ S32 LLDrawPoolTerrain::getDetailMode() void LLDrawPoolTerrain::render(S32 pass) { - LLFastTimer t(FTM_RENDER_TERRAIN); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); if (mDrawFace.empty()) { @@ -197,61 +189,45 @@ void LLDrawPoolTerrain::render(S32 pass) } LLGLSPipeline gls; - - if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) { - gPipeline.enableLightsDynamic(); + LLGLState light_state; - renderFullShader(); - } - else - { - gPipeline.enableLightsStatic(); - - if (sDetailMode == 0) + if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) { - renderSimple(); - } - else if (gGLManager.mNumTextureUnits < 4) - { - renderFull2TU(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } - else + gPipeline.enableLightsDynamic(light_state); + + renderFullShader(); + } + else { - renderFull4TU(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + gPipeline.enableLightsStatic(light_state); + + if (sDetailMode == 0) + { + renderSimple(); + } + else if (gGLManager.mNumTextureUnits < 4) + { + renderFull2TU(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } + else + { + renderFull4TU(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } } } // Special-case for land ownership feedback - static const LLCachedControl show_parcel_owners("ShowParcelOwners",false); - if (show_parcel_owners) { - if (mVertexShaderLevel > 1) - { //use fullbright shader for highlighting - LLGLSLShader* old_shader = sShader; - sShader->unbind(); - sShader = &gHighlightProgram; - sShader->bind(); - gGL.diffuseColor4f(1,1,1,1); - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - renderOwnership(); - sShader = old_shader; - sShader->bind(); - } - else - { - gPipeline.disableLights(); - renderOwnership(); - } + hilightParcelOwners(); } } void LLDrawPoolTerrain::beginDeferredPass(S32 pass) { - LLFastTimer t(FTM_RENDER_TERRAIN); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); LLFacePool::beginRenderPass(pass); sShader = &gDeferredTerrainProgram; @@ -261,24 +237,31 @@ void LLDrawPoolTerrain::beginDeferredPass(S32 pass) void LLDrawPoolTerrain::endDeferredPass(S32 pass) { - LLFastTimer t(FTM_RENDER_TERRAIN); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); LLFacePool::endRenderPass(pass); sShader->unbind(); } void LLDrawPoolTerrain::renderDeferred(S32 pass) { - LLFastTimer t(FTM_RENDER_TERRAIN); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); if (mDrawFace.empty()) { return; } + renderFullShader(); + + // Special-case for land ownership feedback + { + hilightParcelOwners(); + } + } void LLDrawPoolTerrain::beginShadowPass(S32 pass) { - LLFastTimer t(FTM_SHADOW_TERRAIN); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_TERRAIN); LLFacePool::beginRenderPass(pass); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gDeferredShadowProgram.bind(); @@ -286,14 +269,14 @@ void LLDrawPoolTerrain::beginShadowPass(S32 pass) void LLDrawPoolTerrain::endShadowPass(S32 pass) { - LLFastTimer t(FTM_SHADOW_TERRAIN); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_TERRAIN); LLFacePool::endRenderPass(pass); gDeferredShadowProgram.unbind(); } void LLDrawPoolTerrain::renderShadow(S32 pass) { - LLFastTimer t(FTM_SHADOW_TERRAIN); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_TERRAIN); if (mDrawFace.empty()) { return; @@ -465,6 +448,29 @@ void LLDrawPoolTerrain::renderFullShader() gGL.matrixMode(LLRender::MM_MODELVIEW); } +void LLDrawPoolTerrain::hilightParcelOwners() +{ + static const LLCachedControl show_parcel_owners("ShowParcelOwners",false); + if (!show_parcel_owners) return; + if (mVertexShaderLevel > 1) + { //use fullbright shader for highlighting + LLGLSLShader* old_shader = sShader; + sShader->unbind(); + sShader = &gHighlightProgram; + sShader->bind(); + gGL.diffuseColor4f(1,1,1,1); + LLGLEnable polyOffset; + gGL.setPolygonOffset(-1.0f, -1.0f); + renderOwnership(); + sShader = old_shader; + sShader->bind(); + } + else + { + renderOwnership(); + } +} + void LLDrawPoolTerrain::renderFull4TU() { // Hack! Get the region that this draw pool is rendering from! @@ -608,7 +614,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.translatef(-1.f, 0.f, 0.f); - gGL.matrixMode(LLRender::MM_MODELVIEW); // Set alpha texture and do lighting modulation @@ -617,7 +622,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(0)->activate(); { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; drawLoop(); } @@ -743,7 +748,7 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.getTexUnit(0)->activate(); { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; drawLoop(); } //---------------------------------------------------------------------------- @@ -782,7 +787,7 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_ALPHA); { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; drawLoop(); } @@ -821,7 +826,7 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.getTexUnit(0)->activate(); { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; drawLoop(); } diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index a9fb48bac6..08ab122769 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -76,12 +76,11 @@ class LLDrawPoolTerrain : public LLFacePool /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display - LLPointer mAlphaRampImagep; LLPointer m2DAlphaRampImagep; - LLPointer mAlphaNoiseImagep; static S32 sDetailMode; static F32 sDetailScale; // meters per texture + protected: void renderSimple(); void renderOwnership(); @@ -90,6 +89,9 @@ class LLDrawPoolTerrain : public LLFacePool void renderFull4TU(); void renderFullShader(); void drawLoop(); + +private: + void hilightParcelOwners(); }; #endif // LL_LLDRAWPOOLSIMPLE_H diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 8ef66aa241..c02c55d683 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -47,7 +47,7 @@ S32 LLDrawPoolTree::sDiffTex = 0; static LLGLSLShader* shader = NULL; -static LLFastTimer::DeclareTimer FTM_SHADOW_TREE("Tree Shadow"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_TREE("Tree Shadow"); LLDrawPoolTree::LLDrawPoolTree(LLViewerTexture *texturep) : LLFacePool(POOL_TREE), @@ -68,7 +68,7 @@ void LLDrawPoolTree::prerender() void LLDrawPoolTree::beginRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_TREES); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TREES); if (LLPipeline::sUnderWaterRender) { @@ -87,21 +87,25 @@ void LLDrawPoolTree::beginRenderPass(S32 pass) } else { - gPipeline.enableLightsDynamic(); gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); } } void LLDrawPoolTree::render(S32 pass) { - LLFastTimer t(LLPipeline::sShadowRender ? FTM_SHADOW_TREE : FTM_RENDER_TREES); + LL_RECORD_BLOCK_TIME(LLPipeline::sShadowRender ? FTM_SHADOW_TREE : FTM_RENDER_TREES); if (mDrawFace.empty()) { return; } - LLGLState test(GL_ALPHA_TEST, LLGLSLShader::sNoFixedFunction ? 0 : 1); + LLGLState test(LLGLSLShader::sNoFixedFunction ? 0 : 1); + LLGLState light_state; + if (!LLGLSLShader::sNoFixedFunction) + { + gPipeline.enableLightsDynamic(light_state); + } LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); gGL.getTexUnit(sDiffTex)->bind(mTexturep); @@ -165,7 +169,7 @@ void LLDrawPoolTree::render(S32 pass) void LLDrawPoolTree::endRenderPass(S32 pass) { - LLFastTimer t(FTM_RENDER_TREES); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TREES); if (gPipeline.canUseWindLightShadersOnObjects()) { @@ -183,7 +187,7 @@ void LLDrawPoolTree::endRenderPass(S32 pass) //============================================ void LLDrawPoolTree::beginDeferredPass(S32 pass) { - LLFastTimer t(FTM_RENDER_TREES); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TREES); shader = &gDeferredTreeProgram; shader->bind(); @@ -197,7 +201,7 @@ void LLDrawPoolTree::renderDeferred(S32 pass) void LLDrawPoolTree::endDeferredPass(S32 pass) { - LLFastTimer t(FTM_RENDER_TREES); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TREES); shader->unbind(); } @@ -207,11 +211,11 @@ void LLDrawPoolTree::endDeferredPass(S32 pass) //============================================ void LLDrawPoolTree::beginShadowPass(S32 pass) { - LLFastTimer t(FTM_SHADOW_TREE); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_TREE); static const LLCachedControl render_deferred_offset("RenderDeferredTreeShadowOffset",1.f); static const LLCachedControl render_deferred_bias("RenderDeferredTreeShadowBias",1.f); - glPolygonOffset(render_deferred_offset,render_deferred_bias); + gGL.setPolygonOffset(render_deferred_offset,render_deferred_bias); gDeferredTreeShadowProgram.bind(); gDeferredTreeShadowProgram.setMinimumAlpha(0.5f); } @@ -223,11 +227,11 @@ void LLDrawPoolTree::renderShadow(S32 pass) void LLDrawPoolTree::endShadowPass(S32 pass) { - LLFastTimer t(FTM_SHADOW_TREE); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_TREE); static const LLCachedControl render_deferred_offset("RenderDeferredSpotShadowOffset",1.f); static const LLCachedControl render_deferred_bias("RenderDeferredSpotShadowBias",1.f); - glPolygonOffset(render_deferred_offset,render_deferred_bias); + gGL.setPolygonOffset(render_deferred_offset,render_deferred_bias); gDeferredTreeShadowProgram.unbind(); } diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index ff04959a0a..1928794f23 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -73,11 +73,11 @@ LLVector3 LLDrawPoolWater::sLightDir; LLDrawPoolWater::LLDrawPoolWater() : LLFacePool(POOL_WATER) { - mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLGLTexture::BOOST_UI); + mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); gGL.getTexUnit(0)->bind(mHBTex[0]) ; mHBTex[0]->setAddressMode(LLTexUnit::TAM_CLAMP); - mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLGLTexture::BOOST_UI); + mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); gGL.getTexUnit(0)->bind(mHBTex[1]); mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -149,7 +149,7 @@ void LLDrawPoolWater::endPostDeferredPass(S32 pass) //=============================== void LLDrawPoolWater::renderDeferred(S32 pass) { - LLFastTimer t(FTM_RENDER_WATER); + LL_RECORD_BLOCK_TIME(FTM_RENDER_WATER); deferred_render = TRUE; shade(); deferred_render = FALSE; @@ -159,7 +159,7 @@ void LLDrawPoolWater::renderDeferred(S32 pass) void LLDrawPoolWater::render(S32 pass) { - LLFastTimer ftm(FTM_RENDER_WATER); + LL_RECORD_BLOCK_TIME(FTM_RENDER_WATER); if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1) { return; @@ -182,7 +182,7 @@ void LLDrawPoolWater::render(S32 pass) return; } - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; if (mVertexShaderLevel > 0) { @@ -202,11 +202,12 @@ void LLDrawPoolWater::render(S32 pass) LLFace* refl_face = voskyp->getReflFace(); - gPipeline.disableLights(); + LLGLState light_state; + gPipeline.disableLights(light_state); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - LLGLDisable cullFace(GL_CULL_FACE); + LLGLDisable cullFace; // Set up second pass first mWaterImagep->addTextureStats(1024.f*1024.f); @@ -253,7 +254,7 @@ void LLDrawPoolWater::render(S32 pass) glClearStencil(1); glClear(GL_STENCIL_BUFFER_BIT); glClearStencil(0); - LLGLEnable gls_stencil(GL_STENCIL_TEST); + LLGLEnable gls_stencil; glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); @@ -369,10 +370,10 @@ void LLDrawPoolWater::renderOpaqueLegacyWater() // of no transparency. And no face culling so // that the underside of the water is also opaque. LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); - LLGLDisable no_cull(GL_CULL_FACE); - LLGLDisable no_blend(GL_BLEND); - - gPipeline.disableLights(); + LLGLDisable no_cull; + LLGLDisable no_blend; + LLGLState light_state; + gPipeline.disableLights(light_state); //Singu note: This is a hack around bizarre opensim behavior. The opaque water texture we get is pure white and only has one channel. // This behavior is clearly incorrect, so we try to detect that case, purge it from the cache, and try to re-fetch the texture. @@ -522,7 +523,7 @@ void LLDrawPoolWater::shade() return; } - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; LLColor3 light_diffuse(0,0,0); F32 light_exp = 0.0f; @@ -649,14 +650,6 @@ void LLDrawPoolWater::shade() sWaterFogColor.mV[3] = param_mgr->mDensitySliderValue; shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV); } - - F32 screenRes[] = - { - 1.f/gGLViewport[2], - 1.f/gGLViewport[3] - }; - shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes); - stop_glerror(); S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP); stop_glerror(); @@ -708,8 +701,8 @@ void LLDrawPoolWater::shade() } { - LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0); - LLGLDisable cullface(GL_CULL_FACE); + LLGLEnable depth_clamp(gGLManager.mHasDepthClamp); + LLGLDisable cullface; for (std::vector::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 53bd3d5655..6257187dca 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -179,7 +179,7 @@ void LLDrawPoolWLSky::renderSkyHaze(F32 camHeightLocal) const { if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)) { - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; sky_shader->bind(); @@ -202,15 +202,16 @@ void LLDrawPoolWLSky::renderStars(void) const return; LLGLSPipelineSkyBox gls_sky; - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.setSceneBlendType(LLRender::BT_ALPHA); // *NOTE: have to have bound the cloud noise texture already since register // combiners blending below requires something to be bound // and we might as well only bind once. gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - - gPipeline.disableLights(); + + LLGLState light_state; + gPipeline.disableLights(light_state); /*if (!LLPipeline::sReflectionRender) { @@ -251,7 +252,7 @@ void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const { if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WL_CLOUDS) && sCloudNoiseTexture.notNull()) { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.setSceneBlendType(LLRender::BT_ALPHA); gGL.getTexUnit(0)->bind(sCloudNoiseTexture); @@ -274,9 +275,9 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() color.mV[VW] = llclamp(color.mV[VW]*color.mV[VW]*4.f,0.f,1.f); LLGLSPipelineSkyBox gls_skybox; - LLGLEnable blend_on(GL_BLEND); + LLGLEnable blend_on; + LLGLDisable lighting; gGL.setSceneBlendType(LLRender::BT_ALPHA); - gPipeline.disableLights(); #if 0 // when we want to re-add a texture sun disc, here's where to do it. LLFace * face = gSky.mVOSkyp->mFace[LLVOSky::FACE_SUN]; @@ -328,14 +329,14 @@ void LLDrawPoolWLSky::renderDeferred(S32 pass) { return; } - LLFastTimer ftm(FTM_RENDER_WL_SKY); + LL_RECORD_BLOCK_TIME(FTM_RENDER_WL_SKY); const F32 camHeightLocal = LLWLParamManager::getInstance()->getDomeOffset() * LLWLParamManager::getInstance()->getDomeRadius(); - LLGLDisable stencil(GL_STENCIL_TEST); + LLGLDisable stencil; LLGLSNoFog disableFog; LLGLDepthTest depth(GL_TRUE, GL_FALSE); - LLGLDisable clip(GL_CLIP_PLANE0); + LLGLDisable clip; LLGLSquashToFarClip far_clip(glh_get_current_projection()); @@ -373,13 +374,13 @@ void LLDrawPoolWLSky::render(S32 pass) { return; } - LLFastTimer ftm(FTM_RENDER_WL_SKY); + LL_RECORD_BLOCK_TIME(FTM_RENDER_WL_SKY); const F32 camHeightLocal = LLWLParamManager::getInstance()->getDomeOffset() * LLWLParamManager::getInstance()->getDomeRadius(); LLGLSNoFog disableFog; LLGLDepthTest depth(GL_TRUE, GL_FALSE); - LLGLDisable clip(GL_CLIP_PLANE0); + LLGLDisable clip; LLGLSquashToFarClip far_clip(glh_get_current_projection()); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 15c86d0c3f..2daf5b6e97 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -51,7 +51,7 @@ S32 LLViewerDynamicTexture::sNumRenders = 0; // LLViewerDynamicTexture() //----------------------------------------------------------------------------- LLViewerDynamicTexture::LLViewerDynamicTexture(S32 width, S32 height, S32 components, EOrder order, BOOL clamp) : - LLViewerTexture(width, height, components, FALSE), + LLViewerTexture(width, height, components, FALSE, false), mClamp(clamp) { llassert((1 <= components) && (components <= 4)); @@ -109,7 +109,7 @@ void LLViewerDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum } if(fill_color) raw_image->fill(*fill_color); - createGLTexture(0, raw_image, 0, TRUE, LLViewerTexture::DYNAMIC_TEX); + createGLTexture(0, raw_image, nullptr, TRUE, LLViewerTexture::DYNAMIC_TEX); setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); mGLTexturep->setGLTextureCreated(false); } @@ -161,9 +161,10 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth) mCamera.setView(camera->getView()); mCamera.setNear(camera->getNear()); - glViewport(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight); + gGL.setViewport(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight); if (clear_depth) { + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT); } } @@ -226,7 +227,6 @@ BOOL LLViewerDynamicTexture::updateAllInstances() } LLGLSLShader::bindNoShader(); - LLVertexBuffer::unbind(); BOOL result = FALSE; BOOL ret = FALSE ; @@ -237,7 +237,8 @@ BOOL LLViewerDynamicTexture::updateAllInstances() { LLViewerDynamicTexture *dynamicTexture = *iter; if (dynamicTexture->needsRender()) - { + { + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT); gDepthDirty = TRUE; diff --git a/indra/newview/llenvmanager.cpp b/indra/newview/llenvmanager.cpp index 4abd7fc8e9..d2fb204cca 100644 --- a/indra/newview/llenvmanager.cpp +++ b/indra/newview/llenvmanager.cpp @@ -505,7 +505,7 @@ void LLEnvManagerNew::onRegionSettingsResponse(const LLSD& content) mRegionSettingsChangeSignal(); // reset - if (!gHippoGridManager->getConnectedGrid()->isAurora()) // On Aurora, the region says when to refresh + if (!gHippoGridManager->getConnectedGrid()->isWhiteCore()) // On WhiteCore, the region says when to refresh mInterpNextChangeMessage = false; } @@ -704,7 +704,7 @@ void LLEnvManagerNew::onRegionChange() } } -// Aurora-sim windlight refresh +// WhiteCore windlight refresh class WindLightRefresh : public LLHTTPNode { /*virtual*/ void post(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index 7aae068ad0..f48b994118 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -39,12 +39,58 @@ #include "llnotify.h" #include "lleventinfo.h" -#include "llfloaterdirectory.h" +#include "llfloaterevent.h" #include "llfloaterworldmap.h" #include "llagent.h" #include "llappviewer.h" // for gPacificDaylightTime +#include "llcommandhandler.h" // secondlife:///app/... support #include "llviewercontrol.h" +class LLEventHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLEventHandler() : LLCommandHandler("event", UNTRUSTED_THROTTLE) { } + bool handle(const LLSD& params, const LLSD& query_map, + LLMediaCtrl* web) + { + if (params.size() < 2) + { + return false; + } + std::string event_command = params[1].asString(); + S32 event_id = params[0].asInteger(); + if (event_command == "about" || event_command == "details") + { + LLFloaterEventInfo::show(event_id); + return true; + } + else if(event_command == "notify") + { + // we're adding or removing a notification, so grab the date, name and notification bool + if (params.size() < 3) + { + return false; + } + if(params[2].asString() == "enable") + { + gEventNotifier.add(event_id); + // tell the server to modify the database as this was a slurl event notification command + gEventNotifier.serverPushRequest(event_id, true); + } + else + { + gEventNotifier.remove(event_id); + } + return true; + } + + return false; + } +}; +LLEventHandler gEventHandler; + + LLEventNotifier gEventNotifier; LLEventNotifier::LLEventNotifier() @@ -104,8 +150,7 @@ bool LLEventNotifier::handleResponse(U32 eventId, LLVector3d eventPos, const LLS gFloaterWorldMap->trackLocation(eventPos); break; case 1: - gDisplayEventHack = TRUE; - LLFloaterDirectory::showEvents(eventId); + LLFloaterEventInfo::show(eventId); break; case 2: break; diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 22b7155901..b1a412b493 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -183,13 +183,32 @@ namespace { if (mDone) return; - // A HTTP_BAD_GATEWAY (502) error is our standard timeout response - // we get this when there are no events. - if ( mStatus == HTTP_BAD_GATEWAY ) - { + // Timeout + if (is_internal_http_error_that_warrants_a_retry(mStatus)) + { // A standard timeout response we get this when there are no events. mErrorCount = 0; makeRequest(); } + else if ( mStatus == HTTP_BAD_GATEWAY ) + { // LEGACY: A HTTP_BAD_GATEWAY (502) error is our standard timeout response + // we get this when there are no events. + mErrorCount = 0; + makeRequest(); + } + else if (mStatus == HTTP_NOT_FOUND) + { // Event polling for this server has been canceled. In + // some cases the server gets ahead of the viewer and will + // return a 404 error (Not Found) before the cancel event + // comes back in the queue + LL_WARNS("LLEventPollImpl") << "Canceling coroutine" << LL_ENDL; + stop(); + } + else if (mCode != CURLE_OK) + { + /// Some LLCore or LIBCurl error was returned. This is unlikely to be recoverable + LL_WARNS("LLEventPollImpl") << "Critical error from poll request returned from libraries. Canceling coroutine." << LL_ENDL; + stop(); + } else if (mErrorCount < MAX_EVENT_POLL_HTTP_ERRORS) { ++mErrorCount; @@ -213,6 +232,7 @@ namespace // They are essentially disconnected from the region even though some things may still work. // Since things won't get better until they relog we force a disconnect now. + /* Singu Note: There's no reason to disconnect, just because this failed a few too many times // *NOTE:Mani - The following condition check to see if this failing event poll // is attached to the Agent's main region. If so we disconnect the viewer. // Else... its a child region and we just leave the dead event poll stopped and @@ -222,6 +242,7 @@ namespace LL_WARNS() << "Forcing disconnect due to stalled main region event poll." << LL_ENDL; LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection")); } + */ } } diff --git a/indra/newview/llexperiencelog.cpp b/indra/newview/llexperiencelog.cpp new file mode 100644 index 0000000000..ea2e57535f --- /dev/null +++ b/indra/newview/llexperiencelog.cpp @@ -0,0 +1,289 @@ +/** + * @file llexperiencelog.cpp + * @brief llexperiencelog implementation + * + * $LicenseInfo:firstyear=2014&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, 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 "llviewerprecompiledheaders.h" +#include "llexperiencelog.h" + +#include "lldispatcher.h" +#include "llsdserialize.h" +#include "llviewergenericmessage.h" +#include "llnotificationsutil.h" +#include "lltrans.h" +#include "llerror.h" +#include "lldate.h" + + +class LLExperienceLogDispatchHandler final : public LLDispatchHandler +{ +public: + bool operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) override + { + LLSD message; + + sparam_t::const_iterator it = strings.begin(); + if(it != strings.end()){ + const std::string& llsdRaw = *it++; + std::istringstream llsdData(llsdRaw); + if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length())) + { + LL_WARNS() << "LLExperienceLogDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL; + } + } + message["public_id"] = invoice; + + // Object Name + if(it != strings.end()) + { + message["ObjectName"] = *it++; + } + + // parcel Name + if(it != strings.end()) + { + message["ParcelName"] = *it++; + } + message["Count"] = 1; + + LLExperienceLog::instance().handleExperienceMessage(message); + return true; + } +}; + +static LLExperienceLogDispatchHandler experience_log_dispatch_handler; + +void LLExperienceLog::handleExperienceMessage(LLSD& message) +{ + time_t now; + time(&now); + char daybuf[16];/* Flawfinder: ignore */ + char time_of_day[16];/* Flawfinder: ignore */ + strftime(daybuf, 16, "%Y-%m-%d", localtime(&now)); + strftime(time_of_day, 16, " %H:%M:%S", localtime(&now)); + message["Time"] = time_of_day; + + std::string day = daybuf; + + if(!mEvents.has(day)) + { + mEvents[day] = LLSD::emptyArray(); + } + LLSD& dayEvents = mEvents[day]; + if(dayEvents.size() > 0) + { + LLSD& last = *(dayEvents.rbeginArray()); + if( last["public_id"].asUUID() == message["public_id"].asUUID() + && last["ObjectName"].asString() == message["ObjectName"].asString() + && last["OwnerID"].asUUID() == message["OwnerID"].asUUID() + && last["ParcelName"].asString() == message["ParcelName"].asString() + && last["Permission"].asInteger() == message["Permission"].asInteger()) + { + last["Count"] = last["Count"].asInteger() + 1; + last["Time"] = time_of_day; + mSignals(last); + return; + } + } + message["Time"] = time_of_day; + mEvents[day].append(message); + mSignals(message); +} + +LLExperienceLog::LLExperienceLog() + : mMaxDays(7) + , mPageSize(25) + , mNotifyNewEvent(false) +{ +} + +void LLExperienceLog::initialize() +{ + loadEvents(); + if(!gGenericDispatcher.isHandlerPresent("ExperienceEvent")) + { + gGenericDispatcher.addHandler("ExperienceEvent", &experience_log_dispatch_handler); + } +} + +std::string LLExperienceLog::getFilename() +{ + return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "experience_events.xml"); +} + + +std::string LLExperienceLog::getPermissionString( const LLSD& message, const std::string& base ) +{ + std::ostringstream buf; + if(message.has("Permission")) + { + buf << base << message["Permission"].asInteger(); + std::string entry; + if(LLTrans::findString(entry, buf.str())) + { + buf.str(entry); + } + } + + if(buf.str().empty()) + { + buf << base << "Unknown"; + + buf.str(LLTrans::getString(buf.str(), message)); + } + + return buf.str(); +} + +void LLExperienceLog::notify( LLSD& message ) +{ + message["EventType"] = getPermissionString(message, "ExperiencePermission"); + if(message.has("IsAttachment") && message["IsAttachment"].asBoolean()) + { + LLNotificationsUtil::add("ExperienceEventAttachment", message); + } + else + { + LLNotificationsUtil::add("ExperienceEvent", message); + } + message.erase("EventType"); +} + +void LLExperienceLog::saveEvents() +{ + eraseExpired(); + std::string filename = getFilename(); + LLSD settings = LLSD::emptyMap().with("Events", mEvents); + + settings["MaxDays"] = (int)mMaxDays; + settings["Notify"] = mNotifyNewEvent; + settings["PageSize"] = (int)mPageSize; + + llofstream stream(filename.c_str()); + LLSDSerialize::toPrettyXML(settings, stream); +} + + +void LLExperienceLog::loadEvents() +{ + LLSD settings = LLSD::emptyMap(); + + std::string filename = getFilename(); + llifstream stream(filename.c_str()); + LLSDSerialize::fromXMLDocument(settings, stream); + + if(settings.has("MaxDays")) + { + setMaxDays((U32)settings["MaxDays"].asInteger()); + } + if(settings.has("Notify")) + { + setNotifyNewEvent(settings["Notify"].asBoolean()); + } + if(settings.has("PageSize")) + { + setPageSize((U32)settings["PageSize"].asInteger()); + } + mEvents.clear(); + if(mMaxDays > 0 && settings.has("Events")) + { + mEvents = settings["Events"]; + } + + eraseExpired(); +} + +LLExperienceLog::~LLExperienceLog() +{ + saveEvents(); +} + +void LLExperienceLog::eraseExpired() +{ + std::vector expired; + for (const auto& event_pair : mEvents.map()) + { + const std::string& date = event_pair.first; + if (isExpired(date)) + { + expired.push_back(date); + } + } + + for (const auto& date : expired) + { + mEvents.erase(date); + } +} + +bool LLExperienceLog::isExpired(const std::string& date) const +{ + if (date.empty()) + return true; + + S32 month, day, year = 0; + S32 matched = sscanf(date.c_str(), "%d-%d-%d", &year, &month, &day); + if (matched != 3) return false; + LLDate event_date; + event_date.fromYMDHMS(year, month, day); + + return event_date.secondsSinceEpoch() <= (LLDate::now().secondsSinceEpoch() - F64(getMaxDays() * 86400U)); +} + +const LLSD& LLExperienceLog::getEvents() const +{ + return mEvents; +} + +void LLExperienceLog::clear() +{ + mEvents.clear(); +} + +void LLExperienceLog::setMaxDays( U32 val ) +{ + mMaxDays = val; +} + +LLExperienceLog::callback_connection_t LLExperienceLog::addUpdateSignal( const callback_slot_t& cb ) +{ + return mSignals.connect(cb); +} + +void LLExperienceLog::setNotifyNewEvent( bool val ) +{ + mNotifyNewEvent = val; + if(!val && mNotifyConnection.connected()) + { + mNotifyConnection.disconnect(); + } + else if( val && !mNotifyConnection.connected()) + { + mNotifyConnection = addUpdateSignal(std::function(LLExperienceLog::notify)); + } +} diff --git a/indra/newview/llexperiencelog.h b/indra/newview/llexperiencelog.h new file mode 100644 index 0000000000..27012898c6 --- /dev/null +++ b/indra/newview/llexperiencelog.h @@ -0,0 +1,86 @@ +/** + * @file llexperiencelog.h + * @brief llexperiencelog and related class definitions + * + * $LicenseInfo:firstyear=2014&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, 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_LLEXPERIENCELOG_H +#define LL_LLEXPERIENCELOG_H + +#include "llsingleton.h" + +class LLExperienceLog final : public LLSingleton +{ + friend class LLSingleton; + LLExperienceLog(); +public: + typedef boost::signals2::signal + callback_signal_t; + typedef callback_signal_t::slot_type callback_slot_t; + typedef boost::signals2::connection callback_connection_t; + callback_connection_t addUpdateSignal(const callback_slot_t& cb); + + void initialize(); + + U32 getMaxDays() const { return mMaxDays; } + void setMaxDays(U32 val); + + bool getNotifyNewEvent() const { return mNotifyNewEvent; } + void setNotifyNewEvent(bool val); + + U32 getPageSize() const { return mPageSize; } + void setPageSize(U32 val) { mPageSize = val; } + + const LLSD& getEvents()const; + void clear(); + + virtual ~LLExperienceLog(); + + static void notify(LLSD& message); + static std::string getFilename(); + static std::string getPermissionString(const LLSD& message, const std::string& base); + bool isExpired(const std::string& date) const; +protected: + void handleExperienceMessage(LLSD& message); + + + void loadEvents(); + void saveEvents(); + void eraseExpired(); + + LLSD mEvents; + callback_signal_t mSignals; + callback_connection_t mNotifyConnection; + U32 mMaxDays; + U32 mPageSize; + bool mNotifyNewEvent; + + friend class LLExperienceLogDispatchHandler; +}; + + + + +#endif // LL_LLEXPERIENCELOG_H diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 11dc74b823..c0271b3066 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -59,6 +59,7 @@ #include "llviewershadermgr.h" #include "llviewertexture.h" #include "llvoavatar.h" +#include "llsculptidsize.h" #define LL_MAX_INDICES_COUNT 1000000 @@ -330,6 +331,8 @@ void LLFace::dirtyTexture() if (vobj) { vobj->mLODChanged = TRUE; + + vobj->updateVisualComplexity(); // Animmesh+ } gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, FALSE); } @@ -339,6 +342,34 @@ void LLFace::dirtyTexture() gPipeline.markTextured(drawablep); } +void LLFace::notifyAboutCreatingTexture(LLViewerTexture *texture) +{ + LLDrawable* drawablep = getDrawable(); + if(mVObjp.notNull() && mVObjp->getVolume()) + { + LLVOVolume *vobj = drawablep->getVOVolume(); + if(vobj && vobj->notifyAboutCreatingTexture(texture)) + { + gPipeline.markTextured(drawablep); + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME); + } + } +} + +void LLFace::notifyAboutMissingAsset(LLViewerTexture *texture) +{ + LLDrawable* drawablep = getDrawable(); + if(mVObjp.notNull() && mVObjp->getVolume()) + { + LLVOVolume *vobj = drawablep->getVOVolume(); + if(vobj && vobj->notifyAboutMissingAsset(texture)) + { + gPipeline.markTextured(drawablep); + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME); + } + } +} + void LLFace::switchTexture(U32 ch, LLViewerTexture* new_texture) { llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); @@ -548,8 +579,8 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) LLRiggedVolume* rigged = volume->getRiggedVolume(); if (rigged) { - LLGLEnable offset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.f, -1.f); + LLGLEnable offset; + gGL.setPolygonOffset(-1.f, -1.f); gGL.multMatrix(volume->getRelativeXform()); const LLVolumeFace& vol_face = rigged->getVolumeFace(getTEOffset()); @@ -579,7 +610,7 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, vol_face.mPositions, vol_face.mTexCoords, vol_face.mNumIndices, vol_face.mIndices); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, vol_face.mNumVertices, vol_face.mPositions, vol_face.mTexCoords, vol_face.mNumIndices, vol_face.mIndices); if(prev_shader) { @@ -592,8 +623,8 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) else { gGL.diffuseColor4fv(color.mV); - LLGLEnable poly_offset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.f,-1.f); + LLGLEnable poly_offset; + gGL.setPolygonOffset(-1.f,-1.f); // Singu Note: Disable per-vertex color to prevent fixed-function pipeline from using it. We want glColor color, not vertex color! mVertexBuffer->setBuffer(mVertexBuffer->getTypeMask() & ~(LLVertexBuffer::MAP_COLOR)); mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); @@ -765,9 +796,6 @@ static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVect // Texture transforms are done about the center of the face. st.setAdd(tex_coord, trans); - // Handle rotation - LLVector4a rot_st; - // LLVector4a s0; s0.splat(st, 0); @@ -823,12 +851,6 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, //get bounding box if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED)) { - //VECTORIZE THIS - const LLMatrix4a& mat_vert = mat_vert_in; - //mat_vert.loadu(mat_vert_in); - - LLVector4a min,max; - if (f >= volume.getNumVolumeFaces()) { LL_WARNS() << "Generating bounding box for invalid face index!" << LL_ENDL; @@ -836,77 +858,41 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, } const LLVolumeFace &face = volume.getVolumeFace(f); - min = face.mExtents[0]; - max = face.mExtents[1]; - - llassert(less_than_max_mag(min)); - llassert(less_than_max_mag(max)); - - //min, max are in volume space, convert to drawable render space - - //get 8 corners of bounding box - LLVector4Logical mask[6]; - - for (U32 i = 0; i < 6; ++i) - { - mask[i].clear(); - } - - mask[0].setElement<2>(); //001 - mask[1].setElement<1>(); //010 - mask[2].setElement<1>(); //011 - mask[2].setElement<2>(); - mask[3].setElement<0>(); //100 - mask[4].setElement<0>(); //101 - mask[4].setElement<2>(); - mask[5].setElement<0>(); //110 - mask[5].setElement<1>(); - LLVector4a v[8]; - - v[6] = min; - v[7] = max; - for (U32 i = 0; i < 6; ++i) + // MAINT-8264 - stray vertices, especially in low LODs, cause bounding box errors. + if (face.mNumVertices < 3) { - v[i].setSelectWithMask(mask[i], min, max); + LL_DEBUGS("RiggedBox") << "skipping face " << f << ", bad num vertices " + << face.mNumVertices << " " << face.mNumIndices << " " << face.mWeights << LL_ENDL; + return FALSE; } - LLVector4a tv[8]; + //VECTORIZE THIS + LLMatrix4a mat_vert = mat_vert_in; - //transform bounding box into drawable space - for (U32 i = 0; i < 8; ++i) - { - mat_vert.affineTransform(v[i], tv[i]); - } - - //find bounding box - LLVector4a& newMin = mExtents[0]; - LLVector4a& newMax = mExtents[1]; + llassert(less_than_max_mag(face.mExtents[0])); + llassert(less_than_max_mag(face.mExtents[1])); - newMin = newMax = tv[0]; - - for (U32 i = 1; i < 8; ++i) - { - newMin.setMin(newMin, tv[i]); - newMax.setMax(newMax, tv[i]); - } + matMulBoundBox(mat_vert, face.mExtents, mExtents); if (!mDrawablep->isActive()) { // Shift position for region LLVector4a offset; offset.load3(mDrawablep->getRegion()->getOriginAgent().mV); - newMin.add(offset); - newMax.add(offset); + mExtents[0].add(offset); + mExtents[1].add(offset); + LL_DEBUGS("RiggedBox") << "updating extents for face " << f + << " not active, added offset " << offset << LL_ENDL; } LLVector4a t; - t.setAdd(newMin,newMax); + t.setAdd(mExtents[0],mExtents[1]); t.mul(0.5f); mCenterLocal.set(t.getF32ptr()); - t.setSub(newMax,newMin); + t.setSub(mExtents[1],mExtents[0]); mBoundingSphereRadius = t.getLength3().getF32()*0.5f; updateCenterAgent(); @@ -987,6 +973,10 @@ void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_po { const LLMatrix4a& vol_mat = getWorldMatrix(); const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset); + if (!vf.mTangents) + { + return; + } const LLVector4a& normal = vf.mNormals[0]; const LLVector4a& tangent = vf.mTangents[0]; @@ -1094,9 +1084,10 @@ bool LLFace::canRenderAsMask() static const LLCachedControl use_rmse_auto_mask("SHUseRMSEAutoMask",false); static const LLCachedControl auto_mask_max_rmse("SHAutoMaskMaxRMSE",.09f); + static const LLCachedControl auto_mask_max_mid("SHAutoMaskMaxMid", .25f); if ((te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha (te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask - (getTexture()->getIsAlphaMask((!getViewerObject()->isAttachment() && use_rmse_auto_mask) ? auto_mask_max_rmse : -1.f))) // texture actually qualifies for masking (lazily recalculated but expensive) + (getTexture()->getIsAlphaMask((!getViewerObject()->isAttachment() && use_rmse_auto_mask) ? auto_mask_max_rmse : -1.f, auto_mask_max_mid))) // texture actually qualifies for masking (lazily recalculated but expensive) { if (LLPipeline::sRenderDeferred) { @@ -1119,12 +1110,12 @@ bool LLFace::canRenderAsMask() } -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_VOLUME("Volume VB Cache"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_VOLUME("Volume VB Cache"); //static void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf) { - LLFastTimer t(FTM_FACE_GEOM_VOLUME); + LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_VOLUME); U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL; @@ -1185,33 +1176,33 @@ void push_for_transform(LLVertexBuffer* buff, U32 source_count, U32 dest_count) gPipeline.mTransformFeedbackPrimitives += dest_count; } } -static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_POSITION("Position"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_NORMAL("Normal"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_TEXTURE("Texture"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_COLOR("Color"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_EMISSIVE("Emissive"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_WEIGHTS("Weights"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_TANGENT("Binormal"); - -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK("Face Feedback"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_POSITION("Feedback Position"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_NORMAL("Feedback Normal"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_TEXTURE("Feedback Texture"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_COLOR("Feedback Color"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_EMISSIVE("Feedback Emissive"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_BINORMAL("Feedback Binormal"); - -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX("Index"); -static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX_TAIL("Tail"); -static LLFastTimer::DeclareTimer FTM_FACE_POSITION_STORE("Pos"); -static LLFastTimer::DeclareTimer FTM_FACE_TEXTURE_INDEX_STORE("TexIdx"); -static LLFastTimer::DeclareTimer FTM_FACE_POSITION_PAD("Pad"); -static LLFastTimer::DeclareTimer FTM_FACE_TEX_DEFAULT("Default"); -static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK("Quick"); -static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_NO_XFORM("No Xform"); -static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_XFORM("Xform"); -static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_PLANAR("Quick Planar"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GET_GEOM("Face Geom"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_POSITION("Position"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_NORMAL("Normal"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_TEXTURE("Texture"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_COLOR("Color"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_EMISSIVE("Emissive"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_WEIGHTS("Weights"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_TANGENT("Binormal"); + +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK("Face Feedback"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_POSITION("Feedback Position"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_NORMAL("Feedback Normal"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_TEXTURE("Feedback Texture"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_COLOR("Feedback Color"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_EMISSIVE("Feedback Emissive"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_BINORMAL("Feedback Binormal"); + +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_INDEX("Index"); +static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_INDEX_TAIL("Tail"); +static LLTrace::BlockTimerStatHandle FTM_FACE_POSITION_STORE("Pos"); +static LLTrace::BlockTimerStatHandle FTM_FACE_TEXTURE_INDEX_STORE("TexIdx"); +static LLTrace::BlockTimerStatHandle FTM_FACE_POSITION_PAD("Pad"); +static LLTrace::BlockTimerStatHandle FTM_FACE_TEX_DEFAULT("Default"); +static LLTrace::BlockTimerStatHandle FTM_FACE_TEX_QUICK("Quick"); +static LLTrace::BlockTimerStatHandle FTM_FACE_TEX_QUICK_NO_XFORM("No Xform"); +static LLTrace::BlockTimerStatHandle FTM_FACE_TEX_QUICK_XFORM("Xform"); +static LLTrace::BlockTimerStatHandle FTM_FACE_TEX_QUICK_PLANAR("Quick Planar"); BOOL LLFace::getGeometryVolume(const LLVolume& volume, const S32 &f, @@ -1219,7 +1210,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, const U16 &index_offset, bool force_rebuild) { - LLFastTimer t(FTM_FACE_GET_GEOM); + LL_RECORD_BLOCK_TIME(FTM_FACE_GET_GEOM); llassert(verify()); const LLVolumeFace &vf = volume.getVolumeFace(f); S32 num_vertices = (S32)vf.mNumVertices; @@ -1294,6 +1285,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, const LLTextureEntry *tep = mVObjp->getTE(f); const U8 bump_code = tep ? tep->getBumpmap() : 0; + if ( bump_code && rebuild_tcoord && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TANGENT) ) + { + LLMaterial* mat = tep->getMaterialParams().get(); + if( !mat || mat->getNormalID().isNull() ) + rebuild_tangent = true; + } + BOOL is_static = mDrawablep->isStatic(); BOOL is_global = is_static; @@ -1315,23 +1313,17 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if(mShinyInAlpha) { - GLfloat alpha[4] = - { - 0.00f, - 0.25f, - 0.5f, - 0.75f - }; - + // Singu Note: Avoid casing. Store as LLColor4U. + static const LLColor4U shine_steps(LLColor4(0.f, .25f, .5f, 7.5f)); llassert(tep->getShiny() <= 3); - color.mV[3] = U8 (alpha[tep->getShiny()] * 255); + color.mV[3] = shine_steps.mV[tep->getShiny()]; } } // INDICES if (full_rebuild) { - LLFastTimer t(FTM_FACE_GEOM_INDEX); + LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_INDEX); mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, map_range); volatile __m128i* dst = (__m128i*) indicesp.get(); @@ -1347,7 +1339,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } { - LLFastTimer t(FTM_FACE_GEOM_INDEX_TAIL); + LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_INDEX_TAIL); U16* idx = (U16*) dst; for (S32 i = end*8; i < num_indices; ++i) @@ -1399,152 +1391,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } static LLCachedControl use_transform_feedback("RenderUseTransformFeedback", false); - -#ifdef GL_TRANSFORM_FEEDBACK_BUFFER - if (use_transform_feedback && - gTransformPositionProgram.mProgramObject && //transform shaders are loaded - mVertexBuffer->useVBOs() && //target buffer is in VRAM - !rebuild_weights && //TODO: add support for weights - !volume.isUnique()) //source volume is NOT flexi - { //use transform feedback to pack vertex buffer - LLFastTimer t(FTM_FACE_GEOM_FEEDBACK); - LLGLEnable discard(GL_RASTERIZER_DISCARD); - LLVertexBuffer* buff = (LLVertexBuffer*) vf.mVertexBuffer.get(); - - if (vf.mVertexBuffer.isNull() || buff->getNumVerts() != vf.mNumVertices) - { - mVObjp->getVolume()->genTangents(f); - LLFace::cacheFaceInVRAM(vf); - buff = (LLVertexBuffer*) vf.mVertexBuffer.get(); - } - - LLGLSLShader* cur_shader = LLGLSLShader::sCurBoundShaderPtr; - - gGL.pushMatrix(); - gGL.loadMatrix(mat_vert_in); - - if (rebuild_pos) - { - LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_POSITION); - gTransformPositionProgram.bind(); - - mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount); - - U8 index = mTextureIndex < 255 ? mTextureIndex : 0; - - S32 val = 0; - U8* vp = (U8*) &val; - vp[0] = index; - vp[1] = 0; - vp[2] = 0; - vp[3] = 0; - - gTransformPositionProgram.uniform1i(sTextureIndexIn, val); - glBeginTransformFeedback(GL_POINTS); - buff->setBuffer(LLVertexBuffer::MAP_VERTEX); - - push_for_transform(buff, vf.mNumVertices, mGeomCount); - - glEndTransformFeedback(); - } - - if (rebuild_color) - { - LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_COLOR); - gTransformColorProgram.bind(); - - mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_COLOR, mGeomIndex, mGeomCount); - - S32 val = *((S32*) color.mV); - - gTransformColorProgram.uniform1i(sColorIn, val); - glBeginTransformFeedback(GL_POINTS); - buff->setBuffer(LLVertexBuffer::MAP_VERTEX); - push_for_transform(buff, vf.mNumVertices, mGeomCount); - glEndTransformFeedback(); - } - - if (rebuild_emissive) - { - LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_EMISSIVE); - gTransformColorProgram.bind(); - - mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_EMISSIVE, mGeomIndex, mGeomCount); - - U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); - - S32 glow32 = glow | - (glow << 8) | - (glow << 16) | - (glow << 24); - - gTransformColorProgram.uniform1i(sColorIn, glow32); - glBeginTransformFeedback(GL_POINTS); - buff->setBuffer(LLVertexBuffer::MAP_VERTEX); - push_for_transform(buff, vf.mNumVertices, mGeomCount); - glEndTransformFeedback(); - } - - if (rebuild_normal) - { - LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_NORMAL); - gTransformNormalProgram.bind(); - - mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_NORMAL, mGeomIndex, mGeomCount); - - glBeginTransformFeedback(GL_POINTS); - buff->setBuffer(LLVertexBuffer::MAP_NORMAL); - push_for_transform(buff, vf.mNumVertices, mGeomCount); - glEndTransformFeedback(); - } - - if (rebuild_tangent) - { - LLFastTimer t(FTM_FACE_GEOM_TANGENT); - gTransformTangentProgram.bind(); - - mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TANGENT, mGeomIndex, mGeomCount); - - glBeginTransformFeedback(GL_POINTS); - buff->setBuffer(LLVertexBuffer::MAP_TANGENT); - push_for_transform(buff, vf.mNumVertices, mGeomCount); - glEndTransformFeedback(); - } - - if (rebuild_tcoord) - { - LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_TEXTURE); - gTransformTexCoordProgram.bind(); - - mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD0, mGeomIndex, mGeomCount); - - glBeginTransformFeedback(GL_POINTS); - buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0); - push_for_transform(buff, vf.mNumVertices, mGeomCount); - glEndTransformFeedback(); - - bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); - - if (do_bump) - { - mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD1, mGeomIndex, mGeomCount); - glBeginTransformFeedback(GL_POINTS); - buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0); - push_for_transform(buff, vf.mNumVertices, mGeomCount); - glEndTransformFeedback(); - } - } - - glBindBufferARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0); - gGL.popMatrix(); - - if (cur_shader) - { - cur_shader->bind(); - } - } - else -#endif { //if it's not fullbright and has no normals, bake sunlight based on face normal //bool bake_sunlight = !getTextureEntry()->getFullbright() && @@ -1552,7 +1398,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_tcoord) { - LLFastTimer t(FTM_FACE_GEOM_TEXTURE); + LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_TEXTURE); //bump setup LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); @@ -1560,57 +1406,61 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); LLQuaternion bump_quat; - if (mDrawablep->isActive()) - { - bump_quat = LLQuaternion(LLMatrix4(mDrawablep->getRenderMatrix().getF32ptr())); - } - - if (bump_code) + + if (!LLPipeline::sRenderDeferred) { - mVObjp->getVolume()->genTangents(f); - F32 offset_multiple; - switch( bump_code ) + if (mDrawablep->isActive()) + { + bump_quat = LLQuaternion(LLMatrix4(mDrawablep->getRenderMatrix().getF32ptr())); + } + + if (bump_code) { + mVObjp->getVolume()->genTangents(f); + F32 offset_multiple; + switch (bump_code) + { case BE_NO_BUMP: - offset_multiple = 0.f; - break; + offset_multiple = 0.f; + break; case BE_BRIGHTNESS: case BE_DARKNESS: - if( mTexture[LLRender::DIFFUSE_MAP].notNull() && mTexture[LLRender::DIFFUSE_MAP]->hasGLTexture()) - { - // Offset by approximately one texel - S32 cur_discard = mTexture[LLRender::DIFFUSE_MAP]->getDiscardLevel(); - S32 max_size = llmax( mTexture[LLRender::DIFFUSE_MAP]->getWidth(), mTexture[LLRender::DIFFUSE_MAP]->getHeight() ); - max_size <<= cur_discard; - const F32 ARTIFICIAL_OFFSET = 2.f; - offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; - } - else - { - offset_multiple = 1.f/256; - } - break; + if (mTexture[LLRender::DIFFUSE_MAP].notNull() && mTexture[LLRender::DIFFUSE_MAP]->hasGLTexture()) + { + // Offset by approximately one texel + S32 cur_discard = mTexture[LLRender::DIFFUSE_MAP]->getDiscardLevel(); + S32 max_size = llmax(mTexture[LLRender::DIFFUSE_MAP]->getWidth(), mTexture[LLRender::DIFFUSE_MAP]->getHeight()); + max_size <<= cur_discard; + const F32 ARTIFICIAL_OFFSET = 2.f; + offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; + } + else + { + offset_multiple = 1.f / 256; + } + break; default: // Standard bumpmap textures. Assumed to be 256x256 - offset_multiple = 1.f / 256; - break; - } + offset_multiple = 1.f / 256; + break; + } - F32 s_scale = 1.f; - F32 t_scale = 1.f; - if( tep ) - { - tep->getScale( &s_scale, &t_scale ); + F32 s_scale = 1.f; + F32 t_scale = 1.f; + if (tep) + { + tep->getScale(&s_scale, &t_scale); + } + // Use the nudged south when coming from above sun angle, such + // that emboss mapping always shows up on the upward faces of cubes when + // it's noon (since a lot of builders build with the sun forced to noon). + LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; + LLVector3 moon_ray = gSky.getMoonDirection(); + LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; + + bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); + bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); } - // Use the nudged south when coming from above sun angle, such - // that emboss mapping always shows up on the upward faces of cubes when - // it's noon (since a lot of builders build with the sun forced to noon). - LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; - LLVector3 moon_ray = gSky.getMoonDirection(); - LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; - - bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); - bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); } U8 texgen = getTextureEntry()->getTexGen(); @@ -1648,7 +1498,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, do_xform = false; } - if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) + if (getVirtualSize() >= MIN_TEX_ANIM_SIZE || isState(LLFace::RIGGED)) { //don't override texture transform during tc bake tex_mode = 0; } @@ -1675,18 +1525,18 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (texgen != LLTextureEntry::TEX_GEN_PLANAR) { - LLFastTimer t(FTM_FACE_TEX_QUICK); + LL_RECORD_BLOCK_TIME(FTM_FACE_TEX_QUICK); if (!do_tex_mat) { if (!do_xform) { - LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); + LL_RECORD_BLOCK_TIME(FTM_FACE_TEX_QUICK_NO_XFORM); S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; LLVector4a::memcpyNonAliased16((F32*) tex_coords0.get(), (F32*) vf.mTexCoords, tc_size); } else { - LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM); + LL_RECORD_BLOCK_TIME(FTM_FACE_TEX_QUICK_XFORM); F32* dst = (F32*) tex_coords0.get(); LLVector4a* src = (LLVector4a*) vf.mTexCoords; @@ -1735,7 +1585,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } else { //no bump, no atlas, tex gen planar - LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR); + LL_RECORD_BLOCK_TIME(FTM_FACE_TEX_QUICK_PLANAR); if (do_tex_mat) { for (S32 i = 0; i < num_vertices; i++) @@ -1777,7 +1627,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } else { //either bump mapped or in atlas, just do the whole expensive loop - LLFastTimer t(FTM_FACE_TEX_DEFAULT); + LL_RECORD_BLOCK_TIME(FTM_FACE_TEX_DEFAULT); std::vector bump_tc; @@ -1881,7 +1731,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mVertexBuffer->flush(); } - if (!mat && do_bump) + if ( !LLPipeline::sRenderDeferred && do_bump ) { mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount, map_range); @@ -1934,7 +1784,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a* end = src+num_vertices; //LLVector4a* end_64 = end-4; - //LLFastTimer t(FTM_FACE_GEOM_POSITION); + //LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_POSITION); llassert(num_vertices > 0); mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); @@ -1971,7 +1821,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a tmp; { - //LLFastTimer t2(FTM_FACE_POSITION_STORE); + //LL_RECORD_BLOCK_TIME(FTM_FACE_POSITION_STORE); /*if (num_vertices > 4) { //more than 64 bytes @@ -2011,7 +1861,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } { - //LLFastTimer t(FTM_FACE_POSITION_PAD); + //LL_RECORD_BLOCK_TIME(FTM_FACE_POSITION_PAD); while (dst < end_f32) { res0.store4a((F32*) dst); @@ -2028,7 +1878,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_normal) { - //LLFastTimer t(FTM_FACE_GEOM_NORMAL); + //LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_NORMAL); mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); F32* normals = (F32*) norm.get(); LLVector4a* src = vf.mNormals; @@ -2050,7 +1900,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_tangent) { - LLFastTimer t(FTM_FACE_GEOM_TANGENT); + LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_TANGENT); mVertexBuffer->getTangentStrider(tangent, mGeomIndex, mGeomCount, map_range); F32* tangents = (F32*) tangent.get(); @@ -2058,11 +1908,21 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a* src = vf.mTangents; LLVector4a* end = vf.mTangents+num_vertices; + LLVector4a* src2 = vf.mNormals; + LLVector4a* end2 = vf.mNormals+num_vertices; + + LLMaterial* mat = tep->getMaterialParams().get(); + F32 rot = RAD_TO_DEG * ( (mat && mat->getNormalID().notNull()) ? mat->getNormalRotation() : r); + bool rotate_tangent = src2 && !is_approx_equal(rot, 360.f) && !is_approx_zero(rot); while (src < end) { - LLVector4a tangent_out; - mat_normal.rotate(*src, tangent_out); + LLVector4a tangent_out = *src; + if (rotate_tangent && src2 < end2) + { + gGL.genRot(rot, *src2++).rotate(tangent_out, tangent_out); + } + mat_normal.rotate(tangent_out, tangent_out); tangent_out.normalize3fast(); tangent_out.copyComponent<3>(*src); tangent_out.store4a(tangents); @@ -2079,7 +1939,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_weights && vf.mWeights) { - LLFastTimer t(FTM_FACE_GEOM_WEIGHTS); + LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_WEIGHTS); mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); for(S32 i=0;ihasDataType(LLVertexBuffer::TYPE_COLOR) ) { - LLFastTimer t(FTM_FACE_GEOM_COLOR); + LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_COLOR); mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range); LLVector4a src; @@ -2124,7 +1984,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_emissive) { - LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); + LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_EMISSIVE); LLStrider emissive; mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range); @@ -2619,12 +2479,25 @@ LLViewerTexture* LLFace::getTexture(U32 ch) const void LLFace::setVertexBuffer(LLVertexBuffer* buffer) { + if (buffer) + { + LLSculptIDSize::instance().inc(mDrawablep, buffer->getSize() + buffer->getIndicesSize()); + } + + if (mVertexBuffer) + { + LLSculptIDSize::instance().dec(mDrawablep); + } mVertexBuffer = buffer; llassert(verify()); } void LLFace::clearVertexBuffer() { + if (mVertexBuffer) + { + LLSculptIDSize::instance().dec(mDrawablep); + } mVertexBuffer = NULL; } diff --git a/indra/newview/llface.h b/indra/newview/llface.h index ebd8bb6dfc..e0e478df6e 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -237,6 +237,9 @@ class LLFace static U32 getRiggedDataMask(U32 type); + void notifyAboutCreatingTexture(LLViewerTexture *texture); + void notifyAboutMissingAsset(LLViewerTexture *texture); + public: //aligned members LL_ALIGN_16(LLVector4a mExtents[2]); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index efb981f790..98bdcf0f63 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -397,13 +397,13 @@ BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks) return TRUE; } -static LLFastTimer::DeclareTimer FTM_RENDER_TIMER("Timers", true); +static LLTrace::BlockTimerStatHandle FTM_RENDER_TIMER("Timers", true); static std::map sTimerColors; void LLFastTimerView::draw() { - LLFastTimer t(FTM_RENDER_TIMER); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TIMER); std::string tdesc; @@ -421,7 +421,7 @@ void LLFastTimerView::draw() S32 left, top, right, bottom; S32 x, y, barw, barh, dx, dy; S32 texth; - LLPointer box_imagep = LLUI::getUIImage("rounded_square.tga"); + LLPointer box_imagep = LLUI::getUIImage("Rounded_Square"); // Draw the window background gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -884,7 +884,8 @@ void LLFastTimerView::draw() gGL.color4fv(color.mV); F32 start_fragment = llclamp((F32)(left - sublevel_left[level]) / (F32)sublevel_dx[level], 0.f, 1.f); F32 end_fragment = llclamp((F32)(right - sublevel_left[level]) / (F32)sublevel_dx[level], 0.f, 1.f); - gl_segmented_rect_2d_fragment_tex(sublevel_left[level], top - level + scale_offset, sublevel_right[level], bottom + level - scale_offset, box_imagep->getTextureWidth(), box_imagep->getTextureHeight(), 16, start_fragment, end_fragment); + LLRect rect(sublevel_left[level], top - level + scale_offset, sublevel_right[level], bottom + level - scale_offset); + gl_segmented_rect_2d_fragment_tex(rect, box_imagep->getTextureWidth(), box_imagep->getTextureHeight(), 16, start_fragment, end_fragment); } @@ -964,7 +965,7 @@ void LLFastTimerView::draw() if (mHoverID == idp) { gGL.flush(); - glLineWidth(3); + gGL.setLineWidth(3); } const F32 * col = sTimerColors[idp].mV;// ft_display_table[idx].color->mV; @@ -1014,7 +1015,7 @@ void LLFastTimerView::draw() if (mHoverID == idp) { gGL.flush(); - glLineWidth(1); + gGL.setLineWidth(1); } if (idp->getCollapsed()) @@ -1025,7 +1026,7 @@ void LLFastTimerView::draw() } //interpolate towards new maximum - last_max = (U64) lerp((F32)last_max, (F32) cur_max, LLCriticalDamp::getInterpolant(0.1f)); + last_max = (U64) lerp((F32)last_max, (F32) cur_max, LLSmoothInterpolation::getInterpolant(0.1f)); if (last_max - cur_max <= 1 || cur_max - last_max <= 1) { last_max = cur_max; @@ -1033,7 +1034,7 @@ void LLFastTimerView::draw() F32 alpha_target = last_max > cur_max ? llmin((F32) last_max/ (F32) cur_max - 1.f,1.f) : llmin((F32) cur_max/ (F32) last_max - 1.f,1.f); - alpha_interp = lerp(alpha_interp, alpha_target, LLCriticalDamp::getInterpolant(0.1f)); + alpha_interp = lerp(alpha_interp, alpha_target, LLSmoothInterpolation::getInterpolant(0.1f)); if (mHoverID != NULL) { @@ -1305,7 +1306,7 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t last_p.clear(); - LLGLDisable cull(GL_CULL_FACE); + LLGLDisable cull; LLVector3 base_col(0, 0.7f, 0.f); LLVector3 cur_col(1.f, 0.f, 0.f); @@ -1329,7 +1330,7 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t last_p.clear(); { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.color3fv(cur_col.mV); for (U32 i = 0; i < cur_times.size(); ++i) @@ -1370,7 +1371,7 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t gGL.flush(); { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.color3fv(cur_col.mV); last_p.clear(); @@ -1418,7 +1419,7 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t last_p.clear(); { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.color3fv(cur_col.mV); count = 0; total_count = cur_execution.size(); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp new file mode 100644 index 0000000000..254d750cb7 --- /dev/null +++ b/indra/newview/llfavoritesbar.cpp @@ -0,0 +1,1802 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +/** + * @file llfavoritesbar.cpp + * @brief LLFavoritesBarCtrl class implementation + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfavoritesbar.h" + +//#include "llfloaterreg.h" +#include "llfocusmgr.h" +#include "llinventory.h" +#include "lllandmarkactions.h" +//#include "lltoolbarview.h" +#include "lltrans.h" +#include "llmenugl.h" +//#include "lltooltip.h" +#include "lluictrlfactory.h" + +#include "llagent.h" +#include "llavatarnamecache.h" +#include "llclipboard.h" +#include "llinventorybridge.h" +#include "llinventoryclipboard.h" +#include "llinventoryfunctions.h" +//#include "llfloatersidepanelcontainer.h" +#include "llfloaterworldmap.h" +#include "lllandmarkactions.h" +//#include "lllogininstance.h" +#include "llnotificationsutil.h" +//#include "lltoggleablemenu.h" +#include "llviewerinventory.h" +#include "llviewermenu.h" +#include "hippogridmanager.h" //"llviewernetwork.h" +#include "lltooldraganddrop.h" +#include "llsdserialize.h" + +void open_landmark(LLViewerInventoryItem* inv_item, const std::string& title, BOOL show_keep_discard, const LLUUID& source_id, BOOL take_focus); + +static LLRegisterWidget r("favorites_bar"); + +const S32 DROP_DOWN_MENU_WIDTH = 250; +const S32 DROP_DOWN_MENU_TOP_PAD = 13; + +/** + * Helper for LLFavoriteLandmarkButton and LLFavoriteLandmarkMenuItem. + * Performing requests for SLURL for given Landmark ID + */ +class LLLandmarkInfoGetter +{ +public: + LLLandmarkInfoGetter() + : mLandmarkID(LLUUID::null), + mName("(Loading...)"), + mPosX(0), + mPosY(0), + mPosZ(0), + mLoaded(false) + { + mHandle.bind(this); + } + + void setLandmarkID(const LLUUID& id) { mLandmarkID = id; } + const LLUUID& getLandmarkId() const { return mLandmarkID; } + + const std::string& getName() + { + if(!mLoaded) + requestNameAndPos(); + + return mName; + } + + S32 getPosX() + { + if (!mLoaded) + requestNameAndPos(); + return mPosX; + } + + S32 getPosY() + { + if (!mLoaded) + requestNameAndPos(); + return mPosY; + } + + S32 getPosZ() + { + if (!mLoaded) + requestNameAndPos(); + return mPosZ; + } + +private: + /** + * Requests landmark data from server. + */ + void requestNameAndPos() + { + if (mLandmarkID.isNull()) + return; + + LLVector3d g_pos; + if(LLLandmarkActions::getLandmarkGlobalPos(mLandmarkID, g_pos)) + { + LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(g_pos, + boost::bind(&LLLandmarkInfoGetter::landmarkNameCallback, static_cast >(mHandle), _1, _2, _3, _4)); + } + } + + static void landmarkNameCallback(LLHandle handle, const std::string& name, S32 x, S32 y, S32 z) + { + LLLandmarkInfoGetter* getter = handle.get(); + if (getter) + { + getter->mPosX = x; + getter->mPosY = y; + getter->mPosZ = z; + getter->mName = name; + getter->mLoaded = true; + } + } + + LLUUID mLandmarkID; + std::string mName; + S32 mPosX; + S32 mPosY; + S32 mPosZ; + bool mLoaded; + LLRootHandle mHandle; +}; + +/** + * This class is needed to override LLButton default handleToolTip function and + * show SLURL as button tooltip. + * *NOTE: dzaporozhan: This is a workaround. We could set tooltips for buttons + * in createButtons function but landmark data is not available when Favorites Bar is + * created. Thats why we are requesting landmark data after + */ +class LLFavoriteLandmarkButton : public LLButton +{ +public: + + BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect) override + { + std::string region_name = mLandmarkInfoGetter.getName(); + + if (!region_name.empty()) + { + std::string extra_message = llformat("%s (%d, %d, %d)", region_name.c_str(), + mLandmarkInfoGetter.getPosX(), mLandmarkInfoGetter.getPosY(), mLandmarkInfoGetter.getPosZ()); + + msg = llformat("%s\n%s", getLabelSelected().c_str(), extra_message.c_str()); + *sticky_rect = calcScreenRect(); + } + return TRUE; + } + + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override + { + LLFavoritesBarCtrl* fb = dynamic_cast(getParent()); + + if (fb) + { + fb->handleHover(x, y, mask); + } + + return LLButton::handleHover(x, y, mask); + } + + void setLandmarkID(const LLUUID& id){ mLandmarkInfoGetter.setLandmarkID(id); } + const LLUUID& getLandmarkId() const { return mLandmarkInfoGetter.getLandmarkId(); } + + void onMouseEnter(S32 x, S32 y, MASK mask) override + { + if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) + { + LLUICtrl::onMouseEnter(x, y, mask); + } + else + { + LLButton::onMouseEnter(x, y, mask); + } + } + +//protected: + LLFavoriteLandmarkButton(const LLButton::Params& p) : LLButton(p) {} + friend class LLUICtrlFactory; + +private: + LLLandmarkInfoGetter mLandmarkInfoGetter; +}; + +/** + * This class is needed to override LLMenuItemCallGL default handleToolTip function and + * show SLURL as button tooltip. + * *NOTE: dzaporozhan: This is a workaround. We could set tooltips for buttons + * in showDropDownMenu function but landmark data is not available when Favorites Bar is + * created. Thats why we are requesting landmark data after + */ +class LLFavoriteLandmarkMenuItem : public LLMenuItemCallGL +{ +public: + BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect) override + { + std::string region_name = mLandmarkInfoGetter.getName(); + if (!region_name.empty()) + { + msg = llformat("%s\n%s (%d, %d)", getLabel().c_str(), region_name.c_str(), mLandmarkInfoGetter.getPosX(), mLandmarkInfoGetter.getPosY()); + *sticky_rect = calcScreenRect(); + } + return TRUE; + } + + void setLandmarkID(const LLUUID& id){ mLandmarkInfoGetter.setLandmarkID(id); } + + BOOL handleMouseDown(S32 x, S32 y, MASK mask) override + { + if (mMouseDownSignal) + (*mMouseDownSignal)(this, x, y, mask); + return LLMenuItemCallGL::handleMouseDown(x, y, mask); + } + + BOOL handleMouseUp(S32 x, S32 y, MASK mask) override + { + if (mMouseUpSignal) + (*mMouseUpSignal)(this, x, y, mask); + return LLMenuItemCallGL::handleMouseUp(x, y, mask); + } + + BOOL handleHover(S32 x, S32 y, MASK mask) override + { + if (fb) + { + fb->handleHover(x, y, mask); + } + + return TRUE; + } + + void initFavoritesBarPointer(LLFavoritesBarCtrl* fb) { this->fb = fb; } + +//protected: + + LLFavoriteLandmarkMenuItem(const LLMenuItemCallGL::Params& p) : LLMenuItemCallGL(p.name(), p.label(), nullptr), fb(nullptr) {} + friend class LLUICtrlFactory; + +private: + LLLandmarkInfoGetter mLandmarkInfoGetter; + LLFavoritesBarCtrl* fb; +}; + +/** + * This class was introduced just for fixing the following issue: + * EXT-836 Nav bar: Favorites overflow menu passes left-mouse click through. + * We must explicitly handle drag and drop event by returning TRUE + * because otherwise LLToolDragAndDrop will initiate drag and drop operation + * with the world. + */ +class LLFavoriteLandmarkToggleableMenu : public LLMenuGL +{ +public: + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) override + { + *accept = ACCEPT_NO; + return TRUE; + } + +//protected: + LLFavoriteLandmarkToggleableMenu(): + LLMenuGL("favorites menu") + { + } + + friend class LLUICtrlFactory; +}; + +/** + * This class is needed to update an item being copied to the favorites folder + * with a sort field value (required to save favorites bar's tabs order). + * See method handleNewFavoriteDragAndDrop for more details on how this class is used. + */ +class LLItemCopiedCallback : public LLInventoryCallback +{ +public: + LLItemCopiedCallback(S32 sortField): mSortField(sortField) {} + + void fire(const LLUUID& inv_item) override + { + LLViewerInventoryItem* item = gInventory.getItem(inv_item); + + if (item) + { + LLFavoritesOrderStorage::instance().setSortIndex(item, mSortField); + + item->setComplete(TRUE); + item->updateServer(FALSE); + + gInventory.updateItem(item); + gInventory.notifyObservers(); + LLFavoritesOrderStorage::instance().saveOrder(); + } + + LLView::getWindow()->setCursor(UI_CURSOR_ARROW); + } + +private: + S32 mSortField; +}; + +// updateButtons's helper +struct LLFavoritesSort +{ + // Sorting by creation date and name + // TODO - made it customizible using gSavedSettings + bool operator()(const LLViewerInventoryItem* const& a, const LLViewerInventoryItem* const& b) const + { + S32 sortField1 = LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()); + S32 sortField2 = LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); + + if (!(sortField1 < 0 && sortField2 < 0)) + { + return sortField2 > sortField1; + } + + time_t first_create = a->getCreationDate(); + time_t second_create = b->getCreationDate(); + if (first_create == second_create) + { + return (LLStringUtil::compareDict(a->getName(), b->getName()) < 0); + } + else + { + return (first_create > second_create); + } + } +}; + +LLFavoritesBarCtrl::Params::Params() +: image_drag_indication("image_drag_indication"), + more_button("more_button"), + label("label") +{ +} + +LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p) +: LLUICtrl(p), + mOverflowMenuHandle(), + mContextMenuHandle(), + mFont(p.font.isProvided() ? p.font() : LLFontGL::getFontSansSerifSmall()), + mUpdateDropDownItems(true), + mRestoreOverflowMenu(false), + mImageDragIndication(p.image_drag_indication), + mShowDragMarker(FALSE), + mLandingTab(NULL) + , mLastTab(NULL) +, mTabsHighlightEnabled(TRUE) +{ + // Register callback for menus with current registrar (will be parent panel's registrar) + LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Favorites.DoToSelected", + boost::bind(&LLFavoritesBarCtrl::doToSelected, this, _2)); + + // Add this if we need to selectively enable items + LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Favorites.EnableSelected", + boost::bind(&LLFavoritesBarCtrl::enableSelected, this, _2)); + + gInventory.addObserver(this); + + //make chevron button + mMoreTextBox = new LLTextBox(">>", "\u0032", 50); + mMoreTextBox->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM); + mMoreTextBox->setToolTip(LLStringExplicit("Show more of My Favorites")); + mMoreTextBox->setTabStop(false); + mMoreTextBox->setClickedCallback(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this)); + addChild(mMoreTextBox); + + mDropDownItemsCount = 0; + + mBarLabel = new LLTextBox(p.label.name, p.label.label); + addChild(mBarLabel); +} + +LLFavoritesBarCtrl::~LLFavoritesBarCtrl() +{ + gInventory.removeObserver(this); + + if (mOverflowMenuHandle.get()) mOverflowMenuHandle.get()->die(); + if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); +} + +BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + *accept = ACCEPT_NO; + + LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); + if (LLToolDragAndDrop::SOURCE_AGENT != source && LLToolDragAndDrop::SOURCE_LIBRARY != source) return FALSE; + + switch (cargo_type) + { + + case DAD_LANDMARK: + { + /* + * add a callback to the end drag event. + * the callback will disconnet itself immediately after execution + * this is done because LLToolDragAndDrop is a common tool so it shouldn't + * be overloaded with redundant callbacks. + */ + if (!mEndDragConnection.connected()) + { + mEndDragConnection = LLToolDragAndDrop::getInstance()->setEndDragCallback(boost::bind(&LLFavoritesBarCtrl::onEndDrag, this)); + } + + // Copy the item into the favorites folder (if it's not already there). + LLInventoryItem *item = (LLInventoryItem *)cargo_data; + + if (LLFavoriteLandmarkButton* dest = dynamic_cast(findChildByLocalCoords(x, y))) + { + setLandingTab(dest); + } + else if (mLastTab && (x >= mLastTab->getRect().mRight)) + { + /* + * the condition dest == NULL can be satisfied not only in the case + * of dragging to the right from the last tab of the favbar. there is a + * small gap between each tab. if the user drags something exactly there + * then mLandingTab will be set to NULL and the dragged item will be pushed + * to the end of the favorites bar. this is incorrect behavior. that's why + * we need an additional check which excludes the case described previously + * making sure that the mouse pointer is beyond the last tab. + */ + setLandingTab(NULL); + } + + // check if we are dragging an existing item from the favorites bar + if (item && mDragItemId == item->getUUID()) + { + *accept = ACCEPT_YES_SINGLE; + + showDragMarker(TRUE); + + if (drop) + { + handleExistingFavoriteDragAndDrop(x, y); + } + } + else + { + const LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + if (item && item->getParentUUID() == favorites_id) + { + LL_WARNS("FavoritesBar") << "Attemt to copy a favorite item into the same folder." << LL_ENDL; + break; + } + + *accept = ACCEPT_YES_COPY_MULTI; + + showDragMarker(TRUE); + + if (drop) + { + if (mItems.empty()) + { + setLandingTab(NULL); + } + handleNewFavoriteDragAndDrop(item, favorites_id, x, y); + } + } + } + break; + default: + break; + } + + return TRUE; +} + +void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y) +{ + // Identify the button hovered and the side to drop + LLFavoriteLandmarkButton* dest = dynamic_cast(mLandingTab); + bool insert_before = true; + if (!dest) + { + insert_before = false; + dest = dynamic_cast(mLastTab); + } + + // There is no need to handle if an item was dragged onto itself + if (dest && dest->getLandmarkId() == mDragItemId) + { + return; + } + + // Insert the dragged item in the right place + if (dest) + { + LLInventoryModel::updateItemsOrder(mItems, mDragItemId, dest->getLandmarkId(), insert_before); + } + else + { + // This can happen when the item list is empty + mItems.push_back(gInventory.getItem(mDragItemId)); + } + + LLFavoritesOrderStorage::instance().saveItemsOrder(mItems); + + LLMenuGL* menu = (LLMenuGL*) mOverflowMenuHandle.get(); + + if (menu && menu->getVisible()) + { + menu->setVisible(FALSE); + showDropDownMenu(); + } +} + +void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y) +{ + if (!item) return; + // Identify the button hovered and the side to drop + LLFavoriteLandmarkButton* dest = NULL; + bool insert_before = true; + if (!mItems.empty()) + { + // [MAINT-2386] When multiple landmarks are selected and dragged onto an empty favorites bar, + // the viewer would crash when casting mLastTab below, as mLastTab is still null when the + // second landmark is being added. + // To ensure mLastTab is valid, we need to call updateButtons() at the end of this function + dest = dynamic_cast(mLandingTab); + if (!dest) + { + insert_before = false; + dest = dynamic_cast(mLastTab); + } + } + + // There is no need to handle if an item was dragged onto itself + if (dest && dest->getLandmarkId() == mDragItemId) + { + return; + } + + LLPointer viewer_item = new LLViewerInventoryItem(item); + + // Insert the dragged item in the right place + if (dest) + { + insertItem(mItems, dest->getLandmarkId(), viewer_item, insert_before); + } + else + { + // This can happen when the item list is empty + mItems.push_back(viewer_item); + } + + int sortField = 0; + LLPointer cb; + + // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field + for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i) + { + LLViewerInventoryItem* currItem = *i; + + if (currItem->getUUID() == item->getUUID()) + { + cb = new LLItemCopiedCallback(++sortField); + } + else + { + LLFavoritesOrderStorage::instance().setSortIndex(currItem, ++sortField); + + currItem->setComplete(TRUE); + currItem->updateServer(FALSE); + + gInventory.updateItem(currItem); + } + } + + LLToolDragAndDrop* tool_dad = LLToolDragAndDrop::getInstance(); + if (tool_dad->getSource() == LLToolDragAndDrop::SOURCE_NOTECARD) + { + viewer_item->setType(LLAssetType::AT_LANDMARK); + copy_inventory_from_notecard(favorites_id, + tool_dad->getObjectID(), + tool_dad->getSourceID(), + viewer_item.get(), + gInventoryCallbacks.registerCB(cb)); + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + favorites_id, + std::string(), + cb); + } + + // [MAINT-2386] Ensure the favorite button has been created and is valid. + // This also ensures that mLastTab will be valid when dropping multiple + // landmarks to an empty favorites bar. + updateButtons(); + + LL_INFOS("FavoritesBar") << "Copied inventory item #" << item->getUUID() << " to favorites." << LL_ENDL; +} + +//virtual +void LLFavoritesBarCtrl::changed(U32 mask) +{ + if (mFavoriteFolderId.isNull()) + { + mFavoriteFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + + if (mFavoriteFolderId.notNull()) + { + gInventory.fetchDescendentsOf(mFavoriteFolderId); + } + } + else + { + LLInventoryModel::item_array_t items; + LLInventoryModel::cat_array_t cats; + LLIsType is_type(LLAssetType::AT_LANDMARK); + gInventory.collectDescendentsIf(mFavoriteFolderId, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + + for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) + { + LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID()); + } + + updateButtons(); + } +} + +//virtual +void LLFavoritesBarCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + LLUICtrl::reshape(width, height, called_from_parent); + updateButtons(); +} + +void LLFavoritesBarCtrl::draw() +{ + LLUICtrl::draw(); + + if (mShowDragMarker) + { + S32 w = mImageDragIndication->getWidth(); + S32 h = mImageDragIndication->getHeight(); + + if (mLandingTab) + { + // mouse pointer hovers over an existing tab + LLRect rect = mLandingTab->getRect(); + mImageDragIndication->draw(rect.mLeft, rect.getHeight(), w, h); + } + else if (mLastTab) + { + // mouse pointer hovers over the favbar empty space (right to the last tab) + LLRect rect = mLastTab->getRect(); + mImageDragIndication->draw(rect.mRight, rect.getHeight(), w, h); + } + // Once drawn, mark this false so we won't draw it again (unless we hit the favorite bar again) + mShowDragMarker = FALSE; + } +} + +const LLButton::Params& LLFavoritesBarCtrl::getButtonParams() +{ + static LLButton::Params button_params; + static bool params_initialized = false; + + if (!params_initialized) + { + button_params.image_overlay(LLUI::getUIImage("Favorite_Link_Over")) + .hover_glow_amount(0.15f) + .use_ellipses(true).tab_stop(false) + .name("favorites_bar_btn") + .follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM); + params_initialized = true; + } + + return button_params; +} + +void LLFavoritesBarCtrl::updateButtons() +{ + mItems.clear(); + + if (!collectFavoriteItems(mItems)) + { + return; + } + + const LLButton::Params& button_params = getButtonParams(); + + if(mItems.empty()) + { + mBarLabel->setVisible(TRUE); + } + else + { + mBarLabel->setVisible(FALSE); + } + const child_list_t* childs = getChildList(); + child_list_const_iter_t child_it = childs->begin(); + size_t first_changed_item_index = 0; + int rightest_point = getRect().mRight - mMoreTextBox->getRect().getWidth(); + //lets find first changed button + while (child_it != childs->end() && first_changed_item_index < mItems.size()) + { + LLFavoriteLandmarkButton* button = dynamic_cast (*child_it); + if (button) + { + const LLViewerInventoryItem *item = mItems[first_changed_item_index].get(); + if (item) + { + // an child's order and mItems should be same + if (button->getLandmarkId() != item->getUUID() // sort order has been changed + || button->getLabelSelected() != item->getName() // favorite's name has been changed + || button->getRect().mRight < rightest_point) // favbar's width has been changed + { + break; + } + } + first_changed_item_index++; + } + child_it++; + } + // now first_changed_item_index should contains a number of button that need to change + + if (first_changed_item_index <= mItems.size()) + { + // Rebuild the buttons only + // child_list_t is a linked list, so safe to erase from the middle if we pre-increment the iterator + + while (child_it != childs->end()) + { + //lets remove other landmarks button and rebuild it + child_list_const_iter_t cur_it = child_it++; + LLFavoriteLandmarkButton* button = + dynamic_cast (*cur_it); + if (button) + { + removeChild(button); + delete button; + } + } + // we have to remove ChevronButton to make sure that the last item will be LandmarkButton to get the right aligning + // keep in mind that we are cutting all buttons in space between the last visible child of favbar and ChevronButton + if (mMoreTextBox->getParent() == this) + { + removeChild(mMoreTextBox); + } + int last_right_edge = 0; + //calculate new buttons offset + if (getChildList()->size() > 0) + { + //find last visible child to get the rightest button offset + child_list_const_reverse_iter_t last_visible_it = std::find_if(childs->rbegin(), childs->rend(), + std::mem_fn(&LLView::getVisible)); + if(last_visible_it != childs->rend()) + { + last_right_edge = (*last_visible_it)->getRect().mRight; + } + } + //last_right_edge is saving coordinates + LLButton* last_new_button = NULL; + size_t j = first_changed_item_index; + for (; j < mItems.size(); j++) + { + last_new_button = createButton(mItems[j], button_params, last_right_edge); + if (!last_new_button) + { + break; + } + sendChildToBack(last_new_button); + last_right_edge = last_new_button->getRect().mRight; + + mLastTab = last_new_button; + } + mFirstDropDownItem = j; + // Chevron button + if (mFirstDropDownItem < mItems.size()) + { + // if updateButton had been called it means: + //or there are some new favorites, or width had been changed + // so if we need to display chevron button, we must update dropdown items too. + mUpdateDropDownItems = true; + S32 buttonHGap = button_params.rect.left; // default value + LLRect rect; + // Chevron button should stay right aligned + rect.setOriginAndSize(getRect().mRight - mMoreTextBox->getRect().getWidth() - buttonHGap, 0, + mMoreTextBox->getRect().getWidth(), + mMoreTextBox->getRect().getHeight()); + + addChild(mMoreTextBox); + mMoreTextBox->setRect(rect); + mMoreTextBox->setVisible(TRUE); + } + // Update overflow menu + LLMenuGL* overflow_menu = static_cast (mOverflowMenuHandle.get()); + if (overflow_menu && overflow_menu->getVisible() && (overflow_menu->getItemCount() != mDropDownItemsCount)) + { + overflow_menu->setVisible(FALSE); + if (mUpdateDropDownItems) + { + showDropDownMenu(); + } + } + } + else + { + mUpdateDropDownItems = false; + } + +} + +LLButton* LLFavoritesBarCtrl::createButton(const LLPointer item, const LLButton::Params& button_params, S32 x_offset) +{ + S32 def_button_width = button_params.rect.width; + S32 button_x_delta = button_params.rect.left; // default value + S32 curr_x = x_offset; + + /** + * WORKAROUND: + * There are some problem with displaying of fonts in buttons. + * Empty space or ellipsis might be displayed instead of last symbols, even though the width of the button is enough. + * The problem disappears if we pad the button with 20 pixels. + */ + int required_width = mFont->getWidth(item->getName()) + 20; + int width = required_width > def_button_width? def_button_width : required_width; + LLFavoriteLandmarkButton* fav_btn = NULL; + + // do we have a place for next button + double buttonHGap + mMoreTextBox ? + if(curr_x + width + 2*button_x_delta + mMoreTextBox->getRect().getWidth() > getRect().mRight ) + { + return NULL; + } + LLButton::Params fav_btn_params(button_params); + fav_btn = new LLFavoriteLandmarkButton(fav_btn_params); + if (NULL == fav_btn) + { + LL_WARNS("FavoritesBar") << "Unable to create LLFavoriteLandmarkButton widget: " << item->getName() << LL_ENDL; + return NULL; + } + + addChild(fav_btn); + + LLRect butt_rect (fav_btn->getRect()); + fav_btn->setLandmarkID(item->getUUID()); + butt_rect.setOriginAndSize(curr_x + button_x_delta, fav_btn->getRect().mBottom, width, fav_btn->getRect().getHeight()); + + fav_btn->setRect(butt_rect); + // change only left and save bottom + fav_btn->setFont(mFont); + fav_btn->setLabel(item->getName()); + fav_btn->setToolTip(item->getName()); + fav_btn->setCommitCallback(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID())); + fav_btn->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID(), _1, _2, _3,_4 )); + + fav_btn->LLUICtrl::setMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseDown, this, item->getUUID(), _1, _2, _3, _4)); + fav_btn->LLUICtrl::setMouseUpCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseUp, this, item->getUUID(), _1, _2, _3, _4)); + + return fav_btn; +} + + +BOOL LLFavoritesBarCtrl::postBuild() +{ + // make the popup menu available + LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_favorites.xml", gMenuHolder); + if (!menu) + { + return FALSE; //menu = LLUICtrlFactory::getDefaultWidget("inventory_menu"); + } + menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor")); + mContextMenuHandle = menu->getHandle(); + + return TRUE; +} + +BOOL collectFavoriteItems(LLInventoryModel::item_array_t& items) +{ + + auto mFavoriteFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + if (mFavoriteFolderId.isNull()) + return FALSE; + + + LLInventoryModel::cat_array_t cats; + + LLIsType is_type(LLAssetType::AT_LANDMARK); + gInventory.collectDescendentsIf(mFavoriteFolderId, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + + std::sort(items.begin(), items.end(), LLFavoritesSort()); + + BOOL needToSaveItemsOrder(const LLInventoryModel::item_array_t& items); + //if (needToSaveItemsOrder(items)) + { + S32 sortField = 0; + for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) + { + LLFavoritesOrderStorage::instance().setSortIndex((*i), ++sortField); + } + } + + return TRUE; +} +BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t& items) { return ::collectFavoriteItems(items); } + +void LLFavoritesBarCtrl::showDropDownMenu() +{ + if (mOverflowMenuHandle.isDead()) + { + createOverflowMenu(); + } + + LLMenuGL* menu = (LLMenuGL*)mOverflowMenuHandle.get(); + if (menu) + { + + if (mUpdateDropDownItems) + { + updateMenuItems(menu); + } + + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); + //menu->setButtonRect(mMoreTextBox->getRect(), this); + positionAndShowMenu(menu); + mDropDownItemsCount = menu->getItemCount(); + } +} + +void LLFavoritesBarCtrl::createOverflowMenu() +{ + LLMenuGL* menu = new LLFavoriteLandmarkToggleableMenu(); + menu->setCanTearOff(false); + menu->setVisible(false); + menu->setScrollable(true); + //menu_p.max_scrollable_items = 10; + //menu_p.preferred_width = DROP_DOWN_MENU_WIDTH; + mOverflowMenuHandle = menu->getHandle(); +} + +void LLFavoritesBarCtrl::updateMenuItems(LLMenuGL* menu) +{ + menu->empty(); + + U32 widest_item = 0; + + for (size_t i = mFirstDropDownItem; i < mItems.size(); i++) + { + LLViewerInventoryItem* item = mItems.at(i); + const std::string& item_name = item->getName(); + + LLFavoriteLandmarkMenuItem::Params item_params; + item_params.name(item_name); + item_params.label(item_name); + + LLFavoriteLandmarkMenuItem *menu_item = new LLFavoriteLandmarkMenuItem(item_params); + menu_item->setMouseUpCallback(std::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID())); + menu_item->initFavoritesBarPointer(this); + menu_item->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID(), _1, _2, _3, _4)); + menu_item->LLUICtrl::setMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseDown, this, item->getUUID(), _1, _2, _3, _4)); + menu_item->LLUICtrl::setMouseUpCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseUp, this, item->getUUID(), _1, _2, _3, _4)); + menu_item->setLandmarkID(item->getUUID()); + + fitLabelWidth(menu_item); + + widest_item = llmax(widest_item, menu_item->getNominalWidth()); + + menu->addChild(menu_item); + } + + addOpenLandmarksMenuItem(menu); + mUpdateDropDownItems = false; +} + +void LLFavoritesBarCtrl::fitLabelWidth(LLMenuItemCallGL* menu_item) +{ + U32 max_width = llmin(DROP_DOWN_MENU_WIDTH, getRect().getWidth()); + std::string item_name = menu_item->getName(); + + // Check whether item name wider than menu + if (menu_item->getNominalWidth() > max_width) + { + S32 chars_total = item_name.length(); + S32 chars_fitted = 1; + menu_item->setLabel(LLStringExplicit("")); + S32 label_space = max_width - menu_item->getFont()->getWidth("...") - + menu_item->getNominalWidth();// This returns width of menu item with empty label (pad pixels) + + while (chars_fitted < chars_total + && menu_item->getFont()->getWidth(item_name, 0, chars_fitted) < label_space) + { + chars_fitted++; + } + chars_fitted--; // Rolling back one char, that doesn't fit + + menu_item->setLabel(item_name.substr(0, chars_fitted) + "..."); + } +} + +void LLFavoritesBarCtrl::addOpenLandmarksMenuItem(LLMenuGL* menu) +{ + std::string label_untrans = "Open landmarks"; + std::string label_transl; + bool translated = LLTrans::findString(label_transl, label_untrans); + + LLMenuItemCallGL* menu_item = new LLMenuItemCallGL(std::string("open_my_landmarks"), std::string(translated ? label_transl : label_untrans), nullptr); + void show_floater(const std::string& floater_name); + menu_item->setMouseUpCallback(std::bind(show_floater, "floater_inventory_favs.xml")); + + fitLabelWidth(menu_item); + + LLMenuItemSeparatorGL* separator = new LLMenuItemSeparatorGL; + + menu->addChild(separator); + menu->addChild(menu_item); +} + +void LLFavoritesBarCtrl::positionAndShowMenu(LLMenuGL* menu) +{ + U32 max_width = llmin(DROP_DOWN_MENU_WIDTH, getRect().getWidth()); + + S32 menu_x = getRect().getWidth() - max_width; + S32 menu_y = getParent()->getRect().mBottom - DROP_DOWN_MENU_TOP_PAD; + + /* Singu TODO: Side Toolbar? + // the menu should be offset of the right edge of the window + // so it's no covered by buttons in the right-side toolbar. + LLToolBar* right_toolbar = gToolBarView->getChild("toolbar_right"); + if (right_toolbar && right_toolbar->hasButtons()) + { + S32 toolbar_top = 0; + + if (LLView* top_border_panel = right_toolbar->getChild("button_panel")) + { + toolbar_top = top_border_panel->calcScreenRect().mTop; + } + + // Calculating the bottom (in screen coord) of the drop down menu + S32 menu_top = getParent()->getRect().mBottom - DROP_DOWN_MENU_TOP_PAD; + S32 menu_bottom = menu_top - menu->getRect().getHeight(); + S32 menu_bottom_screen = 0; + + localPointToScreen(0, menu_bottom, &menu_top, &menu_bottom_screen); + + if (menu_bottom_screen < toolbar_top) + { + menu_x -= right_toolbar->getRect().getWidth(); + } + } + */ + + LLMenuGL::showPopup(this, menu, menu_x, menu_y); +} + +void LLFavoritesBarCtrl::onButtonClick(LLUUID item_id) +{ + // We only have one Inventory, gInventory. Some day this should be better abstracted. + LLInvFVBridgeAction::doAction(item_id,&gInventory); +} + +void LLFavoritesBarCtrl::onButtonRightClick( LLUUID item_id,LLView* fav_button,S32 x,S32 y,MASK mask) +{ + mSelectedItemID = item_id; + + LLMenuGL* menu = (LLMenuGL*)mContextMenuHandle.get(); + if (!menu) + { + return; + } + + // Remember that the context menu was shown simultaneously with the overflow menu, + // so that we can restore the overflow menu when user clicks a context menu item + // (which hides the overflow menu). + { + LLView* overflow_menu = mOverflowMenuHandle.get(); + mRestoreOverflowMenu = overflow_menu && overflow_menu->getVisible(); + } + + // Release mouse capture so hover events go to the popup menu + // because this is happening during a mouse down. + gFocusMgr.setMouseCapture(NULL); + + menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(fav_button, menu, x, y); +} + +BOOL LLFavoritesBarCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = childrenHandleRightMouseDown( x, y, mask) != NULL; + /*if(!handled && !gMenuHolder->hasVisibleMenu()) + { + show_navbar_context_menu(this,x,y); + handled = true; + }*/ + + return handled; +} +void copy_slurl_to_clipboard_cb(std::string& slurl) +{ + LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl)); + + LLSD args; + args["SLURL"] = slurl; + LLNotificationsUtil::add("CopySLURL", args); +} + + +bool LLFavoritesBarCtrl::enableSelected(const LLSD& userdata) +{ + std::string param = userdata.asString(); + + if (param == std::string("can_paste")) + { + return isClipboardPasteable(); + } + + return false; +} + +void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) +{ + std::string action = userdata.asString(); + LL_INFOS("FavoritesBar") << "Action = " << action << " Item = " << mSelectedItemID.asString() << LL_ENDL; + + LLViewerInventoryItem* item = gInventory.getItem(mSelectedItemID); + if (!item) + return; + + if (action == "open") + { + onButtonClick(item->getUUID()); + } + else if (action == "about") + { + LLSD key; + key["type"] = "landmark"; + key["id"] = mSelectedItemID; + + open_landmark(item, "Favorite", false, mSelectedItemID, true); + } + else if (action == "copy_slurl") + { + LLVector3d posGlobal; + LLLandmarkActions::getLandmarkGlobalPos(mSelectedItemID, posGlobal); + + if (!posGlobal.isExactlyZero()) + { + LLLandmarkActions::getSLURLfromPosGlobal(posGlobal, copy_slurl_to_clipboard_cb); + } + } + else if (action == "show_on_map") + { + LLFloaterWorldMap* worldmap_instance = gFloaterWorldMap; + + LLVector3d posGlobal; + LLLandmarkActions::getLandmarkGlobalPos(mSelectedItemID, posGlobal); + + if (!posGlobal.isExactlyZero() && worldmap_instance) + { + worldmap_instance->trackLocation(posGlobal); + LLFloaterWorldMap::show(true); + } + } + else if (action == "cut") + { + } + else if (action == "copy") + { + LLInventoryClipboard::instance().add(mSelectedItemID); + } + else if (action == "paste") + { + pasteFromClipboard(); + } + else if (action == "delete") + { + gInventory.removeItem(mSelectedItemID); + } + + // Pop-up the overflow menu again (it gets hidden whenever the user clicks a context menu item). + // See EXT-4217 and STORM-207. + LLMenuGL* menu = (LLMenuGL*) mOverflowMenuHandle.get(); + if (mRestoreOverflowMenu && menu && !menu->getVisible()) + { + menu->resetScrollPositionOnShow(false); + showDropDownMenu(); + menu->resetScrollPositionOnShow(true); + } +} + +BOOL LLFavoritesBarCtrl::isClipboardPasteable() const +{ + if (!LLInventoryClipboard::instance().hasContents()) + { + return FALSE; + } + + uuid_vec_t objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.size(); + for(S32 i = 0; i < count; i++) + { + const LLUUID &item_id = objects.at(i); + + // Can't paste folders + const LLInventoryCategory *cat = gInventory.getCategory(item_id); + if (cat) + { + return FALSE; + } + + const LLInventoryItem *item = gInventory.getItem(item_id); + if (item && LLAssetType::AT_LANDMARK != item->getType()) + { + return FALSE; + } + } + return TRUE; +} + +void LLFavoritesBarCtrl::pasteFromClipboard() const +{ + LLInventoryModel* model = &gInventory; + if(model && isClipboardPasteable()) + { + LLInventoryItem* item = NULL; + uuid_vec_t objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.size(); + LLUUID parent_id(mFavoriteFolderId); + for(S32 i = 0; i < count; i++) + { + item = model->getItem(objects.at(i)); + if (item) + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + parent_id, + std::string(), + LLPointer(NULL)); + } + } + } +} + +void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask) +{ + // EXT-6997 (Fav bar: Pop-up menu for LM in overflow dropdown is kept after LM was dragged away) + // mContextMenuHandle.get() - is a pop-up menu (of items) in already opened dropdown menu. + // We have to check and set visibility of pop-up menu in such a way instead of using + // LLMenuHolderGL::hideMenus() because it will close both menus(dropdown and pop-up), but + // we need to close only pop-up menu while dropdown one should be still opened. + LLMenuGL* menu = (LLMenuGL*)mContextMenuHandle.get(); + if(menu && menu->getVisible()) + { + menu->setVisible(FALSE); + } + + mDragItemId = id; + mStartDrag = TRUE; + + S32 screenX, screenY; + localPointToScreen(x, y, &screenX, &screenY); + + LLToolDragAndDrop::getInstance()->setDragStart(screenX, screenY); +} + +void LLFavoritesBarCtrl::onButtonMouseUp(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask) +{ + mStartDrag = FALSE; + mDragItemId = LLUUID::null; +} + +void LLFavoritesBarCtrl::onEndDrag() +{ + mEndDragConnection.disconnect(); + + showDragMarker(FALSE); + mDragItemId = LLUUID::null; + LLView::getWindow()->setCursor(UI_CURSOR_ARROW); +} + +BOOL LLFavoritesBarCtrl::handleHover(S32 x, S32 y, MASK mask) +{ + if (mDragItemId != LLUUID::null && mStartDrag) + { + S32 screenX, screenY; + localPointToScreen(x, y, &screenX, &screenY); + + if(LLToolDragAndDrop::getInstance()->isOverThreshold(screenX, screenY)) + { + LLToolDragAndDrop::getInstance()->beginDrag( + DAD_LANDMARK, mDragItemId, + LLToolDragAndDrop::SOURCE_LIBRARY); + + mStartDrag = FALSE; + + return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask); + } + } + + return TRUE; +} + +LLUICtrl* LLFavoritesBarCtrl::findChildByLocalCoords(S32 x, S32 y) +{ + LLUICtrl* ctrl = NULL; + const child_list_t* list = getChildList(); + + for (child_list_const_iter_t i = list->begin(); i != list->end(); ++i) + { + // Look only for children that are favorite buttons + if ((*i)->getName() == "favorites_bar_btn") + { + LLRect rect = (*i)->getRect(); + // We consider a button hit if the cursor is left of the right side + // This makes the hit a bit less finicky than hitting directly on the button itself + if (x <= rect.mRight) + { + ctrl = dynamic_cast(*i); + break; + } + } + } + return ctrl; +} + +BOOL needToSaveItemsOrder(const LLInventoryModel::item_array_t& items) +{ + BOOL result = FALSE; + + // if there is an item without sort order field set, we need to save items order + for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) + { + if (LLFavoritesOrderStorage::instance().getSortIndex((*i)->getUUID()) < 0) + { + result = TRUE; + break; + } + } + + return result; +} +BOOL LLFavoritesBarCtrl::needToSaveItemsOrder(const LLInventoryModel::item_array_t& items) { return ::needToSaveItemsOrder(items); } + +void LLFavoritesBarCtrl::insertItem(LLInventoryModel::item_array_t& items, const LLUUID& dest_item_id, LLViewerInventoryItem* insertedItem, bool insert_before) +{ + // Get the iterator to the destination item + LLInventoryModel::item_array_t::iterator it_dest = LLInventoryModel::findItemIterByUUID(items, dest_item_id); + if (it_dest == items.end()) + return; + + // Go to the next element if one wishes to insert after the dest element + if (!insert_before) + { + ++it_dest; + } + + // Insert the source item in the right place + if (it_dest != items.end()) + { + items.insert(it_dest, insertedItem); + } + else + { + // Append to the list if it_dest reached the end + items.push_back(insertedItem); + } +} + +const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml"; +const S32 LLFavoritesOrderStorage::NO_INDEX = -1; + +void LLFavoritesOrderStorage::setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index) +{ + mSortIndexes[inv_item->getUUID()] = sort_index; + mIsDirty = true; + getSLURL(inv_item->getAssetUUID()); +} + +S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id) +{ + sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id); + if (it != mSortIndexes.end()) + { + return it->second; + } + return NO_INDEX; +} + +void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id) +{ + mSortIndexes.erase(inv_item_id); + mIsDirty = true; +} + +void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) +{ + slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id); + if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached + + LLLandmark* lm = gLandmarkList.getAsset(asset_id, + boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1)); + if (lm) + { + LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " already loaded" << LL_ENDL; + onLandmarkLoaded(asset_id, lm); + } +} + +// static +std::string LLFavoritesOrderStorage::getStoredFavoritesFilename() +{ + std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); + + return (user_dir.empty() ? "" + : gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, + "stored_favorites_" + + gHippoGridManager->getCurrentGridName() + + ".xml") + ); +} + +// static +void LLFavoritesOrderStorage::destroyClass() +{ + LLFavoritesOrderStorage::instance().cleanup(); + + + std::string old_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); + llifstream file; + file.open(old_filename.c_str()); + if (file.is_open()) + { + file.close(); + std::string new_filename = getStoredFavoritesFilename(); + LL_INFOS("FavoritesBar") << "moving favorites from old name '" << old_filename + << "' to new name '" << new_filename << "'" + << LL_ENDL; + LLFile::rename(old_filename,new_filename); + } + + if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) + { + LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); + } + else + { + LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser(); + } +} + +std::string LLFavoritesOrderStorage::getSavedOrderFileName() +{ + // If we quit from the login screen we will not have an SL account + // name. Don't try to save, otherwise we'll dump a file in + // C:\Program Files\SecondLife\ or similar. JC + std::string user_dir = gDirUtilp->getLindenUserDir(); + return (user_dir.empty() ? "" : gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME)); +} + +void LLFavoritesOrderStorage::load() +{ + // load per-resident sorting information + std::string filename = getSavedOrderFileName(); + LLSD settings_llsd; + llifstream file; + file.open(filename.c_str()); + if (file.is_open()) + { + LLSDSerialize::fromXML(settings_llsd, file); + LL_INFOS("FavoritesBar") << "loaded favorites order from '" << filename << "' " + << (settings_llsd.isMap() ? "" : "un") << "successfully" + << LL_ENDL; + file.close(); + } + else + { + LL_WARNS("FavoritesBar") << "unable to open favorites order file at '" << filename << "'" << LL_ENDL; + } + + for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); + iter != settings_llsd.endMap(); ++iter) + { + mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); + } +} + +void LLFavoritesOrderStorage::saveFavoritesSLURLs() +{ + // Do not change the file if we are not logged in yet. + if (gAgentID.isNull()) //LLLoginInstance::getInstance()->authSuccess()) + { + LL_WARNS("FavoritesBar") << "Cannot save favorites: not logged in" << LL_ENDL; + return; + } + + std::string filename = getStoredFavoritesFilename(); + if (!filename.empty()) + { + llifstream in_file; + in_file.open(filename.c_str()); + LLSD fav_llsd; + if (in_file.is_open()) + { + LLSDSerialize::fromXML(fav_llsd, in_file); + LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' " + << (fav_llsd.isMap() ? "" : "un") << "successfully" + << LL_ENDL; + in_file.close(); + } + else + { + LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL; + } + + const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + + LLSD user_llsd; + for (LLInventoryModel::item_array_t::const_iterator it = items.cbegin(); it != items.cend(); ++it) + { + if (it->get()->getActualType() != LLAssetType::AT_LANDMARK) continue; + LLSD value; + value["name"] = (*it)->getName(); + value["asset_id"] = (*it)->getAssetUUID(); + + slurls_map_t::const_iterator slurl_iter = mSLURLs.find(value["asset_id"]); + if (slurl_iter != mSLURLs.cend()) + { + LL_DEBUGS("FavoritesBar") << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) + << ", SLURL=" << slurl_iter->second + << ", value=" << value << LL_ENDL; + value["slurl"] = slurl_iter->second; + user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value; + } + else + { + LL_WARNS("FavoritesBar") << "Not saving favorite " << value["name"] << ": no matching SLURL" << LL_ENDL; + } + } + + LLAvatarName av_name; + LLAvatarNameCache::get( gAgentID, &av_name ); + // Note : use the "John Doe" and not the "john.doe" version of the name + // as we'll compare it with the stored credentials in the login panel. + fav_llsd[av_name.getUserName()] = user_llsd; + + llofstream file; + file.open(filename.c_str()); + if ( file.is_open() ) + { + LLSDSerialize::toPrettyXML(fav_llsd, file); + LL_INFOS("FavoritesBar") << "saved favorites for '" << av_name.getUserName() + << "' to '" << filename << "' " + << LL_ENDL; + file.close(); + } + else + { + LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName() + << "' at '" << filename << "' " + << LL_ENDL; + } + } +} + +void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() +{ + std::string filename = getStoredFavoritesFilename(); + if (!filename.empty()) + { + LLSD fav_llsd; + llifstream file; + file.open(filename.c_str()); + if (file.is_open()) + { + LLSDSerialize::fromXML(fav_llsd, file); + file.close(); + + LLAvatarName av_name; + LLAvatarNameCache::get( gAgentID, &av_name ); + // Note : use the "John Doe" and not the "john.doe" version of the name. + // See saveFavoritesSLURLs() here above for the reason why. + if (fav_llsd.has(av_name.getUserName())) + { + LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL; + fav_llsd.erase(av_name.getUserName()); + } + + llofstream out_file; + out_file.open(filename.c_str()); + if ( out_file.is_open() ) + { + LLSDSerialize::toPrettyXML(fav_llsd, out_file); + LL_INFOS("FavoritesBar") << "saved favorites to '" << filename << "' " + << LL_ENDL; + out_file.close(); + } + } + } +} + +void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark) +{ + if (landmark) + { + LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " loaded" << LL_ENDL; + LLVector3d pos_global; + if (!landmark->getGlobalPos(pos_global)) + { + // If global position was unknown on first getGlobalPos() call + // it should be set for the subsequent calls. + landmark->getGlobalPos(pos_global); + } + + if (!pos_global.isExactlyZero()) + { + LL_DEBUGS("FavoritesBar") << "requesting slurl for landmark " << asset_id << LL_ENDL; + LLLandmarkActions::getSLURLfromPosGlobal(pos_global, + boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); + } + } +} + +void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) +{ + LL_DEBUGS("FavoritesBar") << "Saving landmark SLURL '" << slurl << "' for " << asset_id << LL_ENDL; + mSLURLs[asset_id] = slurl; +} + +void LLFavoritesOrderStorage::save() +{ + if (mIsDirty) + { + // something changed, so save it + std::string filename = LLFavoritesOrderStorage::getInstance()->getSavedOrderFileName(); + if (!filename.empty()) + { + LLSD settings_llsd; + + for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) + { + settings_llsd[iter->first.asString()] = iter->second; + } + + llofstream file; + file.open(filename.c_str()); + if ( file.is_open() ) + { + LLSDSerialize::toPrettyXML(settings_llsd, file); + LL_INFOS("FavoritesBar") << "saved favorites order to '" << filename << "' " << LL_ENDL; + } + else + { + LL_WARNS("FavoritesBar") << "failed to open favorites order file '" << filename << "' " << LL_ENDL; + } + } + else + { + LL_DEBUGS("FavoritesBar") << "no user directory available to store favorites order file" << LL_ENDL; + } + } +} + + +void LLFavoritesOrderStorage::cleanup() +{ + // nothing to clean + if (!mIsDirty) return; + + const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + + IsNotInFavorites is_not_in_fav(items); + + sort_index_map_t aTempMap; + //copy unremoved values from mSortIndexes to aTempMap + std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(), + inserter(aTempMap, aTempMap.begin()), + is_not_in_fav); + + //Swap the contents of mSortIndexes and aTempMap + mSortIndexes.swap(aTempMap); +} + +// See also LLInventorySort where landmarks in the Favorites folder are sorted. +class LLViewerInventoryItemSort +{ +public: + bool operator()(const LLPointer& a, const LLPointer& b) const + { + return LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()) + < LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); + } +}; + +void LLFavoritesOrderStorage::saveOrder() +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLIsType is_type(LLAssetType::AT_LANDMARK); + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + std::sort(items.begin(), items.end(), LLViewerInventoryItemSort()); + saveItemsOrder(items); +} + +void LLFavoritesOrderStorage::saveItemsOrder( const LLInventoryModel::item_array_t& items ) +{ + + int sortField = 0; + // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field + for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) + { + LLViewerInventoryItem* item = *i; + + setSortIndex(item, ++sortField); + + item->setComplete(TRUE); + item->updateServer(FALSE); + + gInventory.updateItem(item); + + // Tell the parent folder to refresh its sort order. + gInventory.addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); + } + + gInventory.notifyObservers(); +} + + +// * @param source_item_id - LLUUID of the source item to be moved into new position +// * @param target_item_id - LLUUID of the target item before which source item should be placed. +void LLFavoritesOrderStorage::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + //LLIsType is_type(LLAssetType::AT_LANDMARK); // Singu Note: We can have anything here~ + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + gInventory.collectDescendents(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH/*, is_type*/); + + // ensure items are sorted properly before changing order. EXT-3498 + std::sort(items.begin(), items.end(), LLViewerInventoryItemSort()); + + // update order + gInventory.updateItemsOrder(items, source_item_id, target_item_id); + + saveItemsOrder(items); +} + +void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) +{ + if (mTargetLandmarkId.isNull()) return; + + LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); +} +// EOF diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h new file mode 100644 index 0000000000..7d6008a027 --- /dev/null +++ b/indra/newview/llfavoritesbar.h @@ -0,0 +1,274 @@ +/** + * @file llfavoritesbar.h + * @brief LLFavoritesBarCtrl base class + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFAVORITESBARCTRL_H +#define LL_LLFAVORITESBARCTRL_H + +#include "llbutton.h" +#include "lluictrl.h" +#include "lltextbox.h" + +#include "llinventoryobserver.h" +#include "llinventorymodel.h" +#include "llviewerinventory.h" +#include "llui.h" //"llinitdestroyclass.h" + +class LLMenuItemCallGL; +class LLMenuGL; + +class LLFavoritesBarCtrl : public LLUICtrl, public LLInventoryObserver +{ +public: + struct Params : public LLInitParam::Block + { + Optional image_drag_indication; + Optional more_button; + Optional label; + Params(); + }; + +protected: + LLFavoritesBarCtrl(const Params&); + friend class LLUICtrlFactory; +public: + virtual ~LLFavoritesBarCtrl(); + + /*virtual*/ BOOL postBuild() override; + + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) override; + + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; + // LLInventoryObserver observer trigger + void changed(U32 mask) override; + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override; + void draw() override; + + void showDragMarker(BOOL show) { mShowDragMarker = show; } + void setLandingTab(LLUICtrl* tab) { mLandingTab = tab; } + +protected: + void updateButtons(); + LLButton* createButton(const LLPointer item, const LLButton::Params& button_params, S32 x_offset ); + const LLButton::Params& getButtonParams(); + BOOL collectFavoriteItems(LLInventoryModel::item_array_t &items); + + void onButtonClick(LLUUID id); + void onButtonRightClick(LLUUID id,LLView* button,S32 x,S32 y,MASK mask); + + void onButtonMouseDown(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); + void onOverflowMenuItemMouseDown(LLUUID id, LLUICtrl* item, S32 x, S32 y, MASK mask); + void onButtonMouseUp(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); + + void onEndDrag(); + + bool enableSelected(const LLSD& userdata); + void doToSelected(const LLSD& userdata); + BOOL isClipboardPasteable() const; + void pasteFromClipboard() const; + + void showDropDownMenu(); + + LLHandle mOverflowMenuHandle; + LLHandle mContextMenuHandle; + + LLUUID mFavoriteFolderId; + const LLFontGL *mFont; + size_t mFirstDropDownItem; + U32 mDropDownItemsCount; + bool mUpdateDropDownItems; + bool mRestoreOverflowMenu; + + LLUUID mSelectedItemID; + + LLUIImage* mImageDragIndication; + +private: + /* + * Helper function to make code more readable. It handles all drag and drop + * operations of the existing favorites items on the favorites bar. + */ + void handleExistingFavoriteDragAndDrop(S32 x, S32 y); + + /* + * Helper function to make code more readable. It handles all drag and drop + * operations of the new landmark to the favorites bar. + */ + void handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y); + + // finds a control under the specified LOCAL point + LLUICtrl* findChildByLocalCoords(S32 x, S32 y); + + // checks if the current order of the favorites items must be saved + BOOL needToSaveItemsOrder(const LLInventoryModel::item_array_t& items); + + /** + * inserts an item identified by insertedItemId BEFORE an item identified by beforeItemId. + * this function assumes that an item identified by insertedItemId doesn't exist in items array. + */ + void insertItem(LLInventoryModel::item_array_t& items, const LLUUID& dest_item_id, LLViewerInventoryItem* insertedItem, bool insert_before); + + // finds an item by it's UUID in the items array + LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id); + + void createOverflowMenu(); + + void updateMenuItems(LLMenuGL* menu); + + // Fits menu item label width with favorites menu width + void fitLabelWidth(LLMenuItemCallGL* menu_item); + + void addOpenLandmarksMenuItem(LLMenuGL* menu); + + void positionAndShowMenu(LLMenuGL* menu); + + BOOL mShowDragMarker; + LLUICtrl* mLandingTab; + LLUICtrl* mLastTab; + LLTextBox* mMoreTextBox; + LLTextBox* mBarLabel; + + LLUUID mDragItemId; + BOOL mStartDrag; + LLInventoryModel::item_array_t mItems; + + BOOL mTabsHighlightEnabled; + + boost::signals2::connection mEndDragConnection; +}; + +/** + * Class to store sorting order of favorites landmarks in a local file. EXT-3985. + * It replaced previously implemented solution to store sort index in landmark's name as a "@" prefix. + * Data are stored in user home directory. + */ +class LLFavoritesOrderStorage : public LLSingleton + , public LLDestroyClass +{ + friend class LLSingleton; + LLFavoritesOrderStorage(); //LLSINGLETON(LLFavoritesOrderStorage); + ~LLFavoritesOrderStorage() { save(); } + LOG_CLASS(LLFavoritesOrderStorage); +public: + /** + * Sets sort index for specified with LLUUID favorite landmark + */ + void setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index); + + /** + * Gets sort index for specified with LLUUID favorite landmark + */ + S32 getSortIndex(const LLUUID& inv_item_id); + void removeSortIndex(const LLUUID& inv_item_id); + + void getSLURL(const LLUUID& asset_id); + + // Saves current order of the passed items using inventory item sort field. + // Resets 'items' sort fields and saves them on server. + // Is used to save order for Favorites folder. + void saveItemsOrder(const LLInventoryModel::item_array_t& items); + + void saveOrder(); + + void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); + + /** + * Implementation of LLDestroyClass. Calls cleanup() instance method. + * + * It is important this callback is called before gInventory is cleaned. + * For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(), + * Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called. + * @see cleanup() + */ + static void destroyClass(); + + const static S32 NO_INDEX; +private: + /** + * Removes sort indexes for items which are not in Favorites bar for now. + */ + void cleanup(); + + const static std::string SORTING_DATA_FILE_NAME; + std::string getSavedOrderFileName(); + static std::string getStoredFavoritesFilename(); + + void load(); + void save(); + + void saveFavoritesSLURLs(); + + // Remove record of current user's favorites from file on disk. + void removeFavoritesRecordOfUser(); + + void onLandmarkLoaded(const LLUUID& asset_id, class LLLandmark* landmark); + void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl); + + typedef std::map sort_index_map_t; + sort_index_map_t mSortIndexes; + + typedef std::map slurls_map_t; + slurls_map_t mSLURLs; + uuid_set_t mMissingSLURLs; + bool mIsDirty; + + struct IsNotInFavorites + { + IsNotInFavorites(const LLInventoryModel::item_array_t& items) + : mFavoriteItems(items) + { + + } + + /** + * Returns true if specified item is not found among inventory items + */ + bool operator()(const sort_index_map_t::value_type& id_index_pair) const + { + LLPointer item = gInventory.getItem(id_index_pair.first); + if (item.isNull()) return true; + + LLInventoryModel::item_array_t::const_iterator found_it = + std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item); + + return found_it == mFavoriteItems.end(); + } + private: + LLInventoryModel::item_array_t mFavoriteItems; + }; + +}; + +inline +LLFavoritesOrderStorage::LLFavoritesOrderStorage() : + mIsDirty(false) +{ load(); } + +#endif // LL_LLFAVORITESBARCTRL_H diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index aedcd47b2e..8ecf9f8c67 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -421,6 +421,9 @@ void LLFeatureManager::parseGPUTable(std::string filename) else { LL_WARNS("RenderInit") << "GPU '" << rawRenderer << "' not recognized" << LL_ENDL; + mGPUString = rawRenderer; + mGPUClass = EGPUClass::GPU_CLASS_3; + mGPUSupported = true; } } @@ -676,7 +679,7 @@ void LLFeatureManager::applyBaseMasks() maskFeatures(gpustr); // now mask cpu type ones - if (gSysMemory.getPhysicalMemoryClamped() <= 256*1024*1024) + if (gSysMemory.getPhysicalMemoryKB() <= U32Megabytes(256)) { maskFeatures("RAM256MB"); } diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp index b8e8b37dcf..718d82b502 100644 --- a/indra/newview/llfirstuse.cpp +++ b/indra/newview/llfirstuse.cpp @@ -45,8 +45,8 @@ #include "llviewercontrol.h" #include "llui.h" #include "llappviewer.h" +#include "llfloatertos.h" #include "lltracker.h" -#include "floatervoicelicense.h" #include "llstartup.h" #include "hippogridmanager.h" @@ -303,8 +303,9 @@ void LLFirstUse::voiceLicenseAgreement() { gSavedSettings.setWarning("FirstVoiceLicense", FALSE); - FloaterVoiceLicense::getInstance()->open(); - FloaterVoiceLicense::getInstance()->center(); + auto inst = LLFloaterTOS::show(LLFloaterTOS::TOS_VOICE); + inst->open(); + inst->center(); } else // currently in STATE_LOGIN_VOICE_LICENSE when arriving here { diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 380ea0df18..21bfb48499 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -47,8 +47,8 @@ std::vector LLVolumeImplFlexible::sInstanceList; std::vector LLVolumeImplFlexible::sUpdateDelay; -static LLFastTimer::DeclareTimer FTM_FLEXIBLE_REBUILD("Rebuild"); -static LLFastTimer::DeclareTimer FTM_DO_FLEXIBLE_UPDATE("Flexible Update"); +static LLTrace::BlockTimerStatHandle FTM_FLEXIBLE_REBUILD("Rebuild"); +static LLTrace::BlockTimerStatHandle FTM_DO_FLEXIBLE_UPDATE("Flexible Update"); // LLFlexibleObjectData::pack/unpack now in llprimitive.cpp @@ -328,14 +328,14 @@ void LLVolumeImplFlexible::updateRenderRes() // updated every time step. In the future, perhaps there could be an // optimization similar to what Havok does for objects that are stationary. //--------------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies"); +static LLTrace::BlockTimerStatHandle FTM_FLEXIBLE_UPDATE("Update Flexies"); void LLVolumeImplFlexible::doIdleUpdate() { LLDrawable* drawablep = mVO->mDrawable; if (drawablep) { - //LLFastTimer ftm(FTM_FLEXIBLE_UPDATE); + //LL_RECORD_BLOCK_TIME(FTM_FLEXIBLE_UPDATE); //ensure drawable is active drawablep->makeActive(); @@ -407,7 +407,7 @@ inline S32 log2(S32 x) void LLVolumeImplFlexible::doFlexibleUpdate() { - LLFastTimer ftm(FTM_DO_FLEXIBLE_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_DO_FLEXIBLE_UPDATE); LLVolume* volume = mVO->getVolume(); LLPath *path = &volume->getPath(); if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible()) @@ -759,7 +759,7 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) if (mRenderRes > -1) { - LLFastTimer t(FTM_DO_FLEXIBLE_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_DO_FLEXIBLE_UPDATE); doFlexibleUpdate(); } @@ -779,7 +779,7 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) volume->mDrawable->setState(LLDrawable::REBUILD_VOLUME); volume->dirtySpatialGroup(); { - LLFastTimer t(FTM_FLEXIBLE_REBUILD); + LL_RECORD_BLOCK_TIME(FTM_FLEXIBLE_REBUILD); doFlexibleRebuild(); } volume->genBBoxes(isVolumeGlobal()); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 4f4ac87fcc..a083627142 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -49,7 +49,7 @@ #include "llagent.h" #include "llviewerstats.h" #include "llviewerregion.h" -#include "sgversion.h" +#include "llversioninfo.h" #include "lluictrlfactory.h" #include "lluri.h" #include "llweb.h" @@ -70,6 +70,11 @@ #include "lldxhardware.h" #endif +#include "cef/dullahan.h" +#if VLCPLUGIN +#include "vlc/libvlc_version.h" +#endif // LL_WINDOWS + extern LLMemoryInfo gSysMemory; extern U32 gPacketsIn; @@ -111,6 +116,9 @@ LLFloaterAbout::LLFloaterAbout() LLViewerTextEditor *credits_widget = getChild("credits_editor", true); + + LLViewerTextEditor *licenses_widget = + getChild("licenses_editor", true); childSetAction("copy_btn", onAboutClickCopyToClipboard, this); @@ -135,11 +143,11 @@ LLFloaterAbout::LLFloaterAbout() + " (64 bit)" #endif + llformat(" %d.%d.%d (%d) %s %s (%s)\n", - gVersionMajor, gVersionMinor, gVersionPatch, gVersionBuild, + LLVersionInfo::getMajor(), LLVersionInfo::getMinor(), LLVersionInfo::getPatch(), LLVersionInfo::getBuild(), __DATE__, __TIME__, - gVersionChannel)); + LLVersionInfo::getChannel().c_str())); support_widget->appendColoredText(version, FALSE, FALSE, gColors.getColor("TextFgReadOnlyColor")); - support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, viewer_link_style); + support_widget->appendText(LLTrans::getString("ReleaseNotes"), false, false, viewer_link_style); std::string support; support.append("\n\n"); @@ -192,10 +200,10 @@ LLFloaterAbout::LLFloaterAbout() else support.append(RlvStrings::getString(RLV_STRING_HIDDEN_REGION)); // [/RLVa:KN] - support.append("\n"); + support += '\n'; support.append(gLastVersionChannel); - support.append("\n"); + support += '\n'; support_widget->appendColoredText(support, FALSE, FALSE, gColors.getColor("TextFgReadOnlyColor")); @@ -204,7 +212,7 @@ LLFloaterAbout::LLFloaterAbout() { LLStyleSP server_link_style(new LLStyle(*viewer_link_style)); server_link_style->setLinkHREF(url); - support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, server_link_style); + support_widget->appendText(LLTrans::getString("ReleaseNotes"), false, false, server_link_style); } support = "\n\n"; @@ -217,7 +225,7 @@ LLFloaterAbout::LLFloaterAbout() // CPU support.append("CPU: "); support.append( gSysCPU.getCPUString() ); - support.append("\n"); + support += '\n'; /* This is confusing and WRONG. support.append("SSE Support:"); @@ -228,7 +236,7 @@ LLFloaterAbout::LLFloaterAbout() else support.append(" None\n"); */ - U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024; + U32Megabytes memory = gSysMemory.getPhysicalMemoryKB(); // Moved hack adjustment to Windows memory size into llsys.cpp std::string mem_text = llformat("Memory: %u MB\n", memory ); @@ -236,15 +244,15 @@ LLFloaterAbout::LLFloaterAbout() support.append("OS Version: "); support.append( LLAppViewer::instance()->getOSInfo().getOSString() ); - support.append("\n"); + support += '\n'; support.append("Graphics Card Vendor: "); support.append( (const char*) glGetString(GL_VENDOR) ); - support.append("\n"); + support += '\n'; support.append("Graphics Card: "); support.append( (const char*) glGetString(GL_RENDERER) ); - support.append("\n"); + support += '\n'; #if LL_WINDOWS getWindow()->incBusyCount(); @@ -255,7 +263,7 @@ LLFloaterAbout::LLFloaterAbout() { support.append(driver_info["DriverVersion"]); } - support.append("\n"); + support += '\n'; getWindow()->decBusyCount(); getWindow()->setCursor(UI_CURSOR_ARROW); #endif @@ -263,47 +271,47 @@ LLFloaterAbout::LLFloaterAbout() support.append("OpenGL Version: "); support.append( (const char*) glGetString(GL_VERSION) ); // [RLVa:KB] - Checked: 2010-04-18 (RLVa-1.2.0) - support.append("\n"); + support += '\n'; support.append("RLV Version: " + (RlvActions::isRlvEnabled() ? RlvStrings::getVersionAbout() : "(disabled)")); // [/RLVa:KB] support.append("\n\n"); - support.append("Viewer SSE Version: "); -#if _M_IX86_FP > 0 //Windows - support.append(llformat("SSE%i\n", _M_IX86_FP )); -#elif defined(__SSE2__) //GCC - support.append("SSE2\n"); -#elif defined(__SSE__) //GCC - support.append("SSE\n"); -#else - support.append("None\n"); -#endif - support.append("libcurl Version: "); support.append( LLCurl::getVersionString() ); - support.append("\n"); + support += '\n'; support.append("J2C Decoder Version: "); support.append( LLImageJ2C::getEngineInfo() ); - support.append("\n"); + support += '\n'; support.append("Audio Driver Version: "); bool want_fullname = true; support.append( gAudiop ? gAudiop->getDriverName(want_fullname) : "(none)" ); - support.append("\n"); - - // TODO: Implement media plugin version query - - support.append("Qt Webkit Version: "); - support.append( -#if LL_LINUX && defined(__x86_64__) - "4.8.6" -#else - "4.7.1" + support += '\n'; + + std::stringstream supportstrm; + supportstrm << "Dullahan: " + << DULLAHAN_VERSION_MAJOR + << '.' + << DULLAHAN_VERSION_MINOR + << '.' + << DULLAHAN_VERSION_BUILD + + << " / CEF: " << CEF_VERSION + << " / Chrome: " << CHROME_VERSION_MAJOR + << '\n'; + +#if VLCPLUGIN + supportstrm << "LibVLC: "; + supportstrm << LIBVLC_VERSION_MAJOR; + supportstrm << '.'; + supportstrm << LIBVLC_VERSION_MINOR; + supportstrm << '.'; + supportstrm << LIBVLC_VERSION_REVISION; + supportstrm << '\n'; #endif - ); - support.append(" (version number hard-coded)"); - support.append("\n"); + + support += supportstrm.str(); if (gPacketsIn > 0) { @@ -312,7 +320,7 @@ LLFloaterAbout::LLFloaterAbout() F32(gPacketsIn), 100.f*LLViewerStats::getInstance()->mPacketsLostStat.getCurrent() / F32(gPacketsIn) ); support.append(packet_loss); - support.append("\n"); + support += '\n'; } support_widget->appendColoredText(support, FALSE, FALSE, gColors.getColor("TextFgReadOnlyColor")); @@ -328,6 +336,30 @@ LLFloaterAbout::LLFloaterAbout() credits_widget->setTakesFocus(TRUE); credits_widget->setHandleEditKeysDirectly(TRUE); + // Get the Versions and Copyrights, created at build time + std::string licenses_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "packages-info.txt"); + llifstream licenses_file; + licenses_file.open(licenses_path); /* Flawfinder: ignore */ + if (licenses_file.is_open()) + { + std::string license_line; + licenses_widget->clear(); + while (std::getline(licenses_file, license_line)) + { + licenses_widget->appendColoredText(license_line + '\n', FALSE, FALSE, gColors.getColor("TextFgReadOnlyColor")); + } + licenses_file.close(); + } + else + { + // this case will use the (out of date) hard coded value from the XUI + LL_INFOS("AboutInit") << "Could not read licenses file at " << licenses_path << LL_ENDL; + } + licenses_widget->setCursorPos(0); + licenses_widget->setEnabled(FALSE); + licenses_widget->setTakesFocus(TRUE); + licenses_widget->setHandleEditKeysDirectly(TRUE); + center(); sInstance = this; @@ -353,7 +385,7 @@ void LLFloaterAbout::show(void*) static std::string get_viewer_release_notes_url() { - return "http://www.singularityviewer.org"; + return LLTrans::getString("APP_SITE"); /*std::ostringstream version; version << gVersionMajor << "." << gVersionMinor diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index 4a44b6a3a0..cefa86f5c2 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -3,38 +3,31 @@ * @author James Cook, Ian Wilkes * @brief Implementation of the auction floater. * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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 "llviewerprecompiledheaders.h" #include "llfloaterauction.h" -#include "lldir.h" #include "llgl.h" #include "llimagej2c.h" #include "llimagetga.h" @@ -46,17 +39,21 @@ #include "llagent.h" #include "llcombobox.h" +#include "llmimetypes.h" #include "llnotifications.h" -#include "llnotificationsutil.h" +#include "llnotificationsutil.h" #include "llviewertexturelist.h" #include "llviewerparcelmgr.h" #include "llviewerregion.h" -#include "lluictrlfactory.h" #include "llviewerwindow.h" #include "llviewerdisplay.h" #include "llviewercontrol.h" #include "llui.h" +#include "lluictrlfactory.h" #include "llrender.h" +#include "llsdutil.h" +#include "llsdutil_math.h" +#include "lltrans.h" ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs @@ -74,8 +71,8 @@ void auction_tga_upload_done(const LLUUID& asset_id, LLFloaterAuction* LLFloaterAuction::sInstance = NULL; // Default constructor -LLFloaterAuction::LLFloaterAuction() : - LLFloater(std::string("floater_auction")), +LLFloaterAuction::LLFloaterAuction() + : LLFloater(std::string("floater_auction")), mParcelID(-1) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_auction.xml"); @@ -86,13 +83,13 @@ LLFloaterAuction::LLFloaterAuction() : onCommitControlSetting(gSavedSettings), (void*)"AuctionShowFence"); childSetAction("snapshot_btn", onClickSnapshot, this); - childSetAction("ok_btn", onClickOK, this); + childSetAction("ok_btn", onClickStartAuction, this); } // Destroys the object LLFloaterAuction::~LLFloaterAuction() { - sInstance = NULL; + sInstance = nullptr; } // static @@ -104,12 +101,23 @@ void LLFloaterAuction::show() sInstance->center(); sInstance->setFocus(TRUE); } - sInstance->initialize(); sInstance->open(); /*Flawfinder: ignore*/ } +BOOL LLFloaterAuction::postBuild() +{ + return TRUE; +} + +void LLFloaterAuction::onOpen() +{ + initialize(); +} + void LLFloaterAuction::initialize() { + mParcelUpdateCapUrl.clear(); + mParcelp = LLViewerParcelMgr::getInstance()->getParcelSelection(); LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); LLParcel* parcelp = mParcelp->getParcel(); @@ -117,28 +125,30 @@ void LLFloaterAuction::initialize() { mParcelHost = region->getHost(); mParcelID = parcelp->getLocalID(); + mParcelUpdateCapUrl = region->getCapability("ParcelPropertiesUpdate"); - childSetText("parcel_text", parcelp->getName()); - childEnable("snapshot_btn"); - childEnable("ok_btn"); + getChild("parcel_text")->setValue(parcelp->getName()); + getChildView("snapshot_btn")->setEnabled(TRUE); + getChildView("ok_btn")->setEnabled(true); } else { mParcelHost.invalidate(); if(parcelp && parcelp->getForSale()) { - childSetText("parcel_text", getString("already for sale")); + getChild("parcel_text")->setValue(getString("already for sale")); } else { - childSetText("parcel_text", LLStringUtil::null); + getChild("parcel_text")->setValue(LLStringUtil::null); } mParcelID = -1; - childSetEnabled("snapshot_btn", false); - childSetEnabled("ok_btn", false); + getChildView("snapshot_btn")->setEnabled(false); + getChildView("ok_btn")->setEnabled(false); } + mImageID.setNull(); - mImage = NULL; + mImage = nullptr; } void LLFloaterAuction::draw() @@ -147,9 +157,10 @@ void LLFloaterAuction::draw() if(!isMinimized() && mImage.notNull()) { - LLRect rect; - if (childGetRect("snapshot_icon", rect)) + LLView* snapshot_icon = findChild("snapshot_icon"); + if (snapshot_icon) { + LLRect rect = snapshot_icon->getRect(); { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f)); @@ -176,7 +187,7 @@ void LLFloaterAuction::onClickSnapshot(void* data) LLPointer raw = new LLImageRaw; - gForceRenderLandFence = self->childGetValue("fence_check").asBoolean(); + gForceRenderLandFence = self->getChild("fence_check")->getValue().asBoolean(); BOOL success = gViewerWindow->rawSnapshot(raw, gViewerWindow->getWindowWidth(), gViewerWindow->getWindowHeight(), @@ -218,13 +229,13 @@ void LLFloaterAuction::onClickSnapshot(void* data) } // static -void LLFloaterAuction::onClickOK(void* data) +void LLFloaterAuction::onClickStartAuction(void* data) { LLFloaterAuction* self = (LLFloaterAuction*)(data); if(self->mImageID.notNull()) { - LLSD parcel_name = self->childGetValue("parcel_text"); + LLSD parcel_name = self->getChild("parcel_text")->getValue(); // create the asset std::string* name = new std::string(parcel_name.asString()); @@ -257,11 +268,243 @@ void LLFloaterAuction::onClickOK(void* data) msg->sendReliable(self->mParcelHost); // clean up floater, and get out - self->mImageID.setNull(); - self->mImage = NULL; - self->mParcelID = -1; - self->mParcelHost.invalidate(); - self->close(); + self->cleanupAndClose(); +} + + +void LLFloaterAuction::cleanupAndClose() +{ + mImageID.setNull(); + mImage = nullptr; + mParcelID = -1; + mParcelHost.invalidate(); + close(); +} + + + +// static glue +void LLFloaterAuction::onClickResetParcel(void* data) +{ + LLFloaterAuction* self = (LLFloaterAuction*)(data); + if (self) + { + self->doResetParcel(); + } +} + + +// Reset all the values for the parcel in preparation for a sale +void LLFloaterAuction::doResetParcel() +{ + LLParcel* parcelp = mParcelp->getParcel(); + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + + if (parcelp + && region + && !mParcelUpdateCapUrl.empty()) + { + LLSD body; + std::string empty; + + // request new properties update from simulator + U32 message_flags = 0x01; + body["flags"] = ll_sd_from_U32(message_flags); + + // Set all the default parcel properties for auction + body["local_id"] = parcelp->getLocalID(); + + U32 parcel_flags = PF_ALLOW_LANDMARK | + PF_ALLOW_FLY | + PF_CREATE_GROUP_OBJECTS | + PF_ALLOW_ALL_OBJECT_ENTRY | + PF_ALLOW_GROUP_OBJECT_ENTRY | + PF_ALLOW_GROUP_SCRIPTS | + PF_RESTRICT_PUSHOBJECT | + PF_SOUND_LOCAL | + PF_ALLOW_VOICE_CHAT | + PF_USE_ESTATE_VOICE_CHAN; + + body["parcel_flags"] = ll_sd_from_U32(parcel_flags); + + // Build a parcel name like "Ahern (128,128) PG 4032m" + std::ostringstream parcel_name; + LLVector3 center_point( parcelp->getCenterpoint() ); + center_point.snap(0); // Get rid of fractions + parcel_name << region->getName() + << " (" + << (S32) center_point.mV[VX] + << "," + << (S32) center_point.mV[VY] + << ") " + << region->getSimAccessString() + << " " + << parcelp->getArea() + << "m"; + + std::string new_name(parcel_name.str()); + body["name"] = new_name; + getChild("parcel_text")->setValue(new_name); // Set name in dialog as well, since it won't get updated otherwise + + body["sale_price"] = (S32) 0; + body["description"] = empty; + body["music_url"] = empty; + body["media_url"] = empty; + body["media_desc"] = empty; + body["media_type"] = LLMIMETypes::getDefaultMimeType(); + body["media_width"] = (S32) 0; + body["media_height"] = (S32) 0; + body["auto_scale"] = (S32) 0; + body["media_loop"] = (S32) 0; + body["obscure_media"] = (S32) 0; // OBSOLETE - no longer used + body["obscure_music"] = (S32) 0; // OBSOLETE - no longer used + body["media_id"] = LLUUID::null; + body["group_id"] = MAINTENANCE_GROUP_ID; // Use maintenance group + body["pass_price"] = (S32) 10; // Defaults to $10 + body["pass_hours"] = 0.0f; + body["category"] = (U8) LLParcel::C_NONE; + body["auth_buyer_id"] = LLUUID::null; + body["snapshot_id"] = LLUUID::null; + body["user_location"] = ll_sd_from_vector3( LLVector3::zero ); + body["user_look_at"] = ll_sd_from_vector3( LLVector3::zero ); + body["landing_type"] = (U8) LLParcel::L_DIRECT; + + LL_INFOS() << "Sending parcel update to reset for auction via capability to: " + << mParcelUpdateCapUrl << LL_ENDL; + LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::ResponderIgnore()); + + // Send a message to clear the object return time + LLMessageSystem *msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ParcelSetOtherCleanTime); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ParcelData); + msg->addS32Fast(_PREHASH_LocalID, parcelp->getLocalID()); + msg->addS32Fast(_PREHASH_OtherCleanTime, 5); // 5 minute object auto-return + + msg->sendReliable(region->getHost()); + + // Clear the access lists + clearParcelAccessList(parcelp, region, AL_ACCESS); + clearParcelAccessList(parcelp, region, AL_BAN); + clearParcelAccessList(parcelp, region, AL_ALLOW_EXPERIENCE); + clearParcelAccessList(parcelp, region, AL_BLOCK_EXPERIENCE); + } +} + + + +void LLFloaterAuction::clearParcelAccessList(LLParcel* parcel, LLViewerRegion* region, U32 list) +{ + if (!region || !parcel) return; + + LLUUID transactionUUID; + transactionUUID.generate(); + + LLMessageSystem* msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_ParcelAccessListUpdate); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + msg->nextBlockFast(_PREHASH_Data); + msg->addU32Fast(_PREHASH_Flags, list); + msg->addS32(_PREHASH_LocalID, parcel->getLocalID() ); + msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID); + msg->addS32Fast(_PREHASH_SequenceID, 1); // sequence_id + msg->addS32Fast(_PREHASH_Sections, 0); // num_sections + + // pack an empty block since there will be no data + msg->nextBlockFast(_PREHASH_List); + msg->addUUIDFast(_PREHASH_ID, LLUUID::null ); + msg->addS32Fast(_PREHASH_Time, 0 ); + msg->addU32Fast(_PREHASH_Flags, 0 ); + + msg->sendReliable( region->getHost() ); +} + + + +// static - 'Sell to Anyone' clicked, throw up a confirmation dialog +void LLFloaterAuction::onClickSellToAnyone(void* data) +{ + LLFloaterAuction* self = (LLFloaterAuction*)(data); + if (self) + { + LLParcel* parcelp = self->mParcelp->getParcel(); + + // Do a confirmation + S32 sale_price = parcelp->getArea(); // Selling for L$1 per meter + S32 area = parcelp->getArea(); + + LLSD args; + args["LAND_SIZE"] = llformat("%d", area); + args["SALE_PRICE"] = llformat("%d", sale_price); + args["NAME"] = LLTrans::getString("Anyone"); + + LLNotification::Params params("ConfirmLandSaleChange"); // Re-use existing dialog + params.substitutions(args) + .functor/*.function*/(boost::bind(&LLFloaterAuction::onSellToAnyoneConfirmed, self, _1, _2)); + + params.name("ConfirmLandSaleToAnyoneChange"); + + // ask away + LLNotifications::instance().add(params); + } +} + + +// Sell confirmation clicked +bool LLFloaterAuction::onSellToAnyoneConfirmed(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + doSellToAnyone(); + } + + return false; +} + + + +// Reset all the values for the parcel in preparation for a sale +void LLFloaterAuction::doSellToAnyone() +{ + LLParcel* parcelp = mParcelp->getParcel(); + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + + if (parcelp + && region + && !mParcelUpdateCapUrl.empty()) + { + LLSD body; + + // request new properties update from simulator + U32 message_flags = 0x01; + body["flags"] = ll_sd_from_U32(message_flags); + + // Set all the default parcel properties for auction + body["local_id"] = parcelp->getLocalID(); + + // Set 'for sale' flag + U32 parcel_flags = parcelp->getParcelFlags() | PF_FOR_SALE; + // Ensure objects not included + parcel_flags &= ~PF_FOR_SALE_OBJECTS; + body["parcel_flags"] = ll_sd_from_U32(parcel_flags); + + body["sale_price"] = parcelp->getArea(); // Sell for L$1 per square meter + body["auth_buyer_id"] = LLUUID::null; // To anyone + + LL_INFOS() << "Sending parcel update to sell to anyone for L$1 via capability to: " + << mParcelUpdateCapUrl << LL_ENDL; + + LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::ResponderIgnore()); + + // clean up floater, and get out + cleanupAndClose(); + } } diff --git a/indra/newview/llfloaterauction.h b/indra/newview/llfloaterauction.h index a9f1ea874f..f431a84fc4 100644 --- a/indra/newview/llfloaterauction.h +++ b/indra/newview/llfloaterauction.h @@ -3,31 +3,25 @@ * @author James Cook, Ian Wilkes * @brief llfloaterauction class header file * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * 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. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -36,7 +30,7 @@ #include "llfloater.h" #include "lluuid.h" -#include "llmemory.h" +#include "llsafehandle.h" #include "llviewertexture.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -45,34 +39,50 @@ // Class which holds the functionality to start auctions. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLParcelSelection; +class LLParcel; +class LLViewerRegion; -class LLFloaterAuction : public LLFloater +class LLFloaterAuction final : public LLFloater { public: // LLFloater interface - /*virtual*/ void onClose(bool app_quitting) { setVisible(FALSE); } - /*virtual*/ void draw(); + /*virtual*/ void onOpen() override; + /*virtual*/ void onClose(bool app_quitting) override { setVisible(FALSE); } + /*virtual*/ void draw() override; // LLFloaterAuction interface static void show(); - private: + LLFloaterAuction(); ~LLFloaterAuction(); + void initialize(); static void onClickSnapshot(void* data); - static void onClickOK(void* data); + static void onClickResetParcel(void* data); + static void onClickSellToAnyone(void* data); // Sell to anyone clicked + bool onSellToAnyoneConfirmed(const LLSD& notification, const LLSD& response); // Sell confirmation clicked + static void onClickStartAuction(void* data); static LLFloaterAuction* sInstance; + /*virtual*/ BOOL postBuild() override; + + void doResetParcel(); + void doSellToAnyone(); + void clearParcelAccessList(LLParcel* parcel, LLViewerRegion* region, U32 list); + void cleanupAndClose(); private: + LLTransactionID mTransactionID; LLAssetID mImageID; LLPointer mImage; LLSafeHandle mParcelp; S32 mParcelID; LLHost mParcelHost; + + std::string mParcelUpdateCapUrl; // "ParcelPropertiesUpdate" capability }; diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp index a1d17ddadc..a778162fa1 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -52,8 +52,6 @@ #include "llworld.h" #include -#include -#include // [RLVa:KB] #include "rlvhandler.h" @@ -71,7 +69,7 @@ const S32& radar_namesystem() namespace { - void chat_avatar_status(const std::string& name, const LLUUID& key, ERadarStatType type, bool entering, const F32& dist) + void chat_avatar_status(const std::string& name, const LLUUID& key, ERadarStatType type, bool entering, const F32& dist, bool flood = false) { static LLCachedControl radar_chat_alerts(gSavedSettings, "RadarChatAlerts"); if (!radar_chat_alerts) return; @@ -83,6 +81,8 @@ namespace } // if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) return; // RLVa:LF Don't announce people are around when blind, that cheats the system. + static LLCachedControl radar_alert_flood(gSavedSettings, "RadarAlertFlood"); + if (flood && !radar_alert_flood) return; static LLCachedControl radar_alert_sim(gSavedSettings, "RadarAlertSim"); static LLCachedControl radar_alert_draw(gSavedSettings, "RadarAlertDraw"); static LLCachedControl radar_alert_shout_range(gSavedSettings, "RadarAlertShoutRange"); @@ -97,11 +97,11 @@ namespace case STAT_TYPE_DRAW: if (radar_alert_draw) args["[RANGE]"] = LLTrans::getString("draw_distance"); break; case STAT_TYPE_SHOUTRANGE: if (radar_alert_shout_range) args["[RANGE]"] = LLTrans::getString("shout_range"); break; case STAT_TYPE_CHATRANGE: if (radar_alert_chat_range) args["[RANGE]"] = LLTrans::getString("chat_range"); break; - case STAT_TYPE_AGE: if (radar_alert_age) chat.mText = name + " " + LLTrans::getString("has_triggered_your_avatar_age_alert") + "."; break; + case STAT_TYPE_AGE: if (radar_alert_age) chat.mText = name + ' ' + LLTrans::getString("has_triggered_your_avatar_age_alert") + '.'; break; default: llassert(type); break; } args["[NAME]"] = name; - args["[ACTION]"] = LLTrans::getString(entering ? "has_entered" : "has_left"); + args["[ACTION]"] = LLTrans::getString((entering ? "has_entered" : "has_left") + (flood ? "_flood" : LLStringUtil::null)); if (args.find("[RANGE]") != args.end()) chat.mText = LLTrans::getString("radar_alert_template", args); else if (chat.mText.empty()) return; @@ -111,8 +111,9 @@ namespace if (radar_show_dist) chat.mText += llformat(" (%.2fm)", dist); } chat.mFromName = name; + chat.mFromID = key; if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) // RLVa:LF - No way! - chat.mURL = llformat("secondlife:///app/agent/%s/about", key.asString().c_str()); + chat.mURL = LLAvatarActions::getSLURL(key); chat.mSourceType = CHAT_SOURCE_SYSTEM; LLFloaterChat::addChat(chat); } @@ -132,8 +133,9 @@ namespace } } //namespace +const LLColor4* mm_getMarkerColor(const LLUUID& id, bool mark_only = true); LLAvatarListEntry::LLAvatarListEntry(const LLUUID& id, const std::string& name, const LLVector3d& position) : - mID(id), mName(name), mPosition(position), mMarked(false), mFocused(false), + mID(id), mName(name), mPosition(position), mMarked(mm_getMarkerColor(id)), mFocused(false), mStats(), mActivityType(ACTIVITY_NEW), mActivityTimer(), mIsInList(false), mAge(-1), mTime(time(NULL)) @@ -141,61 +143,81 @@ LLAvatarListEntry::LLAvatarListEntry(const LLUUID& id, const std::string& name, LLAvatarPropertiesProcessor& inst(LLAvatarPropertiesProcessor::instance()); inst.addObserver(mID, this); inst.sendAvatarPropertiesRequest(mID); + inst.sendAvatarNotesRequest(mID); } LLAvatarListEntry::~LLAvatarListEntry() { + static LLCachedControl radar_alert_flood_leaving(gSavedSettings, "RadarAlertFloodLeaving"); + bool cleanup = LLFloaterAvatarList::isCleanup(); + if (radar_alert_flood_leaving || !cleanup) + { + setPosition(mPosition, F32_MIN, false, cleanup); // Dead and gone + } LLAvatarPropertiesProcessor::instance().removeObserver(mID, this); } // virtual void LLAvatarListEntry::processProperties(void* data, EAvatarProcessorType type) { - if (type == APT_PROPERTIES) + // If one wanted more information that gets displayed on profiles to be displayed, here would be the place to do it. + switch(type) { - LLAvatarPropertiesProcessor& inst(LLAvatarPropertiesProcessor::instance()); - inst.removeObserver(mID, this); - const LLAvatarData* pAvatarData = static_cast(data); - if (pAvatarData && (pAvatarData->avatar_id != LLUUID::null)) - { - using namespace boost::gregorian; - int year, month, day; - sscanf(pAvatarData->born_on.c_str(),"%d/%d/%d",&month,&day,&year); - try + case APT_PROPERTIES: + if (mAge == -1) { - mAge = (day_clock::local_day() - date(year, month, day)).days(); - } - catch(const std::exception&) - { - LL_WARNS() << "Failed to extract age from APT_PROPERTIES for " << mID << ", received \"" << pAvatarData->born_on << "\". Requesting properties again." << LL_ENDL; - inst.addObserver(mID, this); - inst.sendAvatarPropertiesRequest(mID); - return; - } - if (!mStats[STAT_TYPE_AGE] && mAge >= 0) //Only announce age once per entry. - { - static const LLCachedControl sAvatarAgeAlertDays(gSavedSettings, "AvatarAgeAlertDays"); - if ((U32)mAge < sAvatarAgeAlertDays) + LLAvatarPropertiesProcessor& inst(LLAvatarPropertiesProcessor::instance()); + const LLAvatarData* pAvatarData = static_cast(data); + if (pAvatarData && (pAvatarData->avatar_id.notNull())) { - chat_avatar_status(mName, mID, STAT_TYPE_AGE, mStats[STAT_TYPE_AGE] = true, (mPosition - gAgent.getPositionGlobal()).magVec()); + using namespace boost::gregorian; + int year, month, day; + const auto born = pAvatarData->born_on; + if (born.empty()) return; // Opensim returns this for NPCs. + if (sscanf(born.c_str(),"%d/%d/%d",&month,&day,&year) == 3) + try + { + mAge = (day_clock::local_day() - date(year, month, day)).days(); + } + catch(const std::out_of_range&) {} // date throws this, so we didn't assign + + if (mAge >= 0) + { + static const LLCachedControl sAvatarAgeAlertDays(gSavedSettings, "AvatarAgeAlertDays"); + if (!mStats[STAT_TYPE_AGE] && (U32)mAge < sAvatarAgeAlertDays) //Only announce age once per entry. + chat_avatar_status(mName, mID, STAT_TYPE_AGE, mStats[STAT_TYPE_AGE] = true, (mPosition - gAgent.getPositionGlobal()).magVec()); + } + else // Something failed, resend request but only on NonSL grids + { + LL_WARNS() << "Failed to extract age from APT_PROPERTIES for " << mID << ", received \"" << born << "\"." << LL_ENDL; + if (!gHippoGridManager->getConnectedGrid()->isSecondLife()) + { + LL_WARNS() << "Requesting properties again." << LL_ENDL; + inst.sendAvatarPropertiesRequest(mID); + } + } } } - // If one wanted more information that gets displayed on profiles to be displayed, here would be the place to do it. - } + break; + case APT_NOTES: + if (const LLAvatarNotes* pAvatarNotes = static_cast(data)) + mNotes = !pAvatarNotes->notes.empty(); + break; + default: break; } } -void LLAvatarListEntry::setPosition(const LLVector3d& position, const F32& dist, bool drawn) +void LLAvatarListEntry::setPosition(const LLVector3d& position, const F32& dist, bool drawn, bool flood) { mPosition = position; bool here(dist != F32_MIN); // F32_MIN only if dead bool this_sim(here && (gAgent.getRegion()->pointInRegionGlobal(position) || !(LLWorld::getInstance()->positionRegionValidGlobal(position)))); - if (this_sim != mStats[STAT_TYPE_SIM]) chat_avatar_status(mName, mID, STAT_TYPE_SIM, mStats[STAT_TYPE_SIM] = this_sim, dist); - if (drawn != mStats[STAT_TYPE_DRAW]) chat_avatar_status(mName, mID, STAT_TYPE_DRAW, mStats[STAT_TYPE_DRAW] = drawn, dist); + if (this_sim != mStats[STAT_TYPE_SIM]) chat_avatar_status(mName, mID, STAT_TYPE_SIM, mStats[STAT_TYPE_SIM] = this_sim, dist, flood); + if (drawn != mStats[STAT_TYPE_DRAW]) chat_avatar_status(mName, mID, STAT_TYPE_DRAW, mStats[STAT_TYPE_DRAW] = drawn, dist, flood); bool shoutrange(here && dist < LFSimFeatureHandler::getInstance()->shoutRange()); - if (shoutrange != mStats[STAT_TYPE_SHOUTRANGE]) chat_avatar_status(mName, mID, STAT_TYPE_SHOUTRANGE, mStats[STAT_TYPE_SHOUTRANGE] = shoutrange, dist); + if (shoutrange != mStats[STAT_TYPE_SHOUTRANGE]) chat_avatar_status(mName, mID, STAT_TYPE_SHOUTRANGE, mStats[STAT_TYPE_SHOUTRANGE] = shoutrange, dist, flood); bool chatrange(here && dist < LFSimFeatureHandler::getInstance()->sayRange()); - if (chatrange != mStats[STAT_TYPE_CHATRANGE]) chat_avatar_status(mName, mID, STAT_TYPE_CHATRANGE, mStats[STAT_TYPE_CHATRANGE] = chatrange, dist); + if (chatrange != mStats[STAT_TYPE_CHATRANGE]) chat_avatar_status(mName, mID, STAT_TYPE_CHATRANGE, mStats[STAT_TYPE_CHATRANGE] = chatrange, dist, flood); } void LLAvatarListEntry::resetName(const bool& hide_tags, const bool& anon_names, const std::string& hidden) @@ -240,6 +262,16 @@ LLFloaterAvatarList::LLFloaterAvatarList() : LLFloater(std::string("radar")), LLFloaterAvatarList::~LLFloaterAvatarList() { + mCleanup = true; + LLSD sort; + for (const auto& col : mAvatarList->getSortOrder()) + { + sort.append(mAvatarList->getColumn(col.first)->mName); + sort.append(col.second); + } + + gSavedSettings.setLLSD("RadarSortOrder", sort); + mAvatars.clear(); } //static @@ -268,7 +300,7 @@ void LLFloaterAvatarList::draw() void LLFloaterAvatarList::onOpen() { - if (mAvatars.size()) refreshAvatarList(); + refreshAvatarList(); } void LLFloaterAvatarList::onClose(bool app_quitting) @@ -285,71 +317,97 @@ BOOL LLFloaterAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask) return LLFloater::handleRightMouseDown(x, y, mask); } +bool is_nearby(const LLUUID& id) +{ + if (id.isNull()) return false; + if (const auto inst = LLFloaterAvatarList::getIfExists()) + return inst->getAvatarEntry(id); + uuid_vec_t avatars; + LLWorld::instance().getAvatars(&avatars); + return std::find(avatars.begin(), avatars.end(), id) != avatars.end(); +} + +const LLVector3d& get_av_pos(const LLUUID& id) +{ + if (const auto inst = LLFloaterAvatarList::getIfExists()) + if (const auto av = inst->getAvatarEntry(id)) + return av->getPosition(); + + LLWorld::pos_map_t avatars; + LLWorld::instance().getAvatars(&avatars); + return avatars[id]; +} + +void track_av(const LLUUID& id) +{ + if (auto inst = LLFloaterAvatarList::getIfExists()) + if (inst->getAvatarEntry(id)) + { + inst->trackAvatar(id); + return; + } + + LLWorld::pos_map_t avatars; + LLWorld::instance().getAvatars(&avatars); + LLTracker::trackLocation(avatars[id], LLStringUtil::null, LLStringUtil::null); +} + static void cmd_profile(const LLAvatarListEntry* entry); -static void cmd_toggle_mark(LLAvatarListEntry* entry); +static void cmd_toggle_mark(LLAvatarListEntry* entry) +{ + bool mark = !entry->isMarked(); + void mm_setcolor(LLUUID key, LLColor4 col); + void mm_clearMark(const LLUUID & id); + mark ? mm_setcolor(entry->getID(), LLColor4::red) : mm_clearMark(entry->getID()); + entry->setMarked(mark); +} static void cmd_ar(const LLAvatarListEntry* entry); static void cmd_teleport(const LLAvatarListEntry* entry); +const LLUUID& active_owner_or_id(const LLSD& userdata); + namespace { typedef LLMemberListener view_listener_t; - class RadarTrack : public view_listener_t + class RadarTrack final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLFloaterAvatarList::instance().onClickTrack(); return true; } }; - class RadarMark : public view_listener_t + class RadarFocus final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLFloaterAvatarList::instance().doCommand(cmd_toggle_mark); + LLFloaterAvatarList::setFocusAvatar(active_owner_or_id(userdata)); return true; } }; - class RadarFocus : public view_listener_t + class RadarFocusPrev final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) - { - LLFloaterAvatarList::instance().onClickFocus(); - return true; - } - }; - - class RadarFocusPrev : public view_listener_t - { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLFloaterAvatarList::instance().focusOnPrev(userdata.asInteger()); return true; } }; - class RadarFocusNext : public view_listener_t + class RadarFocusNext final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLFloaterAvatarList::instance().focusOnNext(userdata.asInteger()); return true; } }; - class RadarTeleportTo : public view_listener_t - { - bool handleEvent(LLPointer event, const LLSD& userdata) - { - LLFloaterAvatarList::instance().doCommand(cmd_teleport, true); - return true; - } - }; - - class RadarAnnounceKeys : public view_listener_t + class RadarAnnounceKeys final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLFloaterAvatarList::instance().sendKeys(); return true; @@ -361,13 +419,11 @@ void addMenu(view_listener_t* menu, const std::string& name); void add_radar_listeners() { - addMenu(new RadarTrack(), "Radar.Track"); - addMenu(new RadarMark(), "Radar.Mark"); - addMenu(new RadarFocus(), "Radar.Focus"); - addMenu(new RadarFocusPrev(), "Radar.FocusPrev"); - addMenu(new RadarFocusNext(), "Radar.FocusNext"); - addMenu(new RadarTeleportTo(), "Radar.TeleportTo"); - addMenu(new RadarAnnounceKeys(), "Radar.AnnounceKeys"); + addMenu(new RadarTrack, "Radar.Track"); + addMenu(new RadarFocus, "Radar.Focus"); + addMenu(new RadarFocusPrev, "Radar.FocusPrev"); + addMenu(new RadarFocusNext, "Radar.FocusNext"); + addMenu(new RadarAnnounceKeys, "Radar.AnnounceKeys"); } BOOL LLFloaterAvatarList::postBuild() @@ -401,19 +457,26 @@ BOOL LLFloaterAvatarList::postBuild() gSavedSettings.getControl("RadarColumnAltitudeHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this)); gSavedSettings.getControl("RadarColumnActivityHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this)); gSavedSettings.getControl("RadarColumnVoiceHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + gSavedSettings.getControl("RadarColumnNotesHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this)); gSavedSettings.getControl("RadarColumnAgeHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this)); gSavedSettings.getControl("RadarColumnTimeHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this)); // Get a pointer to the scroll list from the interface mAvatarList = getChild("avatar_list"); - mAvatarList->sortByColumn("distance", true); + const LLSD sort = gSavedSettings.getLLSD("RadarSortOrder"); + for (auto it = sort.beginArray(), end = sort.endArray(); it < end; ++it) + { + const auto& column_name = (*it); + const auto& ascending = (*++it); + mAvatarList->sortByColumn(column_name.asStringRef(), ascending.asBoolean()); + } mAvatarList->setCommitOnSelectionChange(true); mAvatarList->setCommitCallback(boost::bind(&LLFloaterAvatarList::onSelectName,this)); mAvatarList->setDoubleClickCallback(boost::bind(&LLFloaterAvatarList::onClickFocus,this)); mAvatarList->setSortChangedCallback(boost::bind(&LLFloaterAvatarList::onAvatarSortingChanged,this)); - BOOST_FOREACH(LLViewerRegion* region, LLWorld::instance().getRegionList()) + for (LLViewerRegion* region : LLWorld::instance().getRegionList()) { - updateAvatarList(region); + updateAvatarList(region, true); } assessColumns(); @@ -445,6 +508,21 @@ void col_helper(const bool hide, LLCachedControl &setting, LLScrollListColu } } +enum AVATARS_COLUMN_ORDER +{ + LIST_MARK, + LIST_AVATAR_NAME, + LIST_DISTANCE, + LIST_POSITION, + LIST_ALTITUDE, + LIST_ACTIVITY, + LIST_VOICE, + LIST_NOTES, + LIST_AGE, + LIST_TIME, + LIST_CLIENT, +}; + //Macro to reduce redundant lines. Preprocessor concatenation and stringizing avoids bloat that //wrapping in a class would create. #define BIND_COLUMN_TO_SETTINGS(col, name)\ @@ -459,6 +537,7 @@ void LLFloaterAvatarList::assessColumns() BIND_COLUMN_TO_SETTINGS(LIST_ALTITUDE,Altitude); BIND_COLUMN_TO_SETTINGS(LIST_ACTIVITY,Activity); BIND_COLUMN_TO_SETTINGS(LIST_VOICE,Voice); + BIND_COLUMN_TO_SETTINGS(LIST_NOTES,Notes); BIND_COLUMN_TO_SETTINGS(LIST_AGE,Age); BIND_COLUMN_TO_SETTINGS(LIST_TIME,Time); @@ -509,7 +588,13 @@ void updateParticleActivity(LLDrawable *drawablep) } } -void LLFloaterAvatarList::updateAvatarList(const LLViewerRegion* region) +const F32& radar_range_radius() +{ + static const LLCachedControl radius("RadarRangeRadius", 0); + return radius; +} + +void LLFloaterAvatarList::updateAvatarList(const LLViewerRegion* region, bool first) { // Check whether updates are enabled if (!mUpdate) @@ -520,11 +605,10 @@ void LLFloaterAvatarList::updateAvatarList(const LLViewerRegion* region) { const std::vector& map_avs(region->mMapAvatars); - const std::vector& map_avids(region->mMapAvatarIDs); + const uuid_vec_t& map_avids(region->mMapAvatarIDs); const LLVector3d& mypos(gAgent.getPositionGlobal()); const LLVector3d& origin(region->getOriginGlobal()); - static const LLCachedControl radar_range_radius("RadarRangeRadius", 0); - const F32 max_range(radar_range_radius * radar_range_radius); + const F32 max_range(radar_range_radius() * radar_range_radius()); static LLCachedControl announce(gSavedSettings, "RadarChatKeys"); std::queue announce_keys; @@ -556,7 +640,7 @@ void LLFloaterAvatarList::updateAvatarList(const LLViewerRegion* region) } // Announce position - entry->setPosition(position, (position - mypos).magVec(), avatarp); + entry->setPosition(position, (position - mypos).magVec(), avatarp, first); // Mark as typing if they are typing if (avatarp && avatarp->isTyping()) entry->setActivity(LLAvatarListEntry::ACTIVITY_TYPING); @@ -577,13 +661,13 @@ void LLFloaterAvatarList::updateAvatarList(const LLViewerRegion* region) U32 num_ids = 0; while(!announce_keys.empty()) { - ids << "," << announce_keys.front().asString(); + ids << ',' << announce_keys.front().asString(); ++num_ids; if (ids.tellp() > 200) { send_keys_message(transact_num, num_ids, ids.str()); ids.seekp(num_ids = 0); - ids.str(""); + ids.str(LLStringUtil::null); } announce_keys.pop(); } @@ -594,28 +678,22 @@ void LLFloaterAvatarList::updateAvatarList(const LLViewerRegion* region) void LLFloaterAvatarList::expireAvatarList(const std::list& ids) { - BOOST_FOREACH(const LLUUID& id, ids) + if (!ids.empty()) { - av_list_t::iterator it(std::find_if(mAvatars.begin(), mAvatars.end(), LLAvatarListEntry::uuidMatch(id))); - if (it != mAvatars.end()) + uuid_vec_t existing_avs; + std::vector neighbors; + gAgent.getRegion()->getNeighboringRegions(neighbors); + for (const LLViewerRegion* region : neighbors) + existing_avs.insert(existing_avs.end(), region->mMapAvatarIDs.begin(), region->mMapAvatarIDs.end()); + for (const LLUUID& id : ids) { - LLAvatarListEntry* entry = it->get(); - entry->setPosition(entry->getPosition(), F32_MIN, false); // Dead and gone - mAvatars.erase(it); + if (std::find(existing_avs.begin(), existing_avs.end(), id) != existing_avs.end()) continue; // Now in another region we know. + av_list_t::iterator it(std::find_if(mAvatars.begin(), mAvatars.end(), LLAvatarListEntry::uuidMatch(id))); + if (it != mAvatars.end()) + mAvatars.erase(it); } } - if (mAvatars.empty()) - setTitle(getString("Title")); - else if (mAvatars.size() == 1) - setTitle(getString("TitleOneAvatar")); - else - { - LLStringUtil::format_map_t args; - args["[COUNT]"] = boost::lexical_cast(mAvatars.size()); - setTitle(getString("TitleWithCount", args)); - } - refreshAvatarList(); refreshTracker(); } @@ -648,7 +726,7 @@ bool getCustomColorRLV(const LLUUID& id, LLColor4& color, LLViewerRegion* parent */ void LLFloaterAvatarList::refreshAvatarList() { - // Don't update list when interface is hidden + // Don't update when interface is hidden if (!getVisible()) return; // We rebuild the list fully each time it's refreshed @@ -669,8 +747,9 @@ void LLFloaterAvatarList::refreshAvatarList() localRectToScreen(getLocalRect(), &screen_rect); speakermgr.update(!(screen_rect.pointInRect(gViewerWindow->getCurrentMouseX(), gViewerWindow->getCurrentMouseY()) && gMouseIdleTimer.getElapsedTimeF32() < 5.f)); + av_list_t dead_entries; bool name_restricted(gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS) || gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)); - BOOST_FOREACH(av_list_t::value_type& entry, mAvatars) + for (auto& entry : mAvatars) { LLVector3d position = entry->getPosition(); LLVector3d delta = position - mypos; @@ -684,7 +763,11 @@ void LLFloaterAvatarList::refreshAvatarList() //jcool410 -- this fucks up seeing dueds thru minimap data > 1024m away, so, lets just say > 2048m to the side is bad //aka 8 sims - if (delta.magVec() > 2048.0) continue; + if (delta.magVec() > 2048.0) + { + dead_entries.push_back(entry); + continue; + } entry->setInList(); const LLUUID& av_id = entry->getID(); @@ -700,7 +783,7 @@ void LLFloaterAvatarList::refreshAvatarList() if (entry->isMarked()) { mark.value = "X"; - mark.color = LLColor4::blue; + mark.color = *mm_getMarkerColor(av_id); mark.font_style = "BOLD"; } element.columns.add(mark); @@ -899,6 +982,12 @@ void LLFloaterAvatarList::refreshAvatarList() element.columns.add(voice); } + static const LLCachedControl hide_notes("RadarColumnNotesHidden"); + if (!hide_notes) + { + element.columns.add(LLScrollListCell::Params().column("notes").type("checkbox").enabled(false).value(entry->mNotes)); + } + static const LLCachedControl hide_age("RadarColumnAgeHidden"); if (!hide_age) { @@ -916,7 +1005,7 @@ void LLFloaterAvatarList::refreshAvatarList() color = sRadarTextYoung; } } - agep.value = age_set ? boost::lexical_cast(entry->mAge) : "?"; + agep.value = age_set ? fmt::to_string(entry->mAge) : "?"; agep.color = color; element.columns.add(agep); } @@ -969,6 +1058,20 @@ void LLFloaterAvatarList::refreshAvatarList() mAvatarList->addRow(element); } + for (auto& dead : dead_entries) + mAvatars.erase(std::remove(mAvatars.begin(), mAvatars.end(), dead), mAvatars.end()); + + if (mAvatars.empty()) + setTitle(getString("Title")); + else if (mAvatars.size() == 1) + setTitle(getString("TitleOneAvatar")); + else + { + LLStringUtil::format_map_t args; + args["[COUNT]"] = fmt::to_string(mAvatars.size()); + setTitle(getString("TitleWithCount", args)); + } + // finish mAvatarList->updateSort(); mAvatarList->selectMultiple(selected); @@ -984,7 +1087,7 @@ void LLFloaterAvatarList::resetAvatarNames() bool hide_tags(gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)); bool anon_names(gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)); const std::string& hidden(RlvStrings::getString(RLV_STRING_HIDDEN)); - BOOST_FOREACH(av_list_t::value_type& entry, mAvatars) + for (auto& entry : mAvatars) { entry->resetName(hide_tags, anon_names, hidden); } @@ -1025,8 +1128,11 @@ void LLFloaterAvatarList::onClickTrack() LLScrollListItem* item = mAvatarList->getFirstSelected(); if (!item) return; - LLUUID agent_id = item->getUUID(); + trackAvatar(item->getUUID()); +} +void LLFloaterAvatarList::trackAvatar(const LLUUID& agent_id) +{ if (mTracking && mTrackedAvatar == agent_id) { LLTracker::stopTracking(false); @@ -1074,7 +1180,6 @@ void LLFloaterAvatarList::trackAvatar(const LLAvatarListEntry* entry) const LLAvatarListEntry* LLFloaterAvatarList::getAvatarEntry(const LLUUID& avatar) const { - if (avatar.isNull()) return NULL; av_list_t::const_iterator iter = std::find_if(mAvatars.begin(),mAvatars.end(),LLAvatarListEntry::uuidMatch(avatar)); return (iter != mAvatars.end()) ? iter->get() : NULL; } @@ -1125,15 +1230,22 @@ void LLFloaterAvatarList::onClickFocus() void LLFloaterAvatarList::removeFocusFromAll() { - BOOST_FOREACH(av_list_t::value_type& entry, mAvatars) + for (auto& entry : mAvatars) { entry->setFocus(false); } } +// static void LLFloaterAvatarList::setFocusAvatar(const LLUUID& id) { - if (!gAgentCamera.lookAtObject(id, false) && !lookAtAvatar(id)) return; + if (/*!gAgentCamera.lookAtObject(id, false) &&*/ !lookAtAvatar(id)) return; + if (auto inst = getIfExists()) + inst->setFocusAvatarInternal(id); +} + +void LLFloaterAvatarList::setFocusAvatarInternal(const LLUUID& id) +{ av_list_t::iterator iter = std::find_if(mAvatars.begin(),mAvatars.end(),LLAvatarListEntry::uuidMatch(id)); if (iter == mAvatars.end()) return; removeFocusFromAll(); @@ -1237,13 +1349,13 @@ void LLFloaterAvatarList::sendKeys() const for (U32 i = 0; i < regionp->mMapAvatarIDs.size(); ++i) { - ids << "," << regionp->mMapAvatarIDs.at(i); + ids << ',' << regionp->mMapAvatarIDs.at(i); ++num_ids; if (ids.tellp() > 200) { send_keys_message(transact_num, num_ids, ids.str()); ids.seekp(num_ids = 0); - ids.str(""); + ids.str(LLStringUtil::null); } } if (num_ids > 0) send_keys_message(transact_num, num_ids, ids.str()); @@ -1337,42 +1449,10 @@ void send_eject(const LLUUID& avatar_id, bool ban) } } -static void send_estate_message( - const char* request, - const LLUUID& target) -{ - - LLMessageSystem* msg = gMessageSystem; - LLUUID invoice; - - // This seems to provide an ID so that the sim can say which request it's - // replying to. I think this can be ignored for now. - invoice.generate(); - - LL_INFOS() << "Sending estate request '" << request << "'" << LL_ENDL; - msg->newMessage("EstateOwnerMessage"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgentID); - msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); - msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used - msg->nextBlock("MethodData"); - msg->addString("Method", request); - msg->addUUID("Invoice", invoice); - - // Agent id - msg->nextBlock("ParamList"); - msg->addString("Parameter", gAgentID.asString().c_str()); - - // Target - msg->nextBlock("ParamList"); - msg->addString("Parameter", target.asString().c_str()); - - msg->sendReliable(gAgent.getRegion()->getHost()); -} +void send_estate_message(const std::string request, const std::vector& strings); static void cmd_append_names(const LLAvatarListEntry* entry, std::string &str, std::string &sep) { if(!str.empty())str.append(sep);str.append(entry->getName()); } -static void cmd_toggle_mark(LLAvatarListEntry* entry) { entry->toggleMark(); } static void cmd_ar(const LLAvatarListEntry* entry) { LLFloaterReporter::showFromObject(entry->getID()); } static void cmd_profile(const LLAvatarListEntry* entry) { LLAvatarActions::showProfile(entry->getID()); } static void cmd_teleport(const LLAvatarListEntry* entry) { gAgent.teleportViaLocation(entry->getPosition()); } @@ -1380,8 +1460,9 @@ static void cmd_freeze(const LLAvatarListEntry* entry) { send_freeze(entry->get static void cmd_unfreeze(const LLAvatarListEntry* entry) { send_freeze(entry->getID(), false); } static void cmd_eject(const LLAvatarListEntry* entry) { send_eject(entry->getID(), false); } static void cmd_ban(const LLAvatarListEntry* entry) { send_eject(entry->getID(), true); } -static void cmd_estate_eject(const LLAvatarListEntry* entry){ send_estate_message("teleporthomeuser", entry->getID()); } -static void cmd_estate_ban(const LLAvatarListEntry* entry) { LLPanelEstateInfo::sendEstateAccessDelta(ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_NO_REPLY, entry->getID()); } +static void cmd_estate_eject(const LLAvatarListEntry* entry){ send_estate_message("kickestate", {entry->getID().asString()}); } +static void cmd_estate_tp_home(const LLAvatarListEntry* entry){ send_estate_message("teleporthomeuser", {gAgentID.asString(), entry->getID().asString()}); } +static void cmd_estate_ban(const LLAvatarListEntry* entry) { LLPanelEstateAccess::sendEstateAccessDelta(ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_NO_REPLY, entry->getID()); } void LLFloaterAvatarList::doCommand(avlist_command_t func, bool single/*=false*/) const { @@ -1412,7 +1493,7 @@ std::string LLFloaterAvatarList::getSelectedNames(const std::string& separator) std::string LLFloaterAvatarList::getSelectedName() const { LLAvatarListEntry* entry = getAvatarEntry(getSelectedID()); - return entry ? entry->getName() : ""; + return entry ? entry->getName() : LLStringUtil::null; } LLUUID LLFloaterAvatarList::getSelectedID() const @@ -1451,8 +1532,9 @@ void LLFloaterAvatarList::callbackEjectFromEstate(const LLSD& notification, cons { if (!instanceExists()) return; LLFloaterAvatarList& inst(instance()); - if (!LLNotification::getSelectedOption(notification, response)) // if == 0 - inst.doCommand(cmd_estate_eject); + S32 option = LLNotification::getSelectedOption(notification, response); + if (option != 2) + inst.doCommand(option ? cmd_estate_tp_home : cmd_estate_eject); } //static diff --git a/indra/newview/llfloateravatarlist.h b/indra/newview/llfloateravatarlist.h index 93230f9a55..5c83219878 100644 --- a/indra/newview/llfloateravatarlist.h +++ b/indra/newview/llfloateravatarlist.h @@ -79,7 +79,7 @@ enum ACTIVITY_TYPE * Update world position. * Affects age. */ - void setPosition(const LLVector3d& position, const F32& dist, bool drawn); + void setPosition(const LLVector3d& position, const F32& dist, bool drawn, bool flood = false); const LLVector3d& getPosition() const { return mPosition; } @@ -124,7 +124,7 @@ enum ACTIVITY_TYPE bool isInList() const { return mIsInList; } - void toggleMark() { mMarked = !mMarked; } + void setMarked(bool marked) { mMarked = marked; } struct uuidMatch { @@ -143,6 +143,7 @@ enum ACTIVITY_TYPE bool mMarked; bool mFocused; bool mIsInList; + bool mNotes = false; int mAge; /** @@ -202,7 +203,7 @@ class LLFloaterAvatarList : public LLFloater, public LLSingleton avlist_command_t; @@ -264,7 +251,7 @@ class LLFloaterAvatarList : public LLFloater, public LLSingleton& ids); void updateAvatarSorting(); + static bool isCleanup() + { + const auto& inst = getIfExists(); + return inst && inst->mCleanup; + } private: + void setFocusAvatarInternal(const LLUUID& id); + /** * @brief Pointer to the avatar scroll list */ LLScrollListCtrl* mAvatarList; av_list_t mAvatars; bool mDirtyAvatarSorting; + bool mCleanup = false; /** * @brief true when Updating diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index ece9d1f1a1..6c5e227753 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -257,16 +257,21 @@ void LLFloaterAvatarPicker::onBtnSelect() uuid_vec_t avatar_ids; std::vector avatar_names; getSelectedAvatarData(list, avatar_ids, avatar_names); + if (mCloseOnSelect) // Singu Note: Close before callback if we get here first, makes potential next dialog floater position correctly + { + mCloseOnSelect = FALSE; + close(); + } mSelectionCallback(avatar_ids, avatar_names); } } getChild("SearchResults")->deselectAllItems(TRUE); getChild("NearMe")->deselectAllItems(TRUE); getChild("Friends")->deselectAllItems(TRUE); - if(mCloseOnSelect) + if (mCloseOnSelect) { mCloseOnSelect = FALSE; - close(); + close(); } } @@ -396,47 +401,40 @@ void LLFloaterAvatarPicker::drawFrustum() if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLEnable(GL_CULL_FACE); - gGL.begin(LLRender::QUADS); + LLGLEnable clip; + gGL.begin(LLRender::TRIANGLE_STRIP); { - gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); - gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop); - gGL.vertex2i(origin_rect.mRight, origin_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); - gGL.vertex2i(local_rect.mRight, local_rect.mTop); - gGL.vertex2i(local_rect.mLeft, local_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); gGL.vertex2i(local_rect.mLeft, local_rect.mTop); - gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); - gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom); gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); - gGL.vertex2i(local_rect.mRight, local_rect.mBottom); gGL.vertex2i(local_rect.mRight, local_rect.mTop); gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(origin_rect.mRight, origin_rect.mTop); - gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom); - gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); - gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); gGL.vertex2i(local_rect.mRight, local_rect.mBottom); gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); + gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop); } gGL.end(); } if (gFocusMgr.childHasMouseCapture(getDragHandle())) { - mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime)); + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(mContextConeFadeTime)); } else { - mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime)); + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(mContextConeFadeTime)); } } } diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp index 5308501a82..79c6d72b8a 100644 --- a/indra/newview/llfloateravatartextures.cpp +++ b/indra/newview/llfloateravatartextures.cpp @@ -46,6 +46,10 @@ LLFloaterAvatarTextures::LLFloaterAvatarTextures(const LLUUID& id) : LLFloater(std::string("avatar_texture_debug")), mID(id) { + for (U32 i = 0; i < TEX_NUM_INDICES; i++) + { + mTextures[i] = nullptr; + } } LLFloaterAvatarTextures::~LLFloaterAvatarTextures() diff --git a/indra/newview/llfloaterbanduration.cpp b/indra/newview/llfloaterbanduration.cpp new file mode 100644 index 0000000000..3555cd846d --- /dev/null +++ b/indra/newview/llfloaterbanduration.cpp @@ -0,0 +1,92 @@ +/** +* @file llfloaterbanduration.cpp +* +* $LicenseInfo:firstyear=2004&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2018, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" +#include "llfloaterbanduration.h" + +#include "llcombobox.h" +#include "llspinctrl.h" +#include "lluictrlfactory.h" + +LLFloaterBanDuration::LLFloaterBanDuration(const LLSD& target) : LLFloater() +{ + LLUICtrlFactory::instance().buildFloater(this, "floater_ban_duration.xml"); +} + +BOOL LLFloaterBanDuration::postBuild() +{ + childSetAction("ok_btn", boost::bind(&LLFloaterBanDuration::onClickBan, this)); + childSetAction("cancel_btn", boost::bind(&LLFloaterBanDuration::close, this, false)); + + auto combo = getChild("ban_duration_combo"); + combo->setCommitCallback(boost::bind(&LLFloaterBanDuration::onClickCombo, this, _2, getChild("ban_duration"))); + combo->onCommit(); + + return TRUE; +} + +LLFloaterBanDuration* LLFloaterBanDuration::show(select_callback_t callback, const uuid_vec_t& ids) +{ + LLFloaterBanDuration* floater = showInstance(); + if (!floater) + { + LL_WARNS() << "Cannot instantiate ban duration floater" << LL_ENDL; + return nullptr; + } + + floater->mSelectionCallback = callback; + floater->mAvatar_ids = ids; + + return floater; +} + +void LLFloaterBanDuration::onClickCombo(const LLSD& val, LLUICtrl* duration) +{ + duration->setEnabled(val.asInteger() != 0); +} + +void LLFloaterBanDuration::onClickBan() +{ + if (mSelectionCallback) + { + S32 time = 0; + if (auto type = getChild("ban_duration_combo")->getValue().asInteger()) + { + LLSpinCtrl* duration_spin = getChild("ban_duration"); + if (duration_spin) + { + time = (duration_spin->getValue().asInteger() * 3600); + if (type > 1) + { + time *= type == 2 ? 24 : type == 3 ? 168 : 730; + } + time += LLDate::now().secondsSinceEpoch(); + } + } + mSelectionCallback(mAvatar_ids, time); + } + close(); +} + diff --git a/indra/newview/llfloaterbanduration.h b/indra/newview/llfloaterbanduration.h new file mode 100644 index 0000000000..75b063ec68 --- /dev/null +++ b/indra/newview/llfloaterbanduration.h @@ -0,0 +1,52 @@ +/** +* @file llfloaterbanduration.h +* +* $LicenseInfo:firstyear=2004&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2018, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + + +#ifndef LL_FLOATERBANDURATION_H +#define LL_FLOATERBANDURATION_H + +#include "llfloater.h" + +class LLFloaterBanDuration : public LLFloater +, public LLFloaterSingleton +{ + typedef std::function select_callback_t; + +public: + LLFloaterBanDuration(const LLSD& target); + BOOL postBuild() override; + static LLFloaterBanDuration* show(select_callback_t callback, const uuid_vec_t& ids); + +private: + ~LLFloaterBanDuration() {}; + void onClickBan(); + void onClickCombo(const LLSD&, LLUICtrl*); + + uuid_vec_t mAvatar_ids; + select_callback_t mSelectionCallback; +}; + +#endif // LL_FLOATERBANDURATION_H + diff --git a/indra/newview/llfloaterblacklist.cpp b/indra/newview/llfloaterblacklist.cpp index dd80e21381..bfbfd0a09a 100644 --- a/indra/newview/llfloaterblacklist.cpp +++ b/indra/newview/llfloaterblacklist.cpp @@ -20,10 +20,10 @@ LLFloaterBlacklist* LLFloaterBlacklist::sInstance; -std::vector LLFloaterBlacklist::blacklist_textures; -std::vector LLFloaterBlacklist::blacklist_objects; +uuid_vec_t LLFloaterBlacklist::blacklist_textures; +uuid_vec_t LLFloaterBlacklist::blacklist_objects; -std::map LLFloaterBlacklist::blacklist_entries; +boost::unordered_map LLFloaterBlacklist::blacklist_entries; LLFloaterBlacklist::LLFloaterBlacklist() : LLFloater() @@ -85,10 +85,10 @@ BOOL LLFloaterBlacklist::postBuild() } void LLFloaterBlacklist::refresh() { - + LLScrollListCtrl* list = getChild("file_list"); list->clearRows(); - for(std::map::iterator iter = blacklist_entries.begin(); iter != blacklist_entries.end(); ++iter) + for(auto iter = blacklist_entries.begin(); iter != blacklist_entries.end(); ++iter) { if(iter->first.isNull()) continue; LLSD element; @@ -207,13 +207,17 @@ void LLFloaterBlacklist::onClickRemove(void* user_data) LLScrollListCtrl* list = floaterp->getChild("file_list"); if(list->getFirstSelected()) { - LLScrollListItem* item = list->getFirstSelected(); - LLUUID selected_id = item->getColumn(0)->getValue().asUUID(); - if(selected_id.isNull()) return; - list->deleteSingleItem(list->getFirstSelectedIndex()); - blacklist_entries.erase(selected_id); + uuid_vec_t selectedIDs = list->getSelectedIDs(); + uuid_vec_t::const_iterator iterator; + for(iterator = selectedIDs.begin(); + iterator != selectedIDs.end(); + ++iterator) + { + LLUUID selectedID = *iterator; + blacklist_entries.erase(selectedID); + } + list->deleteSelectedItems(); updateBlacklists(); - } } // static @@ -242,7 +246,7 @@ void LLFloaterBlacklist::updateBlacklists() blacklist_textures.clear(); blacklist_objects.clear(); gAssetStorage->mBlackListedAsset.clear(); - for(std::map::iterator iter = blacklist_entries.begin(); iter != blacklist_entries.end(); ++iter) + for(auto iter = blacklist_entries.begin(); iter != blacklist_entries.end(); ++iter) { if(blacklist_entries[iter->first]["entry_type"].asString() == "0") { @@ -252,12 +256,12 @@ void LLFloaterBlacklist::updateBlacklists() { gAssetStorage->mBlackListedAsset.push_back(LLUUID(iter->first)); } - + if(blacklist_entries[iter->first]["entry_type"].asString() == "6") { blacklist_objects.push_back(LLUUID(iter->first)); } - + } saveToDisk(); LLFloaterBlacklist* instance = LLFloaterBlacklist::getInstance(); @@ -272,7 +276,7 @@ void LLFloaterBlacklist::saveToDisk() std::string file_name = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "blacklist_sg1.xml"); llofstream export_file(file_name); LLSD data; - for(std::map::iterator iter = blacklist_entries.begin(); iter != blacklist_entries.end(); ++iter) + for(auto iter = blacklist_entries.begin(); iter != blacklist_entries.end(); ++iter) { data[iter->first.asString()] = iter->second; } @@ -296,11 +300,11 @@ void LLFloaterBlacklist::onClickSave_continued(AIFilePicker* filepicker) std::string file_name = filepicker->getFilename(); llofstream export_file(file_name); LLSD data; - for(std::map::iterator iter = blacklist_entries.begin(); iter != blacklist_entries.end(); ++iter) + for(auto iter = blacklist_entries.begin(); iter != blacklist_entries.end(); ++iter) { data[iter->first.asString()] = iter->second; } - LLSDSerialize::toPrettyXML(data, export_file); + LLSDSerialize::toPrettyXML(data, export_file); export_file.close(); } } @@ -336,14 +340,13 @@ void LLFloaterBlacklist::onClickLoad_continued(AIFilePicker* filepicker) void LLFloaterBlacklist::onClickRerender(void* user_data) { - std::map blacklist_new; - for(std::map::iterator itr = blacklist_entries.begin(); itr != blacklist_entries.end(); ++itr) + for(auto itr = blacklist_entries.begin(); itr != blacklist_entries.end();) { - if(blacklist_entries[itr->first]["entry_type"].asString() == "6") continue; - blacklist_new[itr->first] = blacklist_entries[itr->first]; - blacklist_new[itr->second] = blacklist_entries[itr->second]; + if (blacklist_entries[itr->first]["entry_type"].asString() == "6") + itr = blacklist_entries.erase(itr); + else + ++itr; } - blacklist_entries = blacklist_new; saveToDisk(); LLFloaterBlacklist* instance = LLFloaterBlacklist::getInstance(); if(instance) diff --git a/indra/newview/llfloaterblacklist.h b/indra/newview/llfloaterblacklist.h index 9b5c4171fc..c15c99a9cb 100644 --- a/indra/newview/llfloaterblacklist.h +++ b/indra/newview/llfloaterblacklist.h @@ -16,8 +16,7 @@ class LLFloaterBlacklist : LLFloater BOOL postBuild(); void refresh(); static LLFloaterBlacklist* getInstance() { return sInstance; }; - - + /*This is the function to call to add anything to the blacklist, key is the asset ID LLSD data is as follows: LLSD[entry_type] = LLAssetType::Etype, @@ -29,12 +28,9 @@ class LLFloaterBlacklist : LLFloater */ static void addEntry(LLUUID key, LLSD data); - - - - static std::map blacklist_entries; - static std::vector blacklist_textures; - static std::vector blacklist_objects; + static boost::unordered_map blacklist_entries; + static uuid_vec_t blacklist_textures; + static uuid_vec_t blacklist_objects; static void loadFromSave(); diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp index 7e9589a790..0fcdc70712 100644 --- a/indra/newview/llfloaterbulkpermission.cpp +++ b/indra/newview/llfloaterbulkpermission.cpp @@ -79,7 +79,7 @@ void LLFloaterBulkPermission::doApply() class ModifiableGatherer : public LLSelectedNodeFunctor { public: - ModifiableGatherer(std::vector& q) : mQueue(q) {} + ModifiableGatherer(uuid_vec_t& q) : mQueue(q) {} virtual bool apply(LLSelectNode* node) { if( node->allowOperationOnNode(PERM_MODIFY, GP_OBJECT_MANIPULATE) ) @@ -89,7 +89,7 @@ void LLFloaterBulkPermission::doApply() return true; } private: - std::vector& mQueue; + uuid_vec_t& mQueue; }; LLScrollListCtrl* list = getChild("queue output"); list->deleteAllItems(); @@ -342,12 +342,13 @@ void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, LLInve //status_text.setArg("[STATUS]", getString("status_ok_text")); status_text.setArg("[STATUS]", ""); } +#if 0 else { //status_text.setArg("[STATUS]", getString("status_bad_text")); status_text.setArg("[STATUS]", ""); } - +#endif list->addSimpleElement(status_text.getString()); //TODO if we are an object inside an object we should check a recuse flag and if set diff --git a/indra/newview/llfloaterbulkpermission.h b/indra/newview/llfloaterbulkpermission.h index 428e8ae963..ccbeb67414 100644 --- a/indra/newview/llfloaterbulkpermission.h +++ b/indra/newview/llfloaterbulkpermission.h @@ -89,7 +89,7 @@ class LLFloaterBulkPermission : public LLFloater, public LLVOInventoryListener, private: // Object Queue - std::vector mObjectIDs; + uuid_vec_t mObjectIDs; LLUUID mCurrentObjectID; BOOL mDone; diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index 8e5ff91ffe..9f4088347b 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -229,7 +229,7 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj, BOOL item_is_multi = FALSE; if ((inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED || inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS) - && !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK)) + && !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK)) { item_is_multi = TRUE; } diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp index 5a6ea24cb4..14f484e574 100644 --- a/indra/newview/llfloaterbuycurrency.cpp +++ b/indra/newview/llfloaterbuycurrency.cpp @@ -277,19 +277,19 @@ void LLFloaterBuyCurrencyUI::updateUI() S32 balance = gStatusBar->getBalance(); childShow("balance_label"); childShow("balance_amount"); - childSetTextArg("balance_amount", "[AMT]", llformat("%d", balance)); + childSetTextArg("balance_amount", "[AMT]", fmt::to_string(balance)); childSetTextArg("balance_amount", "[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); S32 buying = mManager.getAmount(); childShow("buying_label"); childShow("buying_amount"); - childSetTextArg("buying_amount", "[AMT]", llformat("%d", buying)); + childSetTextArg("buying_amount", "[AMT]", fmt::to_string(buying)); childSetTextArg("buying_amount", "[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); S32 total = balance + buying; childShow("total_label"); childShow("total_amount"); - childSetTextArg("total_amount", "[AMT]", llformat("%d", total)); + childSetTextArg("total_amount", "[AMT]", fmt::to_string(total)); childSetTextArg("total_amount", "[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); childSetVisible("purchase_warning_repurchase", false); diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 1ebbb0aece..080a74a48f 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -157,7 +157,8 @@ class LLFloaterBuyLandUI { TransactionPreflight, TransactionCurrency, - TransactionBuy + TransactionBuy, + TransactionNone }; boost::intrusive_ptr mResponder; TransactionType mTransactionType; @@ -175,7 +176,7 @@ class LLFloaterBuyLandUI void updateFloaterCovenantText(const std::string& string, const LLUUID &asset_id); void updateFloaterEstateName(const std::string& name); void updateFloaterLastModified(const std::string& text); - void updateFloaterEstateOwnerName(const std::string& name); + void updateFloaterEstateOwnerID(const LLUUID& id); void updateWebSiteInfo(); void finishWebSiteInfo(); @@ -262,12 +263,12 @@ void LLFloaterBuyLand::updateLastModified(const std::string& text) } // static -void LLFloaterBuyLand::updateEstateOwnerName(const std::string& name) +void LLFloaterBuyLand::updateEstateOwnerID(const LLUUID& id) { - LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::instanceExists() ? LLFloaterBuyLandUI::getInstance() : NULL; + LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::instanceExists() ? LLFloaterBuyLandUI::getInstance() : nullptr; if (floater) { - floater->updateFloaterEstateOwnerName(name); + floater->updateFloaterEstateOwnerID(id); } } @@ -281,11 +282,34 @@ void LLFloaterBuyLand::updateEstateOwnerName(const std::string& name) LLFloaterBuyLandUI::LLFloaterBuyLandUI() : LLFloater(std::string("Buy Land")), mParcelSelectionObserver(this), + mRegion(nullptr), mParcel(0), + mIsClaim(false), + mIsForGroup(false), + mCanBuy(false), + mCannotBuyIsError(false), mBought(false), - mParcelValid(false), mSiteValid(false), - mChildren(*this), mCurrency(*this), - mParcelBuyInfo(0) + mAgentCommittedTier(0), + mAgentHasNeverOwnedLand(true), + mParcelValid(false), + mParcelIsForSale(false), + mParcelIsGroupLand(false), + mParcelGroupContribution(0), + mParcelPrice(0), + mParcelActualArea(0), + mParcelBillableArea(0), + mParcelSupportedObjects(0), + mParcelSoldWithObjects(false), + mUserPlanChoice(0), + mSiteValid(false), + mSiteMembershipUpgrade(false), + mSiteLandUseUpgrade(false), + mPreflightAskBillableArea(0), + mPreflightAskCurrencyBuy(0), + mChildren(*this), + mCurrency(*this), + mParcelBuyInfo(nullptr), + mTransactionType(TransactionNone) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_buy_land.xml"); LLViewerParcelMgr::getInstance()->addObserver(&mParcelSelectionObserver); @@ -347,8 +371,6 @@ void LLFloaterBuyLandUI::updateParcelInfo() mParcelSnapshot.setNull(); mParcelSellerName = ""; - mCanBuy = false; - mCannotBuyIsError = false; if (!mParcelValid) { @@ -607,10 +629,10 @@ void LLFloaterBuyLandUI::updateFloaterLastModified(const std::string& text) if (editor) editor->setText(text); } -void LLFloaterBuyLandUI::updateFloaterEstateOwnerName(const std::string& name) +void LLFloaterBuyLandUI::updateFloaterEstateOwnerID(const LLUUID& id) { LLTextBox* box = getChild("estate_owner_text"); - if (box) box->setText(name); + if (box) box->setValue(id); } void LLFloaterBuyLandUI::updateWebSiteInfo() diff --git a/indra/newview/llfloaterbuyland.h b/indra/newview/llfloaterbuyland.h index 0d90130a0b..8bb98e0c28 100644 --- a/indra/newview/llfloaterbuyland.h +++ b/indra/newview/llfloaterbuyland.h @@ -46,7 +46,7 @@ class LLFloaterBuyLand static void updateCovenantText(const std::string& string, const LLUUID& asset_id); static void updateEstateName(const std::string& name); static void updateLastModified(const std::string& text); - static void updateEstateOwnerName(const std::string& name); + static void updateEstateOwnerID(const LLUUID& id); }; #endif diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index 9d988dcb59..5bf24ddcc3 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -36,13 +36,13 @@ #include "llbvhloader.h" #include "lldatapacker.h" #include "lldir.h" -#include "lleconomy.h" #include "llnotificationsutil.h" #include "llvfile.h" #include "llapr.h" #include "llstring.h" #include "llagent.h" +#include "llagentbenefits.h" #include "llanimationstates.h" #include "llbbox.h" #include "llbutton.h" @@ -144,14 +144,13 @@ std::string STATUS[] = // LLFloaterBvhPreview() //----------------------------------------------------------------------------- LLFloaterBvhPreview::LLFloaterBvhPreview(const std::string& filename, void* item) : - LLFloaterNameDesc(filename, item) + LLFloaterNameDesc(filename, item), + mItem(item), // + mLastMouseX(0), + mLastMouseY(0), + mPlayButton(nullptr), + mStopButton(nullptr) { - // - mItem = item; - // - mLastMouseX = 0; - mLastMouseY = 0; - mIDList["Standing"] = ANIM_AGENT_STAND; mIDList["Walking"] = ANIM_AGENT_FEMALE_WALK; mIDList["Sitting"] = ANIM_AGENT_SIT_FEMALE; @@ -230,7 +229,7 @@ BOOL LLFloaterBvhPreview::postBuild() getChild("priority")->setMaxValue(7); } - childSetLabelArg("ok_btn", "[UPLOADFEE]", gHippoGridManager->getConnectedGrid()->getUploadFee()); + childSetLabelArg("ok_btn", "[UPLOADFEE]", gHippoGridManager->getConnectedGrid()->formatFee(LLAgentBenefitsMgr::current().getAnimationUploadCost())); childSetAction("ok_btn", onBtnOK, this); setDefaultBtn(); @@ -353,7 +352,7 @@ BOOL LLFloaterBvhPreview::postBuild() // pass animation data through memory buffer loaderp->serialize(dp); dp.reset(); - success = motionp && motionp->deserialize(dp); + success = motionp && motionp->deserialize(dp, mMotionID); } else { @@ -412,7 +411,7 @@ BOOL LLFloaterBvhPreview::postBuild() motionp = (LLKeyframeMotion*)mAnimPreview->getDummyAvatar()->createMotion(mMotionID); LLDataPackerBinaryBuffer dp((U8*)file_buffer, file_size); dp.reset(); - success = motionp && motionp->deserialize(dp); + success = motionp && motionp->deserialize(dp, mMotionID); } raw_animatn.close(); @@ -524,16 +523,16 @@ void LLFloaterBvhPreview::draw() gGL.getTexUnit(0)->bind(mAnimPreview); - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLE_STRIP ); { gGL.texCoord2f(0.f, 1.f); gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); gGL.texCoord2f(0.f, 0.f); gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); gGL.texCoord2f(1.f, 1.f); gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); } gGL.end(); @@ -1239,7 +1238,7 @@ void LLFloaterBvhPreview::onBtnOK(void* userdata) std::string name = floaterp->getChild("name_form")->getValue().asString(); std::string desc = floaterp->getChild("description_form")->getValue().asString(); LLAssetStorage::LLStoreAssetCallback callback = NULL; - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 expected_upload_cost = LLAgentBenefitsMgr::current().getAnimationUploadCost(); void *userdata = NULL; // @@ -1269,7 +1268,9 @@ void LLFloaterBvhPreview::onBtnOK(void* userdata) 0, LLFolderType::FT_NONE, LLInventoryType::IT_ANIMATION, - LLFloaterPerms::getNextOwnerPerms("Uploads"), LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"), + LLFloaterPerms::getNextOwnerPerms("Uploads"), + LLFloaterPerms::getGroupPerms("Uploads"), + LLFloaterPerms::getEveryonePerms("Uploads"), name, callback, expected_upload_cost, userdata); } @@ -1309,17 +1310,10 @@ LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLViewerDynamicT mCameraPitch = 0.f; mCameraZoom = 1.f; - mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion()); - mDummyAvatar->createDrawable(&gPipeline); - mDummyAvatar->mIsDummy = TRUE; + mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), LLViewerObject::CO_FLAG_UI_AVATAR); mDummyAvatar->mSpecialRenderMode = 1; - mDummyAvatar->setPositionAgent(LLVector3::zero); - mDummyAvatar->slamPosition(); - mDummyAvatar->updateJointLODs(); - mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); mDummyAvatar->startMotion(ANIM_AGENT_STAND, BASE_ANIM_TIME_OFFSET); mDummyAvatar->hideSkirt(); - //gPipeline.markVisible(mDummyAvatar->mDrawable, *LLViewerCamera::getInstance()); // stop extraneous animations mDummyAvatar->stopMotion( ANIM_AGENT_HEAD_ROT, TRUE ); diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index 18826f961e..c2bf202830 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -50,7 +50,10 @@ const F32 CAMERA_BUTTON_DELAY = 0.0f; // LLFloaterCamera::LLFloaterCamera(const LLSD& val) -: LLFloater("camera floater") // uses "FloaterCameraRect3" +: LLFloater("camera floater"), // uses "FloaterCameraRect3" + mRotate(nullptr), + mZoom(nullptr), + mTrack(nullptr) { setIsChrome(TRUE); diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 449fe6028a..a3e51e234e 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -45,11 +45,13 @@ #include "llcombobox.h" #include "lltextparser.h" #include "lltrans.h" +#include "llurlregistry.h" #include "llwindow.h" // project include #include "ascentkeyword.h" #include "llagent.h" +#include "llavataractions.h" #include "llchatbar.h" #include "llconsole.h" #include "llfloaterchatterbox.h" @@ -77,7 +79,7 @@ // LLColor4 agent_chat_color(const LLUUID& id, const std::string&, bool local_chat = true); LLColor4 get_text_color(const LLChat& chat, bool from_im = false); -void show_log_browser(const std::string&, const std::string&); +void show_log_browser(const std::string&, const LLUUID&); // // Member Functions @@ -94,8 +96,7 @@ LLFloaterChat::LLFloaterChat(const LLSD& seed) LLTextEditor* history_editor_with_mute = getChild("Chat History Editor with mute"); getChild("show mutes")->setCommitCallback(boost::bind(&LLFloaterChat::onClickToggleShowMute, this, _2, getChild("Chat History Editor"), history_editor_with_mute)); - history_editor_with_mute->setVisible(false); - getChild("chat_history_open")->setCommitCallback(boost::bind(show_log_browser, "chat", "chat")); + getChild("chat_history_open")->setCommitCallback(boost::bind(show_log_browser, "chat", LLUUID::null)); } LLFloaterChat::~LLFloaterChat() @@ -195,13 +196,13 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ) // [/RLVa:KB] { - chat.mURL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str()); + chat.mURL = LLAvatarActions::getSLURL(chat.mFromID); } if (chat.mSourceType == CHAT_SOURCE_OBJECT) { LLStringUtil::trim(chat.mFromName); - if (!chat.mFromName.length()) + if (chat.mFromName.empty()) { chat.mFromName = LLTrans::getString("Unnamed"); line = chat.mFromName + line; @@ -212,19 +213,26 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& bool is_irc = italicize && chat.mChatStyle == CHAT_STYLE_IRC; // If the chat line has an associated url, link it up to the name. if (!chat.mURL.empty() - && (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0)) + && boost::algorithm::starts_with(line, chat.mFromName)) { - std::string start_line = line.substr(0, chat.mFromName.length() + 1); - line = line.substr(chat.mFromName.length() + 1); + line = line.substr(chat.mFromName.length()); LLStyleSP sourceStyle = LLStyleMap::instance().lookup(chat.mFromID, chat.mURL); sourceStyle->mItalic = is_irc; - edit->appendStyledText(start_line, false, prepend_newline, sourceStyle); + edit->appendText(chat.mFromName, false, prepend_newline, sourceStyle, false); prepend_newline = false; } LLStyleSP style(new LLStyle); style->setColor(color); style->mItalic = is_irc; - edit->appendStyledText(line, false, prepend_newline, style); + style->mBold = chat.mChatType == CHAT_TYPE_SHOUT; + edit->appendText(line, false, prepend_newline, style, chat.mSourceType == CHAT_SOURCE_SYSTEM); +} + +void LLFloaterChat::addChatHistory(const std::string& str, bool log_to_file) +{ + LLChat chat(str); + chat.mSourceType = CHAT_SOURCE_SYSTEM; + addChatHistory(chat, log_to_file); } void log_chat_text(const LLChat& chat) @@ -235,10 +243,10 @@ void log_chat_text(const LLChat& chat) else histstr = chat.mText; - LLLogChat::saveHistory(std::string("chat"), histstr); + LLLogChat::saveHistory("chat", LLUUID::null, histstr); } // static -void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) +void LLFloaterChat::addChatHistory(LLChat& chat, bool log_to_file) { // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) if (rlv_handler_t::isEnabled()) @@ -246,20 +254,18 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) // TODO-RLVa: we might cast too broad a net by filtering here, needs testing if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) && (!chat.mRlvLocFiltered) && (CHAT_SOURCE_AGENT != chat.mSourceType) ) { - LLChat& rlvChat = const_cast(chat); - RlvUtil::filterLocation(rlvChat.mText); - rlvChat.mRlvLocFiltered = TRUE; + RlvUtil::filterLocation(chat.mText); + chat.mRlvLocFiltered = TRUE; } if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!chat.mRlvNamesFiltered) ) { // NOTE: this will also filter inventory accepted/declined text in the chat history - LLChat& rlvChat = const_cast(chat); if (CHAT_SOURCE_AGENT != chat.mSourceType) { // Filter object and system chat (names are filtered elsewhere to save ourselves an gObjectList lookup) - RlvUtil::filterNames(rlvChat.mText); + RlvUtil::filterNames(chat.mText); } - rlvChat.mRlvNamesFiltered = TRUE; + chat.mRlvNamesFiltered = TRUE; } } // [/RLVa:KB] @@ -271,19 +277,21 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) LLColor4 color = get_text_color(chat); - if (!log_to_file) color = LLColor4::grey; //Recap from log file. + if (!log_to_file) color = gSavedSettings.getColor("LogChatColor"); //Recap from log file. if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) { - LLFloaterScriptDebug::addScriptLine(chat.mText, - chat.mFromName, - color, - chat.mFromID); + LLFloaterScriptDebug::addScriptLine(chat, color); if (!gSavedSettings.getBOOL("ScriptErrorsAsChat")) { return; } } + else if (chat.mChatType == CHAT_TYPE_OWNER && gSavedSettings.getBOOL("SinguOwnerSayAsErrors")) + { + LLFloaterScriptDebug::addScriptLine(chat, color); + return; + } // could flash the chat button in the status bar here. JC LLFloaterChat* chat_floater = LLFloaterChat::getInstance(LLSD()); @@ -292,10 +300,7 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) history_editor->setParseHTML(TRUE); history_editor_with_mute->setParseHTML(TRUE); - - history_editor->setParseHighlights(TRUE); - history_editor_with_mute->setParseHighlights(TRUE); - + if (!chat.mMuted) { add_timestamped_line(history_editor, chat, color); @@ -312,7 +317,7 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) // add objects as transient speakers that can be muted if (chat.mSourceType == CHAT_SOURCE_OBJECT) { - LLLocalSpeakerMgr::getInstance()->setSpeaker(chat.mFromID, chat.mFromName, LLSpeaker::STATUS_NOT_IN_CHANNEL, LLSpeaker::SPEAKER_OBJECT); + LLLocalSpeakerMgr::getInstance()->setSpeaker({ chat.mFromID, LLSpeaker::SPEAKER_OBJECT, LLSpeaker::STATUS_NOT_IN_CHANNEL, boost::none, boost::none, chat.mFromName }); } // start tab flashing on incoming text from other users (ignoring system text, etc) @@ -339,13 +344,18 @@ void LLFloaterChat::setHistoryCursorAndScrollToEnd() //static void LLFloaterChat::onClickToggleShowMute(bool show_mute, LLTextEditor* history_editor, LLTextEditor* history_editor_with_mute) { - history_editor->setVisible(!show_mute); - history_editor_with_mute->setVisible(show_mute); (show_mute ? history_editor_with_mute : history_editor)->setCursorAndScrollToEnd(); } +void LLFloaterChat::addChat(const std::string& str, BOOL from_im, BOOL local_agent) +{ + LLChat chat(str); + chat.mSourceType = CHAT_SOURCE_SYSTEM; + addChat(chat, from_im, local_agent); +} + // Put a line of chat in all the right places -void LLFloaterChat::addChat(const LLChat& chat, +void LLFloaterChat::addChat(LLChat& chat, BOOL from_instant_message, BOOL local_agent) { @@ -361,20 +371,18 @@ void LLFloaterChat::addChat(const LLChat& chat, // TODO-RLVa: we might cast too broad a net by filtering here, needs testing if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) && (!chat.mRlvLocFiltered) && (CHAT_SOURCE_AGENT != chat.mSourceType) ) { - LLChat& rlvChat = const_cast(chat); if (!from_instant_message) - RlvUtil::filterLocation(rlvChat.mText); - rlvChat.mRlvLocFiltered = TRUE; + RlvUtil::filterLocation(chat.mText); + chat.mRlvLocFiltered = TRUE; } if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!chat.mRlvNamesFiltered) ) { - LLChat& rlvChat = const_cast(chat); if ( (!from_instant_message) && (CHAT_SOURCE_AGENT != chat.mSourceType) ) { // Filter object and system chat (names are filtered elsewhere to save ourselves an gObjectList lookup) - RlvUtil::filterNames(rlvChat.mText); + RlvUtil::filterNames(chat.mText); } - rlvChat.mRlvNamesFiltered = TRUE; + chat.mRlvNamesFiltered = TRUE; } } // [/RLVa:KB] @@ -387,7 +395,19 @@ void LLFloaterChat::addChat(const LLChat& chat, // We display anything if it's not an IM. If it's an IM, check pref... if ( !from_instant_message || gSavedSettings.getBOOL("IMInChatConsole") ) { - gConsole->addConsoleLine(chat.mText, text_color); + // Replace registered urls in the console so it looks right. + std::string chit(chat.mText), // Read through this + chat; // Add parts to this + LLUrlMatch match; + while (!chit.empty() && LLUrlRegistry::instance().findUrl(chit, match)) + { + const auto start(match.getStart()), length(match.getEnd()+1-start); + if (start > 0) chat += chit.substr(0, start); // Add up to the start of the match + chat += match.getLabel() + match.getQuery(); // Add the label and the query + chit.erase(0, start+length); // remove the url match and all before it + } + if (!chit.empty()) chat += chit; // Add any leftovers + gConsole->addConsoleLine(chat, text_color); } } @@ -503,7 +523,7 @@ LLColor4 get_text_color(const LLChat& chat, bool from_im) } static const LLCachedControl sKeywordsChangeColor(gSavedPerAccountSettings, "KeywordsChangeColor", false); - if (sKeywordsChangeColor && gAgentID != chat.mFromID && chat.mSourceType != CHAT_SOURCE_SYSTEM && AscentKeyword::hasKeyword(boost::starts_with(chat.mText, chat.mFromName) ? chat.mText.substr(chat.mFromName.length()) : chat.mText, 1)) + if (sKeywordsChangeColor && gAgentID != chat.mFromID && AscentKeyword::hasKeyword((chat.mSourceType != CHAT_SOURCE_SYSTEM && boost::starts_with(chat.mText, chat.mFromName)) ? chat.mText.substr(chat.mFromName.length()) : chat.mText, 1)) { static const LLCachedControl sKeywordsColor(gSavedPerAccountSettings, "KeywordsColor", LLColor4(1.f, 1.f, 1.f, 1.f)); text_color = sKeywordsColor; @@ -515,28 +535,19 @@ LLColor4 get_text_color(const LLChat& chat, bool from_im) //static void LLFloaterChat::loadHistory() { - LLLogChat::loadHistory("chat", &chatFromLogFile, (void*)LLFloaterChat::getInstance()); + LLLogChat::loadHistory("chat", LLUUID::null, boost::bind(&LLFloaterChat::chatFromLogFile, getInstance(), _1, _2)); } -//static -void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata) + +void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type, const std::string& line) { - switch (type) + bool log_line = type == LLLogChat::LOG_LINE; + if (log_line || gSavedPerAccountSettings.getBOOL("LogChat")) { - case LLLogChat::LOG_EMPTY: - if (gSavedPerAccountSettings.getBOOL("LogChat")) - addChatHistory(static_cast(userdata)->getString("IM_logging_string"), false); - break; - case LLLogChat::LOG_END: - if (gSavedPerAccountSettings.getBOOL("LogChat")) - addChatHistory(static_cast(userdata)->getString("IM_end_log_string"), false); - break; - case LLLogChat::LOG_LINE: - addChatHistory(line, FALSE); - break; - default: - // nothing - break; + LLStyleSP style(new LLStyle(true, gSavedSettings.getColor4("LogChatColor"), LLStringUtil::null)); + const auto text = log_line ? line : getString(type == LLLogChat::LOG_END ? "IM_end_log_string" : "IM_logging_string"); + for (const auto& ed_name : { "Chat History Editor", "Chat History Editor with mute" }) + getChild(ed_name)->appendText(text, false, true, style, false); } } diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h index e1c55e779e..7a9a7948ee 100644 --- a/indra/newview/llfloaterchat.h +++ b/indra/newview/llfloaterchat.h @@ -60,18 +60,20 @@ class LLFloaterChat void updateConsoleVisibility(); static void setHistoryCursorAndScrollToEnd(); - + // Add chat to console and history list. // Color based on source, type, distance. - static void addChat(const LLChat& chat, BOOL from_im = FALSE, BOOL local_agent = FALSE); + static void addChat(const std::string& str, BOOL from_im = FALSE, BOOL local_agent = FALSE); + static void addChat(LLChat& chat, BOOL from_im = FALSE, BOOL local_agent = FALSE); // Add chat to history alone. - static void addChatHistory(const LLChat& chat, bool log_to_file = true); + static void addChatHistory(const std::string& str, bool log_to_file = true); + static void addChatHistory(LLChat& chat, bool log_to_file = true); static void triggerAlerts(const std::string& text); void onClickToggleShowMute(bool show_mute, class LLTextEditor* history_editor, LLTextEditor* history_editor_with_mute); - static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata); + void chatFromLogFile(LLLogChat::ELogLineType type, const std::string& line); static void loadHistory(); static void* createSpeakersPanel(void* data); static void* createChatPanel(void* data); diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index fb2ab184cc..487cccc49e 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -78,6 +78,15 @@ const F32 CONTEXT_FADE_TIME = 0.08f; LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate ) : LLFloater (std::string("Color Picker Floater")), + origR(1.f), + origG(1.f), + origB(1.f), + curR(1.f), + curG(1.f), + curB(1.f), + curH(0.f), + curS(0.f), + curL(1.f), mComponents ( 3 ), mMouseDownInLumRegion ( FALSE ), mMouseDownInHueRegion ( FALSE ), @@ -108,7 +117,11 @@ LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show mPaletteRegionHeight ( 40 ), mSwatch ( swatch ), mActive ( TRUE ), + mApplyImmediateCheck(nullptr), mCanApplyImmediately ( show_apply_immediate ), + mSelectBtn(nullptr), + mCancelBtn(nullptr), + mPipetteBtn(nullptr), mContextConeOpacity ( 0.f ) { // build the majority of the gui using the factory builder @@ -490,47 +503,40 @@ void LLFloaterColorPicker::draw() if (hasFocus() && mSwatch->isInVisibleChain() && mContextConeOpacity > 0.001f) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLEnable(GL_CULL_FACE); - gGL.begin(LLRender::QUADS); + LLGLEnable cull; + gGL.begin(LLRender::TRIANGLE_STRIP); { - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); - gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop); - gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop); gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); - gGL.vertex2i(local_rect.mRight, local_rect.mTop); gGL.vertex2i(local_rect.mLeft, local_rect.mTop); - - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); - gGL.vertex2i(local_rect.mLeft, local_rect.mTop); - gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); - gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom); gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); - gGL.vertex2i(local_rect.mRight, local_rect.mBottom); gGL.vertex2i(local_rect.mRight, local_rect.mTop); gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop); - gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); - gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); gGL.vertex2i(local_rect.mRight, local_rect.mBottom); gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop); } gGL.end(); } if (gFocusMgr.childHasMouseCapture(getDragHandle())) { - mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME)); } else { - mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME)); } mPipetteBtn->setToggleState(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index c03c8f1a5f..63aa904ddc 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -56,7 +56,6 @@ #include "statemachine/aifilepicker.h" #include "hippogridmanager.h" #include "aixmllindengenepool.h" -#include "aifile.h" using namespace LLAvatarAppearanceDefines; @@ -119,9 +118,9 @@ LLFloaterCustomize::LLFloaterCustomize() gInventory.addObserver(mInventoryObserver); LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); - outfit_observer.addBOFReplacedCallback(boost::bind(&LLFloaterCustomize::refreshCurrentOutfitName, this, "")); - outfit_observer.addBOFChangedCallback(boost::bind(&LLFloaterCustomize::refreshCurrentOutfitName, this, "")); - outfit_observer.addCOFChangedCallback(boost::bind(&LLFloaterCustomize::refreshCurrentOutfitName, this, "")); + outfit_observer.addBOFReplacedCallback(boost::bind(&LLFloaterCustomize::refreshCurrentOutfitName, this, LLStringUtil::null)); + outfit_observer.addBOFChangedCallback(boost::bind(&LLFloaterCustomize::refreshCurrentOutfitName, this, LLStringUtil::null)); + outfit_observer.addCOFChangedCallback(boost::bind(&LLFloaterCustomize::refreshCurrentOutfitName, this, LLStringUtil::null)); LLCallbackMap::map_t factory_map; const std::string &invalid_name = LLWearableType::getTypeName(LLWearableType::WT_INVALID); @@ -238,7 +237,11 @@ void LLFloaterCustomize::editWearable(LLViewerWearable* wearable, bool disable_c { if(!wearable) return; - LLFloaterCustomize::getInstance()->setCurrentWearableType(wearable->getType(), disable_camera_switch); + auto& inst = LLFloaterCustomize::instance(); + inst.setCurrentWearableType(wearable->getType(), disable_camera_switch); + U32 index(0); + gAgentWearables.getWearableIndex(wearable, index); + static_cast(inst.mTabContainer->getCurrentPanel())->setWearableIndex(index); } //static @@ -511,9 +514,7 @@ void LLFloaterCustomize::onBtnExport_continued(LLViewerWearable* edit_wearable, bool success = false; try { - AIFile outfile(filename, "wb"); - - AIXMLLindenGenepool linden_genepool(outfile); + AIXMLLindenGenepool linden_genepool(filename); linden_genepool.child(edit_wearable->getArchetype()); success = true; @@ -673,7 +674,8 @@ const S32 HEADER_HEIGHT = 3 * (LINE_HEIGHT + LLFLOATER_VPAD) + (2 * LLPANEL_BORD void LLFloaterCustomize::wearablesChanged(LLWearableType::EType type) { llassert( type < LLWearableType::WT_COUNT ); - gSavedSettings.setU32("AvatarSex", (gAgentAvatarp->getSex() == SEX_MALE) ); + if (type == LLWearableType::WT_SHAPE) + gSavedSettings.setU32("AvatarSex", (gAgentAvatarp->getSex() == SEX_MALE)); LLPanelEditWearable* panel = mWearablePanelList[ type ]; if( panel ) diff --git a/indra/newview/llfloaterdirectory.cpp b/indra/newview/llfloaterdirectory.cpp index 25ee21f7d1..a856e4d5f1 100644 --- a/indra/newview/llfloaterdirectory.cpp +++ b/indra/newview/llfloaterdirectory.cpp @@ -204,7 +204,6 @@ LLFloaterDirectory::LLFloaterDirectory(const std::string& name) { sInstance = this; - mFindAllPanel = NULL; mClassifiedPanel = NULL; mEventsPanel = NULL; mLandPanel = NULL; @@ -248,7 +247,7 @@ LLFloaterDirectory::LLFloaterDirectory(const std::string& name) factory_map["Panel Avatar"] = LLCallbackMap(createPanelAvatar, this); - mCommitCallbackRegistrar.add("Search.WebFloater", boost::bind(&LLFloaterSearch::open, boost::bind(LLFloaterSearch::getInstance))); + mCommitCallbackRegistrar.add("Search.WebFloater", boost::bind(&LLFloaterSearch::open, boost::bind(&LLFloaterSearch::getInstance))); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_directory.xml", &factory_map); moveResizeHandlesToFront(); @@ -260,7 +259,12 @@ LLFloaterDirectory::LLFloaterDirectory(const std::string& name) LLTabContainer* container = getChild("Directory Tabs"); if (secondlife) { - container->removeTabPanel(getChild("find_all_old_panel")); // Not used + // Remove unused tabs + container->removeTabPanel(getChild("find_all_old_panel")); + LLPanel* p = getChild("find_all_panel"); + container->removeTabPanel(p); // This should be at the end + p->setLabel(p->getString("classic_label")); // Give it a special label + container->addTabPanel(p, p->getLabel()); } else { @@ -305,9 +309,7 @@ LLFloaterDirectory::~LLFloaterDirectory() // static void *LLFloaterDirectory::createFindAll(void* userdata) { - LLFloaterDirectory *self = (LLFloaterDirectory*)userdata; - self->mFindAllPanel = LLPanelDirFindAllInterface::create(self); - return self->mFindAllPanel; + return LLPanelDirFindAllInterface::create(static_cast(userdata)); } // static @@ -452,24 +454,43 @@ void LLFloaterDirectory::requestClassifieds() } } -void LLFloaterDirectory::searchInAll(const std::string& search_text) +void LLFloaterDirectory::search(const LLFloaterSearch::SearchQuery& search) { start(); - LLPanelDirFindAllInterface::search(sInstance->mFindAllPanel, search_text); - performQueryOn2("classified_panel", search_text); - performQueryOn2("events_panel", search_text); - performQueryOn2("groups_panel", search_text); - performQueryOn2("people_panel", search_text); - performQueryOn2("places_panel", search_text); -} - -void LLFloaterDirectory::showFindAll(const std::string& search_text) -{ - showPanel(LFSimFeatureHandler::instance().searchURL().empty() ? "find_all_old_panel" : "find_all_panel"); - LLPanelDirFindAllInterface::search(sInstance->mFindAllPanel, search_text); + const std::string category(search.category()); + const std::string search_text(search.query); + if (category.empty()) + { + LLPanelDirFindAllInterface::search(sInstance, search); + performQueryOn2("classified_panel", search_text); + performQueryOn2("events_panel", search_text); + performQueryOn2("groups_panel", search_text); + performQueryOn2("people_panel", search_text); + performQueryOn2("places_panel", search_text); + } + else if (category == "all") + LLPanelDirFindAllInterface::search(sInstance, search, true); + else if (category == "people") + showPeople(search.query); + else if (category == "places") + showPlaces(search.query); + else if (category == "events") + showEvents(search.query); + else if (category == "groups") + showGroups(search.query); + /* Singu TODO: Wiki tab in secondlife legacy search floater? + else if (category == "wiki") + LLFloaterDirectory::showWiki(search.query);*/ + else if (category == "destinations") + showDestinations(); + else if (category == "classifieds") + showClassified(search.query); + else if (gHippoGridManager->getConnectedGrid()->isSecondLife()) + LLPanelDirFindAllInterface::search(sInstance, search, true); + else + LLNotificationsUtil::add("UnsupportedCommandSLURL"); // Singu Note: Perhaps we should use a special notification here? } - void LLFloaterDirectory::showClassified(const LLUUID& classified_id) { showPanel("classified_panel"); @@ -598,7 +619,7 @@ void LLFloaterDirectory::start() void LLFloaterDirectory::showPanel(const std::string& tabname) { start(); - sInstance->childShowTab("Directory Tabs", tabname); + sInstance->findChild("Directory Tabs")->selectTabByName(tabname); sInstance->focusCurrentPanel(); } @@ -616,7 +637,7 @@ void LLFloaterDirectory::toggleFind(void*) || (inst.destinationGuideURL().empty() && panel == "showcase_panel")) panel = "find_all_old_panel"; } - else if (panel == "find_all_old_panel") panel = "find_all_panel"; + else if (panel == "find_all_old_panel") panel = "web_panel"; showPanel(panel); diff --git a/indra/newview/llfloaterdirectory.h b/indra/newview/llfloaterdirectory.h index c36ce412bf..792c578d38 100644 --- a/indra/newview/llfloaterdirectory.h +++ b/indra/newview/llfloaterdirectory.h @@ -33,7 +33,7 @@ #ifndef LL_LLFLOATERDIRECTORY_H #define LL_LLFLOATERDIRECTORY_H -#include "llfloater.h" +#include "llfloatersearch.h" #include "lltabcontainer.h" class LLDirectoryCore; @@ -71,8 +71,7 @@ class LLFloaterDirectory : public LLFloater // Outside UI widgets can spawn this floater with various tabs // selected. - static void searchInAll(const std::string& search_text); - static void showFindAll(const std::string& search_text); + static void search(const LLFloaterSearch::SearchQuery& search); static void showClassified(const LLUUID& classified_id); static void showClassified(const std::string& search_text = ""); static void showEvents(S32 event_id); @@ -102,7 +101,6 @@ class LLFloaterDirectory : public LLFloater private: // Some special "showByID" functions use these cached pointers. // They could be replaced by getPanelByName(), perhaps. JC - LLPanelDirFindAll* mFindAllPanel; LLPanelDirClassified* mClassifiedPanel; LLPanelDirEvents* mEventsPanel; LLPanelDirLand* mLandPanel; @@ -144,6 +142,4 @@ class LLFloaterDirectory : public LLFloater static LLFloaterDirectory *sInstance; }; -extern BOOL gDisplayEventHack; - #endif // LL_LLDIRECTORYFLOATER_H diff --git a/indra/newview/llfloaterevent.cpp b/indra/newview/llfloaterevent.cpp index b526767f8f..ec863020c3 100644 --- a/indra/newview/llfloaterevent.cpp +++ b/indra/newview/llfloaterevent.cpp @@ -36,7 +36,6 @@ #include "llfloaterevent.h" // viewer project includes -#include "llcommandhandler.h" #include "llpanelevent.h" // linden library includes @@ -52,29 +51,6 @@ LLMap< U32, LLFloaterEventInfo* > gEventInfoInstances; -class LLEventHandler : public LLCommandHandler -{ -public: - // requires trusted browser to trigger - LLEventHandler() : LLCommandHandler("event", UNTRUSTED_THROTTLE) { } - bool handle(const LLSD& tokens, const LLSD& query_map, - LLMediaCtrl* web) - { - if (tokens.size() < 2) - { - return false; - } - U32 event_id = tokens[0].asInteger(); - if (tokens[1].asString() == "about") - { - LLFloaterEventInfo::show(event_id); - return true; - } - return false; - } -}; -LLEventHandler gEventHandler; - LLFloaterEventInfo::LLFloaterEventInfo(const std::string& name, const U32 event_id) : LLFloater(name), mEventID( event_id ) diff --git a/indra/newview/llfloaterexperiencepicker.cpp b/indra/newview/llfloaterexperiencepicker.cpp new file mode 100644 index 0000000000..7613001b33 --- /dev/null +++ b/indra/newview/llfloaterexperiencepicker.cpp @@ -0,0 +1,167 @@ +/** +* @file llfloaterexperiencepicker.cpp +* @brief Implementation of llfloaterexperiencepicker +* @author dolphin@lindenlab.com +* +* $LicenseInfo:firstyear=2014&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2014, 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 "llviewerprecompiledheaders.h" + +#include "llfloaterexperiencepicker.h" + + +#include "lllineeditor.h" +//#include "llfloaterreg.h" +#include "lluictrlfactory.h" +#include "llscrolllistctrl.h" +#include "llviewerregion.h" +#include "llagent.h" +#include "llexperiencecache.h" +#include "llslurl.h" +#include "llavatarnamecache.h" +#include "llfloaterexperienceprofile.h" +#include "llcombobox.h" +#include "llviewercontrol.h" +#include "lldraghandle.h" +#include "llpanelexperiencepicker.h" + +// +LLFloaterExperiencePicker* show_xp_picker(const LLSD& key) +{ + LLFloaterExperiencePicker* floater = + LLFloaterExperiencePicker::getInstance(key); + if (!floater) + { + floater = new LLFloaterExperiencePicker(key); + } + floater->open(); + return floater; +} +// + +LLFloaterExperiencePicker* LLFloaterExperiencePicker::show( select_callback_t callback, const LLUUID& key, BOOL allow_multiple, BOOL close_on_select, filter_list filters, LLView * frustumOrigin ) +{ + LLFloaterExperiencePicker* floater = show_xp_picker(key); + + if (floater->mSearchPanel) + { + floater->mSearchPanel->mSelectionCallback = callback; + floater->mSearchPanel->mCloseOnSelect = close_on_select; + floater->mSearchPanel->setAllowMultiple(allow_multiple); + floater->mSearchPanel->setDefaultFilters(); + floater->mSearchPanel->addFilters(filters.begin(), filters.end()); + floater->mSearchPanel->filterContent(); + } + + if(frustumOrigin) + { + floater->mFrustumOrigin = frustumOrigin->getHandle(); + } + + return floater; +} + +void LLFloaterExperiencePicker::drawFrustum() +{ + if(mFrustumOrigin.get()) + { + LLView * frustumOrigin = mFrustumOrigin.get(); + LLRect origin_rect; + frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, this); + // draw context cone connecting color picker with color swatch in parent floater + LLRect local_rect = getLocalRect(); + if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLEnable cull_face; + gGL.begin(LLRender::TRIANGLE_STRIP); + { + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); + gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); + gGL.vertex2i(local_rect.mRight, local_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); + gGL.vertex2i(origin_rect.mRight, origin_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); + gGL.vertex2i(local_rect.mRight, local_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); + gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); + gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); + gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop); + } + gGL.end(); + } + + if (gFocusMgr.childHasMouseCapture(getDragHandle())) + { + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime)); + } + else + { + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime)); + } + } +} + +void LLFloaterExperiencePicker::draw() +{ + drawFrustum(); + LLFloater::draw(); +} + +LLFloaterExperiencePicker::LLFloaterExperiencePicker( const LLSD& key ) + :LLFloater() + ,LLInstanceTracker(key.asUUID()) + ,mSearchPanel(nullptr) + ,mContextConeOpacity(0.f) + ,mContextConeInAlpha(0.f) + ,mContextConeOutAlpha(0.f) + ,mContextConeFadeTime(0.f) +{ + mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha"); + mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha"); + mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime"); + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_experience_search.xml", NULL, false); + //buildFromFile("floater_experience_search.xml"); +} + +LLFloaterExperiencePicker::~LLFloaterExperiencePicker() +{ + gFocusMgr.releaseFocusIfNeeded( this ); +} + +BOOL LLFloaterExperiencePicker::postBuild() +{ + mSearchPanel = new LLPanelExperiencePicker(); + addChild(mSearchPanel); + mSearchPanel->setOrigin(0, 0); + return LLFloater::postBuild(); +} diff --git a/indra/newview/llfloaterexperiencepicker.h b/indra/newview/llfloaterexperiencepicker.h new file mode 100644 index 0000000000..4aff63169b --- /dev/null +++ b/indra/newview/llfloaterexperiencepicker.h @@ -0,0 +1,69 @@ +/** +* @file llfloaterexperiencepicker.h +* @brief Header file for llfloaterexperiencepicker +* @author dolphin@lindenlab.com +* +* $LicenseInfo:firstyear=2014&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2014, 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_LLFLOATEREXPERIENCEPICKER_H +#define LL_LLFLOATEREXPERIENCEPICKER_H + +#include "llfloater.h" +#include "llinstancetracker.h" + +class LLScrollListCtrl; +class LLLineEditor; +class LLPanelExperiencePicker; + + +class LLFloaterExperiencePicker : public LLFloater +, public LLInstanceTracker +{ +public: + + typedef std::function select_callback_t; + // filter function for experiences, return true if the experience should be hidden. + typedef std::function filter_function; + typedef std::vector filter_list; + + static LLFloaterExperiencePicker* show( select_callback_t callback, const LLUUID& key, BOOL allow_multiple, BOOL close_on_select, filter_list filters, LLView * frustumOrigin); + + LLFloaterExperiencePicker(const LLSD& key); + virtual ~LLFloaterExperiencePicker(); + + BOOL postBuild() override; + + void draw() override; +private: + + LLPanelExperiencePicker* mSearchPanel; + + void drawFrustum(); + LLHandle mFrustumOrigin; + F32 mContextConeOpacity; + F32 mContextConeInAlpha; + F32 mContextConeOutAlpha; + F32 mContextConeFadeTime; +}; + +#endif // LL_LLFLOATEREXPERIENCEPICKER_H + diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp new file mode 100644 index 0000000000..3195a3bda9 --- /dev/null +++ b/indra/newview/llfloaterexperienceprofile.cpp @@ -0,0 +1,934 @@ +/** + * @file llfloaterexperienceprofile.cpp + * @brief llfloaterexperienceprofile and related class definitions + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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 "llviewerprecompiledheaders.h" +#include "llfloaterexperienceprofile.h" + +#include "llagent.h" +#include "llappviewer.h" +#include "llavatarnamecache.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llcommandhandler.h" +//#include "llexpandabletextbox.h" +#include "llexperiencecache.h" +//#include "llfloaterreg.h" +#include "llgroupactions.h" +#include "lluictrlfactory.h" +#include "lllayoutstack.h" +#include "lllineeditor.h" +#include "llnotificationsutil.h" +#include "llsdserialize.h" +#include "llslurl.h" +#include "lltabcontainer.h" +#include "lltextbox.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltrans.h" +#include "llviewerregion.h" +#include "llevents.h" +#include "llfloatergroups.h" +#include "llnotifications.h" +#include "llfloaterreporter.h" +#include "llurlaction.h" + +#define XML_PANEL_EXPERIENCE_PROFILE "floater_experienceprofile.xml" +#define TF_NAME "experience_title" +#define TF_DESC "experience_description" +#define TF_SLURL "LocationTextText" +#define TF_MRKT "marketplace" +#define TF_MATURITY "ContentRatingText" +#define TF_OWNER "OwnerText" +#define TF_GROUP "GroupText" +#define TF_GRID_WIDE "grid_wide" +#define TF_PRIVILEGED "privileged" +#define EDIT "edit_" + +#define IMG_LOGO "logo" + +#define PNL_TOP "top panel" +#define PNL_IMAGE "image_panel" +#define PNL_DESC "description panel" +#define PNL_LOC "location panel" +#define PNL_MRKT "marketplace panel" +#define PNL_GROUP "group_panel" +#define PNL_PERMS "perm panel" + +#define BTN_ALLOW "allow_btn" +#define BTN_BLOCK "block_btn" +#define BTN_CANCEL "cancel_btn" +#define BTN_CLEAR_LOCATION "clear_btn" +#define BTN_EDIT "edit_btn" +#define BTN_ENABLE "enable_btn" +#define BTN_FORGET "forget_btn" +#define BTN_PRIVATE "private_btn" +#define BTN_REPORT "report_btn" +#define BTN_SAVE "save_btn" +#define BTN_SET_GROUP "Group_btn" +#define BTN_SET_LOCATION "location_btn" + + +class LLExperienceHandler : public LLCommandHandler +{ +public: + LLExperienceHandler() : LLCommandHandler("experience", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, const LLSD& query_map, + LLMediaCtrl* web) override + { + if (params.size() != 2 || params[1].asString() != "profile") + return false; + + LLExperienceCache::instance().get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); + return true; + } + + void experienceCallback(const LLSD& experienceDetails) + { + if (!experienceDetails.has(LLExperienceCache::MISSING)) + { + LLFloaterExperienceProfile::showInstance(experienceDetails[LLExperienceCache::EXPERIENCE_ID].asUUID()); + } + } +}; + +LLExperienceHandler gExperienceHandler; + +void LLFloaterExperienceProfile::showInstance(const LLSD& data) +{ + bool is_map = data.has("experience_id"); + LLFloaterExperienceProfile* floater = getInstance(is_map ? data["experience_id"].asUUID() : data.asUUID()); + if (!floater) floater = new LLFloaterExperienceProfile(data); + else if (is_map && data.has("edit_experience") && data["edit_experience"].asBoolean()) + floater->changeToEdit(); + floater->open(); +} + +LLFloaterExperienceProfile::LLFloaterExperienceProfile(const LLSD& data) + : LLFloater(), LLInstanceTracker(data.asUUID()) + , mSaveCompleteAction(NOTHING) + , mDirty(false) + , mForceClose(false) +{ + if (data.has("experience_id")) +{ + mExperienceId = data["experience_id"].asUUID(); + mPostEdit = data.has("edit_experience") && data["edit_experience"].asBoolean(); +} + else +{ + mExperienceId = data.asUUID(); + mPostEdit = false; + } + LLUICtrlFactory::getInstance()->buildFloater(this, XML_PANEL_EXPERIENCE_PROFILE, NULL, false); + //buildFromFile(XML_PANEL_EXPERIENCE_PROFILE); +} + + +LLFloaterExperienceProfile::~LLFloaterExperienceProfile() +{ + +} + +BOOL LLFloaterExperienceProfile::postBuild() +{ + + if (mExperienceId.notNull()) + { + LLExperienceCache::instance().fetch(mExperienceId, true); + LLExperienceCache::instance().get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, + getDerivedHandle(), _1)); + + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + LLExperienceCache::instance().getExperienceAdmin(mExperienceId, boost::bind( + &LLFloaterExperienceProfile::experienceIsAdmin, getDerivedHandle(), _1)); + } + } + + childSetAction(BTN_EDIT, boost::bind(&LLFloaterExperienceProfile::onClickEdit, this)); + childSetAction(BTN_ALLOW, boost::bind(&LLFloaterExperienceProfile::onClickPermission, this, "Allow")); + childSetAction(BTN_FORGET, boost::bind(&LLFloaterExperienceProfile::onClickForget, this)); + childSetAction(BTN_BLOCK, boost::bind(&LLFloaterExperienceProfile::onClickPermission, this, "Block")); + childSetAction(BTN_CANCEL, boost::bind(&LLFloaterExperienceProfile::onClickCancel, this)); + childSetAction(BTN_SAVE, boost::bind(&LLFloaterExperienceProfile::onClickSave, this)); + childSetAction(BTN_SET_LOCATION, boost::bind(&LLFloaterExperienceProfile::onClickLocation, this)); + childSetAction(BTN_CLEAR_LOCATION, boost::bind(&LLFloaterExperienceProfile::onClickClear, this)); + childSetAction(BTN_SET_GROUP, boost::bind(&LLFloaterExperienceProfile::onPickGroup, this)); + childSetAction(BTN_REPORT, boost::bind(&LLFloaterExperienceProfile::onReportExperience, this)); + + getChild(EDIT TF_DESC)->setKeystrokeCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + getChild(EDIT TF_MATURITY)->setCommitCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + getChild(EDIT TF_MRKT)->setKeystrokeCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + getChild(EDIT TF_NAME)->setKeystrokeCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + + childSetCommitCallback(EDIT BTN_ENABLE, boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this), nullptr); + childSetCommitCallback(EDIT BTN_PRIVATE, boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this), nullptr); + + childSetCommitCallback(EDIT IMG_LOGO, boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this), nullptr); + + if (auto logo = findChild(IMG_LOGO)) + { + void show_picture(const LLUUID& id, const std::string& name); + LLTextBox* name = getChild(TF_NAME); + std::function cb = [logo, name]() { show_picture(logo->getImageAssetID(), "Experience Picture: " + name->getText()); }; + logo->setMouseUpCallback(boost::bind(cb)); + } + + getChild(EDIT TF_DESC)->setCommitOnFocusLost(TRUE); + + LLEventPumps::instance().obtain("experience_permission").listen(mExperienceId.asString()+"-profile", + boost::bind(&LLFloaterExperienceProfile::experiencePermission, getDerivedHandle(this), _1)); + + if (mPostEdit && mExperienceId.notNull()) + { + mPostEdit = false; + changeToEdit(); + } + + return TRUE; +} + +void LLFloaterExperienceProfile::experienceCallback(LLHandle handle, const LLSD& experience ) +{ + LLFloaterExperienceProfile* pllpep = handle.get(); + if (pllpep) + { + pllpep->refreshExperience(experience); + } +} + + +bool LLFloaterExperienceProfile::experiencePermission( LLHandle handle, const LLSD& permission ) +{ + LLFloaterExperienceProfile* pllpep = handle.get(); + if (pllpep) + { + pllpep->updatePermission(permission); + } + return false; +} + + +void LLFloaterExperienceProfile::onClickEdit() +{ + changeToEdit(); +} + + +void LLFloaterExperienceProfile::onClickCancel() +{ + changeToView(); +} + +void LLFloaterExperienceProfile::onClickSave() +{ + doSave(NOTHING); +} + +void LLFloaterExperienceProfile::onClickPermission(const char* perm) +{ + LLViewerRegion* region = gAgent.getRegion(); + if (!region) + return; + LLExperienceCache::instance().setExperiencePermission(mExperienceId, perm, boost::bind( + &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1)); +} + + +void LLFloaterExperienceProfile::onClickForget() +{ + LLViewerRegion* region = gAgent.getRegion(); + if (!region) + return; + + LLExperienceCache::instance().forgetExperiencePermission(mExperienceId, boost::bind( + &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1)); +} + +bool LLFloaterExperienceProfile::setMaturityString( U8 maturity, LLTextBox* child, LLComboBox* combo ) +{ + //LLStyle::Params style; // Singu Note: Nope. + std::string access; + if (maturity <= SIM_ACCESS_PG) + { + //style.image(LLUI::getUIImage(getString("maturity_icon_general"))); // Singu Note: Nope. + access = LLTrans::getString("SIM_ACCESS_PG"); + combo->setCurrentByIndex(2); + } + else if (maturity <= SIM_ACCESS_MATURE) + { + //style.image(LLUI::getUIImage(getString("maturity_icon_moderate"))); // Singu Note: Nope. + access = LLTrans::getString("SIM_ACCESS_MATURE"); + combo->setCurrentByIndex(1); + } + else if (maturity <= SIM_ACCESS_ADULT) + { + //style.image(LLUI::getUIImage(getString("maturity_icon_adult"))); // Singu Note: Nope. + access = LLTrans::getString("SIM_ACCESS_ADULT"); + combo->setCurrentByIndex(0); + } + else + { + return false; + } + + /* Singu Note: Nope. + child->setText(LLStringUtil::null); + + child->appendImageSegment(style); + */ + child->setText(access); + + return true; +} + + +void LLFloaterExperienceProfile::refreshExperience( const LLSD& experience ) +{ + mExperienceDetails = experience; + mPackage = experience; + + + LLLayoutPanel* imagePanel = getChild(PNL_IMAGE); + LLLayoutPanel* descriptionPanel = getChild(PNL_DESC); + LLLayoutPanel* locationPanel = getChild(PNL_LOC); + LLLayoutPanel* marketplacePanel = getChild(PNL_MRKT); + LLLayoutPanel* topPanel = getChild(PNL_TOP); + + + imagePanel->setVisible(FALSE); + descriptionPanel->setVisible(FALSE); + locationPanel->setVisible(FALSE); + marketplacePanel->setVisible(FALSE); + topPanel->setVisible(FALSE); + + + LLTextBox* child = getChild(TF_NAME); + //child->setText(experience[LLExperienceCache::NAME].asString()); + child->setValue(experience[LLExperienceCache::EXPERIENCE_ID].asUUID()); + + LLLineEditor* linechild = getChild(EDIT TF_NAME); + linechild->setText(experience[LLExperienceCache::NAME].asString()); + + std::string value = experience[LLExperienceCache::DESCRIPTION].asString(); + LLTextEditor* exchild = getChild(TF_DESC); + exchild->setText(value); + descriptionPanel->setVisible(value.length()>0); + + LLTextEditor* edit_child = getChild(EDIT TF_DESC); + edit_child->setText(value); + + mLocationSLURL = experience[LLExperienceCache::SLURL].asString(); + edit_child = getChild(TF_SLURL); + bool has_slurl = !mLocationSLURL.empty() && mLocationSLURL != "last"; + locationPanel->setVisible(has_slurl); + if (has_slurl) mLocationSLURL = LLSLURL(mLocationSLURL).getSLURLString(); + edit_child->setText(mLocationSLURL); + + + edit_child = getChild(EDIT TF_SLURL); + if (has_slurl) + { + edit_child->setText(mLocationSLURL); + } + else + { + edit_child->setText(getString("empty_slurl")); + } + + setMaturityString((U8)(experience[LLExperienceCache::MATURITY].asInteger()), getChild(TF_MATURITY), getChild(EDIT TF_MATURITY)); + + LLUUID agent_id = experience[LLExperienceCache::AGENT_ID].asUUID(); + getChild(TF_OWNER)->setValue(agent_id); + + LLUUID id = experience[LLExperienceCache::GROUP_ID].asUUID(); + bool id_null = id.isNull(); + if (!id_null) + { + getChild(TF_GROUP)->setValue(id); + } + getChild(PNL_GROUP)->setVisible(!id_null); + + setEditGroup(id); + + getChild(BTN_SET_GROUP)->setEnabled(agent_id == gAgentID); + + LLCheckBoxCtrl* enable = getChild(EDIT BTN_ENABLE); + S32 properties = mExperienceDetails[LLExperienceCache::PROPERTIES].asInteger(); + enable->set(!(properties & LLExperienceCache::PROPERTY_DISABLED)); + + enable = getChild(EDIT BTN_PRIVATE); + enable->set(properties & LLExperienceCache::PROPERTY_PRIVATE); + + topPanel->setVisible(TRUE); + child=getChild(TF_GRID_WIDE); + child->setVisible(TRUE); + + if(properties & LLExperienceCache::PROPERTY_GRID) + { + child->setText(LLTrans::getString("Grid-Scope")); + } + else + { + child->setText(LLTrans::getString("Land-Scope")); + } + + if (getChild(BTN_EDIT)->getVisible()) + { + topPanel->setVisible(TRUE); + } + + if (properties & LLExperienceCache::PROPERTY_PRIVILEGED) + { + child = getChild(TF_PRIVILEGED); + child->setVisible(TRUE); + } + else + { + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + LLExperienceCache::instance().getExperiencePermission(mExperienceId, boost::bind( + &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1)); + } + } + + value=experience[LLExperienceCache::METADATA].asString(); + if (value.empty()) + return; + + LLPointer parser = new LLSDXMLParser(); + + LLSD data; + + std::istringstream is(value); + if (LLSDParser::PARSE_FAILURE != parser->parse(is, data, value.size())) + { + value.clear(); + if (data.has(TF_MRKT)) + { + value=data[TF_MRKT].asString(); + + edit_child = getChild(TF_MRKT); + edit_child->setText(value); + if(!value.empty()) + { + marketplacePanel->setVisible(TRUE); + } + else + { + marketplacePanel->setVisible(FALSE); + } + } + else + { + marketplacePanel->setVisible(FALSE); + } + + linechild = getChild(EDIT TF_MRKT); + linechild->setText(value); + + if (data.has(IMG_LOGO)) + { + LLTextureCtrl* logo = getChild(IMG_LOGO); + + LLUUID id = data[IMG_LOGO].asUUID(); + logo->setImageAssetID(id); + imagePanel->setVisible(TRUE); + + logo = getChild(EDIT IMG_LOGO); + logo->setImageAssetID(data[IMG_LOGO].asUUID()); + + imagePanel->setVisible(id.notNull()); + } + } + else + { + marketplacePanel->setVisible(FALSE); + imagePanel->setVisible(FALSE); + } + + mDirty=false; + mForceClose = false; + getChild(BTN_SAVE)->setEnabled(mDirty); +} + +void LLFloaterExperienceProfile::setPreferences( const LLSD& content ) +{ + S32 properties = mExperienceDetails[LLExperienceCache::PROPERTIES].asInteger(); + if (properties & LLExperienceCache::PROPERTY_PRIVILEGED) + { + return; + } + + const LLSD& experiences = content["experiences"]; + const LLSD& blocked = content["blocked"]; + + + for(const auto& exp : experiences.array()) + { + if (exp.asUUID()==mExperienceId) + { + experienceAllowed(); + return; + } + } + + for(const auto& exp : blocked.array()) + { + if (exp.asUUID()==mExperienceId) + { + experienceBlocked(); + return; + } + } + + experienceForgotten(); +} + +void LLFloaterExperienceProfile::onFieldChanged() +{ + updatePackage(); + + if (!getChild(BTN_EDIT)->getVisible()) + { + return; + } + + mDirty = mPackage.size() != mExperienceDetails.size(); + if (!mDirty) + { + LLSD::map_const_iterator st = mExperienceDetails.beginMap(); + LLSD::map_const_iterator dt = mPackage.beginMap(); + LLSD::map_const_iterator ste = mExperienceDetails.endMap(); + LLSD::map_const_iterator dte = mPackage.endMap(); + for (; st != ste && dt != dte; ++st, ++dt) + if (mDirty = st->first != dt->first || st->second.asString() != dt->second.asString()) + break; + } + + getChild(BTN_SAVE)->setEnabled(mDirty); +} + + +BOOL LLFloaterExperienceProfile::canClose() +{ + if (mForceClose || !mDirty) + { + return TRUE; + } + else + { + // Bring up view-modal dialog: Save changes? Yes, No, Cancel + LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLFloaterExperienceProfile::handleSaveChangesDialog, this, _1, _2, CLOSE)); + return FALSE; + } +} + +bool LLFloaterExperienceProfile::handleSaveChangesDialog( const LLSD& notification, const LLSD& response, PostSaveAction action ) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch( option ) + { + case 0: // "Yes" + // close after saving + doSave( action ); + break; + + case 1: // "No" + if (action != NOTHING) + { + mForceClose = TRUE; + if (action==CLOSE) + { + close(); + } + else + { + changeToView(); + } + } + break; + + case 2: // "Cancel" + default: + // If we were quitting, we didn't really mean it. + LLAppViewer::instance()->abortQuit(); + break; + } + return false; +} + +void LLFloaterExperienceProfile::doSave( int success_action ) +{ + mSaveCompleteAction=success_action; + + LLViewerRegion* region = gAgent.getRegion(); + if (!region) + return; + + LLExperienceCache::instance().updateExperience(mPackage, boost::bind( + &LLFloaterExperienceProfile::experienceUpdateResult, + getDerivedHandle(), _1)); +} + +void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content ) +{ + LLUUID id = getExperienceId(); + + if (content.has("removed")) + { + const LLSD& removed = content["removed"]; + for(const auto& it : removed.map()) + { + const std::string& field = it.first; + if (field == LLExperienceCache::EXPERIENCE_ID) + { + //this message should be removed by the experience api + continue; + } + const LLSD& data = it.second; + std::string error_tag = data["error_tag"].asString()+ "ExperienceProfileMessage"; + LLSD fields; + if (LLNotificationTemplates::instance().templateExists(error_tag)) + { + fields["field"] = field; + fields["extra_info"] = data["extra_info"]; + LLNotificationsUtil::add(error_tag, fields); + } + else + { + fields["MESSAGE"] = data["en"]; + LLNotificationsUtil::add("GenericAlert", fields); + } + } + } + + if (!content.has("experience_keys")) + { + LL_WARNS() << "LLFloaterExperienceProfile::onSaveComplete called with bad content" << LL_ENDL; + return; + } + + const LLSD& experiences = content["experience_keys"]; + + if (experiences.size() == 0) + { + LL_WARNS() << "LLFloaterExperienceProfile::onSaveComplete called with empty content" << LL_ENDL; + return; + } + + const auto& exp = experiences[0]; + if (!exp.has(LLExperienceCache::EXPERIENCE_ID) || (exp[LLExperienceCache::EXPERIENCE_ID].asUUID() != id)) + { + LL_WARNS() << "LLFloaterExperienceProfile::onSaveComplete called with unexpected experience id" << LL_ENDL; + return; + } + + refreshExperience(exp); + LLExperienceCache::instance().insert(exp); + LLExperienceCache::instance().fetch(id, true); + + if (mSaveCompleteAction == VIEW) + { + LLTabContainer* tabs = getChild("tab_container"); + tabs->selectTabByName("panel_experience_info"); + } + else if (mSaveCompleteAction == CLOSE) + { + close(); + } +} + +void LLFloaterExperienceProfile::changeToView() +{ + if (mForceClose || !mDirty) + { + refreshExperience(mExperienceDetails); + LLTabContainer* tabs = getChild("tab_container"); + + tabs->selectTabByName("panel_experience_info"); + } + else + { + // Bring up view-modal dialog: Save changes? Yes, No, Cancel + LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLFloaterExperienceProfile::handleSaveChangesDialog, this, _1, _2, VIEW)); + } +} + +void LLFloaterExperienceProfile::changeToEdit() +{ + LLTabContainer* tabs = getChild("tab_container"); + + tabs->selectTabByName("edit_panel_experience_info"); +} + +void LLFloaterExperienceProfile::onClickLocation() +{ + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + auto child = getChild(EDIT TF_SLURL); + mLocationSLURL = LLSLURL(region->getName(), gAgent.getPositionGlobal()).getSLURLString(); + child->setText(mLocationSLURL); + onFieldChanged(); + } +} + +void LLFloaterExperienceProfile::onClickClear() +{ + auto child = getChild(EDIT TF_SLURL); + mLocationSLURL.clear(); + child->setText(getString("empty_slurl")); + onFieldChanged(); +} + +void LLFloaterExperienceProfile::updatePermission(const LLSD& permission) +{ + if (permission.has("experience")) + { + if (permission["experience"].asUUID() != mExperienceId) + { + return; + } + + std::string str = permission[mExperienceId.asString()]["permission"].asString(); + if (str == "Allow") + { + experienceAllowed(); + } + else if (str == "Block") + { + experienceBlocked(); + } + else if (str == "Forget") + { + experienceForgotten(); + } + } + else + { + setPreferences(permission); + } +} + +void LLFloaterExperienceProfile::experienceAllowed() +{ + LLButton* button=getChild(BTN_ALLOW); + button->setEnabled(FALSE); + + button=getChild(BTN_FORGET); + button->setEnabled(TRUE); + + button=getChild(BTN_BLOCK); + button->setEnabled(TRUE); +} + +void LLFloaterExperienceProfile::experienceForgotten() +{ + LLButton* button=getChild(BTN_ALLOW); + button->setEnabled(TRUE); + + button=getChild(BTN_FORGET); + button->setEnabled(FALSE); + + button=getChild(BTN_BLOCK); + button->setEnabled(TRUE); +} + +void LLFloaterExperienceProfile::experienceBlocked() +{ + LLButton* button=getChild(BTN_ALLOW); + button->setEnabled(TRUE); + + button=getChild(BTN_FORGET); + button->setEnabled(TRUE); + + button=getChild(BTN_BLOCK); + button->setEnabled(FALSE); +} + +void LLFloaterExperienceProfile::onClose( bool app_quitting ) +{ + LLEventPumps::instance().obtain("experience_permission").stopListening(mExperienceId.asString()+"-profile"); + LLFloater::onClose(app_quitting); +} + +void LLFloaterExperienceProfile::updatePackage() +{ + mPackage[LLExperienceCache::NAME] = getChild(EDIT TF_NAME)->getText(); + mPackage[LLExperienceCache::DESCRIPTION] = getChild(EDIT TF_DESC)->getText(); + if (mLocationSLURL.empty()) + { + mPackage[LLExperienceCache::SLURL] = LLStringUtil::null; + } + else + { + mPackage[LLExperienceCache::SLURL] = mLocationSLURL; + } + + mPackage[LLExperienceCache::MATURITY] = getChild(EDIT TF_MATURITY)->getSelectedValue().asInteger(); + + LLSD metadata; + + metadata[TF_MRKT] = getChild(EDIT TF_MRKT)->getText(); + metadata[IMG_LOGO] = getChild(EDIT IMG_LOGO)->getImageAssetID(); + + LLPointer formatter = new LLSDXMLFormatter(); + + std::ostringstream os; + if (formatter->format(metadata, os)) + { + mPackage[LLExperienceCache::METADATA] = os.str(); + } + + int properties = mPackage[LLExperienceCache::PROPERTIES].asInteger(); + LLCheckBoxCtrl* enable = getChild(EDIT BTN_ENABLE); + if (enable->get()) + { + properties &= ~LLExperienceCache::PROPERTY_DISABLED; + } + else + { + properties |= LLExperienceCache::PROPERTY_DISABLED; + } + + enable = getChild(EDIT BTN_PRIVATE); + if (enable->get()) + { + properties |= LLExperienceCache::PROPERTY_PRIVATE; + } + else + { + properties &= ~LLExperienceCache::PROPERTY_PRIVATE; + } + + mPackage[LLExperienceCache::PROPERTIES] = properties; +} + +void LLFloaterExperienceProfile::onPickGroup() +{ + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + + LLFloaterGroupPicker* widget = LLFloaterGroupPicker::showInstance(gAgent.getID()); + if (widget) + { + widget->setSelectGroupCallback(boost::bind(&LLFloaterExperienceProfile::setEditGroup, this, _1)); + if (parent_floater) + { + LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, widget); + widget->setOrigin(new_rect.mLeft, new_rect.mBottom); + parent_floater->addDependentFloater(widget); + } + } +} + +void LLFloaterExperienceProfile::setEditGroup( LLUUID group_id ) +{ + LLTextBox* child = getChild(EDIT TF_GROUP); + child->setValue(group_id); + mPackage[LLExperienceCache::GROUP_ID] = group_id; + onFieldChanged(); +} + +void LLFloaterExperienceProfile::onReportExperience() +{ + LLFloaterReporter::showFromExperience(mExperienceId); +} + +/*static*/ +bool LLFloaterExperienceProfile::hasPermission(const LLSD& content, const std::string &name, const LLUUID &test) +{ + if (!content.has(name)) + return false; + + const LLSD& list = content[name]; + for (const auto& it : list.array()) + { + if (it.asUUID() == test) + { + return true; + } + } + return false; +} + +/*static*/ +void LLFloaterExperienceProfile::experiencePermissionResults(const LLUUID& exprienceId, const LLSD& result) +{ + std::string permission("Forget"); + if (hasPermission(result, "experiences", exprienceId)) + permission = "Allow"; + else if (hasPermission(result, "blocked", exprienceId)) + permission = "Block"; + + LLSD experience; + LLSD message; + experience["permission"] = permission; + message["experience"] = exprienceId; + message[exprienceId.asString()] = experience; + + LLEventPumps::instance().obtain("experience_permission").post(message); +} + +/*static*/ +void LLFloaterExperienceProfile::experienceIsAdmin(LLHandle handle, const LLSD &result) +{ + LLFloaterExperienceProfile* parent = handle.get(); + if (!parent) + return; + + bool enabled = true; + LLViewerRegion* region = gAgent.getRegion(); + if (!region) + { + enabled = false; + } + else + { + std::string url = region->getCapability("UpdateExperience"); + if (url.empty()) + enabled = false; + } + if (enabled && result["status"].asBoolean()) + { + parent->getChild(PNL_TOP)->setVisible(TRUE); + parent->getChild(BTN_EDIT)->setVisible(TRUE); + } +} + +/*static*/ +void LLFloaterExperienceProfile::experienceUpdateResult(LLHandle handle, const LLSD &result) +{ + LLFloaterExperienceProfile* parent = handle.get(); + if (parent) + { + parent->onSaveComplete(result); + } +} diff --git a/indra/newview/llfloaterexperienceprofile.h b/indra/newview/llfloaterexperienceprofile.h new file mode 100644 index 0000000000..d9dad7784e --- /dev/null +++ b/indra/newview/llfloaterexperienceprofile.h @@ -0,0 +1,113 @@ +/** + * @file llfloaterexperienceprofile.h + * @brief llfloaterexperienceprofile and related class definitions + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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_LLFLOATEREXPERIENCEPROFILE_H +#define LL_LLFLOATEREXPERIENCEPROFILE_H + +#include "llfloater.h" +#include "lluuid.h" +#include "llsd.h" + +class LLLayoutPanel; +class LLTextBox; +class LLComboBox; + +class LLFloaterExperienceProfile final : public LLFloater +, public LLInstanceTracker +{ + LOG_CLASS(LLFloaterExperienceProfile); +public: + enum PostSaveAction + { + NOTHING, + CLOSE, + VIEW, + }; + + static void experiencePermissionResults(const LLUUID& exprienceId, const LLSD& result); + + static void showInstance(const LLSD& data); + LLFloaterExperienceProfile(const LLSD& data); + virtual ~LLFloaterExperienceProfile(); + + LLUUID getExperienceId() const { return mExperienceId; } + void setPreferences( const LLSD& content ); + + + void refreshExperience(const LLSD& experience); + void onSaveComplete( const LLSD& content ); + BOOL canClose() override; + + void onClose(bool app_quitting) override; +protected: + void onClickEdit(); + void onClickPermission(const char* permission); + void onClickForget(); + void onClickCancel(); + void onClickSave(); + void onClickLocation(); + void onClickClear(); + void onPickGroup(); + void onFieldChanged(); + void onReportExperience(); + + void setEditGroup(LLUUID group_id); + + void changeToView(); + void changeToEdit(); + + void experienceForgotten(); + void experienceBlocked(); + void experienceAllowed(); + + static void experienceCallback(LLHandle handle, const LLSD& experience); + static bool experiencePermission(LLHandle handle, const LLSD& permission); + + BOOL postBuild() override; + bool setMaturityString(U8 maturity, LLTextBox* child, LLComboBox* combo); + bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response, PostSaveAction action); + void doSave( int success_action ); + + void updatePackage(); + + void updatePermission( const LLSD& permission ); + LLUUID mExperienceId; + LLSD mExperienceDetails; + LLSD mPackage; + std::string mLocationSLURL; + int mSaveCompleteAction; + bool mDirty; + bool mForceClose; + bool mPostEdit; // edit experience after opening and updating it +private: + static bool hasPermission(const LLSD& content, const std::string &name, const LLUUID &test); + static void experienceIsAdmin(LLHandle handle, const LLSD &result); + static void experienceUpdateResult(LLHandle handle, const LLSD &result); +}; + +#endif // LL_LLFLOATEREXPERIENCEPROFILE_H diff --git a/indra/newview/llfloaterexperiences.cpp b/indra/newview/llfloaterexperiences.cpp new file mode 100644 index 0000000000..395b094706 --- /dev/null +++ b/indra/newview/llfloaterexperiences.cpp @@ -0,0 +1,377 @@ +/** + * @file llfloaterexperiences.cpp + * @brief LLFloaterExperiences class implementation + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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 "llviewerprecompiledheaders.h" +#include "llfloaterexperiences.h" + +#include "llagent.h" +#include "llcororesponder.h" +#include "llevents.h" +#include "llexperiencecache.h" +#include "llfloaterexperienceprofile.h" +#include "llfloaterregioninfo.h" +#include "llnotificationsutil.h" +#include "llpanelexperiencelog.h" +#include "llpanelexperiencepicker.h" +#include "llpanelexperiences.h" +#include "lltabcontainer.h" +#include "lltrans.h" +#include "lluictrlfactory.h" +#include "llviewerregion.h" + + +#define SHOW_RECENT_TAB (0) +LLFloaterExperiences::LLFloaterExperiences(const LLSD& data) + :LLFloater(data) +{ + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_experiences.xml", NULL, false); + //buildFromFile("floater_experiences.xml"); +} + +LLPanelExperiences* LLFloaterExperiences::addTab(const std::string& name, bool select) +{ + LLPanelExperiences* newPanel = LLPanelExperiences::create(name); + getChild("xp_tabs")->addTabPanel( + newPanel, + LLTrans::getString(name), + select); + + return newPanel; +} + +BOOL LLFloaterExperiences::postBuild() +{ + LLPanel* panel = new LLPanelExperiencePicker(); + getChild("xp_tabs")->addTabPanel(panel, panel->getLabel()); + addTab("Allowed_Experiences_Tab", true); + addTab("Blocked_Experiences_Tab", false); + addTab("Admin_Experiences_Tab", false); + addTab("Contrib_Experiences_Tab", false); + LLPanelExperiences* owned = addTab("Owned_Experiences_Tab", false); + owned->setButtonAction("acquire", boost::bind(&LLFloaterExperiences::sendPurchaseRequest, this)); + owned->enableButton(false); +#if SHOW_RECENT_TAB + addTab("Recent_Experiences_Tab", false); +#endif //SHOW_RECENT_TAB + panel = new LLPanelExperienceLog(); + getChild("xp_tabs")->addTabPanel(panel, panel->getLabel()); + resizeToTabs(); + + return TRUE; +} + + +void LLFloaterExperiences::clearFromRecent(const LLSD& ids) +{ +#if SHOW_RECENT_TAB + LLTabContainer* tabs = getChild("xp_tabs"); + + LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Recent_Experiences_Tab"); + if(!tab) + return; + + tab->removeExperiences(ids); +#endif // SHOW_RECENT_TAB +} + +void LLFloaterExperiences::setupRecentTabs() +{ +#if SHOW_RECENT_TAB + LLTabContainer* tabs = getChild("xp_tabs"); + + LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Recent_Experiences_Tab"); + if(!tab) + return; + + LLSD recent; + + const LLExperienceCache::cache_t& experiences = LLExperienceCache::getCached(); + + LLExperienceCache::cache_t::const_iterator it = experiences.begin(); + while( it != experiences.end() ) + { + if(!it->second.has(LLExperienceCache::MISSING)) + { + recent.append(it->first); + } + ++it; + } + + tab->setExperienceList(recent); +#endif // SHOW_RECENT_TAB +} + + +void LLFloaterExperiences::resizeToTabs() +{ + const S32 TAB_WIDTH_PADDING = 16; + + LLTabContainer* tabs = getChild("xp_tabs"); + LLRect rect = getRect(); + if(rect.getWidth() < tabs->getTotalTabWidth() + TAB_WIDTH_PADDING) + { + rect.mRight = rect.mLeft + tabs->getTotalTabWidth() + TAB_WIDTH_PADDING; + } + reshape(rect.getWidth(), rect.getHeight(), FALSE); +} + +void LLFloaterExperiences::refreshContents() +{ + setupRecentTabs(); + + LLViewerRegion* region = gAgent.getRegion(); + + if (region) + { + NameMap_t tabMap; + LLHandle handle = getDerivedHandle(); + + tabMap["experiences"]="Allowed_Experiences_Tab"; + tabMap["blocked"]="Blocked_Experiences_Tab"; + tabMap["experience_ids"]="Owned_Experiences_Tab"; + + retrieveExperienceList(region->getCapability("GetExperiences"), handle, tabMap); + + updateInfo("GetAdminExperiences","Admin_Experiences_Tab"); + updateInfo("GetCreatorExperiences","Contrib_Experiences_Tab"); + + retrieveExperienceList(region->getCapability("AgentExperiences"), handle, tabMap, + "ExperienceAcquireFailed", boost::bind(&LLFloaterExperiences::checkPurchaseInfo, this, _1, _2)); + } +} + +void LLFloaterExperiences::onOpen() +{ + LLEventPumps::instance().obtain("experience_permission").stopListening("LLFloaterExperiences"); + LLEventPumps::instance().obtain("experience_permission").listen("LLFloaterExperiences", + boost::bind(&LLFloaterExperiences::updatePermissions, this, _1)); + + LLViewerRegion* region = gAgent.getRegion(); + if(region) + { + if(region->capabilitiesReceived()) + { + refreshContents(); + return; + } + region->setCapabilitiesReceivedCallback(boost::bind(&LLFloaterExperiences::refreshContents, this)); + return; + } +} + +bool LLFloaterExperiences::updatePermissions( const LLSD& permission ) +{ + LLTabContainer* tabs = getChild("xp_tabs"); + LLUUID experience; + std::string permission_string; + if(permission.has("experience")) + { + experience = permission["experience"].asUUID(); + permission_string = permission[experience.asString()]["permission"].asString(); + + } + LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Allowed_Experiences_Tab"); + if(tab) + { + if(permission.has("experiences")) + { + tab->setExperienceList(permission["experiences"]); + } + else if(experience.notNull()) + { + if(permission_string != "Allow") + { + tab->removeExperience(experience); + } + else + { + tab->addExperience(experience); + } + } + } + + tab = (LLPanelExperiences*)tabs->getPanelByName("Blocked_Experiences_Tab"); + if(tab) + { + if(permission.has("blocked")) + { + tab->setExperienceList(permission["blocked"]); + } + else if(experience.notNull()) + { + if(permission_string != "Block") + { + tab->removeExperience(experience); + } + else + { + tab->addExperience(experience); + } + } + } + return false; +} + +void LLFloaterExperiences::onClose( bool app_quitting ) +{ + LLEventPumps::instance().obtain("experience_permission").stopListening("LLFloaterExperiences"); + LLFloater::onClose(app_quitting); +} + +void LLFloaterExperiences::checkPurchaseInfo(LLPanelExperiences* panel, const LLSD& content) const +{ + panel->enableButton(content.has("purchase")); + + LLFloaterExperiences::findInstance()->updateInfo("GetAdminExperiences","Admin_Experiences_Tab"); + LLFloaterExperiences::findInstance()->updateInfo("GetCreatorExperiences","Contrib_Experiences_Tab"); +} + +void LLFloaterExperiences::checkAndOpen(LLPanelExperiences* panel, const LLSD& content) const +{ + checkPurchaseInfo(panel, content); + + // determine new item + const LLSD& response_ids = content["experience_ids"]; + + if (mPrepurchaseIds.size() + 1 == response_ids.size()) + { + // we have a new element + for (const auto& it : response_ids.array()) + { + LLUUID experience_id = it.asUUID(); + if (std::find(mPrepurchaseIds.begin(), mPrepurchaseIds.end(), experience_id) == mPrepurchaseIds.end()) + { + // new element found, open it + LLSD args; + args["experience_id"] = experience_id; + args["edit_experience"] = true; + LLFloaterExperienceProfile::showInstance(args); + break; + } + } + } +} + +void LLFloaterExperiences::updateInfo(std::string experienceCap, std::string tab) +{ + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + NameMap_t tabMap; + LLHandle handle = getDerivedHandle(); + + tabMap["experience_ids"] = tab; + + retrieveExperienceList(region->getCapability(experienceCap), handle, tabMap); + } +} + +void LLFloaterExperiences::sendPurchaseRequest() +{ + LLViewerRegion* region = gAgent.getRegion(); + + if (region) + { + NameMap_t tabMap; + const std::string tab_owned_name = "Owned_Experiences_Tab"; + LLHandle handle = getDerivedHandle(); + + tabMap["experience_ids"] = tab_owned_name; + + // extract ids for experiences that we already have + LLTabContainer* tabs = getChild("xp_tabs"); + LLPanelExperiences* tab_owned = (LLPanelExperiences*)tabs->getPanelByName(tab_owned_name); + mPrepurchaseIds.clear(); + if (tab_owned) + { + tab_owned->getExperienceIdsList(mPrepurchaseIds); + } + + requestNewExperience(region->getCapability("AgentExperiences"), handle, tabMap, "ExperienceAcquireFailed", + boost::bind(&LLFloaterExperiences::checkAndOpen, this, _1, _2)); + } +} + + +void LLFloaterExperiences::retrieveExperienceList(const std::string &url, + const LLHandle &hparent, const NameMap_t &tabMapping, + const std::string &errorNotify, Callback_t cback, bool post) +{ + if (url.empty()) + { + LL_WARNS() << "retrieveExperienceListCoro called with empty capability!" << LL_ENDL; + return; + } + + auto responder = new LLCoroResponder( + boost::bind(LLFloaterExperiences::retrieveExperienceListCoro, _1, + hparent, tabMapping, errorNotify, cback)); + + if (post) + LLHTTPClient::post(url, LLSD(), responder); + else + LLHTTPClient::get(url, responder); +} + +void LLFloaterExperiences::retrieveExperienceListCoro(const LLCoroResponder& responder, + LLHandle hparent, NameMap_t tabMapping, + std::string errorNotify, Callback_t cback) +{ + LLSD result = responder.getContent(); + + if (!responder.isGoodStatus(responder.getStatus())) + { + LLSD subs; + subs["ERROR_MESSAGE"] = responder.getReason(); + LLNotificationsUtil::add(errorNotify, subs); + + return; + } + + if (hparent.isDead()) + return; + + LLFloaterExperiences* parent = hparent.get(); + LLTabContainer* tabs = parent->getChild("xp_tabs"); + + for (auto& it : tabMapping) + { + if (result.has(it.first)) + { + LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName(it.second); + if (tab) + { + const LLSD& ids = result[it.first]; + tab->setExperienceList(ids); + if (cback != nullptr) + { + cback(tab, result); + } + } + } + } + +} diff --git a/indra/newview/llfloaterexperiences.h b/indra/newview/llfloaterexperiences.h new file mode 100644 index 0000000000..ebe1a00fec --- /dev/null +++ b/indra/newview/llfloaterexperiences.h @@ -0,0 +1,78 @@ +/** + * @file llfloaterexperiences.h + * @brief LLFloaterExperiences class definition + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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_LLFLOATEREXPERIENCES_H +#define LL_LLFLOATEREXPERIENCES_H + +#include "llfloater.h" + +class LLPanelExperiences; + +class LLFloaterExperiences final : + public LLFloater +, public LLFloaterSingleton +{ + friend class LLUISingleton >; +public: + LLFloaterExperiences(const LLSD& data); + void onClose(bool app_quitting) override; + + void onOpen(/*const LLSD& key*/) override; + +protected: + typedef std::map NameMap_t; + typedef std::function Callback_t; + + void clearFromRecent(const LLSD& ids); + void resizeToTabs(); + /*virtual*/ BOOL postBuild() override; + void refreshContents(); + void setupRecentTabs(); + LLPanelExperiences* addTab(const std::string& name, bool select); + + bool updatePermissions(const LLSD& permission); + void sendPurchaseRequest(); + void checkPurchaseInfo(LLPanelExperiences* panel, const LLSD& content)const; + void checkAndOpen(LLPanelExperiences* panel, const LLSD& content) const; + void updateInfo(std::string experiences, std::string tab); + + void retrieveExperienceList(const std::string &url, const LLHandle &hparent, const NameMap_t &tabMapping, + const std::string &errorNotify = std::string("ErrorMessage"), Callback_t cback = Callback_t(), bool post = false); + + void requestNewExperience(const std::string &url, const LLHandle &hparent, const NameMap_t &tabMapping, + const std::string &errorNotify, Callback_t cback) + { + retrieveExperienceList(url, hparent, tabMapping, errorNotify, cback, true); + } + +private: + static void retrieveExperienceListCoro(const struct LLCoroResponder& responder, LLHandle hparent, + NameMap_t tabMapping, std::string errorNotify, Callback_t cback); + uuid_vec_t mPrepurchaseIds; +}; + +#endif //LL_LLFLOATEREXPERIENCES_H + diff --git a/indra/newview/llfloaterexploreanimations.cpp b/indra/newview/llfloaterexploreanimations.cpp index 521065a4ed..6bfa4f52ff 100644 --- a/indra/newview/llfloaterexploreanimations.cpp +++ b/indra/newview/llfloaterexploreanimations.cpp @@ -109,16 +109,16 @@ void LLFloaterExploreAnimations::draw() gGL.getTexUnit(0)->bind(&mAnimPreview); - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLE_STRIP ); { gGL.texCoord2f(0.f, 1.f); gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mTop); gGL.texCoord2f(0.f, 0.f); gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mBottom); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mBottom); gGL.texCoord2f(1.f, 1.f); gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mTop); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mBottom); } gGL.end(); diff --git a/indra/newview/llfloaterexploresounds.cpp b/indra/newview/llfloaterexploresounds.cpp index 36caef3e93..94400f31f9 100644 --- a/indra/newview/llfloaterexploresounds.cpp +++ b/indra/newview/llfloaterexploresounds.cpp @@ -295,7 +295,7 @@ void LLFloaterExploreSounds::handle_play_locally(void* user_data) std::vector selection = list->getAllSelected(); std::vector::iterator selection_iter = selection.begin(); std::vector::iterator selection_end = selection.end(); - std::vector asset_list; + uuid_vec_t asset_list; for( ; selection_iter != selection_end; ++selection_iter) { LLSoundHistoryItem item = floater->getItem((*selection_iter)->getValue()); @@ -353,7 +353,7 @@ void LLFloaterExploreSounds::handle_stop(void* user_data) std::vector selection = list->getAllSelected(); std::vector::iterator selection_iter = selection.begin(); std::vector::iterator selection_end = selection.end(); - std::vector asset_list; + uuid_vec_t asset_list; for( ; selection_iter != selection_end; ++selection_iter) { LLSoundHistoryItem item = floater->getItem((*selection_iter)->getValue()); diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 5a75a47717..da43f9696c 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -272,13 +272,11 @@ BOOL LLPanelFriends::postBuild() { mFriendsList = getChild("friend_list"); mFriendsList->setCommitOnSelectionChange(true); - /* Singu TODO: Update to C++11 and make everything cleaner here auto single_selection(boost::bind(&LLScrollListCtrl::getCurrentID, mFriendsList)); auto selection(boost::bind(&LLScrollListCtrl::getSelectedIDs, mFriendsList)); - */ mFriendsList->setCommitCallback(boost::bind(&LLPanelFriends::onSelectName, this)); //getChild("buddy_group_combobox")->setCommitCallback(boost::bind(&LLPanelFriends::setContactGroup, this, _2)); - mFriendsList->setDoubleClickCallback(boost::bind(LLAvatarActions::startIM, boost::bind(&LLScrollListCtrl::getCurrentID, mFriendsList))); + mFriendsList->setDoubleClickCallback(boost::bind(LLAvatarActions::startIM, single_selection)); // // Contact search and group system. @@ -294,13 +292,13 @@ BOOL LLPanelFriends::postBuild() U32 changed_mask = LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE; refreshNames(changed_mask); - getChild("im_btn")->setCommitCallback(boost::bind(&LLPanelFriends::onClickIM, this, boost::bind(&LLScrollListCtrl::getSelectedIDs, mFriendsList))); - //getChild("assign_btn")->setCommitCallback(boost::bind(ASFloaterContactGroups::show, boost::bind(&LLScrollListCtrl::getSelectedIDs, mFriendsList))); - getChild("profile_btn")->setCommitCallback(boost::bind(LLAvatarActions::showProfiles, boost::bind(&LLScrollListCtrl::getSelectedIDs, mFriendsList), false)); - getChild("offer_teleport_btn")->setCommitCallback(boost::bind(static_cast(LLAvatarActions::offerTeleport), boost::bind(&LLScrollListCtrl::getSelectedIDs, mFriendsList))); - getChild("pay_btn")->setCommitCallback(boost::bind(LLAvatarActions::pay, boost::bind(&LLScrollListCtrl::getCurrentID, mFriendsList))); + getChild("im_btn")->setCommitCallback(boost::bind(&LLPanelFriends::onClickIM, this, selection)); + //getChild("assign_btn")->setCommitCallback(boost::bind(ASFloaterContactGroups::show, selection)); + getChild("profile_btn")->setCommitCallback(boost::bind(LLAvatarActions::showProfiles, selection, false)); + getChild("offer_teleport_btn")->setCommitCallback(boost::bind(static_cast(LLAvatarActions::offerTeleport), selection)); + getChild("pay_btn")->setCommitCallback(boost::bind(LLAvatarActions::pay, single_selection)); getChild("add_btn")->setCommitCallback(boost::bind(&LLPanelFriends::onClickAddFriend, this)); - getChild("remove_btn")->setCommitCallback(boost::bind(LLAvatarActions::removeFriendsDialog, boost::bind(&LLScrollListCtrl::getSelectedIDs, mFriendsList))); + getChild("remove_btn")->setCommitCallback(boost::bind(LLAvatarActions::removeFriendsDialog, selection)); //getChild("export_btn")->setCommitCallback(boost::bind(&LLPanelFriends::onClickExport, this)); Making Dummy View -HgB //getChild("import_btn")->setCommitCallback(boost::bind(&LLPanelFriends::onClickImport, this)); Making Dummy View -HgB diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index bd5cf9d076..e01cb02670 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -331,7 +331,7 @@ void LLFloaterGesture::onClickInventory(void* data) if (!list) return; const LLUUID& item_id = list->getCurrentID(); - LLInventoryView* inv = LLInventoryView::showAgentInventory(); + LLPanelMainInventory* inv = LLPanelMainInventory::showAgentInventory(); if (!inv) return; inv->getPanel()->setSelection(item_id, TRUE); } diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index c06a89ae7d..7e58612762 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -118,6 +118,8 @@ void LLFloaterGodTools::refreshAll() LLFloaterGodTools::LLFloaterGodTools() : LLFloater(std::string("godtools floater")), + mPanelRegionTools(nullptr), + mPanelObjectTools(nullptr), mCurrentHost(LLHost::invalid), mUpdateTimer() { @@ -554,7 +556,7 @@ void LLPanelRegionTools::onSaveState(void* userdata) gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); gMessageSystem->nextBlockFast(_PREHASH_DataBlock); - gMessageSystem->addStringFast(_PREHASH_Filename, NULL); + gMessageSystem->addStringFast(_PREHASH_Filename, nullptr); gAgent.sendReliableMessage(); } } @@ -1352,7 +1354,7 @@ void LLPanelRequestTools::onClickRequest() if(dest == SELECTION) { std::string req =getChild("request")->getValue(); - req = req.substr(0, req.find_first_of(" ")); + req = req.substr(0, req.find_first_of(' ')); std::string param = getChild("parameter")->getValue(); LLSelectMgr::getInstance()->sendGodlikeRequest(req, param); } @@ -1399,11 +1401,11 @@ void LLPanelRequestTools::sendRequest(const LLHost& host) host, FALSE, terrain_download_done, - NULL); + nullptr); } else { - req = req.substr(0, req.find_first_of(" ")); + req = req.substr(0, req.find_first_of(' ')); sendRequest(req, getChild("parameter")->getValue().asString(), host); } } diff --git a/indra/newview/llfloatergroupinvite.cpp b/indra/newview/llfloatergroupinvite.cpp index 207ec78f52..656854e41e 100644 --- a/indra/newview/llfloatergroupinvite.cpp +++ b/indra/newview/llfloatergroupinvite.cpp @@ -112,7 +112,7 @@ LLFloaterGroupInvite::~LLFloaterGroupInvite() } // static -void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, std::vector *agent_ids) +void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, uuid_vec_t *agent_ids) { // Make sure group_id isn't null if (group_id.isNull()) diff --git a/indra/newview/llfloatergroupinvite.h b/indra/newview/llfloatergroupinvite.h index d1485ead91..48c15c3aa0 100644 --- a/indra/newview/llfloatergroupinvite.h +++ b/indra/newview/llfloatergroupinvite.h @@ -43,7 +43,7 @@ class LLFloaterGroupInvite public: virtual ~LLFloaterGroupInvite(); - static void showForGroup(const LLUUID &group_id, std::vector *agent_ids = NULL); + static void showForGroup(const LLUUID &group_id, uuid_vec_t *agent_ids = NULL); protected: LLFloaterGroupInvite(const std::string& name, diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp index 5367bcc6d1..f696bcef0a 100644 --- a/indra/newview/llfloatergroups.cpp +++ b/indra/newview/llfloatergroups.cpp @@ -45,6 +45,7 @@ #include "hbfloatergrouptitles.h" #include "llagent.h" +#include "llagentbenefits.h" #include "llbutton.h" #include "llfloatergroupinvite.h" #include "llgroupactions.h" @@ -187,7 +188,7 @@ void LLPanelGroups::setTexts() LLUICtrl* ctrl(getChild("groupcount")); size_t count(gAgent.mGroups.size()); ctrl->setTextArg("[COUNT]", llformat("%d", count)); - int maxgroups(gHippoLimits->getMaxAgentGroups()); + int maxgroups(LLAgentBenefitsMgr::current().getGroupMembershipLimit()); ctrl->setTextArg("[MAX]", llformat("%d", maxgroups)); ctrl->setTextArg("[LEFT]", llformat("%d", maxgroups - count)); } @@ -375,7 +376,6 @@ LLSD create_group_element(const LLGroupData *group_datap, const LLUUID &active_g void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 powers_mask) { - S32 count = gAgent.mGroups.size(); LLUUID id; LLCtrlListInterface *group_list = ctrl->getListInterface(); if (!group_list) return; @@ -386,11 +386,16 @@ void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 pow group_list->operateOnAll(LLCtrlListInterface::OP_DELETE); - for(S32 i = 0; i < count; ++i) + for(const auto& group : gAgent.mGroups) { - LLSD element = create_group_element(&gAgent.mGroups[i], highlight_id, powers_mask); - if(element.size()) + LLSD element = create_group_element(&group, highlight_id, powers_mask); + if (element.size()) + { group_list->addElement(element, ADD_SORTED); + // Force a name lookup here to get it added to the cache so other UI is prepared + std::string dummy; + gCacheName->getGroupName(group.mID, dummy); + } } // add "none" to list at top diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 74093f2434..6db06034f5 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -40,6 +40,7 @@ #include "llimagej2c.h" #include "llagent.h" +#include "llagentbenefits.h" #include "llbutton.h" #include "llcombobox.h" #include "lldrawable.h" @@ -96,7 +97,8 @@ BOOL LLFloaterImagePreview::postBuild() return FALSE; } - childSetLabelArg("ok_btn", "[UPLOADFEE]", gHippoGridManager->getConnectedGrid()->getUploadFee()); + auto& grid = *gHippoGridManager->getConnectedGrid(); + childSetLabelArg("ok_btn", "[UPLOADFEE]", grid.formatFee(LLAgentBenefitsMgr::current().getTextureUploadCost())); LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); if (iface) @@ -126,7 +128,11 @@ BOOL LLFloaterImagePreview::postBuild() // gSavedSettings.setBOOL("TemporaryUpload",FALSE); - childSetValue("temp_check",FALSE); + auto child = getChildView("temp_check"); + if (grid.isSecondLife()) + child->setVisible(false); + else + child->setValue(false); // } else @@ -252,7 +258,7 @@ void LLFloaterImagePreview::draw() if (selected <= 0) { gl_rect_2d_checkerboard( calcScreenRect(), mPreviewRect); - LLGLDisable gls_alpha(GL_ALPHA_TEST); + LLGLDisable gls_alpha; if(mImagep.notNull()) { @@ -277,16 +283,16 @@ void LLFloaterImagePreview::draw() } gGL.color3f(1.f, 1.f, 1.f); - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLE_STRIP ); { gGL.texCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mTop); gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); gGL.texCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mBottom); gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); - gGL.texCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mBottom); - gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); gGL.texCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mTop); gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); + gGL.texCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mBottom); + gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); } gGL.end(); @@ -309,16 +315,16 @@ void LLFloaterImagePreview::draw() gGL.getTexUnit(0)->bind(mAvatarPreview); } - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLE_STRIP ); { gGL.texCoord2f(0.f, 1.f); gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); gGL.texCoord2f(0.f, 0.f); gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); gGL.texCoord2f(1.f, 1.f); gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); } gGL.end(); @@ -621,15 +627,8 @@ LLImagePreviewAvatar::LLImagePreviewAvatar(S32 width, S32 height) : LLViewerDyna mCameraPitch = 0.f; mCameraZoom = 1.f; - mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion()); - mDummyAvatar->createDrawable(&gPipeline); - mDummyAvatar->mIsDummy = TRUE; + mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), LLViewerObject::CO_FLAG_UI_AVATAR); mDummyAvatar->mSpecialRenderMode = 2; - mDummyAvatar->setPositionAgent(LLVector3::zero); - mDummyAvatar->slamPosition(); - mDummyAvatar->updateJointLODs(); - mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); - // gPipeline.markVisible(mDummyAvatar->mDrawable, *LLViewerCamera::getInstance()); mTextureName = 0; } @@ -757,13 +756,14 @@ BOOL LLImagePreviewAvatar::render() { LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); // make sure alpha=0 shows avatar material color - LLGLDisable no_blend(GL_BLEND); + LLGLDisable no_blend; LLFace* face = avatarp->mDrawable->getFace(0); if (face) { LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)face->getPool(); - gPipeline.enableLightsPreview(); + LLGLState light_state; + gPipeline.enableLightsPreview(light_state); avatarPoolp->renderAvatars(avatarp); // renders only one avatar } } @@ -848,7 +848,7 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) if (imagep) { - mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0); + mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0, false); } const LLVolumeFace &vf = mVolume->getVolumeFace(0); @@ -900,8 +900,8 @@ BOOL LLImagePreviewSculpted::render() { mNeedsUpdate = FALSE; LLGLSUIDefault def; - LLGLDisable no_blend(GL_BLEND); - LLGLEnable cull(GL_CULL_FACE); + LLGLDisable no_blend; + LLGLEnable cull; LLGLDepthTest depth(GL_TRUE); gGL.matrixMode(LLRender::MM_PROJECTION); @@ -928,6 +928,7 @@ BOOL LLImagePreviewSculpted::render() gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.popMatrix(); + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT); LLVector3 target_pos(0, 0, 0); @@ -950,13 +951,14 @@ BOOL LLImagePreviewSculpted::render() const LLVolumeFace &vf = mVolume->getVolumeFace(0); U32 num_indices = vf.mNumIndices; - gPipeline.enableLightsAvatar(); + LLGLState light_state; + gPipeline.enableLightsAvatar(light_state); if (LLGLSLShader::sNoFixedFunction) { gObjectPreviewProgram.bind(); } - gPipeline.enableLightsPreview(); + gPipeline.enableLightsPreview(light_state); gGL.pushMatrix(); const F32 SCALE = 1.25f; diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp index 6b8a18ed82..01dd84dc18 100644 --- a/indra/newview/llfloaterinspect.cpp +++ b/indra/newview/llfloaterinspect.cpp @@ -54,9 +54,11 @@ LLFloaterInspect::LLFloaterInspect(const LLSD&) : LLFloater(std::string("Inspect Object")), + mObjectList(nullptr), mDirty(FALSE) { mCommitCallbackRegistrar.add("Inspect.OwnerProfile", boost::bind(&LLFloaterInspect::onClickOwnerProfile, this)); + mCommitCallbackRegistrar.add("Inspect.LastOwnerProfile", boost::bind(&LLFloaterInspect::onClickLastOwnerProfile, this)); mCommitCallbackRegistrar.add("Inspect.CreatorProfile", boost::bind(&LLFloaterInspect::onClickCreatorProfile, this)); mCommitCallbackRegistrar.add("Inspect.SelectObject", boost::bind(&LLFloaterInspect::onSelectObject, this)); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inspect.xml"); @@ -165,6 +167,36 @@ void LLFloaterInspect::onClickOwnerProfile() } } +void LLFloaterInspect::onClickLastOwnerProfile() +{ + if(mObjectList->getAllSelected().size() == 0) return; + LLScrollListItem* first_selected =mObjectList->getFirstSelected(); + + if (first_selected) + { + LLUUID selected_id = first_selected->getUUID(); + struct f : public LLSelectedNodeFunctor + { + LLUUID obj_id; + f(const LLUUID& id) : obj_id(id) {} + virtual bool apply(LLSelectNode* node) + { + return (obj_id == node->getObject()->getID()); + } + } func(selected_id); + LLSelectNode* node = mObjectSelection->getFirstNode(&func); + if(node) + { + const LLUUID& last_owner_id = node->mPermissions->getLastOwner(); +// [RLVa:KB] - Checked: 2010-08-25 (RLVa-1.2.2a) | Modified: RLVa-1.0.0e + if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) || gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) + if (last_owner_id == node->mPermissions->getOwner()) return; +// [/RLVa:KB] + LLAvatarActions::showProfile(last_owner_id); + } + } +} + void LLFloaterInspect::onSelectObject() { if(LLFloaterInspect::getSelectedUUID() != LLUUID::null) @@ -370,7 +402,7 @@ void LLFloaterInspect::refresh() // void LLFloaterInspect::inventoryChanged(LLViewerObject* viewer_object, LLInventoryObject::object_list_t* inv, S32, void*) { - std::vector::iterator iter = std::find(mQueue.begin(),mQueue.end(),viewer_object->getID()); + auto iter = std::find(mQueue.begin(),mQueue.end(),viewer_object->getID()); if (viewer_object && inv && iter != mQueue.end()) { U32 scripts = 0; diff --git a/indra/newview/llfloaterinspect.h b/indra/newview/llfloaterinspect.h index c60b116d70..3769cedf77 100644 --- a/indra/newview/llfloaterinspect.h +++ b/indra/newview/llfloaterinspect.h @@ -38,7 +38,6 @@ #include "llavatarname.h" #include "llfloater.h" #include "llvoinventorylistener.h" -#include //class LLTool; class LLObjectSelection; @@ -61,6 +60,7 @@ class LLFloaterInspect : public LLFloater, public LLFloaterSingleton mObjectSelection; // std::map > mInventoryNums; // - std::vector mQueue; + uuid_vec_t mQueue; // - boost::container::map mOwnerNameCacheConnection; - boost::container::map mLastOwnerNameCacheConnection; // - boost::container::map mCreatorNameCacheConnection; + std::map mOwnerNameCacheConnection; + std::map mLastOwnerNameCacheConnection; // + std::map mCreatorNameCacheConnection; }; #endif //LL_LLFLOATERINSPECT_H diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index 2795ce016f..da8385485b 100644 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -49,6 +49,9 @@ LLFloaterJoystick::LLFloaterJoystick(const LLSD& data) : LLFloater("floater_joystick") + , mCheckJoystickEnabled(nullptr) + , mCheckFlycamEnabled(nullptr) + , mAxisStatsBar({ {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr} }) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_joystick.xml"); center(); @@ -56,27 +59,21 @@ LLFloaterJoystick::LLFloaterJoystick(const LLSD& data) void LLFloaterJoystick::draw() { + // Singu TODO: Cache these children, or consider not doing this in the draw call bool joystick_inited = LLViewerJoystick::getInstance()->isJoystickInitialized(); childSetEnabled("enable_joystick", joystick_inited); - childSetEnabled("joystick_type", joystick_inited); + auto type(getChild("joystick_type")); + type->setEnabled(joystick_inited); std::string desc = LLViewerJoystick::getInstance()->getDescription(); if (desc.empty()) desc = getString("NoDevice"); - childSetText("joystick_type", desc); + type->setValue(desc); LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); - for (U32 i = 0; i < 6; i++) + for (U32 i = 0; i < 6; ++i) { F32 value = joystick->getJoystickAxis(i); + mAxisStatsBar[i]->fit(value); mAxisStats[i]->addValue(value * gFrameIntervalSeconds); - - if (mAxisStatsBar[i]->mMinBar > value) - { - mAxisStatsBar[i]->mMinBar = value; - } - if (mAxisStatsBar[i]->mMaxBar < value) - { - mAxisStatsBar[i]->mMaxBar = value; - } } LLFloater::draw(); @@ -112,11 +109,12 @@ BOOL LLFloaterJoystick::postBuild() axis.setArg("[NUM]", llformat("%d", i)); std::string stat_name(llformat("Joystick axis %d", i)); mAxisStats[i] = new LLStat(stat_name,4); - mAxisStatsBar[i] = mAxisStatsView->addStat(axis, mAxisStats[i]); - mAxisStatsBar[i]->mMinBar = -range; - mAxisStatsBar[i]->mMaxBar = range; - mAxisStatsBar[i]->mLabelSpacing = range * 0.5f; - mAxisStatsBar[i]->mTickSpacing = range * 0.25f; + LLStatBar::Parameters params; + params.mMinBar = -range; + params.mMaxBar = range; + params.mLabelSpacing = range * 0.5f; + params.mTickSpacing = range * 0.25f; + mAxisStatsBar[i] = mAxisStatsView->addStat(axis, mAxisStats[i], params); } addChild(mAxisStatsView); diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h index 07b4b49c7d..1104b604f0 100644 --- a/indra/newview/llfloaterjoystick.h +++ b/indra/newview/llfloaterjoystick.h @@ -85,7 +85,7 @@ class LLFloaterJoystick : public LLFloater, public LLFloaterSingleton mAxisStatsBar; }; #endif diff --git a/indra/newview/llfloaterlagmeter.cpp b/indra/newview/llfloaterlagmeter.cpp deleted file mode 100644 index d1445cdbb1..0000000000 --- a/indra/newview/llfloaterlagmeter.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/** - * @file llfloaterlagmeter.cpp - * @brief The "Lag-o-Meter" floater used to tell users what is causing lag. - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfloaterlagmeter.h" - -#include "lluictrlfactory.h" -#include "llviewerstats.h" -#include "llviewertexture.h" -#include "llviewercontrol.h" -#include "llappviewer.h" - -#include "lltexturefetch.h" - -#include "llbutton.h" -#include "llfocusmgr.h" -#include "lltextbox.h" - -const std::string LAG_CRITICAL_IMAGE_NAME = "lag_status_critical.tga"; -const std::string LAG_WARNING_IMAGE_NAME = "lag_status_warning.tga"; -const std::string LAG_GOOD_IMAGE_NAME = "lag_status_good.tga"; - -LLFloaterLagMeter::LLFloaterLagMeter(const LLSD& key) - : LLFloater(std::string("floater_lagmeter")) -{ - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_lagmeter.xml"); - - // Don't let this window take keyboard focus -- it's confusing to - // lose arrow-key driving when testing lag. - setIsChrome(TRUE); - - mClientButton = getChild("client_lagmeter"); - mClientText = getChild("client_text"); - mClientCause = getChild("client_lag_cause"); - - mNetworkButton = getChild("network_lagmeter"); - mNetworkText = getChild("network_text"); - mNetworkCause = getChild("network_lag_cause"); - - mServerButton = getChild("server_lagmeter"); - mServerText = getChild("server_text"); - mServerCause = getChild("server_lag_cause"); - - std::string config_string = getString("client_frame_rate_critical_fps", mStringArgs); - mClientFrameTimeCritical = 1.0f / (float)atof( config_string.c_str() ); - config_string = getString("client_frame_rate_warning_fps", mStringArgs); - mClientFrameTimeWarning = 1.0f / (float)atof( config_string.c_str() ); - - config_string = getString("network_packet_loss_critical_pct", mStringArgs); - mNetworkPacketLossCritical = (float)atof( config_string.c_str() ); - config_string = getString("network_packet_loss_warning_pct", mStringArgs); - mNetworkPacketLossWarning = (float)atof( config_string.c_str() ); - - config_string = getString("network_ping_critical_ms", mStringArgs); - mNetworkPingCritical = (float)atof( config_string.c_str() ); - config_string = getString("network_ping_warning_ms", mStringArgs); - mNetworkPingWarning = (float)atof( config_string.c_str() ); - config_string = getString("server_frame_rate_critical_fps", mStringArgs); - - mServerFrameTimeCritical = 1000.0f / (float)atof( config_string.c_str() ); - config_string = getString("server_frame_rate_warning_fps", mStringArgs); - mServerFrameTimeWarning = 1000.0f / (float)atof( config_string.c_str() ); - config_string = getString("server_single_process_max_time_ms", mStringArgs); - mServerSingleProcessMaxTime = (float)atof( config_string.c_str() ); - - mShrunk = false; - config_string = getString("max_width_px", mStringArgs); - mMaxWidth = atoi( config_string.c_str() ); - config_string = getString("min_width_px", mStringArgs); - mMinWidth = atoi( config_string.c_str() ); - - mStringArgs["[CLIENT_FRAME_RATE_CRITICAL]"] = getString("client_frame_rate_critical_fps"); - mStringArgs["[CLIENT_FRAME_RATE_WARNING]"] = getString("client_frame_rate_warning_fps"); - - mStringArgs["[NETWORK_PACKET_LOSS_CRITICAL]"] = getString("network_packet_loss_critical_pct"); - mStringArgs["[NETWORK_PACKET_LOSS_WARNING]"] = getString("network_packet_loss_warning_pct"); - - mStringArgs["[NETWORK_PING_CRITICAL]"] = getString("network_ping_critical_ms"); - mStringArgs["[NETWORK_PING_WARNING]"] = getString("network_ping_warning_ms"); - - mStringArgs["[SERVER_FRAME_RATE_CRITICAL]"] = getString("server_frame_rate_critical_fps"); - mStringArgs["[SERVER_FRAME_RATE_WARNING]"] = getString("server_frame_rate_warning_fps"); - - childSetAction("minimize", onClickShrink, this); - - // were we shrunk last time? - if (gSavedSettings.getBOOL("LagMeterShrunk")) - { - onClickShrink(this); - } -} - -LLFloaterLagMeter::~LLFloaterLagMeter() -{ - // save shrunk status for next time - gSavedSettings.setBOOL("LagMeterShrunk", mShrunk); - // expand so we save the large window rectangle - if (mShrunk) - { - onClickShrink(this); - } -} - -void LLFloaterLagMeter::draw() -{ - determineClient(); - determineNetwork(); - determineServer(); - - LLFloater::draw(); -} - -void LLFloaterLagMeter::determineClient() -{ - F32 client_frame_time = LLViewerStats::getInstance()->mFPSStat.getMeanDuration(); - bool find_cause = false; - - if (!gFocusMgr.getAppHasFocus()) - { - mClientButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME)); - mClientText->setText( getString("client_frame_time_window_bg_msg", mStringArgs) ); - mClientCause->setText( LLStringUtil::null ); - } - else if(client_frame_time >= mClientFrameTimeCritical) - { - mClientButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME)); - mClientText->setText( getString("client_frame_time_critical_msg", mStringArgs) ); - find_cause = true; - } - else if(client_frame_time >= mClientFrameTimeWarning) - { - mClientButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME)); - mClientText->setText( getString("client_frame_time_warning_msg", mStringArgs) ); - find_cause = true; - } - else - { - mClientButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME)); - mClientText->setText( getString("client_frame_time_normal_msg", mStringArgs) ); - mClientCause->setText( LLStringUtil::null ); - } - - if(find_cause) - { - if(gSavedSettings.getF32("RenderFarClip") > 128) - { - mClientCause->setText( getString("client_draw_distance_cause_msg", mStringArgs) ); - } - else if(LLAppViewer::instance()->getTextureFetch()->getNumRequests() > 2) - { - mClientCause->setText( getString("client_texture_loading_cause_msg", mStringArgs) ); - } - else if((BYTES_TO_MEGA_BYTES(LLViewerTexture::sBoundTextureMemoryInBytes)) > LLViewerTexture::sMaxBoundTextureMemInMegaBytes) - { - mClientCause->setText( getString("client_texture_memory_cause_msg", mStringArgs) ); - } - else - { - mClientCause->setText( getString("client_complex_objects_cause_msg", mStringArgs) ); - } - } -} - -void LLFloaterLagMeter::determineNetwork() -{ - F32 packet_loss = LLViewerStats::getInstance()->mPacketsLostPercentStat.getMean(); - F32 ping_time = LLViewerStats::getInstance()->mSimPingStat.getMean(); - bool find_cause_loss = false; - bool find_cause_ping = false; - - // *FIXME: We can't blame a large ping time on anything in - // particular if the frame rate is low, because a low frame - // rate is a sure recipe for crappy ping times right now until - // the network handlers are de-synched from the rendering. - F32 client_frame_time_ms = 1000.0f * LLViewerStats::getInstance()->mFPSStat.getMeanDuration(); - - if(packet_loss >= mNetworkPacketLossCritical) - { - mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME)); - mNetworkText->setText( getString("network_packet_loss_critical_msg", mStringArgs) ); - find_cause_loss = true; - } - else if(ping_time >= mNetworkPingCritical) - { - mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME)); - if (client_frame_time_ms < mNetworkPingCritical) - { - mNetworkText->setText( getString("network_ping_critical_msg", mStringArgs) ); - find_cause_ping = true; - } - } - else if(packet_loss >= mNetworkPacketLossWarning) - { - mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME)); - mNetworkText->setText( getString("network_packet_loss_warning_msg", mStringArgs) ); - find_cause_loss = true; - } - else if(ping_time >= mNetworkPingWarning) - { - mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME)); - if (client_frame_time_ms < mNetworkPingWarning) - { - mNetworkText->setText( getString("network_ping_warning_msg", mStringArgs) ); - find_cause_ping = true; - } - } - else - { - mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME)); - mNetworkText->setText( getString("network_performance_normal_msg", mStringArgs) ); - } - - if(find_cause_loss) - { - mNetworkCause->setText( getString("network_packet_loss_cause_msg", mStringArgs) ); - } - else if(find_cause_ping) - { - mNetworkCause->setText( getString("network_ping_cause_msg", mStringArgs) ); - } - else - { - mNetworkCause->setText( LLStringUtil::null ); - } -} - -void LLFloaterLagMeter::determineServer() -{ - F32 sim_frame_time = LLViewerStats::getInstance()->mSimFrameMsec.getCurrent(); - bool find_cause = false; - - if(sim_frame_time >= mServerFrameTimeCritical) - { - mServerButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME)); - mServerText->setText( getString("server_frame_time_critical_msg", mStringArgs) ); - find_cause = true; - } - else if(sim_frame_time >= mServerFrameTimeWarning) - { - mServerButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME)); - mServerText->setText( getString("server_frame_time_warning_msg", mStringArgs) ); - find_cause = true; - } - else - { - mServerButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME)); - mServerText->setText( getString("server_frame_time_normal_msg", mStringArgs) ); - mServerCause->setText( LLStringUtil::null ); - } - - if(find_cause) - { - if(LLViewerStats::getInstance()->mSimSimPhysicsMsec.getCurrent() > mServerSingleProcessMaxTime) - { - mServerCause->setText( getString("server_physics_cause_msg", mStringArgs) ); - } - else if(LLViewerStats::getInstance()->mSimScriptMsec.getCurrent() > mServerSingleProcessMaxTime) - { - mServerCause->setText( getString("server_scripts_cause_msg", mStringArgs) ); - } - else if(LLViewerStats::getInstance()->mSimNetMsec.getCurrent() > mServerSingleProcessMaxTime) - { - mServerCause->setText( getString("server_net_cause_msg", mStringArgs) ); - } - else if(LLViewerStats::getInstance()->mSimAgentMsec.getCurrent() > mServerSingleProcessMaxTime) - { - mServerCause->setText( getString("server_agent_cause_msg", mStringArgs) ); - } - else if(LLViewerStats::getInstance()->mSimImagesMsec.getCurrent() > mServerSingleProcessMaxTime) - { - mServerCause->setText( getString("server_images_cause_msg", mStringArgs) ); - } - else - { - mServerCause->setText( getString("server_generic_cause_msg", mStringArgs) ); - } - } -} - -//static -void LLFloaterLagMeter::onClickShrink(void * data) -{ - LLFloaterLagMeter * self = (LLFloaterLagMeter*)data; - - LLButton * button = self->getChild("minimize"); - S32 delta_width = self->mMaxWidth - self->mMinWidth; - LLRect r = self->getRect(); - if(self->mShrunk) - { - self->setTitle( self->getString("max_title_msg", self->mStringArgs) ); - // make left edge appear to expand - r.translate(-delta_width, 0); - self->setRect(r); - self->reshape(self->mMaxWidth, self->getRect().getHeight()); - - self->childSetText("client", self->getString("client_text_msg", self->mStringArgs) + ":"); - self->childSetText("network", self->getString("network_text_msg", self->mStringArgs) + ":"); - self->childSetText("server", self->getString("server_text_msg", self->mStringArgs) + ":"); - - // usually "<<" - button->setLabel( self->getString("smaller_label", self->mStringArgs) ); - } - else - { - self->setTitle( self->getString("min_title_msg", self->mStringArgs) ); - // make left edge appear to collapse - r.translate(delta_width, 0); - self->setRect(r); - self->reshape(self->mMinWidth, self->getRect().getHeight()); - - self->childSetText("client", self->getString("client_text_msg", self->mStringArgs) ); - self->childSetText("network", self->getString("network_text_msg", self->mStringArgs) ); - self->childSetText("server", self->getString("server_text_msg", self->mStringArgs) ); - - // usually ">>" - button->setLabel( self->getString("bigger_label", self->mStringArgs) ); - } - // Don't put keyboard focus on the button - button->setFocus(FALSE); - - self->mClientText->setVisible(self->mShrunk); - self->mClientCause->setVisible(self->mShrunk); - self->childSetVisible("client_help", self->mShrunk); - - self->mNetworkText->setVisible(self->mShrunk); - self->mNetworkCause->setVisible(self->mShrunk); - self->childSetVisible("network_help", self->mShrunk); - - self->mServerText->setVisible(self->mShrunk); - self->mServerCause->setVisible(self->mShrunk); - self->childSetVisible("server_help", self->mShrunk); - - self->mShrunk = !self->mShrunk; -} diff --git a/indra/newview/llfloaterlagmeter.h b/indra/newview/llfloaterlagmeter.h deleted file mode 100644 index d9cea18305..0000000000 --- a/indra/newview/llfloaterlagmeter.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file llfloaterlagmeter.h - * @brief The "Lag-o-Meter" floater used to tell users what is causing lag. - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLFLOATERLAGMETER_H -#define LLFLOATERLAGMETER_H - -#include "llfloater.h" - -class LLFloaterLagMeter : public LLFloater, public LLFloaterSingleton -{ - friend class LLUISingleton >; - -public: - /*virtual*/ void draw(); - -private: - LLFloaterLagMeter(const LLSD& key); - /*virtual*/ ~LLFloaterLagMeter(); - - void determineClient(); - void determineNetwork(); - void determineServer(); - - static void onClickShrink(void * data); - - bool mShrunk; - S32 mMaxWidth, mMinWidth; - - F32 mClientFrameTimeCritical; - F32 mClientFrameTimeWarning; - LLButton * mClientButton; - LLTextBox * mClientText; - LLTextBox * mClientCause; - - F32 mNetworkPacketLossCritical; - F32 mNetworkPacketLossWarning; - F32 mNetworkPingCritical; - F32 mNetworkPingWarning; - LLButton * mNetworkButton; - LLTextBox * mNetworkText; - LLTextBox * mNetworkCause; - - F32 mServerFrameTimeCritical; - F32 mServerFrameTimeWarning; - F32 mServerSingleProcessMaxTime; - LLButton * mServerButton; - LLTextBox * mServerText; - LLTextBox * mServerCause; - - LLStringUtil::format_map_t mStringArgs; -}; - -#endif diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 80a84820c1..543e56e8f3 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -46,15 +46,16 @@ #include "llagent.h" #include "llagentaccess.h" -#include "llavataractions.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" -#include "llfloaterauction.h" #include "llfloateravatarpicker.h" +#include "llfloaterauction.h" +#include "llfloaterbanduration.h" #include "llfloatergroups.h" #include "llfloaterscriptlimits.h" -#include "llgroupactions.h" +#include "llavataractions.h" +#include "lllayoutstack.h" #include "lllineeditor.h" #include "llnamelistctrl.h" #include "llpanellandaudio.h" @@ -63,6 +64,7 @@ #include "llscrolllistctrl.h" #include "llscrolllistitem.h" #include "llselectmgr.h" +#include "llslurl.h" #include "llspinctrl.h" #include "lltabcontainer.h" #include "lltextbox.h" @@ -80,15 +82,20 @@ #include "roles_constants.h" #include "llworld.h" #include "lltrans.h" +#include "llpanelexperiencelisteditor.h" +#include "llpanelexperiencepicker.h" +#include "llexperiencecache.h" +#include "llgroupactions.h" #include "hippogridmanager.h" - // [RLVa:KB] #include "rlvhandler.h" // [/RLVa:KB] +const F64 COVENANT_REFRESH_TIME_SEC = 60.0f; + static std::string OWNER_ONLINE = "0"; static std::string OWNER_OFFLINE = "1"; static std::string OWNER_GROUP = "2"; @@ -97,17 +104,37 @@ static std::string OWNER_INSIM = "4"; // constants used in callbacks below - syntactic sugar. static const BOOL BUY_GROUP_LAND = TRUE; static const BOOL BUY_PERSONAL_LAND = FALSE; -LLPointer LLPanelLandGeneral::sSelectionForBuyPass = NULL; // Statics LLParcelSelectionObserver* LLFloaterLand::sObserver = NULL; S32 LLFloaterLand::sLastTab = 0; // Local classes -class LLParcelSelectionObserver : public LLParcelObserver +class LLParcelSelectionObserver final : public LLParcelObserver { public: - virtual void changed() { LLFloaterLand::refreshAll(); } + void changed() override { LLFloaterLand::refreshAll(); } +}; + +class LLPanelLandExperiences final + : public LLPanel +{ +public: + LLPanelLandExperiences(LLSafeHandle& parcelp); + BOOL postBuild() override; + void refresh() override; + + void experienceAdded(const LLUUID& id, U32 xp_type, U32 access_type); + void experienceRemoved(const LLUUID& id, U32 access_type); +protected: + void setupList(LLPanelExperienceListEditor* child, const char* control_name, U32 xp_type, U32 access_type ); + void refreshPanel(LLPanelExperienceListEditor* panel, U32 xp_type); + + LLSafeHandle& mParcel; + + + LLPanelExperienceListEditor* mAllowed; + LLPanelExperienceListEditor* mBlocked; }; //--------------------------------------------------------------------------- @@ -202,7 +229,7 @@ void LLFloaterLand::refreshAll() void LLFloaterLand::onOpen() { - // moved from triggering show instance in llviwermenu.cpp + // moved from triggering show instance in llviewermenu.cpp if (LLViewerParcelMgr::getInstance()->selectionEmpty()) { @@ -221,21 +248,16 @@ void LLFloaterLand::onOpen() } -// virtual -void LLFloaterLand::onClose(bool app_quitting) -{ - // Might have been showing owned objects - LLSelectMgr::getInstance()->unhighlightAll(); - - // Save which panel we had open - sLastTab = mTabLand->getCurrentPanelIndex(); - - destroy(); -} - - LLFloaterLand::LLFloaterLand(const LLSD& seed) : LLFloater(std::string("floaterland"), std::string("FloaterLandRect5"), std::string("About Land")) + , mTabLand(nullptr) + , mPanelGeneral(nullptr) + , mPanelObjects(nullptr) + , mPanelOptions(nullptr) + , mPanelMedia(nullptr) + , mPanelAccess(nullptr) + , mPanelCovenant(nullptr) + , mPanelExperiences(nullptr) { mFactoryMap["land_general_panel"] = LLCallbackMap(createPanelLandGeneral, this); mFactoryMap["land_covenant_panel"] = LLCallbackMap(createPanelLandCovenant, this); @@ -244,6 +266,7 @@ LLFloaterLand::LLFloaterLand(const LLSD& seed) mFactoryMap["land_audio_panel"] = LLCallbackMap(createPanelLandAudio, this); mFactoryMap["land_media_panel"] = LLCallbackMap(createPanelLandMedia, this); mFactoryMap["land_access_panel"] = LLCallbackMap(createPanelLandAccess, this); + //mFactoryMap["land_experiences_panel"] = LLCallbackMap(createPanelLandExperiences, this); // We need to buildPanel this, so we call this in postBuild LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about_land.xml", &getFactoryMap(), false); @@ -259,6 +282,8 @@ BOOL LLFloaterLand::postBuild() if (tab) { + if (!gAgent.getRegion()->getCapability("RegionExperiences").empty()) + createPanelLandExperiences(this); // We need to buildPanel this, so call it here instead of during floater building tab->selectTab(sLastTab); } @@ -288,10 +313,9 @@ void LLFloaterLand::refresh() mPanelMedia->refresh(); mPanelAccess->refresh(); mPanelCovenant->refresh(); + if (mPanelExperiences) mPanelExperiences->refresh(); } - - void* LLFloaterLand::createPanelLandGeneral(void* data) { LLFloaterLand* self = (LLFloaterLand*)data; @@ -324,14 +348,6 @@ void* LLFloaterLand::createPanelLandOptions(void* data) return self->mPanelOptions; } -// static -void* LLFloaterLand::createPanelLandAudio(void* data) -{ - LLFloaterLand* self = (LLFloaterLand*)data; - self->mPanelAudio = new LLPanelLandAudio(self->mParcel); - return self->mPanelAudio; -} - // static void* LLFloaterLand::createPanelLandMedia(void* data) { @@ -348,71 +364,110 @@ void* LLFloaterLand::createPanelLandAccess(void* data) return self->mPanelAccess; } +// static +void* LLFloaterLand::createPanelLandAudio(void* data) +{ + LLFloaterLand* self = (LLFloaterLand*)data; + self->mPanelAudio = new LLPanelLandAudio(self->mParcel); + return self->mPanelAudio; +} + +// static +void* LLFloaterLand::createPanelLandExperiences(void* data) +{ + LLFloaterLand* self = static_cast(data); + self->mPanelExperiences = new LLPanelLandExperiences(self->mParcel); + self->mTabLand->addTabPanel(self->mPanelExperiences, self->mPanelExperiences->getLabel()); // We must build this panel separately from the floater xml, so add it to the tab container manually. + return self->mPanelExperiences; +} + + +LLPointer LLPanelLandGeneral::sSelectionForBuyPass = NULL; + //--------------------------------------------------------------------------- // LLPanelLandGeneral //--------------------------------------------------------------------------- LLPanelLandGeneral::LLPanelLandGeneral(LLParcelSelectionHandle& parcel) -: LLPanel(std::string("land_general_panel")), - mUncheckedSell(FALSE), - mParcel(parcel) + : LLPanel(std::string("land_general_panel")) + , mEditName(nullptr) + , mEditDesc(nullptr) + , mTextSalePending(nullptr) + , mBtnDeedToGroup(nullptr) + , mBtnSetGroup(nullptr) + , mTextOwner(nullptr) + , mContentRating(nullptr) + , mLandType(nullptr) + , mTextGroup(nullptr) + , mTextClaimDate(nullptr) + , mTextPriceLabel(nullptr) + , mTextPrice(nullptr) + , mCheckDeedToGroup(nullptr) + , mCheckContributeWithDeed(nullptr) + , mSaleInfoForSale1(nullptr) + , mSaleInfoForSale2(nullptr) + , mSaleInfoForSaleObjects(nullptr) + , mSaleInfoForSaleNoObjects(nullptr) + , mSaleInfoNotForSale(nullptr) + , mBtnSellLand(nullptr) + , mBtnStopSellLand(nullptr) + , mTextDwell(nullptr) + , mBtnBuyLand(nullptr) + , mBtnScriptLimits(nullptr) + , mBtnBuyGroupLand(nullptr) + , mBtnReleaseLand(nullptr) + , mBtnReclaimLand(nullptr) + , mBtnBuyPass(nullptr) + , mBtnStartAuction(nullptr) + , mParcel(parcel) { } BOOL LLPanelLandGeneral::postBuild() { mEditName = getChild("Name"); - mEditName->setCommitCallback(onCommitAny, this); + mEditName->setCommitCallback(boost::bind(&LLPanelLandGeneral::onCommitAny, this)); getChild("Name")->setPrevalidate(LLLineEditor::prevalidatePrintableNotPipe); mEditDesc = getChild("Description"); mEditDesc->setCommitOnFocusLost(TRUE); - mEditDesc->setCommitCallback(onCommitAny, this); + mEditDesc->setCommitCallback(boost::bind(&LLPanelLandGeneral::onCommitAny, this)); // No prevalidate function - historically the prevalidate function was broken, // allowing residents to put in characters like U+2661 WHITE HEART SUIT, so // preserve that ability. mTextSalePending = getChild("SalePending"); - mTextOwnerLabel = getChild("Owner:"); mTextOwner = getChild("OwnerText"); mContentRating = getChild("ContentRatingText"); mLandType = getChild("LandTypeText"); - - mBtnProfile = getChild("Profile..."); - mBtnProfile->setClickedCallback(boost::bind(&LLPanelLandGeneral::onClickProfile, this)); - - mTextGroupLabel = getChild("Group:"); mTextGroup = getChild("GroupText"); mBtnSetGroup = getChild("Set..."); mBtnSetGroup->setCommitCallback(boost::bind(&LLPanelLandGeneral::onClickSetGroup, this)); - getChild("group_profile")->setClickedCallback(onClickInfoGroup, this); - mCheckDeedToGroup = getChild( "check deed"); - childSetCommitCallback("check deed", onCommitAny, this); + mCheckDeedToGroup->setCommitCallback(boost::bind(&LLPanelLandGeneral::onCommitAny, this)); mBtnDeedToGroup = getChild("Deed..."); - mBtnDeedToGroup->setClickedCallback(onClickDeed, this); + mBtnDeedToGroup->setCommitCallback(boost::bind(&LLPanelLandGeneral::onClickDeed, this)); mCheckContributeWithDeed = getChild( "check contrib"); - childSetCommitCallback("check contrib", onCommitAny, this); + mCheckContributeWithDeed->setCommitCallback(boost::bind(&LLPanelLandGeneral::onCommitAny, this)); - mSaleInfoNotForSale = getChild("Not for sale."); mSaleInfoForSale1 = getChild("For Sale: Price L$[PRICE]."); mBtnSellLand = getChild("Sell Land..."); - mBtnSellLand->setClickedCallback(onClickSellLand, this); + mBtnSellLand->setCommitCallback(boost::bind(&LLPanelLandGeneral::onClickSellLand, this)); mSaleInfoForSale2 = getChild("For sale to"); @@ -422,10 +477,9 @@ BOOL LLPanelLandGeneral::postBuild() mBtnStopSellLand = getChild("Cancel Land Sale"); - mBtnStopSellLand->setClickedCallback(onClickStopSellLand, this); + mBtnStopSellLand->setCommitCallback(boost::bind(&LLPanelLandGeneral::onClickStopSellLand, this)); - mTextClaimDateLabel = getChild("Claimed:"); mTextClaimDate = getChild("DateClaimText"); @@ -438,43 +492,49 @@ BOOL LLPanelLandGeneral::postBuild() mBtnBuyLand = getChild("Buy Land..."); mBtnBuyLand->setClickedCallback(onClickBuyLand, (void*)&BUY_PERSONAL_LAND); + + mBtnBuyGroupLand = getChild("Buy For Group..."); + mBtnBuyGroupLand->setClickedCallback(onClickBuyLand, (void*)&BUY_GROUP_LAND); + + + mBtnBuyPass = getChild("Buy Pass..."); + mBtnBuyPass->setClickedCallback(onClickBuyPass, this); + + mBtnReleaseLand = getChild("Abandon Land..."); + mBtnReleaseLand->setCommitCallback(boost::bind(&LLPanelLandGeneral::onClickRelease, this)); + + mBtnReclaimLand = getChild("Reclaim Land..."); + mBtnReclaimLand->setCommitCallback(boost::bind(&LLPanelLandGeneral::onClickReclaim, this)); + + mBtnStartAuction = getChild("Linden Sale..."); + mBtnStartAuction->setCommitCallback(boost::bind(&LLPanelLandGeneral::onClickStartAuction, this)); + + mBtnScriptLimits = getChild("Scripts..."); + + if(gDisconnected) + { + return TRUE; + } + // note: on region change this will not be re checked, should not matter on Agni as // 99% of the time all regions will return the same caps. In case of an erroneous setting // to enabled the floater will just throw an error when trying to get it's cap - std::string url = gAgent.getRegion()->getCapability("LandResources"); + std::string url = gAgent.getRegionCapability("LandResources"); if (!url.empty()) { - mBtnScriptLimits = getChild("Scripts..."); if(mBtnScriptLimits) { - mBtnScriptLimits->setClickedCallback(onClickScriptLimits, this); + mBtnScriptLimits->setCommitCallback(boost::bind(&LLPanelLandGeneral::onClickScriptLimits, this)); } } else { - mBtnScriptLimits = getChild("Scripts..."); if(mBtnScriptLimits) { mBtnScriptLimits->setVisible(false); } } - mBtnBuyGroupLand = getChild("Buy For Group..."); - mBtnBuyGroupLand->setClickedCallback(onClickBuyLand, (void*)&BUY_GROUP_LAND); - - - mBtnBuyPass = getChild("Buy Pass..."); - mBtnBuyPass->setClickedCallback(onClickBuyPass, this); - - mBtnReleaseLand = getChild("Abandon Land..."); - mBtnReleaseLand->setClickedCallback(onClickRelease, NULL); - - mBtnReclaimLand = getChild("Reclaim Land..."); - mBtnReclaimLand->setClickedCallback(onClickReclaim, NULL); - - mBtnStartAuction = getChild("Linden Sale..."); - mBtnStartAuction->setClickedCallback(onClickStartAuction, this); - return TRUE; } @@ -487,9 +547,56 @@ LLPanelLandGeneral::~LLPanelLandGeneral() // public void LLPanelLandGeneral::refresh() { - mBtnStartAuction->setVisible(gAgent.isGodlike()); + mEditName->setEnabled(FALSE); + mEditName->setText(LLStringUtil::null); - LLParcel *parcel = mParcel->getParcel(); + mEditDesc->setEnabled(FALSE); + mEditDesc->setText(getString("no_selection_text")); + + mTextSalePending->setText(LLStringUtil::null); + mTextSalePending->setEnabled(FALSE); + + mBtnDeedToGroup->setEnabled(FALSE); + mBtnSetGroup->setEnabled(FALSE); + mBtnStartAuction->setEnabled(FALSE); + + mCheckDeedToGroup ->set(FALSE); + mCheckDeedToGroup ->setEnabled(FALSE); + mCheckContributeWithDeed->set(FALSE); + mCheckContributeWithDeed->setEnabled(FALSE); + + mTextOwner->setValue(LLUUID::null); + mContentRating->setText(LLStringUtil::null); + mLandType->setText(LLStringUtil::null); + + mTextClaimDate->setText(LLStringUtil::null); + mTextGroup->setValue(LLUUID::null); + mTextPrice->setText(LLStringUtil::null); + + mSaleInfoForSale1->setVisible(FALSE); + mSaleInfoForSale2->setVisible(FALSE); + mSaleInfoForSaleObjects->setVisible(FALSE); + mSaleInfoForSaleNoObjects->setVisible(FALSE); + mSaleInfoNotForSale->setVisible(FALSE); + mBtnSellLand->setVisible(FALSE); + mBtnStopSellLand->setVisible(FALSE); + + mTextPriceLabel->setText(LLStringUtil::null); + mTextDwell->setText(LLStringUtil::null); + + mBtnBuyLand->setEnabled(FALSE); + mBtnScriptLimits->setEnabled(FALSE); + mBtnBuyGroupLand->setEnabled(FALSE); + mBtnReleaseLand->setEnabled(FALSE); + mBtnReclaimLand->setEnabled(FALSE); + mBtnBuyPass->setEnabled(FALSE); + + if(gDisconnected) + { + return; + } + + mBtnStartAuction->setVisible(gAgent.isGodlike()); bool region_owner = false; LLViewerRegion* regionp = LLViewerParcelMgr::getInstance()->getSelectionRegion(); if(regionp && (regionp->getOwner() == gAgent.getID())) @@ -503,62 +610,14 @@ void LLPanelLandGeneral::refresh() mBtnReleaseLand->setVisible(TRUE); mBtnReclaimLand->setVisible(FALSE); } - if (!parcel) - { - // nothing selected, disable panel - mEditName->setEnabled(FALSE); - mEditName->setText(LLStringUtil::null); - - mEditDesc->setEnabled(FALSE); - mEditDesc->setText(getString("no_selection_text")); - - mTextSalePending->setText(LLStringUtil::null); - mTextSalePending->setEnabled(FALSE); - - mBtnDeedToGroup->setEnabled(FALSE); - mBtnSetGroup->setEnabled(FALSE); - mBtnStartAuction->setEnabled(FALSE); - - mCheckDeedToGroup ->set(FALSE); - mCheckDeedToGroup ->setEnabled(FALSE); - mCheckContributeWithDeed->set(FALSE); - mCheckContributeWithDeed->setEnabled(FALSE); - - mTextOwner->setText(LLStringUtil::null); - mContentRating->setText(LLStringUtil::null); - mLandType->setText(LLStringUtil::null); - mBtnProfile->setLabel(getString("profile_text")); - mBtnProfile->setEnabled(FALSE); - - mTextClaimDate->setText(LLStringUtil::null); - mTextGroup->setText(LLStringUtil::null); - mTextPrice->setText(LLStringUtil::null); - - mSaleInfoForSale1->setVisible(FALSE); - mSaleInfoForSale2->setVisible(FALSE); - mSaleInfoForSaleObjects->setVisible(FALSE); - mSaleInfoForSaleNoObjects->setVisible(FALSE); - mSaleInfoNotForSale->setVisible(FALSE); - mBtnSellLand->setVisible(FALSE); - mBtnStopSellLand->setVisible(FALSE); - - mTextPriceLabel->setText(LLStringUtil::null); - mTextDwell->setText(LLStringUtil::null); - - mBtnBuyLand->setEnabled(FALSE); - mBtnScriptLimits->setEnabled(FALSE); - mBtnBuyGroupLand->setEnabled(FALSE); - mBtnReleaseLand->setEnabled(FALSE); - mBtnReclaimLand->setEnabled(FALSE); - mBtnBuyPass->setEnabled(FALSE); - } - else + LLParcel *parcel = mParcel->getParcel(); + if (parcel) { // something selected, hooray! BOOL is_leased = (LLParcel::OS_LEASED == parcel->getOwnershipStatus()); BOOL region_xfer = FALSE; if(regionp - && !regionp->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL)) + && !(regionp->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL))) { region_xfer = TRUE; } @@ -581,16 +640,19 @@ void LLPanelLandGeneral::refresh() BOOL can_be_sold = owner_sellable || estate_manager_sellable; const LLUUID &owner_id = parcel->getOwnerID(); + const LLUUID& group_id = parcel->getGroupID(); BOOL is_public = parcel->isPublic(); + bool group_owned = parcel->getIsGroupOwned(); // Is it owned? + mTextOwner->setValue(is_public ? LLSD(LLUUID::null) : LLSD().with("id", owner_id).with("type", group_owned ? LFIDBearer::GROUP : LFIDBearer::AVATAR)); + mTextGroup->setValue(is_public ? LLUUID::null : group_id); if (is_public) { mTextSalePending->setText(LLStringUtil::null); mTextSalePending->setEnabled(FALSE); mTextOwner->setText(getString("public_text")); mTextOwner->setEnabled(FALSE); - mBtnProfile->setEnabled(FALSE); mTextClaimDate->setText(LLStringUtil::null); mTextClaimDate->setEnabled(FALSE); mTextGroup->setText(getString("none_text")); @@ -620,21 +682,13 @@ void LLPanelLandGeneral::refresh() mTextOwner->setEnabled(TRUE); // We support both group and personal profiles - mBtnProfile->setEnabled(TRUE); - - if (parcel->getGroupID().isNull()) + if (group_id.isNull()) { - // Not group owned, so "Profile" - mBtnProfile->setLabel(getString("profile_text")); - mTextGroup->setText(getString("none_text")); mTextGroup->setEnabled(FALSE); } else { - // Group owned, so "Info" - mBtnProfile->setLabel(getString("info_text")); - //mTextGroup->setText("HIPPOS!");//parcel->getGroupName()); mTextGroup->setEnabled(TRUE); } @@ -657,9 +711,7 @@ void LLPanelLandGeneral::refresh() mEditDesc->setEnabled(can_edit_identity); BOOL can_edit_agent_only = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_NO_POWERS); - mBtnSetGroup->setEnabled(can_edit_agent_only && !parcel->getIsGroupOwned()); - - const LLUUID& group_id = parcel->getGroupID(); + mBtnSetGroup->setEnabled(can_edit_agent_only && !group_owned); // Can only allow deeding if you own it and it's got a group. BOOL enable_deed = (owner_id == gAgent.getID() @@ -678,11 +730,11 @@ void LLPanelLandGeneral::refresh() mBtnDeedToGroup->setEnabled( parcel->getAllowDeedToGroup() && group_id.notNull() && can_deed - && !parcel->getIsGroupOwned() + && !group_owned ); mEditName->setText( parcel->getName() ); - mEditDesc->setText( parcel->getDesc() ); + mEditDesc->setText( parcel->getDesc(), false ); BOOL for_sale = parcel->getForSale(); @@ -763,6 +815,7 @@ void LLPanelLandGeneral::refresh() mBtnBuyLand->setEnabled( LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false)); mBtnScriptLimits->setEnabled(true); +// LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false)); mBtnBuyGroupLand->setEnabled( LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, true)); @@ -793,34 +846,24 @@ void LLPanelLandGeneral::refreshNames() LLParcel *parcel = mParcel->getParcel(); if (!parcel) { - mTextOwner->setText(LLStringUtil::null); - mTextGroup->setText(LLStringUtil::null); + mTextOwner->setValue(LLUUID::null); + mTextGroup->setValue(LLUUID::null); return; } - std::string owner; - if (parcel->getIsGroupOwned()) + bool group_owned = parcel->getIsGroupOwned(); + mTextOwner->setValue(LLSD().with("id", parcel->getOwnerID()).with("type", group_owned ? LFIDBearer::GROUP : LFIDBearer::AVATAR)); + if (group_owned) { - owner = getString("group_owned_text"); - } - else - { - // Figure out the owner's name - gCacheName->getFullName(parcel->getOwnerID(), owner); + mTextOwner->setText(getString("group_owned_text")); } if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus()) { - owner += getString("sale_pending_text"); + mTextOwner->setText(mTextOwner->getText() + getString("sale_pending_text")); } - mTextOwner->setText(owner); - std::string group; - if (!parcel->getGroupID().isNull()) - { - gCacheName->getGroupName(parcel->getGroupID(), group); - } - mTextGroup->setText(group); + mTextGroup->setValue(parcel->getGroupID()); if (parcel->getForSale()) { @@ -838,13 +881,6 @@ void LLPanelLandGeneral::refreshNames() } } - -// virtual -void LLPanelLandGeneral::draw() -{ - LLPanel::draw(); -} - void LLPanelLandGeneral::onClickSetGroup() { LLFloater* parent_floater = gFloaterView->getParentFloater(this); @@ -862,32 +898,6 @@ void LLPanelLandGeneral::onClickSetGroup() } } -// static -void LLPanelLandGeneral::onClickInfoGroup(void* userdata) -{ - LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)userdata; - LLParcel* parcel = panelp->mParcel->getParcel(); - if (!parcel) return; - LLGroupActions::show(parcel->getGroupID()); -} - -void LLPanelLandGeneral::onClickProfile() -{ - LLParcel* parcel = mParcel->getParcel(); - if (!parcel) return; - - if (parcel->getIsGroupOwned()) - { - const LLUUID& group_id = parcel->getGroupID(); - LLGroupActions::show(group_id); - } - else - { - const LLUUID& avatar_id = parcel->getOwnerID(); - LLAvatarActions::showProfile(avatar_id); - } -} - // public void LLPanelLandGeneral::setGroup(const LLUUID& group_id) { @@ -897,7 +907,6 @@ void LLPanelLandGeneral::setGroup(const LLUUID& group_id) // Set parcel properties and send message parcel->setGroupID(group_id); //parcel->setGroupName(group_name); - //mTextGroup->setText(group_name); // Send update LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate(parcel); @@ -913,19 +922,16 @@ void LLPanelLandGeneral::onClickBuyLand(void* data) LLViewerParcelMgr::getInstance()->startBuyLand(*for_group); } -// static -void LLPanelLandGeneral::onClickScriptLimits(void* data) +void LLPanelLandGeneral::onClickScriptLimits() { - LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if(parcel != NULL) { LLFloaterScriptLimits::showInstance(); } } -// static -void LLPanelLandGeneral::onClickDeed(void*) +void LLPanelLandGeneral::onClickDeed() { //LLParcel* parcel = mParcel->getParcel(); //if (parcel) @@ -934,14 +940,12 @@ void LLPanelLandGeneral::onClickDeed(void*) //} } -// static -void LLPanelLandGeneral::onClickRelease(void*) +void LLPanelLandGeneral::onClickRelease() { LLViewerParcelMgr::getInstance()->startReleaseLand(); } -// static -void LLPanelLandGeneral::onClickReclaim(void*) +void LLPanelLandGeneral::onClickReclaim() { LL_DEBUGS() << "LLPanelLandGeneral::onClickReclaim()" << LL_ENDL; LLViewerParcelMgr::getInstance()->reclaimParcel(); @@ -983,11 +987,9 @@ void LLPanelLandGeneral::onClickBuyPass(void* data) LLNotificationsUtil::add("LandBuyPass", args, LLSD(), cbBuyPass); } -// static -void LLPanelLandGeneral::onClickStartAuction(void* data) +void LLPanelLandGeneral::onClickStartAuction() { - LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; - LLParcel* parcelp = panelp->mParcel->getParcel(); + LLParcel* parcelp = mParcel->getParcel(); if(parcelp) { if(parcelp->getForSale()) @@ -1015,20 +1017,17 @@ bool LLPanelLandGeneral::cbBuyPass(const LLSD& notification, const LLSD& respons return false; } -// static -void LLPanelLandGeneral::onCommitAny(LLUICtrl *ctrl, void *userdata) +void LLPanelLandGeneral::onCommitAny() { - LLPanelLandGeneral *panelp = (LLPanelLandGeneral *)userdata; - - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) { return; } // Extract data from UI - std::string name = panelp->mEditName->getText(); - std::string desc = panelp->mEditDesc->getText(); + std::string name = mEditName->getText(); + std::string desc = mEditDesc->getText(); // Valid data from UI @@ -1036,8 +1035,8 @@ void LLPanelLandGeneral::onCommitAny(LLUICtrl *ctrl, void *userdata) parcel->setName(name); parcel->setDesc(desc); - BOOL allow_deed_to_group= panelp->mCheckDeedToGroup->get(); - BOOL contribute_with_deed = panelp->mCheckContributeWithDeed->get(); + BOOL allow_deed_to_group= mCheckDeedToGroup->get(); + BOOL contribute_with_deed = mCheckContributeWithDeed->get(); parcel->setParcelFlag(PF_ALLOW_DEED_TO_GROUP, allow_deed_to_group); parcel->setContributeWithDeed(contribute_with_deed); @@ -1046,20 +1045,18 @@ void LLPanelLandGeneral::onCommitAny(LLUICtrl *ctrl, void *userdata) LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); // Might have changed properties, so let's redraw! - panelp->refresh(); + refresh(); } -// static -void LLPanelLandGeneral::onClickSellLand(void* data) +void LLPanelLandGeneral::onClickSellLand() { LLViewerParcelMgr::getInstance()->startSellLand(); + refresh(); } -// static -void LLPanelLandGeneral::onClickStopSellLand(void* data) +void LLPanelLandGeneral::onClickStopSellLand() { - LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); parcel->setParcelFlag(PF_FOR_SALE, FALSE); parcel->setSalePrice(0); @@ -1073,7 +1070,7 @@ void LLPanelLandGeneral::onClickStopSellLand(void* data) //--------------------------------------------------------------------------- LLPanelLandObjects::LLPanelLandObjects(LLParcelSelectionHandle& parcel) : LLPanel(std::string("land_objects_panel")), - mParcel(parcel), + mParcelObjectBonus(NULL), mSWTotalObjects(NULL), mObjectContribution(NULL), @@ -1095,7 +1092,8 @@ LLPanelLandObjects::LLPanelLandObjects(LLParcelSelectionHandle& parcel) mOwnerList(NULL), mFirstReply(TRUE), mSelectedCount(0), - mSelectedIsGroup(FALSE) + mSelectedIsGroup(FALSE), + mParcel(parcel) { } @@ -1103,7 +1101,6 @@ LLPanelLandObjects::LLPanelLandObjects(LLParcelSelectionHandle& parcel) BOOL LLPanelLandObjects::postBuild() { - mFirstReply = TRUE; mParcelObjectBonus = getChild("parcel_object_bonus"); mSWTotalObjects = getChild("objects_available"); @@ -1112,37 +1109,37 @@ BOOL LLPanelLandObjects::postBuild() mOwnerObjects = getChild("owner_objects_text"); mBtnShowOwnerObjects = getChild("ShowOwner"); - mBtnShowOwnerObjects->setClickedCallback(onClickShowOwnerObjects, this); + mBtnShowOwnerObjects->setCommitCallback(boost::bind(&LLPanelLandObjects::onClickShowOwnerObjects, this)); mBtnReturnOwnerObjects = getChild("ReturnOwner..."); - mBtnReturnOwnerObjects->setClickedCallback(onClickReturnOwnerObjects, this); + mBtnReturnOwnerObjects->setCommitCallback(boost::bind(&LLPanelLandObjects::onClickReturnOwnerObjects, this)); mGroupObjects = getChild("group_objects_text"); mBtnShowGroupObjects = getChild("ShowGroup"); - mBtnShowGroupObjects->setClickedCallback(onClickShowGroupObjects, this); + mBtnShowGroupObjects->setCommitCallback(boost::bind(&LLPanelLandObjects::onClickShowGroupObjects, this)); mBtnReturnGroupObjects = getChild("ReturnGroup..."); - mBtnReturnGroupObjects->setClickedCallback(onClickReturnGroupObjects, this); + mBtnReturnGroupObjects->setCommitCallback(boost::bind(&LLPanelLandObjects::onClickReturnGroupObjects, this)); mOtherObjects = getChild("other_objects_text"); mBtnShowOtherObjects = getChild("ShowOther"); - mBtnShowOtherObjects->setClickedCallback(onClickShowOtherObjects, this); + mBtnShowOtherObjects->setCommitCallback(boost::bind(&LLPanelLandObjects::onClickShowOtherObjects, this)); mBtnReturnOtherObjects = getChild("ReturnOther..."); - mBtnReturnOtherObjects->setClickedCallback(onClickReturnOtherObjects, this); + mBtnReturnOtherObjects->setCommitCallback(boost::bind(&LLPanelLandObjects::onClickReturnOtherObjects, this)); mSelectedObjects = getChild("selected_objects_text"); mCleanOtherObjectsTime = getChild("clean other time"); mCleanOtherObjectsTime->setFocusLostCallback(boost::bind(&LLPanelLandObjects::onLostFocus, _1, this)); - mCleanOtherObjectsTime->setCommitCallback(onCommitClean, this); + mCleanOtherObjectsTime->setCommitCallback(boost::bind(&LLPanelLandObjects::onCommitClean, this)); mCleanOtherObjectsTime->setPrevalidate(LLLineEditor::prevalidateNonNegativeS32); mBtnRefresh = getChild("Refresh List"); - mBtnRefresh->setClickedCallback(onClickRefresh, this); + mBtnRefresh->setCommitCallback(boost::bind(&LLPanelLandObjects::onClickRefresh, this)); mBtnReturnOwnerList = getChild("Return objects..."); - mBtnReturnOwnerList->setClickedCallback(onClickReturnOwnerList, this); + mBtnReturnOwnerList->setCommitCallback(boost::bind(&LLPanelLandObjects::onClickReturnOwnerList, this)); mIconAvatarOnline = LLUI::getUIImage("icon_avatar_online.tga"); mIconAvatarInSim = LLUI::getUIImage("ff_visible_map.tga"); @@ -1152,46 +1149,16 @@ BOOL LLPanelLandObjects::postBuild() mOwnerList = getChild("owner list"); mOwnerList->sortByColumnIndex(3, FALSE); mOwnerList->setCommitCallback(boost::bind(&LLPanelLandObjects::onCommitList,this)); - mOwnerList->setDoubleClickCallback(boost::bind(&LLPanelLandObjects::onDoubleClickOwner, this)); return TRUE; } - - - // virtual LLPanelLandObjects::~LLPanelLandObjects() { } -// static -void LLPanelLandObjects::onDoubleClickOwner(void *userdata) -{ - LLPanelLandObjects *self = (LLPanelLandObjects *)userdata; - LLScrollListItem* item = self->mOwnerList->getFirstSelected(); - if (item) - { - LLUUID owner_id = item->getUUID(); - // Look up the selected name, for future dialog box use. - const LLScrollListCell* cell; - cell = item->getColumn(1); - if (!cell) - { - return; - } - // Is this a group? - BOOL is_group = cell->getValue().asString() == OWNER_GROUP; - if (is_group) - { - LLGroupActions::show(owner_id); - } - else - { - LLAvatarActions::showProfile(owner_id); - } - } -} +const LLStringExplicit zero_str("0"); // public void LLPanelLandObjects::refresh() @@ -1212,17 +1179,17 @@ void LLPanelLandObjects::refresh() mOwnerList->deleteAllItems(); mOwnerList->setEnabled(FALSE); - if (!parcel) + if (!parcel || gDisconnected) { - mSWTotalObjects->setTextArg("[COUNT]", llformat("%d", 0)); - mSWTotalObjects->setTextArg("[TOTAL]", llformat("%d", 0)); - mSWTotalObjects->setTextArg("[AVAILABLE]", llformat("%d", 0)); - mObjectContribution->setTextArg("[COUNT]", llformat("%d", 0)); - mTotalObjects->setTextArg("[COUNT]", llformat("%d", 0)); - mOwnerObjects->setTextArg("[COUNT]", llformat("%d", 0)); - mGroupObjects->setTextArg("[COUNT]", llformat("%d", 0)); - mOtherObjects->setTextArg("[COUNT]", llformat("%d", 0)); - mSelectedObjects->setTextArg("[COUNT]", llformat("%d", 0)); + mSWTotalObjects->setTextArg("[COUNT]", zero_str); + mSWTotalObjects->setTextArg("[TOTAL]", zero_str); + mSWTotalObjects->setTextArg("[AVAILABLE]", zero_str); + mObjectContribution->setTextArg("[COUNT]", zero_str); + mTotalObjects->setTextArg("[COUNT]", zero_str); + mOwnerObjects->setTextArg("[COUNT]", zero_str); + mGroupObjects->setTextArg("[COUNT]", zero_str); + mOtherObjects->setTextArg("[COUNT]", zero_str); + mSelectedObjects->setTextArg("[COUNT]", zero_str); } else { @@ -1306,12 +1273,6 @@ void LLPanelLandObjects::refresh() } } -// virtual -void LLPanelLandObjects::draw() -{ - LLPanel::draw(); -} - void send_other_clean_time_message(S32 parcel_local_id, S32 other_clean_time) { LLMessageSystem *msg = gMessageSystem; @@ -1330,6 +1291,7 @@ void send_other_clean_time_message(S32 parcel_local_id, S32 other_clean_time) msg->sendReliable(region->getHost()); } + void send_return_objects_message(S32 parcel_local_id, S32 return_type, uuid_list_t* owner_ids = NULL) { @@ -1388,9 +1350,7 @@ bool LLPanelLandObjects::callbackReturnOwnerObjects(const LLSD& notification, co } else { - std::string full_name; - gCacheName->getFullName(owner_id, full_name); - args["NAME"] = full_name; + args["NAME"] = LLSLURL("agent", owner_id, "completename").getSLURLString(); LLNotificationsUtil::add("OtherObjectsReturned", args); } send_return_objects_message(parcel->getLocalID(), RT_OWNER); @@ -1477,57 +1437,49 @@ bool LLPanelLandObjects::callbackReturnOwnerList(const LLSD& notification, const return false; } - -// static -void LLPanelLandObjects::onClickReturnOwnerList(void* userdata) +void LLPanelLandObjects::onClickReturnOwnerList() { - LLPanelLandObjects *self = (LLPanelLandObjects *)userdata; - - LLParcel* parcelp = self->mParcel->getParcel(); + LLParcel* parcelp = mParcel->getParcel(); if (!parcelp) return; // Make sure we have something selected. - if (self->mSelectedOwners.empty()) + if (mSelectedOwners.empty()) { return; } //uuid_list_t::iterator selected_itr = self->mSelectedOwners.begin(); //if (selected_itr == self->mSelectedOwners.end()) return; - send_parcel_select_objects(parcelp->getLocalID(), RT_LIST, &(self->mSelectedOwners)); + send_parcel_select_objects(parcelp->getLocalID(), RT_LIST, &mSelectedOwners); LLSD args; - args["NAME"] = self->mSelectedName; - args["N"] = llformat("%d",self->mSelectedCount); - if (self->mSelectedIsGroup) + args["NAME"] = mSelectedName; + args["N"] = fmt::to_string(mSelectedCount); + if (mSelectedIsGroup) { - LLNotificationsUtil::add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, this, _1, _2)); } else { - LLNotificationsUtil::add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, this, _1, _2)); } } - -// static -void LLPanelLandObjects::onClickRefresh(void* userdata) +void LLPanelLandObjects::onClickRefresh() { - LLPanelLandObjects *self = (LLPanelLandObjects*)userdata; - LLMessageSystem *msg = gMessageSystem; - LLParcel* parcel = self->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) return; LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); if (!region) return; // ready the list for results - self->mOwnerList->deleteAllItems(); - self->mOwnerList->setCommentText(LLTrans::getString("Searching")); - self->mOwnerList->setEnabled(FALSE); - self->mFirstReply = TRUE; + mOwnerList->deleteAllItems(); + mOwnerList->setCommentText(LLTrans::getString("Searching")); + mOwnerList->setEnabled(FALSE); + mFirstReply = TRUE; // send the message msg->newMessageFast(_PREHASH_ParcelObjectOwnersRequest); @@ -1543,7 +1495,7 @@ void LLPanelLandObjects::onClickRefresh(void* userdata) // static void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, void **) { - LLPanelLandObjects* self = LLFloaterLand::getCurrentPanelLandObjects(); + LLPanelLandObjects* self = LLFloaterLand::getInstance()->mPanelObjects; if (!self) { @@ -1552,7 +1504,7 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo return; } - const std::string FONT = "SANSSERIF"; + constexpr auto&& FONT = "SANSSERIF"; // Extract all of the owners. S32 rows = msg->getNumberOfBlocksFast(_PREHASH_Data); @@ -1572,10 +1524,6 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo self->mFirstReply = FALSE; } - LLVector3d mypos = gAgent.getPositionGlobal(); - std::vector avatar_ids; - LLWorld::instance().getAvatars(&avatar_ids, NULL, mypos, F32_MAX); - for(S32 i = 0; i < rows; ++i) { msg->getUUIDFast(_PREHASH_Data, _PREHASH_OwnerID, owner_id, i); @@ -1586,23 +1534,25 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo { msg->getU32("DataExtended", "TimeStamp", most_recent_time, i); } + if (owner_id.isNull()) { continue; } - BOOL in_sim = (std::find(avatar_ids.begin(), avatar_ids.end(), owner_id) != avatar_ids.end()); - LLNameListCtrl::NameItem item_params; item_params.value = owner_id; - item_params.target = is_group_owned ? LLNameListCtrl::GROUP : LLNameListCtrl::INDIVIDUAL; + item_params.target = is_group_owned ? LLNameListItem::GROUP : LLNameListItem::INDIVIDUAL; + + uuid_vec_t avatar_ids; + LLWorld::instance().getAvatars(&avatar_ids, nullptr, gAgent.getPositionGlobal(), F32_MAX); if (is_group_owned) { item_params.columns.add().type("icon").value(self->mIconGroup->getName()).column("type"); item_params.columns.add().value(OWNER_GROUP).font(FONT).column("online_status"); } - else if (in_sim) + else if (std::find(avatar_ids.begin(), avatar_ids.end(), owner_id) != avatar_ids.end()) { item_params.columns.add().type("icon").value(self->mIconAvatarInSim->getName()).column("type"); item_params.columns.add().value(OWNER_INSIM).font(FONT).column("online_status"); @@ -1628,10 +1578,10 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo item_params.columns.add().value(LLDate((time_t)most_recent_time)).font(FONT).column("mostrecent").type("date"); self->mOwnerList->addNameItemRow(item_params); - LL_DEBUGS() << "object owner " << owner_id << " (" << (is_group_owned ? "group" : "agent") << ") owns " << object_count << " objects." << LL_ENDL; } + // check for no results if (0 == self->mOwnerList->getItemCount()) { @@ -1643,9 +1593,10 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo } } +// static void LLPanelLandObjects::onCommitList() { - if (FALSE == mOwnerList->getCanSelect()) + if (mOwnerList->getCanSelect() == FALSE) { return; } @@ -1664,7 +1615,7 @@ void LLPanelLandObjects::onCommitList() cell = item->getColumn(2); mSelectedName = cell->getValue().asString(); cell = item->getColumn(3); - mSelectedCount = atoi(cell->getValue().asString().c_str()); + mSelectedCount = std::stoi(cell->getValue().asString()); // Set the selection, and enable the return button. mSelectedOwners.clear(); @@ -1672,7 +1623,7 @@ void LLPanelLandObjects::onCommitList() mBtnReturnOwnerList->setEnabled(TRUE); // Highlight this user's objects - clickShowCore(this, RT_LIST, &(mSelectedOwners)); + clickShowCore(this, RT_LIST, &mSelectedOwners); } } @@ -1685,31 +1636,26 @@ void LLPanelLandObjects::clickShowCore(LLPanelLandObjects* self, S32 return_type send_parcel_select_objects(parcel->getLocalID(), return_type, list); } -// static -void LLPanelLandObjects::onClickShowOwnerObjects(void* userdata) +void LLPanelLandObjects::onClickShowOwnerObjects() { - clickShowCore((LLPanelLandObjects*)userdata, RT_OWNER); + clickShowCore(this, RT_OWNER); } -// static -void LLPanelLandObjects::onClickShowGroupObjects(void* userdata) +void LLPanelLandObjects::onClickShowGroupObjects() { - clickShowCore((LLPanelLandObjects*)userdata, (RT_GROUP)); + clickShowCore(this, (RT_GROUP)); } -// static -void LLPanelLandObjects::onClickShowOtherObjects(void* userdata) +void LLPanelLandObjects::onClickShowOtherObjects() { - clickShowCore((LLPanelLandObjects*)userdata, RT_OTHER); + clickShowCore(this, RT_OTHER); } -// static -void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata) +void LLPanelLandObjects::onClickReturnOwnerObjects() { S32 owned = 0; - LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata; - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) return; owned = parcel->getOwnerPrimCount(); @@ -1719,26 +1665,22 @@ void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata) LLUUID owner_id = parcel->getOwnerID(); LLSD args; - args["N"] = llformat("%d",owned); + args["N"] = fmt::to_string(owned); if (owner_id == gAgent.getID()) { - LLNotificationsUtil::add("ReturnObjectsOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, this, _1, _2)); } else { - std::string name; - gCacheName->getFullName(owner_id, name); - args["NAME"] = name; - LLNotificationsUtil::add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2)); + args["NAME"] = LLSLURL("agent", owner_id, "completename").getSLURLString(); + LLNotificationsUtil::add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, this, _1, _2)); } } -// static -void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata) +void LLPanelLandObjects::onClickReturnGroupObjects() { - LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata; - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) return; send_parcel_select_objects(parcel->getLocalID(), RT_GROUP); @@ -1751,16 +1693,14 @@ void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata) args["N"] = llformat("%d", parcel->getGroupPrimCount()); // create and show confirmation textbox - LLNotificationsUtil::add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnGroupObjects, panelp, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnGroupObjects, this, _1, _2)); } -// static -void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) +void LLPanelLandObjects::onClickReturnOtherObjects() { S32 other = 0; - LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata; - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) return; other = parcel->getOtherPrimCount(); @@ -1776,7 +1716,7 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) gCacheName->getGroupName(parcel->getGroupID(), group_name); args["NAME"] = group_name; - LLNotificationsUtil::add("ReturnObjectsNotOwnedByGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsNotOwnedByGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, this, _1, _2)); } else { @@ -1784,14 +1724,12 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) if (owner_id == gAgent.getID()) { - LLNotificationsUtil::add("ReturnObjectsNotOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsNotOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, this, _1, _2)); } else { - std::string name; - gCacheName->getFullName(owner_id, name); - args["NAME"] = name; - LLNotificationsUtil::add("ReturnObjectsNotOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2)); + args["NAME"] = LLSLURL("agent", owner_id, "completename").getSLURLString(); + LLNotificationsUtil::add("ReturnObjectsNotOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, this, _1, _2)); } } } @@ -1799,20 +1737,24 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) // static void LLPanelLandObjects::onLostFocus(LLFocusableElement* caller, void* user_data) { - onCommitClean((LLUICtrl*)caller, user_data); + LLPanelLandObjects *lop = static_cast(user_data); + if (lop) lop->onCommitClean(); } -// static -void LLPanelLandObjects::onCommitClean(LLUICtrl *caller, void* user_data) +void LLPanelLandObjects::onCommitClean() { - LLPanelLandObjects *lop = (LLPanelLandObjects *)user_data; - LLParcel* parcel = lop->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (parcel) { - lop->mOtherTime = atoi(lop->mCleanOtherObjectsTime->getText().c_str()); + S32 return_time = std::stoi(mCleanOtherObjectsTime->getText()); + // Only send return time if it has changed + if (return_time != mOtherTime) + { + mOtherTime = return_time; - parcel->setCleanOtherTime(lop->mOtherTime); - send_other_clean_time_message(parcel->getLocalID(), lop->mOtherTime); + parcel->setCleanOtherTime(mOtherTime); + send_other_clean_time_message(parcel->getLocalID(), mOtherTime); + } } } @@ -1844,8 +1786,8 @@ LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel) mGamingCtrl(NULL), mPushRestrictionCtrl(NULL), mSeeAvatarsCtrl(NULL), - mParcel(parcel), - mPublishHelpButton(NULL) + mPublishHelpButton(NULL), + mParcel(parcel) { } @@ -1853,48 +1795,48 @@ LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel) BOOL LLPanelLandOptions::postBuild() { mCheckEditObjects = getChild( "edit objects check"); - childSetCommitCallback("edit objects check", onCommitAny, this); + mCheckEditObjects->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mCheckEditGroupObjects = getChild( "edit group objects check"); - childSetCommitCallback("edit group objects check", onCommitAny, this); + mCheckEditGroupObjects->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mCheckAllObjectEntry = getChild( "all object entry check"); - childSetCommitCallback("all object entry check", onCommitAny, this); + mCheckAllObjectEntry->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mCheckGroupObjectEntry = getChild( "group object entry check"); - childSetCommitCallback("group object entry check", onCommitAny, this); + mCheckGroupObjectEntry->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mCheckEditLand = getChild( "edit land check"); - childSetCommitCallback("edit land check", onCommitAny, this); + mCheckEditLand->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mCheckLandmark = getChild( "check landmark"); - childSetCommitCallback("check landmark", onCommitAny, this); + mCheckLandmark->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mCheckLandmark->setVisible(!gHippoGridManager->getConnectedGrid()->isSecondLife()); mCheckGroupScripts = getChild( "check group scripts"); - childSetCommitCallback("check group scripts", onCommitAny, this); + mCheckGroupScripts->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mCheckFly = getChild( "check fly"); - childSetCommitCallback("check fly", onCommitAny, this); + mCheckFly->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mCheckOtherScripts = getChild( "check other scripts"); - childSetCommitCallback("check other scripts", onCommitAny, this); + mCheckOtherScripts->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mCheckSafe = getChild( "check safe"); - childSetCommitCallback("check safe", onCommitAny, this); + mCheckSafe->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mPushRestrictionCtrl = getChild( "PushRestrictCheck"); - childSetCommitCallback("PushRestrictCheck", onCommitAny, this); + mPushRestrictionCtrl->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mSeeAvatarsCtrl = getChild( "SeeAvatarsCheck"); - childSetCommitCallback("SeeAvatarsCheck", onCommitAny, this); + mSeeAvatarsCtrl->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mCheckShowDirectory = getChild( "ShowDirectoryCheck"); - childSetCommitCallback("ShowDirectoryCheck", onCommitAny, this); + mCheckShowDirectory->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); if (gAgent.getAgentAccess().isInTransition()) @@ -1903,26 +1845,28 @@ BOOL LLPanelLandOptions::postBuild() // Post-transition, it goes away. We can remove this conditional // after the transition and just use the "else" clause. mCategoryCombo = getChild( "land category with adult"); - childSetCommitCallback("land category with adult", onCommitAny, this); } else { // this is the code that should be preserved post-transition // you could also change the XML to set visibility and enabled true. mCategoryCombo = getChild( "land category"); - childSetCommitCallback("land category", onCommitAny, this); } + mCategoryCombo->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mCategoryCombo->setVisible(true); mCategoryCombo->setEnabled(true); mMatureCtrl = getChild( "MatureCheck"); - childSetCommitCallback("MatureCheck", onCommitAny, this); + mMatureCtrl->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); - mGamingCtrl = getChild( "GamingCheck"); - childSetCommitCallback("GamingCheck", onCommitAny, this); - mGamingCtrl->setVisible((gAgent.getRegion()->getGamingFlags() & REGION_GAMING_PRESENT) && !(gAgent.getRegion()->getGamingFlags() & REGION_GAMING_HIDE_PARCEL)); - mGamingCtrl->setEnabled(false); + if (mGamingCtrl = getChild( "GamingCheck")) + { + auto region = gAgent.getRegion(); + mGamingCtrl->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); + mGamingCtrl->setVisible(region && (region->getGamingFlags() & REGION_GAMING_PRESENT) && !(region->getGamingFlags() & REGION_GAMING_HIDE_PARCEL)); + mGamingCtrl->setEnabled(false); + } mPublishHelpButton = getChild("?"); mPublishHelpButton->setClickedCallback(onClickPublishHelp, this); @@ -1940,7 +1884,7 @@ BOOL LLPanelLandOptions::postBuild() mSnapshotCtrl = getChild("snapshot_ctrl"); if (mSnapshotCtrl) { - mSnapshotCtrl->setCommitCallback( onCommitAny, this ); + mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); mSnapshotCtrl->setAllowNoTexture ( TRUE ); mSnapshotCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); mSnapshotCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); @@ -1954,15 +1898,15 @@ BOOL LLPanelLandOptions::postBuild() mLocationText = getChild("landing_point"); mSetBtn = getChild("Set"); - mSetBtn->setClickedCallback(onClickSet, this); + mSetBtn->setCommitCallback(boost::bind(&LLPanelLandOptions::onClickSet, this)); mClearBtn = getChild("Clear"); - mClearBtn->setClickedCallback(onClickClear, this); + mClearBtn->setCommitCallback(boost::bind(&LLPanelLandOptions::onClickClear, this)); mLandingTypeCombo = getChild( "landing type"); - childSetCommitCallback("landing type", onCommitAny, this); + mLandingTypeCombo->setCommitCallback(boost::bind(&LLPanelLandOptions::onCommitAny, this)); getChild("snapshot_ctrl")->setFallbackImageName("default_land_picture.j2c"); @@ -1981,7 +1925,7 @@ void LLPanelLandOptions::refresh() refreshSearch(); LLParcel *parcel = mParcel->getParcel(); - if (!parcel) + if (!parcel || gDisconnected) { mCheckEditObjects ->set(FALSE); mCheckEditObjects ->setEnabled(FALSE); @@ -2097,6 +2041,10 @@ void LLPanelLandOptions::refresh() mSnapshotCtrl->setImageAssetID(parcel->getSnapshotID()); mSnapshotCtrl->setEnabled( can_change_identity ); + // find out where we're looking and convert that to an angle in degrees on a regular compass (not the internal representation) + LLVector3 user_look_at = parcel->getUserLookAt(); + U32 user_look_at_angle = ( (U32)( ( atan2(user_look_at[1], -user_look_at[0]) + F_PI * 2 ) * RAD_TO_DEG + 0.5) - 90) % 360; + LLVector3 pos = parcel->getUserLocation(); if (pos.isExactlyZero()) { @@ -2104,10 +2052,11 @@ void LLPanelLandOptions::refresh() } else { - mLocationText->setTextArg("[LANDING]",llformat("%d, %d, %d", + mLocationText->setTextArg("[LANDING]",llformat("%d, %d, %d (%d\xC2\xB0)", ll_round(pos.mV[VX]), ll_round(pos.mV[VY]), - ll_round(pos.mV[VZ]))); + ll_round(pos.mV[VZ]), + user_look_at_angle)); } mSetBtn->setEnabled( can_change_landing_point ); @@ -2170,12 +2119,11 @@ void LLPanelLandOptions::draw() void LLPanelLandOptions::refreshSearch() { LLParcel *parcel = mParcel->getParcel(); - if (!parcel) + if (!parcel || gDisconnected) { mCheckShowDirectory->set(FALSE); mCheckShowDirectory->setEnabled(FALSE); - // *TODO:Translate const std::string& none_string = LLParcel::getCategoryUIString(LLParcel::C_NONE); mCategoryCombo->setSimple(none_string); mCategoryCombo->setEnabled(FALSE); @@ -2205,7 +2153,6 @@ void LLPanelLandOptions::refreshSearch() mCheckShowDirectory->setLabelArg("[DIRECTORYFEE]", gHippoGridManager->getConnectedGrid()->getDirectoryFee()); // Set by string in case the order in UI doesn't match the order by index. - // *TODO:Translate LLParcel::ECategory cat = parcel->getCategory(); const std::string& category_string = LLParcel::getCategoryUIString(cat); mCategoryCombo->setSimple(category_string); @@ -2265,38 +2212,35 @@ void LLPanelLandOptions::refreshSearch() } -// static -void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) +void LLPanelLandOptions::onCommitAny() { - LLPanelLandOptions *self = (LLPanelLandOptions *)userdata; - - LLParcel* parcel = self->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) { return; } // Extract data from UI - BOOL create_objects = self->mCheckEditObjects->get(); - BOOL create_group_objects = self->mCheckEditGroupObjects->get() || self->mCheckEditObjects->get(); - BOOL all_object_entry = self->mCheckAllObjectEntry->get(); - BOOL group_object_entry = self->mCheckGroupObjectEntry->get() || self->mCheckAllObjectEntry->get(); - BOOL allow_terraform = self->mCheckEditLand->get(); - BOOL allow_damage = !self->mCheckSafe->get(); - BOOL allow_fly = self->mCheckFly->get(); - BOOL allow_landmark = self->mCheckLandmark->get(); - BOOL allow_other_scripts = self->mCheckOtherScripts->get(); - BOOL allow_group_scripts = self->mCheckGroupScripts->get() || allow_other_scripts; + BOOL create_objects = mCheckEditObjects->get(); + BOOL create_group_objects = mCheckEditGroupObjects->get() || mCheckEditObjects->get(); + BOOL all_object_entry = mCheckAllObjectEntry->get(); + BOOL group_object_entry = mCheckGroupObjectEntry->get() || mCheckAllObjectEntry->get(); + BOOL allow_terraform = mCheckEditLand->get(); + BOOL allow_damage = !mCheckSafe->get(); + BOOL allow_fly = mCheckFly->get(); + BOOL allow_landmark = mCheckLandmark->get(); + BOOL allow_other_scripts = mCheckOtherScripts->get(); + BOOL allow_group_scripts = mCheckGroupScripts->get() || allow_other_scripts; BOOL allow_publish = FALSE; - BOOL mature_publish = self->mMatureCtrl->get(); - BOOL push_restriction = self->mPushRestrictionCtrl->get(); - BOOL see_avs = self->mSeeAvatarsCtrl->get(); - bool gaming = self->mGamingCtrl->get(); - BOOL show_directory = self->mCheckShowDirectory->get(); + BOOL mature_publish = mMatureCtrl->get(); + BOOL push_restriction = mPushRestrictionCtrl->get(); + BOOL see_avs = mSeeAvatarsCtrl->get(); + bool gaming = mGamingCtrl->get(); + BOOL show_directory = mCheckShowDirectory->get(); // we have to get the index from a lookup, not from the position in the dropdown! - S32 category_index = LLParcel::getCategoryFromString(self->mCategoryCombo->getSelectedValue()); - S32 landing_type_index = self->mLandingTypeCombo->getCurrentIndex(); - LLUUID snapshot_id = self->mSnapshotCtrl->getImageAssetID(); + S32 category_index = LLParcel::getCategoryFromString(mCategoryCombo->getSelectedValue()); + S32 landing_type_index = mLandingTypeCombo->getCurrentIndex(); + LLUUID snapshot_id = mSnapshotCtrl->getImageAssetID(); LLViewerRegion* region; region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); @@ -2305,8 +2249,8 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) if ( (!allow_other_scripts && parcel->getParcelFlag(PF_ALLOW_OTHER_SCRIPTS)) || (!allow_group_scripts && parcel->getParcelFlag(PF_ALLOW_GROUP_SCRIPTS)) ) { // Don't allow turning off "Run Scripts" if damage is allowed in the region - self->mCheckOtherScripts->set(parcel->getParcelFlag(PF_ALLOW_OTHER_SCRIPTS)); // Restore UI to actual settings - self->mCheckGroupScripts->set(parcel->getParcelFlag(PF_ALLOW_GROUP_SCRIPTS)); + mCheckOtherScripts->set(parcel->getParcelFlag(PF_ALLOW_OTHER_SCRIPTS)); // Restore UI to actual settings + mCheckGroupScripts->set(parcel->getParcelFlag(PF_ALLOW_GROUP_SCRIPTS)); LLNotificationsUtil::add("UnableToDisableOutsideScripts"); return; } @@ -2337,16 +2281,12 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); // Might have changed properties, so let's redraw! - self->refresh(); + refresh(); } - -// static -void LLPanelLandOptions::onClickSet(void* userdata) +void LLPanelLandOptions::onClickSet() { - LLPanelLandOptions* self = (LLPanelLandOptions*)userdata; - - LLParcel* selected_parcel = self->mParcel->getParcel(); + LLParcel* selected_parcel = mParcel->getParcel(); if (!selected_parcel) return; LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); @@ -2364,14 +2304,12 @@ void LLPanelLandOptions::onClickSet(void* userdata) LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate(selected_parcel); - self->refresh(); + refresh(); } -void LLPanelLandOptions::onClickClear(void* userdata) +void LLPanelLandOptions::onClickClear() { - LLPanelLandOptions* self = (LLPanelLandOptions*)userdata; - - LLParcel* selected_parcel = self->mParcel->getParcel(); + LLParcel* selected_parcel = mParcel->getParcel(); if (!selected_parcel) return; // yes, this magic number of 0,0,0 means that it is clear @@ -2381,9 +2319,10 @@ void LLPanelLandOptions::onClickClear(void* userdata) LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate(selected_parcel); - self->refresh(); + refresh(); } + // static void LLPanelLandOptions::onClickPublishHelp(void*) { @@ -2412,27 +2351,29 @@ void LLPanelLandOptions::onClickPublishHelp(void*) //--------------------------------------------------------------------------- LLPanelLandAccess::LLPanelLandAccess(LLParcelSelectionHandle& parcel) - : LLPanel(std::string("land_access_panel")), - mParcel(parcel) + : LLPanel(std::string("land_access_panel")) + , mListAccess(nullptr) + , mListBanned(nullptr) + , mParcel(parcel) { } BOOL LLPanelLandAccess::postBuild() { - childSetCommitCallback("public_access", onCommitPublicAccess, this); - childSetCommitCallback("limit_payment", onCommitAny, this); - childSetCommitCallback("limit_age_verified", onCommitAny, this); - childSetCommitCallback("GroupCheck", onCommitGroupCheck, this); - childSetCommitCallback("PassCheck", onCommitAny, this); - childSetCommitCallback("pass_combo", onCommitAny, this); - childSetCommitCallback("PriceSpin", onCommitAny, this); - childSetCommitCallback("HoursSpin", onCommitAny, this); + getChild("public_access")->setCommitCallback(boost::bind(&LLPanelLandAccess::onCommitPublicAccess, this, _1)); + getChild("limit_payment")->setCommitCallback(boost::bind(&LLPanelLandAccess::onCommitAny, this)); + getChild("limit_age_verified")->setCommitCallback(boost::bind(&LLPanelLandAccess::onCommitAny, this)); + getChild("GroupCheck")->setCommitCallback(boost::bind(&LLPanelLandAccess::onCommitGroupCheck, this, _1)); + getChild("PassCheck")->setCommitCallback(boost::bind(&LLPanelLandAccess::onCommitAny, this)); + getChild("pass_combo")->setCommitCallback(boost::bind(&LLPanelLandAccess::onCommitAny, this)); + getChild("PriceSpin")->setCommitCallback(boost::bind(&LLPanelLandAccess::onCommitAny, this)); + getChild("HoursSpin")->setCommitCallback(boost::bind(&LLPanelLandAccess::onCommitAny, this)); childSetAction("add_allowed", boost::bind(&LLPanelLandAccess::onClickAddAccess, this)); - childSetAction("remove_allowed", onClickRemoveAccess, this); + getChild("remove_allowed")->setCommitCallback(boost::bind(&LLPanelLandAccess::onClickRemoveAccess, this)); childSetAction("add_banned", boost::bind(&LLPanelLandAccess::onClickAddBanned, this)); - childSetAction("remove_banned", onClickRemoveBanned, this); + getChild("remove_banned")->setCommitCallback(boost::bind(&LLPanelLandAccess::onClickRemoveBanned, this)); mListAccess = getChild("AccessList"); if (mListAccess) @@ -2464,127 +2405,118 @@ void LLPanelLandAccess::refresh() LLParcel *parcel = mParcel->getParcel(); // Display options - if (parcel) + if (parcel && !gDisconnected) { BOOL use_access_list = parcel->getParcelFlag(PF_USE_ACCESS_LIST); BOOL use_group = parcel->getParcelFlag(PF_USE_ACCESS_GROUP); BOOL public_access = !use_access_list && !use_group; - getChild("public_access")->setValue(public_access ); - getChild("GroupCheck")->setValue(use_group ); + getChild("public_access")->setValue(public_access); + getChild("GroupCheck")->setValue(use_group); std::string group_name; gCacheName->getGroupName(parcel->getGroupID(), group_name); getChild("GroupCheck")->setLabelArg("[GROUP]", group_name ); - + + const auto always = getString("Always"); + + static const LLCachedControl date("ShortDateFormat"); + static const LLCachedControl time("LongTimeFormat"); + const auto time_format = date() + ' ' + time(); + // Allow list if (mListAccess) { // Clear the sort order so we don't re-sort on every add. + const auto order = mListAccess->getSortOrder(); mListAccess->clearSortOrder(); mListAccess->deleteAllItems(); S32 count = parcel->mAccessList.size(); - getChild("AccessList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count)); - getChild("AccessList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST)); + getChild("AllowedText")->setTextArg("[COUNT]", llformat("%d",count)); + getChild("AllowedText")->setTextArg("[MAX]", llformat("%d",PARCEL_MAX_ACCESS_LIST)); + + mListAccess->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count)); + mListAccess->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST)); - for (access_map_const_iterator cit = parcel->mAccessList.begin(); - cit != parcel->mAccessList.end(); ++cit) + for (const auto& pair : parcel->mAccessList) { - const LLAccessEntry& entry = (*cit).second; - std::string suffix; + const LLAccessEntry& entry = pair.second; + LLSD item; + item["id"] = entry.mID; + LLSD& columns = item["columns"]; + columns[0]["column"] = "name"; // to be populated later + columns[1]["column"] = "duration"; if (entry.mTime != 0) { - S32 now = time(NULL); - S32 seconds = entry.mTime - now; - if (seconds < 0) seconds = 0; - suffix.assign(" ("); - if (seconds >= 120) - { - std::string buf = llformat("%d ", (seconds/60)) + getString("minutes"); - suffix.append(buf); - } - else if (seconds >= 60) - { - suffix.append(getString("1_minute")); - } - else if (seconds == 1) - { - suffix.append(getString("1_second")); - } - else - { - std::string buf = llformat("%d ", seconds) + getString("seconds"); - suffix.append(buf); - } - suffix.append(" " + getString("remaining") + ")"); + columns[1]["type"] = "date"; + columns[1]["format"] = time_format; + columns[1]["value"] = LLDate(entry.mTime); + } + else + { + columns[1]["value"] = always; } - mListAccess->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix); + mListAccess->addElement(item); } - mListAccess->sortByName(TRUE); + mListAccess->setSortOrder(order); } // Ban List if(mListBanned) { // Clear the sort order so we don't re-sort on every add. + const auto order = mListBanned->getSortOrder(); mListBanned->clearSortOrder(); mListBanned->deleteAllItems(); S32 count = parcel->mBanList.size(); + getChild("BanCheck")->setTextArg("[COUNT]", llformat("%d",count)); + getChild("BanCheck")->setTextArg("[MAX]", llformat("%d",PARCEL_MAX_ACCESS_LIST)); - getChild("BannedList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count)); - getChild("BannedList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST)); + mListBanned->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count)); + mListBanned->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST)); - for (access_map_const_iterator cit = parcel->mBanList.begin(); - cit != parcel->mBanList.end(); ++cit) + for (const auto& pair : parcel->mBanList) { - const LLAccessEntry& entry = (*cit).second; - std::string suffix; + const LLAccessEntry& entry = pair.second; + LLSD item; + item["id"] = entry.mID; + LLSD& columns = item["columns"]; + columns[0]["column"] = "name"; // to be populated later + columns[1]["column"] = "duration"; if (entry.mTime != 0) { - S32 now = time(NULL); - S32 seconds = entry.mTime - now; - if (seconds < 0) seconds = 0; - suffix.assign(" ("); - if (seconds >= 120) - { - std::string buf = llformat("%d ", (seconds/60)) + getString("minutes"); - suffix.append(buf); - } - else if (seconds >= 60) - { - suffix.append(getString("1_minute")); - } - else if (seconds == 1) - { - suffix.append(getString("1_second")); - } - else - { - std::string buf = llformat("%d ", seconds) + getString("seconds"); - suffix.append(buf); - } - suffix.append(" " + getString("remaining") + ")"); + columns[1]["type"] = "date"; + columns[1]["format"] = time_format; + columns[1]["value"] = LLDate(entry.mTime); } - mListBanned->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix); + else + { + columns[1]["value"] = always; + } + mListBanned->addElement(item); } - mListBanned->sortByName(TRUE); + mListBanned->setSortOrder(order); } if(parcel->getRegionDenyAnonymousOverride()) { getChild("limit_payment")->setValue(TRUE); + getChild("limit_payment")->setLabelArg("[ESTATE_PAYMENT_LIMIT]", getString("access_estate_defined") ); } else { getChild("limit_payment")->setValue((parcel->getParcelFlag(PF_DENY_ANONYMOUS))); + getChild("limit_payment")->setLabelArg("[ESTATE_PAYMENT_LIMIT]", std::string() ); } if(parcel->getRegionDenyAgeUnverifiedOverride()) { getChild("limit_age_verified")->setValue(TRUE); + getChild("limit_age_verified")->setLabelArg("[ESTATE_AGE_LIMIT]", getString("access_estate_defined") ); } else { getChild("limit_age_verified")->setValue((parcel->getParcelFlag(PF_DENY_AGEUNVERIFIED))); + getChild("limit_age_verified")->setLabelArg("[ESTATE_AGE_LIMIT]", std::string() ); } BOOL use_pass = parcel->getParcelFlag(PF_USE_PASS_LIST); @@ -2615,10 +2547,10 @@ void LLPanelLandAccess::refresh() getChild("PassCheck")->setValue(FALSE); getChild("PriceSpin")->setValue((F32)PARCEL_PASS_PRICE_DEFAULT); getChild("HoursSpin")->setValue(PARCEL_PASS_HOURS_DEFAULT ); - getChild("AccessList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",0)); - getChild("AccessList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",0)); - getChild("BannedList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",0)); - getChild("BannedList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",0)); + mListAccess->setToolTipArg(LLStringExplicit("[LISTED]"), zero_str); + mListAccess->setToolTipArg(LLStringExplicit("[MAX]"), zero_str); + mListBanned->setToolTipArg(LLStringExplicit("[LISTED]"), zero_str); + mListBanned->setToolTipArg(LLStringExplicit("[MAX]"), zero_str); } } @@ -2632,11 +2564,15 @@ void LLPanelLandAccess::refresh_ui() getChildView("pass_combo")->setEnabled(FALSE); getChildView("PriceSpin")->setEnabled(FALSE); getChildView("HoursSpin")->setEnabled(FALSE); - getChildView("AccessList")->setEnabled(FALSE); - getChildView("BannedList")->setEnabled(FALSE); + mListAccess->setEnabled(FALSE); + mListBanned->setEnabled(FALSE); + getChildView("add_allowed")->setEnabled(FALSE); + getChildView("remove_allowed")->setEnabled(FALSE); + getChildView("add_banned")->setEnabled(FALSE); + getChildView("remove_banned")->setEnabled(FALSE); LLParcel *parcel = mParcel->getParcel(); - if (parcel) + if (parcel && !gDisconnected) { BOOL can_manage_allowed = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_MANAGE_ALLOWED); BOOL can_manage_banned = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_MANAGE_BANNED); @@ -2675,7 +2611,7 @@ void LLPanelLandAccess::refresh_ui() getChildView("GroupCheck")->setEnabled(FALSE); getChildView("PassCheck")->setEnabled(FALSE); getChildView("pass_combo")->setEnabled(FALSE); - getChildView("AccessList")->setEnabled(FALSE); + mListAccess->setEnabled(FALSE); } else { @@ -2684,7 +2620,7 @@ void LLPanelLandAccess::refresh_ui() std::string group_name; if (gCacheName->getGroupName(parcel->getGroupID(), group_name)) - { + { getChildView("GroupCheck")->setEnabled(can_manage_allowed); } BOOL sell_passes = getChild("PassCheck")->getValue().asBoolean(); @@ -2696,13 +2632,13 @@ void LLPanelLandAccess::refresh_ui() getChildView("HoursSpin")->setEnabled(can_manage_allowed); } } - getChildView("AccessList")->setEnabled(true/*can_manage_allowed*/); + mListAccess->setEnabled(true/*can_manage_allowed*/); S32 allowed_list_count = parcel->mAccessList.size(); getChildView("add_allowed")->setEnabled(can_manage_allowed && allowed_list_count < PARCEL_MAX_ACCESS_LIST); BOOL has_selected = (mListAccess && mListAccess->getSelectionInterface()->getFirstSelectedIndex() >= 0); getChildView("remove_allowed")->setEnabled(can_manage_allowed && has_selected); - getChildView("BannedList")->setEnabled(true/*can_manage_banned*/); + mListBanned->setEnabled(true/*can_manage_banned*/); S32 banned_list_count = parcel->mBanList.size(); getChildView("add_banned")->setEnabled(can_manage_banned && banned_list_count < PARCEL_MAX_ACCESS_LIST); has_selected = (mListBanned && mListBanned->getSelectionInterface()->getFirstSelectedIndex() >= 0); @@ -2732,70 +2668,60 @@ void LLPanelLandAccess::draw() LLPanel::draw(); } -// static -void LLPanelLandAccess::onCommitPublicAccess(LLUICtrl *ctrl, void *userdata) +void LLPanelLandAccess::onCommitPublicAccess(LLUICtrl *ctrl) { - LLPanelLandAccess *self = (LLPanelLandAccess *)userdata; - LLParcel* parcel = self->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) { return; } // If we disabled public access, enable group access by default (if applicable) - BOOL public_access = self->getChild("public_access")->getValue().asBoolean(); - if (public_access == FALSE) + if (!getChild("public_access")->getValue().asBoolean()) { std::string group_name; if (gCacheName->getGroupName(parcel->getGroupID(), group_name)) { - self->getChild("GroupCheck")->setValue(public_access ? FALSE : TRUE); + getChild("GroupCheck")->setValue(true); } } - onCommitAny(ctrl, userdata); + onCommitAny(); } -void LLPanelLandAccess::onCommitGroupCheck(LLUICtrl *ctrl, void *userdata) +void LLPanelLandAccess::onCommitGroupCheck(LLUICtrl *ctrl) { - LLPanelLandAccess *self = (LLPanelLandAccess *)userdata; - LLParcel* parcel = self->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) { return; } - BOOL use_pass_list = !self->getChild("public_access")->getValue().asBoolean(); - BOOL use_access_group = self->getChild("GroupCheck")->getValue().asBoolean(); - LLCtrlSelectionInterface* passcombo = self->childGetSelectionInterface("pass_combo"); - if (passcombo) + BOOL use_pass_list = !getChild("public_access")->getValue().asBoolean(); + BOOL use_access_group = getChild("GroupCheck")->getValue().asBoolean(); + LLCtrlSelectionInterface* passcombo = childGetSelectionInterface("pass_combo"); + if (passcombo && use_access_group && use_pass_list) { - if (use_access_group && use_pass_list) + if (passcombo->getSelectedValue().asString() == "group") { - if (passcombo->getSelectedValue().asString() == "group") - { - passcombo->selectByValue("anyone"); - } + passcombo->selectByValue("anyone"); } } - onCommitAny(ctrl, userdata); + onCommitAny(); } -// static -void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) +void LLPanelLandAccess::onCommitAny() { - LLPanelLandAccess *self = (LLPanelLandAccess *)userdata; - - LLParcel* parcel = self->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) { return; } // Extract data from UI - BOOL public_access = self->getChild("public_access")->getValue().asBoolean(); - BOOL use_access_group = self->getChild("GroupCheck")->getValue().asBoolean(); + BOOL public_access = getChild("public_access")->getValue().asBoolean(); + BOOL use_access_group = getChild("GroupCheck")->getValue().asBoolean(); if (use_access_group) { std::string group_name; @@ -2813,14 +2739,14 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) { use_access_list = FALSE; use_access_group = FALSE; - limit_payment = self->getChild("limit_payment")->getValue().asBoolean(); - limit_age_verified = self->getChild("limit_age_verified")->getValue().asBoolean(); + limit_payment = getChild("limit_payment")->getValue().asBoolean(); + limit_age_verified = getChild("limit_age_verified")->getValue().asBoolean(); } else { use_access_list = TRUE; - use_pass_list = self->getChild("PassCheck")->getValue().asBoolean(); - LLCtrlSelectionInterface* passcombo = self->childGetSelectionInterface("pass_combo"); + use_pass_list = getChild("PassCheck")->getValue().asBoolean(); + LLCtrlSelectionInterface* passcombo = childGetSelectionInterface("pass_combo"); if (passcombo) { if (use_access_group && use_pass_list) @@ -2833,8 +2759,8 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) } } - S32 pass_price = llfloor((F32)self->getChild("PriceSpin")->getValue().asReal()); - F32 pass_hours = (F32)self->getChild("HoursSpin")->getValue().asReal(); + S32 pass_price = llfloor((F32)getChild("PriceSpin")->getValue().asReal()); + F32 pass_hours = (F32)getChild("HoursSpin")->getValue().asReal(); // Push data into current parcel parcel->setParcelFlag(PF_USE_ACCESS_GROUP, use_access_group); @@ -2851,14 +2777,14 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); // Might have changed properties, so let's redraw! - self->refresh(); + refresh(); } void LLPanelLandAccess::onClickAddAccess() { LLFloater* root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( - boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1)); + boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1), true, true); if (picker) { root_floater->addDependentFloater(picker); @@ -2867,29 +2793,40 @@ void LLPanelLandAccess::onClickAddAccess() void LLPanelLandAccess::callbackAvatarCBAccess(const uuid_vec_t& ids) { - if (!ids.empty()) + LLParcel* parcel = mParcel->getParcel(); + if (!parcel) return; + + U32 lists_to_update = 0; + + for (const auto& id : ids) { - LLUUID id = ids[0]; - LLParcel* parcel = mParcel->getParcel(); - if (parcel) + if (parcel->addToAccessList(id, 0)) { - parcel->addToAccessList(id, 0); - LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(AL_ACCESS); - refresh(); + lists_to_update |= AL_ACCESS; + // agent was successfully added to access list + // but we also need to check ban list to ensure that agent will not be in two lists simultaneously + if(parcel->removeFromBanList(id)) + { + lists_to_update |= AL_BAN; + } } } + if (lists_to_update) + { + LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(lists_to_update); + refresh(); + } } // static -void LLPanelLandAccess::onClickRemoveAccess(void* data) +void LLPanelLandAccess::onClickRemoveAccess() { - LLPanelLandAccess* panelp = (LLPanelLandAccess*)data; - if (panelp && panelp->mListAccess) + if (mListAccess) { - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (parcel) { - std::vector names = panelp->mListAccess->getAllSelected(); + std::vector names = mListAccess->getAllSelected(); for (std::vector::iterator iter = names.begin(); iter != names.end(); ) { @@ -2898,47 +2835,70 @@ void LLPanelLandAccess::onClickRemoveAccess(void* data) parcel->removeFromAccessList(agent_id); } LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(AL_ACCESS); - panelp->refresh(); + refresh(); } } } +// static void LLPanelLandAccess::onClickAddBanned() { LLFloater* root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( - boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1)); + boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1), true, true); if (picker) { root_floater->addDependentFloater(picker); } } +// static void LLPanelLandAccess::callbackAvatarCBBanned(const uuid_vec_t& ids) { - if (!ids.empty()) + LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterBanDuration* duration_floater = LLFloaterBanDuration::show( + boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned2, this, _1, _2), ids); + if (duration_floater) { - LLUUID id = ids[0]; - LLParcel* parcel = mParcel->getParcel(); - if (parcel) + root_floater->addDependentFloater(duration_floater); + } +} + +void LLPanelLandAccess::callbackAvatarCBBanned2(const uuid_vec_t& ids, S32 duration) +{ + LLParcel* parcel = mParcel->getParcel(); + if (!parcel) return; + + U32 lists_to_update = 0; + + for (const auto& id : ids) + { + if (parcel->addToBanList(id, duration)) { - parcel->addToBanList(id, 0); - LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(AL_BAN); - refresh(); + lists_to_update |= AL_BAN; + // agent was successfully added to ban list + // but we also need to check access list to ensure that agent will not be in two lists simultaneously + if(parcel->removeFromAccessList(id)) + { + lists_to_update |= AL_ACCESS; + } } } + if (lists_to_update) + { + LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(lists_to_update); + refresh(); + } } -// static -void LLPanelLandAccess::onClickRemoveBanned(void* data) +void LLPanelLandAccess::onClickRemoveBanned() { - LLPanelLandAccess* panelp = (LLPanelLandAccess*)data; - if (panelp && panelp->mListBanned) + if (mListBanned) { - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (parcel) { - std::vector names = panelp->mListBanned->getAllSelected(); + std::vector names = mListBanned->getAllSelected(); for (std::vector::iterator iter = names.begin(); iter != names.end(); ) { @@ -2947,7 +2907,7 @@ void LLPanelLandAccess::onClickRemoveBanned(void* data) parcel->removeFromBanList(agent_id); } LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(AL_BAN); - panelp->refresh(); + refresh(); } } } @@ -2957,7 +2917,8 @@ void LLPanelLandAccess::onClickRemoveBanned(void* data) //--------------------------------------------------------------------------- LLPanelLandCovenant::LLPanelLandCovenant(LLParcelSelectionHandle& parcel) : LLPanel(std::string("land_covenant_panel")), - mParcel(parcel) + mParcel(parcel), + mNextUpdateTime(0) { } @@ -2975,7 +2936,7 @@ BOOL LLPanelLandCovenant::postBuild() void LLPanelLandCovenant::refresh() { LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); - if(!region) return; + if(!region || gDisconnected) return; LLTextBox* region_name = getChild("region_name_text"); if (region_name) @@ -3018,13 +2979,22 @@ void LLPanelLandCovenant::refresh() } } - // send EstateCovenantInfo message - LLMessageSystem *msg = gMessageSystem; - msg->newMessage("EstateCovenantRequest"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); - msg->sendReliable(region->getHost()); + if (mLastRegionID != region->getRegionID() + || mNextUpdateTime < LLTimer::getElapsedSeconds()) + { + // Request Covenant Info + // Note: LLPanelLandCovenant doesn't change Covenant's content and any + // changes made by Estate floater should be requested by Estate floater + LLMessageSystem *msg = gMessageSystem; + msg->newMessage("EstateCovenantRequest"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); + msg->sendReliable(region->getHost()); + + mLastRegionID = region->getRegionID(); + mNextUpdateTime = LLTimer::getElapsedSeconds() + COVENANT_REFRESH_TIME_SEC; + } } // static @@ -3035,7 +3005,7 @@ void LLPanelLandCovenant::updateCovenantText(const std::string &string) { LLViewerTextEditor* editor = self->getChild("covenant_editor"); editor->setHandleEditKeysDirectly(TRUE); - editor->setText(string); + editor->setText(string, false); } } @@ -3062,16 +3032,119 @@ void LLPanelLandCovenant::updateLastModified(const std::string& text) } // static -void LLPanelLandCovenant::updateEstateOwnerName(const std::string& name) +void LLPanelLandCovenant::updateEstateOwnerID(const LLUUID& id) { LLPanelLandCovenant* self = LLFloaterLand::getCurrentPanelLandCovenant(); if (self) { - LLTextBox* editor = self->getChild("estate_owner_text"); - if (editor) editor->setText(name); + self->getChildView("estate_owner_text")->setValue(id); } } +LLPanelLandExperiences::LLPanelLandExperiences( LLSafeHandle& parcelp ) + : mParcel(parcelp), + mAllowed(nullptr), + mBlocked(nullptr) +{ + mFactoryMap["panel_allowed"] = LLCallbackMap(create_xp_list_editor, reinterpret_cast(&mAllowed)); + mFactoryMap["panel_blocked"] = LLCallbackMap(create_xp_list_editor, reinterpret_cast(&mBlocked)); + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_region_experiences.xml", &mFactoryMap); +} + + +BOOL LLPanelLandExperiences::postBuild() +{ + setupList(mAllowed, "panel_allowed", EXPERIENCE_KEY_TYPE_ALLOWED, AL_ALLOW_EXPERIENCE); + setupList(mBlocked, "panel_blocked", EXPERIENCE_KEY_TYPE_BLOCKED, AL_BLOCK_EXPERIENCE); + + // only non-grid-wide experiences + mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_GRID)); + + // no privileged ones + mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithoutProperties, _1, LLExperienceCache::PROPERTY_PRIVILEGED|LLExperienceCache::PROPERTY_GRID)); + + getChild("trusted_layout_panel")->setVisible(FALSE); + getChild("experiences_help_text")->setVisible(FALSE); + getChild("allowed_text_help")->setText(getString("allowed_parcel_text")); + getChild("blocked_text_help")->setText(getString("blocked_parcel_text")); + + return LLPanel::postBuild(); +} + +void LLPanelLandExperiences::setupList(LLPanelExperienceListEditor* child, const char* control_name, U32 xp_type, U32 access_type ) +{ + //LLPanelExperienceListEditor* child = findChild(control_name); + if (child) + { + child->getChild("text_name")->setText(child->getString(control_name)); + child->setMaxExperienceIDs(PARCEL_MAX_EXPERIENCE_LIST); + child->setAddedCallback(boost::bind(&LLPanelLandExperiences::experienceAdded, this, _1, xp_type, access_type)); + child->setRemovedCallback(boost::bind(&LLPanelLandExperiences::experienceRemoved, this, _1, access_type)); + } + + //return child; +} + +void LLPanelLandExperiences::experienceAdded( const LLUUID& id, U32 xp_type, U32 access_type ) +{ + LLParcel* parcel = mParcel->getParcel(); + if (parcel) + { + parcel->setExperienceKeyType(id, xp_type); + LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(access_type); + refresh(); + } +} + +void LLPanelLandExperiences::experienceRemoved( const LLUUID& id, U32 access_type ) +{ + LLParcel* parcel = mParcel->getParcel(); + if (parcel) + { + parcel->setExperienceKeyType(id, EXPERIENCE_KEY_TYPE_NONE); + LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(access_type); + refresh(); + } +} + +void LLPanelLandExperiences::refreshPanel(LLPanelExperienceListEditor* panel, U32 xp_type) +{ + LLParcel *parcel = mParcel->getParcel(); + + // Display options + if (panel == NULL) + { + return; + } + if (!parcel || gDisconnected) + { + // disable the panel + panel->setEnabled(FALSE); + panel->setExperienceIds(LLSD::emptyArray()); + } + else + { + // enable the panel + panel->setEnabled(TRUE); + LLAccessEntry::map entries = parcel->getExperienceKeysByType(xp_type); + LLAccessEntry::map::iterator it = entries.begin(); + LLSD ids = LLSD::emptyArray(); + for (/**/; it != entries.end(); ++it) + { + ids.append(it->second.mID); + } + panel->setExperienceIds(ids); + panel->setReadonly(!LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_OPTIONS)); + panel->refreshExperienceCounter(); + } +} + +void LLPanelLandExperiences::refresh() +{ + refreshPanel(mAllowed, EXPERIENCE_KEY_TYPE_ALLOWED); + refreshPanel(mBlocked, EXPERIENCE_KEY_TYPE_BLOCKED); +} + // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) void LLFloaterLand::open() { @@ -3109,3 +3182,16 @@ void LLFloaterLand::open() LLFloater::open(); } // [/RLVa:KB] + + +// virtual +void LLFloaterLand::onClose(bool app_quitting) +{ + // Might have been showing owned objects + LLSelectMgr::getInstance()->unhighlightAll(); + + // Save which panel we had open + sLastTab = mTabLand->getCurrentPanelIndex(); + + destroy(); +} diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index 72e906a652..4024d60a27 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -3,46 +3,35 @@ * @author James Cook * @brief "About Land" floater, allowing display and editing of land parcel properties. * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LL_LLFLOATERLAND_H #define LL_LLFLOATERLAND_H -#include -#include - #include "llfloater.h" #include "llpointer.h" // LLPointer<> -//#include "llviewertexturelist.h" #include "llsafehandle.h" -typedef std::set uuid_list_t; const F32 CACHE_REFRESH_TIME = 2.5f; class LLButton; @@ -50,6 +39,7 @@ class LLCheckBoxCtrl; class LLRadioGroup; class LLComboBox; class LLLineEditor; +class LLMessageSystem; class LLNameListCtrl; class LLRadioGroup; class LLParcelSelectionObserver; @@ -59,7 +49,6 @@ class LLTextBox; class LLTextEditor; class LLTextureCtrl; class LLUIImage; -class LLViewerTextEditor; class LLParcelSelection; class LLPanelLandGeneral; @@ -72,9 +61,11 @@ class LLPanelLandBan; class LLPanelLandRenters; class LLPanelLandCovenant; class LLParcel; +class LLPanelLandExperiences; -class LLFloaterLand -: public LLFloater, public LLFloaterSingleton +class LLFloaterLand final +: public LLFloater +, public LLFloaterSingleton { friend class LLUISingleton >; public: @@ -86,24 +77,23 @@ class LLFloaterLand LLParcel* getCurrentSelectedParcel(); // Destroys itself on close. - virtual void onClose(bool app_quitting); - virtual void onOpen(); - virtual BOOL postBuild(); + void onClose(bool app_quitting) override; + void onOpen() override; + BOOL postBuild() override; // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) - virtual void open(); + void open() override; // [/RLVa:KB] - - -protected: - +private: // Does its own instance management, so clients not allowed // to allocate or destroy. LLFloaterLand(const LLSD& seed); virtual ~LLFloaterLand(); - /*virtual*/ void refresh(); +protected: + + /*virtual*/ void refresh() override; static void* createPanelLandGeneral(void* data); static void* createPanelLandCovenant(void* data); @@ -112,12 +102,15 @@ class LLFloaterLand static void* createPanelLandAudio(void* data); static void* createPanelLandMedia(void* data); static void* createPanelLandAccess(void* data); + static void* createPanelLandExperiences(void* data); static void* createPanelLandBan(void* data); + protected: static LLParcelSelectionObserver* sObserver; static S32 sLastTab; + friend class LLPanelLandObjects; LLTabContainer* mTabLand; LLPanelLandGeneral* mPanelGeneral; LLPanelLandObjects* mPanelObjects; @@ -126,6 +119,7 @@ class LLFloaterLand LLPanelLandMedia* mPanelMedia; LLPanelLandAccess* mPanelAccess; LLPanelLandCovenant* mPanelCovenant; + LLPanelLandExperiences* mPanelExperiences; LLSafeHandle mParcel; @@ -138,28 +132,25 @@ class LLFloaterLand }; -class LLPanelLandGeneral +class LLPanelLandGeneral final : public LLPanel { public: LLPanelLandGeneral(LLSafeHandle& parcelp); virtual ~LLPanelLandGeneral(); - /*virtual*/ void refresh(); + /*virtual*/ void refresh() override; void refreshNames(); - virtual void draw(); void setGroup(const LLUUID& group_id); - void onClickProfile(); void onClickSetGroup(); - static void onClickInfoGroup(void*); - static void onClickDeed(void*); static void onClickBuyLand(void* data); - static void onClickScriptLimits(void* data); - static void onClickRelease(void*); - static void onClickReclaim(void*); static void onClickBuyPass(void* deselect_when_done); + void onClickDeed(); + void onClickScriptLimits(); + void onClickRelease(); + void onClickReclaim(); static BOOL enableBuyPass(void*); - static void onCommitAny(LLUICtrl* ctrl, void *userdata); + void onCommitAny(); static void finalizeCommit(void * userdata); static void onForSaleChange(LLUICtrl *ctrl, void * userdata); static void finalizeSetSellChange(void * userdata); @@ -167,27 +158,23 @@ class LLPanelLandGeneral static bool cbBuyPass(const LLSD& notification, const LLSD& response); - static void onClickSellLand(void* data); - static void onClickStopSellLand(void* data); - static void onClickSet(void* data); - static void onClickClear(void* data); - static void onClickShow(void* data); - static void callbackAvatarPick(const std::vector& names, const std::vector& ids, void* data); + void onClickSellLand(); + void onClickStopSellLand(); + void onClickSet(); + void onClickClear(); + void onClickShow(); + static void callbackAvatarPick(const std::vector& names, const uuid_vec_t& ids, void* data); static void finalizeAvatarPick(void* data); static void callbackHighlightTransferable(S32 option, void* userdata); - static void onClickStartAuction(void*); + void onClickStartAuction(); // sale change confirmed when "is for sale", "sale price", "sell to whom" fields are changed static void confirmSaleChange(S32 landSize, S32 salePrice, std::string authorizedName, void(*callback)(void*), void* userdata); static void callbackConfirmSaleChange(S32 option, void* userdata); - virtual BOOL postBuild(); + BOOL postBuild() override; protected: - BOOL mUncheckedSell; // True only when verifying land information when land is for sale on sale info change - - LLTextBox* mLabelName; LLLineEditor* mEditName; - LLTextBox* mLabelDesc; LLTextEditor* mEditDesc; LLTextBox* mTextSalePending; @@ -195,16 +182,12 @@ class LLPanelLandGeneral LLButton* mBtnDeedToGroup; LLButton* mBtnSetGroup; - LLTextBox* mTextOwnerLabel; LLTextBox* mTextOwner; - LLButton* mBtnProfile; - + LLTextBox* mContentRating; LLTextBox* mLandType; LLTextBox* mTextGroup; - LLTextBox* mTextGroupLabel; - LLTextBox* mTextClaimDateLabel; LLTextBox* mTextClaimDate; LLTextBox* mTextPriceLabel; @@ -247,39 +230,36 @@ class LLPanelLandGeneral static LLHandle sBuyPassDialogHandle; }; -class LLPanelLandObjects +class LLPanelLandObjects final : public LLPanel { public: LLPanelLandObjects(LLSafeHandle& parcelp); virtual ~LLPanelLandObjects(); - /*virtual*/ void refresh(); - virtual void draw(); + /*virtual*/ void refresh() override; bool callbackReturnOwnerObjects(const LLSD& notification, const LLSD& response); bool callbackReturnGroupObjects(const LLSD& notification, const LLSD& response); bool callbackReturnOtherObjects(const LLSD& notification, const LLSD& response); bool callbackReturnOwnerList(const LLSD& notification, const LLSD& response); - static void clickShowCore(LLPanelLandObjects* panelp, S32 return_type, uuid_list_t* list = 0); - static void onClickShowOwnerObjects(void*); - static void onClickShowGroupObjects(void*); - static void onClickShowOtherObjects(void*); + static void clickShowCore(LLPanelLandObjects* panelp, S32 return_type, uuid_list_t* list = nullptr); + void onClickShowOwnerObjects(); + void onClickShowGroupObjects(); + void onClickShowOtherObjects(); - static void onClickReturnOwnerObjects(void*); - static void onClickReturnGroupObjects(void*); - static void onClickReturnOtherObjects(void*); - static void onClickReturnOwnerList(void*); - static void onClickRefresh(void*); - - static void onDoubleClickOwner(void*); + void onClickReturnOwnerObjects(); + void onClickReturnGroupObjects(); + void onClickReturnOtherObjects(); + void onClickReturnOwnerList(); + void onClickRefresh(); void onCommitList(); static void onLostFocus(LLFocusableElement* caller, void* user_data); - static void onCommitClean(LLUICtrl* caller, void* user_data); + void onCommitClean(); static void processParcelObjectOwnersReply(LLMessageSystem *msg, void **); - virtual BOOL postBuild(); + BOOL postBuild() override; protected: @@ -319,23 +299,23 @@ class LLPanelLandObjects }; -class LLPanelLandOptions +class LLPanelLandOptions final : public LLPanel { public: LLPanelLandOptions(LLSafeHandle& parcelp); virtual ~LLPanelLandOptions(); - /*virtual*/ BOOL postBuild(); - /*virtual*/ void draw(); - /*virtual*/ void refresh(); + /*virtual*/ BOOL postBuild() override; + /*virtual*/ void draw() override; + /*virtual*/ void refresh() override; private: // Refresh the "show in search" checkbox and category selector. void refreshSearch(); - static void onCommitAny(LLUICtrl* ctrl, void *userdata); - static void onClickSet(void* userdata); - static void onClickClear(void* userdata); + void onCommitAny(); + void onClickSet(); + void onClickClear(); static void onClickPublishHelp(void*); private: @@ -370,28 +350,29 @@ class LLPanelLandOptions }; -class LLPanelLandAccess +class LLPanelLandAccess final : public LLPanel { public: LLPanelLandAccess(LLSafeHandle& parcelp); virtual ~LLPanelLandAccess(); - void refresh(); + void refresh() override; void refresh_ui(); void refreshNames(); - virtual void draw(); + void draw() override; - static void onCommitPublicAccess(LLUICtrl* ctrl, void *userdata); - static void onCommitAny(LLUICtrl* ctrl, void *userdata); - static void onCommitGroupCheck(LLUICtrl* ctrl, void *userdata); - static void onClickRemoveAccess(void*); - static void onClickRemoveBanned(void*); + void onCommitPublicAccess(LLUICtrl* ctrl); + void onCommitAny(); + void onCommitGroupCheck(LLUICtrl* ctrl); + void onClickRemoveAccess(); + void onClickRemoveBanned(); - virtual BOOL postBuild(); + BOOL postBuild() override; void onClickAddAccess(); void onClickAddBanned(); void callbackAvatarCBBanned(const uuid_vec_t& ids); + void callbackAvatarCBBanned2(const uuid_vec_t& ids, S32 duration); void callbackAvatarCBAccess(const uuid_vec_t& ids); protected: @@ -401,22 +382,25 @@ class LLPanelLandAccess LLSafeHandle& mParcel; }; - -class LLPanelLandCovenant +class LLPanelLandCovenant final : public LLPanel { public: LLPanelLandCovenant(LLSafeHandle& parcelp); virtual ~LLPanelLandCovenant(); - virtual BOOL postBuild(); - void refresh(); + BOOL postBuild() override; + void refresh() override; static void updateCovenantText(const std::string& string); static void updateEstateName(const std::string& name); static void updateLastModified(const std::string& text); - static void updateEstateOwnerName(const std::string& name); + static void updateEstateOwnerID(const LLUUID& id); protected: LLSafeHandle& mParcel; + +private: + LLUUID mLastRegionID; + F64 mNextUpdateTime; //seconds since client start }; #endif diff --git a/indra/newview/llfloaterlandmark.cpp b/indra/newview/llfloaterlandmark.cpp index 7ecf7f7f3f..d94546a08c 100644 --- a/indra/newview/llfloaterlandmark.cpp +++ b/indra/newview/llfloaterlandmark.cpp @@ -72,7 +72,6 @@ LLFloaterLandmark::LLFloaterLandmark(const LLSD& data) mFilterEdit(NULL), mContextConeOpacity(0.f), mInventoryPanel(NULL), - mSavedFolderState(NULL), mNoCopyLandmarkSelected( FALSE ) { LLUICtrlFactory::getInstance()->buildFloater(this,"floater_landmark_ctrl.xml"); @@ -105,7 +104,7 @@ BOOL LLFloaterLandmark::postBuild() mInventoryPanel->setAllowMultiSelect(FALSE); // store this filter as the default one - mInventoryPanel->getRootFolder()->getFilter()->markDefault(); + mInventoryPanel->getRootFolder()->getFilter().markDefault(); // Commented out to stop opening all folders with textures mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_LANDMARK); @@ -115,7 +114,6 @@ BOOL LLFloaterLandmark::postBuild() mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO); } - mSavedFolderState = new LLSaveFolderState(); mNoCopyLandmarkSelected = FALSE; getChild("Close")->setClickedCallback(boost::bind(&LLFloaterLandmark::onBtnClose,this)); @@ -127,15 +125,11 @@ BOOL LLFloaterLandmark::postBuild() setCanMinimize(FALSE); - mSavedFolderState->setApply(FALSE); - return true; } LLFloaterLandmark::~LLFloaterLandmark() { - delete mSavedFolderState; - mSavedFolderState = NULL; } void LLFloaterLandmark::setActive( BOOL active ) @@ -394,35 +388,13 @@ void LLFloaterLandmark::onShowFolders(LLUICtrl* ctrl) void LLFloaterLandmark::onFilterEdit(const LLSD& value ) { - std::string upper_case_search_string = value.asString(); - LLStringUtil::toUpper(upper_case_search_string); - - if (upper_case_search_string.empty()) + if (!mInventoryPanel) { - if (mInventoryPanel->getFilterSubString().empty()) - { - // current filter and new filter empty, do nothing - return; - } - - mSavedFolderState->setApply(TRUE); - mInventoryPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - // add folder with current item to list of previously opened folders - LLOpenFoldersWithSelection opener; - mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener); - mInventoryPanel->getRootFolder()->scrollToShowSelection(); - - } - else if (mInventoryPanel->getFilterSubString().empty()) - { - // first letter in search term, save existing folder open state - if (!mInventoryPanel->getRootFolder()->isFilterModified()) - { - mSavedFolderState->setApply(FALSE); - mInventoryPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - } + return; } - mInventoryPanel->setFilterSubString(upper_case_search_string); + // set new filter string + // Internally handles saving/restoring folder states. + mInventoryPanel->setFilterSubString(value.asString()); } diff --git a/indra/newview/llfloaterlandmark.h b/indra/newview/llfloaterlandmark.h index 668590c332..98061e4beb 100644 --- a/indra/newview/llfloaterlandmark.h +++ b/indra/newview/llfloaterlandmark.h @@ -113,7 +113,6 @@ class LLFloaterLandmark: public LLFloater, public LLFloaterSingleton t_panel_status("llpanelmarketplacelistings"); + +LLPanelMarketplaceListings::LLPanelMarketplaceListings() +: mRootFolder(NULL) +, mAuditBtn(nullptr) +, mFilterEditor(nullptr) +, mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME) +, mFilterListingFoldersOnly(false) +{ +} + +LLPanelMarketplaceListings::~LLPanelMarketplaceListings() { delete mMenu; } + +void showMenu(LLView* button, LLMenuGL* menu) +{ + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); + const auto& rect = button->getRect(); + LLMenuGL::showPopup(button->getParent(), menu, rect.mLeft, rect.mBottom); +} + +BOOL LLPanelMarketplaceListings::postBuild() +{ + childSetAction("add_btn", boost::bind(&LLPanelMarketplaceListings::onAddButtonClicked, this)); + childSetAction("audit_btn", boost::bind(&LLPanelMarketplaceListings::onAuditButtonClicked, this)); + mMenu = LLUICtrlFactory::instance().buildMenu("menu_marketplace_view.xml", LLMenuGL::sMenuContainer); + auto sort = getChild("sort_btn"); + sort->setCommitCallback(boost::bind(showMenu, _1, mMenu)); + + mFilterEditor = getChild("filter_editor"); + mFilterEditor->setCommitCallback(boost::bind(&LLPanelMarketplaceListings::onFilterEdit, this, _2)); + + mAuditBtn = getChild("audit_btn"); + mAuditBtn->setEnabled(FALSE); + + return LLPanel::postBuild(); +} + +BOOL LLPanelMarketplaceListings::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + // Special case the drop zone, also we're a giant drop zone + if (!handled_view || (handled_view->getName() == "marketplace_drop_zone")) + { + LLFolderView* root_folder = getRootFolder(); + return root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + return false; +} + +void LLPanelMarketplaceListings::buildAllPanels() +{ + // Build the All panel first + LLInventoryPanel* panel_all_items; + panel_all_items = buildInventoryPanel("All Items", "panel_marketplace_listings_inventory.xml"); + panel_all_items->getFilter().setEmptyLookupMessage("MarketplaceNoMatchingItems"); + panel_all_items->getFilter().markDefault(); + + // Build the other panels + LLInventoryPanel* panel; + panel = buildInventoryPanel("Active Items", "panel_marketplace_listings_listed.xml"); + panel->getFilter().setFilterMarketplaceActiveFolders(); + panel->getFilter().setEmptyLookupMessage("MarketplaceNoMatchingItems"); + panel->getFilter().markDefault(); + panel = buildInventoryPanel("Inactive Items", "panel_marketplace_listings_unlisted.xml"); + panel->getFilter().setFilterMarketplaceInactiveFolders(); + panel->getFilter().setEmptyLookupMessage("MarketplaceNoMatchingItems"); + panel->getFilter().markDefault(); + panel = buildInventoryPanel("Unassociated Items", "panel_marketplace_listings_unassociated.xml"); + panel->getFilter().setFilterMarketplaceUnassociatedFolders(); + panel->getFilter().setEmptyLookupMessage("MarketplaceNoMatchingItems"); + panel->getFilter().markDefault(); + + // Set the tab panel + LLTabContainer* tabs_panel = getChild("marketplace_filter_tabs"); + tabs_panel->setCommitCallback(boost::bind(&LLPanelMarketplaceListings::onTabChange, this)); + tabs_panel->selectTabPanel(panel_all_items); // All panel selected by default + mRootFolder = panel_all_items->getRootFolder(); // Keep the root of the all panel + + // Set the default sort order + setSortOrder(gSavedSettings.getU32("MarketplaceListingsSortOrder")); +} + +LLInventoryPanel* LLPanelMarketplaceListings::buildInventoryPanel(const std::string& childname, const std::string& filename) +{ + LLTabContainer* tabs_panel = getChild("marketplace_filter_tabs"); + // Singu Note: These should already be built!! + LLInventoryPanel* panel = tabs_panel->getChild(childname, false, false); + llassert(panel != NULL); + + // Set sort order and callbacks + panel->getRootFolder()->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME); + panel->setSelectCallback(boost::bind(&LLPanelMarketplaceListings::onSelectionChange, this, panel, _1, _2)); + + return panel; +} + +void LLPanelMarketplaceListings::setSortOrder(U32 sort_order) +{ + mSortOrder = sort_order; + gSavedSettings.setU32("MarketplaceListingsSortOrder", sort_order); + + // Set each panel with that sort order + LLTabContainer* tabs_panel = getChild("marketplace_filter_tabs"); + LLInventoryPanel* panel = (LLInventoryPanel*)tabs_panel->getPanelByName("All Items"); + panel->setSortOrder(mSortOrder); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Active Items"); + panel->setSortOrder(mSortOrder); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Inactive Items"); + panel->setSortOrder(mSortOrder); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Unassociated Items"); + panel->setSortOrder(mSortOrder); +} + +void LLPanelMarketplaceListings::onFilterEdit(const std::string& search_string) +{ + // Find active panel + LLInventoryPanel* panel = (LLInventoryPanel*)getChild("marketplace_filter_tabs")->getCurrentPanel(); + if (panel) + { + // Save filter string (needed when switching tabs) + mFilterSubString = search_string; + // Set filter string on active panel + panel->setFilterSubString(mFilterSubString); + } +} + +void LLPanelMarketplaceListings::draw() +{ + if (LLMarketplaceData::instance().checkDirtyCount()) + { + update_all_marketplace_count(); + } + + // Get the audit button enabled only after the whole inventory is fetched + if (!mAuditBtn->getEnabled()) + { + mAuditBtn->setEnabled(LLInventoryModelBackgroundFetch::instance().isEverythingFetched()); + } + + LLPanel::draw(); +} + +void LLPanelMarketplaceListings::onSelectionChange(LLInventoryPanel *panel, const std::deque& items, BOOL user_action) +{ + panel->onSelectionChange(items, user_action); +} + +bool LLPanelMarketplaceListings::allowDropOnRoot() +{ + LLInventoryPanel* panel = (LLInventoryPanel*)getChild("marketplace_filter_tabs")->getCurrentPanel(); + return (panel ? panel->getAllowDropOnRoot() : false); +} + +void LLPanelMarketplaceListings::onTabChange() +{ + // Find active panel + LLInventoryPanel* panel = (LLInventoryPanel*)getChild("marketplace_filter_tabs")->getCurrentPanel(); + if (panel) + { + // If the panel doesn't allow drop on root, it doesn't allow the creation of new folder on root either + LLButton* add_btn = getChild("add_btn"); + add_btn->setEnabled(panel->getAllowDropOnRoot()); + + // Set filter string on active panel + panel->setFilterSubString(mFilterSubString); + + // Show/hide the drop zone and resize the inventory tabs panel accordingly + LLPanel* drop_zone = (LLPanel*)getChild("marketplace_drop_zone"); + bool drop_zone_visible = drop_zone->getVisible(); + bool allow_drop_on_root = panel->getAllowDropOnRoot(); + if (drop_zone_visible != allow_drop_on_root) + { + LLPanel* tabs = (LLPanel*)getChild("tab_container_panel"); + S32 delta_height = drop_zone->getRect().getHeight(); + delta_height = (drop_zone_visible ? delta_height : -delta_height); + tabs->reshape(tabs->getRect().getWidth(),tabs->getRect().getHeight() + delta_height); + tabs->translate(0,-delta_height); + } + drop_zone->setVisible(allow_drop_on_root); + } +} + +void LLPanelMarketplaceListings::onAddButtonClicked() +{ + // Find active panel + LLInventoryPanel* panel = (LLInventoryPanel*)getChild("marketplace_filter_tabs")->getCurrentPanel(); + if (panel) + { + LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + llassert(marketplacelistings_id.notNull()); + LLFolderType::EType preferred_type = LLFolderType::lookup("category"); + LLUUID category = gInventory.createNewCategory(marketplacelistings_id, preferred_type, LLStringUtil::null); + gInventory.notifyObservers(); + panel->setSelectionByID(category, TRUE); + panel->getRootFolder()->setNeedsAutoRename(TRUE); + } +} + +void LLPanelMarketplaceListings::onAuditButtonClicked() +{ + LLSD data(LLSD::emptyMap()); + new LLFloaterMarketplaceValidation(data); // It tracks itself *sigh* +} + +void LLPanelMarketplaceListings::onViewSortMenuItemClicked(const LLSD& userdata) +{ + std::string chosen_item = userdata.asString(); + + // Sort options + if ((chosen_item == "sort_by_stock_amount") || (chosen_item == "sort_by_name") || (chosen_item == "sort_by_recent")) + { + // We're making sort options exclusive, default is SO_FOLDERS_BY_NAME + if (chosen_item == "sort_by_stock_amount") + { + setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_WEIGHT); + } + else if (chosen_item == "sort_by_name") + { + setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME); + } + else if (chosen_item == "sort_by_recent") + { + setSortOrder(LLInventoryFilter::SO_DATE); + } + } + // Filter option + else if (chosen_item == "show_only_listing_folders") + { + mFilterListingFoldersOnly = !mFilterListingFoldersOnly; + // Set each panel with that filter flag + LLTabContainer* tabs_panel = getChild("marketplace_filter_tabs"); + LLInventoryPanel* panel = (LLInventoryPanel*)tabs_panel->getPanelByName("All Items"); + panel->getFilter().setFilterMarketplaceListingFolders(mFilterListingFoldersOnly); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Active Items"); + panel->getFilter().setFilterMarketplaceListingFolders(mFilterListingFoldersOnly); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Inactive Items"); + panel->getFilter().setFilterMarketplaceListingFolders(mFilterListingFoldersOnly); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Unassociated Items"); + panel->getFilter().setFilterMarketplaceListingFolders(mFilterListingFoldersOnly); + } +} + +bool LLPanelMarketplaceListings::onViewSortMenuItemCheck(const LLSD& userdata) +{ + std::string chosen_item = userdata.asString(); + + if ((chosen_item == "sort_by_stock_amount") || (chosen_item == "sort_by_name") || (chosen_item == "sort_by_recent")) + { + if (chosen_item == "sort_by_stock_amount") + { + return (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_WEIGHT); + } + else if (chosen_item == "sort_by_name") + { + return (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_NAME); + } + else if (chosen_item == "sort_by_recent") + { + return (mSortOrder & LLInventoryFilter::SO_DATE); + } + } + else if (chosen_item == "show_only_listing_folders") + { + return mFilterListingFoldersOnly; + } + return false; +} + +///---------------------------------------------------------------------------- +/// LLMarketplaceListingsAddedObserver helper class +///---------------------------------------------------------------------------- + +class LLMarketplaceListingsAddedObserver : public LLInventoryCategoryAddedObserver +{ +public: + LLMarketplaceListingsAddedObserver(LLFloaterMarketplaceListings * marketplace_listings_floater) + : LLInventoryCategoryAddedObserver() + , mMarketplaceListingsFloater(marketplace_listings_floater) + { + } + + void done() + { + for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it) + { + LLViewerInventoryCategory* added_category = *it; + + LLFolderType::EType added_category_type = added_category->getPreferredType(); + + if (added_category_type == LLFolderType::FT_MARKETPLACE_LISTINGS) + { + mMarketplaceListingsFloater->initializeMarketPlace(); + } + } + } + +private: + LLFloaterMarketplaceListings * mMarketplaceListingsFloater; +}; + +///---------------------------------------------------------------------------- +/// LLFloaterMarketplaceListings +///---------------------------------------------------------------------------- + +LLFloaterMarketplaceListings::LLFloaterMarketplaceListings(const LLSD& key) +: LLFloater(key) +, mCategoriesObserver(NULL) +, mCategoryAddedObserver(NULL) +, mRootFolderId(LLUUID::null) +, mInventoryStatus(NULL) +, mInventoryInitializationInProgress(NULL) +, mInventoryPlaceholder(NULL) +, mInventoryText(NULL) +, mInventoryTitle(NULL) +, mPanelListings(NULL) +, mPanelListingsSet(false) +{ + //buildFromFile("floater_marketplace_listings.xml"); + mFactoryMap["panel_marketplace_listing"] = LLCallbackMap([&](void*) { return mPanelListings = new LLPanelMarketplaceListings; }); + LLUICtrlFactory::instance().buildFloater(this, "floater_marketplace_listings.xml", &getFactoryMap()); +} + +LLFloaterMarketplaceListings::~LLFloaterMarketplaceListings() +{ + if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + } + delete mCategoriesObserver; + + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + } + delete mCategoryAddedObserver; +} + +BOOL LLFloaterMarketplaceListings::postBuild() +{ + mInventoryStatus = getChild("marketplace_status"); + mInventoryInitializationInProgress = getChild("initialization_progress_indicator"); + mInventoryPlaceholder = getChild("marketplace_listings_inventory_placeholder_panel"); + mInventoryText = mInventoryPlaceholder->getChild("marketplace_listings_inventory_placeholder_text"); + mInventoryTitle = mInventoryPlaceholder->getChild("marketplace_listings_inventory_placeholder_title"); + + LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterMarketplaceListings::onFocusReceived, this)); + + // Observe category creation to catch marketplace listings creation (moot if already existing) + mCategoryAddedObserver = new LLMarketplaceListingsAddedObserver(this); + gInventory.addObserver(mCategoryAddedObserver); + + // Fetch aggressively so we can interact with listings right onOpen() + fetchContents(); + + return TRUE; +} + +void LLFloaterMarketplaceListings::onClose(bool app_quitting) +{ + LLFloater::onClose(app_quitting); +} + +void LLFloaterMarketplaceListings::onOpen(/*const LLSD& key*/) +{ + // + // Initialize the Market Place or go update the marketplace listings + // + if (LLMarketplaceData::instance().getSLMStatus() <= MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE) + { + initializeMarketPlace(); + } + else + { + updateView(); + } +} + +void LLFloaterMarketplaceListings::onFocusReceived() +{ + updateView(); +} + +void LLFloaterMarketplaceListings::fetchContents() +{ + if (mRootFolderId.notNull() && + (LLMarketplaceData::instance().getSLMDataFetched() != MarketplaceFetchCodes::MARKET_FETCH_LOADING) && + (LLMarketplaceData::instance().getSLMDataFetched() != MarketplaceFetchCodes::MARKET_FETCH_DONE)) + { + LLMarketplaceData::instance().setDataFetchedSignal(boost::bind(&LLFloaterMarketplaceListings::updateView, this)); + LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_LOADING); + LLInventoryModelBackgroundFetch::instance().start(mRootFolderId); + LLMarketplaceData::instance().getSLMListings(); + } +} + +void LLFloaterMarketplaceListings::setRootFolder() +{ + if ((LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_MERCHANT) && + (LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_MIGRATED_MERCHANT)) + { + // If we are *not* a merchant or we have no market place connection established yet, do nothing + return; + } + + // We are a merchant. Get the Marketplace listings folder, create it if needs be. + LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, true); + if (marketplacelistings_id.isNull()) + { + // We should never get there unless the inventory fails badly + LL_ERRS("SLM") << "Inventory problem: failure to create the marketplace listings folder for a merchant!" << LL_ENDL; + return; + } + + // No longer need to observe new category creation + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + delete mCategoryAddedObserver; + mCategoryAddedObserver = NULL; + } + llassert(!mCategoryAddedObserver); + + if (marketplacelistings_id == mRootFolderId) + { + LL_WARNS("SLM") << "Inventory warning: Marketplace listings folder already set" << LL_ENDL; + return; + } + + mRootFolderId = marketplacelistings_id; +} + +void LLFloaterMarketplaceListings::setPanels() +{ + if (mRootFolderId.isNull()) + { + return; + } + + // Consolidate Marketplace listings + // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention, + // things get messy and conventions get broken down eventually + gInventory.consolidateForType(mRootFolderId, LLFolderType::FT_MARKETPLACE_LISTINGS); + + // Now that we do have a non NULL root, we can build the inventory panels + mPanelListings->buildAllPanels(); + + // Create observer for marketplace listings modifications + if (!mCategoriesObserver) + { + mCategoriesObserver = new LLInventoryCategoriesObserver(); + llassert(mCategoriesObserver); + gInventory.addObserver(mCategoriesObserver); + mCategoriesObserver->addCategory(mRootFolderId, boost::bind(&LLFloaterMarketplaceListings::onChanged, this)); + } + + // Get the content of the marketplace listings folder + fetchContents(); + + // Flag that this is done + mPanelListingsSet = true; +} + +void LLFloaterMarketplaceListings::initializeMarketPlace() +{ + LLMarketplaceData::instance().initializeSLM(boost::bind(&LLFloaterMarketplaceListings::updateView, this)); +} + +S32 LLFloaterMarketplaceListings::getFolderCount() +{ + if (mPanelListings && mRootFolderId.notNull()) + { + LLInventoryModel::cat_array_t * cats; + LLInventoryModel::item_array_t * items; + gInventory.getDirectDescendentsOf(mRootFolderId, cats, items); + + return (cats->size() + items->size()); + } + else + { + return 0; + } +} + +void LLFloaterMarketplaceListings::setStatusString(const std::string& statusString) +{ + mInventoryStatus->setText(statusString); +} + +void LLFloaterMarketplaceListings::updateView() +{ + U32 mkt_status = LLMarketplaceData::instance().getSLMStatus(); + bool is_merchant = (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_MERCHANT) || (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_MIGRATED_MERCHANT); + U32 data_fetched = LLMarketplaceData::instance().getSLMDataFetched(); + + // Get or create the root folder if we are a merchant and it hasn't been done already + if (mRootFolderId.isNull() && is_merchant) + { + setRootFolder(); + } + + // Update the bottom initializing status and progress dial if we are initializing or if we're a merchant and still loading + if ((mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) || (is_merchant && (data_fetched <= MarketplaceFetchCodes::MARKET_FETCH_LOADING)) ) + { + // Just show the loading indicator in that case and fetch the data (fetch will be skipped if it's already loading) + mInventoryInitializationInProgress->setVisible(true); + mPanelListings->setVisible(FALSE); + fetchContents(); + return; + } + else + { + mInventoryInitializationInProgress->setVisible(false); + } + + // Update the middle portion : tabs or messages + if (getFolderCount() > 0) + { + if (!mPanelListingsSet) + { + // We need to rebuild the tabs cleanly the first time we make them visible + setPanels(); + } + mPanelListings->setVisible(TRUE); + mInventoryPlaceholder->setVisible(FALSE); + } + else + { + mPanelListings->setVisible(FALSE); + mInventoryPlaceholder->setVisible(TRUE); + + std::string text; + std::string title; + std::string tooltip; + + const LLSD& subs = LLMarketplaceData::instance().getMarketplaceStringSubstitutions(); + + // Update the top message or flip to the tabs and folders view + // *TODO : check those messages and create better appropriate ones in strings.xml + if (mRootFolderId.notNull()) + { + // "Marketplace listings is empty!" message strings + text = LLTrans::getString("InventoryMarketplaceListingsNoItems", subs); + title = LLTrans::getString("InventoryMarketplaceListingsNoItemsTitle"); + tooltip = LLTrans::getString("InventoryMarketplaceListingsNoItemsTooltip"); + } + else if (mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) + { + // "Initializing!" message strings + text = LLTrans::getString("InventoryOutboxInitializing", subs); + title = LLTrans::getString("InventoryOutboxInitializingTitle"); + tooltip = LLTrans::getString("InventoryOutboxInitializingTooltip"); + } + else if (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT) + { + // "Not a merchant!" message strings + text = LLTrans::getString("InventoryOutboxNotMerchant", subs); + title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); + tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); + } + else + { + // "Errors!" message strings + text = LLTrans::getString("InventoryMarketplaceError", subs); + title = LLTrans::getString("InventoryOutboxErrorTitle"); + tooltip = LLTrans::getString("InventoryOutboxErrorTooltip"); + } + + mInventoryText->setValue(text); + mInventoryTitle->setValue(title); + mInventoryPlaceholder->getParent()->setToolTip(tooltip); + } +} + +bool LLFloaterMarketplaceListings::isAccepted(EAcceptance accept) +{ + return (accept >= ACCEPT_YES_COPY_SINGLE); +} + +BOOL LLFloaterMarketplaceListings::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + // If there's no panel to accept drops or no existing marketplace listings folder, we refuse all drop + if (!mPanelListings || mRootFolderId.isNull()) + { + return FALSE; + } + + tooltip_msg = ""; + + // Pass to the children + LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + BOOL handled = (handled_view != NULL); + + // If no one handled it or it was not accepted and we drop on an empty panel, we try to accept it at the floater level + // as if it was dropped on the marketplace listings root folder + if ((!handled || !isAccepted(*accept)) && !mPanelListings->getVisible() && mRootFolderId.notNull()) + { + if (!mPanelListingsSet) + { + setPanels(); + } + LLFolderView* root_folder = mPanelListings->getRootFolder(); + handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + + return handled; +} + +BOOL LLFloaterMarketplaceListings::handleHover(S32 x, S32 y, MASK mask) +{ + return LLFloater::handleHover(x, y, mask); +} + +void LLFloaterMarketplaceListings::onMouseLeave(S32 x, S32 y, MASK mask) +{ + LLFloater::onMouseLeave(x, y, mask); +} + +void LLFloaterMarketplaceListings::onChanged() +{ + LLViewerInventoryCategory* category = gInventory.getCategory(mRootFolderId); + if (mRootFolderId.notNull() && category) + { + updateView(); + } + else + { + // Invalidate the marketplace listings data + mRootFolderId.setNull(); + } +} + +//----------------------------------------------------------------------------- +// LLFloaterAssociateListing +//----------------------------------------------------------------------------- + +// Tell if a listing has one only version folder +bool hasUniqueVersionFolder(const LLUUID& folder_id) +{ + LLInventoryModel::cat_array_t* categories; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(folder_id, categories, items); + return (categories->size() == 1); +} + +LLFloaterAssociateListing::LLFloaterAssociateListing(const LLSD& key) +: LLFloater(key) +, mUUID() +{ + //buildFromFile("floater_associate_listing.xml"); + LLUICtrlFactory::instance().buildFloater(this, "floater_associate_listing.xml"); +} + +LLFloaterAssociateListing::~LLFloaterAssociateListing() +{ + gFocusMgr.releaseFocusIfNeeded( this ); +} + +BOOL LLFloaterAssociateListing::postBuild() +{ + getChild("OK")->setCommitCallback(boost::bind(&LLFloaterAssociateListing::apply, this, TRUE)); + getChild("Cancel")->setCommitCallback(boost::bind(&LLFloaterAssociateListing::cancel, this)); + getChild("listing_id")->setPrevalidate(&LLLineEditor::prevalidateNonNegativeS32); + center(); + + return LLFloater::postBuild(); +} + +BOOL LLFloaterAssociateListing::handleKeyHere(KEY key, MASK mask) +{ + if (key == KEY_RETURN && mask == MASK_NONE) + { + apply(); + return TRUE; + } + else if (key == KEY_ESCAPE && mask == MASK_NONE) + { + cancel(); + return TRUE; + } + + return LLFloater::handleKeyHere(key, mask); +} + +// static +void LLFloaterAssociateListing::show(LLFloaterAssociateListing* floater, const LLSD& folder_id) +{ + if (!floater) return; + + floater->mUUID = folder_id.asUUID(); + + floater->open(); +} + +// Callback for apply if DAMA required... +void LLFloaterAssociateListing::callback_apply(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + apply(FALSE); + } +} + +void LLFloaterAssociateListing::apply(BOOL user_confirm) +{ + if (mUUID.notNull()) + { + S32 id = (S32)getChild("listing_id")->getValue().asInteger(); + if (id > 0) + { + // Check if the id exists in the merchant SLM DB: note that this record might exist in the LLMarketplaceData + // structure even if unseen in the UI, for instance, if its listing_uuid doesn't exist in the merchant inventory + LLUUID listing_uuid = LLMarketplaceData::instance().getListingFolder(id); + if (listing_uuid.notNull() && user_confirm && LLMarketplaceData::instance().getActivationState(listing_uuid) && !hasUniqueVersionFolder(mUUID)) + { + // Look for user confirmation before unlisting + LLNotificationsUtil::add("ConfirmMerchantUnlist", LLSD(), LLSD(), boost::bind(&LLFloaterAssociateListing::callback_apply, this, _1, _2)); + return; + } + // Associate the id with the user chosen folder + LLMarketplaceData::instance().associateListing(mUUID,listing_uuid,id); + } + else + { + LLNotificationsUtil::add("AlertMerchantListingInvalidID"); + } + } + close(); +} + +void LLFloaterAssociateListing::cancel() +{ + close(); +} + +//----------------------------------------------------------------------------- +// LLFloaterMarketplaceValidation +//----------------------------------------------------------------------------- + +// Note: The key is the UUID of the folder to validate. +// Validates the whole marketplace listings content if UUID is null. + +LLFloaterMarketplaceValidation::LLFloaterMarketplaceValidation(const LLSD& key) +: LLFloater(), + mKey(key), + mEditor(NULL) +{ + //buildFromFile("floater_marketplace_validation.xml"); + LLUICtrlFactory::instance().buildFloater(this, "floater_marketplace_validation.xml"); +} + +BOOL LLFloaterMarketplaceValidation::postBuild() +{ + childSetAction("OK", onOK, this); + + // This widget displays the validation messages + mEditor = getChild("validation_text"); + mEditor->setEnabled(FALSE); + mEditor->setFocus(TRUE); + mEditor->setValue(LLSD()); + + return TRUE; +} + +LLFloaterMarketplaceValidation::~LLFloaterMarketplaceValidation() +{ +} + +// virtual +void LLFloaterMarketplaceValidation::draw() +{ + // draw children + LLFloater::draw(); +} + +void LLFloaterMarketplaceValidation::onOpen(/*const LLSD& key*/) +{ + // Clear the messages + clearMessages(); + + // Get the folder UUID to validate. Use the whole marketplace listing if none provided. + LLUUID cat_id(mKey.asUUID()); + if (cat_id.isNull()) + { + cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + } + + // Validates the folder + if (cat_id.notNull()) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); + validate_marketplacelistings(cat, boost::bind(&LLFloaterMarketplaceValidation::appendMessage, this, _1, _2, _3), false); + } + + // Handle the listing folder being processed + handleCurrentListing(); + + // Dump result to the editor panel + if (mEditor) + { + mEditor->setValue(LLSD()); + if (mMessages.empty()) + { + // Display a no error message + mEditor->appendText(LLTrans::getString("Marketplace Validation No Error"), false, false); + } + else + { + // Print out all the messages to the panel + message_list_t::iterator mCurrentLine = mMessages.begin(); + bool new_line = false; + while (mCurrentLine != mMessages.end()) + { + // Errors are printed in bold, other messages in normal font + LLStyleSP style(new LLStyle); + style->setColor(mEditor->getReadOnlyFgColor()); + style->mBold = mCurrentLine->mErrorLevel == LLError::LEVEL_ERROR; + mEditor->appendText(mCurrentLine->mMessage, false, new_line, style); + new_line = true; + mCurrentLine++; + } + } + } + // We don't need the messages anymore + clearMessages(); +} + +// static +void LLFloaterMarketplaceValidation::onOK( void* userdata ) +{ + // destroys this object + LLFloaterMarketplaceValidation* self = (LLFloaterMarketplaceValidation*) userdata; + self->clearMessages(); + self->close(); +} + +void LLFloaterMarketplaceValidation::appendMessage(std::string& message, S32 depth, LLError::ELevel log_level) +{ + // Dump previous listing messages if we're starting a new listing + if (depth == 1) + { + handleCurrentListing(); + } + + // Store the message in the current listing message list + Message current_message; + current_message.mErrorLevel = log_level; + current_message.mMessage = message; + mCurrentListingMessages.push_back(current_message); + mCurrentListingErrorLevel = (mCurrentListingErrorLevel < log_level ? log_level : mCurrentListingErrorLevel); +} + +// Move the current listing messages to the general list if needs be and reset the current listing data +void LLFloaterMarketplaceValidation::handleCurrentListing() +{ + // Dump the current folder messages to the general message list if level warrants it + if (mCurrentListingErrorLevel > LLError::LEVEL_INFO) + { + message_list_t::iterator mCurrentLine = mCurrentListingMessages.begin(); + while (mCurrentLine != mCurrentListingMessages.end()) + { + mMessages.push_back(*mCurrentLine); + mCurrentLine++; + } + } + + // Reset the current listing + mCurrentListingMessages.clear(); + mCurrentListingErrorLevel = LLError::LEVEL_INFO; +} + +void LLFloaterMarketplaceValidation::clearMessages() +{ + mMessages.clear(); + mCurrentListingMessages.clear(); + mCurrentListingErrorLevel = LLError::LEVEL_INFO; +} + +/* Singu Note: What even is this? Where is this used?! +//----------------------------------------------------------------------------- +// LLFloaterItemProperties +//----------------------------------------------------------------------------- + +LLFloaterItemProperties::LLFloaterItemProperties(const LLSD& key) +: LLFloater(key) +{ +} + +LLFloaterItemProperties::~LLFloaterItemProperties() +{ +} + +BOOL LLFloaterItemProperties::postBuild() +{ + // On the standalone properties floater, we have no need for a back button... + LLPanel* panel = getChild("item_panel"); + LLButton* back_btn = panel->getChild("back_btn"); + back_btn->setVisible(FALSE); + + return LLFloater::postBuild(); +} + +void LLFloaterItemProperties::onOpen(const LLSD& key) +{ + // Tell the panel which item it needs to visualize + LLPanel* panel = getChild("item_panel"); + panel->setItemID(mKey["id"].asUUID()); +} +*/ diff --git a/indra/newview/llfloatermarketplacelistings.h b/indra/newview/llfloatermarketplacelistings.h new file mode 100644 index 0000000000..496117a7f8 --- /dev/null +++ b/indra/newview/llfloatermarketplacelistings.h @@ -0,0 +1,239 @@ +/** + * @file llfloatermarketplacelistings.h + * @brief Implementation of the marketplace listings floater and panels + * @author merov@lindenlab.com + * + * $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 + * ABILITY 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_LLFLOATERMARKETPLACELISTINGS_H +#define LL_LLFLOATERMARKETPLACELISTINGS_H + +#include "llfloater.h" +#include "llinventoryfilter.h" +#include "llinventorypanel.h" +#include "llnotificationptr.h" +#include "llmodaldialog.h" +#include "lltexteditor.h" + +class LLInventoryCategoriesObserver; +class LLInventoryCategoryAddedObserver; +class LLTextBox; +class LLView; +class LLFilterEditor; + +class LLFloaterMarketplaceListings; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLPanelMarketplaceListings +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLPanelMarketplaceListings : public LLPanel +{ +public: + LLPanelMarketplaceListings(); + ~LLPanelMarketplaceListings(); + BOOL postBuild(); + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + void draw(); + LLFolderView* getRootFolder() { return mRootFolder; } + bool allowDropOnRoot(); + + void buildAllPanels(); + +private: + friend struct MarketplaceViewSortAction; + friend struct MarketplaceViewSortCheckItem; + + LLInventoryPanel* buildInventoryPanel(const std::string& childname, const std::string& filename); + + // UI callbacks + void onViewSortMenuItemClicked(const LLSD& userdata); + bool onViewSortMenuItemCheck(const LLSD& userdata); + void onAddButtonClicked(); + void onAuditButtonClicked(); + void onSelectionChange(LLInventoryPanel *panel, const std::deque& items, BOOL user_action); + void onTabChange(); + void onFilterEdit(const std::string& search_string); + + void setSortOrder(U32 sort_order); + + LLFolderView* mRootFolder; + LLButton* mAuditBtn; + class LLMenuGL* mMenu; + LLFilterEditor* mFilterEditor; + std::string mFilterSubString; + bool mFilterListingFoldersOnly; + U32 mSortOrder; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFloaterMarketplaceListings +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFloaterMarketplaceListings : public LLFloater, public LLFloaterSingleton +{ +public: + LLFloaterMarketplaceListings(const LLSD& key); + ~LLFloaterMarketplaceListings(); + + void initializeMarketPlace(); + + // virtuals + BOOL postBuild(); + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + void showNotification(const LLNotificationPtr& notification); + + BOOL handleHover(S32 x, S32 y, MASK mask); + void onMouseLeave(S32 x, S32 y, MASK mask); + +protected: + void setRootFolder(); + void setPanels(); + void fetchContents(); + + void setStatusString(const std::string& statusString); + + void onClose(bool app_quitting); + void onOpen(/*const LLSD& key*/); + void onFocusReceived(); + void onChanged(); + + bool isAccepted(EAcceptance accept); + + void updateView(); + +private: + friend struct MarketplaceViewSortAction; + friend struct MarketplaceViewSortCheckItem; + S32 getFolderCount(); + + LLInventoryCategoriesObserver * mCategoriesObserver; + LLInventoryCategoryAddedObserver * mCategoryAddedObserver; + + LLTextBox * mInventoryStatus; + LLView * mInventoryInitializationInProgress; + LLView * mInventoryPlaceholder; + LLTextEditor * mInventoryText; + LLTextBox * mInventoryTitle; + + LLUUID mRootFolderId; + LLPanelMarketplaceListings * mPanelListings; + bool mPanelListingsSet; +}; + +//----------------------------------------------------------------------------- +// LLFloaterAssociateListing +//----------------------------------------------------------------------------- +class LLFloaterAssociateListing : public LLFloater, public LLUISingleton +{ +friend class LLUISingleton; +public: + virtual BOOL postBuild(); + virtual BOOL handleKeyHere(KEY key, MASK mask); + + static bool visible(LLFloaterAssociateListing* floater, const LLSD& key) { return floater && !floater->isMinimized() && floater->isInVisibleChain(); } + static void show(LLFloaterAssociateListing* floater, const LLSD& folder_id); + static void hide(LLFloaterAssociateListing* floater, const LLSD& key) { if (floater) floater->close(); } + +private: + LLFloaterAssociateListing(const LLSD& key); + virtual ~LLFloaterAssociateListing(); + + // UI Callbacks + void apply(BOOL user_confirm = TRUE); + void cancel(); + void callback_apply(const LLSD& notification, const LLSD& response); + + LLUUID mUUID; +}; + +//----------------------------------------------------------------------------- +// LLFloaterMarketplaceValidation +//----------------------------------------------------------------------------- +// Note: The key is the UUID of the folder to validate. Validates the whole +// marketplace listings content if UUID is null. +// Note: For the moment, we just display the validation text. Eventually, we should +// get the validation triggered on the server and display the html report. +// *TODO : morph into an html/text window using the pattern in llfloatertos + +class LLFloaterMarketplaceValidation : public LLFloater +{ +public: + LLFloaterMarketplaceValidation(const LLSD& key); + virtual ~LLFloaterMarketplaceValidation(); + + virtual BOOL postBuild(); + virtual void draw(); + virtual void onOpen(/*const LLSD& key*/); + + void clearMessages(); + void appendMessage(std::string& message, S32 depth, LLError::ELevel log_level); + static void onOK( void* userdata ); + +private: + struct Message { + LLError::ELevel mErrorLevel; + std::string mMessage; + }; + typedef std::vector message_list_t; + + void handleCurrentListing(); + + message_list_t mCurrentListingMessages; + LLError::ELevel mCurrentListingErrorLevel; + + message_list_t mMessages; + + LLSD mKey; + LLTextEditor* mEditor; +}; + + +#if 0 +//----------------------------------------------------------------------------- +// LLFloaterItemProperties +//----------------------------------------------------------------------------- + +class LLFloaterItemProperties : public LLFloater +{ +public: + LLFloaterItemProperties(const LLSD& key); + virtual ~LLFloaterItemProperties(); + + BOOL postBuild(); + virtual void onOpen(/*const LLSD& key*/); + +private: +}; +#endif + +#endif // LL_LLFLOATERMARKETPLACELISTINGS_H diff --git a/indra/newview/llfloatermediafilter.cpp b/indra/newview/llfloatermediafilter.cpp index 3b636484b3..f03216ff07 100644 --- a/indra/newview/llfloatermediafilter.cpp +++ b/indra/newview/llfloatermediafilter.cpp @@ -77,11 +77,11 @@ void LLFloaterMediaFilter::updateLists(LLMediaFilter::EMediaList list_type) const LLMediaFilter::string_list_t& list = white ? inst.getWhiteList() : inst.getBlackList(); LLScrollListCtrl* scroll(white ? mWhitelist : mBlacklist); scroll->clearRows(); - for (LLMediaFilter::string_list_t::const_iterator itr = list.begin(); itr != list.end(); ++itr) + for (const auto& value : list) { LLSD element; element["columns"][0]["column"] = "list"; - element["columns"][0]["value"] = (*itr); + element["columns"][0]["value"] = value; scroll->addElement(element); } enableButton(getChildView(white ? "remove_whitelist" : "remove_blacklist"), scroll); @@ -103,9 +103,9 @@ void LLFloaterMediaFilter::onRemoveFromList(bool white) { std::vector selected = (white ? mWhitelist : mBlacklist)->getAllSelected(); LLMediaFilter::string_vec_t domains; - for (std::vector::iterator itr = selected.begin(); itr != selected.end(); ++itr) + for (auto* item : selected) { - domains.push_back((*itr)->getColumn(0)->getValue().asString()); + domains.push_back(item->getColumn(0)->getValue().asString()); } LLMediaFilter::getInstance()->removeFromMediaList(domains, white ? LLMediaFilter::WHITELIST : LLMediaFilter::BLACKLIST); } diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp index f0f1f38695..53e405af8d 100644 --- a/indra/newview/llfloatermediasettings.cpp +++ b/indra/newview/llfloatermediasettings.cpp @@ -43,10 +43,13 @@ LLFloaterMediaSettings* LLFloaterMediaSettings::sInstance = NULL; // LLFloaterMediaSettings::LLFloaterMediaSettings(const LLSD& key) : LLFloater(key), - mTabContainer(NULL), - mPanelMediaSettingsGeneral(NULL), - mPanelMediaSettingsSecurity(NULL), - mPanelMediaSettingsPermissions(NULL), + mOKBtn(nullptr), + mCancelBtn(nullptr), + mApplyBtn(nullptr), + mTabContainer(nullptr), + mPanelMediaSettingsGeneral(nullptr), + mPanelMediaSettingsSecurity(nullptr), + mPanelMediaSettingsPermissions(nullptr), mWaitingToClose( false ), mIdenticalHasMediaInfo( true ), mMultipleMedia(false), diff --git a/indra/newview/llfloatermessagelog.cpp b/indra/newview/llfloatermessagelog.cpp index 8847ca2ca2..39072b1bf0 100644 --- a/indra/newview/llfloatermessagelog.cpp +++ b/indra/newview/llfloatermessagelog.cpp @@ -86,11 +86,11 @@ LLFloaterMessageLogItem::LLFloaterMessageLogItem(LLMessageLogEntry entry) mSummary.append(" ] "); } - LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end(); - for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin(); + LLMessageTemplate::message_block_map_t::const_iterator blocks_end = temp->mMemberBlocks.end(); + for (LLMessageTemplate::message_block_map_t::const_iterator blocks_iter = temp->mMemberBlocks.begin(); blocks_iter != blocks_end; ++blocks_iter) { - LLMessageBlock* block = (*blocks_iter); + const LLMessageBlock* block = temp->mMemberBlocks.toValue(blocks_iter); const char* block_name = block->mName; S32 num_blocks = sTemplateMessageReader->getNumberOfBlocks(block_name); if(!num_blocks) @@ -100,11 +100,11 @@ LLFloaterMessageLogItem::LLFloaterMessageLogItem(LLMessageLogEntry entry) else for(S32 i = 0; i < 1; i++) { mSummary.append(" { "); - LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end(); - for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin(); + LLMessageBlock::message_variable_map_t::const_iterator var_end = block->mMemberVariables.end(); + for (LLMessageBlock::message_variable_map_t::const_iterator var_iter = block->mMemberVariables.begin(); var_iter != var_end; ++var_iter) { - LLMessageVariable* variable = (*var_iter); + const LLMessageVariable* variable = block->mMemberVariables.toValue(var_iter); const char* var_name = variable->getName(); BOOL returned_hex; std::string value = getString(sTemplateMessageReader, block_name, i, var_name, variable->getType(), returned_hex, TRUE); @@ -179,21 +179,22 @@ std::string LLFloaterMessageLogItem::getFull(BOOL show_header) full.append(llformat("LL_RESENT_FLAG = %s\n", (mFlags & LL_RESENT_FLAG) ? "True" : "False")); full.append(llformat("LL_ACK_FLAG = %s\n", (mFlags & LL_ACK_FLAG) ? "True" : "False")); } - LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end(); - for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin(); + LLMessageTemplate::message_block_map_t::const_iterator blocks_end = temp->mMemberBlocks.end(); + for (LLMessageTemplate::message_block_map_t::const_iterator blocks_iter = temp->mMemberBlocks.begin(); blocks_iter != blocks_end; ++blocks_iter) { - LLMessageBlock* block = (*blocks_iter); + const LLMessageBlock* block = temp->mMemberBlocks.toValue(blocks_iter); const char* block_name = block->mName; S32 num_blocks = sTemplateMessageReader->getNumberOfBlocks(block_name); for(S32 i = 0; i < num_blocks; i++) { full.append(llformat("[%s]\n", block->mName)); - LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end(); - for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin(); + LLMessageBlock::message_variable_map_t::const_iterator var_end = block->mMemberVariables.end(); + for (LLMessageBlock::message_variable_map_t::const_iterator var_iter = block->mMemberVariables.begin(); var_iter != var_end; ++var_iter) { - LLMessageVariable* variable = (*var_iter); + const LLMessageVariable* variable = block->mMemberVariables.toValue(var_iter); + //LLMessageVariable* variable = var_iter->second; const char* var_name = variable->getName(); BOOL returned_hex; std::string value = getString(sTemplateMessageReader, block_name, i, var_name, variable->getType(), returned_hex); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 327a37cdd6..dc73d08600 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -32,10 +32,8 @@ #include "llviewerprecompiledheaders.h" -#include "dae.h" -#include "dom/domCOLLADA.h" -#include "dom/domConstants.h" -#include "dom/domProfile_COMMON.h" +#include "llmodelloader.h" +#include "lldaeloader.h" #include "llfloatermodelpreview.h" @@ -53,6 +51,7 @@ #include "llmatrix4a.h" #include "llnotificationsutil.h" #include "llsdutil_math.h" +#include "llskinningutil.h" #include "lltextbox.h" #include "lltoolmgr.h" #include "llui.h" @@ -82,12 +81,11 @@ #include "hippogridmanager.h" #include "hippolimits.h" -const S32 SLM_SUPPORTED_VERSION = 3; - //static S32 LLFloaterModelPreview::sUploadAmount = 10; LLFloaterModelPreview* LLFloaterModelPreview::sInstance = NULL; -std::list LLModelLoader::sActiveLoaderList; + +bool LLModelPreview::sIgnoreLoadedCallback = false; // "Retain%" decomp parameter has values from 0.0 to 1.0 by 0.01 // But according to the UI spec for upload model floater, this parameter @@ -104,238 +102,129 @@ const S32 SMOOTH_VALUES_NUMBER = 10; void drawBoxOutline(const LLVector3& pos, const LLVector3& size); -std::string lod_name[NUM_LOD] = + +std::string lod_name[NUM_LOD+1] = { "lowest", "low", "medium", "high", + "I went off the end of the lod_name array. Me so smart." }; -std::string lod_triangles_name[NUM_LOD] = +std::string lod_triangles_name[NUM_LOD+1] = { "lowest_triangles", "low_triangles", "medium_triangles", "high_triangles", + "I went off the end of the lod_triangles_name array. Me so smart." }; -std::string lod_vertices_name[NUM_LOD] = +std::string lod_vertices_name[NUM_LOD+1] = { "lowest_vertices", "low_vertices", "medium_vertices", "high_vertices", + "I went off the end of the lod_vertices_name array. Me so smart." }; -std::string lod_status_name[NUM_LOD] = +std::string lod_status_name[NUM_LOD+1] = { "lowest_status", "low_status", "medium_status", "high_status", + "I went off the end of the lod_status_name array. Me so smart." }; -std::string lod_icon_name[NUM_LOD] = +std::string lod_icon_name[NUM_LOD+1] = { "status_icon_lowest", "status_icon_low", "status_icon_medium", "status_icon_high", + "I went off the end of the lod_status_name array. Me so smart." }; -std::string lod_status_image[NUM_LOD] = +std::string lod_status_image[] = { "green_checkmark.png", "lag_status_warning.tga", "red_x.png", + "I went off the end of the lod_status_image array. Me so smart." }; -std::string lod_label_name[NUM_LOD] = +std::string lod_label_name[NUM_LOD+1] = { "lowest_label", "low_label", "medium_label", "high_label", + "I went off the end of the lod_label_name array. Me so smart." }; -std::string colladaVersion[VERSIONTYPE_COUNT + 1] = -{ - "1.4.0", - "1.4.1", - "Unsupported" -}; - -#define LL_DEGENERACY_TOLERANCE 1e-7f - -inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b) -{ - volatile F32 p0 = a[0] * b[0]; - volatile F32 p1 = a[1] * b[1]; - volatile F32 p2 = a[2] * b[2]; - return p0 + p1 + p2; -} - -bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE) +BOOL stop_gloderror() { - // small area check - { - LLVector4a edge1; edge1.setSub(a, b); - LLVector4a edge2; edge2.setSub(a, c); - ////////////////////////////////////////////////////////////////////////// - /// Linden Modified - ////////////////////////////////////////////////////////////////////////// - - // If no one edge is more than 10x longer than any other edge, we weaken - // the tolerance by a factor of 1e-4f. - - LLVector4a edge3; edge3.setSub(c, b); - const F32 len1sq = edge1.dot3(edge1).getF32(); - const F32 len2sq = edge2.dot3(edge2).getF32(); - const F32 len3sq = edge3.dot3(edge3).getF32(); - bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq); - bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq); - bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq); - if (abOK && acOK && cbOK) - { - tolerance *= 1e-4f; - } - - ////////////////////////////////////////////////////////////////////////// - /// End Modified - ////////////////////////////////////////////////////////////////////////// - - LLVector4a cross; cross.setCross3(edge1, edge2); - - LLVector4a edge1b; edge1b.setSub(b, a); - LLVector4a edge2b; edge2b.setSub(b, c); - LLVector4a crossb; crossb.setCross3(edge1b, edge2b); - - if ((cross.dot3(cross).getF32() < tolerance) || (crossb.dot3(crossb).getF32() < tolerance)) - { - return true; - } - } + GLuint error = glodGetError(); - // point triangle distance check + if (error != GLOD_NO_ERROR) { - LLVector4a Q; Q.setSub(a, b); - LLVector4a R; R.setSub(c, b); - - const F32 QQ = dot3fpu(Q, Q); - const F32 RR = dot3fpu(R, R); - const F32 QR = dot3fpu(R, Q); - - volatile F32 QQRR = QQ * RR; - volatile F32 QRQR = QR * QR; - F32 Det = (QQRR - QRQR); - - if (Det == 0.0f) - { - return true; - } + LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << LL_ENDL; + return TRUE; } - return false; + return FALSE; } -bool validate_face(const LLVolumeFace& face) +LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material) { + LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW); - for (S32 v = 0; v < face.mNumVertices; v++) - { - if(face.mPositions && !face.mPositions[v].isFinite3()) - { - LL_WARNS() << "NaN position data in face found!" << LL_ENDL; - return false; - } - - if(face.mNormals && !face.mNormals[v].isFinite3()) - { - LL_WARNS() << "NaN normal data in face found!" << LL_ENDL; - return false; - } - } - - for (S32 i = 0; i < face.mNumIndices; ++i) + if (texture) { - if (face.mIndices[i] >= face.mNumVertices) + if (texture->getDiscardLevel() > -1) { - LL_WARNS() << "Face has invalid index." << LL_ENDL; - return false; + gGL.getTexUnit(0)->bind(texture, true); + return texture; } } - if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0) - { - LL_WARNS() << "Face has invalid number of indices." << LL_ENDL; - return false; - } - - /*const LLVector4a scale(0.5f); - - for (U32 i = 0; i < face.mNumIndices; i+=3) - { - U16 idx1 = face.mIndices[i]; - U16 idx2 = face.mIndices[i + 1]; - U16 idx3 = face.mIndices[i+2]; - - LLVector4a v1; v1.setMul(face.mPositions[idx1], scale); - LLVector4a v2; v2.setMul(face.mPositions[idx2], scale); - LLVector4a v3; v3.setMul(face.mPositions[idx3], scale); - - if (ll_is_degenerate(v1,v2,v3)) - { - LL_WARNS() << "Degenerate face found!" << LL_ENDL; - return false; - } - }*/ - - return true; + return NULL; } -bool validate_model(const LLModel* mdl) +std::string stripSuffix(std::string name) { - if (mdl->getNumVolumeFaces() == 0) + if ((name.find("_LOD") != std::string::npos) || (name.find("_PHYS") != std::string::npos)) { - LL_WARNS() << "Model has no faces!" << LL_ENDL; - return false; + return name.substr(0, name.rfind('_')); } - - for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) - { - if (mdl->getVolumeFace(i).mNumVertices == 0) - { - LL_WARNS() << "Face has no vertices." << LL_ENDL; - return false; - } - - if (mdl->getVolumeFace(i).mNumIndices == 0) - { - LL_WARNS() << "Face has no indices." << LL_ENDL; - return false; - } - - if (!validate_face(mdl->getVolumeFace(i))) - { - return false; - } - } - - return true; + return name; } -BOOL stop_gloderror() -{ - GLuint error = glodGetError(); - - if (error != GLOD_NO_ERROR) - { - LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << std::dec << LL_ENDL; - return TRUE; - } - - return FALSE; +void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut) +{ + LLModelLoader::scene::iterator base_iter = scene.begin(); + bool found = false; + while (!found && (base_iter != scene.end())) + { + matOut = base_iter->first; + + LLModelLoader::model_instance_list::iterator base_instance_iter = base_iter->second.begin(); + while (!found && (base_instance_iter != base_iter->second.end())) + { + LLModelInstance& base_instance = *base_instance_iter++; + LLModel* base_model = base_instance.mModel; + + if (base_model && (base_model->mLabel == name_to_match)) + { + baseModelOut = base_model; + return; + } + } + base_iter++; + } } //----------------------------------------------------------------------------- @@ -475,9 +364,16 @@ BOOL LLFloaterModelPreview::postBuild() mUploadBtn = getChild("ok_btn"); mCalculateBtn = getChild("calculate_btn"); + if (LLConvexDecomposition::getInstance() != NULL) + { mCalculateBtn->setClickedCallback(boost::bind(&LLFloaterModelPreview::onClickCalculateBtn, this)); toggleCalculateButton(true); + } + else + { + mCalculateBtn->setEnabled(false); + } return TRUE; } @@ -566,6 +462,23 @@ void LLFloaterModelPreview::loadModel_continued(AIFilePicker* filepicker, S32 lo if (filepicker->hasFilename()) // User did not click Cancel? { filename = filepicker->getFilename(); + + const U32 lod_high = LLModel::LOD_HIGH; + for (S32 lod = 0; lod <= lod_high; ++lod) + { + std::string message = "status_reading_file"; + + mModelPreview->mFMP->childSetText(lod_triangles_name[lod], LLStringExplicit("?")); + mModelPreview->mFMP->childSetText(lod_vertices_name[lod], LLStringExplicit("?")); + LLIconCtrl* icon = mModelPreview->mFMP->getChild(lod_icon_name[lod]); + icon->setVisible(false); + } + } + + if (lod == LLModel::LOD_PHYSICS) + { + // loading physics from file + mModelPreview->mPhysicsSearchLOD = lod; } mModelPreview->loadModel(filename, lod); // Pass an empty filename if the user clicked Cancel. } @@ -587,7 +500,9 @@ void LLFloaterModelPreview::onClickCalculateBtn() mUploadModelUrl.clear(); gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale, - childGetValue("upload_textures").asBoolean(), upload_skinweights, upload_joint_positions, mUploadModelUrl, false, + childGetValue("upload_textures").asBoolean(), + upload_skinweights, upload_joint_positions, + mUploadModelUrl, false, getWholeModelFeeObserverHandle()); toggleCalculateButton(false); @@ -686,6 +601,11 @@ void LLFloaterModelPreview::toggleGenerateNormals() { bool enabled = childGetValue("gen_normals").asBoolean(); childSetEnabled("crease_angle", enabled); + if(enabled) { + mModelPreview->generateNormals(); + } else { + mModelPreview->restoreNormals(); + } } //static @@ -701,12 +621,26 @@ void LLFloaterModelPreview::onAutoFillCommit(LLUICtrl* ctrl, void* userdata) { LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; - fp->mModelPreview->genLODs(); + fp->mModelPreview->queryLODs(); } void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit) { mModelPreview->onLODParamCommit(lod, enforce_tri_limit); + + //refresh LoDs that reference this one + for (S32 i = lod - 1; i >= 0; --i) + { + LLComboBox* lod_source_combo = getChild("lod_source_" + lod_name[i]); + if (lod_source_combo->getCurrentIndex() == LLModelPreview::USE_LOD_ABOVE) + { + onLoDSourceCommit(i); + } + else + { + break; + } + } } @@ -717,6 +651,10 @@ void LLFloaterModelPreview::draw() { LLFloater::draw(); + if (!mModelPreview) + { + return; + } mModelPreview->update(); if (!mModelPreview->mLoading) @@ -726,16 +664,21 @@ void LLFloaterModelPreview::draw() childSetTextArg("status", "[STATUS]", getString("status_material_mismatch")); } else - if (mModelPreview->getLoadState() > LLModelLoader::ERROR_PARSING) + if ( mModelPreview->getLoadState() > LLModelLoader::ERROR_MODEL ) { - childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_PARSING))); + childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_MODEL))); } else - if (mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING) + if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING ) { childSetTextArg("status", "[STATUS]", getString("status_parse_error")); toggleCalculateButton(false); } + else + if (mModelPreview->getLoadState() == LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION) + { + childSetTextArg("status", "[STATUS]", getString("status_bind_shape_orientation")); + } else { childSetTextArg("status", "[STATUS]", getString("status_idle")); @@ -747,12 +690,13 @@ void LLFloaterModelPreview::draw() childSetTextArg("description_label", "[TEXTURES]", llformat("%d", mModelPreview->mTextureSet.size())); */ - if (mModelPreview) + if (mModelPreview->lodsReady()) { gGL.color3f(1.f, 1.f, 1.f); gGL.getTexUnit(0)->bind(mModelPreview); + LLView* preview_panel = getChild("preview_panel"); LLRect rect = preview_panel->getRect(); @@ -762,16 +706,16 @@ void LLFloaterModelPreview::draw() mPreviewRect = preview_panel->getRect(); } - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { gGL.texCoord2f(0.f, 1.f); gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mTop - 1); gGL.texCoord2f(0.f, 0.f); gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mBottom); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2i(mPreviewRect.mRight - 1, mPreviewRect.mBottom); gGL.texCoord2f(1.f, 1.f); gGL.vertex2i(mPreviewRect.mRight - 1, mPreviewRect.mTop - 1); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2i(mPreviewRect.mRight - 1, mPreviewRect.mBottom); } gGL.end(); @@ -878,11 +822,19 @@ BOOL LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) } /*virtual*/ -void LLFloaterModelPreview::onOpen(/*const LLSD& key*/) +void LLFloaterModelPreview::onOpen() { + LLModelPreview::sIgnoreLoadedCallback = false; requestAgentUploadPermissions(); } +/*virtual*/ +void LLFloaterModelPreview::onClose(bool app_quitting) +{ + LLModelPreview::sIgnoreLoadedCallback = true; + LLFloater::onClose(app_quitting); +} + //static void LLFloaterModelPreview::onPhysicsParamCommit(LLUICtrl* ctrl, void* data) { @@ -1238,1984 +1190,158 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl } //----------------------------------------------------------------------------- -// LLModelLoader +// LLModelPreview //----------------------------------------------------------------------------- -LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, - std::deque& jointsFromNodes) -: mJointList( jointMap ) -, mJointsFromNode( jointsFromNodes ) -, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE), mNumOfFetchingTextures(0) -{ - mJointMap["mPelvis"] = "mPelvis"; - mJointMap["mTorso"] = "mTorso"; - mJointMap["mChest"] = "mChest"; - mJointMap["mNeck"] = "mNeck"; - mJointMap["mHead"] = "mHead"; - mJointMap["mSkull"] = "mSkull"; - mJointMap["mEyeRight"] = "mEyeRight"; - mJointMap["mEyeLeft"] = "mEyeLeft"; - mJointMap["mCollarLeft"] = "mCollarLeft"; - mJointMap["mShoulderLeft"] = "mShoulderLeft"; - mJointMap["mElbowLeft"] = "mElbowLeft"; - mJointMap["mWristLeft"] = "mWristLeft"; - mJointMap["mCollarRight"] = "mCollarRight"; - mJointMap["mShoulderRight"] = "mShoulderRight"; - mJointMap["mElbowRight"] = "mElbowRight"; - mJointMap["mWristRight"] = "mWristRight"; - mJointMap["mHipRight"] = "mHipRight"; - mJointMap["mKneeRight"] = "mKneeRight"; - mJointMap["mAnkleRight"] = "mAnkleRight"; - mJointMap["mFootRight"] = "mFootRight"; - mJointMap["mToeRight"] = "mToeRight"; - mJointMap["mHipLeft"] = "mHipLeft"; - mJointMap["mKneeLeft"] = "mKneeLeft"; - mJointMap["mAnkleLeft"] = "mAnkleLeft"; - mJointMap["mFootLeft"] = "mFootLeft"; - mJointMap["mToeLeft"] = "mToeLeft"; - - mJointMap["avatar_mPelvis"] = "mPelvis"; - mJointMap["avatar_mTorso"] = "mTorso"; - mJointMap["avatar_mChest"] = "mChest"; - mJointMap["avatar_mNeck"] = "mNeck"; - mJointMap["avatar_mHead"] = "mHead"; - mJointMap["avatar_mSkull"] = "mSkull"; - mJointMap["avatar_mEyeRight"] = "mEyeRight"; - mJointMap["avatar_mEyeLeft"] = "mEyeLeft"; - mJointMap["avatar_mCollarLeft"] = "mCollarLeft"; - mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft"; - mJointMap["avatar_mElbowLeft"] = "mElbowLeft"; - mJointMap["avatar_mWristLeft"] = "mWristLeft"; - mJointMap["avatar_mCollarRight"] = "mCollarRight"; - mJointMap["avatar_mShoulderRight"] = "mShoulderRight"; - mJointMap["avatar_mElbowRight"] = "mElbowRight"; - mJointMap["avatar_mWristRight"] = "mWristRight"; - mJointMap["avatar_mHipRight"] = "mHipRight"; - mJointMap["avatar_mKneeRight"] = "mKneeRight"; - mJointMap["avatar_mAnkleRight"] = "mAnkleRight"; - mJointMap["avatar_mFootRight"] = "mFootRight"; - mJointMap["avatar_mToeRight"] = "mToeRight"; - mJointMap["avatar_mHipLeft"] = "mHipLeft"; - mJointMap["avatar_mKneeLeft"] = "mKneeLeft"; - mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft"; - mJointMap["avatar_mFootLeft"] = "mFootLeft"; - mJointMap["avatar_mToeLeft"] = "mToeLeft"; - - mJointMap["hip"] = "mPelvis"; - mJointMap["abdomen"] = "mTorso"; - mJointMap["chest"] = "mChest"; - mJointMap["neck"] = "mNeck"; - mJointMap["head"] = "mHead"; - mJointMap["figureHair"] = "mSkull"; - mJointMap["lCollar"] = "mCollarLeft"; - mJointMap["lShldr"] = "mShoulderLeft"; - mJointMap["lForeArm"] = "mElbowLeft"; - mJointMap["lHand"] = "mWristLeft"; - mJointMap["rCollar"] = "mCollarRight"; - mJointMap["rShldr"] = "mShoulderRight"; - mJointMap["rForeArm"] = "mElbowRight"; - mJointMap["rHand"] = "mWristRight"; - mJointMap["rThigh"] = "mHipRight"; - mJointMap["rShin"] = "mKneeRight"; - mJointMap["rFoot"] = "mFootRight"; - mJointMap["lThigh"] = "mHipLeft"; - mJointMap["lShin"] = "mKneeLeft"; - mJointMap["lFoot"] = "mFootLeft"; - - if (mPreview) - { - //only try to load from slm if viewer is configured to do so and this is the - //initial model load (not an LoD or physics shape) - mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mPreview->mUploadData.empty(); - mPreview->setLoadState(STARTING); - } - else - { - mTrySLM = false; - } - - assert_main_thread(); - sActiveLoaderList.push_back(this); -} - -LLModelLoader::~LLModelLoader() -{ - assert_main_thread(); - sActiveLoaderList.remove(this); -} -void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform) +LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) +: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex() +, mLodsQuery() +, mLodsWithParsingError() +, mPelvisZOffset( 0.0f ) +, mLegacyRigValid( false ) +, mRigValidJointUpload( false ) +, mPhysicsSearchLOD( LLModel::LOD_PHYSICS ) +, mResetJoints( false ) +, mModelNoErrors( true ) +, mLastJointUpdate( false ) { - LLVector4a box[] = - { - LLVector4a(-1, 1,-1), - LLVector4a(-1, 1, 1), - LLVector4a(-1,-1,-1), - LLVector4a(-1,-1, 1), - LLVector4a( 1, 1,-1), - LLVector4a( 1, 1, 1), - LLVector4a( 1,-1,-1), - LLVector4a( 1,-1, 1), - }; + mNeedsUpdate = TRUE; + mCameraDistance = 0.f; + mCameraYaw = 0.f; + mCameraPitch = 0.f; + mCameraZoom = 1.f; + mTextureName = 0; + mPreviewLOD = 0; + mModelLoader = NULL; + mMaxTriangleLimit = 0; + mDirty = false; + mGenLOD = false; + mLoading = false; + mLoadState = LLModelLoader::STARTING; + mGroup = 0; + mLODFrozen = false; + mBuildShareTolerance = 0.f; + mBuildQueueMode = GLOD_QUEUE_GREEDY; + mBuildBorderMode = GLOD_BORDER_UNLOCK; + mBuildOperator = GLOD_OPERATOR_EDGE_COLLAPSE; - for (S32 j = 0; j < model->getNumVolumeFaces(); ++j) + for (U32 i = 0; i < LLModel::NUM_LODS; ++i) { - const LLVolumeFace& face = model->getVolumeFace(j); - - LLVector4a center; - center.setAdd(face.mExtents[0], face.mExtents[1]); - center.mul(0.5f); - LLVector4a size; - size.setSub(face.mExtents[1],face.mExtents[0]); - size.mul(0.5f); - - for (U32 i = 0; i < 8; i++) - { - LLVector4a t; - t.setMul(size, box[i]); - t.add(center); - - LLVector4a v; - - mat.affineTransform(t, v); - - if (first_transform) - { - first_transform = FALSE; - min = max = v; - } - else - { - update_min_max(min, max, v); - } - } + mRequestedTriangleCount[i] = 0; + mRequestedCreaseAngle[i] = -1.f; + mRequestedLoDMode[i] = 0; + mRequestedErrorThreshold[i] = 0.f; + mRequestedBuildOperator[i] = 0; + mRequestedQueueMode[i] = 0; + mRequestedBorderMode[i] = 0; + mRequestedShareTolerance[i] = 0.f; } -} -void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform) -{ - LLVector4a mina, maxa; - LLMatrix4a mata; + mViewOption["show_textures"] = false; - mata.loadu(mat); - mina.load3(min.mV); - maxa.load3(max.mV); + mFMP = fmp; - stretch_extents(model, mata, mina, maxa, first_transform); + mHasPivot = false; + mModelPivot = LLVector3(0.0f, 0.0f, 0.0f); - min.set(mina.getF32ptr()); - max.set(maxa.getF32ptr()); -} + glodInit(); -void LLModelLoader::run() -{ - doLoadModel(); - doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this)); + createPreviewAvatar(); } -bool LLModelLoader::doLoadModel() +LLModelPreview::~LLModelPreview() { - //first, look for a .slm file of the same name that was modified later - //than the .dae - - if (mTrySLM) - { - std::string filename = mFilename; - - std::string::size_type i = filename.rfind("."); - if (i != std::string::npos) - { - filename.replace(i, filename.size() - 1, ".slm"); - llstat slm_status; - if (LLFile::stat(filename, &slm_status) == 0) - { //slm file exists - llstat dae_status; - if (LLFile::stat(mFilename, &dae_status) != 0 || - dae_status.st_mtime < slm_status.st_mtime) - { - if (loadFromSLM(filename)) - { //slm successfully loaded, if this fails, fall through and - //try loading from dae - - mLod = -1; //successfully loading from an slm implicitly sets all - //LoDs - return true; - } - } - } - } - } - - //no suitable slm exists, load from the .dae file - //replace illegal # in path as collada's escapser is broken - std::string tmp_file = mFilename; - boost::replace_all(tmp_file, "#", "%23"); - DAE dae; - domCOLLADA* dom = dae.open(tmp_file); - - if (!dom) + // glod apparently has internal mem alignment issues that are angering + // the heap-check code in windows, these should be hunted down in that + // TP code, if possible + // + // kernel32.dll!HeapFree() + 0x14 bytes + // msvcr100.dll!free(void * pBlock) Line 51 C + // glod.dll!glodGetGroupParameteriv() + 0x119 bytes + // glod.dll!glodShutdown() + 0x77 bytes + // + //glodShutdown(); + if(mModelLoader) { - LL_INFOS() <<" Error with dae - traditionally indicates a corrupt file."<getVersion(); - //0=1.4 - //1=1.4.1 - //2=Currently unsupported, however may work - if (docVersion > 1) - { - docVersion = VERSIONTYPE_COUNT; + mModelLoader->shutdown(); } - LL_INFOS() <<"Dae version "<getElementCount(NULL, COLLADA_TYPE_MESH); +} - daeDocument* doc = dae.getDoc(tmp_file); - if (!doc) - { - LL_WARNS() << "can't find internal doc" << LL_ENDL; - return false; - } +U32 LLModelPreview::calcResourceCost() +{ + assert_main_thread(); - daeElement* root = doc->getDomRoot(); - if (!root) - { - LL_WARNS() << "document has no root" << LL_ENDL; - return false; - } + rebuildUploadData(); - //Verify some basic properties of the dae - //1. Basic validity check on controller - U32 controllerCount = (int) db->getElementCount(NULL, "controller"); - bool result = false; - for (U32 i = 0; i < controllerCount; ++i) + //Upload skin is selected BUT check to see if the joints coming in from the asset were malformed. + if (mFMP && mFMP->childGetValue("upload_skin").asBoolean()) { - domController* pController = NULL; - db->getElement((daeElement**) &pController, i , NULL, "controller"); - result = mPreview->verifyController(pController); - if (!result) + bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean(); + if (uploadingJointPositions && !isRigValidForJointPositionUpload()) { - setLoadState(ERROR_PARSING); - return true; + mFMP->childDisable("ok_btn"); } } - //get unit scale - mTransform.setIdentity(); - - domAsset::domUnit* unit = daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID()))); - - if (unit) - { - F32 meter = unit->getMeter(); - mTransform.mMatrix[0][0] = meter; - mTransform.mMatrix[1][1] = meter; - mTransform.mMatrix[2][2] = meter; - } - - //get up axis rotation - LLMatrix4 rotation; + std::set accounted; + U32 num_points = 0; + U32 num_hulls = 0; - domUpAxisType up = UPAXISTYPE_Y_UP; // default is Y_UP - domAsset::domUp_axis* up_axis = - daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID()))); + F32 debug_scale = mFMP ? mFMP->childGetValue("import_scale").asReal() : 1.f; + mPelvisZOffset = mFMP ? mFMP->childGetValue("pelvis_offset").asReal() : 3.0f; - if (up_axis) + if (mFMP && mFMP->childGetValue("upload_joints").asBoolean()) { - up = up_axis->getValue(); + // FIXME if preview avatar ever gets reused, this fake mesh ID stuff will fail. + // see also call to addAttachmentPosOverride. + LLUUID fake_mesh_id; + fake_mesh_id.generate(); + getPreviewAvatar()->addPelvisFixup( mPelvisZOffset, fake_mesh_id ); } - if (up == UPAXISTYPE_X_UP) - { - rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f); - } - else if (up == UPAXISTYPE_Y_UP) + F32 streaming_cost = 0.f; + F32 physics_cost = 0.f; + for (U32 i = 0; i < mUploadData.size(); ++i) { - rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f); - } - - rotation *= mTransform; - mTransform = rotation; - - for (daeInt idx = 0; idx < count; ++idx) - { //build map of domEntities to LLModel - domMesh* mesh = NULL; - db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH); + LLModelInstance& instance = mUploadData[i]; - if (mesh) + if (accounted.find(instance.mModel) == accounted.end()) { - LLPointer model = LLModel::loadModelFromDomMesh(mesh); + accounted.insert(instance.mModel); + + LLModel::Decomposition& decomp = + instance.mLOD[LLModel::LOD_PHYSICS] ? + instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics : + instance.mModel->mPhysics; - if (model->getStatus() != LLModel::NO_ERRORS) + //update instance skin info for each lods pelvisZoffset + for (int j = 0; j < LLModel::NUM_LODS; ++j) { - setLoadState(ERROR_PARSING + model->getStatus()); - return false; //abort + if (instance.mLOD[j]) + { + instance.mLOD[j]->mSkinInfo.mPelvisOffset = mPelvisZOffset; + } } - if (model.notNull() && validate_model(model)) + std::stringstream ostr; + LLSD ret = LLModel::writeModel(ostr, + instance.mLOD[4], + instance.mLOD[3], + instance.mLOD[2], + instance.mLOD[1], + instance.mLOD[0], + decomp, + mFMP->childGetValue("upload_skin").asBoolean(), + mFMP->childGetValue("upload_joints").asBoolean(), + false, + TRUE, + FALSE, + instance.mModel->mSubmodelID); + + num_hulls += decomp.mHull.size(); + for (U32 i = 0; i < decomp.mHull.size(); ++i) { - mModelList.push_back(model); - mModel[mesh] = model; - } - } - } - - count = db->getElementCount(NULL, COLLADA_TYPE_SKIN); - for (daeInt idx = 0; idx < count; ++idx) - { //add skinned meshes as instances - domSkin* skin = NULL; - db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN); - - if (skin) - { - domGeometry* geom = daeSafeCast(skin->getSource().getElement()); - - if (geom) - { - domMesh* mesh = geom->getMesh(); - if (mesh) - { - LLModel* model = mModel[mesh]; - if (model) - { - LLVector3 mesh_scale_vector; - LLVector3 mesh_translation_vector; - model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); - - LLMatrix4 normalized_transformation; - normalized_transformation.setTranslation(mesh_translation_vector); - - LLMatrix4 mesh_scale; - mesh_scale.initScale(mesh_scale_vector); - mesh_scale *= normalized_transformation; - normalized_transformation = mesh_scale; - - LLMatrix4a inv_mat; - inv_mat.loadu(normalized_transformation); - inv_mat.invert(); - - LLMatrix4 inverse_normalized_transformation(inv_mat.getF32ptr()); - - domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix(); - - if (bind_mat) - { //get bind shape matrix - domFloat4x4& dom_value = bind_mat->getValue(); - - LLMeshSkinInfo& skin_info = model->mSkinInfo; - - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4]; - } - } - - LLMatrix4 trans = normalized_transformation; - trans *= skin_info.mBindShapeMatrix; - skin_info.mBindShapeMatrix = trans; - } - - //Some collada setup for accessing the skeleton - daeElement* pElement = 0; - dae.getDatabase()->getElement(&pElement, 0, 0, "skeleton"); - - //Try to get at the skeletal instance controller - domInstance_controller::domSkeleton* pSkeleton = daeSafeCast(pElement); - bool missingSkeletonOrScene = false; - - //If no skeleton, do a breadth-first search to get at specific joints - bool rootNode = false; - - //Need to test for a skeleton that does not have a root node - //This occurs when your instance controller does not have an associated scene - if (pSkeleton) - { - daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); - if (pSkeletonRootNode) - { - rootNode = true; - } - - } - if (!pSkeleton || !rootNode) - { - daeElement* pScene = root->getDescendant("visual_scene"); - if (!pScene) - { - LL_WARNS()<<"No visual scene - unable to parse bone offsets "< > children = pScene->getChildren(); - S32 childCount = children.getCount(); - - //Process any children that are joints - //Not all children are joints, some code be ambient lights, cameras, geometry etc.. - for (S32 i = 0; i < childCount; ++i) - { - domNode* pNode = daeSafeCast(children[i]); - if (isNodeAJoint(pNode)) - { - processJointNode(pNode, mJointList); - } - } - } - } - else - //Has Skeleton - { - //Get the root node of the skeleton - daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); - if (pSkeletonRootNode) - { - //Once we have the root node - start acccessing it's joint components - const int jointCnt = mJointMap.size(); - std::map :: const_iterator jointIt = mJointMap.begin(); - - //Loop over all the possible joints within the .dae - using the allowed joint list in the ctor. - for (int i = 0; i < jointCnt; ++i, ++jointIt) - { - //Build a joint for the resolver to work with - char str[64]={0}; - sprintf(str,"./%s",(*jointIt).first.c_str()); - //llwarns<<"Joint "<< str <(resolver.getElement()); - if (pJoint) - { - //Pull out the translate id and store it in the jointTranslations map - daeSIDResolver jointResolverA(pJoint, "./translate"); - domTranslate* pTranslateA = daeSafeCast(jointResolverA.getElement()); - daeSIDResolver jointResolverB(pJoint, "./location"); - domTranslate* pTranslateB = daeSafeCast(jointResolverB.getElement()); - - LLMatrix4 workingTransform; - - //Translation via SID - if (pTranslateA) - { - extractTranslation(pTranslateA, workingTransform); - } - else - if (pTranslateB) - { - extractTranslation(pTranslateB, workingTransform); - } - else - { - //Translation via child from element - daeElement* pTranslateElement = getChildFromElement(pJoint, "translate"); - if (pTranslateElement && pTranslateElement->typeID() != domTranslate::ID()) - { - LL_WARNS() << "The found element is not a translate node" << LL_ENDL; - missingSkeletonOrScene = true; - } - else - if (pTranslateElement) - { - extractTranslationViaElement(pTranslateElement, workingTransform); - } - else - { - extractTranslationViaSID(pJoint, workingTransform); - } - - } - - //Store the joint transform w/respect to it's name. - mJointList[(*jointIt).second.c_str()] = workingTransform; - } - } - - //If anything failed in regards to extracting the skeleton, joints or translation id, - //mention it - if (missingSkeletonOrScene) - { - LL_WARNS() << "Partial jointmap found in asset - did you mean to just have a partial map?" << LL_ENDL; - } - } //got skeleton? - } - - domSkin::domJoints* joints = skin->getJoints(); - - domInputLocal_Array& joint_input = joints->getInput_array(); - - for (size_t i = 0; i < joint_input.getCount(); ++i) - { - domInputLocal* input = joint_input.get(i); - xsNMTOKEN semantic = input->getSemantic(); - - if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0) - { //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames - daeElement* elem = input->getSource().getElement(); - - domSource* source = daeSafeCast(elem); - if (source) - { - domName_array* names_source = source->getName_array(); - - if (names_source) - { - domListOfNames &names = names_source->getValue(); - - for (size_t j = 0; j < names.getCount(); ++j) - { - std::string name(names.get(j)); - if (mJointMap.find(name) != mJointMap.end()) - { - name = mJointMap[name]; - } - model->mSkinInfo.mJointNames.push_back(name); - model->mSkinInfo.mJointMap[name] = j; - } - } - else - { - domIDREF_array* names_source = source->getIDREF_array(); - if (names_source) - { - xsIDREFS& names = names_source->getValue(); - - for (size_t j = 0; j < names.getCount(); ++j) - { - std::string name(names.get(j).getID()); - if (mJointMap.find(name) != mJointMap.end()) - { - name = mJointMap[name]; - } - model->mSkinInfo.mJointNames.push_back(name); - model->mSkinInfo.mJointMap[name] = j; - } - } - } - } - } - else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0) - { //found inv_bind_matrix array, fill model->mInvBindMatrix - domSource* source = daeSafeCast(input->getSource().getElement()); - if (source) - { - domFloat_array* t = source->getFloat_array(); - if (t) - { - domListOfFloats& transform = t->getValue(); - S32 count = transform.getCount()/16; - - for (S32 k = 0; k < count; ++k) - { - LLMatrix4 mat; - - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - mat.mMatrix[i][j] = transform[k*16 + i + j*4]; - } - } - - model->mSkinInfo.mInvBindMatrix.push_back(mat); - } - } - } - } - } - - //Now that we've parsed the joint array, let's determine if we have a full rig - //(which means we have all the joint sthat are required for an avatar versus - //a skinned asset attached to a node in a file that contains an entire skeleton, - //but does not use the skeleton). - buildJointToNodeMappingFromScene(root); - mPreview->critiqueRigForUploadApplicability(model->mSkinInfo.mJointNames); - - if (!missingSkeletonOrScene) - { - //Set the joint translations on the avatar - if it's a full mapping - //The joints are reset in the dtor - if (mPreview->getRigWithSceneParity()) - { - std::map :: const_iterator masterJointIt = mJointMap.begin(); - std::map :: const_iterator masterJointItEnd = mJointMap.end(); - for ( ;masterJointIt!=masterJointItEnd;++masterJointIt) - { - std::string lookingForJoint = (*masterJointIt).first.c_str(); - - if (mJointList.find(lookingForJoint) != mJointList.end()) - { - //LL_INFOS() <<"joint "<getPreviewAvatar()->getJoint(lookingForJoint); - if (pJoint) - { - pJoint->storeCurrentXform(jointTransform.getTranslation()); - } - else - { - //Most likely an error in the asset. - LL_WARNS() << "Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL; - } - } - } - } - } //missingSkeletonOrScene - - //We need to construct the alternate bind matrix (which contains the new joint positions) - //in the same order as they were stored in the joint buffer. The joints associated - //with the skeleton are not stored in the same order as they are in the exported joint buffer. - //This remaps the skeletal joints to be in the same order as the joints stored in the model. - std::vector :: const_iterator jointIt = model->mSkinInfo.mJointNames.begin(); - const int jointCnt = model->mSkinInfo.mJointNames.size(); - for (int i = 0; i < jointCnt; ++i, ++jointIt) - { - std::string lookingForJoint = (*jointIt).c_str(); - //Look for the joint xform that we extracted from the skeleton, using the jointIt as the key - //and store it in the alternate bind matrix - if (mJointList.find(lookingForJoint) != mJointList.end()) - { - LLMatrix4 jointTransform = mJointList[lookingForJoint]; - LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i]; - newInverse.setTranslation(mJointList[lookingForJoint].getTranslation()); - model->mSkinInfo.mAlternateBindMatrix.push_back(newInverse); - } - else - { - LL_WARNS() << "Possibly misnamed/missing joint [" << lookingForJoint.c_str() << " ] " << LL_ENDL; - } - } - - //grab raw position array - - domVertices* verts = mesh->getVertices(); - if (verts) - { - domInputLocal_Array& inputs = verts->getInput_array(); - for (size_t i = 0; i < inputs.getCount() && model->mPosition.empty(); ++i) - { - if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0) - { - domSource* pos_source = daeSafeCast(inputs[i]->getSource().getElement()); - if (pos_source) - { - domFloat_array* pos_array = pos_source->getFloat_array(); - if (pos_array) - { - domListOfFloats& pos = pos_array->getValue(); - - for (size_t j = 0; j < pos.getCount(); j += 3) - { - if (pos.getCount() <= j+2) - { - LL_ERRS() << "Invalid position array size." << LL_ENDL; - } - - LLVector3 v(pos[j], pos[j + 1], pos[j+2]); - - //transform from COLLADA space to volume space - v = v * inverse_normalized_transformation; - - model->mPosition.push_back(v); - } - } - } - } - } - } - - //grab skin weights array - domSkin::domVertex_weights* weights = skin->getVertex_weights(); - if (weights) - { - domInputLocalOffset_Array& inputs = weights->getInput_array(); - domFloat_array* vertex_weights = NULL; - for (size_t i = 0; i < inputs.getCount(); ++i) - { - if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0) - { - domSource* weight_source = daeSafeCast(inputs[i]->getSource().getElement()); - if (weight_source) - { - vertex_weights = weight_source->getFloat_array(); - } - } - } - - if (vertex_weights) - { - domListOfFloats& w = vertex_weights->getValue(); - domListOfUInts& vcount = weights->getVcount()->getValue(); - domListOfInts& v = weights->getV()->getValue(); - - U32 c_idx = 0; - for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx) - { //for each vertex - daeUInt count = vcount[vc_idx]; - - //create list of weights that influence this vertex - LLModel::weight_list weight_list; - - for (daeUInt i = 0; i < count; ++i) - { //for each weight - daeInt joint_idx = v[c_idx++]; - daeInt weight_idx = v[c_idx++]; - - if (joint_idx == -1) - { - //ignore bindings to bind_shape_matrix - continue; - } - - F32 weight_value = w[weight_idx]; - - weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value)); - } - - //sort by joint weight - std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater()); - - std::vector wght; - - F32 total = 0.f; - - for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i) - { //take up to 4 most significant weights - if (weight_list[i].mWeight > 0.f) - { - wght.push_back(weight_list[i]); - total += weight_list[i].mWeight; - } - } - - F32 scale = 1.f/total; - if (scale != 1.f) - { //normalize weights - for (U32 i = 0; i < wght.size(); ++i) - { - wght[i].mWeight *= scale; - } - } - - model->mSkinWeights[model->mPosition[vc_idx]] = wght; - } - - //add instance to scene for this model - - LLMatrix4 transformation = mTransform; - // adjust the transformation to compensate for mesh normalization - - LLMatrix4 mesh_translation; - mesh_translation.setTranslation(mesh_translation_vector); - mesh_translation *= transformation; - transformation = mesh_translation; - - LLMatrix4 mesh_scale; - mesh_scale.initScale(mesh_scale_vector); - mesh_scale *= transformation; - transformation = mesh_scale; - - std::map materials; - for (U32 i = 0; i < model->mMaterialList.size(); ++i) - { - materials[model->mMaterialList[i]] = LLImportMaterial(); - } - mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials)); - stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); - } - } - } - } - } - } - } - - daeElement* scene = root->getDescendant("visual_scene"); - - if (!scene) - { - LL_WARNS() << "document has no visual_scene" << LL_ENDL; - setLoadState(ERROR_PARSING); - return true; - } - - setLoadState(DONE); - - bool badElement = false; - - processElement(scene, badElement); - - if (badElement) - { - setLoadState(ERROR_PARSING); - } - - return true; -} - -void LLModelLoader::setLoadState(U32 state) -{ - if (mPreview) - { - mPreview->setLoadState(state); - } -} - -bool LLModelLoader::loadFromSLM(const std::string& filename) -{ - //only need to populate mScene with data from slm - llstat stat; - - if (LLFile::stat(filename, &stat)) - { //file does not exist - return false; - } - - S32 file_size = (S32) stat.st_size; - - llifstream ifstream(filename, std::ifstream::in | std::ifstream::binary); - LLSD data; - LLSDSerialize::fromBinary(data, ifstream, file_size); - ifstream.close(); - - //build model list for each LoD - model_list model[LLModel::NUM_LODS]; - - if (data["version"].asInteger() != SLM_SUPPORTED_VERSION) - { //unsupported version - return false; - } - - LLSD& mesh = data["mesh"]; - - LLVolumeParams volume_params; - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - - for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) - { - for (int i = 0; i < mesh.size(); ++i) - { - std::stringstream str(mesh[i].asString()); - LLPointer loaded_model = new LLModel(volume_params, (F32) lod); - if (loaded_model->loadModel(str)) - { - loaded_model->mLocalID = i; - model[lod].push_back(loaded_model); - - if (lod == LLModel::LOD_HIGH && !loaded_model->mSkinInfo.mJointNames.empty()) - { - //check to see if rig is valid - mPreview->critiqueRigForUploadApplicability(loaded_model->mSkinInfo.mJointNames); - } - } - } - } - - if (model[LLModel::LOD_HIGH].empty()) - { //failed to load high lod - return false; - } - - // Set name. - std::string name = data["name"]; - if (!name.empty()) - { - model[LLModel::LOD_HIGH][0]->mLabel = name; - } - - //load instance list - model_instance_list instance_list; - - LLSD& instance = data["instance"]; - - for (int i = 0; i < instance.size(); ++i) - { - //deserialize instance list - instance_list.push_back(LLModelInstance(instance[i])); - - //match up model instance pointers - S32 idx = instance_list[i].mLocalMeshID; - - for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod) - { - if (!model[lod].empty()) - { - instance_list[i].mLOD[lod] = model[lod][idx]; - } - } - - instance_list[i].mModel = model[LLModel::LOD_HIGH][idx]; - } - - //convert instance_list to mScene - mFirstTransform = TRUE; - for (U32 i = 0; i < instance_list.size(); ++i) - { - LLModelInstance& cur_instance = instance_list[i]; - mScene[cur_instance.mTransform].push_back(cur_instance); - stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform); - } - - setLoadState(DONE); - - return true; -} - -//static -bool LLModelLoader::isAlive(LLModelLoader* loader) -{ - if (!loader) - { - return false; - } - - std::list::iterator iter = sActiveLoaderList.begin(); - for ( ; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter); - - return *iter == loader; -} - -void LLModelLoader::loadModelCallback() -{ - assert_main_thread(); - - if (mPreview) - { - mPreview->loadModelCallback(mLod); - } - - while (!isStopped()) - { //wait until this thread is stopped before deleting self - apr_sleep(100); - } - - //double check if "this" is valid before deleting it, in case it is aborted during running. - if (!isAlive(this)) - { - return; - } - - //cleanup model loader - if (mPreview) - { - mPreview->mModelLoader = NULL; - } - - delete this; -} - -//----------------------------------------------------------------------------- -// buildJointToNodeMappingFromScene() -//----------------------------------------------------------------------------- -void LLModelLoader::buildJointToNodeMappingFromScene(daeElement* pRoot) -{ - daeElement* pScene = pRoot->getDescendant("visual_scene"); - if (pScene) - { - daeTArray< daeSmartRef > children = pScene->getChildren(); - S32 childCount = children.getCount(); - for (S32 i = 0; i < childCount; ++i) - { - domNode* pNode = daeSafeCast(children[i]); - processJointToNodeMapping(pNode); - } - } -} - -//----------------------------------------------------------------------------- -// processJointToNodeMapping() -//----------------------------------------------------------------------------- -void LLModelLoader::processJointToNodeMapping(domNode* pNode) -{ - if (isNodeAJoint(pNode)) - { - //1.Store the parent - std::string nodeName = pNode->getName(); - if (!nodeName.empty()) - { - mJointsFromNode.push_front(pNode->getName()); - } - //2. Handle the kiddo's - processChildJoints(pNode); - } - else - { - //Determine if the're any children wrt to this failed node. - //This occurs when an armature is exported and ends up being what essentially amounts to - //as the root for the visual_scene - if (pNode) - { - processChildJoints(pNode); - } - else - { - LL_INFOS() <<"Node is NULL"< > childOfChild = pParentNode->getChildren(); - S32 childOfChildCount = childOfChild.getCount(); - for (S32 i = 0; i < childOfChildCount; ++i) - { - domNode* pChildNode = daeSafeCast(childOfChild[i]); - if (pChildNode) - { - processJointToNodeMapping(pChildNode); - } - } -} - -//----------------------------------------------------------------------------- -// critiqueRigForUploadApplicability() -//----------------------------------------------------------------------------- -void LLModelPreview::critiqueRigForUploadApplicability(const std::vector &jointListFromAsset) -{ - critiqueJointToNodeMappingFromScene(); - - //Determines the following use cases for a rig: - //1. It is suitable for upload with skin weights & joint positions, or - //2. It is suitable for upload as standard av with just skin weights - - bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload(jointListFromAsset); - bool isRigLegacyOK = isRigLegacy(jointListFromAsset); - - //It's OK that both could end up being true, both default to false - if (isJointPositionUploadOK) - { - setRigValidForJointPositionUpload(true); - } - - if (isRigLegacyOK) - { - setLegacyRigValid(true); - } - -} - -//----------------------------------------------------------------------------- -// critiqueJointToNodeMappingFromScene() -//----------------------------------------------------------------------------- -void LLModelPreview::critiqueJointToNodeMappingFromScene(void) -{ - //Do the actual nodes back the joint listing from the dae? - //if yes then this is a fully rigged asset, otherwise it's just a partial rig - - std::deque::iterator jointsFromNodeIt = mJointsFromNode.begin(); - std::deque::iterator jointsFromNodeEndIt = mJointsFromNode.end(); - bool result = true; - - if (!mJointsFromNode.empty()) - { - for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt) - { - std::string name = *jointsFromNodeIt; - if (mJointTransformMap.find(name) != mJointTransformMap.end()) - { - continue; - } - else - { - LL_INFOS() <<"critiqueJointToNodeMappingFromScene is missing a: "< &jointListFromAsset) -{ - //No joints in asset - if (jointListFromAsset.size() == 0) - { - return false; - } - - bool result = false; - - std::deque :: const_iterator masterJointIt = mMasterLegacyJointList.begin(); - std::deque :: const_iterator masterJointEndIt = mMasterLegacyJointList.end(); - - std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); - std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); - - for ( ;masterJointIt!=masterJointEndIt;++masterJointIt) - { - result = false; - modelJointIt = jointListFromAsset.begin(); - - for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt) - { - if (*masterJointIt == *modelJointIt) - { - result = true; - break; - } - } - if (!result) - { - LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; - break; - } - } - return result; -} - -//----------------------------------------------------------------------------- -// isRigSuitableForJointPositionUpload() -//----------------------------------------------------------------------------- -bool LLModelPreview::isRigSuitableForJointPositionUpload(const std::vector &jointListFromAsset) -{ - bool result = false; - - std::deque :: const_iterator masterJointIt = mMasterJointList.begin(); - std::deque :: const_iterator masterJointEndIt = mMasterJointList.end(); - - std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); - std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); - - for ( ;masterJointIt!=masterJointEndIt;++masterJointIt) - { - result = false; - modelJointIt = jointListFromAsset.begin(); - - for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt) - { - if (*masterJointIt == *modelJointIt) - { - result = true; - break; - } - } - if (!result) - { - LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; - break; - } - } - return result; -} - -//called in the main thread -void LLModelLoader::loadTextures() -{ - BOOL is_paused = isPaused(); - pause(); //pause the loader - - for (scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter) - { - for (U32 i = 0; i < iter->second.size(); i++) - { - for (std::map::iterator j = iter->second[i].mMaterial.begin(); - j != iter->second[i].mMaterial.end(); ++j) - { - LLImportMaterial& material = j->second; - - if (!material.mDiffuseMapFilename.empty()) - { - material.mDiffuseMap = - LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, TRUE, LLGLTexture::BOOST_PREVIEW); - material.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE); - material.mDiffuseMap->forceToSaveRawImage(0, F32_MAX); - mNumOfFetchingTextures++; - } - } - } - } - - if (!is_paused) - { - unpause(); - } -} - -//----------------------------------------------------------------------------- -// isNodeAJoint() -//----------------------------------------------------------------------------- -bool LLModelLoader::isNodeAJoint(domNode* pNode) -{ - if (!pNode) - { - LL_INFOS() <<"Created node is NULL"<getName() == NULL) - { - LL_INFOS() <<"Parsed node has no name "<getId()) - { - LL_INFOS() <<"Parsed node ID: "<getId()<getName()) != mJointMap.end()) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// verifyCount -//----------------------------------------------------------------------------- -bool LLModelPreview::verifyCount(int expected, int result) -{ - if (expected != result) - { - LL_INFOS() << "Error: (expected/got)"<getSkin(); - - if (pSkin) - { - xsAnyURI & uri = pSkin->getSource(); - domElement* pElement = uri.getElement(); - - if (!pElement) - { - LL_INFOS() <<"Can't resolve skin source"<getTypeName(); - if (stricmp(type_str, "geometry") == 0) - { - //Skin is reference directly by geometry and get the vertex count from skin - domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights(); - U32 vertexWeightsCount = pVertexWeights->getCount(); - domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement(); - domMesh* pMesh = pGeometry->getMesh(); - - if (pMesh) - { - //Get vertex count from geometry - domVertices* pVertices = pMesh->getVertices(); - if (!pVertices) - { - LL_INFOS() <<"No vertices!"<getInput_array()[0]->getSource(); - domSource* pSource = (domSource*) (domElement*) src.getElement(); - U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount(); - result = verifyCount(verticesCount, vertexWeightsCount); - if (!result) - { - return result; - } - } - } - - U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount(); - result = verifyCount(vcountCount, vertexWeightsCount); - if (!result) - { - return result; - } - - domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array(); - U32 sum = 0; - for (size_t i = 0; i < vcountCount; i++) - { - sum += pVertexWeights->getVcount()->getValue()[i]; - } - result = verifyCount(sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount()); - } - } - - return result; -} - -//----------------------------------------------------------------------------- -// extractTranslation() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslation(domTranslate* pTranslate, LLMatrix4& transform) -{ - domFloat3 jointTrans = pTranslate->getValue(); - LLVector3 singleJointTranslation(jointTrans[0], jointTrans[1], jointTrans[2]); - transform.setTranslation(singleJointTranslation); -} - -//----------------------------------------------------------------------------- -// extractTranslationViaElement() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslationViaElement(daeElement* pTranslateElement, LLMatrix4& transform) -{ - if (pTranslateElement) - { - domTranslate* pTranslateChild = dynamic_cast(pTranslateElement); - domFloat3 translateChild = pTranslateChild->getValue(); - LLVector3 singleJointTranslation(translateChild[0], translateChild[1], translateChild[2]); - transform.setTranslation(singleJointTranslation); - } -} - -//----------------------------------------------------------------------------- -// extractTranslationViaSID() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslationViaSID(daeElement* pElement, LLMatrix4& transform) -{ - if (pElement) - { - daeSIDResolver resolver(pElement, "./transform"); - domMatrix* pMatrix = daeSafeCast(resolver.getElement()); - //We are only extracting out the translational component atm - LLMatrix4 workingTransform; - if (pMatrix) - { - domFloat4x4 domArray = pMatrix->getValue(); - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - workingTransform.mMatrix[i][j] = domArray[i + j*4]; - } - } - LLVector3 trans = workingTransform.getTranslation(); - transform.setTranslation(trans); - } - } - else - { - LL_WARNS() << "Element is nonexistent - empty/unsupported node." << LL_ENDL; - } -} - -//----------------------------------------------------------------------------- -// processJointNode() -//----------------------------------------------------------------------------- -void LLModelLoader::processJointNode(domNode* pNode, JointTransformMap& jointTransforms) -{ - if (pNode->getName() == NULL) - { - LL_WARNS() << "nameless node, can't process" << LL_ENDL; - return; - } - - //llwarns<<"ProcessJointNode# Node:" <getName()<(jointResolverA.getElement()); - daeSIDResolver jointResolverB(pNode, "./location"); - domTranslate* pTranslateB = daeSafeCast(jointResolverB.getElement()); - - //Translation via SID was successful - if (pTranslateA) - { - extractTranslation(pTranslateA, workingTransform); - } - else - if (pTranslateB) - { - extractTranslation(pTranslateB, workingTransform); - } - else - { - //Translation via child from element - daeElement* pTranslateElement = getChildFromElement(pNode, "translate"); - if (!pTranslateElement || pTranslateElement->typeID() != domTranslate::ID()) - { - //llwarns<< "The found element is not a translate node" <(jointResolver.getElement()); - if (pMatrix) - { - //LL_INFOS() <<"A matrix SID was however found!"<getValue(); - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - workingTransform.mMatrix[i][j] = domArray[i + j*4]; - } - } - } - else - { - LL_WARNS() << "The found element is not translate or matrix node - most likely a corrupt export!" << LL_ENDL; - } - } - else - { - extractTranslationViaElement(pTranslateElement, workingTransform); - } - } - - //Store the working transform relative to the nodes name. - jointTransforms[ pNode->getName() ] = workingTransform; - - //2. handle the nodes children - - //Gather and handle the incoming nodes children - daeTArray< daeSmartRef > childOfChild = pNode->getChildren(); - S32 childOfChildCount = childOfChild.getCount(); - - for (S32 i = 0; i < childOfChildCount; ++i) - { - domNode* pChildNode = daeSafeCast(childOfChild[i]); - if (pChildNode) - { - processJointNode(pChildNode, jointTransforms); - } - } -} - -//----------------------------------------------------------------------------- -// getChildFromElement() -//----------------------------------------------------------------------------- -daeElement* LLModelLoader::getChildFromElement(daeElement* pElement, std::string const & name) -{ - daeElement* pChildOfElement = pElement->getChild(name.c_str()); - if (pChildOfElement) - { - return pChildOfElement; - } - LL_WARNS() << "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL; - return NULL; -} - -void LLModelLoader::processElement(daeElement* element, bool& badElement) -{ - LLMatrix4 saved_transform = mTransform; - - domTranslate* translate = daeSafeCast(element); - if (translate) - { - domFloat3 dom_value = translate->getValue(); - - LLMatrix4 translation; - translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2])); - - translation *= mTransform; - mTransform = translation; - } - - domRotate* rotate = daeSafeCast(element); - if (rotate) - { - domFloat4 dom_value = rotate->getValue(); - - LLMatrix4 rotation; - rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0)); - - rotation *= mTransform; - mTransform = rotation; - } - - domScale* scale = daeSafeCast(element); - if (scale) - { - domFloat3 dom_value = scale->getValue(); - - LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]); - scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes - LLMatrix4 scaling; - scaling.initScale(scale_vector); - - scaling *= mTransform; - mTransform = scaling; - } - - domMatrix* matrix = daeSafeCast(element); - if (matrix) - { - domFloat4x4 dom_value = matrix->getValue(); - - LLMatrix4 matrix_transform; - - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - matrix_transform.mMatrix[i][j] = dom_value[i + j*4]; - } - } - - matrix_transform *= mTransform; - mTransform = matrix_transform; - } - - domInstance_geometry* instance_geo = daeSafeCast(element); - if (instance_geo) - { - domGeometry* geo = daeSafeCast(instance_geo->getUrl().getElement()); - if (geo) - { - domMesh* mesh = daeSafeCast(geo->getDescendant(daeElement::matchType(domMesh::ID()))); - if (mesh) - { - LLModel* model = mModel[mesh]; - if (model) - { - LLMatrix4 transformation = mTransform; - - if (mTransform.determinant() < 0) - { //negative scales are not supported - LL_INFOS() << "Negative scale detected, unsupported transform. domInstance_geometry: " << LLModel::getElementLabel(instance_geo) << LL_ENDL; - badElement = true; - } - - std::map materials = getMaterials(model, instance_geo); - - // adjust the transformation to compensate for mesh normalization - LLVector3 mesh_scale_vector; - LLVector3 mesh_translation_vector; - model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); - - LLMatrix4 mesh_translation; - mesh_translation.setTranslation(mesh_translation_vector); - mesh_translation *= transformation; - transformation = mesh_translation; - - LLMatrix4 mesh_scale; - mesh_scale.initScale(mesh_scale_vector); - mesh_scale *= transformation; - transformation = mesh_scale; - - std::string label = getElementLabel(instance_geo); - mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials)); - - stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); - } - } - } - else - { - LL_INFOS() <<"Unable to resolve geometry URL."<(element); - if (instance_node) - { - daeElement* instance = instance_node->getUrl().getElement(); - if (instance) - { - processElement(instance,badElement); - } - } - - //process children - daeTArray< daeSmartRef > children = element->getChildren(); - int childCount = children.getCount(); - for (S32 i = 0; i < childCount; i++) - { - processElement(children[i],badElement); - } - - domNode* node = daeSafeCast(element); - if (node) - { //this element was a node, restore transform before processiing siblings - mTransform = saved_transform; - } -} - -std::map LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo) -{ - std::map materials; - for (U32 i = 0; i < model->mMaterialList.size(); i++) - { - LLImportMaterial import_material; - - domInstance_material* instance_mat = NULL; - - domBind_material::domTechnique_common* technique = - daeSafeCast(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID()))); - - if (technique) - { - daeTArray< daeSmartRef > inst_materials = technique->getChildrenByType(); - for (U32 j = 0; j < inst_materials.getCount(); j++) - { - std::string symbol(inst_materials[j]->getSymbol()); - - if (symbol == model->mMaterialList[i]) // found the binding - { - instance_mat = inst_materials[j]; - } - } - } - - if (instance_mat) - { - domMaterial* material = daeSafeCast(instance_mat->getTarget().getElement()); - if (material) - { - domInstance_effect* instance_effect = - daeSafeCast(material->getDescendant(daeElement::matchType(domInstance_effect::ID()))); - if (instance_effect) - { - domEffect* effect = daeSafeCast(instance_effect->getUrl().getElement()); - if (effect) - { - domProfile_COMMON* profile = - daeSafeCast(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID()))); - if (profile) - { - import_material = profileToMaterial(profile); - } - } - } - } - } - - import_material.mBinding = model->mMaterialList[i]; - materials[model->mMaterialList[i]] = import_material; - } - - return materials; -} - -LLImportMaterial LLModelLoader::profileToMaterial(domProfile_COMMON* material) -{ - LLImportMaterial mat; - mat.mFullbright = FALSE; - - daeElement* diffuse = material->getDescendant("diffuse"); - if (diffuse) - { - domCommon_color_or_texture_type_complexType::domTexture* texture = - daeSafeCast(diffuse->getDescendant("texture")); - if (texture) - { - domCommon_newparam_type_Array newparams = material->getNewparam_array(); - for (U32 i = 0; i < newparams.getCount(); i++) - { - domFx_surface_common* surface = newparams[i]->getSurface(); - if (surface) - { - domFx_surface_init_common* init = surface->getFx_surface_init_common(); - if (init) - { - domFx_surface_init_from_common_Array init_from = init->getInit_from_array(); - - if (init_from.getCount() > i) - { - domImage* image = daeSafeCast(init_from[i]->getValue().getElement()); - if (image) - { - // we only support init_from now - embedded data will come later - domImage::domInit_from* init = image->getInit_from(); - if (init) - { - mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str()); - mat.mDiffuseMapLabel = getElementLabel(material); - } - } - } - } - } - } - } - - domCommon_color_or_texture_type_complexType::domColor* color = - daeSafeCast(diffuse->getDescendant("color")); - if (color) - { - domFx_color_common domfx_color = color->getValue(); - LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); - mat.mDiffuseColor = value; - } - } - - daeElement* emission = material->getDescendant("emission"); - if (emission) - { - LLColor4 emission_color = getDaeColor(emission); - if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25) - { - mat.mFullbright = TRUE; - } - } - - return mat; -} - -// try to get a decent label for this element -std::string LLModelLoader::getElementLabel(daeElement *element) -{ - // if we have a name attribute, use it - std::string name = element->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if we have an ID attribute, use it - if (element->getID()) - { - return std::string(element->getID()); - } - - // if we have a parent, use it - daeElement* parent = element->getParent(); - if (parent) - { - // if parent has a name, use it - std::string name = parent->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if parent has an ID, use it - if (parent->getID()) - { - return std::string(parent->getID()); - } - } - - // try to use our type - daeString element_name = element->getElementName(); - if (element_name) - { - return std::string(element_name); - } - - // if all else fails, use "object" - return std::string("object"); -} - -LLColor4 LLModelLoader::getDaeColor(daeElement* element) -{ - LLColor4 value; - domCommon_color_or_texture_type_complexType::domColor* color = - daeSafeCast(element->getDescendant("color")); - if (color) - { - domFx_color_common domfx_color = color->getValue(); - value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); - } - - return value; -} - -//----------------------------------------------------------------------------- -// LLModelPreview -//----------------------------------------------------------------------------- - -LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) -: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex() -, mPelvisZOffset( 0.0f ) -, mLegacyRigValid( false ) -, mRigValidJointUpload( false ) -, mResetJoints( false ) -, mRigParityWithScene( false ) -, mLastJointUpdate( false ) -{ - mNeedsUpdate = TRUE; - mCameraDistance = 0.f; - mCameraYaw = 0.f; - mCameraPitch = 0.f; - mCameraZoom = 1.f; - mTextureName = 0; - mPreviewLOD = 0; - mModelLoader = NULL; - mMaxTriangleLimit = 0; - mDirty = false; - mGenLOD = false; - mLoading = false; - mLoadState = LLModelLoader::STARTING; - mGroup = 0; - mLODFrozen = false; - mBuildShareTolerance = 0.f; - mBuildQueueMode = GLOD_QUEUE_GREEDY; - mBuildBorderMode = GLOD_BORDER_UNLOCK; - mBuildOperator = GLOD_OPERATOR_EDGE_COLLAPSE; - - for (U32 i = 0; i < LLModel::NUM_LODS; ++i) - { - mRequestedTriangleCount[i] = 0; - mRequestedCreaseAngle[i] = -1.f; - mRequestedLoDMode[i] = 0; - mRequestedErrorThreshold[i] = 0.f; - mRequestedBuildOperator[i] = 0; - mRequestedQueueMode[i] = 0; - mRequestedBorderMode[i] = 0; - mRequestedShareTolerance[i] = 0.f; - } - - mViewOption["show_textures"] = false; - - mFMP = fmp; - - mHasPivot = false; - mModelPivot = LLVector3(0.0f, 0.0f, 0.0f); - - glodInit(); - - //move into joint mapper class - //1. joints for joint offset verification - mMasterJointList.push_front("mPelvis"); - mMasterJointList.push_front("mTorso"); - mMasterJointList.push_front("mChest"); - mMasterJointList.push_front("mNeck"); - mMasterJointList.push_front("mHead"); - mMasterJointList.push_front("mCollarLeft"); - mMasterJointList.push_front("mShoulderLeft"); - mMasterJointList.push_front("mElbowLeft"); - mMasterJointList.push_front("mWristLeft"); - mMasterJointList.push_front("mCollarRight"); - mMasterJointList.push_front("mShoulderRight"); - mMasterJointList.push_front("mElbowRight"); - mMasterJointList.push_front("mWristRight"); - mMasterJointList.push_front("mHipRight"); - mMasterJointList.push_front("mKneeRight"); - mMasterJointList.push_front("mFootRight"); - mMasterJointList.push_front("mHipLeft"); - mMasterJointList.push_front("mKneeLeft"); - mMasterJointList.push_front("mFootLeft"); - //2. legacy joint list - used to verify rigs that will not be using joint offsets - mMasterLegacyJointList.push_front("mPelvis"); - mMasterLegacyJointList.push_front("mTorso"); - mMasterLegacyJointList.push_front("mChest"); - mMasterLegacyJointList.push_front("mNeck"); - mMasterLegacyJointList.push_front("mHead"); - mMasterLegacyJointList.push_front("mHipRight"); - mMasterLegacyJointList.push_front("mKneeRight"); - mMasterLegacyJointList.push_front("mFootRight"); - mMasterLegacyJointList.push_front("mHipLeft"); - mMasterLegacyJointList.push_front("mKneeLeft"); - mMasterLegacyJointList.push_front("mFootLeft"); - - createPreviewAvatar(); -} - -LLModelPreview::~LLModelPreview() -{ - if (mModelLoader) - { - mModelLoader->mPreview = NULL; - mModelLoader = NULL; - } - // *HACK : *TODO : turn this back on when we understand why this crashes - //glodShutdown(); -} - -U32 LLModelPreview::calcResourceCost() -{ - assert_main_thread(); - - rebuildUploadData(); - - //Upload skin is selected BUT check to see if the joints coming in from the asset were malformed. - if (mFMP && mFMP->childGetValue("upload_skin").asBoolean()) - { - bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean(); - if (uploadingJointPositions && !isRigValidForJointPositionUpload()) - { - mFMP->childDisable("ok_btn"); - } - } - - std::set accounted; - U32 num_points = 0; - U32 num_hulls = 0; - - F32 debug_scale = mFMP ? mFMP->childGetValue("import_scale").asReal() : 1.f; - mPelvisZOffset = mFMP ? mFMP->childGetValue("pelvis_offset").asReal() : 3.0f; - - if (mFMP && mFMP->childGetValue("upload_joints").asBoolean()) - { - getPreviewAvatar()->setPelvisOffset(mPelvisZOffset); - } - - F32 streaming_cost = 0.f; - F32 physics_cost = 0.f; - for (U32 i = 0; i < mUploadData.size(); ++i) - { - LLModelInstance& instance = mUploadData[i]; - - if (accounted.find(instance.mModel) == accounted.end()) - { - accounted.insert(instance.mModel); - - LLModel::Decomposition& decomp = - instance.mLOD[LLModel::LOD_PHYSICS] ? - instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics : - instance.mModel->mPhysics; - - //update instance skin info for each lods pelvisZoffset - for (int j = 0; j < LLModel::NUM_LODS; ++j) - { - if (instance.mLOD[j]) - { - instance.mLOD[j]->mSkinInfo.mPelvisOffset = mPelvisZOffset; - } - } - - std::stringstream ostr; - LLSD ret = LLModel::writeModel(ostr, - instance.mLOD[4], - instance.mLOD[3], - instance.mLOD[2], - instance.mLOD[1], - instance.mLOD[0], - decomp, - mFMP->childGetValue("upload_skin").asBoolean(), - mFMP->childGetValue("upload_joints").asBoolean(), - TRUE); - - num_hulls += decomp.mHull.size(); - for (U32 i = 0; i < decomp.mHull.size(); ++i) - { - num_points += decomp.mHull[i].size(); + num_points += decomp.mHull[i].size(); } //calculate streaming cost @@ -3233,7 +1359,11 @@ U32 LLModelPreview::calcResourceCost() F32 radius = scale.length()*0.5f*debug_scale; - streaming_cost += LLMeshRepository::getStreamingCost(ret, radius); + LLMeshCostData costs; + if (LLMeshRepository::getCostData(ret, costs)) + { + streaming_cost += costs.getRadiusBasedStreamingCost(radius); + } } } @@ -3254,6 +1384,15 @@ void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", z)); } +void LLFloaterModelPreview::setPreviewLOD(S32 lod) +{ + if (mModelPreview) + { + mModelPreview->setPreviewLOD(lod); + } +} + + void LLModelPreview::rebuildUploadData() { assert_main_thread(); @@ -3276,29 +1415,12 @@ void LLModelPreview::rebuildUploadData() F32 max_scale = 0.f; - //reorder materials to match mBaseModel - for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) - { - if (mBaseModel.size() == mModel[i].size()) - { - for (U32 j = 0; j < mBaseModel.size(); ++j) - { - - int refFaceCnt = 0; - int modelFaceCnt = 0; - - if (!mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt)) - { - setLoadState( LLModelLoader::ERROR_MATERIALS ); - mFMP->childDisable("calculate_btn"); - } - } - } - } + BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug"); + BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching"); for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter) - { //for each transform in scene - LLMatrix4 mat = iter->first; + { //for each transform in scene + LLMatrix4 mat = iter->first; // compute position LLVector3 position = LLVector3(0, 0, 0) * mat; @@ -3320,42 +1442,223 @@ void LLModelPreview::rebuildUploadData() LLModelInstance instance = *model_iter; LLModel* base_model = instance.mModel; - - if (base_model) + + if (base_model && !requested_name.empty()) { base_model->mRequestedLabel = requested_name; base_model->mMetric = metric; } - U32 idx = 0; - for (idx = 0; idx < mBaseModel.size(); ++idx) - { //find reference instance for this model - if (mBaseModel[idx] == base_model) + for (int i = LLModel::NUM_LODS - 1; i >= LLModel::LOD_IMPOSTOR; i--) + { + LLModel* lod_model = NULL; + if (!legacyMatching) { - break; + // Fill LOD slots by finding matching meshes by label with name extensions + // in the appropriate scene for each LOD. This fixes all kinds of issues + // where the indexed method below fails in spectacular fashion. + // If you don't take the time to name your LOD and PHYS meshes + // with the name of their corresponding mesh in the HIGH LOD, + // then the indexed method will be attempted below. + + LLMatrix4 transform; + + std::string name_to_match = instance.mLabel; + llassert(!name_to_match.empty()); + + int extensionLOD; + if (i != LLModel::LOD_PHYSICS || mModel[LLModel::LOD_PHYSICS].empty()) + { + extensionLOD = i; + } + else + { + //Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for + extensionLOD = mPhysicsSearchLOD; + } + + std::string toAdd; + switch (extensionLOD) + { + case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break; + case LLModel::LOD_LOW: toAdd = "_LOD1"; break; + case LLModel::LOD_MEDIUM: toAdd = "_LOD2"; break; + case LLModel::LOD_PHYSICS: toAdd = "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + if (name_to_match.find(toAdd) == std::string::npos) + { + name_to_match += toAdd; + } + + FindModel(mScene[i], name_to_match, lod_model, transform); + + if (!lod_model && i != LLModel::LOD_PHYSICS) + { + if (importerDebug) + { + LL_INFOS() << "Search of" << name_to_match << " in LOD" << i << " list failed. Searching for alternative among LOD lists." << LL_ENDL; + } + + int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i; + while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model) + { + std::string name_to_match = instance.mLabel; + llassert(!name_to_match.empty()); + + std::string toAdd; + switch (searchLOD) + { + case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break; + case LLModel::LOD_LOW: toAdd = "_LOD1"; break; + case LLModel::LOD_MEDIUM: toAdd = "_LOD2"; break; + case LLModel::LOD_PHYSICS: toAdd = "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + if (name_to_match.find(toAdd) == std::string::npos) + { + name_to_match += toAdd; + } + + // See if we can find an appropriately named model in LOD 'searchLOD' + // + FindModel(mScene[searchLOD], name_to_match, lod_model, transform); + searchLOD++; + } + } } - } + else + { + // Use old method of index-based association + U32 idx = 0; + for (idx = 0; idx < mBaseModel.size(); ++idx) + { + // find reference instance for this model + if (mBaseModel[idx] == base_model) + { + if (importerDebug) + { + LL_INFOS() << "Attempting to use model index " << idx << " for LOD " << i << " of " << instance.mLabel << LL_ENDL; + } + break; + } + } - if (idx < mBaseModel.size()) - { - for (U32 i = 0; i < LLModel::NUM_LODS; i++) - { //fill LOD slots based on reference model index + // If the model list for the current LOD includes that index... + // if (mModel[i].size() > idx) { - instance.mLOD[i] = mModel[i][idx]; + // Assign that index from the model list for our LOD as the LOD model for this instance + // + lod_model = mModel[i][idx]; + if (importerDebug) + { + LL_INFOS() << "Indexed match of model index " << idx << " at LOD " << i << " to model named " << lod_model->mLabel << LL_ENDL; + } } - else + else if (importerDebug) + { + LL_INFOS() << "List of models does not include index " << idx << LL_ENDL; + } + } + + if (lod_model) + { + if (importerDebug) { - instance.mLOD[i] = NULL; + if (i == LLModel::LOD_PHYSICS) + { + LL_INFOS() << "Assigning collision for " << instance.mLabel << " to match " << lod_model->mLabel << LL_ENDL; + } + else + { + LL_INFOS() << "Assigning LOD" << i << " for " << instance.mLabel << " to found match " << lod_model->mLabel << LL_ENDL; + } + } + instance.mLOD[i] = lod_model; + } + else + { + if (i < LLModel::LOD_HIGH && !lodsReady()) + { + // assign a placeholder from previous LOD until lod generation is complete. + // Note: we might need to assign it regardless of conditions like named search does, to prevent crashes. + instance.mLOD[i] = instance.mLOD[i + 1]; + } + if (importerDebug) + { + LL_INFOS() << "List of models does not include " << instance.mLabel << LL_ENDL; + } + } + } + + LLModel* high_lod_model = instance.mLOD[LLModel::LOD_HIGH]; + if (!high_lod_model) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } + else + { + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) + { + int refFaceCnt = 0; + int modelFaceCnt = 0; + llassert(instance.mLOD[i]); + if (instance.mLOD[i] && !instance.mLOD[i]->matchMaterialOrder(high_lod_model, refFaceCnt, modelFaceCnt ) ) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); } } + LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) mFMP; + bool upload_skinweights = fmp && fmp->childGetValue("upload_skin").asBoolean(); + if (upload_skinweights && high_lod_model->mSkinInfo.mJointNames.size() > 0) + { + LLQuaternion bind_rot = LLSkinningUtil::getUnscaledQuaternion(high_lod_model->mSkinInfo.mBindShapeMatrix); + LLQuaternion identity; + if (!bind_rot.isEqualEps(identity,0.01f)) + { + LL_WARNS() << "non-identity bind shape rot. mat is " << high_lod_model->mSkinInfo.mBindShapeMatrix + << " bind_rot " << bind_rot << LL_ENDL; + setLoadState( LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION ); + } + } } instance.mTransform = mat; mUploadData.push_back(instance); } } - + for (U32 lod = 0; lod < LLModel::NUM_LODS-1; lod++) + { + // Search for models that are not included into upload data + // If we found any, that means something we loaded is not a sub-model. + for (U32 model_ind = 0; model_ind < mModel[lod].size(); ++model_ind) + { + bool found_model = false; + for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) + { + LLModelInstance& instance = *iter; + if (instance.mLOD[lod] == mModel[lod][model_ind]) + { + found_model = true; + break; + } + } + if (!found_model && mModel[lod][model_ind] && !mModel[lod][model_ind]->mSubmodelID) + { + if (importerDebug) + { + LL_INFOS() << "Model " << mModel[lod][model_ind]->mLabel << " was not used - mismatching lod models." << LL_ENDL; + } + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } + } + } const F32 DEFAULT_MAX_PRIM_SCALE(gHippoLimits->getMaxPrimScale()); F32 max_import_scale = (DEFAULT_MAX_PRIM_SCALE-0.1f)/max_scale; @@ -3436,15 +1739,17 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw instance.mLOD[LLModel::LOD_LOW], instance.mLOD[LLModel::LOD_IMPOSTOR], decomp, - save_skinweights, save_joint_positions, FALSE, TRUE); - + save_skinweights, + save_joint_positions, + FALSE, TRUE, instance.mModel->mSubmodelID); + data["mesh"][instance.mModel->mLocalID] = str.str(); } data["instance"][i] = instance.asLLSD(); } - llofstream out(filename, std::ios_base::out | std::ios_base::binary); + llofstream out(filename.c_str(), std::ios_base::out | std::ios_base::binary); LLSDSerialize::toBinary(data, out); out.flush(); out.close(); @@ -3462,6 +1767,28 @@ void LLModelPreview::clearModel(S32 lod) mScene[lod].clear(); } +void LLModelPreview::getJointAliases( JointMap& joint_map) +{ + // Get all standard skeleton joints from the preview avatar. + LLVOAvatar *av = getPreviewAvatar(); + + //Joint names and aliases come from avatar_skeleton.xml + + joint_map = av->getJointAliases(); + + std::vector cv_names, attach_names; + av->getSortedJointNames(1, cv_names); + av->getSortedJointNames(2, attach_names); + for (std::vector::iterator it = cv_names.begin(); it != cv_names.end(); ++it) + { + joint_map[*it] = *it; + } + for (std::vector::iterator it = attach_names.begin(); it != attach_names.end(); ++it) + { + joint_map[*it] = *it; + } +} + void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable_slm) { assert_main_thread(); @@ -3486,8 +1813,9 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable // this is the initial file picking. Close the whole floater // if we don't have a base model to show for high LOD. mFMP->close(); - mLoading = false; + } + mLoading = false; return; } @@ -3504,13 +1832,34 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable clearGLODGroup(); } - mModelLoader = new LLModelLoader(filename, lod, this, mJointTransformMap, mJointsFromNode); + std::map joint_alias_map; + getJointAliases(joint_alias_map); + + mModelLoader = new LLDAELoader( + filename, + lod, + &LLModelPreview::loadedCallback, + &LLModelPreview::lookupJointByName, + &LLModelPreview::loadTextures, + &LLModelPreview::stateChangedCallback, + this, + mJointTransformMap, + mJointsFromNode, + joint_alias_map, + LLSkinningUtil::getMaxJointCount(), + gSavedSettings.getU32("ImporterModelLimit"), + gSavedSettings.getBOOL("ImporterPreprocessDAE")); if (force_disable_slm) { mModelLoader->mTrySLM = false; } - + else + { + //only try to load from slm if viewer is configured to do so and this is the + //initial model load (not an LoD or physics shape) + mModelLoader->mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mUploadData.empty(); + } mModelLoader->start(); mFMP->childSetTextArg("status", "[STATUS]", mFMP->getString("status_reading_file")); @@ -3541,6 +1890,7 @@ void LLModelPreview::setPhysicsFromLOD(S32 lod) if (lod >= 0 && lod <= 3) { + mPhysicsSearchLOD = lod; mModel[LLModel::LOD_PHYSICS] = mModel[lod]; mScene[LLModel::LOD_PHYSICS] = mScene[lod]; mLODFile[LLModel::LOD_PHYSICS].clear(); @@ -3560,11 +1910,14 @@ void LLModelPreview::clearIncompatible(S32 lod) return; } + // at this point we don't care about sub-models, + // different amount of sub-models means face count mismatch, not incompatibility + U32 lod_size = countRootModels(mModel[lod]); for (U32 i = 0; i <= LLModel::LOD_HIGH; i++) - { //clear out any entries that aren't compatible with this model + { //clear out any entries that aren't compatible with this model if (i != lod) { - if (mModel[i].size() != mModel[lod].size()) + if (countRootModels(mModel[i]) != lod_size) { mModel[i].clear(); mScene[i].clear(); @@ -3599,7 +1952,7 @@ void LLModelPreview::clearGLODGroup() } } -void LLModelPreview::loadModelCallback(S32 lod) +void LLModelPreview::loadModelCallback(S32 loaded_lod) { assert_main_thread(); @@ -3612,12 +1965,25 @@ void LLModelPreview::loadModelCallback(S32 lod) if (getLoadState() >= LLModelLoader::ERROR_PARSING) { mLoading = false; - return; + mModelLoader = NULL; + mLodsWithParsingError.push_back(loaded_lod); + return ; + } + + mLodsWithParsingError.erase(std::remove(mLodsWithParsingError.begin(), mLodsWithParsingError.end(), loaded_lod), mLodsWithParsingError.end()); + if(mLodsWithParsingError.empty()) + { + mFMP->childEnable( "calculate_btn" ); } - mModelLoader->loadTextures(); + // Copy determinations about rig so UI will reflect them + // + setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload()); + setLegacyRigValid(mModelLoader->isLegacyRigValid()); - if (lod == -1) + mModelLoader->loadTextures() ; + + if (loaded_lod == -1) { //populate all LoDs from model loader scene mBaseModel.clear(); mBaseScene.clear(); @@ -3649,8 +2015,13 @@ void LLModelPreview::loadModelCallback(S32 lod) //override displayed model with current LoD list_iter->mModel = list_iter->mLOD[lod]; + if (!list_iter->mModel) + { + continue; + } + //add current model to current LoD's model list (LLModel::mLocalID makes a good vector index) - U32 idx = list_iter->mModel->mLocalID; + size_t idx = list_iter->mModel->mLocalID; if (mModel[lod].size() <= idx) { //stretch model list to fit model at given index @@ -3699,32 +2070,109 @@ void LLModelPreview::loadModelCallback(S32 lod) resetPreviewTarget(); } else - { //only replace given LoD - mModel[lod] = mModelLoader->mModelList; - mScene[lod] = mModelLoader->mScene; - mVertexBuffer[lod].clear(); + { //only replace given LoD + mModel[loaded_lod] = mModelLoader->mModelList; + mScene[loaded_lod] = mModelLoader->mScene; + mVertexBuffer[loaded_lod].clear(); - setPreviewLOD(lod); + setPreviewLOD(loaded_lod); - if (lod == LLModel::LOD_HIGH) - { //save a copy of the highest LOD for automatic LOD manipulation + if (loaded_lod == LLModel::LOD_HIGH) + { //save a copy of the highest LOD for automatic LOD manipulation if (mBaseModel.empty()) - { //first time we've loaded a model, auto-gen LoD + { //first time we've loaded a model, auto-gen LoD mGenLOD = true; } - mBaseModel = mModel[lod]; - clearGLODGroup(); + mBaseModel = mModel[loaded_lod]; + clearGLODGroup(); + + mBaseScene = mScene[loaded_lod]; + mVertexBuffer[5].clear(); + } + else + { + BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug"); + BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching"); + if (!legacyMatching) + { + if (!mBaseModel.empty()) + { + BOOL name_based = FALSE; + BOOL has_submodels = FALSE; + for (U32 idx = 0; idx < mBaseModel.size(); ++idx) + { + if (mBaseModel[idx]->mSubmodelID) + { // don't do index-based renaming when the base model has submodels + has_submodels = TRUE; + if (importerDebug) + { + LL_INFOS() << "High LOD has submodels" << LL_ENDL; + } + break; + } + } + + for (U32 idx = 0; idx < mModel[loaded_lod].size(); ++idx) + { + std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel); + + LLModel* found_model = NULL; + LLMatrix4 transform; + FindModel(mBaseScene, loaded_name, found_model, transform); + if (found_model) + { // don't rename correctly named models (even if they are placed in a wrong order) + name_based = TRUE; + } + + if (mModel[loaded_lod][idx]->mSubmodelID) + { // don't rename the models when loaded LOD model has submodels + has_submodels = TRUE; + } + } + + if (importerDebug) + { + LL_INFOS() << "Loaded LOD " << loaded_lod << ": correct names" << (name_based ? "" : "NOT ") << "found; submodels " << (has_submodels ? "" : "NOT ") << "found" << LL_ENDL; + } + + if (!name_based && !has_submodels) + { // replace the name of the model loaded for any non-HIGH LOD to match the others (MAINT-5601) + // this actually works like "ImporterLegacyMatching" for this particular LOD + for (U32 idx = 0; idx < mModel[loaded_lod].size() && idx < mBaseModel.size(); ++idx) + { + std::string name = mBaseModel[idx]->mLabel; + std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel); + + if (loaded_name != name) + { + switch (loaded_lod) + { + case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; + case LLModel::LOD_LOW: name += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + if (importerDebug) + { + LL_WARNS() << "Loded model name " << mModel[loaded_lod][idx]->mLabel << " for LOD " << loaded_lod << " doesn't match the base model. Renaming to " << name << LL_ENDL; + } - mBaseScene = mScene[lod]; - mVertexBuffer[5].clear(); + mModel[loaded_lod][idx]->mLabel = name; + } + } + } + } + } } - clearIncompatible(lod); + clearIncompatible(loaded_lod); mDirty = true; - if (lod == LLModel::LOD_HIGH) + if (loaded_lod == LLModel::LOD_HIGH) { resetPreviewTarget(); } @@ -3733,18 +2181,18 @@ void LLModelPreview::loadModelCallback(S32 lod) mLoading = false; if (mFMP) { + mFMP->getChild("confirm_checkbox")->set(FALSE); if (!mBaseModel.empty()) { - if (mFMP->getChild("description_form")->getValue().asString().empty()) - { - const std::string& model_name = mBaseModel[0]->getName(); - mFMP->getChild("description_form")->setValue(model_name); - } + const std::string& model_name = mBaseModel[0]->getName(); + mFMP->getChild("description_form")->setValue(model_name); } } refresh(); mModelLoadedSignal(); + + mModelLoader = NULL; } void LLModelPreview::resetPreviewTarget() @@ -3764,7 +2212,8 @@ void LLModelPreview::generateNormals() S32 which_lod = mPreviewLOD; - if (which_lod > 4 || which_lod < 0 || mModel[which_lod].empty()) + if (which_lod > 4 || which_lod < 0 || + mModel[which_lod].empty()) { return; } @@ -3777,19 +2226,81 @@ void LLModelPreview::generateNormals() if (which_lod == 3 && !mBaseModel.empty()) { - for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter) + if(mBaseModelFacesCopy.empty()) + { + mBaseModelFacesCopy.reserve(mBaseModel.size()); + for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it) + { + v_LLVolumeFace_t faces; + (*it)->copyFacesTo(faces); + mBaseModelFacesCopy.push_back(faces); + } + } + + for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it) { - (*iter)->generateNormals(angle_cutoff); + (*it)->generateNormals(angle_cutoff); } mVertexBuffer[5].clear(); } - for (LLModelLoader::model_list::iterator iter = mModel[which_lod].begin(); iter != mModel[which_lod].end(); ++iter) + bool perform_copy = mModelFacesCopy[which_lod].empty(); + if(perform_copy) { + mModelFacesCopy[which_lod].reserve(mModel[which_lod].size()); + } + + for (LLModelLoader::model_list::iterator it = mModel[which_lod].begin(), itE = mModel[which_lod].end(); it != itE; ++it) + { + if(perform_copy) + { + v_LLVolumeFace_t faces; + (*it)->copyFacesTo(faces); + mModelFacesCopy[which_lod].push_back(faces); + } + + (*it)->generateNormals(angle_cutoff); + } + + mVertexBuffer[which_lod].clear(); + refresh(); + updateStatusMessages(); +} + +void LLModelPreview::restoreNormals() +{ + S32 which_lod = mPreviewLOD; + + if (which_lod > 4 || which_lod < 0 || + mModel[which_lod].empty()) + { + return; + } + + if(!mBaseModelFacesCopy.empty()) { - (*iter)->generateNormals(angle_cutoff); + llassert(mBaseModelFacesCopy.size() == mBaseModel.size()); + + vv_LLVolumeFace_t::const_iterator itF = mBaseModelFacesCopy.begin(); + for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it, ++itF) + { + (*it)->copyFacesFrom((*itF)); + } + + mBaseModelFacesCopy.clear(); } + + if(!mModelFacesCopy[which_lod].empty()) + { + vv_LLVolumeFace_t::const_iterator itF = mModelFacesCopy[which_lod].begin(); + for (LLModelLoader::model_list::iterator it = mModel[which_lod].begin(), itE = mModel[which_lod].end(); it != itE; ++it, ++itF) + { + (*it)->copyFacesFrom((*itF)); + } + mModelFacesCopy[which_lod].clear(); + } + mVertexBuffer[which_lod].clear(); refresh(); updateStatusMessages(); @@ -4029,6 +2540,20 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f); + std::string name = base->mLabel; + + switch (lod) + { + case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; + case LLModel::LOD_LOW: name += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + mModel[lod][mdl_idx]->mLabel = name; + mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID; + GLint* sizes = new GLint[patch_count*2]; glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes); stop_gloderror(); @@ -4141,17 +2666,112 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim { shader->bind(); } +} +void LLModelPreview::genModelBBox() +{ + LLVector3 min, max; + min = this->mModelLoader->mExtents[0]; + max = this->mModelLoader->mExtents[1]; + std::vector v_list; + v_list.resize(4); + std::map > face_list; + + // Face 0 + v_list[0] = LLVector3(min.mV[VX], max.mV[VY], max.mV[VZ]); + v_list[1] = LLVector3(min.mV[VX], min.mV[VY], max.mV[VZ]); + v_list[2] = LLVector3(max.mV[VX], min.mV[VY], max.mV[VZ]); + v_list[3] = LLVector3(max.mV[VX], max.mV[VY], max.mV[VZ]); + face_list.insert(std::pair >(0, v_list)); + + // Face 1 + v_list[0] = LLVector3(max.mV[VX], min.mV[VY], max.mV[VZ]); + v_list[1] = LLVector3(max.mV[VX], min.mV[VY], min.mV[VZ]); + v_list[2] = LLVector3(max.mV[VX], max.mV[VY], min.mV[VZ]); + v_list[3] = LLVector3(max.mV[VX], max.mV[VY], max.mV[VZ]); + face_list.insert(std::pair >(1, v_list)); + + // Face 2 + v_list[0] = LLVector3(min.mV[VX], max.mV[VY], min.mV[VZ]); + v_list[1] = LLVector3(min.mV[VX], max.mV[VY], max.mV[VZ]); + v_list[2] = LLVector3(max.mV[VX], max.mV[VY], max.mV[VZ]); + v_list[3] = LLVector3(max.mV[VX], max.mV[VY], min.mV[VZ]); + face_list.insert(std::pair >(2, v_list)); + + // Face 3 + v_list[0] = LLVector3(min.mV[VX], max.mV[VY], max.mV[VZ]); + v_list[1] = LLVector3(min.mV[VX], max.mV[VY], min.mV[VZ]); + v_list[2] = LLVector3(min.mV[VX], min.mV[VY], min.mV[VZ]); + v_list[3] = LLVector3(min.mV[VX], min.mV[VY], max.mV[VZ]); + face_list.insert(std::pair >(3, v_list)); + + // Face 4 + v_list[0] = LLVector3(min.mV[VX], min.mV[VY], max.mV[VZ]); + v_list[1] = LLVector3(min.mV[VX], min.mV[VY], min.mV[VZ]); + v_list[2] = LLVector3(max.mV[VX], min.mV[VY], min.mV[VZ]); + v_list[3] = LLVector3(max.mV[VX], min.mV[VY], max.mV[VZ]); + face_list.insert(std::pair >(4, v_list)); + + // Face 5 + v_list[0] = LLVector3(min.mV[VX], min.mV[VY], min.mV[VZ]); + v_list[1] = LLVector3(min.mV[VX], max.mV[VY], min.mV[VZ]); + v_list[2] = LLVector3(max.mV[VX], max.mV[VY], min.mV[VZ]); + v_list[3] = LLVector3(max.mV[VX], min.mV[VY], min.mV[VZ]); + face_list.insert(std::pair >(5, v_list)); + + U16 Idx[] = { 0, 1, 2, 3, 0, 2, }; + + U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; + LLPointer buff = new LLVertexBuffer(type_mask, 0); + buff->allocateBuffer(4, 6, true); + + LLStrider pos; + LLStrider idx; + LLStrider norm; + LLStrider tc; + + buff->getVertexStrider(pos); + buff->getIndexStrider(idx); + + buff->getNormalStrider(norm); + buff->getTexCoord0Strider(tc); + + for (U32 i = 0; i < 6; ++i) + { + idx[i] = Idx[i]; + } + + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + LLModel* mdl = new LLModel(volume_params, 0.f); + mdl->mLabel = "BBOX"; // please adopt name from high LOD (mBaseModel) or from original model otherwise it breaks search mechanics which is name based + + mdl->setNumVolumeFaces(6); + for (U8 i = 0; i < 6; ++i) + { + for (U8 j = 0; j < 4; ++j) + { + pos[j] = face_list[i][j]; + } + + mdl->setVolumeFaceData(i, pos, norm, tc, idx, buff->getNumVerts(), buff->getNumIndices()); + } + + if (validate_model(mdl)) + { + LLMatrix4 mat; + std::map materials; + std::vector instance_list; + instance_list.push_back(LLModelInstance(mdl, mdl->mLabel, mat, materials)); - /*if (which_lod == -1 && mScene[LLModel::LOD_PHYSICS].empty()) - { //build physics scene - mScene[LLModel::LOD_PHYSICS] = mScene[LLModel::LOD_LOW]; - mModel[LLModel::LOD_PHYSICS] = mModel[LLModel::LOD_LOW]; + for (S32 i = LLModel::LOD_HIGH - 1; i >= 0; i--) + { + mModel[i].clear(); + mModel[i].push_back(mdl); - for (U32 i = 1; i < mModel[LLModel::LOD_PHYSICS].size(); ++i) - { - mPhysicsQ.push(mModel[LLModel::LOD_PHYSICS][i]); - } - }*/ + mScene[i].clear(); + mScene[i].insert(std::pair >(mat, instance_list)); + } + } } void LLModelPreview::updateStatusMessages() @@ -4168,43 +2788,89 @@ void LLModelPreview::updateStatusMessages() S32 total_verts[LLModel::NUM_LODS]; S32 total_submeshes[LLModel::NUM_LODS]; - for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) + { + total_tris[i] = 0; + total_verts[i] = 0; + total_submeshes[i] = 0; + } + + for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) { - //initialize total for this lod to 0 - total_tris[lod] = total_verts[lod] = total_submeshes[lod] = 0; + LLModelInstance& instance = *iter; - for (LLModelLoader::scene::iterator iter = mScene[lod].begin(), endIter = mScene[lod].end(); iter != endIter; ++iter) + LLModel* model_high_lod = instance.mLOD[LLModel::LOD_HIGH]; + if (!model_high_lod) { - for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance) - { - LLModel* model = instance->mModel; - if (model) - { - //for each model in the lod - S32 cur_tris = 0; - S32 cur_verts = 0; - S32 cur_submeshes = model->getNumVolumeFaces(); + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + continue; + } - for (S32 j = 0; j < cur_submeshes; ++j) - { //for each submesh (face), add triangles and vertices to current total - const LLVolumeFace& face = model->getVolumeFace(j); - cur_tris += face.mNumIndices/3; - cur_verts += face.mNumVertices; - } + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) + { + LLModel* lod_model = instance.mLOD[i]; + if (!lod_model) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } + + int refFaceCnt = 0; + int modelFaceCnt = 0; - //add this model to the lod total - total_tris[lod] += cur_tris; - total_verts[lod] += cur_verts; - total_submeshes[lod] += cur_submeshes; + if (!lod_model->matchMaterialOrder(model_high_lod, refFaceCnt, modelFaceCnt ) ) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } - //store this model's counts to asset data - tris[lod].push_back(cur_tris); - verts[lod].push_back(cur_verts); - submeshes[lod].push_back(cur_submeshes); + if (lod_model) + { + //for each model in the lod + S32 cur_tris = 0; + S32 cur_verts = 0; + S32 cur_submeshes = lod_model->getNumVolumeFaces(); + + for (S32 j = 0; j < cur_submeshes; ++j) + { //for each submesh (face), add triangles and vertices to current total + const LLVolumeFace& face = lod_model->getVolumeFace(j); + cur_tris += face.mNumIndices/3; + cur_verts += face.mNumVertices; } + + std::string instance_name = instance.mLabel; + + BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug"); + if (importerDebug) + { + // Useful for debugging generalized complaints below about total submeshes which don't have enough + // context to address exactly what needs to be fixed to move towards compliance with the rules. + // + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Verts: " << cur_verts << LL_ENDL; + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Tris: " << cur_tris << LL_ENDL; + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Faces: " << cur_submeshes << LL_ENDL; + + LLModel::material_list::iterator mat_iter = lod_model->mMaterialList.begin(); + while (mat_iter != lod_model->mMaterialList.end()) + { + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Material " << *(mat_iter) << LL_ENDL; + mat_iter++; + } + } + + //add this model to the lod total + total_tris[i] += cur_tris; + total_verts[i] += cur_verts; + total_submeshes[i] += cur_submeshes; + + //store this model's counts to asset data + tris[i].push_back(cur_tris); + verts[i].push_back(cur_verts); + submeshes[i].push_back(cur_submeshes); } } - } + } if (mMaxTriangleLimit == 0) { @@ -4217,29 +2883,36 @@ void LLModelPreview::updateStatusMessages() U32 lod = LLModel::LOD_PHYSICS; const LLVector4a scale(0.5f); for (U32 i = 0; i < mModel[lod].size() && !has_degenerate; ++i) - { //for each model in the lod - if (mModel[lod][i]->mPhysics.mHull.empty()) - { //no decomp exists + { //for each model in the lod + if (mModel[lod][i] && mModel[lod][i]->mPhysics.mHull.empty()) + { //no decomp exists S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces(); for (S32 j = 0; j < cur_submeshes && !has_degenerate; ++j) - { //for each submesh (face), add triangles and vertices to current total - const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); - for (S32 k = 0; k < face.mNumIndices && !has_degenerate; ) + { //for each submesh (face), add triangles and vertices to current total + LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); + for (S32 k = 0; (k < face.mNumIndices) && !has_degenerate; ) { - LLVector4a v1; v1.setMul(face.mPositions[face.mIndices[k++]], scale); - LLVector4a v2; v2.setMul(face.mPositions[face.mIndices[k++]], scale); - LLVector4a v3; v3.setMul(face.mPositions[face.mIndices[k++]], scale); + U16 index_a = face.mIndices[k+0]; + U16 index_b = face.mIndices[k+1]; + U16 index_c = face.mIndices[k+2]; + + LLVector4a v1; v1.setMul(face.mPositions[index_a], scale); + LLVector4a v2; v2.setMul(face.mPositions[index_b], scale); + LLVector4a v3; v3.setMul(face.mPositions[index_c], scale); - if (ll_is_degenerate(v1, v2, v3)) + if (ll_is_degenerate(v1,v2,v3)) { has_degenerate = true; } + else + { + k += 3; + } } } } } } - /* Singu Note: Dummy views and what for? mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH])); */ @@ -4248,9 +2921,12 @@ void LLModelPreview::updateStatusMessages() S32 upload_status[LLModel::LOD_HIGH + 1]; - bool upload_ok = true; + mModelNoErrors = true; - for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod) + const U32 lod_high = LLModel::LOD_HIGH; + U32 high_submodel_count = mModel[lod_high].size() - countRootModels(mModel[lod_high]); + + for (S32 lod = 0; lod <= lod_high; ++lod) { upload_status[lod] = 0; @@ -4263,7 +2939,7 @@ void LLModelPreview::updateStatusMessages() } else { - if (lod == LLModel::LOD_HIGH) + if (lod == lod_high) { upload_status[lod] = 2; message = "mesh_status_missing_lod"; @@ -4284,8 +2960,6 @@ void LLModelPreview::updateStatusMessages() mFMP->childSetText(lod_vertices_name[lod], mesh_status_na); } - const U32 lod_high = LLModel::LOD_HIGH; - if (lod != lod_high) { if (total_submeshes[lod] && total_submeshes[lod] != total_submeshes[lod_high]) @@ -4293,6 +2967,13 @@ void LLModelPreview::updateStatusMessages() message = "mesh_status_submesh_mismatch"; upload_status[lod] = 2; } + else if (mModel[lod].size() - countRootModels(mModel[lod]) != high_submodel_count) + {//number of submodels is different, not all faces are matched correctly. + message = "mesh_status_submesh_mismatch"; + upload_status[lod] = 2; + // Note: Submodels in instance were loaded from higher LOD and as result face count + // returns same value and total_submeshes[lod] is identical to high_lod one. + } else if (!tris[lod].empty() && tris[lod].size() != tris[lod_high].size()) { //number of meshes is different message = "mesh_status_mesh_mismatch"; @@ -4313,68 +2994,91 @@ void LLModelPreview::updateStatusMessages() { //too many vertices in this lod message = "mesh_status_too_many_vertices"; - upload_status[lod] = 2; + upload_status[lod] = 1; } } } - std::string img = lod_status_image[upload_status[lod]]; LLIconCtrl* icon = mFMP->getChild(lod_icon_name[lod]); - icon->setVisible(true); - icon->setValue(img); + LLUIImagePtr img = LLUI::getUIImage(lod_status_image[upload_status[lod]]); + icon->setVisible(lodsReady()); + icon->setImage(img); if (upload_status[lod] >= 2) { - upload_ok = false; + mModelNoErrors = false; } if (lod == mPreviewLOD) { mFMP->childSetText("lod_status_message_text", mFMP->getString(message)); icon = mFMP->getChild("lod_status_message_icon"); - icon->setValue(img); + icon->setImage(img); } updateLodControls(lod); } - //make sure no hulls have more than 256 points in them - for (U32 i = 0; upload_ok && i < mModel[LLModel::LOD_PHYSICS].size(); ++i) + + //warn if hulls have more than 256 points in them + BOOL physExceededVertexLimit = FALSE; + for (U32 i = 0; mModelNoErrors && i < mModel[LLModel::LOD_PHYSICS].size(); ++i) { LLModel* mdl = mModel[LLModel::LOD_PHYSICS][i]; - for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j) + if (mdl) { - if (mdl->mPhysics.mHull[j].size() > 256) + for (U32 j = 0; j < mdl->mPhysics.mHull.size(); ++j) { - upload_ok = false; + if (mdl->mPhysics.mHull[j].size() > 256) + { + physExceededVertexLimit = TRUE; + LL_INFOS() << "Physical model " << mdl->mLabel << " exceeds vertex per hull limitations." << LL_ENDL; + break; + } } } } + mFMP->childSetVisible("physics_status_message_text", physExceededVertexLimit); + LLIconCtrl* physStatusIcon = mFMP->getChild("physics_status_message_icon"); + physStatusIcon->setVisible(physExceededVertexLimit); + if (physExceededVertexLimit) + { + mFMP->childSetValue("physics_status_message_text", mFMP->getString("phys_status_vertex_limit_exceeded")); + LLUIImagePtr img = LLUI::getUIImage("ModelImport_Status_Warning"); + physStatusIcon->setImage(img); + } - bool errorStateFromLoader = getLoadState() >= LLModelLoader::ERROR_PARSING ? true : false; + if (getLoadState() >= LLModelLoader::ERROR_PARSING) + { + mModelNoErrors = false; + LL_INFOS() << "Loader returned errors, model can't be uploaded" << LL_ENDL; + } - bool skinAndRigOk = true; bool uploadingSkin = mFMP->childGetValue("upload_skin").asBoolean(); bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean(); - if (uploadingSkin) + if ( uploadingSkin ) { - if (uploadingJointPositions && !isRigValidForJointPositionUpload()) + if ( uploadingJointPositions && !isRigValidForJointPositionUpload() ) { - skinAndRigOk = false; + mModelNoErrors = false; + LL_INFOS() << "Invalid rig, there might be issues with uploading Joint positions" << LL_ENDL; } } - if (upload_ok && mModelLoader) + if(mModelNoErrors && mModelLoader) { - if (!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean()) + if(!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean()) { - upload_ok = false; + // Some textures are still loading, prevent upload until they are done + mModelNoErrors = false; } } - if (!upload_ok || errorStateFromLoader || !skinAndRigOk || has_degenerate) + // Todo: investigate use of has_degenerate and include into mModelNoErrors upload blocking mechanics + // current use of has_degenerate won't block upload permanently - later checks will restore the button + if (!mModelNoErrors || has_degenerate) { mFMP->childDisable("ok_btn"); } @@ -4692,11 +3396,6 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) model = &(mModel[lod]); } - if (!mVertexBuffer[lod].empty()) - { - mVertexBuffer[lod].clear(); - } - mVertexBuffer[lod].clear(); LLModelLoader::model_list::iterator base_iter = mBaseModel.begin(); @@ -4712,7 +3411,8 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) LLModel* base_mdl = *base_iter; base_iter++; - for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + S32 num_faces = mdl->getNumVolumeFaces(); + for (S32 i = 0; i < num_faces; ++i) { const LLVolumeFace &vf = mdl->getVolumeFace(i); U32 num_vertices = vf.mNumVertices; @@ -4780,9 +3480,11 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) for (U32 i = 0; i < weight_list.size(); ++i) { - F32 wght = llmin(weight_list[i].mWeight, 0.999999f); + F32 wght = llclamp(weight_list[i].mWeight, 0.001f, 0.999f); F32 joint = (F32) weight_list[i].mJointIdx; w.mV[i] = joint + wght; + llassert(w.mV[i]-(S32)w.mV[i]>0.0f); // because weights are non-zero, and range of wt values + //should not cause floating point precision issues. } (*(weights_strider++)).loadua(w.mV); @@ -4806,21 +3508,32 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) void LLModelPreview::update() { - if (mDirty) + if (mGenLOD) + { + bool subscribe_for_generation = mLodsQuery.empty(); + mGenLOD = false; + mDirty = true; + mLodsQuery.clear(); + + for (S32 lod = LLModel::LOD_HIGH; lod >= 0; --lod) + { + // adding all lods into query for generation + mLodsQuery.push_back(lod); + } + + if (subscribe_for_generation) + { + doOnIdleRepeating(lodQueryCallback); + } + } + + if (mDirty && mLodsQuery.empty()) { mDirty = false; mResourceCost = calcResourceCost(); refresh(); updateStatusMessages(); } - - if (mGenLOD) - { - mGenLOD = false; - genLODs(); - refresh(); - updateStatusMessages(); - } } //----------------------------------------------------------------------------- @@ -4840,28 +3553,92 @@ LLVector3 LLModelPreview::getTranslationForJointOffset(std::string joint) //----------------------------------------------------------------------------- // createPreviewAvatar //----------------------------------------------------------------------------- -void LLModelPreview::createPreviewAvatar(void) +void LLModelPreview::createPreviewAvatar( void ) { - mPreviewAvatar = (LLVOAvatar*)gObjectList.createObjectViewer( LL_PCODE_LEGACY_AVATAR, gAgent.getRegion() ); - if (mPreviewAvatar) + mPreviewAvatar = (LLVOAvatar*)gObjectList.createObjectViewer( LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), LLViewerObject::CO_FLAG_UI_AVATAR ); + if ( mPreviewAvatar ) { - mPreviewAvatar->createDrawable(&gPipeline); - mPreviewAvatar->mIsDummy = TRUE; + mPreviewAvatar->createDrawable( &gPipeline ); mPreviewAvatar->mSpecialRenderMode = 1; - mPreviewAvatar->setPositionAgent(LLVector3::zero); - mPreviewAvatar->slamPosition(); - mPreviewAvatar->updateJointLODs(); - mPreviewAvatar->updateGeometry(mPreviewAvatar->mDrawable); - mPreviewAvatar->startMotion(ANIM_AGENT_STAND); + mPreviewAvatar->startMotion( ANIM_AGENT_STAND ); mPreviewAvatar->hideSkirt(); } else { - LL_INFOS() <<"Failed to create preview avatar for upload model window"<mSubmodelID == 0) + { + root_models++; + } + model_iter++; + } + return root_models; +} + +void LLModelPreview::loadedCallback( + LLModelLoader::scene& scene, + LLModelLoader::model_list& model_list, + S32 lod, + void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview && !LLModelPreview::sIgnoreLoadedCallback) + { + pPreview->loadModelCallback(lod); + } +} + +void LLModelPreview::stateChangedCallback(U32 state,void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview) + { + pPreview->setLoadState(state); + } +} + +LLJoint* LLModelPreview::lookupJointByName(const std::string& str, void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview) + { + return pPreview->getPreviewAvatar()->getJoint(str); } + return NULL; +} + +U32 LLModelPreview::loadTextures(LLImportMaterial& material,void* opaque) +{ + (void)opaque; + + if (material.mDiffuseMapFilename.size()) + { + material.mOpaqueData = new LLPointer< LLViewerFetchedTexture >; + LLPointer< LLViewerFetchedTexture >& tex = (*reinterpret_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData)); + + tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW); + tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, opaque, NULL, FALSE); + tex->forceToSaveRawImage(0, F32_MAX); + material.setDiffuseMap(tex->getID()); // record tex ID + return 1; + } + + material.mOpaqueData = NULL; + return 0; } -void LLModelPreview::addEmptyFace(LLModel* pTarget) +void LLModelPreview::addEmptyFace( LLModel* pTarget ) { U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; @@ -4919,10 +3696,10 @@ BOOL LLModelPreview::render() S32 height = getHeight(); LLGLSUIDefault def; - LLGLDisable no_blend(GL_BLEND); - LLGLEnable cull(GL_CULL_FACE); + LLGLDisable no_blend; + LLGLEnable cull; LLGLDepthTest depth(GL_TRUE); - LLGLDisable fog(GL_FOG); + LLGLDisable fog; { if (use_shaders) @@ -4984,8 +3761,9 @@ BOOL LLModelPreview::render() if (fmp && isLegacyRigValid()) { fmp->enableViewOption("show_skin_weight"); - fmp->setViewOptionEnabled("show_joint_positions", skin_weight); + fmp->setViewOptionEnabled("show_joint_positions", skin_weight); mFMP->childEnable("upload_skin"); + mFMP->childSetValue("show_skin_weight", skin_weight); } } else @@ -4996,8 +3774,11 @@ BOOL LLModelPreview::render() mViewOption["show_skin_weight"] = false; fmp->disableViewOption("show_skin_weight"); fmp->disableViewOption("show_joint_positions"); + + skin_weight = false; + mFMP->childSetValue("show_skin_weight", false); + fmp->setViewOptionEnabled("show_skin_weight", skin_weight); } - skin_weight = false; } if (upload_skin && !has_skin_weights) @@ -5020,6 +3801,7 @@ BOOL LLModelPreview::render() F32 explode = mFMP->childGetValue("physics_explode").asReal(); + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT); LLRect preview_rect; @@ -5055,7 +3837,8 @@ BOOL LLModelPreview::render() } gGL.loadIdentity(); - gPipeline.enableLightsPreview(); + LLGLState light_state; + gPipeline.enableLightsPreview(light_state); LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * LLQuaternion(mCameraYaw, LLVector3::z_axis); @@ -5079,7 +3862,7 @@ BOOL LLModelPreview::render() const U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; - LLGLEnable normalize(GL_NORMALIZE); + LLGLEnable normalize; if (!mBaseModel.empty() && mVertexBuffer[5].empty()) { @@ -5101,29 +3884,20 @@ BOOL LLModelPreview::render() const LLVertexBuffer* buff = vb_vec[0]; regen = buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) != skin_weight; } - } - - //make sure material lists all match - for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) - { - if (mBaseModel.size() == mModel[i].size()) + else { - for (U32 j = 0; j < mBaseModel.size(); ++j) - { - int refFaceCnt = 0; - int modelFaceCnt = 0; - - if (!mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt)) - { - mFMP->childDisable("calculate_btn"); - } - } + LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL; + regen = TRUE; } } if (regen) { genBuffers(mPreviewLOD, skin_weight); + { + LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL; + regen = TRUE; + } } if (!skin_weight) @@ -5139,39 +3913,40 @@ BOOL LLModelPreview::render() continue; } - gGL.pushMatrix(); - LLMatrix4a mat; - mat.loadu((F32*)instance.mTransform.mMatrix); + gGL.pushMatrix(); - gGL.multMatrix(mat); - - for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) - { - LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; + LLMatrix4a transform; + transform.loadu(instance.mTransform); + gGL.multMatrix(transform); - buffer->setBuffer(type_mask & buffer->getTypeMask()); - if (textures) + U32 num_models = mVertexBuffer[mPreviewLOD][model].size(); + for (U32 i = 0; i < num_models; ++i) { - U32 materialCnt = instance.mModel->mMaterialList.size(); - if (i < materialCnt) + LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; + + buffer->setBuffer(type_mask & buffer->getTypeMask()); + + if (textures) { - const std::string& binding = instance.mModel->mMaterialList[i]; - const LLImportMaterial& material = instance.mMaterial[binding]; + U32 materialCnt = instance.mModel->mMaterialList.size(); + if ( i < materialCnt ) + { + const std::string& binding = instance.mModel->mMaterialList[i]; + const LLImportMaterial& material = instance.mMaterial[binding]; - gGL.diffuseColor4fv(material.mDiffuseColor.mV); + gGL.diffuseColor4fv(material.mDiffuseColor.mV); - if (material.mDiffuseMap.notNull()) - { - if (material.mDiffuseMap->getDiscardLevel() > -1) + // Find the tex for this material, bind it, and add it to our set + // + LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material); + if (tex) { - gGL.getTexUnit(0)->bind(material.mDiffuseMap, true); - mTextureSet.insert(material.mDiffuseMap.get()); + mTextureSet.insert(tex); } } } - } - else + else { gGL.diffuseColor4f(1,1,1,1); } @@ -5182,11 +3957,11 @@ BOOL LLModelPreview::render() if (edges) { - glLineWidth(3.f); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setLineWidth(3.f); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glLineWidth(1.f); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); + gGL.setLineWidth(1.f); } } gGL.popMatrix(); @@ -5194,6 +3969,7 @@ BOOL LLModelPreview::render() if (physics) { + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT); for (U32 i = 0; i < 2; i++) @@ -5208,7 +3984,7 @@ BOOL LLModelPreview::render() } //enable alpha blending on second pass but not first pass - LLGLState blend(GL_BLEND, i); + LLGLState blend(i); gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); @@ -5286,12 +4062,14 @@ BOOL LLModelPreview::render() if (mVertexBuffer[LLModel::LOD_PHYSICS].empty()) { genBuffers(LLModel::LOD_PHYSICS, false); - } - for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i) - { - LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; + } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); + for (U32 i = 0; i < num_models; ++i) + { + LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f); buffer->setBuffer(type_mask & buffer->getTypeMask()); @@ -5299,24 +4077,25 @@ BOOL LLModelPreview::render() gGL.diffuseColor3f(1.f, 1.f, 0.f); - glLineWidth(2.f); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setLineWidth(2.f); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glLineWidth(1.f); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); + gGL.setLineWidth(1.f); } } gGL.popMatrix(); } - glLineWidth(3.f); - glPointSize(8.f); - gPipeline.enableLightsFullbright(LLColor4::white); + gGL.setLineWidth(3.f); + gGL.setPointSize(8.f); + LLGLState light_state; + gPipeline.enableLightsFullbright(light_state); //show degenerate triangles LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); - LLGLDisable cull(GL_CULL_FACE); + LLGLDisable cull; gGL.diffuseColor4f(1.f,0.f,0.f,1.f); const LLVector4a scale(0.5f); @@ -5383,9 +4162,8 @@ BOOL LLModelPreview::render() gGL.popMatrix(); } - glLineWidth(1.f); - glPointSize(1.f); - gPipeline.enableLightsPreview(); + gGL.setLineWidth(1.f); + gGL.setPointSize(1.f); gGL.setSceneBlendType(LLRender::BT_ALPHA); } } @@ -5399,20 +4177,6 @@ BOOL LLModelPreview::render() LLVector3::z_axis, // up target_pos); // point of interest - if (joint_positions) - { - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - if (shader) - { - gDebugProgram.bind(); - } - getPreviewAvatar()->renderCollisionVolumes(); - if (shader) - { - shader->bind(); - } - } - for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter) { for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) @@ -5437,30 +4201,46 @@ BOOL LLModelPreview::render() buffer->setBuffer(type_mask & buffer->getTypeMask()); gGL.diffuseColor4fv(material.mDiffuseColor.mV); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (material.mDiffuseMap.notNull()) + + // Find the tex for this material, bind it, and add it to our set + // + LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material); + if (tex) { - if (material.mDiffuseMap->getDiscardLevel() > -1) - { - gGL.getTexUnit(0)->bind(material.mDiffuseMap, true); - mTextureSet.insert(material.mDiffuseMap.get()); - } + mTextureSet.insert(tex); } - + buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0); gGL.diffuseColor3f(0.4f, 0.4f, 0.4f); if (edges) { - glLineWidth(3.f); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setLineWidth(3.f); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glLineWidth(1.f); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); + gGL.setLineWidth(1.f); } } } } } + + if (joint_positions) + { + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + if (shader) + { + gDebugProgram.bind(); + } + getPreviewAvatar()->renderCollisionVolumes(); + getPreviewAvatar()->renderBones(); + if (shader) + { + shader->bind(); + } + } + } } @@ -5520,6 +4300,12 @@ void LLModelPreview::setPreviewLOD(S32 lod) combo_box->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order mFMP->childSetText("lod_file_" + lod_name[mPreviewLOD], mLODFile[mPreviewLOD]); + LLComboBox* combo_box2 = mFMP->getChild("preview_lod_combo2"); + combo_box2->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order + + LLComboBox* combo_box3 = mFMP->getChild("preview_lod_combo3"); + combo_box3->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order + LLColor4 highlight_color = LLUI::sColorsGroup->getColor("MeshImportTableHighlightColor"); LLColor4 normal_color = LLUI::sColorsGroup->getColor("MeshImportTableNormalColor"); @@ -5552,14 +4338,14 @@ void LLFloaterModelPreview::onReset(void* user_data) LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) user_data; fmp->childDisable("reset_btn"); LLModelPreview* mp = fmp->mModelPreview; - std::string filename = mp->mLODFile[3]; + std::string filename = mp->mLODFile[LLModel::LOD_HIGH]; fmp->resetDisplayOptions(); //reset model preview fmp->initModelPreview(); mp = fmp->mModelPreview; - mp->loadModel(filename,3,true); + mp->loadModel(filename,LLModel::LOD_HIGH,true); } //static @@ -5579,7 +4365,9 @@ void LLFloaterModelPreview::onUpload(void* user_data) mp->mModelPreview->saveUploadData(upload_skinweights, upload_joint_positions); gMeshRepo.uploadModel(mp->mModelPreview->mUploadData, mp->mModelPreview->mPreviewScale, - mp->childGetValue("upload_textures").asBoolean(), upload_skinweights, upload_joint_positions, mp->mUploadModelUrl, + mp->childGetValue("upload_textures").asBoolean(), + upload_skinweights, upload_joint_positions, + mp->mUploadModelUrl, true, LLHandle(), mp->getWholeModelUploadObserverHandle()); } @@ -5590,7 +4378,14 @@ void LLFloaterModelPreview::refresh() } //static -void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ) +void LLModelPreview::textureLoadedCallback( + BOOL success, + LLViewerFetchedTexture *src_vi, + LLImageRaw* src, + LLImageRaw* src_aux, + S32 discard_level, + BOOL final, + void* userdata ) { LLModelPreview* preview = (LLModelPreview*) userdata; preview->refresh(); @@ -5604,6 +4399,39 @@ void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture } } +// static +bool LLModelPreview::lodQueryCallback() +{ + // not the best solution, but model preview belongs to floater + // so it is an easy way to check that preview still exists. + LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance; + if (fmp) + { + if (fmp->mModelPreview) + { + LLModelPreview* preview = fmp->mModelPreview; + if (preview->mLodsQuery.size() > 0) + { + S32 lod = preview->mLodsQuery.back(); + preview->mLodsQuery.pop_back(); + preview->genLODs(lod); + + // return false to continue cycle + return false; + } + } + + for (U32 lod = 0; lod < NUM_LOD; ++lod) + { + LLIconCtrl* icon = fmp->getChild(lod_icon_name[lod]); + icon->setVisible(true); + } + } + + // nothing to process + return true; +} + void LLModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit) { if (!mLODFrozen) @@ -5652,7 +4480,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible) } mUploadBtn->setVisible(!visible); - mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); + mUploadBtn->setEnabled(isModelUploadAllowed()); if (visible) { @@ -5674,6 +4502,12 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod) { mModelPreview->updateLodControls(lod); refresh(); + + LLComboBox* lod_source_combo = getChild("lod_source_" + lod_name[lod]); + if (lod_source_combo->getCurrentIndex() == LLModelPreview::GENERATE) + { //rebuild LoD to update triangle counts + onLODParamCommit(lod, true); + } } void LLFloaterModelPreview::resetDisplayOptions() @@ -5712,7 +4546,7 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived() childSetTextArg("price_breakdown", "[MODEL]", llformat("%d", result["upload_price_breakdown"]["model"].asInteger())); childSetVisible("upload_fee", true); childSetVisible("price_breakdown", true); - mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); + mUploadBtn->setEnabled(isModelUploadAllowed()); } void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) @@ -5736,6 +4570,16 @@ void LLFloaterModelPreview::onModelUploadFailure() mUploadBtn->setEnabled(true); } +bool LLFloaterModelPreview::isModelUploadAllowed() +{ + bool allow_upload = mHasUploadPerm && !mUploadModelUrl.empty(); + if (mModelPreview) + { + allow_upload &= mModelPreview->mModelNoErrors; + } + return allow_upload; +} + S32 LLFloaterModelPreview::DecompRequest::statusCallback(const char* status, S32 p1, S32 p2) { if (mContinue) @@ -5785,8 +4629,17 @@ void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result) // BAP HACK: handle "" for case that MeshUploadFlag cap is broken. mHasUploadPerm = (("" == upload_status) || ("valid" == upload_status)); - //mUploadBtn->setEnabled(mHasUploadPerm); - mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); + if (!mHasUploadPerm) + { + LL_WARNS() << "Upload permission set to false because upload_status=\"" << upload_status << "\"" << LL_ENDL; + } + else if (mHasUploadPerm && mUploadModelUrl.empty()) + { + LL_WARNS() << "Upload permission set to true but uploadModelUrl is empty!" << LL_ENDL; + } + + // isModelUploadAllowed() includes mHasUploadPerm + mUploadBtn->setEnabled(isModelUploadAllowed()); getChild("warning_title")->setVisible(!mHasUploadPerm); getChild("warning_message")->setVisible(!mHasUploadPerm); } @@ -5797,3 +4650,13 @@ void LLFloaterModelPreview::setPermissonsErrorStatus(U32 status, const std::stri LLNotificationsUtil::add("MeshUploadPermError"); } + +bool LLFloaterModelPreview::isModelLoading() +{ + if(mModelPreview) + { + return mModelPreview->mLoading; + } + return false; +} + diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 46e290dcba..7585dce936 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -2,31 +2,25 @@ * @file llfloatermodelpreview.h * @brief LLFloaterModelPreview class definition * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2010, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * 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. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -42,105 +36,24 @@ #include "llviewermenufile.h" #include "llfloatermodeluploadbase.h" +#include "lldaeloader.h" + class LLComboBox; +class LLJoint; +class LLViewerJointMesh; class LLVOAvatar; class LLVertexBuffer; class LLModelPreview; class LLFloaterModelPreview; +class DAE; class daeElement; class domProfile_COMMON; class domInstance_geometry; class domNode; class domTranslate; class domController; - -typedef std::map JointTransformMap; -typedef std::map:: iterator JointTransformMapIt; - -const S32 NUM_LOD = 4; - -class LLModelLoader : public LLThread -{ -public: - typedef enum - { - STARTING = 0, - READING_FILE, - CREATING_FACES, - GENERATING_VERTEX_BUFFERS, - GENERATING_LOD, - DONE, - ERROR_PARSING, //basically loading failed - ERROR_MATERIALS, - } eLoadState; - - U32 mState; - std::string mFilename; - S32 mLod; - LLModelPreview* mPreview; - LLMatrix4 mTransform; - BOOL mFirstTransform; - LLVector3 mExtents[2]; - bool mTrySLM; - - std::map > mModel; - - typedef std::vector > model_list; - model_list mModelList; - - typedef std::vector model_instance_list; - - typedef std::map scene; - - scene mScene; - - typedef std::queue > model_queue; - - //queue of models that need a physics rep - model_queue mPhysicsQ; - - LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, - std::deque& jointsFromNodes); - ~LLModelLoader() ; - - virtual void run(); - bool doLoadModel(); - bool loadFromSLM(const std::string& filename); - void loadModelCallback(); - - void loadTextures() ; //called in the main thread. - void processElement(daeElement* element, bool& badElement); - std::map getMaterials(LLModel* model, domInstance_geometry* instance_geo); - LLImportMaterial profileToMaterial(domProfile_COMMON* material); - std::string getElementLabel(daeElement *element); - LLColor4 getDaeColor(daeElement* element); - - daeElement* getChildFromElement(daeElement* pElement, std::string const & name); - - bool isNodeAJoint(domNode* pNode); - void processJointNode(domNode* pNode, std::map& jointTransforms); - void extractTranslation(domTranslate* pTranslate, LLMatrix4& transform); - void extractTranslationViaElement(daeElement* pTranslateElement, LLMatrix4& transform); - void extractTranslationViaSID(daeElement* pElement, LLMatrix4& transform); - - void setLoadState(U32 state); - - void buildJointToNodeMappingFromScene(daeElement* pRoot); - void processJointToNodeMapping(domNode* pNode); - void processChildJoints(domNode* pParentNode); - - //map of avatar joints as named in COLLADA assets to internal joint names - std::map mJointMap; - JointTransformMap& mJointList; - std::deque& mJointsFromNode; - - S32 mNumOfFetchingTextures ; //updated in the main thread - bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread. - -private: - static std::list sActiveLoaderList; - static bool isAlive(LLModelLoader* loader) ; -}; +class domSkin; +class domMesh; class LLFloaterModelPreview : public LLFloaterModelUploadBase { @@ -171,13 +84,14 @@ class LLFloaterModelPreview : public LLFloaterModelUploadBase BOOL handleHover(S32 x, S32 y, MASK mask); BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - /*virtual*/ void onOpen(/*const LLSD& key*/); + /*virtual*/ void onOpen(); + /*virtual*/ void onClose(bool app_quitting); static void onMouseCaptureLostModelPreview(LLMouseHandler*); static void setUploadAmount(S32 amount) { sUploadAmount = amount; } void setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost); - + void setPreviewLOD(S32 lod); void onBrowseLOD(S32 lod); static void onReset(void* data); @@ -197,6 +111,8 @@ class LLFloaterModelPreview : public LLFloaterModelUploadBase void enableViewOption(const std::string& option); void disableViewOption(const std::string& option); + bool isModelLoading(); + // shows warning message if agent has no permissions to upload model /*virtual*/ void onPermissionsReceived(const LLSD& result); @@ -211,6 +127,8 @@ class LLFloaterModelPreview : public LLFloaterModelUploadBase /*virtual*/ void onModelUploadFailure(); + bool isModelUploadAllowed(); + protected: friend class LLModelPreview; friend class LLPhysicsDecomp; @@ -337,10 +255,15 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex virtual BOOL needsRender() { return mNeedsUpdate; } void setPreviewLOD(S32 lod); void clearModel(S32 lod); + void getJointAliases(JointMap& joint_map); void loadModel(std::string filename, S32 lod, bool force_disable_slm = false); void loadModelCallback(S32 lod); + bool lodsReady() { return !mGenLOD && mLodsQuery.empty(); } + void queryLODs() { mGenLOD = true; }; void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false); + void genModelBBox(); // Generate just a model BBox if we can't generate proper LOD void generateNormals(); + void restoreNormals(); U32 calcResourceCost(); void rebuildUploadData(); void saveUploadData(bool save_skinweights, bool save_joint_poisitions); @@ -354,44 +277,52 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex const bool getModelPivot(void) const { return mHasPivot; } void setHasPivot(bool val) { mHasPivot = val; } - void setModelPivot(const LLVector3& pivot) { mModelPivot = pivot; } + void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; } - //Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps) - void critiqueRigForUploadApplicability(const std::vector &jointListFromAsset); - void critiqueJointToNodeMappingFromScene(void); //Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions //Accessors for joint position upload friendly rigs - const bool isRigValidForJointPositionUpload(void) const { return mRigValidJointUpload; } - void setRigValidForJointPositionUpload(bool rigValid) { mRigValidJointUpload = rigValid; } - bool isRigSuitableForJointPositionUpload(const std::vector &jointListFromAsset); - //Determines if a rig is a legacy from the joint list - bool isRigLegacy(const std::vector &jointListFromAsset); + const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; } + void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; } + //Accessors for the legacy rigs - const bool isLegacyRigValid(void) const { return mLegacyRigValid; } - void setLegacyRigValid(bool rigValid) { mLegacyRigValid = rigValid; } - //Verify that a controller matches vertex counts - bool verifyController(domController* pController); + const bool isLegacyRigValid( void ) const { return mLegacyRigValid; } + void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; } + + static void textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); + static bool lodQueryCallback(); + + boost::signals2::connection setDetailsCallback( const details_signal_t::slot_type& cb ){ return mDetailsSignal.connect(cb); } + boost::signals2::connection setModelLoadedCallback( const model_loaded_signal_t::slot_type& cb ){ return mModelLoadedSignal.connect(cb); } + boost::signals2::connection setModelUpdatedCallback( const model_updated_signal_t::slot_type& cb ){ return mModelUpdatedSignal.connect(cb); } + + void setLoadState( U32 state ) { mLoadState = state; } + U32 getLoadState() { return mLoadState; } + void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; } + const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; } + + LLVector3 getTranslationForJointOffset( std::string joint ); - static void textureLoadedCallback(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata); + static bool sIgnoreLoadedCallback; + std::vector mLodsQuery; + std::vector mLodsWithParsingError; - boost::signals2::connection setDetailsCallback(const details_signal_t::slot_type& cb){ return mDetailsSignal.connect(cb); } - boost::signals2::connection setModelLoadedCallback(const model_loaded_signal_t::slot_type& cb){ return mModelLoadedSignal.connect(cb); } - boost::signals2::connection setModelUpdatedCallback(const model_updated_signal_t::slot_type& cb){ return mModelUpdatedSignal.connect(cb); } +protected: - void setLoadState(U32 state) { mLoadState = state; } - U32 getLoadState() { return mLoadState; } - void setRigWithSceneParity(bool state) { mRigParityWithScene = state; } - const bool getRigWithSceneParity(void) const { return mRigParityWithScene; } + static void loadedCallback(LLModelLoader::scene& scene,LLModelLoader::model_list& model_list, S32 lod, void* opaque); + static void stateChangedCallback(U32 state, void* opaque); - LLVector3 getTranslationForJointOffset(std::string joint); + static LLJoint* lookupJointByName(const std::string&, void* opaque); + static U32 loadTextures(LLImportMaterial& material, void* opaque); private: //Utility function for controller vertex compare - bool verifyCount(int expected, int result); + bool verifyCount( int expected, int result ); //Creates the dummy avatar for the preview window - void createPreviewAvatar(void); + void createPreviewAvatar( void ); //Accessor for the dummy avatar - LLVOAvatar* getPreviewAvatar(void) { return mPreviewAvatar; } + LLVOAvatar* getPreviewAvatar( void ) { return mPreviewAvatar; } + // Count amount of original models, excluding sub-models + static U32 countRootModels(LLModelLoader::model_list models); protected: friend class LLModelLoader; @@ -413,12 +344,14 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex LLVector3 mPreviewTarget; LLVector3 mPreviewScale; S32 mPreviewLOD; + S32 mPhysicsSearchLOD; U32 mResourceCost; std::string mLODFile[LLModel::NUM_LODS]; bool mLoading; U32 mLoadState; bool mResetJoints; bool mRigParityWithScene; + bool mModelNoErrors; std::map mViewOption; @@ -445,6 +378,12 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex LLModelLoader::model_list mModel[LLModel::NUM_LODS]; LLModelLoader::model_list mBaseModel; + typedef std::vector v_LLVolumeFace_t; + typedef std::vector vv_LLVolumeFace_t; + + vv_LLVolumeFace_t mModelFacesCopy[LLModel::NUM_LODS]; + vv_LLVolumeFace_t mBaseModelFacesCopy; + U32 mGroup; std::map, U32> mObject; U32 mMaxTriangleLimit; @@ -463,16 +402,15 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex bool mHasPivot; float mPelvisZOffset; - + bool mRigValidJointUpload; bool mLegacyRigValid; bool mLastJointUpdate; - std::deque mMasterJointList; - std::deque mMasterLegacyJointList; - std::deque mJointsFromNode; - JointTransformMap mJointTransformMap; + JointNameSet mJointsFromNode; + JointTransformMap mJointTransformMap; + LLPointer mPreviewAvatar; }; diff --git a/indra/newview/llfloatermute.cpp b/indra/newview/llfloatermute.cpp index cced63ab15..568cae367f 100644 --- a/indra/newview/llfloatermute.cpp +++ b/indra/newview/llfloatermute.cpp @@ -41,11 +41,10 @@ // project include #include "llfloateravatarpicker.h" +#include "llgroupactions.h" #include "llmutelist.h" #include "llnamelistctrl.h" -#include - // // Constants // @@ -248,20 +247,20 @@ void LLFloaterMute::refreshMuteList() { case LLMute::GROUP: icon_column.value = mGroupIcon->getName(); - element.target = LLNameListCtrl::GROUP; + element.target = LLNameListItem::GROUP; break; case LLMute::AGENT: icon_column.value = mAvatarIcon->getName(); - element.target = LLNameListCtrl::INDIVIDUAL; + element.target = LLNameListItem::INDIVIDUAL; break; case LLMute::OBJECT: icon_column.value = mObjectIcon->getName(); - element.target = LLNameListCtrl::SPECIAL; + element.target = LLNameListItem::SPECIAL; break; case LLMute::BY_NAME: default: icon_column.value = mNameIcon->getName(); - element.target = LLNameListCtrl::SPECIAL; + element.target = LLNameListItem::SPECIAL; break; } diff --git a/indra/newview/llfloatermute.h b/indra/newview/llfloatermute.h index 1a04ae198a..b9a1165286 100644 --- a/indra/newview/llfloatermute.h +++ b/indra/newview/llfloatermute.h @@ -72,6 +72,7 @@ class LLFloaterMute void onPickUser(const uuid_vec_t& ids, const std::vector& names); static void onClickMuteByName(void*); static void callbackMuteByName(const std::string& text, void*); + void showProfile() const; private: LLNameListCtrl* mMuteList; diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp index 465b7d3762..32730a5612 100644 --- a/indra/newview/llfloaternamedesc.cpp +++ b/indra/newview/llfloaternamedesc.cpp @@ -48,11 +48,11 @@ #include "llviewermenufile.h" // upload_new_resource() #include "lluictrlfactory.h" #include "llstring.h" -#include "lleconomy.h" // linden includes #include "llassetstorage.h" #include "llinventorytype.h" +#include "llagentbenefits.h" #include "hippogridmanager.h" @@ -134,13 +134,37 @@ BOOL LLFloaterNameDesc::postBuild() // Cancel button getChild("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnCancel, this)); - getChild("ok_btn")->setLabelArg("[UPLOADFEE]", llformat("%s%d", gHippoGridManager->getConnectedGrid()->getCurrencySymbol().c_str(), LLGlobalEconomy::Singleton::getInstance()->getPriceUpload())); + S32 expected_upload_cost = getExpectedUploadCost(); + getChild("ok_btn")->setLabelArg("[UPLOADFEE]", llformat("%s%d", gHippoGridManager->getConnectedGrid()->getCurrencySymbol().c_str(), expected_upload_cost)); setDefaultBtn("ok_btn"); return TRUE; } +S32 LLFloaterNameDesc::getExpectedUploadCost() const +{ + std::string exten = gDirUtilp->getExtension(mFilename); + LLAssetType::EType asset_type = exten == "wav" ? LLAssetType::AT_SOUND + : (exten == "anim" || exten == "bvh") ? LLAssetType::AT_ANIMATION + : exten != "lsl" ? LLAssetType::AT_TEXTURE + : LLAssetType::AT_NONE; + S32 upload_cost = -1; + + if (asset_type != LLAssetType::AT_NONE) + { + if (!LLAgentBenefitsMgr::current().findUploadCost(asset_type, upload_cost)) + { + LL_WARNS() << "Unable to find upload cost for asset type " << asset_type << LL_ENDL; + } + } + /*else + { + LL_WARNS() << "Unable to find upload cost for " << mFilename << LL_ENDL; + }*/ + return upload_cost; +} + //----------------------------------------------------------------------------- // LLFloaterNameDesc() //----------------------------------------------------------------------------- @@ -173,7 +197,8 @@ void LLFloaterNameDesc::onBtnOK() getChildView("ok_btn")->setEnabled(FALSE); // don't allow inadvertent extra uploads LLAssetStorage::LLStoreAssetCallback callback = NULL; - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass). + S32 expected_upload_cost = getExpectedUploadCost(); + void *nruserdata = NULL; std::string display_name = LLStringUtil::null; diff --git a/indra/newview/llfloaternamedesc.h b/indra/newview/llfloaternamedesc.h index ad7472d4f0..5b5229dd49 100644 --- a/indra/newview/llfloaternamedesc.h +++ b/indra/newview/llfloaternamedesc.h @@ -53,6 +53,8 @@ class LLFloaterNameDesc : public LLFloater void onBtnCancel(); void doCommit(); + S32 getExpectedUploadCost() const; + protected: virtual void onCommit(); diff --git a/indra/newview/llfloaterobjectiminfo.cpp b/indra/newview/llfloaterobjectiminfo.cpp index e1a0806f8c..5d26dac1b9 100644 --- a/indra/newview/llfloaterobjectiminfo.cpp +++ b/indra/newview/llfloaterobjectiminfo.cpp @@ -35,17 +35,13 @@ #include "llfloaterobjectiminfo.h" #include "llagentdata.h" -#include "llavataractions.h" -#include "llcachename.h" #include "llcommandhandler.h" -#include "llfloatergroupinfo.h" #include "llfloatermute.h" -#include "llgroupactions.h" #include "llmutelist.h" +#include "llnamebox.h" #include "llslurl.h" #include "lltrans.h" #include "llui.h" -#include "lluictrl.h" #include "lluictrlfactory.h" #include "llurlaction.h" #include "llweb.h" @@ -61,25 +57,16 @@ LLFloaterObjectIMInfo::LLFloaterObjectIMInfo(const LLSD& seed) : mName(), mSLurl(), mOwnerID(), mGroupOwned(false) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_object_im_info.xml"); - - if (!getRect().mLeft && !getRect().mBottom) - center(); -} -static void show_avatar_profile(const LLUUID& id) -{ -// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0g - if ((gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) || gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) && RlvUtil::isNearbyAgent(id)) - return; -// [/RLVa:KB] - LLAvatarActions::showProfile(id); + const auto& rect = getRect(); + if (!rect.mLeft && !rect.mBottom) + center(); } BOOL LLFloaterObjectIMInfo::postBuild() { getChild("Mute")->setCommitCallback(boost::bind(&LLFloaterObjectIMInfo::onClickMute, this)); - getChild("OwnerName")->setClickedCallback(boost::bind(boost::ref(mGroupOwned) ? boost::bind(LLGroupActions::show, boost::ref(mOwnerID)) : boost::bind(show_avatar_profile, boost::ref(mOwnerID)))); - getChild("Slurl")->setClickedCallback(boost::bind(LLUrlAction::executeSLURL, boost::bind(std::plus(), "secondlife:///app/worldmap/", boost::ref(mSLurl)))); + getChild("Slurl")->setClickedCallback(boost::bind(LLUrlAction::executeSLURL, boost::bind(std::plus(), "secondlife:///app/worldmap/", boost::ref(mSLurl)), true)); return true; } @@ -103,23 +90,20 @@ void LLFloaterObjectIMInfo::update(const LLSD& data) childSetVisible("Unknown_Slurl",!have_slurl); childSetVisible("Slurl",have_slurl); - childSetText("ObjectName",mName); + childSetText("ObjectName", mName); std::string slurl(mSLurl); std::string::size_type i = slurl.rfind("?owner_not_object"); if (i != std::string::npos) slurl.erase(i) += getString("owner"); childSetText("Slurl", slurl); - childSetText("OwnerName", LLStringUtil::null); + getChild("OwnerName")->setNameID(mOwnerID, mGroupOwned ? LFIDBearer::GROUP : LFIDBearer::AVATAR); getChildView("ObjectID")->setValue(data["object_id"].asUUID()); -// bool my_object = (owner_id == gAgentID); +// bool my_object = !mGroupOwned && (owner_id == gAgentID); // [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0g - bool my_object = (mOwnerID == gAgentID) || ((gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) || gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) && (RlvUtil::isNearbyAgent(mOwnerID))); + bool my_object = !mGroupOwned && (mOwnerID == gAgentID) || ((gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) || gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) && (RlvUtil::isNearbyAgent(mOwnerID))); // [/RLVa:KB] childSetEnabled("Mute",!my_object); - - if (gCacheName) - gCacheName->get(mOwnerID, mGroupOwned, boost::bind(&LLFloaterObjectIMInfo::nameCallback, this, _2)); } void LLFloaterObjectIMInfo::onClickMute() @@ -130,31 +114,21 @@ void LLFloaterObjectIMInfo::onClickMute() // [/RLVa:KB] LLMuteList::instance().add(LLMute(mOwnerID, mName, mGroupOwned ? LLMute::GROUP : LLMute::AGENT)); - LLFloaterMute::showInstance(); + LLFloaterMute::showInstance()->selectMute(mOwnerID); close(); } -//static -void LLFloaterObjectIMInfo::nameCallback(const std::string& full_name) -{ - childSetText("OwnerName", mName = -// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0g - (!mGroupOwned && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) || gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) && RlvUtil::isNearbyAgent(mOwnerID)) ? RlvStrings::getAnonym(mName) : -// [/RLVa:KB] - full_name); -} - //////////////////////////////////////////////////////////////////////////// // LLObjectIMHandler //moved to llchathistory.cpp in v2 // support for secondlife:///app/objectim/{UUID}/ SLapps -class LLObjectIMHandler : public LLCommandHandler +class LLObjectIMHandler final : public LLCommandHandler { public: // requests will be throttled from a non-trusted browser LLObjectIMHandler() : LLCommandHandler("objectim", UNTRUSTED_THROTTLE) { } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) override { if (params.size() < 1) { diff --git a/indra/newview/llfloaterobjectiminfo.h b/indra/newview/llfloaterobjectiminfo.h index 31ff8c1628..acddd14797 100644 --- a/indra/newview/llfloaterobjectiminfo.h +++ b/indra/newview/llfloaterobjectiminfo.h @@ -35,21 +35,19 @@ #include "llfloater.h" -class LLFloaterObjectIMInfo : public LLFloater, public LLFloaterSingleton +class LLFloaterObjectIMInfo final : public LLFloater, public LLFloaterSingleton { public: LLFloaterObjectIMInfo(const LLSD& sd); virtual ~LLFloaterObjectIMInfo() { }; - /*virtual*/ BOOL postBuild(); + BOOL postBuild() override; void update(const LLSD& payload); // UI Handlers void onClickMute(); - void nameCallback(const std::string& full_name); - private: LLUUID mOwnerID; std::string mSLurl; diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp index e84517fbd0..3eb19e065e 100644 --- a/indra/newview/llfloaterobjectweights.cpp +++ b/indra/newview/llfloaterobjectweights.cpp @@ -44,11 +44,10 @@ bool LLCrossParcelFunctor::apply(LLViewerObject* obj) mBoundingBox.addBBoxAgent(LLBBox(obj->getPositionRegion(), obj->getRotationRegion(), obj->getScale() * -0.5f, obj->getScale() * 0.5f).getAxisAligned()); // Extend the bounding box across all the children. - LLViewerObject::const_child_list_t children = obj->getChildren(); - for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin(); - iter != children.end(); iter++) + LLViewerObject::const_child_list_t const& children = obj->getChildren(); + for (const auto& iter : children) { - LLViewerObject* child = *iter; + LLViewerObject* child = iter; mBoundingBox.addBBoxAgent(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); } @@ -67,16 +66,16 @@ bool LLCrossParcelFunctor::apply(LLViewerObject* obj) LLFloaterObjectWeights::LLFloaterObjectWeights(const LLSD& key) : LLFloater(key), - mSelectedObjects(NULL), - mSelectedPrims(NULL), - mSelectedDownloadWeight(NULL), - mSelectedPhysicsWeight(NULL), - mSelectedServerWeight(NULL), - mSelectedDisplayWeight(NULL), - mSelectedOnLand(NULL), - mRezzedOnLand(NULL), - mRemainingCapacity(NULL), - mTotalCapacity(NULL) + mSelectedObjects(nullptr), + mSelectedPrims(nullptr), + mSelectedDownloadWeight(nullptr), + mSelectedPhysicsWeight(nullptr), + mSelectedServerWeight(nullptr), + mSelectedDisplayWeight(nullptr), + mSelectedOnLand(nullptr), + mRezzedOnLand(nullptr), + mRemainingCapacity(nullptr), + mTotalCapacity(nullptr) { //buildFromFile("floater_tools.xml"); LLUICtrlFactory::getInstance()->buildFloater(this,"floater_object_weights.xml", NULL, false); @@ -142,7 +141,8 @@ void LLFloaterObjectWeights::setErrorStatus(U32 status, const std::string& reaso void LLFloaterObjectWeights::updateLandImpacts(const LLParcel* parcel) { - if (!parcel || LLSelectMgr::getInstance()->getSelection()->isEmpty()) + auto selection = LLSelectMgr::instance().getSelection(); + if (!parcel || !selection || selection->isEmpty()) { updateIfNothingSelected(); } @@ -161,24 +161,24 @@ void LLFloaterObjectWeights::updateLandImpacts(const LLParcel* parcel) void LLFloaterObjectWeights::refresh() { - LLSelectMgr* sel_mgr = LLSelectMgr::getInstance(); + auto selection = LLSelectMgr::instance().getSelection(); - if (sel_mgr->getSelection()->isEmpty()) + if (!selection || selection->isEmpty()) { updateIfNothingSelected(); } else { - S32 prim_count = sel_mgr->getSelection()->getObjectCount(); - S32 link_count = sel_mgr->getSelection()->getRootObjectCount(); - F32 prim_equiv = sel_mgr->getSelection()->getSelectedLinksetCost(); + S32 prim_count = selection->getObjectCount(); + S32 link_count = selection->getRootObjectCount(); + F32 prim_equiv = selection->getSelectedLinksetCost(); mSelectedObjects->setText(llformat("%d", link_count)); mSelectedPrims->setText(llformat("%d", prim_count)); mSelectedOnLand->setText(llformat("%.1d", (S32)prim_equiv)); LLCrossParcelFunctor func; - if (sel_mgr->getSelection()->applyToRootObjects(&func, true)) + if (selection->applyToRootObjects(&func, true)) { // Some of the selected objects cross parcel bounds. // We don't display object weights and land impacts in this case. @@ -194,8 +194,8 @@ void LLFloaterObjectWeights::refresh() LLViewerRegion* region = gAgent.getRegion(); if (region && region->capabilitiesReceived()) { - for (LLObjectSelection::valid_root_iterator iter = sel_mgr->getSelection()->valid_root_begin(); - iter != sel_mgr->getSelection()->valid_root_end(); ++iter) + for (LLObjectSelection::valid_root_iterator iter = selection->valid_root_begin(); + iter != selection->valid_root_end(); ++iter) { LLAccountingCostManager::getInstance()->addObject((*iter)->getObject()->getID()); } @@ -212,7 +212,6 @@ void LLFloaterObjectWeights::refresh() } else { - //LL_WARNS() << "Failed to get region capabilities" << LL_ENDL; LL_WARNS() << "Failed to get region capabilities" << LL_ENDL; } } diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp deleted file mode 100644 index 22dbe1d87c..0000000000 --- a/indra/newview/llfloateroutbox.cpp +++ /dev/null @@ -1,688 +0,0 @@ -/** - * @file llfloateroutbox.cpp - * @brief Implementation of the merchant outbox window - * - * $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 "llviewerprecompiledheaders.h" - -#include "llfloateroutbox.h" - -#include "llfolderview.h" -#include "llinventorybridge.h" -#include "llinventorymodelbackgroundfetch.h" -#include "llinventoryobserver.h" -#include "llinventorypanel.h" -#include "llmarketplacefunctions.h" -#include "llnotifications.h" -#include "llnotificationsutil.h" -#include "lltextbox.h" -#include "lltexteditor.h" -//#include "lltransientfloatermgr.h" -#include "lltrans.h" -#include "llviewernetwork.h" -//#include "llwindowshade.h" - -#define USE_WINDOWSHADE_DIALOGS 0 - - -///---------------------------------------------------------------------------- -/// LLOutboxNotification class -///---------------------------------------------------------------------------- - -class LLOutboxNotification -{ -public: - bool processNotification(const LLSD& notify) - { - LLFloaterOutbox* outbox_floater = LLFloaterOutbox::getInstance(); - - outbox_floater->showNotification(notify); - - return false; - } -}; - -///---------------------------------------------------------------------------- -/// LLOutboxAddedObserver helper class -///---------------------------------------------------------------------------- - -class LLOutboxAddedObserver : public LLInventoryCategoryAddedObserver -{ -public: - LLOutboxAddedObserver(LLFloaterOutbox * outboxFloater) - : LLInventoryCategoryAddedObserver() - , mOutboxFloater(outboxFloater) - { - } - - void done() - { - for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it) - { - LLViewerInventoryCategory* added_category = *it; - - LLFolderType::EType added_category_type = added_category->getPreferredType(); - - if (added_category_type == LLFolderType::FT_OUTBOX) - { - mOutboxFloater->initializeMarketPlace(); - } - } - } - -private: - LLFloaterOutbox * mOutboxFloater; -}; - -///---------------------------------------------------------------------------- -/// LLFloaterOutbox -///---------------------------------------------------------------------------- - -LLFloaterOutbox::LLFloaterOutbox(const LLSD& key) - : LLFloater(key) - , mCategoriesObserver(NULL) - , mCategoryAddedObserver(NULL) - , mImportBusy(false) - , mImportButton(NULL) - , mInventoryFolderCountText(NULL) - , mInventoryImportInProgress(NULL) - , mInventoryPlaceholder(NULL) - , mInventoryText(NULL) - , mInventoryTitle(NULL) - , mOutboxId(LLUUID::null) - , mOutboxItemCount(0) - , mOutboxTopLevelDropZone(NULL) -// , mWindowShade(NULL) -{ - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_merchant_outbox.xml"); - -} - -LLFloaterOutbox::~LLFloaterOutbox() -{ - if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) - { - gInventory.removeObserver(mCategoriesObserver); - } - delete mCategoriesObserver; - - if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) - { - gInventory.removeObserver(mCategoryAddedObserver); - } - delete mCategoryAddedObserver; -} - -BOOL LLFloaterOutbox::postBuild() -{ - mInventoryFolderCountText = getChild("outbox_folder_count"); - mInventoryImportInProgress = getChild("import_progress_indicator"); - mInventoryPlaceholder = getChild("outbox_inventory_placeholder_panel"); - mInventoryText = mInventoryPlaceholder->getChild("outbox_inventory_placeholder_text"); - // For some reason, adding style doesn't work unless this is true. - mInventoryText->setParseHTML(TRUE); - - mInventoryTitle = mInventoryPlaceholder->getChild("outbox_inventory_placeholder_title"); - - mImportButton = getChild("outbox_import_btn"); - mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this)); - - // Set up the outbox inventory view - LLInventoryPanel* inventory_panel = getChild("panel_outbox_inventory"); - mOutboxInventoryPanel = inventory_panel->getInventoryPanelHandle(); - llassert(mOutboxInventoryPanel.get() != NULL); - - mOutboxTopLevelDropZone = getChild("outbox_generic_drag_target"); - - LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this)); - - // Observe category creation to catch outbox creation (moot if already existing) - mCategoryAddedObserver = new LLOutboxAddedObserver(this); - gInventory.addObserver(mCategoryAddedObserver); - - return TRUE; -} - -void LLFloaterOutbox::cleanOutbox() -{ - // Note: we cannot delete the mOutboxInventoryPanel as that point - // as this is called through callback observers of the panel itself. - // Doing so would crash rapidly. - - // Invalidate the outbox data - mOutboxId.setNull(); - mOutboxItemCount = 0; -} - -void LLFloaterOutbox::onClose(bool app_quitting) -{ -/* - if (mWindowShade) - { - delete mWindowShade; - - mWindowShade = NULL; - } -*/ - setVisible(FALSE); - //destroy(); //Don't because outbox should be persistent. -} - -void LLFloaterOutbox::onOpen() -{ - // - // Initialize the Market Place or go update the outbox - // - - if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED) - { - initializeMarketPlace(); - } - else - { - setupOutbox(); - } - - // - // Update the floater view - // - updateView(); - - // - // Trigger fetch of outbox contents - // - fetchOutboxContents(); -} - -void LLFloaterOutbox::onFocusReceived() -{ - fetchOutboxContents(); -} - -void LLFloaterOutbox::fetchOutboxContents() -{ - if (mOutboxId.notNull()) - { - LLInventoryModelBackgroundFetch::instance().start(mOutboxId); - } -} - -void LLFloaterOutbox::setupOutbox() -{ - if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() != MarketplaceStatusCodes::MARKET_PLACE_MERCHANT) - { - // If we are *not* a merchant or we have no market place connection established yet, do nothing - return; - } - - // We are a merchant. Get the outbox, create it if needs be. - LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, true); - if (outbox_id.isNull()) - { - // We should never get there unless inventory fails badly - LL_ERRS() << "Inventory problem: failure to create the outbox for a merchant!" << LL_ENDL; - return; - } - - // Consolidate Merchant Outbox - // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention, things get messy and conventions get broken down eventually - gInventory.consolidateForType(outbox_id, LLFolderType::FT_OUTBOX); - - if (outbox_id == mOutboxId) - { - - LL_WARNS() << "Inventory warning: Merchant outbox already set" << LL_ENDL; - return; - } - mOutboxId = outbox_id; - - // No longer need to observe new category creation - if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) - { - gInventory.removeObserver(mCategoryAddedObserver); - delete mCategoryAddedObserver; - mCategoryAddedObserver = NULL; - } - llassert(!mCategoryAddedObserver); - - // Create observer for outbox modifications : clear the old one and create a new one - if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) - { - gInventory.removeObserver(mCategoriesObserver); - delete mCategoriesObserver; - } - mCategoriesObserver = new LLInventoryCategoriesObserver(); - gInventory.addObserver(mCategoriesObserver); - mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this)); - llassert(mCategoriesObserver); - - // Set up the outbox inventory view - // Singu Note: we handle this in postBuild, grabbing the panel from the built xml. - LLInventoryPanel* inventory_panel = mOutboxInventoryPanel.get(); - - // Reshape the inventory to the proper size - LLRect inventory_placeholder_rect = mInventoryPlaceholder->getRect(); - inventory_panel->setShape(inventory_placeholder_rect); - - // Set the sort order newest to oldest - inventory_panel->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME); - inventory_panel->getFilter()->markDefault(); - - // Get the content of the outbox - fetchOutboxContents(); -} - -void LLFloaterOutbox::initializeMarketPlace() -{ - // - // Initialize the marketplace import API - // - LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance(); - - if (!importer.isInitialized()) - { - importer.setInitializationErrorCallback(boost::bind(&LLFloaterOutbox::initializationReportError, this, _1, _2)); - importer.setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1)); - importer.setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2)); - importer.initialize(); - } -} - -void LLFloaterOutbox::setStatusString(const std::string& statusString) -{ - llassert(mInventoryFolderCountText != NULL); - - mInventoryFolderCountText->setText(statusString); -} - -void LLFloaterOutbox::updateFolderCount() -{ - if (mOutboxInventoryPanel.get() && mOutboxId.notNull()) - { - S32 item_count = 0; - - if (mOutboxId.notNull()) - { - LLInventoryModel::cat_array_t * cats; - LLInventoryModel::item_array_t * items; - gInventory.getDirectDescendentsOf(mOutboxId, cats, items); - - item_count = cats->size() + items->size(); - } - - mOutboxItemCount = item_count; - } - else - { - // If there's no outbox, the number of items in it should be set to 0 for consistency - mOutboxItemCount = 0; - } - - if (!mImportBusy) - { - updateFolderCountStatus(); - } -} - -void LLFloaterOutbox::updateFolderCountStatus() -{ - if (mOutboxInventoryPanel.get() && mOutboxId.notNull()) - { - switch (mOutboxItemCount) - { - case 0: setStatusString(getString("OutboxFolderCount0")); break; - case 1: setStatusString(getString("OutboxFolderCount1")); break; - default: - { - std::string item_count_str = llformat("%d", mOutboxItemCount); - - LLStringUtil::format_map_t args; - args["[NUM]"] = item_count_str; - - setStatusString(getString("OutboxFolderCountN", args)); - break; - } - } - } - - mImportButton->setEnabled(mOutboxItemCount > 0); -} - -void LLFloaterOutbox::updateView() -{ - //updateView() is called twice the first time. - updateFolderCount(); - LLInventoryPanel* panel = mOutboxInventoryPanel.get(); - - if (mOutboxItemCount > 0) - { - panel->setVisible(TRUE); - mInventoryPlaceholder->setVisible(FALSE); - mOutboxTopLevelDropZone->setVisible(TRUE); - } - else - { - if (panel) - { - panel->setVisible(FALSE); - } - - // Show the drop zone if there is an outbox folder - mOutboxTopLevelDropZone->setVisible(mOutboxId.notNull()); - - mInventoryPlaceholder->setVisible(TRUE); - - std::string outbox_text; - std::string outbox_text2; - std::string outbox_title; - std::string outbox_tooltip; - - const LLSD& subs = getMarketplaceStringSubstitutions(); - U32 mkt_status = LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus(); - - // Text styles for marketplace hyperlinks - std::string subs_link; - std::string subs_text; - - if (mOutboxId.notNull()) - { - // Does the outbox needs recreation? - if ((mOutboxInventoryPanel.get() == NULL) || !gInventory.getCategory(mOutboxId)) - { - setupOutbox(); - } - // "Outbox is empty!" message strings - outbox_text = LLTrans::getString("InventoryOutboxNoItems"); - subs_link = "[MARKETPLACE_DASHBOARD_URL]"; - subs_text = " " + LLTrans::getString("InventoryOutboxNoItemsSubs"); - outbox_text2 = LLTrans::getString("InventoryOutboxNoItems2"); - outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle"); - outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip"); - } - else if (mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) - { - // "Initializing!" message strings - outbox_text = LLTrans::getString("InventoryOutboxInitializing"); - subs_link = "[MARKETPLACE_CREATE_STORE_URL]"; - subs_text = " " + LLTrans::getString("InventoryOutboxInitializingSubs"); - outbox_text2 = LLTrans::getString("InventoryOutboxInitializing2"); - outbox_title = LLTrans::getString("InventoryOutboxInitializingTitle"); - outbox_tooltip = LLTrans::getString("InventoryOutboxInitializingTooltip"); - } - else if (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT) - { - // "Not a merchant!" message strings - outbox_text = LLTrans::getString("InventoryOutboxNotMerchant"); - subs_link = "[MARKETPLACE_CREATE_STORE_URL]"; - subs_text = " " + LLTrans::getString("InventoryOutboxNotMerchantSubs"); - outbox_text2 = LLTrans::getString("InventoryOutboxNotMerchant2"); - outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); - outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); - } - else - { - // "Errors!" message strings - outbox_text = LLTrans::getString("InventoryOutboxError"); - subs_link = "[MARKETPLACE_CREATE_STORE_URL]"; - subs_text = " " + LLTrans::getString("InventoryOutboxErrorSubs"); - outbox_text2 = " " + LLTrans::getString("InventoryOutboxError2"); - outbox_title = LLTrans::getString("InventoryOutboxErrorTitle"); - outbox_tooltip = LLTrans::getString("InventoryOutboxErrorTooltip"); - } - - mInventoryText->clear(); - const LLColor4 color = gColors.getColor("TextFgReadOnlyColor"); - mInventoryText->appendColoredText(outbox_text, false, false, color); - LLStringUtil::format(subs_link, subs); - LLStyleSP subs_link_style(new LLStyle); - subs_link_style->setLinkHREF(subs_link); - subs_link_style->setColor(gSavedSettings.getColor4("HTMLLinkColor")); - mInventoryText->appendStyledText(subs_text, false, false, subs_link_style); - mInventoryText->appendColoredText(outbox_text2, false, false, color); - mInventoryTitle->setValue(outbox_title); - mInventoryPlaceholder->getParent()->setToolTip(outbox_tooltip); - } -} - -bool isAccepted(EAcceptance accept) -{ - return (accept >= ACCEPT_YES_COPY_SINGLE); -} - -BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - if ((mOutboxInventoryPanel.get() == NULL) || - //(mWindowShade && mWindowShade->isShown()) || - LLMarketplaceInventoryImporter::getInstance()->isImportInProgress() || - mOutboxId.isNull()) - { - return FALSE; - } - - LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - BOOL handled = (handled_view != NULL); - - // Determine if the mouse is inside the inventory panel itself or just within the floater - bool pointInInventoryPanel = false; - bool pointInInventoryPanelChild = false; - LLInventoryPanel* panel = mOutboxInventoryPanel.get(); - LLFolderView * root_folder = panel->getRootFolder(); - if (panel->getVisible()) - { - S32 inv_x, inv_y; - localPointToOtherView(x, y, &inv_x, &inv_y, panel); - - pointInInventoryPanel = panel->getRect().pointInRect(inv_x, inv_y); - - LLView * inventory_panel_child_at_point = panel->childFromPoint(inv_x, inv_y, true); - pointInInventoryPanelChild = (inventory_panel_child_at_point != root_folder); - } - - // Pass all drag and drop for this floater to the outbox inventory control - if (!handled || !isAccepted(*accept)) - { - // Handle the drag and drop directly to the root of the outbox if we're not in the inventory panel - // (otherwise the inventory panel itself will handle the drag and drop operation, without any override) - if (!pointInInventoryPanel) - { - handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - } - - mOutboxTopLevelDropZone->setBackgroundVisible(handled && !drop && isAccepted(*accept)); - } - else - { - mOutboxTopLevelDropZone->setBackgroundVisible(!pointInInventoryPanelChild); - } - - return handled; -} - -BOOL LLFloaterOutbox::handleHover(S32 x, S32 y, MASK mask) -{ - mOutboxTopLevelDropZone->setBackgroundVisible(FALSE); - - return LLFloater::handleHover(x, y, mask); -} -/* -void LLFloaterOutbox::onMouseLeave(S32 x, S32 y, MASK mask) -{ - mOutboxTopLevelDropZone->setBackgroundVisible(FALSE); - - LLFloater::onMouseLeave(x, y, mask); -} -*/ -void LLFloaterOutbox::onImportButtonClicked() -{ - if (mOutboxInventoryPanel.get()) - { - mOutboxInventoryPanel.get()->clearSelection(); - } - - mImportBusy = LLMarketplaceInventoryImporter::instance().triggerImport(); -} - -void LLFloaterOutbox::onOutboxChanged() -{ - LLViewerInventoryCategory* category = gInventory.getCategory(mOutboxId); - if (mOutboxId.notNull() && category) - { - fetchOutboxContents(); - updateView(); - } - else - { - cleanOutbox(); - } -} - -void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content) -{ - if (status == MarketplaceErrorCodes::IMPORT_DONE) - { - LLNotificationsUtil::add("OutboxImportComplete"); - } - else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) - { - const LLSD& subs = getMarketplaceStringSubstitutions(); - - LLNotificationsUtil::add("OutboxImportHadErrors", subs); - } - else - { - char status_string[16]; - sprintf(status_string, "%d", status); - - LLSD subs; - subs["[ERROR_CODE]"] = status_string; - - LLNotificationsUtil::add("OutboxImportFailed", subs); - } - - updateView(); -} - -void LLFloaterOutbox::importStatusChanged(bool inProgress) -{ - if (mOutboxId.isNull() && (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_MERCHANT)) - { - setupOutbox(); - } - - if (inProgress) - { - if (mImportBusy) - { - setStatusString(getString("OutboxImporting")); - } - else - { - setStatusString(getString("OutboxInitializing")); - } - - mImportBusy = true; - mImportButton->setEnabled(false); - mInventoryImportInProgress->setVisible(true); - } - else - { - setStatusString(""); - mImportBusy = false; - mImportButton->setEnabled(mOutboxItemCount > 0); - mInventoryImportInProgress->setVisible(false); - } - - updateView(); -} - -void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content) -{ - if (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) - { - char status_string[16]; - sprintf(status_string, "%d", status); - - LLSD subs; - subs["[ERROR_CODE]"] = status_string; - - LLNotificationsUtil::add("OutboxInitFailed", subs); - } - - updateView(); -} - -void LLFloaterOutbox::showNotification(const LLSD& notify) -{ - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if (!notification) - { - LL_ERRS() << "Unable to find outbox notification!" << notify.asString() << LL_ENDL; - - return; - } - -#if USE_WINDOWSHADE_DIALOGS - - if (mWindowShade) - { - delete mWindowShade; - } - - LLRect floater_rect = getLocalRect(); - floater_rect.mTop -= getHeaderHeight(); - floater_rect.stretch(-5, 0); - - LLWindowShade::Params params; - params.name = "notification_shade"; - params.rect = floater_rect; - params.follows.flags = FOLLOWS_ALL; - params.modal = true; - params.can_close = false; - params.shade_color = LLColor4::white % 0.25f; - params.text_color = LLColor4::white; - - mWindowShade = LLUICtrlFactory::create(params); - - addChild(mWindowShade); - mWindowShade->show(notification); - -#else //USE_WINDOWSHADE_DIALOGS -/* - LLNotificationsUI::LLEventHandler * handler = - LLNotificationsUI::LLNotificationManager::instance().getHandlerForNotification("alertmodal"); - - LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast(handler); - llassert(sys_handler); - - sys_handler->processNotification(notify); -*/ - LLNotifications::instance().add(notification); -#endif //USE_WINDOWSHADE_DIALOGS -} - diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h deleted file mode 100644 index 61a11c50d0..0000000000 --- a/indra/newview/llfloateroutbox.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @file llfloateroutbox.h - * @brief LLFloaterOutbox - * class definition - * - * $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 - * ABILITY 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_LLFLOATEROUTBOX_H -#define LL_LLFLOATEROUTBOX_H - -#include "llfloater.h" -#include "llfoldertype.h" -#include "llnotificationptr.h" - - -class LLButton; -class LLInventoryCategoriesObserver; -class LLInventoryCategoryAddedObserver; -class LLInventoryPanel; -class LLLoadingIndicator; -class LLNotification; -class LLTextBox; -class LLTextEditor; -class LLView; -//class LLWindowShade; - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFloaterOutbox -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFloaterOutbox : public LLFloater, public LLFloaterSingleton -{ -public: - LLFloaterOutbox(const LLSD& key); - ~LLFloaterOutbox(); - - void initializeMarketPlace(); - - // virtuals - BOOL postBuild(); - BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - - void showNotification(const LLSD& notify); - - BOOL handleHover(S32 x, S32 y, MASK mask); -// void onMouseLeave(S32 x, S32 y, MASK mask); - -protected: - void setupOutbox(); - void cleanOutbox(); - void fetchOutboxContents(); - - void importReportResults(U32 status, const LLSD& content); - void importStatusChanged(bool inProgress); - void initializationReportError(U32 status, const LLSD& content); - - void onClose(bool app_quitting); - void onOpen(); - - void onFocusReceived(); - - void onImportButtonClicked(); - void onOutboxChanged(); - - void setStatusString(const std::string& statusString); - - void updateFolderCount(); - void updateFolderCountStatus(); - void updateView(); - -private: - LLInventoryCategoriesObserver * mCategoriesObserver; - LLInventoryCategoryAddedObserver * mCategoryAddedObserver; - - bool mImportBusy; - LLButton * mImportButton; - - LLTextBox * mInventoryFolderCountText; - LLView * mInventoryImportInProgress; - LLView * mInventoryPlaceholder; - LLTextEditor * mInventoryText; - LLTextBox * mInventoryTitle; - - LLUUID mOutboxId; - LLHandle mOutboxInventoryPanel; - U32 mOutboxItemCount; - LLPanel * mOutboxTopLevelDropZone; - - //LLWindowShade * mWindowShade; -}; - -#endif // LL_LLFLOATEROUTBOX_H diff --git a/indra/newview/llfloaterpathfindinglinksets.cpp b/indra/newview/llfloaterpathfindinglinksets.cpp index 35f6b9c1f4..8352d140cc 100644 --- a/indra/newview/llfloaterpathfindinglinksets.cpp +++ b/indra/newview/llfloaterpathfindinglinksets.cpp @@ -77,6 +77,7 @@ LLFloaterPathfindingLinksets::LLFloaterPathfindingLinksets(const LLSD& pSeed) mFilterByDescription(NULL), mFilterByLinksetUse(NULL), mEditLinksetUse(NULL), + mEditLinksetUseUnset(nullptr), mEditLinksetUseWalkable(NULL), mEditLinksetUseStaticObstacle(NULL), mEditLinksetUseDynamicObstacle(NULL), diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp index aa6b76c87b..a71419139a 100644 --- a/indra/newview/llfloaterperms.cpp +++ b/indra/newview/llfloaterperms.cpp @@ -42,6 +42,7 @@ #include "llviewerwindow.h" #include "lluictrlfactory.h" #include "llpermissions.h" +#include "llsdserialize.h" #include "hippogridmanager.h" extern class AIHTTPTimeoutPolicy floaterPermsResponder_timeout; @@ -64,19 +65,18 @@ U32 LLFloaterPerms::getEveryonePerms(std::string prefix) } //static -U32 LLFloaterPerms::getNextOwnerPermsInverted(std::string prefix) +U32 LLFloaterPerms::getNextOwnerPerms(std::string prefix) { - // Sets bits for permissions that are off U32 flags = PERM_MOVE; - if (!gSavedSettings.getBOOL(prefix+"NextOwnerCopy")) + if ( gSavedSettings.getBOOL(prefix+"NextOwnerCopy") ) { flags |= PERM_COPY; } - if (!gSavedSettings.getBOOL(prefix+"NextOwnerModify")) + if ( gSavedSettings.getBOOL(prefix+"NextOwnerModify") ) { flags |= PERM_MODIFY; } - if (!gSavedSettings.getBOOL(prefix+"NextOwnerTransfer")) + if ( gSavedSettings.getBOOL(prefix+"NextOwnerTransfer") ) { flags |= PERM_TRANSFER; } @@ -84,18 +84,19 @@ U32 LLFloaterPerms::getNextOwnerPermsInverted(std::string prefix) } //static -U32 LLFloaterPerms::getNextOwnerPerms(std::string prefix) +U32 LLFloaterPerms::getNextOwnerPermsInverted(std::string prefix) { + // Sets bits for permissions that are off U32 flags = PERM_MOVE; - if ( gSavedSettings.getBOOL(prefix+"NextOwnerCopy") ) + if (!gSavedSettings.getBOOL(prefix+"NextOwnerCopy")) { flags |= PERM_COPY; } - if ( gSavedSettings.getBOOL(prefix+"NextOwnerModify") ) + if (!gSavedSettings.getBOOL(prefix+"NextOwnerModify")) { flags |= PERM_MODIFY; } - if ( gSavedSettings.getBOOL(prefix+"NextOwnerTransfer") ) + if (!gSavedSettings.getBOOL(prefix+"NextOwnerTransfer")) { flags |= PERM_TRANSFER; } @@ -138,6 +139,7 @@ LLFloaterPermsDefault::LLFloaterPermsDefault(const LLSD& seed) LLUICtrlFactory::getInstance()->buildFloater(this, "floater_perm_prefs.xml"); } + // String equivalents of enum Categories - initialization order must match enum order! const std::string LLFloaterPermsDefault::sCategoryNames[CAT_LAST] = { @@ -224,41 +226,66 @@ void LLFloaterPermsDefault::onClickCancel() close(); } -class LLFloaterPermsResponder : public LLHTTPClient::ResponderWithResult +struct LLFloaterPermsRequester final : LLSingleton +{ + friend class LLSingleton; + std::string mUrl; + LLSD mReport; + U8 mRetriesCount = 0; + static void init(const std::string url, const LLSD report) + { + auto& inst = instance(); + inst.mUrl = url; + inst.mReport = report; + inst.retry(); + } + bool retry(); +}; + +class LLFloaterPermsResponder final : public LLHTTPClient::ResponderWithResult { -public: - LLFloaterPermsResponder() : LLHTTPClient::ResponderWithResult() {} -private: static std::string sPreviousReason; - void httpFailure(void) + void httpFailure() override { - // Prevent 404s from annoying the user all the tme - if (mStatus == HTTP_NOT_FOUND) - LL_INFOS("FloaterPermsResponder") << "Failed to send default permissions to simulator. 404, reason: " << mReason << LL_ENDL; - else - // + auto* requester = LLFloaterPermsRequester::getIfExists(); + if (!requester || requester->retry()) return; + + LLFloaterPermsRequester::deleteSingleton(); + const std::string& reason = getReason(); // Do not display the same error more than once in a row - if (mReason != sPreviousReason) + if (reason != sPreviousReason) { - sPreviousReason = mReason; + sPreviousReason = reason; LLSD args; - args["REASON"] = mReason; + args["REASON"] = reason; LLNotificationsUtil::add("DefaultObjectPermissions", args); } } - void httpSuccess(void) + void httpSuccess() override { + //const LLSD& content = getContent(); + //dump_sequential_xml("perms_responder_result.xml", content); + // Since we have had a successful POST call be sure to display the next error message // even if it is the same as a previous one. sPreviousReason = ""; - mCapSent = true; - LL_INFOS("FloaterPermsResponder") << "Sent default permissions to simulator" << LL_ENDL; + LL_INFOS("ObjectPermissionsFloater") << "Default permissions successfully sent to simulator" << LL_ENDL; } - /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy() const { return floaterPermsResponder_timeout; } - /*virtual*/ char const* getName() const { return "LLFloaterPermsResponder"; } + AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy() const override { return floaterPermsResponder_timeout; } + char const* getName() const override { return "LLFloaterPermsResponder"; } }; +bool LLFloaterPermsRequester::retry() +{ + if (++mRetriesCount < 5) + { + LLHTTPClient::post(mUrl, mReport, new LLFloaterPermsResponder); + return true; + } + return false; +} + std::string LLFloaterPermsResponder::sPreviousReason; void LLFloaterPermsDefault::sendInitialPerms() @@ -266,12 +293,13 @@ void LLFloaterPermsDefault::sendInitialPerms() if (!mCapSent) { updateCap(); + mCapSent = true; } } void LLFloaterPermsDefault::updateCap() { - std::string object_url = gAgent.getRegion()->getCapability("AgentPreferences"); + std::string object_url = gAgent.getRegionCapability("AgentPreferences"); if (!object_url.empty()) { @@ -283,13 +311,24 @@ void LLFloaterPermsDefault::updateCap() report["default_object_perm_masks"]["NextOwner"] = (LLSD::Integer)LLFloaterPerms::getNextOwnerPerms(sCategoryNames[CAT_OBJECTS]); - LLHTTPClient::post(object_url, report, new LLFloaterPermsResponder()); + { + std::ostringstream sent_perms_log; + LLSDSerialize::toPrettyXML(report, sent_perms_log); + LL_DEBUGS("ObjectPermissionsFloater") << "Sending default permissions to '" + << object_url << "'\n" + << sent_perms_log.str() << LL_ENDL; + } + LLFloaterPermsRequester::init(object_url, report); } + else + { + LL_DEBUGS("ObjectPermissionsFloater") << "AgentPreferences cap not available." << LL_ENDL; + } } void LLFloaterPermsDefault::ok() { - // Changes were already applied to saved settings. + // Changes were already applied automatically to saved settings. // Refreshing internal values makes it official. refresh(); @@ -302,11 +341,11 @@ void LLFloaterPermsDefault::cancel() { for (U32 iter = CAT_OBJECTS; iter < CAT_LAST; iter++) { - gSavedSettings.setBOOL(sCategoryNames[iter]+"ShareWithGroup", mShareWithGroup[iter]); - gSavedSettings.setBOOL(sCategoryNames[iter]+"EveryoneCopy", mEveryoneCopy[iter]); gSavedSettings.setBOOL(sCategoryNames[iter]+"NextOwnerCopy", mNextOwnerCopy[iter]); gSavedSettings.setBOOL(sCategoryNames[iter]+"NextOwnerModify", mNextOwnerModify[iter]); gSavedSettings.setBOOL(sCategoryNames[iter]+"NextOwnerTransfer", mNextOwnerTransfer[iter]); + gSavedSettings.setBOOL(sCategoryNames[iter]+"ShareWithGroup", mShareWithGroup[iter]); + gSavedSettings.setBOOL(sCategoryNames[iter]+"EveryoneCopy", mEveryoneCopy[iter]); gSavedPerAccountSettings.setBOOL(sCategoryNames[iter]+"EveryoneExport", mEveryoneExport[iter]); } } diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index d75796d3fa..045acd953c 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -41,6 +41,7 @@ #include "lldir.h" #include "llagent.h" +#include "llagentui.h" #include "llui.h" #include "lllineeditor.h" #include "llviewertexteditor.h" @@ -54,7 +55,6 @@ #include "llviewerwindow.h" #include "llstatusbar.h" #include "llviewerregion.h" -#include "lleconomy.h" #include "lltrans.h" #include "llgl.h" @@ -103,11 +103,7 @@ void LLFloaterPostcard::init() if(!gAgent.getID().isNull()) { // we're logged in, so we can get this info. - gMessageSystem->newMessageFast(_PREHASH_UserInfoRequest); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gAgent.sendReliableMessage(); + gAgent.sendAgentUserInfoRequest(); } sInstances.insert(this); @@ -128,7 +124,7 @@ BOOL LLFloaterPostcard::postBuild() childDisable("from_form"); std::string name_string; - gAgent.buildFullname(name_string); + LLAgentUI::buildFullname(name_string); childSetValue("name_form", LLSD(name_string)); LLTextEditor* MsgField = getChild("msg_form"); @@ -233,7 +229,7 @@ void LLFloaterPostcard::onClose(bool app_quitting) destroy(); } -class LLSendPostcardResponder : public LLAssetUploadResponder +class LLSendPostcardResponder final : public LLAssetUploadResponder { private: int mSnapshotIndex; @@ -248,22 +244,22 @@ class LLSendPostcardResponder : public LLAssetUploadResponder { } // *TODO define custom uploadFailed here so it's not such a generic message - /*virtual*/ void uploadComplete(const LLSD& content) + void uploadComplete(const LLSD& content) override final { // we don't care about what the server returns from this post, just clean up the UI LLFloaterSnapshot::savePostcardDone(true, mSnapshotIndex); } - /*virtual*/ void uploadFailure(const LLSD& content) + void uploadFailure(const LLSD& content) override final { LLAssetUploadResponder::uploadFailure(content); LLFloaterSnapshot::savePostcardDone(false, mSnapshotIndex); } - /*virtual*/ void httpFailure(void) + void httpFailure(void) override final { LLAssetUploadResponder::httpFailure(); LLFloaterSnapshot::savePostcardDone(false, mSnapshotIndex); } - /*virtual*/ char const* getName(void) const { return "LLSendPostcardResponder"; } + char const* getName(void) const override final { return "LLSendPostcardResponder"; } }; // static @@ -273,7 +269,6 @@ void LLFloaterPostcard::onClickSend(void* data) { LLFloaterPostcard *self = (LLFloaterPostcard *)data; - std::string from(self->childGetValue("from_form").asString()); std::string to(self->childGetValue("to_form").asString()); boost::regex emailFormat("[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}(,[ \t]*[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})*"); @@ -284,12 +279,6 @@ void LLFloaterPostcard::onClickSend(void* data) return; } - if (from.empty() || !boost::regex_match(from, emailFormat)) - { - LLNotificationsUtil::add("PromptSelfEmail"); - return; - } - std::string subject(self->childGetValue("subject_form").asString()); if(subject.empty() || !self->mHasFirstMsgFocus) { @@ -349,10 +338,8 @@ void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data, // static void LLFloaterPostcard::updateUserInfo(const std::string& email) { - for (instance_list_t::iterator iter = sInstances.begin(); - iter != sInstances.end(); ++iter) + for (auto& instance : sInstances) { - LLFloaterPostcard *instance = *iter; const std::string& text = instance->childGetValue("from_form").asString(); if (text.empty()) { @@ -416,7 +403,6 @@ void LLFloaterPostcard::sendPostcard() // the capability already encodes: agent ID, region ID body["pos-global"] = mPosTakenGlobal.getValue(); body["to"] = childGetValue("to_form").asString(); - body["from"] = childGetValue("from_form").asString(); body["name"] = childGetValue("name_form").asString(); body["subject"] = childGetValue("subject_form").asString(); body["msg"] = childGetValue("msg_form").asString(); diff --git a/indra/newview/llfloaterpostcard.h b/indra/newview/llfloaterpostcard.h index e40479c171..2ae0f2fa92 100644 --- a/indra/newview/llfloaterpostcard.h +++ b/indra/newview/llfloaterpostcard.h @@ -46,17 +46,17 @@ class LLLineEditor; class LLButton; class LLImageJPEG; -class LLFloaterPostcard +class LLFloaterPostcard final : public LLFloater { public: LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global, int index); - /*virtual*/ ~LLFloaterPostcard(); + /*virtual*/ ~LLFloaterPostcard() override; - /*virtual*/ void init(); - /*virtual*/ BOOL postBuild(); - /*virtual*/ void draw(); - /*virtual*/ void onClose(bool app_quitting); + void init(); + /*virtual*/ BOOL postBuild() override; + /*virtual*/ void draw() override; + /*virtual*/ void onClose(bool app_quitting) override; static LLFloaterPostcard* showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global, int index); diff --git a/indra/newview/llfloaterpostprocess.cpp b/indra/newview/llfloaterpostprocess.cpp index 22a89e0152..f7626f333e 100644 --- a/indra/newview/llfloaterpostprocess.cpp +++ b/indra/newview/llfloaterpostprocess.cpp @@ -43,16 +43,11 @@ #include "llcombobox.h" #include "lllineeditor.h" #include "llviewerwindow.h" -#if LL_MSVC -// disable boost::lexical_cast warning -#pragma warning (disable:4702) -#endif -#include LLFloaterPostProcess* LLFloaterPostProcess::sPostProcess = NULL; -LLFloaterPostProcess::LLFloaterPostProcess() : LLFloater(std::string("Post-Process Floater")) +LLFloaterPostProcess::LLFloaterPostProcess(const LLSD&) : LLFloater("Post-Process Floater") { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_post_process.xml"); @@ -91,24 +86,11 @@ LLFloaterPostProcess::LLFloaterPostProcess() : LLFloater(std::string("Post-Proce getChild("PPSaveEffect")->setCommitCallback(boost::bind(&LLFloaterPostProcess::onSaveEffect, this, editBox)); syncMenu(); + LLPostProcess::instance().setSelectedEffectChangeCallback(boost::bind(&LLFloaterPostProcess::syncMenu, this)); } LLFloaterPostProcess::~LLFloaterPostProcess() { - - -} - -LLFloaterPostProcess* LLFloaterPostProcess::instance() -{ - // if we don't have our singleton instance, create it - if (!sPostProcess) - { - sPostProcess = new LLFloaterPostProcess(); - sPostProcess->open(); - sPostProcess->setFocus(TRUE); - } - return sPostProcess; } @@ -122,8 +104,6 @@ void LLFloaterPostProcess::onLoadEffect(LLComboBox* comboBox) LLSD::String effectName(comboBox->getSelectedValue().asString()); LLPostProcess::getInstance()->setSelectedEffect(effectName); - - syncMenu(); } void LLFloaterPostProcess::onSaveEffect(LLLineEditor* editBox) @@ -139,7 +119,6 @@ void LLFloaterPostProcess::onSaveEffect(LLLineEditor* editBox) else { LLPostProcess::getInstance()->saveEffectAs(effectName); - syncMenu(); } } @@ -161,48 +140,40 @@ bool LLFloaterPostProcess::saveAlertCallback(const LLSD& notification, const LLS if (option == 0) { LLPostProcess::getInstance()->saveEffectAs(notification["payload"]["effect_name"].asString()); - - syncMenu(); } return false; } -void LLFloaterPostProcess::show() -{ - // get the instance, make sure the values are synced - // and open the menu - LLFloaterPostProcess* postProcess = instance(); - postProcess->syncMenu(); - postProcess->open(); -} - // virtual void LLFloaterPostProcess::onClose(bool app_quitting) { // just set visibility to false, don't get fancy yet - if (sPostProcess) - { - sPostProcess->setVisible(FALSE); - } + if (app_quitting) + die(); + else + setVisible(FALSE); } -void LLFloaterPostProcess::syncMenu() +void populatePostProcessList(LLComboBox* comboBox) { - // add the combo boxe contents - LLComboBox* comboBox = getChild("PPEffectsCombo"); - comboBox->removeall(); - LLSD::map_const_iterator currEffect; - for(currEffect = LLPostProcess::getInstance()->getAllEffectInfo().beginMap(); - currEffect != LLPostProcess::getInstance()->getAllEffectInfo().endMap(); + const auto& inst(LLPostProcess::instance()); + for(auto currEffect = inst.getAllEffectInfo().beginMap(), end = inst.getAllEffectInfo().endMap(); + currEffect != end; ++currEffect) { comboBox->add(currEffect->first); } // set the current effect as selected. - comboBox->selectByValue(LLPostProcess::getInstance()->getSelectedEffectName()); + comboBox->selectByValue(inst.getSelectedEffectName()); +} + +void LLFloaterPostProcess::syncMenu() +{ + // add the combo boxe contents + populatePostProcessList(getChild("PPEffectsCombo")); const LLSD &tweaks = LLPostProcess::getInstance()->getSelectedEffectInfo(); //Iterate down all uniforms handled by post-process shaders. Update any linked ui elements. @@ -214,7 +185,7 @@ void LLFloaterPostProcess::syncMenu() //llsd["uniform"][1]=>"uniform[1]" for(S32 i=0;isecond.size();++i) { - childSetValue(it->first+"["+boost::lexical_cast(i)+"]",it->second[i]); + childSetValue(it->first+'['+fmt::to_string(i)+']',it->second[i]); } } else diff --git a/indra/newview/llfloaterpostprocess.h b/indra/newview/llfloaterpostprocess.h index f49a339819..e2ffbf86e8 100644 --- a/indra/newview/llfloaterpostprocess.h +++ b/indra/newview/llfloaterpostprocess.h @@ -49,16 +49,13 @@ class LLPanelFace; /** * Menu for adjusting the post process settings of the world */ -class LLFloaterPostProcess : public LLFloater +class LLFloaterPostProcess : public LLFloater, public LLFloaterSingleton { public: - LLFloaterPostProcess(); + LLFloaterPostProcess(const LLSD&); virtual ~LLFloaterPostProcess(); - /// one and one instance only - static LLFloaterPostProcess* instance(); - /// post process callbacks static void onControlChanged(LLUICtrl* ctrl, const LLSD& v); void onLoadEffect(LLComboBox* comboBox); @@ -68,18 +65,12 @@ class LLFloaterPostProcess : public LLFloater /// prompts a user when overwriting an effect bool saveAlertCallback(const LLSD& notification, const LLSD& response); - /// show off our menu - static void show(); - /// stuff to do on exit virtual void onClose(bool app_quitting); /// sync up sliders void syncMenu(); -/* - void refresh(); -*/ public: static LLFloaterPostProcess* sPostProcess; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 95f92c1c63..680fa258ec 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -333,9 +333,9 @@ void LLPreferenceCore::onTabChanged(LLUICtrl* ctrl) } -void LLPreferenceCore::setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email) +void LLPreferenceCore::setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email, bool is_verified) { - mPrefsIM->setPersonalInfo(visibility, im_via_email, email); + mPrefsIM->setPersonalInfo(visibility, im_via_email, email, is_verified); } ////////////////////////////////////////////// @@ -408,15 +408,7 @@ void LLFloaterPreference::show(void*) sInstance->open(); /* Flawfinder: ignore */ - if(!gAgent.getID().isNull()) - { - // we're logged in, so we can get this info. - gMessageSystem->newMessageFast(_PREHASH_UserInfoRequest); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gAgent.sendReliableMessage(); - } + gAgent.sendAgentUserInfoRequest(); LLPanelLogin::setAlwaysRefresh(true); } @@ -441,6 +433,8 @@ void LLFloaterPreference::onBtnOK() close(false); gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); + if (gAgentID.notNull()) + gSavedPerAccountSettings.saveToFile( gSavedSettings.getString("PerAccountSettingsFile"), TRUE ); } else { @@ -494,11 +488,11 @@ void LLFloaterPreference::onBtnCancel() // static -void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email) +void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email, bool is_verified) { - if(sInstance && sInstance->mPreferenceCore) + if (sInstance && sInstance->mPreferenceCore) { - sInstance->mPreferenceCore->setPersonalInfo(visibility, im_via_email, email); + sInstance->mPreferenceCore->setPersonalInfo(visibility, im_via_email, email, is_verified); } } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index e16f40cb68..4ee0053f2e 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -73,7 +73,7 @@ class LLPreferenceCore LLTabContainer* getTabContainer() { return mTabContainer; } - void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email); + void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email, bool is_verified); static void onTabChanged(LLUICtrl* ctrl); @@ -109,7 +109,7 @@ class LLFloaterPreference : public LLFloater static void show(void*); // static data update, called from message handler - static void updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email); + static void updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email, bool is_verified = false); static void switchTab(S32 i); diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp index 2f80d004d0..2dac6344f4 100644 --- a/indra/newview/llfloaterproperties.cpp +++ b/indra/newview/llfloaterproperties.cpp @@ -44,6 +44,8 @@ #include "llavataractions.h" #include "llbutton.h" #include "llcheckboxctrl.h" +#include "llcororesponder.h" +#include "llexperiencecache.h" #include "llgroupactions.h" #include "llinventorymodel.h" #include "llinventoryobserver.h" @@ -51,8 +53,8 @@ #include "llradiogroup.h" #include "llresmgr.h" #include "roles_constants.h" +#include "llnamebox.h" #include "llselectmgr.h" -#include "lltextbox.h" #include "lltrans.h" #include "llviewerinventory.h" #include "llviewerobjectlist.h" @@ -64,11 +66,6 @@ #include "lfsimfeaturehandler.h" #include "hippogridmanager.h" - -// [RLVa:KB] -#include "rlvhandler.h" -// [/RLVa:KB] - bool can_set_export(const U32& base, const U32& own, const U32& next); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -81,7 +78,7 @@ bool can_set_export(const U32& base, const U32& own, const U32& next); // from the inventory observer list when destroyed, which could // happen after gInventory has already been destroyed if a singleton. // Instead, do our own ref counting and create / destroy it as needed -class LLPropertiesObserver : public LLInventoryObserver +class LLPropertiesObserver final : public LLInventoryObserver { public: LLPropertiesObserver(LLFloaterProperties* floater) @@ -93,9 +90,10 @@ class LLPropertiesObserver : public LLInventoryObserver { gInventory.removeObserver(this); } - virtual void changed(U32 mask); + + void changed(U32 mask) override; private: - LLFloaterProperties* mFloater; + LLFloaterProperties* mFloater; // Not a handle because LLFloaterProperties is managing LLPropertiesObserver }; void LLPropertiesObserver::changed(U32 mask) @@ -154,7 +152,7 @@ LLFloaterProperties::LLFloaterProperties(const std::string& name, const LLRect& LLFloaterProperties::~LLFloaterProperties() { delete mPropertiesObserver; - mPropertiesObserver = NULL; + mPropertiesObserver = nullptr; } // virtual @@ -168,12 +166,6 @@ BOOL LLFloaterProperties::postBuild() getChild("LabelItemName")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitName,this)); getChild("LabelItemDesc")->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe); getChild("LabelItemDesc")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitDescription,this)); - // Creator information - getChild("BtnCreator")->setCommitCallback(boost::bind(&LLFloaterProperties::onClickCreator,this)); - // owner information - getChild("BtnOwner")->setCommitCallback(boost::bind(&LLFloaterProperties::onClickOwner,this)); - // last owner information - getChild("BtnLastOwner")->setCommitCallback(boost::bind(&LLFloaterProperties::onClickLastOwner,this)); // acquired date // owner permissions // Permissions debug text @@ -222,15 +214,12 @@ void LLFloaterProperties::refresh() mDirty = TRUE; - const char* enableNames[]={ + static constexpr std::array enableNames{{ "LabelItemName", "LabelItemDesc", "LabelCreatorName", - "BtnCreator", "LabelOwnerName", - "BtnOwner", "LabelLastOwnerName", - "BtnLastOwner", "CheckOwnerModify", "CheckOwnerCopy", "CheckOwnerTransfer", @@ -247,21 +236,21 @@ void LLFloaterProperties::refresh() "CheckPurchase", "RadioSaleType", "Edit Cost" - }; - for(size_t t=0; tsetEnabled(false); + getChildView(name)->setEnabled(false); } - const char* hideNames[]={ + static constexpr std::array hideNames{{ "BaseMaskDebug", "OwnerMaskDebug", "GroupMaskDebug", "EveryoneMaskDebug", "NextMaskDebug" - }; - for(size_t t=0; tsetVisible(false); + getChildView(name)->setVisible(false); } } } @@ -299,7 +288,7 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) // You need permission to modify the object to modify an inventory // item in it. - LLViewerObject* object = NULL; + LLViewerObject* object = nullptr; if(!mObjectID.isNull()) object = gObjectList.findObject(mObjectID); BOOL is_obj_modify = TRUE; if(object) @@ -307,6 +296,24 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) is_obj_modify = object->permOwnerModify(); } + if (item->getInventoryType() == LLInventoryType::IT_LSL) + { + getChildView("LabelItemExperienceTitle")->setVisible(TRUE); + LLTextBox* tb = getChild("LabelItemExperience"); + if (tb->getValue().asUUID().isNull()) + { + tb->setText(getString("loading_experience")); + tb->setVisible(TRUE); + } + std::string url = std::string(); + if(object && object->getRegion()) + { + url = object->getRegion()->getCapability("GetMetadata"); + } + LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), url, + boost::bind(&LLFloaterProperties::setAssociatedExperience, getDerivedHandle(), _1)); + } + ////////////////////// // ITEM NAME & DESC // ////////////////////// @@ -328,72 +335,46 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) if(!gCacheName) return; if(!gAgent.getRegion()) return; + getChild("LabelCreatorName")->setValue(item->getCreatorUUID()); if (item->getCreatorUUID().notNull()) { - std::string name; - gCacheName->getFullName(item->getCreatorUUID(), name); - getChildView("BtnCreator")->setEnabled(TRUE); getChildView("LabelCreatorTitle")->setEnabled(TRUE); getChildView("LabelCreatorName")->setEnabled(TRUE); - getChild("LabelCreatorName")->setValue(name); } else { - getChildView("BtnCreator")->setEnabled(FALSE); getChildView("LabelCreatorTitle")->setEnabled(FALSE); getChildView("LabelCreatorName")->setEnabled(FALSE); - getChild("LabelCreatorName")->setValue(getString("unknown")); + getChild("LabelCreatorName")->setText(getString("unknown")); } + getChild("LabelLastOwnerName")->setValue(perm.getLastOwner()); if (perm.getLastOwner().notNull()) { - std::string name; - gCacheName->getFullName(perm.getLastOwner(), name); getChildView("LabelLastOwnerTitle")->setEnabled(true); getChildView("LabelLastOwnerName")->setEnabled(true); - getChild("LabelLastOwnerName")->setValue(name); } else { getChildView("LabelLastOwnerTitle")->setEnabled(false); getChildView("LabelLastOwnerName")->setEnabled(false); - getChild("LabelLastOwnerName")->setValue(getString("unknown")); + getChild("LabelLastOwnerName")->setText(getString("unknown")); } //////////////// // OWNER NAME // //////////////// + getChild("LabelOwnerName")->setValue(perm.getOwner()); if(perm.isOwned()) { - std::string name; - if (perm.isGroupOwned()) - { - gCacheName->getGroupName(perm.getGroup(), name); - } - else - { - gCacheName->getFullName(perm.getOwner(), name); -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) - { - name = RlvStrings::getAnonym(name); - } -// [/RLVa:KB] - } - getChildView("BtnOwner")->setEnabled(TRUE); -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-1.0.0e - getChildView("BtnOwner")->setEnabled(!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)); -// [/RLVa:KB] getChildView("LabelOwnerTitle")->setEnabled(TRUE); getChildView("LabelOwnerName")->setEnabled(TRUE); - getChild("LabelOwnerName")->setValue(name); } else { - getChildView("BtnOwner")->setEnabled(FALSE); getChildView("LabelOwnerTitle")->setEnabled(FALSE); getChildView("LabelOwnerName")->setEnabled(FALSE); - getChild("LabelOwnerName")->setValue(getString("public")); + getChild("LabelOwnerName")->setText(getString("public")); } ////////////////// @@ -438,11 +419,11 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) getChild("CheckOwnerCopy")->setValue(LLSD((BOOL)(owner_mask & PERM_COPY))); getChildView("CheckOwnerTransfer")->setEnabled(FALSE); getChild("CheckOwnerTransfer")->setValue(LLSD((BOOL)(owner_mask & PERM_TRANSFER))); + getChildView("CheckOwnerExport")->setEnabled(FALSE); + getChild("CheckOwnerExport")->setValue(LLSD((BOOL)(owner_mask & PERM_EXPORT))); bool supports_export = LFSimFeatureHandler::instance().simSupportsExport(); - getChildView("CheckOwnerExport")->setEnabled(false); - getChild("CheckOwnerExport")->setValue(LLSD((BOOL)(supports_export && owner_mask & PERM_EXPORT))); - if (!gHippoGridManager->getCurrentGrid()->isSecondLife()) + if (!supports_export) getChildView("CheckOwnerExport")->setVisible(false); /////////////////////// @@ -555,6 +536,9 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) const LLSaleInfo& sale_info = item->getSaleInfo(); BOOL is_for_sale = sale_info.isForSale(); + LLRadioGroup* radioSaleType = getChild("RadioSaleType"); + LLUICtrl* edit_cost = getChild("Edit Cost"); + // Check for ability to change values. if (is_obj_modify && can_agent_sell && gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE)) @@ -568,9 +552,9 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) getChildView("CheckNextOwnerCopy")->setEnabled(no_export && (base_mask & PERM_COPY) && !cannot_restrict_permissions); getChildView("CheckNextOwnerTransfer")->setEnabled(no_export && (next_owner_mask & PERM_COPY) && !cannot_restrict_permissions); - getChildView("RadioSaleType")->setEnabled(is_complete && is_for_sale); + radioSaleType->setEnabled(is_complete && is_for_sale); getChildView("TextPrice")->setEnabled(is_complete && is_for_sale); - getChildView("Edit Cost")->setEnabled(is_complete && is_for_sale); + edit_cost->setEnabled(is_complete && is_for_sale); } else { @@ -582,65 +566,54 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) getChildView("CheckNextOwnerCopy")->setEnabled(FALSE); getChildView("CheckNextOwnerTransfer")->setEnabled(FALSE); - getChildView("RadioSaleType")->setEnabled(FALSE); + radioSaleType->setEnabled(FALSE); getChildView("TextPrice")->setEnabled(FALSE); - getChildView("Edit Cost")->setEnabled(FALSE); + edit_cost->setEnabled(FALSE); } // Set values. getChild("CheckPurchase")->setValue(is_for_sale); - getChildView("Edit Cost")->setEnabled(is_for_sale); + edit_cost->setEnabled(is_for_sale); getChild("CheckNextOwnerModify")->setValue(LLSD(BOOL(next_owner_mask & PERM_MODIFY))); getChild("CheckNextOwnerCopy")->setValue(LLSD(BOOL(next_owner_mask & PERM_COPY))); getChild("CheckNextOwnerTransfer")->setValue(LLSD(BOOL(next_owner_mask & PERM_TRANSFER))); - LLRadioGroup* radioSaleType = getChild("RadioSaleType"); if (is_for_sale) { - radioSaleType->setSelectedIndex((S32)sale_info.getSaleType() - 1); S32 numerical_price; numerical_price = sale_info.getSalePrice(); - getChild("Edit Cost")->setValue(llformat("%d",numerical_price)); + edit_cost->setValue(llformat("%d",numerical_price)); + radioSaleType->setSelectedIndex((S32)sale_info.getSaleType() - 1); } else { + edit_cost->setValue("0"); radioSaleType->setSelectedIndex(-1); - getChild("Edit Cost")->setValue(llformat("%d",0)); } } -void LLFloaterProperties::onClickCreator() -{ - LLInventoryItem* item = findItem(); - if(!item) return; - LLAvatarActions::showProfile(item->getCreatorUUID()); -} -// static -void LLFloaterProperties::onClickOwner() +void LLFloaterProperties::setAssociatedExperience(LLHandle hInfo, const LLSD& experience) { - LLInventoryItem* item = findItem(); - if(!item) return; - if(item->getPermissions().isGroupOwned()) - { - LLGroupActions::show(item->getPermissions().getGroup()); - } - else + LLFloaterProperties* info = hInfo.get(); + if (info && experience.has(LLExperienceCache::EXPERIENCE_ID)) { -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) - if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) -// [/RLVa:KB] + auto id = experience[LLExperienceCache::EXPERIENCE_ID].asUUID(); + if (id.notNull()) { - LLAvatarActions::showProfile(item->getPermissions().getOwner()); + //info->getChild("LabelItemExperience")->setText(LLSLURL("experience", id, "profile").getSLURLString(); + if (LLNameBox* tb = info->getChild("LabelItemExperience")) + { + tb->setValue(id); + } + } + else + { + info->getChild("LabelItemExperience")->setText(LLTrans::getString("ExperienceNameNull")); } } } -void LLFloaterProperties::onClickLastOwner() -{ - if (const LLInventoryItem* item = findItem()) LLAvatarActions::showProfile(item->getPermissions().getLastOwner()); -} - // static void LLFloaterProperties::onCommitName() { @@ -754,11 +727,6 @@ void LLFloaterProperties::onCommitPermissions() perm.setEveryoneBits(gAgent.getID(), gAgent.getGroupID(), CheckEveryoneCopy->get(), PERM_COPY); } - LLCheckBoxCtrl* CheckExport = getChild("CheckExport"); - if(CheckExport) - { - perm.setEveryoneBits(gAgent.getID(), gAgent.getGroupID(), CheckExport->get(), PERM_EXPORT); - } LLCheckBoxCtrl* CheckNextOwnerModify = getChild("CheckNextOwnerModify"); if(CheckNextOwnerModify) @@ -778,6 +746,13 @@ void LLFloaterProperties::onCommitPermissions() perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(), CheckNextOwnerTransfer->get(), PERM_TRANSFER); } + + LLCheckBoxCtrl* CheckExport = getChild("CheckExport"); + if(CheckExport && CheckExport->getVisible()) + { + perm.setEveryoneBits(gAgent.getID(), gAgent.getGroupID(), CheckExport->get(), PERM_EXPORT); + } + if(perm != item->getPermissions() && item->isFinished()) { @@ -951,7 +926,7 @@ void LLFloaterProperties::updateSaleInfo() LLInventoryItem* LLFloaterProperties::findItem() const { - LLInventoryItem* item = NULL; + LLInventoryItem* item = nullptr; if(mObjectID.isNull()) { // it is in agent inventory diff --git a/indra/newview/llfloaterproperties.h b/indra/newview/llfloaterproperties.h index d2640f07d3..547040e6b1 100644 --- a/indra/newview/llfloaterproperties.h +++ b/indra/newview/llfloaterproperties.h @@ -74,9 +74,6 @@ class LLFloaterProperties : public LLFloater, public LLInstanceTracker hInfo, const LLSD& experience); + protected: // The item id of the inventory item in question. LLUUID mItemID; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 6f1cb5e77d..e4d775491c 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -3,31 +3,25 @@ * @author Aaron Brashears * @brief Implementation of the region info and controls floater and panels. * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -53,6 +47,7 @@ #include "llfloateravatarpicker.h" #include "llbutton.h" #include "llcheckboxctrl.h" +#include "llclipboard.h" #include "llcombobox.h" #include "lldaycyclemanager.h" #include "llenvmanager.h" @@ -64,6 +59,7 @@ #include "llfloaterregiondebugconsole.h" #include "llfloatertelehub.h" #include "llinventorymodel.h" +#include "lllayoutstack.h" #include "lllineeditor.h" #include "llnamelistctrl.h" #include "llnotifications.h" @@ -87,6 +83,11 @@ #include "llvlcomposition.h" #include "llwaterparammanager.h" #include "llagentui.h" +#include "llpanelexperiencelisteditor.h" +#include +#include "llpanelexperiencepicker.h" +#include "llexperiencecache.h" +#include "llpanelexperiences.h" #include "hippogridmanager.h" // [RLVa:KB] #include "rlvhandler.h" @@ -95,32 +96,46 @@ const S32 TERRAIN_TEXTURE_COUNT = 4; const S32 CORNER_COUNT = 4; +const U32 MAX_LISTED_NAMES = 100; + ///---------------------------------------------------------------------------- /// Local class declaration ///---------------------------------------------------------------------------- -class LLDispatchEstateUpdateInfo : public LLDispatchHandler +class LLDispatchEstateUpdateInfo final : public LLDispatchHandler { public: LLDispatchEstateUpdateInfo() {} virtual ~LLDispatchEstateUpdateInfo() {} - virtual bool operator()( + bool operator()( const LLDispatcher* dispatcher, const std::string& key, const LLUUID& invoice, - const sparam_t& strings); + const sparam_t& strings) override; }; -class LLDispatchSetEstateAccess : public LLDispatchHandler +class LLDispatchSetEstateAccess final : public LLDispatchHandler { public: LLDispatchSetEstateAccess() {} virtual ~LLDispatchSetEstateAccess() {} - virtual bool operator()( + bool operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) override; +}; + +class LLDispatchSetEstateExperience final : public LLDispatchHandler +{ +public: + bool operator()( const LLDispatcher* dispatcher, const std::string& key, const LLUUID& invoice, - const sparam_t& strings); + const sparam_t& strings) override; + + LLSD getIDs(sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count); }; @@ -204,6 +219,9 @@ LLUUID LLFloaterRegionInfo::sRequestInvoice; LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed) + : LLFloater() + , mTab(nullptr) + , mInfoPanels() { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_region_info.xml", NULL, FALSE); } @@ -220,6 +238,11 @@ BOOL LLFloaterRegionInfo::postBuild() LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_estate.xml"); mTab->addTabPanel(panel, panel->getLabel(), FALSE); + panel = new LLPanelEstateAccess; + mInfoPanels.push_back(panel); + LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_access.xml"); + mTab->addTabPanel(panel, panel->getLabel(), FALSE); + panel = new LLPanelEstateCovenant; mInfoPanels.push_back(panel); LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_covenant.xml"); @@ -245,6 +268,18 @@ BOOL LLFloaterRegionInfo::postBuild() LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_debug.xml"); mTab->addTabPanel(panel, panel->getLabel(), FALSE); + if(gDisconnected) + { + return TRUE; + } + + if (!gAgent.getRegion()->getCapability("RegionExperiences").empty()) + { + panel = new LLPanelRegionExperiences; + mInfoPanels.push_back(panel); + mTab->addTabPanel(panel, panel->getLabel(), FALSE); + } + gMessageSystem->setHandlerFunc( "EstateOwnerMessage", &processEstateOwnerRequest); @@ -268,9 +303,24 @@ void LLFloaterRegionInfo::onOpen() refreshFromRegion(gAgent.getRegion()); requestRegionInfo(); requestMeshRezInfo(); + + if (!mGodLevelChangeSlot.connected()) + { + mGodLevelChangeSlot = gAgent.registerGodLevelChanageListener(boost::bind(&LLFloaterRegionInfo::onGodLevelChange, this, _1)); + } + LLFloater::onOpen(); } +void LLFloaterRegionInfo::onClose(bool app_quitting) +{ + if (mGodLevelChangeSlot.connected()) + { + mGodLevelChangeSlot.disconnect(); + } + LLFloater::onClose(app_quitting); +} + // static void LLFloaterRegionInfo::requestRegionInfo() { @@ -280,6 +330,9 @@ void LLFloaterRegionInfo::requestRegionInfo() tab->getChild("Debug")->setCtrlsEnabled(FALSE); tab->getChild("Terrain")->setCtrlsEnabled(FALSE); tab->getChild("Estate")->setCtrlsEnabled(FALSE); + auto panel = tab->getChild("Access"); + panel->setCtrlsEnabled(FALSE); + panel->getChildView("tabs")->setEnabled(true); // Must allow anyone to request the RegionInfo data // so non-owners/non-gods can see the values. @@ -307,8 +360,7 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**) LLPanelEstateInfo::initDispatch(dispatch); } - LLTabContainer* tab = floater->getChild("region_panels"); - LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild("Estate"); + LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); // unpack the message std::string request; @@ -324,7 +376,10 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**) //dispatch the message dispatch.dispatch(request, invoice, strings); - panel->updateControls(gAgent.getRegion()); + if (panel) + { + panel->updateControls(gAgent.getRegion()); + } } @@ -457,18 +512,28 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) LLPanelEstateInfo* LLFloaterRegionInfo::getPanelEstate() { LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance(); - if (!floater) return NULL; + if (!floater) return nullptr; LLTabContainer* tab = floater->getChild("region_panels"); LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild("Estate"); return panel; } // static -LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant() +LLPanelEstateAccess* LLFloaterRegionInfo::getPanelAccess() { LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance(); if (!floater) return NULL; LLTabContainer* tab = floater->getChild("region_panels"); + LLPanelEstateAccess* panel = (LLPanelEstateAccess*)tab->getChild("Access"); + return panel; +} + +// static +LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant() +{ + LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance(); + if (!floater) return nullptr; + LLTabContainer* tab = floater->getChild("region_panels"); LLPanelEstateCovenant* panel = (LLPanelEstateCovenant*)tab->getChild("Covenant"); return panel; } @@ -480,7 +545,7 @@ LLPanelRegionTerrainInfo* LLFloaterRegionInfo::getPanelRegionTerrain() if (!floater) { llassert(floater); - return NULL; + return nullptr; } LLTabContainer* tab_container = floater->getChild("region_panels"); @@ -490,6 +555,14 @@ LLPanelRegionTerrainInfo* LLFloaterRegionInfo::getPanelRegionTerrain() return panel; } +LLPanelRegionExperiences* LLFloaterRegionInfo::getPanelExperiences() +{ + LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance(); + if (!floater) return nullptr; + LLTabContainer* tab = floater->getChild("region_panels"); + return (LLPanelRegionExperiences*)tab->getChild("Experiences"); +} + void LLFloaterRegionInfo::onTabSelected(const LLSD& param) { LLPanelRegionInfo* active_panel = getChild(param.asString()); @@ -508,11 +581,7 @@ void LLFloaterRegionInfo::refreshFromRegion(LLViewerRegion* region) mInfoPanels.begin(), mInfoPanels.end(), llbind2nd( -#if LL_WINDOWS - std::mem_fun1(&LLPanelRegionInfo::refreshFromRegion), -#else std::mem_fun(&LLPanelRegionInfo::refreshFromRegion), -#endif region)); } @@ -526,6 +595,14 @@ void LLFloaterRegionInfo::refresh() } } +void LLFloaterRegionInfo::onGodLevelChange(U8 god_level) +{ + LLFloaterRegionInfo* floater = getInstance(); + if (floater && floater->getVisible()) + { + refreshFromRegion(gAgent.getRegion()); + } +} ///---------------------------------------------------------------------------- /// Local class implementation @@ -617,7 +694,7 @@ void LLPanelRegionInfo::sendEstateOwnerMessage( if(strings.empty()) { msg->nextBlock("ParamList"); - msg->addString("Parameter", NULL); + msg->addString("Parameter", nullptr); } else { @@ -1485,10 +1562,6 @@ void LLPanelEstateInfo::initDispatch(LLDispatcher& dispatch) { std::string name; -// name.assign("setowner"); -// static LLDispatchSetEstateOwner set_owner; -// dispatch.addHandler(name, &set_owner); - name.assign("estateupdateinfo"); static LLDispatchEstateUpdateInfo estate_update_info; dispatch.addHandler(name, &estate_update_info); @@ -1497,125 +1570,12 @@ void LLPanelEstateInfo::initDispatch(LLDispatcher& dispatch) static LLDispatchSetEstateAccess set_access; dispatch.addHandler(name, &set_access); - estate_dispatch_initialized = true; -} - -//--------------------------------------------------------------------------- -// Add/Remove estate access button callbacks -//--------------------------------------------------------------------------- -void LLPanelEstateInfo::onClickAddAllowedAgent() -{ - LLCtrlListInterface *list = childGetListInterface("allowed_avatar_name_list"); - if (!list) return; - if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS) - { - //args - - LLSD args; - args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); - LLNotificationsUtil::add("MaxAllowedAgentOnRegion", args); - return; - } - accessAddCore(ESTATE_ACCESS_ALLOWED_AGENT_ADD, "EstateAllowedAgentAdd"); -} - -void LLPanelEstateInfo::onClickRemoveAllowedAgent() -{ - accessRemoveCore(ESTATE_ACCESS_ALLOWED_AGENT_REMOVE, "EstateAllowedAgentRemove", "allowed_avatar_name_list"); -} - -void LLPanelEstateInfo::onClickAddAllowedGroup() -{ - LLCtrlListInterface *list = childGetListInterface("allowed_group_name_list"); - if (!list) return; - if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS) - { - LLSD args; - args["MAX_GROUPS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); - LLNotificationsUtil::add("MaxAllowedGroupsOnRegion", args); - return; - } - - LLNotification::Params params("ChangeLindenAccess"); - params.functor(boost::bind(&LLPanelEstateInfo::addAllowedGroup, this, _1, _2)); - if (isLindenEstate()) - { - LLNotifications::instance().add(params); - } - else - { - LLNotifications::instance().forceResponse(params, 0); - } -} - -bool LLPanelEstateInfo::addAllowedGroup(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return false; - - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - - LLFloaterGroupPicker* widget = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID())); - if (widget) - { - widget->removeNoneOption(); - widget->setSelectGroupCallback(boost::bind(&LLPanelEstateInfo::addAllowedGroup2, this, _1)); - if (parent_floater) - { - LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, widget); - widget->setOrigin(new_rect.mLeft, new_rect.mBottom); - parent_floater->addDependentFloater(widget); - } - } - - return false; -} - -void LLPanelEstateInfo::onClickRemoveAllowedGroup() -{ - accessRemoveCore(ESTATE_ACCESS_ALLOWED_GROUP_REMOVE, "EstateAllowedGroupRemove", "allowed_group_name_list"); -} - -void LLPanelEstateInfo::onClickAddBannedAgent() -{ - LLCtrlListInterface *list = childGetListInterface("banned_avatar_name_list"); - if (!list) return; - if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS) - { - LLSD args; - args["MAX_BANNED"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); - LLNotificationsUtil::add("MaxBannedAgentsOnRegion", args); - return; - } - accessAddCore(ESTATE_ACCESS_BANNED_AGENT_ADD, "EstateBannedAgentAdd"); -} - -void LLPanelEstateInfo::onClickRemoveBannedAgent() -{ - accessRemoveCore(ESTATE_ACCESS_BANNED_AGENT_REMOVE, "EstateBannedAgentRemove", "banned_avatar_name_list"); -} -// static -void LLPanelEstateInfo::onClickAddEstateManager() -{ - LLCtrlListInterface *list = childGetListInterface("estate_manager_name_list"); - if (!list) return; - if (list->getItemCount() >= ESTATE_MAX_MANAGERS) - { // Tell user they can't add more managers - LLSD args; - args["MAX_MANAGER"] = llformat("%d",ESTATE_MAX_MANAGERS); - LLNotificationsUtil::add("MaxManagersOnRegion", args); - } - else - { // Go pick managers to add - accessAddCore(ESTATE_ACCESS_MANAGER_ADD, "EstateManagerAdd"); - } -} + name.assign("setexperience"); + static LLDispatchSetEstateExperience set_experience; + dispatch.addHandler(name, &set_experience); -// static -void LLPanelEstateInfo::onClickRemoveEstateManager() -{ - accessRemoveCore(ESTATE_ACCESS_MANAGER_REMOVE, "EstateManagerRemove", "estate_manager_name_list"); + estate_dispatch_initialized = true; } //--------------------------------------------------------------------------- @@ -1721,12 +1681,9 @@ struct LLEstateAccessChangeInfo { mDialogName = sd["dialog_name"].asString(); mOperationFlag = (U32)sd["operation"].asInteger(); - LLSD::array_const_iterator end_it = sd["allowed_ids"].endArray(); - for (LLSD::array_const_iterator id_it = sd["allowed_ids"].beginArray(); - id_it != end_it; - ++id_it) + for (auto const& id : sd["allowed_ids"].array()) { - mAgentOrGroupIDs.push_back(id_it->asUUID()); + mAgentOrGroupIDs.push_back(id.asUUID()); } } @@ -1735,11 +1692,13 @@ struct LLEstateAccessChangeInfo LLSD sd; sd["name"] = mDialogName; sd["operation"] = (S32)mOperationFlag; - for (uuid_vec_t::const_iterator it = mAgentOrGroupIDs.begin(); - it != mAgentOrGroupIDs.end(); - ++it) + for (U32 i = 0; i < mAgentOrGroupIDs.size(); ++i) { - sd["allowed_ids"].append(*it); + sd["allowed_ids"].append(mAgentOrGroupIDs[i]); + if (mAgentNames.size() > i) + { + sd["allowed_names"].append(mAgentNames[i].asLLSD()); + } } return sd; } @@ -1747,1881 +1706,2737 @@ struct LLEstateAccessChangeInfo U32 mOperationFlag; // ESTATE_ACCESS_BANNED_AGENT_ADD, _REMOVE, etc. std::string mDialogName; uuid_vec_t mAgentOrGroupIDs; // List of agent IDs to apply to this change + std::vector mAgentNames; // Optional list of the agent names for notifications }; -// Special case callback for groups, since it has different callback format than names -void LLPanelEstateInfo::addAllowedGroup2(LLUUID id) +// static +void LLPanelEstateInfo::updateEstateOwnerID(const LLUUID& id) { - LLSD payload; - payload["operation"] = (S32)ESTATE_ACCESS_ALLOWED_GROUP_ADD; - payload["dialog_name"] = "EstateAllowedGroupAdd"; - payload["allowed_ids"].append(id); - - LLSD args; - args["ALL_ESTATES"] = all_estates_text(); - - LLNotification::Params params("EstateAllowedGroupAdd"); - params.payload(payload) - .substitutions(args) - .functor(accessCoreConfirm); - if (isLindenEstate()) - { - LLNotifications::instance().forceResponse(params, 0); - } - else + LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate(); + if (panelp) { - LLNotifications::instance().add(params); + panelp->getChild("estate_owner")->setValue(id); } } // static -void LLPanelEstateInfo::accessAddCore(U32 operation_flag, const std::string& dialog_name) +void LLPanelEstateInfo::updateEstateName(const std::string& name) { - LLSD payload; - payload["operation"] = (S32)operation_flag; - payload["dialog_name"] = dialog_name; - // agent id filled in after avatar picker - - LLNotification::Params params("ChangeLindenAccess"); - params.payload(payload) - .functor(accessAddCore2); - - if (isLindenEstate()) - { - LLNotifications::instance().add(params); - } - else + LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate(); + if (panelp) { - // same as clicking "OK" - LLNotifications::instance().forceResponse(params, 0); + panelp->getChildRef("estate_name").setText(name); } } -// static -bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& response) +void LLPanelEstateInfo::updateControls(LLViewerRegion* region) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) - { - // abort change - return false; - } + BOOL god = gAgent.isGodlike(); + BOOL owner = (region && (region->getOwner() == gAgent.getID())); + BOOL manager = (region && region->isEstateManager()); + setCtrlsEnabled(god || owner || manager); - LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]); - // avatar picker yes multi-select, yes close-on-select - LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, change_info), TRUE, TRUE); - return false; + getChildView("message_estate_btn")->setEnabled(god || owner || manager); + getChildView("kick_user_from_estate_btn")->setEnabled(god || owner || manager); + + refresh(); } -// static -void LLPanelEstateInfo::accessAddCore3(const uuid_vec_t& ids, LLEstateAccessChangeInfo* change_info) +bool LLPanelEstateInfo::refreshFromRegion(LLViewerRegion* region) { - if (!change_info) return; - if (ids.empty()) - { - // User didn't select a name. - delete change_info; - change_info = NULL; - return; - } - // User did select a name. - change_info->mAgentOrGroupIDs = ids; - // Can't put estate owner on ban list - LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); - if (!panel) return; - LLViewerRegion* region = gAgent.getRegion(); - if (!region) return; + updateControls(region); - if (change_info->mOperationFlag & ESTATE_ACCESS_ALLOWED_AGENT_ADD) - { - LLCtrlListInterface *list = panel->childGetListInterface("allowed_avatar_name_list"); - int currentCount = (list ? list->getItemCount() : 0); - if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS) - { - LLSD args; - args["NUM_ADDED"] = llformat("%d",ids.size()); - args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); - args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents"); - args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS); - LLNotificationsUtil::add("MaxAgentOnRegionBatch", args); - delete change_info; - return; + // let the parent class handle the general data collection. + bool rv = LLPanelRegionInfo::refreshFromRegion(region); + + // We want estate info. To make sure it works across region + // boundaries and multiple packets, we add a serial number to the + // integers and track against that on update. + strings_t strings; + //integers_t integers; + //LLFloaterRegionInfo::incrementSerial(); + LLFloaterRegionInfo::nextInvoice(); + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + //integers.push_back(LLFloaterRegionInfo::());::getPanelEstate(); + + + sendEstateOwnerMessage(gMessageSystem, "getinfo", invoice, strings); + + refresh(); + + return rv; +} + +void LLPanelEstateInfo::updateChild(LLUICtrl* child_ctrl) +{ + // Ensure appropriate state of the management ui. + updateControls(gAgent.getRegion()); +} + +bool LLPanelEstateInfo::estateUpdate(LLMessageSystem* msg) +{ + LL_INFOS() << "LLPanelEstateInfo::estateUpdate()" << LL_ENDL; + return false; +} + + +BOOL LLPanelEstateInfo::postBuild() +{ + // set up the callbacks for the generic controls + initCtrl("externally_visible_check"); + initCtrl("allow_direct_teleport"); + initCtrl("limit_payment"); + initCtrl("limit_age_verified"); + initCtrl("voice_chat_check"); + initCtrl("use_global_time_check"); + initCtrl("fixed_sun_check"); + initCtrl("sun_hour_slider"); + initHelpBtn("use_global_time_help", "HelpEstateUseGlobalTime"); + initHelpBtn("fixed_sun_help", "HelpEstateFixedSun"); + initHelpBtn("externally_visible_help", "HelpEstateExternallyVisible"); + initHelpBtn("allow_direct_teleport_help", "HelpEstateAllowDirectTeleport"); + initHelpBtn("voice_chat_help", "HelpEstateVoiceChat"); + + // Set up the Legacy Estate Environment checkboxes + { + LLUICtrl* global_time = getChild("use_global_time_check"); + LLUICtrl* fixed_sun = getChild("fixed_sun_check"); + LLUICtrl* hour_slider = getChild("sun_hour_slider"); + global_time->setCommitCallback(boost::bind(on_change_use_other_sun, _2, fixed_sun, hour_slider)); + fixed_sun->setCommitCallback(boost::bind(on_change_fixed_sun, _2, global_time, hour_slider)); + } + + childSetAction("message_estate_btn", boost::bind(&LLPanelEstateInfo::onClickMessageEstate, this)); + childSetAction("kick_user_from_estate_btn", boost::bind(&LLPanelEstateInfo::onClickKickUser, this)); + + return LLPanelRegionInfo::postBuild(); +} + +void LLPanelEstateInfo::refresh() +{ + // Disable access restriction controls if they make no sense. + bool public_access = getChild("externally_visible_check")->getValue().asBoolean(); + + getChildView("Only Allow")->setEnabled(public_access); + getChildView("limit_payment")->setEnabled(public_access); + getChildView("limit_age_verified")->setEnabled(public_access); + + // if this is set to false, then the limit fields are meaningless and should be turned off + if (public_access == false) + { + getChild("limit_payment")->setValue(false); + getChild("limit_age_verified")->setValue(false); + } +} + +void LLPanelEstateInfo::refreshFromEstate() +{ + const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); + + getChild("estate_name")->setValue(estate_info.getName()); + getChild("estate_owner")->setValue(estate_info.getOwnerID()); + + getChild("externally_visible_check")->setValue(estate_info.getIsExternallyVisible()); + getChild("voice_chat_check")->setValue(estate_info.getAllowVoiceChat()); + getChild("allow_direct_teleport")->setValue(estate_info.getAllowDirectTeleport()); + getChild("limit_payment")->setValue(estate_info.getDenyAnonymous()); + getChild("limit_age_verified")->setValue(estate_info.getDenyAgeUnverified()); + + // Ensure appropriate state of the management UI + updateControls(gAgent.getRegion()); + // Support Legacy Estate Environment + { + const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); + bool global_time = estate_info.getGlobalTime(); + getChild("use_global_time_check")->setValue(global_time); + getChild("fixed_sun_check")->setEnabled(!global_time); + getChild("sun_hour_slider")->setEnabled(!global_time); + if (global_time) + { + getChild("use_global_time_check")->setEnabled(true); + getChild("fixed_sun_check")->setValue(false); + } + else + { + bool fixed_sun = estate_info.getUseFixedSun(); + getChild("use_global_time_check")->setEnabled(!fixed_sun); + getChild("fixed_sun_check")->setValue(fixed_sun); + F32 sun_hour = estate_info.getSunHour(); + if (sun_hour < 6.0f) sun_hour += 24.0f; + getChild("sun_hour_slider")->setValue(sun_hour); } } - if (change_info->mOperationFlag & ESTATE_ACCESS_BANNED_AGENT_ADD) + refresh(); +} + +BOOL LLPanelEstateInfo::sendUpdate() +{ + LL_INFOS() << "LLPanelEstateInfo::sendUpdate()" << LL_ENDL; + + LLNotification::Params params("ChangeLindenEstate"); + params.functor(boost::bind(&LLPanelEstateInfo::callbackChangeLindenEstate, this, _1, _2)); + + if (isLindenEstate()) { - LLCtrlListInterface *list = panel->childGetListInterface("banned_avatar_name_list"); - int currentCount = (list ? list->getItemCount() : 0); - if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS) + // trying to change reserved estate, warn + LLNotifications::instance().add(params); + } + else + { + // for normal estates, just make the change + LLNotifications::instance().forceResponse(params, 0); + } + return TRUE; +} + +bool LLPanelEstateInfo::callbackChangeLindenEstate(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch(option) + { + case 0: { - LLSD args; - args["NUM_ADDED"] = llformat("%d",ids.size()); - args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); - args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents"); - args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS); - LLNotificationsUtil::add("MaxAgentOnRegionBatch", args); - delete change_info; - return; + LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); + + // update model + estate_info.setIsExternallyVisible(getChild("externally_visible_check")->getValue().asBoolean()); + estate_info.setUseFixedSun(getChild("fixed_sun_check")->getValue().asBoolean()); + estate_info.setSunHour(get_sun_hour(getChild("sun_hour_slider"))); + estate_info.setAllowDirectTeleport(getChild("allow_direct_teleport")->getValue().asBoolean()); + estate_info.setDenyAnonymous(getChild("limit_payment")->getValue().asBoolean()); + estate_info.setDenyAgeUnverified(getChild("limit_age_verified")->getValue().asBoolean()); + estate_info.setAllowVoiceChat(getChild("voice_chat_check")->getValue().asBoolean()); + + // send the update to sim + estate_info.sendEstateInfo(); } + + // we don't want to do this because we'll get it automatically from the sim + // after the spaceserver processes it +// else +// { +// // caps method does not automatically send this info +// LLFloaterRegionInfo::requestRegionInfo(); +// } + break; + case 1: + default: + // do nothing + break; } + return false; +} - LLSD args; - args["ALL_ESTATES"] = all_estates_text(); - LLNotification::Params params(change_info->mDialogName); - params.substitutions(args) - .payload(change_info->asLLSD()) - .functor(accessCoreConfirm); +/* +// Request = "getowner" +// SParam[0] = "" (empty string) +// IParam[0] = serial +void LLPanelEstateInfo::getEstateOwner() +{ + // TODO -- disable the panel + // and call this function whenever we cross a region boundary + // re-enable when owner matches, and get new estate info + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_EstateOwnerRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + + msg->nextBlockFast(_PREHASH_RequestData); + msg->addStringFast(_PREHASH_Request, "getowner"); + + // we send an empty string so that the variable block is not empty + msg->nextBlockFast(_PREHASH_StringData); + msg->addStringFast(_PREHASH_SParam, ""); + + msg->nextBlockFast(_PREHASH_IntegerData); + msg->addS32Fast(_PREHASH_IParam, LLFloaterRegionInfo::getSerial()); + + gAgent.sendMessage(); +} +*/ + +const std::string LLPanelEstateInfo::getOwnerName() const +{ + return getChild("estate_owner")->getText(); +} + +// static +void LLPanelEstateInfo::onClickMessageEstate(void* userdata) +{ + LL_INFOS() << "LLPanelEstateInfo::onClickMessageEstate" << LL_ENDL; + LLNotificationsUtil::add("MessageEstate", LLSD(), LLSD(), boost::bind(&LLPanelEstateInfo::onMessageCommit, (LLPanelEstateInfo*)userdata, _1, _2)); +} + +bool LLPanelEstateInfo::onMessageCommit(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + std::string text = response["message"].asString(); + if(option != 0) return false; + if(text.empty()) return false; + LL_INFOS() << "Message to everyone: " << text << LL_ENDL; + strings_t strings; + //integers_t integers; + std::string name; + LLAgentUI::buildFullname(name); + strings.push_back(strings_t::value_type(name)); + strings.push_back(strings_t::value_type(text)); + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + sendEstateOwnerMessage(gMessageSystem, "instantmessage", invoice, strings); + return false; +} + +LLPanelEstateCovenant::LLPanelEstateCovenant() + : LLPanelRegionInfo() + , mEstateNameText(nullptr) + , mEstateOwnerText(nullptr) + , mLastModifiedText(nullptr) + , mCovenantID(LLUUID::null) + , mEditor(nullptr) + , mAssetStatus(ASSET_ERROR) +{ +} + +// virtual +bool LLPanelEstateCovenant::refreshFromRegion(LLViewerRegion* region) +{ + LLTextBox* region_name = getChild("region_name_text"); + if (region_name) + { + region_name->setText(region->getName()); + } + + LLTextBox* resellable_clause = getChild("resellable_clause"); + if (resellable_clause) + { + if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL)) + { + resellable_clause->setText(getString("can_not_resell")); + } + else + { + resellable_clause->setText(getString("can_resell")); + } + } + + LLTextBox* changeable_clause = getChild("changeable_clause"); + if (changeable_clause) + { + if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES)) + { + changeable_clause->setText(getString("can_change")); + } + else + { + changeable_clause->setText(getString("can_not_change")); + } + } + + LLTextBox* region_maturity = getChild("region_maturity_text"); + if (region_maturity) + { + region_maturity->setText(region->getSimAccessString()); + } + + LLTextBox* region_landtype = getChild("region_landtype_text"); + region_landtype->setText(region->getLocalizedSimProductName()); + + // let the parent class handle the general data collection. + bool rv = LLPanelRegionInfo::refreshFromRegion(region); + LLMessageSystem *msg = gMessageSystem; + msg->newMessage("EstateCovenantRequest"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); + msg->sendReliable(region->getHost()); + return rv; +} + +// virtual +bool LLPanelEstateCovenant::estateUpdate(LLMessageSystem* msg) +{ + LL_INFOS() << "LLPanelEstateCovenant::estateUpdate()" << LL_ENDL; + return true; +} + +// virtual +BOOL LLPanelEstateCovenant::postBuild() +{ + initHelpBtn("covenant_help", "HelpEstateCovenant"); + mEstateNameText = getChild("estate_name_text"); + mEstateOwnerText = getChild("estate_owner_text"); + mLastModifiedText = getChild("covenant_timestamp_text"); + mEditor = getChild("covenant_editor"); + if (mEditor) mEditor->setHandleEditKeysDirectly(TRUE); + LLButton* reset_button = getChild("reset_covenant"); + reset_button->setEnabled(gAgent.canManageEstate()); + reset_button->setClickedCallback(LLPanelEstateCovenant::resetCovenantID, nullptr); + + return LLPanelRegionInfo::postBuild(); +} + +// virtual +void LLPanelEstateCovenant::updateChild(LLUICtrl* child_ctrl) +{ +} + +// virtual +BOOL LLPanelEstateCovenant::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + LLInventoryItem* item = (LLInventoryItem*)cargo_data; + + if (!gAgent.canManageEstate()) + { + *accept = ACCEPT_NO; + return TRUE; + } + + switch(cargo_type) + { + case DAD_NOTECARD: + *accept = ACCEPT_YES_COPY_SINGLE; + if (item && drop) + { + LLSD payload; + payload["item_id"] = item->getUUID(); + LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), payload, + LLPanelEstateCovenant::confirmChangeCovenantCallback); + } + break; + default: + *accept = ACCEPT_NO; + break; + } + + return TRUE; +} + +// static +bool LLPanelEstateCovenant::confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + LLInventoryItem* item = gInventory.getItem(notification["payload"]["item_id"].asUUID()); + LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant(); + + if (!item || !self) return false; + + switch(option) + { + case 0: + self->loadInvItem(item); + break; + default: + break; + } + return false; +} + +// static +void LLPanelEstateCovenant::resetCovenantID(void* userdata) +{ + LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), LLSD(), confirmResetCovenantCallback); +} + +// static +bool LLPanelEstateCovenant::confirmResetCovenantCallback(const LLSD& notification, const LLSD& response) +{ + LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant(); + if (!self) return false; + + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch(option) + { + case 0: + self->loadInvItem(nullptr); + break; + default: + break; + } + return false; +} + +void LLPanelEstateCovenant::loadInvItem(LLInventoryItem *itemp) +{ + const BOOL high_priority = TRUE; + if (itemp) + { + gAssetStorage->getInvItemAsset(gAgent.getRegionHost(), + gAgent.getID(), + gAgent.getSessionID(), + itemp->getPermissions().getOwner(), + LLUUID::null, + itemp->getUUID(), + itemp->getAssetUUID(), + itemp->getType(), + onLoadComplete, + (void*)this, + high_priority); + mAssetStatus = ASSET_LOADING; + } + else + { + mAssetStatus = ASSET_LOADED; + setCovenantTextEditor(LLTrans::getString("RegionNoCovenant")); + sendChangeCovenantID(LLUUID::null); + } +} + +// static +void LLPanelEstateCovenant::onLoadComplete(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status) +{ + LL_INFOS() << "LLPanelEstateCovenant::onLoadComplete()" << LL_ENDL; + LLPanelEstateCovenant* panelp = (LLPanelEstateCovenant*)user_data; + if( panelp ) + { + if(0 == status) + { + LLVFile file(vfs, asset_uuid, type, LLVFile::READ); + + S32 file_length = file.getSize(); + + std::vector buffer(file_length+1); + file.read((U8*)&buffer[0], file_length); + // put a EOS at the end + buffer[file_length] = 0; + + if( (file_length > 19) && !strncmp( &buffer[0], "Linden text version", 19 ) ) + { + if( !panelp->mEditor->importBuffer( &buffer[0], file_length+1 ) ) + { + LL_WARNS() << "Problem importing estate covenant." << LL_ENDL; + LLNotificationsUtil::add("ProblemImportingEstateCovenant"); + } + else + { + panelp->sendChangeCovenantID(asset_uuid); + } + } + else + { + // Version 0 (just text, doesn't include version number) + panelp->sendChangeCovenantID(asset_uuid); + } + } + else + { + LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); + + if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || + LL_ERR_FILE_EMPTY == status) + { + LLNotificationsUtil::add("MissingNotecardAssetID"); + } + else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) + { + LLNotificationsUtil::add("NotAllowedToViewNotecard"); + } + else + { + LLNotificationsUtil::add("UnableToLoadNotecardAsset"); + } + + LL_WARNS() << "Problem loading notecard: " << status << LL_ENDL; + } + panelp->mAssetStatus = ASSET_LOADED; + panelp->setCovenantID(asset_uuid); + } +} + +// key = "estatechangecovenantid" +// strings[0] = str(estate_id) (added by simulator before relay - not here) +// strings[1] = str(covenant_id) +void LLPanelEstateCovenant::sendChangeCovenantID(const LLUUID &asset_id) +{ + if (asset_id != getCovenantID()) + { + setCovenantID(asset_id); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("EstateOwnerMessage"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used + + msg->nextBlock("MethodData"); + msg->addString("Method", "estatechangecovenantid"); + msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice()); - if (isLindenEstate()) - { - // just apply to this estate - LLNotifications::instance().forceResponse(params, 0); - } - else - { - // ask if this estate or all estates with this owner - LLNotifications::instance().add(params); + msg->nextBlock("ParamList"); + msg->addString("Parameter", getCovenantID().asString()); + gAgent.sendReliableMessage(); } } -// static -void LLPanelEstateInfo::accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name) +// virtual +BOOL LLPanelEstateCovenant::sendUpdate() { - LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); - if (!panel) return; - LLNameListCtrl* name_list = panel->getChild(list_ctrl_name); - if (!name_list) return; + return TRUE; +} - std::vector list_vector = name_list->getAllSelected(); - if (list_vector.size() == 0) - return; +std::string LLPanelEstateCovenant::getEstateName() const +{ + return mEstateNameText->getText(); +} - LLSD payload; - payload["operation"] = (S32)operation_flag; - payload["dialog_name"] = dialog_name; - - for (std::vector::const_iterator iter = list_vector.begin(); - iter != list_vector.end(); - iter++) +void LLPanelEstateCovenant::setEstateName(const std::string& name) +{ + mEstateNameText->setText(name); +} + +// static +void LLPanelEstateCovenant::updateCovenantText(const std::string& string, const LLUUID& asset_id) +{ + LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); + if( panelp ) { - LLScrollListItem *item = (*iter); - payload["allowed_ids"].append(item->getUUID()); + panelp->mEditor->setText(string, false); + panelp->setCovenantID(asset_id); } - - LLNotification::Params params("ChangeLindenAccess"); - params.payload(payload) - .functor(accessRemoveCore2); +} - if (isLindenEstate()) +// static +void LLPanelEstateCovenant::updateEstateName(const std::string& name) +{ + LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); + if( panelp ) { - // warn on change linden estate - LLNotifications::instance().add(params); + panelp->mEstateNameText->setText(name); } - else +} + +// static +void LLPanelEstateCovenant::updateLastModified(const std::string& text) +{ + LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); + if( panelp ) { - // just proceed, as if clicking OK - LLNotifications::instance().forceResponse(params, 0); + panelp->mLastModifiedText->setText(text); } } // static -bool LLPanelEstateInfo::accessRemoveCore2(const LLSD& notification, const LLSD& response) +void LLPanelEstateCovenant::updateEstateOwnerID(const LLUUID& id) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) + LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); + if( panelp ) { - // abort - return false; + panelp->mEstateOwnerText->setValue(id); } +} - // If Linden estate, can only apply to "this" estate, not all estates - // owned by NULL. - if (isLindenEstate()) +std::string LLPanelEstateCovenant::getOwnerName() const +{ + return mEstateOwnerText->getText(); +} + +void LLPanelEstateCovenant::setCovenantTextEditor(const std::string& text) +{ + mEditor->setText(text, false); +} + +// key = "estateupdateinfo" +// strings[0] = estate name +// strings[1] = str(owner_id) +// strings[2] = str(estate_id) +// strings[3] = str(estate_flags) +// strings[4] = str((S32)(sun_hour * 1024)) +// strings[5] = str(parent_estate_id) +// strings[6] = str(covenant_id) +// strings[7] = str(covenant_timestamp) +// strings[8] = str(send_to_agent_only) +// strings[9] = str(abuse_email_addr) +bool LLDispatchEstateUpdateInfo::operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) +{ + LL_DEBUGS() << "Received estate update" << LL_ENDL; + + // Update estate info model. + // This will call LLPanelEstateInfo::refreshFromEstate(). + // *TODO: Move estate message handling stuff to llestateinfomodel.cpp. + LLEstateInfoModel::instance().update(strings); + + return true; +} + +bool LLDispatchSetEstateAccess::operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) +{ + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return true; + + S32 index = 1; // skip estate_id + U32 access_flags = strtoul(strings[index++].c_str(), nullptr,10); + S32 num_allowed_agents = strtol(strings[index++].c_str(), nullptr, 10); + S32 num_allowed_groups = strtol(strings[index++].c_str(), nullptr, 10); + S32 num_banned_agents = strtol(strings[index++].c_str(), nullptr, 10); + S32 num_estate_managers = strtol(strings[index++].c_str(), nullptr, 10); + + // sanity ckecks + if (num_allowed_agents > 0 + && !(access_flags & ESTATE_ACCESS_ALLOWED_AGENTS)) { - accessCoreConfirm(notification, response); + LL_WARNS() << "non-zero count for allowed agents, but no corresponding flag" << LL_ENDL; } - else + if (num_allowed_groups > 0 + && !(access_flags & ESTATE_ACCESS_ALLOWED_GROUPS)) { - LLSD args; - args["ALL_ESTATES"] = all_estates_text(); - LLNotificationsUtil::add(notification["payload"]["dialog_name"], - args, - notification["payload"], - accessCoreConfirm); + LL_WARNS() << "non-zero count for allowed groups, but no corresponding flag" << LL_ENDL; + } + if (num_banned_agents > 0 + && !(access_flags & ESTATE_ACCESS_BANNED_AGENTS)) + { + LL_WARNS() << "non-zero count for banned agents, but no corresponding flag" << LL_ENDL; + } + if (num_estate_managers > 0 + && !(access_flags & ESTATE_ACCESS_MANAGERS)) + { + LL_WARNS() << "non-zero count for managers, but no corresponding flag" << LL_ENDL; } - return false; -} - -// Used for both access add and remove operations, depending on the mOperationFlag -// passed in (ESTATE_ACCESS_BANNED_AGENT_ADD, ESTATE_ACCESS_ALLOWED_AGENT_REMOVE, etc.) -// static -bool LLPanelEstateInfo::accessCoreConfirm(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger(); - LLViewerRegion* region = gAgent.getRegion(); - - LLSD::array_const_iterator end_it = notification["payload"]["allowed_ids"].endArray(); + // Build an LLSD to fake the http response on older grids + LLSD result; - for (LLSD::array_const_iterator iter = notification["payload"]["allowed_ids"].beginArray(); - iter != end_it; - iter++) + // grab the UUID's out of the string fields + if (access_flags & ESTATE_ACCESS_ALLOWED_AGENTS) { - U32 flags = originalFlags; - if (iter + 1 != end_it) - flags |= ESTATE_ACCESS_NO_REPLY; + LLNameListCtrl* allowed_agent_name_list = panel->getChild("allowed_avatar_name_list"); - const LLUUID id = iter->asUUID(); - if (((U32)notification["payload"]["operation"].asInteger() & ESTATE_ACCESS_BANNED_AGENT_ADD) - && region && (region->getOwner() == id)) + if (allowed_agent_name_list) { - LLNotificationsUtil::add("OwnerCanNotBeDenied"); - break; + auto& allowed_agents = result["AllowedAgents"]; + for (const auto& id : allowed_agent_name_list->getAllIDs()) + { + allowed_agents.append(LLSD().with("id", id)); + } + for (S32 i = 0; i < num_allowed_agents; ++i) + { + LLUUID id; + memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ + allowed_agents.append(LLSD().with("id", id)); + } } - switch(option) + } + + if (access_flags & ESTATE_ACCESS_ALLOWED_GROUPS) + { + auto& allowed_groups = result["AllowedGroups"]; + for (S32 i = 0; i < num_allowed_groups; ++i) { - case 0: - // This estate - sendEstateAccessDelta(flags, id); - break; - case 1: + LLUUID id; + memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ + allowed_groups.append(LLSD().with("id", id)); + } + } + + if (access_flags & ESTATE_ACCESS_BANNED_AGENTS) + { + if (LLNameListCtrl* banned_agent_name_list = panel->getChild("banned_avatar_name_list")) + { + auto& banned_agents = result["BannedAgents"]; + for (const auto& id : banned_agent_name_list->getAllIDs()) { - // All estates, either than I own or manage for this owner. - // This will be verified on simulator. JC - if (!region) break; - if (region->getOwner() == gAgent.getID() - || gAgent.isGodlike()) - { - flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES; - sendEstateAccessDelta(flags, id); - } - else if (region->isEstateManager()) - { - flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES; - sendEstateAccessDelta(flags, id); - } - break; + banned_agents.append(LLSD().with("id", id)); + } + for (S32 i = 0; i < num_banned_agents; i++) + { + LLUUID id; + memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ + banned_agents.append(LLSD().with("id", id)); } - case 2: - default: - break; } } - return false; + + if (access_flags & ESTATE_ACCESS_MANAGERS) + { + auto& managers = result["Managers"]; + for (S32 i = 0; i < num_estate_managers; ++i) + { + LLUUID id; + memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ + managers.append(LLSD().with("id", id)); + } + } + + if (panel) + { + panel->onEstateAccessReceived(result); // Until HTTP response use UDP Result + if (panel->getPendingUpdate()) + { + panel->setPendingUpdate(false); + panel->updateLists(); + } + } + return true; +} + +LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ) +{ + LLSD idList = LLSD::emptyArray(); + LLUUID id; + while(count--> 0) + { + memcpy(id.mData, (*(it++)).data(), UUID_BYTES); + idList.append(id); + } + return idList; +} + +// key = "setexperience" +// strings[0] = str(estate_id) +// strings[1] = str(send_to_agent_only) +// strings[2] = str(num blocked) +// strings[3] = str(num trusted) +// strings[4] = str(num allowed) +// strings[8] = bin(uuid) ... +// ... +bool LLDispatchSetEstateExperience::operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) +{ + LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences(); + if (!panel) return true; + + sparam_t::const_iterator it = strings.begin(); + ++it; // U32 estate_id = strtol((*it).c_str(), NULL, 10); + ++it; // U32 send_to_agent_only = strtoul((*(++it)).c_str(), NULL, 10); + + LLUUID id; + S32 num_blocked = strtol((*(it++)).c_str(), nullptr, 10); + S32 num_trusted = strtol((*(it++)).c_str(), nullptr, 10); + S32 num_allowed = strtol((*(it++)).c_str(), nullptr, 10); + + LLSD ids = LLSD::emptyMap() + .with("blocked", getIDs(it, strings.end(), num_blocked)) + .with("trusted", getIDs(it + (num_blocked), strings.end(), num_trusted)) + .with("allowed", getIDs(it + (num_blocked+num_trusted), strings.end(), num_allowed)); + + panel->processResponse(ids); + + return true; } -// key = "estateaccessdelta" -// str(estate_id) will be added to front of list by forward_EstateOwnerRequest_to_dataserver -// str[0] = str(agent_id) requesting the change -// str[1] = str(flags) (ESTATE_ACCESS_DELTA_*) -// str[2] = str(agent_id) to add or remove -// static -void LLPanelEstateInfo::sendEstateAccessDelta(U32 flags, const LLUUID& agent_or_group_id) + + +LLPanelEnvironmentInfo::LLPanelEnvironmentInfo() +: mEnableEditing(false), + mRegionSettingsRadioGroup(nullptr), + mDayCycleSettingsRadioGroup(nullptr), + mWaterPresetCombo(nullptr), + mSkyPresetCombo(nullptr), + mDayCyclePresetCombo(nullptr) { - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("EstateOwnerMessage"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used +} - msg->nextBlock("MethodData"); - msg->addString("Method", "estateaccessdelta"); - msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice()); +// virtual +BOOL LLPanelEnvironmentInfo::postBuild() +{ + mRegionSettingsRadioGroup = getChild("region_settings_radio_group"); + mRegionSettingsRadioGroup->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSwitchRegionSettings, this)); - std::string buf; - gAgent.getID().toString(buf); - msg->nextBlock("ParamList"); - msg->addString("Parameter", buf); + mDayCycleSettingsRadioGroup = getChild("sky_dayc_settings_radio_group"); + mDayCycleSettingsRadioGroup->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSwitchDayCycle, this)); - buf = llformat("%u", flags); - msg->nextBlock("ParamList"); - msg->addString("Parameter", buf); + mWaterPresetCombo = getChild("water_settings_preset_combo"); + mWaterPresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectWaterPreset, this)); - agent_or_group_id.toString(buf); - msg->nextBlock("ParamList"); - msg->addString("Parameter", buf); + mSkyPresetCombo = getChild("sky_settings_preset_combo"); + mSkyPresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectSkyPreset, this)); + + mDayCyclePresetCombo = getChild("dayc_settings_preset_combo"); + mDayCyclePresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectDayCycle, this)); + getChild("apply_btn")->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onBtnApply, this)); + getChild("apply_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpUserPrefs, LLEnvManagerNew::getInstance())); + getChild("cancel_btn")->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onBtnCancel, this)); + getChild("cancel_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpPresets, LLEnvManagerNew::getInstance())); - LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); + LLEnvManagerNew::instance().setRegionSettingsChangeCallback(boost::bind(&LLPanelEnvironmentInfo::onRegionSettingschange, this)); + LLEnvManagerNew::instance().setRegionSettingsAppliedCallback(boost::bind(&LLPanelEnvironmentInfo::onRegionSettingsApplied, this, _1)); - if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | - ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_BANNED_AGENT_REMOVE)) - { - - panel->clearAccessLists(); - } + LLDayCycleManager::instance().setModifyCallback(boost::bind(&LLPanelEnvironmentInfo::populateDayCyclesList, this)); + LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLPanelEnvironmentInfo::populateSkyPresetsList, this)); + LLWaterParamManager::instance().setPresetListChangeCallback(boost::bind(&LLPanelEnvironmentInfo::populateWaterPresetsList, this)); - gAgent.sendReliableMessage(); + return TRUE; } -// static -void LLPanelEstateInfo::updateEstateOwnerName(const std::string& name) +// virtual +void LLPanelEnvironmentInfo::onOpen(const LLSD& key) { - LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate(); - if (panelp) - { - panelp->setOwnerName(name); - } + LL_DEBUGS("Windlight") << "Panel opened, refreshing" << LL_ENDL; + refresh(); } -// static -void LLPanelEstateInfo::updateEstateName(const std::string& name) +// virtual +void LLPanelEnvironmentInfo::handleVisibilityChange(BOOL new_visibility) { - LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate(); - if (panelp) + // If hiding (user switched to another tab or closed the floater), + // display user's preferred environment. + if (!new_visibility) { - panelp->getChildRef("estate_name").setText(name); + LLEnvManagerNew::instance().usePrefs(); } } -void LLPanelEstateInfo::updateControls(LLViewerRegion* region) +// virtual +bool LLPanelEnvironmentInfo::refreshFromRegion(LLViewerRegion* region) { - BOOL god = gAgent.isGodlike(); - BOOL owner = (region && (region->getOwner() == gAgent.getID())); - BOOL manager = (region && region->isEstateManager()); - setCtrlsEnabled(god || owner || manager); + LL_DEBUGS("Windlight") << "Region updated, enabling/disabling controls" << LL_ENDL; + BOOL owner_or_god = gAgent.isGodlike() || (region && (region->getOwner() == gAgent.getID())); + BOOL owner_or_god_or_manager = owner_or_god || (region && region->isEstateManager()); - BOOL has_allowed_avatar = getChild("allowed_avatar_name_list")->getFirstSelected() ? TRUE : FALSE; - BOOL has_allowed_group = getChild("allowed_group_name_list")->getFirstSelected() ? TRUE : FALSE; - BOOL has_banned_agent = getChild("banned_avatar_name_list")->getFirstSelected() ? TRUE : FALSE; - BOOL has_estate_manager = getChild("estate_manager_name_list")->getFirstSelected() ? TRUE : FALSE; + // Don't refresh from region settings to avoid flicker after applying new region settings. + mEnableEditing = owner_or_god_or_manager; + setControlsEnabled(mEnableEditing); - getChildView("add_allowed_avatar_btn")->setEnabled(god || owner || manager); - getChildView("remove_allowed_avatar_btn")->setEnabled(has_allowed_avatar && (god || owner || manager)); - getChildView("allowed_avatar_name_list")->setEnabled(god || owner || manager); + return LLPanelRegionInfo::refreshFromRegion(region); +} - getChildView("add_allowed_group_btn")->setEnabled(god || owner || manager); - getChildView("remove_allowed_group_btn")->setEnabled(has_allowed_group && (god || owner || manager) ); - getChildView("allowed_group_name_list")->setEnabled(god || owner || manager); +void LLPanelEnvironmentInfo::refresh() +{ + if(gDisconnected) + { + return; + } - // Can't ban people from mainland, orientation islands, etc. because this - // creates much network traffic and server load. - // Disable their accounts in CSR tool instead. - bool linden_estate = isLindenEstate(); - bool enable_ban = (god || owner || manager) && !linden_estate; - getChildView("add_banned_avatar_btn")->setEnabled(enable_ban); - getChildView("remove_banned_avatar_btn")->setEnabled(has_banned_agent && enable_ban); - getChildView("banned_avatar_name_list")->setEnabled(god || owner || manager); + populateWaterPresetsList(); + populateSkyPresetsList(); + populateDayCyclesList(); - getChildView("message_estate_btn")->setEnabled(god || owner || manager); - getChildView("kick_user_from_estate_btn")->setEnabled(god || owner || manager); + // Init radio groups. + const LLEnvironmentSettings& settings = LLEnvManagerNew::instance().getRegionSettings(); + const LLSD& dc = settings.getWLDayCycle(); + LLSD::Real first_frame_time = dc.size() > 0 ? dc[0][0].asReal() : 0.0f; + const bool use_fixed_sky = dc.size() == 1 && first_frame_time < 0; + mRegionSettingsRadioGroup->setSelectedIndex(settings.getSkyMap().size() == 0 ? 0 : 1); + mDayCycleSettingsRadioGroup->setSelectedIndex(use_fixed_sky ? 0 : 1); - // estate managers can't add estate managers - getChildView("add_estate_manager_btn")->setEnabled(god || owner); - getChildView("remove_estate_manager_btn")->setEnabled(has_estate_manager && (god || owner)); - getChildView("estate_manager_name_list")->setEnabled(god || owner); + setControlsEnabled(mEnableEditing); - refresh(); + setDirty(false); } -bool LLPanelEstateInfo::refreshFromRegion(LLViewerRegion* region) +void LLPanelEnvironmentInfo::setControlsEnabled(bool enabled) { - updateControls(region); - - // let the parent class handle the general data collection. - bool rv = LLPanelRegionInfo::refreshFromRegion(region); - - // We want estate info. To make sure it works across region - // boundaries and multiple packets, we add a serial number to the - // integers and track against that on update. - strings_t strings; - //integers_t integers; - //LLFloaterRegionInfo::incrementSerial(); - LLFloaterRegionInfo::nextInvoice(); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - //integers.push_back(LLFloaterRegionInfo::());::getPanelEstate(); + mRegionSettingsRadioGroup->setEnabled(enabled); + mDayCycleSettingsRadioGroup->setEnabled(enabled); - - LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); - panel->clearAccessLists(); - + mWaterPresetCombo->setEnabled(enabled); + mSkyPresetCombo->setEnabled(enabled); + mDayCyclePresetCombo->setEnabled(enabled); - sendEstateOwnerMessage(gMessageSystem, "getinfo", invoice, strings); + getChildView("apply_btn")->setEnabled(enabled); + getChildView("cancel_btn")->setEnabled(enabled); - refresh(); + if (enabled) + { + // Enable/disable some controls based on currently selected radio buttons. + bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0; + getChild("user_environment_settings")->setEnabled(!use_defaults); - return rv; + bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0; + mSkyPresetCombo->setEnabled(is_fixed_sky); + mDayCyclePresetCombo->setEnabled(!is_fixed_sky); + } } -void LLPanelEstateInfo::updateChild(LLUICtrl* child_ctrl) +void LLPanelEnvironmentInfo::setApplyProgress(bool started) { - // Ensure appropriate state of the management ui. - updateControls(gAgent.getRegion()); + LLTextBox* indicator = getChild("progress_indicator"); + + indicator->setVisible(started); + +/* Singu TODO: LLLoadingIndicator + if (started) + { + indicator->start(); + } + else + { + indicator->stop(); + } +*/ } -bool LLPanelEstateInfo::estateUpdate(LLMessageSystem* msg) +void LLPanelEnvironmentInfo::setDirty(bool dirty) { - LL_INFOS() << "LLPanelEstateInfo::estateUpdate()" << LL_ENDL; - return false; + getChildView("apply_btn")->setEnabled(dirty); + getChildView("cancel_btn")->setEnabled(dirty); } - -BOOL LLPanelEstateInfo::postBuild() +void LLPanelEnvironmentInfo::sendRegionSunUpdate() { - // set up the callbacks for the generic controls - initCtrl("externally_visible_check"); - initCtrl("use_global_time_check"); - initCtrl("fixed_sun_check"); - initCtrl("sun_hour_slider"); - initCtrl("allow_direct_teleport"); - initCtrl("limit_payment"); - initCtrl("limit_age_verified"); - initCtrl("voice_chat_check"); - initHelpBtn("estate_manager_help", "HelpEstateEstateManager"); - initHelpBtn("use_global_time_help", "HelpEstateUseGlobalTime"); - initHelpBtn("fixed_sun_help", "HelpEstateFixedSun"); - initHelpBtn("externally_visible_help", "HelpEstateExternallyVisible"); - initHelpBtn("allow_direct_teleport_help", "HelpEstateAllowDirectTeleport"); - initHelpBtn("allow_resident_help", "HelpEstateAllowResident"); - initHelpBtn("allow_group_help", "HelpEstateAllowGroup"); - initHelpBtn("ban_resident_help", "HelpEstateBanResident"); - initHelpBtn("voice_chat_help", "HelpEstateVoiceChat"); + LLRegionInfoModel& region_info = LLRegionInfoModel::instance(); - // Set up the Legacy Estate Environment checkboxes + // If the region is being switched to fixed sky, + // change the region's sun hour according to the (fixed) sun position. + // This is needed for llGetSunDirection() LSL function to work properly (STORM-1330). + const LLSD& sky_map = mNewRegionSettings.getSkyMap(); + bool region_use_fixed_sky = sky_map.size() == 1; + if (region_use_fixed_sky) { - LLUICtrl* global_time = getChild("use_global_time_check"); - LLUICtrl* fixed_sun = getChild("fixed_sun_check"); - LLUICtrl* hour_slider = getChild("sun_hour_slider"); - global_time->setCommitCallback(boost::bind(on_change_use_other_sun, _2, fixed_sun, hour_slider)); - fixed_sun->setCommitCallback(boost::bind(on_change_fixed_sun, _2, global_time, hour_slider)); + LLWLParamSet param_set; + llassert(sky_map.isMap()); + param_set.setAll(sky_map.beginMap()->second); + F32 sun_angle = param_set.getSunAngle(); + + LL_DEBUGS("Windlight Sync") << "Old sun hour: " << region_info.mSunHour << LL_ENDL; + // convert value range from 0..2pi to 6..30 + region_info.mSunHour = fmodf((sun_angle / F_TWO_PI) * 24.f, 24.f) + 6.f; } - getChild("allowed_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); - LLNameListCtrl *avatar_name_list = getChild("allowed_avatar_name_list"); - if (avatar_name_list) + region_info.setUseFixedSun(region_use_fixed_sky); + region_info.mUseEstateSun = !region_use_fixed_sky; + LL_DEBUGS("Windlight Sync") << "Sun hour: " << region_info.mSunHour << LL_ENDL; + + region_info.sendRegionTerrain(LLFloaterRegionInfo::getLastInvoice()); +} + +void LLPanelEnvironmentInfo::fixEstateSun() +{ + // We don't support fixed sun estates anymore and need to fix + // such estates for region day cycle to take effect. + // *NOTE: Assuming that current estate settings have arrived already. + LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); + if (estate_info.getUseFixedSun()) { - avatar_name_list->setCommitOnSelectionChange(TRUE); - avatar_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS); + LL_INFOS() << "Switching estate to global sun" << LL_ENDL; + estate_info.setUseFixedSun(false); + estate_info.sendEstateInfo(); } +} - childSetAction("add_allowed_avatar_btn", boost::bind(&LLPanelEstateInfo::onClickAddAllowedAgent, this)); - childSetAction("remove_allowed_avatar_btn", boost::bind(&LLPanelEstateInfo::onClickRemoveAllowedAgent, this)); +void LLPanelEnvironmentInfo::populateWaterPresetsList() +{ + mWaterPresetCombo->removeall(); - getChild("allowed_group_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); - LLNameListCtrl* group_name_list = getChild("allowed_group_name_list"); - if (group_name_list) + // If the region already has water params, add them to the list. + const LLEnvironmentSettings& region_settings = LLEnvManagerNew::instance().getRegionSettings(); + if (region_settings.getWaterParams().size() != 0) { - group_name_list->setCommitOnSelectionChange(TRUE); - group_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS); + const std::string& region_name = gAgent.getRegion()->getName(); + mWaterPresetCombo->add(region_name, LLWLParamKey(region_name, LLEnvKey::SCOPE_REGION).toLLSD()); + mWaterPresetCombo->addSeparator(); } - getChild("add_allowed_group_btn")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onClickAddAllowedGroup, this)); - childSetAction("remove_allowed_group_btn", boost::bind(&LLPanelEstateInfo::onClickRemoveAllowedGroup, this)); + std::list user_presets, system_presets; + LLWaterParamManager::instance().getPresetNames(user_presets, system_presets); - getChild("banned_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); - LLNameListCtrl* banned_name_list = getChild("banned_avatar_name_list"); - if (banned_name_list) + // Add local user presets first. + for (std::list::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it) { - banned_name_list->setCommitOnSelectionChange(TRUE); - banned_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS); + mWaterPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD()); } - childSetAction("add_banned_avatar_btn", boost::bind(&LLPanelEstateInfo::onClickAddBannedAgent, this)); - childSetAction("remove_banned_avatar_btn", boost::bind(&LLPanelEstateInfo::onClickRemoveBannedAgent, this)); - - getChild("estate_manager_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); - LLNameListCtrl* manager_name_list = getChild("estate_manager_name_list"); - if (manager_name_list) + if (user_presets.size() > 0) { - manager_name_list->setCommitOnSelectionChange(TRUE); - manager_name_list->setMaxItemCount(ESTATE_MAX_MANAGERS * 4); // Allow extras for dupe issue + mWaterPresetCombo->addSeparator(); } - childSetAction("add_estate_manager_btn", boost::bind(&LLPanelEstateInfo::onClickAddEstateManager, this)); - childSetAction("remove_estate_manager_btn", boost::bind(&LLPanelEstateInfo::onClickRemoveEstateManager, this)); - childSetAction("message_estate_btn", boost::bind(&LLPanelEstateInfo::onClickMessageEstate, this)); - childSetAction("kick_user_from_estate_btn", boost::bind(&LLPanelEstateInfo::onClickKickUser, this)); + // Add local system presets. + for (std::list::const_iterator it = system_presets.begin(); it != system_presets.end(); ++it) + { + mWaterPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD()); + } - return LLPanelRegionInfo::postBuild(); + // There's no way to select current preset because its name is not stored on server. } -void LLPanelEstateInfo::refresh() +void LLPanelEnvironmentInfo::populateSkyPresetsList() { - // Disable access restriction controls if they make no sense. - bool public_access = getChild("externally_visible_check")->getValue().asBoolean(); + mSkyPresetCombo->removeall(); - getChildView("Only Allow")->setEnabled(public_access); - getChildView("limit_payment")->setEnabled(public_access); - getChildView("limit_age_verified")->setEnabled(public_access); + LLWLParamManager::preset_name_list_t region_presets; + LLWLParamManager::preset_name_list_t user_presets, sys_presets; + LLWLParamManager::instance().getPresetNames(region_presets, user_presets, sys_presets); - // if this is set to false, then the limit fields are meaningless and should be turned off - if (public_access == false) + // Add region presets. + std::string region_name = gAgent.getRegion() ? gAgent.getRegion()->getName() : LLTrans::getString("Unknown"); + for (LLWLParamManager::preset_name_list_t::const_iterator it = region_presets.begin(); it != region_presets.end(); ++it) { - getChild("limit_payment")->setValue(false); - getChild("limit_age_verified")->setValue(false); + std::string preset_name = *it; + std::string item_title = preset_name + " (" + region_name + ")"; + mSkyPresetCombo->add(item_title, LLWLParamKey(preset_name, LLEnvKey::SCOPE_REGION).toStringVal()); } -} -void LLPanelEstateInfo::refreshFromEstate() -{ - const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); + if (!region_presets.empty()) + { + mSkyPresetCombo->addSeparator(); + } - getChild("estate_name")->setValue(estate_info.getName()); - LLAvatarNameCache::get(estate_info.getOwnerID(), boost::bind(&LLPanelEstateInfo::setOwnerName, this, boost::bind(&LLAvatarName::getNSName, _2, main_name_system()))); + // Add user presets. + for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it) + { + mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal()); + } - getChild("externally_visible_check")->setValue(estate_info.getIsExternallyVisible()); - getChild("voice_chat_check")->setValue(estate_info.getAllowVoiceChat()); - getChild("allow_direct_teleport")->setValue(estate_info.getAllowDirectTeleport()); - getChild("limit_payment")->setValue(estate_info.getDenyAnonymous()); - getChild("limit_age_verified")->setValue(estate_info.getDenyAgeUnverified()); + if (!user_presets.empty()) + { + mSkyPresetCombo->addSeparator(); + } - // Ensure appropriate state of the management UI - updateControls(gAgent.getRegion()); - // Support Legacy Estate Environment + // Add system presets. + for (LLWLParamManager::preset_name_list_t::const_iterator it = sys_presets.begin(); it != sys_presets.end(); ++it) { - const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); - bool global_time = estate_info.getGlobalTime(); - getChild("use_global_time_check")->setValue(global_time); - getChild("fixed_sun_check")->setEnabled(!global_time); - getChild("sun_hour_slider")->setEnabled(!global_time); - if (global_time) - { - getChild("use_global_time_check")->setEnabled(true); - getChild("fixed_sun_check")->setValue(false); - } - else - { - bool fixed_sun = estate_info.getUseFixedSun(); - getChild("use_global_time_check")->setEnabled(!fixed_sun); - getChild("fixed_sun_check")->setValue(fixed_sun); - F32 sun_hour = estate_info.getSunHour(); - if (sun_hour < 6.0f) sun_hour += 24.0f; - getChild("sun_hour_slider")->setValue(sun_hour); - } + mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal()); + } + + // Select current preset. + LLSD sky_map = LLEnvManagerNew::instance().getRegionSettings().getSkyMap(); + if (sky_map.size() == 1) // if the region is set to fixed sky + { + std::string preset_name = sky_map.beginMap()->first; + mSkyPresetCombo->selectByValue(LLWLParamKey(preset_name, LLEnvKey::SCOPE_REGION).toStringVal()); } - refresh(); } -BOOL LLPanelEstateInfo::sendUpdate() +void LLPanelEnvironmentInfo::populateDayCyclesList() { - LL_INFOS() << "LLPanelEstateInfo::sendUpdate()" << LL_ENDL; + mDayCyclePresetCombo->removeall(); - LLNotification::Params params("ChangeLindenEstate"); - params.functor(boost::bind(&LLPanelEstateInfo::callbackChangeLindenEstate, this, _1, _2)); + // If the region already has env. settings, add its day cycle to the list. + const LLSD& cur_region_dc = LLEnvManagerNew::instance().getRegionSettings().getWLDayCycle(); + if (cur_region_dc.size() != 0) + { + LLViewerRegion* region = gAgent.getRegion(); + llassert(region != NULL); - if (isLindenEstate()) + LLWLParamKey key(region->getName(), LLEnvKey::SCOPE_REGION); + mDayCyclePresetCombo->add(region->getName(), key.toStringVal()); + mDayCyclePresetCombo->addSeparator(); + } + + // Add local user day cycles. + LLDayCycleManager::preset_name_list_t user_days, sys_days; + LLDayCycleManager::instance().getPresetNames(user_days, sys_days); + for (LLDayCycleManager::preset_name_list_t::const_iterator it = user_days.begin(); it != user_days.end(); ++it) { - // trying to change reserved estate, warn - LLNotifications::instance().add(params); + mDayCyclePresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal()); } - else + + if (user_days.size() > 0) { - // for normal estates, just make the change - LLNotifications::instance().forceResponse(params, 0); + mDayCyclePresetCombo->addSeparator(); } - return TRUE; + + // Add local system day cycles. + for (LLDayCycleManager::preset_name_list_t::const_iterator it = sys_days.begin(); it != sys_days.end(); ++it) + { + mDayCyclePresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal()); + } + + // Current day cycle is already selected. } -bool LLPanelEstateInfo::callbackChangeLindenEstate(const LLSD& notification, const LLSD& response) +bool LLPanelEnvironmentInfo::getSelectedWaterParams(LLSD& water_params) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - switch(option) + LLWLParamKey water_key(mWaterPresetCombo->getSelectedValue()); + + if (water_key.scope == LLEnvKey::SCOPE_REGION) { - case 0: + water_params = LLEnvManagerNew::instance().getRegionSettings().getWaterParams(); + } + else + { + LLWaterParamSet param_set; + if (!LLWaterParamManager::instance().getParamSet(water_key.name, param_set)) { - LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); - - // update model - estate_info.setIsExternallyVisible(getChild("externally_visible_check")->getValue().asBoolean()); - estate_info.setUseFixedSun(getChild("fixed_sun_check")->getValue().asBoolean()); - estate_info.setSunHour(get_sun_hour(getChild("sun_hour_slider"))); - estate_info.setAllowDirectTeleport(getChild("allow_direct_teleport")->getValue().asBoolean()); - estate_info.setDenyAnonymous(getChild("limit_payment")->getValue().asBoolean()); - estate_info.setDenyAgeUnverified(getChild("limit_age_verified")->getValue().asBoolean()); - estate_info.setAllowVoiceChat(getChild("voice_chat_check")->getValue().asBoolean()); - - // send the update to sim - estate_info.sendEstateInfo(); + LL_WARNS() << "Error getting water preset: " << water_key.name << LL_ENDL; + return false; } - // we don't want to do this because we'll get it automatically from the sim - // after the spaceserver processes it -// else -// { -// // caps method does not automatically send this info -// LLFloaterRegionInfo::requestRegionInfo(); -// } - break; - case 1: - default: - // do nothing - break; + water_params = param_set.getAll(); } - return false; + + return true; } +bool LLPanelEnvironmentInfo::getSelectedSkyParams(LLSD& sky_params, std::string& preset_name) +{ + std::string preset_key(mSkyPresetCombo->getValue().asString()); + LLWLParamKey preset(preset_key); -/* -// Request = "getowner" -// SParam[0] = "" (empty string) -// IParam[0] = serial -void LLPanelEstateInfo::getEstateOwner() + // Get the preset sky params. + LLWLParamSet param_set; + if (!LLWLParamManager::instance().getParamSet(preset, param_set)) + { + LL_WARNS() << "Error getting sky params: " << preset.toLLSD() << LL_ENDL; + return false; + } + + sky_params = param_set.getAll(); + preset_name = preset.name; + return true; +} + +bool LLPanelEnvironmentInfo::getSelectedDayCycleParams(LLSD& day_cycle, LLSD& sky_map, short& scope) { - // TODO -- disable the panel - // and call this function whenever we cross a region boundary - // re-enable when owner matches, and get new estate info - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_EstateOwnerRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + std::string preset_key(mDayCyclePresetCombo->getValue().asString()); + LLWLParamKey dc(preset_key); + LL_DEBUGS("Windlight") << "Use day cycle: " << dc.toLLSD() << LL_ENDL; - msg->nextBlockFast(_PREHASH_RequestData); - msg->addStringFast(_PREHASH_Request, "getowner"); + if (dc.scope == LLEnvKey::SCOPE_REGION) // current region day cycle + { + const LLEnvironmentSettings& cur_region_settings = LLEnvManagerNew::instance().getRegionSettings(); + day_cycle = cur_region_settings.getWLDayCycle(); + sky_map = cur_region_settings.getSkyMap(); + } + else // a local day cycle + { + if (!LLDayCycleManager::instance().getPreset(dc.name, day_cycle)) + { + LL_WARNS() << "Error getting day cycle " << dc.name << LL_ENDL; + return false; + } - // we send an empty string so that the variable block is not empty - msg->nextBlockFast(_PREHASH_StringData); - msg->addStringFast(_PREHASH_SParam, ""); + // Create sky map from the day cycle. + { + LLWLDayCycle tmp_day; + tmp_day.loadDayCycle(day_cycle, dc.scope); + tmp_day.getSkyMap(sky_map); + } + } - msg->nextBlockFast(_PREHASH_IntegerData); - msg->addS32Fast(_PREHASH_IParam, LLFloaterRegionInfo::getSerial()); + scope = dc.scope; - gAgent.sendMessage(); + return true; } -*/ - -class LLEstateChangeInfoResponder : public LLHTTPClient::ResponderWithResult +void LLPanelEnvironmentInfo::onSwitchRegionSettings() { - LOG_CLASS(LLEstateChangeInfoResponder); -public: - LLEstateChangeInfoResponder(LLPanelEstateInfo* panel) - { - mpPanel = panel->getHandle(); - } - -protected: - // if we get a normal response, handle it here - virtual void httpSuccess() - { - LL_INFOS("Windlight") << "Successfully committed estate info" << LL_ENDL; + bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0; + getChild("user_environment_settings")->setEnabled(!use_defaults); - // refresh the panel from the database - LLPanelEstateInfo* panel = dynamic_cast(mpPanel.get()); - if (panel) - panel->refresh(); + if (use_defaults) + { + LLEnvManagerNew::instance().useDefaults(); } - - // if we get an error response - virtual void httpFailure() + else { - LL_WARNS("Windlight") << dumpResponse() << LL_ENDL; + onSelectWaterPreset(); + onSwitchDayCycle(); } - /*virtual*/ char const* getName(void) const { return "LLEstateChangeInfoResponder"; } - -private: - LLHandle mpPanel; -}; - -const std::string LLPanelEstateInfo::getOwnerName() const -{ - return getChild("estate_owner")->getValue().asString(); + setDirty(true); } -void LLPanelEstateInfo::setOwnerName(const std::string& name) +void LLPanelEnvironmentInfo::onSwitchDayCycle() { - getChild("estate_owner")->setValue(LLSD(name)); -} + bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0; -void LLPanelEstateInfo::clearAccessLists() -{ - LLNameListCtrl* name_list = getChild("allowed_avatar_name_list"); - if (name_list) + mSkyPresetCombo->setEnabled(is_fixed_sky); + mDayCyclePresetCombo->setEnabled(!is_fixed_sky); + + if (is_fixed_sky) { - name_list->deleteAllItems(); + onSelectSkyPreset(); } - - name_list = getChild("banned_avatar_name_list"); - if (name_list) + else { - name_list->deleteAllItems(); + onSelectDayCycle(); } - updateControls(gAgent.getRegion()); -} -// static -void LLPanelEstateInfo::onClickMessageEstate(void* userdata) -{ - LL_INFOS() << "LLPanelEstateInfo::onClickMessageEstate" << LL_ENDL; - LLNotificationsUtil::add("MessageEstate", LLSD(), LLSD(), boost::bind(&LLPanelEstateInfo::onMessageCommit, (LLPanelEstateInfo*)userdata, _1, _2)); + setDirty(true); } -bool LLPanelEstateInfo::onMessageCommit(const LLSD& notification, const LLSD& response) +void LLPanelEnvironmentInfo::onSelectWaterPreset() { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - std::string text = response["message"].asString(); - if(option != 0) return false; - if(text.empty()) return false; - LL_INFOS() << "Message to everyone: " << text << LL_ENDL; - strings_t strings; - //integers_t integers; - std::string name; - LLAgentUI::buildFullname(name); - strings.push_back(strings_t::value_type(name)); - strings.push_back(strings_t::value_type(text)); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - sendEstateOwnerMessage(gMessageSystem, "instantmessage", invoice, strings); - return false; -} + LLSD water_params; -LLPanelEstateCovenant::LLPanelEstateCovenant() - : - mCovenantID(LLUUID::null) -{ + if (getSelectedWaterParams(water_params)) + { + LLEnvManagerNew::instance().useWaterParams(water_params); + } + + setDirty(true); } -// virtual -bool LLPanelEstateCovenant::refreshFromRegion(LLViewerRegion* region) +void LLPanelEnvironmentInfo::onSelectSkyPreset() { - LLTextBox* region_name = getChild("region_name_text"); - if (region_name) - { - region_name->setText(region->getName()); - } + LLSD params; + std::string dummy; - LLTextBox* resellable_clause = getChild("resellable_clause"); - if (resellable_clause) - { - if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL)) - { - resellable_clause->setText(getString("can_not_resell")); - } - else - { - resellable_clause->setText(getString("can_resell")); - } - } - - LLTextBox* changeable_clause = getChild("changeable_clause"); - if (changeable_clause) + if (getSelectedSkyParams(params, dummy)) { - if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES)) - { - changeable_clause->setText(getString("can_change")); - } - else - { - changeable_clause->setText(getString("can_not_change")); - } + LLEnvManagerNew::instance().useSkyParams(params); } - LLTextBox* region_maturity = getChild("region_maturity_text"); - if (region_maturity) - { - region_maturity->setText(region->getSimAccessString()); - } - - LLTextBox* region_landtype = getChild("region_landtype_text"); - region_landtype->setText(region->getLocalizedSimProductName()); - - // let the parent class handle the general data collection. - bool rv = LLPanelRegionInfo::refreshFromRegion(region); - LLMessageSystem *msg = gMessageSystem; - msg->newMessage("EstateCovenantRequest"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); - msg->sendReliable(region->getHost()); - return rv; + setDirty(true); } -// virtual -bool LLPanelEstateCovenant::estateUpdate(LLMessageSystem* msg) -{ - LL_INFOS() << "LLPanelEstateCovenant::estateUpdate()" << LL_ENDL; - return true; -} - -// virtual -BOOL LLPanelEstateCovenant::postBuild() +void LLPanelEnvironmentInfo::onSelectDayCycle() { - initHelpBtn("covenant_help", "HelpEstateCovenant"); - mEstateNameText = getChild("estate_name_text"); - mEstateOwnerText = getChild("estate_owner_text"); - mLastModifiedText = getChild("covenant_timestamp_text"); - mEditor = getChild("covenant_editor"); - if (mEditor) mEditor->setHandleEditKeysDirectly(TRUE); - LLButton* reset_button = getChild("reset_covenant"); - reset_button->setEnabled(gAgent.canManageEstate()); - reset_button->setClickedCallback(LLPanelEstateCovenant::resetCovenantID, NULL); + LLSD day_cycle; + LLSD sky_map; // unused + short scope; - return LLPanelRegionInfo::postBuild(); -} + if (getSelectedDayCycleParams(day_cycle, sky_map, scope)) + { + LLEnvManagerNew::instance().useDayCycleParams(day_cycle, (LLEnvKey::EScope) scope); + } -// virtual -void LLPanelEstateCovenant::updateChild(LLUICtrl* child_ctrl) -{ + setDirty(true); } -// virtual -BOOL LLPanelEstateCovenant::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) +void LLPanelEnvironmentInfo::onBtnApply() { - LLInventoryItem* item = (LLInventoryItem*)cargo_data; + const bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0; + const bool use_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0; - if (!gAgent.canManageEstate()) + LLSD day_cycle; + LLSD sky_map; + LLSD water_params; + + if (use_defaults) { - *accept = ACCEPT_NO; - return TRUE; + // settings will be empty + LL_DEBUGS("Windlight") << "Defaults" << LL_ENDL; } - - switch(cargo_type) + else // use custom region settings { - case DAD_NOTECARD: - *accept = ACCEPT_YES_COPY_SINGLE; - if (item && drop) + if (use_fixed_sky) { - LLSD payload; - payload["item_id"] = item->getUUID(); - LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), payload, - LLPanelEstateCovenant::confirmChangeCovenantCallback); + LL_DEBUGS("Windlight") << "Use fixed sky" << LL_ENDL; + + // Get selected sky params. + LLSD params; + std::string preset_name; + if (!getSelectedSkyParams(params, preset_name)) + { + return; + } + + // Create a day cycle consisting of a single sky preset. + LLSD key(LLSD::emptyArray()); + key.append(-1.0f); // indicate that user preference is actually fixed sky, not a day cycle + key.append(preset_name); + day_cycle.append(key); + + // Create a sky map consisting of only the sky preset. + std::map refs; + LLWLParamSet param_set; + param_set.setAll(params); + refs[LLWLParamKey(preset_name, LLEnvKey::SCOPE_LOCAL)] = param_set; // scope doesn't matter here + sky_map = LLWLParamManager::createSkyMap(refs); } - break; - default: - *accept = ACCEPT_NO; - break; + else // use day cycle + { + LL_DEBUGS("Windlight") << "Use day cycle" << LL_ENDL; + + short scope; // unused + if (!getSelectedDayCycleParams(day_cycle, sky_map, scope)) + { + return; + } + + // If it's a special single-preset day cycle meaning using a fixed sky, + // reset the frame time to a non-negative value, + // so that the region setting is displayed in the floater as + // a day cycle, not a preset. (STORM-1289) + if (day_cycle.size() == 1 && day_cycle[0][0].asReal() < 0.0f) + { + LL_DEBUGS("Windlight") << "Fixing negative time" << LL_ENDL; + day_cycle[0][0] = 0.0f; + } + } + + // Get water params. + if (!getSelectedWaterParams(water_params)) + { + // *TODO: show a notification? + return; + } + } + + // Send settings apply request. + LLEnvironmentSettings new_region_settings; + new_region_settings.saveParams(day_cycle, sky_map, water_params, 0.0f); + if (!LLEnvManagerNew::instance().sendRegionSettings(new_region_settings)) + { + LL_WARNS() << "Error applying region environment settings" << LL_ENDL; + return; } - return TRUE; -} + // When the settings get applied, we'll also send the region sun position update. + // To determine the sun angle we're going to need the new settings. + mNewRegionSettings = new_region_settings; -// static -bool LLPanelEstateCovenant::confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response) + // Start spinning the progress indicator. + setApplyProgress(true); +} + +void LLPanelEnvironmentInfo::onBtnCancel() { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - LLInventoryItem* item = gInventory.getItem(notification["payload"]["item_id"].asUUID()); - LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant(); + // Reload last saved region settings. + refresh(); - if (!item || !self) return false; + // Apply them. + LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance(); + const LLEnvironmentSettings& cur_settings = env_mgr.getRegionSettings(); + const LLSD& region_day_cycle = cur_settings.getWLDayCycle(); + const LLSD& region_water = cur_settings.getWaterParams(); + env_mgr.useWaterParams(region_water); + env_mgr.useDayCycleParams(region_day_cycle, LLEnvKey::SCOPE_REGION); +} - switch(option) +void LLPanelEnvironmentInfo::onRegionSettingschange() +{ + LL_DEBUGS("Windlight") << "Region settings changed, refreshing" << LL_ENDL; + refresh(); + + // Stop applying progress indicator (it may be running if it's us who initiated settings update). + setApplyProgress(false); +} + +void LLPanelEnvironmentInfo::onRegionSettingsApplied(bool ok) +{ + // If applying new settings has failed, stop the indicator right away. + // Otherwise it will be stopped when we receive the updated settings from server. + if (ok) { - case 0: - self->loadInvItem(item); - break; - default: - break; + // Set the region sun phase/flags according to the chosen new preferences. + // + // If we do this earlier we may get jerky transition from fixed sky to a day cycle (STORM-1481). + // That is caused by the simulator re-sending the region info, which in turn makes us + // re-request and display old region environment settings while the new ones haven't been applied yet. + sendRegionSunUpdate(); + + // Switch estate to not using fixed sun for the region day cycle to work properly (STORM-1506). + fixEstateSun(); + } + else + { + setApplyProgress(false); + + // We need to re-request environment setting here, + // otherwise our subsequent attempts to change region settings will fail with the following error: + // "Unable to update environment settings because the last update your viewer saw was not the same + // as the last update sent from the simulator. Try sending your update again, and if this + // does not work, try leaving and returning to the region." + LLEnvManagerNew::instance().requestRegionSettings(); } - return false; } -// static -void LLPanelEstateCovenant::resetCovenantID(void* userdata) +LLPanelRegionExperiences::LLPanelRegionExperiences() +: mTrusted(nullptr) +, mAllowed(nullptr) +, mBlocked(nullptr) { - LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), LLSD(), confirmResetCovenantCallback); + mFactoryMap["panel_trusted"] = LLCallbackMap(create_xp_list_editor, reinterpret_cast(&mTrusted)); + mFactoryMap["panel_allowed"] = LLCallbackMap(create_xp_list_editor, reinterpret_cast(&mAllowed)); + mFactoryMap["panel_blocked"] = LLCallbackMap(create_xp_list_editor, reinterpret_cast(&mBlocked)); + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_region_experiences.xml", &mFactoryMap); } -// static -bool LLPanelEstateCovenant::confirmResetCovenantCallback(const LLSD& notification, const LLSD& response) +BOOL LLPanelRegionExperiences::postBuild() { - LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant(); - if (!self) return false; + setupList(mAllowed, "panel_allowed", ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE); + setupList(mTrusted, "panel_trusted", ESTATE_EXPERIENCE_TRUSTED_ADD, ESTATE_EXPERIENCE_TRUSTED_REMOVE); + setupList(mBlocked, "panel_blocked", ESTATE_EXPERIENCE_BLOCKED_ADD, ESTATE_EXPERIENCE_BLOCKED_REMOVE); - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - switch(option) + getChild("trusted_layout_panel")->setVisible(TRUE); + getChild("experiences_help_text")->setText(getString("estate_caption")); + getChild("trusted_text_help")->setText(getString("trusted_estate_text")); + getChild("allowed_text_help")->setText(getString("allowed_estate_text")); + getChild("blocked_text_help")->setText(getString("blocked_estate_text")); + + return LLPanelRegionInfo::postBuild(); +} + +void LLPanelRegionExperiences::setupList(LLPanelExperienceListEditor* child, const char* control_name, U32 add_id, U32 remove_id ) +{ + //LLPanelExperienceListEditor* child = findChild(control_name); + if(child) { - case 0: - self->loadInvItem(NULL); - break; - default: - break; + child->getChild("text_name")->setText(child->getString(control_name)); + child->setMaxExperienceIDs(ESTATE_MAX_EXPERIENCE_IDS); + child->setAddedCallback( boost::bind(&LLPanelRegionExperiences::itemChanged, this, add_id, _1)); + child->setRemovedCallback(boost::bind(&LLPanelRegionExperiences::itemChanged, this, remove_id, _1)); } - return false; + + //return child; } -void LLPanelEstateCovenant::loadInvItem(LLInventoryItem *itemp) + +void LLPanelRegionExperiences::processResponse( const LLSD& content ) { - const BOOL high_priority = TRUE; - if (itemp) + if(content.has("default")) { - gAssetStorage->getInvItemAsset(gAgent.getRegionHost(), - gAgent.getID(), - gAgent.getSessionID(), - itemp->getPermissions().getOwner(), - LLUUID::null, - itemp->getUUID(), - itemp->getAssetUUID(), - itemp->getType(), - onLoadComplete, - (void*)this, - high_priority); - mAssetStatus = ASSET_LOADING; + mDefaultExperience = content["default"].asUUID(); } - else + + mAllowed->setExperienceIds(content["allowed"]); + mBlocked->setExperienceIds(content["blocked"]); + + LLSD trusted = content["trusted"]; + if(mDefaultExperience.notNull()) { - mAssetStatus = ASSET_LOADED; - setCovenantTextEditor(LLTrans::getString("RegionNoCovenant")); - sendChangeCovenantID(LLUUID::null); + mTrusted->setStickyFunction(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience)); + trusted.append(mDefaultExperience); } + + mTrusted->setExperienceIds(trusted); + + mAllowed->refreshExperienceCounter(); + mBlocked->refreshExperienceCounter(); + mTrusted->refreshExperienceCounter(); + } +// Used for both access add and remove operations, depending on the flag +// passed in (ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE, etc.) // static -void LLPanelEstateCovenant::onLoadComplete(LLVFS *vfs, - const LLUUID& asset_uuid, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status) +bool LLPanelRegionExperiences::experienceCoreConfirm(const LLSD& notification, const LLSD& response) { - LL_INFOS() << "LLPanelEstateCovenant::onLoadComplete()" << LL_ENDL; - LLPanelEstateCovenant* panelp = (LLPanelEstateCovenant*)user_data; - if( panelp ) - { - if(0 == status) - { - LLVFile file(vfs, asset_uuid, type, LLVFile::READ); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger(); - S32 file_length = file.getSize(); + LLViewerRegion* region = gAgent.getRegion(); - std::vector buffer(file_length+1); - file.read((U8*)&buffer[0], file_length); - // put a EOS at the end - buffer[file_length] = 0; + LLSD::array_const_iterator end_it = notification["payload"]["allowed_ids"].endArray(); - if( (file_length > 19) && !strncmp( &buffer[0], "Linden text version", 19 ) ) + for (LLSD::array_const_iterator iter = notification["payload"]["allowed_ids"].beginArray(); + iter != end_it; + iter++) + { + U32 flags = originalFlags; + if (iter + 1 != end_it) + flags |= ESTATE_ACCESS_NO_REPLY; + + const LLUUID id = iter->asUUID(); + switch(option) + { + case 0: + // This estate + sendEstateExperienceDelta(flags, id); + break; + case 1: { - if( !panelp->mEditor->importBuffer( &buffer[0], file_length+1 ) ) + // All estates, either than I own or manage for this owner. + // This will be verified on simulator. JC + if (!region) break; + if (region->getOwner() == gAgent.getID() + || gAgent.isGodlike()) { - LL_WARNS() << "Problem importing estate covenant." << LL_ENDL; - LLNotificationsUtil::add("ProblemImportingEstateCovenant"); + flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES; + sendEstateExperienceDelta(flags, id); } - else + else if (region->isEstateManager()) { - panelp->sendChangeCovenantID(asset_uuid); + flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES; + sendEstateExperienceDelta(flags, id); } + break; } - else - { - // Version 0 (just text, doesn't include version number) - panelp->sendChangeCovenantID(asset_uuid); - } - } - else - { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || - LL_ERR_FILE_EMPTY == status) - { - LLNotificationsUtil::add("MissingNotecardAssetID"); - } - else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) - { - LLNotificationsUtil::add("NotAllowedToViewNotecard"); - } - else - { - LLNotificationsUtil::add("UnableToLoadNotecardAsset"); - } - - LL_WARNS() << "Problem loading notecard: " << status << LL_ENDL; + case 2: + default: + break; } - panelp->mAssetStatus = ASSET_LOADED; - panelp->setCovenantID(asset_uuid); } + return false; } -// key = "estatechangecovenantid" -// strings[0] = str(estate_id) (added by simulator before relay - not here) -// strings[1] = str(covenant_id) -void LLPanelEstateCovenant::sendChangeCovenantID(const LLUUID &asset_id) -{ - if (asset_id != getCovenantID()) - { - setCovenantID(asset_id); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("EstateOwnerMessage"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used - msg->nextBlock("MethodData"); - msg->addString("Method", "estatechangecovenantid"); - msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice()); +// Send the actual "estateexperiencedelta" message +void LLPanelRegionExperiences::sendEstateExperienceDelta(U32 flags, const LLUUID& experience_id) +{ + strings_t str(3, std::string()); + gAgent.getID().toString(str[0]); + str[1] = llformat("%u", flags); + experience_id.toString(str[2]); - msg->nextBlock("ParamList"); - msg->addString("Parameter", getCovenantID().asString()); - gAgent.sendReliableMessage(); + LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences(); + if (panel) + { + panel->sendEstateOwnerMessage(gMessageSystem, "estateexperiencedelta", LLFloaterRegionInfo::getLastInvoice(), str); } } -// virtual -BOOL LLPanelEstateCovenant::sendUpdate() -{ - return TRUE; -} - -std::string LLPanelEstateCovenant::getEstateName() const -{ - return mEstateNameText->getText(); -} -void LLPanelEstateCovenant::setEstateName(const std::string& name) +void LLPanelRegionExperiences::infoCallback(LLHandle handle, const LLSD& content) { - mEstateNameText->setText(name); -} + if (handle.isDead()) + return; -// static -void LLPanelEstateCovenant::updateCovenantText(const std::string& string, const LLUUID& asset_id) -{ - LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); - if( panelp ) + LLPanelRegionExperiences* floater = handle.get(); + if (floater) { - panelp->mEditor->setText(string); - panelp->setCovenantID(asset_id); + floater->processResponse(content); } } -// static -void LLPanelEstateCovenant::updateEstateName(const std::string& name) +/*static*/ +std::string LLPanelRegionExperiences::regionCapabilityQuery(LLViewerRegion* region, const std::string &cap) { - LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); - if( panelp ) - { - panelp->mEstateNameText->setText(name); - } + // region->getHandle() How to get a region * from a handle? + + return region->getCapability(cap); } -// static -void LLPanelEstateCovenant::updateLastModified(const std::string& text) +bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region) { - LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); - if( panelp ) - { - panelp->mLastModifiedText->setText(text); - } + BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); + + mAllowed->loading(); + mAllowed->setReadonly(!allow_modify); + // remove grid-wide experiences + mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_GRID)); + // remove default experience + mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience)); + + mBlocked->loading(); + mBlocked->setReadonly(!allow_modify); + // only grid-wide experiences + mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithoutProperty, _1, LLExperienceCache::PROPERTY_GRID)); + // but not privileged ones + mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_PRIVILEGED)); + // remove default experience + mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience)); + + mTrusted->loading(); + mTrusted->setReadonly(!allow_modify); + + LLExperienceCache::instance().getRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), + boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle(), _1)); + + return LLPanelRegionInfo::refreshFromRegion(region); } -// static -void LLPanelEstateCovenant::updateEstateOwnerName(const std::string& name) +LLSD LLPanelRegionExperiences::addIds(LLPanelExperienceListEditor* panel) { - LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); - if( panelp ) + LLSD ids; + const uuid_list_t& id_list = panel->getExperienceIds(); + for(uuid_list_t::const_iterator it = id_list.begin(); it != id_list.end(); ++it) { - panelp->mEstateOwnerText->setText(name); + ids.append(*it); } + return ids; } -std::string LLPanelEstateCovenant::getOwnerName() const -{ - return mEstateOwnerText->getText(); -} -void LLPanelEstateCovenant::setOwnerName(const std::string& name) +BOOL LLPanelRegionExperiences::sendUpdate() { - mEstateOwnerText->setText(name); -} + LLViewerRegion* region = gAgent.getRegion(); -void LLPanelEstateCovenant::setCovenantTextEditor(const std::string& text) -{ - mEditor->setText(text); + LLSD content; + + content["allowed"]=addIds(mAllowed); + content["blocked"]=addIds(mBlocked); + content["trusted"]=addIds(mTrusted); + + LLExperienceCache::instance().setRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), + content, boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle(), _1)); + + return TRUE; } -// key = "estateupdateinfo" -// strings[0] = estate name -// strings[1] = str(owner_id) -// strings[2] = str(estate_id) -// strings[3] = str(estate_flags) -// strings[4] = str((S32)(sun_hour * 1024)) -// strings[5] = str(parent_estate_id) -// strings[6] = str(covenant_id) -// strings[7] = str(covenant_timestamp) -// strings[8] = str(send_to_agent_only) -// strings[9] = str(abuse_email_addr) -bool LLDispatchEstateUpdateInfo::operator()( - const LLDispatcher* dispatcher, - const std::string& key, - const LLUUID& invoice, - const sparam_t& strings) +void LLPanelRegionExperiences::itemChanged( U32 event_type, const LLUUID& id ) { - LL_DEBUGS() << "Received estate update" << LL_ENDL; + std::string dialog_name; + switch (event_type) + { + case ESTATE_EXPERIENCE_ALLOWED_ADD: + dialog_name = "EstateAllowedExperienceAdd"; + break; - // Update estate info model. - // This will call LLPanelEstateInfo::refreshFromEstate(). - // *TODO: Move estate message handling stuff to llestateinfomodel.cpp. - LLEstateInfoModel::instance().update(strings); + case ESTATE_EXPERIENCE_ALLOWED_REMOVE: + dialog_name = "EstateAllowedExperienceRemove"; + break; - return true; -} + case ESTATE_EXPERIENCE_TRUSTED_ADD: + dialog_name = "EstateTrustedExperienceAdd"; + break; + case ESTATE_EXPERIENCE_TRUSTED_REMOVE: + dialog_name = "EstateTrustedExperienceRemove"; + break; -// key = "setaccess" -// strings[0] = str(estate_id) -// strings[1] = str(packed_access_lists) -// strings[2] = str(num allowed agent ids) -// strings[3] = str(num allowed group ids) -// strings[4] = str(num banned agent ids) -// strings[5] = str(num estate manager agent ids) -// strings[6] = bin(uuid) -// strings[7] = bin(uuid) -// strings[8] = bin(uuid) -// ... -bool LLDispatchSetEstateAccess::operator()( - const LLDispatcher* dispatcher, - const std::string& key, - const LLUUID& invoice, - const sparam_t& strings) -{ - LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); - if (!panel) return true; + case ESTATE_EXPERIENCE_BLOCKED_ADD: + dialog_name = "EstateBlockedExperienceAdd"; + break; - S32 index = 1; // skip estate_id - U32 access_flags = strtoul(strings[index++].c_str(), NULL,10); - S32 num_allowed_agents = strtol(strings[index++].c_str(), NULL, 10); - S32 num_allowed_groups = strtol(strings[index++].c_str(), NULL, 10); - S32 num_banned_agents = strtol(strings[index++].c_str(), NULL, 10); - S32 num_estate_managers = strtol(strings[index++].c_str(), NULL, 10); + case ESTATE_EXPERIENCE_BLOCKED_REMOVE: + dialog_name = "EstateBlockedExperienceRemove"; + break; - // sanity ckecks - if (num_allowed_agents > 0 - && !(access_flags & ESTATE_ACCESS_ALLOWED_AGENTS)) - { - LL_WARNS() << "non-zero count for allowed agents, but no corresponding flag" << LL_ENDL; - } - if (num_allowed_groups > 0 - && !(access_flags & ESTATE_ACCESS_ALLOWED_GROUPS)) - { - LL_WARNS() << "non-zero count for allowed groups, but no corresponding flag" << LL_ENDL; + default: + return; } - if (num_banned_agents > 0 - && !(access_flags & ESTATE_ACCESS_BANNED_AGENTS)) + + LLSD payload; + payload["operation"] = (S32)event_type; + payload["dialog_name"] = dialog_name; + payload["allowed_ids"].append(id); + + LLSD args; + args["ALL_ESTATES"] = all_estates_text(); + + LLNotification::Params params(dialog_name); + params.payload(payload) + .substitutions(args) + .functor(LLPanelRegionExperiences::experienceCoreConfirm); + if (LLPanelEstateInfo::isLindenEstate()) { - LL_WARNS() << "non-zero count for banned agents, but no corresponding flag" << LL_ENDL; + LLNotifications::instance().forceResponse(params, 0); } - if (num_estate_managers > 0 - && !(access_flags & ESTATE_ACCESS_MANAGERS)) + else { - LL_WARNS() << "non-zero count for managers, but no corresponding flag" << LL_ENDL; + LLNotifications::instance().add(params); } - // grab the UUID's out of the string fields - if (access_flags & ESTATE_ACCESS_ALLOWED_AGENTS) - { - LLNameListCtrl* allowed_agent_name_list; - allowed_agent_name_list = panel->getChild("allowed_avatar_name_list"); + onChangeAnything(); +} - int totalAllowedAgents = num_allowed_agents; - - if (allowed_agent_name_list) - { - totalAllowedAgents += allowed_agent_name_list->getItemCount(); - } - LLStringUtil::format_map_t args; - args["[ALLOWEDAGENTS]"] = llformat ("%d", totalAllowedAgents); - args["[MAXACCESS]"] = llformat ("%d", ESTATE_MAX_ACCESS_IDS); - std::string msg = LLTrans::getString("RegionInfoAllowedResidents", args); - panel->getChild("allow_resident_label")->setValue(LLSD(msg)); +LLPanelEstateAccess::LLPanelEstateAccess() +: LLPanelRegionInfo(), mPendingUpdate(false) +{} - if (allowed_agent_name_list) - { - // Don't sort these as we add them, sort them when we are done. - allowed_agent_name_list->clearSortOrder(); - for (S32 i = 0; i < num_allowed_agents && i < ESTATE_MAX_ACCESS_IDS; i++) - { - LLUUID id; - memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ - allowed_agent_name_list->addNameItem(id); - } - allowed_agent_name_list->sortByName(TRUE); - } +BOOL LLPanelEstateAccess::postBuild() +{ + // set up the callbacks for the generic controls + initHelpBtn("estate_manager_help", "HelpEstateEstateManager"); + initHelpBtn("allow_resident_help", "HelpEstateAllowResident"); + initHelpBtn("allow_group_help", "HelpEstateAllowGroup"); + initHelpBtn("ban_resident_help", "HelpEstateBanResident"); + + getChild("allowed_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); + LLNameListCtrl *avatar_name_list = getChild("allowed_avatar_name_list"); + if (avatar_name_list) + { + avatar_name_list->setCommitOnSelectionChange(TRUE); + avatar_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS); } - if (access_flags & ESTATE_ACCESS_ALLOWED_GROUPS) + getChild("allowed_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onAllowedSearchEdit, this, _2)); + childSetAction("add_allowed_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickAddAllowedAgent, this)); + childSetAction("remove_allowed_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveAllowedAgent, this)); + childSetAction("copy_allowed_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyAllowedList, this)); + + getChild("allowed_group_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); + LLNameListCtrl* group_name_list = getChild("allowed_group_name_list"); + if (group_name_list) { - LLNameListCtrl* allowed_group_name_list; - allowed_group_name_list = panel->getChild("allowed_group_name_list"); + group_name_list->setCommitOnSelectionChange(TRUE); + group_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS); + } - LLStringUtil::format_map_t args; - args["[ALLOWEDGROUPS]"] = llformat ("%d", num_allowed_groups); - args["[MAXACCESS]"] = llformat ("%d", ESTATE_MAX_GROUP_IDS); - std::string msg = LLTrans::getString("RegionInfoAllowedGroups", args); - panel->getChild("allow_group_label")->setValue(LLSD(msg)); + getChild("allowed_group_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onAllowedGroupsSearchEdit, this, _2)); + getChild("add_allowed_group_btn")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onClickAddAllowedGroup, this)); + childSetAction("remove_allowed_group_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveAllowedGroup, this)); + childSetAction("copy_allowed_group_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyAllowedGroupList, this)); - if (allowed_group_name_list) - { - // Don't sort these as we add them, sort them when we are done. - allowed_group_name_list->clearSortOrder(); - allowed_group_name_list->deleteAllItems(); - for (S32 i = 0; i < num_allowed_groups && i < ESTATE_MAX_GROUP_IDS; i++) - { - LLUUID id; - memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ - allowed_group_name_list->addGroupNameItem(id); - } - allowed_group_name_list->sortByName(TRUE); - } + getChild("banned_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateAccess::updateChild, this, _1)); + LLNameListCtrl* banned_name_list = getChild("banned_avatar_name_list"); + if (banned_name_list) + { + banned_name_list->setCommitOnSelectionChange(TRUE); + banned_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS); } - if (access_flags & ESTATE_ACCESS_BANNED_AGENTS) + getChild("banned_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onBannedSearchEdit, this, _2)); + childSetAction("add_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickAddBannedAgent, this)); + childSetAction("remove_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveBannedAgent, this)); + childSetAction("copy_banned_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyBannedList, this)); + + getChild("estate_manager_name_list")->setCommitCallback(boost::bind(&LLPanelEstateAccess::updateChild, this, _1)); + LLNameListCtrl* manager_name_list = getChild("estate_manager_name_list"); + if (manager_name_list) { - LLNameListCtrl* banned_agent_name_list; - banned_agent_name_list = panel->getChild("banned_avatar_name_list"); + manager_name_list->setCommitOnSelectionChange(TRUE); + manager_name_list->setMaxItemCount(ESTATE_MAX_MANAGERS * 4); // Allow extras for dupe issue + } - int totalBannedAgents = num_banned_agents; - - if (banned_agent_name_list) - { - totalBannedAgents += banned_agent_name_list->getItemCount(); - } + childSetAction("add_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickAddEstateManager, this)); + childSetAction("remove_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveEstateManager, this)); + return TRUE; +} - LLStringUtil::format_map_t args; - args["[BANNEDAGENTS]"] = llformat("%d", totalBannedAgents); - args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); - std::string msg = LLTrans::getString("RegionInfoBannedResidents", args); - panel->getChild("ban_resident_label")->setValue(LLSD(msg)); +void LLPanelEstateAccess::updateControls(LLViewerRegion* region) +{ + BOOL god = gAgent.isGodlike(); + BOOL owner = (region && (region->getOwner() == gAgent.getID())); + BOOL manager = (region && region->isEstateManager()); + bool enable_cotrols = god || owner || manager; + setCtrlsEnabled(enable_cotrols); - if (banned_agent_name_list) - { - // Don't sort these as we add them, sort them when we are done. - banned_agent_name_list->clearSortOrder(); + BOOL has_allowed_avatar = getChild("allowed_avatar_name_list")->getFirstSelected() ? TRUE : FALSE; + BOOL has_allowed_group = getChild("allowed_group_name_list")->getFirstSelected() ? TRUE : FALSE; + BOOL has_banned_agent = getChild("banned_avatar_name_list")->getFirstSelected() ? TRUE : FALSE; + BOOL has_estate_manager = getChild("estate_manager_name_list")->getFirstSelected() ? TRUE : FALSE; - for (S32 i = 0; i < num_banned_agents && i < ESTATE_MAX_ACCESS_IDS; i++) - { - LLUUID id; - memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ - banned_agent_name_list->addNameItem(id); - } - banned_agent_name_list->sortByName(TRUE); - } - } + getChildView("add_allowed_avatar_btn")->setEnabled(enable_cotrols); + getChildView("remove_allowed_avatar_btn")->setEnabled(has_allowed_avatar && enable_cotrols); + getChildView("allowed_avatar_name_list")->setEnabled(enable_cotrols); - if (access_flags & ESTATE_ACCESS_MANAGERS) - { - LLStringUtil::format_map_t args; - args["[ESTATEMANAGERS]"] = llformat("%d", num_estate_managers); - args["[MAXMANAGERS]"] = llformat("%d", ESTATE_MAX_MANAGERS); - std::string msg = LLTrans::getString("RegionInfoEstateManagers", args); - panel->getChild("estate_manager_label")->setValue(LLSD(msg)); + getChildView("add_allowed_group_btn")->setEnabled(enable_cotrols); + getChildView("remove_allowed_group_btn")->setEnabled(has_allowed_group && enable_cotrols); + getChildView("allowed_group_name_list")->setEnabled(enable_cotrols); - LLNameListCtrl* estate_manager_name_list = - panel->getChild("estate_manager_name_list"); - if (estate_manager_name_list) - { - // Don't sort these as we add them, sort them when we are done. - estate_manager_name_list->clearSortOrder(); + // Can't ban people from mainland, orientation islands, etc. because this + // creates much network traffic and server load. + // Disable their accounts in CSR tool instead. + bool linden_estate = LLPanelEstateInfo::isLindenEstate(); + bool enable_ban = enable_cotrols && !linden_estate; + getChildView("add_banned_avatar_btn")->setEnabled(enable_ban); + getChildView("remove_banned_avatar_btn")->setEnabled(has_banned_agent && enable_ban); + getChildView("banned_avatar_name_list")->setEnabled(enable_cotrols); - estate_manager_name_list->deleteAllItems(); // Clear existing entries + // estate managers can't add estate managers + getChildView("add_estate_manager_btn")->setEnabled(god || owner); + getChildView("remove_estate_manager_btn")->setEnabled(has_estate_manager && (god || owner)); + getChildView("estate_manager_name_list")->setEnabled(god || owner); - // There should be only ESTATE_MAX_MANAGERS people in the list, but if the database gets more (SL-46107) don't - // truncate the list unless it's really big. Go ahead and show the extras so the user doesn't get confused, - // and they can still remove them. - for (S32 i = 0; i < num_estate_managers && i < (ESTATE_MAX_MANAGERS * 4); i++) - { - LLUUID id; - memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ - estate_manager_name_list->addNameItem(id); - } - estate_manager_name_list->sortByName(TRUE); - } + if (enable_cotrols != mCtrlsEnabled) + { + mCtrlsEnabled = enable_cotrols; + updateLists(); // update the lists on the agent's access level change } +} - // Update the buttons which may change based on the list contents but also needs to account for general access features. - panel->updateControls(gAgent.getRegion()); +//--------------------------------------------------------------------------- +// Add/Remove estate access button callbacks +//--------------------------------------------------------------------------- +void LLPanelEstateAccess::onClickAddAllowedAgent() +{ + LLCtrlListInterface *list = childGetListInterface("allowed_avatar_name_list"); + if (!list) return; + if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS) + { + //args - return true; + LLSD args; + args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); + LLNotificationsUtil::add("MaxAllowedAgentOnRegion", args); + return; + } + accessAddCore(ESTATE_ACCESS_ALLOWED_AGENT_ADD, "EstateAllowedAgentAdd"); } -LLPanelEnvironmentInfo::LLPanelEnvironmentInfo() -: mEnableEditing(false), - mRegionSettingsRadioGroup(NULL), - mDayCycleSettingsRadioGroup(NULL), - mWaterPresetCombo(NULL), - mSkyPresetCombo(NULL), - mDayCyclePresetCombo(NULL) +void LLPanelEstateAccess::onClickRemoveAllowedAgent() { + accessRemoveCore(ESTATE_ACCESS_ALLOWED_AGENT_REMOVE, "EstateAllowedAgentRemove", "allowed_avatar_name_list"); } -// virtual -BOOL LLPanelEnvironmentInfo::postBuild() +void LLPanelEstateAccess::onClickAddAllowedGroup() { - mRegionSettingsRadioGroup = getChild("region_settings_radio_group"); - mRegionSettingsRadioGroup->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSwitchRegionSettings, this)); - - mDayCycleSettingsRadioGroup = getChild("sky_dayc_settings_radio_group"); - mDayCycleSettingsRadioGroup->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSwitchDayCycle, this)); - - mWaterPresetCombo = getChild("water_settings_preset_combo"); - mWaterPresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectWaterPreset, this)); - - mSkyPresetCombo = getChild("sky_settings_preset_combo"); - mSkyPresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectSkyPreset, this)); + LLCtrlListInterface *list = childGetListInterface("allowed_group_name_list"); + if (!list) return; + if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS) + { + LLSD args; + args["MAX_GROUPS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); + LLNotificationsUtil::add("MaxAllowedGroupsOnRegion", args); + return; + } - mDayCyclePresetCombo = getChild("dayc_settings_preset_combo"); - mDayCyclePresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectDayCycle, this)); + LLNotification::Params params("ChangeLindenAccess"); + params.functor(boost::bind(&LLPanelEstateAccess::addAllowedGroup, this, _1, _2)); + if (LLPanelEstateInfo::isLindenEstate()) + { + LLNotifications::instance().add(params); + } + else + { + LLNotifications::instance().forceResponse(params, 0); + } +} - getChild("apply_btn")->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onBtnApply, this)); - //getChild("apply_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpUserPrefs, LLEnvManagerNew::getInstance())); - getChild("cancel_btn")->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onBtnCancel, this)); - //getChild("cancel_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpPresets, LLEnvManagerNew::getInstance())); +bool LLPanelEstateAccess::addAllowedGroup(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return false; - LLEnvManagerNew::instance().setRegionSettingsChangeCallback(boost::bind(&LLPanelEnvironmentInfo::onRegionSettingschange, this)); - LLEnvManagerNew::instance().setRegionSettingsAppliedCallback(boost::bind(&LLPanelEnvironmentInfo::onRegionSettingsApplied, this, _1)); + LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLDayCycleManager::instance().setModifyCallback(boost::bind(&LLPanelEnvironmentInfo::populateDayCyclesList, this)); - LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLPanelEnvironmentInfo::populateSkyPresetsList, this)); - LLWaterParamManager::instance().setPresetListChangeCallback(boost::bind(&LLPanelEnvironmentInfo::populateWaterPresetsList, this)); + LLFloaterGroupPicker* widget = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID())); + if (widget) + { + widget->removeNoneOption(); + widget->setSelectGroupCallback(boost::bind(&LLPanelEstateAccess::addAllowedGroup2, this, _1)); + if (parent_floater) + { + LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, widget); + widget->setOrigin(new_rect.mLeft, new_rect.mBottom); + parent_floater->addDependentFloater(widget); + } + } - return TRUE; + return false; } -// virtual -void LLPanelEnvironmentInfo::onOpen(const LLSD& key) +void LLPanelEstateAccess::onClickRemoveAllowedGroup() { - LL_DEBUGS("Windlight") << "Panel opened, refreshing" << LL_ENDL; - refresh(); + accessRemoveCore(ESTATE_ACCESS_ALLOWED_GROUP_REMOVE, "EstateAllowedGroupRemove", "allowed_group_name_list"); } -// virtual -void LLPanelEnvironmentInfo::handleVisibilityChange(BOOL new_visibility) +void LLPanelEstateAccess::onClickAddBannedAgent() { - // If hiding (user switched to another tab or closed the floater), - // display user's preferred environment. - if (!new_visibility) + LLCtrlListInterface *list = childGetListInterface("banned_avatar_name_list"); + if (!list) return; + if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS) { - LLEnvManagerNew::instance().usePrefs(); + LLSD args; + args["MAX_BANNED"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); + LLNotificationsUtil::add("MaxBannedAgentsOnRegion", args); + return; } + accessAddCore(ESTATE_ACCESS_BANNED_AGENT_ADD, "EstateBannedAgentAdd"); } -// virtual -bool LLPanelEnvironmentInfo::refreshFromRegion(LLViewerRegion* region) +void LLPanelEstateAccess::onClickRemoveBannedAgent() { - LL_DEBUGS("Windlight") << "Region updated, enabling/disabling controls" << LL_ENDL; - BOOL owner_or_god = gAgent.isGodlike() || (region && (region->getOwner() == gAgent.getID())); - BOOL owner_or_god_or_manager = owner_or_god || (region && region->isEstateManager()); - - // Don't refresh from region settings to avoid flicker after applying new region settings. - mEnableEditing = owner_or_god_or_manager; - setControlsEnabled(mEnableEditing); - - return LLPanelRegionInfo::refreshFromRegion(region); + accessRemoveCore(ESTATE_ACCESS_BANNED_AGENT_REMOVE, "EstateBannedAgentRemove", "banned_avatar_name_list"); } -void LLPanelEnvironmentInfo::refresh() +void LLPanelEstateAccess::onClickCopyAllowedList() { - populateWaterPresetsList(); - populateSkyPresetsList(); - populateDayCyclesList(); - - // Init radio groups. - const LLEnvironmentSettings& settings = LLEnvManagerNew::instance().getRegionSettings(); - const LLSD& dc = settings.getWLDayCycle(); - LLSD::Real first_frame_time = dc.size() > 0 ? dc[0][0].asReal() : 0.0f; - const bool use_fixed_sky = dc.size() == 1 && first_frame_time < 0; - mRegionSettingsRadioGroup->setSelectedIndex(settings.getSkyMap().size() == 0 ? 0 : 1); - mDayCycleSettingsRadioGroup->setSelectedIndex(use_fixed_sky ? 0 : 1); + copyListToClipboard("allowed_avatar_name_list"); +} - setControlsEnabled(mEnableEditing); +void LLPanelEstateAccess::onClickCopyAllowedGroupList() +{ + copyListToClipboard("allowed_group_name_list"); +} - setDirty(false); +void LLPanelEstateAccess::onClickCopyBannedList() +{ + copyListToClipboard("banned_avatar_name_list"); } -void LLPanelEnvironmentInfo::setControlsEnabled(bool enabled) +// static +void LLPanelEstateAccess::onClickAddEstateManager() { - mRegionSettingsRadioGroup->setEnabled(enabled); - mDayCycleSettingsRadioGroup->setEnabled(enabled); + LLCtrlListInterface *list = childGetListInterface("estate_manager_name_list"); + if (!list) return; + if (gHippoGridManager->getConnectedGrid()->isSecondLife() && list->getItemCount() >= ESTATE_MAX_MANAGERS) + { // Tell user they can't add more managers + LLSD args; + args["MAX_MANAGER"] = llformat("%d",ESTATE_MAX_MANAGERS); + LLNotificationsUtil::add("MaxManagersOnRegion", args); + } + else + { // Go pick managers to add + accessAddCore(ESTATE_ACCESS_MANAGER_ADD, "EstateManagerAdd"); + } +} - mWaterPresetCombo->setEnabled(enabled); - mSkyPresetCombo->setEnabled(enabled); - mDayCyclePresetCombo->setEnabled(enabled); +// static +void LLPanelEstateAccess::onClickRemoveEstateManager() +{ + accessRemoveCore(ESTATE_ACCESS_MANAGER_REMOVE, "EstateManagerRemove", "estate_manager_name_list"); +} - getChildView("apply_btn")->setEnabled(enabled); - getChildView("cancel_btn")->setEnabled(enabled); - if (enabled) +// Special case callback for groups, since it has different callback format than names +void LLPanelEstateAccess::addAllowedGroup2(LLUUID id) +{ + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (panel) { - // Enable/disable some controls based on currently selected radio buttons. - bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0; - getChild("user_environment_settings")->setEnabled(!use_defaults); + LLNameListCtrl* group_list = panel->getChild("allowed_group_name_list"); + LLScrollListItem* item = group_list->getNameItemByAgentId(id); + if (item) + { + LLSD args; + args["GROUP"] = item->getColumn(0)->getValue().asString(); + LLNotificationsUtil::add("GroupIsAlreadyInList", args); + return; + } + } + + LLSD payload; + payload["operation"] = (S32)ESTATE_ACCESS_ALLOWED_GROUP_ADD; + payload["dialog_name"] = "EstateAllowedGroupAdd"; + payload["allowed_ids"].append(id); - bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0; - mSkyPresetCombo->setEnabled(is_fixed_sky); - mDayCyclePresetCombo->setEnabled(!is_fixed_sky); + LLSD args; + args["ALL_ESTATES"] = all_estates_text(); + + LLNotification::Params params("EstateAllowedGroupAdd"); + params.payload(payload) + .substitutions(args) + .functor(accessCoreConfirm); + if (LLPanelEstateInfo::isLindenEstate()) + { + LLNotifications::instance().forceResponse(params, 0); + } + else + { + LLNotifications::instance().add(params); } } -void LLPanelEnvironmentInfo::setApplyProgress(bool started) +// static +void LLPanelEstateAccess::accessAddCore(U32 operation_flag, const std::string& dialog_name) { - LLTextBox* indicator = getChild("progress_indicator"); + LLSD payload; + payload["operation"] = (S32)operation_flag; + payload["dialog_name"] = dialog_name; + // agent id filled in after avatar picker - indicator->setVisible(started); + LLNotification::Params params("ChangeLindenAccess"); + params.payload(payload) + .functor(accessAddCore2); -/* Singu TODO: LLLoadingIndicator - if (started) + if (LLPanelEstateInfo::isLindenEstate()) { - indicator->start(); + LLNotifications::instance().add(params); } else { - indicator->stop(); + // same as clicking "OK" + LLNotifications::instance().forceResponse(params, 0); } -*/ -} - -void LLPanelEnvironmentInfo::setDirty(bool dirty) -{ - getChildView("apply_btn")->setEnabled(dirty); - getChildView("cancel_btn")->setEnabled(dirty); } -void LLPanelEnvironmentInfo::sendRegionSunUpdate() +// static +bool LLPanelEstateAccess::accessAddCore2(const LLSD& notification, const LLSD& response) { - LLRegionInfoModel& region_info = LLRegionInfoModel::instance(); - - // If the region is being switched to fixed sky, - // change the region's sun hour according to the (fixed) sun position. - // This is needed for llGetSunDirection() LSL function to work properly (STORM-1330). - const LLSD& sky_map = mNewRegionSettings.getSkyMap(); - bool region_use_fixed_sky = sky_map.size() == 1; - if (region_use_fixed_sky) + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) { - LLWLParamSet param_set; - llassert(sky_map.isMap()); - param_set.setAll(sky_map.beginMap()->second); - F32 sun_angle = param_set.getSunAngle(); - - LL_DEBUGS("Windlight Sync") << "Old sun hour: " << region_info.mSunHour << LL_ENDL; - // convert value range from 0..2pi to 6..30 - region_info.mSunHour = fmodf((sun_angle / F_TWO_PI) * 24.f, 24.f) + 6.f; + // abort change + return false; } - region_info.setUseFixedSun(region_use_fixed_sky); - region_info.mUseEstateSun = !region_use_fixed_sky; - LL_DEBUGS("Windlight Sync") << "Sun hour: " << region_info.mSunHour << LL_ENDL; + LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]); + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + LLFloater* parent_floater = panel ? gFloaterView->getParentFloater(panel) : NULL; - region_info.sendRegionTerrain(LLFloaterRegionInfo::getLastInvoice()); -} + // avatar picker yes multi-select, yes close-on-select + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateAccess::accessAddCore3, _1, _2, change_info), TRUE, TRUE); -void LLPanelEnvironmentInfo::fixEstateSun() -{ - // We don't support fixed sun estates anymore and need to fix - // such estates for region day cycle to take effect. - // *NOTE: Assuming that current estate settings have arrived already. - LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); - if (estate_info.getUseFixedSun()) + //Allows the closed parent floater to close the child floater (avatar picker) + if (child_floater) { - LL_INFOS() << "Switching estate to global sun" << LL_ENDL; - estate_info.setUseFixedSun(false); - estate_info.sendEstateInfo(); + parent_floater->addDependentFloater(child_floater); } + + return false; } -void LLPanelEnvironmentInfo::populateWaterPresetsList() +// static +void LLPanelEstateAccess::accessAddCore3(const uuid_vec_t& ids, const std::vector& names, LLEstateAccessChangeInfo* change_info) { - mWaterPresetCombo->removeall(); - - // If the region already has water params, add them to the list. - const LLEnvironmentSettings& region_settings = LLEnvManagerNew::instance().getRegionSettings(); - if (region_settings.getWaterParams().size() != 0) + if (!change_info) return; + if (ids.empty()) { - const std::string& region_name = gAgent.getRegion()->getName(); - mWaterPresetCombo->add(region_name, LLWLParamKey(region_name, LLEnvKey::SCOPE_REGION).toLLSD()); - mWaterPresetCombo->addSeparator(); + // User didn't select a name. + delete change_info; + change_info = NULL; + return; + } + // User did select a name. + change_info->mAgentOrGroupIDs = ids; + // Can't put estate owner on ban list + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLViewerRegion* region = gAgent.getRegion(); + if (!region) return; + + if (change_info->mOperationFlag & ESTATE_ACCESS_ALLOWED_AGENT_ADD) + { + LLNameListCtrl* name_list = panel->getChild("allowed_avatar_name_list"); + int currentCount = (name_list ? name_list->getItemCount() : 0); + if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS) + { + LLSD args; + args["NUM_ADDED"] = llformat("%d",ids.size()); + args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents"); + args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS); + LLNotificationsUtil::add("MaxAgentOnRegionBatch", args); + delete change_info; + return; + } + + uuid_vec_t ids_allowed; + std::vector names_allowed; + std::string already_allowed; + bool single = true; + for (U32 i = 0; i < ids.size(); ++i) + { + LLScrollListItem* item = name_list->getNameItemByAgentId(ids[i]); + if (item) + { + if (!already_allowed.empty()) + { + already_allowed += ", "; + single = false; + } + already_allowed += item->getColumn(0)->getValue().asString(); + } + else + { + ids_allowed.push_back(ids[i]); + names_allowed.push_back(names[i]); + } + } + if (!already_allowed.empty()) + { + LLSD args; + args["AGENT"] = already_allowed; + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents"); + LLNotificationsUtil::add(single ? "AgentIsAlreadyInList" : "AgentsAreAlreadyInList", args); + if (ids_allowed.empty()) + { + delete change_info; + return; + } + } + change_info->mAgentOrGroupIDs = ids_allowed; + change_info->mAgentNames = names_allowed; } + if (change_info->mOperationFlag & ESTATE_ACCESS_BANNED_AGENT_ADD) + { + LLNameListCtrl* name_list = panel->getChild("banned_avatar_name_list"); + LLNameListCtrl* em_list = panel->getChild("estate_manager_name_list"); + int currentCount = (name_list ? name_list->getItemCount() : 0); + if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS) + { + LLSD args; + args["NUM_ADDED"] = llformat("%d",ids.size()); + args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents"); + args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS); + LLNotificationsUtil::add("MaxAgentOnRegionBatch", args); + delete change_info; + return; + } + + uuid_vec_t ids_allowed; + std::vector names_allowed; + std::string already_banned; + std::string em_ban; + bool single = true; + for (U32 i = 0; i < ids.size(); ++i) + { + bool is_allowed = true; + LLScrollListItem* em_item = em_list->getNameItemByAgentId(ids[i]); + if (em_item) + { + if (!em_ban.empty()) + { + em_ban += ", "; + } + em_ban += em_item->getColumn(0)->getValue().asString(); + is_allowed = false; + } - std::list user_presets, system_presets; - LLWaterParamManager::instance().getPresetNames(user_presets, system_presets); + LLScrollListItem* item = name_list->getNameItemByAgentId(ids[i]); + if (item) + { + if (!already_banned.empty()) + { + already_banned += ", "; + single = false; + } + already_banned += item->getColumn(0)->getValue().asString(); + is_allowed = false; + } - // Add local user presets first. - for (std::list::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it) - { - mWaterPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD()); + if (is_allowed) + { + ids_allowed.push_back(ids[i]); + names_allowed.push_back(names[i]); + } + } + if (!em_ban.empty()) + { + LLSD args; + args["AGENT"] = em_ban; + LLNotificationsUtil::add("ProblemBanningEstateManager", args); + if (ids_allowed.empty()) + { + delete change_info; + return; + } + } + if (!already_banned.empty()) + { + LLSD args; + args["AGENT"] = already_banned; + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents"); + LLNotificationsUtil::add(single ? "AgentIsAlreadyInList" : "AgentsAreAlreadyInList", args); + if (ids_allowed.empty()) + { + delete change_info; + return; + } + } + change_info->mAgentOrGroupIDs = ids_allowed; + change_info->mAgentNames = names_allowed; } - if (user_presets.size() > 0) + LLSD args; + args["ALL_ESTATES"] = all_estates_text(); + LLNotification::Params params(change_info->mDialogName); + params.substitutions(args) + .payload(change_info->asLLSD()) + .functor(accessCoreConfirm); + + if (LLPanelEstateInfo::isLindenEstate()) { - mWaterPresetCombo->addSeparator(); + // just apply to this estate + LLNotifications::instance().forceResponse(params, 0); } - - // Add local system presets. - for (std::list::const_iterator it = system_presets.begin(); it != system_presets.end(); ++it) + else { - mWaterPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD()); + // ask if this estate or all estates with this owner + LLNotifications::instance().add(params); } - - // There's no way to select current preset because its name is not stored on server. } -void LLPanelEnvironmentInfo::populateSkyPresetsList() +// static +void LLPanelEstateAccess::accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name) { - mSkyPresetCombo->removeall(); + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLNameListCtrl* name_list = panel->getChild(list_ctrl_name); + if (!name_list) return; - LLWLParamManager::preset_name_list_t region_presets; - LLWLParamManager::preset_name_list_t user_presets, sys_presets; - LLWLParamManager::instance().getPresetNames(region_presets, user_presets, sys_presets); + std::vector list_vector = name_list->getAllSelected(); + if (list_vector.size() == 0) + return; - // Add region presets. - std::string region_name = gAgent.getRegion() ? gAgent.getRegion()->getName() : LLTrans::getString("Unknown"); - for (LLWLParamManager::preset_name_list_t::const_iterator it = region_presets.begin(); it != region_presets.end(); ++it) + LLSD payload; + payload["operation"] = (S32)operation_flag; + payload["dialog_name"] = dialog_name; + + for (std::vector::const_iterator iter = list_vector.begin(); + iter != list_vector.end(); + iter++) { - std::string preset_name = *it; - std::string item_title = preset_name + " (" + region_name + ")"; - mSkyPresetCombo->add(item_title, LLWLParamKey(preset_name, LLEnvKey::SCOPE_REGION).toStringVal()); + LLScrollListItem *item = (*iter); + payload["allowed_ids"].append(item->getUUID()); } + + LLNotification::Params params("ChangeLindenAccess"); + params.payload(payload) + .functor(accessRemoveCore2); - if (!region_presets.empty()) + if (LLPanelEstateInfo::isLindenEstate()) { - mSkyPresetCombo->addSeparator(); + // warn on change linden estate + LLNotifications::instance().add(params); } - - // Add user presets. - for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it) + else { - mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal()); + // just proceed, as if clicking OK + LLNotifications::instance().forceResponse(params, 0); } +} - if (!user_presets.empty()) +// static +bool LLPanelEstateAccess::accessRemoveCore2(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) { - mSkyPresetCombo->addSeparator(); + // abort + return false; } - // Add system presets. - for (LLWLParamManager::preset_name_list_t::const_iterator it = sys_presets.begin(); it != sys_presets.end(); ++it) + // If Linden estate, can only apply to "this" estate, not all estates + // owned by NULL. + if (LLPanelEstateInfo::isLindenEstate()) { - mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal()); + accessCoreConfirm(notification, response); } - - // Select current preset. - LLSD sky_map = LLEnvManagerNew::instance().getRegionSettings().getSkyMap(); - if (sky_map.size() == 1) // if the region is set to fixed sky + else { - std::string preset_name = sky_map.beginMap()->first; - mSkyPresetCombo->selectByValue(LLWLParamKey(preset_name, LLEnvKey::SCOPE_REGION).toStringVal()); + LLSD args; + args["ALL_ESTATES"] = all_estates_text(); + LLNotificationsUtil::add(notification["payload"]["dialog_name"], + args, + notification["payload"], + accessCoreConfirm); } + return false; } -void LLPanelEnvironmentInfo::populateDayCyclesList() +// Used for both access add and remove operations, depending on the mOperationFlag +// passed in (ESTATE_ACCESS_BANNED_AGENT_ADD, ESTATE_ACCESS_ALLOWED_AGENT_REMOVE, etc.) +// static +bool LLPanelEstateAccess::accessCoreConfirm(const LLSD& notification, const LLSD& response) { - mDayCyclePresetCombo->removeall(); - - // If the region already has env. settings, add its day cycle to the list. - const LLSD& cur_region_dc = LLEnvManagerNew::instance().getRegionSettings().getWLDayCycle(); - if (cur_region_dc.size() != 0) - { - LLViewerRegion* region = gAgent.getRegion(); - llassert(region != NULL); - - LLWLParamKey key(region->getName(), LLEnvKey::SCOPE_REGION); - mDayCyclePresetCombo->add(region->getName(), key.toStringVal()); - mDayCyclePresetCombo->addSeparator(); - } + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger(); + U32 flags = originalFlags; - // Add local user day cycles. - LLDayCycleManager::preset_name_list_t user_days, sys_days; - LLDayCycleManager::instance().getPresetNames(user_days, sys_days); - for (LLDayCycleManager::preset_name_list_t::const_iterator it = user_days.begin(); it != user_days.end(); ++it) + LLViewerRegion* region = gAgent.getRegion(); + + if (option == 2) // cancel { - mDayCyclePresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal()); + return false; } - - if (user_days.size() > 0) + else if (option == 1) { - mDayCyclePresetCombo->addSeparator(); + // All estates, either than I own or manage for this owner. + // This will be verified on simulator. JC + if (!region) return false; + if (region->getOwner() == gAgent.getID() + || gAgent.isGodlike()) + { + flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES; + } + else if (region->isEstateManager()) + { + flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES; + } } - // Add local system day cycles. - for (LLDayCycleManager::preset_name_list_t::const_iterator it = sys_days.begin(); it != sys_days.end(); ++it) + std::string names; + U32 listed_names = 0; + const auto& ids = notification["payload"]["allowed_ids"]; + const auto& allowed_names = notification["payload"]["allowed_names"]; + U32 size = ids.size(); + for (U32 i = 0; i < size; ++i) { - mDayCyclePresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal()); - } + if (i + 1 != size) + { + flags |= ESTATE_ACCESS_NO_REPLY; + } + else + { + flags &= ~ESTATE_ACCESS_NO_REPLY; + } - // Current day cycle is already selected. -} + const LLUUID id = ids[i].asUUID(); + if (((U32)notification["payload"]["operation"].asInteger() & ESTATE_ACCESS_BANNED_AGENT_ADD) + && region && (region->getOwner() == id)) + { + LLNotificationsUtil::add("OwnerCanNotBeDenied"); + break; + } -bool LLPanelEnvironmentInfo::getSelectedWaterParams(LLSD& water_params) -{ - LLWLParamKey water_key(mWaterPresetCombo->getSelectedValue()); + sendEstateAccessDelta(flags, id); - if (water_key.scope == LLEnvKey::SCOPE_REGION) + if ((flags & (ESTATE_ACCESS_ALLOWED_GROUP_ADD | ESTATE_ACCESS_ALLOWED_GROUP_REMOVE)) == 0) + { + // fill the name list for confirmation + if (listed_names < MAX_LISTED_NAMES) + { + if (!names.empty()) + { + names += ", "; + } + const auto& display_name = allowed_names[i]["display_name"].asStringRef(); + if (!display_name.empty()) + { + names += display_name; + } + else + { //try to get an agent name from cache + LLAvatarName av_name; + if (LLAvatarNameCache::get(id, &av_name)) + { + names += av_name.getCompleteName(); + } + } + + } + listed_names++; + } + } + if (listed_names > MAX_LISTED_NAMES) { - water_params = LLEnvManagerNew::instance().getRegionSettings().getWaterParams(); + LLSD args; + args["EXTRA_COUNT"] = llformat("%d", listed_names - MAX_LISTED_NAMES); + names += " " + LLTrans::getString("AndNMore", args); } - else + + if (!names.empty()) // show the conirmation { - LLWaterParamSet param_set; - if (!LLWaterParamManager::instance().getParamSet(water_key.name, param_set)) + LLSD args; + args["AGENT"] = names; + + if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE)) { - LL_WARNS() << "Error getting water preset: " << water_key.name << LL_ENDL; - return false; + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents"); + } + else if (flags & (ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_BANNED_AGENT_REMOVE)) + { + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents"); } - water_params = param_set.getAll(); + if (flags & ESTATE_ACCESS_APPLY_TO_ALL_ESTATES) + { + args["ESTATE"] = LLTrans::getString("RegionInfoAllEstates"); + } + else if (flags & ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES) + { + args["ESTATE"] = LLTrans::getString("RegionInfoManagedEstates"); + } + else + { + args["ESTATE"] = LLTrans::getString("RegionInfoThisEstate"); + } + + bool single = (listed_names == 1); + if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_ADD | ESTATE_ACCESS_BANNED_AGENT_ADD)) + { + LLNotificationsUtil::add(single ? "AgentWasAddedToList" : "AgentsWereAddedToList", args); + } + else if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_BANNED_AGENT_REMOVE)) + { + LLNotificationsUtil::add(single ? "AgentWasRemovedFromList" : "AgentsWereRemovedFromList", args); + } } - return true; + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (panel) + { + panel->setPendingUpdate(true); + } + + return false; } -bool LLPanelEnvironmentInfo::getSelectedSkyParams(LLSD& sky_params, std::string& preset_name) +// key = "estateaccessdelta" +// str(estate_id) will be added to front of list by forward_EstateOwnerRequest_to_dataserver +// str[0] = str(agent_id) requesting the change +// str[1] = str(flags) (ESTATE_ACCESS_DELTA_*) +// str[2] = str(agent_id) to add or remove +// static +void LLPanelEstateAccess::sendEstateAccessDelta(U32 flags, const LLUUID& agent_or_group_id) { - std::string preset_key(mSkyPresetCombo->getValue().asString()); - LLWLParamKey preset(preset_key); + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("EstateOwnerMessage"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used - // Get the preset sky params. - LLWLParamSet param_set; - if (!LLWLParamManager::instance().getParamSet(preset, param_set)) - { - LL_WARNS() << "Error getting sky params: " << preset.toLLSD() << LL_ENDL; - return false; - } + msg->nextBlock("MethodData"); + msg->addString("Method", "estateaccessdelta"); + msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice()); - sky_params = param_set.getAll(); - preset_name = preset.name; - return true; -} + std::string buf; + gAgent.getID().toString(buf); + msg->nextBlock("ParamList"); + msg->addString("Parameter", buf); + + buf = llformat("%u", flags); + msg->nextBlock("ParamList"); + msg->addString("Parameter", buf); + + agent_or_group_id.toString(buf); + msg->nextBlock("ParamList"); + msg->addString("Parameter", buf); -bool LLPanelEnvironmentInfo::getSelectedDayCycleParams(LLSD& day_cycle, LLSD& sky_map, short& scope) -{ - std::string preset_key(mDayCyclePresetCombo->getValue().asString()); - LLWLParamKey dc(preset_key); - LL_DEBUGS("Windlight") << "Use day cycle: " << dc.toLLSD() << LL_ENDL; - if (dc.scope == LLEnvKey::SCOPE_REGION) // current region day cycle - { - const LLEnvironmentSettings& cur_region_settings = LLEnvManagerNew::instance().getRegionSettings(); - day_cycle = cur_region_settings.getWLDayCycle(); - sky_map = cur_region_settings.getSkyMap(); - } - else // a local day cycle + if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | + ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_BANNED_AGENT_REMOVE)) { - if (!LLDayCycleManager::instance().getPreset(dc.name, day_cycle)) - { - LL_WARNS() << "Error getting day cycle " << dc.name << LL_ENDL; - return false; - } - - // Create sky map from the day cycle. + if (auto panel = LLFloaterRegionInfo::getPanelAccess()) { - LLWLDayCycle tmp_day; - tmp_day.loadDayCycle(day_cycle, dc.scope); - tmp_day.getSkyMap(sky_map); + // Clear these out before we ask for an update + if (auto name_list = panel->getChild("allowed_avatar_name_list")) + name_list->deleteAllItems(); + if (auto name_list = panel->getChild("banned_avatar_name_list")) + name_list->deleteAllItems(); } } - scope = dc.scope; - - return true; + gAgent.sendReliableMessage(); } -void LLPanelEnvironmentInfo::onSwitchRegionSettings() + +void LLPanelEstateAccess::updateChild(LLUICtrl* child_ctrl) { - bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0; - getChild("user_environment_settings")->setEnabled(!use_defaults); + // Ensure appropriate state of the management ui. + updateControls(gAgent.getRegion()); +} - if (use_defaults) +struct RequestEstateGetAccessResponder : public LLHTTPClient::ResponderWithCompleted +{ + void httpCompleted() override { - LLEnvManagerNew::instance().useDefaults(); + LLPanelEstateAccess::onEstateAccessReceived(mContent); } - else + char const* getName() const override { return "requestEstateGetAccessCoro"; } +}; + +void LLPanelEstateAccess::updateLists() +{ + std::string cap_url = gAgent.getRegionCapability("EstateAccess"); + if (!cap_url.empty()) { - onSelectWaterPreset(); - onSwitchDayCycle(); + LLHTTPClient::get(cap_url, new RequestEstateGetAccessResponder); + } +} +/* + LLCoros::instance().launch("LLFloaterRegionInfo::requestEstateGetAccessCoro", boost::bind(LLPanelEstateAccess::requestEstateGetAccessCoro, cap_url)); } - - setDirty(true); } -void LLPanelEnvironmentInfo::onSwitchDayCycle() +void LLPanelEstateAccess::requestEstateGetAccessCoro(std::string url) { - bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0; + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestEstateGetAccessoCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - mSkyPresetCombo->setEnabled(is_fixed_sky); - mDayCyclePresetCombo->setEnabled(!is_fixed_sky); + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); - if (is_fixed_sky) - { - onSelectSkyPreset(); - } - else - { - onSelectDayCycle(); - } + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - setDirty(true); + onEstateAccessReceived(result); } +*/ -void LLPanelEnvironmentInfo::onSelectWaterPreset() +const std::string& getNAString() { - LLSD water_params; - - if (getSelectedWaterParams(water_params)) - { - LLEnvManagerNew::instance().useWaterParams(water_params); - } - - setDirty(true); + static const auto na = LLTrans::getString("na"); + return na; } -void LLPanelEnvironmentInfo::onSelectSkyPreset() +#if defined(__GNUC__) && __GNUC__ < 5 // On GCC 4, implement std::get_time using strptime +#include + +namespace std { - LLSD params; - std::string dummy; + struct get_time + { + tm* mTime; + const char* mFmt; + get_time(tm* time, const char* fmt) : mTime(time), mFmt(fmt) {} + }; - if (getSelectedSkyParams(params, dummy)) + istringstream& operator>>(istringstream&& str, get_time&& rhs) { - LLEnvManagerNew::instance().useSkyParams(params); + if (!strptime(str.str().data(), rhs.mFmt, rhs.mTime)) + str.setstate(ios_base::failbit); + return str; } - - setDirty(true); } +#endif -void LLPanelEnvironmentInfo::onSelectDayCycle() +void handlePseudoISO8601(const std::string& date_str, LLSD& column, const std::string& fmt) { - LLSD day_cycle; - LLSD sky_map; // unused - short scope; - - if (getSelectedDayCycleParams(day_cycle, sky_map, scope)) + if (date_str.front() == '0') // server returns the "0000-00-00 00:00:00" date in case it doesn't know it { - LLEnvManagerNew::instance().useDayCycleParams(day_cycle, (LLEnvKey::EScope) scope); + column["value"] = getNAString(); + } + else + { + std::tm time = {}; + if (std::istringstream(date_str) >> std::get_time(&time, "%F %T")) + { + column["value"] = LLDate(mktime(&time)); + column["type"] = "date"; + column["format"] = fmt; + } + else column["value"] = date_str; } - - setDirty(true); } - -void LLPanelEnvironmentInfo::onBtnApply() +void LLPanelEstateAccess::onEstateAccessReceived(const LLSD& result) { - const bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0; - const bool use_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0; - - LLSD day_cycle; - LLSD sky_map; - LLSD water_params; - - if (use_defaults) + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + + LLNameListCtrl* allowed_agent_name_list = panel->getChild("allowed_avatar_name_list"); + if (allowed_agent_name_list && result.has("AllowedAgents")) { - // settings will be empty - LL_DEBUGS("Windlight") << "Defaults" << LL_ENDL; + LLStringUtil::format_map_t args; + args["[ALLOWEDAGENTS]"] = llformat("%d", result["AllowedAgents"].size()); + args["[MAXACCESS]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); + std::string msg = LLTrans::getString("RegionInfoAllowedResidents", args); + panel->getChild("allow_resident_label")->setValue(LLSD(msg)); + + const auto order = allowed_agent_name_list->getSortOrder(); + allowed_agent_name_list->clearSortOrder(); + allowed_agent_name_list->deleteAllItems(); + for (auto const& entry : result["AllowedAgents"].array()) + { + LLUUID id = entry["id"].asUUID(); + allowed_agent_name_list->addNameItem(id); + } + allowed_agent_name_list->setSortOrder(order); } - else // use custom region settings + + LLNameListCtrl* banned_agent_name_list = panel->getChild("banned_avatar_name_list"); + if (banned_agent_name_list && result.has("BannedAgents")) { - if (use_fixed_sky) + LLStringUtil::format_map_t args; + args["[BANNEDAGENTS]"] = llformat("%d", result["BannedAgents"].size()); + args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); + std::string msg = LLTrans::getString("RegionInfoBannedResidents", args); + panel->getChild("ban_resident_label")->setValue(LLSD(msg)); + + const auto format = gSavedSettings.getString("ShortDateFormat"); + const auto order = banned_agent_name_list->getSortOrder(); + banned_agent_name_list->clearSortOrder(); + banned_agent_name_list->deleteAllItems(); + for (auto const& entry : result["BannedAgents"].array()) { - LL_DEBUGS("Windlight") << "Use fixed sky" << LL_ENDL; + LLSD item; + item["id"] = entry["id"].asUUID(); + LLSD& columns = item["columns"]; - // Get selected sky params. - LLSD params; - std::string preset_name; - if (!getSelectedSkyParams(params, preset_name)) - { - return; - } + columns[0]["column"] = "name"; // to be populated later - // Create a day cycle consisting of a single sky preset. - LLSD key(LLSD::emptyArray()); - key.append(-1.0f); // indicate that user preference is actually fixed sky, not a day cycle - key.append(preset_name); - day_cycle.append(key); + auto& col = columns[1]; + col["column"] = "last_login_date"; + handlePseudoISO8601(entry["last_login_date"].asString(), col, format); - // Create a sky map consisting of only the sky preset. - std::map refs; - LLWLParamSet param_set; - param_set.setAll(params); - refs[LLWLParamKey(preset_name, LLEnvKey::SCOPE_LOCAL)] = param_set; // scope doesn't matter here - sky_map = LLWLParamManager::createSkyMap(refs); - } - else // use day cycle - { - LL_DEBUGS("Windlight") << "Use day cycle" << LL_ENDL; + columns[2]["column"] = "ban_date"; + handlePseudoISO8601(entry["ban_date"].asString(), columns[2], format); - short scope; // unused - if (!getSelectedDayCycleParams(day_cycle, sky_map, scope)) + columns[3]["column"] = "bannedby"; + LLUUID banning_id = entry["banning_id"].asUUID(); + LLAvatarName av_name; + if (banning_id.isNull()) { - return; + columns[3]["value"] = getNAString(); } - - // If it's a special single-preset day cycle meaning using a fixed sky, - // reset the frame time to a non-negative value, - // so that the region setting is displayed in the floater as - // a day cycle, not a preset. (STORM-1289) - if (day_cycle.size() == 1 && day_cycle[0][0].asReal() < 0.0f) + else if (LLAvatarNameCache::get(banning_id, &av_name)) { - LL_DEBUGS("Windlight") << "Fixing negative time" << LL_ENDL; - day_cycle[0][0] = 0.0f; + columns[3]["value"] = av_name.getCompleteName(); //TODO: fetch the name if it wasn't cached } + + banned_agent_name_list->addElement(item); } + banned_agent_name_list->setSortOrder(order); + } - // Get water params. - if (!getSelectedWaterParams(water_params)) + LLNameListCtrl* allowed_group_name_list = panel->getChild("allowed_group_name_list"); + if (allowed_group_name_list && result.has("AllowedGroups")) + { + LLStringUtil::format_map_t args; + args["[ALLOWEDGROUPS]"] = llformat("%d", result["AllowedGroups"].size()); + args["[MAXACCESS]"] = llformat("%d", ESTATE_MAX_GROUP_IDS); + std::string msg = LLTrans::getString("RegionInfoAllowedGroups", args); + panel->getChild("allow_group_label")->setValue(LLSD(msg)); + + const auto order = allowed_group_name_list->getSortOrder(); + allowed_group_name_list->clearSortOrder(); + allowed_group_name_list->deleteAllItems(); + for (auto const& entry : result["AllowedGroups"].array()) { - // *TODO: show a notification? - return; + LLUUID id = entry["id"].asUUID(); + allowed_group_name_list->addGroupNameItem(id); } + allowed_group_name_list->setSortOrder(order); } - // Send settings apply request. - LLEnvironmentSettings new_region_settings; - new_region_settings.saveParams(day_cycle, sky_map, water_params, 0.0f); - if (!LLEnvManagerNew::instance().sendRegionSettings(new_region_settings)) + LLNameListCtrl* estate_manager_name_list = panel->getChild("estate_manager_name_list"); + if (estate_manager_name_list && result.has("Managers")) { - LL_WARNS() << "Error applying region environment settings" << LL_ENDL; - return; + LLStringUtil::format_map_t args; + args["[ESTATEMANAGERS]"] = llformat("%d", result["Managers"].size()); + args["[MAXMANAGERS]"] = llformat("%d", ESTATE_MAX_MANAGERS); + std::string msg = LLTrans::getString("RegionInfoEstateManagers", args); + panel->getChild("estate_manager_label")->setValue(LLSD(msg)); + + const auto order = estate_manager_name_list->getSortOrder(); + estate_manager_name_list->clearSortOrder(); + estate_manager_name_list->deleteAllItems(); + for (auto const& entry : result["Managers"].array()) + { + LLUUID id = entry["agent_id"].asUUID(); + estate_manager_name_list->addNameItem(id); + } + estate_manager_name_list->setSortOrder(order); } - // When the settings get applied, we'll also send the region sun position update. - // To determine the sun angle we're going to need the new settings. - mNewRegionSettings = new_region_settings; - // Start spinning the progress indicator. - setApplyProgress(true); + panel->updateControls(gAgent.getRegion()); } -void LLPanelEnvironmentInfo::onBtnCancel() +//--------------------------------------------------------------------------- +// Access lists search +//--------------------------------------------------------------------------- +void LLPanelEstateAccess::onAllowedSearchEdit(const std::string& search_string) { - // Reload last saved region settings. - refresh(); + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLNameListCtrl* allowed_agent_name_list = panel->getChild("allowed_avatar_name_list"); + searchAgent(allowed_agent_name_list, search_string); +} - // Apply them. - LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance(); - const LLEnvironmentSettings& cur_settings = env_mgr.getRegionSettings(); - const LLSD& region_day_cycle = cur_settings.getWLDayCycle(); - const LLSD& region_water = cur_settings.getWaterParams(); - env_mgr.useWaterParams(region_water); - env_mgr.useDayCycleParams(region_day_cycle, LLEnvKey::SCOPE_REGION); +void LLPanelEstateAccess::onAllowedGroupsSearchEdit(const std::string& search_string) +{ + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLNameListCtrl* allowed_group_name_list = panel->getChild("allowed_group_name_list"); + searchAgent(allowed_group_name_list, search_string); } -void LLPanelEnvironmentInfo::onRegionSettingschange() +void LLPanelEstateAccess::onBannedSearchEdit(const std::string& search_string) { - LL_DEBUGS("Windlight") << "Region settings changed, refreshing" << LL_ENDL; - refresh(); + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLNameListCtrl* banned_agent_name_list = panel->getChild("banned_avatar_name_list"); + searchAgent(banned_agent_name_list, search_string); +} - // Stop applying progress indicator (it may be running if it's us who initiated settings update). - setApplyProgress(false); +void LLPanelEstateAccess::searchAgent(LLNameListCtrl* listCtrl, const std::string& search_string) +{ + if (!listCtrl) return; + listCtrl->setFilter(search_string); } -void LLPanelEnvironmentInfo::onRegionSettingsApplied(bool ok) +void LLPanelEstateAccess::copyListToClipboard(std::string list_name) { - // If applying new settings has failed, stop the indicator right away. - // Otherwise it will be stopped when we receive the updated settings from server. - if (ok) - { - // Set the region sun phase/flags according to the chosen new preferences. - // - // If we do this earlier we may get jerky transition from fixed sky to a day cycle (STORM-1481). - // That is caused by the simulator re-sending the region info, which in turn makes us - // re-request and display old region environment settings while the new ones haven't been applied yet. - sendRegionSunUpdate(); + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLNameListCtrl* name_list = panel->getChild(list_name); + if (!name_list) return; - // Switch estate to not using fixed sun for the region day cycle to work properly (STORM-1506). - fixEstateSun(); - } - else - { - setApplyProgress(false); + std::vector list_vector = name_list->getAllData(); + if (list_vector.size() == 0) return; - // We need to re-request environment setting here, - // otherwise our subsequent attempts to change region settings will fail with the following error: - // "Unable to update environment settings because the last update your viewer saw was not the same - // as the last update sent from the simulator. Try sending your update again, and if this - // does not work, try leaving and returning to the region." - LLEnvManagerNew::instance().requestRegionSettings(); + LLSD::String list_to_copy; + for (std::vector::const_iterator iter = list_vector.begin(); + iter != list_vector.end(); + iter++) + { + LLScrollListItem *item = (*iter); + if (item) + { + list_to_copy += item->getColumn(0)->getValue().asString(); + } + if (std::next(iter) != list_vector.end()) + { + list_to_copy += '\n'; + } } + + auto wstr = utf8str_to_wstring(list_to_copy); + gClipboard.copyFromSubstring(wstr, 0, wstr.length()); +} + +bool LLPanelEstateAccess::refreshFromRegion(LLViewerRegion* region) +{ + // Clear these out before we ask for an update + if (auto name_list = getChild("allowed_avatar_name_list")) + name_list->deleteAllItems(); + if (auto name_list = getChild("banned_avatar_name_list")) + name_list->deleteAllItems(); + + updateLists(); + return LLPanelRegionInfo::refreshFromRegion(region); } + // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) void LLFloaterRegionInfo::open() { @@ -3630,10 +4445,11 @@ void LLFloaterRegionInfo::open() { const LLViewerRegion* region(gAgent.getRegion()); // Should be able to call LLRegion::canManageEstate() but then we can fake god like - if (!(region && region->isEstateManager() && region->getOwner() == gAgentID)) + if (!region || !region->isEstateManager() || region->getOwner() != gAgentID) return; } LLFloater::open(); } // [/RLVa:KB] + diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index beb6893e1d..0a5840116c 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -3,31 +3,25 @@ * @author Aaron Brashears * @brief Declaration of the region info and controls floater and panels. * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -35,12 +29,14 @@ #define LL_LLFLOATERREGIONINFO_H #include +#include "llagent.h" #include "llfloater.h" #include "llpanel.h" #include "llenvmanager.h" // for LLEnvironmentSettings class LLAvatarName; +class LLDispatcher; struct LLEstateAccessChangeInfo; class LLLineEditor; class LLMessageSystem; @@ -56,6 +52,7 @@ class LLRadioGroup; class LLSliderCtrl; class LLSpinCtrl; class LLTextBox; +class LLVFS; class AIFilePicker; class LLPanelRegionGeneralInfo; @@ -63,18 +60,29 @@ class LLPanelRegionDebugInfo; class LLPanelRegionTerrainInfo; class LLPanelEstateInfo; class LLPanelEstateCovenant; - +class LLPanelExperienceListEditor; +class LLPanelExperiences; +class LLPanelRegionExperiences; +class LLPanelEstateAccess; + +class LLEventTimer; +class LLEnvironmentSettings; +class LLWLParamManager; +class LLWaterParamManager; +class LLWLParamSet; +class LLWaterParamSet; class LLFloaterRegionInfo : public LLFloater, public LLFloaterSingleton { - friend class LLUISingleton >; + friend class LLUISingleton>; public: - /*virtual*/ void onOpen(); - /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(/*const LLSD& key*/) override; + /*virtual*/ void onClose(bool app_quitting) override; + /*virtual*/ BOOL postBuild() override; // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) - /*virtual*/ void open(); + /*virtual*/ void open() override; // [/RLVa:KB] static void processEstateOwnerRequest(LLMessageSystem* msg, void**); @@ -88,11 +96,13 @@ class LLFloaterRegionInfo : public LLFloater, public LLFloaterSingleton& names); @@ -231,9 +247,9 @@ class LLPanelRegionTerrainInfo : public LLPanelRegionInfo LLPanelRegionTerrainInfo() : LLPanelRegionInfo() {} ~LLPanelRegionTerrainInfo() {} - virtual BOOL postBuild(); // LLPanel + BOOL postBuild() override; // LLPanel - virtual bool refreshFromRegion(LLViewerRegion* region); // refresh local settings from region update from simulator + bool refreshFromRegion(LLViewerRegion* region) override; // refresh local settings from region update from simulator void setEnvControls(bool available); // Whether environment settings are available for this region BOOL validateTextureSizes(); @@ -242,7 +258,7 @@ class LLPanelRegionTerrainInfo : public LLPanelRegionInfo //static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button - virtual BOOL sendUpdate(); + BOOL sendUpdate() override; static void onClickDownloadRaw(void*); void onClickDownloadRaw_continued(AIFilePicker* filepicker); @@ -261,41 +277,18 @@ class LLPanelEstateInfo : public LLPanelRegionInfo void onChangeFixedSun(); void onChangeUseGlobalTime(); + void onChangeAccessOverride(); void onClickEditSky(); void onClickEditSkyHelp(); void onClickEditDayCycle(); void onClickEditDayCycleHelp(); - void onClickAddAllowedAgent(); - void onClickRemoveAllowedAgent(); - void onClickAddAllowedGroup(); - void onClickRemoveAllowedGroup(); - void onClickAddBannedAgent(); - void onClickRemoveBannedAgent(); - void onClickAddEstateManager(); - void onClickRemoveEstateManager(); void onClickKickUser(); - // Group picker callback is different, can't use core methods below - bool addAllowedGroup(const LLSD& notification, const LLSD& response); - void addAllowedGroup2(LLUUID id); - // Core methods for all above add/remove button clicks - static void accessAddCore(U32 operation_flag, const std::string& dialog_name); - static bool accessAddCore2(const LLSD& notification, const LLSD& response); - static void accessAddCore3(const uuid_vec_t& ids, LLEstateAccessChangeInfo* change_info); - - static void accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name); - static bool accessRemoveCore2(const LLSD& notification, const LLSD& response); - - // used for both add and remove operations - static bool accessCoreConfirm(const LLSD& notification, const LLSD& response); bool kickUserConfirm(const LLSD& notification, const LLSD& response); - // Send the actual EstateOwnerRequest "estateaccessdelta" message - static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id); - void onKickUserCommit(const uuid_vec_t& ids, const std::vector& names); static void onClickMessageEstate(void* data); bool onMessageCommit(const LLSD& notification, const LLSD& response); @@ -306,32 +299,30 @@ class LLPanelEstateInfo : public LLPanelRegionInfo void updateControls(LLViewerRegion* region); static void updateEstateName(const std::string& name); - static void updateEstateOwnerName(const std::string& name); + static void updateEstateOwnerID(const LLUUID& id); - virtual bool refreshFromRegion(LLViewerRegion* region); - virtual bool estateUpdate(LLMessageSystem* msg); + bool refreshFromRegion(LLViewerRegion* region) override; + bool estateUpdate(LLMessageSystem* msg) override; // LLPanel - virtual BOOL postBuild(); - virtual void updateChild(LLUICtrl* child_ctrl); - virtual void refresh(); + BOOL postBuild() override; + void updateChild(LLUICtrl* child_ctrl) override; + void refresh() override; void refreshFromEstate(); static bool isLindenEstate(); const std::string getOwnerName() const; - void setOwnerName(const std::string& name); protected: - virtual BOOL sendUpdate(); + BOOL sendUpdate() override; // confirmation dialog callback bool callbackChangeLindenEstate(const LLSD& notification, const LLSD& response); void commitEstateAccess(); void commitEstateManagers(); - void clearAccessLists(); BOOL checkSunHourSlider(LLUICtrl* child_ctrl); U32 mEstateID; @@ -346,16 +337,16 @@ class LLPanelEstateCovenant : public LLPanelRegionInfo ~LLPanelEstateCovenant() {} // LLPanel - virtual BOOL postBuild(); - virtual void updateChild(LLUICtrl* child_ctrl); - virtual bool refreshFromRegion(LLViewerRegion* region); - virtual bool estateUpdate(LLMessageSystem* msg); + BOOL postBuild() override; + void updateChild(LLUICtrl* child_ctrl) override; + bool refreshFromRegion(LLViewerRegion* region) override; + bool estateUpdate(LLMessageSystem* msg) override; // LLView overrides BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, - std::string& tooltip_msg); + std::string& tooltip_msg) override; static bool confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response); static void resetCovenantID(void* userdata); static bool confirmResetCovenantCallback(const LLSD& notification, const LLSD& response); @@ -370,14 +361,13 @@ class LLPanelEstateCovenant : public LLPanelRegionInfo static void updateCovenantText(const std::string& string, const LLUUID& asset_id); static void updateEstateName(const std::string& name); static void updateLastModified(const std::string& text); - static void updateEstateOwnerName(const std::string& name); + static void updateEstateOwnerID(const LLUUID& id); const LLUUID& getCovenantID() const { return mCovenantID; } void setCovenantID(const LLUUID& id) { mCovenantID = id; } std::string getEstateName() const; void setEstateName(const std::string& name); std::string getOwnerName() const; - void setOwnerName(const std::string& name); void setCovenantTextEditor(const std::string& text); typedef enum e_asset_status @@ -389,7 +379,7 @@ class LLPanelEstateCovenant : public LLPanelRegionInfo } EAssetStatus; protected: - virtual BOOL sendUpdate(); + BOOL sendUpdate() override; LLTextBox* mEstateNameText; LLTextBox* mEstateOwnerText; LLTextBox* mLastModifiedText; @@ -409,19 +399,17 @@ class LLPanelEnvironmentInfo : public LLPanelRegionInfo LLPanelEnvironmentInfo(); // LLPanel - /*virtual*/ BOOL postBuild(); - - // LLPanelRegionInfo - /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ BOOL postBuild() override; + /*virtual*/ void onOpen(const LLSD& key) override; // LLView - /*virtual*/ void handleVisibilityChange(BOOL new_visibility); + /*virtual*/ void handleVisibilityChange(BOOL new_visibility) override; // LLPanelRegionInfo - /*virtual*/ bool refreshFromRegion(LLViewerRegion* region); + /*virtual*/ bool refreshFromRegion(LLViewerRegion* region) override; private: - void refresh(); + void refresh() override; void setControlsEnabled(bool enabled); void setApplyProgress(bool started); void setDirty(bool dirty); @@ -463,4 +451,102 @@ class LLPanelEnvironmentInfo : public LLPanelRegionInfo LLComboBox* mDayCyclePresetCombo; }; +class LLPanelRegionExperiences : public LLPanelRegionInfo +{ + LOG_CLASS(LLPanelEnvironmentInfo); + +public: + LLPanelRegionExperiences(); + /*virtual*/ BOOL postBuild() override; + BOOL sendUpdate() override; + + static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response); + static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id); + + static void infoCallback(LLHandle handle, const LLSD& content); + bool refreshFromRegion(LLViewerRegion* region) override; + void sendPurchaseRequest()const; + void processResponse( const LLSD& content ); +private: + void refreshRegionExperiences(); + + static std::string regionCapabilityQuery(LLViewerRegion* region, const std::string &cap); + + void setupList(LLPanelExperienceListEditor* child, const char* control_name, U32 add_id, U32 remove_id); + static LLSD addIds( LLPanelExperienceListEditor* panel ); + + void itemChanged(U32 event_type, const LLUUID& id); + + LLPanelExperienceListEditor* mTrusted; + LLPanelExperienceListEditor* mAllowed; + LLPanelExperienceListEditor* mBlocked; + LLUUID mDefaultExperience; +}; + + +class LLPanelEstateAccess : public LLPanelRegionInfo +{ + LOG_CLASS(LLPanelEnvironmentInfo); + +public: + LLPanelEstateAccess(); + + virtual BOOL postBuild(); + virtual void updateChild(LLUICtrl* child_ctrl); + + void updateControls(LLViewerRegion* region); + void updateLists(); + + void setPendingUpdate(bool pending) { mPendingUpdate = pending; } + bool getPendingUpdate() { return mPendingUpdate; } + + virtual bool refreshFromRegion(LLViewerRegion* region); + + static void onEstateAccessReceived(const LLSD& result); + +private: + void onClickAddAllowedAgent(); + void onClickRemoveAllowedAgent(); + void onClickCopyAllowedList(); + void onClickAddAllowedGroup(); + void onClickRemoveAllowedGroup(); + void onClickCopyAllowedGroupList(); + void onClickAddBannedAgent(); + void onClickRemoveBannedAgent(); + void onClickCopyBannedList(); + void onClickAddEstateManager(); + void onClickRemoveEstateManager(); + void onAllowedSearchEdit(const std::string& search_string); + void onAllowedGroupsSearchEdit(const std::string& search_string); + void onBannedSearchEdit(const std::string& search_string); + + // Group picker callback is different, can't use core methods below + bool addAllowedGroup(const LLSD& notification, const LLSD& response); + void addAllowedGroup2(LLUUID id); + + // Core methods for all above add/remove button clicks + static void accessAddCore(U32 operation_flag, const std::string& dialog_name); + static bool accessAddCore2(const LLSD& notification, const LLSD& response); + static void accessAddCore3(const uuid_vec_t& ids, const std::vector& names, LLEstateAccessChangeInfo* change_info); + + static void accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name); + static bool accessRemoveCore2(const LLSD& notification, const LLSD& response); + + // used for both add and remove operations + static bool accessCoreConfirm(const LLSD& notification, const LLSD& response); + +public: + // Send the actual EstateOwnerRequest "estateaccessdelta" message + static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id); + +private: + //static void requestEstateGetAccessCoro(std::string url); + + void searchAgent(LLNameListCtrl* listCtrl, const std::string& search_string); + void copyListToClipboard(std::string list_name); + + bool mPendingUpdate; + bool mCtrlsEnabled; +}; + #endif diff --git a/indra/newview/llfloaterregionrestarting.cpp b/indra/newview/llfloaterregionrestarting.cpp index 448b852166..3064425e48 100644 --- a/indra/newview/llfloaterregionrestarting.cpp +++ b/indra/newview/llfloaterregionrestarting.cpp @@ -39,8 +39,11 @@ #include "lllandmarklist.h" #include "llviewerregion.h" #include "llworldmap.h" -void emergency_teleport() +void emergency_teleport(const U32& seconds) { + static const LLCachedControl time(gSavedSettings, "EmergencyTeleportSeconds"); + if (seconds > time) return; + static const LLCachedControl landmark(gSavedPerAccountSettings, "EmergencyTeleportLandmark"); if (landmark().empty()) return; LLUUID id(landmark); @@ -97,12 +100,12 @@ LLFloaterRegionRestarting::LLFloaterRegionRestarting(const LLSD& key) : LLEventTimer(1) , mRestartSeconds(NULL) , mSeconds(key["SECONDS"].asInteger()) +, mName(key.has("NAME") ? key["NAME"].asString() : gAgent.getRegion()->getName()) // , mShakeIterations() , mShakeMagnitude() { //buildFromFile("floater_region_restarting.xml"); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_region_restarting.xml"); - mName = key.has("NAME") ? key["NAME"].asString() : gAgent.getRegion()->getName(); // center(); } @@ -120,7 +123,7 @@ LLFloaterRegionRestarting::~LLFloaterRegionRestarting() BOOL LLFloaterRegionRestarting::postBuild() { mRegionChangedConnection = gAgent.addRegionChangedCallback(boost::bind(&LLFloaterRegionRestarting::regionChange, this)); - if (mSeconds <= 20) emergency_teleport(); // For emergency teleports + emergency_teleport(mSeconds); // For emergency teleports LLStringUtil::format_map_t args; std::string text; @@ -158,7 +161,7 @@ void LLFloaterRegionRestarting::refresh() args["[SECONDS]"] = llformat("%d", mSeconds); mRestartSeconds->setValue(getString("RestartSeconds", args)); - if (mSeconds == 20) emergency_teleport(); // For emergency teleports + emergency_teleport(mSeconds); // For emergency teleports if (!mSeconds) return; // Zero means we're done. --mSeconds; } @@ -233,6 +236,6 @@ void LLFloaterRegionRestarting::draw() void LLFloaterRegionRestarting::updateTime(const U32& time) { mSeconds = time; - if (mSeconds <= 20) emergency_teleport(); // For emergency teleports + emergency_teleport(mSeconds); // For emergency teleports sShakeState = SHAKE_START; } diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 05ed662bf9..a6c705ad81 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -74,7 +74,7 @@ #include "llfloateravatarpicker.h" #include "lldir.h" #include "llselectmgr.h" -#include "sgversion.h" +#include "llversioninfo.h" #include "lluictrlfactory.h" #include "llviewernetwork.h" @@ -82,6 +82,9 @@ #include "llagentui.h" #include "lltrans.h" +#include "llexperiencecache.h" + +#include "llcororesponder.h" #include "rlvhandler.h" @@ -111,17 +114,6 @@ LLFloaterReporter::LLFloaterReporter() LLUICtrlFactory::getInstance()->buildFloater(this, "floater_report_abuse.xml"); } -// static -void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg) -{ - U32 region_flags; - msg->getU32("RegionInfo", "RegionFlags", region_flags); - - if (LLFloaterReporter::instanceExists() && LLFloaterReporter::getInstance()->getVisible()) - { - LLNotificationsUtil::add("HelpReportAbuseEmailLL"); - } -} // virtual BOOL LLFloaterReporter::postBuild() { @@ -148,13 +140,14 @@ BOOL LLFloaterReporter::postBuild() // Default text to be blank getChild("object_name")->setValue(LLStringUtil::null); - getChild("owner_name")->setValue(LLStringUtil::null); + getChild("owner_name")->setValue(LLUUID::null); mOwnerName = LLStringUtil::null; getChild("summary_edit")->setFocus(TRUE); mDefaultSummary = getChild("details_edit")->getValue().asString(); + /* Singu Note: We only used this to trigger the notification that's now below, there's no point to this anymore. // send a message and ask for information about this region - // result comes back in processRegionInfo(..) LLMessageSystem* msg = gMessageSystem; @@ -163,6 +156,8 @@ BOOL LLFloaterReporter::postBuild() msg->addUUID("AgentID", gAgent.getID()); msg->addUUID("SessionID", gAgent.getSessionID()); gAgent.sendReliableMessage(); + */ + LLNotificationsUtil::add("HelpReportAbuseEmailLL"); // abuser name is selected from a list @@ -179,15 +174,34 @@ BOOL LLFloaterReporter::postBuild() childSetAction("send_btn", onClickSend, this); childSetAction("cancel_btn", onClickCancel, this); + // grab the user's name - std::string reporter; - gAgent.buildFullname(reporter); - getChild("reporter_field")->setValue(reporter); + getChild("reporter_field")->setValue(gAgent.getID()); + + // request categories + if (gAgent.getRegion() + && gAgent.getRegion()->capabilitiesReceived()) + { + std::string cap_url = gAgent.getRegionCapability("AbuseCategories"); + + if (!cap_url.empty()) + { + std::string lang = gSavedSettings.getString("Language"); + if (lang != "default" && !lang.empty()) + { + cap_url += "?lc="; + cap_url += lang; + } + LLHTTPClient::get(cap_url, new LLCoroResponder( + boost::bind(LLFloaterReporter::requestAbuseCategoriesCoro, _1, cap_url, this->getHandle()))); + } + } center(); return TRUE; } + // virtual LLFloaterReporter::~LLFloaterReporter() { @@ -212,19 +226,10 @@ LLFloaterReporter::~LLFloaterReporter() delete mResourceDatap; } -// virtual -void LLFloaterReporter::draw() -{ - getChildView("screen_check")->setEnabled(TRUE ); - - LLFloater::draw(); -} - void LLFloaterReporter::enableControls(BOOL enable) { getChildView("category_combo")->setEnabled(enable); - getChildView("screen_check")->setEnabled(enable); - getChildView("screenshot")->setEnabled(false); + getChildView("screenshot")->setEnabled(FALSE); getChildView("pick_btn")->setEnabled(enable); getChildView("summary_edit")->setEnabled(enable); getChildView("details_edit")->setEnabled(enable); @@ -232,6 +237,30 @@ void LLFloaterReporter::enableControls(BOOL enable) getChildView("cancel_btn")->setEnabled(enable); } +void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id) +{ + mExperienceID = experience_id; + + if (LLUUID::null != mExperienceID) + { + const LLSD& experience = LLExperienceCache::instance().get(mExperienceID); + std::stringstream desc; + + if (experience.isDefined()) + { + setFromAvatarID(experience[LLExperienceCache::AGENT_ID]); + desc << "Experience id: " << mExperienceID; + } + else + { + desc << "Unable to retrieve details for id: "<< mExperienceID; + } + + LLUICtrl* details = getChild("details_edit"); + details->setValue(desc.str()); + } +} + void LLFloaterReporter::getObjectInfo(const LLUUID& object_id) { // TODO -- @@ -260,6 +289,14 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id) if (regionp) { getChild("sim_field")->setValue(regionp->getName()); +// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) +/* + if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) + { + childSetText("sim_field", RlvStrings::getString(RLV_STRING_HIDDEN_REGION)); + } +*/ +// [/RLVa:KB] LLVector3d global_pos; global_pos.setVec(objectp->getPositionRegion()); setPosBox(global_pos); @@ -316,6 +353,7 @@ void LLFloaterReporter::callbackAvatarID(const uuid_vec_t& ids, const std::vecto void LLFloaterReporter::setFromAvatarID(const LLUUID& avatar_id) { mAbuserID = mObjectID = avatar_id; + getChild("owner_name")->setValue(mObjectID); if (mAvatarNameCacheConnection.connected()) { @@ -332,12 +370,74 @@ void LLFloaterReporter::onAvatarNameCache(const LLUUID& avatar_id, const LLAvata { mOwnerName = av_name.getNSName(); const std::string& name(((gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) || gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) && RlvUtil::isNearbyAgent(avatar_id)) ? RlvStrings::getString(RLV_STRING_HIDDEN) : mOwnerName); - getChild("owner_name")->setValue(name); + getChild("owner_name")->setValue(avatar_id); getChild("object_name")->setValue(name); getChild("abuser_name_edit")->setValue(name); } } +void LLFloaterReporter::requestAbuseCategoriesCoro(const LLCoroResponder& responder, std::string url, LLHandle handle) +{ + LLSD result = responder.getContent(); + + if (!responder.isGoodStatus(responder.getStatus()) || !result.has("categories")) // success = httpResults["success"].asBoolean(); + { + LL_WARNS() << "Error requesting Abuse Categories from capability: " << url << LL_ENDL; + return; + } + + if (handle.isDead()) + { + // nothing to do + return; + } + + LLFloater* floater = handle.get(); + LLComboBox* combo = floater->getChild("category_combo"); + if (!combo) + { + LL_WARNS() << "categories category_combo not found!" << LL_ENDL; + return; + } + + //get selection (in case capability took a while) + S32 selection = combo->getCurrentIndex(); + + // Combobox should have a "Select category" element; + // This is a bit of workaround since there is no proper and simple way to save array of + // localizable strings in xml along with data (value). For now combobox is initialized along + // with placeholders, and first element is "Select category" which we want to keep, so remove + // everything but first element. + // Todo: once sim with capability fully releases, just remove this string and all unnecessary + // items from combobox since they will be obsolete (or depending on situation remake this to + // something better, for example move "Select category" to separate string) + while (combo->remove(1)); + + LLSD contents = result["categories"]; + + LLSD::array_iterator i = contents.beginArray(); + LLSD::array_iterator iEnd = contents.endArray(); + for (; i != iEnd; ++i) + { + const LLSD &message_data(*i); + std::string label = message_data["description_localized"]; + const auto& cat = message_data["category"]; + combo->add(label, cat); + switch(cat.asInteger()) + { + // Fraud + case 47: combo->add(floater->getString("Ridiculous3"), 1000); break; + // Harassment + case 51: combo->add(floater->getString("Ridiculous1"), 1000); break; + // Land > Encroachment + case 63: combo->add(floater->getString("Ridiculous2"), 1000); break; + default: break; + } + } + + //restore selection + combo->selectNthItem(selection); +} // static void LLFloaterReporter::onClickSend(void *userdata) @@ -391,19 +491,10 @@ void LLFloaterReporter::onClickSend(void *userdata) } else { - if(self->getChild("screen_check")->getValue()) - { - self->getChildView("send_btn")->setEnabled(FALSE); - self->getChildView("cancel_btn")->setEnabled(FALSE); - // the callback from uploading the image calls sendReportViaLegacy() - self->uploadImage(); - } - else - { - self->sendReportViaLegacy(self->gatherReport()); - LLUploadDialog::modalUploadFinished(); - self->close(); - } + self->getChildView("send_btn")->setEnabled(FALSE); + self->getChildView("cancel_btn")->setEnabled(FALSE); + // the callback from uploading the image calls sendReportViaLegacy() + self->uploadImage(); } } } @@ -433,7 +524,7 @@ void LLFloaterReporter::onClickObjPicker(void *userdata) LLToolMgr::getInstance()->setTransientTool(LLToolObjPicker::getInstance()); self->mPicking = TRUE; self->getChild("object_name")->setValue(LLStringUtil::null); - self->getChild("owner_name")->setValue(LLStringUtil::null); + self->getChild("owner_name")->setValue(LLUUID::null); self->mOwnerName = LLStringUtil::null; LLButton* pick_btn = self->getChild("pick_btn"); if (pick_btn) pick_btn->setToggleState(TRUE); @@ -474,7 +565,7 @@ void LLFloaterReporter::showFromMenu(EReportType report_type) } // static -void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_name) +void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_name, const LLUUID& experience_id) { LLFloaterReporter* f = getInstance(); @@ -487,6 +578,23 @@ void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_ { f->setFromAvatarID(object_id); } + if (experience_id.notNull()) + { + f->getExperienceInfo(experience_id); + } + + // Need to deselect on close + f->mDeselectOnClose = TRUE; + + f->open(); /* Flawfinder: ignore */ +} + + + +void LLFloaterReporter::showFromExperience(const LLUUID& experience_id) +{ + LLFloaterReporter* f = getInstance(); + f->getExperienceInfo(experience_id); // Need to deselect on close f->mDeselectOnClose = TRUE; @@ -496,9 +604,9 @@ void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_ // static -void LLFloaterReporter::showFromObject(const LLUUID& object_id) +void LLFloaterReporter::showFromObject(const LLUUID& object_id, const LLUUID& experience_id) { - show(object_id); + show(object_id, LLStringUtil::null, experience_id); } // static @@ -520,7 +628,7 @@ void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name } else { - getChild("owner_name")->setValue(owner_name); + getChild("owner_name")->setValue(owner_id); getChild("abuser_name_edit")->setValue(owner_name); } mAbuserID = owner_id; @@ -533,7 +641,7 @@ bool LLFloaterReporter::validateReport() // Ensure user selected a category from the list LLSD category_sd = getChild("category_combo")->getValue(); U8 category = (U8)category_sd.asInteger(); - if(category >= 100) //This is here for reasons (like shenanigans) + if(category == 1000) //This is here for reasons (like shenanigans) { LLNotificationsUtil::add("HelpReportNope"); return false; @@ -624,10 +732,7 @@ LLSD LLFloaterReporter::gatherReport() std::ostringstream details; - details << "V" << gVersionMajor << "." // client version moved to body of email for abuse reports - << gVersionMinor << "." - << gVersionPatch << "." - << gVersionBuild << std::endl << std::endl; + details << 'V' << LLVersionInfo::getVersion() << "\n\n"; // client version moved to body of email for abuse reports std::string object_name = getChild("object_name")->getValue().asString(); if (!object_name.empty() && !mOwnerName.empty()) @@ -644,22 +749,16 @@ LLSD LLFloaterReporter::gatherReport() std::string version_string; version_string = llformat( - "%d.%d.%d %s %s %s %s", - gVersionMajor, - gVersionMinor, - gVersionPatch, + "%s %s %s %s %s", + LLVersionInfo::getShortVersion().c_str(), platform, gSysCPU.getFamily().c_str(), gGLManager.mGLRenderer.c_str(), gGLManager.mDriverVersionVendorString.c_str()); - // only send a screenshot ID if we're asked to and the email is + // only send a screenshot ID if we're asked to and the email is // going to LL - Estate Owners cannot see the screenshot asset - LLUUID screenshot_id = LLUUID::null; - if (getChild("screen_check")->getValue()) - { - screenshot_id = getChild("screenshot")->getValue(); - } + LLUUID screenshot_id = getChild("screenshot")->getValue().asUUID(); LLSD report = LLSD::emptyMap(); report["report-type"] = (U8) mReportType; @@ -705,7 +804,7 @@ void LLFloaterReporter::sendReportViaLegacy(const LLSD & report) msg->sendReliable(regionp->getHost()); } -class LLUserReportScreenshotResponder : public LLAssetUploadResponder +class LLUserReportScreenshotResponder final : public LLAssetUploadResponder { public: LLUserReportScreenshotResponder(const LLSD & post_data, @@ -725,17 +824,17 @@ class LLUserReportScreenshotResponder : public LLAssetUploadResponder LLUploadDialog::modalUploadFinished(); } - /*virtual*/ char const* getName(void) const { return "LLUserReportScreenshotResponder"; } + char const* getName() const override { return "LLUserReportScreenshotResponder"; } }; -class LLUserReportResponder : public LLHTTPClient::ResponderWithCompleted +class LLUserReportResponder final : public LLHTTPClient::ResponderWithCompleted { LOG_CLASS(LLUserReportResponder); public: LLUserReportResponder() { } private: - void httpCompleted() + void httpCompleted() override { if (!isGoodStatus(mStatus)) { @@ -745,12 +844,12 @@ class LLUserReportResponder : public LLHTTPClient::ResponderWithCompleted // we don't care about what the server returns LLUploadDialog::modalUploadFinished(); } - char const* getName() const { return "LLUserReportResponder"; } + char const* getName() const override { return "LLUserReportResponder"; } }; void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report) { - if(getChild("screen_check")->getValue().asBoolean() && !sshot_url.empty()) + if(!sshot_url.empty()) { // try to upload screenshot LLHTTPClient::post(sshot_url, report, new LLUserReportScreenshotResponder(report, @@ -807,11 +906,11 @@ void LLFloaterReporter::takeScreenshot() // store in the image list so it doesn't try to fetch from the server LLPointer image_in_list = - LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::FETCHED_TEXTURE); - image_in_list->createGLTexture(0, raw, 0, TRUE, LLViewerTexture::OTHER); + LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::FETCHED_TEXTURE); + image_in_list->createGLTexture(0, raw, nullptr, TRUE, LLViewerTexture::OTHER); // the texture picker then uses that texture - LLTexturePicker* texture = getChild("screenshot"); + LLTextureCtrl* texture = getChild("screenshot"); if (texture) { texture->setImageAssetID(mResourceDatap->mAssetInfo.mUuid); @@ -886,6 +985,7 @@ void LLFloaterReporter::setPosBox(const LLVector3d &pos) getChild("pos_field")->setValue(pos_string); } + //void LLFloaterReporter::setDescription(const std::string& description, LLMeanCollisionData *mcd) //{ // LLFloaterReporter *self = getInstance(); diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index 71f478e525..0cef2d4e8b 100644 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -38,7 +38,6 @@ #include "v3math.h" class LLAvatarName; -class LLMessageSystem; class LLViewerTexture; class LLInventoryItem; class LLViewerObject; @@ -48,9 +47,9 @@ class LLMeanCollisionData; struct LLResourceData; // these flags are used to label info requests to the server -//const U32 BUG_REPORT_REQUEST = 0x01 << 0; // DEPRECATED -const U32 COMPLAINT_REPORT_REQUEST = 0x01 << 1; -const U32 OBJECT_PAY_REQUEST = 0x01 << 2; +//constexpr U32 BUG_REPORT_REQUEST = 0x01 << 0; // DEPRECATED +constexpr U32 COMPLAINT_REPORT_REQUEST = 0x01 << 1; +constexpr U32 OBJECT_PAY_REQUEST = 0x01 << 2; // ************************************************************ @@ -78,22 +77,22 @@ enum EReportType CS_REQUEST_REPORT = 4 }; -class LLFloaterReporter +class LLFloaterReporter final : public LLFloater, public LLSingleton { public: LLFloaterReporter(); /*virtual*/ ~LLFloaterReporter(); - /*virtual*/ BOOL postBuild(); - virtual void draw(); + /*virtual*/ BOOL postBuild() override; void setReportType(EReportType type) { mReportType = type; } // Enables all buttons static void showFromMenu(EReportType report_type); - static void showFromObject(const LLUUID& object_id); + static void showFromObject(const LLUUID& object_id, const LLUUID& experience_id = LLUUID::null); static void showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name); + static void showFromExperience(const LLUUID& experience_id); static void onClickSend (void *userdata); static void onClickCancel (void *userdata); @@ -101,16 +100,13 @@ class LLFloaterReporter void onClickSelectAbuser (); static void closePickTool (void *userdata); static void uploadDoneCallback(const LLUUID &uuid, void* user_data, S32 result, LLExtStat ext_status); - static void addDescription(const std::string& description, LLMeanCollisionData *mcd = NULL); - static void setDescription(const std::string& description, LLMeanCollisionData *mcd = NULL); - - // static - static void processRegionInfo(LLMessageSystem* msg); + static void addDescription(const std::string& description, LLMeanCollisionData *mcd = nullptr); + static void setDescription(const std::string& description, LLMeanCollisionData *mcd = nullptr); void setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id); private: - static void show(const LLUUID& object_id, const std::string& avatar_name = LLStringUtil::null); + static void show(const LLUUID& object_id, const std::string& avatar_name = LLStringUtil::null, const LLUUID& experience_id = LLUUID::null); void takeScreenshot(); void sendReportViaCaps(std::string url); @@ -122,16 +118,20 @@ class LLFloaterReporter void sendReportViaCaps(std::string url, std::string sshot_url, const LLSD & report); void setPosBox(const LLVector3d &pos); void enableControls(BOOL own_avatar); + void getExperienceInfo(const LLUUID& object_id); void getObjectInfo(const LLUUID& object_id); void callbackAvatarID(const uuid_vec_t& ids, const std::vector& names); void setFromAvatarID(const LLUUID& avatar_id); void onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name); + static void requestAbuseCategoriesCoro(const struct LLCoroResponder& responder, std::string url, LLHandle handle); + private: EReportType mReportType; LLUUID mObjectID; LLUUID mScreenID; LLUUID mAbuserID; + LLUUID mExperienceID; // Store the real name, not the link, for upstream reporting std::string mOwnerName; BOOL mDeselectOnClose; diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp index df9ff37eb1..e1209ccdf2 100644 --- a/indra/newview/llfloaterscriptdebug.cpp +++ b/indra/newview/llfloaterscriptdebug.cpp @@ -32,20 +32,16 @@ #include "llviewerprecompiledheaders.h" -#include "lluictrlfactory.h" #include "llfloaterscriptdebug.h" -#include "llfontgl.h" -#include "llrect.h" -#include "llerror.h" -#include "llstring.h" -#include "message.h" +#include "lluictrlfactory.h" // project include -#include "llviewertexteditor.h" -#include "llviewercontrol.h" +#include "llslurl.h" #include "llviewerobjectlist.h" -#include "llviewertexturelist.h" +#include "llviewerregion.h" +#include "llviewertexteditor.h" +#include "llvoavatarself.h" // // Statics @@ -122,31 +118,67 @@ LLFloater* LLFloaterScriptDebug::addOutputWindow(const LLUUID &object_id) return floaterp; } -void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std::string &user_name, const LLColor4& color, const LLUUID& source_id) +void LLFloaterScriptDebug::addScriptLine(LLChat& chat, const LLColor4& color) { + const auto& utf8mesg = chat.mText; + const auto& user_name = chat.mFromName; + const auto& source_id = chat.mFromID; + LLViewerObject* objectp = gObjectList.findObject(source_id); std::string floater_label; + // Handle /me messages. + std::string prefix = utf8mesg.substr(0, 4); + std::string message = (prefix == "/me " || prefix == "/me'") ? user_name + utf8mesg.substr(3) : utf8mesg; + + LLSD sdQuery = LLSD().with("name", user_name); if (objectp) { - objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", TRUE, LLGLTexture::BOOST_UI)); - floater_label = llformat("%s(%.2f, %.2f)", user_name.c_str(), objectp->getPositionRegion().mV[VX], objectp->getPositionRegion().mV[VY]); + if(objectp->isHUDAttachment()) + { + if (isAgentAvatarValid()) + { + ((LLViewerObject*)gAgentAvatarp)->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); + } + } + else + { + objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); + } + + const auto& pos = objectp->getPositionRegion(); + sdQuery.with("owner", objectp->mOwnerID) + .with("groupowned", objectp->flagObjectGroupOwned()) + .with("slurl", LLSLURL(objectp->getRegion()->getName(), pos).getLocationString()); + + floater_label = llformat("%s(%.0f, %.0f, %.0f)", + user_name.c_str(), + pos.mV[VX], + pos.mV[VY], + pos.mV[VZ]); } else { floater_label = user_name; } + chat.mURL = LLSLURL("objectim", source_id, LLURI::mapToQueryString(sdQuery)).getSLURLString(); + addOutputWindow(LLUUID::null); addOutputWindow(source_id); // add to "All" floater - LLFloaterScriptDebugOutput* floaterp = LLFloaterScriptDebugOutput::getFloaterByID(LLUUID::null); - floaterp->addLine(utf8mesg, user_name, color); - + if (auto floaterp = LLFloaterScriptDebugOutput::getFloaterByID(LLUUID::null)) + { + floaterp->addLine(chat, message, color); + } + // add to specific script instance floater - floaterp = LLFloaterScriptDebugOutput::getFloaterByID(source_id); - floaterp->addLine(utf8mesg, floater_label, color); + if (auto floaterp = LLFloaterScriptDebugOutput::getFloaterByID(source_id)) + { + floaterp->setTitle(floater_label); // Update title + floaterp->addLine(chat, message, color); + } } // @@ -162,7 +194,8 @@ LLFloaterScriptDebugOutput::LLFloaterScriptDebugOutput() } LLFloaterScriptDebugOutput::LLFloaterScriptDebugOutput(const LLUUID& object_id) -: LLFloater(std::string("script instance floater"), LLRect(0, 200, 200, 0), std::string("Script"), TRUE), mObjectID(object_id) +: LLFloater(std::string("script instance floater"), LLRect(0, 200, 200, 0), std::string("Script"), TRUE), mObjectID(object_id), + mHistoryEditor(nullptr) { S32 y = getRect().getHeight() - LLFLOATER_HEADER_SIZE - LLFLOATER_VPAD; S32 x = LLFLOATER_HPAD; @@ -179,6 +212,7 @@ LLFloaterScriptDebugOutput::LLFloaterScriptDebugOutput(const LLUUID& object_id) mHistoryEditor->setFollowsAll(); mHistoryEditor->setEnabled( FALSE ); mHistoryEditor->setTabStop( TRUE ); // We want to be able to cut or copy from the history. + mHistoryEditor->setParseHTML(true); addChild(mHistoryEditor); } @@ -202,6 +236,7 @@ void LLFloaterScriptDebugOutput::initFloater(const std::string& title, BOOL resi mHistoryEditor->setFollowsAll(); mHistoryEditor->setEnabled( FALSE ); mHistoryEditor->setTabStop( TRUE ); // We want to be able to cut or copy from the history. + mHistoryEditor->setParseHTML(true); addChild(mHistoryEditor); } @@ -210,20 +245,15 @@ LLFloaterScriptDebugOutput::~LLFloaterScriptDebugOutput() sInstanceMap.erase(mObjectID); } -void LLFloaterScriptDebugOutput::addLine(const std::string &utf8mesg, const std::string &user_name, const LLColor4& color) +void LLFloaterScriptDebugOutput::addLine(const LLChat& chat, std::string message, const LLColor4& color) { - if (mObjectID.isNull()) - { - //setTitle("[All scripts]"); - setCanTearOff(FALSE); - setCanClose(FALSE); - } - else + if (!chat.mURL.empty()) { - setTitle(user_name); + message.erase(0, chat.mFromName.size()); + mHistoryEditor->appendText(chat.mURL, false, true); } - - mHistoryEditor->appendColoredText(utf8mesg, false, true, color); + LLStyleSP style(new LLStyle(true, color, LLStringUtil::null)); + mHistoryEditor->appendText(message, false, false, style, false); } //static @@ -236,6 +266,13 @@ LLFloaterScriptDebugOutput* LLFloaterScriptDebugOutput::show(const LLUUID& objec floaterp = new LLFloaterScriptDebugOutput(object_id); sInstanceMap[object_id] = floaterp; floaterp->open(); /* Flawfinder: ignore*/ + + if (object_id.isNull()) + { + //floaterp->setTitle("[All scripts]"); + floaterp->setCanTearOff(FALSE); + floaterp->setCanClose(FALSE); + } } else { diff --git a/indra/newview/llfloaterscriptdebug.h b/indra/newview/llfloaterscriptdebug.h index 0d5bc7411f..8e28ea33d0 100644 --- a/indra/newview/llfloaterscriptdebug.h +++ b/indra/newview/llfloaterscriptdebug.h @@ -35,6 +35,7 @@ #include "llmultifloater.h" +class LLChat; class LLTextEditor; class LLUUID; @@ -45,7 +46,7 @@ class LLFloaterScriptDebug : public LLMultiFloater virtual void onClose(bool app_quitting) { setVisible(FALSE); } virtual BOOL postBuild(); static void show(const LLUUID& object_id); - static void addScriptLine(const std::string &utf8mesg, const std::string &user_name, const LLColor4& color, const LLUUID& source_id); + static void addScriptLine(LLChat& chat, const LLColor4& color); protected: LLFloaterScriptDebug(); @@ -67,7 +68,7 @@ class LLFloaterScriptDebugOutput : public LLFloater S32 min_width, S32 min_height, BOOL drag_on_left, BOOL minimizable, BOOL close_btn); - void addLine(const std::string &utf8mesg, const std::string &user_name, const LLColor4& color); + void addLine(const LLChat& chat, std::string message, const LLColor4& color); static LLFloaterScriptDebugOutput* show(const LLUUID& object_id); static LLFloaterScriptDebugOutput* getFloaterByID(const LLUUID& id); diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 0f6b6b78b8..2cd7af83f6 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -58,7 +58,7 @@ // debug switches, won't work in release #ifndef LL_RELEASE_FOR_DOWNLOAD -// dump responder replies to llinfos for debugging +// dump responder replies to LL_INFOS() for debugging //#define DUMP_REPLIES_TO_LLINFOS #ifdef DUMP_REPLIES_TO_LLINFOS @@ -84,6 +84,8 @@ const S32 SIZE_OF_ONE_KB = 1024; LLFloaterScriptLimits::LLFloaterScriptLimits(const LLSD& seed) : LLFloater(/*seed*/) + , mTab(nullptr) + , mInfoPanels() { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_script_limits.xml"); } @@ -752,6 +754,8 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) LLScrollListCell::Params cell_params; //cell_params.font = LLFontGL::getFontSansSerif(); + // Start out right justifying numeric displays + cell_params.font_halign = LLFontGL::RIGHT; cell_params.column = "size"; cell_params.value = size; @@ -761,6 +765,8 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) cell_params.value = urls; item_params.columns.add(cell_params); + cell_params.font_halign = LLFontGL::LEFT; + // The rest of the columns are text to left justify them cell_params.column = "name"; cell_params.value = name_buf; item_params.columns.add(cell_params); @@ -852,13 +858,20 @@ void LLPanelScriptLimitsRegionMemory::setRegionSummary(LLSD content) if((mParcelMemoryUsed >= 0) && (mParcelMemoryMax >= 0)) { - S32 parcel_memory_available = mParcelMemoryMax - mParcelMemoryUsed; - LLStringUtil::format_map_t args_parcel_memory; args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed); - args_parcel_memory["[MAX]"] = llformat ("%d", mParcelMemoryMax); - args_parcel_memory["[AVAILABLE]"] = llformat ("%d", parcel_memory_available); - std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_parcel_memory); + std::string translate_message = "ScriptLimitsMemoryUsedSimple"; + + if (0 < mParcelMemoryMax) + { + S32 parcel_memory_available = mParcelMemoryMax - mParcelMemoryUsed; + + args_parcel_memory["[MAX]"] = llformat ("%d", mParcelMemoryMax); + args_parcel_memory["[AVAILABLE]"] = llformat ("%d", parcel_memory_available); + translate_message = "ScriptLimitsMemoryUsed"; + } + + std::string msg_parcel_memory = LLTrans::getString(translate_message, args_parcel_memory); getChild("memory_used")->setValue(LLSD(msg_parcel_memory)); } @@ -1243,10 +1256,12 @@ void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content) element["columns"][0]["column"] = "size"; element["columns"][0]["value"] = llformat("%d", size); element["columns"][0]["font"] = "SANSSERIF"; + element["columns"][0]["halign"] = LLFontGL::RIGHT; element["columns"][1]["column"] = "urls"; element["columns"][1]["value"] = llformat("%d", urls); element["columns"][1]["font"] = "SANSSERIF"; + element["columns"][1]["halign"] = LLFontGL::RIGHT; element["columns"][2]["column"] = "name"; element["columns"][2]["value"] = name; @@ -1333,14 +1348,20 @@ void LLPanelScriptLimitsAttachment::setAttachmentSummary(LLSD content) if((mAttachmentMemoryUsed >= 0) && (mAttachmentMemoryMax >= 0)) { - S32 attachment_memory_available = mAttachmentMemoryMax - mAttachmentMemoryUsed; - LLStringUtil::format_map_t args_attachment_memory; args_attachment_memory["[COUNT]"] = llformat ("%d", mAttachmentMemoryUsed); - args_attachment_memory["[MAX]"] = llformat ("%d", mAttachmentMemoryMax); - args_attachment_memory["[AVAILABLE]"] = llformat ("%d", attachment_memory_available); - std::string msg_attachment_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_attachment_memory); - getChild("memory_used")->setValue(LLSD(msg_attachment_memory)); + std::string translate_message = "ScriptLimitsMemoryUsedSimple"; + + if (0 < mAttachmentMemoryMax) + { + S32 attachment_memory_available = mAttachmentMemoryMax - mAttachmentMemoryUsed; + + args_attachment_memory["[MAX]"] = llformat ("%d", mAttachmentMemoryMax); + args_attachment_memory["[AVAILABLE]"] = llformat ("%d", attachment_memory_available); + translate_message = "ScriptLimitsMemoryUsed"; + } + + getChild("memory_used")->setValue(LLTrans::getString(translate_message, args_attachment_memory)); } if((mAttachmentURLsUsed >= 0) && (mAttachmentURLsMax >= 0)) diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 67e9421a56..f0fdc34445 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -113,20 +113,8 @@ LLFloaterSearch::_Params::_Params() } LLFloaterSearch::LLFloaterSearch(const Params& key) : - LLFloaterWebContent(key), - mSearchGodLevel(0) + LLFloaterWebContent(key) { - // declare a map that transforms a category name into - // the URL suffix that is used to search that category - mCategoryPaths = LLSD::emptyMap(); - mCategoryPaths["all"] = "search"; - mCategoryPaths["people"] = "search/people"; - mCategoryPaths["places"] = "search/places"; - mCategoryPaths["events"] = "search/events"; - mCategoryPaths["groups"] = "search/groups"; - mCategoryPaths["wiki"] = "search/wiki"; - mCategoryPaths["destinations"] = "destinations"; - mCategoryPaths["classifieds"] = "classifieds"; LLUICtrlFactory::getInstance()->buildFloater(this, "floater_web_content.xml"); } @@ -143,8 +131,8 @@ BOOL LLFloaterSearch::postBuild() getChildView("popexternal")->setEnabled(false); setRectControl("FloaterSearchRect"); applyRectControl(); - search(SearchQuery()); - gSavedSettings.getControl("SearchURL")->getSignal()->connect(boost::bind(&LLFloaterSearch::search, this, SearchQuery())); + search(SearchQuery(), mWebBrowser); + gSavedSettings.getControl("SearchURL")->getSignal()->connect(boost::bind(LLFloaterSearch::search, SearchQuery(), mWebBrowser)); return TRUE; } @@ -156,32 +144,11 @@ void LLFloaterSearch::showInstance(const SearchQuery& search, bool web) { LLFloaterSearch* floater = getInstance(); floater->open(); // May not be open - floater->search(search); + floater->search(search, floater->mWebBrowser); } else { - const std::string category(search.category()); - if (category.empty()) - LLFloaterDirectory::searchInAll(search.query); - else if (category == "all") - LLFloaterDirectory::showFindAll(search.query); - else if (category == "people") - LLFloaterDirectory::showPeople(search.query); - else if (category == "places") - LLFloaterDirectory::showPlaces(search.query); - else if (category == "events") - LLFloaterDirectory::showEvents(search.query); - else if (category == "groups") - LLFloaterDirectory::showGroups(search.query); - /* Singu TODO: Wiki tab in secondlife legacy search floater? - else if (category == "wiki") - LLFloaterDirectory::showWiki(search.query);*/ - else if (category == "destinations") - LLFloaterDirectory::showDestinations(); - else if (category == "classifieds") - LLFloaterDirectory::showClassified(search.query); - else - LLNotificationsUtil::add("UnsupportedCommandSLURL"); // Singu Note: Perhaps we should use a special notification here? + LLFloaterDirectory::search(search); } } @@ -192,7 +159,7 @@ void LLFloaterSearch::showInstance(const SearchQuery& search, bool web) p.allow_address_entry = false; LLFloaterWebContent::onOpen(p); - search(p.search); + search(p.search, mWebBrowser); }*/ void LLFloaterSearch::onClose(bool app_quitting) @@ -208,31 +175,30 @@ void LLFloaterSearch::onClose(bool app_quitting) destroy(); } -void LLFloaterSearch::godLevelChanged(U8 godlevel) -{ - // search results can change based upon god level - if the user - // changes god level, then give them a warning (we don't refresh - // the search as this might undo any page navigation or - // AJAX-driven changes since the last search). - - //FIXME: set status bar text - - //getChildView("refresh_search")->setVisible( (godlevel != mSearchGodLevel)); -} - -void LLFloaterSearch::search(const SearchQuery &p) +// static +void LLFloaterSearch::search(const SearchQuery &p, LLMediaCtrl* mWebBrowser) { if (! mWebBrowser || !p.validateBlock()) { return; } - // reset the god level warning as we're sending the latest state - //getChildView("refresh_search")->setVisible(FALSE); - mSearchGodLevel = gAgent.getGodLevel(); - // work out the subdir to use based on the requested category LLSD subs; + // declare a map that transforms a category name into + // the URL suffix that is used to search that category + static LLSD mCategoryPaths = LLSD::emptyMap(); + if (mCategoryPaths.size() == 0) + { + mCategoryPaths["all"] = "search"; + mCategoryPaths["people"] = "search/people"; + mCategoryPaths["places"] = "search/places"; + mCategoryPaths["events"] = "search/events"; + mCategoryPaths["groups"] = "search/groups"; + mCategoryPaths["wiki"] = "search/wiki"; + mCategoryPaths["destinations"] = "destinations"; + mCategoryPaths["classifieds"] = "classifieds"; + } if (mCategoryPaths.has(p.category)) { subs["CATEGORY"] = mCategoryPaths[p.category].asString(); diff --git a/indra/newview/llfloatersearch.h b/indra/newview/llfloatersearch.h index 8cba06a1e5..96fbd35c1f 100644 --- a/indra/newview/llfloatersearch.h +++ b/indra/newview/llfloatersearch.h @@ -79,18 +79,10 @@ class LLFloaterSearch : /// - "id": specifies the text phrase to search for /// - "category": one of "all" (default), "people", "places", /// "events", "groups", "wiki", "destinations", "classifieds" - void search(const SearchQuery &query); - - /// changing godmode can affect the search results that are - /// returned by the search website - use this method to tell the - /// search floater that the user has changed god level. - void godLevelChanged(U8 godlevel); + static void search(const SearchQuery& query, LLMediaCtrl* mWebBrowser); private: /*virtual*/ BOOL postBuild(); - - LLSD mCategoryPaths; - U8 mSearchGodLevel; }; #endif // LL_LLFLOATERSEARCH_H diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp index 9c0fcf1597..8d91be3706 100644 --- a/indra/newview/llfloatersettingsdebug.cpp +++ b/indra/newview/llfloatersettingsdebug.cpp @@ -35,26 +35,31 @@ #include "llfloatersettingsdebug.h" #include "llcolorswatch.h" -//#include "llfirstuse.h" #include "llfloater.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" +#include "llsdserialize.h" #include "llspinctrl.h" #include "lltexteditor.h" #include "lluictrlfactory.h" #include "llviewercontrol.h" #include "llwindow.h" -// [RLVa:KB] - Checked: 2010-03-18 (RLVa-1.2.0a) -#include "rlvhandler.h" -#include "rlvextensions.h" -// [/RLVa:KB] - LLFloaterSettingsDebug::LLFloaterSettingsDebug() : LLFloater(std::string("Configuration Editor")) -, mCurrentControlVariable(NULL) -, mOldControlVariable(NULL) -, mOldSearchTerm(std::string("---")) +, mOldSearchTerm("---") +, mCurrentControlVariable(nullptr) +, mSettingsScrollList(nullptr) +, mValSpinner1(nullptr) +, mValSpinner2(nullptr) +, mValSpinner3(nullptr) +, mValSpinner4(nullptr) +, mValColor(nullptr) +, mValBool(nullptr) +, mValText(nullptr) +, mComment(nullptr) +, mBtnCopy(nullptr) +, mBtnDefault(nullptr) { mCommitCallbackRegistrar.add("SettingSelect", boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this)); mCommitCallbackRegistrar.add("CommitSettings", boost::bind(&LLFloaterSettingsDebug::onCommitSettings, this)); @@ -67,19 +72,20 @@ LLFloaterSettingsDebug::LLFloaterSettingsDebug() LLFloaterSettingsDebug::~LLFloaterSettingsDebug() { - if (mOldControlVariable) - mOldControlVariable->getCommitSignal()->disconnect(boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this)); + if (mCurrentControlVariable) + mCurrentControlVariable->getCommitSignal()->disconnect(boost::bind(&LLFloaterSettingsDebug::updateControl, this)); } BOOL LLFloaterSettingsDebug::postBuild() { mSettingsScrollList = getChild("settings_scroll_list"); - struct f : public LLControlGroup::ApplyFunctor + struct f final : public LLControlGroup::ApplyFunctor { settings_map_t* map; f(settings_map_t* m) : map(m) {} - virtual void apply(const std::string& name, LLControlVariable* control) + + void apply(const std::string& name, LLControlVariable* control) override final { if (!control->isHiddenFromSettingsEditor()) { @@ -93,26 +99,30 @@ BOOL LLFloaterSettingsDebug::postBuild() gColors.applyToAll(&func); // Populate the list - { - for(settings_map_t::iterator it = mSettingsMap.begin(); it != mSettingsMap.end(); it++) - { - LLSD item; - item["columns"][0]["value"] = it->second->getName(); - mSettingsScrollList->addElement(item, ADD_BOTTOM, it->second); - } - } + for(const auto& pair : mSettingsMap) + addRow(pair.second); + mSettingsScrollList->sortByColumnIndex(0, true); + mComment = getChild("comment_text"); + mValSpinner1 = getChild("val_spinner_1"); + mValSpinner2 = getChild("val_spinner_2"); + mValSpinner3 = getChild("val_spinner_3"); + mValSpinner4 = getChild("val_spinner_4"); + mValColor = getChild("val_color_swatch"); + mValBool = getChild("boolean_combo"); + mValText = getChild("val_text"); + mBtnCopy = getChildView("copy_btn"); + mBtnDefault = getChildView("default_btn"); LL_INFOS() << mSettingsScrollList->getItemCount() << " total debug settings displayed." << LL_ENDL; - mComment = getChild("comment_text"); return TRUE; } void LLFloaterSettingsDebug::draw() { // check for changes in control visibility, like RLVa does - if(mCurrentControlVariable && mCurrentControlVariable->isHiddenFromSettingsEditor() != mOldVisibility) + if (mCurrentControlVariable && mCurrentControlVariable->isHiddenFromSettingsEditor() != mOldVisibility) updateControl(); LLFloater::draw(); @@ -121,36 +131,66 @@ void LLFloaterSettingsDebug::draw() LLControlVariable* LLFloaterSettingsDebug::getControlVariable() { LLScrollListItem* item = mSettingsScrollList->getFirstSelected(); - if (!item) return NULL; + if (!item) return nullptr; LLControlVariable* controlp = static_cast(item->getUserdata()); - return controlp ? controlp->getCOAActive() : NULL; + return controlp ? controlp->getCOAActive() : nullptr; +} + +void LLFloaterSettingsDebug::addRow(LLControlVariable* control, const std::string& searchTerm) +{ + const auto& name = control->getName(); + const auto& comment = control->getComment(); + + if (!searchTerm.empty()) + { + std::string itemValue = control->getName(); + LLStringUtil::toLower(itemValue); + if (itemValue.find(searchTerm, 0) == std::string::npos) + { + std::string itemComment = control->getComment(); + LLStringUtil::toLower(itemComment); + if (itemComment.find(searchTerm, 0) == std::string::npos) + return; + } + } + + auto params = LLScrollListItem::Params(); + params.userdata(control) + .columns.add(LLScrollListCell::Params() + .value(name) + .tool_tip(comment)); + mSettingsScrollList->addRow(params); } void LLFloaterSettingsDebug::onSettingSelect() { - mCurrentControlVariable = getControlVariable(); + auto new_control = getControlVariable(); - if (mOldControlVariable == mCurrentControlVariable) return; + if (new_control == mCurrentControlVariable) return; // unbind change control signal from previously selected control - if(mOldControlVariable) - mOldControlVariable->getCommitSignal()->disconnect(boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this)); + if (mCurrentControlVariable) + mCurrentControlVariable->getCommitSignal()->disconnect(boost::bind(&LLFloaterSettingsDebug::updateControl, this)); - // bind change control signal, so we can see updates to the current control in realtime - if(mCurrentControlVariable) - mCurrentControlVariable->getCommitSignal()->connect(boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this)); + mCurrentControlVariable = new_control; - mOldControlVariable = mCurrentControlVariable; + // bind change control signal, so we can see updates to the current control in realtime + if (mCurrentControlVariable) + mCurrentControlVariable->getCommitSignal()->connect(boost::bind(&LLFloaterSettingsDebug::updateControl, this)); updateControl(); } void LLFloaterSettingsDebug::onCommitSettings() { - if (!mCurrentControlVariable) + LLControlVariable* controlp = mCurrentControlVariable; + + if (!controlp) + { return; + } LLVector3 vector; LLVector3d vectord; @@ -160,60 +200,73 @@ void LLFloaterSettingsDebug::onCommitSettings() LLColor4U col4U; LLColor4 color_with_alpha; - switch(mCurrentControlVariable->type()) + switch(controlp->type()) { case TYPE_U32: - mCurrentControlVariable->set(getChild("val_spinner_1")->getValue()); + controlp->set(mValSpinner1->getValue()); break; case TYPE_S32: - mCurrentControlVariable->set(getChild("val_spinner_1")->getValue()); + controlp->set(mValSpinner1->getValue()); break; case TYPE_F32: - mCurrentControlVariable->set(LLSD(getChild("val_spinner_1")->getValue().asReal())); + controlp->set(LLSD(mValSpinner1->getValue().asReal())); break; case TYPE_BOOLEAN: - mCurrentControlVariable->set(getChild("boolean_combo")->getValue()); + controlp->set(mValBool->getValue()); break; case TYPE_STRING: - mCurrentControlVariable->set(LLSD(getChild("val_text")->getValue().asString())); + controlp->set(mValText->getValue()); break; case TYPE_VEC3: - vector.mV[VX] = (F32)getChild("val_spinner_1")->getValue().asReal(); - vector.mV[VY] = (F32)getChild("val_spinner_2")->getValue().asReal(); - vector.mV[VZ] = (F32)getChild("val_spinner_3")->getValue().asReal(); - mCurrentControlVariable->set(vector.getValue()); + vector.mV[VX] = (F32)mValSpinner1->getValue().asReal(); + vector.mV[VY] = (F32)mValSpinner2->getValue().asReal(); + vector.mV[VZ] = (F32)mValSpinner3->getValue().asReal(); + controlp->set(vector.getValue()); break; case TYPE_VEC3D: - vectord.mdV[VX] = getChild("val_spinner_1")->getValue().asReal(); - vectord.mdV[VY] = getChild("val_spinner_2")->getValue().asReal(); - vectord.mdV[VZ] = getChild("val_spinner_3")->getValue().asReal(); - mCurrentControlVariable->set(vectord.getValue()); + vectord.mdV[VX] = mValSpinner1->getValue().asReal(); + vectord.mdV[VY] = mValSpinner2->getValue().asReal(); + vectord.mdV[VZ] = mValSpinner3->getValue().asReal(); + controlp->set(vectord.getValue()); break; case TYPE_RECT: - rect.mLeft = getChild("val_spinner_1")->getValue().asInteger(); - rect.mRight = getChild("val_spinner_2")->getValue().asInteger(); - rect.mBottom = getChild("val_spinner_3")->getValue().asInteger(); - rect.mTop = getChild("val_spinner_4")->getValue().asInteger(); - mCurrentControlVariable->set(rect.getValue()); + rect.mLeft = mValSpinner1->getValue().asInteger(); + rect.mRight = mValSpinner2->getValue().asInteger(); + rect.mBottom = mValSpinner3->getValue().asInteger(); + rect.mTop = mValSpinner4->getValue().asInteger(); + controlp->set(rect.getValue()); break; case TYPE_COL4: - col3.setValue(getChild("val_color_swatch")->getValue()); - col4 = LLColor4(col3, (F32)getChild("val_spinner_4")->getValue().asReal()); - mCurrentControlVariable->set(col4.getValue()); + col3.setValue(mValColor->getValue()); + col4 = LLColor4(col3, (F32)mValSpinner4->getValue().asReal()); + controlp->set(col4.getValue()); break; case TYPE_COL3: - mCurrentControlVariable->set(getChild("val_color_swatch")->getValue()); - //col3.mV[VRED] = (F32)getChild("val_spinner_1")->getValue().asC(); - //col3.mV[VGREEN] = (F32)getChild("val_spinner_2")->getValue().asReal(); - //col3.mV[VBLUE] = (F32)getChild("val_spinner_3")->getValue().asReal(); + controlp->set(mValColor->getValue()); + //col3.mV[VRED] = (F32)mValSpinner1->getValue().asReal(); + //col3.mV[VGREEN] = (F32)mValSpinner2->getValue().asReal(); + //col3.mV[VBLUE] = (F32)mValSpinner3->getValue().asReal(); //mCurrentControlVariable->set(col3.getValue()); break; case TYPE_COL4U: - col3.setValue(getChild("val_color_swatch")->getValue()); + col3.setValue(mValColor->getValue()); col4U.setVecScaleClamp(col3); - col4U.mV[VALPHA] = getChild("val_spinner_4")->getValue().asInteger(); + col4U.mV[VALPHA] = mValSpinner4->getValue().asInteger(); mCurrentControlVariable->set(col4U.getValue()); break; + case TYPE_LLSD: + { + const auto& val = mValText->getValue().asString(); + LLSD sd; + if (!val.empty()) + { + std::istringstream str(val); + if (LLSDSerialize::fromXML(sd, str) == LLSDParser::PARSE_FAILURE) + break; + } + mCurrentControlVariable->set(sd); + break; + } default: break; } @@ -231,164 +284,156 @@ void LLFloaterSettingsDebug::onClickDefault() void LLFloaterSettingsDebug::onCopyToClipboard() { if (mCurrentControlVariable) + { getWindow()->copyTextToClipboard(utf8str_to_wstring(mCurrentControlVariable->getName())); + } } -// we've switched controls, so update spinners, etc. +// we've switched controls, or doing per-frame update, so update spinners, etc. void LLFloaterSettingsDebug::updateControl() { - LLSpinCtrl* spinner1 = getChild("val_spinner_1"); - LLSpinCtrl* spinner2 = getChild("val_spinner_2"); - LLSpinCtrl* spinner3 = getChild("val_spinner_3"); - LLSpinCtrl* spinner4 = getChild("val_spinner_4"); - LLColorSwatchCtrl* color_swatch = getChild("val_color_swatch"); - LLUICtrl* bool_ctrl = getChild("boolean_combo"); - - if (!spinner1 || !spinner2 || !spinner3 || !spinner4 || !color_swatch) + if (!mValSpinner1 || !mValSpinner2 || !mValSpinner3 || !mValSpinner4 || !mValColor) { LL_WARNS() << "Could not find all desired controls by name" << LL_ENDL; return; } - spinner1->setVisible(FALSE); - spinner2->setVisible(FALSE); - spinner3->setVisible(FALSE); - spinner4->setVisible(FALSE); - color_swatch->setVisible(FALSE); - getChildView("val_text")->setVisible( FALSE); - mComment->setText(LLStringUtil::null); - childSetEnabled("copy_btn", false); - childSetEnabled("default_btn", false); - bool_ctrl->setVisible(false); + mValSpinner1->setVisible(FALSE); + mValSpinner2->setVisible(FALSE); + mValSpinner3->setVisible(FALSE); + mValSpinner4->setVisible(FALSE); + mValColor->setVisible(FALSE); + mValText->setVisible(FALSE); + if (!mComment->hasFocus()) // + { + mComment->setText(LLStringUtil::null); + } + mValBool->setVisible(false); + mBtnCopy->setEnabled(false); + mBtnDefault->setEnabled(false); if (mCurrentControlVariable) { // [RLVa:KB] - Checked: 2011-05-28 (RLVa-1.4.0a) | Modified: RLVa-1.4.0a // If "HideFromEditor" was toggled while the floater is open then we need to manually disable access to the control mOldVisibility = mCurrentControlVariable->isHiddenFromSettingsEditor(); - spinner1->setEnabled(!mOldVisibility); - spinner2->setEnabled(!mOldVisibility); - spinner3->setEnabled(!mOldVisibility); - spinner4->setEnabled(!mOldVisibility); - color_swatch->setEnabled(!mOldVisibility); - childSetEnabled("val_text", !mOldVisibility); - bool_ctrl->setEnabled(!mOldVisibility); - childSetEnabled("default_btn", !mOldVisibility); + mValSpinner1->setEnabled(!mOldVisibility); + mValSpinner2->setEnabled(!mOldVisibility); + mValSpinner3->setEnabled(!mOldVisibility); + mValSpinner4->setEnabled(!mOldVisibility); + mValColor->setEnabled(!mOldVisibility); + mValText->setEnabled(!mOldVisibility); + mValBool->setEnabled(!mOldVisibility); + mBtnDefault->setEnabled(!mOldVisibility); // [/RLVa:KB] - childSetEnabled("copy_btn", true); + mBtnCopy->setEnabled(true); eControlType type = mCurrentControlVariable->type(); - - mComment->setText(mCurrentControlVariable->getName() + std::string(": ") + mCurrentControlVariable->getComment()); - - spinner1->setMaxValue(F32_MAX); - spinner2->setMaxValue(F32_MAX); - spinner3->setMaxValue(F32_MAX); - spinner4->setMaxValue(F32_MAX); - spinner1->setMinValue(-F32_MAX); - spinner2->setMinValue(-F32_MAX); - spinner3->setMinValue(-F32_MAX); - spinner4->setMinValue(-F32_MAX); - if (!spinner1->hasFocus()) + if (!mComment->hasFocus()) // + { + mComment->setText(mCurrentControlVariable->getName() + std::string(": ") + mCurrentControlVariable->getComment()); + } + mValSpinner1->setMaxValue(F32_MAX); + mValSpinner2->setMaxValue(F32_MAX); + mValSpinner3->setMaxValue(F32_MAX); + mValSpinner4->setMaxValue(F32_MAX); + mValSpinner1->setMinValue(-F32_MAX); + mValSpinner2->setMinValue(-F32_MAX); + mValSpinner3->setMinValue(-F32_MAX); + mValSpinner4->setMinValue(-F32_MAX); + if (!mValSpinner1->hasFocus()) { - spinner1->setIncrement(0.1f); + mValSpinner1->setIncrement(0.1f); } - if (!spinner2->hasFocus()) + if (!mValSpinner2->hasFocus()) { - spinner2->setIncrement(0.1f); + mValSpinner2->setIncrement(0.1f); } - if (!spinner3->hasFocus()) + if (!mValSpinner3->hasFocus()) { - spinner3->setIncrement(0.1f); + mValSpinner3->setIncrement(0.1f); } - if (!spinner4->hasFocus()) + if (!mValSpinner4->hasFocus()) { - spinner4->setIncrement(0.1f); + mValSpinner4->setIncrement(0.1f); } LLSD sd = mCurrentControlVariable->get(); switch(type) { case TYPE_U32: - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("value")); // Debug, don't translate - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("value")); // Debug, don't translate + if (!mValSpinner1->hasFocus()) { - spinner1->setValue(sd); - spinner1->setMinValue((F32)U32_MIN); - spinner1->setMaxValue((F32)U32_MAX); - spinner1->setIncrement(1.f); - spinner1->setPrecision(0); + mValSpinner1->setValue(sd); + mValSpinner1->setMinValue((F32)U32_MIN); + mValSpinner1->setMaxValue((F32)U32_MAX); + mValSpinner1->setIncrement(1.f); + mValSpinner1->setPrecision(0); } break; case TYPE_S32: - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("value")); // Debug, don't translate - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("value")); // Debug, don't translate + if (!mValSpinner1->hasFocus()) { - spinner1->setValue(sd); - spinner1->setMinValue((F32)S32_MIN); - spinner1->setMaxValue((F32)S32_MAX); - spinner1->setIncrement(1.f); - spinner1->setPrecision(0); + mValSpinner1->setValue(sd); + mValSpinner1->setMinValue((F32)S32_MIN); + mValSpinner1->setMaxValue((F32)S32_MAX); + mValSpinner1->setIncrement(1.f); + mValSpinner1->setPrecision(0); } break; case TYPE_F32: - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("value")); // Debug, don't translate - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("value")); // Debug, don't translate + if (!mValSpinner1->hasFocus()) { - spinner1->setPrecision(3); - spinner1->setValue(sd); + mValSpinner1->setPrecision(3); + mValSpinner1->setValue(sd); } break; case TYPE_BOOLEAN: - bool_ctrl->setVisible(true); - if (!bool_ctrl->hasFocus()) + mValBool->setVisible(true); + if (!mValBool->hasFocus()) { - if (sd.asBoolean()) - { - bool_ctrl->setValue(LLSD("TRUE")); - } - else - { - bool_ctrl->setValue(LLSD("FALSE")); - } + mValBool->setValue(LLSD(sd.asBoolean() ? "TRUE" : "FALSE")); } break; case TYPE_STRING: - getChildView("val_text")->setVisible( TRUE); - if (!getChild("val_text")->hasFocus()) + mValText->setVisible(TRUE); + if (!mValText->hasFocus()) { - getChild("val_text")->setValue(sd); + mValText->setValue(sd); } break; case TYPE_VEC3: { LLVector3 v; v.setValue(sd); - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("X")); - spinner2->setVisible(TRUE); - spinner2->setLabel(std::string("Y")); - spinner3->setVisible(TRUE); - spinner3->setLabel(std::string("Z")); - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("X")); + mValSpinner2->setVisible(TRUE); + mValSpinner2->setLabel(LLStringExplicit("Y")); + mValSpinner3->setVisible(TRUE); + mValSpinner3->setLabel(LLStringExplicit("Z")); + if (!mValSpinner1->hasFocus()) { - spinner1->setPrecision(3); - spinner1->setValue(v[VX]); + mValSpinner1->setPrecision(3); + mValSpinner1->setValue(v[VX]); } - if (!spinner2->hasFocus()) + if (!mValSpinner2->hasFocus()) { - spinner2->setPrecision(3); - spinner2->setValue(v[VY]); + mValSpinner2->setPrecision(3); + mValSpinner2->setValue(v[VY]); } - if (!spinner3->hasFocus()) + if (!mValSpinner3->hasFocus()) { - spinner3->setPrecision(3); - spinner3->setValue(v[VZ]); + mValSpinner3->setPrecision(3); + mValSpinner3->setValue(v[VZ]); } break; } @@ -396,26 +441,26 @@ void LLFloaterSettingsDebug::updateControl() { LLVector3d v; v.setValue(sd); - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("X")); - spinner2->setVisible(TRUE); - spinner2->setLabel(std::string("Y")); - spinner3->setVisible(TRUE); - spinner3->setLabel(std::string("Z")); - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("X")); + mValSpinner2->setVisible(TRUE); + mValSpinner2->setLabel(LLStringExplicit("Y")); + mValSpinner3->setVisible(TRUE); + mValSpinner3->setLabel(LLStringExplicit("Z")); + if (!mValSpinner1->hasFocus()) { - spinner1->setPrecision(3); - spinner1->setValue(v[VX]); + mValSpinner1->setPrecision(3); + mValSpinner1->setValue(v[VX]); } - if (!spinner2->hasFocus()) + if (!mValSpinner2->hasFocus()) { - spinner2->setPrecision(3); - spinner2->setValue(v[VY]); + mValSpinner2->setPrecision(3); + mValSpinner2->setValue(v[VY]); } - if (!spinner3->hasFocus()) + if (!mValSpinner3->hasFocus()) { - spinner3->setPrecision(3); - spinner3->setValue(v[VZ]); + mValSpinner3->setPrecision(3); + mValSpinner3->setValue(v[VZ]); } break; } @@ -423,70 +468,70 @@ void LLFloaterSettingsDebug::updateControl() { LLRect r; r.setValue(sd); - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("Left")); - spinner2->setVisible(TRUE); - spinner2->setLabel(std::string("Right")); - spinner3->setVisible(TRUE); - spinner3->setLabel(std::string("Bottom")); - spinner4->setVisible(TRUE); - spinner4->setLabel(std::string("Top")); - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("Left")); + mValSpinner2->setVisible(TRUE); + mValSpinner2->setLabel(LLStringExplicit("Right")); + mValSpinner3->setVisible(TRUE); + mValSpinner3->setLabel(LLStringExplicit("Bottom")); + mValSpinner4->setVisible(TRUE); + mValSpinner4->setLabel(LLStringExplicit("Top")); + if (!mValSpinner1->hasFocus()) { - spinner1->setPrecision(0); - spinner1->setValue(r.mLeft); + mValSpinner1->setPrecision(0); + mValSpinner1->setValue(r.mLeft); } - if (!spinner2->hasFocus()) + if (!mValSpinner2->hasFocus()) { - spinner2->setPrecision(0); - spinner2->setValue(r.mRight); + mValSpinner2->setPrecision(0); + mValSpinner2->setValue(r.mRight); } - if (!spinner3->hasFocus()) + if (!mValSpinner3->hasFocus()) { - spinner3->setPrecision(0); - spinner3->setValue(r.mBottom); + mValSpinner3->setPrecision(0); + mValSpinner3->setValue(r.mBottom); } - if (!spinner4->hasFocus()) + if (!mValSpinner4->hasFocus()) { - spinner4->setPrecision(0); - spinner4->setValue(r.mTop); + mValSpinner4->setPrecision(0); + mValSpinner4->setValue(r.mTop); } - spinner1->setMinValue((F32)S32_MIN); - spinner1->setMaxValue((F32)S32_MAX); - spinner1->setIncrement(1.f); + mValSpinner1->setMinValue((F32)S32_MIN); + mValSpinner1->setMaxValue((F32)S32_MAX); + mValSpinner1->setIncrement(1.f); - spinner2->setMinValue((F32)S32_MIN); - spinner2->setMaxValue((F32)S32_MAX); - spinner2->setIncrement(1.f); + mValSpinner2->setMinValue((F32)S32_MIN); + mValSpinner2->setMaxValue((F32)S32_MAX); + mValSpinner2->setIncrement(1.f); - spinner3->setMinValue((F32)S32_MIN); - spinner3->setMaxValue((F32)S32_MAX); - spinner3->setIncrement(1.f); + mValSpinner3->setMinValue((F32)S32_MIN); + mValSpinner3->setMaxValue((F32)S32_MAX); + mValSpinner3->setIncrement(1.f); - spinner4->setMinValue((F32)S32_MIN); - spinner4->setMaxValue((F32)S32_MAX); - spinner4->setIncrement(1.f); + mValSpinner4->setMinValue((F32)S32_MIN); + mValSpinner4->setMaxValue((F32)S32_MAX); + mValSpinner4->setIncrement(1.f); break; } case TYPE_COL4: { LLColor4 clr; clr.setValue(sd); - color_swatch->setVisible(TRUE); + mValColor->setVisible(TRUE); // only set if changed so color picker doesn't update - if(clr != LLColor4(color_swatch->getValue())) + if(clr != LLColor4(mValColor->getValue())) { - color_swatch->set(LLColor4(sd), TRUE, FALSE); + mValColor->set(LLColor4(sd), TRUE, FALSE); } - spinner4->setVisible(TRUE); - spinner4->setLabel(std::string("Alpha")); - if (!spinner4->hasFocus()) + mValSpinner4->setVisible(TRUE); + mValSpinner4->setLabel(LLStringExplicit("Alpha")); + if (!mValSpinner4->hasFocus()) { - spinner4->setPrecision(3); - spinner4->setMinValue(0.0); - spinner4->setMaxValue(1.f); - spinner4->setValue(clr.mV[VALPHA]); + mValSpinner4->setPrecision(3); + mValSpinner4->setMinValue(0.0); + mValSpinner4->setMaxValue(1.f); + mValSpinner4->setValue(clr.mV[VALPHA]); } break; } @@ -494,35 +539,42 @@ void LLFloaterSettingsDebug::updateControl() { LLColor3 clr; clr.setValue(sd); - color_swatch->setVisible(TRUE); - color_swatch->setValue(sd); + mValColor->setVisible(TRUE); + mValColor->setValue(sd); break; } case TYPE_COL4U: { - LLColor4U clr; - clr.setValue(sd); - color_swatch->setVisible(TRUE); - if(LLColor4(clr) != LLColor4(color_swatch->getValue())) + LLColor4U clr(sd); + mValColor->setVisible(TRUE); + if (LLColor4(clr) != LLColor4(mValColor->getValue())) { - color_swatch->set(LLColor4(clr), TRUE, FALSE); + mValColor->set(LLColor4(clr), TRUE, FALSE); } - spinner4->setVisible(TRUE); - spinner4->setLabel(std::string("Alpha")); - if(!spinner4->hasFocus()) + mValSpinner4->setVisible(TRUE); + mValSpinner4->setLabel(std::string("Alpha")); + if(!mValSpinner4->hasFocus()) { - spinner4->setPrecision(0); - spinner4->setValue(clr.mV[VALPHA]); + mValSpinner4->setPrecision(0); + mValSpinner4->setValue(clr.mV[VALPHA]); } - spinner4->setMinValue(0); - spinner4->setMaxValue(255); - spinner4->setIncrement(1.f); + mValSpinner4->setMinValue(0); + mValSpinner4->setMaxValue(255); + mValSpinner4->setIncrement(1.f); break; } + case TYPE_LLSD: + mValText->setVisible(true); + { + std::ostringstream str; + LLSDSerialize::toPrettyXML(sd, str); + mValText->setValue(str.str()); + } + break; default: - mComment->setText(std::string("unknown")); + mComment->setText(LLStringExplicit("unknown")); break; } } @@ -536,49 +588,23 @@ void LLFloaterSettingsDebug::onUpdateFilter(const LLSD& value) void LLFloaterSettingsDebug::updateFilter(std::string searchTerm) { + LLStringUtil::toLower(searchTerm); + // make sure not to reselect the first item in the list on focus restore if (searchTerm == mOldSearchTerm) return; mOldSearchTerm = searchTerm; - LLStringUtil::toLower(searchTerm); - mSettingsScrollList->deleteAllItems(); - for(settings_map_t::iterator it = mSettingsMap.begin(); it != mSettingsMap.end(); it++) - { - bool addItem = searchTerm.empty(); - if (!addItem) - { - std::string itemValue = it->second->getName(); - - LLStringUtil::toLower(itemValue); - - if (itemValue.find(searchTerm, 0) != std::string::npos) - { - addItem = true; - } - else // performance: broken out to save toLower calls on comments - { - std::string itemComment = it->second->getComment(); - LLStringUtil::toLower(itemComment); - if (itemComment.find(searchTerm, 0) != std::string::npos) - addItem = true; - } - } + for(const auto& pair : mSettingsMap) + addRow(pair.second, searchTerm); - if (addItem) - { - LLSD item; - item["columns"][0]["value"] = it->second->getName(); - mSettingsScrollList->addElement(item, ADD_BOTTOM, it->second); - } - } mSettingsScrollList->sortByColumnIndex(0, true); // if at least one match was found, highlight and select the topmost entry in the list // but only if actually a search term was given - if (mSettingsScrollList->getItemCount() && !searchTerm.empty()) + if (!searchTerm.empty() && mSettingsScrollList->getItemCount()) mSettingsScrollList->selectFirstItem(); onSettingSelect(); diff --git a/indra/newview/llfloatersettingsdebug.h b/indra/newview/llfloatersettingsdebug.h index 5c94d6bd08..d9fd50e91a 100644 --- a/indra/newview/llfloatersettingsdebug.h +++ b/indra/newview/llfloatersettingsdebug.h @@ -36,10 +36,14 @@ #include "llcontrol.h" #include "llfloater.h" +class LLControlVariable; +class LLColorSwatchCtrl; class LLScrollListCtrl; +class LLSpinCtrl; class LLTextEditor; +class LLUICtrl; -class LLFloaterSettingsDebug +class LLFloaterSettingsDebug final : public LLFloater , public LLSingleton { @@ -47,8 +51,8 @@ class LLFloaterSettingsDebug LLFloaterSettingsDebug(); virtual ~LLFloaterSettingsDebug(); - virtual BOOL postBuild(); - virtual void draw(); + BOOL postBuild() override; + void draw() override; void updateControl(); @@ -64,6 +68,7 @@ class LLFloaterSettingsDebug private: // returns a pointer to the currently selected control variable, or NULL LLControlVariable* getControlVariable(); + void addRow(LLControlVariable* control, const std::string& searchTerm = LLStringUtil::null); protected: typedef std::map settings_map_t; @@ -72,11 +77,19 @@ class LLFloaterSettingsDebug std::string mOldSearchTerm; LLControlVariable* mCurrentControlVariable; - LLControlVariable* mOldControlVariable; bool mOldVisibility; LLScrollListCtrl* mSettingsScrollList; + LLSpinCtrl* mValSpinner1; + LLSpinCtrl* mValSpinner2; + LLSpinCtrl* mValSpinner3; + LLSpinCtrl* mValSpinner4; + LLColorSwatchCtrl* mValColor; + LLUICtrl* mValBool; + LLUICtrl* mValText; LLTextEditor* mComment; + LLView* mBtnCopy; + LLView* mBtnDefault; }; #endif //LLFLOATERDEBUGSETTINGS_H diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 44adf58d4a..7c63c0e773 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -54,7 +54,7 @@ #include "llfocusmgr.h" #include "llbutton.h" #include "llcombobox.h" -#include "lleconomy.h" +#include "llagentbenefits.h" #include "llsliderctrl.h" #include "llspinctrl.h" #include "llviewercontrol.h" @@ -552,13 +552,12 @@ void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y) alpha_color, TRUE); } // Draw border around captured part. - F32 line_width; - glGetFloatv(GL_LINE_WIDTH, &line_width); - glLineWidth(2.0f * line_width); + F32 line_width = gGL.getLineWidth(); + gGL.setLineWidth(2.0f * line_width); gl_rect_2d( mThumbnailPreviewRect.mLeft + offset_x, mThumbnailPreviewRect.mTop + offset_y, mThumbnailPreviewRect.mRight + offset_x, mThumbnailPreviewRect.mBottom + offset_y, LLColor4::black, FALSE); - glLineWidth(line_width); + gGL.setLineWidth(line_width); } //called when the frame is frozen. @@ -583,7 +582,7 @@ void LLSnapshotLivePreview::draw() gGL.pushMatrix(); { gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { gGL.texCoord2f(uv_width, uv_height); gGL.vertex2i(rect.getWidth(), rect.getHeight() ); @@ -591,11 +590,11 @@ void LLSnapshotLivePreview::draw() gGL.texCoord2f(0.f, uv_height); gGL.vertex2i(0, rect.getHeight() ); - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2i(0, 0); - gGL.texCoord2f(uv_width, 0.f); gGL.vertex2i(rect.getWidth(), 0); + + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2i(0, 0); } gGL.end(); } @@ -607,7 +606,7 @@ void LLSnapshotLivePreview::draw() { if (mFlashAlpha < 1.f) { - mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f)); + mFlashAlpha = lerp(mFlashAlpha, 1.f, LLSmoothInterpolation::getInterpolant(0.02f)); } else { @@ -616,7 +615,7 @@ void LLSnapshotLivePreview::draw() } else { - mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f)); + mFlashAlpha = lerp(mFlashAlpha, 0.f, LLSmoothInterpolation::getInterpolant(0.15f)); } if (mShineCountdown > 0) @@ -646,18 +645,18 @@ void LLSnapshotLivePreview::draw() S32 y2 = gViewerWindow->getWindowHeightScaled(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { gGL.color4f(1.f, 1.f, 1.f, 0.f); - gGL.vertex2i(x1, y1); gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2); + gGL.vertex2i(x1, y1); gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY); gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2); gGL.vertex2i(x2, y1); gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY); - gGL.vertex2i(x2, y1); gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2); + gGL.vertex2i(x2, y1); gGL.color4f(1.f, 1.f, 1.f, 0.f); gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2); gGL.vertex2i(x3, y1); @@ -678,27 +677,18 @@ void LLSnapshotLivePreview::draw() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4f(1.f, 1.f, 1.f, 1.f); LLRect outline_rect = mFullScreenImageRect; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); + gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop); gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); gGL.vertex2i(outline_rect.mRight, outline_rect.mTop); - gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop); - - gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom); - gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom); gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); + gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom); gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); - - gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop); gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom); - gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); - - gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom); - gGL.vertex2i(outline_rect.mRight, outline_rect.mTop); - gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); - gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); + gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop); } gGL.end(); } @@ -721,7 +711,7 @@ void LLSnapshotLivePreview::draw() LLRect const& rect = mFallFullScreenImageRect; gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom - ll_round(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f); gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { gGL.texCoord2f(uv_width, uv_height); gGL.vertex2i(rect.getWidth(), rect.getHeight() ); @@ -729,11 +719,11 @@ void LLSnapshotLivePreview::draw() gGL.texCoord2f(0.f, uv_height); gGL.vertex2i(0, rect.getHeight() ); - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2i(0, 0); - gGL.texCoord2f(uv_width, 0.f); gGL.vertex2i(rect.getWidth(), 0); + + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2i(0, 0); } gGL.end(); } @@ -1424,7 +1414,7 @@ void LLSnapshotLivePreview::saveTexture() std::string who_took_it; LLAgentUI::buildFullname(who_took_it); LLAssetStorage::LLStoreAssetCallback callback = &LLSnapshotLivePreview::saveTextureDone; - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); saveTextureUserData* user_data = new saveTextureUserData(this, sSnapshotIndex, gSavedSettings.getBOOL("TemporaryUpload")); if (upload_new_resource(tid, // tid LLAssetType::AT_TEXTURE, @@ -1555,7 +1545,7 @@ void LLSnapshotLivePreview::saveTextureDone(LLUUID const& asset_id, void* user_d // Call the default call back. LLAssetStorage::LLStoreAssetCallback asset_callback = temporary ? &temp_upload_callback : &upload_done_callback; - (*asset_callback)(asset_id, user_data, status, ext_status); + asset_callback(asset_id, user_data, status, ext_status); } // This callback used when the capability NewFileAgentInventory is available and it wasn't a temporary. @@ -1762,7 +1752,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater, bool de { DoutEntering(dc::snapshot, "LLFloaterSnapshot::Impl::updateControls()"); const HippoGridInfo& grid(*gHippoGridManager->getConnectedGrid()); - floater->childSetLabelArg("upload_btn", "[UPLOADFEE]", gSavedSettings.getBOOL("TemporaryUpload") ? (grid.getCurrencySymbol() + '0') : grid.getUploadFee()); + floater->childSetLabelArg("upload_btn", "[UPLOADFEE]", grid.formatFee(gSavedSettings.getBOOL("TemporaryUpload") ? 0 : LLAgentBenefitsMgr::current().getTextureUploadCost())); LLSnapshotLivePreview::ESnapshotType shot_type = (LLSnapshotLivePreview::ESnapshotType)gSavedSettings.getS32("LastSnapshotType"); ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); @@ -1867,7 +1857,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater, bool de { bytes_string = floater->getString("unknown"); } - S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); floater->childSetLabelArg("texture", "[AMOUNT]", llformat("%d",upload_cost)); floater->childSetLabelArg("upload_btn", "[AMOUNT]", llformat("%d",upload_cost)); floater->childSetTextArg("file_size_label", "[SIZE]", bytes_string); @@ -3196,16 +3186,9 @@ BOOL LLSnapshotFloaterView::handleKey(KEY key, MASK mask, BOOL called_from_paren return LLFloaterView::handleKey(key, mask, called_from_parent); } - if (called_from_parent) - { - // pass all keystrokes down - LLFloaterView::handleKey(key, mask, called_from_parent); - } - else - { - // bounce keystrokes back down - LLFloaterView::handleKey(key, mask, TRUE); - } + // pass all keystrokes down + // bounce keystrokes back down + LLFloaterView::handleKey(key, mask, TRUE); return TRUE; } diff --git a/indra/newview/llfloaterstats.cpp b/indra/newview/llfloaterstats.cpp index 53a6c17085..25243e9f2e 100644 --- a/indra/newview/llfloaterstats.cpp +++ b/indra/newview/llfloaterstats.cpp @@ -53,12 +53,11 @@ const S32 LL_SCROLL_BORDER = 1; void LLFloaterStats::buildStats() { LLRect rect; - LLStatBar *stat_barp; // // Viewer advanced stats // - LLStatView *stat_viewp = NULL; + LLStatView* stat_viewp = NULL; // // Viewer Basic @@ -73,51 +72,62 @@ void LLFloaterStats::buildStats() stat_viewp = LLUICtrlFactory::create(params); addStatView(stat_viewp); - stat_barp = stat_viewp->addStat("FPS", &(LLViewerStats::getInstance()->mFPSStat), - "DebugStatModeFPS", TRUE, TRUE); - stat_barp->setUnitLabel(" fps"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 60.f; - stat_barp->mTickSpacing = 3.f; - stat_barp->mLabelSpacing = 15.f; - stat_barp->mPrecision = 1; - - stat_barp = stat_viewp->addStat("Bandwidth", &(LLViewerStats::getInstance()->mKBitStat), - "DebugStatModeBandwidth", TRUE, FALSE); - stat_barp->setUnitLabel(" kbps"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 900.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 300.f; - - stat_barp = stat_viewp->addStat("Packet Loss", &(LLViewerStats::getInstance()->mPacketsLostPercentStat), "DebugStatModePacketLoss"); - stat_barp->setUnitLabel(" %"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 5.f; - stat_barp->mTickSpacing = 1.f; - stat_barp->mLabelSpacing = 1.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = TRUE; - stat_barp->mPrecision = 1; - - stat_barp = stat_viewp->addStat("Ping Sim", &(LLViewerStats::getInstance()->mSimPingStat), "DebugStatMode"); - stat_barp->setUnitLabel(" msec"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 1000.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 200.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - if(SGMemStat::haveStat()) { - stat_barp = stat_viewp->addStat("Allocated memory", &(LLViewerStats::getInstance()->mMallocStat), "DebugStatModeMalloc"); - stat_barp->setUnitLabel(" MB"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 2048.f; - stat_barp->mTickSpacing = 128.f; - stat_barp->mLabelSpacing = 512.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; + { + LLStatBar::Parameters params; + params.mUnitLabel = " fps"; + params.mMinBar = 0.f; + params.mMaxBar = 60.f; + params.mTickSpacing = 3.f; + params.mLabelSpacing = 15.f; + params.mPrecision = 1; + stat_viewp->addStat("FPS", &(LLViewerStats::getInstance()->mFPSStat), params, "DebugStatModeFPS", TRUE, TRUE); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " kbps"; + params.mMinBar = 0.f; + params.mMaxBar = 900.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 300.f; + stat_viewp->addStat("Bandwidth", &(LLViewerStats::getInstance()->mKBitStat), params, "DebugStatModeBandwidth", TRUE, FALSE); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " %"; + params.mMinBar = 0.f; + params.mMaxBar = 5.f; + params.mTickSpacing = 1.f; + params.mLabelSpacing = 1.f; + params.mPerSec = FALSE; + params.mDisplayMean = TRUE; + params.mDisplayMean = 1; + stat_viewp->addStat("Packet Loss", &(LLViewerStats::getInstance()->mPacketsLostPercentStat), params, "DebugStatModePacketLoss"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " msec"; + params.mMinBar = 0.f; + params.mMaxBar = 1000.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 200.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + stat_viewp->addStat("Ping Sim", &(LLViewerStats::getInstance()->mSimPingStat), params, "DebugStatMode"); + } + + if (SGMemStat::haveStat()) { + LLStatBar::Parameters params; + params.mUnitLabel = " MB"; + params.mMinBar = 0.f; + params.mMaxBar = 2048.f; + params.mTickSpacing = 128.f; + params.mLabelSpacing = 512.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + stat_viewp->addStat("Allocated memory", &(LLViewerStats::getInstance()->mMallocStat), params, "DebugStatModeMalloc"); } params.name("advanced stat view"); @@ -133,47 +143,63 @@ void LLFloaterStats::buildStats() params.label("Render"); params.setting("OpenDebugStatRender"); params.rect(rect); - LLStatView *render_statviewp = stat_viewp->addStatView(params); - - stat_barp = render_statviewp->addStat("KTris Drawn", &(LLViewerStats::getInstance()->mTrianglesDrawnStat), "DebugStatModeKTrisDrawnFr"); - stat_barp->setUnitLabel("/fr"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 3000.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 500.f; - stat_barp->mPrecision = 1; - stat_barp->mPerSec = FALSE; - - stat_barp = render_statviewp->addStat("KTris Drawn", &(LLViewerStats::getInstance()->mTrianglesDrawnStat), "DebugStatModeKTrisDrawnSec"); - stat_barp->setUnitLabel("/sec"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 100000.f; - stat_barp->mTickSpacing = 4000.f; - stat_barp->mLabelSpacing = 20000.f; - stat_barp->mPrecision = 1; - - stat_barp = render_statviewp->addStat("Total Objs", &(LLViewerStats::getInstance()->mNumObjectsStat), "DebugStatModeTotalObjs"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 10000.f; - stat_barp->mTickSpacing = 2500.f; - stat_barp->mLabelSpacing = 5000.f; - stat_barp->mPerSec = FALSE; - - stat_barp = render_statviewp->addStat("New Objs", &(LLViewerStats::getInstance()->mNumNewObjectsStat), "DebugStatModeNewObjs"); - stat_barp->setUnitLabel("/sec"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 1000.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 500.f; - stat_barp->mPerSec = TRUE; - - stat_barp = render_statviewp->addStat("Object Cache Hit Rate", &(LLViewerStats::getInstance()->mNumNewObjectsStat), std::string(), false, true); - stat_barp->setUnitLabel("%"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 100.f; - stat_barp->mTickSpacing = 20.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; + + LLStatView* render_statviewp = stat_viewp->addStatView(params); + + { + LLStatBar::Parameters params; + params.mUnitLabel = "/fr"; + params.mMinBar = 0.f; + params.mMaxBar = 3000.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 500.f; + params.mPrecision = 1; + params.mPerSec = FALSE; + render_statviewp->addStat("KTris Drawn", &(LLViewerStats::getInstance()->mTrianglesDrawnStat), params, "DebugStatModeKTrisDrawnFr"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = "/sec"; + params.mMinBar = 0.f; + params.mMaxBar = 100000.f; + params.mTickSpacing = 4000.f; + params.mLabelSpacing = 20000.f; + params.mPrecision = 1; + render_statviewp->addStat("KTris Drawn", &(LLViewerStats::getInstance()->mTrianglesDrawnStat), params, "DebugStatModeKTrisDrawnSec"); + } + + { + LLStatBar::Parameters params; + params.mMinBar = 0.f; + params.mMaxBar = 10000.f; + params.mTickSpacing = 2500.f; + params.mLabelSpacing = 5000.f; + params.mPerSec = FALSE; + render_statviewp->addStat("Total Objs", &(LLViewerStats::getInstance()->mNumObjectsStat), params, "DebugStatModeTotalObjs"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = "/sec"; + params.mMinBar = 0.f; + params.mMaxBar = 1000.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 500.f; + params.mPerSec = TRUE; + render_statviewp->addStat("New Objs", &(LLViewerStats::getInstance()->mNumNewObjectsStat), params, "DebugStatModeNewObjs"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = "%"; + params.mMinBar = 0.f; + params.mMaxBar = 100.f; + params.mTickSpacing = 20.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + render_statviewp->addStat("Object Cache Hit Rate", &(LLViewerStats::getInstance()->mNumNewObjectsStat), params, std::string(), false, true); + } // Texture statistics params.name("texture stat view"); @@ -181,152 +207,197 @@ void LLFloaterStats::buildStats() params.label("Texture"); params.setting("OpenDebugStatTexture"); params.rect(rect); - LLStatView *texture_statviewp = render_statviewp->addStatView(params); - - stat_barp = texture_statviewp->addStat("Cache Hit Rate", &(LLTextureFetch::sCacheHitRate), std::string(), false, true); - stat_barp->setUnitLabel("%"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 100.f; - stat_barp->mTickSpacing = 20.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - - stat_barp = texture_statviewp->addStat("Cache Read Latency", &(LLTextureFetch::sCacheReadLatency), std::string(), false, true); - stat_barp->setUnitLabel("msec"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 1000.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 200.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = texture_statviewp->addStat("Count", &(LLViewerStats::getInstance()->mNumImagesStat), "DebugStatModeTextureCount"); - stat_barp->setUnitLabel(""); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 8000.f; - stat_barp->mTickSpacing = 2000.f; - stat_barp->mLabelSpacing = 4000.f; - stat_barp->mPerSec = FALSE; - - stat_barp = texture_statviewp->addStat("Raw Count", &(LLViewerStats::getInstance()->mNumRawImagesStat), "DebugStatModeRawCount"); - stat_barp->setUnitLabel(""); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 8000.f; - stat_barp->mTickSpacing = 2000.f; - stat_barp->mLabelSpacing = 4000.f; - stat_barp->mPerSec = FALSE; - - stat_barp = texture_statviewp->addStat("GL Mem", &(LLViewerStats::getInstance()->mGLTexMemStat), "DebugStatModeGLMem"); - stat_barp->setUnitLabel(""); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 400.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 200.f; - stat_barp->mPrecision = 1; - stat_barp->mPerSec = FALSE; - - stat_barp = texture_statviewp->addStat("Formatted Mem", &(LLViewerStats::getInstance()->mFormattedMemStat), "DebugStatModeFormattedMem"); - stat_barp->setUnitLabel(""); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 400.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 200.f; - stat_barp->mPrecision = 1; - stat_barp->mPerSec = FALSE; - - stat_barp = texture_statviewp->addStat("Raw Mem", &(LLViewerStats::getInstance()->mRawMemStat), "DebugStatModeRawMem"); - stat_barp->setUnitLabel(""); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 400.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 200.f; - stat_barp->mPrecision = 1; - stat_barp->mPerSec = FALSE; - - stat_barp = texture_statviewp->addStat("Bound Mem", &(LLViewerStats::getInstance()->mGLBoundMemStat), "DebugStatModeBoundMem"); - stat_barp->setUnitLabel(""); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 400.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 200.f; - stat_barp->mPrecision = 1; - stat_barp->mPerSec = FALSE; - + LLStatView* texture_statviewp = render_statviewp->addStatView(params); + + { + LLStatBar::Parameters params; + params.mUnitLabel = "%"; + params.mMinBar = 0.f; + params.mMaxBar = 100.f; + params.mTickSpacing = 20.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + texture_statviewp->addStat("Cache Hit Rate", &(LLTextureFetch::sCacheHitRate), params, std::string(), false, true); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = "msec"; + params.mMinBar = 0.f; + params.mMaxBar = 1000.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 200.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + texture_statviewp->addStat("Cache Read Latency", &(LLTextureFetch::sCacheReadLatency), params, std::string(), false, true); + } + + { + LLStatBar::Parameters params; + params.mMinBar = 0.f; + params.mMaxBar = 8000.f; + params.mTickSpacing = 2000.f; + params.mLabelSpacing = 4000.f; + params.mPerSec = FALSE; + texture_statviewp->addStat("Count", &(LLViewerStats::getInstance()->mNumImagesStat), params, "DebugStatModeTextureCount"); + } + + { + LLStatBar::Parameters params; + params.mMinBar = 0.f; + params.mMaxBar = 8000.f; + params.mTickSpacing = 2000.f; + params.mLabelSpacing = 4000.f; + params.mPerSec = FALSE; + texture_statviewp->addStat("Raw Count", &(LLViewerStats::getInstance()->mNumRawImagesStat), params, "DebugStatModeRawCount"); + } + + { + LLStatBar::Parameters params; + params.mMinBar = 0.f; + params.mMaxBar = 400.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 200.f; + params.mPrecision = 1; + params.mPerSec = FALSE; + texture_statviewp->addStat("GL Mem", &(LLViewerStats::getInstance()->mGLTexMemStat), params, "DebugStatModeGLMem"); + } + + { + LLStatBar::Parameters params; + params.mMinBar = 0.f; + params.mMaxBar = 400.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 200.f; + params.mPrecision = 1; + params.mPerSec = FALSE; + texture_statviewp->addStat("Formatted Mem", &(LLViewerStats::getInstance()->mFormattedMemStat), params, "DebugStatModeFormattedMem"); + } + + { + LLStatBar::Parameters params; + params.mMinBar = 0.f; + params.mMaxBar = 400.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 200.f; + params.mPrecision = 1; + params.mPerSec = FALSE; + texture_statviewp->addStat("Raw Mem", &(LLViewerStats::getInstance()->mRawMemStat), params, "DebugStatModeRawMem"); + } + + { + LLStatBar::Parameters params; + params.mMinBar = 0.f; + params.mMaxBar = 400.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 200.f; + params.mPrecision = 1; + params.mPerSec = FALSE; + texture_statviewp->addStat("Bound Mem", &(LLViewerStats::getInstance()->mGLBoundMemStat), params, "DebugStatModeBoundMem"); + } + // Network statistics params.name("network stat view"); params.show_label(true); params.label("Network"); params.setting("OpenDebugStatNet"); params.rect(rect); - LLStatView *net_statviewp = stat_viewp->addStatView(params); - - stat_barp = net_statviewp->addStat("UDP Packets In", &(LLViewerStats::getInstance()->mPacketsInStat), "DebugStatModePacketsIn"); - stat_barp->setUnitLabel("/sec"); - - stat_barp = net_statviewp->addStat("UDP Packets Out", &(LLViewerStats::getInstance()->mPacketsOutStat), "DebugStatModePacketsOut"); - stat_barp->setUnitLabel("/sec"); - - stat_barp = net_statviewp->addStat("HTTP Textures", &(LLViewerStats::getInstance()->mHTTPTextureKBitStat), "DebugStatModeHTTPTexture"); - stat_barp->setUnitLabel(" kbps"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = gSavedSettings.getF32("HTTPThrottleBandwidth"); - stat_barp->mMaxBar *= llclamp(2.0 - (stat_barp->mMaxBar - 400.f) / 3600.f, 1.0, 2.0); // Allow for overshoot (allow more for low bandwidth values). - stat_barp->mTickSpacing = 1.f; - while (stat_barp->mTickSpacing < stat_barp->mMaxBar / 8) - stat_barp->mTickSpacing *= 2.f; - stat_barp->mLabelSpacing = 2 * stat_barp->mTickSpacing; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = net_statviewp->addStat("UDP Textures", &(LLViewerStats::getInstance()->mUDPTextureKBitStat), "DebugStatModeUDPTexture"); - stat_barp->setUnitLabel(" kbps"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 1024.f; - stat_barp->mTickSpacing = 128.f; - stat_barp->mLabelSpacing = 256.f; - - stat_barp = net_statviewp->addStat("Objects (UDP)", &(LLViewerStats::getInstance()->mObjectKBitStat), "DebugStatModeObjects"); - stat_barp->setUnitLabel(" kbps"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 1024.f; - stat_barp->mTickSpacing = 128.f; - stat_barp->mLabelSpacing = 256.f; - - stat_barp = net_statviewp->addStat("Assets (UDP)", &(LLViewerStats::getInstance()->mAssetKBitStat), "DebugStatModeAsset"); - stat_barp->setUnitLabel(" kbps"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 1024.f; - stat_barp->mTickSpacing = 128.f; - stat_barp->mLabelSpacing = 256.f; - - stat_barp = net_statviewp->addStat("Layers (UDP)", &(LLViewerStats::getInstance()->mLayersKBitStat), "DebugStatModeLayers"); - stat_barp->setUnitLabel(" kbps"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 1024.f; - stat_barp->mTickSpacing = 128.f; - stat_barp->mLabelSpacing = 256.f; - - stat_barp = net_statviewp->addStat("Actual In (UDP)", &(LLViewerStats::getInstance()->mActualInKBitStat), - "DebugStatModeActualIn", TRUE, FALSE); - stat_barp->setUnitLabel(" kbps"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 1024.f; - stat_barp->mTickSpacing = 128.f; - stat_barp->mLabelSpacing = 256.f; - - stat_barp = net_statviewp->addStat("Actual Out (UDP)", &(LLViewerStats::getInstance()->mActualOutKBitStat), - "DebugStatModeActualOut", TRUE, FALSE); - stat_barp->setUnitLabel(" kbps"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 512.f; - stat_barp->mTickSpacing = 128.f; - stat_barp->mLabelSpacing = 256.f; - - stat_barp = net_statviewp->addStat("VFS Pending Ops", &(LLViewerStats::getInstance()->mVFSPendingOperations), - "DebugStatModeVFSPendingOps"); - stat_barp->setUnitLabel(" "); - stat_barp->mPerSec = FALSE; + LLStatView* net_statviewp = stat_viewp->addStatView(params); + + { + LLStatBar::Parameters params; + params.mUnitLabel = "/sec"; + net_statviewp->addStat("UDP Packets In", &(LLViewerStats::getInstance()->mPacketsInStat), params, "DebugStatModePacketsIn"); + + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = "/sec"; + net_statviewp->addStat("UDP Packets Out", &(LLViewerStats::getInstance()->mPacketsOutStat), params, "DebugStatModePacketsOut"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " kbps"; + params.mMinBar = 0.f; + params.mMaxBar = gSavedSettings.getF32("HTTPThrottleBandwidth"); + params.mMaxBar *= llclamp(2.0 - (params.mMaxBar - 400.f) / 3600.f, 1.0, 2.0); // Allow for overshoot (allow more for low bandwidth values). + params.mTickSpacing = 1.f; + while (params.mTickSpacing < params.mMaxBar / 8) + params.mTickSpacing *= 2.f; + params.mLabelSpacing = 2 * params.mTickSpacing; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + net_statviewp->addStat("HTTP Textures", &(LLViewerStats::getInstance()->mHTTPTextureKBitStat), params, "DebugStatModeHTTPTexture"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " kbps"; + params.mMinBar = 0.f; + params.mMaxBar = 1024.f; + params.mTickSpacing = 128.f; + params.mLabelSpacing = 256.f; + net_statviewp->addStat("UDP Textures", &(LLViewerStats::getInstance()->mUDPTextureKBitStat), params, "DebugStatModeUDPTexture"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " kbps"; + params.mMinBar = 0.f; + params.mMaxBar = 1024.f; + params.mTickSpacing = 128.f; + params.mLabelSpacing = 256.f; + net_statviewp->addStat("Objects (UDP)", &(LLViewerStats::getInstance()->mObjectKBitStat), params, "DebugStatModeObjects"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " kbps"; + params.mMinBar = 0.f; + params.mMaxBar = 1024.f; + params.mTickSpacing = 128.f; + params.mLabelSpacing = 256.f; + net_statviewp->addStat("Assets (UDP)", &(LLViewerStats::getInstance()->mAssetKBitStat), params, "DebugStatModeAsset"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " kbps"; + params.mMinBar = 0.f; + params.mMaxBar = 1024.f; + params.mTickSpacing = 128.f; + params.mLabelSpacing = 256.f; + net_statviewp->addStat("Layers (UDP)", &(LLViewerStats::getInstance()->mLayersKBitStat), params, "DebugStatModeLayers"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " kbps"; + params.mMinBar = 0.f; + params.mMaxBar = 1024.f; + params.mTickSpacing = 128.f; + params.mLabelSpacing = 256.f; + net_statviewp->addStat("Actual In (UDP)", &(LLViewerStats::getInstance()->mActualInKBitStat), params, "DebugStatModeActualIn", TRUE, FALSE); + } + { + LLStatBar::Parameters params; + params.mUnitLabel = " kbps"; + params.mMinBar = 0.f; + params.mMaxBar = 512.f; + params.mTickSpacing = 128.f; + params.mLabelSpacing = 256.f; + net_statviewp->addStat("Actual Out (UDP)", &(LLViewerStats::getInstance()->mActualOutKBitStat), params, "DebugStatModeActualOut", TRUE, FALSE); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " "; + params.mPerSec = FALSE; + net_statviewp->addStat("VFS Pending Ops", &(LLViewerStats::getInstance()->mVFSPendingOperations), params, "DebugStatModeVFSPendingOps"); + } // Simulator stats params.name("sim stat view"); @@ -334,312 +405,401 @@ void LLFloaterStats::buildStats() params.label("Simulator"); params.setting("OpenDebugStatSim"); params.rect(rect); - LLStatView *sim_statviewp = LLUICtrlFactory::create(params); + LLStatView* sim_statviewp = LLUICtrlFactory::create(params); addStatView(sim_statviewp); - stat_barp = sim_statviewp->addStat("Time Dilation", &(LLViewerStats::getInstance()->mSimTimeDilation), "DebugStatModeTimeDialation"); - stat_barp->mPrecision = 2; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 1.f; - stat_barp->mTickSpacing = 0.25f; - stat_barp->mLabelSpacing = 0.5f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Sim FPS", &(LLViewerStats::getInstance()->mSimFPS), "DebugStatModeSimFPS"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 200.f; - stat_barp->mTickSpacing = 20.f; - stat_barp->mLabelSpacing = 100.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Physics FPS", &(LLViewerStats::getInstance()->mSimPhysicsFPS), "DebugStatModePhysicsFPS"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 66.f; - stat_barp->mTickSpacing = 33.f; - stat_barp->mLabelSpacing = 33.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; + { + LLStatBar::Parameters params; + params.mPrecision = 2; + params.mMinBar = 0.f; + params.mMaxBar = 1.f; + params.mTickSpacing = 0.25f; + params.mLabelSpacing = 0.5f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Time Dilation", &(LLViewerStats::getInstance()->mSimTimeDilation), params, "DebugStatModeTimeDialation"); + } + + { + LLStatBar::Parameters params; + params.mMinBar = 0.f; + params.mMaxBar = 200.f; + params.mTickSpacing = 20.f; + params.mLabelSpacing = 100.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Sim FPS", &(LLViewerStats::getInstance()->mSimFPS), params, "DebugStatModeSimFPS"); + } + + { + LLStatBar::Parameters params; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 66.f; + params.mTickSpacing = 33.f; + params.mLabelSpacing = 33.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Physics FPS", &(LLViewerStats::getInstance()->mSimPhysicsFPS), params, "DebugStatModePhysicsFPS"); + } params.name("phys detail view"); params.show_label(true); params.label("Physics Details"); params.setting("OpenDebugStatPhysicsDetails"); params.rect(rect); - LLStatView *phys_details_viewp = sim_statviewp->addStatView(params); - - stat_barp = phys_details_viewp->addStat("Pinned Objects", &(LLViewerStats::getInstance()->mPhysicsPinnedTasks), "DebugStatModePinnedObjects"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 500.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 40.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = phys_details_viewp->addStat("Low LOD Objects", &(LLViewerStats::getInstance()->mPhysicsLODTasks), "DebugStatModeLowLODObjects"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 500.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 40.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = phys_details_viewp->addStat("Memory Allocated", &(LLViewerStats::getInstance()->mPhysicsMemoryAllocated), "DebugStatModeMemoryAllocated"); - stat_barp->setUnitLabel(" MB"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 1024.f; - stat_barp->mTickSpacing = 128.f; - stat_barp->mLabelSpacing = 256.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Agent Updates/Sec", &(LLViewerStats::getInstance()->mSimAgentUPS), "DebugStatModeAgentUpdatesSec"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 100.f; - stat_barp->mTickSpacing = 25.f; - stat_barp->mLabelSpacing = 50.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Main Agents", &(LLViewerStats::getInstance()->mSimMainAgents), "DebugStatModeMainAgents"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 80.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 40.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Child Agents", &(LLViewerStats::getInstance()->mSimChildAgents), "DebugStatModeChildAgents"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 5.f; - stat_barp->mLabelSpacing = 10.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Objects", &(LLViewerStats::getInstance()->mSimObjects), "DebugStatModeSimObjects"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 30000.f; - stat_barp->mTickSpacing = 5000.f; - stat_barp->mLabelSpacing = 10000.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Active Objects", &(LLViewerStats::getInstance()->mSimActiveObjects), "DebugStatModeSimActiveObjects"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 800.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 200.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Active Scripts", &(LLViewerStats::getInstance()->mSimActiveScripts), "DebugStatModeSimActiveScripts"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 800.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 200.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Scripts Run", &(LLViewerStats::getInstance()->mSimPctScriptsRun), std::string(), false, true); - stat_barp->setUnitLabel("%"); - stat_barp->mPrecision = 3; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 100.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - - stat_barp = sim_statviewp->addStat("Script Events", &(LLViewerStats::getInstance()->mSimScriptEPS), "DebugStatModeSimScriptEvents"); - stat_barp->setUnitLabel(" eps"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 20000.f; - stat_barp->mTickSpacing = 2500.f; - stat_barp->mLabelSpacing = 5000.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; + LLStatView* phys_details_viewp = sim_statviewp->addStatView(params); + + { + LLStatBar::Parameters params; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 500.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 40.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + phys_details_viewp->addStat("Pinned Objects", &(LLViewerStats::getInstance()->mPhysicsPinnedTasks), params, "DebugStatModePinnedObjects"); + } + + { + LLStatBar::Parameters params; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 500.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 40.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + phys_details_viewp->addStat("Low LOD Objects", &(LLViewerStats::getInstance()->mPhysicsLODTasks), params, "DebugStatModeLowLODObjects"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " MB"; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 1024.f; + params.mTickSpacing = 128.f; + params.mLabelSpacing = 256.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + phys_details_viewp->addStat("Memory Allocated", &(LLViewerStats::getInstance()->mPhysicsMemoryAllocated), params, "DebugStatModeMemoryAllocated"); + } + + { + LLStatBar::Parameters params; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 100.f; + params.mTickSpacing = 25.f; + params.mLabelSpacing = 50.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Agent Updates/Sec", &(LLViewerStats::getInstance()->mSimAgentUPS), params, "DebugStatModeAgentUpdatesSec"); + } + + { + LLStatBar::Parameters params; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 80.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 40.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Main Agents", &(LLViewerStats::getInstance()->mSimMainAgents), params, "DebugStatModeMainAgents"); + } + + { + LLStatBar::Parameters params; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 5.f; + params.mLabelSpacing = 10.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Child Agents", &(LLViewerStats::getInstance()->mSimChildAgents), params, "DebugStatModeChildAgents"); + } + + { + LLStatBar::Parameters params; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 30000.f; + params.mTickSpacing = 5000.f; + params.mLabelSpacing = 10000.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Objects", &(LLViewerStats::getInstance()->mSimObjects), params, "DebugStatModeSimObjects"); + } + + { + LLStatBar::Parameters params; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 800.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 200.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Active Objects", &(LLViewerStats::getInstance()->mSimActiveObjects), params, "DebugStatModeSimActiveObjects"); + } + + { + LLStatBar::Parameters params; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 800.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 200.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Active Scripts", &(LLViewerStats::getInstance()->mSimActiveScripts), params, "DebugStatModeSimActiveScripts"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = "%"; + params.mPrecision = 3; + params.mMinBar = 0.f; + params.mMaxBar = 100.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + sim_statviewp->addStat("Scripts Run", &(LLViewerStats::getInstance()->mSimPctScriptsRun), params, std::string(), false, true); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " eps"; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 20000.f; + params.mTickSpacing = 2500.f; + params.mLabelSpacing = 5000.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Script Events", &(LLViewerStats::getInstance()->mSimScriptEPS), params, "DebugStatModeSimScriptEvents"); + } params.name("pathfinding view"); params.show_label(true); params.label("Pathfinding Details"); params.rect(rect); - LLStatView *pathfinding_viewp = sim_statviewp->addStatView(params); - - stat_barp = pathfinding_viewp->addStat("AI Step Time", &(LLViewerStats::getInstance()->mSimSimAIStepMsec)); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 3; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = render_statviewp->addStat("Skipped Silhouette Steps", &(LLViewerStats::getInstance()->mSimSimSkippedSilhouetteSteps)); - stat_barp->setUnitLabel("/sec"); - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 45.f; - stat_barp->mTickSpacing = 4.f; - stat_barp->mLabelSpacing = 8.f; - stat_barp->mPrecision = 0; - - stat_barp = pathfinding_viewp->addStat("Characters Updated", &(LLViewerStats::getInstance()->mSimSimPctSteppedCharacters)); - stat_barp->setUnitLabel("%"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 100.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = TRUE; - - stat_barp = sim_statviewp->addStat("Packets In", &(LLViewerStats::getInstance()->mSimInPPS), "DebugStatModeSimInPPS"); - stat_barp->setUnitLabel(" pps"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 2000.f; - stat_barp->mTickSpacing = 250.f; - stat_barp->mLabelSpacing = 1000.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Packets Out", &(LLViewerStats::getInstance()->mSimOutPPS), "DebugStatModeSimOutPPS"); - stat_barp->setUnitLabel(" pps"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 2000.f; - stat_barp->mTickSpacing = 250.f; - stat_barp->mLabelSpacing = 1000.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Pending Downloads", &(LLViewerStats::getInstance()->mSimPendingDownloads), "DebugStatModeSimPendingDownloads"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 800.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 200.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Pending Uploads", &(LLViewerStats::getInstance()->mSimPendingUploads), "SimPendingUploads"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 100.f; - stat_barp->mTickSpacing = 25.f; - stat_barp->mLabelSpacing = 50.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_statviewp->addStat("Total Unacked Bytes", &(LLViewerStats::getInstance()->mSimTotalUnackedBytes), "DebugStatModeSimTotalUnackedBytes"); - stat_barp->setUnitLabel(" kb"); - stat_barp->mPrecision = 0; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 100000.f; - stat_barp->mTickSpacing = 25000.f; - stat_barp->mLabelSpacing = 50000.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; + LLStatView* pathfinding_viewp = sim_statviewp->addStatView(params); + + { + LLStatBar::Parameters params; + params.mUnitLabel = "ms"; + params.mPrecision = 3; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + pathfinding_viewp->addStat("AI Step Time", &(LLViewerStats::getInstance()->mSimSimAIStepMsec), params); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = "/sec"; + params.mMinBar = 0.f; + params.mMaxBar = 45.f; + params.mTickSpacing = 4.f; + params.mLabelSpacing = 8.f; + params.mPrecision = 0; + render_statviewp->addStat("Skipped Silhouette Steps", &(LLViewerStats::getInstance()->mSimSimSkippedSilhouetteSteps), params); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = "%"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 100.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = TRUE; + pathfinding_viewp->addStat("Characters Updated", &(LLViewerStats::getInstance()->mSimSimPctSteppedCharacters), params); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " pps"; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 2000.f; + params.mTickSpacing = 250.f; + params.mLabelSpacing = 1000.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Packets In", &(LLViewerStats::getInstance()->mSimInPPS), params, "DebugStatModeSimInPPS"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " pps"; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 2000.f; + params.mTickSpacing = 250.f; + params.mLabelSpacing = 1000.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Packets Out", &(LLViewerStats::getInstance()->mSimOutPPS), params, "DebugStatModeSimOutPPS"); + } + + { + LLStatBar::Parameters params; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 800.f; + params.mTickSpacing = 100.f; + params.mLabelSpacing = 200.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Pending Downloads", &(LLViewerStats::getInstance()->mSimPendingDownloads), params, "DebugStatModeSimPendingDownloads"); + } + + { + LLStatBar::Parameters params; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 100.f; + params.mTickSpacing = 25.f; + params.mLabelSpacing = 50.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Pending Uploads", &(LLViewerStats::getInstance()->mSimPendingUploads), params, "SimPendingUploads"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = " kb"; + params.mPrecision = 0; + params.mMinBar = 0.f; + params.mMaxBar = 100000.f; + params.mTickSpacing = 25000.f; + params.mLabelSpacing = 50000.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_statviewp->addStat("Total Unacked Bytes", &(LLViewerStats::getInstance()->mSimTotalUnackedBytes), params, "DebugStatModeSimTotalUnackedBytes"); + } params.name("sim perf view"); params.show_label(true); params.label("Time (ms)"); params.setting("OpenDebugStatSimTime"); params.rect(rect); - LLStatView *sim_time_viewp = sim_statviewp->addStatView(params); - - stat_barp = sim_time_viewp->addStat("Total Frame Time", &(LLViewerStats::getInstance()->mSimFrameMsec), "DebugStatModeSimFrameMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_time_viewp->addStat("Net Time", &(LLViewerStats::getInstance()->mSimNetMsec), "DebugStatModeSimNetMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_time_viewp->addStat("Physics Time", &(LLViewerStats::getInstance()->mSimSimPhysicsMsec), "DebugStatModeSimSimPhysicsMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_time_viewp->addStat("Simulation Time", &(LLViewerStats::getInstance()->mSimSimOtherMsec), "DebugStatModeSimSimOtherMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_time_viewp->addStat("Agent Time", &(LLViewerStats::getInstance()->mSimAgentMsec), "DebugStatModeSimAgentMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_time_viewp->addStat("Images Time", &(LLViewerStats::getInstance()->mSimImagesMsec), "DebugStatModeSimImagesMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_time_viewp->addStat("Script Time", &(LLViewerStats::getInstance()->mSimScriptMsec), "DebugStatModeSimScriptMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = sim_time_viewp->addStat("Spare Time", &(LLViewerStats::getInstance()->mSimSpareMsec), "DebugStatModeSimSpareMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; + LLStatView* sim_time_viewp = sim_statviewp->addStatView(params); + + { + LLStatBar::Parameters params; + params.mUnitLabel = "ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_time_viewp->addStat("Total Frame Time", &(LLViewerStats::getInstance()->mSimFrameMsec), params, "DebugStatModeSimFrameMsec"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = "ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_time_viewp->addStat("Net Time", &(LLViewerStats::getInstance()->mSimNetMsec), params, "DebugStatModeSimNetMsec"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel = "ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_time_viewp->addStat("Physics Time", &(LLViewerStats::getInstance()->mSimSimPhysicsMsec), params, "DebugStatModeSimSimPhysicsMsec"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel ="ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_time_viewp->addStat("Simulation Time", &(LLViewerStats::getInstance()->mSimSimOtherMsec), params, "DebugStatModeSimSimOtherMsec"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel ="ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_time_viewp->addStat("Agent Time", &(LLViewerStats::getInstance()->mSimAgentMsec), params, "DebugStatModeSimAgentMsec"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel ="ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_time_viewp->addStat("Images Time", &(LLViewerStats::getInstance()->mSimImagesMsec), params, "DebugStatModeSimImagesMsec"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel ="ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_time_viewp->addStat("Script Time", &(LLViewerStats::getInstance()->mSimScriptMsec), params, "DebugStatModeSimScriptMsec"); + } + { + LLStatBar::Parameters params; + params.mUnitLabel = "ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + sim_time_viewp->addStat("Spare Time", &(LLViewerStats::getInstance()->mSimSpareMsec), params, "DebugStatModeSimSpareMsec"); + } // 2nd level time blocks under 'Details' second params.name("sim perf view"); @@ -648,56 +808,70 @@ void LLFloaterStats::buildStats() params.setting("OpenDebugStatSimTimeDetails"); params.rect(rect); LLStatView *detailed_time_viewp = sim_time_viewp->addStatView(params); + + { + LLStatBar::Parameters params; + params.mUnitLabel ="ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + detailed_time_viewp->addStat(" Physics Step", &(LLViewerStats::getInstance()->mSimSimPhysicsStepMsec), params, "DebugStatModeSimSimPhysicsStepMsec"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel ="ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + detailed_time_viewp->addStat(" Update Physics Shapes", &(LLViewerStats::getInstance()->mSimSimPhysicsShapeUpdateMsec), params, "DebugStatModeSimSimPhysicsShapeUpdateMsec"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel ="ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + detailed_time_viewp->addStat(" Physics Other", &(LLViewerStats::getInstance()->mSimSimPhysicsOtherMsec), params, "DebugStatModeSimSimPhysicsOtherMsec"); + } + + { + LLStatBar::Parameters params; + params.mUnitLabel ="ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + detailed_time_viewp->addStat(" Sleep Time", &(LLViewerStats::getInstance()->mSimSleepMsec), params, "DebugStatModeSimSleepMsec"); + } + { - stat_barp = detailed_time_viewp->addStat(" Physics Step", &(LLViewerStats::getInstance()->mSimSimPhysicsStepMsec), "DebugStatModeSimSimPhysicsStepMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = detailed_time_viewp->addStat(" Update Physics Shapes", &(LLViewerStats::getInstance()->mSimSimPhysicsShapeUpdateMsec), "DebugStatModeSimSimPhysicsShapeUpdateMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = detailed_time_viewp->addStat(" Physics Other", &(LLViewerStats::getInstance()->mSimSimPhysicsOtherMsec), "DebugStatModeSimSimPhysicsOtherMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = detailed_time_viewp->addStat(" Sleep Time", &(LLViewerStats::getInstance()->mSimSleepMsec), "DebugStatModeSimSleepMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; - - stat_barp = detailed_time_viewp->addStat(" Pump IO", &(LLViewerStats::getInstance()->mSimPumpIOMsec), "DebugStatModeSimPumpIOMsec"); - stat_barp->setUnitLabel("ms"); - stat_barp->mPrecision = 1; - stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 40.f; - stat_barp->mTickSpacing = 10.f; - stat_barp->mLabelSpacing = 20.f; - stat_barp->mPerSec = FALSE; - stat_barp->mDisplayMean = FALSE; + LLStatBar::Parameters params; + params.mUnitLabel ="ms"; + params.mPrecision = 1; + params.mMinBar = 0.f; + params.mMaxBar = 40.f; + params.mTickSpacing = 10.f; + params.mLabelSpacing = 20.f; + params.mPerSec = FALSE; + params.mDisplayMean = FALSE; + detailed_time_viewp->addStat(" Pump IO", &(LLViewerStats::getInstance()->mSimPumpIOMsec), params, "DebugStatModeSimPumpIOMsec"); } LLRect r = getRect(); diff --git a/indra/newview/llfloaterteleporthistory.cpp b/indra/newview/llfloaterteleporthistory.cpp index ceac57f0f2..f3369782dc 100644 --- a/indra/newview/llfloaterteleporthistory.cpp +++ b/indra/newview/llfloaterteleporthistory.cpp @@ -157,7 +157,12 @@ void LLFloaterTeleportHistory::addEntry(std::string parcelName) // add the new list entry on top of the list, deselect all and disable the buttons const S32 max_entries = gSavedSettings.getS32("TeleportHistoryMaxEntries"); S32 num_entries = mPlacesList->getItemCount(); - while(num_entries >= max_entries) + if (max_entries <= 0) + { + if (!max_entries) + mPlacesList->clearRows(); + } + else while(num_entries >= max_entries) { mPlacesList->deleteItems(LLSD(mID - num_entries--)); } @@ -212,7 +217,7 @@ void LLFloaterTeleportHistory::loadFile(const std::string &file_name) else { const S32 max_entries = gSavedSettings.getS32("TeleportHistoryMaxEntries"); - const S32 num_entries = llmin(max_entries,(const S32)data.size()); + const S32 num_entries = llmin(max_entries < 0 ? S32_MAX : max_entries,(const S32)data.size()); pScrollList->clear(); for(S32 i = 0; i < num_entries; i++) //Lower entry = newer { diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 5087b89e84..55847532ac 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -538,36 +538,74 @@ void LLFloaterTools::refresh() else #endif { - F32 link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetCost(); - S32 link_count = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount(); - + auto selection = LLSelectMgr::getInstance()->getSelection(); + F32 link_cost = selection->getSelectedLinksetCost(); + S32 link_count = selection->getRootObjectCount(); + S32 prim_count = selection->getObjectCount(); + auto child = getChild("link_num_obj_count"); + auto selected_face = -1; + if (auto node = prim_count == 1 ? *selection->begin() : nullptr) + //for (const auto& node : selection) // All selected objects + { + // TODO: Count selected faces? What use is there for this? + if (node->getTESelectMask() == 0xFFFFFFFF) // All faces selected + { + selected_face = -2; // Multiple + } + if (const auto& obj = node->getObject()) // This node's object + { + //if (!obj->isSelected()) continue; + const auto& numTEs = obj->getNumTEs(); + for (S32 te = 0; selected_face != -2 && te < numTEs; ++te) // Faces + { + if (!node->isTESelected(te)) continue; + if (selected_face != -1) + { + selected_face = -2; // Multiple + } + else selected_face = te; + } + } + //if (selected_face == -2) break; + } // Added in Link Num value -HgB - S32 prim_count = LLSelectMgr::getInstance()->getEditSelection()->getObjectCount(); std::string value_string; - bool edit_linked(gSavedSettings.getBOOL("EditLinkedParts")); - if (edit_linked && prim_count == 1) //Selecting a single prim in "Edit Linked" mode, show link number + bool edit_linked(mCheckSelectIndividual->getValue()); + if (mRadioSelectFace->getValue() || selected_face > 0) // In select faces mode, show either multiple or the face number, otherwise only show if single face selected + { + child->setTextArg("[DESC]", getString("Selected Face:")); + if (selected_face < 0) + { + value_string = LLTrans::getString(selected_face == -1 && !prim_count ? "None" : "multiple_textures"); + } + else LLResMgr::getInstance()->getIntegerString(value_string, selected_face); + } + else if (edit_linked && prim_count == 1) //Selecting a single prim in "Edit Linked" mode, show link number { - link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectCost(); - childSetTextArg("link_num_obj_count", "[DESC]", std::string("Link number:")); + link_cost = selection->getSelectedObjectCost(); + child->setTextArg("[DESC]", getString("Link number:")); - LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - if (selected && selected->getRootEdit()) + if (LLViewerObject* selected = selection->getFirstObject()) { - LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren(); - if (children.empty()) + if (auto root = selected->getRootEdit()) { - value_string = "0"; // An unlinked prim is "link 0". - } - else - { - children.push_front(selected->getRootEdit()); // need root in the list too - S32 index = 1; - for (LLViewerObject::child_list_t::iterator iter = children.begin(); iter != children.end(); ++iter, ++index) + LLViewerObject::child_list_t children = root->getChildren(); + if (children.empty()) + { + value_string = "0"; // An unlinked prim is "link 0". + } + else { - if ((*iter)->isSelected()) + children.push_front(selected->getRootEdit()); // need root in the list too + S32 index = 1; + for (const auto& child : children) { - LLResMgr::getInstance()->getIntegerString(value_string, index); - break; + if (child->isSelected()) + { + LLResMgr::getInstance()->getIntegerString(value_string, index); + break; + } + ++index; } } } @@ -575,16 +613,16 @@ void LLFloaterTools::refresh() } else if (edit_linked) { - childSetTextArg("link_num_obj_count", "[DESC]", std::string("Selected prims:")); + child->setTextArg("[DESC]", getString("Selected prims:")); LLResMgr::getInstance()->getIntegerString(value_string, prim_count); - link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectCost(); + link_cost = selection->getSelectedObjectCost(); } else { - childSetTextArg("link_num_obj_count", "[DESC]", std::string("Selected objects:")); + child->setTextArg("[DESC]", getString("Selected objects:")); LLResMgr::getInstance()->getIntegerString(value_string, link_count); } - childSetTextArg("link_num_obj_count", "[NUM]", value_string); + child->setTextArg("[NUM]", value_string); /* Singu Note: We're not using this yet because we have no place to put it LLCrossParcelFunctor func; @@ -610,18 +648,17 @@ void LLFloaterTools::refresh() } } - LLStringUtil::format_map_t selection_args; - selection_args["OBJ_COUNT"] = llformat("%.1d", prim_count); - selection_args["LAND_IMPACT"] = llformat(edit_linked ? "%.2f" : "%.0f", link_cost); - - std::ostringstream selection_info; - - selection_info << getString("status_selectcount", selection_args); - - getChild("selection_count")->setText(selection_info.str()); + auto sel_count = getChild("selection_count"); + bool have_selection = !selection->isEmpty(); + if (have_selection) + { + LLStringUtil::format_map_t selection_args; + selection_args["OBJ_COUNT"] = llformat("%.1d", prim_count); + selection_args["LAND_IMPACT"] = llformat(edit_linked ? "%.2f" : "%.0f", link_cost); - bool have_selection = !LLSelectMgr::getInstance()->getSelection()->isEmpty(); - childSetVisible("selection_count", have_selection); + sel_count->setText(getString("status_selectcount", selection_args)); + } + sel_count->setVisible(have_selection); //childSetVisible("remaining_capacity", have_selection); childSetVisible("selection_empty", !have_selection); } @@ -1346,8 +1383,8 @@ void LLFloaterTools::getMediaState() for ( ; iter != end; ++iter) { LLSelectNode* node = *iter; - LLVOVolume* object = dynamic_cast(node->getObject()); - if (NULL != object) + LLVOVolume* object = node ? node->getObject()->asVolume() : nullptr; + if (nullptr != object) { if (!object->permModify()) { diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index 8c767e64b1..d78a9ef28c 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -93,6 +93,7 @@ LLFloaterTopObjects::LLFloaterTopObjects() mCommitCallbackRegistrar.add("TopObjects.CommitObjectsList",boost::bind(&LLFloaterTopObjects::onCommitObjectsList, this)); mCommitCallbackRegistrar.add("TopObjects.TeleportToObject", boost::bind(&LLFloaterTopObjects::onTeleportToObject, this)); + mCommitCallbackRegistrar.add("TopObjects.CamToObject", boost::bind(&LLFloaterTopObjects::onCamToObject, this)); mCommitCallbackRegistrar.add("TopObjects.Kick", boost::bind(&LLFloaterTopObjects::onKick, this)); mCommitCallbackRegistrar.add("TopObjects.Profile", boost::bind(&LLFloaterTopObjects::onProfile, this)); @@ -327,21 +328,11 @@ void LLFloaterTopObjects::doToObjects(int action, bool all) LLViewerRegion* region = gAgent.getRegion(); if (!region) return; - LLCtrlListInterface *list = getChild("objects_list")->getListInterface(); + const auto list = getChild("objects_list"); if (!list || list->getItemCount() == 0) return; - uuid_vec_t::iterator id_itor; - bool start_message = true; - - for (id_itor = mObjectListIDs.begin(); id_itor != mObjectListIDs.end(); ++id_itor) - { - LLUUID task_id = *id_itor; - if (!all && !list->isSelected(task_id)) - { - // Selected only - continue; - } + auto func = [&](const LLUUID& task_id){ if (start_message) { if (action == ACTION_RETURN) @@ -358,10 +349,9 @@ void LLFloaterTopObjects::doToObjects(int action, bool all) msg->nextBlockFast(_PREHASH_ParcelData); msg->addS32Fast(_PREHASH_LocalID, -1); // Whole region msg->addS32Fast(_PREHASH_ReturnType, RT_NONE); + msg->nextBlockFast(_PREHASH_TaskIDs); start_message = false; } - - msg->nextBlockFast(_PREHASH_TaskIDs); msg->addUUIDFast(_PREHASH_TaskID, task_id); if (msg->isSendFullFast(_PREHASH_TaskIDs)) @@ -369,7 +359,10 @@ void LLFloaterTopObjects::doToObjects(int action, bool all) msg->sendReliable(region->getHost()); start_message = true; } - } + }; + + if (all) for (const auto& id : mObjectListIDs) func(id); + else for (const auto& item : list->getAllSelected()) func(item->getUUID()); if (!start_message) { @@ -494,23 +487,11 @@ void LLFloaterTopObjects::onGetByParcelName() void LLFloaterTopObjects::showBeacon() { - LLScrollListCtrl* list = getChild("objects_list"); - if (!list) return; - - LLScrollListItem* first_selected = list->getFirstSelected(); - if (!first_selected) return; - + LLVector3d pos_global = getSelectedPosition(); + if (pos_global.isExactlyZero()) return; + LLScrollListItem* first_selected = getChild("objects_list")->getFirstSelected(); std::string name = first_selected->getColumn(1)->getValue().asString(); - std::string pos_string = first_selected->getColumn(3)->getValue().asString(); - - F32 x, y, z; - S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z); - if (matched != 3) return; - - LLVector3 pos_agent(x, y, z); - LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); - std::string tooltip(""); - LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM); + LLTracker::trackLocation(pos_global, name, LLStringUtil::null, LLTracker::LOCATION_ITEM); const LLUUID& taskid = first_selected->getUUID(); if(LLVOAvatar* voavatar = gObjectList.findAvatar(taskid)) @@ -522,26 +503,39 @@ void LLFloaterTopObjects::showBeacon() } } -void LLFloaterTopObjects::onTeleportToObject() +LLVector3d LLFloaterTopObjects::getSelectedPosition() const { LLScrollListCtrl* list = getChild("objects_list"); - if (!list) return; + if (!list) return LLVector3d::zero; LLScrollListItem* first_selected = list->getFirstSelected(); - if (!first_selected) return; + if (!first_selected) return LLVector3d::zero; std::string pos_string = first_selected->getColumn(3)->getValue().asString(); F32 x, y, z; S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z); - if (matched != 3) return; + if (matched != 3) return LLVector3d::zero; LLVector3 pos_agent(x, y, z); - LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); + return gAgent.getPosGlobalFromAgent(pos_agent); +} +void LLFloaterTopObjects::onTeleportToObject() +{ + LLVector3d pos_global = getSelectedPosition(); + if (pos_global.isExactlyZero()) return; gAgent.teleportViaLocation( pos_global ); } +void LLFloaterTopObjects::onCamToObject() +{ + LLVector3d pos_global = getSelectedPosition(); + if (pos_global.isExactlyZero()) return; + const LLUUID& id = getChild("objects_list")->getFirstSelected()->getUUID(); + gAgentCamera.setCameraPosAndFocusGlobal(pos_global + LLVector3d(3.5,1.35,0.75), pos_global, id); +} + void LLFloaterTopObjects::onKick() { LLScrollListCtrl* list = getChild("objects_list"); diff --git a/indra/newview/llfloatertopobjects.h b/indra/newview/llfloatertopobjects.h index a69de5fc9b..9f1b2794d6 100644 --- a/indra/newview/llfloatertopobjects.h +++ b/indra/newview/llfloatertopobjects.h @@ -74,7 +74,9 @@ class LLFloaterTopObjects : public LLFloater, public LLSingletonbuildFloater(LLFloaterTOS::sInstance, "floater_tos.xml"); - } - else - { - LLUICtrlFactory::getInstance()->buildFloater(LLFloaterTOS::sInstance, "floater_critical.xml"); - } - - return LLFloaterTOS::sInstance; + if (sInstance) sInstance->close(); + return sInstance = new LLFloaterTOS(type, message); } -LLFloaterTOS::LLFloaterTOS(ETOSType type, const std::string & message) -: LLModalDialog( std::string(" "), 100, 100 ), +LLFloaterTOS::LLFloaterTOS(ETOSType type, const std::string& message) +: LLModalDialog(std::string(" "), 100, 100), mType(type), - mMessage(message), - mLoadCompleteCount( 0 ) + mLoadCompleteCount(0) { + LLUICtrlFactory::getInstance()->buildFloater(this, + mType == TOS_CRITICAL_MESSAGE ? "floater_critical.xml" + : mType == TOS_TOS ? "floater_tos.xml" + : "floater_voice_license.xml"); + + if (mType == TOS_CRITICAL_MESSAGE) + { + // this displays the critical message + LLTextEditor *editor = getChild("tos_text"); + editor->setHandleEditKeysDirectly(TRUE); + editor->setEnabled(FALSE); + editor->setWordWrap(TRUE); + editor->setFocus(TRUE); + editor->setValue(message); + } } // helper class that trys to download a URL from a web site and calls a method // on parent class indicating if the web server is working or not class LLIamHere : public LLHTTPClient::ResponderWithResult { - private: - LLIamHere( LLFloaterTOS* parent ) : - mParent( parent ) - {} + LLIamHere(LLFloaterTOS* parent) : mParent(parent->getDerivedHandle()) {} + LLHandle mParent; - LLFloaterTOS* mParent; - - public: - - static boost::intrusive_ptr< LLIamHere > build( LLFloaterTOS* parent ) - { - return boost::intrusive_ptr< LLIamHere >( new LLIamHere( parent ) ); - }; - - virtual void setParent( LLFloaterTOS* parentIn ) - { - mParent = parentIn; - }; +public: + static boost::intrusive_ptr build(LLFloaterTOS* parent) + { + return boost::intrusive_ptr(new LLIamHere(parent)); + } - /*virtual*/ void httpSuccess(void) - { - if ( mParent ) - mParent->setSiteIsAlive( true ); - }; + void httpSuccess() override + { + if (!mParent.isDead()) + mParent.get()->setSiteIsAlive(true); + } - /*virtual*/ void httpFailure(void) + void httpFailure() override + { + if (!mParent.isDead()) { - if ( mParent ) - { - // *HACK: For purposes of this alive check, 302 Found - // (aka Moved Temporarily) is considered alive. The web site - // redirects this link to a "cache busting" temporary URL. JC - bool alive = (mStatus == HTTP_FOUND); - mParent->setSiteIsAlive( alive ); - } - }; - - /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return iamHere_timeout; } - /*virtual*/ bool pass_redirect_status(void) const { return true; } - /*virtual*/ char const* getName(void) const { return "LLIamHere"; } -}; + // *HACK: For purposes of this alive check, 302 Found + // (aka Moved Temporarily) is considered alive. The web site + // redirects this link to a "cache busting" temporary URL. JC + mParent.get()->setSiteIsAlive(mStatus == HTTP_FOUND); + } + } -// this is global and not a class member to keep crud out of the header file -namespace { - boost::intrusive_ptr< LLIamHere > gResponsePtr = 0; + AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy() const override { return iamHere_timeout; } + bool pass_redirect_status() const override { return true; } + char const* getName() const override { return "LLIamHere"; } }; BOOL LLFloaterTOS::postBuild() @@ -146,78 +130,60 @@ BOOL LLFloaterTOS::postBuild() childSetAction("Cancel", onCancel, this); childSetCommitCallback("agree_chk", updateAgree, this); - if ( mType != TOS_TOS ) - { - // this displays the critical message - LLTextEditor *editor = getChild("tos_text"); - editor->setHandleEditKeysDirectly( TRUE ); - editor->setEnabled( FALSE ); - editor->setWordWrap(TRUE); - editor->setFocus(TRUE); - editor->setValue(LLSD(mMessage)); - - return TRUE; - } + if (mType == TOS_CRITICAL_MESSAGE) return TRUE; // disable Agree to TOS radio button until the page has fully loaded LLCheckBoxCtrl* tos_agreement = getChild("agree_chk"); - tos_agreement->setEnabled( false ); + tos_agreement->setEnabled(false); + bool voice = mType == TOS_VOICE; // hide the SL text widget if we're displaying TOS with using a browser widget. - LLTextEditor *editor = getChild("tos_text"); - editor->setVisible( FALSE ); + getChild(voice ? "license_text" : "tos_text")->setVisible(FALSE); - LLMediaCtrl* web_browser = getChild("tos_html"); - if ( web_browser ) + if (LLMediaCtrl* web_browser = getChild(voice ? "license_html" : "tos_html")) { + // start to observe it so we see navigate complete events web_browser->addObserver(this); - gResponsePtr = LLIamHere::build( this ); - LLHTTPClient::get( getString( "real_url" ), gResponsePtr ); + std::string url = getString( "real_url" ); + if (!voice || url.substr(0,4) == "http") { + LLHTTPClient::get(url, LLIamHere::build(this)); + } else { + setSiteIsAlive(false); + } } return TRUE; } -void LLFloaterTOS::setSiteIsAlive( bool alive ) +void LLFloaterTOS::setSiteIsAlive(bool alive) { // only do this for TOS pages - if ( mType == TOS_TOS ) + if (mType != TOS_CRITICAL_MESSAGE) { - LLMediaCtrl* web_browser = getChild("tos_html"); + bool voice = mType == TOS_VOICE; + LLMediaCtrl* web_browser = getChild(voice ? "license_html" : "tos_html"); // if the contents of the site was retrieved - if ( alive ) + if (alive) { - if ( web_browser ) + if (web_browser) { // navigate to the "real" page - web_browser->navigateTo( getString( "real_url" ) ); - }; + web_browser->navigateTo(getString("real_url")); + } } else { + if (voice) web_browser->navigateToLocalPage("license", getString("fallback_html")); // normally this is set when navigation to TOS page navigation completes (so you can't accept before TOS loads) // but if the page is unavailable, we need to do this now - LLCheckBoxCtrl* tos_agreement = getChild("agree_chk"); - tos_agreement->setEnabled( true ); - }; - }; + getChild("agree_chk")->setEnabled(true); + } + } } LLFloaterTOS::~LLFloaterTOS() { - - // tell the responder we're not here anymore - if ( gResponsePtr ) - gResponsePtr->setParent( 0 ); - - LLFloaterTOS::sInstance = NULL; -} - -// virtual -void LLFloaterTOS::draw() -{ - // draw children - LLModalDialog::draw(); + sInstance = nullptr; } // static @@ -229,11 +195,21 @@ void LLFloaterTOS::updateAgree(LLUICtrl*, void* userdata ) } // static -void LLFloaterTOS::onContinue( void* userdata ) +void LLFloaterTOS::onContinue(void* userdata) { LLFloaterTOS* self = (LLFloaterTOS*) userdata; - LL_INFOS() << "User agrees with TOS." << LL_ENDL; - if (self->mType == TOS_TOS) + bool voice = self->mType == TOS_VOICE; + LL_INFOS() << (voice ? "User agreed to the Vivox personal license" : "User agrees with TOS.") << LL_ENDL; + if (voice) + { + // enabling voice by default here seems like the best behavior + gSavedSettings.setBOOL("EnableVoiceChat", TRUE); + gSavedSettings.setBOOL("VivoxLicenseAccepted", TRUE); + + // save these settings in case something bad happens later + gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); + } + else if (self->mType == TOS_TOS) { gAcceptTOS = TRUE; } @@ -242,42 +218,57 @@ void LLFloaterTOS::onContinue( void* userdata ) gAcceptCriticalMessage = TRUE; } + auto state = LLStartUp::getStartupState(); // Testing TOS dialog - #if ! LL_RELEASE_FOR_DOWNLOAD - if ( LLStartUp::getStartupState() == STATE_LOGIN_WAIT ) +#if !LL_RELEASE_FOR_DOWNLOAD + if (!voice && state == STATE_LOGIN_WAIT) { - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + LLStartUp::setStartupState(STATE_LOGIN_SHOW); } else - #endif - - LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); // Go back and finish authentication +#endif + if (!voice || state == STATE_LOGIN_VOICE_LICENSE) + { + LLStartUp::setStartupState(STATE_LOGIN_AUTH_INIT); // Go back and finish authentication + } self->close(); // destroys this object } // static -void LLFloaterTOS::onCancel( void* userdata ) +void LLFloaterTOS::onCancel(void* userdata) { LLFloaterTOS* self = (LLFloaterTOS*) userdata; - LL_INFOS() << "User disagrees with TOS." << LL_ENDL; - LLNotificationsUtil::add("MustAgreeToLogIn", LLSD(), LLSD(), login_alert_done); - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); - self->mLoadCompleteCount = 0; // reset counter for next time we come to TOS + if (self->mType == TOS_VOICE) + { + LL_INFOS() << "User disagreed with the Vivox personal license" << LL_ENDL; + gSavedSettings.setBOOL("EnableVoiceChat", FALSE); + gSavedSettings.setBOOL("VivoxLicenseAccepted", FALSE); + + if (LLStartUp::getStartupState() == STATE_LOGIN_VOICE_LICENSE) + { + LLStartUp::setStartupState(STATE_LOGIN_AUTH_INIT); // Go back and finish authentication + } + } + else + { + LL_INFOS() << "User disagrees with TOS." << LL_ENDL; + LLNotificationsUtil::add("MustAgreeToLogIn", LLSD(), LLSD(), login_alert_done); + LLStartUp::setStartupState(STATE_LOGIN_SHOW); + } self->close(); // destroys this object } //virtual void LLFloaterTOS::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event) { - if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) + if (event == MEDIA_EVENT_NAVIGATE_COMPLETE) { // skip past the loading screen navigate complete - if ( ++mLoadCompleteCount == 2 ) + if (++mLoadCompleteCount == 2) { LL_INFOS() << "NAVIGATE COMPLETE" << LL_ENDL; // enable Agree to TOS radio button now that page has loaded - LLCheckBoxCtrl * tos_agreement = getChild("agree_chk"); - tos_agreement->setEnabled( true ); + getChild("agree_chk")->setEnabled(true); } } } diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h index 331458178b..6bfced8703 100644 --- a/indra/newview/llfloatertos.h +++ b/indra/newview/llfloatertos.h @@ -24,7 +24,7 @@ * that you have read and understood your obligations described above, * and agree to abide by those obligations. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * ALL SOURCE CODE IS PROVIDED "AS IS." THE AUTHOR MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ @@ -54,15 +54,13 @@ class LLFloaterTOS : enum ETOSType { TOS_TOS = 0, - TOS_CRITICAL_MESSAGE = 1 + TOS_CRITICAL_MESSAGE = 1, + TOS_VOICE = 2 }; - // Asset_id is overwritten with LLUUID::null when agree is clicked. - static LLFloaterTOS* show(ETOSType type, const std::string & message); + static LLFloaterTOS* show(ETOSType type, const std::string& message = LLStringUtil::null); BOOL postBuild(); - - virtual void draw(); static void updateAgree( LLUICtrl *, void* userdata ); static void onContinue( void* userdata ); @@ -74,12 +72,9 @@ class LLFloaterTOS : /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); private: - // Asset_id is overwritten with LLUUID::null when agree is clicked. - LLFloaterTOS(ETOSType type, const std::string & message); + LLFloaterTOS(ETOSType type, const std::string& message); -private: ETOSType mType; - std::string mMessage; int mLoadCompleteCount; static LLFloaterTOS* sInstance; diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index 3c526a1acd..727a89b3c6 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -103,6 +103,7 @@ class LLMediaTypeResponder : public LLHTTPClient::ResponderHeadersOnly LLFloaterURLEntry::LLFloaterURLEntry(LLHandle parent) : LLFloater(), + mMediaURLEdit(nullptr), mPanelLandMediaHandle(parent) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_url_entry.xml"); diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp index fc74c9e87d..3c0fe3af0b 100644 --- a/indra/newview/llfloatervoiceeffect.cpp +++ b/indra/newview/llfloatervoiceeffect.cpp @@ -38,6 +38,7 @@ LLFloaterVoiceEffect::LLFloaterVoiceEffect(const LLSD& key) : LLFloater(/*key*/) + , mVoiceEffectList(nullptr) { mCommitCallbackRegistrar.add("VoiceEffect.Record", boost::bind(&LLFloaterVoiceEffect::onClickRecord, this)); mCommitCallbackRegistrar.add("VoiceEffect.Play", boost::bind(&LLFloaterVoiceEffect::onClickPlay, this)); @@ -74,7 +75,7 @@ BOOL LLFloaterVoiceEffect::postBuild() LLStyleSP link(new LLStyle); link->setLinkHREF(LLTrans::getString("voice_morphing_url")); link->setColor(gSavedSettings.getColor4("HTMLLinkColor")); - editor->appendStyledText(text, false, false, link); + editor->appendText(text, false, false, link); } mVoiceEffectList = getChild("voice_effect_list"); diff --git a/indra/newview/llfloatervoiceeffect.h b/indra/newview/llfloatervoiceeffect.h index 9bee8937cd..e7c0af852c 100644 --- a/indra/newview/llfloatervoiceeffect.h +++ b/indra/newview/llfloatervoiceeffect.h @@ -67,7 +67,6 @@ class LLFloaterVoiceEffect void onClickStop(); void onClickActivate(); - LLUUID mSelectedID; LLScrollListCtrl* mVoiceEffectList; }; diff --git a/indra/newview/llfloaterwhitelistentry.cpp b/indra/newview/llfloaterwhitelistentry.cpp index f930e09400..c7a17f136f 100644 --- a/indra/newview/llfloaterwhitelistentry.cpp +++ b/indra/newview/llfloaterwhitelistentry.cpp @@ -37,8 +37,9 @@ /////////////////////////////////////////////////////////////////////////////// // -LLFloaterWhiteListEntry::LLFloaterWhiteListEntry() : - LLFloater() +LLFloaterWhiteListEntry::LLFloaterWhiteListEntry() + : LLFloater() + , mWhiteListEdit(nullptr) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_whitelist_entry.xml"); } diff --git a/indra/newview/llfloaterwindlight.cpp b/indra/newview/llfloaterwindlight.cpp index 7e9eb6a1f8..9a9b9768fa 100644 --- a/indra/newview/llfloaterwindlight.cpp +++ b/indra/newview/llfloaterwindlight.cpp @@ -302,6 +302,10 @@ void LLFloaterWindLight::syncMenu() // blue horizon param_mgr->mBlueHorizon = cur_params.getVector(param_mgr->mBlueHorizon.mName, err); //setColorSwatch("WLBlueHorizon", param_mgr->mBlueHorizon, WL_BLUE_HORIZON_DENSITY_SCALE); + childSetValue("WLBlueHorizonR", param_mgr->mBlueHorizon.r / WL_BLUE_HORIZON_DENSITY_SCALE); + childSetValue("WLBlueHorizonG", param_mgr->mBlueHorizon.g / WL_BLUE_HORIZON_DENSITY_SCALE); + childSetValue("WLBlueHorizonB", param_mgr->mBlueHorizon.b / WL_BLUE_HORIZON_DENSITY_SCALE); + childSetValue("WLBlueHorizonI", param_mgr->mBlueHorizon.i / WL_BLUE_HORIZON_DENSITY_SCALE); // haze density, horizon, mult, and altitude param_mgr->mHazeDensity = cur_params.getFloat(param_mgr->mHazeDensity.mName, err); @@ -316,12 +320,20 @@ void LLFloaterWindLight::syncMenu() // blue density param_mgr->mBlueDensity = cur_params.getVector(param_mgr->mBlueDensity.mName, err); //setColorSwatch("WLBlueDensity", param_mgr->mBlueDensity, WL_BLUE_HORIZON_DENSITY_SCALE); + childSetValue("WLBlueDensityR", param_mgr->mBlueDensity.r / WL_BLUE_HORIZON_DENSITY_SCALE); + childSetValue("WLBlueDensityG", param_mgr->mBlueDensity.g / WL_BLUE_HORIZON_DENSITY_SCALE); + childSetValue("WLBlueDensityB", param_mgr->mBlueDensity.b / WL_BLUE_HORIZON_DENSITY_SCALE); + childSetValue("WLBlueDensityI", param_mgr->mBlueDensity.i / WL_BLUE_HORIZON_DENSITY_SCALE); // Lighting // sunlight param_mgr->mSunlight = cur_params.getVector(param_mgr->mSunlight.mName, err); //setColorSwatch("WLSunlight", param_mgr->mSunlight, WL_SUN_AMBIENT_SLIDER_SCALE); + childSetValue("WLSunlightR", param_mgr->mSunlight.r / WL_SUN_AMBIENT_SLIDER_SCALE); + childSetValue("WLSunlightG", param_mgr->mSunlight.g / WL_SUN_AMBIENT_SLIDER_SCALE); + childSetValue("WLSunlightB", param_mgr->mSunlight.b / WL_SUN_AMBIENT_SLIDER_SCALE); + childSetValue("WLSunlightI", param_mgr->mSunlight.i / WL_SUN_AMBIENT_SLIDER_SCALE); // glow param_mgr->mGlow = cur_params.getVector(param_mgr->mGlow.mName, err); @@ -331,6 +343,10 @@ void LLFloaterWindLight::syncMenu() // ambient param_mgr->mAmbient = cur_params.getVector(param_mgr->mAmbient.mName, err); //setColorSwatch("WLAmbient", param_mgr->mAmbient, WL_SUN_AMBIENT_SLIDER_SCALE); + childSetValue("WLAmbientR", param_mgr->mAmbient.r / WL_SUN_AMBIENT_SLIDER_SCALE); + childSetValue("WLAmbientG", param_mgr->mAmbient.g / WL_SUN_AMBIENT_SLIDER_SCALE); + childSetValue("WLAmbientB", param_mgr->mAmbient.b / WL_SUN_AMBIENT_SLIDER_SCALE); + childSetValue("WLAmbientI", param_mgr->mAmbient.i / WL_SUN_AMBIENT_SLIDER_SCALE); childSetValue("WLSunAngle", param_mgr->mCurParams.getFloat("sun_angle",err) / F_TWO_PI); childSetValue("WLEastAngle", param_mgr->mCurParams.getFloat("east_angle",err) / F_TWO_PI); @@ -340,6 +356,10 @@ void LLFloaterWindLight::syncMenu() // Cloud Color param_mgr->mCloudColor = cur_params.getVector(param_mgr->mCloudColor.mName, err); //setColorSwatch("WLCloudColor", param_mgr->mCloudColor, WL_CLOUD_SLIDER_SCALE); + childSetValue("WLCloudColorR", param_mgr->mCloudColor.r / WL_CLOUD_SLIDER_SCALE); + childSetValue("WLCloudColorG", param_mgr->mCloudColor.g / WL_CLOUD_SLIDER_SCALE); + childSetValue("WLCloudColorB", param_mgr->mCloudColor.b / WL_CLOUD_SLIDER_SCALE); + childSetValue("WLCloudColorI", param_mgr->mCloudColor.i / WL_CLOUD_SLIDER_SCALE); // Cloud param_mgr->mCloudMain = cur_params.getVector(param_mgr->mCloudMain.mName, err); @@ -493,18 +513,7 @@ void LLFloaterWindLight::onColorControlRMoved(LLUICtrl* ctrl, void* userdata) std::string name = color_ctrl->mSliderName; name.append("I"); - if (color_ctrl->isSunOrAmbientColor) - { - childSetValue(name, color_ctrl->r / WL_SUN_AMBIENT_SLIDER_SCALE); - } - else if (color_ctrl->isBlueHorizonOrDensity) - { - childSetValue(name, color_ctrl->r / WL_BLUE_HORIZON_DENSITY_SCALE); - } - else - { - childSetValue(name, color_ctrl->r); - } + childSetValue(name, sldr_ctrl->getValueF32()); } color_ctrl->update(LLWLParamManager::getInstance()->mCurParams); diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index caca3f627c..e86ad2a184 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -515,7 +515,7 @@ void LLFloaterWorldMap::draw() } else { - if (mCompletingRegionName != "") + if (!mCompletingRegionName.empty()) { F64 seconds = LLTimer::getElapsedSeconds(); double value = fmod(seconds, 2); @@ -1097,7 +1097,7 @@ void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui) } //Singu Note: Don't do this. It basically 'eats' the first click onto void space if the previous tracked target was a valid sim. //LLWorldMap::getInstance()->cancelTracking(); - mCompletingRegionName = ""; + mCompletingRegionName.clear(); } @@ -1648,7 +1648,7 @@ void LLFloaterWorldMap::flyToAvatar() void LLFloaterWorldMap::updateSims(bool found_null_sim) { - if (mCompletingRegionName == "") + if (mCompletingRegionName.empty()) { return; } @@ -1656,8 +1656,6 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) LLScrollListCtrl *list = getChild("search_results"); list->operateOnAll(LLCtrlListInterface::OP_DELETE); - S32 name_length = mCompletingRegionName.length(); - LLSD match; S32 num_results = 0; @@ -1665,13 +1663,13 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) std::vector > sim_info_vec(LLWorldMap::getInstance()->getRegionMap().begin(), LLWorldMap::getInstance()->getRegionMap().end()); std::sort(sim_info_vec.begin(), sim_info_vec.end(), SortRegionNames()); - for (std::vector >::const_iterator it = sim_info_vec.begin(); it != sim_info_vec.end(); ++it) + for (const auto& sim_info_pair : sim_info_vec) { - LLSimInfo* info = it->second; + LLSimInfo* info = sim_info_pair.second; std::string sim_name_lower = info->getName(); LLStringUtil::toLower(sim_name_lower); - if (sim_name_lower.substr(0, name_length) == mCompletingRegionName) + if (sim_name_lower.find(mCompletingRegionName) != std::string::npos) { if (sim_name_lower == mCompletingRegionName) { @@ -1689,7 +1687,7 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) if (found_null_sim || match.isDefined()) { - mCompletingRegionName = ""; + mCompletingRegionName.clear(); } if (num_results > 0) @@ -1729,10 +1727,9 @@ void LLFloaterWorldMap::onCommitSearchResult() } LLStringUtil::toLower(sim_name); - std::map::const_iterator it; - for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) + for (auto map_pair : LLWorldMap::getInstance()->getRegionMap()) { - LLSimInfo* info = it->second; + LLSimInfo* info = map_pair.second; if (info->isName(sim_name)) { diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 4751b15e1a..2e5a1b9050 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -169,8 +169,8 @@ class LLFloaterWorldMap : public LLFloater // enable/disable teleport destination coordinates void enableTeleportCoordsDisplay( bool enabled ); - std::vector mLandmarkAssetIDList; - std::vector mLandmarkItemIDList; + uuid_vec_t mLandmarkAssetIDList; + uuid_vec_t mLandmarkItemIDList; static const LLUUID sHomeID; diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 8826e0421c..67dfddd5b2 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -66,6 +66,7 @@ // Linden library includes #include "lldbstrings.h" +#include "llfavoritesbar.h" // Singu TODO: Favorites bar. #include "llfocusmgr.h" #include "llfontgl.h" #include "llgl.h" @@ -201,7 +202,7 @@ LLFolderView::LLFolderView( const std::string& name, mNeedsAutoRename(FALSE), mDebugFilters(FALSE), mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately - mFilter( new LLInventoryFilter(name) ), + mFilter(LLInventoryFilter::Params().name(name)), mShowSelectionContext(FALSE), mShowSingleSelection(FALSE), mArrangeGeneration(0), @@ -298,9 +299,6 @@ LLFolderView::~LLFolderView( void ) mFolders.clear(); mItemMap.clear(); - - delete mFilter; - mFilter = NULL; } BOOL LLFolderView::canFocusChildren() const @@ -308,13 +306,13 @@ BOOL LLFolderView::canFocusChildren() const return FALSE; } -static LLFastTimer::DeclareTimer FTM_SORT("Sort Inventory"); +static LLTrace::BlockTimerStatHandle FTM_SORT("Sort Inventory"); void LLFolderView::setSortOrder(U32 order) { if (order != mSortOrder) { - LLFastTimer t(FTM_SORT); + LL_RECORD_BLOCK_TIME(FTM_SORT); mSortOrder = order; @@ -371,7 +369,7 @@ U32 LLFolderView::toggleSearchType(std::string toggle) if (getFilterSubString().length()) { - mFilter->setModified(LLInventoryFilter::FILTER_RESTART); + mFilter.setModified(LLInventoryFilter::FILTER_RESTART); } return mSearchType; @@ -428,7 +426,7 @@ void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse mIsOpen = TRUE; } -static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); +static LLTrace::BlockTimerStatHandle FTM_ARRANGE("Arrange"); // This view grows and shrinks to enclose all of its children items and folders. S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) @@ -445,9 +443,9 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen } } - LLFastTimer t2(FTM_ARRANGE); + LL_RECORD_BLOCK_TIME(FTM_ARRANGE); - filter_generation = mFilter->getMinRequiredGeneration(); + filter_generation = mFilter.getFirstSuccessGeneration(); mMinWidth = 0; mHasVisibleChildren = hasFilteredDescendants(filter_generation); @@ -455,7 +453,7 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen mLastArrangeGeneration = getRoot()->getArrangeGeneration(); LLInventoryFilter::EFolderShow show_folder_state = - getRoot()->getFilter()->getShowFolderState(); + getRoot()->getFilter().getShowFolderState(); S32 total_width = LEFT_PAD; S32 running_height = mDebugFilters ? llceil(LLFontGL::getFontMonospace()->getLineHeight()) : 0; @@ -541,14 +539,14 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen const std::string LLFolderView::getFilterSubString(BOOL trim) { - return mFilter->getFilterSubString(trim); + return mFilter.getFilterSubString(trim); } -static LLFastTimer::DeclareTimer FTM_FILTER("Filter Inventory"); +static LLTrace::BlockTimerStatHandle FTM_FILTER("Filter Inventory"); void LLFolderView::filter( LLInventoryFilter& filter ) { - LLFastTimer t2(FTM_FILTER); + LL_RECORD_BLOCK_TIME(FTM_FILTER); filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) @@ -633,6 +631,10 @@ LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) return NULL; } +LLFolderView::selected_items_t& LLFolderView::getSelectedItems( void ) +{ + return mSelectedItems; +} // Record the selected item and pass it down the hierachy. BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, @@ -736,16 +738,16 @@ BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) return rv; } -static LLFastTimer::DeclareTimer FTM_SANITIZE_SELECTION("Sanitize Selection"); +static LLTrace::BlockTimerStatHandle FTM_SANITIZE_SELECTION("Sanitize Selection"); void LLFolderView::sanitizeSelection() { - LLFastTimer _(FTM_SANITIZE_SELECTION); + LL_RECORD_BLOCK_TIME(FTM_SANITIZE_SELECTION); // store off current item in case it is automatically deselected // and we want to preserve context LLFolderViewItem* original_selected_item = getCurSelectedItem(); // Cache "Show all folders" filter setting - BOOL show_all_folders = (getRoot()->getFilter()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS); + BOOL show_all_folders = (getRoot()->getFilter().getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS); std::vector items_to_remove; selected_items_t::iterator item_iter; @@ -863,24 +865,23 @@ void LLFolderView::clearSelection() mSelectThisID.setNull(); } -std::set LLFolderView::getSelectionList() const +uuid_set_t LLFolderView::getSelectionList() const { - std::set selection; - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); - ++item_it) + uuid_set_t selection; + for (const auto& item : mSelectedItems) { - selection.insert((*item_it)->getListener()->getUUID()); + selection.insert(item->getListener()->getUUID()); } return selection; } -BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source) +bool LLFolderView::startDrag(LLToolDragAndDrop::ESource source) { std::vector types; uuid_vec_t cargo_ids; selected_items_t::iterator item_it; - BOOL can_drag = TRUE; + bool can_drag = true; + if (!mSelectedItems.empty()) { for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) @@ -908,7 +909,7 @@ void LLFolderView::draw() if (mDebugFilters) { std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", - mFilter->getCurrentGeneration(), mFilter->getMinRequiredGeneration(), mFilter->getMustPassGeneration()); + mFilter.getCurrentGeneration(), mFilter.getFirstSuccessGeneration(), mFilter.getFirstRequiredGeneration()); LLFontGL::getFontMonospace()->renderUTF8(current_filter_string, 0, 2, getRect().getHeight() - LLFontGL::getFontMonospace()->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f), LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); @@ -922,31 +923,25 @@ void LLFolderView::draw() } // while dragging, update selection rendering to reflect single/multi drag status - if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) + LLToolDragAndDrop& dad_inst(LLToolDragAndDrop::instance()); + if (dad_inst.hasMouseCapture()) { - EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); - if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) - { - setShowSingleSelection(TRUE); - } - else - { - setShowSingleSelection(FALSE); - } + EAcceptance last_accept = dad_inst.getLastAccept(); + setShowSingleSelection(last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE); } else { setShowSingleSelection(FALSE); } - - if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout") || !mSearchString.size()) + static LLUICachedControl type_ahead_timeout("TypeAheadTimeout", 0); + if (mSearchTimer.getElapsedTimeF32() > type_ahead_timeout || !mSearchString.size()) { mSearchString.clear(); } if (hasVisibleChildren() - || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) + || mFilter.getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) { mStatusText.clear(); mStatusTextBox->setVisible( FALSE ); @@ -954,18 +949,13 @@ void LLFolderView::draw() else if (mShowEmptyMessage) { static LLCachedControl sSearchStatusColor(gColors, "InventorySearchStatusColor", LLColor4::white ); - if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) + if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter.getFirstSuccessGeneration()) { mStatusText = LLTrans::getString("Searching"); } else { - // if(getFilter()) - // { - // LLStringUtil::format_map_t args; - // args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig()); - mStatusText = LLTrans::getString("InventoryNoMatchingItems"); //, args); - // } + mStatusText = getFilter().getEmptyLookupMessage(); } mStatusTextBox->setWrappedText(mStatusText); mStatusTextBox->setVisible( TRUE ); @@ -977,7 +967,7 @@ void LLFolderView::draw() // get preferable text height... S32 pixel_height = mStatusTextBox->getTextPixelHeight(); - bool height_changed = local_rect.getHeight() != pixel_height; + bool height_changed = (local_rect.getHeight() != pixel_height); if (height_changed) { // ... if it does not match current height, lets rearrange current view. @@ -988,6 +978,8 @@ void LLFolderView::draw() } } + // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, + // and arrow for the root folder LLView::draw(); mDragAndDropThisFrame = FALSE; @@ -1006,7 +998,7 @@ void LLFolderView::finishRenamingItem( void ) closeRenamer(); - // List is re-sorted alphabeticly, so scroll to make sure the selected item is visible. + // List is re-sorted alphabetically, so scroll to make sure the selected item is visible. scrollToShowSelection(); } @@ -1054,9 +1046,9 @@ void LLFolderView::removeCutItems() return; // Get the list of clipboard item uuids and iterate through them - std::vector objects; + uuid_vec_t objects; LLInventoryClipboard::instance().retrieve(objects); - for (std::vector::const_iterator iter = objects.begin(); + for (auto iter = objects.begin(); iter != objects.end(); ++iter) { @@ -1064,7 +1056,7 @@ void LLFolderView::removeCutItems() } } -void LLFolderView::removeSelectedItems( void ) +void LLFolderView::removeSelectedItems() { if(getVisible() && getEnabled()) { @@ -1075,8 +1067,7 @@ void LLFolderView::removeSelectedItems( void ) // items, since the removal will futz with internal data // structures. std::vector items; - S32 count = mSelectedItems.size(); - if(count == 0) return; + if(mSelectedItems.empty()) return; LLFolderViewItem* item = NULL; selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) @@ -1094,7 +1085,7 @@ void LLFolderView::removeSelectedItems( void ) } // iterate through the new container. - count = items.size(); + size_t count = items.size(); LLUUID new_selection_id; if(count == 1) { @@ -1149,7 +1140,7 @@ void LLFolderView::removeSelectedItems( void ) setSelectionFromRoot(NULL, mParentPanel.get()->hasFocus()); } - for(S32 i = 0; i < count; ++i) + for(size_t i = 0; i < count; ++i) { listener = items[i]->getListener(); if(listener && (std::find(listeners.begin(), listeners.end(), listener) == listeners.end())) @@ -1342,25 +1333,22 @@ BOOL LLFolderView::canCopy() const } // copy selected item -void LLFolderView::copy() +void LLFolderView::copy() const { // *NOTE: total hack to clear the inventory clipboard LLInventoryClipboard::instance().reset(); S32 count = mSelectedItems.size(); if(getVisible() && getEnabled() && (count > 0)) { - LLFolderViewEventListener* listener = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + for (auto item : mSelectedItems) { - listener = (*item_it)->getListener(); - if(listener) + if(auto listener = item->getListener()) { listener->copyToClipboard(); } } } - mSearchString.clear(); + //mSearchString.clear(); // Singu Note: There's no good reason to clear out the jumpto item search string now, it'll time out anyway, let's remain const } BOOL LLFolderView::canCut() const @@ -1546,25 +1534,37 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) case KEY_PAGE_UP: mSearchString.clear(); - mScrollContainer->pageUp(30); + if (mScrollContainer) + { + mScrollContainer->pageUp(30); + } handled = TRUE; break; case KEY_PAGE_DOWN: mSearchString.clear(); - mScrollContainer->pageDown(30); + if (mScrollContainer) + { + mScrollContainer->pageDown(30); + } handled = TRUE; break; case KEY_HOME: mSearchString.clear(); - mScrollContainer->goToTop(); + if (mScrollContainer) + { + mScrollContainer->goToTop(); + } handled = TRUE; break; case KEY_END: mSearchString.clear(); - mScrollContainer->goToBottom(); + if (mScrollContainer) + { + mScrollContainer->goToBottom(); + } break; case KEY_DOWN: @@ -1572,7 +1572,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) { LLFolderViewItem* last_selected = getCurSelectedItem(); bool shift_select = mask & MASK_SHIFT; - LLFolderViewItem* next = last_selected->getNextOpenNode(); + LLFolderViewItem* next = last_selected->getNextOpenNode(!shift_select); if (!mKeyboardSelection || (!shift_select && (!next || next == last_selected))) { @@ -1587,12 +1587,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if (next->isSelected()) { // shrink selection - changeSelectionFromRoot(last_selected, FALSE); + changeSelection(last_selected, FALSE); } else if (last_selected->getParentFolder() == next->getParentFolder()) { // grow selection - changeSelectionFromRoot(next, TRUE); + changeSelection(next, TRUE); } } } @@ -1650,12 +1650,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if (prev->isSelected()) { // shrink selection - changeSelectionFromRoot(last_selected, FALSE); + changeSelection(last_selected, FALSE); } else if (last_selected->getParentFolder() == prev->getParentFolder()) { // grow selection - changeSelectionFromRoot(prev, TRUE); + changeSelection(prev, TRUE); } } } @@ -1723,7 +1723,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) { mSearchString.erase(mSearchString.size() - 1, 1); } - search(getCurSelectedItem(), mSearchString, FALSE); + search(getCurSelectedItem(), wstring_to_utf8str(mSearchString), FALSE); handled = TRUE; } } @@ -1739,12 +1739,6 @@ BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) return FALSE; } - if (uni_char > 0x7f) - { - LL_WARNS() << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << LL_ENDL; - return FALSE; - } - BOOL handled = FALSE; if (mParentPanel.get()->hasFocus()) { @@ -1757,7 +1751,8 @@ BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) } //do text search - if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout")) + static LLUICachedControl type_ahead_timeout("TypeAheadTimeout", 0.f); + if (mSearchTimer.getElapsedTimeF32() > type_ahead_timeout) { mSearchString.clear(); } @@ -1766,7 +1761,7 @@ BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) { mSearchString += uni_char; } - search(getCurSelectedItem(), mSearchString, FALSE); + search(getCurSelectedItem(), wstring_to_utf8str(mSearchString), FALSE); handled = TRUE; } @@ -1892,7 +1887,7 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) S32 count = mSelectedItems.size(); LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); if ( handled - && ( count > 0 && (hasVisibleChildren() || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) ) // show menu only if selected items are visible + && ( count > 0 && (hasVisibleChildren() || mFilter.getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) ) // show menu only if selected items are visible && menu ) { updateMenuOptions(menu); @@ -2015,7 +2010,7 @@ void LLFolderView::scrollToShowSelection() // However we allow scrolling for folder views with mAutoSelectOverride // (used in Places SP) as an exception because the selection in them // is not reset during items filtering. See STORM-133. - if ( (!LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mAutoSelectOverride) + if ( (LLInventoryModelBackgroundFetch::instance().isEverythingFetched() || mAutoSelectOverride) && mSelectedItems.size() ) { mNeedsScroll = TRUE; @@ -2090,7 +2085,7 @@ BOOL LLFolderView::getShowSelectionContext() return FALSE; } -void LLFolderView::setShowSingleSelection(BOOL show) +void LLFolderView::setShowSingleSelection(bool show) { if (show != mShowSingleSelection) { @@ -2109,17 +2104,16 @@ void LLFolderView::removeItemID(const LLUUID& id) mItemMap.erase(id); } -LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); +LLTrace::BlockTimerStatHandle FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id) { - LLFastTimer _(FTM_GET_ITEM_BY_ID); + LL_RECORD_BLOCK_TIME(FTM_GET_ITEM_BY_ID); if (id == getListener()->getUUID()) { return this; } - std::map::iterator map_it; - map_it = mItemMap.find(id); + auto map_it = mItemMap.find(id); if (map_it != mItemMap.end()) { return map_it->second; @@ -2149,8 +2143,8 @@ LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id) } -static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select"); -static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); +static LLTrace::BlockTimerStatHandle FTM_AUTO_SELECT("Open and Select"); +static LLTrace::BlockTimerStatHandle FTM_INVENTORY("Inventory"); // Main idle routine void LLFolderView::doIdle() { @@ -2161,8 +2155,13 @@ void LLFolderView::doIdle() { return; } + + // We have all items, now we can save them to favorites + BOOL collectFavoriteItems(LLInventoryModel::item_array_t&); // Singu TODO: Proper Favorites Bar + LLInventoryModel::item_array_t items; + collectFavoriteItems(items); - LLFastTimer t2(FTM_INVENTORY); + LL_RECORD_BLOCK_TIME(FTM_INVENTORY); BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters"); if (debug_filters != getDebugFilters()) @@ -2171,9 +2170,9 @@ void LLFolderView::doIdle() arrangeAll(); } - mFilter->clearModified(); - BOOL filter_modified_and_active = mCompletedFilterGeneration < mFilter->getCurrentGeneration() && - mFilter->isNotDefault(); + mFilter.clearModified(); + BOOL filter_modified_and_active = mCompletedFilterGeneration < mFilter.getCurrentGeneration() && + mFilter.isNotDefault(); mNeedsAutoSelect = filter_modified_and_active && !(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture()); @@ -2187,7 +2186,7 @@ void LLFolderView::doIdle() // potentially changed if (mNeedsAutoSelect) { - LLFastTimer t3(FTM_AUTO_SELECT); + LL_RECORD_BLOCK_TIME(FTM_AUTO_SELECT); // select new item only if a filtered item not currently selected LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); if ((selected_itemp && !selected_itemp->getFiltered()) && !mAutoSelectOverride) @@ -2199,7 +2198,7 @@ void LLFolderView::doIdle() // Open filtered folders for folder views with mAutoSelectOverride=TRUE. // Used by LLPlacesFolderView. - if (mAutoSelectOverride && !mFilter->getFilterSubString().empty()) + if (mAutoSelectOverride && !mFilter.getFilterSubString().empty()) { LLOpenFilteredFolders filter; applyFunctorRecursively(filter); @@ -2305,8 +2304,8 @@ void LLFolderView::idle(void* user_data) void LLFolderView::dumpSelectionInformation() { - LL_INFOS() << "LLFolderView::dumpSelectionInformation()" << LL_ENDL; - LL_INFOS() << "****************************************" << LL_ENDL; + LL_INFOS() << "LLFolderView::dumpSelectionInformation()" << LL_NEWLINE + << "****************************************" << LL_ENDL; selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { @@ -2352,15 +2351,15 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) } // Successively filter out invalid options - - U32 flags = FIRST_SELECTED_ITEM; + U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); + U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; for (selected_items_t::iterator item_itor = mSelectedItems.begin(); item_itor != mSelectedItems.end(); ++item_itor) { LLFolderViewItem* selected_item = (*item_itor); selected_item->buildContextMenu(*menu, flags); - flags = 0x0; + flags = multi_select_flag; } // This adds a check for restrictions based on the entire @@ -2385,6 +2384,22 @@ void LLFolderView::updateMenu() } } +void LLFolderView::saveFolderState() +{ + mSavedFolderState = std::unique_ptr(new LLSaveFolderState()); + applyFunctorRecursively(*mSavedFolderState); +} + +void LLFolderView::restoreFolderState() +{ + if (mSavedFolderState) + { + mSavedFolderState->setApply(true); + applyFunctorRecursively(*mSavedFolderState); + mSavedFolderState.reset(); + } +} + bool LLFolderView::selectFirstItem() { for (folders_t::iterator iter = mFolders.begin(); @@ -2486,34 +2501,24 @@ void LLFolderView::onRenamerLost() } } -LLInventoryFilter* LLFolderView::getFilter() -{ - return mFilter; -} - void LLFolderView::setFilterPermMask( PermissionMask filter_perm_mask ) { - mFilter->setFilterPermissions(filter_perm_mask); -} - -bool LLFolderView::getFilterWorn() const -{ - return mFilter->getFilterWorn(); + mFilter.setFilterPermissions(filter_perm_mask); } U32 LLFolderView::getFilterObjectTypes() const { - return mFilter->getFilterObjectTypes(); + return mFilter.getFilterObjectTypes(); } PermissionMask LLFolderView::getFilterPermissions() const { - return mFilter->getFilterPermissions(); + return mFilter.getFilterPermissions(); } BOOL LLFolderView::isFilterModified() { - return mFilter->isNotDefault(); + return mFilter.isNotDefault(); } void delete_selected_item(void* user_data) diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 3a147c442e..a0a41f44e6 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -1,3 +1,4 @@ + /** * @file llfolderview.h * @brief Definition of the folder view collection of classes. @@ -49,9 +50,12 @@ #include "lldepthstack.h" #include "lleditmenuhandler.h" #include "llfontgl.h" +#include "llinventoryfilter.h" #include "lltooldraganddrop.h" #include "llviewertexture.h" +#include + class LLFolderViewEventListener; class LLFolderViewGroupedItemModel; class LLFolderViewFolder; @@ -63,6 +67,7 @@ class LLMenuGL; class LLScrollContainer; class LLUICtrl; class LLTextBox; +class LLSaveFolderState; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderView @@ -86,6 +91,7 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler virtual BOOL canFocusChildren() const; + virtual const LLFolderView* getRoot() const { return this; } virtual LLFolderView* getRoot() { return this; } LLFolderViewGroupedItemModel* getFolderViewGroupedItemModel() { return mGroupedItemModel; } @@ -100,13 +106,15 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } void setAllowMultiSelect(BOOL allow) { mAllowMultiSelect = allow; } + void setShowEmptyMessage(bool show) { mShowEmptyMessage = show; } + /*void setShowItemLinkOverlays(bool show) { mShowItemLinkOverlays = show; } + void setAllowDropOnRoot(bool show) { mAllowDropOnRoot = show; }*/ - LLInventoryFilter* getFilter(); + LLInventoryFilter& getFilter() { return mFilter; } const std::string getFilterSubString(BOOL trim = FALSE); - bool getFilterWorn() const; U32 getFilterObjectTypes() const; PermissionMask getFilterPermissions() const; - // *NOTE: use getFilter()->getShowFolderState(); + // *NOTE: use getFilter().getShowFolderState(); //LLInventoryFilter::EFolderShow getShowFolderState(); U32 getSortOrder() const; BOOL isFilterModified(); @@ -131,15 +139,16 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler void arrangeAll() { mArrangeGeneration++; } S32 getArrangeGeneration() { return mArrangeGeneration; } - // Apply filters to control visibility of inventory items + // applies filters to control visibility of items virtual void filter( LLInventoryFilter& filter); // Get the last selected item virtual LLFolderViewItem* getCurSelectedItem( void ); + selected_items_t& getSelectedItems( void ); // Record the selected item and pass it down the hierarchy. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus); + BOOL take_keyboard_focus = TRUE); // Used by menu callbacks void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); @@ -147,19 +156,19 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler // Called once a frame to update the selection if mSelectThisID has been set void updateSelection(); - // This method is used to toggle the selection of an item. - // Walks children and keeps track of selected objects. + // This method is used to toggle the selection of an item. Walks + // children, and keeps track of selected objects. virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - virtual std::set getSelectionList() const; + virtual uuid_set_t getSelectionList() const; - // Make sure if ancestor is selected, descendents are not + // Make sure if ancestor is selected, descendants are not void sanitizeSelection(); - void clearSelection(); + virtual void clearSelection(); void addToSelectionList(LLFolderViewItem* item); void removeFromSelectionList(LLFolderViewItem* item); - BOOL startDrag(LLToolDragAndDrop::ESource source); + bool startDrag(LLToolDragAndDrop::ESource source); void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; } void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } @@ -178,31 +187,24 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler void autoOpenItem(LLFolderViewFolder* item); void closeAutoOpenedFolders(); BOOL autoOpenTest(LLFolderViewFolder* item); + BOOL isOpen() const { return TRUE; } // root folder always open // Copy & paste - virtual void copy(); virtual BOOL canCopy() const; + virtual void copy() const override final; - virtual void cut(); virtual BOOL canCut() const; + virtual void cut(); - virtual void paste(); virtual BOOL canPaste() const; + virtual void paste(); - virtual void doDelete(); virtual BOOL canDoDelete() const; + virtual void doDelete(); // Public rename functionality - can only start the process void startRenamingSelectedItem( void ); - // These functions were used when there was only one folderview, - // and relied on that concept. This functionality is now handled - // by the listeners and the lldraganddroptool. - //LLFolderViewItem* getMovingItem() { return mMovingItem; } - //void setMovingItem( LLFolderViewItem* item ) { mMovingItem = item; } - //void dragItemIntoFolder( LLFolderViewItem* moving_item, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept ); - //void dragFolderIntoFolder( LLFolderViewFolder* moving_folder, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept ); - // LLView functionality ///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent ); /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); @@ -217,6 +219,7 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler EAcceptance* accept, std::string& tooltip_msg); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) { setShowSelectionContext(FALSE); } virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); virtual void draw(); virtual void deleteAllChildren(); @@ -227,12 +230,13 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler LLRect getVisibleRect(); BOOL search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward); - void setShowSelectionContext(BOOL show) { mShowSelectionContext = show; } + void setShowSelectionContext(bool show) { mShowSelectionContext = show; } BOOL getShowSelectionContext(); - void setShowSingleSelection(BOOL show); + void setShowSingleSelection(bool show); BOOL getShowSingleSelection() { return mShowSingleSelection; } F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } bool getUseEllipses() { return mUseEllipses; } + S32 getSelectedCount() { return (S32)mSelectedItems.size(); } void addItemID(const LLUUID& id, LLFolderViewItem* itemp); void removeItemID(const LLUUID& id); @@ -247,6 +251,7 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler void setNeedsAutoRename(BOOL val) { mNeedsAutoRename = val; } void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; } void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } + bool getAutoSelectOverride() const { return mAutoSelectOverride; } BOOL getDebugFilters() { return mDebugFilters; } @@ -257,7 +262,9 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler virtual S32 notify(const LLSD& info) ; bool useLabelSuffix() { return mUseLabelSuffix; } - void updateMenu(); + virtual void updateMenu(); + void saveFolderState(); + void restoreFolderState(); // Note: We may eventually have to move that method up the hierarchy to LLFolderViewItem. LLHandle getHandle() const { return getDerivedHandle(); } @@ -279,39 +286,44 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler bool selectLastItem(); BOOL addNoOptions(LLMenuGL* menu) const; + +private: + std::unique_ptr mSavedFolderState; protected: LLHandle mPopupMenuHandle; selected_items_t mSelectedItems; - BOOL mKeyboardSelection; - BOOL mAllowMultiSelect; - BOOL mShowEmptyMessage; - BOOL mShowFolderHierarchy; + bool mKeyboardSelection, + mAllowMultiSelect, + mShowEmptyMessage, + mShowFolderHierarchy, + mNeedsScroll, + mPinningSelectedItem, + mNeedsAutoSelect, + mAutoSelectOverride, + mNeedsAutoRename, + mUseLabelSuffix, + mDragAndDropThisFrame, + mShowSelectionContext, + mShowSingleSelection; + LLUUID mSourceID; // Renaming variables and methods LLFolderViewItem* mRenameItem; // The item currently being renamed LLLineEditor* mRenamer; - BOOL mNeedsScroll; - BOOL mPinningSelectedItem; LLRect mScrollConstraintRect; - BOOL mNeedsAutoSelect; - BOOL mAutoSelectOverride; - BOOL mNeedsAutoRename; - bool mUseLabelSuffix; - - BOOL mDebugFilters; + + bool mDebugFilters; U32 mSortOrder; U32 mSearchType; LLDepthStack mAutoOpenItems; LLFolderViewFolder* mAutoOpenCandidate; LLFrameTimer mAutoOpenTimer; LLFrameTimer mSearchTimer; - std::string mSearchString; - LLInventoryFilter* mFilter; - BOOL mShowSelectionContext; - BOOL mShowSingleSelection; + LLWString mSearchString; + LLInventoryFilter mFilter; LLFrameTimer mMultiSelectionFadeTimer; S32 mArrangeGeneration; @@ -320,9 +332,7 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler S32 mSignalSelectCallback; S32 mMinWidth; S32 mRunningHeight; - std::map mItemMap; - BOOL mDragAndDropThisFrame; - + boost::unordered_map mItemMap; LLUUID mSelectThisID; // if non null, select this item LLHandle mParentPanel; @@ -346,11 +356,10 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler }; -bool sort_item_name(LLFolderViewItem* a, LLFolderViewItem* b); -bool sort_item_date(LLFolderViewItem* a, LLFolderViewItem* b); // Flags for buildContextMenu() const U32 SUPPRESS_OPEN_ITEM = 0x1; const U32 FIRST_SELECTED_ITEM = 0x2; +const U32 ITEM_IN_MULTI_SELECTION = 0x4; #endif // LL_LLFOLDERVIEW_H diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index dd1c7957d4..026dcf63f5 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -64,6 +64,9 @@ class LLFolderViewEventListener virtual void previewItem( void ) = 0; virtual void selectItem(void) = 0; virtual void showProperties(void) = 0; + + virtual BOOL isItemWearable() const { return FALSE; } + virtual BOOL isItemRenameable() const = 0; virtual BOOL renameItem(const std::string& new_name) = 0; virtual void nameOrDescriptionChanged(void) const { } // Singu note: Currently only used by LLWearableBridge. @@ -75,7 +78,7 @@ class LLFolderViewEventListener virtual void move( LLFolderViewEventListener* parent_listener ) = 0; virtual BOOL isItemCopyable() const = 0; virtual BOOL copyToClipboard() const = 0; - virtual void cutToClipboard() = 0; + virtual BOOL cutToClipboard() = 0; virtual BOOL isClipboardPasteable() const = 0; virtual void pasteFromClipboard(bool only_copies = false) = 0; virtual void pasteLinkFromClipboard() = 0; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 7bf80e0211..3d11804064 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -75,7 +75,7 @@ LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) void LLFolderViewItem::initClass() { sArrowImage = LLUI::getUIImage("folder_arrow.tga"); - sBoxImage = LLUI::getUIImage("rounded_square.tga"); + sBoxImage = LLUI::getUIImage("Rounded_Square"); } //static @@ -142,6 +142,10 @@ LLFolderView* LLFolderViewItem::getRoot() return mRoot; } +const LLFolderView* LLFolderViewItem::getRoot() const +{ + return mRoot; +} // Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) { @@ -210,12 +214,12 @@ BOOL LLFolderViewItem::potentiallyVisible() { // we haven't been checked against min required filter // or we have and we passed - return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered(); + return getLastFilterGeneration() < getRoot()->getFilter().getFirstSuccessGeneration() || getFiltered(); } BOOL LLFolderViewItem::getFiltered() { - return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); + return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter().getFirstSuccessGeneration(); } BOOL LLFolderViewItem::getFiltered(S32 filter_generation) @@ -324,7 +328,7 @@ void LLFolderViewItem::filterFromRoot( void ) { LLFolderViewItem* root = getRoot(); - root->filter(*((LLFolderView*)root)->getFilter()); + root->filter(((LLFolderView*)root)->getFilter()); } // This function is called when the folder view is dirty. It's @@ -374,16 +378,9 @@ void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, getRoot()->setSelection(selection, openitem, take_keyboard_focus); } -// helper function to change the selection from the root. -void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected) -{ - getRoot()->changeSelection(selection, selected); -} - -std::set LLFolderViewItem::getSelectionList() const +uuid_set_t LLFolderViewItem::getSelectionList() const { - std::set selection; - return selection; + return uuid_set_t(); } EInventorySortGroup LLFolderViewItem::getSortGroup() const @@ -587,7 +584,8 @@ void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) void LLFolderViewItem::openItem( void ) { - if( mListener ) + if (!mListener) return; + //if (mAllowWear || mListener->isItemWearable()) // Singu Note: This will do nothing if can't do anything, so just call it { mListener->openItem(); } @@ -678,7 +676,7 @@ BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) { if(!mIsSelected) { - setSelectionFromRoot(this, FALSE); + getRoot()->setSelection(this, FALSE); } make_ui_sound("UISndClick"); return TRUE; @@ -699,7 +697,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) { if(mask & MASK_CONTROL) { - changeSelectionFromRoot(this, !mIsSelected); + getRoot()->changeSelection(this, !mIsSelected); } else if (mask & MASK_SHIFT) { @@ -707,12 +705,14 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) } else { - setSelectionFromRoot(this, FALSE); + getRoot()->setSelection(this, FALSE); } make_ui_sound("UISndClick"); } else { + // If selected, we reserve the decision of deselecting/reselecting to the mouse up moment. + // This is necessary so we maintain selection consistent when starting a drag. mSelectPending = TRUE; } @@ -768,7 +768,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) // item. gFocusMgr.setKeyboardFocus(NULL); - return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); + return LLToolDragAndDrop::getInstance()->handleHover( screen_x, screen_y, mask ); } } } @@ -781,6 +781,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) { gViewerWindow->setCursor(UI_CURSOR_NOLOCKED); } + return TRUE; } else @@ -821,7 +822,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) //...then select if(mask & MASK_CONTROL) { - changeSelectionFromRoot(this, !mIsSelected); + getRoot()->changeSelection(this, !mIsSelected); } else if (mask & MASK_SHIFT) { @@ -829,7 +830,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) } else { - setSelectionFromRoot(this, FALSE); + getRoot()->setSelection(this, FALSE); } } @@ -837,7 +838,10 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) if( hasMouseCapture() ) { - getRoot()->setShowSelectionContext(FALSE); + if (getRoot()) + { + getRoot()->setShowSelectionContext(FALSE); + } gFocusMgr.setMouseCapture( NULL ); } return TRUE; @@ -895,8 +899,12 @@ void LLFolderViewItem::draw() const S32 FOCUS_LEFT = 1; const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - const BOOL in_inventory = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getRootFolderID()); - const BOOL in_library = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getLibraryRootFolderID()); + const LLUUID* id = getListener() ? &getListener()->getUUID() : nullptr; + const BOOL in_inventory = id && gInventory.isObjectDescendentOf(*id, gInventory.getRootFolderID()); + const BOOL in_library = id && !in_inventory && gInventory.isObjectDescendentOf(*id, gInventory.getLibraryRootFolderID()); + + // Don't draw filtered top level marketplace folders + if (in_inventory && !getFiltered() && depth_nesting_in_marketplace(*id) == 1) return; //--------------------------------------------------------------------------------// // Draw open folder arrow @@ -1032,7 +1040,7 @@ void LLFolderViewItem::draw() { color.mV[VALPHA] *= 0.5f; } - LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? + LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter().getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f); LLFontGL::getFontMonospace()->renderUTF8(mStatusText, 0, text_left, y, filter_color, @@ -1124,7 +1132,7 @@ LLFolderViewFolder::LLFolderViewFolder( const std::string& name, LLUIImagePtr ic LLUIImagePtr icon_open, LLUIImagePtr icon_link, LLFolderView* root, - LLFolderViewEventListener* listener ): + LLFolderViewEventListener* listener): LLFolderViewItem( name, icon, icon_open, icon_link, 0, root, listener ), // 0 = no create time mIsOpen(FALSE), mExpanderHighlighted(FALSE), @@ -1158,7 +1166,7 @@ void LLFolderViewFolder::setFilteredFolder(bool filtered, S32 filter_generation) bool LLFolderViewFolder::getFilteredFolder(S32 filter_generation) { - return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); + return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter().getFirstSuccessGeneration(); } // addToFolder() returns TRUE if it succeeds. FALSE otherwise @@ -1185,7 +1193,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) mNeedsSort = false; } - mHasVisibleChildren = hasFilteredDescendants(filter_generation); + bool filtered = !getFilteredFolder(filter_generation); // calculate height as a single item (without any children), and reshapes rectangle to match LLFolderViewItem::arrange( width, height, filter_generation ); @@ -1198,12 +1206,53 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) F32 running_height = (F32)*height; F32 target_height = (F32)*height; + bool marketplace_top = mListener && depth_nesting_in_marketplace(mListener->getUUID()) == 1; + // are my children visible? if (needsArrange()) { // set last arrange generation first, in case children are animating // and need to be arranged again mLastArrangeGeneration = getRoot()->getArrangeGeneration(); + + mHasVisibleChildren = !filtered && hasFilteredDescendants(filter_generation); + if (mHasVisibleChildren) + { + // We have to verify that there's at least one child that's not filtered out + bool found = false; + // Try the items first + for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + found = itemp->getFiltered(filter_generation); + if (found) + break; + } + if (!found) + { + // If no item found, try the folders + for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) + { + LLFolderViewFolder* folderp = (*fit); + found = folderp->getListener() + && (folderp->getFiltered(filter_generation) + || (folderp->getFilteredFolder(filter_generation) + && folderp->hasFilteredDescendants(filter_generation))); + if (found) + break; + } + } + + mHasVisibleChildren = found; + } + + // Hide marketplaces top level folders that don't match the filter for this view + if (marketplace_top) + { + setVisible(!filtered); + if (filtered) mCurHeight = target_height = 0; + } + if (mIsOpen) { // Add sizes of children @@ -1278,9 +1327,9 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) } // animate current height towards target height - if (llabs(mCurHeight - mTargetHeight) > 1.f) + if (!(marketplace_top && filtered) && llabs(mCurHeight - mTargetHeight) > 1.f) { - mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); + mCurHeight = lerp(mCurHeight, mTargetHeight, LLSmoothInterpolation::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); requestArrange(); @@ -1355,7 +1404,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) // if failed to pass filter newer than must_pass_generation // you will automatically fail this time, so we only // check against items that have passed the filter - S32 must_pass_generation = filter.getMustPassGeneration(); + S32 must_pass_generation = filter.getFirstRequiredGeneration(); bool autoopen_folders = (filter.hasFilterString()); @@ -1408,7 +1457,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) // when applying a filter, matching folders get their contents downloaded first if (filter.isNotDefault() - && getFiltered(filter.getMinRequiredGeneration()) + && getFiltered(filter.getFirstSuccessGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID()))) { @@ -1433,7 +1482,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) if (folder->getCompletedFilterGeneration() >= filter_generation) { // track latest generation to pass any child items - if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getMinRequiredGeneration())) + if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getFirstSuccessGeneration())) { mMostFilteredDescendantGeneration = filter_generation; requestArrange(); @@ -1487,7 +1536,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) item->filter( filter ); - if (item->getFiltered(filter.getMinRequiredGeneration())) + if (item->getFiltered(filter.getFirstSuccessGeneration())) { mMostFilteredDescendantGeneration = filter_generation; requestArrange(); @@ -1547,12 +1596,14 @@ void LLFolderViewFolder::dirtyFilter() { // we're a folder, so invalidate our completed generation setCompletedFilterGeneration(-1, FALSE); + for (auto folder : mFolders) // Dirty our children's filters too, so they get updated. + folder->dirtyFilter(); LLFolderViewItem::dirtyFilter(); } BOOL LLFolderViewFolder::getFiltered() { - return getFilteredFolder(getRoot()->getFilter()->getMinRequiredGeneration()) + return getFilteredFolder(getRoot()->getFilter().getFirstSuccessGeneration()) && LLFolderViewItem::getFiltered(); } @@ -1569,7 +1620,7 @@ BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation) BOOL LLFolderViewFolder::hasFilteredDescendants() { - return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration(); + return mMostFilteredDescendantGeneration >= getRoot()->getFilter().getCurrentGeneration(); } // Passes selection information on to children and record selection @@ -1770,7 +1821,7 @@ void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFo { return; } - if (selecting) + if (selecting && (*it)->getVisible()) { items.push_back(*it); } @@ -1789,7 +1840,7 @@ void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFo return; } - if (selecting) + if (selecting && (*it)->getVisible()) { items.push_back(*it); } @@ -1811,7 +1862,7 @@ void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFo return; } - if (selecting) + if (selecting && (*it)->getVisible()) { items.push_back(*it); } @@ -1830,7 +1881,7 @@ void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFo return; } - if (selecting) + if (selecting && (*it)->getVisible()) { items.push_back(*it); } @@ -1938,6 +1989,7 @@ void LLFolderViewFolder::destroyView() while (!mFolders.empty()) { LLFolderViewFolder *folderp = mFolders.back(); + mFolders.pop_back(); folderp->destroyView(); // removes entry from mFolders } @@ -2411,9 +2463,16 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { + if (!mAllowDrop) + { + *accept = ACCEPT_NO; + tooltip_msg = LLTrans::getString("TooltipOutboxCannotDropOnRoot"); + return TRUE; + } + BOOL accepted = mListener && mListener->dragOrDrop(mask, drop, cargo_type, cargo_data); - - if (accepted) + + if (accepted) { mDragAndDropTarget = TRUE; *accept = ACCEPT_YES_MULTI; @@ -2521,11 +2580,11 @@ void LLFolderViewFolder::draw() } else if (mIsOpen) { - mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); + mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLSmoothInterpolation::getInterpolant(0.04f)); } else { - mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); + mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLSmoothInterpolation::getInterpolant(0.025f)); } bool possibly_has_children = false; @@ -2572,9 +2631,9 @@ BOOL LLFolderViewFolder::potentiallyVisible() // folder should be visible by it's own filter status return LLFolderViewItem::potentiallyVisible() // or one or more of its descendants have passed the minimum filter requirement - || hasFilteredDescendants(getRoot()->getFilter()->getMinRequiredGeneration()) + || hasFilteredDescendants(getRoot()->getFilter().getFirstSuccessGeneration()) // or not all of its descendants have been checked against minimum filter requirement - || getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration(); + || getCompletedFilterGeneration() < getRoot()->getFilter().getFirstSuccessGeneration(); } // this does prefix traversal, as folders are listed above their contents @@ -2797,6 +2856,7 @@ bool LLInventorySort::updateSort(U32 order) mByDate = (order & LLInventoryFilter::SO_DATE); mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); + mFoldersByWeight = (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_WEIGHT); return true; } return false; @@ -2804,39 +2864,9 @@ bool LLInventorySort::updateSort(U32 order) bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b) { - /* TO-DO - // ignore sort order for landmarks in the Favorites folder. - // they should be always sorted as in Favorites bar. See EXT-719 - if (a->getSortGroup() == SG_ITEM - && b->getSortGroup() == SG_ITEM - && a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK - && b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) - { - - static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - - LLUUID a_uuid = a->getParentFolder()->getListener()->getUUID(); - LLUUID b_uuid = b->getParentFolder()->getListener()->getUUID(); - - if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) - { - // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem - // or to LLInvFVBridge - LLViewerInventoryItem* aitem = (static_cast(a->getListener()))->getItem(); - LLViewerInventoryItem* bitem = (static_cast(b->getListener()))->getItem(); - if (!aitem || !bitem) - return false; - S32 a_sort = aitem->getSortField(); - S32 b_sort = bitem->getSortField(); - return a_sort < b_sort; - } - }*/ - // We sort by name if we aren't sorting by date // OR if these are folders and we are sorting folders by name. - bool by_name = (!mByDate - || (mFoldersByName - && (a->getSortGroup() != SG_ITEM))); + bool by_name = ((!mByDate || (mFoldersByName && (a->getSortGroup() != SG_ITEM))) && !mFoldersByWeight); if (a->getSortGroup() != b->getSortGroup()) { @@ -2868,6 +2898,31 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde return (compare < 0); } } + else if (mFoldersByWeight) + { + S32 weight_a = compute_stock_count(a->getListener()->getUUID()); + S32 weight_b = compute_stock_count(b->getListener()->getUUID()); + if (weight_a == weight_b) + { + // Equal weight -> use alphabetical order + return (LLStringUtil::compareDict(a->getListener()->getDisplayName(), b->getListener()->getDisplayName()) < 0); + } + else if (weight_a == COMPUTE_STOCK_INFINITE) + { + // No stock -> move a at the end of the list + return false; + } + else if (weight_b == COMPUTE_STOCK_INFINITE) + { + // No stock -> move b at the end of the list + return true; + } + else + { + // Lighter is first (sorted in increasing order of weight) + return (weight_a < weight_b); + } + } else { // BUG: This is very very slow. The getCreationDate() is log n in number diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 56990360a1..9bb163c804 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -30,6 +30,8 @@ #include "lluiimage.h" #include "lluictrl.h" +#include + class LLFontGL; class LLFolderView; class LLFolderViewEventListener; @@ -61,7 +63,8 @@ class LLInventorySort : mSortOrder(0), mByDate(false), mSystemToTop(false), - mFoldersByName(false) { } + mFoldersByName(false), + mFoldersByWeight(false) { } // Returns true if order has changed bool updateSort(U32 order); @@ -74,6 +77,7 @@ class LLInventorySort bool mByDate; bool mSystemToTop; bool mFoldersByName; + bool mFoldersByWeight; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -139,12 +143,11 @@ class LLFolderViewItem : public LLUICtrl BOOL mIsLoading; LLTimer mTimeSinceRequestStart; bool mShowLoadStatus; + bool mAllowDrop; + bool mAllowWear; std::string mSearchable; U32 mSearchType; - - // helper function to change the selection from the root. - void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); //Sets extra search criteria 'labels' to be compared against by filter. void updateExtraSearchCriteria(); @@ -217,7 +220,7 @@ class LLFolderViewItem : public LLUICtrl virtual void selectItem(); // gets multiple-element selection - virtual std::set getSelectionList() const; + virtual uuid_set_t getSelectionList() const; // Returns true is this object and all of its children can be removed (deleted by user) virtual BOOL isRemovable(); @@ -240,13 +243,16 @@ class LLFolderViewItem : public LLUICtrl void setShowLoadStatus(bool status) { mShowLoadStatus = status; } + void setAllowDrop(bool allow) { mAllowDrop = allow; } + void setAllowWear(bool allow) { mAllowWear = allow; } + // Call through to the viewed object and return true if it can be // removed. Returns true if it's removed. //virtual BOOL removeRecursively(BOOL single_item); BOOL remove(); // Build an appropriate context menu for the item. Flags unused. - void buildContextMenu(LLMenuGL& menu, U32 flags); + void buildContextMenu(class LLMenuGL& menu, U32 flags); // This method returns the actual name of the thing being // viewed. This method will ask the viewed object itself. @@ -283,12 +289,12 @@ class LLFolderViewItem : public LLUICtrl virtual void openItem( void ); virtual void preview(void); - // Show children (unfortunate that this is called "open") + // Show children virtual void setOpen(BOOL open = TRUE) {}; - virtual BOOL isOpen() const { return FALSE; } virtual LLFolderView* getRoot(); + virtual const LLFolderView* getRoot() const; BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); S32 getIndentation() { return mIndentation; } @@ -532,12 +538,14 @@ class LLFolderViewFolder : public LLFolderViewItem virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); - BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop, + BOOL handleDragAndDropToThisFolder(MASK mask, + BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, @@ -554,6 +562,7 @@ class LLFolderViewFolder : public LLFolderViewItem items_t::const_iterator getItemsBegin() const { return mItems.begin(); } items_t::const_iterator getItemsEnd() const { return mItems.end(); } items_t::size_type getItemsCount() const { return mItems.size(); } + LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector& items); }; diff --git a/indra/newview/llfollowcam.cpp b/indra/newview/llfollowcam.cpp index c089b6d01b..e30eb176c4 100644 --- a/indra/newview/llfollowcam.cpp +++ b/indra/newview/llfollowcam.cpp @@ -334,11 +334,11 @@ void LLFollowCam::update() F32 force = focusOffsetDistance - focusThresholdNormalizedByDistance; */ - F32 focusLagLerp = LLCriticalDamp::getInterpolant( mFocusLag ); + F32 focusLagLerp = LLSmoothInterpolation::getInterpolant( mFocusLag ); focus_pt_agent = lerp( focus_pt_agent, whereFocusWantsToBe, focusLagLerp ); mSimulatedFocusGlobal = gAgent.getPosGlobalFromAgent(focus_pt_agent); } - mRelativeFocus = lerp(mRelativeFocus, (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation, LLCriticalDamp::getInterpolant(0.05f)); + mRelativeFocus = lerp(mRelativeFocus, (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation, LLSmoothInterpolation::getInterpolant(0.05f)); }// if focus is not locked --------------------------------------------- @@ -421,7 +421,7 @@ void LLFollowCam::update() //------------------------------------------------------------------------------------------------- if ( distanceFromPositionToIdealPosition > mPositionThreshold ) { - F32 positionPullLerp = LLCriticalDamp::getInterpolant( mPositionLag ); + F32 positionPullLerp = LLSmoothInterpolation::getInterpolant( mPositionLag ); simulated_pos_agent = lerp( simulated_pos_agent, whereCameraPositionWantsToBe, positionPullLerp ); } @@ -441,7 +441,7 @@ void LLFollowCam::update() updateBehindnessConstraint(gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal), simulated_pos_agent); mSimulatedPositionGlobal = gAgent.getPosGlobalFromAgent(simulated_pos_agent); - mRelativePos = lerp(mRelativePos, (simulated_pos_agent - mSubjectPosition) * ~mSubjectRotation, LLCriticalDamp::getInterpolant(0.05f)); + mRelativePos = lerp(mRelativePos, (simulated_pos_agent - mSubjectPosition) * ~mSubjectRotation, LLSmoothInterpolation::getInterpolant(0.05f)); } // if position is not locked ----------------------------------------------------------- @@ -496,7 +496,7 @@ BOOL LLFollowCam::updateBehindnessConstraint(LLVector3 focus, LLVector3& cam_pos if ( cameraOffsetAngle > mBehindnessMaxAngle ) { - F32 fraction = ((cameraOffsetAngle - mBehindnessMaxAngle) / cameraOffsetAngle) * LLCriticalDamp::getInterpolant(mBehindnessLag); + F32 fraction = ((cameraOffsetAngle - mBehindnessMaxAngle) / cameraOffsetAngle) * LLSmoothInterpolation::getInterpolant(mBehindnessLag); cam_position = focus + horizontalSubjectBack * (slerp(fraction, camera_offset_rotation, LLQuaternion::DEFAULT)); cam_position.mV[VZ] = cameraZ; // clamp z value back to what it was before we started messing with it constraint_active = TRUE; diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index c07705a8cf..4c18641858 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -66,14 +66,10 @@ void fake_local_chat(std::string msg); // Longest time, in seconds, to wait for all animations to stop playing const F32 MAX_WAIT_ANIM_SECS = 30.f; -// If this gesture is a link, get the base gesture that this link points to, -// otherwise just return this id. -static const LLUUID& get_linked_uuid(const LLUUID& item_id); - // Lightweight constructor. // init() does the heavy lifting. LLGestureMgr::LLGestureMgr() -: mValid(FALSE), +: mValid(false), mPlaying(), mActive(), mLoadingCount(0) @@ -91,7 +87,7 @@ LLGestureMgr::~LLGestureMgr() LLMultiGesture* gesture = (*it).second; delete gesture; - gesture = NULL; + gesture = nullptr; } gInventory.removeObserver(this); } @@ -152,86 +148,64 @@ void LLGestureMgr::activateGesture(const LLUUID& item_id) mLoadingCount = 1; mDeactivateSimilarNames.clear(); - const BOOL inform_server = TRUE; - const BOOL deactivate_similar = FALSE; + const bool inform_server = true; + const bool deactivate_similar = false; activateGestureWithAsset(item_id, asset_id, inform_server, deactivate_similar); } void LLGestureMgr::activateGestures(LLViewerInventoryItem::item_array_t& items) { + mDeactivateSimilarNames.clear(); + // Load up the assets - S32 count = 0; - LLViewerInventoryItem::item_array_t::const_iterator it; - for (it = items.begin(); it != items.end(); ++it) - { - LLViewerInventoryItem* item = *it; + mLoadingCount = 0; - if (isGestureActive(item->getUUID())) + // Inform the database of this change + LLMessageSystem* msg = gMessageSystem; + bool start_message = true; + + for (const auto& item : items) + { + const auto& id = item->getUUID(); + if (isGestureActive(id)) { continue; } - else - { // Make gesture active and persistent through login sessions. -Aura 07-12-06 - activateGesture(item->getUUID()); - } - count++; - } + // Make gesture active and persistent through login sessions. -Aura 07-12-06 + activateGesture(id); - mLoadingCount = count; - mDeactivateSimilarNames.clear(); - - for (it = items.begin(); it != items.end(); ++it) - { - LLViewerInventoryItem* item = *it; + ++mLoadingCount; - if (isGestureActive(item->getUUID())) - { - continue; - } + const auto& asset_id = item->getAssetUUID(); // Don't inform server, we'll do that in bulk - const BOOL no_inform_server = FALSE; - const BOOL deactivate_similar = TRUE; - activateGestureWithAsset(item->getUUID(), item->getAssetUUID(), + const bool no_inform_server = false; + const bool deactivate_similar = true; + activateGestureWithAsset(id, asset_id, no_inform_server, deactivate_similar); - } - - // Inform the database of this change - LLMessageSystem* msg = gMessageSystem; - - BOOL start_message = TRUE; - - for (it = items.begin(); it != items.end(); ++it) - { - LLViewerInventoryItem* item = *it; - - if (isGestureActive(item->getUUID())) - { - continue; - } if (start_message) { msg->newMessage("ActivateGestures"); msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("AgentID", gAgentID); msg->addUUID("SessionID", gAgent.getSessionID()); msg->addU32("Flags", 0x0); - start_message = FALSE; + start_message = false; } msg->nextBlock("Data"); - msg->addUUID("ItemID", item->getUUID()); - msg->addUUID("AssetID", item->getAssetUUID()); + msg->addUUID("ItemID", id); + msg->addUUID("AssetID", asset_id); msg->addU32("GestureFlags", 0x0); if (msg->getCurrentSendTotal() > MTUBYTES) { gAgent.sendReliableMessage(); - start_message = TRUE; + start_message = true; } } @@ -245,8 +219,8 @@ void LLGestureMgr::activateGestures(LLViewerInventoryItem::item_array_t& items) struct LLLoadInfo { LLUUID mItemID; - BOOL mInformServer; - BOOL mDeactivateSimilar; + bool mInformServer; + bool mDeactivateSimilar; }; // If inform_server is true, will send a message upstream to update @@ -256,10 +230,10 @@ struct LLLoadInfo */ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, const LLUUID& asset_id, - BOOL inform_server, - BOOL deactivate_similar) + bool inform_server, + bool deactivate_similar) { - const LLUUID& base_item_id = get_linked_uuid(item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); if( !gAssetStorage ) { @@ -279,9 +253,9 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, // return; // } - // For now, put NULL into the item map. We'll build a gesture + // For now, put nullptr into the item map. We'll build a gesture // class object when the asset data arrives. - mActive[base_item_id] = NULL; + mActive[base_item_id] = nullptr; // Copy the UUID if (asset_id.notNull()) @@ -291,7 +265,7 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, info->mInformServer = inform_server; info->mDeactivateSimilar = deactivate_similar; - const BOOL high_priority = TRUE; + const bool high_priority = true; gAssetStorage->getAssetData(asset_id, LLAssetType::AT_GESTURE, onLoadComplete, @@ -307,8 +281,8 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, void LLGestureMgr::deactivateGesture(const LLUUID& item_id) { - const LLUUID& base_item_id = get_linked_uuid(item_id); - item_map_t::iterator it = mActive.find(base_item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); + const auto& it = mActive.find(base_item_id); if (it == mActive.end()) { LL_WARNS() << "deactivateGesture for inactive gesture " << base_item_id << LL_ENDL; @@ -318,13 +292,13 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) // mActive owns this gesture pointer, so clean up memory. LLMultiGesture* gesture = (*it).second; - // Can be NULL gestures in the map + // Can be nullptr gestures in the map if (gesture) { stopGesture(gesture); delete gesture; - gesture = NULL; + gesture = nullptr; } mActive.erase(it); @@ -334,7 +308,7 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) LLMessageSystem* msg = gMessageSystem; msg->newMessage("DeactivateGestures"); msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("AgentID", gAgentID); msg->addUUID("SessionID", gAgent.getSessionID()); msg->addU32("Flags", 0x0); @@ -350,14 +324,16 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) } -void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id) +void LLGestureMgr::deactivateSimilarGestures(const LLMultiGesture* in, const LLUUID& in_item_id) { - const LLUUID& base_in_item_id = get_linked_uuid(in_item_id); - uuid_vec_t gest_item_ids; + const LLUUID& base_in_item_id = gInventory.getLinkedItemID(in_item_id); + + // Inform database of the change + LLMessageSystem* msg = gMessageSystem; + bool start_message = true; // Deactivate all gestures that match - item_map_t::iterator it; - for (it = mActive.begin(); it != mActive.end(); ) + for (auto it = mActive.begin(), end = mActive.end(); it != end; ) { const LLUUID& item_id = (*it).first; LLMultiGesture* gest = (*it).second; @@ -372,16 +348,38 @@ void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& i else if ((!gest->mTrigger.empty() && gest->mTrigger == in->mTrigger) || (gest->mKey != KEY_NONE && gest->mKey == in->mKey && gest->mMask == in->mMask)) { - gest_item_ids.push_back(item_id); - stopGesture(gest); delete gest; - gest = NULL; + gest = nullptr; - mActive.erase(it++); + it = mActive.erase(it); + end = mActive.end(); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + if (start_message) + { + msg->newMessage("DeactivateGestures"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgentID); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->addU32("Flags", 0x0); + start_message = false; + } + + msg->nextBlock("Data"); + msg->addUUID("ItemID", item_id); + msg->addU32("GestureFlags", 0x0); + + if (msg->getCurrentSendTotal() > MTUBYTES) + { + gAgent.sendReliableMessage(); + start_message = true; + } + + // Add to the list of names for the user. + if (const auto& item = gInventory.getItem(item_id)) + mDeactivateSimilarNames += item->getName() + '\n'; } else { @@ -389,88 +387,45 @@ void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& i } } - // Inform database of the change - LLMessageSystem* msg = gMessageSystem; - BOOL start_message = TRUE; - uuid_vec_t::const_iterator vit = gest_item_ids.begin(); - while (vit != gest_item_ids.end()) - { - if (start_message) - { - msg->newMessage("DeactivateGestures"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->addU32("Flags", 0x0); - start_message = FALSE; - } - - msg->nextBlock("Data"); - msg->addUUID("ItemID", *vit); - msg->addU32("GestureFlags", 0x0); - - if (msg->getCurrentSendTotal() > MTUBYTES) - { - gAgent.sendReliableMessage(); - start_message = TRUE; - } - - ++vit; - } - if (!start_message) { gAgent.sendReliableMessage(); } - // Add to the list of names for the user. - for (vit = gest_item_ids.begin(); vit != gest_item_ids.end(); ++vit) - { - LLViewerInventoryItem* item = gInventory.getItem(*vit); - if (!item) continue; - - mDeactivateSimilarNames.append(item->getName()); - mDeactivateSimilarNames.append("\n"); - } - + // *TODO: We call notify observers in stopGesture above, should we pass a flag to only do that here? notifyObservers(); } -BOOL LLGestureMgr::isGestureActive(const LLUUID& item_id) +bool LLGestureMgr::isGestureActive(const LLUUID& item_id) const { - const LLUUID& base_item_id = get_linked_uuid(item_id); - item_map_t::iterator it = mActive.find(base_item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); + const auto& it = mActive.find(base_item_id); return (it != mActive.end()); } -BOOL LLGestureMgr::isGesturePlaying(const LLUUID& item_id) +bool LLGestureMgr::isGesturePlaying(const LLUUID& item_id) const { - const LLUUID& base_item_id = get_linked_uuid(item_id); - item_map_t::iterator it = mActive.find(base_item_id); - if (it == mActive.end()) return FALSE; + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); + const auto& it = mActive.find(base_item_id); + if (it == mActive.end()) return false; - LLMultiGesture* gesture = (*it).second; - if (!gesture) return FALSE; + const LLMultiGesture* gesture = (*it).second; + if (!gesture) return false; return gesture->mPlaying; } -BOOL LLGestureMgr::isGesturePlaying(LLMultiGesture* gesture) +bool LLGestureMgr::isGesturePlaying(const LLMultiGesture* gesture) const { - if(!gesture) - { - return FALSE; - } - - return gesture->mPlaying; + return gesture && gesture->mPlaying; } void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id) { - const LLUUID& base_item_id = get_linked_uuid(item_id); - item_map_t::iterator it = mActive.find(base_item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); + const auto& it = mActive.find(base_item_id); if (it == mActive.end()) { LL_WARNS() << "replaceGesture for inactive gesture " << base_item_id << LL_ENDL; @@ -485,7 +440,7 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_ges mActive[base_item_id] = new_gesture; delete old_gesture; - old_gesture = NULL; + old_gesture = nullptr; if (asset_id.notNull()) { @@ -494,10 +449,10 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_ges LLLoadInfo* info = new LLLoadInfo; info->mItemID = base_item_id; - info->mInformServer = TRUE; - info->mDeactivateSimilar = FALSE; + info->mInformServer = true; + info->mDeactivateSimilar = false; - const BOOL high_priority = TRUE; + const bool high_priority = true; gAssetStorage->getAssetData(asset_id, LLAssetType::AT_GESTURE, onLoadComplete, @@ -510,9 +465,9 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_ges void LLGestureMgr::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id) { - const LLUUID& base_item_id = get_linked_uuid(item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); - item_map_t::iterator it = LLGestureMgr::instance().mActive.find(base_item_id); + auto it = LLGestureMgr::instance().mActive.find(base_item_id); if (it == mActive.end()) { LL_WARNS() << "replaceGesture for inactive gesture " << base_item_id << LL_ENDL; @@ -532,7 +487,7 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool local) gesture->mCurrentStep = 0; // Add to list of playing - gesture->mPlaying = TRUE; + gesture->mPlaying = true; gesture->mLocal = local; mPlaying.push_back(gesture); @@ -569,7 +524,7 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool local) LLAssetType::AT_ANIMATION, onAssetLoadComplete, (void *)id, - TRUE); + true); } break; } @@ -585,8 +540,8 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool local) gAssetStorage->getAssetData(sound_id, LLAssetType::AT_SOUND, onAssetLoadComplete, - NULL, - TRUE); + nullptr, + true); } break; } @@ -613,7 +568,7 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool local) // Convenience function that looks up the item_id for you. void LLGestureMgr::playGesture(const LLUUID& item_id, bool local) { - const LLUUID& base_item_id = get_linked_uuid(item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); item_map_t::iterator it = mActive.find(base_item_id); if (it == mActive.end()) return; @@ -628,12 +583,12 @@ void LLGestureMgr::playGesture(const LLUUID& item_id, bool local) // Iterates through space delimited tokens in string, triggering any gestures found. // Generates a revised string that has the found tokens replaced by their replacement strings // and (as a minor side effect) has multiple spaces in a row replaced by single spaces. -BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::string* revised_string) +bool LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::string* revised_string) { std::string tokenized = utf8str; - BOOL found_gestures = FALSE; - BOOL first_token = TRUE; + bool found_gestures = false; + bool first_token = true; typedef boost::tokenizer > tokenizer; boost::char_separator sep(" "); @@ -643,17 +598,16 @@ BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::strin for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) { const char* cur_token = token_iter->c_str(); - LLMultiGesture* gesture = NULL; + LLMultiGesture* gesture = nullptr; // Only pay attention to the first gesture in the string. if( !found_gestures ) { // collect gestures that match std::vector matching; - item_map_t::iterator it; - for (it = mActive.begin(); it != mActive.end(); ++it) + for (const auto& pair : mActive) { - gesture = (*it).second; + gesture = pair.second; // Gesture asset data might not have arrived yet if (!gesture) continue; @@ -663,7 +617,7 @@ BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::strin matching.push_back(gesture); } - gesture = NULL; + gesture = nullptr; } @@ -677,59 +631,43 @@ BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::strin playGesture(gesture); - if (!gesture->mReplaceText.empty()) + if (revised_string && !gesture->mReplaceText.empty()) { - if( !first_token ) - { - if (revised_string) - revised_string->append( " " ); - } + if (!first_token) revised_string->push_back(' '); // Don't muck with the user's capitalization if we don't have to. - if( LLStringUtil::compareInsensitive(cur_token, gesture->mReplaceText) == 0) - { - if (revised_string) - revised_string->append( cur_token ); - } - else - { - if (revised_string) - revised_string->append( gesture->mReplaceText ); - } + revised_string->append(LLStringUtil::compareInsensitive(cur_token, gesture->mReplaceText) == 0 ? + cur_token : gesture->mReplaceText); } - found_gestures = TRUE; + found_gestures = true; } } } - if(!gesture) + if (!gesture && revised_string) { // This token doesn't match a gesture. Pass it through to the output. - if( !first_token ) - { - if (revised_string) - revised_string->append( " " ); - } - if (revised_string) - revised_string->append( cur_token ); + if (!first_token) revised_string->push_back(' '); + revised_string->append(cur_token); } - first_token = FALSE; - gesture = NULL; + first_token = false; + gesture = nullptr; } return found_gestures; } -BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask) +bool LLGestureMgr::triggerGesture(KEY key, MASK mask) { - std::vector matching; - item_map_t::iterator it; + if (mActive.empty()) return false; + + std::vector matching; // collect matching gestures - for (it = mActive.begin(); it != mActive.end(); ++it) + for (const auto& pair : mActive) { - LLMultiGesture* gesture = (*it).second; + LLMultiGesture* gesture = pair.second; // asset data might not have arrived yet if (!gesture) continue; @@ -742,16 +680,13 @@ BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask) } // choose one and play it - if (matching.size() > 0) + const auto& count = matching.size(); + if (count > 0) { - U32 random = ll_rand(matching.size()); - - LLMultiGesture* gesture = matching[random]; - - playGesture(gesture); - return TRUE; + playGesture(matching[ll_rand(count)]); + return true; } - return FALSE; + return false; } @@ -761,53 +696,35 @@ S32 LLGestureMgr::getPlayingCount() const } -struct IsGesturePlaying : public std::unary_function -{ - bool operator()(const LLMultiGesture* gesture) const - { - return gesture->mPlaying ? true : false; - } -}; - void LLGestureMgr::update() { - S32 i; - for (i = 0; i < (S32)mPlaying.size(); ++i) - { - stepGesture(mPlaying[i]); - } - - // Clear out gestures that are done, by moving all the - // ones that are still playing to the front. - std::vector::iterator new_end; - new_end = std::partition(mPlaying.begin(), - mPlaying.end(), - IsGesturePlaying()); - - // Something finished playing - if (new_end != mPlaying.end()) + bool notify = false; + for (auto it = mPlaying.begin(), end = mPlaying.end(); it != end;) { - // Delete the completed gestures that want deletion - std::vector::iterator it; - for (it = new_end; it != mPlaying.end(); ++it) + auto& gesture = *it; + stepGesture(gesture); + if (!gesture->mPlaying) { - LLMultiGesture* gesture = *it; - + // Delete the completed gestures that want deletion if (gesture->mDoneCallback) { gesture->mDoneCallback(gesture); // callback might have deleted gesture, can't // rely on this pointer any more - gesture = NULL; + gesture = nullptr; } - } - - // And take done gestures out of the playing list - mPlaying.erase(new_end, mPlaying.end()); - notifyObservers(); + // And take done gesture out of the playing list + it = mPlaying.erase(it); + end = mPlaying.end(); + notify = true; + } + else ++it; } + + // Something finished playing + if (notify) notifyObservers(); } @@ -822,22 +739,21 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) // Of the ones that started playing, have any stopped? - std::set::iterator gest_it; - for (gest_it = gesture->mPlayingAnimIDs.begin(); - gest_it != gesture->mPlayingAnimIDs.end(); - ) + const auto& signaled(gAgentAvatarp->mSignaledAnimations); + const auto& signaled_end(signaled.end()); + for (auto gest_it = gesture->mPlayingAnimIDs.begin(), end = gesture->mPlayingAnimIDs.end(); gest_it != end;) { if (gesture->mLocal) { // Local, erase if no longer playing (or gone) LLMotion* motion = gAgentAvatarp->findMotion(*gest_it); if (!motion || motion->isStopped()) - gesture->mPlayingAnimIDs.erase(gest_it); - ++gest_it; + gest_it = gesture->mPlayingAnimIDs.erase(gest_it); + else ++gest_it; } // look in signaled animations (simulator's view of what is // currently playing. - else if (gAgentAvatarp->mSignaledAnimations.find(*gest_it) != gAgentAvatarp->mSignaledAnimations.end()) + else if (signaled.find(*gest_it) != signaled_end) { ++gest_it; } @@ -845,23 +761,20 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) { // not found, so not currently playing or scheduled to play // delete from the triggered set - gesture->mPlayingAnimIDs.erase(gest_it++); + gest_it = gesture->mPlayingAnimIDs.erase(gest_it); } } // Of all the animations that we asked the sim to start for us, // pick up the ones that have actually started. - for (gest_it = gesture->mRequestedAnimIDs.begin(); - gest_it != gesture->mRequestedAnimIDs.end(); - ) + for (auto gest_it = gesture->mRequestedAnimIDs.begin(), end = gesture->mRequestedAnimIDs.end(); gest_it != end;) { - LLVOAvatar::AnimIterator play_it = gAgentAvatarp->mSignaledAnimations.find(*gest_it); - if (play_it != gAgentAvatarp->mSignaledAnimations.end()) + if (signaled.find(*gest_it) != signaled_end) { // Hooray, this animation has started playing! // Copy into playing. gesture->mPlayingAnimIDs.insert(*gest_it); - gesture->mRequestedAnimIDs.erase(gest_it++); + gest_it = gesture->mRequestedAnimIDs.erase(gest_it); } else { @@ -871,21 +784,21 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) } // Run the current steps - BOOL waiting = FALSE; + bool waiting = false; while (!waiting && gesture->mPlaying) { // Get the current step, if there is one. // Otherwise enter the waiting at end state. - LLGestureStep* step = NULL; + LLGestureStep* step = nullptr; if (gesture->mCurrentStep < (S32)gesture->mSteps.size()) { step = gesture->mSteps[gesture->mCurrentStep]; - llassert(step != NULL); + llassert(step != nullptr); } else { // step stays null, we're off the end - gesture->mWaitingAtEnd = TRUE; + gesture->mWaitingAtEnd = true; } @@ -900,12 +813,12 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) && gesture->mPlayingAnimIDs.empty())) { // all animations are done playing - gesture->mWaitingAtEnd = FALSE; - gesture->mPlaying = FALSE; + gesture->mWaitingAtEnd = false; + gesture->mPlaying = false; } else { - waiting = TRUE; + waiting = true; } continue; } @@ -920,20 +833,20 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) && gesture->mPlayingAnimIDs.empty())) { // all animations are done playing - gesture->mWaitingAnimations = FALSE; - gesture->mCurrentStep++; + gesture->mWaitingAnimations = false; + ++gesture->mCurrentStep; } else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_ANIM_SECS) { // we've waited too long for an animation LL_INFOS() << "Waited too long for animations to stop, continuing gesture." << LL_ENDL; - gesture->mWaitingAnimations = FALSE; - gesture->mCurrentStep++; + gesture->mWaitingAnimations = false; + ++gesture->mCurrentStep; } else { - waiting = TRUE; + waiting = true; } continue; } @@ -949,13 +862,13 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) if (elapsed > wait_step->mWaitSeconds) { // wait is done, continue execution - gesture->mWaitingTimer = FALSE; - gesture->mCurrentStep++; + gesture->mWaitingTimer = false; + ++gesture->mCurrentStep; } else { // we're waiting, so execution is done for now - waiting = TRUE; + waiting = true; } continue; } @@ -975,7 +888,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step; if (anim_step->mAnimAssetID.isNull()) { - gesture->mCurrentStep++; + ++gesture->mCurrentStep; } if (anim_step->mFlags & ANIM_FLAG_STOP) @@ -988,7 +901,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) { gAgent.sendAnimationRequest(anim_step->mAnimAssetID, ANIM_REQUEST_STOP); // remove it from our request set in case we just requested it - std::set::iterator set_it = gesture->mRequestedAnimIDs.find(anim_step->mAnimAssetID); + auto set_it = gesture->mRequestedAnimIDs.find(anim_step->mAnimAssetID); if (set_it != gesture->mRequestedAnimIDs.end()) { gesture->mRequestedAnimIDs.erase(set_it); @@ -1012,37 +925,37 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) gesture->mRequestedAnimIDs.insert(anim_step->mAnimAssetID); } } - gesture->mCurrentStep++; + ++gesture->mCurrentStep; break; } case STEP_SOUND: { LLGestureStepSound* sound_step = (LLGestureStepSound*)step; const LLUUID& sound_id = sound_step->mSoundAssetID; - const F32 volume = 1.f; + constexpr F32 volume = 1.f; if (gesture->mLocal) gAudiop->triggerSound(sound_id, gAgentID, volume, LLAudioEngine::AUDIO_TYPE_UI, gAgent.getPositionGlobal()); else send_sound_trigger(sound_id, volume); - gesture->mCurrentStep++; + ++gesture->mCurrentStep; break; } case STEP_CHAT: { LLGestureStepChat* chat_step = (LLGestureStepChat*)step; - std::string chat_text = chat_step->mChatText; + const std::string& chat_text = chat_step->mChatText; // Don't animate the nodding, as this might not blend with // other playing animations. - const BOOL animate = FALSE; - if ( cmd_line_chat(chat_text, CHAT_TYPE_NORMAL)) + constexpr bool animate = false; + if (cmd_line_chat(chat_text, CHAT_TYPE_NORMAL)) { #if SHY_MOD //Command handler if(!SHCommandHandler::handleCommand(true, chat_text, gAgentID, gAgentAvatarp))//returns true if handled #endif //shy_mod gesture->mLocal ? fake_local_chat(chat_text) : gChatBar->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); } - gesture->mCurrentStep++; + ++gesture->mCurrentStep; break; } case STEP_WAIT: @@ -1050,19 +963,19 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) LLGestureStepWait* wait_step = (LLGestureStepWait*)step; if (wait_step->mFlags & WAIT_FLAG_TIME) { - gesture->mWaitingTimer = TRUE; + gesture->mWaitingTimer = true; gesture->mWaitTimer.reset(); } else if (wait_step->mFlags & WAIT_FLAG_ALL_ANIM) { - gesture->mWaitingAnimations = TRUE; + gesture->mWaitingAnimations = true; // Use the wait timer as a deadlock breaker for animation // waits. gesture->mWaitTimer.reset(); } else { - gesture->mCurrentStep++; + ++gesture->mCurrentStep; } // Don't increment instruction pointer until wait is complete. break; @@ -1083,37 +996,29 @@ void LLGestureMgr::onLoadComplete(LLVFS *vfs, { LLLoadInfo* info = (LLLoadInfo*)user_data; - LLUUID item_id = info->mItemID; - BOOL inform_server = info->mInformServer; - BOOL deactivate_similar = info->mDeactivateSimilar; + const LLUUID item_id = info->mItemID; + const bool inform_server = info->mInformServer; + const bool deactivate_similar = info->mDeactivateSimilar; delete info; - info = NULL; + info = nullptr; LLGestureMgr& self = LLGestureMgr::instance(); - self.mLoadingCount--; + --self.mLoadingCount; if (0 == status) { LLVFile file(vfs, asset_uuid, type, LLVFile::READ); S32 size = file.getSize(); - char* buffer = new char[size+1]; - if (buffer == NULL) - { - LL_ERRS() << "Memory Allocation Failed" << LL_ENDL; - return; - } - - file.read((U8*)buffer, size); /* Flawfinder: ignore */ - // ensure there's a trailing NULL so strlen will work. - buffer[size] = '\0'; + // ensure there's a trailing nullptr so strlen will work. + std::vector buffer(size+1, '\0'); + file.read((U8*)&buffer[0], size); LLMultiGesture* gesture = new LLMultiGesture(); - LLDataPackerAsciiBuffer dp(buffer, size+1); - BOOL ok = gesture->deserialize(dp); + LLDataPackerAsciiBuffer dp(&buffer[0], size+1); - if (ok) + if (gesture->deserialize(dp)) { if (deactivate_similar) { @@ -1163,8 +1068,8 @@ void LLGestureMgr::onLoadComplete(LLVFS *vfs, gAgent.sendReliableMessage(); } - callback_map_t::iterator i_cb = self.mCallbackMap.find(item_id); - + + auto i_cb = self.mCallbackMap.find(item_id); if(i_cb != self.mCallbackMap.end()) { i_cb->second(gesture); @@ -1180,11 +1085,8 @@ void LLGestureMgr::onLoadComplete(LLVFS *vfs, self.mActive.erase(item_id); delete gesture; - gesture = NULL; + gesture = nullptr; } - - delete [] buffer; - buffer = NULL; } else { @@ -1251,11 +1153,8 @@ bool LLGestureMgr::hasLoadingAssets(LLMultiGesture* gesture) { LLGestureMgr& self = LLGestureMgr::instance(); - for (std::vector::iterator steps_it = gesture->mSteps.begin(); - steps_it != gesture->mSteps.end(); - ++steps_it) + for (auto& step : gesture->mSteps) { - LLGestureStep* step = *steps_it; switch(step->getType()) { case STEP_ANIMATION: @@ -1304,28 +1203,22 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture) if (!gesture) return; // Stop any animations that this gesture is currently playing - std::set::const_iterator set_it; - for (set_it = gesture->mRequestedAnimIDs.begin(); set_it != gesture->mRequestedAnimIDs.end(); ++set_it) + for (const auto& anim_id : gesture->mRequestedAnimIDs) { - const LLUUID& anim_id = *set_it; gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP); } - for (set_it = gesture->mPlayingAnimIDs.begin(); set_it != gesture->mPlayingAnimIDs.end(); ++set_it) + gesture->mRequestedAnimIDs.clear(); + + for (const auto& anim_id : gesture->mPlayingAnimIDs) { - const LLUUID& anim_id = *set_it; if (gesture->mLocal) - gAgentAvatarp->stopMotion(anim_id, TRUE); + gAgentAvatarp->stopMotion(anim_id, true); else gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP); } + gesture->mPlayingAnimIDs.clear(); - std::vector::iterator it; - it = std::find(mPlaying.begin(), mPlaying.end(), gesture); - while (it != mPlaying.end()) - { - mPlaying.erase(it); - it = std::find(mPlaying.begin(), mPlaying.end(), gesture); - } + mPlaying.erase(std::remove(mPlaying.begin(), mPlaying.end(), gesture), mPlaying.end()); gesture->reset(); @@ -1335,7 +1228,7 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture) // callback might have deleted gesture, can't // rely on this pointer any more - gesture = NULL; + gesture = nullptr; } notifyObservers(); @@ -1344,8 +1237,8 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture) void LLGestureMgr::stopGesture(const LLUUID& item_id) { - const LLUUID& base_item_id = get_linked_uuid(item_id); - item_map_t::iterator it = mActive.find(base_item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); + auto it = mActive.find(base_item_id); if (it == mActive.end()) return; LLMultiGesture* gesture = (*it).second; @@ -1362,9 +1255,9 @@ void LLGestureMgr::addObserver(LLGestureManagerObserver* observer) void LLGestureMgr::removeObserver(LLGestureManagerObserver* observer) { - std::vector::iterator it; - it = std::find(mObservers.begin(), mObservers.end(), observer); - if (it != mObservers.end()) + const auto& end = mObservers.end(); + auto it = std::find(mObservers.begin(), end, observer); + if (it != end) { mObservers.erase(it); } @@ -1377,27 +1270,23 @@ void LLGestureMgr::notifyObservers() { LL_DEBUGS() << "LLGestureMgr::notifyObservers" << LL_ENDL; - for(std::vector::iterator iter = mObservers.begin(); - iter != mObservers.end(); - ++iter) + for(auto& observer : mObservers) { - LLGestureManagerObserver* observer = (*iter); observer->changed(); } } -BOOL LLGestureMgr::matchPrefix(const std::string& in_str, std::string* out_str) +bool LLGestureMgr::matchPrefix(const std::string& in_str, std::string* out_str) const { S32 in_len = in_str.length(); #ifdef MATCH_COMMON_CHARS - std::string rest_of_match = ""; - std::string buf = ""; + std::string rest_of_match; + std::string buf; #endif - item_map_t::iterator it; - for (it = mActive.begin(); it != mActive.end(); ++it) + for (const auto& pair : mActive) { - LLMultiGesture* gesture = (*it).second; + const LLMultiGesture* gesture = pair.second; if (gesture) { const std::string& trigger = gesture->getTrigger(); @@ -1406,7 +1295,7 @@ BOOL LLGestureMgr::matchPrefix(const std::string& in_str, std::string* out_str) if (!LLStringUtil::compareInsensitive(in_str, trigger)) { *out_str = trigger; - return TRUE; + return true; } #else if (in_len > (S32)trigger.length()) continue; // too short, bail out @@ -1419,37 +1308,36 @@ BOOL LLGestureMgr::matchPrefix(const std::string& in_str, std::string* out_str) { #ifndef MATCH_COMMON_CHARS *out_str = trigger; - return TRUE; + return true; #else - if (rest_of_match.compare("") == 0) + if (rest_of_match.empty()) { rest_of_match = trigger.substr(in_str.size()); } std::string cur_rest_of_match = trigger.substr(in_str.size()); - buf = ""; - U32 i=0; + buf.clear(); - while (ipush_back(it->first); + ids->push_back(pair.first); } } void LLGestureMgr::done() { bool notify = false; - for(item_map_t::iterator it = mActive.begin(); it != mActive.end(); ++it) + for(const auto& pair : mActive) { - if(it->second && it->second->mName.empty()) + if (pair.second && pair.second->mName.empty()) { - LLViewerInventoryItem* item = gInventory.getItem(it->first); + LLViewerInventoryItem* item = gInventory.getItem(pair.first); if(item) { - it->second->mName = item->getName(); + pair.second->mName = item->getName(); notify = true; } } @@ -1500,13 +1387,4 @@ void LLGestureMgr::done() } } -// static -const LLUUID& get_linked_uuid(const LLUUID &item_id) -{ - LLViewerInventoryItem* item = gInventory.getItem(item_id); - if (item && item->getIsLinkType()) - { - return item->getLinkedUUID(); - } - return item_id; -} + diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index 419ae77e78..ff28a164d0 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -27,8 +27,9 @@ #ifndef LL_LLGESTUREMGR_H #define LL_LLGESTUREMGR_H -#include #include +#include +#include #include #include "llassetstorage.h" // LLAssetType @@ -53,10 +54,10 @@ class LLGestureMgr : public LLSingleton, public LLInventoryFetchIt { public: - typedef boost::function gesture_loaded_callback_t; + typedef std::function gesture_loaded_callback_t; // Maps inventory item_id to gesture - typedef std::map item_map_t; - typedef std::map callback_map_t; + typedef boost::unordered_map item_map_t; + typedef boost::unordered_map callback_map_t; LLGestureMgr(); ~LLGestureMgr(); @@ -81,24 +82,24 @@ class LLGestureMgr : public LLSingleton, public LLInventoryFetchIt // Load gesture into in-memory active form. // Can be called even if the inventory item isn't loaded yet. - // inform_server TRUE will send message upstream to update database + // inform_server true will send message upstream to update database // user_gesture_active table, which isn't necessary on login. // deactivate_similar will cause other gestures with the same trigger phrase // or keybinding to be deactivated. - void activateGestureWithAsset(const LLUUID& item_id, const LLUUID& asset_id, BOOL inform_server, BOOL deactivate_similar); + void activateGestureWithAsset(const LLUUID& item_id, const LLUUID& asset_id, bool inform_server, bool deactivate_similar); // Takes gesture out of active list and deletes it. void deactivateGesture(const LLUUID& item_id); // Deactivates all gestures that match either this trigger phrase, // or this hot key. - void deactivateSimilarGestures(LLMultiGesture* gesture, const LLUUID& in_item_id); + void deactivateSimilarGestures(const LLMultiGesture* gesture, const LLUUID& in_item_id); - BOOL isGestureActive(const LLUUID& item_id); + bool isGestureActive(const LLUUID& item_id) const; - BOOL isGesturePlaying(const LLUUID& item_id); + bool isGesturePlaying(const LLUUID& item_id) const; - BOOL isGesturePlaying(LLMultiGesture* gesture); + bool isGesturePlaying(const LLMultiGesture* gesture) const; const item_map_t& getActiveGestures() const { return mActive; } // Force a gesture to be played, for example, if it is being @@ -115,19 +116,19 @@ class LLGestureMgr : public LLSingleton, public LLInventoryFetchIt * Note: * Manager will call cb after gesture will be loaded and will remove cb automatically. */ - void setGestureLoadedCallback(LLUUID inv_item_id, gesture_loaded_callback_t cb) + void setGestureLoadedCallback(const LLUUID& inv_item_id, gesture_loaded_callback_t cb) { mCallbackMap[inv_item_id] = cb; } // Trigger the first gesture that matches this key. // Returns TRUE if it finds a gesture bound to that key. - BOOL triggerGesture(KEY key, MASK mask); + bool triggerGesture(KEY key, MASK mask); // Trigger all gestures referenced as substrings in this string - BOOL triggerAndReviseString(const std::string &str, std::string *revised_string = NULL); + bool triggerAndReviseString(const std::string &str, std::string *revised_string = nullptr); // Does some gesture have this key bound? - BOOL isKeyBound(KEY key, MASK mask); + //bool isKeyBound(KEY key, MASK mask) const; S32 getPlayingCount() const; @@ -138,10 +139,10 @@ class LLGestureMgr : public LLSingleton, public LLInventoryFetchIt // Overriding so we can update active gesture names and notify observers void changed(U32 mask); - BOOL matchPrefix(const std::string& in_str, std::string* out_str); + bool matchPrefix(const std::string& in_str, std::string* out_str) const; // Copy item ids into the vector - void getItemIDs(uuid_vec_t* ids); + void getItemIDs(uuid_vec_t* ids) const; protected: // Handle the processing of a single gesture @@ -172,7 +173,7 @@ class LLGestureMgr : public LLSingleton, public LLInventoryFetchIt private: // Active gestures. - // NOTE: The gesture pointer CAN BE NULL. This means that + // NOTE: The gesture pointer CAN BE a nullptr. This means that // there is a gesture with that item_id, but the asset data // is still on its way down from the server. item_map_t mActive; @@ -183,9 +184,9 @@ class LLGestureMgr : public LLSingleton, public LLInventoryFetchIt std::vector mObservers; callback_map_t mCallbackMap; std::vector mPlaying; - BOOL mValid; + bool mValid; - std::set mLoadingAssets; + uuid_set_t mLoadingAssets; }; #endif diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp index a1d49b63c1..73bc6cd835 100644 --- a/indra/newview/llgiveinventory.cpp +++ b/indra/newview/llgiveinventory.cpp @@ -36,6 +36,7 @@ #include "llagentdata.h" #include "llagentui.h" #include "llagentwearables.h" +#include "llavataractions.h" #include "llfloaterchat.h" //for addChatHistory #include "llfloatertools.h" // for gFloaterTool #include "llhudeffecttrail.h" @@ -55,7 +56,7 @@ // MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES // or 18 * count < 1200 => count < 1200/18 => 66. I've cut it down a // bit from there to give some pad. -const S32 MAX_ITEMS = 42; +const size_t MAX_ITEMS = 50; class LLGiveable : public LLInventoryCollectFunctor { @@ -259,9 +260,9 @@ bool LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, items, LLInventoryModel::EXCLUDE_TRASH, giveable); - S32 count = cats.size(); + size_t count = cats.size(); bool complete = true; - for(S32 i = 0; i < count; ++i) + for(size_t i = 0; i < count; ++i) { if(!gInventory.isCategoryComplete(cats.at(i)->getUUID())) { @@ -331,7 +332,7 @@ void LLGiveInventory::logInventoryOffer(const LLUUID& to_agent, const LLUUID &im (!RlvUIEnabler::hasOpenProfile(to_agent)) ) { // Log to chat history if the user didn't drop on an IM session or a profile to avoid revealing the name of the recipient - std::string strMsgName = "inventory_item_offered"; LLSD args; LLAvatarName avName; + std::string strMsgName = "inventory_item_offered-im"; LLSD args; LLAvatarName avName; if (LLAvatarNameCache::get(to_agent, &avName)) { args["NAME"] = RlvStrings::getAnonym(avName); @@ -348,13 +349,9 @@ void LLGiveInventory::logInventoryOffer(const LLUUID& to_agent, const LLUUID &im // If this item was given by drag-and-drop on avatar while IM panel wasn't open, log this action to IM history. else { - std::string full_name; - if (gCacheName->getFullName(to_agent, full_name)) - { - LLChat chat(LLTrans::getString("inventory_item_offered_to") + " " + full_name); - chat.mSourceType = CHAT_SOURCE_SYSTEM; - LLFloaterChat::addChatHistory(chat); - } + LLChat chat(LLTrans::getString("inventory_item_offered_to") + ' ' + LLAvatarActions::getSLURL(to_agent)); + chat.mSourceType = CHAT_SOURCE_SYSTEM; + LLFloaterChat::addChatHistory(chat); } } @@ -475,8 +472,8 @@ bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, cons items, LLInventoryModel::EXCLUDE_TRASH, remove); - S32 count = items.size(); - for(S32 i = 0; i < count; ++i) + size_t count = items.size(); + for(size_t i = 0; i < count; ++i) { gInventory.deleteObject(items.at(i)->getUUID()); } @@ -529,8 +526,8 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, // MAX ITEMS is based on (sizeof(uuid)+2) * count must be < // MTUBYTES or 18 * count < 1200 => count < 1200/18 => // 66. I've cut it down a bit from there to give some pad. - S32 count = items.size() + cats.size(); - if(count > MAX_ITEMS) + size_t count = items.size() + cats.size(); + if (count > MAX_ITEMS) { LLNotificationsUtil::add("TooManyItems"); give_successful = false; @@ -546,7 +543,7 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, LLAgentUI::buildFullname(name); LLUUID transaction_id; transaction_id.generate(); - S32 bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1); + size_t bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1); U8* bucket = new U8[bucket_size]; U8* pos = bucket; U8 type = (U8)cat->getType(); @@ -554,7 +551,7 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, pos += sizeof(U8); memcpy(pos, &(cat->getUUID()), UUID_BYTES); /* Flawfinder: ignore */ pos += UUID_BYTES; - S32 i; + size_t i; count = cats.size(); for(i = 0; i < count; ++i) { diff --git a/indra/newview/llgivemoney.cpp b/indra/newview/llgivemoney.cpp index bd9243827a..31f1ac598f 100644 --- a/indra/newview/llgivemoney.cpp +++ b/indra/newview/llgivemoney.cpp @@ -54,7 +54,6 @@ #include "hippogridmanager.h" -#include ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- @@ -76,16 +75,13 @@ LLFloaterPay::LLFloaterPay(const std::string& name, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES), mCallback(callback), - mObjectNameText(NULL), mTargetUUID(uuid), mTargetIsObject(target_is_object), mTargetIsGroup(FALSE), - mDefaultValue(0) + mDefaultValue(0), + mQuickPayButton({ {nullptr,nullptr,nullptr,nullptr} }), + mQuickPayInfo({ {PAY_BUTTON_DEFAULT_0, PAY_BUTTON_DEFAULT_1, PAY_BUTTON_DEFAULT_2, PAY_BUTTON_DEFAULT_3} }) { - mQuickPayInfo[0] = PAY_BUTTON_DEFAULT_0; - mQuickPayInfo[1] = PAY_BUTTON_DEFAULT_1; - mQuickPayInfo[2] = PAY_BUTTON_DEFAULT_2; - mQuickPayInfo[3] = PAY_BUTTON_DEFAULT_3; BOOST_STATIC_ASSERT(MAX_PAY_BUTTONS == 4); if (target_is_object) @@ -100,7 +96,7 @@ LLFloaterPay::LLFloaterPay(const std::string& name, for(U32 i = 0; i < MAX_PAY_BUTTONS; ++i) { - mQuickPayButton[i] = getChild("fastpay " + boost::lexical_cast(mQuickPayInfo[i])); + mQuickPayButton[i] = getChild("fastpay " + fmt::to_string(mQuickPayInfo[i])); mQuickPayButton[i]->setClickedCallback(boost::bind(&LLFloaterPay::onGive,this,boost::ref(mQuickPayInfo[i]))); mQuickPayButton[i]->setVisible(FALSE); mQuickPayButton[i]->setLabelArg("[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); diff --git a/indra/newview/llgivemoney.h b/indra/newview/llgivemoney.h index 540d0dade0..26abf34500 100644 --- a/indra/newview/llgivemoney.h +++ b/indra/newview/llgivemoney.h @@ -81,14 +81,12 @@ class LLFloaterPay : public LLFloater protected: money_callback mCallback; - LLTextBox* mObjectNameText; LLUUID mTargetUUID; BOOL mTargetIsObject; BOOL mTargetIsGroup; - BOOL mHaveName; - LLButton* mQuickPayButton[MAX_PAY_BUTTONS]; - S32 mQuickPayInfo[MAX_PAY_BUTTONS]; + std::array mQuickPayButton; + std::array mQuickPayInfo; S32 mDefaultValue; LLSafeHandle mObjectSelection; diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 26396ec27a..6dca4a376e 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -386,25 +386,16 @@ void LLViewerParcelMgr::renderRect(const LLVector3d &west_south_bottom_global, gGL.end(); gGL.color4f(1.f, 1.f, 0.f, 0.2f); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex3f(west, north, nw_bottom); gGL.vertex3f(west, north, nw_top); + gGL.vertex3f(west, north, nw_bottom); gGL.vertex3f(east, north, ne_top); gGL.vertex3f(east, north, ne_bottom); - - gGL.vertex3f(east, north, ne_bottom); - gGL.vertex3f(east, north, ne_top); gGL.vertex3f(east, south, se_top); gGL.vertex3f(east, south, se_bottom); - - gGL.vertex3f(east, south, se_bottom); - gGL.vertex3f(east, south, se_top); gGL.vertex3f(west, south, sw_top); gGL.vertex3f(west, south, sw_bottom); - - gGL.vertex3f(west, south, sw_bottom); - gGL.vertex3f(west, south, sw_top); gGL.vertex3f(west, north, nw_top); gGL.vertex3f(west, north, nw_bottom); @@ -524,8 +515,8 @@ void LLViewerParcelMgr::renderOneSegment(F32 x1, F32 y1, F32 x2, F32 y2, F32 hei if (clamped_y2 > BORDER) clamped_y2 = BORDER; F32 z; - F32 z1 = regionp->getLand().resolveHeightRegion( LLVector3( clamped_x1, clamped_y1, 0.f ) );; - F32 z2 = regionp->getLand().resolveHeightRegion( LLVector3( clamped_x2, clamped_y2, 0.f ) );; + F32 z1 = regionp->getLand().resolveHeightRegion( LLVector3( clamped_x1, clamped_y1, 0.f ) ); + F32 z2 = regionp->getLand().resolveHeightRegion( LLVector3( clamped_x2, clamped_y2, 0.f ) ); // Convert x1 and x2 from region-local to agent coords. LLVector3 origin = regionp->getOriginAgent(); @@ -541,10 +532,11 @@ void LLViewerParcelMgr::renderOneSegment(F32 x1, F32 y1, F32 x2, F32 y2, F32 hei gGL.vertex3f(x1, y1, z1); - gGL.vertex3f(x2, y2, z2); - - z = z2+height; + z = z2 + height; + gGL.vertex3f(x2, y2, z); gGL.vertex3f(x2, y2, z); + gGL.vertex3f(x1, y1, z1); + gGL.vertex3f(x2, y2, z2); } else { @@ -581,11 +573,14 @@ void LLViewerParcelMgr::renderOneSegment(F32 x1, F32 y1, F32 x2, F32 y2, F32 hei // top edge stairsteps z = llmax(z2+height, z1+height); + gGL.texCoord2f(tex_coord1*0.5f + 0.5f, z*0.5f); + gGL.vertex3f(x1, y1, z); + gGL.texCoord2f(tex_coord1*0.5f + 0.5f, z*0.5f); + gGL.vertex3f(x1, y1, z); gGL.texCoord2f(tex_coord2*0.5f+0.5f, z*0.5f); gGL.vertex3f(x2, y2, z); - - gGL.texCoord2f(tex_coord1*0.5f+0.5f, z*0.5f); - gGL.vertex3f(x1, y1, z); + gGL.texCoord2f(tex_coord1*0.5f + 0.5f, z1*0.5f); + gGL.vertex3f(x1, y1, z1); } } @@ -625,7 +620,7 @@ void LLViewerParcelMgr::renderHighlightSegments(const U8* segments, LLViewerRegi if (!has_segments) { has_segments = true; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); } renderOneSegment(x1, y1, x2, y2, PARCEL_POST_HEIGHT, SOUTH_MASK, regionp); } @@ -641,7 +636,7 @@ void LLViewerParcelMgr::renderHighlightSegments(const U8* segments, LLViewerRegi if (!has_segments) { has_segments = true; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); } renderOneSegment(x1, y1, x2, y2, PARCEL_POST_HEIGHT, WEST_MASK, regionp); } @@ -675,7 +670,7 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV LLGLSUIDefault gls_ui; LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - LLGLDisable cull(GL_CULL_FACE); + LLGLDisable cull; if (mCollisionBanned == BA_BANNED || regionp->getRegionFlag(REGION_FLAGS_BLOCK_FLYOVER)) @@ -697,7 +692,7 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV gGL.getTexUnit(0)->bind(mBlockedImage); } - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); for (y = 0; y < STRIDE; y++) { @@ -851,8 +846,7 @@ void LLViewerObjectList::renderObjectBeacons() S32 line_width = debug_beacon.mLineWidth; if (line_width != last_line_width) { - gGL.flush(); - glLineWidth( (F32)line_width ); + gGL.setLineWidth(line_width); last_line_width = line_width; } @@ -887,8 +881,7 @@ void LLViewerObjectList::renderObjectBeacons() S32 line_width = debug_beacon.mLineWidth; if (line_width != last_line_width) { - gGL.flush(); - glLineWidth( (F32)line_width ); + gGL.setLineWidth(line_width); last_line_width = line_width; } @@ -907,13 +900,12 @@ void LLViewerObjectList::renderObjectBeacons() gGL.end(); } - gGL.flush(); - glLineWidth(1.f); + gGL.setLineWidth(1.f); for (std::vector::iterator iter = mDebugBeacons.begin(); iter != mDebugBeacons.end(); ++iter) { LLDebugBeacon &debug_beacon = *iter; - if (debug_beacon.mString == "") + if (debug_beacon.mString.empty()) { continue; } diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index d97cd8d354..91141253c5 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -400,6 +400,13 @@ void LLGroupActions::show(const LLUUID& group_id) openGroupProfile(group_id); } +// static +void LLGroupActions::showProfiles(const uuid_vec_t& ids) +{ + for (const auto& id : ids) + show(id); +} + // static void LLGroupActions::showTab(const LLUUID& group_id, const std::string& tab_name) { @@ -601,3 +608,8 @@ LLFloaterGroupInfo* LLGroupActions::openGroupProfile(const LLUUID& group_id) return fgi; } +std::string LLGroupActions::getSLURL(const LLUUID& id) +{ + return llformat("secondlife:///app/group/%s/about", id.asString().c_str()); +} + diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h index 0cce7460ba..dc4ff4fe5d 100644 --- a/indra/newview/llgroupactions.h +++ b/indra/newview/llgroupactions.h @@ -58,6 +58,7 @@ class LLGroupActions * Show group information panel. */ static void show(const LLUUID& group_id); + static void showProfiles(const uuid_vec_t& group_ids); /** * Show group information panel, with specific tab open. @@ -121,6 +122,11 @@ class LLGroupActions */ static bool isAvatarMemberOfGroup(const LLUUID& group_id, const LLUUID& avatar_id); + /** + * @return slurl string from group ID + */ + static std::string getSLURL(const LLUUID& id); + private: static bool onJoinGroup(const LLSD& notification, const LLSD& response); static bool onLeaveGroup(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 028060358c..1804c558a3 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -38,12 +38,12 @@ #include "llappviewer.h" //For gFrameCount #include "llagent.h" +#include "llavatarnamecache.h" #include "llui.h" #include "message.h" #include "roles_constants.h" #include "lltransactiontypes.h" #include "llstatusbar.h" -#include "lleconomy.h" #include "llviewerregion.h" #include "llviewerwindow.h" #include "llfloaterdirectory.h" @@ -79,6 +79,7 @@ LLRoleActionSet::~LLRoleActionSet() { delete mActionSetData; std::for_each(mActions.begin(), mActions.end(), DeletePointer()); + mActions.clear(); } // @@ -158,7 +159,7 @@ LLGroupRoleData::~LLGroupRoleData() { } -S32 LLGroupRoleData::getMembersInRole(uuid_vec_t members, +S32 LLGroupRoleData::getMembersInRole(uuid_vec_t& members, BOOL needs_sort) { if (mRoleID.isNull()) @@ -237,7 +238,8 @@ LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) : mRoleMemberDataComplete(false), mGroupPropertiesDataComplete(false), mPendingRoleMemberRequest(false), - mAccessTime(0.0f) + mAccessTime(0.0f), + mPendingBanRequest(false) { mMemberVersion.generate(); } @@ -844,8 +846,69 @@ void LLGroupMgrGroupData::removeBanEntry(const LLUUID& ban_id) mBanList.erase(ban_id); } +void LLGroupMgrGroupData::banMemberById(const LLUUID& participant_uuid) +{ + if (!mMemberDataComplete || + !mRoleDataComplete || + !(mRoleMemberDataComplete && mMembers.size())) + { + LL_WARNS() << "No Role-Member data yet, setting ban request to pending." << LL_ENDL; + mPendingBanRequest = true; + mPendingBanMemberID = participant_uuid; + + if (!mMemberDataComplete) + { + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mID); + } + + if (!mRoleDataComplete) + { + LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mID); + } + + return; + } + + LLGroupMgrGroupData::member_list_t::iterator mi = mMembers.find((participant_uuid)); + if (mi == mMembers.end()) + { + if (!mPendingBanRequest) + { + mPendingBanRequest = true; + mPendingBanMemberID = participant_uuid; + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mID); // member isn't in members list, request reloading + } + else + { + mPendingBanRequest = false; + } + return; + } + mPendingBanRequest = false; + + LLGroupMemberData* member_data = (*mi).second; + if (member_data && member_data->isInRole(mOwnerRole)) + { + return; // can't ban group owner + } + + uuid_vec_t ids; + ids.push_back(participant_uuid); + + LLGroupBanData ban_data; + createBanEntry(participant_uuid, ban_data); + LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mID, LLGroupMgr::BAN_CREATE, ids); + LLGroupMgr::getInstance()->sendGroupMemberEjects(mID, ids); + LLGroupMgr::getInstance()->sendGroupMembersRequest(mID); + LLSD args; + std::string name; + LLAvatarNameCache::getNSName(participant_uuid, name); + args["AVATAR_NAME"] = name; + args["GROUP_NAME"] = mName; + LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args)); +} // // LLGroupMgr @@ -1352,6 +1415,11 @@ void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data) group_datap->mChanged = TRUE; LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_MEMBER_DATA); + + if (group_datap->mPendingBanRequest) + { + group_datap->banMemberById(group_datap->mPendingBanMemberID); + } } // static @@ -2014,7 +2082,7 @@ void GroupBanDataResponder::httpSuccess() void LLGroupMgr::sendGroupBanRequest( EBanRequestType request_type, const LLUUID& group_id, U32 ban_action, /* = BAN_NO_ACTION */ - const std::vector ban_list) /* = std::vector() */ + const uuid_vec_t& ban_list) /* = uuid_vec_t() */ { LLViewerRegion* currentRegion = gAgent.getRegion(); if (!currentRegion) @@ -2082,6 +2150,7 @@ void LLGroupMgr::processGroupBanRequest(const LLSD& content) if (!gdatap) return; + gdatap->clearBanList(); LLSD::map_const_iterator i = content["ban_list"].beginMap(); LLSD::map_const_iterator iEnd = content["ban_list"].endMap(); for(;i != iEnd; ++i) @@ -2195,11 +2264,6 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) return; } - // If we have no members, there's no reason to do anything else - S32 num_members = content["member_count"]; - if (num_members < 1) - return; - LLUUID group_id = content["group_id"].asUUID(); LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id); @@ -2209,6 +2273,18 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) return; } + // If we have no members, there's no reason to do anything else + S32 num_members = content["member_count"]; + if (num_members < 1) + { + LL_INFOS("GrpMgr") << "Received empty group members list for group id: " << group_id.asString() << LL_ENDL; + // Set mMemberDataComplete for correct handling of empty responses. See MAINT-5237 + group_datap->mMemberDataComplete = true; + group_datap->mChanged = TRUE; + LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA); + return; + } + group_datap->mMemberCount = num_members; LLSD member_list = content["members"]; diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index 20c637112d..73a8546249 100644 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -148,8 +148,8 @@ friend class LLGroupMgrGroupData; const LLUUID& getID() const { return mRoleID; } const uuid_vec_t& getRoleMembers() const { return mMemberIDs; } - S32 getMembersInRole(uuid_vec_t members, BOOL needs_sort = TRUE); - S32 getTotalMembersInRole() { return mMemberIDs.size(); } + S32 getMembersInRole(uuid_vec_t& members, BOOL needs_sort = TRUE); + S32 getTotalMembersInRole() { return mMemberCount ? mMemberCount : mMemberIDs.size(); } //FIXME: Returns 0 for Everyone role when Member list isn't yet loaded, see MAINT-5225 LLRoleData getRoleData() const { return mRoleData; } void setRoleData(LLRoleData data) { mRoleData = data; } @@ -269,7 +269,7 @@ friend class LLGroupMgr; void createBanEntry(const LLUUID& ban_id, const LLGroupBanData& ban_data = LLGroupBanData()); void removeBanEntry(const LLUUID& ban_id); - + void banMemberById(const LLUUID& participant_uuid); public: typedef std::map member_list_t; @@ -301,6 +301,9 @@ friend class LLGroupMgr; S32 mMemberCount; S32 mRoleCount; + bool mPendingBanRequest; + LLUUID mPendingBanMemberID; + protected: void sendRoleChanges(); void cancelRoleChanges(); @@ -398,7 +401,7 @@ class LLGroupMgr : public LLSingleton static void sendGroupBanRequest(EBanRequestType request_type, const LLUUID& group_id, U32 ban_action = BAN_NO_ACTION, - const uuid_vec_t ban_list = uuid_vec_t()); + const uuid_vec_t& ban_list = uuid_vec_t()); static void processGroupBanRequest(const LLSD& content); diff --git a/indra/newview/llgroupnotify.cpp b/indra/newview/llgroupnotify.cpp index b2b6788781..c1af61a3c3 100644 --- a/indra/newview/llgroupnotify.cpp +++ b/indra/newview/llgroupnotify.cpp @@ -36,6 +36,7 @@ #include "llfocusmgr.h" +#include "llavataractions.h" #include "llbutton.h" #include "lliconctrl.h" #include "llfloaterchat.h" // for add_chat_history() @@ -94,15 +95,15 @@ LLGroupNotifyBox::LLGroupNotifyBox(const std::string& subject, mHasInventory(has_inventory), mInventoryOffer(NULL) { - const S32 VPAD = 2; - const S32 TOP = getRect().getHeight() - 32; // Get past the top menu bar - const S32 BOTTOM_PAD = VPAD * 2; - const S32 BTN_TOP = BOTTOM_PAD + BTN_HEIGHT + VPAD; - const S32 RIGHT = getRect().getWidth() - HPAD - HPAD; - const S32 LINE_HEIGHT = 16; + constexpr S32 PAD = 2; + const S32 TOP = getRect().getHeight() - 28; // Get past the top menu bar + const S32 BOTTOM_PAD = PAD * 2; + const S32 BTN_TOP = BOTTOM_PAD + BTN_HEIGHT + PAD; + const S32 RIGHT = getRect().getWidth() - HPAD; + constexpr S32 LINE_HEIGHT = 16; - const S32 LABEL_WIDTH = 64; - const S32 ICON_WIDTH = 64; + constexpr S32 LABEL_WIDTH = 64; + constexpr S32 ICON_WIDTH = 64; time_t timestamp = (time_t)time_stamp.secondsSinceEpoch(); if (!timestamp) time(×tamp); @@ -122,71 +123,75 @@ LLGroupNotifyBox::LLGroupNotifyBox(const std::string& subject, setBackgroundColor( gColors.getColor("GroupNotifyBoxColor") ); S32 y = TOP; - S32 x = HPAD + HPAD; + S32 x = ICON_WIDTH + HPAD + PAD; + static const auto text_color = gColors.getColor("GroupNotifyTextColor"); class NoticeText : public LLTextBox { public: - NoticeText(const std::string& name, const LLRect& rect, const std::string& text = LLStringUtil::null, const LLFontGL* font = NULL) + NoticeText(const std::string& name, const LLRect& rect, const std::string& text = LLStringUtil::null, const LLFontGL* font = NULL) : LLTextBox(name, rect, text, font) { setHAlign(LLFontGL::RIGHT); setFontShadow(LLFontGL::DROP_SHADOW_SOFT); setBorderVisible(FALSE); - setColor( gColors.getColor("GroupNotifyTextColor") ); - setBackgroundColor( gColors.getColor("GroupNotifyBoxColor") ); + setColor(text_color); + setBackgroundColor(LLColor4::transparent); } }; - // Title - addChild(new NoticeText(std::string("title"),LLRect(x,y,RIGHT - HPAD,y - LINE_HEIGHT),LLTrans::getString("GroupNotifyGroupNotice"),LLFontGL::getFontSansSerifHuge())); - - y -= llfloor(1.5f*LINE_HEIGHT); + static LLStyleSP headerstyle = nullptr; + if (!headerstyle) + { + headerstyle = new LLStyle(true, text_color, LLStringUtil::null); + headerstyle->mBold = true; + } + const auto bottom = y - ICON_WIDTH; - x += HPAD + HPAD + ICON_WIDTH; + auto links = new LLTextEditor(std::string("group"), LLRect(x, y + 5, RIGHT, bottom), S32_MAX, LLStringUtil::null, nullptr, false, true); // Top adjustment to line up with icon + links->setBorderVisible(FALSE); + static const auto header_bg_color = gColors.getColor("GroupNotifyHeaderBGColor"); + if (header_bg_color[VALPHA]) links->setReadOnlyFgColor(text_color); + links->setReadOnlyBgColor(header_bg_color); + links->setEnabled(false); + links->setTakesNonScrollClicks(TRUE); + links->setHideScrollbarForShortDocs(TRUE); + links->setWordWrap(TRUE); - std::stringstream from; - from << LLTrans::getString("GroupNotifySentBy") << " " + from_name << LLTrans::getString(",") + " " << group_name; + links->appendText(subject, false, false, headerstyle, false); // This is from a user, do not force replace. + links->appendText(time_buf, false, true, nullptr, true); + links->appendText(LLTrans::getString("GroupNotifyBy", LLSD().with("NAME", from_name).with("GROUP", group_name)), false, true, nullptr, true); + addChild(links); - addChild(new NoticeText(std::string("group"),LLRect(x,y,RIGHT - HPAD,y - LINE_HEIGHT),from.str(),LLFontGL::getFontSansSerif())); - - y -= (LINE_HEIGHT + VPAD); - x = HPAD + HPAD; + x = HPAD; - // TODO: change this to be the group icon. LLIconCtrl* icon = new LLIconCtrl(std::string("icon"), - LLRect(x, y, x+ICON_WIDTH, y-ICON_WIDTH), - group_insignia.isNull() ? "notify_box_icon.tga" : group_insignia.asString()); + LLRect(x, y, x+ICON_WIDTH, bottom), + group_insignia.isNull() ? "icon_groupnotice.tga" : group_insignia.asString()); icon->setMouseOpaque(FALSE); addChild(icon); - x += HPAD + HPAD + ICON_WIDTH; + y = bottom - PAD*2; + // If we have inventory with this message, leave room for the name. - S32 box_bottom = BTN_TOP + (mHasInventory ? (LINE_HEIGHT + 2*VPAD) : 0); + S32 box_bottom = BTN_TOP + (mHasInventory ? (LINE_HEIGHT + 2*PAD) : 0); LLTextEditor* text = new LLViewerTextEditor(std::string("box"), LLRect(x, y, RIGHT, box_bottom), DB_GROUP_NOTICE_MSG_STR_LEN, LLStringUtil::null, LLFontGL::getFontSansSerif(), - FALSE); - - static const LLStyleSP headerstyle(new LLStyle(true,LLColor4::black,"SansSerifBig")); - static const LLStyleSP datestyle(new LLStyle(true,LLColor4::black,"serif")); + FALSE, + true); + text->setBorderVisible(false); - text->appendStyledText(subject + "\n",false,false,headerstyle); + static const LLStyleSP msgstyle(new LLStyle(true, LLColor4::grey4, LLStringUtil::null)); - text->appendStyledText(time_buf,false,false,datestyle); - // Sadly, our LLTextEditor can't handle both styled and unstyled text - // at the same time. Hence this space must be styled. JC - text->appendColoredText(std::string(" "),false,false,LLColor4::grey4); - text->setParseHTML(TRUE); - text->appendColoredText(std::string("\n\n") + message,false,false,LLColor4::grey4); + text->appendText(message, false, false, msgstyle, false); LLColor4 semi_transparent(1.0f,1.0f,1.0f,0.8f); text->setCursor(0,0); - text->setEnabled(FALSE); text->setWordWrap(TRUE); //text->setTabStop(FALSE); // was interfering with copy-and-paste text->setTabsToNextField(TRUE); @@ -199,11 +204,11 @@ LLGroupNotifyBox::LLGroupNotifyBox(const std::string& subject, addChild(text); - y = box_bottom - VPAD; + y = box_bottom - PAD; if (mHasInventory) { - addChild(new NoticeText(std::string("subjecttitle"),LLRect(x,y,x + LABEL_WIDTH,y - LINE_HEIGHT),LLTrans::getString("GroupNotifyAttached"),LLFontGL::getFontSansSerif())); + addChild(new NoticeText(std::string("subjecttitle"), LLRect(x,y,x + LABEL_WIDTH,y - LINE_HEIGHT), LLTrans::getString("GroupNotifyAttached") + ' ', LLFontGL::getFontSansSerif())); LLUIImagePtr item_icon = LLInventoryIcon::getIcon(mInventoryOffer->mType, LLInventoryType::IT_TEXTURE, @@ -243,7 +248,7 @@ LLGroupNotifyBox::LLGroupNotifyBox(const std::string& subject, S32 btn_width = 80; S32 wide_btn_width = 136; LLRect btn_rect; - x = 3 * HPAD; + x = 2 * HPAD; btn_rect.setOriginAndSize(x, BOTTOM_PAD, @@ -294,7 +299,8 @@ LLGroupNotifyBox::~LLGroupNotifyBox() // virtual BOOL LLGroupNotifyBox::handleRightMouseDown(S32 x, S32 y, MASK mask) { - moveToBack(); + if (!LLPanel::handleRightMouseDown(x, y, mask)) + moveToBack(); return TRUE; } @@ -366,10 +372,10 @@ bool LLGroupNotifyBox::onNewNotification(const LLSD& notify) gNotifyBoxView->addChild(new LLGroupNotifyBox(payload["subject"].asString(), payload["message"].asString(), - payload["sender_name"].asString(), + payload.has("sender_id") ? LLAvatarActions::getSLURL(payload["sender_id"]) : payload["sender_name"].asString(), payload["group_id"].asUUID(), group_data.mInsigniaID, - group_data.mName, + LLGroupActions::getSLURL(payload["group_id"].asUUID()), notification->getDate(), payload["inventory_offer"].isDefined(), payload["inventory_name"].asString(), diff --git a/indra/newview/llgroupnotify.h b/indra/newview/llgroupnotify.h index ac7e5abec1..bf741aa342 100644 --- a/indra/newview/llgroupnotify.h +++ b/indra/newview/llgroupnotify.h @@ -43,7 +43,7 @@ class LLButton; // NotifyBox - for notifications that require a response from the // user. Replaces LLMessageBox. -class LLGroupNotifyBox +class LLGroupNotifyBox final : public LLPanel, public LLInitClass { @@ -70,10 +70,10 @@ class LLGroupNotifyBox /*virtual*/ ~LLGroupNotifyBox(); - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; // Animate as sliding onto the screen. - /*virtual*/ void draw(); + /*virtual*/ void draw() override; void moveToBack(); diff --git a/indra/newview/llhoverview.cpp b/indra/newview/llhoverview.cpp index b6821d601c..925f7a1a4c 100644 --- a/indra/newview/llhoverview.cpp +++ b/indra/newview/llhoverview.cpp @@ -66,6 +66,7 @@ #include "llviewerparcelmgr.h" #include "llviewerregion.h" #include "llviewerwindow.h" +#include "llvoavatarself.h" #include "llglheaders.h" #include "llviewertexturelist.h" //#include "lltoolobjpicker.h" @@ -271,7 +272,7 @@ void LLHoverView::updateText() line.clear(); if (hit_object->isAvatar()) { - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) + if (gAgentAvatarp != hit_object && gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) return; // No tag, no tip. LLNameValue* title = hit_object->getNVPair("Title"); LLNameValue* firstname = hit_object->getNVPair("FirstName"); @@ -306,6 +307,8 @@ void LLHoverView::updateText() line.append(LLTrans::getString("TooltipPerson")); } mText.push_back(line); + + mText.push_back(LLTrans::getString("Complexity", LLSD().with("NUM", static_cast(hit_object->asAvatar()->getVisualComplexity())))); } else { @@ -542,11 +545,16 @@ void LLHoverView::updateText() line.append(LLTrans::getString("TooltipForSaleMsg", args)); } mText.push_back(line); + + auto objects = LLSelectMgr::getInstance()->getHoverObjects(); + line.clear(); - S32 prim_count = LLSelectMgr::getInstance()->getHoverObjects()->getObjectCount(); + S32 prim_count = objects->getObjectCount(); line.append(llformat("Prims: %d", prim_count)); mText.push_back(line); + mText.push_back(llformat("LI: %.2f", objects->getSelectedLinksetCost())); + line.clear(); line.append("Position: "); @@ -803,8 +811,8 @@ void LLHoverView::draw() return; } - LLUIImagePtr box_imagep = LLUI::getUIImage("rounded_square.tga"); - LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga"); + LLUIImagePtr box_imagep = LLUI::getUIImage("Rounded_Square"); + LLUIImagePtr shadow_imagep = LLUI::getUIImage("Rounded_Square_Soft"); const LLFontGL* fontp = LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF_SMALL); diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp index 29d2ca87aa..0c529f41b8 100644 --- a/indra/newview/llhudeffectlookat.cpp +++ b/indra/newview/llhudeffectlookat.cpp @@ -572,7 +572,7 @@ void LLHUDEffectLookAt::render() offset.normalize(); LLVector3 shadow_offset = offset * 0.49f; offset *= 0.5f; - LLGLEnable gl_blend(GL_BLEND); + LLGLEnable gl_blend; const LLFontGL* fontp = LLFontGL::getFontSansSerif(); gGL.pushMatrix(); diff --git a/indra/newview/llhudeffectpointat.cpp b/indra/newview/llhudeffectpointat.cpp index 5cbbbb577d..90546e5b94 100644 --- a/indra/newview/llhudeffectpointat.cpp +++ b/indra/newview/llhudeffectpointat.cpp @@ -441,7 +441,7 @@ bool LLHUDEffectPointAt::calcTargetPosition() mTargetPos -= mSourceObject->getRenderPosition(); - if (!llfinite(mTargetPos.lengthSquared())) + if (!std::isfinite(mTargetPos.lengthSquared())) { return false; } diff --git a/indra/newview/llhudeffecttrail.h b/indra/newview/llhudeffecttrail.h index 033fbeb06d..15daa80db9 100644 --- a/indra/newview/llhudeffecttrail.h +++ b/indra/newview/llhudeffecttrail.h @@ -42,7 +42,7 @@ class LLViewerObject; -const U32 NUM_TRAIL_POINTS = 40; +constexpr U32 NUM_TRAIL_POINTS = 40; class LLHUDEffectSpiral : public LLHUDEffect diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp index b11cbaf440..574084991a 100644 --- a/indra/newview/llhudicon.cpp +++ b/indra/newview/llhudicon.cpp @@ -94,7 +94,7 @@ void LLHUDIcon::renderIcon(BOOL for_select) if (mHidden) return; - if (mSourceObject.isNull() || mImagep.isNull()) + if (mSourceObject.isNull() || mImagep.isNull() || mSourceObject->mDrawable.isNull()) { markDead(); return; @@ -169,16 +169,16 @@ void LLHUDIcon::renderIcon(BOOL for_select) gGL.getTexUnit(0)->bind(mImagep); } - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { gGL.texCoord2f(0.f, 1.f); gGL.vertex3fv(upper_left.mV); gGL.texCoord2f(0.f, 0.f); gGL.vertex3fv(lower_left.mV); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex3fv(lower_right.mV); gGL.texCoord2f(1.f, 1.f); gGL.vertex3fv(upper_right.mV); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex3fv(lower_right.mV); } gGL.end(); } diff --git a/indra/newview/llhudmanager.cpp b/indra/newview/llhudmanager.cpp index 8ffb1a9be9..c5e21e9b1b 100644 --- a/indra/newview/llhudmanager.cpp +++ b/indra/newview/llhudmanager.cpp @@ -61,11 +61,11 @@ LLHUDManager::~LLHUDManager() { } -static LLFastTimer::DeclareTimer FTM_HUD_EFFECTS("Hud Effects"); +static LLTrace::BlockTimerStatHandle FTM_HUD_EFFECTS("Hud Effects"); void LLHUDManager::updateEffects() { - LLFastTimer ftm(FTM_HUD_EFFECTS); + LL_RECORD_BLOCK_TIME(FTM_HUD_EFFECTS); U32 i; for (i = 0; i < mHUDEffects.size(); i++) { diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index d870a2b7f5..3d712439ae 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -112,7 +112,7 @@ LLHUDNameTag::LLHUDNameTag(const U8 type) { LLPointer ptr(this); sTextObjects.insert(ptr); - mBubbleImage = LLUI::getUIImage("Rounded_Rect.png"); + mBubbleImage = LLUI::getUIImage("Rounded_Rect"); } LLHUDNameTag::~LLHUDNameTag() @@ -281,8 +281,8 @@ void LLHUDNameTag::renderText(BOOL for_select) gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); } - LLGLState gls_blend(GL_BLEND, for_select ? FALSE : TRUE); - LLGLState gls_alpha(GL_ALPHA_TEST, for_select ? FALSE : TRUE); + LLGLState gls_blend(for_select ? FALSE : TRUE); + LLGLState gls_alpha(for_select ? FALSE : TRUE); gGL.setSceneBlendType(LLRender::BT_ALPHA); //Workaround avoiding inheriting stale blendstate from... something. LLColor4 shadow_color(0.f, 0.f, 0.f, 1.f); @@ -304,29 +304,14 @@ void LLHUDNameTag::renderText(BOOL for_select) mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f)); + LLUIImagePtr imagep = mBubbleImage; + // *TODO: make this a per-text setting static const LLCachedControl background_chat_color("BackgroundChatColor", LLColor4(0,0,0,1.f)); static const LLCachedControl chat_bubble_opacity("ChatBubbleOpacity", .5); LLColor4 bg_color = background_chat_color; bg_color.setAlpha(chat_bubble_opacity.get() * alpha_factor); - // maybe a no-op? - //const S32 border_height = 16; - //const S32 border_width = 16; - const S32 border_height = 8; - const S32 border_width = 8; - - // *TODO move this into helper function - F32 border_scale = 1.f; - - if (border_height * 2 > mHeight) - { - border_scale = (F32)mHeight / ((F32)border_height * 2.f); - } - if (border_width * 2 > mWidth) - { - border_scale = llmin(border_scale, (F32)mWidth / ((F32)border_width * 2.f)); - } // scale screen size of borders down //RN: for now, text on hud objects is never occluded @@ -336,34 +321,42 @@ void LLHUDNameTag::renderText(BOOL for_select) LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec); - LLVector2 border_scale_vec((F32)border_width / (F32)mBubbleImage->getTextureWidth(), (F32)border_height / (F32)mBubbleImage->getTextureHeight()); LLVector3 width_vec = mWidth * x_pixel_vec; LLVector3 height_vec = mHeight * y_pixel_vec; - LLVector3 scaled_border_width = (F32)llfloor(border_scale * (F32)border_width) * x_pixel_vec; - LLVector3 scaled_border_height = (F32)llfloor(border_scale * (F32)border_height) * y_pixel_vec; mRadius = (width_vec + height_vec).magVec() * 0.5f; LLCoordGL screen_pos; LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE); - LLVector2 screen_offset; -// if (!mUseBubble) -// { -// screen_offset = mPositionOffset; -// } -// else -// { - screen_offset = updateScreenPos(mPositionOffset); -// } + LLVector2 screen_offset = updateScreenPos(mPositionOffset); LLVector3 render_position = mPositionAgent + (x_pixel_vec * screen_offset.mV[VX]) + (y_pixel_vec * screen_offset.mV[VY]); -// if (mUseBubble) + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + LLRect screen_rect; + screen_rect.setCenterAndSize(0, static_cast(lltrunc(-mHeight / 2 + mOffsetY)), static_cast(lltrunc(mWidth)), static_cast(lltrunc(mHeight))); + imagep->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); + if (mLabelSegments.size()) + { + LLUIImagePtr rect_top_image = LLUI::getUIImage("Rounded_Rect_Top"); + LLRect label_top_rect = screen_rect; + 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] = chat_bubble_opacity * alpha_factor; + + rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); + } + + BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f; + BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f); + + // draw line segments pointing to parent object + if (!mOffscreen && (outside_width || outside_height)) { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLUI::pushMatrix(); { LLVector3 bg_pos = render_position @@ -371,46 +364,9 @@ void LLHUDNameTag::renderText(BOOL for_select) - (width_vec / 2.f) - (height_vec); LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - - if (for_select) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - S32 name = mSourceObject->mGLName; - LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); - gGL.color4ubv(coloru.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - LLUI::popMatrix(); - return; - } - else - { - gGL.getTexUnit(0)->bind(mBubbleImage->getImage()); - - gGL.color4fv(bg_color.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - - if ( mLabelSegments.size()) - { - LLUI::pushMatrix(); - { - gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], chat_bubble_opacity * alpha_factor); - LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; - LLVector3 label_offset = height_vec - label_height; - LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); - gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); - } - LLUI::popMatrix(); - } - } - - BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f; - BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f); - - // draw line segments pointing to parent object - if (!mOffscreen && (outside_width || outside_height)) + + /*LLUI::pushMatrix(); { - LLUI::pushMatrix(); - { gGL.color4fv(bg_color.mV); LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec); target_pos += (width_vec / 2.f); @@ -419,67 +375,65 @@ void LLHUDNameTag::renderText(BOOL for_select) target_pos -= 6.f * y_pixel_vec; LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]); gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec); - } - LLUI::popMatrix(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE); - - LLVector3 box_center_offset; - box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f); - LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]); - gGL.color4fv(bg_color.mV); - LLUI::setLineWidth(2.0); - gGL.begin(LLRender::LINES); + } + LLUI::popMatrix();*/ + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE); + + LLVector3 box_center_offset; + box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f); + LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]); + gGL.color4fv(bg_color.mV); + LLUI::setLineWidth(2.0); + gGL.begin(LLRender::LINES); + { + if (outside_width) { - if (outside_width) + LLVector3 vert; + // draw line in x then y + if (mPositionOffset.mV[VX] < 0.f) { - LLVector3 vert; - // draw line in x then y - if (mPositionOffset.mV[VX] < 0.f) - { - // start at right edge - vert = width_vec * 0.5f; - gGL.vertex3fv(vert.mV); - } - else - { - // start at left edge - vert = width_vec * -0.5f; - gGL.vertex3fv(vert.mV); - } - vert = -mPositionOffset.mV[VX] * x_pixel_vec; + // start at right edge + vert = width_vec * 0.5f; gGL.vertex3fv(vert.mV); + } + else + { + // start at left edge + vert = width_vec * -0.5f; gGL.vertex3fv(vert.mV); - vert -= mPositionOffset.mV[VY] * y_pixel_vec; - vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); + } + vert = -mPositionOffset.mV[VX] * x_pixel_vec; + gGL.vertex3fv(vert.mV); + gGL.vertex3fv(vert.mV); + vert -= mPositionOffset.mV[VY] * y_pixel_vec; + vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); + gGL.vertex3fv(vert.mV); + } + else + { + LLVector3 vert; + // draw line in y then x + if (mPositionOffset.mV[VY] < 0.f) + { + // start at top edge + vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); gGL.vertex3fv(vert.mV); } else { - LLVector3 vert; - // draw line in y then x - if (mPositionOffset.mV[VY] < 0.f) - { - // start at top edge - vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); - gGL.vertex3fv(vert.mV); - } - else - { - // start at bottom edge - vert = (height_vec * -0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); - gGL.vertex3fv(vert.mV); - } - vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec; - vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); + // start at bottom edge + vert = (height_vec * -0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); gGL.vertex3fv(vert.mV); } + vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec; + vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); + gGL.vertex3fv(vert.mV); } - gGL.end(); - LLUI::setLineWidth(1.0); - } + gGL.end(); + LLUI::setLineWidth(1.0); } LLUI::popMatrix(); } @@ -1011,7 +965,7 @@ void LLHUDNameTag::updateAll() // { // continue; // } - (*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC)); + (*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLSmoothInterpolation::getInterpolant(POSITION_DAMPING_TC)); } } @@ -1102,15 +1056,16 @@ void LLHUDNameTag::reshape() F32 LLHUDNameTag::LLHUDTextSegment::getWidth(const LLFontGL* font) { - std::map::iterator iter = mFontWidthMap.find(font); - if (iter != mFontWidthMap.end()) + // Singu note: Reworked hotspot. Less indirection + if (mFontWidthMap[0].first == font) { - return iter->second; + return mFontWidthMap[0].second; } - else + else if (mFontWidthMap[1].first == font) { - F32 width = font->getWidthF32(mText.c_str()); - mFontWidthMap[font] = width; - return width; + return mFontWidthMap[1].second; } + F32 width = font->getWidthF32(mText.c_str()); + mFontWidthMap[mFontWidthMap[0].first != nullptr] = std::make_pair(font, width); + return width; } diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h index e238fac5a9..bc48d788e9 100644 --- a/indra/newview/llhudnametag.h +++ b/indra/newview/llhudnametag.h @@ -63,14 +63,14 @@ class LLHUDNameTag : public LLHUDObject {} F32 getWidth(const LLFontGL* font); const LLWString& getText() const { return mText; } - void clearFontWidthMap() { mFontWidthMap.clear(); } + void clearFontWidthMap() { mFontWidthMap[0].first = nullptr; mFontWidthMap[1].first = nullptr; } LLColor4 mColor; LLFontGL::StyleFlags mStyle; const LLFontGL* mFont; private: LLWString mText; - std::map mFontWidthMap; + std::pair mFontWidthMap[2]; }; public: diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp index b5c05f8fe3..613c70b219 100644 --- a/indra/newview/llhudobject.cpp +++ b/indra/newview/llhudobject.cpp @@ -257,12 +257,12 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type) return hud_objectp; } -static LLFastTimer::DeclareTimer FTM_HUD_UPDATE("Update Hud"); +static LLTrace::BlockTimerStatHandle FTM_HUD_UPDATE("Update Hud"); // static void LLHUDObject::updateAll() { - LLFastTimer ftm(FTM_HUD_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_HUD_UPDATE); LLHUDText::updateAll(); LLHUDIcon::updateAll(); LLHUDNameTag::updateAll(); diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 2cba0a759c..d456584cf4 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -134,9 +134,9 @@ void LLHUDText::renderText() return; } - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - LLGLState gls_blend(GL_BLEND, TRUE); - LLGLState gls_alpha(GL_ALPHA_TEST, TRUE); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + LLGLEnable gls_blend; + LLGLEnable gls_alpha; LLColor4 shadow_color(0.f, 0.f, 0.f, 1.f); F32 alpha_factor = 1.f; @@ -158,7 +158,7 @@ void LLHUDText::renderText() mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f)); // *TODO: cache this image - LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); // *TODO: make this a per-text setting static const LLCachedControl background_chat_color("BackgroundChatColor", LLColor4(0,0,0,1.f)); @@ -613,12 +613,12 @@ void LLHUDText::markDead() void LLHUDText::renderAllHUD() { - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + LLGLStateValidator::checkClientArrays(); { - LLGLEnable color_mat(GL_COLOR_MATERIAL); + LLGLEnable color_mat; LLGLDepthTest depth(GL_FALSE, GL_FALSE); VisibleTextObjectIterator text_it; @@ -633,9 +633,9 @@ void LLHUDText::renderAllHUD() LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + LLGLStateValidator::checkClientArrays(); } void LLHUDText::shiftAll(const LLVector3& offset) @@ -674,17 +674,18 @@ void LLHUDText::reshape() F32 LLHUDText::LLHUDTextSegment::getWidth(const LLFontGL* font) { - std::map::iterator iter = mFontWidthMap.find(font); - if (iter != mFontWidthMap.end()) + // Singu note: Reworked hotspot. Less indirection + if (mFontWidthMap[0].first == font) { - return iter->second; + return mFontWidthMap[0].second; } - else + else if (mFontWidthMap[1].first == font) { - F32 width = font->getWidthF32(mText.c_str()); - mFontWidthMap[font] = width; - return width; + return mFontWidthMap[1].second; } + F32 width = font->getWidthF32(mText.c_str()); + mFontWidthMap[mFontWidthMap[0].first != nullptr] = std::make_pair(font, width); + return width; } // [RLVa:KB] - Checked: 2010-03-27 (RLVa-1.4.0a) | Added: RLVa-1.0.0f diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h index 68450753ca..9ee224954c 100644 --- a/indra/newview/llhudtext.h +++ b/indra/newview/llhudtext.h @@ -61,14 +61,14 @@ class LLHUDText : public LLHUDObject {} F32 getWidth(const LLFontGL* font); const LLWString& getText() const { return mText; } - void clearFontWidthMap() { mFontWidthMap.clear(); } + void clearFontWidthMap() { mFontWidthMap[0].first = nullptr; mFontWidthMap[1].first = nullptr; } LLColor4 mColor; LLFontGL::StyleFlags mStyle; const LLFontGL* mFont; private: LLWString mText; - std::map mFontWidthMap; + std::pair mFontWidthMap[2]; }; public: diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 319e9a7e8d..2e563cf919 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -35,13 +35,17 @@ #include "ascentkeyword.h" #include "llagent.h" +#include "llagentcamera.h" +#include "llagentui.h" #include "llautoreplace.h" #include "llavataractions.h" #include "llavatarnamecache.h" #include "llbutton.h" #include "llcombobox.h" +#include "llfloateravatarpicker.h" #include "llfloaterchat.h" #include "llfloaterinventory.h" +#include "llfloaterreporter.h" #include "llfloaterwebcontent.h" // For web browser display of logs #include "llgroupactions.h" #include "llhttpclient.h" @@ -56,11 +60,14 @@ #include "llstylemap.h" #include "lltrans.h" #include "lluictrlfactory.h" +#include "llversioninfo.h" +#include "llviewerobjectlist.h" #include "llviewertexteditor.h" #include "llviewerstats.h" #include "llviewerwindow.h" #include "llvoicechannel.h" +#include #include // [RLVa:KB] - Checked: 2013-05-10 (RLVa-1.4.9) @@ -109,7 +116,7 @@ void session_starter_helper( msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary std::string name; - gAgent.buildFullname(name); + LLAgentUI::buildFullname(name); msg->addStringFast(_PREHASH_FromAgentName, name); msg->addStringFast(_PREHASH_Message, LLStringUtil::null); @@ -207,7 +214,7 @@ class LLStartConferenceChatResponder : public LLHTTPClient::ResponderIgnoreBody bool send_start_session_messages( const LLUUID& temp_session_id, const LLUUID& other_participant_id, - const std::vector& ids, + const uuid_vec_t& ids, EInstantMessage dialog) { if ( dialog == IM_SESSION_GROUP_START ) @@ -276,18 +283,19 @@ LLFloaterIMPanel::LLFloaterIMPanel( const LLUUID& session_id, const LLUUID& other_participant_id, const EInstantMessage& dialog, - const std::vector& ids) : + const uuid_vec_t& ids) : LLFloater(log_label, LLRect(), log_label), mStartCallOnInitialize(false), mInputEditor(NULL), mHistoryEditor(NULL), mSessionInitialized(false), - mSessionStartMsgPos(0), + mSessionStartMsgPos({0, 0}), mSessionType(P2P_SESSION), mSessionUUID(session_id), mLogLabel(log_label), mQueuedMsgsForInit(), mOtherParticipantUUID(other_participant_id), + mInitialTargetIDs(ids), mDialog(dialog), mTyping(false), mTypingLineStartIndex(0), @@ -321,13 +329,14 @@ LLFloaterIMPanel::LLFloaterIMPanel( case IM_SESSION_GROUP_START: case IM_SESSION_INVITE: case IM_SESSION_CONFERENCE_START: - mCommitCallbackRegistrar.add("FlipDing", boost::bind(boost::lambda::_1 = !boost::lambda::_1, boost::ref(mDing))); + mCommitCallbackRegistrar.add("FlipDing", [=](LLUICtrl*, const LLSD&) { mDing = !mDing; }); // determine whether it is group or conference session if (gAgent.isInGroup(mSessionUUID)) { static LLCachedControl concise("UseConciseGroupChatButtons"); xml_filename = concise ? "floater_instant_message_group_concisebuttons.xml" : "floater_instant_message_group.xml"; - mSessionType = GROUP_SESSION; + bool support = boost::starts_with(mLogLabel, LLTrans::getString("SHORT_APP_NAME") + ' '); + mSessionType = support ? SUPPORT_SESSION : GROUP_SESSION; } else { @@ -366,9 +375,7 @@ LLFloaterIMPanel::LLFloaterIMPanel( if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) { - LLLogChat::loadHistory(mLogLabel, - &chatFromLogFile, - (void *)this); + LLLogChat::loadHistory(mLogLabel, mSessionType == P2P_SESSION ? mOtherParticipantUUID : mSessionUUID, boost::bind(&LLFloaterIMPanel::chatFromLogFile, this, _1, _2)); } if ( !mSessionInitialized ) @@ -389,12 +396,14 @@ LLFloaterIMPanel::LLFloaterIMPanel( LLUIString session_start = sSessionStartString; session_start.setArg("[NAME]", getTitle()); - mSessionStartMsgPos = mHistoryEditor->getWText().length(); + mSessionStartMsgPos.first = mHistoryEditor->getLength(); addHistoryLine( session_start, gSavedSettings.getColor4("SystemChatColor"), false); + + mSessionStartMsgPos.second = mHistoryEditor->getLength() - mSessionStartMsgPos.first; } } } @@ -520,9 +529,14 @@ BOOL LLFloaterIMPanel::postBuild() if (LLComboBox* flyout = findChild("instant_message_flyout")) { flyout->setCommitCallback(boost::bind(&LLFloaterIMPanel::onFlyoutCommit, this, flyout, _2)); - if (is_agent_mappable(mOtherParticipantUUID)) - flyout->add(getString("find on map"), -2); - addDynamics(flyout); + if (mSessionType == P2P_SESSION) + { + if (is_agent_mappable(mOtherParticipantUUID)) + flyout->add(getString("find on map"), -2); + addDynamics(flyout); + if (gObjectList.findAvatar(mOtherParticipantUUID)) + flyout->add(getString("focus"), -3); + } } if (LLUICtrl* ctrl = findChild("tp_btn")) ctrl->setCommitCallback(boost::bind(static_cast(LLAvatarActions::offerTeleport), mOtherParticipantUUID)); @@ -541,7 +555,6 @@ BOOL LLFloaterIMPanel::postBuild() mHistoryEditor = getChild("im_history"); mHistoryEditor->setParseHTML(TRUE); - mHistoryEditor->setParseHighlights(TRUE); sTitleString = getString("title_string"); sTypingStartString = getString("typing_start_string"); @@ -552,11 +565,32 @@ BOOL LLFloaterIMPanel::postBuild() mSpeakerPanel->refreshSpeakers(); } - if (mSessionType == P2P_SESSION) + switch (mSessionType) + { + case P2P_SESSION: { getChild("mute_btn")->setCommitCallback(boost::bind(&LLFloaterIMPanel::onClickMuteVoice, this)); getChild("speaker_volume")->setCommitCallback(boost::bind(&LLVoiceClient::setUserVolume, LLVoiceClient::getInstance(), mOtherParticipantUUID, _2)); } + break; + case SUPPORT_SESSION: + { + auto support = getChildView("Support Check"); + support->setVisible(true); + auto control = gSavedSettings.getControl(support->getControlName()); + if (control->get().asInteger() == -1) + { + LLNotificationsUtil::add("SupportChatShowInfo", LLSD(), LLSD(), [control](const LLSD& p, const LLSD& f) + { + control->set(!LLNotificationsUtil::getSelectedOption(p, f)); + }); + } + // Singu Note: We could make a button feature for dumping Help->About contents for support, too. + } + break; + default: + break; + } setDefaultBtn("send_btn"); @@ -682,7 +716,7 @@ class LLSessionInviteResponder : public LLHTTPClient::ResponderIgnoreBody LLUUID mSessionID; }; -bool LLFloaterIMPanel::inviteToSession(const std::vector& ids) +bool LLFloaterIMPanel::inviteToSession(const uuid_vec_t& ids) { LLViewerRegion* region = gAgent.getRegion(); if (!region) @@ -765,7 +799,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, LLColor4 incol // Now we're adding the actual line of text, so erase the // "Foo is typing..." text segment, and the optional timestamp // if it was present. JC - removeTypingIndicator(NULL); + removeTypingIndicator(source); // Actually add the line bool prepend_newline = true; @@ -777,16 +811,19 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, LLColor4 incol std::string show_name = name; bool is_irc = false; + bool system = name.empty(); // 'name' is a sender name that we want to hotlink so that clicking on it opens a profile. - if (!name.empty()) // If name exists, then add it to the front of the message. + if (!system) // If name exists, then add it to the front of the message. { // Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text. if (name == SYSTEM_FROM) { + system = true; mHistoryEditor->appendColoredText(name,false,prepend_newline,incolor); } else { + system = !from_user; // IRC style text starts with a colon here; empty names and system messages aren't irc style. static const LLCachedControl italicize("LiruItalicizeActions"); is_irc = italicize && utf8msg[0] != ':'; @@ -795,7 +832,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, LLColor4 incol // Convert the name to a hotlink and add to message. LLStyleSP source_style = LLStyleMap::instance().lookupAgent(source); source_style->mItalic = is_irc; - mHistoryEditor->appendStyledText(show_name,false,prepend_newline,source_style); + mHistoryEditor->appendText(show_name,false,prepend_newline,source_style, system); } prepend_newline = false; } @@ -806,7 +843,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, LLColor4 incol style->setColor(incolor); style->mItalic = is_irc; style->mBold = from_user && gSavedSettings.getBOOL("SingularityBoldGroupModerator") && isModerator(source); - mHistoryEditor->appendStyledText(utf8msg, false, prepend_newline, style); + mHistoryEditor->appendText(utf8msg, false, prepend_newline, style, system); } if (log_to_file @@ -822,7 +859,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, LLColor4 incol // Floater title contains display name -> bad idea to use that as filename // mLogLabel, however, is the old legacy name //LLLogChat::saveHistory(getTitle(),histstr); - LLLogChat::saveHistory(mLogLabel, histstr); + LLLogChat::saveHistory(mLogLabel, mSessionType == P2P_SESSION ? mOtherParticipantUUID : mSessionUUID, histstr); // [/Ansariel: Display name support] } @@ -930,9 +967,7 @@ BOOL LLFloaterIMPanel::dropCallingCard(LLInventoryItem* item, BOOL drop) { if (drop) { - std::vector ids; - ids.push_back(item->getCreatorUUID()); - inviteToSession(ids); + inviteToSession({ item->getCreatorUUID() }); } return true; } @@ -959,7 +994,7 @@ BOOL LLFloaterIMPanel::dropCategory(LLInventoryCategory* category, BOOL drop) } else if(drop) { - std::vector ids; + uuid_vec_t ids; for(S32 i = 0; i < count; ++i) { ids.push_back(items.at(i)->getCreatorUUID()); @@ -975,6 +1010,96 @@ bool LLFloaterIMPanel::isInviteAllowed() const return mSessionType == ADHOC_SESSION; } +void LLFloaterIMPanel::onAddButtonClicked() +{ + LLView * button = findChild("instant_message_flyout"); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterIMPanel::addSessionParticipants, this, _1), TRUE, TRUE, FALSE, root_floater->getName(), button); + if (!picker) + { + return; + } + + // Need to disable 'ok' button when selected users are already in conversation. + picker->setOkBtnEnableCb(boost::bind(&LLFloaterIMPanel::canAddSelectedToChat, this, _1)); + + if (root_floater) + { + root_floater->addDependentFloater(picker); + } +} + +bool LLFloaterIMPanel::canAddSelectedToChat(const uuid_vec_t& uuids) const +{ + switch (mSessionType) + { + case P2P_SESSION: return true; // Don't bother blocking self or peer + case ADHOC_SESSION: + { + // For a conference session we need to check against the list from LLSpeakerMgr, + // because this list may change when participants join or leave the session. + + LLSpeakerMgr::speaker_list_t speaker_list; + LLIMSpeakerMgr* speaker_mgr = getSpeakerManager(); + if (speaker_mgr) + { + speaker_mgr->getSpeakerList(&speaker_list, true); + } + + for (const auto& id : uuids) + for (const LLPointer& speaker : speaker_list) + if (id == speaker->mID) + return false; + } + return true; + default: return false; + } +} + +void LLFloaterIMPanel::addSessionParticipants(const uuid_vec_t& uuids) +{ + if (mSessionType == P2P_SESSION) + { + LLSD payload; + LLSD args; + + LLNotificationsUtil::add("ConfirmAddingChatParticipants", args, payload, + boost::bind(&LLFloaterIMPanel::addP2PSessionParticipants, this, _1, _2, uuids)); + } + else inviteToSession(uuids); +} + +void LLFloaterIMPanel::addP2PSessionParticipants(const LLSD& notification, const LLSD& response, const uuid_vec_t& uuids) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) + { + return; + } + + LLVoiceChannel* voice_channel = LLActiveSpeakerMgr::getInstance()->getVoiceChannel(); + + // first check whether this is a voice session + bool is_voice_call = voice_channel != nullptr && voice_channel->getSessionID() == mSessionUUID && voice_channel->isActive(); + + uuid_vec_t temp_ids; + + // Add the initial participant of a P2P session + temp_ids.push_back(mOtherParticipantUUID); + temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end()); + + // Start a new ad hoc voice call if we invite new participants to a P2P call, + // or start a text chat otherwise. + if (is_voice_call) + { + LLAvatarActions::startAdhocCall(temp_ids); + } + else + { + LLAvatarActions::startConference(temp_ids); + } +} + void LLFloaterIMPanel::removeDynamics(LLComboBox* flyout) { flyout->remove(mDing ? getString("ding on") : getString("ding off")); @@ -991,56 +1116,84 @@ void LLFloaterIMPanel::addDynamics(LLComboBox* flyout) flyout->add(LLAvatarActions::isBlocked(mOtherParticipantUUID) ? getString("unmute") : getString("mute"), 9); } -void copy_profile_uri(const LLUUID& id, bool group = false); +void LLFloaterIMPanel::addDynamicFocus() +{ + findChild("instant_message_flyout")->add(getString("focus"), -3); +} + +void LLFloaterIMPanel::removeDynamicFocus() +{ + findChild("instant_message_flyout")->remove(getString("focus")); +} + +void copy_profile_uri(const LLUUID& id, const LFIDBearer::Type& type = LFIDBearer::AVATAR); void LLFloaterIMPanel::onFlyoutCommit(LLComboBox* flyout, const LLSD& value) { if (value.isUndefined() || value.asInteger() == 0) { - LLAvatarActions::showProfile(mOtherParticipantUUID); - return; + switch (mSessionType) + { + case SUPPORT_SESSION: + case GROUP_SESSION: LLGroupActions::show(mSessionUUID); return; + case P2P_SESSION: LLAvatarActions::showProfile(mOtherParticipantUUID); return; + default: onClickHistory(); return; // If there's no profile for this type, we should be the history button. + } } - int option = value.asInteger(); - if (option == 1) onClickHistory(); - else if (option == 2) LLAvatarActions::offerTeleport(mOtherParticipantUUID); - else if (option == 3) LLAvatarActions::teleportRequest(mOtherParticipantUUID); - else if (option == 4) LLAvatarActions::pay(mOtherParticipantUUID); - else if (option == 5) LLAvatarActions::inviteToGroup(mOtherParticipantUUID); - else if (option == -1) copy_profile_uri(mOtherParticipantUUID); - else if (option == -2) LLAvatarActions::showOnMap(mOtherParticipantUUID); - else if (option >= 6) // Options that use dynamic items + switch (int option = value.asInteger()) + { + case 1: onClickHistory(); break; + case 2: LLAvatarActions::offerTeleport(mOtherParticipantUUID); break; + case 3: LLAvatarActions::teleportRequest(mOtherParticipantUUID); break; + case 4: LLAvatarActions::pay(mOtherParticipantUUID); break; + case 5: LLAvatarActions::inviteToGroup(mOtherParticipantUUID); break; + case -1: copy_profile_uri(mOtherParticipantUUID); break; + case -2: LLAvatarActions::showOnMap(mOtherParticipantUUID); break; + case -3: gAgentCamera.lookAtObject(mOtherParticipantUUID); break; + case -4: onAddButtonClicked(); break; + case -5: LLFloaterReporter::showFromAvatar(mOtherParticipantUUID, mLogLabel); break; + default: // Options >= 6 use dynamic items { // First remove them all removeDynamics(flyout); // Toggle as requested, adjust the strings - if (option == 6) mDing = !mDing; - else if (option == 7) mRPMode = !mRPMode; - else if (option == 8) LLAvatarActions::isFriend(mOtherParticipantUUID) ? LLAvatarActions::removeFriendDialog(mOtherParticipantUUID) : LLAvatarActions::requestFriendshipDialog(mOtherParticipantUUID); - else if (option == 9) LLAvatarActions::toggleBlock(mOtherParticipantUUID); + switch (option) + { + case 6: mDing = !mDing; break; + case 7: mRPMode = !mRPMode; break; + case 8: LLAvatarActions::isFriend(mOtherParticipantUUID) ? LLAvatarActions::removeFriendDialog(mOtherParticipantUUID) : LLAvatarActions::requestFriendshipDialog(mOtherParticipantUUID); break; + case 9: LLAvatarActions::toggleBlock(mOtherParticipantUUID); break; + } // Last add them back addDynamics(flyout); + // Always have Focus last + const std::string focus(getString("focus")); + if (flyout->remove(focus)) // If present, reorder to bottom. + flyout->add(focus, -3); + } } } -void show_log_browser(const std::string& name, const std::string& id) +void show_log_browser(const std::string& name, const LLUUID& id) { - const std::string file(LLLogChat::makeLogFileName(name)); - if (gSavedSettings.getBOOL("LiruLegacyLogLaunch")) + const std::string file(LLLogChat::makeLogFileName(name, id)); + if (!LLFile::isfile(file)) { -#if LL_WINDOWS || LL_DARWIN - gViewerWindow->getWindow()->ShellEx(file); -#elif LL_LINUX - // xdg-open might not actually be installed on all distros, but it's our best bet. - if (!std::system(("/usr/bin/xdg-open \"" + file +'"').c_str())) // 0 = success, otherwise fallback on internal browser. -#endif + make_ui_sound("UISndBadKeystroke"); + LL_WARNS() << "File not present: " << file << LL_ENDL; return; } + if (gSavedSettings.getBOOL("LiruLegacyLogLaunch")) + { + if (!LLWindow::ShellEx(file)) // 0 = success, otherwise fallback on internal browser. + return; + } LLFloaterWebContent::Params p; p.url("file:///" + file); - p.id(id); + p.id(id.asString()); p.show_chrome(false); p.trusted_content(true); LLFloaterWebContent::showInstance("log", p); // If we passed id instead of "log", there would be no control over how many log browsers opened at once. @@ -1051,8 +1204,8 @@ void LLFloaterIMPanel::onClickHistory() if (mOtherParticipantUUID.notNull()) { // [Ansariel: Display name support] - //show_log_browser(getTitle(), mOtherParticipantUUID.asString()); - show_log_browser(mLogLabel, mOtherParticipantUUID.asString()); + //show_log_browser(getTitle(), mSessionType == P2P_SESSION ? mOtherParticipantUUID : mSessionUUID); + show_log_browser(mLogLabel, mSessionType == P2P_SESSION ? mOtherParticipantUUID : mSessionUUID); // [/Ansariel: Display name support] } } @@ -1094,7 +1247,7 @@ void deliver_message(const std::string& utf8_text, { std::string name; bool sent = false; - gAgent.buildFullname(name); + LLAgentUI::buildFullname(name); const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id); @@ -1103,7 +1256,7 @@ void deliver_message(const std::string& utf8_text, if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id))) { // User is online through the OOW connector, but not with a regular viewer. Try to send the message via SLVoice. - sent = LLVoiceClient::getInstance()->sendTextMessage(other_participant_id, utf8_text); +// sent = LLVoiceClient::getInstance()->sendTextMessage(other_participant_id, utf8_text); } if(!sent) @@ -1194,6 +1347,8 @@ void LLFloaterIMPanel::onSendMsg() case GROUP_SESSION: // Group chat fRlvFilter = !RlvActions::canSendIM(mSessionUUID); break; + case SUPPORT_SESSION: // Support Group, never filter, they may need help!! + break; case ADHOC_SESSION: // Conference chat: allow if all participants can be sent an IM { if (!mSpeakers) @@ -1228,6 +1383,11 @@ void LLFloaterIMPanel::onSendMsg() } // [/RLVa:KB] + if (mSessionType == SUPPORT_SESSION && getChildView("Support Check")->getValue()) + { + utf8_text.insert(action ? 3 : 0, llformat(action ? " (%d%s)" : "(%d%s): ", LL_VIEWER_VERSION_BUILD, wstring_to_utf8str(LL_VIEWER_CHANNEL_GRK).data())); + } + if ( mSessionInitialized ) { // Split messages that are too long, same code like in llimpanel.cpp @@ -1282,12 +1442,12 @@ void LLFloaterIMPanel::onSendMsg() (mOtherParticipantUUID.notNull())) { std::string name; - gAgent.buildFullname(name); + LLAgentUI::buildFullname(name); // Look for actions here. if (action) { - utf8_text.replace(0,3,""); + utf8_text.erase(0,3); } else { @@ -1296,7 +1456,7 @@ void LLFloaterIMPanel::onSendMsg() bool other_was_typing = mOtherTyping; addHistoryLine(utf8_text, gSavedSettings.getColor("UserChatColor"), true, gAgentID, name); - if (other_was_typing) addTypingIndicator(mOtherTypingName); + if (other_was_typing) addTypingIndicator(mOtherParticipantUUID); } } else @@ -1347,11 +1507,7 @@ void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id) mVoiceChannel->updateSessionID(session_id); mSessionInitialized = true; - //we assume the history editor hasn't moved at all since - //we added the starting session message - //so, we count how many characters to remove - S32 chars_to_remove = mHistoryEditor->getWText().length() - mSessionStartMsgPos; - mHistoryEditor->removeTextFromEnd(chars_to_remove); + mHistoryEditor->remove(mSessionStartMsgPos.first, mSessionStartMsgPos.second, true); //and now, send the queued msg for (LLSD::array_iterator iter = mQueuedMsgsForInit.beginArray(); @@ -1413,7 +1569,7 @@ void LLFloaterIMPanel::sendTypingState(bool typing) if (mSessionType != P2P_SESSION) return; std::string name; - gAgent.buildFullname(name); + LLAgentUI::buildFullname(name); pack_instant_message( gMessageSystem, @@ -1430,89 +1586,99 @@ void LLFloaterIMPanel::sendTypingState(bool typing) } -void LLFloaterIMPanel::processIMTyping(const LLIMInfo* im_info, bool typing) +void LLFloaterIMPanel::processIMTyping(const LLUUID& from_id, BOOL typing) { if (typing) { // other user started typing - std::string name; - if (!LLAvatarNameCache::getNSName(im_info->mFromID, name)) name = im_info->mName; - addTypingIndicator(name); + addTypingIndicator(from_id); } else { // other user stopped typing - removeTypingIndicator(im_info); + removeTypingIndicator(from_id); } } -void LLFloaterIMPanel::addTypingIndicator(const std::string &name) +void LLFloaterIMPanel::addTypingIndicator(const LLUUID& from_id) { - // we may have lost a "stop-typing" packet, don't add it twice - if (!mOtherTyping) + // Singu TODO: Actually implement this? +/* Operation of " is typing" state machine: +Not Typing state: + + User types in P2P IM chat ... Send Start Typing, save Started time, + start Idle Timer (N seconds) go to Typing state + +Typing State: + + User enters a non-return character: if Now - Started > ME_TYPING_TIMEOUT, send + Start Typing, restart Idle Timer + User enters a return character: stop Idle Timer, send IM and Stop + Typing, go to Not Typing state + Idle Timer expires: send Stop Typing, go to Not Typing state + +The recipient has a complementary state machine in which a Start Typing +that is not followed by either an IM or another Start Typing within OTHER_TYPING_TIMEOUT +seconds switches the sender out of typing state. + +This has the nice quality of being self-healing for lost start/stop +messages while adding messages only for the (relatively rare) case of a +user who types a very long message (one that takes more than ME_TYPING_TIMEOUT seconds +to type). + +Note: OTHER_TYPING_TIMEOUT must be > ME_TYPING_TIMEOUT for proper operation of the state machine + +*/ + + // We may have lost a "stop-typing" packet, don't add it twice + if (from_id.notNull() && !mOtherTyping) { + mOtherTyping = true; + // Save im_info so that removeTypingIndicator can be properly called because a timeout has occurred + LLAvatarNameCache::getNSName(from_id, mOtherTypingName); + mTypingLineStartIndex = mHistoryEditor->getWText().length(); LLUIString typing_start = sTypingStartString; - typing_start.setArg("[NAME]", name); + typing_start.setArg("[NAME]", mOtherTypingName); addHistoryLine(typing_start, gSavedSettings.getColor4("SystemChatColor"), false); - mOtherTypingName = name; - mOtherTyping = true; + + // Update speaker + LLIMSpeakerMgr* speaker_mgr = mSpeakers; + if ( speaker_mgr ) + { + speaker_mgr->setSpeakerTyping(from_id, TRUE); + } + mOtherTyping = true; // addHistoryLine clears this flag. Set it again. } - // MBW -- XXX -- merge from release broke this (argument to this function changed from an LLIMInfo to a name) - // Richard will fix. -// mSpeakers->setSpeakerTyping(im_info->mFromID, TRUE); } - -void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info) +void LLFloaterIMPanel::removeTypingIndicator(const LLUUID& from_id) { if (mOtherTyping) { - // Must do this first, otherwise addHistoryLine calls us again. mOtherTyping = false; S32 chars_to_remove = mHistoryEditor->getWText().length() - mTypingLineStartIndex; mHistoryEditor->removeTextFromEnd(chars_to_remove); - if (im_info) + + if (from_id.notNull()) { - mSpeakers->setSpeakerTyping(im_info->mFromID, FALSE); + mSpeakers->setSpeakerTyping(from_id, FALSE); } } } -//static -void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata) +void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, const std::string& line) { - LLFloaterIMPanel* self = (LLFloaterIMPanel*)userdata; - std::string message = line; - - switch (type) + bool log_line = type == LLLogChat::LOG_LINE; + if (log_line || gSavedPerAccountSettings.getBOOL("LogInstantMessages")) { - case LLLogChat::LOG_EMPTY: - // add warning log enabled message - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) - { - message = LLFloaterChat::getInstance()->getString("IM_logging_string"); - } - break; - case LLLogChat::LOG_END: - // add log end message - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) - { - message = LLFloaterChat::getInstance()->getString("IM_end_log_string"); - } - break; - case LLLogChat::LOG_LINE: - // just add normal lines from file - break; - default: - // nothing - break; + LLStyleSP style(new LLStyle(true, gSavedSettings.getColor4("LogChatColor"), LLStringUtil::null)); + mHistoryEditor->appendText(log_line ? line : + getString(type == LLLogChat::LOG_END ? "IM_end_log_string" : "IM_logging_string"), + false, true, style, false); } - - //self->addHistoryLine(line, LLColor4::grey, FALSE); - self->mHistoryEditor->appendColoredText(message, false, true, LLColor4::grey); } void LLFloaterIMPanel::showSessionStartError( diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index e016c4ca35..da0b22d0e4 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -39,7 +39,6 @@ class LLAvatarName; class LLIMSpeakerMgr; -class LLIMInfo; class LLInventoryCategory; class LLInventoryItem; class LLLineEditor; @@ -60,7 +59,7 @@ class LLFloaterIMPanel : public LLFloater, public LLFriendObserver, public LLMut const LLUUID& session_id, const LLUUID& target_id, const EInstantMessage& dialog, - const std::vector& ids = std::vector()); + const uuid_vec_t& ids = uuid_vec_t()); virtual ~LLFloaterIMPanel(); void onAvatarNameLookup(const LLAvatarName& avatar_name); @@ -77,7 +76,7 @@ class LLFloaterIMPanel : public LLFloater, public LLFriendObserver, public LLMut // add target ids to the session. // Return TRUE if successful, otherwise FALSE. - bool inviteToSession(const std::vector& agent_ids); + bool inviteToSession(const uuid_vec_t& agent_ids); void addHistoryLine(const std::string &utf8msg, LLColor4 incolor = LLColor4::white, @@ -114,6 +113,7 @@ class LLFloaterIMPanel : public LLFloater, public LLFriendObserver, public LLMut { P2P_SESSION, GROUP_SESSION, + SUPPORT_SESSION, ADHOC_SESSION }; const SType& getSessionType() const { return mSessionType; } @@ -125,8 +125,8 @@ class LLFloaterIMPanel : public LLFloater, public LLFriendObserver, public LLMut void sessionInitReplyReceived(const LLUUID& im_session_id); // Handle other participant in the session typing. - void processIMTyping(const LLIMInfo* im_info, bool typing); - static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata); + void processIMTyping(const LLUUID& from_id, BOOL typing); + void chatFromLogFile(LLLogChat::ELogLineType type, const std::string& line); //show error statuses to the user void showSessionStartError(const std::string& error_string); @@ -141,7 +141,13 @@ class LLFloaterIMPanel : public LLFloater, public LLFriendObserver, public LLMut bool getSessionInitialized() const { return mSessionInitialized; } bool mStartCallOnInitialize; +protected: + friend class LLViewerObjectList; + void addDynamicFocus(); + void removeDynamicFocus(); + private: + friend class LLSpeakerMgr; // Called by UI methods. void onSendMsg(); @@ -160,15 +166,20 @@ class LLFloaterIMPanel : public LLFloater, public LLFriendObserver, public LLMut // test if local agent can add agents. bool isInviteAllowed() const; + void onAddButtonClicked(); + void addSessionParticipants(const uuid_vec_t& uuids); + void addP2PSessionParticipants(const LLSD& notification, const LLSD& response, const uuid_vec_t& uuids); + bool canAddSelectedToChat(const uuid_vec_t& uuids) const; + // Called whenever the user starts or stops typing. // Sends the typing state to the other user if necessary. void setTyping(bool typing); // Add the "User is typing..." indicator. - void addTypingIndicator(const std::string &name); + void addTypingIndicator(const LLUUID& from_id); // Remove the "User is typing..." indicator. - void removeTypingIndicator(const LLIMInfo* im_info); + void removeTypingIndicator(const LLUUID& from_id = LLUUID::null); void sendTypingState(bool typing); @@ -180,8 +191,8 @@ class LLFloaterIMPanel : public LLFloater, public LLFriendObserver, public LLMut bool mSessionInitialized; - // Where does the "Starting session..." line start? - S32 mSessionStartMsgPos; + // Where does the "Starting session..." line start and how long is it? + std::pair mSessionStartMsgPos; SType mSessionType; @@ -203,6 +214,7 @@ class LLFloaterIMPanel : public LLFloater, public LLFriendObserver, public LLMut // inventory folder ==> first target id in list // 911 ==> sender LLUUID mOtherParticipantUUID; + uuid_vec_t mInitialTargetIDs; EInstantMessage mDialog; diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp new file mode 100644 index 0000000000..cee8d629f8 --- /dev/null +++ b/indra/newview/llimprocessing.cpp @@ -0,0 +1,2027 @@ +/** +* @file LLIMProcessing.cpp +* @brief Container for Instant Messaging +* +* $LicenseInfo:firstyear=2001&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2018, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "llimprocessing.h" + +#include "hippofloaterxml.h" +#include "llagent.h" +#include "llagentui.h" +#include "llavataractions.h" +#include "llavatarnamecache.h" +#include "llbase64.h" +#include "llcororesponder.h" +#include "llfloaterchat.h" +#include "llgiveinventory.h" +#include "llgroupactions.h" +#include "llimpanel.h" +#include "llimview.h" +#include "llinventoryobserver.h" +#include "llmutelist.h" +#include "llnotificationsutil.h" +#include "llslurl.h" +#include "lltrans.h" +#include "llversioninfo.h" +#include "llviewergenericmessage.h" +#include "llviewerobjectlist.h" +#include "llviewermessage.h" +#include "llviewerwindow.h" +#include "llvoavatarself.h" +#include "llwindow.h" +#include "NACLantispam.h" +// [RLVa:KB] - Checked: 2010-03-09 (RLVa-1.2.0a) +#include "rlvactions.h" +#include "rlvhandler.h" +#include "rlvui.h" +// [/RLVa:KB] + +#include // +#include +#include +#include + +bool has_spam_bypass(bool is_friend, bool is_owned_by_me); + + +// Replace wild cards in message strings +std::string replace_wildcards(std::string input, const LLUUID& id, const std::string& name) +{ + boost::algorithm::replace_all(input, "#n", name); + + LLSLURL slurl; + LLAgentUI::buildSLURL(slurl); + boost::algorithm::replace_all(input, "#r", slurl.getSLURLString()); + + LLAvatarName av_name; + boost::algorithm::replace_all(input, "#d", LLAvatarNameCache::get(id, &av_name) ? av_name.getDisplayName() : name); + + if (isAgentAvatarValid()) + { + LLStringUtil::format_map_t args; + args["[MINS]"] = boost::lexical_cast(gAgentAvatarp->mIdleTimer.getElapsedTimeF32()/60); + boost::algorithm::replace_all(input, "#i", LLTrans::getString("IM_autoresponse_minutes", args)); + } + + return input; +} + +void autoresponder_finish(bool show_autoresponded, const LLUUID& session_id, const LLUUID& from_id, const std::string& name, const LLUUID& itemid, bool is_muted) +{ + void cmdline_printchat(const std::string& message); + if (show_autoresponded) + { + const std::string notice(LLTrans::getString("IM_autoresponded_to") + ' ' + LLAvatarActions::getSLURL(from_id)); + is_muted ? cmdline_printchat(notice) : gIMMgr->addMessage(session_id, from_id, name, notice); + } + if (LLViewerInventoryItem* item = gInventory.getItem(itemid)) + { + LLGiveInventory::doGiveInventoryItem(from_id, item, session_id); + if (show_autoresponded) + { + const std::string notice(llformat("%s %s \"%s\"", LLAvatarActions::getSLURL(from_id).data(), LLTrans::getString("IM_autoresponse_sent_item").c_str(), item->getName().c_str())); + is_muted ? cmdline_printchat(notice) : gIMMgr->addMessage(session_id, from_id, name, notice); + } + } +} + +// defined in llchatbar.cpp, but not declared in any header +void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel); + +void script_msg_api(const std::string& msg) +{ + static const LLCachedControl channel("ScriptMessageAPI"); + if (!channel) return; + static const LLCachedControl key("ScriptMessageAPIKey"); + std::string str; + for (size_t i = 0, keysize = key().size(); i != msg.size(); ++i) + str += msg[i] ^ key()[i%keysize]; + send_chat_from_viewer(LLBase64::encode(reinterpret_cast(str.c_str()), str.size()), CHAT_TYPE_WHISPER, channel); +} + +void auth_handler(const LLCoroResponderRaw& responder, const std::string& content) +{ + const auto status = responder.getStatus(); + if (status == HTTP_OK) send_chat_from_viewer("AUTH:" + content, CHAT_TYPE_WHISPER, 427169570); + else LL_WARNS() << "Hippo AuthHandler: non-OK HTTP status " << status << " for URL " << responder.getURL() << " (" << responder.getReason() << "). Error body: \"" << content << "\"." << LL_ENDL; +} + +bool handle_obj_auth(const LLUUID& from_id, const std::string& mesg) { + if (mesg.size() < 4 || mesg.substr(0, 3) != "># ") + return false; + + static std::set sChatObjectAuth; + if (mesg.size() >= 5 && mesg.substr(mesg.size()-3, 3) == " #<"){ + // hello from object + if (from_id.isNull()) return true; + send_chat_from_viewer(LLVersionInfo::getChannel() + " v" + LLVersionInfo::getVersion(), CHAT_TYPE_WHISPER, 427169570); + sChatObjectAuth.insert(from_id); + } + else if (from_id.isNull() || sChatObjectAuth.find(from_id) != sChatObjectAuth.end()) { + LLUUID key; + if (mesg.size() >= 39 && key.set(mesg.substr(3, 36), false)) { + // object command found + if (key.isNull() && mesg.size() == 39) { + // clear all nameplates + for (auto& pair : gObjectList.mUUIDAvatarMap) + if (auto& avatar = pair.second) + avatar->clearNameFromChat(); + } + else if (LLVOAvatar *avatar = key.isNull() ? nullptr : gObjectList.findAvatar(key)) { + if (mesg.size() == 39) avatar->clearNameFromChat(); + else if (mesg.size() > 40 && mesg[39] == ' ') + avatar->setNameFromChat(mesg.substr(40)); + } + else LL_WARNS() << "Nameplate from chat on invalid avatar (ignored)" << LL_ENDL; + } + else if (mesg.size() > 11 && mesg.substr(2, 9) == " floater ") + HippoFloaterXml::execute(mesg.substr(11)); + else if (mesg.size() > 8 && mesg.substr(2, 6) == " auth ") { + std::string authUrl = mesg.substr(8); + authUrl += (authUrl.find('?') != std::string::npos)? "&auth=": "?auth="; + authUrl += gAuthString; + LLHTTPClient::get(authUrl, new LLCoroResponderRaw(auth_handler)); + } + else return false; + } + else return false; + return true; +} + +// Strip out "Resident" for display, but only if the message came from a user +// (rather than a script) +static std::string clean_name_from_im(const std::string& name, EInstantMessage type) +{ + switch (type) + { + case IM_NOTHING_SPECIAL: + case IM_MESSAGEBOX: + case IM_GROUP_INVITATION: + case IM_INVENTORY_OFFERED: + case IM_INVENTORY_ACCEPTED: + case IM_INVENTORY_DECLINED: + case IM_GROUP_VOTE: + case IM_GROUP_MESSAGE_DEPRECATED: + //IM_TASK_INVENTORY_OFFERED + //IM_TASK_INVENTORY_ACCEPTED + //IM_TASK_INVENTORY_DECLINED + case IM_NEW_USER_DEFAULT: + case IM_SESSION_INVITE: + case IM_SESSION_P2P_INVITE: + case IM_SESSION_GROUP_START: + case IM_SESSION_CONFERENCE_START: + case IM_SESSION_SEND: + case IM_SESSION_LEAVE: + //IM_FROM_TASK + case IM_BUSY_AUTO_RESPONSE: + case IM_CONSOLE_AND_CHAT_HISTORY: + case IM_LURE_USER: + case IM_LURE_ACCEPTED: + case IM_LURE_DECLINED: + case IM_GODLIKE_LURE_USER: + case IM_TELEPORT_REQUEST: + case IM_GROUP_ELECTION_DEPRECATED: + //IM_GOTO_URL + //IM_FROM_TASK_AS_ALERT + case IM_GROUP_NOTICE: + case IM_GROUP_NOTICE_INVENTORY_ACCEPTED: + case IM_GROUP_NOTICE_INVENTORY_DECLINED: + case IM_GROUP_INVITATION_ACCEPT: + case IM_GROUP_INVITATION_DECLINE: + case IM_GROUP_NOTICE_REQUESTED: + case IM_FRIENDSHIP_OFFERED: + case IM_FRIENDSHIP_ACCEPTED: + case IM_FRIENDSHIP_DECLINED_DEPRECATED: + case IM_TYPING_START: + //IM_TYPING_STOP + return LLCacheName::cleanFullName(name); + default: + return name; + } +} + +static std::string clean_name_from_task_im(const std::string& msg, + BOOL from_group) +{ + boost::smatch match; + static const boost::regex returned_exp( + "(.*been returned to your inventory lost and found folder by )(.+)( (from|near).*)"); + if (boost::regex_match(msg, match, returned_exp)) + { + // match objects are 1-based for groups + std::string final = match[1].str(); + std::string name = match[2].str(); + // Don't try to clean up group names + if (!from_group) + { + if (LLAvatarName::useDisplayNames()) + { + // ...just convert to username + final += LLCacheName::buildUsername(name); + } + else + { + // ...strip out legacy "Resident" name + final += LLCacheName::cleanFullName(name); + } + } + final += match[3].str(); + return final; + } + return msg; +} + +const std::string NOT_ONLINE_MSG("User not online - message will be stored and delivered later."); +const std::string NOT_ONLINE_INVENTORY("User not online - inventory has been saved."); +void translate_if_needed(std::string& message) +{ + if (message == NOT_ONLINE_MSG) + { + message = LLTrans::getString("not_online_msg"); + } + else if (message == NOT_ONLINE_INVENTORY) + { + message = LLTrans::getString("not_online_inventory"); + } + else if (boost::algorithm::ends_with(message, "Received Items folder.")) + { + boost::smatch match; + const boost::regex gift_exp("^You've received a gift! (.*) has given you \\\"(.*)\\\", and says \\\"(.*)\\\"\\. You can find your gift in your Received Items folder\\.$"); + bool gift = boost::regex_match(message, match, gift_exp); + if (gift || boost::regex_match(message, match, boost::regex("^Your purchase of (.*) has been delivered to your Received Items folder\\.$"))) + message = LLTrans::getString(gift ? "ReceivedGift" : "ReceivedPurchase", + gift ? LLSD().with("USER", match[1].str()).with("PRODUCT", match[2].str()).with("MESSAGE", match[3].str()) + : LLSD().with("PRODUCT", match[1].str())); + if (gSavedSettings.getBOOL("LiruReceivedItemsNotify")) LLNotificationsUtil::add("SystemMessage", LLSD().with("MESSAGE", message)); + } +} + +void inventory_offer_handler(LLOfferInfo* info, bool is_friend, bool is_owned_by_me) +{ + // NaCl - Antispam Registry + static const LLCachedControl no_landmarks("AntiSpamItemOffersLandmarks"); + auto antispam = NACLAntiSpamRegistry::getIfExists(); + if ((antispam && antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_INVENTORY, info->mFromID, info->mFromGroup ? LFIDBearer::GROUP : LFIDBearer::AVATAR)) + || (!has_spam_bypass(is_friend, is_owned_by_me) + && (no_landmarks && info->mType == LLAssetType::AT_LANDMARK))) + { + delete info; + return; + } + // NaCl End + + // If muted, don't even go through the messaging stuff. Just curtail the offer here. + // Passing in a null UUID handles the case of where you have muted one of your own objects by_name. + // The solution for STORM-1297 seems to handle the cases where the object is owned by someone else. + if (LLMuteList::getInstance()->isMuted(info->mFromID, info->mFromName) || + LLMuteList::getInstance()->isMuted(LLUUID::null, info->mFromName)) + { + info->forceResponse(IOR_MUTE); + return; + } + + if (!info->mFromGroup) script_msg_api(info->mFromID.asString() + ", 1"); + + // If the user wants to, accept all offers of any kind + if (gSavedSettings.getBOOL("AutoAcceptAllNewInventory")) + { + info->forceResponse(IOR_ACCEPT); + return; + } + + // Avoid the Accept/Discard dialog if the user so desires. JC + if (gSavedSettings.getBOOL("AutoAcceptNewInventory") + && (info->mType == LLAssetType::AT_NOTECARD + || info->mType == LLAssetType::AT_LANDMARK + || info->mType == LLAssetType::AT_TEXTURE)) + { + // For certain types, just accept the items into the inventory, + // and possibly open them on receipt depending upon "ShowNewInventory". + info->forceResponse(IOR_ACCEPT); + return; + } + + if (gAgent.isDoNotDisturb() && info->mIM != IM_TASK_INVENTORY_OFFERED) // busy mode must not affect interaction with objects (STORM-565) + { + // Until throttling is implemented, busy mode should reject inventory instead of silently + // accepting it. SEE SL-39554 + info->forceResponse(IOR_DECLINE); + return; + } + + // Strip any SLURL from the message display. (DEV-2754) + std::string msg = info->mDesc; + int indx = msg.find(" ( http://slurl.com/secondlife/"); + if(indx == std::string::npos) + { + // try to find new slurl host + indx = msg.find(" ( http://maps.secondlife.com/secondlife/"); + } + if(indx >= 0) + { + LLStringUtil::truncate(msg, indx); + } + + LLSD args; + args["[OBJECTNAME]"] = msg; + + LLSD payload; + + // must protect against a NULL return from lookupHumanReadable() + std::string typestr = ll_safe_string(LLAssetType::lookupHumanReadable(info->mType)); + if (!typestr.empty()) + { + // human readable matches string name from strings.xml + // lets get asset type localized name + args["OBJECTTYPE"] = LLTrans::getString(typestr); + } + else + { + LL_WARNS("Messaging") << "LLAssetType::lookupHumanReadable() returned NULL - probably bad asset type: " << info->mType << LL_ENDL; + args["OBJECTTYPE"] = ""; + + // This seems safest, rather than propagating bogosity + LL_WARNS("Messaging") << "Forcing an inventory-decline for probably-bad asset type." << LL_ENDL; + info->forceResponse(IOR_DECLINE); + return; + } + + // Name cache callbacks don't store userdata, so can't save + // off the LLOfferInfo. Argh. + payload["from_id"] = info->mFromID; + args["OBJECTFROMNAME"] = info->mFromName; + args["NAME"] = info->mFromName; + if (info->mFromGroup) + { + args["NAME"] = LLGroupActions::getSLURL(info->mFromID); + } + else + { + std::string full_name = LLAvatarActions::getSLURL(info->mFromID); +// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Modified: RLVa-1.2.2a + // Only filter if the object owner is a nearby agent + if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(info->mFromID)) ) + { + full_name = RlvStrings::getAnonym(full_name); + } +// [/RLVa:KB] + args["NAME"] = full_name; + } + + + LLNotification::Params p("ObjectGiveItem"); + p.substitutions(args).payload(payload).functor(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2)); + + // Object -> Agent Inventory Offer + if (info->mFromObject) + { + p.name = "ObjectGiveItem"; + } + else // Agent -> Agent Inventory Offer + { +// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Modified: RLVa-1.2.2a + // Only filter if the offer is from a nearby agent and if there's no open IM session (doesn't necessarily have to be focused) + if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(info->mFromID)) && + (!RlvUIEnabler::hasOpenIM(info->mFromID)) ) + { + args["NAME"] = RlvStrings::getAnonym(info->mFromName); + } +// [/RLVa:KB] + p.name = "UserGiveItem"; + } + + LLNotifications::instance().add(p); +} + +// Callback for name resolution of a god/estate message +static void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string message) +{ + LLSD args; + args["NAME"] = av_name.getNSName(); + args["MESSAGE"] = message; + LLNotificationsUtil::add("GodMessage", args); + + // Treat like a system message and put in chat history. + chat.mSourceType = CHAT_SOURCE_SYSTEM; + chat.mText = av_name.getNSName() + ": " + message; + + // Claim to be from a local agent so it doesn't go into console. + LLFloaterChat::addChat(chat, false, true); + +} + +static bool parse_lure_bucket(const std::string& bucket, + U64& region_handle, + LLVector3& pos, + LLVector3& look_at, + U8& region_access) +{ + // tokenize the bucket + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("|", "", boost::keep_empty_tokens); + tokenizer tokens(bucket, sep); + tokenizer::iterator iter = tokens.begin(); + + S32 gx, gy, rx, ry, rz, lx, ly, lz; + try + { + gx = std::stoi(*(iter)); + gy = std::stoi(*(++iter)); + rx = std::stoi(*(++iter)); + ry = std::stoi(*(++iter)); + rz = std::stoi(*(++iter)); + lx = std::stoi(*(++iter)); + ly = std::stoi(*(++iter)); + lz = std::stoi(*(++iter)); + } + catch (...) + { + LL_WARNS("parse_lure_bucket") + << "Couldn't parse lure bucket." + << LL_ENDL; + return false; + } + + // Grab region access + region_access = SIM_ACCESS_MIN; + if (++iter != tokens.end()) + { + std::string access_str((*iter).c_str()); + LLStringUtil::trim(access_str); + if (access_str == "A") + { + region_access = SIM_ACCESS_ADULT; + } + else if (access_str == "M") + { + region_access = SIM_ACCESS_MATURE; + } + else if (access_str == "PG") + { + region_access = SIM_ACCESS_PG; + } + } + + pos.setVec((F32)rx, (F32)ry, (F32)rz); + look_at.setVec((F32)lx, (F32)ly, (F32)lz); + + region_handle = to_region_handle(gx, gy); + return true; +} + +static void notification_display_name_callback(const LLUUID& id, + const LLAvatarName& av_name, + const std::string& name, + LLSD& substitutions, + const LLSD& payload) +{ + substitutions["NAME"] = av_name.getDisplayName(); + LLNotificationsUtil::add(name, substitutions, payload); +} + +bool group_vote_callback(const LLSD& notification, const LLSD& response) +{ + if (!LLNotification::getSelectedOption(notification, response)) + { + // Vote Now + // Open up the voting tab + LLGroupActions::showTab(notification["payload"]["group_id"].asUUID(), "voting_tab"); + } + return false; +} +static LLNotificationFunctorRegistration group_vote_callback_reg("GroupVote", group_vote_callback); + +void LLIMProcessing::processNewMessage(const LLUUID& from_id, + BOOL from_group, + const LLUUID& to_id, + U8 offline, + EInstantMessage dialog, // U8 + const LLUUID& session_id, + U32 timestamp, + std::string& name, + std::string& message, + U32 parent_estate_id, + const LLUUID& region_id, + LLVector3 position, + U8 *binary_bucket, + S32 binary_bucket_size, + LLHost &sender, + const LLUUID& aux_id) +{ + LLChat chat; + std::string buffer; + + // make sure that we don't have an empty or all-whitespace name + LLStringUtil::trim(name); + if (name.empty()) + { + name = LLTrans::getString("Unnamed"); + } + + // Preserve the unaltered name for use in group notice mute checking. + std::string original_name = name; + + // IDEVO convert new-style "Resident" names for display + name = clean_name_from_im(name, dialog); + + // + if (region_id.notNull()) + LL_INFOS() << "RegionID: " << region_id.asString() << LL_ENDL; + // + + bool is_do_not_disturb = gAgent.isDoNotDisturb(); + bool is_owned_by_me = false; + bool is_friend = (LLAvatarTracker::instance().getBuddyInfo(from_id) == nullptr) ? false : true; + bool accept_im_from_only_friend = gSavedSettings.getBOOL("InstantMessagesFriendsOnly"); + + chat.mFromID = from_id; + chat.mFromName = name; + chat.mSourceType = (from_id.isNull() || (name == SYSTEM_FROM)) ? CHAT_SOURCE_SYSTEM : + (dialog == IM_FROM_TASK || dialog == IM_FROM_TASK_AS_ALERT) ? CHAT_SOURCE_OBJECT : CHAT_SOURCE_AGENT; + + bool is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat) + // object IMs contain sender object id in session_id (STORM-1209) + || (chat.mSourceType == CHAT_SOURCE_OBJECT && LLMuteList::getInstance()->isMuted(session_id)); + + // Singu Note: Try to get Owner whenever possible, here owner is the from id + if (chat.mSourceType == CHAT_SOURCE_OBJECT && session_id.notNull()) + if (auto obj = gObjectList.findObject(session_id)) obj->mOwnerID = from_id; + + bool is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT && + LLMuteList::getInstance()->isLinden(name); + chat.mMuted = is_muted && !is_linden; + + if (chat.mSourceType == CHAT_SOURCE_SYSTEM) + { // Translate server message if required (MAINT-6109) + translate_if_needed(message); + } + + LLViewerObject *source = gObjectList.findObject(session_id); //Session ID is probably the wrong thing. + if (source || (source = gObjectList.findObject(from_id))) + { + is_owned_by_me = source->permYouOwner(); + } + + // NaCl - Antispam + bool is_spam_filtered(const EInstantMessage& dialog, bool is_friend, bool is_owned_by_me); + if (is_spam_filtered(dialog, is_friend, is_owned_by_me)) return; + // NaCl End + + std::string separator_string(": "); + int message_offset = 0; + + //Handle IRC styled /me messages. + std::string prefix = message.substr(0, 4); + if (prefix == "/me " || prefix == "/me'") + { + chat.mChatStyle = CHAT_STYLE_IRC; + separator_string = ""; + message_offset = 3; + } + + // These bools are here because they would make mess of logic down below in IM_NOTHING_SPECIAL. + static LLCachedControl sAutorespond(gSavedPerAccountSettings, "AutoresponseAnyone", false); + static LLCachedControl sAutorespondFriendsOnly(gSavedPerAccountSettings, "AutoresponseAnyoneFriendsOnly", false); + static LLCachedControl sAutorespondAway(gSavedPerAccountSettings, "AutoresponseOnlyIfAway", false); + static LLCachedControl sAutorespondNonFriend(gSavedPerAccountSettings, "AutoresponseNonFriends", false); + static LLCachedControl sAutorespondMuted(gSavedPerAccountSettings, "AutoresponseMuted", false); + static LLCachedControl sAutorespondRepeat(gSavedPerAccountSettings, "AscentInstantMessageResponseRepeat", false); + static LLCachedControl sFakeAway(gSavedSettings, "FakeAway", false); + bool autorespond_status = !sAutorespondAway || sFakeAway || gAgent.getAFK(); + bool is_autorespond = !is_muted && autorespond_status && (is_friend || !sAutorespondFriendsOnly) && sAutorespond; + bool is_autorespond_muted = is_muted && sAutorespondMuted; + bool is_autorespond_nonfriends = !is_friend && !is_muted && autorespond_status && sAutorespondNonFriend; + + LLSD args; + switch (dialog) + { + case IM_CONSOLE_AND_CHAT_HISTORY: + args["MESSAGE"] = message; + + // Note: don't put the message in the IM history, even though was sent + // via the IM mechanism. + LLNotificationsUtil::add("SystemMessageTip",args); + break; + + case IM_NOTHING_SPECIAL: // p2p IM + // Don't show dialog, just do IM + if (!gAgent.isGodlike() + && gAgent.getRegion()->isPrelude() + && to_id.isNull()) + { + // do nothing -- don't distract newbies in + // Prelude with global IMs + } +// [RLVa:KB] - Checked: 2011-05-28 (RLVa-1.4.0) + else if ( (rlv_handler_t::isEnabled()) && (offline == IM_ONLINE) && ("@version" == message) && + (!is_muted) && ((!accept_im_from_only_friend) || (is_friend)) ) + { + RlvUtil::sendBusyMessage(from_id, RlvStrings::getVersion(), session_id); + // We won't receive a typing stop message, so do that manually (see comment at the end of LLFloaterIMPanel::sendMsg) + gIMMgr->processIMTypingStop(from_id, dialog); + } +// [/RLVa:KB] + else if (offline == IM_ONLINE + && is_do_not_disturb + && !is_muted // Note: Never if muted + && from_id.notNull() //not a system message + && to_id.notNull() //not global message +// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0) + && RlvActions::canReceiveIM(from_id)) +// [/RLVa:KB] + { + // now store incoming IM in chat history + buffer = separator_string + message.substr(message_offset); + + LL_INFOS("Messaging") << "session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; + script_msg_api(from_id.asString() + ", 0"); + + // add to IM panel, but do not bother the user + gIMMgr->addMessage( + session_id, + from_id, + name, + buffer, + name, + dialog, + parent_estate_id, + region_id, + position, + true); + + // pretend this is chat generated by self, so it does not show up on screen + chat.mText = std::string("IM: ") + name + separator_string + message.substr(message_offset); + LLFloaterChat::addChat(chat, true, true); + + if (sAutorespondRepeat || !gIMMgr->hasSession(session_id)) + { + // if the user wants to repeat responses over and over or + // if there is not a panel for this conversation (i.e. it is a new IM conversation + // initiated by the other party) then... + // return a standard "do not disturb" message, but only do it to online IM + // (i.e. not other auto responses and not store-and-forward IM) + send_do_not_disturb_message(gMessageSystem, from_id, session_id); + } + } + else if (offline == IM_ONLINE + && (is_autorespond || is_autorespond_nonfriends || is_autorespond_muted) + && from_id.notNull() //not a system message + && to_id.notNull() //not global message +// [RLVa:LF] - Same as above: Checked: 2010-11-30 (RLVa-1.3.0) + && RlvActions::canReceiveIM(from_id) && RlvActions::canSendIM(from_id)) +// [/RLVa:LF] + { + buffer = separator_string + message.substr(message_offset); + + LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; + if (!is_muted) script_msg_api(from_id.asString() + ", 0"); + + bool send_response = !gIMMgr->hasSession(session_id) || sAutorespondRepeat; + + // add to IM panel, but do not bother the user + gIMMgr->addMessage(session_id, + from_id, + name, + buffer, + name, + dialog, + parent_estate_id, + region_id, + position, + true); + + // pretend this is chat generated by self, so it does not show up on screen + chat.mText = std::string("IM: ") + name + separator_string + message.substr(message_offset); + LLFloaterChat::addChat( chat, TRUE, TRUE ); + + if (send_response) + { + // if there is not a panel for this conversation (i.e. it is a new IM conversation + // initiated by the other party) then... + std::string my_name; + LLAgentUI::buildFullname(my_name); + std::string response; + bool show_autoresponded = false; + LLUUID itemid; + if (is_muted) + { + response = gSavedPerAccountSettings.getString("AutoresponseMutedMessage"); + if (gSavedPerAccountSettings.getBOOL("AutoresponseMutedItem")) + itemid = static_cast(gSavedPerAccountSettings.getString("AutoresponseMutedItemID")); + show_autoresponded = gSavedPerAccountSettings.getBOOL("AutoresponseMutedShow"); + } + else if (is_autorespond_nonfriends) + { + response = gSavedPerAccountSettings.getString("AutoresponseNonFriendsMessage"); + if (gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsItem")) + itemid = static_cast(gSavedPerAccountSettings.getString("AutoresponseNonFriendsItemID")); + show_autoresponded = gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsShow"); + } + else if (is_autorespond) + { + response = gSavedPerAccountSettings.getString("AutoresponseAnyoneMessage"); + if (gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneItem")) + itemid = static_cast(gSavedPerAccountSettings.getString("AutoresponseAnyoneItemID")); + show_autoresponded = gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneShow"); + } + pack_instant_message( + gMessageSystem, + gAgentID, + FALSE, + gAgentSessionID, + from_id, + my_name, + replace_wildcards(response, from_id, name), + IM_ONLINE, + IM_BUSY_AUTO_RESPONSE, + session_id); + gAgent.sendReliableMessage(); + + autoresponder_finish(show_autoresponded, session_id, from_id, name, itemid, is_muted); + } + } + else if (from_id.isNull()) + { + // Messages from "Second Life" ID don't go to IM history + // messages which should be routed to IM window come from a user ID with name=SYSTEM_NAME + chat.mText = name + ": " + message; + LLFloaterChat::addChat(chat, FALSE, FALSE); + } + else if (to_id.isNull()) + { + // Message to everyone from GOD, look up the fullname since + // server always slams name to legacy names + LLAvatarNameCache::get(from_id, boost::bind(god_message_name_cb, _2, chat, message)); + } + else + { + // standard message, not from system + bool mute_im = is_muted; + if (accept_im_from_only_friend && !is_friend && !is_linden) + { + if (!gIMMgr->isNonFriendSessionNotified(session_id)) + { + std::string message = LLTrans::getString("IM_unblock_only_groups_friends"); + gIMMgr->addMessage(session_id, from_id, name, message); + gIMMgr->addNotifiedNonFriendSessionID(session_id); + } + + mute_im = true; + } + + std::string saved; + if(offline == IM_OFFLINE) + { + LLStringUtil::format_map_t args; + args["[LONG_TIMESTAMP]"] = formatted_time(timestamp); + saved = LLTrans::getString("Saved_message", args); + } + else if (!mute_im) script_msg_api(from_id.asString() + ", 0"); + buffer = separator_string + saved + message.substr(message_offset); + + LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; + + // Muted nonfriend code moved up + +// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0) + // Don't block offline IMs, or IMs from Lindens + if ( (rlv_handler_t::isEnabled()) && (offline != IM_OFFLINE) && (!RlvActions::canReceiveIM(from_id)) && (!is_linden) ) + { + if (!mute_im) + RlvUtil::sendBusyMessage(from_id, RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM_REMOTE), session_id); + buffer = RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM); + } +// [/RLVa:KB] + + if (!mute_im || is_linden) + { + gIMMgr->addMessage( + session_id, + from_id, + name, + buffer, + name, + dialog, + parent_estate_id, + region_id, + position, + true); + chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset); + LLFloaterChat::addChat(chat, true, false); + } + else + { + // muted user, so don't start an IM session, just record line in chat + // history. Pretend the chat is from a local agent, + // so it will go into the history but not be shown on screen. + chat.mText = buffer; + LLFloaterChat::addChat(chat, true, true); + + // Autoresponse to muted avatars + if (!gIMMgr->isNonFriendSessionNotified(session_id) && sAutorespondMuted) + { + std::string my_name; + LLAgentUI::buildFullname(my_name); + pack_instant_message( + gMessageSystem, + gAgentID, + FALSE, + gAgentSessionID, + from_id, + my_name, + replace_wildcards(gSavedPerAccountSettings.getString("AutoresponseMutedMessage"), from_id, name), + IM_ONLINE, + IM_BUSY_AUTO_RESPONSE, + session_id); + gAgent.sendReliableMessage(); + autoresponder_finish(gSavedPerAccountSettings.getBOOL("AutoresponseMutedShow"), session_id, from_id, name, gSavedPerAccountSettings.getBOOL("AutoresponseMutedItem") ? static_cast(gSavedPerAccountSettings.getString("AutoresponseMutedItemID")) : LLUUID::null, true); + } + } + } + break; + + case IM_TYPING_START: + { + static LLCachedControl sNotifyIncomingMessage(gSavedSettings, "AscentInstantMessageAnnounceIncoming"); + // Don't announce that someone has started messaging, if they're muted or when in busy mode + if (sNotifyIncomingMessage && + !gIMMgr->hasSession(session_id) && + ((accept_im_from_only_friend && (is_friend || is_linden)) || + (!(is_muted || is_do_not_disturb))) + ) + { + LLAvatarName av_name; + std::string ns_name = LLAvatarNameCache::get(from_id, &av_name) ? av_name.getNSName() : name; + + gIMMgr->addMessage(session_id, + from_id, + name, + llformat("%s ", ns_name.c_str()) + LLTrans::getString("IM_announce_incoming"), + name, + IM_NOTHING_SPECIAL, + parent_estate_id, + region_id, + position, + false); + + + // This block is very similar to the one above, but is necessary, since a session is opened to announce incoming message.. + // In order to prevent doubling up on the first response, We neglect to send this if Repeat for each message is on. + if ((is_autorespond_nonfriends || is_autorespond) && !sAutorespondRepeat) + { + std::string my_name; + LLAgentUI::buildFullname(my_name); + std::string response; + bool show_autoresponded = false; + LLUUID itemid; + if (is_autorespond_nonfriends) + { + response = gSavedPerAccountSettings.getString("AutoresponseNonFriendsMessage"); + if (gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsItem")) + itemid = static_cast(gSavedPerAccountSettings.getString("AutoresponseNonFriendsItemID")); + show_autoresponded = gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsShow"); + } + else if (is_autorespond) + { + response = gSavedPerAccountSettings.getString("AutoresponseAnyoneMessage"); + if (gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneItem")) + itemid = static_cast(gSavedPerAccountSettings.getString("AutoresponseAnyoneItemID")); + show_autoresponded = gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneShow"); + } + pack_instant_message(gMessageSystem, gAgentID, false, gAgentSessionID, from_id, my_name, replace_wildcards(response, from_id, name), IM_ONLINE, IM_BUSY_AUTO_RESPONSE, session_id); + gAgent.sendReliableMessage(); + + autoresponder_finish(show_autoresponded, session_id, from_id, name, itemid, is_muted); + } + } + + gIMMgr->processIMTypingStart(from_id, dialog); + script_msg_api(from_id.asString() + ", 4"); + } + break; + + case IM_TYPING_STOP: + { + gIMMgr->processIMTypingStop(from_id, dialog); + script_msg_api(from_id.asString() + ", 5"); + } + break; + + case IM_MESSAGEBOX: + { + // This is a block, modeless dialog. + args["MESSAGE"] = message; + LLNotificationsUtil::add("SystemMessageTip", args); + } + break; + case IM_GROUP_NOTICE: + case IM_GROUP_NOTICE_REQUESTED: + { + LL_INFOS("Messaging") << "Received IM_GROUP_NOTICE message." << LL_ENDL; + + LLUUID agent_id; + U8 has_inventory; + U8 asset_type = 0; + LLUUID group_id; + std::string item_name; + + if (aux_id.notNull()) + { + // aux_id contains group id, binary bucket contains name and asset type + group_id = aux_id; + has_inventory = binary_bucket_size > 1 ? TRUE : FALSE; + from_group = TRUE; // inaccurate value correction + if (has_inventory) + { + std::string str_bucket = ll_safe_string((char*)binary_bucket, binary_bucket_size); + + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("|", "", boost::keep_empty_tokens); + tokenizer tokens(str_bucket, sep); + tokenizer::iterator iter = tokens.begin(); + + asset_type = (LLAssetType::EType)(atoi((*(iter++)).c_str())); + iter++; // wearable type if applicable, otherwise asset type + item_name = std::string((*(iter++)).c_str()); + // Note There is more elements in 'tokens' ... + + + for (int i = 0; i < 6; i++) + { + LL_WARNS() << *(iter++) << LL_ENDL; + iter++; + } + } + } + else + { + // All info is in binary bucket, read it for more information. + struct notice_bucket_header_t + { + U8 has_inventory; + U8 asset_type; + LLUUID group_id; + }; + struct notice_bucket_full_t + { + struct notice_bucket_header_t header; + U8 item_name[DB_INV_ITEM_NAME_BUF_SIZE]; + }*notice_bin_bucket; + + // Make sure the binary bucket is big enough to hold the header + // and a null terminated item name. + if ((binary_bucket_size < (S32)((sizeof(notice_bucket_header_t) + sizeof(U8)))) + || (binary_bucket[binary_bucket_size - 1] != '\0')) + { + LL_WARNS("Messaging") << "Malformed group notice binary bucket" << LL_ENDL; + break; + } + + notice_bin_bucket = (struct notice_bucket_full_t*) &binary_bucket[0]; + has_inventory = notice_bin_bucket->header.has_inventory; + asset_type = notice_bin_bucket->header.asset_type; + group_id = notice_bin_bucket->header.group_id; + item_name = ll_safe_string((const char*)notice_bin_bucket->item_name); + } + + if (group_id != from_id) + { + agent_id = from_id; + } + else + { + std::string::size_type index = original_name.find(" Resident"); + if (index != std::string::npos) + { + original_name = original_name.substr(0, index); + } + + // The group notice packet does not have an AgentID. Obtain one from the name cache. + // If last name is "Resident" strip it out so the cache name lookup works. + std::string legacy_name = gCacheName->buildLegacyName(original_name); + gCacheName->getUUID(legacy_name, agent_id); + + if (agent_id.isNull()) + { + LL_WARNS("Messaging") << "buildLegacyName returned null while processing " << original_name << LL_ENDL; + } + } + + if (agent_id.notNull() && LLMuteList::getInstance()->isMuted(agent_id)) + { + break; + } + + // If there is inventory, give the user the inventory offer. + LLOfferInfo* info = nullptr; + + if (has_inventory) + { + info = new LLOfferInfo(); + + info->mIM = IM_GROUP_NOTICE; + info->mFromID = from_id; + info->mFromGroup = true; + info->mFromObject = false; + info->mTransactionID = session_id; + info->mType = (LLAssetType::EType) asset_type; + info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType)); + info->mFromName = LLTrans::getString("AGroupMemberNamed", LLSD().with("GROUP_ID", group_id).with("FROM_ID", from_id)); + info->mDesc = item_name; + info->mHost = sender; + } + + // Tokenize the string. + // TODO: Support escaped tokens ("||" -> "|") + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("|", "", boost::keep_empty_tokens); + tokenizer tokens(message, sep); + tokenizer::iterator iter = tokens.begin(); + + std::string subj(*iter++); + std::string mes(*iter++); + + // Send the notification down the new path. + // For requested notices, we don't want to send the popups. + if (dialog != IM_GROUP_NOTICE_REQUESTED) + { + LLSD payload; + payload["subject"] = subj; + payload["message"] = mes; + payload["sender_name"] = name; + payload["sender_id"] = agent_id; + payload["group_id"] = group_id; + payload["inventory_name"] = item_name; + payload["received_time"] = LLDate::now(); + if (info && info->asLLSD()) + { + payload["inventory_offer"] = info->asLLSD(); + } + + LLSD args; + args["SUBJECT"] = subj; + args["MESSAGE"] = mes; + LLDate notice_date = LLDate(timestamp).notNull() ? LLDate(timestamp) : LLDate::now(); + LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).timestamp(notice_date)); + } + + // Also send down the old path for now. + if (IM_GROUP_NOTICE_REQUESTED == dialog) + { + LLGroupActions::showNotice(subj,mes,group_id,has_inventory,item_name,info); + } + else + { + delete info; + } + } + break; + case IM_GROUP_INVITATION: + { + if (!is_muted) + { + // group is not blocked, but we still need to check agent that sent the invitation + // and we have no agent's id + // Note: server sends username "first.last". + size_t index = original_name.find(" Resident"); + if (index != std::string::npos) + { + original_name = original_name.substr(0, index); + } + std::string legacy_name = gCacheName->buildLegacyName(original_name); + LLUUID agent_id; + gCacheName->getUUID(legacy_name, agent_id); + if (agent_id.isNull()) + { + LL_WARNS("Messaging") << "buildLegacyName returned null while processing " << original_name << LL_ENDL; + } + else + { + is_muted |= (bool) LLMuteList::getInstance()->isMuted(agent_id); + } + } + //if (is_do_not_disturb || is_muted) + if (is_muted) return; + if (is_do_not_disturb) + { + send_do_not_disturb_message(gMessageSystem, from_id); + } + + //if (!is_muted) + { + LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL; + // Read the binary bucket for more information. + struct invite_bucket_t + { + S32 membership_fee; + LLUUID role_id; + }* invite_bucket; + + // Make sure the binary bucket is the correct size. + if (binary_bucket_size != sizeof(invite_bucket_t)) + { + LL_WARNS("Messaging") << "Malformed group invite binary bucket" << LL_ENDL; + break; + } + + invite_bucket = (struct invite_bucket_t*) &binary_bucket[0]; + S32 membership_fee = ntohl(invite_bucket->membership_fee); + // NaCl - Antispam + if (membership_fee > 0 && gSavedSettings.getBOOL("AntiSpamGroupFeeInvites")) + return; + // NaCl End + + LLSD payload; + payload["transaction_id"] = session_id; + payload["group_id"] = from_group ? from_id : aux_id; + payload["name"] = name; + payload["message"] = message; + payload["fee"] = membership_fee; + payload["use_offline_cap"] = session_id.isNull() && (offline == IM_OFFLINE); + + LLSD args; + args["MESSAGE"] = message; + // we shouldn't pass callback functor since it is registered in LLFunctorRegistration + LLNotificationsUtil::add("JoinGroup", args, payload); + } + } + break; + + case IM_INVENTORY_OFFERED: + case IM_TASK_INVENTORY_OFFERED: + // Someone has offered us some inventory. + { + LLOfferInfo* info = new LLOfferInfo; + if (IM_INVENTORY_OFFERED == dialog) + { + struct offer_agent_bucket_t + { + S8 asset_type; + LLUUID object_id; + }* bucketp; + + if (sizeof(offer_agent_bucket_t) != binary_bucket_size) + { + LL_WARNS("Messaging") << "Malformed inventory offer from agent" << LL_ENDL; + delete info; + break; + } + bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0]; + info->mType = (LLAssetType::EType) bucketp->asset_type; + info->mObjectID = bucketp->object_id; + info->mFromObject = FALSE; + } + else // IM_TASK_INVENTORY_OFFERED + { + if (sizeof(S8) == binary_bucket_size) + { + info->mType = (LLAssetType::EType) binary_bucket[0]; + } + else + { + /*RIDER*/ // The previous version of the protocol returned the wrong binary bucket... we + // still might be able to figure out the type... even though the offer is not retrievable. + + // Should be safe to remove once DRTSIM-451 fully deploys + std::string str_bucket(reinterpret_cast(binary_bucket)); + std::string str_type(str_bucket.substr(0, str_bucket.find('|'))); + + std::stringstream type_convert(str_type); + + S32 type; + type_convert >> type; + + // We could try AT_UNKNOWN which would be more accurate, but that causes an auto decline + info->mType = static_cast(type); + // Don't break in the case of a bad binary bucket. Go ahead and show the + // accept/decline popup even though it will not do anything. + LL_WARNS("Messaging") << "Malformed inventory offer from object, type might be " << info->mType << LL_ENDL; + } + info->mObjectID = LLUUID::null; + info->mFromObject = TRUE; + } + + info->mIM = dialog; + info->mFromID = from_id; + info->mFromGroup = from_group; + info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType)); + + info->mTransactionID = session_id.notNull() ? session_id : aux_id; + + info->mFromName = name; + info->mDesc = message; + info->mHost = sender; + //if (((is_do_not_disturb && !is_owned_by_me) || is_muted)) + if (is_muted) + { + // Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331) + if (IM_INVENTORY_OFFERED == dialog) + { + LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID); + fetch_item->startFetch(); + delete fetch_item; + // Same as closing window + info->forceResponse(IOR_DECLINE); + } + else + { + info->forceResponse(IOR_MUTE); + } + } + /* Singu Note: Handle this inside inventory_offer_handler so if the user wants to autoaccept offers, they can while busy. + // old logic: busy mode must not affect interaction with objects (STORM-565) + // new logic: inventory offers from in-world objects should be auto-declined (CHUI-519) + // Singu Note: We should use old logic + else if (is_do_not_disturb && dialog != IM_TASK_INVENTORY_OFFERED) // busy mode must not affect interaction with objects (STORM-565) + { + // Until throttling is implemented, do not disturb mode should reject inventory instead of silently + // accepting it. SEE SL-39554 + info->forceResponse(IOR_DECLINE); + } + */ + else + { + inventory_offer_handler(info, is_friend, is_owned_by_me); + } + } + break; + + case IM_INVENTORY_ACCEPTED: + { +// args["NAME"] = LLAvatarActions::getSLURL(from_id); +// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Modified: RLVa-1.2.2a + // Only anonymize the name if the agent is nearby, there isn't an open IM session to them and their profile isn't open + bool fRlvFilterName = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(from_id)) && + (!RlvUIEnabler::hasOpenProfile(from_id)) && (!RlvUIEnabler::hasOpenIM(from_id)); + args["NAME"] = (!fRlvFilterName) ? LLAvatarActions::getSLURL(from_id) : RlvStrings::getAnonym(name); +// [/RLVa:KB] + LLNotificationsUtil::add("InventoryAccepted", args); + break; + } + case IM_INVENTORY_DECLINED: + { +// args["NAME"] = LLAvatarActions::getSLURL(from_id); +// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Modified: RLVa-1.2.2a + // Only anonymize the name if the agent is nearby, there isn't an open IM session to them and their profile isn't open + bool fRlvFilterName = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(from_id)) && + (!RlvUIEnabler::hasOpenProfile(from_id)) && (!RlvUIEnabler::hasOpenIM(from_id)); + args["NAME"] = (!fRlvFilterName) ? LLAvatarActions::getSLURL(from_id) : RlvStrings::getAnonym(name); +// [/RLVa:KB] + LLNotificationsUtil::add("InventoryDeclined", args); + break; + } + // TODO: _DEPRECATED suffix as part of vote removal - DEV-24856 + case IM_GROUP_VOTE: + { + LLSD args; + args["NAME"] = name; + args["MESSAGE"] = message; + + LLSD payload; + payload["group_id"] = session_id; + LLNotificationsUtil::add("GroupVote", args, payload); + } + break; + + case IM_GROUP_ELECTION_DEPRECATED: + { + LL_WARNS("Messaging") << "Received IM: IM_GROUP_ELECTION_DEPRECATED" << LL_ENDL; + } + break; + + case IM_FROM_TASK: + { + if (is_do_not_disturb && !is_owned_by_me) + { + return; + } + chat.mText = name + separator_string + message.substr(message_offset); + chat.mFromName = name; + + // Build a link to open the object IM info window. + std::string location = ll_safe_string((char*)binary_bucket, binary_bucket_size-1); + + if (session_id.notNull()) + { + chat.mFromID = session_id; + } + else + { + // This message originated on a region without the updated code for task id and slurl information. + // We just need a unique ID for this object that isn't the owner ID. + // If it is the owner ID it will overwrite the style that contains the link to that owner's profile. + // This isn't ideal - it will make 1 style for all objects owned by the the same person/group. + // This works because the only thing we can really do in this case is show the owner name and link to their profile. + chat.mFromID = from_id ^ gAgent.getSessionID(); + } + + chat.mSourceType = CHAT_SOURCE_OBJECT; + + // To conclude that the source type of message is CHAT_SOURCE_SYSTEM it's not + // enough to check only from name (i.e. fromName = "Second Life"). For example + // source type of messages from objects called "Second Life" should not be CHAT_SOURCE_SYSTEM. + bool chat_from_system = (SYSTEM_FROM == name) && region_id.isNull() && position.isNull(); + if (chat_from_system) + { + // System's UUID is NULL (fixes EXT-4766) + chat.mFromID = LLUUID::null; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + } + else script_msg_api(chat.mFromID.asString() + ", 6"); + + // IDEVO Some messages have embedded resident names + message = clean_name_from_task_im(message, from_group); + + LLSD query_string; + query_string["owner"] = from_id; +// [RLVa:KB] - Checked: 2010-04-22 (RLVa-1.2.0f) | Added: RLVa-1.2.0f + if (rlv_handler_t::isEnabled()) + { + // NOTE: the chat message itself will be filtered in LLNearbyChatHandler::processChat() + if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) || gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) && (!from_group) && (RlvUtil::isNearbyAgent(from_id)) ) + { + query_string["rlv_shownames"] = TRUE; + + RlvUtil::filterNames(name); + chat.mFromName = name; + } + if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) + { + std::string::size_type idxPos = location.find('/'); + if ( (std::string::npos != idxPos) && (RlvUtil::isNearbyRegion(location.substr(0, idxPos))) ) + location = RlvStrings::getString(RLV_STRING_HIDDEN_REGION); + } + } +// [/RLVa:KB] + query_string["slurl"] = location; + query_string["name"] = name; + if (from_group) + { + query_string["groupowned"] = "true"; + } + +// chat.mURL = LLSLURL("objectim", session_id, "").getSLURLString(); +// [SL:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Added: RLVa-1.2.2a + chat.mURL = LLSLURL("objectim", session_id, LLURI::mapToQueryString(query_string)).getSLURLString(); +// [/SL:KB] + chat.mText = name + separator_string + message.substr(message_offset); + + // Note: lie to Nearby Chat, pretending that this is NOT an IM, because + // IMs from objects don't open IM sessions. + LLFloaterChat::addChat(chat, FALSE, FALSE); + } + break; + + case IM_SESSION_SEND: // ad-hoc or group IMs + { + if (!is_linden && is_do_not_disturb) return; + + // Only show messages if we have a session open (which + // should happen after you get an "invitation" +// if ( !gIMMgr->hasSession(session_id) ) +// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c + LLFloaterIMPanel* pIMFloater = gIMMgr->findFloaterBySession(session_id); + if (!pIMFloater) + { + return; + } + + if (from_id != gAgentID && (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM) || gRlvHandler.hasBehaviour(RLV_BHVR_RECVIMFROM))) + { + switch (pIMFloater->getSessionType()) + { + case LLFloaterIMPanel::GROUP_SESSION: // Group chat + if (!RlvActions::canReceiveIM(session_id)) + return; + break; + case LLFloaterIMPanel::ADHOC_SESSION: // Conference chat + if (!RlvActions::canReceiveIM(from_id)) + message = RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM); + break; + default: + RLV_ASSERT(false); + return; + } + } +// [/RLVa:KB] + + // standard message, not from system + std::string saved; + if (offline == IM_OFFLINE) + { + LLStringUtil::format_map_t args; + args["[LONG_TIMESTAMP]"] = formatted_time(timestamp); + saved = LLTrans::getString("Saved_message", args); + } + buffer = separator_string + saved + message.substr(message_offset); + + LL_DEBUGS("Messaging") << "standard message session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; + + gIMMgr->addMessage( + session_id, + from_id, + name, + buffer, + ll_safe_string((char*)binary_bucket), + IM_SESSION_INVITE, + parent_estate_id, + region_id, + position, + true); + + std::string prepend_msg; + if (gAgent.isInGroup(session_id)&& gSavedSettings.getBOOL("OptionShowGroupNameInChatIM")) + { + prepend_msg = '['; + prepend_msg += std::string((char*)binary_bucket); + prepend_msg += "] "; + } + else + { + prepend_msg = std::string("IM: "); + } + chat.mText = prepend_msg + name + separator_string + saved + message.substr(message_offset); + LLFloaterChat::addChat(chat, TRUE, from_id == gAgentID); + + break; + } + case IM_FROM_TASK_AS_ALERT: + if (is_do_not_disturb && !is_owned_by_me) + { + return; + } + { + // Construct a viewer alert for this message. + args["NAME"] = name; + args["MESSAGE"] = message; + LLNotificationsUtil::add("ObjectMessage", args); + } + break; + case IM_BUSY_AUTO_RESPONSE: + if (is_muted) + { + LL_DEBUGS("Messaging") << "Ignoring do-not-disturb response from " << from_id << LL_ENDL; + return; + } + else + { + gIMMgr->addMessage(session_id, from_id, name, separator_string + message.substr(message_offset), name, dialog, parent_estate_id, region_id, position, true); + } + break; + + case IM_LURE_USER: + case IM_TELEPORT_REQUEST: + { + // [RLVa:KB] - Checked: RLVa-1.4.9 + // If we auto-accept the offer/request then this will override DnD status (but we'll still let the other party know later) + bool fRlvAutoAccept = (rlv_handler_t::isEnabled()) && + ( ((IM_LURE_USER == dialog) && (RlvActions::autoAcceptTeleportOffer(from_id))) || + ((IM_TELEPORT_REQUEST == dialog) && (RlvActions::autoAcceptTeleportRequest(from_id))) ); +// [/RLVa:KB] + + bool following = gAgent.getAutoPilotLeaderID() == from_id; + + if (!following && is_muted) + { + return; + } +// else if (!following && is_do_not_disturb) +// [RLVa:KB] - Checked: 2013-11-08 (RLVa-1.4.9) + else if (!following && is_do_not_disturb && !fRlvAutoAccept ) +// [/RLVa:KB] + { + send_do_not_disturb_message(gMessageSystem, from_id); + } + else + { +// if (!following && is_do_not_disturb) +// [RLVa:KB] - Checked: RLVa-1.4.9 + if (!following && (is_do_not_disturb) && (!fRlvAutoAccept) ) +// [/RLVa:KB] + { + send_do_not_disturb_message(gMessageSystem, from_id); + } + + LLVector3 pos, look_at; + U64 region_handle(0); + U8 region_access(SIM_ACCESS_MIN); + std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size); + std::string region_access_str = LLStringUtil::null; + std::string region_access_icn = LLStringUtil::null; + std::string region_access_lc = LLStringUtil::null; + + bool canUserAccessDstRegion = true; + bool doesUserRequireMaturityIncrease = false; + + // Do not parse the (empty) lure bucket for TELEPORT_REQUEST + if (IM_TELEPORT_REQUEST != dialog && parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) + { + region_access_str = LLViewerRegion::accessToString(region_access); + region_access_icn = LLViewerRegion::getAccessIcon(region_access); + region_access_lc = region_access_str; + LLStringUtil::toLower(region_access_lc); + + if (!gAgent.isGodlike()) + { + switch (region_access) + { + case SIM_ACCESS_MIN: + case SIM_ACCESS_PG: + break; + case SIM_ACCESS_MATURE: + if (gAgent.isTeen()) + { + canUserAccessDstRegion = false; + } + else if (gAgent.prefersPG()) + { + doesUserRequireMaturityIncrease = true; + } + break; + case SIM_ACCESS_ADULT: + if (!gAgent.isAdult()) + { + canUserAccessDstRegion = false; + } + else if (!gAgent.prefersAdult()) + { + doesUserRequireMaturityIncrease = true; + } + break; + default: + llassert(0); + break; + } + } + } + +// [RLVa:KB] - Checked: RLVa-1.4.9 + if (rlv_handler_t::isEnabled()) + { + if ( ((IM_LURE_USER == dialog) && (!RlvActions::canAcceptTpOffer(from_id))) || + ((IM_TELEPORT_REQUEST == dialog) && (!RlvActions::canAcceptTpRequest(from_id))) ) + { + RlvUtil::sendBusyMessage(from_id, RlvStrings::getString(RLV_STRING_BLOCKED_TPLUREREQ_REMOTE)); + if (is_do_not_disturb) + send_do_not_disturb_message(gMessageSystem, from_id); + return; + } + + // Censor message if: 1) restricted from receiving IMs from the sender, or 2) teleport offer/request and @showloc=n restricted + if ( (!RlvActions::canReceiveIM(from_id)) || + ((gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) && (IM_LURE_USER == dialog || IM_TELEPORT_REQUEST == dialog)) ) + { + message = RlvStrings::getString(RLV_STRING_HIDDEN); + } + } +// [/RLVa:KB] + + LLSD args; + // *TODO: Translate -> [FIRST] [LAST] (maybe) + args["NAME"] = LLAvatarActions::getSLURL(from_id); + args["MESSAGE"] = message; + args["MATURITY_STR"] = region_access_str; + args["MATURITY_ICON"] = region_access_icn; + args["REGION_CONTENT_MATURITY"] = region_access_lc; + LLSD payload; + payload["from_id"] = from_id; + payload["lure_id"] = session_id; + payload["godlike"] = FALSE; + payload["region_maturity"] = region_access; + + /* Singu TODO: Figure if we should use these + if (!canUserAccessDstRegion) + { + LLNotification::Params params("TeleportOffered_MaturityBlocked"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add(params, from_id, false); + send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id); + send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id); + } + else if (doesUserRequireMaturityIncrease) + { + LLNotification::Params params("TeleportOffered_MaturityExceeded"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add(params, from_id, false); + } + else + */ + { + /* Singu Note: No default constructor for LLNotification::Params + LLNotification::Params params; + if (IM_LURE_USER == dialog) + { + params.name = "TeleportOffered"; + params.functor_name = "TeleportOffered"; + } + else if (IM_TELEPORT_REQUEST == dialog) + { + params.name = "TeleportRequest"; + params.functor_name = "TeleportRequest"; + } + */ + LLNotification::Params params(IM_LURE_USER == dialog ? "TeleportOffered" : "TeleportRequest"); + params.substitutions = args; + params.payload = payload; + + if (following) + { + LLNotifications::instance().forceResponse(LLNotification::Params(params.name).payload(payload), 0); + } + else +// [RLVa:KB] - Checked: 20103-11-08 (RLVa-1.4.9) + if ( (rlv_handler_t::isEnabled()) && (fRlvAutoAccept) ) + { + if (IM_LURE_USER == dialog) + gRlvHandler.setCanCancelTp(false); + if (is_do_not_disturb) + send_do_not_disturb_message(gMessageSystem, from_id); + LLNotifications::instance().forceResponse(LLNotification::Params(params.name).payload(payload), 0); + } + else + { + LLNotifications::instance().add(params); + + // + if (IM_LURE_USER == dialog) + gAgent.showLureDestination(LLAvatarActions::getSLURL(from_id), region_handle, pos.mV[VX], pos.mV[VY], pos.mV[VZ]); + script_msg_api(from_id.asString().append(IM_LURE_USER == dialog ? ", 2" : ", 3")); + // + } +// [/RLVa:KB] +// LLNotifications::instance().add(params); + } + } + } + break; + + case IM_GODLIKE_LURE_USER: + { + LLVector3 pos, look_at; + U64 region_handle(0); + U8 region_access(SIM_ACCESS_MIN); + std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size); + std::string region_access_str = LLStringUtil::null; + std::string region_access_icn = LLStringUtil::null; + std::string region_access_lc = LLStringUtil::null; + + bool canUserAccessDstRegion = true; + bool doesUserRequireMaturityIncrease = false; + + if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) + { + region_access_str = LLViewerRegion::accessToString(region_access); + region_access_icn = LLViewerRegion::getAccessIcon(region_access); + region_access_lc = region_access_str; + LLStringUtil::toLower(region_access_lc); + + if (!gAgent.isGodlike()) + { + switch (region_access) + { + case SIM_ACCESS_MIN: + case SIM_ACCESS_PG: + break; + case SIM_ACCESS_MATURE: + if (gAgent.isTeen()) + { + canUserAccessDstRegion = false; + } + else if (gAgent.prefersPG()) + { + doesUserRequireMaturityIncrease = true; + } + break; + case SIM_ACCESS_ADULT: + if (!gAgent.isAdult()) + { + canUserAccessDstRegion = false; + } + else if (!gAgent.prefersAdult()) + { + doesUserRequireMaturityIncrease = true; + } + break; + default: + llassert(0); + break; + } + } + } + + LLSD args; + // *TODO: Translate -> [FIRST] [LAST] (maybe) + args["NAME"] = LLAvatarActions::getSLURL(from_id); + args["MESSAGE"] = message; + args["MATURITY_STR"] = region_access_str; + args["MATURITY_ICON"] = region_access_icn; + args["REGION_CONTENT_MATURITY"] = region_access_lc; + LLSD payload; + payload["from_id"] = from_id; + payload["lure_id"] = session_id; + payload["godlike"] = TRUE; + payload["region_maturity"] = region_access; + + /*if (!canUserAccessDstRegion) + { + LLNotification::Params params("TeleportOffered_MaturityBlocked"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add(params, from_id, false); + send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id); + send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id); + } + else if (doesUserRequireMaturityIncrease) + { + LLNotification::Params params("TeleportOffered_MaturityExceeded"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add(params, from_id, false); + } + else*/ + { + // do not show a message box, because you're about to be + // teleported. + LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0); + } + } + break; + + case IM_GOTO_URL: + { + LLSD args; + // n.b. this is for URLs sent by the system, not for + // URLs sent by scripts (i.e. llLoadURL) + if (binary_bucket_size <= 0) + { + LL_WARNS("Messaging") << "bad binary_bucket_size: " + << binary_bucket_size + << " - aborting function." << LL_ENDL; + return; + } + + std::string url; + + url.assign((char*)binary_bucket, binary_bucket_size-1); + args["MESSAGE"] = message; + args["URL"] = url; + LLSD payload; + payload["url"] = url; + LLNotificationsUtil::add("GotoURL", args, payload); + } + break; + + case IM_FRIENDSHIP_OFFERED: + { + LLSD payload; + payload["from_id"] = from_id; + payload["session_id"] = session_id; + payload["online"] = (offline == IM_ONLINE); + payload["sender"] = sender.getIPandPort(); + + if (is_muted) + { + LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1); + } + else + { + if (is_do_not_disturb) + { + send_do_not_disturb_message(gMessageSystem, from_id); + } + args["[NAME_SLURL]"] = LLAvatarActions::getSLURL(from_id); + if (message.empty()) + { + //support for frienship offers from clients before July 2008 + LLNotificationsUtil::add("OfferFriendshipNoMessage", args, payload); + } + else + { + args["[MESSAGE]"] = message; + LLNotificationsUtil::add("OfferFriendship", args, payload); + } + } + } + break; + + case IM_FRIENDSHIP_ACCEPTED: + { + // In the case of an offline IM, the formFriendship() may be extraneous + // as the database should already include the relationship. But it + // doesn't hurt for dupes. + LLAvatarTracker::formFriendship(from_id); + + std::vector strings; + strings.push_back(from_id.asString()); + send_generic_message("requestonlinenotification", strings); + + args["NAME"] = LLAvatarActions::getSLURL(from_id); + LLSD payload; + payload["from_id"] = from_id; + LLAvatarNameCache::get(from_id, boost::bind(¬ification_display_name_callback, _1, _2, "FriendshipAccepted", args, payload)); + } + break; + + case IM_FRIENDSHIP_DECLINED_DEPRECATED: + default: + LL_WARNS("Messaging") << "Instant message calling for unknown dialog " + << (S32)dialog << LL_ENDL; + break; + } + + LLWindow* viewer_window = gViewerWindow->getWindow(); + if (viewer_window && viewer_window->getMinimized() && gSavedSettings.getBOOL("LiruFlashWhenMinimized")) + { + viewer_window->flashIcon(5.f); + } +} + +void LLIMProcessing::requestOfflineMessages() +{ + static BOOL requested = FALSE; + if (!requested + && gMessageSystem + && LLMuteList::getInstance()->isLoaded() + && isAgentAvatarValid() + && gAgent.getRegion() + && gAgent.getRegion()->capabilitiesReceived()) + { + std::string cap_url = gAgent.getRegionCapability("ReadOfflineMsgs"); + + // Auto-accepted inventory items may require the avatar object + // to build a correct name. Likewise, inventory offers from + // muted avatars require the mute list to properly mute. + if (cap_url.empty() + || gAgent.getRegionCapability("AcceptFriendship").empty() + || gAgent.getRegionCapability("AcceptGroupInvite").empty()) + { + // Offline messages capability provides no session/transaction ids for message AcceptFriendship and IM_GROUP_INVITATION to work + // So make sure we have the caps before using it. + requestOfflineMessagesLegacy(); + } + else + { + LLHTTPClient::get(cap_url, new LLCoroResponder( + LLIMProcessing::requestOfflineMessagesCoro)); + } + requested = TRUE; + } +} + +void LLIMProcessing::requestOfflineMessagesCoro(const LLCoroResponder& responder) +{ + if (LLApp::isQuitting() || !gAgent.getRegion()) + { + return; + } + + auto status = responder.getStatus(); + + if (!responder.isGoodStatus(status)) // success = httpResults["success"].asBoolean(); + { + LL_WARNS("Messaging") << "Error requesting offline messages via capability " << responder.getURL() << ", Status: " << status << ", Reason: " << responder.getReason() << "\nFalling back to legacy method." << LL_ENDL; + + requestOfflineMessagesLegacy(); + return; + } + + const auto& contents = responder.getContent(); + + if (!contents.size()) + { + LL_WARNS("Messaging") << "No contents received for offline messages via capability " << responder.getURL() << LL_ENDL; + return; + } + + // Todo: once dirtsim-369 releases, remove one of the map/array options + LLSD messages; + if (contents.isArray()) + { + messages = *contents.beginArray(); + } + else if (contents.has("messages")) + { + messages = contents["messages"]; + } + else + { + LL_WARNS("Messaging") << "Invalid offline message content received via capability " << responder.getURL() << LL_ENDL; + return; + } + + if (!messages.isArray()) + { + LL_WARNS("Messaging") << "Invalid offline message content received via capability " << responder.getURL() << LL_ENDL; + return; + } + + if (messages.emptyArray()) + { + // Nothing to process + return; + } + + LL_INFOS("Messaging") << "Processing offline messages." << LL_ENDL; + + LLHost sender = gAgent.getRegion()->getHost(); + + LLSD::array_iterator i = messages.beginArray(); + LLSD::array_iterator iEnd = messages.endArray(); + for (; i != iEnd; ++i) + { + const LLSD &message_data(*i); + + /* RIDER: Many fields in this message are using a '_' rather than the standard '-'. This + * should be changed but would require tight coordination with the simulator. + */ + LLVector3 position; + if (message_data.has("position")) + { + position.setValue(message_data["position"]); + } + else + { + position.set(message_data["local_x"].asReal(), message_data["local_y"].asReal(), message_data["local_z"].asReal()); + } + + std::vector bin_bucket; + if (message_data.has("binary_bucket")) + { + bin_bucket = message_data["binary_bucket"].asBinary(); + } +#if 0 + else + { + bin_bucket.push_back(0); + } +#endif + // Todo: once drtsim-451 releases, remove the string option + BOOL from_group; + if (message_data["from_group"].isInteger()) + { + from_group = message_data["from_group"].asInteger(); + } + else + { + from_group = message_data["from_group"].asString() == "Y"; + } + + auto agentName = message_data["from_agent_name"].asString(); + auto message = message_data["message"].asString(); + LLIMProcessing::processNewMessage( + message_data["from_agent_id"].asUUID(), + from_group, + message_data["to_agent_id"].asUUID(), + message_data.has("offline") ? static_cast(message_data["offline"].asInteger()) : IM_OFFLINE, + static_cast(message_data["dialog"].asInteger()), + message_data["transaction-id"].asUUID(), + static_cast(message_data["timestamp"].asInteger()), + agentName, + message, + message_data.has("parent_estate_id") ? static_cast(message_data["parent_estate_id"].asInteger()) : 1U, // 1 - IMMainland + message_data["region_id"].asUUID(), + position, + bin_bucket.data(), + bin_bucket.size(), + sender, + message_data["asset_id"].asUUID()); // not necessarily an asset + } +} + +void LLIMProcessing::requestOfflineMessagesLegacy() +{ + LL_INFOS("Messaging") << "Requesting offline messages (Legacy)." << LL_ENDL; + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RetrieveInstantMessages); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); +} + diff --git a/indra/newview/llimprocessing.h b/indra/newview/llimprocessing.h new file mode 100644 index 0000000000..c8cc47f494 --- /dev/null +++ b/indra/newview/llimprocessing.h @@ -0,0 +1,68 @@ +/** +* @file LLIMMgr.h +* @brief Container for Instant Messaging +* +* $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_LLIMPROCESSING_H +#define LL_LLIMPROCESSING_H + +#include "llinstantmessage.h" + +struct LLCoroResponder; + +std::string replace_wildcards(std::string input, const LLUUID& id, const std::string& name); +bool handle_obj_auth(const LLUUID& from_id, const std::string& mesg); + +class LLIMProcessing +{ +public: + // Pre-process message for IM manager + static void processNewMessage(const LLUUID& from_id, + BOOL from_group, + const LLUUID& to_id, + U8 offline, + EInstantMessage dialog, // U8 + const LLUUID& session_id, + U32 timestamp, + std::string& agentName, + std::string& message, + U32 parent_estate_id, + const LLUUID& region_id, + LLVector3 position, + U8 *binary_bucket, + S32 binary_bucket_size, + LLHost &sender, + const LLUUID& aux_id = LLUUID::null); + + // Either receives list of offline messages from 'ReadOfflineMsgs' capability + // or uses legacy method + static void requestOfflineMessages(); + +private: + static void requestOfflineMessagesCoro(const LLCoroResponder& responder); + static void requestOfflineMessagesLegacy(); +}; + + +#endif // LL_LLLLIMPROCESSING_H diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c36143d499..351cdaadfe 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -45,10 +45,12 @@ #include "llagent.h" #include "llagentcamera.h" +#include "llagentui.h" #include "llavataractions.h" #include "llavatarnamecache.h" #include "llfloaterchat.h" #include "llfloaterchatterbox.h" +#include "llgroupactions.h" #include "llimpanel.h" #include "llmutelist.h" #include "llspeakers.h" @@ -615,7 +617,7 @@ LLUUID LLIMMgr::addSession( LLFloaterIMPanel* floater = findFloaterBySession(session_id); if(!floater) { - std::vector ids; + uuid_vec_t ids; ids.push_back(other_participant_id); floater = createFloater(session_id, other_participant_id, name, dialog, ids, true); @@ -659,7 +661,7 @@ LLUUID LLIMMgr::addSession( const std::string& name, EInstantMessage dialog, const LLUUID& other_participant_id, - const std::vector& ids) + const uuid_vec_t& ids) { if (0 == ids.size()) { @@ -791,43 +793,19 @@ void LLIMMgr::inviteToSession( if ( !mPendingInvitations.has(session_id.asString()) ) { - if (caller_name.empty()) - { - gCacheName->get(caller_id, true, // voice - boost::bind(&LLIMMgr::onInviteNameLookup, _1, _2, _3, payload)); - } - else - { - LLSD args; - args["NAME"] = caller_name; - args["GROUP"] = session_name; + LLSD args; + args["NAME"] = LLAvatarActions::getSLURL(caller_id); + args["GROUP"] = LLGroupActions::getSLURL(session_id); - LLNotifications::instance().add(notify_box_type, - args, - payload, - &inviteUserResponse); + LLNotifications::instance().add(notify_box_type, + args, + payload, + &inviteUserResponse); - } mPendingInvitations[session_id.asString()] = LLSD(); } } -//static -void LLIMMgr::onInviteNameLookup(const LLUUID& id, const std::string& full_name, bool is_group, LLSD payload) -{ - payload["caller_name"] = full_name; - payload["session_name"] = full_name; - - LLSD args; - args["NAME"] = full_name; - - LLNotifications::instance().add( - payload["notify_box_type"].asString(), - args, - payload, - &inviteUserResponse); -} - void LLIMMgr::setFloaterOpen(BOOL set_open) { if (set_open) @@ -1050,7 +1028,7 @@ LLFloaterIMPanel* LLIMMgr::createFloater( const LLUUID& other_participant_id, const std::string& session_label, const EInstantMessage& dialog, - const std::vector& ids, + const uuid_vec_t& ids, bool user_initiated) { if (session_id.isNull()) @@ -1096,38 +1074,46 @@ bool LLIMMgr::isNonFriendSessionNotified(const LLUUID& session_id) return mNotifiedNonFriendSessions.end() != mNotifiedNonFriendSessions.find(session_id); } +std::string LLIMMgr::getOfflineMessage(const LLUUID& id) +{ + std::string full_name; + if (LLAvatarNameCache::getNSName(id, full_name)) + { + LLUIString offline = LLTrans::getString("offline_message"); + offline.setArg("[NAME]", full_name); + return offline; + } + return LLStringUtil::null; +} + void LLIMMgr::noteOfflineUsers( LLFloaterIMPanel* floater, - const std::vector& ids) + const uuid_vec_t& ids) { - S32 count = ids.size(); - if(count == 0) + if(ids.empty()) { const std::string& only_user = LLTrans::getString("only_user_message"); floater->addHistoryLine(only_user, gSavedSettings.getColor4("SystemChatColor")); } else { - const LLRelationship* info = NULL; + const LLRelationship* info = nullptr; LLAvatarTracker& at = LLAvatarTracker::instance(); - for(S32 i = 0; i < count; ++i) + for(const auto& id : ids) { - info = at.getBuddyInfo(ids.at(i)); - std::string full_name; - if (info - && !info->isOnline() - && LLAvatarNameCache::getNSName(ids.at(i), full_name)) + info = at.getBuddyInfo(id); + if (info && !info->isOnline()) { - LLUIString offline = LLTrans::getString("offline_message"); - offline.setArg("[NAME]", full_name); - floater->addHistoryLine(offline, gSavedSettings.getColor4("SystemChatColor")); + auto offline(getOfflineMessage(id)); + if (!offline.empty()) + floater->addHistoryLine(offline, gSavedSettings.getColor4("SystemChatColor")); } } } } void LLIMMgr::noteMutedUsers(LLFloaterIMPanel* floater, - const std::vector& ids) + const uuid_vec_t& ids) { // Don't do this if we don't have a mute list. LLMuteList *ml = LLMuteList::getInstance(); @@ -1152,23 +1138,23 @@ void LLIMMgr::noteMutedUsers(LLFloaterIMPanel* floater, } } -void LLIMMgr::processIMTypingStart(const LLIMInfo* im_info) +void LLIMMgr::processIMTypingStart(const LLUUID& from_id, const EInstantMessage im_type) { - processIMTypingCore(im_info, TRUE); + processIMTypingCore(from_id, im_type, TRUE); } -void LLIMMgr::processIMTypingStop(const LLIMInfo* im_info) +void LLIMMgr::processIMTypingStop(const LLUUID& from_id, const EInstantMessage im_type) { - processIMTypingCore(im_info, FALSE); + processIMTypingCore(from_id, im_type, FALSE); } -void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing) +void LLIMMgr::processIMTypingCore(const LLUUID& from_id, const EInstantMessage im_type, BOOL typing) { - LLUUID session_id = computeSessionID(im_info->mIMType, im_info->mFromID); - LLFloaterIMPanel* floater = findFloaterBySession(session_id); - if (floater) + LLUUID session_id = computeSessionID(im_type, from_id); + LLFloaterIMPanel* im_floater = findFloaterBySession(session_id); + if (im_floater) { - floater->processIMTyping(im_info, typing); + im_floater->processIMTyping(from_id, typing); } } @@ -1289,10 +1275,10 @@ LLFloaterChatterBox* LLIMMgr::getFloater() return LLFloaterChatterBox::getInstance(LLSD()); } -class LLViewerChatterBoxSessionStartReply : public LLHTTPNode +class LLViewerChatterBoxSessionStartReply final : public LLHTTPNode { public: - virtual void describe(Description& desc) const + void describe(Description& desc) const override { desc.shortInfo("Used for receiving a reply to a request to initialize an ChatterBox session"); desc.postAPI(); @@ -1301,18 +1287,15 @@ class LLViewerChatterBoxSessionStartReply : public LLHTTPNode desc.source(__FILE__, __LINE__); } - virtual void post(ResponsePtr response, + void post(ResponsePtr response, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { - LLSD body; - LLUUID temp_session_id; LLUUID session_id; - bool success; - body = input["body"]; - success = body["success"].asBoolean(); - temp_session_id = body["temp_session_id"].asUUID(); + LLSD body = input["body"]; + bool success = body["success"].asBoolean(); + LLUUID temp_session_id = body["temp_session_id"].asUUID(); if ( success ) { @@ -1350,10 +1333,10 @@ class LLViewerChatterBoxSessionStartReply : public LLHTTPNode } }; -class LLViewerChatterBoxSessionEventReply : public LLHTTPNode +class LLViewerChatterBoxSessionEventReply final : public LLHTTPNode { public: - virtual void describe(Description& desc) const + void describe(Description& desc) const override { desc.shortInfo("Used for receiving a reply to a ChatterBox session event"); desc.postAPI(); @@ -1362,24 +1345,18 @@ class LLViewerChatterBoxSessionEventReply : public LLHTTPNode desc.source(__FILE__, __LINE__); } - virtual void post(ResponsePtr response, + void post(ResponsePtr response, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { - LLUUID session_id; - bool success; - LLSD body = input["body"]; - success = body["success"].asBoolean(); - session_id = body["session_id"].asUUID(); + bool success = body["success"].asBoolean(); + LLUUID session_id = body["session_id"].asUUID(); if ( !success ) { //throw an error dialog - LLFloaterIMPanel* floater = - gIMMgr->findFloaterBySession(session_id); - - if (floater) + if (auto* floater = gIMMgr->findFloaterBySession(session_id)) { floater->showSessionEventError( body["event"].asString(), @@ -1392,46 +1369,40 @@ class LLViewerChatterBoxSessionEventReply : public LLHTTPNode class LLViewerForceCloseChatterBoxSession: public LLHTTPNode { public: - virtual void post(ResponsePtr response, + void post(ResponsePtr response, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { - LLUUID session_id; - std::string reason; - - session_id = input["body"]["session_id"].asUUID(); - reason = input["body"]["reason"].asString(); - - LLFloaterIMPanel* floater = - gIMMgr ->findFloaterBySession(session_id); + LLUUID session_id = input["body"]["session_id"].asUUID(); + std::string reason = input["body"]["reason"].asString(); - if ( floater ) + if (auto* floater = gIMMgr ->findFloaterBySession(session_id)) { floater->showSessionForceClose(reason); } } }; -class LLViewerChatterBoxSessionAgentListUpdates : public LLHTTPNode +class LLViewerChatterBoxSessionAgentListUpdates final : public LLHTTPNode { public: - virtual void post( + void post( ResponsePtr responder, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { const LLUUID& session_id = input["body"]["session_id"].asUUID(); gIMMgr->processAgentListUpdates(session_id, input["body"]); } }; -class LLViewerChatterBoxSessionUpdate : public LLHTTPNode +class LLViewerChatterBoxSessionUpdate final : public LLHTTPNode { public: - virtual void post( + void post( ResponsePtr responder, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { LLUUID session_id = input["body"]["session_id"].asUUID(); LLFloaterIMPanel* im_floater = gIMMgr->findFloaterBySession(session_id); @@ -1452,21 +1423,21 @@ void leave_group_chat(const LLUUID& from_id, const LLUUID& session_id) { // Tell the server we've left group chat std::string name; - gAgent.buildFullname(name); + LLAgentUI::buildFullname(name); pack_instant_message(gMessageSystem, gAgentID, false, gAgentSessionID, from_id, name, LLStringUtil::null, IM_ONLINE, IM_SESSION_LEAVE, session_id); gAgent.sendReliableMessage(); gIMMgr->removeSession(session_id); } -class LLViewerChatterBoxInvitation : public LLHTTPNode +class LLViewerChatterBoxInvitation final : public LLHTTPNode { public: - virtual void post( + void post( ResponsePtr response, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { //for backwards compatiblity reasons...we need to still //check for 'text' or 'voice' invitations...bleh @@ -1596,10 +1567,9 @@ class LLViewerChatterBoxInvitation : public LLHTTPNode LLFloaterChat::addChat(chat, TRUE, is_this_agent); //K now we want to accept the invitation - std::string url = gAgent.getRegion()->getCapability( - "ChatSessionRequest"); + std::string url = gAgent.getRegionCapability("ChatSessionRequest"); - if ( url != "" ) + if (!url.empty()) { LLSD data; data["method"] = "accept invitation"; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index b5a0f56e42..4f0159c2f6 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -42,7 +42,7 @@ class LLFloaterChatterBox; class LLFloaterIMPanel; -class LLIMMgr : public LLSingleton +class LLIMMgr final : public LLSingleton { public: enum EInvitationType @@ -92,7 +92,7 @@ class LLIMMgr : public LLSingleton LLUUID addSession(const std::string& name, EInstantMessage dialog, const LLUUID& other_participant_id, - const std::vector& ids); + const uuid_vec_t& ids); // Creates a P2P session with the requisite handle for responding to voice calls LLUUID addP2PSession(const std::string& name, @@ -121,8 +121,8 @@ class LLIMMgr : public LLSingleton void updateFloaterSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id); - void processIMTypingStart(const LLIMInfo* im_info); - void processIMTypingStop(const LLIMInfo* im_info); + void processIMTypingStart(const LLUUID& from_id, const EInstantMessage im_type); + void processIMTypingStop(const LLUUID& from_id, const EInstantMessage im_type); void clearNewIMNotification(); @@ -188,6 +188,8 @@ class LLIMMgr : public LLSingleton bool isNonFriendSessionNotified(const LLUUID& session_id); + static std::string getOfflineMessage(const LLUUID& id); + private: // create a panel and update internal representation for // consistency. Returns the pointer, caller (the class instance @@ -197,19 +199,17 @@ class LLIMMgr : public LLSingleton const LLUUID& target_id, const std::string& name, const EInstantMessage& dialog, - const std::vector& ids = std::vector(), + const uuid_vec_t& ids = uuid_vec_t(), bool user_initiated = false); // This simple method just iterates through all of the ids, and // prints a simple message if they are not online. Used to help // reduce 'hello' messages to the linden employees unlucky enough // to have their calling card in the default inventory. - void noteOfflineUsers(LLFloaterIMPanel* panel, const std::vector& ids); - void noteMutedUsers(LLFloaterIMPanel* panel, const std::vector& ids); - - void processIMTypingCore(const LLIMInfo* im_info, BOOL typing); + void noteOfflineUsers(LLFloaterIMPanel* panel, const uuid_vec_t& ids); + void noteMutedUsers(LLFloaterIMPanel* panel, const uuid_vec_t& ids); - static void onInviteNameLookup(const LLUUID& id, const std::string& full_name, bool is_group, LLSD payload); + void processIMTypingCore(const LLUUID& from_id, const EInstantMessage im_type, BOOL typing); private: std::set > mFloaters; @@ -219,7 +219,7 @@ class LLIMMgr : public LLSingleton // the user should be notified that to be able to see this message the option should be OFF. // This set stores session IDs in which user was notified. Need to store this IDs so that the user // be notified only one time per session with non-friend. - typedef std::set notified_non_friend_sessions_t; + typedef uuid_set_t notified_non_friend_sessions_t; notified_non_friend_sessions_t mNotifiedNonFriendSessions; // An IM has been received that you haven't seen yet. diff --git a/indra/newview/llinventoryactions.cpp b/indra/newview/llinventoryactions.cpp index 74691e4af1..e06b407241 100644 --- a/indra/newview/llinventoryactions.cpp +++ b/indra/newview/llinventoryactions.cpp @@ -44,6 +44,7 @@ #include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" #include "llmakeoutfitdialog.h" +#include "llmarketplacefunctions.h" #include "llnotificationsutil.h" #include "llpanelmaininventory.h" #include "llpanelobjectinventory.h" @@ -60,37 +61,152 @@ extern LLUUID gAgentID; using namespace LLOldEvents; +bool contains_nocopy_items(const LLUUID& id); + namespace LLInventoryAction { - bool doToSelected(LLFolderView* folder, std::string action); + void callback_doToSelected(const LLSD& notification, const LLSD& response, LLFolderView* folder, const std::string& action); + void callback_copySelected(const LLSD& notification, const LLSD& response, class LLFolderView* root, const std::string& action); + bool doToSelected(LLFolderView* root, std::string action, BOOL user_confirm = TRUE); + + void buildMarketplaceFolders(LLFolderView* root); + void updateMarketplaceFolders(); + std::list sMarketplaceFolders; // Marketplace folders that will need update once the action is completed } typedef LLMemberListener object_inventory_listener_t; -typedef LLMemberListener inventory_listener_t; +typedef LLMemberListener inventory_listener_t; typedef LLMemberListener inventory_panel_listener_t; -bool LLInventoryAction::doToSelected(LLFolderView* folder, std::string action) +// Callback for doToSelected if DAMA required... +void LLInventoryAction::callback_doToSelected(const LLSD& notification, const LLSD& response, LLFolderView* folder, const std::string& action) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + doToSelected(folder, action, false); + } +} + +void LLInventoryAction::callback_copySelected(const LLSD& notification, const LLSD& response, class LLFolderView* root, const std::string& action) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES, Move no copy item(s) + { + doToSelected(root, "copy_or_move_to_marketplace_listings", false); + } + else if (option == 1) // NO, Don't move no copy item(s) (leave them behind) + { + doToSelected(root, "copy_to_marketplace_listings", false); + } +} + +// Succeeds iff all selected items are bridges to objects, in which +// case returns their corresponding uuids. +bool get_selection_object_uuids(LLFolderView *root, uuid_vec_t& ids) { - if (!folder) + uuid_vec_t results; + //S32 no_object = 0; + for(const auto& id : root->getSelectionList()) + { + if(id.notNull()) + { + results.push_back(id); + } + else + { + return false; //non_object++; + } + } + //if (non_object == 0) + { + ids = results; return true; + } + //return false; +} + +bool LLInventoryAction::doToSelected(LLFolderView* root, std::string action, BOOL user_confirm) +{ + if (!root) + return true; + + auto selected_items = root->getSelectionList(); + + // Prompt the user and check for authorization for some marketplace active listing edits + if (user_confirm && (("delete" == action) || ("cut" == action) || ("rename" == action) || ("properties" == action) || ("task_properties" == action) || ("open" == action))) + { + auto set_iter = std::find_if(selected_items.begin(), selected_items.end(), boost::bind(&depth_nesting_in_marketplace, _1) >= 0); + if (set_iter != selected_items.end()) + { + if ("open" == action) + { + if (get_can_item_be_worn(*set_iter)) + { + // Wearing an object from any listing, active or not, is verbotten + LLNotificationsUtil::add("AlertMerchantListingCannotWear"); + return true; + } + // Note: we do not prompt for change when opening items (e.g. textures or note cards) on the marketplace... + } + else if (LLMarketplaceData::instance().isInActiveFolder(*set_iter) || + LLMarketplaceData::instance().isListedAndActive(*set_iter)) + { + // If item is in active listing, further confirmation is required + if ((("cut" == action) || ("delete" == action)) && (LLMarketplaceData::instance().isListed(*set_iter) || LLMarketplaceData::instance().isVersionFolder(*set_iter))) + { + // Cut or delete of the active version folder or listing folder itself will unlist the listing so ask that question specifically + LLNotificationsUtil::add("ConfirmMerchantUnlist", LLSD(), LLSD(), boost::bind(&LLInventoryAction::callback_doToSelected, _1, _2, root, action)); + return true; + } + // Any other case will simply modify but not unlist a listing + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLInventoryAction::callback_doToSelected, _1, _2, root, action)); + return true; + } + // Cutting or deleting a whole listing needs confirmation as SLM will be archived and inaccessible to the user + else if (LLMarketplaceData::instance().isListed(*set_iter) && (("cut" == action) || ("delete" == action))) + { + LLNotificationsUtil::add("ConfirmListingCutOrDelete", LLSD(), LLSD(), boost::bind(&LLInventoryAction::callback_doToSelected, _1, _2, root, action)); + return true; + } + } + } + // Copying to the marketplace needs confirmation if nocopy items are involved + if (("copy_to_marketplace_listings" == action)) + { + auto set_iter = selected_items.begin(); + if (contains_nocopy_items(*set_iter)) + { + LLNotificationsUtil::add("ConfirmCopyToMarketplace", LLSD(), LLSD(), boost::bind(&LLInventoryAction::callback_copySelected, _1, _2, root, action)); + return true; + } + } + + // Keep track of the marketplace folders that will need update of their status/name after the operation is performed + buildMarketplaceFolders(root); + LLInventoryModel* model = &gInventory; if ("rename" == action) { - folder->startRenamingSelectedItem(); + root->startRenamingSelectedItem(); + // Update the marketplace listings that have been affected by the operation + updateMarketplaceFolders(); return true; } - else if ("delete" == action) + + if ("delete" == action) { - folder->removeSelectedItems(); + root->removeSelectedItems(); + + // Update the marketplace listings that have been affected by the operation + updateMarketplaceFolders(); return true; } - else if ("copy" == action || "cut" == action) + if ("copy" == action || "cut" == action) { LLInventoryClipboard::instance().reset(); } - std::set selected_items = folder->getSelectionList(); - LLMultiFloater* multi_floaterp = NULL; if (("task_open" == action || "open" == action) && selected_items.size() > 1) @@ -114,16 +230,30 @@ bool LLInventoryAction::doToSelected(LLFolderView* folder, std::string action) LLFloater::setFloaterHost(multi_floaterp); } - std::set::iterator set_iter; - for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) + // This rather warty piece of code is to allow items to be removed + // from the avatar in a batch, eliminating redundant + // updateAppearanceFromCOF() requests further down the line. (MAINT-4918) + // + // There are probably other cases where similar batching would be + // desirable, but the current item-by-item performAction() + // approach would need to be reworked. + uuid_vec_t object_uuids_to_remove; + if (isRemoveAction(action) && get_selection_object_uuids(root, object_uuids_to_remove)) + { + LLAppearanceMgr::instance().removeItemsFromAvatar(object_uuids_to_remove); + } + else { - LLFolderViewItem* folder_item = folder->getItemByID(*set_iter); - if(!folder_item) continue; - LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); - if(!bridge) continue; + for (const auto& id : selected_items) + { + LLFolderViewItem* folder_item = root->getItemByID(id); + if(!folder_item) continue; + LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); + if(!bridge) continue; - bridge->performAction(model, action); + bridge->performAction(model, action); + } } LLFloater::setFloaterHost(NULL); @@ -135,7 +265,93 @@ bool LLInventoryAction::doToSelected(LLFolderView* folder, std::string action) return true; } -struct LLNewWindow : public inventory_listener_t +void LLInventoryAction::buildMarketplaceFolders(LLFolderView* root) +{ + // Make a list of all marketplace folders containing the elements in the selected list + // as well as the elements themselves. + // Once those elements are updated (cut, delete in particular but potentially any action), their + // containing folder will need to be updated as well as their initially containing folder. For + // instance, moving a stock folder from a listed folder to another will require an update of the + // 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, false); + if (marketplacelistings_id.isNull()) + { + return; + } + + for (const auto& item : root->getSelectionList()) + { + const LLInventoryObject* obj(gInventory.getObject(item)); + if (!obj) continue; + if (gInventory.isObjectDescendentOf(obj->getParentUUID(), marketplacelistings_id)) + { + const LLUUID& parent_id = obj->getParentUUID(); + if (parent_id != marketplacelistings_id) + { + sMarketplaceFolders.push_back(parent_id); + } + const LLUUID& curr_id = obj->getUUID(); + if (curr_id != marketplacelistings_id) + { + sMarketplaceFolders.push_back(curr_id); + } + } + } + // Suppress dupes in the list so we wo't update listings twice + sMarketplaceFolders.sort(); + sMarketplaceFolders.unique(); +} + +void LLInventoryAction::updateMarketplaceFolders() +{ + while (!sMarketplaceFolders.empty()) + { + update_marketplace_category(sMarketplaceFolders.back()); + sMarketplaceFolders.pop_back(); + } +} + + + +class LLDoToSelectedPanel : public object_inventory_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLPanelObjectInventory *panel = mPtr; + LLFolderView* folder = panel->getRootFolder(); + if(!folder) return true; + + return LLInventoryAction::doToSelected(folder, userdata.asString()); + } +}; + +class LLDoToSelectedFloater : public inventory_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLInventoryPanel *panel = mPtr->getPanel(); + LLFolderView* folder = panel->getRootFolder(); + if(!folder) return true; + + return LLInventoryAction::doToSelected(folder, userdata.asString()); + } +}; + +class LLDoToSelected : public inventory_panel_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLInventoryPanel *panel = mPtr; + LLFolderView* folder = panel->getRootFolder(); + if(!folder) return true; + + return LLInventoryAction::doToSelected(folder, userdata.asString()); + } +}; + +class LLNewWindow : public inventory_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { @@ -143,7 +359,7 @@ struct LLNewWindow : public inventory_listener_t S32 left = 0 , top = 0; gFloaterView->getNewFloaterPosition(&left, &top); rect.setLeftTopAndSize(left, top, rect.getWidth(), rect.getHeight()); - LLInventoryView* iv = new LLInventoryView(std::string("Inventory"), + LLPanelMainInventory* iv = new LLPanelMainInventory(std::string("Inventory"), rect, mPtr->getActivePanel()->getModel()); iv->getActivePanel()->setFilterTypes(mPtr->getActivePanel()->getFilterObjectTypes()); @@ -173,7 +389,15 @@ void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, const LLSD& sdtyp LLFolderType::FT_NONE, LLStringUtil::null); } model->notifyObservers(); + + // Singu Note: SV-2036 + // Hack! setSelection sets category to fetching state, which disables scrolling. Scrolling, however, is desired. + // Setting autoSelectOverride to true just happens to skip the fetch check, thus allowing the scroll to proceed. + bool autoselected = ptr->getRootFolder()->getAutoSelectOverride(); + ptr->getRootFolder()->setAutoSelectOverride(true); ptr->setSelection(category, TRUE); + // Restore autoSelectOverride to whatever it was before we hijacked it. + ptr->getRootFolder()->setAutoSelectOverride(autoselected); } else if ("lsl" == type) { @@ -292,22 +516,19 @@ struct LLBeginIMSession : public inventory_panel_listener_t LLInventoryPanel *panel = mPtr; LLInventoryModel* model = panel->getModel(); if(!model) return true; - std::set selected_items = panel->getRootFolder()->getSelectionList(); std::string name; static int session_num = 1; - std::vector members; + uuid_vec_t members; EInstantMessage type = IM_SESSION_CONFERENCE_START; // [RLVa:KB] - Checked: 2013-05-08 (RLVa-1.4.9) bool fRlvCanStartIM = true; // [/RLVa:KB] - for (std::set::const_iterator iter = selected_items.begin(); iter != selected_items.end(); iter++) + for (const auto& item : panel->getRootFolder()->getSelectionList()) { - - LLUUID item = *iter; LLFolderViewItem* folder_item = panel->getRootFolder()->getItemByID(item); if(folder_item) @@ -414,7 +635,7 @@ struct LLAttachObject : public inventory_panel_listener_t LLFolderView* folder = panel->getRootFolder(); if(!folder) return true; - std::set selected_items = folder->getSelectionList(); + auto selected_items = folder->getSelectionList(); LLUUID id = *selected_items.begin(); std::string joint_name = userdata.asString(); @@ -464,25 +685,25 @@ struct LLAttachObject : public inventory_panel_listener_t void init_object_inventory_panel_actions(LLPanelObjectInventory *panel) { - (new LLBindMemberListener(panel, "Inventory.DoToSelected", boost::bind(&LLInventoryAction::doToSelected, boost::bind(&LLPanelObjectInventory::getRootFolder, panel), _2))); + (new LLBindMemberListener(panel, "Inventory.DoToSelected", boost::bind(&LLInventoryAction::doToSelected, boost::bind(&LLPanelObjectInventory::getRootFolder, panel), _2, true))); } -void init_inventory_actions(LLInventoryView *floater) +void init_inventory_actions(LLPanelMainInventory *floater) { - (new LLBindMemberListener(floater, "Inventory.DoToSelected", boost::bind(&LLInventoryAction::doToSelected, boost::bind(&LLInventoryView::getRootFolder, floater), _2))); - (new LLBindMemberListener(floater, "Inventory.CloseAllFolders", boost::bind(&LLInventoryPanel::closeAllFolders, boost::bind(&LLInventoryView::getPanel, floater)))); + (new LLBindMemberListener(floater, "Inventory.DoToSelected", boost::bind(&LLInventoryAction::doToSelected, boost::bind(&LLPanelMainInventory::getRootFolder, floater), _2, true))); + (new LLBindMemberListener(floater, "Inventory.CloseAllFolders", boost::bind(&LLInventoryPanel::closeAllFolders, boost::bind(&LLPanelMainInventory::getPanel, floater)))); (new LLBindMemberListener(floater, "Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "", LLFolderType::FT_TRASH))); - (new LLBindMemberListener(floater, "Inventory.DoCreate", boost::bind(&do_create, &gInventory, boost::bind(&LLInventoryView::getPanel, floater), _2, (LLFolderBridge*)0))); + (new LLBindMemberListener(floater, "Inventory.DoCreate", boost::bind(&do_create, &gInventory, boost::bind(&LLPanelMainInventory::getPanel, floater), _2, (LLFolderBridge*)0))); (new LLNewWindow())->registerListener(floater, "Inventory.NewWindow"); - (new LLBindMemberListener(floater, "Inventory.ShowFilters", boost::bind(&LLInventoryView::toggleFindOptions, floater))); - (new LLBindMemberListener(floater, "Inventory.ResetFilter", boost::bind(&LLInventoryView::resetFilters, floater))); + (new LLBindMemberListener(floater, "Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, floater))); + (new LLBindMemberListener(floater, "Inventory.ResetFilter", boost::bind(&LLPanelMainInventory::resetFilters, floater))); (new LLSetSortBy())->registerListener(floater, "Inventory.SetSortBy"); (new LLSetSearchType())->registerListener(floater, "Inventory.SetSearchType"); } void init_inventory_panel_actions(LLInventoryPanel *panel) { - (new LLBindMemberListener(panel, "Inventory.DoToSelected", boost::bind(&LLInventoryAction::doToSelected, boost::bind(&LLInventoryPanel::getRootFolder, panel), _2))); + (new LLBindMemberListener(panel, "Inventory.DoToSelected", boost::bind(&LLInventoryAction::doToSelected, boost::bind(&LLInventoryPanel::getRootFolder, panel), _2, true))); (new LLAttachObject())->registerListener(panel, "Inventory.AttachObject"); (new LLBindMemberListener(panel, "Inventory.CloseAllFolders", boost::bind(&LLInventoryPanel::closeAllFolders, panel))); (new LLBindMemberListener(panel, "Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH))); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 8fc8f56b97..fb645329a2 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -36,14 +36,17 @@ #include "lffloaterinvpanel.h" #include "llagent.h" +#include "llagentbenefits.h" #include "llagentcamera.h" #include "llagentwearables.h" #include "llappearancemgr.h" #include "llattachmentsmgr.h" #include "llavataractions.h" #include "llcallingcard.h" +#include "llfavoritesbar.h" // management of favorites folder #include "llfirstuse.h" #include "llfloatercustomize.h" +#include "llfloatermarketplacelistings.h" #include "llfloateropenobject.h" #include "llfloaterproperties.h" #include "llfloaterworldmap.h" @@ -72,6 +75,7 @@ #include "llselectmgr.h" #include "lltooldraganddrop.h" #include "lltrans.h" +#include "llurlaction.h" #include "llviewerassettype.h" #include "llviewerfoldertype.h" #include "llviewermenu.h" @@ -91,16 +95,12 @@ #include "rlvhandler.h" #include "rlvlocks.h" // [/RLVa:KB] -#include - -// Marketplace outbox current disabled -#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 1 -#define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 1 -#define BLOCK_WORN_ITEMS_IN_OUTBOX 1 typedef std::pair two_uuids_t; typedef std::list two_uuids_list_t; +const F32 SOUND_GAIN = 1.0f; + struct LLMoveInv { LLUUID mObjectID; @@ -118,7 +118,7 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*); bool confirm_attachment_rez(const LLSD& notification, const LLSD& response); static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); -void build_context_menu_folder_options(LLInventoryModel* mModel, const LLUUID& mUUID, menuentry_vec_t& mItems, menuentry_vec_t& mDisabledItems); +void build_context_menu_folder_options(LLInventoryModel* mModel, const LLUUID& mUUID, menuentry_vec_t& items, menuentry_vec_t& disabled_items); // Helper functions @@ -129,17 +129,7 @@ bool isAddAction(const std::string& action) bool isRemoveAction(const std::string& action) { - return ("take_off" == action || "detach" == action || "deactivate" == action); -} - -bool isMarketplaceCopyAction(const std::string& action) -{ - return (("copy_to_outbox" == action) || ("move_to_outbox" == action)); -} - -bool isMarketplaceSendAction(const std::string& action) -{ - return ("send_to_marketplace" == action); + return ("take_off" == action || "detach" == action); } // Used by LLFolderBridge as callback for directory fetching recursion @@ -210,7 +200,6 @@ const std::string& LLInvFVBridge::getDisplayName() const { buildDisplayName(); } - return mDisplayName; } @@ -274,12 +263,48 @@ BOOL LLInvFVBridge::isLibraryItem() const /** * @brief Adds this item into clipboard storage */ -void LLInvFVBridge::cutToClipboard() +BOOL LLInvFVBridge::cutToClipboard() { if(isItemMovable()) + { + const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const BOOL cut_from_marketplacelistings = gInventory.isObjectDescendentOf(mUUID, marketplacelistings_id); + + if (cut_from_marketplacelistings && (LLMarketplaceData::instance().isInActiveFolder(mUUID) || + LLMarketplaceData::instance().isListedAndActive(mUUID))) + { + // Prompt the user if cutting from a marketplace active listing + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLInvFVBridge::callback_cutToClipboard, this, _1, _2)); + } + else + { + // Otherwise just perform the cut + return perform_cutToClipboard(); + } + } + return FALSE; +} + +// Callback for cutToClipboard if DAMA required... +BOOL LLInvFVBridge::callback_cutToClipboard(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + return perform_cutToClipboard(); + } + return FALSE; +} + +BOOL LLInvFVBridge::perform_cutToClipboard() +{ + if (isItemMovable()) { LLInventoryClipboard::instance().cut(mUUID); + LLFolderView::removeCutItems(); + return true; } + return false; } BOOL LLInvFVBridge::copyToClipboard() const @@ -293,15 +318,23 @@ BOOL LLInvFVBridge::copyToClipboard() const return FALSE; } -// *TODO: make sure this does the right thing void LLInvFVBridge::showProperties() { - show_item_profile(mUUID); - - // Disable old properties floater; this is replaced by the sidepanel. - /* - LLFloaterReg::showInstance("properties", mUUID); - */ + if (isMarketplaceListingsFolder()) + { + show_item_profile(mUUID); + LLFloater* floater_properties = LLFloaterProperties::find(mUUID, LLUUID::null); + if (floater_properties) + { + floater_properties->setVisible(true); + floater_properties->setFrontmost(true); + //floater_properties->setVisibleAndFrontmost(); + } + } + else + { + show_item_profile(mUUID); + } } void LLInvFVBridge::removeBatch(std::vector& batch) @@ -317,7 +350,7 @@ void LLInvFVBridge::removeBatch(std::vector& batch) U32 i,j; for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.at(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); if (item) @@ -330,7 +363,7 @@ void LLInvFVBridge::removeBatch(std::vector& batch) } for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.at(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); if (cat) @@ -371,7 +404,7 @@ void LLInvFVBridge::removeBatchNoCheck(std::vector& // being deleted. for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.at(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); if(item) @@ -384,7 +417,7 @@ void LLInvFVBridge::removeBatchNoCheck(std::vector& for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.at(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); if(item) @@ -425,7 +458,7 @@ void LLInvFVBridge::removeBatchNoCheck(std::vector& for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.at(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); if(cat) @@ -499,14 +532,14 @@ BOOL LLInvFVBridge::isClipboardPasteable() const // In normal mode, we need to check each element of the clipboard to know if we can paste or not LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - std::vector objects; + uuid_vec_t objects; LLInventoryClipboard::instance().retrieve(objects); S32 count = objects.size(); for(S32 i = 0; i < count; i++) { const LLUUID &item_id = objects.at(i); - // Folders are pasteable if all items in there are copyable + // Folders are pastable if all items in there are copyable const LLInventoryCategory *cat = model->getCategory(item_id); if (cat) { @@ -517,7 +550,7 @@ BOOL LLInvFVBridge::isClipboardPasteable() const continue; } - // Each item must be copyable to be pasteable + // Each item must be copyable to be pastable LLItemBridge item_br(panel, mRoot, item_id); if (!item_br.isItemCopyable()) return FALSE; @@ -541,7 +574,7 @@ bool LLInvFVBridge::isClipboardPasteableAsCopy() const // In copy mode, we need to check each element of the clipboard to know if it's a link LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - std::vector objects; + uuid_vec_t objects; LLInventoryClipboard::instance().retrieve(objects); const S32 count = objects.size(); for(S32 i = 0; i < count; i++) @@ -579,7 +612,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const return FALSE; } - std::vector objects; + uuid_vec_t objects; LLInventoryClipboard::instance().retrieve(objects); S32 count = objects.size(); for(S32 i = 0; i < count; i++) @@ -675,7 +708,7 @@ void hide_context_entries(LLMenuGL& menu, // between two separators). if (found) { - const bool is_entry_separator = (dynamic_cast(menu_item) != NULL); + const bool is_entry_separator = !branchp && (dynamic_cast(menu_item) != NULL); found = !(is_entry_separator && is_previous_entry_separator); is_previous_entry_separator = is_entry_separator; } @@ -748,7 +781,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, if (!isInboxFolder()) { items.push_back(std::string("Rename")); - if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) + if (!isItemRenameable() || ((flags & FIRST_SELECTED_ITEM) == 0)) { disabled_items.push_back(std::string("Rename")); } @@ -786,14 +819,19 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Cut")); } - if (canListOnMarketplace()) + if (canListOnMarketplace() && !isMarketplaceListingsFolder() && !isInboxFolder()) { items.push_back(std::string("Marketplace Separator")); - items.push_back(std::string("Merchant Copy")); - if (!canListOnMarketplaceNow()) + if (gMenuHolder->getChild("MarketplaceListings")->getVisible()) { - disabled_items.push_back(std::string("Merchant Copy")); + items.push_back(std::string("Marketplace Copy")); + items.push_back(std::string("Marketplace Move")); + if (!canListOnMarketplaceNow()) + { + disabled_items.push_back(std::string("Marketplace Copy")); + disabled_items.push_back(std::string("Marketplace Move")); + } } } } @@ -801,7 +839,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, bool paste_as_copy = false; // If Paste As Copy is on the menu, Paste As Link will always show up disabled, so don't bother. // Don't allow items to be pasted directly into the COF or the inbox/outbox - if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder()) + if (!isCOFFolder() && !isInboxFolder()) { items.push_back(std::string("Paste")); // Paste as copy if we have links. @@ -846,10 +884,6 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); - } - else if(isOutboxFolder()) - { - addOutboxContextMenuOptions(flags, items, disabled_items); } else { @@ -965,30 +999,126 @@ void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items) items.push_back(std::string("Open")); } -void LLInvFVBridge::addOutboxContextMenuOptions(U32 flags, +void LLInvFVBridge::addMarketplaceContextMenuOptions(U32 flags, menuentry_vec_t &items, menuentry_vec_t &disabled_items) { - items.push_back(std::string("Rename")); - items.push_back(std::string("Delete")); - - if ((flags & FIRST_SELECTED_ITEM) == 0) + S32 depth = depth_nesting_in_marketplace(mUUID); + if (depth == 1) + { + // Options available at the Listing Folder level + items.push_back(std::string("Marketplace Create Listing")); + items.push_back(std::string("Marketplace Associate Listing")); + items.push_back(std::string("Marketplace Check Listing")); + items.push_back(std::string("Marketplace List")); + items.push_back(std::string("Marketplace Unlist")); + if (LLMarketplaceData::instance().isUpdating(mUUID,depth) || ((flags & FIRST_SELECTED_ITEM) == 0)) + { + // During SLM update, disable all marketplace related options + // Also disable all if multiple selected items + disabled_items.push_back(std::string("Marketplace Create Listing")); + disabled_items.push_back(std::string("Marketplace Associate Listing")); + disabled_items.push_back(std::string("Marketplace Check Listing")); + disabled_items.push_back(std::string("Marketplace List")); + disabled_items.push_back(std::string("Marketplace Unlist")); + } + else + { + if (gSavedSettings.getBOOL("MarketplaceListingsLogging")) + { + items.push_back(std::string("Marketplace Get Listing")); + } + if (LLMarketplaceData::instance().isListed(mUUID)) + { + disabled_items.push_back(std::string("Marketplace Create Listing")); + disabled_items.push_back(std::string("Marketplace Associate Listing")); + items.push_back(std::string("Marketplace Copy ID")); + if (LLMarketplaceData::instance().getVersionFolder(mUUID).isNull()) + { + disabled_items.push_back(std::string("Marketplace List")); + disabled_items.push_back(std::string("Marketplace Unlist")); + } + else + { + if (LLMarketplaceData::instance().getActivationState(mUUID)) + { + disabled_items.push_back(std::string("Marketplace List")); + } + else + { + disabled_items.push_back(std::string("Marketplace Unlist")); + } + } + } + else + { + disabled_items.push_back(std::string("Marketplace List")); + disabled_items.push_back(std::string("Marketplace Unlist")); + if (gSavedSettings.getBOOL("MarketplaceListingsLogging")) + { + disabled_items.push_back(std::string("Marketplace Get Listing")); + } + } + } + } + if (depth == 2) { - disabled_items.push_back(std::string("Rename")); + // Options available at the Version Folder levels and only for folders + LLInventoryCategory* cat = gInventory.getCategory(mUUID); + if (cat && LLMarketplaceData::instance().isListed(cat->getParentUUID())) + { + items.push_back(std::string("Marketplace Activate")); + items.push_back(std::string("Marketplace Deactivate")); + if (LLMarketplaceData::instance().isUpdating(mUUID,depth) || ((flags & FIRST_SELECTED_ITEM) == 0)) + { + // During SLM update, disable all marketplace related options + // Also disable all if multiple selected items + disabled_items.push_back(std::string("Marketplace Activate")); + disabled_items.push_back(std::string("Marketplace Deactivate")); + } + else + { + if (LLMarketplaceData::instance().isVersionFolder(mUUID)) + { + disabled_items.push_back(std::string("Marketplace Activate")); + if (LLMarketplaceData::instance().getActivationState(mUUID)) + { + disabled_items.push_back(std::string("Marketplace Deactivate")); + } + } + else + { + disabled_items.push_back(std::string("Marketplace Deactivate")); + } + } + } } - -#if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU - if (isOutboxFolderDirectParent()) + + items.push_back(std::string("Marketplace Edit Listing")); + LLUUID listing_folder_id = nested_parent_id(mUUID,depth); + LLUUID version_folder_id = LLMarketplaceData::instance().getVersionFolder(listing_folder_id); + + if (depth >= 2) { - items.push_back(std::string("Marketplace Separator")); - items.push_back(std::string("Marketplace Send")); - - if (!canListOnMarketplaceNow() || (flags & FIRST_SELECTED_ITEM) == 0) + // Prevent creation of new folders if the max count has been reached on this version folder (active or not) + LLUUID local_version_folder_id = nested_parent_id(mUUID,depth-1); + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(local_version_folder_id, categories, items, FALSE); + if (categories.size() >= gSavedSettings.getU32("InventoryOutboxMaxFolderCount")) { - disabled_items.push_back(std::string("Marketplace Send")); + disabled_items.push_back(std::string("New Folder")); } } -#endif // ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU + + // Options available at all levels on items and categories + if (!LLMarketplaceData::instance().isListed(listing_folder_id) || version_folder_id.isNull()) + { + disabled_items.push_back(std::string("Marketplace Edit Listing")); + } + + // Separator + items.push_back(std::string("Marketplace Listings Separator")); } // *TODO: remove this @@ -1034,7 +1164,13 @@ LLInventoryObject* LLInvFVBridge::getInventoryObject() const LLInventoryModel* LLInvFVBridge::getInventoryModel() const { LLInventoryPanel* panel = mInventoryPanel.get(); - return panel ? panel->getModel() : NULL; + return panel ? panel->getModel() : nullptr; +} + +LLInventoryFilter* LLInvFVBridge::getInventoryFilter() const +{ + LLInventoryPanel* panel = mInventoryPanel.get(); + return panel ? &panel->getFilter() : nullptr; } BOOL LLInvFVBridge::isItemInTrash() const @@ -1087,6 +1223,7 @@ BOOL LLInvFVBridge::isCOFFolder() const return LLAppearanceMgr::instance().getIsInCOF(mUUID); } +// *TODO : Suppress isInboxFolder() once Merchant Outbox is fully deprecated BOOL LLInvFVBridge::isInboxFolder() const { const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false); @@ -1099,39 +1236,16 @@ BOOL LLInvFVBridge::isInboxFolder() const return gInventory.isObjectDescendentOf(mUUID, inbox_id); } -BOOL LLInvFVBridge::isOutboxFolder() const +BOOL LLInvFVBridge::isMarketplaceListingsFolder() const { - const LLUUID outbox_id = getOutboxFolder(); + const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); - if (outbox_id.isNull()) + if (folder_id.isNull()) { return FALSE; } - return gInventory.isObjectDescendentOf(mUUID, outbox_id); -} - -BOOL LLInvFVBridge::isOutboxFolderDirectParent() const -{ - BOOL outbox_is_parent = FALSE; - - const LLInventoryCategory *cat = gInventory.getCategory(mUUID); - - if (cat) - { - const LLUUID outbox_id = getOutboxFolder(); - - outbox_is_parent = (outbox_id.notNull() && (outbox_id == cat->getParentUUID())); - } - - return outbox_is_parent; -} - -const LLUUID LLInvFVBridge::getOutboxFolder() const -{ - const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); - - return outbox_id; + return gInventory.isObjectDescendentOf(mUUID, folder_id); } BOOL LLInvFVBridge::isItemPermissive() const @@ -1261,11 +1375,18 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, case LLAssetType::AT_CATEGORY: if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) { - // Create a link folder handler instead. + // Create a link folder handler instead new_listener = new LLLinkFolderBridge(inventory, root, uuid); - break; } - new_listener = new LLFolderBridge(inventory, root, uuid); + else if (actual_asset_type == LLAssetType::AT_MARKETPLACE_FOLDER) + { + // Create a marketplace folder handler + new_listener = new LLMarketplaceFolderBridge(inventory, root, uuid); + } + else + { + new_listener = new LLFolderBridge(inventory, root, uuid); + } break; case LLAssetType::AT_LINK: case LLAssetType::AT_LINK_FOLDER: @@ -1285,6 +1406,9 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, //LL_WARNS() << LLAssetType::lookup(asset_type) << " asset type is unhandled for uuid " << uuid << LL_ENDL; break; + case LLAssetType::AT_SETTINGS: + break; + default: LL_INFOS() << "Unhandled asset type (llassetstorage.h): " << (S32)asset_type << " (" << LLAssetType::lookup(asset_type) << ")" << LL_ENDL; @@ -1308,6 +1432,22 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) } } +void LLInvFVBridge::removeObject(LLInventoryModel *model, const LLUUID &uuid) +{ + // Keep track of the parent + LLInventoryItem* itemp = model->getItem(uuid); + LLUUID parent_id = (itemp ? itemp->getParentUUID() : LLUUID::null); + // Remove the object + model->removeObject(uuid); + // Get the parent updated + if (parent_id.notNull()) + { + LLViewerInventoryCategory* parent_cat = model->getCategory(parent_id); + model->updateCategory(parent_cat); + model->notifyObservers(); + } +} + bool LLInvFVBridge::canShare() const { bool can_share = false; @@ -1338,11 +1478,9 @@ bool LLInvFVBridge::canShare() const bool LLInvFVBridge::canListOnMarketplace() const { -#if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU - LLInventoryModel * model = getInventoryModel(); - const LLViewerInventoryCategory * cat = model->getCategory(mUUID); + LLViewerInventoryCategory * cat = model->getCategory(mUUID); if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) { return false; @@ -1353,16 +1491,6 @@ bool LLInvFVBridge::canListOnMarketplace() const return false; } - if (getOutboxFolder().isNull()) - { - return false; - } - - if (isInboxFolder() || isOutboxFolder()) - { - return false; - } - LLViewerInventoryItem * item = model->getItem(mUUID); if (item) { @@ -1378,24 +1506,12 @@ bool LLInvFVBridge::canListOnMarketplace() const } return true; - -#else - return false; -#endif } bool LLInvFVBridge::canListOnMarketplaceNow() const { -#if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU - bool can_list = true; - // Do not allow listing while import is in progress - if (LLMarketplaceInventoryImporter::instanceExists()) - { - can_list = !LLMarketplaceInventoryImporter::instance().isImportInProgress(); - } - const LLInventoryObject* obj = getInventoryObject(); can_list &= (obj != NULL); @@ -1412,37 +1528,41 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const can_list = !object_folderp->isLoading(); } } - + if (can_list) { - // Get outbox id - const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); - LLFolderViewItem * outbox_itemp = mRoot->getItemByID(outbox_id); - - if (outbox_itemp) + std::string error_msg; + LLInventoryModel* model = getInventoryModel(); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + if (marketplacelistings_id.notNull()) { - MASK mask = 0x0; - BOOL drop = FALSE; - EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType()); - void * cargo_data = (void *) obj; - - can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data); + LLViewerInventoryCategory * master_folder = model->getCategory(marketplacelistings_id); + LLInventoryCategory *cat = model->getCategory(mUUID); + if (cat) + { + can_list = can_move_folder_to_marketplace(master_folder, master_folder, cat, error_msg); + } + else + { + LLInventoryItem *item = model->getItem(mUUID); + can_list = (item ? can_move_item_to_marketplace(master_folder, master_folder, item, error_msg) : false); + } + } + else + { + can_list = false; } } } - - return can_list; -#else - return false; -#endif + return can_list; } // +=================================================+ // | InventoryFVBridgeBuilder | // +=================================================+ -LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type, +LLInvFVBridge* LLInventoryFolderViewModelBuilder::createBridge(LLAssetType::EType asset_type, LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, @@ -1510,7 +1630,6 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) else if ("cut" == action) { cutToClipboard(); - LLFolderView::removeCutItems(); return; } else if ("copy" == action) @@ -1553,15 +1672,18 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) folder_view_itemp->getListener()->pasteLinkFromClipboard(); return; } - else if (isMarketplaceCopyAction(action)) + else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action)) { - LL_INFOS() << "Copy item to marketplace action!" << LL_ENDL; - LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; - - const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); - copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId()); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + // 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)); + } + else if ("marketplace_edit_listing" == action) + { + std::string url = LLMarketplaceData::instance().getListingURL(mUUID); + LLUrlAction::openURL(url); } } @@ -1617,7 +1739,7 @@ void LLItemBridge::restoreToWorld() //Similar functionality to the drag and drop rez logic bool no_copy = !itemp->getPermissions().allowCopyBy(gAgentID); if (no_copy && gHippoGridManager->getCurrentGrid()->isSecondLife()) - LLNotificationsUtil::add("RestoreToWorldConfirm", LLSD(), LLSD(), boost::bind(restore_to_world, itemp, true, !boost::bind(LLNotification::getSelectedOption, _1, _2))); + LLNotificationsUtil::add("RezRestoreToWorld", LLSD(), LLSD(), boost::bind(restore_to_world, itemp, true, !boost::bind(LLNotification::getSelectedOption, _1, _2))); else restore_to_world(itemp, no_copy); } @@ -1647,7 +1769,6 @@ LLUIImagePtr LLItemBridge::getIcon() const } return LLInventoryIcon::getIcon(LLInventoryType::ICONNAME_OBJECT); - } LLUIImagePtr LLItemBridge::getIconOverlay() const @@ -1739,9 +1860,7 @@ std::string LLItemBridge::getLabelSuffix() const suffix += NO_XFER; } - BOOL temp = item->getPermissions().getGroup() == gAgent.getID(); - - if (temp) + if (item->getPermissions().getGroup() == gAgent.getID()) { suffix += TEMPO; } @@ -1823,13 +1942,15 @@ BOOL LLItemBridge::removeItem() } // move it to the trash - LLPreview::hide(mUUID, TRUE); LLInventoryModel* model = getInventoryModel(); if(!model) return FALSE; const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); LLViewerInventoryItem* item = getItem(); if (!item) return FALSE; - + if (item->getType() != LLAssetType::AT_LSL_TEXT) + { + LLPreview::hide(mUUID, TRUE); + } // Already in trash if (model->isObjectDescendentOf(mUUID, trash_id)) return FALSE; @@ -1969,6 +2090,27 @@ void LLFolderBridge::buildDisplayName() const mDisplayName.assign(getName()); } +std::string LLFolderBridge::getLabelSuffix() const +{ + /* Singu TODO? + static LLCachedControl folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime", 0.5f); + + if (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay()) + { + return llformat(" ( %s ) ", LLTrans::getString("LoadingData").c_str()); + } + */ + + return LLInvFVBridge::getLabelSuffix(); +} + +LLFontGL::StyleFlags LLFolderBridge::getLabelStyle() const +{ + return LLFontGL::NORMAL; +} + + + // Iterate through a folder's children to determine if // all the children are removable. class LLIsItemRemovable : public LLFolderViewFunctor @@ -2006,6 +2148,11 @@ BOOL LLFolderBridge::isItemRemovable() const } } + if (isMarketplaceListingsFolder() && LLMarketplaceData::instance().getActivationState(mUUID)) + { + return FALSE; + } + return TRUE; } @@ -2071,7 +2218,7 @@ BOOL LLFolderBridge::isClipboardPasteable() const return FALSE; } - std::vector objects; + uuid_vec_t objects; LLInventoryClipboard::instance().retrieve(objects); const LLViewerInventoryCategory *current_cat = getCategory(); @@ -2119,7 +2266,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder(current_cat); */ const LLUUID ¤t_cat_id = current_cat->getUUID(); - std::vector objects; + uuid_vec_t objects; LLInventoryClipboard::instance().retrieve(objects); S32 count = objects.size(); for (S32 i = 0; i < count; i++) @@ -2155,84 +2302,10 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const } -static BOOL can_move_to_outbox(LLInventoryItem* inv_item) -{ - // Collapse links directly to items/folders - LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; - LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem(); - if (linked_item != NULL) - { - inv_item = linked_item; - } - - bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); - if (!allow_transfer) - { - return false; - } - -#if BLOCK_WORN_ITEMS_IN_OUTBOX - bool worn = get_is_item_worn(inv_item->getUUID()); - if (worn) - { - return false; - } -#endif - - bool calling_card = (LLAssetType::AT_CALLINGCARD == inv_item->getType()); - if (calling_card) - { - return false; - } - - return true; -} - - -int get_folder_levels(LLInventoryCategory* inv_cat) -{ - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items); - - int max_child_levels = 0; - - for (S32 i=0; i < cats->size(); ++i) - { - LLInventoryCategory* category = cats->at(i); - max_child_levels = llmax(max_child_levels, get_folder_levels(category)); - } - - return 1 + max_child_levels; -} - -int get_folder_path_length(const LLUUID& ancestor_id, const LLUUID& descendant_id) -{ - int depth = 0; - - if (ancestor_id == descendant_id) return depth; - - const LLInventoryCategory* category = gInventory.getCategory(descendant_id); - - while(category) - { - LLUUID parent_id = category->getParentUUID(); - - if (parent_id.isNull()) break; - - depth++; - - if (parent_id == ancestor_id) return depth; - - category = gInventory.getCategory(parent_id); - } - - LL_WARNS() << "get_folder_path_length() couldn't trace a path from the descendant to the ancestor" << LL_ENDL; - return -1; -} BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, - BOOL drop) + BOOL drop, + BOOL user_confirm) { LLInventoryModel* model = getInventoryModel(); @@ -2244,11 +2317,12 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const LLUUID &cat_id = inv_cat->getUUID(); const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const LLUUID& marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID from_folder_uuid = inv_cat->getParentUUID(); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); - const BOOL move_is_from_outbox = model->isObjectDescendentOf(cat_id, outbox_id); + const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); + const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(cat_id, marketplacelistings_id); // check to make sure source is agent inventory, and is represented there. LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); @@ -2260,9 +2334,11 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, { const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); + //const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); - const BOOL move_is_into_outfit = getCategory() && (getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT); + //const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); + const BOOL move_is_into_outfit = /*move_is_into_my_outfits ||*/ (getCategory() && getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT); const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); //-------------------------------------------------------------------------------- @@ -2270,7 +2346,20 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, // BOOL is_movable = TRUE; + std::string tooltip_msg; + if (is_movable && (marketplacelistings_id == cat_id)) + { + is_movable = FALSE; + tooltip_msg = LLTrans::getString("TooltipOutboxCannotMoveRoot"); + } + if (is_movable && move_is_from_marketplacelistings && LLMarketplaceData::instance().getActivationState(cat_id)) + { + // If the incoming folder is listed and active (and is therefore either the listing or the version folder), + // then moving is *not* allowed + is_movable = FALSE; + tooltip_msg = LLTrans::getString("TooltipOutboxDragActive"); + } // Can't move a folder into itself if (is_movable && (mUUID == cat_id)) { @@ -2301,6 +2390,12 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, is_movable = FALSE; // tooltip? } + if (is_movable && (getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK)) + { + // One cannot move a folder into a stock folder + is_movable = FALSE; + // tooltip? + } LLInventoryModel::cat_array_t descendent_categories; LLInventoryModel::item_array_t descendent_items; @@ -2374,99 +2469,64 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, is_movable = RlvFolderLocks::instance().canMoveFolder(cat_id, mUUID); } // [/RLVa:KB] - if (is_movable && move_is_into_outbox) + + if (is_movable && move_is_into_marketplacelistings) { - const int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat); - - if (nested_folder_levels > (S32)gSavedSettings.getU32("InventoryOutboxMaxFolderDepth")) - { - is_movable = FALSE; - } - else + const LLViewerInventoryCategory* master_folder = model->getFirstDescendantOf(marketplacelistings_id, mUUID); + LLViewerInventoryCategory * dest_folder = getCategory(); + S32 bundle_size = (drop ? 1 : LLToolDragAndDrop::instance().getCargoCount()); + is_movable = can_move_folder_to_marketplace(master_folder, dest_folder, inv_cat, tooltip_msg, bundle_size); + } + + // + //-------------------------------------------------------------------------------- + + accept = is_movable; + + if (accept && drop) + { + // Dropping in or out of marketplace needs (sometimes) confirmation + if (user_confirm && (move_is_from_marketplacelistings || move_is_into_marketplacelistings)) { - int dragged_folder_count = descendent_categories.size(); - int existing_item_count = 0; - int existing_folder_count = 0; - - const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID); - - if (master_folder != NULL) + if (move_is_from_marketplacelistings && (LLMarketplaceData::instance().isInActiveFolder(cat_id) || + LLMarketplaceData::instance().isListedAndActive(cat_id))) { - if (model->isObjectDescendentOf(cat_id, master_folder->getUUID())) + if (LLMarketplaceData::instance().isListed(cat_id) || LLMarketplaceData::instance().isVersionFolder(cat_id)) { - // Don't use count because we're already inside the same category anyway - dragged_folder_count = 0; + // Move the active version folder or listing folder itself outside marketplace listings will unlist the listing so ask that question specifically + LLNotificationsUtil::add("ConfirmMerchantUnlist", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); } else { - existing_folder_count = 1; // Include the master folder in the count! - - // If we're in the drop operation as opposed to the drag without drop, we are doing a - // single category at a time so don't block based on the total amount of cargo data items - if (drop) - { - dragged_folder_count += 1; - } - else - { - // NOTE: The cargo id's count is a total of categories AND items but we err on the side of - // prevention rather than letting too many folders into the hierarchy of the outbox, - // when we're dragging the item to a new parent - dragged_folder_count += LLToolDragAndDrop::instance().getCargoIDsCount(); - } + // Any other case will simply modify but not unlist an active listed listing + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); } - - // Tally the total number of categories and items inside the master folder - - LLInventoryModel::cat_array_t existing_categories; - LLInventoryModel::item_array_t existing_items; - - model->collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE); - - existing_folder_count += existing_categories.size(); - existing_item_count += existing_items.size(); + return true; } - else + if (move_is_from_marketplacelistings && LLMarketplaceData::instance().isVersionFolder(cat_id)) { - // Assume a single category is being dragged to the outbox since we evaluate one at a time - // when not putting them under a parent item. - dragged_folder_count += 1; + // Moving the version folder from its location will deactivate it. Ask confirmation. + LLNotificationsUtil::add("ConfirmMerchantClearVersion", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); + return true; } - - const int nested_folder_count = existing_folder_count + dragged_folder_count; - const int nested_item_count = existing_item_count + descendent_items.size(); - - if (nested_folder_count > (S32)gSavedSettings.getU32("InventoryOutboxMaxFolderCount")) + if (move_is_into_marketplacelistings && LLMarketplaceData::instance().isInActiveFolder(mUUID)) { - is_movable = FALSE; + // Moving something in an active listed listing will modify it. Ask confirmation. + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); + return true; } - else if (nested_item_count > (S32)gSavedSettings.getU32("InventoryOutboxMaxItemCount")) + if (move_is_from_marketplacelistings && LLMarketplaceData::instance().isListed(cat_id)) { - is_movable = FALSE; + // Moving a whole listing folder will result in archival of SLM data. Ask confirmation. + LLNotificationsUtil::add("ConfirmListingCutOrDelete", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); + return true; } - - if (is_movable == TRUE) + if (move_is_into_marketplacelistings && !move_is_from_marketplacelistings) { - for (S32 i=0; i < descendent_items.size(); ++i) - { - LLInventoryItem* item = descendent_items[i]; - if (!can_move_to_outbox(item)) - { - is_movable = FALSE; - break; - } - } + LLNotificationsUtil::add("ConfirmMerchantMoveInventory", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); + return true; } } - } - - // - //-------------------------------------------------------------------------------- - - accept = is_movable; - - if (accept && drop) - { // Look for any gestures and deactivate them if (move_is_into_trash) { @@ -2480,6 +2540,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } } + // if target is an outfit or current outfit folder we use link if (move_is_into_current_outfit || move_is_into_outfit) { @@ -2498,7 +2559,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, LLInventoryModel::item_array_t items; model->collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); LLInventoryObject::const_object_list_t citems; - BOOST_FOREACH(LLPointer item, items) + for (LLPointer item : items) { citems.push_back(item.get()); } @@ -2506,9 +2567,9 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } } - else if (move_is_into_outbox && !move_is_from_outbox) + else if (move_is_into_marketplacelistings) { - copy_folder_to_outbox(inv_cat, mUUID, cat_id, LLToolDragAndDrop::getOperationId()); + move_folder_to_marketplacelistings(inv_cat, mUUID); } else { @@ -2525,11 +2586,38 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, mUUID, move_is_into_trash); } + if (move_is_from_marketplacelistings) + { + // If we are moving a folder at the listing folder level (i.e. its parent is the marketplace listings folder) + if (from_folder_uuid == marketplacelistings_id) + { + // Clear the folder from the marketplace in case it is a listing folder + if (LLMarketplaceData::instance().isListed(cat_id)) + { + LLMarketplaceData::instance().clearListing(cat_id); + } + } + else + { + // If we move from within an active (listed) listing, check that it's still valid, if not, unlist + LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid); + if (version_folder_id.notNull()) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id); + if (!validate_marketplacelistings(cat, NULL)) + { + LLMarketplaceData::instance().activateListing(version_folder_id,false); + } + } + // In all cases, update the listing we moved from so suffix are updated + update_marketplace_category(from_folder_uuid); + } + } } } else if (LLToolDragAndDrop::SOURCE_WORLD == source) { - if (move_is_into_outbox) + if (move_is_into_marketplacelistings) { accept = FALSE; } @@ -2540,7 +2628,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) { - if (move_is_into_outbox) + if (move_is_into_marketplacelistings) { accept = FALSE; } @@ -2818,10 +2906,10 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) { if (!mFolderAdded) { - const std::set& changed_items = gInventory.getChangedIDs(); + const uuid_set_t& changed_items = gInventory.getChangedIDs(); - std::set::const_iterator id_it = changed_items.begin(); - std::set::const_iterator id_end = changed_items.end(); + auto id_it = changed_items.begin(); + auto id_end = changed_items.end(); for (;id_it != id_end; ++id_it) { if ((*id_it) == mCatID) @@ -2874,7 +2962,13 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) LLInventoryModel* model = getInventoryModel(); LLViewerInventoryCategory* cat = getCategory(); if (!model || !cat) return; - LFFloaterInvPanel::show(mUUID, model, cat->getName()); + LFFloaterInvPanel::show(LLSD().with("id", mUUID), cat->getName(), model); + return; + } + else if ("copy_folder_uuid" == action) + { + // Single folder only + gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(mUUID.asString())); return; } else if ("paste" == action) @@ -2910,7 +3004,6 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) else if ("cut" == action) { cutToClipboard(); - LLFolderView::removeCutItems(); return; } else if ("copy" == action) @@ -2942,6 +3035,125 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) restoreItem(); return; } + else if ("marketplace_list" == action) + { + if (depth_nesting_in_marketplace(mUUID) == 1) + { + LLUUID version_folder_id = LLMarketplaceData::instance().getVersionFolder(mUUID); + LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id); + mMessage = ""; + if (!validate_marketplacelistings(cat, boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3))) + { + LLSD subs; + subs["[ERROR_CODE]"] = mMessage; + LLNotificationsUtil::add("MerchantListingFailed", subs); + } + else + { + LLMarketplaceData::instance().activateListing(mUUID,true); + } + } + return; + } + else if ("marketplace_activate" == action) + { + if (depth_nesting_in_marketplace(mUUID) == 2) + { + LLInventoryCategory* category = gInventory.getCategory(mUUID); + mMessage = ""; + if (!validate_marketplacelistings(category,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),false,2)) + { + LLSD subs; + subs["[ERROR_CODE]"] = mMessage; + LLNotificationsUtil::add("MerchantFolderActivationFailed", subs); + } + else + { + LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), mUUID); + } + } + return; + } + else if ("marketplace_unlist" == action) + { + if (depth_nesting_in_marketplace(mUUID) == 1) + { + LLMarketplaceData::instance().activateListing(mUUID, false,1); + } + return; + } + else if ("marketplace_deactivate" == action) + { + if (depth_nesting_in_marketplace(mUUID) == 2) + { + LLInventoryCategory* category = gInventory.getCategory(mUUID); + LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), LLUUID::null, 1); + } + return; + } + else if ("marketplace_create_listing" == action) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(mUUID); + mMessage = ""; + bool validates = validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),false); + if (!validates) + { + mMessage = ""; + validates = validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),true); + if (validates) + { + LLNotificationsUtil::add("MerchantForceValidateListing"); + } + } + + if (!validates) + { + LLSD subs; + subs["[ERROR_CODE]"] = mMessage; + LLNotificationsUtil::add("MerchantListingFailed", subs); + } + else + { + LLMarketplaceData::instance().createListing(mUUID); + } + return; + } + else if ("marketplace_disassociate_listing" == action) + { + LLMarketplaceData::instance().clearListing(mUUID); + return; + } + else if ("marketplace_get_listing" == action) + { + // This is used only to exercise the SLM API but won't be shown to end users + LLMarketplaceData::instance().getListing(mUUID); + return; + } + else if ("marketplace_associate_listing" == action) + { + LLFloaterAssociateListing::showInstance(mUUID); + return; + } + else if ("marketplace_check_listing" == action) + { + LLSD data(mUUID); + new LLFloaterMarketplaceValidation(data); // new.. but floaters clean themselves up. + return; + } + else if ("marketplace_edit_listing" == action) + { + std::string url = LLMarketplaceData::instance().getListingURL(mUUID); + if (!url.empty()) + { + LLUrlAction::openURL(url); + } + return; + } + else if ("marketplace_copy_id" == action) + { + auto id = LLMarketplaceData::instance().getListingID(mUUID); + gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(fmt::to_string(id))); + } // Move displaced inventory to lost and found else if ("move_to_lost_and_found" == action) { @@ -2956,28 +3168,31 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) removeSystemFolder(); } #endif - else if (isMarketplaceCopyAction(action)) + else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action)) { - LL_INFOS() << "Copy folder to marketplace action!" << LL_ENDL; - LLInventoryCategory * cat = gInventory.getCategory(mUUID); if (!cat) return; - - const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); - copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId()); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("move_to_marketplace_listings" != action), (("copy_or_move_to_marketplace_listings" == action))); } -#if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU - else if (isMarketplaceSendAction(action)) - { - LL_INFOS() << "Send to marketplace action!" << LL_ENDL; +} - /*LLInventoryCategory * cat = gInventory.getCategory(mUUID); - if (!cat) return; - - send_to_marketplace(cat);*/ - LLMarketplaceInventoryImporter::instance().triggerImport(); +void LLFolderBridge::gatherMessage(std::string& message, S32 depth, LLError::ELevel log_level) +{ + if (log_level >= LLError::LEVEL_ERROR) + { + if (!mMessage.empty()) + { + // Currently, we do not gather all messages as it creates very long alerts + // Users can get to the whole list of errors on a listing using the "Check for Errors" audit button or "Check listing" right click menu + //mMessage += "\n"; + return; + } + // Take the leading spaces out... + std::string::size_type start = message.find_first_not_of(" "); + // Append the message + mMessage += message.substr(start, message.length() - start); } -#endif // ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU } void LLFolderBridge::openItem() @@ -3047,27 +3262,32 @@ LLFolderType::EType LLFolderBridge::getPreferredType() const // Icons for folders are based on the preferred type LLUIImagePtr LLFolderBridge::getIcon() const { - LLFolderType::EType preferred_type = LLFolderType::FT_NONE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat) + return getFolderIcon(FALSE); +} + +LLUIImagePtr LLFolderBridge::getIconOpen() const +{ + return getFolderIcon(TRUE); +} + +LLUIImagePtr LLFolderBridge::getFolderIcon(BOOL is_open) const +{ + LLFolderType::EType preferred_type = getPreferredType(); + S32 depth = depth_nesting_in_marketplace(mUUID); + if ((preferred_type == LLFolderType::FT_NONE) && (depth == 2)) { - preferred_type = cat->getPreferredType(); + // We override the type when in the marketplace listings folder and only for version folder + preferred_type = LLFolderType::FT_MARKETPLACE_VERSION; } - return getIcon(preferred_type); + return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, is_open)); } -// static +// static : use by LLLinkFolderBridge to get the closed type icons LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) { return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE)); } -LLUIImagePtr LLFolderBridge::getIconOpen() const -{ - return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE)); - -} - LLUIImagePtr LLFolderBridge::getIconOverlay() const { if (getInventoryObject() && getInventoryObject()->getIsLinkType()) @@ -3147,54 +3367,114 @@ bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& re void LLFolderBridge::pasteFromClipboard(bool only_copies) { LLInventoryModel* model = getInventoryModel(); - if(model && isClipboardPasteable()) + if (model && isClipboardPasteable()) + { + const LLUUID& marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const BOOL paste_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); + + BOOL cut_from_marketplacelistings = FALSE; + const auto& clipboard(LLInventoryClipboard::instance()); + if (clipboard.isCutMode()) + { + //Items are not removed from folder on "cut", so we need update listing folder on "paste" operation + uuid_vec_t objects; + clipboard.retrieve(objects); + for (auto iter = objects.begin(); iter != objects.end(); ++iter) + { + const LLUUID& item_id = (*iter); + if(gInventory.isObjectDescendentOf(item_id, marketplacelistings_id) && (LLMarketplaceData::instance().isInActiveFolder(item_id) || + LLMarketplaceData::instance().isListedAndActive(item_id))) + { + cut_from_marketplacelistings = TRUE; + break; + } + } + } + if (cut_from_marketplacelistings || (paste_into_marketplacelistings && !LLMarketplaceData::instance().isListed(mUUID) && LLMarketplaceData::instance().isInActiveFolder(mUUID))) + { + // Prompt the user if pasting in a marketplace active version listing (note that pasting right under the listing folder root doesn't need a prompt) + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_pasteFromClipboard, this, _1, _2, only_copies)); + } + else + { + // Otherwise just do the paste + perform_pasteFromClipboard(only_copies); + } + } +} + +// Callback for pasteFromClipboard if DAMA required... +void LLFolderBridge::callback_pasteFromClipboard(const LLSD& notification, const LLSD& response, bool only_copies) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + perform_pasteFromClipboard(only_copies); + } +} + +void LLFolderBridge::perform_pasteFromClipboard(bool only_copies) +{ + LLInventoryModel* model = getInventoryModel(); + if (model && isClipboardPasteable()) { const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const LLUUID& marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); + const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); - std::vector objects; + uuid_vec_t objects; LLInventoryClipboard::instance().retrieve(objects); - if (move_is_into_outbox) + LLViewerInventoryCategory* dest_folder = getCategory(); + if (move_is_into_marketplacelistings) { - LLFolderViewItem * outbox_itemp = mRoot->getItemByID(mUUID); - - if (outbox_itemp) + std::string error_msg; + const LLViewerInventoryCategory* master_folder = model->getFirstDescendantOf(marketplacelistings_id, mUUID); + int index = 0; + for (auto iter = objects.begin(); iter != objects.end(); ++iter) { - //LLToolDragAndDrop::instance().setCargoCount(objects.size()); - - BOOL can_list = TRUE; + const LLUUID& item_id = (*iter); + LLInventoryItem *item = model->getItem(item_id); + LLInventoryCategory *cat = model->getCategory(item_id); - for (std::vector::const_iterator iter = objects.begin(); - (iter != objects.end()) && (can_list == TRUE); - ++iter) + if (item && !can_move_item_to_marketplace(master_folder, dest_folder, item, error_msg, objects.size() - index, true)) { - const LLUUID& item_id = (*iter); - LLInventoryItem *item = model->getItem(item_id); - - if (item) - { - MASK mask = 0x0; - BOOL drop = FALSE; - EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(item->getActualType()); - void * cargo_data = (void *) item; - //std::string tooltip_msg; - - can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data/*, tooltip_msg*/); - } + break; } + if (cat && !can_move_folder_to_marketplace(master_folder, dest_folder, cat, error_msg, objects.size() - index, true, true)) + { + break; + } + ++index; + } + if (!error_msg.empty()) + { + LLSD subs; + subs["[ERROR_CODE]"] = error_msg; + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return; + } + } + else + { + // Check that all items can be moved into that folder : for the moment, only stock folder mismatch is checked + for (auto iter = objects.begin(); iter != objects.end(); ++iter) + { + const LLUUID& item_id = (*iter); + LLInventoryItem *item = model->getItem(item_id); + LLInventoryCategory *cat = model->getCategory(item_id); - //LLToolDragAndDrop::instance().resetCargoCount(); - - if (can_list == FALSE) + if ((item && !dest_folder->acceptItem(item)) || (cat && (dest_folder->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK))) { - // Notify user of failure somehow -- play error sound? modal dialog? + std::string error_msg = LLTrans::getString("TooltipOutboxMixedStock"); + LLSD subs; + subs["[ERROR_CODE]"] = error_msg; + LLNotificationsUtil::add("StockPasteFailed", subs); return; } } @@ -3202,7 +3482,7 @@ void LLFolderBridge::pasteFromClipboard(bool only_copies) const LLUUID parent_id(mUUID); - for (std::vector::const_iterator iter = objects.begin(); + for (auto iter = objects.begin(); iter != objects.end(); ++iter) { @@ -3225,11 +3505,24 @@ void LLFolderBridge::pasteFromClipboard(bool only_copies) // move_inventory_item() is not enough, as we have to update inventory locally too if (LLAssetType::AT_CATEGORY == obj->getType()) { - LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id); + LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *)model->getCategory(item_id); llassert(vicat); if (vicat) { - changeCategoryParent(model, vicat, parent_id, FALSE); + // Clear the cut folder from the marketplace if it is a listing folder + if (LLMarketplaceData::instance().isListed(item_id)) + { + LLMarketplaceData::instance().clearListing(item_id); + } + if (move_is_into_marketplacelistings) + { + move_folder_to_marketplacelistings(vicat, parent_id); + } + else + { + //changeCategoryParent() implicitly calls dirtyFilter + changeCategoryParent(model, vicat, parent_id, FALSE); + } } } else @@ -3238,7 +3531,19 @@ void LLFolderBridge::pasteFromClipboard(bool only_copies) llassert(viitem); if (viitem) { - changeItemParent(model, viitem, parent_id, FALSE); + if (move_is_into_marketplacelistings) + { + if (!move_item_to_marketplacelistings(viitem, parent_id)) + { + // Stop pasting into the marketplace as soon as we get an error + break; + } + } + else + { + //changeItemParent() implicitly calls dirtyFilter + changeItemParent(model, viitem, parent_id, FALSE); + } } } } @@ -3252,31 +3557,54 @@ void LLFolderBridge::pasteFromClipboard(bool only_copies) // Do a "copy" to "paste" a regular copy clipboard if (LLAssetType::AT_CATEGORY == obj->getType()) { - LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id); + LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *)model->getCategory(item_id); llassert(vicat); if (vicat) { - copy_inventory_category(model, vicat, parent_id); + if (move_is_into_marketplacelistings) + { + move_folder_to_marketplacelistings(vicat, parent_id, true); + } + else + { + copy_inventory_category(model, vicat, parent_id); + } } } -// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a - else if (!only_copies && LLAssetType::lookupIsLinkType(item->getActualType())) + // [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a + else if (!move_is_into_marketplacelistings && !only_copies && LLAssetType::lookupIsLinkType(item->getActualType())) { link_inventory_object( parent_id, item, NULL); } -// [/SL:KB] + // [/SL:KB] else { - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - parent_id, - std::string(), - LLPointer(NULL)); + LLViewerInventoryItem* viitem = dynamic_cast(item); + llassert(viitem); + if (viitem) + { + if (move_is_into_marketplacelistings) + { + if (!move_item_to_marketplacelistings(viitem, parent_id, true)) + { + // Stop pasting into the marketplace as soon as we get an error + break; + } + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + parent_id, + std::string(), + LLPointer(NULL)); + } + } } } } @@ -3292,15 +3620,15 @@ void LLFolderBridge::pasteLinkFromClipboard() if(model) { const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const LLUUID& marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); + const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); - if (move_is_into_outbox) + if (move_is_into_marketplacelistings) { // Notify user of failure somehow -- play error sound? modal dialog? return; @@ -3308,9 +3636,9 @@ void LLFolderBridge::pasteLinkFromClipboard() const LLUUID parent_id(mUUID); - std::vector objects; + uuid_vec_t objects; LLInventoryClipboard::instance().retrieve(objects); - for (std::vector::const_iterator iter = objects.begin(); + for (auto iter = objects.begin(); iter != objects.end(); ++iter) { @@ -3364,9 +3692,9 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items LLInventoryModel* model = getInventoryModel(); llassert(model != NULL); - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - + const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + const LLUUID& lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); + const LLUUID& marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); if (lost_and_found_id == mUUID) { @@ -3380,6 +3708,35 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items disabled_items.push_back(std::string("New Clothes")); disabled_items.push_back(std::string("New Body Parts")); } + if (isMarketplaceListingsFolder()) + { + addMarketplaceContextMenuOptions(flags, items, disabled_items); + if (LLMarketplaceData::instance().isUpdating(mUUID)) + { + disabled_items.push_back(std::string("New Folder")); + disabled_items.push_back(std::string("Rename")); + disabled_items.push_back(std::string("Cut")); + disabled_items.push_back(std::string("Copy")); + disabled_items.push_back(std::string("Paste")); + disabled_items.push_back(std::string("Delete")); + } + } + if (getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + disabled_items.push_back(std::string("New Folder")); + disabled_items.push_back(std::string("New Script")); + disabled_items.push_back(std::string("New Note")); + disabled_items.push_back(std::string("New Gesture")); + disabled_items.push_back(std::string("New Clothes")); + disabled_items.push_back(std::string("New Body Parts")); + } + if (marketplace_listings_id == mUUID) + { + disabled_items.push_back(std::string("New Folder")); + disabled_items.push_back(std::string("Rename")); + disabled_items.push_back(std::string("Cut")); + disabled_items.push_back(std::string("Delete")); + } if(trash_id == mUUID) { // This is the trash. @@ -3391,10 +3748,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items items.clear(); // clear any items that used to exist addTrashContextMenuOptions(items, disabled_items); } - else if(isOutboxFolder()) - { - addOutboxContextMenuOptions(flags, items, disabled_items); - } else if(isAgentInventory()) // do not allow creating in library { LLViewerInventoryCategory *cat = getCategory(); @@ -3403,16 +3756,20 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items const bool is_cof(isCOFFolder()); if (!is_cof && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) { - LLInventoryPanel* panel = mInventoryPanel.get(); - if(panel && !panel->getFilterWorn()) - if (!isInboxFolder() && !isOutboxFolder()) // don't allow creation in inbox or outbox + if (!isInboxFolder()) // don't allow creation in inbox { - items.push_back(std::string("New Folder")); - items.push_back(std::string("New Script")); - items.push_back(std::string("New Note")); - items.push_back(std::string("New Gesture")); - items.push_back(std::string("New Clothes")); - items.push_back(std::string("New Body Parts")); + { + items.push_back(std::string("New Folder")); + } + if (!isMarketplaceListingsFolder()) + { + items.push_back(std::string("New Folder")); + items.push_back(std::string("New Script")); + items.push_back(std::string("New Note")); + items.push_back(std::string("New Gesture")); + items.push_back(std::string("New Clothes")); + items.push_back(std::string("New Body Parts")); + } } getClipboardEntries(false, items, disabled_items, flags); } @@ -3469,7 +3826,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items disabled_items.push_back(std::string("Delete System Folder")); } - if (!isOutboxFolder() && !isItemInTrash()) // + if (!isMarketplaceListingsFolder() && !isItemInTrash()) // { items.push_back(std::string("Share")); if (!canShare()) @@ -3477,9 +3834,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items disabled_items.push_back(std::string("Share")); } } + // Add menu items that are dependent on the contents of the folder. LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); - if (category) + if (category && (marketplace_listings_id != mUUID)) { uuid_vec_t folders; folders.push_back(category->getUUID()); @@ -3507,7 +3865,6 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& // Build folder specific options back up LLInventoryModel* model = getInventoryModel(); - if (isOutboxFolder()) return; if (!isAgentInventory()) return; build_context_menu_folder_options(model, mUUID, items, disabled_items); @@ -3532,11 +3889,21 @@ void build_context_menu_folder_options(LLInventoryModel* model, const LLUUID& mU const LLInventoryCategory* category = model->getCategory(mUUID); if(!category) return; + items.push_back(std::string("Open Folder In New Window")); + items.push_back(std::string("Copy Folder UUID")); + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); if (trash_id == mUUID) return; if (model->isObjectDescendentOf(mUUID, trash_id)) return; - items.push_back(std::string("Open Folder In New Window")); + if (!get_is_item_removable(model, mUUID)) + { + disabled_items.push_back(std::string("Delete")); + } + + // copied from ::isMarketplaceListingsFolder + const LLUUID listings_folder = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + if (listings_folder.notNull() && gInventory.isObjectDescendentOf(mUUID, listings_folder)) return; LLFolderType::EType type = category->getPreferredType(); const bool is_system_folder = LLFolderType::lookupIsProtectedType(type); @@ -3830,6 +4197,124 @@ void LLFolderBridge::modifyOutfit(BOOL append/*, BOOL replace*/) LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, append ); } + +// +=================================================+ +// | LLMarketplaceFolderBridge | +// +=================================================+ + +// LLMarketplaceFolderBridge is a specialized LLFolderBridge for use in Marketplace Inventory panels +LLMarketplaceFolderBridge::LLMarketplaceFolderBridge(LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid) : +LLFolderBridge(inventory, root, uuid) +{ + m_depth = depth_nesting_in_marketplace(mUUID); + m_stockCountCache = COMPUTE_STOCK_NOT_EVALUATED; +} + +LLUIImagePtr LLMarketplaceFolderBridge::getIcon() const +{ + return getMarketplaceFolderIcon(FALSE); +} + +LLUIImagePtr LLMarketplaceFolderBridge::getIconOpen() const +{ + return getMarketplaceFolderIcon(TRUE); +} + +LLUIImagePtr LLMarketplaceFolderBridge::getMarketplaceFolderIcon(BOOL is_open) const +{ + LLFolderType::EType preferred_type = getPreferredType(); + if (!LLMarketplaceData::instance().isUpdating(getUUID())) + { + // Skip computation (expensive) if we're waiting for updates. Use the old value in that case. + m_depth = depth_nesting_in_marketplace(mUUID); + } + if ((preferred_type == LLFolderType::FT_NONE) && (m_depth == 2)) + { + // We override the type when in the marketplace listings folder and only for version folder + preferred_type = LLFolderType::FT_MARKETPLACE_VERSION; + } + return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, is_open)); +} + +std::string LLMarketplaceFolderBridge::getLabelSuffix() const +{ + /* Singu TODO? + static LLCachedControl folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime", 0.5f); + + if (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay()) + { + return llformat(" ( %s ) ", LLTrans::getString("LoadingData").c_str()); + } + */ + + std::string suffix = ""; + // Listing folder case + if (LLMarketplaceData::instance().isListed(getUUID())) + { + suffix = llformat("%d",LLMarketplaceData::instance().getListingID(getUUID())); + if (suffix.empty()) + { + suffix = LLTrans::getString("MarketplaceNoID"); + } + suffix = " (" + suffix + ")"; + if (LLMarketplaceData::instance().getActivationState(getUUID())) + { + suffix += " (" + LLTrans::getString("MarketplaceLive") + ")"; + } + } + // Version folder case + else if (LLMarketplaceData::instance().isVersionFolder(getUUID())) + { + suffix += " (" + LLTrans::getString("MarketplaceActive") + ")"; + } + // Add stock amount + bool updating = LLMarketplaceData::instance().isUpdating(getUUID()); + if (!updating) + { + // Skip computation (expensive) if we're waiting for update anyway. Use the old value in that case. + m_stockCountCache = compute_stock_count(getUUID()); + } + if (m_stockCountCache == 0) + { + suffix += " (" + LLTrans::getString("MarketplaceNoStock") + ")"; + } + else if (m_stockCountCache != COMPUTE_STOCK_INFINITE) + { + if (getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + suffix += " (" + LLTrans::getString("MarketplaceStock"); + } + else + { + suffix += " (" + LLTrans::getString("MarketplaceMax"); + } + if (m_stockCountCache == COMPUTE_STOCK_NOT_EVALUATED) + { + suffix += "=" + LLTrans::getString("MarketplaceUpdating") + ")"; + } + else + { + suffix += "=" + llformat("%d", m_stockCountCache) + ")"; + } + } + // Add updating suffix + if (updating) + { + suffix += " (" + LLTrans::getString("MarketplaceUpdating") + ")"; + } + return LLInvFVBridge::getLabelSuffix() + suffix; +} + +LLFontGL::StyleFlags LLMarketplaceFolderBridge::getLabelStyle() const +{ + return (LLMarketplaceData::instance().getActivationState(getUUID()) ? LLFontGL::BOLD : LLFontGL::NORMAL); +} + + + + // helper stuff bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv) { @@ -3839,7 +4324,7 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response if(option == 0 && object) { - if (cat_and_wear && cat_and_wear->mWear) + if (cat_and_wear && cat_and_wear->mWear) // && !cat_and_wear->mFolderResponded) { LLInventoryObject::object_list_t inventory_objects; object->getInventoryContents(inventory_objects); @@ -3944,16 +4429,39 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c } else { - LLPointer cb = NULL; + LLPointer cb = nullptr; link_inventory_object(mUUID, LLConstPointer(inv_item), cb); } } +// Callback for drop item if DAMA required... +void LLFolderBridge::callback_dropItemIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryItem* inv_item) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + //std::string tooltip_msg; + dragItemIntoFolder(inv_item, TRUE, /*tooltip_msg,*/ FALSE); + } +} + +// Callback for drop category if DAMA required... +void LLFolderBridge::callback_dropCategoryIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryCategory* inv_category) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + //std::string tooltip_msg; + dragCategoryIntoFolder(inv_category, TRUE, /*tooltip_msg,*/ FALSE); + } +} + // This is used both for testing whether an item can be dropped // into the folder, as well as performing the actual drop, depending // if drop == TRUE. BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, - BOOL drop) + BOOL drop, + BOOL user_confirm) { LLInventoryModel* model = getInventoryModel(); @@ -3964,19 +4472,23 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLInventoryPanel* destination_panel = mInventoryPanel.get(); if (!destination_panel) return false; + LLInventoryFilter* filter = getInventoryFilter(); + if (!filter) return false; + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); - const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const LLUUID& marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); + const LLUUID from_folder_uuid = inv_item->getParentUUID(); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); const BOOL move_is_into_favorites = (mUUID == favorites_id); const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); - const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); - const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_item->getUUID(), outbox_id); + const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); + const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(inv_item->getUUID(), marketplacelistings_id); LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); BOOL accept = FALSE; @@ -4046,57 +4558,46 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, //-------------------------------------------------------------------------------- // Determine if item can be moved & dropped - // + // Note: if user_confirm is false, we already went through those accept logic test and can skip them accept = TRUE; - if (!is_movable) + if (user_confirm && !is_movable) { accept = FALSE; } - else if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites) + else if (user_confirm && (mUUID == inv_item->getParentUUID()) && !move_is_into_favorites) { accept = FALSE; } - else if (move_is_into_current_outfit || move_is_into_outfit) + else if (user_confirm && (move_is_into_current_outfit || move_is_into_outfit)) { accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); } - else if (move_is_into_favorites || move_is_into_landmarks) + else if (user_confirm && (/*move_is_into_favorites ||*/ move_is_into_landmarks)) { accept = can_move_to_landmarks(inv_item); } - else if (move_is_into_outbox) + else if (user_confirm && move_is_into_marketplacelistings) { - accept = can_move_to_outbox(inv_item); - - if (accept) - { - const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID); - - int existing_item_count = LLToolDragAndDrop::instance().getCargoIDsCount(); - - if (master_folder != NULL) - { - LLInventoryModel::cat_array_t existing_categories; - LLInventoryModel::item_array_t existing_items; - - gInventory.collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE); - - existing_item_count += existing_items.size(); - } - - if (existing_item_count > (S32)gSavedSettings.getU32("InventoryOutboxMaxItemCount")) - { - accept = FALSE; - } - } + const LLViewerInventoryCategory* master_folder = model->getFirstDescendantOf(marketplacelistings_id, mUUID); + LLViewerInventoryCategory* dest_folder = getCategory(); + std::string tooltip_msg; + accept = can_move_item_to_marketplace(master_folder, dest_folder, inv_item, tooltip_msg, LLToolDragAndDrop::instance().getCargoCount() - LLToolDragAndDrop::instance().getCargoIndex()); + } + + // Check that the folder can accept this item based on folder/item type compatibility (e.g. stock folder compatibility) + if (user_confirm && accept) + { + LLViewerInventoryCategory * dest_folder = getCategory(); + accept = dest_folder->acceptItem(inv_item); } LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); // Check whether the item being dragged from active inventory panel - if (accept && active_panel) + // passes the filter of the destination panel. + if (user_confirm && accept && active_panel) { LLFolderView* active_folder_view = active_panel->getRootFolder(); if (!active_folder_view) return false; @@ -4115,14 +4616,29 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // and then select any item that is dropped only in the panel that it is dropped in if (active_panel && (destination_panel != active_panel)) { - active_panel->unSelectAll(); + active_panel->unSelectAll(); + } + // Dropping in or out of marketplace needs (sometimes) confirmation + if (user_confirm && (move_is_from_marketplacelistings || move_is_into_marketplacelistings)) + { + if ((move_is_from_marketplacelistings && (LLMarketplaceData::instance().isInActiveFolder(inv_item->getUUID()) + || LLMarketplaceData::instance().isListedAndActive(inv_item->getUUID()))) || + (move_is_into_marketplacelistings && LLMarketplaceData::instance().isInActiveFolder(mUUID))) + { + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropItemIntoFolder, this, _1, _2, inv_item)); + return true; + } + if (move_is_into_marketplacelistings && !move_is_from_marketplacelistings) + { + LLNotificationsUtil::add("ConfirmMerchantMoveInventory", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropItemIntoFolder, this, _1, _2, inv_item)); + return true; + } } //-------------------------------------------------------------------------------- // Destination folder logic // - /* Singu TODO: Favorites // REORDER // (only reorder the item in Favorites folder) if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites) @@ -4132,13 +4648,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { LLUUID srcItemId = inv_item->getUUID(); LLUUID destItemId = itemp->getListener()->getUUID(); - gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); + LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(srcItemId, destItemId); } } // FAVORITES folder // (copy the item) - else */if (move_is_into_favorites) + else if (move_is_into_favorites) { dropToFavorites(inv_item); } @@ -4148,16 +4664,11 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { dropToOutfit(inv_item, move_is_into_current_outfit); } - else if (move_is_into_outbox) + // MARKETPLACE LISTINGS folder + // Move the item + else if (move_is_into_marketplacelistings) { - if (move_is_from_outbox) - { - move_item_within_outbox(inv_item, mUUID, LLToolDragAndDrop::getOperationId()); - } - else - { - copy_item_to_outbox(inv_item, mUUID, LLUUID::null, LLToolDragAndDrop::getOperationId()); - } + move_item_to_marketplacelistings(inv_item, mUUID); } // NORMAL or TRASH folder // (move the item, restamp if into trash) @@ -4176,7 +4687,21 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, move_is_into_trash); } - // + if (move_is_from_marketplacelistings) + { + // If we move from an active (listed) listing, checks that it's still valid, if not, unlist + LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid); + if (version_folder_id.notNull()) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id); + if (!validate_marketplacelistings(cat, NULL)) + { + LLMarketplaceData::instance().activateListing(version_folder_id, false); + } + } + } + + // //-------------------------------------------------------------------------------- } } @@ -4220,12 +4745,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } // Don't allow to move a single item to Favorites or Landmarks // if it is not a landmark or a link to a landmark. - else if ((move_is_into_favorites || move_is_into_landmarks) + else if ((/*move_is_into_favorites ||*/ move_is_into_landmarks) && !can_move_to_landmarks(inv_item)) { accept = FALSE; } - else if (move_is_into_outbox) + else if (move_is_into_marketplacelistings) { accept = FALSE; } @@ -4255,7 +4780,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) { - if (move_is_into_outbox) + if (move_is_into_marketplacelistings) { accept = FALSE; } @@ -4281,7 +4806,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { accept = TRUE; - if (move_is_into_outbox) + if (move_is_into_marketplacelistings) { accept = FALSE; } @@ -4291,7 +4816,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } // Don't allow to move a single item to Favorites or Landmarks // if it is not a landmark or a link to a landmark. - else if (move_is_into_favorites || move_is_into_landmarks) + else if (/*move_is_into_favorites ||*/ move_is_into_landmarks) { accept = can_move_to_landmarks(inv_item); } @@ -4419,10 +4944,12 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); - } - else if(isOutboxFolder()) + } + else if (isMarketplaceListingsFolder()) { - addOutboxContextMenuOptions(flags, items, disabled_items); + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); } else { @@ -4482,7 +5009,7 @@ void LLSoundBridge::previewItem() LLViewerInventoryItem* item = getItem(); if(item) { - send_sound_trigger(item->getAssetUUID(), 1.0); + send_sound_trigger(item->getAssetUUID(), SOUND_GAIN); } } @@ -4511,9 +5038,11 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t items; menuentry_vec_t disabled_items; - if (isOutboxFolder()) + if (isMarketplaceListingsFolder()) { - addOutboxContextMenuOptions(flags, items, disabled_items); + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); } else { @@ -4548,7 +5077,7 @@ void LLSoundBridge::performAction(LLInventoryModel* model, std::string action) LLViewerInventoryItem* item = getItem(); if(item) { - send_sound_trigger(item->getAssetUUID(), 1.f); + send_sound_trigger(item->getAssetUUID(), SOUND_GAIN); } } else if ("open" == action) @@ -4586,9 +5115,11 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t disabled_items; LL_DEBUGS() << "LLLandmarkBridge::buildContextMenu()" << LL_ENDL; - if(isOutboxFolder()) + if (isMarketplaceListingsFolder()) { - addOutboxContextMenuOptions(flags, items, disabled_items); + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); } else { @@ -4865,10 +5396,12 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); - } - else if(isOutboxFolder()) + } + else if (isMarketplaceListingsFolder()) { - items.push_back(std::string("Delete")); + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); } else { @@ -5040,6 +5573,25 @@ void LLNotecardBridge::openItem() } } +void LLNotecardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + LL_DEBUGS() << "LLNotecardBridge::buildContextMenu()" << LL_ENDL; + + if (isMarketplaceListingsFolder()) + { + menuentry_vec_t items; + menuentry_vec_t disabled_items; + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); + hide_context_entries(menu, items, disabled_items); + } + else + { + LLItemBridge::buildContextMenu(menu, flags); + } +} + // +=================================================+ // | LLGestureBridge | // +=================================================+ @@ -5091,7 +5643,7 @@ void LLGestureBridge::performAction(LLInventoryModel* model, std::string action) gInventory.updateItem(item); gInventory.notifyObservers(); } - else if (isRemoveAction(action)) + else if ("deactivate" == action || isRemoveAction(action)) { LLGestureMgr::instance().deactivateGesture(mUUID); @@ -5110,7 +5662,7 @@ void LLGestureBridge::performAction(LLInventoryModel* model, std::string action) // we need to inform server about gesture activating to be consistent with LLPreviewGesture and LLGestureComboList. BOOL inform_server = TRUE; BOOL deactivate_similar = FALSE; - LLGestureMgr::instance().setGestureLoadedCallback(mUUID, boost::bind(&LLGestureBridge::playGesture, mUUID)); + LLGestureMgr::instance().setGestureLoadedCallback(mUUID, std::bind(&LLGestureBridge::playGesture, mUUID)); LLViewerInventoryItem* item = gInventory.getItem(mUUID); llassert(item); if (item) @@ -5176,9 +5728,11 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { addTrashContextMenuOptions(items, disabled_items); } - else if(isOutboxFolder()) + else if (isMarketplaceListingsFolder()) { - items.push_back(std::string("Delete")); + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); } else { @@ -5230,9 +5784,11 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t disabled_items; LL_DEBUGS() << "LLAnimationBridge::buildContextMenu()" << LL_ENDL; - if(isOutboxFolder()) + if (isMarketplaceListingsFolder()) { - items.push_back(std::string("Delete")); + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); } else { @@ -5267,9 +5823,7 @@ void LLAnimationBridge::performAction(LLInventoryModel* model, std::string actio if ((action == "playworld") || (action == "playlocal")) { // See if we can bring an existing preview to the front - if (LLPreview::show(mUUID)) - return; - + if (LLPreview::show(mUUID)) return; if (getItem()) { LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; @@ -5407,7 +5961,6 @@ std::string LLObjectBridge::getLabelSuffix() const std::string attachment_point_name; if (gAgentAvatarp->getAttachedPointName(mUUID, attachment_point_name)) { - // e.g. "(worn on ...)" / "(attached to ...)" LLStringUtil::format_map_t args; args["[ATTACHMENT_POINT]"] = LLTrans::getString(attachment_point_name); @@ -5443,13 +5996,11 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach // Check for duplicate request. if (isAgentAvatarValid() && - (gAgentAvatarp->attachmentWasRequested(item_id) || - gAgentAvatarp->isWearingAttachment(item_id))) + gAgentAvatarp->isWearingAttachment(item_id)) { - LL_WARNS() << "duplicate attachment request, ignoring" << LL_ENDL; + LL_WARNS() << "ATT duplicate attachment request, ignoring" << LL_ENDL; return; } - gAgentAvatarp->addAttachmentRequest(item_id); S32 attach_pt = 0; if (isAgentAvatarValid() && attachment) @@ -5500,7 +6051,7 @@ bool confirm_attachment_rez(const LLSD& notification, const LLSD& response) if (!gAgentAvatarp->canAttachMoreObjects()) { LLSD args; - args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS); + args["MAX_ATTACHMENTS"] = llformat("%d", LLAgentBenefitsMgr::current().getAttachmentLimit()); LLNotificationsUtil::add("MaxAttachmentsOnOutfit", args); return false; } @@ -5513,36 +6064,14 @@ bool confirm_attachment_rez(const LLSD& notification, const LLSD& response) if (itemp) { - /* - { - U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID()); - msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner()); - msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); - pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions()); - msg->addStringFast(_PREHASH_Name, itemp->getName()); - msg->addStringFast(_PREHASH_Description, itemp->getDescription()); - msg->sendReliable(gAgent.getRegion()->getHost()); - return false; - } - */ - // Queue up attachments to be sent in next idle tick, this way the // attachments are batched up all into one message versus each attachment // being sent in its own separate attachments message. U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); BOOL is_add = notification["payload"]["is_add"].asBoolean(); - LLAttachmentsMgr::instance().addAttachment(item_id, - attachment_pt, - is_add); + LL_DEBUGS("Avatar") << "ATT calling addAttachmentRequest " << (itemp ? itemp->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + LLAttachmentsMgr::instance().addAttachmentRequest(item_id, attachment_pt, is_add); } } return false; @@ -5563,10 +6092,12 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); - } - else if(isOutboxFolder()) + } + else if (isMarketplaceListingsFolder()) { - items.push_back(std::string("Delete")); + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); } else { @@ -5835,12 +6366,8 @@ void LLWearableBridge::performAction(LLInventoryModel* model, std::string action void LLWearableBridge::openItem() { - LLViewerInventoryItem* item = getItem(); - - if (item) - { + if (LLViewerInventoryItem* item = getItem()) LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } } void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) @@ -5852,9 +6379,11 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { addTrashContextMenuOptions(items, disabled_items); } - else if(isOutboxFolder()) + else if (isMarketplaceListingsFolder()) { - items.push_back(std::string("Delete")); + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); } else { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere @@ -6227,15 +6756,6 @@ void LLMeshBridge::openItem() } } -void LLMeshBridge::previewItem() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - // preview mesh - } -} - void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { LL_DEBUGS() << "LLMeshBridge::buildContextMenu()" << LL_ENDL; @@ -6252,9 +6772,11 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("Restore Item")); } - else if(isOutboxFolder()) + else if (isMarketplaceListingsFolder()) { - addOutboxContextMenuOptions(flags, items, disabled_items); + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); } else { @@ -6306,7 +6828,7 @@ void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) else { getClipboardEntries(false, items, disabled_items, flags); - if (LLInventoryView::getActiveInventory() && !isOutboxFolder() && isAgentInventory()) + if (LLPanelMainInventory::getActiveInventory() && isAgentInventory()) build_context_menu_folder_options(getInventoryModel(), getFolderID(), items, disabled_items); addDeleteContextMenuOptions(items, disabled_items); } @@ -6340,7 +6862,7 @@ void LLLinkFolderBridge::performAction(LLInventoryModel* model, std::string acti copyToClipboard(); return; } - if (LLInventoryView* iv = LLInventoryView::getActiveInventory()) + if (LLPanelMainInventory* iv = LLPanelMainInventory::getActiveInventory()) { if (LLFolderViewItem* folder_item = iv->getActivePanel()->getRootFolder()->getItemByID(getFolderID())) { @@ -6509,7 +7031,7 @@ class LLCallingCardBridgeAction: public LLInvFVBridgeAction virtual void doIt() { LLViewerInventoryItem* item = getItem(); - if (item) + if (item && item->getCreatorUUID().notNull()) { LLAvatarActions::showProfile(item->getCreatorUUID()); } @@ -6701,7 +7223,7 @@ void LLWearableBridgeAction::wearOnAvatar() LLViewerInventoryItem* item = getItem(); if(item) { - if (get_is_item_worn(item)) + if (get_is_item_worn(item->getUUID())) { LLAppearanceMgr::instance().removeItemFromAvatar(item->getUUID()); } @@ -6791,7 +7313,7 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( } else { - new_listener = LLInventoryFVBridgeBuilder::createBridge(asset_type, + new_listener = LLInventoryFolderViewModelBuilder::createBridge(asset_type, actual_asset_type, inv_type, inventory, diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 1ea6b47245..84bbc985e2 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -111,7 +111,7 @@ class LLInvFVBridge : public LLFolderViewEventListener virtual void move(LLFolderViewEventListener* new_parent_bridge) {} virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const; - virtual void cutToClipboard(); + virtual BOOL cutToClipboard(); virtual BOOL isClipboardPasteable() const; bool isClipboardPasteableAsCopy() const; virtual BOOL isClipboardPasteableAsLink() const; @@ -138,13 +138,14 @@ class LLInvFVBridge : public LLFolderViewEventListener virtual void addDeleteContextMenuOptions(menuentry_vec_t &items, menuentry_vec_t &disabled_items); virtual void addOpenRightClickMenuOption(menuentry_vec_t &items); - virtual void addOutboxContextMenuOptions(U32 flags, + virtual void addMarketplaceContextMenuOptions(U32 flags, menuentry_vec_t &items, menuentry_vec_t &disabled_items); protected: LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); LLInventoryModel* getInventoryModel() const; + LLInventoryFilter* getInventoryFilter() const; BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash? BOOL isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory? @@ -152,8 +153,8 @@ class LLInvFVBridge : public LLFolderViewEventListener BOOL isAgentInventory() const; // false if lost or in the inventory library BOOL isCOFFolder() const; // true if COF or descendant of BOOL isInboxFolder() const; // true if COF or descendant of marketplace inbox - BOOL isOutboxFolderDirectParent() const; - const LLUUID getOutboxFolder() const; + + BOOL isMarketplaceListingsFolder() const; // true if descendant of Marketplace listings folder virtual BOOL isItemPermissive() const; static void changeItemParent(LLInventoryModel* model, @@ -166,7 +167,10 @@ class LLInvFVBridge : public LLFolderViewEventListener BOOL restamp); void removeBatchNoCheck(std::vector& batch); public: - BOOL isOutboxFolder() const; // true if COF or descendant of marketplace outbox + + BOOL callback_cutToClipboard(const LLSD& notification, const LLSD& response); + BOOL perform_cutToClipboard(); + protected: LLHandle mInventoryPanel; LLFolderView* mRoot; @@ -177,6 +181,7 @@ class LLInvFVBridge : public LLFolderViewEventListener void purgeItem(LLInventoryModel *model, const LLUUID &uuid); virtual void buildDisplayName() const {} + void removeObject(LLInventoryModel* model, const LLUUID& uuid); }; class AIFilePicker; @@ -186,11 +191,11 @@ class AIFilePicker; // This class intended to build Folder View Bridge via LLInvFVBridge::createBridge. // It can be overridden with another way of creation necessary Inventory-Folder-View-Bridge. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryFVBridgeBuilder +class LLInventoryFolderViewModelBuilder { public: - LLInventoryFVBridgeBuilder() {} - virtual ~LLInventoryFVBridgeBuilder() {} + LLInventoryFolderViewModelBuilder() {} + virtual ~LLInventoryFolderViewModelBuilder() {} virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type, LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, @@ -246,8 +251,10 @@ class LLFolderBridge : public LLInvFVBridge mWearables(FALSE) {} - BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop); - BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop); + BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, BOOL user_confirm = TRUE); + BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, BOOL user_confirm = TRUE); + void callback_dropItemIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryItem* inv_item); + void callback_dropCategoryIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryCategory* inv_item); virtual void buildDisplayName() const; @@ -262,8 +269,9 @@ class LLFolderBridge : public LLInvFVBridge virtual LLUIImagePtr getIcon() const; virtual LLUIImagePtr getIconOpen() const; virtual LLUIImagePtr getIconOverlay() const; - static LLUIImagePtr getIcon(LLFolderType::EType preferred_type); + virtual std::string getLabelSuffix() const; + virtual LLFontGL::StyleFlags getLabelStyle() const; virtual BOOL renameItem(const std::string& new_name); @@ -332,10 +340,15 @@ class LLFolderBridge : public LLInvFVBridge static LLHandle sSelf; static void staticFolderOptionsMenu(); -private: +protected: + void callback_pasteFromClipboard(const LLSD& notification, const LLSD& response, bool only_copies); + void perform_pasteFromClipboard(bool only_copies); + void gatherMessage(std::string& message, S32 depth, LLError::ELevel log_level); + LLUIImagePtr getFolderIcon(BOOL is_open) const; bool mCallingCards; bool mWearables; + std::string mMessage; LLRootHandle mHandle; }; @@ -421,6 +434,7 @@ class LLNotecardBridge : public LLItemBridge const LLUUID& uuid) : LLItemBridge(inventory, root, uuid) {} virtual void openItem(); + virtual void buildContextMenu(LLMenuGL& menu, U32 flags); }; class LLGestureBridge : public LLItemBridge @@ -467,6 +481,7 @@ class LLObjectBridge : public LLItemBridge virtual LLUIImagePtr getIcon() const; virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem(); + virtual BOOL isItemWearable() const { return TRUE; } virtual std::string getLabelSuffix() const; virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual BOOL renameItem(const std::string& new_name); @@ -500,6 +515,7 @@ class LLWearableBridge : public LLItemBridge virtual LLUIImagePtr getIcon() const; virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem(); + virtual BOOL isItemWearable() const { return TRUE; } virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual std::string getLabelSuffix() const; virtual BOOL renameItem(const std::string& new_name); @@ -564,7 +580,6 @@ class LLMeshBridge : public LLItemBridge public: virtual LLUIImagePtr getIcon() const; virtual void openItem(); - virtual void previewItem(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); protected: @@ -628,11 +643,10 @@ class LLRecentItemsFolderBridge : public LLFolderBridge }; // Bridge builder to create Inventory-Folder-View-Bridge for Recent Inventory Panel -class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder +class LLRecentInventoryBridgeBuilder : public LLInventoryFolderViewModelBuilder { public: LLRecentInventoryBridgeBuilder() {} - // Overrides FolderBridge for Recent Inventory Panel. // It use base functionality for bridges other than FolderBridge. virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type, @@ -644,6 +658,31 @@ class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder U32 flags = 0x00) const; }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Marketplace Inventory Panel related classes +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLMarketplaceFolderBridge : public LLFolderBridge +{ +public: + // Overloads some display related methods specific to folders in a marketplace floater context + LLMarketplaceFolderBridge(LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid); + + virtual LLUIImagePtr getIcon() const; + virtual LLUIImagePtr getIconOpen() const; + virtual std::string getLabelSuffix() const; + virtual LLFontGL::StyleFlags getLabelStyle() const; + +private: + LLUIImagePtr getMarketplaceFolderIcon(BOOL is_open) const; + // Those members are mutable because they are cached variables to speed up display, not a state variables + mutable S32 m_depth; + mutable S32 m_stockCountCache; +}; + + void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment, bool replace = false); @@ -671,4 +710,8 @@ class LLFolderViewGroupedItemBridge: public LLFolderViewGroupedItemModel virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu); }; +// Helper functions to classify actions. +bool isAddAction(const std::string& action); +bool isRemoveAction(const std::string& action); + #endif // LL_LLINVENTORYBRIDGE_H diff --git a/indra/newview/llinventoryclipboard.cpp b/indra/newview/llinventoryclipboard.cpp index 2a6fe947db..fd121ee010 100644 --- a/indra/newview/llinventoryclipboard.cpp +++ b/indra/newview/llinventoryclipboard.cpp @@ -62,7 +62,7 @@ void LLInventoryClipboard::store(const LLUUID& object) mObjects.push_back(object); } -void LLInventoryClipboard::store(const std::vector& inv_objects) +void LLInventoryClipboard::store(const uuid_vec_t& inv_objects) { reset(); S32 count = inv_objects.size(); @@ -82,7 +82,7 @@ void LLInventoryClipboard::cut(const LLUUID& object) mCutMode = true; add(object); } -void LLInventoryClipboard::retrieve(std::vector& inv_objects) const +void LLInventoryClipboard::retrieve(uuid_vec_t& inv_objects) const { inv_objects.clear(); S32 count = mObjects.size(); @@ -107,7 +107,7 @@ BOOL LLInventoryClipboard::hasContents() const // returns true if the input uuid is in the list of clipboard objects. bool LLInventoryClipboard::isOnClipboard(const LLUUID& object) const { - std::vector::const_iterator iter = std::find(mObjects.begin(), mObjects.end(), object); + auto iter = std::find(mObjects.begin(), mObjects.end(), object); return (iter != mObjects.end()); } diff --git a/indra/newview/llinventoryclipboard.h b/indra/newview/llinventoryclipboard.h index 35a5c6fcf0..e6d4938820 100644 --- a/indra/newview/llinventoryclipboard.h +++ b/indra/newview/llinventoryclipboard.h @@ -51,12 +51,12 @@ class LLInventoryClipboard void store(const LLUUID& object); // this method stores an array of objects - void store(const std::vector& inventory_objects); + void store(const uuid_vec_t& inventory_objects); void cut(const LLUUID& object); // this method gets the objects in the clipboard by copying them // into the array provided. - void retrieve(std::vector& inventory_objects) const; + void retrieve(uuid_vec_t& inventory_objects) const; // this method empties out the clipboard void reset(); @@ -72,7 +72,7 @@ class LLInventoryClipboard protected: static LLInventoryClipboard sInstance; - std::vector mObjects; + uuid_vec_t mObjects; bool mCutMode; public: diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 519c7aad0d..c43103fce5 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -29,75 +29,75 @@ #include "llinventoryfilter.h" // viewer includes +#include "llappearancemgr.h" #include "llfoldervieweventlistener.h" #include "llfolderviewitem.h" +#include "llinventoryfunctions.h" #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" +#include "llinventoryfunctions.h" +#include "llmarketplacefunctions.h" #include "llviewercontrol.h" #include "llfolderview.h" #include "llinventorybridge.h" #include "llviewerfoldertype.h" +#include "llstartup.h" #include "llagentwearables.h" #include "llvoavatarself.h" -#include "llinventoryclipboard.h" // linden library includes +#include "llinventoryclipboard.h" #include "lltrans.h" -LLInventoryFilter::FilterOps::FilterOps() : - mFilterObjectTypes(0xffffffffffffffffULL), - mFilterCategoryTypes(0xffffffffffffffffULL), - mFilterWearableTypes(0xffffffffffffffffULL), - mMinDate(time_min()), - mMaxDate(time_max()), - mHoursAgo(0), - mShowFolderState(SHOW_NON_EMPTY_FOLDERS), - mPermissions(PERM_NONE), - mFilterTypes(FILTERTYPE_OBJECT), - mFilterWorn(false), - mFilterUUID(LLUUID::null), - mFilterLinks(FILTERLINK_INCLUDE_LINKS) +LLInventoryFilter::FilterOps::FilterOps(const Params& p) +: mFilterTypes(p.types), + mFilterObjectTypes(p.object_types), + mFilterWearableTypes(p.wearable_types), + mFilterCategoryTypes(p.category_types), + mFilterLinks(p.links), + mFilterUUID(p.uuid), + mMinDate(p.date_range.min_date), + mMaxDate(p.date_range.max_date), + mHoursAgo(p.hours_ago), + mDateSearchDirection(p.date_search_direction), + mShowFolderState(p.show_folder_state), + mPermissions(p.permissions), + mFilterWornItems(p.worn_items) { } ///---------------------------------------------------------------------------- /// Class LLInventoryFilter ///---------------------------------------------------------------------------- -LLInventoryFilter::LLInventoryFilter(const std::string& name) -: mName(name), - mModified(FALSE), - mNeedTextRebuild(TRUE) +LLInventoryFilter::LLInventoryFilter(const Params& p) +: mFilterOps(p.filter_ops), + mFilterSubString(p.substring), + mName(p.name), + mFilterModified(FILTER_NONE), + mEmptyLookupMessage("InventoryNoMatchingItems"), + mCurrentGeneration(0), + mFirstRequiredGeneration(0), + mFirstSuccessGeneration(0) { mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately - mSubStringMatchOffset = 0; - mFilterSubString.clear(); - mFilterGeneration = 0; - mMustPassGeneration = S32_MAX; - mMinRequiredGeneration = 0; + mSubStringMatchOffset = std::string::npos; mFilterCount = 0; - mNextFilterGeneration = mFilterGeneration + 1; - - mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff"); - mFilterBehavior = FILTER_NONE; + // Singu Note: Why aren't we calling fromParams here? // copy mFilterOps into mDefaultFilterOps markDefault(); } -LLInventoryFilter::~LLInventoryFilter() -{ -} - -BOOL LLInventoryFilter::check(LLFolderViewItem* item) +bool LLInventoryFilter::check(LLFolderViewItem* item) { // Clipboard cut items are *always* filtered so we need this value upfront const LLFolderViewEventListener* listener = item->getListener(); const LLUUID item_id = listener ? listener->getUUID() : LLUUID::null; - const bool passed_clipboard = item_id.notNull() ? checkAgainstClipboard(item_id) : true; + const bool passed_clipboard = listener && item_id.notNull() ? checkAgainstClipboard(item_id) : true; // If it's a folder and we're showing all folders, return automatically. - const BOOL is_folder = (dynamic_cast(item) != NULL); + const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY; if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)) { return passed_clipboard; @@ -105,17 +105,16 @@ BOOL LLInventoryFilter::check(LLFolderViewItem* item) mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; - const BOOL passed_filtertype = checkAgainstFilterType(item); - const BOOL passed_permissions = checkAgainstPermissions(item); - const BOOL passed_filterlink = checkAgainstFilterLinks(item); - const BOOL passed_wearable = !mFilterOps.mFilterWorn || (gAgentWearables.isWearingItem(item_id) || (gAgentAvatarp && gAgentAvatarp->isWearingAttachment(item_id))); - const BOOL passed = (passed_filtertype && + const bool passed_filtertype = checkAgainstFilterType(item); + const bool passed_permissions = checkAgainstPermissions(item); + const bool passed_filterlink = checkAgainstFilterLinks(item); + const bool passed_wearable = (mFilterOps.mFilterTypes & FILTERTYPE_WORN) != FILTERTYPE_WORN || (gAgentWearables.isWearingItem(item_id) || (gAgentAvatarp && gAgentAvatarp->isWearingAttachment(item_id))); + const bool passed = (passed_filtertype && passed_permissions && passed_filterlink && passed_clipboard && passed_wearable && (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); - return passed; } @@ -131,13 +130,17 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const const LLFolderViewEventListener* listener = folder->getListener(); if (!listener) { - LL_WARNS() << "Folder view event listener not found." << LL_ENDL; - llassert(false); // crash in development builds + LL_ERRS() << "Folder view event listener not found." << LL_ENDL; return false; } const LLUUID folder_id = listener->getUUID(); - + + return checkFolder(folder_id); +} + +bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const +{ // Always check against the clipboard const BOOL passed_clipboard = checkAgainstClipboard(folder_id); @@ -147,13 +150,81 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const return passed_clipboard; } + // when applying a filter, matching folders get their contents downloaded first + // but make sure we are not interfering with pre-download + if (isNotDefault() + && !gInventory.isCategoryComplete(folder_id) + && LLStartUp::getStartupState() > STATE_WEARABLES_WAIT) + { + LLInventoryModelBackgroundFetch::instance().start(folder_id); + } + + // Marketplace folder filtering + const U32 filterTypes = mFilterOps.mFilterTypes; + const U32 marketplace_filter = FILTERTYPE_MARKETPLACE_ACTIVE | FILTERTYPE_MARKETPLACE_INACTIVE | + FILTERTYPE_MARKETPLACE_UNASSOCIATED | FILTERTYPE_MARKETPLACE_LISTING_FOLDER | + FILTERTYPE_NO_MARKETPLACE_ITEMS; + if (filterTypes & marketplace_filter) + { + S32 depth = depth_nesting_in_marketplace(folder_id); + + if (filterTypes & FILTERTYPE_NO_MARKETPLACE_ITEMS) + { + if (depth >= 0) + { + return false; + } + } + + if (filterTypes & FILTERTYPE_MARKETPLACE_LISTING_FOLDER) + { + if (depth > 1) + { + return false; + } + } + + if (depth > 0) + { + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + if (filterTypes & FILTERTYPE_MARKETPLACE_ACTIVE) + { + if (!LLMarketplaceData::instance().getActivationState(listing_uuid)) + { + return false; + } + } + else if (filterTypes & FILTERTYPE_MARKETPLACE_INACTIVE) + { + if (!LLMarketplaceData::instance().isListed(listing_uuid) || LLMarketplaceData::instance().getActivationState(listing_uuid)) + { + return false; + } + } + else if (filterTypes & FILTERTYPE_MARKETPLACE_UNASSOCIATED) + { + if (LLMarketplaceData::instance().isListed(listing_uuid)) + { + return false; + } + } + } + } + + // show folder links + LLViewerInventoryItem* item = gInventory.getItem(folder_id); + if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER) + { + return passed_clipboard; + } + if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY) { // Can only filter categories for items in your inventory // (e.g. versus in-world object contents). const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id); if (!cat) - return false; + return folder_id.isNull(); LLFolderType::EType cat_type = cat->getPreferredType(); if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0)) return false; @@ -162,7 +233,7 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const return passed_clipboard; } -BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const { const LLFolderViewEventListener* listener = item->getListener(); if (!listener) return FALSE; @@ -178,6 +249,7 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con // Pass if this item's type is of the correct filter type if (filterTypes & FILTERTYPE_OBJECT) { + // If it has no type, pass it, unless it's a link. if (object_type == LLInventoryType::IT_NONE) { @@ -210,6 +282,7 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con { const U16 HOURS_TO_SECONDS = 3600; time_t earliest = time_corrected() - mFilterOps.mHoursAgo * HOURS_TO_SECONDS; + if (mFilterOps.mMinDate > time_min() && mFilterOps.mMinDate < earliest) { earliest = mFilterOps.mMinDate; @@ -218,9 +291,19 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con { earliest = 0; } - if (listener->getCreationDate() < earliest || - listener->getCreationDate() > mFilterOps.mMaxDate) - return FALSE; + + if (FILTERDATEDIRECTION_NEWER == mFilterOps.mDateSearchDirection || isSinceLogoff()) + { + if (listener->getCreationDate() < earliest || + listener->getCreationDate() > mFilterOps.mMaxDate) + return FALSE; + } + else + { + if (listener->getCreationDate() > earliest || + listener->getCreationDate() > mFilterOps.mMaxDate) + return FALSE; + } } //////////////////////////////////////////////////////////////////////////////// @@ -246,7 +329,11 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con if (is_hidden_if_empty) { // Force the fetching of those folders so they are hidden if they really are empty... - gInventory.fetchDescendentsOf(object_id); + // But don't interfere with startup download + if (LLStartUp::getStartupState() > STATE_WEARABLES_WAIT) + { + gInventory.fetchDescendentsOf(object_id); + } LLInventoryModel::cat_array_t* cat_array = NULL; LLInventoryModel::item_array_t* item_array = NULL; @@ -264,9 +351,73 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con } } + //////////////////////////////////////////////////////////////////////////////// + // FILTERTYPE_WORN + // Pass if this item is worn + if (filterTypes & FILTERTYPE_WORN) + { + if (!object) return FALSE; + LLUUID cat_id = object->getParentUUID(); + const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + return (get_is_item_worn(object_id) // if it's worn + && !LLAppearanceMgr::instance().getIsInCOF(object_id) // if it's not in CoF + && (!cat || cat->getPreferredType() != LLFolderType::FT_OUTFIT) // if it's not in an outfit + && !object->getIsLinkType()); // and it's not a link + } + return TRUE; } +bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) const +{ + LLInventoryType::EType object_type = item->getInventoryType(); + const LLUUID object_id = item->getUUID(); + + const U32 filterTypes = mFilterOps.mFilterTypes; + + //////////////////////////////////////////////////////////////////////////////// + // FILTERTYPE_OBJECT + // Pass if this item's type is of the correct filter type + if (filterTypes & FILTERTYPE_OBJECT) + { + // If it has no type, pass it, unless it's a link. + if (object_type == LLInventoryType::IT_NONE) + { + if (item && item->getIsLinkType()) + { + return false; + } + } + else if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0)) + { + return false; + } + } + + //////////////////////////////////////////////////////////////////////////////// + // FILTERTYPE_UUID + // Pass if this item is the target UUID or if it links to the target UUID + if (filterTypes & FILTERTYPE_UUID) + { + if (!item) return false; + + if (item->getLinkedUUID() != mFilterOps.mFilterUUID) + return false; + } + + //////////////////////////////////////////////////////////////////////////////// + // FILTERTYPE_DATE + // Pass if this item is within the date range. + if (filterTypes & FILTERTYPE_DATE) + { + // We don't get the updated item creation date for the task inventory or + // a notecard embedded item. See LLTaskInvFVBridge::getCreationDate(). + return false; + } + + return true; +} + // Items and folders that are on the clipboard or, recursively, in a folder which // is on the clipboard must be filtered out if the clipboard is in the "cut" mode. bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const @@ -291,7 +442,7 @@ bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const return true; } -BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const { const LLFolderViewEventListener* listener = item->getListener(); if (!listener) return FALSE; @@ -308,12 +459,23 @@ BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) co return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; } -BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) const +{ + if (!item) return false; + + LLPointer new_item = new LLViewerInventoryItem(item); + PermissionMask perm = new_item->getPermissionMask(); + new_item = NULL; + + return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; +} + +bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const { const LLFolderViewEventListener* listener = item->getListener(); if (!listener) return TRUE; - const LLUUID object_id = listener->getUUID(); + const LLUUID& object_id = listener->getUUID(); const LLInventoryObject *object = gInventory.getObject(object_id); if (!object) return TRUE; @@ -335,27 +497,31 @@ std::string::size_type LLInventoryFilter::getStringMatchOffset() const return mSubStringMatchOffset; } +bool LLInventoryFilter::isDefault() const +{ + return !isNotDefault(); +} + // has user modified default filter params? -BOOL LLInventoryFilter::isNotDefault() const +bool LLInventoryFilter::isNotDefault() const { - BOOL not_default = FALSE; + bool not_default = false; not_default |= (mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes); not_default |= (mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes); not_default |= (mFilterOps.mFilterWearableTypes != mDefaultFilterOps.mFilterWearableTypes); not_default |= (mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes); not_default |= (mFilterOps.mFilterLinks != mDefaultFilterOps.mFilterLinks); - not_default |= (mFilterSubString.size()); - not_default |= (mFilterOps.mFilterWorn != mDefaultFilterOps.mFilterWorn); + not_default |= (mFilterSubString.size() > 0); not_default |= (mFilterOps.mPermissions != mDefaultFilterOps.mPermissions); not_default |= (mFilterOps.mMinDate != mDefaultFilterOps.mMinDate); not_default |= (mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate); not_default |= (mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo); - return not_default; + return not_default != 0; } -BOOL LLInventoryFilter::isActive() const +bool LLInventoryFilter::isActive() const { return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL || mFilterOps.mFilterCategoryTypes != 0xffffffffffffffffULL @@ -363,23 +529,15 @@ BOOL LLInventoryFilter::isActive() const || mFilterOps.mFilterTypes != FILTERTYPE_OBJECT || mFilterOps.mFilterLinks != FILTERLINK_INCLUDE_LINKS || mFilterSubString.size() - || mFilterOps.mFilterWorn != false || mFilterOps.mPermissions != PERM_NONE || mFilterOps.mMinDate != time_min() || mFilterOps.mMaxDate != time_max() || mFilterOps.mHoursAgo != 0; } -BOOL LLInventoryFilter::isModified() const -{ - return mModified; -} - -BOOL LLInventoryFilter::isModifiedAndClear() +bool LLInventoryFilter::isModified() const { - BOOL ret = mModified; - mModified = FALSE; - return ret; + return mFilterModified != FILTER_NONE; } void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types) @@ -393,7 +551,7 @@ void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types) current_types = types; if (more_bits_set && fewer_bits_set) { - // neither less or more restrive, both simultaneously + // neither less or more restrictive, both simultaneously // so we need to filter from scratch setModified(FILTER_RESTART); } @@ -411,6 +569,8 @@ void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types) void LLInventoryFilter::setFilterObjectTypes(U64 types) { + if (types == mFilterOps.mFilterObjectTypes && mFilterOps.mFilterTypes & FILTERTYPE_OBJECT) + return; updateFilterTypes(types, mFilterOps.mFilterObjectTypes); mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT; } @@ -432,8 +592,51 @@ void LLInventoryFilter::setFilterEmptySystemFolders() mFilterOps.mFilterTypes |= FILTERTYPE_EMPTYFOLDERS; } +void LLInventoryFilter::setFilterWornItems() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_WORN; +} + +void LLInventoryFilter::setFilterMarketplaceActiveFolders() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_ACTIVE; +} + +void LLInventoryFilter::setFilterMarketplaceInactiveFolders() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_INACTIVE; +} + +void LLInventoryFilter::setFilterMarketplaceUnassociatedFolders() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_UNASSOCIATED; +} + +void LLInventoryFilter::setFilterMarketplaceListingFolders(bool select_only_listing_folders) +{ + if (select_only_listing_folders) + { + mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_LISTING_FOLDER; + setModified(FILTER_MORE_RESTRICTIVE); + } + else + { + mFilterOps.mFilterTypes &= ~FILTERTYPE_MARKETPLACE_LISTING_FOLDER; + setModified(FILTER_LESS_RESTRICTIVE); + } +} + +void LLInventoryFilter::setFilterNoMarketplaceFolder() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_NO_MARKETPLACE_ITEMS; +} + void LLInventoryFilter::setFilterUUID(const LLUUID& object_id) { + if (mFilterOps.mFilterUUID == object_id) + { + return; + } if (mFilterOps.mFilterUUID == LLUUID::null) { setModified(FILTER_MORE_RESTRICTIVE); @@ -443,7 +646,10 @@ void LLInventoryFilter::setFilterUUID(const LLUUID& object_id) setModified(FILTER_RESTART); } mFilterOps.mFilterUUID = object_id; - mFilterOps.mFilterTypes = FILTERTYPE_UUID; + if(object_id.isNull()) + mFilterOps.mFilterTypes &= ~FILTERTYPE_UUID; + else + mFilterOps.mFilterTypes |= FILTERTYPE_UUID; } void LLInventoryFilter::setFilterSubString(const std::string& string) @@ -478,18 +684,12 @@ void LLInventoryFilter::setFilterSubString(const std::string& string) } // Cancel out UUID once the search string is modified - if (mFilterOps.mFilterTypes == FILTERTYPE_UUID) + if (mFilterOps.mFilterTypes & FILTERTYPE_UUID) { mFilterOps.mFilterTypes &= ~FILTERTYPE_UUID; - //mFilterOps.mFilterUUID == LLUUID::null; + mFilterOps.mFilterUUID == LLUUID::null; setModified(FILTER_RESTART); } - - // Cancel out filter links once the search string is modified - // Singu Note: No, don't do this... - { - //mFilterOps.mFilterLinks = FILTERLINK_INCLUDE_LINKS; - } } } @@ -531,39 +731,53 @@ void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date) mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date); setModified(); } - mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + + if (areDateLimitsSet()) + { + mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + } + else + { + mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE; + } } void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) { + static LLCachedControl s_last_logoff(gSavedPerAccountSettings, "LastLogoff", 0); if (sl && !isSinceLogoff()) { - setDateRange(mLastLogoff, time_max()); + setDateRange(s_last_logoff, time_max()); setModified(); } if (!sl && isSinceLogoff()) { - setDateRange(0, time_max()); + setDateRange(time_min(), time_max()); setModified(); } - mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + + if (areDateLimitsSet()) + { + mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + } + else + { + mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE; + } } -BOOL LLInventoryFilter::isSinceLogoff() const +bool LLInventoryFilter::isSinceLogoff() const { - bool min_date = (mFilterOps.mMinDate == (time_t)mLastLogoff); + static LLCachedControl s_last_logoff(gSavedSettings, "LastLogoff", 0); + bool min_date = (mFilterOps.mMinDate == (time_t)s_last_logoff); bool max_date = (mFilterOps.mMaxDate == time_max()); bool is_filter = (mFilterOps.mFilterTypes & FILTERTYPE_DATE); return min_date && max_date && is_filter; - //return (mFilterOps.mMinDate == (time_t)mLastLogoff) && - // (mFilterOps.mMaxDate == time_max()) && - // (mFilterOps.mFilterTypes & FILTERTYPE_DATE); } void LLInventoryFilter::clearModified() { - mModified = FALSE; - mFilterBehavior = FILTER_NONE; + mFilterModified = FILTER_NONE; } void LLInventoryFilter::setHoursAgo(U32 hours) @@ -572,12 +786,37 @@ void LLInventoryFilter::setHoursAgo(U32 hours) { bool are_date_limits_valid = mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max(); - bool is_increasing = hours > mFilterOps.mHoursAgo; - bool is_increasing_from_zero = is_increasing && !mFilterOps.mHoursAgo; - // *NOTE: need to cache last filter time, in case filter goes stale - BOOL less_restrictive = ((are_date_limits_valid && ((is_increasing && mFilterOps.mHoursAgo))) || !hours); - BOOL more_restrictive = ((are_date_limits_valid && (!is_increasing && hours)) || is_increasing_from_zero); + bool less_restrictive = false; + bool more_restrictive = false; + + switch (mFilterOps.mDateSearchDirection) + { + case FILTERDATEDIRECTION_NEWER: + less_restrictive = ((are_date_limits_valid && (hours > mFilterOps.mHoursAgo + && mFilterOps.mHoursAgo)) + || !hours); + + more_restrictive = ((are_date_limits_valid && (hours < mFilterOps.mHoursAgo + && hours)) + || (hours > mFilterOps.mHoursAgo + && !mFilterOps.mHoursAgo + && !isSinceLogoff())); + break; + case FILTERDATEDIRECTION_OLDER: + less_restrictive = ((are_date_limits_valid && (hours < mFilterOps.mHoursAgo + && mFilterOps.mHoursAgo)) + || !hours); + + more_restrictive = ((are_date_limits_valid && (hours > mFilterOps.mHoursAgo + && hours)) + || (hours < mFilterOps.mHoursAgo + && !mFilterOps.mHoursAgo + && !isSinceLogoff())); + break; + default: + break; + } mFilterOps.mHoursAgo = hours; mFilterOps.mMinDate = time_min(); @@ -595,20 +834,42 @@ void LLInventoryFilter::setHoursAgo(U32 hours) setModified(FILTER_RESTART); } } - mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + + if (areDateLimitsSet()) + { + mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + } + else + { + mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE; + } +} + +void LLInventoryFilter::setDateSearchDirection(U32 direction) +{ + if (direction != mFilterOps.mDateSearchDirection) + { + mFilterOps.mDateSearchDirection = direction; + setModified(FILTER_RESTART); + } +} + +U32 LLInventoryFilter::getDateSearchDirection() const +{ + return mFilterOps.mDateSearchDirection; } -void LLInventoryFilter::setFilterLinks(U64 filter_links) +void LLInventoryFilter::setFilterLinks(EFilterLink filter_links) { if (mFilterOps.mFilterLinks != filter_links) { - if (mFilterOps.mFilterLinks == FILTERLINK_EXCLUDE_LINKS || - mFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS) + mFilterOps.mFilterLinks = filter_links; + if (filter_links == FILTERLINK_EXCLUDE_LINKS || + filter_links == FILTERLINK_ONLY_LINKS) setModified(FILTER_MORE_RESTRICTIVE); else setModified(FILTER_LESS_RESTRICTIVE); } - mFilterOps.mFilterLinks = filter_links; } void LLInventoryFilter::setShowFolderState(EFolderShow state) @@ -653,83 +914,68 @@ void LLInventoryFilter::resetDefault() setModified(); } -void LLInventoryFilter::setModified(EFilterBehavior behavior) +void LLInventoryFilter::setModified(EFilterModified behavior) { - mModified = TRUE; - mNeedTextRebuild = TRUE; - mFilterGeneration = mNextFilterGeneration++; + mFilterText.clear(); + mCurrentGeneration++; - if (mFilterBehavior == FILTER_NONE) + if (mFilterModified == FILTER_NONE) { - mFilterBehavior = behavior; + mFilterModified = behavior; } - else if (mFilterBehavior != behavior) + else if (mFilterModified != behavior) { // trying to do both less restrictive and more restrictive filter // basically means restart from scratch - mFilterBehavior = FILTER_RESTART; + mFilterModified = FILTER_RESTART; } - if (isNotDefault()) - { - // if not keeping current filter results, update last valid as well - switch(mFilterBehavior) - { - case FILTER_RESTART: - mMustPassGeneration = mFilterGeneration; - mMinRequiredGeneration = mFilterGeneration; - break; - case FILTER_LESS_RESTRICTIVE: - mMustPassGeneration = mFilterGeneration; - break; - case FILTER_MORE_RESTRICTIVE: - mMinRequiredGeneration = mFilterGeneration; - // must have passed either current filter generation (meaningless, as it hasn't been run yet) - // or some older generation, so keep the value - mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration); - break; - default: - LL_ERRS() << "Bad filter behavior specified" << LL_ENDL; - } - } - else + // if not keeping current filter results, update last valid as well + switch(mFilterModified) { - // shortcut disabled filters to show everything immediately - mMinRequiredGeneration = 0; - mMustPassGeneration = S32_MAX; + case FILTER_RESTART: + mFirstRequiredGeneration = mCurrentGeneration; + mFirstSuccessGeneration = mCurrentGeneration; + break; + case FILTER_LESS_RESTRICTIVE: + mFirstRequiredGeneration = mCurrentGeneration; + break; + case FILTER_MORE_RESTRICTIVE: + mFirstSuccessGeneration = mCurrentGeneration; + break; + default: + LL_ERRS() << "Bad filter behavior specified" << LL_ENDL; } } -BOOL LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const +bool LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const { return mFilterOps.mFilterObjectTypes & (1LL << t); } const std::string& LLInventoryFilter::getFilterText() { - if (!mNeedTextRebuild) + if (!mFilterText.empty()) { return mFilterText; } - mNeedTextRebuild = FALSE; std::string filtered_types; std::string not_filtered_types; BOOL filtered_by_type = FALSE; BOOL filtered_by_all_types = TRUE; S32 num_filter_types = 0; + mFilterText.clear(); if (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION)) { - //filtered_types += " Animations,"; filtered_types += LLTrans::getString("Animations"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Animations,"; not_filtered_types += LLTrans::getString("Animations"); filtered_by_all_types = FALSE; @@ -737,146 +983,126 @@ const std::string& LLInventoryFilter::getFilterText() if (isFilterObjectTypesWith(LLInventoryType::IT_CALLINGCARD)) { - //filtered_types += " Calling Cards,"; filtered_types += LLTrans::getString("Calling Cards"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Calling Cards,"; not_filtered_types += LLTrans::getString("Calling Cards"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_WEARABLE)) { - //filtered_types += " Clothing,"; filtered_types += LLTrans::getString("Clothing"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Clothing,"; not_filtered_types += LLTrans::getString("Clothing"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_GESTURE)) { - //filtered_types += " Gestures,"; filtered_types += LLTrans::getString("Gestures"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Gestures,"; not_filtered_types += LLTrans::getString("Gestures"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_LANDMARK)) { - //filtered_types += " Landmarks,"; filtered_types += LLTrans::getString("Landmarks"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Landmarks,"; not_filtered_types += LLTrans::getString("Landmarks"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD)) { - //filtered_types += " Notecards,"; filtered_types += LLTrans::getString("Notecards"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Notecards,"; not_filtered_types += LLTrans::getString("Notecards"); filtered_by_all_types = FALSE; } - + if (isFilterObjectTypesWith(LLInventoryType::IT_OBJECT) && isFilterObjectTypesWith(LLInventoryType::IT_ATTACHMENT)) { - //filtered_types += " Objects,"; filtered_types += LLTrans::getString("Objects"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Objects,"; not_filtered_types += LLTrans::getString("Objects"); filtered_by_all_types = FALSE; } - + if (isFilterObjectTypesWith(LLInventoryType::IT_LSL)) { - //filtered_types += " Scripts,"; filtered_types += LLTrans::getString("Scripts"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Scripts,"; not_filtered_types += LLTrans::getString("Scripts"); filtered_by_all_types = FALSE; } - + if (isFilterObjectTypesWith(LLInventoryType::IT_SOUND)) { - //filtered_types += " Sounds,"; filtered_types += LLTrans::getString("Sounds"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Sounds,"; not_filtered_types += LLTrans::getString("Sounds"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_TEXTURE)) { - //filtered_types += " Textures,"; filtered_types += LLTrans::getString("Textures"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Textures,"; not_filtered_types += LLTrans::getString("Textures"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_SNAPSHOT)) { - //filtered_types += " Snapshots,"; filtered_types += LLTrans::getString("Snapshots"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Snapshots,"; not_filtered_types += LLTrans::getString("Snapshots"); filtered_by_all_types = FALSE; } - if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive() - && filtered_by_type + if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive() + && filtered_by_type && !filtered_by_all_types) { mFilterText += " - "; @@ -886,7 +1112,6 @@ const std::string& LLInventoryFilter::getFilterText() } else { - //mFilterText += "No "; mFilterText += LLTrans::getString("No Filters"); mFilterText += not_filtered_types; } @@ -896,73 +1121,79 @@ const std::string& LLInventoryFilter::getFilterText() if (isSinceLogoff()) { - //mFilterText += " - Since Logoff"; mFilterText += LLTrans::getString("Since Logoff"); } - - if (getFilterWorn()) + + if (getFilterWornItems()) { - //mFilterText += " - Worn"; mFilterText += LLTrans::getString("Worn"); } - + return mFilterText; } -void LLInventoryFilter::toLLSD(LLSD& data) const +LLInventoryFilter& LLInventoryFilter::operator=( const LLInventoryFilter& other ) { - data["filter_types"] = (LLSD::Integer)getFilterObjectTypes(); - data["min_date"] = (LLSD::Integer)getMinDate(); - data["max_date"] = (LLSD::Integer)getMaxDate(); - data["hours_ago"] = (LLSD::Integer)getHoursAgo(); - data["show_folder_state"] = (LLSD::Integer)getShowFolderState(); - data["permissions"] = (LLSD::Integer)getFilterPermissions(); - data["substring"] = (LLSD::String)getFilterSubString(); - data["sort_order"] = (LLSD::Integer)getSortOrder(); - data["since_logoff"] = (LLSD::Boolean)isSinceLogoff(); + setFilterObjectTypes(other.getFilterObjectTypes()); + setDateRange(other.getMinDate(), other.getMaxDate()); + setHoursAgo(other.getHoursAgo()); + setDateSearchDirection(other.getDateSearchDirection()); + setShowFolderState(other.getShowFolderState()); + setFilterPermissions(other.getFilterPermissions()); + setFilterSubString(other.getFilterSubString()); + setDateRangeLastLogoff(other.isSinceLogoff()); + return *this; } -void LLInventoryFilter::fromLLSD(LLSD& data) -{ - if(data.has("filter_types")) - { - setFilterObjectTypes((U32)data["filter_types"].asInteger()); - } - - if(data.has("min_date") && data.has("max_date")) - { - setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger()); - } - - if(data.has("hours_ago")) - { - setHoursAgo((U32)data["hours_ago"].asInteger()); - } - if(data.has("show_folder_state")) +void LLInventoryFilter::toParams(Params& params) const +{ + params.filter_ops.types = getFilterObjectTypes(); + params.filter_ops.category_types = getFilterCategoryTypes(); + if (getFilterObjectTypes() & FILTERTYPE_WEARABLE) { - setShowFolderState((EFolderShow)data["show_folder_state"].asInteger()); + params.filter_ops.wearable_types = getFilterWearableTypes(); } + params.filter_ops.date_range.min_date = getMinDate(); + params.filter_ops.date_range.max_date = getMaxDate(); + params.filter_ops.hours_ago = getHoursAgo(); + params.filter_ops.date_search_direction = getDateSearchDirection(); + params.filter_ops.show_folder_state = getShowFolderState(); + params.filter_ops.permissions = getFilterPermissions(); + params.substring = getFilterSubString(); + params.since_logoff = isSinceLogoff(); +} - if(data.has("permissions")) +void LLInventoryFilter::fromParams(const Params& params) +{ + if (!params.validateBlock()) { - setFilterPermissions((PermissionMask)data["permissions"].asInteger()); + return; } - if(data.has("substring")) + setFilterObjectTypes(params.filter_ops.types); + setFilterCategoryTypes(params.filter_ops.category_types); + if (params.filter_ops.wearable_types.isProvided()) { - setFilterSubString(std::string(data["substring"].asString())); + setFilterWearableTypes(params.filter_ops.wearable_types); } - if(data.has("sort_order")) + setDateRange(params.filter_ops.date_range.min_date, params.filter_ops.date_range.max_date); + setHoursAgo(params.filter_ops.hours_ago); + setDateSearchDirection(params.filter_ops.date_search_direction); + setShowFolderState(params.filter_ops.show_folder_state); + setFilterPermissions(params.filter_ops.permissions); + setFilterSubString(params.substring); + setDateRangeLastLogoff(params.since_logoff); + if (params.filter_ops.links.isProvided()) { - setSortOrder((U32)data["sort_order"].asInteger()); + setFilterLinks(params.filter_ops.links); } +} - if(data.has("since_logoff")) - { - setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean()); - } +U64 LLInventoryFilter::getFilterTypes() const +{ + return mFilterOps.mFilterTypes; } U64 LLInventoryFilter::getFilterObjectTypes() const @@ -975,11 +1206,26 @@ U64 LLInventoryFilter::getFilterCategoryTypes() const return mFilterOps.mFilterCategoryTypes; } -BOOL LLInventoryFilter::hasFilterString() const +U64 LLInventoryFilter::getFilterWearableTypes() const +{ + return mFilterOps.mFilterWearableTypes; +} + +U64 LLInventoryFilter::getFilterWornItems() const +{ + return mFilterOps.mFilterTypes & FILTERTYPE_WORN; +} + +bool LLInventoryFilter::hasFilterString() const { return mFilterSubString.size() > 0; } +std::string::size_type LLInventoryFilter::getFilterStringSize() const +{ + return mFilterSubString.size(); +} + PermissionMask LLInventoryFilter::getFilterPermissions() const { return mFilterOps.mPermissions; @@ -998,7 +1244,7 @@ U32 LLInventoryFilter::getHoursAgo() const { return mFilterOps.mHoursAgo; } -U64 LLInventoryFilter::getFilterLinks() const +LLInventoryFilter::EFilterLink LLInventoryFilter::getFilterLinks() const { return mFilterOps.mFilterLinks; } @@ -1010,10 +1256,6 @@ U32 LLInventoryFilter::getSortOrder() const { return mOrder; } -const std::string& LLInventoryFilter::getName() const -{ - return mName; -} void LLInventoryFilter::setFilterCount(S32 count) { @@ -1031,13 +1273,58 @@ void LLInventoryFilter::decrementFilterCount() S32 LLInventoryFilter::getCurrentGeneration() const { - return mFilterGeneration; + return mCurrentGeneration; } -S32 LLInventoryFilter::getMinRequiredGeneration() const +S32 LLInventoryFilter::getFirstSuccessGeneration() const { - return mMinRequiredGeneration; + return mFirstSuccessGeneration; } -S32 LLInventoryFilter::getMustPassGeneration() const +S32 LLInventoryFilter::getFirstRequiredGeneration() const { - return mMustPassGeneration; + return mFirstRequiredGeneration; +} + +void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) +{ + mEmptyLookupMessage = message; +} + +std::string LLInventoryFilter::getEmptyLookupMessage() const +{ + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(getFilterSubStringOrig()); + + return LLTrans::getString(mEmptyLookupMessage, args); + +} + +bool LLInventoryFilter::areDateLimitsSet() +{ + return mFilterOps.mMinDate != time_min() + || mFilterOps.mMaxDate != time_max() + || mFilterOps.mHoursAgo != 0; +} + +bool LLInventoryFilter::showAllResults() const +{ + return hasFilterString(); +} + + + +bool LLInventoryFilter::FilterOps::DateRange::validateBlock( bool emit_errors /*= true*/ ) const +{ + bool valid = LLInitParam::Block::validateBlock(emit_errors); + if (valid) + { + if (max_date() < min_date()) + { + if (emit_errors) + { + LL_WARNS() << "max_date should be greater or equal to min_date" << LL_ENDL; + } + valid = false; + } + } + return valid; } diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 588844c013..789e37dcf3 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -32,24 +32,25 @@ class LLFolderViewItem; class LLFolderViewFolder; +class LLInventoryItem; class LLInventoryFilter { public: - enum EFolderShow - { - SHOW_ALL_FOLDERS, - SHOW_NON_EMPTY_FOLDERS, - SHOW_NO_FOLDERS - }; - - enum EFilterBehavior + enum EFilterModified { FILTER_NONE, // nothing to do, already filtered FILTER_RESTART, // restart filtering from scratch FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one }; + + enum EFolderShow + { + SHOW_ALL_FOLDERS, + SHOW_NON_EMPTY_FOLDERS, + SHOW_NO_FOLDERS + }; enum EFilterType { FILTERTYPE_NONE = 0, @@ -58,7 +59,20 @@ class LLInventoryFilter FILTERTYPE_UUID = 0x1 << 2, // find the object with UUID and any links to it FILTERTYPE_DATE = 0x1 << 3, // search by date range FILTERTYPE_WEARABLE = 0x1 << 4, // search by wearable type - FILTERTYPE_EMPTYFOLDERS = 0x1 << 5 // pass if folder is not a system folder to be hidden if empty + FILTERTYPE_EMPTYFOLDERS = 0x1 << 5, // pass if folder is not a system folder to be hidden if empty + FILTERTYPE_MARKETPLACE_ACTIVE = 0x1 << 6, // pass if folder is a marketplace active folder + FILTERTYPE_MARKETPLACE_INACTIVE = 0x1 << 7, // pass if folder is a marketplace inactive folder + FILTERTYPE_MARKETPLACE_UNASSOCIATED = 0x1 << 8, // pass if folder is a marketplace non associated (no market ID) folder + FILTERTYPE_MARKETPLACE_LISTING_FOLDER = 0x1 << 9, // pass iff folder is a listing folder + FILTERTYPE_NO_MARKETPLACE_ITEMS = 0x1 << 10, // pass iff folder is not under the marketplace + FILTERTYPE_WORN = 0x1 << 11 // search by worn items + + }; + + enum EFilterDateDirection + { + FILTERDATEDIRECTION_NEWER, + FILTERDATEDIRECTION_OLDER }; enum EFilterLink @@ -73,32 +87,124 @@ class LLInventoryFilter SO_NAME = 0, // Sort inventory by name SO_DATE = 0x1, // Sort inventory by date SO_FOLDERS_BY_NAME = 0x1 << 1, // Force folder sort by name - SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2 // Force system folders to be on top + SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2, // Force system folders to be on top + SO_FOLDERS_BY_WEIGHT = 0x1 << 3, // Force folder sort by weight, usually, amount of some elements in their descendents }; - LLInventoryFilter(const std::string& name); - virtual ~LLInventoryFilter(); + struct FilterOps + { + struct DateRange : public LLInitParam::Block + { + Optional min_date, + max_date; + + DateRange() + : min_date("min_date", time_min()), + max_date("max_date", time_max()) + {} + + bool validateBlock(bool emit_errors = true) const; + }; + + struct Params : public LLInitParam::Block + { + Optional types; + Optional object_types, + wearable_types, + category_types, + worn_items; + Optional links; + Optional uuid; + Optional date_range; + Optional hours_ago; + Optional date_search_direction; + Optional show_folder_state; + Optional permissions; + + Params() + : types("filter_types", FILTERTYPE_OBJECT), + object_types("object_types", 0xffffFFFFffffFFFFULL), + wearable_types("wearable_types", 0/*0xffffFFFFffffFFFFULL*/), + category_types("category_types", 0xffffFFFFffffFFFFULL), + worn_items("worn_items", 0xffffFFFFffffFFFFULL), + links("links", FILTERLINK_INCLUDE_LINKS), + uuid("uuid"), + date_range("date_range"), + hours_ago("hours_ago", 0), + date_search_direction("date_search_direction", FILTERDATEDIRECTION_NEWER), + show_folder_state("show_folder_state", SHOW_NON_EMPTY_FOLDERS), + permissions("permissions", PERM_NONE) + { + addSynonym(links, "filter_links"); + } + }; + + FilterOps(const Params& = Params()); + + U32 mFilterTypes; + U64 mFilterObjectTypes, // For _OBJECT + mFilterWearableTypes, + mFilterCategoryTypes, // For _CATEGORY + mFilterWornItems; + EFilterLink mFilterLinks; + LLUUID mFilterUUID; // for UUID + + time_t mMinDate, + mMaxDate; + U32 mHoursAgo; + U32 mDateSearchDirection; + + EFolderShow mShowFolderState; + PermissionMask mPermissions; + + bool mFilterWorn; + }; + + struct Params : public LLInitParam::Block + { + Optional name; + Optional filter_ops; + Optional substring; + Optional since_logoff; + + Params() + : name("name"), + filter_ops(""), + substring("substring"), + since_logoff("since_logoff") + {} + }; + + LLInventoryFilter(const Params& p = Params()); + LLInventoryFilter(const LLInventoryFilter& other) { *this = other; } + virtual ~LLInventoryFilter() {} // +-------------------------------------------------------------------+ // + Parameters // +-------------------------------------------------------------------+ - void setFilterObjectTypes(U64 types); + U64 getFilterTypes() const; U64 getFilterObjectTypes() const; U64 getFilterCategoryTypes() const; - BOOL isFilterObjectTypesWith(LLInventoryType::EType t) const; + U64 getFilterWearableTypes() const; + U64 getFilterWornItems() const; + bool isFilterObjectTypesWith(LLInventoryType::EType t) const; + void setFilterObjectTypes(U64 types); void setFilterCategoryTypes(U64 types); void setFilterUUID(const LLUUID &object_id); void setFilterWearableTypes(U64 types); void setFilterEmptySystemFolders(); + void setFilterMarketplaceActiveFolders(); + void setFilterMarketplaceInactiveFolders(); + void setFilterMarketplaceUnassociatedFolders(); + void setFilterMarketplaceListingFolders(bool select_only_listing_folders); + void setFilterNoMarketplaceFolder(); void updateFilterTypes(U64 types, U64& current_types); + void setFilterWornItems(); void setFilterSubString(const std::string& string); const std::string& getFilterSubString(BOOL trim = FALSE) const; const std::string& getFilterSubStringOrig() const { return mFilterSubStringOrig; } - BOOL hasFilterString() const; - - void setFilterWorn(bool worn) { mFilterOps.mFilterWorn = worn; } - bool getFilterWorn() const { return mFilterOps.mFilterWorn; } + bool hasFilterString() const; void setFilterPermissions(PermissionMask perms); PermissionMask getFilterPermissions() const; @@ -110,46 +216,48 @@ class LLInventoryFilter void setHoursAgo(U32 hours); U32 getHoursAgo() const; + void setDateSearchDirection(U32 direction); + U32 getDateSearchDirection() const; - void setFilterLinks(U64 filter_link); - U64 getFilterLinks() const; + void setFilterLinks(EFilterLink filter_link); + EFilterLink getFilterLinks() const; // +-------------------------------------------------------------------+ // + Execution And Results // +-------------------------------------------------------------------+ - BOOL check(LLFolderViewItem* item); + bool check(LLFolderViewItem* item); + bool check(const LLInventoryItem* item); bool checkFolder(const LLFolderViewFolder* folder) const; - BOOL checkAgainstFilterType(const LLFolderViewItem* item) const; - BOOL checkAgainstPermissions(const LLFolderViewItem* item) const; - BOOL checkAgainstFilterLinks(const LLFolderViewItem* item) const; - bool checkAgainstClipboard(const LLUUID& object_id) const; + bool checkFolder(const LLUUID& folder_id) const; - std::string::size_type getStringMatchOffset() const; + bool showAllResults() const; + std::string::size_type getStringMatchOffset() const; + std::string::size_type getFilterStringSize() const; // +-------------------------------------------------------------------+ // + Presentation // +-------------------------------------------------------------------+ void setShowFolderState( EFolderShow state); EFolderShow getShowFolderState() const; + void setEmptyLookupMessage(const std::string& message); + std::string getEmptyLookupMessage() const; + void setSortOrder(U32 order); U32 getSortOrder() const; - - // +-------------------------------------------------------------------+ // + Status // +-------------------------------------------------------------------+ - BOOL isActive() const; + bool isActive() const; - BOOL isModified() const; - BOOL isModifiedAndClear(); - BOOL isSinceLogoff() const; + bool isModified() const; + bool isSinceLogoff() const; void clearModified(); - const std::string& getName() const; + const std::string& getName() const { return mName; } const std::string& getFilterText(); //RN: this is public to allow system to externally force a global refilter - void setModified(EFilterBehavior behavior = FILTER_RESTART); + void setModified(EFilterModified behavior = FILTER_RESTART); // +-------------------------------------------------------------------+ // + Count @@ -161,7 +269,8 @@ class LLInventoryFilter // +-------------------------------------------------------------------+ // + Default // +-------------------------------------------------------------------+ - BOOL isNotDefault() const; + bool isDefault() const; + bool isNotDefault() const; void markDefault(); void resetDefault(); @@ -169,37 +278,27 @@ class LLInventoryFilter // + Generation // +-------------------------------------------------------------------+ S32 getCurrentGeneration() const; - S32 getMinRequiredGeneration() const; - S32 getMustPassGeneration() const; + S32 getFirstSuccessGeneration() const; + S32 getFirstRequiredGeneration() const; // +-------------------------------------------------------------------+ // + Conversion // +-------------------------------------------------------------------+ - void toLLSD(LLSD& data) const; - void fromLLSD(LLSD& data); + void toParams(Params& params) const; + void fromParams(const Params& p); -private: - struct FilterOps - { - FilterOps(); - U32 mFilterTypes; - - U64 mFilterObjectTypes; // For _OBJECT - U64 mFilterWearableTypes; - U64 mFilterCategoryTypes; // For _CATEGORY - LLUUID mFilterUUID; // for UUID + LLInventoryFilter& operator =(const LLInventoryFilter& other); - time_t mMinDate; - time_t mMaxDate; - U32 mHoursAgo; - EFolderShow mShowFolderState; - PermissionMask mPermissions; - U64 mFilterLinks; - bool mFilterWorn; - }; +private: + bool areDateLimitsSet(); + bool checkAgainstFilterType(const LLFolderViewItem* item) const; + bool checkAgainstFilterType(const LLInventoryItem* item) const; + bool checkAgainstPermissions(const LLFolderViewItem* item) const; + bool checkAgainstPermissions(const LLInventoryItem* item) const; + bool checkAgainstFilterLinks(const LLFolderViewItem* item) const; + bool checkAgainstClipboard(const LLUUID& object_id) const; U32 mOrder; - U32 mLastLogoff; FilterOps mFilterOps; FilterOps mDefaultFilterOps; @@ -209,17 +308,18 @@ class LLInventoryFilter std::string mFilterSubStringOrig; const std::string mName; - S32 mFilterGeneration; - S32 mMustPassGeneration; - S32 mMinRequiredGeneration; - S32 mNextFilterGeneration; + S32 mCurrentGeneration; + // The following makes checking for pass/no pass possible even if the item is not checked against the current generation + // Any item that *did not pass* the "required generation" will *not pass* the current one + // Any item that *passes* the "success generation" will *pass* the current one + S32 mFirstRequiredGeneration; + S32 mFirstSuccessGeneration; S32 mFilterCount; - EFilterBehavior mFilterBehavior; + EFilterModified mFilterModified; - BOOL mModified; - BOOL mNeedTextRebuild; std::string mFilterText; + std::string mEmptyLookupMessage; }; #endif diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 124fbffe15..d23ad44178 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -37,6 +37,7 @@ #include "llinventorydefines.h" #include "llsdserialize.h" #include "llspinctrl.h" +#include "lltrans.h" #include "llui.h" #include "message.h" @@ -45,7 +46,7 @@ #include "llappviewer.h" //#include "llfirstuse.h" #include "llfloaterinventory.h" -#include "llfloateroutbox.h" +#include "llfloatermarketplacelistings.h" #include "llfocusmgr.h" #include "llfolderview.h" #include "llgesturemgr.h" @@ -57,6 +58,7 @@ #include "llinventorypanel.h" #include "lllineeditor.h" #include "llmarketplacenotifications.h" +#include "llmarketplacefunctions.h" #include "llmenugl.h" #include "llnotificationsutil.h" #include "llpanelmaininventory.h" @@ -79,17 +81,135 @@ #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llwearablelist.h" - -#include - // [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" #include "rlvlocks.h" // [/RLVa:KB] +#include + BOOL LLInventoryState::sWearNewClothing = FALSE; LLUUID LLInventoryState::sWearNewClothingTransactionID; +// Helper function : callback to update a folder after inventory action happened in the background +void update_folder_cb(const LLUUID& dest_folder) +{ + LLViewerInventoryCategory* dest_cat = gInventory.getCategory(dest_folder); + gInventory.updateCategory(dest_cat); + gInventory.notifyObservers(); +} + +// Helper function : Count only the copyable items, i.e. skip the stock items (which are no copy) +S32 count_copyable_items(LLInventoryModel::item_array_t& items) +{ + S32 count = 0; + for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it) + { + LLViewerInventoryItem* item = *it; + if (item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + count++; + } + } + return count; +} + +// Helper function : Count only the non-copyable items, i.e. the stock items, skip the others +S32 count_stock_items(LLInventoryModel::item_array_t& items) +{ + S32 count = 0; + for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it) + { + LLViewerInventoryItem* item = *it; + if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + count++; + } + } + return count; +} + +// Helper function : Count the number of stock folders +S32 count_stock_folders(LLInventoryModel::cat_array_t& categories) +{ + S32 count = 0; + for (LLInventoryModel::cat_array_t::const_iterator it = categories.begin(); it != categories.end(); ++it) + { + LLInventoryCategory* cat = *it; + if (cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + count++; + } + } + return count; +} + +// Helper funtion : Count the number of items (not folders) in the descending hierarchy +S32 count_descendants_items(const LLUUID& cat_id) +{ + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array); + + S32 count = item_array->size(); + + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLViewerInventoryCategory* category = *iter; + count += count_descendants_items(category->getUUID()); + } + + return count; +} + +// Helper function : Returns true if the hierarchy contains nocopy items +bool contains_nocopy_items(const LLUUID& id) +{ + LLInventoryCategory* cat = gInventory.getCategory(id); + + if (cat) + { + // Get the content + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(id,cat_array,item_array); + + // Check all the items: returns true upon encountering a nocopy item + for (LLInventoryModel::item_array_t::iterator iter = item_array->begin(); iter != item_array->end(); iter++) + { + LLInventoryItem* item = *iter; + LLViewerInventoryItem * inv_item = (LLViewerInventoryItem *) item; + if (!inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + return true; + } + } + + // Check all the sub folders recursively + for (LLInventoryModel::cat_array_t::iterator iter = cat_array->begin(); iter != cat_array->end(); iter++) + { + LLViewerInventoryCategory* cat = *iter; + if (contains_nocopy_items(cat->getUUID())) + { + return true; + } + } + } + else + { + LLInventoryItem* item = gInventory.getItem(id); + LLViewerInventoryItem * inv_item = (LLViewerInventoryItem *) item; + if (!inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + return true; + } + } + + // Exit without meeting a nocopy item + return false; +} + // Generates a string containing the path to the item specified by // item_id. void append_path(const LLUUID& id, std::string& path) @@ -111,35 +231,149 @@ void append_path(const LLUUID& id, std::string& path) path.append(temp); } -// Path should already end on '/' if it is not empty. -void append_path_short(LLUUID const& id, std::string& path) +void update_marketplace_folder_hierarchy(const LLUUID cat_id) { - LLInventoryObject const* obj = gInventory.getObject(id); - if (!obj) return; + // When changing the marketplace status of a folder, the only thing that needs to happen is + // for all observers of the folder to, possibly, change the display label of the folder + // so that's the only thing we change on the update mask. + gInventory.addChangedMask(LLInventoryObserver::LABEL, cat_id); + + // Update all descendent folders down + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array); - LLUUID const root_id = gInventory.getRootFolderID(); - std::string const forward_slash("/"); + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLInventoryCategory* category = *iter; + update_marketplace_folder_hierarchy(category->getUUID()); + } + return; +} - std::string result; - while(1) +void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistency_enforcement) +{ + // When changing the marketplace status of an item, we usually have to change the status of all + // folders in the same listing. This is because the display of each folder is affected by the + // overall status of the whole listing. + // Consequently, the only way to correctly update an item anywhere in the marketplace is to + // update the whole listing from its listing root. + // This is not as bad as it seems as we only update folders, not items, and the folder nesting depth + // is limited to 4. + // We also take care of degenerated cases so we don't update all folders in the inventory by mistake. + + if (cur_uuid.isNull() + || gInventory.getCategory(cur_uuid) == NULL + || gInventory.getCategory(cur_uuid)->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) { - LLUUID parent_id = obj->getParentUUID(); - if (parent_id == root_id || - !(obj = gInventory.getCategory(parent_id))) + return; + } + + // Grab marketplace listing data for this item + S32 depth = depth_nesting_in_marketplace(cur_uuid); + if (depth > 0) + { + // Retrieve the listing uuid this object is in + LLUUID listing_uuid = nested_parent_id(cur_uuid, depth); + LLViewerInventoryCategory* listing_cat = gInventory.getCategory(listing_uuid); + bool listing_cat_loaded = listing_cat != NULL && listing_cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN; + + // Verify marketplace data consistency for this listing + if (perform_consistency_enforcement + && listing_cat_loaded + && LLMarketplaceData::instance().isListed(listing_uuid)) { - break; + LLUUID version_folder_uuid = LLMarketplaceData::instance().getVersionFolder(listing_uuid); + S32 version_depth = depth_nesting_in_marketplace(version_folder_uuid); + if (version_folder_uuid.notNull() && (!gInventory.isObjectDescendentOf(version_folder_uuid, listing_uuid) || (version_depth != 2))) + { + LL_INFOS("SLM") << "Unlist and clear version folder as the version folder is not at the right place anymore!!" << LL_ENDL; + LLMarketplaceData::instance().setVersionFolder(listing_uuid, LLUUID::null,1); + } + else if (version_folder_uuid.notNull() + && gInventory.isCategoryComplete(version_folder_uuid) + && LLMarketplaceData::instance().getActivationState(version_folder_uuid) + && (count_descendants_items(version_folder_uuid) == 0) + && !LLMarketplaceData::instance().isUpdating(version_folder_uuid,version_depth)) + { + LL_INFOS("SLM") << "Unlist as the version folder is empty of any item!!" << LL_ENDL; + LLNotificationsUtil::add("AlertMerchantVersionFolderEmpty"); + LLMarketplaceData::instance().activateListing(listing_uuid, false,1); + } + } + + // Check if the count on hand needs to be updated on SLM + if (perform_consistency_enforcement + && listing_cat_loaded + && (compute_stock_count(listing_uuid) != LLMarketplaceData::instance().getCountOnHand(listing_uuid))) + { + LLMarketplaceData::instance().updateCountOnHand(listing_uuid,1); + } + // Update all descendents starting from the listing root + update_marketplace_folder_hierarchy(listing_uuid); + } + else if (depth == 0) + { + // If this is the marketplace listings root itself, update all descendents + if (gInventory.getCategory(cur_uuid)) + { + update_marketplace_folder_hierarchy(cur_uuid); + } + } + else + { + // If the folder is outside the marketplace listings root, clear its SLM data if needs be + if (perform_consistency_enforcement && LLMarketplaceData::instance().isListed(cur_uuid)) + { + LL_INFOS("SLM") << "Disassociate as the listing folder is not under the marketplace folder anymore!!" << LL_ENDL; + LLMarketplaceData::instance().clearListing(cur_uuid); + } + // Update all descendents if this is a category + if (gInventory.getCategory(cur_uuid)) + { + update_marketplace_folder_hierarchy(cur_uuid); } - std::string temp; - temp.swap(result); - result = obj->getName(); - if (!temp.empty()) + } + + return; +} + +// Iterate through the marketplace and flag for label change all categories that countain a stock folder (i.e. stock folders and embedding folders up the hierarchy) +void update_all_marketplace_count(const LLUUID& cat_id) +{ + // Get all descendent folders down + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat_id, cat_array, item_array); + + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLInventoryCategory* category = *iter; + if (category->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) { - result.append(forward_slash); - result.append(temp); + // Listing containing stock folders needs to be updated but not others + // Note: we take advantage of the fact that stock folder *do not* contain sub folders to avoid a recursive call here + update_marketplace_category(category->getUUID()); + } + else + { + // Explore the contained folders recursively + update_all_marketplace_count(category->getUUID()); } } +} - path.append(result); +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, false); + if (!marketplace_listings_uuid.isNull()) + { + update_all_marketplace_count(marketplace_listings_uuid); + } + return; } void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name) @@ -162,7 +396,8 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, - const LLUUID& root_copy_id) + const LLUUID& root_copy_id, + bool move_no_copy_items) { // Create the initial folder LLUUID new_cat_uuid = gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName()); @@ -176,18 +411,41 @@ void copy_inventory_category(LLInventoryModel* model, LLInventoryModel::item_array_t* item_array; gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array); + // If root_copy_id is null, tell the marketplace model we'll be waiting for new items to be copied over for this folder + if (root_copy_id.isNull()) + { + LLMarketplaceData::instance().setValidationWaiting(root_id,count_descendants_items(cat->getUUID())); + } + // Copy all the items LLInventoryModel::item_array_t item_array_copy = *item_array; for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) { LLInventoryItem* item = *iter; - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - new_cat_uuid, - std::string(), - LLPointer(NULL)); + LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, new_cat_uuid)); + + if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + // If the item is nocopy, we do nothing or, optionally, move it + if (move_no_copy_items) + { + // Reparent the item + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) item; + gInventory.changeItemParent(viewer_inv_item, new_cat_uuid, true); + } + // Decrement the count in root_id since that one item won't be copied over + LLMarketplaceData::instance().decrementValidationWaiting(root_id); + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + new_cat_uuid, + std::string(), + cb); + } } // Copy all the folders @@ -197,7 +455,7 @@ void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* category = *iter; if (category->getUUID() != root_id) { - copy_inventory_category(model, category, new_cat_uuid, root_id); + copy_inventory_category(model, category, new_cat_uuid, root_id, move_no_copy_items); } } } @@ -253,16 +511,19 @@ BOOL get_is_parent_to_worn_item(const LLUUID& id) return FALSE; } -BOOL get_is_item_worn(const LLInventoryItem *item) + +BOOL get_is_item_worn(const LLUUID& id) { + const LLViewerInventoryItem* item = gInventory.getItem(id); if (!item) return FALSE; // Consider the item as worn if it has links in COF. - /* if (LLCOFMgr::instance().isLinkInCOF(item->getUUID())) - { REMOVED due to advice from Kitty Barnett, looks like it WILL cause trouble on some grids -SG - return TRUE; - } */ +// [SL:KB] - The code below causes problems across the board so it really just needs to go +// if (LLAppearanceMgr::instance().isLinkedInCOF(id)) +// { +// return TRUE; +// } switch(item->getType()) { @@ -287,18 +548,13 @@ BOOL get_is_item_worn(const LLInventoryItem *item) return FALSE; } -BOOL get_is_item_worn(const LLUUID& id) -{ - return get_is_item_worn(gInventory.getItem(id)); -} - BOOL get_can_item_be_worn(const LLUUID& id) { const LLViewerInventoryItem* item = gInventory.getItem(id); if (!item) return FALSE; - if (LLAppearanceMgr::isLinkInCOF(item->getLinkedUUID())) + if (LLAppearanceMgr::instance().isLinkedInCOF(item->getLinkedUUID())) { // an item having links in COF (i.e. a worn item) return FALSE; @@ -502,174 +758,1007 @@ void show_item_profile(const LLUUID& item_uuid) } } -void open_outbox() +void open_marketplace_listings() { - LLFloaterOutbox::showInstance(); + LLFloaterMarketplaceListings::showInstance(); } -LLUUID create_folder_in_outbox_for_item(LLInventoryItem* item, const LLUUID& destFolderId, S32 operation_id) +///---------------------------------------------------------------------------- +// Marketplace functions +// +// Handles Copy and Move to or within the Marketplace listings folder. +// Handles creation of stock folders, nesting of listings and version folders, +// permission checking and listings validation. +///---------------------------------------------------------------------------- + +S32 depth_nesting_in_marketplace(LLUUID cur_uuid) { - llassert(item); - llassert(destFolderId.notNull()); + // Get the marketplace listings root, exit with -1 (i.e. not under the marketplace listings root) if none + const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + if (marketplace_listings_uuid.isNull()) + { + return -1; + } + // If not a descendent of the marketplace listings root, then the nesting depth is -1 by definition + if (!gInventory.isObjectDescendentOf(cur_uuid, marketplace_listings_uuid)) + { + return -1; + } - LLUUID created_folder_id = gInventory.createNewCategory(destFolderId, LLFolderType::FT_NONE, item->getName()); - gInventory.notifyObservers(); + // Iterate through the parents till we hit the marketplace listings root + // Note that the marketplace listings root itself will return 0 + S32 depth = 0; + LLInventoryObject* cur_object = gInventory.getObject(cur_uuid); + while (cur_uuid != marketplace_listings_uuid) + { + depth++; + cur_uuid = cur_object->getParentUUID(); + cur_object = gInventory.getCategory(cur_uuid); + } + return depth; +} + +// Returns the UUID of the marketplace listing this object is in +LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth) +{ + if (depth < 1) + { + // For objects outside the marketplace listings root (or root itself), we return a NULL UUID + return LLUUID::null; + } + else if (depth == 1) + { + // Just under the root, we return the passed UUID itself if it's a folder, NULL otherwise (not a listing) + LLViewerInventoryCategory* cat = gInventory.getCategory(cur_uuid); + return (cat ? cur_uuid : LLUUID::null); + } + + // depth > 1 + LLInventoryObject* cur_object = gInventory.getObject(cur_uuid); + while (depth > 1) + { + depth--; + cur_uuid = cur_object->getParentUUID(); + cur_object = gInventory.getCategory(cur_uuid); + } + return cur_uuid; +} + +S32 compute_stock_count(LLUUID cat_uuid, bool force_count /* false */) +{ + // Handle the case of the folder being a stock folder immediately + LLViewerInventoryCategory* cat = gInventory.getCategory(cat_uuid); + if (!cat) + { + // Not a category so no stock count to speak of + return COMPUTE_STOCK_INFINITE; + } + if (cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + // If the folder is not completely fetched, we do not want to return any confusing value that could lead to unlisting + // "COMPUTE_STOCK_NOT_EVALUATED" denotes that a stock folder has a count that cannot be evaluated at this time (folder not up to date) + return COMPUTE_STOCK_NOT_EVALUATED; + } + // Note: stock folders are *not* supposed to have nested subfolders so we stop recursion here but we count only items (subfolders will be ignored) + // Note: we *always* give a stock count for stock folders, it's useful even if the listing is unassociated + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat_uuid,cat_array,item_array); + return item_array->size(); + } + + // When force_count is true, we do not do any verification of the marketplace status and simply compute + // the stock amount based on the descendent hierarchy. This is used specifically when creating a listing. + if (!force_count) + { + // Grab marketplace data for this folder + S32 depth = depth_nesting_in_marketplace(cat_uuid); + LLUUID listing_uuid = nested_parent_id(cat_uuid, depth); + if (!LLMarketplaceData::instance().isListed(listing_uuid)) + { + // If not listed, the notion of stock is meaningless so it won't be computed for any level + return COMPUTE_STOCK_INFINITE; + } + + LLUUID version_folder_uuid = LLMarketplaceData::instance().getVersionFolder(listing_uuid); + // Handle the case of the first 2 levels : listing and version folders + if (depth == 1) + { + if (version_folder_uuid.notNull()) + { + // If there is a version folder, the stock value for the listing is the version folder stock + return compute_stock_count(version_folder_uuid, true); + } + else + { + // If there's no version folder associated, the notion of stock count has no meaning + return COMPUTE_STOCK_INFINITE; + } + } + else if (depth == 2) + { + if (version_folder_uuid.notNull() && (version_folder_uuid != cat_uuid)) + { + // If there is a version folder but we're not it, our stock count is meaningless + return COMPUTE_STOCK_INFINITE; + } + } + } + + // In all other cases, the stock count is the min of stock folders count found in the descendents + // "COMPUTE_STOCK_NOT_EVALUATED" denotes that a stock folder in the hierarchy has a count that cannot be evaluated at this time (folder not up to date) + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat_uuid,cat_array,item_array); + + // "COMPUTE_STOCK_INFINITE" denotes a folder that doesn't contain any stock folders in its descendents + S32 curr_count = COMPUTE_STOCK_INFINITE; + + // Note: marketplace listings have a maximum depth nesting of 4 + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLInventoryCategory* category = *iter; + S32 count = compute_stock_count(category->getUUID(), true); + if ((curr_count == COMPUTE_STOCK_INFINITE) || ((count != COMPUTE_STOCK_INFINITE) && (count < curr_count))) + { + curr_count = count; + } + } + + return curr_count; +} + +// local helper +bool can_move_to_marketplace(LLInventoryItem* inv_item, std::string& tooltip_msg, bool resolve_links) +{ + // Collapse links directly to items/folders + LLViewerInventoryItem* viewer_inv_item = (LLViewerInventoryItem *) inv_item; + LLViewerInventoryItem* linked_item = viewer_inv_item->getLinkedItem(); + LLViewerInventoryCategory* linked_category = viewer_inv_item->getLinkedCategory(); + + // Linked items and folders cannot be put for sale + if (linked_category || linked_item) + { + tooltip_msg = LLTrans::getString("TooltipOutboxLinked"); + return false; + } + + // A category is always considered as passing... + if (linked_category != NULL) + { + return true; + } + + // Take the linked item if necessary + if (linked_item != NULL) + { + inv_item = linked_item; + } + + // Check that the agent has transfer permission on the item: this is required as a resident cannot + // put on sale items she cannot transfer. Proceed with move if we have permission. + bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); + if (!allow_transfer) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer"); + return false; + } + + // Check worn/not worn status: worn items cannot be put on the marketplace + bool worn = get_is_item_worn(inv_item->getUUID()); + if (worn) + { + tooltip_msg = LLTrans::getString("TooltipOutboxWorn"); + return false; + } + + // Check library status: library items cannot be put on the marketplace + if (!gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.getRootFolderID())) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + return false; + } + + // Check type: for the moment, calling cards cannot be put on the marketplace + bool calling_card = (LLAssetType::AT_CALLINGCARD == inv_item->getType()); + if (calling_card) + { + tooltip_msg = LLTrans::getString("TooltipOutboxCallingCard"); + return false; + } + + return true; +} + +// local helper +// Returns the max tree length (in folder nodes) down from the argument folder +int get_folder_levels(LLInventoryCategory* inv_cat) +{ + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items); + + int max_child_levels = 0; + + for (U32 i = 0; i < cats->size(); ++i) + { + LLInventoryCategory* category = cats->at(i); + max_child_levels = llmax(max_child_levels, get_folder_levels(category)); + } + + return 1 + max_child_levels; +} + +// local helper +// Returns the distance (in folder nodes) between the ancestor and its descendant. Returns -1 if not related. +int get_folder_path_length(const LLUUID& ancestor_id, const LLUUID& descendant_id) +{ + int depth = 0; + + if (ancestor_id == descendant_id) return depth; + + const LLInventoryCategory* category = gInventory.getCategory(descendant_id); + + while (category) + { + LLUUID parent_id = category->getParentUUID(); + + if (parent_id.isNull()) break; - LLNotificationsUtil::add("OutboxFolderCreated"); + depth++; - return created_folder_id; + if (parent_id == ancestor_id) return depth; + + category = gInventory.getCategory(parent_id); + } + + LL_WARNS("SLM") << "get_folder_path_length() couldn't trace a path from the descendant to the ancestor" << LL_ENDL; + return -1; } -void move_to_outbox_cb_action(const LLSD& payload) +// local helper +// Returns true if all items within the argument folder are fit for sale, false otherwise +bool has_correct_permissions_for_sale(LLInventoryCategory* cat, std::string& error_msg) { - LLViewerInventoryItem * viitem = gInventory.getItem(payload["item_id"].asUUID()); - LLUUID dest_folder_id = payload["dest_folder_id"].asUUID(); + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array); + + LLInventoryModel::item_array_t item_array_copy = *item_array; - if (viitem) - { - // when moving item directly into outbox create folder with that name - if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) + { + LLInventoryItem* item = *iter; + if (!can_move_to_marketplace(item, error_msg, false)) { - S32 operation_id = payload["operation_id"].asInteger(); - dest_folder_id = create_folder_in_outbox_for_item(viitem, dest_folder_id, operation_id); + return false; } + } + + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLInventoryCategory* category = *iter; + if (!has_correct_permissions_for_sale(category, error_msg)) + { + return false; + } + } + return true; +} - LLUUID parent = viitem->getParentUUID(); +// Returns true if inv_item can be dropped in dest_folder, a folder nested in marketplace listings (or merchant inventory) under the root_folder root +// If returns is false, tooltip_msg contains an error message to display to the user (localized and all). +// bundle_size is the amount of sibling items that are getting moved to the marketplace at the same time. +bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size, bool from_paste) +{ + // Check stock folder type matches item type in marketplace listings (even if of no use there for the moment) + LLViewerInventoryCategory* view_folder = dynamic_cast(dest_folder); + bool move_in_stock = (view_folder && (view_folder->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK)); + bool accept = (view_folder && view_folder->acceptItem(inv_item)); + if (!accept) + { + tooltip_msg = LLTrans::getString("TooltipOutboxMixedStock"); + } + + // Check that the item has the right type and permissions to be sold on the marketplace + if (accept) + { + accept = can_move_to_marketplace(inv_item, tooltip_msg, true); + } + + // Check that the total amount of items won't violate the max limit on the marketplace + if (accept) + { + // If the dest folder is a stock folder, we do not count the incoming items toward the total (stock items are seen as one) + S32 existing_item_count = (move_in_stock ? 0 : bundle_size); - gInventory.changeItemParent( - viitem, - dest_folder_id, - false); + // If the dest folder is a stock folder, we do assume that the incoming items are also stock items (they should anyway) + S32 existing_stock_count = (move_in_stock ? bundle_size : 0); - LLUUID top_level_folder = payload["top_level_folder"].asUUID(); + S32 existing_folder_count = 0; - if (top_level_folder != LLUUID::null) + // Get the version folder: that's where the counts start from + const LLViewerInventoryCategory* version_folder = ((root_folder && (root_folder != dest_folder)) ? gInventory.getFirstDescendantOf(root_folder->getUUID(), dest_folder->getUUID()) : NULL); + + if (version_folder) { - LLViewerInventoryCategory* category; + if (!from_paste && gInventory.isObjectDescendentOf(inv_item->getUUID(), version_folder->getUUID())) + { + // Clear those counts or they will be counted twice because we're already inside the version category + existing_item_count = 0; + } + + LLInventoryModel::cat_array_t existing_categories; + LLInventoryModel::item_array_t existing_items; - while (parent.notNull()) + gInventory.collectDescendents(version_folder->getUUID(), existing_categories, existing_items, FALSE); + + existing_item_count += count_copyable_items(existing_items) + count_stock_folders(existing_categories); + existing_stock_count += count_stock_items(existing_items); + existing_folder_count += existing_categories.size(); + + // If the incoming item is a nocopy (stock) item, we need to consider that it will create a stock folder + if (!inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) && !move_in_stock) { - LLInventoryModel::cat_array_t* cat_array; - LLInventoryModel::item_array_t* item_array; - gInventory.getDirectDescendentsOf(parent,cat_array,item_array); + // Note : we do not assume that all incoming items are nocopy of different kinds... + existing_folder_count += 1; + } + } - LLUUID next_parent; + if (existing_item_count > (S32)gSavedSettings.getU32("InventoryOutboxMaxItemCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxItemCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects", args); + accept = false; + } + else if (existing_stock_count > (S32)gSavedSettings.getU32("InventoryOutboxMaxStockItemCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxStockItemCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyStockItems", args); + accept = false; + } + else if (existing_folder_count > (S32)gSavedSettings.getU32("InventoryOutboxMaxFolderCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxFolderCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyFolders", args); + accept = false; + } + } - category = gInventory.getCategory(parent); + return accept; +} - if (!category) break; +// Returns true if inv_cat can be dropped in dest_folder, a folder nested in marketplace listings (or merchant inventory) under the root_folder root +// If returns is false, tooltip_msg contains an error message to display to the user (localized and all). +// bundle_size is the amount of sibling items that are getting moved to the marketplace at the same time. +bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryCategory* inv_cat, std::string& tooltip_msg, S32 bundle_size, bool check_items, bool from_paste) +{ + bool accept = true; - next_parent = category->getParentUUID(); + // Compute the nested folders level we'll add into with that incoming folder + int incoming_folder_depth = get_folder_levels(inv_cat); + // Compute the nested folders level we're inserting ourselves in + // Note: add 1 when inserting under a listing folder as we need to take the root listing folder in the count + int insertion_point_folder_depth = (root_folder ? get_folder_path_length(root_folder->getUUID(), dest_folder->getUUID()) + 1 : 1); - if (cat_array->empty() && item_array->empty()) - { - gInventory.removeCategory(parent); - } + // Get the version folder: that's where the folders and items counts start from + const LLViewerInventoryCategory* version_folder = (insertion_point_folder_depth >= 2 ? gInventory.getFirstDescendantOf(root_folder->getUUID(), dest_folder->getUUID()) : NULL); + + // Compare the whole with the nested folders depth limit + // Note: substract 2 as we leave root and version folder out of the count threshold + if ((incoming_folder_depth + insertion_point_folder_depth - 2) > (S32)(gSavedSettings.getU32("InventoryOutboxMaxFolderDepth"))) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxFolderDepth"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels", args); + accept = false; + } - if (parent == top_level_folder) + if (accept) + { + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + gInventory.collectDescendents(inv_cat->getUUID(), descendent_categories, descendent_items, FALSE); + + S32 dragged_folder_count = descendent_categories.size() + bundle_size; // Note: We assume that we're moving a bunch of folders in. That might be wrong... + S32 dragged_item_count = count_copyable_items(descendent_items) + count_stock_folders(descendent_categories); + S32 dragged_stock_count = count_stock_items(descendent_items); + S32 existing_item_count = 0; + S32 existing_stock_count = 0; + S32 existing_folder_count = 0; + + if (version_folder) + { + if (!from_paste && gInventory.isObjectDescendentOf(inv_cat->getUUID(), version_folder->getUUID())) + { + // Clear those counts or they will be counted twice because we're already inside the version category + dragged_folder_count = 0; + dragged_item_count = 0; + dragged_stock_count = 0; + } + + // Tally the total number of categories and items inside the root folder + LLInventoryModel::cat_array_t existing_categories; + LLInventoryModel::item_array_t existing_items; + gInventory.collectDescendents(version_folder->getUUID(), existing_categories, existing_items, FALSE); + + existing_folder_count += existing_categories.size(); + existing_item_count += count_copyable_items(existing_items) + count_stock_folders(existing_categories); + existing_stock_count += count_stock_items(existing_items); + } + + const S32 total_folder_count = existing_folder_count + dragged_folder_count; + const S32 total_item_count = existing_item_count + dragged_item_count; + const S32 total_stock_count = existing_stock_count + dragged_stock_count; + + if (total_folder_count > (S32)gSavedSettings.getU32("InventoryOutboxMaxFolderCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxFolderCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyFolders", args); + accept = false; + } + else if (total_item_count > (S32)gSavedSettings.getU32("InventoryOutboxMaxItemCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxItemCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects", args); + accept = false; + } + else if (total_stock_count > (S32)gSavedSettings.getU32("InventoryOutboxMaxStockItemCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxStockItemCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyStockItems", args); + accept = false; + } + + // Now check that each item in the folder can be moved in the marketplace + if (accept && check_items) + { + for (U32 i=0; i < descendent_items.size(); ++i) + { + LLInventoryItem* item = descendent_items[i]; + if (!can_move_to_marketplace(item, tooltip_msg, false)) { + accept = false; break; } - - parent = next_parent; } } - - open_outbox(); } + + return accept; } -void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id) +bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy) { - // Collapse links directly to items/folders + // Get the marketplace listings depth of the destination folder, exit with error if not under marketplace + S32 depth = depth_nesting_in_marketplace(dest_folder); + if (depth < 0) + { + LLSD subs; + subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Merchant"); + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return false; + } + + // We will collapse links into items/folders LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory(); + if (linked_category != NULL) { - copy_folder_to_outbox(linked_category, dest_folder, top_level_folder, operation_id); + // Move the linked folder directly + return move_folder_to_marketplacelistings(linked_category, dest_folder, copy); } else { + // Grab the linked item if any LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem(); - if (linked_item != NULL) + viewer_inv_item = (linked_item != NULL ? linked_item : viewer_inv_item); + + // If we want to copy but the item is no copy, fail silently (this is a common case that doesn't warrant notification) + if (copy && !viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) { - inv_item = (LLInventoryItem *) linked_item; + return false; } - - // Check for copy permissions - if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + + // Check that the agent has transfer permission on the item: this is required as a resident cannot + // put on sale items she cannot transfer. Proceed with move if we have permission. + std::string error_msg; + if (can_move_to_marketplace(inv_item, error_msg, true)) { - // when moving item directly into outbox create folder with that name - if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + // When moving an isolated item, we might need to create the folder structure to support it + if (depth == 0) + { + // We need a listing folder + dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName()); + depth++; + } + if (depth == 1) + { + // We need a version folder + dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName()); + depth++; + } + LLViewerInventoryCategory* dest_cat = gInventory.getCategory(dest_folder); + if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) && + (dest_cat->getPreferredType() != LLFolderType::FT_MARKETPLACE_STOCK)) + { + // We need to create a stock folder to move a no copy item + dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_MARKETPLACE_STOCK, viewer_inv_item->getName()); + dest_cat = gInventory.getCategory(dest_folder); + depth++; + } + + // Verify we can have this item in that destination category + if (!dest_cat->acceptItem(viewer_inv_item)) { - dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id); + LLSD subs; + subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Accepted"); + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return false; } - - copy_inventory_item(gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - dest_folder, - inv_item->getName(), - LLPointer(NULL)); - open_outbox(); + // Get the parent folder of the moved item : we may have to update it + LLUUID src_folder = viewer_inv_item->getParentUUID(); + + if (copy) + { + // Copy the item + LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, dest_folder)); + copy_inventory_item( + gAgent.getID(), + viewer_inv_item->getPermissions().getOwner(), + viewer_inv_item->getUUID(), + dest_folder, + std::string(), + cb); + } + else + { + // Reparent the item + gInventory.changeItemParent(viewer_inv_item, dest_folder, true); + } } else { - LLSD payload; - payload["item_id"] = inv_item->getUUID(); - payload["dest_folder_id"] = dest_folder; - payload["top_level_folder"] = top_level_folder; - payload["operation_id"] = operation_id; - - LLMarketplaceInventoryNotifications::addNoCopyNotification(payload, move_to_outbox_cb_action); + LLSD subs; + subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + error_msg; + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return false; } } + + open_marketplace_listings(); + return true; } -void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id) +bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy, bool move_no_copy_items) { - // when moving item directly into outbox create folder with that name - if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + // Check that we have adequate permission on all items being moved. Proceed if we do. + std::string error_msg; + if (has_correct_permissions_for_sale(inv_cat, error_msg)) { - dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id); + // Get the destination folder + LLViewerInventoryCategory* dest_cat = gInventory.getCategory(dest_folder); + + // Check it's not a stock folder + if (dest_cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + LLSD subs; + subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Accepted"); + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return false; + } + + // Get the parent folder of the moved item : we may have to update it + LLUUID src_folder = inv_cat->getParentUUID(); + + LLViewerInventoryCategory* viewer_inv_cat = (LLViewerInventoryCategory*) inv_cat; + if (copy) + { + // Copy the folder + copy_inventory_category(&gInventory, viewer_inv_cat, dest_folder, LLUUID::null, move_no_copy_items); + } + else + { + // Reparent the folder + gInventory.changeCategoryParent(viewer_inv_cat, dest_folder, false); + // Check the destination folder recursively for no copy items and promote the including folders if any + validate_marketplacelistings(dest_cat); + } + + // Update the modified folders + update_marketplace_category(src_folder); + update_marketplace_category(dest_folder); + gInventory.notifyObservers(); } - - LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; + else + { + LLSD subs; + subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + error_msg; + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return false; + } + + open_marketplace_listings(); + return true; +} - gInventory.changeItemParent( - viewer_inv_item, - dest_folder, - false); +bool sort_alpha(const LLViewerInventoryCategory* cat1, const LLViewerInventoryCategory* cat2) +{ + return cat1->getName().compare(cat2->getName()) < 0; } -void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id) +void dump_trace(std::string& message, S32 depth, LLError::ELevel log_level) { - LLUUID new_folder_id = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_cat->getName()); - gInventory.notifyObservers(); + LL_INFOS() << "validate_marketplacelistings : error = "<< log_level << ", depth = " << depth << ", message = " << message << LL_ENDL; +} + +// Make all relevant business logic checks on the marketplace listings starting with the folder as argument. +// This function does no deletion of listings but a mere audit and raises issues to the user (through the +// optional callback cb). It also returns a boolean, true if things validate, false if issues are raised. +// The only inventory changes that are done is to move and sort folders containing no-copy items to stock folders. +bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_t cb, bool fix_hierarchy, S32 depth) +{ +#if 0 + // Used only for debug + if (!cb) + { + cb = boost::bind(&dump_trace, _1, _2, _3); + } +#endif + // Folder is valid unless issue is raised + bool result = true; + + // Get the type and the depth of the folder + LLViewerInventoryCategory* viewer_cat = (LLViewerInventoryCategory*) (cat); + const LLFolderType::EType folder_type = cat->getPreferredType(); + if (depth < 0) + { + // If the depth argument was not provided, evaluate the depth directly + depth = depth_nesting_in_marketplace(cat->getUUID()); + } + if (depth < 0) + { + // If the folder is not under the marketplace listings root, we run validation as if it was a listing folder and prevent any hierarchy fix + // This allows the function to be used to pre-validate a folder anywhere in the inventory + depth = 1; + fix_hierarchy = false; + } + + // Set the indentation for print output (typically, audit button in marketplace folder floater) + std::string indent; + for (int i = 1; i < depth; i++) + { + indent += " "; + } + + // Check out that version folders are marketplace ready + if (depth == 2) + { + std::string message; + // Note: if we fix the hierarchy, we want to check the items individually, hence the last argument here + if (!can_move_folder_to_marketplace(cat, cat, cat, message, 0, fix_hierarchy)) + { + result = false; + if (cb) + { + message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error") + " " + message; + cb(message, depth, LLError::LEVEL_ERROR); + } + } + } + + // Check out that stock folders are at the right level + if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth <= 2)) + { + if (fix_hierarchy) + { + if (cb) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Warning") + " " + LLTrans::getString("Marketplace Validation Warning Stock"); + cb(message, depth, LLError::LEVEL_WARN); + } + // Nest the stock folder one level deeper in a normal folder and restart from there + LLUUID parent_uuid = cat->getParentUUID(); + LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, LLFolderType::FT_NONE, cat->getName()); + LLInventoryCategory* new_cat = gInventory.getCategory(folder_uuid); + gInventory.changeCategoryParent(viewer_cat, folder_uuid, false); + result &= validate_marketplacelistings(new_cat, cb, fix_hierarchy, depth + 1); + return result; + } + else + { + result = false; + if (cb) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error") + " " + LLTrans::getString("Marketplace Validation Warning Stock"); + cb(message, depth, LLError::LEVEL_ERROR); + } + } + } + + // Item sorting and validation : sorting and moving the various stock items is complicated as the set of constraints is high + // We need to: + // * separate non stock items, stock items per types in different folders + // * have stock items nested at depth 2 at least + // * never ever move the non-stock items LLInventoryModel::cat_array_t* cat_array; LLInventoryModel::item_array_t* item_array; - gInventory.getDirectDescendentsOf(inv_cat->getUUID(),cat_array,item_array); + gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array); - // copy the vector because otherwise the iterator won't be happy if we delete from it - LLInventoryModel::item_array_t item_array_copy = *item_array; + // We use a composite (type,permission) key on that map to store UUIDs of items of same (type,permissions) + std::map items_vector; + // Parse the items and create vectors of item UUIDs sorting copyable items and stock items of various types + bool has_bad_items = false; + LLInventoryModel::item_array_t item_array_copy = *item_array; for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) { LLInventoryItem* item = *iter; - copy_item_to_outbox(item, new_folder_id, top_level_folder, operation_id); + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) item; + + // Test but skip items that shouldn't be there to start with, raise an error message for those + std::string error_msg; + if (!can_move_to_marketplace(item, error_msg, false)) + { + has_bad_items = true; + if (cb && fix_hierarchy) + { + std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error") + " " + error_msg; + cb(message, depth, LLError::LEVEL_ERROR); + } + continue; + } + // Update the appropriate vector item for that type + LLInventoryType::EType type = LLInventoryType::IT_COUNT; // Default value for non stock items + U32 perms = 0; + if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + // Get the item type for stock items + type = viewer_inv_item->getInventoryType(); + perms = viewer_inv_item->getPermissions().getMaskNextOwner(); + } + U32 key = (((U32)(type) & 0xFF) << 24) | (perms & 0xFFFFFF); + items_vector[key].push_back(viewer_inv_item->getUUID()); + } + + // How many types of items? Which type is it if only one? + S32 count = items_vector.size(); + U32 default_key = (U32)(LLInventoryType::IT_COUNT) << 24; // This is the key for any normal copyable item + U32 unique_key = (count == 1 ? items_vector.begin()->first : default_key); // The key in the case of one item type only + + // If we have no items in there (only folders or empty), analyze a bit further + if ((count == 0) && !has_bad_items) + { + if (cat_array->size() == 0) + { + // So we have no item and no folder. That's at least a warning. + if (depth == 2) + { + // If this is an empty version folder, warn only (listing won't be delivered by AIS, but only AIS should unlist) + if (cb) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Empty Version"); + cb(message, depth, LLError::LEVEL_WARN); + } + } + else if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth > 2)) + { + // If this is a legit but empty stock folder, warn only (listing must stay searchable when out of stock) + if (cb) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Empty Stock"); + cb(message, depth, LLError::LEVEL_WARN); + } + } + else if (cb) + { + // We warn if there's nothing in a regular folder (maybe it's an under construction listing) + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Warning Empty"); + cb(message, depth, LLError::LEVEL_WARN); + } + } + else + { + // Done with that folder : Print out the folder name unless we already found an error here + if (cb && result && (depth >= 1)) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log"); + cb(message, depth, LLError::LEVEL_INFO); + } + } + } + // If we have a single type of items of the right type in the right place, we're done + else if ((count == 1) && !has_bad_items && (((unique_key == default_key) && (depth > 1)) || ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth > 2) && (cat_array->size() == 0)))) + { + // Done with that folder : Print out the folder name unless we already found an error here + if (cb && result && (depth >= 1)) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log"); + cb(message, depth, LLError::LEVEL_INFO); + } } + else + { + if (fix_hierarchy && !has_bad_items) + { + // Alert the user when an existing stock folder has to be split + if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && ((count >= 2) || (cat_array->size() > 0))) + { + LLNotificationsUtil::add("AlertMerchantStockFolderSplit"); + } + // If we have more than 1 type of items or we are at the listing level or we have stock/no stock type mismatch, wrap the items in subfolders + if ((count > 1) || (depth == 1) || + ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (unique_key == default_key)) || + ((folder_type != LLFolderType::FT_MARKETPLACE_STOCK) && (unique_key != default_key))) + { + // Create one folder per vector at the right depth and of the right type + auto items_vector_it = items_vector.begin(); + while (items_vector_it != items_vector.end()) + { + // Create a new folder + LLUUID parent_uuid = (depth > 2 ? viewer_cat->getParentUUID() : viewer_cat->getUUID()); + LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(items_vector_it->second.back()); + std::string folder_name = (depth >= 1 ? viewer_cat->getName() : viewer_inv_item->getName()); + LLFolderType::EType new_folder_type = (items_vector_it->first == default_key ? LLFolderType::FT_NONE : LLFolderType::FT_MARKETPLACE_STOCK); + if (cb) + { + std::string message = ""; + if (new_folder_type == LLFolderType::FT_MARKETPLACE_STOCK) + { + message = indent + folder_name + LLTrans::getString("Marketplace Validation Warning Create Stock"); + } + else + { + message = indent + folder_name + LLTrans::getString("Marketplace Validation Warning Create Version"); + } + cb(message, depth, LLError::LEVEL_WARN); + } + LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, new_folder_type, folder_name); + + // Move each item to the new folder + while (!items_vector_it->second.empty()) + { + LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(items_vector_it->second.back()); + if (cb) + { + std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Move"); + cb(message, depth, LLError::LEVEL_WARN); + } + gInventory.changeItemParent(viewer_inv_item, folder_uuid, true); + items_vector_it->second.pop_back(); + } + + // Next type + update_marketplace_category(parent_uuid); + update_marketplace_category(folder_uuid); + gInventory.notifyObservers(); + items_vector_it++; + } + } + // Stock folder should have no sub folder so reparent those up + if (folder_type == LLFolderType::FT_MARKETPLACE_STOCK) + { + LLUUID parent_uuid = cat->getParentUUID(); + gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array); + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLViewerInventoryCategory* viewer_cat = (LLViewerInventoryCategory*) (*iter); + gInventory.changeCategoryParent(viewer_cat, parent_uuid, false); + result &= validate_marketplacelistings(viewer_cat, cb, fix_hierarchy, depth); + } + } + } + else if (cb) + { + // We are not fixing the hierarchy but reporting problems, report everything we can find + // Print the folder name + if (result && (depth >= 1)) + { + if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (count >= 2)) + { + // Report if a stock folder contains a mix of items + result = false; + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Mixed Stock"); + cb(message, depth, LLError::LEVEL_ERROR); + } + else if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (cat_array->size() != 0)) + { + // Report if a stock folder contains subfolders + result = false; + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Subfolder In Stock"); + cb(message, depth, LLError::LEVEL_ERROR); + } + else + { + // Simply print the folder name + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log"); + cb(message, depth, LLError::LEVEL_INFO); + + } + } + // Scan each item and report if there's a problem + LLInventoryModel::item_array_t item_array_copy = *item_array; + for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) + { + LLInventoryItem* item = *iter; + LLViewerInventoryItem* viewer_inv_item = (LLViewerInventoryItem*) item; + std::string error_msg; + if (!can_move_to_marketplace(item, error_msg, false)) + { + // Report items that shouldn't be there to start with + result = false; + std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error") + " " + error_msg; + cb(message, depth, LLError::LEVEL_ERROR); + } + else if ((!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) && (folder_type != LLFolderType::FT_MARKETPLACE_STOCK)) + { + // Report stock items that are misplaced + result = false; + std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error Stock Item"); + cb(message, depth, LLError::LEVEL_ERROR); + } + else if (depth == 1) + { + // Report items not wrapped in version folder + result = false; + std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Unwrapped Item"); + cb(message, depth, LLError::LEVEL_ERROR); + } + } + } + // Clean up + if (viewer_cat->getDescendentCount() == 0) + { + // Remove the current folder if it ends up empty + if (cb) + { + std::string message = indent + viewer_cat->getName() + LLTrans::getString("Marketplace Validation Warning Delete"); + cb(message, depth, LLError::LEVEL_WARN); + } + gInventory.removeCategory(cat->getUUID()); + gInventory.notifyObservers(); + return result && !has_bad_items; + } + } + + // Recursion : Perform the same validation on each nested folder + gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array); LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + // Sort the folders in alphabetical order first + std::sort(cat_array_copy.begin(), cat_array_copy.end(), sort_alpha); for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) { - LLViewerInventoryCategory* category = *iter; - copy_folder_to_outbox(category, new_folder_id, top_level_folder, operation_id); + LLInventoryCategory* category = *iter; + result &= validate_marketplacelistings(category, cb, fix_hierarchy, depth + 1); } - open_outbox(); + update_marketplace_category(cat->getUUID()); + gInventory.notifyObservers(); + return result && !has_bad_items; } ///---------------------------------------------------------------------------- @@ -687,14 +1776,14 @@ bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(const LLInventoryIte case LLAssetType::AT_OBJECT: case LLAssetType::AT_BODYPART: case LLAssetType::AT_CLOTHING: - if (!get_is_item_worn(item->getUUID())) + //if (!get_is_item_worn(item->getUUID())) // return true; break; default: return true; break; } - return false; +// return false; } bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item) diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index e986eabda0..4b82be393c 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -32,6 +32,10 @@ #include "llinventory.h" #include "llwearabletype.h" +// compute_stock_count() return error code +const S32 COMPUTE_STOCK_INFINITE = -1; +const S32 COMPUTE_STOCK_NOT_EVALUATED = -2; + /******************************************************************************** ** ** ** MISCELLANEOUS GLOBAL FUNCTIONS @@ -41,7 +45,6 @@ BOOL get_is_parent_to_worn_item(const LLUUID& id); // Is this item or its baseitem is worn, attached, etc... -BOOL get_is_item_worn(const LLInventoryItem *item); BOOL get_is_item_worn(const LLUUID& id); // Could this item be worn (correct type + not already being worn) @@ -55,20 +58,28 @@ BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id) void show_item_profile(const LLUUID& item_uuid); +// Nudge the listing categories in the inventory to signal that their marketplace status changed +void update_marketplace_category(const LLUUID& cat_id, bool perform_consistency_enforcement = true); +// Nudge all listing categories to signal that their marketplace status changed +void update_all_marketplace_count(); + void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name); -void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null); +void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null, bool move_no_copy_items = false); // Generates a string containing the path to the item specified by item_id. void append_path(const LLUUID& id, std::string& path); -// Same as append_path but omits the root prefix "/My Inventory/". -void append_path_short(const LLUUID& id, std::string& path); - -void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id); -void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id); +typedef boost::function validation_callback_t; -void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id); +bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size = 1, bool from_paste = false); +bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryCategory* inv_cat, std::string& tooltip_msg, S32 bundle_size = 1, bool check_items = true, bool from_paste = false); +bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy = false); +bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy = false, bool move_no_copy_items = false); +bool validate_marketplacelistings(LLInventoryCategory* inv_cat, validation_callback_t cb = NULL, bool fix_hierarchy = true, S32 depth = -1); +S32 depth_nesting_in_marketplace(LLUUID cur_uuid); +LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth); +S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false); /** Miscellaneous global functions ** ** @@ -238,7 +249,7 @@ class LLUniqueBuddyCollector : public LLInventoryCollectFunctor LLInventoryItem* item); protected: - std::set mSeen; + uuid_set_t mSeen; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -481,7 +492,7 @@ class LLSaveFolderState : public LLFolderViewFunctor void setApply(BOOL apply); void clearOpenFolders() { mOpenFolders.clear(); } protected: - std::set mOpenFolders; + uuid_set_t mOpenFolders; BOOL mApply; }; diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index f93dc8dd71..65b21fa7c8 100644 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -79,6 +79,7 @@ LLIconDictionary::LLIconDictionary() addEntry(LLInventoryType::ICONNAME_CLOTHING_SKIRT, new IconEntry("inv_item_skirt.tga")); addEntry(LLInventoryType::ICONNAME_CLOTHING_ALPHA, new IconEntry("inv_item_alpha.tga")); addEntry(LLInventoryType::ICONNAME_CLOTHING_TATTOO, new IconEntry("inv_item_tattoo.tga")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, new IconEntry("Inv_Universal.png")); addEntry(LLInventoryType::ICONNAME_ANIMATION, new IconEntry("inv_item_animation.tga")); addEntry(LLInventoryType::ICONNAME_GESTURE, new IconEntry("inv_item_gesture.tga")); @@ -88,8 +89,14 @@ LLIconDictionary::LLIconDictionary() addEntry(LLInventoryType::ICONNAME_LINKFOLDER, new IconEntry("inv_link_folder.tga")); addEntry(LLInventoryType::ICONNAME_MESH, new IconEntry("inv_item_mesh.tga")); + addEntry(LLInventoryType::ICONNAME_SETTINGS_SKY, new IconEntry("Inv_SettingsSky.png")); + addEntry(LLInventoryType::ICONNAME_SETTINGS_WATER, new IconEntry("Inv_SettingsWater.png")); + addEntry(LLInventoryType::ICONNAME_SETTINGS_DAY, new IconEntry("Inv_SettingsDay.png")); + addEntry(LLInventoryType::ICONNAME_SETTINGS, new IconEntry("Inv_Settings.png")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_UNKNOWN, new IconEntry("inv_item_unknown.tga")); addEntry(LLInventoryType::ICONNAME_INVALID, new IconEntry("inv_invalid.png")); + addEntry(LLInventoryType::ICONNAME_UNKNOWN, new IconEntry("Inv_UnknownObject.png")); addEntry(LLInventoryType::ICONNAME_NONE, new IconEntry("NONE")); } @@ -163,6 +170,14 @@ const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type, break; case LLAssetType::AT_MESH: idx = LLInventoryType::ICONNAME_MESH; + break; + case LLAssetType::AT_SETTINGS: + // TODO: distinguish between Sky and Water settings. + idx = assignSettingsIcon(misc_flag); + break; + case LLAssetType::AT_UNKNOWN: + idx = LLInventoryType::ICONNAME_UNKNOWN; + break; default: break; } @@ -179,6 +194,17 @@ const std::string& LLInventoryIcon::getIconName(LLInventoryType::EIconName idx) LLInventoryType::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag) { - const LLWearableType::EType wearable_type = LLWearableType::EType(LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK & misc_flag); + const LLWearableType::EType wearable_type = LLWearableType::EType(LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK & misc_flag); return LLWearableType::getIconName(wearable_type); } + +LLInventoryType::EIconName LLInventoryIcon::assignSettingsIcon(U32 misc_flag) +{ + switch (misc_flag & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK) + { + case 0: return LLInventoryType::ICONNAME_SETTINGS_SKY; + case 1: return LLInventoryType::ICONNAME_SETTINGS_WATER; + case 2: return LLInventoryType::ICONNAME_SETTINGS_DAY; + } + return LLInventoryType::ICONNAME_SETTINGS; +} diff --git a/indra/newview/llinventoryicon.h b/indra/newview/llinventoryicon.h index 659448143d..58e1ffdb61 100644 --- a/indra/newview/llinventoryicon.h +++ b/indra/newview/llinventoryicon.h @@ -49,6 +49,7 @@ class LLInventoryIcon protected: static LLInventoryType::EIconName assignWearableIcon(U32 misc_flag); + static LLInventoryType::EIconName assignSettingsIcon(U32 misc_flag); }; #endif // LL_LLINVENTORYICON_H diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 279c9dc351..3d020e9d48 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2014, 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 @@ -25,12 +25,16 @@ */ #include "llviewerprecompiledheaders.h" + +#include + #include "llinventorymodel.h" #include "llaisapi.h" #include "llagent.h" #include "llagentwearables.h" #include "llappearancemgr.h" +#include "llavatarnamecache.h" #include "llinventoryclipboard.h" #include "llinventorypanel.h" #include "llinventorybridge.h" @@ -38,6 +42,7 @@ #include "llinventoryobserver.h" #include "llinventorypanel.h" #include "llnotificationsutil.h" +#include "llmarketplacefunctions.h" #include "llwindow.h" #include "llviewercontrol.h" #include "llpreview.h" @@ -50,7 +55,6 @@ #include "llvoavatarself.h" #include "llgesturemgr.h" #include "llsdutil.h" -#include #include "statemachine/aievent.h" // [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) @@ -63,11 +67,8 @@ #include "process.h" #endif -class AIHTTPTimeoutPolicy; -extern AIHTTPTimeoutPolicy createInventoryCategoryResponder_timeout; - // Increment this if the inventory contents change in a non-backwards-compatible way. -// For viewers with link items support, former caches are incorrect. +// For viewer 2, the addition of link items makes a pre-viewer-2 cache incorrect. const S32 LLInventoryModel::sCurrentInvCacheVersion = 2; BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE; @@ -91,11 +92,11 @@ class LLCanCache : public LLInventoryCollectFunctor { public: LLCanCache(LLInventoryModel* model) : mModel(model) {} - virtual ~LLCanCache() {} - virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item); + virtual ~LLCanCache() = default; + bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override; protected: LLInventoryModel* mModel; - std::set mCachedCatIDs; + uuid_set_t mCachedCatIDs; }; bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item) @@ -136,7 +137,6 @@ LLInventoryModel gInventory; // Default constructor LLInventoryModel::LLInventoryModel() : // These are now ordered, keep them that way. - mBacklinkMMap(), mIsAgentInvUsable(false), mRootFolderID(), mLibraryRootFolderID(), @@ -145,7 +145,8 @@ LLInventoryModel::LLInventoryModel() mItemMap(), mParentChildCategoryTree(), mParentChildItemTree(), - mLastItem(NULL), + mBacklinkMMap(), + mLastItem(nullptr), mIsNotifyObservers(FALSE), mModifyMask(LLInventoryObserver::ALL), mChangedItemIDs(), @@ -154,6 +155,7 @@ LLInventoryModel::LLInventoryModel() mItemLock() {} + // Destroys the object LLInventoryModel::~LLInventoryModel() { @@ -183,7 +185,7 @@ BOOL LLInventoryModel::isObjectDescendentOf(const LLUUID& obj_id, if (obj_id == cat_id) return TRUE; //The while loop will ALWAYS return false if parent_id is null, regardless of cat_id being null too. Don't bother trying. if(cat_id.isNull()) return FALSE; - LLInventoryObject* obj = getObject(obj_id); + const LLInventoryObject* obj = getObject(obj_id); int depthCounter = 0; while(obj) { @@ -223,7 +225,11 @@ BOOL LLInventoryModel::isObjectDescendentOf(const LLUUID& obj_id, const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(const LLUUID& obj_id) const { const LLInventoryObject* obj = getObject(obj_id); - + if(!obj) + { + LL_WARNS(LOG_INV) << "Non-existent object [ id: " << obj_id << " ] " << LL_ENDL; + return nullptr; + } // Search up the parent chain until we get to root or an acceptable folder. // This assumes there are no cycles in the tree else we'll get a hang. LLUUID parent_id = obj->getParentUUID(); @@ -240,7 +246,7 @@ const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(cons } parent_id = cat->getParentUUID(); } - return NULL; + return nullptr; } // @@ -250,17 +256,17 @@ const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LL { if (master_parent_id == obj_id) { - return NULL; + return nullptr; } const LLViewerInventoryCategory* current_cat = getCategory(obj_id); - if (current_cat == NULL) + if (current_cat == nullptr) { current_cat = getCategory(getObject(obj_id)->getParentUUID()); } - while (current_cat != NULL) + while (current_cat != nullptr) { const LLUUID& current_parent_id = current_cat->getParentUUID(); @@ -272,7 +278,7 @@ const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LL current_cat = getCategory(current_parent_id); } - return NULL; + return nullptr; } bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const @@ -305,21 +311,21 @@ LLInventoryObject* LLInventoryModel::getObject(const LLUUID& id) const { return item; } - return NULL; + return nullptr; } // Get the item by id. Returns NULL if not found. LLViewerInventoryItem* LLInventoryModel::getItem(const LLUUID& id) const { - LLViewerInventoryItem* item = NULL; + LLViewerInventoryItem* item = nullptr; if(mLastItem.notNull() && mLastItem->getUUID() == id) { item = mLastItem; } else { - item_map_t::const_iterator iter = mItemMap.find(id); - if (iter != mItemMap.end()) + const auto iter = mItemMap.find(id); + if (iter != mItemMap.cend()) { item = iter->second; mLastItem = item; @@ -331,13 +337,12 @@ LLViewerInventoryItem* LLInventoryModel::getItem(const LLUUID& id) const // Get the category by id. Returns NULL if not found LLViewerInventoryCategory* LLInventoryModel::getCategory(const LLUUID& id) const { - LLViewerInventoryCategory* category = NULL; - cat_map_t::const_iterator iter = mCategoryMap.find(id); - if (iter != mCategoryMap.end()) + const auto iter = mCategoryMap.find(id); + if (iter != mCategoryMap.cend()) { - category = iter->second; + return iter->second; } - return category; + return nullptr; } S32 LLInventoryModel::getItemCount() const @@ -383,7 +388,7 @@ LLMD5 LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const } for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin(); iter != item_array->end(); - iter++) + ++iter) { const LLViewerInventoryItem *item = (*iter); if (!item) @@ -419,10 +424,10 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id) void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::EType type) { // Make a list of folders that are not "main_id" and are of "type" - std::vector folder_ids; - for (cat_map_t::iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit) + uuid_vec_t folder_ids; + for (const auto& cat_pair : mCategoryMap) { - LLViewerInventoryCategory* cat = cit->second; + LLViewerInventoryCategory* cat = cat_pair.second; if ((cat->getPreferredType() == type) && (cat->getUUID() != main_id)) { folder_ids.push_back(cat->getUUID()); @@ -430,10 +435,8 @@ void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::E } // Iterate through those folders - for (std::vector::iterator folder_ids_it = folder_ids.begin(); folder_ids_it != folder_ids.end(); ++folder_ids_it) + for (LLUUID const& folder_id: folder_ids) { - LLUUID folder_id = (*folder_ids_it); - // Get the content of this folder cat_array_t* cats; item_array_t* items; @@ -443,12 +446,12 @@ void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::E // Note : we get the list of UUIDs and iterate on them instead of iterating directly on item_array_t // elements. This is because moving elements modify the maps and, consequently, invalidate iterators on them. // This "gather and iterate" method is verbose but resilient. - std::vector list_uuids; + uuid_vec_t list_uuids; for (item_array_t::const_iterator it = items->begin(); it != items->end(); ++it) { list_uuids.push_back((*it)->getUUID()); } - for (std::vector::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it) + for (auto it = list_uuids.begin(); it != list_uuids.end(); ++it) { LLViewerInventoryItem* item = getItem(*it); changeItemParent(item, main_id, TRUE); @@ -460,7 +463,7 @@ void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::E { list_uuids.push_back((*it)->getUUID()); } - for (std::vector::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it) + for (auto it = list_uuids.begin(); it != list_uuids.end(); ++it) { LLViewerInventoryCategory* cat = getCategory(*it); changeCategoryParent(cat, main_id, TRUE); @@ -476,6 +479,8 @@ void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::E } } + + const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot( LLFolderType::EType preferred_type, bool create_folder, @@ -488,7 +493,7 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot( } else if (root_id.notNull()) { - cat_array_t* cats = NULL; + cat_array_t* cats = nullptr; cats = get_ptr_in_map(mParentChildCategoryTree, root_id); if(cats) { @@ -553,7 +558,7 @@ LLUUID LLInventoryModel::findCategoryByName(std::string name) return LLUUID::null; } -class LLCreateInventoryCategoryResponder : public LLHTTPClient::ResponderWithResult +class LLCreateInventoryCategoryResponder final : public LLHTTPClient::ResponderWithResult { LOG_CLASS(LLCreateInventoryCategoryResponder); public: @@ -564,12 +569,13 @@ class LLCreateInventoryCategoryResponder : public LLHTTPClient::ResponderWithRes { } - /*virtual*/ void httpFailure(void) +protected: + void httpFailure() override { - LL_WARNS(LOG_INV) << "CreateInventoryCategory failed. status = " << mStatus << ", reason = \"" << mReason << "\"" << LL_ENDL; + LL_WARNS(LOG_INV) << dumpResponse() << LL_ENDL; } - /*virtual*/ void httpSuccess(void) + void httpSuccess() override { //Server has created folder. const LLSD& content = getContent(); @@ -598,11 +604,9 @@ class LLCreateInventoryCategoryResponder : public LLHTTPClient::ResponderWithRes { mCallback.get()(category_id); } - } - /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return createInventoryCategoryResponder_timeout; } - /*virtual*/ char const* getName(void) const { return "LLCreateInventoryCategoryResponder"; } + char const* getName(void) const override { return "LLCreateInventoryCategoryResponder"; } private: boost::optional mCallback; @@ -628,7 +632,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, if(LLFolderType::lookup(preferred_type) == LLFolderType::badLookup()) { - LL_DEBUGS(LOG_INV) << "Attempt to create undefined category. (" << preferred_type << ")" << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Attempt to create undefined category." << LL_ENDL; return id; } @@ -671,10 +675,15 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, return LLUUID::null; } + if (!gMessageSystem) + { + return LLUUID::null; + } + // Add the category to the internal representation LLPointer cat = new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID()); - cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL); + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 cat->setDescendentCount(0); LLCategoryUpdate update(cat->getParentUUID(), 1); accountForUpdate(update); @@ -709,7 +718,7 @@ bool LLInventoryModel::hasMatchingDirectDescendent(const LLUUID& cat_id, for (LLInventoryModel::cat_array_t::const_iterator it = cats->begin(); it != cats->end(); ++it) { - if (filter(*it,NULL)) + if (filter(*it, nullptr)) { return true; } @@ -720,7 +729,7 @@ bool LLInventoryModel::hasMatchingDirectDescendent(const LLUUID& cat_id, for (LLInventoryModel::item_array_t::const_iterator it = items->begin(); it != items->end(); ++it) { - if (filter(NULL,*it)) + if (filter(nullptr, *it)) { return true; } @@ -751,9 +760,10 @@ bool LLInventoryModel::hasMatchingDirectDescendent(const LLUUID& cat_id, class LLAlwaysCollect : public LLInventoryCollectFunctor { public: - virtual ~LLAlwaysCollect() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item) + virtual ~LLAlwaysCollect() = default; + + bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item) override { return TRUE; } @@ -796,7 +806,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id, for(S32 i = 0; i < count; ++i) { LLViewerInventoryCategory* cat = cat_array->at(i); - if(add(cat,NULL)) + if(add(cat, nullptr)) { cats.push_back(cat); } @@ -807,7 +817,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id, } } - LLViewerInventoryItem* item = NULL; + LLViewerInventoryItem* item = nullptr; item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id); // Move onto items @@ -817,7 +827,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id, for(S32 i = 0; i < count; ++i) { item = item_array->at(i); - if(add(NULL, item)) + if(add(nullptr, item)) { items.push_back(item); } @@ -870,11 +880,9 @@ void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask) return; LLInventoryModel::item_array_t item_array = collectLinksTo(object_id); - for (LLInventoryModel::item_array_t::iterator iter = item_array.begin(); - iter != item_array.end(); - iter++) + for (auto& iter : item_array) { - LLViewerInventoryItem *linked_item = (*iter); + LLViewerInventoryItem *linked_item = iter; addChangedMask(mask, linked_item->getUUID()); }; } @@ -949,14 +957,6 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) return mask; } - // We're hiding mesh types -#if 0 - if (item->getType() == LLAssetType::AT_MESH) - { - return mask; - } -#endif - LLPointer old_item = getItem(item->getUUID()); LLPointer new_item; if(old_item) @@ -965,12 +965,23 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) new_item = old_item; LLUUID old_parent_id = old_item->getParentUUID(); LLUUID new_parent_id = item->getParentUUID(); + bool update_parent_on_server = false; + + if (new_parent_id.isNull()) + { + // item with null parent will end in random location and then in Lost&Found, + // either move to default folder as if it is new item or don't move at all + LL_WARNS(LOG_INV) << "Update attempts to reparent item " << item->getUUID() + << " to null folder. Moving to Lost&Found. Old item name: " << old_item->getName() + << ". New name: " << item->getName() + << "." << LL_ENDL; + new_parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); + update_parent_on_server = true; + } if(old_parent_id != new_parent_id) { - // need to update the parent-child tree - item_array_t* item_array; - item_array = get_ptr_in_map(mParentChildItemTree, old_parent_id); + item_array_t * item_array = get_ptr_in_map(mParentChildItemTree, old_parent_id); if(item_array) { vector_replace_with_last(*item_array, old_item); @@ -978,6 +989,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) item_array = get_ptr_in_map(mParentChildItemTree, new_parent_id); if(item_array) { + if (update_parent_on_server) + { + LLInventoryModel::LLCategoryUpdate update(new_parent_id, 1); + gInventory.accountForUpdate(update); + } item_array->push_back(old_item); } mask |= LLInventoryObserver::STRUCTURE; @@ -991,6 +1007,12 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) mask |= LLInventoryObserver::DESCRIPTION; } old_item->copyViewerItem(item); + if (update_parent_on_server) + { + // Parent id at server is null, so update server even if item already is in the same folder + old_item->setParent(new_parent_id); + new_item->updateParentOnServer(FALSE); + } mask |= LLInventoryObserver::INTERNAL; } else @@ -1006,8 +1028,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, category_id); if( item_array ) { + LLInventoryModel::LLCategoryUpdate update(category_id, 1); + gInventory.accountForUpdate(update); + // *FIX: bit of a hack to call update server from here... - new_item->updateServer(TRUE); + new_item->updateParentOnServer(FALSE); item_array->push_back(new_item); } else @@ -1048,9 +1073,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) item_array = get_ptr_in_map(mParentChildItemTree, parent_id); if(item_array) { + LLInventoryModel::LLCategoryUpdate update(parent_id, 1); + gInventory.accountForUpdate(update); // *FIX: bit of a hack to call update server from // here... - new_item->updateServer(TRUE); + new_item->updateParentOnServer(FALSE); item_array->push_back(new_item); } else @@ -1073,19 +1100,17 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) { // Valid UUID; set the item UUID and rename it new_item->setCreator(id); - std::string avatar_name; + LLAvatarName av_name; - if (gCacheName->getFullName(id, avatar_name)) + if (LLAvatarNameCache::get(id, &av_name)) { - new_item->rename(avatar_name); + new_item->rename(av_name.getLegacyName()); mask |= LLInventoryObserver::LABEL; } else { // Fetch the current name - gCacheName->get(id, FALSE, - boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(), - _1, _2, _3)); + LLAvatarNameCache::get(id, boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(), _1, _2)); } } @@ -1122,7 +1147,7 @@ LLInventoryModel::item_array_t* LLInventoryModel::getUnlockedItemArray(const LLU // an existing item with the matching id, or it will add the category. void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 mask) { - if(cat->getUUID().isNull()) + if(!cat || cat->getUUID().isNull()) { return; } @@ -1136,14 +1161,13 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 LLPointer old_cat = getCategory(cat->getUUID()); if(old_cat) { - // We already have an old category, modify it's values + // We already have an old category, modify its values LLUUID old_parent_id = old_cat->getParentUUID(); LLUUID new_parent_id = cat->getParentUUID(); if(old_parent_id != new_parent_id) { // need to update the parent-child tree - cat_array_t* cat_array; - cat_array = getUnlockedCatArray(old_parent_id); + cat_array_t* cat_array = getUnlockedCatArray(old_parent_id); if(cat_array) { vector_replace_with_last(*cat_array, old_cat); @@ -1160,6 +1184,12 @@ 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, false); + if (marketplace_id.notNull() && isObjectDescendentOf(cat->getUUID(), marketplace_id)) + { + mask |= LLInventoryObserver::LABEL; + } old_cat->copyViewerCategory(cat); addChangedMask(mask, cat->getUUID()); } @@ -1171,21 +1201,21 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 addCategory(new_cat); // make sure this category is correctly referenced by its parent. - cat_array_t* cat_array; - cat_array = getUnlockedCatArray(cat->getParentUUID()); + cat_array_t* cat_array = getUnlockedCatArray(cat->getParentUUID()); if(cat_array) { cat_array->push_back(new_cat); } // make space in the tree for this category's children. - llassert_always(mCategoryLock[LLUUID(new_cat->getUUID())] == false); - llassert_always(mItemLock[LLUUID(new_cat->getUUID())] == false); + llassert_always(mCategoryLock[new_cat->getUUID()] == false); + llassert_always(mItemLock[new_cat->getUUID()] == false); cat_array_t* catsp = new cat_array_t; item_array_t* itemsp = new item_array_t; mParentChildCategoryTree[new_cat->getUUID()] = catsp; mParentChildItemTree[new_cat->getUUID()] = itemsp; - addChangedMask(LLInventoryObserver::ADD, cat->getUUID()); + mask |= LLInventoryObserver::ADD; + addChangedMask(mask, cat->getUUID()); } } @@ -1207,8 +1237,7 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id) LLPointer cat = getCategory(object_id); if(cat && (cat->getParentUUID() != cat_id)) { - cat_array_t* cat_array; - cat_array = getUnlockedCatArray(cat->getParentUUID()); + cat_array_t* cat_array = getUnlockedCatArray(cat->getParentUUID()); if(cat_array) vector_replace_with_last(*cat_array, cat); cat_array = getUnlockedCatArray(cat_id); cat->setParent(cat_id); @@ -1219,8 +1248,7 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id) LLPointer item = getItem(object_id); if(item && (item->getParentUUID() != cat_id)) { - item_array_t* item_array; - item_array = getUnlockedItemArray(item->getParentUUID()); + item_array_t* item_array = getUnlockedItemArray(item->getParentUUID()); if(item_array) vector_replace_with_last(*item_array, item); item_array = getUnlockedItemArray(cat_id); item->setParent(cat_id); @@ -1296,7 +1324,8 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update) { LLTimer timer; - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + static LLCachedControl debug_ava_appr_msg(gSavedSettings, "DebugAvatarAppearanceMessage"); + if (debug_ava_appr_msg) { dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update); } @@ -1437,7 +1466,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo if (getCategory(uu_id)) { cat_array_t* cat_list = getUnlockedCatArray(uu_id); - if (!cat_list || (cat_list->size() == 0)) + if (!cat_list || (cat_list->empty())) { deleteObject(uu_id, fix_broken_links); deleted_count++; @@ -1496,7 +1525,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo } LL_DEBUGS(LOG_INV) << "Deleting inventory object " << id << LL_ENDL; - mLastItem = NULL; + mLastItem = nullptr; LLUUID parent_id = obj->getParentUUID(); mCategoryMap.erase(id); mItemMap.erase(id); @@ -1513,10 +1542,15 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo LLPointer cat = (LLViewerInventoryCategory*)((LLInventoryObject*)obj); vector_replace_with_last(*cat_list, cat); } + + // Note : We need to tell the inventory observers that those things are going to be deleted *before* the tree is cleared or they won't know what to delete (in views and view models) + addChangedMask(LLInventoryObserver::REMOVE, id); + gInventory.notifyObservers(); + item_list = getUnlockedItemArray(id); if(item_list) { - if (item_list->size()) + if (!item_list->empty()) { LL_WARNS(LOG_INV) << "Deleting cat " << id << " while it still has child items" << LL_ENDL; } @@ -1526,7 +1560,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo cat_list = getUnlockedCatArray(id); if(cat_list) { - if (cat_list->size()) + if (!cat_list->empty()) { LL_WARNS(LOG_INV) << "Deleting cat " << id << " while it still has child cats" << LL_ENDL; } @@ -1544,11 +1578,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo // Can't have links to links, so there's no need for this update // if the item removed is a link. Can also skip if source of the // update is getting broken link info separately. - obj = NULL; // delete obj if (fix_broken_links && !is_link_type) { updateLinkedObjectsFromPurge(id); } + obj = nullptr; // delete obj if (do_notify_observers) { notifyObservers(); @@ -1561,12 +1595,12 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) // REBUILD is expensive, so clear the current change list first else // everything else on the changelist will also get rebuilt. - if (item_array.size() > 0) + if (!item_array.empty()) { notifyObservers(); for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); iter != item_array.end(); - iter++) + ++iter) { const LLViewerInventoryItem *linked_item = (*iter); const LLUUID &item_id = linked_item->getUUID(); @@ -1596,7 +1630,7 @@ BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) const void LLInventoryModel::idleNotifyObservers() { - if (mModifyMask == LLInventoryObserver::NONE && (mChangedItemIDs.size() == 0)) + if (mModifyMask == LLInventoryObserver::NONE && (mChangedItemIDs.empty())) { return; } @@ -1658,9 +1692,10 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent) } mModifyMask |= mask; - if (referent.notNull()) + if (referent.notNull() && (mChangedItemIDs.find(referent) == mChangedItemIDs.end())) { mChangedItemIDs.insert(referent); + update_marketplace_category(referent, false); if (mask & LLInventoryObserver::ADD) { @@ -1717,7 +1752,7 @@ void LLInventoryModel::cache( item_array_t items; LLCanCache can_cache(this); - can_cache(root_cat, NULL); + can_cache(root_cat, nullptr); collectDescendentsIf( parent_folder_id, categories, @@ -1766,8 +1801,7 @@ void LLInventoryModel::addCategory(LLViewerInventoryCategory* category) bool LLInventoryModel::hasBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id) const { - std::pair range; - range = mBacklinkMMap.equal_range(target_id); + std::pair range = mBacklinkMMap.equal_range(target_id); for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it) { if (it->second == link_id) @@ -1788,8 +1822,7 @@ void LLInventoryModel::addBacklinkInfo(const LLUUID& link_id, const LLUUID& targ void LLInventoryModel::removeBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id) { - std::pair range; - range = mBacklinkMMap.equal_range(target_id); + std::pair range = mBacklinkMMap.equal_range(target_id); for (backlink_mmap_t::iterator it = range.first; it != range.second; ) { if (it->second == link_id) @@ -1810,11 +1843,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) llassert(item); if(item) { - // This can happen if assettype enums from llassettype.h ever change. - // For example, there is a known backwards compatibility issue in some viewer prototypes prior to when - // the AT_LINK enum changed from 23 to 24. - if ((item->getType() == LLAssetType::AT_NONE) - || LLAssetType::lookup(item->getType()) == LLAssetType::badLookup()) + if (item->getType() <= LLAssetType::AT_NONE) { LL_WARNS(LOG_INV) << "Got bad asset type for item [ name: " << item->getName() << " type: " << item->getType() @@ -1822,6 +1851,23 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) return; } + if (LLAssetType::lookup(item->getType()) == LLAssetType::badLookup()) + { + if (item->getType() >= LLAssetType::AT_COUNT) + { + // Not yet supported. + LL_DEBUGS(LOG_INV) << "Got unknown asset type for item [ name: " << item->getName() + << " type: " << item->getType() + << " inv-type: " << item->getInventoryType() << " ]." << LL_ENDL; + } + else + { + LL_WARNS(LOG_INV) << "Got unknown asset type for item [ name: " << item->getName() + << " type: " << item->getType() + << " inv-type: " << item->getInventoryType() << " ]." << LL_ENDL; + } + } + // This condition means that we tried to add a link without the baseobj being in memory. // The item will show up as a broken link. if (item->getIsBrokenLink()) @@ -1844,7 +1890,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) // Empty the entire contents void LLInventoryModel::empty() { -// LL_INFOS() << "LLInventoryModel::empty()" << LL_ENDL; + // LL_INFOS(LOG_INV) << "LLInventoryModel::empty()" << LL_ENDL; std::for_each( mParentChildCategoryTree.begin(), mParentChildCategoryTree.end(), @@ -1903,8 +1949,7 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const } } -void LLInventoryModel::accountForUpdate( - const LLInventoryModel::update_list_t& update) +void LLInventoryModel::accountForUpdate(const LLInventoryModel::update_list_t& update) { update_list_t::const_iterator it = update.begin(); update_list_t::const_iterator end = update.end(); @@ -1914,8 +1959,7 @@ void LLInventoryModel::accountForUpdate( } } -void LLInventoryModel::accountForUpdate( - const LLInventoryModel::update_map_t& update) +void LLInventoryModel::accountForUpdate(const LLInventoryModel::update_map_t& update) { LLCategoryUpdate up; update_map_t::const_iterator it = update.begin(); @@ -1928,8 +1972,7 @@ void LLInventoryModel::accountForUpdate( } } -LLInventoryModel::EHasChildren LLInventoryModel::categoryHasChildren( - const LLUUID& cat_id) const +LLInventoryModel::EHasChildren LLInventoryModel::categoryHasChildren(const LLUUID& cat_id) const { LLViewerInventoryCategory* cat = getCategory(cat_id); if(!cat) return CHILDREN_NO; @@ -1948,13 +1991,13 @@ LLInventoryModel::EHasChildren LLInventoryModel::categoryHasChildren( } // Shouldn't have to run this, but who knows. - parent_cat_map_t::const_iterator cat_it = mParentChildCategoryTree.find(cat->getUUID()); - if (cat_it != mParentChildCategoryTree.end() && cat_it->second->size() > 0) + const auto cat_it = mParentChildCategoryTree.find(cat->getUUID()); + if (cat_it != mParentChildCategoryTree.cend() && !cat_it->second->empty()) { return CHILDREN_YES; } - parent_item_map_t::const_iterator item_it = mParentChildItemTree.find(cat->getUUID()); - if (item_it != mParentChildItemTree.end() && item_it->second->size() > 0) + const auto item_it = mParentChildItemTree.find(cat->getUUID()); + if (item_it != mParentChildItemTree.cend() && !item_it->second->empty()) { return CHILDREN_YES; } @@ -2030,6 +2073,7 @@ bool LLInventoryModel::loadSkeleton( update_map_t child_counts; cat_array_t categories; item_array_t items; + changed_items_t categories_to_update; item_array_t possible_broken_links; cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded. std::string owner_id_str; @@ -2042,11 +2086,11 @@ bool LLInventoryModel::loadSkeleton( gzip_filename.append(".gz"); LLFILE* fp = LLFile::fopen(gzip_filename, "rb"); bool remove_inventory_file = false; - if (fp) + if(fp) { fclose(fp); - fp = NULL; - if (gunzip_file(gzip_filename, inventory_filename)) + fp = nullptr; + if(gunzip_file(gzip_filename, inventory_filename)) { // we only want to remove the inventory file if it was // gzipped before we loaded, and we successfully @@ -2059,7 +2103,7 @@ bool LLInventoryModel::loadSkeleton( } } bool is_cache_obsolete = false; - if(loadFromFile(inventory_filename, categories, items, is_cache_obsolete)) + if (loadFromFile(inventory_filename, categories, items, categories_to_update, is_cache_obsolete)) { // We were able to find a cache of files. So, use what we // found to generate a set of categories we should add. We @@ -2067,7 +2111,7 @@ bool LLInventoryModel::loadSkeleton( // does not match, invalidate the version. S32 count = categories.size(); cat_set_t::iterator not_cached = temp_cats.end(); - std::set cached_ids; + uuid_set_t cached_ids; for(S32 i = 0; i < count; ++i) { LLViewerInventoryCategory* cat = categories[i]; @@ -2078,13 +2122,19 @@ bool LLInventoryModel::loadSkeleton( } LLViewerInventoryCategory* tcat = *cit; + if (categories_to_update.find(tcat->getUUID()) != categories_to_update.end()) + { + tcat->setVersion(NO_VERSION); + LL_WARNS() << "folder to update: " << tcat->getName() << LL_ENDL; + } + // we can safely ignore anything loaded from file, but // not sent down in the skeleton. Must have been removed from inventory. if (cit == not_cached) { continue; } - if (cat->getVersion() != tcat->getVersion()) + else if (cat->getVersion() != tcat->getVersion()) { // if the cached version does not match the server version, // throw away the version we have so we can fetch the @@ -2098,20 +2148,20 @@ bool LLInventoryModel::loadSkeleton( } // go ahead and add the cats returned during the download - std::set::const_iterator not_cached_id = cached_ids.end(); + auto not_cached_id = cached_ids.end(); cached_category_count = cached_ids.size(); - for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it) + for (const auto& temp_cat : temp_cats) { - if (cached_ids.find((*it)->getUUID()) == not_cached_id) + if(cached_ids.find(temp_cat->getUUID()) == not_cached_id) { // this check is performed so that we do not // mark new folders in the skeleton (and not in cache) // as being cached. - LLViewerInventoryCategory *llvic = (*it); + LLViewerInventoryCategory *llvic = temp_cat; llvic->setVersion(NO_VERSION); } - addCategory(*it); - ++child_counts[(*it)->getParentUUID()]; + addCategory(temp_cat); + ++child_counts[temp_cat->getParentUUID()]; } // Add all the items loaded which are parented to a @@ -2119,14 +2169,13 @@ bool LLInventoryModel::loadSkeleton( S32 bad_link_count = 0; S32 good_link_count = 0; S32 recovered_link_count = 0; - cat_map_t::iterator unparented = mCategoryMap.end(); + const auto unparented = mCategoryMap.cend(); for(item_array_t::const_iterator item_iter = items.begin(); item_iter != items.end(); ++item_iter) { LLViewerInventoryItem *item = (*item_iter).get(); - const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID()); - + const auto cit = mCategoryMap.find(item->getParentUUID()); if(cit != unparented) { const LLViewerInventoryCategory* cat = cit->second.get(); @@ -2143,7 +2192,7 @@ bool LLInventoryModel::loadSkeleton( possible_broken_links.push_back(item); continue; } - else if (item->getIsLinkType()) + if (item->getIsLinkType()) { good_link_count++; } @@ -2153,20 +2202,20 @@ bool LLInventoryModel::loadSkeleton( } } } - if (possible_broken_links.size() > 0) + if (!possible_broken_links.empty()) { for(item_array_t::const_iterator item_iter = possible_broken_links.begin(); item_iter != possible_broken_links.end(); ++item_iter) { LLViewerInventoryItem *item = (*item_iter).get(); - const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID()); + const auto cit = mCategoryMap.find(item->getParentUUID()); const LLViewerInventoryCategory* cat = cit->second.get(); if (item->getIsBrokenLink()) { bad_link_count++; invalid_categories.insert(cit->second); - //LL_INFOS() << "link still broken: " << item->getName() << " in folder " << cat->getName() << LL_ENDL; + //LL_INFOS(LOG_INV) << "link still broken: " << item->getName() << " in folder " << cat->getName() << LL_ENDL; } else { @@ -2190,21 +2239,19 @@ bool LLInventoryModel::loadSkeleton( { // go ahead and add everything after stripping the version // information. - for (cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it) + for (const auto& temp_cat : temp_cats) { - LLViewerInventoryCategory *llvic = (*it); + LLViewerInventoryCategory *llvic = temp_cat; llvic->setVersion(NO_VERSION); - addCategory(*it); + addCategory(temp_cat); } } // Invalidate all categories that failed fetching descendents for whatever // reason (e.g. one of the descendents was a broken link). - for (cat_set_t::iterator invalid_cat_it = invalid_categories.begin(); - invalid_cat_it != invalid_categories.end(); - invalid_cat_it++) + for (const auto& invalid_categorie : invalid_categories) { - LLViewerInventoryCategory* cat = (*invalid_cat_it).get(); + LLViewerInventoryCategory* cat = invalid_categorie.get(); cat->setVersion(NO_VERSION); LL_DEBUGS(LOG_INV) << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << LL_ENDL; } @@ -2214,9 +2261,9 @@ bool LLInventoryModel::loadSkeleton( // category which successfully cached so that we do not // needlessly fetch descendents for categories which we have. update_map_t::const_iterator no_child_counts = child_counts.end(); - for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it) + for (const auto& temp_cat : temp_cats) { - LLViewerInventoryCategory* cat = (*it).get(); + LLViewerInventoryCategory* cat = temp_cat.get(); if(cat->getVersion() != NO_VERSION) { update_map_t::const_iterator the_count = child_counts.find(cat->getUUID()); @@ -2232,7 +2279,7 @@ bool LLInventoryModel::loadSkeleton( } } - if (remove_inventory_file) + if(remove_inventory_file) { // clean up the gunzipped file. LLFile::remove(inventory_filename); @@ -2272,9 +2319,9 @@ void LLInventoryModel::buildParentChildMap() cat_array_t* catsp; item_array_t* itemsp; - for(cat_map_t::iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit) + for (auto& cit : mCategoryMap) { - LLViewerInventoryCategory* cat = cit->second; + LLViewerInventoryCategory* cat = cit.second; cats.push_back(cat); if (mParentChildCategoryTree.count(cat->getUUID()) == 0) { @@ -2348,22 +2395,28 @@ void LLInventoryModel::buildParentChildMap() // plop it into the lost & found. LLFolderType::EType pref = cat->getPreferredType(); if(LLFolderType::FT_NONE == pref) - { - cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); - } - else if(LLFolderType::FT_ROOT_INVENTORY == pref) - { - // it's the root - cat->setParent(LLUUID::null); - } - else - { - // it's a protected folder. - cat->setParent(gInventory.getRootFolderID()); - } - cat->updateServer(TRUE); - catsp = getUnlockedCatArray(cat->getParentUUID()); - if(catsp) + { + cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); + } + else if(LLFolderType::FT_ROOT_INVENTORY == pref) + { + // it's the root + cat->setParent(LLUUID::null); + } + else + { + // it's a protected folder. + cat->setParent(gInventory.getRootFolderID()); + } + // FIXME note that updateServer() fails with protected + // types, so this will not work as intended in that case. + // UpdateServer uses AIS, AIS cat move is not implemented yet + // cat->updateServer(TRUE); + + // MoveInventoryFolder message, intentionally per item + cat->updateParentOnServer(FALSE); + catsp = getUnlockedCatArray(cat->getParentUUID()); + if(catsp) { catsp->push_back(cat); } @@ -2383,10 +2436,9 @@ void LLInventoryModel::buildParentChildMap() item_array_t items; if(!mItemMap.empty()) { - LLPointer item; - for(item_map_t::iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit) + for (auto& iit : mItemMap) { - item = (*iit).second; + LLPointer item = iit.second; items.push_back(item); } } @@ -2395,8 +2447,7 @@ void LLInventoryModel::buildParentChildMap() uuid_vec_t lost_item_ids; for(i = 0; i < count; ++i) { - LLPointer item; - item = items.at(i); + LLPointer item = items.at(i); itemsp = getUnlockedItemArray(item->getParentUUID()); if(itemsp) { @@ -2445,7 +2496,7 @@ void LLInventoryModel::buildParentChildMap() msg->nextBlockFast(_PREHASH_InventoryData); msg->addUUIDFast(_PREHASH_ItemID, (*it)); msg->addUUIDFast(_PREHASH_FolderID, lnf); - msg->addString("NewName", NULL); + msg->addString("NewName", nullptr); if(msg->isSendFull(NULL)) { start_new_message = TRUE; @@ -2458,16 +2509,16 @@ void LLInventoryModel::buildParentChildMap() } } - const LLUUID& agent_inv_root_id = gInventory.getRootFolderID(); + const LLUUID &agent_inv_root_id = gInventory.getRootFolderID(); if (agent_inv_root_id.notNull()) { cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id); if(catsp) { // *HACK - fix root inventory folder - // some accounts has pbroken inventory root folders + // some accounts has broken inventory root folders - std::string name = "My Inventory"; + static const std::string name = "My Inventory"; LLUUID prev_root_id = mRootFolderID; for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(), it_end = mParentChildCategoryTree.end(); it != it_end; ++it) @@ -2495,6 +2546,7 @@ void LLInventoryModel::buildParentChildMap() // root of the agent's inv found. // The inv tree is built. mIsAgentInvUsable = true; + AIEvent::trigger(AIEvent::LLInventoryModel_mIsAgentInvUsable_true); // notifyObservers() has been moved to // llstartup/idle_startup() after this func completes. @@ -2519,7 +2571,7 @@ void LLInventoryModel::createCommonSystemCategories() struct LLUUIDAndName { - LLUUIDAndName() {} + LLUUIDAndName() = default; LLUUIDAndName(const LLUUID& id, const std::string& name); bool operator==(const LLUUIDAndName& rhs) const; bool operator<(const LLUUIDAndName& rhs) const; @@ -2553,6 +2605,7 @@ bool LLUUIDAndName::operator>(const LLUUIDAndName& rhs) const bool LLInventoryModel::loadFromFile(const std::string& filename, LLInventoryModel::cat_array_t& categories, LLInventoryModel::item_array_t& items, + LLInventoryModel::changed_items_t& cats_to_update, bool &is_cache_obsolete) { if(filename.empty()) @@ -2575,7 +2628,7 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, while(!feof(file) && fgets(buffer, MAX_STRING, file)) { sscanf(buffer, " %126s %126s", keyword, value); /* Flawfinder: ignore */ - if (0 == strcmp("inv_cache_version", keyword)) + if(0 == strcmp("inv_cache_version", keyword)) { S32 version; int succ = sscanf(value,"%d",&version); @@ -2627,7 +2680,14 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, } else { - items.push_back(inv_item); + if (inv_item->getType() == LLAssetType::AT_UNKNOWN) + { + cats_to_update.insert(inv_item->getParentUUID()); + } + else + { + items.push_back(inv_item); + } } } else @@ -2666,8 +2726,7 @@ bool LLInventoryModel::saveToFile(const std::string& filename, return false; } - fprintf(file, "\tinv_cache_version\t%d\n", sCurrentInvCacheVersion); - + fprintf(file, "\tinv_cache_version\t%d\n",sCurrentInvCacheVersion); S32 count = categories.size(); S32 i; for(i = 0; i < count; ++i) @@ -2775,7 +2834,6 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 item_array_t items; update_map_t update; S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); - LLUUID folder_id; // Does this loop ever execute more than once? for(S32 i = 0; i < count; ++i) { @@ -2802,10 +2860,6 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 { ++update[titem->getParentUUID()]; } - if (folder_id.isNull()) - { - folder_id = titem->getParentUUID(); - } } if(account) { @@ -2818,9 +2872,9 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 mask |= LLInventoryObserver::CREATE; } //as above, this loop never seems to loop more than once per call - for (item_array_t::iterator it = items.begin(); it != items.end(); ++it) + for (auto& item : items) { - changes |= gInventory.updateItem(*it, mask); + changes |= gInventory.updateItem(item, mask); } gInventory.notifyObservers(); gViewerWindow->getWindow()->decBusyCount(); @@ -2852,10 +2906,10 @@ void LLInventoryModel::removeInventoryItem(LLUUID agent_id, LLMessageSystem* msg } } gInventory.accountForUpdate(update); - for(uuid_vec_t::iterator it = item_ids.begin(); it != item_ids.end(); ++it) + for (auto& item_id : item_ids) { - LL_DEBUGS(LOG_INV) << "Calling deleteObject " << *it << LL_ENDL; - gInventory.deleteObject(*it); + LL_DEBUGS(LOG_INV) << "Calling deleteObject " << item_id << LL_ENDL; + gInventory.deleteObject(item_id); } } @@ -2863,7 +2917,7 @@ void LLInventoryModel::removeInventoryItem(LLUUID agent_id, LLMessageSystem* msg void LLInventoryModel::processRemoveInventoryItem(LLMessageSystem* msg, void**) { LL_DEBUGS(LOG_INV) << "LLInventoryModel::processRemoveInventoryItem()" << LL_ENDL; - LLUUID agent_id, item_id; + LLUUID agent_id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); if(agent_id != gAgent.getID()) { @@ -2880,7 +2934,7 @@ void LLInventoryModel::processUpdateInventoryFolder(LLMessageSystem* msg, void**) { LL_DEBUGS(LOG_INV) << "LLInventoryModel::processUpdateInventoryFolder()" << LL_ENDL; - LLUUID agent_id, folder_id, parent_id; + LLUUID agent_id; //char name[DB_INV_ITEM_NAME_BUF_SIZE]; msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_AgentID, agent_id); if(agent_id != gAgent.getID()) @@ -2921,9 +2975,9 @@ void LLInventoryModel::processUpdateInventoryFolder(LLMessageSystem* msg, } } gInventory.accountForUpdate(update); - for (cat_array_t::iterator it = folders.begin(); it != folders.end(); ++it) + for (auto& folder : folders) { - gInventory.updateCategory(*it); + gInventory.updateCategory(folder); } gInventory.notifyObservers(); @@ -2936,8 +2990,7 @@ void LLInventoryModel::processUpdateInventoryFolder(LLMessageSystem* msg, } // static -void LLInventoryModel::removeInventoryFolder(LLUUID agent_id, - LLMessageSystem* msg) +void LLInventoryModel::removeInventoryFolder(LLUUID agent_id, LLMessageSystem* msg) { LLUUID folder_id; uuid_vec_t folder_ids; @@ -2954,15 +3007,14 @@ void LLInventoryModel::removeInventoryFolder(LLUUID agent_id, } } gInventory.accountForUpdate(update); - for(uuid_vec_t::iterator it = folder_ids.begin(); it != folder_ids.end(); ++it) + for (auto& folder_id : folder_ids) { - gInventory.deleteObject(*it); + gInventory.deleteObject(folder_id); } } // static -void LLInventoryModel::processRemoveInventoryFolder(LLMessageSystem* msg, - void**) +void LLInventoryModel::processRemoveInventoryFolder(LLMessageSystem* msg, void**) { LL_DEBUGS() << "LLInventoryModel::processRemoveInventoryFolder()" << LL_ENDL; LLUUID agent_id, session_id; @@ -2979,8 +3031,7 @@ void LLInventoryModel::processRemoveInventoryFolder(LLMessageSystem* msg, } // static -void LLInventoryModel::processRemoveInventoryObjects(LLMessageSystem* msg, - void**) +void LLInventoryModel::processRemoveInventoryObjects(LLMessageSystem* msg, void**) { LL_DEBUGS() << "LLInventoryModel::processRemoveInventoryObjects()" << LL_ENDL; LLUUID agent_id, session_id; @@ -2998,8 +3049,7 @@ void LLInventoryModel::processRemoveInventoryObjects(LLMessageSystem* msg, } // static -void LLInventoryModel::processSaveAssetIntoInventory(LLMessageSystem* msg, - void**) +void LLInventoryModel::processSaveAssetIntoInventory(LLMessageSystem* msg, void**) { LLUUID agent_id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); @@ -3071,9 +3121,8 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) update_map_t update; cat_array_t folders; - S32 count; S32 i; - count = msg->getNumberOfBlocksFast(_PREHASH_FolderData); + S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData); for(i = 0; i < count; ++i) { LLPointer tfolder = new LLViewerInventoryCategory(gAgent.getID()); @@ -3081,7 +3130,18 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) LL_DEBUGS("Inventory") << "unpacked folder '" << tfolder->getName() << "' (" << tfolder->getUUID() << ") in " << tfolder->getParentUUID() << LL_ENDL; - if(tfolder->getUUID().notNull()) + + // If the folder is a listing or a version folder, all we need to do is update the SLM data + int depth_folder = depth_nesting_in_marketplace(tfolder->getUUID()); + if ((depth_folder == 1) || (depth_folder == 2)) + { + // Trigger an SLM listing update + LLUUID listing_uuid = (depth_folder == 1 ? tfolder->getUUID() : tfolder->getParentUUID()); + S32 listing_id = LLMarketplaceData::instance().getListingID(listing_uuid); + LLMarketplaceData::instance().getListing(listing_id); + // In that case, there is no item to update so no callback -> we skip the rest of the update + } + else if(tfolder->getUUID().notNull()) { folders.push_back(tfolder); LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID()); @@ -3141,7 +3201,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) if(titem->getUUID().notNull() ) // && callback_id.notNull() ) { items.push_back(titem); - cblist.push_back(InventoryCallbackInfo(callback_id, titem->getUUID())); + cblist.emplace_back(callback_id, titem->getUUID()); if (titem->getInventoryType() == LLInventoryType::IT_WEARABLE) { wearable_ids.push_back(titem->getUUID()); @@ -3171,18 +3231,18 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) } else { - cblist.push_back(InventoryCallbackInfo(callback_id, LLUUID::null)); + cblist.emplace_back(callback_id, LLUUID::null); } } gInventory.accountForUpdate(update); - for (cat_array_t::iterator cit = folders.begin(); cit != folders.end(); ++cit) + for (auto& folder : folders) { - gInventory.updateCategory(*cit); + gInventory.updateCategory(folder); } - for (item_array_t::iterator iit = items.begin(); iit != items.end(); ++iit) + for (auto& item : items) { - gInventory.updateItem(*iit); + gInventory.updateItem(item); } gInventory.notifyObservers(); @@ -3200,20 +3260,21 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) count = wearable_ids.size(); for (i = 0; i < count; ++i) { - LLViewerInventoryItem* wearable_item; - wearable_item = gInventory.getItem(wearable_ids[i]); + LLViewerInventoryItem * wearable_item = gInventory.getItem(wearable_ids[i]); LLAppearanceMgr::instance().wearItemOnAvatar(wearable_item->getUUID(), true, true); } } - std::list::iterator inv_it; - for (inv_it = cblist.begin(); inv_it != cblist.end(); ++inv_it) + for (auto& inv_it : cblist) { - InventoryCallbackInfo cbinfo = (*inv_it); + InventoryCallbackInfo cbinfo = inv_it; gInventoryCallbacks.fire(cbinfo.mCallback, cbinfo.mInvID); } + + //gInventory.validate(); + // Don't show the inventory. We used to call showAgentInventory here. - //LLInventoryView* view = LLInventoryView::getActiveInventory(); + //LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); //if(view) //{ // const BOOL take_keyboard_focus = FALSE; @@ -3223,10 +3284,10 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) // // HACK to open inventory offers that are accepted. This information // // really needs to flow through the instant messages and inventory // // transfer/update messages. - // if (LLInventoryView::sOpenNextNewItem) + // if (LLFloaterInventory::sOpenNextNewItem) // { // view->openSelected(); - // LLInventoryView::sOpenNextNewItem = FALSE; + // LLFloaterInventory::sOpenNextNewItem = FALSE; // } // // // restore keyboard focus @@ -3357,7 +3418,7 @@ bool LLInventoryModel::callbackEmptyFolderType(const LLSD& notification, const L if (option == 0) // YES { const LLUUID folder_id = findCategoryUUIDForType(preferred_type); - purge_descendents_of(folder_id, NULL); + purge_descendents_of(folder_id, nullptr); } return false; } @@ -3372,7 +3433,7 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderT else { const LLUUID folder_id = findCategoryUUIDForType(preferred_type); - purge_descendents_of(folder_id, NULL); + purge_descendents_of(folder_id, nullptr); } } @@ -3434,6 +3495,11 @@ void LLInventoryModel::removeCategory(const LLUUID& category_id) void LLInventoryModel::removeObject(const LLUUID& object_id) { + if(object_id.isNull()) + { + return; + } + LLInventoryObject* obj = getObject(object_id); if (dynamic_cast(obj)) { @@ -3581,25 +3647,25 @@ void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& item } */ // See also LLInventorySort where landmarks in the Favorites folder are sorted. -/*class LLViewerInventoryItemSort +class LLViewerInventoryItemSort { public: - bool operator()(const LLPointer& a, const LLPointer& b) + bool operator()(const LLPointer& a, const LLPointer& b) const { return a->getSortField() < b->getSortField(); } -};*/ +}; /** * Sorts passed items by LLViewerInventoryItem sort field. * * @param[in, out] items - array of items, not sorted. */ -/*static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) -{ - static LLViewerInventoryItemSort sort_functor; - std::sort(items.begin(), items.end(), sort_functor); -}*/ +//static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) +//{ +// static LLViewerInventoryItemSort sort_functor; +// std::sort(items.begin(), items.end(), sort_functor); +//} // * @param source_item_id - LLUUID of the source item to be moved into new position // * @param target_item_id - LLUUID of the target item before which source item should be placed. @@ -3628,13 +3694,14 @@ void LLInventoryModel::dumpInventory() const { LL_INFOS() << "\nBegin Inventory Dump\n**********************:" << LL_ENDL; LL_INFOS() << "mCategory[] contains " << mCategoryMap.size() << " items." << LL_ENDL; - for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit) + for (const auto& cit : mCategoryMap) { - const LLViewerInventoryCategory* cat = cit->second; + const LLViewerInventoryCategory* cat = cit.second; if(cat) { LL_INFOS() << " " << cat->getUUID() << " '" << cat->getName() << "' " - << cat->getVersion() << " " << cat->getDescendentCount() << " parent: " << cat->getParentUUID() + << cat->getVersion() << " " << cat->getDescendentCount() + << " parent: " << cat->getParentUUID() << LL_ENDL; } else @@ -3643,9 +3710,9 @@ void LLInventoryModel::dumpInventory() const } } LL_INFOS() << "mItemMap[] contains " << mItemMap.size() << " items." << LL_ENDL; - for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit) + for (const auto& iit : mItemMap) { - const LLViewerInventoryItem* item = iit->second; + const LLViewerInventoryItem* item = iit.second; if(item) { LL_INFOS() << " " << item->getUUID() << " " @@ -3687,10 +3754,10 @@ bool LLInventoryModel::validate() const S32 item_lock = 0; S32 desc_unknown_count = 0; S32 version_unknown_count = 0; - for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit) + for (const auto& cit : mCategoryMap) { - const LLUUID& cat_id = cit->first; - const LLViewerInventoryCategory *cat = cit->second; + const LLUUID& cat_id = cit.first; + const LLViewerInventoryCategory *cat = cit.second; if (!cat) { LL_WARNS() << "invalid cat" << LL_ENDL; @@ -3824,9 +3891,9 @@ bool LLInventoryModel::validate() const else { bool found = false; - for (U32 i = 0; isize(); i++) + for (auto& i : *cats) { - LLViewerInventoryCategory *kid_cat = cats->at(i); + LLViewerInventoryCategory *kid_cat = i; if (kid_cat == cat) { found = true; @@ -3842,10 +3909,10 @@ bool LLInventoryModel::validate() const } } - for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit) + for (const auto& iit : mItemMap) { - const LLUUID& item_id = iit->first; - LLViewerInventoryItem *item = iit->second; + const LLUUID& item_id = iit.first; + LLViewerInventoryItem *item = iit.second; if (item->getUUID() != item_id) { LL_WARNS() << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL; @@ -3870,9 +3937,9 @@ bool LLInventoryModel::validate() const else { bool found = false; - for (U32 i=0; isize(); ++i) + for (auto& i : *items) { - if (items->at(i) == item) + if (i == item) { found = true; break; @@ -3973,13 +4040,17 @@ BOOL decompress_file(const char* src_filename, const char* dst_filename) S32 bytes = 0; const S32 DECOMPRESS_BUFFER_SIZE = 32000; - // open the files +// open the files +#if LL_WINDOWS + src = gzopen_w(utf8str_to_utf16str(src_filename).c_str(), "rb"); +#else src = gzopen(src_filename, "rb"); +#endif if(!src) goto err_decompress; dst = LLFile::fopen(dst_filename, "wb"); if(!dst) goto err_decompress; - // decompress. +// decompress. buffer = new U8[DECOMPRESS_BUFFER_SIZE + 1]; do @@ -3993,7 +4064,7 @@ BOOL decompress_file(const char* src_filename, const char* dst_filename) fwrite(buffer, bytes, 1, dst); } while(gzeof(src) == 0); - // success +// success rv = TRUE; err_decompress: @@ -4005,13 +4076,13 @@ BOOL decompress_file(const char* src_filename, const char* dst_filename) #endif // If we get back a normal response, handle it here -void LLInventoryModel::FetchItemHttpHandler::httpSuccess(void) +void LLInventoryModel::FetchItemHttpHandler::httpSuccess() { start_new_inventory_observer(); #if 0 LLUUID agent_id; - agent_id = content["agent_id"].asUUID(); + agent_id = mContent["agent_id"].asUUID(); if (agent_id != gAgent.getID()) { LL_WARNS(LOG_INV) << "Got a inventory update for the wrong agent: " << agent_id @@ -4041,7 +4112,7 @@ void LLInventoryModel::FetchItemHttpHandler::httpSuccess(void) if (itemp) { - if(titem->getParentUUID() == itemp->getParentUUID()) + if (titem->getParentUUID() == itemp->getParentUUID()) { update[titem->getParentUUID()]; } @@ -4055,6 +4126,7 @@ void LLInventoryModel::FetchItemHttpHandler::httpSuccess(void) { ++update[titem->getParentUUID()]; } + if (folder_id.isNull()) { folder_id = titem->getParentUUID(); @@ -4063,9 +4135,9 @@ void LLInventoryModel::FetchItemHttpHandler::httpSuccess(void) // as above, this loop never seems to loop more than once per call U32 changes(0U); - for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it) + for (auto& item : items) { - changes |= gInventory.updateItem(*it); + changes |= gInventory.updateItem(item); } // *HUH: Have computed 'changes', nothing uses it. @@ -4073,9 +4145,10 @@ void LLInventoryModel::FetchItemHttpHandler::httpSuccess(void) gViewerWindow->getWindow()->decBusyCount(); } //If we get back an error (not found, etc...), handle it here -void LLInventoryModel::FetchItemHttpHandler::httpFailure(void) +void LLInventoryModel::FetchItemHttpHandler::httpFailure() { - LL_INFOS() << "FetchItemHttpHandler::error " + LL_WARNS(LOG_INV) << "FetchItemHttpHandler::error " << mStatus << ": " << mReason << LL_ENDL; gInventory.notifyObservers(); } + diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index b9187ef6fe..d81fe7b97e 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -27,7 +27,7 @@ #ifndef LL_LLINVENTORYMODEL_H #define LL_LLINVENTORYMODEL_H -#include +#include #include #include #include @@ -76,7 +76,7 @@ class LLInventoryModel typedef std::vector > cat_array_t; typedef std::vector > item_array_t; - typedef std::set changed_items_t; + typedef uuid_set_t changed_items_t; class FetchItemHttpHandler : public LLHTTPClient::ResponderWithResult { @@ -154,13 +154,13 @@ class LLInventoryModel // the inventory using several different identifiers. // mInventory member data is the 'master' list of inventory, and // mCategoryMap and mItemMap store uuid->object mappings. - typedef std::map > cat_map_t; - typedef std::map > item_map_t; + typedef boost::unordered_map > cat_map_t; + typedef boost::unordered_map > item_map_t; cat_map_t mCategoryMap; item_map_t mItemMap; // This last set of indices is used to map parents to children. - typedef std::map parent_cat_map_t; - typedef std::map parent_item_map_t; + typedef boost::unordered_map parent_cat_map_t; + typedef boost::unordered_map parent_item_map_t; parent_cat_map_t mParentChildCategoryTree; parent_item_map_t mParentChildItemTree; @@ -192,14 +192,14 @@ class LLInventoryModel **/ //-------------------------------------------------------------------- - // Descendents + // Descendants //-------------------------------------------------------------------- public: - // Make sure we have the descendents in the structure. Returns true + // Make sure we have the descendants in the structure. Returns true // if a fetch was performed. bool fetchDescendentsOf(const LLUUID& folder_id) const; - // Return the direct descendents of the id provided.Set passed + // Return the direct descendants of the id provided.Set passed // in values to NULL if the call fails. // NOTE: The array provided points straight into the guts of // this object, and should only be used for read operations, since @@ -211,10 +211,10 @@ class LLInventoryModel void getDirectDescendentsOf(const LLUUID& cat_id, cat_array_t*& categories) const; - // Compute a hash of direct descendent names (for detecting child name changes) + // Compute a hash of direct descendant names (for detecting child name changes) LLMD5 hashDirectDescendentNames(const LLUUID& cat_id) const; - // Starting with the object specified, add its descendents to the + // Starting with the object specified, add its descendants to the // array provided, but do not add the inventory object specified // by id. There is no guaranteed order. // NOTE: Neither array will be erased before adding objects to it. @@ -340,7 +340,7 @@ class LLInventoryModel U32 updateItem(const LLViewerInventoryItem* item, U32 mask = 0); // Change an existing item with the matching id or add - // the category. No notifcation will be sent to observers. This + // the category. No notification will be sent to observers. This // method will only generate network traffic if the item had to be // reparented. // NOTE: In usage, you will want to perform cache accounting @@ -378,7 +378,7 @@ class LLInventoryModel bool update_parent_version = true, bool do_notify_observers = true); - // Update model after all descendents removed from server. + // Update model after all descendants removed from server. void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true); // Update model after an existing item gets updated on server. @@ -418,15 +418,6 @@ class LLInventoryModel // Returns end() of the vector if not found. static LLInventoryModel::item_array_t::iterator findItemIterByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id); - // Saves current order of the passed items using inventory item sort field. - // Resets 'items' sort fields and saves them on server. - // Is used to save order for Favorites folder. - //void saveItemsOrder(const LLInventoryModel::item_array_t& items); - - // Rearranges Landmarks inside Favorites folder. - // Moves source landmark before target one. - void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); - //-------------------------------------------------------------------- // Creation //-------------------------------------------------------------------- @@ -476,7 +467,7 @@ class LLInventoryModel LLInitializedS32& operator++() { ++mValue; return *this; } LLInitializedS32& operator--() { --mValue; return *this; } }; - typedef std::map update_map_t; + typedef boost::unordered_map update_map_t; // Call when there are category updates. Call them *before* the // actual update so the method can do descendent accounting correctly. @@ -508,10 +499,12 @@ class LLInventoryModel // Call to explicitly update everyone on a new state. void notifyObservers(); + // Allows outsiders to tell the inventory if something has // been changed 'under the hood', but outside the control of the // inventory. The next notify will include that notification. void addChangedMask(U32 mask, const LLUUID& referent); + const changed_items_t& getChangedIDs() const { return mChangedItemIDs; } const changed_items_t& getAddedIDs() const { return mAddedItemIDs; } protected: @@ -565,6 +558,7 @@ class LLInventoryModel static bool loadFromFile(const std::string& filename, cat_array_t& categories, item_array_t& items, + changed_items_t& cats_to_update, bool& is_cache_obsolete); static bool saveToFile(const std::string& filename, const cat_array_t& categories, @@ -601,8 +595,8 @@ class LLInventoryModel cat_array_t* getUnlockedCatArray(const LLUUID& id); item_array_t* getUnlockedItemArray(const LLUUID& id); private: - std::map mCategoryLock; - std::map mItemLock; + boost::unordered_map mCategoryLock; + boost::unordered_map mItemLock; //-------------------------------------------------------------------- // Debugging diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 88bbaed3d5..e3060d226d 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -876,12 +876,9 @@ void BGFolderHttpHandler::httpFailure(void) if (is_internal_http_error_that_warrants_a_retry(mStatus)) // timed out { - for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray(); - folder_it != mRequestSD["folders"].endArray(); - ++folder_it) + for (auto const& entry : mRequestSD["folders"].array()) { - LLSD folder_sd(*folder_it); - LLUUID folder_id(folder_sd["folder_id"].asUUID()); + LLUUID folder_id(entry["folder_id"].asUUID()); const BOOL recursive = getIsRecursive(folder_id); fetcher->addRequestAtFront(folder_id, recursive, true); } diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index c9c91de856..b1b9858cf4 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -589,7 +589,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask) if (!mCategoryMap.size()) return; - std::vector deleted_categories_ids; + uuid_vec_t deleted_categories_ids; for (category_map_t::iterator iter = mCategoryMap.begin(); iter != mCategoryMap.end(); @@ -665,7 +665,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask) } // Remove deleed categories from the list - for (std::vector::iterator deleted_id = deleted_categories_ids.begin(); deleted_id != deleted_categories_ids.end(); ++deleted_id) + for (auto deleted_id = deleted_categories_ids.begin(); deleted_id != deleted_categories_ids.end(); ++deleted_id) { removeCategory(*deleted_id); } diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index baa245788a..afc4bebd09 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -30,6 +30,7 @@ #include "lluuid.h" #include "llmd5.h" #include +#include #include class LLViewerInventoryCategory; @@ -177,7 +178,7 @@ class LLInventoryAddItemByAssetObserver : public LLInventoryObserver virtual void onAssetAdded(const LLUUID& asset_id) {} virtual void done() = 0; - typedef std::vector item_ref_t; + typedef uuid_vec_t item_ref_t; item_ref_t mAddedItems; item_ref_t mWatchedAssets; @@ -256,7 +257,7 @@ class LLInventoryCompletionObserver : public LLInventoryObserver class LLInventoryCategoriesObserver : public LLInventoryObserver { public: - typedef boost::function callback_t; + typedef std::function callback_t; LLInventoryCategoriesObserver() {}; virtual void changed(U32 mask); @@ -284,7 +285,7 @@ class LLInventoryCategoriesObserver : public LLInventoryObserver LLUUID mCatID; }; - typedef std::map category_map_t; + typedef boost::unordered_map category_map_t; typedef category_map_t::value_type category_map_value_t; category_map_t mCategoryMap; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 4fbcb778e2..4cb2bf65fd 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -37,6 +37,7 @@ #include "llfolderview.h" #include "llimview.h" #include "llinventorybridge.h" +#include "llinventoryfilter.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" #include "llviewerfoldertype.h" @@ -44,7 +45,6 @@ #include "llscrollcontainer.h" #include "llviewerassettype.h" #include "llpanelmaininventory.h" -#include "llpanelmarketplaceoutboxinventory.h" #include "llsdserialize.h" @@ -58,7 +58,7 @@ const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventoryS const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder"); const std::string LLInventoryPanel::WORNITEMS_SORT_ORDER = std::string("WornItemsSortOrder"); const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); -static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; +static const LLInventoryFolderViewModelBuilder INVENTORY_BRIDGE_BUILDER; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -72,7 +72,8 @@ class LLInventoryPanelObserver : public LLInventoryObserver public: LLInventoryPanelObserver(LLInventoryPanel* ip) : mIP(ip) {} virtual ~LLInventoryPanelObserver() {} - virtual void changed(U32 mask) + + void changed(U32 mask) override { mIP->modelChanged(mask); } @@ -80,12 +81,6 @@ class LLInventoryPanelObserver : public LLInventoryObserver LLInventoryPanel* mIP; }; - - - - - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInvPanelComplObserver // @@ -102,7 +97,7 @@ class LLInventoryPanelObserver : public LLInventoryObserver class LLInvPanelComplObserver : public LLInventoryCompletionObserver { public: - typedef boost::function callback_t; + typedef std::function callback_t; LLInvPanelComplObserver(callback_t cb) : mCallback(cb) @@ -112,7 +107,7 @@ class LLInvPanelComplObserver : public LLInventoryCompletionObserver void reset(); private: - /*virtual*/ void done(); + /*virtual*/ void done() override; /// Called when all the items are complete. callback_t mCallback; @@ -129,9 +124,13 @@ void LLInvPanelComplObserver::done() mCallback(); } +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryPanel +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + LLInventoryPanel::LLInventoryPanel(const std::string& name, const std::string& sort_order_setting, - const std::string& start_folder, + const LLSD& start_folder, const LLRect& rect, LLInventoryModel* inventory, BOOL allow_multi_select, @@ -142,6 +141,12 @@ LLInventoryPanel::LLInventoryPanel(const std::string& name, mScroller(NULL), mSortOrderSetting(sort_order_setting), mStartFolder(start_folder), + mShowRootFolder(false), + mShowEmptyMessage(true), + //mShowItemLinkOverlays(false), + mAllowDropOnRoot(true), + mAllowWear(true), + mUseMarketplaceFolders(false), mInventory(inventory), mAllowMultiSelect(allow_multi_select), mViewsInitialized(false), @@ -159,33 +164,12 @@ void LLInventoryPanel::buildFolderView() { // Determine the root folder in case specified, and // build the views starting with that folder. - - //std::string start_folder_name(params.start_folder()); - - const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolder); - - LLUUID root_id; - - if ("LIBRARY" == mStartFolder) - { - root_id = gInventory.getLibraryRootFolderID(); - } - else - { - root_id = (preferred_type != LLFolderType::FT_NONE) - ? gInventory.findCategoryUUIDForType(preferred_type, false) - : gInventory.getCategory(static_cast(mStartFolder)) ? static_cast(mStartFolder) // Singu Note: if start folder is an id of a folder, use it - : LLUUID::null; - } - - if ((root_id == LLUUID::null) && !mStartFolder.empty()) - { - LL_WARNS() << "No category found that matches start_folder: " << mStartFolder << LL_ENDL; - root_id = LLUUID::generateNewID(); - } + LLUUID root_id = getRootFolderID(); + if (!mStartFolder.has("id")) + mStartFolder["id"] = root_id; // Cache this, so we don't waste time on future getRootFolderID calls LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, - LLAssetType::AT_CATEGORY, + (mUseMarketplaceFolders/*mParams.use_marketplace_folders*/ ? LLAssetType::AT_MARKETPLACE_FOLDER : LLAssetType::AT_CATEGORY), LLInventoryType::IT_CATEGORY, this, NULL, @@ -193,6 +177,8 @@ void LLInventoryPanel::buildFolderView() LLFolderView* folder_view = createFolderView(new_listener, true/*params.use_label_suffix()*/); mFolderRoot = folder_view->getHandle(); + + addItemID(root_id, mFolderRoot.get()); } BOOL LLInventoryPanel::postBuild() { @@ -225,6 +211,7 @@ BOOL LLInventoryPanel::postBuild() { initializeViews(); } + gIdleCallbacks.addFunction(onIdle, (void*)this); if (mSortOrderSetting != INHERIT_SORT_ORDER) @@ -235,7 +222,25 @@ BOOL LLInventoryPanel::postBuild() { setSortOrder(gSavedSettings.getU32(DEFAULT_SORT_ORDER)); } - getFilter()->setFilterEmptySystemFolders(); + + // hide inbox + if (!gSavedSettings.getBOOL("InventoryOutboxMakeVisible")) + { + //getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); // Singu Nope! + getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX)); + } + // hide marketplace listing box, unless we are a marketplace panel + if (!gSavedSettings.getBOOL("InventoryOutboxMakeVisible") && !mUseMarketplaceFolders/*mParams.use_marketplace_folders*/) + { + getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_MARKETPLACE_LISTINGS)); + } + + // set the filter for the empty folder if the debug setting is on + if (gSavedSettings.getBOOL("DebugHideEmptySystemFolders")) + { + getFilter().setFilterEmptySystemFolders(); + } + return LLPanel::postBuild(); } @@ -296,7 +301,7 @@ class LLInventoryRecentItemsPanel : public LLInventoryPanel public: LLInventoryRecentItemsPanel(const std::string& name, const std::string& sort_order_setting, - const std::string& start_folder, + const LLSD& start_folder, const LLRect& rect, LLInventoryModel* inventory, BOOL allow_multi_select, @@ -306,6 +311,14 @@ class LLInventoryRecentItemsPanel : public LLInventoryPanel LLView* LLInventoryPanel::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) { + std::string filename; + if (node->getAttributeString("filename", filename) && !filename.empty()) + { + LLXMLNodePtr node; + if (LLUICtrlFactory::getLayeredXMLNode(filename, node)) + return factory->createCtrlWidget(static_cast(parent), node); + } + LLInventoryPanel* panel; std::string name("inventory_panel"); @@ -320,22 +333,32 @@ LLView* LLInventoryPanel::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac std::string sort_order(INHERIT_SORT_ORDER); node->getAttributeString("sort_order", sort_order); - std::string start_folder; - node->getAttributeString("start_folder", start_folder); + LLSD start_folder; + std::string start; + if (node->getAttributeString("start_folder.name", start)) + start_folder["name"] = start; + if (node->getAttributeString("start_folder.id", start)) + start_folder["id"] = LLUUID(start); + if (node->getAttributeString("start_folder.type", start)) + start_folder["type"] = start; - if(name == "Recent Items") + if (name == "Recent Items") panel = new LLInventoryRecentItemsPanel(name, sort_order, start_folder, rect, &gInventory, allow_multi_select, parent); - else if(name == "panel_outbox_inventory") - panel = new LLOutboxInventoryPanel(name, sort_order, start_folder, - rect, &gInventory, - allow_multi_select, parent); else panel = new LLInventoryPanel(name, sort_order, start_folder, rect, &gInventory, allow_multi_select, parent); + // Singu TODO: Turn these into mParams like upstream. + node->getAttribute_bool("show_root_folder", panel->mShowRootFolder); + node->getAttribute_bool("show_empty_message", panel->mShowEmptyMessage); + //node->getAttribute_bool("show_item_link_overlays", panel->mShowItemLinkOverlays); + node->getAttribute_bool("allow_drop_on_root", panel->mAllowDropOnRoot); + node->getAttribute_bool("allow_wear", panel->mAllowWear); + node->getAttribute_bool("use_marketplace_folders", panel->mUseMarketplaceFolders); + panel->initFromXML(node, parent); panel->postBuild(); @@ -346,77 +369,102 @@ LLView* LLInventoryPanel::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac void LLInventoryPanel::draw() { // Select the desired item (in case it wasn't loaded when the selection was requested) - mFolderRoot.get()->updateSelection(); + updateSelection(); + LLPanel::draw(); } -LLInventoryFilter* LLInventoryPanel::getFilter() +LLInventoryFilter& LLInventoryPanel::getFilter() { - if (mFolderRoot.get()) - { - return mFolderRoot.get()->getFilter(); - } - return NULL; + return mFolderRoot.get()->getFilter(); } -const LLInventoryFilter* LLInventoryPanel::getFilter() const +const LLInventoryFilter& LLInventoryPanel::getFilter() const { - if (mFolderRoot.get()) - { - return mFolderRoot.get()->getFilter(); - } - return NULL; + return mFolderRoot.get()->getFilter(); } void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type) { if (filter_type == LLInventoryFilter::FILTERTYPE_OBJECT) - getFilter()->setFilterObjectTypes(types); + { + getFilter().setFilterObjectTypes(types); + } if (filter_type == LLInventoryFilter::FILTERTYPE_CATEGORY) - getFilter()->setFilterCategoryTypes(types); + getFilter().setFilterCategoryTypes(types); } U32 LLInventoryPanel::getFilterObjectTypes() const { - return mFolderRoot.get()->getFilterObjectTypes(); + return getFilter().getFilterObjectTypes(); } U32 LLInventoryPanel::getFilterPermMask() const { - return mFolderRoot.get()->getFilterPermissions(); + return getFilter().getFilterPermissions(); } void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask) { - getFilter()->setFilterPermissions(filter_perm_mask); + getFilter().setFilterPermissions(filter_perm_mask); } void LLInventoryPanel::setFilterWearableTypes(U64 types) { - getFilter()->setFilterWearableTypes(types); + getFilter().setFilterWearableTypes(types); } -void LLInventoryPanel::setFilterWorn(bool worn) +void LLInventoryPanel::setFilterWornItems() { - getFilter()->setFilterWorn(worn); + getFilter().setFilterWornItems(); } void LLInventoryPanel::setFilterSubString(const std::string& string) { - getFilter()->setFilterSubString(string); + if (!getRootFolder()) + return; + + std::string uppercase_search_string = string; + LLStringUtil::toUpper(uppercase_search_string); + const std::string prior_search_string = getFilterSubString(); + + if (prior_search_string == uppercase_search_string) + { + // current filter and new filter match, do nothing + return; + } + + if (string.empty()) + { + // Unlike v3, do not clear other filters. Text is independent. + getFilter().setFilterSubString(LLStringUtil::null); + getRootFolder()->restoreFolderState(); + LLOpenFoldersWithSelection opener; + getRootFolder()->applyFunctorRecursively(opener); + getRootFolder()->scrollToShowSelection(); + } + else + { + if (prior_search_string.empty()) + { + // save current folder open state if no filter currently applied + getRootFolder()->saveFolderState(); + } + // set new filter string + getFilter().setFilterSubString(string); + } } const std::string LLInventoryPanel::getFilterSubString() { - return mFolderRoot.get()->getFilterSubString(); + return getFilter().getFilterSubString(); } - void LLInventoryPanel::setSortOrder(U32 order) { - getFilter()->setSortOrder(order); - if (getFilter()->isModified()) + getFilter().setSortOrder(order); + if (getFilter().isModified()) { mFolderRoot.get()->setSortOrder(order); // try to keep selection onscreen, even if it wasn't to start with @@ -436,33 +484,39 @@ void LLInventoryPanel::requestSort() void LLInventoryPanel::setSinceLogoff(BOOL sl) { - getFilter()->setDateRangeLastLogoff(sl); + getFilter().setDateRangeLastLogoff(sl); } void LLInventoryPanel::setHoursAgo(U32 hours) { - getFilter()->setHoursAgo(hours); + getFilter().setHoursAgo(hours); +} + +void LLInventoryPanel::setDateSearchDirection(U32 direction) +{ + getFilter().setDateSearchDirection(direction); } -void LLInventoryPanel::setFilterLinks(U64 filter_links) +void LLInventoryPanel::setFilterLinks(LLInventoryFilter::EFilterLink filter_links) { - getFilter()->setFilterLinks(filter_links); + getFilter().setFilterLinks(filter_links); } void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show) { - getFilter()->setShowFolderState(show); + getFilter().setShowFolderState(show); } LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState() { - return getFilter()->getShowFolderState(); + return getFilter().getShowFolderState(); } +// Called when something changed in the global model (new item, item coming through the wire, rename, move, etc...) (CHUI-849) void LLInventoryPanel::modelChanged(U32 mask) { - static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh"); - LLFastTimer t2(FTM_REFRESH); + static LLTrace::BlockTimerStatHandle FTM_REFRESH("Inventory Refresh"); + LL_RECORD_BLOCK_TIME(FTM_REFRESH); if (!mViewsInitialized) return; @@ -478,11 +532,18 @@ void LLInventoryPanel::modelChanged(U32 mask) { const LLUUID& item_id = (*items_iter); const LLInventoryObject* model_item = model->getObject(item_id); - LLFolderViewItem* view_item = mFolderRoot.get()->getItemByID(item_id); + LLFolderViewItem* view_item = getItemByID(item_id); // LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item // to folder is the fast way to get a folder without searching through folders tree. - LLFolderViewFolder* view_folder = dynamic_cast(view_item); + LLFolderViewFolder* view_folder = NULL; + + // Check requires as this item might have already been deleted + // as a child of its deleted parent. + if (model_item && view_item) + { + view_folder = dynamic_cast(view_item); + } ////////////////////////////// // LABEL Operation @@ -501,6 +562,11 @@ void LLInventoryPanel::modelChanged(U32 mask) } // Singu note: Needed to propagate name change to wearables. view_item->nameOrDescriptionChanged(); + LLFolderViewFolder* parent = view_item->getParentFolder(); + if(parent) + { + parent->requestSort(); + } } } @@ -522,7 +588,9 @@ void LLInventoryPanel::modelChanged(U32 mask) { if (model_item && view_item) { + const LLUUID& idp = view_item->getListener()->getUUID(); view_item->destroyView(); + removeItemID(idp); } view_item = buildNewViews(item_id); view_folder = dynamic_cast(view_item); @@ -566,11 +634,13 @@ void LLInventoryPanel::modelChanged(U32 mask) { // Add the UI element for this item. buildNewViews(item_id); + if (auto parent = getFolderByID(model_item->getParentUUID())) parent->requestSort(); // Select any newly created object that has the auto rename at top of folder root set. if(mFolderRoot.get()->getRoot()->needsAutoRename()) { setSelection(item_id, FALSE); } + //updateFolderLabel(model_item->getParentUUID()); } ////////////////////////////// @@ -578,18 +648,21 @@ void LLInventoryPanel::modelChanged(U32 mask) // This item already exists in both memory and UI. It was probably reparented. else if (model_item && view_item) { + LLFolderViewFolder* old_parent = view_item->getParentFolder(); // Don't process the item if it is the root if (view_item->getRoot() != view_item) { - LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolderRoot.get()->getItemByID(model_item->getParentUUID()); + //auto* viewmodel_folder = old_parent->getListener(); + LLFolderViewFolder* new_parent = (LLFolderViewFolder*)getItemByID(model_item->getParentUUID()); // Item has been moved. - if (view_item->getParentFolder() != new_parent) + if (old_parent != new_parent) { if (new_parent != NULL) { // Item is to be moved and we found its new parent in the panel's directory, so move the item's UI. view_item->getParentFolder()->extractItem(view_item); view_item->addToFolder(new_parent, mFolderRoot.get()); + addItemID(view_item->getListener()->getUUID(), view_item); if (mInventory) { const LLUUID trash_id = mInventory->findCategoryUUIDForType(LLFolderType::FT_TRASH); @@ -598,13 +671,23 @@ void LLInventoryPanel::modelChanged(U32 mask) setSelection(item_id, FALSE); } } + //updateFolderLabel(model_item->getParentUUID()); } else { + // Remove the item ID before destroying the view because the view-model-item gets + // destroyed when the view is destroyed + removeItemID(view_item->getListener()->getUUID()); + // Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that // doesn't include trash). Just remove the item's UI. view_item->destroyView(); } + /*if(viewmodel_folder) + { + updateFolderLabel(viewmodel_folder->getUUID()); + }*/ + old_parent->requestSort(); } } } @@ -615,10 +698,61 @@ void LLInventoryPanel::modelChanged(U32 mask) else if (!model_item && view_item) { // Remove the item's UI. + LLFolderViewFolder* parent = view_item->getParentFolder(); + removeItemID(view_item->getListener()->getUUID()); view_item->destroyView(); + if(parent) + { + parent->requestSort(); + /*auto* viewmodel_folder = parent->getListener(); + if(viewmodel_folder) + { + updateFolderLabel(viewmodel_folder->getUUID()); + }*/ + } + } + } + } +} + +const LLUUID LLInventoryPanel::getRootFolderID() const +{ + LLUUID root_id; + if (mFolderRoot.get() && mFolderRoot.get()->getListener()) + { + root_id = mFolderRoot.get()->getListener()->getUUID(); + } + else + { + if (mStartFolder.has("id")) + { + root_id = mStartFolder["id"]; + } + else + { + LLStringExplicit label(mStartFolder["name"]); + const LLFolderType::EType preferred_type = mStartFolder.has("type") + ? LLFolderType::lookup(mStartFolder["type"]) + : LLViewerFolderType::lookupTypeFromNewCategoryName(label); + + if ("LIBRARY" == label) + { + root_id = gInventory.getLibraryRootFolderID(); + } + else if (preferred_type != LLFolderType::FT_NONE) + { + //setLabel(label); + + root_id = gInventory.findCategoryUUIDForType(preferred_type, false); + if (root_id.isNull()) + { + LL_WARNS() << "Could not find folder for " << mStartFolder << LL_ENDL; + root_id.generateNewID(); + } } } } + return root_id; } // static @@ -639,10 +773,7 @@ void LLInventoryPanel::onIdle(void *userdata) } } -const LLUUID& LLInventoryPanel::getRootFolderID() const -{ - return mFolderRoot.get()->getListener()->getUUID(); -} + void LLInventoryPanel::initializeViews() { @@ -658,14 +789,14 @@ void LLInventoryPanel::initializeViews() if (gAgent.isFirstLogin()) { // Auto open the user's library - LLFolderViewFolder* lib_folder = mFolderRoot.get()->getFolderByID(gInventory.getLibraryRootFolderID()); + LLFolderViewFolder* lib_folder = getFolderByID(gInventory.getLibraryRootFolderID()); if (lib_folder) { lib_folder->setOpen(TRUE); } // Auto close the user's my inventory folder - LLFolderViewFolder* my_inv_folder = mFolderRoot.get()->getFolderByID(gInventory.getRootFolderID()); + LLFolderViewFolder* my_inv_folder = getFolderByID(gInventory.getRootFolderID()); if (my_inv_folder) { my_inv_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); @@ -699,10 +830,13 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u bridge, mGroupedItemBridge); ret->setAllowMultiSelect(mAllowMultiSelect); + ret->setShowEmptyMessage(mShowEmptyMessage); + /*ret->setShowItemLinkOverlays(mShowItemLinkOverlays); + ret->setAllowDropOnRoot(mAllowDropOnRoot);*/ return ret; } -LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge) +LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge* bridge) { return new LLFolderViewFolder( bridge->getDisplayName(), @@ -727,80 +861,106 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) { - LLInventoryObject const* objectp = gInventory.getObject(id); - LLUUID root_id = mFolderRoot.get()->getListener()->getUUID(); - LLFolderViewFolder* parent_folder = NULL; - LLFolderViewItem* itemp = NULL; - - if (id == root_id) - { - parent_folder = mFolderRoot.get(); - } - else if (objectp) - { - const LLUUID &parent_id = objectp->getParentUUID(); - parent_folder = (LLFolderViewFolder*)mFolderRoot.get()->getItemByID(parent_id); - - if (parent_folder) - { - if (objectp->getType() <= LLAssetType::AT_NONE || - objectp->getType() >= LLAssetType::AT_COUNT) - { - LL_WARNS() << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " - << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() - << LL_ENDL; - return NULL; - } - - if ((objectp->getType() == LLAssetType::AT_CATEGORY) && - (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) + LLInventoryObject const* objectp = gInventory.getObject(id); + LLFolderViewFolder* parent_folder = mFolderRoot.get(); + LLUUID root_id = parent_folder->getListener()->getUUID(); + LLFolderViewItem* folder_view_item = nullptr; + + if (id != root_id && !objectp) + { + return NULL; + } + + if (objectp) + { + folder_view_item = getItemByID(id); + + const LLUUID& parent_id = objectp->getParentUUID(); + parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); + + // Force the creation of an extra root level folder item if required by the inventory panel (default is "false") + bool allow_drop = true; + bool create_root = false; + if (mShowRootFolder) + { + LLUUID root_id = getRootFolderID(); + if (root_id == id) + { + // We insert an extra level that's seen by the UI but has no influence on the model + parent_folder = dynamic_cast(folder_view_item); + folder_view_item = NULL; + allow_drop = mAllowDropOnRoot; + create_root = true; + } + } + + if (!folder_view_item && parent_folder) + { + if (objectp->getType() <= LLAssetType::AT_NONE || + objectp->getType() >= LLAssetType::AT_COUNT) + { + LL_WARNS() << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " + << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() + << LL_ENDL; + return NULL; + } + + if ((objectp->getType() == LLAssetType::AT_CATEGORY) && + (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) + { + LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, + (mUseMarketplaceFolders ? LLAssetType::AT_MARKETPLACE_FOLDER : LLAssetType::AT_CATEGORY), + LLInventoryType::IT_CATEGORY, + this, + mFolderRoot.get(), + objectp->getUUID()); + if (new_listener) { - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), - objectp->getType(), - LLInventoryType::IT_CATEGORY, - this, - mFolderRoot.get(), - objectp->getUUID()); - if (new_listener) - { - LLFolderViewFolder* folderp = createFolderViewFolder(new_listener); - if (folderp) - { - folderp->setItemSortOrder(mFolderRoot.get()->getSortOrder()); - } - itemp = folderp; - } - } - else - { - // Build new view for item. - LLInventoryItem* item = (LLInventoryItem*)objectp; - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), - item->getActualType(), - item->getInventoryType(), - this, - mFolderRoot.get(), - item->getUUID(), - item->getFlags()); - - if (new_listener) - { - itemp = createFolderViewItem(new_listener); - } - } - - if (itemp) - { - itemp->addToFolder(parent_folder, mFolderRoot.get()); - } + folder_view_item = createFolderViewFolder(new_listener); + if (folder_view_item) + { + static_cast(folder_view_item)->setItemSortOrder(mFolderRoot.get()->getSortOrder()); + folder_view_item->setAllowDrop(allow_drop); + folder_view_item->setAllowWear(mAllowWear); + } + } + } + else + { + // Build new view for item. + LLInventoryItem* item = (LLInventoryItem*)objectp; + LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), + item->getActualType(), + item->getInventoryType(), + this, + mFolderRoot.get(), + item->getUUID(), + item->getFlags()); + + if (new_listener) + { + folder_view_item = createFolderViewItem(new_listener); + } + } + + if (folder_view_item) + { + llassert(parent_folder != NULL); + folder_view_item->addToFolder(parent_folder, mFolderRoot.get()); + addItemID(id, folder_view_item); + // In the case of the root folder been shown, open that folder by default once the widget is created + if (create_root) + { + folder_view_item->setOpen(TRUE); + } } } + } // If this is a folder, add the children of the folder and recursively add any // child folders. if (id.isNull() - || (objectp - && objectp->getType() == LLAssetType::AT_CATEGORY)) + || (folder_view_item && objectp->getType() == LLAssetType::AT_CATEGORY)) { LLViewerInventoryCategory::cat_array_t* categories; LLViewerInventoryItem::item_array_t* items; @@ -817,7 +977,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) } } - if(items && parent_folder) + if(items) { for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin(); item_iter != items->end(); @@ -830,7 +990,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) mInventory->unlockDirectDescendentArrays(id); } - return itemp; + return folder_view_item; } // bit of a hack to make sure the inventory is open. @@ -850,24 +1010,6 @@ void LLInventoryPanel::openStartFolderOrMyInventory() } } -struct LLConfirmPurgeData -{ - LLUUID mID; - LLInventoryModel* mModel; -}; - -class LLIsNotWorn : public LLInventoryCollectFunctor -{ -public: - LLIsNotWorn() {} - virtual ~LLIsNotWorn() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item) - { - return !gAgentWearables.isWearingItem(item->getUUID()); - } -}; - class LLOpenFolderByID : public LLFolderViewFunctor { public: @@ -907,7 +1049,8 @@ BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask) BOOL handled = LLView::handleHover(x, y, mask); if(handled) { - if (LLInventoryModelBackgroundFetch::instance().folderFetchActive()) + ECursorType cursor = getWindow()->getCursor(); + if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() && cursor == UI_CURSOR_ARROW) { // replace arrow cursor with arrow and hourglass cursor getWindow()->setCursor(UI_CURSOR_WORKING); @@ -935,7 +1078,7 @@ BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // If folder view is empty the (x, y) point won't be in its rect // so the handler must be called explicitly. // but only if was not handled before. See EXT-6746. - if (!handled && !mFolderRoot.get()->hasVisibleChildren()) + if (!handled && mAllowDropOnRoot && !mFolderRoot.get()->hasVisibleChildren()) { handled = mFolderRoot.get()->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); } @@ -995,10 +1138,10 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc { return; } - mFolderRoot.get()->setSelectionByID(obj_id, take_keyboard_focus); + setSelectionByID(obj_id, take_keyboard_focus); } -void LLInventoryPanel::setSelectCallback(const boost::function& items, BOOL user_action)>& cb) +void LLInventoryPanel::setSelectCallback(const std::function& items, BOOL user_action)>& cb) { if (mFolderRoot.get()) { @@ -1009,6 +1152,7 @@ void LLInventoryPanel::setSelectCallback(const boost::functionclearSelection(); + mSelectThisID.setNull(); } void LLInventoryPanel::onSelectionChange(const std::deque& items, BOOL user_action) @@ -1026,7 +1170,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque& it } } - LLFolderView* fv = getRootFolder(); + LLFolderView* fv = mFolderRoot.get(); if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename { fv->setNeedsAutoRename(FALSE); @@ -1067,7 +1211,7 @@ void LLInventoryPanel::createNewItem(const std::string& name, BOOL LLInventoryPanel::getSinceLogoff() { - return getFilter()->isSinceLogoff(); + return getFilter().isSinceLogoff(); } // DEBUG ONLY @@ -1081,7 +1225,7 @@ void LLInventoryPanel::dumpSelectionInformation(void* user_data) LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) { LLInventoryPanel* res = NULL; - LLInventoryView* floater_inventory = LLInventoryView::getActiveInventory(); + LLPanelMainInventory* floater_inventory = LLPanelMainInventory::getActiveInventory(); if (!floater_inventory) { LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL; @@ -1102,18 +1246,169 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) res = floater_inventory->getActivePanel(); } + return res; } void LLInventoryPanel::addHideFolderType(LLFolderType::EType folder_type) { - getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << folder_type)); + getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << folder_type)); } BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) const { - return !(getFilter()->getFilterCategoryTypes() & (1ULL << folder_type)); + return !(getFilter().getFilterCategoryTypes() & (1ULL << folder_type)); +} + +void LLInventoryPanel::addItemID( const LLUUID& id, LLFolderViewItem* itemp ) +{ + mItemMap[id] = itemp; +} + +void LLInventoryPanel::removeItemID(const LLUUID& id) +{ + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(id, categories, items, TRUE); + + mItemMap.erase(id); + + for (LLInventoryModel::cat_array_t::iterator it = categories.begin(), end_it = categories.end(); + it != end_it; + ++it) + { + mItemMap.erase((*it)->getUUID()); +} + + for (LLInventoryModel::item_array_t::iterator it = items.begin(), end_it = items.end(); + it != end_it; + ++it) + { + mItemMap.erase((*it)->getUUID()); + } +} + +//static LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); +LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id) +{ + return mFolderRoot.get()->getItemByID(id); + /* + LLFastTimer mew(FTM_GET_ITEM_BY_ID); + + std::map::iterator map_it; + map_it = mItemMap.find(id); + if (map_it != mItemMap.end()) + { + return map_it->second; + } + + return NULL;*/ +} + +LLFolderViewFolder* LLInventoryPanel::getFolderByID(const LLUUID& id) +{ + return mFolderRoot.get()->getFolderByID(id); +/* + LLFolderViewItem* item = getItemByID(id); + return dynamic_cast(item); +*/ +} + + +void LLInventoryPanel::setSelectionByID( const LLUUID& obj_id, BOOL take_keyboard_focus ) +{ + mFolderRoot.get()->setSelectionByID(obj_id, take_keyboard_focus); + /* + LLFolderViewItem* itemp = getItemByID(obj_id); + if(itemp && itemp->getListener()) + { + itemp->arrangeAndSet(TRUE, take_keyboard_focus); + mSelectThisID.setNull(); + return; + } + else + { + // save the desired item to be selected later (if/when ready) + mSelectThisID = obj_id; + }*/ +} + +void LLInventoryPanel::updateSelection() +{ + mFolderRoot.get()->updateSelection(); +/* + if (mSelectThisID.notNull()) + { + setSelectionByID(mSelectThisID, false); + } +*/ +} + +namespace LLInventoryAction +{ + bool doToSelected(LLFolderView* root, std::string action, BOOL user_confirm = TRUE); +} + +void LLInventoryPanel::doToSelected(const LLSD& userdata) +{ + LLInventoryAction::doToSelected(mFolderRoot.get(), userdata.asString()); + + return; +} + +BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask ) +{ + /* + BOOL handled = FALSE; + switch (key) + { + case KEY_RETURN: + // Open selected items if enter key hit on the inventory panel + if (mask == MASK_NONE) + { + LLInventoryAction::doToSelected(mFolderRoot.get(), "open"); + handled = TRUE; + } + break; + case KEY_DELETE: + case KEY_BACKSPACE: + // Delete selected items if delete or backspace key hit on the inventory panel + // Note: on Mac laptop keyboards, backspace and delete are one and the same + if (isSelectionRemovable() && (mask == MASK_NONE)) + { + LLInventoryAction::doToSelected(mFolderRoot.get(), "delete"); + handled = TRUE; + } + break; + }*/ + return LLPanel::handleKeyHere(key, mask); } +bool LLInventoryPanel::isSelectionRemovable() +{ + bool can_delete = false; + if (mFolderRoot.get()) + { + auto selection_set = mFolderRoot.get()->getSelectionList(); + if (!selection_set.empty()) + { + can_delete = true; + for (const auto& id : selection_set) + { + LLFolderViewItem *item = getItemByID(id); + const LLFolderViewEventListener* listener =item->getListener(); + if (!listener) + { + can_delete = false; + } + else + { + can_delete &= listener->isItemRemovable() && !listener->isItemInTrash(); + } + } + } + } + return can_delete; +} /************************************************************************/ /* Recent Inventory Panel related class */ @@ -1124,13 +1419,14 @@ static const LLRecentInventoryBridgeBuilder RECENT_ITEMS_BUILDER; LLInventoryRecentItemsPanel:: LLInventoryRecentItemsPanel(const std::string& name, const std::string& sort_order_setting, - const std::string& start_folder, + const LLSD& start_folder, const LLRect& rect, LLInventoryModel* inventory, BOOL allow_multi_select, LLView *parent_view) : - LLInventoryPanel(name, sort_order_setting, start_folder,rect,inventory,allow_multi_select,parent_view) + LLInventoryPanel(name, sort_order_setting,start_folder,rect,inventory,allow_multi_select,parent_view) { + // replace bridge builder to have necessary View bridges. mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER; } diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 992c1a7619..524710b67e 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -1,6 +1,6 @@ /** - * @file llinventoryview.h - * @brief LLInventoryView, LLInventoryFolder, and LLInventoryItem + * @file llinventorypanel.h + * @brief LLInventoryPanel * class definition * * $LicenseInfo:firstyear=2001&license=viewergpl$ @@ -52,7 +52,7 @@ class LLFolderViewItem; class LLInventoryFilter; class LLInventoryModel; class LLInvFVBridge; -class LLInventoryFVBridgeBuilder; +class LLInventoryFolderViewModelBuilder; class LLMenuBarGL; class LLCheckBoxCtrl; class LLSpinCtrl; @@ -65,11 +65,37 @@ class LLFolderViewGroupedItemBridge; class LLInventoryPanel : public LLPanel { + //-------------------------------------------------------------------- + // Data + //-------------------------------------------------------------------- +public: + struct Filter : public LLInitParam::Block + { + Optional sort_order; + Optional types; + Optional search_string; + + Filter() + : sort_order("sort_order"), + types("types", 0xffffffff), + search_string("search_string") + {} + }; + + struct InventoryState : public LLInitParam::Block + { + Mandatory filter; + //Mandatory sort; + }; + + //-------------------------------------------------------------------- + // Initialization + //-------------------------------------------------------------------- protected: friend class LFFloaterInvPanel; LLInventoryPanel(const std::string& name, const std::string& sort_order_setting, - const std::string& start_folder, + const LLSD& start_folder, const LLRect& rect, LLInventoryModel* inventory, BOOL allow_multi_select, @@ -87,6 +113,7 @@ class LLInventoryPanel : public LLPanel // LLView methods void draw(); + /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); BOOL handleHover(S32 x, S32 y, MASK mask); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, @@ -102,10 +129,11 @@ class LLInventoryPanel : public LLPanel void closeAllFolders(); void openDefaultFolderForType(LLAssetType::EType); void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus); - void setSelectCallback(const boost::function& items, BOOL user_action)>& cb); + void setSelectCallback(const std::function& items, BOOL user_action)>& cb); void clearSelection(); - LLInventoryFilter* getFilter(); - const LLInventoryFilter* getFilter() const; + bool isSelectionRemovable(); + LLInventoryFilter& getFilter(); + const LLInventoryFilter& getFilter() const; void setFilterTypes(U64 filter, LLInventoryFilter::EFilterType = LLInventoryFilter::FILTERTYPE_OBJECT); U32 getFilterObjectTypes() const; void setFilterPermMask(PermissionMask filter_perm_mask); @@ -113,13 +141,13 @@ class LLInventoryPanel : public LLPanel void setFilterWearableTypes(U64 filter); void setFilterSubString(const std::string& string); const std::string getFilterSubString(); - void setFilterWorn(bool worn); - bool getFilterWorn() const { return mFolderRoot.get()->getFilterWorn(); } - + void setFilterWornItems(); + void setSinceLogoff(BOOL sl); void setHoursAgo(U32 hours); + void setDateSearchDirection(U32 direction); BOOL getSinceLogoff(); - void setFilterLinks(U64 filter_links); + void setFilterLinks(LLInventoryFilter::EFilterLink filter_links); void setShowFolderState(LLInventoryFilter::EFolderShow show); LLInventoryFilter::EFolderShow getShowFolderState(); @@ -128,10 +156,14 @@ class LLInventoryPanel : public LLPanel void modelChanged(U32 mask); LLFolderView* getRootFolder() { return mFolderRoot.get(); } LLScrollContainer* getScrollableContainer() { return mScroller; } + bool getAllowDropOnRoot() const { return mAllowDropOnRoot; } void onSelectionChange(const std::deque &items, BOOL user_action); LLHandle getInventoryPanelHandle() const { return getDerivedHandle(); } + + // Callbacks + void doToSelected(const LLSD& userdata); // DEBUG ONLY: static void dumpSelectionInformation(void* user_data); @@ -155,6 +187,13 @@ class LLInventoryPanel : public LLPanel LLInventoryType::EType inv_type, U32 next_owner_perm = 0); + void addItemID(const LLUUID& id, LLFolderViewItem* itemp); + void removeItemID(const LLUUID& id); + LLFolderViewItem* getItemByID(const LLUUID& id); + LLFolderViewFolder* getFolderByID(const LLUUID& id); + void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); + void updateSelection(); + // Clean up stuff when the folder root gets deleted void clearFolderRoot(); @@ -162,23 +201,25 @@ class LLInventoryPanel : public LLPanel void openStartFolderOrMyInventory(); // open the first level of inventory void onItemsCompletion(); // called when selected items are complete + LLUUID mSelectThisID; LLInventoryModel* mInventory; LLInventoryObserver* mInventoryObserver; LLInvPanelComplObserver* mCompletionObserver; - - BOOL mAllowMultiSelect; + bool mAllowMultiSelect; + LLHandle mFolderRoot; LLScrollContainer* mScroller; LLPointer mGroupedItemBridge; + boost::unordered_map mItemMap; /** - * Pointer to LLInventoryFVBridgeBuilder. + * Pointer to LLInventoryFolderViewModelBuilder. * * It is set in LLInventoryPanel's constructor and can be overridden in derived classes with * another implementation. * Take into account it will not be deleted by LLInventoryPanel itself. */ - const LLInventoryFVBridgeBuilder* mInvFVBridgeBuilder; + const LLInventoryFolderViewModelBuilder* mInvFVBridgeBuilder; //-------------------------------------------------------------------- @@ -195,7 +236,13 @@ class LLInventoryPanel : public LLPanel void requestSort(); private: - const std::string mStartFolder; + LLSD mStartFolder; + bool mShowRootFolder; + bool mShowEmptyMessage; + //bool mShowItemLinkOverlays; + bool mAllowDropOnRoot; + bool mAllowWear; + bool mUseMarketplaceFolders; const std::string mSortOrderSetting; //-------------------------------------------------------------------- @@ -206,7 +253,7 @@ class LLInventoryPanel : public LLPanel public: BOOL getIsViewsInitialized() const { return mViewsInitialized; } - const LLUUID& getRootFolderID() const; + const LLUUID getRootFolderID() const; protected: // Builds the UI. Call this once the inventory is usable. void initializeViews(); @@ -222,10 +269,7 @@ class LLInventoryPanel : public LLPanel BOOL mViewsInitialized; // Views have been generated }; -class LLInventoryView; - - - +class LLPanelMainInventory; ///---------------------------------------------------------------------------- /// Function declarations, constants, enums, and typedefs @@ -234,7 +278,7 @@ class LLInventoryView; // useful functions with the inventory view // *FIX: move these methods. -void init_inventory_actions(LLInventoryView *floater); +void init_inventory_actions(LLPanelMainInventory *floater); void init_inventory_panel_actions(LLInventoryPanel *panel); class LLInventoryCategory; @@ -249,6 +293,3 @@ const BOOL TAKE_FOCUS_YES = TRUE; const BOOL TAKE_FOCUS_NO = FALSE; #endif // LL_LLINVENTORYPANEL_H - - - diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp index 2dae860ed6..2c1698538f 100644 --- a/indra/newview/lljoystickbutton.cpp +++ b/indra/newview/lljoystickbutton.cpp @@ -661,7 +661,7 @@ void LLJoystickCameraRotate::drawRotatedImage( LLTexture* image, S32 rotations ) gGL.color4fv(UI_VERTEX_COLOR.mV); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { gGL.texCoord2fv( uv[ (rotations + 0) % 4]); gGL.vertex2i(width, height ); @@ -669,11 +669,11 @@ void LLJoystickCameraRotate::drawRotatedImage( LLTexture* image, S32 rotations ) gGL.texCoord2fv( uv[ (rotations + 1) % 4]); gGL.vertex2i(0, height ); - gGL.texCoord2fv( uv[ (rotations + 2) % 4]); - gGL.vertex2i(0, 0); - gGL.texCoord2fv( uv[ (rotations + 3) % 4]); gGL.vertex2i(width, 0); + + gGL.texCoord2fv( uv[ (rotations + 2) % 4]); + gGL.vertex2i(0, 0); } gGL.end(); } diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp new file mode 100644 index 0000000000..7652164d9b --- /dev/null +++ b/indra/newview/lllandmarkactions.cpp @@ -0,0 +1,422 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +/** +* @file lllandmarkactions.cpp +* @brief LLLandmarkActions class implementation +* +* $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 "llviewerprecompiledheaders.h" +#include "lllandmarkactions.h" + +#include "roles_constants.h" + +#include "llinventory.h" +#include "llinventoryfunctions.h" +#include "lllandmark.h" +#include "llparcel.h" +#include "llregionhandle.h" + +#include "llnotificationsutil.h" + +#include "llagent.h" +#include "llagentui.h" +#include "llinventorymodel.h" +#include "lllandmarklist.h" +#include "llslurl.h" +#include "llstring.h" +#include "llviewerinventory.h" +#include "llviewerparcelmgr.h" +#include "llworldmapmessage.h" +#include "llviewerwindow.h" +#include "llwindow.h" +#include "llworldmap.h" + +void copy_slurl_to_clipboard_callback(const std::string& slurl); + +class LLFetchlLandmarkByPos : public LLInventoryCollectFunctor +{ +private: + LLVector3d mPos; +public: + LLFetchlLandmarkByPos(const LLVector3d& pos) : + mPos(pos) + {} + + bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override + { + if (!item || item->getType() != LLAssetType::AT_LANDMARK) + return false; + + LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID()); + if (!landmark) // the landmark not been loaded yet + return false; + + LLVector3d landmark_global_pos; + if (!landmark->getGlobalPos(landmark_global_pos)) + return false; + //we have to round off each coordinates to compare positions properly + return ll_round(mPos.mdV[VX]) == ll_round(landmark_global_pos.mdV[VX]) + && ll_round(mPos.mdV[VY]) == ll_round(landmark_global_pos.mdV[VY]) + && ll_round(mPos.mdV[VZ]) == ll_round(landmark_global_pos.mdV[VZ]); + } +}; + +class LLFetchLandmarksByName : public LLInventoryCollectFunctor +{ +private: + std::string name; + BOOL use_substring; + //this member will be contain copy of founded items to keep the result unique + std::set check_duplicate; + +public: +LLFetchLandmarksByName(std::string &landmark_name, BOOL if_use_substring) +:name(landmark_name), +use_substring(if_use_substring) + { + LLStringUtil::toLower(name); + } + +public: + bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override + { + if (!item || item->getType() != LLAssetType::AT_LANDMARK) + return false; + + LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID()); + if (!landmark) // the landmark not been loaded yet + return false; + + bool acceptable = false; + std::string landmark_name = item->getName(); + LLStringUtil::toLower(landmark_name); + if(use_substring) + { + acceptable = landmark_name.find( name ) != std::string::npos; + } + else + { + acceptable = landmark_name == name; + } + if(acceptable){ + if(check_duplicate.find(landmark_name) != check_duplicate.end()){ + // we have duplicated items in landmarks + acceptable = false; + }else{ + check_duplicate.insert(landmark_name); + } + } + + return acceptable; + } +}; + +// Returns true if the given inventory item is a landmark pointing to the current parcel. +// Used to find out if there is at least one landmark from current parcel. +class LLFirstAgentParcelLandmark : public LLInventoryCollectFunctor +{ +private: + bool mFounded;// to avoid unnecessary check + +public: + LLFirstAgentParcelLandmark(): mFounded(false){} + + bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override + { + if (mFounded || !item || item->getType() != LLAssetType::AT_LANDMARK) + return false; + + LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID()); + if (!landmark) // the landmark not been loaded yet + return false; + + LLVector3d landmark_global_pos; + if (!landmark->getGlobalPos(landmark_global_pos)) + return false; + mFounded = LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos); + return mFounded; + } +}; + +static void fetch_landmarks(LLInventoryModel::cat_array_t& cats, + LLInventoryModel::item_array_t& items, + LLInventoryCollectFunctor& add) +{ + // Look in "My Favorites" + const LLUUID favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + gInventory.collectDescendentsIf(favorites_folder_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + add); + + // Look in "Landmarks" + const LLUUID landmarks_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); + gInventory.collectDescendentsIf(landmarks_folder_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + add); +} + +LLInventoryModel::item_array_t LLLandmarkActions::fetchLandmarksByName(std::string& name, BOOL use_substring) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLFetchLandmarksByName by_name(name, use_substring); + fetch_landmarks(cats, items, by_name); + + return items; +} + +bool LLLandmarkActions::landmarkAlreadyExists() +{ + // Determine whether there are landmarks pointing to the current global agent position. + return findLandmarkForAgentPos() != nullptr; +} + +//static +bool LLLandmarkActions::hasParcelLandmark() +{ + LLFirstAgentParcelLandmark get_first_agent_landmark; + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + fetch_landmarks(cats, items, get_first_agent_landmark); + return !items.empty(); + +} + +// *TODO: This could be made more efficient by only fetching the FIRST +// landmark that meets the criteria +LLViewerInventoryItem* LLLandmarkActions::findLandmarkForGlobalPos(const LLVector3d &pos) +{ + // Determine whether there are landmarks pointing to the current parcel. + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLFetchlLandmarkByPos is_current_pos_landmark(pos); + fetch_landmarks(cats, items, is_current_pos_landmark); + + return (items.empty()) ? nullptr : items[0]; +} + +LLViewerInventoryItem* LLLandmarkActions::findLandmarkForAgentPos() +{ + return findLandmarkForGlobalPos(gAgent.getPositionGlobal()); +} + +bool LLLandmarkActions::canCreateLandmarkHere() +{ + LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if(!agent_parcel) + { + LL_WARNS() << "No agent region" << LL_ENDL; + return false; + } + if (agent_parcel->getAllowLandmark() + || LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK)) + { + return true; + } + + return false; +} + +void LLLandmarkActions::createLandmarkHere( + const std::string& name, + const std::string& desc, + const LLUUID& folder_id) +{ + if(!gAgent.getRegion()) + { + LL_WARNS() << "No agent region" << LL_ENDL; + return; + } + LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!agent_parcel) + { + LL_WARNS() << "No agent parcel" << LL_ENDL; + return; + } + if (!canCreateLandmarkHere()) + { + LLNotificationsUtil::add("CannotCreateLandmarkNotOwner"); + return; + } + + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), + folder_id, LLTransactionID::tnull, + name, desc, + LLAssetType::AT_LANDMARK, + LLInventoryType::IT_LANDMARK, + NOT_WEARABLE, PERM_ALL, + NULL); +} + +void LLLandmarkActions::createLandmarkHere() +{ + std::string landmark_name, landmark_desc; + + LLAgentUI::buildLocationString(landmark_name, LLAgentUI::LOCATION_FORMAT_LANDMARK); + LLAgentUI::buildLocationString(landmark_desc, LLAgentUI::LOCATION_FORMAT_FULL); + const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); + + createLandmarkHere(landmark_name, landmark_desc, folder_id); +} + +LLVector3d getRegionPosFromGlobalPos(const LLVector3d& global_pos, const LLSimInfo* siminfo) +{ + LLVector3d local_pos; + local_pos[0] = fmod(global_pos[0], siminfo ? siminfo->getSizeX() : 256); + local_pos[1] = fmod(global_pos[1], siminfo ? siminfo->getSizeY() : 256); + local_pos[2] = global_pos[2]; + return local_pos; +} + +void LLLandmarkActions::getSLURLfromPosGlobal(const LLVector3d& global_pos, slurl_callback_t cb, bool escaped /* = true */) +{ + const LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(global_pos); + if (siminfo) + { + std::string slurl = LLSLURL(siminfo->getName(), getRegionPosFromGlobalPos(global_pos, siminfo)).getSLURLString(); + cb(slurl); + } + else + { + U64 new_region_handle = to_region_handle(global_pos); + + LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseSLURL, + cb, + global_pos, + escaped, + _2); + + LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, LLStringExplicit("unused"), false); + } +} + +void LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(const LLVector3d& global_pos, region_name_and_coords_callback_t cb) +{ + LLSimInfo* sim_infop = LLWorldMap::getInstance()->simInfoFromPosGlobal(global_pos); + if (sim_infop) + { + LLVector3 pos = sim_infop->getLocalPos(global_pos); + std::string name = sim_infop->getName() ; + cb(name, ll_round(pos.mV[VX]), ll_round(pos.mV[VY]),ll_round(pos.mV[VZ])); + } + else + { + U64 new_region_handle = to_region_handle(global_pos); + + LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseNameAndCoords, + cb, + global_pos, + _1); + + LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false); + } +} + +void LLLandmarkActions::onRegionResponseSLURL(slurl_callback_t cb, + const LLVector3d& global_pos, + bool escaped, + const std::string& url) +{ + std::string sim_name; + std::string slurl; + const LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(global_pos); + if (siminfo) + { + slurl = LLSLURL(siminfo->getName(), getRegionPosFromGlobalPos(global_pos, siminfo)).getSLURLString(); + } + else + { + slurl.clear(); + } + + cb(slurl); +} + +void LLLandmarkActions::onRegionResponseNameAndCoords(region_name_and_coords_callback_t cb, + const LLVector3d& global_pos, + U64 region_handle) +{ + LLSimInfo* sim_infop = LLWorldMap::getInstance()->simInfoFromHandle(region_handle); + if (sim_infop) + { + LLVector3 local_pos = sim_infop->getLocalPos(global_pos); + std::string name = sim_infop->getName() ; + cb(name, ll_round(local_pos.mV[VX]), ll_round(local_pos.mV[VY]), ll_round(local_pos.mV[VZ])); + } +} + +bool LLLandmarkActions::getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal) +{ + LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID); + if (NULL == item) + return false; + + const LLUUID& asset_id = item->getAssetUUID(); + + LLLandmark* landmark = gLandmarkList.getAsset(asset_id); + if (NULL == landmark) + return false; + + return landmark->getGlobalPos(posGlobal); +} + +LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID, LLLandmarkList::loaded_callback_t cb) +{ + LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID); + if (NULL == item) + return NULL; + + const LLUUID& asset_id = item->getAssetUUID(); + + LLLandmark* landmark = gLandmarkList.getAsset(asset_id, cb); + if (landmark) + { + return landmark; + } + + return NULL; +} + +void LLLandmarkActions::copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID) +{ + LLLandmark* landmark = LLLandmarkActions::getLandmark(landmarkInventoryItemID); + if(landmark) + { + LLVector3d global_pos; + landmark->getGlobalPos(global_pos); + LLLandmarkActions::getSLURLfromPosGlobal(global_pos,©_slurl_to_clipboard_callback,true); + } +} + +void copy_slurl_to_clipboard_callback(const std::string& slurl) +{ + gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl)); + LLSD args; + args["SLURL"] = slurl; + LLNotificationsUtil::add("CopySLURL", args); +} diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h new file mode 100644 index 0000000000..8ac61d6af4 --- /dev/null +++ b/indra/newview/lllandmarkactions.h @@ -0,0 +1,138 @@ +/** + * @file lllandmarkactions.h + * @brief LLLandmark class declaration + * + * $LicenseInfo:firstyear=2000&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_LLLANDMARKACTIONS_H +#define LL_LLLANDMARKACTIONS_H + +#include "llinventorymodel.h" + +#include "lllandmarklist.h" + +class LLLandmark; + +/** + * @brief Provides helper functions to manage landmarks + */ +class LLLandmarkActions +{ +public: + typedef std::function slurl_callback_t; + typedef std::function region_name_and_coords_callback_t; + + /** + * @brief Fetches landmark LLViewerInventoryItems for the given landmark name. + */ + static LLInventoryModel::item_array_t fetchLandmarksByName(std::string& name, BOOL if_use_substring); + /** + * @brief Checks whether landmark exists for current agent position. + */ + static bool landmarkAlreadyExists(); + + /** + * @brief Checks whether landmark exists for current agent parcel. + */ + static bool hasParcelLandmark(); + + /** + * @brief Searches landmark for global position. + * @return Returns landmark or NULL. + * + * *TODO: dzaporozhan: There can be many landmarks for single parcel. + */ + static LLViewerInventoryItem* findLandmarkForGlobalPos(const LLVector3d &pos); + + /** + * @brief Searches landmark for agent global position. + * @return Returns landmark or NULL. + * + * *TODO: dzaporozhan: There can be many landmarks for single parcel. + */ + static LLViewerInventoryItem* findLandmarkForAgentPos(); + + + /** + * @brief Checks whether agent has rights to create landmark for current parcel. + */ + static bool canCreateLandmarkHere(); + + /** + * @brief Creates landmark for current parcel. + */ + static void createLandmarkHere(); + + /** + * @brief Creates landmark for current parcel. + */ + static void createLandmarkHere( + const std::string& name, + const std::string& desc, + const LLUUID& folder_id); + /** + * @brief Creates SLURL for given global position. + */ + static void getSLURLfromPosGlobal(const LLVector3d& global_pos, slurl_callback_t cb, bool escaped = true); + + static void getRegionNameAndCoordsFromPosGlobal(const LLVector3d& global_pos, region_name_and_coords_callback_t cb); + + /** + * @brief Gets landmark global position specified by inventory LLUUID. + * Found position is placed into "posGlobal" variable. + *. + * @return - true if specified item exists in Inventory and an appropriate landmark found. + * and its position is known, false otherwise. + */ + // *TODO: mantipov: profide callback for cases, when Landmark is not loaded yet. + static bool getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal); + + /** + * @brief Retrieve a landmark from gLandmarkList by inventory item's id + * If a landmark is not currently in the gLandmarkList a callback "cb" is called when it is loaded. + * + * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist or wasn't loaded. + */ + static LLLandmark* getLandmark(const LLUUID& landmarkInventoryItemID, LLLandmarkList::loaded_callback_t cb = nullptr); + + /** + * @brief Performs standard action of copying of SLURL from landmark to user's clipboard. + * This action requires additional server request. The user will be notified by info message, + * when URL is copied . + */ + static void copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID); + +private: + LLLandmarkActions() = delete; + LLLandmarkActions(const LLLandmarkActions&) = delete; + + static void onRegionResponseSLURL(slurl_callback_t cb, + const LLVector3d& global_pos, + bool escaped, + const std::string& url); + static void onRegionResponseNameAndCoords(region_name_and_coords_callback_t cb, + const LLVector3d& global_pos, + U64 region_handle); +}; + +#endif //LL_LLLANDMARKACTIONS_H diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index 1d2eab1020..02cfd326a8 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com /** * @file lllandmarklist.cpp * @brief Landmark asset list class @@ -35,7 +37,6 @@ #include "llagent.h" #include "llvfile.h" #include "llviewerstats.h" -#include "llnotificationsutil.h" // Globals LLLandmarkList gLandmarkList; @@ -47,6 +48,7 @@ LLLandmarkList gLandmarkList; LLLandmarkList::~LLLandmarkList() { std::for_each(mList.begin(), mList.end(), DeletePairedPointer()); + mList.clear(); } LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t cb) @@ -67,7 +69,7 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t { if ( mBadList.find(asset_uuid) != mBadList.end() ) { - return NULL; + return nullptr; } landmark_requested_list_t::iterator iter = mRequestedList.find(asset_uuid); @@ -76,7 +78,7 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t const F32 rerequest_time = 30.f; // 30 seconds between requests if (gFrameTimeSeconds - iter->second < rerequest_time) { - return NULL; + return nullptr; } } @@ -89,10 +91,10 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t gAssetStorage->getAssetData(asset_uuid, LLAssetType::AT_LANDMARK, LLLandmarkList::processGetAssetReply, - NULL); + nullptr); mRequestedList[asset_uuid] = gFrameTimeSeconds; } - return NULL; + return nullptr; } // static @@ -143,14 +145,16 @@ void LLLandmarkList::processGetAssetReply( else { LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - + // SJB: No use case for a notification here. Use LL_DEBUGS() instead if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ) { - LLNotificationsUtil::add("LandmarkMissing"); + LL_WARNS("Landmarks") << "Missing Landmark" << LL_ENDL; + //LLNotificationsUtil::add("LandmarkMissing"); } else { - LLNotificationsUtil::add("UnableToLoadLandmark"); + LL_WARNS("Landmarks") << "Unable to load Landmark" << LL_ENDL; + //LLNotificationsUtil::add("UnableToLoadLandmark"); } gLandmarkList.mBadList.insert(uuid); diff --git a/indra/newview/lllandmarklist.h b/indra/newview/lllandmarklist.h index ab51f71356..057c8d5e75 100644 --- a/indra/newview/lllandmarklist.h +++ b/indra/newview/lllandmarklist.h @@ -27,11 +27,6 @@ #ifndef LL_LLLANDMARKLIST_H #define LL_LLLANDMARKLIST_H -#ifndef BOOST_FUNCTION_HPP_INCLUDED -#include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif -#include #include "lllandmark.h" #include "lluuid.h" #include "llassetstorage.h" @@ -43,7 +38,7 @@ class LLInventoryItem; class LLLandmarkList { public: - typedef boost::function loaded_callback_t; + typedef std::function loaded_callback_t; LLLandmarkList() {} ~LLLandmarkList(); @@ -53,7 +48,7 @@ class LLLandmarkList //const LLLandmark* getNext() { return mList.getNextData(); } BOOL assetExists(const LLUUID& asset_uuid); - LLLandmark* getAsset(const LLUUID& asset_uuid, loaded_callback_t cb = NULL); + LLLandmark* getAsset(const LLUUID& asset_uuid, loaded_callback_t cb = nullptr); static void processGetAssetReply( LLVFS *vfs, const LLUUID& uuid, @@ -73,7 +68,7 @@ class LLLandmarkList typedef std::map landmark_list_t; landmark_list_t mList; - typedef std::set landmark_bad_list_t; + typedef uuid_set_t landmark_bad_list_t; landmark_bad_list_t mBadList; typedef std::map landmark_requested_list_t; diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 029a2c4dfe..7da15ec618 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -36,35 +36,132 @@ #include "lllogchat.h" #include "llappviewer.h" #include "llfloaterchat.h" +#include "llsdserialize.h" +static std::string get_log_dir_file(const std::string& filename) +{ + return gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename); +} //static -std::string LLLogChat::makeLogFileName(std::string filename) +std::string LLLogChat::makeLogFileNameInternal(std::string filename) { - if (gSavedPerAccountSettings.getBOOL("LogFileNamewithDate")) + static const LLCachedControl with_date(gSavedPerAccountSettings, "LogFileNamewithDate"); + if (with_date) { time_t now; time(&now); - char dbuffer[100]; /* Flawfinder: ignore */ - if (filename == "chat") - { - static const LLCachedControl local_chat_date_format(gSavedPerAccountSettings, "LogFileLocalChatDateFormat", "-%Y-%m-%d"); - strftime(dbuffer, 100, local_chat_date_format().c_str(), localtime(&now)); - } - else - { - static const LLCachedControl ims_date_format(gSavedPerAccountSettings, "LogFileIMsDateFormat", "-%Y-%m"); - strftime(dbuffer, 100, ims_date_format().c_str(), localtime(&now)); - } - filename += dbuffer; + std::array dbuffer; + static const LLCachedControl local_chat_date_format(gSavedPerAccountSettings, "LogFileLocalChatDateFormat", "-%Y-%m-%d"); + static const LLCachedControl ims_date_format(gSavedPerAccountSettings, "LogFileIMsDateFormat", "-%Y-%m"); + strftime(dbuffer.data(), dbuffer.size(), (filename == "chat" ? local_chat_date_format : ims_date_format)().c_str(), localtime(&now)); + filename += dbuffer.data(); + } + cleanFileName(filename); + return get_log_dir_file(filename + ".txt"); +} + +bool LLLogChat::migrateFile(const std::string& old_name, const std::string& filename) +{ + std::string oldfile = makeLogFileNameInternal(old_name); + if (!LLFile::isfile(oldfile)) return false; // An old file by this name doesn't exist + + if (LLFile::isfile(filename)) // A file by the new name also exists, but wasn't being tracked yet + { + auto&& new_untracked_log = llifstream(filename); + auto&& tracked_log = llofstream(oldfile, llofstream::out|llofstream::app); + // Append new to old and find out if it failed + bool failed = !(tracked_log << new_untracked_log.rdbuf()); + // Close streams + new_untracked_log.close(); + tracked_log.close(); + if (failed || LLFile::remove(filename)) // Delete the untracked new file so that reclaiming its name won't fail + return true; // We failed to remove it or update the old file, let's just use the new file and leave the old one alone + } + + LLFile::rename(oldfile, filename); // Move the existing file to the new name + return true; // Report success +} + +static LLSD sIDMap; + +static std::string get_ids_map_file() { return get_log_dir_file("ids_to_names.json"); } +void LLLogChat::initializeIDMap() +{ + const auto map_file = get_ids_map_file(); + bool write = true; // Do we want to write back to map_file? + if (LLFile::isfile(map_file)) // If we've already made this file, load our map from it + { + if (auto&& fstr = llifstream(map_file)) + { + LLSDSerialize::fromNotation(sIDMap, fstr, LLSDSerialize::SIZE_UNLIMITED); + fstr.close(); + } + write = false; // Don't write what we just read + } + + if (gCacheName) // Load what we can from name cache to initialize or update the map and its file + { + bool empty = sIDMap.size() == 0; // Opt out of searching the map for IDs we added if we started with none + for (const auto& r : gCacheName->getReverseMap()) // For every name id pair + { + const auto id = r.second.asString(); + const auto& name = r.first; + const auto filename = makeLogFileNameInternal(name); + bool id_known = !empty && sIDMap.has(id); // Is this ID known? + if (id_known ? name != sIDMap[id].asStringRef() // If names don't match + && migrateFile(sIDMap[id].asStringRef(), filename) // Do we need to migrate an existing log? + : LLFile::isfile(filename)) // Otherwise if there's a log file for them but they're not in the map yet + { + if (id_known) write = true; // We updated, write + sIDMap[id] = name; // Add them to the map + } + } + + if (write) + if (auto&& fstr = llofstream(map_file)) + { + LLSDSerialize::toPrettyNotation(sIDMap, fstr); + fstr.close(); + } + } + +} + +//static +std::string LLLogChat::makeLogFileName(const std::string& username, const LLUUID& id) +{ + const auto name = username.empty() ? id.asString() : username; // Fall back on ID if the grid sucks and we have no name + std::string filename = makeLogFileNameInternal(name); + if (id.notNull() && !LLFile::isfile(filename)) // No existing file by this user's current name, check for possible file rename + { + auto& entry = sIDMap[id.asString()]; + const bool empty = !entry.size(); + if (empty || entry != name) // If we haven't seen this entry yet, or the name is different than we remember + { + if (empty) // We didn't see this entry on load + { + // Ideally, we would look up the old names here via server request + // In lieu of that, our reverse cache has old names and new names that we've gained since our initialization of the ID map + for (const auto& r : gCacheName->getReverseMap()) + if (r.second == id && migrateFile(r.first, filename)) + break; + } + else migrateFile(entry.asStringRef(), filename); // We've seen this entry before, migrate old file if it exists + + entry = name; // Update the entry to point to the new name + + if (auto&& fstr = llofstream(get_ids_map_file())) // Write back to our map file + { + LLSDSerialize::toPrettyNotation(sIDMap, fstr); + fstr.close(); + } + } } - filename = cleanFileName(filename); - filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename); - filename += ".txt"; return filename; } -std::string LLLogChat::cleanFileName(std::string filename) +void LLLogChat::cleanFileName(std::string& filename) { std::string invalidChars = "\"\'\\/?*:<>|[]{}~"; // Cannot match glob or illegal filename chars S32 position = filename.find_first_of(invalidChars); @@ -73,48 +170,59 @@ std::string LLLogChat::cleanFileName(std::string filename) filename[position] = '_'; position = filename.find_first_of(invalidChars, position); } - return filename; } -std::string LLLogChat::timestamp(bool withdate) +static void time_format(std::string& out, const char* fmt, const std::tm* time) { - time_t utc_time; - utc_time = time_corrected(); + typedef typename std::vector> vec_t; + static thread_local vec_t charvector(1024); // Evolves into charveleon + #define format_the_time() std::strftime(charvector.data(), charvector.capacity(), fmt, time) + const auto smallsize(charvector.capacity()); + const auto size = format_the_time(); + if (size < 0) + { + LL_ERRS() << "Formatting time failed, code " << size << ". String hint: " << out << '/' << fmt << LL_ENDL; + } + else if (static_cast(size) >= smallsize) // Resize if we need more space + { + charvector.resize(1+size); // Use the String Stone + format_the_time(); + } + #undef format_the_time + out.assign(charvector.data()); +} - // There's only one internal tm buffer. - struct tm* timep; +std::string LLLogChat::timestamp(bool withdate) +{ // Convert to Pacific, based on server's opinion of whether // it's daylight savings time there. - timep = utc_to_pacific_time(utc_time, gPacificDaylightTime); - - static LLCachedControl withseconds("SecondsInLog"); - std::string text; - if (withdate) - if (withseconds) - text = llformat("[%d/%02d/%02d %02d:%02d:%02d] ", (timep->tm_year-100)+2000, timep->tm_mon+1, timep->tm_mday, timep->tm_hour, timep->tm_min, timep->tm_sec); - else - text = llformat("[%d/%02d/%02d %02d:%02d] ", (timep->tm_year-100)+2000, timep->tm_mon+1, timep->tm_mday, timep->tm_hour, timep->tm_min); - else - if (withseconds) - text = llformat("[%02d:%02d:%02d] ", timep->tm_hour, timep->tm_min, timep->tm_sec); - else - text = llformat("[%02d:%02d] ", timep->tm_hour, timep->tm_min); + auto time = utc_to_pacific_time(time_corrected(), gPacificDaylightTime); + + static const LLCachedControl withseconds("SecondsInLog"); + static const LLCachedControl date("ShortDateFormat"); + static const LLCachedControl shorttime("ShortTimeFormat"); + static const LLCachedControl longtime("LongTimeFormat"); + std::string text = "["; + if (withdate) text += date() + ' '; + text += (withseconds ? longtime : shorttime)() + "] "; + + time_format(text, text.data(), time); return text; } //static -void LLLogChat::saveHistory(std::string const& filename, std::string line) +void LLLogChat::saveHistory(const std::string& name, const LLUUID& id, const std::string& line) { - if(!filename.size()) + if(name.empty() && id.isNull()) { LL_INFOS() << "Filename is Empty!" << LL_ENDL; return; } - LLFILE* fp = LLFile::fopen(LLLogChat::makeLogFileName(filename), "a"); /*Flawfinder: ignore*/ + LLFILE* fp = LLFile::fopen(LLLogChat::makeLogFileName(name, id), "a"); /*Flawfinder: ignore*/ if (!fp) { LL_INFOS() << "Couldn't open chat history log!" << LL_ENDL; @@ -129,10 +237,9 @@ void LLLogChat::saveHistory(std::string const& filename, std::string line) static long const LOG_RECALL_BUFSIZ = 2048; -void LLLogChat::loadHistory(std::string const& filename , void (*callback)(ELogLineType, std::string, void*), void* userdata) +void LLLogChat::loadHistory(const std::string& name, const LLUUID& id, std::function callback) { - bool filename_empty = filename.empty(); - if (filename_empty) + if (name.empty() && id.isNull()) { LL_WARNS() << "filename is empty!" << LL_ENDL; } @@ -143,7 +250,7 @@ void LLLogChat::loadHistory(std::string const& filename , void (*callback)(ELogL if (lines == 0) break; // Open the log file. - LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "rb"); + LLFILE* fptr = LLFile::fopen(makeLogFileName(name, id), "rb"); if (!fptr) break; // Set pos to point to the last character of the file, if any. @@ -188,20 +295,15 @@ void LLLogChat::loadHistory(std::string const& filename , void (*callback)(ELogL // Read lines from the file one by one until we reach the end of the file. while (fgets(buffer, LOG_RECALL_BUFSIZ, fptr)) { - size_t len = strlen(buffer); - int i = len - 1; - while (i >= 0 && (buffer[i] == '\r' || buffer[i] == '\n')) // strip newline chars from the end of the string - { - buffer[i] = '\0'; - i--; - } - callback(LOG_LINE, buffer, userdata); + // strip newline chars from the end of the string + for (S32 i = strlen(buffer) - 1; i >= 0 && (buffer[i] == '\r' || buffer[i] == '\n'); --i) + buffer[i] = '\0'; + callback(LOG_LINE, buffer); } fclose(fptr); - callback(LOG_END, LLStringUtil::null, userdata); + callback(LOG_END, LLStringUtil::null); return; } - callback(LOG_EMPTY, LLStringUtil::null, userdata); + callback(LOG_EMPTY, LLStringUtil::null); } - diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index 84f6760ab6..245eb95ce0 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -45,14 +45,16 @@ class LLLogChat LOG_LINE, LOG_END }; + static void initializeIDMap(); static std::string timestamp(bool withdate = false); - static std::string makeLogFileName(std::string filename); - static void saveHistory(std::string const& filename, std::string line); - static void loadHistory(std::string const& filename, - void (*callback)(ELogLineType,std::string,void*), - void* userdata); + static std::string makeLogFileName(const std::string& name, const LLUUID& id); + static void saveHistory(const std::string& name, const LLUUID& id, const std::string& line); + static void loadHistory(const std::string& name, const LLUUID& id, + std::function callback); private: - static std::string cleanFileName(std::string filename); + static std::string makeLogFileNameInternal(std::string filename); + static bool migrateFile(const std::string& old_name, const std::string& filename); + static void cleanFileName(std::string& filename); }; #endif diff --git a/indra/newview/llmakeoutfitdialog.cpp b/indra/newview/llmakeoutfitdialog.cpp index d01860947a..f029210b9e 100644 --- a/indra/newview/llmakeoutfitdialog.cpp +++ b/indra/newview/llmakeoutfitdialog.cpp @@ -52,7 +52,15 @@ LLMakeOutfitDialog::LLMakeOutfitDialog(bool modal) : LLModalDialog(LLStringUtil: // Build list of check boxes for (S32 i = 0; i < LLWearableType::WT_COUNT; i++) { - std::string name = std::string("checkbox_") + LLWearableType::getTypeLabel((LLWearableType::EType)i); + std::string label = LLWearableType::getTypeLabel((LLWearableType::EType)i); + std::string name = std::string("checkbox_") + label; + std::string labellower = label; + labellower[0] = tolower(labellower[0]); + std::string namelower = std::string("checkbox_") + labellower; + if (findChild(namelower)) + { + name = namelower; + } mCheckBoxList.push_back(std::make_pair(name, i)); // Hide undergarments from teens if (gAgent.isTeen() && ((LLWearableType::WT_UNDERSHIRT == (LLWearableType::EType)i) || (LLWearableType::WT_UNDERPANTS == (LLWearableType::EType)i))) diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index d4c607dd85..fc4e2a46da 100644 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -456,7 +456,7 @@ void LLManip::renderXYZ(const LLVector3 &vec) gGL.pushMatrix(); { - LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); gViewerWindow->setup2DRender(); const LLVector2& display_scale = gViewerWindow->getDisplayScale(); gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f); diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 45b18ae2f8..6204b8ba1b 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -115,8 +115,8 @@ void LLManipRotate::render() LLGLSUIDefault gls_ui; gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); LLGLDepthTest gls_depth(GL_TRUE); - LLGLEnable gl_blend(GL_BLEND); - LLGLEnable gls_alpha_test(GL_ALPHA_TEST); + LLGLEnable gl_blend; + LLGLEnable gls_alpha_test; // You can rotate if you can move LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE); @@ -160,7 +160,7 @@ void LLManipRotate::render() gDebugProgram.bind(); } - LLGLEnable cull_face(GL_CULL_FACE); + LLGLEnable cull_face; LLGLDepthTest gls_depth(GL_FALSE); gGL.pushMatrix(); { @@ -242,7 +242,7 @@ void LLManipRotate::render() if (mManipPart == LL_ROT_Z) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.pushMatrix(); { // selected part @@ -253,7 +253,7 @@ void LLManipRotate::render() } else if (mManipPart == LL_ROT_Y) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.pushMatrix(); { static const LLMatrix4a rot = gGL.genRot( 90.f, 1.f, 0.f, 0.f ); @@ -265,7 +265,7 @@ void LLManipRotate::render() } else if (mManipPart == LL_ROT_X) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.pushMatrix(); { static const LLMatrix4a rot = gGL.genRot( 90.f, 0.f, 1.f, 0.f ); @@ -277,17 +277,17 @@ void LLManipRotate::render() } else if (mManipPart == LL_ROT_ROLL) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); } else if (mManipPart == LL_NO_PART) { if (mHighlightedPart == LL_NO_PART) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); } - LLGLEnable cull_face(GL_CULL_FACE); - LLGLEnable clip_plane0(GL_CLIP_PLANE0); + LLGLEnable cull_face; + LLGLEnable clip_plane0; LLGLDepthTest gls_depth(GL_FALSE); // First pass: centers. Second pass: sides. @@ -298,7 +298,7 @@ void LLManipRotate::render() { if (mHighlightedPart == LL_ROT_Z) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.scalef(mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ]); // hovering over part gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 0.f, 1.f, 1.f ), LLColor4( 0.f, 0.f, 1.f, 0.5f ), CIRCLE_STEPS, i); @@ -317,7 +317,7 @@ void LLManipRotate::render() gGL.rotatef( rot ); if (mHighlightedPart == LL_ROT_Y) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.scalef(mManipulatorScales.mV[VY], mManipulatorScales.mV[VY], mManipulatorScales.mV[VY]); // hovering over part gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 1.f, 0.f, 1.f ), LLColor4( 0.f, 1.f, 0.f, 0.5f ), CIRCLE_STEPS, i); @@ -336,7 +336,7 @@ void LLManipRotate::render() gGL.rotatef( rot ); if (mHighlightedPart == LL_ROT_X) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.scalef(mManipulatorScales.mV[VX], mManipulatorScales.mV[VX], mManipulatorScales.mV[VX]); // hovering over part @@ -352,7 +352,7 @@ void LLManipRotate::render() if (mHighlightedPart == LL_ROT_ROLL) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); } } @@ -488,7 +488,7 @@ BOOL LLManipRotate::handleMouseUp(S32 x, S32 y, MASK mask) LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); // have permission to move and object is root of selection or individually selected - if (object->permMove() && !object->isPermanentEnforced() && + if (object && object->permMove() && !object->isPermanentEnforced() && ((root_object == NULL) || !root_object->isPermanentEnforced()) && (object->isRootEdit() || selectNode->mIndividualSelection)) { @@ -578,7 +578,7 @@ void LLManipRotate::drag( S32 x, S32 y ) LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); // have permission to move and object is root of selection or individually selected - if (object->permMove() && !object->isPermanentEnforced() && + if (object && object->permMove() && !object->isPermanentEnforced() && ((root_object == NULL) || !root_object->isPermanentEnforced()) && (object->isRootEdit() || selectNode->mIndividualSelection)) { @@ -736,7 +736,7 @@ void LLManipRotate::drag( S32 x, S32 y ) void LLManipRotate::renderActiveRing( F32 radius, F32 width, const LLColor4& front_color, const LLColor4& back_color) { - LLGLEnable cull_face(GL_CULL_FACE); + LLGLEnable cull_face; { gl_ring(radius, width, back_color, back_color * 0.5f, CIRCLE_STEPS, FALSE); gl_ring(radius, width, back_color, back_color * 0.5f, CIRCLE_STEPS, TRUE); @@ -1216,8 +1216,8 @@ LLQuaternion LLManipRotate::dragUnconstrained( S32 x, S32 y ) F32 dist_from_sphere_center = sqrt(delta_x * delta_x + delta_y * delta_y); LLVector3 axis = mMouseDown % mMouseCur; + F32 angle = atan2(sqrtf(axis * axis), mMouseDown * mMouseCur); axis.normVec(); - F32 angle = acos(mMouseDown * mMouseCur); LLQuaternion sphere_rot( angle, axis ); if (is_approx_zero(1.f - mMouseDown * mMouseCur)) @@ -1614,9 +1614,9 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) mInSnapRegime = FALSE; } - angle = acos(mMouseCur * mMouseDown); - - F32 dir = (mMouseDown % mMouseCur) * constraint_axis; // cross product + LLVector3 cross_product = mMouseDown % mMouseCur; + angle = atan2(sqrtf(cross_product * cross_product), mMouseCur * mMouseDown); + F32 dir = cross_product * constraint_axis; // cross product if( dir < 0.f ) { angle *= -1.f; diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index 4b6a3d6cc6..fedebbd108 100644 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -213,8 +213,8 @@ void LLManipScale::render() LLGLSUIDefault gls_ui; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLGLDepthTest gls_depth(GL_TRUE); - LLGLEnable gl_blend(GL_BLEND); - LLGLEnable gls_alpha_test(GL_ALPHA_TEST); + LLGLEnable gl_blend; + LLGLEnable gls_alpha_test; LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); if( canAffectSelection() ) @@ -293,8 +293,8 @@ void LLManipScale::render() { - LLGLEnable poly_offset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset( -2.f, -2.f); + LLGLEnable poly_offset; + gGL.setPolygonOffset( -2.f, -2.f); // JC - Band-aid until edge stretch working similar to side stretch // in non-uniform. @@ -308,7 +308,7 @@ void LLManipScale::render() renderGuidelinesPart( bbox ); } - glPolygonOffset( 0.f, 0.f); + gGL.setPolygonOffset( 0.f, 0.f); } } gGL.popMatrix(); @@ -543,11 +543,11 @@ void LLManipScale::highlightManipulators(S32 x, S32 y) { if (mHighlightedPart == MANIPULATOR_IDS[i]) { - mManipulatorScales[i] = lerp(mManipulatorScales[i], SELECTED_MANIPULATOR_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales[i] = lerp(mManipulatorScales[i], SELECTED_MANIPULATOR_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); } else { - mManipulatorScales[i] = lerp(mManipulatorScales[i], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales[i] = lerp(mManipulatorScales[i], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); } } @@ -610,43 +610,55 @@ void LLManipScale::renderFaces( const LLBBox& bbox ) { gGL.color4fv( default_normal_color.mV ); LLGLDepthTest gls_depth(GL_FALSE); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { // Face 0 gGL.vertex3f(min.mV[VX], max.mV[VY], max.mV[VZ]); gGL.vertex3f(min.mV[VX], min.mV[VY], max.mV[VZ]); - gGL.vertex3f(max.mV[VX], min.mV[VY], max.mV[VZ]); gGL.vertex3f(max.mV[VX], max.mV[VY], max.mV[VZ]); + gGL.vertex3f(max.mV[VX], max.mV[VY], max.mV[VZ]); + gGL.vertex3f(min.mV[VX], min.mV[VY], max.mV[VZ]); + gGL.vertex3f(max.mV[VX], min.mV[VY], max.mV[VZ]); // Face 1 gGL.vertex3f(max.mV[VX], min.mV[VY], max.mV[VZ]); gGL.vertex3f(max.mV[VX], min.mV[VY], min.mV[VZ]); - gGL.vertex3f(max.mV[VX], max.mV[VY], min.mV[VZ]); gGL.vertex3f(max.mV[VX], max.mV[VY], max.mV[VZ]); + gGL.vertex3f(max.mV[VX], max.mV[VY], max.mV[VZ]); + gGL.vertex3f(max.mV[VX], min.mV[VY], min.mV[VZ]); + gGL.vertex3f(max.mV[VX], max.mV[VY], min.mV[VZ]); // Face 2 gGL.vertex3f(min.mV[VX], max.mV[VY], min.mV[VZ]); gGL.vertex3f(min.mV[VX], max.mV[VY], max.mV[VZ]); - gGL.vertex3f(max.mV[VX], max.mV[VY], max.mV[VZ]); gGL.vertex3f(max.mV[VX], max.mV[VY], min.mV[VZ]); + gGL.vertex3f(max.mV[VX], max.mV[VY], min.mV[VZ]); + gGL.vertex3f(min.mV[VX], max.mV[VY], max.mV[VZ]); + gGL.vertex3f(max.mV[VX], max.mV[VY], max.mV[VZ]); // Face 3 gGL.vertex3f(min.mV[VX], max.mV[VY], max.mV[VZ]); gGL.vertex3f(min.mV[VX], max.mV[VY], min.mV[VZ]); - gGL.vertex3f(min.mV[VX], min.mV[VY], min.mV[VZ]); gGL.vertex3f(min.mV[VX], min.mV[VY], max.mV[VZ]); + gGL.vertex3f(min.mV[VX], min.mV[VY], max.mV[VZ]); + gGL.vertex3f(min.mV[VX], max.mV[VY], min.mV[VZ]); + gGL.vertex3f(min.mV[VX], min.mV[VY], min.mV[VZ]); // Face 4 gGL.vertex3f(min.mV[VX], min.mV[VY], max.mV[VZ]); gGL.vertex3f(min.mV[VX], min.mV[VY], min.mV[VZ]); - gGL.vertex3f(max.mV[VX], min.mV[VY], min.mV[VZ]); gGL.vertex3f(max.mV[VX], min.mV[VY], max.mV[VZ]); + gGL.vertex3f(max.mV[VX], min.mV[VY], max.mV[VZ]); + gGL.vertex3f(min.mV[VX], min.mV[VY], min.mV[VZ]); + gGL.vertex3f(max.mV[VX], min.mV[VY], min.mV[VZ]); // Face 5 gGL.vertex3f(min.mV[VX], min.mV[VY], min.mV[VZ]); gGL.vertex3f(min.mV[VX], max.mV[VY], min.mV[VZ]); - gGL.vertex3f(max.mV[VX], max.mV[VY], min.mV[VZ]); gGL.vertex3f(max.mV[VX], min.mV[VY], min.mV[VZ]); + gGL.vertex3f(max.mV[VX], min.mV[VY], min.mV[VZ]); + gGL.vertex3f(min.mV[VX], max.mV[VY], min.mV[VZ]); + gGL.vertex3f(max.mV[VX], max.mV[VY], min.mV[VZ]); } gGL.end(); } diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index a3e2561af8..c5ffcdae66 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -542,7 +542,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) { F32 max_drag_distance = gSavedSettings.getF32("MaxDragDistance"); - if (gHippoGridManager->getConnectedGrid()->isAurora()) + if (gHippoGridManager->getConnectedGrid()->isWhiteCore()) max_drag_distance = llmin(10000.f, max_drag_distance); if (relative_move.magVecSquared() > max_drag_distance * max_drag_distance) @@ -704,7 +704,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) } LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); - if (object->permMove() && !object->isPermanentEnforced() && + if (object && object->permMove() && !object->isPermanentEnforced() && ((root_object == NULL) || !root_object->isPermanentEnforced())) { // handle attachments in local space @@ -1103,7 +1103,7 @@ void LLManipTranslate::renderSnapGuides() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLGLDepthTest gls_depth(GL_TRUE); - LLGLDisable gls_cull(GL_CULL_FACE); + LLGLDisable gls_cull; LLVector3 translate_axis; if (mManipPart == LL_NO_PART) @@ -1546,7 +1546,7 @@ void LLManipTranslate::renderSnapGuides() LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); { - LLGLDisable stencil(GL_STENCIL_TEST); + LLGLDisable stencil; { LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName()); @@ -1558,7 +1558,7 @@ void LLManipTranslate::renderSnapGuides() } { - LLGLDisable alpha_test(GL_ALPHA_TEST); + LLGLDisable alpha_test; //draw black overlay gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); renderGrid(u,v,tiles,0.0f, 0.0f, 0.0f,a*0.16f); @@ -1579,7 +1579,7 @@ void LLManipTranslate::renderSnapGuides() { LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); - LLGLEnable stipple(GL_LINE_STIPPLE); + LLGLEnable stipple; gGL.flush(); if (!LLGLSLShader::sNoFixedFunction) @@ -1675,10 +1675,11 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal, { glStencilMask(stencil_mask); glClearStencil(1); + gGL.syncContextState(); glClear(GL_STENCIL_BUFFER_BIT); glClearStencil(0); - LLGLEnable cull_face(GL_CULL_FACE); - LLGLEnable stencil(GL_STENCIL_TEST); + LLGLEnable cull_face; + LLGLEnable stencil; LLGLDepthTest depth (GL_TRUE, GL_FALSE, GL_ALWAYS); glStencilFunc(GL_ALWAYS, 0, stencil_mask); gGL.setColorMask(false, false); @@ -1768,7 +1769,7 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal, { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLGLDepthTest depth(GL_FALSE); - LLGLEnable stencil(GL_STENCIL_TEST); + LLGLEnable stencil; glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, 0, stencil_mask); renderGrid(0,0,tiles,inner_color.mV[0], inner_color.mV[1], inner_color.mV[2], 0.25f); @@ -1915,7 +1916,7 @@ void LLManipTranslate::renderTranslationHandles() { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDisable cull_face(GL_CULL_FACE); + LLGLDisable cull_face; LLColor4 color1; LLColor4 color2; @@ -1925,18 +1926,18 @@ void LLManipTranslate::renderTranslationHandles() { if (index == mManipPart - LL_X_ARROW || index == mHighlightedPart - LL_X_ARROW) { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], SELECTED_ARROW_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); } else if (index == mManipPart - LL_YZ_PLANE || index == mHighlightedPart - LL_YZ_PLANE) { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], SELECTED_ARROW_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); } else { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); } } @@ -2207,8 +2208,8 @@ void LLManipTranslate::renderTranslationHandles() void LLManipTranslate::renderArrow(S32 which_arrow, S32 selected_arrow, F32 box_size, F32 arrow_size, F32 handle_size, BOOL reverse_direction) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLEnable gls_blend(GL_BLEND); - LLGLEnable gls_color_material(GL_COLOR_MATERIAL); + LLGLEnable gls_blend; + LLGLEnable gls_color_material; for (S32 pass = 1; pass <= 2; pass++) { @@ -2317,7 +2318,7 @@ BOOL LLManipTranslate::canAffectSelection() virtual bool apply(LLViewerObject* objectp) { LLViewerObject *root_object = (objectp == NULL) ? NULL : objectp->getRootEdit(); - return objectp->permMove() && !objectp->isPermanentEnforced() && + return objectp && objectp->permMove() && !objectp->isPermanentEnforced() && ((root_object == NULL) || !root_object->isPermanentEnforced()) && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); } diff --git a/indra/newview/llmapresponders.cpp b/indra/newview/llmapresponders.cpp index 0a63eb85b0..813830a135 100644 --- a/indra/newview/llmapresponders.cpp +++ b/indra/newview/llmapresponders.cpp @@ -59,11 +59,8 @@ void LLMapLayerResponder::httpSuccess(void) LLWorldMap::getInstance()->mMapLayers.clear(); - LLSD::array_const_iterator iter; - for(iter = mContent["LayerData"].beginArray(); iter != mContent["LayerData"].endArray(); ++iter) + for (auto const& layer_data : mContent["LayerData"].array()) { - const LLSD& layer_data = *iter; - LLWorldMapLayer new_layer; new_layer.LayerDefined = TRUE; diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index d8c921b9ba..5234efbac8 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -29,14 +29,23 @@ #include "llmarketplacefunctions.h" #include "llagent.h" +#include "llbufferstream.h" #include "llhttpclient.h" +#include "llinventoryfunctions.h" +#include "llinventoryobserver.h" +#include "llnotificationsutil.h" +#include "llsdjson.h" #include "lltimer.h" #include "lltrans.h" #include "llviewercontrol.h" +#include "llviewerinventory.h" #include "llviewermedia.h" #include "llviewernetwork.h" +#include "llviewerregion.h" #include "hippogridmanager.h" +#include "llsdutil.h" + // // Helpers // @@ -84,7 +93,7 @@ static std::string getMarketplaceDomain() else { // TODO: Find out if OpenSim, and Avination adopted any outbox stuffs, if so code HippoGridManager for this - // Aurora grid has not. + // WhiteCore has not. // For now, set domain on other grids to the loginUri domain, so we don't harass LL web services. domain = getLoginUriDomain(); //gHippoGridManager->getCurrentGrid()->getMarketPlaceDomain(); } @@ -101,7 +110,7 @@ static std::string getMarketplaceURL(const std::string& urlStringName) return marketplace_url; } -LLSD getMarketplaceStringSubstitutions() +LLSD LLMarketplaceData::getMarketplaceStringSubstitutions() { std::string marketplace_url = getMarketplaceURL("MarketplaceURL"); std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore"); @@ -120,16 +129,549 @@ LLSD getMarketplaceStringSubstitutions() return marketplace_sub_map; } +// Get the version folder: if there is only one subfolder, we will use it as a version folder +LLUUID getVersionFolderIfUnique(const LLUUID& folder_id) +{ + LLUUID version_id = LLUUID::null; + LLInventoryModel::cat_array_t* categories; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(folder_id, categories, items); + if (categories->size() == 1) + { + version_id = categories->begin()->get()->getUUID(); + } + else + { + LLNotificationsUtil::add("AlertMerchantListingActivateRequired"); + } + return version_id; +} + +/////////////////////////////////////////////////////////////////////////////// + // SLM Reporters +void log_SLM_warning(const std::string& request, U32 status, const std::string& reason, const std::string& code, const LLSD& content) +{ + LL_WARNS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", reason : " << reason << ", code : " << code << ", description : " << ll_pretty_print_sd(content) << LL_ENDL; + if ((status == 422) && + content.isArray() && + content.size() > 4) + { + // Unprocessable Entity : Special case that error as it is a frequent answer when trying to list an incomplete listing + LLNotificationsUtil::add("MerchantUnprocessableEntity"); + } + else + { + // Prompt the user with the warning (so they know why things are failing) + LLSD subs; + // We do show long descriptions in the alert (unlikely to be readable). The description string will be in the log though. + std::string description; + { + if (content.isArray()) + { + for (auto it = content.beginArray(); it != content.endArray(); ++it) + { + if (!description.empty()) + description += '\n'; + description += (*it).asString(); + } + } + else + { + description = content.asString(); + } + } + std::string reason_lc = reason; + LLStringUtil::toLower(reason_lc); + if (!description.empty() && reason_lc.find("unknown") != std::string::npos) + { + subs["[ERROR_REASON]"] = LLStringUtil::null; + } + else + { + subs["[ERROR_REASON]"] = '\'' + reason +"'\n"; + } + subs["[ERROR_DESCRIPTION]"] = description; + LLNotificationsUtil::add("MerchantTransactionFailed", subs); + } +} + +void log_SLM_infos(const std::string& request, U32 status, const std::string& body) +{ + if (gSavedSettings.getBOOL("MarketplaceListingsLogging")) + { + LL_INFOS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", body or description : " << body << LL_ENDL; + } +} + +void log_SLM_infos(const std::string& request, const std::string& url, const std::string& body) +{ + if (gSavedSettings.getBOOL("MarketplaceListingsLogging")) + { + LL_INFOS("SLM") << "SLM API : Sending " << request << ". url : " << url << ", body : " << body << LL_ENDL; + } +} + +class LLSLMGetMerchantResponder : public LLHTTPClient::ResponderWithCompleted +{ + LOG_CLASS(LLSLMGetMerchantResponder); +public: + + LLSLMGetMerchantResponder() {} + +protected: + void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) override + { + S32 httpCode = getStatus(); + + if (!isGoodStatus(mStatus)) + { + if (httpCode == HTTP_NOT_FOUND) + { + log_SLM_infos("Get /merchant", httpCode, std::string("User is not a merchant")); + LLMarketplaceData::instance(). + setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT); + } + else if (httpCode == HTTP_SERVICE_UNAVAILABLE) + { + log_SLM_infos("Get /merchant", httpCode, std::string("Merchant is not migrated")); + LLMarketplaceData::instance(). + setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT); + } + else if (httpCode == 499) + { + const auto& content(getContent()); + // 499 includes timeout and ssl error - marketplace is down or having issues, we do not show it in this request according to MAINT-5938 + LL_WARNS("SLM") << "SLM Merchant Request failed with status: " << httpCode + << ", reason : " << getReason() + << ", code : " << content.get("error_code") + << ", description : " << content.get("error_description") << LL_ENDL; + LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE); + } + else + { + log_SLM_warning("Get /merchant", httpCode, getReason(), LLStringUtil::null, getContent()); + LLMarketplaceData::instance(). + setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE); + } + return; + } + + log_SLM_infos("Get /merchant", getStatus(), "User is a merchant"); + LLMarketplaceData::instance(). + setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_MERCHANT); + } + virtual char const* getName() const { return "getMerchantStatus"; } +}; + +class LLSLMGetListingsResponder : public LLHTTPClient::ResponderWithCompleted +{ + LOG_CLASS(LLSLMGetListingsResponder); +public: + LLSLMGetListingsResponder(const LLUUID& folder_id) + { + folderId = folder_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance(). + setUpdating(folderId, false); + + std::string body; + decode_raw_body(channels, buffer, body); + + LLSD result = LlsdFromJsonString(body); + if (result.isUndefined()) + { + log_SLM_warning("Get /listings", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response"); + return; + } + + if (!isGoodStatus(mStatus)) + { + log_SLM_warning("Get /listings", getStatus(), getReason(), LLStringUtil::null, result); + LLMarketplaceData::instance(). + setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_FAILED); + update_marketplace_category(folderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Get /listings", getStatus(), body); + + // Extract the info from the results + for (auto const& listing : result["listings"].array()) + { + int listingId = listing["id"].asInteger(); + bool isListed = listing["is_listed"].asBoolean(); + std::string editUrl = listing["edit_url"].asString(); + LLUUID folderUuid = listing["inventory_info"]["listing_folder_id"].asUUID(); + LLUUID versionUuid = listing["inventory_info"]["version_folder_id"].asUUID(); + int count = listing["inventory_info"]["count_on_hand"].asInteger(); + + if (folderUuid.notNull()) + { + LLMarketplaceData::instance(). + addListing(folderUuid, listingId, versionUuid, isListed, editUrl, count); + } + } + + // Update all folders under the root + LLMarketplaceData::instance(). + setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_DONE); + update_marketplace_category(folderId, false); + gInventory.notifyObservers(); + } + virtual char const* getName() const { return "getSLMListings"; } +private: + LLUUID folderId; +}; + +class LLSLMCreateListingsResponder : public LLHTTPClient::ResponderWithCompleted +{ + LOG_CLASS(LLSLMCreateListingsResponder); +public: + + LLSLMCreateListingsResponder(const LLUUID& folder_id) + { + folderId = folder_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance().setUpdating(folderId, false); + + std::string body; + decode_raw_body(channels, buffer, body); + + LLSD result = LlsdFromJsonString(body); + if (result.isUndefined()) + { + log_SLM_warning("Post /listings", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response"); + return; + } + + if (!isGoodStatus(mStatus)) + { + log_SLM_warning("Post /listings", getStatus(), getReason(), LLStringUtil::null, result); + update_marketplace_category(folderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Post /listings", getStatus(), body); + + // Extract the info from the Json string + for (auto const& listing : result["listings"].array()) + { + int listing_id = listing["id"].asInteger(); + bool is_listed = listing["is_listed"].asBoolean(); + std::string edit_url = listing["edit_url"].asString(); + std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString(); + std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString(); + int count = listing["inventory_info"]["count_on_hand"].asInteger(); + + LLUUID folder_id(folder_uuid_string); + LLUUID version_id(version_uuid_string); + LLMarketplaceData::instance().addListing(folder_id,listing_id,version_id,is_listed,edit_url,count); + update_marketplace_category(folder_id, false); + gInventory.notifyObservers(); + } + } + virtual char const* getName() const { return "LLSLMCreateListingsResponder"; } +private: + LLUUID folderId; +}; + +class LLSLMGetListingResponder : public LLHTTPClient::ResponderWithCompleted +{ + LOG_CLASS(LLSLMGetListingResponder); +public: + + LLSLMGetListingResponder(const LLUUID& folder_id) + { + folderId = folder_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance(). + setUpdating(folderId, false); + + std::string body; + decode_raw_body(channels, buffer, body); + + LLSD result = LlsdFromJsonString(body); + if (result.isUndefined()) + { + log_SLM_warning("Get /listing", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response"); + return; + } + + if (!isGoodStatus(mStatus)) + { + if (getStatus() == HTTP_NOT_FOUND) + { + // That listing does not exist -> delete its record from the local SLM data store + LLMarketplaceData::instance(). + deleteListing(folderId, false); + } + else + { + log_SLM_warning("Get /listing", getStatus(), getReason(), LLStringUtil::null, result); + } + update_marketplace_category(folderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Get /listing", getStatus(), body); + + // Extract the info from the results + for (auto const& listing : result["listings"].array()) + { + int resListingId = listing["id"].asInteger(); + bool isListed = listing["is_listed"].asBoolean(); + std::string editUrl = listing["edit_url"].asString(); + LLUUID folderUuid = listing["inventory_info"]["listing_folder_id"].asUUID(); + LLUUID versionUuid = listing["inventory_info"]["version_folder_id"].asUUID(); + int count = listing["inventory_info"]["count_on_hand"].asInteger(); + + // Update that listing + LLMarketplaceData::instance(). + setListingID(folderUuid, resListingId, false); + LLMarketplaceData::instance(). + setVersionFolderID(folderUuid, versionUuid, false); + LLMarketplaceData::instance(). + setActivationState(folderUuid, isListed, false); + LLMarketplaceData::instance(). + setListingURL(folderUuid, editUrl, false); + LLMarketplaceData::instance(). + setCountOnHand(folderUuid, count, false); + update_marketplace_category(folderUuid, false); + gInventory.notifyObservers(); + } + } + virtual char const* getName() const { return "getSingleListingCoro"; } +private: + LLUUID folderId; +}; + +class LLSLMUpdateListingsResponder : public LLHTTPClient::ResponderWithCompleted +{ + LOG_CLASS(LLSLMUpdateListingsResponder); +public: + + LLSLMUpdateListingsResponder(const LLUUID& folder_id, bool expected_listed_state, const LLUUID& expected_version_id) + { + folderId = folder_id; + isListed = expected_listed_state; + versionId = expected_version_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance(). + setUpdating(folderId, false); + + std::string body; + decode_raw_body(channels, buffer, body); + + LLSD result = LlsdFromJsonString(body); + if (result.isUndefined()) + { + log_SLM_warning("Put /listing", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response"); + return; + } + + if (!isGoodStatus(mStatus)) + { + log_SLM_warning("Put /listing", getStatus(), getReason(), LLStringUtil::null, result); + update_marketplace_category(folderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Put /listing", getStatus(), body); + + // Extract the info from the Json string + for (auto const& listing : result["listings"].array()) + { + int listing_id = listing["id"].asInteger(); + bool is_listed = listing["is_listed"].asBoolean(); + std::string edit_url = listing["edit_url"].asString(); + LLUUID folderUuid = listing["inventory_info"]["listing_folder_id"].asUUID(); + LLUUID versionUuid = listing["inventory_info"]["version_folder_id"].asUUID(); + int onHand = listing["inventory_info"]["count_on_hand"].asInteger(); + + // Update that listing + LLMarketplaceData::instance(). + setListingID(folderUuid, listing_id, false); + LLMarketplaceData::instance(). + setVersionFolderID(folderUuid, versionUuid, false); + LLMarketplaceData::instance(). + setActivationState(folderUuid, is_listed, false); + LLMarketplaceData::instance(). + setListingURL(folderUuid, edit_url, false); + LLMarketplaceData::instance(). + setCountOnHand(folderUuid, onHand, false); + update_marketplace_category(folderUuid, false); + gInventory.notifyObservers(); + + // Show a notification alert if what we got is not what we expected + // (this actually doesn't result in an error status from the SLM API protocol) + if ((isListed != is_listed) || (versionId != versionUuid)) + { + LLSD subs; + subs["[URL]"] = edit_url; + LLNotificationsUtil::add("AlertMerchantListingNotUpdated", subs); + } + } + } + virtual char const* getName() const { return "updateSLMListingCoro"; } +private: + LLUUID folderId; + bool isListed; + LLUUID versionId; +}; + +class LLSLMAssociateListingsResponder : public LLHTTPClient::ResponderWithCompleted +{ + LOG_CLASS(LLSLMAssociateListingsResponder); +public: + + LLSLMAssociateListingsResponder(const LLUUID& folder_id, const LLUUID& source_folder_id) + { + folderId = folder_id; + sourceFolderId = source_folder_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance().setUpdating(folderId, false); + LLMarketplaceData::instance().setUpdating(sourceFolderId, false); + + std::string body; + decode_raw_body(channels, buffer, body); + + LLSD result = LlsdFromJsonString(body); + if (result.isUndefined()) + { + log_SLM_warning("Put /associate_inventory", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response"); + return; + } + + if (!isGoodStatus(mStatus)) + { + log_SLM_warning("Put /associate_inventory", getStatus(), getReason(), LLStringUtil::null, result); + update_marketplace_category(folderId, false); + update_marketplace_category(sourceFolderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Put /associate_inventory", getStatus(), body); + + for (auto const& listing : result["listings"].array()) + { + int listing_id = listing["id"].asInteger(); + bool is_listed = listing["is_listed"].asBoolean(); + std::string edit_url = listing["edit_url"].asString(); + LLUUID folder_uuid = listing["inventory_info"]["listing_folder_id"].asUUID(); + LLUUID version_uuid = listing["inventory_info"]["version_folder_id"].asUUID(); + int count = listing["inventory_info"]["count_on_hand"].asInteger(); + + // Check that the listing ID is not already associated to some other record + LLUUID old_listing = LLMarketplaceData::instance().getListingFolder(listing_id); + if (old_listing.notNull()) + { + // If it is already used, unlist the old record (we can't have 2 listings with the same listing ID) + LLMarketplaceData::instance().deleteListing(old_listing); + } + + // Add the new association + LLMarketplaceData::instance(). + addListing(folder_uuid, listing_id, version_uuid, is_listed, edit_url, count); + update_marketplace_category(folder_uuid, false); + gInventory.notifyObservers(); + + // The stock count needs to be updated with the new local count now + LLMarketplaceData::instance(). + updateCountOnHand(folder_uuid, 1); + } + + // Always update the source folder so its widget updates + update_marketplace_category(sourceFolderId, false); + } + + virtual char const* getName() const { return "associateSLMListingCoro"; } +private: + LLUUID folderId; // This is the folder now associated with the id. + LLUUID sourceFolderId; // This is the folder initially associated with the id. Can be LLUUID::null +}; + +class LLSLMDeleteListingsResponder : public LLHTTPClient::ResponderWithCompleted +{ + LOG_CLASS(LLSLMDeleteListingsResponder); +public: + + LLSLMDeleteListingsResponder(const LLUUID& folder_id) + { + folderId = folder_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance().setUpdating(folderId, false); + + std::string body; + decode_raw_body(channels, buffer, body); + LLSD result = LlsdFromJsonString(body); + if (result.isUndefined()) + { + log_SLM_warning("Delete /listing", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response"); + return; + } + + if (!isGoodStatus(mStatus)) + { + log_SLM_warning("Delete /listing", getStatus(), getReason(), LLStringUtil::null, result); + update_marketplace_category(folderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Delete /listing", getStatus(), body); + + for (auto const& listing : result["listings"].array()) + { + int listing_id = listing["id"].asInteger(); + LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id); + LLMarketplaceData::instance().deleteListing(folder_id); + } + } + virtual char const* getName() const { return "deleteSLMListingCoro"; } +private: + LLUUID folderId; +}; + +// SLM Responders End +/////////////////////////////////////////////////////////////////////////////// namespace LLMarketplaceImport { // Basic interface for this namespace - bool hasSessionCookie(); bool inProgress(); bool resultPending(); - U32 getResultStatus(); + S32 getResultStatus(); const LLSD& getResults(); bool establishMarketplaceSessionCookie(); @@ -138,12 +680,12 @@ namespace LLMarketplaceImport // Internal state variables - static std::string sMarketplaceCookie = ""; + static std::string sMarketplaceCookie; static LLSD sImportId = LLSD::emptyMap(); static bool sImportInProgress = false; static bool sImportPostPending = false; static bool sImportGetPending = false; - static U32 sImportResultStatus = 0; + static S32 sImportResultStatus = 0; static LLSD sImportResults = LLSD::emptyMap(); static LLTimer slmGetTimer; @@ -153,30 +695,32 @@ namespace LLMarketplaceImport class LLImportPostResponder : public LLHTTPClient::ResponderWithCompleted { + LOG_CLASS(LLImportPostResponder); public: - /*virtual*/ void httpCompleted(void) + void httpCompleted() override { slmPostTimer.stop(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - LL_INFOS() << " SLM POST status: " << mStatus << LL_ENDL; - LL_INFOS() << " SLM POST reason: " << mReason << LL_ENDL; - LL_INFOS() << " SLM POST content: " << mContent.asString() << LL_ENDL; - LL_INFOS() << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << LL_ENDL; + LL_INFOS() << " SLM [timer:" << slmPostTimer.getElapsedTimeF32() << "] " + << dumpResponse() << LL_ENDL; } - // MAINT-2301 : we determined we can safely ignore that error in that context - if (mStatus == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT) + S32 httpCode = getStatus(); + if ((httpCode == MarketplaceErrorCodes::IMPORT_REDIRECT) || + (httpCode == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || + // MAINT-2301 : we determined we can safely ignore that error in that context + (httpCode == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)) { if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { LL_INFOS() << " SLM POST : Ignoring time out status and treating it as success" << LL_ENDL; } - mStatus = MarketplaceErrorCodes::IMPORT_DONE; + httpCode = MarketplaceErrorCodes::IMPORT_DONE; } - if (mStatus >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) + if (httpCode >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) { if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { @@ -185,17 +729,19 @@ namespace LLMarketplaceImport sMarketplaceCookie.clear(); } - sImportInProgress = (mStatus == MarketplaceErrorCodes::IMPORT_DONE); + sImportInProgress = (httpCode == MarketplaceErrorCodes::IMPORT_DONE); sImportPostPending = false; - sImportResultStatus = mStatus; - sImportId = mContent; + sImportResultStatus = httpCode; + + sImportId = getContent(); } - /*virtual*/ char const* getName(void) const { return "LLImportPostResponder"; } + char const* getName() const override { return "LLImportPostResponder"; } }; class LLImportGetResponder : public LLHTTPClient::ResponderWithCompleted { + LOG_CLASS(LLImportGetResponder); public: /*virtual*/ bool needsHeaders(void) const { return true; } @@ -215,42 +761,42 @@ namespace LLMarketplaceImport } } - /*virtual*/ void httpCompleted(void) + /*virtual*/ void httpCompleted() { slmGetTimer.stop(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - LL_INFOS() << " SLM GET status: " << mStatus << LL_ENDL; - LL_INFOS() << " SLM GET reason: " << mReason << LL_ENDL; - LL_INFOS() << " SLM GET content: " << mContent.asString() << LL_ENDL; - LL_INFOS() << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << LL_ENDL; + LL_INFOS() << " SLM [timer:" << slmGetTimer.getElapsedTimeF32() << "] " + << dumpResponse() << LL_ENDL; } // MAINT-2452 : Do not clear the cookie on IMPORT_DONE_WITH_ERRORS : Happens when trying to import objects with wrong permissions // ACME-1221 : Do not clear the cookie on IMPORT_NOT_FOUND : Happens for newly created Merchant accounts that are initially empty - if ((mStatus >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) && - (mStatus != MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) && - (mStatus != MarketplaceErrorCodes::IMPORT_NOT_FOUND)) + S32 httpCode = getStatus(); + if ((httpCode >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) && + (httpCode != MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) && + (httpCode != MarketplaceErrorCodes::IMPORT_NOT_FOUND)) { if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - LL_INFOS() << " SLM GET clearing marketplace cookie due to client or server error (" << mStatus << " / " << mReason << ")." << LL_ENDL; + LL_INFOS() << " SLM GET clearing marketplace cookie due to client or server error" << LL_ENDL; } sMarketplaceCookie.clear(); } - else if (gSavedSettings.getBOOL("InventoryOutboxLogging") && (mStatus >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST)) + else if (gSavedSettings.getBOOL("InventoryOutboxLogging") && (httpCode >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST)) { - LL_INFOS() << " SLM GET : Got error status = " << mStatus << ", but marketplace cookie not cleared." << LL_ENDL; + LL_INFOS() << " SLM GET : Got error status = " << httpCode << ", but marketplace cookie not cleared." << LL_ENDL; } - sImportInProgress = (mStatus == MarketplaceErrorCodes::IMPORT_PROCESSING); + sImportInProgress = (httpCode == MarketplaceErrorCodes::IMPORT_PROCESSING); sImportGetPending = false; - sImportResultStatus = mStatus; - sImportResults = mContent; + sImportResultStatus = httpCode; + + sImportResults = getContent(); } - /*virtual*/ char const* getName(void) const { return "LLImportGetResponder"; } + char const* getName() const override { return "LLImportGetResponder"; } }; // Basic API @@ -270,7 +816,7 @@ namespace LLMarketplaceImport return (sImportPostPending || sImportGetPending); } - U32 getResultStatus() + S32 getResultStatus() { return sImportResultStatus; } @@ -307,8 +853,10 @@ namespace LLMarketplaceImport if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { LL_INFOS() << " SLM GET: establishMarketplaceSessionCookie, LLHTTPClient::get, url = " << url << LL_ENDL; + std::stringstream str; + str << headers; //LLSDSerialize::toPrettyXML(headers, str); LL_INFOS() << " SLM GET: headers " << LL_ENDL; - LL_INFOS() << headers << LL_ENDL; + LL_INFOS() << str.str() << LL_ENDL; } slmGetTimer.start(); @@ -334,14 +882,17 @@ namespace LLMarketplaceImport AIHTTPHeaders headers; headers.addHeader("Accept", "*/*"); headers.addHeader("Cookie", sMarketplaceCookie); + // *TODO: Why are we setting Content-Type for a GET request? headers.addHeader("Content-Type", "application/llsd+xml"); headers.addHeader("User-Agent", LLViewerMedia::getCurrentUserAgent()); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { LL_INFOS() << " SLM GET: pollStatus, LLHTTPClient::get, url = " << url << LL_ENDL; + std::stringstream str; + str << headers; //LLSDSerialize::toPrettyXML(headers, str); LL_INFOS() << " SLM GET: headers " << LL_ENDL; - LL_INFOS() << headers << LL_ENDL; + LL_INFOS() << str.str() << LL_ENDL; } slmGetTimer.start(); @@ -376,8 +927,10 @@ namespace LLMarketplaceImport if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { LL_INFOS() << " SLM POST: triggerImport, LLHTTPClient::post, url = " << url << LL_ENDL; + std::stringstream str; + str << headers; //LLSDSerialize::toPrettyXML(headers, str); LL_INFOS() << " SLM POST: headers " << LL_ENDL; - LL_INFOS() << headers << LL_ENDL; + LL_INFOS() << str.str() << LL_ENDL; } slmPostTimer.start(); @@ -403,7 +956,6 @@ void LLMarketplaceInventoryImporter::update() if (update_timer.hasExpired()) { LLMarketplaceInventoryImporter::instance().updateImport(); - //static LLCachedControl MARKET_IMPORTER_UPDATE_FREQUENCY("MarketImporterUpdateFreq", 1.0f); update_timer.setTimerExpirySec(MARKET_IMPORTER_UPDATE_FREQUENCY); } } @@ -509,54 +1061,967 @@ void LLMarketplaceInventoryImporter::updateImport() // If we are no longer in progress if (!mImportInProgress) { + // Look for results success + mInitialized = LLMarketplaceImport::hasSessionCookie(); + + // Report results + if (mStatusReportSignal) + { + (*mStatusReportSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + } + if (mInitialized) { - // Report results - if (mStatusReportSignal) + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MERCHANT; + // Follow up with auto trigger of import + if (mAutoTriggerImport) { - (*mStatusReportSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + mAutoTriggerImport = false; + mImportInProgress = triggerImport(); } } else { - // Look for results success - mInitialized = LLMarketplaceImport::hasSessionCookie(); + U32 status = LLMarketplaceImport::getResultStatus(); + if ((status == MarketplaceErrorCodes::IMPORT_FORBIDDEN) || + (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR)) + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT; + } + else if (status == MarketplaceErrorCodes::IMPORT_SERVER_API_DISABLED) + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MIGRATED_MERCHANT; + } + else + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE; + } + if (mErrorInitSignal && (mMarketPlaceStatus == MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE)) + { + (*mErrorInitSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + } + } + } + } + + // Make sure we trigger the status change with the final state (in case of auto trigger after initialize) + if (mStatusChangedSignal) + { + (*mStatusChangedSignal)(mImportInProgress); + } +} + +// +// Direct Delivery : Marketplace tuples and data +// +class LLMarketplaceInventoryObserver : public LLInventoryObserver +{ +public: + LLMarketplaceInventoryObserver() {} + virtual ~LLMarketplaceInventoryObserver() {} + virtual void changed(U32 mask); +}; + +void LLMarketplaceInventoryObserver::changed(U32 mask) +{ + // When things are added to the marketplace, we might need to re-validate and fix the containing listings + if (mask & LLInventoryObserver::ADD) + { + const uuid_set_t& changed_items = gInventory.getChangedIDs(); + + auto id_it = changed_items.begin(); + auto id_end = changed_items.end(); + // First, count the number of items in this list... + S32 count = 0; + for (;id_it != id_end; ++id_it) + { + LLInventoryObject* obj = gInventory.getObject(*id_it); + if (obj && (LLAssetType::AT_CATEGORY != obj->getType())) + { + count++; + } + } + // Then, decrement the folders of that amount + // Note that of all of those, only one folder will be a listing folder (if at all). + // The other will be ignored by the decrement method. + id_it = changed_items.begin(); + for (;id_it != id_end; ++id_it) + { + LLInventoryObject* obj = gInventory.getObject(*id_it); + if (obj && (LLAssetType::AT_CATEGORY == obj->getType())) + { + LLMarketplaceData::instance().decrementValidationWaiting(obj->getUUID(),count); + } + } + } + + // When things are changed in the inventory, this can trigger a host of changes in the marketplace listings folder: + // * stock counts changing : no copy items coming in and out will change the stock count on folders + // * version and listing folders : moving those might invalidate the marketplace data itself + // Since we should cannot raise inventory change while the observer is called (the list will be cleared + // once observers are called) we need to raise a flag in the inventory to signal that things have been dirtied. + + if (mask & (LLInventoryObserver::INTERNAL | LLInventoryObserver::STRUCTURE)) + { + const uuid_set_t& changed_items = gInventory.getChangedIDs(); - if (mInitialized) + auto id_it = changed_items.begin(); + auto id_end = changed_items.end(); + for (;id_it != id_end; ++id_it) + { + LLInventoryObject* obj = gInventory.getObject(*id_it); + if (obj) + { + if (LLAssetType::AT_CATEGORY == obj->getType()) { - mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MERCHANT; - // Follow up with auto trigger of import - if (mAutoTriggerImport) + // If it's a folder known to the marketplace, let's check it's in proper shape + if (LLMarketplaceData::instance().isListed(*id_it) || LLMarketplaceData::instance().isVersionFolder(*id_it)) { - mAutoTriggerImport = false; - mImportInProgress = triggerImport(); + LLInventoryCategory* cat = (LLInventoryCategory*)(obj); + validate_marketplacelistings(cat); } } else { - U32 status = LLMarketplaceImport::getResultStatus(); - if ((status == MarketplaceErrorCodes::IMPORT_FORBIDDEN) || - (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR)) - { - mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT; - } - else + // If it's not a category, it's an item... + LLInventoryItem* item = (LLInventoryItem*)(obj); + // If it's a no copy item, we may need to update the label count of marketplace listings + if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) { - mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE; - } - if (mErrorInitSignal && (mMarketPlaceStatus == MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE)) - { - (*mErrorInitSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + LLMarketplaceData::instance().setDirtyCount(); } } } } + } +} - // Make sure we trigger the status change with the final state (in case of auto trigger after initialize) - if (mStatusChangedSignal) - { - (*mStatusChangedSignal)(mImportInProgress); - } +// Tuple == Item +LLMarketplaceTuple::LLMarketplaceTuple() : + mListingFolderId(), + mListingId(0), + mVersionFolderId(), + mIsActive(false), + mEditURL("") +{ +} + +LLMarketplaceTuple::LLMarketplaceTuple(const LLUUID& folder_id) : + mListingFolderId(folder_id), + mListingId(0), + mVersionFolderId(), + mIsActive(false), + mEditURL("") +{ +} + +LLMarketplaceTuple::LLMarketplaceTuple(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed) : + mListingFolderId(folder_id), + mListingId(listing_id), + mVersionFolderId(version_id), + mIsActive(is_listed), + mEditURL("") +{ +} + + +// Data map +LLMarketplaceData::LLMarketplaceData() : + mMarketPlaceStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED), + mMarketPlaceDataFetched(MarketplaceFetchCodes::MARKET_FETCH_NOT_DONE), + mStatusUpdatedSignal(NULL), + mDataFetchedSignal(NULL), + mDirtyCount(false) +{ + mInventoryObserver = new LLMarketplaceInventoryObserver; + gInventory.addObserver(mInventoryObserver); +} + +LLMarketplaceData::~LLMarketplaceData() +{ + gInventory.removeObserver(mInventoryObserver); +} + +void LLMarketplaceData::initializeSLM(const status_updated_signal_t::slot_type& cb) +{ + if (mStatusUpdatedSignal == NULL) + { + mStatusUpdatedSignal = new status_updated_signal_t(); + } + mStatusUpdatedSignal->connect(cb); + + if (mMarketPlaceStatus != MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED) + { + // If already initialized, just confirm the status so the callback gets called + setSLMStatus(mMarketPlaceStatus); + } + else + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING; + } + + std::string url = getSLMConnectURL("/merchant"); + if (url.empty()) + { + LL_WARNS("Marketplace") << "No marketplace capability on Sim" << LL_ENDL; + setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE); + return; } + + log_SLM_infos("LLHTTPClient::get", url, LLStringUtil::null); + LLHTTPClient::get(url, new LLSLMGetMerchantResponder); +} + +void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot_type& cb) +{ + if (mDataFetchedSignal == NULL) + { + mDataFetchedSignal = new status_updated_signal_t(); + } + mDataFetchedSignal->connect(cb); +} + +// Get/Post/Put requests to the SLM Server using the SLM API +void LLMarketplaceData::getSLMListings() +{ + AIHTTPHeaders headers; + headers.addHeader("Accept", "application/json"); + headers.addHeader("Content-Type", "application/json"); + + // Send request + std::string url = getSLMConnectURL("/listings"); + log_SLM_infos("LLHTTPClient::get", url, ""); + const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + setUpdating(marketplacelistings_id, true); + LLHTTPClient::get(url, new LLSLMGetListingsResponder(marketplacelistings_id), headers); +} + +void LLMarketplaceData::getSLMListing(S32 listingId) +{ + LLUUID folderId = getListingFolder(listingId); + setUpdating(folderId, true); + + AIHTTPHeaders headers; + headers.addHeader("Accept", "application/json"); + headers.addHeader("Content-Type", "application/json"); + + // Send request + std::string url = getSLMConnectURL("/listing/") + llformat("%d", listingId); + log_SLM_infos("LLHTTPClient::get", url, LLStringUtil::null); + LLHTTPClient::get(url, new LLSLMGetListingResponder(folderId), headers); +} + +void LLMarketplaceData::createSLMListing(const LLUUID& folderId, const LLUUID& versionId, S32 count) +{ + AIHTTPHeaders headers; + headers.addHeader("Accept", "application/json"); + headers.addHeader("Content-Type", "application/json"); + + LLViewerInventoryCategory* category = gInventory.getCategory(folderId); + LLSD invInfo; + invInfo["listing_folder_id"] = folderId; + invInfo["version_folder_id"] = versionId; + invInfo["count_on_hand"] = count; + LLSD listing; + listing["name"] = category->getName(); + listing["inventory_info"] = invInfo; + LLSD postData; + postData["listing"] = listing; + + auto json = LlsdToJson(postData); + auto json_str = json.dump(); + + // postRaw() takes ownership of the buffer and releases it later. + size_t size = json_str.length(); + U8* data = new U8[size]; + memcpy(data, (U8*)(json_str.c_str()), size); + + // Send request + std::string url = getSLMConnectURL("/listings"); + log_SLM_infos("LLHTTPClient::postRaw", url, json_str); + setUpdating(folderId, true); + LLHTTPClient::postRaw(url, data, size, new LLSLMCreateListingsResponder(folderId), headers); +} + +void LLMarketplaceData::updateSLMListing(const LLUUID& folderId, S32 listingId, const LLUUID& versionId, bool isListed, S32 count) +{ + AIHTTPHeaders headers; + headers.addHeader("Accept", "application/json"); + headers.addHeader("Content-Type", "application/json"); + + // Note : auto unlist if the count is 0 (out of stock) + if (isListed && (count == 0)) + { + isListed = false; + LLNotificationsUtil::add("AlertMerchantStockFolderEmpty"); + } + + LLSD invInfo; + invInfo["listing_folder_id"] = folderId; + invInfo["version_folder_id"] = versionId; + invInfo["count_on_hand"] = count; + LLSD listing; + listing["inventory_info"] = invInfo; + listing["id"] = listingId; + listing["is_listed"] = isListed; + LLSD postData; + postData["listing"] = listing; + + auto json = LlsdToJson(postData); + auto json_str = json.dump(); + + // postRaw() takes ownership of the buffer and releases it later. + size_t size = json_str.size(); + U8* data = new U8[size]; + memcpy(data, (U8*)(json_str.c_str()), size); + + std::string url = getSLMConnectURL("/listing/") + llformat("%d", listingId); + log_SLM_infos("LLHTTPClient::putRaw", url, json_str); + setUpdating(folderId, true); + LLHTTPClient::putRaw(url, data, size, new LLSLMUpdateListingsResponder(folderId, isListed, versionId), headers); +} + +void LLMarketplaceData::associateSLMListing(const LLUUID& folderId, S32 listingId, const LLUUID& versionId, const LLUUID& sourceFolderId) +{ + AIHTTPHeaders headers; + headers.addHeader("Accept", "application/json"); + headers.addHeader("Content-Type", "application/json"); + + LLSD invInfo; + invInfo["listing_folder_id"] = folderId; + invInfo["version_folder_id"] = versionId; + LLSD listing; + listing["id"] = listingId; + listing["inventory_info"] = invInfo; + LLSD postData; + postData["listing"] = listing; + + auto json = LlsdToJson(postData); + auto json_str = json.dump(); + + // postRaw() takes ownership of the buffer and releases it later. + size_t size = json_str.size(); + U8* data = new U8[size]; + memcpy(data, (U8*)(json_str.c_str()), size); + + // Send request + std::string url = getSLMConnectURL("/associate_inventory/") + llformat("%d", listingId); + log_SLM_infos("LLHTTPClient::putRaw", url, json_str); + setUpdating(folderId, true); + setUpdating(sourceFolderId, true); + + LLHTTPClient::putRaw(url, data, size, new LLSLMAssociateListingsResponder(folderId, sourceFolderId), headers); +} + +void LLMarketplaceData::deleteSLMListing(S32 listingId) +{ + AIHTTPHeaders headers; + headers.addHeader("Accept", "application/json"); + headers.addHeader("Content-Type", "application/json"); + + // Send request + std::string url = getSLMConnectURL("/listing/") + llformat("%d", listingId); + log_SLM_infos("LLHTTPClient::del", url, ""); + LLUUID folderId = getListingFolder(listingId); + + setUpdating(folderId, true); + LLHTTPClient::del(url, new LLSLMDeleteListingsResponder(folderId), headers); +} + +std::string LLMarketplaceData::getSLMConnectURL(const std::string& route) +{ + std::string url; + LLViewerRegion* regionp = gAgent.getRegion(); + if (regionp) + { + // Get DirectDelivery cap + url = regionp->getCapability("DirectDelivery"); + if (!url.empty()) + { + url += route; + } + } + return url; +} + +void LLMarketplaceData::setSLMStatus(U32 status) +{ + mMarketPlaceStatus = status; + if (mStatusUpdatedSignal) + { + (*mStatusUpdatedSignal)(); + } +} + +void LLMarketplaceData::setSLMDataFetched(U32 status) +{ + mMarketPlaceDataFetched = status; + if (mDataFetchedSignal) + { + (*mDataFetchedSignal)(); + } +} + +// Creation / Deletion / Update +// Methods publicly called +bool LLMarketplaceData::createListing(const LLUUID& folder_id) +{ + if (isListed(folder_id)) + { + // Listing already exists -> exit with error + return false; + } + + // Get the version folder: if there is only one subfolder, we will set it as a version folder immediately + S32 count = -1; + LLUUID version_id = getVersionFolderIfUnique(folder_id); + if (version_id.notNull()) + { + count = compute_stock_count(version_id, true); + } + + // Validate the count on hand + if (count == COMPUTE_STOCK_NOT_EVALUATED) + { + // If the count on hand cannot be evaluated, we will consider it empty (out of stock) at creation time + // It will get reevaluated and updated once the items are fetched + count = 0; + } + + // Post the listing creation request to SLM + createSLMListing(folder_id, version_id, count); + + return true; +} + +bool LLMarketplaceData::clearListing(const LLUUID& folder_id, S32 depth) +{ + if (folder_id.isNull()) + { + // Folder doesn't exist -> exit with error + return false; + } + + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + // Folder id can be the root of the listing or not so we need to retrieve the root first + LLUUID listing_uuid = (isListed(folder_id) ? folder_id : nested_parent_id(folder_id, depth)); + S32 listing_id = getListingID(listing_uuid); + + if (listing_id == 0) + { + // Listing doesn't exist -> exit with error + return false; + } + + // Update the SLM Server so that this listing is deleted (actually, archived...) + deleteSLMListing(listing_id); + + return true; +} + +bool LLMarketplaceData::getListing(const LLUUID& folder_id, S32 depth) +{ + if (folder_id.isNull()) + { + // Folder doesn't exist -> exit with error + return false; + } + + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + // Folder id can be the root of the listing or not so we need to retrieve the root first + LLUUID listing_uuid = (isListed(folder_id) ? folder_id : nested_parent_id(folder_id, depth)); + S32 listing_id = getListingID(listing_uuid); + + if (listing_id == 0) + { + // Listing doesn't exist -> exit with error + return false; + } + + // Get listing data from SLM + getSLMListing(listing_id); + + return true; +} + +bool LLMarketplaceData::getListing(S32 listing_id) +{ + if (listing_id == 0) + { + return false; + } + + // Get listing data from SLM + getSLMListing(listing_id); + return true; +} + +bool LLMarketplaceData::activateListing(const LLUUID& folder_id, bool activate, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + // Folder id can be the root of the listing or not so we need to retrieve the root first + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + S32 listing_id = getListingID(listing_uuid); + if (listing_id == 0) + { + // Listing doesn't exist -> exit with error + return false; + } + + if (getActivationState(listing_uuid) == activate) + { + // If activation state is unchanged, no point spamming SLM with an update + return true; + } + + LLUUID version_uuid = getVersionFolder(listing_uuid); + + // Also update the count on hand + S32 count = compute_stock_count(folder_id); + if (count == COMPUTE_STOCK_NOT_EVALUATED) + { + // If the count on hand cannot be evaluated locally, we should not change that SLM value + // We are assuming that this issue is local and should not modify server side values + count = getCountOnHand(listing_uuid); + } + + // Post the listing update request to SLM + updateSLMListing(listing_uuid, listing_id, version_uuid, activate, count); + + return true; +} + +bool LLMarketplaceData::setVersionFolder(const LLUUID& folder_id, const LLUUID& version_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + // Folder id can be the root of the listing or not so we need to retrieve the root first + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + S32 listing_id = getListingID(listing_uuid); + if (listing_id == 0) + { + // Listing doesn't exist -> exit with error + return false; + } + + if (getVersionFolder(listing_uuid) == version_id) + { + // If version folder is unchanged, no point spamming SLM with an update + return true; + } + + // Note: if the version_id is cleared, we need to unlist the listing, otherwise, state unchanged + bool is_listed = (version_id.isNull() ? false : getActivationState(listing_uuid)); + + // Also update the count on hand + S32 count = compute_stock_count(version_id); + if (count == COMPUTE_STOCK_NOT_EVALUATED) + { + // If the count on hand cannot be evaluated, we will consider it empty (out of stock) when resetting the version folder + // It will get reevaluated and updated once the items are fetched + count = 0; + } + + // Post the listing update request to SLM + updateSLMListing(listing_uuid, listing_id, version_id, is_listed, count); + + return true; +} + +bool LLMarketplaceData::updateCountOnHand(const LLUUID& folder_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + // Folder id can be the root of the listing or not so we need to retrieve the root first + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + S32 listing_id = getListingID(listing_uuid); + if (listing_id == 0) + { + // Listing doesn't exist -> exit with error + return false; + } + + // Compute the new count on hand + S32 count = compute_stock_count(folder_id); + + if (count == getCountOnHand(listing_uuid)) + { + // If count on hand is unchanged, no point spamming SLM with an update + return true; + } + else if (count == COMPUTE_STOCK_NOT_EVALUATED) + { + // If local count on hand is not known at that point, do *not* force an update to SLM + return false; + } + + // Get the unchanged values + bool is_listed = getActivationState(listing_uuid); + LLUUID version_uuid = getVersionFolder(listing_uuid); + + + // Post the listing update request to SLM + updateSLMListing(listing_uuid, listing_id, version_uuid, is_listed, count); + + // Force the local value as it prevents spamming (count update may occur in burst when restocking) + // Note that if SLM has a good reason to return a different value, it'll be updated by the responder + setCountOnHand(listing_uuid, count, false); + + return true; +} + +bool LLMarketplaceData::associateListing(const LLUUID& folder_id, const LLUUID& source_folder_id, S32 listing_id) +{ + if (isListed(folder_id)) + { + // Listing already exists -> exit with error + return false; + } + + // Get the version folder: if there is only one subfolder, we will set it as a version folder immediately + LLUUID version_id = getVersionFolderIfUnique(folder_id); + + // Post the listing associate request to SLM + associateSLMListing(folder_id, listing_id, version_id, source_folder_id); + + return true; +} + +// Methods privately called or called by SLM responders to perform changes +bool LLMarketplaceData::addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, const std::string& edit_url, S32 count) +{ + mMarketplaceItems[folder_id] = LLMarketplaceTuple(folder_id, listing_id, version_id, is_listed); + mMarketplaceItems[folder_id].mEditURL = edit_url; + mMarketplaceItems[folder_id].mCountOnHand = count; + if (version_id.notNull()) + { + mVersionFolders[version_id] = folder_id; + } + return true; +} + +bool LLMarketplaceData::deleteListing(const LLUUID& folder_id, bool update) +{ + LLUUID version_folder = getVersionFolder(folder_id); + + if (mMarketplaceItems.erase(folder_id) != 1) + { + return false; + } + mVersionFolders.erase(version_folder); + + if (update) + { + update_marketplace_category(folder_id, false); + gInventory.notifyObservers(); + } + return true; +} + +bool LLMarketplaceData::deleteListing(S32 listing_id, bool update) +{ + if (listing_id == 0) + { + return false; + } + + LLUUID folder_id = getListingFolder(listing_id); + return deleteListing(folder_id, update); +} + +// Accessors +bool LLMarketplaceData::getActivationState(const LLUUID& folder_id) +{ + // Listing folder case + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it != mMarketplaceItems.end()) + { + return (it->second).mIsActive; + } + // Version folder case + version_folders_list_t::iterator it_version = mVersionFolders.find(folder_id); + if (it_version != mVersionFolders.end()) + { + marketplace_items_list_t::iterator it = mMarketplaceItems.find(it_version->second); + if (it != mMarketplaceItems.end()) + { + return (it->second).mIsActive; + } + } + return false; +} + +S32 LLMarketplaceData::getListingID(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it == mMarketplaceItems.end() ? 0 : (it->second).mListingId); +} + +S32 LLMarketplaceData::getCountOnHand(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it == mMarketplaceItems.end() ? -1 : (it->second).mCountOnHand); +} + +LLUUID LLMarketplaceData::getVersionFolder(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it == mMarketplaceItems.end() ? LLUUID::null : (it->second).mVersionFolderId); +} + +// Reverse lookup : find the listing folder id from the listing id +LLUUID LLMarketplaceData::getListingFolder(S32 listing_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.begin(); + while (it != mMarketplaceItems.end()) + { + if ((it->second).mListingId == listing_id) + { + return (it->second).mListingFolderId; + } + it++; + } + return LLUUID::null; +} + +std::string LLMarketplaceData::getListingURL(const LLUUID& folder_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + + marketplace_items_list_t::iterator it = mMarketplaceItems.find(listing_uuid); + return (it == mMarketplaceItems.end() ? "" : (it->second).mEditURL); +} + +bool LLMarketplaceData::isListed(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it != mMarketplaceItems.end()); +} + +bool LLMarketplaceData::isListedAndActive(const LLUUID& folder_id) +{ + return (isListed(folder_id) && getActivationState(folder_id)); +} + +bool LLMarketplaceData::isVersionFolder(const LLUUID& folder_id) +{ + version_folders_list_t::iterator it = mVersionFolders.find(folder_id); + return (it != mVersionFolders.end()); +} + +bool LLMarketplaceData::isInActiveFolder(const LLUUID& obj_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(obj_id); + + } + + LLUUID listing_uuid = nested_parent_id(obj_id, depth); + bool active = getActivationState(listing_uuid); + LLUUID version_uuid = getVersionFolder(listing_uuid); + return (active && ((obj_id == version_uuid) || gInventory.isObjectDescendentOf(obj_id, version_uuid))); +} + +LLUUID LLMarketplaceData::getActiveFolder(const LLUUID& obj_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(obj_id); + + } + + LLUUID listing_uuid = nested_parent_id(obj_id, depth); + return (getActivationState(listing_uuid) ? getVersionFolder(listing_uuid) : LLUUID::null); +} + +bool LLMarketplaceData::isUpdating(const LLUUID& folder_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + } + if ((depth <= 0) || (depth > 2)) + { + // Only listing and version folders though are concerned by that status + return false; + } + else + { + const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + auto it = mPendingUpdateSet.find(marketplace_listings_uuid); + if (it != mPendingUpdateSet.end()) + { + // If we're waiting for data for the marketplace listings root, we are in the updating process for all + return true; + } + else + { + // Check if the listing folder is waiting for data + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + it = mPendingUpdateSet.find(listing_uuid); + return (it != mPendingUpdateSet.end()); + } + } +} + +void LLMarketplaceData::setUpdating(const LLUUID& folder_id, bool isUpdating) +{ + auto it = mPendingUpdateSet.find(folder_id); + if (it != mPendingUpdateSet.end()) + { + mPendingUpdateSet.erase(it); + } + if (isUpdating) + { + mPendingUpdateSet.insert(folder_id); + } +} + +void LLMarketplaceData::setValidationWaiting(const LLUUID& folder_id, S32 count) +{ + mValidationWaitingList[folder_id] = count; +} + +void LLMarketplaceData::decrementValidationWaiting(const LLUUID& folder_id, S32 count) +{ + waiting_list_t::iterator found = mValidationWaitingList.find(folder_id); + if (found != mValidationWaitingList.end()) + { + found->second -= count; + if (found->second <= 0) + { + mValidationWaitingList.erase(found); + LLInventoryCategory *cat = gInventory.getCategory(folder_id); + validate_marketplacelistings(cat); + update_marketplace_category(folder_id); + gInventory.notifyObservers(); + } + } +} + +// Private Modifiers +bool LLMarketplaceData::setListingID(const LLUUID& folder_id, S32 listing_id, bool update) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + + (it->second).mListingId = listing_id; + + if (update) + { + update_marketplace_category(folder_id, false); + gInventory.notifyObservers(); + } + return true; +} + +bool LLMarketplaceData::setCountOnHand(const LLUUID& folder_id, S32 count, bool update) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + + (it->second).mCountOnHand = count; + + return true; +} + +bool LLMarketplaceData::setVersionFolderID(const LLUUID& folder_id, const LLUUID& version_id, bool update) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + + LLUUID old_version_id = (it->second).mVersionFolderId; + if (old_version_id == version_id) + { + return false; + } + + (it->second).mVersionFolderId = version_id; + mVersionFolders.erase(old_version_id); + if (version_id.notNull()) + { + mVersionFolders[version_id] = folder_id; + } + + if (update) + { + update_marketplace_category(old_version_id, false); + update_marketplace_category(version_id, false); + gInventory.notifyObservers(); + } + return true; +} + +bool LLMarketplaceData::setActivationState(const LLUUID& folder_id, bool activate, bool update) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + + (it->second).mIsActive = activate; + + if (update) + { + update_marketplace_category((it->second).mListingFolderId, false); + gInventory.notifyObservers(); + } + return true; +} + +bool LLMarketplaceData::setListingURL(const LLUUID& folder_id, const std::string& edit_url, bool update) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + + (it->second).mEditURL = edit_url; + return true; } diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h index d658775b94..91a7410181 100644 --- a/indra/newview/llmarketplacefunctions.h +++ b/indra/newview/llmarketplacefunctions.h @@ -30,10 +30,7 @@ #include -#ifndef BOOST_FUNCTION_HPP_INCLUDED #include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif #include #include "llsingleton.h" @@ -41,26 +38,24 @@ #include "llhttpstatuscodes.h" -LLSD getMarketplaceStringSubstitutions(); - namespace MarketplaceErrorCodes { enum eCode { - IMPORT_DONE = HTTP_OK, - IMPORT_PROCESSING = HTTP_ACCEPTED, - IMPORT_REDIRECT = HTTP_FOUND, - IMPORT_BAD_REQUEST = HTTP_BAD_REQUEST, - IMPORT_AUTHENTICATION_ERROR = HTTP_UNAUTHORIZED, - IMPORT_FORBIDDEN = HTTP_FORBIDDEN, - IMPORT_NOT_FOUND = HTTP_NOT_FOUND, - IMPORT_DONE_WITH_ERRORS = HTTP_CONFLICT, - IMPORT_JOB_FAILED = HTTP_GONE, + IMPORT_DONE = 200, + IMPORT_PROCESSING = 202, + IMPORT_REDIRECT = 302, + IMPORT_BAD_REQUEST = 400, + IMPORT_AUTHENTICATION_ERROR = 401, + IMPORT_FORBIDDEN = 403, + IMPORT_NOT_FOUND = 404, + IMPORT_DONE_WITH_ERRORS = 409, + IMPORT_JOB_FAILED = 410, IMPORT_JOB_LOW_SPEED = HTTP_INTERNAL_ERROR_LOW_SPEED, - IMPORT_JOB_TIMEOUT = HTTP_INTERNAL_ERROR_CURL_TIMEOUT, - IMPORT_SERVER_SITE_DOWN = HTTP_INTERNAL_SERVER_ERROR, - IMPORT_SERVER_API_DISABLED = HTTP_SERVICE_UNAVAILABLE, + IMPORT_JOB_TIMEOUT = 499, + IMPORT_SERVER_SITE_DOWN = 500, + IMPORT_SERVER_API_DISABLED = 503, }; } @@ -71,8 +66,21 @@ namespace MarketplaceStatusCodes MARKET_PLACE_NOT_INITIALIZED = 0, MARKET_PLACE_INITIALIZING = 1, MARKET_PLACE_CONNECTION_FAILURE = 2, - MARKET_PLACE_MERCHANT = 3, - MARKET_PLACE_NOT_MERCHANT = 4, + MARKET_PLACE_NOT_MERCHANT = 3, + MARKET_PLACE_MERCHANT = 4, + MARKET_PLACE_NOT_MIGRATED_MERCHANT = 5, + MARKET_PLACE_MIGRATED_MERCHANT = 6 + }; +} + +namespace MarketplaceFetchCodes +{ + enum sCode + { + MARKET_FETCH_NOT_DONE = 0, + MARKET_FETCH_LOADING = 1, + MARKET_FETCH_FAILED = 2, + MARKET_FETCH_DONE = 3 }; } @@ -114,6 +122,167 @@ class LLMarketplaceInventoryImporter }; +// Classes handling the data coming from and going to the Marketplace SLM Server DB: +// * implement the Marketplace API +// * cache the current Marketplace data (tuples) +// * provide methods to get Marketplace data on any inventory item +// * set Marketplace data +// * signal Marketplace updates to inventory +namespace SLMErrorCodes +{ + enum eCode + { + SLM_SUCCESS = 200, + SLM_RECORD_CREATED = 201, + SLM_MALFORMED_PAYLOAD = 400, + SLM_NOT_FOUND = 404, + }; +} + +class LLMarketplaceData; +class LLInventoryObserver; + +// A Marketplace item is known by its tuple +class LLMarketplaceTuple +{ +public: + friend class LLMarketplaceData; + + LLMarketplaceTuple(); + LLMarketplaceTuple(const LLUUID& folder_id); + LLMarketplaceTuple(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed = false); + +private: + // Representation of a marketplace item in the Marketplace DB (well, what we know of it...) + LLUUID mListingFolderId; + S32 mListingId; + LLUUID mVersionFolderId; + bool mIsActive; + S32 mCountOnHand; + std::string mEditURL; +}; +// Notes: +// * The mListingFolderId is used as a key to this map. It could therefore be taken off the LLMarketplaceTuple objects themselves. +// * The SLM DB however uses mListingId as its primary key and it shows in its API. In the viewer though, the mListingFolderId is what we use to grab an inventory record. +typedef std::map marketplace_items_list_t; +typedef std::map version_folders_list_t; + +// Session cache of all Marketplace tuples +// Notes: +// * There's one and only one possible set of Marketplace dataset per agent and per session thus making it an LLSingleton +// * Some of those records might correspond to folders that do not exist in the inventory anymore. We do not clear them out though. They just won't show up in the UI. + +class LLSLMGetMerchantResponder; +class LLSLMGetListingsResponder; +class LLSLMCreateListingsResponder; +class LLSLMGetListingResponder; +class LLSLMUpdateListingsResponder; +class LLSLMAssociateListingsResponder; +class LLSLMDeleteListingsResponder; + +class LLMarketplaceData + : public LLSingleton +{ +public: + friend class LLSLMGetMerchantResponder; + friend class LLSLMGetListingsResponder; + friend class LLSLMCreateListingsResponder; + friend class LLSLMGetListingResponder; + friend class LLSLMUpdateListingsResponder; + friend class LLSLMAssociateListingsResponder; + friend class LLSLMDeleteListingsResponder; + + static LLSD getMarketplaceStringSubstitutions(); + LLMarketplaceData(); + virtual ~LLMarketplaceData(); + + // Public SLM API : Initialization and status + typedef boost::signals2::signal status_updated_signal_t; + void initializeSLM(const status_updated_signal_t::slot_type& cb); + U32 getSLMStatus() const { return mMarketPlaceStatus; } + void setSLMStatus(U32 status); + void getSLMListings(); + bool isEmpty() const { return (mMarketplaceItems.size() == 0); } + void setDataFetchedSignal(const status_updated_signal_t::slot_type& cb); + void setSLMDataFetched(U32 status); + U32 getSLMDataFetched() { return mMarketPlaceDataFetched; } + + // High level create/delete/set Marketplace data: each method returns true if the function succeeds, false if error + bool createListing(const LLUUID& folder_id); + bool activateListing(const LLUUID& folder_id, bool activate, S32 depth = -1); + bool clearListing(const LLUUID& folder_id, S32 depth = -1); + bool setVersionFolder(const LLUUID& folder_id, const LLUUID& version_id, S32 depth = -1); + bool associateListing(const LLUUID& folder_id, const LLUUID& source_folder_id, S32 listing_id); + bool updateCountOnHand(const LLUUID& folder_id, S32 depth = -1); + bool getListing(const LLUUID& folder_id, S32 depth = -1); + bool getListing(S32 listing_id); + bool deleteListing(S32 listing_id, bool update = true); + + // Probe the Marketplace data set to identify folders + bool isListed(const LLUUID& folder_id); // returns true if folder_id is a Listing folder + bool isListedAndActive(const LLUUID& folder_id); // returns true if folder_id is an active (listed) Listing folder + bool isVersionFolder(const LLUUID& folder_id); // returns true if folder_id is a Version folder + bool isInActiveFolder(const LLUUID& obj_id, S32 depth = -1); // returns true if the obj_id is buried in an active version folder + LLUUID getActiveFolder(const LLUUID& obj_id, S32 depth = -1); // returns the UUID of the active version folder obj_id is in + bool isUpdating(const LLUUID& folder_id, S32 depth = -1); // returns true if we're waiting from SLM incoming data for folder_id + + // Access Marketplace data set : each method returns a default value if the argument can't be found + bool getActivationState(const LLUUID& folder_id); + S32 getListingID(const LLUUID& folder_id); + LLUUID getVersionFolder(const LLUUID& folder_id); + std::string getListingURL(const LLUUID& folder_id, S32 depth = -1); + LLUUID getListingFolder(S32 listing_id); + S32 getCountOnHand(const LLUUID& folder_id); + + // Used to flag if stock count values for Marketplace have to be updated + bool checkDirtyCount() { if (mDirtyCount) { mDirtyCount = false; return true; } else { return false; } } + void setDirtyCount() { mDirtyCount = true; } + void setUpdating(const LLUUID& folder_id, bool isUpdating); + + // Used to decide when to run a validation on listing folders + void setValidationWaiting(const LLUUID& folder_id, S32 count); + void decrementValidationWaiting(const LLUUID& folder_id, S32 count = 1); + +private: + // Modify Marketplace data set : each method returns true if the function succeeds, false if error + // Used internally only by SLM Responders when data are received from the SLM Server + bool addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, const std::string& edit_url, S32 count); + bool deleteListing(const LLUUID& folder_id, bool update = true); + bool setListingID(const LLUUID& folder_id, S32 listing_id, bool update = true); + bool setVersionFolderID(const LLUUID& folder_id, const LLUUID& version_id, bool update = true); + bool setActivationState(const LLUUID& folder_id, bool activate, bool update = true); + bool setListingURL(const LLUUID& folder_id, const std::string& edit_url, bool update = true); + bool setCountOnHand(const LLUUID& folder_id, S32 count, bool update = true); + + // Private SLM API : package data and get/post/put requests to the SLM Server through the SLM API + void createSLMListing(const LLUUID& folder_id, const LLUUID& version_id, S32 count); + void getSLMListing(S32 listing_id); + void updateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, S32 count); + void associateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, const LLUUID& source_folder_id); + void deleteSLMListing(S32 listing_id); + std::string getSLMConnectURL(const std::string& route); + + // Handling Marketplace connection and inventory connection + U32 mMarketPlaceStatus; + status_updated_signal_t* mStatusUpdatedSignal; + LLInventoryObserver* mInventoryObserver; + bool mDirtyCount; // If true, stock count value need to be updated at the next check + + // Update data + U32 mMarketPlaceDataFetched; + status_updated_signal_t* mDataFetchedSignal; + uuid_set_t mPendingUpdateSet; + + // Listing folders waiting for validation + typedef std::map waiting_list_t; + waiting_list_t mValidationWaitingList; + + // The cache of SLM data (at last...) + marketplace_items_list_t mMarketplaceItems; + // We need a list (version folder -> listing folder) because such reverse lookups are frequent + version_folders_list_t mVersionFolders; +}; + #endif // LL_LLMARKETPLACEFUNCTIONS_H diff --git a/indra/newview/llmarketplacenotifications.cpp b/indra/newview/llmarketplacenotifications.cpp index 0886f9a990..8944d293ff 100644 --- a/indra/newview/llmarketplacenotifications.cpp +++ b/indra/newview/llmarketplacenotifications.cpp @@ -33,10 +33,6 @@ #include "llerror.h" -#include -#include - - namespace LLMarketplaceInventoryNotifications { typedef boost::signals2::signal no_copy_payload_cb_signal_t; @@ -54,7 +50,7 @@ namespace LLMarketplaceInventoryNotifications llassert(!no_copy_payloads.empty()); llassert(no_copy_cb_action != NULL); - BOOST_FOREACH(const LLSD& payload, no_copy_payloads) + for (const LLSD& payload : no_copy_payloads) { (*no_copy_cb_action)(payload); } diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index b659653fe2..7ccded7883 100644 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -134,7 +134,7 @@ LLMaterialMgr::~LLMaterialMgr() bool LLMaterialMgr::isGetPending(const LLUUID& region_id, const LLMaterialID& material_id) const { get_pending_map_t::const_iterator itPending = mGetPending.find(pending_material_t(region_id, material_id)); - return (mGetPending.end() != itPending) && (LLFrameTimer::getTotalSeconds() < itPending->second + MATERIALS_POST_TIMEOUT); + return (mGetPending.end() != itPending) && (LLFrameTimer::getTotalSeconds() < itPending->second + F64(MATERIALS_POST_TIMEOUT)); } void LLMaterialMgr::markGetPending(const LLUUID& region_id, const LLMaterialID& material_id) @@ -270,7 +270,7 @@ boost::signals2::connection LLMaterialMgr::getTE(const LLUUID& region_id, const bool LLMaterialMgr::isGetAllPending(const LLUUID& region_id) const { getall_pending_map_t::const_iterator itPending = mGetAllPending.find(region_id); - return (mGetAllPending.end() != itPending) && (LLFrameTimer::getTotalSeconds() < itPending->second + MATERIALS_GET_TIMEOUT); + return (mGetAllPending.end() != itPending) && (LLFrameTimer::getTotalSeconds() < itPending->second + F64(MATERIALS_GET_TIMEOUT)); } void LLMaterialMgr::getAll(const LLUUID& region_id) @@ -328,6 +328,25 @@ void LLMaterialMgr::remove(const LLUUID& object_id, const U8 te) put(object_id, te, LLMaterial::null); } +void LLMaterialMgr::setLocalMaterial(const LLUUID& region_id, LLMaterialPtr material_ptr) +{ + LLUUID uuid; + uuid.generate(); + LLMaterialID material_id(uuid); + while (mMaterials.end() != mMaterials.find(material_id)) + { //probability that this loop will executed is very, very low (one in a billion chance) + uuid.generate(); + material_id.set(uuid.mData); + } + + LL_DEBUGS("Materials") << "region " << region_id << "new local material id " << material_id << LL_ENDL; + mMaterials.insert(std::pair(material_id, material_ptr)); + + setMaterialCallbacks(material_id, material_ptr); + + mGetPending.erase(pending_material_t(region_id, material_id)); +} + const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LLMaterialID& material_id, const LLSD& material_data) { LL_DEBUGS("Materials") << "region " << region_id << " material id " << material_id << LL_ENDL; @@ -340,17 +359,26 @@ const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LL itMaterial = ret.first; } + setMaterialCallbacks(material_id, itMaterial->second); + + mGetPending.erase(pending_material_t(region_id, material_id)); + + return itMaterial->second; +} + +void LLMaterialMgr::setMaterialCallbacks(const LLMaterialID& material_id, const LLMaterialPtr material_ptr) +{ TEMaterialPair te_mat_pair; te_mat_pair.materialID = material_id; U32 i = 0; - while (i < LLTEContents::MAX_TES) + while (i < LLTEContents::MAX_TES && !mGetTECallbacks.empty()) { te_mat_pair.te = i++; get_callback_te_map_t::iterator itCallbackTE = mGetTECallbacks.find(te_mat_pair); if (itCallbackTE != mGetTECallbacks.end()) { - (*itCallbackTE->second)(material_id, itMaterial->second, te_mat_pair.te); + (*itCallbackTE->second)(material_id, material_ptr, te_mat_pair.te); delete itCallbackTE->second; mGetTECallbacks.erase(itCallbackTE); } @@ -359,15 +387,11 @@ const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LL get_callback_map_t::iterator itCallback = mGetCallbacks.find(material_id); if (itCallback != mGetCallbacks.end()) { - (*itCallback->second)(material_id, itMaterial->second); + (*itCallback->second)(material_id, material_ptr); delete itCallback->second; mGetCallbacks.erase(itCallback); } - - mGetPending.erase(pending_material_t(region_id, material_id)); - - return itMaterial->second; } void LLMaterialMgr::onGetResponse(bool success, const LLSD& content, const LLUUID& region_id) @@ -396,9 +420,8 @@ void LLMaterialMgr::onGetResponse(bool success, const LLSD& content, const LLUUI llassert(response_data.isArray()); LL_DEBUGS("Materials") << "response has "<< response_data.size() << " materials" << LL_ENDL; - for (LLSD::array_const_iterator itMaterial = response_data.beginArray(); itMaterial != response_data.endArray(); ++itMaterial) + for (auto const& material_data : response_data.array()) { - const LLSD& material_data = *itMaterial; llassert(material_data.isMap()); llassert(material_data.has(MATERIALS_CAP_OBJECT_ID_FIELD)); @@ -441,9 +464,8 @@ void LLMaterialMgr::onGetAllResponse(bool success, const LLSD& content, const LL llassert(response_data.isArray()); LL_DEBUGS("Materials") << "response has "<< response_data.size() << " materials" << LL_ENDL; - for (LLSD::array_const_iterator itMaterial = response_data.beginArray(); itMaterial != response_data.endArray(); ++itMaterial) + for (auto const& material_data : response_data.array()) { - const LLSD& material_data = *itMaterial; llassert(material_data.isMap()); llassert(material_data.has(MATERIALS_CAP_OBJECT_ID_FIELD)); @@ -507,11 +529,9 @@ void LLMaterialMgr::onPutResponse(bool success, const LLSD& content) { llassert(response_data.isArray()); LL_DEBUGS("Materials") << "response has "<< response_data.size() << " materials" << LL_ENDL; - for (LLSD::array_const_iterator faceIter = response_data.beginArray(); faceIter != response_data.endArray(); ++faceIter) +#ifdef SHOW_ASSERT + for (auto const& face_data : response_data.array()) { -# ifndef LL_RELEASE_FOR_DOWNLOAD - const LLSD& face_data = *faceIter; // conditional to avoid unused variable warning -# endif llassert(face_data.isMap()); llassert(face_data.has(MATERIALS_CAP_OBJECT_ID_FIELD)); @@ -528,14 +548,15 @@ void LLMaterialMgr::onPutResponse(bool success, const LLSD& content) // *TODO: do we really still need to process this? } +#endif } } -static LLFastTimer::DeclareTimer FTM_MATERIALS_IDLE("Materials"); +static LLTrace::BlockTimerStatHandle FTM_MATERIALS_IDLE("Materials"); void LLMaterialMgr::onIdle(void*) { - LLFastTimer t(FTM_MATERIALS_IDLE); + LL_RECORD_BLOCK_TIME(FTM_MATERIALS_IDLE); LLMaterialMgr* instancep = LLMaterialMgr::getInstance(); @@ -562,7 +583,7 @@ void LLMaterialMgr::processGetQueue() { get_queue_t::iterator itRegionQueue = loopRegionQueue++; - const LLUUID& region_id = itRegionQueue->first; + const LLUUID region_id = itRegionQueue->first; if (isGetAllPending(region_id)) { continue; @@ -600,12 +621,12 @@ void LLMaterialMgr::processGetQueue() material_queue_t& materials = itRegionQueue->second; U32 max_entries = regionp->getMaxMaterialsPerTransaction(); material_queue_t::iterator loopMaterial = materials.begin(); - while ( (materials.end() != loopMaterial) && (materialsData.size() < (int)max_entries) ) + while ( (materials.end() != loopMaterial) && ((U32)materialsData.size() < max_entries) ) { material_queue_t::iterator itMaterial = loopMaterial++; materialsData.append((*itMaterial).asLLSD()); - materials.erase(itMaterial); markGetPending(region_id, *itMaterial); + materials.erase(itMaterial); } if (materials.empty()) { @@ -706,7 +727,7 @@ void LLMaterialMgr::processPutQueue() facematerial_map_t& face_map = itQueue->second; U32 max_entries = regionp->getMaxMaterialsPerTransaction(); facematerial_map_t::iterator itFace = face_map.begin(); - while ( (face_map.end() != itFace) && (facesData.size() < (int)max_entries) ) + while ( (face_map.end() != itFace) && ((U32)facesData.size() < max_entries) ) { LLSD faceData = LLSD::emptyMap(); faceData[MATERIALS_CAP_FACE_FIELD] = static_cast(itFace->first); diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index e83f1f4e01..b20fed92fd 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -55,14 +55,17 @@ class LLMaterialMgr : public LLSingleton boost::signals2::connection getAll(const LLUUID& region_id, getall_callback_t::slot_type cb); void put(const LLUUID& object_id, const U8 te, const LLMaterial& material); void remove(const LLUUID& object_id, const U8 te); - -protected: + + //explicitly add new material to material manager + void setLocalMaterial(const LLUUID& region_id, LLMaterialPtr material_ptr); + +private: void clearGetQueues(const LLUUID& region_id); bool isGetPending(const LLUUID& region_id, const LLMaterialID& material_id) const; bool isGetAllPending(const LLUUID& region_id) const; void markGetPending(const LLUUID& region_id, const LLMaterialID& material_id); const LLMaterialPtr setMaterial(const LLUUID& region_id, const LLMaterialID& material_id, const LLSD& material_data); - + void setMaterialCallbacks(const LLMaterialID& material_id, const LLMaterialPtr material_ptr); static void onIdle(void*); void processGetQueue(); void onGetResponse(bool success, const LLSD& content, const LLUUID& region_id); @@ -72,15 +75,6 @@ class LLMaterialMgr : public LLSingleton void onPutResponse(bool success, const LLSD& content); void onRegionRemoved(LLViewerRegion* regionp); -protected: - typedef std::set material_queue_t; - typedef std::map get_queue_t; - get_queue_t mGetQueue; - typedef std::pair pending_material_t; - typedef std::map get_pending_map_t; - get_pending_map_t mGetPending; - typedef std::map get_callback_map_t; - get_callback_map_t mGetCallbacks; // struct for TE-specific material ID query class TEMaterialPair @@ -108,22 +102,32 @@ class LLMaterialMgr : public LLSingleton bool operator()(const TEMaterialPair& left, const TEMaterialPair& right) const { return left < right; } }; - typedef boost::unordered_map get_callback_te_map_t; - get_callback_te_map_t mGetTECallbacks; + typedef std::set material_queue_t; + typedef std::map get_queue_t; + typedef std::pair pending_material_t; + typedef std::map get_pending_map_t; + typedef std::map get_callback_map_t; + + typedef boost::unordered_map get_callback_te_map_t; typedef std::set getall_queue_t; - getall_queue_t mGetAllQueue; - getall_queue_t mGetAllRequested; typedef std::map getall_pending_map_t; - getall_pending_map_t mGetAllPending; typedef std::map getall_callback_map_t; - getall_callback_map_t mGetAllCallbacks; - typedef std::map facematerial_map_t; typedef std::map put_queue_t; - put_queue_t mPutQueue; - material_map_t mMaterials; + + get_queue_t mGetQueue; + get_pending_map_t mGetPending; + get_callback_map_t mGetCallbacks; + + get_callback_te_map_t mGetTECallbacks; + getall_queue_t mGetAllQueue; + getall_queue_t mGetAllRequested; + getall_pending_map_t mGetAllPending; + getall_callback_map_t mGetAllCallbacks; + put_queue_t mPutQueue; + material_map_t mMaterials; U32 getMaxEntries(const LLViewerRegion* regionp); }; diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index ef98d11dc3..fe5b50253c 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -54,6 +54,7 @@ #include "llviewermenu.h" // linden library includes +#include "llclipboard.h" #include "llfocusmgr.h" #include "llsdutil.h" #include "lltextbox.h" @@ -70,14 +71,14 @@ LLMediaCtrl::Params::Params() : start_url("start_url"), border_visible("border_visible", false), decouple_texture_size("decouple_texture_size", false), + trusted_content("trusted_content", false), + focus_on_click("focus_on_click", true), texture_width("texture_width", 1024), texture_height("texture_height", 1024), caret_color("caret_color"), initial_mime_type("initial_mime_type"), - error_page_url("error_page_url"), media_id("media_id"), - trusted_content("trusted_content", false), - focus_on_click("focus_on_click", true) + error_page_url("error_page_url") { } @@ -85,24 +86,25 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : LLPanel( p.name, p.rect, FALSE), LLInstanceTracker(LLUUID::generateNewID()), mTextureDepthBytes( 4 ), - mBorder(NULL), + mBorder(nullptr), mFrequentUpdates( true ), mForceUpdate( false ), - mHomePageUrl( "" ), + mTrusted(p.trusted_content), mAlwaysRefresh( false ), - mMediaSource( 0 ), mTakeFocusOnClick( p.focus_on_click ), - mCurrentNavUrl( "about:blank" ), mStretchToFill( true ), mMaintainAspectRatio ( true ), - mDecoupleTextureSize ( false ), - mTextureWidth ( 1024 ), - mTextureHeight ( 1024 ), mClearCache(false), + mHoverTextChanged(false), + mDecoupleTextureSize ( false ), + mUpdateScrolls( false ), + mHomePageUrl( "" ), mHomePageMimeType(p.initial_mime_type), + mCurrentNavUrl( "about:blank" ), mErrorPageURL(p.error_page_url), - mTrusted(p.trusted_content), - mHoverTextChanged(false), + mMediaSource( nullptr ), + mTextureWidth ( 1024 ), + mTextureHeight ( 1024 ), mContextMenu() { { @@ -140,10 +142,17 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : LLMediaCtrl::~LLMediaCtrl() { + auto menu = mContextMenu.get(); + if (menu) + { + menu->die(); + mContextMenu.markDead(); + } + if (mMediaSource) { mMediaSource->remObserver( this ); - mMediaSource = NULL; + mMediaSource = nullptr; } } @@ -157,7 +166,9 @@ void LLMediaCtrl::setBorderVisible( BOOL border_visible ) addChild( mBorder ); } if(mBorder) + { mBorder->setVisible(border_visible); + } }; //////////////////////////////////////////////////////////////////////////////// @@ -196,7 +207,10 @@ BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks ) { if (LLPanel::handleScrollWheel(x, y, clicks)) return TRUE; if (mMediaSource && mMediaSource->hasMedia()) - mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE)); + { + convertInputCoords(x, y); + mMediaSource->scrollWheel(x, y, 0, clicks, gKeyboard->currentMask(TRUE)); + } return TRUE; } @@ -240,7 +254,7 @@ BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) mMediaSource->mouseUp(x, y, mask); } - gFocusMgr.setMouseCapture( NULL ); + gFocusMgr.setMouseCapture(nullptr ); return TRUE; } @@ -285,7 +299,7 @@ BOOL LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask ) } } - gFocusMgr.setMouseCapture( NULL ); + gFocusMgr.setMouseCapture(nullptr ); return TRUE; } @@ -309,12 +323,19 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask ) setFocus( TRUE ); } - LLMenuGL* menu = (LLMenuGL*)mContextMenu.get(); - if (menu) + auto con_menu = (LLMenuGL*)mContextMenu.get(); + if (con_menu) { - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this,menu, x, y); + /* Singu Note: Share your toys!! + // hide/show debugging options + bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); + con_menu->setItemVisible("open_webinspector", media_plugin_debugging_enabled ); + con_menu->setItemVisible("debug_separator", media_plugin_debugging_enabled ); + */ + + con_menu->buildDrawLabels(); + con_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, con_menu, x, y); } return TRUE; @@ -366,7 +387,7 @@ void LLMediaCtrl::onFocusLost() if( LLEditMenuHandler::gEditMenuHandler == mMediaSource ) { // Clear focus for edit menu items - LLEditMenuHandler::gEditMenuHandler = NULL; + LLEditMenuHandler::gEditMenuHandler = nullptr; } } @@ -379,22 +400,43 @@ void LLMediaCtrl::onFocusLost() // BOOL LLMediaCtrl::postBuild () { - LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_media_ctrl.xml",LLMenuGL::sMenuContainer); + /*LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; + registar.add("Copy.PageURL", boost::bind(&LLMediaCtrl::onCopyURL, this)); + registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this)); + registar.add("Open.ViewSource", boost::bind(&LLMediaCtrl::onShowSource, this)); + + // stinson 05/05/2014 : use this as the parent of the context menu if the static menu + // container has yet to be created + LLView* menuParent = (gMenuHolder != nullptr) ? dynamic_cast(gMenuHolder) : dynamic_cast(this); + llassert(menuParent != NULL);*/ + auto menu = LLUICtrlFactory::getInstance()->buildMenu("menu_media_ctrl.xml",LLMenuGL::sMenuContainer); if(menu) { mContextMenu = menu->getHandle(); } - setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2)); + setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2)); return true; } +void LLMediaCtrl::onCopyURL() const +{ + auto wurl = utf8str_to_wstring(mCurrentNavUrl); + gClipboard.copyFromSubstring(wurl, 0, wurl.size()); +} + void LLMediaCtrl::onOpenWebInspector() { if (mMediaSource && mMediaSource->hasMedia()) mMediaSource->getMediaPlugin()->showWebInspector( true ); } +void LLMediaCtrl::onShowSource() +{ + if (mMediaSource && mMediaSource->hasMedia()) + mMediaSource->getMediaPlugin()->showPageSource(); +} + //////////////////////////////////////////////////////////////////////////////// // BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) @@ -412,6 +454,23 @@ BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) return result; } +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLMediaCtrl::handleKeyUpHere(KEY key, MASK mask) +{ + BOOL result = FALSE; + + if (mMediaSource) + { + result = mMediaSource->handleKeyUpHere(key, mask); + } + + if (!result) + result = LLPanel::handleKeyUpHere(key, mask); + + return result; +} + //////////////////////////////////////////////////////////////////////////////// // void LLMediaCtrl::handleVisibilityChange ( BOOL new_visibility ) @@ -429,12 +488,9 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) { BOOL result = FALSE; - // only accept 'printable' characters, sigh... - if (uni_char >= 32 // discard 'control' characters - && uni_char != 127) // SDL thinks this is 'delete' - yuck. + if (mMediaSource) { - if (mMediaSource) - result = mMediaSource->handleUnicodeCharHere(uni_char); + result = mMediaSource->handleUnicodeCharHere(uni_char); } if ( ! result ) @@ -445,7 +501,7 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) //////////////////////////////////////////////////////////////////////////////// // -void LLMediaCtrl::onVisibilityChange ( const LLSD& new_visibility ) +void LLMediaCtrl::onVisibilityChanged( const LLSD& new_visibility ) { // set state of frequent updates automatically if visibility changes if ( new_visibility.asBoolean() ) @@ -497,6 +553,16 @@ void LLMediaCtrl::navigateForward() } } +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::navigateStop() +{ + if (mMediaSource && mMediaSource->hasMedia()) + { + mMediaSource->getMediaPlugin()->browse_stop(); + } +} + //////////////////////////////////////////////////////////////////////////////// // bool LLMediaCtrl::canNavigateBack() @@ -534,23 +600,7 @@ void LLMediaCtrl::clearCache() //////////////////////////////////////////////////////////////////////////////// // -void LLMediaCtrl::set404RedirectUrl( std::string redirect_url ) -{ - if(mMediaSource && mMediaSource->hasMedia()) - mMediaSource->getMediaPlugin()->set_status_redirect( 404, redirect_url ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLMediaCtrl::clr404RedirectUrl() -{ - if(mMediaSource && mMediaSource->hasMedia()) - mMediaSource->getMediaPlugin()->set_status_redirect(404, ""); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) +void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type, bool clean_browser) { // don't browse to anything that starts with secondlife:// or sl:// const std::string protocol1 = "secondlife://"; @@ -565,12 +615,9 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) if (ensureMediaSourceExists()) { - if (mCurrentNavUrl != url_in) - { - mCurrentNavUrl = url_in; - mMediaSource->setSize(mTextureWidth, mTextureHeight); - mMediaSource->navigateTo(url_in, mime_type, mime_type.empty()); - } + mCurrentNavUrl = url_in; + mMediaSource->setSize(mTextureWidth, mTextureHeight); + mMediaSource->navigateTo(url_in, mime_type, mime_type.empty(), false, clean_browser); } } @@ -578,15 +625,9 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) // void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::string& filename_in ) { - std::string language = LLUI::getLanguage(); std::string filename(gDirUtilp->add(subdir, filename_in)); + std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", filename); - std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", language, filename); - - if (expanded_filename.empty() && language != "en-us") - { - expanded_filename = gDirUtilp->findSkinnedFilename("html", "en-us", filename); - } if(expanded_filename.empty()) { LL_WARNS() << "File " << filename << "not found" << LL_ENDL; @@ -598,7 +639,6 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str mMediaSource->setSize(mTextureWidth, mTextureHeight); mMediaSource->navigateTo(LLWeb::escapeURL(expanded_filename), "text/html", false); } - } //////////////////////////////////////////////////////////////////////////////// @@ -688,7 +728,13 @@ bool LLMediaCtrl::ensureMediaSourceExists() mMediaSource->addObserver( this ); mMediaSource->setBackgroundColor( getBackgroundColor() ); mMediaSource->setTrustedBrowser(mTrusted); - mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); + + F32 scale_factor = LLUI::getScaleFactor().mV[ VX ]; + if (scale_factor != mMediaSource->getPageZoomFactor()) + { + mMediaSource->setPageZoomFactor( scale_factor ); + mUpdateScrolls = true; + } if(mClearCache) { @@ -710,7 +756,11 @@ bool LLMediaCtrl::ensureMediaSourceExists() // void LLMediaCtrl::unloadMediaSource() { - mMediaSource = NULL; + if (mMediaSource) + { + mMediaSource->remObserver(this); + mMediaSource = nullptr; + } } //////////////////////////////////////////////////////////////////////////////// @@ -724,10 +774,11 @@ LLPluginClassMedia* LLMediaCtrl::getMediaPlugin() // void LLMediaCtrl::draw() { - if ( gRestoreGL == 1 ) + if ( gRestoreGL == 1 || mUpdateScrolls) { LLRect r = getRect(); reshape( r.getWidth(), r.getHeight(), FALSE ); + mUpdateScrolls = false; return; } @@ -745,12 +796,12 @@ void LLMediaCtrl::draw() // alpha off for this LLGLSUIDefault gls_ui; - LLGLDisable gls_alphaTest( GL_ALPHA_TEST ); + LLGLDisable gls_alpha_test; bool draw_media = false; - LLPluginClassMedia* media_plugin = NULL; - LLViewerMediaTexture* media_texture = NULL; + LLPluginClassMedia* media_plugin = nullptr; + LLViewerMediaTexture* media_texture = nullptr; if(mMediaSource && mMediaSource->hasMedia()) { @@ -773,7 +824,12 @@ void LLMediaCtrl::draw() { gGL.pushUIMatrix(); { - mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); + F32 scale_factor = LLUI::getScaleFactor().mV[ VX ]; + if (scale_factor != mMediaSource->getPageZoomFactor()) + { + mMediaSource->setPageZoomFactor( scale_factor ); + mUpdateScrolls = true; + } // scale texture to fit the space using texture coords gGL.getTexUnit(0)->bind(media_texture); @@ -782,56 +838,12 @@ void LLMediaCtrl::draw() F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth(); F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight(); - LLRect r = getRect(); - S32 width, height; - S32 x_offset = 0; - S32 y_offset = 0; - - if(mStretchToFill) - { - if(mMaintainAspectRatio) - { - F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight()); - F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight()); - if(media_aspect > view_aspect) - { - // max width, adjusted height - width = r.getWidth(); - height = llmin(llmax(ll_round(width / media_aspect), 0), r.getHeight()); - } - else - { - // max height, adjusted width - height = r.getHeight(); - width = llmin(llmax(ll_round(height * media_aspect), 0), r.getWidth()); - } - } - else - { - width = r.getWidth(); - height = r.getHeight(); - } - } - else - { - width = llmin(media_plugin->getWidth(), r.getWidth()); - height = llmin(media_plugin->getHeight(), r.getHeight()); - } - - x_offset = (r.getWidth() - width) / 2; - y_offset = (r.getHeight() - height) / 2; - - /*if (mIgnoreUIScale) - { - x_offset = ll_round((F32)x_offset * LLUI::getScaleFactor().mV[VX]); - y_offset = ll_round((F32)y_offset * LLUI::getScaleFactor().mV[VY]); - width = ll_round((F32)width * LLUI::getScaleFactor().mV[VX]); - height = ll_round((F32)height * LLUI::getScaleFactor().mV[VY]); - }*/ + S32 x_offset, y_offset, width, height; + calcOffsetsAndSize(&x_offset, &y_offset, &width, &height); // draw the browser gGL.setSceneBlendType(LLRender::BT_REPLACE); - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLE_STRIP ); if (! media_plugin->getTextureCoordsOpenGL()) { // render using web browser reported width and height, instead of trying to invert GL scale @@ -841,11 +853,11 @@ void LLMediaCtrl::draw() gGL.texCoord2f( 0.f, 0.f ); gGL.vertex2i( x_offset, y_offset + height ); + gGL.texCoord2f(max_u, max_v); + gGL.vertex2i(x_offset + width, y_offset); + gGL.texCoord2f( 0.f, max_v ); gGL.vertex2i( x_offset, y_offset ); - - gGL.texCoord2f( max_u, max_v ); - gGL.vertex2i( x_offset + width, y_offset ); } else { @@ -856,11 +868,11 @@ void LLMediaCtrl::draw() gGL.texCoord2f( 0.f, max_v ); gGL.vertex2i( x_offset, y_offset + height ); + gGL.texCoord2f(max_u, 0.f); + gGL.vertex2i(x_offset + width, y_offset); + gGL.texCoord2f( 0.f, 0.f ); gGL.vertex2i( x_offset, y_offset ); - - gGL.texCoord2f( max_u, 0.f ); - gGL.vertex2i( x_offset + width, y_offset ); } gGL.end(); gGL.setSceneBlendType(LLRender::BT_ALPHA); @@ -886,6 +898,50 @@ void LLMediaCtrl::draw() setBackgroundOpaque(background_opaque); } +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::calcOffsetsAndSize(S32 *x_offset, S32 *y_offset, S32 *width, S32 *height) +{ + const LLRect &r = getRect(); + *x_offset = *y_offset = 0; + + const auto& media_plugin = mMediaSource->getMediaPlugin(); + + if(mStretchToFill) + { + if(mMaintainAspectRatio) + { + F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight()); + F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight()); + if(media_aspect > view_aspect) + { + // max width, adjusted height + *width = r.getWidth(); + *height = llmin(llmax(ll_round(*width / media_aspect), 0), r.getHeight()); + } + else + { + // max height, adjusted width + *height = r.getHeight(); + *width = llmin(llmax(ll_round(*height * media_aspect), 0), r.getWidth()); + } + } + else + { + *width = r.getWidth(); + *height = r.getHeight(); + } + } + else + { + *width = llmin(media_plugin->getWidth(), r.getWidth()); + *height = llmin(media_plugin->getHeight(), r.getHeight()); + } + + *x_offset = (r.getWidth() - *width) / 2; + *y_offset = (r.getHeight() - *height) / 2; +} + //////////////////////////////////////////////////////////////////////////////// // void LLMediaCtrl::convertInputCoords(S32& x, S32& y) @@ -940,7 +996,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL; } break; - + case MEDIA_EVENT_NAVIGATE_BEGIN: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL; @@ -989,27 +1045,36 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) case MEDIA_EVENT_CLICK_LINK_HREF: { - LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL; // retrieve the event parameters std::string url = self->getClickURL(); std::string target = self->getClickTarget(); std::string uuid = self->getClickUUID(); + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL; - LLNotification::Params notify_params("PopupAttempt"); - notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID); - notify_params.functor(boost::bind(&LLMediaCtrl::onPopup, this, _1, _2)); - - if (mTrusted) - { - LLNotifications::instance().forceResponse(notify_params, 0); - } - else + // try as slurl first + if (!LLURLDispatcher::dispatch(url, "clicked", nullptr, mTrusted)) { - LLNotifications::instance().add(notify_params); + LLWeb::loadURL(url, target, uuid); } + + // CP: removing this code because we no longer support popups so this breaks the flow. + // replaced with a bare call to LLWeb::LoadURL(...) + //LLNotification::Params notify_params; + //notify_params.name = "PopupAttempt"; + //notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID); + //notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2); + + //if (mTrusted) + //{ + // LLNotifications::instance().forceResponse(notify_params, 0); + //} + //else + //{ + // LLNotifications::instance().add(notify_params); + //} break; }; - + case MEDIA_EVENT_CLICK_LINK_NOFOLLOW: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL; @@ -1076,9 +1141,33 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) }; break; + case MEDIA_EVENT_FILE_DOWNLOAD: + { + //llinfos << "Media event - file download requested - filename is " << self->getFileDownloadFilename() << llendl; + //LLNotificationsUtil::add("MediaFileDownloadUnsupported"); + }; + break; + case MEDIA_EVENT_DEBUG_MESSAGE: { - LL_INFOS("media") << self->getDebugMessageText() << LL_ENDL; + std::string level = self->getDebugMessageLevel(); + if (level == "debug") + { + LL_DEBUGS("Media") << self->getDebugMessageText() << LL_ENDL; + } + else if (level == "info") + { + LL_INFOS("Media") << self->getDebugMessageText() << LL_ENDL; + } + else if (level == "warn") + { + LL_WARNS("Media") << self->getDebugMessageText() << LL_ENDL; + } + else if (level == "error") + { + LL_ERRS("Media") << self->getDebugMessageText() << LL_ENDL; + } + }; break; @@ -1099,7 +1188,7 @@ std::string LLMediaCtrl::getCurrentNavUrl() return mCurrentNavUrl; } -bool LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) +void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) { if (response["open"]) { @@ -1110,7 +1199,6 @@ bool LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) // Make sure the opening instance knows its window open request was denied, so it can clean things up. LLViewerMedia::proxyWindowClosed(notification["payload"]["uuid"]); } - return FALSE; } void LLMediaCtrl::showNotification(LLNotificationPtr notify) @@ -1142,6 +1230,16 @@ void LLMediaCtrl::setTrustedContent(bool trusted) } } +bool LLMediaCtrl::wantsKeyUpKeyDown() const +{ + return true; +} + +bool LLMediaCtrl::wantsReturnKey() const +{ + return true; +} + // virtual LLXMLNodePtr LLMediaCtrl::getXML(bool save_children) const { diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 306d686500..87c17413f6 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -2,31 +2,25 @@ * @file llmediactrl.h * @brief Web browser UI control * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * 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. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,6 +31,7 @@ #include "lluictrl.h" #include "llframetimer.h" +#include "llnotificationptr.h" class LLViewBorder; class LLUICtrlFactory; @@ -51,6 +46,7 @@ class LLMediaCtrl : { LOG_CLASS(LLMediaCtrl); public: + struct Params : public LLInitParam::Block { Optional start_url; @@ -88,24 +84,25 @@ class LLMediaCtrl : // Defaults to true. void setTakeFocusOnClick( bool take_focus ); - virtual LLXMLNodePtr getXML(bool save_children = true) const; + virtual LLXMLNodePtr getXML(bool save_children = true) const override; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); // handle mouse related methods - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen); + BOOL handleHover( S32 x, S32 y, MASK mask ) override; + BOOL handleMouseUp( S32 x, S32 y, MASK mask ) override; + BOOL handleMouseDown( S32 x, S32 y, MASK mask ) override; + BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; + BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) override; + BOOL handleDoubleClick( S32 x, S32 y, MASK mask ) override; + BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ) override; + BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) override; // navigation - void navigateTo( std::string url_in, std::string mime_type = ""); + void navigateTo( std::string url_in, std::string mime_type = "", bool clean_browser = false); void navigateBack(); void navigateHome(); void navigateForward(); + void navigateStop(); void navigateToLocalPage( const std::string& subdir, const std::string& filename_in ); bool canNavigateBack(); bool canNavigateForward(); @@ -128,9 +125,6 @@ class LLMediaCtrl : // Clear the browser cache when the instance gets loaded void clearCache(); - void set404RedirectUrl( std::string redirect_url ); - void clr404RedirectUrl(); - // accessor/mutator for flag that indicates if frequent updates to texture happen bool getFrequentUpdates() { return mFrequentUpdates; }; void setFrequentUpdates( bool frequentUpdatesIn ) { mFrequentUpdates = frequentUpdatesIn; }; @@ -153,37 +147,49 @@ class LLMediaCtrl : void setTextureSize(S32 width, S32 height); - void showNotification(boost::shared_ptr notify); + void showNotification(LLNotificationPtr notify); void hideNotification(); void setTrustedContent(bool trusted); // over-rides - virtual BOOL handleKeyHere( KEY key, MASK mask); - virtual void handleVisibilityChange ( BOOL new_visibility ); - virtual BOOL handleUnicodeCharHere(llwchar uni_char); - virtual void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE); - virtual void draw(); - virtual BOOL postBuild(); + BOOL handleKeyHere( KEY key, MASK mask) override; + BOOL handleKeyUpHere(KEY key, MASK mask) override; + void handleVisibilityChange ( BOOL new_visibility ) override; + BOOL handleUnicodeCharHere(llwchar uni_char) override; + void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE) override; + void draw() override; + BOOL postBuild() override; // focus overrides - void onFocusLost(); - void onFocusReceived(); + void onFocusLost() override; + void onFocusReceived() override; // Incoming media event dispatcher - virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override; + void onCopyURL() const; // right click debugging item void onOpenWebInspector(); + void onShowSource(); LLUUID getTextureID() {return mMediaTextureID;} + // The Browser windows want keyup and keydown events. Overridden from LLFocusableElement to return true. + bool wantsKeyUpKeyDown() const override; + bool wantsReturnKey() const override; + + virtual BOOL acceptsTextInput() const override { return TRUE; } + protected: void convertInputCoords(S32& x, S32& y); private: - void onVisibilityChange ( const LLSD& new_visibility ); - bool onPopup(const LLSD& notification, const LLSD& response); + void calcOffsetsAndSize(S32 *x_offset, S32 *y_offset, S32 *width, S32 *height); + + private: + void onVisibilityChanged ( const LLSD& new_visibility ); + void onPopup(const LLSD& notification, const LLSD& response); const S32 mTextureDepthBytes; LLUUID mMediaTextureID; @@ -199,7 +205,8 @@ class LLMediaCtrl : mHidingInitialLoad, mClearCache, mHoverTextChanged, - mDecoupleTextureSize; + mDecoupleTextureSize, + mUpdateScrolls; std::string mHomePageUrl, mHomePageMimeType, diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index 304f7050b0..2690e39581 100644 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -28,13 +28,6 @@ #include "llmediadataclient.h" -#if LL_MSVC -// disable boost::lexical_cast warning -#pragma warning (disable:4702) -#endif - -#include - #include "llhttpstatuscodes.h" #include "llsdutil.h" #include "llmediaentry.h" diff --git a/indra/newview/llmediafilter.cpp b/indra/newview/llmediafilter.cpp index 528dfc86fa..9ab66af5af 100644 --- a/indra/newview/llmediafilter.cpp +++ b/indra/newview/llmediafilter.cpp @@ -161,9 +161,9 @@ void LLMediaFilter::addToMediaList(const std::string& in_url, EMediaList list, b string_list_t& p_list(list == WHITELIST ? mWhiteList : mBlackList); // Check for duplicates - for (string_list_t::const_iterator itr = p_list.begin(); itr != p_list.end(); ++itr) + for (const auto& p : p_list) { - if (url == *itr) + if (url == p) { LL_INFOS("MediaFilter") << "URL " << url << " already in list!" << LL_ENDL; return; @@ -177,8 +177,8 @@ void LLMediaFilter::addToMediaList(const std::string& in_url, EMediaList list, b void LLMediaFilter::removeFromMediaList(string_vec_t domains, EMediaList list) { if (domains.empty()) return; - for (string_vec_t::const_iterator itr = domains.begin(); itr != domains.end(); ++itr) - (list == WHITELIST ? mWhiteList : mBlackList).remove(*itr); + for (const auto& domain : domains) + (list == WHITELIST ? mWhiteList : mBlackList).remove(domain); mMediaListUpdate(list); saveMediaFilterToDisk(); } @@ -221,10 +221,10 @@ void LLMediaFilter::loadMediaFilterFromDisk() void medialist_to_llsd(const LLMediaFilter::string_list_t& list, LLSD& list_llsd, const LLSD& action) { - for (LLMediaFilter::string_list_t::const_iterator itr = list.begin(); itr != list.end(); ++itr) + for (const auto& domain : list) { LLSD item; - item["domain"] = *itr; + item["domain"] = domain; item["action"] = action; list_llsd.append(item); } @@ -352,13 +352,13 @@ bool handle_media_filter_callback(const LLSD& notification, const LLSD& response LLParcel* queue = inst.getQueuedMedia(); switch(option) { - case 2: // Whitelist domain + case 3: // Whitelist domain inst.addToMediaList(url, LLMediaFilter::WHITELIST); case 0: // Allow if (inst.getCurrentParcel() == LLViewerParcelMgr::getInstance()->getAgentParcel()) LLViewerParcelMedia::play(parcel); break; - case 3: // Blacklist domain + case 2: // Blacklist domain inst.addToMediaList(url, LLMediaFilter::BLACKLIST); case 1: // Deny break; diff --git a/indra/newview/llmediaremotectrl.cpp b/indra/newview/llmediaremotectrl.cpp index c044496dc1..e6d0aece19 100644 --- a/indra/newview/llmediaremotectrl.cpp +++ b/indra/newview/llmediaremotectrl.cpp @@ -192,7 +192,7 @@ void LLMediaRemoteCtrl::enableMediaButtons() play_media_enabled = true; media_icon_color = LLUI::sColorsGroup->getColor( "IconEnabledColor" ); - + /* LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus(); switch(status) { @@ -216,6 +216,18 @@ void LLMediaRemoteCtrl::enableMediaButtons() // inherit defaults above break; } + */ + if (LLViewerMedia::isParcelMediaPlaying()) + { + stop_media_enabled = true; + play_media_enabled = false; + } + else + { + stop_media_enabled = false; + play_media_enabled = true; + } + // } } @@ -277,7 +289,7 @@ void LLMediaRemoteCtrl::enableMediaButtons() { sLastTooltip = info_text; LLChat chat; - chat.mText = getString("Now_playing") + " " + info_text; + chat.mText = getString("Now_playing") + ' ' + info_text; chat.mSourceType = CHAT_SOURCE_SYSTEM; // Lie to RLVa so it won't filter this chat.mRlvLocFiltered = true; diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp index e7684b0349..01bf1fd7f0 100644 --- a/indra/newview/llmenucommands.cpp +++ b/indra/newview/llmenucommands.cpp @@ -64,6 +64,7 @@ #include "llfloaterdisplayname.h" #include "llfloatereditui.h" #include "llfloaterenvsettings.h" +#include "llfloaterexperiences.h" #include "llfloaterexploreanimations.h" #include "llfloaterexploresounds.h" #include "llfloaterfonttest.h" @@ -73,16 +74,15 @@ #include "llfloaterinspect.h" #include "llfloaterinventory.h" #include "llfloaterjoystick.h" -#include "llfloaterlagmeter.h" #include "llfloaterland.h" #include "llfloaterlandholdings.h" #include "llfloatermap.h" +#include "llfloatermarketplacelistings.h" #include "llfloatermediafilter.h" #include "llfloatermemleak.h" #include "llfloatermessagelog.h" #include "llfloatermute.h" #include "llfloaternotificationsconsole.h" -#include "llfloateroutbox.h" #include "llfloaterpathfindingcharacters.h" #include "llfloaterpathfindinglinksets.h" #include "llfloaterperms.h" @@ -120,6 +120,7 @@ void handle_debug_avatar_textures(void*); template void handle_singleton_toggle(void*); void show_outfit_dialog() { new LLMakeOutfitDialog(false); } +class LLFloaterExperiencePicker* show_xp_picker(const LLSD& key); void toggle_build() { LLToolMgr::getInstance()->toggleBuildMode(); } void toggle_control(const std::string& name) { if (LLControlVariable* control = gSavedSettings.getControl(name)) control->set(!control->get()); } void toggle_search_floater(); @@ -127,7 +128,7 @@ void toggle_always_run() { gAgent.getAlwaysRun() ? gAgent.clearAlwaysRun() : gAg void toggle_sit(); void toggle_mouselook() { gAgentCamera.cameraMouselook() ? gAgentCamera.changeCameraToDefault() : gAgentCamera.changeCameraToMouselook(); } -bool is_visible_view(boost::function get) +bool is_visible_view(std::function get) { if (LLView* v = get()) return v->getVisible(); @@ -145,9 +146,9 @@ struct CommWrapper static void toggleInstance(const LLSD& key) { only_comm() ? LLFloaterChatterBox::toggleInstance(key) : LLFloaterMyFriends::toggleInstance(key); } }; -struct MenuFloaterDict : public LLSingleton +struct MenuFloaterDict final : public LLSingleton { - typedef std::map, boost::function > > menu_floater_map_t; + typedef std::map, std::function>> menu_floater_map_t; menu_floater_map_t mEntries; MenuFloaterDict() @@ -163,10 +164,9 @@ struct MenuFloaterDict : public LLSingleton registerConsole("texture size console", gTextureSizeView); } registerConsole("velocity", gVelocityBar); - registerFloater("about", boost::bind(&LLFloaterAbout::show,(void*)NULL)); + registerFloater("about", boost::bind(&LLFloaterAbout::show,nullptr)); registerFloater("always run", boost::bind(toggle_always_run), boost::bind(&LLAgent::getAlwaysRun, &gAgent)); registerFloater("anims_explorer", boost::bind(LLFloaterExploreAnimations::show)); - registerFloater("ao", boost::bind(LLFloaterAO::show, (void*)NULL)); registerFloater("appearance", boost::bind(LLFloaterCustomize::show)); registerFloater("asset_blacklist", boost::bind(LLFloaterBlacklist::toggle), boost::bind(LLFloaterBlacklist::visible)); registerFloater("build", boost::bind(toggle_build)); @@ -174,46 +174,46 @@ struct MenuFloaterDict : public LLSingleton registerFloater("buy land", boost::bind(&LLViewerParcelMgr::startBuyLand, boost::bind(LLViewerParcelMgr::getInstance), false)); registerFloater("complaint reporter", boost::bind(LLFloaterReporter::showFromMenu, COMPLAINT_REPORT)); registerFloater("DayCycle", boost::bind(LLFloaterDayCycle::show), boost::bind(LLFloaterDayCycle::isOpen)); - registerFloater("debug avatar", boost::bind(handle_debug_avatar_textures, (void*)NULL)); - registerFloater("debug settings", boost::bind(handle_singleton_toggle, (void*)NULL)); - registerFloater("edit ui", boost::bind(LLFloaterEditUI::show, (void*)NULL)); + registerFloater("debug avatar", boost::bind(handle_debug_avatar_textures, nullptr)); + registerFloater("debug settings", boost::bind(handle_singleton_toggle, nullptr)); + registerFloater("edit ui", boost::bind(LLFloaterEditUI::show, nullptr)); registerFloater("EnvSettings", boost::bind(LLFloaterEnvSettings::show), boost::bind(LLFloaterEnvSettings::isOpen)); + registerFloater("experience_search", boost::bind(show_xp_picker, LLSD())); registerFloater("fly", boost::bind(LLAgent::toggleFlying)); - registerFloater("font test", boost::bind(LLFloaterFontTest::show, (void*)NULL)); - registerFloater("god tools", boost::bind(LLFloaterGodTools::show, (void*)NULL)); - registerFloater("grid options", boost::bind(LLFloaterBuildOptions::show, (void*)NULL)); + registerFloater("font test", boost::bind(LLFloaterFontTest::show, nullptr)); + registerFloater("god tools", boost::bind(LLFloaterGodTools::show, nullptr)); + registerFloater("grid options", boost::bind(LLFloaterBuildOptions::show, nullptr)); registerFloater("group titles", boost::bind(HBFloaterGroupTitles::toggle)); //Singu TODO: Re-implement f1 help. //registerFloater("help f1", boost::bind(/*gViewerHtmlHelp.show*/)); registerFloater("help tutorial", boost::bind(LLFloaterHUD::showHUD)); - registerFloater("inventory", boost::bind(LLInventoryView::toggleVisibility, (void*)NULL), boost::bind(is_visible_view, static_cast >(LLInventoryView::getActiveInventory))); + registerFloater("inventory", boost::bind(LLPanelMainInventory::toggleVisibility, nullptr), boost::bind(is_visible_view, static_cast >(LLPanelMainInventory::getActiveInventory))); registerFloater("local assets", boost::bind(FloaterLocalAssetBrowser::show, (void*)0)); - registerFloater("mean events", boost::bind(LLFloaterBump::show, (void*)NULL)); - registerFloater("media ticker", boost::bind(handle_ticker_toggle, (void*)NULL), boost::bind(SHFloaterMediaTicker::instanceExists)); - registerFloater("memleak", boost::bind(LLFloaterMemLeak::show, (void*)NULL)); + registerFloater("mean events", boost::bind(LLFloaterBump::show, nullptr)); + registerFloater("media ticker", boost::bind(handle_ticker_toggle, nullptr), boost::bind(SHFloaterMediaTicker::instanceExists)); + registerFloater("memleak", boost::bind(LLFloaterMemLeak::show, nullptr)); registerFloater("messagelog", boost::bind(LLFloaterMessageLog::show)); registerFloater("mouselook", boost::bind(toggle_mouselook)); - registerFloater("my land", boost::bind(LLFloaterLandHoldings::show, (void*)NULL)); + registerFloater("my land", boost::bind(LLFloaterLandHoldings::show, nullptr)); registerFloater("outfit", boost::bind(show_outfit_dialog)); - registerFloater("PostProcess", boost::bind(LLFloaterPostProcess::show)); - registerFloater("preferences", boost::bind(LLFloaterPreference::show, (void*)NULL)); + registerFloater("preferences", boost::bind(LLFloaterPreference::show, nullptr)); registerFloater("quit", boost::bind(&LLAppViewer::userQuit, LLAppViewer::instance())); - registerFloater("RegionDebugConsole", boost::bind(handle_singleton_toggle, (void*)NULL), boost::bind(LLFloaterRegionDebugConsole::instanceExists)); + registerFloater("RegionDebugConsole", boost::bind(handle_singleton_toggle, nullptr), boost::bind(LLFloaterRegionDebugConsole::instanceExists)); registerFloater("script errors", boost::bind(LLFloaterScriptDebug::show, LLUUID::null)); registerFloater("search", boost::bind(toggle_search_floater)); registerFloater("show inspect", boost::bind(LLFloaterInspect::showInstance, LLSD())); registerFloater("sit", boost::bind(toggle_sit)); - registerFloater("snapshot", boost::bind(LLFloaterSnapshot::show, (void*)NULL)); + registerFloater("snapshot", boost::bind(LLFloaterSnapshot::show, nullptr)); registerFloater("sound_explorer", boost::bind(LLFloaterExploreSounds::toggle), boost::bind(LLFloaterExploreSounds::visible)); - registerFloater("test", boost::bind(LLFloaterTest::show, (void*)NULL)); + registerFloater("test", boost::bind(LLFloaterTest::show, nullptr)); // Phoenix: Wolfspirit: Enabled Show Floater out of viewer menu registerFloater("WaterSettings", boost::bind(LLFloaterWater::show), boost::bind(LLFloaterWater::isOpen)); - registerFloater("web", boost::bind(LLFloaterWebContent::showInstance, "dict web", LLFloaterWebContent::Params())); registerFloater("Windlight", boost::bind(LLFloaterWindLight::show), boost::bind(LLFloaterWindLight::isOpen)); registerFloater("world map", boost::bind(LLFloaterWorldMap::toggle)); registerFloater ("about land"); registerFloater ("about region"); registerFloater ("active speakers"); + registerFloater ("ao"); registerFloater ("areasearch"); registerFloater ("autoreplace"); registerFloater ("avatar"); @@ -223,22 +223,23 @@ struct MenuFloaterDict : public LLSingleton registerFloater ("communicate"); registerFloater ("destinations"); registerFloater ("displayname"); + registerFloater ("experiences"); registerFloater ("friends", 0); registerFloater ("gestures"); registerFloater ("groups", 1); registerFloater ("im"); registerFloater ("inspect"); registerFloater ("joystick"); - registerFloater ("lag meter"); registerFloater ("media filter"); registerFloater ("mini map"); + registerFloater ("marketplace_listings"); registerFloater ("movement controls"); registerFloater ("mute list"); registerFloater ("notifications console"); - registerFloater ("outbox"); registerFloater ("pathfinding_characters"); registerFloater ("pathfinding_linksets"); registerFloater ("perm prefs"); + registerFloater ("PostProcess"); registerFloater ("radar"); registerFloater ("region_tracker"); registerFloater ("script info"); @@ -251,12 +252,13 @@ struct MenuFloaterDict : public LLSingleton registerFloater("rlv strings"); // [/RLVa:LF] } +public: template void registerConsole(const std::string& name, T* console) { registerFloater(name, boost::bind(&T::setVisible, console, !boost::bind(&T::getVisible, console)), boost::bind(&T::getVisible, console)); } - void registerFloater(const std::string& name, boost::function show, boost::function visible = NULL) + void registerFloater(const std::string& name, std::function show, std::function visible = nullptr) { mEntries.insert( std::make_pair( name, std::make_pair( show, visible ) ) ); } diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 70bfef4277..160dc67be3 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -38,7 +38,6 @@ #include "lldatapacker.h" #include "llfasttimer.h" #include "llfloaterperms.h" -#include "lleconomy.h" #include "llimagej2c.h" #include "llhost.h" #include "llnotificationsutil.h" @@ -66,7 +65,7 @@ #include "lluploadfloaterobservers.h" #include "aicurl.h" -#include "boost/lexical_cast.hpp" +#include #ifndef LL_WINDOWS #include "netdb.h" @@ -104,14 +103,13 @@ U32 LLMeshRepository::sLODPending = 0; U32 LLMeshRepository::sCacheBytesRead = 0; U32 LLMeshRepository::sCacheBytesWritten = 0; U32 LLMeshRepository::sPeakKbps = 0; - const U32 MAX_TEXTURE_UPLOAD_RETRIES = 5; static S32 dump_num = 0; std::string make_dump_name(std::string prefix, S32 num) { - return prefix + boost::lexical_cast(num) + std::string(".xml"); + return prefix + fmt::to_string(num) + std::string(".xml"); } void dump_llsd_to_file(const LLSD& content, std::string filename); @@ -124,6 +122,7 @@ std::string header_lod[] = "medium_lod", "high_lod" }; +const char * const LOG_MESH = "Mesh"; //get the number of bytes resident in memory for given volume @@ -206,6 +205,12 @@ void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res, } } +LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMaterial& material) +{ + LLPointer< LLViewerFetchedTexture > * ppTex = static_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData); + return ppTex ? (*ppTex).get() : NULL; +} + S32 LLMeshRepoThread::sActiveHeaderRequests = 0; S32 LLMeshRepoThread::sActiveLODRequests = 0; U32 LLMeshRepoThread::sMaxConcurrentRequests = 1; @@ -215,6 +220,7 @@ class LLMeshHeaderResponder : public LLHTTPClient::ResponderWithCompleted public: LLVolumeParams mMeshParams; bool mProcessed; + void retry(); LLMeshHeaderResponder(const LLVolumeParams& mesh_params) : mMeshParams(mesh_params) @@ -231,15 +237,15 @@ class LLMeshHeaderResponder : public LLHTTPClient::ResponderWithCompleted { //something went wrong, retry LL_WARNS() << "Timeout or service unavailable, retrying." << LL_ENDL; LLMeshRepository::sHTTPRetryCount++; - LLMeshRepoThread::HeaderRequest req(mMeshParams); LLMutexLock lock(gMeshRepo.mThread->mMutex); - gMeshRepo.mThread->mHeaderReqQ.push(req); + gMeshRepo.mThread->pushHeaderRequest(mMeshParams, 10.f); } LLMeshRepoThread::decActiveHeaderRequests(); } } + virtual void completedRaw(LLChannelDescriptors const& channels, LLIOPipe::buffer_ptr_t const& buffer); @@ -256,6 +262,7 @@ class LLMeshLODResponder : public LLHTTPClient::ResponderWithCompleted U32 mRequestedBytes; U32 mOffset; bool mProcessed; + void retry(); LLMeshLODResponder(const LLVolumeParams& mesh_params, S32 lod, U32 offset, U32 requested_bytes) : mMeshParams(mesh_params), mLOD(lod), mOffset(offset), mRequestedBytes(requested_bytes) @@ -293,6 +300,7 @@ class LLMeshSkinInfoResponder : public LLHTTPClient::ResponderWithCompleted U32 mRequestedBytes; U32 mOffset; bool mProcessed; + void retry(); LLMeshSkinInfoResponder(const LLUUID& id, U32 offset, U32 size) : mMeshID(id), mRequestedBytes(size), mOffset(offset) @@ -327,6 +335,7 @@ class LLMeshDecompositionResponder : public LLHTTPClient::ResponderWithCompleted U32 mRequestedBytes; U32 mOffset; bool mProcessed; + void retry(); LLMeshDecompositionResponder(const LLUUID& id, U32 offset, U32 size) : mMeshID(id), mRequestedBytes(size), mOffset(offset) @@ -361,6 +370,7 @@ class LLMeshPhysicsShapeResponder : public LLHTTPClient::ResponderWithCompleted U32 mRequestedBytes; U32 mOffset; bool mProcessed; + void retry(); LLMeshPhysicsShapeResponder(const LLUUID& id, U32 offset, U32 size) : mMeshID(id), mRequestedBytes(size), mOffset(offset) @@ -558,6 +568,8 @@ LLMeshRepoThread::LLMeshRepoThread() mMutex = new LLMutex(); mHeaderMutex = new LLMutex(); mSignal = new LLCondition(); + mSkinInfoQMutex = new LLMutex(); + mDecompositionQMutex = new LLMutex(); } LLMeshRepoThread::~LLMeshRepoThread() @@ -568,6 +580,84 @@ LLMeshRepoThread::~LLMeshRepoThread() mHeaderMutex = NULL; delete mSignal; mSignal = NULL; + delete mSkinInfoQMutex; + mSkinInfoQMutex = NULL; + delete mDecompositionQMutex; + mDecompositionQMutex = NULL; +} + +bool LLMeshRepoThread::HeaderRequest::fetch(U32& count) +{ + return gMeshRepo.mThread->fetchMeshHeader(this->mMeshParams, count); +} + +void LLMeshRepoThread::LODRequest::preFetch() +{ + --LLMeshRepository::sLODProcessing; +} + +bool LLMeshRepoThread::LODRequest::fetch(U32& count) +{ + if (!gMeshRepo.mThread->fetchMeshLOD(this->mMeshParams, this->mLOD, count)) + { + gMeshRepo.mThread->mMutex->lock(); + ++LLMeshRepository::sLODProcessing; + gMeshRepo.mThread->mMutex->unlock(); + return false; + } + return true; +} + +void LLMeshRepoThread::runQueue(std::deque, F32> >& query, U32& count, S32& active_requests) +{ + std::queue, F32> > incomplete; + while (!query.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && active_requests < (S32)sMaxConcurrentRequests) + { + if (mMutex) + { + mMutex->lock(); + auto req = query.front().first; + F32 delay = query.front().second; + query.pop_front(); + req->preFetch(); + mMutex->unlock(); + F32 remainder = delay - req->mTimer.getElapsedTimeF32(); + if (remainder > 0.f) + { + //LL_INFOS() << req->mMeshParams.getSculptID() << " skipped. " << remainder << "s remaining" << LL_ENDL; + incomplete.push(std::make_pair(req, delay)); + } + else if (!req->fetch(count))//failed, resubmit + { + LL_INFOS() << req->mMeshParams.getSculptID() << " fetch failed outright. Delaying for " << (delay ? delay : 15) << "s" << LL_ENDL; + req->mTimer.reset(); + incomplete.push(std::make_pair(req, delay ? delay : 15)); + } + else { + //LL_INFOS() << req->mMeshParams.getSculptID() << " fetch request created. " << std::hex << &(req->mMeshParams) << std::dec << LL_ENDL; + } + } + } + if (!incomplete.empty()) + { + mMutex->lock(); + while (!incomplete.empty()) + { + query.push_back(incomplete.front()); + incomplete.pop(); + } + mMutex->unlock(); + } +} + +void LLMeshRepoThread::runSet(uuid_set_t& set, std::function fn) +{ + for (auto iter = set.begin(); iter != set.end();) + { + if (fn(*iter)) + iter = set.erase(iter); + else ++iter; + } } void LLMeshRepoThread::run() @@ -594,84 +684,21 @@ void LLMeshRepoThread::run() } // NOTE: throttling intentionally favors LOD requests over header requests + runQueue(mLODReqQ, count, sActiveLODRequests); + runQueue(mHeaderReqQ, count, sActiveHeaderRequests); - while (!mLODReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveLODRequests < (S32)sMaxConcurrentRequests) - { - if (mMutex) - { - mMutex->lock(); - LODRequest req = mLODReqQ.front(); - mLODReqQ.pop(); - LLMeshRepository::sLODProcessing--; - mMutex->unlock(); - if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit - { - mMutex->lock(); - mLODReqQ.push(req); - mMutex->unlock(); - } - } - } - - while (!mHeaderReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveHeaderRequests < (S32)sMaxConcurrentRequests) - { - if (mMutex) - { - mMutex->lock(); - HeaderRequest req = mHeaderReqQ.front(); - mHeaderReqQ.pop(); - mMutex->unlock(); - if (!fetchMeshHeader(req.mMeshParams, count))//failed, resubmit - { - mMutex->lock(); - mHeaderReqQ.push(req) ; - mMutex->unlock(); - } - } - } - - { //mSkinRequests is protected by mSignal - std::set incomplete; - for (std::set::iterator iter = mSkinRequests.begin(); iter != mSkinRequests.end(); ++iter) - { - LLUUID mesh_id = *iter; - if (!fetchMeshSkinInfo(mesh_id)) - { - incomplete.insert(mesh_id); - } - } - mSkinRequests = incomplete; - } - - { //mDecompositionRequests is protected by mSignal - std::set incomplete; - for (std::set::iterator iter = mDecompositionRequests.begin(); iter != mDecompositionRequests.end(); ++iter) - { - LLUUID mesh_id = *iter; - if (!fetchMeshDecomposition(mesh_id)) - { - incomplete.insert(mesh_id); - } - } - mDecompositionRequests = incomplete; - } - - { //mPhysicsShapeRequests is protected by mSignal - std::set incomplete; - for (std::set::iterator iter = mPhysicsShapeRequests.begin(); iter != mPhysicsShapeRequests.end(); ++iter) - { - LLUUID mesh_id = *iter; - if (!fetchMeshPhysicsShape(mesh_id)) - { - incomplete.insert(mesh_id); - } - } - mPhysicsShapeRequests = incomplete; - } + // Protected by mSignal + runSet(mSkinRequests, std::bind(&LLMeshRepoThread::fetchMeshSkinInfo, this, std::placeholders::_1)); + runSet(mDecompositionRequests, std::bind(&LLMeshRepoThread::fetchMeshDecomposition, this, std::placeholders::_1)); + runSet(mPhysicsShapeRequests, std::bind(&LLMeshRepoThread::fetchMeshPhysicsShape, this, std::placeholders::_1)); } - mSignal->wait(); + mSignal->unlock(); + ms_sleep(1000 / 60); + mSignal->lock(); + + //mSignal->wait(); } if (mSignal->isLocked()) @@ -714,20 +741,18 @@ void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) { //could be called from any thread + std::unique_lock header_lock(*mHeaderMutex); + bool exists = mMeshHeader.find(mesh_params.getSculptID()) != mMeshHeader.end(); + header_lock.unlock(); LLMutexLock lock(mMutex); - mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID()); - if (iter != mMeshHeader.end()) - { //if we have the header, request LOD byte range - LODRequest req(mesh_params, lod); - { - mLODReqQ.push(req); - LLMeshRepository::sLODProcessing++; - } + if (exists) + { + //if we have the header, request LOD byte range + gMeshRepo.mThread->pushLODRequest(mesh_params, lod, 0.f); + LLMeshRepository::sLODProcessing++; } else { - HeaderRequest req(mesh_params); - pending_lod_map::iterator pending = mPendingLOD.find(mesh_params); if (pending != mPendingLOD.end()) @@ -737,7 +762,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) } else { //if no header request is pending, fetch header - mHeaderReqQ.push(req); + gMeshRepo.mThread->pushHeaderRequest(mesh_params, 0.f); mPendingLOD[mesh_params].push_back(lod); } } @@ -783,9 +808,11 @@ bool LLMeshRepoThread::getMeshHeaderInfo(const LLUUID& mesh_id, const char* bloc if ((info.mHeaderSize = mMeshHeaderSize[mesh_id]) > 0) { - info.mVersion = mMeshHeader[mesh_id]["version"].asInteger(); - info.mOffset = info.mHeaderSize + mMeshHeader[mesh_id][block_name]["offset"].asInteger(); - info.mSize = mMeshHeader[mesh_id][block_name]["size"].asInteger(); + const LLSD& header = mMeshHeader[mesh_id]; + const LLSD& block = header[block_name]; + info.mVersion = header["version"].asInteger(); + info.mOffset = info.mHeaderSize + block["offset"].asInteger(); + info.mSize = block["size"].asInteger(); } return true; } @@ -1089,9 +1116,8 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat { for (U32 i = 0; i < iter->second.size(); ++i) { - LODRequest req(mesh_params, iter->second[i]); - mLODReqQ.push(req); LLMeshRepository::sLODProcessing++; + gMeshRepo.mThread->pushLODRequest(mesh_params, iter->second[i], 0.f); } mPendingLOD.erase(iter); } @@ -1149,7 +1175,9 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat info.mMeshID = mesh_id; //LL_INFOS() <<"info pelvis offset"<lock(); mSkinInfoQ.push(info); + mSkinInfoQMutex->unlock(); } return true; @@ -1175,7 +1203,9 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3 { LLModel::Decomposition* d = new LLModel::Decomposition(decomp); d->mMeshID = mesh_id; + mDecompositionQMutex->lock(); mDecompositionQ.push(d); + mDecompositionQMutex->unlock(); } return true; @@ -1234,7 +1264,9 @@ bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 } } + mDecompositionQMutex->lock(); mDecompositionQ.push(d); + mDecompositionQMutex->unlock(); return true; } @@ -1429,6 +1461,13 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) { LLMeshUploadData data; data.mBaseModel = iter->first; + + if (data.mBaseModel->mSubmodelID) + { + // These are handled below to insure correct parenting order on creation + // due to map walking being based on model address (aka random) + continue; + } LLModelInstance& first_instance = *(iter->second.begin()); for (S32 i = 0; i < 5; i++) { @@ -1466,7 +1505,10 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) data.mModel[LLModel::LOD_IMPOSTOR], decomp, mUploadSkin, - mUploadJoints); + mUploadJoints, + FALSE, + FALSE, + data.mBaseModel->mSubmodelID); data.mAssetData = ostr.str(); std::string str = ostr.str(); @@ -1500,17 +1542,27 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) instance_entry["scale"] = ll_sd_from_vector3(scale); instance_entry["material"] = LL_MCODE_WOOD; - instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); + instance_entry["physics_shape_type"] = data.mModel[LLModel::LOD_PHYSICS].notNull() ? (U8)(LLViewerObject::PHYSICS_SHAPE_PRIM) : (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); instance_entry["mesh"] = mesh_index[data.mBaseModel]; + instance_entry["mesh_name"] = instance.mLabel; instance_entry["face_list"] = LLSD::emptyArray(); - S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ; + // We want to be able to allow more than 8 materials... + // + S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ; + for (S32 face_num = 0; face_num < end; face_num++) { LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]]; LLSD face_entry = LLSD::emptyMap(); - LLViewerFetchedTexture *texture = material.mDiffuseMap.get(); + + LLViewerFetchedTexture *texture = NULL; + + if (material.mDiffuseMapFilename.size()) + { + texture = FindViewerTexture(material); + } if ((texture != NULL) && (textures.find(texture) == textures.end())) @@ -1525,9 +1577,171 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) { LLPointer upload_file = LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage()); + + if (!upload_file.isNull() && upload_file->getDataSize()) + { texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize()); } } + } + + if (texture != NULL && + mUploadTextures && + texture_index.find(texture) == texture_index.end()) + { + texture_index[texture] = texture_num; + std::string str = texture_str.str(); + res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end()); + texture_num++; + } + + // Subset of TextureEntry fields. + if (texture != NULL && mUploadTextures) + { + face_entry["image"] = texture_index[texture]; + face_entry["scales"] = 1.0; + face_entry["scalet"] = 1.0; + face_entry["offsets"] = 0.0; + face_entry["offsett"] = 0.0; + face_entry["imagerot"] = 0.0; + } + face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor); + face_entry["fullbright"] = material.mFullbright; + instance_entry["face_list"][face_num] = face_entry; + } + + res["instance_list"][instance_num] = instance_entry; + instance_num++; + } + } + + for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter) + { + LLMeshUploadData data; + data.mBaseModel = iter->first; + + if (!data.mBaseModel->mSubmodelID) + { + // These were handled above already... + // + continue; + } + + LLModelInstance& first_instance = *(iter->second.begin()); + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = first_instance.mLOD[i]; + } + + if (mesh_index.find(data.mBaseModel) == mesh_index.end()) + { + // Have not seen this model before - create a new mesh_list entry for it. + if (model_name.empty()) + { + model_name = data.mBaseModel->getName(); + } + + if (model_metric.empty()) + { + model_metric = data.mBaseModel->getMetric(); + } + + std::stringstream ostr; + + LLModel::Decomposition& decomp = + data.mModel[LLModel::LOD_PHYSICS].notNull() ? + data.mModel[LLModel::LOD_PHYSICS]->mPhysics : + data.mBaseModel->mPhysics; + + decomp.mBaseHull = mHullMap[data.mBaseModel]; + + LLSD mesh_header = LLModel::writeModel( + ostr, + data.mModel[LLModel::LOD_PHYSICS], + data.mModel[LLModel::LOD_HIGH], + data.mModel[LLModel::LOD_MEDIUM], + data.mModel[LLModel::LOD_LOW], + data.mModel[LLModel::LOD_IMPOSTOR], + decomp, + mUploadSkin, + mUploadJoints, + FALSE, + FALSE, + data.mBaseModel->mSubmodelID); + + data.mAssetData = ostr.str(); + std::string str = ostr.str(); + + res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end()); + mesh_index[data.mBaseModel] = mesh_num; + mesh_num++; + } + + // For all instances that use this model + for (instance_list::iterator instance_iter = iter->second.begin(); + instance_iter != iter->second.end(); + ++instance_iter) + { + + LLModelInstance& instance = *instance_iter; + + LLSD instance_entry; + + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = instance.mLOD[i]; + } + + LLVector3 pos, scale; + LLQuaternion rot; + LLMatrix4 transformation = instance.mTransform; + decomposeMeshMatrix(transformation,pos,rot,scale); + instance_entry["position"] = ll_sd_from_vector3(pos); + instance_entry["rotation"] = ll_sd_from_quaternion(rot); + instance_entry["scale"] = ll_sd_from_vector3(scale); + + instance_entry["material"] = LL_MCODE_WOOD; + instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE); + instance_entry["mesh"] = mesh_index[data.mBaseModel]; + + instance_entry["face_list"] = LLSD::emptyArray(); + + // We want to be able to allow more than 8 materials... + // + S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ; + + for (S32 face_num = 0; face_num < end; face_num++) + { + LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]]; + LLSD face_entry = LLSD::emptyMap(); + + LLViewerFetchedTexture *texture = NULL; + + if (material.mDiffuseMapFilename.size()) + { + texture = FindViewerTexture(material); + } + + if ((texture != NULL) && + (textures.find(texture) == textures.end())) + { + textures.insert(texture); + } + + std::stringstream texture_str; + if (texture != NULL && include_textures && mUploadTextures) + { + if(texture->hasSavedRawImage()) + { + LLPointer upload_file = + LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage()); + + if (!upload_file.isNull() && upload_file->getDataSize()) + { + texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize()); + } + } + } if (texture != NULL && mUploadTextures && @@ -1662,14 +1876,22 @@ void LLMeshRepoThread::notifyLoadedMeshes() while (!mSkinInfoQ.empty()) { - gMeshRepo.notifySkinInfoReceived(mSkinInfoQ.front()); + mSkinInfoQMutex->lock(); + auto req = mSkinInfoQ.front(); mSkinInfoQ.pop(); + mSkinInfoQMutex->unlock(); + + gMeshRepo.notifySkinInfoReceived(req); } while (!mDecompositionQ.empty()) { - gMeshRepo.notifyDecompositionReceived(mDecompositionQ.front()); + mDecompositionQMutex->lock(); + auto req = mDecompositionQ.front(); mDecompositionQ.pop(); + mDecompositionQMutex->unlock(); + + gMeshRepo.notifyDecompositionReceived(req); } } @@ -1693,7 +1915,7 @@ S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod) { lod = llclamp(lod, 0, 3); - S32 version = header["version"]; + S32 version = header["version"].asInteger(); if (header.has("404") || version > MAX_MESH_VERSION) { @@ -1749,6 +1971,13 @@ void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header) } +void LLMeshLODResponder::retry() +{ + AIStateMachine::StateTimer timer("loadMeshLOD"); + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->loadMeshLOD(mMeshParams, mLOD); +} + void LLMeshLODResponder::completedRaw(LLChannelDescriptors const& channels, LLIOPipe::buffer_ptr_t const& buffer) { @@ -1771,10 +2000,8 @@ void LLMeshLODResponder::completedRaw(LLChannelDescriptors const& channels, { if (is_internal_http_error_that_warrants_a_retry(mStatus) || mStatus == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again - AIStateMachine::StateTimer timer("loadMeshLOD"); LL_WARNS() << "Timeout or service unavailable, retrying." << LL_ENDL; - LLMeshRepository::sHTTPRetryCount++; - gMeshRepo.mThread->loadMeshLOD(mMeshParams, mLOD); + retry(); } else { @@ -1816,6 +2043,12 @@ void LLMeshLODResponder::completedRaw(LLChannelDescriptors const& channels, delete [] data; } +void LLMeshSkinInfoResponder::retry() +{ + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->loadMeshSkinInfo(mMeshID); +} + void LLMeshSkinInfoResponder::completedRaw(LLChannelDescriptors const& channels, LLIOPipe::buffer_ptr_t const& buffer) { @@ -1839,8 +2072,7 @@ void LLMeshSkinInfoResponder::completedRaw(LLChannelDescriptors const& channels, if (is_internal_http_error_that_warrants_a_retry(mStatus) || mStatus == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again LL_WARNS() << "Timeout or service unavailable, retrying loadMeshSkinInfo() for " << mMeshID << LL_ENDL; - LLMeshRepository::sHTTPRetryCount++; - gMeshRepo.mThread->loadMeshSkinInfo(mMeshID); + retry(); } else { @@ -1879,6 +2111,12 @@ void LLMeshSkinInfoResponder::completedRaw(LLChannelDescriptors const& channels, delete [] data; } +void LLMeshDecompositionResponder::retry() +{ + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->loadMeshDecomposition(mMeshID); +} + void LLMeshDecompositionResponder::completedRaw(LLChannelDescriptors const& channels, LLIOPipe::buffer_ptr_t const& buffer) { @@ -1901,8 +2139,7 @@ void LLMeshDecompositionResponder::completedRaw(LLChannelDescriptors const& chan if (is_internal_http_error_that_warrants_a_retry(mStatus) || mStatus == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again LL_WARNS() << "Timeout or service unavailable, retrying loadMeshDecomposition() for " << mMeshID << LL_ENDL; - LLMeshRepository::sHTTPRetryCount++; - gMeshRepo.mThread->loadMeshDecomposition(mMeshID); + retry(); } else { @@ -1941,6 +2178,11 @@ void LLMeshDecompositionResponder::completedRaw(LLChannelDescriptors const& chan delete [] data; } +void LLMeshPhysicsShapeResponder::retry() +{ + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->loadMeshPhysicsShape(mMeshID); +} void LLMeshPhysicsShapeResponder::completedRaw(LLChannelDescriptors const& channels, LLIOPipe::buffer_ptr_t const& buffer) { @@ -1964,8 +2206,7 @@ void LLMeshPhysicsShapeResponder::completedRaw(LLChannelDescriptors const& chann if (is_internal_http_error_that_warrants_a_retry(mStatus) || mStatus == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again LL_WARNS() << "Timeout or service unavailable, retrying loadMeshPhysicsShape() for " << mMeshID << LL_ENDL; - LLMeshRepository::sHTTPRetryCount++; - gMeshRepo.mThread->loadMeshPhysicsShape(mMeshID); + retry(); } else { @@ -2004,9 +2245,18 @@ void LLMeshPhysicsShapeResponder::completedRaw(LLChannelDescriptors const& chann delete [] data; } +void LLMeshHeaderResponder::retry() +{ + AIStateMachine::StateTimer timer("Retry"); + LLMeshRepository::sHTTPRetryCount++; + LLMutexLock lock(gMeshRepo.mThread->mMutex); + gMeshRepo.mThread->pushHeaderRequest(mMeshParams, 10.f); +} + void LLMeshHeaderResponder::completedRaw(LLChannelDescriptors const& channels, LLIOPipe::buffer_ptr_t const& buffer) { + //LL_INFOS() << mMeshParams.getSculptID() << " Status: " << mStatus << LL_ENDL; mProcessed = true; // thread could have already be destroyed during logout @@ -2032,13 +2282,8 @@ void LLMeshHeaderResponder::completedRaw(LLChannelDescriptors const& channels, if (is_internal_http_error_that_warrants_a_retry(mStatus) || mStatus == HTTP_SERVICE_UNAVAILABLE) { //retry - AIStateMachine::StateTimer timer("Retry"); LL_WARNS() << "Timeout or service unavailable, retrying." << LL_ENDL; - LLMeshRepository::sHTTPRetryCount++; - LLMeshRepoThread::HeaderRequest req(mMeshParams); - LLMutexLock lock(gMeshRepo.mThread->mMutex); - gMeshRepo.mThread->mHeaderReqQ.push(req); - + retry(); return; } else @@ -2130,14 +2375,18 @@ void LLMeshHeaderResponder::completedRaw(LLChannelDescriptors const& channels, } if (data.size() > BUFF_MAX_STATIC_SIZE) + { + std::vector().swap(data); data.resize(BUFF_MAX_STATIC_SIZE); + } } LLMeshRepository::LLMeshRepository() : mMeshMutex(NULL), mMeshThreadCount(0), - mThread(NULL) + mThread(NULL), + mDecompThread(nullptr) { } @@ -2164,7 +2413,7 @@ void LLMeshRepository::init() void LLMeshRepository::shutdown() { - LL_INFOS() << "Shutting down mesh repository." << LL_ENDL; + LL_INFOS(LOG_MESH) << "Shutting down mesh repository." << LL_ENDL; mThread->mSignal->signal(); @@ -2178,7 +2427,7 @@ void LLMeshRepository::shutdown() delete mMeshMutex; mMeshMutex = NULL; - LL_INFOS() << "Shutting down decomposition system." << LL_ENDL; + LL_INFOS(LOG_MESH) << "Shutting down decomposition system." << LL_ENDL; if (mDecompThread) { @@ -2190,6 +2439,17 @@ void LLMeshRepository::shutdown() LLConvexDecomposition::quitSystem(); } +void LLMeshRepository::unregisterMesh(LLVOVolume* vobj) +{ + for (auto& lod : mLoadingMeshes) + { + for (auto& param : lod) + { + vector_replace_with_last(param.second, vobj); + } + } +} + S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail, S32 last_lod) { if (detail < 0 || detail > 4) @@ -2203,12 +2463,15 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_params); if (iter != mLoadingMeshes[detail].end()) { //request pending for this mesh, append volume id to list - iter->second.insert(vobj->getID()); + auto it = std::find(iter->second.begin(), iter->second.end(), vobj); + if (it == iter->second.end()) { + iter->second.push_back(vobj); + } } else { //first request for this mesh - mLoadingMeshes[detail][mesh_params].insert(vobj->getID()); + mLoadingMeshes[detail][mesh_params].push_back(vobj); mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail)); LLMeshRepository::sLODPending++; } @@ -2347,7 +2610,8 @@ void LLMeshRepository::notifyLoadedMeshes() if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived()) { region_name = gAgent.getRegion()->getName(); - mGetMeshCapability = gAgent.getRegion()->getCapability("GetMesh2"); + const std::string mesh_cap(gAgent.getRegion()->getViewerAssetUrl()); + mGetMeshCapability = !mesh_cap.empty() ? mesh_cap : gAgent.getRegion()->getCapability("GetMesh2"); if (mGetMeshCapability.empty()) { mGetMeshCapability = gAgent.getRegion()->getCapability("GetMesh"); @@ -2368,34 +2632,30 @@ void LLMeshRepository::notifyLoadedMeshes() S32 push_count = LLMeshRepoThread::sMaxConcurrentRequests-(LLMeshRepoThread::sActiveHeaderRequests+LLMeshRepoThread::sActiveLODRequests); + push_count = llmin(push_count, (S32)mPendingRequests.size()); + if (push_count > 0) { //calculate "score" for pending requests //create score map - std::map score_map; + boost::unordered_map score_map; - for (U32 i = 0; i < 4; ++i) + for (auto& lod : mLoadingMeshes) { - for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter) + for (auto& param : lod) { F32 max_score = 0.f; - for (std::set::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) + for (auto& vobj : param.second) { - LLViewerObject* object = gObjectList.findObject(*obj_iter); - - if (object) + if (LLDrawable* drawable = vobj->mDrawable) { - LLDrawable* drawable = object->mDrawable; - if (drawable) - { - F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f); - max_score = llmax(max_score, cur_score); - } + F32 cur_score = drawable->getRadius() / llmax(drawable->mDistanceWRTCamera, 1.f); + max_score = llmax(max_score, cur_score); } } - score_map[iter->first.getSculptID()] = max_score; + score_map[param.first.getSculptID()] = max_score; } } @@ -2406,7 +2666,8 @@ void LLMeshRepository::notifyLoadedMeshes() } //sort by "score" - std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater()); + std::partial_sort(mPendingRequests.begin(), mPendingRequests.begin() + push_count, + mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater()); while (!mPendingRequests.empty() && push_count > 0) { @@ -2447,12 +2708,12 @@ void LLMeshRepository::notifyLoadedMeshes() void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info) { - mSkinMap[info.mMeshID] = info; + mSkinMap.insert_or_assign(info.mMeshID, info); skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID); if (iter != mLoadingSkins.end()) { - for (std::set::iterator obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id) + for (auto obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id) { LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*obj_id); if (vobj) @@ -2460,9 +2721,8 @@ void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info) vobj->notifyMeshLoaded(); } } + mLoadingSkins.erase(info.mMeshID); } - - mLoadingSkins.erase(info.mMeshID); } void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decomp) @@ -2471,18 +2731,18 @@ void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decom if (iter == mDecompositionMap.end()) { //just insert decomp into map mDecompositionMap[decomp->mMeshID] = decomp; + mLoadingDecompositions.erase(decomp->mMeshID); } else - { //merge decomp with existing entry + { //merge decomp with existing entry iter->second->merge(decomp); + mLoadingDecompositions.erase(decomp->mMeshID); delete decomp; } - - mLoadingDecompositions.erase(decomp->mMeshID); } void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume) -{ //called from main thread +{ //called from main thread S32 detail = LLVolumeLODGroup::getVolumeDetailFromScale(volume->getDetail()); //get list of objects waiting to be notified this mesh is loaded @@ -2493,7 +2753,8 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol //make sure target volume is still valid if (volume->getNumVolumeFaces() <= 0) { - LL_WARNS() << "Mesh loading returned empty volume." << LL_ENDL; + LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume. ID: " << mesh_params.getSculptID() + << LL_ENDL; } { //update system volume @@ -2506,18 +2767,15 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol } else { - LL_WARNS() << "Couldn't find system volume for given mesh." << LL_ENDL; + LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_params.getSculptID() + << LL_ENDL; } } //notify waiting LLVOVolume instances that their requested mesh is available - for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + for (auto& vobj : obj_iter->second) { - LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); - if (vobj) - { - vobj->notifyMeshLoaded(); - } + vobj->notifyMeshLoaded(); } mLoadingMeshes[detail].erase(mesh_params); @@ -2533,19 +2791,14 @@ void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params, if (obj_iter != mLoadingMeshes[lod].end()) { - for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + for (auto& vobj : obj_iter->second) { - LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); - if (vobj) - { - LLVolume* obj_volume = vobj->getVolume(); - - if (obj_volume && - obj_volume->getDetail() == detail && - obj_volume->getParams() == mesh_params) - { //should force volume to find most appropriate LOD + LLVolume* obj_volume = vobj->getVolume(); + if (obj_volume && + obj_volume->getDetail() == detail && + obj_volume->getParams() == mesh_params) + { //should force volume to find most appropriate LOD vobj->setVolume(obj_volume->getParams(), lod); - } } } @@ -2562,8 +2815,8 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const { if (mesh_id.notNull()) { - skin_map::iterator iter = mSkinMap.find(mesh_id); - if (iter != mSkinMap.end()) + const auto iter = mSkinMap.find(mesh_id); + if (iter != mSkinMap.cend()) { return &(iter->second); } @@ -2600,7 +2853,7 @@ void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id) { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes - std::set::iterator iter = mLoadingPhysicsShapes.find(mesh_id); + auto iter = mLoadingPhysicsShapes.find(mesh_id); if (iter == mLoadingPhysicsShapes.end()) { //no request pending for this skin info mLoadingPhysicsShapes.insert(mesh_id); @@ -2628,7 +2881,7 @@ LLModel::Decomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh_id { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes - std::set::iterator iter = mLoadingDecompositions.find(mesh_id); + auto iter = mLoadingDecompositions.find(mesh_id); if (iter == mLoadingDecompositions.end()) { //no request pending for this skin info mLoadingDecompositions.insert(mesh_id); @@ -2685,7 +2938,7 @@ LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id) { LLMutexLock lock(mHeaderMutex); mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); - if (iter != mMeshHeader.end()) + if (iter != mMeshHeader.end() && mMeshHeaderSize[mesh_id] > 0) { return iter->second; } @@ -2711,10 +2964,11 @@ void LLMeshRepository::uploadModel(std::vector& data, LLVector3 S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod) { - if (mThread) + if (mThread && mesh_id.notNull() && LLPrimitive::NO_LOD != lod) { + LLMutexLock lock(mThread->mHeaderMutex); LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); - if (iter != mThread->mMeshHeader.end()) + if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) { LLSD& header = iter->second; @@ -2773,37 +3027,6 @@ void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation, result_rot = quat_rotation; } -bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const -{ - if (mDiffuseMap != rhs.mDiffuseMap) - { - return mDiffuseMap < rhs.mDiffuseMap; - } - - if (mDiffuseMapFilename != rhs.mDiffuseMapFilename) - { - return mDiffuseMapFilename < rhs.mDiffuseMapFilename; - } - - if (mDiffuseMapLabel != rhs.mDiffuseMapLabel) - { - return mDiffuseMapLabel < rhs.mDiffuseMapLabel; - } - - if (mDiffuseColor != rhs.mDiffuseColor) - { - return mDiffuseColor < rhs.mDiffuseColor; - } - - if (mBinding != rhs.mBinding) - { - return mBinding < rhs.mBinding; - } - - return mFullbright < rhs.mFullbright; -} - - void LLMeshRepository::updateInventory(inventory_data data) { LLMutexLock lock(mMeshMutex); @@ -2818,9 +3041,88 @@ void LLMeshRepository::uploadError(LLSD& args) mUploadErrorQ.push(args); } +F32 LLMeshRepository::getEstTrianglesMax(LLUUID mesh_id) +{ + LLMeshCostData costs; + if (getCostData(mesh_id, costs)) + { + return costs.getEstTrisMax(); + } + else + { + return 0.f; + } +} + +F32 LLMeshRepository::getEstTrianglesStreamingCost(LLUUID mesh_id) +{ + LLMeshCostData costs; + if (getCostData(mesh_id, costs)) + { + return costs.getEstTrisForStreamingCost(); + } + else + { + return 0.f; + } +} + +// FIXME replace with calc based on LLMeshCostData +F32 LLMeshRepository::getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value) +{ + F32 result = 0.f; + if (mThread && mesh_id.notNull()) + { + LLMutexLock lock(mThread->mHeaderMutex); + LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); + if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) + { + result = getStreamingCostLegacy(iter->second, radius, bytes, bytes_visible, lod, unscaled_value); + } + } + if (result > 0.f) + { + LLMeshCostData data; + if (getCostData(mesh_id, data)) + { + F32 ref_streaming_cost = data.getRadiusBasedStreamingCost(radius); + F32 ref_weighted_tris = data.getRadiusWeightedTris(radius); + if (!is_approx_equal(ref_streaming_cost,result)) + { + LL_WARNS() << mesh_id << "streaming mismatch " << result << " " << ref_streaming_cost << LL_ENDL; + } + if (unscaled_value && !is_approx_equal(ref_weighted_tris,*unscaled_value)) + { + LL_WARNS() << mesh_id << "weighted_tris mismatch " << *unscaled_value << " " << ref_weighted_tris << LL_ENDL; + } + if (bytes && (*bytes != data.getSizeTotal())) + { + LL_WARNS() << mesh_id << "bytes mismatch " << *bytes << " " << data.getSizeTotal() << LL_ENDL; + } + if (bytes_visible && (lod >=0) && (lod < 4) && (*bytes_visible != data.getSizeByLOD(lod))) + { + LL_WARNS() << mesh_id << "bytes_visible mismatch " << *bytes_visible << " " << data.getSizeByLOD(lod) << LL_ENDL; + } + } + else + { + LL_WARNS() << "getCostData failed!!!" << LL_ENDL; + } + } + return result; +} + +// FIXME replace with calc based on LLMeshCostData //static -F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value) +F32 LLMeshRepository::getStreamingCostLegacy(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value) { + if (header.has("404") + || !header.has("lowest_lod") + || (header.has("version") && header["version"].asInteger() > MAX_MESH_VERSION)) + { + return 0.f; + } + F32 max_distance = 512.f; F32 dlowest = llmin(radius/0.03f, max_distance); @@ -2885,7 +3187,7 @@ F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32 } } - F32 max_area = 102932.f; //area of circle that encompasses region + F32 max_area = 102944.f; //area of circle that encompasses region (see MAINT-6559) F32 min_area = 1.f; F32 high_area = llmin(F_PI*dmid*dmid, max_area); @@ -2921,7 +3223,205 @@ F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32 return weighted_avg/mesh_triangle_budget*15000.f; } +LLMeshCostData::LLMeshCostData() +{ + mSizeByLOD.resize(4); + mEstTrisByLOD.resize(4); + + std::fill(mSizeByLOD.begin(), mSizeByLOD.end(), 0); + std::fill(mEstTrisByLOD.begin(), mEstTrisByLOD.end(), 0.f); +} + +bool LLMeshCostData::init(const LLSD& header) +{ + mSizeByLOD.resize(4); + mEstTrisByLOD.resize(4); + + std::fill(mSizeByLOD.begin(), mSizeByLOD.end(), 0); + std::fill(mEstTrisByLOD.begin(), mEstTrisByLOD.end(), 0.f); + + S32 bytes_high = header["high_lod"]["size"].asInteger(); + S32 bytes_med = header["medium_lod"]["size"].asInteger(); + if (bytes_med == 0) + { + bytes_med = bytes_high; + } + S32 bytes_low = header["low_lod"]["size"].asInteger(); + if (bytes_low == 0) + { + bytes_low = bytes_med; + } + S32 bytes_lowest = header["lowest_lod"]["size"].asInteger(); + if (bytes_lowest == 0) + { + bytes_lowest = bytes_low; + } + mSizeByLOD[0] = bytes_lowest; + mSizeByLOD[1] = bytes_low; + mSizeByLOD[2] = bytes_med; + mSizeByLOD[3] = bytes_high; + + F32 METADATA_DISCOUNT = (F32) gSavedSettings.getU32("MeshMetaDataDiscount"); //discount 128 bytes to cover the cost of LLSD tags and compression domain overhead + F32 MINIMUM_SIZE = (F32) gSavedSettings.getU32("MeshMinimumByteSize"); //make sure nothing is "free" + F32 bytes_per_triangle = (F32) gSavedSettings.getU32("MeshBytesPerTriangle"); + + for (S32 i=0; i<4; i++) + { + mEstTrisByLOD[i] = llmax((F32) mSizeByLOD[i]-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle; + } + + return true; +} + + +S32 LLMeshCostData::getSizeByLOD(S32 lod) +{ + if (llclamp(lod,0,3) != lod) + { + return 0; + } + return mSizeByLOD[lod]; +} + +S32 LLMeshCostData::getSizeTotal() +{ + return mSizeByLOD[0] + mSizeByLOD[1] + mSizeByLOD[2] + mSizeByLOD[3]; +} + +F32 LLMeshCostData::getEstTrisByLOD(S32 lod) +{ + if (llclamp(lod,0,3) != lod) + { + return 0.f; + } + return mEstTrisByLOD[lod]; +} + +F32 LLMeshCostData::getEstTrisMax() +{ + return llmax(mEstTrisByLOD[0], mEstTrisByLOD[1], mEstTrisByLOD[2], mEstTrisByLOD[3]); +} + +F32 LLMeshCostData::getRadiusWeightedTris(F32 radius) +{ + F32 max_distance = 512.f; + + F32 dlowest = llmin(radius/0.03f, max_distance); + F32 dlow = llmin(radius/0.06f, max_distance); + F32 dmid = llmin(radius/0.24f, max_distance); + + F32 triangles_lowest = mEstTrisByLOD[0]; + F32 triangles_low = mEstTrisByLOD[1]; + F32 triangles_mid = mEstTrisByLOD[2]; + F32 triangles_high = mEstTrisByLOD[3]; + + F32 max_area = 102944.f; //area of circle that encompasses region (see MAINT-6559) + F32 min_area = 1.f; + + F32 high_area = llmin(F_PI*dmid*dmid, max_area); + F32 mid_area = llmin(F_PI*dlow*dlow, max_area); + F32 low_area = llmin(F_PI*dlowest*dlowest, max_area); + F32 lowest_area = max_area; + lowest_area -= low_area; + low_area -= mid_area; + mid_area -= high_area; + + high_area = llclamp(high_area, min_area, max_area); + mid_area = llclamp(mid_area, min_area, max_area); + low_area = llclamp(low_area, min_area, max_area); + lowest_area = llclamp(lowest_area, min_area, max_area); + + F32 total_area = high_area + mid_area + low_area + lowest_area; + high_area /= total_area; + mid_area /= total_area; + low_area /= total_area; + lowest_area /= total_area; + + F32 weighted_avg = triangles_high*high_area + + triangles_mid*mid_area + + triangles_low*low_area + + triangles_lowest*lowest_area; + + return weighted_avg; +} + +F32 LLMeshCostData::getEstTrisForStreamingCost() +{ + LL_DEBUGS("StreamingCost") << "tris_by_lod: " + << mEstTrisByLOD[0] << ", " + << mEstTrisByLOD[1] << ", " + << mEstTrisByLOD[2] << ", " + << mEstTrisByLOD[3] << LL_ENDL; + + F32 charged_tris = mEstTrisByLOD[3]; + F32 allowed_tris = mEstTrisByLOD[3]; + const F32 ENFORCE_FLOOR = 64.0f; + for (S32 i=2; i>=0; i--) + { + // How many tris can we have in this LOD without affecting land impact? + // - normally an LOD should be at most half the size of the previous one. + // - once we reach a floor of ENFORCE_FLOOR, don't require LODs to get any smaller. + allowed_tris = llclamp(allowed_tris/2.0f,ENFORCE_FLOOR,mEstTrisByLOD[i]); + F32 excess_tris = mEstTrisByLOD[i]-allowed_tris; + if (excess_tris>0.f) + { + LL_DEBUGS("StreamingCost") << "excess tris in lod[" << i << "] " << excess_tris << " allowed " << allowed_tris << LL_ENDL; + charged_tris += excess_tris; + } + } + return charged_tris; +} + +F32 LLMeshCostData::getRadiusBasedStreamingCost(F32 radius) +{ + return getRadiusWeightedTris(radius)/gSavedSettings.getU32("MeshTriangleBudget")*15000.f; +} + +F32 LLMeshCostData::getTriangleBasedStreamingCost() +{ + F32 result = ANIMATED_OBJECT_COST_PER_KTRI * 0.001 * getEstTrisForStreamingCost(); + return result; +} + + +bool LLMeshRepository::getCostData(LLUUID mesh_id, LLMeshCostData& data) +{ + data = LLMeshCostData(); + + if (mThread && mesh_id.notNull()) + { + LLMutexLock lock(mThread->mHeaderMutex); + LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); + if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) + { + const LLSD& header = iter->second; + + bool header_invalid = (header.has("404") + || !header.has("lowest_lod") + || (header.has("version") && header["version"].asInteger() > MAX_MESH_VERSION)); + if (!header_invalid) + { + return getCostData(header, data); + } + + return true; + } + } + return false; +} + +bool LLMeshRepository::getCostData(LLSD& header, LLMeshCostData& data) +{ + data = LLMeshCostData(); + + if (!data.init(header)) + { + return false; + } + + return true; +} LLPhysicsDecomp::LLPhysicsDecomp() : LLThread("Physics Decomp") { @@ -3035,7 +3535,7 @@ void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh, bool vertex_based) if (ret) { - LL_ERRS() << "Convex Decomposition thread valid but could not set mesh data" << LL_ENDL; + LL_ERRS(LOG_MESH) << "Convex Decomposition thread valid but could not set mesh data." << LL_ENDL; } } } @@ -3111,7 +3611,8 @@ void LLPhysicsDecomp::doDecomposition() if (ret) { - LL_WARNS() << "Convex Decomposition thread valid but could not execute stage " << stage << LL_ENDL; + LL_WARNS(LOG_MESH) << "Convex Decomposition thread valid but could not execute stage " << stage << "." + << LL_ENDL; LLMutexLock lock(mMutex); mCurRequest->mHull.clear(); @@ -3242,7 +3743,7 @@ void LLPhysicsDecomp::doDecompositionSingleHull() LLCDResult ret = decomp->buildSingleHull() ; if(ret) { - LL_WARNS() << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL; + LL_WARNS(LOG_MESH) << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL; make_box(mCurRequest); } else @@ -3490,60 +3991,6 @@ void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg) mStatusMessage = msg; } -LLModelInstance::LLModelInstance(LLSD& data) -{ - mLocalMeshID = data["mesh_id"].asInteger(); - mLabel = data["label"].asString(); - mTransform.setValue(data["transform"]); - - for (U32 i = 0; i < (U32)data["material"].size(); ++i) - { - LLImportMaterial mat(data["material"][i]); - mMaterial[mat.mBinding] = mat; - } -} - - -LLSD LLModelInstance::asLLSD() -{ - LLSD ret; - - ret["mesh_id"] = mModel->mLocalID; - ret["label"] = mLabel; - ret["transform"] = mTransform.getValue(); - - U32 i = 0; - for (std::map::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter) - { - ret["material"][i++] = iter->second.asLLSD(); - } - - return ret; -} - -LLImportMaterial::LLImportMaterial(LLSD& data) -{ - mDiffuseMapFilename = data["diffuse"]["filename"].asString(); - mDiffuseMapLabel = data["diffuse"]["label"].asString(); - mDiffuseColor.setValue(data["diffuse"]["color"]); - mFullbright = data["fullbright"].asBoolean(); - mBinding = data["binding"].asString(); -} - - -LLSD LLImportMaterial::asLLSD() -{ - LLSD ret; - - ret["diffuse"]["filename"] = mDiffuseMapFilename; - ret["diffuse"]["label"] = mDiffuseMapLabel; - ret["diffuse"]["color"] = mDiffuseColor.getValue(); - ret["fullbright"] = mFullbright; - ret["binding"] = mBinding; - - return ret; -} - void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp) { decomp.mMesh.resize(decomp.mHull.size()); diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index c6ccd68cd2..c73511dcd0 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -39,6 +39,8 @@ #include "lluploadfloaterobservers.h" #include "aistatemachinethread.h" +#include + #ifndef BOOST_FUNCTION_HPP_INCLUDED #include #define BOOST_FUNCTION_HPP_INCLUDED @@ -92,54 +94,6 @@ class LLTextureUploadData } }; -class LLImportMaterial -{ -public: - LLPointer mDiffuseMap; - std::string mDiffuseMapFilename; - std::string mDiffuseMapLabel; - std::string mBinding; - LLColor4 mDiffuseColor; - bool mFullbright; - - bool operator<(const LLImportMaterial ¶ms) const; - - LLImportMaterial() - : mFullbright(false) - { - mDiffuseColor.set(1, 1, 1, 1); - } - - LLImportMaterial(LLSD& data); - - LLSD asLLSD(); -}; - -class LLModelInstance -{ -public: - LLPointer mModel; - LLPointer mLOD[5]; - - std::string mLabel; - - LLUUID mMeshID; - S32 mLocalMeshID; - - LLMatrix4 mTransform; - std::map mMaterial; - - LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map& materials) - : mModel(model), mLabel(label), mTransform(transform), mMaterial(materials) - { - mLocalMeshID = -1; - } - - LLModelInstance(LLSD& data); - - LLSD asLLSD(); -}; - class LLPhysicsDecomp : public LLThread { public: @@ -235,33 +189,42 @@ class LLMeshRepoThread : public LLThread std::map mMeshHeaderSize; - class HeaderRequest + struct MeshRequest + { + LLTimer mTimer; + LLVolumeParams mMeshParams; + MeshRequest(const LLVolumeParams& mesh_params) : mMeshParams(mesh_params) + { + mTimer.start(); + } + virtual ~MeshRequest() {} + virtual void preFetch() {} + virtual bool fetch(U32& count) = 0; + }; + class HeaderRequest : public MeshRequest { public: - const LLVolumeParams mMeshParams; - HeaderRequest(const LLVolumeParams& mesh_params) - : mMeshParams(mesh_params) - { - } - + : MeshRequest(mesh_params) + {} + bool fetch(U32& count); bool operator<(const HeaderRequest& rhs) const { return mMeshParams < rhs.mMeshParams; } }; - class LODRequest + class LODRequest : public MeshRequest { public: - LLVolumeParams mMeshParams; S32 mLOD; F32 mScore; LODRequest(const LLVolumeParams& mesh_params, S32 lod) - : mMeshParams(mesh_params), mLOD(lod), mScore(0.f) - { - } + : MeshRequest(mesh_params), mLOD(lod), mScore(0.f) + {} + void preFetch(); + bool fetch(U32& count); }; struct CompareScoreGreater @@ -298,25 +261,27 @@ class LLMeshRepoThread : public LLThread }; //set of requested skin info - std::set mSkinRequests; + uuid_set_t mSkinRequests; //queue of completed skin info requests std::queue mSkinInfoQ; + LLMutex* mSkinInfoQMutex; //set of requested decompositions - std::set mDecompositionRequests; + uuid_set_t mDecompositionRequests; //set of requested physics shapes - std::set mPhysicsShapeRequests; + uuid_set_t mPhysicsShapeRequests; //queue of completed Decomposition info requests std::queue mDecompositionQ; + LLMutex* mDecompositionQMutex; //queue of requested headers - std::queue mHeaderReqQ; + std::deque, F32> > mHeaderReqQ; //queue of requested LODs - std::queue mLODReqQ; + std::deque, F32> > mLODReqQ; //queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD) std::queue mUnavailableQ; @@ -333,6 +298,20 @@ class LLMeshRepoThread : public LLThread LLMeshRepoThread(); ~LLMeshRepoThread(); + void runQueue(std::deque, F32> >& queue, U32& count, S32& active_requests); + void runSet(uuid_set_t& set, std::function fn); + void pushHeaderRequest(const LLVolumeParams& mesh_params, F32 delay = 0) + { + std::shared_ptr req; + req.reset(new LLMeshRepoThread::HeaderRequest(mesh_params)); + mHeaderReqQ.push_back(std::make_pair(req, delay)); + } + void pushLODRequest(const LLVolumeParams& mesh_params, S32 lod, F32 delay = 0) + { + std::shared_ptr req; + req.reset(new LLMeshRepoThread::LODRequest(mesh_params, lod)); + mLODReqQ.push_back(std::make_pair(req, delay)); + } virtual void run(); void lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod); @@ -441,6 +420,7 @@ class LLMeshUploadThread : public AIThreadImpl void setFeeObserverHandle(LLHandle observer_handle) { mFeeObserverHandle = observer_handle; } void setUploadObserverHandle(LLHandle observer_handle) { mUploadObserverHandle = observer_handle; } + LLViewerFetchedTexture* FindViewerTexture(const LLImportMaterial& material); private: LLHandle mFeeObserverHandle; LLHandle mUploadObserverHandle; @@ -476,6 +456,53 @@ class AIMeshUpload : public AIStateMachine /*virtual*/ void multiplex_impl(state_type run_state); }; +// Params related to streaming cost, render cost, and scene complexity tracking. +class LLMeshCostData +{ +public: + LLMeshCostData(); + + bool init(const LLSD& header); + + // Size for given LOD + S32 getSizeByLOD(S32 lod); + + // Sum of all LOD sizes. + S32 getSizeTotal(); + + // Estimated triangle counts for the given LOD. + F32 getEstTrisByLOD(S32 lod); + + // Estimated triangle counts for the largest LOD. Typically this + // is also the "high" LOD, but not necessarily. + F32 getEstTrisMax(); + + // Triangle count as computed by original streaming cost + // formula. Triangles in each LOD are weighted based on how + // frequently they will be seen. + // This was called "unscaled_value" in the original getStreamingCost() functions. + F32 getRadiusWeightedTris(F32 radius); + + // Triangle count used by triangle-based cost formula. Based on + // triangles in highest LOD plus potentially partial charges for + // lower LODs depending on complexity. + F32 getEstTrisForStreamingCost(); + + // Streaming cost. This should match the server-side calculation + // for the corresponding volume. + F32 getRadiusBasedStreamingCost(F32 radius); + + // New streaming cost formula, currently only used for animated objects. + F32 getTriangleBasedStreamingCost(); + +private: + // From the "size" field of the mesh header. LOD 0=lowest, 3=highest. + std::vector mSizeByLOD; + + // Estimated triangle counts derived from the LOD sizes. LOD 0=lowest, 3=highest. + std::vector mEstTrisByLOD; +}; + class LLMeshRepository { public: @@ -490,13 +517,20 @@ class LLMeshRepository static U32 sCacheBytesWritten; static U32 sPeakKbps; - static F32 getStreamingCost(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL); + // Estimated triangle count of the largest LOD + F32 getEstTrianglesMax(LLUUID mesh_id); + F32 getEstTrianglesStreamingCost(LLUUID mesh_id); + F32 getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL); + static F32 getStreamingCostLegacy(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL); + bool getCostData(LLUUID mesh_id, LLMeshCostData& data); + static bool getCostData(LLSD& header, LLMeshCostData& data); LLMeshRepository(); void init(); void shutdown(); + void unregisterMesh(LLVOVolume* volume); //mesh management functions S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1); @@ -528,10 +562,10 @@ class LLMeshRepository S32 getMeshSize(const LLUUID& mesh_id, S32 lod); - typedef std::map > mesh_load_map; + typedef std::map > mesh_load_map; mesh_load_map mLoadingMeshes[4]; - typedef boost::unordered_map skin_map; + typedef absl::node_hash_map skin_map; skin_map mSkinMap; typedef std::map decomposition_map; @@ -542,20 +576,20 @@ class LLMeshRepository std::vector mPendingRequests; //list of mesh ids awaiting skin info - typedef std::map > skin_load_map; + typedef std::map skin_load_map; skin_load_map mLoadingSkins; //list of mesh ids that need to send skin info fetch requests std::queue mPendingSkinRequests; //list of mesh ids awaiting decompositions - std::set mLoadingDecompositions; + uuid_set_t mLoadingDecompositions; //list of mesh ids that need to send decomposition fetch requests std::queue mPendingDecompositionRequests; //list of mesh ids awaiting physics shapes - std::set mLoadingPhysicsShapes; + uuid_set_t mLoadingPhysicsShapes; //list of mesh ids that need to send physics shape fetch requests std::queue mPendingPhysicsShapeRequests; @@ -588,9 +622,11 @@ class LLMeshRepository void updateInventory(inventory_data data); std::string mGetMeshCapability; - }; extern LLMeshRepository gMeshRepo; +const F32 ANIMATED_OBJECT_BASE_COST = 15.0f; +const F32 ANIMATED_OBJECT_COST_PER_KTRI = 1.5f; + #endif diff --git a/indra/newview/llmimetypes.cpp b/indra/newview/llmimetypes.cpp index 60a50fe7ee..697f5e911b 100644 --- a/indra/newview/llmimetypes.cpp +++ b/indra/newview/llmimetypes.cpp @@ -35,6 +35,7 @@ #include "llmimetypes.h" #include "lltrans.h" +#include "llxmlnode.h" #include "lluictrlfactory.h" @@ -84,7 +85,7 @@ bool LLMIMETypes::parseMIMETypes(const std::string& xml_filename) } for (LLXMLNode* node = root->getFirstChild(); - node != NULL; + node != nullptr; node = node->getNextSibling()) { if (node->hasName("defaultlabel")) @@ -105,7 +106,7 @@ bool LLMIMETypes::parseMIMETypes(const std::string& xml_filename) node->getAttributeString("name", mime_type); LLMIMEInfo info; for (LLXMLNode* child = node->getFirstChild(); - child != NULL; + child != nullptr; child = child->getNextSibling()) { if (child->hasName("label")) @@ -129,7 +130,7 @@ bool LLMIMETypes::parseMIMETypes(const std::string& xml_filename) node->getAttributeString("name", set_name); LLMIMEWidgetSet info; for (LLXMLNode* child = node->getFirstChild(); - child != NULL; + child != nullptr; child = child->getNextSibling()) { if (child->hasName("label")) diff --git a/indra/newview/llmimetypes.h b/indra/newview/llmimetypes.h index 3461769ff3..1ac983cd03 100644 --- a/indra/newview/llmimetypes.h +++ b/indra/newview/llmimetypes.h @@ -34,9 +34,6 @@ #ifndef LLMIMETYPES_H #define LLMIMETYPES_H -#include -#include - class LLMIMETypes { public: diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index f6ebe00bf4..aae99afdd9 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -58,6 +58,7 @@ #include "llxfermanager.h" #include "llagent.h" +#include "llavataractions.h" #include "llviewergenericmessage.h" // for gGenericDispatcher #include "llworld.h" //for particle system banning #include "llfloaterchat.h" @@ -71,7 +72,7 @@ namespace { // This method is used to return an object to mute given an object id. // Its used by the LLMute constructor and LLMuteList::isMuted. - LLViewerObject* get_object_to_mute_from_id(LLUUID object_id) + LLViewerObject* get_object_to_mute_from_id(const LLUUID& object_id) { LLViewerObject *objectp = gObjectList.findObject(object_id); if ((objectp) && (!objectp->isAvatar())) @@ -90,11 +91,11 @@ namespace class LLDispatchEmptyMuteList : public LLDispatchHandler { public: - virtual bool operator()( + bool operator()( const LLDispatcher* dispatcher, const std::string& key, const LLUUID& invoice, - const sparam_t& strings) + const sparam_t& strings) override { LLMuteList::getInstance()->setLoaded(); return true; @@ -159,10 +160,10 @@ std::string LLMute::getDisplayType() const LLMuteList* LLMuteList::getInstance() { // Register callbacks at the first time that we find that the message system has been created. - static BOOL registered = FALSE; - if( !registered && gMessageSystem != NULL) + static bool registered = false; + if( !registered && gMessageSystem) { - registered = TRUE; + registered = true; // Register our various callbacks gMessageSystem->setHandlerFuncFast(_PREHASH_MuteListUpdate, processMuteListUpdate); gMessageSystem->setHandlerFuncFast(_PREHASH_UseCachedMuteList, processUseCachedMuteList); @@ -205,7 +206,7 @@ BOOL LLMuteList::isLinden(const std::string& name) const tokenizer::iterator token_iter = tokens.begin(); if (token_iter == tokens.end()) return FALSE; - token_iter++; + ++token_iter; if (token_iter == tokens.end()) return FALSE; std::string last_name = *token_iter; @@ -226,7 +227,7 @@ static LLVOAvatar* find_avatar(const LLUUID& id) } else { - return NULL; + return nullptr; } } @@ -236,6 +237,7 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags) if ((mute.mType == LLMute::AGENT) && isLinden(mute.mName) && (flags & LLMute::flagTextChat || flags == 0)) { + LL_WARNS() << "Trying to mute a Linden; ignored" << LL_ENDL; LLNotifications::instance().add("MuteLinden", LLSD(), LLSD()); return FALSE; } @@ -244,6 +246,7 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags) if (mute.mType == LLMute::AGENT && mute.mID == gAgent.getID()) { + LL_WARNS() << "Trying to self; ignored" << LL_ENDL; return FALSE; } @@ -274,67 +277,67 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags) } else { + LL_INFOS() << "duplicate mute ignored" << LL_ENDL; // was duplicate return FALSE; } } - else + + // Need a local (non-const) copy to set up flags properly. + LLMute localmute = mute; + + // If an entry for the same entity is already in the list, remove it, saving flags as necessary. + mute_set_t::iterator it = mMutes.find(localmute); + bool duplicate = it != mMutes.end(); + if (duplicate) { - // Need a local (non-const) copy to set up flags properly. - LLMute localmute = mute; + // This mute is already in the list. Save the existing entry's flags if that's warranted. + localmute.mFlags = it->mFlags; - // If an entry for the same entity is already in the list, remove it, saving flags as necessary. - mute_set_t::iterator it = mMutes.find(localmute); - if (it != mMutes.end()) - { - // This mute is already in the list. Save the existing entry's flags if that's warranted. - localmute.mFlags = it->mFlags; - - mMutes.erase(it); - // Don't need to call notifyObservers() here, since it will happen after the entry has been re-added below. - } - else - { - // There was no entry in the list previously. Fake things up by making it look like the previous entry had all properties unmuted. - localmute.mFlags = LLMute::flagAll; - } + mMutes.erase(it); + // Don't need to call notifyObservers() here, since it will happen after the entry has been re-added below. + } + else + { + // There was no entry in the list previously. Fake things up by making it look like the previous entry had all properties unmuted. + localmute.mFlags = LLMute::flagAll; + } - if(flags) - { - // The user passed some combination of flags. Make sure those flag bits are turned off (i.e. those properties will be muted). - localmute.mFlags &= (~flags); - } - else - { - // The user passed 0. Make sure all flag bits are turned off (i.e. all properties will be muted). - localmute.mFlags = 0; - } + if(flags) + { + // The user passed some combination of flags. Make sure those flag bits are turned off (i.e. those properties will be muted). + localmute.mFlags &= (~flags); + } + else + { + // The user passed 0. Make sure all flag bits are turned off (i.e. all properties will be muted). + localmute.mFlags = 0; + } - // (re)add the mute entry. - { - std::pair result = mMutes.insert(localmute); - if (result.second) + // (re)add the mute entry. + { + auto result = mMutes.insert(localmute); + if (result.second) + { + LL_INFOS() << "Muting " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << LL_ENDL; + updateAdd(localmute); + notifyObservers(); + notifyObserversDetailed(localmute); + if(!(localmute.mFlags & LLMute::flagParticles)) { - LL_INFOS() << "Muting " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << LL_ENDL; - updateAdd(localmute); - notifyObservers(); - notifyObserversDetailed(localmute); - if(!(localmute.mFlags & LLMute::flagParticles)) - { - //Kill all particle systems owned by muted task - if(localmute.mType == LLMute::AGENT || localmute.mType == LLMute::OBJECT) - { - LLViewerPartSim::getInstance()->clearParticlesByOwnerID(localmute.mID); - } - } - //mute local lights that are attached to the avatar - LLVOAvatar *avatarp = find_avatar(localmute.mID); - if (avatarp) + //Kill all particle systems owned by muted task + if(localmute.mType == LLMute::AGENT || localmute.mType == LLMute::OBJECT) { - LLPipeline::removeMutedAVsLights(avatarp); + LLViewerPartSim::getInstance()->clearParticlesByOwnerID(localmute.mID); } - return TRUE; } + //mute local lights that are attached to the avatar + LLVOAvatar *avatarp = find_avatar(localmute.mID); + if (avatarp) + { + LLPipeline::removeMutedAVsLights(avatarp); + } + return !duplicate; } } @@ -458,7 +461,7 @@ void LLMuteList::updateRemove(const LLMute& mute) gAgent.sendReliableMessage(); } -void notify_automute_callback(const LLUUID& agent_id, const std::string& full_name, bool is_group, LLMuteList::EAutoReason reason) +static void notify_automute_callback(const LLUUID& agent_id, const LLMuteList::EAutoReason& reason) { std::string notif_name; switch (reason) @@ -475,11 +478,7 @@ void notify_automute_callback(const LLUUID& agent_id, const std::string& full_na break; } - LLSD args; - args["NAME"] = full_name; - - LLNotificationPtr notif_ptr = LLNotifications::instance().add(notif_name, args, LLSD()); - if (notif_ptr) + if (auto notif_ptr = LLNotifications::instance().add(notif_name, LLSD().with("NAME", LLAvatarActions::getSLURL(agent_id)), LLSD())) { std::string message = notif_ptr->getMessage(); @@ -506,18 +505,7 @@ BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason) removed = TRUE; remove(automute); - std::string full_name; - if (gCacheName->getFullName(agent_id, full_name)) - { - // name in cache, call callback directly - notify_automute_callback(agent_id, full_name, false, reason); - } - else - { - // not in cache, lookup name from cache - gCacheName->get(agent_id, false, - boost::bind(¬ify_automute_callback, _1, _2, _3, reason)); - } + notify_automute_callback(agent_id, reason); } return removed; @@ -528,18 +516,14 @@ std::vector LLMuteList::getMutes() const { std::vector mutes; - for (mute_set_t::const_iterator it = mMutes.begin(); - it != mMutes.end(); - ++it) + for (const auto& mMute : mMutes) { - mutes.push_back(*it); + mutes.push_back(mMute); } - for (string_set_t::const_iterator it = mLegacyMutes.begin(); - it != mLegacyMutes.end(); - ++it) + for (const auto& mLegacyMute : mLegacyMutes) { - LLMute legacy(LLUUID::null, *it); + LLMute legacy(LLUUID::null, mLegacyMute); mutes.push_back(legacy); } @@ -552,7 +536,7 @@ std::vector LLMuteList::getMutes() const //----------------------------------------------------------------------------- BOOL LLMuteList::loadFromFile(const std::string& filename) { - if(!filename.size()) + if(filename.empty()) { LL_WARNS() << "Mute List Filename is Empty!" << LL_ENDL; return FALSE; @@ -602,7 +586,7 @@ BOOL LLMuteList::loadFromFile(const std::string& filename) //----------------------------------------------------------------------------- BOOL LLMuteList::saveToFile(const std::string& filename) { - if(!filename.size()) + if(filename.empty()) { LL_WARNS() << "Mute List Filename is Empty!" << LL_ENDL; return FALSE; @@ -617,23 +601,19 @@ BOOL LLMuteList::saveToFile(const std::string& filename) // legacy mutes have null uuid std::string id_string; LLUUID::null.toString(id_string); - for (string_set_t::iterator it = mLegacyMutes.begin(); - it != mLegacyMutes.end(); - ++it) + for (const auto& mLegacyMute : mLegacyMutes) { - fprintf(fp, "%d %s %s|\n", (S32)LLMute::BY_NAME, id_string.c_str(), it->c_str()); + fprintf(fp, "%d %s %s|\n", (S32)LLMute::BY_NAME, id_string.c_str(), mLegacyMute.c_str()); } - for (mute_set_t::iterator it = mMutes.begin(); - it != mMutes.end(); - ++it) + for (const auto& mMute : mMutes) { // Don't save external mutes as they are not sent to the server and probably won't //be valid next time anyway. - if (it->mType != LLMute::EXTERNAL) + if (mMute.mType != LLMute::EXTERNAL) { - it->mID.toString(id_string); - const std::string& name = it->mName; - fprintf(fp, "%d %s %s|%u\n", (S32)it->mType, id_string.c_str(), name.c_str(), it->mFlags); + mMute.mID.toString(id_string); + const std::string& name = mMute.mName; + fprintf(fp, "%d %s %s|%u\n", (S32)mMute.mType, id_string.c_str(), name.c_str(), mMute.mFlags); } } fclose(fp); @@ -643,6 +623,9 @@ BOOL LLMuteList::saveToFile(const std::string& filename) BOOL LLMuteList::isMuted(const LLUUID& id, const std::string& name, U32 flags) const { + if (mMutes.empty() && mLegacyMutes.empty()) + return FALSE; + // for objects, check for muting on their parent prim LLViewerObject* mute_object = get_object_to_mute_from_id(id); LLUUID id_to_check = (mute_object) ? mute_object->getID() : id; @@ -676,10 +659,8 @@ BOOL LLMuteList::isMuted(const LLUUID& id, const std::string& name, U32 flags) c //----------------------------------------------------------------------------- void LLMuteList::requestFromServer(const LLUUID& agent_id) { - std::string agent_id_string; - std::string filename; - agent_id.toString(agent_id_string); - filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string) + ".cached_mute"; + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, + llformat("%s.cached_mute", agent_id.asString().c_str())); LLCRC crc; crc.update(filename); @@ -702,10 +683,8 @@ void LLMuteList::cache(const LLUUID& agent_id) // Write to disk even if empty. if(mIsLoaded) { - std::string agent_id_string; - std::string filename; - agent_id.toString(agent_id_string); - filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string) + ".cached_mute"; + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, + llformat("%s.cached_mute", agent_id.asString().c_str())); saveToFile(filename); } } @@ -743,10 +722,8 @@ void LLMuteList::processUseCachedMuteList(LLMessageSystem* msg, void**) { LL_INFOS() << "LLMuteList::processUseCachedMuteList()" << LL_ENDL; - std::string agent_id_string; - gAgent.getID().toString(agent_id_string); - std::string filename; - filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string) + ".cached_mute"; + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, + llformat("%s.cached_mute", gAgent.getID().asString().c_str())); LLMuteList::getInstance()->loadFromFile(filename); } diff --git a/indra/newview/llnamebox.cpp b/indra/newview/llnamebox.cpp index 28381301d3..d20e5429f7 100644 --- a/indra/newview/llnamebox.cpp +++ b/indra/newview/llnamebox.cpp @@ -33,114 +33,93 @@ #include "llviewerprecompiledheaders.h" #include "llnamebox.h" - -#include "llerror.h" -#include "llfontgl.h" -#include "llui.h" -#include "llviewercontrol.h" -#include "lluuid.h" - -#include "llcachename.h" -#include "llagent.h" - -// statics -std::set LLNameBox::sInstances; +#include "llwindow.h" static LLRegisterWidget r("name_box"); - -LLNameBox::LLNameBox(const std::string& name) -: LLTextBox(name, LLRect(), "" , NULL, TRUE) -{ - mNameID = LLUUID::null; - mLink = false; - //mParseHTML = mLink; // STORM-215 - mInitialValue = "(retrieving)"; - LLNameBox::sInstances.insert(this); - setText(LLStringUtil::null); -} - -LLNameBox::~LLNameBox() +LLNameBox::LLNameBox(const std::string& name, + const LLUUID& name_id, + const Type& type, + const std::string& loading, + bool rlv_sensitive, + const std::string& name_system, + bool click_for_profile) +: LLNameUI(loading, rlv_sensitive, name_id, type, name_system, click_for_profile) +, LLTextBox(name, LLRect(), LLStringUtil::null, nullptr, TRUE) { - LLNameBox::sInstances.erase(this); -} - -void LLNameBox::setNameID(const LLUUID& name_id, BOOL is_group) -{ - mNameID = name_id; - - std::string name; - BOOL got_name = FALSE; - - if (!is_group) - { - got_name = gCacheName->getFullName(name_id, name); - } - else + setClickedCallback(boost::bind(&LLNameUI::showProfile, this)); + if (!name_id.isNull()) { - got_name = gCacheName->getGroupName(name_id, name); + setNameID(name_id, type); } - - // Got the name already? Set it. - // Otherwise it will be set later in refresh(). - if (got_name) - setName(name, is_group); - else - setText(mInitialValue); + else setText(mInitialValue); } -void LLNameBox::refresh(const LLUUID& id, const std::string& full_name, bool is_group) +void LLNameBox::displayAsLink(bool link) { - if (id == mNameID) - { - setName(full_name, is_group); - } + static const LLUICachedControl color("HTMLAgentColor"); + setColor(link ? color : LLUI::sColorsGroup->getColor("LabelTextColor")); + setDisabledColor(link ? color : LLUI::sColorsGroup->getColor("LabelDisabledColor")); } -void LLNameBox::refreshAll(const LLUUID& id, const std::string& full_name, bool is_group) +// virtual +BOOL LLNameBox::handleRightMouseDown(S32 x, S32 y, MASK mask) { - std::set::iterator it; - for (it = LLNameBox::sInstances.begin(); - it != LLNameBox::sInstances.end(); - ++it) + auto handled = LLTextBox::handleRightMouseDown(x, y, mask); + if (mAllowInteract && !handled) { - LLNameBox* box = *it; - box->refresh(id, full_name, is_group); + if (mNameID.notNull()) + { + showMenu(this, sMenus[getSelectedType()], x, y); + handled = true; + } } + return handled; } -void LLNameBox::setName(const std::string& name, BOOL is_group) +// virtual +BOOL LLNameBox::handleHover(S32 x, S32 y, MASK mask) { - if (mLink) + auto handled = LLTextBox::handleHover(x, y, mask); + if (mClickForProfile && mAllowInteract) { - std::string url; - - if (is_group) - url = "[secondlife:///app/group/" + mNameID.asString() + "/about " + name + "]"; - else - url = "[secondlife:///app/agent/" + mNameID.asString() + "/about " + name + "]"; - - setText(url); - } - else - { - setText(name); + getWindow()->setCursor(UI_CURSOR_HAND); + handled = true; } + return handled; } // virtual -void LLNameBox::initFromXML(LLXMLNodePtr node, LLView* parent) +LLXMLNodePtr LLNameBox::getXML(bool save_children) const { - LLTextBox::initFromXML(node, parent); - node->getAttributeBOOL("link", mLink); - node->getAttributeString("initial_value", mInitialValue); + LLXMLNodePtr node = LLTextBox::getXML(); + + node->setName("name_box"); + node->createChild("initial_value", TRUE)->setStringValue(mInitialValue); + node->createChild("rlv_sensitive", TRUE)->setBoolValue(mRLVSensitive); + node->createChild("click_for_profile", TRUE)->setBoolValue(mClickForProfile); + node->createChild("name_system", TRUE)->setStringValue(mNameSystem); + + return node; } // static LLView* LLNameBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) { - LLNameBox* name_box = new LLNameBox("name_box"); + S8 type = AVATAR; + node->getAttributeS8("id_type", type); + LLUUID id; + node->getAttributeUUID("id", id); + std::string loading; + node->getAttributeString("initial_value", loading); + bool rlv_sensitive = false; + node->getAttribute_bool("rlv_sensitive", rlv_sensitive); + std::string name_system; + node->getAttributeString("name_system", name_system); + bool click_for_profile = true; + node->getAttribute_bool("click_for_profile", click_for_profile); + LLNameBox* name_box = new LLNameBox("name_box", id, (Type)type, loading, rlv_sensitive, name_system, click_for_profile); name_box->initFromXML(node,parent); + return name_box; } - diff --git a/indra/newview/llnamebox.h b/indra/newview/llnamebox.h index 0d5ec6a834..f27d6bbff3 100644 --- a/indra/newview/llnamebox.h +++ b/indra/newview/llnamebox.h @@ -33,42 +33,34 @@ #ifndef LL_LLNAMEBOX_H #define LL_LLNAMEBOX_H -#include - -#include "llview.h" -#include "llstring.h" -#include "llfontgl.h" +#include "llnameui.h" #include "lltextbox.h" -class LLNameBox +class LLNameBox final : public LLTextBox +, public LLNameUI { public: - virtual void initFromXML(LLXMLNodePtr node, LLView* parent); + LLXMLNodePtr getXML(bool save_children = true) const override final; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - virtual ~LLNameBox(); - - void setNameID(const LLUUID& name_id, BOOL is_group); - - void refresh(const LLUUID& id, const std::string& full_name, bool is_group); - - static void refreshAll(const LLUUID& id, const std::string& full_name, bool is_group); - -protected: - LLNameBox (const std::string& name); - - friend class LLUICtrlFactory; -private: - void setName(const std::string& name, BOOL is_group); - - static std::set sInstances; + void displayAsLink(bool link) override final; + void setText(const std::string& text) override final { LLTextBox::setText(text); } + void setValue(const LLSD& value) override final { LLNameUI::setValue(value); } + LLSD getValue() const override final { return LLNameUI::getValue(); } -private: - LLUUID mNameID; - BOOL mLink; - std::string mInitialValue; + BOOL handleMouseDown(S32 x, S32 y, MASK mask) override final { return mClickForProfile && mAllowInteract && LLTextBox::handleMouseDown(x, y, mask); } + BOOL handleMouseUp(S32 x, S32 y, MASK mask) override final { return mClickForProfile && mAllowInteract && LLTextBox::handleMouseUp(x, y, mask); } + BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override final; + BOOL handleHover(S32 x, S32 y, MASK mask) override final; + LLNameBox(const std::string& name, + const LLUUID& name_id = LLUUID::null, + const Type& type = AVATAR, + const std::string& loading = LLStringUtil::null, + bool rlv_sensitive = false, + const std::string& name_system = LLStringUtil::null, + bool click_for_profile = false); }; #endif diff --git a/indra/newview/llnameeditor.cpp b/indra/newview/llnameeditor.cpp index d7c948d36c..7a10ae3ff6 100644 --- a/indra/newview/llnameeditor.cpp +++ b/indra/newview/llnameeditor.cpp @@ -33,91 +33,85 @@ #include "llviewerprecompiledheaders.h" #include "llnameeditor.h" -#include "llcachename.h" -#include "llagent.h" -#include "llfontgl.h" - -#include "lluuid.h" -#include "llrect.h" -#include "llstring.h" -#include "llui.h" +#include "llmenugl.h" +#include "lluictrlfactory.h" +#include "llwindow.h" static LLRegisterWidget r("name_editor"); -// statics -std::set LLNameEditor::sInstances; - LLNameEditor::LLNameEditor(const std::string& name, const LLRect& rect, - const LLUUID& name_id, - BOOL is_group, + const LLUUID& name_id, + const Type& type, + const std::string& loading, + bool rlv_sensitive, + const std::string& name_system, + bool click_for_profile, const LLFontGL* glfont, S32 max_text_length) -: LLLineEditor(name, rect, - std::string("(retrieving)"), - glfont, - max_text_length), - mNameID(name_id) +: LLNameUI(loading, rlv_sensitive, name_id, type, name_system, click_for_profile) +, LLLineEditor(name, rect, LLStringUtil::null, glfont, max_text_length) { - LLNameEditor::sInstances.insert(this); - if(!name_id.isNull()) + if (!name_id.isNull()) { - setNameID(name_id, is_group); + setNameID(name_id, type); } + else setText(mInitialValue); } - -LLNameEditor::~LLNameEditor() +// virtual +BOOL LLNameEditor::handleMouseDown(S32 x, S32 y, MASK mask) { - LLNameEditor::sInstances.erase(this); + if (mClickForProfile && mAllowInteract) + { + showProfile(); + return true; + } + else return LLLineEditor::handleMouseDown(x, y, mask); } -void LLNameEditor::setNameID(const LLUUID& name_id, BOOL is_group) +// virtual +BOOL LLNameEditor::handleRightMouseDown(S32 x, S32 y, MASK mask) { - mNameID = name_id; - - std::string name; - - if (!is_group) + bool simple_menu = mContextMenuHandle.get()->getName() == "rclickmenu"; + std::string new_menu; + bool needs_simple = !mAllowInteract || mNameID.isNull(); // Need simple if no ID or blocking interaction + if (!simple_menu && needs_simple) // Switch to simple menu { - gCacheName->getFullName(name_id, name); + new_menu = "menu_texteditor.xml"; } - else + else // TODO: This is lazy, but I cannot recall a name editor that switches between group and avatar, so logic is not needed yet. { - gCacheName->getGroupName(name_id, name); + new_menu = mType == GROUP ? "menu_nameeditor_group.xml" : "menu_nameeditor_avatar.xml"; } + if (!new_menu.empty()) setContextMenu(LLUICtrlFactory::instance().buildMenu(new_menu, LLMenuGL::sMenuContainer)); + setActive(); - setText(name); + return LLLineEditor::handleRightMouseDown(x, y, mask); } -void LLNameEditor::refresh(const LLUUID& id, const std::string& full_name, bool is_group) -{ - if (id == mNameID) - { - setText(full_name); - } -} - -void LLNameEditor::refreshAll(const LLUUID& id, const std::string& full_name, bool is_group) +// virtual +BOOL LLNameEditor::handleHover(S32 x, S32 y, MASK mask) { - std::set::iterator it; - for (it = LLNameEditor::sInstances.begin(); - it != LLNameEditor::sInstances.end(); - ++it) + auto handled = LLLineEditor::handleHover(x, y, mask); + if (mAllowInteract && mClickForProfile && !mIsSelecting) { - LLNameEditor* box = *it; - box->refresh(id, full_name, is_group); + getWindow()->setCursor(UI_CURSOR_HAND); + handled = true; } + return handled; } -void LLNameEditor::setValue( const LLSD& value ) +void LLNameEditor::displayAsLink(bool link) { - setNameID(value.asUUID(), FALSE); + static const LLUICachedControl color("HTMLAgentColor"); + setReadOnlyFgColor(link ? color : LLUI::sColorsGroup->getColor("TextFgReadOnlyColor")); } -LLSD LLNameEditor::getValue() const +void LLNameEditor::setText(const std::string& text) { - return LLSD(mNameID); + setToolTip(text); + LLLineEditor::setText(text); } // virtual @@ -126,6 +120,10 @@ LLXMLNodePtr LLNameEditor::getXML(bool save_children) const LLXMLNodePtr node = LLLineEditor::getXML(); node->setName(LL_NAME_EDITOR_TAG); + node->createChild("label", TRUE)->setStringValue(mInitialValue); + node->createChild("rlv_sensitive", TRUE)->setBoolValue(mRLVSensitive); + node->createChild("click_for_profile", TRUE)->setBoolValue(mClickForProfile); + node->createChild("name_system", TRUE)->setStringValue(mNameSystem); return node; } @@ -135,22 +133,28 @@ LLView* LLNameEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory LLRect rect; createRect(node, rect, parent, LLRect()); - S32 max_text_length = 128; + S32 max_text_length = 1024; node->getAttributeS32("max_length", max_text_length); - - LLFontGL* font = LLView::selectFont(node); + S8 type = AVATAR; + node->getAttributeS8("id_type", type); + LLUUID id; + node->getAttributeUUID("id", id); + std::string loading; + node->getAttributeString("label", loading); + bool rlv_sensitive = false; + node->getAttribute_bool("rlv_sensitive", rlv_sensitive); + bool click_for_profile = true; + node->getAttribute_bool("click_for_profile", click_for_profile); + std::string name_system; + node->getAttributeString("name_system", name_system); LLNameEditor* line_editor = new LLNameEditor("name_editor", - rect, - LLUUID::null, FALSE, - font, + rect, + id, (Type)type, loading, rlv_sensitive, name_system, + click_for_profile, + LLView::selectFont(node), max_text_length); - std::string label; - if(node->getAttributeString("label", label)) - { - line_editor->setLabel(label); - } line_editor->setColorParameters(node); line_editor->initFromXML(node, parent); diff --git a/indra/newview/llnameeditor.h b/indra/newview/llnameeditor.h index 6ac6e45383..aa61336123 100644 --- a/indra/newview/llnameeditor.h +++ b/indra/newview/llnameeditor.h @@ -33,50 +33,36 @@ #ifndef LL_LLNAMEEDITOR_H #define LL_LLNAMEEDITOR_H -#include - -#include "llview.h" -#include "v4color.h" -#include "llstring.h" -#include "llfontgl.h" #include "lllineeditor.h" +#include "llnameui.h" - -class LLNameEditor +class LLNameEditor final : public LLLineEditor +, public LLNameUI { public: LLNameEditor(const std::string& name, const LLRect& rect, const LLUUID& name_id = LLUUID::null, - BOOL is_group = FALSE, - const LLFontGL* glfont = NULL, + const Type& type = AVATAR, + const std::string& loading = LLStringUtil::null, + bool rlv_sensitive = false, + const std::string& name_system = LLStringUtil::null, + bool click_for_profile = true, + const LLFontGL* glfont = nullptr, S32 max_text_length = 254); - // By default, follows top and left and is mouse-opaque. - // If no text, text = name. - // If no font, uses default system font. - virtual ~LLNameEditor(); + BOOL handleMouseDown(S32 x, S32 y, MASK mask) override final; + BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override final; + BOOL handleHover(S32 x, S32 y, MASK mask) override final; - virtual LLXMLNodePtr getXML(bool save_children = true) const; + LLXMLNodePtr getXML(bool save_children = true) const override final; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - void setNameID(const LLUUID& name_id, BOOL is_group); - - void refresh(const LLUUID& id, const std::string& full_name, bool is_group); - - static void refreshAll(const LLUUID& id, const std::string& full_name, bool is_group); - - - // Take/return agent UUIDs - virtual void setValue( const LLSD& value ); - virtual LLSD getValue() const; - -private: - static std::set sInstances; - -private: - LLUUID mNameID; + void setValue(const LLSD& value) override final { LLNameUI::setValue(value); } + LLSD getValue() const override final { return LLNameUI::getValue(); } + void displayAsLink(bool link) override final; + void setText(const std::string& text) override final; }; #endif diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 4724eb02a9..f19520b011 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -33,8 +33,12 @@ #include "llavatarnamecache.h" #include "llcachename.h" #include "llagent.h" +#include "llavataractions.h" +#include "llfloaterexperienceprofile.h" +#include "llgroupactions.h" #include "llinventory.h" #include "llscrolllistitem.h" +#include "llscrolllistcell.h" #include "llscrolllistcolumn.h" #include "llsdparam.h" #include "lltrans.h" @@ -42,11 +46,12 @@ static LLRegisterWidget r("name_list"); -void LLNameListCtrl::NameTypeNames::declareValues() +void LLNameListItem::NameTypeNames::declareValues() { - declare("INDIVIDUAL", LLNameListCtrl::INDIVIDUAL); - declare("GROUP", LLNameListCtrl::GROUP); - declare("SPECIAL", LLNameListCtrl::SPECIAL); + declare("INDIVIDUAL", INDIVIDUAL); + declare("GROUP", GROUP); + declare("SPECIAL", SPECIAL); + declare("EXPERIENCE", EXPERIENCE); } LLNameListCtrl::LLNameListCtrl(const std::string& name, const LLRect& rect, BOOL allow_multiple_selection, BOOL draw_border, bool draw_heading, S32 name_column_index, const std::string& name_system, const std::string& tooltip) @@ -61,16 +66,16 @@ LLNameListCtrl::LLNameListCtrl(const std::string& name, const LLRect& rect, BOOL // public LLScrollListItem* LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, - BOOL enabled, const std::string& suffix) + BOOL enabled, const std::string& suffix, const std::string& prefix) { //LL_INFOS() << "LLNameListCtrl::addNameItem " << agent_id << LL_ENDL; NameItem item; item.value = agent_id; item.enabled = enabled; - item.target = INDIVIDUAL; + item.target = LLNameListItem::INDIVIDUAL; - return addNameItemRow(item, pos, suffix); + return addNameItemRow(item, pos, suffix, prefix); } // virtual, public @@ -121,6 +126,52 @@ BOOL LLNameListCtrl::handleDragAndDrop( return handled; } +BOOL LLNameListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + bool handled = LLScrollListCtrl::handleDoubleClick(x, y, mask); + if (!handled) + { + if (auto item = static_cast(hitItem(x, y))) + { + switch (item->getNameType()) + { + case LLNameListItem::INDIVIDUAL: LLAvatarActions::showProfile(item->getValue()); break; + case LLNameListItem::GROUP: LLGroupActions::show(item->getValue()); break; + case LLNameListItem::EXPERIENCE: LLFloaterExperienceProfile::showInstance(item->getValue()); break; + default: return false; + } + handled = true; + } + } + return handled; +} + +#define CONVERT_TO_RETTYPE(nametype, rettype) \ +nametype: \ +{ \ + if (ret == NONE) \ + ret = rettype; \ + else if (ret != rettype) \ + return MULTIPLE; \ + break; \ +} + +LFIDBearer::Type LLNameListCtrl::getSelectedType() const +{ + auto ret = NONE; + for (const auto& item : getAllSelected()) + { + switch (static_cast(item)->getNameType()) + { + CONVERT_TO_RETTYPE(case LLNameListItem::INDIVIDUAL, AVATAR) + CONVERT_TO_RETTYPE(case LLNameListItem::GROUP, GROUP) + CONVERT_TO_RETTYPE(case LLNameListItem::EXPERIENCE, EXPERIENCE) + CONVERT_TO_RETTYPE(default, COUNT) // Invalid, but just use count instead + } + } + return ret; +} +#undef CONVERT_TO_RETTYPE // public void LLNameListCtrl::addGroupNameItem(const LLUUID& group_id, EAddPosition pos, @@ -129,7 +180,7 @@ void LLNameListCtrl::addGroupNameItem(const LLUUID& group_id, EAddPosition pos, NameItem item; item.value = group_id; item.enabled = enabled; - item.target = GROUP; + item.target = LLNameListItem::GROUP; addNameItemRow(item, pos); } @@ -137,13 +188,13 @@ void LLNameListCtrl::addGroupNameItem(const LLUUID& group_id, EAddPosition pos, // public void LLNameListCtrl::addGroupNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos) { - item.target = GROUP; + item.target = LLNameListItem::GROUP; addNameItemRow(item, pos); } LLScrollListItem* LLNameListCtrl::addNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos) { - item.target = INDIVIDUAL; + item.target = LLNameListItem::INDIVIDUAL; return addNameItemRow(item, pos); } @@ -160,12 +211,13 @@ LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, EAddPosition p LLScrollListItem* LLNameListCtrl::addNameItemRow( const LLNameListCtrl::NameItem& name_item, EAddPosition pos, - const std::string& suffix) + const std::string& suffix, + const std::string& prefix) { LLUUID id = name_item.value().asUUID(); - LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP); + LLNameListItem* item = new LLNameListItem(name_item); - if (!item) return NULL; + if (!item) return nullptr; LLScrollListCtrl::addRow(item, name_item, pos); @@ -173,19 +225,31 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( std::string fullname = name_item.name; switch(name_item.target) { - case GROUP: - gCacheName->getGroupName(id, fullname); - // fullname will be "nobody" if group not found + case LLNameListItem::GROUP: + if (!gCacheName->getGroupName(id, fullname)) + { + avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(id); + if (it != mAvatarNameCacheConnections.end()) + { + if (it->second.connected()) + { + it->second.disconnect(); + } + mAvatarNameCacheConnections.erase(it); + } + mAvatarNameCacheConnections[id] = gCacheName->getGroup(id, boost::bind(&LLNameListCtrl::onGroupNameCache, this, _1, _2, item->getHandle())); + } break; - case SPECIAL: + case LLNameListItem::SPECIAL: // just use supplied name break; - case INDIVIDUAL: + case LLNameListItem::INDIVIDUAL: { LLAvatarName av_name; if (id.isNull()) { - fullname = LLTrans::getString("AvatarNameNobody"); + static const auto nobody = LLTrans::getString("AvatarNameNobody"); + fullname = nobody; } else if (LLAvatarNameCache::get(id, &av_name)) { @@ -203,12 +267,12 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( } mAvatarNameCacheConnections.erase(it); } - mAvatarNameCacheConnections[id] = LLAvatarNameCache::get(id,boost::bind(&LLNameListCtrl::onAvatarNameCache,this, _1, _2, suffix, item->getHandle())); + mAvatarNameCacheConnections[id] = LLAvatarNameCache::get(id,boost::bind(&LLNameListCtrl::onAvatarNameCache,this, _1, _2, suffix, prefix, item->getHandle())); if (mPendingLookupsRemaining <= 0) { // BAKER TODO: - // We might get into a state where mPendingLookupsRemainig might + // We might get into a state where mPendingLookupsRemaining might // go negative. So just reset it right now and figure out if it's // possible later :) mPendingLookupsRemaining = 0; @@ -218,6 +282,8 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( } break; } + case LLNameListItem::EXPERIENCE: + // just use supplied name default: break; } @@ -231,7 +297,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( LLScrollListCell* cell = item->getColumn(mNameColumnIndex); if (cell) { - cell->setValue(fullname); + cell->setValue(prefix + fullname); } dirtyColumns(); @@ -271,9 +337,24 @@ void LLNameListCtrl::removeNameItem(const LLUUID& agent_id) } } +// public +LLScrollListItem* LLNameListCtrl::getNameItemByAgentId(const LLUUID& agent_id) +{ + for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++) + { + LLScrollListItem* item = *it; + if (item && item->getUUID() == agent_id) + { + return item; + } + } + return NULL; +} + void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, + std::string prefix, LLHandle item) { avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(agent_id); @@ -295,6 +376,11 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, name.append(suffix); } + if (!prefix.empty()) + { + name.insert(0, prefix); + } + LLNameListItem* list_item = item.get(); if (list_item && list_item->getUUID() == agent_id) { @@ -326,6 +412,33 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, dirtyColumns(); } +void LLNameListCtrl::onGroupNameCache(const LLUUID& group_id, const std::string name, LLHandle item) +{ + avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(group_id); + if (it != mAvatarNameCacheConnections.end()) + { + if (it->second.connected()) + { + it->second.disconnect(); + } + mAvatarNameCacheConnections.erase(it); + } + + LLNameListItem* list_item = item.get(); + if (list_item && list_item->getUUID() == group_id) + { + LLScrollListCell* cell = list_item->getColumn(mNameColumnIndex); + if (cell) + { + cell->setValue(name); + setNeedsSort(); + } + } + + dirtyColumns(); +} + + void LLNameListCtrl::sortByName(BOOL ascending) { sortByColumnIndex(mNameColumnIndex,ascending); @@ -355,13 +468,13 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto LLRect rect; createRect(node, rect, parent, LLRect()); - BOOL multi_select = FALSE; + BOOL multi_select = false; node->getAttributeBOOL("multi_select", multi_select); - BOOL draw_border = TRUE; + BOOL draw_border = true; node->getAttributeBOOL("draw_border", draw_border); - BOOL draw_heading = FALSE; + BOOL draw_heading = false; node->getAttributeBOOL("draw_heading", draw_heading); S32 name_column_index = 0; @@ -388,108 +501,5 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto name_list->initFromXML(node, parent); - LLSD columns; - S32 index = 0; - LLXMLNodePtr child; - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) - { - if (child->hasName("column")) - { - std::string labelname(""); - child->getAttributeString("label", labelname); - - std::string columnname(labelname); - child->getAttributeString("name", columnname); - - std::string sortname(columnname); - child->getAttributeString("sort", sortname); - - if (child->hasAttribute("relative_width")) - { - F32 columnrelwidth = 0.f; - child->getAttributeF32("relative_width", columnrelwidth); - columns[index]["relative_width"] = columnrelwidth; - } - else if (child->hasAttribute("relwidth")) - { - F32 columnrelwidth = 0.f; - child->getAttributeF32("relwidth", columnrelwidth); - columns[index]["relative_width"] = columnrelwidth; - } - else if (child->hasAttribute("dynamic_width")) - { - BOOL columndynamicwidth = FALSE; - child->getAttributeBOOL("dynamic_width", columndynamicwidth); - columns[index]["dynamic_width"] = columndynamicwidth; - } - else if (child->hasAttribute("dynamicwidth")) - { - BOOL columndynamicwidth = FALSE; - child->getAttributeBOOL("dynamicwidth", columndynamicwidth); - columns[index]["dynamic_width"] = columndynamicwidth; - } - else - { - S32 columnwidth = -1; - child->getAttributeS32("width", columnwidth); - columns[index]["width"] = columnwidth; - } - - LLFontGL::HAlign h_align = LLFontGL::LEFT; - h_align = LLView::selectFontHAlign(child); - - columns[index]["name"] = columnname; - columns[index]["label"] = labelname; - columns[index]["halign"] = (S32)h_align; - columns[index]["sort"] = sortname; - - index++; - } - } - name_list->setColumnHeadings(columns); - - - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) - { - if (child->hasName("row")) - { - LLUUID id; - child->getAttributeUUID("id", id); - - LLSD row; - - row["id"] = id; - - S32 column_idx = 0; - LLXMLNodePtr row_child; - for (row_child = node->getFirstChild(); row_child.notNull(); row_child = row_child->getNextSibling()) - { - if (row_child->hasName("column")) - { - std::string value = row_child->getTextContents(); - - std::string columnname(""); - row_child->getAttributeString("name", columnname); - - std::string font(""); - row_child->getAttributeString("font", font); - - std::string font_style(""); - row_child->getAttributeString("font-style", font_style); - - row["columns"][column_idx]["column"] = columnname; - row["columns"][column_idx]["value"] = value; - row["columns"][column_idx]["font"] = font; - row["columns"][column_idx]["font-style"] = font_style; - column_idx++; - } - } - name_list->addElement(row); - } - } - - std::string contents = node->getTextContents(); - name_list->setCommentText(contents); - return name_list; } diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 7f6d3763a6..b1dd64da5f 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -39,67 +39,68 @@ class LLAvatarName; * We don't use LLScrollListItem to be able to override getUUID(), which is needed * because the name list item value is not simply an UUID but a map (uuid, is_group). */ -class LLNameListItem : public LLScrollListItem, public LLHandleProvider +class LLNameListItem final : public LLScrollListItem, public LLHandleProvider { public: - bool isGroup() const { return mIsGroup; } - void setIsGroup(bool is_group) { mIsGroup = is_group; } + enum ENameType + { + INDIVIDUAL, + GROUP, + SPECIAL, + EXPERIENCE + }; + + // provide names for enums + struct NameTypeNames : public LLInitParam::TypeValuesHelper + { + static void declareValues(); + }; + + struct Params : public LLInitParam::Block + { + Optional name; + Optional target; + + Params() + : name("name"), + target("target", INDIVIDUAL) + {} + }; + ENameType getNameType() const { return mNameType; } + void setNameType(ENameType name_type) { mNameType = name_type; } protected: friend class LLNameListCtrl; - LLNameListItem( const LLScrollListItem::Params& p ) - : LLScrollListItem(p), mIsGroup(false) + LLNameListItem( const Params& p ) + : LLScrollListItem(p), mNameType(p.target) { } - LLNameListItem( const LLScrollListItem::Params& p, bool is_group ) - : LLScrollListItem(p), mIsGroup(is_group) + LLNameListItem( const LLScrollListItem::Params& p, ENameType name_type) + : LLScrollListItem(p), mNameType(name_type) { } private: - bool mIsGroup; + ENameType mNameType; }; -class LLNameListCtrl +class LLNameListCtrl final : public LLScrollListCtrl, public LLInstanceTracker { public: typedef boost::signals2::signal namelist_complete_signal_t; - - typedef enum e_name_type - { - INDIVIDUAL, - GROUP, - SPECIAL - } ENameType; - - // provide names for enums - struct NameTypeNames : public LLInitParam::TypeValuesHelper - { - static void declareValues(); - }; - - struct NameItem : public LLInitParam::Block - { - Optional name; - Optional target; - - NameItem() - : name("name"), - target("target", INDIVIDUAL) - {} - }; + typedef LLNameListItem::Params NameItem; struct NameColumn : public LLInitParam::ChoiceBlock { Alternative column_index; Alternative column_name; NameColumn() - : column_name("name_column"), - column_index("name_column_index", 0) + : column_index("name_column_index", 0), + column_name("name_column") {} }; @@ -118,17 +119,18 @@ class LLNameListCtrl } friend class LLUICtrlFactory; public: - virtual LLXMLNodePtr getXML(bool save_children = true) const; + virtual LLXMLNodePtr getXML(bool save_children = true) const override; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); // Add a user to the list by name. It will be added, the name // requested from the cache, and updated as necessary. LLScrollListItem* addNameItem(const LLUUID& agent_id, EAddPosition pos = ADD_BOTTOM, - BOOL enabled = TRUE, const std::string& suffix = LLStringUtil::null); + BOOL enabled = TRUE, const std::string& suffix = LLStringUtil::null, const std::string& prefix = LLStringUtil::null); LLScrollListItem* addNameItem(NameItem& item, EAddPosition pos = ADD_BOTTOM); - /*virtual*/ LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); - LLScrollListItem* addNameItemRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM, const std::string& suffix = LLStringUtil::null); + /*virtual*/ LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL) override; + LLScrollListItem* addNameItemRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM, const std::string& suffix = LLStringUtil::null, + const std::string& prefix = LLStringUtil::null); // Add a user to the list by name. It will be added, the name // requested from the cache, and updated as necessary. @@ -139,22 +141,29 @@ class LLNameListCtrl void removeNameItem(const LLUUID& agent_id); + LLScrollListItem* getNameItemByAgentId(const LLUUID& agent_id); + // LLView interface /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, - std::string& tooltip_msg); + std::string& tooltip_msg) override; + BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override; + + Type getSelectedType() const override final; void setAllowCallingCardDrop(BOOL b) { mAllowCallingCardDrop = b; } void sortByName(BOOL ascending); private: - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, LLHandle item); + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, std::string prefix, LLHandle item); + void onGroupNameCache(const LLUUID& group_id, const std::string name, LLHandle item); private: S32 mNameColumnIndex; + //std::string mNameColumn; BOOL mAllowCallingCardDrop; - const LLCachedControl mNameSystem; + const LLCachedControl mNameSystem; // Singu Note: Instead of mShortNames typedef std::map avatar_name_cache_connection_map_t; avatar_name_cache_connection_map_t mAvatarNameCacheConnections; @@ -162,7 +171,7 @@ class LLNameListCtrl namelist_complete_signal_t mNameListCompleteSignal; public: - boost::signals2::connection setOnNameListCompleteCallback(boost::function onNameListCompleteCallback) + boost::signals2::connection setOnNameListCompleteCallback(std::function onNameListCompleteCallback) { return mNameListCompleteSignal.connect(onNameListCompleteCallback); } diff --git a/indra/newview/llnameui.cpp b/indra/newview/llnameui.cpp new file mode 100644 index 0000000000..5699684cdd --- /dev/null +++ b/indra/newview/llnameui.cpp @@ -0,0 +1,168 @@ +/** + * @file llnameui.cpp + * @brief Name UI refreshes a name and bears a menu for interacting with it + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. 2019, Liru Frs + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llnameui.h" + +#include "llagentdata.h" +#include "llavataractions.h" +#include "llavatarnamecache.h" +#include "llexperiencecache.h" +#include "llfloaterexperienceprofile.h" +#include "llgroupactions.h" +#include "lltrans.h" + +#include "rlvactions.h" +#include "rlvcommon.h" + +// statics +std::set LLNameUI::sInstances; + +LLNameUI::LLNameUI(const std::string& loading, bool rlv_sensitive, const LLUUID& id, const Type& type, const std::string& name_system, bool click_for_profile) +: mNameID(id), mRLVSensitive(rlv_sensitive), mType(NONE), mAllowInteract(false) +, mNameSystem(name_system.empty() ? "PhoenixNameSystem" : name_system), mInitialValue(!loading.empty() ? loading : LLTrans::getString("LoadingData")) +, mClickForProfile(click_for_profile) +{ + setType(type); +} + +void LLNameUI::setType(const Type& type) +{ + // Disconnect active connections if needed + for (auto& connection : mConnections) + connection.disconnect(); + + if (mType != type) + { + if (type == GROUP) + sInstances.insert(this); + else + { + sInstances.erase(this); + if (type == AVATAR) + mConnections[1] = gSavedSettings.getControl(mNameSystem)->getCommitSignal()->connect(boost::bind(&LLNameUI::setNameText, this)); + } + mType = type; + } +} + +void LLNameUI::setNameID(const LLUUID& name_id, const Type& type) +{ + mNameID = name_id; + setType(type); + + if (mAllowInteract = mNameID.notNull()) + { + setNameText(); + } + else + { + setText(LLTrans::getString(mType == GROUP ? "GroupNameNone" : + mType == AVATAR ? "AvatarNameNobody" : "ExperienceNameNull")); + displayAsLink(false); + } +} + +void LLNameUI::setNameText() +{ + std::string name; + bool got_name = false; + + if (mType == GROUP) + { + got_name = gCacheName->getGroupName(mNameID, name); + } + else if (mType == EXPERIENCE) + { + auto& cache = LLExperienceCache::instance(); + const auto& exp = cache.get(mNameID); + if (got_name = exp.isMap()) + name = exp.has(LLExperienceCache::MISSING) && exp[LLExperienceCache::MISSING] ? LLTrans::getString("ExperienceNameNull") : exp[LLExperienceCache::NAME].asString(); + else + cache.get(mNameID, boost::bind(&LLNameUI::setNameText, this)); + } + else + { + LLAvatarName av_name; + if (got_name = LLAvatarNameCache::get(mNameID, &av_name)) + name = mNameSystem.empty() ? av_name.getNSName() : av_name.getNSName(gSavedSettings.getS32(mNameSystem)); + else + mConnections[0] = LLAvatarNameCache::get(mNameID, boost::bind(&LLNameUI::setNameText, this)); + } + + if (mType == AVATAR && got_name && mRLVSensitive) // Filter if needed + { + if ((RlvActions::hasBehaviour(RLV_BHVR_SHOWNAMES) || RlvActions::hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) + && mNameID != gAgentID && RlvUtil::isNearbyAgent(mNameID)) + { + mAllowInteract = false; + name = RlvStrings::getAnonym(name); + } + else mAllowInteract = true; + } + + displayAsLink(mAllowInteract); + + // Got the name already? Set it. + // Otherwise it will be set later in refresh(). + setText(got_name ? name : mInitialValue); +} + +void LLNameUI::refresh(const LLUUID& id, const std::string& full_name) +{ + if (id == mNameID) + { + setNameText(); + } +} + +void LLNameUI::refreshAll(const LLUUID& id, const std::string& full_name) +{ + for (auto box : sInstances) + { + box->refresh(id, full_name); + } +} + +void LLNameUI::showProfile() +{ + if (!mAllowInteract) return; + + switch (mType) + { + case LFIDBearer::GROUP: LLGroupActions::show(mNameID); break; + case LFIDBearer::AVATAR: LLAvatarActions::showProfile(mNameID); break; + case LFIDBearer::EXPERIENCE: LLFloaterExperienceProfile::showInstance(mNameID); break; + default: break; + } +} diff --git a/indra/newview/llnameui.h b/indra/newview/llnameui.h new file mode 100644 index 0000000000..bade1a1cf1 --- /dev/null +++ b/indra/newview/llnameui.h @@ -0,0 +1,86 @@ +/** + * @file llnameui.h + * @brief display and refresh a name from the name cache + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. 2019, Liru Frs + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#pragma once + +#include + +#include "lfidbearer.h" + +struct LLNameUI : public LFIDBearer +{ + LLNameUI(const std::string& loading = LLStringUtil::null, bool rlv_sensitive = false, const LLUUID& id = LLUUID::null, const Type& type = AVATAR, const std::string& name_system = LLStringUtil::null, bool click_for_profile = true); + virtual ~LLNameUI() + { + if (mType == GROUP) sInstances.erase(this); + for (auto& connection : mConnections) + connection.disconnect(); + } + + LLUUID getStringUUIDSelectedItem() const override final { return mNameID; } + Type getSelectedType() const override final { return mType; } + + void setType(const Type& type); + void setNameID(const LLUUID& name_id, const Type& type); + void setNameText(); // Sets the name to whatever the name cache has at the moment + void refresh(const LLUUID& id, const std::string& name); + static void refreshAll(const LLUUID& id, const std::string& name); + + void showProfile(); + + virtual void displayAsLink(bool link) = 0; // Override to make the name display as a link + virtual void setText(const std::string& text) = 0; + + // Take either UUID or a map of "id" to UUID and "group" to boolean + virtual void setValue(const LLSD& value) + { + if (value.has("id")) + setNameID(value["id"].asUUID(), (Type)value["type"].asInteger()); + else + setNameID(value.asUUID(), mType); + } + // Return agent UUIDs + virtual LLSD getValue() const { return LLSD(mNameID); } + +private: + static std::set sInstances; + std::array mConnections; + +protected: + LLUUID mNameID; + bool mRLVSensitive; // Whether or not we're doing RLV filtering + Type mType; + bool mAllowInteract; + std::string mInitialValue; + std::string mNameSystem; + bool mClickForProfile; +}; diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index d9fe32e4ea..727597f244 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -53,6 +53,7 @@ #include "llavatarnamecache.h" #include "llcallingcard.h" #include "llcolorscheme.h" +#include "llfloatermap.h" #include "llfloaterworldmap.h" #include "llframetimer.h" // [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3.0) @@ -84,6 +85,82 @@ // [/RLVa:KB] using namespace LLOldEvents; +typedef LLMemberListener view_listener_t; + +class LLScaleMap : public view_listener_t +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; + +class LLChatRings : public view_listener_t +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; + +class LLCheckChatRings : public view_listener_t +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; + +class LLStopTracking : public view_listener_t +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; + +class LLIsTracking : public view_listener_t +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; + +//moymod - Custom minimap markers :o +class mmsetred : public view_listener_t //moymod +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; +class mmsetgreen : public view_listener_t //moymod +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; +class mmsetblue : public view_listener_t //moymod +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; +class mmsetyellow : public view_listener_t //moymod +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; +class mmsetcustom : public view_listener_t //moymod +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; +class mmsetunmark : public view_listener_t //moymod +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; +class mmenableunmark : public view_listener_t //moymod +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; + +// [SL:KB] - Patch: World-MiniMap | Checked: 2012-07-08 (Catznip-3.3.0) +class OverlayToggle : public view_listener_t +{ +public: + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override final; +}; +// [/SL:KB] const F32 LLNetMap::MAP_SCALE_MIN = 32; const F32 LLNetMap::MAP_SCALE_MID = 256; @@ -103,7 +180,7 @@ const S32 CIRCLE_STEPS = 100; const F64 COARSEUPDATE_MAX_Z = 1020.0f; std::map LLNetMap::mClosestAgentsToCursor; // -static std::map mClosestAgentsAtLastClick; // +uuid_vec_t LLNetMap::mClosestAgentsAtLastClick; // LLNetMap::LLNetMap(const std::string& name) : LLPanel(name), @@ -132,8 +209,6 @@ LLNetMap::LLNetMap(const std::string& name) : mClosestAgentToCursor(), mPopupMenu(NULL) { - mPixelsPerMeter = mScale / REGION_WIDTH_METERS; - mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS); setScale(gSavedSettings.getF32("MiniMapScale")); LLUICtrlFactory::getInstance()->buildPanel(this, "panel_mini_map.xml"); @@ -146,26 +221,29 @@ LLNetMap::~LLNetMap() BOOL LLNetMap::postBuild() { + mELabel = getChild("e_label"); + mNLabel = getChild("n_label"); + mWLabel = getChild("w_label"); + mSLabel = getChild("s_label"); + mNELabel = getChild("ne_label"); + mNWLabel = getChild("nw_label"); + mSWLabel = getChild("sw_label"); + mSELabel = getChild("se_label"); + // Register event listeners for popup menu - (new LLScaleMap())->registerListener(this, "MiniMap.ZoomLevel"); - (new LLCenterMap())->registerListener(this, "MiniMap.Center"); - (new LLCheckCenterMap())->registerListener(this, "MiniMap.CheckCenter"); - (new LLChatRings())->registerListener(this, "MiniMap.ChatRings"); - (new LLCheckChatRings())->registerListener(this, "MiniMap.CheckChatRings"); - (new LLStopTracking())->registerListener(this, "MiniMap.StopTracking"); - (new LLEnableTracking())->registerListener(this, "MiniMap.EnableTracking"); - (new LLShowAgentProfile())->registerListener(this, "MiniMap.ShowProfile"); - (new LLEnableProfile())->registerListener(this, "MiniMap.EnableProfile"); - (new LLCamFollow())->registerListener(this, "MiniMap.CamFollow"); //moymod - add cam follow crap thingie - (new mmsetred())->registerListener(this, "MiniMap.setred"); - (new mmsetgreen())->registerListener(this, "MiniMap.setgreen"); - (new mmsetblue())->registerListener(this, "MiniMap.setblue"); - (new mmsetyellow())->registerListener(this, "MiniMap.setyellow"); - (new mmsetcustom())->registerListener(this, "MiniMap.setcustom"); - (new mmsetunmark())->registerListener(this, "MiniMap.setunmark"); - (new mmenableunmark())->registerListener(this, "MiniMap.enableunmark"); - (new LLToggleControl())->registerListener(this, "MiniMap.ToggleControl"); - (new OverlayToggle())->registerListener(this, "Minimap.ToggleOverlay"); + (new LLScaleMap())->registerListener(gMenuHolder, "MiniMap.ZoomLevel"); + (new LLChatRings())->registerListener(gMenuHolder, "MiniMap.ChatRings"); + (new LLCheckChatRings())->registerListener(gMenuHolder, "MiniMap.CheckChatRings"); + (new LLStopTracking())->registerListener(gMenuHolder, "StopTracking"); + (new LLIsTracking())->registerListener(gMenuHolder, "IsTracking"); + (new mmsetred())->registerListener(gMenuHolder, "MiniMap.setred"); + (new mmsetgreen())->registerListener(gMenuHolder, "MiniMap.setgreen"); + (new mmsetblue())->registerListener(gMenuHolder, "MiniMap.setblue"); + (new mmsetyellow())->registerListener(gMenuHolder, "MiniMap.setyellow"); + (new mmsetcustom())->registerListener(gMenuHolder, "MiniMap.setcustom"); + (new mmsetunmark())->registerListener(gMenuHolder, "MiniMap.setunmark"); + (new mmenableunmark())->registerListener(gMenuHolder, "MiniMap.enableunmark"); + (new OverlayToggle())->registerListener(gMenuHolder, "Minimap.ToggleOverlay"); // [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3.0) LLViewerParcelMgr::instance().setCollisionUpdateCallback(boost::bind(&LLNetMap::refreshParcelOverlay, this)); @@ -174,7 +252,7 @@ BOOL LLNetMap::postBuild() updateMinorDirections(); - mPopupMenu = LLUICtrlFactory::getInstance()->buildMenu("menu_mini_map.xml", this); + mPopupMenu = LLUICtrlFactory::getInstance()->buildMenu("menu_mini_map.xml", gMenuHolder); if (!mPopupMenu) mPopupMenu = new LLMenuGL(LLStringUtil::null); mPopupMenu->setVisible(FALSE); return TRUE; @@ -218,15 +296,31 @@ std::size_t hash_value(const LLUUID& uuid) return (std::size_t)uuid.getCRC32(); } boost::unordered_map mm_MarkerColors; +const LLColor4* mm_getMarkerColor(const LLUUID& id, bool mark_only) +{ + if (!mark_only) // They're trying to get the color and they're not the minimap or the radar mark + { + static const LLCachedControl use_marked_color("LiruUseMarkedColor"); + if (!use_marked_color) return nullptr; + } + auto it = mm_MarkerColors.find(id); + return it == mm_MarkerColors.end() ? nullptr : &it->second; +} +const LLColor4* mm_getMarkerColor(const LLUUID& id) { return mm_getMarkerColor(id, false); } + bool mm_getMarkerColor(const LLUUID& id, LLColor4& color) { - boost::unordered_map::const_iterator it = mm_MarkerColors.find(id); - if (it == mm_MarkerColors.end()) return false; - color = it->second; - return true; + auto c = mm_getMarkerColor(id); + if (c) color = *c; + return c; } -void LLNetMap::mm_setcolor(LLUUID key,LLColor4 col) +void mm_clearMark(const LLUUID& id) +{ + mm_MarkerColors.erase(id); +} + +void mm_setcolor(LLUUID key,LLColor4 col) { mm_MarkerColors[key] = col; } @@ -259,30 +353,21 @@ void LLNetMap::draw() } // [/SL:KB] - static LLUICachedControl center("MiniMapCenter"); - if (center != MAP_CENTER_NONE) + static const LLUICachedControl center("MiniMapCenter"); + if (center) { - mCurPan = lerp(mCurPan, mTargetPan, LLCriticalDamp::getInterpolant(0.1f)); + mCurPan = lerp(mCurPan, mTargetPan, LLSmoothInterpolation::getInterpolant(0.1f)); } // Prepare a scissor region F32 rotation = 0; - gGL.pushMatrix(); gGL.pushUIMatrix(); - - LLVector3 offset = gGL.getUITranslation(); - LLVector3 scale = gGL.getUIScale(); - gGL.loadIdentity(); - gGL.loadUIIdentity(); - gGL.scalef(scale.mV[0], scale.mV[1], scale.mV[2]); - gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]); { LLLocalClipRect clip(getLocalRect()); { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.matrixMode(LLRender::MM_MODELVIEW); // Draw background rectangle. if(isBackgroundVisible()) @@ -297,15 +382,16 @@ void LLNetMap::draw() S32 center_sw_left = getRect().getWidth() / 2 + llfloor(mCurPan.mV[VX]); S32 center_sw_bottom = getRect().getHeight() / 2 + llfloor(mCurPan.mV[VY]); - gGL.pushMatrix(); - gGL.translatef( (F32) center_sw_left, (F32) center_sw_bottom, 0.f); + gGL.pushUIMatrix(); + gGL.translateUI( (F32) center_sw_left, (F32) center_sw_bottom, 0.f); static LLCachedControl rotate_map("MiniMapRotate", true); if (rotate_map) { // Rotate subsequent draws to agent rotation. rotation = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ); - gGL.rotatef( rotation * RAD_TO_DEG, 0.f, 0.f, 1.f); + LLQuaternion rot(rotation, LLVector3(0.f, 0.f, 1.f)); + gGL.rotateUI(rot); } // Figure out where agent is. @@ -351,9 +437,9 @@ void LLNetMap::draw() { const LLViewerRegion::tex_matrix_t& tiles(regionp->getWorldMapTiles()); - for (S32 i(0), scaled_width(real_width/region_width), square_width(scaled_width*scaled_width); i < square_width; ++i) + for (S32 i(0), scaled_width((S32)real_width/region_width), square_width(scaled_width*scaled_width); i < square_width; ++i) { - const F32 y(i/scaled_width); + const F32 y(i / (F32)scaled_width); const F32 x(i - y*scaled_width); const F32 local_left(left + x*mScale); const F32 local_right(local_left + mScale); @@ -363,15 +449,15 @@ void LLNetMap::draw() if (pRegionImage && pRegionImage->hasGLTexture()) { gGL.getTexUnit(0)->bind(pRegionImage); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(local_left, local_top); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(local_left, local_bottom); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2f(local_right, local_bottom); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(local_right, local_top); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2f(local_right, local_bottom); gGL.end(); pRegionImage->setBoostLevel(LLViewerTexture::BOOST_MAP_VISIBLE); @@ -387,15 +473,15 @@ void LLNetMap::draw() // [/SL:KB] // Draw using texture. gGL.getTexUnit(0)->bind(regionp->getLand().getSTexture()); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(left, top); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(left, bottom); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2f(right, bottom); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(right, top); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2f(right, bottom); gGL.end(); // Draw water @@ -404,15 +490,15 @@ void LLNetMap::draw() if (regionp->getLand().getWaterTexture()) { gGL.getTexUnit(0)->bind(regionp->getLand().getWaterTexture()); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(left, top); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(left, bottom); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2f(right, bottom); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(right, top); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2f(right, bottom); gGL.end(); } } @@ -502,15 +588,15 @@ void LLNetMap::draw() { gGL.getTexUnit(0)->bind(mObjectImagep); // [/SL:KB] - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, image_half_height + map_center_agent.mV[VY]); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, map_center_agent.mV[VY] - image_half_height); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2f(image_half_width + map_center_agent.mV[VX], map_center_agent.mV[VY] - image_half_height); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(image_half_width + map_center_agent.mV[VX], image_half_height + map_center_agent.mV[VY]); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2f(image_half_width + map_center_agent.mV[VX], map_center_agent.mV[VY] - image_half_height); gGL.end(); // [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-07-26 (Catznip-3.3) } @@ -524,20 +610,20 @@ void LLNetMap::draw() map_center_agent.mV[VY] *= mScale / region_width; gGL.getTexUnit(0)->bind(mParcelImagep); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, image_half_height + map_center_agent.mV[VY]); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, map_center_agent.mV[VY] - image_half_height); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2f(image_half_width + map_center_agent.mV[VX], map_center_agent.mV[VY] - image_half_height); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(image_half_width + map_center_agent.mV[VX], image_half_height + map_center_agent.mV[VY]); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2f(image_half_width + map_center_agent.mV[VX], map_center_agent.mV[VY] - image_half_height); gGL.end(); } // [/SL:KB] - gGL.popMatrix(); + gGL.popUIMatrix(); // Mouse pointer in local coordinates S32 local_mouse_x; @@ -568,14 +654,14 @@ void LLNetMap::draw() gmSelected = LLFloaterAvatarList::instance().getSelectedIDs(); // Draw avatars - for(LLWorld::pos_map_t::const_iterator iter = positions.cbegin(), iter_end = positions.cend(); iter != iter_end; ++iter) + for(const auto& pair : positions) { - const LLUUID& uuid = iter->first; + const LLUUID& uuid = pair.first; static const LLCachedControl standard_color("MapAvatar",LLColor4(0.f,1.f,0.f,1.f)); LLColor4 color = standard_color; // TODO: it'd be very cool to draw these in sorted order from lowest Z to highest. // just be careful to sort the avatar IDs along with the positions. -MG - const LLVector3d& position = iter->second; + const LLVector3d& position = pair.second; pos_map = globalPosToView(position); if (position.mdV[VZ] == 0.f || position.mdV[VZ] == COARSEUPDATE_MAX_Z) { @@ -588,10 +674,14 @@ void LLNetMap::draw() static const LLCachedControl map_avatar_rollover_color(gSavedSettings, "ExodusMapRolloverColor", LLColor4::cyan); color = map_avatar_rollover_color; } + else if (auto mark_color = mm_getMarkerColor(uuid, true)) + { + color = *mark_color; + } else { - bool getCustomColorRLV(const LLUUID&, LLColor4&, LLViewerRegion*, bool name_restricted); - getCustomColorRLV(uuid, color, LLWorld::getInstance()->getRegionFromPosGlobal(position), !show_friends); + bool getColorFor(const LLUUID & id, LLViewerRegion * parent_estate, LLColor4 & color, bool name_restricted = false); + getColorFor(uuid, LLWorld::getInstance()->getRegionFromPosGlobal(position), color, !show_friends); } LLWorldMapView::drawAvatar( @@ -707,38 +797,30 @@ void LLNetMap::draw() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (rotate_map) - { - LLColor4 c = map_frustum_color(); - - gGL.begin( LLRender::TRIANGLES ); - gGL.color4fv(c.mV); - gGL.vertex2f( ctr_x, ctr_y ); - c.mV[VW] *= .1f; - gGL.color4fv(c.mV); - gGL.vertex2f( ctr_x - half_width_pixels, ctr_y + far_clip_pixels ); - gGL.vertex2f( ctr_x + half_width_pixels, ctr_y + far_clip_pixels ); - gGL.end(); - } - else + LLColor4 c = rotate_map ? map_frustum_color() : map_frustum_rotating_color(); + + gGL.pushUIMatrix(); + + gGL.translateUI(ctr_x, ctr_y, 0); + + // If we don't rotate the map, we have to rotate the frustum. + if (!rotate_map) { - LLColor4 c = map_frustum_rotating_color(); - - // If we don't rotate the map, we have to rotate the frustum. - gGL.pushMatrix(); - gGL.translatef( ctr_x, ctr_y, 0 ); - gGL.rotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f); - gGL.begin( LLRender::TRIANGLES ); - gGL.color4fv(c.mV); - gGL.vertex2f( 0.f, 0.f ); - c.mV[VW] *= .1f; - gGL.color4fv(c.mV); - gGL.vertex2f( -half_width_pixels, far_clip_pixels ); - gGL.vertex2f( half_width_pixels, far_clip_pixels ); - gGL.end(); - gGL.popMatrix(); + LLQuaternion rot(atan2(LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY]), LLVector3(0.f, 0.f, -1.f)); + gGL.rotateUI(rot); } + gGL.begin( LLRender::TRIANGLES ); + gGL.color4fv(c.mV); + gGL.vertex2f( 0, 0 ); + c.mV[VW] *= .1f; + gGL.color4fv(c.mV); + gGL.vertex2f( half_width_pixels, far_clip_pixels ); + gGL.vertex2f( -half_width_pixels, far_clip_pixels ); + gGL.end(); + + gGL.popUIMatrix(); + // Draw mouse radius static const LLCachedControl map_avatar_rollover_color("ExodusMapRolloverCircleColor"); gGL.color4fv((map_avatar_rollover_color()).mV); @@ -746,20 +828,19 @@ void LLNetMap::draw() gl_circle_2d(local_mouse_x, local_mouse_y, min_pick_dist, 32, true); // } - - gGL.popMatrix(); + ; gGL.popUIMatrix(); // Rotation of 0 means that North is up - setDirectionPos( getChild("e_label"), rotation); - setDirectionPos( getChild("n_label"), rotation + F_PI_BY_TWO); - setDirectionPos( getChild("w_label"), rotation + F_PI); - setDirectionPos( getChild("s_label"), rotation + F_PI + F_PI_BY_TWO); + setDirectionPos(mELabel, rotation); + setDirectionPos(mNLabel, rotation + F_PI_BY_TWO); + setDirectionPos(mWLabel, rotation + F_PI); + setDirectionPos(mSLabel, rotation + F_PI + F_PI_BY_TWO); - setDirectionPos( getChild("ne_label"), rotation + F_PI_BY_TWO / 2); - setDirectionPos( getChild("nw_label"), rotation + F_PI_BY_TWO + F_PI_BY_TWO / 2); - setDirectionPos( getChild("sw_label"), rotation + F_PI + F_PI_BY_TWO / 2); - setDirectionPos( getChild("se_label"), rotation + F_PI + F_PI_BY_TWO + F_PI_BY_TWO / 2); + setDirectionPos(mNELabel, rotation + F_PI_BY_TWO / 2); + setDirectionPos(mNWLabel, rotation + F_PI_BY_TWO + F_PI_BY_TWO / 2); + setDirectionPos(mSWLabel, rotation + F_PI + F_PI_BY_TWO / 2); + setDirectionPos(mSELabel, rotation + F_PI + F_PI_BY_TWO + F_PI_BY_TWO / 2); LLUICtrl::draw(); } @@ -780,9 +861,6 @@ LLVector3 LLNetMap::globalPosToView(const LLVector3d& global_pos) LLVector3 pos_local; pos_local.setVec(relative_pos_global); // convert to floats from doubles -// Aurora Sim - mPixelsPerMeter = mScale / REGION_WIDTH_METERS; -// Aurora Sim pos_local.mV[VX] *= mPixelsPerMeter; pos_local.mV[VY] *= mPixelsPerMeter; // leave Z component in meters @@ -803,17 +881,12 @@ LLVector3 LLNetMap::globalPosToView(const LLVector3d& global_pos) void LLNetMap::drawRing(const F32 radius, const LLVector3 pos_map, const LLColor4& color) { -// Aurora Sim - F32 meters_to_pixels = mScale / LLWorld::getInstance()->getRegionWidthInMeters(); - //F32 meters_to_pixels = mScale / REGION_WIDTH_METERS; -// Aurora Sim - F32 radius_pixels = radius * meters_to_pixels; + F32 radius_pixels = radius * mPixelsPerMeter; - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.translatef((F32)pos_map.mV[VX], (F32)pos_map.mV[VY], 0.f); - gl_ring(radius_pixels, WIDTH_PIXELS, color, color, CIRCLE_STEPS, FALSE); - gGL.popMatrix(); + gGL.pushUIMatrix(); + gGL.translateUI(pos_map.mV[VX], pos_map.mV[VY], 0.f); + gl_washer_2d(radius_pixels, radius_pixels-WIDTH_PIXELS, CIRCLE_STEPS, color, color); + gGL.popUIMatrix(); } void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color, @@ -885,8 +958,8 @@ BOOL LLNetMap::handleScrollWheel(S32 x, S32 y, S32 clicks) setScale(new_scale); - static LLUICachedControl center("MiniMapCenter"); - if (center == MAP_CENTER_NONE) + static const LLUICachedControl center("MiniMapCenter"); + if (!center) { // Adjust pan to center the zoom on the mouse pointer LLVector2 zoom_offset; @@ -915,7 +988,7 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& tool_tip, LLRect* stick sticky_rect.mRight = sticky_rect.mLeft + 2 * SLOP; sticky_rect.mTop = sticky_rect.mBottom + 2 * SLOP; - tool_tip.assign(""); + tool_tip.clear(); if (region->mMapAvatarIDs.size()) { @@ -927,12 +1000,10 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& tool_tip, LLRect* stick LLVector3d myPosition = gAgent.getPositionGlobal(); - std::map::iterator current = mClosestAgentsToCursor.begin(); - std::map::iterator end = mClosestAgentsToCursor.end(); - for (; current != end; ++current) + for (const auto& target : mClosestAgentsToCursor) { - LLUUID targetUUID = (*current).first; - LLVector3d targetPosition = (*current).second; + const auto& targetUUID = target.first; + auto targetPosition = target.second; std::string fullName; if (targetUUID.notNull() && LLAvatarNameCache::getNSName(targetUUID, fullName)) @@ -954,12 +1025,12 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& tool_tip, LLRect* stick LLVector3d delta = targetPosition - myPosition; F32 distance = (F32)delta.magVec(); if (single_agent) - tool_tip.append( llformat("\n\n(Distance: %.02fm)\n",distance) ); + tool_tip.append( llformat("\n(Distance: %.02fm)\n",distance) ); else tool_tip.append(llformat(" (%.02fm)\n", distance)); } } - tool_tip.append("\n"); + tool_tip += '\n'; } } // [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-04 (RLVa-1.0.0a) | Modified: RLVa-0.2.0b @@ -967,9 +1038,9 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& tool_tip, LLRect* stick // [/RLVa:KB] //tool_tip.append("\n\n" + region->getName()); - tool_tip.append("\n" + region->getHost().getHostName()); - tool_tip.append("\n" + region->getHost().getString()); - tool_tip.append("\n" + getToolTip()); + tool_tip.append('\n' + region->getHost().getHostName()); + tool_tip.append('\n' + region->getHost().getString()); + tool_tip.append('\n' + getToolTip()); } else { @@ -998,19 +1069,16 @@ void LLNetMap::setDirectionPos( LLTextBox* text_box, F32 rotation ) void LLNetMap::updateMinorDirections() { - if (getChild("ne_label", TRUE, FALSE) == NULL) - { - return; - } + if (!mNELabel) return; // Hide minor directions if they cover too much of the map - bool show_minors = getChild("ne_label")->getRect().getHeight() < MAP_MINOR_DIR_THRESHOLD * + bool show_minors = mNELabel->getRect().getHeight() < MAP_MINOR_DIR_THRESHOLD * llmin(getRect().getWidth(), getRect().getHeight()); - getChild("ne_label")->setVisible(show_minors); - getChild("nw_label")->setVisible(show_minors); - getChild("sw_label")->setVisible(show_minors); - getChild("se_label")->setVisible(show_minors); + mNELabel->setVisible(show_minors); + mNWLabel->setVisible(show_minors); + mSWLabel->setVisible(show_minors); + mSELabel->setVisible(show_minors); } void LLNetMap::renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &color, F32 radius_meters ) @@ -1128,7 +1196,7 @@ void LLNetMap::renderPropertyLinesForRegion(const LLViewerRegion* pRegion, const // Draw the north and east region borders // const F32 real_width(pRegion->getWidth()); -const S32 borderY = originY + ll_round(real_width * mObjectMapTPM); + const S32 borderY = originY + ll_round(real_width * mObjectMapTPM); if ( (borderY >= 0) && (borderY < imgHeight) ) { S32 curX = llclamp(originX, 0, imgWidth), endX = llclamp(originX + ll_round(real_width * mObjectMapTPM), 0, imgWidth - 1); @@ -1146,8 +1214,8 @@ const S32 borderY = originY + ll_round(real_width * mObjectMapTPM); // // Render parcel lines // - static const F32 GRID_STEP = PARCEL_GRID_STEP_METERS; - static const S32 GRIDS_PER_EDGE = real_width / GRID_STEP; + const F32 GRID_STEP = PARCEL_GRID_STEP_METERS; + const S32 GRIDS_PER_EDGE = real_width / GRID_STEP; const U8* pOwnership = pRegion->getParcelOverlay()->getOwnership(); const U8* pCollision = (pRegion->getHandle() == LLViewerParcelMgr::instance().getCollisionRegionHandle()) ? LLViewerParcelMgr::instance().getCollisionBitmap() : NULL; @@ -1310,29 +1378,29 @@ BOOL LLNetMap::handleMouseUp( S32 x, S32 y, MASK mask ) } // [SL:KB] - Patch: World-MiniMap | Checked: 2012-07-08 (Catznip-3.3.0) -bool LLNetMap::OverlayToggle::handleEvent(LLPointer event, const LLSD& sdParam) +bool OverlayToggle::handleEvent(LLPointer event, const LLSD& sdParam) { - // Toggle the setting - const std::string strControl = sdParam.asString(); - BOOL fCurValue = gSavedSettings.getBOOL(strControl); - gSavedSettings.setBOOL(strControl, !fCurValue); - // Force an overlay update - mPtr->mUpdateParcelImage = true; + LLFloaterMap::findInstance()->mPanelMap->mUpdateParcelImage = true; return true; } // [/SL:KB] BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask) { - mClosestAgentsAtLastClick = mClosestAgentsToCursor; + mClosestAgentsAtLastClick.clear(); + mClosestAgentsAtLastClick.reserve(mClosestAgentsToCursor.size()); + for (const auto& pair : mClosestAgentsToCursor) + mClosestAgentsAtLastClick.push_back(pair.first); mClosestAgentAtLastRightClick = mClosestAgentToCursor; if (mPopupMenu) { - // Singu TODO: It'd be spectacular to address multiple avatars from here. - mPopupMenu->buildDrawLabels(); - mPopupMenu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, mPopupMenu, x, y); + showMenu(this, mPopupMenu, x, y); + mPopupMenu->getChildView("avs_menu")->setVisible(!mClosestAgentsAtLastClick.empty() && ! +// [RLVa:LF] - 2019 + gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) +// [/RLVa:LF] + ); } return TRUE; } @@ -1423,22 +1491,22 @@ BOOL LLNetMap::handleHover( S32 x, S32 y, MASK mask ) } // static -bool LLNetMap::LLScaleMap::handleEvent(LLPointer event, const LLSD& userdata) +bool LLScaleMap::handleEvent(LLPointer event, const LLSD& userdata) { - LLNetMap *self = mPtr; + auto self = LLFloaterMap::findInstance()->mPanelMap; S32 level = userdata.asInteger(); switch(level) { case 0: - self->setScale(MAP_SCALE_MIN); + self->setScale(LLNetMap::MAP_SCALE_MIN); break; case 1: - self->setScale(MAP_SCALE_MID); + self->setScale(LLNetMap::MAP_SCALE_MID); break; case 2: - self->setScale(MAP_SCALE_MAX); + self->setScale(LLNetMap::MAP_SCALE_MAX); break; default: break; @@ -1450,149 +1518,94 @@ bool LLNetMap::LLScaleMap::handleEvent(LLPointer event, const LLSD& use //moymod - minimap color shit void markMassAgents(const LLColor4& color) { - std::map::iterator current = mClosestAgentsAtLastClick.begin(); - std::map::iterator end = mClosestAgentsAtLastClick.end(); - for(; current != end; ++current) LLNetMap::mm_setcolor((*current).first, color); + auto radar = LLFloaterAvatarList::getInstance(); + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + { + mm_setcolor(id, color); + if (auto entry = radar ? radar->getAvatarEntry(id) : nullptr) + entry->setMarked(true); + } } -bool LLNetMap::mmsetred::handleEvent(LLPointer, const LLSD&) -{ - markMassAgents(LLColor4::red); return true; -} -bool LLNetMap::mmsetgreen::handleEvent(LLPointer, const LLSD&) -{ - markMassAgents(LLColor4::green); return true; -} -bool LLNetMap::mmsetblue::handleEvent(LLPointer, const LLSD&) +bool mmsetred::handleEvent(LLPointer, const LLSD&) { - markMassAgents(LLColor4::blue); return true; + markMassAgents(LLColor4::red); + return true; } -bool LLNetMap::mmsetyellow::handleEvent(LLPointer, const LLSD&) +bool mmsetgreen::handleEvent(LLPointer, const LLSD&) { - markMassAgents(LLColor4::yellow); return true; + markMassAgents(LLColor4::green); + return true; } -bool LLNetMap::mmsetcustom::handleEvent(LLPointer, const LLSD&) +bool mmsetblue::handleEvent(LLPointer, const LLSD&) { - markMassAgents(gSavedSettings.getColor4("MoyMiniMapCustomColor")); return true; + markMassAgents(LLColor4::blue); + return true; } -bool LLNetMap::mmsetunmark::handleEvent(LLPointer, const LLSD&) +bool mmsetyellow::handleEvent(LLPointer, const LLSD&) { - std::map::iterator it = mClosestAgentsAtLastClick.begin(); - std::map::iterator end = mClosestAgentsAtLastClick.end(); - for(; it!= end; ++it) mm_MarkerColors.erase((*it).first); + markMassAgents(LLColor4::yellow); return true; } -bool LLNetMap::mmenableunmark::handleEvent(LLPointer, const LLSD& userdata) +bool mmsetcustom::handleEvent(LLPointer, const LLSD&) { - bool enabled(false); - std::map::iterator it = mClosestAgentsAtLastClick.begin(); - std::map::iterator end = mClosestAgentsAtLastClick.end(); - for(; it != end && !enabled; ++it) enabled = mm_MarkerColors.find((*it).first) != mm_MarkerColors.end(); - mPtr->findControl(userdata["control"].asString())->setValue(enabled); + markMassAgents(gSavedSettings.getColor4("MoyMiniMapCustomColor")); return true; } - -bool LLNetMap::LLCenterMap::handleEvent(LLPointer event, const LLSD& userdata) +bool mmsetunmark::handleEvent(LLPointer, const LLSD&) { - EMiniMapCenter center = (EMiniMapCenter)userdata.asInteger(); - - if (gSavedSettings.getS32("MiniMapCenter") == center) + auto radar = LLFloaterAvatarList::getInstance(); + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) { - gSavedSettings.setS32("MiniMapCenter", MAP_CENTER_NONE); + mm_clearMark(id); + if (auto entry = radar ? radar->getAvatarEntry(id) : nullptr) + entry->setMarked(false); } - else - { - gSavedSettings.setS32("MiniMapCenter", userdata.asInteger()); - } - return true; } - -bool LLNetMap::LLCheckCenterMap::handleEvent(LLPointer event, const LLSD& userdata) +bool mmenableunmark::handleEvent(LLPointer, const LLSD& userdata) { - LLNetMap *self = mPtr; - EMiniMapCenter center = (EMiniMapCenter)userdata["data"].asInteger(); - BOOL enabled = (gSavedSettings.getS32("MiniMapCenter") == center); - - self->findControl(userdata["control"].asString())->setValue(enabled); + bool enabled(false); + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + if (enabled = mm_MarkerColors.find(id) != mm_MarkerColors.end()) + break; + mPtr->findControl(userdata["control"].asString())->setValue(enabled); return true; } -bool LLNetMap::LLChatRings::handleEvent(LLPointer event, const LLSD& userdata) +bool LLChatRings::handleEvent(LLPointer event, const LLSD& userdata) { - BOOL whisper_enabled = gSavedSettings.getBOOL("MiniMapWhisperRing"); - BOOL chat_enabled = gSavedSettings.getBOOL("MiniMapChatRing"); - BOOL shout_enabled = gSavedSettings.getBOOL("MiniMapShoutRing"); - BOOL all_enabled = whisper_enabled && chat_enabled && shout_enabled; + auto whisper = gSavedSettings.getControl("MiniMapWhisperRing"); + auto chat = gSavedSettings.getControl("MiniMapChatRing"); + auto shout = gSavedSettings.getControl("MiniMapShoutRing"); + bool all_enabled = whisper->get() && chat->get() && shout->get(); - gSavedSettings.setBOOL("MiniMapWhisperRing", !all_enabled); - gSavedSettings.setBOOL("MiniMapChatRing", !all_enabled); - gSavedSettings.setBOOL("MiniMapShoutRing", !all_enabled); + whisper->set(!all_enabled); + chat->set(!all_enabled); + shout->set(!all_enabled); return true; } -bool LLNetMap::LLCheckChatRings::handleEvent(LLPointer event, const LLSD& userdata) +bool LLCheckChatRings::handleEvent(LLPointer event, const LLSD& userdata) { - BOOL whisper_enabled = gSavedSettings.getBOOL("MiniMapWhisperRing"); - BOOL chat_enabled = gSavedSettings.getBOOL("MiniMapChatRing"); - BOOL shout_enabled = gSavedSettings.getBOOL("MiniMapShoutRing"); - BOOL all_enabled = whisper_enabled && chat_enabled && shout_enabled; + bool all_enabled = gSavedSettings.getBOOL("MiniMapWhisperRing") + && gSavedSettings.getBOOL("MiniMapChatRing") + && gSavedSettings.getBOOL("MiniMapShoutRing"); - LLNetMap *self = mPtr; - self->findControl(userdata["control"].asString())->setValue(all_enabled); + mPtr->findControl(userdata["control"].asString())->setValue(all_enabled); return true; } -bool LLNetMap::LLStopTracking::handleEvent(LLPointer event, const LLSD& userdata) +bool LLStopTracking::handleEvent(LLPointer event, const LLSD& userdata) { LLTracker::stopTracking(false); return true; } -bool LLNetMap::LLEnableTracking::handleEvent(LLPointer event, const LLSD& userdata) +bool LLIsTracking::handleEvent(LLPointer event, const LLSD& userdata) { - LLNetMap *self = mPtr; - self->findControl(userdata["control"].asString())->setValue(LLTracker::isTracking()); + mPtr->findControl(userdata["control"].asString())->setValue(LLTracker::isTracking()); return true; } - -bool LLNetMap::LLCamFollow::handleEvent(LLPointer event, const LLSD& userdata) -{ - LLNetMap *self = mPtr; - LLFloaterAvatarList::lookAtAvatar(self->mClosestAgentAtLastRightClick); - return true; -} - - -bool LLNetMap::LLShowAgentProfile::handleEvent(LLPointer event, const LLSD& userdata) -{ - LLNetMap *self = mPtr; -// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.0b - if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) - { - LLAvatarActions::showProfile(self->mClosestAgentAtLastRightClick); - } -// [/RLVa:KB] - //LLAvatarActions::showProfile(self->mClosestAgentAtLastRightClick); - return true; -} - -bool LLNetMap::LLEnableProfile::handleEvent(LLPointer event, const LLSD& userdata) -{ - LLNetMap *self = mPtr; -// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.0b - self->findControl(userdata["control"].asString())->setValue( - (self->isAgentUnderCursor()) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ); -// [/RLVa:KB] - //self->findControl(userdata["control"].asString())->setValue(self->isAgentUnderCursor()); - return true; -} - -bool LLNetMap::LLToggleControl::handleEvent(LLPointer event, const LLSD& userdata) -{ - std::string control_name = userdata.asString(); - gSavedSettings.setBOOL(control_name, !gSavedSettings.getBOOL(control_name)); - return true; -} diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index 0b291b5bc0..67eb3d4bee 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -33,33 +33,20 @@ #ifndef LL_LLNETMAP_H #define LL_LLNETMAP_H -#include "llmath.h" +#include "lfidbearer.h" #include "llpanel.h" -#include "llmemberlistener.h" -#include "v3math.h" -#include "v3dmath.h" -#include "v4color.h" -#include "llpointer.h" -#include "llcoord.h" class LLTextBox; class LLImageRaw; class LLViewerTexture; class LLFloaterMap; -class LLMenuGL; // [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3.0) class LLViewerRegion; class LLAvatarName; // [/SL:KB] -enum EMiniMapCenter -{ - MAP_CENTER_NONE = 0, - MAP_CENTER_CAMERA = 1 -}; - -class LLNetMap : public LLPanel +class LLNetMap final : public LLPanel, public LFIDBearer { public: LLNetMap(const std::string& name); @@ -81,8 +68,8 @@ class LLNetMap : public LLPanel /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); /*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - static void mm_setcolor(LLUUID key,LLColor4 col); //moymod - + LLUUID getStringUUIDSelectedItem() const override final { return mClosestAgentAtLastRightClick; } + uuid_vec_t getSelectedIDs() const override final { return mClosestAgentsAtLastClick; } // [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3.0) void refreshParcelOverlay() { mUpdateParcelImage = true; } @@ -127,6 +114,15 @@ class LLNetMap : public LLPanel private: // [/SL:KB] + LLTextBox *mELabel = nullptr, + *mNLabel = nullptr, + *mWLabel = nullptr, + *mSLabel = nullptr, + *mNELabel = nullptr, + *mNWLabel = nullptr, + *mSWLabel = nullptr, + *mSELabel = nullptr; + F32 mScale; // Size of a region in pixels F32 mPixelsPerMeter; // world meters to map pixels F32 mObjectMapTPM; // texels per meter on map @@ -152,125 +148,12 @@ class LLNetMap : public LLPanel // [/SL:KB] static std::map mClosestAgentsToCursor; // + static uuid_vec_t mClosestAgentsAtLastClick; // LLUUID mClosestAgentToCursor; LLUUID mClosestAgentAtLastRightClick; - static void showAgentProfile(void*); - BOOL isAgentUnderCursor() { return mClosestAgentToCursor.notNull(); } - - class LLScaleMap : public LLMemberListener - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - - class LLCenterMap : public LLMemberListener - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - - class LLCheckCenterMap : public LLMemberListener - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - - class LLChatRings : public LLMemberListener - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - - class LLCheckChatRings : public LLMemberListener - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - - class LLStopTracking : public LLMemberListener - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - - class LLEnableTracking : public LLMemberListener - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - - class LLShowAgentProfile : public LLMemberListener - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - - class LLCamFollow : public LLMemberListener //moymod - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - - //moymod - Custom minimap markers :o - class mmsetred : public LLMemberListener //moymod - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - class mmsetgreen : public LLMemberListener //moymod - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - class mmsetblue : public LLMemberListener //moymod - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - class mmsetyellow : public LLMemberListener //moymod - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - class mmsetcustom : public LLMemberListener //moymod - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - class mmsetunmark : public LLMemberListener //moymod - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - class mmenableunmark : public LLMemberListener //moymod - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - - - class LLEnableProfile : public LLMemberListener - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - - class LLToggleControl : public LLMemberListener - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; - -// [SL:KB] - Patch: World-MiniMap | Checked: 2012-07-08 (Catznip-3.3.0) - class OverlayToggle : public LLMemberListener - { - public: - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - }; -// [/SL:KB] - + BOOL isAgentUnderCursor() const { return mClosestAgentToCursor.notNull(); } LLMenuGL* mPopupMenu; }; diff --git a/indra/newview/llnotify.cpp b/indra/newview/llnotify.cpp index 3a4e8f2edf..b8c9150c63 100644 --- a/indra/newview/llnotify.cpp +++ b/indra/newview/llnotify.cpp @@ -35,25 +35,20 @@ #include "llnotify.h" #include "llchat.h" -#include "llfocusmgr.h" -#include "llrender.h" -#include "llbutton.h" -#include "llfocusmgr.h" -#include "llglheaders.h" #include "lliconctrl.h" +#include "llmenugl.h" #include "lltextbox.h" #include "lltexteditor.h" #include "lltrans.h" #include "lluiconstants.h" -#include "llui.h" -#include "llxmlnode.h" -#include "llviewercontrol.h" #include "llviewerdisplay.h" #include "llviewertexturelist.h" +#include "llviewerwindow.h" // for gViewerWindow #include "llfloaterchat.h" // for add_chat_history() #include "lloverlaybar.h" // for gOverlayBar #include "lluictrlfactory.h" +#include "llcheckboxctrl.h" #include "hippogridmanager.h" @@ -183,117 +178,56 @@ LLNotifyBox::LLNotifyBox(LLNotificationPtr notification) bool layout_script_dialog(notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); LLRect rect = mIsTip ? getNotifyTipRect(message) : getNotifyRect(is_textbox ? 10 : mNumOptions, layout_script_dialog, mIsCaution); + if ((form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE || form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)) + rect.mBottom -= BTN_HEIGHT; setRect(rect); setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT)); setBackgroundVisible(FALSE); setBackgroundOpaque(TRUE); - LLIconCtrl* icon; - LLTextEditor* text; - const S32 TOP = getRect().getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32); const S32 BOTTOM = (S32)sFont->getLineHeight(); S32 x = HPAD + HPAD; S32 y = TOP; - if (mIsTip) - { - // use the tip notification icon - icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), std::string("notify_tip_icon.tga")); - } - else if (mIsCaution) - { - // use the caution notification icon - icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), std::string("notify_caution_icon.tga")); - } - else - { - // use the default notification icon - icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), std::string("notify_box_icon.tga")); - } + auto icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), mIsTip ? "notify_tip_icon.tga" : mIsCaution ? "notify_caution_icon.tga" : "notify_box_icon.tga"); icon->setMouseOpaque(FALSE); addChild(icon); x += HPAD + HPAD + 32; - // add a caution textbox at the top of a caution notification - LLTextBox* caution_box = NULL; - if (mIsCaution && !mIsTip) { - S32 caution_height = ((S32)sFont->getLineHeight() * 2) + VPAD; - caution_box = new LLTextBox( - std::string("caution_box"), - LLRect(x, y, getRect().getWidth() - 2, caution_height), - LLStringUtil::null, - sFont, - FALSE); - - caution_box->setFontStyle(LLFontGL::BOLD); - caution_box->setColor(gColors.getColor("NotifyCautionWarnColor")); - caution_box->setBackgroundColor(gColors.getColor("NotifyCautionBoxColor")); - caution_box->setBorderVisible(FALSE); - caution_box->setWrappedText(notification->getMessage()); - - addChild(caution_box); - - // adjust the vertical position of the next control so that - // it appears below the caution textbox - y = y - caution_height; - } - else if (mIsCaution && mIsTip) - { - const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD); // Tokenization on \n is handled by LLTextBox const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title. + const auto height = mIsTip ? BOTTOM : BTN_TOP+16; - text = new LLTextEditor(std::string("box"), LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16), MAX_LENGTH, message, sFont, FALSE); - text->setWordWrap(TRUE); - text->setTabStop(FALSE); - text->setMouseOpaque(FALSE); - text->setBorderVisible(FALSE); - text->setTakesNonScrollClicks(FALSE); - text->setHideScrollbarForShortDocs(TRUE); - text->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually - // rendered under the text box, therefore we want - // the actual text box to be transparent - text->setReadOnlyFgColor ( gColors.getColor("NotifyCautionWarnColor") ); //sets caution text color for tip notifications - text->setEnabled(FALSE); // makes it read-only - text->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard) - addChild(text); - } - else - { - const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD); + mText = new LLTextEditor(std::string("box"), LLRect(x, y, getRect().getWidth()-2, height), MAX_LENGTH, LLStringUtil::null, sFont, FALSE, true); - // Tokenization on \n is handled by LLTextBox - const S32 MAX_LENGTH = 512 + 20 + - DB_FIRST_NAME_BUF_SIZE + - DB_LAST_NAME_BUF_SIZE + - DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title. - - text = new LLTextEditor(std::string("box"), - LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16), - MAX_LENGTH, - message, - sFont, - FALSE); - text->setWordWrap(TRUE); - text->setTabStop(FALSE); - text->setMouseOpaque(FALSE); - text->setBorderVisible(FALSE); - text->setTakesNonScrollClicks(FALSE); - text->setHideScrollbarForShortDocs(TRUE); - text->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually + mText->setWordWrap(TRUE); + mText->setMouseOpaque(TRUE); + mText->setBorderVisible(FALSE); + mText->setTakesNonScrollClicks(TRUE); + mText->setHideScrollbarForShortDocs(TRUE); + mText->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually // rendered under the text box, therefore we want // the actual text box to be transparent - text->setReadOnlyFgColor ( gColors.getColor("NotifyTextColor") ); - text->setEnabled(FALSE); // makes it read-only - text->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard) - addChild(text); + + auto text_color = gColors.getColor(mIsCaution ? "NotifyCautionWarnColor" : "NotifyTextColor"); + LLStyleSP style = new LLStyle(true, text_color, LLStringUtil::null); + style->mBold = mIsCaution && !mIsTip; + + mText->setReadOnlyFgColor(text_color); //sets caution text color for tip notifications + if (!mIsCaution || !mIsTip) // We could do some extra color math here to determine if bg's too close to link color, but let's just cross with the link color instead + mText->setLinkColor(new LLColor4(lerp(text_color, gSavedSettings.getColor4("HTMLLinkColor"), 0.4f))); + mText->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard) + mText->appendText(message,false,false,style); // Now we can set the text, since colors have been set. + if (is_textbox || layout_script_dialog) + mText->appendText(notification->getSubstitutions()["SCRIPT_MESSAGE"], false, true, style, false); + addChild(mText); } if (mIsTip) @@ -359,6 +293,45 @@ LLNotifyBox::LLNotifyBox(LLNotificationPtr notification) addButton("OK", "OK", false, true, layout_script_dialog); mAddedDefaultBtn = true; } + + std::string check_title; + if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE) + { + check_title = LLNotificationTemplates::instance().getGlobalString("skipnexttime"); + } + else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) + { + check_title = LLNotificationTemplates::instance().getGlobalString("alwayschoose"); + } + if (!check_title.empty()) + { + const LLFontGL* font = LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF); + S32 line_height = llfloor(font->getLineHeight() + 0.99f); + + // Extend dialog for "check next time" + S32 max_msg_width = getRect().getWidth() - HPAD * 9; + S32 check_width = S32(font->getWidth(check_title) + 0.99f) + 16; + max_msg_width = llmax(max_msg_width, check_width); + + S32 msg_x = (getRect().getWidth() - max_msg_width) / 2; + + LLRect check_rect; + check_rect.setOriginAndSize(msg_x, BOTTOM_PAD + BTN_HEIGHT + VPAD*2 + (BTN_HEIGHT + VPAD) * (mNumButtons / 3), + max_msg_width, line_height); + + LLCheckboxCtrl* check = new LLCheckboxCtrl(std::string("check"), check_rect, check_title, font, + // Lambda abuse. + [this](LLUICtrl* ctrl, const LLSD& param) + { + this->mNotification->setIgnored(ctrl->getValue()); + }); + check->setEnabledColor(LLUI::sColorsGroup->getColor(mIsCaution ? "AlertCautionTextColor" : "AlertTextColor")); + if (mIsCaution) + { + check->setButtonColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor")); + } + addChild(check); + } if (++sNotifyBoxCount <= 0) LL_WARNS() << "A notification was mishandled. sNotifyBoxCount = " << sNotifyBoxCount << LL_ENDL; @@ -390,9 +363,9 @@ LLButton* LLNotifyBox::addButton(const std::string& name, const std::string& lab if (layout_script_dialog) { - // Add two "blank" option spaces, before the "Ignore" button - index = button_index + 2; - if (button_index == 0) + // Add one "blank" option space, before the "Block" and "Ignore" buttons + index = button_index + 1; + if (button_index == 0 || button_index == 1) { // Ignore button is smaller, less wide btn_height = BTN_HEIGHT_SMALL; @@ -409,6 +382,7 @@ LLButton* LLNotifyBox::addButton(const std::string& name, const std::string& lab LLButton* btn = new LLButton(name, btn_rect, "", boost::bind(&LLNotifyBox::onClickButton, this, is_option ? name : "")); btn->setLabel(label); + btn->setToolTip(label); btn->setFont(font); if (mIsCaution) @@ -428,7 +402,8 @@ LLButton* LLNotifyBox::addButton(const std::string& name, const std::string& lab BOOL LLNotifyBox::handleMouseUp(S32 x, S32 y, MASK mask) { - if (mIsTip) + bool done = LLPanel::handleMouseUp(x, y, mask); + if (!done && mIsTip) { mNotification->respond(mNotification->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON)); @@ -438,21 +413,34 @@ BOOL LLNotifyBox::handleMouseUp(S32 x, S32 y, MASK mask) setFocus(TRUE); - return LLPanel::handleMouseUp(x, y, mask); + return done; } // virtual BOOL LLNotifyBox::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if (!mIsTip) - { + if (!LLPanel::handleRightMouseDown(x, y, mask)) // Allow Children to handle first moveToBack(true); - return TRUE; - } + return true; +} - return LLPanel::handleRightMouseDown(x, y, mask); +// virtual +BOOL LLNotifyBox::handleHover(S32 x, S32 y, MASK mask) +{ + if (mIsTip) mEventTimer.stop(); // Stop timer on hover so the user can interact + return LLPanel::handleHover(x, y, mask); } +bool LLNotifyBox::userIsInteracting() const +{ + // If the mouse is over us, the user may wish to interact + S32 local_x; + S32 local_y; + screenPointToLocal(gViewerWindow->getCurrentMouseX(), gViewerWindow->getCurrentMouseY(), &local_x, &local_y); + return pointInView(local_x, local_y) || // We're actively hovered + // our text is the target of an active menu that could be open (getVisibleMenu sucks because it contains a loop of two dynamic casts, so keep this at the end) + (mText && mText->getActive() == mText && LLMenuGL::sMenuContainer->getVisibleMenu()); +} // virtual void LLNotifyBox::draw() @@ -460,7 +448,7 @@ void LLNotifyBox::draw() // If we are teleporting, stop the timer and restart it when the teleporting completes if (gTeleportDisplay) mEventTimer.stop(); - else if (!mEventTimer.getStarted()) + else if (!mEventTimer.getStarted() && (!mIsTip || !userIsInteracting())) // If it's not a tip, we can resume instantly, otherwise the user may be interacting mEventTimer.start(); F32 display_time = mAnimateTimer.getElapsedTimeF32(); @@ -497,7 +485,7 @@ void LLNotifyBox::draw() void LLNotifyBox::drawBackground() const { - if (LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga")) + if (LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square")) { gGL.getTexUnit(0)->bind(imagep->getImage()); // set proper background color depending on whether notify box is a caution or not @@ -565,6 +553,7 @@ BOOL LLNotifyBox::tick() { if (mIsTip) { + LLNotifications::instance().cancel(mNotification); close(); } return FALSE; @@ -625,9 +614,9 @@ LLRect LLNotifyBox::getNotifyRect(S32 num_options, bool layout_script_dialog, bo if (num_options < 1) num_options = 1; - // Add two "blank" option spaces. + // Add one "blank" option space. if (layout_script_dialog) - num_options += 2; + num_options += 1; S32 additional_lines = (num_options-1) / 3; diff --git a/indra/newview/llnotify.h b/indra/newview/llnotify.h index fa85eb17e5..4ea8ca9cb4 100644 --- a/indra/newview/llnotify.h +++ b/indra/newview/llnotify.h @@ -43,7 +43,7 @@ class LLNotifyBoxTemplate; class LLTextEditor; // NotifyBox - for notifications that require a response from the user. -class LLNotifyBox : +class LLNotifyBox final : public LLPanel, public LLEventTimer, public LLInitClass, @@ -54,7 +54,7 @@ class LLNotifyBox : bool isTip() const { return mIsTip; } bool isCaution() const { return mIsCaution; } - /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void setVisible(BOOL visible) override; void stopAnimation() { mAnimating = false; } void close(); @@ -70,12 +70,14 @@ class LLNotifyBox : LLButton* addButton(const std::string& name, const std::string& label, bool is_option, bool is_default, bool layout_script_dialog); - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; + BOOL handleHover(S32 x, S32 y, MASK mask) override; + bool userIsInteracting() const; // Animate as sliding onto the screen. - /*virtual*/ void draw(); - /*virtual*/ BOOL tick(); + /*virtual*/ void draw() override; + /*virtual*/ BOOL tick() override; void moveToBack(bool getfocus = false); @@ -92,7 +94,7 @@ class LLNotifyBox : void drawBackground() const; protected: - LLTextEditor *mUserInputBox; + LLTextEditor *mUserInputBox = nullptr, *mText = nullptr; LLNotificationPtr mNotification; bool mIsTip; @@ -111,13 +113,13 @@ class LLNotifyBox : bool mAddedDefaultBtn; }; -class LLNotifyBoxView : public LLUICtrl +class LLNotifyBoxView final : public LLUICtrl { public: LLNotifyBoxView(const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 follows=FOLLOWS_NONE); void showOnly(LLView* ctrl); LLNotifyBox* getFirstNontipBox() const; - /*virtual*/ void deleteAllChildren(); + /*virtual*/ void deleteAllChildren() override; struct Matcher { diff --git a/indra/newview/lloverlaybar.cpp b/indra/newview/lloverlaybar.cpp index 3e8d77d0e9..d57235dcd7 100644 --- a/indra/newview/lloverlaybar.cpp +++ b/indra/newview/lloverlaybar.cpp @@ -65,7 +65,7 @@ #include "rlvhandler.h" // [/RLVa:KB] -#include +#include // // Globals @@ -244,7 +244,7 @@ void LLOverlayBar::layoutButtons() { U32 button_count = 0; const child_list_t& view_list = *(mStateManagementContainer->getChildList()); - BOOST_FOREACH(LLView* viewp, view_list) + for (LLView* viewp : view_list) { if(!viewp->getEnabled()) continue; @@ -264,7 +264,7 @@ void LLOverlayBar::layoutButtons() S32 left = 0; S32 bottom = 1; - BOOST_REVERSE_FOREACH(LLView* viewp, view_list) + for (LLView* viewp : boost::adaptors::reverse(view_list)) { if(!viewp->getEnabled()) continue; @@ -324,7 +324,7 @@ void LLOverlayBar::refresh() } buttons_changed |= updateButtonVisiblity(mNotBusy, gAgent.isDoNotDisturb()) != NULL; buttons_changed |= updateButtonVisiblity(mFlyCam,LLViewerJoystick::getInstance()->getOverrideCamera()) != NULL; - buttons_changed |= updateButtonVisiblity(mMouseLook,gAgent.isControlGrabbed(CONTROL_ML_LBUTTON_DOWN_INDEX)||gAgent.isControlGrabbed(CONTROL_ML_LBUTTON_UP_INDEX)) != NULL; + buttons_changed |= updateButtonVisiblity(mMouseLook,gAgent.isControlBlocked(CONTROL_ML_LBUTTON_DOWN_INDEX)||gAgent.isControlBlocked(CONTROL_ML_LBUTTON_UP_INDEX)) != NULL; // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) // buttons_changed |= updateButtonVisiblity("Stand Up", isAgentAvatarValid() && gAgentAvatarp->isSitting()) != NULL; buttons_changed |= updateButtonVisiblity(mStandUp,isAgentAvatarValid() && gAgentAvatarp->isSitting() && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) != NULL; diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 7cecc062f9..3e284649d9 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -45,6 +45,7 @@ #include "llwindow.h" #include "llagent.h" +#include "llagentbenefits.h" #include "llavataractions.h" #include "llavatarpropertiesprocessor.h" #include "llcallingcard.h" @@ -70,6 +71,9 @@ #include #include + +#include "hippogridmanager.h" // Include Gridmanager for OpenSim Support in profiles, provides ability for the helpbutton to redirect to GRID Websites Help page + // [RLVa:KB] #include "rlvhandler.h" // [/RLVa:KB] @@ -138,7 +142,6 @@ LLPanelAvatarSecondLife::LLPanelAvatarSecondLife(const std::string& name, LLPanelAvatarSecondLife::~LLPanelAvatarSecondLife() { - mCacheConnection.disconnect(); LLMuteList::instance().removeObserver(this); } @@ -146,12 +149,6 @@ void LLPanelAvatarSecondLife::refresh() { } -void LLPanelAvatarSecondLife::updatePartnerName(const LLAvatarName& name) -{ - mCacheConnection.disconnect(); - childSetTextArg("partner_edit", "[NAME]", name.getNSName()); -} - //----------------------------------------------------------------------------- // clearControls() // Empty the data out of the controls, since we have to wait for new @@ -164,7 +161,7 @@ void LLPanelAvatarSecondLife::clearControls() childSetValue("born", LLStringUtil::null); childSetValue("acct", LLStringUtil::null); - childSetTextArg("partner_edit", "[NAME]", LLStringUtil::null); + childSetValue("partner_edit", LLUUID::null); mPartnerID = LLUUID::null; getChild("groups")->deleteAllItems(); @@ -183,7 +180,12 @@ void LLPanelAvatarSecondLife::processProperties(void* data, EAvatarProcessorType args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(pAvatarData); args["[AGEVERIFICATION]"] = LLStringUtil::null; - getChild("acct")->setValue(getString("CaptionTextAcctInfo", args)); + { + const auto account_info = getString("CaptionTextAcctInfo", args); + auto acct = getChild("acct"); + acct->setValue(account_info); + acct->setToolTip(account_info); + } getChild("img")->setImageAssetID(pAvatarData->image_id); @@ -191,23 +193,25 @@ void LLPanelAvatarSecondLife::processProperties(void* data, EAvatarProcessorType { using namespace boost::gregorian; int year, month, day; - sscanf(pAvatarData->born_on.c_str(),"%d/%d/%d", &month, &day, &year); - date birthday(year, month, day), today(day_clock::local_day()); - std::ostringstream born_on; - born_on << pAvatarData->born_on << " (" << today - birthday << ')'; - childSetValue("born", born_on.str()); + const auto& born = pAvatarData->born_on; + if (!born.empty() && sscanf(born.c_str(),"%d/%d/%d", &month, &day, &year) == 3 // Make sure input is valid + && month > 0 && month <= 12 && day > 0 && day <= 31 && year >= 1400) // Don't use numbers that gregorian will choke on + { + date birthday(year, month, day), today(day_clock::local_day()); + std::ostringstream born_on; + const std::locale date_fmt(std::locale::classic(), new date_facet(gSavedSettings.getString("ShortDateFormat").data())); + born_on.imbue(date_fmt); + born_on << birthday << " (" << today - birthday << ')'; + childSetValue("born", born_on.str()); + } + else childSetValue("born", born); } bool allow_publish = (pAvatarData->flags & AVATAR_ALLOW_PUBLISH); childSetValue("allow_publish", allow_publish); - setPartnerID(pAvatarData->partner_id); - if (mPartnerID.notNull()) - { - mCacheConnection.disconnect(); - mCacheConnection = LLAvatarNameCache::get(mPartnerID, boost::bind(&LLPanelAvatarSecondLife::updatePartnerName, this, _2)); - childSetEnabled("partner_info", TRUE); - } + mPartnerID = pAvatarData->partner_id; + getChildView("partner_edit")->setValue(mPartnerID); } } else if (type == APT_GROUPS) @@ -287,7 +291,7 @@ void LLPanelAvatarFirstLife::processProperties(void* data, EAvatarProcessorType if (pAvatarData && (mAvatarID == pAvatarData->avatar_id) && (pAvatarData->avatar_id != LLUUID::null)) { // Teens don't get these - getChildView("about")->setValue(pAvatarData->fl_about_text); + getChild("about")->setText(pAvatarData->fl_about_text, false); getChild("img")->setImageAssetID(pAvatarData->fl_image_id); } } @@ -299,11 +303,15 @@ void LLPanelAvatarSecondLife::onDoubleClickGroup() LLGroupActions::show(item->getUUID()); } -// static +// static - Not anymore :P bool LLPanelAvatarSecondLife::onClickPartnerHelpLoadURL(const LLSD& notification, const LLSD& response) { if (!LLNotification::getSelectedOption(notification, response)) - LLWeb::loadURL("http://secondlife.com/partner"); + { + const auto& grid = *gHippoGridManager->getConnectedGrid(); + const std::string url = grid.isSecondLife() ? "http://secondlife.com/partner" : grid.getPartnerUrl(); + if (!url.empty()) LLWeb::loadURL(url); + } return false; } @@ -330,16 +338,27 @@ void LLPanelAvatarFirstLife::enableControls(BOOL self) void show_picture(const LLUUID& id, const std::string& name); static std::string profile_picture_title(const std::string& str) { return "Profile Picture: " + str; } static void show_partner_help() { LLNotificationsUtil::add("ClickPartnerHelpAvatar", LLSD(), LLSD(), boost::bind(LLPanelAvatarSecondLife::onClickPartnerHelpLoadURL, _1, _2)); } +void show_log_browser(const LLUUID& id, const LFIDBearer::Type& type) +{ + void show_log_browser(const std::string& name, const LLUUID& id); + std::string name; + if (type == LFIDBearer::AVATAR) + { + LLAvatarName av_name; + LLAvatarNameCache::get(id, &av_name); + name = av_name.getLegacyName(); + } + else // GROUP + { + gCacheName->getGroupName(id, name); + } + show_log_browser(name, id); +} BOOL LLPanelAvatarSecondLife::postBuild() { childSetEnabled("born", FALSE); childSetEnabled("partner_edit", FALSE); getChild("partner_help")->setCommitCallback(boost::bind(show_partner_help)); - if (LLUICtrl* ctrl = getChild("partner_info")) - { - ctrl->setCommitCallback(boost::bind(LLAvatarActions::showProfile, boost::ref(mPartnerID), false)); - ctrl->setEnabled(mPartnerID.notNull()); - } childSetAction("?", boost::bind(LLNotificationsUtil::add, "ClickPublishHelpAvatar")); LLPanelAvatar* pa = getPanelAvatar(); @@ -359,6 +378,7 @@ BOOL LLPanelAvatarSecondLife::postBuild() getChild("GroupInvite_Button")->setCommitCallback(boost::bind(static_cast(LLAvatarActions::inviteToGroup), boost::bind(&LLPanelAvatar::getAvatarID, pa))); getChild("Add Friend...")->setCommitCallback(boost::bind(LLAvatarActions::requestFriendshipDialog, boost::bind(&LLPanelAvatar::getAvatarID, pa))); + getChild("Log")->setCommitCallback(boost::bind(show_log_browser, boost::bind(&LLPanelAvatar::getAvatarID, pa), LFIDBearer::AVATAR)); getChild("Pay...")->setCommitCallback(boost::bind(LLAvatarActions::pay, boost::bind(&LLPanelAvatar::getAvatarID, pa))); if (LLUICtrl* ctrl = findChild("Mute")) { @@ -372,21 +392,32 @@ BOOL LLPanelAvatarSecondLife::postBuild() LLTextureCtrl* ctrl = getChild("img"); ctrl->setFallbackImageName("default_profile_picture.j2c"); + auto show_pic = [&] + { + show_picture(getChild("img")->getImageAssetID(), profile_picture_title(getChild("dnname")->getText())); + }; + auto show_pic_if_not_self = [=] { if (!ctrl->canChange()) show_pic(); }; - getChild("bigimg")->setCommitCallback(boost::bind(boost::bind(show_picture, boost::bind(&LLTextureCtrl::getImageAssetID, ctrl), boost::bind(profile_picture_title, boost::bind(&LLView::getValue, getChild("dnname")))))); + ctrl->setMouseUpCallback(std::bind(show_pic_if_not_self)); + getChild("bigimg")->setCommitCallback(std::bind(show_pic)); return TRUE; } BOOL LLPanelAvatarFirstLife::postBuild() { - BOOL own_avatar = (getPanelAvatar()->getAvatarID() == gAgent.getID() ); - enableControls(own_avatar); + enableControls(getPanelAvatar()->getAvatarID() == gAgentID); LLTextureCtrl* ctrl = getChild("img"); ctrl->setFallbackImageName("default_profile_picture.j2c"); + auto show_pic = [&] + { + show_picture(getChild("img")->getImageAssetID(), "First Life Picture"); + }; + auto show_pic_if_not_self = [=] { if (!ctrl->canChange()) show_pic(); }; - getChild("flbigimg")->setCommitCallback(boost::bind(boost::bind(boost::bind(show_picture, boost::bind(&LLTextureCtrl::getImageAssetID, ctrl), "First Life Picture")))); + ctrl->setMouseUpCallback(std::bind(show_pic_if_not_self)); + getChild("flbigimg")->setCommitCallback(std::bind(show_pic)); return TRUE; } @@ -954,23 +985,24 @@ void LLPanelAvatarPicks::processProperties(void* data, EAvatarProcessorType type // are no tabs in the container. tabs->selectFirstTab(); bool edit(getPanelAvatar()->isEditable()); - S32 tab_count = tabs->getTabCount(); + auto count = tabs->getTabCount(); + bool can_add = self && count < LLAgentBenefitsMgr::current().getPicksLimit(); LLView* view = getChildView("New..."); - view->setEnabled(self && tab_count < MAX_AVATAR_PICKS + view->setEnabled(can_add // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) && !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)); // [/RLVa:KB] view->setVisible(self && edit); view = getChildView("Delete..."); - view->setEnabled(self && tab_count); + view->setEnabled(count); view->setVisible(self && edit); //For pick import/export - RK view = getChildView("Import..."); view->setVisible(self && edit); - view->setEnabled(tab_count < MAX_AVATAR_PICKS); + view->setEnabled(can_add); view = getChildView("Export..."); - view->setEnabled(self && tab_count); + view->setEnabled(count); view->setVisible(self); childSetVisible("loading_text", false); @@ -992,13 +1024,13 @@ void LLPanelAvatarPicks::onClickNew() panel_pick->initNewPick(); tabs->addTabPanel(panel_pick, panel_pick->getPickName()); tabs->selectLastTab(); - S32 tab_count = tabs->getTabCount(); - getChildView("New...")->setEnabled(tab_count < MAX_AVATAR_PICKS + bool can_add = tabs->getTabCount() < LLAgentBenefitsMgr::current().getPicksLimit(); + getChildView("New...")->setEnabled(can_add // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) && !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)); // [/RLVa:KB] getChildView("Delete...")->setEnabled(true); - getChildView("Import...")->setEnabled(tab_count < MAX_AVATAR_PICKS); + getChildView("Import...")->setEnabled(can_add); } //Pick import and export - RK @@ -1009,17 +1041,17 @@ void LLPanelAvatarPicks::onClickImport() } // static -void LLPanelAvatarPicks::onClickImport_continued(void* data, bool import) +void LLPanelAvatarPicks::onClickImport_continued(void* data, bool importt) { LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data; LLTabContainer* tabs = self->getChild("picks tab"); - if (import && self->mPanelPick) + if (importt && self->mPanelPick) { tabs->addTabPanel(self->mPanelPick, self->mPanelPick->getPickName()); tabs->selectLastTab(); self->childSetEnabled("New...", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)); self->childSetEnabled("Delete...", false); - self->childSetEnabled("Import...", tabs->getTabCount() < MAX_AVATAR_PICKS); + self->childSetEnabled("Import...", tabs->getTabCount() < LLAgentBenefitsMgr::current().getPicksLimit()); } } @@ -1213,25 +1245,18 @@ void LLPanelAvatar::setOnlineStatus(EOnlineStatus online_status) } } -void LLPanelAvatar::onAvatarNameResponse(const LLUUID& agent_id, const LLAvatarName& av_name) -{ - mCacheConnection.disconnect(); - getChild("dnname")->setText(gSavedSettings.getBOOL("SinguCompleteNameProfiles") ? av_name.getCompleteName() : av_name.getNSName()); -} - void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id) { - if (avatar_id.isNull()) return; - - //BOOL avatar_changed = FALSE; if (avatar_id != mAvatarID) { - //avatar_changed = TRUE; if (mAvatarID.notNull()) LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarID, this); mAvatarID = avatar_id; + getChild("dnname")->setNameID(avatar_id, LFIDBearer::AVATAR); } + if (avatar_id.isNull()) return; + LLAvatarPropertiesProcessor::getInstance()->addObserver(mAvatarID, this); // Determine if we have their calling card. @@ -1256,12 +1281,8 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id) if (LLDropTarget* drop_target = findChild("drop_target_rect")) drop_target->setEntityID(mAvatarID); - mCacheConnection.disconnect(); - mCacheConnection = LLAvatarNameCache::get(avatar_id, boost::bind(&LLPanelAvatar::onAvatarNameResponse, this, _1, _2)); - - LLNameEditor* key_edit = getChild("avatar_key"); - if (key_edit) - key_edit->setText(mAvatarID.asString()); + if (auto key_edit = getChildView("avatar_key")) + key_edit->setValue(mAvatarID.asString()); // While we're waiting for data off the network, clear out the old data. if (mPanelSecondLife) @@ -1316,8 +1337,7 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id) view = getChildView("Pay..."); view->setVisible(!own_avatar); view->setEnabled(false); - - getChild("avatar_key")->setText(avatar_id.asString()); + getChildView("Log")->setVisible(!own_avatar); bool is_god = gAgent.isGodlike(); view = getChildView("Kick"); @@ -1388,7 +1408,7 @@ void LLPanelAvatar::onClickCopy(const LLSD& val) } else { - void copy_profile_uri(const LLUUID& id, bool group = false); + void copy_profile_uri(const LLUUID& id, const LFIDBearer::Type& type = LFIDBearer::AVATAR); copy_profile_uri(mAvatarID); } } @@ -1436,7 +1456,9 @@ void LLPanelAvatar::sendAvatarNotesUpdate() notes == mLastNotes) // Avatar notes unchanged return; - LLAvatarPropertiesProcessor::instance().sendNotes(mAvatarID, notes); + auto& inst(LLAvatarPropertiesProcessor::instance()); + inst.sendNotes(mAvatarID, notes); + inst.sendAvatarNotesRequest(mAvatarID); // Rerequest notes to update anyone that might be listening, also to be sure we match the server. } // virtual @@ -1464,7 +1486,7 @@ void LLPanelAvatar::processProperties(void* data, EAvatarProcessorType type) timeStructToFormattedString(&t, gSavedSettings.getString("ShortDateFormat"), born_on); }*/ setOnlineStatus(pAvatarData->flags & AVATAR_ONLINE ? ONLINE_STATUS_YES : ONLINE_STATUS_NO); - childSetValue("about", pAvatarData->about_text); + getChild("about")->setText(pAvatarData->about_text, false); } } else if (type == APT_NOTES) @@ -1472,9 +1494,13 @@ void LLPanelAvatar::processProperties(void* data, EAvatarProcessorType type) const LLAvatarNotes* pAvatarNotes = static_cast( data ); if (pAvatarNotes && (mAvatarID == pAvatarNotes->target_id) && (pAvatarNotes->target_id != LLUUID::null)) { - childSetValue("notes edit", pAvatarNotes->notes); - childSetEnabled("notes edit", true); - mHaveNotes = true; + if (!mHaveNotes) // Only update the UI if we don't already have the notes, we could be editing them now! + { + auto notes = getChildView("notes edit"); + notes->setEnabled(true); + notes->setValue(pAvatarNotes->notes); + mHaveNotes = true; + } mLastNotes = pAvatarNotes->notes; } } diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index cc6e10b517..6876b224c1 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -119,13 +119,9 @@ class LLPanelAvatarSecondLife void clearControls(); void enableControls(BOOL own_avatar); void updateOnlineText(BOOL online, BOOL have_calling_card); - void updatePartnerName(const LLAvatarName& name); - void setPartnerID(LLUUID id) { mPartnerID = id; } - private: LLUUID mPartnerID; - boost::signals2::connection mCacheConnection; }; @@ -255,7 +251,7 @@ class LLPanelAvatarPicks : public LLPanelAvatarTab //Pick import and export - RK void onClickImport(); - static void onClickImport_continued(void* self, bool import); + static void onClickImport_continued(void* self, bool importt); void onClickExport(); bool callbackDelete(const LLSD& notification, const LLSD& response); @@ -282,8 +278,6 @@ class LLPanelAvatar : public LLPanel, public LLAvatarPropertiesObserver void setAvatar(LLViewerObject *avatarp); - void onAvatarNameResponse(const LLUUID& agent_id, const LLAvatarName& av_name); - // Fill in the avatar ID and handle some field fill-in, as well as // button enablement. void setAvatarID(const LLUUID &avatar_id); diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 8aec5a381b..786088cc01 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -354,7 +354,7 @@ void LLPanelClassifiedInfo::processProperties(void* data, EAvatarProcessorType t // Update UI controls mNameEditor->setText(c_info->name); - mDescEditor->setText(c_info->description); + mDescEditor->setText(c_info->description, false); mSnapshotCtrl->setImageAssetID(c_info->snapshot_id); mLocationEditor->setText(location_text); mLocationChanged = false; diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index af7855ca33..e9f394b31d 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -100,7 +100,7 @@ void LLPanelContents::getState(LLViewerObject *objectp ) } LLUUID group_id; // used for SL-23488 - LLSelectMgr::getInstance()->selectGetGroup(group_id); // sets group_id as a side effect SL-23488 + (void)LLSelectMgr::getInstance()->selectGetGroup(group_id); // sets group_id as a side effect SL-23488 // BUG? Check for all objects being editable? bool editable = gAgent.isGodlike() diff --git a/indra/newview/llpaneldirevents.cpp b/indra/newview/llpaneldirevents.cpp index 6f5412cef8..eed058cc91 100644 --- a/indra/newview/llpaneldirevents.cpp +++ b/indra/newview/llpaneldirevents.cpp @@ -52,8 +52,6 @@ #include "llnotificationsutil.h" #include "llviewerregion.h" -BOOL gDisplayEventHack = FALSE; - LLPanelDirEvents::LLPanelDirEvents(const std::string& name, LLFloaterDirectory* floater) : LLPanelDirBrowser(name, floater), mDoneQuery(FALSE), @@ -85,12 +83,7 @@ BOOL LLPanelDirEvents::postBuild() mCurrentSortColumn = "time"; - if (!gDisplayEventHack) - { - setDay(0); // for today - //performQuery(); // Temporary change to help DB - Sabin - } - gDisplayEventHack = FALSE; + setDay(0); // for today LLViewerRegion* region(gAgent.getRegion()); getChildView("filter_gaming")->setVisible(region && (gAgent.getRegion()->getGamingFlags() & REGION_GAMING_PRESENT) && !(gAgent.getRegion()->getGamingFlags() & REGION_GAMING_HIDE_FIND_EVENTS)); diff --git a/indra/newview/llpaneldirfind.cpp b/indra/newview/llpaneldirfind.cpp index 1792d0c9d0..e046e1b42b 100644 --- a/indra/newview/llpaneldirfind.cpp +++ b/indra/newview/llpaneldirfind.cpp @@ -67,12 +67,7 @@ #include "hippogridmanager.h" #include "lfsimfeaturehandler.h" -#if LL_MSVC -// disable boost::lexical_cast warning -#pragma warning (disable:4702) -#endif #include -#include //--------------------------------------------------------------------------- // LLPanelDirFindAll - Google search appliance based search @@ -243,9 +238,6 @@ BOOL LLPanelDirFind::postBuild() // need to handle secondlife:///app/ URLs for direct teleports mWebBrowser->setTrustedContent( true ); - // redirect 404 pages from S3 somewhere else - mWebBrowser->set404RedirectUrl( getString("redirect_404_url") ); - navigateToDefaultPage(); } @@ -471,7 +463,7 @@ const std::string LLPanelDirFind::getSearchURLSuffix(bool inc_pg, bool inc_matur (inc_pg ? SEARCH_PG : SEARCH_NONE) | (inc_mature ? SEARCH_MATURE : SEARCH_NONE) | (inc_adult ? SEARCH_ADULT : SEARCH_NONE); - url.replace(url.find(substring), substring.length(), boost::lexical_cast(maturityFlag)); + url.replace(url.find(substring), substring.length(), fmt::to_string(maturityFlag)); // Include region and x/y position, not for the GSA, but // just to get logs on the web server for search_proxy.php @@ -598,6 +590,7 @@ void LLPanelDirFind::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent even // LLPanelDirFindAllInterface //--------------------------------------------------------------------------- +static LLPanelDirFindAll* sFindAll = NULL; // static LLPanelDirFindAll* LLPanelDirFindAllInterface::create(LLFloaterDirectory* floater) { @@ -606,12 +599,29 @@ LLPanelDirFindAll* LLPanelDirFindAllInterface::create(LLFloaterDirectory* floate static LLPanelDirFindAllOld* sFindAllOld = NULL; // static -void LLPanelDirFindAllInterface::search(LLPanelDirFindAll* panel, - const std::string& search_text) +void LLPanelDirFindAllInterface::search(LLFloaterDirectory* inst, + const LLFloaterSearch::SearchQuery& search, bool show) { bool secondlife(gHippoGridManager->getConnectedGrid()->isSecondLife()); - if (secondlife || !getSearchUrl().empty()) panel->search(search_text); - if (!secondlife && sFindAllOld) sFindAllOld->search(search_text); + LLPanelDirFind* find_panel(secondlife ? inst->findChild("web_panel") : sFindAll); + LLPanel* panel(find_panel); + if (secondlife) + LLFloaterSearch::search(search, find_panel->mWebBrowser); + else + { + bool has_url(!getSearchUrl().empty()); + if (has_url) find_panel->search(search.query); + if (sFindAllOld) + { + sFindAllOld->search(search.query); + if (!has_url) panel = sFindAllOld; + } + } + if (show && panel) + { + inst->findChild("Directory Tabs")->selectTabPanel(panel); + panel->setFocus(true); + } } // static diff --git a/indra/newview/llpaneldirfind.h b/indra/newview/llpaneldirfind.h index 866c330a80..f5e4b690cc 100644 --- a/indra/newview/llpaneldirfind.h +++ b/indra/newview/llpaneldirfind.h @@ -34,10 +34,8 @@ #define LL_LLPANELDIRFIND_H #include "llpaneldirbrowser.h" -#include "llmediactrl.h" +#include "llfloatersearch.h" -class LLUICtrl; -class LLLineEditor; class LLPanelDirFindAll; class LLFloaterDirectory; @@ -76,6 +74,7 @@ class LLPanelDirFind /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); protected: + friend class LLPanelDirFindAllInterface; LLMediaCtrl* mWebBrowser; std::string mBrowserName; }; @@ -84,7 +83,7 @@ class LLPanelDirFindAllInterface { public: static LLPanelDirFindAll* create(LLFloaterDirectory* floater); - static void search(LLPanelDirFindAll* panel, const std::string& search_text); + static void search(LLFloaterDirectory* inst, const LLFloaterSearch::SearchQuery& search, bool show = false); static void focus(LLPanelDirFindAll* panel); }; diff --git a/indra/newview/llpaneldisplay.cpp b/indra/newview/llpaneldisplay.cpp index 688c03f6cc..3bc5db91cb 100644 --- a/indra/newview/llpaneldisplay.cpp +++ b/indra/newview/llpaneldisplay.cpp @@ -472,9 +472,13 @@ void LLPanelDisplay::refreshEnabledState() mWindowSizeLabel->setVisible(!isFullScreen); mCtrlWindowSize->setVisible(!isFullScreen); + F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); + S32Megabytes min_tex_mem = LLViewerTextureList::getMinVideoRamSetting(); + S32Megabytes max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier); + // Hardware tab - getChild("GrapicsCardTextureMemory")->setMinValue(LLViewerTextureList::getMinVideoRamSetting()); - getChild("GrapicsCardTextureMemory")->setMaxValue(LLViewerTextureList::getMaxVideoRamSetting()); + getChild("GrapicsCardTextureMemory")->setMinValue(min_tex_mem.value()); + getChild("GrapicsCardTextureMemory")->setMaxValue(max_tex_mem.value()); if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") || !gGLManager.mHasVertexBufferObject) @@ -550,15 +554,16 @@ void LLPanelDisplay::refreshEnabledState() if (render_deferred && wlatmos && shaders) { getChildView("fbo")->setEnabled(false); - getChildView("fbo")->setValue(true); + //getChildView("fbo")->setValue(true); mCtrlAvatarVP->setEnabled(false); - gSavedSettings.setBOOL("RenderAvatarVP", true); + //gSavedSettings.setBOOL("RenderAvatarVP", true); } else { getChildView("fbo")->setEnabled(gGLManager.mHasFramebufferObject); + //getChildView("fbo")->setValue(gSavedSettings.getBOOL("RenderUseFBO")); mCtrlAvatarVP->setEnabled(shaders); - if (!shaders) gSavedSettings.setBOOL("RenderAvatarVP", false); + //if (!shaders) gSavedSettings.setBOOL("RenderAvatarVP", false); } // now turn off any features that are unavailable @@ -714,25 +719,23 @@ void LLPanelDisplay::cancel() void LLPanelDisplay::apply() { - U32 fsaa_value = childGetValue("fsaa").asInteger(); - S32 vsync_value = childGetValue("vsync").asInteger(); - bool fbo_value = childGetValue("fbo").asBoolean(); + bool can_defer = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"); + S32 vsync_value = childGetValue("vsync").asInteger(); + bool fbo_value = childGetValue("fbo").asBoolean() || (can_defer && mCtrlDeferred->getValue().asBoolean()); + bool fbo_prior_value = mUseFBO || (can_defer && mDeferred ); + U8 fsaa_value = fbo_value ? 0 : childGetValue("fsaa").asInteger(); + U8 fsaa_prior_value = fbo_prior_value ? 0 : mFSAASamples; LLWindow* window = gViewerWindow->getWindow(); if(vsync_value == -1 && !gGLManager.mHasAdaptiveVsync) vsync_value = 0; - bool apply_fsaa_change = fbo_value ? false : (mFSAASamples != fsaa_value); - - if(!apply_fsaa_change && (bool)mUseFBO != fbo_value) - { - apply_fsaa_change = fsaa_value != 0 || mFSAASamples != 0 ; - } + bool apply_fsaa_change = fsaa_value != fsaa_prior_value; bool apply_vsync_change = vsync_value != mVsyncMode; - gSavedSettings.setU32("RenderFSAASamples", fsaa_value); + gSavedSettings.setU32("RenderFSAASamples", childGetValue("fsaa").asInteger()); gSavedSettings.setS32("SHRenderVsyncMode", vsync_value); applyResolution(); @@ -751,14 +754,14 @@ void LLPanelDisplay::apply() bool logged_in = (LLStartUp::getStartupState() >= STATE_STARTED); LLCoordScreen size; window->getSize(&size); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); gViewerWindow->changeDisplaySettings(window->getFullscreen(), size, vsync_value, logged_in); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); } } diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index dc656a0d3d..e179b971ee 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -103,6 +103,7 @@ enum ESubpart SUBPART_SKIRT, SUBPART_ALPHA, SUBPART_TATTOO, + SUBPART_UNIVERSAL, SUBPART_PHYSICS_BREASTS_UPDOWN, SUBPART_PHYSICS_BREASTS_INOUT, SUBPART_PHYSICS_BREASTS_LEFTRIGHT, @@ -137,7 +138,7 @@ class LLEditWearableDictionary : public LLSingleton const std::string &title, U8 num_color_swatches, // number of 'color_swatches' U8 num_texture_pickers, // number of 'texture_pickers' - U8 num_subparts, ... ); // number of subparts followed by a list of ETextureIndex and ESubparts + unsigned int num_subparts, ... ); // number of subparts followed by a list of ETextureIndex and ESubparts const LLWearableType::EType mWearableType; @@ -245,6 +246,7 @@ LLEditWearableDictionary::Wearables::Wearables() addEntry(LLWearableType::WT_SKIRT, new WearableEntry(LLWearableType::WT_SKIRT,"edit_skirt_title",1,1,1, TEX_SKIRT, TEX_SKIRT, SUBPART_SKIRT)); addEntry(LLWearableType::WT_ALPHA, new WearableEntry(LLWearableType::WT_ALPHA,"edit_alpha_title",0,5,1, TEX_LOWER_ALPHA, TEX_UPPER_ALPHA, TEX_HEAD_ALPHA, TEX_EYES_ALPHA, TEX_HAIR_ALPHA, SUBPART_ALPHA)); addEntry(LLWearableType::WT_TATTOO, new WearableEntry(LLWearableType::WT_TATTOO,"edit_tattoo_title",1,3,1, TEX_HEAD_TATTOO, TEX_LOWER_TATTOO, TEX_UPPER_TATTOO, TEX_HEAD_TATTOO, SUBPART_TATTOO)); + addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(LLWearableType::WT_UNIVERSAL, "edit_universal_title", 1, 11, 1, TEX_HEAD_UNIVERSAL_TATTOO, TEX_HEAD_UNIVERSAL_TATTOO, TEX_UPPER_UNIVERSAL_TATTOO, TEX_LOWER_UNIVERSAL_TATTOO, TEX_SKIRT_TATTOO, TEX_HAIR_TATTOO, TEX_EYES_TATTOO, TEX_LEFT_ARM_TATTOO, TEX_LEFT_LEG_TATTOO, TEX_AUX1_TATTOO, TEX_AUX2_TATTOO, TEX_AUX3_TATTOO, SUBPART_UNIVERSAL)); addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(LLWearableType::WT_PHYSICS,"edit_physics_title",0,0,7, SUBPART_PHYSICS_BREASTS_UPDOWN, SUBPART_PHYSICS_BREASTS_INOUT, SUBPART_PHYSICS_BREASTS_LEFTRIGHT, SUBPART_PHYSICS_BELLY_UPDOWN, SUBPART_PHYSICS_BUTT_UPDOWN, SUBPART_PHYSICS_BUTT_LEFTRIGHT, SUBPART_PHYSICS_ADVANCED)); } @@ -252,7 +254,7 @@ LLEditWearableDictionary::WearableEntry::WearableEntry(LLWearableType::EType typ const std::string &title, U8 num_color_swatches, U8 num_texture_pickers, - U8 num_subparts, ... ) : + unsigned int num_subparts, ... ) : LLDictionaryEntry(title), mWearableType(type) { @@ -315,6 +317,8 @@ LLEditWearableDictionary::Subparts::Subparts() addEntry(SUBPART_UNDERPANTS, new SubpartEntry(SUBPART_UNDERPANTS, "mPelvis", "underpants",LLStringUtil::null, LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f), SEX_BOTH)); addEntry(SUBPART_ALPHA, new SubpartEntry(SUBPART_ALPHA, "mPelvis", "alpha",LLStringUtil::null, LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f), SEX_BOTH)); addEntry(SUBPART_TATTOO, new SubpartEntry(SUBPART_TATTOO, "mPelvis", "tattoo", LLStringUtil::null, LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); + addEntry(SUBPART_UNIVERSAL, new SubpartEntry(SUBPART_UNIVERSAL, "mPelvis", "universal", LLStringUtil::null, LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f), SEX_BOTH)); + addEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, "mTorso", "physics_breasts_updown", "Breast Bounce", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-0.8f, 0.15f, 0.38),SEX_FEMALE)); addEntry(SUBPART_PHYSICS_BREASTS_INOUT, new SubpartEntry(SUBPART_PHYSICS_BREASTS_INOUT, "mTorso", "physics_breasts_inout", "Breast Cleavage", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-0.8f, 0.15f, 0.38f),SEX_FEMALE)); addEntry(SUBPART_PHYSICS_BREASTS_LEFTRIGHT, new SubpartEntry(SUBPART_PHYSICS_BREASTS_LEFTRIGHT, "mTorso", "physics_breasts_leftright", "Breast Sway", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-0.8f, 0.15f, 0.38f),SEX_FEMALE)); @@ -354,6 +358,7 @@ LLEditWearableDictionary::ColorSwatchCtrls::ColorSwatchCtrls() addEntry ( TEX_UPPER_UNDERSHIRT, new PickerControlEntry (TEX_UPPER_UNDERSHIRT, "Color/Tint" )); addEntry ( TEX_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "Color/Tint" )); addEntry ( TEX_HEAD_TATTOO, new PickerControlEntry(TEX_HEAD_TATTOO, "Color/Tint" )); + addEntry (TEX_HEAD_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_HEAD_UNIVERSAL_TATTOO, "Color/Tint")); } LLEditWearableDictionary::TextureCtrls::TextureCtrls() @@ -381,6 +386,17 @@ LLEditWearableDictionary::TextureCtrls::TextureCtrls() addEntry ( TEX_LOWER_TATTOO, new PickerControlEntry (TEX_LOWER_TATTOO, "Lower Tattoo", LLUUID::null, TRUE )); addEntry ( TEX_UPPER_TATTOO, new PickerControlEntry (TEX_UPPER_TATTOO, "Upper Tattoo", LLUUID::null, TRUE )); addEntry ( TEX_HEAD_TATTOO, new PickerControlEntry (TEX_HEAD_TATTOO, "Head Tattoo", LLUUID::null, TRUE )); + addEntry ( TEX_LOWER_UNIVERSAL_TATTOO, new PickerControlEntry( TEX_LOWER_UNIVERSAL_TATTOO, "Lower Universal Tattoo", LLUUID::null, TRUE)); + addEntry ( TEX_UPPER_UNIVERSAL_TATTOO, new PickerControlEntry( TEX_UPPER_UNIVERSAL_TATTOO, "Upper Universal Tattoo", LLUUID::null, TRUE)); + addEntry ( TEX_HEAD_UNIVERSAL_TATTOO, new PickerControlEntry( TEX_HEAD_UNIVERSAL_TATTOO, "Head Universal Tattoo", LLUUID::null, TRUE)); + addEntry ( TEX_SKIRT_TATTOO, new PickerControlEntry(TEX_SKIRT_TATTOO, "Skirt Tattoo", LLUUID::null, TRUE)); + addEntry ( TEX_HAIR_TATTOO, new PickerControlEntry(TEX_HAIR_TATTOO, "Hair Tattoo", LLUUID::null, TRUE)); + addEntry ( TEX_EYES_TATTOO, new PickerControlEntry(TEX_EYES_TATTOO, "Eyes Tattoo", LLUUID::null, TRUE)); + addEntry (TEX_LEFT_ARM_TATTOO, new PickerControlEntry(TEX_LEFT_ARM_TATTOO, "Left Arm Tattoo", LLUUID::null, TRUE)); + addEntry (TEX_LEFT_LEG_TATTOO, new PickerControlEntry(TEX_LEFT_LEG_TATTOO, "Left Leg Tattoo", LLUUID::null, TRUE)); + addEntry (TEX_AUX1_TATTOO, new PickerControlEntry(TEX_AUX1_TATTOO, "Aux1 Tattoo", LLUUID::null, TRUE)); + addEntry (TEX_AUX2_TATTOO, new PickerControlEntry(TEX_AUX2_TATTOO, "Aux2 Tattoo", LLUUID::null, TRUE)); + addEntry (TEX_AUX3_TATTOO, new PickerControlEntry(TEX_AUX3_TATTOO, "Aux3 Tattoo", LLUUID::null, TRUE)); } LLEditWearableDictionary::PickerControlEntry::PickerControlEntry(ETextureIndex tex_index, @@ -407,9 +423,9 @@ get_pickers_indexes(const LLEditWearableDictionary::WearableEntry *wearable_entr // Specializations of this template function return picker control entry for particular control type. template const LLEditWearableDictionary::PickerControlEntry* -get_picker_entry (const ETextureIndex index) { return NULL; } +get_picker_entry (const ETextureIndex index) { return nullptr; } -typedef boost::function function_t; +typedef std::function function_t; typedef struct PickerControlEntryNamePredicate { @@ -473,16 +489,13 @@ find_picker_ctrl_entry_if(LLWearableType::EType type, const Predicate pred) if (!wearable_entry) { LL_WARNS() << "could not get wearable dictionary entry for wearable of type: " << type << LL_ENDL; - return NULL; + return nullptr; } const texture_vec_t& indexes = get_pickers_indexes(wearable_entry); - for (texture_vec_t::const_iterator - iter = indexes.begin(), - iter_end = indexes.end(); - iter != iter_end; ++iter) + for (auto te : indexes) { - const ETextureIndex te = *iter; - const LLEditWearableDictionary::PickerControlEntry* entry = get_picker_entry(te); + const LLEditWearableDictionary::PickerControlEntry* entry + = get_picker_entry(te); if (!entry) { LL_WARNS() << "could not get picker dictionary entry (" << te << ") for wearable of type: " << type << LL_ENDL; @@ -493,7 +506,7 @@ find_picker_ctrl_entry_if(LLWearableType::EType type, const Predicate pred) return entry; } } - return NULL; + return nullptr; } template @@ -511,12 +524,8 @@ void for_each_picker_ctrl_entry(LLPanel* panel, LLWearableType::EType type, func return; } const texture_vec_t& indexes = get_pickers_indexes(wearable_entry); - for (texture_vec_t::const_iterator - iter = indexes.begin(), - iter_end = indexes.end(); - iter != iter_end; ++iter) + for (const auto& te : indexes) { - const ETextureIndex te = *iter; const LLEditWearableDictionary::PickerControlEntry* entry = get_picker_entry(te); if (!entry) { @@ -684,6 +693,16 @@ LLPanelEditWearable::~LLPanelEditWearable() } } +static std::string getTabName(U32 i) { return llformat("%i", i); } +void LLPanelEditWearable::addLayerTabs(U32 index, U32 last) +{ + for(U32 i = index; i <= last; ++i) + { + const auto number = getTabName(i); + mTab->addTabPanel(new LLPanel(number), "Layer " + number); + } +} + BOOL LLPanelEditWearable::postBuild() { std::string icon_name = LLInventoryIcon::getIconName(LLWearableType::getAssetType( mType ),LLInventoryType::IT_WEARABLE,mType,FALSE); @@ -691,15 +710,31 @@ BOOL LLPanelEditWearable::postBuild() getChildView("icon")->setValue(icon_name); mCreateNew = getChild("Create New"); - mCreateNew->setCommitCallback(boost::bind(&LLPanelEditWearable::onBtnCreateNew, this) ); + mCreateNew->setCommitCallback(boost::bind(&LLPanelEditWearable::onBtnCreateNew, this)); + + if (mCreateNewLayer = findChild("New Layer")) + { + mCreateNewLayer->setCommitCallback(boost::bind(&LLPanelEditWearable::onBtnCreateNew, this)); + } + + if (mTakeOff = findChild("Take Off")) + { + // If PG, can't take off underclothing or shirt + mCanTakeOff = !(gAgent.isTeen() && (mType == LLWearableType::WT_UNDERSHIRT || mType == LLWearableType::WT_UNDERPANTS) ); + mTakeOff->setVisible(mCanTakeOff); + mTakeOff->setCommitCallback(boost::bind(&LLPanelEditWearable::onBtnTakeOff, this)); + } + + if (mArrowLeft = findChild("Arrow Left")) + { + mArrowLeft->setCommitCallback(boost::bind(&LLPanelEditWearable::onMoveToLayer, this, true)); + } + + if (mArrowRight = findChild("Arrow Right")) + { + mArrowRight->setCommitCallback(boost::bind(&LLPanelEditWearable::onMoveToLayer, this, false)); + } - mTakeOff = getChild("Take Off"); - // If PG, can't take off underclothing or shirt - mCanTakeOff = - LLWearableType::getAssetType( mType ) == LLAssetType::AT_CLOTHING && - !( gAgent.isTeen() && (mType == LLWearableType::WT_UNDERSHIRT || mType == LLWearableType::WT_UNDERPANTS) ); - mTakeOff->setVisible(mCanTakeOff); - mTakeOff->setCommitCallback(boost::bind(&LLPanelEditWearable::onBtnTakeOff, this) ); if (mSexRadio = findChild("sex radio")) { @@ -707,7 +742,7 @@ BOOL LLPanelEditWearable::postBuild() } mSave = getChild("Save"); - mSave->setCommitCallback(boost::bind(&LLPanelEditWearable::saveChanges, this, false, std::string()) ); + mSave->setCommitCallback(boost::bind(&LLPanelEditWearable::saveChanges, this, false, LLStringUtil::null) ); mSaveAs = getChild("Save As"); mSaveAs->setCommitCallback(boost::bind(&LLPanelEditWearable::onBtnSaveAs, this) ); @@ -738,9 +773,9 @@ BOOL LLPanelEditWearable::postBuild() { LL_WARNS() << "could not get wearable dictionary entry for wearable of type: " << mType << LL_ENDL; } - U8 num_subparts = wearable_entry->mSubparts.size(); + const U8 num_subparts = (U8) wearable_entry->mSubparts.size(); - for (U8 index = 0; index < num_subparts; ++index) + for (U8 index = 0; num_subparts > 1 && index < num_subparts; ++index) { // dive into data structures to get the panel we need ESubpart subpart_e = wearable_entry->mSubparts[index]; @@ -755,7 +790,7 @@ BOOL LLPanelEditWearable::postBuild() if (!subpart_entry->mButtonName.empty()) { - LL_INFOS() << "Finding button " << subpart_entry->mButtonName << LL_ENDL; + //LL_INFOS() << "Finding button " << subpart_entry->mButtonName << LL_ENDL; LLButton* btn(findChild(subpart_entry->mButtonName)); llassert_always(btn); mSubpartBtns.push_back(btn); @@ -774,12 +809,7 @@ BOOL LLPanelEditWearable::postBuild() if (mTab = findChild("layer_tabs")) { - LL_COMPILE_TIME_MESSAGE("layer_tabs needs re-implemented"); - for(U32 i = 1; i <= 6/*LLAgentWearables::MAX_CLOTHING_PER_TYPE*/; ++i) - { - LLPanel* new_panel = new LLPanel(llformat("%i",i)); - mTab->addTabPanel(new_panel, llformat("Layer %i",i)); - } + addLayerTabs(1, gAgentWearables.getWearableCount(mType)); mTab->setCommitCallback(boost::bind(&LLPanelEditWearable::onTabChanged, this, _1)); mTab->setValidateCallback(boost::bind(&LLPanelEditWearable::onTabPrecommit, this)); } @@ -805,13 +835,12 @@ void LLPanelEditWearable::draw() refreshWearables(false); LLViewerWearable* wearable = getWearable(); - BOOL has_wearable = (wearable != NULL ); - BOOL has_any_wearable = has_wearable || gAgentWearables.getWearableCount(mType); + BOOL has_wearable = wearable != nullptr; BOOL is_dirty = isDirty(); BOOL is_modifiable = FALSE; BOOL is_copyable = FALSE; BOOL is_complete = FALSE; - LLInventoryItem* item = NULL; + LLInventoryItem* item = nullptr; if (wearable && (item = gInventory.getItem(wearable->getItemID()))) { const LLPermissions& perm = item->getPermissions(); @@ -823,17 +852,8 @@ void LLPanelEditWearable::draw() mSave->setEnabled(has_wearable && is_modifiable && is_complete && is_dirty); mSaveAs->setEnabled(has_wearable && is_copyable && is_complete); mRevert->setEnabled(has_wearable && is_dirty ); - mTakeOff->setEnabled(has_wearable); - if (mCanTakeOff) mTakeOff->setVisible(has_wearable); - mCreateNew->setVisible(!has_any_wearable); - mNotWornI->setVisible(!has_any_wearable); - mNotWornT->setVisible(!has_any_wearable); - mNoModI->setVisible(has_wearable && !is_modifiable); - mNoModT->setVisible(has_wearable && !is_modifiable); mTitle->setVisible(has_wearable && is_modifiable && is_complete); - mTitleLoading->setVisible(has_wearable ? is_modifiable && !is_complete : has_any_wearable); - mPath->setVisible(has_wearable); - mSquare->setVisible(has_wearable && !is_modifiable); //lock icon + mTitleLoading->setVisible(has_wearable && is_modifiable && !is_complete); if (has_wearable && is_modifiable) { @@ -859,9 +879,9 @@ void LLPanelEditWearable::draw() const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(mType); if (wearable_entry) { - U8 num_subparts = wearable_entry->mSubparts.size(); + const U8 num_subparts = (U8) wearable_entry->mSubparts.size(); - for (U8 index = 0; index < num_subparts; ++index) + for (U8 index = 0; num_subparts > 1 && index < num_subparts; ++index) { // dive into data structures to get the panel we need ESubpart subpart_e = wearable_entry->mSubparts[index]; @@ -924,7 +944,7 @@ void LLPanelEditWearable::onTabChanged(LLUICtrl* ctrl) if (mPendingWearable) return; U32 tab_index = ((LLTabContainer*)ctrl)->getCurrentPanelIndex(); - U32 wearable_index = gAgentWearables.getWearableCount(mType) - tab_index - 1; + U32 wearable_index = tab_index ; if (wearable_index != mCurrentIndex ) { setWearableIndex(wearable_index); @@ -945,25 +965,17 @@ void LLPanelEditWearable::setWearableIndex(S32 index) if (mTab) { - U32 tab_index = gAgentWearables.getWearableCount(mType) - index - 1; - - if (mTab->getCurrentPanelIndex() != tab_index) - mTab->selectTab(tab_index); + if (mTab->getTabCount() && mTab->getCurrentPanelIndex() != index) + mTab->selectTab(index); } + LLViewerWearable* wearable = gAgentWearables.getViewerWearable(mType,mCurrentIndex); // Singu note: Set title even if the wearable didn't change: the name might have changed (when renamed). - if (wearable) - { - mTitle->setTextArg("[DESC]", wearable->getName()); - mNoModT->setTextArg("[DESC]", wearable->getName()); - } - else - { - mTitle->setTextArg("[DESC]", std::string(LLWearableType::getTypeLabel(mType))); - mNoModT->setTextArg("[DESC]", std::string(LLWearableType::getTypeLabel(mType))); - } + const auto& desc = wearable ? wearable->getName() : LLWearableType::getTypeLabel(mType); + mTitle->setTextArg("[DESC]", desc); + mNoModT->setTextArg("[DESC]", desc); if (wearable == getWearable()) return; @@ -999,7 +1011,6 @@ void LLPanelEditWearable::setWearableIndex(S32 index) } updateScrollingPanelList(); - } void LLPanelEditWearable::refreshWearables(bool force_immediate) @@ -1028,10 +1039,22 @@ void LLPanelEditWearable::refreshWearables(bool force_immediate) if (mTab) { - LL_COMPILE_TIME_MESSAGE("layer_tabs needs re-implemented"); - for(U32 i = 0; i < 6/*LLAgentWearables::MAX_CLOTHING_PER_TYPE*/; ++i) + S32 layer_count = gAgentWearables.getWearableCount(mType); + S32 tab_count = mTab->getTabCount(); + if (tab_count > layer_count) // Remove some tabs { - mTab->enableTabButton(i, i < gAgentWearables.getWearableCount(mType)); + while (tab_count && tab_count > layer_count) + { + if (auto tab = mTab->getChild(getTabName(tab_count--), false, false)) + { + mTab->removeTabPanel(tab); + delete tab; + } + } + } + else if (layer_count > tab_count) // Add some tabs + { + addLayerTabs(tab_count+1, layer_count); } } setWearableIndex(index); @@ -1078,7 +1101,7 @@ void LLPanelEditWearable::onCommitSexChange() return; } - bool is_new_sex_male = (gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE) == SEX_MALE; + bool is_new_sex_male = gSavedSettings.getU32("AvatarSex") ? true : false; LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, index); if (wearable) { @@ -1116,7 +1139,7 @@ bool LLPanelEditWearable::onSelectAutoWearOption(const LLSD& notification, const // Only auto wear the new item if the AutoWearNewClothing checkbox is selected. LLPointer cb = option == 0 ? - new LLBoostFuncInventoryCallback(boost::bind(&wear_on_avatar_cb,_1,false)) : NULL; + new LLBoostFuncInventoryCallback(boost::bind(&wear_on_avatar_cb,_1,false)) : nullptr; create_inventory_item(gAgent.getID(), gAgent.getSessionID(), folder_id, wearable->getTransactionID(), wearable->getName(), wearable->getDescription(), asset_type, LLInventoryType::IT_WEARABLE, wearable->getType(), @@ -1125,9 +1148,27 @@ bool LLPanelEditWearable::onSelectAutoWearOption(const LLSD& notification, const return false; } +void LLPanelEditWearable::onMoveToLayer(bool closer) +{ + const auto wearable = getWearable(); + auto& appearance_mgr(LLAppearanceMgr::instance()); + auto links = appearance_mgr.findCOFItemLinks(wearable->getItemID()); + if (links.empty()) return; + auto link = links.front(); + if (gAgentWearables.moveWearable(link, closer)) + { + gAgentAvatarp->wearableUpdated(mType, true); + /* Singu TODO: Figure out how to maintain focus on the current tab + U32 index(0); + gAgentWearables.getWearableIndex(wearable, index); + setWearableIndex(index); + */ + } +} + LLViewerWearable* LLPanelEditWearable::getWearable() const { - return mCurrentWearable;//gAgentWearables.getWearable(mType, mCurrentIndex); // TODO: MULTI-WEARABLE + return mCurrentWearable; } U32 LLPanelEditWearable::getIndex() const @@ -1278,13 +1319,18 @@ void LLPanelEditWearable::saveChanges(bool force_save_as, std::string new_name) if (link_item) { // Create new link + LL_DEBUGS("Avatar") << "link refresh, creating new link to " << link_item->getLinkedUUID() + << " removing old link at " << link_item->getUUID() + << /*" wearable item id " << mWearablePtr->getItemID() <<*/ LL_ENDL; + link_inventory_object( LLAppearanceMgr::instance().getCOF(), link_item, NULL); + // Remove old link remove_inventory_item(link_item, NULL); } - gAgentWearables.saveWearable(mType, index, TRUE, new_name); + gAgentWearables.saveWearable(mType, index, new_name); } } @@ -1440,23 +1486,58 @@ void LLPanelEditWearable::updateScrollingPanelList() void LLPanelEditWearable::updateScrollingPanelUI() { LLViewerWearable* wearable = getWearable(); - // do nothing if we don't have a valid wearable we're editing - if (!wearable) - { - return; - } - - LL_INFOS() << llformat("%#.8lX",wearable) << LL_ENDL; - LL_INFOS() << "cur_wearable->isDirty()=" << wearable->isDirty() << LL_ENDL; - LLViewerInventoryItem* item = gInventory.getItem(wearable->getItemID()); + BOOL is_modifiable = FALSE; + BOOL is_copyable = FALSE; + LLViewerInventoryItem* item = wearable ? gInventory.getItem(wearable->getItemID()) : nullptr; if (item) { - U32 perm_mask = item->getPermissions().getMaskOwner(); BOOL is_complete = item->isComplete(); LLScrollingPanelParam::sUpdateDelayFrames = 0; - mCustomizeFloater->getScrollingPanelList()->updatePanels((perm_mask & PERM_MODIFY) && is_complete); + const LLPermissions& perm = item->getPermissions(); + const auto& group_id(gAgent.getGroupID()); + is_modifiable = perm.allowModifyBy(gAgentID, group_id); + is_copyable = perm.allowCopyBy(gAgentID, group_id); + mCustomizeFloater->getScrollingPanelList()->updatePanels(is_modifiable && is_complete); } + + // Update some UI here instead of the draw call + bool has_wearable = wearable != nullptr; + bool max_layers = gAgentWearables.getClothingLayerCount() == LLAgentWearables::MAX_CLOTHING_LAYERS; + bool show_create_new = !has_wearable && !max_layers; + + if (mTakeOff) + { + mTakeOff->setEnabled(has_wearable); + if (mCanTakeOff) mTakeOff->setVisible(has_wearable); + } + if (mCreateNewLayer) + { + mCreateNewLayer->setVisible(has_wearable && !max_layers); + } + if (mArrowLeft) + { + mArrowLeft->setEnabled(has_wearable && gAgentWearables.getBottomWearable(mType) != wearable); + mArrowLeft->setVisible(has_wearable); + } + if (mArrowRight) + { + mArrowRight->setEnabled(has_wearable && gAgentWearables.getTopWearable(mType) != wearable); + mArrowRight->setVisible(has_wearable); + } + mCreateNew->setVisible(show_create_new); + mNotWornI->setVisible(show_create_new); + mNotWornT->setVisible(show_create_new); + mNoModI->setVisible(has_wearable && !is_modifiable); + mNoModT->setVisible(has_wearable && !is_modifiable); + mPath->setVisible(has_wearable); + mSquare->setVisible(has_wearable && !is_modifiable); //lock icon + + // do nothing else if we don't have a valid wearable we're editing + if (!wearable) return; + //LL_INFOS() << llformat("%#.8lX", wearable) << LL_ENDL; + //LL_INFOS() << "cur_wearable->isDirty()=" << wearable->isDirty() << LL_ENDL; + refreshWearables(false); } void LLPanelEditWearable::onBtnTakeOff() @@ -1599,7 +1680,7 @@ void LLPanelEditWearable::initPreviousAlphaTextures() initPreviousAlphaTextureEntry(TEX_UPPER_ALPHA); initPreviousAlphaTextureEntry(TEX_HEAD_ALPHA); initPreviousAlphaTextureEntry(TEX_EYES_ALPHA); - initPreviousAlphaTextureEntry(TEX_LOWER_ALPHA); + initPreviousAlphaTextureEntry(TEX_HAIR_ALPHA); } void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLAvatarAppearanceDefines::ETextureIndex te) diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 4bf1cc75eb..a6da8c73c5 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -56,6 +56,7 @@ class LLPanelEditWearable : public LLPanel LLPanelEditWearable( LLWearableType::EType type, LLFloaterCustomize* parent ); virtual ~LLPanelEditWearable(); + void addLayerTabs(U32 index, U32 last); /*virtual*/ BOOL postBuild(); /*virtual*/ BOOL isDirty() const; // LLUICtrl /*virtual*/ void draw(); @@ -108,6 +109,8 @@ class LLPanelEditWearable : public LLPanel void onBtnCreateNew(); static bool onSelectAutoWearOption(const LLSD& notification, const LLSD& response); + void onMoveToLayer(bool closer); + void onColorSwatchCommit(const LLUICtrl*); void onTexturePickerCommit(const LLUICtrl*); void setNewImageID(ETextureIndex te_index, LLUUID const& uuid); //Singu note: this used to be part of onTexturePickerCommit. @@ -137,7 +140,7 @@ class LLPanelEditWearable : public LLPanel //a bazillion pointless (and not particularly valid) times. Deferring to draw effectively sorts it all out. // Cached UI - LLUICtrl *mCreateNew, *mTakeOff, *mSexRadio, *mSave, *mSaveAs, *mRevert, *mNotWornT, *mNoModT, *mTitle, *mTitleLoading, *mPath, *mAvHeight; + LLUICtrl *mCreateNew, *mCreateNewLayer, *mTakeOff, *mArrowLeft, *mArrowRight, *mSexRadio, *mSave, *mSaveAs, *mRevert, *mNotWornT, *mNoModT, *mTitle, *mTitleLoading, *mPath, *mAvHeight; LLView *mNotWornI, *mNoModI, *mSquare; LLTabContainer* mTab; std::vector mSubpartBtns; diff --git a/indra/newview/llpanelevent.cpp b/indra/newview/llpanelevent.cpp index 5295d97b8f..5eb6fe51d8 100644 --- a/indra/newview/llpanelevent.cpp +++ b/indra/newview/llpanelevent.cpp @@ -54,6 +54,8 @@ #include "llweb.h" #include "llworldmap.h" #include "lluictrlfactory.h" +#include "hippogridmanager.h" +#include "lfsimfeaturehandler.h" //static std::list LLPanelEvent::sAllPanels; @@ -69,6 +71,10 @@ LLPanelEvent::~LLPanelEvent() sAllPanels.remove(this); } +void enable_create(const std::string& url, LLView* btn) +{ + btn->setEnabled(!url.empty()); +} BOOL LLPanelEvent::postBuild() { @@ -97,8 +103,15 @@ BOOL LLPanelEvent::postBuild() mNotifyBtn = getChild( "notify_btn"); mNotifyBtn->setClickedCallback(boost::bind(&LLPanelEvent::onClickNotify,this)); - mCreateEventBtn = getChild( "create_event_btn"); - mCreateEventBtn->setClickedCallback(boost::bind(&LLPanelEvent::onClickCreateEvent,this)); + mCreateEventBtn = getChild("create_event_btn"); + mCreateEventBtn->setClickedCallback(boost::bind(&LLPanelEvent::onClickCreateEvent, this)); + if (!gHippoGridManager->getConnectedGrid()->isSecondLife()) + { + auto& inst(LFSimFeatureHandler::instance()); + mCreateEventBtn->setEnabled(!inst.getEventsURL().empty()); + inst.setEventsURLCallback(boost::bind(enable_create, _1, mCreateEventBtn)); + } + return TRUE; } @@ -126,9 +139,8 @@ void LLPanelEvent::processEventInfoReply(LLMessageSystem *msg, void **) msg->getU32("EventData", "EventID", event_id); // look up all panels which have this avatar - for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter) + for (auto& self : sAllPanels) { - LLPanelEvent* self = *iter; // Skip updating panels which aren't for this event if (self->mEventID != event_id) { @@ -138,7 +150,8 @@ void LLPanelEvent::processEventInfoReply(LLMessageSystem *msg, void **) self->mTBName->setText(self->mEventInfo.mName); self->mTBCategory->setText(self->mEventInfo.mCategoryStr); self->mTBDate->setText(self->mEventInfo.mTimeStr); - self->mTBDesc->setText(self->mEventInfo.mDesc); + self->mTBDesc->setText(self->mEventInfo.mDesc, false); + self->mTBRunBy->setValue(self->mEventInfo.mRunByID); self->mTBDuration->setText(llformat("%d:%.2d", self->mEventInfo.mDuration / 60, self->mEventInfo.mDuration % 60)); @@ -192,17 +205,6 @@ void LLPanelEvent::processEventInfoReply(LLMessageSystem *msg, void **) } } - -void LLPanelEvent::draw() -{ - std::string name; - gCacheName->getFullName(mEventInfo.mRunByID, name); - - mTBRunBy->setText(name); - - LLPanel::draw(); -} - void LLPanelEvent::resetInfo() { // Clear all of the text fields. @@ -286,8 +288,8 @@ bool LLPanelEvent::callbackCreateEventWebPage(const LLSD& notification, const LL if (0 == option) { LL_INFOS() << "Loading events page " << EVENTS_URL << LL_ENDL; - - LLWeb::loadURL(EVENTS_URL); + const std::string& opensim_events = LFSimFeatureHandler::instance().getEventsURL(); + LLWeb::loadURL(opensim_events.empty() ? EVENTS_URL : opensim_events); } return false; } diff --git a/indra/newview/llpanelevent.h b/indra/newview/llpanelevent.h index 90c08bde0a..353b66fd16 100644 --- a/indra/newview/llpanelevent.h +++ b/indra/newview/llpanelevent.h @@ -51,7 +51,6 @@ class LLPanelEvent : public LLPanel /*virtual*/ ~LLPanelEvent(); /*virtual*/ BOOL postBuild(); - /*virtual*/ void draw(); void setEventID(const U32 event_id); void sendEventInfoRequest(); diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp new file mode 100644 index 0000000000..784fc9cfea --- /dev/null +++ b/indra/newview/llpanelexperiencelisteditor.cpp @@ -0,0 +1,280 @@ +/** + * @file llpanelexperiencelisteditor.cpp + * @brief Editor for building a list of experiences + * + * $LicenseInfo:firstyear=2014&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 "llviewerprecompiledheaders.h" + +#include "llpanelexperiencelisteditor.h" + +#include "llbutton.h" +#include "llexperiencecache.h" +#include "llfloaterexperiencepicker.h" +#include "llfloaterexperienceprofile.h" +//#include "llfloaterreg.h" +#include "llhandle.h" +#include "llnamelistctrl.h" +#include "llscrolllistctrl.h" +#include "llviewerregion.h" +#include "llagent.h" +#include "lltextbox.h" +#include "lltrans.h" + + +/* Singu Note: We do not have injectors, so we'll have to call this function instead +static LLPanelInjector t_panel_experience_list_editor("panel_experience_list_editor"); +*/ +void* create_xp_list_editor(void* data) +{ + return *reinterpret_cast(data) = new LLPanelExperienceListEditor; +} + + +LLPanelExperienceListEditor::LLPanelExperienceListEditor() + :mItems(nullptr) + ,mAdd(nullptr) + ,mRemove(nullptr) + ,mProfile(nullptr) + ,mAddedCallback() + ,mRemovedCallback() + ,mReadonly(false) + ,mMaxExperienceIDs(0) +{ +} + +BOOL LLPanelExperienceListEditor::postBuild() +{ + mItems = getChild("experience_list"); + mAdd = getChild("btn_add"); + mRemove = getChild("btn_remove"); + mProfile = getChild("btn_profile"); + + childSetAction("btn_add", boost::bind(&LLPanelExperienceListEditor::onAdd, this)); + childSetAction("btn_remove", boost::bind(&LLPanelExperienceListEditor::onRemove, this)); + childSetAction("btn_profile", boost::bind(&LLPanelExperienceListEditor::onProfile, this)); + + mItems->setCommitCallback(boost::bind(&LLPanelExperienceListEditor::checkButtonsEnabled, this)); + + checkButtonsEnabled(); + return TRUE; +} + +const uuid_list_t& LLPanelExperienceListEditor::getExperienceIds() const +{ + return mExperienceIds; +} + +void LLPanelExperienceListEditor::addExperienceIds( const uuid_vec_t& experience_ids ) +{ + // the commented out code in this function is handled by the callback and no longer necessary! + + //mExperienceIds.insert(experience_ids.begin(), experience_ids.end()); + //onItems(); + if(!mAddedCallback.empty()) + { + for(uuid_vec_t::const_iterator it = experience_ids.begin(); it != experience_ids.end(); ++it) + { + mAddedCallback(*it); + } + } +} + + +void LLPanelExperienceListEditor::setExperienceIds( const LLSD& experience_ids ) +{ + mExperienceIds.clear(); + for (const auto& id : experience_ids.array()) + { + // Using insert(range) doesn't work here because the conversion from + // LLSD to LLUUID is ambiguous: have to specify asUUID() for each entry. + mExperienceIds.insert(id.asUUID()); + } + onItems(); +} + +void LLPanelExperienceListEditor::addExperience( const LLUUID& id ) +{ + mExperienceIds.insert(id); + onItems(); +} +void LLPanelExperienceListEditor::onAdd() +{ + if(!mPicker.isDead()) + { + mPicker.markDead(); + } + + mKey.generateNewID(); + + LLFloaterExperiencePicker* picker = LLFloaterExperiencePicker::show(boost::bind(&LLPanelExperienceListEditor::addExperienceIds, this, _1), mKey, FALSE, TRUE, mFilters, mAdd); + mPicker = picker->getDerivedHandle(); +} + + +void LLPanelExperienceListEditor::onRemove() +{ + // the commented out code in this function is handled by the callback and no longer necessary! + + std::vector items= mItems->getAllSelected(); + std::vector::iterator it = items.begin(); + for(/**/; it != items.end(); ++it) + { + if((*it) != nullptr) + { + //mExperienceIds.erase((*it)->getValue()); + mRemovedCallback((*it)->getValue()); + } + } + mItems->selectFirstItem(); + checkButtonsEnabled(); + //onItems(); +} + +void LLPanelExperienceListEditor::onProfile() +{ + LLScrollListItem* item = mItems->getFirstSelected(); + if(item) + { + LLFloaterExperienceProfile::showInstance(item->getUUID()); + } +} + +void LLPanelExperienceListEditor::checkButtonsEnabled() +{ + mAdd->setEnabled(!mReadonly); + int selected = mItems->getNumSelected(); + + bool remove_enabled = !mReadonly && selected>0; + if(remove_enabled && mSticky) + { + std::vector items= mItems->getAllSelected(); + std::vector::iterator it = items.begin(); + for(/**/; it != items.end() && remove_enabled; ++it) + { + if((*it) != nullptr) + { + remove_enabled = !mSticky((*it)->getValue()); + } + } + + + } + mRemove->setEnabled(remove_enabled); + mProfile->setEnabled(selected==1); +} + +void LLPanelExperienceListEditor::onItems() +{ + mItems->deleteAllItems(); + + LLSD item; + uuid_list_t::iterator it = mExperienceIds.begin(); + for(/**/; it != mExperienceIds.end(); ++it) + { + const LLUUID& experience = *it; + item["id"]=experience; + item["target"] = LLNameListItem::EXPERIENCE; + LLSD& columns = item["columns"]; + columns[0]["column"] = "experience_name"; + columns[0]["value"] = getString("loading"); + mItems->addElement(item); + + LLExperienceCache::instance().get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, + getDerivedHandle(), _1)); + } + + + if(mItems->getItemCount() == 0) + { + mItems->setCommentText(getString("no_results")); + } + + + checkButtonsEnabled(); +} + +void LLPanelExperienceListEditor::experienceDetailsCallback( LLHandle panel, const LLSD& experience ) +{ + if(!panel.isDead()) + { + panel.get()->onExperienceDetails(experience); + } +} + +void LLPanelExperienceListEditor::onExperienceDetails( const LLSD& experience ) +{ + LLScrollListItem* item = mItems->getItem(experience[LLExperienceCache::EXPERIENCE_ID]); + if(!item) + return; + + std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); + if (experience_name_string.empty()) + { + experience_name_string = LLTrans::getString("ExperienceNameUntitled"); + } + + item->getColumn(0)->setValue(experience_name_string); +} + +LLPanelExperienceListEditor::~LLPanelExperienceListEditor() +{ + if(!mPicker.isDead()) + { + mPicker.get()->close(); + } +} + +void LLPanelExperienceListEditor::loading() +{ + mItems->clear(); + mItems->setCommentText( getString("loading")); +} + +void LLPanelExperienceListEditor::setReadonly( bool val ) +{ + mReadonly = val; + checkButtonsEnabled(); +} + +void LLPanelExperienceListEditor::refreshExperienceCounter() +{ + if(mMaxExperienceIDs > 0) + { + LLStringUtil::format_map_t args; + args["[EXPERIENCES]"] = llformat("%d", mItems->getItemCount()); + args["[MAXEXPERIENCES]"] = llformat("%d", mMaxExperienceIDs); + getChild("text_count")->setText(LLTrans::getString("ExperiencesCounter", args)); + } +} + +boost::signals2::connection LLPanelExperienceListEditor::setAddedCallback( list_changed_signal_t::slot_type cb ) +{ + return mAddedCallback.connect(cb); +} + +boost::signals2::connection LLPanelExperienceListEditor::setRemovedCallback( list_changed_signal_t::slot_type cb ) +{ + return mRemovedCallback.connect(cb); +} + diff --git a/indra/newview/llpanelexperiencelisteditor.h b/indra/newview/llpanelexperiencelisteditor.h new file mode 100644 index 0000000000..38b2c2179c --- /dev/null +++ b/indra/newview/llpanelexperiencelisteditor.h @@ -0,0 +1,102 @@ +/** +* @file llpanelexperiencelisteditor.cpp +* @brief Editor for building a list of experiences +* +* $LicenseInfo:firstyear=2014&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_LLPANELEXPERIENCELISTEDITOR_H +#define LL_LLPANELEXPERIENCELISTEDITOR_H + +#include "llpanel.h" +#include "lluuid.h" +#include + +class LLNameListCtrl; +class LLScrollListCtrl; +class LLButton; +class LLFloaterExperiencePicker; + +void* create_xp_list_editor(void* data); // +class LLPanelExperienceListEditor final : public LLPanel +{ +public: + + typedef boost::signals2::signal list_changed_signal_t; + // filter function for experiences, return true if the experience should be hidden. + typedef std::function experience_function; + typedef std::vector filter_list; + typedef LLHandle PickerHandle; + LLPanelExperienceListEditor(); + ~LLPanelExperienceListEditor(); + BOOL postBuild() override; + + void loading(); + + const uuid_list_t& getExperienceIds()const; + void setExperienceIds(const LLSD& experience_ids); + void addExperienceIds(const uuid_vec_t& experience_ids); + + void addExperience(const LLUUID& id); + + boost::signals2::connection setAddedCallback(list_changed_signal_t::slot_type cb ); + boost::signals2::connection setRemovedCallback(list_changed_signal_t::slot_type cb ); + + bool getReadonly() const { return mReadonly; } + void setReadonly(bool val); + + void refreshExperienceCounter(); + + void addFilter(experience_function func){mFilters.push_back(func);} + void setStickyFunction(experience_function func){mSticky = func;} + U32 getMaxExperienceIDs() const { return mMaxExperienceIDs; } + void setMaxExperienceIDs(U32 val) { mMaxExperienceIDs = val; } +private: + + void onItems(); + void onRemove(); + void onAdd(); + void onProfile(); + + void checkButtonsEnabled(); + static void experienceDetailsCallback( LLHandle panel, const LLSD& experience ); + void onExperienceDetails( const LLSD& experience ); + void processResponse( const LLSD& content ); + uuid_list_t mExperienceIds; + + + LLScrollListCtrl* mItems; + filter_list mFilters; + LLButton* mAdd; + LLButton* mRemove; + LLButton* mProfile; + PickerHandle mPicker; + list_changed_signal_t mAddedCallback; + list_changed_signal_t mRemovedCallback; + LLUUID mKey; + bool mReadonly; + experience_function mSticky; + U32 mMaxExperienceIDs; + +}; + +#endif //LL_LLPANELEXPERIENCELISTEDITOR_H diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp new file mode 100644 index 0000000000..fb866261a2 --- /dev/null +++ b/indra/newview/llpanelexperiencelog.cpp @@ -0,0 +1,270 @@ +/** + * @file llpanelexperiencelog.cpp + * @brief llpanelexperiencelog + * + * $LicenseInfo:firstyear=2014&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, 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 "llviewerprecompiledheaders.h" +#include "llpanelexperiencelog.h" + +#include "llexperiencelog.h" +#include "llexperiencecache.h" +#include "llbutton.h" +#include "llscrolllistctrl.h" +#include "llcombobox.h" +#include "llspinctrl.h" +#include "llcheckboxctrl.h" +#include "llfloaterexperienceprofile.h" +//#include "llfloaterreg.h" +#include "lluictrlfactory.h" +#include "llfloaterreporter.h" +#include "llinventoryfunctions.h" + +#include + + +#define BTN_PROFILE_XP "btn_profile_xp" +#define BTN_REPORT_XP "btn_report_xp" + +/* Singu Note: We do not have injectors, so we'll have to call this function instead +static LLPanelInjector register_experiences_panel("experience_log"); +*/ +void* create_xp_log(void* data) { return new LLPanelExperienceLog(false); } + + +LLPanelExperienceLog::LLPanelExperienceLog(bool build) + : mEventList(nullptr) + , mPageSize(25) + , mCurrentPage(0) +{ + //buildFromFile("panel_experience_log.xml"); + if (build) LLUICtrlFactory::getInstance()->buildPanel(this, "panel_experience_log.xml"); // Singu Note: Use filename in xml +} + +BOOL LLPanelExperienceLog::postBuild( void ) +{ + LLExperienceLog* log = LLExperienceLog::getInstance(); + mEventList = getChild("experience_log_list"); + mEventList->setCommitCallback(boost::bind(&LLPanelExperienceLog::onSelectionChanged, this)); + mEventList->setDoubleClickCallback( boost::bind(&LLPanelExperienceLog::onProfileExperience, this)); + + getChild("btn_clear")->setCommitCallback(boost::bind(&LLExperienceLog::clear, log)); + getChild("btn_clear")->setCommitCallback(boost::bind(&LLPanelExperienceLog::refresh, this)); + + getChild(BTN_PROFILE_XP)->setCommitCallback(boost::bind(&LLPanelExperienceLog::onProfileExperience, this)); + getChild(BTN_REPORT_XP )->setCommitCallback(boost::bind(&LLPanelExperienceLog::onReportExperience, this)); + getChild("btn_notify" )->setCommitCallback(boost::bind(&LLPanelExperienceLog::onNotify, this)); + getChild("btn_next" )->setCommitCallback(boost::bind(&LLPanelExperienceLog::onNext, this)); + getChild("btn_prev" )->setCommitCallback(boost::bind(&LLPanelExperienceLog::onPrev, this)); + + LLCheckBoxCtrl* check = getChild("notify_all"); + check->set(log->getNotifyNewEvent()); + check->setCommitCallback(boost::bind(&LLPanelExperienceLog::notifyChanged, this)); + + + LLSpinCtrl* spin = getChild("logsizespinner"); + spin->set(log->getMaxDays()); + spin->setCommitCallback(boost::bind(&LLPanelExperienceLog::logSizeChanged, this)); + + mPageSize = log->getPageSize(); + refresh(); + mNewEvent = LLExperienceLog::instance().addUpdateSignal(boost::bind(&LLPanelExperienceLog::refresh, this)); + return TRUE; +} + +LLPanelExperienceLog* LLPanelExperienceLog::create() +{ + return new LLPanelExperienceLog(); +} + +void LLPanelExperienceLog::refresh() +{ + S32 selected = mEventList->getFirstSelectedIndex(); + mEventList->deleteAllItems(); + const LLSD events = LLExperienceLog::instance().getEvents(); + + if(events.size() == 0) + { + mEventList->setCommentText(getString("no_events")); + return; + } + + setAllChildrenEnabled(FALSE); + + LLSD item; + bool waiting = false; + LLUUID waiting_id; + + U32 itemsToSkip = mPageSize*mCurrentPage; + U32 items = 0; + bool moreItems = false; + + if (!events.emptyMap()) + { + for (const auto& day : boost::adaptors::reverse(events.map())) + { + const std::string& date = day.first; + if (LLExperienceLog::instance().isExpired(date)) + { + continue; + } + const LLSD& dayArray = day.second; + U32 size = dayArray.size(); + if(itemsToSkip > size) + { + itemsToSkip -= size; + continue; + } + if(items >= mPageSize && size > 0) + { + moreItems = true; + break; + } + for(int i = dayArray.size() - itemsToSkip - 1; i >= 0; i--) + { + if (items >= mPageSize) + { + moreItems = true; + break; + } + const LLSD event = dayArray[i]; + LLUUID id = event[LLExperienceCache::EXPERIENCE_ID].asUUID(); + const LLSD& experience = LLExperienceCache::instance().get(id); + if(experience.isUndefined()){ + waiting = true; + waiting_id = id; + } + if(!waiting) + { + item["id"] = event; + + LLSD& columns = item["columns"]; + columns[0]["column"] = "time"; + columns[0]["value"] = day.first+event["Time"].asString(); + columns[1]["column"] = "event"; + columns[1]["value"] = LLExperienceLog::getPermissionString(event, "ExperiencePermissionShort"); + columns[2]["column"] = "experience_name"; + columns[2]["value"] = experience[LLExperienceCache::NAME].asString(); + columns[3]["column"] = "object_name"; + columns[3]["value"] = event["ObjectName"].asString(); + mEventList->addElement(item); + } + ++items; + } + } + } + if (waiting) + { + mEventList->deleteAllItems(); + mEventList->setCommentText(getString("loading")); + LLExperienceCache::instance().get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); + } + else + { + setAllChildrenEnabled(TRUE); + + mEventList->setEnabled(TRUE); + getChild("btn_next")->setEnabled(moreItems); + getChild("btn_prev")->setEnabled(mCurrentPage>0); + getChild("btn_clear")->setEnabled(mEventList->getItemCount()>0); + if (selected < 0) + { + selected = 0; + } + mEventList->selectNthItem(selected); + onSelectionChanged(); + } +} + +void LLPanelExperienceLog::onProfileExperience() +{ + LLSD event = getSelectedEvent(); + if (event.isDefined()) + { + LLFloaterExperienceProfile::showInstance(event[LLExperienceCache::EXPERIENCE_ID].asUUID()); + } +} + +void LLPanelExperienceLog::onReportExperience() +{ + LLSD event = getSelectedEvent(); + if (event.isDefined()) + { + LLFloaterReporter::showFromExperience(event[LLExperienceCache::EXPERIENCE_ID].asUUID()); + } +} + +void LLPanelExperienceLog::onNotify() +{ + LLSD event = getSelectedEvent(); + if (event.isDefined()) + { + LLExperienceLog::instance().notify(event); + } +} + +void LLPanelExperienceLog::onNext() +{ + mCurrentPage++; + refresh(); +} + +void LLPanelExperienceLog::onPrev() +{ + if(mCurrentPage>0) + { + mCurrentPage--; + refresh(); + } +} + +void LLPanelExperienceLog::notifyChanged() +{ + LLExperienceLog::instance().setNotifyNewEvent(getChild("notify_all")->get()); +} + +void LLPanelExperienceLog::logSizeChanged() +{ + int value = (int)(getChild("logsizespinner")->get()); + LLExperienceLog::instance().setMaxDays(value); + refresh(); +} + +void LLPanelExperienceLog::onSelectionChanged() +{ + bool enabled = (1 == mEventList->getNumSelected()); + getChild(BTN_REPORT_XP)->setEnabled(enabled); + getChild(BTN_PROFILE_XP)->setEnabled(enabled); + getChild("btn_notify")->setEnabled(enabled); +} + +LLSD LLPanelExperienceLog::getSelectedEvent() +{ + LLScrollListItem* item = mEventList->getFirstSelected(); + if(item) + { + return item->getValue(); + } + return LLSD(); +} diff --git a/indra/newview/llpanelexperiencelog.h b/indra/newview/llpanelexperiencelog.h new file mode 100644 index 0000000000..03e50a6045 --- /dev/null +++ b/indra/newview/llpanelexperiencelog.h @@ -0,0 +1,65 @@ +/** + * @file llpanelexperiencelog.h + * @brief llpanelexperiencelog and related class definitions + * + * $LicenseInfo:firstyear=2014&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, 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_LLPANELEXPERIENCELOG_H +#define LL_LLPANELEXPERIENCELOG_H + +#include "llpanel.h" +class LLScrollListCtrl; + +void* create_xp_log(void* data); +class LLPanelExperienceLog final + : public LLPanel +{ +public: + + LLPanelExperienceLog(bool build = true); + + static LLPanelExperienceLog* create(); + + /*virtual*/ BOOL postBuild(void) override; + + void refresh() override; +protected: + void logSizeChanged(); + void notifyChanged(); + void onNext(); + void onNotify(); + void onPrev(); + void onProfileExperience(); + void onReportExperience(); + void onSelectionChanged(); + + LLSD getSelectedEvent(); +private: + LLScrollListCtrl* mEventList; + U32 mPageSize; + U32 mCurrentPage; + boost::signals2::scoped_connection mNewEvent; +}; + +#endif // LL_LLPANELEXPERIENCELOG_H diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp new file mode 100644 index 0000000000..d27393d255 --- /dev/null +++ b/indra/newview/llpanelexperiencepicker.cpp @@ -0,0 +1,453 @@ +/** +* @file llpanelexperiencepicker.cpp +* @brief Implementation of llpanelexperiencepicker +* @author dolphin@lindenlab.com +* +* $LicenseInfo:firstyear=2014&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2014, 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 "llviewerprecompiledheaders.h" + +#include "llpanelexperiencepicker.h" + + +#include "lllineeditor.h" +#include "llfloaterexperienceprofile.h" +#include "llfloaterexperiences.h" +//#include "llfloaterreg.h" +#include "lluictrlfactory.h" +#include "llscrolllistctrl.h" +#include "llviewerregion.h" +#include "llagent.h" +#include "llexperiencecache.h" +#include "llslurl.h" +#include "llavatarnamecache.h" +#include "llcombobox.h" +#include "llviewercontrol.h" +#include "llfloater.h" +#include "lltrans.h" +#include + +#define BTN_FIND "find" +#define BTN_OK "ok_btn" +#define BTN_CANCEL "cancel_btn" +#define BTN_PROFILE "profile_btn" +#define BTN_LEFT "left_btn" +#define BTN_RIGHT "right_btn" +#define TEXT_EDIT "edit" +#define TEXT_MATURITY "maturity" +#define LIST_RESULTS "search_results" +#define PANEL_SEARCH "search_panel" + +const static std::string columnSpace = " "; + +/* Singu Note: We do not have injectors, so we'll have to call this function instead +static LLPanelInjector t_panel_status("llpanelexperiencepicker"); +*/ + +LLPanelExperiencePicker::LLPanelExperiencePicker() + :LLPanel() +{ + //buildFromFile("panel_experience_search.xml"); + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_experience_search.xml"); // Singu Note: Use filename in xml + setDefaultFilters(); +} + +LLPanelExperiencePicker::~LLPanelExperiencePicker() +{ +} + +BOOL LLPanelExperiencePicker::postBuild() +{ + getChild(TEXT_EDIT)->setKeystrokeCallback(boost::bind(&LLPanelExperiencePicker::editKeystroke, this, _1)); + + childSetAction(BTN_FIND, boost::bind(&LLPanelExperiencePicker::onBtnFind, this)); + getChildView(BTN_FIND)->setEnabled(TRUE); + + LLScrollListCtrl* searchresults = getChild(LIST_RESULTS); + searchresults->setDoubleClickCallback( boost::bind(&LLPanelExperiencePicker::onBtnSelect, this)); + searchresults->setCommitCallback(boost::bind(&LLPanelExperiencePicker::onList, this)); + getChildView(LIST_RESULTS)->setEnabled(FALSE); + getChild(LIST_RESULTS)->setCommentText(getString("no_results")); + + childSetAction(BTN_OK, boost::bind(&LLPanelExperiencePicker::onBtnSelect, this)); + getChildView(BTN_OK)->setEnabled(FALSE); + childSetAction(BTN_CANCEL, boost::bind(&LLPanelExperiencePicker::onBtnClose, this)); + childSetAction(BTN_PROFILE, boost::bind(&LLPanelExperiencePicker::onBtnProfile, this)); + getChildView(BTN_PROFILE)->setEnabled(FALSE); + + getChild(TEXT_MATURITY)->setCurrentByIndex(2); + getChild(TEXT_MATURITY)->setCommitCallback(boost::bind(&LLPanelExperiencePicker::onMaturity, this)); + getChild(TEXT_EDIT)->setFocus(TRUE); + + childSetAction(BTN_LEFT, boost::bind(&LLPanelExperiencePicker::onPage, this, -1)); + childSetAction(BTN_RIGHT, boost::bind(&LLPanelExperiencePicker::onPage, this, 1)); + + LLPanel* search_panel = getChild(PANEL_SEARCH); + if (search_panel) + { + // Start searching when Return is pressed in the line editor. + search_panel->setDefaultBtn(BTN_FIND); + } + return TRUE; +} + +void LLPanelExperiencePicker::editKeystroke(class LLLineEditor* caller) +{ + getChildView(BTN_FIND)->setEnabled(!caller->getText().empty()); +} + +void LLPanelExperiencePicker::onBtnFind() +{ + mCurrentPage=1; + boost::cmatch what; + std::string text = getChild(TEXT_EDIT)->getValue().asString(); + // *TODO: this should be part of LLUrlEntry + static const boost::regex expression("secondlife:///app/experience/[\\da-f-]+/profile"); + if (boost::regex_match(text.c_str(), what, expression)) + { + LLURI uri(text); + LLSD path_array = uri.pathArray(); + if (path_array.size() == 4) + { + std::string exp_id = path_array.get(2).asString(); + LLUUID experience_id(exp_id); + if (!experience_id.isNull()) + { + const LLSD& experience_details = LLExperienceCache::instance().get(experience_id); + if(!experience_details.isUndefined()) + { + std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString(); + if(!experience_name_string.empty()) + { + getChild(TEXT_EDIT)->setValue(experience_name_string); + } + } + else + { + getChild(LIST_RESULTS)->deleteAllItems(); + getChild(LIST_RESULTS)->setCommentText(getString("searching")); + + getChildView(BTN_OK)->setEnabled(FALSE); + getChildView(BTN_PROFILE)->setEnabled(FALSE); + + getChildView(BTN_RIGHT)->setEnabled(FALSE); + getChildView(BTN_LEFT)->setEnabled(FALSE); + LLExperienceCache::instance().get(experience_id, boost::bind(&LLPanelExperiencePicker::onBtnFind, this)); + return; + } + } + } + } + + + find(); +} + +void LLPanelExperiencePicker::onList() +{ + bool enabled = isSelectButtonEnabled(); + getChildView(BTN_OK)->setEnabled(enabled); + + enabled = enabled && getChild(LIST_RESULTS)->getNumSelected() == 1; + getChildView(BTN_PROFILE)->setEnabled(enabled); +} + +void LLPanelExperiencePicker::find() +{ + std::string text = getChild(TEXT_EDIT)->getValue().asString(); + mQueryID.generate(); + + LLExperienceCache::instance().findExperienceByName(text, mCurrentPage, + boost::bind(&LLPanelExperiencePicker::findResults, getDerivedHandle(), mQueryID, _1)); + + getChild(LIST_RESULTS)->deleteAllItems(); + getChild(LIST_RESULTS)->setCommentText(getString("searching")); + + getChildView(BTN_OK)->setEnabled(FALSE); + getChildView(BTN_PROFILE)->setEnabled(FALSE); + + getChildView(BTN_RIGHT)->setEnabled(FALSE); + getChildView(BTN_LEFT)->setEnabled(FALSE); +} + +/*static*/ +void LLPanelExperiencePicker::findResults(LLHandle hparent, LLUUID queryId, LLSD foundResult) +{ + if (hparent.isDead()) + return; + + LLPanelExperiencePicker* panel = hparent.get(); + if (panel) + { + panel->processResponse(queryId, foundResult); + } +} + +bool LLPanelExperiencePicker::isSelectButtonEnabled() +{ + LLScrollListCtrl* list=getChild(LIST_RESULTS); + return list->getFirstSelectedIndex() >=0; +} + +void LLPanelExperiencePicker::getSelectedExperienceIds( const LLScrollListCtrl* results, uuid_vec_t &experience_ids ) +{ + std::vector items = results->getAllSelected(); + for(std::vector::iterator it = items.begin(); it != items.end(); ++it) + { + LLScrollListItem* item = *it; + if (item->getUUID().notNull()) + { + experience_ids.push_back(item->getUUID()); + } + } +} + +void LLPanelExperiencePicker::setAllowMultiple( bool allow_multiple ) +{ + getChild(LIST_RESULTS)->setAllowMultipleSelection(allow_multiple); +} + + +void name_callback(const LLHandle& floater, const LLUUID& experience_id, const LLUUID& agent_id, const LLAvatarName& av_name) +{ + if (floater.isDead()) + return; + LLPanelExperiencePicker* picker = floater.get(); + LLScrollListCtrl* search_results = picker->getChild(LIST_RESULTS); + + LLScrollListItem* item = search_results->getItem(experience_id); + if (!item) + return; + + item->getColumn(2)->setValue(columnSpace+av_name.getNSName()); + +} + +void LLPanelExperiencePicker::processResponse( const LLUUID& query_id, const LLSD& content ) +{ + if (query_id != mQueryID) + { + return; + } + + mResponse = content; + + getChildView(BTN_RIGHT)->setEnabled(content.has("next_page_url")); + getChildView(BTN_LEFT)->setEnabled(content.has("previous_page_url")); + + filterContent(); + +} + +void LLPanelExperiencePicker::onBtnSelect() +{ + if (!isSelectButtonEnabled()) + { + return; + } + + if(mSelectionCallback != nullptr) + { + const LLScrollListCtrl* results = getChild(LIST_RESULTS); + uuid_vec_t experience_ids; + + getSelectedExperienceIds(results, experience_ids); + mSelectionCallback(experience_ids); + getChild(LIST_RESULTS)->deselectAllItems(TRUE); + if (mCloseOnSelect) + { + mCloseOnSelect = FALSE; + onBtnClose(); + } + } + else + { + onBtnProfile(); + } +} + +void LLPanelExperiencePicker::onBtnClose() +{ + LLFloater* floater = mSelectionCallback ? static_cast(getParent()) : LLFloaterExperiences::findInstance(); + if (floater) + { + floater->close(); + } +} + +void LLPanelExperiencePicker::onBtnProfile() +{ + LLScrollListItem* item = getChild(LIST_RESULTS)->getFirstSelected(); + if (item) + { + LLFloaterExperienceProfile::showInstance(item->getUUID()); + } +} + +std::string LLPanelExperiencePicker::getMaturityString(int maturity) +{ + if (maturity <= SIM_ACCESS_PG) + { + return getString("maturity_icon_general"); + } + else if (maturity <= SIM_ACCESS_MATURE) + { + return getString("maturity_icon_moderate"); + } + return getString("maturity_icon_adult"); +} + +void LLPanelExperiencePicker::filterContent() +{ + LLScrollListCtrl* search_results = getChild(LIST_RESULTS); + + const LLSD& experiences=mResponse["experience_keys"]; + + search_results->deleteAllItems(); + + LLSD item; + for (const auto& experience : experiences.array()) + { + if (isExperienceHidden(experience)) + continue; + + std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); + if (experience_name_string.empty()) + { + experience_name_string = LLTrans::getString("ExperienceNameUntitled"); + } + + item["id"]=experience[LLExperienceCache::EXPERIENCE_ID]; + LLSD& columns = item["columns"]; + columns[0]["column"] = "maturity"; + columns[0]["value"] = getMaturityString(experience[LLExperienceCache::MATURITY].asInteger()); + columns[0]["type"]="icon"; + columns[0]["halign"]="right"; + columns[1]["column"] = "experience_name"; + columns[1]["value"] = columnSpace+experience_name_string; + columns[2]["column"] = "owner"; + columns[2]["value"] = columnSpace+getString("loading"); + search_results->addElement(item); + LLAvatarNameCache::get(experience[LLExperienceCache::AGENT_ID], boost::bind(name_callback, getDerivedHandle(), experience[LLExperienceCache::EXPERIENCE_ID], _1, _2)); + } + + if (search_results->isEmpty()) + { + LLStringUtil::format_map_t map; + std::string search_text = getChild(TEXT_EDIT)->getValue().asString(); + map["[TEXT]"] = search_text; + if (search_text.empty()) + { + getChild(LIST_RESULTS)->setCommentText(getString("no_results")); + } + else + { + getChild(LIST_RESULTS)->setCommentText(getString("not_found", map)); + } + search_results->setEnabled(false); + getChildView(BTN_OK)->setEnabled(false); + getChildView(BTN_PROFILE)->setEnabled(false); + } + else + { + getChildView(BTN_OK)->setEnabled(true); + search_results->setEnabled(true); + search_results->sortByColumnIndex(1, TRUE); + std::string text = getChild(TEXT_EDIT)->getValue().asString(); + if (!search_results->selectItemByLabel(text, TRUE)) + { + search_results->selectFirstItem(); + } + onList(); + search_results->setFocus(TRUE); + } +} + +void LLPanelExperiencePicker::onMaturity() +{ + if (mResponse.has("experience_keys") && mResponse["experience_keys"].beginArray() != mResponse["experience_keys"].endArray()) + { + filterContent(); + } +} + +bool LLPanelExperiencePicker::isExperienceHidden( const LLSD& experience) const +{ + bool hide=false; + filter_list::const_iterator it = mFilters.begin(); + for(/**/;it != mFilters.end(); ++it) + { + if ((*it)(experience)){ + return true; + } + } + + return hide; +} + +bool LLPanelExperiencePicker::FilterOverRating( const LLSD& experience ) +{ + int maturity = getChild(TEXT_MATURITY)->getSelectedValue().asInteger(); + return experience[LLExperienceCache::MATURITY].asInteger() > maturity; +} + +bool LLPanelExperiencePicker::FilterWithProperty( const LLSD& experience, S32 prop) +{ + return (experience[LLExperienceCache::PROPERTIES].asInteger() & prop) != 0; +} + +bool LLPanelExperiencePicker::FilterWithoutProperties( const LLSD& experience, S32 prop) +{ + return ((experience[LLExperienceCache::PROPERTIES].asInteger() & prop) == prop); +} + +bool LLPanelExperiencePicker::FilterWithoutProperty( const LLSD& experience, S32 prop ) +{ + return (experience[LLExperienceCache::PROPERTIES].asInteger() & prop) == 0; +} + +void LLPanelExperiencePicker::setDefaultFilters() +{ + mFilters.clear(); + addFilter(boost::bind(&LLPanelExperiencePicker::FilterOverRating, this, _1)); +} + +bool LLPanelExperiencePicker::FilterMatching( const LLSD& experience, const LLUUID& id ) +{ + if (experience.isUUID()) + { + return experience.asUUID() == id; + } + return experience[LLExperienceCache::EXPERIENCE_ID].asUUID() == id; +} + +void LLPanelExperiencePicker::onPage( S32 direction ) +{ + mCurrentPage += direction; + if (mCurrentPage < 1) + { + mCurrentPage = 1; + } + find(); +} + diff --git a/indra/newview/llpanelexperiencepicker.h b/indra/newview/llpanelexperiencepicker.h new file mode 100644 index 0000000000..1af7fe108b --- /dev/null +++ b/indra/newview/llpanelexperiencepicker.h @@ -0,0 +1,95 @@ +/** +* @file llpanelexperiencepicker.h +* @brief Header file for llpanelexperiencepicker +* @author dolphin@lindenlab.com +* +* $LicenseInfo:firstyear=2014&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2014, 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_LLPANELEXPERIENCEPICKER_H +#define LL_LLPANELEXPERIENCEPICKER_H + +#include "llpanel.h" + +class LLScrollListCtrl; +class LLLineEditor; + +class LLPanelExperiencePicker final : public LLPanel +{ +public: + friend class LLExperienceSearchResponder; + friend class LLFloaterExperiencePicker; + + typedef std::function select_callback_t; + // filter function for experiences, return true if the experience should be hidden. + typedef std::function filter_function; + typedef std::vector filter_list; + + LLPanelExperiencePicker(); + virtual ~LLPanelExperiencePicker(); + + BOOL postBuild() override; + + void addFilter(filter_function func){mFilters.push_back(func);} + template + void addFilters(IT begin, IT end){mFilters.insert(mFilters.end(), begin, end);} + void setDefaultFilters(); + + static bool FilterWithProperty(const LLSD& experience, S32 prop); + static bool FilterWithoutProperties(const LLSD& experience, S32 prop); + static bool FilterWithoutProperty(const LLSD& experience, S32 prop); + static bool FilterMatching(const LLSD& experience, const LLUUID& id); + bool FilterOverRating(const LLSD& experience); + +private: + void editKeystroke(LLLineEditor* caller); + + void onBtnFind(); + void onBtnSelect(); + void onBtnClose(); + void onBtnProfile(); + void onList(); + void onMaturity(); + void onPage(S32 direction); + + void getSelectedExperienceIds( const LLScrollListCtrl* results, uuid_vec_t &experience_ids ); + void setAllowMultiple(bool allow_multiple); + + void find(); + static void findResults(LLHandle hparent, LLUUID queryId, LLSD foundResult); + + bool isSelectButtonEnabled(); + void processResponse( const LLUUID& query_id, const LLSD& content ); + + void filterContent(); + bool isExperienceHidden(const LLSD& experience) const ; + std::string getMaturityString(int maturity); + + + select_callback_t mSelectionCallback; + filter_list mFilters; + LLUUID mQueryID; + LLSD mResponse; + bool mCloseOnSelect; + S32 mCurrentPage; +}; + +#endif // LL_LLPANELEXPERIENCEPICKER_H diff --git a/indra/newview/llpanelexperiences.cpp b/indra/newview/llpanelexperiences.cpp new file mode 100644 index 0000000000..97473a006b --- /dev/null +++ b/indra/newview/llpanelexperiences.cpp @@ -0,0 +1,152 @@ +/** + * @file llpanelexperiences.cpp + * @brief LLPanelExperiences class implementation + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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 "llviewerprecompiledheaders.h" + + +#include "lluictrlfactory.h" +#include "llexperiencecache.h" +#include "llagent.h" + +#include "llfloaterexperienceprofile.h" +#include "llpanelexperiences.h" +#include "lllayoutstack.h" +#include "llnamelistctrl.h" + +//static LLPanelInjector register_experiences_panel("experiences_panel"); + +LLPanelExperiences::LLPanelExperiences() + : mExperiencesList(nullptr) +{ + //buildFromFile("panel_experiences.xml"); + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_experiences.xml"); +} + +BOOL LLPanelExperiences::postBuild( void ) +{ + mExperiencesList = getChild("experiences_list"); + if (hasString("loading_experiences")) + { + mExperiencesList->setCommentText(getString("loading_experiences")); + } + else if (hasString("no_experiences")) + { + mExperiencesList->setCommentText(getString("no_experiences")); + } + + return TRUE; +} + +void addExperienceToList(const LLSD& experience, LLNameListCtrl* list) +{ + // Don't add missing experiences, that seems wrong + if (experience.has(LLExperienceCache::MISSING) && experience[LLExperienceCache::MISSING].asBoolean()) + return; + + const auto& id = experience[LLExperienceCache::EXPERIENCE_ID]; + list->removeNameItem(id); // Don't add the same item twice, this can happen + auto item = LLNameListCtrl::NameItem() + .name(experience[LLExperienceCache::NAME].asString()) + .target(LLNameListItem::EXPERIENCE); + item.value(id) + .columns.add(LLScrollListCell::Params()); // Dummy column for names + list->addNameItemRow(item); +} + +void LLPanelExperiences::setExperienceList( const LLSD& experiences ) +{ + mExperiencesList->setSortEnabled(false); + + if (hasString("no_experiences")) + { + mExperiencesList->setCommentText(getString("no_experiences")); + } + mExperiencesList->clear(); + + auto& cache = LLExperienceCache::instance(); + for(const auto& exp : experiences.array()) + { + LLUUID public_key = exp.asUUID(); + if (public_key.notNull()) + cache.get(public_key, boost::bind(addExperienceToList, _1, mExperiencesList)); + } + + mExperiencesList->setSortEnabled(true); +} + +void LLPanelExperiences::getExperienceIdsList(uuid_vec_t& result) +{ + result = mExperiencesList->getAllIDs(); +} + +LLPanelExperiences* LLPanelExperiences::create(const std::string& name) +{ + LLPanelExperiences* panel= new LLPanelExperiences(); + panel->setName(name); + return panel; +} + +void LLPanelExperiences::removeExperiences( const LLSD& ids ) +{ + for (const auto& id : ids.array()) + { + removeExperience(id.asUUID()); + } +} + +void LLPanelExperiences::removeExperience( const LLUUID& id ) +{ + mExperiencesList->removeNameItem(id); +} + +void LLPanelExperiences::addExperience( const LLUUID& id ) +{ + if (!mExperiencesList->getItem(id)) + { + LLExperienceCache::instance().get(id, boost::bind(addExperienceToList, _1, mExperiencesList)); + } +} + +void LLPanelExperiences::setButtonAction(const std::string& label, const commit_signal_t::slot_type& cb ) +{ + if(label.empty()) + { + getChild("button_panel")->setVisible(false); + } + else + { + getChild("button_panel")->setVisible(true); + LLButton* child = getChild("btn_action"); + child->setCommitCallback(cb); + child->setLabel(getString(label)); + } +} + +void LLPanelExperiences::enableButton( bool enable ) +{ + getChild("btn_action")->setEnabled(enable); +} diff --git a/indra/newview/llpanelexperiences.h b/indra/newview/llpanelexperiences.h new file mode 100644 index 0000000000..31e9d1a002 --- /dev/null +++ b/indra/newview/llpanelexperiences.h @@ -0,0 +1,54 @@ +/** + * @file llpanelexperiences.h + * @brief LLPanelExperiences class definition + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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_LLPANELEXPERIENCES_H +#define LL_LLPANELEXPERIENCES_H + +#include "llpanel.h" + +class LLPanelExperiences final + : public LLPanel +{ +public: + LLPanelExperiences(); + + static LLPanelExperiences* create(const std::string& name); + + /*virtual*/ BOOL postBuild(void) override; + + void setExperienceList(const LLSD& experiences); + void getExperienceIdsList(uuid_vec_t& result); + + void removeExperiences( const LLSD& ids ); + void removeExperience( const LLUUID& id); + void addExperience( const LLUUID& id); + void setButtonAction(const std::string& label, const commit_signal_t::slot_type& cb); + void enableButton(bool enable); + +private: + class LLNameListCtrl* mExperiencesList; +}; +#endif // LL_LLPANELEXPERIENCES_H diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index f957414f19..8c6f103367 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1866,6 +1866,8 @@ void LLPanelFace::onCancelNormalTexture(const LLSD& data) U8 bumpy = 0; bool identical_bumpy = false; LLSelectedTE::getBumpmap(bumpy, identical_bumpy); + LLUUID norm_map_id = mBumpyTextureCtrl->getImageAssetID(); + bumpy = norm_map_id.isNull() ? bumpy : BUMPY_TEXTURE; sendBump(bumpy); } @@ -2162,6 +2164,15 @@ void LLPanelFace::LLSelectedTE::getTexId(LLUUID& id, bool& identical) { LLUUID get(LLViewerObject* object, S32 te_index) { + LLTextureEntry *te = object->getTE(te_index); + if (te) + { + if ((te->getID() == IMG_USE_BAKED_EYES) || (te->getID() == IMG_USE_BAKED_HAIR) || (te->getID() == IMG_USE_BAKED_HEAD) || (te->getID() == IMG_USE_BAKED_LOWER) || (te->getID() == IMG_USE_BAKED_SKIRT) || (te->getID() == IMG_USE_BAKED_UPPER) + || (te->getID() == IMG_USE_BAKED_LEFTARM) || (te->getID() == IMG_USE_BAKED_LEFTLEG) || (te->getID() == IMG_USE_BAKED_AUX1) || (te->getID() == IMG_USE_BAKED_AUX2) || (te->getID() == IMG_USE_BAKED_AUX3)) + { + return te->getID(); + } + } LLUUID id; LLViewerTexture* image = object->getTEImage(te_index); if (image) @@ -2171,10 +2182,9 @@ void LLPanelFace::LLSelectedTE::getTexId(LLUUID& id, bool& identical) if (!id.isNull() && LLViewerMedia::textureHasMedia(id)) { - LLTextureEntry *te = object->getTE(te_index); if (te) { - LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL; + LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_STANDARD) : NULL; if(!tex) { tex = LLViewerFetchedTexture::sDefaultImagep; diff --git a/indra/newview/llpanelgeneral.cpp b/indra/newview/llpanelgeneral.cpp index d794e43da5..30a0e64301 100644 --- a/indra/newview/llpanelgeneral.cpp +++ b/indra/newview/llpanelgeneral.cpp @@ -87,7 +87,7 @@ BOOL LLPanelGeneral::postBuild() childSetValue("ui_auto_scale", gSavedSettings.getBOOL("UIAutoScale")); LLComboBox* crash_behavior_combobox = getChild("crash_behavior_combobox"); - crash_behavior_combobox->setCurrentByIndex(gSavedSettings.getS32(CRASH_BEHAVIOR_SETTING)); + crash_behavior_combobox->setValue(gSavedSettings.getS32("CrashSubmitBehavior")); childSetValue("language_combobox", gSavedSettings.getString("Language")); @@ -163,7 +163,7 @@ void LLPanelGeneral::apply() gSavedSettings.setString("Language", childGetValue("language_combobox")); LLComboBox* crash_behavior_combobox = getChild("crash_behavior_combobox"); - gSavedSettings.setS32(CRASH_BEHAVIOR_SETTING, crash_behavior_combobox->getCurrentIndex()); + gSavedSettings.setS32("CrashSubmitBehavior", crash_behavior_combobox->getValue()); } void LLPanelGeneral::cancel() diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index 4e65628bbf..56e61a5597 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -34,6 +34,7 @@ #include "llpanelgroup.h" // Library includes +#include "lfidbearer.h" #include "llbutton.h" #include "lltabcontainer.h" #include "lltextbox.h" @@ -53,6 +54,9 @@ #include "llpanelgrouproles.h" #include "llpanelgroupvoting.h" #include "llpanelgrouplandmoney.h" +#include "llpanelgroupexperiences.h" + +#include "hippogridmanager.h" // static void* LLPanelGroupTab::createTab(void* data) @@ -129,7 +133,7 @@ void LLPanelGroupTab::handleClickHelp() } } -void copy_profile_uri(const LLUUID& id, bool group); +void copy_profile_uri(const LLUUID& id, const LFIDBearer::Type& type); LLPanelGroup::LLPanelGroup(const LLUUID& group_id) : LLPanel("PanelGroup", LLRect(), FALSE), @@ -153,6 +157,8 @@ LLPanelGroup::LLPanelGroup(const LLUUID& group_id) &mID); mFactoryMap["land_money_tab"]= LLCallbackMap(LLPanelGroupLandMoney::createTab, &mID); + mFactoryMap["experiences_tab"] = LLCallbackMap(LLPanelGroupExperiences::createTab, + &mID); // Roles sub tabs mFactoryMap["members_sub_tab"] = LLCallbackMap(LLPanelGroupMembersSubTab::createTab, &mID); mFactoryMap["roles_sub_tab"] = LLCallbackMap(LLPanelGroupRolesSubTab::createTab, &mID); @@ -161,7 +167,7 @@ LLPanelGroup::LLPanelGroup(const LLUUID& group_id) LLGroupMgr::getInstance()->addObserver(this); - mCommitCallbackRegistrar.add("Group.CopyURI", boost::bind(copy_profile_uri, boost::ref(mID), true)); + mCommitCallbackRegistrar.add("Group.CopyURI", boost::bind(copy_profile_uri, boost::ref(mID), LFIDBearer::GROUP)); // Pass on construction of this panel to the control factory. LLUICtrlFactory::getInstance()->buildPanel(this, "panel_group.xml", &getFactoryMap()); } @@ -208,6 +214,14 @@ BOOL LLPanelGroup::postBuild() if (mTabContainer) { + // Group Voting no longer exists on SecondLife, hide it + if (gHippoGridManager->getConnectedGrid()->isSecondLife()) + { + auto panel = mTabContainer->getPanelByName("voting_tab"); + mTabContainer->removeTabPanel(panel); + delete panel; + } + //our initial tab selection was invalid, just select the //first tab then or default to selecting the initial //selected tab specified in the layout file diff --git a/indra/newview/llpanelgroupbulkban.cpp b/indra/newview/llpanelgroupbulkban.cpp index 5915d355fb..aa7f55196a 100644 --- a/indra/newview/llpanelgroupbulkban.cpp +++ b/indra/newview/llpanelgroupbulkban.cpp @@ -49,8 +49,6 @@ #include "lluictrlfactory.h" #include "llviewerwindow.h" -#include - LLPanelGroupBulkBan::LLPanelGroupBulkBan(const LLUUID& group_id) : LLPanelGroupBulk(group_id) { // Pass on construction of this panel to the control factory. @@ -131,7 +129,7 @@ void LLPanelGroupBulkBan::submit() (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); return; } - std::vector banned_agent_list; + uuid_vec_t banned_agent_list; std::vector agents = mImplementation->mBulkAgentList->getAllData(); std::vector::iterator iter = agents.begin(); for(;iter != agents.end(); ++iter) @@ -155,7 +153,7 @@ void LLPanelGroupBulkBan::submit() std::vector banned_avatar_names; std::vector out_of_limit_names; bool banning_self = FALSE; - std::vector::iterator conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), gAgent.getID()); + auto conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), gAgent.getID()); if (conflict != banned_agent_list.end()) { banned_agent_list.erase(conflict); @@ -163,10 +161,10 @@ void LLPanelGroupBulkBan::submit() } if (group_datap) { - BOOST_FOREACH(const LLGroupMgrGroupData::ban_list_t::value_type& group_ban_pair, group_datap->mBanList) + for (const LLGroupMgrGroupData::ban_list_t::value_type& group_ban_pair : group_datap->mBanList) { const LLUUID& group_ban_agent_id = group_ban_pair.first; - std::vector::iterator conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), group_ban_agent_id); + auto conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), group_ban_agent_id); if (conflict != banned_agent_list.end()) { LLAvatarName av_name; @@ -184,8 +182,8 @@ void LLPanelGroupBulkBan::submit() // Otherwise we have a possibility of cutting more then we need to. if (banned_agent_list.size() > GB_MAX_BANNED_AGENTS - group_datap->mBanList.size()) { - std::vector::iterator exeedes_limit = banned_agent_list.begin() + GB_MAX_BANNED_AGENTS - group_datap->mBanList.size(); - for (std::vector::iterator itor = exeedes_limit ; + auto exeedes_limit = banned_agent_list.begin() + GB_MAX_BANNED_AGENTS - group_datap->mBanList.size(); + for (auto itor = exeedes_limit ; itor != banned_agent_list.end(); ++itor) { LLAvatarName av_name; diff --git a/indra/newview/llpanelgroupbulkimpl.h b/indra/newview/llpanelgroupbulkimpl.h index 235eeb8f9b..ec2e06b477 100644 --- a/indra/newview/llpanelgroupbulkimpl.h +++ b/indra/newview/llpanelgroupbulkimpl.h @@ -78,7 +78,7 @@ class LLPanelGroupBulkImpl std::string mBanLimitFail; std::string mCannotBanYourself; - std::set mInviteeIDs; + uuid_set_t mInviteeIDs; void (*mCloseCallback)(void* data); void* mCloseCallbackUserData; diff --git a/indra/newview/llpanelgroupexperiences.cpp b/indra/newview/llpanelgroupexperiences.cpp new file mode 100644 index 0000000000..76553b4334 --- /dev/null +++ b/indra/newview/llpanelgroupexperiences.cpp @@ -0,0 +1,130 @@ +/** + * @file llpanelgroupexperiences.cpp + * @brief List of experiences owned by a group. + * + * $LicenseInfo:firstyear=2006&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 "llviewerprecompiledheaders.h" + +#include "llpanelgroupexperiences.h" + +#include "lluictrlfactory.h" +#include "llappviewer.h" +#include "llexperiencecache.h" +#include "llnamelistctrl.h" + +void addExperienceToList(const LLSD& experience, LLNameListCtrl* list); + +//static LLPanelInjector t_panel_group_experiences("panel_group_experiences"); +//static +void* LLPanelGroupExperiences::createTab(void* data) +{ + LLUUID* group_id = static_cast(data); + return new LLPanelGroupExperiences("panel group experiences", *group_id); +} + + +LLPanelGroupExperiences::LLPanelGroupExperiences(const std::string& name, const LLUUID& id) +: LLPanelGroupTab(name, id), mExperiencesList(nullptr) +{ +} + +LLPanelGroupExperiences::~LLPanelGroupExperiences() +{ +} + +BOOL LLPanelGroupExperiences::isVisibleByAgent(LLAgent* agentp) +{ + //default to being visible + return TRUE; +} + +BOOL LLPanelGroupExperiences::postBuild() +{ + mExperiencesList = getChild("experiences_list"); + if (hasString("loading_experiences")) + { + mExperiencesList->setCommentText(getString("loading_experiences")); + } + else if (hasString("no_experiences")) + { + mExperiencesList->setCommentText(getString("no_experiences")); + } + + return LLPanelGroupTab::postBuild(); +} + +void LLPanelGroupExperiences::activate() +{ + if ((getGroupID() == LLUUID::null) || gDisconnected) + { + return; + } + + LLExperienceCache::instance().getGroupExperiences(getGroupID(), + boost::bind(&LLPanelGroupExperiences::groupExperiencesResults, getDerivedHandle(), _1)); +} + +void LLPanelGroupExperiences::setGroupID(const LLUUID& id) +{ + LLPanelGroupTab::setGroupID(id); + + if (id == LLUUID::null) + { + return; + } + + activate(); +} + +void LLPanelGroupExperiences::setExperienceList(const LLSD& experiences) +{ + if (hasString("no_experiences")) + { + mExperiencesList->setCommentText(getString("no_experiences")); + } + mExperiencesList->clear(); + + auto& cache = LLExperienceCache::instance(); + for (const auto& exp : experiences.array()) + { + LLUUID public_key = exp.asUUID(); + if (public_key.notNull()) + cache.get(public_key, boost::bind(addExperienceToList, _1, mExperiencesList)); + } +} + +/*static*/ +void LLPanelGroupExperiences::groupExperiencesResults(LLHandle handle, const LLSD &experiences) +{ + if (handle.isDead()) + { + return; + } + + LLPanelGroupExperiences* panel = handle.get(); + if (panel) + { + panel->setExperienceList(experiences); + } +} diff --git a/indra/newview/llpanelgroupexperiences.h b/indra/newview/llpanelgroupexperiences.h new file mode 100644 index 0000000000..e16cd98adb --- /dev/null +++ b/indra/newview/llpanelgroupexperiences.h @@ -0,0 +1,56 @@ +/** + * @file llpanelgroupexperiences.h + * @brief List of experiences owned by a group. + * + * $LicenseInfo:firstyear=2006&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_LLPANELGROUPEXPERIENCES_H +#define LL_LLPANELGROUPEXPERIENCES_H + +#include "llpanelgroup.h" + +class LLPanelGroupExperiences final : public LLPanelGroupTab +{ +public: + static void* createTab(void* data); + LLPanelGroupExperiences(const std::string& name, const LLUUID& id); + virtual ~LLPanelGroupExperiences(); + + // LLPanelGroupTab + void activate() override; + BOOL isVisibleByAgent(LLAgent* agentp) override; + + BOOL postBuild() override; + + void setGroupID(const LLUUID& id) override; + + void setExperienceList(const LLSD& experiences); + +protected: + class LLNameListCtrl* mExperiencesList; + +private: + static void groupExperiencesResults(LLHandle, const LLSD &); +}; + +#endif diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 94047f771b..54a73ccc02 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -35,6 +35,7 @@ #include "llpanelgroupgeneral.h" #include "llagent.h" +#include "llagentbenefits.h" #include "lluictrlfactory.h" #include "roles_constants.h" @@ -43,7 +44,6 @@ #include "llcheckboxctrl.h" #include "llcombobox.h" #include "lldbstrings.h" -#include "llavataractions.h" #include "llgroupactions.h" #include "llimview.h" #include "lllineeditor.h" @@ -60,7 +60,6 @@ #include "llviewerwindow.h" #include "hippogridmanager.h" -#include // consts const S32 MATURE_CONTENT = 1; @@ -84,7 +83,6 @@ LLPanelGroupGeneral::LLPanelGroupGeneral(const std::string& name, mGroupNameEditor(NULL), mFounderName(NULL), mInsignia(NULL), - mGroupName(NULL), mEditCharter(NULL), mBtnJoinGroup(NULL), mListVisibleMembers(NULL), @@ -122,15 +120,17 @@ BOOL LLPanelGroupGeneral::postBuild() // General info mGroupNameEditor = getChild("group_name_editor", recurse); - mGroupName = getChild("group_name", recurse); - + mInsignia = getChild("insignia", recurse); if (mInsignia) { mInsignia->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitAny,this)); mDefaultIconID = mInsignia->getImageAssetID(); void show_picture(const LLUUID& id, const std::string& name); - getChild("bigimg")->setCommitCallback(boost::bind(boost::bind(show_picture, boost::bind(&LLTextureCtrl::getImageAssetID, mInsignia), "Group Insignia"))); + auto show_pic = [this] { show_picture(mInsignia->getImageAssetID(), "Group Insignia"); }; + auto show_pic_if_not_self = [=] { if (!mInsignia->canChange()) show_pic(); }; + mInsignia->setMouseUpCallback(std::bind(show_pic_if_not_self)); + getChild("bigimg")->setCommitCallback(std::bind(show_pic)); } mEditCharter = getChild("charter", recurse); @@ -156,10 +156,6 @@ BOOL LLPanelGroupGeneral::postBuild() mFounderName = getChild("founder_name"); mListVisibleMembers = getChild("visible_members", recurse); - if (mListVisibleMembers) - { - mListVisibleMembers->setDoubleClickCallback(boost::bind(LLAvatarActions::showProfile, boost::bind(&LLScrollListCtrl::getCurrentID, mListVisibleMembers), false)); - } // Options mCtrlShowInGroupList = getChild("show_in_group_list", recurse); @@ -186,10 +182,11 @@ BOOL LLPanelGroupGeneral::postBuild() mCtrlOpenEnrollment->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitAny,this)); } + auto& grid = *gHippoGridManager->getConnectedGrid(); mCtrlEnrollmentFee = getChild("check_enrollment_fee", recurse); if (mCtrlEnrollmentFee) { - mCtrlEnrollmentFee->setLabelArg("[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); + mCtrlEnrollmentFee->setLabelArg("[CURRENCY]", grid.getCurrencySymbol()); mCtrlEnrollmentFee->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitEnrollment,this)); } @@ -246,7 +243,7 @@ BOOL LLPanelGroupGeneral::postBuild() } LLStringUtil::format_map_t args; - args["[GROUPCREATEFEE]"] = gHippoGridManager->getConnectedGrid()->getGroupCreationFee(); + args["[GROUPCREATEFEE]"] = grid.formatFee(LLAgentBenefitsMgr::current().getCreateGroupCost()); mIncompleteMemberDataStr = getString("incomplete_member_data_str"); mConfirmGroupCreateStr = getString("confirm_group_create_str", args); @@ -265,12 +262,12 @@ BOOL LLPanelGroupGeneral::postBuild() mBtnJoinGroup->setVisible(FALSE); mBtnInfo->setVisible(FALSE); - mGroupName->setVisible(FALSE); + getChildView("group_name")->setVisible(FALSE); } std::string member_count(LLTrans::getString("LoadingData")); if (LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID)) - member_count = boost::lexical_cast(gdatap->mMembers.size()); + member_count = fmt::to_string(gdatap->mMembers.size()); getChild("text_owners_and_visible_members")->setTextArg("[COUNT]", member_count); return LLPanelGroupTab::postBuild(); @@ -733,15 +730,14 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) if (mInsignia) mInsignia->setEnabled(can_change_ident); if (mEditCharter) mEditCharter->setEnabled(can_change_ident); - - if (mGroupName) mGroupName->setText(gdatap->mName); + + getChildView("group_name")->setValue(mGroupID); if (mGroupNameEditor) mGroupNameEditor->setVisible(FALSE); - if (mFounderName) mFounderName->setNameID(gdatap->mFounderID,FALSE); + if (mFounderName) mFounderName->setValue(gdatap->mFounderID); - LLNameEditor* key_edit = getChild("group_key"); - if(key_edit) + if (auto key_edit = getChildView("group_key")) { - key_edit->setText(gdatap->getID().asString()); + key_edit->setValue(gdatap->getID().asString()); } if (mInsignia) @@ -758,7 +754,7 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) if (mEditCharter) { - mEditCharter->setText(gdatap->mCharter); + mEditCharter->setText(gdatap->mCharter, false); mEditCharter->resetDirty(); } } @@ -839,7 +835,7 @@ void LLPanelGroupGeneral::updateMembers() } } - getChild("text_owners_and_visible_members")->setTextArg("[COUNT]", boost::lexical_cast(gdatap->mMembers.size())); + getChild("text_owners_and_visible_members")->setTextArg("[COUNT]", fmt::to_string(gdatap->mMembers.size())); if (mMemberProgress == gdatap->mMembers.end()) { @@ -910,7 +906,6 @@ void LLPanelGroupGeneral::updateChanged() LLUICtrl *check_list[] = { mGroupNameEditor, - mGroupName, mFounderName, mInsignia, mEditCharter, diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h index a0a1fd5fb8..aa54e83b74 100644 --- a/indra/newview/llpanelgroupgeneral.h +++ b/indra/newview/llpanelgroupgeneral.h @@ -91,7 +91,6 @@ class LLPanelGroupGeneral : public LLPanelGroupTab // Group information (include any updates in updateChanged) LLLineEditor *mGroupNameEditor; - LLTextBox *mGroupName; LLNameBox *mFounderName; LLTextureCtrl *mInsignia; LLTextEditor *mEditCharter; diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index 70037243d5..ac779221be 100644 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -195,7 +195,7 @@ class LLPanelGroupLandMoney::impl void requestGroupLandInfo(); - int getStoredContribution(); + S32 getStoredContribution(); void setYourContributionTextField(int contrib); void setYourMaxContributionTextBox(int max); @@ -341,20 +341,20 @@ bool LLPanelGroupLandMoney::impl::applyContribution() // Retrieves the land contribution for this agent that is currently // stored in the database, NOT what is currently entered in the text field -int LLPanelGroupLandMoney::impl::getStoredContribution() +S32 LLPanelGroupLandMoney::impl::getStoredContribution() { LLGroupData group_data; group_data.mContribution = 0; - gAgent.getGroupData(mPanel.mGroupID, group_data); + bool found_group = gAgent.getGroupData(mPanel.mGroupID, group_data); - return group_data.mContribution; + return found_group ? group_data.mContribution : 0; } // Fills in the text field with the contribution, contrib void LLPanelGroupLandMoney::impl::setYourContributionTextField(int contrib) { - std::string buffer = llformat("%d", contrib); + std::string buffer = fmt::to_string(contrib); if ( mYourContributionEditorp ) { @@ -364,7 +364,7 @@ void LLPanelGroupLandMoney::impl::setYourContributionTextField(int contrib) void LLPanelGroupLandMoney::impl::setYourMaxContributionTextBox(int max) { - mPanel.getChild("your_contribution_max_value")->setTextArg("[AMOUNT]", llformat("%d", max)); + mPanel.getChild("your_contribution_max_value")->setTextArg("[AMOUNT]", fmt::to_string(max)); } //static diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 0498e7e49a..862a89dd4c 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -529,12 +529,7 @@ void LLPanelGroupNotices::showNotice(const std::string& subject, arrangeNoticeView(VIEW_PAST_NOTICE); if(mViewSubject) mViewSubject->setText(subject); - if (mViewMessage) { - // We need to prune the highlights, and clear() is not doing it... - mViewMessage->removeTextFromEnd(mViewMessage->getMaxLength()); - // Now we append the new text (setText() won't highlight URLs) - mViewMessage->appendColoredText(message, false, false, mViewMessage->getReadOnlyFgColor()); - } + if (mViewMessage) mViewMessage->setText(message, false); if (mInventoryOffer) { diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 6a172cdb31..38fef06e43 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -34,7 +34,6 @@ #include "llcheckboxctrl.h" #include "llagent.h" -#include "llavataractions.h" #include "llavatarnamecache.h" #include "llbutton.h" #include "llfiltereditor.h" @@ -860,8 +859,6 @@ BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root) // We want to be notified whenever a member is selected. mMembersList->setCommitOnSelectionChange(TRUE); mMembersList->setCommitCallback(boost::bind(&LLPanelGroupMembersSubTab::onMemberSelect,_1,this)); - // Show the member's profile on double click. - mMembersList->setDoubleClickCallback(boost::bind(&LLPanelGroupMembersSubTab::onMemberDoubleClick,this)); LLButton* button = parent->getChild("member_invite", recurse); if ( button ) @@ -1150,13 +1147,6 @@ void LLPanelGroupMembersSubTab::handleMemberSelect() mEjectBtn->setEnabled(can_eject_members); } -// static -void LLPanelGroupMembersSubTab::onMemberDoubleClick(void* user_data) -{ - LLPanelGroupMembersSubTab* self = static_cast(user_data); - self->handleMemberDoubleClick(); -} - //static void LLPanelGroupMembersSubTab::onInviteMember(void *userdata) { @@ -1334,15 +1324,6 @@ void LLPanelGroupMembersSubTab::onRoleCheck(LLUICtrl* ctrl, void* user_data) } } -void LLPanelGroupMembersSubTab::handleMemberDoubleClick() -{ - LLScrollListItem* selected = mMembersList->getFirstSelected(); - if (selected) - { - LLAvatarActions::showProfile(selected->getUUID()); - } -} - void LLPanelGroupMembersSubTab::activate() { LLPanelGroupSubTab::activate(); diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index aaf60c7a6a..c6fb9871f6 100644 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -175,9 +175,6 @@ class LLPanelGroupMembersSubTab : public LLPanelGroupSubTab static void onMemberSelect(LLUICtrl*, void*); void handleMemberSelect(); - static void onMemberDoubleClick(void*); - void handleMemberDoubleClick(); - static void onInviteMember(void*); void handleInviteMember(); diff --git a/indra/newview/llpanelgroupvoting.cpp b/indra/newview/llpanelgroupvoting.cpp index 09a28efeaf..b58f15721a 100644 --- a/indra/newview/llpanelgroupvoting.cpp +++ b/indra/newview/llpanelgroupvoting.cpp @@ -307,7 +307,7 @@ void LLPanelGroupVoting::impl::setEnableVoteProposal() if ( proposal_cell ) { //proposal text - mProposalText->setText(proposal_cell->getValue().asString()); + mProposalText->setText(proposal_cell->getValue().asString(), false); } else { // Something's wrong... should have some text @@ -556,7 +556,7 @@ void LLPanelGroupVoting::impl::setEnableHistoryItem() const LLScrollListCell *cell = item->getColumn(5); if (cell) { - mVoteHistoryText->setText(cell->getValue().asString()); + mVoteHistoryText->setText(cell->getValue().asString(), false); } else { // Something's wrong... diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index b346aa922a..3c7abe1742 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -42,7 +42,6 @@ #include "llfontgl.h" #include "llmd5.h" #include "llsecondlifeurls.h" -#include "sgversion.h" #include "v4color.h" #include "llappviewer.h" @@ -62,6 +61,7 @@ #include "llui.h" #include "lluiconstants.h" #include "llurlhistory.h" // OGPX : regionuri text box has a history of region uris (if FN/LN are loaded at startup) +#include "llversioninfo.h" #include "llviewertexturelist.h" #include "llviewermenu.h" // for handle_preferences() #include "llviewernetwork.h" @@ -83,9 +83,10 @@ // #include "llspinctrl.h" #include "llviewermessage.h" -#include // #include + +#include "llsdserialize.h" #include "llstring.h" #include @@ -103,7 +104,7 @@ static bool nameSplit(const std::string& full, std::string& first, std::string& return false; first = fragments[0]; last = (fragments.size() == 1) ? - gHippoGridManager->getCurrentGrid()->isAurora() ? "" : "Resident" : + gHippoGridManager->getCurrentGrid()->isWhiteCore() ? LLStringUtil::null : "Resident" : fragments[1]; return (fragments.size() <= 2); } @@ -113,9 +114,9 @@ static std::string nameJoin(const std::string& first,const std::string& last, bo if (last.empty() || (strip_resident && boost::algorithm::iequals(last, "Resident"))) return first; else if (std::islower(last[0])) - return first + "." + last; + return first + '.' + last; else - return first + " " + last; + return first + ' ' + last; } static std::string getDisplayString(const std::string& first, const std::string& last, const std::string& grid, bool is_secondlife) @@ -124,7 +125,7 @@ static std::string getDisplayString(const std::string& first, const std::string& if (grid == gHippoGridManager->getDefaultGridName()) return nameJoin(first, last, is_secondlife); else - return nameJoin(first, last, is_secondlife) + " (" + grid + ")"; + return nameJoin(first, last, is_secondlife) + " (" + grid + ')'; } static std::string getDisplayString(const LLSavedLoginEntry& entry) @@ -132,22 +133,87 @@ static std::string getDisplayString(const LLSavedLoginEntry& entry) return getDisplayString(entry.getFirstName(), entry.getLastName(), entry.getGrid(), entry.isSecondLife()); } -class LLLoginRefreshHandler : public LLCommandHandler + +class LLLoginLocationAutoHandler : public LLCommandHandler { public: // don't allow from external browsers - LLLoginRefreshHandler() : LLCommandHandler("login_refresh", UNTRUSTED_BLOCK) { } + LLLoginLocationAutoHandler() : LLCommandHandler("location_login", UNTRUSTED_BLOCK) { } bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP) { - LLPanelLogin::loadLoginPage(); + if ( tokens.size() == 0 || tokens.size() > 4 ) + return false; + + // unescape is important - uris with spaces are escaped in this code path + // (e.g. space -> %20) and the code to log into a region doesn't support that. + const std::string region = LLURI::unescape( tokens[0].asString() ); + + // just region name as payload + if ( tokens.size() == 1 ) + { + // region name only - slurl will end up as center of region + LLSLURL slurl(region); + LLPanelLogin::autologinToLocation(slurl); + } + else + // region name and x coord as payload + if ( tokens.size() == 2 ) + { + // invalid to only specify region and x coordinate + // slurl code will revert to same as region only, so do this anyway + LLSLURL slurl(region); + LLPanelLogin::autologinToLocation(slurl); + } + else + // region name and x/y coord as payload + if ( tokens.size() == 3 ) + { + // region and x/y specified - default z to 0 + F32 xpos; + std::istringstream codec(tokens[1].asString()); + codec >> xpos; + + F32 ypos; + codec.clear(); + codec.str(tokens[2].asString()); + codec >> ypos; + + const LLVector3 location(xpos, ypos, 0.0f); + LLSLURL slurl(region, location); + + LLPanelLogin::autologinToLocation(slurl); + } + else + // region name and x/y/z coord as payload + if ( tokens.size() == 4 ) + { + // region and x/y/z specified - ok + F32 xpos; + std::istringstream codec(tokens[1].asString()); + codec >> xpos; + + F32 ypos; + codec.clear(); + codec.str(tokens[2].asString()); + codec >> ypos; + + F32 zpos; + codec.clear(); + codec.str(tokens[3].asString()); + codec >> zpos; + + const LLVector3 location(xpos, ypos, zpos); + LLSLURL slurl(region, location); + + LLPanelLogin::autologinToLocation(slurl); + }; } return true; } }; - -LLLoginRefreshHandler gLoginRefreshHandler; +LLLoginLocationAutoHandler gLoginLocationAutoHandler; //--------------------------------------------------------------------------- // Public methods @@ -170,6 +236,11 @@ LLPanelLogin::LLPanelLogin(const LLRect& rect) reshape(rect.getWidth(), rect.getHeight()); +#ifndef LL_FMODSTUDIO + getChildView("fmod_text")->setVisible(false); + getChildView("fmod_logo")->setVisible(false); +#endif + LLComboBox* username_combo(getChild("username_combo")); username_combo->setCommitCallback(boost::bind(LLPanelLogin::onSelectLoginEntry, _2)); username_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onLoginComboLostFocus, this, username_combo)); @@ -199,8 +270,8 @@ LLPanelLogin::LLPanelLogin(const LLRect& rect) location_combo->setFocusLostCallback( boost::bind(&LLPanelLogin::onLocationSLURL, this) ); LLComboBox* server_choice_combo = getChild("grids_combo"); - server_choice_combo->setCommitCallback(boost::bind(&LLPanelLogin::onSelectGrid, _1)); - server_choice_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onSelectGrid, server_choice_combo)); + server_choice_combo->setCommitCallback(boost::bind(&LLPanelLogin::onSelectGrid, this, _1)); + server_choice_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onSelectGrid, this, server_choice_combo)); // Load all of the grids, sorted, and then add a bar and the current grid at the top updateGridCombo(); @@ -210,7 +281,7 @@ LLPanelLogin::LLPanelLogin(const LLRect& rect) { // no, so get the preference setting std::string defaultStartLocation = gSavedSettings.getString("LoginLocation"); - LL_INFOS("AppInit")<<"default LoginLocation '"<("grids_btn")->setCommitCallback(boost::bind(LLPanelLogin::onClickGrids)); - std::string channel = gVersionChannel; + std::string channel = LLVersionInfo::getChannel(); + + std::string version = llformat("%s (%d)", + LLVersionInfo::getShortVersion().c_str(), + LLVersionInfo::getBuild()); - std::string version = llformat("%d.%d.%d (%d)", - gVersionMajor, - gVersionMinor, - gVersionPatch, - gVersionBuild ); LLTextBox* channel_text = getChild("channel_text"); channel_text->setTextArg("[CHANNEL]", channel); // though not displayed channel_text->setTextArg("[VERSION]", version); @@ -290,6 +360,67 @@ LLPanelLogin::LLPanelLogin(const LLRect& rect) { setFields(*saved_login_entries.rbegin()); } + + addFavoritesToStartLocation(); +} + +void LLPanelLogin::addFavoritesToStartLocation() +{ + // Clear the combo. + auto combo = getChild("start_location_combo"); + if (!combo) return; + S32 num_items = combo->getItemCount(); + for (S32 i = num_items - 1; i > 2; i--) + { + combo->remove(i); + } + + // Load favorites into the combo. + const auto grid = gHippoGridManager->getCurrentGrid(); + std::string first, last, password; + getFields(first, last, password); + auto user_defined_name(first + ' ' + last); + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites_" + grid->getGridName() + ".xml"); + std::string old_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); + + LLSD fav_llsd; + llifstream file; + file.open(filename); + if (!file.is_open()) + { + file.open(old_filename); + if (!file.is_open()) return; + } + LLSDSerialize::fromXML(fav_llsd, file); + + for (LLSD::map_const_iterator iter = fav_llsd.beginMap(); + iter != fav_llsd.endMap(); ++iter) + { + // The account name in stored_favorites.xml has Resident last name even if user has + // a single word account name, so it can be compared case-insensitive with the + // user defined "firstname lastname". + S32 res = LLStringUtil::compareInsensitive(user_defined_name, iter->first); + if (res != 0) + { + LL_DEBUGS() << "Skipping favorites for " << iter->first << LL_ENDL; + continue; + } + + combo->addSeparator(); + LL_DEBUGS() << "Loading favorites for " << iter->first << LL_ENDL; + auto user_llsd = iter->second; + for (LLSD::array_const_iterator iter1 = user_llsd.beginArray(); + iter1 != user_llsd.endArray(); ++iter1) + { + std::string label = (*iter1)["name"].asString(); + std::string value = (*iter1)["slurl"].asString(); + if (!label.empty() && !value.empty()) + { + combo->add(label, value); + } + } + break; + } } void LLPanelLogin::setSiteIsAlive(bool alive) @@ -304,15 +435,40 @@ void LLPanelLogin::setSiteIsAlive(bool alive) } } +void LLPanelLogin::clearPassword() +{ + getChild("password_edit")->setValue(mIncomingPassword = mMungedPassword = LLStringUtil::null); +} + +void LLPanelLogin::hidePassword() +{ + // This is a MD5 hex digest of a password. + // We don't actually use the password input field, + // fill it with MAX_PASSWORD characters so we get a + // nice row of asterixes. + getChild("password_edit")->setValue("123456789!123456"); +} + void LLPanelLogin::mungePassword(const std::string& password) { // Re-md5 if we've changed at all if (password != mIncomingPassword) { - LLMD5 pass((unsigned char *)password.c_str()); - char munged_password[MD5HEX_STR_SIZE]; - pass.hex_digest(munged_password); - mMungedPassword = munged_password; + // Max "actual" password length is 16 characters. + // Hex digests are always 32 characters. + if (password.length() == MD5HEX_STR_BYTES) + { + hidePassword(); + mMungedPassword = password; + } + else + { + LLMD5 pass((unsigned char *)utf8str_truncate(password, gHippoGridManager->getCurrentGrid()->isOpenSimulator() ? 24 : 16).c_str()); + char munged_password[MD5HEX_STR_SIZE]; + pass.hex_digest(munged_password); + mMungedPassword = munged_password; + } + mIncomingPassword = password; } } @@ -320,7 +476,7 @@ void LLPanelLogin::mungePassword(const std::string& password) // (with some padding so the other login screen doesn't show through) void LLPanelLogin::reshapeBrowser() { - LLMediaCtrl* web_browser = getChild("login_html"); + auto web_browser = getChild("login_html"); LLRect rect = gViewerWindow->getWindowRectScaled(); LLRect html_rect; html_rect.setCenterAndSize( @@ -335,10 +491,13 @@ LLPanelLogin::~LLPanelLogin() { std::string login_hist_filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "saved_logins_sg2.xml"); LLSavedLogins::saveFile(mLoginHistoryData, login_hist_filepath); - LLPanelLogin::sInstance = NULL; + sInstance = nullptr; + + // Controls having keyboard focus by default + // must reset it on destroy. (EXT-2748) if (gFocusMgr.getDefaultKeyboardFocus() == this) - gFocusMgr.setDefaultKeyboardFocus(NULL); + gFocusMgr.setDefaultKeyboardFocus(nullptr); } // virtual @@ -391,7 +550,7 @@ BOOL LLPanelLogin::handleKeyHere(KEY key, MASK mask) if ( KEY_F2 == key ) { LL_INFOS() << "Spawning floater TOS window" << LL_ENDL; - LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS,""); + LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS,LLStringUtil::null); tos_dialog->startModal(); return TRUE; } @@ -429,8 +588,8 @@ void LLPanelLogin::giveFocus() BOOL have_username = !username.empty(); BOOL have_pass = !pass.empty(); - LLLineEditor* edit = NULL; - LLComboBox* combo = NULL; + LLLineEditor* edit = nullptr; + LLComboBox* combo = nullptr; if (have_username && !have_pass) { // User saved his name but not his password. Move @@ -488,29 +647,11 @@ void LLPanelLogin::setFields(const std::string& firstname, llassert_always(firstname.find(' ') == std::string::npos); login_combo->setLabel(nameJoin(firstname, lastname, false)); - // Max "actual" password length is 16 characters. - // Hex digests are always 32 characters. - if (password.length() == 32) - { - // This is a MD5 hex digest of a password. - // We don't actually use the password input field, - // fill it with MAX_PASSWORD characters so we get a - // nice row of asterixes. - const std::string filler("123456789!123456"); - sInstance->getChild("password_edit")->setValue(filler); - sInstance->mIncomingPassword = filler; - sInstance->mMungedPassword = password; - } - else - { - // this is a normal text password + sInstance->mungePassword(password); + if (sInstance->mIncomingPassword != sInstance->mMungedPassword) sInstance->getChild("password_edit")->setValue(password); - sInstance->mIncomingPassword = password; - LLMD5 pass((unsigned char *)password.c_str()); - char munged_password[MD5HEX_STR_SIZE]; - pass.hex_digest(munged_password); - sInstance->mMungedPassword = munged_password; - } + else + sInstance->hidePassword(); } // static @@ -527,33 +668,26 @@ void LLPanelLogin::setFields(const LLSavedLoginEntry& entry, bool takeFocus) LLComboBox* login_combo = sInstance->getChild("username_combo"); login_combo->setTextEntry(fullname); login_combo->resetTextDirty(); - //sInstance->getChild("username_combo")->setValue(fullname); + //login_combo->setValue(fullname); - std::string grid = entry.getGrid(); + const auto& grid = entry.getGrid(); //grid comes via LLSavedLoginEntry, which uses full grid names, not nicks - if(!grid.empty() && gHippoGridManager->getGrid(grid) && grid != gHippoGridManager->getCurrentGridName()) + if (!grid.empty() && gHippoGridManager->getGrid(grid) && grid != gHippoGridManager->getCurrentGridName()) { gHippoGridManager->setCurrentGrid(grid); } - - if (entry.getPassword().empty()) - { - sInstance->getChild("password_edit")->setValue(LLStringUtil::null); - remember_pass_check->setValue(LLSD(false)); - } - else - { - const std::string filler("123456789!123456"); - sInstance->getChild("password_edit")->setValue(filler); - sInstance->mIncomingPassword = filler; - sInstance->mMungedPassword = entry.getPassword(); - remember_pass_check->setValue(LLSD(true)); - } - if (takeFocus) + const auto& password = entry.getPassword(); + bool remember_pass = !password.empty(); + if (remember_pass) { - giveFocus(); + sInstance->mIncomingPassword = sInstance->mMungedPassword = password; + sInstance->hidePassword(); } + else sInstance->clearPassword(); + remember_pass_check->setValue(remember_pass); + + if (takeFocus) giveFocus(); } // static @@ -614,7 +748,7 @@ void LLPanelLogin::onUpdateStartSLURL(const LLSLURL& new_start_slurl) LL_DEBUGS("AppInit")<getChild("start_location_combo"); + auto location_combo = sInstance->getChild("start_location_combo"); /* * Determine whether or not the new_start_slurl modifies the grid. * @@ -633,12 +767,15 @@ void LLPanelLogin::onUpdateStartSLURL(const LLSLURL& new_start_slurl) location_combo->setTextEntry(new_start_slurl.getLocationString()); } break; + case LLSLURL::HOME_LOCATION: location_combo->setCurrentByIndex(0); // home location break; + case LLSLURL::LAST_LOCATION: location_combo->setCurrentByIndex(1); // last location break; + default: LL_WARNS("AppInit")<<"invalid login slurl, using home"<setCurrentByIndex(1); // home location @@ -654,14 +791,27 @@ void LLPanelLogin::setLocation(const LLSLURL& slurl) LLStartUp::setStartSLURL(slurl); // calls onUpdateStartSLURL, above } +void LLPanelLogin::autologinToLocation(const LLSLURL& slurl) +{ + LL_DEBUGS("AppInit")<<"automatically logging into Location "<onClickConnect(); + } +} + + // static void LLPanelLogin::close() { if (sInstance) { sInstance->getParent()->removeChild(sInstance); + delete sInstance; - sInstance = NULL; + sInstance = nullptr; } } @@ -722,25 +872,27 @@ void LLPanelLogin::loadLoginPage() sInstance->setSiteIsAlive(false); return; } - + // Use the right delimeter depending on how LLURI parses the URL LLURI login_page = LLURI(login_page_str); LLSD params(login_page.queryMap()); LL_DEBUGS("AppInit") << "login_page: " << login_page << LL_ENDL; - // Language + // Language params["lang"] = LLUI::getLanguage(); - - // First Login? - if (gSavedSettings.getBOOL("FirstLoginThisInstall")) + + // First Login? + if (gSavedSettings.getBOOL("FirstLoginThisInstall")) { params["firstlogin"] = "TRUE"; // not bool: server expects string TRUE - } - - params["version"]= llformat("%d.%d.%d (%d)", - gVersionMajor, gVersionMinor, gVersionPatch, gVersionBuild); - params["channel"] = gVersionChannel; + } + + // Channel and Version + params["version"] = llformat("%s (%d)", + LLVersionInfo::getShortVersion().c_str(), + LLVersionInfo::getBuild()); + params["channel"] = LLVersionInfo::getChannel(); // Grid @@ -765,7 +917,7 @@ void LLPanelLogin::loadLoginPage() { params["grid"] = gHippoGridManager->getCurrentGrid()->getGridNick(); } - else if (gHippoGridManager->getCurrentGrid()->getPlatform() == HippoGridInfo::PLATFORM_AURORA) + else if (gHippoGridManager->getCurrentGrid()->getPlatform() == HippoGridInfo::PLATFORM_WHITECORE) { params["grid"] = LLViewerLogin::getInstance()->getGridLabel(); } @@ -773,10 +925,13 @@ void LLPanelLogin::loadLoginPage() // add OS info params["os"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple(); + auto&& uri_with_params = [](const LLURI& uri, const LLSD& params) { + return LLURI(uri.scheme(), uri.userName(), uri.password(), uri.hostName(), uri.hostPort(), uri.path(), + LLURI::mapToQueryString(params)); + }; + // Make an LLURI with this augmented info - LLURI login_uri(LLURI::buildHTTP(login_page.authority(), - login_page.path(), - params)); + LLURI login_uri(uri_with_params(login_page, params)); gViewerWindow->setMenuBackgroundColor(false, !LLViewerLogin::getInstance()->isInProductionGrid()); gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor()); @@ -785,7 +940,14 @@ void LLPanelLogin::loadLoginPage() if (!singularity_splash_uri.empty()) { params["original_page"] = login_uri.asString(); - login_uri = LLURI::buildHTTP(singularity_splash_uri, gSavedSettings.getString("SingularitySplashPagePath"), params); + login_uri = LLURI(singularity_splash_uri + gSavedSettings.getString("SingularitySplashPagePath")); + + // Copy any existent splash path params + auto& params_map = params.map(); + for (auto&& pair : login_uri.queryMap().map()) + params_map.emplace(pair); + + login_uri = uri_with_params(login_uri, params); } LLMediaCtrl* web_browser = sInstance->getChild("login_html"); @@ -923,7 +1085,7 @@ void LLPanelLogin::onSelectGrid(LLUICtrl *ctrl) LLStringUtil::trim(grid); // Guard against copy paste if (!gHippoGridManager->getGrid(grid)) // We can't get an input grid by name or nick, perhaps a Login URI was entered { - HippoGridInfo* info(new HippoGridInfo("")); // Start off with empty grid name, otherwise we don't know what to name + HippoGridInfo* info(new HippoGridInfo(LLStringUtil::null)); // Start off with empty grid name, otherwise we don't know what to name info->setLoginUri(grid); try { @@ -963,11 +1125,47 @@ void LLPanelLogin::onSelectGrid(LLUICtrl *ctrl) } gHippoGridManager->setCurrentGrid(grid); ctrl->setValue(grid); + addFavoritesToStartLocation(); + + /* + * Determine whether or not the value in the start_location_combo makes sense + * with the new grid value. + * + * Note that some forms that could be in the location combo are grid-agnostic, + * such as "MyRegion/128/128/0". There could be regions with that name on any + * number of grids, so leave them alone. Other forms, such as + * https://grid.example.com/region/Party%20Town/20/30/5 specify a particular + * grid; in those cases we want to clear the location. + */ + auto location_combo = getChild("start_location_combo"); + S32 index = location_combo->getCurrentIndex(); + switch (index) + { + case 0: // last location + case 1: // home location + // do nothing - these are grid-agnostic locations + break; + + default: + { + std::string location = location_combo->getValue().asString(); + LLSLURL slurl(location); // generata a slurl from the location combo contents + if ( slurl.getType() == LLSLURL::LOCATION + && slurl.getGrid() != gHippoGridManager->getCurrentGridNick() + ) + { + // the grid specified by the location is not this one, so clear the combo + location_combo->setCurrentByIndex(0); // last location on the new grid + location_combo->setTextEntry(LLStringUtil::null); + } + } + break; + } } void LLPanelLogin::onLocationSLURL() { - LLComboBox* location_combo = getChild("start_location_combo"); + auto location_combo = getChild("start_location_combo"); std::string location = location_combo->getValue().asString(); LLStringUtil::trim(location); LL_DEBUGS("AppInit")<setNameEditted(true); + + sInstance->addFavoritesToStartLocation(); } void LLPanelLogin::onLoginComboLostFocus(LLComboBox* combo_box) { if (combo_box->isTextDirty()) { - getChild("password_edit")->setValue(mIncomingPassword = mMungedPassword = LLStringUtil::null); + clearPassword(); combo_box->resetTextDirty(); } } diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 661bc6df0a..478588aa48 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -79,6 +79,7 @@ class LLPanelLogin: static void getFields(std::string& firstname, std::string& lastname, std::string& password); static void setLocation(const LLSLURL& slurl); + static void autologinToLocation(const LLSLURL& slurl); /// Call when preferences that control visibility may have changed static void updateLocationSelectorsVisibility(); @@ -94,6 +95,8 @@ class LLPanelLogin: static void refreshLoginPage(); static void giveFocus(); static void setAlwaysRefresh(bool refresh); + void clearPassword(); + void hidePassword(); void mungePassword(const std::string& password); // inherited from LLViewerMediaObserver @@ -104,13 +107,14 @@ class LLPanelLogin: private: void reshapeBrowser(); + void addFavoritesToStartLocation(); void onLocationSLURL(); void onClickConnect(); static void onClickNewAccount(); static bool newAccountAlertCallback(const LLSD& notification, const LLSD& response); static void onClickGrids(); - static void onSelectGrid(LLUICtrl *ctrl); + void onSelectGrid(LLUICtrl *ctrl); static void onClickForgotPassword(); static void onPassKey(); static void onSelectLoginEntry(const LLSD& selected_entry); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 02f3eedf06..659a5dfb4a 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -29,7 +29,6 @@ #include "llagent.h" #include "llagentcamera.h" -#include "lleconomy.h" #include "llfirstuse.h" #include "llfiltereditor.h" #include "llinventorybridge.h" @@ -40,6 +39,7 @@ #include "llresmgr.h" #include "llscrollcontainer.h" #include "llsdserialize.h" +#include "llsdparam.h" #include "llspinctrl.h" #include "lltooldraganddrop.h" #include "llviewermenu.h" @@ -47,67 +47,79 @@ #include "llpanelobjectinventory.h" #include "llappviewer.h" +#include "llradiogroup.h" + #include "rlvhandler.h" const std::string FILTERS_FILENAME("filters.xml"); -std::vector LLInventoryView::sActiveViews; +std::vector LLPanelMainInventory::sActiveViews; const S32 INV_MIN_WIDTH = 240; const S32 INV_MIN_HEIGHT = 150; const S32 INV_FINDER_WIDTH = 160; const S32 INV_FINDER_HEIGHT = 408; -//BOOL LLInventoryView::sOpenNextNewItem = FALSE; class LLFloaterInventoryFinder : public LLFloater { public: LLFloaterInventoryFinder(const std::string& name, const LLRect& rect, - LLInventoryView* inventory_view); + LLPanelMainInventory* inventory_view); virtual void draw(); /*virtual*/ BOOL postBuild(); virtual void onClose(bool app_quitting); void changeFilter(LLInventoryFilter* filter); void updateElementsFromFilter(); + BOOL getCheckShowLinks(); BOOL getCheckShowEmpty(); BOOL getCheckSinceLogoff(); + U32 getDateSearchDirection(); + void onLinks(const LLSD& val); static void onTimeAgo(LLUICtrl*, void *); static void onCloseBtn(void* user_data); static void selectAllTypes(void* user_data); static void selectNoTypes(void* user_data); protected: - LLInventoryView* mInventoryView; + LLPanelMainInventory* mPanelMainInventory; LLSpinCtrl* mSpinSinceDays; LLSpinCtrl* mSpinSinceHours; + LLUICtrl* mRadioLinks; LLInventoryFilter* mFilter; }; - ///---------------------------------------------------------------------------- -/// LLInventoryView +/// LLPanelMainInventory ///---------------------------------------------------------------------------- // Default constructor -LLInventoryView::LLInventoryView(const std::string& name, +LLPanelMainInventory::LLPanelMainInventory(const std::string& name, const std::string& rect, LLInventoryModel* inventory) : LLFloater(name, rect, std::string("Inventory"), RESIZE_YES, INV_MIN_WIDTH, INV_MIN_HEIGHT, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES), - mActivePanel(NULL) + mFilterEditor(nullptr), + mFilterTabs(nullptr), + mActivePanel(nullptr), + mResortActivePanel(true), + mFilterText("") //LLHandle mFinderHandle takes care of its own initialization { init(inventory); } -LLInventoryView::LLInventoryView(const std::string& name, +LLPanelMainInventory::LLPanelMainInventory(const std::string& name, const LLRect& rect, LLInventoryModel* inventory) : LLFloater(name, rect, std::string("Inventory"), RESIZE_YES, INV_MIN_WIDTH, INV_MIN_HEIGHT, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES), - mActivePanel(NULL) + mFilterEditor(nullptr), + mFilterTabs(nullptr), + mActivePanel(nullptr), + mResortActivePanel(true), + mFilterText("") //LLHandle mFinderHandle takes care of its own initialization { init(inventory); @@ -115,7 +127,7 @@ LLInventoryView::LLInventoryView(const std::string& name, } -void LLInventoryView::init(LLInventoryModel* inventory) +void LLPanelMainInventory::init(LLInventoryModel* inventory) { // Callbacks init_inventory_actions(this); @@ -132,13 +144,10 @@ void LLInventoryView::init(LLInventoryModel* inventory) addBoolControl("Inventory.SearchDesc", FALSE); addBoolControl("Inventory.SearchCreator", FALSE); - mSavedFolderState = new LLSaveFolderState(); - mSavedFolderState->setApply(FALSE); - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory.xml", NULL); } -BOOL LLInventoryView::postBuild() +BOOL LLPanelMainInventory::postBuild() { gInventory.addObserver(this); @@ -150,9 +159,8 @@ BOOL LLInventoryView::postBuild() { // "All Items" is the previous only view, so it gets the InventorySortOrder mActivePanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER)); - mActivePanel->getFilter()->markDefault(); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - mActivePanel->setSelectCallback(boost::bind(&LLInventoryView::onSelectionChange, this, mActivePanel, _1, _2)); + mActivePanel->getFilter().markDefault(); + mActivePanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mActivePanel, _1, _2)); mResortActivePanel = true; } LLInventoryPanel* recent_items_panel = getChild("Recent Items"); @@ -161,24 +169,26 @@ BOOL LLInventoryView::postBuild() recent_items_panel->setSinceLogoff(TRUE); recent_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::RECENTITEMS_SORT_ORDER)); recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - recent_items_panel->getFilter()->markDefault(); - recent_items_panel->setSelectCallback(boost::bind(&LLInventoryView::onSelectionChange, this, recent_items_panel, _1, _2)); + LLInventoryFilter& recent_filter = recent_items_panel->getFilter(); + recent_filter.setFilterObjectTypes(recent_filter.getFilterObjectTypes() & ~(0x1 << LLInventoryType::IT_CATEGORY)); + recent_filter.markDefault(); + recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2)); } LLInventoryPanel* worn_items_panel = getChild("Worn Items"); if (worn_items_panel) { worn_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::WORNITEMS_SORT_ORDER)); worn_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - worn_items_panel->getFilter()->markDefault(); - worn_items_panel->setFilterWorn(true); + worn_items_panel->getFilter().markDefault(); + worn_items_panel->setFilterWornItems(); worn_items_panel->setFilterLinks(LLInventoryFilter::FILTERLINK_EXCLUDE_LINKS); - worn_items_panel->setSelectCallback(boost::bind(&LLInventoryView::onSelectionChange, this, worn_items_panel, _1, _2)); + worn_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, worn_items_panel, _1, _2)); } // Now load the stored settings from disk, if available. std::ostringstream filterSaveName; filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME); - LL_INFOS() << "LLInventoryView::init: reading from " << filterSaveName.str() << LL_ENDL; + LL_INFOS() << "LLPanelMainInventory::init: reading from " << filterSaveName.str() << LL_ENDL; llifstream file(filterSaveName.str()); LLSD savedFilterState; if (file.is_open()) @@ -187,36 +197,50 @@ BOOL LLInventoryView::postBuild() file.close(); // Load the persistent "Recent Items" settings. - // Note that the "All Items" and "Worn Items" settings do not persist per-account. + // Note that the "All Items" settings do not persist. if(recent_items_panel) { - if(savedFilterState.has(recent_items_panel->getFilter()->getName())) + if(savedFilterState.has(recent_items_panel->getFilter().getName())) { LLSD recent_items = savedFilterState.get( - recent_items_panel->getFilter()->getName()); - recent_items_panel->getFilter()->fromLLSD(recent_items); + recent_items_panel->getFilter().getName()); + LLInventoryFilter::Params p; + LLParamSDParser parser; + parser.readSD(recent_items, p); + recent_items_panel->getFilter().fromParams(p); + } + } + if(worn_items_panel) + { + if(savedFilterState.has(worn_items_panel->getFilter().getName())) + { + LLSD worn_items = savedFilterState.get( + worn_items_panel->getFilter().getName()); + LLInventoryFilter::Params p; + LLParamSDParser parser; + parser.readSD(worn_items, p); + worn_items_panel->getFilter().fromParams(p); } } } - mFilterEditor = getChild("inventory search editor"); if (mFilterEditor) { - mFilterEditor->setCommitCallback(boost::bind(&LLInventoryView::onFilterEdit, this, _2)); + mFilterEditor->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterEdit, this, _2)); } mQuickFilterCombo = getChild("Quick Filter"); if (mQuickFilterCombo) { - mQuickFilterCombo->setCommitCallback(boost::bind(LLInventoryView::onQuickFilterCommit, _1, this)); + mQuickFilterCombo->setCommitCallback(boost::bind(LLPanelMainInventory::onQuickFilterCommit, _1, this)); } sActiveViews.push_back(this); - getChild("inventory filter tabs")->setCommitCallback(boost::bind(&LLInventoryView::onFilterSelected,this)); + getChild("inventory filter tabs")->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected,this)); childSetAction("Inventory.ResetAll",onResetAll,this); childSetAction("Inventory.ExpandAll",onExpandAll,this); @@ -225,62 +249,65 @@ BOOL LLInventoryView::postBuild() } // Destroys the object -LLInventoryView::~LLInventoryView( void ) +LLPanelMainInventory::~LLPanelMainInventory( void ) { // Save the filters state. LLSD filterRoot; LLInventoryPanel* all_items_panel = getChild("All Items"); if (all_items_panel) { - LLInventoryFilter* filter = all_items_panel->getFilter(); - if (filter) + LLSD filterState; + LLInventoryPanel::InventoryState p; + all_items_panel->getFilter().toParams(p.filter); + if (p.validateBlock(false)) { - LLSD filterState; - filter->toLLSD(filterState); - filterRoot[filter->getName()] = filterState; + LLParamSDParser().writeSD(filterState, p); + filterRoot[all_items_panel->getName()] = filterState; } } - LLInventoryPanel* recent_items_panel = getChild("Recent Items"); - if (recent_items_panel) + LLInventoryPanel* recent_panel = findChild("Recent Items"); + if (recent_panel) { - LLInventoryFilter* filter = recent_items_panel->getFilter(); - if (filter) + LLSD filterState; + LLInventoryPanel::InventoryState p; + recent_panel->getFilter().toParams(p.filter); + if (p.validateBlock(false)) { - LLSD filterState; - filter->toLLSD(filterState); - filterRoot[filter->getName()] = filterState; + LLParamSDParser().writeSD(filterState, p); + filterRoot[recent_panel->getName()] = filterState; } } - LLInventoryPanel* worn_items_panel = getChild("Worn Items"); - if (worn_items_panel) + LLInventoryPanel* worn_panel = findChild("Worn Items"); + if (worn_panel) { - LLInventoryFilter* filter = worn_items_panel->getFilter(); - if (filter) + LLSD filterState; + LLInventoryPanel::InventoryState p; + worn_panel->getFilter().toParams(p.filter); + if (p.validateBlock(false)) { - LLSD filterState; - filter->toLLSD(filterState); - filterRoot[filter->getName()] = filterState; + LLParamSDParser().writeSD(filterState, p); + filterRoot[worn_panel->getName()] = filterState; } } - std::ostringstream filterSaveName; - filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml"); - llofstream filtersFile(filterSaveName.str()); + std::string filterSaveName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME)); + llofstream filtersFile(filterSaveName.c_str()); if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile)) { - LL_WARNS() << "Could not write to filters save file " << filterSaveName.str().c_str() << LL_ENDL; + LL_WARNS() << "Could not write to filters save file " << filterSaveName.c_str() << LL_ENDL; } else + { filtersFile.close(); + } vector_replace_with_last(sActiveViews, this); gInventory.removeObserver(this); - delete mSavedFolderState; } -void LLInventoryView::startSearch() +void LLPanelMainInventory::startSearch() { // this forces focus to line editor portion of search editor if (mFilterEditor) @@ -290,18 +317,18 @@ void LLInventoryView::startSearch() } // virtual, from LLView -void LLInventoryView::setVisible( BOOL visible ) +void LLPanelMainInventory::setVisible( BOOL visible ) { gSavedSettings.setBOOL("ShowInventory", visible); LLFloater::setVisible(visible); } // Destroy all but the last floater, which is made invisible. -void LLInventoryView::onClose(bool app_quitting) +void LLPanelMainInventory::onClose(bool app_quitting) { // S32 count = sActiveViews.count(); // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) - // See LLInventoryView::closeAll() on why we're doing it this way + // See LLPanelMainInventory::closeAll() on why we're doing it this way S32 count = 0; for (S32 idx = 0, cnt = sActiveViews.size(); idx < cnt; idx++) { @@ -320,21 +347,13 @@ void LLInventoryView::onClose(bool app_quitting) { gSavedSettings.setBOOL("ShowInventory", FALSE); } - // clear filters, but save user's folder state first - if (!mActivePanel->getRootFolder()->isFilterModified()) - { - mSavedFolderState->setApply(FALSE); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - } - - // onClearSearch(this); // pass up LLFloater::setVisible(FALSE); } } -BOOL LLInventoryView::handleKeyHere(KEY key, MASK mask) +BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask) { LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL; if (root_folder) @@ -366,21 +385,15 @@ BOOL LLInventoryView::handleKeyHere(KEY key, MASK mask) // static // *TODO: remove take_keyboard_focus param -LLInventoryView* LLInventoryView::showAgentInventory(BOOL take_keyboard_focus) +LLPanelMainInventory* LLPanelMainInventory::showAgentInventory(BOOL take_keyboard_focus) { - if (gDisconnected || gNoRender) - { - return NULL; - } + if (gDisconnected) return NULL; // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV)) - { - return NULL; - } + if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV)) return NULL; // [/RLVa:KB] - LLInventoryView* iv = LLInventoryView::getActiveInventory(); + LLPanelMainInventory* iv = LLPanelMainInventory::getActiveInventory(); #if 0 && !LL_RELEASE_FOR_DOWNLOAD if (sActiveViews.count() == 1) { @@ -391,7 +404,7 @@ LLInventoryView* LLInventoryView::showAgentInventory(BOOL take_keyboard_focus) if(!iv && !gAgentCamera.cameraMouselook()) { // create one. - iv = new LLInventoryView(std::string("Inventory"), + iv = new LLPanelMainInventory(std::string("Inventory"), std::string("FloaterInventoryRect"), &gInventory); iv->open(); @@ -406,28 +419,23 @@ LLInventoryView* LLInventoryView::showAgentInventory(BOOL take_keyboard_focus) iv->setTitle(std::string("Inventory")); iv->open(); /*Flawfinder: ignore*/ } - //if (take_keyboard_focus) - //{ - // iv->startSearch(); - // gFocusMgr.triggerFocusFlash(); - //} return iv; } // static -LLInventoryView* LLInventoryView::getActiveInventory() +LLPanelMainInventory* LLPanelMainInventory::getActiveInventory() { - LLInventoryView* iv = NULL; + LLPanelMainInventory* iv = NULL; S32 count = sActiveViews.size(); if(count > 0) { - iv = sActiveViews.at(0); + iv = sActiveViews.front(); S32 z_order = gFloaterView->getZOrder(iv); S32 z_next = 0; - LLInventoryView* next_iv = NULL; + LLPanelMainInventory* next_iv = NULL; for(S32 i = 1; i < count; ++i) { - next_iv = sActiveViews.at(i); + next_iv = sActiveViews[i]; z_next = gFloaterView->getZOrder(next_iv); if(z_next < z_order) { @@ -440,7 +448,7 @@ LLInventoryView* LLInventoryView::getActiveInventory() } // static -void LLInventoryView::toggleVisibility() +void LLPanelMainInventory::toggleVisibility() { S32 count = sActiveViews.size(); if (0 == count) @@ -451,9 +459,9 @@ void LLInventoryView::toggleVisibility() } else if (1 == count) { - if (sActiveViews.at(0)->getVisible()) + if (sActiveViews.front()->getVisible()) { - sActiveViews.at(0)->close(); + sActiveViews.front()->close(); gSavedSettings.setBOOL("ShowInventory", FALSE); } else @@ -467,23 +475,23 @@ void LLInventoryView::toggleVisibility() // is visible. // Close all the last one spawned. - S32 last_index = sActiveViews.size() - 1; - sActiveViews.at(last_index)->close(); + sActiveViews.back()->close(); } } // static -void LLInventoryView::cleanup() +void LLPanelMainInventory::cleanup() { S32 count = sActiveViews.size(); for (S32 i = 0; i < count; i++) { sActiveViews.at(i)->destroy(); } + sActiveViews.clear(); } -void LLInventoryView::updateSortControls() +void LLPanelMainInventory::updateSortControls() { U32 order = mActivePanel ? mActivePanel->getSortOrder() : gSavedSettings.getU32("InventorySortOrder"); bool sort_by_date = order & LLInventoryFilter::SO_DATE; @@ -496,11 +504,10 @@ void LLInventoryView::updateSortControls() getControl("Inventory.SystemFoldersToTop")->setValue(sys_folders_on_top); } -void LLInventoryView::resetFilters() +void LLPanelMainInventory::resetFilters() { - LLFloaterInventoryFinder *finder = getFinder(); - getActivePanel()->getFilter()->resetDefault(); - if (finder) + getActivePanel()->getFilter().resetDefault(); + if (LLFloaterInventoryFinder* finder = getFinder()) { finder->updateElementsFromFilter(); } @@ -509,72 +516,34 @@ void LLInventoryView::resetFilters() } // static -BOOL LLInventoryView::filtersVisible(void* user_data) +BOOL LLPanelMainInventory::filtersVisible(void* user_data) { - LLInventoryView* self = (LLInventoryView*)user_data; + LLPanelMainInventory* self = (LLPanelMainInventory*)user_data; if(!self) return FALSE; return self->getFinder() != NULL; } -void LLInventoryView::onClearSearch() +void LLPanelMainInventory::onFilterEdit(const std::string& search_string ) { - LLFloater *finder = getFinder(); - if (mActivePanel) - { - mActivePanel->setFilterSubString(LLStringUtil::null); - mActivePanel->setFilterTypes(0xffffffffffffffffULL); - } - - if (finder) - { - LLFloaterInventoryFinder::selectAllTypes(finder); - } - - // re-open folders that were initially open - if (mActivePanel) - { - mSavedFolderState->setApply(TRUE); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - LLOpenFoldersWithSelection opener; - mActivePanel->getRootFolder()->applyFunctorRecursively(opener); - mActivePanel->getRootFolder()->scrollToShowSelection(); - } - //self->mFilterSubString = ""; -} - -void LLInventoryView::onFilterEdit(const std::string& search_string ) -{ - if (search_string == "") - { - onClearSearch(); - } if (!mActivePanel) { return; } - LLInventoryModelBackgroundFetch::instance().start(); - - //self->mFilterSubString = search_string; - std::string filter_text = search_string; - std::string uppercase_search_string = filter_text; - LLStringUtil::toUpper(uppercase_search_string); - if (mActivePanel->getFilterSubString().empty() && uppercase_search_string.empty() /*self->mFilterSubString.empty()*/) + /* Singu Note: This is the old behavior, desired by SV-2078, but we'd prefer the new behavior. + * I've left this here in case we want to add it back in some way. + if (search_string.empty()) { - // current filter and new filter empty, do nothing - return; - } - - // save current folder open state if no filter currently applied - if (!mActivePanel->getRootFolder()->isFilterModified()) - { - mSavedFolderState->setApply(FALSE); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + mActivePanel->setFilterTypes(0xffffffffffffffffULL); + if (auto* finder = getFinder()) + LLFloaterInventoryFinder::selectAllTypes(finder); } + */ // set new filter string - mActivePanel->setFilterSubString(uppercase_search_string/*self->mFilterSubString*/); + // Internally handles saving/restoring folder states. + mActivePanel->setFilterSubString(search_string); } struct FilterEntry : public LLDictionaryEntry @@ -589,7 +558,7 @@ class LLFilterDictionary : public LLSingleton, public: LLFilterDictionary() {} - void init(LLInventoryView *view) + void init(LLPanelMainInventory *view) { addEntry(0x1 << LLInventoryType::IT_ANIMATION, new FilterEntry(view->getString("filter_type_animation"))); addEntry(0x1 << LLInventoryType::IT_CALLINGCARD, new FilterEntry(view->getString("filter_type_callingcard"))); @@ -611,12 +580,12 @@ class LLFilterDictionary : public LLSingleton, }; //static -void LLInventoryView::onQuickFilterCommit(LLUICtrl* ctrl, void* user_data) +void LLPanelMainInventory::onQuickFilterCommit(LLUICtrl* ctrl, void* user_data) { LLComboBox* quickfilter = (LLComboBox*)ctrl; - LLInventoryView* view = (LLInventoryView*)(quickfilter->getParent()); + LLPanelMainInventory* view = (LLPanelMainInventory*)(quickfilter->getParent()); if (!view->mActivePanel) { return; @@ -649,8 +618,7 @@ void LLInventoryView::onQuickFilterCommit(LLUICtrl* ctrl, void* user_data) view->mActivePanel->setFilterTypes( filter_type ); // Force the filters window to update itself, if it's open. - LLFloaterInventoryFinder* finder = view->getFinder(); - if( finder ) + if (LLFloaterInventoryFinder* finder = view->getFinder()) finder->updateElementsFromFilter(); } } @@ -659,9 +627,9 @@ void LLInventoryView::onQuickFilterCommit(LLUICtrl* ctrl, void* user_data) //static -void LLInventoryView::refreshQuickFilter(LLUICtrl* ctrl) +void LLPanelMainInventory::refreshQuickFilter(LLUICtrl* ctrl) { - LLInventoryView* view = (LLInventoryView*)(ctrl->getParent()); + LLPanelMainInventory* view = (LLPanelMainInventory*)(ctrl->getParent()); if (!view->mActivePanel) { return; @@ -690,7 +658,7 @@ void LLInventoryView::refreshQuickFilter(LLUICtrl* ctrl) filter_type &= filter_mask; - //LL_INFOS() << "filter_type: " << filter_type << LL_ENDL; + //LL_INFOS() << "filter_type: " << filter_type << LL_ENDL; std::string selection; if (filter_type == filter_mask) @@ -699,25 +667,22 @@ void LLInventoryView::refreshQuickFilter(LLUICtrl* ctrl) } else { - const FilterEntry *entry = LLFilterDictionary::instance().lookup(filter_type); - if(entry) + if (const FilterEntry *entry = LLFilterDictionary::instance().lookup(filter_type)) selection = entry->mName; else selection = view->getString("filter_type_custom"); } // Select the chosen item by label text - BOOL result = quickfilter->setSimple( (selection) ); - - if( !result ) + if (!quickfilter->setSimple(selection)) { LL_INFOS() << "The item didn't exist: " << selection << LL_ENDL; } } -void LLInventoryView::onResetAll(void* userdata) +void LLPanelMainInventory::onResetAll(void* userdata) { - LLInventoryView* self = (LLInventoryView*) userdata; + LLPanelMainInventory* self = (LLPanelMainInventory*) userdata; self->mActivePanel = (LLInventoryPanel*)self->childGetVisibleTab("inventory filter tabs"); if (!self->mActivePanel) @@ -728,14 +693,17 @@ void LLInventoryView::onResetAll(void* userdata) { self->mFilterEditor->setText(LLStringUtil::null); } - self->onFilterEdit(""); + self->onFilterEdit(LLStringUtil::null); + self->mActivePanel->setFilterTypes(0xffffffffffffffffULL); + if (auto* finder = self->getFinder()) + LLFloaterInventoryFinder::selectAllTypes(finder); self->mActivePanel->closeAllFolders(); } //static -void LLInventoryView::onExpandAll(void* userdata) +void LLPanelMainInventory::onExpandAll(void* userdata) { - LLInventoryView* self = (LLInventoryView*) userdata; + LLPanelMainInventory* self = (LLPanelMainInventory*) userdata; self->mActivePanel = (LLInventoryPanel*)self->childGetVisibleTab("inventory filter tabs"); if (!self->mActivePanel) @@ -747,9 +715,9 @@ void LLInventoryView::onExpandAll(void* userdata) //static -void LLInventoryView::onCollapseAll(void* userdata) +void LLPanelMainInventory::onCollapseAll(void* userdata) { - LLInventoryView* self = (LLInventoryView*) userdata; + LLPanelMainInventory* self = (LLPanelMainInventory*) userdata; self->mActivePanel = (LLInventoryPanel*)self->childGetVisibleTab("inventory filter tabs"); if (!self->mActivePanel) @@ -759,24 +727,23 @@ void LLInventoryView::onCollapseAll(void* userdata) self->mActivePanel->closeAllFolders(); } -void LLInventoryView::onFilterSelected() +void LLPanelMainInventory::onFilterSelected() { // Find my index - mActivePanel = (LLInventoryPanel*)childGetVisibleTab("inventory filter tabs"); + mActivePanel = (LLInventoryPanel*)getChild("inventory filter tabs")->getCurrentPanel(); if (!mActivePanel) { return; } - //>setFilterSubString(self->mFilterSubString); - LLInventoryFilter* filter = mActivePanel->getFilter(); + LLInventoryFilter& filter = mActivePanel->getFilter(); LLFloaterInventoryFinder *finder = getFinder(); if (finder) { - finder->changeFilter(filter); + finder->changeFilter(&filter); } - if (filter->isActive()) + if (filter.isActive()) { // If our filter is active we may be the first thing requiring a fetch so we better start it here. LLInventoryModelBackgroundFetch::instance().start(); @@ -785,18 +752,18 @@ void LLInventoryView::onFilterSelected() updateSortControls(); } -const std::string LLInventoryView::getFilterSubString() +const std::string LLPanelMainInventory::getFilterSubString() { return mActivePanel->getFilterSubString(); } -void LLInventoryView::setFilterSubString(const std::string& string) +void LLPanelMainInventory::setFilterSubString(const std::string& string) { mActivePanel->setFilterSubString(string); } -BOOL LLInventoryView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +BOOL LLPanelMainInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, @@ -818,7 +785,7 @@ BOOL LLInventoryView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return handled; } -void LLInventoryView::changed(U32 mask) +void LLPanelMainInventory::changed(U32 mask) { // Singu note: only if there's a change we're interested in. if ((mask & (LLInventoryObserver::ADD | LLInventoryObserver::REMOVE)) != 0) @@ -827,7 +794,7 @@ void LLInventoryView::changed(U32 mask) } } -void LLInventoryView::draw() +void LLPanelMainInventory::draw() { if (mActivePanel && mFilterEditor) { @@ -838,7 +805,6 @@ void LLInventoryView::draw() { refreshQuickFilter( mQuickFilterCombo ); } - if (mActivePanel && mResortActivePanel) { // EXP-756: Force resorting of the list the first time we draw the list: @@ -850,12 +816,11 @@ void LLInventoryView::draw() mActivePanel->setSortOrder(order); mResortActivePanel = false; } - updateItemcountText(); LLFloater::draw(); } -void LLInventoryView::updateItemcountText() +void LLPanelMainInventory::updateItemcountText() { std::ostringstream title; title << "Inventory"; @@ -873,12 +838,12 @@ void LLInventoryView::updateItemcountText() setTitle(title.str()); } -void LLInventoryView::setFilterTextFromFilter() +void LLPanelMainInventory::setFilterTextFromFilter() { - mFilterText = mActivePanel->getFilter()->getFilterText(); + mFilterText = mActivePanel->getFilter().getFilterText(); } -void LLInventoryView::toggleFindOptions() +void LLPanelMainInventory::toggleFindOptions() { LLFloater *floater = getFinder(); if (!floater) @@ -903,19 +868,19 @@ void LLInventoryView::toggleFindOptions() } } -LLFolderView* LLInventoryView::getRootFolder() const +LLFolderView* LLPanelMainInventory::getRootFolder() const { return mActivePanel ? (mActivePanel->getRootFolder()) : NULL; } -void LLInventoryView::setSelectCallback(const LLFolderView::signal_t::slot_type& cb) +void LLPanelMainInventory::setSelectCallback(const LLFolderView::signal_t::slot_type& cb) { getChild("All Items")->setSelectCallback(cb); getChild("Recent Items")->setSelectCallback(cb); getChild("Worn Items")->setSelectCallback(cb); } -void LLInventoryView::onSelectionChange(LLInventoryPanel *panel, const std::deque& items, BOOL user_action) +void LLPanelMainInventory::onSelectionChange(LLInventoryPanel *panel, const std::deque& items, BOOL user_action) { panel->onSelectionChange(items, user_action); } @@ -924,7 +889,7 @@ void LLInventoryView::onSelectionChange(LLInventoryPanel *panel, const std::dequ /// LLFloaterInventoryFinder ///---------------------------------------------------------------------------- -LLFloaterInventoryFinder* LLInventoryView::getFinder() +LLFloaterInventoryFinder* LLPanelMainInventory::getFinder() { return (LLFloaterInventoryFinder*)mFinderHandle.get(); } @@ -932,12 +897,12 @@ LLFloaterInventoryFinder* LLInventoryView::getFinder() LLFloaterInventoryFinder::LLFloaterInventoryFinder(const std::string& name, const LLRect& rect, - LLInventoryView* inventory_view) : + LLPanelMainInventory* inventory_view) : LLFloater(name, rect, std::string("Filters"), RESIZE_NO, INV_FINDER_WIDTH, INV_FINDER_HEIGHT, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES), - mInventoryView(inventory_view), - mFilter(inventory_view->getPanel()->getFilter()) + mPanelMainInventory(inventory_view), + mFilter(&inventory_view->getPanel()->getFilter()) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory_view_finder.xml"); @@ -946,7 +911,7 @@ LLFloaterInventoryFinder::LLFloaterInventoryFinder(const std::string& name, BOOL LLFloaterInventoryFinder::postBuild() { - const LLRect& viewrect = mInventoryView->getRect(); + const LLRect& viewrect = mPanelMainInventory->getRect(); setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight())); childSetAction("All", selectAllTypes, this); @@ -958,23 +923,54 @@ BOOL LLFloaterInventoryFinder::postBuild() mSpinSinceDays = getChild("spin_days_ago"); childSetCommitCallback("spin_days_ago", onTimeAgo, this); + mRadioLinks = getChild("radio_links"); + mRadioLinks->setCommitCallback(std::bind(&LLFloaterInventoryFinder::onLinks, this, std::placeholders::_2)); + childSetAction("Close", onCloseBtn, this); updateElementsFromFilter(); return TRUE; } +void LLFloaterInventoryFinder::onLinks(const LLSD& val) +{ + auto value = val.asInteger(); + mFilter->setFilterLinks(value == 0 ? LLInventoryFilter::FILTERLINK_INCLUDE_LINKS : value == 1 ? LLInventoryFilter::FILTERLINK_EXCLUDE_LINKS : LLInventoryFilter::FILTERLINK_ONLY_LINKS); +} + void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data) { LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; if (!self) return; - bool since_logoff=true; if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) { - since_logoff = false; + self->getChild("check_since_logoff")->setValue(false); + + U32 days = (U32)self->mSpinSinceDays->get(); + U32 hours = (U32)self->mSpinSinceHours->get(); + if (hours >= 24) + { + // Try to handle both cases of spinner clicking and text input in a sensible fashion as best as possible. + // There is no way to tell if someone has clicked the spinner to get to 24 or input 24 manually, so in + // this case add to days. Any value > 24 means they have input the hours manually, so do not add to the + // current day value. + if (24 == hours) // Got to 24 via spinner clicking or text input of 24 + { + days = days + hours / 24; + } + else // Text input, so do not add to days + { + days = hours / 24; + } + hours = (U32)hours % 24; + self->mSpinSinceHours->setFocus(false); + self->mSpinSinceDays->setFocus(false); + self->mSpinSinceDays->set((F32)days); + self->mSpinSinceHours->set((F32)hours); + self->mSpinSinceHours->setFocus(true); + } } - self->childSetValue("check_since_logoff", since_logoff); } void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter) @@ -991,11 +987,13 @@ void LLFloaterInventoryFinder::updateElementsFromFilter() // Get data needed for filter display U32 filter_types = mFilter->getFilterObjectTypes(); std::string filter_string = mFilter->getFilterSubString(); + LLInventoryFilter::EFilterLink show_links = mFilter->getFilterLinks(); LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState(); U32 hours = mFilter->getHoursAgo(); + U32 date_search_direction = mFilter->getDateSearchDirection(); // update the ui elements - LLFloater::setTitle(mFilter->getName()); + setTitle(mFilter->getName()); getChild("check_animation")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION)); @@ -1009,10 +1007,14 @@ void LLFloaterInventoryFinder::updateElementsFromFilter() getChild("check_sound")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND)); getChild("check_texture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE)); getChild("check_snapshot")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT)); + getChild("check_show_links")->setValue(show_links == LLInventoryFilter::FILTERLINK_INCLUDE_LINKS); getChild("check_show_empty")->setValue(show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS); getChild("check_since_logoff")->setValue(mFilter->isSinceLogoff()); mSpinSinceHours->set((F32)(hours % 24)); mSpinSinceDays->set((F32)(hours / 24)); + auto value = mFilter->getFilterLinks(); + mRadioLinks->setValue(value == LLInventoryFilter::FILTERLINK_INCLUDE_LINKS ? 0 : value == LLInventoryFilter::FILTERLINK_EXCLUDE_LINKS ? 1 : 2); + getChild("date_search_direction")->setSelectedIndex(date_search_direction); } void LLFloaterInventoryFinder::draw() @@ -1091,16 +1093,19 @@ void LLFloaterInventoryFinder::draw() filtered_by_all_types = FALSE; } - if (!filtered_by_all_types) + if (!filtered_by_all_types || (mPanelMainInventory->getPanel()->getFilter().getFilterTypes() & LLInventoryFilter::FILTERTYPE_DATE)) { - // don't include folders in filter, unless I've selected everything + // don't include folders in filter, unless I've selected everything or filtering by date filter &= ~(0x1 << LLInventoryType::IT_CATEGORY); } // update the panel, panel will update the filter - mInventoryView->getPanel()->setShowFolderState(getCheckShowEmpty() ? + mPanelMainInventory->getPanel()->setFilterLinks(getCheckShowLinks() ? + LLInventoryFilter::FILTERLINK_INCLUDE_LINKS : LLInventoryFilter::FILTERLINK_EXCLUDE_LINKS); + + mPanelMainInventory->getPanel()->setShowFolderState(getCheckShowEmpty() ? LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mInventoryView->getPanel()->setFilterTypes(filter); + mPanelMainInventory->getPanel()->setFilterTypes(filter); if (getCheckSinceLogoff()) { mSpinSinceDays->set(0); @@ -1108,7 +1113,7 @@ void LLFloaterInventoryFinder::draw() } U32 days = (U32)mSpinSinceDays->get(); U32 hours = (U32)mSpinSinceHours->get(); - if (hours > 24) + if (hours >= 24) { days += hours / 24; hours = (U32)hours % 24; @@ -1116,38 +1121,49 @@ void LLFloaterInventoryFinder::draw() mSpinSinceHours->set((F32)hours); } hours += days * 24; - mInventoryView->getPanel()->setHoursAgo(hours); - mInventoryView->getPanel()->setSinceLogoff(getCheckSinceLogoff()); - mInventoryView->setFilterTextFromFilter(); + mPanelMainInventory->getPanel()->setHoursAgo(hours); + mPanelMainInventory->getPanel()->setSinceLogoff(getCheckSinceLogoff()); + mPanelMainInventory->setFilterTextFromFilter(); + mPanelMainInventory->getPanel()->setDateSearchDirection(getDateSearchDirection()); LLFloater::draw(); } void LLFloaterInventoryFinder::onClose(bool app_quitting) { - if (mInventoryView) mInventoryView->getControl("Inventory.ShowFilters")->setValue(FALSE); + if (mPanelMainInventory) mPanelMainInventory->getControl("Inventory.ShowFilters")->setValue(FALSE); // If you want to reset the filter on close, do it here. This functionality was // hotly debated - Paulm #if 0 - if (mInventoryView) + if (mPanelMainInventory) { - LLInventoryView::onResetFilter((void *)mInventoryView); + LLPanelMainInventory::onResetFilter((void *)mPanelMainInventory); } #endif destroy(); } +BOOL LLFloaterInventoryFinder::getCheckShowLinks() +{ + return getChild("check_show_links")->getValue(); +} BOOL LLFloaterInventoryFinder::getCheckShowEmpty() { return getChild("check_show_empty")->getValue(); } + BOOL LLFloaterInventoryFinder::getCheckSinceLogoff() { return getChild("check_since_logoff")->getValue(); } +U32 LLFloaterInventoryFinder::getDateSearchDirection() +{ + return getChild("date_search_direction")->getSelectedIndex(); +} + void LLFloaterInventoryFinder::onCloseBtn(void* user_data) { LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data; diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 0b258ac8b5..2f74cbda2e 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -1,4 +1,4 @@ -/** + /** * @file llpanelmaininventory.h * @brief llpanelmaininventory.h * class definition @@ -46,22 +46,22 @@ class LLFilterEditor; class LLComboBox; class LLFloaterInventoryFinder; -class LLInventoryView : public LLFloater, LLInventoryObserver +class LLPanelMainInventory : public LLFloater, LLInventoryObserver { friend class LLFloaterInventoryFinder; public: - LLInventoryView(const std::string& name, const std::string& rect, + LLPanelMainInventory(const std::string& name, const std::string& rect, LLInventoryModel* inventory); - LLInventoryView(const std::string& name, const LLRect& rect, + LLPanelMainInventory(const std::string& name, const LLRect& rect, LLInventoryModel* inventory); - ~LLInventoryView(); + ~LLPanelMainInventory(); BOOL postBuild(); //TODO: Move these statics. - static LLInventoryView* showAgentInventory(BOOL take_keyboard_focus=FALSE); - static LLInventoryView* getActiveInventory(); + static LLPanelMainInventory* showAgentInventory(BOOL take_keyboard_focus=FALSE); + static LLPanelMainInventory* getActiveInventory(); static void toggleVisibility(); static void toggleVisibility(void*) { toggleVisibility(); } // Final cleanup, destroy all open inventory views. @@ -80,9 +80,8 @@ friend class LLFloaterInventoryFinder; void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); - /*virtual*/ void changed(U32 mask); + /*virtual*/ void changed(U32); /*virtual*/ void draw(); - LLInventoryPanel* getPanel() { return mActivePanel; } LLInventoryPanel* getActivePanel() { return mActivePanel; } @@ -92,6 +91,7 @@ friend class LLFloaterInventoryFinder; const std::string& getFilterText() const { return mFilterText; } void setSelectCallback(const LLFolderView::signal_t::slot_type& cb); + void onFilterEdit(const std::string& search_string); // // Misc functions @@ -103,25 +103,21 @@ friend class LLFloaterInventoryFinder; void onSelectionChange(LLInventoryPanel *panel, const std::deque& items, BOOL user_action); static BOOL filtersVisible(void* user_data); - void onClearSearch(); static void onFoldersByName(void *user_data); static BOOL checkFoldersByName(void *user_data); - void onFilterSelected(); const std::string getFilterSubString(); void setFilterSubString(const std::string& string); - - static void onQuickFilterCommit(LLUICtrl* ctrl, void* user_data); static void refreshQuickFilter(LLUICtrl* ctrl); - + static void onResetAll(void* userdata); static void onExpandAll(void* userdata); - static void onCollapseAll(void* userdata); - + static void onCollapseAll(void* userdata); + void updateSortControls(); void resetFilters(); @@ -132,7 +128,7 @@ friend class LLFloaterInventoryFinder; { // If there are mulitple inventory floaters open then clicking the "Inventory" button will close // them one by one (see LLToolBar::onClickInventory() => toggleVisibility() ) until we get to the - // last one which will just be hidden instead of closed/destroyed (see LLInventoryView::onClose) + // last one which will just be hidden instead of closed/destroyed (see LLPanelMainInventory::onClose) // // However the view isn't removed from sActiveViews until its destructor is called and since // 'LLMortician::sDestroyImmediate == FALSE' while the viewer is running the destructor won't be @@ -143,7 +139,7 @@ friend class LLFloaterInventoryFinder; // // Workaround: "fix" onClose() to count only views that aren't marked as "dead" - LLInventoryView* pView; U8 flagsSound; + LLPanelMainInventory* pView; U8 flagsSound; for (S32 idx = sActiveViews.size() - 1; idx >= 0; idx--) { pView = sActiveViews.at(idx); @@ -162,23 +158,22 @@ friend class LLFloaterInventoryFinder; protected: LLFloaterInventoryFinder* getFinder(); + LLFilterEditor* mFilterEditor; LLComboBox* mQuickFilterCombo; LLTabContainer* mFilterTabs; LLHandle mFinderHandle; LLInventoryPanel* mActivePanel; bool mResortActivePanel; - LLSaveFolderState* mSavedFolderState; std::string mFilterText; //std::string mFilterSubString; // This container is used to hold all active inventory views. This // is here to support the inventory toggle show button. - static std::vector sActiveViews; + static std::vector sActiveViews; }; - #endif // LL_LLPANELMAININVENTORY_H diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp deleted file mode 100644 index 9932c86415..0000000000 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @file llpanelmarketplaceoutboxinventory.cpp - * @brief LLOutboxInventoryPanel class definition - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelmarketplaceoutboxinventory.h" - -//#include "llfolderview.h" -//#include "llfoldervieweventlistener.h" -#include "llinventorybridge.h" -//#include "llinventoryfunctions.h" -#include "lltrans.h" -//#include "llviewerfoldertype.h" - - -// -// statics -// - -static LLRegisterWidget r1("outbox_inventory_panel"); -//static LLRegisterWidget r2("outbox_folder_view_folder"); - -// -// LLOutboxInventoryPanel Implementation -// - -LLOutboxInventoryPanel::LLOutboxInventoryPanel(const std::string& name, - const std::string& sort_order_setting, - const std::string& start_folder, - const LLRect& rect, - LLInventoryModel* inventory, - BOOL allow_multi_select, - LLView* parent_view) - : LLInventoryPanel(name, sort_order_setting, start_folder, rect, inventory, allow_multi_select, parent_view) -{ -} - -LLOutboxInventoryPanel::~LLOutboxInventoryPanel() -{ -} - -// virtual -void LLOutboxInventoryPanel::buildFolderView(/*const LLInventoryPanel::Params& params*/) -{ - // Determine the root folder in case specified, and - // build the views starting with that folder. - - LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); - - if (root_id == LLUUID::null) - { - LL_WARNS() << "Outbox inventory panel has no root folder!" << LL_ENDL; - root_id = LLUUID::generateNewID(); - } - - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, - LLAssetType::AT_CATEGORY, - LLInventoryType::IT_CATEGORY, - this, - NULL, - root_id); - - mFolderRoot = createFolderView(new_listener, true/*params.use_label_suffix()*/)->getHandle(); -} - -LLFolderViewFolder * LLOutboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge) -{ - return new LLOutboxFolderViewFolder( - bridge->getDisplayName(), - bridge->getIcon(), - bridge->getIconOpen(), - LLUI::getUIImage("inv_link_overlay.tga"), - mFolderRoot.get(), - bridge); -} - -LLFolderViewItem * LLOutboxInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge) -{ - return new LLOutboxFolderViewItem( - bridge->getDisplayName(), - bridge->getIcon(), - bridge->getIconOpen(), - LLUI::getUIImage("inv_link_overlay.tga"), - bridge->getCreationDate(), - mFolderRoot.get(), - bridge); -} - -// -// LLOutboxFolderViewFolder Implementation -// - -LLOutboxFolderViewFolder::LLOutboxFolderViewFolder(const std::string& name, LLUIImagePtr icon, - LLUIImagePtr icon_open, - LLUIImagePtr icon_link, - LLFolderView* root, - LLFolderViewEventListener* listener) - : LLFolderViewFolder(name, icon, icon_open, icon_link, root, listener) -{ -} - -// -// LLOutboxFolderViewItem Implementation -// - -LLOutboxFolderViewItem::LLOutboxFolderViewItem(const std::string& name, LLUIImagePtr icon, - LLUIImagePtr icon_open, - LLUIImagePtr icon_overlay, - S32 creation_date, - LLFolderView* root, - LLFolderViewEventListener* listener) - : LLFolderViewItem(name, icon, icon_open, icon_overlay, creation_date, root, listener) -{ -} - -BOOL LLOutboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) -{ - return TRUE; -} - -void LLOutboxFolderViewItem::openItem() -{ - // Intentionally do nothing to block attaching items from the outbox -} - -// eof diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.h b/indra/newview/llpanelmarketplaceoutboxinventory.h deleted file mode 100644 index 0eee7ed9e6..0000000000 --- a/indra/newview/llpanelmarketplaceoutboxinventory.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @file llpanelmarketplaceoutboxinventory.h - * @brief LLOutboxInventoryPanel class declaration - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_OUTBOXINVENTORYPANEL_H -#define LL_OUTBOXINVENTORYPANEL_H - - -#include "llinventorypanel.h" -#include "llfolderviewitem.h" - - -class LLOutboxInventoryPanel : public LLInventoryPanel -{ -public: - LLOutboxInventoryPanel(const std::string& name, - const std::string& sort_order_setting, - const std::string& start_folder, - const LLRect& rect, - LLInventoryModel* inventory, - BOOL allow_multi_select, - LLView *parent_view = NULL); - ~LLOutboxInventoryPanel(); - - // virtual - void buildFolderView(/*const LLInventoryPanel::Params& params*/); - - // virtual - LLFolderViewFolder * createFolderViewFolder(LLInvFVBridge * bridge); - LLFolderViewItem * createFolderViewItem(LLInvFVBridge * bridge); -}; - - -class LLOutboxFolderViewFolder : public LLFolderViewFolder -{ -public: - LLOutboxFolderViewFolder(const std::string& name, LLUIImagePtr icon, LLUIImagePtr icon_open, LLUIImagePtr icon_link, LLFolderView* root, LLFolderViewEventListener* listener); -}; - - -class LLOutboxFolderViewItem : public LLFolderViewItem -{ -public: - LLOutboxFolderViewItem(const std::string& name, LLUIImagePtr icon, LLUIImagePtr icon_open, LLUIImagePtr icon_overlay, S32 creation_date, LLFolderView* root, LLFolderViewEventListener* listener); - - // virtual - BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - void openItem(); -}; - - -#endif //LL_OUTBOXINVENTORYPANEL_H diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index f8ede13ba9..7372064c43 100644 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -467,7 +467,7 @@ bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace(bool only_if_current_ bool all_face_media_navigated = false; LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection(); - selected_objects->getSelectedTEValue( &functor_navigate_media, all_face_media_navigated ); + (void)selected_objects->getSelectedTEValue( &functor_navigate_media, all_face_media_navigated ); // Note: we don't update the 'current URL' field until the media data itself changes diff --git a/indra/newview/llpanelmediasettingspermissions.cpp b/indra/newview/llpanelmediasettingspermissions.cpp index d9e5d4ad27..2b0043372a 100644 --- a/indra/newview/llpanelmediasettingspermissions.cpp +++ b/indra/newview/llpanelmediasettingspermissions.cpp @@ -101,15 +101,15 @@ void LLPanelMediaSettingsPermissions::draw() { if(mPermsGroupName) { - mPermsGroupName->setNameID(group_id, true); + mPermsGroupName->setNameID(group_id, LFIDBearer::GROUP); } } else { if(mPermsGroupName) { - mPermsGroupName->setNameID(LLUUID::null, TRUE); - mPermsGroupName->refresh(LLUUID::null, std::string(), true); + mPermsGroupName->setNameID(LLUUID::null, LFIDBearer::GROUP); + mPermsGroupName->refresh(LLUUID::null, std::string()); } } } diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index c578c9a8d3..9503de65f9 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -76,13 +76,24 @@ static const LLUUID PARCEL_AUDIO_LIST_ITEM_UUID = LLUUID("DF4B020D-8A24-4B95-AB5 LLPanelNearByMedia::LLPanelNearByMedia(bool standalone_panel) -: mMediaList(NULL), - mEnableAllCtrl(NULL), - mAllMediaDisabled(false), - mDebugInfoVisible(false), - mParcelMediaItem(NULL), - mParcelAudioItem(NULL), - mStandalonePanel(standalone_panel) + : mNearbyMediaPanel(nullptr) + , mMediaList(nullptr) + , mEnableAllCtrl(nullptr) + , mDisableAllCtrl(nullptr) + , mShowCtrl(nullptr) + , mStopCtrl(nullptr) + , mPlayCtrl(nullptr) + , mPauseCtrl(nullptr) + , mMuteCtrl(nullptr) + , mVolumeSliderCtrl(nullptr) + , mZoomCtrl(nullptr) + , mUnzoomCtrl(nullptr) + , mVolumeSlider(nullptr) + , mMuteBtn(nullptr) + , mDebugInfoVisible(false) + , mParcelMediaItem(nullptr) + , mParcelAudioItem(nullptr) + , mStandalonePanel(standalone_panel) { mHoverTimer.stop(); diff --git a/indra/newview/llpanelnearbymedia.h b/indra/newview/llpanelnearbymedia.h index 410dfb48c5..8b5bbdc357 100644 --- a/indra/newview/llpanelnearbymedia.h +++ b/indra/newview/llpanelnearbymedia.h @@ -165,7 +165,6 @@ class LLPanelNearByMedia : public LLPanel LLSlider* mVolumeSlider; LLButton* mMuteBtn; - bool mAllMediaDisabled; bool mDebugInfoVisible; bool mParcelAudioAutoStart; std::string mEmptyNameString; diff --git a/indra/newview/llpanelnetwork.cpp b/indra/newview/llpanelnetwork.cpp index 414c9275f0..ebf19eb5fb 100644 --- a/indra/newview/llpanelnetwork.cpp +++ b/indra/newview/llpanelnetwork.cpp @@ -74,17 +74,32 @@ BOOL LLPanelNetwork::postBuild() } childSetValue("max_bandwidth", gSavedSettings.getF32("ThrottleBandwidthKBPS")); childSetValue("tex_bandwidth", gSavedSettings.getF32("HTTPThrottleBandwidth")); - childSetValue("http_textures", gSavedSettings.getBOOL("ImagePipelineUseHTTP")); - childSetValue("http_inventory", gSavedSettings.getBOOL("UseHTTPInventory")); childSetValue("connection_port_enabled", gSavedSettings.getBOOL("ConnectionPortEnabled")); childSetValue("connection_port", (F32)gSavedSettings.getU32("ConnectionPort")); - // If in Avination, hide the texture bandwidth slider, Avination throttles server-side - if (gHippoGridManager->getConnectedGrid()->isAvination()) + const auto& grid = gHippoGridManager->getConnectedGrid(); + if (!grid->isSecondLife()) { - childSetVisible("text_box4", FALSE); - childSetVisible("tex_bandwidth", FALSE); - childSetVisible("text_box3", FALSE); + if (auto view = getChildView("use_http_for")) + view->setVisible(true); + if (auto view = getChildView("http_textures")) + { + view->setVisible(true); + view->setValue(gSavedSettings.getBOOL("ImagePipelineUseHTTP")); + } + if (auto view = getChildView("http_inventory")) + { + view->setVisible(true); + view->setValue(gSavedSettings.getBOOL("UseHTTPInventory")); + } + + // If in Avination, hide the texture bandwidth slider, Avination throttles server-side + if (grid->isAvination()) + { + childSetVisible("text_box4", FALSE); + childSetVisible("tex_bandwidth", FALSE); + childSetVisible("text_box3", FALSE); + } } // Socks 5 proxy settings, commit callbacks @@ -124,9 +139,15 @@ void LLPanelNetwork::apply() { gSavedSettings.setU32("CacheSize", childGetValue("cache_size").asInteger()); gSavedSettings.setF32("ThrottleBandwidthKBPS", childGetValue("max_bandwidth").asReal()); - gSavedSettings.setF32("HTTPThrottleBandwidth", childGetValue("tex_bandwidth").asReal()); - gSavedSettings.setBOOL("ImagePipelineUseHTTP", childGetValue("http_textures")); - gSavedSettings.setBOOL("UseHTTPInventory", childGetValue("http_inventory")); + if (const auto& view = getChildView("tex_bandwidth")) + if (view->getVisible()) + gSavedSettings.setF32("HTTPThrottleBandwidth", view->getValue().asReal()); + if (const auto& view = getChildView("http_textures")) + if (view->getVisible()) + gSavedSettings.setBOOL("ImagePipelineUseHTTP", view->getValue()); + if (const auto& view = getChildView("http_inventory")) + if (view->getVisible()) + gSavedSettings.setBOOL("UseHTTPInventory", view->getValue()); gSavedSettings.setBOOL("ConnectionPortEnabled", childGetValue("connection_port_enabled")); gSavedSettings.setU32("ConnectionPort", childGetValue("connection_port").asInteger()); @@ -161,8 +182,11 @@ void LLPanelNetwork::cancel() void LLPanelNetwork::onClickClearCache(void*) { // flag client cache for clearing next time the client runs - gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE); - LLNotificationsUtil::add("CacheWillClear"); + if (!gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) + { + gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE); + LLNotificationsUtil::add("CacheWillClear"); + } } // static diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index e7fef5ebf3..e9d82f8c01 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -36,7 +36,6 @@ #include "llpanelobject.h" // linden library includes -#include "lleconomy.h" #include "llerror.h" #include "llfontgl.h" #include "llpermissionsflags.h" @@ -130,10 +129,10 @@ LLVector3 LLPanelObject::mClipboardPos; LLVector3 LLPanelObject::mClipboardSize; LLVector3 LLPanelObject::mClipboardRot; LLVolumeParams LLPanelObject::mClipboardVolumeParams; -LLFlexibleObjectData* LLPanelObject::mClipboardFlexiParams = NULL; -LLLightParams* LLPanelObject::mClipboardLightParams = NULL; -LLSculptParams* LLPanelObject::mClipboardSculptParams = NULL; -LLLightImageParams* LLPanelObject::mClipboardLightImageParams = NULL; +const LLFlexibleObjectData* LLPanelObject::mClipboardFlexiParams = NULL; +const LLLightParams* LLPanelObject::mClipboardLightParams = NULL; +const LLSculptParams* LLPanelObject::mClipboardSculptParams = NULL; +const LLLightImageParams* LLPanelObject::mClipboardLightImageParams = NULL; BOOL LLPanelObject::hasParamClipboard = FALSE; BOOL LLPanelObject::postBuild() @@ -895,7 +894,7 @@ void LLPanelObject::getState( ) } - if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + if (objectp->getSculptParams()) { selected_item = MI_SCULPT; LLFirstUse::useSculptedPrim(); @@ -1398,7 +1397,7 @@ void LLPanelObject::getState( ) LLUUID id; - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = objectp->getSculptParams(); if (sculpt_params) // if we have a legal sculpt param block for this object: @@ -1574,13 +1573,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); + const 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); + const LLSculptParams *sculpt_params = self->mObject->getSculptParams(); if (sculpt_params) self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, TRUE); } @@ -2141,17 +2140,17 @@ void LLPanelObject::sendSculpt() return; LLSculptParams sculpt_params; + LLUUID sculpt_id = LLUUID::null; if (mCtrlSculptTexture) - sculpt_params.setSculptTexture(mCtrlSculptTexture->getImageAssetID()); + sculpt_id = mCtrlSculptTexture->getImageAssetID(); U8 sculpt_type = 0; if (mCtrlSculptType) sculpt_type |= mCtrlSculptType->getCurrentIndex(); - bool enabled = true; - enabled = sculpt_type != LL_SCULPT_TYPE_MESH; + bool enabled = sculpt_type != LL_SCULPT_TYPE_MESH; if (mCtrlSculptMirror) { @@ -2168,7 +2167,7 @@ void LLPanelObject::sendSculpt() if ((mCtrlSculptInvert) && (mCtrlSculptInvert->get())) sculpt_type |= LL_SCULPT_FLAG_INVERT; - sculpt_params.setSculptType(sculpt_type); + sculpt_params.setSculptTexture(sculpt_id, sculpt_type); mObject->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); } @@ -2463,16 +2462,16 @@ void LLPanelObject::onCopyParams(void* user_data) LLViewerObject* objp = self->mObject; - mClipboardFlexiParams = objp->getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE) ? static_cast(objp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE)) : NULL; - mClipboardLightParams = objp->getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT) ? static_cast(objp->getParameterEntry(LLNetworkData::PARAMS_LIGHT)) : NULL; - mClipboardSculptParams = objp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT) ? static_cast(objp->getParameterEntry(LLNetworkData::PARAMS_SCULPT)) : NULL; + mClipboardFlexiParams = objp->getFlexibleObjectData(); + mClipboardLightParams = objp->getLightParams(); + mClipboardSculptParams = objp->getSculptParams(); if (mClipboardSculptParams) { const LLUUID id = mClipboardSculptParams->getSculptTexture(); if (id != LLUUID(SCULPT_DEFAULT_TEXTURE) && !texturePermsCheck(id)) mClipboardSculptParams = NULL; } - mClipboardLightImageParams = objp->getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE) ? static_cast(objp->getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE)) : NULL; + mClipboardLightImageParams = objp->getLightImageParams(); if (mClipboardLightImageParams && texturePermsCheck(mClipboardLightImageParams->getLightTexture())) { mClipboardLightImageParams = NULL; diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index e988087476..18877663c3 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -122,10 +122,10 @@ class LLPanelObject : public LLPanel static LLVector3 mClipboardSize; static LLVector3 mClipboardRot; static LLVolumeParams mClipboardVolumeParams; - static LLFlexibleObjectData* mClipboardFlexiParams; - static LLLightParams* mClipboardLightParams; - static LLSculptParams* mClipboardSculptParams; - static LLLightImageParams* mClipboardLightImageParams; + static const LLFlexibleObjectData* mClipboardFlexiParams; + static const LLLightParams* mClipboardLightParams; + static const LLSculptParams* mClipboardSculptParams; + static const LLLightImageParams* mClipboardLightImageParams; static BOOL hasParamClipboard; S32 mComboMaterialItemCount; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 7e0f9c198d..09a6a77cdc 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -40,6 +40,7 @@ #include "roles_constants.h" #include "llagent.h" +#include "llavataractions.h" #include "llcallbacklist.h" #include "llfloaterbuycontents.h" #include "llfloaterbuycurrency.h" @@ -130,7 +131,7 @@ class LLTaskInvFVBridge : public LLFolderViewEventListener virtual void move(LLFolderViewEventListener* parent_listener); virtual BOOL isItemCopyable() const; virtual BOOL copyToClipboard() const; - virtual void cutToClipboard(); + virtual BOOL cutToClipboard(); virtual BOOL isClipboardPasteable() const; virtual void pasteFromClipboard(bool only_copies = false); virtual void pasteLinkFromClipboard(); @@ -138,8 +139,8 @@ class LLTaskInvFVBridge : public LLFolderViewEventListener virtual void performAction(LLInventoryModel* model, std::string action); virtual BOOL isUpToDate() const { return TRUE; } virtual bool hasChildren() const { return FALSE; } - virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } - virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } + virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::EType::IT_NONE; } + virtual LLWearableType::EType getWearableType() const { return LLWearableType::EType::WT_NONE; } // LLDragAndDropBridge functionality virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; @@ -160,7 +161,7 @@ LLTaskInvFVBridge::LLTaskInvFVBridge( mPanel(panel), mFlags(flags), mAssetType(LLAssetType::AT_NONE), - mInventoryType(LLInventoryType::IT_NONE) + mInventoryType(LLInventoryType::EType::IT_NONE) { const LLInventoryItem *item = findItem(); if (item) @@ -203,27 +204,11 @@ void LLTaskInvFVBridge::showProperties() } } -struct LLBuyInvItemData -{ - LLUUID mTaskID; - LLUUID mItemID; - LLAssetType::EType mType; - - LLBuyInvItemData(const LLUUID& task, - const LLUUID& item, - LLAssetType::EType type) : - mTaskID(task), mItemID(item), mType(type) - {} -}; - void LLTaskInvFVBridge::buyItem() { LL_INFOS() << "LLTaskInvFVBridge::buyItem()" << LL_ENDL; LLInventoryItem* item = findItem(); if(!item || !item->getSaleInfo().isForSale()) return; - LLBuyInvItemData* inv = new LLBuyInvItemData(mPanel->getTaskUUID(), - mUUID, - item->getType()); const LLSaleInfo& sale_info = item->getSaleInfo(); const LLPermissions& perm = item->getPermissions(); @@ -234,7 +219,6 @@ void LLTaskInvFVBridge::buyItem() { LLNotificationsUtil::add("Cannot_Purchase_an_Attachment"); LL_INFOS() << "Attempt to purchase an attachment" << LL_ENDL; - delete inv; } else { @@ -265,9 +249,9 @@ void LLTaskInvFVBridge::buyItem() } LLSD payload; - payload["task_id"] = inv->mTaskID; - payload["item_id"] = inv->mItemID; - payload["type"] = inv->mType; + payload["task_id"] = mPanel->getTaskUUID(); + payload["item_id"] = mUUID; + payload["type"] = item->getType(); LLNotificationsUtil::add(alertdesc, args, payload, LLTaskInvFVBridge::commitBuyItem); } } @@ -495,12 +479,9 @@ bool remove_task_inventory_callback(const LLSD& notification, const LLSD& respon if(option == 0 && object) { // yes - LLSD::array_const_iterator list_end = notification["payload"]["inventory_ids"].endArray(); - for (LLSD::array_const_iterator list_it = notification["payload"]["inventory_ids"].beginArray(); - list_it != list_end; - ++list_it) + for (auto const& entry : notification["payload"]["inventory_ids"].array()) { - object->removeInventory(list_it->asUUID()); + object->removeInventory(entry.asUUID()); } // refresh the UI. @@ -596,8 +577,9 @@ BOOL LLTaskInvFVBridge::copyToClipboard() const return FALSE; } -void LLTaskInvFVBridge::cutToClipboard() +BOOL LLTaskInvFVBridge::cutToClipboard() { + return FALSE; } BOOL LLTaskInvFVBridge::isClipboardPasteable() const @@ -605,7 +587,7 @@ BOOL LLTaskInvFVBridge::isClipboardPasteable() const return FALSE; } -void LLTaskInvFVBridge::pasteFromClipboard(bool only_copies) +void LLTaskInvFVBridge::pasteFromClipboard(bool) { } @@ -666,11 +648,6 @@ BOOL LLTaskInvFVBridge::dragOrDrop(MASK mask, BOOL drop, return FALSE; } -//void LLTaskInvFVBridge::dropped() -//{ -// LL_WARNS() << "LLTaskInvFVBridge::dropped() - not implemented" << LL_ENDL; -//} - void pack_script_message(LLMessageSystem*, const LLInventoryItem*, const LLViewerObject*); void reset_script(const LLInventoryItem* item, const LLViewerObject* obj) @@ -760,7 +737,7 @@ void LLTaskInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) return; } - if(gAgent.allowOperation(PERM_OWNER, item->getPermissions(), + if(!gAgent.allowOperation(PERM_OWNER, item->getPermissions(), GP_OBJECT_MANIPULATE) && item->getSaleInfo().isForSale()) { @@ -979,16 +956,6 @@ BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop, case DAD_CALLINGCARD: case DAD_MESH: accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data); - // testzone - //if(LLToolDragAndDrop::isInventoryDropAcceptable( - // object, (LLViewerInventoryItem*)cargo_data) - /*if(object->permModify() - // - && (LLToolDragAndDrop::SOURCE_WORLD != LLToolDragAndDrop::getInstance()->getSource()) - && (LLToolDragAndDrop::SOURCE_NOTECARD != LLToolDragAndDrop::getInstance()->getSource())) - { - accept = TRUE; - }*/ if(accept && drop) { LLToolDragAndDrop::dropInventory(object, @@ -1171,7 +1138,6 @@ void LLTaskSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else if (canOpenItem()) { - //items.push_back(std::string("Task Open")); if (!isItemCopyable()) { disabled_items.push_back(std::string("Task Open")); @@ -1237,6 +1203,7 @@ BOOL LLTaskCallingCardBridge::renameItem(const std::string& new_name) return FALSE; } + ///---------------------------------------------------------------------------- /// Class LLTaskScriptBridge ///---------------------------------------------------------------------------- @@ -1664,7 +1631,7 @@ void LLPanelObjectInventory::clearContents() if( mScroller ) { // removes mFolders - removeChild( mScroller ); + removeChild( mScroller ); //*TODO: Really shouldn't do this during draw()/refresh() mScroller->die(); mScroller = NULL; mFolders = NULL; @@ -1681,7 +1648,7 @@ void LLPanelObjectInventory::reset() LLRect dummy_rect(0, 1, 1, 0); mFolders = new LLFolderView(std::string("task inventory"), dummy_rect, getTaskUUID(), this, LLTaskInvFVBridge::createObjectBridge(this, NULL)); // this ensures that we never say "searching..." or "no items found" - mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + mFolders->getFilter().setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); LLRect scroller_rect(0, getRect().getHeight(), getRect().getWidth(), 0); mScroller = new LLScrollContainer(std::string("task inventory scroller"), scroller_rect, mFolders ); @@ -1740,35 +1707,35 @@ void LLPanelObjectInventory::updateInventory() // << " panel UUID: " << panel->mTaskUUID << "\n" // << " task UUID: " << object->mID << LL_ENDL; // We're still interested in this task's inventory. - std::set selected_items; + uuid_set_t selected_items; BOOL inventory_has_focus = FALSE; - if (mHaveInventory) + if (mHaveInventory && mFolders) { selected_items = mFolders->getSelectionList(); inventory_has_focus = gFocusMgr.childHasKeyboardFocus(mFolders); } - reset(); - LLViewerObject* objectp = gObjectList.findObject(mTaskUUID); if (objectp) { LLInventoryObject* inventory_root = objectp->getInventoryRoot(); LLInventoryObject::object_list_t contents; objectp->getInventoryContents(contents); + if (inventory_root) { - createFolderViews(inventory_root, contents); - mHaveInventory = TRUE; + reset(); mIsInventoryEmpty = FALSE; + createFolderViews(inventory_root, contents); mFolders->setEnabled(TRUE); } else { // TODO: create an empty inventory mIsInventoryEmpty = TRUE; - mHaveInventory = TRUE; } + + mHaveInventory = TRUE; } else { @@ -1778,11 +1745,11 @@ void LLPanelObjectInventory::updateInventory() } // restore previous selection - std::set::iterator selection_it; - BOOL first_item = TRUE; - for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it) + bool first_item = true; + for (const auto id : selected_items) { - LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it); + LLFolderViewItem* selected_item = mFolders->getItemByID(id); + if (selected_item) { //HACK: "set" first item then "change" each other one to get keyboard focus right @@ -1798,8 +1765,12 @@ void LLPanelObjectInventory::updateInventory() } } - mFolders->requestArrange(); + if (mFolders) + { + mFolders->requestArrange(); + } mInventoryNeedsUpdate = FALSE; + // Edit menu handler is set in onFocusReceived } // *FIX: This is currently a very expensive operation, because we have @@ -1941,13 +1912,18 @@ void LLPanelObjectInventory::refresh() } if(!has_inventory) { - mTaskUUID = LLUUID::null; - removeVOInventoryListener(); - clearContents(); + clearInventoryTask(); } //LL_INFOS() << "LLPanelObjectInventory::refresh() " << mTaskUUID << LL_ENDL; } +void LLPanelObjectInventory::clearInventoryTask() +{ + mTaskUUID = LLUUID::null; + removeVOInventoryListener(); + clearContents(); +} + void LLPanelObjectInventory::removeSelectedItem() { if(mFolders) @@ -2032,7 +2008,6 @@ void LLPanelObjectInventory::idle(void* user_data) { LLPanelObjectInventory* self = (LLPanelObjectInventory*)user_data; - if (self->mInventoryNeedsUpdate) { self->updateInventory(); diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 736900c76a..e43c1b37fa 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -52,6 +52,7 @@ class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener void refresh(); const LLUUID& getTaskUUID() { return mTaskUUID;} + void clearInventoryTask(); void removeSelectedItem(); void startRenamingSelectedItem(); @@ -77,7 +78,6 @@ class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener void createViewsForCategory(LLInventoryObject::object_list_t* inventory, LLInventoryObject* parent, LLFolderViewFolder* folder); - void clearContents(); private: diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index d881f1b165..9d82fb8d45 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -69,10 +69,6 @@ -// [RLVa:KB] -#include "rlvhandler.h" -// [/RLVa:KB] - // base and own must have EXPORT, next owner must be UNRESTRICTED bool can_set_export(const U32& base, const U32& own, const U32& next) { @@ -117,13 +113,7 @@ BOOL LLPanelPermissions::postBuild() childSetCommitCallback("Object Description",LLPanelPermissions::onCommitDesc,this); getChild("Object Description")->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe); - - getChild("button owner profile")->setCommitCallback(boost::bind(&LLPanelPermissions::onClickOwner,this)); - getChild("button last owner profile")->setCommitCallback(boost::bind(&LLPanelPermissions::onClickLastOwner,this)); - getChild("button creator profile")->setCommitCallback(boost::bind(&LLPanelPermissions::onClickCreator,this)); - getChild("button set group")->setCommitCallback(boost::bind(&LLPanelPermissions::onClickGroup,this)); - getChild("button open group")->setCommitCallback(boost::bind(LLPanelPermissions::onClickOpenGroup)); childSetCommitCallback("checkbox share with group",LLPanelPermissions::onCommitGroupShare,this); @@ -182,25 +172,33 @@ void LLPanelPermissions::disableAll() getChild("pathfinding_attributes_value")->setValue(LLStringUtil::null); getChildView("Creator:")->setEnabled(FALSE); - getChild("Creator Name")->setValue(LLStringUtil::null); - getChildView("Creator Name")->setEnabled(FALSE); - getChildView("button creator profile")->setEnabled(FALSE); + if (auto view = getChildView("Creator Name")) + { + view->setValue(LLUUID::null); + view->setEnabled(FALSE); + } getChildView("Owner:")->setEnabled(FALSE); - getChild("Owner Name")->setValue(LLStringUtil::null); - getChildView("Owner Name")->setEnabled(FALSE); - getChildView("button owner profile")->setEnabled(FALSE); + if (auto view = getChildView("Owner Name")) + { + view->setValue(LLUUID::null); + view->setEnabled(FALSE); + } getChildView("Last Owner:")->setEnabled(FALSE); - getChild("Last Owner Name")->setValue(LLStringUtil::null); - getChildView("Last Owner Name")->setEnabled(FALSE); - getChildView("button last owner profile")->setEnabled(FALSE); - + if (auto view = getChildView("Last Owner Name")) + { + view->setValue(LLUUID::null); + view->setEnabled(FALSE); + } + getChildView("Group:")->setEnabled(FALSE); - getChild("Group Name Proxy")->setValue(LLStringUtil::null); - getChildView("Group Name Proxy")->setEnabled(FALSE); + if (mLabelGroupName) + { + mLabelGroupName->setNameID(LLUUID::null, LFIDBearer::GROUP); + mLabelGroupName->setEnabled(FALSE); + } getChildView("button set group")->setEnabled(FALSE); - getChildView("button open group")->setEnabled(FALSE); LLLineEditor* ed = getChild("Object Name"); ed->setValue(LLStringUtil::null); @@ -329,7 +327,7 @@ void LLPanelPermissions::refresh() const LLFocusableElement* keyboard_focus_view = gFocusMgr.getKeyboardFocus(); S32 string_index = 0; - std::string MODIFY_INFO_STRINGS[] = + static std::string MODIFY_INFO_STRINGS[] = { getString("text modify info 1"), getString("text modify info 2"), @@ -385,18 +383,6 @@ void LLPanelPermissions::refresh() // Update creator text field getChildView("Creator:")->setEnabled(TRUE); -// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Modified: RLVa-1.2.2a - BOOL creators_identical = FALSE; -// [/RLVa:KB] - std::string creator_name; -// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Modified: RLVa-1.2.2a - creators_identical = LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, creator_name); -// [/RLVa:KB] -// LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, creator_name); - -// getChild("Creator Name")->setValue(creator_name); -// getChildView("Creator Name")->setEnabled(TRUE); -// [RLVa:KB] - Moved further down to avoid an annoying flicker when the text is set twice in a row // Update owner text field getChildView("Owner:")->setEnabled(TRUE); @@ -404,108 +390,62 @@ void LLPanelPermissions::refresh() // Update last owner text field getChildView("Last Owner:")->setEnabled(TRUE); - std::string owner_name; - const BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_name); - -// LL_INFOS() << "owners_identical " << (owners_identical ? "TRUE": "FALSE") << LL_ENDL; - std::string last_owner_name; - LLSelectMgr::getInstance()->selectGetLastOwner(mLastOwnerID, last_owner_name); - - if (mOwnerID.isNull()) + static const auto none_str = LLTrans::getString("GroupNameNone"); + std::string owner_app_link(none_str); + if (auto view = getChild("Creator Name")) { - if(LLSelectMgr::getInstance()->selectIsGroupOwned()) + if (LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, owner_app_link)) { - // Group owned already displayed by selectGetOwner + view->setValue(mCreatorID); } else { - // Display last owner if public - std::string last_owner_name; - LLSelectMgr::getInstance()->selectGetLastOwner(mLastOwnerID, last_owner_name); - - // It should never happen that the last owner is null and the owner - // is null, but it seems to be a bug in the simulator right now. JC - if (!mLastOwnerID.isNull() && !last_owner_name.empty()) - { - owner_name.append(", last "); - owner_name.append( last_owner_name ); - } + view->setValue(LLUUID::null); + view->setText(owner_app_link); } + view->setEnabled(true); } -// getChild("Owner Name")->setValue(owner_name); -// getChildView("Owner Name")->setEnabled(TRUE); -// [RLVa:KB] - Moved further down to avoid an annoying flicker when the text is set twice in a row - -// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Modified: RLVa-1.2.2a - bool fRlvEnableOwner = true; - bool fRlvEnableCreator = true; - bool fRlvEnableLastOwner = true; - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) - { - // Only anonymize the creator if all of the selection was created by the same avie who's also the owner or they're a nearby avie - if ( (creators_identical) && (mCreatorID != gAgent.getID()) && ((mCreatorID == mOwnerID) || (RlvUtil::isNearbyAgent(mCreatorID))) ) - { - creator_name = RlvStrings::getAnonym(creator_name); - fRlvEnableCreator = false; - } - // Only anonymize the owner name if all of the selection is owned by the same avie and isn't group owned - if ( (owners_identical) && (!LLSelectMgr::getInstance()->selectIsGroupOwned()) && (mOwnerID != gAgent.getID()) ) + owner_app_link = none_str; + const BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_app_link); + if (auto view = getChild("Owner Name")) + { + if (owners_identical) { - owner_name = RlvStrings::getAnonym(owner_name); - fRlvEnableOwner = false; + view->setValue(mOwnerID); } - - if (RlvUtil::isNearbyAgent(mLastOwnerID)) + else { - last_owner_name = RlvStrings::getAnonym(last_owner_name); - fRlvEnableLastOwner = false; + view->setValue(LLUUID::null); + view->setText(owner_app_link); } + view->setEnabled(true); } - else if ((objectp->isAttachment() || objectp->isAvatar()) && gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS) && mOwnerID != gAgentID) - { - owner_name = RlvStrings::getAnonym(owner_name); - fRlvEnableOwner = false; - if (mOwnerID == mCreatorID) + if (auto view = getChild("Last Owner Name")) + { + owner_app_link = none_str; + if (LLSelectMgr::getInstance()->selectGetLastOwner(mLastOwnerID, owner_app_link)) { - creator_name = RlvStrings::getAnonym(creator_name); - fRlvEnableCreator = false; + view->setValue(mLastOwnerID); } - - if (mOwnerID == mLastOwnerID) + else { - last_owner_name = RlvStrings::getAnonym(last_owner_name); - fRlvEnableLastOwner = false; + view->setValue(LLUUID::null); + view->setText(owner_app_link); } + view->setEnabled(true); } -// [/RLVa:KB] - getChild("Creator Name")->setValue(creator_name); - getChildView("Creator Name")->setEnabled(TRUE); - - getChild("Owner Name")->setValue(owner_name); - getChildView("Owner Name")->setEnabled(TRUE); -// childSetEnabled("button owner profile",owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned())); -// getChildView("button last owner profile")->setEnabled(owners_identical && mLastOwnerID.notNull()); -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) - getChildView("button owner profile")->setEnabled(fRlvEnableOwner && owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned())); - getChildView("button creator profile")->setEnabled(fRlvEnableCreator && creators_identical && mCreatorID.notNull()); - getChildView("button last owner profile")->setEnabled(fRlvEnableLastOwner && owners_identical && mLastOwnerID.notNull()); -// [/RLVa:KB] - - getChild("Last Owner Name")->setValue(last_owner_name); - getChildView("Last Owner Name")->setEnabled(TRUE); // update group text field getChildView("Group:")->setEnabled(TRUE); - //getChild("Group Name")->setValue(LLStringUtil::null); LLUUID group_id; BOOL groups_identical = LLSelectMgr::getInstance()->selectGetGroup(group_id); if (groups_identical) { if(mLabelGroupName) { - mLabelGroupName->setNameID(group_id, TRUE); + mLabelGroupName->setNameID(group_id, LFIDBearer::GROUP); mLabelGroupName->setEnabled(TRUE); } } @@ -513,14 +453,13 @@ void LLPanelPermissions::refresh() { if(mLabelGroupName) { - mLabelGroupName->setNameID(LLUUID::null, TRUE); - mLabelGroupName->refresh(LLUUID::null, std::string(), true); + mLabelGroupName->setNameID(LLUUID::null, LFIDBearer::GROUP); + mLabelGroupName->setNameText(); mLabelGroupName->setEnabled(FALSE); } } getChildView("button set group")->setEnabled(root_selected && owners_identical && (mOwnerID == gAgent.getID()) && is_nonpermanent_enforced); - getChildView("button open group")->setEnabled(group_id.notNull()); getChildView("Name:")->setEnabled(TRUE); LLLineEditor* LineEditorObjectName = getChild("Object Name"); @@ -1049,36 +988,6 @@ void LLPanelPermissions::onClickRelease(void*) LLSelectMgr::getInstance()->sendOwner(LLUUID::null, LLUUID::null); } -void LLPanelPermissions::onClickCreator() -{ - LLAvatarActions::showProfile(mCreatorID); -} - -void LLPanelPermissions::onClickOwner() -{ - if (LLSelectMgr::getInstance()->selectIsGroupOwned()) - { - LLUUID group_id; - LLSelectMgr::getInstance()->selectGetGroup(group_id); - LLGroupActions::show(group_id); - } - else - { -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) - if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) - { - LLAvatarActions::showProfile(mOwnerID); - } -// [/RLVa:KB] -// LLAvatarActions::showProfile(mOwnerID); - } -} - -void LLPanelPermissions::onClickLastOwner() -{ - LLAvatarActions::showProfile(mLastOwnerID); -} - void LLPanelPermissions::onClickGroup() { LLUUID owner_id; @@ -1103,18 +1012,11 @@ void LLPanelPermissions::onClickGroup() } } -void LLPanelPermissions::onClickOpenGroup() -{ - LLUUID group_id; - LLSelectMgr::getInstance()->selectGetGroup(group_id); - LLGroupActions::show(group_id); -} - void LLPanelPermissions::cbGroupID(LLUUID group_id) { if(mLabelGroupName) { - mLabelGroupName->setNameID(group_id, TRUE); + mLabelGroupName->setNameID(group_id, LFIDBearer::GROUP); } LLSelectMgr::getInstance()->sendGroup(group_id); } diff --git a/indra/newview/llpanelpermissions.h b/indra/newview/llpanelpermissions.h index 58b6dbac9b..87868108b7 100644 --- a/indra/newview/llpanelpermissions.h +++ b/indra/newview/llpanelpermissions.h @@ -58,11 +58,7 @@ class LLPanelPermissions : public LLPanel // statics static void onClickClaim(void*); static void onClickRelease(void*); - void onClickCreator(); - void onClickOwner(); - void onClickLastOwner(); void onClickGroup(); - static void onClickOpenGroup(); void cbGroupID(LLUUID group_id); static void onClickDeedToGroup(void*); static void onClickCopyObjKey(); diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 55e58a4c90..99d5f0c916 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -61,12 +61,14 @@ void show_picture(const LLUUID& id, const std::string& name) { // Try to show and focus existing preview - if (LLPreview::show(id)) return; + if (id.isNull() || LLPreview::show(id)) return; // If there isn't one, make a new preview S32 left, top; gFloaterView->getNewFloaterPosition(&left, &top); LLRect rect = gSavedSettings.getRect("PreviewTextureRect"); - (new LLPreviewTexture("preview texture", rect.translate(left - rect.mLeft, rect.mTop - top), name, id))->setFocus(true); + auto preview = new LLPreviewTexture("preview texture", rect.translate(left - rect.mLeft, rect.mTop - top), name, id); + preview->setFocus(true); + gFloaterView->adjustToFitScreen(preview, false); } //static @@ -126,8 +128,11 @@ void LLPanelPick::reset() BOOL LLPanelPick::postBuild() { + auto show_pic = [this] { show_picture(mSnapshotCtrl->getImageAssetID(), mNameEditor->getText()); }; + auto show_pic_if_not_self = [=] { if (!mSnapshotCtrl->canChange()) show_pic(); }; mSnapshotCtrl = getChild("snapshot_ctrl"); mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelPick::onCommitAny, this)); + mSnapshotCtrl->setMouseUpCallback(std::bind(show_pic_if_not_self)); mNameEditor = getChild("given_name_editor"); mNameEditor->setCommitOnFocusLost(true); @@ -144,7 +149,7 @@ BOOL LLPanelPick::postBuild() mSetBtn->setCommitCallback(boost::bind(&LLPanelPick::onClickSet,this)); mOpenBtn = getChild("open_picture_btn"); - mOpenBtn->setCommitCallback(boost::bind(show_picture, boost::bind(&LLTextureCtrl::getImageAssetID, mSnapshotCtrl), boost::bind(&LLLineEditor::getText, mNameEditor))); + mOpenBtn->setCommitCallback(std::bind(show_pic)); getChild("pick_teleport_btn")->setCommitCallback(boost::bind(&LLPanelPick::onClickTeleport,this)); getChild("pick_map_btn")->setCommitCallback(boost::bind(&LLPanelPick::onClickMap,this)); @@ -196,7 +201,7 @@ void LLPanelPick::processProperties(void* data, EAvatarProcessorType type) // Update UI controls mNameEditor->setText(pick_info->name); - mDescEditor->setText(pick_info->desc); + mDescEditor->setText(pick_info->desc, false); mSnapshotCtrl->setImageAssetID(pick_info->snapshot_id); mLocationEditor->setText(location_text); } diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp index 9dc433463b..00f7bc4d11 100644 --- a/indra/newview/llpanelplace.cpp +++ b/indra/newview/llpanelplace.cpp @@ -125,7 +125,7 @@ BOOL LLPanelPlace::postBuild() void LLPanelPlace::displayItemInfo(const LLInventoryItem* pItem) { mNameEditor->setText(pItem->getName()); - mDescEditor->setText(pItem->getDescription()); + mDescEditor->setText(pItem->getDescription(), false); } // Use this for search directory clicks, because we are totally @@ -248,7 +248,7 @@ void LLPanelPlace::processParcelInfo(const LLParcelData& parcel_data) if( !parcel_data.desc.empty() && mDescEditor && mDescEditor->getText().empty()) { - mDescEditor->setText(parcel_data.desc); + mDescEditor->setText(parcel_data.desc, false); } std::string info_text; diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 577e1cd646..79237f8067 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -84,12 +84,12 @@ const int LLPanelPrimMediaControls::kNumZoomLevels = 2; // LLPanelPrimMediaControls::LLPanelPrimMediaControls() : - mAlpha(1.f), - mCurrentURL(""), - mPreviousURL(""), mPauseFadeout(false), mUpdateSlider(true), mClearFaceOnFade(false), + mAlpha(1.f), + mCurrentURL(""), + mPreviousURL(""), mCurrentRate(0.0), mMovieDuration(0.0), mTargetObjectID(LLUUID::null), @@ -118,6 +118,7 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() : mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeDown", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeDown, this)); mCommitCallbackRegistrar.add("MediaCtrl.Volume", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeSlider, this)); mCommitCallbackRegistrar.add("MediaCtrl.ToggleMute", boost::bind(&LLPanelPrimMediaControls::onToggleMute, this)); + mCommitCallbackRegistrar.add("MediaCtrl.MOAPStop", std::bind([this]() { getTargetMediaImpl()->setDisabled(true); })); mCommitCallbackRegistrar.add("MediaCtrl.ShowVolumeSlider", boost::bind(&LLPanelPrimMediaControls::showVolumeSlider, this)); mCommitCallbackRegistrar.add("MediaCtrl.HideVolumeSlider", boost::bind(&LLPanelPrimMediaControls::hideVolumeSlider, this)); mCommitCallbackRegistrar.add("MediaCtrl.SkipBack", boost::bind(&LLPanelPrimMediaControls::onClickSkipBack, this)); @@ -150,6 +151,7 @@ BOOL LLPanelPrimMediaControls::postBuild() mPauseCtrl = getChild("pause"); mStopCtrl = getChild("stop"); mMediaStopCtrl = getChild("media_stop"); + mMOAPStopCtrl = getChild("moap_stop"); mHomeCtrl = getChild("home"); mUnzoomCtrl = getChild("close"); // This is actually "unzoom" mOpenCtrl = getChild("new_window"); @@ -283,7 +285,7 @@ LLPluginClassMedia* LLPanelPrimMediaControls::getTargetMediaPlugin() return impl->getMediaPlugin(); } - return NULL; + return nullptr; } void LLPanelPrimMediaControls::updateShape() @@ -297,7 +299,7 @@ void LLPanelPrimMediaControls::updateShape() return; } - LLPluginClassMedia* media_plugin = NULL; + LLPluginClassMedia* media_plugin = nullptr; if(media_impl->hasMedia()) { media_plugin = media_impl->getMediaPlugin(); @@ -318,10 +320,11 @@ void LLPanelPrimMediaControls::updateShape() { bool mini_controls = false; LLMediaEntry *media_data = objectp->getTE(mTargetObjectFace)->getMediaData(); - if (media_data && NULL != dynamic_cast(objectp)) + LLVOVolume *vol = objectp ? objectp->asVolume() : nullptr; + if (media_data && vol) { // Don't show the media controls if we do not have permissions - enabled = dynamic_cast(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL); + enabled = vol->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL); mini_controls = (LLMediaEntry::MINI == media_data->getControls()); } const bool is_hud = objectp->isHUDAttachment(); @@ -351,11 +354,11 @@ void LLPanelPrimMediaControls::updateShape() mSecureLockIcon->setVisible(false); mCurrentURL = media_impl->getCurrentMediaURL(); - mBackCtrl->setEnabled((media_impl != NULL) && media_impl->canNavigateBack() && can_navigate); - mFwdCtrl->setEnabled((media_impl != NULL) && media_impl->canNavigateForward() && can_navigate); + mBackCtrl->setEnabled((media_impl != nullptr) && media_impl->canNavigateBack() && can_navigate); + mFwdCtrl->setEnabled((media_impl != nullptr) && media_impl->canNavigateForward() && can_navigate); mStopCtrl->setEnabled(has_focus && can_navigate); mHomeCtrl->setEnabled(has_focus && can_navigate); - LLPluginClassMediaOwner::EMediaStatus result = ((media_impl != NULL) && media_impl->hasMedia()) ? media_plugin->getStatus() : LLPluginClassMediaOwner::MEDIA_NONE; + LLPluginClassMediaOwner::EMediaStatus result = ((media_impl != nullptr) && media_impl->hasMedia()) ? media_plugin->getStatus() : LLPluginClassMediaOwner::MEDIA_NONE; mVolumeCtrl->setVisible(has_focus); mVolumeCtrl->setEnabled(has_focus); @@ -367,6 +370,7 @@ void LLPanelPrimMediaControls::updateShape() mReloadCtrl->setEnabled(false); mReloadCtrl->setVisible(false); mMediaStopCtrl->setVisible(has_focus); + mMOAPStopCtrl->setVisible(false); mHomeCtrl->setVisible(has_focus); mBackCtrl->setVisible(false); mFwdCtrl->setVisible(false); @@ -419,7 +423,7 @@ void LLPanelPrimMediaControls::updateShape() mMediaPlaySliderCtrl->setEnabled(true); } - // video vloume + // video volume if(volume <= 0.0) { mMuteBtn->setToggleState(true); @@ -465,6 +469,7 @@ void LLPanelPrimMediaControls::updateShape() mPlayCtrl->setVisible(FALSE); mPauseCtrl->setVisible(FALSE); mMediaStopCtrl->setVisible(FALSE); + mMOAPStopCtrl->setVisible(!!media_plugin); mMediaAddressCtrl->setVisible(has_focus && !mini_controls); mMediaAddressCtrl->setEnabled(has_focus && !mini_controls); mMediaPlaySliderPanel->setVisible(FALSE); @@ -547,21 +552,21 @@ void LLPanelPrimMediaControls::updateShape() switch (mScrollState) { case SCROLL_UP: - media_impl->scrollWheel(0, -1, MASK_NONE); + media_impl->scrollWheel(0, 0, 0, -1, MASK_NONE); break; case SCROLL_DOWN: - media_impl->scrollWheel(0, 1, MASK_NONE); + media_impl->scrollWheel(0, 0, 0, 1, MASK_NONE); break; case SCROLL_LEFT: - media_impl->scrollWheel(1, 0, MASK_NONE); + media_impl->scrollWheel(0, 0, 1, 0, MASK_NONE); // media_impl->handleKeyHere(KEY_LEFT, MASK_NONE); break; case SCROLL_RIGHT: - media_impl->scrollWheel(-1, 0, MASK_NONE); + media_impl->scrollWheel(0, 0, -1, 0, MASK_NONE); // media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE); break; case SCROLL_NONE: - default: + default: break; } } @@ -1101,7 +1106,7 @@ void LLPanelPrimMediaControls::onScrollUp(void* user_data) if(impl) { - impl->scrollWheel(0, -1, MASK_NONE); + impl->scrollWheel(0, 0, 0, -1, MASK_NONE); } } void LLPanelPrimMediaControls::onScrollUpHeld(void* user_data) @@ -1118,7 +1123,7 @@ void LLPanelPrimMediaControls::onScrollRight(void* user_data) if(impl) { - impl->scrollWheel(-1, 0, MASK_NONE); + impl->scrollWheel(0, 0, -1, 0, MASK_NONE); // impl->handleKeyHere(KEY_RIGHT, MASK_NONE); } } @@ -1137,7 +1142,7 @@ void LLPanelPrimMediaControls::onScrollLeft(void* user_data) if(impl) { - impl->scrollWheel(1, 0, MASK_NONE); + impl->scrollWheel(0, 0, 1, 0, MASK_NONE); // impl->handleKeyHere(KEY_LEFT, MASK_NONE); } } @@ -1156,7 +1161,7 @@ void LLPanelPrimMediaControls::onScrollDown(void* user_data) if(impl) { - impl->scrollWheel(0, 1, MASK_NONE); + impl->scrollWheel(0, 0, 0, 1, MASK_NONE); } } void LLPanelPrimMediaControls::onScrollDownHeld(void* user_data) diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index 7db687d23d..2cf196a225 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -155,6 +155,7 @@ class LLPanelPrimMediaControls : public LLPanel LLUICtrl *mPauseCtrl; LLUICtrl *mStopCtrl; LLUICtrl *mMediaStopCtrl; + LLUICtrl *mMOAPStopCtrl; LLUICtrl *mHomeCtrl; LLUICtrl *mUnzoomCtrl; LLUICtrl *mOpenCtrl; diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 910e43e9e3..6c26444409 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -41,7 +41,11 @@ #include "lltabcontainer.h" #include "llviewercontrol.h" #include "llviewernetwork.h" +#include "llmutelist.h" +#endif +#include "llfloatermute.h" +#ifdef AI_UNUSED static const std::string PANEL_PICKS = "panel_picks"; #endif // AI_UNUSED @@ -55,19 +59,19 @@ std::string getProfileURL(const std::string& agent_name) llassert(!url.empty()); LLSD subs; subs["AGENT_NAME"] = agent_name; - url = LLWeb::expandURLSubstitutions(url,subs); + url = LLWeb::expandURLSubstitutions(url, subs); LLStringUtil::toLower(url); return url; } -class LLProfileHandler : public LLCommandHandler +class LLProfileHandler final : public LLCommandHandler { public: // requires trusted browser to trigger LLProfileHandler() : LLCommandHandler("profile", UNTRUSTED_THROTTLE) { } bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + LLMediaCtrl* web) override { if (params.size() < 1) return false; std::string agent_name = params[0]; @@ -80,14 +84,14 @@ class LLProfileHandler : public LLCommandHandler }; LLProfileHandler gProfileHandler; -class LLAgentHandler : public LLCommandHandler +class LLAgentHandler final : public LLCommandHandler { public: // requires trusted browser to trigger LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { } bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + LLMediaCtrl* web) override { if (params.size() < 2) return false; LLUUID avatar_id; @@ -97,14 +101,8 @@ class LLAgentHandler : public LLCommandHandler } std::string verb = params[1].asString(); -#if LL_WINDOWS // C++11 - while (!verb.empty() && std::ispunct(verb.back())) - verb.pop_back(); -#else - for (size_t i = verb.size()-1; i >= 0 && std::ispunct(verb[i]); --i) - verb.erase(i); -#endif - if (verb == "about") + for (; !verb.empty() && std::ispunct(verb.back()); verb.pop_back()); + if (verb == "about" || verb == "completename" || verb == "displayname" || verb == "username") { LLAvatarActions::showProfile(avatar_id); return true; @@ -150,6 +148,12 @@ class LLAgentHandler : public LLCommandHandler return true; } + if (verb == "removefriend") + { + LLAvatarActions::removeFriendDialog(avatar_id); + return true; + } + if (verb == "mute") { if (! LLAvatarActions::isBlocked(avatar_id)) @@ -168,6 +172,28 @@ class LLAgentHandler : public LLCommandHandler return true; } + if (verb == "block") + { + if (params.size() > 2) + { + const std::string object_name = LLURI::unescape(params[2].asString()); + LLMute mute(avatar_id, object_name, LLMute::OBJECT); + LLMuteList::getInstance()->add(mute); + LLFloaterMute::showInstance()->selectMute(mute.mID); + } + return true; + } + + if (verb == "unblock") + { + if (params.size() > 2) + { + const std::string object_name = params[2].asString(); + LLMute mute(avatar_id, object_name, LLMute::OBJECT); + LLMuteList::getInstance()->remove(mute); + } + return true; + } return false; } }; @@ -177,13 +203,13 @@ LLAgentHandler gAgentHandler; #ifdef AI_UNUSED //-- LLPanelProfile::ChildStack begins ---------------------------------------- LLPanelProfile::ChildStack::ChildStack() -: mParent(NULL) +: mParent(nullptr) { } LLPanelProfile::ChildStack::~ChildStack() { - while (mStack.size() != 0) + while (!mStack.empty()) { view_list_t& top = mStack.back(); for (view_list_t::const_iterator it = top.begin(); it != top.end(); ++it) @@ -223,7 +249,7 @@ bool LLPanelProfile::ChildStack::push() /// Restore saved children (adding them back to the child list). bool LLPanelProfile::ChildStack::pop() { - if (mStack.size() == 0) + if (mStack.empty()) { LL_WARNS() << "Empty stack" << LL_ENDL; llassert(mStack.size() == 0); @@ -246,7 +272,7 @@ bool LLPanelProfile::ChildStack::pop() void LLPanelProfile::ChildStack::preParentReshape() { mSavedStack = mStack; - while(mStack.size() > 0) + while(!mStack.empty()) { pop(); } @@ -261,9 +287,8 @@ void LLPanelProfile::ChildStack::postParentReshape() for (stack_t::const_iterator stack_it = mStack.begin(); stack_it != mStack.end(); ++stack_it) { const view_list_t& vlist = (*stack_it); - for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it) + for (auto viewp : vlist) { - LLView* viewp = *list_it; LL_DEBUGS() << "removing " << viewp->getName() << LL_ENDL; mParent->removeChild(viewp); } @@ -279,9 +304,9 @@ void LLPanelProfile::ChildStack::dump() std::ostringstream dbg_line; dbg_line << "lvl #" << lvl << ":"; const view_list_t& vlist = (*stack_it); - for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it) + for (auto list_it : vlist) { - dbg_line << " " << (*list_it)->getName(); + dbg_line << " " << list_it->getName(); } LL_DEBUGS() << dbg_line.str() << LL_ENDL; } @@ -378,7 +403,7 @@ void LLPanelProfile::onOpen() void LLPanelProfile::onTabSelected(const LLSD& param) { std::string tab_name = param.asString(); - if (NULL != getTabContainer()[tab_name]) + if (nullptr != getTabContainer()[tab_name]) { getTabContainer()[tab_name]->onOpen(getAvatarId()); } @@ -422,7 +447,7 @@ void LLPanelProfile::closePanel(LLPanel* panel) // Prevent losing focus by the floater const child_list_t* child_list = getChildList(); - if (child_list->size() > 0) + if (!child_list->empty()) { child_list->front()->setFocus(TRUE); } diff --git a/indra/newview/llpanelskins.cpp b/indra/newview/llpanelskins.cpp index 53d5ce60fb..834fd98329 100644 --- a/indra/newview/llpanelskins.cpp +++ b/indra/newview/llpanelskins.cpp @@ -116,8 +116,7 @@ void LLPanelSkins::refresh() LLButton* b = getChild("custom_skin_preview"); std::string imagename = data["preview_image"].asString(); if(imagename == "" || imagename == " " || !LLFile::isfile(imagename)) imagename = "preview.png"; - std::string imageprev(".."+gDirUtilp->getDirDelimiter()+ - ".."+gDirUtilp->getDirDelimiter()+ + std::string imageprev(path_name+ data["folder_name"].asString()+gDirUtilp->getDirDelimiter()+ "textures"+gDirUtilp->getDirDelimiter()+ imagename); diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index ab3feb724c..36cc6647ef 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -36,7 +36,6 @@ // linden library includes #include "llclickaction.h" -#include "lleconomy.h" #include "llerror.h" #include "llfontgl.h" #include "llflexibleobject.h" @@ -84,6 +83,8 @@ #include "llviewercontrol.h" #include "llmeshrepository.h" +#include "llvoavatarself.h" + #include // "Features" Tab @@ -92,7 +93,8 @@ BOOL LLPanelVolume::postBuild() { // Flexible Objects Parameters { - getChild("Flexible1D Checkbox Ctrl")->setCommitCallback(boost::bind(&LLPanelVolume::onCommitIsFlexible, this, _1, _2), NULL); + childSetCommitCallback("Animated Mesh Checkbox Ctrl", boost::bind(&LLPanelVolume::onCommitAnimatedMeshCheckbox, this, _1, _2), NULL); + childSetCommitCallback("Flexible1D Checkbox Ctrl", boost::bind(&LLPanelVolume::onCommitIsFlexible, this, _1, _2), NULL); childSetCommitCallback("FlexNumSections",onCommitFlexible,this); getChild("FlexNumSections")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("FlexGravity",onCommitFlexible,this); @@ -228,6 +230,11 @@ void LLPanelVolume::getState( ) { volobjp = (LLVOVolume *)objectp; } + LLVOVolume *root_volobjp = NULL; + if (root_objectp && (root_objectp->getPCode() == LL_PCODE_VOLUME)) + { + root_volobjp = (LLVOVolume *)root_objectp; + } if( !objectp ) { @@ -251,6 +258,8 @@ void LLPanelVolume::getState( ) BOOL editable = root_objectp->permModify() && !root_objectp->isPermanentEnforced(); BOOL single_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ) && LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1; + BOOL single_root_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ) && + LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1; // Select Single Message if (single_volume) @@ -340,7 +349,57 @@ void LLPanelVolume::getState( ) getChildView("Light Focus")->setEnabled(false); getChildView("Light Ambiance")->setEnabled(false); } - + + // Animated Mesh + BOOL is_animated_mesh = single_root_volume && root_volobjp && root_volobjp->isAnimatedObject(); + getChild("Animated Mesh Checkbox Ctrl")->setValue(is_animated_mesh); + BOOL enabled_animated_object_box = FALSE; + if (root_volobjp && root_volobjp == volobjp) + { + enabled_animated_object_box = single_root_volume && root_volobjp && root_volobjp->canBeAnimatedObject() && editable; +#if 0 + if (!enabled_animated_object_box) + { + LL_INFOS() << "not enabled: srv " << single_root_volume << " root_volobjp " << (bool) root_volobjp << LL_ENDL; + if (root_volobjp) + { + LL_INFOS() << " cba " << root_volobjp->canBeAnimatedObject() + << " editable " << editable << " permModify() " << root_volobjp->permModify() + << " ispermenf " << root_volobjp->isPermanentEnforced() << LL_ENDL; + } + } +#endif + if (enabled_animated_object_box && !is_animated_mesh && + root_volobjp->isAttachment() && !gAgentAvatarp->canAttachMoreAnimatedObjects()) + { + // Turning this attachment animated would cause us to exceed the limit. + enabled_animated_object_box = false; + } + } + getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(enabled_animated_object_box); + + //refresh any bakes + if (root_volobjp) + { + root_volobjp->refreshBakeTexture(); + + LLViewerObject::const_child_list_t& child_list = root_volobjp->getChildren(); + for (const auto& iter : child_list) + { + LLViewerObject* objectp = iter; + if (objectp) + { + objectp->refreshBakeTexture(); + } + } + + if (gAgentAvatarp) + { + gAgentAvatarp->updateMeshVisibility(); + } + } + + // Flexible properties BOOL is_flexible = volobjp && volobjp->isFlexible(); getChild("Flexible1D Checkbox Ctrl")->setValue(is_flexible); @@ -372,7 +431,7 @@ void LLPanelVolume::getState( ) getChildView("FlexForceY")->setEnabled(true); getChildView("FlexForceZ")->setEnabled(true); - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + const LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData(); getChild("FlexNumSections")->setValue((F32)attributes->getSimulateLOD()); getChild("FlexGravity")->setValue(attributes->getGravity()); @@ -424,7 +483,7 @@ void LLPanelVolume::getState( ) mComboPhysicsShapeType->add(getString("None"), LLSD(1)); BOOL isMesh = FALSE; - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = objectp->getSculptParams(); if (sculpt_params) { U8 sculpt_type = sculpt_params->getSculptType(); @@ -739,7 +798,7 @@ void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata ) return; } - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + const LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData(); if (attributes) { LLFlexibleObjectData new_attributes; @@ -764,6 +823,52 @@ void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata ) self->refresh(); } +void LLPanelVolume::onCommitAnimatedMeshCheckbox(LLUICtrl *, void*) +{ + LLViewerObject* objectp = mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + LLVOVolume *volobjp = (LLVOVolume *)objectp; + BOOL animated_mesh = getChild("Animated Mesh Checkbox Ctrl")->getValue(); + U32 flags = volobjp->getExtendedMeshFlags(); + U32 new_flags = flags; + if (animated_mesh) + { + new_flags |= LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; + } + else + { + new_flags &= ~LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; + } + if (new_flags != flags) + { + volobjp->setExtendedMeshFlags(new_flags); + } + + //refresh any bakes + if (volobjp) + { + volobjp->refreshBakeTexture(); + + LLViewerObject::const_child_list_t& child_list = volobjp->getChildren(); + for (const auto& iter : child_list) + { + LLViewerObject* objectp = iter; + if (objectp) + { + objectp->refreshBakeTexture(); + } + } + + if (gAgentAvatarp) + { + gAgentAvatarp->updateMeshVisibility(); + } + } +} + void LLPanelVolume::onCommitIsFlexible(LLUICtrl *, void*) { if (mObject->flagObjectPermanent()) diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index e81f430528..76a206f74b 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -67,7 +67,8 @@ class LLPanelVolume : public LLPanel static void onCommitLight( LLUICtrl* ctrl, void* userdata); void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata); static void onCommitFlexible( LLUICtrl* ctrl, void* userdata); - static void onCommitPhysicsParam( LLUICtrl* ctrl, void* userdata); + void onCommitAnimatedMeshCheckbox(LLUICtrl* ctrl, void* userdata); + static void onCommitPhysicsParam( LLUICtrl* ctrl, void* userdata); void onLightCancelColor(const LLSD& data); void onLightSelectColor(const LLSD& data); diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index d9b34ca933..872b90514d 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -30,11 +30,12 @@ #include "llagent.h" #include "llmutelist.h" #include "llparticipantlist.h" -#include "llscrolllistctrl.h" -#include "llscrolllistitem.h" +#include "llnamelistctrl.h" #include "llspeakers.h" +#include "lluictrlfactory.h" // Edit: For menu duality +#include "llviewermenu.h" // Edit: For menu duality #include "llviewerwindow.h" -#include "llvoiceclient.h" +#include "llvoicechannel.h" // Edit: For menu duality #include "llworld.h" // Edit: For ghost detection // [RLVa:KB] #include "rlvhandler.h" @@ -43,7 +44,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, bool show_text_chatters) : mSpeakerMgr(data_source), - mAvatarList(NULL), + mAvatarList(nullptr), mShowTextChatters(show_text_chatters), mValidateSpeakerCallback(NULL) { @@ -58,16 +59,31 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, mSpeakerClearListener = new SpeakerClearListener(*this); //mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this); mSpeakerMuteListener = new SpeakerMuteListener(*this); - + mSpeakerBatchBeginListener = new SpeakerBatchBeginListener(*this); + mSpeakerBatchEndListener = new SpeakerBatchEndListener(*this); + mSpeakerSortingUpdateListener = new SpeakerSortingUpdateListener(*this); mSpeakerMgr->addListener(mSpeakerAddListener, "add"); mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove"); mSpeakerMgr->addListener(mSpeakerClearListener, "clear"); + mSpeakerMgr->addListener(mSpeakerBatchBeginListener, "batch_begin"); + mSpeakerMgr->addListener(mSpeakerBatchEndListener, "batch_end"); + mSpeakerMgr->addListener(mSpeakerSortingUpdateListener, "update_sorting"); //mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator"); } +void LLParticipantList::setupContextMenu() +{ + if (mSpeakerMgr->getVoiceChannel() == LLVoiceChannelProximal::getInstance()) + { + static LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_local_avs.xml", gMenuHolder); + mAvatarList->setContextMenu(menu); + } + else mAvatarList->setContextMenu(LFIDBearer::AVATAR); +} + BOOL LLParticipantList::postBuild() { - mAvatarList = getChild("speakers_list"); + mAvatarList = getChild("speakers_list"); mAvatarList->sortByColumn(gSavedSettings.getString("FloaterActiveSpeakersSortColumn"), gSavedSettings.getBOOL("FloaterActiveSpeakersSortAscending")); mAvatarList->setDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this)); @@ -92,6 +108,7 @@ BOOL LLParticipantList::postBuild() // update speaker UI handleSpeakerSelect(); + setupContextMenu(); return true; } @@ -103,25 +120,6 @@ LLParticipantList::~LLParticipantList() mAvatarListRefreshConnection.disconnect(); mAvatarListReturnConnection.disconnect(); mAvatarListToggleIconsConnection.disconnect(); - - // It is possible Participant List will be re-created from LLCallFloater::onCurrentChannelChanged() - // See ticket EXT-3427 - // hide menu before deleting it to stop enable and check handlers from triggering. - if(mParticipantListMenu && !LLApp::isExiting()) - { - mParticipantListMenu->hide(); - } - - if (mParticipantListMenu) - { - delete mParticipantListMenu; - mParticipantListMenu = NULL; - } - - mAvatarList->setContextMenu(NULL); - mAvatarList->setComparator(NULL); - - delete mAvalineUpdater; */ } @@ -226,6 +224,11 @@ void LLParticipantList::handleSpeakerSelect() void LLParticipantList::refreshSpeakers() { + if (mUpdateTimer.getElapsedTimeF32() < .5f) + { + return; + } + mUpdateTimer.reset(); // store off current selection and scroll state to preserve across list rebuilds const S32 scroll_pos = mAvatarList->getScrollInterface()->getScrollPos(); @@ -236,27 +239,42 @@ void LLParticipantList::refreshSpeakers() // panel and hasn't been motionless for more than a few seconds. see DEV-6655 -MG LLRect screen_rect; localRectToScreen(getLocalRect(), &screen_rect); - mSpeakerMgr->update(!(screen_rect.pointInRect(gViewerWindow->getCurrentMouseX(), gViewerWindow->getCurrentMouseY()) && gMouseIdleTimer.getElapsedTimeF32() < 5.f)); + bool resort_ok = !(screen_rect.pointInRect(gViewerWindow->getCurrentMouseX(), gViewerWindow->getCurrentMouseY()) && gMouseIdleTimer.getElapsedTimeF32() < 5.f); + mSpeakerMgr->update(resort_ok); + bool re_sort = false; + size_t start_pos = llmax(0, scroll_pos - 20); + size_t end_pos = scroll_pos + mAvatarList->getLinesPerPage() + 20; std::vector items = mAvatarList->getAllData(); + if (start_pos >= items.size()) + { + return; + } + size_t count = 0; for (std::vector::iterator item_it = items.begin(); item_it != items.end(); ++item_it) { + LLScrollListItem* itemp = (*item_it); LLPointer speakerp = mSpeakerMgr->findSpeaker(itemp->getUUID()); if (speakerp.isNull()) continue; - if (LLScrollListCell* icon_cell = itemp->getColumn(0)) + ++count; + + // Color changes. Only perform for rows that are near or in the viewable area. + if (count > start_pos && count <= end_pos) { - if (speakerp->mStatus == LLSpeaker::STATUS_MUTED) - { - icon_cell->setValue("mute_icon.tga"); - static const LLCachedControl sAscentMutedColor("AscentMutedColor"); - icon_cell->setColor(speakerp->mModeratorMutedVoice ? /*LLColor4::grey*/sAscentMutedColor : LLColor4(1.f, 71.f / 255.f, 71.f / 255.f, 1.f)); - } - else + if (LLScrollListCell* icon_cell = itemp->getColumn(0)) { - switch(llmin(2, llfloor((speakerp->mSpeechVolume / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f))) + if (speakerp->mStatus == LLSpeaker::STATUS_MUTED) + { + icon_cell->setValue("mute_icon.tga"); + static const LLCachedControl sAscentMutedColor("AscentMutedColor"); + icon_cell->setColor(speakerp->mModeratorMutedVoice ? /*LLColor4::grey*/sAscentMutedColor : LLColor4(1.f, 71.f / 255.f, 71.f / 255.f, 1.f)); + } + else { + switch (llmin(2, llfloor((speakerp->mSpeechVolume / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f))) + { case 0: icon_cell->setValue("icn_active-speakers-dot-lvl0.tga"); break; @@ -266,62 +284,68 @@ void LLParticipantList::refreshSpeakers() case 2: icon_cell->setValue("icn_active-speakers-dot-lvl2.tga"); break; + } + // non voice speakers have hidden icons, render as transparent + icon_cell->setColor(speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE ? LLColor4::transparent : speakerp->mDotColor); } - // non voice speakers have hidden icons, render as transparent - icon_cell->setColor(speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE ? LLColor4::transparent : speakerp->mDotColor); - } - } - // update name column - if (LLScrollListCell* name_cell = itemp->getColumn(1)) - { - if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL) - { - // draw inactive speakers in different color - static const LLCachedControl sSpeakersInactive(gColors, "SpeakersInactive"); - name_cell->setColor(sSpeakersInactive); } - else + // update name column + if (LLScrollListCell* name_cell = itemp->getColumn(1)) { - // - bool found = mShowTextChatters || speakerp->mID == gAgentID; - const LLWorld::region_list_t& regions = LLWorld::getInstance()->getRegionList(); - for (LLWorld::region_list_t::const_iterator iter = regions.begin(); !found && iter != regions.end(); ++iter) - { - // Are they in this sim? - if (const LLViewerRegion* regionp = *iter) - if (std::find(regionp->mMapAvatarIDs.begin(), regionp->mMapAvatarIDs.end(), speakerp->mID) != regionp->mMapAvatarIDs.end()) - found = true; - } - if (!found) + if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL) { - static const LLCachedControl sSpeakersGhost(gColors, "SpeakersGhost"); - name_cell->setColor(sSpeakersGhost); + // draw inactive speakers in different color + static const LLCachedControl sSpeakersInactive(gColors, "SpeakersInactive"); + name_cell->setColor(sSpeakersInactive); } else - // { - static const LLCachedControl sDefaultListText(gColors, "DefaultListText"); - name_cell->setColor(sDefaultListText); + // + bool found = mShowTextChatters || speakerp->mID == gAgentID; + if (!found) + for (const LLViewerRegion* regionp : LLWorld::getInstance()->getRegionList()) + { + // Are they in this sim? + if (std::find(regionp->mMapAvatarIDs.begin(), regionp->mMapAvatarIDs.end(), speakerp->mID) != regionp->mMapAvatarIDs.end()) + { + found = true; + break; + } + } + if (!found) + { + static const LLCachedControl sSpeakersGhost(gColors, "SpeakersGhost"); + name_cell->setColor(sSpeakersGhost); + } + else + // + { + static const LLCachedControl sDefaultListText(gColors, "DefaultListText"); + name_cell->setColor(sDefaultListText); + } } } - + } + // update name column. Need to update all rows to make name sorting behave correctly. + if (LLScrollListCell* name_cell = itemp->getColumn(1)) + { std::string speaker_name = speakerp->mDisplayName.empty() ? LLCacheName::getDefaultName() : speakerp->mDisplayName; if (speakerp->mIsModerator) - speaker_name += " " + getString("moderator_label"); - name_cell->setValue(speaker_name); + speaker_name += ' ' + getString("moderator_label"); + if (name_cell->getValue().asString() != speaker_name) + { + re_sort = true; + name_cell->setValue(speaker_name); + } static_cast(name_cell)->setFontStyle(speakerp->mIsModerator ? LLFontGL::BOLD : LLFontGL::NORMAL); } - // update speaking order column - if (LLScrollListCell* speaking_status_cell = itemp->getColumn(2)) - { - // since we are forced to sort by text, encode sort order as string - // print speaking ordinal in a text-sorting friendly manner - speaking_status_cell->setValue(llformat("%010d", speakerp->mSortIndex)); - } } // we potentially modified the sort order by touching the list items - mAvatarList->setNeedsSort(); + if (re_sort) + { + mAvatarList->setNeedsSortColumn(1); + } // keep scroll value stable mAvatarList->getScrollInterface()->setScrollPos(scroll_pos); @@ -358,6 +382,7 @@ bool LLParticipantList::onRemoveItemEvent(LLPointer event, bool LLParticipantList::onClearListEvent(LLPointer event, const LLSD& userdata) { mAvatarList->clearRows(); + setupContextMenu(); return true; } @@ -378,6 +403,44 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer event return true; } +void LLParticipantList::onSpeakerBatchBeginEvent() +{ + mAvatarList->setSortEnabled(false); +} + +void LLParticipantList::onSpeakerBatchEndEvent() +{ + mAvatarList->setSortEnabled(true); +} + +void LLParticipantList::onSpeakerSortingUpdateEvent() +{ + bool re_sort = false; + for (auto&& item : mAvatarList->getAllData()) + { + // update speaking order column + if (LLScrollListCell* speaking_status_cell = item->getColumn(2)) + { + LLPointer speakerp = mSpeakerMgr->findSpeaker(item->getUUID()); + if (speakerp) + { + re_sort = true; + std::string sort_index = llformat("%010d", speakerp->mSortIndex); + // since we are forced to sort by text, encode sort order as string + // print speaking ordinal in a text-sorting friendly manner + if (speaking_status_cell->getValue().asString() != sort_index) + { + speaking_status_cell->setValue(sort_index); + } + } + } + } + if (re_sort) + { + mAvatarList->setNeedsSortColumn(2); + } +} + void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) { //if (mExcludeAgent && gAgent.getID() == avatar_id) return; @@ -405,22 +468,16 @@ void LLParticipantList::adjustParticipant(const LLUUID& speaker_id) LLPointer speakerp = mSpeakerMgr->findSpeaker(speaker_id); if (speakerp.isNull()) return; - LLSD row; - row["id"] = speaker_id; - LLSD& columns = row["columns"]; - columns[0]["column"] = "icon_speaking_status"; - columns[0]["type"] = "icon"; - columns[0]["value"] = "icn_active-speakers-dot-lvl0.tga"; - + LLNameListItem::Params name_item; + name_item.value = speaker_id; + name_item.columns.add(LLScrollListCell::Params().column("icon_speaking_status").type("icon").value("icn_active-speakers-dot-lvl0.tga")); const std::string& display_name = LLVoiceClient::getInstance()->getDisplayName(speaker_id); - columns[1]["column"] = "speaker_name"; - columns[1]["type"] = "text"; - columns[1]["value"] = display_name.empty() ? LLCacheName::getDefaultName() : display_name; + name_item.name = display_name; + name_item.columns.add(LLScrollListCell::Params().column("speaker_name").type("text").value(display_name)); + name_item.columns.add(LLScrollListCell::Params().column("speaking_status").type("text") + .value(llformat("%010d", speakerp->mSortIndex))); // print speaking ordinal in a text-sorting friendly manner - columns[2]["column"] = "speaking_status"; - columns[2]["type"] = "text"; - columns[2]["value"] = llformat("%010d", speakerp->mSortIndex); // print speaking ordinal in a text-sorting friendly manner - mAvatarList->addElement(row); + mAvatarList->addNameItemRow(name_item); // add listener to process moderation changes speakerp->addListener(mSpeakerMuteListener); @@ -468,6 +525,23 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer event, const LLSD& userdata) +{ + mParent.onSpeakerBatchBeginEvent(); + return true; +} +bool LLParticipantList::SpeakerBatchEndListener::handleEvent(LLPointer event, const LLSD& userdata) +{ + mParent.onSpeakerBatchEndEvent(); + return true; +} + +bool LLParticipantList::SpeakerSortingUpdateListener::handleEvent(LLPointer event, const LLSD& userdata) +{ + mParent.onSpeakerSortingUpdateEvent(); + return true; +} + // Singu Note: The following functions are actually of the LLParticipantListMenu class, but we haven't married lists with menus yet. void LLParticipantList::toggleAllowTextChat(const LLSD& userdata) { diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 1177b778a0..091753d5dc 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -30,7 +30,7 @@ #include "lllayoutstack.h" class LLSpeakerMgr; -class LLScrollListCtrl; +class LLNameListCtrl; class LLUICtrl; class LLParticipantList : public LLLayoutPanel @@ -76,6 +76,9 @@ class LLParticipantList : public LLLayoutPanel bool onClearListEvent(LLPointer event, const LLSD& userdata); //bool onModeratorUpdateEvent(LLPointer event, const LLSD& userdata); bool onSpeakerMuteEvent(LLPointer event, const LLSD& userdata); + void onSpeakerBatchBeginEvent(); + void onSpeakerBatchEndEvent(); + void onSpeakerSortingUpdateEvent(); /** * List of listeners implementing LLOldEvents::LLSimpleListener. @@ -126,6 +129,27 @@ class LLParticipantList : public LLLayoutPanel /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); }; + class SpeakerBatchBeginListener : public BaseSpeakerListener + { + public: + SpeakerBatchBeginListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); + }; + + class SpeakerBatchEndListener : public BaseSpeakerListener + { + public: + SpeakerBatchEndListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); + }; + + class SpeakerSortingUpdateListener : public BaseSpeakerListener + { + public: + SpeakerSortingUpdateListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); + }; + /** * Menu used in the participant list. class LLParticipantListMenu : public LLListContextMenu @@ -179,6 +203,7 @@ class LLParticipantList : public LLLayoutPanel private: void onAvatarListDoubleClicked(); + void setupContextMenu(); /** * Adjusts passed participant to work properly. @@ -194,14 +219,18 @@ class LLParticipantList : public LLLayoutPanel void onVolumeChange(const LLSD& param); LLSpeakerMgr* mSpeakerMgr; - LLScrollListCtrl* mAvatarList; + LLNameListCtrl* mAvatarList; bool mShowTextChatters; + LLFrameTimer mUpdateTimer; LLPointer mSpeakerAddListener; LLPointer mSpeakerRemoveListener; LLPointer mSpeakerClearListener; //LLPointer mSpeakerModeratorListener; LLPointer mSpeakerMuteListener; + LLPointer mSpeakerBatchBeginListener; + LLPointer mSpeakerBatchEndListener; + LLPointer mSpeakerSortingUpdateListener; validate_speaker_callback_t mValidateSpeakerCallback; }; diff --git a/indra/newview/llprefschat.cpp b/indra/newview/llprefschat.cpp index f62a4d4e9e..f76df16791 100644 --- a/indra/newview/llprefschat.cpp +++ b/indra/newview/llprefschat.cpp @@ -179,7 +179,6 @@ void LLPrefsChatImpl::apply() gSavedSettings.setColor4("BackgroundChatColor", childGetValue("background")); gSavedSettings.setColor4("HTMLLinkColor", childGetValue("links")); - LLTextEditor::setLinkColor(childGetValue("links")); gSavedSettings.setBOOL("ArrowKeysMoveAvatar", childGetValue("arrow_keys_move_avatar_check")); gSavedSettings.setBOOL("ChatShowTimestamps", childGetValue("show_timestamps_check")); diff --git a/indra/newview/llprefsim.cpp b/indra/newview/llprefsim.cpp index 2f7faca756..8023cd1a37 100644 --- a/indra/newview/llprefsim.cpp +++ b/indra/newview/llprefsim.cpp @@ -63,7 +63,7 @@ class LLPrefsIMImpl : public LLPanel void apply(); void cancel(); - void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email); + void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email, bool is_verified); void enableHistory(); static void onClickLogPath(void* user_data); @@ -193,13 +193,6 @@ void LLPrefsIMImpl::apply() if((new_im_via_email != mOriginalIMViaEmail) ||(new_hide_online != mOriginalHideOnlineStatus)) { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_UpdateUserInfo); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_UserData); - msg->addBOOLFast(_PREHASH_IMViaEMail, new_im_via_email); // This hack is because we are representing several different // possible strings with a single checkbox. Since most users // can only select between 2 values, we represent it as a @@ -212,8 +205,7 @@ void LLPrefsIMImpl::apply() //Update showonline value, otherwise multiple applys won't work mOriginalHideOnlineStatus = new_hide_online; } - msg->addString("DirectoryVisibility", mDirectoryVisibility); - gAgent.sendReliableMessage(); + gAgent.sendAgentUpdateUserInfo(new_im_via_email, mDirectoryVisibility); } } else @@ -227,7 +219,7 @@ void LLPrefsIMImpl::apply() } } -void LLPrefsIMImpl::setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email) +void LLPrefsIMImpl::setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email, bool is_verified) { mGotPersonalInfo = true; mOriginalIMViaEmail = im_via_email; @@ -254,8 +246,13 @@ void LLPrefsIMImpl::setPersonalInfo(const std::string& visibility, bool im_via_e childSetValue("online_visibility", mOriginalHideOnlineStatus); childSetLabelArg("online_visibility", "[DIR_VIS]", mDirectoryVisibility); - childEnable("send_im_to_email"); - childSetValue("send_im_to_email", im_via_email); + if (auto child = getChildView("send_im_to_email")) + { + child->setValue(im_via_email); + child->setEnabled(is_verified); + if (!is_verified) + child->setToolTip(getString("email_unverified_tooltip")); + } childEnable("log_instant_messages"); childEnable("log_chat"); childEnable("log_instant_messages_timestamp"); @@ -332,9 +329,9 @@ void LLPrefsIM::cancel() impl.cancel(); } -void LLPrefsIM::setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email) +void LLPrefsIM::setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email, bool is_verified) { - impl.setPersonalInfo(visibility, im_via_email, email); + impl.setPersonalInfo(visibility, im_via_email, email, is_verified); } LLPanel* LLPrefsIM::getPanel() diff --git a/indra/newview/llprefsim.h b/indra/newview/llprefsim.h index 90bf4656a7..7b7b3cefc1 100644 --- a/indra/newview/llprefsim.h +++ b/indra/newview/llprefsim.h @@ -45,7 +45,7 @@ class LLPrefsIM void apply(); void cancel(); - void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email); + void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email, bool is_verified); LLPanel* getPanel(); diff --git a/indra/newview/llprefsvoice.cpp b/indra/newview/llprefsvoice.cpp index 86e39d07db..ccd5743c74 100644 --- a/indra/newview/llprefsvoice.cpp +++ b/indra/newview/llprefsvoice.cpp @@ -35,8 +35,8 @@ #include "llprefsvoice.h" -#include "floatervoicelicense.h" #include "llcheckboxctrl.h" +#include "llfloatertos.h" #include "llfocusmgr.h" #include "llkeyboard.h" #include "llmodaldialog.h" @@ -158,8 +158,9 @@ void LLPrefsVoice::apply() if (enable_voice && !gSavedSettings.getBOOL("VivoxLicenseAccepted")) { // This window enables voice chat if license is accepted - FloaterVoiceLicense::getInstance()->open(); - FloaterVoiceLicense::getInstance()->center(); + auto inst = LLFloaterTOS::show(LLFloaterTOS::TOS_VOICE); + inst->open(); + inst->center(); } else { diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h index 02184af85c..5203ce31fa 100644 --- a/indra/newview/llpreview.h +++ b/indra/newview/llpreview.h @@ -137,6 +137,8 @@ class LLPreview : public LLFloater, LLInventoryObserver // for LLInventoryObserver virtual void changed(U32 mask); BOOL mDirty; + +public: virtual const char *getTitleName() const { return "Preview"; } protected: diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index c0ab5ef97d..a375be2d03 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -86,10 +86,9 @@ class LLInventoryGestureAvailable : public LLInventoryCompletionObserver void LLInventoryGestureAvailable::done() { - for(uuid_vec_t::iterator it = mComplete.begin(); it != mComplete.end(); ++it) + for(auto id : mComplete) { - LLPreview* preview = LLPreview::find((*it)); - if(preview) + if (auto preview = LLPreview::find(id)) { preview->refresh(); } @@ -98,15 +97,6 @@ void LLInventoryGestureAvailable::done() delete this; } -// Used for sorting -struct SortItemPtrsByName -{ - bool operator()(const LLInventoryItem* i1, const LLInventoryItem* i2) - { - return (LLStringUtil::compareDict(i1->getName(), i2->getName()) < 0); - } -}; - // static LLPreviewGesture* LLPreviewGesture::show(const std::string& title, const LLUUID& item_id, const LLUUID& object_id, BOOL take_focus) { @@ -128,7 +118,7 @@ LLPreviewGesture* LLPreviewGesture::show(const std::string& title, const LLUUID& // Move window to top-left of screen LLMultiFloater* hostp = preview->getHost(); - if (hostp == NULL) + if (hostp == nullptr) { LLRect r = preview->getRect(); LLRect screen = gFloaterView->getRect(); @@ -226,7 +216,7 @@ BOOL LLPreviewGesture::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, } else if (drop) { - LLScrollListItem* line = NULL; + LLScrollListItem* line = nullptr; if (cargo_type == DAD_ANIMATION) { line = addStep( STEP_ANIMATION ); @@ -342,23 +332,23 @@ bool LLPreviewGesture::handleSaveChangesDialog(const LLSD& notification, const L LLPreviewGesture::LLPreviewGesture() : LLPreview("Gesture Preview"), - mTriggerEditor(NULL), - mModifierCombo(NULL), - mKeyCombo(NULL), - mLibraryList(NULL), - mAddBtn(NULL), - mUpBtn(NULL), - mDownBtn(NULL), - mDeleteBtn(NULL), - mStepList(NULL), - mOptionsText(NULL), - mAnimationRadio(NULL), - mAnimationCombo(NULL), - mSoundCombo(NULL), - mChatEditor(NULL), - mSaveBtn(NULL), - mPreviewBtn(NULL), - mPreviewGesture(NULL), + mTriggerEditor(nullptr), + mModifierCombo(nullptr), + mKeyCombo(nullptr), + mLibraryList(nullptr), + mAddBtn(nullptr), + mUpBtn(nullptr), + mDownBtn(nullptr), + mDeleteBtn(nullptr), + mStepList(nullptr), + mOptionsText(nullptr), + mAnimationRadio(nullptr), + mAnimationCombo(nullptr), + mSoundCombo(nullptr), + mChatEditor(nullptr), + mSaveBtn(nullptr), + mPreviewBtn(nullptr), + mPreviewGesture(nullptr), mDirty(FALSE) { } @@ -367,14 +357,11 @@ LLPreviewGesture::LLPreviewGesture() LLPreviewGesture::~LLPreviewGesture() { // Userdata for all steps is a LLGestureStep we need to clean up - std::vector data_list = mStepList->getAllData(); - std::vector::iterator data_itor; - for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor) + for (auto& item : mStepList->getAllData()) { - LLScrollListItem* item = *data_itor; LLGestureStep* step = (LLGestureStep*)item->getUserdata(); delete step; - step = NULL; + step = nullptr; } } @@ -517,9 +504,10 @@ BOOL LLPreviewGesture::postBuild() if (item) { - childSetCommitCallback("desc", LLPreview::onText, this); - childSetText("desc", item->getDescription()); - getChild("desc")->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe); + auto desc = getChild("desc"); + desc->setCommitCallback(LLPreview::onText, this); + desc->setValue(item->getDescription()); + desc->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe); } return TRUE; @@ -541,7 +529,20 @@ static const std::string valid_key_to_string(KEY key) { std::string skey(1,(char)key); std::string strkey = LLKeyboard::stringFromKey(key); - return ((skey == strkey && key >= ' ' && key <= '~') || (skey != strkey) ) ? strkey : ""; + return ((skey == strkey && key >= ' ' && key <= '~') || (skey != strkey) ) ? strkey : LLStringUtil::null; +} + +void load_and_sort(LLComboBox* combo, const LLViewerInventoryItem::item_array_t& items) +{ + combo->removeall(); + + // Load up the combobox + for (const auto& item : items) + { + combo->add(item->getName(), item->getAssetUUID()); + } + // Sort + combo->sortByName(); } void LLPreviewGesture::addKeys() @@ -549,10 +550,10 @@ void LLPreviewGesture::addKeys() LLComboBox* combo = mKeyCombo; combo->add( NONE_LABEL ); - for (KEY key = ' '; key < KEY_NONE; key++) + for (KEY key = ' '; key < KEY_NONE; ++key) { std::string keystr = valid_key_to_string(key); - if(keystr != "")combo->add( keystr, ADD_BOTTOM ); + if (!keystr.empty()) combo->add( keystr, ADD_BOTTOM ); } combo->setCurrentByIndex(0); } @@ -562,22 +563,7 @@ void LLPreviewGesture::addKeys() void LLPreviewGesture::addAnimations() { LLComboBox* combo = mAnimationCombo; - combo->removeall(); - - std::string none_text = getString("none_text"); - - combo->add(none_text, LLUUID::null); - - // Add all the default (legacy) animations - S32 i; - for (i = 0; i < gUserAnimStatesCount; ++i) - { - // Use the user-readable name - std::string label = LLAnimStateLabels::getStateLabel( gUserAnimStates[i].mName ); - const LLUUID& id = gUserAnimStates[i].mID; - combo->add(label, id); - } // Get all inventory items that are animations LLViewerInventoryCategory::cat_array_t cats; @@ -592,38 +578,21 @@ void LLPreviewGesture::addAnimations() LLInventoryModel::EXCLUDE_TRASH, is_copyable_animation); - // Copy into something we can sort - std::vector animations; + load_and_sort(combo, items); - S32 count = items.size(); - for(i = 0; i < count; ++i) - { - animations.push_back( items.at(i) ); - } - - // Do the sort - std::sort(animations.begin(), animations.end(), SortItemPtrsByName()); - - // And load up the combobox - std::vector::iterator it; - for (it = animations.begin(); it != animations.end(); ++it) + // Add all the default (legacy) animations + for (S32 i = gUserAnimStatesCount - 1; i >= 0; --i) { - LLInventoryItem* item = *it; - - combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM); + // Use the user-readable name + const auto& state = gUserAnimStates[i]; + combo->add(LLAnimStateLabels::getStateLabel(state.mName), state.mID, ADD_TOP); } + combo->add(getString("none_text"), LLUUID::null, ADD_TOP); } void LLPreviewGesture::addSounds() { - LLComboBox* combo = mSoundCombo; - combo->removeall(); - - std::string none_text = getString("none_text"); - - combo->add(none_text, LLUUID::null); - // Get all inventory items that are sounds LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; @@ -637,27 +606,9 @@ void LLPreviewGesture::addSounds() LLInventoryModel::EXCLUDE_TRASH, is_copyable_sound); - // Copy sounds into something we can sort - std::vector sounds; - - S32 i; - S32 count = items.size(); - for(i = 0; i < count; ++i) - { - sounds.push_back( items.at(i) ); - } - - // Do the sort - std::sort(sounds.begin(), sounds.end(), SortItemPtrsByName()); - - // And load up the combobox - std::vector::iterator it; - for (it = sounds.begin(); it != sounds.end(); ++it) - { - LLInventoryItem* item = *it; - - combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM); - } + LLComboBox* combo = mSoundCombo; + load_and_sort(combo, items); + combo->add(getString("none_text"), LLUUID::null, ADD_TOP); } @@ -732,12 +683,12 @@ void LLPreviewGesture::refresh() BOOL have_replace = !replace.empty(); LLScrollListItem* library_item = mLibraryList->getFirstSelected(); - BOOL have_library = (library_item != NULL); + BOOL have_library = (library_item != nullptr); LLScrollListItem* step_item = mStepList->getFirstSelected(); S32 step_index = mStepList->getFirstSelectedIndex(); S32 step_count = mStepList->getItemCount(); - BOOL have_step = (step_item != NULL); + BOOL have_step = (step_item != nullptr); mReplaceText->setEnabled(have_trigger || have_replace); mReplaceEditor->setEnabled(have_trigger || have_replace); @@ -937,7 +888,7 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs, } delete gesture; - gesture = NULL; + gesture = nullptr; self->mAssetStatus = PREVIEW_ASSET_LOADED; } @@ -960,7 +911,7 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs, } } delete item_idp; - item_idp = NULL; + item_idp = nullptr; } @@ -1007,7 +958,7 @@ void LLPreviewGesture::loadUIFromGesture(LLMultiGesture* gesture) { LLGestureStep* step = gesture->mSteps[i]; - LLGestureStep* new_step = NULL; + LLGestureStep* new_step = nullptr; switch(step->getType()) { @@ -1099,23 +1050,22 @@ void LLPreviewGesture::saveIfNeeded() LLDataPackerAsciiBuffer dp(buffer, max_size); - BOOL ok = gesture->serialize(dp); - - // - //if (dp.getCurrentSize() > 1000) - if(0) - // + bool ok = gesture->serialize(dp); +#if 0 // + if (dp.getCurrentSize() > 1000) { LLNotificationsUtil::add("GestureSaveFailedTooManySteps"); delete gesture; - gesture = NULL; + gesture = nullptr; } else if (!ok) +#endif // + if (!ok) { LLNotificationsUtil::add("GestureSaveFailedTryAgain"); delete gesture; - gesture = NULL; + gesture = nullptr; } else { @@ -1187,7 +1137,7 @@ void LLPreviewGesture::saveIfNeeded() { // we're done with this gesture delete gesture; - gesture = NULL; + gesture = nullptr; } mDirty = FALSE; @@ -1200,7 +1150,7 @@ void LLPreviewGesture::saveIfNeeded() } delete [] buffer; - buffer = NULL; + buffer = nullptr; } @@ -1237,7 +1187,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, { // Saving into in-world object inventory LLViewerObject* object = gObjectList.findObject(info->mObjectUUID); - LLViewerInventoryItem* item = NULL; + LLViewerInventoryItem* item = nullptr; if(object) { item = (LLViewerInventoryItem*)object->getInventoryObject(info->mItemUUID); @@ -1271,7 +1221,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, LLNotificationsUtil::add("GestureSaveFailedReason", args); } delete info; - info = NULL; + info = nullptr; } @@ -1306,11 +1256,8 @@ LLMultiGesture* LLPreviewGesture::createGesture() LLKeyboard::keyFromString(key_string, &(gesture->mKey)); } - std::vector data_list = mStepList->getAllData(); - std::vector::iterator data_itor; - for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor) + for (auto& item : mStepList->getAllData()) { - LLScrollListItem* item = *data_itor; LLGestureStep* step = (LLGestureStep*)item->getUserdata(); switch(step->getType()) @@ -1366,11 +1313,7 @@ LLMultiGesture* LLPreviewGesture::createGesture() void LLPreviewGesture::updateLabel(LLScrollListItem* item) { LLGestureStep* step = (LLGestureStep*)item->getUserdata(); - - LLScrollListCell* cell = item->getColumn(0); - LLScrollListText* text_cell = (LLScrollListText*)cell; - std::string label = getLabel( step->getLabel()); - text_cell->setText(label); + static_cast(item->getColumn(0))->setText(getLabel(step->getLabel())); } void LLPreviewGesture::onCommitSetDirty() @@ -1518,9 +1461,7 @@ void LLPreviewGesture::onCommitWait() LLLocale locale(LLLocale::USER_LOCALE); F32 wait_seconds = (F32)atof(mWaitTimeEditor->getText().c_str()); - if (wait_seconds < 0.f) wait_seconds = 0.f; - if (wait_seconds > 3600.f) wait_seconds = 3600.f; - wait_step->mWaitSeconds = wait_seconds; + wait_step->mWaitSeconds = llclamp(wait_seconds, 0.f, 3600.f); } // Enable the input area if necessary @@ -1579,7 +1520,7 @@ LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type ) { // Order of enum EStepType MUST match the library_list element in floater_preview_gesture.xml - LLGestureStep* step = NULL; + LLGestureStep* step = nullptr; switch( step_type) { case STEP_ANIMATION: @@ -1596,13 +1537,14 @@ LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type ) break; default: LL_ERRS() << "Unknown step type: " << (S32)step_type << LL_ENDL; - return NULL; + return nullptr; } // Create an enabled item with this step LLSD row; - row["columns"][0]["value"] = getLabel(step->getLabel()); - row["columns"][0]["font"] = "SANSSERIF_SMALL"; + auto& element = row["columns"][0]; + element["value"] = getLabel(step->getLabel()); + element["font"] = "SANSSERIF_SMALL"; LLScrollListItem* step_item = mStepList->addElement(row); step_item->setUserdata(step); @@ -1616,57 +1558,66 @@ LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type ) } // static -std::string LLPreviewGesture::getLabel(std::vector labels) +std::string LLPreviewGesture::getLabel(const std::vector& v_labels) { - std::vector v_labels = labels ; - std::string result(""); - if( v_labels.size() != 2) { - return result; + return LLStringUtil::null; } - - if(v_labels[0]=="Chat") + + auto result(v_labels[0]); + if (result == "Chat") { - result=LLTrans::getString("Chat Message"); + static const auto chat = LLTrans::getString("Chat Message"); + result = chat; } - else if(v_labels[0]=="Sound") + else if (result == "Sound") { - result=LLTrans::getString("Sound"); + static const auto sound = LLTrans::getString("Sound"); + result = sound; } - else if(v_labels[0]=="Wait") + else if (result == "Wait") { - result=LLTrans::getString("Wait"); + static const auto wait = LLTrans::getString("Wait"); + result = wait; } - else if(v_labels[0]=="AnimFlagStop") + else if (result == "AnimFlagStop") { - result=LLTrans::getString("AnimFlagStop"); + static const auto stop = LLTrans::getString("AnimFlagStop"); + result = stop; } - else if(v_labels[0]=="AnimFlagStart") + else if (result == "AnimFlagStart") { - result=LLTrans::getString("AnimFlagStart"); + static const auto start = LLTrans::getString("AnimFlagStart"); + result = start; } // lets localize action value std::string action = v_labels[1]; if ("None" == action) { - action = LLTrans::getString("GestureActionNone"); + static const auto none = LLTrans::getString("GestureActionNone"); + action = none; } else if ("until animations are done" == action) { //action = LLFloaterReg::getInstance("preview_gesture")->getChild("wait_anim_check")->getLabel(); //Worst. Thing. Ever. We are in a static function. Find any existing gesture preview and grab the label from its 'wait_anim_check' element. - for(preview_map_t::iterator it = LLPreview::sInstances.begin(); it != LLPreview::sInstances.end();++it) + static auto wait_anim = LLStringUtil::null; + if (wait_anim.empty()) { - LLPreviewGesture* pPreview = dynamic_cast(it->second); - if(pPreview) + for(const auto& pair : LLPreview::sInstances) { - pPreview->getChild("wait_anim_check")->getLabel(); - break; + const auto& pPreview(pair.second); + constexpr std::string_view gesture("Gesture"); + if (pPreview && std::string_view(pPreview->getTitleName()) == gesture) + { + wait_anim = pPreview->getChild("wait_anim_check")->getLabel(); + break; + } } } - + action = wait_anim; } result.append(action); return result; @@ -1716,13 +1667,14 @@ void LLPreviewGesture::onClickDelete() void LLPreviewGesture::onCommitActive() { - if (!LLGestureMgr::instance().isGestureActive(mItemUUID)) + auto& inst(LLGestureMgr::instance()); + if (!inst.isGestureActive(mItemUUID)) { - LLGestureMgr::instance().activateGesture(mItemUUID); + inst.activateGesture(mItemUUID); } else { - LLGestureMgr::instance().deactivateGesture(mItemUUID); + inst.deactivateGesture(mItemUUID); } // Make sure the (active) label in the inventory gets updated. @@ -1773,7 +1725,7 @@ void LLPreviewGesture::onDonePreview(LLMultiGesture* gesture) mPreviewBtn->setLabel(getString("preview_txt")); delete mPreviewGesture; - mPreviewGesture = NULL; + mPreviewGesture = nullptr; refresh(); } diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h index 7bb27063ff..757d843085 100644 --- a/indra/newview/llpreviewgesture.h +++ b/indra/newview/llpreviewgesture.h @@ -113,7 +113,7 @@ class LLPreviewGesture : public LLPreview // "Sound", "Chat", or "Wait" LLScrollListItem* addStep(const enum EStepType step_type); - static std::string getLabel(std::vector labels); + static std::string getLabel(const std::vector& labels); static void updateLabel(LLScrollListItem* item); void onCommitSetDirty(); diff --git a/indra/newview/llpreviewlandmark.cpp b/indra/newview/llpreviewlandmark.cpp index c67f7c13d7..ac70e0ccc9 100644 --- a/indra/newview/llpreviewlandmark.cpp +++ b/indra/newview/llpreviewlandmark.cpp @@ -43,7 +43,6 @@ #include "llagent.h" #include "llbutton.h" -#include "lleconomy.h" #include "llfloaterinventory.h" #include "llfloaterworldmap.h" #include "lliconctrl.h" @@ -63,10 +62,6 @@ //////////////////////////////////////////////////////////////////////////// // LLPreviewLandmark -// static -LLPreviewLandmarkList LLPreviewLandmark::sOrderedInstances; - - LLPreviewLandmark::LLPreviewLandmark(const std::string& name, const LLRect& rect, const std::string& title, @@ -112,18 +107,10 @@ LLPreviewLandmark::LLPreviewLandmark(const std::string& name, translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop); } */ - LLPreviewLandmark::sOrderedInstances.push_back( this ); } LLPreviewLandmark::~LLPreviewLandmark() { - LLPreviewLandmarkList::iterator this_itr; - this_itr = std::find(LLPreviewLandmark::sOrderedInstances.begin(), - LLPreviewLandmark::sOrderedInstances.end(), this); - if (this_itr != LLPreviewLandmark::sOrderedInstances.end()) - { - LLPreviewLandmark::sOrderedInstances.erase(this_itr); - } } diff --git a/indra/newview/llpreviewlandmark.h b/indra/newview/llpreviewlandmark.h index 5957eb46d4..82e358ed38 100644 --- a/indra/newview/llpreviewlandmark.h +++ b/indra/newview/llpreviewlandmark.h @@ -33,72 +33,43 @@ #ifndef LL_LLPREVIEWLANDMARK_H #define LL_LLPREVIEWLANDMARK_H -#include - -#include "lllandmark.h" - -#include "llfloater.h" -#include "llmap.h" -#include "llstring.h" -#include "lluuid.h" -#include "v3dmath.h" -#include "v4coloru.h" - -#include "llhudtext.h" #include "llpreview.h" class LLIconCtrl; -class LLInventoryItem; -class LLLandmarkList; -class LLLineEditor; -class LLMessageSystem; -class LLPreviewLandmark; class LLPanelPlace; +class LLLandmark; -const S32 PREVIEW_LANDMARK_NUM_COLORS = 6; - -typedef std::deque< LLPreviewLandmark* > LLPreviewLandmarkList; - -class LLPreviewLandmark : public LLPreview +class LLPreviewLandmark final : public LLPreview { public: LLPreviewLandmark(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid, BOOL show_keep_discard = FALSE, - LLViewerInventoryItem* inv_item = NULL); + LLViewerInventoryItem* inv_item = nullptr); virtual ~LLPreviewLandmark(); - /*virtual*/ void draw(); + /*virtual*/ void draw() override; const std::string& getName() const; const LLColor4& getMarkerColor() const; LLVector3d getPositionGlobal() const; - //static S32 getNumInstances() { return LLPreviewLandmark::sOrderedInstances.getLength(); } - //static const LLPreviewLandmark* getFirst() { return LLPreviewLandmark::sOrderedInstances.getFirstData(); } - //static const LLPreviewLandmark* getNext() { return LLPreviewLandmark::sOrderedInstances.getNextData(); } - static void* createPlaceDetail(void* userdata); - /*virtual*/ void loadAsset(); - /*virtual*/ EAssetStatus getAssetStatus(); + /*virtual*/ void loadAsset() override; + /*virtual*/ EAssetStatus getAssetStatus() override; protected: void getDegreesAndDist(F32* degrees, F64* horiz_dist, F64* vert_dist) const; - virtual const char *getTitleName() const { return "Landmark"; } + const char *getTitleName() const override { return "Landmark"; } private: -// void renderBeacon(); -// LLPointer mBeaconText; - LLIconCtrl* mIconLandmark; LLPanelPlace* mPlacePanel; LLLandmark* mLandmark; LLColor4 mMarkerColor; - - static LLPreviewLandmarkList sOrderedInstances; }; #endif diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index e5b8d4898d..75afa197f4 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -45,6 +45,7 @@ #include "llfloatersearchreplace.h" #include "llinventorymodel.h" #include "lllineeditor.h" +#include "llmenugl.h" #include "llnotificationsutil.h" #include "llresmgr.h" #include "roles_constants.h" @@ -286,6 +287,8 @@ void LLPreviewNotecard::loadAsset() // request the asset. if (const LLInventoryItem* item = getItem()) { + bool modify = gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); + if (modify) editor->setParseHTML(false); // Don't do the url parsing or we'll lose text! if (gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE) || gAgent.isGodlike()) @@ -344,8 +347,7 @@ void LLPreviewNotecard::loadAsset() editor->setEnabled(FALSE); mAssetStatus = PREVIEW_ASSET_LOADED; } - if(!gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), - GP_OBJECT_MANIPULATE)) + if(!modify) { editor->setEnabled(FALSE); // You can always save in task inventory @@ -387,7 +389,11 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs, // put a EOS at the end buffer[file_length] = 0; - + // Singu Note: Set Enabled first, it determines whether or not our text will be linked + const LLInventoryItem* item = preview->getItem(); + BOOL modifiable = item && gAgent.allowOperation(PERM_MODIFY, + item->getPermissions(), GP_OBJECT_MANIPULATE); + preview->setEnabled(modifiable); if (LLViewerTextEditor* previewEditor = preview->findChild("Notecard Editor")) { if ((file_length > 19) && !strncmp(buffer, "Linden text version", 19)) @@ -400,16 +406,11 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs, else { // Version 0 (just text, doesn't include version number) - previewEditor->setText(LLStringExplicit(buffer)); + previewEditor->setText(LLStringExplicit(buffer), false); } previewEditor->makePristine(); } - - const LLInventoryItem* item = preview->getItem(); - BOOL modifiable = item && gAgent.allowOperation(PERM_MODIFY, - item->getPermissions(), GP_OBJECT_MANIPULATE); - preview->setEnabled(modifiable); delete[] buffer; preview->mAssetStatus = PREVIEW_ASSET_LOADED; } @@ -613,7 +614,7 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data } else { - LL_WARNS() << "Inventory item for script " << info->mItemUUID + LL_WARNS() << "Inventory item for notecard " << info->mItemUUID << " is no longer in agent inventory." << LL_ENDL; } } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 1039544c28..3cd30ce8e1 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1,11 +1,11 @@ -/** +/** * @file llpreviewscript.cpp * @brief LLPreviewScript class implementation * * $LicenseInfo:firstyear=2002&license=viewergpl$ - * + * * Copyright (c) 2002-2009, Linden Research, Inc. - * + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 @@ -13,17 +13,17 @@ * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. @@ -39,6 +39,7 @@ #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" +#include "llcororesponder.h" #include "lldir.h" #include "llexternaleditor.h" #include "statemachine/aifilepicker.h" @@ -80,6 +81,8 @@ #include "lluictrlfactory.h" #include "lltrans.h" #include "llappviewer.h" +#include "llexperiencecache.h" +#include "llfloaterexperienceprofile.h" #include "llsdserialize.h" @@ -116,13 +119,13 @@ const S32 LINE_COLUMN_HEIGHT = 14; const S32 SCRIPT_EDITOR_MIN_HEIGHT = 2 * SCROLLBAR_SIZE + 2 * LLPANEL_BORDER_WIDTH + 128; -const S32 SCRIPT_MIN_WIDTH = - 2 * SCRIPT_BORDER + - 2 * SCRIPT_BUTTON_WIDTH + +const S32 SCRIPT_MIN_WIDTH = + 2 * SCRIPT_BORDER + + 2 * SCRIPT_BUTTON_WIDTH + SCRIPT_PAD + RESIZE_HANDLE_WIDTH + SCRIPT_PAD; -const S32 SCRIPT_MIN_HEIGHT = +const S32 SCRIPT_MIN_HEIGHT = 2 * SCRIPT_BORDER + 3*(SCRIPT_BUTTON_HEIGHT + SCRIPT_PAD) + LINE_COLUMN_HEIGHT + @@ -139,13 +142,35 @@ static bool have_script_upload_cap(LLUUID& object_id) return object && (! object->getRegion()->getCapability("UpdateScriptTask").empty()); } + +class ExperienceResponder : public LLHTTPClient::ResponderWithResult +{ +public: + ExperienceResponder(const LLHandle& parent) : mParent(parent) + { + } + + LLHandle mParent; + + /*virtual*/ void httpSuccess() + { + LLLiveLSLEditor* parent = mParent.get(); + if (!parent) + return; + + parent->setExperienceIds(getContent()["experience_ids"]); + } + + /*virtual*/ char const* getName() const { return "ExperienceResponder"; } +}; + /// --------------------------------------------------------------------------- /// LLLiveLSLFile /// --------------------------------------------------------------------------- class LLLiveLSLFile : public LLLiveFile { public: - typedef boost::function change_callback_t; + typedef std::function change_callback_t; LLLiveLSLFile(std::string file_path, change_callback_t change_cb); ~LLLiveLSLFile(); @@ -153,16 +178,16 @@ class LLLiveLSLFile : public LLLiveFile void ignoreNextUpdate() { mIgnoreNextUpdate = true; } protected: - /*virtual*/ bool loadFile(); + /*virtual*/ bool loadFile() override; change_callback_t mOnChangeCallback; bool mIgnoreNextUpdate; }; LLLiveLSLFile::LLLiveLSLFile(std::string file_path, change_callback_t change_cb) - : mOnChangeCallback(change_cb) +: LLLiveFile(file_path, 1.0) +, mOnChangeCallback(change_cb) , mIgnoreNextUpdate(false) - , LLLiveFile(file_path, 1.0) { llassert(mOnChangeCallback); } @@ -183,6 +208,188 @@ bool LLLiveLSLFile::loadFile() return mOnChangeCallback(filename()); } +// +#if 0 +/// --------------------------------------------------------------------------- +/// LLFloaterScriptSearch +/// --------------------------------------------------------------------------- +class LLFloaterScriptSearch : public LLFloater +{ +public: + LLFloaterScriptSearch(LLScriptEdCore* editor_core); + ~LLFloaterScriptSearch(); + + /*virtual*/ BOOL postBuild(); + static void show(LLScriptEdCore* editor_core); + static void onBtnSearch(void* userdata); + void handleBtnSearch(); + + static void onBtnReplace(void* userdata); + void handleBtnReplace(); + + static void onBtnReplaceAll(void* userdata); + void handleBtnReplaceAll(); + + LLScriptEdCore* getEditorCore() { return mEditorCore; } + static LLFloaterScriptSearch* getInstance() { return sInstance; } + + virtual bool hasAccelerators() const; + virtual BOOL handleKeyHere(KEY key, MASK mask); + +private: + + LLScriptEdCore* mEditorCore; + static LLFloaterScriptSearch* sInstance; + +protected: + LLLineEditor* mSearchBox; + LLLineEditor* mReplaceBox; + void onSearchBoxCommit(); +}; + +LLFloaterScriptSearch* LLFloaterScriptSearch::sInstance = NULL; + +LLFloaterScriptSearch::LLFloaterScriptSearch(LLScriptEdCore* editor_core) +: LLFloater(LLSD()), + mSearchBox(NULL), + mReplaceBox(NULL), + mEditorCore(editor_core) +{ + buildFromFile("floater_script_search.xml"); + + sInstance = this; + + // find floater in which script panel is embedded + LLView* viewp = (LLView*)editor_core; + while(viewp) + { + LLFloater* floaterp = dynamic_cast(viewp); + if (floaterp) + { + floaterp->addDependentFloater(this); + break; + } + viewp = viewp->getParent(); + } +} + +BOOL LLFloaterScriptSearch::postBuild() +{ + mReplaceBox = getChild("replace_text"); + mSearchBox = getChild("search_text"); + mSearchBox->setCommitCallback(boost::bind(&LLFloaterScriptSearch::onSearchBoxCommit, this)); + mSearchBox->setCommitOnFocusLost(FALSE); + childSetAction("search_btn", onBtnSearch,this); + childSetAction("replace_btn", onBtnReplace,this); + childSetAction("replace_all_btn", onBtnReplaceAll,this); + + setDefaultBtn("search_btn"); + + return TRUE; +} + +//static +void LLFloaterScriptSearch::show(LLScriptEdCore* editor_core) +{ + LLSD::String search_text; + LLSD::String replace_text; + if (sInstance && sInstance->mEditorCore && sInstance->mEditorCore != editor_core) + { + search_text=sInstance->mSearchBox->getValue().asString(); + replace_text=sInstance->mReplaceBox->getValue().asString(); + sInstance->closeFloater(); + delete sInstance; + } + + if (!sInstance) + { + // sInstance will be assigned in the constructor. + new LLFloaterScriptSearch(editor_core); + sInstance->mSearchBox->setValue(search_text); + sInstance->mReplaceBox->setValue(replace_text); + } + + sInstance->openFloater(); +} + +LLFloaterScriptSearch::~LLFloaterScriptSearch() +{ + sInstance = NULL; +} + +// static +void LLFloaterScriptSearch::onBtnSearch(void *userdata) +{ + LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata; + self->handleBtnSearch(); +} + +void LLFloaterScriptSearch::handleBtnSearch() +{ + LLCheckBoxCtrl* caseChk = getChild("case_text"); + mEditorCore->mEditor->selectNext(mSearchBox->getValue().asString(), caseChk->get()); +} + +// static +void LLFloaterScriptSearch::onBtnReplace(void *userdata) +{ + LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata; + self->handleBtnReplace(); +} + +void LLFloaterScriptSearch::handleBtnReplace() +{ + LLCheckBoxCtrl* caseChk = getChild("case_text"); + mEditorCore->mEditor->replaceText(mSearchBox->getValue().asString(), mReplaceBox->getValue().asString(), caseChk->get()); +} + +// static +void LLFloaterScriptSearch::onBtnReplaceAll(void *userdata) +{ + LLFloaterScriptSearch* self = (LLFloaterScriptSearch*)userdata; + self->handleBtnReplaceAll(); +} + +void LLFloaterScriptSearch::handleBtnReplaceAll() +{ + LLCheckBoxCtrl* caseChk = getChild("case_text"); + mEditorCore->mEditor->replaceTextAll(mSearchBox->getValue().asString(), mReplaceBox->getValue().asString(), caseChk->get()); +} + +bool LLFloaterScriptSearch::hasAccelerators() const +{ + if (mEditorCore) + { + return mEditorCore->hasAccelerators(); + } + return FALSE; +} + +BOOL LLFloaterScriptSearch::handleKeyHere(KEY key, MASK mask) +{ + if (mEditorCore) + { + BOOL handled = mEditorCore->handleKeyHere(key, mask); + if (!handled) + { + LLFloater::handleKeyHere(key, mask); + } + } + + return FALSE; +} + +void LLFloaterScriptSearch::onSearchBoxCommit() +{ + if (mEditorCore && mEditorCore->mEditor) + { + LLCheckBoxCtrl* caseChk = getChild("case_text"); + mEditorCore->mEditor->selectNext(mSearchBox->getValue().asString(), caseChk->get()); + } +} +#endif +// + /// --------------------------------------------------------------------------- /// LLScriptEdCore /// --------------------------------------------------------------------------- @@ -209,7 +416,7 @@ void LLScriptEdCore::parseFunctions(const std::string& filename) { LLSDSerialize::fromXMLDocument(function_list, importer); importer.close(); - + for (LLSD::map_const_iterator it = function_list.beginMap(); it != function_list.endMap(); ++it) { LSLFunctionProps fn; @@ -244,9 +451,9 @@ LLScriptEdCore::LLScriptEdCore( mLastHelpToken(NULL), mLiveHelpHistorySize(0), mEnableSave(FALSE), + mHasScriptData(FALSE), mLiveFile(NULL), - mContainer(container), - mHasScriptData(FALSE) + mContainer(container) { setFollowsAll(); setBorderVisible(FALSE); @@ -259,19 +466,79 @@ LLScriptEdCore::~LLScriptEdCore() { deleteBridges(); + // If the search window is up for this editor, close it. +// [SL:KB] - Patch: UI-FloaterSearchReplace +// LLFloaterScriptSearch* script_search = LLFloaterScriptSearch::getInstance(); +// if (script_search && script_search->getEditorCore() == this) +// { +// script_search->closeFloater(); +// delete script_search; +// } +// [/SL:KB] + delete mLiveFile; } +void LLLiveLSLEditor::experienceChanged() +{ + if (mScriptEd->getAssociatedExperience() != mExperiences->getSelectedValue().asUUID()) + { + mScriptEd->enableSave(getIsModifiable()); + //getChildView("Save_btn")->setEnabled(TRUE); + mScriptEd->setAssociatedExperience(mExperiences->getSelectedValue().asUUID()); + updateExperiencePanel(); + } +} + +void LLLiveLSLEditor::onViewProfile(LLUICtrl* ui, void* userdata) +{ + LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; + + LLUUID id; + if (self->mExperienceEnabled->get()) + { + id = self->mScriptEd->getAssociatedExperience(); + if (id.notNull()) + { + LLFloaterExperienceProfile::showInstance(id); + } + } + +} + +void LLLiveLSLEditor::onToggleExperience(LLUICtrl* ui, void* userdata) +{ + LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; + + LLUUID id; + if (self->mExperienceEnabled->get()) + { + if (self->mScriptEd->getAssociatedExperience().isNull()) + { + id = self->mExperienceIds.beginArray()->asUUID(); + } + } + + if (id != self->mScriptEd->getAssociatedExperience()) + { + self->mScriptEd->enableSave(self->getIsModifiable()); + } + self->mScriptEd->setAssociatedExperience(id); + + self->updateExperiencePanel(); +} + BOOL LLScriptEdCore::postBuild() { mErrorList = getChild("lsl errors"); mFunctions = getChild( "Insert..."); - + childSetCommitCallback("Insert...", &LLScriptEdCore::onBtnInsertFunction, this); mEditor = getChild("Script Editor"); mEditor->setHandleEditKeysDirectly(TRUE); + mEditor->setParseHighlights(TRUE); childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this); childSetAction("Save_btn", boost::bind(&LLScriptEdCore::doSave,this,FALSE)); @@ -290,25 +557,25 @@ BOOL LLScriptEdCore::postBuild() { std::string name = i->mName; funcs.push_back(name); - + std::string desc_name = "LSLTipText_"; desc_name += name; std::string desc = LLTrans::getString(desc_name); - + F32 sleep_time = i->mSleepTime; if( sleep_time ) { desc += "\n"; - + LLStringUtil::format_map_t args; args["[SLEEP_TIME]"] = llformat("%.1f", sleep_time ); desc += LLTrans::getString("LSLTipSleepTime", args); } - + // A \n linefeed is not part of xml. Let's add one to keep all // the tips one-per-line in strings.xml LLStringUtil::replaceString( desc, "\\n", "\n" ); - + tooltips.push_back(desc); } } @@ -366,7 +633,7 @@ void LLScriptEdCore::initMenu() menuItem = getChild("Save"); menuItem->setMenuCallback(onBtnSave, this); menuItem->setEnabledCallback(hasChanged); - + menuItem = getChild("Revert All Changes"); menuItem->setMenuCallback(onBtnUndoChanges, this); menuItem->setEnabledCallback(hasChanged); @@ -400,8 +667,12 @@ void LLScriptEdCore::initMenu() menuItem->setEnabledCallback(enableDeselectMenu); menuItem = getChild("Search / Replace..."); +// menuItem->setClickCallback(boost::bind(&LLFloaterScriptSearch::show, this)); menuItem->setMenuCallback(onSearchMenu, this); menuItem->setEnabledCallback(NULL); +// [/SL:KB] + + // Singu TODO: Merge LLFloaterGotoLine? menuItem = getChild("Help..."); menuItem->setMenuCallback(onBtnHelp, this); @@ -438,19 +709,27 @@ bool LLScriptEdCore::loadScriptText(const std::string& filename) // read in the whole file fseek(file, 0L, SEEK_END); - size_t file_length = (size_t) ftell(file); + size_t file_length = ftell(file); fseek(file, 0L, SEEK_SET); - char* buffer = new char[file_length+1]; - size_t nread = fread(buffer, 1, file_length, file); - if (nread < file_length) + if (file_length > 0) { - LL_WARNS() << "Short read" << LL_ENDL; - } - buffer[nread] = '\0'; - fclose(file); + char* buffer = new char[file_length+1]; + size_t nread = fread(buffer, 1, file_length, file); + if (nread < file_length) + { + LL_WARNS() << "Short read" << LL_ENDL; + } + buffer[nread] = '\0'; + fclose(file); - mEditor->setText(LLStringExplicit(buffer)); - delete[] buffer; + mEditor->setText(LLStringExplicit(buffer)); + delete[] buffer; + } + else + { + LL_WARNS() << "Error opening " << filename << LL_ENDL; + return false; + } return true; } @@ -472,9 +751,33 @@ bool LLScriptEdCore::writeToFile(const std::string& filename) std::string utf8text = mEditor->getText(); // Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889 - if (utf8text.size() == 0) + if (utf8text.empty()) + { + utf8text.push_back(' '); + } + else // We cut the fat ones down to size { - utf8text = " "; + std::stringstream strm(utf8text); + utf8text.clear(); + bool quote = false; + for (std::string line; std::getline(strm, line);) + { + //if ((std::count(line.begin(), line.end(), '"') % 2) == 0) quote = !quote; // This would work if escaping wasn't a thing + bool backslash = false; + for (const auto& ch : line) + { + switch (ch) + { + case '\\': backslash = !backslash; break; + case '"': if (!backslash) quote = !quote; // Fall through + default: backslash = false; break; + } + } + if (!quote) LLStringUtil::trimTail(line); + if (!utf8text.empty()) utf8text += '\n'; + utf8text += line; + } + if (utf8text.empty()) utf8text.push_back(' '); } fputs(utf8text.c_str(), fp); @@ -594,7 +897,7 @@ void LLScriptEdCore::setHelpPage(const std::string& help_string) { LLFloater* help_floater = mLiveHelpHandle.get(); if (!help_floater) return; - + LLMediaCtrl* web_browser = help_floater->getChild("lsl_guide_html"); if (!web_browser) return; @@ -699,7 +1002,7 @@ bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLS return false; } -// static +// static bool LLScriptEdCore::onHelpWebDialog(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); @@ -715,7 +1018,7 @@ bool LLScriptEdCore::onHelpWebDialog(const LLSD& notification, const LLSD& respo return false; } -// static +// static void LLScriptEdCore::onBtnHelp(void* userdata) { LLSD payload; @@ -723,7 +1026,7 @@ void LLScriptEdCore::onBtnHelp(void* userdata) LLNotificationsUtil::add("WebLaunchLSLGuide", LLSD(), payload, onHelpWebDialog); } -// static +// static void LLScriptEdCore::onBtnDynamicHelp(void* userdata) { LLScriptEdCore* corep = (LLScriptEdCore*)userdata; @@ -752,8 +1055,8 @@ void LLScriptEdCore::onBtnDynamicHelp(void* userdata) LLComboBox* help_combo = live_help_floater->getChild("history_combo"); LLKeywordToken *token; LLKeywords::keyword_iterator_t token_it; - for (token_it = corep->mEditor->keywordsBegin(); - token_it != corep->mEditor->keywordsEnd(); + for (token_it = corep->mEditor->keywordsBegin(); + token_it != corep->mEditor->keywordsEnd(); ++token_it) { token = token_it->second; @@ -768,7 +1071,7 @@ void LLScriptEdCore::onBtnDynamicHelp(void* userdata) corep->updateDynamicHelp(TRUE); } -//static +//static void LLScriptEdCore::onClickBack(void* userdata) { LLScriptEdCore* corep = (LLScriptEdCore*)userdata; @@ -783,7 +1086,7 @@ void LLScriptEdCore::onClickBack(void* userdata) } } -//static +//static void LLScriptEdCore::onClickForward(void* userdata) { LLScriptEdCore* corep = (LLScriptEdCore*)userdata; @@ -809,7 +1112,7 @@ void LLScriptEdCore::onCheckLock(LLUICtrl* ctrl, void* userdata) corep->mLastHelpToken = NULL; } -// static +// static void LLScriptEdCore::onBtnInsertSample(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*) userdata; @@ -820,7 +1123,7 @@ void LLScriptEdCore::onBtnInsertSample(void* userdata) self->mEditor->insertText(self->mSampleText); } -// static +// static void LLScriptEdCore::onHelpComboCommit(LLUICtrl* ctrl, void* userdata) { LLScriptEdCore* corep = (LLScriptEdCore*)userdata; @@ -839,7 +1142,7 @@ void LLScriptEdCore::onHelpComboCommit(LLUICtrl* ctrl, void* userdata) } } -// static +// static void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*) userdata; @@ -943,7 +1246,7 @@ void LLScriptEdCore::onSearchMenu(void* userdata) } } -// static +// static void LLScriptEdCore::onUndoMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -951,7 +1254,7 @@ void LLScriptEdCore::onUndoMenu(void* userdata) self->mEditor->undo(); } -// static +// static void LLScriptEdCore::onRedoMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -959,7 +1262,7 @@ void LLScriptEdCore::onRedoMenu(void* userdata) self->mEditor->redo(); } -// static +// static void LLScriptEdCore::onCutMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -967,7 +1270,7 @@ void LLScriptEdCore::onCutMenu(void* userdata) self->mEditor->cut(); } -// static +// static void LLScriptEdCore::onCopyMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -975,7 +1278,7 @@ void LLScriptEdCore::onCopyMenu(void* userdata) self->mEditor->copy(); } -// static +// static void LLScriptEdCore::onPasteMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -983,7 +1286,7 @@ void LLScriptEdCore::onPasteMenu(void* userdata) self->mEditor->paste(); } -// static +// static void LLScriptEdCore::onSelectAllMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -991,7 +1294,7 @@ void LLScriptEdCore::onSelectAllMenu(void* userdata) self->mEditor->selectAll(); } -// static +// static void LLScriptEdCore::onDeselectMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -999,7 +1302,7 @@ void LLScriptEdCore::onDeselectMenu(void* userdata) self->mEditor->deselect(); } -// static +// static BOOL LLScriptEdCore::enableUndoMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -1007,7 +1310,7 @@ BOOL LLScriptEdCore::enableUndoMenu(void* userdata) return self->mEditor->canUndo(); } -// static +// static BOOL LLScriptEdCore::enableRedoMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -1015,7 +1318,7 @@ BOOL LLScriptEdCore::enableRedoMenu(void* userdata) return self->mEditor->canRedo(); } -// static +// static BOOL LLScriptEdCore::enableCutMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -1023,7 +1326,7 @@ BOOL LLScriptEdCore::enableCutMenu(void* userdata) return self->mEditor->canCut(); } -// static +// static BOOL LLScriptEdCore::enableCopyMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -1031,7 +1334,7 @@ BOOL LLScriptEdCore::enableCopyMenu(void* userdata) return self->mEditor->canCopy(); } -// static +// static BOOL LLScriptEdCore::enablePasteMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -1039,7 +1342,7 @@ BOOL LLScriptEdCore::enablePasteMenu(void* userdata) return self->mEditor->canPaste(); } -// static +// static BOOL LLScriptEdCore::enableSelectAllMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -1047,7 +1350,7 @@ BOOL LLScriptEdCore::enableSelectAllMenu(void* userdata) return self->mEditor->canSelectAll(); } -// static +// static BOOL LLScriptEdCore::enableDeselectMenu(void* userdata) { LLScriptEdCore* self = (LLScriptEdCore*)userdata; @@ -1074,7 +1377,6 @@ void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data) //LL_INFOS() << "LLScriptEdCore::onErrorList() - " << row << ", " //<< column << LL_ENDL; self->mEditor->setCursor(row, column); - self->mEditor->setFocus(TRUE); } } @@ -1160,6 +1462,153 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask) return FALSE; } +LLUUID LLScriptEdCore::getAssociatedExperience() const +{ + return mAssociatedExperience; +} + +void LLLiveLSLEditor::setExperienceIds(const LLSD& experience_ids) +{ + mExperienceIds = experience_ids; + updateExperiencePanel(); +} + + +void LLLiveLSLEditor::updateExperiencePanel() +{ + if (mScriptEd->getAssociatedExperience().isNull()) + { + mExperienceEnabled->set(FALSE); + mExperiences->setVisible(FALSE); + if (mExperienceIds.size() > 0) + { + mExperienceEnabled->setEnabled(TRUE); + mExperienceEnabled->setToolTip(getString("add_experiences")); + } + else + { + mExperienceEnabled->setEnabled(FALSE); + mExperienceEnabled->setToolTip(getString("no_experiences")); + } + getChild("view_profile")->setVisible(FALSE); + } + else + { + mExperienceEnabled->setToolTip(getString("experience_enabled")); + mExperienceEnabled->setEnabled(getIsModifiable()); + mExperiences->setVisible(TRUE); + mExperienceEnabled->set(TRUE); + getChild("view_profile")->setToolTip(getString("show_experience_profile")); + buildExperienceList(); + } +} + +void LLLiveLSLEditor::buildExperienceList() +{ + mExperiences->clearRows(); + bool foundAssociated = false; + const LLUUID& associated = mScriptEd->getAssociatedExperience(); + LLUUID last; + LLScrollListItem* item; + for(LLSD::array_const_iterator it = mExperienceIds.beginArray(); it != mExperienceIds.endArray(); ++it) + { + LLUUID id = it->asUUID(); + EAddPosition position = ADD_BOTTOM; + if (id == associated) + { + foundAssociated = true; + position = ADD_TOP; + } + + const LLSD& experience = LLExperienceCache::instance().get(id); + if (experience.isUndefined()) + { + mExperiences->add(getString("loading"), id, position); + last = id; + } + else + { + std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); + if (experience_name_string.empty()) + { + experience_name_string = LLTrans::getString("ExperienceNameUntitled"); + } + mExperiences->add(experience_name_string, id, position); + } + } + + if (!foundAssociated) + { + const LLSD& experience = LLExperienceCache::instance().get(associated); + if (experience.isDefined()) + { + std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); + if (experience_name_string.empty()) + { + experience_name_string = LLTrans::getString("ExperienceNameUntitled"); + } + item=mExperiences->add(experience_name_string, associated, ADD_TOP); + } + else + { + item = mExperiences->add(getString("loading"), associated, ADD_TOP); + last = associated; + } + item->setEnabled(FALSE); + } + + if (last.notNull()) + { + mExperiences->setEnabled(FALSE); + LLExperienceCache::instance().get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); + } + else + { + mExperiences->setEnabled(TRUE); + mExperiences->sortByName(TRUE); + mExperiences->setCurrentByIndex(mExperiences->getCurrentIndex()); + getChild("view_profile")->setVisible(TRUE); + } +} + + +void LLScriptEdCore::setAssociatedExperience(const LLUUID& experience_id) +{ + mAssociatedExperience = experience_id; +} + + + +void LLLiveLSLEditor::requestExperiences() +{ + if (!getIsModifiable()) + { + return; + } + + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + std::string lookup_url = region->getCapability("GetCreatorExperiences"); + if (!lookup_url.empty()) + { + LLHTTPClient::get(lookup_url, new LLCoroResponder( + boost::bind(&LLLiveLSLEditor::receiveExperienceIds, _1, getDerivedHandle()))); + } + } +} + +/*static*/ +void LLLiveLSLEditor::receiveExperienceIds(const LLCoroResponder& responder, LLHandle hparent) +{ + LLLiveLSLEditor* parent = hparent.get(); + if (!parent) + return; + + parent->setExperienceIds(responder.getContent()["experience_ids"]); +} + + /// --------------------------------------------------------------------------- /// LLScriptEdContainer /// --------------------------------------------------------------------------- @@ -1246,7 +1695,7 @@ struct LLScriptSaveInfo //static void* LLPreviewLSL::createScriptEdPanel(void* userdata) { - + LLPreviewLSL *self = (LLPreviewLSL*)userdata; self->mScriptEd = new LLScriptEdCore( @@ -1258,7 +1707,6 @@ void* LLPreviewLSL::createScriptEdPanel(void* userdata) LLPreviewLSL::onSearchReplace, self, 0); - return self->mScriptEd; } @@ -1274,7 +1722,7 @@ LLPreviewLSL::LLPreviewLSL(const std::string& name, const LLRect& rect, const st // virtual BOOL LLPreviewLSL::postBuild() { - const LLInventoryItem* item = getItem(); + const LLInventoryItem* item = getItem(); llassert(item); if (item) @@ -1332,7 +1780,7 @@ void LLPreviewLSL::loadAsset() } if(item) { - BOOL is_copyable = gAgent.allowOperation(PERM_COPY, + BOOL is_copyable = gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE); BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); @@ -1390,7 +1838,7 @@ void LLPreviewLSL::closeIfNeeded() void LLPreviewLSL::onSearchReplace(void* userdata) { LLPreviewLSL* self = (LLPreviewLSL*)userdata; - LLScriptEdCore* sec = self->mScriptEd; + LLScriptEdCore* sec = self->mScriptEd; if (sec && sec->mEditor) { LLFloaterSearchReplace::show(sec->mEditor); @@ -1417,7 +1865,6 @@ void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save) // fails, go ahead and save the text anyway. void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/) { - // LL_INFOS() << "LLPreviewLSL::saveIfNeeded()" << LL_ENDL; if(!mScriptEd->hasChanged()) { return; @@ -1442,13 +1889,14 @@ void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/) mScriptEd->sync(); } + if (!gAgent.getRegion()) return; const LLInventoryItem *inv_item = getItem(); // save it out to asset server - std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent"); if(inv_item) { getWindow()->incBusyCount(); mPendingUploads++; + std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent"); if (!url.empty()) { uploadAssetViaCaps(url, filename, mItemUUID); @@ -1459,12 +1907,6 @@ void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/) mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileQueueProblemUploading")); LLFile::remove(filename); } -#if 0 //Client side compiling disabled. - else if (gAssetStorage) - { - uploadAssetLegacy(filename, mItemUUID, tid); - } -#endif } } @@ -1486,180 +1928,6 @@ void LLPreviewLSL::uploadAssetViaCaps(const std::string& url, LLHTTPClient::post(url, body, new LLUpdateAgentInventoryResponder(body, filename, LLAssetType::AT_LSL_TEXT)); } -#if 0 //Client side compiling disabled. -void LLPreviewLSL::uploadAssetLegacy(const std::string& filename, - const LLUUID& item_id, - const LLTransactionID& tid) -{ - LLLineEditor* descEditor = getChild("desc"); - LLScriptSaveInfo* info = new LLScriptSaveInfo(item_id, - descEditor->getText(), - tid); - gAssetStorage->storeAssetData(filename, tid, - LLAssetType::AT_LSL_TEXT, - &LLPreviewLSL::onSaveComplete, - info); - - LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); - std::string dst_filename = llformat("%s.lso", filepath.c_str()); - std::string err_filename = llformat("%s.out", filepath.c_str()); - - const BOOL compile_to_mono = FALSE; - if(!lscript_compile(filename.c_str(), - dst_filename.c_str(), - err_filename.c_str(), - compile_to_mono, - asset_id.asString().c_str(), - gAgent.isGodlike())) - { - LL_INFOS() << "Compile failed!" << LL_ENDL; - //char command[256]; - //sprintf(command, "type %s\n", err_filename.c_str()); - //system(command); - - // load the error file into the error scrolllist - LLFILE* fp = LLFile::fopen(err_filename, "r"); - if(fp) - { - char buffer[MAX_STRING]; /*Flawfinder: ignore*/ - std::string line; - while(!feof(fp)) - { - if (fgets(buffer, MAX_STRING, fp) == NULL) - { - buffer[0] = '\0'; - } - if(feof(fp)) - { - break; - } - else - { - line.assign(buffer); - LLStringUtil::stripNonprintable(line); - - LLSD row; - row["columns"][0]["value"] = line; - row["columns"][0]["font"] = "OCRA"; - mScriptEd->mErrorList->addElement(row); - } - } - fclose(fp); - mScriptEd->selectFirstError(); - } - } - else - { - LL_INFOS() << "Compile worked!" << LL_ENDL; - if(gAssetStorage) - { - getWindow()->incBusyCount(); - mPendingUploads++; - LLUUID* this_uuid = new LLUUID(mItemUUID); - gAssetStorage->storeAssetData(dst_filename, - tid, - LLAssetType::AT_LSL_BYTECODE, - &LLPreviewLSL::onSaveBytecodeComplete, - (void**)this_uuid); - } - } - - // get rid of any temp files left lying around - LLFile::remove(filename); - LLFile::remove(err_filename); - LLFile::remove(dst_filename); -} - - -// static -void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) -{ - LLScriptSaveInfo* info = reinterpret_cast(user_data); - if(0 == status) - { - if (info) - { - const LLViewerInventoryItem* item; - item = (const LLViewerInventoryItem*)gInventory.getItem(info->mItemUUID); - if(item) - { - LLPointer new_item = new LLViewerInventoryItem(item); - new_item->setAssetUUID(asset_uuid); - new_item->setTransactionID(info->mTransactionID); - new_item->updateServer(FALSE); - gInventory.updateItem(new_item); - gInventory.notifyObservers(); - } - else - { - LL_WARNS() << "Inventory item for script " << info->mItemUUID - << " is no longer in agent inventory." << LL_ENDL; - } - - // Find our window and close it if requested. - LLPreviewLSL* self = static_cast(LLPreview::find(info->mItemUUID)); - if (self) - { - getWindow()->decBusyCount(); - self->mPendingUploads--; - if (self->mPendingUploads <= 0 - && self->mCloseAfterSave) - { - self->close(); - } - } - } - } - else - { - LL_WARNS() << "Problem saving script: " << status << LL_ENDL; - LLSD args; - args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotificationsUtil::add("SaveScriptFailReason", args); - } - delete info; -} - -// static -void LLPreviewLSL::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) -{ - LLUUID* instance_uuid = (LLUUID*)user_data; - LLPreviewLSL* self = NULL; - if(instance_uuid) - { - self = static_cast(LLPreview::find(*instance_uuid)); - } - if (0 == status) - { - if (self) - { - LLSD row; - row["columns"][0]["value"] = "Compile successful!"; - row["columns"][0]["font"] = "SANSSERIF_SMALL"; - self->mScriptEd->mErrorList->addElement(row); - - // Find our window and close it if requested. - self->getWindow()->decBusyCount(); - self->mPendingUploads--; - if (self->mPendingUploads <= 0 - && self->mCloseAfterSave) - { - self->close(); - } - } - } - else - { - LL_WARNS() << "Problem saving LSL Bytecode (Preview)" << LL_ENDL; - LLSD args; - args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotificationsUtil::add("SaveBytecodeFailReason", args); - } - delete instance_uuid; -} -#endif - // static void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status) @@ -1689,7 +1957,7 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)) { - is_modifiable = TRUE; + is_modifiable = TRUE; } preview->mScriptEd->setEnableEditing(is_modifiable); preview->mAssetStatus = PREVIEW_ASSET_LOADED; @@ -1725,10 +1993,9 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset /// --------------------------------------------------------------------------- -//static +//static void* LLLiveLSLEditor::createScriptEdPanel(void* userdata) { - LLLiveLSLEditor *self = (LLLiveLSLEditor*)userdata; self->mScriptEd = new LLScriptEdCore( @@ -1740,19 +2007,18 @@ void* LLLiveLSLEditor::createScriptEdPanel(void* userdata) &LLLiveLSLEditor::onSearchReplace, self, 0); - return self->mScriptEd; } LLLiveLSLEditor::LLLiveLSLEditor(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& object_id, const LLUUID& item_id) : LLScriptEdContainer(name, rect, title, item_id, object_id), + mIsNew(false), mAskedForRunningInfo(FALSE), mHaveRunningInfo(FALSE), mCloseAfterSave(FALSE), mPendingUploads(0), - mIsModifiable(FALSE), - mIsNew(false) + mIsModifiable(FALSE) { mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); LLUICtrlFactory::getInstance()->buildFloater(this,"floater_live_lsleditor.xml", &getFactoryMap()); @@ -1773,6 +2039,16 @@ BOOL LLLiveLSLEditor::postBuild() mScriptEd->mEditor->makePristine(); mScriptEd->mEditor->setFocus(TRUE); + + mExperiences = getChild("Experiences..."); + mExperiences->setCommitCallback(boost::bind(&LLLiveLSLEditor::experienceChanged, this)); + + mExperienceEnabled = getChild("enable_xp"); + + childSetCommitCallback("enable_xp", onToggleExperience, this); + childSetCommitCallback("view_profile", onViewProfile, this); + + return LLPreview::postBuild(); } @@ -1816,59 +2092,65 @@ void LLLiveLSLEditor::loadAsset() if(object) { LLViewerInventoryItem* item = dynamic_cast(object->getInventoryObject(mItemUUID)); - if(item - && (gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE) - || gAgent.isGodlike())) - { - mItem = new LLViewerInventoryItem(item); - //LL_INFOS() << "asset id " << mItem->getAssetUUID() << LL_ENDL; - } - if(!gAgent.isGodlike() - && (item - && (!gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE) - || !gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)))) + if (item) { - mItem = new LLViewerInventoryItem(item); - mScriptEd->setScriptText(getString("not_allowed"), FALSE); - mScriptEd->mEditor->makePristine(); - mScriptEd->enableSave(FALSE); - mAssetStatus = PREVIEW_ASSET_LOADED; - } - else if(item && mItem.notNull()) - { - // request the text from the object - LLUUID* user_data = new LLUUID(mItemUUID); // ^ mObjectUUID - gAssetStorage->getInvItemAsset(object->getRegion()->getHost(), - gAgent.getID(), - gAgent.getSessionID(), - item->getPermissions().getOwner(), - object->getID(), - item->getUUID(), - item->getAssetUUID(), - item->getType(), - &LLLiveLSLEditor::onLoadComplete, - (void*)user_data, - TRUE); - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_GetScriptRunning); - msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, mObjectUUID); - msg->addUUIDFast(_PREHASH_ItemID, mItemUUID); - msg->sendReliable(object->getRegion()->getHost()); - mAskedForRunningInfo = TRUE; - mAssetStatus = PREVIEW_ASSET_LOADING; + LLViewerRegion* region = object->getRegion(); + std::string url = std::string(); + if(region) + { + url = region->getCapability("GetMetadata"); + } + LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), url, + boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle(), _1)); + + bool isGodlike = gAgent.isGodlike(); + bool copyManipulate = gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE); + mIsModifiable = gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); + + if (!isGodlike && (!copyManipulate || !mIsModifiable)) + { + mItem = new LLViewerInventoryItem(item); + mScriptEd->setScriptText(getString("not_allowed"), FALSE); + mScriptEd->mEditor->makePristine(); + mScriptEd->enableSave(FALSE); + mAssetStatus = PREVIEW_ASSET_LOADED; + } + else if (copyManipulate || isGodlike) + { + mItem = new LLViewerInventoryItem(item); + // request the text from the object + LLUUID* user_data = new LLUUID(mItemUUID); // ^ mObjectUUID + gAssetStorage->getInvItemAsset(object->getRegion()->getHost(), + gAgent.getID(), + gAgent.getSessionID(), + item->getPermissions().getOwner(), + object->getID(), + item->getUUID(), + item->getAssetUUID(), + item->getType(), + &LLLiveLSLEditor::onLoadComplete, + (void*)user_data, + TRUE); + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_GetScriptRunning); + msg->nextBlockFast(_PREHASH_Script); + msg->addUUIDFast(_PREHASH_ObjectID, mObjectUUID); + msg->addUUIDFast(_PREHASH_ItemID, mItemUUID); + msg->sendReliable(object->getRegion()->getHost()); + mAskedForRunningInfo = TRUE; + mAssetStatus = PREVIEW_ASSET_LOADING; + } } - else + + if (mItem.isNull()) { mScriptEd->setScriptText(LLStringUtil::null, FALSE); mScriptEd->mEditor->makePristine(); mAssetStatus = PREVIEW_ASSET_LOADED; + mIsModifiable = FALSE; } - mIsModifiable = item && gAgent.allowOperation(PERM_MODIFY, - item->getPermissions(), - GP_OBJECT_MANIPULATE); refreshFromItem(item); // This is commented out, because we don't completely // handle script exports yet. @@ -1906,6 +2188,8 @@ void LLLiveLSLEditor::loadAsset() time_corrected()); mAssetStatus = PREVIEW_ASSET_LOADED; } + + requestExperiences(); } // static @@ -2032,7 +2316,7 @@ void LLLiveLSLEditor::onReset(void *userdata) } else { - LLNotificationsUtil::add("CouldNotStartStopScript"); + LLNotificationsUtil::add("CouldNotStartStopScript"); } } @@ -2085,6 +2369,7 @@ void LLLiveLSLEditor::draw() // Really ought to put in main window. setTitle(LLTrans::getString("ObjectOutOfRange")); runningCheckbox->setEnabled(FALSE); + mMonoCheckbox->setEnabled(FALSE); // object may have fallen out of range. mHaveRunningInfo = FALSE; } @@ -2097,7 +2382,7 @@ void LLLiveLSLEditor::onSearchReplace(void* userdata) { LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; - LLScriptEdCore* sec = self->mScriptEd; + LLScriptEdCore* sec = self->mScriptEd; if (sec && sec->mEditor) { LLFloaterSearchReplace::show(sec->mEditor); @@ -2188,7 +2473,7 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) { mScriptEd->sync(); } - + // save it out to asset server std::string url = object->getRegion()->getCapability("UpdateScriptTask"); getWindow()->incBusyCount(); @@ -2196,26 +2481,21 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) BOOL is_running = getChild( "running")->get(); if (!url.empty()) { - uploadAssetViaCaps(url, filename, mObjectUUID, mItemUUID, is_running); + uploadAssetViaCaps(url, filename, mObjectUUID, mItemUUID, is_running, mScriptEd->getAssociatedExperience()); } else { mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileQueueProblemUploading")); LLFile::remove(filename); } -#if 0 //Client side compiling disabled. - else if (gAssetStorage) - { - uploadAssetLegacy(filename, object, tid, is_running); - } -#endif } void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url, const std::string& filename, const LLUUID& task_id, const LLUUID& item_id, - BOOL is_running) + BOOL is_running, + const LLUUID& experience_public_id) { LL_INFOS() << "Update Task Inventory via capability " << url << LL_ENDL; LLSD body; @@ -2223,188 +2503,11 @@ void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url, body["item_id"] = item_id; body["is_script_running"] = is_running; body["target"] = monoChecked() ? "mono" : "lsl2"; + body["experience"] = experience_public_id; LLHTTPClient::post(url, body, new LLUpdateTaskInventoryResponder(body, filename, LLAssetType::AT_LSL_TEXT)); } -#if 0 //Client side compiling disabled. -void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, - LLViewerObject* object, - const LLTransactionID& tid, - BOOL is_running) -{ - LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectUUID, - mItem, - is_running); - gAssetStorage->storeAssetData(filename, tid, - LLAssetType::AT_LSL_TEXT, - &onSaveTextComplete, - (void*)data, - FALSE); - - LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); - std::string dst_filename = llformat("%s.lso", filepath.c_str()); - std::string err_filename = llformat("%s.out", filepath.c_str()); - - LLFILE *fp; - const BOOL compile_to_mono = FALSE; - if(!lscript_compile(filename.c_str(), - dst_filename.c_str(), - err_filename.c_str(), - compile_to_mono, - asset_id.asString().c_str(), - gAgent.isGodlike())) - { - // load the error file into the error scrolllist - LL_INFOS() << "Compile failed!" << LL_ENDL; - if(NULL != (fp = LLFile::fopen(err_filename, "r"))) - { - char buffer[MAX_STRING]; /*Flawfinder: ignore*/ - std::string line; - while(!feof(fp)) - { - - if (fgets(buffer, MAX_STRING, fp) == NULL) - { - buffer[0] = '\0'; - } - if(feof(fp)) - { - break; - } - else - { - line.assign(buffer); - LLStringUtil::stripNonprintable(line); - - LLSD row; - row["columns"][0]["value"] = line; - row["columns"][0]["font"] = "OCRA"; - mScriptEd->mErrorList->addElement(row); - } - } - fclose(fp); - mScriptEd->selectFirstError(); - // don't set the asset id, because we want to save the - // script, even though the compile failed. - //mItem->setAssetUUID(LLUUID::null); - object->saveScript(mItem, FALSE, false); - dialog_refresh_all(); - } - } - else - { - LL_INFOS() << "Compile worked!" << LL_ENDL; - mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessfulSaving")); - if(gAssetStorage) - { - LL_INFOS() << "LLLiveLSLEditor::saveAsset " - << mItem->getAssetUUID() << LL_ENDL; - getWindow()->incBusyCount(); - mPendingUploads++; - LLLiveLSLSaveData* data = NULL; - data = new LLLiveLSLSaveData(mObjectUUID, - mItem, - is_running); - gAssetStorage->storeAssetData(dst_filename, - tid, - LLAssetType::AT_LSL_BYTECODE, - &LLLiveLSLEditor::onSaveBytecodeComplete, - (void*)data); - dialog_refresh_all(); - } - } - - // get rid of any temp files left lying around - LLFile::remove(filename); - LLFile::remove(err_filename); - LLFile::remove(dst_filename); - - // If we successfully saved it, then we should be able to check/uncheck the running box! - LLCheckBoxCtrl* runningCheckbox = getChild( "running"); - runningCheckbox->setLabel(getString("script_running")); - runningCheckbox->setEnabled(TRUE); -} - -void LLLiveLSLEditor::onSaveTextComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) -{ - LLLiveLSLSaveData* data = (LLLiveLSLSaveData*)user_data; - - if (status) - { - LL_WARNS() << "Unable to save text for a script." << LL_ENDL; - LLSD args; - args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotificationsUtil::add("CompileQueueSaveText", args); - } - else - { - LLLiveLSLEditor* self = static_cast(LLPreview::find(data->mItem->getUUID())); // ^ data->mSaveObjectID - if (self) - { - self->getWindow()->decBusyCount(); - self->mPendingUploads--; - if (self->mPendingUploads <= 0 - && self->mCloseAfterSave) - { - self->close(); - } - } - } - delete data; - data = NULL; -} - - -void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) -{ - LLLiveLSLSaveData* data = (LLLiveLSLSaveData*)user_data; - if(!data) - return; - if(0 ==status) - { - LL_INFOS() << "LSL Bytecode saved" << LL_ENDL; - LLLiveLSLEditor* self = static_cast(LLPreview::find(data->mItem->getUUID())); // ^ data->mSaveObjectID - if(self) - { - // Tell the user that the compile worked. - self->mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); - // close the window if this completes both uploads - self->getWindow()->decBusyCount(); - self->mPendingUploads--; - if (self->mPendingUploads <= 0 - && self->mCloseAfterSave) - { - self->close(); - } - } - LLViewerObject* object = gObjectList.findObject(data->mSaveObjectID); - if(object) - { - object->saveScript(data->mItem, data->mActive, false); - dialog_refresh_all(); - //LLToolDragAndDrop::dropScript(object, ids->first, - // LLAssetType::AT_LSL_TEXT, FALSE); - } - } - else - { - LL_INFOS() << "Problem saving LSL Bytecode (Live Editor)" << LL_ENDL; - LL_WARNS() << "Unable to save a compiled script." << LL_ENDL; - - LLSD args; - args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotificationsUtil::add("CompileQueueSaveBytecode", args); - } - - std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_uuid.asString()); - std::string dst_filename = llformat("%s.lso", filepath.c_str()); - LLFile::remove(dst_filename); - delete data; -} -#endif - BOOL LLLiveLSLEditor::canClose() { return (mScriptEd->canClose()); @@ -2475,4 +2578,19 @@ BOOL LLLiveLSLEditor::monoChecked() const return mMonoCheckbox->getValue()? TRUE : FALSE; } return FALSE; -} \ No newline at end of file +} + +void LLLiveLSLEditor::setAssociatedExperience(LLHandle editor, const LLSD& experience) +{ + LLLiveLSLEditor* scriptEd = editor.get(); + if (scriptEd) + { + LLUUID id; + if (experience.has(LLExperienceCache::EXPERIENCE_ID)) + { + id = experience[LLExperienceCache::EXPERIENCE_ID].asUUID(); + } + scriptEd->mScriptEd->setAssociatedExperience(id); + scriptEd->updateExperiencePanel(); + } +} diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index dd1c8c7806..35f6571f4f 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -81,8 +81,8 @@ class LLScriptEdCore : public LLPanel void initMenu(); - virtual void draw(); - /*virtual*/ BOOL postBuild(); + void draw() override; + BOOL postBuild() override; BOOL canClose(); void setEnableEditing(bool enable); @@ -104,7 +104,6 @@ class LLScriptEdCore : public LLPanel static void onClickForward(void* userdata); static void onBtnInsertSample(void*); static void onBtnInsertFunction(LLUICtrl*, void*); - // Singu TODO: modernize the menu callbacks and get rid of/update this giant block of static functions static BOOL hasChanged(void* userdata); static void onBtnSave(void*); @@ -127,7 +126,9 @@ class LLScriptEdCore : public LLPanel static BOOL enableSelectAllMenu(void* userdata); static BOOL enableDeselectMenu(void* userdata); - virtual bool hasAccelerators() const { return true; } + bool hasAccelerators() const override { return true; } + LLUUID getAssociatedExperience() const; + void setAssociatedExperience(const LLUUID& experience_id); private: static bool onHelpWebDialog(const LLSD& notification, const LLSD& response); @@ -139,7 +140,7 @@ class LLScriptEdCore : public LLPanel void selectFirstError(); - virtual BOOL handleKeyHere(KEY key, MASK mask); + BOOL handleKeyHere(KEY key, MASK mask) override; void enableSave(BOOL b) {mEnableSave = b;} @@ -169,6 +170,7 @@ class LLScriptEdCore : public LLPanel BOOL mEnableSave; BOOL mHasScriptData; LLLiveLSLFile* mLiveFile; + LLUUID mAssociatedExperience; LLScriptEdContainer* mContainer; // parent view @@ -194,41 +196,37 @@ class LLScriptEdContainer : public LLPreview bool onExternalChange(const std::string& filename); virtual void saveIfNeeded(bool sync = true) = 0; - LLTextEditor* getEditor() { return mScriptEd->mEditor; } - /*virtual*/ const char *getTitleName() const { return "Script"; } + LLTextEditor* getEditor() const { return mScriptEd->mEditor; } + /*virtual*/ const char *getTitleName() const override { return "Script"; } // - /*virtual*/ BOOL canSaveAs() const; - /*virtual*/ void saveAs(); + /*virtual*/ BOOL canSaveAs() const override; + /*virtual*/ void saveAs() override; void saveAs_continued(AIFilePicker* filepicker); // LLScriptEdCore* mScriptEd; }; -// Used to view and edit a LSL from your inventory. -class LLPreviewLSL : public LLScriptEdContainer +// Used to view and edit an LSL script from your inventory. +class LLPreviewLSL final : public LLScriptEdContainer { public: LLPreviewLSL(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid ); virtual void callbackLSLCompileSucceeded(); virtual void callbackLSLCompileFailed(const LLSD& compile_errors); - /*virtual*/ BOOL postBuild(); + /*virtual*/ BOOL postBuild() override; + protected: - virtual BOOL canClose(); + BOOL canClose() override; void closeIfNeeded(); - virtual void loadAsset(); - /*virtual*/ void saveIfNeeded(bool sync = true); + void loadAsset() override; + /*virtual*/ void saveIfNeeded(bool sync = true) override; void uploadAssetViaCaps(const std::string& url, const std::string& filename, const LLUUID& item_id); -#if 0 //Client side compiling disabled. - void uploadAssetLegacy(const std::string& filename, - const LLUUID& item_id, - const LLTransactionID& tid); -#endif static void onSearchReplace(void* userdata); static void onLoad(void* userdata); @@ -237,10 +235,6 @@ class LLPreviewLSL : public LLScriptEdContainer static void onLoadComplete(LLVFS *vfs, const LLUUID& uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); -#if 0 //Client side compiling disabled. - static void onSaveComplete(const LLUUID& uuid, void* user_data, S32 status, LLExtStat ext_status); - static void onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status); -#endif protected: static void* createScriptEdPanel(void* userdata); @@ -254,8 +248,8 @@ class LLPreviewLSL : public LLScriptEdContainer }; -// Used to view and edit an LSL that is attached to an object. -class LLLiveLSLEditor : public LLScriptEdContainer +// Used to view and edit an LSL script that is attached to an object. +class LLLiveLSLEditor final : public LLScriptEdContainer { friend class LLLiveLSLFile; public: @@ -269,29 +263,35 @@ class LLLiveLSLEditor : public LLScriptEdContainer bool is_script_running); virtual void callbackLSLCompileFailed(const LLSD& compile_errors); - /*virtual*/ BOOL postBuild(); + /*virtual*/ BOOL postBuild() override; void setIsNew() { mIsNew = TRUE; } + static void setAssociatedExperience(LLHandle editor, const LLSD& experience); + static void onToggleExperience(LLUICtrl* ui, void* userdata); + static void onViewProfile(LLUICtrl* ui, void* userdata); + + void setExperienceIds(const LLSD& experience_ids); + void buildExperienceList(); + void updateExperiencePanel(); + void requestExperiences(); + void experienceChanged(); + void addAssociatedExperience(const LLSD& experience); + private: - virtual BOOL canClose(); + BOOL canClose() override; void closeIfNeeded(); - virtual void draw(); + void draw() override; - virtual void loadAsset(); + void loadAsset() override; void loadAsset(BOOL is_new); - /*virtual*/ void saveIfNeeded(bool sync = true); + /*virtual*/ void saveIfNeeded(bool sync = true) override; void uploadAssetViaCaps(const std::string& url, - const std::string& filename, + const std::string& filename, const LLUUID& task_id, const LLUUID& item_id, - BOOL is_running); -#if 0 //Client side compiling disabled. - void uploadAssetLegacy(const std::string& filename, - LLViewerObject* object, - const LLTransactionID& tid, - BOOL is_running); -#endif + BOOL is_running, + const LLUUID& experience_public_id); BOOL monoChecked() const; @@ -302,10 +302,6 @@ class LLLiveLSLEditor : public LLScriptEdContainer static void onLoadComplete(LLVFS *vfs, const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); -#if 0 //Client side compiling disabled. - static void onSaveTextComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status); - static void onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status); -#endif static void onRunningCheckboxClicked(LLUICtrl*, void* userdata); static void onReset(void* userdata); @@ -317,6 +313,8 @@ class LLLiveLSLEditor : public LLScriptEdContainer static void onMonoCheckboxClicked(LLUICtrl*, void* userdata); + static void receiveExperienceIds(const struct LLCoroResponder& responder, LLHandle parent); + private: bool mIsNew; //LLUUID mTransmitID; @@ -330,9 +328,16 @@ class LLLiveLSLEditor : public LLScriptEdContainer S32 mPendingUploads; BOOL getIsModifiable() const { return mIsModifiable; } // Evaluated on load assert - + LLCheckBoxCtrl* mMonoCheckbox; BOOL mIsModifiable; + + + LLComboBox* mExperiences; + LLCheckBoxCtrl* mExperienceEnabled; + LLSD mExperienceIds; + + LLHandle mExperienceProfile; }; #endif // LL_LLPREVIEWSCRIPT_H diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index c5e6a987c8..ac2da07816 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -36,6 +36,7 @@ #include "llagent.h" #include "llavataractions.h" +#include "llavatarnamecache.h" #include "llbutton.h" #include "llcombobox.h" #include "statemachine/aifilepicker.h" @@ -229,25 +230,17 @@ void LLPreviewTexture::init() childSetText("desc", item->getDescription()); getChild("desc")->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe); childSetText("uuid", getItemID().asString()); - childSetText("uploader", getItemCreatorName()); - childSetText("uploadtime", getItemCreationDate()); childSetText("alphanote", LLTrans::getString("LoadingData")); } } - + childSetText("uploader", getItemCreatorName()); + childSetText("uploadtime", getItemCreationDate()); + childSetCommitCallback("combo_aspect_ratio", onAspectRatioCommit, this); LLComboBox* combo = getChild("combo_aspect_ratio"); combo->setCurrentByIndex(0); } -void LLPreviewTexture::callbackLoadAvatarName(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data) -{ - if (!sInstance) return; - std::ostringstream fullname; - fullname << first << " " << last; - sInstance->childSetText("uploader", fullname.str()); -} - void LLPreviewTexture::draw() { if (mUpdateDimensions) @@ -282,7 +275,8 @@ void LLPreviewTexture::draw() static const LLCachedControl use_rmse_auto_mask("SHUseRMSEAutoMask",false); static const LLCachedControl auto_mask_max_rmse("SHAutoMaskMaxRMSE",.09f); - if (mAlphaMaskResult != mImage->getIsAlphaMask(use_rmse_auto_mask ? auto_mask_max_rmse : -1.f)) + static const LLCachedControl auto_mask_max_mid("SHAutoMaskMaxMid", .25f); + if (mAlphaMaskResult != mImage->getIsAlphaMask(use_rmse_auto_mask ? auto_mask_max_rmse : -1.f, auto_mask_max_mid)) { mAlphaMaskResult = !mAlphaMaskResult; if (!mAlphaMaskResult) @@ -485,17 +479,20 @@ std::string LLPreviewTexture::getItemCreationDate() timeToFormattedString(item->getCreationDate(), gSavedSettings.getString("TimestampFormat"), time); return time; } - return getString("Unknown"); + const LLDate date = mImage->getUploadTime(); + return date.notNull() ? date.toHTTPDateString(gSavedSettings.getString("TimestampFormat")) + : getString("Unknown"); } std::string LLPreviewTexture::getItemCreatorName() { const LLViewerInventoryItem* item = getItem(); - if(item) + const LLUUID& id = item ? item->getCreatorUUID() : mImage->getUploader(); + if (id.notNull()) { std::string name; - gCacheName->getFullName(item->getCreatorUUID(), name); - mCreatorKey = item->getCreatorUUID(); + LLAvatarNameCache::getNSName(id, name); + mCreatorKey = id; return name; } return getString("Unknown"); @@ -576,6 +573,14 @@ void LLPreviewTexture::updateDimensions() } + // Update the width/height display every time + if (mImage->getUploader().notNull()) + { + // Singu Note: This is what Alchemy does, we may need it, but it might help if it didn't load in init. + childSetText("uploader", getItemCreatorName()); + childSetText("uploadtime", getItemCreationDate()); + } + if (!mUserResized) { // clamp texture size to fit within actual size of floater after attempting resize @@ -685,7 +690,7 @@ void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata) void LLPreviewTexture::loadAsset() { - mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mImageOldBoostLevel = mImage->getBoostLevel(); mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); mImage->forceToSaveRawImage(0) ; diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h index 073f76bfa5..f1ad314c62 100644 --- a/indra/newview/llpreviewtexture.h +++ b/indra/newview/llpreviewtexture.h @@ -104,7 +104,6 @@ class LLPreviewTexture : public LLPreview static LLPreviewTexture* sInstance; static void onClickProfile(void* userdata); - static void callbackLoadAvatarName(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data); // This is stored off in a member variable, because the save-as // button and drag and drop functionality need to know. diff --git a/indra/newview/llsculptidsize.cpp b/indra/newview/llsculptidsize.cpp new file mode 100644 index 0000000000..9edd78bff0 --- /dev/null +++ b/indra/newview/llsculptidsize.cpp @@ -0,0 +1,154 @@ +/** +* @file llsculptidsize.cpp +* @brief LLSculptIDSize class implementation +* +* $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$ +*/ + +#include "llviewerprecompiledheaders.h" +#include "llsculptidsize.h" +#include "llvovolume.h" +#include "lldrawable.h" +#include "llvoavatar.h" +//boost +#include "boost/make_shared.hpp" + +//........... + +extern LLControlGroup gSavedSettings; + +//........... + +typedef std::pair pair_iter_iter_BY_SCULPT_ID_t; + +//........... + +void _nothing_to_do_func(int) { /*nothing todo here because of the size it's a shared member*/ } + +void LLSculptIDSize::inc(const LLDrawable *pdrawable, int sz) +{ + llassert(sz >= 0); + + if (!pdrawable) return; + LLVOVolume* vvol = pdrawable->getVOVolume(); + if (!vvol) return; + if (!vvol->isAttachment()) return; + if (!vvol->getAvatar()) return; + if (vvol->getAvatar()->isSelf()) return; + LLVolume *vol = vvol->getVolume(); + if (!vol) return; + + const LLUUID &sculptId = vol->getParams().getSculptID(); + if (sculptId.isNull()) return; + + unsigned int total_size = 0; + + pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get().equal_range(sculptId); + if (itLU.first == itLU.second) + { //register + llassert(mSizeInfo.get().end() == mSizeInfo.get().find(pdrawable)); + mSizeInfo.get().insert(Info(pdrawable, sz, boost::make_shared(sz), sculptId)); + total_size = sz; + } + else + { //update + register + Info &nfo = const_cast(*itLU.first); + //calc new size + total_size = nfo.getSizeSum() + sz; + nfo.mSharedSizeSum->mSizeSum = total_size; + nfo.mSize = sz; + //update size for all LLDrwable in range of sculptId + for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first; it != itLU.second; ++it) + { + mSizeInfo.get().modify_key(mSizeInfo.project(it), boost::bind(&_nothing_to_do_func, _1)); + } + + //trying insert the LLDrawable + mSizeInfo.get().insert(Info(pdrawable, sz, nfo.mSharedSizeSum, sculptId)); + } + + static LLCachedControl render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U); + + if (0 != render_auto_mute_byte_limit && total_size > render_auto_mute_byte_limit) + { + pair_iter_iter_BY_SCULPT_ID_t it_eqr = mSizeInfo.get().equal_range(sculptId); + for (; it_eqr.first != it_eqr.second; ++it_eqr.first) + { + const Info &i = *it_eqr.first; + LLVOVolume *pVVol = i.mDrawable->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD != pVVol->getLOD() + ) + { + addToUnloaded(sculptId); + //immediately + const_cast(i.mDrawable)->unload(); + } + } + } +} + +void LLSculptIDSize::dec(const LLDrawable *pdrawable) +{ + container_BY_DRAWABLE_view::iterator it = mSizeInfo.get().find(pdrawable); + if (mSizeInfo.get().end() == it) return; + + unsigned int size = it->getSizeSum() - it->getSize(); + + if (0 == size) + { + mSizeInfo.get().erase(it->getSculptId()); + } + else + { + Info &nfo = const_cast(*it); + nfo.mSize = 0; + pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get().equal_range(it->getSculptId()); + it->mSharedSizeSum->mSizeSum = size; + for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first; it != itLU.second; ++it) + { + mSizeInfo.get().modify_key(mSizeInfo.project(it), boost::bind(&_nothing_to_do_func, _1)); + } + } +} + +void LLSculptIDSize::rem(const LLUUID &sculptId) +{ + mSizeInfo.get().erase(sculptId); +} + +void LLSculptIDSize::resetSizeSum(const LLUUID &sculptId) +{ + const pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get().equal_range(sculptId); + + if (itLU.first != itLU.second) { + itLU.first->mSharedSizeSum->mSizeSum = 0; + } + + for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first, itE = itLU.second; it != itE; ++it) + { + mSizeInfo.get().modify_key(mSizeInfo.project(it), boost::bind(&_nothing_to_do_func, _1)); + } +} diff --git a/indra/newview/llsculptidsize.h b/indra/newview/llsculptidsize.h new file mode 100644 index 0000000000..678155e1d5 --- /dev/null +++ b/indra/newview/llsculptidsize.h @@ -0,0 +1,134 @@ +/** +* @file llsculptidsize.h +* @brief LLSculptIDSize class definition +* +* $LicenseInfo:firstyear=2009&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_LLSCULPTIDSIZE_H +#define LL_LLSCULPTIDSIZE_H + +#include "lluuid.h" + +//std +#include +//boost +#include "boost/multi_index_container.hpp" +#include "boost/multi_index/ordered_index.hpp" +#include "boost/multi_index/mem_fun.hpp" + +class LLDrawable; + + +class LLSculptIDSize +{ +public: + struct SizeSum + { + SizeSum(int size) + : mSizeSum(size) + {} + unsigned int mSizeSum; + }; + + struct Info + { + typedef boost::shared_ptr PtrSizeSum; + + Info(const LLDrawable *drawable, int size, PtrSizeSum sizeInfo, LLUUID sculptId) + : mDrawable(drawable) + , mSize(size) + , mSharedSizeSum(sizeInfo) + , mSculptId(sculptId) + {} + + const LLDrawable *mDrawable; + unsigned int mSize; + PtrSizeSum mSharedSizeSum; + LLUUID mSculptId; + + inline const LLDrawable* getPtrLLDrawable() const { return mDrawable; } + inline unsigned int getSize() const { return mSize; } + inline unsigned int getSizeSum() const { return mSharedSizeSum->mSizeSum; } + inline LLUUID getSculptId() const { return mSculptId; } + PtrSizeSum getSizeInfo() { return mSharedSizeSum; } + }; + +public: + //tags + struct tag_BY_DRAWABLE {}; + struct tag_BY_SCULPT_ID {}; + struct tag_BY_SIZE {}; + + //container + typedef boost::multi_index_container < + Info, + boost::multi_index::indexed_by < + boost::multi_index::ordered_unique< boost::multi_index::tag + , boost::multi_index::const_mem_fun + > + , boost::multi_index::ordered_non_unique + , boost::multi_index::const_mem_fun + > + , boost::multi_index::ordered_non_unique < boost::multi_index::tag + , boost::multi_index::const_mem_fun < Info, unsigned int, &Info::getSizeSum > + > + > + > container; + + //views + typedef container::index::type container_BY_DRAWABLE_view; + typedef container::index::type container_BY_SCULPT_ID_view; + typedef container::index::type container_BY_SIZE_view; + +private: + LLSculptIDSize() + {} + +public: + static LLSculptIDSize & instance() + { + static LLSculptIDSize inst; + return inst; + } + +public: + void inc(const LLDrawable *pdrawable, int sz); + void dec(const LLDrawable *pdrawable); + void rem(const LLUUID &sculptId); + + inline void addToUnloaded(const LLUUID &sculptId) { mMarkAsUnloaded.insert(sculptId); } + inline void remFromUnloaded(const LLUUID &sculptId) { mMarkAsUnloaded.erase(sculptId); } + inline bool isUnloaded(const LLUUID &sculptId) const { return mMarkAsUnloaded.end() != mMarkAsUnloaded.find(sculptId); } + inline void clearUnloaded() { mMarkAsUnloaded.clear(); } + + void resetSizeSum(const LLUUID &sculptId); + + inline const container & getSizeInfo() const { return mSizeInfo; } + +private: + container mSizeInfo; + typedef uuid_set_t std_LLUUID; + std_LLUUID mMarkAsUnloaded; +}; + +#endif diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 6744184891..2e8a7b1f81 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com /** * @file llselectmgr.cpp * @brief A manager for selected objects and faces. @@ -34,7 +36,6 @@ // library includes #include "llcachename.h" #include "lldbstrings.h" -#include "lleconomy.h" #include "llgl.h" #include "llmediaentry.h" #include "llrender.h" @@ -44,6 +45,7 @@ #include "llundo.h" #include "lluuid.h" #include "llvolume.h" +#include "llcontrolavatar.h" #include "message.h" #include "object_flags.h" #include "llquaternion.h" @@ -51,6 +53,7 @@ // viewer includes #include "llagent.h" #include "llagentcamera.h" +#include "llattachmentsmgr.h" #include "llviewerwindow.h" #include "lldrawable.h" #include "llfloaterinspect.h" @@ -65,8 +68,8 @@ #include "llmenugl.h" #include "llmeshrepository.h" #include "llmutelist.h" -#include "llparcel.h" #include "llnotificationsutil.h" +#include "llparcel.h" // Rez under Land Group #include "llstatusbar.h" #include "llsurface.h" #include "lltool.h" @@ -82,7 +85,7 @@ #include "llviewermenu.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" -#include "llviewerparcelmgr.h" +#include "llviewerparcelmgr.h" // Rez under Land Group #include "llviewerregion.h" #include "llviewerstats.h" #include "llvoavatarself.h" @@ -255,7 +258,7 @@ void LLSelectMgr::updateEffects() //keep reference grid objects active struct f : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) + bool apply(LLViewerObject* object) override { LLDrawable* drawable = object->mDrawable; if (drawable) @@ -279,7 +282,7 @@ void LLSelectMgr::overrideObjectUpdates() //override any position updates from simulator on objects being edited struct f : public LLSelectedNodeFunctor { - virtual bool apply(LLSelectNode* selectNode) + bool apply(LLSelectNode* selectNode) override { LLViewerObject* object = selectNode->getObject(); if (object && object->permMove() && !object->isPermanentEnforced()) @@ -369,7 +372,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S3 //----------------------------------------------------------------------------- // Select the object, parents and children. //----------------------------------------------------------------------------- -LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end) +LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end, BOOL ignore_select_owned) { llassert( obj ); @@ -386,7 +389,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, return NULL; } - if (!canSelectObject(obj)) + if (!canSelectObject(obj,ignore_select_owned)) { //make_ui_sound("UISndInvalidOp"); return NULL; @@ -524,17 +527,15 @@ BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id) { BOOL object_found = FALSE; LLTool *tool = NULL; - if (!gNoRender) - { - tool = LLToolMgr::getInstance()->getCurrentTool(); - // It's possible that the tool is editing an object that is not selected - LLViewerObject* tool_editing_object = tool->getEditingObject(); - if( tool_editing_object && tool_editing_object->mID == id) - { - tool->stopEditing(); - object_found = TRUE; - } + tool = LLToolMgr::getInstance()->getCurrentTool(); + + // It's possible that the tool is editing an object that is not selected + LLViewerObject* tool_editing_object = tool->getEditingObject(); + if( tool_editing_object && tool_editing_object->mID == id) + { + tool->stopEditing(); + object_found = TRUE; } // Iterate through selected objects list and kill the object @@ -650,7 +651,7 @@ bool LLSelectMgr::enableLinkObjects() { struct f : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) + bool apply(LLViewerObject* object) override { LLViewerObject *root_object = (object == NULL) ? NULL : object->getRootEdit(); return object->permModify() && !object->isPermanentEnforced() && @@ -661,6 +662,10 @@ bool LLSelectMgr::enableLinkObjects() new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly); } } + if (!LLSelectMgr::getInstance()->getSelection()->checkAnimatedObjectLinkable()) + { + new_value = false; + } // [RLVa:KB] - Checked: 2011-03-19 (RLVa-1.3.0f) | Modified: RLVa-0.2.0g if ( (new_value) && ((rlv_handler_t::isEnabled()) && (!RlvActions::canStand())) ) { @@ -967,6 +972,10 @@ LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 iter != objects.end(); ++iter) { LLViewerObject* cur_objectp = *iter; + if(!cur_objectp || cur_objectp->isDead()) + { + continue; + } LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE); nodep->selectTE(face, TRUE); mHoverObjects->addNodeAtEnd(nodep); @@ -1211,7 +1220,7 @@ void LLSelectMgr::setGridMode(EGridMode mode) updateSelectionCenter(); } -void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &scale) +void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &scale, bool for_snap_guides) { mGridObjects.cleanupNodes(); @@ -1236,7 +1245,15 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & } else if (mGridMode == GRID_MODE_REF_OBJECT && first_grid_object && first_grid_object->mDrawable.notNull()) { - mGridRotation = first_grid_object->getRenderRotation(); + LLSelectNode *node = mSelectedObjects->findNode(first_grid_object); + if (!for_snap_guides && node) + { + mGridRotation = node->mSavedRotation; + } + else + { + mGridRotation = first_grid_object->getRenderRotation(); + } LLVector4a min_extents(F32_MAX); LLVector4a max_extents(-F32_MAX); @@ -1546,7 +1563,7 @@ void LLSelectMgr::cleanup() struct LLSelectMgrSendFunctor : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -1581,11 +1598,15 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid) struct f : public LLSelectedTEFunctor { - LLViewerInventoryItem* mItem; + LLPointer mItem; LLUUID mImageID; f(LLViewerInventoryItem* item, const LLUUID& id) : mItem(item), mImageID(id) {} - bool apply(LLViewerObject* objectp, S32 te) + bool apply(LLViewerObject* objectp, S32 te) override { + if(objectp && !objectp->permModify()) + { + return false; + } if (mItem) { if (te == -1) // all faces @@ -1616,23 +1637,26 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid) } return true; } - } setfunc(item, imageid); + }; + + f setfunc(item, imageid); getSelection()->applyToTEs(&setfunc); struct g : public LLSelectedObjectFunctor { LLViewerInventoryItem* mItem; g(LLViewerInventoryItem* item) : mItem(item) {} - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { if (!mItem) { object->sendTEUpdate(); - // 1 particle effect per object // if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) { // + // 1 particle effect per object LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); effectp->setSourceObject(gAgentAvatarp); effectp->setTargetObject(object); @@ -1657,7 +1681,7 @@ void LLSelectMgr::selectionSetColor(const LLColor4 &color) { LLColor4 mColor; f(const LLColor4& c) : mColor(c) {} - bool apply(LLViewerObject* object, S32 te) + bool apply(LLViewerObject* object, S32 te) override { if (object->permModify()) { @@ -1681,7 +1705,7 @@ void LLSelectMgr::selectionSetColorOnly(const LLColor4 &color) { LLColor4 mColor; f(const LLColor4& c) : mColor(c) {} - bool apply(LLViewerObject* object, S32 te) + bool apply(LLViewerObject* object, S32 te) override { if (object->permModify()) { @@ -1708,7 +1732,7 @@ void LLSelectMgr::selectionSetAlphaOnly(const F32 alpha) { F32 mAlpha; f(const F32& a) : mAlpha(a) {} - bool apply(LLViewerObject* object, S32 te) + bool apply(LLViewerObject* object, S32 te) override { if (object->permModify()) { @@ -1732,7 +1756,7 @@ void LLSelectMgr::selectionRevertColors() { LLObjectSelectionHandle mSelectedObjects; f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} - bool apply(LLViewerObject* object, S32 te) + bool apply(LLViewerObject* object, S32 te) override { if (object->permModify()) { @@ -1753,13 +1777,47 @@ void LLSelectMgr::selectionRevertColors() getSelection()->applyToObjects(&sendfunc); } +void LLSelectMgr::selectionRevertShinyColors() +{ + struct f : public LLSelectedTEFunctor + { + LLObjectSelectionHandle mSelectedObjects; + f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} + bool apply(LLViewerObject* object, S32 te) override + { + if (object->permModify()) + { + LLSelectNode* nodep = mSelectedObjects->findNode(object); + if (nodep && te < (S32)nodep->mSavedShinyColors.size()) + { + LLColor4 color = nodep->mSavedShinyColors[te]; + // update viewer side color in anticipation of update from simulator + LLMaterialPtr old_mat = object->getTE(te)->getMaterialParams(); + if (!old_mat.isNull()) + { + LLMaterialPtr new_mat = gFloaterTools->getPanelFace()->createDefaultMaterial(old_mat); + new_mat->setSpecularLightColor(color); + object->getTE(te)->setMaterialParams(new_mat); + LLMaterialMgr::getInstance()->put(object->getID(), te, *new_mat); + } + } + } + return true; + } + } setfunc(mSelectedObjects); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); +} + BOOL LLSelectMgr::selectionRevertTextures() { struct f : public LLSelectedTEFunctor { LLObjectSelectionHandle mSelectedObjects; f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} - bool apply(LLViewerObject* object, S32 te) + bool apply(LLViewerObject* object, S32 te) override { if (object->permModify()) { @@ -1799,7 +1857,7 @@ void LLSelectMgr::selectionSetBumpmap(U8 bumpmap) { U8 mBump; f(const U8& b) : mBump(b) {} - bool apply(LLViewerObject* object, S32 te) + bool apply(LLViewerObject* object, S32 te) override { if (object->permModify()) { @@ -1821,7 +1879,7 @@ void LLSelectMgr::selectionSetTexGen(U8 texgen) { U8 mTexgen; f(const U8& t) : mTexgen(t) {} - bool apply(LLViewerObject* object, S32 te) + bool apply(LLViewerObject* object, S32 te) override { if (object->permModify()) { @@ -1844,7 +1902,7 @@ void LLSelectMgr::selectionSetShiny(U8 shiny) { U8 mShiny; f(const U8& t) : mShiny(t) {} - bool apply(LLViewerObject* object, S32 te) + bool apply(LLViewerObject* object, S32 te) override { if (object->permModify()) { @@ -1866,7 +1924,7 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright) { U8 mFullbright; f(const U8& t) : mFullbright(t) {} - bool apply(LLViewerObject* object, S32 te) + bool apply(LLViewerObject* object, S32 te) override { if (object->permModify()) { @@ -1882,7 +1940,8 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright) { U8 mFullbright; g(const U8& t) : mFullbright(t) {} - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -1915,7 +1974,7 @@ void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) U8 mMediaFlags; const LLSD &mMediaData; f(const U8& t, const LLSD& d) : mMediaFlags(t), mMediaData(d) {} - bool apply(LLViewerObject* object, S32 te) + bool apply(LLViewerObject* object, S32 te) override { if (object->permModify()) { @@ -1931,14 +1990,14 @@ void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) llassert(mMediaData.isMap()); const LLTextureEntry *texture_entry = object->getTE(te); if (!mMediaData.isMap() || - (NULL != texture_entry) && !texture_entry->hasMedia() && !mMediaData.has(LLMediaEntry::HOME_URL_KEY)) + ((NULL != texture_entry) && !texture_entry->hasMedia() && !mMediaData.has(LLMediaEntry::HOME_URL_KEY))) { // skip adding/updating media } else { // Add/update media object->setTEMediaFlags(te, mMediaFlags); - LLVOVolume *vo = dynamic_cast(object); + LLVOVolume *vo = object->asVolume(); llassert(NULL != vo); if (NULL != vo) { @@ -1959,12 +2018,12 @@ void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) struct f2 : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) + bool apply(LLViewerObject* object) override { if (object->permModify()) { object->sendTEUpdate(); - LLVOVolume *vo = dynamic_cast(object); + LLVOVolume *vo = object->asVolume(); llassert(NULL != vo); // It's okay to skip this object if hasMedia() is false... // the sendTEUpdate() above would remove all media data if it were @@ -1987,7 +2046,7 @@ void LLSelectMgr::selectionSetGlow(F32 glow) { F32 mGlow; f1(F32 glow) : mGlow(glow) {}; - bool apply(LLViewerObject* object, S32 face) + bool apply(LLViewerObject* object, S32 face) override { if (object->permModify()) { @@ -2001,7 +2060,7 @@ void LLSelectMgr::selectionSetGlow(F32 glow) struct f2 : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -2020,7 +2079,7 @@ void LLSelectMgr::selectionSetMaterialParams(LLSelectedTEMaterialFunctor* materi LLMaterialPtr mMaterial; f1(LLSelectedTEMaterialFunctor* material_func) : _material_func(material_func) {} - bool apply(LLViewerObject* object, S32 face) + bool apply(LLViewerObject* object, S32 face) override { if (object && object->permModify() && _material_func) { @@ -2040,7 +2099,7 @@ void LLSelectMgr::selectionSetMaterialParams(LLSelectedTEMaterialFunctor* materi struct f2 : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -2056,7 +2115,7 @@ void LLSelectMgr::selectionRemoveMaterial() { struct f1 : public LLSelectedTEFunctor { - bool apply(LLViewerObject* object, S32 face) + bool apply(LLViewerObject* object, S32 face) override { if (object->permModify()) { @@ -2071,7 +2130,7 @@ void LLSelectMgr::selectionRemoveMaterial() struct f2 : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -2112,7 +2171,7 @@ BOOL LLSelectMgr::selectionGetGlow(F32 *glow) F32 lglow = 0.f; struct f1 : public LLSelectedTEGetFunctor { - F32 get(LLViewerObject* object, S32 face) + F32 get(LLViewerObject* object, S32 face) override { return object->getTE(face)->getGlow(); } @@ -2130,7 +2189,8 @@ void LLSelectMgr::selectionSetPhysicsType(U8 type) { U8 mType; f(const U8& t) : mType(t) {} - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -2149,7 +2209,8 @@ void LLSelectMgr::selectionSetFriction(F32 friction) { F32 mFriction; f(const F32& friction) : mFriction(friction) {} - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -2168,7 +2229,8 @@ void LLSelectMgr::selectionSetGravity(F32 gravity ) { F32 mGravity; f(const F32& gravity) : mGravity(gravity) {} - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -2187,7 +2249,8 @@ void LLSelectMgr::selectionSetDensity(F32 density ) { F32 mDensity; f(const F32& density ) : mDensity(density) {} - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -2206,7 +2269,8 @@ void LLSelectMgr::selectionSetRestitution(F32 restitution) { F32 mRestitution; f(const F32& restitution ) : mRestitution(restitution) {} - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -2229,7 +2293,8 @@ void LLSelectMgr::selectionSetMaterial(U8 material) { U8 mMaterial; f(const U8& t) : mMaterial(t) {} - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -2251,7 +2316,8 @@ BOOL LLSelectMgr::selectionAllPCode(LLPCode code) { LLPCode mCode; f(const LLPCode& t) : mCode(t) {} - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { if (object->getPCode() != mCode) { @@ -2302,6 +2368,7 @@ void LLSelectMgr::selectionSetIncludeInSearch(bool include_in_search) "ObjectIncludeInSearch", packAgentAndSessionID, packObjectIncludeInSearch, + logNoOp, &include_in_search, SEND_ONLY_ROOTS); } @@ -2321,7 +2388,8 @@ BOOL LLSelectMgr::selectionGetClickAction(U8 *out_action) { U8 mAction; f(const U8& t) : mAction(t) {} - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { if ( mAction != object->getClickAction()) { @@ -2340,7 +2408,8 @@ void LLSelectMgr::selectionSetClickAction(U8 action) { U8 mAction; f(const U8& t) : mAction(t) {} - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { object->setClickAction(mAction); return true; @@ -2351,6 +2420,7 @@ void LLSelectMgr::selectionSetClickAction(U8 action) sendListToRegions("ObjectClickAction", packAgentAndSessionID, packObjectClickAction, + logNoOp, &action, SEND_INDIVIDUALS); } @@ -2386,7 +2456,7 @@ void LLSelectMgr::sendGodlikeRequest(const std::string& request, const std::stri } else { - sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, &data, SEND_ONLY_ROOTS); + sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, logNoOp, &data, SEND_ONLY_ROOTS); } } @@ -2414,6 +2484,23 @@ void LLSelectMgr::packGodlikeHead(void* user_data) } } +// static +void LLSelectMgr::logNoOp(LLSelectNode* node, void *) +{ +} + +// static +void LLSelectMgr::logAttachmentRequest(LLSelectNode* node, void *) +{ + LLAttachmentsMgr::instance().onAttachmentRequested(node->mItemID); +} + +// static +void LLSelectMgr::logDetachRequest(LLSelectNode* node, void *) +{ + LLAttachmentsMgr::instance().onDetachRequested(node->mItemID); +} + // static void LLSelectMgr::packObjectIDAsParam(LLSelectNode* node, void *) { @@ -2431,7 +2518,7 @@ void LLSelectMgr::selectionTexScaleAutofit(F32 repeats_per_meter) { F32 mRepeatsPerMeter; f(const F32& t) : mRepeatsPerMeter(t) {} - bool apply(LLViewerObject* object, S32 te) + bool apply(LLViewerObject* object, S32 te) override { if (object->permModify()) @@ -2681,6 +2768,35 @@ BOOL LLSelectMgr::selectGetRootsModify() return TRUE; } +//----------------------------------------------------------------------------- +// selectGetSameRegion() - return TRUE if all objects are in same region +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetSameRegion() +{ + if (getSelection()->isEmpty()) + { + return TRUE; + } + LLViewerObject* object = getSelection()->getFirstObject(); + if (!object) + { + return FALSE; + } + LLViewerRegion* current_region = object->getRegion(); + + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++) + { + LLSelectNode* node = *iter; + object = node->getObject(); + if (!node->mValid || !object || current_region != object->getRegion()) + { + return FALSE; + } + } + + return TRUE; +} //----------------------------------------------------------------------------- // selectGetNonPermanentEnforced() - return TRUE if all objects are not @@ -3537,22 +3653,20 @@ bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, // attempt to derez into the trash. LLDeRezInfo info(DRD_TRASH, trash_id); LLSelectMgr::getInstance()->sendListToRegions("DeRezObject", - packDeRezHeader, - packObjectLocalID, - (void*) &info, - SEND_ONLY_ROOTS); + packDeRezHeader, + packObjectLocalID, + logNoOp, + (void*) &info, + SEND_ONLY_ROOTS); // VEFFECT: Delete Object - one effect for all deletes - if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) + if (!gSavedSettings.getBOOL("DisablePointAtAndBeam") && (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD)) { - if (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD) - { - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); - effectp->setPositionGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal() ); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - F32 duration = 0.5f; - duration += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount() / 64.f; - effectp->setDuration(duration); - } + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); + effectp->setPositionGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal() ); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + F32 duration = 0.5f; + duration += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount() / 64.f; + effectp->setDuration(duration); } gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); @@ -3577,6 +3691,7 @@ void LLSelectMgr::selectForceDelete() "ObjectDelete", packDeleteHeader, packObjectLocalID, + logNoOp, (void*)TRUE, SEND_ONLY_ROOTS); } @@ -3750,7 +3865,7 @@ void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy) data.offset = offset; data.flags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); - sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS); + sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, logNoOp, &data, SEND_ONLY_ROOTS); if (select_copy) { @@ -3805,7 +3920,7 @@ void LLSelectMgr::repeatDuplicate() data.offset = LLVector3::zero; data.flags = 0x0; - sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS); + sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, logNoOp, &data, SEND_ONLY_ROOTS); // move current selection based on delta from duplication position and update duplication position for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); @@ -3884,7 +3999,7 @@ void LLSelectMgr::selectDuplicateOnRay(const LLVector3 &ray_start_region, data.mFlags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); sendListToRegions("ObjectDuplicateOnRay", - packDuplicateOnRayHead, packObjectLocalID, &data, SEND_ONLY_ROOTS); + packDuplicateOnRayHead, packObjectLocalID, logNoOp, &data, SEND_ONLY_ROOTS); if (select_copy) { @@ -3902,21 +4017,19 @@ void LLSelectMgr::packDuplicateOnRayHead(void *user_data) msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - LLUUID group_id = gAgent.getGroupID(); - // Apply always rez under owned land group setting for objects - // duplicated by shift-dragging or duplicating - if (gSavedSettings.getBOOL("AscentAlwaysRezInGroup")) + // Rez under Land Group + static LLCachedControl AlchemyRezUnderLandGroup(gSavedSettings, "AscentAlwaysRezInGroup"); + LLUUID group_id = gAgent.getGroupID(); + if (AlchemyRezUnderLandGroup) { - LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (gAgent.isInGroup(parcel->getGroupID())) - { - group_id = parcel->getGroupID(); - } - else if (gAgent.isInGroup(parcel->getOwnerID())) - { - group_id = parcel->getOwnerID(); - } + LLParcel* land_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + // Is the agent in the land group + if (gAgent.isInGroup(land_parcel->getGroupID())) + group_id = land_parcel->getGroupID(); + // Is the agent in the land group (the group owns the land) + else if(gAgent.isInGroup(land_parcel->getOwnerID())) + group_id = land_parcel->getOwnerID(); } msg->addUUIDFast(_PREHASH_GroupID, group_id); @@ -3951,6 +4064,7 @@ void LLSelectMgr::sendMultipleUpdate(U32 type) "MultipleObjectUpdate", packAgentAndSessionID, packMultipleUpdate, + logNoOp, &type, send_type); } @@ -4014,7 +4128,7 @@ void LLSelectMgr::sendOwner(const LLUUID& owner_id, data.group_id = group_id; data.override = override; - sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, &data, SEND_ONLY_ROOTS); + sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, logNoOp, &data, SEND_ONLY_ROOTS); } // static @@ -4038,7 +4152,7 @@ void LLSelectMgr::packOwnerHead(void *user_data) void LLSelectMgr::sendGroup(const LLUUID& group_id) { LLUUID local_group_id(group_id); - sendListToRegions("ObjectGroup", packAgentAndSessionAndGroupID, packObjectLocalID, &local_group_id, SEND_ONLY_ROOTS); + sendListToRegions("ObjectGroup", packAgentAndSessionAndGroupID, packObjectLocalID, logNoOp, &local_group_id, SEND_ONLY_ROOTS); } @@ -4062,7 +4176,7 @@ void LLSelectMgr::sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, con LLBuyData buy; buy.mCategoryID = category_id; buy.mSaleInfo = sale_info; - sendListToRegions("ObjectBuy", packAgentGroupAndCatID, packBuyObjectIDs, &buy, SEND_ONLY_ROOTS); + sendListToRegions("ObjectBuy", packAgentGroupAndCatID, packBuyObjectIDs, logNoOp, &buy, SEND_ONLY_ROOTS); } // static @@ -4106,7 +4220,7 @@ void LLSelectMgr::selectionSetObjectPermissions(U8 field, data.mMask = mask; data.mOverride = override; - sendListToRegions("ObjectPermissions", packPermissionsHead, packPermissions, &data, SEND_ONLY_ROOTS); + sendListToRegions("ObjectPermissions", packPermissionsHead, packPermissions, logNoOp, &data, SEND_ONLY_ROOTS); } void LLSelectMgr::packPermissionsHead(void* user_data) @@ -4149,6 +4263,7 @@ void LLSelectMgr::deselectAll() "ObjectDeselect", packAgentAndSessionID, packObjectLocalID, + logNoOp, NULL, SEND_INDIVIDUALS); @@ -4179,6 +4294,7 @@ void LLSelectMgr::deselectAllForStandingUp() "ObjectDeselect", packAgentAndSessionID, packObjectLocalID, + logNoOp, NULL, SEND_INDIVIDUALS); @@ -4290,19 +4406,21 @@ void LLSelectMgr::selectionSetObjectName(const std::string& name) std::string name_copy(name); // we only work correctly if 1 object is selected. - if(mSelectedObjects->getRootObjectCount() /*== 1*/) // Singu Note: It was requested that the user be able to bulk rename + if(mSelectedObjects->getRootObjectCount() >= 1) // { sendListToRegions("ObjectName", packAgentAndSessionID, packObjectName, + logNoOp, (void*)(&name_copy), SEND_ONLY_ROOTS); } - else if(mSelectedObjects->getObjectCount() /*== 1*/) + else if(mSelectedObjects->getObjectCount() >= 1) // { sendListToRegions("ObjectName", packAgentAndSessionID, packObjectName, + logNoOp, (void*)(&name_copy), SEND_INDIVIDUALS); } @@ -4313,19 +4431,21 @@ void LLSelectMgr::selectionSetObjectDescription(const std::string& desc) std::string desc_copy(desc); // we only work correctly if 1 object is selected. - if (mSelectedObjects->getRootObjectCount() /*== 1*/) // Singu Note: It was requested that the user be able to bulk change description + if(mSelectedObjects->getRootObjectCount() >= 1) // { sendListToRegions("ObjectDescription", packAgentAndSessionID, packObjectDescription, + logNoOp, (void*)(&desc_copy), SEND_ONLY_ROOTS); } - else if (mSelectedObjects->getObjectCount() /*== 1*/) + else if(mSelectedObjects->getObjectCount() >= 1) // { sendListToRegions("ObjectDescription", packAgentAndSessionID, packObjectDescription, + logNoOp, (void*)(&desc_copy), SEND_INDIVIDUALS); } @@ -4339,6 +4459,7 @@ void LLSelectMgr::selectionSetObjectCategory(const LLCategory& category) sendListToRegions("ObjectCategory", packAgentAndSessionID, packObjectCategory, + logNoOp, (void*)(&category), SEND_ONLY_ROOTS); } @@ -4348,6 +4469,7 @@ void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info) sendListToRegions("ObjectSaleInfo", packAgentAndSessionID, packObjectSaleInfo, + logNoOp, (void*)(&sale_info), SEND_ONLY_ROOTS); } @@ -4381,10 +4503,14 @@ void LLSelectMgr::sendAttach(U8 attachment_point, bool replace) "ObjectAttach", packAgentIDAndSessionAndAttachment, packObjectIDAndRotation, + logAttachmentRequest, &attachment_point, SEND_ONLY_ROOTS ); if (!build_mode) { + // After "ObjectAttach" server will unsubscribe us from properties updates + // so either deselect objects or resend selection after attach packet reaches server + // In case of build_mode LLPanelObjectInventory::refresh() will deal with selection deselectAll(); } } @@ -4401,6 +4527,7 @@ void LLSelectMgr::sendDetach() "ObjectDetach", packAgentAndSessionID, packObjectLocalID, + logDetachRequest, NULL, SEND_ONLY_ROOTS ); } @@ -4417,6 +4544,7 @@ void LLSelectMgr::sendDropAttachment() "ObjectDrop", packAgentAndSessionID, packObjectLocalID, + logDetachRequest, NULL, SEND_ONLY_ROOTS); } @@ -4436,6 +4564,7 @@ void LLSelectMgr::sendLink() "ObjectLink", packAgentAndSessionID, packObjectLocalID, + logNoOp, NULL, SEND_ONLY_ROOTS); } @@ -4451,7 +4580,7 @@ void LLSelectMgr::sendDelink() { //on delink, any modifyable object should f() {} - virtual bool apply(LLViewerObject* object) + bool apply(LLViewerObject* object) override { if (object->permModify()) { @@ -4473,6 +4602,7 @@ void LLSelectMgr::sendDelink() "ObjectDelink", packAgentAndSessionID, packObjectLocalID, + logNoOp, NULL, SEND_INDIVIDUALS); } @@ -4525,6 +4655,7 @@ void LLSelectMgr::sendSelect() "ObjectSelect", packAgentAndSessionID, packObjectLocalID, + logNoOp, NULL, SEND_INDIVIDUALS); } @@ -4546,7 +4677,7 @@ void LLSelectMgr::selectionDump() { struct f : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) + bool apply(LLViewerObject* object) override { object->dump(); return true; @@ -4559,7 +4690,7 @@ void LLSelectMgr::saveSelectedObjectColors() { struct f : public LLSelectedNodeFunctor { - virtual bool apply(LLSelectNode* node) + bool apply(LLSelectNode* node) override { node->saveColors(); return true; @@ -4568,12 +4699,25 @@ void LLSelectMgr::saveSelectedObjectColors() getSelection()->applyToNodes(&func); } +void LLSelectMgr::saveSelectedShinyColors() +{ + struct f : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) override + { + node->saveShinyColors(); + return true; + } + } func; + getSelection()->applyToNodes(&func); +} + void LLSelectMgr::saveSelectedObjectTextures() { // invalidate current selection so we update saved textures struct f : public LLSelectedNodeFunctor { - virtual bool apply(LLSelectNode* node) + bool apply(LLSelectNode* node) override { node->mValid = FALSE; return true; @@ -4601,7 +4745,8 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type) EActionType mActionType; LLSelectMgr* mManager; f(EActionType a, LLSelectMgr* p) : mActionType(a), mManager(p) {} - virtual bool apply(LLSelectNode* selectNode) + + bool apply(LLSelectNode* selectNode) override { LLViewerObject* object = selectNode->getObject(); if (!object) @@ -4661,13 +4806,21 @@ struct LLSelectMgrApplyFlags : public LLSelectedObjectFunctor LLSelectMgrApplyFlags(U32 flags, BOOL state) : mFlags(flags), mState(state) {} U32 mFlags; BOOL mState; - virtual bool apply(LLViewerObject* object) + + bool apply(LLViewerObject* object) override { - if ( object->permModify() && // preemptive permissions check - object->isRoot()) // don't send for child objects + if ( object->permModify()) { - object->setFlags( mFlags, mState); - } + if (object->isRoot()) // don't send for child objects + { + object->setFlags( mFlags, mState); + } + else if (FLAGS_WORLD & mFlags && ((LLViewerObject*)object->getRoot())->isSelected()) + { + // FLAGS_WORLD are shared by all items in linkset + object->setFlagsWithoutUpdate(FLAGS_WORLD & mFlags, mState); + } + }; return true; } }; @@ -4742,23 +4895,19 @@ void LLSelectMgr::packAgentAndSessionAndGroupID(void* user_data) // static void LLSelectMgr::packDuplicateHeader(void* data) { - LLUUID group_id(gAgent.getGroupID()); - - // Apply always rez under owned land group setting for objects - // duplicated by shift-dragging or duplicating - if (gSavedSettings.getBOOL("AscentAlwaysRezInGroup")) + // Rez under Land Group + static LLCachedControl AlchemyRezUnderLandGroup(gSavedSettings, "AscentAlwaysRezInGroup"); + LLUUID group_id = gAgent.getGroupID(); + if (AlchemyRezUnderLandGroup) { - LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (gAgent.isInGroup(parcel->getGroupID())) - { - group_id = parcel->getGroupID(); - } - else if (gAgent.isInGroup(parcel->getOwnerID())) - { - group_id = parcel->getOwnerID(); - } + LLParcel* land_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + // Is the agent in the land group + if (gAgent.isInGroup(land_parcel->getGroupID())) + group_id = land_parcel->getGroupID(); + // Is the agent in the land group (the group owns the land) + else if(gAgent.isInGroup(land_parcel->getOwnerID())) + group_id = land_parcel->getOwnerID(); } - packAgentAndSessionAndGroupID(&group_id); LLDuplicateData* dup_data = (LLDuplicateData*) data; @@ -4917,10 +5066,12 @@ void LLSelectMgr::packPermissions(LLSelectNode* node, void *user_data) void LLSelectMgr::sendListToRegions(const std::string& message_name, void (*pack_header)(void *user_data), void (*pack_body)(LLSelectNode* node, void *user_data), + void (*log_func)(LLSelectNode* node, void *user_data), void *user_data, ESendType send_type) { LLSelectNode* node; + LLSelectNode* linkset_root = NULL; LLViewerRegion* last_region; LLViewerRegion* current_region; @@ -4928,10 +5079,12 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name, S32 packets_sent = 0; S32 objects_in_this_packet = 0; + bool link_operation = message_name == "ObjectLink"; + //clear update override data (allow next update through) struct f : public LLSelectedNodeFunctor { - virtual bool apply(LLSelectNode* node) + bool apply(LLSelectNode* node) override { node->mLastPositionLocal.setVec(0,0,0); node->mLastRotation = LLQuaternion(); @@ -4947,7 +5100,8 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name, { std::queue& nodes_to_send; push_all(std::queue& n) : nodes_to_send(n) {} - virtual bool apply(LLSelectNode* node) + + bool apply(LLSelectNode* node) override { if (node->getObject()) { @@ -4961,7 +5115,8 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name, std::queue& nodes_to_send; bool mRoots; push_some(std::queue& n, bool roots) : nodes_to_send(n), mRoots(roots) {} - virtual bool apply(LLSelectNode* node) + + bool apply(LLSelectNode* node) override { if (node->getObject()) { @@ -5036,8 +5191,16 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name, && (! gMessageSystem->isSendFull(NULL)) && (objects_in_this_packet < MAX_OBJECTS_PER_PACKET)) { + if (link_operation && linkset_root == NULL) + { + // linksets over 254 will be split into multiple messages, + // but we need to provide same root for all messages or we will get separate linksets + linkset_root = node; + } // add another instance of the body of the data (*pack_body)(node, user_data); + // do any related logging + (*log_func)(node, user_data); ++objects_sent; ++objects_in_this_packet; @@ -5062,6 +5225,22 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name, gMessageSystem->newMessage(message_name.c_str()); (*pack_header)(user_data); + if (linkset_root != NULL) + { + if (current_region != last_region) + { + // root should be in one region with the child, reset it + linkset_root = NULL; + } + else + { + // add root instance into new message + (*pack_body)(linkset_root, user_data); + ++objects_sent; + ++objects_in_this_packet; + } + } + // don't move to the next object, we still need to add the // body data. } @@ -5186,7 +5365,8 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data { LLUUID mID; f(const LLUUID& id) : mID(id) {} - virtual bool apply(LLSelectNode* node) + + bool apply(LLSelectNode* node) override { return (node->getObject() && node->getObject()->mID == mID); } @@ -5265,18 +5445,12 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data node->mInventorySerial = inv_serial; node->mSitName.assign(sit_name); node->mTouchName.assign(touch_name); + if (auto obj = node->getObject()) obj->mOwnerID = owner_id; // Singu Note: Try to get Owner whenever possible } } dialog_refresh_all(); - // silly hack to allow 'save into inventory' - if(gPopupMenuView->getVisible()) - { - gPopupMenuView->setItemEnabled(SAVE_INTO_INVENTORY, - enable_save_into_inventory(NULL)); - } - // hack for left-click buy object LLToolPie::selectionPropertiesReceived(); } @@ -5339,7 +5513,8 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use { LLUUID mID; f(const LLUUID& id) : mID(id) {} - virtual bool apply(LLSelectNode* node) + + bool apply(LLSelectNode* node) override { return (node->getObject() && node->getObject()->mID == mID); } @@ -5408,7 +5583,7 @@ void LLSelectMgr::updateSilhouettes() if (!mSilhouetteImagep) { - mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", TRUE, LLGLTexture::BOOST_UI); + mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI); } mHighlightedObjects->cleanupNodes(); @@ -5417,7 +5592,7 @@ void LLSelectMgr::updateSilhouettes() { struct f : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) + bool apply(LLViewerObject* object) override { object->setChanged(LLXform::SILHOUETTE); return true; @@ -5683,7 +5858,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) gGL.getTexUnit(0)->bind(mSilhouetteImagep); LLGLSPipelineSelection gls_select; - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); if (isAgentAvatarValid() && for_hud) @@ -5718,9 +5893,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) } LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getFocusedObjectID(); - // //for (S32 pass = 0; pass < 2; pass++) - // { for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); iter != mSelectedObjects->end(); iter++) @@ -5837,6 +6010,7 @@ LLSelectNode::LLSelectNode(LLViewerObject* object, BOOL glow) { selectAllTEs(FALSE); saveColors(); + saveShinyColors(); } LLSelectNode::LLSelectNode(const LLSelectNode& nodep) @@ -5882,6 +6056,11 @@ LLSelectNode::LLSelectNode(const LLSelectNode& nodep) { mSavedColors.push_back(*color_iter); } + mSavedShinyColors.clear(); + for (color_iter = nodep.mSavedShinyColors.begin(); color_iter != nodep.mSavedShinyColors.end(); ++color_iter) + { + mSavedShinyColors.push_back(*color_iter); + } saveTextures(nodep.mSavedTextures); } @@ -5934,6 +6113,11 @@ S32 LLSelectNode::getLastSelectedTE() return mLastTESelected; } +S32 LLSelectNode::getLastOperatedTE() +{ + return mLastTESelected; +} + LLViewerObject* LLSelectNode::getObject() { if (!mObject) @@ -5965,6 +6149,26 @@ void LLSelectNode::saveColors() } } +void LLSelectNode::saveShinyColors() +{ + if (mObject.notNull()) + { + mSavedShinyColors.clear(); + for (S32 i = 0; i < mObject->getNumTEs(); i++) + { + const LLMaterialPtr mat = mObject->getTE(i)->getMaterialParams(); + if (!mat.isNull()) + { + mSavedShinyColors.push_back(LLColor4(mat->getSpecularLightColor())); + } + else + { + mSavedShinyColors.push_back(LLColor4::white); + } + } + } +} + void LLSelectNode::saveTextures(const uuid_vec_t& textures) { if (mObject.notNull()) @@ -6140,7 +6344,7 @@ void pushWireframe(LLDrawable* drawable) for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) { const LLVolumeFace& face = volume->getVolumeFace(i); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mNumVertices, face.mPositions, NULL, face.mNumIndices, face.mIndices); } } @@ -6188,14 +6392,13 @@ void LLSelectNode::renderOneWireframe(const LLColor4& color) gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); } - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); //Singu Note: Diverges from v3. If sRenderHiddenSelections set, draw non-z-culled wireframe, else draw occluded 'thick' wireframe to create an outline. if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible()) { gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL); - if (shader) { gGL.diffuseColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); @@ -6205,7 +6408,7 @@ void LLSelectNode::renderOneWireframe(const LLColor4& color) { if (!LLGLSLShader::sNoFixedFunction) { - LLGLEnable fog(GL_FOG); + LLGLEnable fog; glFogi(GL_FOG_MODE, GL_LINEAR); float d = (LLViewerCamera::getInstance()->getPointOfInterest() - LLViewerCamera::getInstance()->getOrigin()).magVec(); LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal() - gAgentCamera.getCameraPositionGlobal()).magVec() / (LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec() * 4), 0.0, 1.0); @@ -6224,18 +6427,19 @@ void LLSelectNode::renderOneWireframe(const LLColor4& color) } else { - LLGLEnable cull_face(GL_CULL_FACE); - LLGLEnable offset(GL_POLYGON_OFFSET_LINE); + LLGLEnable cull_face; + LLGLEnable offset; gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.diffuseColor4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); - glPolygonOffset(3.f, 3.f); - glLineWidth(3.f); + gGL.setPolygonOffset(3.f, 3.f); + gGL.setLineWidth(3.f); pushWireframe(drawable); - glLineWidth(1.f); + gGL.setLineWidth(1.f); } - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); gGL.popMatrix(); if (shader) @@ -6330,7 +6534,7 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE); if (!LLGLSLShader::sNoFixedFunction) { - LLGLEnable fog(GL_FOG); + LLGLEnable fog; glFogi(GL_FOG_MODE, GL_LINEAR); float d = (LLViewerCamera::getInstance()->getPointOfInterest() - LLViewerCamera::getInstance()->getOrigin()).magVec(); LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal() - gAgentCamera.getCameraPositionGlobal()).magVec() / (LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec() * 4), 0.0, 1.0); @@ -6343,10 +6547,11 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.begin(LLRender::LINES); { + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); + for(S32 i = 0; i < (S32)mSilhouetteVertices.size(); i += 2) { u_coord += u_divisor * LLSelectMgr::sHighlightUScale; - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); gGL.texCoord2f( u_coord, v_coord ); gGL.vertex3fv( mSilhouetteVertices[i].mV); u_coord += u_divisor * LLSelectMgr::sHighlightUScale; @@ -6433,11 +6638,6 @@ void dialog_refresh_all() // and call into this function. Yuck. LLSelectMgr::getInstance()->mUpdateSignal(); - if (gNoRender) - { - return; - } - // *TODO: Eliminate all calls into outside classes below, make those // objects register with the update signal. @@ -6514,7 +6714,6 @@ void LLSelectMgr::updateSelectionCenter() mSelectionCenterGlobal.clearVec(); mShowSelection = FALSE; mSelectionBBox = LLBBox(); - mPauseRequests.clear(); resetAgentHUDZoom(); } @@ -6522,21 +6721,7 @@ void LLSelectMgr::updateSelectionCenter() { mSelectedObjects->mSelectType = getSelectTypeForObject(object); - if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid()) - { - // Freeze avatars with a selected attachment, and all avatars with synchronized motions, if any. - LLVOAvatar* avatar = object->getAvatar(); - // It is possible that 'avatar' is NULL despite this being an attachment because of some race condition. - // In that case just don't freeze the avatar. - if (avatar) - { - avatar->pauseAllSyncedCharacters(mPauseRequests); - } - } - else - { - mPauseRequests.clear(); - } + if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && isAgentAvatarValid()) { @@ -6614,6 +6799,67 @@ void LLSelectMgr::updateSelectionCenter() { gEditMenuHandler = NULL; } + + pauseAssociatedAvatars(); +} + +//----------------------------------------------------------------------------- +// pauseAssociatedAvatars +// +// If the selection includes an attachment or an animated object, the +// associated avatars should pause their animations until they are no +// longer selected. +//----------------------------------------------------------------------------- +void LLSelectMgr::pauseAssociatedAvatars() +{ + mPauseRequests.clear(); + + for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); + iter != mSelectedObjects->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if (!object) + continue; + + mSelectedObjects->mSelectType = getSelectTypeForObject(object); + + if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT && + isAgentAvatarValid() && object->getParent() != NULL) + { + if (object->isAnimatedObject()) + { + // Is an animated object attachment. + // Pause both the control avatar and the avatar it's attached to. + if (object->getControlAvatar()) + { + object->getControlAvatar()->pauseAllSyncedCharacters(mPauseRequests); + } + LLVOAvatar* avatar = object->getAvatar(); + if (avatar) + { + avatar->pauseAllSyncedCharacters(mPauseRequests); + } + } + else + { + // Is a regular attachment. Pause the avatar it's attached to. + LLVOAvatar* avatar = object->getAvatar(); + if (avatar) + { + avatar->pauseAllSyncedCharacters(mPauseRequests); + } + } + } + else + { + if (object && object->isAnimatedObject() && object->getControlAvatar()) + { + // Is a non-attached animated object. Pause the control avatar. + object->getControlAvatar()->pauseAllSyncedCharacters(mPauseRequests); + } + } + } } void LLSelectMgr::updatePointAt() @@ -6678,7 +6924,7 @@ void LLSelectMgr::undo() { BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); LLUUID group_id(gAgent.getGroupID()); - sendListToRegions("Undo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); + sendListToRegions("Undo", packAgentAndSessionAndGroupID, packObjectID, logNoOp, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); } //----------------------------------------------------------------------------- @@ -6696,7 +6942,7 @@ void LLSelectMgr::redo() { BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); LLUUID group_id(gAgent.getGroupID()); - sendListToRegions("Redo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); + sendListToRegions("Redo", packAgentAndSessionAndGroupID, packObjectID, logNoOp, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); } //----------------------------------------------------------------------------- @@ -6811,7 +7057,7 @@ void LLSelectMgr::validateSelection() { struct f : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) + bool apply(LLViewerObject* object) override { if (!LLSelectMgr::getInstance()->canSelectObject(object)) { @@ -6823,7 +7069,7 @@ void LLSelectMgr::validateSelection() getSelection()->applyToObjects(&func); } -BOOL LLSelectMgr::canSelectObject(LLViewerObject* object) +BOOL LLSelectMgr::canSelectObject(LLViewerObject* object, BOOL ignore_select_owned) { // Never select dead objects if (!object || object->isDead()) @@ -6836,11 +7082,14 @@ BOOL LLSelectMgr::canSelectObject(LLViewerObject* object) return TRUE; } - if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) || - (gSavedSettings.getBOOL("SelectMovableOnly") && (!object->permMove() || object->isPermanentEnforced()))) + if(!ignore_select_owned) { - // only select my own objects - return FALSE; + if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) || + (gSavedSettings.getBOOL("SelectMovableOnly") && (!object->permMove() || object->isPermanentEnforced()))) + { + // only select my own objects + return FALSE; + } } // Can't select orphans @@ -7039,7 +7288,7 @@ F32 LLObjectSelection::getSelectedLinksetCost() LLSelectNode* node = *iter; LLViewerObject* object = node->getObject(); - if (object) + if (object && !object->isAttachment()) { LLViewerObject* root = static_cast(object->getRoot()); if (root) @@ -7114,10 +7363,16 @@ F32 LLObjectSelection::getSelectedObjectStreamingCost(S32* total_bytes, S32* vis if (object) { + cost += object->getStreamingCost(); + S32 bytes = 0; S32 visible = 0; - cost += object->getStreamingCost(&bytes, &visible); - + LLMeshCostData costs; + if (object->getCostData(costs)) + { + bytes = costs.getSizeTotal(); + visible = costs.getSizeByLOD(object->getLOD()); + } if (total_bytes) { *total_bytes += bytes; @@ -7143,7 +7398,9 @@ U32 LLObjectSelection::getSelectedObjectTriangleCount(S32* vcount) if (object) { - count += object->getTriangleCount(vcount); + S32 vt = 0; + count += object->getTriangleCount(&vt); + *vcount += vt; } } @@ -7154,8 +7411,7 @@ S32 LLObjectSelection::getSelectedObjectRenderCost() { S32 cost = 0; LLVOVolume::texture_cost_t textures; - typedef std::set uuid_list_t; - uuid_list_t computed_objects; + uuid_set_t computed_objects; typedef std::list > child_list_t; typedef const child_list_t const_child_list_t; @@ -7178,7 +7434,7 @@ S32 LLObjectSelection::getSelectedObjectRenderCost() ++child_iter) { LLViewerObject* child_obj = *child_iter; - LLVOVolume *child = dynamic_cast( child_obj ); + LLVOVolume *child = child_obj ? child_obj->asVolume() : nullptr; if (child) { cost += child->getRenderCost(textures); @@ -7272,6 +7528,31 @@ bool LLObjectSelection::applyToObjects(LLSelectedObjectFunctor* func) return result; } +bool LLObjectSelection::checkAnimatedObjectEstTris() +{ + F32 est_tris = 0; + F32 max_tris = 0; + S32 anim_count = 0; + for (root_iterator iter = root_begin(); iter != root_end(); ++iter) + { + LLViewerObject* object = (*iter)->getObject(); + if (!object) + continue; + if (object->isAnimatedObject()) + { + anim_count++; + } + est_tris += object->recursiveGetEstTrianglesMax(); + max_tris = llmax((F32)max_tris,(F32)object->getAnimatedObjectMaxTris()); + } + return anim_count==0 || est_tris <= max_tris; +} + +bool LLObjectSelection::checkAnimatedObjectLinkable() +{ + return checkAnimatedObjectEstTris(); +} + bool LLObjectSelection::applyToRootObjects(LLSelectedObjectFunctor* func, bool firstonly) { bool result = firstonly ? false : true; @@ -7528,7 +7809,7 @@ LLSelectNode* LLObjectSelection::getFirstMoveableNode(BOOL get_root_first) { struct f : public LLSelectedNodeFunctor { - bool apply(LLSelectNode* node) + bool apply(LLSelectNode* node) override { LLViewerObject* obj = node->getObject(); return obj && obj->permMove() && !obj->isPermanentEnforced(); @@ -7545,7 +7826,7 @@ LLViewerObject* LLObjectSelection::getFirstCopyableObject(BOOL get_parent) { struct f : public LLSelectedNodeFunctor { - bool apply(LLSelectNode* node) + bool apply(LLSelectNode* node) override { LLViewerObject* obj = node->getObject(); return obj && obj->permCopy() && !obj->isAttachment(); @@ -7564,7 +7845,7 @@ LLViewerObject* LLObjectSelection::getFirstDeleteableObject() struct f : public LLSelectedNodeFunctor { - bool apply(LLSelectNode* node) + bool apply(LLSelectNode* node) override { LLViewerObject* obj = node->getObject(); // you can delete an object if you are the owner @@ -7593,7 +7874,7 @@ LLViewerObject* LLObjectSelection::getFirstEditableObject(BOOL get_parent) { struct f : public LLSelectedNodeFunctor { - bool apply(LLSelectNode* node) + bool apply(LLSelectNode* node) override { LLViewerObject* obj = node->getObject(); return obj && obj->permModify(); @@ -7609,7 +7890,7 @@ LLViewerObject* LLObjectSelection::getFirstMoveableObject(BOOL get_parent) { struct f : public LLSelectedNodeFunctor { - bool apply(LLSelectNode* node) + bool apply(LLSelectNode* node) override { LLViewerObject* obj = node->getObject(); return obj && obj->permMove() && !obj->isPermanentEnforced(); diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 145c25005f..5252c5a179 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -146,6 +146,7 @@ class LLSelectNode void selectTE(S32 te_index, BOOL selected); BOOL isTESelected(S32 te_index); S32 getLastSelectedTE(); + S32 getLastOperatedTE(); S32 getTESelectMask() { return mTESelectMask; } void renderOneWireframe(const LLColor4& color); void renderOneSilhouette(const LLColor4 &color); @@ -155,6 +156,7 @@ class LLSelectNode void setObject(LLViewerObject* object); // *NOTE: invalidate stored textures and colors when # faces change void saveColors(); + void saveShinyColors(); void saveTextures(const uuid_vec_t& textures); void saveTextureScaleRatios(LLRender::eTexIndex index_to_query); @@ -191,6 +193,7 @@ class LLSelectNode std::string mSitName; U64 mCreationDate; std::vector mSavedColors; + std::vector mSavedShinyColors; uuid_vec_t mSavedTextures; std::vector mTextureScaleRatios; std::vector mSilhouetteVertices; // array of vertices to render silhouette of object @@ -206,6 +209,7 @@ class LLSelectNode class LLObjectSelection : public LLRefCount { friend class LLSelectMgr; + friend class LLSafeHandle; protected: ~LLObjectSelection(); @@ -218,7 +222,7 @@ class LLObjectSelection : public LLRefCount { bool operator()(LLSelectNode* node) { - return (node->getObject() != NULL); + return (node->getObject() != nullptr); } }; typedef boost::filter_iterator iterator; @@ -229,7 +233,7 @@ class LLObjectSelection : public LLRefCount { bool operator()(LLSelectNode* node) { - return (node->getObject() != NULL) && node->mValid; + return (node->getObject() != nullptr) && node->mValid; } }; typedef boost::filter_iterator valid_iterator; @@ -267,8 +271,8 @@ class LLObjectSelection : public LLRefCount BOOL isEmpty() const; - LLSelectNode* getFirstNode(LLSelectedNodeFunctor* func = NULL); - LLSelectNode* getFirstRootNode(LLSelectedNodeFunctor* func = NULL, BOOL non_root_ok = FALSE); + LLSelectNode* getFirstNode(LLSelectedNodeFunctor* func = nullptr); + LLSelectNode* getFirstRootNode(LLSelectedNodeFunctor* func = nullptr, BOOL non_root_ok = FALSE); LLViewerObject* getFirstSelectedObject(LLSelectedNodeFunctor* func, BOOL get_parent = FALSE); LLViewerObject* getFirstObject(); LLViewerObject* getFirstRootObject(BOOL non_root_ok = FALSE); @@ -298,8 +302,8 @@ class LLObjectSelection : public LLRefCount F32 getSelectedLinksetPhysicsCost(); S32 getSelectedObjectRenderCost(); - F32 getSelectedObjectStreamingCost(S32* total_bytes = NULL, S32* visible_bytes = NULL); - U32 getSelectedObjectTriangleCount(S32* vcount = NULL); + F32 getSelectedObjectStreamingCost(S32* total_bytes = nullptr, S32* visible_bytes = nullptr); + U32 getSelectedObjectTriangleCount(S32* vcount = nullptr); S32 getTECount(); S32 getRootObjectCount(); @@ -311,6 +315,9 @@ class LLObjectSelection : public LLRefCount // returns TRUE is any node is currenly worn as an attachment BOOL isAttachment(); + bool checkAnimatedObjectEstTris(); + bool checkAnimatedObjectLinkable(); + // Apply functors to various subsets of the selected objects // If firstonly is FALSE, returns the AND of all apply() calls. // Else returns TRUE immediately if any apply() call succeeds (i.e. OR with early exit) @@ -320,6 +327,15 @@ class LLObjectSelection : public LLRefCount bool applyToRootNodes(LLSelectedNodeFunctor* func, bool firstonly = false); bool applyToNodes(LLSelectedNodeFunctor* func, bool firstonly = false); + /* + * Used to apply (no-copy) textures to the selected object or + * selected face/faces of the object. + * This method moves (no-copy) texture to the object's inventory + * and doesn't make copy of the texture for each face. + * Then this only texture is used for all selected faces. + */ + void applyNoCopyTextureToTEs(LLViewerInventoryItem* item); + ESelectType getSelectType() const { return mSelectType; } private: @@ -330,10 +346,8 @@ class LLObjectSelection : public LLRefCount void deleteAllNodes(); void cleanupNodes(); - -private: list_t mList; - const LLObjectSelection &operator=(const LLObjectSelection &); + const LLObjectSelection& operator=(const LLObjectSelection&) = delete; LLPointer mPrimaryObject; std::map, LLSelectNode*> mSelectNodeMap; @@ -347,6 +361,9 @@ typedef LLSafeHandle LLObjectSelectionHandle; extern template class LLSelectMgr* LLSingleton::getInstance(); #endif +// For use with getFirstTest() +struct LLSelectGetFirstTest; + class LLSelectMgr : public LLEditMenuHandler, public LLSingleton { public: @@ -380,20 +397,19 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton static void cleanupGlobals(); // LLEditMenuHandler interface - virtual BOOL canUndo() const; - virtual void undo(); - - virtual BOOL canRedo() const; - virtual void redo(); + BOOL canUndo() const override; + void undo() override; - virtual BOOL canDoDelete() const; - virtual void doDelete(); + BOOL canRedo() const override; + void redo() override; - virtual void selectAll(); - virtual BOOL canSelectAll() const; + BOOL canDoDelete() const override; + void doDelete() override; - virtual void deselect(); - virtual BOOL canDeselect() const; + void selectAll() override; + BOOL canSelectAll() const override; + void deselect() override; + BOOL canDeselect() const override; virtual void duplicate(); virtual BOOL canDuplicate() const; @@ -419,7 +435,7 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton // // *NOTE: You must hold on to the object selection handle, otherwise // the objects will be automatically deselected in 1 frame. - LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE); + LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE, BOOL ignore_select_owned = FALSE); // For when you want just a child object. LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES); @@ -491,7 +507,7 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton void clearGridObjects(); void setGridMode(EGridMode mode); EGridMode getGridMode() { return mGridMode; } - void getGrid(LLVector3& origin, LLQuaternion& rotation, LLVector3 &scale); + void getGrid(LLVector3& origin, LLQuaternion& rotation, LLVector3 &scale, bool for_snap_guides = false); BOOL getTEMode() { return mTEMode; } void setTEMode(BOOL b) { mTEMode = b; } @@ -513,6 +529,7 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton //////////////////////////////////////////////////////////////// void saveSelectedObjectTransform(EActionType action_type); void saveSelectedObjectColors(); + void saveSelectedShinyColors(); void saveSelectedObjectTextures(); // Sets which texture channel to query for scale and rot of display @@ -541,6 +558,7 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton void selectionSetColorOnly(const LLColor4 &color); // Set only the RGB channels void selectionSetAlphaOnly(const F32 alpha); // Set only the alpha channel void selectionRevertColors(); + void selectionRevertShinyColors(); BOOL selectionRevertTextures(); void selectionSetBumpmap( U8 bumpmap ); void selectionSetTexGen( U8 texgen ); @@ -573,7 +591,7 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton void validateSelection(); // returns TRUE if it is possible to select this object - BOOL canSelectObject(LLViewerObject* object); + BOOL canSelectObject(LLViewerObject* object, BOOL ignore_select_owned = FALSE); // Returns TRUE if the viewer has information on all selected objects BOOL selectGetAllRootsValid(); @@ -584,6 +602,9 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton BOOL selectGetRootsModify(); BOOL selectGetModify(); + // returns TRUE if all objects are in same region + BOOL selectGetSameRegion(); + // returns TRUE if is all objects are non-permanent-enforced BOOL selectGetRootsNonPermanentEnforced(); BOOL selectGetNonPermanentEnforced(); @@ -699,6 +720,8 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton LLVector3d getSelectionCenterGlobal() const { return mSelectionCenterGlobal; } void updateSelectionCenter(); + void pauseAssociatedAvatars(); + void resetAgentHUDZoom(); void setAgentHUDZoom(F32 target_zoom, F32 current_zoom); void getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const; @@ -723,6 +746,7 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton void sendListToRegions( const std::string& message_name, void (*pack_header)(void *user_data), void (*pack_body)(LLSelectNode* node, void *user_data), + void (*log_func)(LLSelectNode* node, void *user_data), void *user_data, ESendType send_type); @@ -758,6 +782,9 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton static void packHingeHead(void *user_data); static void packPermissionsHead(void* user_data); static void packGodlikeHead(void* user_data); + static void logNoOp(LLSelectNode* node, void *user_data); + static void logAttachmentRequest(LLSelectNode* node, void *user_data); + static void logDetachRequest(LLSelectNode* node, void *user_data); static bool confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle); public: diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp new file mode 100644 index 0000000000..7df3211ea2 --- /dev/null +++ b/indra/newview/llskinningutil.cpp @@ -0,0 +1,356 @@ +/** +* @file llskinningutil.cpp +* @brief Functions for mesh object skinning +* @author vir@lindenlab.com +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, 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 "llviewerprecompiledheaders.h" + +#include "llskinningutil.h" +#include "llvoavatar.h" +#include "llviewercontrol.h" +#include "llmeshrepository.h" + +// static +void LLSkinningUtil::initClass() +{ +} + +U32 LLSkinningUtil::getMaxJointCount() +{ + U32 result = LL_MAX_JOINTS_PER_MESH_OBJECT; + return result; +} + +U32 LLSkinningUtil::getMeshJointCount(const LLMeshSkinInfo *skin) +{ + return llmin((U32)getMaxJointCount(), (U32)skin->mJointNames.size()); +} + +void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin) +{ + if (skin->mInvalidJointsScrubbed) + { + return; + } + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + // Fix invalid names to "mPelvis". Currently meshes with + // invalid names will be blocked on upload, so this is just + // needed for handling of any legacy bad data. + if (!avatar->getJoint(skin->mJointNames[j])) + { + LL_DEBUGS("Avatar") << avatar->getFullname() << " mesh rigged to invalid joint " << skin->mJointNames[j] << LL_ENDL; + LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " mesh rigged to invalid joint" << skin->mJointNames[j] << LL_ENDL; + skin->mJointNames[j] = "mPelvis"; + skin->mJointNumsInitialized = false; // force update after names change. + } + } + skin->mInvalidJointsScrubbed = true; +} + +// static +void LLSkinningUtil::initSkinningMatrixPalette( + LLMatrix4a* mat, + S32 count, + const LLMeshSkinInfo* skin, + LLVOAvatar *avatar, + bool relative_to_avatar) +{ + LLVector4a pos = LLVector4a::getZero(); + if (relative_to_avatar) + { + pos.load3(avatar->getPosition().mV); + pos.mul(-1.f); + } + + initJointNums(const_cast(skin), avatar); + for (U32 j = 0; j < (U32)count; ++j) + { + LLJoint *joint = avatar->getJoint(skin->mJointNums[j]); + if (joint) + { + LLMatrix4a bind; + bind.loadu((F32*)skin->mInvBindMatrix[j].mMatrix); + LLMatrix4a world = joint->getWorldMatrix(); + world.getRow<3>().add(pos); // Append pos into world matrix. + mat[j].setMul(world, bind); + } + else + { + mat[j].loadu((F32*)skin->mInvBindMatrix[j].mMatrix); + // This shouldn't happen - in mesh upload, skinned + // rendering should be disabled unless all joints are + // valid. In other cases of skinned rendering, invalid + // joints should already have been removed during scrubInvalidJoints(). + LL_WARNS_ONCE("Avatar") << avatar->getFullname() + << " rigged to invalid joint name " << skin->mJointNames[j] + << " num " << skin->mJointNums[j] << LL_ENDL; + LL_WARNS_ONCE("Avatar") << avatar->getFullname() + << " avatar build state: isBuilt() " << avatar->isBuilt() + << " mInitFlags " << avatar->mInitFlags << LL_ENDL; + } + } +} + + +void LLSkinningUtil::checkSkinWeights(const LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) +{ +#ifndef LL_RELEASE_FOR_DOWNLOAD + const S32 max_joints = skin->mJointNames.size(); + for (U32 j=0; j=0); + llassert(i 0.0f); + } +#endif +} + +void LLSkinningUtil::scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) +{ + const S32 max_joints = skin->mJointNames.size(); + for (U32 j=0; j0.f); + + wght *= 1.f/scale; + } + + for (U32 k = 0; k < 4; k++) + { + F32 w = wght[k]; + + LLMatrix4a src; + src.setMul(mat[idx[k]], w); + + final_mat.add(src); + } + // SL-366 - with weight validation/cleanup code, it should no longer be + // possible to hit the bad scale case. + llassert(valid_weights); +} + +void LLSkinningUtil::initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar) +{ + if (!skin->mJointNumsInitialized) + { + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + LLJoint *joint = NULL; + if (skin->mJointNums[j] == -1) + { + joint = avatar->getJoint(skin->mJointNames[j]); + if (joint) + { + skin->mJointNums[j] = joint->getJointNum(); + if (skin->mJointNums[j] < 0) + { + LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " joint has unusual number " << skin->mJointNames[j] << ": " << skin->mJointNums[j] << LL_ENDL; + LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " avatar build state: isBuilt() " << avatar->isBuilt() << " mInitFlags " << avatar->mInitFlags << LL_ENDL; + } + } + else + { + LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " unable to find joint " << skin->mJointNames[j] << LL_ENDL; + LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " avatar build state: isBuilt() " << avatar->isBuilt() << " mInitFlags " << avatar->mInitFlags << LL_ENDL; +#if 0 + dump_avatar_and_skin_state("initJointNums joint not found", avatar, skin); +#endif + } + } + } + skin->mJointNumsInitialized = true; + } +} + +static LLTrace::BlockTimerStatHandle FTM_FACE_RIGGING_INFO("Face Rigging Info"); + +// How many copies of the same code do we need, LL? +void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *avatar, LLVolumeFace& vol_face) +{ + LL_RECORD_BLOCK_TIME(FTM_FACE_RIGGING_INFO); + + if (vol_face.mJointRiggingInfoTab.needsUpdate()) + { + S32 num_verts = vol_face.mNumVertices; + if (num_verts>0 && vol_face.mWeights && (skin->mJointNames.size()>0)) + { + initJointNums(const_cast(skin), avatar); + if (vol_face.mJointRiggingInfoTab.size()==0) + { + //std::set active_joints; + //S32 active_verts = 0; + vol_face.mJointRiggingInfoTab.resize(LL_CHARACTER_MAX_ANIMATED_JOINTS); + LLJointRiggingInfoTab &rig_info_tab = vol_face.mJointRiggingInfoTab; + LLMatrix4a bind_shape; + bind_shape.loadu(skin->mBindShapeMatrix); + LLMatrix4a matrixPalette[LL_CHARACTER_MAX_ANIMATED_JOINTS]; + for (U32 i = 0; i < llmin(skin->mInvBindMatrix.size(), (size_t)LL_CHARACTER_MAX_ANIMATED_JOINTS); ++i) + { + LLMatrix4a inverse_bind; + inverse_bind.loadu(skin->mInvBindMatrix[i]); + matrixPalette[i].setMul(inverse_bind, bind_shape); + } + for (S32 i=0; i 0.0f) + { + for (U32 k=0; k<4; ++k) + { + wght[k] /= scale; + } + } + for (U32 k=0; k<4; ++k) + { + S32 joint_index = idx[k]; + if (wght[k] > 0.0f) + { + S32 joint_num = skin->mJointNums[joint_index]; + if (joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS) + { + rig_info_tab[joint_num].setIsRiggedTo(true); + LLVector4a pos_joint_space; + matrixPalette[joint_index].affineTransform(pos, pos_joint_space); + pos_joint_space.mul(wght[k]); + LLVector4a *extents = rig_info_tab[joint_num].getRiggedExtents(); + update_min_max(extents[0], extents[1], pos_joint_space); + } + } + } + } + //LL_DEBUGS("RigSpammish") << "built rigging info for vf " << &vol_face + // << " num_verts " << vol_face.mNumVertices + // << " active joints " << active_joints.size() + // << " active verts " << active_verts + // << LL_ENDL; + vol_face.mJointRiggingInfoTab.setNeedsUpdate(false); + } + } + if (vol_face.mJointRiggingInfoTab.size()!=0) + { + LL_DEBUGS("RigSpammish") << "we have rigging info for vf " << &vol_face + << " num_verts " << vol_face.mNumVertices << LL_ENDL; + } + else + { + LL_DEBUGS("RigSpammish") << "no rigging info for vf " << &vol_face + << " num_verts " << vol_face.mNumVertices << LL_ENDL; + } + + } +} + +// This is used for extracting rotation from a bind shape matrix that +// already has scales baked in +LLQuaternion LLSkinningUtil::getUnscaledQuaternion(const LLMatrix4& mat4) +{ + LLMatrix3 bind_mat = mat4.getMat3(); + for (auto i = 0; i < 3; i++) + { + F32 len = 0.0f; + for (auto j = 0; j < 3; j++) + { + len += bind_mat.mMatrix[i][j] * bind_mat.mMatrix[i][j]; + } + if (len > 0.0f) + { + len = sqrt(len); + for (auto j = 0; j < 3; j++) + { + bind_mat.mMatrix[i][j] /= len; + } + } + } + bind_mat.invert(); + LLQuaternion bind_rot = bind_mat.quaternion(); + bind_rot.normalize(); + return bind_rot; +} diff --git a/indra/newview/llskinningutil.h b/indra/newview/llskinningutil.h new file mode 100644 index 0000000000..fd4643febb --- /dev/null +++ b/indra/newview/llskinningutil.h @@ -0,0 +1,50 @@ +/** +* @file llskinningutil.h +* @brief Functions for mesh object skinning +* @author vir@lindenlab.com +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, 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 LLSKINNINGUTIL_H +#define LLSKINNINGUTIL_H + +class LLVOAvatar; +class LLMeshSkinInfo; +class LLMatrix4a; +class LLVolumeFace; + +namespace LLSkinningUtil +{ + void initClass(); + U32 getMaxJointCount(); + U32 getMeshJointCount(const LLMeshSkinInfo *skin); + void scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin); + void initSkinningMatrixPalette(LLMatrix4a* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar, bool relative_to_avatar = false); + void checkSkinWeights(const LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); + void scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); + void getPerVertexSkinMatrix(const F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); + void initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar); + void updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *avatar, LLVolumeFace& vol_face); + LLQuaternion getUnscaledQuaternion(const LLMatrix4& mat4); +}; + +#endif diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp index de99cb86fa..b223acf78a 100644 --- a/indra/newview/llsky.cpp +++ b/indra/newview/llsky.cpp @@ -287,38 +287,38 @@ LLColor4U LLSky::getFadeColor() const void LLSky::init(const LLVector3 &sun_direction) { - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); mVOWLSkyp = static_cast(gObjectList.createObjectViewer(LLViewerObject::LL_VO_WL_SKY, NULL)); mVOWLSkyp->initSunDirection(sun_direction, LLVector3::zero); gPipeline.createObject(mVOWLSkyp.get()); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); mVOSkyp = (LLVOSky *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SKY, NULL); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); mVOSkyp->initSunDirection(sun_direction, LLVector3()); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); gPipeline.createObject((LLViewerObject *)mVOSkyp); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); mVOGroundp = (LLVOGround*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_GROUND, NULL); LLVOGround *groundp = mVOGroundp; gPipeline.createObject((LLViewerObject *)groundp); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + gSky.setFogRatio(gSavedSettings.getF32("RenderFogRatio")); //////////////////////////// @@ -330,8 +330,8 @@ void LLSky::init(const LLVector3 &sun_direction) // Get the parameters. mSunDefaultPosition = gSavedSettings.getVector3("SkySunDefaultPosition"); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + //LLGLStateValidator::checkStates(); + //LLGLStateValidator::checkTextureChannels(); if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition") || mOverrideSimSunPosition) { @@ -342,8 +342,8 @@ void LLSky::init(const LLVector3 &sun_direction) setSunDirection(sun_direction, LLVector3(0.f, 0.f, 0.f)); } - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + //LLGLStateValidator::checkStates(); + //LLGLStateValidator::checkTextureChannels(); mUpdatedThisFrame = TRUE; } diff --git a/indra/newview/llslurl.cpp b/indra/newview/llslurl.cpp index d221783777..03f67b41de 100644 --- a/indra/newview/llslurl.cpp +++ b/indra/newview/llslurl.cpp @@ -1,5 +1,7 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com /** - * @file llurlsimstring.cpp (was llsimurlstring.cpp) + * @file llslurl.cpp (was llsimurlstring.cpp) * @brief Handles "SLURL fragments" like Ahern/123/45 for * startup processing, login screen, prefs, etc. * @@ -48,7 +50,8 @@ const char* LLSLURL::SLURL_COM = "slurl.com"; const char* LLSLURL::WWW_SLURL_COM = "www.slurl.com"; const char* LLSLURL::MAPS_SECONDLIFE_COM = "maps.secondlife.com"; -const char* LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME = "x-grid-location-info"; +const char* LLSLURL::SLURL_X_GRID_INFO_SCHEME = "x-grid-info"; +const char* LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME = "x-grid-location-info"; // <- deprecated! const char* LLSLURL::SLURL_APP_PATH = "app"; const char* LLSLURL::SLURL_REGION_PATH = "region"; const char* LLSLURL::SIM_LOCATION_HOME = "home"; @@ -58,8 +61,8 @@ const std::string MAIN_GRID_SLURL_BASE = "http://maps.secondlife.com/secondlife/ const std::string SYSTEM_GRID_APP_SLURL_BASE = "secondlife:///app"; const char* SYSTEM_GRID_SLURL_BASE = "secondlife://%s/secondlife/"; -const char* DEFAULT_SLURL_BASE = "https://%s/region/"; -const char* DEFAULT_APP_SLURL_BASE = "x-grid-location-info://%s/app"; +const char* DEFAULT_SLURL_BASE = "x-grid-info://%s/region/"; +const char* DEFAULT_APP_SLURL_BASE = "x-grid-info://%s/app"; #define MAINGRID "secondlife" // resolve a simstring from a slurl @@ -214,7 +217,8 @@ LLSLURL::LLSLURL(const std::string& slurl) } else if((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME) || (slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) || - (slurl_uri.scheme() == LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME)) + (slurl_uri.scheme() == LLSLURL::SLURL_X_GRID_INFO_SCHEME) || + (slurl_uri.scheme() == LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME)) // deprecated legacy { // We're dealing with either a Standalone style slurl or slurl.com slurl if ((slurl_uri.hostName() == LLSLURL::SLURL_COM) || @@ -239,7 +243,7 @@ LLSLURL::LLSLURL(const std::string& slurl) // As it's a Standalone grid/open, we will always have a hostname, as Standalone/open style // urls are properly formed, unlike the stinky maingrid style - mGrid = slurl_uri.hostName(); + mGrid = slurl_uri.hostNameAndPort(); } if (path_array.size() == 0) { @@ -266,7 +270,7 @@ LLSLURL::LLSLURL(const std::string& slurl) } else { - // not a valid https/http/x-grid-location-info slurl, so it'll likely just be a URL + // not a valid https/http/x-grid-info slurl, so it'll likely just be a URL return; } } @@ -304,7 +308,14 @@ LLSLURL::LLSLURL(const std::string& slurl) // at this point, head of the path array should be [ , , , ] where x, y and z // are collectively optional // are optional + mRegion = LLURI::unescape(path_array[0].asString()); + + if(LLStringUtil::containsNonprintable(mRegion)) + { + LLStringUtil::stripNonprintable(mRegion); + } + path_array.erase(0); // parse the x, y, and optionally z @@ -313,11 +324,11 @@ LLSLURL::LLSLURL(const std::string& slurl) mPosition = LLVector3(path_array); // this construction handles LLSD without all components (values default to 0.f) if((F32(mPosition[VX]) < 0.f) || - (mPosition[VX] > 8192.f/*REGION_WIDTH_METERS*/) || + (mPosition[VX] > 8192.f) || (F32(mPosition[VY]) < 0.f) || - (mPosition[VY] > 8192.f/*REGION_WIDTH_METERS*/) || + (mPosition[VY] > 8192.f) || (F32(mPosition[VZ]) < 0.f) || - (mPosition[VZ] > 8192.f/*REGION_HEIGHT_METERS*/)) + (mPosition[VZ] > 8192.f)) { mType = INVALID; return; @@ -444,9 +455,9 @@ std::string LLSLURL::getSLURLString() const app_url << SYSTEM_GRID_APP_SLURL_BASE << "/" << mAppCmd; else app_url << llformat(DEFAULT_APP_SLURL_BASE, gHippoGridManager->getCurrentGridNick().c_str()) << "/" << mAppCmd; - for(LLSD::array_const_iterator i = mAppPath.beginArray(); + for(auto i = mAppPath.beginArray(); i != mAppPath.endArray(); - i++) + ++i) { app_url << "/" << i->asString(); } diff --git a/indra/newview/llslurl.h b/indra/newview/llslurl.h index b86cf7949b..3beff26c74 100644 --- a/indra/newview/llslurl.h +++ b/indra/newview/llslurl.h @@ -44,6 +44,7 @@ class LLSLURL static const char* WWW_SLURL_COM; static const char* SECONDLIFE_COM; static const char* MAPS_SECONDLIFE_COM; + static const char* SLURL_X_GRID_INFO_SCHEME; static const char* SLURL_X_GRID_LOCATION_INFO_SCHEME; static LLSLURL START_LOCATION; static const char* SIM_LOCATION_HOME; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 7d66f75fcf..97decd6fea 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -59,9 +59,10 @@ #include "llvolumemgr.h" #include "llglslshader.h" #include "llviewershadermgr.h" +#include "llcontrolavatar.h" -static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling"); -static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound"); +static LLTrace::BlockTimerStatHandle FTM_FRUSTUM_CULL("Frustum Culling"); +static LLTrace::BlockTimerStatHandle FTM_CULL_REBOUND("Cull Rebound"); extern bool gShiftFrame; @@ -69,6 +70,7 @@ static U32 sZombieGroups = 0; U32 LLSpatialGroup::sNodeCount = 0; U32 gOctreeMaxCapacity; +float gOctreeMinSize; U32 gOctreeReserveCapacity; BOOL LLSpatialGroup::sNoDelete = FALSE; @@ -76,6 +78,8 @@ BOOL LLSpatialGroup::sNoDelete = FALSE; static F32 sLastMaxTexPriority = 1.f; static F32 sCurMaxTexPriority = 1.f; +BOOL LLSpatialPartition::sTeleportRequested = FALSE; + //BOOL LLSpatialPartition::sFreezeState = FALSE; //static counter for frame to switch LOD on @@ -293,10 +297,10 @@ void LLSpatialGroup::rebuildMesh() } } -static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); -static LLFastTimer::DeclareTimer FTM_ADD_GEOMETRY_COUNT("Add Geometry"); -static LLFastTimer::DeclareTimer FTM_CREATE_VB("Create VB"); -static LLFastTimer::DeclareTimer FTM_GET_GEOMETRY("Get Geometry"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_VBO("VBO Rebuilt"); +static LLTrace::BlockTimerStatHandle FTM_ADD_GEOMETRY_COUNT("Add Geometry"); +static LLTrace::BlockTimerStatHandle FTM_CREATE_VB("Create VB"); +static LLTrace::BlockTimerStatHandle FTM_GET_GEOMETRY("Get Geometry"); void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { @@ -311,7 +315,7 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) group->mLastUpdateViewAngle = group->mViewAngle; } - LLFastTimer ftm(FTM_REBUILD_VBO); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VBO); group->clearDrawMap(); @@ -320,14 +324,14 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) U32 vertex_count = 0; { - LLFastTimer t(FTM_ADD_GEOMETRY_COUNT); + LL_RECORD_BLOCK_TIME(FTM_ADD_GEOMETRY_COUNT); addGeometryCount(group, vertex_count, index_count); } if (vertex_count > 0 && index_count > 0) { //create vertex buffer containing volume geometry for this node { - LLFastTimer t(FTM_CREATE_VB); + LL_RECORD_BLOCK_TIME(FTM_CREATE_VB); group->mBuilt = 1.f; if (group->mVertexBuffer.isNull() || !group->mVertexBuffer->isWriteable() || @@ -345,14 +349,14 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) } { - LLFastTimer t(FTM_GET_GEOMETRY); + LL_RECORD_BLOCK_TIME(FTM_GET_GEOMETRY); getGeometry(group); } } else { group->mVertexBuffer = NULL; - group->mBufferMap.clear(); + group->mBufferVec.clear(); } group->mLastUpdateTime = gFrameTimeSeconds; @@ -737,22 +741,9 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) } } - //clean up avatar attachment stats - LLSpatialBridge* bridge = getSpatialPartition()->asBridge(); - if (bridge) - { - if (bridge->mAvatar.notNull()) - { - bridge->mAvatar->mAttachmentGeometryBytes -= mGeometryBytes; - bridge->mAvatar->mAttachmentGeometryBytes = llmax(bridge->mAvatar->mAttachmentGeometryBytes, U32(0)); - bridge->mAvatar->mAttachmentSurfaceArea -= mSurfaceArea; - bridge->mAvatar->mAttachmentSurfaceArea = llmax(bridge->mAvatar->mAttachmentSurfaceArea, F32(0.f)); - } - } - clearDrawMap(); mVertexBuffer = NULL; - mBufferMap.clear(); + mBufferVec.clear(); sZombieGroups++; mOctreeNode = NULL; } @@ -761,7 +752,7 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c { if (child->getListenerCount() == 0) { - new LLSpatialGroup(child, getSpatialPartition()); + LLPointer tmp = new LLSpatialGroup(child, getSpatialPartition()); } else { @@ -784,7 +775,7 @@ void LLSpatialGroup::destroyGL(bool keep_occlusion) mLastUpdateTime = gFrameTimeSeconds; mVertexBuffer = NULL; - mBufferMap.clear(); + mBufferVec.clear(); clearDrawMap(); @@ -813,17 +804,12 @@ void LLSpatialGroup::destroyGL(bool keep_occlusion) } } - - - - - - //============================================== -LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage) +LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage, LLViewerRegion* regionp) : mRenderByGroup(render_by_group), mBridge(NULL) { + mRegionp = regionp; mPartitionType = LLViewerRegion::PARTITION_NONE; mVertexDataMask = data_mask; mBufferUsage = buffer_usage; @@ -831,7 +817,7 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mSlopRatio = 0.25f; mInfiniteFarClip = FALSE; - new LLSpatialGroup(mOctree, this); + LLPointer tmp = new LLSpatialGroup(mOctree, this); } @@ -1284,6 +1270,7 @@ class LLOctreeDirty : public OctreeTraveler group->destroyGL(); {OctreeGuard guard(group->getOctreeNode()); + if (!mNoRebuild) // Singu note: No need to iterate if not rebuilding... for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); @@ -1314,7 +1301,7 @@ void LLSpatialPartition::restoreGL() void LLSpatialPartition::resetVertexBuffers() { - LLOctreeDirty dirty; + LLOctreeDirty dirty(sTeleportRequested); dirty.traverse(mOctree); } @@ -1325,7 +1312,7 @@ BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, visMaxa.load3(visMax.mV); { - LLFastTimer ftm(FTM_CULL_REBOUND); + LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); } @@ -1353,7 +1340,7 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* result { //BOOL temp = sFreezeState; //sFreezeState = FALSE; - LLFastTimer ftm(FTM_CULL_REBOUND); + LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); //sFreezeState = temp; @@ -1374,7 +1361,7 @@ S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion) ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); #endif { - LLFastTimer ftm(FTM_CULL_REBOUND); + LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); } @@ -1385,19 +1372,19 @@ S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion) if (LLPipeline::sShadowRender) { - LLFastTimer ftm(FTM_FRUSTUM_CULL); + LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); LLOctreeCullShadow culler(&camera); culler.traverse(mOctree); } else if (mInfiniteFarClip || !LLPipeline::sUseFarClip) { - LLFastTimer ftm(FTM_FRUSTUM_CULL); + LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); LLOctreeCullNoFarClip culler(&camera); culler.traverse(mOctree); } else { - LLFastTimer ftm(FTM_FRUSTUM_CULL); + LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); LLOctreeCull culler(&camera); culler.traverse(mOctree); } @@ -1461,7 +1448,7 @@ void pushVerts(LLVolume* volume) for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) { const LLVolumeFace& face = volume->getVolumeFace(i); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mNumVertices, face.mPositions, NULL, face.mNumIndices, face.mIndices); } } @@ -1488,9 +1475,9 @@ void pushBufferVerts(LLSpatialGroup* group, U32 mask, bool push_alpha = true) pushBufferVerts(group->mVertexBuffer, mask); } - for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) + for (LLSpatialGroup::buffer_vec_t::iterator i = group->mBufferVec.begin(); i != group->mBufferVec.end(); ++i) { - for (LLSpatialGroup::buffer_texture_map_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + for (LLSpatialGroup::buffer_texture_vec_t::iterator j = i->second.begin(); j != i->second.end(); ++j) { for (LLSpatialGroup::buffer_list_t::iterator k = j->second.begin(); k != j->second.end(); ++k) { @@ -1563,17 +1550,15 @@ void renderOctree(LLSpatialGroup* group) if (group->mBufferUsage != GL_STATIC_DRAW_ARB) { LLGLDepthTest gl_depth(FALSE, FALSE); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); gGL.diffuseColor4f(1,0,0,group->mBuilt); - gGL.flush(); - glLineWidth(5.f); + gGL.setLineWidth(5.f); const LLVector4a* bounds = group->getObjectBounds(); drawBoxOutline(bounds[0], bounds[1]); - gGL.flush(); - glLineWidth(1.f); - gGL.flush(); + gGL.setLineWidth(1.f); + OctreeGuard guard(group->getOctreeNode()); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { @@ -1619,7 +1604,7 @@ void renderOctree(LLSpatialGroup* group) gGL.popMatrix(); } } - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); gGL.diffuseColor4f(1,1,1,1); } } @@ -1639,10 +1624,10 @@ void renderOctree(LLSpatialGroup* group) gGL.diffuseColor4fv(col.mV); LLVector4a fudge; fudge.splat(0.001f); - const LLVector4a* bounds = group->getObjectBounds(); - LLVector4a size = bounds[1]; - size.mul(1.01f); - size.add(fudge); + //const LLVector4a* bounds = group->getObjectBounds(); + //LLVector4a size = bounds[1]; + //size.mul(1.01f); + //size.add(fudge);*/ //{ // LLGLDepthTest depth(GL_TRUE, GL_FALSE); @@ -1690,10 +1675,10 @@ void renderOctree(LLSpatialGroup* group) void renderVisibility(LLSpatialGroup* group, LLCamera* camera) { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.setSceneBlendType(LLRender::BT_ALPHA); - LLGLEnable cull(GL_CULL_FACE); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + LLGLEnable cull; + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && !group->isEmpty(); @@ -1714,7 +1699,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); if (render_objects) { @@ -1728,11 +1713,11 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) gGL.diffuseColor4f(1.0f, 0.f, 0.f, 0.5f); glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_box_fan_indices(camera, group->mBounds[0])); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); gGL.diffuseColor4f(1.0f, 1.f, 1.f, 1.0f); glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_box_fan_indices(camera, group->mBounds[0])); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); }*/ } } @@ -1759,7 +1744,7 @@ void renderUpdateType(LLDrawable* drawablep) { return; } - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; switch (vobj->getLastUpdateType()) { case OUT_FULL: @@ -1803,7 +1788,7 @@ void renderComplexityDisplay(LLDrawable* drawablep) return; } - LLVOVolume *voVol = dynamic_cast(vobj); + LLVOVolume *voVol = vobj->asVolume();; if (!voVol) { @@ -1852,7 +1837,7 @@ void renderComplexityDisplay(LLDrawable* drawablep) // cap cost ratio at 1.0f in case cost_max is at a low threshold cost_ratio = cost_ratio > 1.0f ? 1.0f : cost_ratio; - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; LLColor4 color; const LLColor4 color_min = gSavedSettings.getColor4("RenderComplexityColorMin"); @@ -1946,7 +1931,28 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) gGL.diffuseColor4f(0,0.5f,0,1); break; default: - gGL.diffuseColor4f(1,0,1,1); + LLControlAvatar *cav = dynamic_cast(drawable->getVObj()->asAvatar()); + if (cav) + { + bool has_pos_constraint = (cav->mPositionConstraintFixup != LLVector3()); + bool has_scale_constraint = (cav->mScaleConstraintFixup != 1.0f); + if (has_pos_constraint || has_scale_constraint) + { + gGL.diffuseColor4f(1,0,0,1); + } + else + { + gGL.diffuseColor4f(0,1,0.5,1); + } + } + else if (drawable->getVObj()->asAvatar()) + { + gGL.diffuseColor4f(.5, 0, 1, 1); + } + else + { + gGL.diffuseColor4f(1,0,1,1); // magenta + } break; } } @@ -1959,7 +1965,9 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) const LLVector4a* ext; LLVector4a pos, size; - if (drawable->getVOVolume()) + static LLCachedControl sh_override_rigged_bounds("SHOverrideRiggedBounds", true); + LLVOVolume* volume = drawable->getVOVolume(); + if (volume && (!sh_override_rigged_bounds || !volume->isAttachment() || !(drawable->isState(LLDrawable::RIGGED) || volume->isRiggedMesh()))) { //render face bounding boxes for (S32 i = 0; i < drawable->getNumFaces(); i++) @@ -1990,13 +1998,11 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) LLViewerObject* vobj = drawable->getVObj(); if (vobj && vobj->onActiveList()) { - gGL.flush(); - glLineWidth(llmax(4.f*sinf(gFrameTimeSeconds*2.f)+1.f, 1.f)); + gGL.setLineWidth(llmax(4.f*sinf(gFrameTimeSeconds*2.f)+1.f, 1.f)); //glLineWidth(4.f*(sinf(gFrameTimeSeconds*2.f)*0.25f+0.75f)); stop_glerror(); drawBoxOutline(pos,size); - gGL.flush(); - glLineWidth(1.f); + gGL.setLineWidth(1.f); } else { @@ -2109,14 +2115,14 @@ void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColo return; gGL.diffuseColor4fv(color.mV); LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); - LLGLEnable offset(GL_POLYGON_OFFSET_LINE); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glPolygonOffset(3.f, 3.f); - glLineWidth(3.f); + LLGLEnable offset; + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); + gGL.setPolygonOffset(3.f, 3.f); + gGL.setLineWidth(3.f); gGL.diffuseColor4fv(line_color.mV); LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); - glLineWidth(1.f); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setLineWidth(1.f); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); } void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) @@ -2199,10 +2205,10 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) gGL.diffuseColor4fv(color.mV); LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); gGL.diffuseColor4fv(line_color.mV); LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); } else { //no mesh or decomposition, render base hull @@ -2323,18 +2329,18 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) { //render hull - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); gGL.diffuseColor4fv(line_color.mV); LLVertexBuffer::unbind(); llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); gGL.diffuseColor4fv(color.mV); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); } else @@ -2390,13 +2396,13 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) S32 detail = get_physics_detail(volume_params, volume->getScale()); LLVolume* phys_volume = LLPrimitive::getVolumeManager()->refVolume(volume_params, detail); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); gGL.diffuseColor4fv(line_color.mV); pushVerts(phys_volume); gGL.diffuseColor4fv(color.mV); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); pushVerts(phys_volume); LLPrimitive::getVolumeManager()->unrefVolume(phys_volume); } @@ -2409,13 +2415,13 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) if (phys_volume->mHullPoints && phys_volume->mHullIndices) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); gGL.diffuseColor4fv(line_color.mV); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); } else { @@ -2494,14 +2500,14 @@ void renderPhysicsShapes(LLSpatialGroup* group) LLVertexBuffer* buff = face->getVertexBuffer(); if (buff) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); buff->setBuffer(LLVertexBuffer::MAP_VERTEX); gGL.diffuseColor3f(0.2f, 0.5f, 0.3f); buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); gGL.diffuseColor3f(0.2f, 1.f, 0.3f); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); } } @@ -2525,7 +2531,7 @@ void renderTexturePriority(LLDrawable* drawable) LLVector4 boost_cold(0,0,0,0); LLVector4 boost_hot(0,1,0,1); - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; //LLViewerTexture* imagep = facep->getTexture(); //if (imagep) @@ -2599,22 +2605,22 @@ void renderTextureAnim(LLDrawInfo* params) return; } - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.diffuseColor4f(1,1,0,0.5f); pushVerts(params, LLVertexBuffer::MAP_VERTEX); } void renderBatchSize(LLDrawInfo* params) { - LLGLEnable offset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.f, 1.f); + LLGLEnable offset; + gGL.setPolygonOffset(-1.f, 1.f); gGL.diffuseColor4ubv((GLubyte*) &(params->mDebugColor)); pushVerts(params, LLVertexBuffer::MAP_VERTEX); } void renderShadowFrusta(LLDrawInfo* params) { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.setSceneBlendType(LLRender::BT_ADD); LLVector4a center; @@ -2658,7 +2664,7 @@ void renderLights(LLDrawable* drawablep) if (drawablep->getNumFaces()) { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.diffuseColor4f(0,1,1,0.5f); for (S32 i = 0; i < drawablep->getNumFaces(); i++) @@ -2741,8 +2747,7 @@ class LLRenderOctreeRaycast : public LLOctreeTriangleRayIntersect if (i == 1) { - gGL.flush(); - glLineWidth(3.f); + gGL.setLineWidth(3.f); } gGL.begin(LLRender::TRIANGLES); @@ -2760,8 +2765,7 @@ class LLRenderOctreeRaycast : public LLOctreeTriangleRayIntersect if (i == 1) { - gGL.flush(); - glLineWidth(1.f); + gGL.setLineWidth(1.f); } } } @@ -2771,14 +2775,14 @@ void renderRaycast(LLDrawable* drawablep) { if (drawablep->getNumFaces()) { - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.diffuseColor4f(0,1,1,0.5f); if (drawablep->getVOVolume()) { - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + //gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); //pushVerts(drawablep->getFace(gDebugRaycastFaceHit), LLVertexBuffer::MAP_VERTEX); - //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + //gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); LLVOVolume* vobj = drawablep->getVOVolume(); LLVolume* volume = vobj->getVolume(); @@ -2824,12 +2828,12 @@ void renderRaycast(LLDrawable* drawablep) dir.setSub(end, start); gGL.flush(); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); { //render face positions gGL.diffuseColor4f(0,1,1,0.5f); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mNumVertices, face.mPositions, NULL, face.mNumIndices, face.mIndices); } if (!volume->isUnique()) @@ -2847,7 +2851,7 @@ void renderRaycast(LLDrawable* drawablep) } gGL.popMatrix(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); } } } @@ -2917,6 +2921,10 @@ void renderAvatarCollisionVolumes(LLVOAvatar* avatar) avatar->renderCollisionVolumes(); } +void renderAvatarBones(LLVOAvatar* avatar) +{ + avatar->renderBones(); +} void renderAgentTarget(LLVOAvatar* avatar) { // render these for self only (why, i don't know) @@ -2990,7 +2998,7 @@ class LLOctreeRenderNonOccluded : public OctreeTraveler return; } - LLGLDisable stencil(GL_STENCIL_TEST); + LLGLDisable stencil; group->rebuildGeom(); group->rebuildMesh(); @@ -3077,7 +3085,7 @@ class LLOctreeRenderNonOccluded : public OctreeTraveler if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_JOINTS)) { - avatar->renderJoints(); + renderAvatarBones(avatar); } if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AGENT_TARGET)) @@ -3305,13 +3313,11 @@ void LLSpatialPartition::renderPhysicsShapes() camera = NULL; } - gGL.flush(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - glLineWidth(3.f); + gGL.setLineWidth(3.f); LLOctreeRenderPhysicsShapes render_physics(camera); render_physics.traverse(mOctree); - gGL.flush(); - glLineWidth(1.f); + gGL.setLineWidth(1.f); } void LLSpatialPartition::renderDebug() @@ -3349,11 +3355,12 @@ void LLSpatialPartition::renderDebug() sCurMaxTexPriority = 0.f; } - LLGLDisable cullface(GL_CULL_FACE); - LLGLEnable blend(GL_BLEND); + LLGLDisable cullface; + LLGLEnable blend; gGL.setSceneBlendType(LLRender::BT_ALPHA); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gPipeline.disableLights(); + LLGLState light_state; + gPipeline.disableLights(light_state); LLSpatialBridge* bridge = asBridge(); LLCamera* camera = LLViewerCamera::getInstance(); @@ -3414,8 +3421,9 @@ class LLOctreeIntersect : public LLOctreeTraveler LLVector4a *mTangent; LLDrawable* mHit; BOOL mPickTransparent; + BOOL mPickRigged; - LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, + LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) : mStart(start), mEnd(end), @@ -3425,7 +3433,8 @@ class LLOctreeIntersect : public LLOctreeTraveler mNormal(normal), mTangent(tangent), mHit(NULL), - mPickTransparent(pick_transparent) + mPickTransparent(pick_transparent), + mPickRigged(pick_rigged) { } @@ -3507,9 +3516,9 @@ class LLOctreeIntersect : public LLOctreeTraveler if (vobj->isAvatar()) { LLVOAvatar* avatar = (LLVOAvatar*) vobj; - if (gFloaterTools->getVisible() || LLFloaterInspect::findInstance()) + if (mPickRigged) { - LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mTangent); + LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent); if (hit) { mEnd = intersection; @@ -3529,7 +3538,7 @@ class LLOctreeIntersect : public LLOctreeTraveler } } - if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mTangent)) + if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent)) { mEnd = intersection; // shorten ray so we only find CLOSER hits if (mIntersection) @@ -3548,6 +3557,7 @@ class LLOctreeIntersect : public LLOctreeTraveler LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, + BOOL pick_rigged, S32* face_hit, // return the face hit LLVector4a* intersection, // return the intersection point LLVector2* tex_coord, // return the texture coordinates of the intersection point @@ -3556,7 +3566,7 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, co ) { - LLOctreeIntersect intersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, tangent); + LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, face_hit, intersection, tex_coord, normal, tangent); LLDrawable* drawable = intersect.check(mOctree); return drawable; @@ -3576,6 +3586,7 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, mOffset(offset), mFullbright(fullbright), mBump(bump), + mShiny(0), mParticle(particle), mPartSize(part_size), mVSize(0.f), diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 97a4f67f1f..c89126432a 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -116,7 +116,7 @@ class LLDrawInfo : public LLRefCount BOOL mParticle; F32 mPartSize; F32 mVSize; - LLSpatialGroup* mGroup; + LLPointer mGroup; LL_ALIGN_16(LLFace* mFace); //associated face F32 mDistance; U32 mDrawMode; @@ -127,9 +127,7 @@ class LLDrawInfo : public LLRefCount U32 mBlendFuncDst; BOOL mHasGlow; LLPointer mSpecularMap; - const LLMatrix4* mSpecularMapMatrix; LLPointer mNormalMap; - const LLMatrix4* mNormalMapMatrix; LLVector4 mSpecColor; // XYZ = Specular RGB, W = Specular Exponent F32 mEnvIntensity; F32 mAlphaMaskCutoff; @@ -243,8 +241,8 @@ class LLSpatialGroup : public LLOcclusionCullingGroup typedef std::vector > drawmap_elem_t; typedef std::map draw_map_t; typedef std::vector > buffer_list_t; - typedef std::map buffer_texture_map_t; - typedef std::map buffer_map_t; + typedef std::vector > buffer_texture_vec_t; + typedef std::vector > buffer_vec_t; @@ -318,13 +316,13 @@ class LLSpatialGroup : public LLOcclusionCullingGroup void drawObjectBox(LLColor4 col); - LLSpatialPartition* getSpatialPartition() {return (LLSpatialPartition*)mSpatialPartition;} + LLSpatialPartition* getSpatialPartition() const {return mSpatialPartition;} //LISTENER FUNCTIONS - virtual void handleInsertion(const TreeNode* node, LLViewerOctreeEntry* face); - virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* face); - virtual void handleDestruction(const TreeNode* node); - virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); + void handleInsertion(const TreeNode* node, LLViewerOctreeEntry* face) final override; + void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* face) final override; + void handleDestruction(const TreeNode* node) final override; + void handleChildAddition(const OctreeNode* parent, OctreeNode* child) final override; LL_ALIGN_16(LLVector4a mViewAngle); @@ -339,7 +337,7 @@ class LLSpatialGroup : public LLOcclusionCullingGroup public: bridge_list_t mBridgeList; - buffer_map_t mBufferMap; //used by volume buffers to store unique buffers per texture + buffer_vec_t mBufferVec; //used by volume buffers to store unique buffers per texture U32 mGeometryBytes; //used by volumes to track how many bytes of geometry data are in this node F32 mSurfaceArea; //used by volumes to track estimated surface area of geometry in this node @@ -386,7 +384,7 @@ class LLSpatialPartition: public LLViewerOctreePartition, public LLGeometryManag { public: //static BOOL sFreezeState; //if true, no spatialgroup state updates will be made - LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage); + LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage, LLViewerRegion* regionp); virtual ~LLSpatialPartition(); LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE); @@ -394,6 +392,7 @@ class LLSpatialPartition: public LLViewerOctreePartition, public LLGeometryManag LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, + BOOL pick_rigged, S32* face_hit, // return the face hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point @@ -440,6 +439,8 @@ class LLSpatialPartition: public LLViewerOctreePartition, public LLGeometryManag U32 mVertexDataMask; F32 mSlopRatio; //percentage distance must change before drawables receive LOD update (default is 0.25); BOOL mDepthMask; //if TRUE, objects in this partition will be written to depth during alpha rendering + + static BOOL sTeleportRequested; //started to issue a teleport request }; // class for creating bridges between spatial partitions @@ -451,7 +452,7 @@ class LLSpatialBridge : public LLDrawable, public LLSpatialPartition public: typedef std::vector > bridge_vector_t; - LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask); + LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask, LLViewerRegion* regionp); void destroyTree(); @@ -470,7 +471,6 @@ class LLSpatialBridge : public LLDrawable, public LLSpatialPartition virtual LLCamera transformCamera(LLCamera& camera); LLDrawable* mDrawable; - LLPointer mAvatar; }; class LLCullResult @@ -478,7 +478,7 @@ class LLCullResult public: LLCullResult() {} - typedef std::vector sg_list_t; + typedef std::vector > sg_list_t; typedef std::vector drawable_list_t; typedef std::vector bridge_list_t; typedef std::vector drawinfo_list_t; @@ -540,7 +540,7 @@ class LLCullResult class LLWaterPartition : public LLSpatialPartition { public: - LLWaterPartition(); + LLWaterPartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group) { } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } }; @@ -549,14 +549,14 @@ class LLWaterPartition : public LLSpatialPartition class LLVoidWaterPartition : public LLWaterPartition { public: - LLVoidWaterPartition(); + LLVoidWaterPartition(LLViewerRegion* regionp); }; //spatial partition for terrain (impelmented in LLVOSurfacePatch.cpp) class LLTerrainPartition : public LLSpatialPartition { public: - LLTerrainPartition(); + LLTerrainPartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group); virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage); }; @@ -565,7 +565,7 @@ class LLTerrainPartition : public LLSpatialPartition class LLTreePartition : public LLSpatialPartition { public: - LLTreePartition(); + LLTreePartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group) { } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } @@ -575,7 +575,7 @@ class LLTreePartition : public LLSpatialPartition class LLParticlePartition : public LLSpatialPartition { public: - LLParticlePartition(); + LLParticlePartition(LLViewerRegion* regionp); virtual void rebuildGeom(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); @@ -587,14 +587,14 @@ class LLParticlePartition : public LLSpatialPartition class LLHUDParticlePartition : public LLParticlePartition { public: - LLHUDParticlePartition(); + LLHUDParticlePartition(LLViewerRegion* regionp); }; //spatial partition for grass (implemented in LLVOGrass.cpp) class LLGrassPartition : public LLSpatialPartition { public: - LLGrassPartition(); + LLGrassPartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group); virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); protected: @@ -606,7 +606,7 @@ class LLGrassPartition : public LLSpatialPartition class LLCloudPartition : public LLParticlePartition { public: - LLCloudPartition(); + LLCloudPartition(LLViewerRegion* regionp); }; #endif @@ -621,18 +621,32 @@ class LLVolumeGeometryManager: public LLGeometryManager DISTANCE_SORT } eSortType; + LLVolumeGeometryManager(); + virtual ~LLVolumeGeometryManager(); virtual void rebuildGeom(LLSpatialGroup* group); virtual void rebuildMesh(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); void genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE); void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type); +private: + void allocateFaces(U32 pMaxFaceCount); + void freeFaces(); + + static int32_t sInstanceCount; + static LLFace** sFullbrightFaces; + static LLFace** sBumpFaces; + static LLFace** sSimpleFaces; + static LLFace** sNormFaces; + static LLFace** sSpecFaces; + static LLFace** sNormSpecFaces; + static LLFace** sAlphaFaces; }; //spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp) class LLVolumePartition : public LLSpatialPartition, public LLVolumeGeometryManager { public: - LLVolumePartition(); + LLVolumePartition(LLViewerRegion* regionp); virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); } @@ -643,7 +657,7 @@ class LLVolumePartition : public LLSpatialPartition, public LLVolumeGeometryMana class LLVolumeBridge : public LLSpatialBridge, public LLVolumeGeometryManager { public: - LLVolumeBridge(LLDrawable* drawable); + LLVolumeBridge(LLDrawable* drawable, LLViewerRegion* regionp); virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); } @@ -653,13 +667,13 @@ class LLVolumeBridge : public LLSpatialBridge, public LLVolumeGeometryManager class LLAttachmentBridge : public LLVolumeBridge { public: - LLAttachmentBridge(LLDrawable* drawable); + LLAttachmentBridge(LLDrawable* drawable, LLViewerRegion* regionp); }; class LLHUDBridge : public LLVolumeBridge { public: - LLHUDBridge(LLDrawable* drawablep); + LLHUDBridge(LLDrawable* drawablep, LLViewerRegion* regionp); virtual void shiftPos(const LLVector4a& vec); virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); }; @@ -668,7 +682,7 @@ class LLHUDBridge : public LLVolumeBridge class LLBridgePartition : public LLSpatialPartition { public: - LLBridgePartition(); + LLBridgePartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group) { } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } }; @@ -677,13 +691,13 @@ class LLBridgePartition : public LLSpatialPartition class LLAttachmentPartition : public LLBridgePartition { public: - LLAttachmentPartition(); + LLAttachmentPartition(LLViewerRegion* regionp); }; class LLHUDPartition : public LLBridgePartition { public: - LLHUDPartition(); + LLHUDPartition(LLViewerRegion* regionp); virtual void shift(const LLVector4a &offset) { } //HUD objects don't shift with region crossing. That would be silly. }; diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 254aa72d88..2eb588e7de 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -42,38 +42,57 @@ #include "rlvhandler.h" -#include - -extern AIHTTPTimeoutPolicy moderationResponder_timeout; - const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f); const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f); -LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerType type) : - mStatus(LLSpeaker::STATUS_TEXT_ONLY), +LLSpeaker::LLSpeaker(const speaker_entry_t& entry) : + mID(entry.id), + mStatus(entry.status), + mType(entry.type), + mIsModerator(entry.moderator != boost::none && *entry.moderator), + mModeratorMutedText(entry.moderator_muted_text != boost::none && *entry.moderator_muted_text), + mModeratorMutedVoice(FALSE), mLastSpokeTime(0.f), mSpeechVolume(0.f), mHasSpoken(FALSE), mHasLeftCurrentCall(FALSE), mDotColor(LLColor4::white), - mID(id), mTyping(FALSE), mSortIndex(0), - mType(type), - mIsModerator(FALSE), - mModeratorMutedVoice(FALSE), - mModeratorMutedText(FALSE) + mDisplayName(entry.name), + mNeedsResort(true) { - if (name.empty() && type == SPEAKER_AGENT) + if (mType == SPEAKER_AGENT) { lookupName(); } - else +} + +void LLSpeaker::update(const speaker_entry_t& entry) +{ + // keep highest priority status (lowest value) instead of overriding current value + setStatus(llmin(mStatus, entry.status)); + if (entry.moderator != boost::none) { - mDisplayName = name; + mIsModerator = *entry.moderator; + } + if (entry.moderator_muted_text != boost::none) + { + mModeratorMutedText = *entry.moderator_muted_text; + }; + + // RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id + // we need to override speakers that we think are objects when we find out they are really + // residents + if (entry.type == LLSpeaker::SPEAKER_AGENT) + { + mType = LLSpeaker::SPEAKER_AGENT; + lookupName(); } -} + if (mDisplayName.empty()) + setName(entry.name); +} void LLSpeaker::lookupName() { @@ -81,7 +100,7 @@ void LLSpeaker::lookupName() { // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-1.0.0g if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) && gAgentID != mID) - mDisplayName = RlvStrings::getAnonym(mDisplayName); + setName(RlvStrings::getAnonym(mDisplayName)); else // [/RLVa:KB] LLAvatarNameCache::get(mID, boost::bind(&LLSpeaker::onNameCache, this, _2)); @@ -92,9 +111,9 @@ void LLSpeaker::onNameCache(const LLAvatarName& full_name) { static const LLCachedControl name_system("SpeakerNameSystem"); if (!name_system) - mDisplayName = gCacheName->cleanFullName(full_name.getLegacyName()); + setName(gCacheName->cleanFullName(full_name.getLegacyName())); else - mDisplayName = full_name.getNSName(name_system); + setName(full_name.getNSName(name_system)); } bool LLSpeaker::isInVoiceChannel() @@ -204,7 +223,7 @@ BOOL LLSpeakerActionTimer::tick() void LLSpeakerActionTimer::unset() { - mActionCallback = 0; + mActionCallback = nullptr; } LLSpeakersDelayActionsStorage::LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay) @@ -221,7 +240,7 @@ LLSpeakersDelayActionsStorage::~LLSpeakersDelayActionsStorage() void LLSpeakersDelayActionsStorage::setActionTimer(const LLUUID& speaker_id) { bool not_found = true; - if (mActionTimersMap.size() > 0) + if (!mActionTimersMap.empty()) { not_found = mActionTimersMap.find(speaker_id) == mActionTimersMap.end(); } @@ -239,7 +258,7 @@ void LLSpeakersDelayActionsStorage::setActionTimer(const LLUUID& speaker_id) void LLSpeakersDelayActionsStorage::unsetActionTimer(const LLUUID& speaker_id) { - if (mActionTimersMap.size() == 0) return; + if (mActionTimersMap.empty()) return; LLSpeakerActionTimer::action_timer_iter_t it_speaker = mActionTimersMap.find(speaker_id); @@ -289,9 +308,10 @@ class ModerationResponder : public LLHTTPClient::ResponderIgnoreBody mSessionID = session_id; } - virtual void httpFailure(void) +protected: + virtual void httpFailure() { - LL_WARNS() << mStatus << ": " << mReason << LL_ENDL; + LL_WARNS() << dumpResponse() << LL_ENDL; if ( gIMMgr ) { @@ -314,7 +334,6 @@ class ModerationResponder : public LLHTTPClient::ResponderIgnoreBody } } } - /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return moderationResponder_timeout; } /*virtual*/ char const* getName(void) const { return "ModerationResponder"; } private: @@ -342,47 +361,42 @@ LLSpeakerMgr::~LLSpeakerMgr() delete mSpeakerDelayRemover; } -LLPointer LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type) +void LLSpeakerMgr::setSpeakers(const std::vector& speakers) +{ + if (!speakers.empty()) + { + fireEvent(new LLOldEvents::LLEvent(this), "batch_begin"); + for (auto entry : speakers) + { + setSpeaker(entry); + } + fireEvent(new LLOldEvents::LLEvent(this), "batch_end"); + } +} + +LLPointer LLSpeakerMgr::setSpeaker(const speaker_entry_t& entry) { LLUUID session_id = getSessionID(); + const LLUUID& id = entry.id; if (id.isNull() || (id == session_id)) { return NULL; } LLPointer speakerp; - if (mSpeakers.find(id) == mSpeakers.end()) + auto it = mSpeakers.find(id); + if (it == mSpeakers.end() || it->second.isNull()) { - speakerp = new LLSpeaker(id, name, type); - speakerp->mStatus = status; - mSpeakers.insert(std::make_pair(speakerp->mID, speakerp)); - mSpeakersSorted.push_back(speakerp); - LL_DEBUGS("Speakers") << "Added speaker " << id << LL_ENDL; - fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add"); + mSpeakersSorted.emplace_back(new LLSpeaker(entry)); + mSpeakers.emplace(id, mSpeakersSorted.back()); + fireEvent(new LLSpeakerListChangeEvent(this, id), "add"); } else { - speakerp = findSpeaker(id); - if (speakerp.notNull()) - { - // keep highest priority status (lowest value) instead of overriding current value - speakerp->mStatus = llmin(speakerp->mStatus, status); - // RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id - // we need to override speakers that we think are objects when we find out they are really - // residents - if (type == LLSpeaker::SPEAKER_AGENT) - { - speakerp->mType = LLSpeaker::SPEAKER_AGENT; - speakerp->lookupName(); - } - } - else - { - LL_WARNS("Speakers") << "Speaker " << id << " not found" << LL_ENDL; - } + it->second->update(entry); } - mSpeakerDelayRemover->unsetActionTimer(speakerp->mID); + mSpeakerDelayRemover->unsetActionTimer(entry.id); return speakerp; } @@ -420,8 +434,8 @@ void LLSpeakerMgr::update(BOOL resort_ok) return; } - LLColor4 speaking_color = gSavedSettings.getColor4("SpeakingColor"); - LLColor4 overdriven_color = gSavedSettings.getColor4("OverdrivenColor"); + static const LLCachedControl speaking_color(gSavedSettings, "SpeakingColor"); + static const LLCachedControl overdriven_color(gSavedSettings, "OverdrivenColor"); if(resort_ok) // only allow list changes when user is not interacting with it { @@ -430,15 +444,16 @@ void LLSpeakerMgr::update(BOOL resort_ok) // update status of all current speakers BOOL voice_channel_active = (!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()); - for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); speaker_it++) + bool re_sort = false; + for (auto& speaker : mSpeakers) { - LLUUID speaker_id = speaker_it->first; - LLSpeaker* speakerp = speaker_it->second; + LLUUID speaker_id = speaker.first; + LLSpeaker* speakerp = speaker.second; if (voice_channel_active && LLVoiceClient::getInstance()->getVoiceEnabled(speaker_id)) { speakerp->mSpeechVolume = LLVoiceClient::getInstance()->getCurrentPower(speaker_id); - BOOL moderator_muted_voice = LLVoiceClient::getInstance()->getIsModeratorMuted(speaker_id); + bool moderator_muted_voice = LLVoiceClient::getInstance()->getIsModeratorMuted(speaker_id); if (moderator_muted_voice != speakerp->mModeratorMutedVoice) { speakerp->mModeratorMutedVoice = moderator_muted_voice; @@ -448,18 +463,18 @@ void LLSpeakerMgr::update(BOOL resort_ok) if (LLVoiceClient::getInstance()->getOnMuteList(speaker_id) || speakerp->mModeratorMutedVoice) { - speakerp->mStatus = LLSpeaker::STATUS_MUTED; + speakerp->setStatus(LLSpeaker::STATUS_MUTED); } else if (LLVoiceClient::getInstance()->getIsSpeaking(speaker_id)) { // reset inactivity expiration if (speakerp->mStatus != LLSpeaker::STATUS_SPEAKING) { - speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32(); + speakerp->setSpokenTime(mSpeechTimer.getElapsedTimeF32()); speakerp->mHasSpoken = TRUE; fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker"); } - speakerp->mStatus = LLSpeaker::STATUS_SPEAKING; + speakerp->setStatus(LLSpeaker::STATUS_SPEAKING); // interpolate between active color and full speaking color based on power of speech output speakerp->mDotColor = speaking_color; if (speakerp->mSpeechVolume > LLVoiceClient::OVERDRIVEN_POWER_LEVEL) @@ -475,12 +490,12 @@ void LLSpeakerMgr::update(BOOL resort_ok) if (speakerp->mHasSpoken) { // have spoken once, not currently speaking - speakerp->mStatus = LLSpeaker::STATUS_HAS_SPOKEN; + speakerp->setStatus(LLSpeaker::STATUS_HAS_SPOKEN); } else { // default state for being in voice channel - speakerp->mStatus = LLSpeaker::STATUS_VOICE_ACTIVE; + speakerp->setStatus(LLSpeaker::STATUS_VOICE_ACTIVE); } } } @@ -494,39 +509,49 @@ void LLSpeakerMgr::update(BOOL resort_ok) } else { - speakerp->mStatus = LLSpeaker::STATUS_TEXT_ONLY; + speakerp->setStatus(LLSpeaker::STATUS_TEXT_ONLY); speakerp->mSpeechVolume = 0.f; speakerp->mDotColor = ACTIVE_COLOR; } } + if (speakerp->mNeedsResort) + { + re_sort = true; + speakerp->mNeedsResort = false; + } } - if(resort_ok) // only allow list changes when user is not interacting with it + if (resort_ok && re_sort) // only allow list changes when user is not interacting with it { // sort by status then time last spoken std::sort(mSpeakersSorted.begin(), mSpeakersSorted.end(), LLSortRecentSpeakers()); - } - // for recent speakers who are not currently speaking, show "recent" color dot for most recent - // fading to "active" color + // for recent speakers who are not currently speaking, show "recent" color dot for most recent + // fading to "active" color - S32 recent_speaker_count = 0; - S32 sort_index = 0; - speaker_list_t::iterator sorted_speaker_it; - for(sorted_speaker_it = mSpeakersSorted.begin(); - sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it) - { - LLPointer speakerp = *sorted_speaker_it; + bool index_changed = false; + S32 recent_speaker_count = 0; + S32 sort_index = 0; + for (auto speakerp : mSpeakersSorted) + { + // color code recent speakers who are not currently speaking + if (speakerp->mStatus == LLSpeaker::STATUS_HAS_SPOKEN) + { + speakerp->mDotColor = lerp(speaking_color, ACTIVE_COLOR, clamp_rescale((F32)recent_speaker_count, -2.f, 3.f, 0.f, 1.f)); + recent_speaker_count++; + } - // color code recent speakers who are not currently speaking - if (speakerp->mStatus == LLSpeaker::STATUS_HAS_SPOKEN) + // stuff sort ordinal into speaker so the ui can sort by this value + if (speakerp->mSortIndex != sort_index++) + { + speakerp->mSortIndex = sort_index-1; + index_changed = true; + } + } + if (index_changed) { - speakerp->mDotColor = lerp(speaking_color, ACTIVE_COLOR, clamp_rescale((F32)recent_speaker_count, -2.f, 3.f, 0.f, 1.f)); - recent_speaker_count++; + fireEvent(new LLOldEvents::LLEvent(this), "update_sorting"); } - - // stuff sort ordinal into speaker so the ui can sort by this value - speakerp->mSortIndex = sort_index++; } } @@ -535,21 +560,26 @@ void LLSpeakerMgr::updateSpeakerList() // Are we bound to the currently active voice channel? if ((!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive())) { - std::set participants; + uuid_set_t participants; LLVoiceClient::getInstance()->getParticipantList(participants); // If we are, add all voice client participants to our list of known speakers - for (std::set::iterator participant_it = participants.begin(); participant_it != participants.end(); ++participant_it) + std::vector speakers; + speakers.reserve(participants.size()); + for (auto participant : participants) { - setSpeaker(*participant_it, - LLVoiceClient::getInstance()->getDisplayName(*participant_it), - LLSpeaker::STATUS_VOICE_ACTIVE, - (LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it)?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL)); + speakers.emplace_back(participant, + (LLVoiceClient::getInstance()->isParticipantAvatar(participant) ? LLSpeaker::SPEAKER_AGENT : LLSpeaker::SPEAKER_EXTERNAL), + LLSpeaker::STATUS_VOICE_ACTIVE, + boost::none, + boost::none, + LLVoiceClient::getInstance()->getDisplayName(participant)); } + setSpeakers(speakers); } else { // If not, check if the list is empty, except if it's Nearby Chat (session_id NULL). - LLUUID session_id = getSessionID(); + LLUUID const& session_id = getSessionID(); if (!session_id.isNull() && !mSpeakerListUpdated) { // If the list is empty, we update it with whatever we have locally so that it doesn't stay empty too long. @@ -573,10 +603,11 @@ void LLSpeakerMgr::updateSpeakerList() } else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) { + std::vector speakers; + speakers.reserve(gdatap->mMembers.size()); + // Add group members when we get the complete list (note: can take a while before we get that list) LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin(); - const S32 load_group_max_members = gSavedSettings.getS32("ChatLoadGroupMaxMembers"); - S32 updated = 0; while (member_it != gdatap->mMembers.end()) { LLGroupMemberData* member = member_it->second; @@ -585,34 +616,32 @@ void LLSpeakerMgr::updateSpeakerList() const std::string& localized_online(); if ((member->getOnlineStatus() == localized_online()) && (mSpeakers.find(id) == mSpeakers.end())) { - LLPointer speakerp = setSpeaker(id, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); - speakerp->mIsModerator = ((member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR); - updated++; + speakers.emplace_back( + id, + LLSpeaker::SPEAKER_AGENT, + LLSpeaker::STATUS_VOICE_ACTIVE, + (member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR); } ++member_it; - // Limit the number of "manually updated" participants to a reasonable number to avoid severe fps drop - // *TODO : solve the perf issue of having several hundreds of widgets in the conversation list - if (updated >= load_group_max_members) - break; } + setSpeakers(speakers); mSpeakerListUpdated = true; } } - /* Singu TODO: LLIMModel::LLIMSession - else if (mSpeakers.size() == 0) + else if (floater && mSpeakers.empty()) { // For all other session type (ad-hoc, P2P, avaline), we use the initial participants targets list - for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) + for (const auto& target_id : floater->mInitialTargetIDs) { // Add buddies if they are on line, add any other avatar. - if (!LLAvatarTracker::instance().isBuddy(*it) || LLAvatarTracker::instance().isBuddyOnline(*it)) + if (!LLAvatarTracker::instance().isBuddy(target_id) || LLAvatarTracker::instance().isBuddyOnline( + target_id)) { - setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + setSpeaker({target_id, LLSpeaker::SPEAKER_AGENT, LLSpeaker::STATUS_VOICE_ACTIVE }); } } mSpeakerListUpdated = true; } - */ else { // The list has been updated the normal way (i.e. by a ChatterBoxSessionAgentListUpdates received from the server) @@ -621,14 +650,17 @@ void LLSpeakerMgr::updateSpeakerList() } } // Always add the current agent (it has to be there...). Will do nothing if already there. - setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + setSpeaker({ gAgentID, LLSpeaker::SPEAKER_AGENT, LLSpeaker::STATUS_VOICE_ACTIVE }); } -void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) +void LLSpeakerMgr::setSpeakerNotInChannel(LLPointer speakerp) { - speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; - speakerp->mDotColor = INACTIVE_COLOR; - mSpeakerDelayRemover->setActionTimer(speakerp->mID); + if (speakerp.notNull()) + { + speakerp->setStatus(LLSpeaker::STATUS_NOT_IN_CHANNEL); + speakerp->mDotColor = INACTIVE_COLOR; + mSpeakerDelayRemover->setActionTimer(speakerp->mID); + } } bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id) @@ -657,12 +689,12 @@ bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id) LLPointer LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id) { //In some conditions map causes crash if it is empty(Windows only), adding check (EK) - if (mSpeakers.size() == 0) - return NULL; + if (mSpeakers.empty()) + return nullptr; speaker_map_t::iterator found_it = mSpeakers.find(speaker_id); if (found_it == mSpeakers.end()) { - return NULL; + return nullptr; } return found_it->second; } @@ -670,9 +702,9 @@ LLPointer LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id) void LLSpeakerMgr::getSpeakerList(speaker_list_t* speaker_list, BOOL include_text) { speaker_list->clear(); - for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it) + for (auto& speaker : mSpeakers) { - LLPointer speakerp = speaker_it->second; + LLPointer speakerp = speaker.second; // what about text only muted or inactive? if (include_text || speakerp->mStatus != LLSpeaker::STATUS_TEXT_ONLY) { @@ -681,12 +713,12 @@ void LLSpeakerMgr::getSpeakerList(speaker_list_t* speaker_list, BOOL include_tex } } -const LLUUID LLSpeakerMgr::getSessionID() +const LLUUID LLSpeakerMgr::getSessionID() const { return mVoiceChannel->getSessionID(); } -bool LLSpeakerMgr::isSpeakerToBeRemoved(const LLUUID& speaker_id) +bool LLSpeakerMgr::isSpeakerToBeRemoved(const LLUUID& speaker_id) const { return mSpeakerDelayRemover && mSpeakerDelayRemover->isTimerStarted(speaker_id); } @@ -706,13 +738,13 @@ void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id) LLPointer speakerp = findSpeaker(speaker_id); if (speakerp.notNull()) { - speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32(); + speakerp->setSpokenTime(mSpeechTimer.getElapsedTimeF32()); speakerp->mHasSpoken = TRUE; fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker"); } } -BOOL LLSpeakerMgr::isVoiceActive() +BOOL LLSpeakerMgr::isVoiceActive() const { // mVoiceChannel = NULL means current voice channel, whatever it is return LLVoiceClient::getInstance()->voiceEnabled() && mVoiceChannel && mVoiceChannel->isActive(); @@ -741,89 +773,76 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers) { if ( !speakers.isMap() ) return; + std::vector speakerentries; if ( speakers.has("agent_info") && speakers["agent_info"].isMap() ) { - LLSD::map_const_iterator speaker_it; - for(speaker_it = speakers["agent_info"].beginMap(); - speaker_it != speakers["agent_info"].endMap(); - ++speaker_it) + for (const auto& speaker : speakers["agent_info"].map()) { - LLUUID agent_id(speaker_it->first); - - LLPointer speakerp = setSpeaker( - agent_id, - LLStringUtil::null, - LLSpeaker::STATUS_TEXT_ONLY); - - if ( speaker_it->second.isMap() ) + boost::optional moderator; + boost::optional moderator_muted; + if (speaker.second.isMap()) { - BOOL is_moderator = speakerp->mIsModerator; - speakerp->mIsModerator = speaker_it->second["is_moderator"]; - speakerp->mModeratorMutedText = - speaker_it->second["mutes"]["text"]; - // Fire event only if moderator changed - if ( is_moderator != speakerp->mIsModerator ) - { - LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << LL_ENDL; - fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator"); - } + moderator = speaker.second["is_moderator"]; + moderator_muted = speaker.second["mutes"]["text"]; } + speakerentries.emplace_back( + LLUUID(speaker.first), + LLSpeaker::SPEAKER_AGENT, + LLSpeaker::STATUS_TEXT_ONLY, + moderator, + moderator_muted + ); } } else if ( speakers.has("agents" ) && speakers["agents"].isArray() ) { //older, more decprecated way. Need here for //using older version of servers - LLSD::array_const_iterator speaker_it; - for(speaker_it = speakers["agents"].beginArray(); - speaker_it != speakers["agents"].endArray(); - ++speaker_it) + for (auto const& entry : speakers["agents"].array()) { - const LLUUID agent_id = (*speaker_it).asUUID(); - - LLPointer speakerp = setSpeaker( - agent_id, - LLStringUtil::null, - LLSpeaker::STATUS_TEXT_ONLY); + speakerentries.emplace_back(entry.asUUID()); } } + LLSpeakerMgr::setSpeakers(speakerentries); } void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) { if ( !update.isMap() ) return; + std::vector speakerentries; if ( update.has("agent_updates") && update["agent_updates"].isMap() ) { - LLSD::map_const_iterator update_it; - for( - update_it = update["agent_updates"].beginMap(); - update_it != update["agent_updates"].endMap(); - ++update_it) + for (const auto& update_it : update["agent_updates"].map()) { - LLUUID agent_id(update_it->first); + LLUUID agent_id(update_it.first); LLPointer speakerp = findSpeaker(agent_id); - LLSD agent_data = update_it->second; + bool new_speaker = false; + boost::optional moderator; + boost::optional moderator_muted_text; + LLSD agent_data = update_it.second; if (agent_data.isMap() && agent_data.has("transition")) { - if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull()) + if (agent_data["transition"].asString() == "LEAVE") { setSpeakerNotInChannel(speakerp); } else if (agent_data["transition"].asString() == "ENTER") { // add or update speaker - speakerp = setSpeaker(agent_id); + new_speaker = true; } else { - LL_WARNS() << "bad membership list update " << ll_print_sd(agent_data["transition"]) << LL_ENDL; + LL_WARNS() << "bad membership list update from 'agent_updates' for agent " << agent_id << ", transition " << ll_print_sd(agent_data["transition"]) << LL_ENDL; } } - - if (speakerp.isNull()) continue; + if (speakerp.isNull() && !new_speaker) + { + continue; + } // should have a valid speaker from this point on if (agent_data.isMap() && agent_data.has("info")) @@ -832,51 +851,46 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) if (agent_info.has("is_moderator")) { - BOOL is_moderator = speakerp->mIsModerator; - speakerp->mIsModerator = agent_info["is_moderator"]; - // Fire event only if moderator changed - if ( is_moderator != speakerp->mIsModerator ) - { - LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << LL_ENDL; - fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator"); - } + moderator = agent_info["is_moderator"]; } - if (agent_info.has("mutes")) { - speakerp->mModeratorMutedText = agent_info["mutes"]["text"]; + moderator_muted_text = agent_info["mutes"]["text"]; } } + speakerentries.emplace_back( + agent_id, + LLSpeaker::SPEAKER_AGENT, + LLSpeaker::STATUS_TEXT_ONLY, + moderator, + moderator_muted_text + ); } } else if ( update.has("updates") && update["updates"].isMap() ) { - LLSD::map_const_iterator update_it; - for ( - update_it = update["updates"].beginMap(); - update_it != update["updates"].endMap(); - ++update_it) + for (const auto& update_it : update["updates"].map()) { - LLUUID agent_id(update_it->first); + LLUUID agent_id(update_it.first); LLPointer speakerp = findSpeaker(agent_id); - std::string agent_transition = update_it->second.asString(); - if (agent_transition == "LEAVE" && speakerp.notNull()) + std::string agent_transition = update_it.second.asString(); + if (agent_transition == "LEAVE") { setSpeakerNotInChannel(speakerp); } else if ( agent_transition == "ENTER") { // add or update speaker - speakerp = setSpeaker(agent_id); + speakerentries.emplace_back(agent_id); } else { - LL_WARNS() << "bad membership list update " - << agent_transition << LL_ENDL; + LL_WARNS() << "bad membership list update from 'updates' for agent " << agent_id << ", transition " << agent_transition << LL_ENDL; } } } + LLSpeakerMgr::setSpeakers(speakerentries); } void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) @@ -884,7 +898,7 @@ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) LLPointer speakerp = findSpeaker(speaker_id); if (!speakerp) return; - std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); + std::string url = gAgent.getRegionCapability("ChatSessionRequest"); LLSD data; data["method"] = "mute update"; data["session-id"] = getSessionID(); @@ -909,7 +923,7 @@ void LLIMSpeakerMgr::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmu // do not send voice moderation changes for avatars not in voice channel if (!is_in_voice) return; - std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); + std::string url = gAgent.getRegionCapability("ChatSessionRequest"); LLSD data; data["method"] = "mute update"; data["session-id"] = getSessionID(); @@ -949,7 +963,7 @@ void LLIMSpeakerMgr::processSessionUpdate(const LLSD& session_update) void LLIMSpeakerMgr::moderateVoiceSession(const LLUUID& session_id, bool disallow_voice) { - std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); + std::string url = gAgent.getRegionCapability("ChatSessionRequest"); LLSD data; data["method"] = "session update"; data["session-id"] = session_id; @@ -965,13 +979,13 @@ void LLIMSpeakerMgr::moderateVoiceSession(const LLUUID& session_id, bool disallo void LLIMSpeakerMgr::forceVoiceModeratedMode(bool should_be_muted) { - for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it) + for (auto& speaker : mSpeakers) { - LLUUID speaker_id = speaker_it->first; - LLSpeaker* speakerp = speaker_it->second; + LLUUID speaker_id = speaker.first; + LLSpeaker* speakerp = speaker.second; // participant does not match requested state - if (should_be_muted != (bool)speakerp->mModeratorMutedVoice) + if (should_be_muted != static_cast(speakerp->mModeratorMutedVoice)) { moderateVoiceParticipant(speaker_id, !should_be_muted); } @@ -989,10 +1003,11 @@ LLActiveSpeakerMgr::LLActiveSpeakerMgr() : LLSpeakerMgr(NULL) void LLActiveSpeakerMgr::updateSpeakerList() { // point to whatever the current voice channel is + const auto old_channel = mVoiceChannel; mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel(); // always populate from active voice channel - if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) //MA: seems this is always false + if (mVoiceChannel != old_channel) //Singu Note: Don't let this always be false. { LL_DEBUGS("Speakers") << "Removed all speakers" << LL_ENDL; fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear"); @@ -1004,10 +1019,9 @@ void LLActiveSpeakerMgr::updateSpeakerList() LLSpeakerMgr::updateSpeakerList(); // clean up text only speakers - for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it) + for (auto& speaker : mSpeakers) { - LLUUID speaker_id = speaker_it->first; - LLSpeaker* speakerp = speaker_it->second; + LLSpeaker* speakerp = speaker.second; if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) { // automatically flag text only speakers for removal @@ -1043,18 +1057,21 @@ void LLLocalSpeakerMgr::updateSpeakerList() // pick up non-voice speakers in chat range uuid_vec_t avatar_ids; - LLWorld::getInstance()->getAvatars(&avatar_ids, NULL, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS); - BOOST_FOREACH(const LLUUID& id, avatar_ids) + LLWorld::getInstance()->getAvatars(&avatar_ids, nullptr, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS); + std::vector speakers; + speakers.reserve(avatar_ids.size()); + for (const auto& id : avatar_ids) { - setSpeaker(id); + speakers.emplace_back(id); } + setSpeakers(speakers); // check if text only speakers have moved out of chat range - for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it) + for (auto& speaker : mSpeakers) { - LLUUID speaker_id = speaker_it->first; - LLSpeaker* speakerp = speaker_it->second; - if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) + LLUUID speaker_id = speaker.first; + LLPointer speakerp = speaker.second; + if (speakerp.notNull() && speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) { LLVOAvatar* avatarp = gObjectList.findAvatar(speaker_id); if (!avatarp || dist_vec_squared(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS * CHAT_NORMAL_RADIUS) diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 107749224a..e28cd9a203 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -36,7 +36,7 @@ class LLSpeakerMgr; class LLVoiceChannel; // data for a given participant in a voice channel -class LLSpeaker : public LLRefCount, public LLOldEvents::LLObservable, public LLHandleProvider, public boost::signals2::trackable +class LLSpeaker final : public LLRefCount, public LLOldEvents::LLObservable, public LLHandleProvider, public boost::signals2::trackable { public: typedef enum e_speaker_type @@ -56,69 +56,118 @@ class LLSpeaker : public LLRefCount, public LLOldEvents::LLObservable, public LL STATUS_MUTED } ESpeakerStatus; - - LLSpeaker(const LLUUID& id, const std::string& name = LLStringUtil::null, const ESpeakerType type = SPEAKER_AGENT); - ~LLSpeaker() {}; + struct speaker_entry_t + { + speaker_entry_t(const LLUUID& id, + LLSpeaker::ESpeakerType type = ESpeakerType::SPEAKER_AGENT, + LLSpeaker::ESpeakerStatus status = ESpeakerStatus::STATUS_TEXT_ONLY, + const boost::optional moderator = boost::none, + const boost::optional moderator_muted_text = boost::none, + std::string name = std::string()) : + id(id), + type(type), + status(status), + moderator(moderator), + moderator_muted_text(moderator_muted_text), + name(name) + {} + const LLUUID id; + const LLSpeaker::ESpeakerType type; + const LLSpeaker::ESpeakerStatus status; + const boost::optional moderator; + const boost::optional moderator_muted_text; + const std::string name; + }; + + LLSpeaker(const speaker_entry_t& entry); + ~LLSpeaker() = default; + void update(const speaker_entry_t& entry); void lookupName(); void onNameCache(const LLAvatarName& full_name); bool isInVoiceChannel(); + void setStatus(ESpeakerStatus status) + { + if (status != mStatus) + { + mStatus = status; + mNeedsResort = true; + } + } + void setName(const std::string& name) + { + if (name != mDisplayName) + { + mDisplayName = name; + mNeedsResort = true; + } + } + void setSpokenTime(F32 time) + { + if (mLastSpokeTime != time) + { + mLastSpokeTime = time; + mNeedsResort = true; + } + } + + LLUUID mID; ESpeakerStatus mStatus; // current activity status in speech group + ESpeakerType mType : 2; + bool mIsModerator : 1; + bool mModeratorMutedVoice : 1; + bool mModeratorMutedText : 1; + bool mHasSpoken : 1; // has this speaker said anything this session? + bool mHasLeftCurrentCall : 1; // has this speaker left the current voice call? + bool mTyping : 1; F32 mLastSpokeTime; // timestamp when this speaker last spoke F32 mSpeechVolume; // current speech amplitude (timea average rms amplitude?) std::string mDisplayName; // cache user name for this speaker - BOOL mHasSpoken; // has this speaker said anything this session? - BOOL mHasLeftCurrentCall; // has this speaker left the current voice call? LLColor4 mDotColor; - LLUUID mID; - BOOL mTyping; + bool mNeedsResort; S32 mSortIndex; - ESpeakerType mType; - BOOL mIsModerator; - BOOL mModeratorMutedVoice; - BOOL mModeratorMutedText; }; -class LLSpeakerUpdateSpeakerEvent : public LLOldEvents::LLEvent +class LLSpeakerUpdateSpeakerEvent final : public LLOldEvents::LLEvent { public: LLSpeakerUpdateSpeakerEvent(LLSpeaker* source); - /*virtual*/ LLSD getValue(); + /*virtual*/ LLSD getValue() override; private: const LLUUID& mSpeakerID; }; -class LLSpeakerUpdateModeratorEvent : public LLOldEvents::LLEvent +class LLSpeakerUpdateModeratorEvent final : public LLOldEvents::LLEvent { public: LLSpeakerUpdateModeratorEvent(LLSpeaker* source); - /*virtual*/ LLSD getValue(); + /*virtual*/ LLSD getValue() override; private: const LLUUID& mSpeakerID; BOOL mIsModerator; }; -class LLSpeakerTextModerationEvent : public LLOldEvents::LLEvent +class LLSpeakerTextModerationEvent final : public LLOldEvents::LLEvent { public: LLSpeakerTextModerationEvent(LLSpeaker* source); - /*virtual*/ LLSD getValue(); + /*virtual*/ LLSD getValue() override; }; -class LLSpeakerVoiceModerationEvent : public LLOldEvents::LLEvent +class LLSpeakerVoiceModerationEvent final : public LLOldEvents::LLEvent { public: LLSpeakerVoiceModerationEvent(LLSpeaker* source); - /*virtual*/ LLSD getValue(); + /*virtual*/ LLSD getValue() override; }; -class LLSpeakerListChangeEvent : public LLOldEvents::LLEvent +class LLSpeakerListChangeEvent final : public LLOldEvents::LLEvent { public: LLSpeakerListChangeEvent(LLSpeakerMgr* source, const LLUUID& speaker_id); - /*virtual*/ LLSD getValue(); + /*virtual*/ LLSD getValue() override; private: const LLUUID& mSpeakerID; @@ -134,10 +183,10 @@ class LLSpeakerListChangeEvent : public LLOldEvents::LLEvent * Otherwise it should be deleted manually in place where it is used. * If action callback is not set timer will tick only once and deleted. */ -class LLSpeakerActionTimer : public LLEventTimer +class LLSpeakerActionTimer final : public LLEventTimer { public: - typedef boost::function action_callback_t; + typedef std::function action_callback_t; typedef std::map action_timers_map_t; typedef action_timers_map_t::value_type action_value_t; typedef action_timers_map_t::const_iterator action_timer_const_iter_t; @@ -151,14 +200,14 @@ class LLSpeakerActionTimer : public LLEventTimer * @param speaker_id - LLUUID of speaker which will be passed into action callback. */ LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id); - virtual ~LLSpeakerActionTimer() {}; + virtual ~LLSpeakerActionTimer() = default; /** * Implements timer "tick". * * If action callback is not specified returns true. Instance will be deleted by LLEventTimer::updateClass(). */ - virtual BOOL tick(); + BOOL tick() override; /** * Clears the callback. @@ -223,6 +272,8 @@ class LLSpeakerMgr : public LLOldEvents::LLObservable LOG_CLASS(LLSpeakerMgr); public: + typedef LLSpeaker::speaker_entry_t speaker_entry_t; + LLSpeakerMgr(LLVoiceChannel* channelp); virtual ~LLSpeakerMgr(); @@ -230,18 +281,17 @@ class LLSpeakerMgr : public LLOldEvents::LLObservable void update(BOOL resort_ok); void setSpeakerTyping(const LLUUID& speaker_id, BOOL typing); void speakerChatted(const LLUUID& speaker_id); - LLPointer setSpeaker(const LLUUID& id, - const std::string& name = LLStringUtil::null, - LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY, - LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT); - BOOL isVoiceActive(); + void setSpeakers(const std::vector& speakers); + LLPointer setSpeaker(const speaker_entry_t& speakers); + + BOOL isVoiceActive() const; typedef std::vector > speaker_list_t; void getSpeakerList(speaker_list_t* speaker_list, BOOL include_text); LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; } - const LLUUID getSessionID(); - bool isSpeakerToBeRemoved(const LLUUID& speaker_id); + const LLUUID getSessionID() const; + bool isSpeakerToBeRemoved(const LLUUID& speaker_id) const; /** * Removes avaline speaker. @@ -260,7 +310,7 @@ class LLSpeakerMgr : public LLOldEvents::LLObservable protected: virtual void updateSpeakerList(); - void setSpeakerNotInChannel(LLSpeaker* speackerp); + void setSpeakerNotInChannel(LLPointer speackerp); bool removeSpeaker(const LLUUID& speaker_id); typedef std::map > speaker_map_t; @@ -286,7 +336,7 @@ class LLSpeakerMgr : public LLOldEvents::LLObservable bool mModerateModeHandledFirstTime; }; -class LLIMSpeakerMgr : public LLSpeakerMgr +class LLIMSpeakerMgr final : public LLSpeakerMgr { LOG_CLASS(LLIMSpeakerMgr); @@ -326,7 +376,7 @@ class LLIMSpeakerMgr : public LLSpeakerMgr void processSessionUpdate(const LLSD& session_update); protected: - virtual void updateSpeakerList(); + void updateSpeakerList() override; void moderateVoiceSession(const LLUUID& session_id, bool disallow_voice); @@ -337,24 +387,24 @@ class LLIMSpeakerMgr : public LLSpeakerMgr }; -class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton +class LLActiveSpeakerMgr final : public LLSpeakerMgr, public LLSingleton { LOG_CLASS(LLActiveSpeakerMgr); public: LLActiveSpeakerMgr(); protected: - virtual void updateSpeakerList(); + void updateSpeakerList() override; }; -class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton +class LLLocalSpeakerMgr final : public LLSpeakerMgr, public LLSingleton { LOG_CLASS(LLLocalSpeakerMgr); public: LLLocalSpeakerMgr(); ~LLLocalSpeakerMgr (); protected: - virtual void updateSpeakerList(); + void updateSpeakerList() override; }; #endif // LL_LLSPEAKERS_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 7be6ffd4fe..862d6d3098 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -44,27 +44,23 @@ #include "llviewermedia_streamingaudio.h" #include "llaudioengine.h" - -#if LL_FMODSTUDIO +#ifdef LL_FMODSTUDIO # include "llaudioengine_fmodstudio.h" #endif -#if LL_FMODEX -# include "llaudioengine_fmodex.h" -#endif - #ifdef LL_OPENAL #include "llaudioengine_openal.h" #endif +#include "aosystem.h" #include "hippogridmanager.h" #include "hippolimits.h" -#include "floaterao.h" #include "statemachine/aifilepicker.h" #include "lfsimfeaturehandler.h" #include "llares.h" #include "llavatarnamecache.h" +#include "llexperiencecache.h" #include "lllandmark.h" #include "llcachename.h" #include "lldir.h" @@ -90,7 +86,7 @@ #include "lltexteditor.h" #include "llurlentry.h" #include "lluserrelations.h" -#include "sgversion.h" +#include "llversioninfo.h" #include "llviewercontrol.h" #include "llvfs.h" #include "llxorcipher.h" // saved password, MAC address @@ -99,6 +95,7 @@ #include "v3math.h" #include "llagent.h" +#include "llagentbenefits.h" #include "llagentcamera.h" #include "llagentwearables.h" #include "llagentpilot.h" @@ -208,8 +205,7 @@ #include "llweb.h" #include "llvoiceclient.h" #include "llnamelistctrl.h" -#include "llnamebox.h" -#include "llnameeditor.h" +#include "llnameui.h" #include "llwlparammanager.h" #include "llwaterparammanager.h" #include "llagentlanguage.h" @@ -221,6 +217,7 @@ #include "generichandlers.h" // +#include "floaterlocalassetbrowse.h" #include "llpanellogin.h" //#include "llfloateravatars.h" //#include "llactivation.h" @@ -229,11 +226,11 @@ #include "llfloaterblacklist.h" #include "scriptcounter.h" #include "shfloatermediaticker.h" +#include "shupdatechecker.h" #include "llpacketring.h" // #include "llpathfindingmanager.h" -#include "llevents.h" #include "lgghunspell_wrapper.h" @@ -241,6 +238,8 @@ #include "rlvhandler.h" // [/RLVa:KB] +#include "llevents.h" +#include "llexperiencelog.h" #if LL_WINDOWS #include "llwindebug.h" #include "lldxhardware.h" @@ -288,6 +287,7 @@ static LLHost gFirstSim; static std::string gFirstSimSeedCap; static LLVector3 gAgentStartLookAt(1.0f, 0.f, 0.f); static std::string gAgentStartLocation = "safe"; +static bool mBenefitsSuccessfullyInit = false; boost::scoped_ptr LLStartUp::sStateWatcher(new LLEventStream("StartupState")); @@ -318,12 +318,12 @@ void apply_udp_blacklist(const std::string& csv); //bool process_login_success_response(std::string& password); bool process_login_success_response(std::string& password, U32& first_sim_size_x, U32& first_sim_size_y); // Aurora Sim +void on_benefits_failed_callback(const LLSD& notification, const LLSD& response); void transition_back_to_login_panel(const std::string& emsg); void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is_group) { - LLNameBox::refreshAll(id, full_name, is_group); - LLNameEditor::refreshAll(id, full_name, is_group); + LLNameUI::refreshAll(id, full_name); // TODO: Actually be intelligent about the refresh. // For now, just brute force refresh the dialogs. @@ -434,17 +434,6 @@ void init_audio() } #endif -#ifdef LL_FMODEX - if (!gAudiop -#if !LL_WINDOWS - && NULL == getenv("LL_BAD_FMODEX_DRIVER") -#endif // !LL_WINDOWS - ) - { - gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("SHEnableFMODExProfiler"),gSavedSettings.getBOOL("SHEnableFMODEXVerboseDebugging")); - } -#endif - #ifdef LL_OPENAL if (!gAudiop #if !LL_WINDOWS @@ -653,21 +642,34 @@ bool idle_startup() // LL_DEBUGS("AppInit") << "Initializing messaging system..." << LL_ENDL; - std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg"); + auto app_settings_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, LLStringUtil::null); + std::string message_template_path = gDirUtilp->add(app_settings_path, "message_template.msg"); LLFILE* found_template = NULL; found_template = LLFile::fopen(message_template_path, "r"); /* Flawfinder: ignore */ + if (!found_template) + { + app_settings_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, #if LL_WINDOWS - // On the windows dev builds, unpackaged, the message_template.msg + // On the windows dev builds, unpackaged, the message_template.msg // file will be located in: // indra/build-vc**/newview//app_settings. - 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 */ - } + "app_settings" + #elif LL_DARWIN + // On Mac dev builds, message_template.msg lives in: + // indra/build-*/newview//Second Life/Contents/Resources/app_settings + "../Resources/app_settings" + #else // LL_LINUX and other + // On the linux dev builds, the message_template.msg + // file will be located in: + // indra/build-linux**/newview/packaged/app_settings. + "../app_settings" #endif + , LLStringUtil::null); + message_template_path = gDirUtilp->add(app_settings_path, "message_template.msg"); + found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ + } if (found_template) { @@ -693,9 +695,9 @@ bool idle_startup() if(!start_messaging_system( message_template_path, port, - gVersionMajor, - gVersionMinor, - gVersionPatch, + LLVersionInfo::getMajor(), + LLVersionInfo::getMinor(), + LLVersionInfo::getPatch(), FALSE, std::string(), responder, @@ -708,22 +710,8 @@ bool idle_startup() LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic)); } - #if LL_WINDOWS - // On the windows dev builds, unpackaged, the message.xml file will - // be located in indra/build-vc**/newview//app_settings. - std::string message_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message.xml"); - - if (!LLFile::isfile(message_path.c_str())) - { - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "")); - } - else - { - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - } - #else - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - #endif + // Take into account dev checkout status on all platforms, by using app_settings_path ~Liru + LLMessageConfig::initClass("viewer", app_settings_path); } else @@ -864,6 +852,7 @@ bool idle_startup() // Go to the next startup state LLStartUp::setStartupState( STATE_BROWSER_INIT ); + check_for_updates(); return FALSE; } @@ -872,7 +861,7 @@ bool idle_startup() { LL_DEBUGS("AppInit") << "STATE_BROWSER_INIT" << LL_ENDL; //std::string msg = LLTrans::getString("LoginInitializingBrowser"); - //set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str()); + //set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD); display_startup(); // LLViewerMedia::initBrowser(); LLStartUp::setStartupState( STATE_LOGIN_SHOW ); @@ -903,6 +892,8 @@ bool idle_startup() LLToolMgr::getInstance()->initTools(); display_startup(); + // Load local textures now, maybe someone wants to use them in UI (why?) + LocalAssetBrowser::instance(); // // Quickly get something onscreen to look at. gViewerWindow->initWorldUI(); display_startup(); @@ -957,7 +948,11 @@ bool idle_startup() display_startup(); // Push our window frontmost - gViewerWindow->getWindow()->show(); + // Singu Note: Actually, don't! But flash the window to let the user know + auto& window(*gViewerWindow->getWindow()); + window.show(false); + if (gSavedSettings.getBOOL("LiruFlashWhenMinimized")) // No, we're not minimized, but if you flash my bar, I will give you the biggest SIGSEGV ~Liru <3 + window.flashIcon(5.f); display_startup(); // DEV-16927. The following code removes errant keystrokes that happen while the window is being @@ -1096,27 +1091,12 @@ bool idle_startup() } //Get these logs out of my newview root directory, PLEASE. - if (gHippoGridManager->getCurrentGrid()->isSecondLife()) - { - gDirUtilp->setPerAccountChatLogsDir(LLStringUtil::null, - gSavedSettings.getString("FirstName"), gSavedSettings.getString("LastName") ); - } - else - { - gDirUtilp->setPerAccountChatLogsDir(gHippoGridManager->getConnectedGrid()->getGridNick(), - gSavedSettings.getString("FirstName"), gSavedSettings.getString("LastName") ); - } + gDirUtilp->setPerAccountChatLogsDir(gHippoGridManager->getCurrentGrid()->isSecondLife() ? LLStringUtil::null : gHippoGridManager->getConnectedGrid()->getGridNick(), + gSavedSettings.getString("FirstName"), gSavedSettings.getString("LastName")); LLFile::mkdir(gDirUtilp->getChatLogsDir()); LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); - // NaCl - Antispam - U32 antispam_time = gSavedSettings.getU32("_NACL_AntiSpamTime"); - U32 antispam_amount = gSavedSettings.getU32("_NACL_AntiSpamAmount"); - NACLAntiSpamRegistry::registerQueues(antispam_time, antispam_amount); - gSavedSettings.getControl("_NACL_AntiSpamGlobalQueue")->getSignal()->connect(boost::bind(&NACLAntiSpamRegistry::handleNaclAntiSpamGlobalQueueChanged, _2)); - gSavedSettings.getControl("_NACL_AntiSpamTime")->getSignal()->connect(boost::bind(&NACLAntiSpamRegistry::handleNaclAntiSpamTimeChanged, _2)); - gSavedSettings.getControl("_NACL_AntiSpamAmount")->getSignal()->connect(boost::bind(&NACLAntiSpamRegistry::handleNaclAntiSpamAmountChanged, _2)); - // NaCl End + NACLAntiSpamRegistry::startup(); // NaCl - Antispam //good a place as any to create user windlight directories std::string user_windlight_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight", "")); @@ -1145,14 +1125,9 @@ bool idle_startup() //LLPanelLogin::close(); } - //For HTML parsing in text boxes. - LLTextEditor::setLinkColor( gSavedSettings.getColor4("HTMLLinkColor") ); - // Load URL History File LLURLHistory::loadFile("url_history.xml"); - // Load media plugin cookies - LLViewerMedia::loadCookieFile(); - + //------------------------------------------------- // Handle startup progress screen //------------------------------------------------- @@ -1599,9 +1574,9 @@ bool idle_startup() if (!secondlife || !boost::algorithm::iequals(lastname, "Resident")) { - name += " " + lastname; + name += ' ' + lastname; } - if (gSavedSettings.getBOOL("LiruGridInTitle")) gWindowTitle += "- " + gHippoGridManager->getCurrentGrid()->getGridName() + " "; + if (gSavedSettings.getBOOL("LiruGridInTitle")) gWindowTitle += "- " + gHippoGridManager->getCurrentGrid()->getGridName() + ' '; gViewerWindow->getWindow()->setTitle(gWindowTitle += "- " + name); if (!secondlife) @@ -1739,6 +1714,9 @@ bool idle_startup() // object is created. I think this must be done after setting the region. JC gAgent.setPositionAgent(agent_start_position_region); + display_startup(); + LLStartUp::initExperiences(); + display_startup(); LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); return FALSE; @@ -1859,6 +1837,7 @@ bool idle_startup() display_startup(); LLStartUp::initNameCache(); + LLLogChat::initializeIDMap(); // Name cache loaded, create a happy mappy display_startup(); // update the voice settings *after* gCacheName initialization @@ -1935,13 +1914,13 @@ bool idle_startup() { LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL; // Initialize all of the viewer object classes for the first time (doing things like texture fetches. - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); gSky.init(initial_sun_direction); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); } display_startup(); @@ -1983,7 +1962,7 @@ bool idle_startup() gFirstSim, MAX_TIMEOUT_COUNT, FALSE, - TIMEOUT_SECONDS, + F32Seconds(TIMEOUT_SECONDS), use_circuit_callback, NULL); @@ -2034,7 +2013,7 @@ bool idle_startup() send_complete_agent_movement(regionp->getHost()); gAssetStorage->setUpstream(regionp->getHost()); gCacheName->setUpstream(regionp->getHost()); - msg->newMessageFast(_PREHASH_EconomyDataRequest); + if (!mBenefitsSuccessfullyInit) msg->newMessageFast(_PREHASH_EconomyDataRequest); gAgent.sendReliableMessage(); } display_startup(); @@ -2295,13 +2274,13 @@ bool idle_startup() // Create the inventory views LL_INFOS() << "Creating Inventory Views" << LL_ENDL; - LLInventoryView::showAgentInventory(); + LLPanelMainInventory::showAgentInventory(); display_startup(); // Hide the inventory if it wasn't shown at exit if(!shown_at_exit) { - LLInventoryView::toggleVisibility(NULL); + LLPanelMainInventory::toggleVisibility(NULL); } display_startup(); @@ -2355,6 +2334,12 @@ bool idle_startup() } display_startup(); + + // *TODO : Uncomment that line once the whole grid migrated to SLM and suppress it from LLAgent::handleTeleportFinished() (llagent.cpp) + //check_merchant_status(); + + display_startup(); + // We're successfully logged in. gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE); @@ -2572,17 +2557,17 @@ bool idle_startup() && !sInitialOutfit.empty() // registration set up an outfit && !sInitialOutfitGender.empty() // and a gender && isAgentAvatarValid() // can't wear clothes without object - && !gAgent.isGenderChosen() ) // nothing already loading + && !gAgent.isOutfitChosen()) // nothing already loading { // Start loading the wearables, textures, gestures LLStartUp::loadInitialOutfit( sInitialOutfit, sInitialOutfitGender ); } // If not first login, we need to fetch COF contents and // compute appearance from that. - if (isAgentAvatarValid() && !gAgent.isFirstLogin() && !gAgent.isGenderChosen()) + if (isAgentAvatarValid() && !gAgent.isFirstLogin() && !gAgent.isOutfitChosen()) { gAgentWearables.notifyLoadingStarted(); - gAgent.setGenderChosen(TRUE); + gAgent.setOutfitChosen(TRUE); gAgentWearables.sendDummyAgentWearablesUpdate(); callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), set_flags_and_update_appearance); } @@ -2590,7 +2575,7 @@ bool idle_startup() display_startup(); // wait precache-delay and for agent's avatar or a lot longer. - if((timeout_frac > 1.f) && isAgentAvatarValid()) + if ((timeout_frac > 1.f) && isAgentAvatarValid()) { LLStartUp::setStartupState( STATE_WEARABLES_WAIT ); } @@ -2633,11 +2618,11 @@ bool idle_startup() const F32 wearables_time = wearables_timer.getElapsedTimeF32(); const F32 MAX_WEARABLES_TIME = 10.f; - if (!gAgent.isGenderChosen() && isAgentAvatarValid()) + if (!gAgent.isOutfitChosen() && isAgentAvatarValid()) { - // No point in waiting for clothing, we don't even - // know what gender we are. Pop a dialog to ask and - // proceed to draw the world. JC + // No point in waiting for clothing, we don't even know + // what outfit we want. Pop up a gender chooser dialog to + // ask and proceed to draw the world. JC // // *NOTE: We might hit this case even if we have an // initial outfit, but if the load hasn't started @@ -2665,7 +2650,7 @@ bool idle_startup() if (isAgentAvatarValid() && gAgentAvatarp->isFullyLoaded()) { - //LL_INFOS() << "avatar fully loaded" << LL_ENDL; + LL_DEBUGS("Avatar") << "avatar fully loaded" << LL_ENDL; LLStartUp::setStartupState( STATE_CLEANUP ); return TRUE; } @@ -2676,7 +2661,7 @@ bool idle_startup() if ( gAgentWearables.areWearablesLoaded() ) { // We have our clothing, proceed. - //LL_INFOS() << "wearables loaded" << LL_ENDL; + LL_DEBUGS("Avatar") << "wearables loaded" << LL_ENDL; LLStartUp::setStartupState( STATE_CLEANUP ); return TRUE; } @@ -2686,17 +2671,22 @@ bool idle_startup() update_texture_fetch(); display_startup(); set_startup_status(0.9f + 0.1f * wearables_time / MAX_WEARABLES_TIME, - LLTrans::getString("LoginDownloadingClothing").c_str(), - gAgent.mMOTD.c_str()); + LLTrans::getString("LoginDownloadingClothing"), + gAgent.mMOTD); display_startup(); return TRUE; } if (STATE_CLEANUP == LLStartUp::getStartupState()) { - set_startup_status(1.0, "", ""); + set_startup_status(1.0, LLStringUtil::null, LLStringUtil::null); display_startup(); + if (!mBenefitsSuccessfullyInit && gHippoGridManager->getConnectedGrid()->isSecondLife()) + { + LLNotificationsUtil::add("FailedToGetBenefits", LLSD(), LLSD(), boost::bind(on_benefits_failed_callback, _1, _2)); + } + // Let the map know about the inventory. LLFloaterWorldMap* floater_world_map = gFloaterWorldMap; if(floater_world_map) @@ -2706,16 +2696,13 @@ bool idle_startup() } // Start the AO now that settings have loaded and login successful -- MC - if (!gAOInvTimer) - { - gAOInvTimer = new AOInvTimer(); - } + AOSystem::start(); gViewerWindow->showCursor(); gViewerWindow->getWindow()->resetBusyCount(); gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); LL_DEBUGS("AppInit") << "Done releasing bitmap" << LL_ENDL; - + //gViewerWindow->revealIntroPanel(); gViewerWindow->setStartupComplete(); gViewerWindow->setProgressCancelButtonVisible(FALSE); display_startup(); @@ -3027,17 +3014,7 @@ void pass_processObjectPropertiesFamily(LLMessageSystem *msg, void**) void process_script_running_reply(LLMessageSystem* msg, void** v) { LLLiveLSLEditor::processScriptRunningReply(msg, v); - if (ScriptCounter::sCheckMap.size()) - { - LLUUID item_id; - msg->getUUIDFast(_PREHASH_Script, _PREHASH_ItemID, item_id); - std::map::iterator it = ScriptCounter::sCheckMap.find(item_id); - if (it != ScriptCounter::sCheckMap.end()) - { - it->second->processRunningReply(msg); - ScriptCounter::sCheckMap.erase(it); - } - } + ScriptCounter::processScriptRunningReply(msg); } void register_viewer_callbacks(LLMessageSystem* msg) @@ -3072,6 +3049,7 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFuncFast(_PREHASH_NameValuePair, process_name_value); msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair, process_remove_name_value); msg->setHandlerFuncFast(_PREHASH_AvatarAnimation, process_avatar_animation); + msg->setHandlerFuncFast(_PREHASH_ObjectAnimation, process_object_animation); msg->setHandlerFuncFast(_PREHASH_AvatarAppearance, process_avatar_appearance); msg->setHandlerFunc("AgentCachedTextureResponse", LLAgent::processAgentCachedTextureResponse); msg->setHandlerFunc("RebakeAvatarTextures", LLVOAvatarSelf::processRebakeAvatarTextures); @@ -3147,9 +3125,6 @@ void register_viewer_callbacks(LLMessageSystem* msg) // msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply, // LLFloaterRate::processReputationIndividualReply); - msg->setHandlerFuncFast(_PREHASH_AgentWearablesUpdate, - LLAgentWearables::processAgentInitialWearablesUpdate ); - msg->setHandlerFunc("ScriptControlChange", LLAgent::processScriptControlChange ); @@ -3324,9 +3299,8 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, LL_DEBUGS() << "initial outfit category id: " << cat_id << LL_ENDL; } - // This is really misnamed -- it means we have started loading - // an outfit/shape that will give the avatar a gender eventually. JC - gAgent.setGenderChosen(TRUE); + gAgent.setOutfitChosen(TRUE); + gAgentWearables.sendDummyAgentWearablesUpdate(); } //static @@ -3339,10 +3313,10 @@ void LLStartUp::saveInitialOutfit() if (sWearablesLoadedCon.connected()) { - LL_DEBUGS() << "sWearablesLoadedCon is connected, disconnecting" << LL_ENDL; + LL_DEBUGS("Avatar") << "sWearablesLoadedCon is connected, disconnecting" << LL_ENDL; sWearablesLoadedCon.disconnect(); } - LL_DEBUGS() << "calling makeNewOutfitLinks( \"" << sInitialOutfit << "\" )" << LL_ENDL; + LL_DEBUGS("Avatar") << "calling makeNewOutfitLinks( \"" << sInitialOutfit << "\" )" << LL_ENDL; LLAppearanceMgr::getInstance()->makeNewOutfitLinks(sInitialOutfit,false); } @@ -3562,12 +3536,22 @@ void LLStartUp::initNameCache() LLAvatarNameCache::setUseUsernames(!phoenix_name_system || phoenix_name_system == 1 || phoenix_name_system == 3); } + +void LLStartUp::initExperiences() +{ + // Should trigger loading the cache. + LLExperienceCache::instance().setCapabilityQuery( + boost::bind(&LLAgent::getRegionCapability, &gAgent, _1)); + + LLExperienceLog::instance().initialize(); +} + void LLStartUp::cleanupNameCache() { LLAvatarNameCache::cleanupClass(); delete gCacheName; - gCacheName = NULL; + gCacheName = nullptr; } bool LLStartUp::dispatchURL() @@ -3911,10 +3895,70 @@ void apply_udp_blacklist(const std::string& csv) } +void on_benefits_failed_callback(const LLSD& notification, const LLSD& response) +{ + LL_WARNS("Benefits") << "Failed to load benefits information" << LL_ENDL; +} + +bool init_benefits(LLSD& response) +{ + bool succ = true; + + std::string package_name = response["account_type"].asString(); + const LLSD& benefits_sd = response["account_level_benefits"]; + if (!LLAgentBenefitsMgr::init(package_name, benefits_sd) || + !LLAgentBenefitsMgr::initCurrent(package_name, benefits_sd)) + { + succ = false; + } + else + { + LL_DEBUGS("Benefits") << "Initialized current benefits, level " << package_name << " from " << benefits_sd << LL_ENDL; + } + const LLSD& packages_sd = response["premium_packages"]; + for(LLSD::map_const_iterator package_iter = packages_sd.beginMap(); + package_iter != packages_sd.endMap(); + ++package_iter) + { + std::string package_name = package_iter->first; + const LLSD& benefits_sd = package_iter->second["benefits"]; + if (LLAgentBenefitsMgr::init(package_name, benefits_sd)) + { + LL_DEBUGS("Benefits") << "Initialized benefits for package " << package_name << " from " << benefits_sd << LL_ENDL; + } + else + { + LL_WARNS("Benefits") << "Failed init for package " << package_name << " from " << benefits_sd << LL_ENDL; + succ = false; + } + } + + if (!LLAgentBenefitsMgr::has("Base")) + { + LL_WARNS("Benefits") << "Benefits info did not include required package Base" << LL_ENDL; + succ = false; + } + if (!LLAgentBenefitsMgr::has("Premium")) + { + LL_WARNS("Benefits") << "Benefits info did not include required package Premium" << LL_ENDL; + succ = false; + } + + // FIXME PREMIUM - for testing if login does not yet provide Premium Plus. Should be removed thereafter. + //if (succ && !LLAgentBenefitsMgr::has("Premium Plus")) + //{ + // LLAgentBenefitsMgr::init("Premium Plus", packages_sd["Premium"]["benefits"]); + // llassert(LLAgentBenefitsMgr::has("Premium Plus")); + //} + return succ; +} + bool process_login_success_response(std::string& password, U32& first_sim_size_x, U32& first_sim_size_y) { LLSD response = LLUserAuth::getInstance()->getResponse(); + mBenefitsSuccessfullyInit = init_benefits(response); + std::string text(response["udp_blacklist"]); if(!text.empty()) { @@ -4009,17 +4053,6 @@ bool process_login_success_response(std::string& password, U32& first_sim_size_x gSavedSettings.setU32("PreferredMaturity", preferredMaturity); } - // During the AO transition, this flag will be true. Then the flag will - // go away. After the AO transition, this code and all the code that - // uses it can be deleted. - text = response["ao_transition"].asString(); - if (!text.empty()) - { - if (text == "1") - { - gAgent.setAOTransition(); - } - } text = response["start_location"].asString(); if(!text.empty()) @@ -4131,6 +4164,7 @@ bool process_login_success_response(std::string& password, U32& first_sim_size_x // We don't care about this flag anymore; now base whether // outfit is chosen on COF contents, initial outfit // requested and available, etc. + //gAgent.setGenderChosen(TRUE); } @@ -4147,14 +4181,15 @@ bool process_login_success_response(std::string& password, U32& first_sim_size_x LLWorldMap::gotMapServerURL(true); } - bool opensim = gHippoGridManager->getConnectedGrid()->isOpenSimulator(); + auto& grid = *gHippoGridManager->getConnectedGrid(); + bool opensim = !grid.isSecondLife(); if (opensim) { std::string web_profile_url = response["web_profile_url"]; //if(!web_profile_url.empty()) // Singu Note: We're using this to check if this grid supports web profiles at all, so set empty if empty. gSavedSettings.setString("WebProfileURL", web_profile_url); } - else if(!gHippoGridManager->getConnectedGrid()->isInProductionGrid()) + else if(!grid.isInProductionGrid()) { gSavedSettings.setString("WebProfileURL", "https://my-demo.secondlife.com/[AGENT_NAME]"); } @@ -4203,45 +4238,46 @@ bool process_login_success_response(std::string& password, U32& first_sim_size_x gCloudTextureID = id; } #endif - // set the location of the Agent Appearance service, from which we can request - // avatar baked textures if they are supported by the current region - std::string agent_appearance_url = response["agent_appearance_service"]; - if (!agent_appearance_url.empty()) - { - gSavedSettings.setString("AgentAppearanceServiceURL", agent_appearance_url); - } + } + + // set the location of the Agent Appearance service, from which we can request + // avatar baked textures if they are supported by the current region + std::string agent_appearance_url = response["agent_appearance_service"]; + if (!agent_appearance_url.empty()) + { + gSavedSettings.setString("AgentAppearanceServiceURL", agent_appearance_url); } // Override grid info with anything sent in the login response std::string tmp = response["gridname"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setGridName(tmp); + if (!tmp.empty()) grid.setGridName(tmp); tmp = response["loginuri"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setLoginUri(tmp); + if (!tmp.empty()) grid.setLoginUri(tmp); tmp = response["welcome"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setLoginPage(tmp); + if (!tmp.empty()) grid.setLoginPage(tmp); tmp = response["loginpage"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setLoginPage(tmp); + if (!tmp.empty()) grid.setLoginPage(tmp); tmp = response["economy"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setHelperUri(tmp); + if (!tmp.empty()) grid.setHelperUri(tmp); tmp = response["helperuri"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setHelperUri(tmp); + if (!tmp.empty()) grid.setHelperUri(tmp); tmp = response["about"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setWebSite(tmp); + if (!tmp.empty()) grid.setWebSite(tmp); tmp = response["website"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setWebSite(tmp); + if (!tmp.empty()) grid.setWebSite(tmp); tmp = response["help"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setSupportUrl(tmp); + if (!tmp.empty()) grid.setSupportUrl(tmp); tmp = response["support"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setSupportUrl(tmp); + if (!tmp.empty()) grid.setSupportUrl(tmp); tmp = response["register"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setRegisterUrl(tmp); + if (!tmp.empty()) grid.setRegisterUrl(tmp); tmp = response["account"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setRegisterUrl(tmp); + if (!tmp.empty()) grid.setRegisterUrl(tmp); tmp = response["password"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setPasswordUrl(tmp); + if (!tmp.empty()) grid.setPasswordUrl(tmp); tmp = response["search"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setSearchUrl(tmp); - else if (opensim) tmp = gHippoGridManager->getConnectedGrid()->getSearchUrl(); // Fallback from grid info response for setting + if (!tmp.empty()) grid.setSearchUrl(tmp); + else if (opensim) tmp = grid.getSearchUrl(); // Fallback from grid info response for setting if (opensim) { gSavedSettings.setString("SearchURL", tmp); // Singu Note: For web search purposes, always set this setting @@ -4250,32 +4286,31 @@ bool process_login_success_response(std::string& password, U32& first_sim_size_x gMenuBarView->getChildView("Avatar Picker")->setVisible(!tmp.empty()); gSavedSettings.setString("DestinationGuideURL", response["destination_guide_url"].asString()); tmp = response["classified_fee"].asString(); - gHippoGridManager->getConnectedGrid()->setClassifiedFee(tmp.empty() ? 0 : atoi(tmp.c_str())); + grid.setClassifiedFee(tmp.empty() ? 0 : atoi(tmp.c_str())); } tmp = response["currency"].asString(); if (!tmp.empty()) { LLTrans::setDefaultArg("[CURRENCY]", tmp); - gHippoGridManager->getConnectedGrid()->setCurrencySymbol(tmp); + grid.setCurrencySymbol(tmp); } tmp = response["currency_text"].asString(); if (!tmp.empty()) { LLTrans::setDefaultArg("[CURRENCY_TEXT]", tmp); - gHippoGridManager->getConnectedGrid()->setCurrencyText(tmp); + grid.setCurrencyText(tmp); } tmp = response["real_currency"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setRealCurrencySymbol(tmp); + if (!tmp.empty()) grid.setRealCurrencySymbol(tmp); tmp = response["directory_fee"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setDirectoryFee(atoi(tmp.c_str())); - tmp = response["max_groups"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setMaxAgentGroups(atoi(tmp.c_str())); - tmp = response["max-agent-groups"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setMaxAgentGroups(atoi(tmp.c_str())); + if (!tmp.empty()) grid.setDirectoryFee(atoi(tmp.c_str())); + if (mBenefitsSuccessfullyInit) tmp = response["VoiceConnector"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setVoiceConnector(tmp); + if (!tmp.empty()) grid.setVoiceConnector(tmp); tmp = response["upc_supported"].asString(); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setUPCSupported(true); + if (!tmp.empty()) grid.setUPCSupported(true); + if (opensim && !mBenefitsSuccessfullyInit) + LLAgentBenefitsMgr::instance().initNonSL(response); gHippoGridManager->saveFile(); gHippoLimits->setLimits(); @@ -4308,3 +4343,4 @@ void transition_back_to_login_panel(const std::string& emsg) reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW ); gSavedSettings.setBOOL("AutoLogin", FALSE); } + diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index f53d9d5b04..88cdac5e6b 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -104,6 +104,7 @@ class LLStartUp static void fontInit(); static void initNameCache(); + static void initExperiences(); static void cleanupNameCache(); @@ -138,6 +139,7 @@ class LLStartUp static bool startLLProxy(); // Initialize the SOCKS 5 proxy static LLViewerStats::PhaseMap& getPhases() { return *sPhases; } + static LLEventPump& getStateEventPump() { return *sStateWatcher; } private: static LLSLURL sStartSLURL; diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index ba97444971..4dbb92f1ce 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -41,11 +41,11 @@ #include "llfloaterbuycurrency.h" #include "llfloaterchat.h" #include "llfloaterinventory.h" -#include "llfloaterlagmeter.h" #include "llfloaterland.h" #include "llfloaterregioninfo.h" #include "llfloaterscriptdebug.h" #include "llfloatersearch.h" +#include "llfloaterstats.h" #include "llhudicon.h" #include "llkeyboard.h" #include "lllineeditor.h" @@ -56,6 +56,7 @@ #include "llpathfindingnavmeshstatus.h" #include "llimview.h" #include "lltextbox.h" +#include "lltrans.h" #include "llui.h" #include "llviewerparceloverlay.h" #include "llviewerregion.h" @@ -235,7 +236,7 @@ mIsNavMeshDirty(false) mSearchBevel->setVisible(show_search); mTextParcelName->setClickedCallback(boost::bind(onClickParcelInfo)); - mTextBalance->setClickedCallback(boost::bind(LLFloaterBuyCurrency::buyCurrency)); + mTextBalance->setClickedCallback(boost::bind(LLStatusBar::sendMoneyBalanceRequest, true)); // TODO: Disable buying currency when connected to non-SL grids // that don't support currency yet -- MC @@ -276,7 +277,7 @@ mIsNavMeshDirty(false) addChild(mSGPacketLoss); mStatBtn = getChild("stat_btn"); - mStatBtn->setClickedCallback(boost::bind(LLFloaterLagMeter::showInstance, LLSD())); + mStatBtn->setClickedCallback(boost::bind(LLFloaterStats::toggleInstance, LLSD())); } LLStatusBar::~LLStatusBar() @@ -672,8 +673,10 @@ void LLStatusBar::setUPC(S32 upc) } // static -void LLStatusBar::sendMoneyBalanceRequest() +void LLStatusBar::sendMoneyBalanceRequest(bool from_user) { + void cmdline_printchat(const std::string& message); + if (from_user) cmdline_printchat(LLTrans::getString("refreshing balance")); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_MoneyBalanceRequest); msg->nextBlockFast(_PREHASH_AgentData); @@ -895,7 +898,7 @@ class LLBalanceHandler : public LLCommandHandler if (tokens.size() == 1 && tokens[0].asString() == "request") { - LLStatusBar::sendMoneyBalanceRequest(); + LLStatusBar::sendMoneyBalanceRequest(true); return true; } return false; diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 1db2806c7c..3acf9998f1 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -66,7 +66,7 @@ class LLStatusBar void creditBalance(S32 credit); // Request the latest currency balance from the server - static void sendMoneyBalanceRequest(); + static void sendMoneyBalanceRequest(bool from_user = false); void setHealth(S32 percent); diff --git a/indra/newview/llstylemap.cpp b/indra/newview/llstylemap.cpp index a0c64505e1..fb6dad7a23 100644 --- a/indra/newview/llstylemap.cpp +++ b/indra/newview/llstylemap.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llstylemap.h" +#include "llavataractions.h" LLStyleMap::LLStyleMap() { @@ -58,9 +59,8 @@ const LLStyleSP &LLStyleMap::lookupAgent(const LLUUID &source) LLStyleSP style(new LLStyle); if (source.notNull()) { - style->setColor(gSavedSettings.getColor4("HTMLLinkColor")); - std::string link = llformat("secondlife:///app/agent/%s/about",source.asString().c_str()); - style->setLinkHREF(link); + style->setColor(gSavedSettings.getColor4("HTMLAgentColor")); + style->setLinkHREF(LLAvatarActions::getSLURL(source)); } (*this)[source] = style; } @@ -77,7 +77,7 @@ const LLStyleSP &LLStyleMap::lookup(const LLUUID& id, const std::string& link) LLStyleSP style(new LLStyle); if (id.notNull() && !link.empty()) { - style->setColor(gSavedSettings.getColor4("HTMLLinkColor")); + style->setColor(gSavedSettings.getColor4("HTMLAgentColor")); style->setLinkHREF(link); } else @@ -102,6 +102,6 @@ void LLStyleMap::update() { LLStyleSP &style = iter->second; // Update the link color in case it has been changed. - style->setColor(gSavedSettings.getColor4("HTMLLinkColor")); + style->setColor(gSavedSettings.getColor4("HTMLAgentColor")); } } diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index f265321106..81dd368037 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -53,6 +53,7 @@ #include "llglheaders.h" #include "lldrawpoolterrain.h" #include "lldrawable.h" +#include "hippogridmanager.h" extern LLPipeline gPipeline; extern bool gShiftFrame; @@ -71,7 +72,6 @@ LLSurface::LLSurface(U32 type, LLViewerRegion *regionp) : mGridsPerEdge(0), mOOGridsPerEdge(0.f), mPatchesPerEdge(0), - mNumberOfPatches(0), mType(type), mDetailTextureScale(0.f), mOriginGlobal(0.0, 0.0, 0.0), @@ -86,9 +86,6 @@ LLSurface::LLSurface(U32 type, LLViewerRegion *regionp) : mSurfaceZ = NULL; mNorm = NULL; - // Patch data - mPatchList = NULL; - // One of each for each camera mVisiblePatchCount = 0; @@ -119,7 +116,6 @@ LLSurface::~LLSurface() mGridsPerEdge = 0; mGridsPerPatchEdge = 0; mPatchesPerEdge = 0; - mNumberOfPatches = 0; destroyPatchData(); LLDrawPoolTerrain *poolp = (LLDrawPoolTerrain*) gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep); @@ -167,10 +163,9 @@ void LLSurface::create(const S32 grids_per_edge, mGridsPerEdge = grids_per_edge + 1; // Add 1 for the east and north buffer mOOGridsPerEdge = 1.f / mGridsPerEdge; mGridsPerPatchEdge = grids_per_patch_edge; - mPatchesPerEdge = (mGridsPerEdge - 1) / mGridsPerPatchEdge; - mNumberOfPatches = mPatchesPerEdge * mPatchesPerEdge; - mMetersPerGrid = width / ((F32)(mGridsPerEdge - 1)); - mMetersPerEdge = mMetersPerGrid * (mGridsPerEdge - 1); + mPatchesPerEdge = grids_per_edge / mGridsPerPatchEdge; + mMetersPerGrid = width / (F32)grids_per_edge; + mMetersPerEdge = mMetersPerGrid * grids_per_edge; // Aurora Sim sTextureSize = width; // Aurora Sim @@ -310,14 +305,13 @@ void LLSurface::setOriginGlobal(const LLVector3d &origin_global) { LLVector3d new_origin_global; mOriginGlobal = origin_global; - LLSurfacePatch *patchp; S32 i, j; // Need to update the southwest corners of the patches for (j=0; jgetOriginGlobal(); @@ -369,383 +363,154 @@ void LLSurface::getNeighboringRegionsStatus( std::vector& regions ) } } -void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction) +void LLSurface::connectNeighbor(LLSurface* neighborp, U32 direction) { - S32 i; - LLSurfacePatch *patchp, *neighbor_patchp; -// Aurora Sim - S32 neighborPatchesPerEdge = neighborp->mPatchesPerEdge; -// Aurora Sim - - mNeighbors[direction] = neighborp; - neighborp->mNeighbors[gDirOpposite[direction]] = this; - -// Aurora Sim - S32 ppe[2]; - S32 own_offset[2] = {0, 0}; - S32 neighbor_offset[2] = {0, 0}; - U32 own_xpos, own_ypos, neighbor_xpos, neighbor_ypos; - - ppe[0] = (mPatchesPerEdge < neighborPatchesPerEdge) ? mPatchesPerEdge : neighborPatchesPerEdge; // used for x - ppe[1] = ppe[0]; // used for y - - from_region_handle(mRegionp->getHandle(), &own_xpos, &own_ypos); - from_region_handle(neighborp->getRegion()->getHandle(), &neighbor_xpos, &neighbor_ypos); - - if(own_ypos >= neighbor_ypos) + // Constraints: + // - Regions width must equal height + // - Region width divisible by mGridsPerPatchEdge (16) + // - Region can only neighbor one other per side and coner (8 total, N, S, E, W, NW, NE, SW, SE) + // - Non-power-of-2 regions should work here, but the rest of the viewer code will probably choke on them. + + surface_patch_ref patchp, neighbor_patchp; + if (mNeighbors[direction] == neighborp) { - neighbor_offset[1] = (own_ypos - neighbor_ypos) / mGridsPerPatchEdge; - ppe[1] = llmin(mPatchesPerEdge, neighborPatchesPerEdge-neighbor_offset[1]); + return; } - else + if (mNeighbors[direction]) { - own_offset[1] = (neighbor_ypos - own_ypos) / mGridsPerPatchEdge; - ppe[1] = llmin(mPatchesPerEdge-own_offset[1], neighborPatchesPerEdge); + mNeighbors[direction]->disconnectNeighbor(this, gDirOpposite[direction]); } + mNeighbors[direction] = neighborp; - if(own_xpos >= neighbor_xpos) - { - neighbor_offset[0] = (own_xpos - neighbor_xpos) / mGridsPerPatchEdge; - ppe[0] = llmin(mPatchesPerEdge, neighborPatchesPerEdge-neighbor_offset[0]); - } - else - { - own_offset[0] = (neighbor_xpos - own_xpos) / mGridsPerPatchEdge; - ppe[0] = llmin(mPatchesPerEdge-own_offset[0], neighborPatchesPerEdge); - } -// Aurora Sim + const S32 max_idx = mPatchesPerEdge - 1; + const S32 neighbor_max_idx = neighborp->mPatchesPerEdge - 1; // Connect patches - if (NORTHEAST == direction) - { - patchp = getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1); -// Aurora Sim - //neighbor_patchp = neighborp->getPatch(0, 0); - neighbor_patchp = neighborp->getPatch(neighbor_offset[0], neighbor_offset[1]); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - patchp->updateNorthEdge(); // Only update one of north or east. - patchp->dirtyZ(); - } - else if (NORTHWEST == direction) - { -// Aurora Sim - S32 off = mPatchesPerEdge + neighbor_offset[1] - own_offset[1]; -// Aurora Sim - patchp = getPatch(0, mPatchesPerEdge - 1); -// Aurora Sim - //neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, 0); - neighbor_patchp = neighborp->getPatch(neighbor_offset[0] - 1, off); //neighborPatchesPerEdge - 1 - if (!neighbor_patchp) - { - mNeighbors[direction] = NULL; - return; - } -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - } - else if (SOUTHWEST == direction) - { - patchp = getPatch(0, 0); -// Aurora Sim - //neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(neighbor_offset[0] - 1, neighbor_offset[1] - 1); - if (!neighbor_patchp) - { - mNeighbors[direction] = NULL; - return; - } -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - -// Aurora Sim - //neighbor_patchp->updateNorthEdge(); // Only update one of north or east. - neighbor_patchp->updateEastEdge(); // Only update one of north or east. -// Aurora Sim - neighbor_patchp->dirtyZ(); - } - else if (SOUTHEAST == direction) - { -// Aurora Sim - S32 off = mPatchesPerEdge + neighbor_offset[0] - own_offset[0]; -// Aurora Sim - - patchp = getPatch(mPatchesPerEdge - 1, 0); -// Aurora Sim - //neighbor_patchp = neighborp->getPatch(0, mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(off, neighbor_offset[1] - 1); //0 - if (!neighbor_patchp) - { - mNeighbors[direction] = NULL; - return; - } -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - } - else if (EAST == direction) - { - // Do east/west connections, first -// Aurora Sim - //for (i = 0; i < (S32)mPatchesPerEdge; i++) - for (i = 0; i < ppe[1]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(mPatchesPerEdge - 1, i); - //neighbor_patchp = neighborp->getPatch(0, i); - patchp = getPatch(mPatchesPerEdge - 1, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(0, i + neighbor_offset[1]); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - patchp->updateEastEdge(); - patchp->dirtyZ(); - } - - // Now do northeast/southwest connections -// Aurora Sim - //for (i = 0; i < (S32)mPatchesPerEdge - 1; i++) - for (i = 0; i < ppe[1] - 1; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(mPatchesPerEdge - 1, i); - //neighbor_patchp = neighborp->getPatch(0, i+1); - patchp = getPatch(mPatchesPerEdge - 1, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(0, i+1 + neighbor_offset[1]); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, NORTHEAST); - neighbor_patchp->connectNeighbor(patchp, SOUTHWEST); - } - // Now do southeast/northwest connections -// Aurora Sim - //for (i = 1; i < (S32)mPatchesPerEdge; i++) - for (i = 1; i < ppe[1]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(mPatchesPerEdge - 1, i); - //neighbor_patchp = neighborp->getPatch(0, i-1); - patchp = getPatch(mPatchesPerEdge - 1, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(0, i-1 + neighbor_offset[1]); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, SOUTHEAST); - neighbor_patchp->connectNeighbor(patchp, NORTHWEST); - } - } - else if (NORTH == direction) + if (direction >= 4) { - // Do north/south connections, first -// Aurora Sim - //for (i = 0; i < (S32)mPatchesPerEdge; i++) - for (i = 0; i < ppe[0]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(i, mPatchesPerEdge - 1); - //neighbor_patchp = neighborp->getPatch(i, 0); - patchp = getPatch(i + own_offset[0], mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(i + neighbor_offset[0], 0); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - patchp->updateNorthEdge(); - patchp->dirtyZ(); - } - - // Do northeast/southwest connections -// Aurora Sim - //for (i = 0; i < (S32)mPatchesPerEdge - 1; i++) - for (i = 0; i < ppe[0] - 1; i++) -// Aurora Sim + // Corner stitch + S32 patches[4][2] = { + {max_idx, max_idx}, //NORTHEAST + {0, max_idx}, //NORTHWEST + {0, 0}, //SOUTHWEST + {max_idx, 0}, //SOUTHEAST + }; + const S32* p = patches[direction - 4]; + surface_patch_ref patchp = getPatch(p[0], p[1]); + patchp->connectNeighbor(neighborp->getPatch(max_idx - p[0], max_idx - p[1]), direction); + if (NORTHEAST == direction) { -// Aurora Sim - //patchp = getPatch(i, mPatchesPerEdge - 1); - //neighbor_patchp = neighborp->getPatch(i+1, 0); - patchp = getPatch(i + own_offset[0], mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(i+1 + neighbor_offset[0], 0); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, NORTHEAST); - neighbor_patchp->connectNeighbor(patchp, SOUTHWEST); - } - // Do southeast/northwest connections -// Aurora Sim - //for (i = 1; i < (S32)mPatchesPerEdge; i++) - for (i = 1; i < ppe[0]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(i, mPatchesPerEdge - 1); - //neighbor_patchp = neighborp->getPatch(i-1, 0); - patchp = getPatch(i + own_offset[0], mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(i-1 + neighbor_offset[0], 0); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, NORTHWEST); - neighbor_patchp->connectNeighbor(patchp, SOUTHEAST); + patchp->updateNorthEdge(); // Only update one of north or east. + if (patchp->dirtyZ()) + { + dirtySurfacePatch(patchp); + } } - } - else if (WEST == direction) +} + else { - // Do east/west connections, first -// Aurora Sim - //for (i = 0; i < mPatchesPerEdge; i++) - for (i = 0; i < ppe[1]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(0, i); - //neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i); - patchp = getPatch(0, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(neighborPatchesPerEdge - 1, i + neighbor_offset[1]); - if (!neighbor_patchp) continue; -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - neighbor_patchp->updateEastEdge(); - neighbor_patchp->dirtyZ(); - } - - // Now do northeast/southwest connections -// Aurora Sim - //for (i = 1; i < mPatchesPerEdge; i++) - for (i = 1; i < ppe[1]; i++) -// Aurora Sim + // Edge stitch + // Aurora complicates this logic. + U32 pos[2][2] = { {0,0},{0,0} }; + from_region_handle(mRegionp->getHandle(), &pos[0][0], &pos[0][1]); + from_region_handle(neighborp->getRegion()->getHandle(), &pos[1][0], &pos[1][1]); + S32 width[2] = { (S32)mRegionp->getWidth(), (S32)neighborp->getRegion()->getWidth() }; + U32 mins[2] = { llmax(pos[0][0], pos[1][0]), llmax(pos[0][1], pos[1][1]) }; + U32 maxs[2] = { llmin(pos[0][0] + width[0], pos[1][0] + width[1]), llmin(pos[0][1] + width[0], pos[1][1] + width[1]) }; + S32 start[2][2] = { + {S32((mins[0] - pos[0][0]) / mGridsPerPatchEdge) - 1, S32((mins[1] - pos[0][1]) / mGridsPerPatchEdge) - 1}, + {S32((mins[0] - pos[1][0]) / neighborp->mGridsPerPatchEdge) - 1,S32((mins[1] - pos[1][1]) / neighborp->mGridsPerPatchEdge) - 1} + }; + + S32 end[2] = { llmin(S32((maxs[0] - pos[0][0]) / mGridsPerPatchEdge), max_idx), llmin(S32((maxs[1] - pos[0][1]) / mGridsPerPatchEdge), max_idx) }; + const U32& neighbor_direction = gDirOpposite[direction]; + S32 stride[4][4][2] = { + {{0, 1}, {max_idx, 0}, {neighbor_max_idx, 0}, {NORTHEAST, SOUTHEAST}}, //EAST + {{1, 0}, {0, max_idx}, {0, neighbor_max_idx}, {NORTHEAST, NORTHWEST} }, //NORTH + {{0, 1}, {0, 0}, {0, 0}, {NORTHWEST, SOUTHWEST}}, //WEST + {{1, 0}, {0, 0}, {0, 0}, {SOUTHEAST, SOUTHWEST}} //SOUTH + }; + const S32 offs[2][2] = { + {stride[direction][0][0], stride[direction][0][1]}, + {stride[neighbor_direction][0][0], stride[neighbor_direction][0][1]} + }; + + S32 x[2], y[2]; + x[0] = stride[direction][1][0] + offs[0][0] * start[0][0]; + y[0] = stride[direction][1][1] + offs[0][1] * start[0][1]; + x[1] = stride[neighbor_direction][2][0] + offs[1][0] * start[1][0]; + y[1] = stride[neighbor_direction][2][1] + offs[1][1] * start[1][1]; + + for ( + x[0] = stride[direction][1][0] + offs[0][0] * start[0][0], + y[0] = stride[direction][1][1] + offs[0][1] * start[0][1], + x[1] = stride[neighbor_direction][2][0] + offs[1][0] * start[1][0], + y[1] = stride[neighbor_direction][2][1] + offs[1][1] * start[1][1]; + (!offs[0][0] || x[0] <= end[0]) && (!offs[0][1] || (y[0] <= end[1])); + x[0] += offs[0][0], y[0] += offs[0][1], + x[1] += offs[1][0], y[1] += offs[1][1]) { -// Aurora Sim - //patchp = getPatch(0, i); - //neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i - 1); - patchp = getPatch(0, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(neighborPatchesPerEdge - 1, i - 1 + neighbor_offset[1]); - if (!neighbor_patchp) continue; -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, SOUTHWEST); - neighbor_patchp->connectNeighbor(patchp, NORTHEAST); - } - - // Now do northwest/southeast connections -// Aurora Sim - //for (i = 0; i < mPatchesPerEdge - 1; i++) - for (i = 0; i < ppe[1] - 1; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(0, i); - //neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i + 1); - patchp = getPatch(0, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(neighborPatchesPerEdge - 1, i + 1 + neighbor_offset[1]); - if (!neighbor_patchp) continue; -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, NORTHWEST); - neighbor_patchp->connectNeighbor(patchp, SOUTHEAST); + if (x[0] < 0 || y[0] < 0) { + continue; + } + surface_patch_ref patchp = getPatch(x[0], y[0]); + // diagonal stitch 1 + if ((offs[1][0] > 0 && x[1] > 0) || (offs[1][1] > 0 && y[1] > 0)) + { + patchp->connectNeighbor(neighborp->getPatch(x[1] - offs[1][0], y[1] - offs[1][1]), stride[direction][3][1]); + } + // edge stitch + if (x[1] >= 0 && y[1] >= 0 && x[1] <= neighbor_max_idx && y[1] <= neighbor_max_idx) + { + patchp->connectNeighbor(neighborp->getPatch(x[1], y[1]), direction); + } + // diagonal stitch 2 + if (x[1] + offs[1][0] <= neighbor_max_idx && y[1] + offs[1][1] <= neighbor_max_idx) + { + patchp->connectNeighbor(neighborp->getPatch(x[1] + offs[1][0], y[1] + offs[1][1]), stride[direction][3][0]); + } + if (direction == EAST) + { + patchp->updateEastEdge(); + if (patchp->dirtyZ()) + { + dirtySurfacePatch(patchp); + } + } + else if (direction == NORTH) + { + patchp->updateNorthEdge(); + if (patchp->dirtyZ()) + { + dirtySurfacePatch(patchp); + } + } } } - else if (SOUTH == direction) - { - // Do north/south connections, first -// Aurora Sim - //for (i = 0; i < mPatchesPerEdge; i++) - for (i = 0; i < ppe[0]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(i, 0); - //neighbor_patchp = neighborp->getPatch(i, mPatchesPerEdge - 1); - patchp = getPatch(i + own_offset[0], 0); - neighbor_patchp = neighborp->getPatch(i + neighbor_offset[0], neighborPatchesPerEdge - 1); - if (!neighbor_patchp) continue; -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - neighbor_patchp->updateNorthEdge(); - neighbor_patchp->dirtyZ(); - } - - // Now do northeast/southwest connections -// Aurora Sim - //for (i = 1; i < mPatchesPerEdge; i++) - for (i = 1; i < ppe[0]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(i, 0); - //neighbor_patchp = neighborp->getPatch(i - 1, mPatchesPerEdge - 1); - patchp = getPatch(i + own_offset[0], 0); - neighbor_patchp = neighborp->getPatch(i - 1 + neighbor_offset[0], neighborPatchesPerEdge - 1); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, SOUTHWEST); - neighbor_patchp->connectNeighbor(patchp, NORTHEAST); - } - // Now do northeast/southwest connections -// Aurora Sim - //for (i = 0; i < mPatchesPerEdge - 1; i++) - for (i = 0; i < ppe[0] - 1; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(i, 0); - //neighbor_patchp = neighborp->getPatch(i + 1, mPatchesPerEdge - 1); - patchp = getPatch(i + own_offset[0], 0); - neighbor_patchp = neighborp->getPatch(i + 1 + neighbor_offset[0], neighborPatchesPerEdge - 1); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, SOUTHEAST); - neighbor_patchp->connectNeighbor(patchp, NORTHWEST); - } - } } -void LLSurface::disconnectNeighbor(LLSurface *surfacep) +void LLSurface::disconnectNeighbor(LLSurface* surfacep, U32 direction) { - S32 i; - for (i = 0; i < 8; i++) + if (surfacep && surfacep == mNeighbors[direction]) { - if (surfacep == mNeighbors[i]) + mNeighbors[direction] = NULL; + for (auto& patchp : mPatchList) { - mNeighbors[i] = NULL; + patchp->disconnectNeighbor(surfacep); } } - - // Iterate through surface patches, removing any connectivity to removed surface. - for (i = 0; i < mNumberOfPatches; i++) - { - (mPatchList + i)->disconnectNeighbor(surfacep); - } } void LLSurface::disconnectAllNeighbors() { - S32 i; - for (i = 0; i < 8; i++) + for (size_t i = 0; i < mNeighbors.size(); ++i) { - if (mNeighbors[i]) + auto& neighbor = mNeighbors[i]; + if (neighbor) { - mNeighbors[i]->disconnectNeighbor(this); - mNeighbors[i] = NULL; + neighbor->disconnectNeighbor(this, gDirOpposite[i]); + neighbor = NULL; } } } @@ -801,13 +566,9 @@ void LLSurface::updatePatchVisibilities(LLAgent &agent) LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(gAgentCamera.getCameraPositionGlobal()); - LLSurfacePatch *patchp; - mVisiblePatchCount = 0; - for (S32 i=0; iupdateVisibility(); if (patchp->getVisible()) { @@ -831,19 +592,29 @@ BOOL LLSurface::idleUpdate(F32 max_update_time) // If the Z height data has changed, we need to rebuild our // property line vertex arrays. - if (mDirtyPatchList.size() > 0) + if (!mDirtyPatchList.empty()) { getRegion()->dirtyHeights(); } // Always call updateNormals() / updateVerticalStats() // every frame to avoid artifacts - for(std::set::iterator iter = mDirtyPatchList.begin(); - iter != mDirtyPatchList.end(); ) + for (auto it = mDirtyPatchList.cbegin(); it != mDirtyPatchList.cend();) { - std::set::iterator curiter = iter++; - LLSurfacePatch *patchp = *curiter; - patchp->updateNormals(); + if (it->second.expired()) + { + LL_WARNS() << "Expired dirty patch detected. Side " << it->first << LL_ENDL; + } + surface_patch_ref patchp = it->second.lock(); + if (!patchp) + { + it = mDirtyPatchList.erase(it); + continue; + } + if (patchp->updateNormals()) + { + patchp->getSurface()->dirtySurfacePatch(patchp); + } patchp->updateVerticalStats(); if (max_update_time == 0.f || update_timer.getElapsedTimeF32() < max_update_time) { @@ -851,9 +622,11 @@ BOOL LLSurface::idleUpdate(F32 max_update_time) { did_update = TRUE; patchp->clearDirty(); - mDirtyPatchList.erase(curiter); + it = mDirtyPatchList.erase(it); + continue; } } + ++it; } return did_update; } @@ -864,7 +637,6 @@ void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL LLPatchHeader ph; S32 j, i; S32 patch[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE]; - LLSurfacePatch *patchp; init_patch_decompressor(gopp->patch_size); gopp->stride = mGridsPerEdge; @@ -911,8 +683,7 @@ void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL return; } - patchp = &mPatchList[j*mPatchesPerEdge + i]; - + const surface_patch_ref& patchp = mPatchList[j * mPatchesPerEdge + i]; decode_patch(bitpack, patch); decompress_patch(patchp->getDataZ(), patch, &ph); @@ -920,22 +691,26 @@ void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL // Update edges for neighbors. Need to guarantee that this gets done before we generate vertical stats. patchp->updateNorthEdge(); patchp->updateEastEdge(); - if (patchp->getNeighborPatch(WEST)) + LLSurfacePatch* neighborPatch; + if (neighborPatch = patchp->getNeighborPatch(WEST)) { - patchp->getNeighborPatch(WEST)->updateEastEdge(); + neighborPatch->updateEastEdge(); } - if (patchp->getNeighborPatch(SOUTHWEST)) + if (neighborPatch = patchp->getNeighborPatch(SOUTHWEST)) { - patchp->getNeighborPatch(SOUTHWEST)->updateEastEdge(); - patchp->getNeighborPatch(SOUTHWEST)->updateNorthEdge(); + neighborPatch->updateEastEdge(); + neighborPatch->updateNorthEdge(); } - if (patchp->getNeighborPatch(SOUTH)) + if (neighborPatch = patchp->getNeighborPatch(SOUTH)) { - patchp->getNeighborPatch(SOUTH)->updateNorthEdge(); + neighborPatch->updateNorthEdge(); } // Dirty patch statistics, and flag that the patch has data. - patchp->dirtyZ(); + if (patchp->dirtyZ()) + { + dirtySurfacePatch(patchp); + } patchp->setHasReceivedData(); } } @@ -1088,8 +863,13 @@ LLVector3 LLSurface::resolveNormalGlobal(const LLVector3d& pos_global) const } -LLSurfacePatch *LLSurface::resolvePatchRegion(const F32 x, const F32 y) const +const surface_patch_ref& LLSurface::resolvePatchRegion(const F32 x, const F32 y) const { + if (mPatchList.empty()) { + LL_WARNS() << "No patches for current region!" << LL_ENDL; + static surface_patch_ref empty; + return empty; + } // x and y should be region-local coordinates. // If x and y are outside of the surface, then the returned // index will be for the nearest boundary patch. @@ -1140,29 +920,24 @@ LLSurfacePatch *LLSurface::resolvePatchRegion(const F32 x, const F32 y) const // *NOTE: Super paranoia code follows. S32 index = i + j * mPatchesPerEdge; - if((index < 0) || (index >= mNumberOfPatches)) + if((index < 0) || (index >= mPatchList.size())) { - if(0 == mNumberOfPatches) - { - LL_WARNS() << "No patches for current region!" << LL_ENDL; - return NULL; - } S32 old_index = index; - index = llclamp(old_index, 0, (mNumberOfPatches - 1)); + index = llclamp(old_index, 0, ((S32)mPatchList.size() - 1)); LL_WARNS() << "Clamping out of range patch index " << old_index << " to " << index << LL_ENDL; } - return &(mPatchList[index]); + return mPatchList[index]; } -LLSurfacePatch *LLSurface::resolvePatchRegion(const LLVector3 &pos_region) const +const surface_patch_ref& LLSurface::resolvePatchRegion(const LLVector3 &pos_region) const { return resolvePatchRegion(pos_region.mV[VX], pos_region.mV[VY]); } -LLSurfacePatch *LLSurface::resolvePatchGlobal(const LLVector3d &pos_global) const +const surface_patch_ref& LLSurface::resolvePatchGlobal(const LLVector3d &pos_global) const { llassert(mRegionp); LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(pos_global); @@ -1191,37 +966,28 @@ void LLSurface::createPatchData() // Assumes mGridsPerEdge, mGridsPerPatchEdge, and mPatchesPerEdge have been properly set // TODO -- check for create() called when surface is not empty S32 i, j; - LLSurfacePatch *patchp; // Allocate memory - mPatchList = new LLSurfacePatch[mNumberOfPatches]; - - // One of each for each camera - mVisiblePatchCount = mNumberOfPatches; - - for (j=0; jsetSurface(this); - } + mPatchList[i] = std::make_shared(this, i); } + // One of each for each camera + mVisiblePatchCount = mPatchList.size(); + for (j=0; jmHasReceivedData = FALSE; - patchp->mSTexUpdate = TRUE; + const auto& patchp = getPatch(i, j); S32 data_offset = i * mGridsPerPatchEdge + j * mGridsPerPatchEdge * mGridsPerEdge; patchp->setDataZ(mSurfaceZ + data_offset); patchp->setDataNorm(mNorm + data_offset); - // We make each patch point to its neighbors so we can do resolution checking // when butting up different resolutions. Patches that don't have neighbors // somewhere will point to NULL on that side. @@ -1310,9 +1076,7 @@ void LLSurface::createPatchData() void LLSurface::destroyPatchData() { // Delete all of the cached patch data for these patches. - - delete [] mPatchList; - mPatchList = NULL; + mPatchList.clear(); mVisiblePatchCount = 0; } @@ -1335,36 +1099,50 @@ U32 LLSurface::getRenderStride(const U32 render_level) const } -LLSurfacePatch *LLSurface::getPatch(const S32 x, const S32 y) const +const surface_patch_ref& LLSurface::getPatch(const S32 x, const S32 y) const { + static surface_patch_ref empty(nullptr); if ((x < 0) || (x >= mPatchesPerEdge)) { LL_WARNS() << "Asking for patch out of bounds" << LL_ENDL; - return NULL; + return empty; } if ((y < 0) || (y >= mPatchesPerEdge)) { LL_WARNS() << "Asking for patch out of bounds" << LL_ENDL; - return NULL; + return empty; } - return mPatchList + x + y*mPatchesPerEdge; + return mPatchList[x + y*mPatchesPerEdge]; } void LLSurface::dirtyAllPatches() { - S32 i; - for (i = 0; i < mNumberOfPatches; i++) + for (auto& patchp : mPatchList) { - mPatchList[i].dirtyZ(); + if (patchp->dirtyZ()) + { + dirtySurfacePatch(patchp); + } } } -void LLSurface::dirtySurfacePatch(LLSurfacePatch *patchp) +void LLSurface::dirtySurfacePatch(const surface_patch_ref& patchp) { + if (!patchp) + { + return; + } + // Put surface patch on dirty surface patch list - mDirtyPatchList.insert(patchp); + if (std::find_if(mDirtyPatchList.begin(), mDirtyPatchList.end(), + [&patchp](std::pair >& entry) -> bool { + return entry.second.lock().get() == patchp.get(); + }) == mDirtyPatchList.end()) + { + mDirtyPatchList.push_back(std::make_pair(patchp->getSide(), patchp)); + } } diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h index aedac01a39..abc7785ad3 100644 --- a/indra/newview/llsurface.h +++ b/indra/newview/llsurface.h @@ -60,9 +60,12 @@ static const S32 ONE_LESS_THAN_NEIGHBOR = -1; const S32 ABOVE_WATERLINE_ALPHA = 32; // The alpha of water when the land elevation is above the waterline. class LLViewerRegion; -class LLSurfacePatch; class LLBitPack; class LLGroupHeader; +class LLSurfacePatch; + +typedef std::shared_ptr surface_patch_ref; +typedef std::weak_ptr surface_patch_weak_ref; class LLSurface { @@ -82,7 +85,7 @@ class LLSurface void setOriginGlobal(const LLVector3d &origin_global); void connectNeighbor(LLSurface *neighborp, U32 direction); - void disconnectNeighbor(LLSurface *neighborp); + void disconnectNeighbor(LLSurface *neighborp, U32 direction); void disconnectAllNeighbors(); // Aurora Sim @@ -111,9 +114,9 @@ class LLSurface F32 resolveHeightGlobal(const LLVector3d &position_global) const; LLVector3 resolveNormalGlobal(const LLVector3d& v) const; // Returns normal to surface - LLSurfacePatch *resolvePatchRegion(const F32 x, const F32 y) const; - LLSurfacePatch *resolvePatchRegion(const LLVector3 &position_region) const; - LLSurfacePatch *resolvePatchGlobal(const LLVector3d &position_global) const; + const surface_patch_ref& resolvePatchRegion(const F32 x, const F32 y) const; + const surface_patch_ref& resolvePatchRegion(const LLVector3 &position_region) const; + const surface_patch_ref& resolvePatchGlobal(const LLVector3d &position_global) const; // Update methods (called during idle, normally) BOOL idleUpdate(F32 max_update_time); @@ -136,7 +139,7 @@ class LLSurface void dirtyAllPatches(); // Use this to dirty all patches when changing terrain parameters - void dirtySurfacePatch(LLSurfacePatch *patchp); + void dirtySurfacePatch(const surface_patch_ref& patchp); LLVOWater *getWaterObj() { return mWaterObjp; } static void setTextureSize(const S32 texture_size); @@ -155,8 +158,6 @@ class LLSurface F32 mOOGridsPerEdge; // Inverse of grids per edge S32 mPatchesPerEdge; // Number of patches on one side of a region - S32 mNumberOfPatches; // Total number of patches - // Each surface points at 8 neighbors (or NULL) // +---+---+---+ @@ -166,7 +167,7 @@ class LLSurface // +---+---+---+ // |SW | S | SE| // +---+---+---+ - LLSurface *mNeighbors[8]; // Adjacent patches + std::array mNeighbors; // Adjacent patches U32 mType; // Useful for identifying derived classes @@ -191,11 +192,11 @@ class LLSurface //F32 updateTexture(LLSurfacePatch *ppatch); - LLSurfacePatch *getPatch(const S32 x, const S32 y) const; + const surface_patch_ref& getPatch(const S32 x, const S32 y) const; protected: LLVector3d mOriginGlobal; // In absolute frame - LLSurfacePatch *mPatchList; // Array of all patches + std::vector< surface_patch_ref > mPatchList; // Array of all patches // Array of grid data, mGridsPerEdge * mGridsPerEdge F32 *mSurfaceZ; @@ -203,7 +204,7 @@ class LLSurface // Array of grid normals, mGridsPerEdge * mGridsPerEdge LLVector3 *mNorm; - std::set mDirtyPatchList; + std::vector< std::pair > mDirtyPatchList; // The textures should never be directly initialized - use the setter methods! diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 52727dd6c0..c999fff22f 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -44,12 +44,12 @@ #include "llperlin.h" extern bool gShiftFrame; -extern U64 gFrameTime; +extern U64MicrosecondsImplicit gFrameTime; extern LLPipeline gPipeline; -LLSurfacePatch::LLSurfacePatch() +LLSurfacePatch::LLSurfacePatch(LLSurface* surface, U32 side) : mHasReceivedData(FALSE), - mSTexUpdate(FALSE), + mSTexUpdate(TRUE), mDirty(FALSE), mDirtyZStats(TRUE), mHeightsGenerated(FALSE), @@ -70,17 +70,12 @@ LLSurfacePatch::LLSurfacePatch() // set to non-zero values by higher classes. mConnectedEdge(NO_EDGE), mLastUpdateTime(0), - mSurfacep(NULL) -{ - S32 i; - for (i = 0; i < 8; i++) - { - setNeighborPatch(i, NULL); - } - for (i = 0; i < 9; i++) - { - mNormalsInvalid[i] = TRUE; - } + mSurfacep(NULL), + mNeighborPatches{ 0,0,0,0,0,0,0,0 }, + mNormalsInvalid{ 1,1,1,1,1,1,1,1,1 }, + mSide(side) +{ + setSurface(surface); } @@ -90,7 +85,7 @@ LLSurfacePatch::~LLSurfacePatch() } -void LLSurfacePatch::dirty() +bool LLSurfacePatch::dirty() { // These are outside of the loop in case we're still waiting for a dirty from the // texture being updated... @@ -109,8 +104,9 @@ void LLSurfacePatch::dirty() if (!mDirty) { mDirty = TRUE; - mSurfacep->dirtySurfacePatch(this); + return true; } + return false; } @@ -133,45 +129,31 @@ void LLSurfacePatch::disconnectNeighbor(LLSurface *surfacep) U32 i; for (i = 0; i < 8; i++) { - if (getNeighborPatch(i)) + const auto& patch = getNeighborPatch(i); + if (patch) { - if (getNeighborPatch(i)->mSurfacep == surfacep) + if (patch->mSurfacep == surfacep) { + if (EAST == i) + { + mConnectedEdge &= EAST_EDGE; + } + else if (NORTH == i) + { + mConnectedEdge &= NORTH_EDGE; + } + else if (WEST == i) + { + mConnectedEdge &= WEST_EDGE; + } + else if (SOUTH == i) + { + mConnectedEdge &= SOUTH_EDGE; + } setNeighborPatch(i, NULL); - mNormalsInvalid[i] = TRUE; } } } - - // Clean up connected edges - if (getNeighborPatch(EAST)) - { - if (getNeighborPatch(EAST)->mSurfacep == surfacep) - { - mConnectedEdge &= ~EAST_EDGE; - } - } - if (getNeighborPatch(NORTH)) - { - if (getNeighborPatch(NORTH)->mSurfacep == surfacep) - { - mConnectedEdge &= ~NORTH_EDGE; - } - } - if (getNeighborPatch(WEST)) - { - if (getNeighborPatch(WEST)->mSurfacep == surfacep) - { - mConnectedEdge &= ~WEST_EDGE; - } - } - if (getNeighborPatch(SOUTH)) - { - if (getNeighborPatch(SOUTH)->mSurfacep == surfacep) - { - mConnectedEdge &= ~SOUTH_EDGE; - } - } } LLVector3 LLSurfacePatch::getPointAgent(const U32 x, const U32 y) const @@ -283,65 +265,66 @@ void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride) { for (j = 0; j < 2; j++) { + LLSurfacePatch* patch; if (poffsets[i][j][0] < 0) { - if (!ppatches[i][j]->getNeighborPatch(WEST)) + if (patch = ppatches[i][j]->getNeighborPatch(WEST)) { - poffsets[i][j][0] = 0; + // Aurora Sim + ppatches[i][j] = patch; + poffsets[i][j][0] += patch_width; + poffsets[i][j][2] = patch->getSurface()->getGridsPerEdge(); +// Aurora Sim } else { -// Aurora Sim - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(WEST); - poffsets[i][j][0] += patch_width; - poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge(); -// Aurora Sim + poffsets[i][j][0] = 0; } } if (poffsets[i][j][1] < 0) { - if (!ppatches[i][j]->getNeighborPatch(SOUTH)) - { - poffsets[i][j][1] = 0; - } - else + if (patch = ppatches[i][j]->getNeighborPatch(SOUTH)) { // Aurora Sim - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(SOUTH); + ppatches[i][j] = patch; poffsets[i][j][1] += patch_width; - poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge(); + poffsets[i][j][2] = patch->getSurface()->getGridsPerEdge(); // CR> Aurora Sim } + else + { + poffsets[i][j][1] = 0; + } } if (poffsets[i][j][0] >= (S32)patch_width) { - if (!ppatches[i][j]->getNeighborPatch(EAST)) - { - poffsets[i][j][0] = patch_width - 1; - } - else + if (patch = ppatches[i][j]->getNeighborPatch(EAST)) { // Aurora Sim - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(EAST); + ppatches[i][j] = patch; poffsets[i][j][0] -= patch_width; - poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge(); + poffsets[i][j][2] = patch->getSurface()->getGridsPerEdge(); // Aurora Sim } + else + { + poffsets[i][j][0] = patch_width - 1; + } } if (poffsets[i][j][1] >= (S32)patch_width) { - if (!ppatches[i][j]->getNeighborPatch(NORTH)) - { - poffsets[i][j][1] = patch_width - 1; - } - else + if (patch = ppatches[i][j]->getNeighborPatch(NORTH)) { // Aurora Sim - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(NORTH); + ppatches[i][j] = patch; poffsets[i][j][1] -= patch_width; - poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge(); + poffsets[i][j][2] = patch->getSurface()->getGridsPerEdge(); // Aurora Sim } + else + { + poffsets[i][j][1] = patch_width - 1; + } } } } @@ -474,11 +457,11 @@ void LLSurfacePatch::updateVerticalStats() } -void LLSurfacePatch::updateNormals() +bool LLSurfacePatch::updateNormals() { if (mSurfacep->mType == 'w') { - return; + return false; } U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); U32 grids_per_edge = mSurfacep->getGridsPerEdge(); @@ -515,10 +498,12 @@ void LLSurfacePatch::updateNormals() // update the west edge if (mNormalsInvalid[NORTHWEST] || mNormalsInvalid[WEST] || mNormalsInvalid[SOUTHWEST]) { + LLSurfacePatch* northwest_patchp = getNeighborPatch(NORTHWEST); + LLSurfacePatch* north_patchp = getNeighborPatch(NORTH); // Aurora Sim - if (!getNeighborPatch(NORTH) && getNeighborPatch(NORTHWEST) && getNeighborPatch(NORTHWEST)->getHasReceivedData()) + if (!north_patchp && northwest_patchp && northwest_patchp->getHasReceivedData()) { - *(mDataZ + grids_per_patch_edge*grids_per_edge) = *(getNeighborPatch(NORTHWEST)->mDataZ + grids_per_patch_edge); + *(mDataZ + grids_per_patch_edge*grids_per_edge) = *(northwest_patchp->mDataZ + grids_per_patch_edge); } // Aurora Sim @@ -533,10 +518,12 @@ void LLSurfacePatch::updateNormals() // update the south edge if (mNormalsInvalid[SOUTHWEST] || mNormalsInvalid[SOUTH] || mNormalsInvalid[SOUTHEAST]) { + LLSurfacePatch* southeast_patchp = getNeighborPatch(SOUTHEAST); + LLSurfacePatch* east_patchp = getNeighborPatch(EAST); // Aurora Sim - if (!getNeighborPatch(EAST) && getNeighborPatch(SOUTHEAST) && getNeighborPatch(SOUTHEAST)->getHasReceivedData()) + if (!east_patchp && southeast_patchp && southeast_patchp->getHasReceivedData()) { - *(mDataZ + grids_per_patch_edge) = *(getNeighborPatch(SOUTHEAST)->mDataZ + grids_per_patch_edge * getNeighborPatch(SOUTHEAST)->getSurface()->getGridsPerEdge()); + *(mDataZ + grids_per_patch_edge) = *(southeast_patchp->mDataZ + grids_per_patch_edge * southeast_patchp->getSurface()->getGridsPerEdge()); } // Aurora Sim @@ -552,11 +539,14 @@ void LLSurfacePatch::updateNormals() // we'll want to do different things. if (mNormalsInvalid[NORTHEAST]) { - if (!getNeighborPatch(NORTHEAST)) + LLSurfacePatch* northeast_patchp = getNeighborPatch(NORTHEAST); + LLSurfacePatch* north_patchp = getNeighborPatch(NORTH); + LLSurfacePatch* east_patchp = getNeighborPatch(EAST); + if (!northeast_patchp) { - if (!getNeighborPatch(NORTH)) + if (!north_patchp) { - if (!getNeighborPatch(EAST)) + if (!east_patchp) { // No north or east neighbors. Pull from the diagonal in your own patch. *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = @@ -564,13 +554,13 @@ void LLSurfacePatch::updateNormals() } else { - if (getNeighborPatch(EAST)->getHasReceivedData()) + if (east_patchp->getHasReceivedData()) { // East, but not north. Pull from your east neighbor's northwest point. *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = // Aurora Sim //*(getNeighborPatch(EAST)->mDataZ + (grids_per_patch_edge - 1)*grids_per_edge); - *(getNeighborPatch(EAST)->mDataZ + (getNeighborPatch(EAST)->getSurface()->getGridsPerPatchEdge() - 1)*getNeighborPatch(EAST)->getSurface()->getGridsPerEdge()); + *(east_patchp->mDataZ + (east_patchp->getSurface()->getGridsPerPatchEdge() - 1)* east_patchp->getSurface()->getGridsPerEdge()); // Aurora Sim } else @@ -583,7 +573,7 @@ void LLSurfacePatch::updateNormals() else { // We have a north. - if (getNeighborPatch(EAST)) + if (east_patchp) { // North and east neighbors, but not northeast. // Pull from diagonal in your own patch. @@ -592,13 +582,13 @@ void LLSurfacePatch::updateNormals() } else { - if (getNeighborPatch(NORTH)->getHasReceivedData()) + if (north_patchp->getHasReceivedData()) { // North, but not east. Pull from your north neighbor's southeast corner. *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = // Aurora Sim //*(getNeighborPatch(NORTH)->mDataZ + (grids_per_patch_edge - 1)); - *(getNeighborPatch(NORTH)->mDataZ + (getNeighborPatch(NORTH)->getSurface()->getGridsPerPatchEdge() - 1)); + *(north_patchp->mDataZ + (north_patchp->getSurface()->getGridsPerPatchEdge() - 1)); // Aurora Sim } else @@ -609,25 +599,25 @@ void LLSurfacePatch::updateNormals() } } } - else if (getNeighborPatch(NORTHEAST)->mSurfacep != mSurfacep) + else if (northeast_patchp->mSurfacep != mSurfacep) { if ( - (!getNeighborPatch(NORTH) || (getNeighborPatch(NORTH)->mSurfacep != mSurfacep)) + (!north_patchp || (north_patchp->mSurfacep != mSurfacep)) && - (!getNeighborPatch(EAST) || (getNeighborPatch(EAST)->mSurfacep != mSurfacep))) + (!east_patchp || (east_patchp->mSurfacep != mSurfacep))) { // Aurora Sim U32 own_xpos, own_ypos, neighbor_xpos, neighbor_ypos; S32 own_offset = 0, neighbor_offset = 0; from_region_handle(mSurfacep->getRegion()->getHandle(), &own_xpos, &own_ypos); - from_region_handle(getNeighborPatch(NORTHEAST)->mSurfacep->getRegion()->getHandle(), &neighbor_xpos, &neighbor_ypos); + from_region_handle(northeast_patchp->mSurfacep->getRegion()->getHandle(), &neighbor_xpos, &neighbor_ypos); if (own_ypos >= neighbor_ypos) neighbor_offset = own_ypos - neighbor_ypos; else own_offset = neighbor_ypos - own_ypos; *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = - *(getNeighborPatch(NORTHEAST)->mDataZ + (grids_per_edge + neighbor_offset - own_offset - 1) * getNeighborPatch(NORTHEAST)->getSurface()->getGridsPerEdge()); + *(northeast_patchp->mDataZ + (grids_per_edge + neighbor_offset - own_offset - 1) * northeast_patchp->getSurface()->getGridsPerEdge()); // Aurora Sim } } @@ -656,15 +646,12 @@ void LLSurfacePatch::updateNormals() dirty_patch = TRUE; } - if (dirty_patch) - { - mSurfacep->dirtySurfacePatch(this); - } - for (i = 0; i < 9; i++) { mNormalsInvalid[i] = FALSE; } + + return dirty_patch; } void LLSurfacePatch::updateEastEdge() @@ -719,7 +706,8 @@ void LLSurfacePatch::updateNorthEdge() U32 i; F32 *south_surface, *north_surface; - if (!getNeighborPatch(NORTH)) + LLSurfacePatch* patchp = getNeighborPatch(NORTH); + if (!patchp) { south_surface = mDataZ + grids_per_patch_edge*grids_per_edge; north_surface = mDataZ + (grids_per_patch_edge - 1) * grids_per_edge; @@ -727,7 +715,7 @@ void LLSurfacePatch::updateNorthEdge() else if (mConnectedEdge & NORTH_EDGE) { south_surface = mDataZ + grids_per_patch_edge*grids_per_edge; - north_surface = getNeighborPatch(NORTH)->mDataZ; + north_surface = patchp->mDataZ; } else { @@ -748,10 +736,11 @@ BOOL LLSurfacePatch::updateTexture() F32 meters_per_grid = getSurface()->getMetersPerGrid(); F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge(); - if ((!getNeighborPatch(EAST) || getNeighborPatch(EAST)->getHasReceivedData()) - && (!getNeighborPatch(WEST) || getNeighborPatch(WEST)->getHasReceivedData()) - && (!getNeighborPatch(SOUTH) || getNeighborPatch(SOUTH)->getHasReceivedData()) - && (!getNeighborPatch(NORTH) || getNeighborPatch(NORTH)->getHasReceivedData())) + LLSurfacePatch* patchp; + if ((!(patchp = getNeighborPatch(EAST)) || patchp->getHasReceivedData()) + && (!(patchp = getNeighborPatch(WEST)) || patchp->getHasReceivedData()) + && (!(patchp = getNeighborPatch(SOUTH)) || patchp->getHasReceivedData()) + && (!(patchp = getNeighborPatch(NORTH)) || patchp->getHasReceivedData())) { LLViewerRegion *regionp = getSurface()->getRegion(); LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal(); @@ -813,7 +802,7 @@ void LLSurfacePatch::updateGL() } } -void LLSurfacePatch::dirtyZ() +bool LLSurfacePatch::dirtyZ() { mSTexUpdate = TRUE; @@ -827,20 +816,36 @@ void LLSurfacePatch::dirtyZ() // Invalidate normals in this and neighboring patches for (i = 0; i < 8; i++) { - if (getNeighborPatch(i)) + if (mNeighborPatches[i] == nullptr) { - getNeighborPatch(i)->mNormalsInvalid[gDirOpposite[i]] = TRUE; - getNeighborPatch(i)->dirty(); + continue; + } + if (mNeighborPatches[i]->expired()) + { + LL_WARNS() << "Expired neighbor patch detected. Side " << i << LL_ENDL; + delete mNeighborPatches[i]; + mNeighborPatches[i] = nullptr; + continue; + } + const surface_patch_ref& patchp = mNeighborPatches[i]->lock(); + if (patchp) + { + patchp->mNormalsInvalid[gDirOpposite[i]] = TRUE; + if (patchp->dirty()) + { + patchp->getSurface()->dirtySurfacePatch(patchp); + } if (i < 4) { - getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][0]] = TRUE; - getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][1]] = TRUE; + patchp->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][0]] = TRUE; + patchp->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][1]] = TRUE; } } } - dirty(); mLastUpdateTime = gFrameTime; + + return dirty(); } @@ -877,35 +882,29 @@ void LLSurfacePatch::setOriginGlobal(const LLVector3d &origin_global) } -void LLSurfacePatch::connectNeighbor(LLSurfacePatch *neighbor_patchp, const U32 direction) +void LLSurfacePatch::connectNeighbor(const surface_patch_ref& neighbor_patchp, const U32 direction) { llassert(neighbor_patchp); if (!neighbor_patchp) return; mNormalsInvalid[direction] = TRUE; - neighbor_patchp->mNormalsInvalid[gDirOpposite[direction]] = TRUE; setNeighborPatch(direction, neighbor_patchp); - neighbor_patchp->setNeighborPatch(gDirOpposite[direction], this); if (EAST == direction) { mConnectedEdge |= EAST_EDGE; - neighbor_patchp->mConnectedEdge |= WEST_EDGE; } else if (NORTH == direction) { mConnectedEdge |= NORTH_EDGE; - neighbor_patchp->mConnectedEdge |= SOUTH_EDGE; } else if (WEST == direction) { mConnectedEdge |= WEST_EDGE; - neighbor_patchp->mConnectedEdge |= EAST_EDGE; } else if (SOUTH == direction) { mConnectedEdge |= SOUTH_EDGE; - neighbor_patchp->mConnectedEdge |= NORTH_EDGE; } } @@ -963,13 +962,14 @@ void LLSurfacePatch::updateVisibility() if (mVObjp) { mVObjp->dirtyGeom(); - if (getNeighborPatch(WEST)) + LLSurfacePatch* patchp; + if (patchp = getNeighborPatch(WEST)) { - getNeighborPatch(WEST)->mVObjp->dirtyGeom(); + patchp->mVObjp->dirtyGeom(); } - if (getNeighborPatch(SOUTH)) + if (patchp = getNeighborPatch(SOUTH)) { - getNeighborPatch(SOUTH)->mVObjp->dirtyGeom(); + patchp->mVObjp->dirtyGeom(); } } } @@ -1074,9 +1074,21 @@ F32 LLSurfacePatch::getMaxComposition() const return mMaxComposition; } -void LLSurfacePatch::setNeighborPatch(const U32 direction, LLSurfacePatch *neighborp) +void LLSurfacePatch::setNeighborPatch(const U32 direction, const surface_patch_ref& neighborp) { - mNeighborPatches[direction] = neighborp; + if (!neighborp) + { + delete mNeighborPatches[direction]; + mNeighborPatches[direction] = nullptr; + } + else + { + if (mNeighborPatches[direction] == nullptr) + { + mNeighborPatches[direction] = new surface_patch_weak_ref(); + } + *mNeighborPatches[direction] = neighborp; + } mNormalsInvalid[direction] = TRUE; if (direction < 4) { @@ -1087,7 +1099,15 @@ void LLSurfacePatch::setNeighborPatch(const U32 direction, LLSurfacePatch *neigh LLSurfacePatch *LLSurfacePatch::getNeighborPatch(const U32 direction) const { - return mNeighborPatches[direction]; + if (mNeighborPatches[direction] == nullptr) + { + return nullptr; + } + else if (mNeighborPatches[direction]->expired()) + { + LL_WARNS() << "Expired neighbor patch detected. Side " << direction << LL_ENDL; + } + return mNeighborPatches[direction]->lock().get(); } void LLSurfacePatch::clearVObj() diff --git a/indra/newview/llsurfacepatch.h b/indra/newview/llsurfacepatch.h index ebfb64c1d8..8d6447e7f9 100644 --- a/indra/newview/llsurfacepatch.h +++ b/indra/newview/llsurfacepatch.h @@ -43,6 +43,10 @@ class LLVector2; class LLColor4U; class LLAgent; +class LLSurfacePatch; +typedef std::shared_ptr surface_patch_ref; +typedef std::weak_ptr surface_patch_weak_ref; + // A patch shouldn't know about its visibility since that really depends on the // camera that is looking (or not looking) at it. So, anything about a patch // that is specific to a camera should be in the class below. @@ -64,26 +68,23 @@ class LLPatchVisibilityInfo -class LLSurfacePatch +class LLSurfacePatch { public: - LLSurfacePatch(); + LLSurfacePatch(LLSurface* surface, U32 side); ~LLSurfacePatch(); - void reset(const U32 id); - void connectNeighbor(LLSurfacePatch *neighborp, const U32 direction); + void connectNeighbor(const surface_patch_ref& neighbor_patchp, const U32 direction); void disconnectNeighbor(LLSurface *surfacep); - void setNeighborPatch(const U32 direction, LLSurfacePatch *neighborp); + void setNeighborPatch(const U32 direction, const surface_patch_ref& neighborp); LLSurfacePatch *getNeighborPatch(const U32 direction) const; - void colorPatch(const U8 r, const U8 g, const U8 b); - BOOL updateTexture(); void updateVerticalStats(); void updateCompositionStats(); - void updateNormals(); + bool updateNormals(); void updateEastEdge(); void updateNorthEdge(); @@ -92,7 +93,7 @@ class LLSurfacePatch void updateVisibility(); void updateGL(); - void dirtyZ(); // Dirty the z values of this patch + bool dirtyZ(); // Dirty the z values of this patch void setHasReceivedData(); BOOL getHasReceivedData() const; @@ -139,17 +140,19 @@ class LLSurfacePatch void setDataNorm(LLVector3 *data_norm) { mDataNorm = data_norm; } F32 *getDataZ() const { return mDataZ; } - void dirty(); // Mark this surface patch as dirty... + bool dirty(); // Mark this surface patch as dirty... void clearDirty() { mDirty = FALSE; } void clearVObj(); + U32 getSide() const { return mSide; } + public: BOOL mHasReceivedData; // has the patch EVER received height data? BOOL mSTexUpdate; // Does the surface texture need to be updated? protected: - LLSurfacePatch *mNeighborPatches[8]; // Adjacent patches + std::weak_ptr* mNeighborPatches[8]; // Adjacent patches BOOL mNormalsInvalid[9]; // Which normals are invalid BOOL mDirty; @@ -184,6 +187,8 @@ class LLSurfacePatch // of LLSurface that is "connected" to another LLSurface U64 mLastUpdateTime; // Time patch was last updated + U32 mSide; // Side relative to parent surface. + LLSurface *mSurfacep; // Pointer to "parent" surface }; diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 0817aa9fdc..077b6a8c7c 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -931,17 +931,17 @@ void LLTextureCache::setReadOnly(BOOL read_only) } //called in the main thread. -S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL texture_cache_mismatch) +U64 LLTextureCache::initCache(ELLPath location, U64 max_size, BOOL texture_cache_mismatch) { llassert_always(getPending() == 0); //should not start accessing the texture cache before initialized. - S64 header_size = (max_size * 2) / 10; - S64 max_entries = header_size / TEXTURE_CACHE_ENTRY_SIZE; - sCacheMaxEntries = (S32)(llmin((S64)sCacheMaxEntries, max_entries)); + U64 header_size = (max_size * 2) / 10; + U32 max_entries = header_size / TEXTURE_CACHE_ENTRY_SIZE; + sCacheMaxEntries = (llmin(sCacheMaxEntries, max_entries)); header_size = sCacheMaxEntries * TEXTURE_CACHE_ENTRY_SIZE; max_size -= header_size; if (sCacheMaxTexturesSize > 0) - sCacheMaxTexturesSize = llmin(sCacheMaxTexturesSize, max_size); + sCacheMaxTexturesSize = (U32)llmin((U64)sCacheMaxTexturesSize, max_size); else sCacheMaxTexturesSize = max_size; max_size -= sCacheMaxTexturesSize; @@ -1064,9 +1064,9 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create else { // Look for a still valid entry in the LRU - for (std::set::iterator iter2 = mLRU.begin(); iter2 != mLRU.end();) + for (auto iter2 = mLRU.begin(); iter2 != mLRU.end();) { - std::set::iterator curiter2 = iter2++; + auto curiter2 = iter2++; LLUUID oldid = *curiter2; // Erase entry from LRU regardless mLRU.erase(curiter2); @@ -1305,14 +1305,12 @@ void LLTextureCache::writeEntriesAndClose(const std::vector& entries) if (!mReadOnly) { LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo)); - for (S32 idx=0; idxwrite((void*)(entries.data()), write_size); + if (bytes_written != write_size) { - S32 bytes_written = aprfile->write((void*)(&entries[idx]), (S32)sizeof(Entry)); - if(bytes_written != sizeof(Entry)) - { - clearCorruptedCache(); //clear the cache. - return; - } + clearCorruptedCache(); //clear the cache. + return; } closeHeaderEntriesFile(); } diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index 2715ef2c41..49b2eabc24 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -105,7 +105,7 @@ class LLTextureCache : public LLWorkerThread void purgeCache(ELLPath location); void setReadOnly(BOOL read_only) ; - S64 initCache(ELLPath location, S64 maxsize, BOOL texture_cache_mismatch); + U64 initCache(ELLPath location, U64 maxsize, BOOL texture_cache_mismatch); handle_t readFromCache(const std::string& local_filename, const LLUUID& id, U32 priority, S32 offset, S32 size, ReadResponder* responder); @@ -129,8 +129,8 @@ class LLTextureCache : public LLWorkerThread // debug S32 getNumReads() { return mReaders.size(); } S32 getNumWrites() { return mWriters.size(); } - S64 getUsage() { return mTexturesSizeTotal; } - S64 getMaxUsage() { return sCacheMaxTexturesSize; } + S64Bytes getUsage() { return S64Bytes(mTexturesSizeTotal); } + S64Bytes getMaxUsage() { return S64Bytes(sCacheMaxTexturesSize); } U32 getEntries() { return mHeaderEntriesInfo.mEntries; } U32 getMaxEntries() { return sCacheMaxEntries; }; BOOL isInCache(const LLUUID& id) ; @@ -193,7 +193,7 @@ class LLTextureCache : public LLWorkerThread std::string mHeaderDataFileName; EntriesInfo mHeaderEntriesInfo; std::set mFreeList; // deleted entries - std::set mLRU; + uuid_set_t mLRU; typedef std::map id_map_t; id_map_t mHeaderIDMap; @@ -202,7 +202,7 @@ class LLTextureCache : public LLWorkerThread typedef std::map size_map_t; size_map_t mTexturesSizeMap; S64 mTexturesSizeTotal; - LLAtomic32 mDoPurge; + LLAtomic32 mDoPurge; typedef std::map idx_entry_map_t; idx_entry_map_t mUpdatedEntryMap; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 7dfc7f68d7..192f2bc9f2 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -60,14 +60,16 @@ #include "llscrollcontainer.h" #include "lltoolmgr.h" #include "lltoolpipette.h" - -#include "lltool.h" +#include "llglheaders.h" +#include "llselectmgr.h" +#include "lltrans.h" +#include "lluictrlfactory.h" #include "llviewerwindow.h" #include "llviewerobject.h" #include "llviewercontrol.h" -#include "llglheaders.h" -#include "lluictrlfactory.h" -#include "lltrans.h" + +#include "llavatarappearancedefines.h" + // #include "llmenugl.h" // @@ -177,6 +179,7 @@ class LLFloaterTexturePicker : public LLFloater void onSelectionChange(const std::deque &items, BOOL user_action); static void onShowFolders(LLUICtrl* ctrl, void* userdata); static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata); + void onBakeTextureSelect(const LLSD& val); void onFilterEdit(const std::string& filter_string ); void onTextureSelect( const LLTextureEntry& te ); @@ -222,7 +225,6 @@ class LLFloaterTexturePicker : public LLFloater BOOL mCanApplyImmediately; BOOL mNoCopyTextureSelected; F32 mContextConeOpacity; - LLSaveFolderState mSavedFolderState; BOOL mSelectedItemPinned; LLScrollListCtrl* mLocalScrollCtrl; // tag: vaa emerald local_asset_browser @@ -273,8 +275,6 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( setCanMinimize(FALSE); - - mSavedFolderState.setApply(FALSE); } LLFloaterTexturePicker::~LLFloaterTexturePicker() @@ -288,22 +288,42 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id) mNoCopyTextureSelected = FALSE; mIsDirty = TRUE; mImageAssetID = image_id; - LLUUID item_id = findItemID(mImageAssetID, FALSE); - if (item_id.isNull()) + + std::string tab; + if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) + { + tab = "bake"; + getChild("l_bake_use_texture_combo_box")->selectByID(mImageAssetID); + } + /* TODO: Figure out how to select local asset if in use? + // tag: vaa emerald local_asset_browser [begin] + else if (mLocalScrollCtrl->selectByID(mImageAssetID)) { - mInventoryPanel->getRootFolder()->clearSelection(); + tab = "local_tab"; } + // tag: vaa emerald local_asset_browser [end] + */ else { - LLInventoryItem* itemp = gInventory.getItem(image_id); - if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) + LLUUID item_id = findItemID(mImageAssetID, FALSE); + if (item_id.isNull()) { - // no copy texture - getChild("apply_immediate_check")->setValue(FALSE); - mNoCopyTextureSelected = TRUE; + mInventoryPanel->getRootFolder()->clearSelection(); + } + else + { + tab = "server_tab"; + LLInventoryItem* itemp = gInventory.getItem(image_id); + if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) + { + // no copy texture + getChild("apply_immediate_check")->setValue(FALSE); + mNoCopyTextureSelected = TRUE; + } + mInventoryPanel->setSelection(item_id, TAKE_FOCUS_NO); } - mInventoryPanel->setSelection(item_id, TAKE_FOCUS_NO); } + if (!tab.empty()) getChild("actions_tab_container")->selectTabByName(tab); } } @@ -560,6 +580,8 @@ BOOL LLFloaterTexturePicker::postBuild() // update permission filter once UI is fully initialized updateFilterPermMask(); LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1)); + + getChild("l_bake_use_texture_combo_box")->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onBakeTextureSelect, this, _2)); return TRUE; } @@ -575,37 +597,29 @@ void LLFloaterTexturePicker::draw() if (gFocusMgr.childHasKeyboardFocus(this) && mOwner->isInVisibleChain() && mContextConeOpacity > 0.001f) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLEnable(GL_CULL_FACE); - gGL.begin(LLRender::QUADS); + LLGLEnable clip; + gGL.begin(LLRender::TRIANGLE_STRIP); { - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); - gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop); - gGL.vertex2i(owner_rect.mRight, owner_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); - gGL.vertex2i(local_rect.mRight, local_rect.mTop); - gGL.vertex2i(local_rect.mLeft, local_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); gGL.vertex2i(local_rect.mLeft, local_rect.mTop); - gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); - gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom); gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); - gGL.vertex2i(local_rect.mRight, local_rect.mBottom); gGL.vertex2i(local_rect.mRight, local_rect.mTop); gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); gGL.vertex2i(owner_rect.mRight, owner_rect.mTop); - gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom); - - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); - gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); gGL.vertex2i(local_rect.mRight, local_rect.mBottom); gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop); } gGL.end(); } @@ -613,11 +627,11 @@ void LLFloaterTexturePicker::draw() if (gFocusMgr.childHasMouseCapture(getDragHandle())) { - mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME)); } else { - mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME)); } updateImageStats(); @@ -634,14 +648,32 @@ void LLFloaterTexturePicker::draw() //BOOL allow_copy = FALSE; if( mOwner ) { - mTexturep = NULL; + mTexturep = nullptr; if(mImageAssetID.notNull()) { - mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES, LLGLTexture::BOOST_PREVIEW); + LLPointer texture = NULL; + + if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) + { + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if (obj) + { + LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID); + texture = viewerTexture ? dynamic_cast(viewerTexture) : NULL; + } + } + + if (texture.isNull()) + { + texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID); + } + + mTexturep = texture; + mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW); } else if (!mFallbackImageName.empty()) { - mTexturep = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, MIPMAP_YES, LLGLTexture::BOOST_PREVIEW); + mTexturep = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, FTT_LOCAL_FILE, MIPMAP_YES, LLGLTexture::BOOST_PREVIEW); } if (mTentativeLabel) @@ -706,11 +738,10 @@ void LLFloaterTexturePicker::draw() LLFolderView* folder_view = mInventoryPanel->getRootFolder(); if (!folder_view) return; - LLInventoryFilter* filter = folder_view->getFilter(); - if (!filter) return; + LLInventoryFilter& filter = folder_view->getFilter(); - bool is_filter_active = folder_view->getCompletedFilterGeneration() < filter->getCurrentGeneration() && - filter->isNotDefault(); + bool is_filter_active = folder_view->getCompletedFilterGeneration() < filter.getCurrentGeneration() && + filter.isNotDefault(); // After inventory panel filter is applied we have to update // constraint rect for the selected item because of folder view @@ -933,7 +964,7 @@ void LLFloaterTexturePicker::onBtnBrowser(void *userdata) // reacts to user clicking a valid field in the local scroll list. void LLFloaterTexturePicker::onLocalScrollCommit() { - LLUUID id(mLocalScrollCtrl->getSelectedItemLabel(LOCALLIST_COL_ID)); + LLUUID id(mLocalScrollCtrl->getStringUUIDSelectedItem()); mOwner->setImageAssetID(id); if (childGetValue("apply_immediate_check").asBoolean()) @@ -1042,6 +1073,19 @@ void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_da picker->commitIfImmediateSet(); } +void LLFloaterTexturePicker::onBakeTextureSelect(const LLSD& val) +{ + LLUUID imageID = val.asUUID(); + + setImageID(imageID); + + if (mCanPreview) + { + // only commit intentional selections, not implicit ones + commitIfImmediateSet(); + } +} + void LLFloaterTexturePicker::updateFilterPermMask() { //mInventoryPanel->setFilterPermMask( getFilterPermMask() ); Commented out due to no-copy texture loss. @@ -1059,36 +1103,14 @@ void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply) void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) { - std::string upper_case_search_string = search_string; - LLStringUtil::toUpper(upper_case_search_string); - - if (upper_case_search_string.empty()) + if (!mInventoryPanel) { - if (mInventoryPanel->getFilterSubString().empty()) - { - // current filter and new filter empty, do nothing - return; - } - - mSavedFolderState.setApply(TRUE); - mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); - // add folder with current item to list of previously opened folders - LLOpenFoldersWithSelection opener; - mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener); - mInventoryPanel->getRootFolder()->scrollToShowSelection(); - - } - else if (mInventoryPanel->getFilterSubString().empty()) - { - // first letter in search term, save existing folder open state - if (!mInventoryPanel->getRootFolder()->isFilterModified()) - { - mSavedFolderState.setApply(FALSE); - mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); - } + return; } - mInventoryPanel->setFilterSubString(upper_case_search_string); + // set new filter string + // Internally handles saving/restoring folder states. + mInventoryPanel->setFilterSubString(search_string); } void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) @@ -1339,7 +1361,7 @@ void LLTextureCtrl::setEnabled( BOOL enabled ) mCaption->setEnabled( enabled ); mEnable = enabled; - LLView::setEnabled( enabled ); + //LLView::setEnabled( enabled ); // } void LLTextureCtrl::setValid(BOOL valid ) @@ -1449,9 +1471,10 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask) // if(!mEnable) return FALSE; - BOOL handled = LLUICtrl::handleMouseDown( x, y , mask ); + const auto clicked_picture = mBorder->parentPointInView(x, y); + BOOL handled = (mCaption->getText().empty() || clicked_picture) && LLUICtrl::handleMouseDown( x, y , mask ); - if (!handled && mBorder->parentPointInView(x, y)) + if (!handled && clicked_picture) { showPicker(FALSE); //grab textures first... @@ -1615,21 +1638,40 @@ void LLTextureCtrl::draw() if (!mValid) { - mTexturep = NULL; + mTexturep = nullptr; } else if (!mImageAssetID.isNull()) { - mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES,LLGLTexture::BOOST_PREVIEW, LLViewerTexture::LOD_TEXTURE); - mTexturep->forceToSaveRawImage(0) ; + LLPointer texture = NULL; + + if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) + { + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if (obj) + { + LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID); + texture = viewerTexture ? dynamic_cast(viewerTexture) : NULL; + } + } + + if (texture.isNull()) + { + texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } + + texture->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + texture->forceToSaveRawImage(0) ; + + mTexturep = texture; } else if (!mFallbackImageName.empty()) { // Show fallback image. - mTexturep = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, MIPMAP_YES,LLGLTexture::BOOST_PREVIEW, LLViewerTexture::LOD_TEXTURE); + mTexturep = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, FTT_LOCAL_FILE, MIPMAP_YES,LLGLTexture::BOOST_PREVIEW, LLViewerTexture::LOD_TEXTURE); } else // mImageAssetID == LLUUID::null { - mTexturep = NULL; + mTexturep = nullptr; } // Border diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 718aa11061..5d43dfdf0f 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -150,6 +150,8 @@ class LLTextureCtrl void onFloaterCommit(ETexturePickOp op); void onFloaterCommit(ETexturePickOp op, LLUUID id); // tag: vaa emerald local_asset_browser + bool canChange() { return mEnable; } // + // This call is returned when a drag is detected. Your callback // should return TRUE if the drag is acceptable. void setDragCallback(drag_n_drop_callback cb) { mDragCallback = cb; } diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 432d34ec81..6983336428 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -60,6 +60,7 @@ #include "llstartup.h" #include "llsdserialize.h" #include "llbuffer.h" +#include "llhttpretrypolicy.h" #include "hippogridmanager.h" #include @@ -74,6 +75,9 @@ LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128); LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128); ////////////////////////////////////////////////////////////////////////////// +// Log scope +static const char * const LOG_TXT = "Texture"; + class LLTextureFetchWorker : public LLWorkerClass { friend class LLTextureFetch; @@ -190,7 +194,8 @@ class LLTextureFetchWorker : public LLWorkerClass LLTextureFetch & getFetcher() { return *mFetcher; } protected: - LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host, + LLTextureFetchWorker(LLTextureFetch* fetcher, FTType f_type, + const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 discard, S32 size); private: @@ -256,8 +261,9 @@ class LLTextureFetchWorker : public LLWorkerClass e_write_to_cache_state mWriteToCacheState; LLTextureFetch* mFetcher; LLPointer mFormattedImage; - LLPointer mRawImage; - LLPointer mAuxImage; + LLPointer mRawImage, + mAuxImage; + const FTType mFTType; LLUUID mID; LLHost mHost; std::string mUrl; @@ -266,23 +272,23 @@ class LLTextureFetchWorker : public LLWorkerClass F32 mImagePriority; U32 mWorkPriority; F32 mRequestedPriority; - S32 mDesiredDiscard; - S32 mSimRequestedDiscard; - S32 mRequestedDiscard; - S32 mLoadedDiscard; - S32 mDecodedDiscard; - LLFrameTimer mRequestedTimer; - LLFrameTimer mFetchTimer; + S32 mDesiredDiscard, + mSimRequestedDiscard, + mRequestedDiscard, + mLoadedDiscard, + mDecodedDiscard; + LLFrameTimer mRequestedTimer, + mFetchTimer; LLTimer mCacheReadTimer; F32 mCacheReadTime; - LLTextureCache::handle_t mCacheReadHandle; - LLTextureCache::handle_t mCacheWriteHandle; + LLTextureCache::handle_t mCacheReadHandle, + mCacheWriteHandle; std::vector mHttpBuffer; - S32 mRequestedSize; - S32 mRequestedOffset; - S32 mDesiredSize; - S32 mFileSize; - S32 mCachedSize; + S32 mRequestedSize, + mRequestedOffset, + mDesiredSize, + mFileSize, + mCachedSize; e_request_state mSentRequest; handle_t mDecodeHandle; BOOL mLoaded; @@ -291,8 +297,8 @@ class LLTextureFetchWorker : public LLWorkerClass BOOL mNeedsAux; BOOL mHaveAllData; BOOL mInLocalCache; - bool mCanUseHTTP ; - bool mCanUseNET ; //can get from asset server. + bool mCanUseHTTP, + mCanUseNET ; //can get from asset server. S32 mHTTPFailCount; S32 mRetryAttempt; S32 mActiveCount; @@ -303,9 +309,12 @@ class LLTextureFetchWorker : public LLWorkerClass LLMutex mWorkMutex; struct PacketData { - PacketData(U8* data, S32 size) { mData = data; mSize = size; } + PacketData(U8* data, S32 size) + : mData(data), mSize(size) + {} ~PacketData() { clearData(); } void clearData() { delete[] mData; mData = NULL; } + U8* mData; U32 mSize; }; @@ -316,11 +325,11 @@ class LLTextureFetchWorker : public LLWorkerClass U8 mImageCodec; LLViewerAssetStats::duration_t mMetricsStartTime; - unsigned int mHttpReplySize; // Actual received data size - unsigned int mHttpReplyOffset; // Actual received data offset + U32 mHttpReplySize, // Actual received data size + mHttpReplyOffset; // Actual received data offset // State history - U32 mCacheReadCount; - U32 mCacheWriteCount; + U32 mCacheReadCount, + mCacheWriteCount; }; ////////////////////////////////////////////////////////////////////////////// @@ -328,7 +337,7 @@ class HTTPGetResponder : public LLHTTPClient::ResponderWithCompleted { LOG_CLASS(HTTPGetResponder); public: - HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id, U64 startTime, S32 requestedSize, U32 offset) + HTTPGetResponder( FTType f_type, LLTextureFetch* fetcher, const LLUUID& id, U64 startTime, S32 requestedSize, U32 offset) : mFetcher(fetcher) , mID(id) , mMetricsStartTime(startTime) @@ -337,7 +346,9 @@ class HTTPGetResponder : public LLHTTPClient::ResponderWithCompleted , mReplyOffset(0) , mReplyLength(0) , mReplyFullLength(0) + , mFTType(f_type) { + mFetchRetryPolicy = new LLAdaptiveRetryPolicy(10.0,3600.0,2.0,10); } ~HTTPGetResponder() { @@ -396,13 +407,11 @@ class HTTPGetResponder : public LLHTTPClient::ResponderWithCompleted if (log_to_viewer_log || log_to_sim) { - - U64 timeNow = LLTimer::getTotalTime(); mFetcher->mTextureInfo.setRequestStartTime(mID, mMetricsStartTime); mFetcher->mTextureInfo.setRequestType(mID, LLTextureInfoDetails::REQUEST_TYPE_HTTP); mFetcher->mTextureInfo.setRequestSize(mID, mRequestedSize); mFetcher->mTextureInfo.setRequestOffset(mID, mRequestedOffset); - mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow); + mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, LLTimer::getTotalTime()); } LL_DEBUGS("Texture") << "HTTP COMPLETE: " << mID << LL_ENDL; @@ -414,6 +423,7 @@ class HTTPGetResponder : public LLHTTPClient::ResponderWithCompleted bool partial = false; if (HTTP_OK <= mStatus && mStatus < HTTP_MULTIPLE_CHOICES) { + mFetchRetryPolicy->onSuccess(); success = true; if (HTTP_PARTIAL_CONTENT == mStatus) // partial information { @@ -422,17 +432,42 @@ class HTTPGetResponder : public LLHTTPClient::ResponderWithCompleted } if (!success) { + if(mFTType == FTT_SERVER_BAKE) + { + mFetchRetryPolicy->onFailure(getStatus(), getResponseHeaders()); + F32 retry_after; + if (mFetchRetryPolicy->shouldRetry(retry_after)) + { + LL_INFOS(LOG_TXT) << mID << " will retry after " << retry_after << " seconds, resetting state to LOAD_FROM_NETWORK" << LL_ENDL; + mFetcher->removeFromHTTPQueue(mID, 0); + worker->setGetStatus(mStatus, mReason); + worker->setState(LLTextureFetchWorker::LOAD_FROM_NETWORK); + worker->unlockWorkMutex(); + return; + } + } worker->setGetStatus(mStatus, mReason); - LL_WARNS() << "CURL GET FAILED, status:" << mStatus << " reason:" << mReason << LL_ENDL; + if (mFTType != FTT_MAP_TILE) // missing map tiles are normal, don't complain about them. + { + LL_WARNS(LOG_TXT) << "CURL GET FAILED, status:" << mStatus + << " reason: " << mReason << LL_ENDL; + } } - S32 data_size = worker->callbackHttpGet(mReplyOffset, mReplyLength, channels, buffer, partial, success); + S32BytesImplicit data_size = worker->callbackHttpGet(mReplyOffset, mReplyLength, channels, buffer, partial, success); if(log_texture_traffic && data_size > 0) { - LLViewerTexture* tex = LLViewerTextureManager::findTexture(mID) ; - if(tex) + // one worker per multiple textures + std::vector textures; + LLViewerTextureManager::findTextures(mID, textures); + std::vector::iterator iter = textures.begin(); + while (iter != textures.end()) { - gTotalTextureBytesPerBoostLevel[tex->getBoostLevel()] += data_size ; + LLViewerTexture* tex = *iter++; + if (tex) + { + gTotalTextureBytesPerBoostLevel[tex->getBoostLevel()] += data_size; + } } } @@ -455,12 +490,15 @@ class HTTPGetResponder : public LLHTTPClient::ResponderWithCompleted LLTextureFetch* mFetcher; LLUUID mID; + const FTType mFTType; + LLPointer mFetchRetryPolicy; U64 mMetricsStartTime; S32 mRequestedSize; U32 mRequestedOffset; U32 mReplyOffset; U32 mReplyLength; U32 mReplyFullLength; + }; ////////////////////////////////////////////////////////////////////////////// @@ -485,7 +523,7 @@ class SGHostBlackList{ } //should make a functor. if i cared. static void cleanup() { - std::remove_if(blacklist.begin(), blacklist.end(), is_obsolete); + (void)std::remove_if(blacklist.begin(), blacklist.end(), is_obsolete); } static iter find(std::string host) { @@ -780,6 +818,7 @@ volatile bool LLTextureFetch::svMetricsDataBreak(true); // Start with a data bre // called from MAIN THREAD LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, + FTType f_type, // Fetched image type const std::string& url, // Optional URL const LLUUID& id, // Image UUID const LLHost& host, // Simulator host @@ -790,6 +829,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mState(INIT), mWriteToCacheState(NOT_WRITE), mFetcher(fetcher), + mFTType(f_type), mID(id), mHost(host), mUrl(url), @@ -832,7 +872,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mCacheReadCount(0U), mCacheWriteCount(0U) { - mCanUseNET = mUrl.empty() ; + mCanUseNET = mUrl.empty(); // Necessary for precached UUID textures, regardless of grid. if (!mCanUseNET) { @@ -901,7 +941,7 @@ void LLTextureFetchWorker::setupPacketData() mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1; if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size) { - LL_WARNS() << "Bad CACHED TEXTURE size: " << data_size << " removing." << LL_ENDL; + LL_WARNS(LOG_TXT) << "Bad CACHED TEXTURE size: " << data_size << " removing." << LL_ENDL; removeFromCache(); resetFormattedData(); clearPackets(); @@ -1013,14 +1053,14 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (mState == INIT || mState == LOAD_FROM_NETWORK/* || mState == LOAD_FROM_SIMULATOR*/) //If we've already sent out requests.. might as well continue. { - LL_WARNS("Texture") << mID << " abort: mImagePriority < F_ALMOST_ZERO" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " abort: mImagePriority < F_ALMOST_ZERO" << LL_ENDL; return true; // abort } } if(mState > CACHE_POST && !mCanUseNET && !mCanUseHTTP) { //nowhere to get data, abort. - LL_WARNS("Texture") << mID << " abort, nowhere to get data" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " abort, nowhere to get data" << LL_ENDL; return true ; } @@ -1069,7 +1109,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mCacheWriteHandle = LLTextureCache::nullHandle(); setState(LOAD_FROM_TEXTURE_CACHE); mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE - LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority) + LL_DEBUGS(LOG_TXT) << mID << ": Priority: " << llformat("%8.0f",mImagePriority) << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; // fall through } @@ -1101,7 +1141,7 @@ bool LLTextureFetchWorker::doWork(S32 param) offset, size, responder); mCacheReadTimer.reset(); } - else if (mUrl.empty()) + else if ((mUrl.empty() || mFTType==FTT_SERVER_BAKE)) { setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it @@ -1142,7 +1182,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // //This should never happen // - LL_WARNS("Texture") << mID << " this should never happen" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " this should never happen" << LL_ENDL; return false; } } @@ -1163,12 +1203,12 @@ bool LLTextureFetchWorker::doWork(S32 param) mLoadedDiscard = mDesiredDiscard; if (mLoadedDiscard < 0) { - LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard << ", should be >=0" << LL_ENDL; } setState(DECODE_IMAGE); mWriteToCacheState = NOT_WRITE ; - LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize() + LL_DEBUGS(LOG_TXT) << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize() << " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight()) << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; LLTextureFetch::sCacheHitRate.addValue(100.f); @@ -1178,13 +1218,13 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mUrl.compare(0, 7, "file://") == 0) { // failed to load local file, we're done. - LL_WARNS("Texture") << mID << ": abort, failed to load local file " << mUrl << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << ": abort, failed to load local file " << mUrl << LL_ENDL; return true; } // need more data else { - LL_DEBUGS("Texture") << mID << ": Not in Cache" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << ": Not in Cache" << LL_ENDL; setState(LOAD_FROM_NETWORK); } @@ -1196,9 +1236,10 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == LOAD_FROM_NETWORK) { static LLCachedControl use_http(gSavedSettings,"ImagePipelineUseHTTP"); + bool is_sl = gHippoGridManager->getConnectedGrid()->isSecondLife(); // if (mHost != LLHost::invalid) use_http = false; - if (use_http && mCanUseHTTP && mUrl.empty()) // get http url. + if ((is_sl || use_http) && mCanUseHTTP && mUrl.empty()) // get http url. { LLViewerRegion* region = NULL; if (mHost == LLHost::invalid) @@ -1208,26 +1249,39 @@ bool LLTextureFetchWorker::doWork(S32 param) if (region) { - std::string http_url = region->getHttpUrl() ; + std::string http_url = region->getViewerAssetUrl(); + if (http_url.empty()) http_url = region->getCapability("GetTexture"); if (!http_url.empty()) { + if (mFTType != FTT_DEFAULT) + { + LL_WARNS(LOG_TXT) << "trying to seek a non-default texture on the sim. Bad! mFTType: " << mFTType << LL_ENDL; + } mUrl = http_url + "/?texture_id=" + mID.asString().c_str(); + LL_DEBUGS(LOG_TXT) << "Texture URL: " << mUrl << LL_ENDL; mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id. mPerServicePtr = AIPerService::instance(AIPerService::extract_canonical_servicename(http_url)); } else { mCanUseHTTP = false ; + LL_DEBUGS(LOG_TXT) << "Texture not available via HTTP: empty URL." << LL_ENDL; } } else { // This will happen if not logged in or if a region does not have HTTP Texture enabled //LL_WARNS() << "Region not found for host: " << mHost << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "Texture not available via HTTP: no region " << mUrl << LL_ENDL; mCanUseHTTP = false; } } + else if (mFTType == FTT_SERVER_BAKE) + { + mWriteToCacheState = CAN_WRITE; + } if (!mUrl.empty() && SGHostBlackList::isBlacklisted(mUrl)){ + LL_DEBUGS("Texture") << mID << "Blacklisted" << LL_ENDL; mCanUseHTTP = false; } if (mCanUseHTTP && !mUrl.empty()) @@ -1240,7 +1294,12 @@ bool LLTextureFetchWorker::doWork(S32 param) } // don't return, fall through to next state } - else if (mSentRequest == UNSENT && mCanUseNET) + else if (!mCanUseNET) + { + LL_WARNS(LOG_TXT) << mID << "Unable to retrieve texture via HTTP and UDP unavailable (probable 404): " << mUrl << LL_ENDL; + return true; + } + else if (mSentRequest == UNSENT) { LL_DEBUGS("Texture") << mID << " moving to UDP fetch. mSentRequest=" << mSentRequest << " mCanUseNET = " << mCanUseNET << LL_ENDL; setState(SEND_UDP_REQ); @@ -1272,19 +1331,19 @@ bool LLTextureFetchWorker::doWork(S32 param) } if (processSimulatorPackets()) { - LL_DEBUGS("Texture") << mID << ": Loaded from Sim. Bytes: " << mFormattedImage->getDataSize() << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << ": Loaded from Sim. Bytes: " << mFormattedImage->getDataSize() << LL_ENDL; mFetcher->removeFromNetworkQueue(this, false); if (mFormattedImage.isNull() || !mFormattedImage->getDataSize()) { // processSimulatorPackets() failed // LL_WARNS() << "processSimulatorPackets() failed to load buffer" << LL_ENDL; - LL_WARNS("Texture") << mID << " processSimulatorPackets() failed to load buffer" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " processSimulatorPackets() failed to load buffer" << LL_ENDL; return true; // failed } setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); if (mLoadedDiscard < 0) { - LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard << ", should be >=0" << LL_ENDL; } setState(DECODE_IMAGE); @@ -1337,7 +1396,7 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (! mCanUseHTTP) { - LL_WARNS("Texture") << mID << " abort: SEND_HTTP_REQ but !mCanUseHTTP" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " abort: SEND_HTTP_REQ but !mCanUseHTTP" << LL_ENDL; return true ; //abort } S32 cur_size = 0; @@ -1355,7 +1414,7 @@ bool LLTextureFetchWorker::doWork(S32 param) setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); if (mLoadedDiscard < 0) { - LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard << ", should be >=0" << LL_ENDL; } setState(DECODE_IMAGE); @@ -1363,7 +1422,7 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { - LL_WARNS("Texture") << mID << " SEND_HTTP_REQ abort: cur_size " << cur_size << " <=0" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " SEND_HTTP_REQ abort: cur_size " << cur_size << " <=0" << LL_ENDL; return true ; //abort. } } @@ -1401,35 +1460,33 @@ bool LLTextureFetchWorker::doWork(S32 param) mRequestedSize += 1; } - if (!mUrl.empty()) - { - mRequestedTimer.reset(); - mLoaded = FALSE; - mGetStatus = 0; - mGetReason.clear(); - LL_DEBUGS("Texture") << "HTTP GET: " << mID << " Offset: " << mRequestedOffset - << " Bytes: " << mRequestedSize - << LL_ENDL; - // Will call callbackHttpGet when curl request completes - AIHTTPHeaders headers("Accept", "image/x-j2c"); - // Call LLHTTPClient::request directly instead of LLHTTPClient::getByteRange, because we want to pass a NULL AIEngine. - if (mRequestedOffset > 0 || mRequestedSize > 0) - { - int const range_end = mRequestedOffset + mRequestedSize - 1; - char const* const range_format = (range_end >= HTTP_REQUESTS_RANGE_END_MAX) ? "bytes=%d-" : "bytes=%d-%d"; - headers.addHeader("Range", llformat(range_format, mRequestedOffset, range_end)); - } - LLHTTPClient::request(mUrl, LLHTTPClient::HTTP_GET, NULL, - new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, mRequestedOffset), - headers, approved/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, no_does_authentication, allow_compressed_reply, NULL, 0, NULL); - } - else + if (mUrl.empty()) { LL_WARNS() << "HTTP GET request failed for " << mID << LL_ENDL; resetFormattedData(); ++mHTTPFailCount; return true; // failed } + + mRequestedTimer.reset(); + mLoaded = FALSE; + mGetStatus = 0; + mGetReason.clear(); + LL_DEBUGS(LOG_TXT) << "HTTP GET: " << mID << " Offset: " << mRequestedOffset + << " Bytes: " << mRequestedSize + << LL_ENDL; + // Will call callbackHttpGet when curl request completes + AIHTTPHeaders headers("Accept", "image/x-j2c"); + // Call LLHTTPClient::request directly instead of LLHTTPClient::getByteRange, because we want to pass a NULL AIEngine. + if (mRequestedOffset > 0 || mRequestedSize > 0) + { + int const range_end = mRequestedOffset + mRequestedSize - 1; + char const* const range_format = (range_end >= HTTP_REQUESTS_RANGE_END_MAX) ? "bytes=%d-" : "bytes=%d-%d"; + headers.addHeader("Range", llformat(range_format, mRequestedOffset, range_end)); + } + LLHTTPClient::request(mUrl, LLHTTPClient::HTTP_GET, NULL, + new HTTPGetResponder( mFTType, mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, mRequestedOffset), + headers, approved/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, no_does_authentication, allow_compressed_reply, NULL, 0, NULL); mFetcher->addToHTTPQueue(mID); recordTextureStart(true); @@ -1505,14 +1562,21 @@ bool LLTextureFetchWorker::doWork(S32 param) mHTTPFailCount = max_attempts = 1; // Don't retry if(mGetStatus == HTTP_NOT_FOUND) { + if (mFTType != FTT_MAP_TILE) + { + LL_WARNS(LOG_TXT) << "Texture missing from server (404): " << mUrl << LL_ENDL; + } + if(mWriteToCacheState == NOT_WRITE) //map tiles { resetFormattedData(); setState(DONE); - //LL_INFOS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << LL_ENDL; + if (mFTType != FTT_MAP_TILE) + { + LL_WARNS(LOG_TXT) << mID << " abort: WAIT_HTTP_REQ not found" << LL_ENDL; + } return true; // failed, means no map tile on the empty region. } - LL_WARNS() << "Texture missing from server (404): " << mUrl << LL_ENDL; } else if (mGetStatus == HTTP_INTERNAL_ERROR_CURL_TIMEOUT || mGetStatus == HTTP_INTERNAL_ERROR_LOW_SPEED) { @@ -1573,6 +1637,10 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mHTTPFailCount >= max_attempts) { + if (mFTType != FTT_SERVER_BAKE) + { + mUrl.clear(); + } // Make max_attempts attempt at decoding what data we have, // then bail forever on this image if (cur_size > 0 && (mHTTPFailCount < (max_attempts+1)) ) @@ -1582,8 +1650,8 @@ bool LLTextureFetchWorker::doWork(S32 param) setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); if (mLoadedDiscard < 0) { - LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard - << ", should be >=0" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard + << ", should be >=0" << LL_ENDL; } setState(DECODE_IMAGE); return false; @@ -1605,7 +1673,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // UDP is not an option, we are dead resetFormattedData(); setState(DONE); - LL_INFOS("Texture") << mID << " abort: fail harder" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " abort: fail harder" << LL_ENDL; return true; // failed } } @@ -1620,7 +1688,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // Clear the url since we're done with the fetch // Note: mUrl is used to check is fetching is required so failure to clear it will force an http fetch // next time the texture is requested, even if the data have already been fetched. - if(mWriteToCacheState != NOT_WRITE) + if(mWriteToCacheState != NOT_WRITE && mFTType != FTT_SERVER_BAKE) { // Why do we want to keep url if NOT_WRITE - is this a proxy for map tiles? mUrl.clear(); @@ -1630,7 +1698,7 @@ bool LLTextureFetchWorker::doWork(S32 param) { //abort. setState(DONE); - LL_WARNS("Texture") << mID << " abort: no data received" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " abort: no data received" << LL_ENDL; return true; } @@ -1645,7 +1713,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // Get back into alignment. if ((S32)mHttpReplyOffset > cur_size) { - LL_WARNS("Texture") << "Partial HTTP response produces break in image data for texture " + LL_WARNS(LOG_TXT) << "Partial HTTP response produces break in image data for texture " << mID << ". Aborting load." << LL_ENDL; setState(DONE); return true; @@ -1697,7 +1765,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mLoadedDiscard = mRequestedDiscard; if (mLoadedDiscard < 0) { - LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard << ", should be >=0" << LL_ENDL; } setState(DECODE_IMAGE); @@ -1731,26 +1799,26 @@ bool LLTextureFetchWorker::doWork(S32 param) { // We aborted, don't decode setState(DONE); - LL_WARNS("Texture") << mID << " DECODE_IMAGE abort: desired discard " << mDesiredDiscard << "<0" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: desired discard " << mDesiredDiscard << "<0" << LL_ENDL; return true; } if (mFormattedImage->getDataSize() <= 0) { - LL_WARNS() << "Decode entered with invalid mFormattedImage. ID = " << mID << LL_ENDL; + LL_WARNS(LOG_TXT) << "Decode entered with invalid mFormattedImage. ID = " << mID << LL_ENDL; //abort, don't decode setState(DONE); - LL_WARNS("Texture") << mID << " DECODE_IMAGE abort: (mFormattedImage->getDataSize() <= 0)" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: (mFormattedImage->getDataSize() <= 0)" << LL_ENDL; return true; } if (mLoadedDiscard < 0) { - LL_WARNS() << "Decode entered with invalid mLoadedDiscard. ID = " << mID << LL_ENDL; + LL_WARNS(LOG_TXT) << "Decode entered with invalid mLoadedDiscard. ID = " << mID << LL_ENDL; //abort, don't decode setState(DONE); - LL_WARNS("Texture") << mID << " DECODE_IMAGE abort: mLoadedDiscard < 0" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: mLoadedDiscard < 0" << LL_ENDL; return true; } @@ -1760,8 +1828,9 @@ bool LLTextureFetchWorker::doWork(S32 param) S32 discard = mHaveAllData ? 0 : mLoadedDiscard; U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority; mDecoded = FALSE; + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); setState(DECODE_IMAGE_UPDATE); - LL_DEBUGS("Texture") << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard + LL_DEBUGS(LOG_TXT) << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard << " All Data: " << mHaveAllData << LL_ENDL; mDecodeHandle = mFetcher->mImageDecodeThread->decodeImage(mFormattedImage, image_priority, discard, mNeedsAux, new DecodeResponder(mFetcher, mID, this)); @@ -1774,11 +1843,11 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (mDecodedDiscard < 0) { - LL_WARNS("Texture") << mID << ": Failed to Decode." << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << ": Failed to Decode." << LL_ENDL; if (mCachedSize > 0 && !mInLocalCache && mRetryAttempt == 0) { // Cache file should be deleted, try again -// LL_WARNS() << mID << ": Decode of cached file failed (removed), retrying" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << ": Decode of cached file failed (removed), retrying" << LL_ENDL; llassert_always(mDecodeHandle == 0); mFormattedImage = NULL; ++mRetryAttempt; @@ -1795,7 +1864,7 @@ bool LLTextureFetchWorker::doWork(S32 param) else { llassert_always(mRawImage.notNull()); - LL_DEBUGS("Texture") << mID << ": Decoded. Discard: " << mDecodedDiscard + LL_DEBUGS(LOG_TXT) << mID << ": Decoded. Discard: " << mDecodedDiscard << " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); setState(WRITE_TO_CACHE); @@ -1868,9 +1937,9 @@ bool LLTextureFetchWorker::doWork(S32 param) { // More data was requested, return to INIT setState(INIT); - LL_WARNS("Texture") << mID << " more data requested, returning to INIT: " - << " mDecodedDiscard " << mDecodedDiscard << ">= 0 && mDesiredDiscard " << mDesiredDiscard - << "<" << " mDecodedDiscard " << mDecodedDiscard << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " more data requested, returning to INIT: " + << " mDecodedDiscard " << mDecodedDiscard << ">= 0 && mDesiredDiscard " << mDesiredDiscard + << "<" << " mDecodedDiscard " << mDecodedDiscard << LL_ENDL; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); return false; } @@ -2031,13 +2100,13 @@ S32 LLTextureFetchWorker::callbackHttpGet(U32 offset, U32 length, if (mState != WAIT_HTTP_REQ) { - LL_WARNS() << "callbackHttpGet for unrequested fetch worker: " << mID + LL_WARNS(LOG_TXT) << "callbackHttpGet for unrequested fetch worker: " << mID << " req=" << mSentRequest << " state= " << mState << LL_ENDL; return data_size; } if (mLoaded) { - LL_WARNS() << "Duplicate callback for " << mID.asString() << LL_ENDL; + LL_WARNS(LOG_TXT) << "Duplicate callback for " << mID.asString() << LL_ENDL; return data_size; // ignore duplicate callback } if (success) @@ -2045,7 +2114,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(U32 offset, U32 length, // get length of stream: data_size = buffer->countAfter(channels.in(), NULL); - LL_DEBUGS("Texture") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL; if (data_size > 0) { LLViewerStatsRecorder::instance().textureFetch(data_size); @@ -2081,7 +2150,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(U32 offset, U32 length, // response body becomes the entire dataset. if (data_size <= mRequestedOffset) { - LL_WARNS("Texture") << "Fetched entire texture " << mID + LL_WARNS(LOG_TXT) << "Fetched entire texture " << mID << " when it was expected to be marked complete. mImageSize: " << mFileSize << " datasize: " << mFormattedImage->getDataSize() << LL_ENDL; @@ -2097,7 +2166,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(U32 offset, U32 length, else if (data_size > mRequestedSize) { // *TODO: This shouldn't be happening any more - LL_WARNS() << "data_size = " << data_size << " > requested: " << mRequestedSize << LL_ENDL; + LL_WARNS(LOG_TXT) << "data_size = " << data_size << " > requested: " << mRequestedSize << LL_ENDL; mHaveAllData = TRUE; llassert_always(mDecodeHandle == 0); mFormattedImage = NULL; // discard any previous data we had @@ -2185,18 +2254,18 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag mRawImage = raw; mAuxImage = aux; mDecodedDiscard = mFormattedImage->getDiscardLevel(); - LL_DEBUGS("Texture") << mID << ": Decode Finished. Discard: " << mDecodedDiscard + LL_DEBUGS(LOG_TXT) << mID << ": Decode Finished. Discard: " << mDecodedDiscard << " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL; } else { if (mFormattedImage.notNull()) { - LL_WARNS("Texture") << "DECODE FAILED: id = " << mID << ", Discard = " << (S32)mFormattedImage->getDiscardLevel() << LL_ENDL; + LL_WARNS(LOG_TXT) << "DECODE FAILED: id = " << mID << ", Discard = " << (S32)mFormattedImage->getDiscardLevel() << LL_ENDL; } else { - LL_WARNS("Texture") << "DECODE FAILED: id = " << mID << ", mFormattedImage is Null!" << LL_ENDL; + LL_WARNS(LOG_TXT) << "DECODE FAILED: id = " << mID << ", mFormattedImage is Null!" << LL_ENDL; } removeFromCache(); mDecodedDiscard = -1; // Redundant, here for clarity and paranoia @@ -2234,7 +2303,7 @@ bool LLTextureFetchWorker::writeToCacheComplete() // Threads: Ttf void LLTextureFetchWorker::recordTextureStart(bool is_http) { - if (! mMetricsStartTime) + if (! mMetricsStartTime.value()) { mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); } @@ -2247,13 +2316,13 @@ void LLTextureFetchWorker::recordTextureStart(bool is_http) // Threads: Ttf void LLTextureFetchWorker::recordTextureDone(bool is_http) { - if (mMetricsStartTime) + if (mMetricsStartTime.value()) { LLViewerAssetStatsFF::record_response_thread1(LLViewerAssetType::AT_TEXTURE, is_http, LLImageBase::TYPE_AVATAR_BAKE == mType, LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime); - mMetricsStartTime = 0; + mMetricsStartTime = (U32Seconds)0; } LLViewerAssetStatsFF::record_dequeue_thread1(LLViewerAssetType::AT_TEXTURE, is_http, @@ -2277,7 +2346,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mTotalCacheReadCount(0U), mTotalCacheWriteCount(0U) { - mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold")); + mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), U32Bytes(gSavedSettings.getU32("TextureLoggingThreshold"))); } LLTextureFetch::~LLTextureFetch() @@ -2287,27 +2356,30 @@ LLTextureFetch::~LLTextureFetch() while (! mCommands.empty()) { TFRequest * req(mCommands.front()); - mCommands.erase(mCommands.begin()); + mCommands.pop_front(); delete req; } // ~LLQueuedThread() called here } -bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, +bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http) { if (mDebugPause) { return false; } - - LLTextureFetchWorker* worker = getWorker(id); + if (f_type == FTT_SERVER_BAKE) + { + LL_DEBUGS("Avatar") << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << " type " << f_type << LL_ENDL; + } + LLTextureFetchWorker* worker = getWorker(id) ; if (worker) { if (worker->mHost != host) { - LL_WARNS() << "LLTextureFetch::createRequest " << id << " called with multiple hosts: " + LL_WARNS(LOG_TXT) << "LLTextureFetch::createRequest " << id << " called with multiple hosts: " << host << " != " << worker->mHost << LL_ENDL; removeRequest(worker, true); worker = NULL; @@ -2317,9 +2389,21 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con S32 desired_size; std::string exten = gDirUtilp->getExtension(url); - if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)) + //if (f_type == FTT_SERVER_BAKE) + if ((f_type == FTT_SERVER_BAKE) && !url.empty() && !exten.empty() && (LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)) + { + // SH-4030: This case should be redundant with the following one, just + // breaking it out here to clarify that it's intended behavior. + llassert(!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)); + + // Do full requests for baked textures to reduce interim blurring. + LL_DEBUGS(LOG_TXT) << "full request for " << id << " texture is FTT_SERVER_BAKE" << LL_ENDL; + desired_size = MAX_IMAGE_DATA_SIZE; + desired_discard = 0; + } + else if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)) { - LL_DEBUGS("Texture") << "full request for " << id << " exten is not J2C: " << exten << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "full request for " << id << " exten is not J2C: " << exten << LL_ENDL; // Only do partial requests for J2C at the moment //LL_INFOS() << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << LL_ENDL; desired_size = MAX_IMAGE_DATA_SIZE; @@ -2372,7 +2456,7 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con } else { - worker = new LLTextureFetchWorker(this, url, id, host, priority, desired_discard, desired_size); + worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size); lockQueue() ; mRequestMap[id] = worker; unlockQueue() ; @@ -2384,7 +2468,8 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con worker->unlockWorkMutex(); } - LL_DEBUGS("Texture") << "REQUESTED: " << id << " Discard: " << desired_discard << " size " << desired_size << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "REQUESTED: " << id << " f_type " << fttype_to_string(f_type) + << " Discard: " << desired_discard << " size " << desired_size << LL_ENDL; return true; } @@ -2703,10 +2788,10 @@ void LLTextureFetch::startThread() // Threads: Ttf void LLTextureFetch::endThread() { - LL_INFOS("Texture") << "CacheReads: " << mTotalCacheReadCount - << ", CacheWrites: " << mTotalCacheWriteCount - << ", TotalHTTPReq: " << getTotalNumHTTPRequests() - << LL_ENDL; + LL_INFOS(LOG_TXT) << "CacheReads: " << mTotalCacheReadCount + << ", CacheWrites: " << mTotalCacheWriteCount + << ", TotalHTTPReq: " << getTotalNumHTTPRequests() + << LL_ENDL; } // Threads: Ttf @@ -2731,7 +2816,7 @@ void LLTextureFetch::threadedUpdate() S32 q = mCurlGetRequest->getQueued(); if (q > 0) { - LL_INFOS() << "Queued gets: " << q << LL_ENDL; + LL_INFOS(LOG_TXT) << "Queued gets: " << q << LL_ENDL; info_timer.reset(); } } @@ -2783,7 +2868,7 @@ void LLTextureFetch::sendRequestListToSimulators() (req->mState != LLTextureFetchWorker::LOAD_FROM_SIMULATOR)) { // We already received our URL, remove from the queue - LL_WARNS() << "Worker: " << req->mID << " in mNetworkQueue but in wrong state: " << req->mState << LL_ENDL; + LL_WARNS(LOG_TXT) << "Worker: " << req->mID << " in mNetworkQueue but in wrong state: " << req->mState << LL_ENDL; mNetworkQueue.erase(curiter); continue; } @@ -3118,7 +3203,7 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 if (log_to_viewer_log || log_to_sim) { - U64 timeNow = LLTimer::getTotalTime(); + U64Microseconds timeNow = LLTimer::getTotalTime(); mTextureInfo.setRequestSize(id, worker->mFileSize); mTextureInfo.setRequestCompleteTimeAndLog(id, timeNow); } @@ -3196,25 +3281,25 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r void LLTextureFetch::dump() { - LL_INFOS() << "LLTextureFetch REQUESTS:" << LL_ENDL; + LL_INFOS(LOG_TXT) << "LLTextureFetch REQUESTS:" << LL_ENDL; for (request_queue_t::iterator iter = mRequestQueue.begin(); iter != mRequestQueue.end(); ++iter) { LLQueuedThread::QueuedRequest* qreq = *iter; LLWorkerThread::WorkRequest* wreq = (LLWorkerThread::WorkRequest*)qreq; LLTextureFetchWorker* worker = (LLTextureFetchWorker*)wreq->getWorkerClass(); - LL_INFOS() << " ID: " << worker->mID + LL_INFOS(LOG_TXT) << " ID: " << worker->mID << " PRI: " << llformat("0x%08x",wreq->getPriority()) << " STATE: " << worker->sStateDescs[worker->mState] << LL_ENDL; } - LL_INFOS() << "LLTextureFetch ACTIVE_HTTP:" << LL_ENDL; + LL_INFOS(LOG_TXT) << "LLTextureFetch ACTIVE_HTTP:" << LL_ENDL; for (queue_t::const_iterator iter(mHTTPTextureQueue.begin()); mHTTPTextureQueue.end() != iter; ++iter) { - LL_INFOS() << " ID: " << (*iter) << LL_ENDL; + LL_INFOS(LOG_TXT) << " ID: " << (*iter) << LL_ENDL; } } @@ -3290,7 +3375,7 @@ LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue() if (! mCommands.empty()) { ret = mCommands.front(); - mCommands.erase(mCommands.begin()); + mCommands.pop_front(); } unlockQueue(); // -Mfq diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index adabfcf913..58dcadf96e 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -43,6 +43,7 @@ #include "lltextureinfo.h" #include "llapr.h" #include "llstat.h" +#include "llviewertexture.h" class LLViewerTexture; class LLTextureFetchWorker; @@ -68,7 +69,7 @@ class LLTextureFetch : public LLWorkerThread void shutDownTextureCacheThread() ; //called in the main thread after the TextureCacheThread shuts down. void shutDownImageDecodeThread() ; //called in the main thread after the ImageDecodeThread shuts down. - bool createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, + bool createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http); void deleteRequest(const LLUUID& id, bool cancel); void deleteAllRequests(); @@ -162,10 +163,10 @@ class LLTextureFetch : public LLWorkerThread map_t mRequestMap; // Set of requests that require network data - typedef std::set queue_t; + typedef uuid_set_t queue_t; queue_t mNetworkQueue; queue_t mHTTPTextureQueue; - typedef std::map > cancel_queue_t; + typedef std::map cancel_queue_t; cancel_queue_t mCancelQueue; LLTextureInfo mTextureInfo; @@ -176,7 +177,7 @@ class LLTextureFetch : public LLWorkerThread // is logically tied to LLQueuedThread's list of // QueuedRequest instances and so must be covered by the // same locks. - typedef std::vector command_queue_t; + typedef std::deque command_queue_t; command_queue_t mCommands; // If true, modifies some behaviors that help with QA tasks. diff --git a/indra/newview/lltextureinfo.cpp b/indra/newview/lltextureinfo.cpp index d24ca3341c..e115021d30 100644 --- a/indra/newview/lltextureinfo.cpp +++ b/indra/newview/lltextureinfo.cpp @@ -44,17 +44,17 @@ LLTextureInfo::LLTextureInfo() : mTextureDownloadsStarted(0), mTextureDownloadsCompleted(0), mTextureDownloadProtocol("NONE"), - mTextureLogThreshold(100 * 1024), + mTextureLogThreshold(LLUnits::Kilobytes::fromValue(100)), mCurrentStatsBundleStartTime(0) { mTextures.clear(); } -void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold) +void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, U32Bytes textureLogThreshold) { mLogTextureDownloadsToViewerLog = writeToViewerLog; mLogTextureDownloadsToSimulator = sendToSim; - mTextureLogThreshold = textureLogThreshold; + mTextureLogThreshold = U32Bytes(textureLogThreshold); } LLTextureInfo::~LLTextureInfo() @@ -82,15 +82,7 @@ U32 LLTextureInfo::getTextureInfoMapSize() bool LLTextureInfo::has(const LLUUID& id) { - std::map::iterator iterator = mTextures.find(id); - if (iterator == mTextures.end()) - { - return false; - } - else - { - return true; - } + return mTextures.end() != mTextures.find(id); } void LLTextureInfo::setRequestStartTime(const LLUUID& id, U64 startTime) @@ -99,7 +91,7 @@ void LLTextureInfo::setRequestStartTime(const LLUUID& id, U64 startTime) { addRequest(id); } - mTextures[id]->mStartTime = startTime; + mTextures[id]->mStartTime = (U64Microseconds)startTime; mTextureDownloadsStarted++; } @@ -109,7 +101,7 @@ void LLTextureInfo::setRequestSize(const LLUUID& id, U32 size) { addRequest(id); } - mTextures[id]->mSize = size; + mTextures[id]->mSize = (U32Bytes)size; } void LLTextureInfo::setRequestOffset(const LLUUID& id, U32 offset) @@ -130,16 +122,19 @@ void LLTextureInfo::setRequestType(const LLUUID& id, LLTextureInfoDetails::LLReq mTextures[id]->mType = type; } -void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime) +void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64Microseconds completeTime) { if (!has(id)) { addRequest(id); } - mTextures[id]->mCompleteTime = completeTime; + + LLTextureInfoDetails& details = *mTextures[id]; + + details.mCompleteTime = completeTime; std::string protocol = "NONE"; - switch(mTextures[id]->mType) + switch(details.mType) { case LLTextureInfoDetails::REQUEST_TYPE_HTTP: protocol = "HTTP"; @@ -156,21 +151,21 @@ void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeT if (mLogTextureDownloadsToViewerLog) { - LL_INFOS() << "texture=" << id - << " start=" << mTextures[id]->mStartTime - << " end=" << mTextures[id]->mCompleteTime - << " size=" << mTextures[id]->mSize - << " offset=" << mTextures[id]->mOffset - << " length_in_ms=" << (mTextures[id]->mCompleteTime - mTextures[id]->mStartTime) / 1000 - << " protocol=" << protocol - << LL_ENDL; + LL_INFOS() << "texture=" << id + << " start=" << details.mStartTime + << " end=" << details.mCompleteTime + << " size=" << details.mSize + << " offset=" << details.mOffset + << " length=" << U32Milliseconds(details.mCompleteTime - details.mStartTime) + << " protocol=" << protocol + << LL_ENDL; } if(mLogTextureDownloadsToSimulator) { - S32 texture_stats_upload_threshold = mTextureLogThreshold; - mTotalBytes += mTextures[id]->mSize; - mTotalMilliseconds += mTextures[id]->mCompleteTime - mTextures[id]->mStartTime; + U32Bytes texture_stats_upload_threshold = mTextureLogThreshold; + mTotalBytes += details.mSize; + mTotalMilliseconds += details.mCompleteTime - details.mStartTime; mTextureDownloadsCompleted++; mTextureDownloadProtocol = protocol; if (mTotalBytes >= texture_stats_upload_threshold) @@ -194,18 +189,15 @@ void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeT LLSD LLTextureInfo::getAverages() { LLSD averagedTextureData; - S32 averageDownloadRate; - if(mTotalMilliseconds == 0) + S32 averageDownloadRate = 0; + unsigned int download_time = mTotalMilliseconds.valueInUnits(); + if (0 != download_time) { - averageDownloadRate = 0; - } - else - { - averageDownloadRate = (mTotalBytes * 8) / mTotalMilliseconds; + averageDownloadRate = mTotalBytes.valueInUnits() / download_time; } averagedTextureData["bits_per_second"] = averageDownloadRate; - averagedTextureData["bytes_downloaded"] = mTotalBytes; + averagedTextureData["bytes_downloaded"] = (LLSD::Integer)mTotalBytes.valueInUnits(); averagedTextureData["texture_downloads_started"] = mTextureDownloadsStarted; averagedTextureData["texture_downloads_completed"] = mTextureDownloadsCompleted; averagedTextureData["transport"] = mTextureDownloadProtocol; @@ -215,19 +207,19 @@ LLSD LLTextureInfo::getAverages() void LLTextureInfo::resetTextureStatistics() { - mTotalMilliseconds = 0; - mTotalBytes = 0; + mTotalMilliseconds = U32Milliseconds(0); + mTotalBytes = U32Bytes(0); mTextureDownloadsStarted = 0; mTextureDownloadsCompleted = 0; mTextureDownloadProtocol = "NONE"; mCurrentStatsBundleStartTime = LLTimer::getTotalTime(); } -U32 LLTextureInfo::getRequestStartTime(const LLUUID& id) +U32Microseconds LLTextureInfo::getRequestStartTime(const LLUUID& id) { if (!has(id)) { - return 0; + return U32Microseconds(0); } else { @@ -236,11 +228,11 @@ U32 LLTextureInfo::getRequestStartTime(const LLUUID& id) } } -U32 LLTextureInfo::getRequestSize(const LLUUID& id) +U32Bytes LLTextureInfo::getRequestSize(const LLUUID& id) { if (!has(id)) { - return 0; + return U32Bytes(0); } else { @@ -275,11 +267,11 @@ LLTextureInfoDetails::LLRequestType LLTextureInfo::getRequestType(const LLUUID& } } -U32 LLTextureInfo::getRequestCompleteTime(const LLUUID& id) +U32Microseconds LLTextureInfo::getRequestCompleteTime(const LLUUID& id) { if (!has(id)) { - return 0; + return U32Microseconds(0); } else { diff --git a/indra/newview/lltextureinfo.h b/indra/newview/lltextureinfo.h index 71b0ea431f..2c9c494c04 100644 --- a/indra/newview/lltextureinfo.h +++ b/indra/newview/lltextureinfo.h @@ -43,18 +43,18 @@ class LLTextureInfo LLTextureInfo(); ~LLTextureInfo(); - void setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold); + void setUpLogging(bool writeToViewerLog, bool sendToSim, U32Bytes textureLogThreshold); bool has(const LLUUID& id); void setRequestStartTime(const LLUUID& id, U64 startTime); void setRequestSize(const LLUUID& id, U32 size); void setRequestOffset(const LLUUID& id, U32 offset); void setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type); - void setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime); - U32 getRequestStartTime(const LLUUID& id); - U32 getRequestSize(const LLUUID& id); + void setRequestCompleteTimeAndLog(const LLUUID& id, U64Microseconds completeTime); + U32Microseconds getRequestStartTime(const LLUUID& id); + U32Bytes getRequestSize(const LLUUID& id); U32 getRequestOffset(const LLUUID& id); LLTextureInfoDetails::LLRequestType getRequestType(const LLUUID& id); - U32 getRequestCompleteTime(const LLUUID& id); + U32Microseconds getRequestCompleteTime(const LLUUID& id); void resetTextureStatistics(); U32 getTextureInfoMapSize(); LLSD getAverages(); @@ -66,15 +66,15 @@ class LLTextureInfo LLSD mAverages; - bool mLogTextureDownloadsToViewerLog; - bool mLogTextureDownloadsToSimulator; - S32 mTotalBytes; - S32 mTotalMilliseconds; + bool mLogTextureDownloadsToViewerLog, + mLogTextureDownloadsToSimulator; + U32Bytes mTotalBytes; + U32Milliseconds mTotalMilliseconds; S32 mTextureDownloadsStarted; S32 mTextureDownloadsCompleted; std::string mTextureDownloadProtocol; - U32 mTextureLogThreshold; // in bytes - U64 mCurrentStatsBundleStartTime; + U32Bytes mTextureLogThreshold; // in bytes + U64Microseconds mCurrentStatsBundleStartTime; }; #endif // LL_LLTEXTUREINFO_H diff --git a/indra/newview/lltextureinfodetails.cpp b/indra/newview/lltextureinfodetails.cpp index f6ef47a2ee..d0c5f1e3a8 100644 --- a/indra/newview/lltextureinfodetails.cpp +++ b/indra/newview/lltextureinfodetails.cpp @@ -34,7 +34,9 @@ #include "lltextureinfodetails.h" -LLTextureInfoDetails::LLTextureInfoDetails() : mStartTime(0), mCompleteTime(0), mSize(0), mType(REQUEST_TYPE_NONE), mOffset(0) +LLTextureInfoDetails::LLTextureInfoDetails() +: mType(REQUEST_TYPE_NONE), + mOffset(0) { } diff --git a/indra/newview/lltextureinfodetails.h b/indra/newview/lltextureinfodetails.h index 091fa01a3d..ef8f74ae8c 100644 --- a/indra/newview/lltextureinfodetails.h +++ b/indra/newview/lltextureinfodetails.h @@ -34,10 +34,10 @@ #define LL_LLTEXTUREINFODETAILS_H #include "lluuid.h" +#include "llunits.h" -class LLTextureInfoDetails +struct LLTextureInfoDetails { -public: enum LLRequestType { REQUEST_TYPE_NONE, @@ -45,11 +45,11 @@ class LLTextureInfoDetails REQUEST_TYPE_UDP }; - U32 mStartTime; - U32 mCompleteTime; - U32 mOffset; - U32 mSize; - LLRequestType mType; + U32Microseconds mStartTime, + mCompleteTime; + U32 mOffset; + U32Bytes mSize; + LLRequestType mType; LLTextureInfoDetails(); }; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index b201bfcca9..c2f924bc0b 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -182,7 +182,7 @@ void LLTextureBar::draw() { color = LLColor4::green4; } - else if (mImagep->getBoostLevel() > LLGLTexture::BOOST_NONE) + else if (mImagep->getBoostLevel() > LLGLTexture::BOOST_ALM) { color = LLColor4::magenta; } @@ -407,7 +407,7 @@ void LLTextureBar::draw() default:; }; std::string num_str = llformat("%4dx%4d (%+d) %7d %s", mImagep->getWidth(), mImagep->getHeight(), - mImagep->getDiscardLevel(), mImagep->hasGLTexture() ? mImagep->getTextureMemory() : 0, boost_lvl.c_str()); + mImagep->getDiscardLevel(), mImagep->hasGLTexture() ? mImagep->getTextureMemory().value() : 0, boost_lvl.c_str()); LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, title_x4, getRect().getHeight(), color, LLFontGL::LEFT, LLFontGL::TOP); } @@ -564,18 +564,18 @@ class LLGLTexMemBar : public LLView void LLGLTexMemBar::draw() { - S32 bound_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sBoundTextureMemoryInBytes); - S32 max_bound_mem = LLViewerTexture::sMaxBoundTextureMemInMegaBytes; - S32 total_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sTotalTextureMemoryInBytes); - S32 max_total_mem = LLViewerTexture::sMaxTotalTextureMemInMegaBytes; + S32Megabytes bound_mem = LLViewerTexture::sBoundTextureMemory; + S32Megabytes max_bound_mem = LLViewerTexture::sMaxBoundTextureMemory; + S32Megabytes total_mem = LLViewerTexture::sTotalTextureMemory; + S32Megabytes max_total_mem = LLViewerTexture::sMaxTotalTextureMem; F32 discard_bias = LLViewerTexture::sDesiredDiscardBias; - F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ; - F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ; - S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - S32 v_offset = 0; - F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024); - F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024); - U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ; + F32 cache_usage = LLAppViewer::getTextureCache()->getUsage().valueInUnits(); + F32 cache_max_usage = LLAppViewer::getTextureCache()->getMaxUsage().valueInUnits(); + S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); + S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f); + F32Bytes total_texture_downloaded = gTotalTextureData; + F32Bytes total_object_downloaded = gTotalObjectData; + U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests(); //---------------------------------------------------------------------------- LLGLSUIDefault gls_ui; LLColor4 text_color(1.f, 1.f, 1.f, 0.75f); @@ -583,18 +583,18 @@ void LLGLTexMemBar::draw() std::string text = ""; - S32 global_raw_memory; + S64 global_raw_memory; { - global_raw_memory = *AIAccess(LLImageRaw::sGlobalRawMemory); + global_raw_memory = *AIAccess(LLImageRaw::sGlobalRawMemory); } - text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d", - total_mem, - max_total_mem, - bound_mem, - max_bound_mem, + text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %lld MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d", + total_mem.value(), + max_total_mem.value(), + bound_mem.value(), + max_bound_mem.value(), LLRenderTarget::sBytesAllocated/(1024*1024), global_raw_memory >> 20, discard_bias, - cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded, total_http_requests); + cache_usage, cache_max_usage, total_texture_downloaded.valueInUnits(), total_object_downloaded.valueInUnits(), total_http_requests); //, cache_entries, cache_max_entries LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3, @@ -829,7 +829,7 @@ LLTextureView::~LLTextureView() typedef std::pair decode_pair_t; struct compare_decode_pair { - bool operator()(const decode_pair_t& a, const decode_pair_t& b) + bool operator()(const decode_pair_t& a, const decode_pair_t& b) const { return a.first > b.first; } @@ -890,7 +890,7 @@ void LLTextureView::draw() if (mPrintList) { - S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory() : 0 ; + S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory().value() : 0 ; LL_INFOS() << imagep->getID() << "\t" << tex_mem << "\t" << imagep->getBoostLevel() @@ -1317,7 +1317,7 @@ void LLTextureSizeView::drawTextureCategoryGraph() for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) { U32 k = LLViewerTexture::getIndexFromCategory(i) ; - mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k] >> 20, LLImageGL::sTextureMemByCategoryBound[k] >> 20, size_bar_scale) ; + mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k].value() >> 20, LLImageGL::sTextureMemByCategoryBound[k].value() >> 20, size_bar_scale) ; mTextureSizeBar[i]->draw() ; } LLImageGL::resetCurTexSizebar(); @@ -1335,7 +1335,7 @@ F32 LLTextureSizeView::drawTextureCategoryDistributionGraph() S32 count = 0 ; for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++) { - S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ; + S32 tmp = LLImageGL::sTextureMemByCategory[i].value() >> 20 ; if(tmp > count) { count = tmp ; diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp index 02d45586ab..fb1e9601a7 100644 --- a/indra/newview/lltoolbar.cpp +++ b/indra/newview/lltoolbar.cpp @@ -101,6 +101,8 @@ F32 LLToolBar::sInventoryAutoOpenTime = 1.f; // Functions // void show_floater(const std::string& floater_name); +void show_inv_floater(const LLSD& userdata, const std::string& field); +void show_web_floater(const std::string& type); LLToolBar::LLToolBar() : LLLayoutPanel() @@ -108,6 +110,10 @@ LLToolBar::LLToolBar() setIsChrome(TRUE); setFocusRoot(TRUE); mCommitCallbackRegistrar.add("ShowFloater", boost::bind(show_floater, _2)); + mCommitCallbackRegistrar.add("ShowInvFloater.ID", boost::bind(show_inv_floater, _2, "id")); + mCommitCallbackRegistrar.add("ShowInvFloater.Name", boost::bind(show_inv_floater, _2, "name")); + mCommitCallbackRegistrar.add("ShowInvFloater.Type", boost::bind(show_inv_floater, _2, "type")); + mCommitCallbackRegistrar.add("ShowWebFloater", boost::bind(show_web_floater, _2)); } @@ -121,17 +127,6 @@ BOOL LLToolBar::postBuild() mRadarBtn.connect(this, "radar_btn"); mInventoryBtn.connect(this, "inventory_btn"); - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) - { - LLView *view = *child_iter; - LLButton* buttonp = dynamic_cast(view); - if(buttonp) - { - buttonp->setSoundFlags(LLView::SILENT); - } - } - #if LL_DARWIN LLResizeHandle::Params p; p.rect(LLRect(0, 0, RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT)); @@ -161,7 +156,7 @@ BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, LLButton* inventory_btn = mInventoryBtn; if (!inventory_btn || !inventory_btn->getVisible()) return FALSE; - LLInventoryView* active_inventory = LLInventoryView::getActiveInventory(); + LLPanelMainInventory* active_inventory = LLPanelMainInventory::getActiveInventory(); if (active_inventory && active_inventory->getVisible()) { @@ -174,7 +169,7 @@ BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, if (!(active_inventory && active_inventory->getVisible()) && mInventoryAutoOpenTimer.getElapsedTimeF32() > sInventoryAutoOpenTime) { - LLInventoryView::showAgentInventory(); + LLPanelMainInventory::showAgentInventory(); } } else @@ -249,18 +244,19 @@ void LLToolBar::updateCommunicateList() bold_if_equal(LLFloaterMyFriends::getInstance(), frontmost_floater, mCommunicateBtn->add(LLFloaterMyFriends::getInstance()->getShortTitle(), LLSD("contacts"), ADD_TOP)); bold_if_equal(LLFloaterChat::getInstance(), frontmost_floater, mCommunicateBtn->add(LLFloaterChat::getInstance()->getShortTitle(), LLSD("local chat"), ADD_TOP)); mCommunicateBtn->addSeparator(ADD_TOP); - mCommunicateBtn->add(getString("Redock Windows"), LLSD("redock"), ADD_TOP); + static const auto redock = getString("Redock Windows"); + mCommunicateBtn->add(redock, LLSD("redock"), ADD_TOP); mCommunicateBtn->addSeparator(ADD_TOP); bold_if_equal(LLFloaterMute::getInstance(), frontmost_floater, mCommunicateBtn->add(LLFloaterMute::getInstance()->getShortTitle(), LLSD("mute list"), ADD_TOP)); if (gIMMgr->getIMFloaterHandles().size() > 0) mCommunicateBtn->addSeparator(ADD_TOP); - for(std::set >::const_iterator floater_handle_it = gIMMgr->getIMFloaterHandles().begin(); floater_handle_it != gIMMgr->getIMFloaterHandles().end(); ++floater_handle_it) + for(const auto& handle : gIMMgr->getIMFloaterHandles()) { - if (LLFloaterIMPanel* im_floaterp = (LLFloaterIMPanel*)floater_handle_it->get()) + if (LLFloaterIMPanel* im_floaterp = (LLFloaterIMPanel*)handle.get()) { const S32 count = im_floaterp->getNumUnreadMessages(); std::string floater_title; - if (count > 0) floater_title = "*"; + if (count > 0) floater_title = '*'; floater_title.append(im_floaterp->getShortTitle()); static const LLCachedControl show_counts("ShowUnreadIMsCounts", true); if (show_counts && count > 0) @@ -270,11 +266,14 @@ void LLToolBar::updateCommunicateList() { LLStringUtil::format_map_t args; args["COUNT"] = llformat("%d", count); - floater_title += getString("IMs", args); + static LLUIString ims = getString("IMs"); + ims.setArgList(args); + floater_title += ims.getString(); } else { - floater_title += getString("IM"); + static const auto im = getString("IM"); + floater_title += im; } } bold_if_equal(im_floaterp, frontmost_floater, mCommunicateBtn->add(floater_title, im_floaterp->getSessionID(), ADD_TOP)); diff --git a/indra/newview/lltoolbrush.cpp b/indra/newview/lltoolbrush.cpp index e5cfdc1ae9..79a9d6c6c8 100644 --- a/indra/newview/lltoolbrush.cpp +++ b/indra/newview/lltoolbrush.cpp @@ -164,10 +164,10 @@ void LLToolBrushLand::modifyLandAtPointGlobal(const LLVector3d &pos_global, //if(!is_changed) continue; // Now to update the patch information so it will redraw correctly. - LLSurfacePatch *patchp= land.resolvePatchRegion(pos_region); - if (patchp) + auto& patchp = land.resolvePatchRegion(pos_region); + if (patchp && patchp->dirtyZ()) { - patchp->dirtyZ(); + patchp->getSurface()->dirtySurfacePatch(patchp); } // Also force the property lines to update, normals to recompute, etc. @@ -305,10 +305,10 @@ void LLToolBrushLand::modifyLandInSelectionGlobal() //if(!is_changed) continue; // Now to update the patch information so it will redraw correctly. - LLSurfacePatch *patchp= land.resolvePatchRegion(min_region); - if (patchp) + auto& patchp = land.resolvePatchRegion(min_region); + if (patchp && patchp->dirtyZ()) { - patchp->dirtyZ(); + patchp->getSurface()->dirtySurfacePatch(patchp); } // Also force the property lines to update, normals to recompute, etc. diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp index 11cd498d87..b628851bbd 100644 --- a/indra/newview/lltoolcomp.cpp +++ b/indra/newview/lltoolcomp.cpp @@ -165,7 +165,7 @@ BOOL LLToolCompInspect::handleMouseDown(S32 x, S32 y, MASK mask) else { mMouseDown = TRUE; - gViewerWindow->pickAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE, TRUE); handled = TRUE; } @@ -275,7 +275,7 @@ BOOL LLToolCompTranslate::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolCompTranslate::handleMouseDown(S32 x, S32 y, MASK mask) { mMouseDown = TRUE; - gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE); + gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE, TRUE); return TRUE; } @@ -399,7 +399,7 @@ BOOL LLToolCompScale::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolCompScale::handleMouseDown(S32 x, S32 y, MASK mask) { mMouseDown = TRUE; - gViewerWindow->pickAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE, TRUE); return TRUE; } @@ -515,7 +515,7 @@ BOOL LLToolCompCreate::handleMouseDown(S32 x, S32 y, MASK mask) if ( (mask == MASK_SHIFT) || (mask == MASK_CONTROL) ) { - gViewerWindow->pickAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE, TRUE); handled = TRUE; } else @@ -599,7 +599,7 @@ BOOL LLToolCompRotate::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolCompRotate::handleMouseDown(S32 x, S32 y, MASK mask) { mMouseDown = TRUE; - gViewerWindow->pickAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE, TRUE); return TRUE; } @@ -758,7 +758,7 @@ BOOL LLToolCompGun::handleHover(S32 x, S32 y, MASK mask) { // *NOTE: This hack is here to make mouselook kick in again after // item selected from context menu. - if ( mCur == mNull && !gPopupMenuView->getVisible() ) + if (mCur == mNull) { LLSelectMgr::getInstance()->deselectAll(); setCurrentTool( (LLTool*) mGrab ); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 5a0711b917..0bd9170679 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -42,7 +42,7 @@ #include "llappearancemgr.h" #include "lldictionary.h" #include "llfirstuse.h" -#include "llfloaterinventory.h" +#include "llfloateravatarpicker.h" #include "llfloatertools.h" #include "llgesturemgr.h" #include "llgiveinventory.h" @@ -52,40 +52,26 @@ #include "llinventorybridge.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" -#include "llinventorypanel.h" -#include "llmutelist.h" -#include "llnotify.h" +#include "llparcel.h" // Rez under Land Group #include "llpreviewnotecard.h" +#include "llrootview.h" #include "llselectmgr.h" #include "lltoolmgr.h" #include "lltrans.h" -#include "llviewertexturelist.h" -#include "llviewerinventory.h" -#include "llviewerobject.h" #include "llviewerobjectlist.h" +#include "llviewerparcelmgr.h" // Rez under Land Group #include "llviewerregion.h" #include "llviewerstats.h" #include "llviewerwindow.h" #include "llvoavatarself.h" -#include "llvolume.h" #include "llworld.h" #include "llpanelface.h" -// -#include "llappviewer.h" // System Folders -#include "llparcel.h" // always rez -#include "llviewerparcelmgr.h" // always rez -// // [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1) #include "rlvhandler.h" #include "rlvlocks.h" // [/RLVa:KB] -// MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES -// or 18 * count < 1200 => count < 1200/18 => 66. I've cut it down a -// bit from there to give some pad. -const S32 MAX_ITEMS = 42; - // syntactic sugar #define callMemberFunction(object,ptrToMember) ((object).*(ptrToMember)) @@ -285,18 +271,18 @@ void LLCategoryDropDescendentsObserver::done() S32 count = items.size(); if(count) { - std::set unique_ids; + uuid_set_t unique_ids; for(S32 i = 0; i < count; ++i) { - unique_ids.insert(items.at(i)->getUUID()); + unique_ids.insert(items.get(i)->getUUID()); } uuid_vec_t ids; std::back_insert_iterator copier(ids); std::copy(unique_ids.begin(), unique_ids.end(), copier); LLCategoryDropObserver* dropper; - dropper = new LLCategoryDropObserver(mObjectID, mSource); - dropper->fetchItems(ids); - if(dropper->isEverythingComplete()) + dropper = new LLCategoryDropObserver(ids, mObjectID, mSource); + dropper->startFetch(); + if (dropper->isDone()) { dropper->done(); } @@ -360,14 +346,15 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary() }; LLToolDragAndDrop::LLToolDragAndDrop() -: LLTool(std::string("draganddrop"), NULL), - mDragStartX(0), - mDragStartY(0), - mSource(SOURCE_AGENT), - mCursor(UI_CURSOR_NO), - mLastAccept(ACCEPT_NO), - mDrop(FALSE), - mCurItemIndex(0) +: LLTool(std::string("draganddrop"), NULL), + mCargoCount(0), + mDragStartX(0), + mDragStartY(0), + mSource(SOURCE_AGENT), + mCursor(UI_CURSOR_NO), + mLastAccept(ACCEPT_NO), + mDrop(FALSE), + mCurItemIndex(0) { } @@ -380,7 +367,7 @@ void LLToolDragAndDrop::setDragStart(S32 x, S32 y) BOOL LLToolDragAndDrop::isOverThreshold(S32 x,S32 y) { - static LLCachedControl drag_and_drop_threshold(gSavedSettings,"DragAndDropDistanceThreshold"); + static LLCachedControl drag_and_drop_threshold(gSavedSettings,"DragAndDropDistanceThreshold", 3); S32 mouse_delta_x = x - mDragStartX; S32 mouse_delta_y = y - mDragStartY; @@ -485,7 +472,7 @@ void LLToolDragAndDrop::beginMultiDrag( // find categories (i.e. inventory folders) in the cargo. LLInventoryCategory* cat = NULL; S32 count = llmin(cargo_ids.size(), types.size()); - std::set cat_ids; + uuid_set_t cat_ids; for(S32 i = 0; i < count; ++i) { cat = gInventory.getCategory(cargo_ids[i]); @@ -524,6 +511,7 @@ void LLToolDragAndDrop::beginMultiDrag( void LLToolDragAndDrop::endDrag() { + mEndDragSignal(); LLSelectMgr::getInstance()->unhighlightAll(); setMouseCapture(FALSE); } @@ -580,6 +568,8 @@ ECursorType LLToolDragAndDrop::acceptanceToCursor( EAcceptance acceptance ) mCursor = UI_CURSOR_NOLOCKED; break; + + case ACCEPT_NO: mCursor = UI_CURSOR_NO; break; @@ -674,33 +664,41 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, sOperationId++; } + // For people drag and drop we don't need an actual inventory object, + // instead we need the current cargo id, which should be a person id. + bool is_uuid_dragged = (mSource == SOURCE_PEOPLE); + if(top_view) { handled = TRUE; for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { - LLInventoryObject* cargo = locateInventory(item, cat); + S32 local_x, local_y; + top_view->screenPointToLocal( x, y, &local_x, &local_y ); + EAcceptance item_acceptance = ACCEPT_NO; + LLInventoryObject* cargo = locateInventory(item, cat); if (cargo) { - S32 local_x, local_y; - top_view->screenPointToLocal( x, y, &local_x, &local_y ); - EAcceptance item_acceptance = ACCEPT_NO; handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, mCargoTypes[mCurItemIndex], (void*)cargo, &item_acceptance, mToolTipMsg); - if (handled) - { - // use sort order to determine priority of acceptance - *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance); - } } - else + else if (is_uuid_dragged) + { + handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); + } + if (handled) { - return; + // use sort order to determine priority of acceptance + *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance); } } @@ -717,20 +715,27 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { - LLInventoryObject* cargo = locateInventory(item, cat); + S32 local_x, local_y; + EAcceptance item_acceptance; + top_view->screenPointToLocal( x, y, &local_x, &local_y ); + LLInventoryObject* cargo = locateInventory(item, cat); if (cargo) { - S32 local_x, local_y; - - EAcceptance item_acceptance; - top_view->screenPointToLocal( x, y, &local_x, &local_y ); handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, TRUE, mCargoTypes[mCurItemIndex], (void*)cargo, &item_acceptance, mToolTipMsg); } + else if (is_uuid_dragged) + { + handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); + } } } if (handled) @@ -747,20 +752,27 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { + EAcceptance item_acceptance = ACCEPT_NO; + LLInventoryObject* cargo = locateInventory(item, cat); - if (!cargo) + // fix for EXT-3191 + if (cargo) { - handled = FALSE; - break; + handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)cargo, + &item_acceptance, + mToolTipMsg); + } + else if (is_uuid_dragged) + { + handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); } - - EAcceptance item_acceptance = ACCEPT_NO; - handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, - mCargoTypes[mCurItemIndex], - (void*)cargo, - &item_acceptance, - mToolTipMsg); if (handled) { // use sort order to determine priority of acceptance @@ -780,17 +792,25 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { - LLInventoryObject* cargo = locateInventory(item, cat); + EAcceptance item_acceptance; + LLInventoryObject* cargo = locateInventory(item, cat); if (cargo) { - EAcceptance item_acceptance; handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE, mCargoTypes[mCurItemIndex], (void*)cargo, &item_acceptance, mToolTipMsg); } + else if (is_uuid_dragged) + { + handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); + } } } @@ -802,6 +822,7 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, if ( !handled ) { + // *TODO: Suppress the "outbox" case once "marketplace" is used everywhere for everyone // Disallow drag and drop to 3D from the outbox const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); if (outbox_id.notNull()) @@ -816,7 +837,21 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, } } } - + // Disallow drag and drop to 3D from the marketplace + const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + if (marketplacelistings_id.notNull()) + { + for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++) + { + if (gInventory.isObjectDescendentOf(mCargoIDs[item_index], outbox_id)) + { + *acceptance = ACCEPT_NO; + mToolTipMsg = LLTrans::getString("TooltipOutboxDragToWorld"); + return; + } + } + } + dragOrDrop3D( x, y, mask, drop, acceptance ); } } @@ -827,12 +862,12 @@ void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAccep if (mDrop) { // don't allow drag and drop onto transparent objects - pick(gViewerWindow->pickImmediate(x, y, FALSE)); + pick(gViewerWindow->pickImmediate(x, y, FALSE, FALSE)); } else { // don't allow drag and drop onto transparent objects - gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE); + gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE, FALSE); } *acceptance = mLastAccept; @@ -929,8 +964,7 @@ void LLToolDragAndDrop::pick(const LLPickInfo& pick_info) const S32 item_index = mCurItemIndex; const EDragAndDropType dad_type = mCargoTypes[item_index]; // Call the right implementation function - (U32)callMemberFunction(*this, - LLDragAndDropDictionary::instance().get(dad_type, target)) + callMemberFunction(*this, LLDragAndDropDictionary::instance().get(dad_type, target)) (hit_obj, hit_face, pick_info.mKeyMask, TRUE); } } @@ -976,11 +1010,14 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, return TRUE; } - // In case the inventory has not been updated (e.g. due to some recent operation - // causing a dirty inventory), stall the user while fetching the inventory. - if (hit_obj->isInventoryDirty()) + // In case the inventory has not been loaded (e.g. due to some recent operation + // causing a dirty inventory) and we can do an update, stall the user + // while fetching the inventory. + // + // Fetch if inventory is dirty and listener is present (otherwise we will not receive update) + if (hit_obj->isInventoryDirty() && hit_obj->hasInventoryListeners()) { - hit_obj->fetchInventoryFromServer(); + hit_obj->requestInventory(); LLSD args; args["ERROR_MESSAGE"] = "Unable to add texture.\nPlease wait a few seconds and try again."; LLNotificationsUtil::add("ErrorMessage", args); @@ -1060,10 +1097,12 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, { hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); } - // Force the object to update its refetch its inventory so it has this texture. - hit_obj->fetchInventoryFromServer(); + // Force the object to update and refetch its inventory so it has this texture. + hit_obj->dirtyInventory(); + hit_obj->requestInventory(); // TODO: Check to see if adding the item was successful; if not, then - // we should return false here. + // we should return false here. This will requre a separate listener + // since without listener, we have no way to receive update } return TRUE; } @@ -1119,8 +1158,7 @@ void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj, } LLSculptParams sculpt_params; - sculpt_params.setSculptTexture(asset_id); - sculpt_params.setSculptType(LL_SCULPT_TYPE_MESH); + sculpt_params.setSculptTexture(asset_id, LL_SCULPT_TYPE_MESH); hit_obj->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); dialog_refresh_all(); @@ -1166,6 +1204,7 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, { switch (LLSelectMgr::getInstance()->getTextureChannel()) { + case 0: default: { @@ -1199,7 +1238,7 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, break; } } - else + else if (hit_obj) { //hit_obj->setTEImage(hit_face, image); hit_obj->setTETexture(hit_face, asset_id); //Singu note: setTETexture will allow the real id to be passed to LLPrimitive::setTETexture, @@ -1374,19 +1413,21 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - // Alway rez objects as land group if available. - if (gSavedSettings.getBOOL("AscentAlwaysRezInGroup")) - { - LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if(gAgent.isInGroup(parcel->getGroupID())) - msg->addUUIDFast(_PREHASH_GroupID, parcel->getGroupID()); - else if(gAgent.isInGroup(parcel->getOwnerID())) - msg->addUUIDFast(_PREHASH_GroupID, parcel->getOwnerID()); - else - msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + // Rez under Land Group + static LLCachedControl AlchemyRezUnderLandGroup(gSavedSettings, "AscentAlwaysRezInGroup"); + LLUUID group_id = gAgent.getGroupID(); + if (AlchemyRezUnderLandGroup) + { + LLParcel* land_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + // Is the agent in the land group + if (gAgent.isInGroup(land_parcel->getGroupID())) + group_id = land_parcel->getGroupID(); + // Is the agent in the land group (the group owns the land) + else if (gAgent.isInGroup(land_parcel->getOwnerID())) + group_id = land_parcel->getOwnerID(); } - else - msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + + msg->addUUIDFast(_PREHASH_GroupID, group_id); msg->nextBlock("RezData"); // if it's being rezzed from task inventory, we need to enable @@ -1449,6 +1490,7 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, gInventory.deleteObject(item->getUUID()); gInventory.notifyObservers(); } + // if (gSavedSettings.getBOOL("BroadcastViewerEffects")) { @@ -1462,6 +1504,7 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, // } // + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_REZ_COUNT); } @@ -1517,6 +1560,7 @@ void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj, // *FIX: only show this if panel not expanded? gFloaterTools->showPanel(LLFloaterTools::PANEL_CONTENTS); } + // if (gSavedSettings.getBOOL("BroadcastViewerEffects")) { @@ -1533,18 +1577,6 @@ void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj, gFloaterTools->dirty(); } -struct LLGiveInventoryInfo -{ - LLUUID mToAgentID; - LLUUID mInventoryObjectID; - LLUUID mIMSessionID; - LLGiveInventoryInfo(const LLUUID& to_agent, const LLUUID& obj_id, const LLUUID &im_session_id = LLUUID::null) : - mToAgentID(to_agent), - mInventoryObjectID(obj_id), - mIMSessionID(im_session_id) - {} -}; - // accessor that looks at permissions, copyability, and names of // inventory items to determine if a drop would be ok. EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item) @@ -1553,9 +1585,7 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL if(!item || !obj) return ACCEPT_NO; // HACK: downcast LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item; - if(!vitem->isFinished()) return ACCEPT_NO; - if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links // deny attempts to drop from an object onto itself. This is to @@ -1639,12 +1669,87 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL } +static void give_inventory_cb(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + // if Cancel pressed + if (option == 1) + { + return; + } + + LLSD payload = notification["payload"]; + const LLUUID& session_id = payload["session_id"]; + const LLUUID& agent_id = payload["agent_id"]; + LLViewerInventoryItem * inv_item = gInventory.getItem(payload["item_id"]); + LLViewerInventoryCategory * inv_cat = gInventory.getCategory(payload["item_id"]); + if (NULL == inv_item && NULL == inv_cat) + { + llassert( FALSE ); + return; + } + bool successfully_shared; + if (inv_item) + { + successfully_shared = LLGiveInventory::doGiveInventoryItem(agent_id, inv_item, session_id); + } + else + { + successfully_shared = LLGiveInventory::doGiveInventoryCategory(agent_id, inv_cat, session_id); + } + if (successfully_shared) + { + if ("avatarpicker" == payload["d&d_dest"].asString()) + { + if (LLFloaterAvatarPicker::instanceExists()) + LLFloaterAvatarPicker::getInstance()->close(); + } + LLNotificationsUtil::add("ItemsShared"); + } +} + +static void show_object_sharing_confirmation(const std::string name, + LLInventoryObject* inv_item, + const LLSD& dest, + const LLUUID& dest_agent, + const LLUUID& session_id = LLUUID::null) +{ + if (!inv_item) + { + llassert(NULL != inv_item); + return; + } + LLSD substitutions; + substitutions["RESIDENTS"] = name; + substitutions["ITEMS"] = inv_item->getName(); + LLSD payload; + payload["agent_id"] = dest_agent; + payload["item_id"] = inv_item->getUUID(); + payload["session_id"] = session_id; + payload["d&d_dest"] = dest.asString(); + LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, payload, &give_inventory_cb); +} + +static void get_name_cb(const LLUUID& id, + const std::string& full_name, + LLInventoryObject* inv_obj, + const LLSD& dest, + const LLUUID& dest_agent) +{ + show_object_sharing_confirmation(full_name, + inv_obj, + dest, + id, + LLUUID::null); +} + // function used as drag-and-drop handler for simple agent give inventory requests //static bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_id, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, - EAcceptance* accept) + EAcceptance* accept, + const LLSD& dest) { // check the type switch(cargo_type) @@ -1749,13 +1854,13 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv( } // must not be already wearing it - // - //LLVOAvatar* my_avatar = gAgentAvatarp; - //if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) ) - //{ - // return ACCEPT_NO; - //} - // + /* + LLVOAvatarSelf* avatar = gAgentAvatarp; + if( !avatar || avatar->isWearingAttachment(item->getUUID()) ) + { + return ACCEPT_NO; + } + */ const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); if(gInventory.isObjectDescendentOf(item->getUUID(), outbox_id)) @@ -1823,13 +1928,14 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand( locateInventory(item, cat); if (!item || !item->isFinished()) return ACCEPT_NO; - // - //LLVOAvatar* my_avatar = gAgentAvatarp; - //if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) ) - //{ - // return ACCEPT_NO; - //} - // + /* + LLVOAvatarSelf* my_avatar = gAgentAvatarp; + if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) ) + { + return ACCEPT_NO; + } + */ + EAcceptance accept; BOOL remove_inventory; @@ -1898,13 +2004,13 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject( LLViewerInventoryCategory* cat; locateInventory(item, cat); if(!item || !item->isFinished()) return ACCEPT_NO; - // - //LLVOAvatar* my_avatar = gAgentAvatarp; - //if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) ) - //{ - // return ACCEPT_NO; - //} - // + /* + LLVOAvatarSelf* my_avatar = gAgentAvatarp; + if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) ) + { + return ACCEPT_NO; + } + */ if((mask & MASK_CONTROL)) { @@ -2007,23 +2113,20 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject( { LL_DEBUGS() << "LLToolDragAndDrop::dad3dApplyToObject()" << LL_ENDL; - // + /* // Fuck this - // *HACK: In order to resolve SL-22177, we need to block drags // from notecards and objects onto other objects. - //if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource)) - //{ - // return ACCEPT_NO; - //} - // + if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource)) + { + return ACCEPT_NO; + } + */ LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isFinished()) return ACCEPT_NO; - EAcceptance rv = willObjectAcceptInventory(obj, item); if((mask & MASK_CONTROL)) { @@ -2446,11 +2549,13 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject( return ACCEPT_NO; } LLVOAvatarSelf* avatar = gAgentAvatarp; + /* if(avatar && avatar->isWearingAttachment( item->getUUID() ) ) { // You can't give objects that are attached to you return ACCEPT_NO; } + */ if( obj && avatar ) { if(drop) @@ -2638,7 +2743,8 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory( item = NULL; cat = NULL; - if (mCargoIDs.empty()) + if (mCargoIDs.empty() + || (mSource == SOURCE_PEOPLE)) ///< There is no inventory item for people drag and drop. { return NULL; } @@ -2668,7 +2774,7 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory( } else if(mSource == SOURCE_NOTECARD) { - LLPreviewNotecard* preview = dynamic_cast(LLPreview::find(mSourceID)); + LLPreviewNotecard* preview = static_cast(LLPreview::find(mSourceID)); if(preview) { item = (LLViewerInventoryItem*)preview->getDragItem(); @@ -2683,11 +2789,11 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory( LLInventoryObject* LLToolDragAndDrop::locateMultipleInventory(LLViewerInventoryCategory::cat_array_t& cats, LLViewerInventoryItem::item_array_t& items) { - if(mCargoIDs.count() == 0) return NULL; + if(mCargoIDs.size() == 0) return NULL; if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)) { // The object should be in user inventory. - for (S32 i = 0; i < mCargoIDs.count(); i++) + for (S32 i = 0; i < mCargoIDs.size(); i++) { LLInventoryItem* item = gInventory.getItem(mCargoIDs[i]); if (item) @@ -2711,7 +2817,7 @@ LLInventoryObject* LLToolDragAndDrop::locateMultipleInventory(LLViewerInventoryC || (mCargoType == DAD_ROOT_CATEGORY)) { // The object should be in user inventory. - for (S32 i = 0; i < mCargoIDs.count(); i++) + for (S32 i = 0; i < mCargoIDs.size(); i++) { LLInventoryCategory* category = (LLInventoryCategory*)obj->getInventoryObject(mCargoIDs[i]); if (category) @@ -2722,7 +2828,7 @@ LLInventoryObject* LLToolDragAndDrop::locateMultipleInventory(LLViewerInventoryC } else { - for (S32 i = 0; i < mCargoIDs.count(); i++) + for (S32 i = 0; i < mCargoIDs.size(); i++) { LLInventoryItem* item = (LLInventoryItem*)obj->getInventoryObject(mCargoIDs[i]); if (item) diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 09de0e6ddc..4d5cacb31b 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -33,10 +33,10 @@ #ifndef LL_TOOLDRAGANDDROP_H #define LL_TOOLDRAGANDDROP_H +#include "lldictionary.h" #include "lltool.h" #include "llview.h" #include "lluuid.h" -#include "stdenums.h" #include "llassetstorage.h" #include "llpermissions.h" #include "llwindow.h" @@ -50,6 +50,8 @@ class LLPickInfo; class LLToolDragAndDrop : public LLTool, public LLSingleton { public: + typedef boost::signals2::signal enddrag_signal_t; + LLToolDragAndDrop(); // overridden from LLTool @@ -68,7 +70,9 @@ class LLToolDragAndDrop : public LLTool, public LLSingleton SOURCE_AGENT, SOURCE_WORLD, SOURCE_NOTECARD, - SOURCE_LIBRARY + SOURCE_LIBRARY, + SOURCE_VIEWER, + SOURCE_PEOPLE }; void beginDrag(EDragAndDropType type, @@ -86,9 +90,23 @@ class LLToolDragAndDrop : public LLTool, public LLSingleton const LLUUID& getObjectID() const { return mObjectID; } EAcceptance getLastAccept() { return mLastAccept; } + boost::signals2::connection setEndDragCallback( const enddrag_signal_t::slot_type& cb ) { return mEndDragSignal.connect(cb); } + + void setCargoCount(U32 count) { mCargoCount = count; } + void resetCargoCount() { mCargoCount = 0; } + U32 getCargoCount() const { return (mCargoCount > 0) ? mCargoCount : mCargoIDs.size(); } + S32 getCargoIndex() const { return mCurItemIndex; } + uuid_vec_t::size_type getCargoIDsCount() const { return mCargoIDs.size(); } static S32 getOperationId() { return sOperationId; } + // deal with permissions of object, etc. returns TRUE if drop can + // proceed, otherwise FALSE. + static BOOL handleDropTextureProtections(LLViewerObject* hit_obj, + LLInventoryItem* item, + LLToolDragAndDrop::ESource source, + const LLUUID& src_id); + protected: enum EDropTarget { @@ -100,6 +118,7 @@ class LLToolDragAndDrop : public LLTool, public LLSingleton DT_COUNT = 5 }; +protected: // dragOrDrop3dImpl points to a member of LLToolDragAndDrop that // takes parameters (LLViewerObject* obj, S32 face, MASK, BOOL // drop) and returns a BOOL if drop is ok @@ -110,11 +129,14 @@ class LLToolDragAndDrop : public LLTool, public LLSingleton EAcceptance* acceptance); void dragOrDrop3D(S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* acceptance); + static void pickCallback(const LLPickInfo& pick_info); void pick(const LLPickInfo& pick_info); protected: + U32 mCargoCount; + S32 mDragStartX; S32 mDragStartY; @@ -135,6 +157,9 @@ class LLToolDragAndDrop : public LLTool, public LLSingleton BOOL mDrop; S32 mCurItemIndex; std::string mToolTipMsg; + std::string mCustomMsg; + + enddrag_signal_t mEndDragSignal; protected: // 3d drop functions. these call down into the static functions @@ -209,13 +234,6 @@ class LLToolDragAndDrop : public LLTool, public LLSingleton // inventory items to determine if a drop would be ok. static EAcceptance willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item); - // deal with permissions of object, etc. returns TRUE if drop can - // proceed, otherwise FALSE. - static BOOL handleDropTextureProtections(LLViewerObject* hit_obj, - LLInventoryItem* item, - LLToolDragAndDrop::ESource source, - const LLUUID& src_id); - public: // helper functions static BOOL isInventoryDropAcceptable(LLViewerObject* obj, LLInventoryItem* item) { return (ACCEPT_YES_COPY_SINGLE <= willObjectAcceptInventory(obj, item)); } @@ -253,7 +271,8 @@ class LLToolDragAndDrop : public LLTool, public LLSingleton static bool handleGiveDragAndDrop(LLUUID agent, LLUUID session, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, - EAcceptance* accept); + EAcceptance* accept, + const LLSD& dest = LLSD()); // Classes used for determining 3d drag and drop types. private: diff --git a/indra/newview/lltoolface.cpp b/indra/newview/lltoolface.cpp index 4b5f19eba0..721ed2842f 100644 --- a/indra/newview/lltoolface.cpp +++ b/indra/newview/lltoolface.cpp @@ -87,7 +87,7 @@ BOOL LLToolFace::handleDoubleClick(S32 x, S32 y, MASK mask) BOOL LLToolFace::handleMouseDown(S32 x, S32 y, MASK mask) { - gViewerWindow->pickAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE, TRUE); return TRUE; } diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp index a6ceaec47f..d9d80fa4d0 100644 --- a/indra/newview/lltoolfocus.cpp +++ b/indra/newview/lltoolfocus.cpp @@ -131,7 +131,9 @@ BOOL LLToolCamera::handleMouseDown(S32 x, S32 y, MASK mask) gViewerWindow->hideCursor(); - gViewerWindow->pickAsync(x, y, mask, pickCallback); + bool pick_rigged = gFloaterTools && gFloaterTools->getVisible(); + + gViewerWindow->pickAsync(x, y, mask, pickCallback, /*BOOL pick_transparent*/ FALSE, pick_rigged, /*BOOL pick_unselectable*/ TRUE); // don't steal focus from UI return FALSE; } diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index f17754f97a..267b34761a 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -141,7 +141,7 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask) if (!gAgent.leftButtonGrabbed()) { // can grab transparent objects (how touch event propagates, scripters rely on this) - gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE, TRUE); + gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE, FALSE, FALSE, TRUE); } return TRUE; } @@ -403,7 +403,7 @@ void LLToolGrab::startGrab() mDragStartPointGlobal = grab_start_global; mDragStartFromCamera = grab_start_global - gAgentCamera.getCameraPositionGlobal(); - send_ObjectGrab_message(objectp, mGrabPick, grab_offset); + send_ObjectGrab_message(objectp, true, &mGrabPick, grab_offset); mGrabOffsetFromCenterInitial = grab_offset; mGrabHiddenOffsetFromCamera = mDragStartFromCamera; @@ -1079,7 +1079,7 @@ void LLToolGrab::stopGrab() case GRAB_ACTIVE_CENTER: case GRAB_NONPHYSICAL: case GRAB_LOCKED: - send_ObjectDeGrab_message(objectp, pick); + send_ObjectGrab_message(objectp, false, &pick); mVerticalDragging = FALSE; break; @@ -1133,64 +1133,45 @@ LLVector3d LLToolGrab::getGrabPointGlobal() } -void send_ObjectGrab_message(LLViewerObject* object, const LLPickInfo & pick, const LLVector3 &grab_offset) +void send_ObjectGrab_message(LLViewerObject* object, bool grab, const LLPickInfo* const pick, const LLVector3 &grab_offset) { if (!object) return; LLMessageSystem *msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ObjectGrab); + msg->newMessageFast(grab ? _PREHASH_ObjectGrab : _PREHASH_ObjectDeGrab); msg->nextBlockFast( _PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast( _PREHASH_ObjectData); msg->addU32Fast( _PREHASH_LocalID, object->mLocalID); - msg->addVector3Fast(_PREHASH_GrabOffset, grab_offset); - msg->nextBlock("SurfaceInfo"); - msg->addVector3("UVCoord", LLVector3(pick.mUVCoords)); - msg->addVector3("STCoord", LLVector3(pick.mSTCoords)); - msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace); - msg->addVector3("Position", pick.mIntersection); - msg->addVector3("Normal", pick.mNormal); - msg->addVector3("Binormal", pick.mBinormal); + if (grab) msg->addVector3Fast(_PREHASH_GrabOffset, grab_offset); + if (pick) + { + msg->nextBlock("SurfaceInfo"); + msg->addVector3("UVCoord", LLVector3(pick->mUVCoords)); + msg->addVector3("STCoord", LLVector3(pick->mSTCoords)); + msg->addS32Fast(_PREHASH_FaceIndex, pick->mObjectFace); + msg->addVector3("Position", pick->mIntersection); + msg->addVector3("Normal", pick->mNormal); + msg->addVector3("Binormal", pick->mBinormal); + } msg->sendMessage( object->getRegion()->getHost()); /* Diagnostic code - LL_INFOS() << "mUVCoords: " << pick.mUVCoords - << ", mSTCoords: " << pick.mSTCoords - << ", mObjectFace: " << pick.mObjectFace - << ", mIntersection: " << pick.mIntersection - << ", mNormal: " << pick.mNormal - << ", mBinormal: " << pick.mBinormal + if (pick) + { + LL_INFOS() << "mUVCoords: " << pick->mUVCoords + << ", mSTCoords: " << pick->mSTCoords + << ", mObjectFace: " << pick->mObjectFace + << ", mIntersection: " << pick->mIntersection + << ", mNormal: " << pick->mNormal + << ", mBinormal: " << pick->mBinormal << LL_ENDL; + } LL_INFOS() << "Avatar pos: " << gAgent.getPositionAgent() << LL_ENDL; LL_INFOS() << "Object pos: " << object->getPosition() << LL_ENDL; */ } - -void send_ObjectDeGrab_message(LLViewerObject* object, const LLPickInfo & pick) -{ - if (!object) return; - - LLMessageSystem *msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_ObjectDeGrab); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_LocalID, object->mLocalID); - msg->nextBlock("SurfaceInfo"); - msg->addVector3("UVCoord", LLVector3(pick.mUVCoords)); - msg->addVector3("STCoord", LLVector3(pick.mSTCoords)); - msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace); - msg->addVector3("Position", pick.mIntersection); - msg->addVector3("Normal", pick.mNormal); - msg->addVector3("Binormal", pick.mBinormal); - msg->sendMessage(object->getRegion()->getHost()); -} - - - diff --git a/indra/newview/lltoolgrab.h b/indra/newview/lltoolgrab.h index d5c99a43fc..98f5fdd913 100644 --- a/indra/newview/lltoolgrab.h +++ b/indra/newview/lltoolgrab.h @@ -41,9 +41,7 @@ class LLPickInfo; // Message utilities -void send_ObjectGrab_message(LLViewerObject* object, const LLPickInfo & pick, const LLVector3 &grab_offset); -void send_ObjectDeGrab_message(LLViewerObject* object, const LLPickInfo & pick); - +void send_ObjectGrab_message(LLViewerObject* object, bool grab, const LLPickInfo* const pick = nullptr, const LLVector3& grab_offset = LLVector3::zero); class LLToolGrab : public LLTool, public LLSingleton diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 9acc349713..e2f88b107d 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -276,16 +276,16 @@ void LLVisualParamHint::draw() gGL.color4f(1.f, 1.f, 1.f, 1.f); LLGLSUIDefault gls_ui; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { gGL.texCoord2i(0, 1); gGL.vertex2i(0, mFullHeight); gGL.texCoord2i(0, 0); gGL.vertex2i(0, 0); - gGL.texCoord2i(1, 0); - gGL.vertex2i(mFullWidth, 0); gGL.texCoord2i(1, 1); gGL.vertex2i(mFullWidth, mFullHeight); + gGL.texCoord2i(1, 0); + gGL.vertex2i(mFullWidth, 0); } gGL.end(); diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 750e9786bb..0f24ca9435 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -107,9 +107,11 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) mMouseOutsideSlop = FALSE; mMouseDownX = x; mMouseDownY = y; - - //left mouse down always picks transparent - mPick = gViewerWindow->pickImmediate(x, y, TRUE); + //LLTimer pick_timer; + BOOL pick_rigged = true; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick"); + //left mouse down always picks transparent (but see handleMouseUp) + mPick = gViewerWindow->pickImmediate(x, y, TRUE, pick_rigged); + //LL_INFOS() << "pick_rigged is " << (S32) pick_rigged << " pick time elapsed " << pick_timer.getElapsedTimeF32() << LL_ENDL; mPick.mKeyMask = mask; mMouseButtonDown = true; @@ -124,7 +126,10 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask) { // don't pick transparent so users can't "pay" transparent objects - mPick = gViewerWindow->pickImmediate(x, y, FALSE); + mPick = gViewerWindow->pickImmediate(x, y, + /*BOOL pick_transparent*/ FALSE, + /*BOOL pick_rigged*/ mask != MASK_SHIFT, + /*BOOL pick_particle*/ TRUE); mPick.mKeyMask = mask; // claim not handled so UI focus stays same @@ -408,7 +413,7 @@ BOOL LLToolPie::handleLeftClickPick() LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); // Spawn pie menu - LLTool::handleRightMouseDown(x, y, mask); + handleRightMouseDown(x, y, mask); return TRUE; } @@ -528,7 +533,7 @@ void LLToolPie::walkToClickedLocation() mAutoPilotDestination->setDuration(3.f); */ - handle_go_to(); + handle_go_to(mPick.mPosGlobal); } // When we get object properties after left-clicking on an object @@ -564,7 +569,7 @@ void LLToolPie::selectionPropertiesReceived() case CLICK_ACTION_PAY: if ( LLToolPie::getInstance()->mClickActionPayEnabled ) { - handle_give_money_dialog(); + handle_give_money_dialog(selected_object); } break; case CLICK_ACTION_OPEN: @@ -580,7 +585,8 @@ void LLToolPie::selectionPropertiesReceived() BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) { - mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE); + BOOL pick_rigged = false; + mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE, pick_rigged); LLViewerObject *parent = NULL; LLViewerObject *object = mHoverPick.getObject(); //LLSelectMgr::getInstance()->setHoverObject(object, mHoverPick.mObjectFace); // Singu TODO: remove llhoverview.cpp @@ -605,6 +611,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) if (handleMediaHover(mHoverPick)) { // cursor set by media object + LL_DEBUGS("UserInput") << "hover handled by LLToolPie (inactive)" << LL_ENDL; } else if (!mMouseOutsideSlop && mMouseButtonDown @@ -632,7 +639,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) else { // perform a separate pick that detects transparent objects since they respond to 1-click actions - LLPickInfo click_action_pick = gViewerWindow->pickImmediate(x, y, TRUE); + LLPickInfo click_action_pick = gViewerWindow->pickImmediate(x, y, TRUE, pick_rigged); LLViewerObject* click_action_object = click_action_pick.getObject(); @@ -640,6 +647,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) { ECursorType cursor = cursorFromObject(click_action_object); gViewerWindow->setCursor(cursor); + LL_DEBUGS("UserInput") << "hover handled by LLToolPie (inactive)" << LL_ENDL; } // [RLVa:KB] - Checked: 2010-03-11 (RLVa-1.2.0e) | Added: RLVa-1.1.0l else if ( (object) && (rlv_handler_t::isEnabled()) && (!gRlvHandler.canTouch(object)) ) @@ -652,22 +660,23 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) || (parent && !parent->isAvatar() && parent->flagUsePhysics())) { gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB); + LL_DEBUGS("UserInput") << "hover handled by LLToolPie (inactive)" << LL_ENDL; } else if ( (object && object->flagHandleTouch()) || (parent && parent->flagHandleTouch())) { gViewerWindow->setCursor(UI_CURSOR_HAND); + LL_DEBUGS("UserInput") << "hover handled by LLToolPie (inactive)" << LL_ENDL; } else { gViewerWindow->setCursor(UI_CURSOR_ARROW); + LL_DEBUGS("UserInput") << "hover handled by LLToolPie (inactive)" << LL_ENDL; } } if(!object) { - //gViewerWindow->setCursor(UI_CURSOR_ARROW); - // We need to clear media hover flag LLViewerMediaFocus::getInstance()->clearHover(); } @@ -693,29 +702,51 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) && gAgentAvatarp && !gAgentAvatarp->isSitting() && !mBlockClickToWalk // another behavior hasn't cancelled click to walk - && !mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick - && (mPick.mPickType == LLPickInfo::PICK_LAND // we clicked on land - || mPick.mObjectID.notNull())) // or on an object + ) { - // handle special cases of steering picks - LLViewerObject* avatar_object = mPick.getObject(); + // We may be doing click to walk, but we don't want to use a target on + // a transparent object because the user thought they were clicking on + // whatever they were seeing through it, so recompute what was clicked on + // ignoring transparent objects + LLPickInfo savedPick = mPick; + mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY, + FALSE /* ignore transparent */, + FALSE /* ignore rigged */, + FALSE /* ignore particles */); + LLViewerObject* objp = mPick.getObject(); + bool is_in_world = mPick.mObjectID.notNull() && objp && !objp->isHUDAttachment(); // We clicked on a non-hud object + bool is_land = mPick.mPickType == LLPickInfo::PICK_LAND; // or on land + bool pos_non_zero = !mPick.mPosGlobal.isExactlyZero(); // valid coordinates for pick + if (pos_non_zero && (is_land || is_in_world)) + { + // get pointer to avatar + while (objp && !objp->isAvatar()) + { + objp = (LLViewerObject*) objp->getParent(); + } - // get pointer to avatar - while (avatar_object && !avatar_object->isAvatar()) - { - avatar_object = (LLViewerObject*)avatar_object->getParent(); - } + if (objp && ((LLVOAvatar*) objp)->isSelf()) + { + const F64 SELF_CLICK_WALK_DISTANCE = 3.0; + // pretend we picked some point a bit in front of avatar + mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE; + } + gAgentCamera.setFocusOnAvatar(TRUE, TRUE); + walkToClickedLocation(); + //LLFirstUse::notMoving(false); - if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf()) - { - const F64 SELF_CLICK_WALK_DISTANCE = 3.0; - // pretend we picked some point a bit in front of avatar - mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE; + return TRUE; } - gAgentCamera.setFocusOnAvatar(TRUE, TRUE); - walkToClickedLocation(); - - return TRUE; + else + { + LL_DEBUGS("maint5901") << "walk target was " + << (mPick.mPosGlobal.isExactlyZero() ? "zero" : "not zero") + << ", pick type was " << (mPick.mPickType == LLPickInfo::PICK_LAND ? "land" : "not land") + << ", pick object was " << mPick.mObjectID + << LL_ENDL; + // we didn't click to walk, so restore the original target + mPick = savedPick; + } } gViewerWindow->setCursor(UI_CURSOR_ARROW); if (hasMouseCapture()) @@ -732,8 +763,7 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) void LLToolPie::stopClickToWalk() { - mPick.mPosGlobal = gAgent.getPositionGlobal(); - handle_go_to(); + handle_go_to(gAgent.getPositionGlobal()); /* Singu TODO: llhudeffectblob if(mAutoPilotDestination) { @@ -749,17 +779,28 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask) LL_INFOS() << "LLToolPie handleDoubleClick (becoming mouseDown)" << LL_ENDL; } - if (gSavedSettings.getBOOL("DoubleClickAutoPilot")) - { - if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) || - (mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero())) - { - walkToClickedLocation(); - return TRUE; - } - } - else if (gSavedSettings.getBOOL("DoubleClickTeleport")) + if (handleMediaDblClick(mPick)) + { + return TRUE; + } + + bool dbl_click_autoplt = gSavedSettings.getBOOL("DoubleClickAutoPilot"); + bool dbl_click_teleport = gSavedSettings.getBOOL("DoubleClickTeleport"); + + if (dbl_click_autoplt || dbl_click_teleport) { + // Save the original pick + LLPickInfo savedPick = mPick; + + // We may be doing double click to walk or a double click teleport, but + // we don't want to use a target on a transparent object because the user + // thought they were clicking on whatever they were seeing through it, so + // recompute what was clicked on ignoring transparent objects + mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY, + FALSE /* ignore transparent */, + FALSE /* ignore rigged */, + FALSE /* ignore particles */); + LLViewerObject* objp = mPick.getObject(); LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL; @@ -767,15 +808,43 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask) bool is_land = mPick.mPickType == LLPickInfo::PICK_LAND; bool pos_non_zero = !mPick.mPosGlobal.isExactlyZero(); bool has_touch_handler = (objp && objp->flagHandleTouch()) || (parentp && parentp->flagHandleTouch()); - bool has_click_action = final_click_action(objp); - - if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && !has_click_action))) + bool no_click_action = final_click_action(objp) == CLICK_ACTION_NONE; + if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && no_click_action))) { - LLVector3d pos = mPick.mPosGlobal; - pos.mdV[VZ] += gAgentAvatarp->getPelvisToFoot(); - gAgent.teleportViaLocationLookAt(pos); - return TRUE; + if (dbl_click_autoplt + && !gAgent.getFlying() // don't auto-navigate while flying until that works + && isAgentAvatarValid() + && !gAgentAvatarp->isSitting() + ) + { + // get pointer to avatar + while (objp && !objp->isAvatar()) + { + objp = (LLViewerObject*) objp->getParent(); + } + + if (objp && ((LLVOAvatar*) objp)->isSelf()) + { + const F64 SELF_CLICK_WALK_DISTANCE = 3.0; + // pretend we picked some point a bit in front of avatar + mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE; + } + gAgentCamera.setFocusOnAvatar(TRUE, TRUE); + walkToClickedLocation(); + //LLFirstUse::notMoving(false); + return TRUE; + } + else if (dbl_click_teleport) + { + LLVector3d pos = mPick.mPosGlobal; + pos.mdV[VZ] += gAgentAvatarp->getPelvisToFoot(); + gAgent.teleportViaLocationLookAt(pos); + return TRUE; + } } + + // restore the original pick for any other purpose + mPick = savedPick; } return FALSE; @@ -879,56 +948,110 @@ static void handle_click_action_play() bool LLToolPie::handleMediaClick(const LLPickInfo& pick) { - //FIXME: how do we handle object in different parcel than us? - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - LLPointer objectp = pick.getObject(); - - - if (!parcel || - objectp.isNull() || - pick.mObjectFace < 0 || - pick.mObjectFace >= objectp->getNumTEs()) - { - LLViewerMediaFocus::getInstance()->clearFocus(); - - return false; - } - - // Does this face have media? - const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); - if(!tep) - return false; - - LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL; - if(!mep) - return false; - - viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); - - if (gSavedSettings.getBOOL("MediaOnAPrimUI")) - { - if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull()) - { - // It's okay to give this a null impl - LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal); - } - else - { - // Make sure keyboard focus is set to the media focus object. - gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance()); - LLEditMenuHandler::gEditMenuHandler = LLViewerMediaFocus::instance().getFocusedMediaImpl(); - - media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(TRUE)); - mMediaMouseCaptureID = mep->getMediaID(); - setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture. - } - - return true; - } - - LLViewerMediaFocus::getInstance()->clearFocus(); + //FIXME: how do we handle object in different parcel than us? + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + LLPointer objectp = pick.getObject(); + + + if (!parcel || + objectp.isNull() || + pick.mObjectFace < 0 || + pick.mObjectFace >= objectp->getNumTEs()) + { + LLViewerMediaFocus::getInstance()->clearFocus(); + + return false; + } + + // Does this face have media? + const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); + if (!tep) + return false; + + LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL; + if (!mep) + return false; + + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); + + if (gSavedSettings.getBOOL("MediaOnAPrimUI")) + { + if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull()) + { + // It's okay to give this a null impl + LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal); + } + else + { + // Make sure keyboard focus is set to the media focus object. + gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance()); + LLEditMenuHandler::gEditMenuHandler = LLViewerMediaFocus::instance().getFocusedMediaImpl(); + + media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(TRUE)); + mMediaMouseCaptureID = mep->getMediaID(); + setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture. + } + + return true; + } + + LLViewerMediaFocus::getInstance()->clearFocus(); + + return false; +} - return false; +bool LLToolPie::handleMediaDblClick(const LLPickInfo& pick) +{ + //FIXME: how do we handle object in different parcel than us? + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + LLPointer objectp = pick.getObject(); + + + if (!parcel || + objectp.isNull() || + pick.mObjectFace < 0 || + pick.mObjectFace >= objectp->getNumTEs()) + { + LLViewerMediaFocus::getInstance()->clearFocus(); + + return false; + } + + // Does this face have media? + const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); + if (!tep) + return false; + + LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL; + if (!mep) + return false; + + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); + + if (gSavedSettings.getBOOL("MediaOnAPrimUI")) + { + if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull()) + { + // It's okay to give this a null impl + LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal); + } + else + { + // Make sure keyboard focus is set to the media focus object. + gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance()); + LLEditMenuHandler::gEditMenuHandler = LLViewerMediaFocus::instance().getFocusedMediaImpl(); + + media_impl->mouseDoubleClick(pick.mUVCoords, gKeyboard->currentMask(TRUE)); + mMediaMouseCaptureID = mep->getMediaID(); + setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture. + } + + return true; + } + + LLViewerMediaFocus::getInstance()->clearFocus(); + + return false; } bool LLToolPie::handleMediaHover(const LLPickInfo& pick) @@ -939,7 +1062,7 @@ bool LLToolPie::handleMediaHover(const LLPickInfo& pick) LLPointer objectp = pick.getObject(); - // Early out cases. Must clear media hover. + // Early out cases. Must clear media hover. // did not hit an object or did not hit a valid face if ( objectp.isNull() || pick.mObjectFace < 0 || @@ -1212,12 +1335,10 @@ BOOL LLToolPie::handleRightClickPick() void LLToolPie::showVisualContextMenuEffect() { - // if (gSavedSettings.getBOOL("DisablePointAtAndBeam")) { return; } - // // VEFFECT: ShowPie LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); @@ -1263,6 +1384,7 @@ bool intersect_ray_with_sphere( const LLVector3& ray_pt, const LLVector3& ray_di void LLToolPie::startCameraSteering() { + //LLFirstUse::notMoving(false); mMouseOutsideSlop = true; mBlockClickToWalk = true; @@ -1370,7 +1492,7 @@ void LLToolPie::steerCameraWithMouse(S32 x, S32 y) { old_yaw_angle = F_PI_BY_TWO + asinf(pick_distance_from_rotation_center / camera_distance_from_rotation_center); - if (mouse_ray * rotation_frame.getLeftAxis() < 0.f) + if (old_mouse_ray * rotation_frame.getLeftAxis() < 0.f) { old_yaw_angle *= -1.f; } diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index 5f3c75c3b3..ffae5b9457 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -89,6 +89,7 @@ class LLToolPie : public LLTool, public LLSingleton ECursorType cursorFromObject(LLViewerObject* object); bool handleMediaClick(const LLPickInfo& info); + bool handleMediaDblClick(const LLPickInfo& info); bool handleMediaHover(const LLPickInfo& info); bool handleMediaMouseUp(); diff --git a/indra/newview/lltoolpipette.cpp b/indra/newview/lltoolpipette.cpp index 878ed0f9a9..c327a39084 100644 --- a/indra/newview/lltoolpipette.cpp +++ b/indra/newview/lltoolpipette.cpp @@ -67,7 +67,7 @@ BOOL LLToolPipette::handleMouseDown(S32 x, S32 y, MASK mask) mSuccess = TRUE; mTooltipMsg.clear(); setMouseCapture(TRUE); - gViewerWindow->pickAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE, TRUE); return TRUE; } diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp index 7baf8f2a7f..1c225398c1 100644 --- a/indra/newview/lltoolplacer.cpp +++ b/indra/newview/lltoolplacer.cpp @@ -95,7 +95,7 @@ BOOL LLToolPlacer::raycastForNewObjPos( S32 x, S32 y, LLViewerObject** hit_obj, // Viewer-side pick to find the right sim to create the object on. // First find the surface the object will be created on. - LLPickInfo pick = gViewerWindow->pickImmediate(x, y, FALSE); + LLPickInfo pick = gViewerWindow->pickImmediate(x, y, FALSE, TRUE); // Note: use the frontmost non-flora version because (a) plants usually have lots of alpha and (b) pants' Havok // representations (if any) are NOT the same as their viewer representation. diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index 4a9b6b0b79..4b53f057de 100644 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -69,7 +69,8 @@ LLToolSelect::LLToolSelect( LLToolComposite* composite ) BOOL LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask) { // do immediate pick query - mPick = gViewerWindow->pickImmediate(x, y, TRUE); + BOOL pick_rigged = true; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick"); + mPick = gViewerWindow->pickImmediate(x, y, TRUE, pick_rigged); // Pass mousedown to agent LLTool::handleMouseDown(x, y, mask); diff --git a/indra/newview/lltoolselectrect.cpp b/indra/newview/lltoolselectrect.cpp index 07f0cae82a..17c9efabca 100644 --- a/indra/newview/lltoolselectrect.cpp +++ b/indra/newview/lltoolselectrect.cpp @@ -78,7 +78,8 @@ void dialog_refresh_all(void); BOOL LLToolSelectRect::handleMouseDown(S32 x, S32 y, MASK mask) { - handlePick(gViewerWindow->pickImmediate(x, y, TRUE)); + BOOL pick_rigged = true; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick"); + handlePick(gViewerWindow->pickImmediate(x, y, TRUE /* pick_transparent */, pick_rigged)); LLTool::handleMouseDown(x, y, mask); diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp index 903b65a048..53abe129ea 100644 --- a/indra/newview/lltracker.cpp +++ b/indra/newview/lltracker.cpp @@ -596,7 +596,7 @@ void LLTracker::renderBeacon(LLVector3d pos_global, LLGLSTracker gls_tracker; // default+ CULL_FACE + LIGHTING + GL_BLEND + GL_ALPHA_TEST gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDisable cull_face(GL_CULL_FACE); + LLGLDisable cull_face; LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); draw_beacon(pos_agent, true, fogged_color, dist); diff --git a/indra/newview/lltracker.h b/indra/newview/lltracker.h index 5c62dbd1d5..1dc56ceed0 100644 --- a/indra/newview/lltracker.h +++ b/indra/newview/lltracker.h @@ -143,8 +143,8 @@ class LLTracker std::string mTrackedLandmarkName; LLUUID mTrackedLandmarkAssetID; LLUUID mTrackedLandmarkItemID; - std::vector mLandmarkAssetIDList; - std::vector mLandmarkItemIDList; + uuid_vec_t mLandmarkAssetIDList; + uuid_vec_t mLandmarkItemIDList; BOOL mHasReachedLandmark; BOOL mHasLandmarkPosition; BOOL mLandmarkHasBeenVisited; diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index 833926afe5..b639c75855 100644 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -35,7 +35,7 @@ #include "llbufferstream.h" #include "lltranslate.h" #include "llui.h" -#include "sgversion.h" +#include "llversioninfo.h" #include "llweb.h" // @@ -64,9 +64,12 @@ void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std std::string url; getTranslateUrl(url, fromLang, toLang, mesg); -// - std::string user_agent = gCurrentVersion; -// + std::string user_agent = llformat("%s %d.%d.%d (%d)", + LLVersionInfo::getChannel().c_str(), + LLVersionInfo::getMajor(), + LLVersionInfo::getMinor(), + LLVersionInfo::getPatch(), + LLVersionInfo::getBuild()); if (m_Header.empty()) { diff --git a/indra/newview/lluiavatar.cpp b/indra/newview/lluiavatar.cpp new file mode 100644 index 0000000000..e4e266c92a --- /dev/null +++ b/indra/newview/lluiavatar.cpp @@ -0,0 +1,61 @@ +/** + * @file lluiavatar.cpp + * @brief Implementation for special dummy avatar used in some UI views + * + * $LicenseInfo:firstyear=2017&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2017, 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 "llviewerprecompiledheaders.h" +#include "lluiavatar.h" +#include "llagent.h" // Get state values from here +#include "llviewerobjectlist.h" +#include "pipeline.h" +#include "llanimationstates.h" +#include "llviewercontrol.h" +#include "llmeshrepository.h" +#include "llviewerregion.h" + +LLUIAvatar::LLUIAvatar(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp) : + LLVOAvatar(id, pcode, regionp) +{ + mIsDummy = TRUE; + mIsUIAvatar = true; +} + +// virtual +LLUIAvatar::~LLUIAvatar() +{ +} + +// virtual +void LLUIAvatar::initInstance() +{ + LLVOAvatar::initInstance(); + + createDrawable( &gPipeline ); + setPositionAgent(LLVector3::zero); + slamPosition(); + updateJointLODs(); + updateGeometry(mDrawable); + + mInitFlags |= 1<<3; +} diff --git a/indra/newview/lluiavatar.h b/indra/newview/lluiavatar.h new file mode 100644 index 0000000000..bcdffedef2 --- /dev/null +++ b/indra/newview/lluiavatar.h @@ -0,0 +1,44 @@ +/** + * @file lluiavatar.h + * @brief Special dummy avatar used in some UI views + * + * $LicenseInfo:firstyear=2017&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2017, 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_UIAVATAR_H +#define LL_UIAVATAR_H + +#include "llvoavatar.h" +#include "llvovolume.h" + +class LLUIAvatar: + public LLVOAvatar +{ + LOG_CLASS(LLUIAvatar); + +public: + LLUIAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); + virtual void initInstance(); // Called after construction to initialize the class. + virtual ~LLUIAvatar(); +}; + +#endif //LL_CONTROLAVATAR_H diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index b9535d36ab..eb976171d1 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -144,7 +144,7 @@ bool LLURLDispatcherImpl::dispatch(const LLSLURL& slurl, bool LLURLDispatcherImpl::dispatchRightClick(const LLSLURL& slurl) { const bool right_click = true; - LLMediaCtrl* web = NULL; + LLMediaCtrl* web = nullptr; const bool trusted_browser = false; return dispatchCore(slurl, "clicked", right_click, web, trusted_browser); } @@ -187,11 +187,18 @@ bool LLURLDispatcherImpl::dispatchRegion(const LLSLURL& slurl, const std::string LLPanelLogin::setLocation(slurl); return true; } + LLSLURL _slurl = slurl; + const std::string& grid = slurl.getGrid(); + const std::string& current_grid = gHippoGridManager->getCurrentGrid()->getGridName(); + if (grid != current_grid) + { + _slurl = LLSLURL(llformat("%s:%s", grid.c_str(), slurl.getRegion().c_str()), slurl.getPosition()); + } // Request a region handle by name LLWorldMapMessage::getInstance()->sendNamedRegionRequest(slurl.getRegion(), LLURLDispatcherImpl::regionNameCallback, - slurl.getSLURLString(), + _slurl.getSLURLString(), LLUI::sConfigGroup->getBOOL("SLURLTeleportDirectly")); // don't teleport return true; } @@ -263,7 +270,8 @@ void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const LLSLURL& //--------------------------------------------------------------------------- // Teleportation links are handled here because they are tightly coupled -// to URL parsing and sim-fragment parsing +// to SLURL parsing and sim-fragment parsing + class LLTeleportHandler : public LLCommandHandler { public: @@ -272,8 +280,9 @@ class LLTeleportHandler : public LLCommandHandler // cause a constant teleport loop. JC LLTeleportHandler() : LLCommandHandler("teleport", UNTRUSTED_THROTTLE) { } + bool handle(const LLSD& tokens, const LLSD& query_map, - LLMediaCtrl* web) + LLMediaCtrl* web) override { // construct a "normal" SLURL, resolve the region to // a global position, and teleport to it @@ -287,12 +296,11 @@ class LLTeleportHandler : public LLCommandHandler tokens[3].asReal()); } - LLSD args; - args["LOCATION"] = tokens[0]; - // Region names may be %20 escaped. std::string region_name = LLURI::unescape(tokens[0]); + LLSD args; + args["LOCATION"] = region_name; LLSD payload; payload["region_name"] = region_name; @@ -351,7 +359,7 @@ bool LLURLDispatcher::dispatchRightClick(const std::string& slurl) } // static -bool LLURLDispatcher::dispatchFromTextEditor(const std::string& slurl) +bool LLURLDispatcher::dispatchFromTextEditor(const std::string& slurl, bool trusted_content) { // *NOTE: Text editors are considered sources of trusted URLs // in order to make avatar profile links in chat history work. @@ -359,9 +367,9 @@ bool LLURLDispatcher::dispatchFromTextEditor(const std::string& slurl) // receiving resident will see it and must affirmatively // click on it. // *TODO: Make this trust model more refined. JC - const bool trusted_browser = true; - LLMediaCtrl* web = NULL; - return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), "clicked", web, trusted_browser); + + LLMediaCtrl* web = nullptr; + return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), "clicked", web, trusted_content); } diff --git a/indra/newview/llurldispatcher.h b/indra/newview/llurldispatcher.h index 82e1d3152d..9b05260af1 100644 --- a/indra/newview/llurldispatcher.h +++ b/indra/newview/llurldispatcher.h @@ -2,36 +2,29 @@ * @file llurldispatcher.h * @brief Central registry for all SL URL handlers * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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 LLURLDISPATCHER_H #define LLURLDISPATCHER_H - class LLMediaCtrl; @@ -49,6 +42,8 @@ class LLURLDispatcher // secondlife://RegionName/123/45/67/ // secondlife:///app/agent/3d6181b0-6a4b-97ef-18d8-722652995cf1/show // sl://app/foo/bar + // @param nav_type + // type of navigation type (see LLQtWebKit::LLWebPage::acceptNavigationRequest) // @param web // Pointer to LLMediaCtrl sending URL, can be NULL // @param trusted_browser @@ -58,7 +53,7 @@ class LLURLDispatcher static bool dispatchRightClick(const std::string& slurl); - static bool dispatchFromTextEditor(const std::string& slurl); + static bool dispatchFromTextEditor(const std::string& slurl, bool trusted_content); }; #endif diff --git a/indra/newview/lluserauth.cpp b/indra/newview/lluserauth.cpp index d67c8d9d70..a2f0ea9e00 100644 --- a/indra/newview/lluserauth.cpp +++ b/indra/newview/lluserauth.cpp @@ -38,7 +38,7 @@ #include #include "lldir.h" -#include "sgversion.h" +#include "llversioninfo.h" #include "llappviewer.h" #include "llviewercontrol.h" #include "llxmlrpcresponder.h" @@ -128,8 +128,8 @@ void LLUserAuth::authenticate( XMLRPC_VectorAppendString(params, "last", lastname.c_str(), 0); XMLRPC_VectorAppendString(params, "web_login_key", web_login_key.getString().c_str(), 0); XMLRPC_VectorAppendString(params, "start", start.c_str(), 0); - XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0); // Includes channel name - XMLRPC_VectorAppendString(params, "channel", gVersionChannel, 0); + XMLRPC_VectorAppendString(params, "version", LLVersionInfo::getChannelAndVersion().c_str(), 0); // Includes channel name + XMLRPC_VectorAppendString(params, "channel", LLVersionInfo::getChannel().c_str(), 0); XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0); XMLRPC_VectorAppendString(params, "platform_version", LLAppViewer::instance()->getOSInfo().getOSVersionString().c_str(), 0); @@ -215,17 +215,13 @@ void LLUserAuth::authenticate( XMLRPC_VectorAppendString(params, "last", lastname.c_str(), 0); XMLRPC_VectorAppendString(params, "passwd", dpasswd.c_str(), 0); XMLRPC_VectorAppendString(params, "start", start.c_str(), 0); - XMLRPC_VectorAppendString(params, "version", llformat("%d.%d.%d.%d", gVersionMajor, gVersionMinor, gVersionPatch, gVersionBuild).c_str(), 0); + XMLRPC_VectorAppendString(params, "version", LLVersionInfo::getVersion().c_str(), 0); // Singu Note: At the request of Linden Lab we change channel sent to the login server in the following way: // * If channel is "Singularity" we change it to "Singularity Release", due to their statistics system // not being able to distinguish just the release version // * We append "64" to channel name on 64-bit for systems for the LL stats system to be able to produce independent // crash statistics depending on the architecture - std::string chan(gVersionChannel); - if (chan == "Singularity") - { - chan += " Release"; - } + std::string chan(LLVersionInfo::getChannel()); #if defined(_WIN64) || defined(__x86_64__) chan += " 64"; #endif diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp new file mode 100644 index 0000000000..765f107362 --- /dev/null +++ b/indra/newview/llversioninfo.cpp @@ -0,0 +1,179 @@ +/** + * @file llversioninfo.cpp + * @brief Routines to access the viewer version and build information + * @author Martin Reddy + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include +#include +#include "llversioninfo.h" +#include + +#if ! defined(LL_VIEWER_CHANNEL) \ + || ! defined(LL_VIEWER_VERSION_MAJOR) \ + || ! defined(LL_VIEWER_VERSION_MINOR) \ + || ! defined(LL_VIEWER_VERSION_PATCH) \ + || ! defined(LL_VIEWER_VERSION_BUILD) + #error "Channel or Version information is undefined" +#endif + +// +// Set the version numbers in indra/VIEWER_VERSION +// + +//static +S32 LLVersionInfo::getMajor() +{ + return LL_VIEWER_VERSION_MAJOR; +} + +//static +S32 LLVersionInfo::getMinor() +{ + return LL_VIEWER_VERSION_MINOR; +} + +//static +S32 LLVersionInfo::getPatch() +{ + return LL_VIEWER_VERSION_PATCH; +} + +//static +S32 LLVersionInfo::getBuild() +{ + return LL_VIEWER_VERSION_BUILD; +} + +//static +const std::string &LLVersionInfo::getVersion() +{ + static std::string version(""); + if (version.empty()) + { + std::ostringstream stream; + stream << LLVersionInfo::getShortVersion() << "." << LLVersionInfo::getBuild(); + // cache the version string + version = stream.str(); + } + return version; +} + +//static +const std::string &LLVersionInfo::getShortVersion() +{ + static std::string short_version(""); + if(short_version.empty()) + { + // cache the version string + std::ostringstream stream; + stream << LL_VIEWER_VERSION_MAJOR << "." + << LL_VIEWER_VERSION_MINOR << "." + << LL_VIEWER_VERSION_PATCH; + short_version = stream.str(); + } + return short_version; +} + +namespace +{ + /// Storage of the channel name the viewer is using. + // The channel name is set by hardcoded constant, + // or by calling LLVersionInfo::resetChannel() + std::string sWorkingChannelName(LL_VIEWER_CHANNEL); + + // Storage for the "version and channel" string. + // This will get reset too. + std::string sVersionChannel(""); +} + +//static +const std::string &LLVersionInfo::getChannelAndVersion() +{ + if (sVersionChannel.empty()) + { + // cache the version string + sVersionChannel = LLVersionInfo::getChannel() + " " + LLVersionInfo::getVersion(); + } + + return sVersionChannel; +} + +//static +const std::string &LLVersionInfo::getChannel() +{ + return sWorkingChannelName; +} + +void LLVersionInfo::resetChannel(const std::string& channel) +{ + sWorkingChannelName = channel; + sVersionChannel.clear(); // Reset version and channel string til next use. +} + +//static +LLVersionInfo::ViewerMaturity LLVersionInfo::getViewerMaturity() +{ + ViewerMaturity maturity; + + std::string channel = getChannel(); + + static const boost::regex is_test_channel("\\bTest\\b"); + static const boost::regex is_alpha_channel("\\bAlpha\\b"); + static const boost::regex is_beta_channel("\\bBeta\\b"); + static const boost::regex is_project_channel("\\bProject\\b"); + static const boost::regex is_release_channel("\\bRelease\\b"); + + if (boost::regex_search(channel, is_release_channel)) + { + maturity = RELEASE_VIEWER; + } + else if (boost::regex_search(channel, is_beta_channel)) + { + maturity = BETA_VIEWER; + } + else if (boost::regex_search(channel, is_alpha_channel)) + { + maturity = ALPHA_VIEWER; + } + else if (boost::regex_search(channel, is_project_channel)) + { + maturity = PROJECT_VIEWER; + } + else if (boost::regex_search(channel, is_test_channel)) + { + maturity = TEST_VIEWER; + } + else + { + LL_WARNS() << "Channel '" << channel + << "' does not follow naming convention, assuming Test" + << LL_ENDL; + maturity = TEST_VIEWER; + } + return maturity; +} + + diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h new file mode 100644 index 0000000000..049b6056b8 --- /dev/null +++ b/indra/newview/llversioninfo.h @@ -0,0 +1,83 @@ +/** + * @file llversioninfo.h + * @brief Routines to access the viewer version and build information + * @author Martin Reddy + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLVERSIONINFO_H +#define LL_LLVERSIONINFO_H + +#include +#include "stdtypes.h" + +/// +/// This API provides version information for the viewer. This +/// includes access to the major, minor, patch, and build integer +/// values, as well as human-readable string representations. All +/// viewer code that wants to query the current version should +/// use this API. +/// +class LLVersionInfo +{ +public: + /// return the major verion number as an integer + static S32 getMajor(); + + /// return the minor verion number as an integer + static S32 getMinor(); + + /// return the patch verion number as an integer + static S32 getPatch(); + + /// return the build number as an integer + static S32 getBuild(); + + /// return the full viewer version as a string like "2.0.0.200030" + static const std::string &getVersion(); + + /// return the viewer version as a string like "2.0.0" + static const std::string &getShortVersion(); + + /// return the viewer version and channel as a string + /// like "Second Life Release 2.0.0.200030" + static const std::string &getChannelAndVersion(); + + /// return the channel name, e.g. "Second Life" + static const std::string &getChannel(); + + /// reset the channel name used by the viewer. + static void resetChannel(const std::string& channel); + + typedef enum + { + TEST_VIEWER, + PROJECT_VIEWER, + ALPHA_VIEWER, + BETA_VIEWER, + RELEASE_VIEWER + } ViewerMaturity; + static ViewerMaturity getViewerMaturity(); +}; + +#endif diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index ed768eb093..7e41b4bddc 100644 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -110,7 +110,7 @@ LLViewerAssetStats::PerRegionStats::reset() } mFPS.reset(); - mTotalTime = 0; + mTotalTime = U64Microseconds(0); mStartTimestamp = LLViewerAssetStatsFF::get_timestamp(); } @@ -315,9 +315,9 @@ LLViewerAssetStats::asLLSD(bool compact_output) slot[enq_tag] = LLSD(S32(stats.mRequests[i].mEnqueued.getCount())); slot[deq_tag] = LLSD(S32(stats.mRequests[i].mDequeued.getCount())); slot[rcnt_tag] = LLSD(S32(stats.mRequests[i].mResponse.getCount())); - slot[rmin_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMin() * 1.0e-6)); - slot[rmax_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMax() * 1.0e-6)); - slot[rmean_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMean() * 1.0e-6)); + slot[rmin_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMin().valueInUnits())); + slot[rmax_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMax().valueInUnits())); + slot[rmean_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMean().valueInUnits())); } } @@ -334,13 +334,13 @@ LLViewerAssetStats::asLLSD(bool compact_output) grid_from_region_handle(it->first, &grid_x, &grid_y); reg_stat["grid_x"] = LLSD::Integer(grid_x); reg_stat["grid_y"] = LLSD::Integer(grid_y); - reg_stat["duration"] = LLSD::Real(stats.mTotalTime * 1.0e-6); + reg_stat["duration"] = LLSD::Real(stats.mTotalTime.valueInUnits()); regions.append(reg_stat); } LLSD ret = LLSD::emptyMap(); ret["regions"] = regions; - ret["duration"] = LLSD::Real((now - mResetTimestamp) * 1.0e-6); + ret["duration"] = LLSD::Real((now - mResetTimestamp).valueInUnits()); return ret; } @@ -524,88 +524,31 @@ asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool i // - gestures // - everything else. // - llassert_always(50 == LLViewerAssetType::AT_COUNT); // Multiple asset definitions are floating around so this requires some // maintenance and attention. - static const LLViewerAssetStats::EViewerAssetCategories asset_to_bin_map[LLViewerAssetType::AT_COUNT] = - { - LLViewerAssetStats::EVACTextureTempHTTPGet, // (0) AT_TEXTURE - LLViewerAssetStats::EVACSoundUDPGet, // AT_SOUND - LLViewerAssetStats::EVACOtherGet, // AT_CALLINGCARD - LLViewerAssetStats::EVACOtherGet, // AT_LANDMARK - LLViewerAssetStats::EVACOtherGet, // AT_SCRIPT - LLViewerAssetStats::EVACWearableUDPGet, // AT_CLOTHING - LLViewerAssetStats::EVACOtherGet, // AT_OBJECT - LLViewerAssetStats::EVACOtherGet, // AT_NOTECARD - LLViewerAssetStats::EVACOtherGet, // AT_CATEGORY - LLViewerAssetStats::EVACOtherGet, // AT_ROOT_CATEGORY - LLViewerAssetStats::EVACOtherGet, // (10) AT_LSL_TEXT - LLViewerAssetStats::EVACOtherGet, // AT_LSL_BYTECODE - LLViewerAssetStats::EVACOtherGet, // AT_TEXTURE_TGA - LLViewerAssetStats::EVACWearableUDPGet, // AT_BODYPART - LLViewerAssetStats::EVACOtherGet, // AT_TRASH - LLViewerAssetStats::EVACOtherGet, // AT_SNAPSHOT_CATEGORY - LLViewerAssetStats::EVACOtherGet, // AT_LOST_AND_FOUND - LLViewerAssetStats::EVACSoundUDPGet, // AT_SOUND_WAV - LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_TGA - LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_JPEG - LLViewerAssetStats::EVACGestureUDPGet, // (20) AT_ANIMATION - LLViewerAssetStats::EVACGestureUDPGet, // AT_GESTURE - LLViewerAssetStats::EVACOtherGet, // AT_SIMSTATE - LLViewerAssetStats::EVACOtherGet, // AT_FAVORITE - LLViewerAssetStats::EVACOtherGet, // AT_LINK - LLViewerAssetStats::EVACOtherGet, // AT_LINK_FOLDER - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // (30) - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // (40) - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // AT_MESH - // (50) - }; - - if (at < 0 || at >= LLViewerAssetType::AT_COUNT) + switch (at) { + case LLAssetType::AT_TEXTURE: + return is_temp ? with_http ? LLViewerAssetStats::EVACTextureTempHTTPGet : LLViewerAssetStats::EVACTextureTempUDPGet + : with_http ? LLViewerAssetStats::EVACTextureTempHTTPGet : LLViewerAssetStats::EVACTextureNonTempUDPGet; + break; + case LLAssetType::AT_SOUND: + case LLAssetType::AT_SOUND_WAV: + return LLViewerAssetStats::EVACSoundUDPGet; + break; + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + return LLViewerAssetStats::EVACWearableUDPGet; + break; + case LLAssetType::AT_ANIMATION: + case LLAssetType::AT_GESTURE: + return LLViewerAssetStats::EVACGestureUDPGet; + break; + case LLAssetType::AT_LANDMARK: + default: return LLViewerAssetStats::EVACOtherGet; + break; } - LLViewerAssetStats::EViewerAssetCategories ret(asset_to_bin_map[at]); - if (LLViewerAssetStats::EVACTextureTempHTTPGet == ret) - { - // Indexed with [is_temp][with_http] - static const LLViewerAssetStats::EViewerAssetCategories texture_bin_map[2][2] = - { - { - LLViewerAssetStats::EVACTextureNonTempUDPGet, - LLViewerAssetStats::EVACTextureNonTempHTTPGet, - }, - { - LLViewerAssetStats::EVACTextureTempUDPGet, - LLViewerAssetStats::EVACTextureTempHTTPGet, - } - }; - - ret = texture_bin_map[is_temp][with_http]; - } - return ret; } - } // anonymous namespace diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index 3381c01ed5..a1091daa1f 100644 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -94,7 +94,7 @@ class LLViewerAssetStats * for compatibility with the pre-existing timestamp on the texture * fetcher class, LLTextureFetch. */ - typedef U64 duration_t; +typedef U64Microseconds duration_t; /** * Type for the region identifier used in stats. Currently uses diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index c2c23891c6..7b6a6dd0cc 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -33,9 +33,12 @@ #include "message.h" #include "llagent.h" +#include "llviewerregion.h" + #include "lltransfersourceasset.h" #include "lltransfertargetvfile.h" #include "llviewerassetstats.h" +#include "llworld.h" ///---------------------------------------------------------------------------- /// LLViewerAssetRequest @@ -51,9 +54,10 @@ class LLViewerAssetRequest : public LLAssetRequest { public: - LLViewerAssetRequest(const LLUUID &uuid, const LLAssetType::EType type) + LLViewerAssetRequest(const LLUUID &uuid, const LLAssetType::EType type, bool with_http) : LLAssetRequest(uuid, type), - mMetricsStartTime(0) + mMetricsStartTime(0), + mWithHTTP(with_http) { } @@ -66,23 +70,30 @@ class LLViewerAssetRequest : public LLAssetRequest recordMetrics(); } + LLBaseDownloadRequest* getCopy() + { + return new LLViewerAssetRequest(*this); + } + bool operator==(const LLViewerAssetRequest& rhs) const { return mUUID == rhs.mUUID && mType == rhs.mType && mWithHTTP == rhs.mWithHTTP; } + protected: void recordMetrics() { - if (mMetricsStartTime) + if (mMetricsStartTime.value()) { // Okay, it appears this request was used for useful things. Record // the expected dequeue and duration of request processing. - LLViewerAssetStatsFF::record_dequeue_main(mType, false, false); - LLViewerAssetStatsFF::record_response_main(mType, false, false, + LLViewerAssetStatsFF::record_dequeue_main(mType, mWithHTTP, false); + LLViewerAssetStatsFF::record_response_main(mType, mWithHTTP, false, (LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime)); - mMetricsStartTime = 0; + mMetricsStartTime = (U32Seconds)0; } } public: LLViewerAssetStats::duration_t mMetricsStartTime; + bool mWithHTTP; }; ///---------------------------------------------------------------------------- @@ -113,7 +124,7 @@ void LLViewerAssetStorage::storeAssetData( bool is_priority, bool store_local, bool user_waiting, - F64 timeout) + F64Seconds timeout) { LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); LL_DEBUGS("AssetStorage") << "LLViewerAssetStorage::storeAssetData (legacy) " << tid << ":" << LLAssetType::lookup(asset_type) @@ -130,7 +141,6 @@ void LLViewerAssetStorage::storeAssetData( LLVFile vfile(mVFS, asset_id, asset_type, LLVFile::READ); S32 asset_size = vfile.getSize(); - LLAssetRequest *req = new LLAssetRequest(asset_id, asset_type); req->mUpCallback = callback; req->mUserData = user_data; @@ -138,7 +148,7 @@ void LLViewerAssetStorage::storeAssetData( if (asset_size < 1) { // This can happen if there's a bug in our code or if the VFS has been corrupted. - LL_WARNS() << "LLViewerAssetStorage::storeAssetData() Data _should_ already be in the VFS, but it's not! " << asset_id << LL_ENDL; + LL_WARNS("AssetStorage") << "LLViewerAssetStorage::storeAssetData() Data _should_ already be in the VFS, but it's not! " << asset_id << LL_ENDL; // LLAssetStorage metric: Zero size VFS reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" ); @@ -179,7 +189,7 @@ void LLViewerAssetStorage::storeAssetData( } else { - LL_WARNS() << "Probable corruption in VFS file, aborting store asset data" << LL_ENDL; + LL_WARNS("AssetStorage") << "Probable corruption in VFS file, aborting store asset data" << LL_ENDL; // LLAssetStorage metric: VFS corrupt - bogus size reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, asset_size, MR_VFS_CORRUPTION, __FILE__, __LINE__, "VFS corruption" ); @@ -208,7 +218,7 @@ void LLViewerAssetStorage::storeAssetData( } else { - LL_WARNS() << "AssetStorage: attempt to upload non-existent vfile " << asset_id << ":" << LLAssetType::lookup(asset_type) << LL_ENDL; + LL_WARNS("AssetStorage") << "AssetStorage: attempt to upload non-existent vfile " << asset_id << ":" << LLAssetType::lookup(asset_type) << LL_ENDL; // LLAssetStorage metric: Zero size VFS reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" ); if (callback) @@ -219,7 +229,7 @@ void LLViewerAssetStorage::storeAssetData( } else { - LL_WARNS() << "Attempt to move asset store request upstream w/o valid upstream provider" << LL_ENDL; + LL_WARNS("AssetStorage") << "Attempt to move asset store request upstream w/o valid upstream provider" << LL_ENDL; // LLAssetStorage metric: Upstream provider dead reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_NO_UPSTREAM, __FILE__, __LINE__, "No upstream provider" ); if (callback) @@ -238,7 +248,7 @@ void LLViewerAssetStorage::storeAssetData( bool temp_file, bool is_priority, bool user_waiting, - F64 timeout) + F64Seconds timeout) { if(filename.empty()) { @@ -302,6 +312,7 @@ void LLViewerAssetStorage::storeAssetData( { // LLAssetStorage metric: Zero size reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file was zero length" ); + fclose(fp); } else { @@ -342,10 +353,24 @@ void LLViewerAssetStorage::_queueDataRequest( BOOL duplicate, BOOL is_priority) { + queueRequestUDP(uuid, atype, callback, user_data, duplicate, is_priority); +} +void LLViewerAssetStorage::queueRequestUDP( + const LLUUID& uuid, + LLAssetType::EType atype, + LLGetAssetCallback callback, + void *user_data, + BOOL duplicate, + BOOL is_priority) +{ + LL_DEBUGS("ViewerAsset") << "Request asset via HTTP " << uuid << " type " << LLAssetType::lookup(atype) << LL_ENDL; + if (mUpstreamHost.isOk()) { - // stash the callback info so we can find it after we get the response message - LLViewerAssetRequest *req = new LLViewerAssetRequest(uuid, atype); + const auto region = gAgent.getRegion(); + // Fallback on UDP if we have no cap or haven't received caps. This means missing some UDP-only region assets before caps received, but that's better for HTTP only. + bool with_http = !region || !region->capabilitiesReceived() || !region->getViewerAssetUrl().empty(); + LLViewerAssetRequest *req = new LLViewerAssetRequest(uuid, atype, with_http); req->mDownCallback = callback; req->mUserData = user_data; req->mIsPriority = is_priority; @@ -355,26 +380,33 @@ void LLViewerAssetStorage::_queueDataRequest( // are piggy-backing and will artificially lower averages. req->mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); } - mPendingDownloads.push_back(req); + // This is the same as the current UDP logic - don't re-request a duplicate. if (!duplicate) { - // send request message to our upstream data provider - // Create a new asset transfer. - LLTransferSourceParamsAsset spa; - spa.setAsset(uuid, atype); - - // Set our destination file, and the completion callback. - LLTransferTargetParamsVFile tpvf; - tpvf.setAsset(uuid, atype); - tpvf.setCallback(downloadCompleteCallback, req); - - LL_DEBUGS("AssetStorage") << "Starting transfer for " << uuid << LL_ENDL; - LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET); - ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f)); - - LLViewerAssetStatsFF::record_enqueue_main(atype, false, false); + bool is_temp = false; + LLViewerAssetStatsFF::record_enqueue_main(atype, with_http, is_temp); + if (!with_http) // maintain this code for older grids + { + // send request message to our upstream data provider + // Create a new asset transfer. + LLTransferSourceParamsAsset spa; + spa.setAsset(uuid, atype); + + // Set our destination file, and the completion callback. + LLTransferTargetParamsVFile tpvf; + tpvf.setAsset(uuid, atype); + tpvf.setCallback(downloadCompleteCallback, *req); + + LL_DEBUGS("AssetStorage") << "Starting transfer for " << uuid << LL_ENDL; + LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET); + ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f)); + } + else + { + LLViewerAssetStorage::assetRequestCoro(req, uuid, atype, callback, user_data); + } } } else @@ -388,3 +420,138 @@ void LLViewerAssetStorage::_queueDataRequest( } } +extern AIHTTPTimeoutPolicy HTTPGetResponder_timeout; +class LLViewerAssetResponder : public LLHTTPClient::ResponderWithCompleted +{ +public: + LLViewerAssetResponder(const LLUUID& id, LLAssetType::EType type) : LLHTTPClient::ResponderWithCompleted() + , uuid(id), atype(type) + {} +private: + LLUUID uuid; + LLAssetType::EType atype; + + void completedRaw(LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) override + { + if (LLApp::isQuitting()) + { + // Bail out if result arrives after shutdown has been started. + return; + } + + LL_DEBUGS("ViewerAsset") << "request succeeded, url " << mURL << LL_ENDL; + + S32 result_code = LL_ERR_NOERR; + LLExtStat ext_status = LL_EXSTAT_NONE; + + if (!isGoodStatus(mStatus)) + { + LL_DEBUGS("ViewerAsset") << "request failed, status " << mStatus << LL_ENDL; + result_code = LL_ERR_ASSET_REQUEST_FAILED; + ext_status = LL_EXSTAT_NONE; + } + else + { + std::string raw; + decode_raw_body(channels, buffer, raw); + + S32 size = raw.size(); + if (size > 0) + { + // This create-then-rename flow is modeled on + // LLTransferTargetVFile, which is what was used in the UDP + // case. + LLUUID temp_id; + temp_id.generate(); + LLVFile vf(gAssetStorage->mVFS, temp_id, atype, LLVFile::WRITE); + vf.setMaxSize(size); + if (!vf.write((const U8*)raw.data(), size)) + { + // TODO asset-http: handle error + LL_WARNS("ViewerAsset") << "Failure in vf.write()" << LL_ENDL; + result_code = LL_ERR_ASSET_REQUEST_FAILED; + ext_status = LL_EXSTAT_VFS_CORRUPT; + } + else if (!vf.rename(uuid, atype)) + { + LL_WARNS("ViewerAsset") << "rename failed" << LL_ENDL; + result_code = LL_ERR_ASSET_REQUEST_FAILED; + ext_status = LL_EXSTAT_VFS_CORRUPT; + } + } + else + { + // TODO asset-http: handle invalid size case + LL_WARNS("ViewerAsset") << "bad size" << LL_ENDL; + result_code = LL_ERR_ASSET_REQUEST_FAILED; + ext_status = LL_EXSTAT_NONE; + } + } + + // Clean up pending downloads and trigger callbacks + gAssetStorage->removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + } + AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy() const override { return HTTPGetResponder_timeout; } + char const* getName() const override { return "assetRequestCoro"; } +}; + +void LLViewerAssetStorage::capsRecvForRegion(const LLUUID& uuid, LLAssetType::EType atype, const LLUUID& region_id) +{ + LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(region_id); + if (!regionp) + { + LL_WARNS("ViewerAsset") << "region not found for region_id " << region_id << LL_ENDL; + } + else + { + mViewerAssetUrl = regionp->getViewerAssetUrl(); + } + + LL_WARNS_ONCE("ViewerAsset") << "capsRecv got event" << LL_ENDL; + LL_WARNS_ONCE("ViewerAsset") << "region " << gAgent.getRegion() << " mViewerAssetUrl " << mViewerAssetUrl << LL_ENDL; + if (mViewerAssetUrl.empty()) + { + LL_WARNS_ONCE("ViewerAsset") << "asset request fails: caps received but no viewer asset cap found" << LL_ENDL; + auto result_code = LL_ERR_ASSET_REQUEST_FAILED; + auto ext_status = LL_EXSTAT_NONE; + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + return; + } + std::string url = getAssetURL(mViewerAssetUrl, uuid,atype); + LL_DEBUGS("ViewerAsset") << "request url: " << url << LL_ENDL; + + LLHTTPClient::get(url, new LLViewerAssetResponder(uuid, atype)); +} + +void LLViewerAssetStorage::assetRequestCoro( + LLViewerAssetRequest *req, + const LLUUID uuid, + LLAssetType::EType atype, + LLGetAssetCallback callback, + void *user_data) +{ + if (!gAgent.getRegion()) + { + LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL; + auto result_code = LL_ERR_ASSET_REQUEST_FAILED; + auto ext_status = LL_EXSTAT_NONE; + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + return; + } + else if (!gAgent.getRegion()->capabilitiesReceived()) + { + LL_WARNS_ONCE("ViewerAsset") << "Waiting for capabilities" << LL_ENDL; + + gAgent.getRegion()->setCapabilitiesReceivedCallback( + boost::bind(&LLViewerAssetStorage::capsRecvForRegion, this, uuid, atype, _1)); + } + else capsRecvForRegion(uuid, atype, gAgent.getRegion()->getRegionID()); +} + +std::string LLViewerAssetStorage::getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype) +{ + std::string type_name = LLAssetType::lookup(atype); + std::string url = cap_url + "/?" + type_name + "_id=" + uuid.asString(); + return url; +} + diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h index ca9b9943fa..75b2d87666 100644 --- a/indra/newview/llviewerassetstorage.h +++ b/indra/newview/llviewerassetstorage.h @@ -32,6 +32,8 @@ class LLVFile; +class LLViewerAssetRequest; + class LLViewerAssetStorage : public LLAssetStorage { public: @@ -41,7 +43,6 @@ class LLViewerAssetStorage : public LLAssetStorage LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS *vfs, LLVFS *static_vfs); - using LLAssetStorage::storeAssetData; virtual void storeAssetData( const LLTransactionID& tid, LLAssetType::EType atype, @@ -51,7 +52,7 @@ class LLViewerAssetStorage : public LLAssetStorage bool is_priority = false, bool store_local = false, bool user_waiting=FALSE, - F64 timeout=LL_ASSET_STORAGE_TIMEOUT); + F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT); virtual void storeAssetData( const std::string& filename, @@ -62,18 +63,35 @@ class LLViewerAssetStorage : public LLAssetStorage bool temp_file = false, bool is_priority = false, bool user_waiting=FALSE, - F64 timeout=LL_ASSET_STORAGE_TIMEOUT); + F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT); protected: - using LLAssetStorage::_queueDataRequest; - // virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, - void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), + LLGetAssetCallback callback, void *user_data, BOOL duplicate, BOOL is_priority); + + void queueRequestUDP(const LLUUID& uuid, + LLAssetType::EType type, + LLGetAssetCallback callback, + void *user_data, + BOOL duplicate, + BOOL is_priority); + + void capsRecvForRegion(const LLUUID& uuid, LLAssetType::EType atype, const LLUUID& region_id); + + void assetRequestCoro(LLViewerAssetRequest *req, + const LLUUID uuid, + LLAssetType::EType atype, + LLGetAssetCallback callback, + void *user_data); + + std::string getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype); + + std::string mViewerAssetUrl; }; #endif diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp index 3eee608820..b98767b1b9 100644 --- a/indra/newview/llviewerassettype.cpp +++ b/indra/newview/llviewerassettype.cpp @@ -88,7 +88,10 @@ LLViewerAssetDictionary::LLViewerAssetDictionary() addEntry(LLViewerAssetType::AT_MESH, new ViewerAssetEntry(DAD_MESH)); + addEntry(LLViewerAssetType::AT_UNKNOWN, new ViewerAssetEntry(DAD_NONE)); + addEntry(LLViewerAssetType::AT_NONE, new ViewerAssetEntry(DAD_NONE)); + addEntry(LLViewerAssetType::AT_SETTINGS, new ViewerAssetEntry(DAD_NONE)); }; EDragAndDropType LLViewerAssetType::lookupDragAndDropType(EType asset_type) diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index abe6ef8bd9..92f6421a76 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -156,7 +156,7 @@ void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zfli { LLVector3 frust[8]; - LLRect view_port(gGLViewport[0],gGLViewport[1]+gGLViewport[3],gGLViewport[0]+gGLViewport[2],gGLViewport[1]); + const LLRect& view_port = gGLViewport; if (no_hacks) { @@ -280,11 +280,8 @@ void LLViewerCamera::setPerspective(BOOL for_selection, { z_far = MAX_FAR_CLIP; } - glViewport(x, y_from_bot, width, height); - gGLViewport[0] = x; - gGLViewport[1] = y_from_bot; - gGLViewport[2] = width; - gGLViewport[3] = height; + gGLViewport.set(x, y_from_bot + height, x + width, y_from_bot); + gGL.setViewport(gGLViewport); } if (mZoomFactor > 1.f) @@ -352,7 +349,7 @@ void LLViewerCamera::projectScreenToPosAgent(const S32 screen_x, const S32 scree { gGL.unprojectf( LLVector3(screen_x,screen_y,0.f), - gGLModelView, gGLProjection, LLRect(gGLViewport[0],gGLViewport[1]+gGLViewport[3],gGLViewport[0]+gGLViewport[2],gGLViewport[1]), + gGLModelView, gGLProjection, gGLViewport, *pos_agent ); } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index ba8d99b401..e1a7a04ef0 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -70,7 +70,6 @@ #include "llnotify.h" #include "llkeyboard.h" #include "llerrorcontrol.h" -#include "sgversion.h" #include "llappviewer.h" #include "llvosurfacepatch.h" #include "llvowlsky.h" @@ -95,10 +94,8 @@ AIThreadSafeDC gSettings; LLControlGroup gSavedSettings("Global"); // saved at end of session LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session LLControlGroup gColors("Colors"); // saved at end of session -LLControlGroup gCrashSettings("CrashSettings"); // saved at end of session std::string gLastRunVersion; -std::string gCurrentVersion; extern BOOL gResizeScreenTexture; extern BOOL gDebugGL; @@ -140,6 +137,16 @@ bool handleStateMachineMaxTimeChanged(const LLSD& newvalue) return true; } +extern bool sInwlfPanelUpdate; +static bool handleAvatarHoverOffsetChanged(const LLSD& newvalue) +{ + if (!sInwlfPanelUpdate && isAgentAvatarValid()) + { + gAgentAvatarp->setHoverIfRegionEnabled(); + } + return true; +} + static bool handleSetShaderChanged(const LLSD& newvalue) { // changing shader level may invalidate existing cached bump maps, as the shader type determines the format of the bump map it expects - clear and repopulate the bump cache @@ -327,7 +334,7 @@ static bool handleMaxPartCountChanged(const LLSD& newvalue) static bool handleVideoMemoryChanged(const LLSD& newvalue) { - gTextureList.updateMaxResidentTexMem(newvalue.asInteger()); + gTextureList.updateMaxResidentTexMem(S32Megabytes(newvalue.asInteger())); return true; } @@ -447,6 +454,7 @@ static bool handleRepartition(const LLSD&) if (gPipeline.isInit()) { gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); + gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize"); gOctreeReserveCapacity = llmin(gSavedSettings.getU32("OctreeReserveNodeCapacity"),U32(512)); gObjectList.repartitionObjects(); } @@ -461,7 +469,7 @@ static bool handleRenderDynamicLODChanged(const LLSD& newvalue) static bool handleRenderLocalLightsChanged(const LLSD& newvalue) { - gPipeline.setLightingDetail(-1); + gPipeline.updateLocalLightingEnabled(); return true; } @@ -654,13 +662,28 @@ static bool handleAllowLargeSounds(const LLSD& newvalue) return true; } +enum DCAction { AUTOPILOT, TELEPORT }; +static void handleDoubleClickActionChanged(const DCAction& action, const LLSD& newvalue) +{ + // Doubleclick actions - there can be only one + if (newvalue.asBoolean()) + { + if (action == AUTOPILOT) + gSavedSettings.setBOOL("DoubleClickTeleport", false); + else + gSavedSettings.setBOOL("DoubleClickAutoPilot", false); + } +} + void handleHighResChanged(const LLSD& val) { if (val) // High Res Snapshot active, must uncheck RenderUIInSnapshot gSavedSettings.setBOOL("RenderUIInSnapshot", false); } +void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value); //////////////////////////////////////////////////////////////////////////// + void settings_setup_listeners() { gSavedSettings.getControl("FirstPersonAvatarVisible")->getSignal()->connect(boost::bind(&handleRenderAvatarMouselookChanged, _2)); @@ -670,6 +693,7 @@ void settings_setup_listeners() gSavedSettings.getControl("OctreeStaticObjectSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeMaxNodeCapacity")->getSignal()->connect(boost::bind(&handleRepartition, _2)); + gSavedSettings.getControl("OctreeMinimumNodeSize")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeReserveNodeCapacity")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeAlphaDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeAttachmentSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); @@ -711,6 +735,7 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("SHUseRMSEAutoMask")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("SHAutoMaskMaxRMSE")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); + gSavedSettings.getControl("SHAutoMaskMaxMid")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("SHAltBatching")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); @@ -823,7 +848,8 @@ void settings_setup_listeners() gSavedSettings.getControl("SkyUseClassicClouds")->getSignal()->connect(boost::bind(&handleCloudSettingsChanged, _2)); gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2)); gSavedSettings.getControl("AlchemyWLCloudTexture")->getSignal()->connect(boost::bind(&handleWindlightCloudChanged, _2)); - + gSavedSettings.getControl("RenderAutoMuteByteLimit")->getSignal()->connect(boost::bind(&handleRenderAutoMuteByteLimitChanged, _2)); + gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ")->getCommitSignal()->connect(boost::bind(&handleAvatarHoverOffsetChanged, _2)); gSavedSettings.getControl("AscentAvatarXModifier")->getSignal()->connect(boost::bind(&handleAscentAvatarModifier, _2)); gSavedSettings.getControl("AscentAvatarYModifier")->getSignal()->connect(boost::bind(&handleAscentAvatarModifier, _2)); gSavedSettings.getControl("AscentAvatarZModifier")->getSignal()->connect(boost::bind(&handleAscentAvatarModifier, _2)); @@ -855,6 +881,8 @@ void settings_setup_listeners() gSavedSettings.getControl("AllowLargeSounds")->getSignal()->connect(boost::bind(&handleAllowLargeSounds, _2)); gSavedSettings.getControl("LiruUseZQSDKeys")->getSignal()->connect(boost::bind(load_default_bindings, _2)); + gSavedSettings.getControl("DoubleClickAutoPilot")->getSignal()->connect(boost::bind(handleDoubleClickActionChanged, AUTOPILOT, _2)); + gSavedSettings.getControl("DoubleClickTeleport")->getSignal()->connect(boost::bind(handleDoubleClickActionChanged, TELEPORT, _2)); gSavedSettings.getControl("HighResSnapshot")->getSignal()->connect(boost::bind(&handleHighResChanged, _2)); } diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h index d8bdf3670b..203c5cfb34 100644 --- a/indra/newview/llviewercontrol.h +++ b/indra/newview/llviewercontrol.h @@ -62,13 +62,8 @@ void create_graphics_group(LLControlGroup& group); // Read-only extern LLControlGroup gColors; -// Saved at end of session -extern LLControlGroup gCrashSettings; - // Set after settings loaded extern std::string gLastRunVersion; -extern std::string gCurrentVersion; - bool handleCloudSettingsChanged(const LLSD& newvalue); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 3d57b6b4bb..6d694ca3bb 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -81,6 +81,7 @@ #include "llviewerregion.h" #include "lldrawpoolwater.h" #include "lldrawpoolbump.h" +#include "lldrawpoolavatar.h" #include "llwlparammanager.h" #include "llwaterparammanager.h" #include "llpostprocess.h" @@ -146,22 +147,22 @@ void display_startup() // Required for HTML update in login screen static S32 frame_count = 0; - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); if (frame_count++ > 1) // make sure we have rendered a frame first { LLViewerDynamicTexture::updateAllInstances(); } - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); gViewerWindow->updateUI(); // Fix ui flicker. + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); LLGLSUIDefault gls_ui; - gPipeline.disableLights(); gViewerWindow->setup2DRender(); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); @@ -172,10 +173,11 @@ void display_startup() LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); gViewerWindow->getWindow()->swapBuffers(); + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT); } @@ -236,9 +238,9 @@ void display_stats() F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency"); if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq) { - gMemoryAllocated = LLMemory::getCurrentRSS(); - U32 memory = (U32)(gMemoryAllocated / (1024*1024)); - LL_INFOS() << llformat("MEMORY: %d MB", memory) << LL_ENDL; + gMemoryAllocated = U64Bytes(LLMemory::getCurrentRSS()); + U32Megabytes memory = gMemoryAllocated; + LL_INFOS() << "MEMORY: " << memory << LL_ENDL; LL_INFOS() << "THREADS: "<< LLThread::getCount() << LL_ENDL; LL_INFOS() << "MALLOC: " << SGMemStat::getPrintableStat() <getWindow()->getFullscreen() && (!gViewerWindow->getWindow() || !gViewerWindow->getWindow()->getVisible() || !gFocusMgr.getAppHasFocus())) + { + return; + }*/ + gViewerWindow->checkSettings(); + LLVBOPool::deleteReleasedBuffers(); + + for (auto avatar : LLCharacter::sInstances) + { + LLVOAvatar* avatarp = dynamic_cast(avatar); + if (!avatarp) continue; + if (avatarp->isDead()) continue; + avatarp->clearRiggedMatrixCache(); + } + sCurCacheHit = 0; if (gWindowResized) { //skip render on frames where window has been resized gGL.flush(); + gGL.syncContextState(); glClear(GL_COLOR_BUFFER_BIT); gViewerWindow->getWindow()->swapBuffers(); LLPipeline::refreshCachedSettings(); @@ -290,12 +312,13 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); stop_glerror(); - gPipeline.disableLights(); + LLGLState light_state; + gPipeline.disableLights(light_state); //reset vertex buffers if needed gPipeline.doResetVertexBuffers(); @@ -323,23 +346,16 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo stop_glerror(); return; } - - gViewerWindow->checkSettings(); - - if(gWindowResized) //Singu Note: gViewerWindow->checkSettings() can call LLViewerWindow::reshape(). If it has then skip this frame. - { - return; - } { - LLFastTimer ftm(FTM_PICK); + LL_RECORD_BLOCK_TIME(FTM_PICK); LLAppViewer::instance()->pingMainloopTimeout("Display:Pick"); gViewerWindow->performPick(); } LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates"); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); ////////////////////////////////////////////////////////// // @@ -634,10 +650,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES)) { LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures"); - LLFastTimer t(FTM_UPDATE_TEXTURES); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_TEXTURES); if (LLViewerDynamicTexture::updateAllInstances()) { gGL.setColorMask(true, true); + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT); } } @@ -677,7 +694,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time gPipeline.createObjects(max_geom_update_time); gPipeline.processPartitionQ(); - gPipeline.updateGeom(max_geom_update_time); + gPipeline.updateGeom(max_geom_update_time, *LLViewerCamera::getInstance()); stop_glerror(); gPipeline.updateGL(); stop_glerror(); @@ -719,9 +736,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo } gDepthDirty = FALSE; - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + LLGLStateValidator::checkClientArrays(); static LLCullResult result; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; @@ -729,9 +746,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip); stop_glerror(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + LLGLStateValidator::checkClientArrays(); BOOL to_texture = LLGLSLShader::sNoFixedFunction && LLPipeline::sRenderGlow; @@ -749,9 +766,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo gGL.setColorMask(true, true); glClearColor(0,0,0,0); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + LLGLStateValidator::checkClientArrays(); if (!for_snapshot || LLPipeline::sRenderDeferred) { @@ -763,13 +780,13 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + LLGLStateValidator::checkClientArrays(); const LLMatrix4a saved_proj = glh_get_current_projection(); const LLMatrix4a saved_mod = glh_get_current_modelview(); - glViewport(0,0,512,512); + gGL.setViewport(0,0,512,512); LLVOAvatar::updateFreezeCounter() ; if(!LLPipeline::sMemAllocationThrottled) @@ -785,16 +802,17 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo gGL.loadMatrix(saved_mod); gViewerWindow->setup3DViewport(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + LLGLStateValidator::checkClientArrays(); } + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } - LLGLState::checkStates(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkClientArrays(); //if (!for_snapshot) { @@ -803,8 +821,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo gPipeline.renderPhysicsDisplay(); } - LLGLState::checkStates(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkClientArrays(); ////////////////////////////////////// // @@ -819,37 +837,37 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo gFrameStats.start(LLFrameStats::IMAGE_UPDATE); { - LLFastTimer t(FTM_IMAGE_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE); { - LLFastTimer t(FTM_IMAGE_UPDATE_CLASS); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_CLASS); LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(), LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean()); } { - LLFastTimer t(FTM_IMAGE_UPDATE_BUMP); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_BUMP); gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first. } { - LLFastTimer t(FTM_IMAGE_UPDATE_LIST); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_LIST); F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame) gTextureList.updateImages(max_image_decode_time); } /*{ - LLFastTimer t(FTM_IMAGE_UPDATE_DELETE); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_DELETE); //remove dead textures from GL LLImageGL::deleteDeadTextures(); stop_glerror(); }*/ } LL_PUSH_CALLSTACKS(); - LLGLState::checkStates(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkClientArrays(); /////////////////////////////////// // @@ -879,14 +897,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo } } - LLGLState::checkStates(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkClientArrays(); LLPipeline::sUseOcclusion = occlusion; { LLAppViewer::instance()->pingMainloopTimeout("Display:Sky"); - LLFastTimer t(FTM_UPDATE_SKY); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_SKY); gSky.updateSky(); } @@ -896,10 +914,13 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo // [/RLVa:KB] { glClearColor(0.5f, 0.5f, 0.5f, 0.f); + gGL.syncContextState(); glClear(GL_COLOR_BUFFER_BIT); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_LINE); } + LLVBOPool::deleteReleasedBuffers(); + LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart"); //// render frontmost floater opaque for occlusion culling purposes @@ -941,8 +962,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; - LLGLState::checkStates(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkClientArrays(); stop_glerror(); @@ -998,11 +1019,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo gGL.loadIdentity(); gGL.color4fv( LLColor4::white.mV ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLE_STRIP ); gGL.vertex3f(rect.mLeft, rect.mTop,0.f); gGL.vertex3f(rect.mLeft, rect.mBottom,0.f); + gGL.vertex3f(rect.mRight, rect.mTop, 0.f); gGL.vertex3f(rect.mRight, rect.mBottom,0.f); - gGL.vertex3f(rect.mRight, rect.mTop,0.f); gGL.end(); gGL.matrixMode(LLRender::MM_PROJECTION); @@ -1017,7 +1038,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo if (render_depth_pre_pass && LLGLSLShader::sNoFixedFunction) { LLGLDepthTest depth(GL_TRUE, GL_TRUE); - LLGLEnable cull_face(GL_CULL_FACE); + LLGLEnable cull_face; gGL.setColorMask(false, false); U32 types[] = { @@ -1036,6 +1057,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo } gGL.setColorMask(true, false); + LLGLEnable lighting; + LLGLEnable normalize; if (LLPipeline::sRenderDeferred) { gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance()); @@ -1106,7 +1129,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); if (!for_snapshot || LLPipeline::sRenderDeferred) { - LLFastTimer t(FTM_RENDER_UI); + LL_RECORD_BLOCK_TIME(FTM_RENDER_UI); gFrameStats.start(LLFrameStats::RENDER_UI); render_ui(); } @@ -1134,6 +1157,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo LLAppViewer::instance()->pingMainloopTimeout("Display:Done"); gShiftFrame = false; + + LLVBOPool::deleteReleasedBuffers(); } void render_hud_attachments() @@ -1152,7 +1177,7 @@ void render_hud_attachments() gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, (!gRlvAttachmentLocks.hasLockedHUD()) ? 0.1f : 0.85f, 1.f); // [/RLVa:KB] // smoothly interpolate current zoom level - gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f)); + gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLSmoothInterpolation::getInterpolant(0.03f)); if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices()) { @@ -1213,8 +1238,6 @@ void render_hud_attachments() gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY); gPipeline.stateSort(hud_cam, result); @@ -1327,11 +1350,11 @@ BOOL setup_hud_matrices(const LLRect& screen_region) return TRUE; } -static LLFastTimer::DeclareTimer FTM_SWAP("Swap"); +static LLTrace::BlockTimerStatHandle FTM_SWAP("Swap"); void render_ui(F32 zoom_factor, int subfield, bool tiling) { - LLGLState::checkStates(); + LLGLStateValidator::checkStates(); const LLMatrix4a saved_view = glh_get_current_modelview(); @@ -1362,20 +1385,17 @@ void render_ui(F32 zoom_factor, int subfield, bool tiling) LLGLSDefault gls_default; LLGLSUIDefault gls_ui; - { - gPipeline.disableLights(); - } { gGL.color4f(1,1,1,1); if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { - LLFastTimer t(FTM_RENDER_UI); + LL_RECORD_BLOCK_TIME(FTM_RENDER_UI); if (!gDisconnected) { render_ui_3d(); - LLGLState::checkStates(); + LLGLStateValidator::checkStates(); } else { @@ -1383,7 +1403,7 @@ void render_ui(F32 zoom_factor, int subfield, bool tiling) } render_ui_2d(); - LLGLState::checkStates(); + LLGLStateValidator::checkStates(); } gGL.flush(); @@ -1404,7 +1424,7 @@ void render_ui(F32 zoom_factor, int subfield, bool tiling) if (gDisplaySwapBuffers) { - LLFastTimer t(FTM_SWAP); + LL_RECORD_BLOCK_TIME(FTM_SWAP); gViewerWindow->getWindow()->swapBuffers(); } gDisplaySwapBuffers = TRUE; @@ -1525,7 +1545,7 @@ void render_ui_2d() // Render 2D UI elements that overlay the world (no z compare) // Disable wireframe mode below here, as this is HUD/menus - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); // Menu overlays, HUD, etc gViewerWindow->setup2DRender(); diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp index c7f8170321..1e559072a3 100644 --- a/indra/newview/llviewerdisplayname.cpp +++ b/indra/newview/llviewerdisplayname.cpp @@ -56,25 +56,22 @@ namespace LLViewerDisplayName void doNothing() { } } -class LLSetDisplayNameResponder : public LLHTTPClient::ResponderIgnoreBody +class LLSetDisplayNameResponder final : public LLHTTPClient::ResponderIgnoreBody { LOG_CLASS(LLSetDisplayNameResponder); private: // only care about errors - /*virtual*/ void httpFailure() + void httpFailure() override { - LL_WARNS() << dumpResponse() << LL_ENDL; - LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD()); + LLViewerDisplayName::sSetDisplayNameSignal(false, LLStringUtil::null, LLSD()); LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots(); } - /*virtual*/ char const* getName(void) const { return "LLSetDisplayNameResponder"; } + char const* getName() const override { return "LLSetDisplayNameResponder"; } }; void LLViewerDisplayName::set(const std::string& display_name, const set_name_slot_t& slot) { - // TODO: simple validation here - LLViewerRegion* region = gAgent.getRegion(); llassert(region); std::string cap_url = region->getCapability("SetDisplayName"); @@ -93,7 +90,7 @@ void LLViewerDisplayName::set(const std::string& display_name, const set_name_sl // Our display name will be in cache before the viewer's UI is available // to request a change, so we can use direct lookup without callback. LLAvatarName av_name; - if (!LLAvatarNameCache::get( gAgent.getID(), &av_name)) + if (!LLAvatarNameCache::get(gAgent.getID(), &av_name)) { slot(false, "name unavailable", LLSD()); return; @@ -104,8 +101,6 @@ void LLViewerDisplayName::set(const std::string& display_name, const set_name_sl change_array.append(av_name.getDisplayName()); change_array.append(display_name); - LL_INFOS() << "Set name POST to " << cap_url << LL_ENDL; - // Record our caller for when the server sends back a reply sSetDisplayNameSignal.connect(slot); @@ -117,14 +112,14 @@ void LLViewerDisplayName::set(const std::string& display_name, const set_name_sl LLHTTPClient::post(cap_url, body, new LLSetDisplayNameResponder, headers); } -class LLSetDisplayNameReply : public LLHTTPNode +class LLSetDisplayNameReply final : public LLHTTPNode { LOG_CLASS(LLSetDisplayNameReply); public: /*virtual*/ void post( LLHTTPNode::ResponsePtr response, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { LLSD body = input["body"]; @@ -157,12 +152,12 @@ class LLSetDisplayNameReply : public LLHTTPNode }; -class LLDisplayNameUpdate : public LLHTTPNode +class LLDisplayNameUpdate final : public LLHTTPNode { /*virtual*/ void post( LLHTTPNode::ResponsePtr response, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { LLSD body = input["body"]; LLUUID agent_id = body["agent_id"]; @@ -195,7 +190,7 @@ class LLDisplayNameUpdate : public LLHTTPNode { LLSD args; args["OLD_NAME"] = old_display_name; - args["SLID"] = av_name.getUserName(); + args["SLID"] = "secondlife:///app/agent/" + agent_id.asString() + "/username"; args["NEW_NAME"] = av_name.getDisplayName(); LLNotificationsUtil::add("DisplayNameUpdate", args); } diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index fbabfa5405..11809193b1 100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llviewerfoldertype.h" +#include "llcontrol.h" #include "lldictionary.h" #include "llmemory.h" #include "llvisualparam.h" @@ -131,12 +132,16 @@ LLViewerFolderDictionary::LLViewerFolderDictionary() addEntry(LLFolderType::FT_OUTFIT, new ViewerFolderEntry("New Outfit", "inv_folder_outfit.tga", "inv_folder_outfit.tga", TRUE, false)); addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "inv_folder_outfit.tga", "inv_folder_outfit.tga", TRUE, false)); addEntry(LLFolderType::FT_MESH, new ViewerFolderEntry("Meshes", "inv_folder_mesh.tga", "inv_folder_mesh.tga", FALSE, false)); - + + //bool boxes_invisible = !gSavedSettings.getBOOL("InventoryOutboxMakeVisible"); addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Received Items", "inv_folder_inbox.tga", "inv_folder_inbox.tga", FALSE, false)); - addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Merchant Outbox", "inv_folder_outbox.tga", "inv_folder_outbox.tga", FALSE, false)); + addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Merchant Outbox", "inv_folder_outbox.tga", "inv_folder_outbox.tga", FALSE, true)); addEntry(LLFolderType::FT_BASIC_ROOT, new ViewerFolderEntry("Basic Root", "inv_folder_plain_open.tga", "inv_folder_plain_closed.tga", FALSE, false)); + addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new ViewerFolderEntry("Marketplace Listings", "inv_folder_plain_open.tga", "inv_folder_plain_closed.tga", FALSE, true)); + addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new ViewerFolderEntry("New Stock", "Inv_StockFolderOpen", "Inv_StockFolderClosed", FALSE, false, "default")); + addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new ViewerFolderEntry("New Version", "Inv_VersionFolderOpen", "Inv_VersionFolderClosed", FALSE, false, "default")); addEntry(LLFolderType::FT_SUITCASE, new ViewerFolderEntry("My Suitcase", "inv_folder_plain_open.tga", "inv_folder_plain_closed.tga", FALSE, false)); addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "inv_folder_plain_open.tga", "inv_folder_plain_closed.tga", FALSE, false, "default")); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index dec9ddb358..db781e6b51 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2014, 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 @@ -50,8 +50,8 @@ #include "llinventorypanel.h" #include "llfloaterinventory.h" #include "llfloaterperms.h" +#include "lllandmarkactions.h" -#include "lllandmark.h" #include "llviewerassettype.h" #include "llviewerregion.h" #include "llviewerobjectlist.h" @@ -62,6 +62,7 @@ #include "llcommandhandler.h" #include "llviewermessage.h" #include "llavatarnamecache.h" +#include "llfavoritesbar.h" #include "llsdutil.h" @@ -83,14 +84,44 @@ static const char * const LOG_INV("Inventory"); static const char * const LOG_LOCAL("InventoryLocalize"); static const char * const LOG_NOTECARD("copy_inventory_from_notecard"); +#if 1 +// *TODO$: LLInventoryCallback should be deprecated to conform to the new boost::bind/coroutine model. +// temp code in transition +void doInventoryCb(LLPointer cb, LLUUID id) +{ + if (cb.notNull()) + cb->fire(id); +} +#endif + ///---------------------------------------------------------------------------- /// Helper class to store special inventory item names and their localized values. ///---------------------------------------------------------------------------- -class LLLocalizedInventoryItemsDictionary : public LLSingleton +class LLLocalizedInventoryItemsDictionary final : public LLSingleton { public: std::map mInventoryItemsDict; + /** + * Finds passed name in dictionary and replaces it with found localized value. + * + * @param object_name - string to be localized. + * @return true if passed name was found and localized, false otherwise. + */ + bool localizeInventoryObjectName(std::string& object_name) + { + LL_DEBUGS(LOG_LOCAL) << "Searching for localization: " << object_name << LL_ENDL; + + std::map::const_iterator dictionary_iter = mInventoryItemsDict.find(object_name); + + bool found = dictionary_iter != mInventoryItemsDict.end(); + if(found) + { + object_name = dictionary_iter->second; + LL_DEBUGS(LOG_LOCAL) << "Found, new name is: " << object_name << LL_ENDL; + } + return found; + } LLLocalizedInventoryItemsDictionary() { mInventoryItemsDict["New Shape"] = LLTrans::getString("New Shape"); @@ -108,6 +139,7 @@ class LLLocalizedInventoryItemsDictionary : public LLSingleton::const_iterator dictionary_iter = mInventoryItemsDict.find(object_name); - - bool found = dictionary_iter != mInventoryItemsDict.end(); - if(found) - { - object_name = dictionary_iter->second; - LL_DEBUGS(LOG_LOCAL) << "Found, new name is: " << object_name << LL_ENDL; - } - return found; - } }; @@ -316,6 +327,7 @@ void LLViewerInventoryItem::updateServer(BOOL is_new) const if(!mIsComplete) { // *FIX: deal with this better. + // If we're crashing here then the UI is incorrectly enabled. LL_ERRS(LOG_INV) << "LLViewerInventoryItem::updateServer() - for incomplete item" << LL_ENDL; LLNotificationsUtil::add("IncompleteInventoryItem"); @@ -332,16 +344,42 @@ void LLViewerInventoryItem::updateServer(BOOL is_new) const LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0); gInventory.accountForUpdate(up); - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_UpdateInventoryItem); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_TransactionID, mTransactionID); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addU32Fast(_PREHASH_CallbackID, 0); - packMessage(msg); - gAgent.sendReliableMessage(); + if (AISAPI::isAvailable()) + { + LLSD updates = asLLSD(); + // Replace asset_id and/or shadow_id with transaction_id (hash_id) + if (updates.has("asset_id")) + { + updates.erase("asset_id"); + if(getTransactionID().notNull()) + { + updates["hash_id"] = getTransactionID(); + } + } + if (updates.has("shadow_id")) + { + updates.erase("shadow_id"); + if(getTransactionID().notNull()) + { + updates["hash_id"] = getTransactionID(); + } + } + AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer)NULL, _1); + AISAPI::UpdateItem(getUUID(), updates, cr); + } + else + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_UpdateInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_TransactionID, mTransactionID); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addU32Fast(_PREHASH_CallbackID, 0); + packMessage(msg); + gAgent.sendReliableMessage(); + } } void LLViewerInventoryItem::fetchFromServer(void) const @@ -369,28 +407,28 @@ void LLViewerInventoryItem::fetchFromServer(void) const { LL_WARNS(LOG_INV) << "Agent Region is absent" << LL_ENDL; } + } - if (!url.empty()) - { - LLSD body; - body["agent_id"] = gAgent.getID(); - body["items"][0]["owner_id"] = mPermissions.getOwner(); - body["items"][0]["item_id"] = mUUID; + if (!url.empty()) + { + LLSD body; + body["agent_id"] = gAgent.getID(); + body["items"][0]["owner_id"] = mPermissions.getOwner(); + body["items"][0]["item_id"] = mUUID; - LLHTTPClient::post(url, body, new LLInventoryModel::FetchItemHttpHandler(body)); - } - else - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("FetchInventory"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("InventoryData"); - msg->addUUID("OwnerID", mPermissions.getOwner()); - msg->addUUID("ItemID", mUUID); - gAgent.sendReliableMessage(); - } + LLHTTPClient::post(url, body, new LLInventoryModel::FetchItemHttpHandler(body)); + } + else + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("FetchInventory"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("InventoryData"); + msg->addUUID("OwnerID", mPermissions.getOwner()); + msg->addUUID("ItemID", mUUID); + gAgent.sendReliableMessage(); } } } @@ -421,7 +459,7 @@ void LLViewerInventoryItem::setTransactionID(const LLTransactionID& transaction_ { mTransactionID = transaction_id; } -// virtual + void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const { msg->addUUIDFast(_PREHASH_ItemID, mUUID); @@ -440,6 +478,7 @@ void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const U32 crc = getCRC32(); msg->addU32Fast(_PREHASH_CRC, crc); } + // virtual BOOL LLViewerInventoryItem::importFile(LLFILE* fp) { @@ -584,18 +623,26 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const LLNotificationsUtil::add("CannotModifyProtectedCategories"); return; } + if (AISAPI::isAvailable()) + { + LLSD new_llsd = asLLSD(); + AISAPI::completion_t cr = boost::bind(&doInventoryCb, LLPointer(NULL), _1); + AISAPI::UpdateCategory(getUUID(), new_llsd, cr); + } + else + { + LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0); + gInventory.accountForUpdate(up); - LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0); - gInventory.accountForUpdate(up); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_UpdateInventoryFolder); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_FolderData); - packMessage(msg); - gAgent.sendReliableMessage(); + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_UpdateInventoryFolder); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_FolderData); + packMessage(msg); + gAgent.sendReliableMessage(); + } } S32 LLViewerInventoryCategory::getVersion() const @@ -769,6 +816,36 @@ bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const return true; } +bool LLViewerInventoryCategory::acceptItem(LLInventoryItem* inv_item) +{ + if (!inv_item) + { + return false; + } + + // Only stock folders have limitation on which item they will accept + bool accept = true; + if (getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + // If the item is copyable (i.e. non stock) do not accept the drop in a stock folder + if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + accept = false; + } + else + { + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(getUUID(),cat_array,item_array); + // Destination stock folder must be empty OR types of incoming and existing items must be identical and have the same permissions + accept = (item_array->empty() || + ((item_array->at(0)->getInventoryType() == inv_item->getInventoryType()) && + (item_array->at(0)->getPermissions().getMaskNextOwner() == inv_item->getPermissions().getMaskNextOwner()))); + } + } + return accept; +} + void LLViewerInventoryCategory::determineFolderType() { /* Do NOT uncomment this code. This is for future 2.1 support of ensembles. @@ -825,18 +902,33 @@ void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type) const LLUUID &folder_id = getUUID(); const LLUUID &parent_id = getParentUUID(); const std::string &name = getName(); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_UpdateInventoryFolder); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_FolderData); - msg->addUUIDFast(_PREHASH_FolderID, folder_id); - msg->addUUIDFast(_PREHASH_ParentID, parent_id); - msg->addS8Fast(_PREHASH_Type, new_folder_type); - msg->addStringFast(_PREHASH_Name, name); - gAgent.sendReliableMessage(); + if (AISAPI::isAvailable()) + { + LLPointer new_cat = new LLViewerInventoryCategory(folder_id, + parent_id, + new_folder_type, + name, + gAgent.getID()); + + + LLSD new_llsd = new_cat->asLLSD(); + AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer) NULL, _1); + AISAPI::UpdateCategory(folder_id, new_llsd, cr); + } + else + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_UpdateInventoryFolder); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_FolderData); + msg->addUUIDFast(_PREHASH_FolderID, folder_id); + msg->addUUIDFast(_PREHASH_ParentID, parent_id); + msg->addS8Fast(_PREHASH_Type, new_folder_type); + msg->addStringFast(_PREHASH_Name, name); + gAgent.sendReliableMessage(); + } setPreferredType(new_folder_type); gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id); @@ -894,10 +986,10 @@ void LLInventoryCallbackManager::destroyClass() { if (sInstance) { - for (callback_map_t::iterator it = sInstance->mMap.begin(), end_it = sInstance->mMap.end(); it != end_it; ++it) + for (auto& it : sInstance->mMap) { // drop LLPointer reference to callback - it->second = NULL; + it.second = NULL; } sInstance->mMap.clear(); } @@ -933,7 +1025,7 @@ void LLInventoryCallbackManager::fire(U32 callback_id, const LLUUID& item_id) } //void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp) -// [SL:KB] - Patch: Appearance-DnDWear | Checked: 2010-09-28 (Catznip-3.0.0a) | Added: Catznip-2.2.0a +// [SL:KB] - Patch: Appearance-DnDWear | Checked: 2010-09-28 (Catznip-3.4) void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp, bool replace) // [/SL:KB] { @@ -963,6 +1055,22 @@ void activate_gesture_cb(const LLUUID& inv_item) LLGestureMgr::instance().activateGesture(inv_item); } +void set_default_permissions(LLViewerInventoryItem* item, std::string perm_type) +{ + llassert(item); + LLPermissions perm = item->getPermissions(); + if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms(perm_type) + || perm.getMaskGroup() != LLFloaterPerms::getGroupPerms(perm_type)) + { + perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms(perm_type)); + perm.setMaskGroup(LLFloaterPerms::getGroupPerms(perm_type)); + + item->setPermissions(perm); + + item->updateServer(FALSE); + } +} + void create_script_cb(const LLUUID& inv_item) { if (!inv_item.isNull()) @@ -970,13 +1078,9 @@ void create_script_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Scripts")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Scripts")); - - item->setPermissions(perm); + set_default_permissions(item, "Scripts"); - item->updateServer(FALSE); + // item was just created, update even if permissions did not changed gInventory.updateItem(item); gInventory.notifyObservers(); } @@ -992,16 +1096,12 @@ void create_gesture_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Gestures")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Gestures")); + set_default_permissions(item, "Gestures"); - item->setPermissions(perm); - - item->updateServer(FALSE); gInventory.updateItem(item); gInventory.notifyObservers(); + if (!LLPreview::show(inv_item,FALSE)) { LLPreviewGesture* preview = LLPreviewGesture::show(std::string("Gesture: ") + item->getName(), inv_item, LLUUID::null); @@ -1012,6 +1112,7 @@ void create_gesture_cb(const LLUUID& inv_item) } } + void create_notecard_cb(const LLUUID& inv_item) { if (!inv_item.isNull()) @@ -1019,26 +1120,14 @@ void create_notecard_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Notecards")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Notecards")); + set_default_permissions(item, "Notecards"); - item->setPermissions(perm); - - item->updateServer(FALSE); gInventory.updateItem(item); gInventory.notifyObservers(); } } } -void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) -{ - if (mTargetLandmarkId.isNull()) return; - - //gInventory.rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); // MULTI-WEARABLES TODO -} - LLInventoryCallbackManager gInventoryCallbacks; void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id, @@ -1090,10 +1179,10 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id, void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent /*= LLUUID::null*/, LLPointer cb/*=NULL*/) { std::string item_desc = avatar_id.asString(); - std::string item_name; - gCacheName->getFullName(avatar_id, item_name); + LLAvatarName av_name; + LLAvatarNameCache::get(avatar_id, &av_name); create_inventory_item(gAgent.getID(), gAgent.getSessionID(), - parent, LLTransactionID::tnull, item_name, item_desc, LLAssetType::AT_CALLINGCARD, + parent, LLTransactionID::tnull, av_name.getLegacyName(), item_desc, LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, cb); } @@ -1226,16 +1315,14 @@ void link_inventory_array(const LLUUID& category, #endif } - bool ais_ran = false; - if (AISCommand::isAPIAvailable()) + if (AISAPI::isAvailable()) { LLSD new_inventory = LLSD::emptyMap(); new_inventory["links"] = links; - boost::intrusive_ptr cmd_ptr = new CreateInventoryCommand(category, new_inventory, cb); - ais_ran = cmd_ptr->run_command(); + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::CreateInventory(category, new_inventory, cr); } - - if (!ais_ran) + else { LLMessageSystem* msg = gMessageSystem; for (LLSD::array_iterator iter = links.beginArray(); iter != links.endArray(); ++iter ) @@ -1292,25 +1379,30 @@ void update_inventory_item( LLPointer cb) { const LLUUID& item_id = update_item->getUUID(); - bool ais_ran = false; - if (AISCommand::isAPIAvailable()) + if (AISAPI::isAvailable()) { LLSD updates = update_item->asLLSD(); // Replace asset_id and/or shadow_id with transaction_id (hash_id) if (updates.has("asset_id")) { updates.erase("asset_id"); - updates["hash_id"] = update_item->getTransactionID(); + if (update_item->getTransactionID().notNull()) + { + updates["hash_id"] = update_item->getTransactionID(); + } } if (updates.has("shadow_id")) { updates.erase("shadow_id"); - updates["hash_id"] = update_item->getTransactionID(); + if (update_item->getTransactionID().notNull()) + { + updates["hash_id"] = update_item->getTransactionID(); + } } - boost::intrusive_ptr cmd_ptr = new UpdateItemCommand(item_id, updates, cb); - ais_ran = cmd_ptr->run_command(); + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::UpdateItem(item_id, updates, cr); } - if (!ais_ran) + else { LLPointer obj = gInventory.getItem(item_id); LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << LL_ENDL; @@ -1346,42 +1438,21 @@ void update_inventory_item( const LLSD& updates, LLPointer cb) { -// [SL:KB] - Patch: Appearance-AISFilter | Checked: 2015-03-01 (Catznip-3.7) - LLPointer obj = gInventory.getItem(item_id); - LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL; - LLPointer new_item = NULL; - - if (obj) + if (AISAPI::isAvailable()) { - new_item = new LLViewerInventoryItem(obj); - new_item->fromLLSD(updates,false); - - LLInventoryModel::LLCategoryUpdate up(new_item->getParentUUID(), 0); - gInventory.accountForUpdate(up); - gInventory.updateItem(new_item); - } -// [/SL:KB] - - bool ais_ran = false; - if (AISCommand::isAPIAvailable()) - { - boost::intrusive_ptr cmd_ptr = new UpdateItemCommand(item_id, updates, cb); - ais_ran = cmd_ptr->run_command(); + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::UpdateItem(item_id, updates, cr); } - if (!ais_ran) + else { -// LLPointer obj = gInventory.getItem(item_id); -// LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL; -// if(obj) -// { -// LLPointer new_item(new LLViewerInventoryItem); -// new_item->copyViewerItem(obj); -// new_item->fromLLSD(updates,false); - -// [SL:KB] - Patch: Appearance-AISFilter | Checked: 2015-03-01 (Catznip-3.7) - if (new_item) + LLPointer obj = gInventory.getItem(item_id); + LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL; + if(obj) { -// [/SL:KB] + LLPointer new_item(new LLViewerInventoryItem); + new_item->copyViewerItem(obj); + new_item->fromLLSD(updates,false); + LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_UpdateInventoryItem); msg->nextBlockFast(_PREHASH_AgentData); @@ -1393,9 +1464,9 @@ void update_inventory_item( new_item->packMessage(msg); gAgent.sendReliableMessage(); -// LLInventoryModel::LLCategoryUpdate up(new_item->getParentUUID(), 0); -// gInventory.accountForUpdate(up); -// gInventory.updateItem(new_item); + LLInventoryModel::LLCategoryUpdate up(new_item->getParentUUID(), 0); + gInventory.accountForUpdate(up); + gInventory.updateItem(new_item); if (cb) { cb->fire(item_id); @@ -1421,12 +1492,11 @@ void update_inventory_category( LLPointer new_cat = new LLViewerInventoryCategory(obj); new_cat->fromLLSD(updates); - // FIXME - restore this once the back-end work has been done. - if (AISCommand::isAPIAvailable()) + if (AISAPI::isAvailable()) { LLSD new_llsd = new_cat->asLLSD(); - boost::intrusive_ptr cmd_ptr = new UpdateCategoryCommand(cat_id, new_llsd, cb); - cmd_ptr->run_command(); + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::UpdateCategory(cat_id, new_llsd, cr); } else // no cap { @@ -1455,11 +1525,9 @@ void remove_inventory_items( LLPointer cb ) { - for (LLInventoryObject::object_list_t::iterator it = items_to_kill.begin(); - it != items_to_kill.end(); - ++it) + for (auto& it : items_to_kill) { - remove_inventory_item(*it, cb); + remove_inventory_item(it, cb); } } @@ -1488,10 +1556,10 @@ void remove_inventory_item( { const LLUUID item_id(obj->getUUID()); LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << obj->getName() << LL_ENDL; - if (AISCommand::isAPIAvailable()) + if (AISAPI::isAvailable()) { - boost::intrusive_ptr cmd_ptr = new RemoveItemCommand(item_id, cb); - cmd_ptr->run_command(); + AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); + AISAPI::RemoveItem(item_id, cr); if (immediate_delete) { @@ -1533,7 +1601,7 @@ class LLRemoveCategoryOnDestroy: public LLInventoryCallback mCB(cb) { } - /* virtual */ void fire(const LLUUID& item_id) {} + /* virtual */ void fire(const LLUUID& item_id) override {} ~LLRemoveCategoryOnDestroy() { LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(mID); @@ -1559,15 +1627,19 @@ void remove_inventory_category( LLPointer obj = gInventory.getCategory(cat_id); if(obj) { + if (!gInventory.isCategoryComplete(cat_id)) + { + LL_WARNS() << "Removing (purging) incomplete category " << obj->getName() << LL_ENDL; + } if(LLFolderType::lookupIsProtectedType(obj->getPreferredType())) { LLNotificationsUtil::add("CannotRemoveProtectedCategories"); return; } - if (AISCommand::isAPIAvailable()) + if (AISAPI::isAvailable()) { - boost::intrusive_ptr cmd_ptr = new RemoveCategoryCommand(cat_id, cb); - cmd_ptr->run_command(); + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::RemoveCategory(cat_id, cr); } else // no cap { @@ -1645,7 +1717,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) LLInventoryModel::item_array_t* items; // Get the list of direct descendants in tha categoy passed as argument gInventory.getDirectDescendentsOf(id, categories, items); - std::vector list_uuids; + uuid_vec_t list_uuids; // Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently) // Note: we need to do that shallow copy as purging things will invalidate the categories or items lists for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it) @@ -1657,7 +1729,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) list_uuids.push_back((*it)->getUUID()); } // Iterate through the list and only purge the UUIDs that are not on the clipboard - for (std::vector::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it) + for (auto it = list_uuids.begin(); it != list_uuids.end(); ++it) { if (!LLInventoryClipboard::instance().isOnClipboard(*it)) { @@ -1667,10 +1739,10 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) } else { - if (AISCommand::isAPIAvailable()) + if (AISAPI::isAvailable()) { - boost::intrusive_ptr cmd_ptr = new PurgeDescendentsCommand(id, cb); - cmd_ptr->run_command(); + AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); + AISAPI::PurgeDescendents(id, cr); } else // no cap { @@ -1779,9 +1851,9 @@ void create_new_item(const std::string& name, LLViewerAssetType::generateDescriptionFor(asset_type, desc); next_owner_perm = (next_owner_perm) ? next_owner_perm : PERM_MOVE | PERM_TRANSFER; - LLPointer cb = NULL; + LLPointer cb = nullptr; - switch(inv_type) + switch (inv_type) { case LLInventoryType::IT_LSL: { @@ -1883,12 +1955,13 @@ void slam_inventory_folder(const LLUUID& folder_id, const LLSD& contents, LLPointer cb) { - if (AISCommand::isAPIAvailable()) + if (AISAPI::isAvailable()) { LL_DEBUGS(LOG_INV) << "using AISv3 to slam folder, id " << folder_id << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL; - boost::intrusive_ptr cmd_ptr = new SlamFolderCommand(folder_id, contents, cb); - cmd_ptr->run_command(); + + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::SlamFolder(folder_id, contents, cr); } else // no cap { @@ -1932,9 +2005,9 @@ void remove_folder_contents(const LLUUID& category, bool keep_outfit_links, LLInventoryModel::item_array_t items; gInventory.collectDescendents(category, cats, items, LLInventoryModel::EXCLUDE_TRASH); - for (U32 i = 0; i < items.size(); ++i) + for (auto& i : items) { - LLViewerInventoryItem *item = items.at(i); + LLViewerInventoryItem *item = i; if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER)) continue; if (item->getIsLinkType()) @@ -2013,7 +2086,7 @@ const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probabl } else { - LL_WARNS() << "Can't create unrecognized type " << type_name << LL_ENDL; + LL_WARNS(LOG_INV) << "Can't create unrecognized type " << type_name << LL_ENDL; } } root->setNeedsAutoRename(TRUE); @@ -2090,17 +2163,21 @@ const std::string& LLViewerInventoryItem::getName() const return LLInventoryItem::getName(); } -#if 0 S32 LLViewerInventoryItem::getSortField() const { return LLFavoritesOrderStorage::instance().getSortIndex(mUUID); } +//void LLViewerInventoryItem::setSortField(S32 sortField) +//{ +// LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField); +// getSLURL(); +//} + void LLViewerInventoryItem::getSLURL() { LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID); } -#endif const LLPermissions& LLViewerInventoryItem::getPermissions() const { @@ -2185,7 +2262,7 @@ void LLViewerInventoryItem::setWearableType(LLWearableType::EType type) LL_WARNS() << "Calling LLViewerInventoryItem::setWearableType for item that does not have an unknown wearable type!?" << LL_ENDL; return; } - mFlags = (mFlags & ~LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK) | type; + mFlags = (mFlags & ~LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK) | type; } time_t LLViewerInventoryItem::getCreationDate() const @@ -2198,6 +2275,33 @@ U32 LLViewerInventoryItem::getCRC32() const return LLInventoryItem::getCRC32(); } +// *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985 +static char getSeparator() { return '@'; } +BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) +{ + const char separator = getSeparator(); + const std::string::size_type separatorPos = name.find(separator, 0); + + BOOL result = FALSE; + + if (separatorPos < std::string::npos) + { + if (sortField) + { + *sortField = std::stoi(name.substr(0, separatorPos)); + } + + if (displayName) + { + *displayName = name.substr(separatorPos + 1, std::string::npos); + } + + result = TRUE; + } + + return result; +} + // This returns true if the item that this item points to // doesn't exist in memory (i.e. LLInventoryModel). The baseitem // might still be in the database but just not loaded yet. @@ -2269,9 +2373,9 @@ PermissionMask LLViewerInventoryItem::getPermissionMask() const //---------- -void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& name, bool is_group) +void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const LLAvatarName& name) { - rename(name); + rename(name.getLegacyName()); gInventory.addChangedMask(LLInventoryObserver::LABEL, getUUID()); gInventory.notifyObservers(); } @@ -2280,9 +2384,10 @@ class LLRegenerateLinkCollector : public LLInventoryCollectFunctor { public: LLRegenerateLinkCollector(const LLViewerInventoryItem *target_item) : mTargetItem(target_item) {} - virtual ~LLRegenerateLinkCollector() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item) + virtual ~LLRegenerateLinkCollector() = default; + + bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item) override { if (item) { @@ -2310,12 +2415,10 @@ LLUUID find_possible_item_for_regeneration(const LLViewerInventoryItem *target_i items, LLInventoryModel::EXCLUDE_TRASH, candidate_matches); - for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items.begin(); - item_iter != items.end(); - ++item_iter) + for (const LLViewerInventoryItem* item : items) { - const LLViewerInventoryItem *item = (*item_iter); - if (true) return item->getUUID(); + if(item) + return item->getUUID(); } return LLUUID::null; } @@ -2335,11 +2438,9 @@ BOOL LLViewerInventoryItem::regenerateLink() items, LLInventoryModel::EXCLUDE_TRASH, asset_id_matches); - for (LLViewerInventoryItem::item_array_t::iterator item_iter = items.begin(); - item_iter != items.end(); - item_iter++) + for (auto& item_iter : items) { - LLViewerInventoryItem *item = (*item_iter); + LLViewerInventoryItem *item = item_iter; item->setAssetUUID(target_item_id); item->updateServer(FALSE); gInventory.addChangedMask(LLInventoryObserver::REBUILD, item->getUUID()); diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 7b9db72342..e24beb89ab 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -42,6 +42,7 @@ class LLFolderView; class LLFolderBridge; class LLViewerInventoryCategory; +class LLAvatarName; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLViewerInventoryItem @@ -50,7 +51,7 @@ class LLViewerInventoryCategory; // their inventory. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::trackable +class LLViewerInventoryItem final : public LLInventoryItem, public boost::signals2::trackable { public: typedef std::vector > item_array_t; @@ -59,21 +60,26 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr ~LLViewerInventoryItem( void ); // ref counted public: - virtual LLAssetType::EType getType() const; - virtual const LLUUID& getAssetUUID() const; + LLAssetType::EType getType() const override; + const LLUUID& getAssetUUID() const override; virtual const LLUUID& getProtectedAssetUUID() const; // returns LLUUID::null if current agent does not have permission to expose this asset's UUID to the user - virtual const std::string& getName() const; - virtual const LLPermissions& getPermissions() const; + const std::string& getName() const override; + virtual S32 getSortField() const; + //virtual void setSortField(S32 sortField); + virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here. + const LLPermissions& getPermissions() const override; virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied - virtual const LLUUID& getCreatorUUID() const; - virtual const std::string& getDescription() const; - virtual const LLSaleInfo& getSaleInfo() const; - virtual LLInventoryType::EType getInventoryType() const; + const LLUUID& getCreatorUUID() const override; + const std::string& getDescription() const override; + const LLSaleInfo& getSaleInfo() const override; + LLInventoryType::EType getInventoryType() const override; virtual bool isWearableType() const; virtual LLWearableType::EType getWearableType() const; - virtual U32 getFlags() const; - virtual time_t getCreationDate() const; - virtual U32 getCRC32() const; // really more of a checksum. + U32 getFlags() const override; + time_t getCreationDate() const override; + U32 getCRC32() const override; // really more of a checksum. + + static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName); // construct a complete viewer inventory item LLViewerInventoryItem(const LLUUID& uuid, const LLUUID& parent_uuid, @@ -107,7 +113,7 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr LLViewerInventoryItem(const LLInventoryItem* other); void copyViewerItem(const LLViewerInventoryItem* other); - /*virtual*/ void copyItem(const LLInventoryItem* other); + /*virtual*/ void copyItem(const LLInventoryItem* other) override; // construct a new clone of this item - it creates a new viewer // inventory item using the copy constructor, and returns it. @@ -115,15 +121,15 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr void cloneViewerItem(LLPointer& newitem) const; // virtual methods - virtual void updateParentOnServer(BOOL restamp) const; - virtual void updateServer(BOOL is_new) const; + void updateParentOnServer(BOOL restamp) const override; + void updateServer(BOOL is_new) const override; void fetchFromServer(void) const; - virtual void packMessage(LLMessageSystem* msg) const; - virtual BOOL unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); + void packMessage(LLMessageSystem* msg) const override; + BOOL unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0) override; virtual BOOL unpackMessage(const LLSD& item); - virtual BOOL importFile(LLFILE* fp); - virtual BOOL importLegacyStream(std::istream& input_stream); + BOOL importFile(LLFILE* fp) override; + BOOL importLegacyStream(std::istream& input_stream) override; // file handling on the viewer. These are not meant for anything // other than cacheing. @@ -155,7 +161,7 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr PermissionMask getPermissionMask() const; // callback - void onCallingCardNameLookup(const LLUUID& id, const std::string& name, bool is_group); + void onCallingCardNameLookup(const LLUUID& id, const LLAvatarName& name); // If this is a broken link, try to fix it and any other identical link. BOOL regenerateLink(); @@ -179,7 +185,7 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr // new ones as needed. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLViewerInventoryCategory : public LLInventoryCategory +class LLViewerInventoryCategory final : public LLInventoryCategory { public: typedef std::vector > cat_array_t; @@ -199,10 +205,10 @@ class LLViewerInventoryCategory : public LLInventoryCategory LLViewerInventoryCategory(const LLViewerInventoryCategory* other); void copyViewerCategory(const LLViewerInventoryCategory* other); - virtual void updateParentOnServer(BOOL restamp_children) const; - virtual void updateServer(BOOL is_new) const; + void updateParentOnServer(BOOL restamp_children) const override; + void updateServer(BOOL is_new) const override; - virtual void packMessage(LLMessageSystem* msg) const; + void packMessage(LLMessageSystem* msg) const override; const LLUUID& getOwnerID() const { return mOwnerID; } @@ -229,9 +235,12 @@ class LLViewerInventoryCategory : public LLInventoryCategory bool importFileLocal(LLFILE* fp); void determineFolderType(); void changeType(LLFolderType::EType new_folder_type); - virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); + void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0) override; virtual BOOL unpackMessage(const LLSD& category); + // returns true if the category object will accept the incoming item + bool acceptItem(LLInventoryItem* inv_item); + private: friend class LLInventoryModel; void localizeName(); // intended to be called from the LLInventoryModel @@ -251,37 +260,37 @@ class LLInventoryCallback : public LLRefCount class LLViewerJointAttachment; -//void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp); -// [SL:KB] - Patch: Appearance-DnDWear | Checked: 2010-09-28 (Catznip-3.0.0a) | Added: Catznip-2.2.0a +// [SL:KB] - Patch: Appearance-DnDWear | Checked: 2010-09-28 (Catznip-3.4) void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp, bool replace = false); // [/SL:KB] +//void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp); void activate_gesture_cb(const LLUUID& inv_item); void create_gesture_cb(const LLUUID& inv_item); -class AddFavoriteLandmarkCallback : public LLInventoryCallback +class AddFavoriteLandmarkCallback final : public LLInventoryCallback { public: AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {} void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; } private: - void fire(const LLUUID& inv_item); + void fire(const LLUUID& inv_item) override; LLUUID mTargetLandmarkId; }; -typedef boost::function inventory_func_type; -typedef boost::function llsd_func_type; -typedef boost::function nullary_func_type; +typedef std::function inventory_func_type; +typedef std::function llsd_func_type; +typedef std::function nullary_func_type; void no_op_inventory_func(const LLUUID&); // A do-nothing inventory_func void no_op_llsd_func(const LLSD&); // likewise for LLSD void no_op(); // A do-nothing nullary func. // Shim between inventory callback and boost function/callable -class LLBoostFuncInventoryCallback: public LLInventoryCallback +class LLBoostFuncInventoryCallback : public LLInventoryCallback { public: @@ -293,7 +302,7 @@ class LLBoostFuncInventoryCallback: public LLInventoryCallback } // virtual - void fire(const LLUUID& item_id) + void fire(const LLUUID& item_id) override { mFireFunc(item_id); } diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp index 2ce4760926..47f967a352 100644 --- a/indra/newview/llviewerjoint.cpp +++ b/indra/newview/llviewerjoint.cpp @@ -48,14 +48,13 @@ LLViewerJoint::LLViewerJoint() : LLAvatarJoint() { } -LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent) : - LLAvatarJoint(name, parent) -{ } - LLViewerJoint::LLViewerJoint(S32 joint_num) : LLAvatarJoint(joint_num) { } +LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent) : + LLAvatarJoint(name, parent) +{ } //----------------------------------------------------------------------------- // ~LLViewerJoint() @@ -99,7 +98,7 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) if ((pixelArea > MIN_PIXEL_AREA_3PASS_HAIR)) { // render all three passes - LLGLDisable cull(GL_CULL_FACE); + LLGLDisable cull; // first pass renders without writing to the z buffer { LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index 4c1192c1ab..1b118ec63a 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -83,15 +83,15 @@ U32 LLViewerJointAttachment::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_ { if (LLVOAvatar::sShowAttachmentPoints) { - LLGLDisable cull_face(GL_CULL_FACE); + LLGLDisable cull_face; gGL.color4f(1.f, 1.f, 1.f, 1.f); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); { gGL.vertex3f(-0.1f, 0.1f, 0.f); gGL.vertex3f(-0.1f, -0.1f, 0.f); - gGL.vertex3f(0.1f, -0.1f, 0.f); gGL.vertex3f(0.1f, 0.1f, 0.f); + gGL.vertex3f(0.1f, -0.1f, 0.f); }gGL.end(); } return 0; @@ -361,6 +361,25 @@ void LLViewerJointAttachment::setOriginalPosition(LLVector3& position) setPosition(position); } +//----------------------------------------------------------------------------- +// getNumAnimatedObjects() +//----------------------------------------------------------------------------- +S32 LLViewerJointAttachment::getNumAnimatedObjects() const +{ + S32 count = 0; + for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin(); + iter != mAttachedObjects.end(); + ++iter) + { + const LLViewerObject *attached_object = *iter; + if (attached_object->isAnimatedObject()) + { + count++; + } + } + return count; +} + //----------------------------------------------------------------------------- // clampObjectPosition() //----------------------------------------------------------------------------- diff --git a/indra/newview/llviewerjointattachment.h b/indra/newview/llviewerjointattachment.h index bb94c3678f..20eb429570 100644 --- a/indra/newview/llviewerjointattachment.h +++ b/indra/newview/llviewerjointattachment.h @@ -87,6 +87,7 @@ class LLViewerJointAttachment : S32 getGroup() const { return mGroup; } S32 getPieSlice() const { return mPieSlice; } S32 getNumObjects() const { return mAttachedObjects.size(); } + S32 getNumAnimatedObjects() const; void clampObjectPosition(); diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 9ba3b804a3..549a67757b 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -255,7 +255,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) //---------------------------------------------------------------- llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive - LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP; LLViewerTexLayerSet *layerset = dynamic_cast(mLayerSet); if (mTestImageName) { @@ -292,19 +291,13 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) else if ( !is_dummy && mTexture.notNull() ) { - if(mTexture->hasGLTexture()) - { - old_mode = mTexture->getAddressMode(); - } gGL.getTexUnit(diffuse_channel)->bind(mTexture); - gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } else { gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); } - - + U32 mask = sRenderMask; U32 start = mMesh->mFaceVertexOffset; @@ -349,12 +342,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) gGL.getTexUnit(diffuse_channel)->setTextureBlendType(LLTexUnit::TB_MULT); } - if (mTexture.notNull() && !is_dummy) - { - gGL.getTexUnit(diffuse_channel)->bind(mTexture); - gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(old_mode); - } - return triangle_count; } @@ -384,7 +371,7 @@ void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 //----------------------------------------------------------------------------- // updateFaceData() //----------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_AVATAR_FACE("Avatar Face"); +static LLTrace::BlockTimerStatHandle FTM_AVATAR_FACE("Avatar Face"); void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update) { @@ -407,7 +394,7 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w } - LLFastTimer t(FTM_AVATAR_FACE); + LL_RECORD_BLOCK_TIME(FTM_AVATAR_FACE); LLStrider verticesp; LLStrider normalsp; diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index aa20990661..1dec470624 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -42,20 +42,21 @@ #include "llfocusmgr.h" #include "rlvhandler.h" +#include #include // ---------------------------------------------------------------------------- // Constants -#define X_I 1 -#define Y_I 2 -#define Z_I 0 -#define RX_I 4 -#define RY_I 5 -#define RZ_I 3 +constexpr auto X_I = 1; +constexpr auto Y_I = 2; +constexpr auto Z_I = 0; +constexpr auto RX_I = 4; +constexpr auto RY_I = 5; +constexpr auto RZ_I = 3; // minimum time after setting away state before coming back -const F32 MIN_AFK_TIME = 2.f; +constexpr F32 MIN_AFK_TIME = 2.f; F32 LLViewerJoystick::sLastDelta[] = {0,0,0,0,0,0,0}; F32 LLViewerJoystick::sDelta[] = {0,0,0,0,0,0,0}; @@ -85,8 +86,7 @@ bool isOUYA(const std::string& desc) { return desc.find("OUYA") != std::string:: bool isXboxLike(const std::string& desc) { - return desc.find("Xbox") != std::string::npos - || isOUYA(desc); + return boost::algorithm::icontains(desc, "xbox") || isOUYA(desc); } bool isDS3Like(const std::string& desc) @@ -111,13 +111,26 @@ enum DS3Keys DS3_LOGO_KEY }; -S32 get_joystick_type() +void set_joystick_type(const S32& type) { - if (sType == SPACE_NAV) return 0; - if (sType == XBOX) return isOUYA(LLViewerJoystick::getInstance()->getDescription()) ? 1 : 2; - if (sType == DS3) return 3; + switch (type) + { + case 0: sType = SPACE_NAV; break; + case 1: case 2: sType = XBOX; break; + case 3: sType = DS3; break; + default: sType = UNKNOWN; break; + } +} - return -1; // sType == NONE || sType == UNKNOWN +S32 get_joystick_type() +{ + switch (sType) + { + case SPACE_NAV: return 0; + case XBOX: return isOUYA(LLViewerJoystick::getInstance()->getDescription()) ? 1 : 2; + case DS3: return 3; + default: return -1; // sType == NONE || sType == UNKNOWN + } } // @@ -126,8 +139,8 @@ S32 get_joystick_type() // should be. It has to be equal to 3000 because the SpaceNavigator on Windows // refuses to respond to the DirectInput SetProperty call; it always returns // values in the [-3000, 3000] range. -#define MAX_SPACENAVIGATOR_INPUT 3000.0f -#define MAX_JOYSTICK_INPUT_VALUE MAX_SPACENAVIGATOR_INPUT +constexpr auto MAX_SPACENAVIGATOR_INPUT = 3000.0f; +constexpr auto MAX_JOYSTICK_INPUT_VALUE = MAX_SPACENAVIGATOR_INPUT; // ----------------------------------------------------------------------------- void LLViewerJoystick::updateEnabled(bool autoenable) @@ -1390,7 +1403,8 @@ void LLViewerJoystick::setSNDefaults(S32 type) const float platformScaleAvXZ = 2.f; const bool is_3d_cursor = true; #endif - + + set_joystick_type(type); // Breaks resetting to default but allows declaring a new identity and button config for the controller //gViewerWindow->alertXml("CacheWillClear"); const bool ouya = type == 1; const bool xbox = ouya || type == 2; diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 89b52d8b55..271d555ba6 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -61,7 +61,7 @@ const S32 NUDGE_FRAMES = 2; const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed struct LLKeyboardActionRegistry -: public LLRegistrySingleton, LLKeyboardActionRegistry> +: public LLRegistrySingleton, LLKeyboardActionRegistry> { }; @@ -87,7 +87,7 @@ void agent_jump( EKeystate s ) gAgent.moveUp(1); } } -// + void agent_toggle_down( EKeystate s ) { if (KEYSTATE_UP == s) return; @@ -101,7 +101,6 @@ void agent_toggle_down( EKeystate s ) } gAgent.moveUp(-1); } -// void agent_push_down( EKeystate s ) { @@ -549,24 +548,29 @@ void start_chat( EKeystate s ) } // start chat - gChatBar->startChat(NULL); + LLChatBar::startChat(NULL); } void start_gesture( EKeystate s ) { + if (LLAppViewer::instance()->quitRequested()) + { + return; // can't talk, gotta go, kthxbye! + } + LLUICtrl* focus_ctrlp = dynamic_cast(gFocusMgr.getKeyboardFocus()); if (KEYSTATE_UP == s && ! (focus_ctrlp && focus_ctrlp->acceptsTextInput())) { - if (gChatBar->getCurrentChat().empty()) + if (gChatBar && gChatBar->getCurrentChat().empty()) { // No existing chat in chat editor, insert '/' - gChatBar->startChat("/"); + LLChatBar::startChat("/"); } else { // Don't overwrite existing text in chat editor - gChatBar->startChat(NULL); + LLChatBar::startChat(NULL); } } } @@ -574,11 +578,11 @@ void start_gesture( EKeystate s ) #define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, ACTION); REGISTER_KEYBOARD_ACTION("jump", agent_jump); REGISTER_KEYBOARD_ACTION("push_down", agent_push_down); +REGISTER_KEYBOARD_ACTION("toggle_down", agent_toggle_down); REGISTER_KEYBOARD_ACTION("push_forward", agent_push_forward); REGISTER_KEYBOARD_ACTION("push_backward", agent_push_backward); REGISTER_KEYBOARD_ACTION("look_up", agent_look_up); REGISTER_KEYBOARD_ACTION("look_down", agent_look_down); -REGISTER_KEYBOARD_ACTION("toggle_down", agent_toggle_down); REGISTER_KEYBOARD_ACTION("toggle_fly", agent_toggle_fly); REGISTER_KEYBOARD_ACTION("turn_left", agent_turn_left); REGISTER_KEYBOARD_ACTION("turn_right", agent_turn_right); @@ -706,13 +710,16 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL return mKeyHandledByUI[translated_key]; } - +BOOL LLViewerKeyboard::handleKeyUp(KEY translated_key, MASK translated_mask) +{ + return gViewerWindow->handleKeyUp(translated_key, translated_mask); +} BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name) { S32 index; - typedef boost::function function_t; - function_t function = NULL; + typedef std::function function_t; + function_t function; std::string name; // Allow remapping of F2-F12 diff --git a/indra/newview/llviewerkeyboard.h b/indra/newview/llviewerkeyboard.h index 29fff6f988..bcc937f498 100644 --- a/indra/newview/llviewerkeyboard.h +++ b/indra/newview/llviewerkeyboard.h @@ -89,6 +89,7 @@ class LLViewerKeyboard LLViewerKeyboard(); BOOL handleKey(KEY key, MASK mask, BOOL repeated); + BOOL handleKeyUp(KEY key, MASK mask); S32 loadBindings(const std::string& filename); // returns number bound, 0 on error S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 1d137f161c..06047dcf69 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -32,9 +32,6 @@ #include "llviewerprecompiledheaders.h" -#include "llviewermedia.h" - - #include "llviewermedia.h" #include "llagent.h" @@ -45,9 +42,10 @@ #include "lldir.h" #include "lldiriterator.h" #include "llevent.h" // LLSimpleListener +#include "aifilepicker.h" +#include "llfloaterdestinations.h" #include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows. #include "llfocusmgr.h" -#include "llhttpclient.h" #include "llkeyboard.h" #include "llmarketplacefunctions.h" #include "llmediaentry.h" @@ -59,7 +57,6 @@ #include "llpanelprofile.h" #include "llparcel.h" #include "llpluginclassmedia.h" -#include "llplugincookiestore.h" #include "llurldispatcher.h" #include "lluuid.h" #include "llvieweraudio.h" @@ -78,13 +75,10 @@ #include "llwebprofile.h" #include "llwindow.h" #include "llvieweraudio.h" +#include "llhttpclient.h" -#include "aifilepicker.h" #include "llstartup.h" -#include // for SkinFolder listener -#include - std::string getProfileURL(const std::string& agent_name); /*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "ParcelMediaAutoPlayEnable"; @@ -176,18 +170,15 @@ LOG_CLASS(LLMimeDiscoveryResponder); : mMediaImpl(media_impl), mInitialized(false) { - if(mMediaImpl->mMimeTypeProbe != NULL) + if(mMediaImpl->mMimeProbe) { LL_ERRS() << "impl already has an outstanding responder" << LL_ENDL; } - mMediaImpl->mMimeTypeProbe = this; + mMediaImpl->mMimeProbe = this; } - ~LLMimeDiscoveryResponder() - { - disconnectOwner(); - } + ~LLMimeDiscoveryResponder() { disconnectOwner(); } private: /* virtual */ void completedHeaders() @@ -266,14 +257,14 @@ LOG_CLASS(LLMimeDiscoveryResponder); { if(mMediaImpl) { - if(mMediaImpl->mMimeTypeProbe != this) + if(mMediaImpl->mMimeProbe != this) { - LL_ERRS() << "internal error: mMediaImpl->mMimeTypeProbe != this" << LL_ENDL; + LL_ERRS() << "internal error: mMediaImpl->mMimeProbe != this" << LL_ENDL; } - mMediaImpl->mMimeTypeProbe = NULL; + mMediaImpl->mMimeProbe = nullptr; } - mMediaImpl = NULL; + mMediaImpl = nullptr; } @@ -342,8 +333,6 @@ LOG_CLASS(LLViewerMediaWebProfileResponder); for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie) { // *TODO: What about bad status codes? Does this destroy previous cookies? - LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie->second, mHost); - if (cookie->second.substr(0, cookie->second.find('=')) == "_my_secondlife_session") { // Set cookie for snapshot publishing. @@ -362,10 +351,9 @@ LOG_CLASS(LLViewerMediaWebProfileResponder); }; -LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL; LLURL LLViewerMedia::sOpenIDURL; std::string LLViewerMedia::sOpenIDCookie; -LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = NULL; +LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = nullptr; static LLViewerMedia::impl_list sViewerMediaImplList; static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap; static LLTimer sMediaCreateTimer; @@ -376,8 +364,6 @@ static LLUUID sOnlyAudibleTextureID = LLUUID::null; static F64 sLowestLoadableImplInterest = 0.0f; static bool sAnyMediaShowing = false; static boost::signals2::connection sTeleportFinishConnection; -static std::string sUpdatedCookies; -static const char *PLUGIN_COOKIE_FILE_NAME = "plugin_cookies.txt"; ////////////////////////////////////////////////////////////////////////////////////////// static void add_media_impl(LLViewerMediaImpl* media) @@ -437,6 +423,7 @@ viewer_media_t LLViewerMedia::newMediaImpl( media_impl->mMediaAutoScale = media_auto_scale; media_impl->mMediaLoop = media_loop; } + media_impl->setPageZoomFactor(media_impl->mZoomFactor); return media_impl; } @@ -798,19 +785,19 @@ static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMedi } } -static LLFastTimer::DeclareTimer FTM_MEDIA_UPDATE("Update Media"); -static LLFastTimer::DeclareTimer FTM_MEDIA_SPARE_IDLE("Spare Idle"); -static LLFastTimer::DeclareTimer FTM_MEDIA_UPDATE_INTEREST("Update/Interest"); -static LLFastTimer::DeclareTimer FTM_MEDIA_SORT("Sort"); -static LLFastTimer::DeclareTimer FTM_MEDIA_SORT2("Sort 2"); -static LLFastTimer::DeclareTimer FTM_MEDIA_MISC("Misc"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_UPDATE("Update Media"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_SPARE_IDLE("Spare Idle"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_UPDATE_INTEREST("Update/Interest"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_SORT("Sort"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_SORT2("Sort 2"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_MISC("Misc"); ////////////////////////////////////////////////////////////////////////////////////////// // static void LLViewerMedia::updateMedia(void *dummy_arg) { - LLFastTimer t1(FTM_MEDIA_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_MEDIA_UPDATE); // Enable/disable the plugin read thread static LLCachedControl pluginUseReadThread(gSavedSettings, "PluginUseReadThread"); @@ -820,18 +807,12 @@ void LLViewerMedia::updateMedia(void *dummy_arg) createSpareBrowserMediaSource(); sAnyMediaShowing = false; - sUpdatedCookies = getCookieStore()->getChangedCookies(); - if(!sUpdatedCookies.empty()) - { - LL_DEBUGS() << "updated cookies will be sent to all loaded plugins: " << LL_ENDL; - LL_DEBUGS() << sUpdatedCookies << LL_ENDL; - } impl_list::iterator iter = sViewerMediaImplList.begin(); impl_list::iterator end = sViewerMediaImplList.end(); { - LLFastTimer t(FTM_MEDIA_UPDATE_INTEREST); + LL_RECORD_BLOCK_TIME(FTM_MEDIA_UPDATE_INTEREST); for(; iter != end;) { LLViewerMediaImpl* pimpl = *iter++; @@ -843,12 +824,12 @@ void LLViewerMedia::updateMedia(void *dummy_arg) // Let the spare media source actually launch if(sSpareBrowserMediaSource) { - LLFastTimer t(FTM_MEDIA_SPARE_IDLE); + LL_RECORD_BLOCK_TIME(FTM_MEDIA_SPARE_IDLE); sSpareBrowserMediaSource->idle(); } { - LLFastTimer t(FTM_MEDIA_SORT); + LL_RECORD_BLOCK_TIME(FTM_MEDIA_SORT); // Sort the static instance list using our interest criteria sViewerMediaImplList.sort(priorityComparitor); } @@ -880,7 +861,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg) // If max_normal + max_low is less than max_instances, things will tend to get unloaded instead of being set to slideshow. { - LLFastTimer t(FTM_MEDIA_MISC); + LL_RECORD_BLOCK_TIME(FTM_MEDIA_MISC); for(; iter != end; iter++) { LLViewerMediaImpl* pimpl = *iter; @@ -1049,7 +1030,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg) } else { - LLFastTimer t(FTM_MEDIA_SORT2); + LL_RECORD_BLOCK_TIME(FTM_MEDIA_SORT2); // Use a distance-based sort for proximity values. std::stable_sort(proximity_order.begin(), proximity_order.end(), proximity_comparitor); } @@ -1176,63 +1157,6 @@ void LLViewerMedia::clearAllCookies() plugin->clear_cookies(); } } - - // Clear all cookies from the cookie store - getCookieStore()->setAllCookies(""); - - // FIXME: this may not be sufficient, since the on-disk cookie file won't get written until some browser instance exits cleanly. - // It also won't clear cookies for other accounts, or for any account if we're not logged in, and won't do anything at all if there are no webkit plugins loaded. - // Until such time as we can centralize cookie storage, the following hack should cover these cases: - - // HACK: Look for cookie files in all possible places and delete them. - // NOTE: this assumes knowledge of what happens inside the webkit plugin (it's what adds 'browser_profile' to the path and names the cookie file) - - // Places that cookie files can be: - // /browser_profile/cookies - // /first_last/browser_profile/cookies (note that there may be any number of these!) - // /first_last/plugin_cookies.txt (note that there may be any number of these!) - - std::string base_dir = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter(); - std::string target; - std::string filename; - - LL_DEBUGS() << "base dir = " << base_dir << LL_ENDL; - - // The non-logged-in version is easy - target = base_dir; - target += "browser_profile"; - target += gDirUtilp->getDirDelimiter(); - target += "cookies"; - LL_DEBUGS() << "target = " << target << LL_ENDL; - if(LLFile::isfile(target)) - { - LLFile::remove(target); - } - - // the hard part: iterate over all user directories and delete the cookie file from each one - LLDirIterator dir_iter(base_dir, "*_*"); - while (dir_iter.next(filename)) - { - target = gDirUtilp->add(base_dir, filename); - gDirUtilp->append(target, "browser_profile"); - gDirUtilp->append(target, "cookies"); - LL_DEBUGS() << "target = " << target << LL_ENDL; - if(LLFile::isfile(target)) - { - LLFile::remove(target); - } - - // Other accounts may have new-style cookie files too -- delete them as well - target = gDirUtilp->add(base_dir, filename); - gDirUtilp->append(target, PLUGIN_COOKIE_FILE_NAME); - LL_DEBUGS() << "target = " << target << LL_ENDL; - if(LLFile::isfile(target)) - { - LLFile::remove(target); - } - } - - // If we have an OpenID cookie, re-add it to the cookie store. setOpenIDCookie(); } @@ -1263,7 +1187,7 @@ void LLViewerMedia::setCookiesEnabled(bool enabled) LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); if(plugin) { - plugin->enable_cookies(enabled); + plugin->cookies_enabled(enabled); } } } @@ -1281,7 +1205,7 @@ void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int por LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); if(plugin) { - plugin->proxy_setup(enable, host, port); + //pimpl->mMediaSource->proxy_setup(enable, host, port); } } } @@ -1289,202 +1213,137 @@ void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int por ///////////////////////////////////////////////////////////////////////////////////////// // static ///////////////////////////////////////////////////////////////////////////////////////// -// static -LLPluginCookieStore *LLViewerMedia::getCookieStore() +//// static + +AIHTTPHeaders LLViewerMedia::getHeaders() { - if(sCookieStore == NULL) - { - sCookieStore = new LLPluginCookieStore; - } - - return sCookieStore; + AIHTTPHeaders headers; + headers.addHeader("Accept", "*/*"); + // *TODO: Should this be 'application/llsd+xml' ? + // *TODO: Should this even be set at all? This header is only not overridden in 'GET' methods. + headers.addHeader("Content-Type", "application/xml"); + headers.addHeader("Cookie", sOpenIDCookie); + headers.addHeader("User-Agent", getCurrentUserAgent()); + + return headers; } ///////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerMedia::loadCookieFile() +bool LLViewerMedia::parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path, bool& httponly, bool& secure) { - // build filename for each user - std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME); - - if (resolved_filename.empty()) - { - LL_INFOS() << "can't get path to plugin cookie file - probably not logged in yet." << LL_ENDL; - return; - } - - // open the file for reading - llifstream file(resolved_filename); - if (!file.is_open()) + std::size_t name_pos = raw_cookie.find_first_of('='); + if (name_pos != std::string::npos) { - LL_WARNS() << "can't load plugin cookies from file \"" << PLUGIN_COOKIE_FILE_NAME << "\"" << LL_ENDL; - return; - } - - getCookieStore()->readAllCookies(file, true); - - file.close(); - - // send the clear_cookies message to all loaded plugins - impl_list::iterator iter = sViewerMediaImplList.begin(); - impl_list::iterator end = sViewerMediaImplList.end(); - for (; iter != end; iter++) - { - LLViewerMediaImpl* pimpl = *iter; - LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); - if(plugin) + name = raw_cookie.substr(0, name_pos); + std::size_t value_pos = raw_cookie.find_first_of(';', name_pos); + if (value_pos != std::string::npos) { - plugin->clear_cookies(); + value = raw_cookie.substr(name_pos + 1, value_pos - name_pos - 1); + path = "/"; // assume root path for now + + httponly = true; // hard coded for now + secure = true; + + return true; } } - - // If we have an OpenID cookie, re-add it to the cookie store. - setOpenIDCookie(); -} + return false; +} -///////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::saveCookieFile() +void LLViewerMedia::setOpenIDCookie() { - // build filename for each user - std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME); - - if (resolved_filename.empty()) + if(!sOpenIDCookie.empty()) { - LL_INFOS() << "can't get path to plugin cookie file - probably not logged in yet." << LL_ENDL; - return; - } + if (gSavedSettings.getString("WebProfileURL").empty()) return; + std::string profileUrl = getProfileURL(""); - // open a file for writing - llofstream file (resolved_filename); - if (!file.is_open()) - { - LL_WARNS() << "can't open plugin cookie file \"" << PLUGIN_COOKIE_FILE_NAME << "\" for writing" << LL_ENDL; - return; + getOpenIDCookieCoro(profileUrl); } - - getCookieStore()->writePersistentCookies(file); - - file.close(); } -///////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path, bool secure) +/*static*/ +void LLViewerMedia::getOpenIDCookieCoro(std::string url) { - std::stringstream cookie; - - cookie << name << "=" << LLPluginCookieStore::quoteString(value); - - if(expires.notNull()) - { - cookie << "; expires=" << expires.asRFC1123(); + // The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port] + // We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that. + // We therefore do it here. + std::string authority = sOpenIDURL.mAuthority; + std::string::size_type hostStart = authority.find('@'); + if(hostStart == std::string::npos) + { // no username/password + hostStart = 0; + } + else + { // Hostname starts after the @. + // (If the hostname part is empty, this may put host_start at the end of the string. In that case, it will end up passing through an empty hostname, which is correct.) + ++hostStart; + } + std::string::size_type hostEnd = authority.rfind(':'); + if((hostEnd == std::string::npos) || (hostEnd < hostStart)) + { // no port + hostEnd = authority.size(); } - - cookie << "; domain=" << domain; - cookie << "; path=" << path; - - if(secure) + if (url.length()) { - cookie << "; secure"; + LLMediaCtrl* media_instance = LLFloaterDestinations::getInstance()->getChild("destination_guide_contents"); + if (media_instance) + { + std::string cookie_host = authority.substr(hostStart, hostEnd - hostStart); + std::string cookie_name = ""; + std::string cookie_value = ""; + std::string cookie_path = ""; + bool httponly = true; + bool secure = true; + if (parseRawCookie(sOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure) && + media_instance->getMediaPlugin()) + { + // MAINT-5711 - inexplicably, the CEF setCookie function will no longer set the cookie if the + // url and domain are not the same. This used to be my.sl.com and id.sl.com respectively and worked. + // For now, we use the URL for the OpenID POST request since it will have the same authority + // as the domain field. + // (Feels like there must be a less dirty way to construct a URL from component LLURL parts) + // MAINT-6392 - Rider: Do not change, however, the original URI requested, since it is used further + // down. + std::string cefUrl(std::string(sOpenIDURL.mURI) + "://" + std::string(sOpenIDURL.mAuthority)); + + media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host, cookie_path, httponly, secure); + } + } } - - getCookieStore()->setCookies(cookie.str()); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path, bool secure) -{ - // A session cookie just has a NULL date. - addCookie(name, value, domain, LLDate(), path, secure); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::removeCookie(const std::string &name, const std::string &domain, const std::string &path ) -{ - // To remove a cookie, add one with the same name, domain, and path that expires in the past. - - addCookie(name, "", domain, LLDate(LLDate::now().secondsSinceEpoch() - 1.0), path); -} - + + // Note: Rider: MAINT-6392 - Some viewer code requires access to the my.sl.com openid cookie for such + // actions as posting snapshots to the feed. This is handled through HTTPCore rather than CEF and so + // we must learn to SHARE the cookies. -AIHTTPHeaders LLViewerMedia::getHeaders() -{ + // Do a web profile get so we can store the cookie AIHTTPHeaders headers; headers.addHeader("Accept", "*/*"); - // *TODO: Should this be 'application/llsd+xml' ? - // *TODO: Should this even be set at all? This header is only not overridden in 'GET' methods. - headers.addHeader("Content-Type", "application/xml"); headers.addHeader("Cookie", sOpenIDCookie); headers.addHeader("User-Agent", getCurrentUserAgent()); - return headers; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::setOpenIDCookie() -{ - if(!sOpenIDCookie.empty()) - { - // The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port] - // We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that. - // We therefore do it here. - std::string authority = sOpenIDURL.mAuthority; - std::string::size_type host_start = authority.find('@'); - if(host_start == std::string::npos) - { - // no username/password - host_start = 0; - } - else - { - // Hostname starts after the @. - // (If the hostname part is empty, this may put host_start at the end of the string. In that case, it will end up passing through an empty hostname, which is correct.) - ++host_start; - } - std::string::size_type host_end = authority.rfind(':'); - if((host_end == std::string::npos) || (host_end < host_start)) - { - // no port - host_end = authority.size(); - } - - getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start)); + LLURL raw_profile_url(url.data()); - if (gSavedSettings.getString("WebProfileURL").empty()) return; - // Do a web profile get so we can store the cookie - AIHTTPHeaders headers; - headers.addHeader("Accept", "*/*"); - headers.addHeader("Cookie", sOpenIDCookie); - headers.addHeader("User-Agent", getCurrentUserAgent()); - - std::string profile_url = getProfileURL(""); - LLURL raw_profile_url( profile_url.c_str() ); - - LL_DEBUGS("MediaAuth") << "Requesting " << profile_url << LL_ENDL; - LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL; - LLHTTPClient::get(profile_url, - new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), - headers); - } + LL_DEBUGS("MediaAuth") << "Requesting " << url << LL_ENDL; + LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL; + LLHTTPClient::get(url, + new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), + headers); } ///////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token) +void LLViewerMedia::openIDSetup(const std::string &openidUrl, const std::string &openidToken) { - LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL; + LL_DEBUGS("MediaAuth") << "url = \"" << openidUrl << "\", token = \"" << openidToken << "\"" << LL_ENDL; // post the token to the url // the responder will need to extract the cookie(s). // Save the OpenID URL for later -- we may need the host when adding the cookie. - sOpenIDURL.init(openid_url.c_str()); + sOpenIDURL.init(openidUrl.c_str()); // We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies. sOpenIDCookie.clear(); @@ -1496,13 +1355,13 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string headers.addHeader("Content-Type", "application/x-www-form-urlencoded"); // postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here. - size_t size = openid_token.size(); + size_t size = openidToken.size(); U8* data = new U8[size]; - memcpy(data, openid_token.data(), size); + memcpy(data, openidToken.data(), size); LLHTTPClient::postRaw( - openid_url, - data, + openidUrl, + data, size, new LLViewerMediaOpenIDResponder(), headers); @@ -1570,7 +1429,7 @@ void LLViewerMedia::createSpareBrowserMediaSource() // The null owner will keep the browser plugin from fully initializing // (specifically, it keeps LLPluginClassMedia from negotiating a size change, // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color) - sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0); + sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", nullptr, 0, 0, 1.0); if (!sSpareBrowserMediaSource) failedLoading = true; } } @@ -1580,7 +1439,7 @@ void LLViewerMedia::createSpareBrowserMediaSource() LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource() { LLPluginClassMedia* result = sSpareBrowserMediaSource; - sSpareBrowserMediaSource = NULL; + sSpareBrowserMediaSource = nullptr; return result; }; @@ -1626,7 +1485,7 @@ std::string LLViewerMedia::getParcelAudioURL() // static void LLViewerMedia::initClass() { - gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL); + gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, nullptr); sTeleportFinishConnection = LLViewerParcelMgr::getInstance()-> setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished)); } @@ -1635,8 +1494,13 @@ void LLViewerMedia::initClass() // static void LLViewerMedia::cleanupClass() { - gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL); + gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, nullptr); sTeleportFinishConnection.disconnect(); + if (sSpareBrowserMediaSource != nullptr) + { + delete sSpareBrowserMediaSource; + sSpareBrowserMediaSource = nullptr; + } } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1645,6 +1509,8 @@ void LLViewerMedia::onTeleportFinished() { // On teleport, clear this setting (i.e. set it to true) gSavedSettings.setBOOL("MediaTentativeAutoPlay", true); + + LLViewerMediaImpl::sMimeTypesFailed.clear(); } @@ -1656,6 +1522,7 @@ void LLViewerMedia::setOnlyAudibleMediaTextureID(const LLUUID& texture_id) sForceUpdate = true; } +std::vector LLViewerMediaImpl::sMimeTypesFailed; ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMediaImpl ////////////////////////////////////////////////////////////////////////////////////////// @@ -1665,6 +1532,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, U8 media_auto_scale, U8 media_loop) : + mZoomFactor(1.0), mMovieImageHasMips(false), mMediaWidth(media_width), mMediaHeight(media_height), @@ -1685,6 +1553,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mNavigateServerRequest(false), mMediaSourceFailed(false), mRequestedVolume(1.0f), + mPreviousVolume(1.0f), mIsMuted(false), mNeedsMuteCheck(false), mPreviousMediaState(MEDIA_NONE), @@ -1693,16 +1562,16 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mIsParcelMedia(false), mProximity(-1), mProximityDistance(0.0f), - mMimeTypeProbe(NULL), mMediaAutoPlay(false), mInNearbyMediaList(false), mClearCache(false), mBackgroundColor(LLColor4::white), mNavigateSuspended(false), mNavigateSuspendedDeferred(false), - mIsUpdated(false), mTrustedBrowser(false), - mZoomFactor(1.0) + mCleanBrowser(false), + mIsUpdated(false), + mMimeProbe(nullptr) { // Set up the mute list observer if it hasn't been set up already. @@ -1770,7 +1639,7 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) mMimeType = mime_type; } - return (mPluginBase != NULL); + return (mPluginBase != nullptr); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1825,15 +1694,16 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) ////////////////////////////////////////////////////////////////////////////////////////// /*static*/ -LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target) +LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target, bool clean_browser) { std::string plugin_basename = LLMIMETypes::implType(media_type); - LLPluginClassMedia* media_source = NULL; + LLPluginClassMedia* media_source = nullptr; // HACK: we always try to keep a spare running webkit plugin around to improve launch times. // If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it. - if((plugin_basename == "media_plugin_webkit") && - !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")) + // Do not use a spare if launching with full viewer control (e.g. Facebook, Twitter and few others) + if ((plugin_basename == "media_plugin_cef") && + !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins") && !clean_browser) { media_source = LLViewerMedia::getSpareBrowserMediaSource(); if(media_source) @@ -1841,6 +1711,8 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ media_source->setOwner(owner); media_source->setTarget(target); media_source->setSize(default_width, default_height); + media_source->setZoomFactor(zoom_factor); + media_source->set_page_zoom_factor(zoom_factor); return media_source; } @@ -1853,20 +1725,25 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ { std::string launcher_name = gDirUtilp->getLLPluginLauncher(); std::string plugin_name = gDirUtilp->getLLPluginFilename(plugin_basename); - std::string user_data_path = gDirUtilp->getOSUserAppDir(); - user_data_path += gDirUtilp->getDirDelimiter(); + + std::string user_data_path_cache = gDirUtilp->getCacheDir(false); + user_data_path_cache += gDirUtilp->getDirDelimiter(); + + std::string user_data_path_cookies = gDirUtilp->getOSUserAppDir(); + user_data_path_cookies += gDirUtilp->getDirDelimiter(); + + std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef_log.txt"); // Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.) // If the linden username returned is blank, that can only mean we are // at the login page displaying login Web page or Web browser test via Develop menu. // In this case we just use whatever gDirUtilp->getOSUserAppDir() gives us (this // is what we always used before this change) - std::string linden_user_dir = gDirUtilp->getLindenUserDir(true); + std::string linden_user_dir = gDirUtilp->getLindenUserDir(); if ( ! linden_user_dir.empty() ) { - // gDirUtilp->getLindenUserDir() is whole path, not just Linden name - user_data_path = linden_user_dir; - user_data_path += gDirUtilp->getDirDelimiter(); + user_data_path_cookies = linden_user_dir; + user_data_path_cookies += gDirUtilp->getDirDelimiter(); }; // See if the plugin executable exists @@ -1882,24 +1759,31 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ else { media_source = new LLPluginClassMedia(owner); + media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getS32("BrowserProxyType"), + gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"), + gSavedSettings.getString("BrowserProxyUsername"), gSavedSettings.getString("BrowserProxyPassword")); media_source->setSize(default_width, default_height); - media_source->setUserDataPath(user_data_path); + media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies, user_data_path_cef_log); media_source->setLanguageCode(LLUI::getLanguage()); + media_source->setZoomFactor(zoom_factor); // collect 'cookies enabled' setting from prefs and send to embedded browser bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" ); - media_source->enable_cookies( cookies_enabled ); + media_source->cookies_enabled( cookies_enabled || clean_browser); // collect 'plugins enabled' setting from prefs and send to embedded browser bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" ); - media_source->setPluginsEnabled( plugins_enabled ); + media_source->setPluginsEnabled( plugins_enabled || clean_browser); // collect 'javascript enabled' setting from prefs and send to embedded browser bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" ); - media_source->setJavascriptEnabled( javascript_enabled ); + media_source->setJavascriptEnabled( javascript_enabled || clean_browser); bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); - media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled ); + media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled || clean_browser); + + // need to set agent string here before instance created + media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent()); media_source->setTarget(target); @@ -1917,12 +1801,18 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } LL_WARNS_ONCE("Plugin") << "plugin initialization failed for mime type: " << media_type << LL_ENDL; - /* There is a reason why ^^ is ONCE - LLSD args; - args["MIME_TYPE"] = media_type; - LLNotificationsUtil::add("NoPlugin", args); - */ - return NULL; + + if(gAgent.isInitialized()) + { + if (std::find(sMimeTypesFailed.begin(), sMimeTypesFailed.end(), media_type) == sMimeTypesFailed.end()) + { + LLSD args; + args["MIME_TYPE"] = media_type; + LLNotificationsUtil::add("NoPlugin", args); + sMimeTypesFailed.push_back(media_type); + } + } + return nullptr; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1934,6 +1824,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // Save the previous media source's last set size before destroying it. mMediaWidth = mMediaSource->getSetWidth(); mMediaHeight = mMediaSource->getSetHeight(); + mZoomFactor = mMediaSource->getZoomFactor(); } // Always delete the old media impl first. @@ -1956,7 +1847,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // Save the MIME type that really caused the plugin to load mCurrentMimeType = mMimeType; - LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget); + LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mZoomFactor, mTarget, mCleanBrowser); if (media_source) { @@ -1976,27 +1867,17 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // Qt/WebKit loads from your system location. // Note: This needs the new CA.pem file with the Equifax Secure Certificate Authority // cert at the bottom: (MIIDIDCCAomgAwIBAgIENd70zzANBg) - std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "CA.pem" ); + std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "ca-bundle.crt" ); media_source->addCertificateFilePath( ca_path ); - media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort")); + media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getS32("BrowserProxyType"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"), + gSavedSettings.getString("BrowserProxyUsername"), gSavedSettings.getString("BrowserProxyPassword")); if(mClearCache) { mClearCache = false; media_source->clear_cache(); } - - // TODO: Only send cookies to plugins that need them - // Ideally, the plugin should tell us whether it handles cookies or not -- either via the init response or through a separate message. - // Due to the ordering of messages, it's possible we wouldn't get that information back in time to send cookies before sending a navigate message, - // which could cause odd race conditions. - std::string all_cookies = LLViewerMedia::getCookieStore()->getAllCookies(); - LL_DEBUGS() << "setting cookies: " << all_cookies << LL_ENDL; - if(!all_cookies.empty()) - { - media_source->set_cookies(all_cookies); - } mPluginBase = media_source; mPluginBase->setDeleteOK(false) ; @@ -2099,7 +1980,7 @@ void LLViewerMediaImpl::play() LLPluginClassMedia* mMediaSource = getMediaPlugin(); // If the media source isn't there, try to initialize it and load an URL. - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { if(!initializeMedia(mMimeType)) { @@ -2212,6 +2093,20 @@ void LLViewerMediaImpl::setVolume(F32 volume) updateVolume(); } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::setMute(bool mute) +{ + if (mute) + { + mPreviousVolume = mRequestedVolume; + setVolume(0.0); + } + else + { + setVolume(mPreviousVolume); + } +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateVolume() { @@ -2426,6 +2321,18 @@ void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords, MASK mask) } } +void LLViewerMediaImpl::mouseDoubleClick(const LLVector2& texture_coords, MASK mask) +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + { + S32 x, y; + scaleTextureCoords(texture_coords, &x, &y); + + mouseDoubleClick(x, y, mask); + } +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button) { @@ -2440,7 +2347,7 @@ void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button) } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, MASK mask) +void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, S32 scroll_x, S32 scroll_y, MASK mask) { LLPluginClassMedia* mMediaSource = getMediaPlugin(); scaleMouse(&x, &y); @@ -2448,7 +2355,7 @@ void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, MASK mask) mLastMouseY = y; if (mMediaSource) { - mMediaSource->scrollEvent(x, y, mask); + mMediaSource->scrollEvent(x, y, scroll_x, scroll_y, mask); } } @@ -2609,7 +2516,7 @@ void LLViewerMediaImpl::unload() } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request) +void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request, bool clean_browser) { if (url.empty()) { @@ -2628,6 +2535,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi // Always set the current URL and MIME type. mMediaURL = url; mMimeType = mime_type; + mCleanBrowser = clean_browser; // Clear the current media URL, since it will no longer be correct. mCurrentMediaURL.clear(); @@ -2684,7 +2592,7 @@ void LLViewerMediaImpl::navigateInternal() return; } - if(mMimeTypeProbe != NULL) + if(mMimeProbe != nullptr) { LL_WARNS() << "MIME type probe already in progress -- bailing out." << LL_ENDL; return; @@ -2733,11 +2641,14 @@ void LLViewerMediaImpl::navigateInternal() } else if("data" == scheme || "file" == scheme || "about" == scheme) { - // FIXME: figure out how to really discover the type for these schemes - // We use "data" internally for a text/html url for loading the login screen - if(initializeMedia("text/html")) + if ("blank" != uri.hostName()) { - loadURI(); + // FIXME: figure out how to really discover the type for these schemes + // We use "data" internally for a text/html url for loading the login screen + if(initializeMedia("text/html")) + { + loadURI(); + } } } else @@ -2777,51 +2688,75 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) if (mMediaSource) { - // FIXME: THIS IS SO WRONG. - // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... - if( MASK_CONTROL & mask && key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END) + switch (mask) { - result = true; - } - - if( MASK_CONTROL & mask ) + case MASK_CONTROL: { - if('C' == key) - { - mMediaSource->copy(); - result = true; - } - else if('V' == key) + result = true; // Avoid redundant code, set false for default. + switch(key) { - mMediaSource->paste(); - result = true; + // FIXME: THIS IS SO WRONG. + // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... + case KEY_LEFT: case KEY_RIGHT: case KEY_HOME: case KEY_END: break; + + case 'C': mMediaSource->copy(); break; + case 'V': mMediaSource->paste(); break; + case 'X': mMediaSource->cut(); break; + case '=': setPageZoomFactor(mZoomFactor + .1); break; + case '-': setPageZoomFactor(mZoomFactor - .1); break; + case '0': setPageZoomFactor(1.0); break; + + default: result = false; break; } - else if('X' == key) + break; + } + case MASK_SHIFT|MASK_CONTROL: + if (key == 'I') { - mMediaSource->cut(); + mMediaSource->showWebInspector(true); result = true; } + break; } // Singu Note: At the very least, let's allow the login menu to function extern LLMenuBarGL* gLoginMenuBarView; - if (gLoginMenuBarView && gLoginMenuBarView->getVisible() && gLoginMenuBarView->handleAcceleratorKey(key, mask)) - return true; + result = result || (gLoginMenuBarView && gLoginMenuBarView->getVisible() && gLoginMenuBarView->handleAcceleratorKey(key, mask)); if(!result) { - LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); - - result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data); - // Since the viewer internal event dispatching doesn't give us key-up events, simulate one here. - (void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask, native_key_data); + result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN, key, mask, native_key_data); } } - + return result; } +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::handleKeyUpHere(KEY key, MASK mask) +{ + bool result = false; + + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + { + // FIXME: THIS IS SO WRONG. + // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... + if (MASK_CONTROL & mask && key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END) + { + result = true; + } + + if (!result) + { + LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); + result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP, key, mask, native_key_data); + } + } + + return result; +} ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) { @@ -2868,16 +2803,16 @@ bool LLViewerMediaImpl::canNavigateBack() } ////////////////////////////////////////////////////////////////////////////////////////// -static LLFastTimer::DeclareTimer FTM_MEDIA_DO_UPDATE("Do Update"); -static LLFastTimer::DeclareTimer FTM_MEDIA_GET_DATA("Get Data"); -static LLFastTimer::DeclareTimer FTM_MEDIA_SET_SUBIMAGE("Set Subimage"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_DO_UPDATE("Do Update"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_GET_DATA("Get Data"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_SET_SUBIMAGE("Set Subimage"); void LLViewerMediaImpl::update() { - LLFastTimer t(FTM_MEDIA_DO_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_MEDIA_DO_UPDATE); LLPluginClassMedia* mMediaSource = getMediaPlugin(); - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { if(mPriority == PRIORITY_UNLOADED) { @@ -2887,7 +2822,7 @@ void LLViewerMediaImpl::update() { // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state. } - else if(mMimeTypeProbe != NULL) + else if(mMimeProbe != nullptr) { // this media source is doing a MIME type probe -- don't try loading it again. } @@ -2912,17 +2847,10 @@ void LLViewerMediaImpl::update() // TODO: this is updated every frame - is this bad? updateJavascriptObject(); - - // If we didn't just create the impl, it may need to get cookie updates. - if(!sUpdatedCookies.empty()) - { - // TODO: Only send cookies to plugins that need them - mMediaSource->set_cookies(sUpdatedCookies); - } } - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { return; } @@ -2935,7 +2863,7 @@ void LLViewerMediaImpl::update() setNavigateSuspended(false); mMediaSource = getMediaPlugin(); - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { return; } @@ -2977,18 +2905,20 @@ void LLViewerMediaImpl::update() if(width > 0 && height > 0) { - U8* data = NULL; + U8* data = nullptr; { - LLFastTimer t(FTM_MEDIA_GET_DATA); + LL_RECORD_BLOCK_TIME(FTM_MEDIA_GET_DATA); data = mMediaSource->getBitsData(); } + if(data != NULL) + { // Offset the pixels pointer to match x_pos and y_pos data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() ); data += ( y_pos * mMediaSource->getTextureDepth() ); { - LLFastTimer t(FTM_MEDIA_SET_SUBIMAGE); + LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE); placeholder_image->setSubImage( data, mMediaSource->getBitsWidth(), @@ -2998,6 +2928,7 @@ void LLViewerMediaImpl::update() width, height, TRUE); // + } } } @@ -3020,7 +2951,7 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() if(mTextureId.isNull()) { // The code that created this instance will read from the plugin's bits. - return NULL; + return nullptr; } LLViewerMediaTexture* placeholder_image = LLViewerTextureManager::getMediaTexture( mTextureId ); @@ -3221,13 +3152,13 @@ bool LLViewerMediaImpl::isForcedUnloaded() const { return true; } - + // If this media's class is not supposed to be shown, unload if (!shouldShowBasedOnClass()) { return true; } - + return false; } @@ -3240,25 +3171,25 @@ bool LLViewerMediaImpl::isPlayable() const // All of the forced-unloaded criteria also imply not playable. return false; } - + if(hasMedia()) { // Anything that's already playing is, by definition, playable. return true; } - + if(!mMediaURL.empty()) { // If something has navigated the instance, it's ready to be played. return true; } - + return false; } static void handle_pick_file_request_continued(LLPluginClassMedia* plugin, AIFilePicker* filepicker) { - plugin->sendPickFileResponse(filepicker->hasFilename() ? filepicker->getFilename() : LLStringUtil::null); + plugin->sendPickFileResponse(filepicker->hasFilename() ? filepicker->getFilenames() : std::vector()); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -3272,7 +3203,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL; std::string url = plugin->getClickURL(); std::string nav_type = plugin->getClickNavType(); - LLURLDispatcher::dispatch(url, nav_type, NULL, mTrustedBrowser); + LLURLDispatcher::dispatch(url, nav_type, nullptr, mTrustedBrowser); } break; case MEDIA_EVENT_CLICK_LINK_HREF: @@ -3332,6 +3263,13 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla } break; + case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD: + { + //llinfos << "Media event - file download requested - filename is " << self->getFileDownloadFilename() << llendl; + LLNotificationsUtil::add("MediaFileDownloadUnsupported"); + } + break; + case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN: { LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL; @@ -3430,7 +3368,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla } break; - case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST: { LLNotification::Params auth_request_params("AuthRequest"); @@ -3486,6 +3423,32 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla } break; + case MEDIA_EVENT_DEBUG_MESSAGE: + { + std::string level = plugin->getDebugMessageLevel(); + if (level == "debug") + { + LL_DEBUGS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else if (level == "info") + { + LL_INFOS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else if (level == "warn") + { + LL_WARNS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else if (level == "error") + { + LL_ERRS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else + { + LL_INFOS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + }; + break; + default: break; } @@ -3499,9 +3462,46 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla //////////////////////////////////////////////////////////////////////////////// // virtual -void LLViewerMediaImpl::handleCookieSet(LLPluginClassMedia* self, const std::string &cookie) +void +LLViewerMediaImpl::undo() +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->undo(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canUndo() const { - LLViewerMedia::getCookieStore()->setCookies(cookie); + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canUndo(); + else + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::redo() +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->redo(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canRedo() const +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canRedo(); + else + return FALSE; } //////////////////////////////////////////////////////////////////////////////// @@ -3529,7 +3529,7 @@ LLViewerMediaImpl::canCut() const //////////////////////////////////////////////////////////////////////////////// // virtual void -LLViewerMediaImpl::copy() +LLViewerMediaImpl::copy() const { LLPluginClassMedia* mMediaSource = getMediaPlugin(); if (mMediaSource) @@ -3570,6 +3570,50 @@ LLViewerMediaImpl::canPaste() const return FALSE; } +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::doDelete() +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->doDelete(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canDoDelete() const +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canDoDelete(); + else + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::selectAll() +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->selectAll(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canSelectAll() const +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canSelectAll(); + else + return FALSE; +} + void LLViewerMediaImpl::setUpdated(BOOL updated) { mIsUpdated = updated ; @@ -3580,14 +3624,14 @@ BOOL LLViewerMediaImpl::isUpdated() return mIsUpdated ; } -static LLFastTimer::DeclareTimer FTM_MEDIA_CALCULATE_INTEREST("Calculate Interest"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_CALCULATE_INTEREST("Calculate Interest"); void LLViewerMediaImpl::calculateInterest() { - LLFastTimer t(FTM_MEDIA_CALCULATE_INTEREST); + LL_RECORD_BLOCK_TIME(FTM_MEDIA_CALCULATE_INTEREST); LLViewerMediaTexture* texture = LLViewerTextureManager::findMediaTexture( mTextureId ); - if(texture != NULL) + if(texture != nullptr) { mInterest = texture->getMaxVirtualSize(); } @@ -3822,16 +3866,16 @@ void LLViewerMediaImpl::setNavigateSuspended(bool suspend) void LLViewerMediaImpl::cancelMimeTypeProbe() { - if(mMimeTypeProbe != NULL) + if(mMimeProbe) { // There doesn't seem to be a way to actually cancel an outstanding request. // Simulate it by telling the LLMimeDiscoveryResponder not to write back any results. - mMimeTypeProbe->cancelRequest(); + mMimeProbe->cancelRequest(); - // The above should already have set mMimeTypeProbe to NULL. - if(mMimeTypeProbe != NULL) + // The above should already have set mMimeProbe to nullptr. + if (mMimeProbe) { - LL_ERRS() << "internal error: mMimeTypeProbe is not NULL after cancelling request." << LL_ENDL; + LL_ERRS() << "internal error: mMimeProbe is not nullptr after cancelling request." << LL_ENDL; } } } @@ -3864,7 +3908,7 @@ const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const LLVOVolume *LLViewerMediaImpl::getSomeObject() { - LLVOVolume *result = NULL; + LLVOVolume *result = nullptr; std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ; if(iter != mObjectList.end()) @@ -3974,13 +4018,13 @@ bool LLViewerMediaImpl::isObjectAttachedToAnotherAvatar(LLVOVolume *obj) bool result = false; LLXform *xform = obj; // Walk up parent chain - while (NULL != xform) + while (nullptr != xform) { LLViewerObject *object = dynamic_cast (xform); - if (NULL != object) + if (nullptr != object) { LLVOAvatar *avatar = object->asAvatar(); - if ((NULL != avatar) && (avatar != gAgentAvatarp)) + if ((nullptr != avatar) && (avatar != gAgentAvatarp)) { result = true; break; diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 4dff5cde55..224225498d 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -2,31 +2,25 @@ * @file llviewermedia.h * @brief Client interface to the media engine * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -46,7 +40,6 @@ #include "llnotificationptr.h" #include "llurl.h" - #include "llviewerpluginmanager.h" class LLViewerMediaImpl; @@ -55,7 +48,6 @@ class LLViewerMediaTexture; class LLMediaEntry; class LLVOVolume; class LLMimeDiscoveryResponder; -class LLPluginCookieStore; typedef LLPointer viewer_media_t; /////////////////////////////////////////////////////////////////////////////// @@ -111,10 +103,14 @@ class LLViewerMedia // Is any media currently "showing"? Includes Parcel Media. Does not include media in the UI. static bool isAnyMediaShowing(); + // Shows if any media is playing, counts visible non time based media as playing. Does not include media in the UI. + static bool isAnyMediaPlaying(); // Set all media enabled or disabled, depending on val. Does not include media in the UI. static void setAllMediaEnabled(bool val); + // Set all media paused(stopped for non time based) or playing, depending on val. Does not include media in the UI. + static void setAllMediaPaused(bool val); - static void updateMedia(void* dummy_arg = NULL); + static void updateMedia(void* dummy_arg = nullptr); static void initClass(); static void cleanupClass(); @@ -151,13 +147,6 @@ class LLViewerMedia // Set the proxy config for all loaded plugins static void setProxyConfig(bool enable, const std::string &host, int port); - static LLPluginCookieStore *getCookieStore(); - static void loadCookieFile(); - static void saveCookieFile(); - static void addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path = std::string("/"), bool secure = false ); - static void addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path = std::string("/"), bool secure = false ); - static void removeCookie(const std::string &name, const std::string &domain, const std::string &path = std::string("/") ); - static void openIDSetup(const std::string &openid_url, const std::string &openid_token); static void openIDCookieResponse(const std::string &cookie); @@ -172,10 +161,12 @@ class LLViewerMedia static class AIHTTPHeaders getHeaders(); private: + static bool parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path, bool& httponly, bool& secure); static void setOpenIDCookie(); static void onTeleportFinished(); - - static LLPluginCookieStore *sCookieStore; + + static void getOpenIDCookieCoro(std::string url); + static LLURL sOpenIDURL; static std::string sOpenIDCookie; static LLPluginClassMedia* sSpareBrowserMediaSource; @@ -201,7 +192,7 @@ class LLViewerMediaImpl ~LLViewerMediaImpl(); // Override inherited version from LLViewerMediaEventEmitter - virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event); + void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event) override; void createMediaSource(); void destroyMediaSource(); @@ -223,6 +214,7 @@ class LLViewerMediaImpl void skipBack(F32 step_scale); void skipForward(F32 step_scale); void setVolume(F32 volume); + void setMute(bool mute); void updateVolume(); F32 getVolume(); void focus(bool focus); @@ -234,8 +226,9 @@ class LLViewerMediaImpl void mouseDown(const LLVector2& texture_coords, MASK mask, S32 button = 0); void mouseUp(const LLVector2& texture_coords, MASK mask, S32 button = 0); void mouseMove(const LLVector2& texture_coords, MASK mask); - void mouseDoubleClick(S32 x,S32 y, MASK mask, S32 button = 0); - void scrollWheel(S32 x, S32 y, MASK mask); + void mouseDoubleClick(const LLVector2& texture_coords, MASK mask); + void mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button = 0); + void scrollWheel(S32 x, S32 y, S32 scroll_x, S32 scroll_y, MASK mask); void mouseCapture(); void navigateBack(); @@ -243,10 +236,11 @@ class LLViewerMediaImpl void navigateReload(); void navigateHome(); void unload(); - void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false); + void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false, bool clean_browser = false); void navigateInternal(); void navigateStop(); bool handleKeyHere(KEY key, MASK mask); + bool handleKeyUpHere(KEY key, MASK mask); bool handleUnicodeCharHere(llwchar uni_char); bool canNavigateForward(); bool canNavigateBack(); @@ -257,6 +251,7 @@ class LLViewerMediaImpl void setHomeURL(const std::string& home_url, const std::string& mime_type = LLStringUtil::null) { mHomeURL = home_url; mHomeMimeType = mime_type;}; void clearCache(); void setPageZoomFactor( double factor ); + double getPageZoomFactor() {return mZoomFactor;} std::string getMimeType() { return mMimeType; } void scaleMouse(S32 *mouse_x, S32 *mouse_y); void scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y); @@ -298,7 +293,7 @@ class LLViewerMediaImpl void setTarget(const std::string& target) { mTarget = target; } // utility function to create a ready-to-use media instance from a desired media type. - static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null); + static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target = LLStringUtil::null, bool clean_browser = false); // Internally set our desired browser user agent string, including // the Second Life version and skin name. Used because we can @@ -310,40 +305,51 @@ class LLViewerMediaImpl static bool handleSkinCurrentChanged(const LLSD& newvalue); // need these to handle mouseup... - /*virtual*/ void onMouseCaptureLost(); - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ void onMouseCaptureLost() override; + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; // Grr... the only thing I want as an LLMouseHandler are the onMouseCaptureLost and handleMouseUp calls. // Sadly, these are all pure virtual, so I have to supply implementations here: - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; }; - /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) { return FALSE; }; - /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) {return FALSE; }; - /*virtual*/ const std::string& getName() const; - /*virtual*/ BOOL isView() const { return FALSE; }; - - /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {}; - /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {}; - /*virtual*/ BOOL hasMouseCapture() { return gFocusMgr.getMouseCapture() == this; }; + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override { return FALSE; }; + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) override { return FALSE; }; + /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) override {return FALSE; }; + /*virtual*/ const std::string& getName() const override; + /*virtual*/ BOOL isView() const override { return FALSE; }; + + /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const override {}; + /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const override {}; + /*virtual*/ BOOL hasMouseCapture() override { return gFocusMgr.getMouseCapture() == this; }; // Inherited from LLPluginClassMediaOwner - /*virtual*/ void handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent); - /*virtual*/ void handleCookieSet(LLPluginClassMedia* self, const std::string &cookie); + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent) override; // LLEditMenuHandler overrides - /*virtual*/ void cut(); - /*virtual*/ BOOL canCut() const; + /*virtual*/ void undo() override; + /*virtual*/ BOOL canUndo() const override; + + /*virtual*/ void redo() override; + /*virtual*/ BOOL canRedo() const override; + + /*virtual*/ void cut() override; + /*virtual*/ BOOL canCut() const override; - /*virtual*/ void copy(); - /*virtual*/ BOOL canCopy() const; + /*virtual*/ void copy() const override final; + /*virtual*/ BOOL canCopy() const override; - /*virtual*/ void paste(); - /*virtual*/ BOOL canPaste() const; + /*virtual*/ void paste() override; + /*virtual*/ BOOL canPaste() const override; + + /*virtual*/ void doDelete() override; + /*virtual*/ BOOL canDoDelete() const override; + + /*virtual*/ void selectAll() override; + /*virtual*/ BOOL canSelectAll() const override; void addObject(LLVOVolume* obj) ; void removeObject(LLVOVolume* obj) ; @@ -463,6 +469,7 @@ class LLViewerMediaImpl bool mNavigateServerRequest; bool mMediaSourceFailed; F32 mRequestedVolume; + F32 mPreviousVolume; bool mIsMuted; bool mNeedsMuteCheck; int mPreviousMediaState; @@ -472,7 +479,6 @@ class LLViewerMediaImpl S32 mProximity; F64 mProximityDistance; F64 mProximityCamera; - LLMimeDiscoveryResponder *mMimeTypeProbe; bool mMediaAutoPlay; std::string mMediaEntryURL; bool mInNearbyMediaList; // used by LLPanelNearbyMedia::refreshList() for performance reasons @@ -483,11 +489,15 @@ class LLViewerMediaImpl bool mTrustedBrowser; std::string mTarget; LLNotificationPtr mNotification; + bool mCleanBrowser; // force the creation of a clean browsing target with full options enabled + static std::vector sMimeTypesFailed; private: BOOL mIsUpdated ; std::list< LLVOVolume* > mObjectList ; + LLMimeDiscoveryResponder* mMimeProbe; + private: LLViewerMediaTexture *updatePlaceholderImage(); }; diff --git a/indra/newview/llviewermedia_streamingaudio.cpp b/indra/newview/llviewermedia_streamingaudio.cpp index de90c85717..5e72ab3480 100644 --- a/indra/newview/llviewermedia_streamingaudio.cpp +++ b/indra/newview/llviewermedia_streamingaudio.cpp @@ -162,7 +162,7 @@ LLPluginClassMedia* LLStreamingAudio_MediaPlugins::initializeMedia(const std::st { LLPluginClassMediaOwner* owner = NULL; S32 default_size = 1; // audio-only - be minimal, doesn't matter - LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size); + LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size, 1.0); if (media_source) { diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index d99a57cd8c..e3b02acd4e 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -351,6 +351,18 @@ BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent) return true; } +BOOL LLViewerMediaFocus::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent) +{ + LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); + if (media_impl) + { + media_impl->handleKeyUpHere(key, mask); + } + return true; +} + + + BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) { LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); @@ -364,12 +376,7 @@ BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks) LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); if(media_impl && media_impl->hasMedia()) { - // the scrollEvent() API's x and y are not the same as handleScrollWheel's x and y. - // The latter is the position of the mouse at the time of the event - // The former is the 'scroll amount' in x and y, respectively. - // All we have for 'scroll amount' here is 'clicks'. - // We're also not passed the keyboard modifier mask, but we can get that from gKeyboard. - media_impl->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE)); + media_impl->scrollWheel(x, y, 0, clicks, gKeyboard->currentMask(TRUE)); retval = TRUE; } return retval; @@ -434,7 +441,6 @@ void LLViewerMediaFocus::update() { mMediaControls.get()->setMediaFace(NULL, 0, NULL); } - } } @@ -603,3 +609,13 @@ LLUUID LLViewerMediaFocus::getControlsMediaID() return LLUUID::null; } + +bool LLViewerMediaFocus::wantsKeyUpKeyDown() const +{ + return true; +} + +bool LLViewerMediaFocus::wantsReturnKey() const +{ + return true; +} diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h index f03dd8751e..0b2a64868e 100644 --- a/indra/newview/llviewermediafocus.h +++ b/indra/newview/llviewermediafocus.h @@ -56,6 +56,7 @@ class LLViewerMediaFocus : /*virtual*/ bool getFocus(); /*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + /*virtual*/ BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent); /*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); @@ -87,6 +88,10 @@ class LLViewerMediaFocus : // Return the ID of the media instance the controls are currently attached to (either focus or hover). LLUUID getControlsMediaID(); + // The MoaP object wants keyup and keydown events. Overridden to return true. + virtual bool wantsKeyUpKeyDown() const; + virtual bool wantsReturnKey() const; + protected: /*virtual*/ void onFocusReceived(); /*virtual*/ void onFocusLost(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c9c223ad17..c28ef2fcc1 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -34,25 +34,29 @@ #include "llviewermenu.h" // linden library includes +#include "lfidbearer.h" #include "llanimationstates.h" // For ANIM_AGENT_AWAY #include "llavatarnamecache.h" // IDEVO +#include "llexperiencecache.h" #include "llinventorypanel.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llfeaturemanager.h" #include "llsecondlifeurls.h" +#include "llurlaction.h" // #include "llfloaterblacklist.h" // #include "statemachine/aifilepicker.h" // newview includes +#include "lffloaterinvpanel.h" #include "lfsimfeaturehandler.h" #include "llagent.h" +#include "llagentbenefits.h" #include "llagentcamera.h" #include "llappearancemgr.h" #include "llagentwearables.h" - #include "llagentpilot.h" #include "llavatarpropertiesprocessor.h" #include "llcallingcard.h" @@ -61,6 +65,7 @@ #include "lldebugview.h" #include "llenvmanager.h" #include "llfirstuse.h" +#include "llfloateravatarlist.h" #include "llfloateravatartextures.h" #include "llfloaterbuy.h" #include "llfloaterbuycontents.h" @@ -70,10 +75,13 @@ #include "llfloatercustomize.h" #include "llfloaterdirectory.h" #include "llfloatereditui.h" +#include "llfloaterexperienceprofile.h" +#include "llfloaterexperiences.h" #include "llfloaterfonttest.h" #include "llfloatergodtools.h" #include "llfloaterhtmlcurrency.h" #include "llfloaterland.h" +#include "llfloatermarketplacelistings.h" #include "llfloatermute.h" #include "llfloateropenobject.h" #include "llfloaterpathfindingcharacters.h" @@ -89,20 +97,24 @@ #include "llframestats.h" #include "llavataractions.h" #include "llgivemoney.h" +#include "llgroupactions.h" #include "llgroupmgr.h" #include "llhoverview.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llinventoryfunctions.h" +#include "llmarketplacefunctions.h" #include "llmimetypes.h" #include "llmenuoptionpathfindingrebakenavmesh.h" #include "llmutelist.h" #include "llnotify.h" +#include "llpanelexperiences.h" #include "llparcel.h" #include "llregioninfomodel.h" #include "llselectmgr.h" #include "llstatusbar.h" #include "lltextureview.h" +#include "lltoolbar.h" #include "lltoolcomp.h" #include "lltoolgrab.h" #include "lltoolmgr.h" @@ -127,6 +139,8 @@ #include "llfloaternotificationsconsole.h" // +#include "jcfloaterareasearch.h" +#include "lltexteditor.h" // Initialize the text editor menu listeners in here #include "llfloatermessagelog.h" #include "shfloatermediaticker.h" #include "llpacketring.h" @@ -137,7 +151,6 @@ #include "llviewerobjectbackup.h" #include "llagentui.h" #include "llpathfindingmanager.h" -#include #include "lltexturecache.h" #include "llvovolume.h" @@ -192,44 +205,41 @@ extern BOOL gDebugTextEditorTips; extern BOOL gShowOverlayTitle; extern BOOL gOcclusionCull; extern AIHTTPView* gHttpView; -extern LLMenuGL* sScrollListMenus[1]; // // Globals // -LLMenuBarGL *gMenuBarView = NULL; -LLViewerMenuHolderGL *gMenuHolder = NULL; -LLMenuGL *gPopupMenuView = NULL; -LLMenuBarGL *gLoginMenuBarView = NULL; +LLMenuBarGL *gMenuBarView = nullptr; +LLViewerMenuHolderGL *gMenuHolder = nullptr; +LLMenuBarGL *gLoginMenuBarView = nullptr; // Pie menus -LLContextMenu *gPieSelf = NULL; -LLContextMenu *gPieAvatar = NULL; -LLContextMenu *gPieObject = NULL; -LLContextMenu *gPieAttachment = NULL; -LLContextMenu *gPieLand = NULL; +LLContextMenu *gPieSelf = nullptr; +LLContextMenu *gPieAvatar = nullptr; +LLContextMenu *gPieObject = nullptr; +LLContextMenu *gPieAttachment = nullptr; +LLContextMenu *gPieLand = nullptr; // local constants const std::string CLIENT_MENU_NAME("Advanced"); const std::string SERVER_MENU_NAME("Admin"); -const std::string SAVE_INTO_INVENTORY("Save Object Back to My Inventory"); const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents"); -LLMenuGL* gAttachSubMenu = NULL; -LLMenuGL* gDetachSubMenu = NULL; -LLMenuGL* gTakeOffClothes = NULL; -LLMenuGL* gMeshesAndMorphsMenu = NULL; -LLContextMenu* gPieRate = NULL; -LLContextMenu* gAttachScreenPieMenu = NULL; -LLContextMenu* gAttachPieMenu = NULL; -LLContextMenu* gAttachBodyPartPieMenus[8]; -LLContextMenu* gDetachPieMenu = NULL; -LLContextMenu* gDetachScreenPieMenu = NULL; -LLContextMenu* gDetachBodyPartPieMenus[8]; - -LLMenuItemCallGL* gAFKMenu = NULL; -LLMenuItemCallGL* gBusyMenu = NULL; +LLMenuGL* gAttachSubMenu = nullptr; +LLMenuGL* gDetachSubMenu = nullptr; +LLMenuGL* gTakeOffClothes = nullptr; +LLMenuGL* gMeshesAndMorphsMenu = nullptr; +LLContextMenu* gPieRate = nullptr; +LLContextMenu* gAttachScreenPieMenu = nullptr; +LLContextMenu* gAttachPieMenu = nullptr; +LLContextMenu* gAttachPieMenu2 = nullptr; +LLContextMenu* gDetachPieMenu = nullptr; +LLContextMenu* gDetachPieMenu2 = nullptr; +LLContextMenu* gDetachScreenPieMenu = nullptr; + +LLMenuItemCallGL* gAFKMenu = nullptr; +LLMenuItemCallGL* gBusyMenu = nullptr; typedef LLMemberListener view_listener_t; @@ -347,7 +357,7 @@ void handle_pose_stand_stop(void*) } void cleanup_pose_stand() { - handle_pose_stand_stop(NULL); + handle_pose_stand_stop(nullptr); } BOOL handle_check_pose(void* userdata) { return current_pose.notNull(); } @@ -446,7 +456,6 @@ BOOL enable_land_selected( void* ); BOOL enable_more_than_one_selected(void* ); BOOL enable_selection_you_own_all(void*); BOOL enable_selection_you_own_one(void*); -BOOL enable_save_into_inventory(void*); BOOL enable_save_into_task_inventory(void*); BOOL enable_detach(const LLSD& = LLSD()); @@ -471,15 +480,15 @@ void reset_vertex_buffers(void *user_data) gPipeline.resetVertexBuffers(); } -class LLMenuParcelObserver : public LLParcelObserver +class LLMenuParcelObserver final : public LLParcelObserver { public: LLMenuParcelObserver(); ~LLMenuParcelObserver(); - virtual void changed(); + void changed() override; }; -static LLMenuParcelObserver* gMenuParcelObserver = NULL; +static LLMenuParcelObserver* gMenuParcelObserver = nullptr; LLMenuParcelObserver::LLMenuParcelObserver() { @@ -493,9 +502,9 @@ LLMenuParcelObserver::~LLMenuParcelObserver() void LLMenuParcelObserver::changed() { - gMenuHolder->childSetEnabled("Land Buy Pass", LLPanelLandGeneral::enableBuyPass(NULL)); + gMenuHolder->childSetEnabled("Land Buy Pass", LLPanelLandGeneral::enableBuyPass(nullptr)); - BOOL buyable = enable_buy_land(NULL); + BOOL buyable = enable_buy_land(nullptr); gMenuHolder->childSetEnabled("Land Buy", buyable); gMenuHolder->childSetEnabled("Buy Land...", buyable); } @@ -555,6 +564,7 @@ void build_pie_menus() // TomY TODO: what shall we do about these? gDetachScreenPieMenu = gMenuHolder->getChild("Object Detach HUD", true); gDetachPieMenu = gMenuHolder->getChild("Object Detach", true); + gDetachPieMenu2 = gMenuHolder->getChild("Object Detach More", true); if (gPieAvatar) delete gPieAvatar; gPieAvatar = LLUICtrlFactory::getInstance()->buildContextMenu("menu_pie_avatar.xml", gMenuHolder); @@ -564,6 +574,7 @@ void build_pie_menus() gAttachScreenPieMenu = gMenuHolder->getChild("Object Attach HUD"); gAttachPieMenu = gMenuHolder->getChild("Object Attach"); + gAttachPieMenu2 = gMenuHolder->getChild("Object Attach More"); gPieRate = gMenuHolder->getChild("Rate Menu"); if (gPieAttachment) delete gPieAttachment; @@ -583,6 +594,38 @@ void rebuild_context_menus() gAgentAvatarp->buildContextMenus(); } +void set_merchant_SLM_menu() +{ + // DD-170 : SLM Alpha and Beta program : for the moment, we always show the SLM menu and + // tools so that all merchants can try out the UI, even if not migrated. + // *TODO : Keep SLM UI hidden for non migrated merchant in released viewer + gMenuHolder->getChild("MarketplaceListings")->setVisible(TRUE); + gToolBar->getChild("marketplace_listings_btn")->setEnabled(true); +} + +void check_merchant_status(bool force) +{ + if (!gSavedSettings.getBOOL("InventoryOutboxDisplayBoth")) + { + if (force) + { + // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status() + LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED); + } + // Hide SLM related menu item + gMenuHolder->getChild("MarketplaceListings")->setVisible(FALSE); + + // Also disable the toolbar button for Marketplace Listings + gToolBar->getChild("marketplace_listings_btn")->setEnabled(false); + + if (!gAgent.getRegionCapability("DirectDelivery").empty()) + { + // Launch an SLM test connection to get the merchant status + LLMarketplaceData::instance().initializeSLM(boost::bind(&set_merchant_SLM_menu)); + } + } +} + void init_menus() { S32 top = gViewerWindow->getRootView()->getRect().getHeight(); @@ -601,16 +644,6 @@ void init_menus() // Initialize actions initialize_menus(); - /// - /// Popup menu - /// - /// The popup menu is now populated by the show_context_menu() - /// method. - - gPopupMenuView = new LLMenuGL( "Popup" ); - gPopupMenuView->setVisible( FALSE ); - gMenuHolder->addChild( gPopupMenuView ); - /// /// Pie menus /// @@ -623,9 +656,6 @@ void init_menus() /// LLColor4 color; - color = gColors.getColor( "MenuPopupBgColor" ); - gPopupMenuView->setBackgroundColor( color ); - // If we are not in production, use a different color to make it apparent. if (LLViewerLogin::getInstance()->isInProductionGrid()) { @@ -651,15 +681,15 @@ void init_menus() gViewerWindow->setMenuBackgroundColor(false, LLViewerLogin::getInstance()->isInProductionGrid()); - // Assume L$10 for now, the server will tell us the real cost at login - const std::string upload_cost("10"); - std::string fee = gHippoGridManager->getConnectedGrid()->getCurrencySymbol() + "10"; - gMenuHolder->childSetLabelArg("Upload Image", "[UPLOADFEE]", fee); - gMenuHolder->childSetLabelArg("Upload Sound", "[UPLOADFEE]", fee); - gMenuHolder->childSetLabelArg("Upload Animation", "[UPLOADFEE]", fee); - gMenuHolder->childSetLabelArg("Bulk Upload", "[UPLOADFEE]", fee); - gMenuHolder->childSetLabelArg("Buy and Sell L$...", "[CURRENCY]", - gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); + std::string symbol = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); + auto& benefits = LLAgentBenefitsMgr::current(); + const std::string texture_upload_cost_str = symbol + fmt::to_string(benefits.getTextureUploadCost()); + const std::string sound_upload_cost_str = symbol + fmt::to_string(benefits.getSoundUploadCost()); + const std::string animation_upload_cost_str = symbol + fmt::to_string(benefits.getAnimationUploadCost()); + gMenuHolder->childSetLabelArg("Upload Image", "[UPLOADFEE]", texture_upload_cost_str); + gMenuHolder->childSetLabelArg("Upload Sound", "[UPLOADFEE]", sound_upload_cost_str); + gMenuHolder->childSetLabelArg("Upload Animation", "[UPLOADFEE]", animation_upload_cost_str); + gMenuHolder->childSetLabelArg("Buy and Sell L$...", "[CURRENCY]", symbol); gAFKMenu = gMenuBarView->getChild("Set Away", TRUE); gBusyMenu = gMenuBarView->getChild("Set Busy", TRUE); @@ -671,13 +701,13 @@ void init_menus() /*LLMenuGL* sub = new LLMenuGL("Pose Stand..."); menu->addChild(sub); - sub->addChild(new LLMenuItemCallGL( "Legs Together Arms Out", &handle_pose_stand_ltao, NULL)); - sub->addChild(new LLMenuItemCallGL( "Legs Together Arms Half", &handle_pose_stand_ltah, NULL)); - sub->addChild(new LLMenuItemCallGL( "Legs Together Arms Down", &handle_pose_stand_ltad, NULL)); - sub->addChild(new LLMenuItemCallGL( "Legs Out Arms Up", &handle_pose_stand_loau, NULL)); - sub->addChild(new LLMenuItemCallGL( "Legs Out Arms Out", &handle_pose_stand_loao, NULL)); - sub->addChild(new LLMenuItemCallGL( "Legs Half Arms Out", &handle_pose_stand_lhao, NULL)); - sub->addChild(new LLMenuItemCallGL( "Stop Pose Stand", &handle_pose_stand_stop, NULL)); + sub->addChild(new LLMenuItemCallGL( "Legs Together Arms Out", &handle_pose_stand_ltao, nullptr)); + sub->addChild(new LLMenuItemCallGL( "Legs Together Arms Half", &handle_pose_stand_ltah, nullptr)); + sub->addChild(new LLMenuItemCallGL( "Legs Together Arms Down", &handle_pose_stand_ltad, nullptr)); + sub->addChild(new LLMenuItemCallGL( "Legs Out Arms Up", &handle_pose_stand_loau, nullptr)); + sub->addChild(new LLMenuItemCallGL( "Legs Out Arms Out", &handle_pose_stand_loao, nullptr)); + sub->addChild(new LLMenuItemCallGL( "Legs Half Arms Out", &handle_pose_stand_lhao, nullptr)); + sub->addChild(new LLMenuItemCallGL( "Stop Pose Stand", &handle_pose_stand_stop, nullptr)); // ------------------------------------------------------*/ // TomY TODO convert these two @@ -708,9 +738,10 @@ void init_menus() menu = new LLMenuGL(CLIENT_MENU_NAME); menu->setCanTearOff(FALSE); - menu->addChild(new LLMenuItemCallGL("Debug Settings...", handle_singleton_toggle, NULL, NULL)); + menu->addChild(new LLMenuItemCallGL("Debug Settings...", handle_singleton_toggle, nullptr, nullptr)); // Debugging view for unified notifications: CTRL-SHIFT-5 - menu->addChild(new LLMenuItemCallGL("Notifications Console...", handle_show_notifications_console, NULL, NULL, '5', MASK_CONTROL|MASK_SHIFT)); + menu->addChild(new LLMenuItemCallGL("Notifications Console...", handle_show_notifications_console, nullptr, nullptr, '5', MASK_CONTROL|MASK_SHIFT)); + menu->addChild(new LLMenuItemCallGL("Load from XML...", handle_load_from_xml)); gLoginMenuBarView->addChild(menu); menu->updateParent(LLMenuGL::sMenuContainer); @@ -727,8 +758,7 @@ void init_menus() gMenuHolder->addChild(gLoginMenuBarView); // Singu Note: Initialize common ScrollListMenus here - sScrollListMenus[0] = LLUICtrlFactory::getInstance()->buildMenu("menu_avs_list.xml", gMenuHolder); - //sScrollListMenus[1] = LLUICtrlFactory::getInstance()->buildMenu("menu_groups_list.xml"); // Singu TODO + LFIDBearer::buildMenus(); LLView* ins = gMenuBarView->getChildView("insert_world", true, false); ins->setVisible(false); @@ -749,7 +779,7 @@ void init_menus() void init_client_menu(LLMenuGL* menu) { - LLMenuGL* sub_menu = NULL; + LLMenuGL* sub_menu = nullptr; { @@ -759,20 +789,20 @@ void init_client_menu(LLMenuGL* menu) menu->addChild(sub); sub->addChild(new LLMenuItemCheckGL("Frame Console", &toggle_visibility, - NULL, + nullptr, &get_visibility, (void*)gDebugView->mFrameStatView, '2', MASK_CONTROL|MASK_SHIFT ) ); sub->addChild(new LLMenuItemCheckGL("Texture Console", &toggle_visibility, - NULL, + nullptr, &get_visibility, (void*)gTextureView, '3', MASK_CONTROL|MASK_SHIFT ) ); LLView* debugview = gDebugView->mDebugConsolep; sub->addChild(new LLMenuItemCheckGL("Debug Console", &toggle_visibility, - NULL, + nullptr, &get_visibility, debugview, '4', MASK_CONTROL|MASK_SHIFT ) ); @@ -781,13 +811,13 @@ void init_client_menu(LLMenuGL* menu) { sub->addChild(new LLMenuItemCheckGL("Texture Size Console", &toggle_visibility, - NULL, + nullptr, &get_visibility, (void*)gTextureSizeView, '5', MASK_CONTROL|MASK_SHIFT ) ); sub->addChild(new LLMenuItemCheckGL("Texture Category Console", &toggle_visibility, - NULL, + nullptr, &get_visibility, (void*)gTextureCategoryView, '6', MASK_CONTROL|MASK_SHIFT ) ); @@ -795,16 +825,16 @@ void init_client_menu(LLMenuGL* menu) sub->addChild(new LLMenuItemCheckGL("HTTP Console", &toggle_visibility, - NULL, + nullptr, &get_visibility, (void*)gHttpView, '7', MASK_CONTROL|MASK_SHIFT ) ); - sub->addChild(new LLMenuItemCheckGL("Region Debug Console", handle_singleton_toggle, NULL, handle_singleton_check,NULL,'`', MASK_CONTROL|MASK_SHIFT)); + sub->addChild(new LLMenuItemCheckGL("Region Debug Console", handle_singleton_toggle, nullptr, handle_singleton_check,nullptr,'`', MASK_CONTROL|MASK_SHIFT)); sub->addChild(new LLMenuItemCheckGL("Fast Timers", &toggle_visibility, - NULL, + nullptr, &get_visibility, (void*)gDebugView->mFastTimerView, '9', MASK_CONTROL|MASK_SHIFT ) ); @@ -813,25 +843,25 @@ void init_client_menu(LLMenuGL* menu) // Debugging view for unified notifications sub->addChild(new LLMenuItemCallGL("Notifications Console...", - &handle_show_notifications_console, NULL, NULL, '5', MASK_CONTROL|MASK_SHIFT )); + &handle_show_notifications_console, nullptr, nullptr, '5', MASK_CONTROL|MASK_SHIFT )); sub->addSeparator(); sub->addChild(new LLMenuItemCallGL("Region Info to Debug Console", - &handle_region_dump_settings, NULL)); + &handle_region_dump_settings, nullptr)); sub->addChild(new LLMenuItemCallGL("Group Info to Debug Console", - &handle_dump_group_info, NULL, NULL)); + &handle_dump_group_info, nullptr, nullptr)); sub->addChild(new LLMenuItemCallGL("Capabilities Info to Debug Console", - &handle_dump_capabilities_info, NULL, NULL)); + &handle_dump_capabilities_info, nullptr, nullptr)); sub->createJumpKeys(); } // neither of these works particularly well at the moment /*menu->addChild(new LLMenuItemCallGL( "Reload UI XML", &reload_ui, - NULL, NULL) );*/ + nullptr, nullptr) );*/ /*menu->addChild(new LLMenuItemCallGL("Reload settings/colors", - &handle_reload_settings, NULL, NULL));*/ + &handle_reload_settings, nullptr, nullptr));*/ menu->addChild(new LLMenuItemCallGL("Reload personal setting overrides", &reload_personal_settings_overrides)); @@ -840,7 +870,7 @@ void init_client_menu(LLMenuGL* menu) sub_menu->setCanTearOff(TRUE); sub_menu->addChild(new LLMenuItemCheckGL("Velocity", &toggle_visibility, - NULL, + nullptr, &get_visibility, (void*)gVelocityBar)); @@ -855,25 +885,25 @@ void init_client_menu(LLMenuGL* menu) menu->addChild(new LLMenuItemCheckGL( "High-res Snapshot", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"HighResSnapshot")); menu->addChild(new LLMenuItemCheckGL( "Quiet Snapshots to Disk", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"QuietSnapshotsToDisk")); menu->addChild(new LLMenuItemCheckGL("Show Mouselook Crosshairs", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"ShowCrosshairs")); menu->addChild(new LLMenuItemCheckGL("Debug Permissions", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"DebugPermissions")); @@ -885,7 +915,7 @@ void init_client_menu(LLMenuGL* menu) { menu->addChild(new LLMenuItemCheckGL("Hacked Godmode", &handle_toggle_hacked_godmode, - NULL, + nullptr, &check_toggle_hacked_godmode, (void*)"HackedGodmode")); } @@ -894,7 +924,7 @@ void init_client_menu(LLMenuGL* menu) menu->addChild(new LLMenuItemCallGL("Clear Group Cache", LLGroupMgr::debugClearAllGroups)); - menu->addChild(new LLMenuItemCheckGL("Use Web Map Tiles", menu_toggle_control, NULL, menu_check_control, (void*)"UseWebMapTiles")); + menu->addChild(new LLMenuItemCheckGL("Use Web Map Tiles", menu_toggle_control, nullptr, menu_check_control, (void*)"UseWebMapTiles")); menu->addSeparator(); @@ -934,67 +964,67 @@ void init_client_menu(LLMenuGL* menu) menu->addChild(sub_menu); { - LLMenuGL* sub = NULL; + LLMenuGL* sub = nullptr; sub = new LLMenuGL("Network"); sub->setCanTearOff(TRUE); - sub->addChild(new LLMenuItemCallGL( "Message Log", &handle_open_message_log, NULL)); + sub->addChild(new LLMenuItemCallGL("Message Log", handle_open_message_log, nullptr)); sub->addChild(new LLMenuItemCallGL("Enable Message Log", - &handle_viewer_enable_message_log, NULL)); + &handle_viewer_enable_message_log, nullptr)); sub->addChild(new LLMenuItemCallGL("Disable Message Log", - &handle_viewer_disable_message_log, NULL)); + &handle_viewer_disable_message_log, nullptr)); sub->addSeparator(); sub->addChild(new LLMenuItemCheckGL("Velocity Interpolate Objects", &velocity_interpolate, - NULL, + nullptr, &menu_check_control, (void*)"VelocityInterpolate")); sub->addChild(new LLMenuItemCheckGL("Ping Interpolate Object Positions", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"PingInterpolate")); sub->addSeparator(); sub->addChild(new LLMenuItemCallGL("Drop a Packet", - &drop_packet, NULL, NULL, + &drop_packet, nullptr, nullptr, 'L', MASK_ALT | MASK_CONTROL)); menu->addChild( sub ); sub->createJumpKeys(); } { - LLMenuGL* sub = NULL; + LLMenuGL* sub = nullptr; sub = new LLMenuGL("Recorder"); sub->setCanTearOff(TRUE); - sub->addChild(new LLMenuItemCheckGL("Full Session Logging", &menu_toggle_control, NULL, &menu_check_control, (void*)"StatsSessionTrackFrameStats")); + sub->addChild(new LLMenuItemCheckGL("Full Session Logging", &menu_toggle_control, nullptr, &menu_check_control, (void*)"StatsSessionTrackFrameStats")); - sub->addChild(new LLMenuItemCallGL("Start Logging", &LLFrameStats::startLogging, NULL)); - sub->addChild(new LLMenuItemCallGL("Stop Logging", &LLFrameStats::stopLogging, NULL)); - sub->addChild(new LLMenuItemCallGL("Log 10 Seconds", &LLFrameStats::timedLogging10, NULL)); - sub->addChild(new LLMenuItemCallGL("Log 30 Seconds", &LLFrameStats::timedLogging30, NULL)); - sub->addChild(new LLMenuItemCallGL("Log 60 Seconds", &LLFrameStats::timedLogging60, NULL)); + sub->addChild(new LLMenuItemCallGL("Start Logging", &LLFrameStats::startLogging, nullptr)); + sub->addChild(new LLMenuItemCallGL("Stop Logging", &LLFrameStats::stopLogging, nullptr)); + sub->addChild(new LLMenuItemCallGL("Log 10 Seconds", &LLFrameStats::timedLogging10, nullptr)); + sub->addChild(new LLMenuItemCallGL("Log 30 Seconds", &LLFrameStats::timedLogging30, nullptr)); + sub->addChild(new LLMenuItemCallGL("Log 60 Seconds", &LLFrameStats::timedLogging60, nullptr)); sub->addSeparator(); - sub->addChild(new LLMenuItemCallGL("Start Playback", &LLAgentPilot::startPlayback, NULL)); - sub->addChild(new LLMenuItemCallGL("Stop Playback", &LLAgentPilot::stopPlayback, NULL)); + sub->addChild(new LLMenuItemCallGL("Start Playback", &LLAgentPilot::startPlayback, nullptr)); + sub->addChild(new LLMenuItemCallGL("Stop Playback", &LLAgentPilot::stopPlayback, nullptr)); sub->addChild(new LLMenuItemToggleGL("Loop Playback", &LLAgentPilot::sLoop) ); - sub->addChild(new LLMenuItemCallGL("Start Record", &LLAgentPilot::startRecord, NULL)); - sub->addChild(new LLMenuItemCallGL("Stop Record", &LLAgentPilot::saveRecord, NULL)); + sub->addChild(new LLMenuItemCallGL("Start Record", &LLAgentPilot::startRecord, nullptr)); + sub->addChild(new LLMenuItemCallGL("Stop Record", &LLAgentPilot::saveRecord, nullptr)); menu->addChild( sub ); sub->createJumpKeys(); } { - LLMenuGL* sub = NULL; + LLMenuGL* sub = nullptr; sub = new LLMenuGL("Media"); sub->setCanTearOff(TRUE); sub->addChild(new LLMenuItemCallGL("Reload MIME types", &LLMIMETypes::reload)); - sub->addChild(new LLMenuItemCallGL("Web Browser Test", &handle_web_browser_test, NULL, NULL, KEY_F1)); + sub->addChild(new LLMenuItemCallGL("Web Browser Test", &handle_web_browser_test, nullptr, nullptr, KEY_F1)); menu->addChild( sub ); sub->createJumpKeys(); } @@ -1007,29 +1037,29 @@ void init_client_menu(LLMenuGL* menu) menu->addSeparator(); menu->addChild(new LLMenuItemCallGL("Compress Images...", - &handle_compress_image, NULL, NULL)); + &handle_compress_image, nullptr, nullptr)); menu->addChild(new LLMenuItemCheckGL("Limit Select Distance", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"LimitSelectDistance")); menu->addChild(new LLMenuItemCheckGL("Disable Camera Constraints", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"DisableCameraConstraints")); menu->addChild(new LLMenuItemCheckGL("Mouse Smoothing", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*) "MouseSmooth")); // Singu Note: When this menu is xml, handle this above, with the other insertion points { - LLMenuItemCallGL* item = new LLMenuItemCallGL("insert_advanced", NULL); + LLMenuItemCallGL* item = new LLMenuItemCallGL("insert_advanced", nullptr); item->setVisible(false); menu->addChild(item); } @@ -1037,22 +1067,22 @@ void init_client_menu(LLMenuGL* menu) menu->addChild(new LLMenuItemCheckGL( "Console Window", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"ShowConsoleWindow")); // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-1.0.0e | OK if (gSavedSettings.controlExists(RLV_SETTING_MAIN)) - menu->addChild(new LLMenuItemCheckGL("RestrainedLove API", &rlvMenuToggleEnabled, NULL, &rlvMenuCheckEnabled, NULL)); + menu->addChild(new LLMenuItemCheckGL("RestrainedLove API", &rlvMenuToggleEnabled, nullptr, &rlvMenuCheckEnabled, nullptr)); // [/RLVa:KB] if(gSavedSettings.getBOOL("QAMode")) { - LLMenuGL* sub = NULL; + LLMenuGL* sub = nullptr; sub = new LLMenuGL("Debugging"); sub->setCanTearOff(TRUE); #if LL_WINDOWS - sub->addChild(new LLMenuItemCallGL("Force Breakpoint", &force_error_breakpoint, NULL, NULL, 'B', MASK_CONTROL | MASK_ALT)); + sub->addChild(new LLMenuItemCallGL("Force Breakpoint", &force_error_breakpoint, nullptr, nullptr, 'B', MASK_CONTROL | MASK_ALT)); #endif sub->addChild(new LLMenuItemCallGL("Force LLError And Crash", &force_error_llerror)); sub->addChild(new LLMenuItemCallGL("Force Bad Memory Access", &force_error_bad_memory_access)); @@ -1066,18 +1096,18 @@ void init_client_menu(LLMenuGL* menu) menu->addChild(new LLMenuItemCheckGL( "Output Debug Minidump", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"SaveMinidump")); - menu->addChild(new LLMenuItemCallGL("Debug Settings...", handle_singleton_toggle, NULL, NULL)); - menu->addChild(new LLMenuItemCheckGL("View Admin Options", &handle_admin_override_toggle, NULL, &check_admin_override, NULL, 'V', MASK_CONTROL | MASK_ALT)); + menu->addChild(new LLMenuItemCallGL("Debug Settings...", handle_singleton_toggle, nullptr, nullptr)); + menu->addChild(new LLMenuItemCheckGL("View Admin Options", &handle_admin_override_toggle, nullptr, &check_admin_override, nullptr, 'V', MASK_CONTROL | MASK_ALT)); menu->addChild(new LLMenuItemCallGL("Request Admin Status", - &handle_god_mode, NULL, NULL, 'G', MASK_ALT | MASK_CONTROL)); + &handle_god_mode, nullptr, nullptr, 'G', MASK_ALT | MASK_CONTROL)); menu->addChild(new LLMenuItemCallGL("Leave Admin Status", - &handle_leave_god_mode, NULL, NULL, 'G', MASK_ALT | MASK_SHIFT | MASK_CONTROL)); + &handle_leave_god_mode, nullptr, nullptr, 'G', MASK_ALT | MASK_SHIFT | MASK_CONTROL)); menu->createJumpKeys(); } @@ -1087,25 +1117,25 @@ void init_debug_world_menu(LLMenuGL* menu) /* REMOVE mouse move sun from menu options menu->addChild(new LLMenuItemCheckGL("Mouse Moves Sun", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"MouseSun", 'M', MASK_CONTROL|MASK_ALT)); */ menu->addChild(new LLMenuItemCheckGL("Sim Sun Override", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"SkyOverrideSimSunPosition")); menu->addChild(new LLMenuItemCallGL("Dump Scripted Camera", - &handle_dump_followcam, NULL, NULL)); + &handle_dump_followcam, nullptr, nullptr)); menu->addChild(new LLMenuItemCheckGL("Fixed Weather", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"FixedWeather")); menu->addChild(new LLMenuItemCallGL("Dump Region Object Cache", - &handle_dump_region_object_cache, NULL, NULL)); + &handle_dump_region_object_cache, nullptr, nullptr)); menu->createJumpKeys(); } @@ -1131,9 +1161,9 @@ static void handle_export_menus_to_xml_continued(AIFilePicker* filepicker) void init_debug_ui_menu(LLMenuGL* menu) { - menu->addChild(new LLMenuItemCheckGL("Rotate Mini-Map", menu_toggle_control, NULL, menu_check_control, (void*)"MiniMapRotate")); - menu->addChild(new LLMenuItemCheckGL("Use default system color picker", menu_toggle_control, NULL, menu_check_control, (void*)"UseDefaultColorPicker")); - menu->addChild(new LLMenuItemCheckGL("Show search panel in overlay bar", menu_toggle_control, NULL, menu_check_control, (void*)"ShowSearchBar")); + menu->addChild(new LLMenuItemCheckGL("Rotate Mini-Map", menu_toggle_control, nullptr, menu_check_control, (void*)"MiniMapRotate")); + menu->addChild(new LLMenuItemCheckGL("Use default system color picker", menu_toggle_control, nullptr, menu_check_control, (void*)"UseDefaultColorPicker")); + menu->addChild(new LLMenuItemCheckGL("Show search panel in overlay bar", menu_toggle_control, nullptr, menu_check_control, (void*)"ShowSearchBar")); menu->addSeparator(); // commented out until work is complete: DEV-32268 @@ -1141,33 +1171,33 @@ void init_debug_ui_menu(LLMenuGL* menu) menu->addChild(new LLMenuItemCallGL("Editable UI", &edit_ui)); menu->addChild(new LLMenuItemCallGL( "Dump SelectMgr", &dump_select_mgr)); menu->addChild(new LLMenuItemCallGL( "Dump Inventory", &dump_inventory)); - menu->addChild(new LLMenuItemCallGL( "Dump Focus Holder", &handle_dump_focus, NULL, NULL, 'F', MASK_ALT | MASK_CONTROL)); - menu->addChild(new LLMenuItemCallGL( "Print Selected Object Info", &print_object_info, NULL, NULL, 'P', MASK_CONTROL|MASK_SHIFT )); - menu->addChild(new LLMenuItemCallGL( "Print Agent Info", &print_agent_nvpairs, NULL, NULL, 'P', MASK_SHIFT )); - menu->addChild(new LLMenuItemCallGL( "Memory Stats", &output_statistics, NULL, NULL, 'M', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); + menu->addChild(new LLMenuItemCallGL( "Dump Focus Holder", &handle_dump_focus, nullptr, nullptr, 'F', MASK_ALT | MASK_CONTROL)); + menu->addChild(new LLMenuItemCallGL( "Print Selected Object Info", &print_object_info, nullptr, nullptr, 'P', MASK_CONTROL|MASK_SHIFT )); + menu->addChild(new LLMenuItemCallGL( "Print Agent Info", &print_agent_nvpairs, nullptr, nullptr, 'P', MASK_SHIFT )); + menu->addChild(new LLMenuItemCallGL( "Memory Stats", &output_statistics, nullptr, nullptr, 'M', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); menu->addChild(new LLMenuItemCheckGL("Double-Click Auto-Pilot", - menu_toggle_double_click_control, NULL, menu_check_control, + menu_toggle_double_click_control, nullptr, menu_check_control, (void*)"DoubleClickAutoPilot")); // add for double click teleport support menu->addChild(new LLMenuItemCheckGL("Double-Click Teleport", - menu_toggle_double_click_control, NULL, menu_check_control, + menu_toggle_double_click_control, nullptr, menu_check_control, (void*)"DoubleClickTeleport")); menu->addSeparator(); -// menu->addChild(new LLMenuItemCallGL( "Print Packets Lost", &print_packets_lost, NULL, NULL, 'L', MASK_SHIFT )); - menu->addChild(new LLMenuItemCheckGL("Debug SelectMgr", menu_toggle_control, NULL, menu_check_control, (void*)"DebugSelectMgr")); +// menu->addChild(new LLMenuItemCallGL( "Print Packets Lost", &print_packets_lost, nullptr, nullptr, 'L', MASK_SHIFT )); + menu->addChild(new LLMenuItemCheckGL("Debug SelectMgr", menu_toggle_control, nullptr, menu_check_control, (void*)"DebugSelectMgr")); menu->addChild(new LLMenuItemToggleGL("Debug Clicks", &gDebugClicks)); menu->addChild(new LLMenuItemToggleGL("Debug Views", &LLView::sDebugRects)); - menu->addChild(new LLMenuItemCheckGL("Show Name Tooltips", toggle_show_xui_names, NULL, check_show_xui_names, NULL)); + menu->addChild(new LLMenuItemCheckGL("Show Name Tooltips", toggle_show_xui_names, nullptr, check_show_xui_names, nullptr)); menu->addChild(new LLMenuItemToggleGL("Debug Mouse Events", &LLView::sDebugMouseHandling)); menu->addChild(new LLMenuItemToggleGL("Debug Keys", &LLView::sDebugKeys)); menu->addChild(new LLMenuItemToggleGL("Debug WindowProc", &gDebugWindowProc)); menu->addChild(new LLMenuItemToggleGL("Debug Text Editor Tips", &gDebugTextEditorTips)); menu->addSeparator(); - menu->addChild(new LLMenuItemCheckGL("Show Time", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowTime")); - menu->addChild(new LLMenuItemCheckGL("Show Render Info", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowRenderInfo")); - menu->addChild(new LLMenuItemCheckGL("Show Matrices", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowRenderMatrices")); - menu->addChild(new LLMenuItemCheckGL("Show Color Under Cursor", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowColor")); - menu->addChild(new LLMenuItemCheckGL("Show FPS", menu_toggle_control, NULL, menu_check_control, (void*)"SLBShowFPS")); + menu->addChild(new LLMenuItemCheckGL("Show Time", menu_toggle_control, nullptr, menu_check_control, (void*)"DebugShowTime")); + menu->addChild(new LLMenuItemCheckGL("Show Render Info", menu_toggle_control, nullptr, menu_check_control, (void*)"DebugShowRenderInfo")); + menu->addChild(new LLMenuItemCheckGL("Show Matrices", menu_toggle_control, nullptr, menu_check_control, (void*)"DebugShowRenderMatrices")); + menu->addChild(new LLMenuItemCheckGL("Show Color Under Cursor", menu_toggle_control, nullptr, menu_check_control, (void*)"DebugShowColor")); + menu->addChild(new LLMenuItemCheckGL("Show FPS", menu_toggle_control, nullptr, menu_check_control, (void*)"SLBShowFPS")); menu->createJumpKeys(); } @@ -1181,16 +1211,16 @@ void init_debug_xui_menu(LLMenuGL* menu) menu->addChild(new LLMenuItemCallGL("Load from XML...", handle_load_from_xml)); // //menu->addChild(new LLMenuItemCallGL("Save to XML...", handle_save_to_xml)); - menu->addChild(new LLMenuItemCallGL("Save to XML...", handle_save_to_xml, NULL, NULL, 'X', MASK_CONTROL | MASK_ALT | MASK_SHIFT)); + menu->addChild(new LLMenuItemCallGL("Save to XML...", handle_save_to_xml, nullptr, nullptr, 'X', MASK_CONTROL | MASK_ALT | MASK_SHIFT)); // - menu->addChild(new LLMenuItemCheckGL("Show XUI Names", toggle_show_xui_names, NULL, check_show_xui_names, NULL)); + menu->addChild(new LLMenuItemCheckGL("Show XUI Names", toggle_show_xui_names, nullptr, check_show_xui_names, nullptr)); menu->createJumpKeys(); } void init_debug_rendering_menu(LLMenuGL* menu) { - LLMenuGL* sub_menu = NULL; + LLMenuGL* sub_menu = nullptr; /////////////////////////// // @@ -1201,43 +1231,43 @@ void init_debug_rendering_menu(LLMenuGL* menu) menu->addChild(sub_menu); sub_menu->addChild(new LLMenuItemCheckGL("Simple", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_SIMPLE, '1', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->addChild(new LLMenuItemCheckGL("Alpha", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_ALPHA, '2', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->addChild(new LLMenuItemCheckGL("Tree", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_TREE, '3', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->addChild(new LLMenuItemCheckGL("Character", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_AVATAR, '4', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->addChild(new LLMenuItemCheckGL("SurfacePatch", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_TERRAIN, '5', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->addChild(new LLMenuItemCheckGL("Sky", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_SKY, '6', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->addChild(new LLMenuItemCheckGL("Water", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_WATER, '7', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->addChild(new LLMenuItemCheckGL("Ground", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_GROUND, '8', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->addChild(new LLMenuItemCheckGL("Volume", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_VOLUME, '9', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->addChild(new LLMenuItemCheckGL("Grass", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_GRASS, '0', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); //NOTE: Using a static variable, as an unsigned long long cannot fit in the space of a pointer. Pass pointer to callbacks @@ -1247,15 +1277,15 @@ void init_debug_rendering_menu(LLMenuGL* menu) #endif ); sub_menu->addChild(new LLMenuItemCheckGL("Clouds", //This clobbers skyuseclassicclouds, but.. big deal. - &LLPipeline::toggleRenderPairedTypeControl, NULL, + &LLPipeline::toggleRenderPairedTypeControl, nullptr, &LLPipeline::hasRenderPairedTypeControl, (void*)&cloud_flags, '-', MASK_CONTROL|MASK_ALT| MASK_SHIFT)); sub_menu->addChild(new LLMenuItemCheckGL("Particles", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_PARTICLES, '=', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->addChild(new LLMenuItemCheckGL("Bump", - &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::toggleRenderTypeControl, nullptr, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_BUMP, '\\', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->createJumpKeys(); @@ -1268,35 +1298,35 @@ void init_debug_rendering_menu(LLMenuGL* menu) #define MODIFIER MASK_ALT #endif sub_menu->addChild(new LLMenuItemCheckGL("UI", - &LLPipeline::toggleRenderDebugFeature, NULL, + &LLPipeline::toggleRenderDebugFeature, nullptr, &LLPipeline::toggleRenderDebugFeatureControl, (void*)LLPipeline::RENDER_DEBUG_FEATURE_UI, KEY_F1, MODIFIER|MASK_CONTROL)); sub_menu->addChild(new LLMenuItemCheckGL("Selected", - &LLPipeline::toggleRenderDebugFeature, NULL, + &LLPipeline::toggleRenderDebugFeature, nullptr, &LLPipeline::toggleRenderDebugFeatureControl, (void*)LLPipeline::RENDER_DEBUG_FEATURE_SELECTED, KEY_F2, MODIFIER|MASK_CONTROL)); sub_menu->addChild(new LLMenuItemCheckGL("Highlighted", - &LLPipeline::toggleRenderDebugFeature, NULL, + &LLPipeline::toggleRenderDebugFeature, nullptr, &LLPipeline::toggleRenderDebugFeatureControl, (void*)LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED, KEY_F3, MODIFIER|MASK_CONTROL)); sub_menu->addChild(new LLMenuItemCheckGL("Dynamic Textures", - &LLPipeline::toggleRenderDebugFeature, NULL, + &LLPipeline::toggleRenderDebugFeature, nullptr, &LLPipeline::toggleRenderDebugFeatureControl, (void*)LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES, KEY_F4, MODIFIER|MASK_CONTROL)); sub_menu->addChild(new LLMenuItemCheckGL( "Foot Shadows", - &LLPipeline::toggleRenderDebugFeature, NULL, + &LLPipeline::toggleRenderDebugFeature, nullptr, &LLPipeline::toggleRenderDebugFeatureControl, (void*)LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS, KEY_F5, MODIFIER|MASK_CONTROL)); sub_menu->addChild(new LLMenuItemCheckGL("Fog", - &LLPipeline::toggleRenderDebugFeature, NULL, + &LLPipeline::toggleRenderDebugFeature, nullptr, &LLPipeline::toggleRenderDebugFeatureControl, (void*)LLPipeline::RENDER_DEBUG_FEATURE_FOG, KEY_F6, MODIFIER|MASK_CONTROL)); sub_menu->addChild(new LLMenuItemCheckGL("Test FRInfo", - &LLPipeline::toggleRenderDebugFeature, NULL, + &LLPipeline::toggleRenderDebugFeature, nullptr, &LLPipeline::toggleRenderDebugFeatureControl, (void*)LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO, KEY_F8, MODIFIER|MASK_CONTROL)); sub_menu->addChild(new LLMenuItemCheckGL( "Flexible Objects", - &LLPipeline::toggleRenderDebugFeature, NULL, + &LLPipeline::toggleRenderDebugFeature, nullptr, &LLPipeline::toggleRenderDebugFeatureControl, (void*)LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE, KEY_F9, MODIFIER|MASK_CONTROL)); sub_menu->createJumpKeys(); @@ -1309,79 +1339,79 @@ void init_debug_rendering_menu(LLMenuGL* menu) sub_menu->setCanTearOff(TRUE); menu->addChild(sub_menu); - sub_menu->addChild(new LLMenuItemCheckGL("Verify", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Verify", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_VERIFY)); - sub_menu->addChild(new LLMenuItemCheckGL("BBoxes", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("BBoxes", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_BBOXES)); - sub_menu->addChild(new LLMenuItemCheckGL("Points", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Points", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_POINTS)); - sub_menu->addChild(new LLMenuItemCheckGL("Octree", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Octree", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_OCTREE)); - sub_menu->addChild(new LLMenuItemCheckGL("Shadow Frusta", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Shadow Frusta", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)); - sub_menu->addChild(new LLMenuItemCheckGL("Occlusion", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Occlusion", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_OCCLUSION)); - sub_menu->addChild(new LLMenuItemCheckGL("Render Batches", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Render Batches", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_BATCH_SIZE)); - sub_menu->addChild(new LLMenuItemCheckGL("Animated Textures", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Animated Textures", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_TEXTURE_ANIM)); - sub_menu->addChild(new LLMenuItemCheckGL("Texture Priority", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Texture Priority", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)); - sub_menu->addChild(new LLMenuItemCheckGL("Avatar Rendering Cost", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Avatar Rendering Cost", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_SHAME, 'C', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); - sub_menu->addChild(new LLMenuItemCheckGL("Texture Area (sqrt(A))",&LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Texture Area (sqrt(A))",&LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_TEXTURE_AREA)); - sub_menu->addChild(new LLMenuItemCheckGL("Face Area (sqrt(A))",&LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Face Area (sqrt(A))",&LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_FACE_AREA)); - sub_menu->addChild(new LLMenuItemCheckGL("Lights", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Lights", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_LIGHTS)); - sub_menu->addChild(new LLMenuItemCheckGL("Particles", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Particles", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_PARTICLES)); - sub_menu->addChild(new LLMenuItemCheckGL("Composition", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Composition", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_COMPOSITION)); - sub_menu->addChild(new LLMenuItemCheckGL("Glow",&LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Glow",&LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_GLOW)); - sub_menu->addChild(new LLMenuItemCheckGL("Raycasting", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Raycasting", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_RAYCAST)); - sub_menu->addChild(new LLMenuItemCheckGL("Sculpt", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Sculpt", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_SCULPTED)); - sub_menu->addChild(new LLMenuItemCheckGL("Build Queue", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Build Queue", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_BUILD_QUEUE)); - sub_menu->addChild(new LLMenuItemCheckGL("Update Types", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Update Types", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_UPDATE_TYPE)); - sub_menu->addChild(new LLMenuItemCheckGL("Physics Shapes", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Physics Shapes", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)); - sub_menu->addChild(new LLMenuItemCheckGL("Normals", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Normals", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_NORMALS)); - sub_menu->addChild(new LLMenuItemCheckGL("LOD Info", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("LOD Info", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_LOD_INFO)); - sub_menu->addChild(new LLMenuItemCheckGL("Wind Vectors", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Wind Vectors", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_WIND_VECTORS)); - sub_menu->addChild(new LLMenuItemCheckGL("Complexity", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->addChild(new LLMenuItemCheckGL("Complexity", &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY)); @@ -1390,7 +1420,7 @@ void init_debug_rendering_menu(LLMenuGL* menu) sub_menu->addChild(new LLMenuItemCheckGL("Camera Offset", &menu_toggle_control, - NULL, + nullptr, &menu_check_control, (void*)"CameraOffset")); @@ -1405,68 +1435,68 @@ void init_debug_rendering_menu(LLMenuGL* menu) menu->addChild( sub_menu ); menu->addSeparator(); - menu->addChild(new LLMenuItemCheckGL("Axes", menu_toggle_control, NULL, menu_check_control, (void*)"ShowAxes")); + menu->addChild(new LLMenuItemCheckGL("Axes", menu_toggle_control, nullptr, menu_check_control, (void*)"ShowAxes")); menu->addSeparator(); - menu->addChild(new LLMenuItemCheckGL("Hide Selected", menu_toggle_control, NULL, menu_check_control, (void*)"HideSelectedObjects")); + menu->addChild(new LLMenuItemCheckGL("Hide Selected", menu_toggle_control, nullptr, menu_check_control, (void*)"HideSelectedObjects")); menu->addSeparator(); - menu->addChild(new LLMenuItemCheckGL("Tangent Basis", menu_toggle_control, NULL, menu_check_control, (void*)"ShowTangentBasis")); - menu->addChild(new LLMenuItemCallGL("Selected Texture Info", handle_selected_texture_info, NULL, NULL, 'T', MASK_CONTROL|MASK_SHIFT|MASK_ALT)); - //menu->addChild(new LLMenuItemCallGL("Dump Image List", handle_dump_image_list, NULL, NULL, 'I', MASK_CONTROL|MASK_SHIFT)); + menu->addChild(new LLMenuItemCheckGL("Tangent Basis", menu_toggle_control, nullptr, menu_check_control, (void*)"ShowTangentBasis")); + menu->addChild(new LLMenuItemCallGL("Selected Texture Info", handle_selected_texture_info, nullptr, nullptr, 'T', MASK_CONTROL|MASK_SHIFT|MASK_ALT)); + //menu->addChild(new LLMenuItemCallGL("Dump Image List", handle_dump_image_list, nullptr, nullptr, 'I', MASK_CONTROL|MASK_SHIFT)); - menu->addChild(new LLMenuItemCheckGL("Wireframe", advanced_toggle_wireframe, NULL, advanced_check_wireframe, NULL, 'R', MASK_CONTROL|MASK_SHIFT)); + menu->addChild(new LLMenuItemCheckGL("Wireframe", advanced_toggle_wireframe, nullptr, advanced_check_wireframe, nullptr, 'R', MASK_CONTROL|MASK_SHIFT)); LLMenuItemCheckGL* item; - item = new LLMenuItemCheckGL("Object-Object Occlusion", menu_toggle_control, NULL, menu_check_control, (void*)"UseOcclusion", 'O', MASK_CONTROL|MASK_SHIFT); + item = new LLMenuItemCheckGL("Object-Object Occlusion", menu_toggle_control, nullptr, menu_check_control, (void*)"UseOcclusion", 'O', MASK_CONTROL|MASK_SHIFT); item->setEnabled(gGLManager.mHasOcclusionQuery && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion")); menu->addChild(item); - item = new LLMenuItemCheckGL("Debug GL", menu_toggle_control, NULL, menu_check_control, (void*)"RenderDebugGL"); + item = new LLMenuItemCheckGL("Debug GL", menu_toggle_control, nullptr, menu_check_control, (void*)"RenderDebugGL"); menu->addChild(item); - item = new LLMenuItemCheckGL("Debug Pipeline", menu_toggle_control, NULL, menu_check_control, (void*)"RenderDebugPipeline"); + item = new LLMenuItemCheckGL("Debug Pipeline", menu_toggle_control, nullptr, menu_check_control, (void*)"RenderDebugPipeline"); menu->addChild(item); - item = new LLMenuItemCheckGL("Automatic Alpha Masks (non-deferred)", menu_toggle_control, NULL, menu_check_control, (void*)"RenderAutoMaskAlphaNonDeferred"); + item = new LLMenuItemCheckGL("Automatic Alpha Masks (non-deferred)", menu_toggle_control, nullptr, menu_check_control, (void*)"RenderAutoMaskAlphaNonDeferred"); menu->addChild(item); - item = new LLMenuItemCheckGL("Automatic Alpha Masks (deferred)", menu_toggle_control, NULL, menu_check_control, (void*)"RenderAutoMaskAlphaDeferred"); + item = new LLMenuItemCheckGL("Automatic Alpha Masks (deferred)", menu_toggle_control, nullptr, menu_check_control, (void*)"RenderAutoMaskAlphaDeferred"); menu->addChild(item); - item = new LLMenuItemCheckGL("Aggressive Alpha Masking", menu_toggle_control, NULL, menu_check_control, (void*)"SHUseRMSEAutoMask"); + item = new LLMenuItemCheckGL("Aggressive Alpha Masking", menu_toggle_control, nullptr, menu_check_control, (void*)"SHUseRMSEAutoMask"); menu->addChild(item); - menu->addChild(new LLMenuItemCallGL("Rebuild Vertex Buffers", reset_vertex_buffers, NULL, NULL, 'V', MASK_CONTROL | MASK_SHIFT)); + menu->addChild(new LLMenuItemCallGL("Rebuild Vertex Buffers", reset_vertex_buffers, nullptr, nullptr, 'V', MASK_CONTROL | MASK_SHIFT)); - item = new LLMenuItemCheckGL("Animate Trees", menu_toggle_control, NULL, menu_check_control, (void*)"RenderAnimateTrees"); + item = new LLMenuItemCheckGL("Animate Trees", menu_toggle_control, nullptr, menu_check_control, (void*)"RenderAnimateTrees"); menu->addChild(item); - item = new LLMenuItemCheckGL("Animate Textures", menu_toggle_control, NULL, menu_check_control, (void*)"AnimateTextures"); + item = new LLMenuItemCheckGL("Animate Textures", menu_toggle_control, nullptr, menu_check_control, (void*)"AnimateTextures"); menu->addChild(item); - item = new LLMenuItemCheckGL("Disable Textures", menu_toggle_control, NULL, menu_check_control, (void*)"TextureDisable"); + item = new LLMenuItemCheckGL("Disable Textures", menu_toggle_control, nullptr, menu_check_control, (void*)"TextureDisable"); menu->addChild(item); - item = new LLMenuItemCheckGL("HTTP Get Textures", menu_toggle_control, NULL, menu_check_control, (void*)"ImagePipelineUseHTTP"); + item = new LLMenuItemCheckGL("HTTP Get Textures", menu_toggle_control, nullptr, menu_check_control, (void*)"ImagePipelineUseHTTP"); menu->addChild(item); - item = new LLMenuItemCheckGL("Run Multiple Threads", menu_toggle_control, NULL, menu_check_control, (void*)"RunMultipleThreads"); + item = new LLMenuItemCheckGL("Run Multiple Threads", menu_toggle_control, nullptr, menu_check_control, (void*)"RunMultipleThreads"); menu->addChild(item); - item = new LLMenuItemCheckGL("Cheesy Beacon", menu_toggle_control, NULL, menu_check_control, (void*)"CheesyBeacon"); + item = new LLMenuItemCheckGL("Cheesy Beacon", menu_toggle_control, nullptr, menu_check_control, (void*)"CheesyBeacon"); menu->addChild(item); - item = new LLMenuItemCheckGL("Attached Lights", menu_toggle_attached_lights, NULL, menu_check_control, (void*)"RenderAttachedLights"); + item = new LLMenuItemCheckGL("Attached Lights", menu_toggle_attached_lights, nullptr, menu_check_control, (void*)"RenderAttachedLights"); menu->addChild(item); - item = new LLMenuItemCheckGL("Attached Particles", menu_toggle_attached_particles, NULL, menu_check_control, (void*)"RenderAttachedParticles"); + item = new LLMenuItemCheckGL("Attached Particles", menu_toggle_attached_particles, nullptr, menu_check_control, (void*)"RenderAttachedParticles"); menu->addChild(item); - item = new LLMenuItemCheckGL("Audit Texture", menu_toggle_control, NULL, menu_check_control, (void*)"AuditTexture"); + item = new LLMenuItemCheckGL("Audit Texture", menu_toggle_control, nullptr, menu_check_control, (void*)"AuditTexture"); menu->addChild(item); menu->addSeparator(); - menu->addChild(new LLMenuItemCallGL("Memory Leaking Simulation", LLFloaterMemLeak::show, NULL, NULL)); + menu->addChild(new LLMenuItemCallGL("Memory Leaking Simulation", LLFloaterMemLeak::show, nullptr, nullptr)); menu->createJumpKeys(); } @@ -1475,13 +1505,13 @@ void init_debug_avatar_menu(LLMenuGL* menu) { LLMenuGL* sub_menu = new LLMenuGL("Character Tests"); sub_menu->setCanTearOff(TRUE); - sub_menu->addChild(new LLMenuItemCheckGL("Go Away/AFK When Idle", menu_toggle_control, NULL, menu_check_control, (void*)"AllowIdleAFK")); + sub_menu->addChild(new LLMenuItemCheckGL("Go Away/AFK When Idle", menu_toggle_control, nullptr, menu_check_control, (void*)"AllowIdleAFK")); sub_menu->addChild(new LLMenuItemCallGL("Appearance To XML", &handle_dump_archetype_xml)); // HACK for easy testing of avatar geometry sub_menu->addChild(new LLMenuItemCallGL( "Toggle Character Geometry", - &handle_god_request_avatar_geometry, &is_god_customer_service, NULL)); + &handle_god_request_avatar_geometry, &is_god_customer_service, nullptr)); sub_menu->addChild(new LLMenuItemCallGL("Test Male", handle_test_male)); @@ -1491,19 +1521,19 @@ void init_debug_avatar_menu(LLMenuGL* menu) sub_menu->addChild(new LLMenuItemCallGL("Toggle PG", handle_toggle_pg)); - sub_menu->addChild(new LLMenuItemCheckGL("Allow Select Avatar", menu_toggle_control, NULL, menu_check_control, (void*)"AllowSelectAvatar")); + sub_menu->addChild(new LLMenuItemCheckGL("Allow Select Avatar", menu_toggle_control, nullptr, menu_check_control, (void*)"AllowSelectAvatar")); sub_menu->createJumpKeys(); menu->addChild(sub_menu); - menu->addChild(new LLMenuItemCheckGL("Tap-Tap-Hold To Run", menu_toggle_control, NULL, menu_check_control, (void*)"AllowTapTapHoldRun")); - menu->addChild(new LLMenuItemCallGL("Force Params to Default", &LLAgent::clearVisualParams, NULL)); - menu->addChild(new LLMenuItemCallGL("Reload Vertex Shader", &reload_vertex_shader, NULL)); + menu->addChild(new LLMenuItemCheckGL("Tap-Tap-Hold To Run", menu_toggle_control, nullptr, menu_check_control, (void*)"AllowTapTapHoldRun")); + menu->addChild(new LLMenuItemCallGL("Force Params to Default", &LLAgent::clearVisualParams, nullptr)); + menu->addChild(new LLMenuItemCallGL("Reload Vertex Shader", &reload_vertex_shader, nullptr)); menu->addChild(new LLMenuItemToggleGL("Animation Info", &LLVOAvatar::sShowAnimationDebug)); - menu->addChild(new LLMenuItemCallGL("Slow Motion Animations", &slow_mo_animations, NULL)); + menu->addChild(new LLMenuItemCallGL("Slow Motion Animations", &slow_mo_animations, nullptr)); LLMenuItemCheckGL* item; - item = new LLMenuItemCheckGL("Show Look At", menu_toggle_control, NULL, menu_check_control, (void*)"AscentShowLookAt"); + item = new LLMenuItemCheckGL("Show Look At", menu_toggle_control, nullptr, menu_check_control, (void*)"AscentShowLookAt"); menu->addChild(item); menu->addChild(new LLMenuItemToggleGL("Show Point At", &LLHUDEffectPointAt::sDebugPointAt)); @@ -1514,27 +1544,27 @@ void init_debug_avatar_menu(LLMenuGL* menu) //diabling collision plane due to DEV-14477 -brad //menu->addChild(new LLMenuItemToggleGL("Show Collision Plane", &LLVOAvatar::sShowFootPlane)); menu->addChild(new LLMenuItemCheckGL("Show Collision Skeleton", - &LLPipeline::toggleRenderDebug, NULL, + &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_AVATAR_VOLUME)); menu->addChild(new LLMenuItemCheckGL("Show Avatar Joints", - &LLPipeline::toggleRenderDebug, NULL, + &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_AVATAR_JOINTS)); menu->addChild(new LLMenuItemCheckGL("Display Agent Target", - &LLPipeline::toggleRenderDebug, NULL, + &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_AGENT_TARGET)); menu->addChild(new LLMenuItemCheckGL("Attachment Bytes", - &LLPipeline::toggleRenderDebug, NULL, + &LLPipeline::toggleRenderDebug, nullptr, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES)); menu->addChild(new LLMenuItemToggleGL( "Debug Rotation", &LLVOAvatar::sDebugAvatarRotation)); menu->addChild(new LLMenuItemCallGL("Dump Attachments", handle_dump_attachments)); menu->addChild(new LLMenuItemCallGL("Rebake Textures", handle_rebake_textures)); #ifndef LL_RELEASE_FOR_DOWNLOAD - menu->addChild(new LLMenuItemCallGL("Debug Avatar Textures", handle_debug_avatar_textures, NULL, NULL, 'A', MASK_SHIFT|MASK_CONTROL|MASK_ALT)); - menu->addChild(new LLMenuItemCallGL("Dump Local Textures", handle_dump_avatar_local_textures, NULL, NULL, 'M', MASK_SHIFT|MASK_ALT )); + menu->addChild(new LLMenuItemCallGL("Debug Avatar Textures", handle_debug_avatar_textures, nullptr, nullptr, 'A', MASK_SHIFT|MASK_CONTROL|MASK_ALT)); + menu->addChild(new LLMenuItemCallGL("Dump Local Textures", handle_dump_avatar_local_textures, nullptr, nullptr, 'M', MASK_SHIFT|MASK_ALT )); #endif gMeshesAndMorphsMenu = new LLMenuGL("Meshes and Morphs"); @@ -1555,39 +1585,39 @@ void init_debug_rlva_menu(LLMenuGL* menu) pDbgMenu->setCanTearOff(TRUE); if (gSavedSettings.controlExists(RLV_SETTING_DEBUG)) - pDbgMenu->addChild(new LLMenuItemCheckGL("Show Debug Messages", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_DEBUG)); + pDbgMenu->addChild(new LLMenuItemCheckGL("Show Debug Messages", menu_toggle_control, nullptr, menu_check_control, (void*)RLV_SETTING_DEBUG)); pDbgMenu->addSeparator(); if (gSavedSettings.controlExists(RLV_SETTING_ENABLELEGACYNAMING)) - pDbgMenu->addChild(new LLMenuItemCheckGL("Enable Legacy Naming", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_ENABLELEGACYNAMING)); + pDbgMenu->addChild(new LLMenuItemCheckGL("Enable Legacy Naming", menu_toggle_control, nullptr, menu_check_control, (void*)RLV_SETTING_ENABLELEGACYNAMING)); if (gSavedSettings.controlExists(RLV_SETTING_SHAREDINVAUTORENAME)) - pDbgMenu->addChild(new LLMenuItemCheckGL("Rename Shared Items on Wear", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_SHAREDINVAUTORENAME)); + pDbgMenu->addChild(new LLMenuItemCheckGL("Rename Shared Items on Wear", menu_toggle_control, nullptr, menu_check_control, (void*)RLV_SETTING_SHAREDINVAUTORENAME)); menu->addChild(pDbgMenu); menu->addSeparator(); } if (gSavedSettings.controlExists(RLV_SETTING_ENABLESHAREDWEAR)) - menu->addChild(new LLMenuItemCheckGL("Enable Shared Wear", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_ENABLESHAREDWEAR)); + menu->addChild(new LLMenuItemCheckGL("Enable Shared Wear", menu_toggle_control, nullptr, menu_check_control, (void*)RLV_SETTING_ENABLESHAREDWEAR)); menu->addSeparator(); if ( (gSavedSettings.controlExists(RLV_SETTING_HIDELOCKEDLAYER)) && (gSavedSettings.controlExists(RLV_SETTING_HIDELOCKEDATTACH)) ) { - menu->addChild(new LLMenuItemCheckGL("Hide Locked Layers", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_HIDELOCKEDLAYER)); - menu->addChild(new LLMenuItemCheckGL("Hide Locked Attachments", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_HIDELOCKEDATTACH)); + menu->addChild(new LLMenuItemCheckGL("Hide Locked Layers", menu_toggle_control, nullptr, menu_check_control, (void*)RLV_SETTING_HIDELOCKEDLAYER)); + menu->addChild(new LLMenuItemCheckGL("Hide Locked Attachments", menu_toggle_control, nullptr, menu_check_control, (void*)RLV_SETTING_HIDELOCKEDATTACH)); //sub_menu->addChild(new LLMenuItemToggleGL("Hide locked inventory", &rlv_handler_t::fHideLockedInventory)); menu->addSeparator(); } if (gSavedSettings.controlExists(RLV_SETTING_FORBIDGIVETORLV)) - menu->addChild(new LLMenuItemCheckGL("Forbid Give to #RLV", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_FORBIDGIVETORLV)); + menu->addChild(new LLMenuItemCheckGL("Forbid Give to #RLV", menu_toggle_control, nullptr, menu_check_control, (void*)RLV_SETTING_FORBIDGIVETORLV)); if (gSavedSettings.controlExists(RLV_SETTING_ENABLELEGACYNAMING)) - menu->addChild(new LLMenuItemCheckGL("Show Name Tags", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_SHOWNAMETAGS)); + menu->addChild(new LLMenuItemCheckGL("Show Name Tags", menu_toggle_control, nullptr, menu_check_control, (void*)RLV_SETTING_SHOWNAMETAGS)); menu->addSeparator(); - menu->addChild(new LLMenuItemCheckGL("Restrictions...", &RlvFloaterBehaviours::toggle, NULL, &RlvFloaterBehaviours::visible, NULL)); - menu->addChild(new LLMenuItemCheckGL("Locks...", &RlvFloaterLocks::toggle, NULL, &RlvFloaterLocks::visible, NULL)); - menu->addChild(new LLMenuItemCheckGL("Strings...", &RlvFloaterStrings::toggle, NULL, &RlvFloaterStrings::visible, NULL)); + menu->addChild(new LLMenuItemCheckGL("Restrictions...", &RlvFloaterBehaviours::toggle, nullptr, &RlvFloaterBehaviours::visible, nullptr)); + menu->addChild(new LLMenuItemCheckGL("Locks...", &RlvFloaterLocks::toggle, nullptr, &RlvFloaterLocks::visible, nullptr)); + menu->addChild(new LLMenuItemCheckGL("Strings...", &RlvFloaterStrings::toggle, nullptr, &RlvFloaterStrings::visible, nullptr)); } // [/RLVa:KB] @@ -1598,18 +1628,18 @@ void init_server_menu(LLMenuGL* menu) menu->addChild(sub); sub->addChild(new LLMenuItemCallGL( "Take Copy", - &force_take_copy, &is_god_customer_service, NULL, + &force_take_copy, &is_god_customer_service, nullptr, 'O', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); #ifdef _CORY_TESTING sub->addChild(new LLMenuItemCallGL( "Export Copy", - &force_export_copy, NULL, NULL)); + &force_export_copy, nullptr, nullptr)); sub->addChild(new LLMenuItemCallGL( "Import Geometry", - &force_import_geometry, NULL, NULL)); + &force_import_geometry, nullptr, nullptr)); #endif //sub->addChild(new LLMenuItemCallGL( "Force Public", - // &handle_object_owner_none, NULL, NULL)); + // &handle_object_owner_none, nullptr, nullptr)); //sub->addChild(new LLMenuItemCallGL( "Force Ownership/Permissive", - // &handle_object_owner_self_and_permissive, NULL, NULL, 'K', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); + // &handle_object_owner_self_and_permissive, nullptr, nullptr, 'K', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); sub->addChild(new LLMenuItemCallGL( "Force Owner To Me", &handle_object_owner_self, &is_god_customer_service)); sub->addChild(new LLMenuItemCallGL( "Force Owner Permissive", @@ -1617,11 +1647,11 @@ void init_server_menu(LLMenuGL* menu) //sub->addChild(new LLMenuItemCallGL( "Force Totally Permissive", // &handle_object_permissive)); sub->addChild(new LLMenuItemCallGL( "Delete", - &handle_force_delete, &is_god_customer_service, NULL, KEY_DELETE, MASK_SHIFT | MASK_ALT | MASK_CONTROL)); + &handle_force_delete, &is_god_customer_service, nullptr, KEY_DELETE, MASK_SHIFT | MASK_ALT | MASK_CONTROL)); sub->addChild(new LLMenuItemCallGL( "Lock", - &handle_object_lock, &is_god_customer_service, NULL, 'L', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); + &handle_object_lock, &is_god_customer_service, nullptr, 'L', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); sub->addChild(new LLMenuItemCallGL( "Get Asset IDs", - &handle_object_asset_ids, &is_god_customer_service, NULL, 'I', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); + &handle_object_asset_ids, &is_god_customer_service, nullptr, 'I', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); sub->createJumpKeys(); } { @@ -1630,10 +1660,10 @@ void init_server_menu(LLMenuGL* menu) sub->addChild(new LLMenuItemCallGL("Owner To Me", &handle_force_parcel_owner_to_me, - &is_god_customer_service, NULL)); + &is_god_customer_service, nullptr)); sub->addChild(new LLMenuItemCallGL("Set to Linden Content", &handle_force_parcel_to_content, - &is_god_customer_service, NULL)); + &is_god_customer_service, nullptr)); sub->addSeparator(); sub->addChild(new LLMenuItemCallGL("Claim Public Land", &handle_claim_public_land, &is_god_customer_service)); @@ -1645,14 +1675,14 @@ void init_server_menu(LLMenuGL* menu) menu->addChild(sub); sub->addChild(new LLMenuItemCallGL("Dump Temp Asset Data", &handle_region_dump_temp_asset_data, - &is_god_customer_service, NULL)); + &is_god_customer_service, nullptr)); sub->createJumpKeys(); } menu->addChild(new LLMenuItemCallGL( "God Tools...", - &LLFloaterGodTools::show, &enable_god_basic, NULL)); + &LLFloaterGodTools::show, &enable_god_basic, nullptr)); { - LLMenuItemCallGL* item = new LLMenuItemCallGL("insert_admin", NULL); + LLMenuItemCallGL* item = new LLMenuItemCallGL("insert_admin", nullptr); item->setVisible(false); menu->addChild(item); } @@ -1660,7 +1690,7 @@ void init_server_menu(LLMenuGL* menu) menu->addSeparator(); menu->addChild(new LLMenuItemCallGL("Save Region State", - &LLPanelRegionTools::onSaveState, &is_god_customer_service, NULL)); + &LLPanelRegionTools::onSaveState, &is_god_customer_service, nullptr)); menu->createJumpKeys(); } @@ -1670,9 +1700,9 @@ void init_server_menu(LLMenuGL* menu) ////////////////////// /* -class LLAdvancedToggleWireframe : public view_listener_t +class LLAdvancedToggleWireframe final : public view_listener_t { - bool handleEvent(const LLSD& userdata) + bool handleEvent(const LLSD& userdata) override */ void advanced_toggle_wireframe(void*) { @@ -1686,15 +1716,17 @@ class LLAdvancedToggleWireframe : public view_listener_t // [/RLVa:KB] // gUseWireframe = !(gUseWireframe); // gWindowResized = TRUE; // Singu Note: We don't use this (yet?) + + LLPipeline::updateRenderDeferred(); gPipeline.resetVertexBuffers(); // return true; } /* }; -class LLAdvancedCheckWireframe : public view_listener_t +class LLAdvancedCheckWireframe final : public view_listener_t { - bool handleEvent(const LLSD& userdata) + bool handleEvent(const LLSD& userdata) override */ BOOL advanced_check_wireframe(void*) { @@ -1710,31 +1742,31 @@ class LLAdvancedCheckWireframe : public view_listener_t void cleanup_menus() { delete gMenuParcelObserver; - gMenuParcelObserver = NULL; + gMenuParcelObserver = nullptr; delete gPieSelf; - gPieSelf = NULL; + gPieSelf = nullptr; delete gPieAvatar; - gPieAvatar = NULL; + gPieAvatar = nullptr; delete gPieObject; - gPieObject = NULL; + gPieObject = nullptr; delete gPieAttachment; - gPieAttachment = NULL; + gPieAttachment = nullptr; delete gPieLand; - gPieLand = NULL; + gPieLand = nullptr; delete gMenuBarView; - gMenuBarView = NULL; + gMenuBarView = nullptr; - delete gPopupMenuView; - gPopupMenuView = NULL; + delete gLoginMenuBarView; + gLoginMenuBarView = nullptr; delete gMenuHolder; - gMenuHolder = NULL; + gMenuHolder = nullptr; sMenus.clear(); } @@ -1743,9 +1775,9 @@ void cleanup_menus() // Object pie menu //----------------------------------------------------------------------------- -class LLObjectReportAbuse : public view_listener_t +class LLObjectReportAbuse final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (objectp) @@ -1757,9 +1789,9 @@ class LLObjectReportAbuse : public view_listener_t }; // Enabled it you clicked an object -class LLObjectEnableReportAbuse : public view_listener_t +class LLObjectEnableReportAbuse final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0; gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -1767,25 +1799,22 @@ class LLObjectEnableReportAbuse : public view_listener_t } }; -class LLObjectTouch : public view_listener_t +class LLObjectTouch final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - handle_object_touch(); + handle_object_touch(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(), &LLToolPie::getInstance()->getPick()); return true; } }; -void handle_object_touch() +void handle_object_touch(LLViewerObject* object, const LLPickInfo* const pick) { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (!object) return; - LLPickInfo pick = LLToolPie::getInstance()->getPick(); - // [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Modified: RLVa-1.1.0l // NOTE: fallback code since we really shouldn't be getting an active selection if we can't touch this - if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canTouch(object, pick.mObjectOffset)) ) + if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canTouch(object, pick ? pick->mObjectOffset : LLVector3::zero)) ) { RLV_ASSERT(false); return; @@ -1795,28 +1824,30 @@ void handle_object_touch() // *NOTE: Hope the packets arrive safely and in order or else // there will be some problems. // *TODO: Just fix this bad assumption. - send_ObjectGrab_message(object, pick, LLVector3::zero); - send_ObjectDeGrab_message(object, pick); + send_ObjectGrab_message(object, true, pick); + send_ObjectGrab_message(object, false, pick); } - -bool enable_object_touch(const LLSD& userdata) +bool enable_object_touch(LLViewerObject* obj, const LLVector3& offset = LLVector3::zero) { - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - bool new_value = obj && obj->flagHandleTouch(); // [RLVa:KB] - Checked: 2010-11-12 (RLVa-1.2.1g) | Added: RLVa-1.2.1g - if ( (rlv_handler_t::isEnabled()) && (new_value) ) + if (new_value && rlv_handler_t::isEnabled()) { // RELEASE-RLVa: [RLVa-1.2.1] Make sure this stays in sync with handle_object_touch() - new_value = gRlvHandler.canTouch(obj, LLToolPie::getInstance()->getPick().mObjectOffset); + new_value = gRlvHandler.canTouch(obj, offset); } // [/RLVa:KB] + return new_value; +} +bool enable_object_touch(const LLSD& userdata) +{ std::string touch_text; // Update label based on the node touch name if available. - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); + auto selection = LLSelectMgr::getInstance()->getSelection(); + LLSelectNode* node = selection->getFirstRootNode(); if (node && node->mValid && !node->mTouchName.empty()) { touch_text = node->mTouchName; @@ -1828,13 +1859,14 @@ bool enable_object_touch(const LLSD& userdata) gMenuHolder->childSetText("Object Touch", touch_text); gMenuHolder->childSetText("Attachment Object Touch", touch_text); - return new_value; + + return enable_object_touch(selection->getPrimaryObject(), LLToolPie::getInstance()->getPick().mObjectOffset); }; // One object must have touch sensor -class LLObjectEnableTouch : public view_listener_t +class LLObjectEnableTouch final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_object_touch(userdata)); return true; @@ -1863,9 +1895,9 @@ void handle_object_open() // LLFloaterOpenObject::show(); } -class LLObjectOpen : public view_listener_t +class LLObjectOpen final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { handle_object_open(); return true; @@ -1885,9 +1917,9 @@ bool enable_object_open() return root->allowOpen(); } -class LLObjectEnableOpen : public view_listener_t +class LLObjectEnableOpen final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_object_open()); @@ -1895,18 +1927,18 @@ class LLObjectEnableOpen : public view_listener_t } }; -class LLViewJoystickFlycam : public view_listener_t +class LLViewJoystickFlycam final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { handle_toggle_flycam(); return true; } }; -class LLViewCheckJoystickFlycam : public view_listener_t +class LLViewCheckJoystickFlycam final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLViewerJoystick::getInstance()->getOverrideCamera(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -1920,9 +1952,9 @@ void handle_toggle_flycam() LLViewerJoystick::getInstance()->toggleFlycam(); } -class LLObjectBuild : public view_listener_t +class LLObjectBuild final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") ) { @@ -1962,7 +1994,7 @@ void handle_object_edit() { LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); RlvSelectIsEditable f; - if ((hSel.notNull()) && ((hSel->getFirstRootNode(&f, TRUE)) != NULL)) + if ((hSel.notNull()) && ((hSel->getFirstRootNode(&f, TRUE)) != nullptr)) return; // Can't edit any object under @edit=n } else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && @@ -2014,9 +2046,9 @@ void handle_object_edit() return; } -class LLObjectEdit : public view_listener_t +class LLObjectEdit final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { handle_object_edit(); return true; @@ -2041,85 +2073,94 @@ void handle_attachment_edit(const LLUUID& idItem) } // [/SL:KB] +bool add_object_to_blacklist( const LLUUID& id, const std::string& entry_name ) +{ + // ...don't kill the avatar + if (id != gAgentID) + { + LLSD indata; + indata["entry_type"] = LLAssetType::AT_OBJECT; + indata["entry_name"] = entry_name; + indata["entry_agent"] = gAgentID; + + LLFloaterBlacklist::addEntry(id, indata); + LLViewerObject *objectp = gObjectList.findObject(id); + if (objectp) + { + gObjectList.killObject(objectp); + } + return true; + } + return false; +} + // Derenderizer. Originally by Phox. -class LLObjectDerender : public view_listener_t +class LLObjectDerender final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerObject* slct = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if(!slct)return true; LLUUID id = slct->getID(); - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - LLUUID root_key; - //delivers null in linked parts if used as getFirstRootNode() - LLSelectNode* node = selection->getFirstRootNode(NULL,TRUE); - /*this works for derendering entire object if child is selected - - LLSelectNode* node = selection->getFirstNode(); - //Delivers node even when linked parts, but only first node - - LLViewerObject* obj = node->getObject(); - LLViewerObject* parent = (LLViewerObject*)obj->getParent();*/ - - if(node) - { - root_key = node->getObject()->getID(); - LL_INFOS() << "Derender node has key " << root_key << LL_ENDL; - } - else - { - LL_INFOS() << "Derender node is null " << LL_ENDL; - } - - LLViewerRegion* cur_region = gAgent.getRegion(); + bool added = false; std::string entry_name; if (slct->isAvatar()) { LLNameValue* firstname = slct->getNVPair("FirstName"); LLNameValue* lastname = slct->getNVPair("LastName"); entry_name = llformat("Derendered: (AV) %s %s",firstname->getString(),lastname->getString()); + added |= add_object_to_blacklist(id, entry_name); } else { - if (root_key.isNull()) + LLViewerRegion* cur_region = gAgent.getRegion(); + + std::list nodes; + for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) { - return true; + nodes.push_back(*iter); } - id = root_key; - if (!node->mName.empty()) + if (nodes.empty()) { - if(cur_region) - entry_name = llformat("Derendered: %s in region %s",node->mName.c_str(),cur_region->getName().c_str()); - else - entry_name = llformat("Derendered: %s",node->mName.c_str()); + nodes.push_back(LLSelectMgr::getInstance()->getSelection()->getFirstNode()); } - else + + for( auto node : nodes ) { - if(cur_region) - entry_name = llformat("Derendered: (unknown object) in region %s",cur_region->getName().c_str()); + if (node) + { + id = node->getObject()->getID(); + } + if (id.isNull()) + { + continue; + } + LL_INFOS() << "Derender node has key " << id << LL_ENDL; + if (!node->mName.empty()) + { + if (cur_region) + entry_name = llformat("Derendered: %s in region %s", node->mName.c_str(), cur_region->getName().c_str()); + else + entry_name = llformat("Derendered: %s", node->mName.c_str()); + } else - entry_name = "Derendered: (unknown object)"; + { + if (cur_region) + entry_name = llformat("Derendered: (unknown object) in region %s", cur_region->getName().c_str()); + else + entry_name = "Derendered: (unknown object)"; + } + added |= add_object_to_blacklist(id, entry_name); } } - // ...don't kill the avatar - if (id != gAgentID) + if (added) { - LLSD indata; - indata["entry_type"] = 6; //AT_TEXTURE - indata["entry_name"] = entry_name; - indata["entry_agent"] = gAgentID; - - LLFloaterBlacklist::addEntry(id,indata); LLSelectMgr::getInstance()->deselectAll(); - LLViewerObject *objectp = gObjectList.findObject(id); - if (objectp) - { - gObjectList.killObject(objectp); - } } return true; } @@ -2138,12 +2179,12 @@ class LLTextureReloader { LLAppViewer::getTextureCache()->removeFromCache(id); img->forceRefetch(); - for (S32 i = 0; i < img->getNumVolumes(); ++i) + for (S32 i = 0; i < img->getNumVolumes(LLRender::SCULPT_TEX); ++i) { - LLVOVolume* volume = (*(img->getVolumeList()))[i]; + LLVOVolume* volume = (*(img->getVolumeList(LLRender::SCULPT_TEX)))[i]; if (volume && volume->isSculpted()) { - LLSculptParams *sculpt_params = (LLSculptParams *)volume->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = volume->getSculptParams(); if(sculpt_params->getSculptTexture() == id) volume->notifyMeshLoaded(); } @@ -2180,7 +2221,7 @@ void reload_objects(LLTextureReloader& texture_list, LLViewerObject::const_child if(object->isSculpted() && !object->isMesh()) { - LLSculptParams *sculpt_params = (LLSculptParams *)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = object->getSculptParams(); if(sculpt_params) { texture_list.addTexture(LLViewerTextureManager::getFetchedTexture(sculpt_params->getSculptTexture())); @@ -2191,7 +2232,7 @@ void reload_objects(LLTextureReloader& texture_list, LLViewerObject::const_child { texture_list.addTexture(object->getTEImage(i)); const LLTextureEntry* te = object->getTE(i); - if (LLMaterial* mat = te ? te->getMaterialParams().get() : NULL) + if (LLMaterial* mat = te ? te->getMaterialParams().get() : nullptr) { if (mat->getSpecularID().notNull()) texture_list.addTexture(LLViewerTextureManager::getFetchedTexture(mat->getSpecularID())); @@ -2208,9 +2249,9 @@ void reload_objects(LLTextureReloader& texture_list, LLViewerObject::const_child } } -class LLAvatarReloadTextures : public view_listener_t +class LLAvatarReloadTextures final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if(avatar) @@ -2241,9 +2282,9 @@ class LLAvatarReloadTextures : public view_listener_t return true; } }; -class LLObjectReloadTextures : public view_listener_t +class LLObjectReloadTextures final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerObject::vobj_list_t object_list; @@ -2263,9 +2304,9 @@ class LLObjectReloadTextures : public view_listener_t //--------------------------------------------------------------------------- // Land pie menu //--------------------------------------------------------------------------- -class LLLandBuild : public view_listener_t +class LLLandBuild final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerParcelMgr::getInstance()->deselectLand(); @@ -2295,20 +2336,20 @@ class LLLandBuild : public view_listener_t } }; -class LLLandBuyPass : public view_listener_t +class LLLandBuyPass final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLPanelLandGeneral::onClickBuyPass((void *)FALSE); return true; } }; -class LLLandEnableBuyPass : public view_listener_t +class LLLandEnableBuyPass final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - bool new_value = LLPanelLandGeneral::enableBuyPass(NULL); + bool new_value = LLPanelLandGeneral::enableBuyPass(nullptr); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -2369,16 +2410,16 @@ bool enable_object_edit() { LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); RlvSelectIsEditable f; - enable = (hSel.notNull()) && ((hSel->getFirstRootNode(&f, TRUE)) == NULL); + enable = (hSel.notNull()) && ((hSel->getFirstRootNode(&f, TRUE)) == nullptr); // [/RLVa:KB] } return enable; } -class LLEnableEdit : public view_listener_t +class LLEnableEdit final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_object_edit()); return true; @@ -2391,17 +2432,17 @@ bool enable_object_select_in_pathfinding_linksets() return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetEditableLinksets(); } -class LLObjectEnablePFLinksetsSelected : public view_listener_t +class LLObjectEnablePFLinksetsSelected final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { return enable_object_select_in_pathfinding_linksets(); } }; -class LLObjectPFCharactersSelected : public view_listener_t +class LLObjectPFCharactersSelected final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects(); return true; @@ -2413,26 +2454,26 @@ bool enable_object_select_in_pathfinding_characters() return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters(); } -class LLObjectEnablePFCharactersSelected : public view_listener_t +class LLObjectEnablePFCharactersSelected final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { return enable_object_select_in_pathfinding_characters(); } }; -class LLSelfRemoveAllAttachments : public view_listener_t +class LLSelfRemoveAllAttachments final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLAppearanceMgr::instance().removeAllAttachmentsFromAvatar(); return true; } }; -class LLSelfEnableRemoveAllAttachments : public view_listener_t +class LLSelfEnableRemoveAllAttachments final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = false; if (isAgentAvatarValid()) @@ -2457,9 +2498,9 @@ class LLSelfEnableRemoveAllAttachments : public view_listener_t } }; -class LLSelfVisibleScriptInfo : public view_listener_t +class LLSelfVisibleScriptInfo final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if (LLViewerRegion* region = gAgent.getRegion()) gMenuHolder->findControl(userdata["control"].asString())->setValue(!region->getCapability("AttachmentResources").empty()); @@ -2476,15 +2517,22 @@ BOOL enable_has_attachments(void*) //--------------------------------------------------------------------------- // Avatar pie menu //--------------------------------------------------------------------------- -//void handle_follow(void *userdata) -//{ -// // follow a given avatar by ID -// LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); -// if (objectp) -// { -// gAgent.startFollowPilot(objectp->getID()); -// } -//} + +class LLObjectFollow final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + // follow a given avatar by ID + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (objectp) + { + if (auto av = objectp->getAvatarAncestor()) // Follow the avatar, not a control avatar or an attachment, if possible + objectp = av; + gAgent.startFollowPilot(objectp->getID(), true, gSavedSettings.getF32("SinguFollowDistance")); + } + return true; + } +}; bool enable_object_mute() { @@ -2511,18 +2559,18 @@ bool enable_object_mute() } } -class LLObjectEnableMute : public view_listener_t +class LLObjectEnableMute final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_object_mute()); return true; } }; -class LLObjectMute : public view_listener_t +class LLObjectMute final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (!object) return true; @@ -2572,7 +2620,7 @@ class LLObjectMute : public view_listener_t else { LLMuteList::getInstance()->add(mute); - LLFloaterMute::showInstance(); + LLFloaterMute::showInstance()->selectMute(mute.mID);; } return true; @@ -2580,20 +2628,20 @@ class LLObjectMute : public view_listener_t }; // -class LLObjectEnableCopyUUID : public view_listener_t +class LLObjectEnableCopyUUID final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - bool new_value = (object != NULL); + bool new_value = (object != nullptr); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } }; -class LLObjectCopyUUID : public view_listener_t +class LLObjectCopyUUID final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if(object) @@ -2604,9 +2652,9 @@ class LLObjectCopyUUID : public view_listener_t } }; -class LLObjectData : public view_listener_t +class LLObjectData final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if(object) @@ -2633,9 +2681,19 @@ class LLObjectData : public view_listener_t } }; -class LLCanIHasKillEmAll : public view_listener_t +class LLSyncAnimations final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + void resync_anims(); + resync_anims(); + return false; + } +}; + +class LLCanIHasKillEmAll final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerObject* objpos = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); bool new_value = false; @@ -2651,9 +2709,9 @@ class LLCanIHasKillEmAll : public view_listener_t } }; -class LLOHGOD : public view_listener_t +class LLOHGOD final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerObject* objpos = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); bool new_value = false; @@ -2670,9 +2728,9 @@ class LLOHGOD : public view_listener_t } }; -class LLPowerfulWizard : public view_listener_t +class LLPowerfulWizard final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerObject* objpos = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); if(objpos) @@ -2706,9 +2764,9 @@ class LLPowerfulWizard : public view_listener_t } }; -class LLKillEmAll : public view_listener_t +class LLKillEmAll final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // Originally by SimmanFederal // Moved here by a big fat fuckin dog. @@ -2748,9 +2806,9 @@ class LLKillEmAll : public view_listener_t } }; -class LLObjectMeasure : public view_listener_t +class LLObjectMeasure final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { static LLVector3 startMeasurePoint = LLVector3::zero; static bool startpoint_set = false; @@ -2777,7 +2835,7 @@ class LLObjectMeasure : public view_listener_t LLFloaterChat::addChat(chat); LLStringUtil::format_map_t args; - args["[DIST]"] = boost::lexical_cast(dist_vec(startMeasurePoint, position)); + args["[DIST]"] = fmt::to_string(dist_vec(startMeasurePoint, position)); chat.mText = LLTrans::getString("MeasuredDistance", args); startpoint_set = false; @@ -2787,9 +2845,9 @@ class LLObjectMeasure : public view_listener_t } }; -class LLObjectPFLinksetsSelected : public view_listener_t +class LLObjectPFLinksetsSelected final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLFloaterPathfindingLinksets::openLinksetsWithSelectedObjects(); return true; @@ -2798,12 +2856,10 @@ class LLObjectPFLinksetsSelected : public view_listener_t // -bool handle_go_to() +void simulator_autopilot(const LLVector3d& pos) { - // try simulator autopilot std::vector strings; std::string val; - LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal; val = llformat("%.9g", pos.mdV[VX]); strings.push_back(val); val = llformat("%.9g", pos.mdV[VY]); @@ -2811,6 +2867,14 @@ bool handle_go_to() val = llformat("%.9g", pos.mdV[VZ]); strings.push_back(val); send_generic_message("autopilot", strings); +} + +void handle_go_to(const LLVector3d& pos) +{ + gAgent.stopAutoPilot(true); // Go To cancels viewer autopilot + + // try simulator autopilot + simulator_autopilot(pos); LLViewerParcelMgr::getInstance()->deselectLand(); @@ -2829,20 +2893,20 @@ bool handle_go_to() // Could be first use LLFirstUse::useGoTo(); - return true; } -class LLGoToObject : public view_listener_t +class LLGoToObject final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - return handle_go_to(); + handle_go_to(LLToolPie::instance().getPick().mPosGlobal); + return true; } }; -class LLAvatarReportAbuse : public view_listener_t +class LLAvatarReportAbuse final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if(avatar) @@ -2857,9 +2921,9 @@ class LLAvatarReportAbuse : public view_listener_t // Object backup //--------------------------------------------------------------------------- -class LLObjectEnableExport : public view_listener_t +class LLObjectEnableExport final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { ExportPolicy export_policy = LFSimFeatureHandler::instance().exportPolicy(); bool can_export_any = false; @@ -2877,36 +2941,36 @@ class LLObjectEnableExport : public view_listener_t } }; -class LLObjectExport : public view_listener_t +class LLObjectExport final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLObjectBackup::getInstance()->exportObject(); return true; } }; -class LLObjectEnableImport : public view_listener_t +class LLObjectEnableImport final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(TRUE); return true; } }; -class LLObjectImport : public view_listener_t +class LLObjectImport final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLObjectBackup::getInstance()->importObject(FALSE); return true; } }; -class LLObjectImportUpload : public view_listener_t +class LLObjectImportUpload final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLObjectBackup::getInstance()->importObject(TRUE); return true; @@ -2933,7 +2997,7 @@ bool callback_freeze(const LLSD& notification, const LLSD& response) void handle_avatar_freeze(const LLSD& avatar_id) { // Use avatar_id if available, otherwise default to right-click avatar - LLVOAvatar* avatar = NULL; + LLVOAvatar* avatar = nullptr; if (avatar_id.asUUID().notNull()) { avatar = find_avatar_from_object(avatar_id.asUUID()); @@ -2972,75 +3036,74 @@ void handle_avatar_freeze(const LLSD& avatar_id) } } -class LLAvatarFreeze : public view_listener_t +class LLAvatarFreeze final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { handle_avatar_freeze(LLUUID::null); return true; } }; -class LLScriptCount : public view_listener_t +void do_script_count(bool del, LLViewerObject* object = nullptr) { - bool handleEvent(LLPointer event, const LLSD& userdata) + if (object || (object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())) { - if (LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()) - { - if (ScriptCounter::getInstance(object->getID())) return true; - ScriptCounter* sc = new ScriptCounter(false, object); - sc->requestInventories(); - // sc will destroy itself - } + if (ScriptCounter::getInstance(object->getID())) return; + ScriptCounter* sc = new ScriptCounter(del, object); + sc->requestInventories(); + // sc will destroy itself + } +} + +class LLScriptCount final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + do_script_count(false, userdata["data"].asString() == "agent" ? gAgentAvatarp : nullptr); return true; } }; -class LLScriptDelete : public view_listener_t +class LLScriptDelete final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - if (LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()) - { - if (ScriptCounter::getInstance(object->getID())) return true; - ScriptCounter* sc = new ScriptCounter(true, object); - sc->requestInventories(); - // sc will destroy itself - } + do_script_count(true); return true; } }; -class LLObjectVisibleScriptCount : public view_listener_t +class LLObjectVisibleScriptCount final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - bool new_value = (object != NULL); + LLViewerObject* object = userdata["data"].asString() == "agent" ? gAgentAvatarp : LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + bool new_value = (object != nullptr); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } }; -class LLObjectEnableScriptDelete : public view_listener_t +class LLObjectEnableScriptDelete final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - bool new_value = (object != NULL); + auto objects = LLSelectMgr::getInstance()->getSelection(); + LLViewerObject* object = objects->getPrimaryObject(); + bool new_value = (object != nullptr); if(new_value) - for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); - iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) + for (LLObjectSelection::root_iterator iter = objects->root_begin(); + iter != objects->root_end(); iter++) { LLSelectNode* selectNode = *iter; LLViewerObject* object = selectNode->getObject(); - if(object) - if(!object->permModify()) - { - new_value=false; - break; - } + if (object && !object->permModify()) + { + new_value=false; + break; + } } gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -3048,18 +3111,18 @@ class LLObjectEnableScriptDelete : public view_listener_t } }; -class LLAvatarVisibleDebug : public view_listener_t +class LLAvatarVisibleDebug final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(gAgent.isGodlike()); return true; } }; -class LLAvatarDebug : public view_listener_t +class LLAvatarDebug final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if (isAgentAvatarValid()) { @@ -3127,7 +3190,7 @@ bool callback_eject(const LLSD& notification, const LLSD& response) void handle_avatar_eject(const LLSD& avatar_id) { // Use avatar_id if available, otherwise default to right-click avatar - LLVOAvatar* avatar = NULL; + LLVOAvatar* avatar = nullptr; if (avatar_id.asUUID().notNull()) { avatar = find_avatar_from_object(avatar_id.asUUID()); @@ -3196,9 +3259,9 @@ void handle_avatar_eject(const LLSD& avatar_id) } } -class LLAvatarEject : public view_listener_t +class LLAvatarEject final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { handle_avatar_eject(LLUUID::null); return true; @@ -3206,9 +3269,9 @@ class LLAvatarEject : public view_listener_t }; -class LLAvatarCopyUUID : public view_listener_t +class LLAvatarCopyUUID final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if(!avatar) return true; @@ -3218,9 +3281,9 @@ class LLAvatarCopyUUID : public view_listener_t } }; -class LLAvatarClientUUID : public view_listener_t +class LLAvatarClientUUID final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if(!avatar) return true; @@ -3233,7 +3296,7 @@ class LLAvatarClientUUID : public view_listener_t bool enable_freeze_eject(const LLSD& avatar_id) { // Use avatar_id if available, otherwise default to right-click avatar - LLVOAvatar* avatar = NULL; + LLVOAvatar* avatar = nullptr; if (avatar_id.asUUID().notNull()) { avatar = find_avatar_from_object(avatar_id.asUUID()); @@ -3264,18 +3327,18 @@ bool enable_freeze_eject(const LLSD& avatar_id) return new_value; } -class LLAvatarEnableFreezeEject : public view_listener_t +class LLAvatarEnableFreezeEject final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_freeze_eject(LLUUID::null)); return true; } }; -class LLAvatarGiveCard : public view_listener_t +class LLAvatarGiveCard final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LL_INFOS() << "handle_give_card()" << LL_ENDL; LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); @@ -3374,7 +3437,7 @@ bool enable_buy_object() // In order to buy, there must only be 1 purchaseable object in // the selection manager. if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return false; - LLViewerObject* obj = NULL; + LLViewerObject* obj = nullptr; LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if(node) { @@ -3393,9 +3456,9 @@ bool enable_buy_object() } -class LLObjectEnableBuy : public view_listener_t +class LLObjectEnableBuy final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = enable_buy_object(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -3516,10 +3579,11 @@ void handle_dump_focus(void *) LL_INFOS() << "Keyboard focus " << (ctrl ? ctrl->getName() : "(none)") << LL_ENDL; } -class LLSelfSitOrStand : public view_listener_t +class LLSelfSitOrStand final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { + gAgent.stopAutoPilot(true); if (gAgentAvatarp && gAgentAvatarp->isSitting()) { gAgent.standUp(); @@ -3551,9 +3615,9 @@ bool enable_sitdown_self() // return isAgentAvatarValid() && !gAgentAvatarp->isSitting() && !gAgent.getFlying(); } -class LLSelfEnableSitOrStand : public view_listener_t +class LLSelfEnableSitOrStand final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { std::string label; std::string sit_text; @@ -3690,7 +3754,7 @@ void handle_fake_away_status(void*) // /* -class LLHaveCallingcard : public LLInventoryCollectFunctor +class LLHaveCallingcard final : public LLInventoryCollectFunctor { public: LLHaveCallingcard(const LLUUID& agent_id); @@ -3736,9 +3800,9 @@ BOOL is_agent_mappable(const LLUUID& agent_id) // Enable a menu item when you don't have someone's card. -class LLAvatarEnableAddFriend : public view_listener_t +class LLAvatarEnableAddFriend final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); // bool new_value = avatar && !LLAvatarActions::isFriend(avatar->getID()); @@ -3775,9 +3839,9 @@ void request_friendship(const LLUUID& dest_id) } -class LLEditEnableCustomizeAvatar : public view_listener_t +class LLEditEnableCustomizeAvatar final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = (gAgentAvatarp && gAgentAvatarp->isFullyLoaded() && @@ -3788,9 +3852,9 @@ class LLEditEnableCustomizeAvatar : public view_listener_t }; -class LLEditEnableChangeDisplayname : public view_listener_t +class LLEditEnableChangeDisplayname final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(LLAvatarName::useDisplayNames()); return true; @@ -3822,28 +3886,14 @@ bool is_object_sittable() } -// only works on pie menu -void handle_object_sit_or_stand() +void handle_object_sit(LLViewerObject* object, const LLVector3& offset = LLVector3::zero) { - LLPickInfo pick = LLToolPie::getInstance()->getPick(); - LLViewerObject *object = pick.getObject();; - if (!object || pick.mPickType == LLPickInfo::PICK_FLORA) - { - return; - } - - if (sitting_on_selection()) - { - gAgent.standUp(); - return; - } - // get object selection offset // if (object && object->getPCode() == LL_PCODE_VOLUME) // [RLVa:KB] - Checked: 2010-03-06 (RLVa-1.2.0c) | Modified: RLVa-1.2.0c if ( (object && object->getPCode() == LL_PCODE_VOLUME) && - ((!rlv_handler_t::isEnabled()) || (gRlvHandler.canSit(object, pick.mObjectOffset))) ) + ((!rlv_handler_t::isEnabled()) || (gRlvHandler.canSit(object, offset))) ) // [/RLVa:KB] { // [RLVa:KB] - Checked: 2010-08-29 (RLVa-1.2.1c) | Added: RLVa-1.2.1c @@ -3864,15 +3914,36 @@ void handle_object_sit_or_stand() gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); gMessageSystem->nextBlockFast(_PREHASH_TargetObject); gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID); - gMessageSystem->addVector3Fast(_PREHASH_Offset, pick.mObjectOffset); + gMessageSystem->addVector3Fast(_PREHASH_Offset, offset); object->getRegion()->sendReliableMessage(); } } -class LLObjectSitOrStand : public view_listener_t +// only works on pie menu +void handle_object_sit_or_stand() +{ + LLPickInfo pick = LLToolPie::getInstance()->getPick(); + LLViewerObject *object = pick.getObject();; + if (!object || pick.mPickType == LLPickInfo::PICK_FLORA) + { + return; + } + + gAgent.stopAutoPilot(true); + + if (sitting_on_selection()) + { + gAgent.standUp(); + return; + } + + handle_object_sit(object, pick.mObjectOffset); +} + +class LLObjectSitOrStand final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { handle_object_sit_or_stand(); return true; @@ -3892,9 +3963,9 @@ void near_sit_down_point(BOOL success, void *) } } -class LLLandSit : public view_listener_t +class LLLandSit final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.2.1f if ( (rlv_handler_t::isEnabled()) && ((!RlvActions::canStand()) || (gRlvHandler.hasBehaviour(RLV_BHVR_SIT))) ) @@ -3915,33 +3986,33 @@ class LLLandSit : public view_listener_t { target_rot = gAgent.getFrameAgent().getQuaternion(); } - gAgent.startAutoPilotGlobal(posGlobal, "Sit", &target_rot, near_sit_down_point, NULL, 0.7f); + gAgent.startAutoPilotGlobal(posGlobal, "Sit", &target_rot, near_sit_down_point, nullptr, 0.7f); return true; } }; -class LLCreateLandmarkCallback : public LLInventoryCallback +class LLCreateLandmarkCallback final : public LLInventoryCallback { public: - /*virtual*/ void fire(const LLUUID& inv_item) + void fire(const LLUUID& inv_item) override { LL_INFOS() << "Created landmark with inventory id " << inv_item << LL_ENDL; } }; -class LLWorldFly : public view_listener_t +class LLWorldFly final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gAgent.toggleFlying(); return true; } }; -class LLWorldEnableFly : public view_listener_t +class LLWorldEnableFly final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(gAgent.enableFlying()); return true; @@ -4024,13 +4095,18 @@ void handle_reset_view() } else { + if (gAgent.getAutoPilot()) + { + gAgent.stopAutoPilot(true); + } + reset_view_final( true ); } } -class LLViewResetView : public view_listener_t +class LLViewResetView final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { handle_reset_view(); return true; @@ -4065,43 +4141,44 @@ void reset_view_final( BOOL proceed ) } gAgentCamera.resetView(TRUE, TRUE); gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); - gSavedSettings.setBOOL("SinguMotionResetsCamera", true); + if (gSavedSettings.getBOOL("SinguMotionResetsCameraReset")) + gSavedSettings.setBOOL("SinguMotionResetsCamera", true); if(gAgentCamera.cameraCustomizeAvatar() && LLFloaterCustomize::instanceExists()) LLFloaterCustomize::getInstance()->close(); } -class LLViewResetPresetAngles : public view_listener_t +class LLViewResetPresetAngles final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gAgentCamera.resetPresetOffsets(); return true; } }; -class LLViewLookAtLastChatter : public view_listener_t +class LLViewLookAtLastChatter final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gAgentCamera.lookAtLastChat(); return true; } }; -class LLViewFullscreen : public view_listener_t +class LLViewFullscreen final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gViewerWindow->toggleFullscreen(TRUE); return true; } }; -class LLViewDefaultUISize : public view_listener_t +class LLViewDefaultUISize final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gSavedSettings.setF32("UIScaleFactor", 1.0f); gSavedSettings.setBOOL("UIAutoScale", FALSE); @@ -4110,9 +4187,9 @@ class LLViewDefaultUISize : public view_listener_t } }; -class LLEditDuplicate : public view_listener_t +class LLEditDuplicate final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) && @@ -4130,9 +4207,9 @@ class LLEditDuplicate : public view_listener_t } }; -class LLEditEnableDuplicate : public view_listener_t +class LLEditEnableDuplicate final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDuplicate(); // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) @@ -4309,7 +4386,6 @@ void handle_claim_public_land(void*) void handle_dump_archetype_xml(void *) { - std::string emptyname; LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if (!avatar) @@ -4412,7 +4488,10 @@ static bool get_derezzable_objects( break; case DRD_RETURN_TO_OWNER: - can_derez_current = TRUE; + if(!object->isAttachment()) + { + can_derez_current = TRUE; + } break; default: @@ -4443,9 +4522,9 @@ static bool get_derezzable_objects( static bool can_derez(EDeRezDestination dest) { - LLViewerRegion* first_region = NULL; + LLViewerRegion* first_region = nullptr; std::string error; - return get_derezzable_objects(dest, error, first_region, NULL, true); + return get_derezzable_objects(dest, error, first_region, nullptr, true); } static void derez_objects( @@ -4520,17 +4599,13 @@ static void derez_objects( LLViewerObject* object = objectsp->at(object_index++); msg->nextBlockFast(_PREHASH_ObjectData); msg->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); - // if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) { - // // VEFFECT: DerezObject LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); effectp->setPositionGlobal(object->getPositionGlobal()); effectp->setColor(LLColor4U(gAgent.getEffectColor())); - // } - // } msg->sendReliable(first_region->getHost()); } @@ -4551,14 +4626,14 @@ static void derez_objects( static void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) { - LLViewerRegion* first_region = NULL; + LLViewerRegion* first_region = nullptr; std::string error; - derez_objects(dest, dest_id, first_region, error, NULL); + derez_objects(dest, dest_id, first_region, error, nullptr); } -class LLToolsTakeCopy : public view_listener_t +class LLToolsTakeCopy final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { handle_take_copy(); return true; @@ -4575,7 +4650,7 @@ void handle_take_copy() // Allow only if the avie isn't sitting on any of the selected objects LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); RlvSelectIsSittingOn f(gAgentAvatarp); - if ( (hSel.notNull()) && (hSel->getFirstRootNode(&f, TRUE) != NULL) ) + if ( (hSel.notNull()) && (hSel->getFirstRootNode(&f, TRUE) != nullptr) ) return; } // [/RLVa:KB] @@ -4585,13 +4660,13 @@ void handle_take_copy() } // You can return an object to its owner if it is on your land. -class LLObjectReturn : public view_listener_t +class LLObjectReturn final : public view_listener_t { public: - LLObjectReturn() : mFirstRegion(NULL) {} + LLObjectReturn() : mFirstRegion(nullptr) {} private: - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; // [RLVa:KB] - Checked: 2010-03-24 (RLVa-1.4.0a) | Modified: RLVa-1.0.0b @@ -4618,10 +4693,10 @@ class LLObjectReturn : public view_listener_t mReturnableObjects.clear(); mError.clear(); - mFirstRegion = NULL; + mFirstRegion = nullptr; // drop reference to current selection - mObjectSelection = NULL; + mObjectSelection = nullptr; return false; } @@ -4635,9 +4710,9 @@ class LLObjectReturn : public view_listener_t // Allow return to owner if one or more of the selected items is // over land you own. -class LLObjectEnableReturn : public view_listener_t +class LLObjectEnableReturn final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) { @@ -4729,7 +4804,7 @@ void handle_take() // such a location and it is not in the trash or library if(!gInventory.getCategory(category_id)) { - // nope, set to NULL. + // nope, set to nullptr. category_id.setNull(); } if(category_id.notNull()) @@ -4870,9 +4945,9 @@ void handle_buy_or_take() } } -class LLToolsBuyOrTake : public view_listener_t +class LLToolsBuyOrTake final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { handle_buy_or_take(); return true; @@ -4884,9 +4959,9 @@ bool visible_take_object() return !is_selection_buy_not_take() && enable_take(); } -class LLToolsEnableBuyOrTake : public view_listener_t +class LLToolsEnableBuyOrTake final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool is_buy = is_selection_buy_not_take(); bool new_value = is_buy ? enable_buy_object() : enable_take(); @@ -4987,14 +5062,14 @@ void show_buy_currency(const char* extra) // Don't show currency web page for branded clients. std::ostringstream mesg; - if (extra != NULL) + if (extra != nullptr) { mesg << extra << "\n \n"; } mesg << "Go to " << BUY_CURRENCY_URL << "\nfor information on purchasing currency?"; LLSD args; - if (extra != NULL) + if (extra != nullptr) { args["EXTRA"] = extra; } @@ -5020,9 +5095,9 @@ void handle_buy() } } -class LLObjectBuy : public view_listener_t +class LLObjectBuy final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { handle_buy(); return true; @@ -5069,11 +5144,12 @@ BOOL sitting_on_selection() return (gAgentAvatarp->isSitting() && gAgentAvatarp->getRoot() == root_object); } -class LLToolsSaveToInventory : public view_listener_t +class LLToolsSaveToInventory final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - if(enable_save_into_inventory(NULL)) + bool enable_save_into_inventory(); + if(enable_save_into_inventory()) { derez_objects(DRD_SAVE_INTO_AGENT_INVENTORY, LLUUID::null); } @@ -5081,9 +5157,9 @@ class LLToolsSaveToInventory : public view_listener_t } }; -class LLToolsSaveToObjectInventory : public view_listener_t +class LLToolsSaveToObjectInventory final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if(node && (node->mValid) && (!node->mFromTaskID.isNull())) @@ -5095,27 +5171,27 @@ class LLToolsSaveToObjectInventory : public view_listener_t } }; -class LLToolsEnablePathfinding : public view_listener_t +class LLToolsEnablePathfinding final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion(); + return (LLPathfindingManager::getInstance() != nullptr) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion(); } }; -class LLToolsEnablePathfindingView : public view_listener_t +class LLToolsEnablePathfindingView final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLPathfindingManager::getInstance()->isPathfindingViewEnabled(); + return (LLPathfindingManager::getInstance() != nullptr) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLPathfindingManager::getInstance()->isPathfindingViewEnabled(); } }; -class LLToolsDoPathfindingRebakeRegion : public view_listener_t +class LLToolsDoPathfindingRebakeRegion final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - bool hasPathfinding = (LLPathfindingManager::getInstance() != NULL); + bool hasPathfinding = (LLPathfindingManager::getInstance() != nullptr); if (hasPathfinding) { @@ -5126,13 +5202,13 @@ class LLToolsDoPathfindingRebakeRegion : public view_listener_t } }; -class LLToolsEnablePathfindingRebakeRegion : public view_listener_t +class LLToolsEnablePathfindingRebakeRegion final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool returnValue = false; - if (LLPathfindingManager::getInstance() != NULL) + if (LLPathfindingManager::getInstance() != nullptr) { LLMenuOptionPathfindingRebakeNavmesh *rebakeInstance = LLMenuOptionPathfindingRebakeNavmesh::getInstance(); returnValue = (rebakeInstance->canRebakeRegion() && @@ -5144,9 +5220,9 @@ class LLToolsEnablePathfindingRebakeRegion : public view_listener_t }; // Round the position of all root objects to the grid -class LLToolsSnapObjectXY : public view_listener_t +class LLToolsSnapObjectXY final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { F64 snap_size = (F64)gSavedSettings.getF32("GridResolution"); @@ -5191,9 +5267,9 @@ class LLToolsSnapObjectXY : public view_listener_t }; // Determine if the option to cycle between linked prims is shown -class LLToolsEnableSelectNextPart : public view_listener_t +class LLToolsEnableSelectNextPart final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = (gSavedSettings.getBOOL("EditLinkedParts") && !LLSelectMgr::getInstance()->getSelection()->isEmpty()); @@ -5205,9 +5281,9 @@ class LLToolsEnableSelectNextPart : public view_listener_t // Cycle selection through linked children in selected object. // FIXME: Order of children list is not always the same as sim's idea of link order. This may confuse // resis. Need link position added to sim messages to address this. -class LLToolsSelectNextPart : public view_listener_t +class LLToolsSelectNextPart final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); if (gSavedSettings.getBOOL("EditLinkedParts") && object_count) @@ -5219,7 +5295,7 @@ class LLToolsSelectNextPart : public view_listener_t bool prev = (userdata.asString() == "previous"); bool ifwd = (userdata.asString() == "includenext"); bool iprev = (userdata.asString() == "includeprevious"); - LLViewerObject* to_select = NULL; + LLViewerObject* to_select = nullptr; LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren(); children.push_front(selected->getRootEdit()); // need root in the list too @@ -5266,7 +5342,7 @@ class LLToolsSelectNextPart : public view_listener_t { if (gFocusMgr.childHasKeyboardFocus(gFloaterTools)) { - gFocusMgr.setKeyboardFocus(NULL); // force edit toolbox to commit any changes + gFocusMgr.setKeyboardFocus(nullptr); // force edit toolbox to commit any changes } if (fwd || prev) { @@ -5289,9 +5365,9 @@ class LLToolsSelectNextPart : public view_listener_t // otherwise. this allows the handle_link method to more finely check // the selection and give an error message when the uer has a // reasonable expectation for the link to work, but it will fail. -class LLToolsEnableLink : public view_listener_t +class LLToolsEnableLink final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLSelectMgr::getInstance()->enableLinkObjects(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -5299,17 +5375,17 @@ class LLToolsEnableLink : public view_listener_t } }; -class LLToolsLink : public view_listener_t +class LLToolsLink final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { return LLSelectMgr::getInstance()->linkObjects(); } }; -class LLToolsEnableUnlink : public view_listener_t +class LLToolsEnableUnlink final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLSelectMgr::getInstance()->enableUnlinkObjects(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -5317,9 +5393,9 @@ class LLToolsEnableUnlink : public view_listener_t } }; -class LLToolsUnlink : public view_listener_t +class LLToolsUnlink final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLSelectMgr::getInstance()->unlinkObjects(); return true; @@ -5327,18 +5403,18 @@ class LLToolsUnlink : public view_listener_t }; -class LLToolsStopAllAnimations : public view_listener_t +class LLToolsStopAllAnimations final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gAgent.stopCurrentAnimations(); return true; } }; -class LLToolsReleaseKeys : public view_listener_t +class LLToolsReleaseKeys final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.0f) | Modified: RLVa-1.0.5a | OK if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_REMOVE)) ) @@ -5350,9 +5426,9 @@ class LLToolsReleaseKeys : public view_listener_t } }; -class LLToolsEnableReleaseKeys : public view_listener_t +class LLToolsEnableReleaseKeys final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.0f) | Modified: RLVa-1.0.5a gMenuHolder->findControl(userdata["control"].asString())->setValue(gAgent.anyControlGrabbed() && @@ -5364,9 +5440,9 @@ class LLToolsEnableReleaseKeys : public view_listener_t }; -class LLEditEnableCut : public view_listener_t +class LLEditEnableCut final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCut(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -5374,9 +5450,9 @@ class LLEditEnableCut : public view_listener_t } }; -class LLEditCut : public view_listener_t +class LLEditCut final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if( LLEditMenuHandler::gEditMenuHandler ) { @@ -5386,9 +5462,9 @@ class LLEditCut : public view_listener_t } }; -class LLEditEnableCopy : public view_listener_t +class LLEditEnableCopy final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCopy(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -5396,9 +5472,9 @@ class LLEditEnableCopy : public view_listener_t } }; -class LLEditCopy : public view_listener_t +class LLEditCopy final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if( LLEditMenuHandler::gEditMenuHandler ) { @@ -5408,9 +5484,9 @@ class LLEditCopy : public view_listener_t } }; -class LLEditEnablePaste : public view_listener_t +class LLEditEnablePaste final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canPaste(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -5418,9 +5494,9 @@ class LLEditEnablePaste : public view_listener_t } }; -class LLEditPaste : public view_listener_t +class LLEditPaste final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if( LLEditMenuHandler::gEditMenuHandler ) { @@ -5430,9 +5506,9 @@ class LLEditPaste : public view_listener_t } }; -class LLEditEnableDelete : public view_listener_t +class LLEditEnableDelete final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete(); @@ -5449,9 +5525,9 @@ class LLEditEnableDelete : public view_listener_t } }; -class LLEditDelete : public view_listener_t +class LLEditDelete final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) // NOTE: we want to disable delete on objects but not disable delete on text @@ -5485,9 +5561,9 @@ bool enable_object_return() (gAgent.isGodlike() || can_derez(DRD_RETURN_TO_OWNER))); } -class LLObjectEnableDelete : public view_listener_t +class LLObjectEnableDelete final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_object_delete()); return true; @@ -5518,13 +5594,13 @@ bool enable_object_delete() class LLObjectsReturnPackage { public: - LLObjectsReturnPackage() : mObjectSelection(), mReturnableObjects(), mError(), mFirstRegion(NULL) {}; + LLObjectsReturnPackage() : mObjectSelection(), mReturnableObjects(), mError(), mFirstRegion(nullptr) {}; ~LLObjectsReturnPackage() { mObjectSelection.clear(); mReturnableObjects.clear(); mError.clear(); - mFirstRegion = NULL; + mFirstRegion = nullptr; }; LLObjectSelectionHandle mObjectSelection; @@ -5558,9 +5634,9 @@ void handle_object_return() } } -class LLObjectDelete : public view_listener_t +class LLObjectDelete final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) ) @@ -5594,9 +5670,9 @@ void handle_force_delete(void*) LLSelectMgr::getInstance()->selectForceDelete(); } -class LLViewEnableJoystickFlycam : public view_listener_t +class LLViewEnableJoystickFlycam final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = (gSavedSettings.getBOOL("JoystickEnabled") && gSavedSettings.getBOOL("JoystickFlycamEnabled")); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -5604,9 +5680,9 @@ class LLViewEnableJoystickFlycam : public view_listener_t } }; -class LLViewEnableLastChatter : public view_listener_t +class LLViewEnableLastChatter final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // *TODO: add check that last chatter is in range bool new_value = (gAgentCamera.cameraThirdPerson() && gAgent.getLastChatter().notNull()); @@ -5615,9 +5691,9 @@ class LLViewEnableLastChatter : public view_listener_t } }; -class LLEditEnableDeselect : public view_listener_t +class LLEditEnableDeselect final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDeselect(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -5625,9 +5701,9 @@ class LLEditEnableDeselect : public view_listener_t } }; -class LLEditDeselect : public view_listener_t +class LLEditDeselect final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if( LLEditMenuHandler::gEditMenuHandler ) { @@ -5637,9 +5713,9 @@ class LLEditDeselect : public view_listener_t } }; -class LLEditEnableSelectAll : public view_listener_t +class LLEditEnableSelectAll final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canSelectAll(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -5648,9 +5724,9 @@ class LLEditEnableSelectAll : public view_listener_t }; -class LLEditSelectAll : public view_listener_t +class LLEditSelectAll final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if( LLEditMenuHandler::gEditMenuHandler ) { @@ -5661,9 +5737,9 @@ class LLEditSelectAll : public view_listener_t }; -class LLEditEnableUndo : public view_listener_t +class LLEditEnableUndo final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -5671,9 +5747,9 @@ class LLEditEnableUndo : public view_listener_t } }; -class LLEditUndo : public view_listener_t +class LLEditUndo final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo() ) { @@ -5683,9 +5759,9 @@ class LLEditUndo : public view_listener_t } }; -class LLEditEnableRedo : public view_listener_t +class LLEditEnableRedo final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -5693,9 +5769,9 @@ class LLEditEnableRedo : public view_listener_t } }; -class LLEditRedo : public view_listener_t +class LLEditRedo final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo() ) { @@ -5769,7 +5845,7 @@ void toggle_debug_menus(void*) // LLUUID gExporterRequestID; // std::string gExportDirectory; -// LLUploadDialog *gExportDialog = NULL; +// LLUploadDialog *gExportDialog = nullptr; // void handle_export_selected( void * ) // { @@ -5822,9 +5898,9 @@ void handle_reload_settings(void*) gColors.loadFromFileLegacy(color_file, FALSE, TYPE_COL4U); } -class LLWorldSetHomeLocation : public view_listener_t +class LLWorldSetHomeLocation final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // we just send the message and let the server check for failure cases // server will echo back a "Home position set." alert if it succeeds @@ -5834,9 +5910,9 @@ class LLWorldSetHomeLocation : public view_listener_t } }; -class LLWorldTeleportHome : public view_listener_t +class LLWorldTeleportHome final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gAgent.teleportHome(); return true; @@ -5849,27 +5925,27 @@ void toggle_sit() gAgent.setControlFlags(gAgentAvatarp->isSitting() ? AGENT_CONTROL_STAND_UP : AGENT_CONTROL_SIT_ON_GROUND); } -class LLWorldSitOnGround : public view_listener_t +class LLWorldSitOnGround final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { toggle_sit(); return true; } }; -class LLWorldFakeAway : public view_listener_t +class LLWorldFakeAway final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - handle_fake_away_status(NULL); + handle_fake_away_status(nullptr); return true; } }; -class LLWorldEnableSitOnGround : public view_listener_t +class LLWorldEnableSitOnGround final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = (gAgentAvatarp); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -5877,9 +5953,9 @@ class LLWorldEnableSitOnGround : public view_listener_t } }; -class LLWorldSetAway : public view_listener_t +class LLWorldSetAway final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if (gAgent.getAFK()) { @@ -5893,9 +5969,9 @@ class LLWorldSetAway : public view_listener_t } }; -class LLWorldSetBusy : public view_listener_t +class LLWorldSetBusy final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool busy = !gAgent.isDoNotDisturb(); gAgent.setDoNotDisturb(busy); @@ -5905,9 +5981,9 @@ class LLWorldSetBusy : public view_listener_t } }; -class LLWorldCreateLandmark : public view_listener_t +class LLWorldCreateLandmark final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.4.5) | Added: RLVa-1.0.0 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) @@ -5949,9 +6025,9 @@ class LLWorldCreateLandmark : public view_listener_t } }; -class LLToolsLookAtSelection : public view_listener_t +class LLToolsLookAtSelection final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { handle_look_at_selection(userdata); return true; @@ -5996,9 +6072,9 @@ void handle_look_at_selection(const LLSD& param) } } -class LLAvatarInviteToGroup : public view_listener_t +class LLAvatarInviteToGroup final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); // if(avatar) @@ -6012,9 +6088,9 @@ class LLAvatarInviteToGroup : public view_listener_t } }; -class LLAvatarAddFriend : public view_listener_t +class LLAvatarAddFriend final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); // if(avatar && !LLAvatarActions::isFriend(avatar->getID())) @@ -6028,7 +6104,44 @@ class LLAvatarAddFriend : public view_listener_t } }; -bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection) +class LLAvatarResetSkeleton final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + if (avatar) + { + avatar->resetSkeleton(false); + } + return true; + } +}; + +class LLAvatarEnableResetSkeleton final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + return avatar != nullptr; + } +}; + + +class LLAvatarResetSkeletonAndAnimations final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + if (avatar) + { + avatar->resetSkeleton(true); + } + return true; + } + +}; + +bool complete_give_money(const LLSD& notification, const LLSD& response, LLViewerObject* objectp) { S32 option = LLNotification::getSelectedOption(notification, response); if (option == 0) @@ -6036,8 +6149,6 @@ bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjec gAgent.setDoNotDisturb(false); } - LLViewerObject* objectp = selection->getPrimaryObject(); - // Show avatar's name if paying attachment if (objectp && objectp->isAttachment()) { @@ -6064,10 +6175,10 @@ bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjec return false; } -void handle_give_money_dialog() +void handle_give_money_dialog(LLViewerObject* obj) { LLNotification::Params params("BusyModePay"); - params.functor(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection())); + params.functor(boost::bind(complete_give_money, _1, _2, obj)); if (gAgent.isDoNotDisturb()) { @@ -6080,11 +6191,11 @@ void handle_give_money_dialog() } } -class LLPayObject : public view_listener_t +class LLPayObject final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - handle_give_money_dialog(); + handle_give_money_dialog(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); return true; } }; @@ -6093,15 +6204,14 @@ bool enable_pay_avatar() { LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); LLVOAvatar* avatar = find_avatar_from_object(obj); -// return (avatar != NULL); +// return (avatar != nullptr); // [RLVa:KB] - Checked: 2010-08-25 (RLVa-1.2.1b) | Added: RLVa-1.2.1b - return (avatar != NULL) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) && !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)); + return (avatar != nullptr) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) && !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)); // [/RLVa:KB] } -bool enable_pay_object() +bool enable_pay_object(LLViewerObject* object) { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if( object ) { LLViewerObject *parent = (LLViewerObject *)object->getParent(); @@ -6160,9 +6270,9 @@ bool enable_object_sit(/*LLUICtrl* ctrl*/) return !sitting_on_sel && is_object_sittable(); } -class LLObjectEnableSitOrStand : public view_listener_t +class LLObjectEnableSitOrStand final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value; @@ -6203,11 +6313,11 @@ class LLObjectEnableSitOrStand : public view_listener_t } }; -class LLEnablePayObject : public view_listener_t +class LLEnablePayObject final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_pay_avatar() || enable_pay_object()); + gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_pay_avatar() || enable_pay_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())); return true; } }; @@ -6245,9 +6355,9 @@ void handle_viewer_disable_message_log(void*) // TomY TODO: Move! void show_floater(const std::string& floater_name); -class LLShowFloater : public view_listener_t +class LLShowFloater final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { show_floater(userdata.asString()); return true; @@ -6255,9 +6365,9 @@ class LLShowFloater : public view_listener_t }; bool floater_visible(const std::string& floater_name); -class LLFloaterVisible : public view_listener_t +class LLFloaterVisible final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(floater_visible(userdata["data"].asString())); return true; @@ -6275,9 +6385,9 @@ bool callback_show_url(const LLSD& notification, const LLSD& response) return false; } -class LLPromptShowURL : public view_listener_t +class LLPromptShowURL final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { std::string param = userdata.asString(); std::string::size_type offset = param.find(","); @@ -6315,9 +6425,9 @@ bool callback_show_file(const LLSD& notification, const LLSD& response) return false; } -class LLPromptShowFile : public view_listener_t +class LLPromptShowFile final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { std::string param = userdata.asString(); std::string::size_type offset = param.find(","); @@ -6338,9 +6448,9 @@ class LLPromptShowFile : public view_listener_t } }; -class LLShowAgentProfile : public view_listener_t +class LLShowAgentProfile final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLUUID agent_id; if (userdata.asString() == "agent") @@ -6372,9 +6482,9 @@ class LLShowAgentProfile : public view_listener_t } }; -class LLLandEdit : public view_listener_t +class LLLandEdit final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) ) @@ -6409,9 +6519,9 @@ class LLLandEdit : public view_listener_t } }; -class LLWorldEnableBuyLand : public view_listener_t +class LLWorldEnableBuyLand final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLViewerParcelMgr::getInstance()->canAgentBuyParcel( LLViewerParcelMgr::getInstance()->selectionEmpty() @@ -6429,9 +6539,9 @@ BOOL enable_buy_land(void*) LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), false); } -class LLWorldVisibleDestinations : public view_listener_t +class LLWorldVisibleDestinations final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool visible(!LFSimFeatureHandler::instance().destinationGuideURL().empty()); gMenuHolder->findControl(userdata["control"].asString())->setValue(visible); @@ -6439,23 +6549,23 @@ class LLWorldVisibleDestinations : public view_listener_t } }; -class LLObjectAttachToAvatar : public view_listener_t +class LLObjectAttachToAvatar final : public view_listener_t { public: LLObjectAttachToAvatar(bool replace) : mReplace(replace) {} static void setObjectSelection(LLObjectSelectionHandle selection) { sObjectSelection = selection; } private: - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { setObjectSelection(LLSelectMgr::getInstance()->getSelection()); LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject(); if (selectedObject) { S32 index = userdata.asInteger(); - LLViewerJointAttachment* attachment_point = NULL; + LLViewerJointAttachment* attachment_point = nullptr; if (index > 0) - attachment_point = get_if_there(gAgentAvatarp->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL); + attachment_point = get_if_there(gAgentAvatarp->mAttachmentPoints, index, (LLViewerJointAttachment*)nullptr); // [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.2.1f // RELEASE-RLVa: [SL-2.2.0] If 'index != 0' then the object will be "add attached" [see LLSelectMgr::sendAttach()] @@ -6464,7 +6574,7 @@ class LLObjectAttachToAvatar : public view_listener_t ((index) && ((RLV_WEAR_ADD & gRlvAttachmentLocks.canAttach(attachment_point)) == 0)) || // or non-attachable attachpt (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) ) // Attach on object == "Take" { - setObjectSelection(NULL); // Clear the selection or it'll get stuck + setObjectSelection(nullptr); // Clear the selection or it'll get stuck return true; } // [/RLVa:KB] @@ -6522,7 +6632,7 @@ void LLObjectAttachToAvatar::onNearAttachObject(BOOL success, void *user_data) } LLSelectMgr::getInstance()->sendAttach(attachment_id, cb_data->mReplace); } - LLObjectAttachToAvatar::setObjectSelection(NULL); + LLObjectAttachToAvatar::setObjectSelection(nullptr); delete cb_data; } @@ -6555,7 +6665,7 @@ void LLObjectAttachToAvatar::confirmReplaceAttachment(S32 option, LLViewerJointA // The callback will be called even if avatar fails to get close enough to the object, so we won't get a memory leak. CallbackData* user_data = new CallbackData(attachment_point, mReplace); - gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(walkToSpot), "Attach", NULL, onNearAttachObject, user_data, stop_distance); + gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(walkToSpot), "Attach", nullptr, onNearAttachObject, user_data, stop_distance); gAgentCamera.clearFocusObject(); } } @@ -6609,9 +6719,9 @@ void callback_attachment_drop(const LLSD& notification, const LLSD& response) return; } -class LLAttachmentDrop : public view_listener_t +class LLAttachmentDrop final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2010-03-15 (RLVa-1.2.0e) | Modified: RLVa-1.0.5 if (rlv_handler_t::isEnabled()) @@ -6621,7 +6731,7 @@ class LLAttachmentDrop : public view_listener_t // NOTE: copy/paste of the code in enable_detach() LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection(); RlvSelectHasLockedAttach f; - if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&f, FALSE) != NULL) ) + if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&f, FALSE) != nullptr) ) return true; } if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) @@ -6726,9 +6836,9 @@ void detach_label(std::string& label, void* user_data) } } -class LLAttachmentDetach : public view_listener_t +class LLAttachmentDetach final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // Called when the user clicked on an object attached to them // and selected "Detach". @@ -6768,7 +6878,7 @@ class LLAttachmentDetach : public view_listener_t { LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection(); RlvSelectHasLockedAttach f; - if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&f, FALSE) != NULL) ) + if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&f, FALSE) != nullptr) ) return true; } // [/RLVa:KB] @@ -6781,7 +6891,7 @@ class LLAttachmentDetach : public view_listener_t //Adding an observer for a Jira 2422 and needs to be a fetch observer //for Jira 3119 -class LLWornItemFetchedObserver : public LLInventoryFetchItemsObserver +class LLWornItemFetchedObserver final : public LLInventoryFetchItemsObserver { public: LLWornItemFetchedObserver(const LLUUID& worn_item_id) : @@ -6799,9 +6909,9 @@ class LLWornItemFetchedObserver : public LLInventoryFetchItemsObserver }; // You can only drop items on parcels where you can build. -class LLAttachmentEnableDrop : public view_listener_t +class LLAttachmentEnableDrop final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { BOOL can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->allowAgentBuild()); @@ -6816,13 +6926,14 @@ class LLAttachmentEnableDrop : public view_listener_t // item is in your inventory LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - LLViewerJointAttachment* attachment = NULL; - LLInventoryItem* item = NULL; + LLViewerJointAttachment* attachment = nullptr; + LLInventoryItem* item = nullptr; - if (object) + // Do not enable drop if all faces of object are not enabled + if (object && LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES )) { - S32 attachmentID = ATTACHMENT_ID_FROM_STATE(object->getState()); - attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL); + S32 attachmentID = ATTACHMENT_ID_FROM_STATE(object->getAttachmentState()); + attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)nullptr); if (attachment) { @@ -6884,7 +6995,7 @@ BOOL enable_detach(const LLSD&) { LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection(); RlvSelectHasLockedAttach f; - if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&f, FALSE) != NULL) ) + if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&f, FALSE) != nullptr) ) return FALSE; } // [/RLVa:KB] @@ -6897,9 +7008,9 @@ BOOL enable_detach(const LLSD&) return FALSE; } -class LLAttachmentEnableDetach : public view_listener_t +class LLAttachmentEnableDetach final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = enable_detach(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -6918,8 +7029,8 @@ BOOL object_selected_and_point_valid(void *user_data) // RELEASE-RLVa: look at the caller graph for this function on every new release // -> 1.22.11 and 1.23.4 - // - object_is_wearable() => dead code [user_data == NULL => default attach point => OK!] - // - LLObjectEnableWear::handleEvent() => Rezzed prim / right-click / "Wear" [user_data == NULL => see above] + // - object_is_wearable() => dead code [user_data == nullptr => default attach point => OK!] + // - LLObjectEnableWear::handleEvent() => Rezzed prim / right-click / "Wear" [user_data == nullptr => see above] // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / right-click / "Attach >" [user_data == pAttachPt] // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / Edit menu / "Attach Object" [user_data == pAttachPt] const LLViewerJointAttachment* pAttachPt = (const LLViewerJointAttachment*)user_data; @@ -6955,7 +7066,7 @@ BOOL object_selected_and_point_valid(void *user_data) selection->getFirstRootObject()->permYouOwner() && !selection->getFirstRootObject()->flagObjectPermanent() && !((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() && - (selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL); + (selection->getFirstRootObject()->getNVPair("AssetContainer") == nullptr); } @@ -6963,7 +7074,7 @@ BOOL object_selected_and_point_valid(void *user_data) /* BOOL object_is_wearable() { - if (!object_selected_and_point_valid(NULL)) + if (!object_selected_and_point_valid(nullptr)) { return FALSE; } @@ -6988,11 +7099,11 @@ BOOL object_is_wearable() // Also for seeing if object can be attached. See above. -class LLObjectEnableWear : public view_listener_t +class LLObjectEnableWear final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - bool is_wearable = object_selected_and_point_valid(NULL); + bool is_wearable = object_selected_and_point_valid(nullptr); gMenuHolder->findControl(userdata["control"].asString())->setValue(is_wearable); return TRUE; } @@ -7012,9 +7123,9 @@ BOOL object_attached(void *user_data) // return attachment->getNumObjects() > 0; } -class LLAvatarSendIM : public view_listener_t +class LLAvatarSendIM final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); // if(avatar) @@ -7030,14 +7141,18 @@ class LLAvatarSendIM : public view_listener_t namespace { - struct QueueObjects : public LLSelectedObjectFunctor + struct QueueObjects final : public LLSelectedObjectFunctor { BOOL scripted; BOOL modifiable; LLFloaterScriptQueue* mQueue; QueueObjects(LLFloaterScriptQueue* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {} - virtual bool apply(LLViewerObject* obj) + bool apply(LLViewerObject* obj) override { + if (!obj) + { + return true; + } scripted = obj->flagScripted(); modifiable = obj->permModify(); @@ -7086,9 +7201,9 @@ void queue_actions(LLFloaterScriptQueue* q, const std::string& msg) } } -class LLToolsSelectedScriptAction : public view_listener_t +class LLToolsSelectedScriptAction final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.0f) | Modified: RLVa-1.0.5a // We'll allow resetting the scripts of objects on a non-attachable attach point since they wouldn't be able to circumvent anything @@ -7096,13 +7211,13 @@ class LLToolsSelectedScriptAction : public view_listener_t { LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); RlvSelectHasLockedAttach f; - if ( (hSel->isAttachment()) && (hSel->getFirstNode(&f) != NULL) ) + if ( (hSel->isAttachment()) && (hSel->getFirstNode(&f) != nullptr) ) return true; } // [/RLVa:KB] std::string action = userdata.asString(); - LLFloaterScriptQueue* queue = NULL; + LLFloaterScriptQueue* queue = nullptr; std::string msg; if (action == "compile mono") { @@ -7249,7 +7364,7 @@ void handle_toggle_pg(void*) { gAgent.setTeen( !gAgent.isTeen() ); - LLFloaterWorldMap::reloadIcons(NULL); + LLFloaterWorldMap::reloadIcons(nullptr); LL_INFOS() << "PG status set to " << gAgent.isTeen() << LL_ENDL; } @@ -7269,7 +7384,7 @@ void handle_dump_attachments(void*) ++attachment_iter) { LLViewerObject *attached_object = (*attachment_iter); - BOOL visible = (attached_object != NULL && + BOOL visible = (attached_object != nullptr && attached_object->mDrawable.notNull() && !attached_object->mDrawable->isRenderType(0)); LLVector3 pos; @@ -7306,23 +7421,14 @@ void menu_toggle_double_click_control(void* user_data) { std::string setting(static_cast(user_data)); LLControlVariable* control(gSavedSettings.getControl(setting)); - bool checked = control->get(); - // Doubleclick actions - there can be only one - if (!checked) - { - if (setting == "DoubleClickAutoPilot") - gSavedSettings.setBOOL("DoubleClickTeleport", false); - else if (setting == "DoubleClickTeleport") - gSavedSettings.setBOOL("DoubleClickAutoPilot", false); - } - control->set(!checked); + control->set(!control->get()); } // these are used in the gl menus to set control values, generically. -class LLToggleControl : public view_listener_t +class LLToggleControl final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLControlVariable* control(gSavedSettings.getControl(userdata.asString())); control->set(!control->get()); @@ -7330,9 +7436,9 @@ class LLToggleControl : public view_listener_t } }; -class LLTogglePerAccountControl : public view_listener_t +class LLTogglePerAccountControl final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLControlVariable* control(gSavedPerAccountSettings.getControl(userdata.asString())); control->set(!control->get()); @@ -7375,9 +7481,9 @@ void menu_toggle_attached_particles(void* user_data) LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); } -class LLSomethingSelected : public view_listener_t +class LLSomethingSelected final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = !(LLSelectMgr::getInstance()->getSelection()->isEmpty()); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -7385,9 +7491,9 @@ class LLSomethingSelected : public view_listener_t } }; -class LLSomethingSelectedNoHUD : public view_listener_t +class LLSomethingSelectedNoHUD final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); bool new_value = !(selection->isEmpty()) && !(selection->getSelectType() == SELECT_TYPE_HUD); @@ -7419,21 +7525,21 @@ static bool is_editable_selected() } // [/RLVa:KB] - return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL); + return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != nullptr); } -class LLEditableSelected : public view_listener_t +class LLEditableSelected final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(is_editable_selected()); return true; } }; -class LLEditableSelectedMono : public view_listener_t +class LLEditableSelectedMono final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerRegion* region = gAgent.getRegion(); if(region && gMenuHolder && gMenuHolder->findControl(userdata["control"].asString())) @@ -7447,9 +7553,9 @@ class LLEditableSelectedMono : public view_listener_t } }; -class LLToolsEnableTakeCopy : public view_listener_t +class LLToolsEnableTakeCopy final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_object_take_copy()); return true; @@ -7470,9 +7576,9 @@ bool enable_object_take_copy() || !gAgent.isGodlike()) # endif { - struct f : public LLSelectedObjectFunctor + struct f final : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* obj) + bool apply(LLViewerObject* obj) override { // return (!obj->permCopy() || obj->isAttachment()); // [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.2.0c) | Modified: RLVa-1.0.0g @@ -7493,17 +7599,17 @@ bool enable_object_take_copy() } // -class LLToolsEnableAdminDelete : public view_listener_t +class LLToolsEnableAdminDelete final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - return (object != NULL); + return (object != nullptr); } }; -class LLToolsAdminDelete : public view_listener_t +class LLToolsAdminDelete final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLSelectMgr::getInstance()->selectForceDelete(); return true; @@ -7515,9 +7621,9 @@ BOOL enable_selection_you_own_all(void*) { if (LLSelectMgr::getInstance()) { - struct f : public LLSelectedObjectFunctor + struct f final : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* obj) + bool apply(LLViewerObject* obj) override { return (!obj->permYouOwner()); } @@ -7536,9 +7642,9 @@ BOOL enable_selection_you_own_one(void*) { if (LLSelectMgr::getInstance()) { - struct f : public LLSelectedObjectFunctor + struct f final : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* obj) + virtual bool apply(LLViewerObject* obj) override { return (obj->permYouOwner()); } @@ -7553,7 +7659,7 @@ BOOL enable_selection_you_own_one(void*) return TRUE; } -class LLHasAsset : public LLInventoryCollectFunctor +class LLHasAsset final : public LLInventoryCollectFunctor { public: LLHasAsset(const LLUUID& id) : mAssetID(id), mHasAsset(FALSE) {} @@ -7577,11 +7683,11 @@ bool LLHasAsset::operator()(LLInventoryCategory* cat, return FALSE; } -BOOL enable_save_into_inventory(void*) +bool enable_save_into_inventory() { // *TODO: clean this up // find the last root - LLSelectNode* last_node = NULL; + LLSelectNode* last_node = nullptr; for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) { @@ -7601,7 +7707,7 @@ BOOL enable_save_into_inventory(void*) // check all pre-req's for save into inventory. if(last_node && last_node->mValid && !last_node->mItemID.isNull() && (last_node->mPermissions->getOwner() == gAgent.getID()) - && (gInventory.getItem(last_node->mItemID) != NULL)) + && (gInventory.getItem(last_node->mItemID) != nullptr)) { LLViewerObject* obj = last_node->getObject(); if( obj && !obj->isAttachment() ) @@ -7628,20 +7734,20 @@ BOOL enable_save_into_task_inventory(void*) return FALSE; } -class LLToolsEnableSaveToObjectInventory : public view_listener_t +class LLToolsEnableSaveToObjectInventory final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - bool new_value = enable_save_into_task_inventory(NULL); + bool new_value = enable_save_into_task_inventory(nullptr); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } }; -class LLViewEnableMouselook : public view_listener_t +class LLViewEnableMouselook final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // You can't go directly from customize avatar to mouselook. // TODO: write code with appropriate dialogs to handle this transition. @@ -7651,9 +7757,9 @@ class LLViewEnableMouselook : public view_listener_t } }; -class LLToolsEnableToolNotPie : public view_listener_t +class LLToolsEnableToolNotPie final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = ( LLToolMgr::getInstance()->getBaseTool() != LLToolPie::getInstance() ); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -7661,9 +7767,9 @@ class LLToolsEnableToolNotPie : public view_listener_t } }; -class LLWorldEnableCreateLandmark : public view_listener_t +class LLWorldEnableCreateLandmark final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = gAgent.isGodlike() || (gAgent.getRegion() && gAgent.getRegion()->getAllowLandmark()); @@ -7675,9 +7781,9 @@ class LLWorldEnableCreateLandmark : public view_listener_t } }; -class LLWorldEnableSetHomeLocation : public view_listener_t +class LLWorldEnableSetHomeLocation final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = gAgent.isGodlike() || (gAgent.getRegion() && gAgent.getRegion()->getAllowSetHome()); @@ -7686,9 +7792,9 @@ class LLWorldEnableSetHomeLocation : public view_listener_t } }; -class LLWorldEnableTeleportHome : public view_listener_t +class LLWorldEnableTeleportHome final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerRegion* regionp = gAgent.getRegion(); bool agent_on_prelude = (regionp && regionp->isPrelude()); @@ -7733,9 +7839,9 @@ BOOL check_show_xui_names(void *) return gSavedSettings.getBOOL("ShowXUINames"); } -class LLToolsSelectOnlyMyObjects : public view_listener_t +class LLToolsSelectOnlyMyObjects final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { BOOL cur_val = gSavedSettings.getBOOL("SelectOwnedOnly"); @@ -7745,9 +7851,9 @@ class LLToolsSelectOnlyMyObjects : public view_listener_t } }; -class LLToolsSelectOnlyMovableObjects : public view_listener_t +class LLToolsSelectOnlyMovableObjects final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { BOOL cur_val = gSavedSettings.getBOOL("SelectMovableOnly"); @@ -7757,9 +7863,9 @@ class LLToolsSelectOnlyMovableObjects : public view_listener_t } }; -class LLToolsSelectBySurrounding : public view_listener_t +class LLToolsSelectBySurrounding final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLSelectMgr::sRectSelectInclusive = !LLSelectMgr::sRectSelectInclusive; @@ -7768,9 +7874,9 @@ class LLToolsSelectBySurrounding : public view_listener_t } }; -class LLToolsShowSelectionHighlights : public view_listener_t +class LLToolsShowSelectionHighlights final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLControlVariable *ctrl = gSavedSettings.getControl("RenderHighlightSelections"); ctrl->setValue(!ctrl->getValue().asBoolean()); @@ -7778,9 +7884,9 @@ class LLToolsShowSelectionHighlights : public view_listener_t } }; -class LLToolsShowHiddenSelection : public view_listener_t +class LLToolsShowHiddenSelection final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // TomY TODO Merge these LLSelectMgr::sRenderHiddenSelections = !LLSelectMgr::sRenderHiddenSelections; @@ -7790,9 +7896,9 @@ class LLToolsShowHiddenSelection : public view_listener_t } }; -class LLToolsShowSelectionLightRadius : public view_listener_t +class LLToolsShowSelectionLightRadius final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // TomY TODO merge these LLSelectMgr::sRenderLightRadius = !LLSelectMgr::sRenderLightRadius; @@ -7802,9 +7908,9 @@ class LLToolsShowSelectionLightRadius : public view_listener_t } }; -class LLToolsEditLinkedParts : public view_listener_t +class LLToolsEditLinkedParts final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { BOOL select_individuals = gSavedSettings.getBOOL("EditLinkedParts"); if (select_individuals) @@ -7930,11 +8036,10 @@ void init_meshes_and_morphs_menu() lod_menu->addSeparator(); - for(LLPolyMesh::morph_list_t::iterator morph_iter = morph_list.begin(); - morph_iter != morph_list.end(); ++morph_iter) + for(auto& morph : morph_list) { - std::string const& morph_name = morph_iter->first; - LLPolyMorphData* morph_data = morph_iter->second; + std::string const& morph_name = morph.first; + LLPolyMorphData* morph_data = morph.second; action_menu = new LLMenuGL(morph_name); @@ -7964,7 +8069,7 @@ void handle_mesh_save_llm(void* data) if (!mesh_name) { - LL_WARNS() << "LPolyMesh::getSharedMeshName returned NULL" << LL_ENDL; + LL_WARNS() << "LPolyMesh::getSharedMeshName returned nullptr" << LL_ENDL; return; } @@ -8037,7 +8142,7 @@ void handle_mesh_save_current_obj(void* data) if (!mesh_name) { - LL_WARNS() << "LPolyMesh::getSharedMeshName returned NULL" << LL_ENDL; + LL_WARNS() << "LPolyMesh::getSharedMeshName returned nullptr" << LL_ENDL; return; } @@ -8086,7 +8191,7 @@ void handle_mesh_save_obj(void* data) if (!mesh_name) { - LL_WARNS() << "LPolyMesh::getSharedMeshName returned NULL" << LL_ENDL; + LL_WARNS() << "LPolyMesh::getSharedMeshName returned nullptr" << LL_ENDL; return; } @@ -8118,7 +8223,7 @@ static void handle_mesh_save_obj_continued(void* data, AIFilePicker* filepicker) return; } - LLPolyMesh mesh(mesh_shared,NULL); + LLPolyMesh mesh(mesh_shared,nullptr); mesh.saveOBJ(fp); fclose(fp); } @@ -8132,7 +8237,7 @@ void handle_mesh_load_obj(void* data) if (!mesh_name) { - LL_WARNS() << "LPolyMesh::getSharedMeshName returned NULL" << LL_ENDL; + LL_WARNS() << "LPolyMesh::getSharedMeshName returned nullptr" << LL_ENDL; return; } @@ -8161,7 +8266,7 @@ static void handle_mesh_load_obj_continued(void* data, AIFilePicker* filepicker) return; } - LLPolyMesh mesh(mesh_shared,NULL); + LLPolyMesh mesh(mesh_shared,nullptr); mesh.loadOBJ(fp); mesh.setSharedFromCurrent(); fclose(fp); @@ -8177,7 +8282,7 @@ void handle_morph_save_obj(void* data) if (!mesh_name) { - LL_WARNS() << "LPolyMesh::getSharedMeshName returned NULL" << LL_ENDL; + LL_WARNS() << "LPolyMesh::getSharedMeshName returned nullptr" << LL_ENDL; return; } @@ -8225,7 +8330,7 @@ void handle_morph_load_obj(void* data) if (!mesh_name) { - LL_WARNS() << "LPolyMesh::getSharedMeshName returned NULL" << LL_ENDL; + LL_WARNS() << "LPolyMesh::getSharedMeshName returned nullptr" << LL_ENDL; return; } @@ -8256,7 +8361,7 @@ static void handle_morph_load_obj_continued(void* data, AIFilePicker* filepicker return; } - LLPolyMesh mesh(mesh_shared,NULL); + LLPolyMesh mesh(mesh_shared,nullptr); mesh.loadOBJ(fp); fclose(fp); @@ -8264,7 +8369,7 @@ static void handle_morph_load_obj_continued(void* data, AIFilePicker* filepicker } // Returns a pointer to the avatar give the UUID of the avatar OR of an attachment the avatar is wearing. -// Returns NULL on failure. +// Returns nullptr on failure. LLVOAvatar* find_avatar_from_object( LLViewerObject* object ) { if (object) @@ -8279,7 +8384,7 @@ LLVOAvatar* find_avatar_from_object( LLViewerObject* object ) } else if( !object->isAvatar() ) { - object = NULL; + object = nullptr; } } @@ -8288,7 +8393,7 @@ LLVOAvatar* find_avatar_from_object( LLViewerObject* object ) // Returns a pointer to the avatar give the UUID of the avatar OR of an attachment the avatar is wearing. -// Returns NULL on failure. +// Returns nullptr on failure. LLVOAvatar* find_avatar_from_object( const LLUUID& object_id ) { return find_avatar_from_object( gObjectList.findObject(object_id) ); @@ -8330,14 +8435,14 @@ void force_error_driver_crash(void *) LLAppViewer::instance()->forceErrorDriverCrash(); } -class LLToolsUseSelectionForGrid : public view_listener_t +class LLToolsUseSelectionForGrid final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLSelectMgr::getInstance()->clearGridObjects(); - struct f : public LLSelectedObjectFunctor + struct f final : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* objectp) + bool apply(LLViewerObject* objectp) override { LLSelectMgr::getInstance()->addGridObject(objectp); return true; @@ -8380,8 +8485,8 @@ BOOL LLViewerMenuHolderGL::hideMenus() } // drop pie menu selection - mParcelSelection = NULL; - mObjectSelection = NULL; + mParcelSelection = nullptr; + mObjectSelection = nullptr; if (gMenuBarView) { @@ -8462,7 +8567,7 @@ static void handle_load_from_xml_continued(AIFilePicker* filepicker) void handle_web_browser_test(void*) { - LLWeb::loadURL("http://secondlife.com/app/search/slurls.html"); + LLWeb::loadURLInternal("http://secondlife.com/app/search/slurls.html"); } void handle_buy_currency_test(void*) @@ -8495,6 +8600,7 @@ void handle_rebake_textures(void*) { LLAppearanceMgr::instance().requestServerAppearanceUpdate(); } + gAgent.setIsCrossingRegion(false); // Attachments getting lost on TP } void toggle_visibility(void* user_data) @@ -8510,18 +8616,18 @@ BOOL get_visibility(void* user_data) } // TomY TODO: Get rid of these? -class LLViewShowHoverTips : public view_listener_t +class LLViewShowHoverTips final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLHoverView::sShowHoverTips = !LLHoverView::sShowHoverTips; return true; } }; -class LLViewCheckShowHoverTips : public view_listener_t +class LLViewCheckShowHoverTips final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLHoverView::sShowHoverTips; gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -8530,9 +8636,9 @@ class LLViewCheckShowHoverTips : public view_listener_t }; // TomY TODO: Get rid of these? -class LLViewHighlightTransparent : public view_listener_t +class LLViewHighlightTransparent final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Modified: RLVa-1.0.0b | OK if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (!LLDrawPoolAlpha::sShowDebugAlpha)) @@ -8544,9 +8650,9 @@ class LLViewHighlightTransparent : public view_listener_t } }; -class LLViewCheckHighlightTransparent : public view_listener_t +class LLViewCheckHighlightTransparent final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLDrawPoolAlpha::sShowDebugAlpha; gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -8554,9 +8660,9 @@ class LLViewCheckHighlightTransparent : public view_listener_t } }; -class LLViewToggleRenderType : public view_listener_t +class LLViewToggleRenderType final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { std::string type = userdata.asString(); if (type == "hideparticles") @@ -8567,9 +8673,9 @@ class LLViewToggleRenderType : public view_listener_t } }; -class LLViewCheckRenderType : public view_listener_t +class LLViewCheckRenderType final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { std::string type = userdata["data"].asString(); bool new_value = false; @@ -8582,9 +8688,9 @@ class LLViewCheckRenderType : public view_listener_t } }; -class LLViewShowHUDAttachments : public view_listener_t +class LLViewShowHUDAttachments final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.1a) | Modified: RLVa-1.0.0c if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedHUD()) && (LLPipeline::sShowHUDAttachments) ) @@ -8596,9 +8702,9 @@ class LLViewShowHUDAttachments : public view_listener_t } }; -class LLViewCheckHUDAttachments : public view_listener_t +class LLViewCheckHUDAttachments final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = LLPipeline::sShowHUDAttachments; gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -8606,9 +8712,9 @@ class LLViewCheckHUDAttachments : public view_listener_t } }; -class LLEditEnableTakeOff : public view_listener_t +class LLEditEnableTakeOff final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool new_value = false; std::string control_name = userdata["control"].asString(); @@ -8628,9 +8734,9 @@ class LLEditEnableTakeOff : public view_listener_t } }; -class LLEditTakeOff : public view_listener_t +class LLEditTakeOff final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { std::string clothing = userdata.asString(); if (clothing == "all") @@ -8668,9 +8774,9 @@ class LLEditTakeOff : public view_listener_t } }; -class LLToolsSelectTool : public view_listener_t +class LLToolsSelectTool final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { std::string tool_name = userdata.asString(); if (tool_name == "focus") @@ -8698,9 +8804,9 @@ class LLToolsSelectTool : public view_listener_t }; /// WINDLIGHT callbacks -class LLWorldEnvSettings : public view_listener_t +class LLWorldEnvSettings final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { // [RLVa:KB] - Checked: 2010-03-18 (RLVa-1.2.0a) | Modified: RLVa-1.0.0g if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV)) @@ -8734,9 +8840,9 @@ class LLWorldEnvSettings : public view_listener_t } }; -class LLWorldEnableEnvSettings : public view_listener_t +class LLWorldEnableEnvSettings final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { bool result = false; std::string tod = userdata.asString(); @@ -8773,56 +8879,93 @@ class LLWorldEnableEnvSettings : public view_listener_t } }; -class SinguCloseAllDialogs : public view_listener_t +class LLUploadCostCalculator final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + auto& asset_type_str = userdata["data"].asStringRef(); + S32 upload_cost = -1; + LLView* view; + + if (asset_type_str == "texture") + { + upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); + view = gMenuHolder->findChild("Upload Image"); + } + else if (asset_type_str == "animation") + { + upload_cost = LLAgentBenefitsMgr::current().getAnimationUploadCost(); + view = gMenuHolder->findChild("Upload Animation"); + } + else if (asset_type_str == "sound") + { + upload_cost = LLAgentBenefitsMgr::current().getSoundUploadCost(); + view = gMenuHolder->findChild("Upload Sound"); + } + else + { + LL_WARNS() << "Unable to find upload cost for asset_type_str " << asset_type_str << LL_ENDL; + return true; + } + auto ctrl = gMenuHolder->findControl(userdata["control"].asString()); + ctrl->setValue(gStatusBar && gStatusBar->getBalance() >= upload_cost); + view->setLabelArg("[UPLOADFEE]", gHippoGridManager->getConnectedGrid()->formatFee(upload_cost)); + + return true; + } +}; + +// TPV listeners go below here +class SinguCloseAllDialogs final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gNotifyBoxView->deleteAllChildren(); return true; } }; -class SinguEnableStreamingAudioDisplay : public view_listener_t +class SinguEnableStreamingAudioDisplay final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - return handle_ticker_enabled(NULL); + return handle_ticker_enabled(nullptr); } }; -class SinguPoseStand : public view_listener_t +class SinguPoseStand final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { if (current_pose.isNull()) set_current_pose("038fcec9-5ebd-8a8e-0e2e-6e71a0a1ac53"); else - handle_pose_stand_stop(NULL); + handle_pose_stand_stop(nullptr); return true; } }; -class SinguCheckPoseStand : public view_listener_t +class SinguCheckPoseStand final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - gMenuHolder->findControl(userdata["control"].asString())->setValue(handle_check_pose(NULL)); + gMenuHolder->findControl(userdata["control"].asString())->setValue(handle_check_pose(nullptr)); return true; } }; -class SinguRebake : public view_listener_t +class SinguRebake final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - handle_rebake_textures(NULL); + handle_rebake_textures(nullptr); return true; } }; -class SinguVisibleDebugConsole : public view_listener_t +class SinguVisibleDebugConsole final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerRegion* region = gAgent.getRegion(); gMenuHolder->findControl(userdata["control"].asString())->setValue(region && !(region->getCapability("SimConsoleAsync").empty() || region->getCapability("SimConsole").empty())); @@ -8830,301 +8973,674 @@ class SinguVisibleDebugConsole : public view_listener_t } }; -class VisibleSecondLife : public view_listener_t +class SinguUrlAction final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - gMenuHolder->findControl(userdata["control"].asString())->setValue(gHippoGridManager->getCurrentGrid()->isSecondLife()); - return true; - } -}; - -class VisibleNotSecondLife : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - gMenuHolder->findControl(userdata["control"].asString())->setValue(!gHippoGridManager->getConnectedGrid()->isSecondLife()); + LLUrlAction::clickAction(userdata.asStringRef(), true); return true; } }; -LLScrollListCtrl* get_focused_list() +void show_inv_floater(const LLSD& userdata, const std::string& field) { - LLScrollListCtrl* list = dynamic_cast(gFocusMgr.getKeyboardFocus()); - llassert(list); // This listener only applies to lists - return list; + LFFloaterInvPanel::toggle(LLSD().with(field, userdata)); } -S32 get_focused_list_num_selected() +static void visible_inv_floater(const LLSD& userdata, const std::string& field) { - if (LLScrollListCtrl* list = get_focused_list()) - return list->getNumSelected(); - return 0; + gMenuHolder->findControl(userdata["control"].asString())->setValue(!!LFFloaterInvPanel::getInstance(LLSD().with(field, userdata["data"]))); } -const LLUUID get_focused_list_id_selected() +class ShowInvFloaterID final : public view_listener_t { - if (LLScrollListCtrl* list = get_focused_list()) - return list->getStringUUIDSelectedItem(); - return LLUUID::null; -} - -const uuid_vec_t get_focused_list_ids_selected() -{ - if (LLScrollListCtrl* list = get_focused_list()) - return list->getSelectedIDs(); - return uuid_vec_t(); -} - -const LLWString get_slurl_for(const LLUUID& id, bool group) -{ - std::string str("secondlife:///app/"); - str += group ? "group/" : "agent/"; - return utf8str_to_wstring(str + id.asString() + "/about"); -} - -void copy_profile_uri(const LLUUID& id, bool group) -{ - gViewerWindow->getWindow()->copyTextToClipboard(get_slurl_for(id, group)); -} - -class ListEnableAnySelected : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - gMenuHolder->findControl(userdata["control"].asString())->setValue(get_focused_list_num_selected()); - return true; - } -}; - -class ListEnableMultipleSelected : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - gMenuHolder->findControl(userdata["control"].asString())->setValue(get_focused_list_num_selected() > 1); + show_inv_floater(userdata, "id"); return true; } }; -class ListEnableSingleSelected : public view_listener_t +class VisibleInvFloaterID final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - gMenuHolder->findControl(userdata["control"].asString())->setValue(get_focused_list_num_selected() == 1); + visible_inv_floater(userdata, "id"); return true; } }; -class ListEnableCall : public view_listener_t +class ShowInvFloaterName final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLScrollListCtrl* list = get_focused_list(); - if (!list) return false; - gMenuHolder->findControl(userdata["control"].asString())->setValue(LLAvatarActions::canCall()); + show_inv_floater(userdata, "name"); return true; } }; -class ListEnableIsFriend : public view_listener_t +class VisibleInvFloaterName final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - gMenuHolder->findControl(userdata["control"].asString())->setValue(LLAvatarActions::isFriend(get_focused_list_id_selected())); + visible_inv_floater(userdata, "name"); return true; } }; -class ListEnableIsNotFriend : public view_listener_t +class ShowInvFloaterType final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - gMenuHolder->findControl(userdata["control"].asString())->setValue(!LLAvatarActions::isFriend(get_focused_list_id_selected())); + show_inv_floater(userdata, "type"); return true; } }; -class ListEnableMute : public view_listener_t +class VisibleInvFloaterType final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - const uuid_vec_t& ids = get_focused_list_ids_selected(); - bool can_block = true; - for (uuid_vec_t::const_iterator it = ids.begin(); can_block && it != ids.end(); ++it) - can_block = LLAvatarActions::canBlock(*it); - gMenuHolder->findControl(userdata["control"].asString())->setValue(can_block); + visible_inv_floater(userdata, "type"); return true; } }; -class ListEnableOfferTeleport : public view_listener_t +void show_web_floater(const std::string& type) { - bool handleEvent(LLPointer event, const LLSD& userdata) + auto p = LLFloaterWebContent::Params(); + if (!type.empty()) p.id = type; + if (type == "marketplace") { - gMenuHolder->findControl(userdata["control"].asString())->setValue(LLAvatarActions::canOfferTeleport(get_focused_list_ids_selected())); - return true; + if (gHippoGridManager->getConnectedGrid()->isSecondLife()) + p.url = "https://marketplace.secondlife.com"; + else if (LLViewerRegion* region = gAgent.getRegion()) + { + LLSD info; + region->getSimulatorFeatures(info); + p.url = info["MarketplaceURL"]; + } } -}; - -class ListVisibleWebProfile : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) + else if (!type.empty() && type != "dict web") { - gMenuHolder->findControl(userdata["control"].asString())->setValue(get_focused_list_num_selected() && !(gSavedSettings.getBOOL("UseWebProfiles") || gSavedSettings.getString("WebProfileURL").empty())); - return true; + p.url = type; // Simple web floaters with direct urls } -}; + LLFloaterWebContent::showInstance(type, p); +} -void ban_from_group(const uuid_vec_t& ids); -class ListBanFromGroup : public view_listener_t +class ShowWebFloater final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - ban_from_group(get_focused_list_ids_selected()); + show_web_floater(userdata.asStringRef()); return true; } }; -class ListCopySLURL : public view_listener_t +class VisibleSecondLife final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - copy_profile_uri(get_focused_list_id_selected(), false); + gMenuHolder->findControl(userdata["control"].asString())->setValue(gHippoGridManager->getCurrentGrid()->isSecondLife()); return true; } }; -class ListCopyUUIDs : public view_listener_t +class VisibleNotSecondLife final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::copyUUIDs(get_focused_list_ids_selected()); + gMenuHolder->findControl(userdata["control"].asString())->setValue(!gHippoGridManager->getConnectedGrid()->isSecondLife()); return true; } }; -class ListInviteToGroup : public view_listener_t +template T* get_focused() { - bool handleEvent(LLPointer event, const LLSD& userdata) + T* t = +#ifdef SHOW_ASSERT + dynamic_cast +#else + static_cast +#endif + (gFocusMgr.getKeyboardFocus()); + llassert(t); // This listener only applies to T + return t; +} + +const JCFloaterAreaSearch::ObjectData* get_obj_data(const LLUUID& id) +{ + auto areasearch = JCFloaterAreaSearch::findInstance(); + return areasearch ? areasearch->getObjectData(id) : nullptr; +} + +const LLUUID& get_obj_owner(const LLUUID& id, const JCFloaterAreaSearch::ObjectData* obj_data = nullptr, const LLViewerObject* objp = nullptr) +{ + if (const auto& obj = objp ? objp : gObjectList.findObject(id)) // Viewer Object is more likely to be up to date + return obj->mOwnerID; + if (const auto& obj = obj_data ? obj_data : get_obj_data(id)) // Fall back on Object Data + return obj->owner_id; + return LLUUID::null; +} + +const std::string get_obj_owner_slurl(const LLUUID& obj_id, const std::string& name = LLStringUtil::null, bool* group_ownedp = nullptr) +{ + bool group_owned; + LLUUID owner; + if (!group_ownedp) + { + if (const auto& obj = gObjectList.findObject(obj_id)) // Viewer Object is more likely to be up to date + { + owner = obj->mOwnerID; + group_owned = obj->flagObjectGroupOwned(); + } + else if (const auto& obj = get_obj_data(obj_id)) // Fall back on Object Data + { + owner = obj->owner_id; + group_owned = owner == obj->group_id; + } + else return name; + } + else + { + owner = get_obj_owner(obj_id); + group_owned = *group_ownedp; + } + return owner.isNull() ? name + : group_owned ? LLGroupActions::getSLURL(owner) + : LLAvatarActions::getSLURL(owner); +} + +const std::string get_obj_slurl(const LLUUID& id, const std::string& name = LLStringUtil::null) +{ + const auto& obj_data = get_obj_data(id); // Needed for object name + const auto& obj = gObjectList.findObject(id); // Has all the other object data + if (!obj_data && !obj && name.empty()) + return name; // Not enough data to show, empty string to show failure, if we had a name we could pair it with the ID at least + + LLSD sdQuery; + + sdQuery["name"] = !name.empty() ? name : + obj_data ? obj_data->name : LLTrans::getString("land_type_unknown"); + + const auto& owner = get_obj_owner(id, obj_data, obj); + if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) && (owner != gAgentID)) + sdQuery["rlv_shownames"] = true; + + sdQuery["owner"] = owner; + sdQuery["group_owned"] = obj ? obj->flagObjectGroupOwned() : obj_data && obj_data->group_id == owner; + + if (const auto region = obj ? obj->getRegion() : nullptr) + sdQuery["slurl"] = LLSLURL(region->getName(), obj->getPositionAgent()).getLocationString(); + + return LLSLURL("objectim", id, LLURI::mapToQueryString(sdQuery)).getSLURLString(); +} + +const std::string get_slurl_for(const LLUUID& id, const LFIDBearer::Type& type) +{ + switch (type) + { + case LFIDBearer::GROUP: return LLGroupActions::getSLURL(id); + case LFIDBearer::AVATAR: return LLAvatarActions::getSLURL(id); + case LFIDBearer::OBJECT: return get_obj_slurl(id); + case LFIDBearer::EXPERIENCE: return LLSLURL("experience", id, "profile").getSLURLString(); + default: return LLStringUtil::null; + } +} + +const LLWString get_wslurl_for(const LLUUID& id, const LFIDBearer::Type& type) +{ + return utf8str_to_wstring(get_slurl_for(id, type)); +} + +void copy_profile_uri(const LLUUID& id, const LFIDBearer::Type& type) +{ + gViewerWindow->getWindow()->copyTextToClipboard(get_wslurl_for(id, type)); +} + +class ListEnableAnySelected final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gMenuHolder->findControl(userdata["control"].asString())->setValue(LFIDBearer::getActiveNumSelected() != 0); + return true; + } +}; + +class ListEnableMultipleSelected final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gMenuHolder->findControl(userdata["control"].asString())->setValue(LFIDBearer::getActiveNumSelected() > 1); + return true; + } +}; + +class ListEnableSingleSelected final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gMenuHolder->findControl(userdata["control"].asString())->setValue(LFIDBearer::getActiveNumSelected() == 1); + return true; + } +}; + +class ListEnableCall final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gMenuHolder->findControl(userdata["control"].asString())->setValue(LLAvatarActions::canCall()); + return true; + } +}; + +class ListEnableIsFriend final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gMenuHolder->findControl(userdata["control"].asString())->setValue(LLAvatarActions::isFriend(LFIDBearer::getActiveSelectedID())); + return true; + } +}; + +class ListEnableIsNotFriend final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gMenuHolder->findControl(userdata["control"].asString())->setValue(!LLAvatarActions::isFriend(LFIDBearer::getActiveSelectedID())); + return true; + } +}; + +class ListEnableUnmute final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + bool are_blocked = false; + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + if (are_blocked = LLAvatarActions::isBlocked(id)) // If any are blocked, allow unblocking + break; + + gMenuHolder->findControl(userdata["control"].asString())->setValue(are_blocked); + return true; + } +}; + +class ListEnableMute final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + bool blockable = false; + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + { + if (!LLAvatarActions::canBlock(id)) // Exit early only when someone is unblockable + { + blockable = false; + break; + } + else if (blockable) // At least one is unblocked, keep looking for unblockables + continue; + + blockable = !LLAvatarActions::isBlocked(id); + } + + gMenuHolder->findControl(userdata["control"].asString())->setValue(blockable); + return true; + } +}; + +class ListEnableOfferTeleport final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gMenuHolder->findControl(userdata["control"].asString())->setValue(LLAvatarActions::canOfferTeleport(LFIDBearer::getActiveSelectedIDs())); + return true; + } +}; + +class ListVisibleWebProfile final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gMenuHolder->findControl(userdata["control"].asString())->setValue(LFIDBearer::getActiveNumSelected() && !(gSavedSettings.getBOOL("UseWebProfiles") || gSavedSettings.getString("WebProfileURL").empty())); + return true; + } +}; + +void ban_from_group(const uuid_vec_t& ids); +class ListBanFromGroup final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + ban_from_group(LFIDBearer::getActiveSelectedIDs()); + return true; + } +}; + +void copy_from_ids(const uuid_vec_t & ids, std::function func); + +uuid_vec_t get_active_owner_ids() +{ + uuid_vec_t ret; + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + { + const auto& owner_id = get_obj_owner(id); + if (owner_id.notNull()) ret.push_back(owner_id); + } + return ret; +} + +const LLUUID& get_active_owner_id() +{ + return get_obj_owner(LFIDBearer::getActiveSelectedID()); +} + +class ListCopyNames final : public view_listener_t +{ + static std::string getGroupName(const LLUUID& id) + { + std::string ret; + gCacheName->getGroupName(id, ret); + return ret; + } + + static std::string getAvatarName(const LLUUID& id) + { + std::string ret; + LLAvatarNameCache::getNSName(id, ret); + return ret; + } + + static std::string getObjectName(const LLUUID& id) + { + const auto& obj_data = get_obj_data(id); + return obj_data ? obj_data->name : LLStringUtil::null; + } + + static std::string getExperienceName(const LLUUID& id) + { + return LLExperienceCache::instance().get(id)[LLExperienceCache::NAME]; + } + + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + LLWString str; + const auto& type = LFIDBearer::getActiveType(); + bool owner = !userdata.asBoolean(); + copy_from_ids(owner ? get_active_owner_ids() : LFIDBearer::getActiveSelectedIDs(), type == LFIDBearer::GROUP ? getGroupName : + type == LFIDBearer::OBJECT ? owner ? getAvatarName : getObjectName : + type == LFIDBearer::EXPERIENCE ? getExperienceName : + getAvatarName); + if (!str.empty()) LLView::getWindow()->copyTextToClipboard(str); + return true; + } +}; +class ListCopySLURL final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + bool owner = !userdata.asBoolean(); + copy_profile_uri(owner ? get_active_owner_id() : LFIDBearer::getActiveSelectedID(), owner ? LFIDBearer::AVATAR : LFIDBearer::getActiveType()); + return true; + } +}; + +const LLUUID& active_owner_or_id(const LLSD& userdata) +{ + return !userdata.asBoolean() ? get_active_owner_id() : LFIDBearer::getActiveSelectedID(); +} + +#define active_owners_or_ids(userdata) !userdata.asBoolean() ? get_active_owner_ids() : LFIDBearer::getActiveSelectedIDs() + +class ListCopyUUIDs final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + LLAvatarActions::copyUUIDs(active_owners_or_ids(userdata)); + return true; + } +}; + +class ListInviteToGroup final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + LLAvatarActions::inviteToGroup(active_owners_or_ids(userdata)); + return true; + } +}; + +class ListOfferTeleport final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + LLAvatarActions::offerTeleport(active_owners_or_ids(userdata)); + return true; + } +}; + +class ListPay final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::inviteToGroup(get_focused_list_ids_selected()); + LLAvatarActions::pay(active_owner_or_id(userdata)); return true; } }; -class ListOfferTeleport : public view_listener_t +class ListRemoveFriend final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::offerTeleport(get_focused_list_ids_selected()); + LLAvatarActions::removeFriendDialog(active_owner_or_id(userdata)); return true; } }; -class ListPay : public view_listener_t +class ListRequestFriendship final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::pay(get_focused_list_id_selected()); + LLAvatarActions::requestFriendshipDialog(active_owner_or_id(userdata)); return true; } }; -class ListRemoveFriend : public view_listener_t +class ListRequestTeleport final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::removeFriendDialog(get_focused_list_id_selected()); + LLAvatarActions::teleportRequest(active_owner_or_id(userdata)); return true; } }; -class ListRequestFriendship : public view_listener_t +class ListShare final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::requestFriendshipDialog(get_focused_list_id_selected()); + LLAvatarActions::share(active_owner_or_id(userdata)); return true; } }; -class ListRequestTeleport : public view_listener_t +bool can_show_web_profile() +{ + return !gSavedSettings.getString("WebProfileURL").empty(); +} + +void show_log_browser(const LLUUID& id, const LFIDBearer::Type& type); +class ListShowLog final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::teleportRequest(get_focused_list_id_selected()); + const auto& type = userdata.asBoolean() ? LFIDBearer::getActiveType() : LFIDBearer::AVATAR; + for (const LLUUID& id : active_owners_or_ids(userdata)) + show_log_browser(id, type); return true; } }; -class ListShare : public view_listener_t +class ListShowProfile final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::share(get_focused_list_id_selected()); + switch (LFIDBearer::getActiveType()) + { + case LFIDBearer::AVATAR: LLAvatarActions::showProfiles(LFIDBearer::getActiveSelectedIDs()); break; + case LFIDBearer::GROUP: LLGroupActions::showProfiles(LFIDBearer::getActiveSelectedIDs()); break; + case LFIDBearer::OBJECT: + if (userdata.asBoolean()) + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) LLUrlAction::openURL(get_slurl_for(id, LFIDBearer::OBJECT)); + else // Owners + LLAvatarActions::showProfiles(get_active_owner_ids()); + break; + case LFIDBearer::EXPERIENCE: for (const auto& id : LFIDBearer::getActiveSelectedIDs()) LLFloaterExperienceProfile::showInstance(id); break; + default: break; + } return true; } }; -class ListShowProfile : public view_listener_t +class ListShowWebProfile final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::showProfiles(get_focused_list_ids_selected()); + LLAvatarActions::showProfiles(active_owners_or_ids(userdata), true); return true; } }; -class ListShowWebProfile : public view_listener_t +class ListStartAdhocCall final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::showProfiles(get_focused_list_ids_selected(), true); + LLAvatarActions::startAdhocCall(active_owners_or_ids(userdata)); return true; } }; -class ListStartAdhocCall : public view_listener_t +class ListStartCall final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::startAdhocCall(get_focused_list_ids_selected()); + (LFIDBearer::getActiveType() == LFIDBearer::GROUP ? LLGroupActions::startCall : LLAvatarActions::startCall)(active_owner_or_id(userdata)); return true; } }; -class ListStartCall : public view_listener_t +class ListStartConference final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::startCall(get_focused_list_id_selected()); + LLAvatarActions::startConference(active_owners_or_ids(userdata)); return true; } }; -class ListStartConference : public view_listener_t +class ListStartIM final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::startConference(get_focused_list_ids_selected()); + const auto&& im = LFIDBearer::getActiveType() == LFIDBearer::GROUP ? [](const LLUUID& id) { LLGroupActions::startIM(id); } : LLAvatarActions::startIM; + for (const auto& id : active_owners_or_ids(userdata)) + im(id); return true; } }; -class ListStartIM : public view_listener_t +const LLVector3d& get_av_pos(const LLUUID& id); +const LLVector3d get_obj_pos(const LLUUID& id) { - bool handleEvent(LLPointer event, const LLSD& userdata) + if (const auto& obj = gObjectList.findObject(id)) + return obj->getPositionGlobal(); + return LLVector3d::zero; +} +static const LLVector3d get_active_pos(const LLSD& userdata) +{ + const auto& id = active_owner_or_id(userdata); + if (userdata.asBoolean() && LFIDBearer::getActiveType() == LFIDBearer::OBJECT) + return get_obj_pos(id); + return get_av_pos(id); +} + +class ListTeleportTo final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLAvatarActions::startIM(get_focused_list_id_selected()); + const auto& pos = get_active_pos(userdata); + if (!pos.isExactlyZero()) + gAgent.teleportViaLocation(pos); return true; } }; -class ListAbuseReport : public view_listener_t +class ListStalk final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - LLFloaterReporter::showFromObject(get_focused_list_id_selected()); + LLAvatarActions::showOnMap(active_owner_or_id(userdata)); + return true; + } +}; + +class ListStalkable final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + BOOL is_agent_mappable(const LLUUID& agent_id); + const auto& ids = active_owners_or_ids(userdata["data"]); + gMenuHolder->findControl(userdata["control"].asString())->setValue(ids.size() == 1 && is_agent_mappable(ids[0])); + return true; + } +}; + +class ListAbuseReport final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + if (LFIDBearer::getActiveType() == LFIDBearer::EXPERIENCE) + LLFloaterReporter::showFromExperience(LFIDBearer::getActiveSelectedID()); + else + LLFloaterReporter::showFromObject(active_owner_or_id(userdata)); + return true; + } +}; + +void set_experience_permission(const char* perm, const uuid_vec_t& ids) +{ + if (!gAgent.getRegion()) return; + auto& cache = LLExperienceCache::instance(); + for (const auto& id : ids) + cache.setExperiencePermission(id, perm, boost::bind(LLFloaterExperienceProfile::experiencePermissionResults, id, _1)); +} + +class ListExperienceAllow final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + set_experience_permission("Allow", LFIDBearer::getActiveSelectedIDs()); + return true; + } +}; + +class ListExperienceForget final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + if (!gAgent.getRegion()) return true; + auto& cache = LLExperienceCache::instance(); + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + cache.forgetExperiencePermission(id, boost::bind(LLFloaterExperienceProfile::experiencePermissionResults, id, _1)); + return true; + } +}; + +class ListExperienceBlock final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + set_experience_permission("Block", LFIDBearer::getActiveSelectedIDs()); return true; } }; @@ -9147,71 +9663,365 @@ void parcel_mod_notice_callback(const uuid_vec_t& ids, S32 choice, boost::functi cb(*it, choice); } +bool is_nearby(const LLUUID& id); +class ListIsNearby final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + const auto& data = userdata["data"]; + const auto& id = active_owner_or_id(data); + gMenuHolder->findControl(userdata["control"].asString())->setValue((LFIDBearer::getActiveType() == LFIDBearer::OBJECT && data.asBoolean()) ? !!gObjectList.findObject(id) : is_nearby(id)); + return true; + } +}; + +class ListFollow final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gAgent.startFollowPilot(active_owner_or_id(userdata), true, gSavedSettings.getF32("SinguFollowDistance")); + return true; + } +}; + +class ListGoTo final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + const auto& pos = get_active_pos(userdata); + if (!pos.isExactlyZero()) + handle_go_to(pos); + return true; + } +}; + +void track_av(const LLUUID& id); +class ListTrack final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + track_av(active_owner_or_id(userdata)); + return true; + } +}; + void send_eject(const LLUUID& avatar_id, bool ban); -class ListEject : public view_listener_t +void confirm_eject(const uuid_vec_t& ids) +{ + LLNotificationsUtil::add("EjectAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_eject)); +} +class ListEject final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - const uuid_vec_t& ids = get_focused_list_ids_selected(); - LLNotificationsUtil::add("EjectAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_eject)); + confirm_eject(active_owners_or_ids(userdata)); return true; } }; void send_freeze(const LLUUID& avatar_id, bool freeze); -class ListFreeze : public view_listener_t +void confirm_freeze(const uuid_vec_t& ids) { - bool handleEvent(LLPointer event, const LLSD& userdata) + LLNotificationsUtil::add("FreezeAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_freeze)); +} +class ListFreeze final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override { - const uuid_vec_t& ids = get_focused_list_ids_selected(); - LLNotificationsUtil::add("FreezeAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_freeze)); + confirm_freeze(active_owners_or_ids(userdata)); return true; } }; -void estate_bulk_eject(const uuid_vec_t& ids, bool ban, S32 zero) +void send_estate_message(const std::string request, const std::vector& strings) { - if (ids.empty() || zero != 0) return; - std::vector strings(2, gAgentID.asString()); // [0] = our agent id - for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) + LLRegionInfoModel::sendEstateOwnerMessage(gMessageSystem, request, LLFloaterRegionInfo::getLastInvoice(), strings); +} + +void estate_bulk_eject(const uuid_vec_t& ids, bool ban, S32 option) +{ + if (ids.empty() || option == (ban ? 1 : 2)) return; + const bool tphome(option == 1); + const std::string agent(tphome ? gAgentID.asString() : LLStringUtil::null); + std::vector strings; + if (!tphome) strings.reserve(ids.size()); + for (const LLUUID& id : ids) { - LLUUID id(*it); if (id.isNull()) continue; - strings[1] = id.asString(); // [1] = target agent id - - LLRegionInfoModel::sendEstateOwnerMessage(gMessageSystem, "teleporthomeuser", LLFloaterRegionInfo::getLastInvoice(), strings); + const std::string idstr(id.asString()); + if (tphome) + send_estate_message("teleporthomeuser", {agent, idstr}); + else + strings.push_back(idstr); if (ban) - LLPanelEstateInfo::sendEstateAccessDelta(ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_NO_REPLY, id); + LLPanelEstateAccess::sendEstateAccessDelta(ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_NO_REPLY, id); } + if (!tphome) send_estate_message("kickestate", strings); } -class ListEstateBan : public view_listener_t +void confirm_estate_ban(const uuid_vec_t& ids) +{ + LLNotificationsUtil::add("EstateBanUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, true, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2))); +} +class ListEstateBan final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + confirm_estate_ban(active_owners_or_ids(userdata)); + return true; + } +}; + +void confirm_estate_kick(const uuid_vec_t& ids) +{ + LLNotificationsUtil::add("EstateKickUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, false, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2))); +} +class ListEstateEject final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + confirm_estate_kick(active_owners_or_ids(userdata)); + return true; + } +}; + +class ListToggleMute final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + for (const auto& id : active_owners_or_ids(userdata)) + LLAvatarActions::toggleBlock(id); + return true; + } +}; + +class ListIsInGroup final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - const uuid_vec_t& ids = get_focused_list_ids_selected(); - LLNotificationsUtil::add("EstateBanUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, true, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2))); + auto in_group = false; + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + if (!(in_group = LLGroupActions::isInGroup(id))) + break; + gMenuHolder->findControl(userdata["control"].asString())->setValue(in_group); return true; } }; -class ListEstateEject : public view_listener_t +class ListNotInGroup final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - const uuid_vec_t& ids = get_focused_list_ids_selected(); - LLNotificationsUtil::add("EstateKickUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, false, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2))); + auto in_group = true; + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + if (in_group = LLGroupActions::isInGroup(id)) + break; + gMenuHolder->findControl(userdata["control"].asString())->setValue(!in_group); return true; } }; -class ListToggleMute : public view_listener_t +class ListLeave final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { - const uuid_vec_t& ids = get_focused_list_ids_selected(); - for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) - LLAvatarActions::toggleBlock(*it); + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + LLGroupActions::leave(id); + return true; + } +}; + +class ListJoin final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + LLGroupActions::join(id); + return true; + } +}; + +class ListActivate final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + LLGroupActions::activate(id); + return true; + } +}; + +class ListObjectCamTo final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gAgentCamera.lookAtObject(LFIDBearer::getActiveSelectedID(), false); + return true; + } +}; + +class ListObjectSit final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gAgent.stopAutoPilot(true); + handle_object_sit(gObjectList.findObject(LFIDBearer::getActiveSelectedID())); + return true; + } +}; + +class ListObjectPay final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + handle_give_money_dialog(gObjectList.findObject(LFIDBearer::getActiveSelectedID())); + return true; + } +}; + +class ListObjectEnablePay final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + const auto& ids = LFIDBearer::getActiveSelectedIDs(); + gMenuHolder->findControl(userdata["control"].asString())->setValue(ids.size() == 1 && enable_pay_object(gObjectList.findObject(ids[0]))); + return true; + } +}; + +void list_for_each_object(std::function func) +{ + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + if (auto obj = gObjectList.findObject(id)) + func(obj); +} + +class ListObjectTouch final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + list_for_each_object([](LLViewerObject* obj) { if (enable_object_touch(obj)) handle_object_touch(obj); }); + return true; + } +}; + +bool list_has_valid_object(std::function func) +{ + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + if (func(gObjectList.findObject(id))) + return true; // First is fine enough, we'll use all we can + return false; +} + +// One object must have touch sensor +class ListObjectEnableTouch final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gMenuHolder->findControl(userdata["control"].asString())->setValue(list_has_valid_object([](LLViewerObject* obj){ return enable_object_touch(obj); })); + return true; + } +}; + +class ListObjectEdit final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + std::vector objs; + auto func = rlv_handler_t::isEnabled() ? static_cast>([&objs](LLViewerObject* obj) { if (gRlvHandler.canEdit(obj)) objs.push_back(obj); }) : [&objs](LLViewerObject* obj) { if (obj) objs.push_back(obj); }; + list_for_each_object(func); + + if (objs.empty()) return true; + + bool new_selection = userdata.asBoolean(); + + auto& selmgr = LLSelectMgr::instance(); + if (new_selection) selmgr.deselectAll(); + + auto selection = new_selection ? nullptr : selmgr.getSelection(); + auto old_primary = selection ? selection->getPrimaryObject() : nullptr; + for (const auto& obj : objs) + selmgr.selectObjectAndFamily(obj, true); + + if (old_primary) selmgr.selectObjectAndFamily(old_primary); + + if (new_selection) handle_object_edit(); + return true; + } +}; + +class ListObjectCanEdit final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + bool new_selection = userdata["data"].asBoolean(); + auto& selmgr = LLSelectMgr::instance(); + auto selection = new_selection ? nullptr : selmgr.getSelection(); + bool has_old_selection = selection && !selection->isEmpty() && !selection->isAttachment(); + auto func = rlv_handler_t::isEnabled() ? static_cast>([](LLViewerObject* obj) { return !!gRlvHandler.canEdit(obj); }) : [](LLViewerObject* obj) { return !!obj; }; + gMenuHolder->findControl(userdata["control"].asString()) + ->setValue((new_selection || has_old_selection) && list_has_valid_object(func)); + return true; + } +}; + +class ListObjectDerender final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + const std::string& unknown = LLTrans::getString("land_type_unknown"); + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + { + const auto& obj_data = get_obj_data(id); // Needed for object name + add_object_to_blacklist(id, obj_data ? obj_data->name : unknown); + } + + return true; + } +}; + +class MediaCtrlCopyURL final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + get_focused()->onCopyURL(); + return true; + } +}; + +class MediaCtrlWebInspector final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + get_focused()->onOpenWebInspector(); + return true; + } +}; + +class MediaCtrlViewSource final : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + get_focused()->onShowSource(); + return true; + } +}; + +struct MarketplaceViewSortAction final : view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + LLFloaterMarketplaceListings::findInstance()->mPanelListings->onViewSortMenuItemClicked(userdata); + return true; + } +}; + +struct MarketplaceViewSortCheckItem final : view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) override + { + gMenuHolder->findControl(userdata["control"].asString()) + ->setValue(LLFloaterMarketplaceListings::findInstance()->mPanelListings->onViewSortMenuItemCheck(userdata["data"])); return true; } }; @@ -9225,12 +10035,12 @@ void addMenu(view_listener_t *menu, const std::string& name) void initialize_menus() { // A parameterized event handler used as ctrl-8/9/0 zoom controls below. - class LLZoomer : public view_listener_t + class LLZoomer final : public view_listener_t { public: // The "mult" parameter says whether "val" is a multiplier or used to set the value. LLZoomer(F32 val, bool mult=true) : mVal(val), mMult(mult) {} - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLViewerCamera& inst(LLViewerCamera::instance()); F32 new_fov_rad = mMult ? inst.getDefaultFOV() * mVal : mVal; @@ -9243,6 +10053,8 @@ void initialize_menus() bool mMult; }; + addMenu(new LLUploadCostCalculator(), "Upload.CalculateCosts"); + // File menu init_menu_file(); @@ -9388,6 +10200,9 @@ void initialize_menus() addMenu(new LLAvatarSendIM(), "Avatar.SendIM"); addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse"); addMenu(new LLObjectEnableMute(), "Avatar.EnableMute"); + addMenu(new LLAvatarResetSkeleton(), "Avatar.ResetSkeleton"); + addMenu(new LLAvatarEnableResetSkeleton(), "Avatar.EnableResetSkeleton"); + addMenu(new LLAvatarResetSkeletonAndAnimations(), "Avatar.ResetSkeletonAndAnimations"); addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend"); addMenu(new LLAvatarEnableFreezeEject(), "Avatar.EnableFreezeEject"); addMenu(new LLAvatarCopyUUID(), "Avatar.CopyUUID"); @@ -9413,6 +10228,7 @@ void initialize_menus() addMenu(new LLOHGOD(), "Object.EnableExplode"); add_wave_listeners(); add_dae_listeners(); + addMenu(new LLObjectFollow(), "Object.Follow"); // addMenu(new LLObjectMute(), "Object.Mute"); addMenu(new LLObjectBuy(), "Object.Buy"); @@ -9491,6 +10307,17 @@ void initialize_menus() addMenu(new SinguCheckPoseStand(), "CheckPoseStand"); addMenu(new SinguRebake(), "Rebake"); addMenu(new SinguVisibleDebugConsole(), "VisibleRegionDebugConsole"); + addMenu(new SinguUrlAction(), "URLAction"); + addMenu(new LLSyncAnimations(), "Tools.ResyncAnimations"); + + addMenu(new ShowInvFloaterID, "ShowInvFloater.ID"); + addMenu(new ShowInvFloaterName, "ShowInvFloater.Name"); + addMenu(new ShowInvFloaterType, "ShowInvFloater.Type"); + addMenu(new VisibleInvFloaterID, "InvFloaterVisible.ID"); + addMenu(new VisibleInvFloaterName, "InvFloaterVisible.Name"); + addMenu(new VisibleInvFloaterType, "InvFloaterVisible.Type"); + + addMenu(new ShowWebFloater, "ShowWebFloater"); // [RLVa:KB] - Checked: 2010-01-18 (RLVa-1.1.0m) | Added: RLVa-1.1.0m | OK if (rlv_handler_t::isEnabled()) @@ -9509,10 +10336,12 @@ void initialize_menus() addMenu(new ListEnableCall(), "List.EnableCall"); addMenu(new ListEnableIsFriend(), "List.EnableIsFriend"); addMenu(new ListEnableIsNotFriend(), "List.EnableIsNotFriend"); + addMenu(new ListEnableUnmute(), "List.EnableUnmute"); addMenu(new ListEnableMute(), "List.EnableMute"); addMenu(new ListEnableOfferTeleport(), "List.EnableOfferTeleport"); addMenu(new ListVisibleWebProfile(), "List.VisibleWebProfile"); addMenu(new ListBanFromGroup(), "List.BanFromGroup"); + addMenu(new ListCopyNames(), "List.CopyNames"); addMenu(new ListCopySLURL(), "List.CopySLURL"); addMenu(new ListCopyUUIDs(), "List.CopyUUIDs"); addMenu(new ListInviteToGroup(), "List.InviteToGroup"); @@ -9522,32 +10351,67 @@ void initialize_menus() addMenu(new ListRequestFriendship(), "List.RequestFriendship"); addMenu(new ListRequestTeleport(), "List.RequestTeleport"); addMenu(new ListShare(), "List.Share"); + addMenu(new ListShowLog(), "List.ShowLog"); addMenu(new ListShowProfile(), "List.ShowProfile"); addMenu(new ListShowWebProfile(), "List.ShowWebProfile"); addMenu(new ListStartAdhocCall(), "List.StartAdhocCall"); addMenu(new ListStartCall(), "List.StartCall"); addMenu(new ListStartConference(), "List.StartConference"); addMenu(new ListStartIM(), "List.StartIM"); + addMenu(new ListStalk, "List.Stalk"); + addMenu(new ListStalkable, "List.Stalkable"); + addMenu(new ListTeleportTo, "List.TeleportTo"); addMenu(new ListAbuseReport(), "List.AbuseReport"); + addMenu(new ListIsNearby, "List.IsNearby"); + addMenu(new ListFollow, "List.Follow"); + addMenu(new ListGoTo, "List.GoTo"); + addMenu(new ListTrack, "List.Track"); addMenu(new ListEject(), "List.ParcelEject"); addMenu(new ListFreeze(), "List.Freeze"); addMenu(new ListEstateBan(), "List.EstateBan"); addMenu(new ListEstateEject(), "List.EstateEject"); addMenu(new ListToggleMute(), "List.ToggleMute"); + addMenu(new ListIsInGroup, "List.IsInGroup"); + addMenu(new ListNotInGroup, "List.NotInGroup"); + addMenu(new ListLeave, "List.Leave"); + addMenu(new ListJoin, "List.Join"); + addMenu(new ListActivate, "List.Activate"); + addMenu(new ListObjectCamTo, "List.Object.CamTo"); + addMenu(new ListObjectSit, "List.Object.Sit"); + addMenu(new ListObjectPay, "List.Object.Pay"); + addMenu(new ListObjectEnablePay, "List.Object.EnablePay"); + addMenu(new ListObjectTouch, "List.Object.Touch"); + addMenu(new ListObjectEnableTouch, "List.Object.EnableTouch"); + addMenu(new ListObjectEdit, "List.Object.Edit"); + addMenu(new ListObjectCanEdit, "List.Object.CanEdit"); + addMenu(new ListObjectDerender, "List.Object.Derender"); + addMenu(new ListExperienceAllow, "List.Experience.Allow"); + addMenu(new ListExperienceForget, "List.Experience.Forget"); + addMenu(new ListExperienceBlock, "List.Experience.Block"); add_radar_listeners(); - class LLViewBuildMode : public view_listener_t + LLTextEditor::addMenuListeners(); + + // Media Ctrl menus + addMenu(new MediaCtrlCopyURL(), "Copy.PageURL"); + addMenu(new MediaCtrlWebInspector(), "Open.WebInspector"); + addMenu(new MediaCtrlViewSource(), "Open.ViewSource"); + + addMenu(new MarketplaceViewSortAction, "Marketplace.ViewSort.Action"); + addMenu(new MarketplaceViewSortCheckItem, "Marketplace.ViewSort.CheckItem"); + + class LLViewBuildMode final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { LLToolMgr::getInstance()->toggleBuildMode(); return true; } }; - class LLViewCheckBuildMode : public view_listener_t + class LLViewCheckBuildMode final : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) + bool handleEvent(LLPointer event, const LLSD& userdata) override { gMenuHolder->findControl(userdata["control"].asString())->setValue(LLToolMgr::getInstance()->inEdit()); return true; @@ -9560,9 +10424,8 @@ void initialize_menus() void region_change() { // Remove current dynamic items - for (custom_menu_item_list_t::iterator i = gCustomMenuItems.begin(); i != gCustomMenuItems.end(); ++i) + for (auto item : gCustomMenuItems) { - LLMenuItemCallGL* item = (*i); item->getParent()->removeChild(item); delete item; } @@ -9601,7 +10464,7 @@ void parse_simulator_features() LLMenuGL* menu = dynamic_cast(marker->getParent()); if (!menu) continue; - std::list::iterator it = menu->find(marker); + auto it = menu->find(marker); for (LLSD::map_iterator j = i->second.beginMap(); j != i->second.endMap(); ++j) { diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index b45cf7633a..35aa889847 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -38,8 +38,10 @@ class LLUICtrl; class LLView; class LLParcelSelection; +class LLPickInfo; class LLObjectSelection; class LLSelectNode; +class LLViewerObject; void pre_init_menus(); void init_menus(); @@ -48,7 +50,6 @@ void cleanup_menus(); void show_debug_menus(); // checks for if menus should be shown first. void show_context_menu( S32 x, S32 y, MASK mask ); void show_build_mode_context_menu(S32 x, S32 y, MASK mask); -BOOL enable_save_into_inventory(void*); void handle_reset_view(); void handle_cut(void*); void handle_copy(void*); @@ -89,13 +90,14 @@ BOOL enable_god_full(void* user_data); BOOL enable_god_liaison(void* user_data); BOOL enable_god_basic(void* user_data); void set_underclothes_menu_options(); +void check_merchant_status(bool force = false); void exchange_callingcard(const LLUUID& dest_id); void handle_gestures(void*); void handle_sit_down(void*); void handle_object_build(void*); -void handle_object_touch(); +void handle_object_touch(LLViewerObject*, const LLPickInfo* const = nullptr); bool enable_object_open(); void handle_object_open(); @@ -133,10 +135,10 @@ void handle_toggle_flycam(); void handle_fake_away_status(void*); void handle_object_sit_or_stand(); -void handle_give_money_dialog(); -bool enable_pay_object(); +void handle_give_money_dialog(LLViewerObject*); +bool enable_pay_object(LLViewerObject*); bool enable_buy_object(); -bool handle_go_to(); +void handle_go_to(const LLVector3d& pos); // Export to XML or Collada void handle_export_selected( void * ); @@ -158,11 +160,8 @@ class LLViewerMenuHolderGL : public LLMenuHolderGL LLSafeHandle mObjectSelection; }; -extern const std::string SAVE_INTO_INVENTORY; - extern LLMenuBarGL* gMenuBarView; //extern LLView* gMenuBarHolder; -extern LLMenuGL* gPopupMenuView; extern LLViewerMenuHolderGL* gMenuHolder; extern LLMenuBarGL* gLoginMenuBarView; @@ -183,8 +182,8 @@ extern LLContextMenu* gAttachScreenPieMenu; extern LLContextMenu* gDetachScreenPieMenu; extern LLContextMenu* gAttachPieMenu; extern LLContextMenu* gDetachPieMenu; -extern LLContextMenu* gAttachBodyPartPieMenus[8]; -extern LLContextMenu* gDetachBodyPartPieMenus[8]; +extern LLContextMenu* gAttachPieMenu2; +extern LLContextMenu* gDetachPieMenu2; extern LLMenuItemCallGL* gAFKMenu; extern LLMenuItemCallGL* gBusyMenu; diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 46f9424029..ac35f39672 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -35,6 +35,7 @@ // project includes #include "llagent.h" +#include "llagentbenefits.h" #include "llagentcamera.h" #include "statemachine/aifilepicker.h" #include "llfloaterbvhpreview.h" @@ -68,7 +69,6 @@ // linden libraries #include "llassetuploadresponders.h" -#include "lleconomy.h" #include "llhttpclient.h" #include "llmemberlistener.h" #include "llnotificationsutil.h" @@ -95,20 +95,26 @@ class LLFileEnableSaveAs : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = gFloaterView->getFrontmost() && - gFloaterView->getFrontmost()->canSaveAs(); - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; - -class LLFileEnableUpload : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - bool new_value = gStatusBar && LLGlobalEconomy::Singleton::getInstance() && - gStatusBar->getBalance() >= LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + LLFloater* frontmost = gFloaterView->getFrontmost(); + if (frontmost && frontmost->hasChild("Save Preview As...", true)) // If we're the tearoff. + { + // Get the next frontmost sibling. + const LLView::child_list_const_iter_t kids_end = gFloaterView->endChild(); + LLView::child_list_const_iter_t kid = std::find(gFloaterView->beginChild(), kids_end, frontmost); + if (kids_end != kid) + { + for (++kid; kid != kids_end; ++kid) + { + LLView* viewp = *kid; + if (viewp->getVisible() && !viewp->isDead()) + { + frontmost = static_cast(viewp); + break; + } + } + } + } + gMenuHolder->findControl(userdata["control"].asString())->setValue(frontmost && frontmost->canSaveAs()); return true; } }; @@ -392,11 +398,15 @@ class LLFileUploadBulk : public view_listener_t // // Also fix single upload to charge first, then refund // - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - const char* notification_type = expected_upload_cost ? "BulkTemporaryUpload" : "BulkTemporaryUploadFree"; - LLSD args; - args["UPLOADCOST"] = gHippoGridManager->getConnectedGrid()->getUploadFee(); - LLNotificationsUtil::add(notification_type, args, LLSD(), onConfirmBulkUploadTemp); + const auto grid(gHippoGridManager->getConnectedGrid()); + if (grid->isSecondLife()) // For SL, we can't do temp uploads anymore. + { + doBulkUpload(); + } + else + { + LLNotificationsUtil::add("BulkTemporaryUpload", LLSD(), LLSD(), onConfirmBulkUploadTemp); + } return true; } @@ -411,10 +421,15 @@ class LLFileUploadBulk : public view_listener_t else // cancel return false; + doBulkUpload(enabled); + return true; + } + + static void doBulkUpload(bool temp = false) + { AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_ALL, "", "openfile", true); - filepicker->run(boost::bind(&LLFileUploadBulk::onConfirmBulkUploadTemp_continued, enabled, filepicker)); - return true; + filepicker->run(boost::bind(&LLFileUploadBulk::onConfirmBulkUploadTemp_continued, temp, filepicker)); } static void onConfirmBulkUploadTemp_continued(bool enabled, AIFilePicker* filepicker) @@ -437,7 +452,6 @@ class LLFileUploadBulk : public view_listener_t std::string display_name = LLStringUtil::null; LLAssetStorage::LLStoreAssetCallback callback = NULL; - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); void *userdata = NULL; gSavedSettings.setBOOL("TemporaryUpload", enabled); upload_new_resource( @@ -446,13 +460,13 @@ class LLFileUploadBulk : public view_listener_t asset_name, 0, LLFolderType::FT_NONE, - LLInventoryType::IT_NONE, + LLInventoryType::EType::IT_NONE, LLFloaterPerms::getNextOwnerPerms("Uploads"), LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"), display_name, callback, - expected_upload_cost, + 0, userdata); } @@ -547,6 +561,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t bool handleEvent(LLPointer event, const LLSD& userdata) { LLPointer raw = new LLImageRaw; + raw->enableOverSize(); S32 width = gViewerWindow->getWindowDisplayWidth(); S32 height = gViewerWindow->getWindowDisplayHeight(); @@ -896,6 +911,9 @@ void upload_new_resource(const std::string& src_filename, std::string name, error = TRUE;; } + // Now that we've determined the type, figure out the cost + if (!error) LLAgentBenefitsMgr::current().findUploadCost(asset_type, expected_upload_cost); + // gen a new transaction ID for this asset tid.generate(); @@ -935,10 +953,10 @@ void upload_new_resource(const std::string& src_filename, std::string name, // hack to create scripts and gestures if(exten == "lsl" || exten == "gesture" || exten == "notecard") // added notecard Oct 15 2009 { - LLInventoryType::EType inv_type = LLInventoryType::IT_GESTURE; - if (exten == "lsl") inv_type = LLInventoryType::IT_LSL; - else if(exten == "gesture") inv_type = LLInventoryType::IT_GESTURE; - else if(exten == "notecard") inv_type = LLInventoryType::IT_NOTECARD; + LLInventoryType::EType inv_type = LLInventoryType::EType::IT_GESTURE; + if (exten == "lsl") inv_type = LLInventoryType::EType::IT_LSL; + else if(exten == "gesture") inv_type = LLInventoryType::EType::IT_GESTURE; + else if(exten == "notecard") inv_type = LLInventoryType::EType::IT_NOTECARD; create_inventory_item( gAgent.getID(), gAgent.getSessionID(), gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(asset_type)), @@ -1250,7 +1268,7 @@ bool upload_new_resource( LLStringUtil::format_map_t args; args["[NAME]"] = name; args["[CURRENCY]"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); - args["[AMOUNT]"] = llformat("%d", expected_upload_cost); + args["[AMOUNT]"] = fmt::to_string(expected_upload_cost); LLFloaterBuyCurrency::buyCurrency( LLTrans::getString("UploadingCosts", args), expected_upload_cost ); return false; } @@ -1326,7 +1344,7 @@ void assign_defaults_and_show_upload_message(LLAssetType::EType asset_type, const std::string& display_name, std::string& description) { - if (LLInventoryType::IT_NONE == inventory_type) + if (LLInventoryType::EType::IT_NONE == inventory_type) { inventory_type = LLInventoryType::defaultForAssetType(asset_type); } @@ -1367,7 +1385,6 @@ void init_menu_file() (new LLFileSavePreview())->registerListener(gMenuHolder, "File.SavePreview"); (new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk"); (new LLFileQuit())->registerListener(gMenuHolder, "File.Quit"); - (new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload"); (new LLFileEnableUploadModel())->registerListener(gMenuHolder, "File.EnableUploadModel"); (new LLFileEnableSaveAs())->registerListener(gMenuHolder, "File.EnableSaveAs"); @@ -1384,9 +1401,9 @@ void NewResourceItemCallback::fire(const LLUUID& new_item_id) std::string type("Uploads"); switch(new_item->getInventoryType()) { - case LLInventoryType::IT_LSL: type = "Scripts"; break; - case LLInventoryType::IT_GESTURE: type = "Gestures"; break; - case LLInventoryType::IT_NOTECARD: type = "Notecard"; break; + case LLInventoryType::EType::IT_LSL: type = "Scripts"; break; + case LLInventoryType::EType::IT_GESTURE: type = "Gestures"; break; + case LLInventoryType::EType::IT_NOTECARD: type = "Notecard"; break; default: break; } LLPermissions perms = new_item->getPermissions(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index d2fdcb6fa8..8d90e1eb49 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -32,15 +32,13 @@ #include "llviewerprecompiledheaders.h" #include "llviewermessage.h" #include -#include #include "llanimationstates.h" #include "llaudioengine.h" #include "llavataractions.h" #include "llavatarnamecache.h" -#include "llbase64.h" +#include "llcororesponder.h" #include "../lscript/lscript_byteformat.h" //Need LSCRIPTRunTimePermissionBits and SCRIPT_PERMISSION_* -#include "lleconomy.h" #include "llfocusmgr.h" #include "llfollowcamparams.h" #include "llinventorydefines.h" @@ -54,13 +52,16 @@ #include "mean_collision_data.h" #include "llagent.h" +#include "llagentbenefits.h" #include "llagentcamera.h" #include "llcallingcard.h" +#include "llcontrolavatar.h" #include "llfirstuse.h" #include "llfloaterbump.h" #include "llfloaterbuycurrency.h" #include "llfloaterbuyland.h" #include "llfloaterchat.h" +#include "llfloaterexperienceprofile.h" #include "llfloaterland.h" #include "llfloaterregioninfo.h" #include "llfloaterlandholdings.h" @@ -72,10 +73,12 @@ #include "llgroupactions.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" -#include "llimpanel.h" +#include "llimprocessing.h" #include "llinventorybridge.h" #include "llinventorymodel.h" #include "llinventorypanel.h" +#include "lllslconstants.h" +#include "llmarketplacefunctions.h" #include "llmutelist.h" #include "llnotify.h" #include "llnotifications.h" @@ -92,7 +95,6 @@ #include "llspeakers.h" #include "lltrans.h" #include "llviewerfoldertype.h" -#include "llviewergenericmessage.h" #include "llviewermenu.h" #include "llviewerinventory.h" #include "llviewerjoystick.h" @@ -111,6 +113,7 @@ #include "llkeythrottle.h" #include "llagentui.h" #include "llviewerregion.h" +#include "llexperiencecache.h" // [RLVa:KB] - Checked: 2010-03-09 (RLVa-1.2.0a) #include "rlvactions.h" @@ -119,18 +122,22 @@ #include "rlvui.h" // [/RLVa:KB] +#include + +//#include "llnotificationmanager.h" // +#include "llexperiencecache.h" + #if SHY_MOD //Command handler # include "shcommandhandler.h" #endif //shy_mod #include "hippogridmanager.h" #include "hippolimits.h" -#include "hippofloaterxml.h" -#include "sgversion.h" #include "m7wlinterface.h" #include "llgiveinventory.h" +#include #include #if LL_WINDOWS // For Windows specific error handler @@ -141,12 +148,9 @@ #include "NACLantispam.h" bool can_block(const LLUUID& id); // NaCl - Newline flood protection -#include static const boost::regex NEWLINES("\\n{1}"); // NaCl End -extern AIHTTPTimeoutPolicy authHandler_timeout; - // // Constants // @@ -166,8 +170,8 @@ extern bool gShiftFrame; // function prototypes bool check_offer_throttle(const std::string& from_name, bool check_only); bool check_asset_previewable(const LLAssetType::EType asset_type); -void callbackCacheEstateOwnerName(const LLUUID& id, const LLAvatarName& av_name); static void process_money_balance_reply_extended(LLMessageSystem* msg); +bool handle_trusted_experiences_notification(const LLSD&); //inventory offer throttle globals LLFrameTimer gThrottleTimer; @@ -195,35 +199,83 @@ const std::string SCRIPT_QUESTIONS[SCRIPT_PERMISSION_EOF] = "ScriptReturnObjects" }; -const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = -{ - TRUE, // ScriptTakeMoney, - FALSE, // ActOnControlInputs - FALSE, // RemapControlInputs - FALSE, // AnimateYourAvatar - FALSE, // AttachToYourAvatar - FALSE, // ReleaseOwnership, - FALSE, // LinkAndDelink, - FALSE, // AddAndRemoveJoints - FALSE, // ChangePermissions - FALSE, // TrackYourCamera, - FALSE, // ControlYourCamera - FALSE, // TeleportYourAgent - FALSE, // JoinAnExperience - FALSE, // SilentlyManageEstateAccess - FALSE, // OverrideYourAnimations - FALSE, // ScriptReturnObjects +constexpr bool SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = +{ + true, // ScriptTakeMoney, + false, // ActOnControlInputs + false, // RemapControlInputs + false, // AnimateYourAvatar + false, // AttachToYourAvatar + false, // ReleaseOwnership, + false, // LinkAndDelink, + false, // AddAndRemoveJoints + false, // ChangePermissions + false, // TrackYourCamera, + false, // ControlYourCamera + false, // TeleportYourAgent + false, // JoinAnExperience + false, // SilentlyManageEstateAccess + false, // OverrideYourAnimations + false, // ScriptReturnObjects }; +void accept_friendship_coro(const LLCoroResponder& responder, const LLSD& notification) +{ + const auto& status = responder.getStatus(); + + if (!responder.isGoodStatus(status)) + { + LL_WARNS("Friendship") << "HTTP status " << status << ": " << responder.getReason() << + ". friendship offer accept failed." << LL_ENDL; + } + else + { + { + LLSD payload = notification["payload"]; + LL_DEBUGS("Friendship") << "Adding friend to list" << responder.getContent() << LL_ENDL; + // add friend to recent people list + //LLRecentPeople::instance().add(payload["from_id"]); + + LLNotificationsUtil::add("FriendshipAcceptedByMe", + notification["substitutions"], payload); + } + } +} + +void decline_friendship_coro(const LLCoroResponder& responder, const LLSD& notification, S32 option) +{ + const auto& status = responder.getStatus(); + + if (!responder.isGoodStatus(status)) + { + LL_WARNS("Friendship") << "HTTP status " << status << ": " << responder.getReason() << + ". friendship offer decline failed." << LL_ENDL; + } + else + { + { + const auto& payload = notification["payload"]; + LL_DEBUGS("Friendship") << "Friendship declined" << responder.getContent() << LL_ENDL; + if (option == 1) + { + LLNotificationsUtil::add("FriendshipDeclinedByMe", + notification["substitutions"], payload); + } + else if (option == 2) + { + // start IM session + LLAvatarActions::startIM(payload["from_id"].asUUID()); + } + } + } +} + bool friendship_offer_callback(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLMessageSystem* msg = gMessageSystem; const LLSD& payload = notification["payload"]; - // add friend to recent people list - //LLRecentPeople::instance().add(payload["from_id"]); - switch(option) { case 0: @@ -234,40 +286,111 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) const LLUUID fid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); // This will also trigger an onlinenotification if the user is online - msg->newMessageFast(_PREHASH_AcceptFriendship); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_TransactionBlock); - msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); - msg->nextBlockFast(_PREHASH_FolderData); - msg->addUUIDFast(_PREHASH_FolderID, fid); - msg->sendReliable(LLHost(payload["sender"].asString())); + std::string url = gAgent.getRegionCapability("AcceptFriendship"); + LL_DEBUGS("Friendship") << "Cap string: " << url << LL_ENDL; + if (!url.empty() && payload.has("online") && payload["online"].asBoolean() == false) + { + LL_DEBUGS("Friendship") << "Accepting friendship via capability" << LL_ENDL; + url += "?from=" + payload["from_id"].asString(); + url += "&agent_name=\"" + LLURI::escape(gAgentAvatarp->getFullname()) + '"'; + LLHTTPClient::post(url, LLSD(), new LLCoroResponder( + boost::bind(accept_friendship_coro, _1, notification))); + } + else if (payload.has("session_id") && payload["session_id"].asUUID().notNull()) + { + LL_DEBUGS("Friendship") << "Accepting friendship via viewer message" << LL_ENDL; + msg->newMessageFast(_PREHASH_AcceptFriendship); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_TransactionBlock); + msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); + msg->nextBlockFast(_PREHASH_FolderData); + msg->addUUIDFast(_PREHASH_FolderID, fid); + msg->sendReliable(LLHost(payload["sender"].asString())); + + // add friend to recent people list + //LLRecentPeople::instance().add(payload["from_id"]); + LLNotificationsUtil::add("FriendshipAcceptedByMe", + notification["substitutions"], payload); + } + else + { + LL_WARNS("Friendship") << "Failed to accept friendship offer, neither capability nor transaction id are accessible" << LL_ENDL; + } break; } - case 1: + case 1: // Decline + // fall-through + //case 3: // Send IM - decline and start IM session + { // decline // We no longer notify other viewers, but we DO still send // the rejection to the simulator to delete the pending userop. - msg->newMessageFast(_PREHASH_DeclineFriendship); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_TransactionBlock); - msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); - msg->sendReliable(LLHost(payload["sender"].asString())); - break; - case 3: - // profile - LLAvatarActions::showProfile(payload["from_id"]); - LLNotificationsUtil::add(notification["name"], notification["substitutions"], payload); //Respawn! + std::string url = gAgent.getRegionCapability("DeclineFriendship"); + LL_DEBUGS("Friendship") << "Cap string: " << url << LL_ENDL; + if (!url.empty() && payload.has("online") && payload["online"].asBoolean() == false) + { + LL_DEBUGS("Friendship") << "Declining friendship via capability" << LL_ENDL; + url += "?from=" + payload["from_id"].asString(); + LLHTTPClient::del(url, new LLCoroResponder( + boost::bind(decline_friendship_coro, _1, notification, option))); + } + else if (payload.has("session_id") && payload["session_id"].asUUID().notNull()) + { + LL_DEBUGS("Friendship") << "Declining friendship via viewer message" << LL_ENDL; + msg->newMessageFast(_PREHASH_DeclineFriendship); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_TransactionBlock); + msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); + msg->sendReliable(LLHost(payload["sender"].asString())); + + if (option == 1) // due to fall-through + { + LLNotificationsUtil::add("FriendshipDeclinedByMe", + notification["substitutions"], payload); + } + /*else if (option == 3) + { + // start IM session + LLAvatarActions::startIM(payload["from_id"].asUUID()); + }*/ + } + else + { + LL_WARNS("Friendship") << "Failed to decline friendship offer, neither capability nor transaction id are accessible" << LL_ENDL; + } + } default: // close button probably, possibly timed out break; } + // TODO: this set of calls has undesirable behavior under Windows OS (CHUI-985): + // here appears three additional toasts instead one modified + // need investigation and fix + + // LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + // modified_form->setElementEnabled("Accept", false); + // modified_form->setElementEnabled("Decline", false); + // notification_ptr->updateForm(modified_form); +// [SL:KB] - Patch: UI-Notifications | Checked: 2013-05-09 (Catznip-3.5) +// // Assume that any offer notification with "getCanBeStored() == true" is the result of RLVa routing it to the notifcation syswell +// /*const*/ LLNotificationsUI::LLScreenChannel* pChannel = LLNotificationsUI::LLChannelManager::instance().getNotificationScreenChannel(); +// /*const*/ LLNotificationsUI::LLToast* pToast = (pChannel) ? pChannel->getToastByNotificationID(notification["id"].asUUID()) : NULL; +// if ( (!pToast) || (!pToast->getCanBeStored()) ) +// { +// [/SL:KB] +// notification_ptr->repost(); +// [SL:KB] - Patch: UI-Notifications | Checked: 2013-05-09 (Catznip-3.5) +// } +// [/SL:KB] + return false; } + static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback); static LLNotificationFunctorRegistration friendship_offer_callback_reg_nm("OfferFriendshipNoMessage", friendship_offer_callback); @@ -277,25 +400,25 @@ static LLNotificationFunctorRegistration friendship_offer_callback_reg_nm("Offer void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group, S32 trx_type, const std::string& desc) { - if(0 == amount || !region) return; + if (0 == amount || !region) return; amount = abs(amount); - LL_INFOS("Messaging") << "give_money(" << uuid << "," << amount << ")"<< LL_ENDL; - if(can_afford_transaction(amount)) + LL_INFOS("Messaging") << "give_money(" << uuid << "," << amount << ")" << LL_ENDL; + if (can_afford_transaction(amount)) { -// gStatusBar->debitBalance(amount); + // gStatusBar->debitBalance(amount); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_MoneyTransferRequest); msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_MoneyData); - msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID()); msg->addUUIDFast(_PREHASH_DestID, uuid); msg->addU8Fast(_PREHASH_Flags, pack_transaction_flags(FALSE, is_group)); msg->addS32Fast(_PREHASH_Amount, amount); msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY); msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY); - msg->addS32Fast(_PREHASH_TransactionType, trx_type ); + msg->addS32Fast(_PREHASH_TransactionType, trx_type); msg->addStringFast(_PREHASH_Description, desc); msg->sendReliable(region->getHost()); } @@ -327,19 +450,19 @@ void process_logout_reply(LLMessageSystem* msg, void**) msg->getUUID("AgentData", "AgentID", agent_id); LLUUID session_id; msg->getUUID("AgentData", "SessionID", session_id); - if((agent_id != gAgent.getID()) || (session_id != gAgent.getSessionID())) + if ((agent_id != gAgent.getID()) || (session_id != gAgent.getSessionID())) { LL_WARNS("Messaging") << "Bogus Logout Reply" << LL_ENDL; } LLInventoryModel::update_map_t parents; - S32 count = msg->getNumberOfBlocksFast( _PREHASH_InventoryData ); - for(S32 i = 0; i < count; ++i) + S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); + for (S32 i = 0; i < count; ++i) { LLUUID item_id; msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id, i); - if( (1 == count) && item_id.isNull() ) + if ((1 == count) && item_id.isNull()) { // Detect dummy item. Indicates an empty list. break; @@ -348,8 +471,8 @@ void process_logout_reply(LLMessageSystem* msg, void**) // We do not need to track the asset ids, just account for an // updated inventory version. LL_INFOS("Messaging") << "process_logout_reply itemID=" << item_id << LL_ENDL; - LLInventoryItem* item = gInventory.getItem( item_id ); - if( item ) + LLInventoryItem* item = gInventory.getItem(item_id); + if (item) { parents[item->getParentUUID()] = 0; gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id); @@ -362,11 +485,13 @@ void process_logout_reply(LLMessageSystem* msg, void**) LLAppViewer::instance()->forceQuit(); } -void process_layer_data(LLMessageSystem *mesgsys, void **user_data) +void process_layer_data(LLMessageSystem* mesgsys, void** user_data) { - LLViewerRegion *regionp = LLWorld::getInstance()->getRegion(mesgsys->getSender()); + LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(mesgsys->getSender()); - if(!regionp || gNoRender) + LL_DEBUGS_ONCE("SceneLoadTiming") << "Received layer data" << LL_ENDL; + + if (!regionp || gNoRender) { LL_WARNS() << "Invalid region for layer data." << LL_ENDL; return; @@ -389,9 +514,9 @@ void process_layer_data(LLMessageSystem *mesgsys, void **user_data) << LL_ENDL; return; } - U8 *datap = new U8[size]; + U8* datap = new U8[size]; mesgsys->getBinaryDataFast(_PREHASH_LayerData, _PREHASH_Data, datap, size); - LLVLData *vl_datap = new LLVLData(regionp, type, datap, size); + LLVLData* vl_datap = new LLVLData(regionp, type, datap, size); if (mesgsys->getReceiveCompressedSize()) { gVLManager.addLayerData(vl_datap, mesgsys->getReceiveCompressedSize()); @@ -402,195 +527,9 @@ void process_layer_data(LLMessageSystem *mesgsys, void **user_data) } } -// S32 exported_object_count = 0; -// S32 exported_image_count = 0; -// S32 current_object_count = 0; -// S32 current_image_count = 0; - -// extern LLNotifyBox *gExporterNotify; -// extern LLUUID gExporterRequestID; -// extern std::string gExportDirectory; - -// extern LLUploadDialog *gExportDialog; - -// std::string gExportedFile; - -// std::map gImageChecksums; - -// void export_complete() -// { -// LLUploadDialog::modalUploadFinished(); -// gExporterRequestID.setNull(); -// gExportDirectory = ""; - -// LLFILE* fXML = LLFile::fopen(gExportedFile, "rb"); /* Flawfinder: ignore */ -// fseek(fXML, 0, SEEK_END); -// long length = ftell(fXML); -// fseek(fXML, 0, SEEK_SET); -// U8 *buffer = new U8[length + 1]; -// size_t nread = fread(buffer, 1, length, fXML); -// if (nread < (size_t) length) -// { -// LL_WARNS("Messaging") << "Short read" << LL_ENDL; -// } -// buffer[nread] = '\0'; -// fclose(fXML); - -// char *pos = (char *)buffer; -// while ((pos = strstr(pos+1, ""); - -// if (pos_uuid) -// { -// char image_uuid_str[UUID_STR_SIZE]; /* Flawfinder: ignore */ -// memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); /* Flawfinder: ignore */ -// image_uuid_str[UUID_STR_SIZE-1] = 0; - -// LLUUID image_uuid(image_uuid_str); - -// LL_INFOS("Messaging") << "Found UUID: " << image_uuid << LL_ENDL; - -// std::map::iterator itor = gImageChecksums.find(image_uuid); -// if (itor != gImageChecksums.end()) -// { -// LL_INFOS("Messaging") << "Replacing with checksum: " << itor->second << LL_ENDL; -// if (!itor->second.empty()) -// { -// memcpy(&pos_check[10], itor->second.c_str(), 32); /* Flawfinder: ignore */ -// } -// } -// } -// } -// } - -// LLFILE* fXMLOut = LLFile::fopen(gExportedFile, "wb"); /* Flawfinder: ignore */ -// if (fwrite(buffer, 1, length, fXMLOut) != length) -// { -// LL_WARNS("Messaging") << "Short write" << LL_ENDL; -// } -// fclose(fXMLOut); - -// delete [] buffer; -// } - - -// void exported_item_complete(const LLTSCode status, void *user_data) -// { -// //std::string *filename = (std::string *)user_data; - -// if (status < LLTS_OK) -// { -// LL_WARNS("Messaging") << "Export failed!" << LL_ENDL; -// } -// else -// { -// ++current_object_count; -// if (current_image_count == exported_image_count && current_object_count == exported_object_count) -// { -// LL_INFOS("Messaging") << "*** Export complete ***" << LL_ENDL; - -// export_complete(); -// } -// else -// { -// gExportDialog->setMessage(llformat("Exported %d/%d object files, %d/%d textures.", current_object_count, exported_object_count, current_image_count, exported_image_count)); -// } -// } -// } - -// struct exported_image_info -// { -// LLUUID image_id; -// std::string filename; -// U32 image_num; -// }; - -// void exported_j2c_complete(const LLTSCode status, void *user_data) -// { -// exported_image_info *info = (exported_image_info *)user_data; -// LLUUID image_id = info->image_id; -// U32 image_num = info->image_num; -// std::string filename = info->filename; -// delete info; - -// if (status < LLTS_OK) -// { -// LL_WARNS("Messaging") << "Image download failed!" << LL_ENDL; -// } -// else -// { -// LLFILE* fIn = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ -// if (fIn) -// { -// LLPointer ImageUtility = new LLImageJ2C; -// LLPointer TargaUtility = new LLImageTGA; - -// fseek(fIn, 0, SEEK_END); -// S32 length = ftell(fIn); -// fseek(fIn, 0, SEEK_SET); -// U8 *buffer = ImageUtility->allocateData(length); -// if (fread(buffer, 1, length, fIn) != length) -// { -// LL_WARNS("Messaging") << "Short read" << LL_ENDL; -// } -// fclose(fIn); -// LLFile::remove(filename); - -// // Convert to TGA -// LLPointer image = new LLImageRaw(); - -// ImageUtility->updateData(); -// ImageUtility->decode(image, 100000.0f); - -// TargaUtility->encode(image); -// U8 *data = TargaUtility->getData(); -// S32 data_size = TargaUtility->getDataSize(); - -// std::string file_path = gDirUtilp->getDirName(filename); - -// std::string output_file = llformat("%s/image-%03d.tga", file_path.c_str(), image_num);//filename; -// //S32 name_len = output_file.length(); -// //strcpy(&output_file[name_len-3], "tga"); -// LLFILE* fOut = LLFile::fopen(output_file, "wb"); /* Flawfinder: ignore */ -// char md5_hash_string[33]; /* Flawfinder: ignore */ -// strcpy(md5_hash_string, "00000000000000000000000000000000"); /* Flawfinder: ignore */ -// if (fOut) -// { -// if (fwrite(data, 1, data_size, fOut) != data_size) -// { -// LL_WARNS("Messaging") << "Short write" << LL_ENDL; -// } -// fseek(fOut, 0, SEEK_SET); -// fclose(fOut); -// fOut = LLFile::fopen(output_file, "rb"); /* Flawfinder: ignore */ -// LLMD5 my_md5_hash(fOut); -// my_md5_hash.hex_digest(md5_hash_string); -// } - -// gImageChecksums.insert(std::pair(image_id, md5_hash_string)); -// } -// } - -// ++current_image_count; -// if (current_image_count == exported_image_count && current_object_count == exported_object_count) -// { -// LL_INFOS("Messaging") << "*** Export textures complete ***" << LL_ENDL; -// export_complete(); -// } -// else -// { -// gExportDialog->setMessage(llformat("Exported %d/%d object files, %d/%d textures.", current_object_count, exported_object_count, current_image_count, exported_image_count)); -// } -//} - void process_derez_ack(LLMessageSystem*, void**) { - if(gViewerWindow) gViewerWindow->getWindow()->decBusyCount(); + if (gViewerWindow) gViewerWindow->getWindow()->decBusyCount(); } void process_places_reply(LLMessageSystem* msg, void** data) @@ -602,7 +541,7 @@ void process_places_reply(LLMessageSystem* msg, void** data) { LLFloaterLandHoldings::processPlacesReply(msg, data); } - else if(gAgent.isInGroup(query_id)) + else if (gAgent.isInGroup(query_id)) { LLPanelGroupLandMoney::processPlacesReply(msg, data); } @@ -614,7 +553,7 @@ void process_places_reply(LLMessageSystem* msg, void** data) void send_sound_trigger(const LLUUID& sound_id, F32 gain) { - if (sound_id.isNull() || gAgent.getRegion() == NULL) + if (sound_id.isNull() || gAgent.getRegion() == nullptr) { // disconnected agent or zero guids don't get sent (no sound) return; @@ -625,9 +564,9 @@ void send_sound_trigger(const LLUUID& sound_id, F32 gain) msg->nextBlockFast(_PREHASH_SoundData); msg->addUUIDFast(_PREHASH_SoundID, sound_id); // Client untrusted, ids set on sim - msg->addUUIDFast(_PREHASH_OwnerID, LLUUID::null ); - msg->addUUIDFast(_PREHASH_ObjectID, LLUUID::null ); - msg->addUUIDFast(_PREHASH_ParentID, LLUUID::null ); + msg->addUUIDFast(_PREHASH_OwnerID, LLUUID::null); + msg->addUUIDFast(_PREHASH_ObjectID, LLUUID::null); + msg->addUUIDFast(_PREHASH_ParentID, LLUUID::null); msg->addU64Fast(_PREHASH_Handle, gAgent.getRegion()->getHandle()); @@ -638,33 +577,163 @@ void send_sound_trigger(const LLUUID& sound_id, F32 gain) gAgent.sendMessage(); } +static LLSD sSavedGroupInvite; +static LLSD sSavedResponse; + +void response_group_invitation_coro(const LLCoroResponder& responder, const LLUUID& group_id, bool notify_and_update) +{ + const auto& status = responder.getStatus(); + + if (!responder.isGoodStatus(status)) + { + LL_WARNS("GroupInvite") << "HTTP status " << status << ": " << responder.getReason() << + ". Group " << group_id << " invitation response processing failed." << LL_ENDL; + } + else + { + { + LL_DEBUGS("GroupInvite") << "Successfully sent response to group " << group_id << " invitation" << LL_ENDL; + if (notify_and_update) + { + LLNotificationsUtil::add("JoinGroupSuccess"); + gAgent.sendAgentDataUpdateRequest(); + + LLGroupMgr::getInstance()->clearGroupData(group_id); + // refresh the floater for this group, if any. + LLGroupActions::refresh(group_id); + } + } + } +} + +void send_join_group_response(const LLUUID& group_id, const LLUUID& transaction_id, bool accept_invite, S32 fee, bool use_offline_cap, LLSD& payload) +{ + if (accept_invite && fee > 0) + { + // If there is a fee to join this group, make + // sure the user is sure they want to join. + LLSD args; + args["COST"] = llformat("%d", fee); + // Set the fee for next time to 0, so that we don't keep + // asking about a fee. + LLSD next_payload = payload; + next_payload["fee"] = 0; + LLNotificationsUtil::add("JoinGroupCanAfford", + args, + next_payload); + } + else if (use_offline_cap) + { + std::string url; + if (accept_invite) + { + url = gAgent.getRegionCapability("AcceptGroupInvite"); + } + else + { + url = gAgent.getRegionCapability("DeclineGroupInvite"); + } + + if (!url.empty()) + { + LL_DEBUGS("GroupInvite") << "Capability url: " << url << LL_ENDL; + LLSD payload; + payload["group"] = group_id; + LLHTTPClient::post(url, payload, new LLCoroResponder( + boost::bind(response_group_invitation_coro, _1, group_id, accept_invite))); + } + else + { + // if sim has no this cap, we can do nothing - regular request will fail + LL_WARNS("GroupInvite") << "No capability, can't reply to offline invitation!" << LL_ENDL; + } + } + else + { + LL_DEBUGS("GroupInvite") << "Replying to group invite via IM message" << LL_ENDL; + + EInstantMessage type = accept_invite ? IM_GROUP_INVITATION_ACCEPT : IM_GROUP_INVITATION_DECLINE; + + send_improved_im(group_id, + std::string("name"), + std::string("message"), + IM_ONLINE, + type, + transaction_id); + } +} + +void send_join_group_response(const LLUUID& group_id, const LLUUID& transaction_id, bool accept_invite, S32 fee, bool use_offline_cap) +{ + LLSD payload; + if (accept_invite) + { + payload["group_id"] = group_id; + payload["transaction_id"] = transaction_id; + payload["fee"] = fee; + payload["use_offline_cap"] = use_offline_cap; + } + send_join_group_response(group_id, transaction_id, accept_invite, fee, use_offline_cap, payload); +} + bool join_group_response(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + // A bit of variable saving and restoring is used to deal with the case where your group list is full and you + // receive an invitation to another group. The data from that invitation is stored in the sSaved + // variables. If you then drop a group and click on the Join button the stored data is restored and used + // to join the group. + LLSD notification_adjusted = notification; + LLSD response_adjusted = response; + + std::string action = notification["name"]; + + // Storing all the information by group id allows for the rare case of being at your maximum + // group count and receiving more than one invitation. + std::string id = notification_adjusted["payload"]["group_id"].asString(); + + if ("JoinGroup" == action || "JoinGroupCanAfford" == action) + { + sSavedGroupInvite[id] = notification; + sSavedResponse[id] = response; + } + else if ("JoinedTooManyGroupsMember" == action) + { + S32 opt = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == opt) // Join button pressed + { + notification_adjusted = sSavedGroupInvite[id]; + response_adjusted = sSavedResponse[id]; + } + sSavedGroupInvite.erase(id); + sSavedResponse.erase(id); + } + + S32 option = LLNotificationsUtil::getSelectedOption(notification_adjusted, response_adjusted); bool accept_invite = false; - LLUUID group_id = notification["payload"]["group_id"].asUUID(); - LLUUID transaction_id = notification["payload"]["transaction_id"].asUUID(); - std::string name = notification["payload"]["name"].asString(); - std::string message = notification["payload"]["message"].asString(); - S32 fee = notification["payload"]["fee"].asInteger(); + LLUUID group_id = notification_adjusted["payload"]["group_id"].asUUID(); + LLUUID transaction_id = notification_adjusted["payload"]["transaction_id"].asUUID(); + std::string name = notification_adjusted["payload"]["name"].asString(); + std::string message = notification_adjusted["payload"]["message"].asString(); + S32 fee = notification_adjusted["payload"]["fee"].asInteger(); + U8 use_offline_cap = notification_adjusted["payload"]["use_offline_cap"].asInteger(); if (option == 2 && !group_id.isNull()) { LLGroupActions::show(group_id); LLSD args; args["MESSAGE"] = message; - LLNotificationsUtil::add("JoinGroup", args, notification["payload"]); + LLNotificationsUtil::add("JoinGroup", args, notification_adjusted["payload"]); return false; } - if(option == 0 && !group_id.isNull()) + if (option == 0 && !group_id.isNull()) { // check for promotion or demotion. - S32 max_groups = gHippoLimits->getMaxAgentGroups(); - if(gAgent.isInGroup(group_id)) ++max_groups; + S32 max_groups = LLAgentBenefitsMgr::current().getGroupMembershipLimit(); + if (gAgent.isInGroup(group_id)) ++max_groups; - if((S32)gAgent.mGroups.size() < max_groups) + if ((S32)gAgent.mGroups.size() < max_groups) { accept_invite = true; } @@ -677,63 +746,29 @@ bool join_group_response(const LLSD& notification, const LLSD& response) return false; } } + send_join_group_response(group_id, transaction_id, accept_invite, fee, use_offline_cap, notification_adjusted["payload"]); - if (accept_invite) - { - // If there is a fee to join this group, make - // sure the user is sure they want to join. - if (fee > 0) - { - LLSD args; - args["COST"] = llformat("%d", fee); - // Set the fee for next time to 0, so that we don't keep - // asking about a fee. - LLSD next_payload = notification["payload"]; - next_payload["fee"] = 0; - LLNotificationsUtil::add("JoinGroupCanAfford", - args, - next_payload); - } - else - { - send_improved_im(group_id, - std::string("name"), - std::string("message"), - IM_ONLINE, - IM_GROUP_INVITATION_ACCEPT, - transaction_id); - } - } - else - { - send_improved_im(group_id, - std::string("name"), - std::string("message"), - IM_ONLINE, - IM_GROUP_INVITATION_DECLINE, - transaction_id); - } + sSavedGroupInvite[id] = LLSD::emptyMap(); + sSavedResponse[id] = LLSD::emptyMap(); return false; } -static void highlight_inventory_objects_in_panel(const std::vector& items, LLInventoryPanel *inventory_panel) +static void highlight_inventory_objects_in_panel(const uuid_vec_t& items, LLInventoryPanel *inventory_panel) { - if (NULL == inventory_panel) return; + if (nullptr == inventory_panel) return; - for (std::vector::const_iterator item_iter = items.begin(); - item_iter != items.end(); - ++item_iter) + for (auto item_id : items) { - const LLUUID& item_id = (*item_iter); - if(!highlight_offered_object(item_id)) + if (!highlight_offered_object(item_id)) { continue; } LLInventoryObject* item = gInventory.getObject(item_id); llassert(item); - if (!item) { + if (!item) + { continue; } @@ -770,14 +805,18 @@ static LLNotificationFunctorRegistration jgr_3("JoinGroupCanAfford", join_group_ //----------------------------------------------------------------------------- // Instant Message //----------------------------------------------------------------------------- -class LLOpenAgentOffer : public LLInventoryFetchItemsObserver +class LLOpenAgentOffer final : public LLInventoryFetchItemsObserver { public: LLOpenAgentOffer(const LLUUID& object_id, const std::string& from_name) : LLInventoryFetchItemsObserver(object_id), - mFromName(from_name) {} - /*virtual*/ void startFetch() + mFromName(from_name) + { + } + + /*virtual*/ + void startFetch() override { for (uuid_vec_t::const_iterator it = mIDs.begin(); it < mIDs.end(); ++it) { @@ -789,12 +828,15 @@ class LLOpenAgentOffer : public LLInventoryFetchItemsObserver } LLInventoryFetchItemsObserver::startFetch(); } - /*virtual*/ void done() + + /*virtual*/ + void done() override { open_inventory_offer(mComplete, mFromName); gInventory.removeObserver(this); delete this; } + private: std::string mFromName; }; @@ -805,19 +847,19 @@ class LLOpenAgentOffer : public LLInventoryFetchItemsObserver * We can't create it each time items are moved because "drop" event is sent separately for each * element even while multi-dragging. We have to have the only instance of the observer. See EXT-4347. */ -class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetObserver +class LLViewerInventoryMoveFromWorldObserver final : public LLInventoryAddItemByAssetObserver { public: LLViewerInventoryMoveFromWorldObserver() : LLInventoryAddItemByAssetObserver() { - } - void setMoveIntoFolderID(const LLUUID& into_folder_uuid) {mMoveIntoFolderID = into_folder_uuid; } + void setMoveIntoFolderID(const LLUUID& into_folder_uuid) { mMoveIntoFolderID = into_folder_uuid; } private: - /*virtual */void onAssetAdded(const LLUUID& asset_id) + /*virtual */ + void onAssetAdded(const LLUUID& asset_id) override { // Store active Inventory panel. if (LLInventoryPanel::getActiveInventoryPanel()) @@ -838,7 +880,7 @@ class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetO * Selects added inventory items watched by their Asset UUIDs if selection was not changed since * all items were started to watch (dropped into a folder). */ - void done() + void done() override { LLInventoryPanel* active_panel = dynamic_cast(mActivePanel.get()); @@ -858,7 +900,7 @@ class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetO { LLInventoryPanel* active_panel = dynamic_cast(mActivePanel.get()); - if (NULL == active_panel) + if (nullptr == active_panel) { return true; } @@ -875,11 +917,11 @@ class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetO LL_DEBUGS("Inventory_Move") << "Selected firstly: " << mSelectedItems.size() << ", now: " << selected_items.size() << ", difference: " << different_items.size() << LL_ENDL; - return different_items.size() > 0; + return !different_items.empty(); } LLHandle mActivePanel; - typedef std::set selected_items_t; + typedef uuid_set_t selected_items_t; selected_items_t mSelectedItems; /** @@ -897,7 +939,7 @@ class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetO LLUUID mMoveIntoFolderID; }; -LLViewerInventoryMoveFromWorldObserver* gInventoryMoveObserver = NULL; +LLViewerInventoryMoveFromWorldObserver* gInventoryMoveObserver = nullptr; void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder_uuid) { @@ -914,7 +956,7 @@ void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder * Used currently for dragging from inbox to regular inventory folders */ -class LLViewerInventoryMoveObserver : public LLInventoryObserver +class LLViewerInventoryMoveObserver final : public LLInventoryObserver { public: @@ -928,39 +970,37 @@ class LLViewerInventoryMoveObserver : public LLInventoryObserver } } - virtual ~LLViewerInventoryMoveObserver() {} - virtual void changed(U32 mask); + virtual ~LLViewerInventoryMoveObserver() = default; + + void changed(U32 mask) override; private: LLUUID mObjectID; LLHandle mActivePanel; - }; void LLViewerInventoryMoveObserver::changed(U32 mask) { LLInventoryPanel* active_panel = dynamic_cast(mActivePanel.get()); - if (NULL == active_panel) + if (nullptr == active_panel) { gInventory.removeObserver(this); return; } - if((mask & (LLInventoryObserver::STRUCTURE)) != 0) + if ((mask & (STRUCTURE)) != 0) { - const std::set& changed_items = gInventory.getChangedIDs(); + const uuid_set_t& changed_items = gInventory.getChangedIDs(); - std::set::const_iterator id_it = changed_items.begin(); - std::set::const_iterator id_end = changed_items.end(); + auto id_it = changed_items.begin(); + auto id_end = changed_items.end(); for (;id_it != id_end; ++id_it) { if ((*id_it) == mObjectID) { active_panel->clearSelection(); - std::vector items; - items.push_back(mObjectID); - highlight_inventory_objects_in_panel(items, active_panel); + highlight_inventory_objects_in_panel({mObjectID}, active_panel); active_panel->getRootFolder()->scrollToShowSelection(); gInventory.removeObserver(this); @@ -981,15 +1021,16 @@ void set_dad_inbox_object(const LLUUID& object_id) //and it never dies. We do this because we don't know the UUID of //task offers until they are accepted, so we don't wouldn't //know what to watch for, so instead we just watch for all additions. -class LLOpenTaskOffer : public LLInventoryAddedObserver +class LLOpenTaskOffer final : public LLInventoryAddedObserver { protected: - /*virtual*/ void done() + /*virtual*/ + void done() override { uuid_vec_t added; - for(uuid_set_t::const_iterator it = gInventory.getAddedIDs().begin(); it != gInventory.getAddedIDs().end(); ++it) + for (auto it : gInventory.getAddedIDs()) { - added.push_back(*it); + added.push_back(it); } for (uuid_vec_t::iterator it = added.begin(); it != added.end();) { @@ -1020,17 +1061,18 @@ class LLOpenTaskOffer : public LLInventoryAddedObserver open_inventory_offer(added, ""); } - }; +}; -class LLOpenTaskGroupOffer : public LLInventoryAddedObserver +class LLOpenTaskGroupOffer final : public LLInventoryAddedObserver { protected: - /*virtual*/ void done() + /*virtual*/ + void done() override { uuid_vec_t added; - for(uuid_set_t::const_iterator it = gInventory.getAddedIDs().begin(); it != gInventory.getAddedIDs().end(); ++it) + for (auto it : gInventory.getAddedIDs()) { - added.push_back(*it); + added.push_back(it); } open_inventory_offer(added, "group_offer"); gInventory.removeObserver(this); @@ -1039,17 +1081,19 @@ class LLOpenTaskGroupOffer : public LLInventoryAddedObserver }; //one global instance to bind them -LLOpenTaskOffer* gNewInventoryObserver=NULL; -class LLNewInventoryHintObserver : public LLInventoryAddedObserver +LLOpenTaskOffer* gNewInventoryObserver = nullptr; + +class LLNewInventoryHintObserver final : public LLInventoryAddedObserver { protected: - /*virtual*/ void done() + /*virtual*/ + void done() override { //LLFirstUse::newInventory(); } }; -LLNewInventoryHintObserver* gNewInventoryHintObserver=NULL; +LLNewInventoryHintObserver* gNewInventoryHintObserver = nullptr; void start_new_inventory_observer() { @@ -1075,7 +1119,7 @@ void start_new_inventory_observer() } } -class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver +class LLDiscardAgentOffer final : public LLInventoryFetchItemsObserver { LOG_CLASS(LLDiscardAgentOffer); @@ -1083,9 +1127,11 @@ class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver LLDiscardAgentOffer(const LLUUID& folder_id, const LLUUID& object_id) : LLInventoryFetchItemsObserver(object_id), mFolderID(folder_id), - mObjectID(object_id) {} + mObjectID(object_id) + { + } - virtual void done() + void done() override { LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << LL_ENDL; @@ -1095,7 +1141,7 @@ class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver // So defer moving the item to trash until viewer gets idle (in a moment). // Use removeObject() rather than removeItem() because at this level, // the object could be either an item or a folder. - LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeObject, &gInventory, mObjectID)); + LLAppViewer::instance()->addOnIdleCallback(std::bind(&LLInventoryModel::removeObject, &gInventory, mObjectID)); gInventory.removeObserver(this); delete this; } @@ -1114,7 +1160,6 @@ bool check_offer_throttle(const std::string& from_name, bool check_only) static U32 throttle_count; static bool throttle_logged; LLChat chat; - std::string log_message; if (!gSavedSettings.getBOOL("ShowNewInventory")) return false; @@ -1124,58 +1169,53 @@ bool check_offer_throttle(const std::string& from_name, bool check_only) return gThrottleTimer.hasExpired(); } - if(gThrottleTimer.checkExpirationAndReset(OFFER_THROTTLE_TIME)) + if (gThrottleTimer.checkExpirationAndReset(OFFER_THROTTLE_TIME)) { LL_DEBUGS("Messaging") << "Throttle Expired" << LL_ENDL; - throttle_count=1; - throttle_logged=false; + throttle_count = 1; + throttle_logged = false; return true; } - else //has not expired + //has not expired + LL_DEBUGS("Messaging") << "Throttle Not Expired, Count: " << throttle_count << LL_ENDL; + // When downloading the initial inventory we get a lot of new items + // coming in and can't tell that from spam. + if (LLStartUp::getStartupState() >= STATE_STARTED + && throttle_count >= OFFER_THROTTLE_MAX_COUNT) { - LL_DEBUGS("Messaging") << "Throttle Not Expired, Count: " << throttle_count << LL_ENDL; - // When downloading the initial inventory we get a lot of new items - // coming in and can't tell that from spam. - if (LLStartUp::getStartupState() >= STATE_STARTED - && throttle_count >= OFFER_THROTTLE_MAX_COUNT) + if (!throttle_logged) { - if (!throttle_logged) - { - // Use the name of the last item giver, who is probably the person - // spamming you. + // Use the name of the last item giver, who is probably the person + // spamming you. - LLStringUtil::format_map_t arg; - std::string log_msg; - std::ostringstream time ; - time<getSecondLifeTitle(); - arg["TIME"] = time.str(); + arg["APP_NAME"] = LLAppViewer::instance()->getSecondLifeTitle(); + arg["TIME"] = time.str(); - if (!from_name.empty()) - { - arg["FROM_NAME"] = from_name; - log_msg = LLTrans::getString("ItemsComingInTooFastFrom", arg); - } - else - { - log_msg = LLTrans::getString("ItemsComingInTooFast", arg); - } + if (!from_name.empty()) + { + arg["FROM_NAME"] = from_name; + log_msg = LLTrans::getString("ItemsComingInTooFastFrom", arg); + } + else + { + log_msg = LLTrans::getString("ItemsComingInTooFast", arg); + } - //this is kinda important, so actually put it on screen - chat.mText = log_msg; - LLFloaterChat::addChat(chat, FALSE, FALSE); + //this is kinda important, so actually put it on screen + chat.mText = log_msg; + LLFloaterChat::addChat(chat, FALSE, FALSE); - throttle_logged=true; - } - return false; - } - else - { - throttle_count++; - return true; + throttle_logged = true; } + return false; } + throttle_count++; + return true; } // Return "true" if we have a preview method for that asset type, "false" otherwise @@ -1192,17 +1232,14 @@ bool check_asset_previewable(const LLAssetType::EType asset_type) void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_name) { if (gAgent.isDoNotDisturb()) return; - for (uuid_vec_t::const_iterator obj_iter = objects.begin(); - obj_iter != objects.end(); - ++obj_iter) + for (auto obj_id : objects) { - const LLUUID& obj_id = (*obj_iter); - if(!highlight_offered_object(obj_id)) + if (!highlight_offered_object(obj_id)) { continue; } - const LLInventoryObject *obj = gInventory.getObject(obj_id); + const LLInventoryObject* obj = gInventory.getObject(obj_id); if (!obj) { LL_WARNS() << "Cannot find object [ itemID:" << obj_id << " ] to open." << LL_ENDL; @@ -1254,7 +1291,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam //highlight item, if it's not in the trash or lost+found // Don't auto-open the inventory floater - LLInventoryView* view = LLInventoryView::getActiveInventory(); + LLPanelMainInventory* view = LLPanelMainInventory::getActiveInventory(); if(!view) { return; @@ -1271,10 +1308,10 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam if (gSavedSettings.getBOOL("ShowInInventory") && objects.size() == 1 && item != NULL && asset_type != LLAssetType::AT_CALLINGCARD && - item->getInventoryType() != LLInventoryType::IT_ATTACHMENT && + item->getInventoryType() != LLInventoryType::EType::IT_ATTACHMENT && !from_name.empty()) { - LLInventoryView::showAgentInventory(TRUE); + LLPanelMainInventory::showAgentInventory(TRUE); } if (!gSavedSettings.getBOOL("LiruHighlightNewInventory")) return; @@ -1291,7 +1328,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam bool highlight_offered_object(const LLUUID& obj_id) { const LLInventoryObject* obj = gInventory.getObject(obj_id); - if(!obj) + if (!obj) { LL_WARNS("Messaging") << "Unable to show inventory item: " << obj_id << LL_ENDL; return false; @@ -1300,9 +1337,9 @@ bool highlight_offered_object(const LLUUID& obj_id) //////////////////////////////////////////////////////////////////////////////// // Don't highlight if it's in certain "quiet" folders which don't need UI // notification (e.g. trash, cof, lost-and-found). - if(!gAgent.getAFK()) + if (!gAgent.getAFK()) { - const LLViewerInventoryCategory *parent = gInventory.getFirstNondefaultParent(obj_id); + const LLViewerInventoryCategory* parent = gInventory.getFirstNondefaultParent(obj_id); if (parent) { const LLFolderType::EType parent_type = parent->getPreferredType(); @@ -1326,16 +1363,18 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, LLMute mute(blocked_id, full_name, mute_type); if (LLMuteList::getInstance()->add(mute)) { - LLFloaterMute::showInstance(); - LLFloaterMute::getInstance()->selectMute(blocked_id); + LLFloaterMute::showInstance()->selectMute(blocked_id); } // purge the message queue of any previously queued inventory offers from the same source. - class OfferMatcher : public LLNotifyBoxView::Matcher + class OfferMatcher final : public LLNotifyBoxView::Matcher { public: - OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {} - bool matches(const LLNotificationPtr notification) const + OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) + { + } + + bool matches(const LLNotificationPtr notification) const override { if(notification->getName() == "ObjectGiveItem" || notification->getName() == "ObjectGiveItemUnknownUser" @@ -1345,6 +1384,7 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, } return FALSE; } + private: const LLUUID& blocked_id; }; @@ -1420,6 +1460,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& return false; } + chat.mSourceType = CHAT_SOURCE_SYSTEM; // There's a slim potential of a user-editable field being a url here? + LLViewerInventoryCategory* catp = NULL; catp = gInventory.getCategory(mObjectID); LLViewerInventoryItem* itemp = NULL; @@ -1464,8 +1506,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& { if (mFromGroup) { - std::string group_name; - if (gCacheName->getGroupName(mFromID, group_name)) + std::string group_name = LLGroupActions::getSLURL(mFromID); + //if (gCacheName->getGroupName(mFromID, group_name)) { from_string = LLTrans::getString("InvOfferAnObjectNamed") + " " + LLTrans::getString("'") + mFromName + LLTrans::getString("'") + " " + LLTrans::getString("InvOfferOwnedByGroup") @@ -1474,35 +1516,38 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByGroup") + " " + group_name + LLTrans::getString("'") + LLTrans::getString("."); } - else + /*else { from_string = LLTrans::getString("InvOfferAnObjectNamed") + " " + LLTrans::getString("'") + mFromName + LLTrans::getString("'") + " " + LLTrans::getString("InvOfferOwnedByUnknownGroup"); chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownGroup") + LLTrans::getString("."); - } + }*/ } else { - std::string full_name; - if (gCacheName->getFullName(mFromID, full_name)) - { + std::string full_name = LLAvatarActions::getSLURL(mFromID); + // [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) - if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(mFromID)) ) + if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(mFromID)) ) + { + if (gCacheName->getFullName(mFromID, full_name)) { full_name = RlvStrings::getAnonym(full_name); } - from_string = LLTrans::getString("InvOfferAnObjectNamed") + " " + LLTrans::getString("'") + mFromName - + LLTrans::getString("'") +" " + LLTrans::getString("InvOfferOwnedBy") + full_name; - chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedBy") + " " + full_name + LLTrans::getString("."); -// [/RLVa:KB] - //from_string = std::string("An object named '") + mFromName + "' owned by " + first_name + " " + last_name; - //chatHistory_string = mFromName + " owned by " + first_name + " " + last_name; + } + + from_string = LLTrans::getString("InvOfferAnObjectNamed") + " " + LLTrans::getString("'") + mFromName + LLTrans::getString("'") + ' '; + chatHistory_string = mFromName + ' '; + if (full_name.empty()) + { + from_string += LLTrans::getString("InvOfferOwnedByUnknownUser"); + chatHistory_string += LLTrans::getString("InvOfferOwnedByUnknownUser") + LLTrans::getString("."); } else +// [/RLVa:KB] { - from_string = LLTrans::getString("InvOfferAnObjectNamed") + " " + LLTrans::getString("'") - + mFromName + LLTrans::getString("'") + " " + LLTrans::getString("InvOfferOwnedByUnknownUser"); - chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownUser") + LLTrans::getString("."); + from_string += LLTrans::getString("InvOfferOwnedBy") + full_name; + chatHistory_string += LLTrans::getString("InvOfferOwnedBy") + " " + full_name + LLTrans::getString("."); } } } @@ -1565,8 +1610,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& //don't spam them if they are getting flooded if (check_offer_throttle(mFromName, true)) { - log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString("."); + log_message = chatHistory_string + ' ' + LLTrans::getString("InvOfferGaveYou") + ' ' + mDesc + LLTrans::getString("."); chat.mText = log_message; + if (mFromObject || !mFromGroup) + chat.mURL = mFromGroup ? LLGroupActions::getSLURL(mFromID) : LLAvatarActions::getSLURL(mFromID); + chat.mFromName = mFromName; LLFloaterChat::addChatHistory(chat); } @@ -1666,7 +1714,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& // send the message msg->sendReliable(mHost); - if (gSavedSettings.getBOOL("LogInventoryDecline")) + if (!mFromGroup && gSavedSettings.getBOOL("LogInventoryDecline")) { // [RLVa:KB] - Checked: 2010-09-23 (RLVa-1.2.1e) | Added: RLVa-1.2.1e if ( (rlv_handler_t::isEnabled()) && @@ -1727,1756 +1775,215 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& return false; } -void script_msg_api(const std::string& msg); +bool has_spam_bypass(bool is_friend, bool is_owned_by_me) +{ + static LLCachedControl antispam_not_mine(gSavedSettings,"AntiSpamNotMine"); + static LLCachedControl antispam_not_friend(gSavedSettings,"AntiSpamNotFriend"); + return (antispam_not_mine && is_owned_by_me) || (antispam_not_friend && is_friend); +} + bool is_spam_filtered(const EInstantMessage& dialog, bool is_friend, bool is_owned_by_me) { - // First, check the master filter + // First, check that this doesn't bypass. + if (has_spam_bypass(is_friend, is_owned_by_me)) return false; + + // Second, check the master filter static LLCachedControl antispam(gSavedSettings,"_NACL_Antispam"); if (antispam) return true; - // Second, check if this dialog type is even being filtered + // Third, check if this dialog type is even being filtered switch(dialog) { case IM_GROUP_NOTICE: case IM_GROUP_NOTICE_REQUESTED: - if (!gSavedSettings.getBOOL("AntiSpamGroupNotices")) return false; - break; + { + static const LLCachedControl filter("AntiSpamGroupNotices"); + return filter; + } case IM_GROUP_INVITATION: - if (!gSavedSettings.getBOOL("AntiSpamGroupInvites")) return false; - break; + { + static const LLCachedControl filter("AntiSpamGroupInvites"); + return filter; + } case IM_INVENTORY_OFFERED: case IM_TASK_INVENTORY_OFFERED: - if (!gSavedSettings.getBOOL("AntiSpamItemOffers")) return false; - break; + { + static const LLCachedControl filter("AntiSpamItemOffers"); + return filter; + } case IM_FROM_TASK_AS_ALERT: - if (!gSavedSettings.getBOOL("AntiSpamAlerts")) return false; - break; + { + static const LLCachedControl filter("AntiSpamAlerts"); + return filter; + } case IM_LURE_USER: - if (!gSavedSettings.getBOOL("AntiSpamTeleports")) return false; - break; + { + static const LLCachedControl filter("AntiSpamTeleports"); + return filter; + } case IM_TELEPORT_REQUEST: - if (!gSavedSettings.getBOOL("AntiSpamTeleportRequests")) return false; - break; + { + static const LLCachedControl filter("AntiSpamTeleportRequests"); + return filter; + } case IM_FRIENDSHIP_OFFERED: - if (!gSavedSettings.getBOOL("AntiSpamFriendshipOffers")) return false; - break; + { + static const LLCachedControl filter("AntiSpamFriendshipOffers"); + return filter; + } case IM_COUNT: + { // Bit of a hack, we should never get here unless we did this on purpose, though, doesn't matter because we'd do nothing anyway - if (!gSavedSettings.getBOOL("AntiSpamScripts")) return false; - break; + static const LLCachedControl filter( "AntiSpamScripts"); + return filter; + } default: return false; } - - // Third, possibly filtered, check the filter bypasses - static LLCachedControl antispam_not_mine(gSavedSettings,"AntiSpamNotMine"); - if (antispam_not_mine && is_owned_by_me) - return false; - - static LLCachedControl antispam_not_friend(gSavedSettings,"AntiSpamNotFriend"); - if (antispam_not_friend && is_friend) - return false; - - // Last, definitely filter - return true; } -void inventory_offer_handler(LLOfferInfo* info) +bool lure_callback(const LLSD& notification, const LLSD& response) { - // NaCl - Antispam Registry - if (NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_INVENTORY,info->mFromID)) + S32 option = 0; + if (response.isInteger()) { - delete info; - return; + option = response.asInteger(); } - // NaCl End - //If muted, don't even go through the messaging stuff. Just curtail the offer here. - if (LLMuteList::getInstance()->isMuted(info->mFromID, info->mFromName)) + else { - info->forceResponse(IOR_MUTE); - return; + option = LLNotificationsUtil::getSelectedOption(notification, response); } + + LLUUID from_id = notification["payload"]["from_id"].asUUID(); + LLUUID lure_id = notification["payload"]["lure_id"].asUUID(); + BOOL godlike = notification["payload"]["godlike"].asBoolean(); - if (!info->mFromGroup) script_msg_api(info->mFromID.asString() + ", 1"); - - // If the user wants to, accept all offers of any kind - if (gSavedSettings.getBOOL("AutoAcceptAllNewInventory")) + switch (option) { - info->forceResponse(IOR_ACCEPT); - return; + case 0: + { + // accept + gAgent.teleportViaLure(lure_id, godlike); + } + break; + case 1: + default: + // decline + send_simple_im(from_id, + LLStringUtil::null, + IM_LURE_DECLINED, + lure_id); + break; } + return false; +} +static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback); - // Avoid the Accept/Discard dialog if the user so desires. JC - if (gSavedSettings.getBOOL("AutoAcceptNewInventory") - && (info->mType == LLAssetType::AT_NOTECARD - || info->mType == LLAssetType::AT_LANDMARK - || info->mType == LLAssetType::AT_TEXTURE)) +bool goto_url_callback(const LLSD& notification, const LLSD& response) +{ + std::string url = notification["payload"]["url"].asString(); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if(1 == option) { - // For certain types, just accept the items into the inventory, - // and possibly open them on receipt depending upon "ShowNewInventory". - info->forceResponse(IOR_ACCEPT); - return; + LLWeb::loadURL(url); } + return false; +} +static LLNotificationFunctorRegistration goto_url_callback_reg("GotoURL", goto_url_callback); - if (gAgent.isDoNotDisturb() && info->mIM != IM_TASK_INVENTORY_OFFERED) // busy mode must not affect interaction with objects (STORM-565) +void process_improved_im(LLMessageSystem *msg, void **user_data) +{ + if (gNoRender) { - // Until throttling is implemented, busy mode should reject inventory instead of silently - // accepting it. SEE SL-39554 - info->forceResponse(IOR_DECLINE); return; } - - // Strip any SLURL from the message display. (DEV-2754) - std::string msg = info->mDesc; - int indx = msg.find(" ( http://slurl.com/secondlife/"); - if(indx == std::string::npos) - { - // try to find new slurl host - indx = msg.find(" ( http://maps.secondlife.com/secondlife/"); - } - if(indx >= 0) - { - LLStringUtil::truncate(msg, indx); - } - - LLSD args; - args["[OBJECTNAME]"] = msg; - - LLSD payload; - - // must protect against a NULL return from lookupHumanReadable() - std::string typestr = ll_safe_string(LLAssetType::lookupHumanReadable(info->mType)); - if (!typestr.empty()) - { - // human readable matches string name from strings.xml - // lets get asset type localized name - args["OBJECTTYPE"] = LLTrans::getString(typestr); - } - else - { - LL_WARNS("Messaging") << "LLAssetType::lookupHumanReadable() returned NULL - probably bad asset type: " << info->mType << LL_ENDL; - args["OBJECTTYPE"] = ""; - - // This seems safest, rather than propagating bogosity - LL_WARNS("Messaging") << "Forcing an inventory-decline for probably-bad asset type." << LL_ENDL; - info->forceResponse(IOR_DECLINE); - return; - } - - // Name cache callbacks don't store userdata, so can't save - // off the LLOfferInfo. Argh. - BOOL name_found = FALSE; - payload["from_id"] = info->mFromID; - args["OBJECTFROMNAME"] = info->mFromName; - args["NAME"] = info->mFromName; - if (info->mFromGroup) - { - std::string group_name; - if (gCacheName->getGroupName(info->mFromID, group_name)) - { - args["NAME"] = group_name; - name_found = TRUE; - } - } - else - { - std::string full_name; - if (gCacheName->getFullName(info->mFromID, full_name)) - { -// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Modified: RLVa-1.2.2a - // Only filter if the object owner is a nearby agent - if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(info->mFromID)) ) - { - full_name = RlvStrings::getAnonym(full_name); - } -// [/RLVa:KB] - args["NAME"] = full_name; - name_found = TRUE; - } - } - - - LLNotification::Params p("ObjectGiveItem"); - p.substitutions(args).payload(payload).functor(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2)); - - // Object -> Agent Inventory Offer - if (info->mFromObject) - { - p.name = name_found ? "ObjectGiveItem" : "ObjectGiveItemUnknownUser"; - } - else // Agent -> Agent Inventory Offer - { -// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Modified: RLVa-1.2.2a - // Only filter if the offer is from a nearby agent and if there's no open IM session (doesn't necessarily have to be focused) - if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(info->mFromID)) && - (!RlvUIEnabler::hasOpenIM(info->mFromID)) ) - { - args["NAME"] = RlvStrings::getAnonym(info->mFromName); - } -// [/RLVa:KB] - p.name = "UserGiveItem"; - } - - LLNotifications::instance().add(p); -} - - -bool group_vote_callback(const LLSD& notification, const LLSD& response) -{ - LLUUID group_id = notification["payload"]["group_id"].asUUID(); - S32 option = LLNotification::getSelectedOption(notification, response); - switch(option) - { - case 0: - // Vote Now - // Open up the voting tab - LLGroupActions::showTab(group_id, "voting_tab"); - break; - default: - // Vote Later or - // close button - break; - } - return false; -} -static LLNotificationFunctorRegistration group_vote_callback_reg("GroupVote", group_vote_callback); - -bool lure_callback(const LLSD& notification, const LLSD& response) -{ - S32 option = 0; - if (response.isInteger()) - { - option = response.asInteger(); - } - else - { - option = LLNotificationsUtil::getSelectedOption(notification, response); - } - - LLUUID from_id = notification["payload"]["from_id"].asUUID(); - LLUUID lure_id = notification["payload"]["lure_id"].asUUID(); - BOOL godlike = notification["payload"]["godlike"].asBoolean(); - - switch(option) - { - case 0: - { - // accept - gAgent.teleportViaLure(lure_id, godlike); - } - break; - case 3: - // profile - LLAvatarActions::showProfile(from_id); - LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]); //Respawn! - break; - case 1: - default: - // decline - send_simple_im(from_id, - LLStringUtil::null, - IM_LURE_DECLINED, - lure_id); - break; - } - return false; -} -static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback); - -bool goto_url_callback(const LLSD& notification, const LLSD& response) -{ - std::string url = notification["payload"]["url"].asString(); - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if(1 == option) - { - LLWeb::loadURL(url); - } - return false; -} -static LLNotificationFunctorRegistration goto_url_callback_reg("GotoURL", goto_url_callback); -static bool parse_lure_bucket(const std::string& bucket, - U64& region_handle, - LLVector3& pos, - LLVector3& look_at, - U8& region_access) -{ - // tokenize the bucket - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("|", "", boost::keep_empty_tokens); - tokenizer tokens(bucket, sep); - tokenizer::iterator iter = tokens.begin(); - - S32 e[8]; - try - { - for (int i = 0; i < 8 && iter != tokens.end(); ++i) - { - e[i] = boost::lexical_cast((*(iter++)).c_str()); - } - } - catch( boost::bad_lexical_cast& ) - { - LL_WARNS("parse_lure_bucket") - << "Couldn't parse lure bucket with content \"" << bucket << "\"." - << LL_ENDL; - return false; - } - // Grab region access - region_access = SIM_ACCESS_MIN; - if (iter != tokens.end()) - { - std::string access_str((*iter).c_str()); - LLStringUtil::trim(access_str); - if ( access_str == "A" ) - { - region_access = SIM_ACCESS_ADULT; - } - else if ( access_str == "M" ) - { - region_access = SIM_ACCESS_MATURE; - } - else if ( access_str == "PG" ) - { - region_access = SIM_ACCESS_PG; - } - } - - pos.setVec((F32)e[2], (F32)e[3], (F32)e[4]); - look_at.setVec((F32)e[5], (F32)e[6], (F32)e[7]); - - region_handle = to_region_handle(e[0], e[1]); - return true; -} - -// Strip out "Resident" for display, but only if the message came from a user -// (rather than a script) -static std::string clean_name_from_im(const std::string& name, EInstantMessage type) -{ - switch(type) - { - case IM_NOTHING_SPECIAL: - case IM_MESSAGEBOX: - case IM_GROUP_INVITATION: - case IM_INVENTORY_OFFERED: - case IM_INVENTORY_ACCEPTED: - case IM_INVENTORY_DECLINED: - case IM_GROUP_VOTE: - case IM_GROUP_MESSAGE_DEPRECATED: - //IM_TASK_INVENTORY_OFFERED - //IM_TASK_INVENTORY_ACCEPTED - //IM_TASK_INVENTORY_DECLINED - case IM_NEW_USER_DEFAULT: - case IM_SESSION_INVITE: - case IM_SESSION_P2P_INVITE: - case IM_SESSION_GROUP_START: - case IM_SESSION_CONFERENCE_START: - case IM_SESSION_SEND: - case IM_SESSION_LEAVE: - //IM_FROM_TASK - case IM_BUSY_AUTO_RESPONSE: - case IM_CONSOLE_AND_CHAT_HISTORY: - case IM_LURE_USER: - case IM_LURE_ACCEPTED: - case IM_LURE_DECLINED: - case IM_GODLIKE_LURE_USER: - case IM_TELEPORT_REQUEST: - case IM_GROUP_ELECTION_DEPRECATED: - //IM_GOTO_URL - //IM_FROM_TASK_AS_ALERT - case IM_GROUP_NOTICE: - case IM_GROUP_NOTICE_INVENTORY_ACCEPTED: - case IM_GROUP_NOTICE_INVENTORY_DECLINED: - case IM_GROUP_INVITATION_ACCEPT: - case IM_GROUP_INVITATION_DECLINE: - case IM_GROUP_NOTICE_REQUESTED: - case IM_FRIENDSHIP_OFFERED: - case IM_FRIENDSHIP_ACCEPTED: - case IM_FRIENDSHIP_DECLINED_DEPRECATED: - case IM_TYPING_START: - //IM_TYPING_STOP - return LLCacheName::cleanFullName(name); - default: - return name; - } -} - -static std::string clean_name_from_task_im(const std::string& msg, - BOOL from_group) -{ - boost::smatch match; - static const boost::regex returned_exp( - "(.*been returned to your inventory lost and found folder by )(.+)( (from|near).*)"); - if (boost::regex_match(msg, match, returned_exp)) - { - // match objects are 1-based for groups - std::string final = match[1].str(); - std::string name = match[2].str(); - // Don't try to clean up group names - if (!from_group) - { - if (LLAvatarName::useDisplayNames()) - { - // ...just convert to username - final += LLCacheName::buildUsername(name); - } - else - { - // ...strip out legacy "Resident" name - final += LLCacheName::cleanFullName(name); - } - } - final += match[3].str(); - return final; - } - return msg; -} - -void notification_display_name_callback(const LLUUID& id, - const LLAvatarName& av_name, - const std::string& name, - LLSD& substitutions, - const LLSD& payload) -{ - substitutions["NAME"] = av_name.getDisplayName(); - LLNotificationsUtil::add(name, substitutions, payload); -} - -// Callback for name resolution of a god/estate message -void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string message) -{ - LLSD args; - args["NAME"] = av_name.getNSName(); - args["MESSAGE"] = message; - LLNotificationsUtil::add("GodMessage", args); - - // Treat like a system message and put in chat history. - chat.mText = av_name.getNSName() + ": " + message; - - // Claim to be from a local agent so it doesn't go into console. - LLFloaterChat::addChat(chat, false, true); - -} - -// Replace wild cards in autoresponse messages -std::string replace_wildcards(std::string autoresponse, const LLUUID& id, const std::string& name) -{ - // Add in their legacy name - boost::algorithm::replace_all(autoresponse, "#n", name); - - LLSLURL slurl; - LLAgentUI::buildSLURL(slurl); - - // Add in our location's slurl - boost::algorithm::replace_all(autoresponse, "#r", slurl.getSLURLString()); - - // Add in their display name - LLAvatarName av_name; - boost::algorithm::replace_all(autoresponse, "#d", LLAvatarNameCache::get(id, &av_name) ? av_name.getDisplayName() : name); - - if (!isAgentAvatarValid()) return autoresponse; - // Add in idle time - LLStringUtil::format_map_t args; - args["[MINS]"] = boost::lexical_cast(gAgentAvatarp->mIdleTimer.getElapsedTimeF32()/60); - boost::algorithm::replace_all(autoresponse, "#i", LLTrans::getString("IM_autoresponse_minutes", args)); - - return autoresponse; -} - -void autoresponder_finish(bool show_autoresponded, const LLUUID& computed_session_id, const LLUUID& from_id, const std::string& name, const LLUUID& itemid, bool is_muted) -{ - LLAvatarName av_name; - const std::string ns_name(LLAvatarNameCache::get(from_id, &av_name) ? av_name.getNSName() : name); - void cmdline_printchat(const std::string& message); - if (show_autoresponded) - { - const std::string notice(LLTrans::getString("IM_autoresponded_to") + ' ' + ns_name); - is_muted ? cmdline_printchat(notice) : gIMMgr->addMessage(computed_session_id, from_id, name, notice); - } - if (LLViewerInventoryItem* item = gInventory.getItem(itemid)) - { - LLGiveInventory::doGiveInventoryItem(from_id, item, computed_session_id); - if (show_autoresponded) - { - const std::string notice(llformat("%s %s \"%s\"", ns_name.c_str(), LLTrans::getString("IM_autoresponse_sent_item").c_str(), item->getName().c_str())); - is_muted ? cmdline_printchat(notice) : gIMMgr->addMessage(computed_session_id, from_id, name, notice); - } - } -} - -void process_improved_im(LLMessageSystem *msg, void **user_data) -{ - if (gNoRender) - { - return; - } - LLUUID from_id; - BOOL from_group; - LLUUID to_id; - U8 offline; - U8 d = 0; - LLUUID session_id; - U32 timestamp; - std::string name; - std::string message; - U32 parent_estate_id = 0; - LLUUID region_id; - LLVector3 position; - U8 binary_bucket[MTUBYTES]; - S32 binary_bucket_size; - LLChat chat; - std::string buffer; - - // *TODO: Translate - need to fix the full name to first/last (maybe) - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, from_id); - msg->getBOOLFast(_PREHASH_MessageBlock, _PREHASH_FromGroup, from_group); - msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ToAgentID, to_id); - msg->getU8Fast( _PREHASH_MessageBlock, _PREHASH_Offline, offline); - msg->getU8Fast( _PREHASH_MessageBlock, _PREHASH_Dialog, d); - msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ID, session_id); - msg->getU32Fast( _PREHASH_MessageBlock, _PREHASH_Timestamp, timestamp); - //msg->getData("MessageBlock", "Count", &count); - msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_FromAgentName, name); - msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_Message, message); - // NaCl - Newline flood protection - static LLCachedControl AntiSpamEnabled(gSavedSettings,"AntiSpamEnabled",false); - if (AntiSpamEnabled && can_block(from_id)) - { - static LLCachedControl SpamNewlines(gSavedSettings,"_NACL_AntiSpamNewlines"); - boost::sregex_iterator iter(message.begin(), message.end(), NEWLINES); - if((U32)std::abs(std::distance(iter, boost::sregex_iterator())) > SpamNewlines) - { - NACLAntiSpamRegistry::blockOnQueue((U32)NACLAntiSpamRegistry::QUEUE_IM,from_id); - LL_INFOS() << "[antispam] blocked owner due to too many newlines: " << from_id << LL_ENDL; - if(gSavedSettings.getBOOL("AntiSpamNotify")) - { - LLSD args; - args["SOURCE"] = from_id.asString(); - args["AMOUNT"] = boost::lexical_cast(SpamNewlines); - LLNotificationsUtil::add("AntiSpamNewlineFlood", args); - } - return; - } - } - // NaCl End - msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_ParentEstateID, parent_estate_id); - msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_RegionID, region_id); - msg->getVector3Fast(_PREHASH_MessageBlock, _PREHASH_Position, position); - msg->getBinaryDataFast( _PREHASH_MessageBlock, _PREHASH_BinaryBucket, binary_bucket, 0, 0, MTUBYTES); - binary_bucket_size = msg->getSizeFast(_PREHASH_MessageBlock, _PREHASH_BinaryBucket); - EInstantMessage dialog = (EInstantMessage)d; - - // NaCl - Antispam Registry - if((dialog != IM_TYPING_START && dialog != IM_TYPING_STOP) - && NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_IM,from_id)) - return; - // NaCl End - - // make sure that we don't have an empty or all-whitespace name - LLStringUtil::trim(name); - if (name.empty()) - { - name = LLTrans::getString("Unnamed"); - } - - // Preserve the unaltered name for use in group notice mute checking. - std::string original_name = name; - - // IDEVO convert new-style "Resident" names for display - name = clean_name_from_im(name, dialog); - - // - if (region_id.notNull()) - LL_INFOS() << "RegionID: " << region_id.asString() << LL_ENDL; - // - - bool is_do_not_disturb = gAgent.isDoNotDisturb(); - BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat) - // object IMs contain sender object id in session_id (STORM-1209) - || dialog == IM_FROM_TASK && LLMuteList::getInstance()->isMuted(session_id); - BOOL is_linden = LLMuteList::getInstance()->isLinden(name); - BOOL is_owned_by_me = FALSE; - BOOL is_friend = (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL) ? false : true; - BOOL accept_im_from_only_friend = gSavedSettings.getBOOL("InstantMessagesFriendsOnly"); - - LLUUID computed_session_id = LLIMMgr::computeSessionID(dialog,from_id); - - chat.mMuted = is_muted && !is_linden; - chat.mFromID = from_id; - chat.mFromName = name; - chat.mSourceType = (from_id.isNull() || (name == std::string(SYSTEM_FROM))) ? CHAT_SOURCE_SYSTEM : CHAT_SOURCE_AGENT; - - if(chat.mSourceType == CHAT_SOURCE_AGENT) - { - LLSD args; - args["NAME"] = name; - } - - LLViewerObject *source = gObjectList.findObject(session_id); //Session ID is probably the wrong thing. - if (source || (source = gObjectList.findObject(from_id))) - { - is_owned_by_me = source->permYouOwner(); - } - - // NaCl - Antispam - if (is_spam_filtered(dialog, is_friend, is_owned_by_me)) return; - // NaCl End - - std::string separator_string(": "); - int message_offset = 0; - - //Handle IRC styled /me messages. - std::string prefix = message.substr(0, 4); - if (prefix == "/me " || prefix == "/me'") - { - chat.mChatStyle = CHAT_STYLE_IRC; - separator_string = ""; - message_offset = 3; - } - - // These bools are here because they would make mess of logic down below in IM_NOTHING_SPECIAL. - bool autorespond_status = gAgent.getAFK() || !gSavedPerAccountSettings.getBOOL("AutoresponseOnlyIfAway") || gSavedSettings.getBOOL("FakeAway"); - bool is_autorespond = !is_muted && autorespond_status && (is_friend || !gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneFriendsOnly")) && gSavedPerAccountSettings.getBOOL("AutoresponseAnyone"); - bool is_autorespond_muted = is_muted && gSavedPerAccountSettings.getBOOL("AutoresponseMuted"); - bool is_autorespond_nonfriends = !is_friend && !is_muted && autorespond_status && gSavedPerAccountSettings.getBOOL("AutoresponseNonFriends"); - - LLSD args; - switch(dialog) - { - case IM_CONSOLE_AND_CHAT_HISTORY: - args["MESSAGE"] = message; - - // Note: don't put the message in the IM history, even though was sent - // via the IM mechanism. - LLNotificationsUtil::add("SystemMessageTip",args); - break; - - case IM_NOTHING_SPECIAL: - // Don't show dialog, just do IM - if (!gAgent.isGodlike() - && gAgent.getRegion()->isPrelude() - && to_id.isNull() ) - { - // do nothing -- don't distract newbies in - // Prelude with global IMs - } -// [RLVa:KB] - Checked: 2011-05-28 (RLVa-1.4.0) - else if ( (rlv_handler_t::isEnabled()) && (offline == IM_ONLINE) && ("@version" == message) && - (!is_muted) && ((!accept_im_from_only_friend) || (is_friend)) ) - { - RlvUtil::sendBusyMessage(from_id, RlvStrings::getVersion(), session_id); - // We won't receive a typing stop message, so do that manually (see comment at the end of LLFloaterIMPanel::sendMsg) - LLPointer im_info = new LLIMInfo(gMessageSystem); - gIMMgr->processIMTypingStop(im_info); - } -// [/RLVa:KB] -// else if (offline == IM_ONLINE -// && is_do_not_disturb -// && !is_muted // Singu Note: Never if muted -// && from_id.notNull() //not a system message -// && to_id.notNull()) //not global message -// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0) - else if (offline == IM_ONLINE - && is_do_not_disturb - && !is_muted // Singu Note: Never if muted - && from_id.notNull() //not a system message - && to_id.notNull() //not global message - && RlvActions::canReceiveIM(from_id)) -// [/RLVa:KB] - { - // return a standard "do not disturb" message, but only do it to online IM - // (i.e. not other auto responses and not store-and-forward IM) - if (!gIMMgr->hasSession(session_id) || gSavedPerAccountSettings.getBOOL("AscentInstantMessageResponseRepeat")) - { - // if the user wants to repeat responses over and over or - // if there is not a panel for this conversation (i.e. it is a new IM conversation - // initiated by the other party) then... - send_do_not_disturb_message(msg, from_id, session_id); - } - - // now store incoming IM in chat history - buffer = separator_string + message.substr(message_offset); - - LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; - script_msg_api(from_id.asString() + ", 0"); - // add to IM panel, but do not bother the user - gIMMgr->addMessage( - session_id, - from_id, - name, - buffer, - name, - dialog, - parent_estate_id, - region_id, - position, - true); - - // pretend this is chat generated by self, so it does not show up on screen - chat.mText = std::string("IM: ") + name + separator_string + message.substr(message_offset); - LLFloaterChat::addChat(chat, true, true); - } -// else if (offline == IM_ONLINE && (is_autorespond || is_autorespond_nonfriends || is_autorespond_muted) && from_id.notNull() && to_id.notNull()) -// [RLVa:LF] - Same as above: Checked: 2010-11-30 (RLVa-1.3.0) - else if (offline == IM_ONLINE && (is_autorespond || is_autorespond_nonfriends || is_autorespond_muted) && from_id.notNull() && to_id.notNull() && RlvActions::canReceiveIM(from_id) && RlvActions::canSendIM(from_id)) -// [/RLVa:LF] - { - // now store incoming IM in chat history - - buffer = separator_string + message.substr(message_offset); - - LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; - if (!is_muted) script_msg_api(from_id.asString() + ", 0"); - bool send_autoresponse = !gIMMgr->hasSession(session_id) || gSavedPerAccountSettings.getBOOL("AscentInstantMessageResponseRepeat"); - - // add to IM panel, but do not bother the user - gIMMgr->addMessage( - session_id, - from_id, - name, - buffer, - name, - dialog, - parent_estate_id, - region_id, - position, - true); - - // pretend this is chat generated by self, so it does not show up on screen - chat.mText = std::string("IM: ") + name + separator_string + message.substr(message_offset); - LLFloaterChat::addChat( chat, TRUE, TRUE ); - - // return a standard "busy" message, but only do it to online IM - // (i.e. not other auto responses and not store-and-forward IM) - if (send_autoresponse) - { - // if there is not a panel for this conversation (i.e. it is a new IM conversation - // initiated by the other party) then... - std::string my_name; - LLAgentUI::buildFullname(my_name); - std::string response; - bool show_autoresponded = false; - LLUUID itemid; - if (is_muted) - { - response = gSavedPerAccountSettings.getString("AutoresponseMutedMessage"); - if (gSavedPerAccountSettings.getBOOL("AutoresponseMutedItem")) - itemid = static_cast(gSavedPerAccountSettings.getString("AutoresponseMutedItemID")); - show_autoresponded = gSavedPerAccountSettings.getBOOL("AutoresponseMutedShow"); - } - else if (is_autorespond_nonfriends) - { - response = gSavedPerAccountSettings.getString("AutoresponseNonFriendsMessage"); - if (gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsItem")) - itemid = static_cast(gSavedPerAccountSettings.getString("AutoresponseNonFriendsItemID")); - show_autoresponded = gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsShow"); - } - else if (is_autorespond) - { - response = gSavedPerAccountSettings.getString("AutoresponseAnyoneMessage"); - if (gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneItem")) - itemid = static_cast(gSavedPerAccountSettings.getString("AutoresponseAnyoneItemID")); - show_autoresponded = gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneShow"); - } - pack_instant_message( - gMessageSystem, - gAgentID, - FALSE, - gAgentSessionID, - from_id, - my_name, - replace_wildcards(response, from_id, name), - IM_ONLINE, - IM_BUSY_AUTO_RESPONSE, - session_id); - gAgent.sendReliableMessage(); - - autoresponder_finish(show_autoresponded, computed_session_id, from_id, name, itemid, is_muted); - } - // We stored the incoming IM in history before autoresponding, logically. - } - else if (from_id.isNull()) - { - // Messages from "Second Life" ID don't go to IM history - // messages which should be routed to IM window come from a user ID with name=SYSTEM_NAME - chat.mText = name + ": " + message; - LLFloaterChat::addChat(chat, FALSE, FALSE); - } - else if (to_id.isNull()) - { - // Message to everyone from GOD, look up the fullname since - // server always slams name to legacy names - LLAvatarNameCache::get(from_id, boost::bind(god_message_name_cb, _2, chat, message)); - } - else - { - // standard message, not from system - bool mute_im = is_muted; - if (accept_im_from_only_friend && !is_friend && !is_linden) - { - if (!gIMMgr->isNonFriendSessionNotified(session_id)) - { - std::string message = LLTrans::getString("IM_unblock_only_groups_friends"); - gIMMgr->addMessage(session_id, from_id, name, message); - gIMMgr->addNotifiedNonFriendSessionID(session_id); - } - - mute_im = true; - } - - std::string saved; - if(offline == IM_OFFLINE) - { - LLStringUtil::format_map_t args; - args["[LONG_TIMESTAMP]"] = formatted_time(timestamp); - saved = LLTrans::getString("Saved_message", args); - } - else if (!mute_im) script_msg_api(from_id.asString() + ", 0"); - buffer = separator_string + saved + message.substr(message_offset); - - LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; - - // Muted nonfriend code moved up - -// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0) - // Don't block offline IMs, or IMs from Lindens - if ( (rlv_handler_t::isEnabled()) && (offline != IM_OFFLINE) && (!RlvActions::canReceiveIM(from_id)) && (!is_linden) ) - { - if (!mute_im) - RlvUtil::sendBusyMessage(from_id, RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM_REMOTE), session_id); - buffer = RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM); - } -// [/RLVa:KB] - - if (!mute_im || is_linden) - { - gIMMgr->addMessage( - session_id, - from_id, - name, - buffer, - name, - dialog, - parent_estate_id, - region_id, - position, - true); - chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset); - LLFloaterChat::addChat(chat, true, false); - } - else - { - // muted user, so don't start an IM session, just record line in chat - // history. Pretend the chat is from a local agent, - // so it will go into the history but not be shown on screen. - chat.mText = buffer; - LLFloaterChat::addChat(chat, true, true); - - // Autoresponse to muted avatars - if (!gIMMgr->isNonFriendSessionNotified(session_id) && gSavedPerAccountSettings.getBOOL("AutoresponseMuted")) - { - std::string my_name; - LLAgentUI::buildFullname(my_name); - pack_instant_message( - gMessageSystem, - gAgentID, - FALSE, - gAgentSessionID, - from_id, - my_name, - replace_wildcards(gSavedPerAccountSettings.getString("AutoresponseMutedMessage"), from_id, name), - IM_ONLINE, - IM_BUSY_AUTO_RESPONSE, - session_id); - gAgent.sendReliableMessage(); - autoresponder_finish(gSavedPerAccountSettings.getBOOL("AutoresponseMutedShow"), computed_session_id, from_id, name, gSavedPerAccountSettings.getBOOL("AutoresponseMutedItem") ? static_cast(gSavedPerAccountSettings.getString("AutoresponseMutedItemID")) : LLUUID::null, true); - } - } - } - break; - - case IM_TYPING_START: - { - // Don't announce that someone has started messaging, if they're muted or when in busy mode - if (!is_muted && (!accept_im_from_only_friend || is_friend) && !is_do_not_disturb && !gIMMgr->hasSession(computed_session_id) && gSavedSettings.getBOOL("AscentInstantMessageAnnounceIncoming")) - { - LLAvatarName av_name; - std::string ns_name = LLAvatarNameCache::get(from_id, &av_name) ? av_name.getNSName() : name; - - gIMMgr->addMessage( - computed_session_id, - from_id, - name, - llformat("%s ", ns_name.c_str()) + LLTrans::getString("IM_announce_incoming"), - name, - IM_NOTHING_SPECIAL, - parent_estate_id, - region_id, - position, - false); - - - // This block is very similar to the one above, but is necessary, since a session is opened to announce incoming message.. - // In order to prevent doubling up on the first response, We neglect to send this if Repeat for each message is on. - if ((is_autorespond_nonfriends || is_autorespond) && !gSavedPerAccountSettings.getBOOL("AscentInstantMessageResponseRepeat")) - { - std::string my_name; - LLAgentUI::buildFullname(my_name); - std::string response; - bool show_autoresponded = false; - LLUUID itemid; - if (is_autorespond_nonfriends) - { - response = gSavedPerAccountSettings.getString("AutoresponseNonFriendsMessage"); - if (gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsItem")) - itemid = static_cast(gSavedPerAccountSettings.getString("AutoresponseNonFriendsItemID")); - show_autoresponded = gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsShow"); - } - else if (is_autorespond) - { - response = gSavedPerAccountSettings.getString("AutoresponseAnyoneMessage"); - if (gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneItem")) - itemid = static_cast(gSavedPerAccountSettings.getString("AutoresponseAnyoneItemID")); - show_autoresponded = gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneShow"); - } - pack_instant_message(gMessageSystem, gAgentID, false, gAgentSessionID, from_id, my_name, replace_wildcards(response, from_id, name), IM_ONLINE, IM_BUSY_AUTO_RESPONSE, session_id); - gAgent.sendReliableMessage(); - - autoresponder_finish(show_autoresponded, computed_session_id, from_id, name, itemid, is_muted); - } - } - LLPointer im_info = new LLIMInfo(gMessageSystem); - gIMMgr->processIMTypingStart(im_info); - script_msg_api(from_id.asString() + ", 4"); - } - break; - - case IM_TYPING_STOP: - { - LLPointer im_info = new LLIMInfo(gMessageSystem); - gIMMgr->processIMTypingStop(im_info); - script_msg_api(from_id.asString() + ", 5"); - } - break; - - case IM_MESSAGEBOX: - { - // This is a block, modeless dialog. - //*TODO: Translate - args["MESSAGE"] = message; - LLNotificationsUtil::add("SystemMessageTip", args); - } - break; - case IM_GROUP_NOTICE: - case IM_GROUP_NOTICE_REQUESTED: - { - LL_INFOS("Messaging") << "Received IM_GROUP_NOTICE message." << LL_ENDL; - // Read the binary bucket for more information. - struct notice_bucket_header_t - { - U8 has_inventory; - U8 asset_type; - LLUUID group_id; - }; - struct notice_bucket_full_t - { - struct notice_bucket_header_t header; - U8 item_name[DB_INV_ITEM_NAME_BUF_SIZE]; - }* notice_bin_bucket; - - // Make sure the binary bucket is big enough to hold the header - // and a null terminated item name. - if ( (binary_bucket_size < (S32)((sizeof(notice_bucket_header_t) + sizeof(U8)))) - || (binary_bucket[binary_bucket_size - 1] != '\0') ) - { - LL_WARNS("Messaging") << "Malformed group notice binary bucket" << LL_ENDL; - break; - } - - // The group notice packet does not have an AgentID. Obtain one from the name cache. - // If last name is "Resident" strip it out so the cache name lookup works. - U32 index = original_name.find(" Resident"); - if (index != std::string::npos) - { - original_name = original_name.substr(0, index); - } - std::string legacy_name = gCacheName->buildLegacyName(original_name); - LLUUID agent_id; - gCacheName->getUUID(legacy_name, agent_id); - - if (agent_id.isNull()) - { - LL_WARNS("Messaging") << "buildLegacyName returned null while processing " << original_name << LL_ENDL; - } - else if (LLMuteList::getInstance()->isMuted(agent_id)) - { - break; - } - - notice_bin_bucket = (struct notice_bucket_full_t*) &binary_bucket[0]; - U8 has_inventory = notice_bin_bucket->header.has_inventory; - U8 asset_type = notice_bin_bucket->header.asset_type; - LLUUID group_id = notice_bin_bucket->header.group_id; - std::string item_name = ll_safe_string((const char*) notice_bin_bucket->item_name); - - // If there is inventory, give the user the inventory offer. - LLOfferInfo* info = NULL; - - if (has_inventory) - { - info = new LLOfferInfo(); - - info->mIM = IM_GROUP_NOTICE; - info->mFromID = from_id; - info->mFromGroup = from_group; - info->mTransactionID = session_id; - info->mType = (LLAssetType::EType) asset_type; - info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType)); - std::string from_name; - - from_name += LLTrans::getString("AGroupMemberNamed") + " "; - from_name += name; - - info->mFromName = from_name; - info->mDesc = item_name; - info->mHost = msg->getSender(); - } - - std::string str(message); - - // Tokenize the string. - // TODO: Support escaped tokens ("||" -> "|") - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("|","",boost::keep_empty_tokens); - tokenizer tokens(str, sep); - tokenizer::iterator iter = tokens.begin(); - - std::string subj(*iter++); - std::string mes(*iter++); - - // Send the notification down the new path. - // For requested notices, we don't want to send the popups. - if (dialog != IM_GROUP_NOTICE_REQUESTED) - { - LLSD payload; - payload["subject"] = subj; - payload["message"] = mes; - payload["sender_name"] = name; - payload["group_id"] = group_id; - payload["inventory_name"] = item_name; - if(info && info->asLLSD()) - { - payload["inventory_offer"] = info->asLLSD(); - } - - LLSD args; - args["SUBJECT"] = subj; - args["MESSAGE"] = mes; - LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).timestamp(timestamp)); - } - - // Also send down the old path for now. - if (IM_GROUP_NOTICE_REQUESTED == dialog) - { - LLGroupActions::showNotice(subj,mes,group_id,has_inventory,item_name,info); - } - else - { - delete info; - } - } - break; - case IM_GROUP_INVITATION: - { - //if (is_do_not_disturb || is_muted) - if (is_muted) return; - if (is_do_not_disturb) - { - LLMessageSystem *msg = gMessageSystem; - send_do_not_disturb_message(msg,from_id); - } - else - { - LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL; - // Read the binary bucket for more information. - struct invite_bucket_t - { - S32 membership_fee; - LLUUID role_id; - }* invite_bucket; - - // Make sure the binary bucket is the correct size. - if (binary_bucket_size != sizeof(invite_bucket_t)) - { - LL_WARNS("Messaging") << "Malformed group invite binary bucket" << LL_ENDL; - break; - } - - invite_bucket = (struct invite_bucket_t*) &binary_bucket[0]; - S32 membership_fee = ntohl(invite_bucket->membership_fee); - // NaCl - Antispam - if (membership_fee > 0 && gSavedSettings.getBOOL("AntiSpamGroupFeeInvites")) - return; - // NaCl End - - LLSD payload; - payload["transaction_id"] = session_id; - payload["group_id"] = from_id; - payload["name"] = name; - payload["message"] = message; - payload["fee"] = membership_fee; - - LLSD args; - args["MESSAGE"] = message; - // we shouldn't pass callback functor since it is registered in LLFunctorRegistration - LLNotificationsUtil::add("JoinGroup", args, payload); - } - } - break; - - case IM_INVENTORY_OFFERED: - case IM_TASK_INVENTORY_OFFERED: - // Someone has offered us some inventory. - { - LLOfferInfo* info = new LLOfferInfo; - if (IM_INVENTORY_OFFERED == dialog) - { - struct offer_agent_bucket_t - { - S8 asset_type; - LLUUID object_id; - }* bucketp; - - if (sizeof(offer_agent_bucket_t) != binary_bucket_size) - { - LL_WARNS("Messaging") << "Malformed inventory offer from agent" << LL_ENDL; - delete info; - break; - } - bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0]; - info->mType = (LLAssetType::EType) bucketp->asset_type; - info->mObjectID = bucketp->object_id; - info->mFromObject = FALSE; - } - else // IM_TASK_INVENTORY_OFFERED - { - if (sizeof(S8) != binary_bucket_size) - { - LL_WARNS("Messaging") << "Malformed inventory offer from object" << LL_ENDL; - delete info; - break; - } - info->mType = (LLAssetType::EType) binary_bucket[0]; - info->mObjectID = LLUUID::null; - info->mFromObject = TRUE; - } - - info->mIM = dialog; - info->mFromID = from_id; - info->mFromGroup = from_group; - info->mTransactionID = session_id; - info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType)); - - info->mFromName = name; - info->mDesc = message; - info->mHost = msg->getSender(); - //if (((is_do_not_disturb && !is_owned_by_me) || is_muted)) - if (is_muted) - { - // Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331) - LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID); - fetch_item->startFetch(); - delete fetch_item; - - // Same as closing window - info->forceResponse(IOR_DECLINE); - } - /* Singu Note: Handle this inside inventory_offer_handler so if the user wants to autoaccept offers, they can while busy. - // old logic: busy mode must not affect interaction with objects (STORM-565) - // new logic: inventory offers from in-world objects should be auto-declined (CHUI-519) - // Singu Note: We should use old logic - else if (is_do_not_disturb && dialog != IM_TASK_INVENTORY_OFFERED) // busy mode must not affect interaction with objects (STORM-565) - { - // Until throttling is implemented, do not disturb mode should reject inventory instead of silently - // accepting it. SEE SL-39554 - info->forceResponse(IOR_DECLINE); - } - */ - else - { - inventory_offer_handler(info); - } - } - break; - - case IM_INVENTORY_ACCEPTED: - { -// args["NAME"] = name; -// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Modified: RLVa-1.2.2a - // Only anonymize the name if the agent is nearby, there isn't an open IM session to them and their profile isn't open - bool fRlvFilterName = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(from_id)) && - (!RlvUIEnabler::hasOpenProfile(from_id)) && (!RlvUIEnabler::hasOpenIM(from_id)); - args["NAME"] = (!fRlvFilterName) ? name : RlvStrings::getAnonym(name); -// [/RLVa:KB] - LLNotificationsUtil::add("InventoryAccepted", args); - break; - } - case IM_INVENTORY_DECLINED: - { -// args["NAME"] = name; -// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Modified: RLVa-1.2.2a - // Only anonymize the name if the agent is nearby, there isn't an open IM session to them and their profile isn't open - bool fRlvFilterName = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(from_id)) && - (!RlvUIEnabler::hasOpenProfile(from_id)) && (!RlvUIEnabler::hasOpenIM(from_id)); - args["NAME"] = (!fRlvFilterName) ? name : RlvStrings::getAnonym(name); -// [/RLVa:KB] - LLNotificationsUtil::add("InventoryDeclined", args); - break; - } - case IM_GROUP_VOTE: - { - LLSD args; - args["NAME"] = name; - args["MESSAGE"] = message; - - LLSD payload; - payload["group_id"] = session_id; - LLNotificationsUtil::add("GroupVote", args, payload); - } - break; - - case IM_GROUP_ELECTION_DEPRECATED: - { - LL_WARNS("Messaging") << "Received IM: IM_GROUP_ELECTION_DEPRECATED" << LL_ENDL; - } - break; - - case IM_SESSION_SEND: - { - if (!is_linden && is_do_not_disturb) - { - return; - } - - // Only show messages if we have a session open (which - // should happen after you get an "invitation" -// if ( !gIMMgr->hasSession(session_id) ) -// { -// return; -// } -// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c - LLFloaterIMPanel* pIMFloater = gIMMgr->findFloaterBySession(session_id); - if (!pIMFloater) - { - return; - } - - if (from_id != gAgentID && (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM) || gRlvHandler.hasBehaviour(RLV_BHVR_RECVIMFROM))) - { - switch (pIMFloater->getSessionType()) - { - case LLFloaterIMPanel::GROUP_SESSION: // Group chat - if (!RlvActions::canReceiveIM(session_id)) - return; - break; - case LLFloaterIMPanel::ADHOC_SESSION: // Conference chat - if (!RlvActions::canReceiveIM(from_id)) - message = RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM); - break; - default: - RLV_ASSERT(false); - return; - } - } -// [/RLVa:KB] - - // standard message, not from system - std::string saved; - if(offline == IM_OFFLINE) - { - LLStringUtil::format_map_t args; - args["[LONG_TIMESTAMP]"] = formatted_time(timestamp); - saved = LLTrans::getString("Saved_message", args); - } - buffer = separator_string + saved + message.substr(message_offset); - gIMMgr->addMessage( - session_id, - from_id, - name, - buffer, - ll_safe_string((char*)binary_bucket), - IM_SESSION_INVITE, - parent_estate_id, - region_id, - position, - true); - - std::string prepend_msg; - if (gAgent.isInGroup(session_id)&& gSavedSettings.getBOOL("OptionShowGroupNameInChatIM")) - { - prepend_msg = "["; - prepend_msg += std::string((char*)binary_bucket); - prepend_msg += "] "; - } - else - { - prepend_msg = std::string("IM: "); - } - chat.mText = prepend_msg + name + separator_string + saved + message.substr(message_offset); - LLFloaterChat::addChat(chat, TRUE, from_id == gAgentID); - } - break; - - case IM_FROM_TASK: - { - if (is_do_not_disturb && !is_owned_by_me) - { - return; - } - chat.mText = name + separator_string + message.substr(message_offset); - chat.mFromName = name; - - // Build a link to open the object IM info window. - std::string location = ll_safe_string((char*)binary_bucket, binary_bucket_size-1); - - if (session_id.notNull()) - { - chat.mFromID = session_id; - } - else - { - // This message originated on a region without the updated code for task id and slurl information. - // We just need a unique ID for this object that isn't the owner ID. - // If it is the owner ID it will overwrite the style that contains the link to that owner's profile. - // This isn't ideal - it will make 1 style for all objects owned by the the same person/group. - // This works because the only thing we can really do in this case is show the owner name and link to their profile. - chat.mFromID = from_id ^ gAgent.getSessionID(); - } - - chat.mSourceType = CHAT_SOURCE_OBJECT; - - // To conclude that the source type of message is CHAT_SOURCE_SYSTEM it's not - // enough to check only from name (i.e. fromName = "Second Life"). For example - // source type of messages from objects called "Second Life" should not be CHAT_SOURCE_SYSTEM. - bool chat_from_system = (SYSTEM_FROM == name) && region_id.isNull() && position.isNull(); - if(chat_from_system) - { - // System's UUID is NULL (fixes EXT-4766) - chat.mFromID = LLUUID::null; - chat.mSourceType = CHAT_SOURCE_SYSTEM; - } - else script_msg_api(chat.mFromID.asString() + ", 6"); - - // IDEVO Some messages have embedded resident names - message = clean_name_from_task_im(message, from_group); - - LLSD query_string; - query_string["owner"] = from_id; -// [RLVa:KB] - Checked: 2010-04-22 (RLVa-1.2.0f) | Added: RLVa-1.2.0f - if (rlv_handler_t::isEnabled()) - { - // NOTE: the chat message itself will be filtered in LLNearbyChatHandler::processChat() - if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) || gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) && (!from_group) && (RlvUtil::isNearbyAgent(from_id)) ) - { - query_string["rlv_shownames"] = TRUE; - - RlvUtil::filterNames(name); - chat.mFromName = name; - } - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) - { - std::string::size_type idxPos = location.find('/'); - if ( (std::string::npos != idxPos) && (RlvUtil::isNearbyRegion(location.substr(0, idxPos))) ) - location = RlvStrings::getString(RLV_STRING_HIDDEN_REGION); - } - } -// [/RLVa:KB] - query_string["slurl"] = location; - query_string["name"] = name; - if (from_group) - { - query_string["groupowned"] = "true"; - } - -// chat.mURL = LLSLURL("objectim", session_id, "").getSLURLString(); -// [SL:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Added: RLVa-1.2.2a - chat.mURL = LLSLURL("objectim", session_id, LLURI::mapToQueryString(query_string)).getSLURLString(); -// [/SL:KB] - chat.mText = name + separator_string + message.substr(message_offset); - - // Note: lie to LLFloaterChat::addChat(), pretending that this is NOT an IM, because - // IMs from objects don't open IM sessions. - LLFloaterChat::addChat(chat, FALSE, FALSE); - } - break; - - case IM_FROM_TASK_AS_ALERT: - if (is_do_not_disturb && !is_owned_by_me) - { - return; - } - { - // Construct a viewer alert for this message. - args["NAME"] = name; - args["MESSAGE"] = message; - LLNotificationsUtil::add("ObjectMessage", args); - } - break; - case IM_BUSY_AUTO_RESPONSE: - if (is_muted) - { - LL_DEBUGS("Messaging") << "Ignoring do-not-disturb response from " << from_id << LL_ENDL; - return; - } - else - { - gIMMgr->addMessage(session_id, from_id, name, separator_string + message.substr(message_offset), name, dialog, parent_estate_id, region_id, position, true); - } - break; - - case IM_LURE_USER: - case IM_TELEPORT_REQUEST: + LLUUID from_id; + BOOL from_group; + LLUUID to_id; + U8 offline; + U8 d = 0; + LLUUID session_id; + U32 timestamp; + std::string agentName; + std::string message; + U32 parent_estate_id = 0; + LLUUID region_id; + LLVector3 position; + U8 binary_bucket[MTUBYTES]; + S32 binary_bucket_size; + + // *TODO: Translate - need to fix the full name to first/last (maybe) + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, from_id); + msg->getBOOLFast(_PREHASH_MessageBlock, _PREHASH_FromGroup, from_group); + msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ToAgentID, to_id); + msg->getU8Fast(_PREHASH_MessageBlock, _PREHASH_Offline, offline); + msg->getU8Fast(_PREHASH_MessageBlock, _PREHASH_Dialog, d); + msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ID, session_id); + msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_Timestamp, timestamp); + //msg->getData("MessageBlock", "Count", &count); + msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_FromAgentName, agentName); + msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_Message, message); + // NaCl - Newline flood protection + auto antispam = NACLAntiSpamRegistry::getIfExists(); + if (antispam && can_block(from_id)) + { + static const LLCachedControl SpamNewlines("_NACL_AntiSpamNewlines"); + boost::sregex_iterator iter(message.begin(), message.end(), NEWLINES); + if((U32)std::abs(std::distance(iter, boost::sregex_iterator())) > SpamNewlines) { -// [RLVa:KB] - Checked: 2013-11-08 (RLVa-1.4.9) - // If we auto-accept the offer/request then this will override DnD status (but we'll still let the other party know later) - bool fRlvAutoAccept = (rlv_handler_t::isEnabled()) && - ( ((IM_LURE_USER == dialog) && (RlvActions::autoAcceptTeleportOffer(from_id))) || - ((IM_TELEPORT_REQUEST == dialog) && (RlvActions::autoAcceptTeleportRequest(from_id))) ); -// [/RLVa:KB] - - if (is_muted) - { - return; - } -// else if (is_do_not_disturb) -// [RLVa:KB] - Checked: 2013-11-08 (RLVa-1.4.9) - else if ( (is_do_not_disturb) && (!fRlvAutoAccept) ) -// [/RLVa:KB] - { - send_do_not_disturb_message(msg, from_id); - } - else + antispam->blockOnQueue(NACLAntiSpamRegistry::QUEUE_IM, from_id); + LL_INFOS() << "[antispam] blocked owner due to too many newlines: " << from_id << LL_ENDL; + if (gSavedSettings.getBOOL("AntiSpamNotify")) { - LLVector3 pos, look_at; - U64 region_handle(0); - U8 region_access(SIM_ACCESS_MIN); - std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size); - std::string region_access_str = LLStringUtil::null; - std::string region_access_icn = LLStringUtil::null; - std::string region_access_lc = LLStringUtil::null; - - bool canUserAccessDstRegion = true; - bool doesUserRequireMaturityIncrease = false; - - // Do not parse the (empty) lure bucket for TELEPORT_REQUEST - if (IM_TELEPORT_REQUEST != dialog && parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) - { - region_access_str = LLViewerRegion::accessToString(region_access); - region_access_icn = LLViewerRegion::getAccessIcon(region_access); - region_access_lc = region_access_str; - LLStringUtil::toLower(region_access_lc); - - if (!gAgent.isGodlike()) - { - switch (region_access) - { - case SIM_ACCESS_MIN : - case SIM_ACCESS_PG : - break; - case SIM_ACCESS_MATURE : - if (gAgent.isTeen()) - { - canUserAccessDstRegion = false; - } - else if (gAgent.prefersPG()) - { - doesUserRequireMaturityIncrease = true; - } - break; - case SIM_ACCESS_ADULT : - if (!gAgent.isAdult()) - { - canUserAccessDstRegion = false; - } - else if (!gAgent.prefersAdult()) - { - doesUserRequireMaturityIncrease = true; - } - break; - default : - llassert(0); - break; - } - } - } - -// [RLVa:KB] - Checked: 2013-11-08 (RLVa-1.4.9) - if (rlv_handler_t::isEnabled()) - { - if ( ((IM_LURE_USER == dialog) && (!RlvActions::canAcceptTpOffer(from_id))) || - ((IM_TELEPORT_REQUEST == dialog) && (!RlvActions::canAcceptTpRequest(from_id))) ) - { - RlvUtil::sendBusyMessage(from_id, RlvStrings::getString(RLV_STRING_BLOCKED_TPLUREREQ_REMOTE)); - if (is_do_not_disturb) - send_do_not_disturb_message(msg, from_id); - return; - } - - // Censor lure message if: 1) restricted from receiving IMs from the sender, or 2) teleport offer and @showloc=n restricted - if ( (!RlvActions::canReceiveIM(from_id)) || ((IM_LURE_USER == dialog) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))) ) - { - message = RlvStrings::getString(RLV_STRING_HIDDEN); - } - } -// [/RLVa:KB] - LLSD args; - // *TODO: Translate -> [FIRST] [LAST] (maybe) - args["NAME"] = name; - args["MESSAGE"] = message; - args["MATURITY_STR"] = region_access_str; - args["MATURITY_ICON"] = region_access_icn; - args["REGION_CONTENT_MATURITY"] = region_access_lc; - LLSD payload; - payload["from_id"] = from_id; - payload["lure_id"] = session_id; - payload["godlike"] = FALSE; - payload["region_maturity"] = region_access; - - /* Singu TODO: Figure if we should use these - if (!canUserAccessDstRegion) - { - LLNotification::Params params("TeleportOffered_MaturityBlocked"); - params.substitutions = args; - params.payload = payload; - LLPostponedNotification::add( params, from_id, false); - send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id); - send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id); - } - else if (doesUserRequireMaturityIncrease) - { - LLNotification::Params params("TeleportOffered_MaturityExceeded"); - params.substitutions = args; - params.payload = payload; - LLPostponedNotification::add( params, from_id, false); - } - else - */ - { - /* Singu Note: No default constructor for LLNotification::Params - LLNotification::Params params; - if (IM_LURE_USER == dialog) - { - params.name = "TeleportOffered"; - params.functor_name = "TeleportOffered"; - } - else if (IM_TELEPORT_REQUEST == dialog) - { - params.name = "TeleportRequest"; - params.functor_name = "TeleportRequest"; - } - */ - LLNotification::Params params(IM_LURE_USER == dialog ? "TeleportOffered" : "TeleportRequest"); - - params.substitutions = args; - params.payload = payload; - -// [RLVa:KB] - Checked: 20103-11-08 (RLVa-1.4.9) - if ( (rlv_handler_t::isEnabled()) && (fRlvAutoAccept) ) - { - if (IM_LURE_USER == dialog) - gRlvHandler.setCanCancelTp(false); - if (is_do_not_disturb) - send_do_not_disturb_message(msg, from_id); - LLNotifications::instance().forceResponse(LLNotification::Params(params.name).payload(payload), 0); - } - else - { - LLNotifications::instance().add(params); - - // - if (IM_LURE_USER == dialog) - gAgent.showLureDestination(name, region_handle, pos.mV[VX], pos.mV[VY], pos.mV[VZ]); - script_msg_api(from_id.asString().append(IM_LURE_USER == dialog ? ", 2" : ", 3")); - // - } -// [/RLVa:KB] -// LLNotifications::instance().add(params); - } - } - } - break; - - case IM_GODLIKE_LURE_USER: - { - LLVector3 pos, look_at; - U64 region_handle(0); - U8 region_access(SIM_ACCESS_MIN); - std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size); - std::string region_access_str = LLStringUtil::null; - std::string region_access_icn = LLStringUtil::null; - std::string region_access_lc = LLStringUtil::null; - - bool canUserAccessDstRegion = true; - bool doesUserRequireMaturityIncrease = false; - - if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) - { - region_access_str = LLViewerRegion::accessToString(region_access); - region_access_icn = LLViewerRegion::getAccessIcon(region_access); - region_access_lc = region_access_str; - LLStringUtil::toLower(region_access_lc); - - if (!gAgent.isGodlike()) - { - switch (region_access) - { - case SIM_ACCESS_MIN : - case SIM_ACCESS_PG : - break; - case SIM_ACCESS_MATURE : - if (gAgent.isTeen()) - { - canUserAccessDstRegion = false; - } - else if (gAgent.prefersPG()) - { - doesUserRequireMaturityIncrease = true; - } - break; - case SIM_ACCESS_ADULT : - if (!gAgent.isAdult()) - { - canUserAccessDstRegion = false; - } - else if (!gAgent.prefersAdult()) - { - doesUserRequireMaturityIncrease = true; - } - break; - default : - llassert(0); - break; - } - } - } - - LLSD args; - // *TODO: Translate -> [FIRST] [LAST] (maybe) - args["NAME"] = name; - args["MESSAGE"] = message; - args["MATURITY_STR"] = region_access_str; - args["MATURITY_ICON"] = region_access_icn; - args["REGION_CONTENT_MATURITY"] = region_access_lc; - LLSD payload; - payload["from_id"] = from_id; - payload["lure_id"] = session_id; - payload["godlike"] = TRUE; - payload["region_maturity"] = region_access; - - // do not show a message box, because you're about to be - // teleported. - LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0); - } - break; - - case IM_GOTO_URL: - { - LLSD args; - // n.b. this is for URLs sent by the system, not for - // URLs sent by scripts (i.e. llLoadURL) - if (binary_bucket_size <= 0) - { - LL_WARNS("Messaging") << "bad binary_bucket_size: " - << binary_bucket_size - << " - aborting function." << LL_ENDL; - return; - } - - std::string url; - - url.assign((char*)binary_bucket, binary_bucket_size-1); - args["MESSAGE"] = message; - args["URL"] = url; - LLSD payload; - payload["url"] = url; - LLNotificationsUtil::add("GotoURL", args, payload ); - } - break; - - case IM_FRIENDSHIP_OFFERED: - { - LLSD payload; - payload["from_id"] = from_id; - payload["session_id"] = session_id;; - payload["online"] = (offline == IM_ONLINE); - payload["sender"] = msg->getSender().getIPandPort(); - - if (is_muted) - { - LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1); - } - else - { - if (is_do_not_disturb) - { - send_do_not_disturb_message(msg, from_id); - } - args["[NAME]"] = name; - if(message.empty()) - { - //support for frienship offers from clients before July 2008 - LLNotificationsUtil::add("OfferFriendshipNoMessage", args, payload); - } - else - { - args["[MESSAGE]"] = message; - LLNotificationsUtil::add("OfferFriendship", args, payload); - } + args["SOURCE"] = from_id; + args["AMOUNT"] = fmt::to_string(SpamNewlines); + LLNotificationsUtil::add("AntiSpamNewlineFlood", args); } + return; } - break; + } + // NaCl End + msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_ParentEstateID, parent_estate_id); + msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_RegionID, region_id); + msg->getVector3Fast(_PREHASH_MessageBlock, _PREHASH_Position, position); + msg->getBinaryDataFast(_PREHASH_MessageBlock, _PREHASH_BinaryBucket, binary_bucket, 0, 0, MTUBYTES); + binary_bucket_size = msg->getSizeFast(_PREHASH_MessageBlock, _PREHASH_BinaryBucket); + EInstantMessage dialog = (EInstantMessage)d; - case IM_FRIENDSHIP_ACCEPTED: - { - // In the case of an offline IM, the formFriendship() may be extraneous - // as the database should already include the relationship. But it - // doesn't hurt for dupes. - LLAvatarTracker::formFriendship(from_id); - - std::vector strings; - strings.push_back(from_id.asString()); - send_generic_message("requestonlinenotification", strings); - - args["NAME"] = name; - LLSD payload; - payload["from_id"] = from_id; - LLAvatarNameCache::get(from_id, boost::bind(¬ification_display_name_callback, _1, _2, "FriendshipAccepted", args, payload)); - } - break; + // NaCl - Antispam Registry + if (antispam && (dialog != IM_TYPING_START && dialog != IM_TYPING_STOP) + && antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_IM, from_id)) + return; + // NaCl End - case IM_FRIENDSHIP_DECLINED_DEPRECATED: - default: - LL_WARNS("Messaging") << "Instant message calling for unknown dialog " - << (S32)dialog << LL_ENDL; - break; - } + LLHost sender = msg->getSender(); - LLWindow* viewer_window = gViewerWindow->getWindow(); - if (viewer_window && viewer_window->getMinimized()) - { - viewer_window->flashIcon(5.f); - } + LLIMProcessing::processNewMessage(from_id, + from_group, + to_id, + offline, + dialog, + session_id, + timestamp, + agentName, + message, + parent_estate_id, + region_id, + position, + binary_bucket, + binary_bucket_size, + sender); } -void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id) +void send_do_not_disturb_message(LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id) { if (gAgent.isDoNotDisturb()) { std::string my_name; LLAgentUI::buildFullname(my_name); - std::string from_name; - msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_FromAgentName, from_name); - from_name = LLCacheName::cleanFullName(from_name); + std::string name; + gCacheName->getFullName(from_id, name); std::string response = gSavedPerAccountSettings.getString("BusyModeResponse"); pack_instant_message( msg, @@ -3485,24 +1992,21 @@ void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, c gAgent.getSessionID(), from_id, my_name, - replace_wildcards(response, from_id, from_name), + replace_wildcards(response, from_id, name), IM_ONLINE, - IM_BUSY_AUTO_RESPONSE); + IM_BUSY_AUTO_RESPONSE, + session_id); gAgent.sendReliableMessage(); LLAvatarName av_name; - std::string ns_name = LLAvatarNameCache::get(from_id, &av_name) ? av_name.getNSName() : from_name; - LLUUID session_id; - msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ID, session_id); - if (gSavedPerAccountSettings.getBOOL("BusyModeResponseShow")) gIMMgr->addMessage(session_id, from_id, from_name, LLTrans::getString("IM_autoresponded_to") + ' ' + ns_name); + std::string ns_name = LLAvatarNameCache::get(from_id, &av_name) ? av_name.getNSName() : name; + const auto show = gSavedPerAccountSettings.getBOOL("BusyModeResponseShow"); + if (show) gIMMgr->addMessage(session_id, from_id, name, LLTrans::getString("IM_autoresponded_to") + ' ' + ns_name); if (!gSavedPerAccountSettings.getBOOL("BusyModeResponseItem")) return; // Not sending an item, finished if (LLViewerInventoryItem* item = gInventory.getItem(static_cast(gSavedPerAccountSettings.getString("BusyModeResponseItemID")))) { - U8 d; - msg->getU8Fast(_PREHASH_MessageBlock, _PREHASH_Dialog, d); - LLUUID computed_session_id = LLIMMgr::computeSessionID(static_cast(d), from_id); - LLGiveInventory::doGiveInventoryItem(from_id, item, computed_session_id); - if (gSavedPerAccountSettings.getBOOL("BusyModeResponseShow")) - gIMMgr->addMessage(computed_session_id, from_id, from_name, llformat("%s %s \"%s\"", ns_name.c_str(), LLTrans::getString("IM_autoresponse_sent_item").c_str(), item->getName().c_str())); + LLGiveInventory::doGiveInventoryItem(from_id, item, session_id); + if (show) + gIMMgr->addMessage(session_id, from_id, name, llformat("%s %s \"%s\"", ns_name.c_str(), LLTrans::getString("IM_autoresponse_sent_item").c_str(), item->getName().c_str())); } } } @@ -3511,9 +2015,8 @@ bool callingcard_offer_callback(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLUUID fid; - LLUUID from_id; LLMessageSystem* msg = gMessageSystem; - switch(option) + switch (option) { case 0: // accept @@ -3546,6 +2049,7 @@ bool callingcard_offer_callback(const LLSD& notification, const LLSD& response) return false; } + static LLNotificationFunctorRegistration callingcard_offer_cb_reg("OfferCallingCard", callingcard_offer_callback); void process_offer_callingcard(LLMessageSystem* msg, void**) @@ -3561,8 +2065,9 @@ void process_offer_callingcard(LLMessageSystem* msg, void**) msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, source_id); // NaCl - Antispam Registry - if(NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_CALLING_CARD,source_id)) - return; + if (auto antispam = NACLAntiSpamRegistry::getIfExists()) + if (antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_CALLING_CARD, source_id)) + return; // NaCl End LLUUID tid; @@ -3576,7 +2081,7 @@ void process_offer_callingcard(LLMessageSystem* msg, void**) LLViewerObject* source = gObjectList.findObject(source_id); LLSD args; std::string source_name; - if(source && source->isAvatar()) + if (source && source->isAvatar()) { LLNameValue* nvfirst = source->getNVPair("FirstName"); LLNameValue* nvlast = source->getNVPair("LastName"); @@ -3587,7 +2092,7 @@ void process_offer_callingcard(LLMessageSystem* msg, void**) } } - if(!source_name.empty()) + if (!source_name.empty()) { if (gAgent.isDoNotDisturb() || LLMuteList::getInstance()->isMuted(source_id, source_name, LLMute::flagTextChat)) @@ -3618,7 +2123,7 @@ void process_decline_callingcard(LLMessageSystem* msg, void**) } #if 0 // Google translate doesn't work anymore -class ChatTranslationReceiver : public LLTranslate::TranslationReceiver +class ChatTranslationReceiver final : public LLTranslate::TranslationReceiver { public : ChatTranslationReceiver(const std::string &fromLang, const std::string &toLang, LLChat *chat, @@ -3656,7 +2161,7 @@ public : delete m_chat; } - /*virtual*/ char const* getName(void) const { return "ChatTranslationReceiver"; } + char const* getName() const override { return "ChatTranslationReceiver"; } private: LLChat *m_chat; @@ -3664,7 +2169,7 @@ public : }; #endif -void add_floater_chat(const LLChat &chat, const BOOL history) +void add_floater_chat(LLChat &chat, const bool history) { if (history) { @@ -3679,7 +2184,7 @@ void add_floater_chat(const LLChat &chat, const BOOL history) } #if 0 // Google translate doesn't work anymore -void check_translate_chat(const std::string &mesg, LLChat &chat, const BOOL history) +void check_translate_chat(const std::string &mesg, LLChat &chat, const bool history) { const bool translate = LLUI::sConfigGroup->getBOOL("TranslateChat"); @@ -3701,42 +2206,7 @@ void check_translate_chat(const std::string &mesg, LLChat &chat, const BOOL hist } #endif -// defined in llchatbar.cpp, but not declared in any header -void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel); - -void script_msg_api(const std::string& msg) -{ - static const LLCachedControl channel("ScriptMessageAPI"); - if (!channel) return; - static const LLCachedControl key("ScriptMessageAPIKey"); - std::string str; - for (size_t i = 0, keysize = key().size(); i != msg.size(); ++i) - str += msg[i] ^ key()[i%keysize]; - send_chat_from_viewer(LLBase64::encode(reinterpret_cast(str.c_str()), str.size()), CHAT_TYPE_WHISPER, channel); -} - -class AuthHandler : public LLHTTPClient::ResponderWithCompleted -{ -protected: - /*virtual*/ void completedRaw(LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) - { - std::string content; - decode_raw_body(channels, buffer, content); - if (mStatus == HTTP_OK) - { - send_chat_from_viewer("AUTH:" + content, CHAT_TYPE_WHISPER, 427169570); - } - else - { - LL_WARNS() << "Hippo AuthHandler: non-OK HTTP status " << mStatus << " for URL " << mURL << " (" << mReason << "). Error body: \"" << content << "\"." << LL_ENDL; - } - } - - /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return authHandler_timeout; } - /*virtual*/ char const* getName(void) const { return "AuthHandler"; } -}; - -void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) +void process_chat_from_simulator(LLMessageSystem* msg, void** user_data) { LLChat chat; std::string mesg; @@ -3769,6 +2239,8 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // Object owner for objects msg->getUUID("ChatData", "OwnerID", owner_id); + bool has_owner = owner_id.notNull(); + if (chatter && has_owner) chatter->mOwnerID = owner_id; // Singu Note: Try to get Owner whenever possible msg->getU8Fast(_PREHASH_ChatData, _PREHASH_SourceType, source_temp); chat.mSourceType = (EChatSourceType)source_temp; @@ -3777,9 +2249,10 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) chat.mChatType = (EChatType)type_temp; // NaCL - Antispam Registry - if((chat.mChatType != CHAT_TYPE_START && chat.mChatType != CHAT_TYPE_STOP) //Chat type isn't typing - &&((owner_id.isNull() && NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_CHAT,from_id)) //Spam from an object? - ||(NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_CHAT,owner_id)))) //Spam from a resident? + auto antispam = NACLAntiSpamRegistry::getIfExists(); + if (antispam && chat.mChatType != CHAT_TYPE_START && chat.mChatType != CHAT_TYPE_STOP //Chat type isn't typing + && (antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_CHAT, from_id, !has_owner ? LFIDBearer::AVATAR : LFIDBearer::OBJECT) // Spam from an object or avatar? + || (has_owner && (antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_CHAT, owner_id))))) // Spam from a resident? return; // NaCl End @@ -3797,7 +2270,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) LLAvatarName av_name; if (LLAvatarNameCache::get(from_id, &av_name)) { - chat.mFromName = av_name.getDisplayName(); + chat.mFromName = av_name.getNSName(); } else { @@ -3817,8 +2290,8 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) bool is_do_not_disturb = gAgent.isDoNotDisturb(); - BOOL is_muted = FALSE; - BOOL is_linden = FALSE; + bool is_muted = false; + bool is_linden = false; is_muted = LLMuteList::getInstance()->isMuted( from_id, from_name, @@ -3827,87 +2300,21 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT && LLMuteList::getInstance()->isLinden(from_name); - BOOL is_audible = (CHAT_AUDIBLE_FULLY == chat.mAudible); + msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg); - static std::map sChatObjectAuth; + bool handle_obj_auth(const LLUUID& from_id, const std::string& mesg); + if (source_temp == CHAT_SOURCE_OBJECT && type_temp == CHAT_TYPE_OWNER && handle_obj_auth(from_id, mesg)) return; + + if (is_muted && (chat.mSourceType == CHAT_SOURCE_OBJECT)) + { + return; + } + BOOL is_audible = (CHAT_AUDIBLE_FULLY == chat.mAudible); // // because I moved it to above //chatter = gObjectList.findObject(from_id); // - - msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg); - - if ((source_temp == CHAT_SOURCE_OBJECT) && (type_temp == CHAT_TYPE_OWNER) && - (mesg.substr(0, 3) == "># ")) - { - if (mesg.substr(mesg.size()-3, 3) == " #<"){ - // hello from object - if (from_id.isNull()) return; - char buf[200]; - snprintf(buf, 200, "%s v%d.%d.%d", gVersionChannel, gVersionMajor, gVersionMinor, gVersionPatch); - send_chat_from_viewer(buf, CHAT_TYPE_WHISPER, 427169570); - sChatObjectAuth[from_id] = 1; - return; - } - else if (from_id.isNull() || sChatObjectAuth.find(from_id) != sChatObjectAuth.end()) - { - LLUUID key; - if (key.set(mesg.substr(3, 36),false)) - { - // object command found - if (key.isNull() && (mesg.size() == 39)) - { - // clear all nameplates - for (int i=0; i(obj)) - { - avatar->clearNameFromChat(); - } - } - } - else - { - if (key.isNull()) - { - LL_WARNS() << "Nameplate from chat on NULL avatar (ignored)" << LL_ENDL; - return; - } - LLVOAvatar *avatar = gObjectList.findAvatar(key); - if (!avatar) - { - LL_WARNS() << "Nameplate from chat on invalid avatar (ignored)" << LL_ENDL; - return; - } - if (mesg.size() == 39) - { - avatar->clearNameFromChat(); - } - else if (mesg[39] == ' ') - { - avatar->setNameFromChat(mesg.substr(40)); - } - } - return; - } - else if (mesg.substr(2, 9) == " floater ") - { - HippoFloaterXml::execute(mesg.substr(11)); - return; - } - else if (mesg.substr(2, 6) == " auth ") - { - std::string authUrl = mesg.substr(8); - authUrl += (authUrl.find('?') != std::string::npos)? "&auth=": "?auth="; - authUrl += gAuthString; - LLHTTPClient::get(authUrl, new AuthHandler); - return; - } - } - } - if (chatter) { chat.mPosAgent = chatter->getPositionAgent(); @@ -3983,18 +2390,17 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) if (is_audible) { // NaCl - Newline flood protection - static LLCachedControl AntiSpamEnabled(gSavedSettings,"AntiSpamEnabled",false); - if (AntiSpamEnabled && can_block(from_id)) + if (antispam && can_block(from_id)) { - static LLCachedControl SpamNewlines(gSavedSettings,"_NACL_AntiSpamNewlines"); + static const LLCachedControl SpamNewlines("_NACL_AntiSpamNewlines"); boost::sregex_iterator iter(mesg.begin(), mesg.end(), NEWLINES); if((U32)std::abs(std::distance(iter, boost::sregex_iterator())) > SpamNewlines) { - NACLAntiSpamRegistry::blockOnQueue((U32)NACLAntiSpamRegistry::QUEUE_CHAT,owner_id); + antispam->blockOnQueue(NACLAntiSpamRegistry::QUEUE_CHAT, owner_id); if(gSavedSettings.getBOOL("AntiSpamNotify")) { LLSD args; - args["MESSAGE"] = "Chat: Blocked newline flood from "+owner_id.asString(); + args["MESSAGE"] = "Chat: Blocked newline flood from " + LLAvatarActions::getSLURL(owner_id); LLNotificationsUtil::add("SystemMessageTip", args); } return; @@ -4011,7 +2417,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) BOOL visible_in_chat_bubble = FALSE; std::string verb; - color.setVec(1.f,1.f,1.f,1.f); + color.setVec(1.f, 1.f, 1.f, 1.f); // [RLVa:KB] - Checked: 2010-04-23 (RLVa-1.2.0f) | Modified: RLVa-1.2.0f if ( (rlv_handler_t::isEnabled()) && (CHAT_TYPE_START != chat.mChatType) && (CHAT_TYPE_STOP != chat.mChatType) ) @@ -4053,7 +2459,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) { RlvUtil::filterNames(chat.mFromName); } - else if (chat.mFromID != gAgent.getID()) + else if (chat.mFromID != gAgentID) { chat.mFromName = RlvStrings::getAnonym(chat.mFromName); chat.mRlvNamesFiltered = TRUE; @@ -4085,7 +2491,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // Look for IRC-style emotes here so chatbubbles work std::string prefix = mesg.substr(0, 4); - if (prefix == "/me " || prefix == "/me'") + if (boost::iequals(prefix, "/me ") || boost::iequals(prefix, "/me'")) // { chat.mText = chat.mFromName; mesg = mesg.substr(3); @@ -4108,7 +2514,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) } return; } - else if (CHAT_TYPE_STOP == chat.mChatType) + if (CHAT_TYPE_STOP == chat.mChatType) { LLLocalSpeakerMgr::getInstance()->setSpeakerTyping(from_id, FALSE); @@ -4141,7 +2547,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) } else { - switch(chat.mChatType) + switch (chat.mChatType) { case CHAT_TYPE_WHISPER: verb = " " + LLTrans::getString("whisper") + " "; @@ -4157,7 +2563,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) std::string strExecuted, strFailed, strRetained, *pstr; boost_tokenizer tokens(mesg, boost::char_separator(",", "", boost::drop_empty_tokens)); - for (boost_tokenizer::iterator itToken = tokens.begin(); itToken != tokens.end(); ++itToken) + for (auto itToken = tokens.begin(); itToken != tokens.end(); ++itToken) { std::string strCmd = *itToken; @@ -4288,11 +2694,19 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // of TeleportRequest, then this info is redundant, but if the sim // initiated the teleport (via a script call, being killed, etc.) // then this info is news to us. -void process_teleport_start(LLMessageSystem *msg, void**) +void process_teleport_start(LLMessageSystem* msg, void**) { + // on teleport, don't tell them about destination guide anymore + //LLFirstUse::notUsingDestinationGuide(false); U32 teleport_flags = 0x0; msg->getU32("Info", "TeleportFlags", teleport_flags); + if (gAgent.getTeleportState() == LLAgent::TELEPORT_MOVING) + { + // Race condition? + LL_WARNS("Messaging") << "Got TeleportStart, but teleport already in progress. TeleportFlags=" << teleport_flags << LL_ENDL; + } + LL_DEBUGS("Messaging") << "Got TeleportStart with TeleportFlags=" << teleport_flags << ". gTeleportDisplay: " << gTeleportDisplay << ", gAgent.mTeleportState: " << gAgent.getTeleportState() << LL_ENDL; // if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) @@ -4310,10 +2724,11 @@ void process_teleport_start(LLMessageSystem *msg, void**) // Freeze the UI and show progress bar // Note: could add data here to differentiate between normal teleport and death. - if( gAgent.getTeleportState() == LLAgent::TELEPORT_NONE ) + if (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE) { gTeleportDisplay = TRUE; - gAgent.setTeleportState( LLAgent::TELEPORT_START ); + gAgent.setTeleportState(LLAgent::TELEPORT_START); + make_ui_sound("UISndTeleportOut"); LL_INFOS("Messaging") << "Teleport initiated by remote TeleportStart message with TeleportFlags: " << teleport_flags << LL_ENDL; @@ -4327,7 +2742,7 @@ void process_teleport_progress(LLMessageSystem* msg, void**) { LLUUID agent_id; msg->getUUID("AgentData", "AgentID", agent_id); - if((gAgent.getID() != agent_id) + if ((gAgent.getID() != agent_id) || (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE)) { LL_WARNS("Messaging") << "Unexpected teleport progress message." << LL_ENDL; @@ -4348,14 +2763,14 @@ void process_teleport_progress(LLMessageSystem* msg, void**) } std::string buffer; msg->getString("Info", "Message", buffer); - LL_DEBUGS("Messaging") << "teleport progress: " << buffer << LL_ENDL; + LL_DEBUGS("Messaging") << "teleport progress: " << buffer << " flags: " << teleport_flags << LL_ENDL; //Sorta hacky...default to using simulator raw messages //if we don't find the coresponding mapping in our progress mappings std::string message = buffer; if (LLAgent::sTeleportProgressMessages.find(buffer) != - LLAgent::sTeleportProgressMessages.end() ) + LLAgent::sTeleportProgressMessages.end()) { message = LLAgent::sTeleportProgressMessages[buffer]; } @@ -4363,13 +2778,15 @@ void process_teleport_progress(LLMessageSystem* msg, void**) gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages[message]); } -class LLFetchInWelcomeArea : public LLInventoryFetchDescendentsObserver +class LLFetchInWelcomeArea final : public LLInventoryFetchDescendentsObserver { public: - LLFetchInWelcomeArea(const uuid_vec_t &ids) : + LLFetchInWelcomeArea(const uuid_vec_t& ids) : LLInventoryFetchDescendentsObserver(ids) - {} - virtual void done() + { + } + + void done() override { LLIsType is_landmark(LLAssetType::AT_LANDMARK); LLIsType is_card(LLAssetType::AT_CALLINGCARD); @@ -4381,7 +2798,7 @@ class LLFetchInWelcomeArea : public LLInventoryFetchDescendentsObserver uuid_vec_t::iterator it = mComplete.begin(); uuid_vec_t::iterator end = mComplete.end(); - for(; it != end; ++it) + for (; it != end; ++it) { gInventory.collectDescendentsIf( (*it), @@ -4397,13 +2814,13 @@ class LLFetchInWelcomeArea : public LLInventoryFetchDescendentsObserver is_card); } LLSD args; - if ( land_items.size() > 0 ) + if (!land_items.empty()) { // Show notification that they can now teleport to landmarks. Use a random landmark from the inventory S32 random_land = ll_rand(land_items.size() - 1); args["NAME"] = land_items[random_land]->getName(); LLNotificationsUtil::add("TeleportToLandmark",args); } - if ( card_items.size() > 0 ) + if (!card_items.empty()) { // Show notification that they can now contact people. Use a random calling card from the inventory S32 random_card = ll_rand(card_items.size() - 1); args["NAME"] = card_items[random_card]->getName(); @@ -4416,18 +2833,17 @@ class LLFetchInWelcomeArea : public LLInventoryFetchDescendentsObserver }; - -class LLPostTeleportNotifiers : public LLEventTimer +class LLPostTeleportNotifiers final : public LLEventTimer { public: LLPostTeleportNotifiers(); virtual ~LLPostTeleportNotifiers(); //function to be called at the supplied frequency - virtual BOOL tick(); + BOOL tick() override; }; -LLPostTeleportNotifiers::LLPostTeleportNotifiers() : LLEventTimer( 2.0 ) +LLPostTeleportNotifiers::LLPostTeleportNotifiers() : LLEventTimer(2.0) { }; @@ -4438,21 +2854,21 @@ LLPostTeleportNotifiers::~LLPostTeleportNotifiers() BOOL LLPostTeleportNotifiers::tick() { BOOL all_done = FALSE; - if ( gAgent.getTeleportState() == LLAgent::TELEPORT_NONE ) + if (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE) { // get callingcards and landmarks available to the user arriving. uuid_vec_t folders; const LLUUID callingcard_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); - if(callingcard_id.notNull()) + if (callingcard_id.notNull()) folders.push_back(callingcard_id); const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); - if(folder_id.notNull()) + if (folder_id.notNull()) folders.push_back(folder_id); - if(!folders.empty()) + if (!folders.empty()) { LLFetchInWelcomeArea* fetcher = new LLFetchInWelcomeArea(folders); fetcher->startFetch(); - if(fetcher->isFinished()) + if (fetcher->isFinished()) { fetcher->done(); } @@ -4468,7 +2884,6 @@ BOOL LLPostTeleportNotifiers::tick() } - // Teleport notification from the simulator // We're going to pretend to be a new agent void process_teleport_finish(LLMessageSystem* msg, void**) @@ -4485,9 +2900,11 @@ void process_teleport_finish(LLMessageSystem* msg, void**) // Teleport is finished; it can't be cancelled now. gViewerWindow->setProgressCancelButtonVisible(FALSE); + //gPipeline.doResetVertexBuffers(true); // Animesh+ + // Do teleport effect for where you're leaving // VEFFECT: TeleportStart - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); + LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); effectp->setPositionGlobal(gAgent.getPositionGlobal()); effectp->setColor(LLColor4U(gAgent.getEffectColor())); LLHUDManager::getInstance()->sendEffects(); @@ -4506,11 +2923,12 @@ void process_teleport_finish(LLMessageSystem* msg, void**) U32 teleport_flags; msg->getU32Fast(_PREHASH_Info, _PREHASH_TeleportFlags, teleport_flags); + std::string seedCap; msg->getStringFast(_PREHASH_Info, _PREHASH_SeedCapability, seedCap); // update home location if we are teleporting out of prelude - specific to teleporting to welcome area - if((teleport_flags & TELEPORT_FLAGS_SET_HOME_TO_TARGET) + if ((teleport_flags & TELEPORT_FLAGS_SET_HOME_TO_TARGET) && (!gAgent.isGodlike())) { gAgent.setHomePosRegion(region_handle, pos); @@ -4524,7 +2942,6 @@ void process_teleport_finish(LLMessageSystem* msg, void**) // Viewer trusts the simulator. gMessageSystem->enableCircuit(sim_host, TRUE); -// Aurora Sim if (!gHippoGridManager->getConnectedGrid()->isSecondLife()) { U32 region_size_x = 256; @@ -4533,12 +2950,13 @@ void process_teleport_finish(LLMessageSystem* msg, void**) msg->getU32Fast(_PREHASH_Info, _PREHASH_RegionSizeY, region_size_y); LLWorld::getInstance()->setRegionSize(region_size_x, region_size_y); } -// Aurora Sim LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host); -/* + M7WindlightInterface::getInstance()->receiveReset(); + + /* // send camera update to new region - gAgent.updateCamera(); + gAgentCamera.updateCamera(); // likewise make sure the camera is behind the avatar gAgentCamera.resetView(TRUE); @@ -4556,8 +2974,6 @@ void process_teleport_finish(LLMessageSystem* msg, void**) gCacheName->setUpstream(sim); */ - M7WindlightInterface::getInstance()->receiveReset(); - // Make sure we're standing gAgent.standUp(); @@ -4572,9 +2988,11 @@ void process_teleport_finish(LLMessageSystem* msg, void**) msg->sendReliable(sim_host); send_complete_agent_movement(sim_host); - gAgent.setTeleportState( LLAgent::TELEPORT_MOVING ); + gAgent.setTeleportState(LLAgent::TELEPORT_MOVING); gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["contacting"]); + LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from process_teleport_finish(). Seed cap == " + << seedCap << LL_ENDL; regionp->setSeedCapability(seedCap); // Don't send camera updates to the new region until we're @@ -4589,9 +3007,9 @@ void process_teleport_finish(LLMessageSystem* msg, void**) effectp->setColor(LLColor4U(gAgent.getEffectColor())); LLHUDManager::getInstance()->sendEffects(); -// gTeleportDisplay = TRUE; -// gTeleportDisplayTimer.reset(); -// gViewerWindow->setShowProgress(TRUE); + // gTeleportDisplay = TRUE; + // gTeleportDisplayTimer.reset(); + // gViewerWindow->setShowProgress(TRUE); } // stuff we have to do every time we get an AvatarInitComplete from a sim @@ -4613,7 +3031,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); LLUUID session_id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id); - if((gAgent.getID() != agent_id) || (gAgent.getSessionID() != session_id)) + if ((gAgent.getID() != agent_id) || (gAgent.getSessionID() != session_id)) { LL_WARNS("Messaging") << "Incorrect id in process_agent_movement_complete()" << LL_ENDL; @@ -4657,7 +3075,6 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) << LL_ENDL; LLAppViewer::instance()->forceDisconnect(LLTrans::getString("SentToInvalidRegion")); return; - } LL_INFOS("Messaging") << "Changing home region to " << x << ":" << y << LL_ENDL; @@ -4674,12 +3091,11 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) regionp->reInitPartitions(); gAgent.setRegion(regionp); // Kill objects in the regions we left behind - for (LLWorld::region_list_t::const_iterator r = LLWorld::getInstance()->getRegionList().begin(); - r != LLWorld::getInstance()->getRegionList().end(); ++r) + for (auto r : LLWorld::getInstance()->getRegionList()) { - if (*r != regionp) + if (r != regionp) { - gObjectList.killObjects(*r); + gObjectList.killObjects(r); } } } @@ -4690,7 +3106,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) bool is_teleport = gAgent.getTeleportState() == LLAgent::TELEPORT_MOVING; - if( is_teleport ) + if (is_teleport) { if (gAgent.getTeleportKeepsLookAt()) { @@ -4703,7 +3119,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) gAgentCamera.slamLookAt(look_at); gAgentCamera.updateCamera(); - gAgent.setTeleportState( LLAgent::TELEPORT_START_ARRIVAL ); + gAgent.setTeleportState(LLAgent::TELEPORT_START_ARRIVAL); // set the appearance on teleport since the new sim does not // know what you look like. @@ -4712,7 +3128,6 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) if (isAgentAvatarValid()) { // Chat the "back" SLURL. (DEV-4907) - LLSLURL slurl; gAgent.getTeleportSourceSLURL(slurl); LLChat chat(LLTrans::getString("completed_from") + " " + slurl.getSLURLString()); @@ -4731,9 +3146,9 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) else { // This is initial log-in or a region crossing - gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + gAgent.setTeleportState(LLAgent::TELEPORT_NONE); - if(LLStartUp::getStartupState() < STATE_STARTED) + if (LLStartUp::getStartupState() < STATE_STARTED) { // This is initial log-in, not a region crossing: // Set the camera looking ahead of the AV so send_agent_update() below // will report the correct location to the server. @@ -4756,7 +3171,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) } else if (is_teleport) { - if (!gAgent.getTeleportKeepsLookAt()) + if (!gAgent.getTeleportKeepsLookAt() && look_at.isExactlyZero()) { //look at the beacon LLVector3 global_agent_pos = agent_pos; @@ -4793,7 +3208,8 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) gAgent.setFlying(false/*gAgent.canFly()*/); } - // force simulator to recognize busy state + // force simulator to recognize do not disturb state + gAgent.setDoNotDisturb(gAgent.isDoNotDisturb()); if (isAgentAvatarValid()) @@ -4816,9 +3232,10 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) if (!gLastVersionChannel.empty() && gSavedSettings.getBOOL("SGServerVersionChangedNotification")) { - LLSD payload; - payload["message"] = version_channel; - LLNotificationsUtil::add("ServerVersionChanged", LLSD(), payload); + LLSD args; + args["OLD_VERSION"] = gLastVersionChannel; + args["NEW_VERSION"] = version_channel; + LLNotificationsUtil::add("ServerVersionChanged", args); } gLastVersionChannel = version_channel; @@ -4830,7 +3247,7 @@ void process_crossed_region(LLMessageSystem* msg, void**) msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); LLUUID session_id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id); - if((gAgent.getID() != agent_id) || (gAgent.getSessionID() != session_id)) + if ((gAgent.getID() != agent_id) || (gAgent.getSessionID() != session_id)) { LL_WARNS("Messaging") << "Incorrect id in process_crossed_region()" << LL_ENDL; @@ -4838,6 +3255,8 @@ void process_crossed_region(LLMessageSystem* msg, void**) } LL_INFOS("Messaging") << "process_crossed_region()" << LL_ENDL; gAgentAvatarp->resetRegionCrossingTimer(); + gAgent.setIsCrossingRegion(false); // Attachments getting lost on TP, region crossing hook + U32 sim_ip; msg->getIPAddrFast(_PREHASH_RegionData, _PREHASH_SimIP, sim_ip); @@ -4852,7 +3271,6 @@ void process_crossed_region(LLMessageSystem* msg, void**) send_complete_agent_movement(sim_host); -// Aurora Sim if (!gHippoGridManager->getConnectedGrid()->isSecondLife()) { U32 region_size_x = 256; @@ -4861,13 +3279,14 @@ void process_crossed_region(LLMessageSystem* msg, void**) msg->getU32(_PREHASH_RegionData, _PREHASH_RegionSizeY, region_size_y); LLWorld::getInstance()->setRegionSize(region_size_x, region_size_y); } -// Aurora Sim LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host); + + LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from process_crossed_region(). Seed cap == " + << seedCap << LL_ENDL; regionp->setSeedCapability(seedCap); } - // Sends avatar and camera information to simulator. // Sent roughly once per frame, or 20 times per second, whichever is less often @@ -4875,7 +3294,7 @@ const F32 THRESHOLD_HEAD_ROT_QDOT = 0.9997f; // ~= 2.5 degrees -- if its less th const F32 MAX_HEAD_ROT_QDOT = 0.99999f; // ~= 0.5 degrees -- if its greater than this then no need to update head_rot // between these values we delay the updates (but no more than one second) -static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE_SEND("Send Message"); +static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE_SEND("Send Message"); void send_agent_update(BOOL force_send, BOOL send_reliable) { @@ -4887,13 +3306,13 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) } // We have already requested to log out. Don't send agent updates. - if(LLAppViewer::instance()->logoutRequestSent()) + if (LLAppViewer::instance()->logoutRequestSent()) { return; } // no region to send update to - if(gAgent.getRegion() == NULL) + if (gAgent.getRegion() == nullptr) { return; } @@ -4903,7 +3322,7 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) // NOTA BENE: This is (intentionally?) using the small angle sine approximation to test for rotation // Plus, there is an extra 0.5 in the mix since the perpendicular between last_camera_at and getAtAxis() bisects cam_rot_change // Thus, we're actually testing against 0.2 degrees - const F32 ROTATION_THRESHOLD = 0.1f * 2.f*F_PI/360.f; // Rotation thresh 0.2 deg, see note above + const F32 ROTATION_THRESHOLD = 0.1f * 2.f * F_PI / 360.f; // Rotation thresh 0.2 deg, see note above const U8 DUP_MSGS = 1; // HACK! number of times to repeat data on motionless agent @@ -4923,7 +3342,7 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) static F32 head_rot_chg = 1.0; static U8 last_flags; - LLMessageSystem *msg = gMessageSystem; + LLMessageSystem* msg = gMessageSystem; LLVector3 camera_pos_agent; // local to avatar's region U8 render_state; @@ -4945,21 +3364,22 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) // trigger a control event. U32 control_flags = gAgent.getControlFlags(); - // - if(gSavedSettings.getBOOL("Nimble")) + // + static LLCachedControl alchemyPrejump(gSavedSettings, "Nimble", false); + if (alchemyPrejump) { control_flags |= AGENT_CONTROL_FINISH_ANIM; } - // + // MASK key_mask = gKeyboard->currentMask(TRUE); if (key_mask & MASK_ALT || key_mask & MASK_CONTROL) { - control_flags &= ~( AGENT_CONTROL_LBUTTON_DOWN | - AGENT_CONTROL_ML_LBUTTON_DOWN ); + control_flags &= ~(AGENT_CONTROL_LBUTTON_DOWN | + AGENT_CONTROL_ML_LBUTTON_DOWN); control_flags |= AGENT_CONTROL_LBUTTON_UP | - AGENT_CONTROL_ML_LBUTTON_UP ; + AGENT_CONTROL_ML_LBUTTON_UP; } control_flag_change = last_control_flags ^ control_flags; @@ -5062,7 +3482,7 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) } */ - LLFastTimer t(FTM_AGENT_UPDATE_SEND); + LL_RECORD_BLOCK_TIME(FTM_AGENT_UPDATE_SEND); // Build the message msg->newMessageFast(_PREHASH_AgentUpdate); msg->nextBlockFast(_PREHASH_AgentData); @@ -5073,10 +3493,10 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) msg->addU8Fast(_PREHASH_State, render_state); msg->addU8Fast(_PREHASH_Flags, flags); -// if (camera_pos_agent.mV[VY] > 255.f) -// { -// LL_INFOS("Messaging") << "Sending camera center " << camera_pos_agent << LL_ENDL; -// } + // if (camera_pos_agent.mV[VY] > 255.f) + // { + // LL_INFOS("Messaging") << "Sending camera center " << camera_pos_agent << LL_ENDL; + // } msg->addVector3Fast(_PREHASH_CameraCenter, camera_pos_agent); msg->addVector3Fast(_PREHASH_CameraAtAxis, LLViewerCamera::getInstance()->getAtAxis()); @@ -5110,7 +3530,7 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) gAgent.sendReliableMessage(); } -// LL_DEBUGS("Messaging") << "agent " << avatar_pos_agent << " cam " << camera_pos_agent << LL_ENDL; + // LL_DEBUGS("Messaging") << "agent " << avatar_pos_agent << " cam " << camera_pos_agent << LL_ENDL; // Copy the old data last_head_rot = head_rotation; @@ -5125,53 +3545,167 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) } +// sounds can arrive before objects, store them for a short time +// Note: this is a workaround for MAINT-4743, real fix would be to make +// server send sound along with object update that creates (rezes) the object +class PostponedSoundData +{ +public: + PostponedSoundData() : + mExpirationTime(0) + {} + PostponedSoundData(const LLUUID &object_id, const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, const U8 flags); + bool hasExpired() { return LLFrameTimer::getTotalSeconds() > mExpirationTime; } + + LLUUID mObjectId; + LLUUID mSoundId; + LLUUID mOwnerId; + F32 mGain; + U8 mFlags; + static const F64 MAXIMUM_PLAY_DELAY; + +private: + F64 mExpirationTime; //seconds since epoch +}; +const F64 PostponedSoundData::MAXIMUM_PLAY_DELAY = 15.0; +static F64 postponed_sounds_update_expiration = 0.0; +static std::map postponed_sounds; + +void set_attached_sound(LLViewerObject *objectp, const LLUUID &object_id, const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, const U8 flags) +{ + if (LLMuteList::getInstance()->isMuted(object_id)) return; + + if (LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) return; + + // Don't play sounds from a region with maturity above current agent maturity + LLVector3d pos = objectp->getPositionGlobal(); + if (!gAgent.canAccessMaturityAtGlobal(pos)) + { + return; + } + + objectp->setAttachedSound(sound_id, owner_id, gain, flags); +} + +PostponedSoundData::PostponedSoundData(const LLUUID &object_id, const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, const U8 flags) + : + mObjectId(object_id), + mSoundId(sound_id), + mOwnerId(owner_id), + mGain(gain), + mFlags(flags), + mExpirationTime(LLFrameTimer::getTotalSeconds() + MAXIMUM_PLAY_DELAY) +{ +} + +// static +void update_attached_sounds() +{ + if (postponed_sounds.empty()) + { + return; + } + + std::map::iterator iter = postponed_sounds.begin(); + std::map::iterator end = postponed_sounds.end(); + while (iter != end) + { + std::map::iterator cur_iter = iter++; + PostponedSoundData* data = &cur_iter->second; + if (data->hasExpired()) + { + postponed_sounds.erase(cur_iter); + } + else + { + LLViewerObject *objectp = gObjectList.findObject(data->mObjectId); + if (objectp) + { + set_attached_sound(objectp, data->mObjectId, data->mSoundId, data->mOwnerId, data->mGain, data->mFlags); + postponed_sounds.erase(cur_iter); + } + } + } + postponed_sounds_update_expiration = LLFrameTimer::getTotalSeconds() + 2 * PostponedSoundData::MAXIMUM_PLAY_DELAY; +} + +//static +void clear_expired_postponed_sounds() +{ + if (postponed_sounds_update_expiration > LLFrameTimer::getTotalSeconds()) + { + return; + } + std::map::iterator iter = postponed_sounds.begin(); + std::map::iterator end = postponed_sounds.end(); + while (iter != end) + { + std::map::iterator cur_iter = iter++; + PostponedSoundData* data = &cur_iter->second; + if (data->hasExpired()) + { + postponed_sounds.erase(cur_iter); + } + } + postponed_sounds_update_expiration = LLFrameTimer::getTotalSeconds() + 2 * PostponedSoundData::MAXIMUM_PLAY_DELAY; +} // *TODO: Remove this dependency, or figure out a better way to handle // this hack. -extern U32 gObjectBits; +extern U32Bits gObjectData; -void process_object_update(LLMessageSystem *mesgsys, void **user_data) +void process_object_update(LLMessageSystem* mesgsys, void** user_data) { // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += U32Bytes(mesgsys->getReceiveCompressedSize()); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += U32Bytes(mesgsys->getReceiveSize()); } // Update the object... + S32 old_num_objects = gObjectList.mNumNewObjects; gObjectList.processObjectUpdate(mesgsys, user_data, OUT_FULL); + if (old_num_objects != gObjectList.mNumNewObjects) + { + update_attached_sounds(); + } } -void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data) +void process_compressed_object_update(LLMessageSystem* mesgsys, void** user_data) { // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += U32Bytes(mesgsys->getReceiveCompressedSize()); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += U32Bytes(mesgsys->getReceiveSize()); } // Update the object... + S32 old_num_objects = gObjectList.mNumNewObjects; gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_FULL_COMPRESSED); + if (old_num_objects != gObjectList.mNumNewObjects) + { + update_attached_sounds(); + } } -void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) +void process_cached_object_update(LLMessageSystem* mesgsys, void** user_data) { // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += U32Bytes(mesgsys->getReceiveCompressedSize()); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += U32Bytes(mesgsys->getReceiveSize()); } // Update the object... @@ -5179,46 +3713,52 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) } -void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_data) +void process_terse_object_update_improved(LLMessageSystem* mesgsys, void** user_data) { if (mesgsys->getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += U32Bytes(mesgsys->getReceiveCompressedSize()); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += U32Bytes(mesgsys->getReceiveSize()); } + S32 old_num_objects = gObjectList.mNumNewObjects; gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_TERSE_IMPROVED); + if (old_num_objects != gObjectList.mNumNewObjects) + { + update_attached_sounds(); + } } -static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects"); - +static LLTrace::BlockTimerStatHandle FTM_PROCESS_OBJECTS("Process Kill Objects"); -void process_kill_object(LLMessageSystem *mesgsys, void **user_data) +void process_kill_object(LLMessageSystem* mesgsys, void** user_data) { - LLFastTimer t(FTM_PROCESS_OBJECTS); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_OBJECTS); + + auto agent_region = gAgent.getRegion(); + if (!agent_region) return; LLUUID id; - U32 local_id; - S32 i; - S32 num_objects; - num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); + U32 ip = mesgsys->getSenderIP(); + U32 port = mesgsys->getSenderPort(); + + bool different_region = mesgsys->getSender().getIPandPort() != agent_region->getHost().getIPandPort(); - for (i = 0; i < num_objects; i++) + S32 num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); + for (S32 i = 0; i < num_objects; ++i) { + U32 local_id; mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); - LLViewerObjectList::getUUIDFromLocal(id, - local_id, - gMessageSystem->getSenderIP(), - gMessageSystem->getSenderPort()); + LLViewerObjectList::getUUIDFromLocal(id, local_id, ip, port); if (id == LLUUID::null) { LL_DEBUGS("Messaging") << "Unknown kill for local " << local_id << LL_ENDL; - gObjectList.mNumUnknownKills++; + ++gObjectList.mNumUnknownKills; continue; } else @@ -5226,38 +3766,58 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data) LL_DEBUGS("Messaging") << "Kill message for local " << local_id << LL_ENDL; } - // ...don't kill the avatar - if (!(id == gAgentID)) + if (id == gAgentID) + { + // never kill our avatar + continue; + } + + LLViewerObject* objectp = gObjectList.findObject(id); + if (objectp) { - LLViewerObject *objectp = gObjectList.findObject(id); - if (objectp) + if (gAgentAvatarp == objectp->getAvatar()) { - // Display green bubble on kill - if ( gShowObjectUpdates ) + if (different_region) + { + LL_WARNS() << "Region other than our own killing our attachments!!" << LL_ENDL; + continue; + } + else if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) { - LLColor4 color(0.f,1.f,0.f,1.f); - gPipeline.addDebugBlip(objectp->getPositionAgent(), color); + LL_WARNS() << "Region killing our attachments during teleport!!" << LL_ENDL; + continue; + } + else if (gAgent.isCrossingRegion()) + { + LL_WARNS() << "Region killing our attachments during region cross!!" << LL_ENDL; + continue; } - - // Do the kill - gObjectList.killObject(objectp); } - else + + // Display green bubble on kill + if (gShowObjectUpdates) { - LL_WARNS("Messaging") << "Object in UUID lookup, but not on object list in kill!" << LL_ENDL; - gObjectList.mNumUnknownKills++; + LLColor4 color(0.f, 1.f, 0.f, 1.f); + gPipeline.addDebugBlip(objectp->getPositionAgent(), color); } + + // Do the kill + gObjectList.killObject(objectp); + } + else + { + LL_WARNS("Messaging") << "Object in UUID lookup, but not on object list in kill!" << LL_ENDL; + gObjectList.mNumUnknownKills++; } // We should remove the object from selection after it is marked dead by gObjectList to make LLToolGrab, // which is using the object, release the mouse capture correctly when the object dies. // See LLToolGrab::handleHoverActive() and LLToolGrab::handleHoverNonPhysical(). LLSelectMgr::getInstance()->removeObjectFromSelections(id); - } } -void process_time_synch(LLMessageSystem *mesgsys, void **user_data) +void process_time_synch(LLMessageSystem* mesgsys, void** user_data) { LLVector3 sun_direction; LLVector3 sun_ang_velocity; @@ -5279,7 +3839,7 @@ void process_time_synch(LLMessageSystem *mesgsys, void **user_data) LLWorld::getInstance()->setSpaceTimeUSec(space_time_usec); - LL_DEBUGS("Windlight Sync") << "Sun phase: " << phase << " rad = " << fmodf(phase / F_TWO_PI + 0.25, 1.f) * 24.f << " h" << LL_ENDL; + LL_DEBUGS("WindlightSync") << "Sun phase: " << phase << " rad = " << fmodf(phase / F_TWO_PI + 0.25, 1.f) * 24.f << " h" << LL_ENDL; gSky.setSunPhase(phase); gSky.setSunTargetDirection(sun_direction, sun_ang_velocity); @@ -5289,9 +3849,15 @@ void process_time_synch(LLMessageSystem *mesgsys, void **user_data) } } -void process_sound_trigger(LLMessageSystem *msg, void **) +void process_sound_trigger(LLMessageSystem* msg, void**) { - if (!gAudiop) return; + if (!gAudiop) + { +#if !LL_LINUX + LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; +#endif + return; + } U64 region_handle = 0; F32 gain = 0; @@ -5306,18 +3872,19 @@ void process_sound_trigger(LLMessageSystem *msg, void **) msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_ObjectID, object_id); // NaCl - Antispam Registry - static LLCachedControl _NACL_AntiSpamSoundMulti(gSavedSettings,"_NACL_AntiSpamSoundMulti"); - if(owner_id.isNull()) - { - bool bDoSpamCheck=1; - std::string sSound=sound_id.asString(); - for(int i=0;i< COLLISION_SOUNDS_SIZE;i++) - if(COLLISION_SOUNDS[i] == sSound) - bDoSpamCheck=0; - if(bDoSpamCheck) - if(NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SOUND,object_id, _NACL_AntiSpamSoundMulti)) return; - } - else if(NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SOUND,owner_id, _NACL_AntiSpamSoundMulti)) return; + if (NACLAntiSpamRegistry::instanceExists()) + { + auto& antispam = NACLAntiSpamRegistry::instance(); + static const LLCachedControl _NACL_AntiSpamSoundMulti("_NACL_AntiSpamSoundMulti"); + if (owner_id.isNull()) + { + bool is_collision_sound(const std::string & sound); + if (!is_collision_sound(sound_id.asString()) + && antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, object_id, LFIDBearer::OBJECT, _NACL_AntiSpamSoundMulti)) + return; + } + else if (antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, owner_id, LFIDBearer::AVATAR, _NACL_AntiSpamSoundMulti)) return; + } // NaCl End msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_ParentID, parent_id); @@ -5349,7 +3916,7 @@ void process_sound_trigger(LLMessageSystem *msg, void **) } // Don't play sounds from a region with maturity above current agent maturity - if( !gAgent.canAccessMaturityInRegion( region_handle ) ) + if (!gAgent.canAccessMaturityInRegion(region_handle)) { return; } @@ -5377,10 +3944,13 @@ void process_sound_trigger(LLMessageSystem *msg, void **) // } -void process_preload_sound(LLMessageSystem *msg, void **user_data) +void process_preload_sound(LLMessageSystem* msg, void** user_data) { if (!gAudiop) { +#if !LL_LINUX + LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; +#endif return; } @@ -5393,20 +3963,24 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data) msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_OwnerID, owner_id); // NaCl - Antispam Registry - static LLCachedControl _NACL_AntiSpamSoundPreloadMulti(gSavedSettings,"_NACL_AntiSpamSoundPreloadMulti"); - if((owner_id.isNull() - && NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SOUND_PRELOAD,object_id,_NACL_AntiSpamSoundPreloadMulti)) - || NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SOUND_PRELOAD,owner_id,_NACL_AntiSpamSoundPreloadMulti)) - return; + if (NACLAntiSpamRegistry::instanceExists()) + { + auto& antispam = NACLAntiSpamRegistry::instance(); + static const LLCachedControl _NACL_AntiSpamSoundPreloadMulti("_NACL_AntiSpamSoundPreloadMulti"); + if ((owner_id.isNull() + && antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND_PRELOAD, object_id, LFIDBearer::OBJECT, _NACL_AntiSpamSoundPreloadMulti)) + || antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND_PRELOAD, owner_id, LFIDBearer::AVATAR, _NACL_AntiSpamSoundPreloadMulti)) + return; + } // NaCl End - LLViewerObject *objectp = gObjectList.findObject(object_id); + LLViewerObject* objectp = gObjectList.findObject(object_id); if (!objectp) return; if (LLMuteList::getInstance()->isMuted(object_id)) return; if (LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) return; - LLAudioSource *sourcep = objectp->getAudioSource(owner_id); + LLAudioSource* sourcep = objectp->getAudioSource(owner_id); if (!sourcep) return; // Note that I don't actually do any loading of the @@ -5422,7 +3996,7 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data) } } -void process_attached_sound(LLMessageSystem *msg, void **user_data) +void process_attached_sound(LLMessageSystem* msg, void** user_data) { F32 gain = 0; LLUUID sound_id; @@ -5435,43 +4009,47 @@ void process_attached_sound(LLMessageSystem *msg, void **user_data) msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_OwnerID, owner_id); // NaCl - Antispam Registry - if((owner_id.isNull() - && NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SOUND,object_id)) - || NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SOUND,owner_id)) - return; + if (NACLAntiSpamRegistry::instanceExists()) + { + auto& antispam = NACLAntiSpamRegistry::instance(); + if ((owner_id.isNull() + && antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, object_id, LFIDBearer::OBJECT)) + || antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, owner_id)) + return; + } // NaCl End msg->getF32Fast(_PREHASH_DataBlock, _PREHASH_Gain, gain); msg->getU8Fast(_PREHASH_DataBlock, _PREHASH_Flags, flags); LLViewerObject *objectp = gObjectList.findObject(object_id); - if (!objectp) + if (objectp) { - // we don't know about this object, just bail - return; + set_attached_sound(objectp, object_id, sound_id, owner_id, gain, flags); } - - if (LLMuteList::getInstance()->isMuted(object_id)) return; - - if (LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) return; - - - // Don't play sounds from a region with maturity above current agent maturity - LLVector3d pos = objectp->getPositionGlobal(); - if( !gAgent.canAccessMaturityAtGlobal(pos) ) + else if (sound_id.notNull()) { - return; + // we don't know about this object yet, probably it has yet to arrive + // std::map for dupplicate prevention. + if (!LLMuteList::getInstance()->isMuted(object_id) && !LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) + postponed_sounds[object_id] = (PostponedSoundData(object_id, sound_id, owner_id, gain, flags)); + clear_expired_postponed_sounds(); + } + else + { + std::map::iterator iter = postponed_sounds.find(object_id); + if (iter != postponed_sounds.end()) + { + postponed_sounds.erase(iter); + } } - - objectp->setAttachedSound(sound_id, owner_id, gain, flags); } - void process_attached_sound_gain_change(LLMessageSystem *mesgsys, void **user_data) { F32 gain = 0; LLUUID object_guid; - LLViewerObject *objectp = NULL; + LLViewerObject* objectp = nullptr; mesgsys->getUUIDFast(_PREHASH_DataBlock, _PREHASH_ObjectID, object_guid); @@ -5487,7 +4065,7 @@ void process_attached_sound_gain_change(LLMessageSystem *mesgsys, void **user_da } -void process_health_message(LLMessageSystem *mesgsys, void **user_data) +void process_health_message(LLMessageSystem* mesgsys, void** user_data) { F32 health; @@ -5500,8 +4078,50 @@ void process_health_message(LLMessageSystem *mesgsys, void **user_data) } -void process_sim_stats(LLMessageSystem *msg, void **user_data) -{ +void process_sim_stats(LLMessageSystem* msg, void** user_data) +{ + static LLHost sLastHost; + auto& stats = LLViewerStats::instance(); + if (msg->getSender() != sLastHost) + { + sLastHost = msg->getSender(); + stats.mSimTimeDilation.reset(); + stats.mSimFPS.reset(); + stats.mSimPhysicsFPS.reset(); + stats.mSimAgentUPS.reset(); + stats.mSimFrameMsec.reset(); + stats.mSimNetMsec.reset(); + stats.mSimSimOtherMsec.reset(); + stats.mSimSimPhysicsMsec.reset(); + stats.mSimAgentMsec.reset(); + stats.mSimImagesMsec.reset(); + stats.mSimScriptMsec.reset(); + stats.mSimObjects.reset(); + stats.mSimActiveObjects.reset(); + stats.mSimMainAgents.reset(); + stats.mSimChildAgents.reset(); + stats.mSimActiveScripts.reset(); + stats.mSimScriptEPS.reset(); + stats.mSimInPPS.reset(); + stats.mSimOutPPS.reset(); + stats.mSimPendingDownloads.reset(); + stats.mSimPendingUploads.reset(); + stats.mSimPendingLocalUploads.reset(); + stats.mSimTotalUnackedBytes.reset(); + stats.mPhysicsPinnedTasks.reset(); + stats.mPhysicsLODTasks.reset(); + stats.mSimSimPhysicsStepMsec.reset(); + stats.mSimSimPhysicsShapeUpdateMsec.reset(); + stats.mSimSimPhysicsOtherMsec.reset(); + stats.mPhysicsMemoryAllocated.reset(); + stats.mSimSpareMsec.reset(); + stats.mSimSleepMsec.reset(); + stats.mSimPumpIOMsec.reset(); + stats.mSimPctScriptsRun.reset(); + stats.mSimSimAIStepMsec.reset(); + stats.mSimSimSkippedSilhouetteSteps.reset(); + stats.mSimSimPctSteppedCharacters.reset(); + } S32 count = msg->getNumberOfBlocks("Stat"); for (S32 i = 0; i < count; ++i) { @@ -5512,131 +4132,128 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data) switch (stat_id) { case LL_SIM_STAT_TIME_DILATION: - LLViewerStats::getInstance()->mSimTimeDilation.addValue(stat_value); + stats.mSimTimeDilation.addValue(stat_value); break; case LL_SIM_STAT_FPS: - LLViewerStats::getInstance()->mSimFPS.addValue(stat_value); + stats.mSimFPS.addValue(stat_value); break; case LL_SIM_STAT_PHYSFPS: - LLViewerStats::getInstance()->mSimPhysicsFPS.addValue(stat_value); + stats.mSimPhysicsFPS.addValue(stat_value); break; case LL_SIM_STAT_AGENTUPS: - LLViewerStats::getInstance()->mSimAgentUPS.addValue(stat_value); + stats.mSimAgentUPS.addValue(stat_value); break; case LL_SIM_STAT_FRAMEMS: - LLViewerStats::getInstance()->mSimFrameMsec.addValue(stat_value); + stats.mSimFrameMsec.addValue(stat_value); break; case LL_SIM_STAT_NETMS: - LLViewerStats::getInstance()->mSimNetMsec.addValue(stat_value); + stats.mSimNetMsec.addValue(stat_value); break; case LL_SIM_STAT_SIMOTHERMS: - LLViewerStats::getInstance()->mSimSimOtherMsec.addValue(stat_value); + stats.mSimSimOtherMsec.addValue(stat_value); break; case LL_SIM_STAT_SIMPHYSICSMS: - LLViewerStats::getInstance()->mSimSimPhysicsMsec.addValue(stat_value); + stats.mSimSimPhysicsMsec.addValue(stat_value); break; case LL_SIM_STAT_AGENTMS: - LLViewerStats::getInstance()->mSimAgentMsec.addValue(stat_value); + stats.mSimAgentMsec.addValue(stat_value); break; case LL_SIM_STAT_IMAGESMS: - LLViewerStats::getInstance()->mSimImagesMsec.addValue(stat_value); + stats.mSimImagesMsec.addValue(stat_value); break; case LL_SIM_STAT_SCRIPTMS: - LLViewerStats::getInstance()->mSimScriptMsec.addValue(stat_value); + stats.mSimScriptMsec.addValue(stat_value); break; case LL_SIM_STAT_NUMTASKS: - LLViewerStats::getInstance()->mSimObjects.addValue(stat_value); + stats.mSimObjects.addValue(stat_value); break; case LL_SIM_STAT_NUMTASKSACTIVE: - LLViewerStats::getInstance()->mSimActiveObjects.addValue(stat_value); + stats.mSimActiveObjects.addValue(stat_value); break; case LL_SIM_STAT_NUMAGENTMAIN: - LLViewerStats::getInstance()->mSimMainAgents.addValue(stat_value); + stats.mSimMainAgents.addValue(stat_value); break; case LL_SIM_STAT_NUMAGENTCHILD: - LLViewerStats::getInstance()->mSimChildAgents.addValue(stat_value); + stats.mSimChildAgents.addValue(stat_value); break; case LL_SIM_STAT_NUMSCRIPTSACTIVE: if (gSavedSettings.getBOOL("AscentDisplayTotalScriptJumps")) { - if(abs(stat_value-gSavedSettings.getF32("Ascentnumscripts"))>gSavedSettings.getF32("Ascentnumscriptdiff")) + auto control = gSavedSettings.getControl("Ascentnumscripts"); + const auto& numscripts = control->get().asFloat(); + if(abs(stat_value-numscripts)>gSavedSettings.getF32("Ascentnumscriptdiff")) { - LLChat chat; std::stringstream os; - os << (U32)gSavedSettings.getF32("Ascentnumscripts"); - std::stringstream ns; - ns << (U32)stat_value; - std::stringstream diff; - S32 tdiff = (stat_value-gSavedSettings.getF32("Ascentnumscripts")); - diff << tdiff; - std::string change_type = ""; - if (tdiff > 0) change_type = "+"; - chat.mText = "Total scripts jumped from " + os.str() + " to " + ns.str() + " ("+change_type+diff.str()+")"; - LLFloaterChat::addChat(chat, FALSE,FALSE); + os << (U32)numscripts << " to " << (U32)stat_value << " ("; + const S32 tdiff = stat_value - numscripts; + if (tdiff > 0) os << "+"; + os << tdiff << ')'; + LLChat chat("Total scripts jumped from " + os.str()); + LLFloaterChat::addChat(chat, FALSE, FALSE); } - gSavedSettings.setF32("Ascentnumscripts",stat_value); + control->set(stat_value); } - LLViewerStats::getInstance()->mSimActiveScripts.addValue(stat_value); + stats.mSimActiveScripts.addValue(stat_value); break; case LL_SIM_STAT_SCRIPT_EPS: - LLViewerStats::getInstance()->mSimScriptEPS.addValue(stat_value); + stats.mSimScriptEPS.addValue(stat_value); break; case LL_SIM_STAT_INPPS: - LLViewerStats::getInstance()->mSimInPPS.addValue(stat_value); + stats.mSimInPPS.addValue(stat_value); break; case LL_SIM_STAT_OUTPPS: - LLViewerStats::getInstance()->mSimOutPPS.addValue(stat_value); + stats.mSimOutPPS.addValue(stat_value); break; case LL_SIM_STAT_PENDING_DOWNLOADS: - LLViewerStats::getInstance()->mSimPendingDownloads.addValue(stat_value); + stats.mSimPendingDownloads.addValue(stat_value); break; case LL_SIM_STAT_PENDING_UPLOADS: - LLViewerStats::getInstance()->mSimPendingUploads.addValue(stat_value); + stats.mSimPendingUploads.addValue(stat_value); break; case LL_SIM_STAT_PENDING_LOCAL_UPLOADS: - LLViewerStats::getInstance()->mSimPendingLocalUploads.addValue(stat_value); + stats.mSimPendingLocalUploads.addValue(stat_value); break; case LL_SIM_STAT_TOTAL_UNACKED_BYTES: - LLViewerStats::getInstance()->mSimTotalUnackedBytes.addValue(stat_value / 1024.f); + stats.mSimTotalUnackedBytes.addValue(stat_value / 1024.f); break; case LL_SIM_STAT_PHYSICS_PINNED_TASKS: - LLViewerStats::getInstance()->mPhysicsPinnedTasks.addValue(stat_value); + stats.mPhysicsPinnedTasks.addValue(stat_value); break; case LL_SIM_STAT_PHYSICS_LOD_TASKS: - LLViewerStats::getInstance()->mPhysicsLODTasks.addValue(stat_value); + stats.mPhysicsLODTasks.addValue(stat_value); break; case LL_SIM_STAT_SIMPHYSICSSTEPMS: - LLViewerStats::getInstance()->mSimSimPhysicsStepMsec.addValue(stat_value); + stats.mSimSimPhysicsStepMsec.addValue(stat_value); break; case LL_SIM_STAT_SIMPHYSICSSHAPEMS: - LLViewerStats::getInstance()->mSimSimPhysicsShapeUpdateMsec.addValue(stat_value); + stats.mSimSimPhysicsShapeUpdateMsec.addValue(stat_value); break; case LL_SIM_STAT_SIMPHYSICSOTHERMS: - LLViewerStats::getInstance()->mSimSimPhysicsOtherMsec.addValue(stat_value); + stats.mSimSimPhysicsOtherMsec.addValue(stat_value); break; case LL_SIM_STAT_SIMPHYSICSMEMORY: - LLViewerStats::getInstance()->mPhysicsMemoryAllocated.addValue(stat_value); + stats.mPhysicsMemoryAllocated.addValue(stat_value); break; case LL_SIM_STAT_SIMSPARETIME: - LLViewerStats::getInstance()->mSimSpareMsec.addValue(stat_value); + stats.mSimSpareMsec.addValue(stat_value); break; case LL_SIM_STAT_SIMSLEEPTIME: - LLViewerStats::getInstance()->mSimSleepMsec.addValue(stat_value); + stats.mSimSleepMsec.addValue(stat_value); break; case LL_SIM_STAT_IOPUMPTIME: - LLViewerStats::getInstance()->mSimPumpIOMsec.addValue(stat_value); + stats.mSimPumpIOMsec.addValue(stat_value); break; case LL_SIM_STAT_PCTSCRIPTSRUN: - LLViewerStats::getInstance()->mSimPctScriptsRun.addValue(stat_value); + stats.mSimPctScriptsRun.addValue(stat_value); break; case LL_SIM_STAT_SIMAISTEPTIMEMS: - LLViewerStats::getInstance()->mSimSimAIStepMsec.addValue(stat_value); + stats.mSimSimAIStepMsec.addValue(stat_value); break; case LL_SIM_STAT_SKIPPEDAISILSTEPS_PS: - LLViewerStats::getInstance()->mSimSimSkippedSilhouetteSteps.addValue(stat_value); + stats.mSimSimSkippedSilhouetteSteps.addValue(stat_value); break; case LL_SIM_STAT_PCTSTEPPEDCHARACTERS: - LLViewerStats::getInstance()->mSimSimPctSteppedCharacters.addValue(stat_value); + stats.mSimSimPctSteppedCharacters.addValue(stat_value); break; default: // Used to be a commented out warning. @@ -5645,28 +4262,6 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data) } } - /* - msg->getF32Fast(_PREHASH_Statistics, _PREHASH_PhysicsTimeDilation, time_dilation); - LLViewerStats::getInstance()->mSimTDStat.addValue(time_dilation); - - // Process information - // { CpuUsage F32 } - // { SimMemTotal F32 } - // { SimMemRSS F32 } - // { ProcessUptime F32 } - F32 cpu_usage; - F32 sim_mem_total; - F32 sim_mem_rss; - F32 process_uptime; - msg->getF32Fast(_PREHASH_Statistics, _PREHASH_CpuUsage, cpu_usage); - msg->getF32Fast(_PREHASH_Statistics, _PREHASH_SimMemTotal, sim_mem_total); - msg->getF32Fast(_PREHASH_Statistics, _PREHASH_SimMemRSS, sim_mem_rss); - msg->getF32Fast(_PREHASH_Statistics, _PREHASH_ProcessUptime, process_uptime); - LLViewerStats::getInstance()->mSimCPUUsageStat.addValue(cpu_usage); - LLViewerStats::getInstance()->mSimMemTotalStat.addValue(sim_mem_total); - LLViewerStats::getInstance()->mSimMemRSSStat.addValue(sim_mem_rss); - */ - // // Various hacks that aren't statistics, but are being handled here. // @@ -5701,16 +4296,14 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data) } - -void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data) +void process_avatar_animation(LLMessageSystem* mesgsys, void** user_data) { LLUUID animation_id; LLUUID uuid; S32 anim_sequence_id; - + mesgsys->getUUIDFast(_PREHASH_Sender, _PREHASH_ID, uuid); - //clear animation flags LLVOAvatar* avatarp = gObjectList.findAvatar(uuid); if (!avatarp) @@ -5723,19 +4316,20 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data) S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationList); S32 num_source_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationSourceList); + LL_DEBUGS("Messaging", "Motion") << "Processing " << num_blocks << " Animations" << LL_ENDL; + + //clear animation flags avatarp->mSignaledAnimations.clear(); if (avatarp->isSelf()) { LLUUID object_id; - for( S32 i = 0; i < num_blocks; i++ ) + for (S32 i = 0; i < num_blocks; i++) { mesgsys->getUUIDFast(_PREHASH_AnimationList, _PREHASH_AnimID, animation_id, i); mesgsys->getS32Fast(_PREHASH_AnimationList, _PREHASH_AnimSequenceID, anim_sequence_id, i); - LL_DEBUGS("Messaging") << "Anim sequence ID: " << anim_sequence_id << LL_ENDL; - avatarp->mSignaledAnimations[animation_id] = anim_sequence_id; // *HACK: Disabling flying mode if it has been enabled shortly before the agent @@ -5760,7 +4354,7 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data) BOOL anim_found = FALSE; LLVOAvatar::AnimSourceIterator anim_it = avatarp->mAnimationSources.find(object_id); - for (;anim_it != avatarp->mAnimationSources.end(); ++anim_it) + for (; anim_it != avatarp->mAnimationSources.end(); ++anim_it) { if (anim_it->second == animation_id) { @@ -5774,12 +4368,20 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data) avatarp->mAnimationSources.insert(LLVOAvatar::AnimationSourceMap::value_type(object_id, animation_id)); } } + LL_DEBUGS("Messaging", "Motion") << "Anim sequence ID: " << anim_sequence_id + << " Animation id: " << animation_id + << " From block: " << object_id << LL_ENDL; + } + else + { + LL_DEBUGS("Messaging", "Motion") << "Anim sequence ID: " << anim_sequence_id + << " Animation id: " << animation_id << LL_ENDL; } } } else { - for( S32 i = 0; i < num_blocks; i++ ) + for (S32 i = 0; i < num_blocks; i++) { mesgsys->getUUIDFast(_PREHASH_AnimationList, _PREHASH_AnimID, animation_id, i); mesgsys->getS32Fast(_PREHASH_AnimationList, _PREHASH_AnimSequenceID, anim_sequence_id, i); @@ -5793,7 +4395,73 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data) } } -void process_avatar_appearance(LLMessageSystem *mesgsys, void **user_data) + +void process_object_animation(LLMessageSystem *mesgsys, void **user_data) +{ + LLUUID animation_id; + LLUUID uuid; + S32 anim_sequence_id; + + mesgsys->getUUIDFast(_PREHASH_Sender, _PREHASH_ID, uuid); + + LL_DEBUGS("AnimatedObjectsNotify") << "Received animation state for object " << uuid << LL_ENDL; + + signaled_animation_map_t signaled_anims; + S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationList); + LL_DEBUGS("AnimatedObjectsNotify") << "processing object animation requests, num_blocks " << num_blocks << " uuid " << uuid << LL_ENDL; + for( S32 i = 0; i < num_blocks; i++ ) + { + mesgsys->getUUIDFast(_PREHASH_AnimationList, _PREHASH_AnimID, animation_id, i); + mesgsys->getS32Fast(_PREHASH_AnimationList, _PREHASH_AnimSequenceID, anim_sequence_id, i); + signaled_anims[animation_id] = anim_sequence_id; + LL_DEBUGS("AnimatedObjectsNotify") << "added signaled_anims animation request for object " + << uuid << " animation id " << animation_id << LL_ENDL; + } + LLObjectSignaledAnimationMap::instance().getMap()[uuid] = signaled_anims; + + LLViewerObject *objp = gObjectList.findObject(uuid); + if (!objp) + { + LL_DEBUGS("AnimatedObjectsNotify") << "Received animation state for unknown object " << uuid << LL_ENDL; + return; + } + + LLVOVolume *volp = objp->asVolume(); + if (!volp) + { + LL_DEBUGS("AnimatedObjectsNotify") << "Received animation state for non-volume object " << uuid << LL_ENDL; + return; + } + + if (!volp->isAnimatedObject()) + { + LL_DEBUGS("AnimatedObjectsNotify") << "Received animation state for non-animated object " << uuid << LL_ENDL; + return; + } + + volp->updateControlAvatar(); + LLControlAvatar *avatarp = volp->getControlAvatar(); + if (!avatarp) + { + LL_DEBUGS("AnimatedObjectsNotify") << "Received animation request for object with no control avatar, ignoring " << uuid << LL_ENDL; + return; + } + + if (!avatarp->mPlaying) + { + avatarp->mPlaying = true; + //if (!avatarp->mRootVolp->isAnySelected()) + { + avatarp->updateVolumeGeom(); + avatarp->mRootVolp->recursiveMarkForUpdate(TRUE); + } + } + + avatarp->updateAnimations(); +} + + +void process_avatar_appearance(LLMessageSystem* mesgsys, void** user_data) { LLUUID uuid; mesgsys->getUUIDFast(_PREHASH_Sender, _PREHASH_ID, uuid); @@ -5801,7 +4469,7 @@ void process_avatar_appearance(LLMessageSystem *mesgsys, void **user_data) LLVOAvatar* avatarp = gObjectList.findAvatar(uuid); if (avatarp) { - avatarp->processAvatarAppearance( mesgsys ); + avatarp->processAvatarAppearance(mesgsys); } else { @@ -5809,15 +4477,19 @@ void process_avatar_appearance(LLMessageSystem *mesgsys, void **user_data) } } -void process_camera_constraint(LLMessageSystem *mesgsys, void **user_data) +void process_camera_constraint(LLMessageSystem* mesgsys, void** user_data) { + static LLCachedControl disableSimConst(gSavedSettings, "AlchemyDisableSimCamConstraint"); + if (disableSimConst) + return; + LLVector4 cameraCollidePlane; mesgsys->getVector4Fast(_PREHASH_CameraCollidePlane, _PREHASH_Plane, cameraCollidePlane); gAgentCamera.setCameraCollidePlane(cameraCollidePlane); } -void near_sit_object(BOOL success, void *data) +void near_sit_object(BOOL success, void* data) { if (success) { @@ -5830,7 +4502,7 @@ void near_sit_object(BOOL success, void *data) } } -void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) +void process_avatar_sit_response(LLMessageSystem* mesgsys, void** user_data) { LLVector3 sitPosition; LLQuaternion sitRotation; @@ -5869,7 +4541,7 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) } else { - gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(sit_spot), "Sit", &sitRotation, near_sit_object, NULL, 0.5f); + gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(sit_spot), "Sit", &sitRotation, near_sit_object, nullptr, 0.5f); } } else @@ -5878,7 +4550,7 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) } } -void process_clear_follow_cam_properties(LLMessageSystem *mesgsys, void **user_data) +void process_clear_follow_cam_properties(LLMessageSystem* mesgsys, void** user_data) { LLUUID source_id; @@ -5887,7 +4559,7 @@ void process_clear_follow_cam_properties(LLMessageSystem *mesgsys, void **user_d LLFollowCamMgr::removeFollowCamParams(source_id); } -void process_set_follow_cam_properties(LLMessageSystem *mesgsys, void **user_data) +void process_set_follow_cam_properties(LLMessageSystem* mesgsys, void** user_data) { S32 type; F32 value; @@ -5913,7 +4585,7 @@ void process_set_follow_cam_properties(LLMessageSystem *mesgsys, void **user_dat { mesgsys->getS32("CameraProperty", "Type", type, block_index); mesgsys->getF32("CameraProperty", "Value", value, block_index); - switch(type) + switch (type) { case FOLLOWCAM_PITCH: LLFollowCamMgr::setPitch(source_id, value); @@ -5957,27 +4629,27 @@ void process_set_follow_cam_properties(LLMessageSystem *mesgsys, void **user_dat break; case FOLLOWCAM_POSITION_X: settingPosition = true; - position.mV[ 0 ] = value; + position.mV[0] = value; break; case FOLLOWCAM_POSITION_Y: settingPosition = true; - position.mV[ 1 ] = value; + position.mV[1] = value; break; case FOLLOWCAM_POSITION_Z: settingPosition = true; - position.mV[ 2 ] = value; + position.mV[2] = value; break; case FOLLOWCAM_FOCUS_X: settingFocus = true; - focus.mV[ 0 ] = value; + focus.mV[0] = value; break; case FOLLOWCAM_FOCUS_Y: settingFocus = true; - focus.mV[ 1 ] = value; + focus.mV[1] = value; break; case FOLLOWCAM_FOCUS_Z: settingFocus = true; - focus.mV[ 2 ] = value; + focus.mV[2] = value; break; case FOLLOWCAM_POSITION_LOCKED: LLFollowCamMgr::setPositionLocked(source_id, value != 0.f); @@ -5991,24 +4663,25 @@ void process_set_follow_cam_properties(LLMessageSystem *mesgsys, void **user_dat } } - if ( settingPosition ) + if (settingPosition) { LLFollowCamMgr::setPosition(source_id, position); } - if ( settingFocus ) + if (settingFocus) { LLFollowCamMgr::setFocus(source_id, focus); } - if ( settingFocusOffset ) + if (settingFocusOffset) { LLFollowCamMgr::setFocusOffset(source_id, focus_offset); } } + //end Ventrella // Culled from newsim lltask.cpp -void process_name_value(LLMessageSystem *mesgsys, void **user_data) +void process_name_value(LLMessageSystem* mesgsys, void** user_data) { std::string temp_str; LLUUID id; @@ -6034,7 +4707,7 @@ void process_name_value(LLMessageSystem *mesgsys, void **user_data) } } -void process_remove_name_value(LLMessageSystem *mesgsys, void **user_data) +void process_remove_name_value(LLMessageSystem* mesgsys, void** user_data) { std::string temp_str; LLUUID id; @@ -6060,7 +4733,7 @@ void process_remove_name_value(LLMessageSystem *mesgsys, void **user_data) } } -void process_kick_user(LLMessageSystem *msg, void** /*user_data*/) +void process_kick_user(LLMessageSystem* msg, void** /*user_data*/) { std::string message; @@ -6123,7 +4796,7 @@ void process_time_dilation(LLMessageSystem *msg, void **user_data) */ -void process_money_balance_reply( LLMessageSystem* msg, void** ) +void process_money_balance_reply(LLMessageSystem* msg, void**) { S32 balance = 0; S32 credit = 0; @@ -6180,7 +4853,7 @@ void process_money_balance_reply( LLMessageSystem* msg, void** ) // off the beginning. const U32 MAX_LOOKBACK = 30; const S32 POP_FRONT_SIZE = 12; - if(recent.size() > MAX_LOOKBACK) + if (recent.size() > MAX_LOOKBACK) { LL_DEBUGS("Messaging") << "Removing oldest transaction records" << LL_ENDL; recent.erase(recent.begin(), recent.begin() + POP_FRONT_SIZE); @@ -6242,9 +4915,12 @@ static std::string reason_from_transaction_type(S32 transaction_type, case TRANS_CLASSIFIED_CHARGE: return LLTrans::getString("to publish a classified ad"); + case TRANS_GIFT: + // Simulator returns "Payment" if no custom description has been entered + return (item_desc == "Payment" ? std::string() : item_desc); + // These have no reason to display, but are expected and should not // generate warnings - case TRANS_GIFT: case TRANS_PAY_OBJECT: case TRANS_OBJECT_PAYS: return std::string(); @@ -6256,39 +4932,6 @@ static std::string reason_from_transaction_type(S32 transaction_type, } } -static void money_balance_group_notify(const LLUUID& group_id, - const std::string& name, - bool is_group, - std::string message, - LLStringUtil::format_map_t args, - LLSD payload) -{ - bool no_transaction_clutter = gSavedSettings.getBOOL("LiruNoTransactionClutter"); - std::string notification = no_transaction_clutter ? "Payment" : "SystemMessage"; - args["NAME"] = name; - LLSD msg_args; - msg_args["MESSAGE"] = LLTrans::getString(message,args); - LLNotificationsUtil::add(notification,msg_args,payload); - - if (!no_transaction_clutter) LLFloaterChat::addChat(msg_args["MESSAGE"].asString()); // Alerts won't automatically log to chat. -} - -static void money_balance_avatar_notify(const LLUUID& agent_id, - const LLAvatarName& av_name, - std::string message, - LLStringUtil::format_map_t args, - LLSD payload) -{ - bool no_transaction_clutter = gSavedSettings.getBOOL("LiruNoTransactionClutter"); - std::string notification = no_transaction_clutter ? "Payment" : "SystemMessage"; - args["NAME"] = av_name.getNSName(); - LLSD msg_args; - msg_args["MESSAGE"] = LLTrans::getString(message,args); - LLNotificationsUtil::add(notification,msg_args,payload); - - if (!no_transaction_clutter) LLFloaterChat::addChat(msg_args["MESSAGE"].asString()); // Alerts won't automatically log to chat. -} - static void process_money_balance_reply_extended(LLMessageSystem* msg) { // Added in server 1.40 and viewer 2.1, support for localization @@ -6338,6 +4981,7 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) LLSD payload; bool you_paid_someone = (source_id == gAgentID); + std::string gift_suffix = (transaction_type == TRANS_GIFT ? "_gift" : ""); if (you_paid_someone) { is_name_group = is_dest_group; @@ -6346,8 +4990,8 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) { if (dest_id.notNull()) { - message = success ? "you_paid_ldollars" : - "you_paid_failure_ldollars"; + message = success ? "you_paid_ldollars" + gift_suffix : + "you_paid_failure_ldollars" + gift_suffix; } else { @@ -6378,7 +5022,7 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) name_id = source_id; if (!reason.empty()) { - message = "paid_you_ldollars"; + message = "paid_you_ldollars" + gift_suffix; } else { @@ -6387,25 +5031,23 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) // make notification loggable payload["from_id"] = source_id; + + void script_msg_api(const std::string& msg); if (!is_source_group) script_msg_api(source_id.asString() + ", 7"); } // Despite using SLURLs, wait until the name is available before // showing the notification, otherwise the UI layout is strange and // the user sees a "Loading..." message - if (is_name_group) - { - gCacheName->getGroup(name_id, - boost::bind(&money_balance_group_notify, - _1, _2, _3, message, - args, payload)); - } - else { - LLAvatarNameCache::get(name_id, - boost::bind(&money_balance_avatar_notify, - _1, _2, message, - args, payload)); - } + // Singu Note: Wat? SLURLs resolve over time, not the end of the world. + bool no_transaction_clutter = gSavedSettings.getBOOL("LiruNoTransactionClutter"); + std::string notification = no_transaction_clutter ? "Payment" : "SystemMessage"; + args["NAME"] = is_name_group ? LLGroupActions::getSLURL(name_id) : LLAvatarActions::getSLURL(name_id); + LLSD msg_args; + msg_args["MESSAGE"] = LLTrans::getString(message,args); + LLNotificationsUtil::add(notification,msg_args,payload); + + if (!no_transaction_clutter) LLFloaterChat::addChat(msg_args["MESSAGE"].asString()); // Alerts won't automatically log to chat. } bool handle_prompt_for_maturity_level_change_callback(const LLSD& notification, const LLSD& response) @@ -6445,164 +5087,192 @@ bool handle_prompt_for_maturity_level_change_and_reteleport_callback(const LLSD& // some of the server notifications need special handling. This is where we do that. bool handle_special_notification(std::string notificationID, LLSD& llsdBlock) { - U8 regionAccess = static_cast(llsdBlock["_region_access"].asInteger()); - std::string regionMaturity = LLViewerRegion::accessToString(regionAccess); - LLStringUtil::toLower(regionMaturity); - llsdBlock["REGIONMATURITY"] = regionMaturity; bool returnValue = false; - LLNotificationPtr maturityLevelNotification; - std::string notifySuffix = "_Notify"; - if (regionAccess == SIM_ACCESS_MATURE) - { - if (gAgent.isTeen()) + if (llsdBlock.has("_region_access")) + { + U8 regionAccess = static_cast(llsdBlock["_region_access"].asInteger()); + std::string regionMaturity = LLViewerRegion::accessToString(regionAccess); + LLStringUtil::toLower(regionMaturity); + llsdBlock["REGIONMATURITY"] = regionMaturity; + LLNotificationPtr maturityLevelNotification; + std::string notifySuffix = "_Notify"; + if (regionAccess == SIM_ACCESS_MATURE) { - gAgent.clearTeleportRequest(); - maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); - returnValue = true; + if (gAgent.isTeen()) + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID + "_AdultsOnlyContent", llsdBlock); + returnValue = true; - notifySuffix = "_NotifyAdultsOnly"; + notifySuffix = "_NotifyAdultsOnly"; + } + else if (gAgent.prefersPG()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID + "_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID + "_PreferencesOutOfSync", llsdBlock, llsdBlock); + returnValue = true; + } } - else if (gAgent.prefersPG()) + else if (regionAccess == SIM_ACCESS_ADULT) { - maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); - returnValue = true; + if (!gAgent.isAdult()) + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID + "_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; + } + else if (gAgent.prefersPG() || gAgent.prefersMature()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID + "_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID + "_PreferencesOutOfSync", llsdBlock, llsdBlock); + returnValue = true; + } } - else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0) + + if ((maturityLevelNotification == nullptr) || maturityLevelNotification->isIgnored()) { - maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock); - returnValue = true; + // Given a simple notification if no maturityLevelNotification is set or it is ignore + LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock); } } - else if (regionAccess == SIM_ACCESS_ADULT) - { - if (!gAgent.isAdult()) - { - gAgent.clearTeleportRequest(); - maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); - returnValue = true; - notifySuffix = "_NotifyAdultsOnly"; - } - else if (gAgent.prefersPG() || gAgent.prefersMature()) + return returnValue; +} + +bool handle_trusted_experiences_notification(const LLSD& llsdBlock) +{ + if (llsdBlock.has("trusted_experiences")) + { + std::ostringstream str; + const LLSD& experiences = llsdBlock["trusted_experiences"]; + LLSD::array_const_iterator it = experiences.beginArray(); + for (/**/; it != experiences.endArray(); ++it) { - maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); - returnValue = true; + str << LLSLURL("experience", it->asUUID(), "profile").getSLURLString() << "\n"; } - else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0) + std::string str_list = str.str(); + if (!str_list.empty()) { - maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock); - returnValue = true; + LLNotificationsUtil::add("TrustedExperiencesAvailable", LLSD::emptyMap().with("EXPERIENCE_LIST", (LLSD)str_list)); + return true; } } - - if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored()) - { - // Given a simple notification if no maturityLevelNotification is set or it is ignore - LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock); - } - - return returnValue; + return false; } // some of the server notifications need special handling. This is where we do that. -bool handle_teleport_access_blocked(LLSD& llsdBlock, const std::string & notificationID, const std::string & defaultMessage) +bool handle_teleport_access_blocked(LLSD& llsdBlock, const std::string& notificationID, const std::string& defaultMessage) { - U8 regionAccess = static_cast(llsdBlock["_region_access"].asInteger()); - std::string regionMaturity = LLViewerRegion::accessToString(regionAccess); - LLStringUtil::toLower(regionMaturity); - llsdBlock["REGIONMATURITY"] = regionMaturity; - bool returnValue = false; - LLNotificationPtr tp_failure_notification; - std::string notifySuffix; - - if (notificationID == std::string("TeleportEntryAccessBlocked")) + if (llsdBlock.has("_region_access")) { - notifySuffix = "_Notify"; - if (regionAccess == SIM_ACCESS_MATURE) - { - if (gAgent.isTeen()) - { - gAgent.clearTeleportRequest(); - tp_failure_notification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); - returnValue = true; + U8 regionAccess = static_cast(llsdBlock["_region_access"].asInteger()); + std::string regionMaturity = LLViewerRegion::accessToString(regionAccess); + LLStringUtil::toLower(regionMaturity); + llsdBlock["REGIONMATURITY"] = regionMaturity; - notifySuffix = "_NotifyAdultsOnly"; - } - else if (gAgent.prefersPG()) + LLNotificationPtr tp_failure_notification; + std::string notifySuffix; + + if (notificationID == std::string("TeleportEntryAccessBlocked")) + { + notifySuffix = "_Notify"; + if (regionAccess == SIM_ACCESS_MATURE) { - if (gAgent.hasRestartableFailedTeleportRequest()) + if (gAgent.isTeen()) { - tp_failure_notification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback); + gAgent.clearTeleportRequest(); + tp_failure_notification = LLNotificationsUtil::add(notificationID + "_AdultsOnlyContent", llsdBlock); returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; + } + else if (gAgent.prefersPG()) + { + if (gAgent.hasRestartableFailedTeleportRequest()) + { + tp_failure_notification = LLNotificationsUtil::add(notificationID + "_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback); + returnValue = true; + } + else + { + gAgent.clearTeleportRequest(); + tp_failure_notification = LLNotificationsUtil::add(notificationID + "_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } } else { gAgent.clearTeleportRequest(); - tp_failure_notification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + tp_failure_notification = LLNotificationsUtil::add(notificationID + "_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); returnValue = true; } } - else - { - gAgent.clearTeleportRequest(); - tp_failure_notification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); - returnValue = true; - } - } - else if (regionAccess == SIM_ACCESS_ADULT) - { - if (!gAgent.isAdult()) + else if (regionAccess == SIM_ACCESS_ADULT) { - gAgent.clearTeleportRequest(); - tp_failure_notification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); - returnValue = true; + if (!gAgent.isAdult()) + { + gAgent.clearTeleportRequest(); + tp_failure_notification = LLNotificationsUtil::add(notificationID + "_AdultsOnlyContent", llsdBlock); + returnValue = true; - notifySuffix = "_NotifyAdultsOnly"; - } - else if (gAgent.prefersPG() || gAgent.prefersMature()) - { - if (gAgent.hasRestartableFailedTeleportRequest()) + notifySuffix = "_NotifyAdultsOnly"; + } + else if (gAgent.prefersPG() || gAgent.prefersMature()) { - tp_failure_notification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback); - returnValue = true; + if (gAgent.hasRestartableFailedTeleportRequest()) + { + tp_failure_notification = LLNotificationsUtil::add(notificationID + "_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback); + returnValue = true; + } + else + { + gAgent.clearTeleportRequest(); + tp_failure_notification = LLNotificationsUtil::add(notificationID + "_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } } else { gAgent.clearTeleportRequest(); - tp_failure_notification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + tp_failure_notification = LLNotificationsUtil::add(notificationID + "_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); returnValue = true; } } + } // End of special handling for "TeleportEntryAccessBlocked" + else + { // Normal case, no message munging + gAgent.clearTeleportRequest(); + if (LLNotificationTemplates::getInstance()->templateExists(notificationID)) + { + tp_failure_notification = LLNotificationsUtil::add(notificationID, llsdBlock, llsdBlock); + } else { - gAgent.clearTeleportRequest(); - tp_failure_notification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); - returnValue = true; + llsdBlock["MESSAGE"] = defaultMessage; + tp_failure_notification = LLNotificationsUtil::add("GenericAlertOK", llsdBlock); } + returnValue = true; } - } // End of special handling for "TeleportEntryAccessBlocked" - else - { // Normal case, no message munging - gAgent.clearTeleportRequest(); - if (LLNotificationTemplates::getInstance()->templateExists(notificationID)) - { - tp_failure_notification = LLNotificationsUtil::add(notificationID, llsdBlock, llsdBlock); - } - else + + if ((tp_failure_notification == nullptr) || tp_failure_notification->isIgnored()) { - llsdBlock["MESSAGE"] = defaultMessage; - tp_failure_notification = LLNotificationsUtil::add("GenericAlertOK", llsdBlock); + // Given a simple notification if no tp_failure_notification is set or it is ignore + LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock); } - returnValue = true; - } - - if ((tp_failure_notification == NULL) || tp_failure_notification->isIgnored()) - { - // Given a simple notification if no tp_failure_notification is set or it is ignore - LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock); } + handle_trusted_experiences_notification(llsdBlock); return returnValue; } @@ -6617,23 +5287,14 @@ void home_position_set() void update_region_restart(const LLSD& llsdBlock) { - U32 seconds; - if (llsdBlock.has("MINUTES")) - { - seconds = 60U * static_cast(llsdBlock["MINUTES"].asInteger()); - } - else - { - seconds = static_cast(llsdBlock["SECONDS"].asInteger()); - } - - LLFloaterRegionRestarting* restarting_floater = LLFloaterRegionRestarting::findInstance(); - - if (restarting_floater) + const U32 seconds = llsdBlock.has("MINUTES") + ? (60U * static_cast(llsdBlock["MINUTES"].asInteger())) + : static_cast(llsdBlock["SECONDS"].asInteger()); + if (LLFloaterRegionRestarting* restarting_floater = LLFloaterRegionRestarting::findInstance()) { restarting_floater->updateTime(seconds); - if (!restarting_floater->isMinimized()) - restarting_floater->center(); + /*if (!restarting_floater->isMinimized()) + restarting_floater->center();*/ } else { @@ -6661,7 +5322,6 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) std::string llsdRaw; LLSD llsdBlock; - msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, notificationID); msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_ExtraParams, llsdRaw); if (llsdRaw.length()) { @@ -6671,6 +5331,9 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) LL_WARNS() << "attempt_standard_notification: Attempted to read notification parameter data into LLSD but failed:" << llsdRaw << LL_ENDL; } } + + + handle_trusted_experiences_notification(llsdBlock); if ( (notificationID == "RegionEntryAccessBlocked") || @@ -6708,6 +5371,11 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) return true; } } + else if (notificationID == "expired_region_handoff" || notificationID == "invalid_region_handoff") // borked region handoff + { + gAgent.setIsCrossingRegion(false); // Attachments getting lost on TP + } + else // HACK -- handle callbacks for specific alerts. if (notificationID == "HomePositionSet") { @@ -6717,12 +5385,50 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) { LLViewerStats::getInstance()->incStat(LLViewerStats::ST_KILLED_COUNT); } - else if (notificationID == "RegionRestartMinutes" || notificationID == "RegionRestartSeconds") + else if (notificationID == "RegionRestartMinutes" || + notificationID == "RegionRestartSeconds") { update_region_restart(llsdBlock); LLUI::sAudioCallback(LLUUID(gSavedSettings.getString("UISndRestart"))); return true; // Floater is enough. } + else + // Special Marketplace update notification + if (notificationID == "SLM_UPDATE_FOLDER") + { + std::string state = llsdBlock["state"].asString(); + if (state == "deleted") + { + // Perform the deletion viewer side, no alert shown in this case + LLMarketplaceData::instance().deleteListing(llsdBlock["listing_id"].asInteger()); + return true; + } + // In general, no message will be displayed, all we want is to get the listing updated in the marketplace floater + // If getListing() fails though, the message of the alert will be shown by the caller of attempt_standard_notification() + return LLMarketplaceData::instance().getListing(llsdBlock["listing_id"].asInteger()); + } + + // Error Notification can come with and without reason + if (notificationID == "JoinGroupError") + { + if (llsdBlock.has("reason")) + { + LLNotificationsUtil::add("JoinGroupErrorReason", llsdBlock); + return true; + } + if (llsdBlock.has("group_id")) + { + LLGroupData agent_gdatap; + bool is_member = gAgent.getGroupData(llsdBlock["group_id"].asUUID(), agent_gdatap); + if (is_member) + { + LLSD args; + args["reason"] = LLTrans::getString("AlreadyInGroup"); + LLNotificationsUtil::add("JoinGroupErrorReason", args); + return true; + } + } + } LLNotificationsUtil::add(notificationID, llsdBlock); return true; @@ -6731,19 +5437,37 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) } +static void process_special_alert_messages(const std::string& message) +{ + // Do special handling for alert messages. This is a legacy hack, and any actual displayed + // text should be altered in the notifications.xml files. + if (message == "You died and have been teleported to your home location") + { + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_KILLED_COUNT); + } + else if (message == "Home position set.") + { + home_position_set(); + } +} + + void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data) { // make sure the cursor is back to the usual default since the // alert is probably due to some kind of error. gViewerWindow->getWindow()->resetBusyCount(); + std::string message; + msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, message); + + process_special_alert_messages(message); + if (!attempt_standard_notification(msgsystem)) { BOOL modal = FALSE; msgsystem->getBOOL("AlertData", "Modal", modal); - std::string buffer; - msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer); - process_alert_core(buffer, modal); + process_alert_core(message, modal); } } @@ -6752,25 +5476,27 @@ void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data) // handled by this routine, there is no "Modal" parameter on the message, and // there's no API to tell if a message has the given parameter or not. // So we can't handle the messages with the same handler. -void process_alert_message(LLMessageSystem *msgsystem, void **user_data) +void process_alert_message(LLMessageSystem* msgsystem, void** user_data) { // make sure the cursor is back to the usual default since the // alert is probably due to some kind of error. gViewerWindow->getWindow()->resetBusyCount(); + std::string message; + msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, message); + process_special_alert_messages(message); + if (!attempt_standard_notification(msgsystem)) { BOOL modal = FALSE; - std::string buffer; - msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer); - process_alert_core(buffer, modal); + process_alert_core(message, modal); } } -bool handle_not_age_verified_alert(const std::string &pAlertName) +bool handle_not_age_verified_alert(const std::string& pAlertName) { LLNotificationPtr notification = LLNotificationsUtil::add(pAlertName); - if ((notification == NULL) || notification->isIgnored()) + if ((notification == nullptr) || notification->isIgnored()) { LLNotificationsUtil::add(pAlertName + "_Notify"); } @@ -6778,12 +5504,11 @@ bool handle_not_age_verified_alert(const std::string &pAlertName) return true; } -bool handle_special_alerts(const std::string &pAlertName) +bool handle_special_alerts(const std::string& pAlertName) { bool isHandled = false; if (LLStringUtil::compareStrings(pAlertName, "NotAgeVerified") == 0) { - isHandled = handle_not_age_verified_alert(pAlertName); } @@ -6792,16 +5517,6 @@ bool handle_special_alerts(const std::string &pAlertName) void process_alert_core(const std::string& message, BOOL modal) { - // HACK -- handle callbacks for specific alerts. It also is localized in notifications.xml - if ( message == "You died and have been teleported to your home location") - { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_KILLED_COUNT); - } - else if( message == "Home position set." ) - { - home_position_set(); - } - const std::string ALERT_PREFIX("ALERT: "); const std::string NOTIFY_PREFIX("NOTIFY: "); if (message.find(ALERT_PREFIX) == 0) @@ -6826,6 +5541,7 @@ void process_alert_core(const std::string& message, BOOL modal) // System message is important, show in upper-right box not tip std::string text(message.substr(1)); LLSD args; + if (text.substr(0,17) == "RESTART_X_MINUTES") { S32 mins = 0; @@ -6846,8 +5562,9 @@ void process_alert_core(const std::string& message, BOOL modal) } else { - // *NOTE: If the text from the server ever changes this line will need to be adjusted. - if (text.substr(0, 25) == "Region restart cancelled.") + // *NOTE: If the text from the server ever changes this line will need to be adjusted. + std::string restart_cancelled = "Region restart cancelled."; + if (text.substr(0, restart_cancelled.length()) == restart_cancelled) { LLFloaterRegionRestarting::hideInstance(); } @@ -6913,17 +5630,17 @@ void process_alert_core(const std::string& message, BOOL modal) mean_collision_list_t gMeanCollisionList; time_t gLastDisplayedTime = 0; -void handle_show_mean_events(void *) +void handle_show_mean_events(void*) { if (gNoRender) { return; } - LLFloaterBump::show(NULL); + LLFloaterBump::show(nullptr); } -void mean_name_callback(const LLUUID &id, const std::string& full_name, bool is_group) +void mean_name_callback(const LLUUID& id, const LLAvatarName& av_name) { if (gNoRender) { @@ -6934,18 +5651,16 @@ void mean_name_callback(const LLUUID &id, const std::string& full_name, bool is_ if (gMeanCollisionList.size() > max_collision_list_size) { mean_collision_list_t::iterator iter = gMeanCollisionList.begin(); - for (U32 i=0; imPerp == id) { - mcd->mFullName = full_name; + mcd->mFullName = av_name.getUserName(); } } } @@ -6970,12 +5685,12 @@ void chat_mean_collision(const LLUUID& id, const LLAvatarName& avname, const EMe args["MAG"] = llformat("%f", mag); LLChat chat(LLTrans::getString("BumpedYou", args)); chat.mFromName = name; - chat.mURL = llformat("secondlife:///app/agent/%s/about", id.asString().c_str()); + chat.mURL = LLAvatarActions::getSLURL(id); chat.mSourceType = CHAT_SOURCE_SYSTEM; LLFloaterChat::addChat(chat); } -void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **user_data) +void process_mean_collision_alert_message(LLMessageSystem* msgsystem, void** user_data) { if (gAgent.inPrelude()) { @@ -7009,10 +5724,8 @@ void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **use BOOL b_found = FALSE; - for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin(); - iter != gMeanCollisionList.end(); ++iter) + for (auto mcd : gMeanCollisionList) { - LLMeanCollisionData *mcd = *iter; if ((mcd->mPerp == perp) && (mcd->mType == type)) { mcd->mTime = time; @@ -7024,14 +5737,14 @@ void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **use if (!b_found) { - LLMeanCollisionData *mcd = new LLMeanCollisionData(gAgentID, perp, time, type, mag); + LLMeanCollisionData* mcd = new LLMeanCollisionData(gAgentID, perp, time, type, mag); gMeanCollisionList.push_front(mcd); - gCacheName->get(perp, false, boost::bind(&mean_name_callback, _1, _2, _3)); + LLAvatarNameCache::get(perp, boost::bind(&mean_name_callback, _1, _2)); } } } -void process_frozen_message(LLMessageSystem *msgsystem, void **user_data) +void process_frozen_message(LLMessageSystem* msgsystem, void** user_data) { // make sure the cursor is back to the usual default since the // alert is probably due to some kind of error. @@ -7050,28 +5763,21 @@ void process_frozen_message(LLMessageSystem *msgsystem, void **user_data) } // do some extra stuff once we get our economy data -void process_economy_data(LLMessageSystem *msg, void** /*user_data*/) +void process_economy_data(LLMessageSystem* msg, void** /*user_data*/) { - LLGlobalEconomy::processEconomyData(msg, LLGlobalEconomy::Singleton::getInstance()); - - S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - - LL_INFOS_ONCE("Messaging") << "EconomyData message arrived; upload cost is L$" << upload_cost << LL_ENDL; - - std::string fee = gHippoGridManager->getConnectedGrid()->getUploadFee(); - gMenuHolder->childSetLabelArg("Upload Image", "[UPLOADFEE]", fee); - gMenuHolder->childSetLabelArg("Upload Sound", "[UPLOADFEE]", fee); - gMenuHolder->childSetLabelArg("Upload Animation", "[UPLOADFEE]", fee); - gMenuHolder->childSetLabelArg("Bulk Upload", "[UPLOADFEE]", fee); - gMenuHolder->childSetLabelArg("Buy and Sell L$...", "[CURRENCY]", - gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); + auto& grid = *gHippoGridManager->getConnectedGrid(); + if (grid.isSecondLife() || !LLAgentBenefitsMgr::isCurrent("NonSL")) return; // Quick hack to allow other grids benefits management + LLAgentBenefitsMgr::current().processEconomyData(msg); } void notify_cautioned_script_question(const LLSD& notification, const LLSD& response, S32 orig_questions, BOOL granted) { // NaCl - Antispam Registry - LLUUID task_id = notification["payload"]["task_id"].asUUID(); - if(NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG,task_id)) return; + if (NACLAntiSpamRegistry::instanceExists()) + { + if (NACLAntiSpamRegistry::instance().checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, notification["payload"]["task_id"].asUUID(), LFIDBearer::OBJECT)) + return; + } // NaCl End // only continue if at least some permissions were requested if (orig_questions) @@ -7174,10 +5880,22 @@ void notify_cautioned_script_question(const LLSD& notification, const LLSD& resp } } +void script_question_mute(const LLUUID& item_id, const std::string& object_name); + +void experiencePermissionBlock(LLUUID experience, LLSD result) +{ + LLSD permission; + LLSD data; + permission["permission"] = "Block"; + data[experience.asString()] = permission; + data["experience"] = experience; + LLEventPumps::instance().obtain("experience_permission").post(data); +} + bool script_question_cb(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - LLMessageSystem *msg = gMessageSystem; + LLMessageSystem* msg = gMessageSystem; S32 orig = notification["payload"]["questions"].asInteger(); S32 new_questions = orig; @@ -7191,6 +5909,12 @@ bool script_question_cb(const LLSD& notification, const LLSD& response) return false; } + LLUUID experience; + if (notification["payload"].has("experience")) + { + experience = notification["payload"]["experience"].asUUID(); + } + // check whether permissions were granted or denied BOOL allowed = TRUE; // the "yes/accept" button is the first button in the template, making it button 0 @@ -7199,7 +5923,17 @@ bool script_question_cb(const LLSD& notification, const LLSD& response) { new_questions = 0; allowed = FALSE; - } + } + else if (experience.notNull()) + { + LLSD permission; + LLSD data; + permission["permission"] = "Allow"; + + data[experience.asString()] = permission; + data["experience"] = experience; + LLEventPumps::instance().obtain("experience_permission").post(data); + } LLUUID task_id = notification["payload"]["task_id"].asUUID(); LLUUID item_id = notification["payload"]["item_id"].asUUID(); @@ -7232,38 +5966,74 @@ bool script_question_cb(const LLSD& notification, const LLSD& response) } // [/RLVa:KB] - if ( response["Mute"] ) // mute + if (response["Mute"]) // mute + { + script_question_mute(task_id, notification["payload"]["object_name"].asString()); + } + if (response["BlockExperience"]) + { + if (experience.notNull()) + { + LLViewerRegion* region = gAgent.getRegion(); + if (!region) + return false; + + LLExperienceCache::instance().setExperiencePermission(experience, std::string("Block"), boost::bind(&experiencePermissionBlock, experience, _1)); + } + } + return false; +} + +void script_question_mute(const LLUUID& task_id, const std::string& object_name) +{ + LLMuteList::getInstance()->add(LLMute(task_id, object_name, LLMute::OBJECT)); + + // purge the message queue of any previously queued requests from the same source. DEV-4879 + class OfferMatcher final : public LLNotifyBoxView::Matcher { - LLMuteList::getInstance()->add(LLMute(item_id, notification["payload"]["object_name"].asString(), LLMute::OBJECT)); + public: + OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) + { + } - // purge the message queue of any previously queued requests from the same source. DEV-4879 - class OfferMatcher : public LLNotifyBoxView::Matcher + bool matches(const LLNotificationPtr notification) const override { - public: - OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {} - bool matches(const LLNotificationPtr notification) const + if (notification->getName() == "ScriptQuestionCaution" + || notification->getName() == "ScriptQuestion") { - if (notification->getName() == "ScriptQuestionCaution" - || notification->getName() == "ScriptQuestion") - { - return (notification->getPayload()["item_id"].asUUID() == blocked_id); - } - return false; + return (notification->getPayload()["task_id"].asUUID() == blocked_id); } - private: - const LLUUID& blocked_id; - }; - // should do this via the channel - gNotifyBoxView->purgeMessagesMatching(OfferMatcher(item_id)); - } + return false; + } - return false; + private: + const LLUUID& blocked_id; + }; + + // should do this via the channel + gNotifyBoxView->purgeMessagesMatching(OfferMatcher(task_id)); } static LLNotificationFunctorRegistration script_question_cb_reg_1("ScriptQuestion", script_question_cb); static LLNotificationFunctorRegistration script_question_cb_reg_2("ScriptQuestionCaution", script_question_cb); +static LLNotificationFunctorRegistration script_question_cb_reg_3("ScriptQuestionExperience", script_question_cb); + +void process_script_experience_details(const LLSD& experience_details, LLSD args, LLSD payload) +{ + if (experience_details[LLExperienceCache::PROPERTIES].asInteger() & LLExperienceCache::PROPERTY_GRID) + { + args["GRID_WIDE"] = LLTrans::getString("Grid-Scope"); + } + else + { + args["GRID_WIDE"] = LLTrans::getString("Land-Scope"); + } + args["EXPERIENCE"] = LLSLURL("experience", experience_details[LLExperienceCache::EXPERIENCE_ID].asUUID(), "profile").getSLURLString(); -void process_script_question(LLMessageSystem *msg, void **user_data) + LLNotificationsUtil::add("ScriptQuestionExperience", args, payload); +} + +void process_script_question(LLMessageSystem* msg, void** user_data) { // *TODO: Translate owner name -> [FIRST] [LAST] @@ -7274,22 +6044,32 @@ void process_script_question(LLMessageSystem *msg, void **user_data) S32 questions; std::string object_name; std::string owner_name; + LLUUID experienceid; // taskid -> object key of object requesting permissions - msg->getUUIDFast(_PREHASH_Data, _PREHASH_TaskID, taskid ); + msg->getUUIDFast(_PREHASH_Data, _PREHASH_TaskID, taskid); // itemid -> script asset key of script requesting permissions - msg->getUUIDFast(_PREHASH_Data, _PREHASH_ItemID, itemid ); + msg->getUUIDFast(_PREHASH_Data, _PREHASH_ItemID, itemid); // NaCl - Antispam Registry - if((taskid.isNull() - && NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG,itemid)) - || NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG,taskid)) - return; + if (NACLAntiSpamRegistry::instanceExists()) + { + auto& antispam = NACLAntiSpamRegistry::instance(); + if ((taskid.isNull() + && antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, itemid, LFIDBearer::NONE)) + || antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, taskid, LFIDBearer::OBJECT)) + return; + } // NaCl End msg->getStringFast(_PREHASH_Data, _PREHASH_ObjectName, object_name); msg->getStringFast(_PREHASH_Data, _PREHASH_ObjectOwner, owner_name); - msg->getS32Fast(_PREHASH_Data, _PREHASH_Questions, questions ); + msg->getS32Fast(_PREHASH_Data, _PREHASH_Questions, questions); + + if (msg->has(_PREHASH_Experience)) + { + msg->getUUIDFast(_PREHASH_Experience, _PREHASH_ExperienceID, experienceid); + } // Special case. If the objects are owned by this agent, throttle per-object instead // of per-owner. It's common for residents to reset a ton of scripts that re-request @@ -7297,11 +6077,11 @@ void process_script_question(LLMessageSystem *msg, void **user_data) // so we'll reuse the same namespace for both throttle types. std::string throttle_name = owner_name; std::string self_name; - LLAgentUI::buildFullname( self_name ); + LLAgentUI::buildFullname(self_name); // NaCl - Antispam if (is_spam_filtered(IM_COUNT, false, owner_name == self_name)) return; // NaCl End - if( owner_name == self_name ) + if (owner_name == self_name) { throttle_name = taskid.getString(); } @@ -7311,7 +6091,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data) // throttle excessive requests from any specific user's scripts typedef LLKeyThrottle LLStringThrottle; - static LLStringThrottle question_throttle( LLREQUEST_PERMISSION_THROTTLE_LIMIT, LLREQUEST_PERMISSION_THROTTLE_INTERVAL ); + static LLStringThrottle question_throttle(LLREQUEST_PERMISSION_THROTTLE_LIMIT, LLREQUEST_PERMISSION_THROTTLE_INTERVAL); switch (question_throttle.noteAction(throttle_name)) { @@ -7332,86 +6112,111 @@ void process_script_question(LLMessageSystem *msg, void **user_data) std::string script_question; if (questions) { - BOOL caution = FALSE; + bool caution = false; S32 count = 0; LLSD args; - args["OBJECTNAME"] = object_name; - args["NAME"] = LLCacheName::cleanFullName(owner_name); - - BOOL has_not_only_debit = questions ^ LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_DEBIT]; + const std::string get_obj_slurl(const LLUUID& id, const std::string& name); + const std::string get_obj_owner_slurl(const LLUUID& obj_id, const std::string& name, bool* group_ownedp = nullptr); + args["OBJECTNAME"] = get_obj_slurl(taskid, object_name); + args["NAME"] = get_obj_owner_slurl(taskid, owner_name); + S32 known_questions = 0; + bool has_not_only_debit = questions ^ LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_DEBIT]; // check the received permission flags against each permission for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++) { if (questions & LSCRIPTRunTimePermissionBits[i]) { count++; - + known_questions |= LSCRIPTRunTimePermissionBits[i]; // check whether permission question should cause special caution dialog caution |= (SCRIPT_QUESTION_IS_CAUTION[i]); if (("ScriptTakeMoney" == SCRIPT_QUESTIONS[i]) && has_not_only_debit) continue; + if (SCRIPT_QUESTIONS[i] == "JoinAnExperience") + { // Some experience only permissions do not have an explicit permission bit. Add them here. + script_question += " " + LLTrans::getString("ForceSitAvatar") + "\n"; + } + script_question += " " + LLTrans::getString(SCRIPT_QUESTIONS[i]) + "\n"; } } + args["QUESTIONS"] = script_question; - LLSD payload; - payload["task_id"] = taskid; - payload["item_id"] = itemid; - payload["sender"] = sender.getIPandPort(); - payload["questions"] = questions; - payload["object_name"] = object_name; - payload["owner_name"] = owner_name; + if (known_questions != questions) + { + // This is in addition to the normal dialog. + // Viewer got a request for not supported/implemented permission + LL_WARNS("Messaging") << "Object \"" << object_name << "\" requested " << script_question + << " permission. Permission is unknown and can't be granted. Item id: " << itemid + << " taskid:" << taskid << LL_ENDL; + } -// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7) - if (rlv_handler_t::isEnabled()) + if (known_questions) { - RlvUtil::filterScriptQuestions(questions, payload); + LLSD payload; + payload["task_id"] = taskid; + payload["item_id"] = itemid; + payload["sender"] = sender.getIPandPort(); + payload["questions"] = known_questions; + payload["object_name"] = object_name; + payload["owner_name"] = owner_name; + + // check whether cautions are even enabled or not + const char* notification = "ScriptQuestion"; - if ( (questions) && (gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTPERMISSION)) ) +// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7) + if (rlv_handler_t::isEnabled()) { - const LLViewerObject* pObj = gObjectList.findObject(taskid); - if (pObj) + RlvUtil::filterScriptQuestions(questions, payload); + + if ( (questions) && (gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTPERMISSION)) ) { - if ( (pObj->permYouOwner()) && (!pObj->isAttachment()) ) - { - questions &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS] | - LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH]); - } - else + const LLViewerObject* pObj = gObjectList.findObject(taskid); + if (pObj) { - questions &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS]); + if ( (pObj->permYouOwner()) && (!pObj->isAttachment()) ) + { + questions &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS] | + LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH]); + } + else + { + questions &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS]); + } + payload["rlv_notify"] = !pObj->permYouOwner(); } - payload["rlv_notify"] = !pObj->permYouOwner(); } } - } - if ( (!caution) && (!questions) ) - { - LLNotifications::instance().forceResponse( - LLNotification::Params("ScriptQuestion").substitutions(args).payload(payload), 0/*YES*/); - } - else if (gSavedSettings.getBOOL("PermissionsCautionEnabled")) + if ( (!caution) && (!questions) ) + { + LLNotifications::instance().forceResponse( + LLNotification::Params(notification).substitutions(args).payload(payload), 0/*YES*/); + return; + } // [/RLVa:KB] - // check whether cautions are even enabled or not - //if (gSavedSettings.getBOOL("PermissionsCautionEnabled")) - { - // display the caution permissions prompt - LLNotificationsUtil::add(caution ? "ScriptQuestionCaution" : "ScriptQuestion", args, payload); - } - else - { - // fall back to default behavior if cautions are entirely disabled - LLNotificationsUtil::add("ScriptQuestion", args, payload); + if (caution && gSavedSettings.getBOOL("PermissionsCautionEnabled")) + { + args["FOOTERTEXT"] = (count > 1) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + '\n' + script_question : LLStringUtil::null; + notification = "ScriptQuestionCaution"; + } + else if (experienceid.notNull()) + { + payload["experience"] = experienceid; + LLExperienceCache::instance().get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); + return; + } + + LLNotificationsUtil::add(notification, args, payload); } } } -void process_derez_container(LLMessageSystem *msg, void**) +void process_derez_container(LLMessageSystem* msg, void**) { LL_WARNS("Messaging") << "call to deprecated process_derez_container" << LL_ENDL; } @@ -7422,12 +6227,12 @@ void container_inventory_arrived(LLViewerObject* object, void* data) { LL_DEBUGS("Messaging") << "container_inventory_arrived()" << LL_ENDL; - if( gAgentCamera.cameraMouselook() ) + if (gAgentCamera.cameraMouselook()) { gAgentCamera.changeCameraToDefault(); } - LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(); + LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(); if (inventory->size() > 2) { @@ -7439,7 +6244,7 @@ void container_inventory_arrived(LLViewerObject* object, LLInventoryObject::object_list_t::const_iterator it = inventory->begin(); LLInventoryObject::object_list_t::const_iterator end = inventory->end(); - for ( ; it != end; ++it) + for (; it != end; ++it) { if ((*it)->getType() != LLAssetType::AT_CATEGORY) { @@ -7465,7 +6270,7 @@ void container_inventory_arrived(LLViewerObject* object, } } gInventory.notifyObservers(); - if(active_panel) + if (active_panel) { active_panel->setSelection(cat_id, TAKE_FOCUS_NO); } @@ -7501,7 +6306,7 @@ void container_inventory_arrived(LLViewerObject* object, new_item->updateServer(TRUE); gInventory.updateItem(new_item); gInventory.notifyObservers(); - if(active_panel) + if (active_panel) { active_panel->setSelection(item_id, TAKE_FOCUS_NO); } @@ -7509,7 +6314,7 @@ void container_inventory_arrived(LLViewerObject* object, // we've got the inventory, now delete this object if this was a take BOOL delete_object = (BOOL)(intptr_t)data; - LLViewerRegion *region = gAgent.getRegion(); + LLViewerRegion* region = gAgent.getRegion(); if (delete_object && region) { gMessageSystem->newMessageFast(_PREHASH_ObjectDelete); @@ -7536,7 +6341,7 @@ std::string formatted_time(const time_t& the_time) } -void process_teleport_failed(LLMessageSystem *msg, void**) +void process_teleport_failed(LLMessageSystem* msg, void**) { std::string message_id; // Tag from server, like "RegionEntryAccessBlocked" std::string big_reason; // Actual message to display @@ -7551,20 +6356,17 @@ void process_teleport_failed(LLMessageSystem *msg, void**) // Get the message ID msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, message_id); big_reason = LLAgent::sTeleportErrorMessages[message_id]; - if ( big_reason.size() > 0 ) - { // Substitute verbose reason from the local map - args["REASON"] = big_reason; - } - else - { // Nothing found in the map - use what the server returned in the original message block + if (big_reason.empty()) + { + // Nothing found in the map - use what the server returned in the original message block msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, big_reason); - args["REASON"] = big_reason; } + args["REASON"] = big_reason; LLSD llsd_block; std::string llsd_raw; msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_ExtraParams, llsd_raw); - if (llsd_raw.length()) + if (!llsd_raw.empty()) { std::istringstream llsd_data(llsd_raw); if (!LLSDSerialize::deserialize(llsd_block, llsd_data, llsd_raw.length())) @@ -7573,12 +6375,23 @@ void process_teleport_failed(LLMessageSystem *msg, void**) } else { + if(llsd_block.has("REGION_NAME")) + { + std::string region_name = llsd_block["REGION_NAME"].asString(); + if(!region_name.empty()) + { + LLStringUtil::format_map_t name_args; + name_args["[REGION_NAME]"] = region_name; + LLStringUtil::format(big_reason, name_args); + args["REASON"] = big_reason; + } + } // change notification name in this special case if (handle_teleport_access_blocked(llsd_block, message_id, args["REASON"])) { - if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) + if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) { - gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + gAgent.setTeleportState(LLAgent::TELEPORT_NONE); } return; } @@ -7591,7 +6404,7 @@ void process_teleport_failed(LLMessageSystem *msg, void**) msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, message_id); big_reason = LLAgent::sTeleportErrorMessages[message_id]; - if ( big_reason.size() > 0 ) + if (!big_reason.empty()) { // Substitute verbose reason from the local map args["REASON"] = big_reason; } @@ -7603,13 +6416,13 @@ void process_teleport_failed(LLMessageSystem *msg, void**) LLNotificationsUtil::add("CouldNotTeleportReason", args); - if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) + if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) { - gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + gAgent.setTeleportState(LLAgent::TELEPORT_NONE); } } -void process_teleport_local(LLMessageSystem *msg,void**) +void process_teleport_local(LLMessageSystem* msg, void**) { LLUUID agent_id; msg->getUUIDFast(_PREHASH_Info, _PREHASH_AgentID, agent_id); @@ -7627,9 +6440,9 @@ void process_teleport_local(LLMessageSystem *msg,void**) msg->getVector3Fast(_PREHASH_Info, _PREHASH_LookAt, look_at); msg->getU32Fast(_PREHASH_Info, _PREHASH_TeleportFlags, teleport_flags); - if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) + if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) { - if( gAgent.getTeleportState() == LLAgent::TELEPORT_LOCAL ) + if (gAgent.getTeleportState() == LLAgent::TELEPORT_LOCAL) { // To prevent TeleportStart messages re-activating the progress screen right // after tp, keep the teleport state and let progress screen clear it after a short delay @@ -7639,7 +6452,7 @@ void process_teleport_local(LLMessageSystem *msg,void**) } else { - gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + gAgent.setTeleportState(LLAgent::TELEPORT_NONE); } } @@ -7656,7 +6469,7 @@ void process_teleport_local(LLMessageSystem *msg,void**) gAgent.setPositionAgent(pos); gAgentCamera.slamLookAt(look_at); - if ( !(gAgent.getTeleportKeepsLookAt() && LLViewerJoystick::getInstance()->getOverrideCamera()) && gSavedSettings.getBOOL("OptionRotateCamAfterLocalTP")) + if (!(gAgent.getTeleportKeepsLookAt() && LLViewerJoystick::getInstance()->getOverrideCamera()) && gSavedSettings.getBOOL("OptionRotateCamAfterLocalTP")) { gAgentCamera.resetView(TRUE, TRUE); } @@ -7725,7 +6538,7 @@ void send_group_notice(const LLUUID& group_id, } else { - bucket_to_send = (U8*) EMPTY_BINARY_BUCKET; + bucket_to_send = (U8*)EMPTY_BINARY_BUCKET; } @@ -7753,10 +6566,9 @@ void send_lures(const LLSD& notification, const LLSD& response) if ( (RlvActions::hasBehaviour(RLV_BHVR_SENDIM)) || (RlvActions::hasBehaviour(RLV_BHVR_SENDIMTO)) ) { // Filter the lure message if one of the recipients of the lure can't be sent an IM to - for (LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray(); - it != notification["payload"]["ids"].endArray(); ++it) + for (auto const& entry : notification["payload"]["ids"].array()) { - if (!RlvActions::canSendIM(it->asUUID())) + if (!RlvActions::canSendIM(entry.asUUID())) { text = rlv_hidden; break; @@ -7777,11 +6589,9 @@ void send_lures(const LLSD& notification, const LLSD& response) bool fRlvHideName = gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES); bool fRlvNoNearbyNames = gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS); // [/RLVa:KB] - for(LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray(); - it != notification["payload"]["ids"].endArray(); - ++it) + for (auto const& entry : notification["payload"]["ids"].array()) { - LLUUID target_id = it->asUUID(); + LLUUID target_id = entry.asUUID(); msg->nextBlockFast(_PREHASH_TargetData); msg->addUUIDFast(_PREHASH_TargetID, target_id); @@ -7802,7 +6612,7 @@ void send_lures(const LLSD& notification, const LLSD& response) target_name = RlvStrings::getAnonym(target_name); else // [/RLVa:KB] - LLAvatarNameCache::getNSName(target_id, target_name); + target_name = LLAvatarActions::getSLURL(target_id); args["TO_NAME"] = target_name; LLSD payload; @@ -7827,7 +6637,7 @@ void send_lures(const LLSD& notification, const LLSD& response) bool handle_lure_callback(const LLSD& notification, const LLSD& response) { static const unsigned OFFER_RECIPIENT_LIMIT = 250; - if(notification["payload"]["ids"].size() > OFFER_RECIPIENT_LIMIT) + if (notification["payload"]["ids"].size() > OFFER_RECIPIENT_LIMIT) { // More than OFFER_RECIPIENT_LIMIT targets will overload the message // producing an llerror. @@ -7840,7 +6650,7 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response) S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if(0 == option) + if (0 == option) { send_lures(notification, response); } @@ -7850,9 +6660,7 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response) void handle_lure(const LLUUID& invitee) { - std::vector ids; - ids.push_back(invitee); - handle_lure(ids); + handle_lure(uuid_vec_t{invitee}); } // Prompt for a message to the invited user. @@ -7866,28 +6674,34 @@ void handle_lure(const uuid_vec_t& ids) // [RLVa:KB] - Checked: 2010-04-07 (RLVa-1.2.0d) | Modified: RLVa-1.0.0a edit_args["REGION"] = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? gAgent.getRegion()->getName() : RlvStrings::getString(RLV_STRING_HIDDEN); // [/RLVa:KB] - //edit_args["REGION"] = gAgent.getRegion()->getName(); +// edit_args["REGION"] = gAgent.getRegion()->getName(); LLSD payload; - for (uuid_vec_t::const_iterator it = ids.begin(); - it != ids.end(); - ++it) +// [RLVa:KB] - Checked: RLVa-2.0.1 + bool fRlvShouldHideNames = false; + for (const LLUUID& idAgent : ids) { -// [RLVa:KB] - Checked: 2010-04-07 (RLVa-1.2.0d) | Modified: RLVa-1.0.0a // Only allow offering teleports if everyone is a @tplure exception or able to map this avie under @showloc=n if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) { - const LLRelationship* pBuddyInfo = LLAvatarTracker::instance().getBuddyInfo(*it); - if ( (!gRlvHandler.isException(RLV_BHVR_TPLURE, *it, RLV_CHECK_PERMISSIVE)) && + const LLRelationship* pBuddyInfo = LLAvatarTracker::instance().getBuddyInfo(idAgent); + if ( (!gRlvHandler.isException(RLV_BHVR_TPLURE, idAgent, RLV_CHECK_PERMISSIVE)) && ((!pBuddyInfo) || (!pBuddyInfo->isOnline()) || (!pBuddyInfo->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION))) ) { return; } } - payload["rlv_shownames"] = !RlvActions::canShowName(RlvActions::SNC_TELEPORTOFFER); -// [/RLVa:KB] - payload["ids"].append(*it); + fRlvShouldHideNames |= !RlvActions::canShowName(RlvActions::SNC_TELEPORTOFFER); + payload["ids"].append(idAgent); } + payload["rlv_shownames"] = fRlvShouldHideNames; +// [/RLVa:KB] +// for (std::vector::const_iterator it = ids.begin(); +// it != ids.end(); +// ++it) +// { +// payload["ids"].append(*it); +// } if (gAgent.isGodlike()) { LLNotificationsUtil::add("OfferTeleportFromGod", edit_args, payload, handle_lure_callback); @@ -7901,7 +6715,7 @@ void handle_lure(const uuid_vec_t& ids) bool teleport_request_callback(const LLSD& notification, const LLSD& response) { LLUUID from_id = notification["payload"]["from_id"].asUUID(); - if(from_id.isNull()) + if (from_id.isNull()) { LL_WARNS() << "from_id is NULL" << LL_ENDL; return false; @@ -7910,7 +6724,7 @@ bool teleport_request_callback(const LLSD& notification, const LLSD& response) std::string from_name; gCacheName->getFullName(from_id, from_name); - if(LLMuteList::getInstance()->isMuted(from_id) && !LLMuteList::getInstance()->isLinden(from_name)) + if (LLMuteList::getInstance()->isMuted(from_id) && !LLMuteList::getInstance()->isLinden(from_name)) { return false; } @@ -7925,7 +6739,7 @@ bool teleport_request_callback(const LLSD& notification, const LLSD& response) option = LLNotificationsUtil::getSelectedOption(notification, response); } - switch(option) + switch (option) { // Yes case 0: @@ -7940,14 +6754,6 @@ bool teleport_request_callback(const LLSD& notification, const LLSD& response) } break; - // Profile - case 3: - { - LLAvatarActions::showProfile(from_id); - LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]); //Respawn! - } - break; - // No case 1: default: @@ -8014,12 +6820,12 @@ void send_places_query(const LLUUID& query_id, gAgent.sendReliableMessage(); } - +// Deprecated in favor of cap "UserInfo" void process_user_info_reply(LLMessageSystem* msg, void**) { LLUUID agent_id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); - if(agent_id != gAgent.getID()) + if (agent_id != gAgent.getID()) { LL_WARNS("Messaging") << "process_user_info_reply - " << "wrong agent id." << LL_ENDL; @@ -8030,8 +6836,9 @@ void process_user_info_reply(LLMessageSystem* msg, void**) std::string email; msg->getStringFast(_PREHASH_UserData, _PREHASH_EMail, email); std::string dir_visibility; - msg->getString( "UserData", "DirectoryVisibility", dir_visibility); + msg->getString("UserData", "DirectoryVisibility", dir_visibility); + // For Message based user info information the is_verified is assumed to be false. LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, email); LLFloaterPostcard::updateUserInfo(email); } @@ -8042,23 +6849,43 @@ void process_user_info_reply(LLMessageSystem* msg, void**) //--------------------------------------------------------------------------- const S32 SCRIPT_DIALOG_MAX_BUTTONS = 12; -const S32 SCRIPT_DIALOG_BUTTON_STR_SIZE = 24; -const S32 SCRIPT_DIALOG_MAX_MESSAGE_SIZE = 512; const char* SCRIPT_DIALOG_HEADER = "Script Dialog:\n"; bool callback_script_dialog(const LLSD& notification, const LLSD& response) { LLNotificationForm form(notification["form"]); - std::string button = LLNotification::getSelectedOptionName(response); + std::string rtn_text; S32 button_idx = LLNotification::getSelectedOption(notification, response); - // Didn't click "Ignore" - if (button_idx != -1) + + if (notification["payload"].has("textbox")) { - if (notification["payload"].has("textbox")) + rtn_text = response["message"].asString(); + } + else + { + rtn_text = LLNotification::getSelectedOptionName(response); + } + + // Button -2 = Mute + // Button -1 = Ignore - no processing needed for this button + // Buttons 0 and above = dialog choices + + if (-2 == button_idx) + { + std::string object_name = notification["payload"]["object_name"].asString(); + LLUUID object_id = notification["payload"]["object_id"].asUUID(); + LLMute mute(object_id, object_name, LLMute::OBJECT); + if (LLMuteList::getInstance()->add(mute)) { - button = response["message"].asString(); + // This call opens the sidebar, displays the block list, and highlights the newly blocked + // object in the list so the user can see that their block click has taken effect. + LLFloaterMute::showInstance()->selectMute(object_id); } + } + + if (0 <= button_idx) + { LLMessageSystem* msg = gMessageSystem; msg->newMessage("ScriptDialogReply"); msg->nextBlock("AgentData"); @@ -8068,12 +6895,13 @@ bool callback_script_dialog(const LLSD& notification, const LLSD& response) msg->addUUID("ObjectID", notification["payload"]["object_id"].asUUID()); msg->addS32("ChatChannel", notification["payload"]["chat_channel"].asInteger()); msg->addS32("ButtonIndex", button_idx); - msg->addString("ButtonLabel", button); + msg->addString("ButtonLabel", rtn_text); msg->sendReliable(LLHost(notification["payload"]["sender"].asString())); } return false; } + static LLNotificationFunctorRegistration callback_script_dialog_reg_1("ScriptDialog", callback_script_dialog); static LLNotificationFunctorRegistration callback_script_dialog_reg_2("ScriptDialogGroup", callback_script_dialog); @@ -8086,24 +6914,32 @@ void process_script_dialog(LLMessageSystem* msg, void**) msg->getUUID("Data", "ObjectID", object_id); // NaCl - Antispam Registry - if(NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG,object_id)) + auto antispam = NACLAntiSpamRegistry::getIfExists(); + if (antispam && antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, object_id, LFIDBearer::OBJECT)) return; // NaCl End -// For compability with OS grids first check for presence of extended packet before fetching data. + std::string first_name; + msg->getString("Data", "FirstName", first_name); + bool const is_group = first_name.empty(); + + // For compability with OS grids first check for presence of extended packet before fetching data. LLUUID owner_id; if (gMessageSystem->getNumberOfBlocks("OwnerData") > 0) { msg->getUUID("OwnerData", "OwnerID", owner_id); // NaCl - Antispam Registry - if(NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG,owner_id)) + if (antispam && antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, owner_id, is_group ? LFIDBearer::GROUP : LFIDBearer::AVATAR)) return; // NaCl End } + bool has_owner = owner_id.notNull(); + // NaCl - Antispam - if (owner_id.isNull() ? is_spam_filtered(IM_COUNT, LLAvatarActions::isFriend(object_id), object_id == gAgentID) : is_spam_filtered(IM_COUNT, LLAvatarActions::isFriend(owner_id), owner_id == gAgentID)) return; + if (!has_owner ? is_spam_filtered(IM_COUNT, LLAvatarActions::isFriend(object_id), object_id == gAgentID) + : is_spam_filtered(IM_COUNT, LLAvatarActions::isFriend(owner_id), !is_group && owner_id == gAgentID)) return; // NaCl End if (LLMuteList::getInstance()->isMuted(object_id) || LLMuteList::getInstance()->isMuted(owner_id)) @@ -8111,13 +6947,15 @@ void process_script_dialog(LLMessageSystem* msg, void**) return; } + auto chatter = gObjectList.findObject(object_id); + // Singu Note: Try to get Owner whenever possible + if (chatter && has_owner) chatter->mOwnerID = owner_id; + std::string message; - std::string first_name; std::string last_name; std::string object_name; S32 chat_channel; - msg->getString("Data", "FirstName", first_name); msg->getString("Data", "LastName", last_name); msg->getString("Data", "ObjectName", object_name); msg->getString("Data", "Message", message); @@ -8129,6 +6967,7 @@ void process_script_dialog(LLMessageSystem* msg, void**) payload["sender"] = msg->getSender().getIPandPort(); payload["object_id"] = object_id; + payload["object_name"] = object_name; payload["chat_channel"] = chat_channel; // build up custom form @@ -8139,47 +6978,61 @@ void process_script_dialog(LLMessageSystem* msg, void**) button_count = SCRIPT_DIALOG_MAX_BUTTONS; } - LLNotificationForm form; - std::string firstbutton; - msg->getString("Buttons", "ButtonLabel", firstbutton, 0); - form.addElement("button", std::string(firstbutton)); bool is_text_box = false; - std::string default_text; - if (firstbutton == "!!llTextBox!!") + LLNotificationForm form; + for (i = 0; i < button_count; i++) { - is_text_box = true; - for (i = 1; i < button_count; i++) - { - std::string tdesc; - msg->getString("Buttons", "ButtonLabel", tdesc, i); - default_text += tdesc; - } + std::string tdesc; + msg->getString("Buttons", "ButtonLabel", tdesc, i); + if (is_text_box = tdesc == TEXTBOX_MAGIC_TOKEN) + break; + form.addElement("button", std::string(tdesc)); } - else + + LLSD query_string; + query_string["owner"] = owner_id; + if (rlv_handler_t::isEnabled() && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) || gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMETAGS)) && !is_group && RlvUtil::isNearbyAgent(owner_id)) + { + query_string["rlv_shownames"] = true; + } + + if (const auto& obj = chatter ? chatter : gObjectList.findObject(owner_id)) // Fallback on the owner, if the chatter isn't present { - for (i = 1; i < button_count; i++) + auto& slurl = query_string["slurl"]; + const auto& region = obj->getRegion(); + if (rlv_handler_t::isEnabled() && gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC) && LLWorld::instance().isRegionListed(region)) + slurl = RlvStrings::getString(RLV_STRING_HIDDEN_REGION); + else { - std::string tdesc; - msg->getString("Buttons", "ButtonLabel", tdesc, i); - form.addElement("button", std::string(tdesc)); + const auto& pos = obj->getPositionRegion(); + S32 x = ll_round((F32)fmod((F64)pos.mV[VX], (F64)REGION_WIDTH_METERS)); + S32 y = ll_round((F32)fmod((F64)pos.mV[VY], (F64)REGION_WIDTH_METERS)); + S32 z = ll_round((F32)pos.mV[VZ]); + std::ostringstream location; + location << region->getName() << '/' << x << '/' << y << '/' << z; + if (chatter != obj) location << "?owner_not_object"; + slurl = location.str(); } } + query_string["name"] = object_name; + query_string["groupowned"] = is_group; + object_name = LLSLURL("objectim", object_id, LLURI::mapToQueryString(query_string)).getSLURLString(); LLSD args; args["TITLE"] = object_name; - args["MESSAGE"] = message; + args["MESSAGE"] = LLStringUtil::null; + args["SCRIPT_MESSAGE"] = message; args["CHANNEL"] = chat_channel; LLNotificationPtr notification; - bool const is_group = first_name.empty(); char const* name = (is_group && !is_text_box) ? "GROUPNAME" : "NAME"; - args[name] = is_group ? last_name : LLCacheName::buildFullName(first_name, last_name); + args[name] = has_owner ? is_group ? LLGroupActions::getSLURL(owner_id) : LLAvatarActions::getSLURL(owner_id) : + is_group ? last_name : LLCacheName::buildFullName(first_name, last_name); if (is_text_box) { - args["DEFAULT"] = default_text; - payload["textbox"] = "true"; + payload["textbox"] = true; LLNotificationsUtil::add("ScriptTextBoxDialog", args, payload, callback_script_dialog); } - else if (!first_name.empty()) + else if (!is_group) { notification = LLNotifications::instance().add( LLNotification::Params("ScriptDialog").substitutions(args).payload(payload).form_elements(form.asLLSD())); @@ -8207,15 +7060,15 @@ bool callback_load_url(const LLSD& notification, const LLSD& response) return false; } -static LLNotificationFunctorRegistration callback_load_url_reg("LoadWebPage", callback_load_url); +static LLNotificationFunctorRegistration callback_load_url_reg("LoadWebPage", callback_load_url); -// We've got the name of the person who owns the object hurling the url. +// We've got the name of the person or group that owns the object hurling the url. // Display confirmation dialog. void callback_load_url_name(const LLUUID& id, const std::string& full_name, bool is_group) { std::vector::iterator it; - for (it = gLoadUrlList.begin(); it != gLoadUrlList.end(); ) + for (it = gLoadUrlList.begin(); it != gLoadUrlList.end();) { LLSD load_url_info = *it; if (load_url_info["owner_id"].asUUID() == id) @@ -8239,7 +7092,7 @@ void callback_load_url_name(const LLUUID& id, const std::string& full_name, bool } LLSD args; args["URL"] = load_url_info["url"].asString(); - args["MESSAGE"] = load_url_info["message"].asString();; + args["MESSAGE"] = load_url_info["message"].asString(); args["OBJECTNAME"] = load_url_info["object_name"].asString(); args["NAME"] = owner_name; @@ -8252,6 +7105,12 @@ void callback_load_url_name(const LLUUID& id, const std::string& full_name, bool } } +// We've got the name of the person who owns the object hurling the url. +void callback_load_url_avatar_name(const LLUUID& id, const LLAvatarName& av_name) +{ + callback_load_url_name(id, av_name.getUserName(), false); +} + void process_load_url(LLMessageSystem* msg, void**) { LLUUID object_id; @@ -8262,21 +7121,26 @@ void process_load_url(LLMessageSystem* msg, void**) char url[256]; /* Flawfinder: ignore */ msg->getString("Data", "ObjectName", 256, object_name); - msg->getUUID( "Data", "ObjectID", object_id); - msg->getUUID( "Data", "OwnerID", owner_id); + msg->getUUID("Data", "ObjectID", object_id); + msg->getUUID("Data", "OwnerID", owner_id); // NaCl - Antispam - if (owner_id.isNull() ? is_spam_filtered(IM_COUNT, LLAvatarActions::isFriend(object_id), object_id == gAgentID) : is_spam_filtered(IM_COUNT, LLAvatarActions::isFriend(owner_id), owner_id == gAgentID)) return; + if (owner_id.isNull() ? is_spam_filtered(IM_COUNT, LLAvatarActions::isFriend(object_id), object_id == gAgentID) + : is_spam_filtered(IM_COUNT, LLAvatarActions::isFriend(owner_id), owner_id == gAgentID)) return; // NaCl End + msg->getBOOL("Data", "OwnerIsGroup", owner_is_group); // NaCl - Antispam Registry - if((owner_id.isNull() - && NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG,object_id)) - || NACLAntiSpamRegistry::checkQueue((U32)NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG,owner_id)) - return; + if (NACLAntiSpamRegistry::instanceExists()) + { + auto& antispam = NACLAntiSpamRegistry::instance(); + if ((owner_id.isNull() + && antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, object_id, LFIDBearer::OBJECT)) + || antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, owner_id, owner_is_group ? LFIDBearer::GROUP : LFIDBearer::AVATAR)) + return; + } // NaCl End - msg->getBOOL( "Data", "OwnerIsGroup", owner_is_group); msg->getString("Data", "Message", 256, message); msg->getString("Data", "URL", 256, url); @@ -8294,15 +7158,21 @@ void process_load_url(LLMessageSystem* msg, void**) if (LLMuteList::getInstance()->isMuted(object_id, object_name) || LLMuteList::getInstance()->isMuted(owner_id)) { - LL_INFOS("Messaging")<<"Ignoring load_url from muted object/owner."<get(owner_id, owner_is_group, - boost::bind(&callback_load_url_name, _1, _2, _3)); + if (owner_is_group) + { + gCacheName->getGroup(owner_id, boost::bind(&callback_load_url_name, _1, _2, _3)); + } + else + { + LLAvatarNameCache::get(owner_id, boost::bind(&callback_load_url_avatar_name, _1, _2)); + } } @@ -8370,7 +7240,6 @@ void process_script_teleport_request(LLMessageSystem* msg, void**) // remove above two lines and replace with below line // to re-enable parcel browser for llMapDestination() // LLURLDispatcher::dispatch(LLSLURL::buildSLURL(sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]), FALSE); - } void process_covenant_reply(LLMessageSystem* msg, void**) @@ -8388,7 +7257,10 @@ void process_covenant_reply(LLMessageSystem* msg, void**) LLPanelEstateInfo::updateEstateName(estate_name); LLFloaterBuyLand::updateEstateName(estate_name); - LLAvatarNameCache::get(estate_owner_id, boost::bind(&callbackCacheEstateOwnerName, _1, _2)); + LLPanelEstateCovenant::updateEstateOwnerID(estate_owner_id); + LLPanelLandCovenant::updateEstateOwnerID(estate_owner_id); + LLPanelEstateInfo::updateEstateOwnerID(estate_owner_id); + LLFloaterBuyLand::updateEstateOwnerID(estate_owner_id); // standard message, not from system std::string last_modified; @@ -8398,7 +7270,7 @@ void process_covenant_reply(LLMessageSystem* msg, void**) } else { - last_modified = LLTrans::getString("covenant_modified") + " " + formatted_time((time_t)covenant_timestamp); + last_modified = LLTrans::getString("covenant_modified") + ' ' + formatted_time((time_t)covenant_timestamp); } LLPanelEstateCovenant::updateLastModified(last_modified); @@ -8416,7 +7288,7 @@ void process_covenant_reply(LLMessageSystem* msg, void**) LLAssetType::AT_NOTECARD, ET_Covenant, onCovenantLoadComplete, - NULL, + nullptr, high_priority); } else @@ -8437,43 +7309,28 @@ void process_covenant_reply(LLMessageSystem* msg, void**) } } -void callbackCacheEstateOwnerName(const LLUUID& id, const LLAvatarName& av_name) -{ - const std::string name(av_name.getNSName()); - LLPanelEstateCovenant::updateEstateOwnerName(name); - LLPanelLandCovenant::updateEstateOwnerName(name); - LLPanelEstateInfo::updateEstateOwnerName(name); - LLFloaterBuyLand::updateEstateOwnerName(name); -} - -void onCovenantLoadComplete(LLVFS *vfs, +void onCovenantLoadComplete(LLVFS* vfs, const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status) { LL_DEBUGS("Messaging") << "onCovenantLoadComplete()" << LL_ENDL; std::string covenant_text; - if(0 == status) + if (0 == status) { LLVFile file(vfs, asset_uuid, type, LLVFile::READ); S32 file_length = file.getSize(); - char* buffer = new char[file_length+1]; - if (buffer == NULL) - { - LL_ERRS("Messaging") << "Memory Allocation failed" << LL_ENDL; - return; - } - - file.read((U8*)buffer, file_length); /* Flawfinder: ignore */ + std::vector buffer(file_length + 1); + file.read((U8*)&buffer[0], file_length); // put a EOS at the end - buffer[file_length] = 0; - - if( (file_length > 19) && !strncmp( buffer, "Linden text version", 19 ) ) + buffer[file_length] = '\0'; + + if ((file_length > 19) && !strncmp(&buffer[0], "Linden text version", 19)) { LLViewerTextEditor * editor = new LLViewerTextEditor(std::string("temp"), LLRect(0,0,0,0), file_length+1); - if( !editor->importBuffer( buffer, file_length+1 ) ) + if( !editor->importBuffer( &buffer[0], file_length+1 ) ) { LL_WARNS("Messaging") << "Problem importing estate covenant." << LL_ENDL; covenant_text = "Problem importing estate covenant."; @@ -8490,13 +7347,12 @@ void onCovenantLoadComplete(LLVFS *vfs, LL_WARNS("Messaging") << "Problem importing estate covenant: Covenant file format error." << LL_ENDL; covenant_text = "Problem importing estate covenant: Covenant file format error."; } - delete[] buffer; } else { LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || + if (LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { covenant_text = "Estate covenant notecard is missing from database."; @@ -8524,9 +7380,9 @@ void process_feature_disabled_message(LLMessageSystem* msg, void**) LLUUID agentID; LLUUID transactionID; std::string messageText; - msg->getStringFast(_PREHASH_FailureInfo,_PREHASH_ErrorMessage, messageText,0); - msg->getUUIDFast(_PREHASH_FailureInfo,_PREHASH_AgentID,agentID); - msg->getUUIDFast(_PREHASH_FailureInfo,_PREHASH_TransactionID,transactionID); + msg->getStringFast(_PREHASH_FailureInfo, _PREHASH_ErrorMessage, messageText, 0); + msg->getUUIDFast(_PREHASH_FailureInfo, _PREHASH_AgentID, agentID); + msg->getUUIDFast(_PREHASH_FailureInfo, _PREHASH_TransactionID, transactionID); LL_WARNS("Messaging") << "Blacklisted Feature Response:" << messageText << LL_ENDL; } diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index ea3275cd7b..acfb590b07 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -70,6 +70,11 @@ enum InventoryOfferResponse BOOL can_afford_transaction(S32 cost); void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group = FALSE, S32 trx_type = TRANS_GIFT, const std::string& desc = LLStringUtil::null); +void send_join_group_response(const LLUUID& group_id, + const LLUUID& transaction_id, + bool accept_invite, + S32 fee, + bool use_offline_cap); void process_logout_reply(LLMessageSystem* msg, void**); void process_layer_data(LLMessageSystem *mesgsys, void **user_data); @@ -102,6 +107,7 @@ void process_health_message(LLMessageSystem *mesgsys, void **user_data); void process_sim_stats(LLMessageSystem *mesgsys, void **user_data); void process_shooter_agent_hit(LLMessageSystem* msg, void** user_data); void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data); +void process_object_animation(LLMessageSystem *mesgsys, void **user_data); void process_avatar_appearance(LLMessageSystem *mesgsys, void **user_data); void process_camera_constraint(LLMessageSystem *mesgsys, void **user_data); void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data); @@ -204,7 +210,6 @@ void process_decline_callingcard(LLMessageSystem* msg, void**); // Message system exception prototypes void invalid_message_callback(LLMessageSystem*, void*, EMessageException); - void process_initiate_download(LLMessageSystem* msg, void**); void start_new_inventory_observer(); void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name); diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h index bb15fd323c..18a6e0c456 100644 --- a/indra/newview/llviewernetwork.h +++ b/indra/newview/llviewernetwork.h @@ -63,7 +63,7 @@ class LLViewerLogin : public LLSingleton private: //void parseCommandLineURIs(); - bool mNameEditted; // Set if the user edits/sets the First or Last name field. + bool mNameEditted = false; // Set if the user edits/sets the First or Last name field. }; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 0f4f433d51..8deaa7829e 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewerobject.cpp * @brief Base class for viewer objects * * $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$ */ @@ -59,6 +59,7 @@ #include "llbbox.h" #include "llbox.h" #include "llcylinder.h" +#include "llcontrolavatar.h" #include "lldrawable.h" #include "llface.h" #include "llfloaterproperties.h" @@ -68,6 +69,7 @@ #include "llselectmgr.h" #include "llrendersphere.h" #include "lltooldraganddrop.h" +#include "lluiavatar.h" #include "llviewercamera.h" #include "llviewertexturelist.h" #include "llviewerinventory.h" @@ -98,7 +100,7 @@ #include "llvowlsky.h" #include "llmanip.h" #include "llmediaentry.h" - +#include "llmeshrepository.h" // [RLVa:KB] #include "rlvhandler.h" #include "rlvlocks.h" @@ -107,7 +109,7 @@ //#define DEBUG_UPDATE_TYPE BOOL LLViewerObject::sVelocityInterpolate = TRUE; -BOOL LLViewerObject::sPingInterpolate = TRUE; +BOOL LLViewerObject::sPingInterpolate = TRUE; U32 LLViewerObject::sNumZombieObjects = 0; S32 LLViewerObject::sNumObjects = 0; @@ -119,18 +121,30 @@ BOOL LLViewerObject::sPulseEnabled(FALSE); BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE // sMaxUpdateInterpolationTime must be greater than sPhaseOutUpdateInterpolationTime -F64 LLViewerObject::sMaxUpdateInterpolationTime = 3.0; // For motion interpolation: after X seconds with no updates, don't predict object motion -F64 LLViewerObject::sPhaseOutUpdateInterpolationTime = 2.0; // For motion interpolation: after Y seconds with no updates, taper off motion prediction +F64Seconds LLViewerObject::sMaxUpdateInterpolationTime(3.0); // For motion interpolation: after X seconds with no updates, don't predict object motion +F64Seconds LLViewerObject::sPhaseOutUpdateInterpolationTime(2.0); // For motion interpolation: after Y seconds with no updates, taper off motion prediction + +std::map LLViewerObject::sObjectDataMap; + +// The maximum size of an object extra parameters binary (packed) block +#define MAX_OBJECT_PARAMS_SIZE 1024 + +// At 45 Hz collisions seem stable and objects seem +// to settle down at a reasonable rate. +// JC 3/18/2003 +const F32 PHYSICS_TIMESTEP = 1.f / 45.f; +const U32 MAX_INV_FILE_READ_FAILS = 25; +const S32 MAX_OBJECT_BINARY_DATA_SIZE = 60 + 16; -static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object"); +static LLTrace::BlockTimerStatHandle FTM_CREATE_OBJECT("Create Object"); // static -LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) +LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, S32 flags) { LLViewerObject *res = NULL; - LLFastTimer t1(FTM_CREATE_OBJECT); - + LL_RECORD_BLOCK_TIME(FTM_CREATE_OBJECT); + switch (pcode) { case LL_PCODE_VOLUME: @@ -145,7 +159,7 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco gAgentAvatarp->initInstance(); gAgentWearables.setAvatarObject(gAgentAvatarp); } - else + else { if (isAgentAvatarValid()) { @@ -154,9 +168,21 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco } res = gAgentAvatarp; } + else if (flags & CO_FLAG_CONTROL_AVATAR) + { + LLControlAvatar *control_avatar = new LLControlAvatar(id, pcode, regionp); + control_avatar->initInstance(); + res = control_avatar; + } + else if (flags & CO_FLAG_UI_AVATAR) + { + LLUIAvatar *ui_avatar = new LLUIAvatar(id, pcode, regionp); + ui_avatar->initInstance(); + res = ui_avatar; + } else { - LLVOAvatar *avatar = new LLVOAvatar(id, pcode, regionp); + LLVOAvatar *avatar = new LLVOAvatar(id, pcode, regionp); avatar->initInstance(); res = avatar; } @@ -224,6 +250,9 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mRenderMedia(FALSE), mBestUpdatePrecision(0), mText(), + + mHudTextColor(LLColor4::white), + mControlAvatar(NULL), mLastInterpUpdateSecs(0.f), mLastMessageUpdateSecs(0.f), mLatestRecvPacketID(0), @@ -234,9 +263,10 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mPixelArea(1024.f), mInventory(NULL), mInventorySerialNum(0), - mRegionp( regionp ), - mInventoryPending(FALSE), + mInvRequestState(INVENTORY_REQUEST_STOPPED), + mInvRequestXFerId(0), mInventoryDirty(FALSE), + mRegionp(regionp), mDead(FALSE), mOrphaned(FALSE), mUserSelected(FALSE), @@ -244,11 +274,10 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mOnMap(FALSE), mStatic(FALSE), mNumFaces(0), - mTimeDilation(1.f), mRotTime(0.f), mAngularVelocityRot(), mPreviousRotation(), - mState(0), + mAttachmentState(0), mMedia(NULL), mClickAction(0), mObjectCost(0), @@ -259,7 +288,8 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mPhysicsShapeUnknown(true), mAttachmentItemID(LLUUID::null), mLastUpdateType(OUT_UNKNOWN), - mLastUpdateCached(FALSE) + mLastUpdateCached(FALSE), + mExtraParameterList(LLNetworkData::PARAMS_MAX >> 4) { if(!is_global) { @@ -305,23 +335,11 @@ LLViewerObject::~LLViewerObject() } // Delete memory associated with extra parameters. - std::map::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - if(iter->second != NULL) - { - // - // There was a crash here - // - delete iter->second->data; - delete iter->second; - } - } mExtraParameterList.clear(); for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ; mNameValuePairs.clear(); - + delete[] mData; mData = NULL; @@ -339,18 +357,18 @@ void LLViewerObject::deleteTEImages() { delete[] mTEImages; mTEImages = NULL; - + if (mTENormalMaps != NULL) { delete[] mTENormalMaps; mTENormalMaps = NULL; } - + if (mTESpecularMaps != NULL) { delete[] mTESpecularMaps; mTESpecularMaps = NULL; - } + } } void LLViewerObject::markDead() @@ -358,7 +376,7 @@ void LLViewerObject::markDead() if (!mDead) { //LL_INFOS() << "Marking self " << mLocalID << " as dead." << LL_ENDL; - + // if (isSelected()) { @@ -377,9 +395,26 @@ void LLViewerObject::markDead() { ((LLViewerObject *)getParent())->removeChild(this); } + LLUUID mesh_id; + { + LLVOAvatar *av = getAvatar(); + if (av && LLVOAvatar::getRiggedMeshID(this,mesh_id)) + { + // This case is needed for indirectly attached mesh objects. + av->updateAttachmentOverrides(); + } + } + if (getControlAvatar()) + { + unlinkControlAvatar(); + } // Mark itself as dead mDead = TRUE; + if(mRegionp) + { + mRegionp->removeFromCreatedList(getLocalID()); + } gObjectList.cleanupReferences(this); LLViewerObject *childp; @@ -394,7 +429,7 @@ void LLViewerObject::markDead() } else { - // make sure avatar is no longer parented, + // make sure avatar is no longer parented, // so we can properly set it's position childp->setDrawableParent(NULL); ((LLVOAvatar*)childp)->getOffObject(); @@ -469,8 +504,8 @@ void LLViewerObject::dump() const LL_INFOS() << "PositionAgent: " << getPositionAgent() << LL_ENDL; LL_INFOS() << "PositionGlobal: " << getPositionGlobal() << LL_ENDL; LL_INFOS() << "Velocity: " << getVelocity() << LL_ENDL; - if (mDrawable.notNull() && - mDrawable->getNumFaces() && + if (mDrawable.notNull() && + mDrawable->getNumFaces() && mDrawable->getFace(0)) { LLFacePool *poolp = mDrawable->getFace(0)->getPool(); @@ -529,6 +564,8 @@ void LLViewerObject::initVOClasses() LLVOGrass::initClass(); LLVOWater::initClass(); LLVOVolume::initClass(); + + initObjectDataMap(); } void LLViewerObject::cleanupVOClasses() @@ -538,6 +575,118 @@ void LLViewerObject::cleanupVOClasses() LLVOTree::cleanupClass(); LLVOAvatar::cleanupClass(); LLVOVolume::cleanupClass(); + + sObjectDataMap.clear(); +} + +//object data map for compressed && !OUT_TERSE_IMPROVED +//static +void LLViewerObject::initObjectDataMap() +{ + U32 count = 0; + + sObjectDataMap["ID"] = count; //full id //LLUUID + count += sizeof(LLUUID); + + sObjectDataMap["LocalID"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["PCode"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["State"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["CRC"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["Material"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["ClickAction"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["Scale"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["Pos"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["Rot"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["SpecialCode"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["Owner"] = count; //LLUUID + count += sizeof(LLUUID); + + sObjectDataMap["Omega"] = count; //LLVector3, when SpecialCode & 0x80 is set + count += sizeof(LLVector3); + + //ParentID is after Omega if there is Omega, otherwise is after Owner + sObjectDataMap["ParentID"] = count;//U32, when SpecialCode & 0x20 is set + count += sizeof(U32); + + //------- + //The rest items are not included here + //------- +} + +//static +void LLViewerObject::unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackVector3(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackUUID(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackU32(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackU8(value, name.c_str()); + dp->reset(); +} + +//static +U32 LLViewerObject::unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id) +{ + dp->shift(sObjectDataMap["SpecialCode"]); + U32 value; + dp->unpackU32(value, "SpecialCode"); + + parent_id = 0; + if(value & 0x20) + { + S32 offset = sObjectDataMap["ParentID"]; + if(!(value & 0x80)) + { + offset -= sizeof(LLVector3); + } + + dp->shift(offset); + dp->unpackU32(parent_id, "ParentID"); + } + dp->reset(); + + return parent_id; } // Replaces all name value pairs with data from \n delimited list @@ -564,6 +713,37 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list) } } +BOOL LLViewerObject::isAnySelected() const +{ + bool any_selected = isSelected(); + for (child_list_t::const_iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + const LLViewerObject* child = *iter; + any_selected = any_selected || child->isSelected(); + } + return any_selected; +} + +void LLViewerObject::setSelected(BOOL sel) +{ + mUserSelected = sel; + static const LLCachedControl use_new_target_omega ("UseNewTargetOmegaCode", true); + if(use_new_target_omega) + { + resetRot(); + } + else + { + mRotTime = 0.f; + } + + if (!sel) + { + setAllTESelected(false); + } +} + // This method returns true if the object is over land owned by the // agent. bool LLViewerObject::isReturnable() @@ -572,7 +752,7 @@ bool LLViewerObject::isReturnable() { return false; } - + // [RLVa:KB] - Checked: 2011-05-28 (RLVa-1.4.0a) | Added: RLVa-1.4.0a // Block if: @rez=n restricted and owned by us or a group *or* @unsit=n restricted and being sat on by us if ( (rlv_handler_t::isEnabled()) && @@ -592,19 +772,19 @@ bool LLViewerObject::isReturnable() } bool result = (mRegionp && mRegionp->objectIsReturnable(getPositionRegion(), boxes)) ? 1 : 0; - + if ( !result ) - { + { //Get list of neighboring regions relative to this vo's region std::vector uniqueRegions; mRegionp->getNeighboringRegions( uniqueRegions ); - + //Build aabb's - for root and all children std::vector returnables; typedef std::vector::iterator RegionIt; RegionIt regionStart = uniqueRegions.begin(); RegionIt regionEnd = uniqueRegions.end(); - + for (; regionStart != regionEnd; ++regionStart ) { LLViewerRegion* pTargetRegion = *regionStart; @@ -614,26 +794,26 @@ bool LLViewerObject::isReturnable() //Add it's children for (child_list_t::iterator iter = mChildList.begin(); iter != mChildList.end(); iter++) { - LLViewerObject* pChild = *iter; + LLViewerObject* pChild = *iter; buildReturnablesForChildrenVO( returnables, pChild, pTargetRegion ); } - } - - //TBD#Eventually create a region -> box list map + } + + //TBD#Eventually create a region -> box list map typedef std::vector::iterator ReturnablesIt; ReturnablesIt retCurrentIt = returnables.begin(); ReturnablesIt retEndIt = returnables.end(); - + for ( ; retCurrentIt !=retEndIt; ++retCurrentIt ) { boxes.clear(); LLViewerRegion* pRegion = (*retCurrentIt).pRegion; - boxes.push_back( (*retCurrentIt).box ); + boxes.push_back( (*retCurrentIt).box ); bool retResult = pRegion && pRegion->childrenObjectReturnable( boxes ) && pRegion->canManageEstate(); if ( retResult ) - { + { result = true; break; } @@ -648,9 +828,9 @@ void LLViewerObject::buildReturnablesForChildrenVO( std::vectormChildList.begin(); iter != pChild->mChildList.end(); iter++) { @@ -661,20 +841,20 @@ void LLViewerObject::buildReturnablesForChildrenVO( std::vector& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion ) { - + LLVector3 targetRegionPos; - targetRegionPos.setVec( pChild->getPositionGlobal() ); - - LLBBox childBBox = LLBBox( targetRegionPos, pChild->getRotationRegion(), pChild->getScale() * -0.5f, - pChild->getScale() * 0.5f).getAxisAligned(); - + targetRegionPos.setVec( pChild->getPositionGlobal() ); + + LLBBox childBBox = LLBBox( targetRegionPos, pChild->getRotationRegion(), pChild->getScale() * -0.5f, + pChild->getScale() * 0.5f).getAxisAligned(); + LLVector3 edgeA = targetRegionPos + childBBox.getMinLocal(); LLVector3 edgeB = targetRegionPos + childBBox.getMaxLocal(); - + LLVector3d edgeAd, edgeBd; edgeAd.setVec(edgeA); edgeBd.setVec(edgeB); - + //Only add the box when either of the extents are in a neighboring region if ( pTargetRegion->pointInRegionGlobal( edgeAd ) || pTargetRegion->pointInRegionGlobal( edgeBd ) ) { @@ -703,7 +883,7 @@ BOOL LLViewerObject::setParent(LLViewerObject* parent) { if (mParent != parent) { - LLViewerObject* old_parent = (LLViewerObject*)mParent ; + LLViewerObject* old_parent = (LLViewerObject*)mParent ; BOOL ret = LLPrimitive::setParent(parent); if (ret && old_parent && parent) { @@ -724,7 +904,7 @@ void LLViewerObject::addChild(LLViewerObject *childp) return; } } - + if (!isAvatar()) { // propagate selection properties @@ -734,9 +914,18 @@ void LLViewerObject::addChild(LLViewerObject *childp) if (childp->setParent(this)) { mChildList.push_back(childp); + childp->afterReparent(); } } +void LLViewerObject::onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent) +{ +} + +void LLViewerObject::afterReparent() +{ +} + void LLViewerObject::removeChild(LLViewerObject *childp) { for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i) @@ -752,12 +941,12 @@ void LLViewerObject::removeChild(LLViewerObject *childp) if(childp->getParent() == this) { - childp->setParent(NULL); + childp->setParent(NULL); } break; } } - + if (childp->isSelected()) { LLSelectMgr::getInstance()->deselectObjectAndFamily(childp); @@ -844,8 +1033,8 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp) return FALSE ; } LLDrawable* old_parent = mDrawable->mParent; - mDrawable->mParent = parentp; - + mDrawable->mParent = parentp; + if (parentp && mDrawable->isActive()) { parentp->makeActive(); @@ -867,7 +1056,7 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp) mDrawable->movePartition(); }*/ } - + return ret; } @@ -895,7 +1084,7 @@ void LLViewerObject::hideExtraDisplayItems( BOOL hidden ) U32 LLViewerObject::checkMediaURL(const std::string &media_url) { - U32 retval = (U32)0x0; + U32 retval = (U32)0x0; if (!mMedia && !media_url.empty()) { retval |= MEDIA_URL_ADDED; @@ -911,23 +1100,41 @@ U32 LLViewerObject::checkMediaURL(const std::string &media_url) retval |= MEDIA_URL_REMOVED; delete mMedia; mMedia = NULL; - } - else if (mMedia->mMediaURL != media_url) // <-- This is an optimization. If they are equal don't bother with below's test. - { - /*if (! (LLTextureEntry::getAgentIDFromMediaVersionString(media_url) == gAgent.getID() && - LLTextureEntry::getVersionFromMediaVersionString(media_url) == - LLTextureEntry::getVersionFromMediaVersionString(mMedia->mMediaURL) + 1)) + } + else if (mMedia->mMediaURL != media_url) // <-- This is an optimization. If they are equal don't bother with below's test. + { + /*if (! (LLTextureEntry::getAgentIDFromMediaVersionString(media_url) == gAgent.getID() && + LLTextureEntry::getVersionFromMediaVersionString(media_url) == + LLTextureEntry::getVersionFromMediaVersionString(mMedia->mMediaURL) + 1)) */ - { - // If the media URL is different and WE were not the one who - // changed it, mark dirty. - retval |= MEDIA_URL_UPDATED; - } - mMedia->mMediaURL = media_url; - mMedia->mPassedWhitelist = FALSE; - } - } - return retval; + { + // If the media URL is different and WE were not the one who + // changed it, mark dirty. + retval |= MEDIA_URL_UPDATED; + } + mMedia->mMediaURL = media_url; + mMedia->mPassedWhitelist = FALSE; + } + } + return retval; +} + +//extract spatial information from object update message +//return parent_id +//static +U32 LLViewerObject::extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot) +{ + U32 parent_id = 0; + LLViewerObject::unpackParentID(dp, parent_id); + + LLViewerObject::unpackVector3(dp, scale, "Scale"); + LLViewerObject::unpackVector3(dp, pos, "Pos"); + + LLVector3 vec; + LLViewerObject::unpackVector3(dp, vec, "Rot"); + rot.unpackFromVector3(vec); + + return parent_id; } U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, @@ -937,7 +1144,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, LLDataPacker *dp) { U32 retval = 0x0; - + // If region is removed from the list it is also deleted. if (!LLWorld::instance().isRegionListed(mRegionp)) { @@ -946,14 +1153,15 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } // Coordinates of objects on simulators are region-local. - U64 region_handle; - mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); + U64 region_handle = 0; + if(mesgsys != NULL) { + mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); if(regionp != mRegionp && regionp && mRegionp)//region cross { - //this is the redundant position and region update, but it is necessary in case the viewer misses the following + //this is the redundant position and region update, but it is necessary in case the viewer misses the following //position and region update messages from sim. //this redundant update should not cause any problems. LLVector3 delta_pos = mRegionp->getOriginAgent() - regionp->getOriginAgent(); @@ -962,10 +1170,21 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } else { + if(regionp != mRegionp) + { + if(mRegionp) + { + mRegionp->removeFromCreatedList(getLocalID()); + } + if(regionp) + { + regionp->addToCreatedList(getLocalID()); + } + } mRegionp = regionp ; } - } - + } + if (!mRegionp) { U32 x, y; @@ -975,11 +1194,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, return retval; } - U16 time_dilation16; - mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16); - F32 time_dilation = ((F32) time_dilation16) / 65535.f; - mTimeDilation = time_dilation; - mRegionp->setTimeDilation(time_dilation); + F32 time_dilation = 1.f; + if(mesgsys != NULL) + { + U16 time_dilation16; + mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16); + time_dilation = ((F32) time_dilation16) / 65535.f; + mRegionp->setTimeDilation(time_dilation); + } // this will be used to determine if we've really changed position // Use getPosition, not getPositionRegion, since this is what we're comparing directly against. @@ -1007,6 +1229,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, parent_id = cur_parentp->mLocalID; } + if (!dp) { switch(update_type) @@ -1035,10 +1258,11 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_Sound, audio_uuid, block_num ); // HACK: Owner id only valid if non-null sound id or particle system mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, block_num ); + if (owner_id.notNull()) mOwnerID = owner_id; // Singu Note: Try to get Owner whenever possible mesgsys->getF32Fast( _PREHASH_ObjectData, _PREHASH_Gain, gain, block_num ); mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_Flags, sound_flags, block_num ); mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_Material, material, block_num ); - mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_ClickAction, click_action, block_num); + mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_ClickAction, click_action, block_num); mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_Scale, new_scale, block_num ); mTotalCRC = crc; @@ -1069,8 +1293,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, mFlags |= flags; U8 state; - mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num ); - mState = state; + mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num); + mAttachmentState = state; // ...new objects that should come in selected need to be added to the selected list mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); @@ -1112,17 +1336,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Setup object text if (!mText) { - mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT); - mText->setFont(LLFontGL::getFontSansSerif()); - mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP); - mText->setMaxLines(-1); - mText->setSourceObject(this); - mText->setOnHUDAttachment(isHUDAttachment()); + initHudText(); } //Cache for reset on debug infodisplay toggle. mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, mHudTextString, block_num ); - + LLColor4U coloru; mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num); @@ -1140,7 +1359,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, mText->setObjectText(mHudTextString); } // [/RLVa:KB] - + setChanged(MOVED | SILHOUETTE); } else if (mText.notNull()) @@ -1151,18 +1370,17 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string media_url; mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, media_url, block_num); - retval |= checkMediaURL(media_url); - + retval |= checkMediaURL(media_url); + // // Unpack particle system data // unpackParticleSource(block_num, owner_id); // Mark all extra parameters not used - std::map::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 @@ -1189,12 +1407,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((i + 1) << 4, entry.data, FALSE, false); } } break; @@ -1228,7 +1447,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, U8 state; dp->unpackU8(state, "State"); - mState = state; + mAttachmentState = state; switch(update_type) { @@ -1289,7 +1508,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { gFloaterTools->dirty(); } - + dp->unpackU32(crc, "CRC"); mTotalCRC = crc; dp->unpackU8(material, "Material"); @@ -1394,15 +1613,15 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, mText = NULL; } - std::string media_url; + std::string media_url; if (value & 0x200) { dp->unpackString(media_url, "MediaURL"); } - retval |= checkMediaURL(media_url); + retval |= checkMediaURL(media_url); // - // Unpack particle system data + // Unpack particle system data (legacy) // if (value & 0x8) { @@ -1412,12 +1631,11 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { deleteParticleSource(); } - + // Mark all extra parameters not used - std::map::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 @@ -1435,12 +1653,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((i + 1) << 4, entry.data, FALSE, false); } } @@ -1468,13 +1687,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Preload these five flags for every object. // Finer shades require the object to be selected, and the selection manager // stores the extended permission info. - U32 flags; - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); - // keep local flags and overwrite remote-controlled flags - mFlags = (mFlags & FLAGS_LOCAL) | flags; - - // ...new objects that should come in selected need to be added to the selected list - mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + if(mesgsys != NULL) + { + U32 flags; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); + loadFlags(flags); + } } break; @@ -1482,7 +1700,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, break; } } - // // Fix object parenting. // @@ -1502,10 +1719,21 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { // No parent now, new parent in message -> attach to that parent if possible LLUUID parent_uuid; - LLViewerObjectList::getUUIDFromLocal(parent_uuid, + + if(mesgsys != NULL) + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, mesgsys->getSenderIP(), mesgsys->getSenderPort()); + } + else + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, + parent_id, + mRegionp->getHost().getAddress(), + mRegionp->getHost().getPort()); + } LLViewerObject *sent_parentp = gObjectList.findObject(parent_uuid); @@ -1516,7 +1744,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { static std::map state_map; std::map::iterator it = state_map.find(getID()); - + if(it != state_map.end() && (!it->second && sent_parentp)) { it->second = sent_parentp != NULL; @@ -1535,9 +1763,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, this->removeChild(sent_parentp); sent_parentp->setDrawableParent(NULL); } - + if (sent_parentp && (sent_parentp != this) && !sent_parentp->isDead()) { + if (((LLViewerObject*)sent_parentp)->isAvatar()) + { + //LL_DEBUGS("Avatar") << "ATT got object update for attachment " << LL_ENDL; + } + // // We have a viewer object for the parent, and it's not dead. // Do the actual reparenting here. @@ -1575,7 +1808,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, if ( (rlv_handler_t::isEnabled()) && (sent_parentp->isAvatar()) && (sent_parentp->getID() == gAgent.getID()) ) { // Rezzed object that's being worn as an attachment (we're assuming this will be due to llAttachToAvatar()) - S32 idxAttachPt = ATTACHMENT_ID_FROM_STATE(getState()); + S32 idxAttachPt = ATTACHMENT_ID_FROM_STATE(getAttachmentState()); if (gRlvAttachmentLocks.isLockedAttachmentPoint(idxAttachPt, RLV_LOCK_ADD)) { // If this will end up on an "add locked" attachment point then treat the attach as a user action @@ -1602,7 +1835,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { sent_parentp->addChild(this); } - + // Show particles, icon and HUD hideExtraDisplayItems( FALSE ); @@ -1614,11 +1847,20 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // No corresponding viewer object for the parent, put the various // pieces on the orphan list. // - + //parent_id - U32 ip = mesgsys->getSenderIP(); - U32 port = mesgsys->getSenderPort(); - + U32 ip, port; + + if(mesgsys != NULL) + { + ip = mesgsys->getSenderIP(); + port = mesgsys->getSenderPort(); + } + else + { + ip = mRegionp->getHost().getAddress(); + port = mRegionp->getHost().getPort(); + } gObjectList.orphanize(this, parent_id, ip, port); // Hide particles, icon and HUD @@ -1656,12 +1898,23 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, else { LLUUID parent_uuid; - LLViewerObjectList::getUUIDFromLocal(parent_uuid, + + if(mesgsys != NULL) + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); + } + else + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, + parent_id, + mRegionp->getHost().getAddress(), + mRegionp->getHost().getPort()); + } sent_parentp = gObjectList.findObject(parent_uuid); - + if (isAvatar()) { // This logic is meant to handle the case where a sitting avatar has reached a new sim @@ -1680,8 +1933,18 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // // Switching parents, but we don't know the new parent. // - U32 ip = mesgsys->getSenderIP(); - U32 port = mesgsys->getSenderPort(); + U32 ip, port; + + if(mesgsys != NULL) + { + ip = mesgsys->getSenderIP(); + port = mesgsys->getSenderPort(); + } + else + { + ip = mRegionp->getHost().getAddress(); + port = mRegionp->getHost().getPort(); + } // We're an orphan, flag things appropriately. gObjectList.orphanize(this, parent_id, ip, port); @@ -1765,13 +2028,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, new_rot.normQuat(); - if (sPingInterpolate) - { + if (sPingInterpolate && mesgsys != NULL) + { LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender()); if (cdp) { - F32 ping_delay = 0.5f * mTimeDilation * ( ((F32)cdp->getPingDelay()) * 0.001f + gFrameDTClamped); - LLVector3 diff = getVelocity() * ping_delay; + F32 ping_delay = 0.5f * time_dilation * ( ((F32)cdp->getPingDelay().valueInUnits()) + gFrameDTClamped); + LLVector3 diff = getVelocity() * ping_delay; new_pos_parent += diff; } else @@ -1786,18 +2049,20 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // // - // If we're going to skip this message, why are we + // If we're going to skip this message, why are we // doing all the parenting, etc above? - U32 packet_id = mesgsys->getCurrentRecvPacketID(); - if (packet_id < mLatestRecvPacketID && - mLatestRecvPacketID - packet_id < 65536) + if(mesgsys != NULL) { - //skip application of this message, it's old - return retval; + U32 packet_id = mesgsys->getCurrentRecvPacketID(); + if (packet_id < mLatestRecvPacketID && + mLatestRecvPacketID - packet_id < 65536) + { + //skip application of this message, it's old + return retval; + } + mLatestRecvPacketID = packet_id; } - mLatestRecvPacketID = packet_id; - // Set the change flags for scale if (new_scale != getScale()) { @@ -1819,16 +2084,16 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, ||(this_update_precision > mBestUpdatePrecision)))) { mBestUpdatePrecision = this_update_precision; - + LLVector3 diff = new_pos_parent - test_pos_parent ; F32 mag_sqr = diff.magVecSquared() ; - if(llfinite(mag_sqr)) + if(std::isfinite(mag_sqr)) { setPositionParent(new_pos_parent); } else { - LL_WARNS() << "Can not move the object/avatar to an infinite location!" << LL_ENDL ; + LL_WARNS() << "Can not move the object/avatar to an infinite location!" << LL_ENDL ; retval |= INVALID_UPDATE ; } @@ -1893,7 +2158,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } } - if ( gShowObjectUpdates ) { LLColor4 color; @@ -1914,7 +2178,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, llassert(accel_mag_sq >= 0.f); llassert(getAngularVelocity().magVecSquared() >= 0.f); - if ((MAG_CUTOFF >= vel_mag_sq) && + if ((MAG_CUTOFF >= vel_mag_sq) && (MAG_CUTOFF >= accel_mag_sq) && (MAG_CUTOFF >= getAngularVelocity().magVecSquared())) { @@ -1938,10 +2202,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Additionally, if any child is selected, need to update the dialogs and selection // center. BOOL needs_refresh = mUserSelected; - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) + for (auto& iter : mChildList) { - LLViewerObject* child = *iter; + LLViewerObject* child = iter; needs_refresh = needs_refresh || child->mUserSelected; } @@ -1954,7 +2217,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // LLSelectMgr::getInstance()->updateSelectionCenter(); dialog_refresh_all(); - } + } // Mark update time as approx. now, with the ping delay. @@ -1989,13 +2252,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, void LLViewerObject::processTerseData(LLMessageSystem *mesgsys, void **user_data, U32 block_num, S32& this_update_precision, LLVector3& new_pos_parent, LLQuaternion& new_rot, LLVector3& new_angv, LLVector3& test_pos_parent) { // Aurora Sim - //const F32 size = LLWorld::getInstance()->getRegionWidthInMeters(); + //const F32 size = LLWorld::getInstance()->getRegionWidthInMeters(); const F32 size = mRegionp->getWidth(); // Aurora Sim const F32 MAX_HEIGHT = LLWorld::getInstance()->getRegionMaxHeight(); const F32 MIN_HEIGHT = LLWorld::getInstance()->getRegionMinHeight(); - U8 data[60+16]; // This needs to match the largest size below. + U8 data[MAX_OBJECT_PARAMS_SIZE]; // This needs to match the largest size below. #ifdef LL_BIG_ENDIAN U16 valswizzle[4]; #endif @@ -2004,7 +2267,7 @@ void LLViewerObject::processTerseData(LLMessageSystem *mesgsys, void **user_data LLVector4 collision_plane; S32 length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num); + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_PARAMS_SIZE); switch (length) { @@ -2060,7 +2323,7 @@ void LLViewerObject::processTerseData(LLMessageSystem *mesgsys, void **user_data test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); #ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); val = valswizzle; #else val = (U16 *)&data[count]; @@ -2071,7 +2334,7 @@ void LLViewerObject::processTerseData(LLMessageSystem *mesgsys, void **user_data new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT); #ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); val = valswizzle; #else val = (U16 *)&data[count]; @@ -2082,7 +2345,7 @@ void LLViewerObject::processTerseData(LLMessageSystem *mesgsys, void **user_data U16_to_F32(val[VZ], -size, size)); #ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); val = valswizzle; #else val = (U16 *)&data[count]; @@ -2093,7 +2356,7 @@ void LLViewerObject::processTerseData(LLMessageSystem *mesgsys, void **user_data U16_to_F32(val[VZ], -size, size)); #ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 8); + htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 8); val = valswizzle; #else val = (U16 *)&data[count]; @@ -2105,7 +2368,7 @@ void LLViewerObject::processTerseData(LLMessageSystem *mesgsys, void **user_data new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f); #ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); val = valswizzle; #else val = (U16 *)&data[count]; @@ -2156,7 +2419,9 @@ void LLViewerObject::processTerseData(LLMessageSystem *mesgsys, void **user_data break; } - mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, mState, block_num); + U8 state; + mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num); + mAttachmentState = state; } BOOL LLViewerObject::isActive() const @@ -2164,86 +2429,100 @@ BOOL LLViewerObject::isActive() const return TRUE; } +//load flags from cache or from message +void LLViewerObject::loadFlags(U32 flags) +{ + if(flags == (U32)(-1)) + { + return; //invalid + } + // keep local flags and overwrite remote-controlled flags + mFlags = (mFlags & FLAGS_LOCAL) | flags; + + // ...new objects that should come in selected need to be added to the selected list + mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + return; +} void LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - //static LLFastTimer::DeclareTimer ftm("Viewer Object"); - //LLFastTimer t(ftm); + //static LLTrace::BlockTimerStatHandle ftm("Viewer Object"); + //LL_RECORD_BLOCK_TIME(ftm); if (!mDead) { - // CRO - don't velocity interp linked objects! - // Leviathan - but DO velocity interp joints - if (!mStatic && sVelocityInterpolate && !isSelected()) - { - // calculate dt from last update - F32 dt_raw = (F32)(time - mLastInterpUpdateSecs); - F32 dt = mTimeDilation * dt_raw; + if (!mStatic && sVelocityInterpolate && !isSelected()) + { + // calculate dt from last update + F32 time_dilation = mRegionp ? mRegionp->getTimeDilation() : 1.0f; + F32 dt_raw = ((F64Seconds)time - mLastInterpUpdateSecs).value(); + F32 dt = time_dilation * dt_raw; applyAngularVelocity(dt); if (isAttachment()) - { - mLastInterpUpdateSecs = time; + { + mLastInterpUpdateSecs = (F64Seconds)time; return; + } + else + { // Move object based on it's velocity and rotation + interpolateLinearMotion(time, dt); + } } - else - { // Move object based on it's velocity and rotation - interpolateLinearMotion(time, dt); - } - } - updateDrawable(FALSE); -} + updateDrawable(FALSE); + } } -// Move an object due to idle-time viewer side updates by iterpolating motion -void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) +// Move an object due to idle-time viewer side updates by interpolating motion +void LLViewerObject::interpolateLinearMotion(const F64SecondsImplicit& time, const F32SecondsImplicit& dt_seconds) { // linear motion // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object // updates represents the average velocity of the last timestep, rather than the final velocity. // the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically - // + // // *TODO: should also wrap linear accel/velocity in check // to see if object is selected, instead of explicitly - // zeroing it out + // zeroing it out - F64 time_since_last_update = time - mLastMessageUpdateSecs; - if (time_since_last_update <= 0.0 || dt <= 0.f) + F32 dt = dt_seconds; + F64Seconds time_since_last_update = time - mLastMessageUpdateSecs; + if (time_since_last_update <= (F64Seconds)0.0 || dt <= 0.f) { return; } LLVector3 accel = getAcceleration(); LLVector3 vel = getVelocity(); - - if (sMaxUpdateInterpolationTime <= 0.0) + + if (sMaxUpdateInterpolationTime <= (F64Seconds)0.0) { // Old code path ... unbounded, simple interpolation if (!(accel.isExactlyZero() && vel.isExactlyZero())) { - LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; - - // region local + LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; + + // region local setPositionRegion(pos + getPositionRegion()); - setVelocity(vel + accel*dt); - + setVelocity(vel + accel*dt); + // for objects that are spinning but not translating, make sure to flag them as having moved setChanged(MOVED | SILHOUETTE); } } else if (!accel.isExactlyZero() || !vel.isExactlyZero()) // object is moving { // Object is moving, and hasn't been too long since we got an update from the server - + // Calculate predicted position and velocity - LLVector3 new_pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; + LLVector3 new_pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; LLVector3 new_v = accel * dt; if (time_since_last_update > sPhaseOutUpdateInterpolationTime && - sPhaseOutUpdateInterpolationTime > 0.0) - { // Haven't seen a viewer update in a while, check to see if the ciruit is still active + sPhaseOutUpdateInterpolationTime > (F64Seconds)0.0) + { // Haven't seen a viewer update in a while, check to see if the circuit is still active if (mRegionp) { // The simulator will NOT send updates if the object continues normally on the path // predicted by the velocity and the acceleration (often gravity) sent to the viewer @@ -2252,14 +2531,14 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) if (cdp) { // Find out how many seconds since last packet arrived on the circuit - F64 time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime(); + F64Seconds time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime(); if (!cdp->isAlive() || // Circuit is dead or blocked cdp->isBlocked() || // or doesn't seem to be getting any packets (time_since_last_packet > sPhaseOutUpdateInterpolationTime)) { // Start to reduce motion interpolation since we haven't seen a server update in a while - F64 time_since_last_interpolation = time - mLastInterpUpdateSecs; + F64Seconds time_since_last_interpolation = time - mLastInterpUpdateSecs; F64 phase_out = 1.0; if (time_since_last_update > sMaxUpdateInterpolationTime) { // Past the time limit, so stop the object @@ -2272,13 +2551,13 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) } else if (mLastInterpUpdateSecs - mLastMessageUpdateSecs > sPhaseOutUpdateInterpolationTime) { // Last update was already phased out a bit - phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / + phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / (sMaxUpdateInterpolationTime - time_since_last_interpolation); //LL_INFOS() << "Continuing motion phase out of " << (F32) phase_out << LL_ENDL; } else { // Phase out from full value - phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / + phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / (sMaxUpdateInterpolationTime - sPhaseOutUpdateInterpolationTime); //LL_INFOS() << "Starting motion phase out of " << (F32) phase_out << LL_ENDL; } @@ -2304,7 +2583,7 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) min_height += (0.5f * getScale().mV[VZ]); } else - { // This will put the object underground, but we can't tell if it will stop + { // This will put the object underground, but we can't tell if it will stop // at ground level or not min_height = LLWorld::getInstance()->getMinAllowedZ(this, new_pos_global); } @@ -2324,11 +2603,11 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) LLVector3d clip_pos_global = LLWorld::getInstance()->clipToVisibleRegions(old_pos_global, new_pos_global); if (clip_pos_global != new_pos_global) { // Was clipped, so this means we hit a edge where there is no region to enter - + //LL_INFOS() << "Hit empty region edge, clipped predicted position to " << mRegionp->getPosRegionFromGlobal(clip_pos_global) // << " from " << new_pos << LL_ENDL; new_pos = mRegionp->getPosRegionFromGlobal(clip_pos_global); - + // Stop motion and get server update for bouncing on the edge new_v.clear(); setAcceleration(LLVector3::zero); @@ -2341,11 +2620,11 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) // Set new position and velocity setPositionRegion(new_pos); - setVelocity(new_v); - + setVelocity(new_v); + // for objects that are spinning but not translating, make sure to flag them as having moved setChanged(MOVED | SILHOUETTE); - } + } // Update the last time we did anything mLastInterpUpdateSecs = time; @@ -2579,12 +2858,22 @@ void LLViewerObject::removeInventoryListener(LLVOInventoryListener* listener) } } +BOOL LLViewerObject::isInventoryPending() +{ + return mInvRequestState != INVENTORY_REQUEST_STOPPED; +} + void LLViewerObject::clearInventoryListeners() { for_each(mInventoryCallbacks.begin(), mInventoryCallbacks.end(), DeletePointer()); mInventoryCallbacks.clear(); } +bool LLViewerObject::hasInventoryListeners() +{ + return !mInventoryCallbacks.empty(); +} + void LLViewerObject::requestInventory() { if(mInventoryDirty && mInventory && !mInventoryCallbacks.empty()) @@ -2592,26 +2881,29 @@ void LLViewerObject::requestInventory() mInventory->clear(); // will deref and delete entries delete mInventory; mInventory = NULL; - mInventoryDirty = FALSE; //since we are going to request it now } + if(mInventory) { + // inventory is either up to date or doesn't has a listener + // if it is dirty, leave it this way in case we gain a listener doInventoryCallback(); } - // throw away duplicate requests else { + // since we are going to request it now + mInventoryDirty = FALSE; + + // Note: throws away duplicate requests fetchInventoryFromServer(); } } void LLViewerObject::fetchInventoryFromServer() { - if (!mInventoryPending) + if (!isInventoryPending()) { delete mInventory; - mInventory = NULL; - mInventoryDirty = FALSE; LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_RequestTaskInventory); msg->nextBlockFast(_PREHASH_AgentData); @@ -2622,14 +2914,248 @@ void LLViewerObject::fetchInventoryFromServer() msg->sendReliable(mRegionp->getHost()); // this will get reset by dirtyInventory or doInventoryCallback - mInventoryPending = TRUE; + mInvRequestState = INVENTORY_REQUEST_PENDING; + } +} + +LLControlAvatar *LLViewerObject::getControlAvatar() +{ + return getRootEdit()->mControlAvatar.get(); +} + +LLControlAvatar *LLViewerObject::getControlAvatar() const +{ + return getRootEdit()->mControlAvatar.get(); +} + +// Manage the control avatar state of a given object. +// Any object can be flagged as animated, but for performance reasons +// we don't want to incur the overhead of managing a control avatar +// unless this would have some user-visible consequence. That is, +// there should be at least one rigged mesh in the linkset. Operations +// that change the state of a linkset, such as linking or unlinking +// prims, can also mean that a control avatar needs to be added or +// removed. At the end, if there is a control avatar, we make sure +// that its animation state is current. +void LLViewerObject::updateControlAvatar() +{ + LLViewerObject *root = getRootEdit(); + bool is_animated_object = root->isAnimatedObject(); + bool has_control_avatar = getControlAvatar(); + if (!is_animated_object && !has_control_avatar) + { + return; + } + + bool should_have_control_avatar = false; + if (is_animated_object) + { + bool any_rigged_mesh = root->isRiggedMesh(); + LLViewerObject::const_child_list_t& child_list = root->getChildren(); + for (const auto& iter : child_list) + { + const LLViewerObject* child = iter; + any_rigged_mesh = any_rigged_mesh || child->isRiggedMesh(); + } + should_have_control_avatar = is_animated_object && any_rigged_mesh; + } + + if (should_have_control_avatar && !has_control_avatar) + { + std::string vobj_name = llformat("Vol%p", root); + LL_DEBUGS("AnimatedObjects") << vobj_name << " calling linkControlAvatar()" << LL_ENDL; + root->linkControlAvatar(); + } + if (!should_have_control_avatar && has_control_avatar) + { + std::string vobj_name = llformat("Vol%p", root); + LL_DEBUGS("AnimatedObjects") << vobj_name << " calling unlinkControlAvatar()" << LL_ENDL; + root->unlinkControlAvatar(); + } + if (getControlAvatar()) + { + getControlAvatar()->updateAnimations(); + if (isSelected()) + { + LLSelectMgr::getInstance()->pauseAssociatedAvatars(); + } } } +void LLViewerObject::print() +{ + if (!mChildList.size()) + return; + LL_INFOS() << "==============" << LL_ENDL; + LL_INFOS() << mID << LL_ENDL; + LL_INFOS() << "isAvatar() " << isAvatar() << LL_ENDL; + LL_INFOS() << " mOwnerID " << mOwnerID << LL_ENDL; + LL_INFOS() << " mRegionp " << std::hex << mRegionp << std::dec << LL_ENDL; + if (mRegionp) + { + LL_INFOS() << " getName() " << mRegionp->getName() << LL_ENDL; + LL_INFOS() << " isAlive() " << mRegionp->isAlive() << LL_ENDL; + } + LL_INFOS() << " mDead " << mDead << LL_ENDL; + LL_INFOS() << " mDrawable " << std::hex << mDrawable.get() << std::dec << LL_ENDL; + if (mDrawable) + { + LL_INFOS() << " isVisible() " << mDrawable->isVisible() << LL_ENDL; + LL_INFOS() << " getRegion() " << std::hex << mDrawable->getRegion() << std::dec << LL_ENDL; + if (mDrawable->getRegion()) + { + LL_INFOS() << " getRegion() " << mDrawable->getRegion()->getName() << LL_ENDL; + } + LL_INFOS() << " isRoot() " << mDrawable->isRoot() << LL_ENDL; + LL_INFOS() << " isDead() " << mDrawable->isDead() << LL_ENDL; + LL_INFOS() << " isNew() " << mDrawable->isNew() << LL_ENDL; + LL_INFOS() << " isUnload() " << mDrawable->isUnload() << LL_ENDL; + LL_INFOS() << " isLight() " << mDrawable->isLight() << LL_ENDL; + LL_INFOS() << " getSpatialGroup() " << mDrawable->getSpatialGroup() << LL_ENDL; + } + LL_INFOS() << " mOrphaned " << mOrphaned << LL_ENDL; + LL_INFOS() << " isAttachment() " << isAttachment() << LL_ENDL; + LL_INFOS() << " isActive() " << isActive() << LL_ENDL; + LL_INFOS() << " isRiggedMesh() " << isRiggedMesh() << LL_ENDL; + LL_INFOS() << " isHUDAttachment() " << isHUDAttachment() << LL_ENDL; + LL_INFOS() << " isMesh() " << isRiggedMesh() << LL_ENDL; + LL_INFOS() << " isParticleSource() " << isRiggedMesh() << LL_ENDL; + LL_INFOS() << " isTempAttachment() " << isTempAttachment() << LL_ENDL; + LL_INFOS() << " getVObjRadius() " << getVObjRadius() << LL_ENDL; + LL_INFOS() << " getNumVertices() " << getNumVertices() << LL_ENDL; + LL_INFOS() << " getNumIndices() " << getNumIndices() << LL_ENDL; + LL_INFOS() << " isAnySelected() " << isAnySelected() << LL_ENDL; + LL_INFOS() << " isFlexible() " << isFlexible() << LL_ENDL; + LL_INFOS() << " isSculpted() " << isSculpted() << LL_ENDL; + LL_INFOS() << " mTotalCRC " << mTotalCRC << LL_ENDL; + LL_INFOS() << " mListIndex " << mListIndex << LL_ENDL; + //LL_INFOS() << " mTEImages " << mTEImages << LL_ENDL; + //LL_INFOS() << " mTENormalMaps " << mTENormalMaps << LL_ENDL; + //LL_INFOS() << " mTESpecularMaps " << mTESpecularMaps << LL_ENDL; + LL_INFOS() << " mGLName " << mGLName << LL_ENDL; + LL_INFOS() << " mbCanSelect " << mbCanSelect << LL_ENDL; + LL_INFOS() << " mFlags" << mFlags << LL_ENDL; + //LL_INFOS() << " mPhysicsShapeType " << mPhysicsShapeType << LL_ENDL; + //LL_INFOS() << " mPhysicsGravity " << mPhysicsGravity << LL_ENDL; + //LL_INFOS() << " mPhysicsFriction " << mPhysicsFriction << LL_ENDL; + //LL_INFOS() << " mPhysicsDensity " << mPhysicsDensity << LL_ENDL; + //LL_INFOS() << " mPhysicsRestitution " << mPhysicsRestitution << LL_ENDL; + //LL_INFOS() << " mCreateSelected " << mCreateSelected << LL_ENDL; + //LL_INFOS() << " mRenderMedia " << mRenderMedia << LL_ENDL; + //LL_INFOS() << " mBestUpdatePrecision " << mBestUpdatePrecision << LL_ENDL; + //LL_INFOS() << " mText" << std::hex << mText.get() << std::dec << LL_ENDL; + //LL_INFOS() << " mHudTextString " << mHudTextString << LL_ENDL; + //LL_INFOS() << " mHudTextColor " << mHudTextColor << LL_ENDL; + //LL_INFOS() << " mIcon" << std::hex << mIcon.get() << std::dec << LL_ENDL; + LL_INFOS() << " mIsNameAttachment " << mIsNameAttachment << LL_ENDL; + LL_INFOS() << " mControlAvatar " << std::hex << mControlAvatar.get() << std::dec << LL_ENDL; + LL_INFOS() << " mChildList.size() " << mChildList.size() << LL_ENDL; + LL_INFOS() << " mLastInterpUpdateSecs " << mLastInterpUpdateSecs << LL_ENDL; + LL_INFOS() << " mLastMessageUpdateSecs " << mLastMessageUpdateSecs << LL_ENDL; + LL_INFOS() << " mLatestRecvPacketID " << mLatestRecvPacketID << LL_ENDL; + //LL_INFOS() << " mData" << std::hex << mData << std::dec << LL_ENDL; + //LL_INFOS() << " mPartSourcep " << std::hex << mPartSourcep.get() << std::dec << LL_ENDL; + //LL_INFOS() << " mAudioSourcep " << std::hex << mAudioSourcep << std::dec << LL_ENDL; + //LL_INFOS() << " mAudioGain " << mAudioGain << LL_ENDL; + LL_INFOS() << " mAppAngle " << mAppAngle << LL_ENDL; + LL_INFOS() << " mPixelArea " << mPixelArea << LL_ENDL; + LL_INFOS() << " mInventory " << mInventory << LL_ENDL; + LL_INFOS() << " mInventorySerialNum " << mInventorySerialNum << LL_ENDL; + LL_INFOS() << " mInvRequestState " << mInvRequestState << LL_ENDL; + LL_INFOS() << " mInvRequestXFerId " << mInvRequestXFerId << LL_ENDL; + LL_INFOS() << " mInventoryDirty " << mInventoryDirty << LL_ENDL; + LL_INFOS() << " mUserSelected " << mUserSelected << LL_ENDL; + LL_INFOS() << " mOnActiveList " << mOnActiveList << LL_ENDL; + LL_INFOS() << " mOnMap" << mOnMap << LL_ENDL; + LL_INFOS() << " mStatic " << mStatic << LL_ENDL; + LL_INFOS() << " mNumFaces " << mNumFaces << LL_ENDL; + LL_INFOS() << " mRotTime " << mRotTime << LL_ENDL; + //LL_INFOS() << " mAngularVelocityRot " << mAngularVelocityRot << LL_ENDL; + //LL_INFOS() << " mPreviousRotation " << mPreviousRotation << LL_ENDL; + LL_INFOS() << " mAttachmentState " << mAttachmentState << LL_ENDL; + LL_INFOS() << " mClickAction " << mClickAction << LL_ENDL; + //LL_INFOS() << " mObjectCost " << mObjectCost << LL_ENDL; + //LL_INFOS() << " mLinksetCost " << mLinksetCost << LL_ENDL; + //LL_INFOS() << " mPhysicsCost " << mPhysicsCost << LL_ENDL; + //LL_INFOS() << " mLinksetPhysicsCost " << mLinksetPhysicsCost << LL_ENDL; + LL_INFOS() << " mCostStale " << mCostStale << LL_ENDL; + LL_INFOS() << " mPhysicsShapeUnknown " << mPhysicsShapeUnknown << LL_ENDL; + LL_INFOS() << " mPositionRegion " << mPositionRegion << LL_ENDL; + LL_INFOS() << " mPositionAgent " << mPositionAgent << LL_ENDL; + LL_INFOS() << " mAttachmentItemID " << mAttachmentItemID << LL_ENDL; + LL_INFOS() << " mLastUpdateType " << mLastUpdateType << LL_ENDL; + LL_INFOS() << " mLastUpdateCached " << mLastUpdateCached << LL_ENDL; + LL_INFOS() << "==============" << LL_ENDL; +} + +void LLViewerObject::linkControlAvatar() +{ + if (!getControlAvatar() && isRootEdit()) + { + LLVOVolume *volp = asVolume(); + if (!volp) + { + LL_WARNS() << "called with null or non-volume object" << LL_ENDL; + return; + } + mControlAvatar = LLControlAvatar::createControlAvatar(volp); + LL_DEBUGS("AnimatedObjects") << volp->getID() + << " created control av for " + << (S32) (1+volp->numChildren()) << " prims" << LL_ENDL; + } + LLControlAvatar *cav = getControlAvatar(); + if (cav) + { + cav->updateAttachmentOverrides(); + if (!cav->mPlaying) + { + cav->mPlaying = true; + //if (!cav->mRootVolp->isAnySelected()) + { + cav->updateVolumeGeom(); + cav->mRootVolp->recursiveMarkForUpdate(TRUE); + } + } + } + else + { + LL_WARNS() << "no control avatar found!" << LL_ENDL; + } +} + +void LLViewerObject::unlinkControlAvatar() +{ + if (getControlAvatar()) + { + getControlAvatar()->updateAttachmentOverrides(); + } + if (isRootEdit()) + { + // This will remove the entire linkset from the control avatar + if (mControlAvatar) + { + mControlAvatar->markForDeath(); + mControlAvatar->mRootVolp = NULL; + mControlAvatar = NULL; + } + } + // For non-root prims, removing from the linkset will + // automatically remove the control avatar connection. +} + +// virtual +bool LLViewerObject::isAnimatedObject() const +{ + return false; +} + struct LLFilenameAndTask { LLUUID mTaskID; std::string mFilename; + + // for sequencing in case of multiple updates + S16 mSerial; #ifdef _DEBUG static S32 sCount; LLFilenameAndTask() @@ -2665,14 +3191,22 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) return; } - msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum); LLFilenameAndTask* ft = new LLFilenameAndTask; ft->mTaskID = task_id; + // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update + msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial); + + if (ft->mSerial < object->mInventorySerialNum) + { + // viewer did some changes to inventory that were not saved yet. + LL_DEBUGS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client serial: " << object->mInventorySerialNum << LL_ENDL; + object->mInventorySerialNum = ft->mSerial; + } std::string unclean_filename; msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename); ft->mFilename = LLDir::getScrubbedFileName(unclean_filename); - + if(ft->mFilename.empty()) { LL_DEBUGS() << "Task has no inventory" << LL_ENDL; @@ -2694,22 +3228,40 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) delete ft; return; } - gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename), + U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename), ft->mFilename, LL_PATH_CACHE, object->mRegionp->getHost(), TRUE, &LLViewerObject::processTaskInvFile, (void**)ft, LLXferManager::HIGH_PRIORITY); + if (object->mInvRequestState == INVENTORY_XFER) + { + if (new_id > 0 && new_id != object->mInvRequestXFerId) + { + // we started new download. + gXferManager->abortRequestById(object->mInvRequestXFerId, -1); + object->mInvRequestXFerId = new_id; + } + } + else + { + object->mInvRequestState = INVENTORY_XFER; + object->mInvRequestXFerId = new_id; + } } void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status) { LLFilenameAndTask* ft = (LLFilenameAndTask*)user_data; LLViewerObject* object = NULL; - if(ft && (0 == error_code) && - (object = gObjectList.findObject(ft->mTaskID))) + + if (ft + && (0 == error_code) + && (object = gObjectList.findObject(ft->mTaskID)) + && ft->mSerial >= object->mInventorySerialNum) { + object->mInventorySerialNum = ft->mSerial; if (object->loadTaskInvFile(ft->mFilename)) { @@ -2717,12 +3269,12 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS LLInventoryObject::object_list_t::iterator end = object->mInventory->end(); std::list& pending_lst = object->mPendingInventoryItemsIDs; - for (; it != end && pending_lst.size(); ++it) + for (; it != end && !pending_lst.empty(); ++it) { LLViewerInventoryItem* item = dynamic_cast(it->get()); if(item && item->getType() != LLAssetType::AT_CATEGORY) { - std::list::iterator id_it = std::find(pending_lst.begin(), pending_lst.begin(), item->getAssetUUID()); + std::list::iterator id_it = std::find(pending_lst.begin(), pending_lst.end(), item->getAssetUUID()); if (id_it != pending_lst.end()) { pending_lst.erase(id_it); @@ -2740,7 +3292,7 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS } else { - // This Occurs When to requests were made, and the first one + // This Occurs When two requests were made, and the first one // has already handled it. LL_DEBUGS() << "Problem loading task inventory. Return code: " << error_code << LL_ENDL; @@ -2751,9 +3303,10 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS BOOL LLViewerObject::loadTaskInvFile(const std::string& filename) { std::string filename_and_local_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, filename); - llifstream ifs(filename_and_local_path); + llifstream ifs(filename_and_local_path.c_str()); if(ifs.good()) { + U32 fail_count = 0; char buffer[MAX_STRING]; /* Flawfinder: ignore */ // *NOTE: This buffer size is hard coded into scanf() below. char keyword[MAX_STRING]; /* Flawfinder: ignore */ @@ -2768,8 +3321,14 @@ BOOL LLViewerObject::loadTaskInvFile(const std::string& filename) while(ifs.good()) { ifs.getline(buffer, MAX_STRING); - if (sscanf(buffer, " %254s", keyword) < 1) continue; - if(0 == strcmp("inv_item", keyword)) + if (sscanf(buffer, " %254s", keyword) == EOF) /* Flawfinder: ignore */ + { + // Blank file? + LL_WARNS() << "Issue reading from file '" + << filename << "'" << LL_ENDL; + break; + } + else if(0 == strcmp("inv_item", keyword)) { LLPointer inv = new LLViewerInventoryItem; inv->importLegacyStream(ifs); @@ -2782,9 +3341,17 @@ BOOL LLViewerObject::loadTaskInvFile(const std::string& filename) inv->rename("Contents"); mInventory->push_front(inv); } + else if (fail_count >= MAX_INV_FILE_READ_FAILS) + { + LL_WARNS() << "Encountered too many unknowns while reading from file: '" + << filename << "'" << LL_ENDL; + break; + } else { - LL_WARNS() << "Unknown token in inventory file '" + // Is there really a point to continue processing? We already failing to display full inventory + fail_count++; + LL_WARNS_ONCE() << "Unknown token while reading from inventory file. Token: '" << keyword << "'" << LL_ENDL; } } @@ -2823,7 +3390,10 @@ void LLViewerObject::doInventoryCallback() mInventoryCallbacks.erase(curiter); } } - mInventoryPending = FALSE; + + // release inventory loading state + mInvRequestXFerId = 0; + mInvRequestState = INVENTORY_REQUEST_STOPPED; } void LLViewerObject::removeInventory(const LLUUID& item_id) @@ -2842,11 +3412,6 @@ void LLViewerObject::removeInventory(const LLUUID& item_id) msg->sendReliable(mRegionp->getHost()); deleteInventoryItem(item_id); ++mInventorySerialNum; - - // The viewer object should not refresh UI since this is a utility - // function. The UI functionality that called this method should - // refresh the views if necessary. - //gBuildView->refresh(); } bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item) @@ -2938,7 +3503,7 @@ LLInventoryObject* LLViewerObject::getInventoryObject(const LLUUID& item_id) rv = *it; break; } - } + } } return rv; } @@ -2961,7 +3526,7 @@ void LLViewerObject::getInventoryContents(LLInventoryObject::object_list_t& obje LLInventoryObject* LLViewerObject::getInventoryRoot() { - if (!mInventory || !mInventory->size()) + if (!mInventory || mInventory->empty()) { return NULL; } @@ -2993,7 +3558,7 @@ LLViewerInventoryItem* LLViewerObject::getInventoryItemByAsset(const LLUUID& ass break; } } - } + } } return rv; } @@ -3016,9 +3581,9 @@ void LLViewerObject::setPixelAreaAndAngle(LLAgent &agent) { //volumes calculate pixel area and angle per face return; } - - LLVector3 viewer_pos_agent = gAgentCamera.getCameraPositionAgent(); - LLVector3 pos_agent = getRenderPosition(); + + const LLVector3& viewer_pos_agent = gAgentCamera.getCameraPositionAgent(); + const LLVector3& pos_agent = getRenderPosition(); F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX]; F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY]; @@ -3032,7 +3597,7 @@ void LLViewerObject::setPixelAreaAndAngle(LLAgent &agent) // to try to get a min distance from face, subtract min_scale/2 from the range. // This means we'll load too much detail sometimes, but that's better than not enough // I don't think there's a better way to do this without calculating distance per-poly - F32 range = sqrt(dx*dx + dy*dy + dz*dz) - min_scale/2; + F32 range = sqrt(dx*dx + dy*dy + dz*dz) - min_scale/2.f; LLViewerCamera* camera = LLViewerCamera::getInstance(); if (range < 0.001f || isHUDAttachment()) // range == zero @@ -3072,7 +3637,7 @@ void LLViewerObject::updateGL() void LLViewerObject::updateFaceSize(S32 idx) { - + } LLDrawable* LLViewerObject::createDrawable(LLPipeline *pipeline) @@ -3085,7 +3650,7 @@ void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped) LLPrimitive::setScale(scale); if (mDrawable.notNull()) { - //encompass completely sheared objects by taking + //encompass completely sheared objects by taking //the most extreme point possible (<1,1,0.5>) mDrawable->setRadius(LLVector3(1,1,0.5f).scaleVec(scale).magVec()); updateDrawable(damped); @@ -3129,8 +3694,17 @@ void LLViewerObject::setLinksetCost(F32 cost) { mLinksetCost = cost; mCostStale = false; - - if (isSelected()) + + BOOL needs_refresh = isSelected(); + child_list_t::iterator iter = mChildList.begin(); + while(iter != mChildList.end() && !needs_refresh) + { + LLViewerObject* child = *iter; + needs_refresh = child->isSelected(); + iter++; + } + + if (needs_refresh) { gFloaterTools->dirty(); } @@ -3151,7 +3725,7 @@ void LLViewerObject::setLinksetPhysicsCost(F32 cost) { mLinksetPhysicsCost = cost; mCostStale = false; - + if (isSelected()) { gFloaterTools->dirty(); @@ -3165,7 +3739,7 @@ F32 LLViewerObject::getObjectCost() { gObjectList.updateObjectCost(this); } - + return mObjectCost; } @@ -3185,7 +3759,7 @@ F32 LLViewerObject::getPhysicsCost() { gObjectList.updateObjectCost(this); } - + return mPhysicsCost; } @@ -3199,11 +3773,65 @@ F32 LLViewerObject::getLinksetPhysicsCost() return mLinksetPhysicsCost; } -F32 LLViewerObject::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_value) const +F32 LLViewerObject::recursiveGetEstTrianglesMax() const +{ + F32 est_tris = getEstTrianglesMax(); + for (const auto& iter : mChildList) + { + const LLViewerObject* child = iter; + if (!child->isAvatar()) + { + est_tris += child->recursiveGetEstTrianglesMax(); + } + } + return est_tris; +} + +S32 LLViewerObject::getAnimatedObjectMaxTris() const +{ + S32 max_tris = 0; + if (gSavedSettings.getBOOL("AnimatedObjectsIgnoreLimits")) + { + max_tris = S32_MAX; + } + else + { + if (gAgent.getRegion()) + { + LLSD features; + gAgent.getRegion()->getSimulatorFeatures(features); + if (features.has("AnimatedObjects")) + { + max_tris = features["AnimatedObjects"]["AnimatedObjectMaxTris"].asInteger(); + } + } + } + return max_tris; +} + +F32 LLViewerObject::getEstTrianglesMax() const +{ + return 0.f; +} + +F32 LLViewerObject::getEstTrianglesStreamingCost() const { return 0.f; } +// virtual +F32 LLViewerObject::getStreamingCost() const +{ + return 0.f; +} + +// virtual +bool LLViewerObject::getCostData(LLMeshCostData& costs) const +{ + costs = LLMeshCostData(); + return false; +} + U32 LLViewerObject::getTriangleCount(S32* vcount) const { return 0; @@ -3214,6 +3842,55 @@ U32 LLViewerObject::getHighLODTriangleCount() return 0; } +U32 LLViewerObject::recursiveGetTriangleCount(S32* vcount) const +{ + S32 total_tris = getTriangleCount(vcount); + LLViewerObject::const_child_list_t& child_list = getChildren(); + for (const auto& iter : child_list) + { + LLViewerObject* childp = iter; + if (childp) + { + total_tris += childp->getTriangleCount(vcount); + } + } + return total_tris; +} + +// This is using the stored surface area for each volume (which +// defaults to 1.0 for the case of everything except a sculpt) and +// then scaling it linearly based on the largest dimension in the +// prim's scale. Should revisit at some point. +F32 LLViewerObject::recursiveGetScaledSurfaceArea() const +{ + F32 area = 0.f; + const LLDrawable* drawable = mDrawable; + if (drawable) + { + const LLVOVolume* volume = drawable->getVOVolume(); + if (volume) + { + if (volume->getVolume()) + { + const LLVector3& scale = volume->getScale(); + area += volume->getVolume()->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); + } + LLViewerObject::const_child_list_t const& children = volume->getChildren(); + for (const auto& child_iter : children) + { + LLViewerObject* child_obj = child_iter; + LLVOVolume *child = child_obj ? child_obj->asVolume() : nullptr; + if (child && child->getVolume()) + { + const LLVector3& scale = child->getScale(); + area += child->getVolume()->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); + } + } + } + } + return area; +} + void LLViewerObject::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) { if(mDrawable.isNull()) @@ -3224,7 +3901,7 @@ void LLViewerObject::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax size.load3(getScale().mV); newMin.setSub(center, size); newMax.setAdd(center, size); - + mDrawable->setPositionGroup(center); } @@ -3237,7 +3914,7 @@ F32 LLViewerObject::getBinRadius() diff.setSub(ext[1], ext[0]); return diff.getLength3().getF32(); } - + return getScale().magVec(); } @@ -3298,16 +3975,16 @@ void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */) S32 tex_count = getNumTEs(); for (i = 0; i < tex_count; i++) { - getTEImage(i)->setBoostLevel(LLGLTexture::BOOST_SELECTED); + getTEImage(i)->setBoostLevel(LLGLTexture::BOOST_SELECTED); } if (isSculpted() && !isMesh()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = getSculptParams(); LLUUID sculpt_id = sculpt_params->getSculptTexture(); - LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLGLTexture::BOOST_SELECTED); + LLViewerTextureManager::getFetchedTexture(sculpt_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLGLTexture::BOOST_SELECTED); } - + if (boost_children) { for (child_list_t::iterator iter = mChildList.begin(); @@ -3416,7 +4093,7 @@ BOOL LLViewerObject::removeNVPair(const std::string& name) gMessageSystem->newMessageFast(_PREHASH_RemoveNameValuePair); gMessageSystem->nextBlockFast(_PREHASH_TaskData); gMessageSystem->addUUIDFast(_PREHASH_ID, mID); - + gMessageSystem->nextBlockFast(_PREHASH_NameValueData); gMessageSystem->addStringFast(_PREHASH_NVPair, buffer); @@ -3474,7 +4151,7 @@ void LLViewerObject::updatePositionCaches() const } const LLVector3d LLViewerObject::getPositionGlobal() const -{ +{ // If region is removed from the list it is also deleted. if(mRegionp && LLWorld::instance().isRegionListed(mRegionp)) { @@ -3483,14 +4160,14 @@ const LLVector3d LLViewerObject::getPositionGlobal() const if (isAttachment()) { position_global = gAgent.getPosGlobalFromAgent(getRenderPosition()); - } + } return position_global; } else { LLVector3d position_global(getPosition()); return position_global; - } + } } const LLVector3 &LLViewerObject::getPositionAgent() const @@ -3546,8 +4223,20 @@ const LLVector3 LLViewerObject::getRenderPosition() const { if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED)) { + LLControlAvatar *cav = getControlAvatar(); + if (isRoot() && cav) + { + F32 fixup; + if ( cav->hasPelvisFixup( fixup) ) + { + //Apply a pelvis fixup (as defined by the avs skin) + LLVector3 pos = mDrawable->getPositionAgent(); + pos[VZ] += fixup; + return pos; + } + } LLVOAvatar* avatar = getAvatar(); - if (avatar) + if ((avatar) && !getControlAvatar()) { return avatar->getPositionAgent(); } @@ -3571,11 +4260,11 @@ const LLVector3 LLViewerObject::getPivotPositionAgent() const const LLQuaternion LLViewerObject::getRenderRotation() const { LLQuaternion ret; - if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED)) + if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED) && !isAnimatedObject()) { return ret; } - + if (mDrawable.isNull() || mDrawable->isStatic()) { ret = getRotationEdit(); @@ -3591,7 +4280,7 @@ const LLQuaternion LLViewerObject::getRenderRotation() const ret = LLQuaternion(LLMatrix4(mDrawable->getWorldMatrix().getF32ptr())); } } - + return ret; } @@ -3638,7 +4327,7 @@ void LLViewerObject::setPositionAbsoluteGlobal( const LLVector3d &pos_global, BO new_pos = new_pos * ~parentp->getRotationRegion(); } LLViewerObject::setPosition(new_pos); - + if (mParent && ((LLViewerObject*)mParent)->isAvatar()) { // we have changed the position of an attachment, so we need to clamp it @@ -3675,7 +4364,7 @@ void LLViewerObject::setPosition(const LLVector3 &pos, BOOL damped) { setChanged(TRANSLATED | SILHOUETTE); } - + LLXform::setPosition(pos); updateDrawable(damped); if (isRoot()) @@ -3709,7 +4398,7 @@ void LLViewerObject::setPositionGlobal(const LLVector3d &pos_global, BOOL damped LLQuaternion invRotation = mDrawable->getRotation(); invRotation.transQuat(); - + delta_pos = delta_pos * invRotation; // *FIX: is this right? Shouldn't we be calling the @@ -3780,7 +4469,7 @@ void LLViewerObject::setPositionAgent(const LLVector3 &pos_agent, BOOL damped) setPositionRegion(pos_region, damped); } -// identical to setPositionRegion() except it checks for child-joints +// identical to setPositionRegion() except it checks for child-joints // and doesn't also move the joint-parent // TODO -- implement similar intelligence for joint-parents toward // their joint-children @@ -3799,14 +4488,14 @@ void LLViewerObject::setPositionEdit(const LLVector3 &pos_edit, BOOL damped) LLViewerObject::setPosition(pos_edit, damped); mPositionRegion = pos_edit; mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); - } + } } LLViewerObject* LLViewerObject::getRootEdit() const { const LLViewerObject* root = this; - while (root->mParent + while (root->mParent && !((LLViewerObject*)root->mParent)->isAvatar()) { root = (LLViewerObject*)root->mParent; @@ -3818,6 +4507,7 @@ LLViewerObject* LLViewerObject::getRootEdit() const BOOL LLViewerObject::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, + BOOL pick_rigged, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, @@ -3943,10 +4633,10 @@ void LLViewerObject::setNumTEs(const U8 num_tes) { LLPointer *new_images; new_images = new LLPointer[num_tes]; - + LLPointer *new_normmaps; new_normmaps = new LLPointer[num_tes]; - + LLPointer *new_specmaps; new_specmaps = new LLPointer[num_tes]; for (i = 0; i < num_tes; i++) @@ -3972,7 +4662,7 @@ void LLViewerObject::setNumTEs(const U8 num_tes) } deleteTEImages(); - + mTEImages = new_images; mTENormalMaps = new_normmaps; mTESpecularMaps = new_specmaps; @@ -4067,20 +4757,97 @@ void LLViewerObject::sendTEUpdate() const msg->sendReliable( regionp->getHost() ); } +LLViewerTexture* LLViewerObject::getBakedTextureForMagicId(const LLUUID& id) +{ + if (!LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id)) + { + return NULL; + } + + LLViewerObject *root = getRootEdit(); + if (root && root->isAnimatedObject()) + { + return LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } + + LLVOAvatar* avatar = getAvatar(); + if (avatar) + { + LLAvatarAppearanceDefines::EBakedTextureIndex texIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::assetIdToBakedTextureIndex(id); + LLViewerTexture* bakedTexture = avatar->getBakedTexture(texIndex); + if (bakedTexture == NULL || bakedTexture->isMissingAsset()) + { + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } + else + { + return bakedTexture; + } + } + else + { + return LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } + +} + +void LLViewerObject::updateAvatarMeshVisibility(const LLUUID& id, const LLUUID& old_id) +{ + if (id == old_id) + { + return; + } + + if (!LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(old_id) && !LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id)) + { + return; + } + + LLVOAvatar* avatar = getAvatar(); + if (avatar) + { + avatar->updateMeshVisibility(); + } +} + void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) { + LLUUID old_image_id; + if (getTE(te)) + { + old_image_id = getTE(te)->getID(); + } + LLPrimitive::setTE(te, texture_entry); const LLUUID& image_id = getTE(te)->getID(); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - + LLViewerTexture* bakedTexture = getBakedTextureForMagicId(image_id); + mTEImages[te] = bakedTexture ? bakedTexture : LLViewerTextureManager::getFetchedTexture(image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + + + updateAvatarMeshVisibility(image_id,old_image_id); + if (getTE(te)->getMaterialParams().notNull()) { const LLUUID& norm_id = getTE(te)->getMaterialParams()->getNormalID(); - mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(norm_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - + mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(norm_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE); + const LLUUID& spec_id = getTE(te)->getMaterialParams()->getSpecularID(); - mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE); + } +} + +void LLViewerObject::refreshBakeTexture() +{ + for (int face_index = 0; face_index < getNumTEs(); face_index++) + { + LLTextureEntry* tex_entry = getTE(face_index); + if (tex_entry && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(tex_entry->getID())) + { + const LLUUID& image_id = tex_entry->getID(); + LLViewerTexture* bakedTexture = getBakedTextureForMagicId(image_id); + changeTEImage(face_index, bakedTexture); + } } } @@ -4088,8 +4855,13 @@ void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) { if (mTEImages[te] != imagep) { - mTEImages[te] = imagep; + LLUUID old_image_id = getTE(te) ? getTE(te)->getID() : LLUUID::null; + LLPrimitive::setTETexture(te, imagep->getID()); + + LLViewerTexture* baked_texture = getBakedTextureForMagicId(imagep->getID()); + mTEImages[te] = baked_texture ? baked_texture : imagep; + updateAvatarMeshVisibility(imagep->getID(), old_image_id); setChanged(TEXTURE); if (mDrawable.notNull()) { @@ -4100,13 +4872,18 @@ void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image) { + if (!image) + return 0; + LLUUID old_image_id = getTE(te)->getID(); const LLUUID& uuid = image->getID(); S32 retval = 0; if (uuid != getTE(te)->getID() || uuid == LLUUID::null) { retval = LLPrimitive::setTETexture(te, uuid); - mTEImages[te] = image; + LLViewerTexture* baked_texture = getBakedTextureForMagicId(uuid); + mTEImages[te] = baked_texture ? baked_texture : image; + updateAvatarMeshVisibility(uuid,old_image_id); setChanged(TEXTURE); if (mDrawable.notNull()) { @@ -4135,7 +4912,7 @@ S32 LLViewerObject::setTENormalMapCore(const U8 te, LLViewerTexture *image) mat->setNormalID(uuid); } } - changeTENormalMap(te,image); + changeTENormalMap(te,image); return retval; } @@ -4156,14 +4933,14 @@ S32 LLViewerObject::setTESpecularMapCore(const U8 te, LLViewerTexture *image) if (mat) { mat->setSpecularID(uuid); - } + } } changeTESpecularMap(te, image); return retval; } //virtual -void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) +void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) { if(index < 0 || index >= getNumTEs()) { @@ -4195,21 +4972,21 @@ S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) { // Invalid host == get from the agent's sim LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture( - uuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); return setTETextureCore(te,image); } S32 LLViewerObject::setTENormalMap(const U8 te, const LLUUID& uuid) { LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( - uuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); return setTENormalMapCore(te, image); } S32 LLViewerObject::setTESpecularMap(const U8 te, const LLUUID& uuid) { LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( - uuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); return setTESpecularMapCore(te, image); } @@ -4408,7 +5185,7 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams); LL_DEBUGS("Material") << "Changing material params for te " << (S32)te << ", object " << mID - << " (" << retval << ")" + << " (" << retval << ")" << LL_ENDL; setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null); setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null); @@ -4553,7 +5330,7 @@ bool LLViewerObject::isImageAlphaBlended(const U8 te) const LLViewerTexture *LLViewerObject::getTENormalMap(const U8 face) const { // llassert(mTEImages); - + if (face < getNumTEs()) { LLViewerTexture* image = mTENormalMaps[face]; @@ -4566,16 +5343,16 @@ LLViewerTexture *LLViewerObject::getTENormalMap(const U8 face) const return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); } } - + LL_ERRS() << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << LL_ENDL; - + return NULL; } LLViewerTexture *LLViewerObject::getTESpecularMap(const U8 face) const { // llassert(mTEImages); - + if (face < getNumTEs()) { LLViewerTexture* image = mTESpecularMaps[face]; @@ -4588,9 +5365,9 @@ LLViewerTexture *LLViewerObject::getTESpecularMap(const U8 face) const return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); } } - + LL_ERRS() << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << LL_ENDL; - + return NULL; } @@ -4610,7 +5387,7 @@ LLBBox LLViewerObject::getBoundingBoxAgent() const { avatar_parent = (LLViewerObject*)root_edit->getParent(); } - + if (avatar_parent && avatar_parent->isAvatar() && root_edit && root_edit->mDrawable.notNull() && root_edit->mDrawable->getXform()->getParent()) { @@ -4623,7 +5400,7 @@ LLBBox LLViewerObject::getBoundingBoxAgent() const position_agent = getPositionAgent(); rot = getRotationRegion(); } - + return LLBBox( position_agent, rot, getScale() * -0.5f, getScale() * 0.5f ); } @@ -4708,12 +5485,7 @@ void LLViewerObject::setDebugText(const std::string &utf8text) if (!mText) { - mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT); - mText->setFont(LLFontGL::getFontSansSerif()); - mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP); - mText->setMaxLines(-1); - mText->setSourceObject(this); - mText->setOnHUDAttachment(isHUDAttachment()); + initHudText(); } mText->setColor(utf8text.empty() ? mHudTextColor : LLColor4::white ); mText->setString(utf8text.empty() ? mHudTextString : utf8text ); @@ -4721,6 +5493,16 @@ void LLViewerObject::setDebugText(const std::string &utf8text) mText->setDoFade(utf8text.empty()); updateText(); } +void LLViewerObject::initHudText() +{ + mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT); + mText->setFont(LLFontGL::getFontSansSerif()); + mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP); + mText->setMaxLines(-1); + mText->setSourceObject(this); + mText->setOnHUDAttachment(isHUDAttachment()); +} + // std::string LLViewerObject::getDebugText() { @@ -4754,8 +5536,8 @@ void LLViewerObject::clearIcon() } } -LLViewerObject* LLViewerObject::getSubParent() -{ +LLViewerObject* LLViewerObject::getSubParent() +{ return (LLViewerObject*) getParent(); } @@ -4775,10 +5557,16 @@ void LLViewerObject::updateText() if (!isDead()) { if (mText.notNull()) - { + { + //LLVOAvatar* avatar = getAvatar(); + //if (avatar) + //{ + // mText->setHidden(avatar->isInMuteList()); + //} + LLVector3 up_offset(0,0,0); up_offset.mV[2] = getScale().mV[VZ]*0.6f; - + if (mDrawable.notNull()) { mText->setPositionAgent(getRenderPosition() + up_offset); @@ -4796,6 +5584,34 @@ LLVOAvatar* LLViewerObject::asAvatar() return NULL; } +// virtual +LLVOVolume* LLViewerObject::asVolume() +{ + return nullptr; +} + +// If this object is directly or indirectly parented by an avatar, +// return it. Normally getAvatar() is the correct function to call; +// it will give the avatar used for skinning. The exception is with +// animated objects that are also attachments; in that case, +// getAvatar() will return the control avatar, used for skinning, and +// getAvatarAncestor will return the avatar to which the object is +// attached. +LLVOAvatar* LLViewerObject::getAvatarAncestor() +{ + LLViewerObject *pobj = (LLViewerObject*) getParent(); + while (pobj) + { + LLVOAvatar *av = pobj->asAvatar(); + if (av) + { + return av; + } + pobj = (LLViewerObject*) pobj->getParent(); + } + return NULL; +} + BOOL LLViewerObject::isParticleSource() const { return !mPartSourcep.isNull() && !mPartSourcep->isDead(); @@ -4810,7 +5626,7 @@ void LLViewerObject::setParticleSource(const LLPartSysData& particle_parameters, LLPointer pss = LLViewerPartSourceScript::createPSS(this, particle_parameters); mPartSourcep = pss; - + if (mPartSourcep) { mPartSourcep->setOwnerUUID(owner_id); @@ -4942,20 +5758,20 @@ void LLViewerObject::updateDrawable(BOOL force_damped) if (!isChanged(MOVED)) { //most common case, having an empty if case here makes for better branch prediction } - else if (mDrawable.notNull() && + else if (mDrawable.notNull() && !mDrawable->isState(LLDrawable::ON_MOVE_LIST)) { - BOOL damped_motion = + BOOL damped_motion = !isChanged(SHIFTED) && // not shifted between regions this frame and... ( force_damped || // ...forced into damped motion by application logic or... ( !isSelected() && // ...not selected and... ( mDrawable->isRoot() || // ... is root or ... (getParent() && !((LLViewerObject*)getParent())->isSelected())// ... parent is not selected and ... - ) && + ) && getPCode() == LL_PCODE_VOLUME && // ...is a volume object and... getVelocity().isExactlyZero() && // ...is not moving physically and... mDrawable->getGeneration() != -1 // ...was not created this frame. - ) + ) ); gPipeline.markMoved(mDrawable, damped_motion); } @@ -4974,7 +5790,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow { return; } - + if (audio_uuid.isNull()) { if (!mAudioSourcep || (flags & LL_SOUND_FLAG_STOP && !mAudioSourcep->isLoop())) @@ -4992,7 +5808,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow mAudioSourcep = NULL; } else if (flags & LL_SOUND_FLAG_STOP) - { + { // Just shut off the sound mAudioSourcep->play(LLUUID::null); } @@ -5007,14 +5823,14 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow } // don't clean up before previous sound is done. Solves: SL-33486 - if ( mAudioSourcep && mAudioSourcep->isDone() ) + if ( mAudioSourcep && mAudioSourcep->isDone() ) { gAudiop->cleanupAudioSource(mAudioSourcep); mAudioSourcep = NULL; } if (mAudioSourcep && mAudioSourcep->isMuted() && - mAudioSourcep->getCurrentData() && mAudioSourcep->getCurrentData()->getID() == audio_uuid) + mAudioSourcep->getCurrentData() && mAudioSourcep->getCurrentData()->getID() == audio_uuid) { //LL_INFOS() << "Already having this sound as muted sound, ignoring" << LL_ENDL; return; @@ -5081,7 +5897,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; } @@ -5094,90 +5910,59 @@ bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp) LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 param_type) { LLNetworkData* new_block = NULL; + bool* in_use = NULL; switch (param_type) { - case LLNetworkData::PARAMS_FLEXIBLE: - { - new_block = new LLFlexibleObjectData(); - break; - } - case LLNetworkData::PARAMS_LIGHT: - { - new_block = new LLLightParams(); - break; - } - case LLNetworkData::PARAMS_SCULPT: - { - new_block = new LLSculptParams(); - break; - } - case LLNetworkData::PARAMS_LIGHT_IMAGE: - { - new_block = new LLLightImageParams(); - break; - } - default: - { - LL_INFOS() << "Unknown param type. (" << llformat("0x%2x",param_type) << ")" << LL_ENDL; - break; - } + case LLNetworkData::PARAMS_FLEXIBLE: + { + new_block = &mFlexibleObjectData; + in_use = &mFlexibleObjectDataInUse; + break; + } + case LLNetworkData::PARAMS_LIGHT: + { + new_block = &mLightParams; + in_use = &mLightParamsInUse; + break; + } + case LLNetworkData::PARAMS_SCULPT: + { + new_block = &mSculptParams; + in_use = &mSculptParamsInUse; + break; + } + case LLNetworkData::PARAMS_LIGHT_IMAGE: + { + new_block = &mLightImageParams; + in_use = &mLightImageParamsInUse; + break; + } + case LLNetworkData::PARAMS_EXTENDED_MESH: + { + new_block = &mExtendedMeshParams; + in_use = &mExtendedMeshParamsInUse; + break; + } + default: + { + LL_INFOS() << "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 - mExtraParameterList[param_type] = new_entry; - return new_entry; - } - return NULL; -} - -LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntry(U16 param_type) const -{ - std::map::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; - } - else - { - return NULL; - } -} - -BOOL LLViewerObject::getParameterEntryInUse(U16 param_type) const -{ - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) - { - return param->in_use; + entry.in_use = in_use; + *entry.in_use = false; // not in use yet + entry.data = new_block; + return &entry; } else { - return FALSE; + entry.is_invalid = true; } + return NULL; } bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin) @@ -5185,11 +5970,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; @@ -5205,22 +5990,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 != (bool)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); + } } } @@ -5295,25 +6086,45 @@ void LLViewerObject::clearDrawableState(U32 state, BOOL recursive) } } +BOOL LLViewerObject::isDrawableState(U32 state, BOOL recursive) const +{ + BOOL matches = FALSE; + if (mDrawable) + { + matches = mDrawable->isState(state); + } + if (recursive) + { + for (child_list_t::const_iterator iter = mChildList.begin(); + (iter != mChildList.end()) && matches; iter++) + { + LLViewerObject* child = *iter; + matches &= child->isDrawableState(state, recursive); + } + } + + return matches; +} + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// RN: these functions assume a 2-level hierarchy +// RN: these functions assume a 2-level hierarchy //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Owned by anyone? BOOL LLViewerObject::permAnyOwner() const -{ +{ if (isRootEdit()) { - return flagObjectAnyOwner(); + return flagObjectAnyOwner(); } else { return ((LLViewerObject*)getParent())->permAnyOwner(); } -} +} // Owned by this viewer? BOOL LLViewerObject::permYouOwner() const -{ +{ if (isRootEdit()) { #ifdef HACKED_GODLIKE_VIEWER @@ -5321,12 +6132,12 @@ BOOL LLViewerObject::permYouOwner() const #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER if (!LLViewerLogin::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) + && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) { return TRUE; } # endif - return flagObjectYouOwner(); + return flagObjectYouOwner(); #endif } else @@ -5336,11 +6147,11 @@ BOOL LLViewerObject::permYouOwner() const } // Owned by a group? -BOOL LLViewerObject::permGroupOwner() const -{ +BOOL LLViewerObject::permGroupOwner() const +{ if (isRootEdit()) { - return flagObjectGroupOwned(); + return flagObjectGroupOwned(); } else { @@ -5350,7 +6161,7 @@ BOOL LLViewerObject::permGroupOwner() const // Can the owner edit BOOL LLViewerObject::permOwnerModify() const -{ +{ if (isRootEdit()) { #ifdef HACKED_GODLIKE_VIEWER @@ -5358,12 +6169,12 @@ BOOL LLViewerObject::permOwnerModify() const #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER if (!LLViewerLogin::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) + && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) { return TRUE; } # endif - return flagObjectOwnerModify(); + return flagObjectOwnerModify(); #endif } else @@ -5374,7 +6185,7 @@ BOOL LLViewerObject::permOwnerModify() const // Can edit BOOL LLViewerObject::permModify() const -{ +{ if (isRootEdit()) { #ifdef HACKED_GODLIKE_VIEWER @@ -5382,12 +6193,12 @@ BOOL LLViewerObject::permModify() const #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER if (!LLViewerLogin::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) + && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) { return TRUE; } # endif - return flagObjectModify(); + return flagObjectModify(); #endif } else @@ -5398,7 +6209,7 @@ BOOL LLViewerObject::permModify() const // Can copy BOOL LLViewerObject::permCopy() const -{ +{ if (isRootEdit()) { #ifdef HACKED_GODLIKE_VIEWER @@ -5406,7 +6217,7 @@ BOOL LLViewerObject::permCopy() const #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER if (!LLViewerLogin::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) + && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) { return TRUE; } @@ -5430,12 +6241,12 @@ BOOL LLViewerObject::permMove() const #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER if (!LLViewerLogin::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) + && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) { return TRUE; } # endif - return flagObjectMove(); + return flagObjectMove(); #endif } else @@ -5446,7 +6257,7 @@ BOOL LLViewerObject::permMove() const // Can be transferred BOOL LLViewerObject::permTransfer() const -{ +{ if (isRootEdit()) { #ifdef HACKED_GODLIKE_VIEWER @@ -5454,12 +6265,12 @@ BOOL LLViewerObject::permTransfer() const #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER if (!LLViewerLogin::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) + && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) { return TRUE; } # endif - return flagObjectTransfer(); + return flagObjectTransfer(); #endif } else @@ -5496,6 +6307,17 @@ void LLViewerObject::updateVolume(const LLVolumeParams& volume_params) } } +void LLViewerObject::recursiveMarkForUpdate(BOOL priority) +{ + for (LLViewerObject::child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + child->markForUpdate(priority); + } + markForUpdate(priority); +} + void LLViewerObject::markForUpdate(BOOL priority) { if (mDrawable.notNull()) @@ -5505,6 +6327,15 @@ void LLViewerObject::markForUpdate(BOOL priority) } } + +void LLViewerObject::markForUnload(BOOL priority) +{ + if (mDrawable.notNull()) + { + gPipeline.markRebuild(mDrawable, LLDrawable::FOR_UNLOAD, priority); + } +} + bool LLViewerObject::isPermanentEnforced() const { return flagObjectPermanent() && (mRegionp != gAgent.getRegion()) && !gAgent.isGodlike(); @@ -5526,7 +6357,18 @@ void LLViewerObject::setRegion(LLViewerRegion *regionp) { LL_WARNS() << "viewer object set region to NULL" << LL_ENDL; } - + if(regionp != mRegionp) + { + if(mRegionp) + { + mRegionp->removeFromCreatedList(getLocalID()); + } + if(regionp) + { + regionp->addToCreatedList(getLocalID()); + } + } + mLatestRecvPacketID = 0; mRegionp = regionp; @@ -5536,10 +6378,29 @@ void LLViewerObject::setRegion(LLViewerRegion *regionp) child->setRegion(regionp); } + if (mControlAvatar) + { + mControlAvatar->setRegion(regionp); + } + setChanged(MOVED | SILHOUETTE); updateDrawable(FALSE); } +// virtual +void LLViewerObject::updateRegion(LLViewerRegion *regionp) +{ +// if (regionp) +// { +// F64 now = LLFrameTimer::getElapsedSeconds(); +// LL_INFOS() << "Updating to region " << regionp->getName() +// << ", ms since last update message: " << (F32)((now - mLastMessageUpdateSecs) * 1000.0) +// << ", ms since last interpolation: " << (F32)((now - mLastInterpUpdateSecs) * 1000.0) +// << LL_ENDL; +// } +} + + bool LLViewerObject::specialHoverCursor() const { return flagUsePhysics() @@ -5643,13 +6504,13 @@ void LLViewerObject::setPhysicsRestitution(F32 restitution) } U8 LLViewerObject::getPhysicsShapeType() const -{ +{ if (mPhysicsShapeUnknown) { gObjectList.updatePhysicsFlags(this); } - return mPhysicsShapeType; + return mPhysicsShapeType; } void LLViewerObject::applyAngularVelocity(F32 dt) @@ -5666,7 +6527,7 @@ void LLViewerObject::applyAngularVelocity(F32 dt) angle = omega * dt; ang_vel *= 1.f/omega; - + // calculate the delta increment based on the object's angular velocity dQ.setQuat(angle, ang_vel); @@ -5676,7 +6537,7 @@ void LLViewerObject::applyAngularVelocity(F32 dt) // accumulate the angular velocity rotations to re-apply in the case of an object update mAngularVelocityRot *= dQ; } - + // Just apply the delta increment to the current rotation setRotation(getRotation()*dQ); setChanged(MOVED | SILHOUETTE); @@ -5695,25 +6556,9 @@ void LLViewerObject::resetRot() } } -//virtual -void LLViewerObject::setSelected(BOOL sel) -{ - mUserSelected = sel; - - static const LLCachedControl use_new_target_omega ("UseNewTargetOmegaCode", true); - if(use_new_target_omega) - { - resetRot(); - } - else - { - mRotTime = 0.f; - } -} - U32 LLViewerObject::getPartitionType() const -{ - return LLViewerRegion::PARTITION_NONE; +{ + return LLViewerRegion::PARTITION_NONE; } void LLViewerObject::dirtySpatialGroup(BOOL priority) const @@ -5777,7 +6622,7 @@ void LLViewerObject::saveUnselectedChildrenPosition(std::vector& posi LLViewerObject* childp = *iter; if (!childp->isSelected() && childp->mDrawable.notNull()) { - positions.push_back(childp->getPositionEdit()); + positions.push_back(childp->getPositionEdit()); } } @@ -5797,15 +6642,15 @@ void LLViewerObject::saveUnselectedChildrenRotation(std::vector& r LLViewerObject* childp = *iter; if (!childp->isSelected() && childp->mDrawable.notNull()) { - rotations.push_back(childp->getRotationEdit()); - } + rotations.push_back(childp->getRotationEdit()); + } } return ; } //counter-rotation -void LLViewerObject::resetChildrenRotationAndPosition(const std::vector& rotations, +void LLViewerObject::resetChildrenRotationAndPosition(const std::vector& rotations, const std::vector& positions) { if(mChildList.empty()) @@ -5826,30 +6671,30 @@ void LLViewerObject::resetChildrenRotationAndPosition(const std::vectorsetRotation(rotations[index] * inv_rotation); childp->setPosition((positions[index] - offset) * inv_rotation); - LLManip::rebuild(childp); + LLManip::rebuild(childp); } else //avatar { LLVector3 reset_pos = (positions[index] - offset) * inv_rotation ; LLQuaternion reset_rot = rotations[index] * inv_rotation ; - ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos); + ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos); ((LLVOAvatar*)childp)->mDrawable->mXform.setRotation(reset_rot) ; - - ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos, TRUE); + + ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos, TRUE); ((LLVOAvatar*)childp)->mDrawable->getVObj()->setRotation(reset_rot, TRUE) ; - LLManip::rebuild(childp); - } + LLManip::rebuild(childp); + } index++; - } + } } return ; } //counter-translation -void LLViewerObject::resetChildrenPosition(const LLVector3& offset, BOOL simplified) +void LLViewerObject::resetChildrenPosition(const LLVector3& offset, BOOL simplified, BOOL skip_avatar_child) { if(mChildList.empty()) { @@ -5888,20 +6733,22 @@ void LLViewerObject::resetChildrenPosition(const LLVector3& offset, BOOL simplif } else //avatar { - LLVector3 reset_pos = ((LLVOAvatar*)childp)->mDrawable->mXform.getPosition() + child_offset ; + if(!skip_avatar_child) + { + LLVector3 reset_pos = ((LLVOAvatar*)childp)->mDrawable->mXform.getPosition() + child_offset ; - ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos); - ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos); - - LLManip::rebuild(childp); - } - } + ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos); + ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos); + LLManip::rebuild(childp); + } + } + } } return ; } -// virtual +// virtual BOOL LLViewerObject::isTempAttachment() const { return (mID.notNull() && (mID == mAttachmentItemID)); @@ -5910,7 +6757,7 @@ BOOL LLViewerObject::isTempAttachment() const // std::string LLViewerObject::getAttachmentPointName() { - S32 point = ATTACHMENT_ID_FROM_STATE(mState); + S32 point = ATTACHMENT_ID_FROM_STATE(mAttachmentState); LLVOAvatar::attachment_map_t::iterator it = gAgentAvatarp->mAttachmentPoints.find(point); if(it != gAgentAvatarp->mAttachmentPoints.end()) { @@ -5969,6 +6816,10 @@ const LLUUID &LLViewerObject::extractAttachmentItemID() //virtual LLVOAvatar* LLViewerObject::getAvatar() const { + if (getControlAvatar()) + { + return getControlAvatar(); + } if (isAttachment()) { LLViewerObject* vobj = (LLViewerObject*) getParent(); @@ -5995,7 +6846,7 @@ class ObjectPhysicsProperties : public LLHTTPNode { LLSD object_data = input["body"]["ObjectData"]; S32 num_entries = object_data.size(); - + for ( S32 i = 0; i < num_entries; i++ ) { LLSD& curr_object_data = object_data[i]; @@ -6028,9 +6879,9 @@ class ObjectPhysicsProperties : public LLHTTPNode node->getObject()->setPhysicsFriction(friction); node->getObject()->setPhysicsDensity(density); node->getObject()->setPhysicsRestitution(restitution); - } + } } - + dialog_refresh_all(); }; }; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index ff5734a19f..e95b25c42a 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -54,27 +54,31 @@ class LLAgent; // TODO: Get rid of this. class LLAudioSource; class LLAudioSourceVO; class LLBBox; -class LLDataPacker; class LLColor4; -class LLFrameTimer; +class LLControlAvatar; +class LLDataPacker; class LLDrawable; +class LLFrameTimer; class LLHost; -class LLWorld; +class LLMessageSystem; class LLNameValue; class LLNetMap; -class LLMessageSystem; class LLPartSysData; -class LLPrimitive; class LLPipeline; +class LLPrimitive; class LLTextureEntry; -class LLViewerTexture; +class LLVOAvatar; +class LLVOInventoryListener; +class LLVOVolume; class LLViewerInventoryItem; class LLViewerObject; +class LLViewerObjectMedia; class LLViewerPartSourceScript; class LLViewerRegion; -class LLViewerObjectMedia; -class LLVOInventoryListener; -class LLVOAvatar; +class LLViewerTexture; +class LLWorld; + +class LLMeshCostData; typedef enum e_object_update_type { @@ -112,18 +116,32 @@ struct PotentialReturnableObject //============================================================================ -class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate +class LLViewerObject +: public LLPrimitive, + public LLRefCount, + public LLGLUpdate { protected: ~LLViewerObject(); // use unref() - // TomY: Provide for a list of extra parameter structures, mapped by structure name +private: struct ExtraParameter { - BOOL in_use; - LLNetworkData *data; + bool is_invalid = false; + bool* in_use = nullptr; + LLNetworkData* data = nullptr; }; - std::map mExtraParameterList; + std::vector mExtraParameterList; + bool mFlexibleObjectDataInUse = false; + bool mLightParamsInUse = false; + bool mSculptParamsInUse = false; + bool mLightImageParamsInUse = false; + bool mExtendedMeshParamsInUse = false; + LLFlexibleObjectData mFlexibleObjectData; + LLLightParams mLightParams; + LLSculptParams mSculptParams; + LLLightImageParams mLightImageParams; + LLExtendedMeshParams mExtendedMeshParams; public: typedef std::list > child_list_t; @@ -140,6 +158,9 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate BOOL isParticleSource() const; virtual LLVOAvatar* asAvatar(); + virtual LLVOVolume* asVolume(); + + LLVOAvatar* getAvatarAncestor(); static void initVOClasses(); static void cleanupVOClasses(); @@ -163,6 +184,7 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate INVALID_UPDATE = 0x80000000 }; + static U32 extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot); virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, @@ -217,6 +239,7 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate LLViewerRegion* getRegion() const { return mRegionp; } BOOL isSelected() const { return mUserSelected; } + BOOL isAnySelected() const; void setSelected(BOOL sel); const LLUUID &getID() const { return mID; } @@ -228,6 +251,7 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate virtual BOOL isFlexible() const { return FALSE; } virtual BOOL isSculpted() const { return FALSE; } virtual BOOL isMesh() const { return FALSE; } + virtual BOOL isRiggedMesh() const { return FALSE; } virtual BOOL hasLightTexture() const { return FALSE; } // This method returns true if the object is over land owned by @@ -252,6 +276,8 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate */ virtual BOOL setParent(LLViewerObject* parent); + virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent); + virtual void afterReparent(); virtual void addChild(LLViewerObject *childp); virtual void removeChild(LLViewerObject *childp); const_child_list_t& getChildren() const { return mChildList; } @@ -270,6 +296,7 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate virtual BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point @@ -356,9 +383,17 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate virtual void setScale(const LLVector3 &scale, BOOL damped = FALSE); - virtual F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL, F32* unscaled_value = NULL) const; + S32 getAnimatedObjectMaxTris() const; + F32 recursiveGetEstTrianglesMax() const; + virtual F32 getEstTrianglesMax() const; + virtual F32 getEstTrianglesStreamingCost() const; + virtual F32 getStreamingCost() const; + virtual bool getCostData(LLMeshCostData& costs) const; virtual U32 getTriangleCount(S32* vcount = NULL) const; virtual U32 getHighLODTriangleCount(); + F32 recursiveGetScaledSurfaceArea() const; + + U32 recursiveGetTriangleCount(S32* vcount = NULL) const; void setObjectCost(F32 cost); F32 getObjectCost(); @@ -376,7 +411,7 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate // U8 getState() { return mState; } // [RLVa:KB] - Checked: 2010-09-26 (RLVa-1.3.0a) | Added: RLVa-1.3.0a - U8 getState() const { return mState; } + U8 getAttachmentState() const { return mAttachmentState; } // [/RLVa:KB] F32 getAppAngle() const { return mAppAngle; } @@ -409,13 +444,17 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate void setCanSelect(BOOL canSelect); void setDebugText(const std::string &utf8text); + void initHudText(); + // std::string getDebugText(); // void setIcon(LLViewerTexture* icon_image); void clearIcon(); - void markForUpdate(BOOL priority); + void recursiveMarkForUpdate(BOOL priority); + virtual void markForUpdate(BOOL priority); + void markForUnload(BOOL priority); void updateVolume(const LLVolumeParams& volume_params); virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max); virtual F32 getBinRadius(); @@ -428,6 +467,7 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate void setDrawableState(U32 state, BOOL recursive = TRUE); void clearDrawableState(U32 state, BOOL recursive = TRUE); + BOOL isDrawableState(U32 state, BOOL recursive = TRUE) const; // Called when the drawable shifts virtual void onShift(const LLVector4a &shift_vector) { } @@ -442,10 +482,10 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate // viewer object has the inventory stored locally. void registerInventoryListener(LLVOInventoryListener* listener, void* user_data); void removeInventoryListener(LLVOInventoryListener* listener); - BOOL isInventoryPending() { return mInventoryPending; } + BOOL isInventoryPending(); void clearInventoryListeners(); + bool hasInventoryListeners(); void requestInventory(); - void fetchInventoryFromServer(); static void processTaskInv(LLMessageSystem* msg, void** user_data); void removeInventory(const LLUUID& item_id); @@ -538,9 +578,10 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate bool specialHoverCursor() const; // does it have a special hover cursor? void setRegion(LLViewerRegion *regionp); - virtual void updateRegion(LLViewerRegion *regionp) {} + virtual void updateRegion(LLViewerRegion *regionp); void updateFlags(BOOL physics_changed = FALSE); + void loadFlags(U32 flags); //load flags from cache or from message BOOL setFlags(U32 flag, BOOL state); BOOL setFlagsWithoutUpdate(U32 flag, BOOL state); void setPhysicsShapeType(U8 type); @@ -559,10 +600,15 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate virtual void dirtySpatialGroup(BOOL priority = FALSE) 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); + const LLFlexibleObjectData* getFlexibleObjectData() const { return mFlexibleObjectDataInUse ? &mFlexibleObjectData : nullptr; } + const LLLightParams* getLightParams() const { return mLightParamsInUse ? &mLightParams : nullptr; } + const LLSculptParams* getSculptParams() const { return mSculptParamsInUse ? &mSculptParams : nullptr; } + const LLLightImageParams* getLightImageParams() const { return mLightImageParamsInUse ? &mLightImageParams : nullptr; } + const LLExtendedMeshParams* getExtendedMeshParams() const { return mExtendedMeshParamsInUse ? &mExtendedMeshParams : 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); @@ -570,9 +616,20 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate friend class LLViewerObjectList; friend class LLViewerMediaList; +public: + LLViewerTexture* getBakedTextureForMagicId(const LLUUID& id); + void updateAvatarMeshVisibility(const LLUUID& id, const LLUUID& old_id); + void refreshBakeTexture(); +public: + static void unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name); + static void unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name); + static void unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name); + static void unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name); + static U32 unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id); + public: //counter-translation - void resetChildrenPosition(const LLVector3& offset, BOOL simplified = FALSE) ; + void resetChildrenPosition(const LLVector3& offset, BOOL simplified = FALSE, BOOL skip_avatar_child = FALSE) ; //counter-rotation void resetChildrenRotationAndPosition(const std::vector& rotations, const std::vector& positions) ; @@ -582,18 +639,47 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate private: ExtraParameter* createNewParameterEntry(U16 param_type); - ExtraParameter* getExtraParameterEntry(U16 param_type) const; - ExtraParameter* getExtraParameterEntryCreate(U16 param_type); - bool unpackParameterEntry(U16 param_type, LLDataPacker *dp); + const ExtraParameter& getExtraParameterEntry(U16 param_type) const + { + return mExtraParameterList[U32(param_type >> 4) - 1]; + } + ExtraParameter& getExtraParameterEntry(U16 param_type) + { + return mExtraParameterList[U32(param_type >> 4) - 1]; + } + ExtraParameter* getExtraParameterEntryCreate(U16 param_type) + { + if (param_type <= LLNetworkData::PARAMS_MAX) + { + ExtraParameter& param = getExtraParameterEntry(param_type); + if (!param.is_invalid) + { + if (!param.data) + { + ExtraParameter* new_entry = createNewParameterEntry(param_type); + return new_entry; + } + return ¶m; + } + } + return nullptr; + } + bool unpackParameterEntry(U16 param_type, LLDataPacker* dp); // This function checks to see if the given media URL has changed its version // and the update wasn't due to this agent's last action. U32 checkMediaURL(const std::string &media_url); // Motion prediction between updates - void interpolateLinearMotion(const F64 & time, const F32 & dt); + void interpolateLinearMotion(const F64SecondsImplicit & time, const F32SecondsImplicit & dt); + + static void initObjectDataMap(); + + // forms task inventory request if none are pending + void fetchInventoryFromServer(); public: + void print(); // // Viewer-side only types - use the LL_PCODE_APP mask. // @@ -644,6 +730,7 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate // Grabbed from UPDATE_FLAGS U32 mFlags; + static std::map sObjectDataMap; public: // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties U8 mPhysicsShapeType; @@ -676,6 +763,27 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate static BOOL sUseSharedDrawables; +public: + // Returns mControlAvatar for the edit root prim of this linkset + LLControlAvatar *getControlAvatar(); + LLControlAvatar *getControlAvatar() const; + + // Create or connect to an existing control av as applicable + void linkControlAvatar(); + // Remove any reference to control av for this prim + void unlinkControlAvatar(); + // Link or unlink as needed + void updateControlAvatar(); + + virtual bool isAnimatedObject() const; + + // Flags for createObject + static const S32 CO_FLAG_CONTROL_AVATAR = 1 << 0; + static const S32 CO_FLAG_UI_AVATAR = 1 << 1; + +protected: + LLPointer mControlAvatar; + protected: // delete an item in the inventory, but don't tell the // server. This is used internally by remove, update, and @@ -686,8 +794,7 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate // updateInventory. void doUpdateInventory(LLPointer& item, U8 key, bool is_new); - - static LLViewerObject *createObject(const LLUUID &id, LLPCode pcode, LLViewerRegion *regionp); + static LLViewerObject *createObject(const LLUUID &id, LLPCode pcode, LLViewerRegion *regionp, S32 flags = 0); BOOL setData(const U8 *datap, const U32 data_size); @@ -710,8 +817,6 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate void deleteParticleSource(); void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id); -public: - private: void setNameValueList(const std::string& list); // clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string void deleteTEImages(); // correctly deletes list of images @@ -722,8 +827,8 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate child_list_t mChildList; - F64 mLastInterpUpdateSecs; // Last update for purposes of interpolation - F64 mLastMessageUpdateSecs; // Last update from a message from the simulator + F64Seconds mLastInterpUpdateSecs; // Last update for purposes of interpolation + F64Seconds mLastMessageUpdateSecs; // Last update from a message from the simulator TPACKETID mLatestRecvPacketID; // Latest time stamp on message from simulator // extra data sent from the sim...currently only used for tree species info @@ -754,9 +859,17 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate callback_list_t mInventoryCallbacks; S16 mInventorySerialNum; + enum EInventoryRequestState + { + INVENTORY_REQUEST_STOPPED, + INVENTORY_REQUEST_PENDING, + INVENTORY_XFER + }; + EInventoryRequestState mInvRequestState; + U64 mInvRequestXFerId; + BOOL mInventoryDirty; + LLViewerRegion *mRegionp; // Region that this object belongs to. - BOOL mInventoryPending; - BOOL mInventoryDirty; BOOL mDead; BOOL mOrphaned; // This is an orphaned child BOOL mUserSelected; // Cached user select information @@ -765,12 +878,11 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate BOOL mStatic; // Object doesn't move. S32 mNumFaces; - F32 mTimeDilation; // Time dilation sent with the object. F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega) LLQuaternion mAngularVelocityRot; // accumulated rotation from the angular velocity computations LLQuaternion mPreviousRotation; - U8 mState; // legacy + U8 mAttachmentState; // this encodes the attachment id in a somewhat complex way. 0 if not an attachment. LLViewerObjectMedia* mMedia; // NULL if no media associated U8 mClickAction; F32 mObjectCost; //resource cost of this object or -1 if unknown @@ -791,12 +903,13 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate static S32 sAxisArrowLength; + // These two caches are only correct for non-parented objects right now! mutable LLVector3 mPositionRegion; mutable LLVector3 mPositionAgent; - static void setPhaseOutUpdateInterpolationTime(F32 value) { sPhaseOutUpdateInterpolationTime = (F64) value; } - static void setMaxUpdateInterpolationTime(F32 value) { sMaxUpdateInterpolationTime = (F64) value; } + static void setPhaseOutUpdateInterpolationTime(F32 value) { sPhaseOutUpdateInterpolationTime = (F64Seconds) value; } + static void setMaxUpdateInterpolationTime(F32 value) { sMaxUpdateInterpolationTime = (F64Seconds) value; } static void setVelocityInterpolate(BOOL value) { sVelocityInterpolate = value; } static void setPingInterpolate(BOOL value) { sPingInterpolate = value; } @@ -804,8 +917,8 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate private: static S32 sNumObjects; - static F64 sPhaseOutUpdateInterpolationTime; // For motion interpolation - static F64 sMaxUpdateInterpolationTime; // For motion interpolation + static F64Seconds sPhaseOutUpdateInterpolationTime; // For motion interpolation + static F64Seconds sMaxUpdateInterpolationTime; // For motion interpolation static BOOL sVelocityInterpolate; static BOOL sPingInterpolate; @@ -824,6 +937,11 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate void setLastUpdateType(EObjectUpdateType last_update_type); BOOL getLastUpdateCached() const; void setLastUpdateCached(BOOL last_update_cached); + + virtual void updateRiggingInfo() {} + + LLJointRiggingInfoTab mJointRiggingInfoTab; + private: LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory. EObjectUpdateType mLastUpdateType; diff --git a/indra/newview/llviewerobjectbackup.cpp b/indra/newview/llviewerobjectbackup.cpp index 9b0f97d97b..c520909e9b 100644 --- a/indra/newview/llviewerobjectbackup.cpp +++ b/indra/newview/llviewerobjectbackup.cpp @@ -35,7 +35,6 @@ #include "llcallbacklist.h" #include "lldir.h" -#include "lleconomy.h" #include "llhttpclient.h" #include "llinventorydefines.h" #include "llimagej2c.h" @@ -525,8 +524,7 @@ bool LLObjectBackup::validateNode(LLSelectNode* node) } else { - LLSculptParams* params; - params = (LLSculptParams*)obj->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams* params = obj->getSculptParams(); LLUUID sculpt_id = params->getSculptTexture(); return validateTexturePerms(sculpt_id); } @@ -871,23 +869,24 @@ LLSD LLObjectBackup::primsToLLSD(LLViewerObject::child_list_t child_list, if (object->isFlexible()) { // Flexible - LLFlexibleObjectData* flex; - flex = (LLFlexibleObjectData*)object->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); - prim_llsd["flexible"] = flex->asLLSD(); + const LLFlexibleObjectData* flex = object->getFlexibleObjectData(); + if (flex) + { + prim_llsd["flexible"] = flex->asLLSD(); + } } - if (object->getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT)) + const LLLightParams* light = object->getLightParams(); + if (light) { // Light - LLLightParams* light; - light = (LLLightParams*)object->getParameterEntry(LLNetworkData::PARAMS_LIGHT); prim_llsd["light"] = light->asLLSD(); } - if (object->getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + + const LLLightImageParams* light_param = object->getLightImageParams(); + if (light_param) { // Light image - LLLightImageParams* light_param; - light_param = (LLLightImageParams*)object->getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); t_id = validateTextureID(light_param->getLightTexture()); if (mTexturesList.count(t_id) == 0) { @@ -898,11 +897,10 @@ LLSD LLObjectBackup::primsToLLSD(LLViewerObject::child_list_t child_list, prim_llsd["light_texture"] = light_param->asLLSD(); } - if (object->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + const LLSculptParams* sculpt = object->getSculptParams(); + if (sculpt) { // Sculpt - LLSculptParams* sculpt; - sculpt = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT); prim_llsd["sculpt"] = sculpt->asLLSD(); if ((sculpt->getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) { @@ -1021,7 +1019,7 @@ void LLObjectBackup::exportNextTexture() continue; } - LLViewerTexture* imagep = LLViewerTextureManager::findTexture(id); + LLViewerTexture* imagep = LLViewerTextureManager::findFetchedTexture(id, TEX_LIST_STANDARD); if (imagep) { if (imagep->getDiscardLevel() > 0) @@ -1124,11 +1122,9 @@ void LLObjectBackup::importObject_continued(AIFilePicker* filepicker) mRezCount = 0; updateImportNumbers(); - for (LLSD::array_const_iterator prim_arr_it = mLLSD["data"].beginArray(), - prim_arr_end = mLLSD["data"].endArray(); - prim_arr_it != prim_arr_end; ++prim_arr_it) + for (auto const& entry : mLLSD["data"].array()) { - LLSD llsd2 = (*prim_arr_it)["group_body"]; + LLSD llsd2 = entry["group_body"]; for (LLSD::map_const_iterator prim_it = llsd2.beginMap(), prim_end = llsd2.endMap(); @@ -1370,7 +1366,7 @@ void LLObjectBackup::xmlToPrim(LLSD prim_llsd, LLViewerObject* object) LLUUID t_id = sculpt.getSculptTexture(); if (mAssetMap.count(t_id)) { - sculpt.setSculptTexture(mAssetMap[t_id]); + sculpt.setSculptTexture(mAssetMap[t_id], sculpt.getSculptType()); } object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt, true); diff --git a/indra/newview/llviewerobjectbackup.h b/indra/newview/llviewerobjectbackup.h index 2b2283dff5..7c1b136165 100644 --- a/indra/newview/llviewerobjectbackup.h +++ b/indra/newview/llviewerobjectbackup.h @@ -212,7 +212,7 @@ class LLObjectBackup : public LLFloater, std::string mFolder; // Export texture list - typedef boost::unordered_set textures_set_t; + typedef uuid_set_t textures_set_t; textures_set_t mTexturesList; textures_set_t mBadPermsTexturesList; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 40c88245bb..2437ce618a 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -101,6 +101,15 @@ class AIHTTPTimeoutPolicy; extern AIHTTPTimeoutPolicy objectCostResponder_timeout; extern AIHTTPTimeoutPolicy physicsFlagsResponder_timeout; +// +#include "llimpanel.h" +#include "llimview.h" +LLFloaterIMPanel* find_im_floater(const LLUUID& id) +{ + return gIMMgr->findFloaterBySession(id ^ gAgentID); +} +// + #define CULL_VIS //#define ORPHAN_SPAM //#define IGNORE_DEAD @@ -282,7 +291,19 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, // RN: this must be called after we have a drawable // (from gPipeline.addObject) // so that the drawable parent is set properly - findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort()); + if(msg != NULL) + { + findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort()); + } + else + { + LLViewerRegion* regionp = objectp->getRegion(); + if(regionp != NULL) + { + findOrphans(objectp, regionp->getHost().getAddress(), regionp->getHost().getPort()); + } + } + if(just_created && objectp && (gImportTracker.getState() == ImportTracker::WAND /*|| @@ -314,14 +335,14 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, } } -static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_OBJECTS("Process Objects"); void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, void **user_data, const EObjectUpdateType update_type, bool cached, bool compressed) { - LLFastTimer t(FTM_PROCESS_OBJECTS); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_OBJECTS); LLViewerObject *objectp; S32 num_objects; @@ -425,24 +446,20 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, { S32 uncompressed_length = 2048; compressed_dp.reset(); - - U32 flags = 0; - if (update_type != OUT_TERSE_IMPROVED) - { - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); - } uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i); + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i, 2048); compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { + U32 flags = 0; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); compressed_dp.unpackUUID(fullid, "ID"); compressed_dp.unpackU32(local_id, "LocalID"); compressed_dp.unpackU8(pcode, "PCode"); } - else + else //OUT_TERSE_IMPROVED { compressed_dp.unpackU32(local_id, "LocalID"); getUUIDFromLocal(fullid, @@ -451,7 +468,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, gMessageSystem->getSenderPort()); if (fullid.isNull()) { - // LL_WARNS() << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << LL_ENDL; + LL_DEBUGS() << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << LL_ENDL; mNumUnknownUpdates++; } } @@ -556,7 +573,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if(std::find(LLFloaterBlacklist::blacklist_objects.begin(), LLFloaterBlacklist::blacklist_objects.end(),fullid) != LLFloaterBlacklist::blacklist_objects.end()) { - LL_INFOS() << "Blacklisted object asset " << fullid.asString() << " blocked." << LL_ENDL; + //LL_INFOS() << "Blacklisted object asset " << fullid.asString() << " blocked." << LL_ENDL; continue; } @@ -729,12 +746,9 @@ class LLObjectCostResponder : public LLHTTPClient::ResponderWithResult void clear_object_list_pending_requests() { // TODO*: No more hard coding - for ( - LLSD::array_iterator iter = mObjectIDs.beginArray(); - iter != mObjectIDs.endArray(); - ++iter) + for (auto const& id : mObjectIDs.array()) { - gObjectList.onObjectCostFetchFailure(iter->asUUID()); + gObjectList.onObjectCostFetchFailure(id.asUUID()); } } @@ -772,23 +786,20 @@ class LLObjectCostResponder : public LLHTTPClient::ResponderWithResult // Success, grab the resource cost and linked set costs // for an object if one was returned - for ( - LLSD::array_iterator iter = mObjectIDs.beginArray(); - iter != mObjectIDs.endArray(); - ++iter) + for (auto const& entry : mObjectIDs.array()) { - LLUUID object_id = iter->asUUID(); + LLUUID object_id = entry.asUUID(); // Check to see if the request contains data for the object - if ( mContent.has(iter->asString()) ) + if ( mContent.has(entry.asString()) ) { F32 link_cost = - mContent[iter->asString()]["linked_set_resource_cost"].asReal(); + mContent[entry.asString()]["linked_set_resource_cost"].asReal(); F32 object_cost = - mContent[iter->asString()]["resource_cost"].asReal(); + mContent[entry.asString()]["resource_cost"].asReal(); - F32 physics_cost = mContent[iter->asString()]["physics_cost"].asReal(); - F32 link_physics_cost = mContent[iter->asString()]["linked_set_physics_cost"].asReal(); + F32 physics_cost = mContent[entry.asString()]["physics_cost"].asReal(); + F32 link_physics_cost = mContent[entry.asString()]["linked_set_physics_cost"].asReal(); gObjectList.updateObjectCost(object_id, object_cost, link_cost, physics_cost, link_physics_cost); } @@ -820,12 +831,9 @@ class LLPhysicsFlagsResponder : public LLHTTPClient::ResponderWithResult void clear_object_list_pending_requests() { // TODO*: No more hard coding - for ( - LLSD::array_iterator iter = mObjectIDs.beginArray(); - iter != mObjectIDs.endArray(); - ++iter) + for (auto const& id : mObjectIDs.array()) { - gObjectList.onPhysicsFlagsFetchFailure(iter->asUUID()); + gObjectList.onPhysicsFlagsFetchFailure(id.asUUID()); } } @@ -863,17 +871,14 @@ class LLPhysicsFlagsResponder : public LLHTTPClient::ResponderWithResult // Success, grab the resource cost and linked set costs // for an object if one was returned - for ( - LLSD::array_iterator iter = mObjectIDs.beginArray(); - iter != mObjectIDs.endArray(); - ++iter) + for (auto const& entry : mObjectIDs.array()) { - LLUUID object_id = iter->asUUID(); + LLUUID object_id = entry.asUUID(); // Check to see if the request contains data for the object - if (mContent.has(iter->asString())) + if (mContent.has(entry.asString())) { - const LLSD& data = mContent[iter->asString()]; + const LLSD& data = mContent[entry.asString()]; S32 shape_type = data["PhysicsShapeType"].asInteger(); @@ -932,14 +937,14 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) // update global timer F32 last_time = gFrameTimeSeconds; - U64 time = totalTime(); // this will become the new gFrameTime when the update is done + U64Microseconds time = totalTime(); // this will become the new gFrameTime when the update is done // Time _can_ go backwards, for example if the user changes the system clock. // It doesn't cause any fatal problems (just some oddness with stats), so we shouldn't assert here. // llassert(time > gFrameTime); - F64 time_diff = U64_to_F64(time - gFrameTime)/(F64)SEC_TO_MICROSEC; - gFrameTime = time; - F64 time_since_start = U64_to_F64(gFrameTime - gStartTime)/(F64)SEC_TO_MICROSEC; - gFrameTimeSeconds = (F32)time_since_start; + F64Seconds time_diff = time - gFrameTime; + gFrameTime = time; + F64Seconds time_since_start = gFrameTime - gStartTime; + gFrameTimeSeconds = time_since_start; gFrameIntervalSeconds = gFrameTimeSeconds - last_time; if (gFrameIntervalSeconds < 0.f) @@ -961,10 +966,10 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) U32 idle_count = 0; - static LLFastTimer::DeclareTimer idle_copy("Idle Copy"); + static LLTrace::BlockTimerStatHandle idle_copy("Idle Copy"); { - LLFastTimer t(idle_copy); + LL_RECORD_BLOCK_TIME(idle_copy); for (std::vector >::iterator active_iter = mActiveObjects.begin(); active_iter != mActiveObjects.end(); active_iter++) @@ -1024,7 +1029,10 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) LLVolumeImplFlexible::updateClass(); //update animated textures - LLViewerTextureAnim::updateClass(); + if (gAnimateTextures) + { + LLViewerTextureAnim::updateClass(); + } } @@ -1042,7 +1050,7 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) // don't factor frames that were paused into the stats if (! mWasPaused) { - LLViewerStats::getInstance()->updateFrameStats(time_diff); + LLViewerStats::getInstance()->updateFrameStats(time_diff.value()); } /* @@ -1117,7 +1125,7 @@ void LLViewerObjectList::fetchObjectCosts() U32 object_index = 0; for ( - std::set::iterator iter = mStaleObjectCost.begin(); + auto iter = mStaleObjectCost.begin(); iter != mStaleObjectCost.end(); ) { @@ -1175,7 +1183,7 @@ void LLViewerObjectList::fetchPhysicsFlags() U32 object_index = 0; for ( - std::set::iterator iter = mStalePhysicsFlags.begin(); + auto iter = mStalePhysicsFlags.begin(); iter != mStalePhysicsFlags.end(); ) { @@ -1243,9 +1251,11 @@ void LLViewerObjectList::clearDebugText() void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) { + bool new_dead_object = true; if (mDeadObjects.find(objectp->mID) != mDeadObjects.end()) { LL_INFOS() << "Object " << objectp->mID << " already on dead list!" << LL_ENDL; + new_dead_object = false; } else { @@ -1256,7 +1266,11 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) // Remove from object map so noone can look it up. mUUIDObjectMap.erase(objectp->mID); - mUUIDAvatarMap.erase(objectp->mID);//No need to be careful here. + // Use the return value (number of erased elements) to determine if we were an avatar. + if (mUUIDAvatarMap.erase(objectp->mID)) //No need to be careful here. + if (LLFloaterIMPanel* im = find_im_floater(objectp->mID)) + im->removeDynamicFocus(); + // //if (objectp->getRegion()) //{ @@ -1283,14 +1297,17 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) // Also, not cleaned up removeDrawable(objectp->mDrawable); - mNumDeadObjects++; + if(new_dead_object) + { + mNumDeadObjects++; + } } -static LLFastTimer::DeclareTimer FTM_REMOVE_DRAWABLE("Remove Drawable"); +static LLTrace::BlockTimerStatHandle FTM_REMOVE_DRAWABLE("Remove Drawable"); void LLViewerObjectList::removeDrawable(LLDrawable* drawablep) { - LLFastTimer t(FTM_REMOVE_DRAWABLE); + LL_RECORD_BLOCK_TIME(FTM_REMOVE_DRAWABLE); if (!drawablep) { @@ -1326,16 +1343,11 @@ BOOL LLViewerObjectList::killObject(LLViewerObject *objectp) if (objectp) { - if (objectp->isDead()) - { - // This object is already dead. Don't need to do more. - return TRUE; - } - else - { - objectp->markDead(); - } - + // We are going to cleanup a lot of smart pointers to this object, they might be last, + // and object being NULLed while inside it's own function won't be pretty + // so create a pointer to make sure object will stay alive untill markDead() finishes + LLPointer sp(objectp); + sp->markDead(); // does the right thing if object already dead return TRUE; } return FALSE; @@ -1589,9 +1601,9 @@ void LLViewerObjectList::onPhysicsFlagsFetchFailure(const LLUUID& object_id) mPendingPhysicsFlags.erase(object_id); } -static LLFastTimer::DeclareTimer FTM_SHIFT_OBJECTS("Shift Objects"); -static LLFastTimer::DeclareTimer FTM_PIPELINE_SHIFT("Pipeline Shift"); -static LLFastTimer::DeclareTimer FTM_REGION_SHIFT("Region Shift"); +static LLTrace::BlockTimerStatHandle FTM_SHIFT_OBJECTS("Shift Objects"); +static LLTrace::BlockTimerStatHandle FTM_PIPELINE_SHIFT("Pipeline Shift"); +static LLTrace::BlockTimerStatHandle FTM_REGION_SHIFT("Region Shift"); void LLViewerObjectList::shiftObjects(const LLVector3 &offset) { @@ -1604,7 +1616,7 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) return; } - LLFastTimer t(FTM_SHIFT_OBJECTS); + LL_RECORD_BLOCK_TIME(FTM_SHIFT_OBJECTS); LLViewerObject *objectp; for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) @@ -1623,12 +1635,12 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) } { - LLFastTimer t(FTM_PIPELINE_SHIFT); + LL_RECORD_BLOCK_TIME(FTM_PIPELINE_SHIFT); gPipeline.shiftObjects(offset); } { - LLFastTimer t(FTM_REGION_SHIFT); + LL_RECORD_BLOCK_TIME(FTM_REGION_SHIFT); LLWorld::getInstance()->shiftRegions(offset); } } @@ -1961,24 +1973,30 @@ void LLViewerObjectList::resetObjectBeacons() mDebugBeacons.clear(); } -LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp) +LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp, S32 flags) { LLUUID fullid; fullid.generate(); - LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp); + LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp, flags); if (!objectp) { // LL_WARNS() << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << LL_ENDL; return NULL; } - mUUIDObjectMap[fullid] = objectp; + mUUIDObjectMap.insert_or_assign(fullid, objectp); if(objectp->isAvatar()) { LLVOAvatar *pAvatar = dynamic_cast(objectp); if(pAvatar) - mUUIDAvatarMap[fullid] = pAvatar; + { + mUUIDAvatarMap.insert_or_assign(fullid, pAvatar); + // + if (LLFloaterIMPanel* im = find_im_floater(fullid)) + im->addDynamicFocus(); + // + } } mObjects.push_back(objectp); @@ -1989,12 +2007,12 @@ LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLVi } -static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object"); +static LLTrace::BlockTimerStatHandle FTM_CREATE_OBJECT("Create Object"); LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id, const LLHost &sender) { - LLFastTimer t(FTM_CREATE_OBJECT); + LL_RECORD_BLOCK_TIME(FTM_CREATE_OBJECT); LLUUID fullid; if (uuid == LLUUID::null) @@ -2012,13 +2030,23 @@ LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRe // LL_WARNS() << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << LL_ENDL; return NULL; } + if(regionp) + { + regionp->addToCreatedList(local_id); + } - mUUIDObjectMap[fullid] = objectp; + mUUIDObjectMap.insert_or_assign(fullid, objectp); if(objectp->isAvatar()) { LLVOAvatar *pAvatar = dynamic_cast(objectp); if(pAvatar) - mUUIDAvatarMap[fullid] = pAvatar; + { + mUUIDAvatarMap.insert_or_assign(fullid, pAvatar); + // + if (LLFloaterIMPanel* im = find_im_floater(fullid)) + im->addDynamicFocus(); + // + } } setUUIDAndLocal(fullid, local_id, diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 6d3dafe58f..6ff21d3e53 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -36,6 +36,8 @@ #include #include +#include "absl/container/flat_hash_map.h" + // common includes #include "llstat.h" #include "llstring.h" @@ -48,15 +50,15 @@ class LLCamera; class LLNetMap; class LLDebugBeacon; -const U32 CLOSE_BIN_SIZE = 10; -const U32 NUM_BINS = 128; +constexpr U32 CLOSE_BIN_SIZE = 10; +constexpr U32 NUM_BINS = 128; // GL name = position in object list + GL_NAME_INDEX_OFFSET so that // we can have special numbers like zero. -const U32 GL_NAME_LAND = 0; -const U32 GL_NAME_PARCEL_WALL = 1; +constexpr U32 GL_NAME_LAND = 0; +constexpr U32 GL_NAME_PARCEL_WALL = 1; -const U32 GL_NAME_INDEX_OFFSET = 10; +constexpr U32 GL_NAME_INDEX_OFFSET = 10; class LLViewerObjectList { @@ -74,7 +76,7 @@ class LLViewerObjectList inline LLViewerObject *findObject(const LLUUID &id) const; inline LLVOAvatar *findAvatar(const LLUUID &id) const; - LLViewerObject *createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp); // Create a viewer-side object + LLViewerObject *createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp, S32 flags = 0); // Create a viewer-side object LLViewerObject *createObject(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id, const LLHost &sender); @@ -141,6 +143,7 @@ class LLViewerObjectList LLViewerObject *getSelectedObject(const U32 object_id); inline S32 getNumObjects() { return (S32) mObjects.size(); } + inline S32 getNumActiveObjects() { return (S32) mActiveObjects.size(); } void addToMap(LLViewerObject *objectp); void removeFromMap(LLViewerObject *objectp); @@ -216,18 +219,18 @@ class LLViewerObjectList vobj_list_t mMapObjects; - std::set mDeadObjects; + uuid_set_t mDeadObjects; - boost::unordered_map > mUUIDObjectMap; - boost::unordered_map > mUUIDAvatarMap; + absl::flat_hash_map > mUUIDObjectMap; + absl::flat_hash_map > mUUIDAvatarMap; //set of objects that need to update their cost - std::set mStaleObjectCost; - std::set mPendingObjectCost; + uuid_set_t mStaleObjectCost; + uuid_set_t mPendingObjectCost; //set of objects that need to update their physics flags - std::set mStalePhysicsFlags; - std::set mPendingPhysicsFlags; + uuid_set_t mStalePhysicsFlags; + uuid_set_t mPendingPhysicsFlags; std::vector mDebugBeacons; @@ -271,8 +274,8 @@ extern LLViewerObjectList gObjectList; // Inlines inline LLViewerObject *LLViewerObjectList::findObject(const LLUUID &id) const { - boost::unordered_map >::const_iterator iter = mUUIDObjectMap.find(id); - if(iter != mUUIDObjectMap.end()) + auto iter = mUUIDObjectMap.find(id); + if(iter != mUUIDObjectMap.cend()) { return iter->second; } @@ -284,8 +287,8 @@ inline LLViewerObject *LLViewerObjectList::findObject(const LLUUID &id) const inline LLVOAvatar *LLViewerObjectList::findAvatar(const LLUUID &id) const { - boost::unordered_map >::const_iterator iter = mUUIDAvatarMap.find(id); - return (iter != mUUIDAvatarMap.end()) ? iter->second.get() : NULL; + auto iter = mUUIDAvatarMap.find(id); + return (iter != mUUIDAvatarMap.cend()) ? iter->second.get() : NULL; } inline LLViewerObject *LLViewerObjectList::getObject(const S32 index) diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 94199d1f59..e810e6c529 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -272,11 +272,10 @@ void LLViewerOctreeEntry::removeData(LLViewerOctreeEntryData* data) mData[data->getDataType()] = NULL; - if(mGroup != NULL && !mData[LLDRAWABLE]) + if(!mGroup.isNull() && !mData[LLDRAWABLE]) { - LLViewerOctreeGroup* group = mGroup; + mGroup->removeFromGroup(data); mGroup = NULL; - group->removeFromGroup(data); llassert(mBinIndex == -1); } @@ -390,7 +389,7 @@ void LLViewerOctreeEntryData::shift(const LLVector4a &shift_vector) LLViewerOctreeGroup* LLViewerOctreeEntryData::getGroup()const { - return mEntry.notNull() ? mEntry->mGroup : NULL; + return mEntry.notNull() ? mEntry->mGroup : LLPointer(); } const LLVector4a& LLViewerOctreeEntryData::getPositionGroup() const @@ -455,17 +454,23 @@ LLViewerOctreeGroup::~LLViewerOctreeGroup() LLViewerOctreeGroup::LLViewerOctreeGroup(OctreeNode* node) : mOctreeNode(node), + mAnyVisible(0), mState(CLEAN) { LLVector4a tmp; tmp.splat(0.f); - mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] = + mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[1] = mObjectExtents[0] = mObjectExtents[1] = tmp; mBounds[0] = node->getCenter(); mBounds[1] = node->getSize(); mOctreeNode->addListener(this); + + for (U32 i = 0; i < sizeof(mVisible) / sizeof(mVisible[0]); i++) + { + mVisible[i] = 0; + } } bool LLViewerOctreeGroup::hasElement(LLViewerOctreeEntryData* data) @@ -631,17 +636,6 @@ void LLViewerOctreeGroup::handleDestruction(const TreeNode* node) mOctreeNode = NULL; } -//virtual -void LLViewerOctreeGroup::handleStateChange(const TreeNode* node) -{ - //drop bounding box upon state change - if (mOctreeNode != node) - { - mOctreeNode = (OctreeNode*) node; - } - unbound(); -} - //virtual void LLViewerOctreeGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) { @@ -760,6 +754,11 @@ BOOL LLViewerOctreeGroup::isRecentlyVisible() const void LLViewerOctreeGroup::setVisible() { mVisible[LLViewerCamera::sCurCameraID] = LLViewerOctreeEntryData::getCurrentFrame(); + + if(LLViewerCamera::sCurCameraID < LLViewerCamera::CAMERA_WATER0) + { + mAnyVisible = LLViewerOctreeEntryData::getCurrentFrame(); + } } void LLViewerOctreeGroup::checkStates() @@ -807,7 +806,7 @@ U32 LLOcclusionCullingGroup::getNewOcclusionQueryObjectName() return sQueryPool.allocate(); } -void LLOcclusionCullingGroup::releaseOcclusionQueryObjectName(GLuint name) +void LLOcclusionCullingGroup::releaseOcclusionQueryObjectName(U32 name) { sQueryPool.release(name); } @@ -847,10 +846,12 @@ class LLSpatialSetOcclusionStateDiff : public LLSpatialSetOcclusionState }; -LLOcclusionCullingGroup::LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctreePartition* part) : +LLOcclusionCullingGroup::LLOcclusionCullingGroup(OctreeNode* node, LLSpatialPartition* part) : LLViewerOctreeGroup(node), mSpatialPartition(part) { + llassert(part); + mSpatialPartition->mGroups.push_back(this); part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod; mLODHash = part->mLODSeed; @@ -868,12 +869,21 @@ LLOcclusionCullingGroup::LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctre LLOcclusionCullingGroup::~LLOcclusionCullingGroup() { + if (mSpatialPartition) + { + auto it = std::find_if(mSpatialPartition->mGroups.begin(), mSpatialPartition->mGroups.end(), [this](LLOcclusionCullingGroup* rhs) {return rhs == this; }); + llassert(it != mSpatialPartition->mGroups.end()); + if (it != mSpatialPartition->mGroups.end()) + { + mSpatialPartition->mGroups.erase(it); + } + } releaseOcclusionQueryObjectNames(); } BOOL LLOcclusionCullingGroup::needsUpdate() { - return (LLDrawable::getCurrentFrame() % mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE; + return mSpatialPartition && (LLDrawable::getCurrentFrame() % mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE; } BOOL LLOcclusionCullingGroup::isRecentlyVisible() const @@ -882,6 +892,12 @@ BOOL LLOcclusionCullingGroup::isRecentlyVisible() const return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < MIN_VIS_FRAME_RANGE ; } +BOOL LLOcclusionCullingGroup::isAnyRecentlyVisible() const +{ + const S32 MIN_VIS_FRAME_RANGE = 2; + return (LLDrawable::getCurrentFrame() - mAnyVisible) < MIN_VIS_FRAME_RANGE ; +} + //virtual void LLOcclusionCullingGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) { @@ -1013,8 +1029,8 @@ void LLOcclusionCullingGroup::clearOcclusionState(eOcclusionState state, S32 mod } } -static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Occlusion Wait"); +static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_READBACK("Readback Occlusion"); +static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_WAIT("Occlusion Wait"); BOOL LLOcclusionCullingGroup::earlyFail(LLCamera* camera, const LLVector4a* bounds) { @@ -1027,7 +1043,7 @@ BOOL LLOcclusionCullingGroup::earlyFail(LLCamera* camera, const LLVector4a* boun LLVector4a fudge(vel*2.f); const LLVector4a& c = bounds[0]; - static LLVector4a r; + LLVector4a r; r.setAdd(bounds[1], fudge); /*if (r.magVecSquared() > 1024.0*1024.0) @@ -1065,9 +1081,13 @@ U32 LLOcclusionCullingGroup::getLastOcclusionIssuedTime() void LLOcclusionCullingGroup::checkOcclusion() { + if (mSpatialPartition == nullptr) + { + return; + } if (LLPipeline::sUseOcclusion > 1) { - LLFastTimer t(FTM_OCCLUSION_READBACK); + LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_READBACK); LLOcclusionCullingGroup* parent = (LLOcclusionCullingGroup*)getParent(); if (parent && parent->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) { //if the parent has been marked as occluded, the child is implicitly occluded @@ -1086,10 +1106,10 @@ void LLOcclusionCullingGroup::checkOcclusion() if (wait_for_query && mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount) { //query was issued last frame, wait until it's available S32 max_loop = 1024; - LLFastTimer t(FTM_OCCLUSION_WAIT); + LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_WAIT); while (!available && max_loop-- > 0) { - F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f); + F32 max_time = llmin(gFrameIntervalSeconds.value()*10.f, 1.f); //do some usefu work while we wait LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread @@ -1152,20 +1172,24 @@ void LLOcclusionCullingGroup::checkOcclusion() } } -static LLFastTimer::DeclareTimer FTM_PUSH_OCCLUSION_VERTS("Push Occlusion"); -static LLFastTimer::DeclareTimer FTM_SET_OCCLUSION_STATE("Occlusion State"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_EARLY_FAIL("Occlusion Early Fail"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_ALLOCATE("Allocate"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_BUILD("Build"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_BEGIN_QUERY("Begin Query"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_END_QUERY("End Query"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_SET_BUFFER("Set Buffer"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW_WATER("Draw Water"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW("Draw"); +static LLTrace::BlockTimerStatHandle FTM_PUSH_OCCLUSION_VERTS("Push Occlusion"); +static LLTrace::BlockTimerStatHandle FTM_SET_OCCLUSION_STATE("Occlusion State"); +static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_EARLY_FAIL("Occlusion Early Fail"); +static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_ALLOCATE("Allocate"); +static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_BUILD("Build"); +static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_BEGIN_QUERY("Begin Query"); +static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_END_QUERY("End Query"); +static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_SET_BUFFER("Set Buffer"); +static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_DRAW_WATER("Draw Water"); +static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_DRAW("Draw"); void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* shift) { - LLGLDisable stencil(GL_STENCIL_TEST); + if (mSpatialPartition == nullptr) + { + return; + } + LLGLDisable stencil; if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1) { //move mBounds to the agent space if necessary @@ -1180,7 +1204,7 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh // Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension if (earlyFail(camera, bounds)) { - LLFastTimer t(FTM_OCCLUSION_EARLY_FAIL); + LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_EARLY_FAIL); setOcclusionState(LLOcclusionCullingGroup::DISCARD_QUERY); assert_states_valid(this); clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); @@ -1191,11 +1215,11 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh if (!isOcclusionState(QUERY_PENDING) || isOcclusionState(DISCARD_QUERY)) { { //no query pending, or previous query to be discarded - LLFastTimer t(FTM_RENDER_OCCLUSION); + LL_RECORD_BLOCK_TIME(FTM_RENDER_OCCLUSION); if (!mOcclusionQuery[LLViewerCamera::sCurCameraID]) { - LLFastTimer t(FTM_OCCLUSION_ALLOCATE); + LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_ALLOCATE); mOcclusionQuery[LLViewerCamera::sCurCameraID] = getNewOcclusionQueryObjectName(); } @@ -1206,7 +1230,7 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER || mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER); - LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0); + LLGLEnable clamp(use_depth_clamp); #if !LL_DARWIN U32 mode = gGLManager.mHasOcclusionQuery2 ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED_ARB; @@ -1219,13 +1243,13 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh #endif { - LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS); + LL_RECORD_BLOCK_TIME(FTM_PUSH_OCCLUSION_VERTS); //store which frame this query was issued on mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount; { - LLFastTimer t(FTM_OCCLUSION_BEGIN_QUERY); + LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_BEGIN_QUERY); glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); } @@ -1236,13 +1260,18 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh //static LLVector4a fudge(SG_OCCLUSION_FUDGE); static LLCachedControl vel("SHOcclusionFudge",SG_OCCLUSION_FUDGE); LLVector4a fudge(SG_OCCLUSION_FUDGE); + if (LLDrawPool::POOL_WATER == mSpatialPartition->mDrawableType) + { + fudge.getF32ptr()[2] = 1.f; + } + static LLVector4a fudged_bounds; fudged_bounds.setAdd(fudge, bounds[1]); shader->uniform3fv(LLShaderMgr::BOX_SIZE, 1, fudged_bounds.getF32ptr()); if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER) { - LLFastTimer t(FTM_OCCLUSION_DRAW_WATER); + LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_DRAW_WATER); LLGLSquashToFarClip squash(glh_get_current_projection(), 1); if (camera->getOrigin().isExactlyZero()) @@ -1257,7 +1286,7 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh } else { - LLFastTimer t(FTM_OCCLUSION_DRAW); + LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_DRAW); if (camera->getOrigin().isExactlyZero()) { //origin is invalid, draw entire box gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); @@ -1271,14 +1300,14 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh { - LLFastTimer t(FTM_OCCLUSION_END_QUERY); + LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_END_QUERY); glEndQueryARB(mode); } } } { - LLFastTimer t(FTM_SET_OCCLUSION_STATE); + LL_RECORD_BLOCK_TIME(FTM_SET_OCCLUSION_STATE); setOcclusionState(LLOcclusionCullingGroup::QUERY_PENDING); clearOcclusionState(LLOcclusionCullingGroup::DISCARD_QUERY); } @@ -1293,7 +1322,8 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh //----------------------------------------------------------------------------------- //class LLViewerOctreePartition definitions //----------------------------------------------------------------------------------- -LLViewerOctreePartition::LLViewerOctreePartition() : +LLViewerOctreePartition::LLViewerOctreePartition() : + mRegionp(NULL), mOcclusionEnabled(TRUE), mDrawableType(0), mLODSeed(0), @@ -1308,6 +1338,11 @@ LLViewerOctreePartition::LLViewerOctreePartition() : LLViewerOctreePartition::~LLViewerOctreePartition() { + llassert(mGroups.empty()); + for (auto& entry : mGroups) + { + entry->mSpatialPartition = nullptr; + } delete mOctree; mOctree = NULL; } @@ -1453,21 +1488,21 @@ bool LLViewerOctreeCull::checkProjectionArea(const LLVector4a& center, const LLV //virtual bool LLViewerOctreeCull::checkObjects(const OctreeNode* branch, const LLViewerOctreeGroup* group) { - if (branch->getElementCount() == 0) //no elements - { - return false; - } - else if (branch->getChildCount() == 0) //leaf state, already checked tightest bounding box - { - return true; - } - else if (mRes == 1 && !frustumCheckObjects(group)) //no objects in frustum - { - return false; - } - + if (branch->getElementCount() == 0) //no elements + { + return false; + } + else if (branch->getChildCount() == 0) //leaf state, already checked tightest bounding box + { return true; } + else if (mRes == 1 && !frustumCheckObjects(group)) //no objects in frustum + { + return false; + } + + return true; +} //virtual void LLViewerOctreeCull::preprocess(LLViewerOctreeGroup* group) diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h index 73749edafc..b1560f23fc 100644 --- a/indra/newview/llvieweroctree.h +++ b/indra/newview/llvieweroctree.h @@ -44,6 +44,7 @@ class LLViewerOctreeEntryData; class LLViewerOctreeGroup; class LLViewerOctreeEntry; class LLViewerOctreePartition; +class LLSpatialPartition; typedef LLOctreeListener OctreeListener; typedef LLTreeNode TreeNode; @@ -77,6 +78,7 @@ class LLViewerOctreeEntry : public LLRefCount typedef enum { LLDRAWABLE = 0, + LLVOCACHEENTRY, NUM_DATA_TYPE }eEntryDataType_t; @@ -92,6 +94,9 @@ class LLViewerOctreeEntry : public LLRefCount LLViewerOctreeEntryData* getDrawable() const {return mData[LLDRAWABLE];} bool hasDrawable() const {return mData[LLDRAWABLE] != NULL;} + LLViewerOctreeEntryData* getVOCacheEntry() const {return mData[LLVOCACHEENTRY];} + bool hasVOCacheEntry() const {return mData[LLVOCACHEENTRY] != NULL;} + const LLVector4a* getSpatialExtents() const {return mExtents;} const LLVector4a& getPositionGroup() const {return mPositionGroup;} LLViewerOctreeGroup* getGroup()const {return mGroup;} @@ -105,7 +110,7 @@ class LLViewerOctreeEntry : public LLRefCount private: LLViewerOctreeEntryData* mData[NUM_DATA_TYPE]; //do not use LLPointer here. - LLViewerOctreeGroup* mGroup; + LLPointer mGroup; //aligned members LL_ALIGN_16(LLVector4a mExtents[2]); @@ -208,6 +213,7 @@ class LLViewerOctreeGroup BOOL isVisible() const; virtual BOOL isRecentlyVisible() const; S32 getVisible(LLViewerCamera::eCameraID id) const {return mVisible[id];} + S32 getAnyVisible() const {return mAnyVisible;} bool isEmpty() const { return mOctreeNode->isEmpty(); } U32 getState() {return mState; } @@ -217,14 +223,14 @@ class LLViewerOctreeGroup void clearState(U32 state) {mState &= ~state;} //LISTENER FUNCTIONS - virtual void handleInsertion(const TreeNode* node, LLViewerOctreeEntry* obj); - virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* obj); - virtual void handleDestruction(const TreeNode* node); - virtual void handleStateChange(const TreeNode* node); - virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); - virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child); + void handleInsertion(const TreeNode* node, LLViewerOctreeEntry* obj) override; + void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* obj) override; + void handleDestruction(const TreeNode* node) override; + void handleChildAddition(const OctreeNode* parent, OctreeNode* child) override; + void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child) final override; OctreeNode* getOctreeNode() {return mOctreeNode;} + const OctreeNode* getOctreeNode() const { return mOctreeNode; } LLViewerOctreeGroup* getParent(); const LLVector4a* getBounds() const {return mBounds;} @@ -233,7 +239,7 @@ class LLViewerOctreeGroup const LLVector4a* getObjectExtents() const {return mObjectExtents;} //octree wrappers to make code more readable - //element_list& getData() { return mOctreeNode->getData(); } //unused + //element_list& getData() { return mOctreeNode->getData(); } element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } U32 getElementCount() const { return mOctreeNode->getElementCount(); } @@ -253,6 +259,7 @@ class LLViewerOctreeGroup LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children LL_ALIGN_16(LLVector4a mObjectExtents[2]); // extents (min, max) of objects in this node + S32 mAnyVisible; //latest visible to any camera S32 mVisible[LLViewerCamera::NUM_CAMERAS]; }; @@ -282,7 +289,7 @@ class LLOcclusionCullingGroup : public LLViewerOctreeGroup virtual ~LLOcclusionCullingGroup(); public: - LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctreePartition* part); + LLOcclusionCullingGroup(OctreeNode* node, LLSpatialPartition* part); LLOcclusionCullingGroup(const LLOcclusionCullingGroup& rhs) : LLViewerOctreeGroup(rhs) { *this = rhs; @@ -302,11 +309,12 @@ class LLOcclusionCullingGroup : public LLViewerOctreeGroup U32 getLastOcclusionIssuedTime(); //virtual - void handleChildAddition(const OctreeNode* parent, OctreeNode* child); + void handleChildAddition(const OctreeNode* parent, OctreeNode* child) override; //virtual BOOL isRecentlyVisible() const; - LLViewerOctreePartition* getSpatialPartition()const {return mSpatialPartition;} + //LLViewerOctreePartition* getSpatialPartition()const {return mSpatialPartition;} + BOOL isAnyRecentlyVisible() const; static U32 getNewOcclusionQueryObjectName(); static void releaseOcclusionQueryObjectName(U32 name); @@ -323,7 +331,8 @@ class LLOcclusionCullingGroup : public LLViewerOctreeGroup S32 mLODHash; - LLViewerOctreePartition* mSpatialPartition; + friend class LLViewerOctreePartition; + LLSpatialPartition* mSpatialPartition; U32 mOcclusionQuery[LLViewerCamera::NUM_CAMERAS]; public: @@ -342,11 +351,13 @@ class LLViewerOctreePartition public: U32 mPartitionType; - U32 mDrawableType; - OctreeNode* mOctree; - BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed - U32 mLODSeed; - U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed) + U32 mDrawableType; + OctreeRoot* mOctree; + LLViewerRegion* mRegionp; // the region this partition belongs to. + BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed + U32 mLODSeed; + U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed) + std::vector mGroups; }; class LLViewerOctreeCull : public OctreeTraveler diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index f5b2a8abe1..34f038cf1b 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -121,20 +121,18 @@ LLViewerParcelMgr::LLViewerParcelMgr() mHoverRequestResult(0), mHoverWestSouth(), mHoverEastNorth(), + mCollisionRegionHandle(0), + mCollisionUpdateSignal(nullptr), mRenderCollision(FALSE), mRenderSelection(TRUE), mCollisionBanned(0), mCollisionTimer(), -// [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3.0) - mCollisionRegionHandle(0), - mCollisionUpdateSignal(NULL), -// [/SL:KB] mMediaParcelId(0), - mMediaRegionId(0), - mHighlightSegments(NULL), - mCollisionSegments(NULL), - mAgentParcelOverlay(NULL), - mParcelsPerEdge(0) + mHighlightSegments(nullptr), + mCollisionSegments(nullptr), + mAgentParcelOverlay(nullptr), + mParcelsPerEdge(0), + mMediaRegionId(0) { mCurrentParcel = new LLParcel(); mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel); @@ -144,17 +142,12 @@ LLViewerParcelMgr::LLViewerParcelMgr() mHoverParcel = new LLParcel(); mCollisionParcel = new LLParcel(); -// Aurora Sim - mParcelsPerEdge = S32(8192.f / PARCEL_GRID_STEP_METERS); // 8192 is the maximum region size on Aurora and solves the audio problem. - //mParcelsPerEdge = S32( REGION_WIDTH_METERS / PARCEL_GRID_STEP_METERS ); -// Aurora Sim + mParcelsPerEdge = S32(8192.f / PARCEL_GRID_STEP_METERS); // 8192 is the maximum region size on WhiteCore and solves the audio problem. mHighlightSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)]; resetSegments(mHighlightSegments); -// [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3.0) mCollisionBitmap = new U8[getCollisionBitmapSize()]; memset(mCollisionBitmap, 0, getCollisionBitmapSize()); -// [/SL:KB] mCollisionSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)]; resetSegments(mCollisionSegments); @@ -162,8 +155,8 @@ LLViewerParcelMgr::LLViewerParcelMgr() // JC: Resolved a merge conflict here, eliminated // mBlockedImage->setAddressMode(LLTexUnit::TAM_WRAP); // because it is done in llviewertexturelist.cpp - mBlockedImage = LLViewerTextureManager::getFetchedTextureFromFile("noentrylines.j2c"); - mPassImage = LLViewerTextureManager::getFetchedTextureFromFile("noentrypasslines.j2c"); + mBlockedImage = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png"); + mPassImage = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png"); S32 overlay_size = mParcelsPerEdge * mParcelsPerEdge / PARCEL_OVERLAY_CHUNKS; sPackedOverlay = new U8[overlay_size]; @@ -175,19 +168,14 @@ LLViewerParcelMgr::LLViewerParcelMgr() mAgentParcelOverlay[i] = 0; } -// Aurora Sim mParcelsPerEdge = S32(REGION_WIDTH_METERS / PARCEL_GRID_STEP_METERS); -// Aurora Sim - mTeleportInProgress = TRUE; // the initial parcel update is treated like teleport } -// Aurora Sim void LLViewerParcelMgr::init(F32 region_size) { mParcelsPerEdge = S32(region_size / PARCEL_GRID_STEP_METERS); } -// Aurora Sim LLViewerParcelMgr::~LLViewerParcelMgr() { @@ -212,10 +200,8 @@ LLViewerParcelMgr::~LLViewerParcelMgr() delete[] mHighlightSegments; mHighlightSegments = NULL; -// [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3.0) delete[] mCollisionBitmap; mCollisionBitmap = NULL; -// [/SL:KB] delete[] mCollisionSegments; mCollisionSegments = NULL; @@ -239,11 +225,9 @@ void LLViewerParcelMgr::dump() mCurrentParcel->dump(); LL_INFOS() << "banning " << mCurrentParcel->mBanList.size() << LL_ENDL; - access_map_const_iterator cit = mCurrentParcel->mBanList.begin(); - access_map_const_iterator end = mCurrentParcel->mBanList.end(); - for ( ; cit != end; ++cit) + for (const auto& pair : mCurrentParcel->mBanList) { - LL_INFOS() << "ban id " << (*cit).first << LL_ENDL; + LL_INFOS() << "ban id " << pair.first << LL_ENDL; } LL_INFOS() << "Hover parcel:" << LL_ENDL; mHoverParcel->dump(); @@ -252,7 +236,7 @@ void LLViewerParcelMgr::dump() } -LLViewerRegion* LLViewerParcelMgr::getSelectionRegion() +LLViewerRegion* LLViewerParcelMgr::getSelectionRegion() const { return LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth ); } @@ -472,14 +456,9 @@ LLParcelSelectionHandle LLViewerParcelMgr::selectParcelInRectangle() void LLViewerParcelMgr::selectCollisionParcel() { // BUG: Claim to be in the agent's region -// Aurora Sim - //mWestSouth = gAgent.getRegion()->getOriginGlobal(); - //mEastNorth = mWestSouth; - //mEastNorth += LLVector3d(PARCEL_GRID_STEP_METERS, PARCEL_GRID_STEP_METERS, 0.0); mWestSouth = getSelectionRegion()->getOriginGlobal(); mEastNorth = mWestSouth; mEastNorth += LLVector3d(getSelectionRegion()->getWidth()/REGION_WIDTH_METERS * PARCEL_GRID_STEP_METERS, getSelectionRegion()->getWidth()/REGION_WIDTH_METERS * PARCEL_GRID_STEP_METERS, 0.0); -// Aurora Sim // BUG: must be in the sim you are in LLMessageSystem *msg = gMessageSystem; @@ -891,8 +870,8 @@ LLParcel* LLViewerParcelMgr::getCollisionParcel() const void LLViewerParcelMgr::render() { - static const LLCachedControl RenderParcelSelection("RenderParcelSelection"); - if (mSelected && mRenderSelection && RenderParcelSelection) + static const LLCachedControl render_parcel_selection(gSavedSettings, "RenderParcelSelection"); + if (mSelected && mRenderSelection && render_parcel_selection) { // Rendering is done in agent-coordinates, so need to supply // an appropriate offset to the render code. @@ -912,8 +891,8 @@ void LLViewerParcelMgr::renderParcelCollision() mRenderCollision = FALSE; } - static const LLCachedControl ShowBanLines("ShowBanLines"); - if (mRenderCollision && ShowBanLines) + static const LLCachedControl render_ban_line(gSavedSettings, "ShowBanLines"); + if (mRenderCollision && render_ban_line) { LLViewerRegion* regionp = gAgent.getRegion(); if (regionp) @@ -936,7 +915,7 @@ void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags) if (!region) return; LLMessageSystem *msg = gMessageSystem; - + if (flags & AL_BAN) { @@ -946,6 +925,14 @@ void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags) { mCurrentParcel->mAccessList.clear(); } + if (flags & AL_ALLOW_EXPERIENCE) + { + mCurrentParcel->clearExperienceKeysByType(EXPERIENCE_KEY_TYPE_ALLOWED); + } + if (flags & AL_BLOCK_EXPERIENCE) + { + mCurrentParcel->clearExperienceKeysByType(EXPERIENCE_KEY_TYPE_BLOCKED); + } // Only the headers differ msg->newMessageFast(_PREHASH_ParcelAccessListRequest); @@ -1322,10 +1309,13 @@ const std::string& LLViewerParcelMgr::getAgentParcelName() const void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_agent_region) { - if(!parcel) return; + if (!parcel) + return; LLViewerRegion *region = use_agent_region ? gAgent.getRegion() : LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth ); - if (!region) return; + if (!region) + return; + //LL_INFOS() << "found region: " << region->getName() << LL_ENDL; LLSD body; @@ -1338,6 +1328,7 @@ void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_ag parcel->packMessage(body); LL_INFOS() << "Sending parcel properties update via capability to: " << url << LL_ENDL; + LLHTTPClient::post(url, body, new LLHTTPClient::ResponderIgnore); } else @@ -1365,10 +1356,8 @@ void LLViewerParcelMgr::setHoverParcel(const LLVector3d& pos) static U32 last_west, last_south; // only request parcel info when tooltip is shown - if (!gSavedSettings.getBOOL("ShowLandHoverTip")) - { - return; - } + if (!gSavedSettings.getBOOL("ShowLandHoverTip")) return; + // only request parcel info if position has changed outside of the // last parcel grid step U32 west_parcel_step = (U32) floor( pos.mdV[VX] / PARCEL_GRID_STEP_METERS ); @@ -1390,6 +1379,7 @@ void LLViewerParcelMgr::setHoverParcel(const LLVector3d& pos) return; } + // Send a rectangle around the point. // This means the parcel sent back is at least a rectangle around the point, // which is more efficient for public land. Fewer requests are sent. JC @@ -1437,11 +1427,7 @@ void LLViewerParcelMgr::processParcelOverlay(LLMessageSystem *msg, void **user) return; } -// Aurora Sim - //S32 parcels_per_edge = LLViewerParcelMgr::getInstance()->mParcelsPerEdge; - //S32 expected_size = parcels_per_edge * parcels_per_edge / PARCEL_OVERLAY_CHUNKS; S32 expected_size = 1024; -// Aurora Sim if (packed_overlay_size != expected_size) { LL_WARNS() << "Got parcel overlay size " << packed_overlay_size @@ -1504,13 +1490,11 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use S32 other_clean_time = 0; LLViewerParcelMgr& parcel_mgr = LLViewerParcelMgr::instance(); -// Aurora Sim LLViewerRegion* msg_region = LLWorld::getInstance()->getRegion(msg->getSender()); if(msg_region) parcel_mgr.mParcelsPerEdge = S32(msg_region->getWidth() / PARCEL_GRID_STEP_METERS); else parcel_mgr.mParcelsPerEdge = S32(gAgent.getRegion()->getWidth() / PARCEL_GRID_STEP_METERS); -// Aurora Sim msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_RequestResult, request_result ); msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SequenceID, sequence_id ); @@ -1624,6 +1608,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use if (parcel == parcel_mgr.mAgentParcel) { + // new agent parcel S32 bitmap_size = parcel_mgr.mParcelsPerEdge * parcel_mgr.mParcelsPerEdge / 8; @@ -1636,6 +1621,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use // Let interesting parties know about agent parcel change. LLViewerParcelMgr* instance = LLViewerParcelMgr::getInstance(); + // Notify anything that wants to know when the agent changes parcels instance->mAgentParcelChangedSignal(); if (instance->mTeleportInProgress) @@ -1714,7 +1700,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use } // Request access list information for this land - parcel_mgr.sendParcelAccessListRequest(AL_ACCESS | AL_BAN); + parcel_mgr.sendParcelAccessListRequest(AL_ACCESS | AL_BAN | AL_ALLOW_EXPERIENCE | AL_BLOCK_EXPERIENCE); // Request dwell for this land, if it's not public land. parcel_mgr.mSelectedDwell = DWELL_NAN; @@ -1819,7 +1805,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use // If there is a new music URL and it's valid, play it. if (music_url.size() > 12) { - if (music_url.substr(0,7) == "http://") + if (music_url.substr(0,7) == "http://" + || music_url.substr(0, 8) == "https://") { optionally_start_music(parcel); } @@ -1827,12 +1814,14 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use { LL_INFOS() << "Stopping parcel music (invalid audio stream URL)" << LL_ENDL; // clears the URL + // null value causes fade out gAudiop->startInternetStream(LLStringUtil::null); } } else if (!gAudiop->getInternetStreamURL().empty()) { LL_INFOS() << "Stopping parcel music (parcel stream URL is empty)" << LL_ENDL; + // null value causes fade out gAudiop->startInternetStream(LLStringUtil::null); } } @@ -1857,7 +1846,7 @@ void optionally_start_music(LLParcel* parcel) // changed as part of SL-4878 if (gOverlayBar && gOverlayBar->musicPlaying()) { - LLPanelNearByMedia* nearby_media_panel = LLFloaterNearbyMedia::instanceExists() ? LLFloaterNearbyMedia::getInstance()->getMediaPanel() : NULL; + LLPanelNearByMedia* nearby_media_panel = LLFloaterNearbyMedia::instanceExists() ? LLFloaterNearbyMedia::getInstance()->getMediaPanel() : nullptr; if ((nearby_media_panel && nearby_media_panel->getParcelAudioAutoStart()) || // or they have expressed no opinion in the UI, but have autoplay on... @@ -1865,6 +1854,7 @@ void optionally_start_music(LLParcel* parcel) /*gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&*/ gSavedSettings.getBOOL("MediaTentativeAutoPlay"))) { + LL_INFOS() << "Starting parcel music " << parcel->getMusicURL() << LL_ENDL; LLViewerParcelMedia::playStreamingMusic(parcel); return; } @@ -1891,7 +1881,7 @@ void LLViewerParcelMgr::processParcelAccessListReply(LLMessageSystem *msg, void if (parcel_id != parcel->getLocalID()) { - LL_WARNS() << "processParcelAccessListReply for parcel " << parcel_id + LL_WARNS_ONCE("") << "processParcelAccessListReply for parcel " << parcel_id << " which isn't the selected parcel " << parcel->getLocalID()<< LL_ENDL; return; } @@ -1904,6 +1894,14 @@ void LLViewerParcelMgr::processParcelAccessListReply(LLMessageSystem *msg, void { parcel->unpackAccessEntries(msg, &(parcel->mBanList) ); } + else if (message_flags & AL_ALLOW_EXPERIENCE) + { + parcel->unpackExperienceEntries(msg, EXPERIENCE_KEY_TYPE_ALLOWED); + } + else if (message_flags & AL_BLOCK_EXPERIENCE) + { + parcel->unpackExperienceEntries(msg, EXPERIENCE_KEY_TYPE_BLOCKED); + } /*else if (message_flags & AL_RENTER) { parcel->unpackAccessEntries(msg, &(parcel->mRenterList) ); @@ -1938,10 +1936,6 @@ void LLViewerParcelMgr::processParcelDwellReply(LLMessageSystem* msg, void**) void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which) { - - LLUUID transactionUUID; - transactionUUID.generate(); - if (!mSelected) { return; @@ -1950,125 +1944,95 @@ void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which) LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth ); if (!region) return; - LLMessageSystem* msg = gMessageSystem; - LLParcel* parcel = mCurrentParcel; if (!parcel) return; if (which & AL_ACCESS) - { - S32 count = parcel->mAccessList.size(); - S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET); - S32 sequence_id = 1; - BOOL start_message = TRUE; - BOOL initial = TRUE; - - access_map_const_iterator cit = parcel->mAccessList.begin(); - access_map_const_iterator end = parcel->mAccessList.end(); - while ( (cit != end) || initial ) - { - if (start_message) - { - msg->newMessageFast(_PREHASH_ParcelAccessListUpdate); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - msg->nextBlockFast(_PREHASH_Data); - msg->addU32Fast(_PREHASH_Flags, AL_ACCESS); - msg->addS32(_PREHASH_LocalID, parcel->getLocalID() ); - msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID); - msg->addS32Fast(_PREHASH_SequenceID, sequence_id); - msg->addS32Fast(_PREHASH_Sections, num_sections); - start_message = FALSE; - - if (initial && (cit == end)) - { - // pack an empty block if there will be no data - msg->nextBlockFast(_PREHASH_List); - msg->addUUIDFast(_PREHASH_ID, LLUUID::null ); - msg->addS32Fast(_PREHASH_Time, 0 ); - msg->addU32Fast(_PREHASH_Flags, 0 ); - } - - initial = FALSE; - sequence_id++; + { + sendParcelAccessListUpdate(AL_ACCESS, parcel->mAccessList, region, parcel->getLocalID()); + } - } - - while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES)) - { + if (which & AL_BAN) + { + sendParcelAccessListUpdate(AL_BAN, parcel->mBanList, region, parcel->getLocalID()); + } - const LLAccessEntry& entry = (*cit).second; - - msg->nextBlockFast(_PREHASH_List); - msg->addUUIDFast(_PREHASH_ID, entry.mID ); - msg->addS32Fast(_PREHASH_Time, entry.mTime ); - msg->addU32Fast(_PREHASH_Flags, entry.mFlags ); - ++cit; - } + if (which & AL_ALLOW_EXPERIENCE) + { + sendParcelAccessListUpdate(AL_ALLOW_EXPERIENCE, parcel->getExperienceKeysByType(EXPERIENCE_KEY_TYPE_ALLOWED), region, parcel->getLocalID()); + } - start_message = TRUE; - msg->sendReliable( region->getHost() ); - } + if (which & AL_BLOCK_EXPERIENCE) + { + sendParcelAccessListUpdate(AL_BLOCK_EXPERIENCE, parcel->getExperienceKeysByType(EXPERIENCE_KEY_TYPE_BLOCKED), region, parcel->getLocalID()); } +} - if (which & AL_BAN) - { - S32 count = parcel->mBanList.size(); - S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET); - S32 sequence_id = 1; - BOOL start_message = TRUE; - BOOL initial = TRUE; - - access_map_const_iterator cit = parcel->mBanList.begin(); - access_map_const_iterator end = parcel->mBanList.end(); - while ( (cit != end) || initial ) - { - if (start_message) - { - msg->newMessageFast(_PREHASH_ParcelAccessListUpdate); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - msg->nextBlockFast(_PREHASH_Data); - msg->addU32Fast(_PREHASH_Flags, AL_BAN); - msg->addS32(_PREHASH_LocalID, parcel->getLocalID() ); - msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID); - msg->addS32Fast(_PREHASH_SequenceID, sequence_id); - msg->addS32Fast(_PREHASH_Sections, num_sections); - start_message = FALSE; - - if (initial && (cit == end)) - { - // pack an empty block if there will be no data - msg->nextBlockFast(_PREHASH_List); - msg->addUUIDFast(_PREHASH_ID, LLUUID::null ); - msg->addS32Fast(_PREHASH_Time, 0 ); - msg->addU32Fast(_PREHASH_Flags, 0 ); - } +void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 flags, const LLAccessEntry::map& entries, LLViewerRegion* region, S32 parcel_local_id) +{ + S32 count = entries.size(); + S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET); + S32 sequence_id = 1; + BOOL start_message = TRUE; + BOOL initial = TRUE; - initial = FALSE; - sequence_id++; - } - - while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES)) + LLUUID transactionUUID; + transactionUUID.generate(); + + + LLMessageSystem* msg = gMessageSystem; + + LLAccessEntry::map::const_iterator cit = entries.begin(); + LLAccessEntry::map::const_iterator end = entries.end(); + while ( (cit != end) || initial ) + { + if (start_message) + { + msg->newMessageFast(_PREHASH_ParcelAccessListUpdate); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + msg->nextBlockFast(_PREHASH_Data); + msg->addU32Fast(_PREHASH_Flags, flags); + msg->addS32(_PREHASH_LocalID, parcel_local_id); + msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID); + msg->addS32Fast(_PREHASH_SequenceID, sequence_id); + msg->addS32Fast(_PREHASH_Sections, num_sections); + start_message = FALSE; + + if (initial && (cit == end)) { - const LLAccessEntry& entry = (*cit).second; - + // pack an empty block if there will be no data msg->nextBlockFast(_PREHASH_List); - msg->addUUIDFast(_PREHASH_ID, entry.mID ); - msg->addS32Fast(_PREHASH_Time, entry.mTime ); - msg->addU32Fast(_PREHASH_Flags, entry.mFlags ); - ++cit; + msg->addUUIDFast(_PREHASH_ID, LLUUID::null ); + msg->addS32Fast(_PREHASH_Time, 0 ); + msg->addU32Fast(_PREHASH_Flags, 0 ); } - start_message = TRUE; - msg->sendReliable( region->getHost() ); + initial = FALSE; + sequence_id++; + } + + while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES)) + { + + const LLAccessEntry& entry = (*cit).second; + + msg->nextBlockFast(_PREHASH_List); + msg->addUUIDFast(_PREHASH_ID, entry.mID ); + msg->addS32Fast(_PREHASH_Time, entry.mTime ); + msg->addU32Fast(_PREHASH_Flags, entry.mFlags ); + ++cit; + } + + start_message = TRUE; + msg->sendReliable( region->getHost() ); } } + void LLViewerParcelMgr::deedLandToGroup() { std::string group_name; @@ -2597,11 +2561,9 @@ void LLViewerParcelMgr::onTeleportFailed() mTeleportFailedSignal(); } -// [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3.0) boost::signals2::connection LLViewerParcelMgr::setCollisionUpdateCallback(const collision_update_signal_t::slot_type & cb) { if (!mCollisionUpdateSignal) mCollisionUpdateSignal = new collision_update_signal_t(); return mCollisionUpdateSignal->connect(cb); } -// [/SL:KB] diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index b9520932d1..fbd829718b 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -33,12 +33,6 @@ #include "llparcelselection.h" #include "llui.h" -#ifndef BOOST_FUNCTION_HPP_INCLUDED -#include -#define BOOST_FUNCTION_HPP_INCLUDED -#endif -#include - class LLUUID; class LLMessageSystem; class LLParcel; @@ -78,26 +72,24 @@ class LLParcelObserver class LLViewerParcelMgr : public LLSingleton { + friend class LLSingleton; + LLViewerParcelMgr(); + ~LLViewerParcelMgr(); public: - typedef boost::function teleport_finished_callback_t; + typedef std::function teleport_finished_callback_t; typedef boost::signals2::signal teleport_finished_signal_t; - typedef boost::function parcel_changed_callback_t; + typedef std::function parcel_changed_callback_t; typedef boost::signals2::signal parcel_changed_signal_t; - LLViewerParcelMgr(); - ~LLViewerParcelMgr(); - -// Aurora Sim void init(F32 region_size); -// Aurora Sim static void cleanupGlobals(); BOOL selectionEmpty() const; F32 getSelectionWidth() const { return F32(mEastNorth.mdV[VX] - mWestSouth.mdV[VX]); } F32 getSelectionHeight() const { return F32(mEastNorth.mdV[VY] - mWestSouth.mdV[VY]); } BOOL getSelection(LLVector3d &min, LLVector3d &max) { min = mWestSouth; max = mEastNorth; return !selectionEmpty();} - LLViewerRegion* getSelectionRegion(); + LLViewerRegion* getSelectionRegion() const; F32 getDwelling() const { return mSelectedDwell;} void getDisplayInfo(S32* area, S32* claim, S32* rent, BOOL* for_sale, F32* dwell); @@ -168,14 +160,13 @@ class LLViewerParcelMgr : public LLSingleton LLParcel* getHoverParcel() const; LLParcel* getCollisionParcel() const; -// [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3.0) + const U8* getCollisionBitmap() const { return mCollisionBitmap; } size_t getCollisionBitmapSize() const { return mParcelsPerEdge * mParcelsPerEdge / 8; } U64 getCollisionRegionHandle() const { return mCollisionRegionHandle; } typedef boost::signals2::signal collision_update_signal_t; boost::signals2::connection setCollisionUpdateCallback(const collision_update_signal_t::slot_type & cb); -// [/SL:KB] // Can this agent build on the parcel he is on? // Used for parcel property icons in nav bar. @@ -304,6 +295,8 @@ class LLViewerParcelMgr : public LLSingleton static BOOL isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power); private: + static void sendParcelAccessListUpdate(U32 flags, const std::map& entries, LLViewerRegion* region, S32 parcel_local_id); + static void sendParcelExperienceUpdate( const U32 flags, uuid_vec_t experience_ids, LLViewerRegion* region, S32 parcel_local_id ); static bool releaseAlertCB(const LLSD& notification, const LLSD& response); // If the user is claiming land and the current selection @@ -368,11 +361,9 @@ class LLViewerParcelMgr : public LLSingleton // Watch for pending collisions with a parcel you can't access. // If it's coming, draw the parcel's boundaries. LLParcel* mCollisionParcel; -// [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3.0) U8* mCollisionBitmap; U64 mCollisionRegionHandle; collision_update_signal_t* mCollisionUpdateSignal; -// [/SL:KB] U8* mCollisionSegments; BOOL mRenderCollision; BOOL mRenderSelection; diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index a0608e4ccd..d172cbc7e4 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -647,7 +647,7 @@ void LLViewerPartSim::shift(const LLVector3 &offset) } } -static LLFastTimer::DeclareTimer FTM_SIMULATE_PARTICLES("Simulate Particles"); +static LLTrace::BlockTimerStatHandle FTM_SIMULATE_PARTICLES("Simulate Particles"); void LLViewerPartSim::updateSimulation() { @@ -662,7 +662,7 @@ void LLViewerPartSim::updateSimulation() return; } - LLFastTimer ftm(FTM_SIMULATE_PARTICLES); + LL_RECORD_BLOCK_TIME(FTM_SIMULATE_PARTICLES); // Start at a random particle system so the same // particle system doesn't always get first pick at the diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index 187e71a72a..44d52371f4 100644 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -41,21 +41,7 @@ #include "linden_common.h" -// We may want to take the windows.h include out, but it used to be in -// linden_common.h, and hence in all the libraries. This is better. JC -#if LL_WINDOWS - // Limit Windows API to small and manageable set. - // If you get undefined symbols, find the appropriate - // Windows header file and include that in your .cpp file. - #define WIN32_LEAN_AND_MEAN - #include - #include -#endif - -// Work around stupid Microsoft STL warning -#ifdef LL_WINDOWS -#pragma warning (disable : 4702) // warning C4702: unreachable code -#endif +#include "llwin32headerslean.h" #include #include diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index f4a01b0fb9..d8291f9d10 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -52,6 +52,8 @@ #include "lfsimfeaturehandler.h" #include "llagent.h" #include "llagentcamera.h" + +#include "llavatarrenderinfoaccountant.h" #include "llcallingcard.h" #include "llcaphttpsender.h" #include "llcapabilitylistener.h" @@ -61,7 +63,6 @@ #include "llfloateravatarlist.h" #include "llfloatergodtools.h" #include "llfloaterperms.h" -#include "llfloaterreporter.h" #include "llfloaterregioninfo.h" #include "llhttpnode.h" #include "llregioninfomodel.h" @@ -106,6 +107,19 @@ typedef std::map CapabilityMap; static void log_capabilities(const CapabilityMap &capmap); + +namespace +{ + +void newRegionEntry(LLViewerRegion& region) +{ + LL_INFOS("LLViewerRegion") << "Entering region [" << region.getName() << "]" << LL_ENDL; + gDebugInfo["CurrentRegion"] = region.getName(); + LLAppViewer::instance()->writeDebugInfo(); +} + +} // anonymous namespace + class LLViewerRegionImpl { public: LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host) @@ -116,6 +130,7 @@ class LLViewerRegionImpl { mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN), mSeedCapAttempts(0), mHttpResponderID(0), + mLandp(NULL), // I'd prefer to set the LLCapabilityListener name to match the region // name -- it's disappointing that's not available at construction time. // We could instead store an LLCapabilityListener*, making @@ -415,7 +430,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, mColoName("unknown"), mProductSKU("unknown"), mProductName("unknown"), - mHttpUrl(""), + mViewerAssetUrl(""), mCacheLoaded(FALSE), mCacheDirty(FALSE), mReleaseNotesRequested(FALSE), @@ -474,21 +489,24 @@ void LLViewerRegion::initPartitions() { //create object partitions //MUST MATCH declaration of eObjectPartitions - mImpl->mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD - mImpl->mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN - mImpl->mObjectPartition.push_back(new LLVoidWaterPartition()); //PARTITION_VOIDWATER - mImpl->mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER - mImpl->mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE - mImpl->mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE + mImpl->mObjectPartition.push_back(new LLHUDPartition(this)); //PARTITION_HUD + mImpl->mObjectPartition.push_back(new LLTerrainPartition(this)); //PARTITION_TERRAIN + mImpl->mObjectPartition.push_back(new LLVoidWaterPartition(this)); //PARTITION_VOIDWATER + mImpl->mObjectPartition.push_back(new LLWaterPartition(this)); //PARTITION_WATER + mImpl->mObjectPartition.push_back(new LLTreePartition(this)); //PARTITION_TREE + mImpl->mObjectPartition.push_back(new LLParticlePartition(this)); //PARTITION_PARTICLE #if ENABLE_CLASSIC_CLOUDS - mImpl->mObjectPartition.push_back(new LLCloudPartition()); //PARTITION_CLOUD + mImpl->mObjectPartition.push_back(new LLCloudPartition(this)); //PARTITION_CLOUD #endif - mImpl->mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS - mImpl->mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME - mImpl->mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE - mImpl->mObjectPartition.push_back(new LLAttachmentPartition()); //PARTITION_ATTACHMENT - mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE + mImpl->mObjectPartition.push_back(new LLGrassPartition(this)); //PARTITION_GRASS + mImpl->mObjectPartition.push_back(new LLVolumePartition(this)); //PARTITION_VOLUME + mImpl->mObjectPartition.push_back(new LLBridgePartition(this)); //PARTITION_BRIDGE + mImpl->mObjectPartition.push_back(new LLAttachmentPartition(this)); //PARTITION_ATTACHMENT + mImpl->mObjectPartition.push_back(new LLHUDParticlePartition(this));//PARTITION_HUD_PARTICLE mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE + + mRenderInfoRequestTimer.resetWithExpiry(0.f); // Set timer to be expired + setCapabilitiesReceivedCallback(boost::bind(&LLAvatarRenderInfoAccountant::expireRenderInfoReportTimer, _1)); } void LLViewerRegion::reInitPartitions() @@ -502,14 +520,14 @@ void LLViewerRegion::initStats() { mImpl->mLastNetUpdate.reset(); mPacketsIn = 0; - mBitsIn = 0; - mLastBitsIn = 0; + mBitsIn = (U32Bits)0; + mLastBitsIn = (U32Bits)0; mLastPacketsIn = 0; mPacketsOut = 0; mLastPacketsOut = 0; mPacketsLost = 0; mLastPacketsLost = 0; - mPingDelay = 0; + mPingDelay = (U32Seconds)0; mAlive = false; // can become false if circuit disconnects } @@ -899,7 +917,6 @@ void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**) LLRegionInfoModel::instance().update(msg); LLFloaterGodTools::processRegionInfo(msg); LLFloaterRegionInfo::processRegionInfo(msg); - LLFloaterReporter::processRegionInfo(msg); } void LLViewerRegion::setCacheID(const LLUUID& id) @@ -929,6 +946,10 @@ void LLViewerRegion::dirtyHeights() } } +void LLViewerRegion::clearCachedVisibleObjects() +{ +} + BOOL LLViewerRegion::idleUpdate(F32 max_update_time) { // did_update returns TRUE if we did at least one significant update @@ -958,6 +979,7 @@ void LLViewerRegion::forceUpdate() void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction) { mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction); + neighborp->mImpl->mLandp->connectNeighbor(mImpl->mLandp, gDirOpposite[direction]); #if ENABLE_CLASSIC_CLOUDS mCloudLayer.connectNeighbor(&(neighborp->mCloudLayer), direction); #endif @@ -1129,7 +1151,7 @@ void LLViewerRegion::updateNetStats() mPacketsLost = cdp->getPacketsLost(); mPingDelay = cdp->getPingDelay(); - mBitStat.addValue(mBitsIn - mLastBitsIn); + mBitStat.addValue((mBitsIn - mLastBitsIn).value()); mPacketsStat.addValue(mPacketsIn - mLastPacketsIn); mPacketsLostStat.addValue(mPacketsLost); } @@ -1229,7 +1251,7 @@ const LLViewerRegion::tex_matrix_t& LLViewerRegion::getWorldMapTiles() const for (U32 x = 0; x != totalX; ++x) for (U32 y = 0; y != totalY; ++y) { - LLPointer tex(LLViewerTextureManager::getFetchedTextureFromUrl(strImgURL+llformat("%d-%d-objects.jpg", gridX + x, gridY + y), TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + LLPointer tex(LLViewerTextureManager::getFetchedTextureFromUrl(strImgURL+llformat("%d-%d-objects.jpg", gridX + x, gridY + y), FTT_MAP_TILE, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); mWorldMapTiles.push_back(tex); tex->setBoostLevel(LLViewerTexture::BOOST_MAP); } @@ -1286,10 +1308,11 @@ class CoarseLocationUpdate : public LLHTTPNode S32 target_index = input["body"]["Index"][0]["Prey"].asInteger(); S32 you_index = input["body"]["Index"][0]["You" ].asInteger(); - std::vector* avatar_locs = ®ion->mMapAvatars; - std::vector* avatar_ids = ®ion->mMapAvatarIDs; - avatar_locs->clear(); - avatar_ids->clear(); + std::vector& avatar_locs = region->mMapAvatars; + uuid_vec_t& avatar_ids = region->mMapAvatarIDs; + std::list map_avids(avatar_ids.begin(), avatar_ids.end()); + avatar_locs.clear(); + avatar_ids.clear(); //LL_INFOS() << "coarse locations agent[0] " << input["body"]["AgentData"][0]["AgentID"].asUUID() << LL_ENDL; //LL_INFOS() << "my agent id = " << gAgent.getID() << LL_ENDL; @@ -1329,13 +1352,14 @@ class CoarseLocationUpdate : public LLHTTPNode pos |= y; pos <<= 8; pos |= z; - avatar_locs->push_back(pos); + avatar_locs.push_back(pos); //LL_INFOS() << "next pos: " << x << "," << y << "," << z << ": " << pos << LL_ENDL; if(has_agent_data) // for backwards compatibility with old message format { LLUUID agent_id(agents_it->get("AgentID").asUUID()); //LL_INFOS() << "next agent: " << agent_id.asString() << LL_ENDL; - avatar_ids->push_back(agent_id); + avatar_ids.push_back(agent_id); + map_avids.remove(agent_id); } } if (has_agent_data) @@ -1343,6 +1367,12 @@ class CoarseLocationUpdate : public LLHTTPNode agents_it++; } } + if (LLFloaterAvatarList::instanceExists()) + { + LLFloaterAvatarList& inst(LLFloaterAvatarList::instance()); + inst.updateAvatarList(region); + inst.expireAvatarList(map_avids); + } } }; @@ -1433,6 +1463,81 @@ void LLViewerRegion::getInfo(LLSD& info) info["Region"]["Handle"]["y"] = (LLSD::Integer)y; } +class BaseFeaturesReceived : public LLHTTPClient::ResponderWithResult +{ + LOG_CLASS(BaseFeaturesReceived); +public: + BaseFeaturesReceived(const std::string& retry_url, U64 region_handle, const char* classname, boost::function fn, + S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS) + : mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts), mClassName(classname), mFunction(fn) + { } + + + void httpFailure(void) + { + LL_WARNS("AppInit", mClassName) << dumpResponse() << LL_ENDL; + retry(); + } + + void httpSuccess(void) + { + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if (!regionp) //region is removed or responder is not created. + { + LL_WARNS("AppInit", mClassName) + << "Received results for region that no longer exists!" << LL_ENDL; + return; + } + + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(400, "Malformed response contents", content); + return; + } + mFunction(regionp, content); + } + + /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return baseFeaturesReceived_timeout; } + /*virtual*/ char const* getName(void) const { return mClassName; } + +private: + + void retry() + { + if (mAttempt < mMaxAttempts) + { + mAttempt++; + LL_WARNS("AppInit", mClassName) << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL; + LLHTTPClient::get(mRetryURL, new BaseFeaturesReceived(*this)); + } + } + + std::string mRetryURL; + U64 mRegionHandle; + S32 mAttempt; + S32 mMaxAttempts; + const char* mClassName; + boost::function mFunction; +}; + +void LLViewerRegion::requestSimulatorFeatures() +{ + LL_DEBUGS("SimulatorFeatures") << "region " << getName() << " ptr " << this + << " trying to request SimulatorFeatures" << LL_ENDL; + // kick off a request for simulator features + std::string url = getCapability("SimulatorFeatures"); + if (!url.empty()) + { + // kick off a request for simulator features + LLHTTPClient::get(url, new BaseFeaturesReceived(url, getHandle(), "SimulatorFeaturesReceived", &LLViewerRegion::setSimulatorFeatures)); + } + else + { + LL_WARNS("AppInit", "SimulatorFeatures") << "SimulatorFeatures cap not set" << LL_ENDL; + } +} + boost::signals2::connection LLViewerRegion::setSimulatorFeaturesReceivedCallback(const caps_received_signal_t::slot_type& cb) { return mSimulatorFeaturesReceivedSignal.connect(cb); @@ -1453,7 +1558,7 @@ bool LLViewerRegion::simulatorFeaturesReceived() const return mSimulatorFeaturesReceived; } -void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features) +void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features) const { sim_features = mSimulatorFeatures; } @@ -1463,10 +1568,11 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) std::stringstream str; LLSDSerialize::toPrettyXML(sim_features, str); - LL_DEBUGS("SimFeatures") << "\n" << str.str() << LL_ENDL; + LL_INFOS() << "region " << getName() << " " << str.str() << LL_ENDL; mSimulatorFeatures = sim_features; setSimulatorFeaturesReceived(true); + } void LLViewerRegion::setGamingData(const LLSD& gaming_data) @@ -1541,6 +1647,14 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec return result; } +void LLViewerRegion::removeFromCreatedList(U32 local_id) +{ +} + +void LLViewerRegion::addToCreatedList(U32 local_id) +{ +} + // Get data packer for this object, if we have cached data // AND the CRC matches. JC LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type) @@ -1872,29 +1986,52 @@ void LLViewerRegion::unpackRegionHandshake() void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) { + capabilityNames.append("AbuseCategories"); + capabilityNames.append("AcceptFriendship"); + capabilityNames.append("AcceptGroupInvite"); // ReadOfflineMsgs recieved messages only!!! capabilityNames.append("AgentPreferences"); capabilityNames.append("AgentState"); capabilityNames.append("AttachmentResources"); //capabilityNames.append("AvatarPickerSearch"); //Display name/SLID lookup (llfloateravatarpicker.cpp) + capabilityNames.append("AvatarRenderInfo"); capabilityNames.append("CharacterProperties"); capabilityNames.append("ChatSessionRequest"); capabilityNames.append("CopyInventoryFromNotecard"); capabilityNames.append("CreateInventoryCategory"); capabilityNames.append("CustomMenuAction"); + capabilityNames.append("DeclineFriendship"); + capabilityNames.append("DeclineGroupInvite"); // ReadOfflineMsgs recieved messages only!!! capabilityNames.append("DispatchRegionInfo"); + capabilityNames.append("DirectDelivery"); capabilityNames.append("EnvironmentSettings"); + capabilityNames.append("EstateAccess"); capabilityNames.append("EstateChangeInfo"); capabilityNames.append("EventQueueGet"); + capabilityNames.append("ExtEnvironment"); capabilityNames.append("FetchLib2"); capabilityNames.append("FetchLibDescendents2"); capabilityNames.append("FetchInventory2"); capabilityNames.append("FetchInventoryDescendents2"); capabilityNames.append("IncrementCOFVersion"); capabilityNames.append("GamingData"); //Used by certain grids. - AISCommand::getCapabilityNames(capabilityNames); + AISAPI::getCapNames(capabilityNames); + capabilityNames.append("GetDisplayNames"); + capabilityNames.append("GetExperiences"); + capabilityNames.append("AgentExperiences"); + capabilityNames.append("FindExperienceByName"); + capabilityNames.append("GetExperienceInfo"); + capabilityNames.append("GetAdminExperiences"); + capabilityNames.append("GetCreatorExperiences"); + capabilityNames.append("ExperiencePreferences"); + capabilityNames.append("GroupExperiences"); + capabilityNames.append("UpdateExperience"); + capabilityNames.append("IsExperienceAdmin"); + capabilityNames.append("IsExperienceContributor"); + capabilityNames.append("RegionExperiences"); capabilityNames.append("GetMesh"); - capabilityNames.append("GetMesh2"); // Used on SecondLife(tm) sim versions 280647 and higher (13.09.17). + capabilityNames.append("GetMesh2"); + capabilityNames.append("GetMetadata"); capabilityNames.append("GetObjectCost"); capabilityNames.append("GetObjectPhysicsData"); capabilityNames.append("GetTexture"); @@ -1908,6 +2045,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("MeshUploadFlag"); capabilityNames.append("NavMeshGenerationStatus"); capabilityNames.append("NewFileAgentInventory"); + capabilityNames.append("ObjectAnimation"); capabilityNames.append("ObjectMedia"); capabilityNames.append("ObjectMediaNavigate"); capabilityNames.append("ObjectNavMeshProperties"); @@ -1916,6 +2054,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("ParcelVoiceInfoRequest"); capabilityNames.append("ProductInfoRequest"); capabilityNames.append("ProvisionVoiceAccountRequest"); + capabilityNames.append("ReadOfflineMsgs"); // Requires to respond reliably: AcceptFriendship, AcceptGroupInvite, DeclineFriendship, DeclineGroupInvite capabilityNames.append("RemoteParcelRequest"); capabilityNames.append("RenderMaterials"); capabilityNames.append("RequestTextureDownload"); @@ -1945,6 +2084,9 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("UpdateScriptAgent"); capabilityNames.append("UpdateScriptTask"); capabilityNames.append("UploadBakedTexture"); + capabilityNames.append("UserInfo"); + capabilityNames.append("ViewerAsset"); + capabilityNames.append("ViewerBenefits"); capabilityNames.append("ViewerMetrics"); capabilityNames.append("ViewerStartAuction"); capabilityNames.append("ViewerStats"); @@ -1962,6 +2104,9 @@ void LLViewerRegion::setSeedCapability(const std::string& url) LL_DEBUGS("CrossingCaps") << "Received duplicate seed capability, posting to seed " << url << LL_ENDL; + // record that we just entered a new region + newRegionEntry(*this); + //Instead of just returning we build up a second set of seed caps and compare them //to the "original" seed cap received and determine why there is problem! LLSD capabilityNames = LLSD::emptyArray(); @@ -1976,6 +2121,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url) mImpl->mCapabilities.clear(); setCapability("Seed", url); + // record that we just entered a new region + newRegionEntry(*this); LLSD capabilityNames = LLSD::emptyArray(); mImpl->buildCapabilityNames(capabilityNames); @@ -2027,64 +2174,6 @@ void LLViewerRegion::failedSeedCapability() } } -class BaseFeaturesReceived : public LLHTTPClient::ResponderWithResult -{ - LOG_CLASS(BaseFeaturesReceived); -public: - BaseFeaturesReceived(const std::string& retry_url, U64 region_handle, const char* classname, boost::function fn, - S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS) - : mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts), mClassName(classname), mFunction(fn) - { } - - - void httpFailure(void) - { - LL_WARNS("AppInit", mClassName) << dumpResponse() << LL_ENDL; - retry(); - } - - void httpSuccess(void) - { - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); - if(!regionp) //region is removed or responder is not created. - { - LL_WARNS("AppInit", mClassName) - << "Received results for region that no longer exists!" << LL_ENDL; - return ; - } - - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(400, "Malformed response contents", content); - return; - } - mFunction(regionp, content); - } - - /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return baseFeaturesReceived_timeout; } - /*virtual*/ char const* getName(void) const { return mClassName; } - -private: - - void retry() - { - if (mAttempt < mMaxAttempts) - { - mAttempt++; - LL_WARNS("AppInit", mClassName) << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL; - LLHTTPClient::get(mRetryURL, new BaseFeaturesReceived(*this)); - } - } - - std::string mRetryURL; - U64 mRegionHandle; - S32 mAttempt; - S32 mMaxAttempts; - const char* mClassName; - boost::function mFunction; -}; - void LLViewerRegion::setCapability(const std::string& name, const std::string& url) { if(name == "EventQueueGet") @@ -2100,10 +2189,8 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u else if (name == "SimulatorFeatures") { // although this is not needed later, add it so we can check if the sim supports it at all later - mImpl->mCapabilities[name] = url; - - // kick off a request for simulator features - LLHTTPClient::get(url, new BaseFeaturesReceived(url, getHandle(), "SimulatorFeaturesReceived", &LLViewerRegion::setSimulatorFeatures)); + mImpl->mCapabilities["SimulatorFeatures"] = url; + requestSimulatorFeatures(); } else if (name == "GamingData") { @@ -2114,9 +2201,20 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u else { mImpl->mCapabilities[name] = url; - if(name == "GetTexture") + if(name == "ViewerAsset") { - mHttpUrl = url ; + /*==============================================================*/ + // The following inserted lines are a hack for testing MAINT-7081, + // which is why the indentation and formatting are left ugly. + const char* VIEWERASSET = getenv("VIEWERASSET"); + if (VIEWERASSET) + { + mImpl->mCapabilities[name] = VIEWERASSET; + mViewerAssetUrl = VIEWERASSET; + } + else + /*==============================================================*/ + mViewerAssetUrl = url; } } } @@ -2127,9 +2225,20 @@ void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::stri if ( ! ( name == "EventQueueGet" || name == "UntrustedSimulatorMessage" || name == "SimulatorFeatures" ) ) { mImpl->mSecondCapabilitiesTracker[name] = url; - if(name == "GetTexture") + if(name == "ViewerAsset") { - mHttpUrl = url ; + /*==============================================================*/ + // The following inserted lines are a hack for testing MAINT-7081, + // which is why the indentation and formatting are left ugly. + const char* VIEWERASSET = getenv("VIEWERASSET"); + if (VIEWERASSET) + { + mImpl->mSecondCapabilitiesTracker[name] = VIEWERASSET; + mViewerAssetUrl = VIEWERASSET; + } + else + /*==============================================================*/ + mViewerAssetUrl = url; } } @@ -2299,9 +2408,19 @@ bool LLViewerRegion::meshUploadEnabled() const } } +bool LLViewerRegion::bakesOnMeshEnabled() const +{ + return (mSimulatorFeatures.has("BakesOnMeshEnabled") && + mSimulatorFeatures["BakesOnMeshEnabled"].asBoolean()); +} + bool LLViewerRegion::meshRezEnabled() const { - if (getCapability("SimulatorFeatures").empty()) + if (!capabilitiesReceived()) + { + return false; + } + else if (getCapability("SimulatorFeatures").empty()) { return !getCapability("GetMesh").empty() || !getCapability("GetMesh2").empty(); } diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 6a82ffbd8e..b4fed423b2 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -51,8 +51,8 @@ #include "llhttpclient.h" // Surface id's -#define LAND 1 -#define WATER 2 +//#define LAND 1 +//#define WATER 2 const U32 MAX_OBJECT_CACHE_ENTRIES = 50000; // Region handshake flags @@ -327,12 +327,15 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface bool meshRezEnabled() const; bool meshUploadEnabled() const; + bool bakesOnMeshEnabled() const; + // has region received its simulator features list? Requires an additional query after caps received. + void requestSimulatorFeatures(); void setSimulatorFeaturesReceived(bool); bool simulatorFeaturesReceived() const; boost::signals2::connection setSimulatorFeaturesReceivedCallback(const caps_received_signal_t::slot_type& cb); - void getSimulatorFeatures(LLSD& info); + void getSimulatorFeatures(LLSD& info) const; void setSimulatorFeatures(const LLSD& info); @@ -361,6 +364,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface void requestCacheMisses(); void addCacheMissFull(const U32 local_id); + void clearCachedVisibleObjects(); void dumpCache(); void unpackRegionHandshake(); @@ -370,8 +374,9 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface friend std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion); /// implements LLCapabilityProvider - virtual std::string getDescription() const; - std::string getHttpUrl() const { return mHttpUrl ;} + virtual std::string getDescription() const override; + + std::string getViewerAssetUrl() const { return mViewerAssetUrl; } LLSpatialPartition* getSpatialPartition(U32 type); @@ -392,6 +397,9 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface void resetMaterialsCapThrottle(); U32 getMaxMaterialsPerTransaction() const; + + void removeFromCreatedList(U32 local_id); + void addToCreatedList(U32 local_id); public: struct CompareDistance { @@ -428,8 +436,10 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface // positions stored in the first array so they're maintained separately until // we stop supporting the old CoarseLocationUpdate message. std::vector mMapAvatars; - std::vector mMapAvatarIDs; + uuid_vec_t mMapAvatarIDs; + + LLFrameTimer & getRenderInfoRequestTimer() { return mRenderInfoRequestTimer; }; private: LLViewerRegionImpl * mImpl; @@ -445,14 +455,14 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface BOOL mIsEstateManager; U32 mPacketsIn; - U32 mBitsIn; - U32 mLastBitsIn; + U32Bits mBitsIn, + mLastBitsIn; U32 mLastPacketsIn; U32 mPacketsOut; U32 mLastPacketsOut; S32 mPacketsLost; S32 mLastPacketsLost; - U32 mPingDelay; + U32Milliseconds mPingDelay; F32 mDeltaTime; // Time since last measurement of lastPackets, Bits, etc U64 mRegionFlags; // includes damage flags @@ -472,7 +482,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface std::string mColoName; std::string mProductSKU; std::string mProductName; - std::string mHttpUrl ; + std::string mViewerAssetUrl; // Maps local ids to cache entries. // Regions can have order 10,000 objects, so assume @@ -499,7 +509,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface U32 mGamingFlags; // the materials capability throttle LLFrameTimer mMaterialsCapThrottleTimer; -LLFrameTimer mRenderInfoRequestTimer; + LLFrameTimer mRenderInfoRequestTimer; }; inline BOOL LLViewerRegion::getRegionProtocol(U64 protocol) const diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index cd27ce0117..f1fb1108a2 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" + #include "llfeaturemanager.h" #include "llviewershadermgr.h" @@ -46,6 +47,8 @@ #include "llsky.h" #include "llvosky.h" #include "llrender.h" +#include "lljoint.h" +#include "llskinningutil.h" #if LL_DARWIN #include "OpenGL/OpenGL.h" @@ -98,7 +101,6 @@ LLGLSLShader gOneTextureNoColorProgram(LLViewerShaderMgr::SHADER_INTERFACE); LLGLSLShader gDebugProgram(LLViewerShaderMgr::SHADER_INTERFACE); LLGLSLShader gClipProgram(LLViewerShaderMgr::SHADER_INTERFACE); LLGLSLShader gDownsampleDepthProgram(LLViewerShaderMgr::SHADER_INTERFACE); -LLGLSLShader gDownsampleDepthRectProgram(LLViewerShaderMgr::SHADER_INTERFACE); LLGLSLShader gAlphaMaskProgram(LLViewerShaderMgr::SHADER_INTERFACE); LLGLSLShader gUIProgram(LLViewerShaderMgr::SHADER_INTERFACE); @@ -306,7 +308,7 @@ void LLViewerShaderMgr::setShaders() } // Lighting - gPipeline.setLightingDetail(-1); + gPipeline.updateLocalLightingEnabled(); // Shaders LL_INFOS("ShaderLoading") << "\n~~~~~~~~~~~~~~~~~~\n Loading Shaders:\n~~~~~~~~~~~~~~~~~~" << LL_ENDL; @@ -495,6 +497,7 @@ void LLViewerShaderMgr::setShaders() //Flag base shader objects for deletion //Don't worry-- they won't be deleted until no programs refrence them. unloadShaderObjects(); + cleanupShaderSources(); } if (gViewerWindow) @@ -513,30 +516,20 @@ void LLViewerShaderMgr::setShaders() void LLViewerShaderMgr::unloadShaders() { - //Instead of manually unloading, shaders are now automatically accumulated in a list. - //Simply iterate and unload. - std::vector &shader_list = LLShaderMgr::getGlobalShaderList(); - for(std::vector::iterator it=shader_list.begin();it!=shader_list.end();++it) - (*it)->unload(); + LLShaderMgr::unloadShaders(); for (S32 i = 0; i < SHADER_COUNT; i++) mVertexShaderLevel[i] = 0; //Unset all shader-dependent static variables. - LLGLSLShader::sNoFixedFunction = false; + LLGLSLShader::sNoFixedFunction = LLRender::sGLCoreProfile; LLGLSLShader::sIndexedTextureChannels = 1; LLPipeline::sRenderDeferred = false; LLPipeline::sWaterReflections = FALSE; LLPipeline::sRenderGlow = FALSE; -} -void LLViewerShaderMgr::unloadShaderObjects() -{ - std::multimap::iterator it = mShaderObjects.begin(); - for (; it != mShaderObjects.end(); ++it) - if (it->second.mHandle) - glDeleteObjectARB(it->second.mHandle); - mShaderObjects.clear(); + // Clear sync hashes. If shaders were just turned off then glLight state needs to be resynced. + gGL.resetSyncHashes(); } BOOL LLViewerShaderMgr::loadBasicShaders() @@ -556,7 +549,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders() } // If we have sun and moon only checked, then only sum those lights. - if (gPipeline.getLightingDetail() == 0) + if (!gPipeline.isLocalLightingEnabled()) { sum_lights_class = 1; } @@ -595,11 +588,15 @@ BOOL LLViewerShaderMgr::loadBasicShaders() } shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) ); + std::map attribs; + attribs["MAX_JOINTS_PER_MESH_OBJECT"] = + fmt::to_string(LLSkinningUtil::getMaxJointCount()); + // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. for (U32 i = 0; i < shaders.size(); i++) { // Note usage of GL_VERTEX_SHADER_ARB - if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB) == 0) + if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB, &attribs) == 0) { return FALSE; } @@ -646,7 +643,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders() for (U32 i = 0; i < shaders.size(); i++) { // Note usage of GL_FRAGMENT_SHADER_ARB - if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, NULL, index_channels[i]) == 0) + if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, &attribs, index_channels[i]) == 0) { return FALSE; } @@ -899,7 +896,6 @@ BOOL LLViewerShaderMgr::loadShadersEffects() shaderUniforms.reserve(3); shaderUniforms.push_back(LLStaticHashedString("inv_proj")); shaderUniforms.push_back(LLStaticHashedString("prev_proj")); - shaderUniforms.push_back(LLStaticHashedString("screen_res")); } gPostMotionBlurProgram.mName = "Motion Blur Shader (Post)"; @@ -922,7 +918,6 @@ BOOL LLViewerShaderMgr::loadShadersEffects() shaderUniforms.reserve(3); shaderUniforms.push_back(LLStaticHashedString("vignette_darkness")); shaderUniforms.push_back(LLStaticHashedString("vignette_radius")); - shaderUniforms.push_back(LLStaticHashedString("screen_res")); } gPostVignetteProgram.mName = "Vignette Shader (Post)"; @@ -959,6 +954,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() BOOL success = TRUE; + success = loadShaderFile("deferred/components/utilityFuncF.glsl", mVertexShaderLevel[SHADER_DEFERRED], GL_FRAGMENT_SHADER_ARB); + if (success) { gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader"; @@ -1238,7 +1235,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { std::string fragment; - std::string vertex = "deferred/sunLightV.glsl"; + std::string vertex = "deferred/postDeferredNoTCV.glsl"; if (gSavedSettings.getBOOL("RenderDeferredSSAO")) { @@ -1267,7 +1264,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredSSAOProgram.mName = "Deferred Ambient Occlusion Shader"; gDeferredSSAOProgram.mShaderFiles.clear(); - gDeferredSSAOProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSSAOProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSSAOProgram.mShaderFiles.push_back(make_pair("deferred/SSAOF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredSSAOProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredSSAOProgram.createShader(NULL, NULL); @@ -1277,7 +1274,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredDownsampleDepthNearestProgram.mName = "Deferred Nearest Downsample Depth Shader"; gDeferredDownsampleDepthNearestProgram.mShaderFiles.clear(); - gDeferredDownsampleDepthNearestProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredDownsampleDepthNearestProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredDownsampleDepthNearestProgram.mShaderFiles.push_back(make_pair("deferred/downsampleDepthNearestF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredDownsampleDepthNearestProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredDownsampleDepthNearestProgram.createShader(NULL, NULL); @@ -1288,7 +1285,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader"; gDeferredBlurLightProgram.mShaderFiles.clear(); - gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredBlurLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredBlurLightProgram.createShader(NULL, NULL); @@ -1544,7 +1541,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredSoftenProgram.mName = "Deferred Soften Shader"; gDeferredSoftenProgram.mShaderFiles.clear(); - gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredSoftenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; @@ -1561,7 +1558,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredSoftenWaterProgram.mName = "Deferred Soften Underwater Shader"; gDeferredSoftenWaterProgram.mShaderFiles.clear(); - gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredSoftenWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; @@ -1677,7 +1674,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredPostGammaCorrectProgram.mName = "Deferred Gamma Correction Post Process"; gDeferredPostGammaCorrectProgram.mShaderFiles.clear(); gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrectF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredPostGammaCorrectProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredPostGammaCorrectProgram.createShader(NULL, NULL); } @@ -1686,8 +1683,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gFXAAProgram.mName = "FXAA Shader"; gFXAAProgram.mShaderFiles.clear(); - gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); + gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/fxaaF.glsl", GL_FRAGMENT_SHADER_ARB)); + static LLCachedControl fxaaQuality("FXAAQuality", 12); + gFXAAProgram.addPermutation("FXAA_QUALITY_M_PRESET", fmt::to_string(fxaaQuality.get())); gFXAAProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gFXAAProgram.createShader(NULL, NULL); } @@ -2374,16 +2373,6 @@ BOOL LLViewerShaderMgr::loadShadersInterface() success = gDownsampleDepthProgram.createShader(NULL, NULL); } - if (success) - { - gDownsampleDepthRectProgram.mName = "DownsampleDepthRect Shader"; - gDownsampleDepthRectProgram.mShaderFiles.clear(); - gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB)); - gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthRectF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDownsampleDepthRectProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; - success = gDownsampleDepthRectProgram.createShader(NULL, NULL); - } - if (success) { gAlphaMaskProgram.mName = "Alpha Mask Shader"; @@ -2548,6 +2537,17 @@ void LLViewerShaderMgr::updateShaderUniforms(LLGLSLShader * shader) LLWaterParamManager::getInstance()->updateShaderUniforms(shader); } +/* virtual */ bool LLViewerShaderMgr::attachClassSharedShaders(LLGLSLShader& shader, S32 shader_class) +{ + switch (shader_class) + { + case LLViewerShaderMgr::SHADER_DEFERRED: + LL_INFOS() << "deferred/components/utilityFuncF.glsl" << LL_ENDL; + return shader.attachObject("deferred/components/utilityFuncF.glsl"); + } + return true; +} + /*static*/ void LLShaderMgr::unloadShaderClass(int shader_class) { std::vector &shader_list = getGlobalShaderList(); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index fe7d4d64cb..e39380f169 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -57,7 +57,6 @@ class LLViewerShaderMgr: public LLShaderMgr void initAttribsAndUniforms(void); void setShaders(); void unloadShaders(); - void unloadShaderObjects(); S32 getVertexShaderLevel(S32 type); BOOL loadBasicShaders(); BOOL loadShadersEffects(); @@ -147,6 +146,8 @@ class LLViewerShaderMgr: public LLShaderMgr /* virtual */ void updateShaderUniforms(LLGLSLShader * shader); // Virtual + /* virtual */ bool attachClassSharedShaders(LLGLSLShader& shader, S32 shader_class); // Virtual + private: std::vector mShinyUniforms; @@ -210,7 +211,6 @@ extern LLGLSLShader gGlowCombineFXAAProgram; extern LLGLSLShader gDebugProgram; extern LLGLSLShader gClipProgram; extern LLGLSLShader gDownsampleDepthProgram; -extern LLGLSLShader gDownsampleDepthRectProgram; //output tex0[tc0] + tex1[tc1] extern LLGLSLShader gTwoTextureAddProgram; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 3ff7a33e0d..15023ff5d5 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -51,6 +51,7 @@ #include "llagentcamera.h" #include "llviewercontrol.h" #include "llfloaterdirectory.h" +#include "llversioninfo.h" #include "llfloatertools.h" #include "lldebugview.h" #include "llfasttimerview.h" @@ -443,15 +444,15 @@ void reset_statistics() void output_statistics(void*) { - S32 global_raw_memory; + S64 global_raw_memory; { - global_raw_memory = *AIAccess(LLImageRaw::sGlobalRawMemory); + global_raw_memory = *AIAccess(LLImageRaw::sGlobalRawMemory); } LL_INFOS() << "Number of orphans: " << gObjectList.getOrphanCount() << LL_ENDL; LL_INFOS() << "Number of dead objects: " << gObjectList.mNumDeadObjects << LL_ENDL; LL_INFOS() << "Num images: " << gTextureList.getNumImages() << LL_ENDL; - LL_INFOS() << "Texture usage: " << LLImageGL::sGlobalTextureMemoryInBytes << LL_ENDL; - LL_INFOS() << "Texture working set: " << LLImageGL::sBoundTextureMemoryInBytes << LL_ENDL; + LL_INFOS() << "Texture usage: " << LLImageGL::sGlobalTextureMemory.value() << LL_ENDL; + LL_INFOS() << "Texture working set: " << LLImageGL::sBoundTextureMemory.value() << LL_ENDL; LL_INFOS() << "Raw usage: " << global_raw_memory << LL_ENDL; LL_INFOS() << "Formatted usage: " << LLImageFormatted::sGlobalFormattedMemory << LL_ENDL; LL_INFOS() << "Zombie Viewer Objects: " << LLViewerObject::getNumZombieObjects() << LL_ENDL; @@ -535,7 +536,6 @@ void output_statistics(void*) LL_INFOS() << "--------------------------------" << LL_ENDL; LL_INFOS() << "Avatar Memory (partly overlaps with above stats):" << LL_ENDL; LLTexLayerStaticImageList::getInstance()->dumpByteCount(); - LLVOAvatarSelf::dumpScratchTextureByteCount(); LLViewerTexLayerSetBuffer::dumpTotalByteCount(); LLVOAvatarSelf::dumpTotalLocalTextureByteCount(); LLTexLayerParamAlpha::dumpCacheByteCount(); @@ -569,19 +569,25 @@ void output_statistics(void*) } -U32 gTotalLandIn = 0, gTotalLandOut = 0; -U32 gTotalWaterIn = 0, gTotalWaterOut = 0; +U32 gTotalLandIn = 0, + gTotalLandOut = 0, + gTotalWaterIn = 0, + gTotalWaterOut = 0; -F32 gAveLandCompression = 0.f, gAveWaterCompression = 0.f; -F32 gBestLandCompression = 1.f, gBestWaterCompression = 1.f; -F32 gWorstLandCompression = 0.f, gWorstWaterCompression = 0.f; +F32 gAveLandCompression = 0.f, + gAveWaterCompression = 0.f, + gBestLandCompression = 1.f, + gBestWaterCompression = 1.f, + gWorstLandCompression = 0.f, + gWorstWaterCompression = 0.f; - - -U32 gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0; -U32 gObjectBits = 0; -F32 gAvgSimPing = 0.f; -U32 gTotalTextureBytesPerBoostLevel[LLGLTexture::MAX_GL_IMAGE_CATEGORY] = {0}; +U32Bytes gTotalWorldData, + gTotalObjectData, + gTotalTextureData; +U32 gSimPingCount = 0; +U32Bits gObjectData; +F32Milliseconds gAvgSimPing(0.f); +U32Bytes gTotalTextureBytesPerBoostLevel[LLGLTexture::MAX_GL_IMAGE_CATEGORY] = {U32Bytes(0)}; extern U32 gVisCompared; extern U32 gVisTested; @@ -590,8 +596,8 @@ LLFrameTimer gTextureTimer; void update_statistics() { - gTotalWorldBytes += gVLManager.getTotalBytes(); - gTotalObjectBytes += gObjectBits / 8; + gTotalWorldData += U32Bytes(gVLManager.getTotalBytes()); + gTotalObjectData += gObjectData; LLViewerStats& stats = LLViewerStats::instance(); @@ -612,7 +618,7 @@ void update_statistics() } } stats.setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable")); - stats.setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail()); + stats.setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.isLocalLightingEnabled()); stats.setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip")); stats.setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles")); #if 0 // 1.9.2 @@ -632,8 +638,8 @@ void update_statistics() LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost()); if (cdp) { - stats.mSimPingStat.addValue(cdp->getPingDelay()); - gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1); + stats.mSimPingStat.addValue(cdp->getPingDelay().value()); + gAvgSimPing = ((gAvgSimPing * gSimPingCount) + cdp->getPingDelay()) / (gSimPingCount + 1); gSimPingCount++; } else @@ -642,11 +648,11 @@ void update_statistics() } stats.mFPSStat.addValue(1); - F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits()); - stats.mLayersKBitStat.addValue(layer_bits/1024.f); - stats.mObjectKBitStat.addValue(gObjectBits/1024.f); + F64Bits layer_bits = F64Bits(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits()); + stats.mLayersKBitStat.addValue((F32)layer_bits.valueInUnits()); + stats.mObjectKBitStat.addValue(gObjectData.valueInUnits()); stats.mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending()); - stats.mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f); + stats.mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET) / 1024); gTransferManager.resetTransferBitsIn(LLTCT_ASSET); if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) @@ -674,7 +680,7 @@ void update_statistics() // Reset all of these values. gVLManager.resetBitCounts(); - gObjectBits = 0; + gObjectData = (U32Bytes)0; // gDecodedBits = 0; // Only update texture stats periodically so that they are less noisy @@ -684,10 +690,10 @@ void update_statistics() if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq) { stats.mHTTPTextureKBitStat.addValue(AICurlInterface::getHTTPBandwidth()/125.f); - stats.mUDPTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f); + stats.mUDPTextureKBitStat.addValue(LLViewerTextureList::sTextureBits.valueInUnits()); stats.mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets); - gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8; - LLViewerTextureList::sTextureBits = 0; + gTotalTextureData += U32Bits(LLViewerTextureList::sTextureBits); + LLViewerTextureList::sTextureBits = U32Bits(0); LLViewerTextureList::sTexturePackets = 0; texture_stats_timer.reset(); } @@ -780,7 +786,7 @@ void send_stats() // send fps only for time app spends in foreground agent["fps"] = (F32)gForegroundFrameCount / gForegroundTime.getElapsedTimeF32(); - agent["version"] = gCurrentVersion; + agent["version"] = LLVersionInfo::getChannelAndVersion(); std::string language = LLUI::getLanguage(); agent["language"] = language; @@ -791,14 +797,14 @@ void send_stats() gSimFrames = (F32) gFrameCount; agent["agents_in_view"] = LLVOAvatar::sNumVisibleAvatars; - agent["ping"] = gAvgSimPing; + agent["ping"] = gAvgSimPing.value(); agent["meters_traveled"] = gAgent.getDistanceTraveled(); agent["regions_visited"] = gAgent.getRegionsVisited(); agent["mem_use"] = LLMemory::getCurrentRSS() / 1024.0; LLSD &system = body["system"]; - system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB(); + system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB().value(); system["os"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple(); system["cpu"] = gSysCPU.getCPUString(); unsigned char MACAddress[MAC_ADDRESS_BYTES]; @@ -822,9 +828,9 @@ void send_stats() LLSD &download = body["downloads"]; - download["world_kbytes"] = gTotalWorldBytes / 1024.0; - download["object_kbytes"] = gTotalObjectBytes / 1024.0; - download["texture_kbytes"] = gTotalTextureBytes / 1024.0; + download["world_kbytes"] = F64Kilobytes(gTotalWorldData).value(); + download["object_kbytes"] = F64Kilobytes(gTotalObjectData).value(); + download["texture_kbytes"] = F64Kilobytes(gTotalTextureData).value(); download["mesh_kbytes"] = LLMeshRepository::sBytesReceived/1024.0; LLSD &in = body["stats"]["net"]["in"]; @@ -885,7 +891,10 @@ void send_stats() body["MinimalSkin"] = false; LLViewerStats::getInstance()->addToMessage(body); - LLHTTPClient::post(url, body, new ViewerStatsResponder); + + LL_INFOS("LogViewerStatsPacket") << "Sending viewer statistics: " << body << LL_ENDL; + LLHTTPClient::post(url, body, new ViewerStatsResponder()); + } LLViewerStats::PhaseMap::PhaseMap() diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index f6300d1e27..90b75a8668 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -321,7 +321,7 @@ void update_statistics(); void send_stats(); extern LLFrameTimer gTextureTimer; -extern U32 gTotalTextureBytes; -extern U32 gTotalObjectBytes; -extern U32 gTotalTextureBytesPerBoostLevel[] ; +extern U32Bytes gTotalTextureData; +extern U32Bytes gTotalObjectData; +extern U32Bytes gTotalTextureBytesPerBoostLevel[] ; #endif // LL_LLVIEWERSTATS_H diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp index c49e459bd7..4e31d561a8 100644 --- a/indra/newview/llviewertexlayer.cpp +++ b/indra/newview/llviewertexlayer.cpp @@ -76,7 +76,7 @@ LLViewerTexLayerSetBuffer::LLViewerTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height) : // ORDER_LAST => must render these after the hints are created. LLTexLayerSetBuffer(owner), - LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ), + LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, FALSE ), mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates mNeedsUpload(FALSE), mNumLowresUploads(0), diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 32d2f70af8..3c9ce82e76 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -441,7 +441,9 @@ void LLEmbeddedItems::bindEmbeddedChars( const LLFontGL* font ) const case LLAssetType::AT_BODYPART: img_name = "inv_item_skin.tga"; break; case LLAssetType::AT_ANIMATION: img_name = "inv_item_animation.tga";break; case LLAssetType::AT_GESTURE: img_name = "inv_item_gesture.tga"; break; - default: llassert(0); continue; + case LLAssetType::AT_MESH: img_name = "Inv_Mesh"; break; + case LLAssetType::AT_SETTINGS: img_name = "Inv_Settings"; break; + default: img_name = "Inv_Invalid"; break; // use the Inv_Invalid icon for undefined object types (see MAINT-3981) } LLUIImagePtr image = LLUI::getUIImage(img_name); @@ -578,34 +580,20 @@ LLViewerTextEditor::LLViewerTextEditor(const std::string& name, S32 max_length, const std::string& default_text, const LLFontGL* font, - BOOL allow_embedded_items) - : LLTextEditor(name, rect, max_length, default_text, font, allow_embedded_items), + BOOL allow_embedded_items, + bool parse_html) + : LLTextEditor(name, rect, max_length, default_text, font, allow_embedded_items, parse_html), mDragItemChar(0), mDragItemSaved(FALSE), mInventoryCallback(new LLEmbeddedNotecardOpener) { mEmbeddedItemList = new LLEmbeddedItems(this); mInventoryCallback->setEditor(this); - - // *TODO: Add right click menus for SLURLs - // Build the right click menu - // make the popup menu available - - //LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_slurl.xml", this); - //if (!menu) - //{ - // menu = new LLMenuGL(LLStringUtil::null); - //} - //menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor")); - //// menu->setVisible(FALSE); - //mPopupMenuHandle = menu->getHandle(); } LLViewerTextEditor::~LLViewerTextEditor() { delete mEmbeddedItemList; - - // The inventory callback may still be in use by gInventoryCallbackManager... // so set its reference to this to null. mInventoryCallback->setEditor(NULL); @@ -672,6 +660,7 @@ BOOL LLViewerTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* s return TRUE; } +// Singu TODO: This is mostly duplicated from LLTextEditor BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; @@ -794,114 +783,28 @@ BOOL LLViewerTextEditor::handleHover(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; - if (!mDragItem) + if (!mIsSelecting && mDragItem && hasMouseCapture()) { - // leave hover segment active during drag and drop - mHoverSegment = NULL; - } - if(hasMouseCapture() ) - { - if( mIsSelecting ) + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y ); + if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) ) { - if (x != mLastSelectionX || y != mLastSelectionY) - { - mLastSelectionX = x; - mLastSelectionY = y; - } + LLToolDragAndDrop::getInstance()->beginDrag( + LLViewerAssetType::lookupDragAndDropType( mDragItem->getType() ), + mDragItem->getUUID(), + LLToolDragAndDrop::SOURCE_NOTECARD, + getSourceID(), mObjectID); - if( y > getTextRect().mTop ) - { - mScrollbar->setDocPos( mScrollbar->getDocPos() - 1 ); - } - else - if( y < getTextRect().mBottom ) - { - mScrollbar->setDocPos( mScrollbar->getDocPos() + 1 ); - } - - setCursorAtLocalPos( x, y, TRUE ); - mSelectionEnd = mCursorPos; - - updateScrollFromCursor(); - getWindow()->setCursor(UI_CURSOR_IBEAM); - } - else if( mDragItem ) - { - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y ); - if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) ) - { - LLToolDragAndDrop::getInstance()->beginDrag( - LLViewerAssetType::lookupDragAndDropType( mDragItem->getType() ), - mDragItem->getUUID(), - LLToolDragAndDrop::SOURCE_NOTECARD, - getSourceID(), mObjectID); - - return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); - } - getWindow()->setCursor(UI_CURSOR_HAND); + return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); } + getWindow()->setCursor(UI_CURSOR_HAND); LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL; handled = TRUE; } - if( !handled ) - { - // Pass to children - handled = LLView::childrenHandleHover(x, y, mask) != NULL; - } - - if( handled ) - { - // Delay cursor flashing - resetKeystrokeTimer(); - } - - // Opaque - if( !handled && mTakesNonScrollClicks) - { - // Check to see if we're over an HTML-style link - if( !mSegments.empty() ) - { - LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); - if( cur_segment ) - { - if(cur_segment->getStyle()->isLink()) - { - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (over link, inactive)" << LL_ENDL; - getWindow()->setCursor(UI_CURSOR_HAND); - handled = TRUE; - } - else - if(cur_segment->getStyle()->getIsEmbeddedItem()) - { - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (over embedded item, inactive)" << LL_ENDL; - getWindow()->setCursor(UI_CURSOR_HAND); - //getWindow()->setCursor(UI_CURSOR_ARROW); - handled = TRUE; - } - mHoverSegment = cur_segment; - } - } - - if( !handled ) - { - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL; - if (!mScrollbar->getVisible() || x < getRect().getWidth() - SCROLLBAR_SIZE) - { - getWindow()->setCursor(UI_CURSOR_IBEAM); - } - else - { - getWindow()->setCursor(UI_CURSOR_ARROW); - } - handled = TRUE; - } - } - - return handled; + return handled || LLTextEditor::handleHover(x, y, mask); } @@ -945,125 +848,36 @@ BOOL LLViewerTextEditor::handleMouseUp(S32 x, S32 y, MASK mask) BOOL LLViewerTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; - if(!handled)handled = LLTextEditor::handleRightMouseDown(x, y, mask); - - // *TODO: Add right click menus for SLURLs -// if(! handled) -// { -// const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); -// if( cur_segment ) -// { -// if(cur_segment->getStyle()->isLink()) -// { -// handled = TRUE; -// mHTML = cur_segment->getStyle()->getLinkHREF(); -// } -// } -// } -// LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); -// if(handled && menu && mParseHTML && mHTML.length() > 0) -// { -// menu->setVisible(TRUE); -// menu->arrange(); -// menu->updateParent(LLMenuGL::sMenuContainer); -// LLMenuGL::showPopup(this, menu, x, y); -// mHTML = ""; -// } -// else -// { -// if(menu && menu->getVisible()) -// { -// menu->setVisible(FALSE); -// } -// } - return handled; + return childrenHandleRightMouseDown(x, y, mask) != NULL || LLTextEditor::handleRightMouseDown(x, y, mask); } BOOL LLViewerTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - handled = childrenHandleMiddleMouseDown(x, y, mask) != NULL; - if (!handled) - { - handled = LLTextEditor::handleMiddleMouseDown(x, y, mask); - } - return handled; + return childrenHandleMiddleMouseDown(x, y, mask) != NULL || LLTextEditor::handleMiddleMouseDown(x, y, mask); } BOOL LLViewerTextEditor::handleMiddleMouseUp(S32 x, S32 y, MASK mask) { - BOOL handled = childrenHandleMiddleMouseUp(x, y, mask) != NULL; - - return handled; + return childrenHandleMiddleMouseUp(x, y, mask) != NULL || LLTextEditor::handleMiddleMouseUp(x, y, mask); } BOOL LLViewerTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - - // let scrollbar have first dibs - handled = LLView::childrenHandleDoubleClick(x, y, mask) != NULL; - - if( !handled && mTakesNonScrollClicks) + if (mTakesNonScrollClicks && allowsEmbeddedItems()) { - if( allowsEmbeddedItems() ) + const LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y); + if (cur_segment && cur_segment->getStyle()->getIsEmbeddedItem()) { - const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); - if( cur_segment && cur_segment->getStyle()->getIsEmbeddedItem() ) + if( openEmbeddedItemAtPos(cur_segment->getStart())) { - if( openEmbeddedItemAtPos( cur_segment->getStart() ) ) - { - deselect(); - setFocus( FALSE ); - return TRUE; - } + deselect(); + setFocus(FALSE); + return TRUE; } } - - - setCursorAtLocalPos( x, y, FALSE ); - deselect(); - - const LLWString &text = getWText(); - - if( isPartOfWord( text[mCursorPos] ) ) - { - // Select word the cursor is over - while ((mCursorPos > 0) && isPartOfWord(text[mCursorPos-1])) - { - mCursorPos--; - } - startSelection(); - - while ((mCursorPos < (S32)text.length()) && isPartOfWord( text[mCursorPos] ) ) - { - mCursorPos++; - } - - mSelectionEnd = mCursorPos; - } - else if ((mCursorPos < (S32)text.length()) && !iswspace( text[mCursorPos]) ) - { - // Select the character the cursor is over - startSelection(); - mCursorPos++; - mSelectionEnd = mCursorPos; - } - - // We don't want handleMouseUp() to "finish" the selection (and thereby - // set mSelectionEnd to where the mouse is), so we finish the selection here. - mIsSelecting = FALSE; - - // delay cursor flashing - resetKeystrokeTimer(); - - // take selection to 'primary' clipboard - updatePrimary(); - - handled = TRUE; } - return handled; + + return LLTextEditor::handleDoubleClick(x, y, mask); } @@ -1243,7 +1057,6 @@ void LLViewerTextEditor::setEmbeddedText(const std::string& instr) std::string LLViewerTextEditor::getEmbeddedText() { -#if 1 // New version (Version 2) mEmbeddedItemList->copyUsedCharsToIndexed(); LLWString outtextw; @@ -1259,26 +1072,6 @@ std::string LLViewerTextEditor::getEmbeddedText() } std::string outtext = wstring_to_utf8str(outtextw); return outtext; -#else - // Old version (Version 1) - mEmbeddedItemList->copyUsedCharsToIndexed(); - std::string outtext; - for (S32 i=0; i<(S32)mWText.size(); i++) - { - llwchar wch = mWText[i]; - if( wch >= FIRST_EMBEDDED_CHAR && wch <= LAST_EMBEDDED_CHAR ) - { - S32 index = mEmbeddedItemList->getIndexFromEmbeddedChar(wch); - wch = 0x80 | index % 128; - } - else if (wch >= 0x80) - { - wch = LL_UNKNOWN_CHAR; - } - outtext.push_back((U8)wch); - } - return outtext; -#endif } std::string LLViewerTextEditor::appendTime(bool prepend_newline) @@ -1670,12 +1463,15 @@ LLView* LLViewerTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlF BOOL parse_html = true; node->getAttributeBOOL("allow_html", parse_html); text_editor->setParseHTML(parse_html); - text_editor->setParseHighlights(TRUE); + BOOL commit_on_focus_lost = FALSE; + node->getAttributeBOOL("commit_on_focus_lost",commit_on_focus_lost); + text_editor->setCommitOnFocusLost(commit_on_focus_lost); + text_editor->initFromXML(node, parent); // add text after all parameters have been set - text_editor->appendStyledText(text, FALSE, FALSE); + text_editor->appendText(text, FALSE, FALSE); return text_editor; } diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h index 702b97ca11..9b5edcc882 100644 --- a/indra/newview/llviewertexteditor.h +++ b/indra/newview/llviewertexteditor.h @@ -39,7 +39,7 @@ // // Classes // -class LLViewerTextEditor : public LLTextEditor +class LLViewerTextEditor final : public LLTextEditor { public: @@ -48,7 +48,8 @@ class LLViewerTextEditor : public LLTextEditor S32 max_length, const std::string& default_text = std::string(), const LLFontGL* glfont = NULL, - BOOL allow_embedded_items = FALSE); + BOOL allow_embedded_items = FALSE, + bool parse_html = false); virtual ~LLViewerTextEditor(); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 11b05813c2..b299f36e46 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -63,6 +63,11 @@ #include "lltexturecache.h" /////////////////////////////////////////////////////////////////////////////// +// extern +const S32Megabytes gMinVideoRam(32); +const S32Megabytes gMaxVideoRam(2048*4); // Bump to 8 gibibyte. + + // statics LLPointer LLViewerTexture::sNullImagep = NULL; LLPointer LLViewerTexture::sBlackImagep = NULL; @@ -71,9 +76,9 @@ LLPointer LLViewerFetchedTexture::sWhiteImagep = NULL; LLPointer LLViewerFetchedTexture::sDefaultImagep = NULL; LLPointer LLViewerFetchedTexture::sSmokeImagep = NULL; LLPointer LLViewerFetchedTexture::sFlatNormalImagep = NULL; -LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap ; +LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap; #if 0 -LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL ; +LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL; #endif const std::string sTesterName("TextureTester"); @@ -83,22 +88,23 @@ S32 LLViewerTexture::sAuxCount = 0; LLFrameTimer LLViewerTexture::sEvaluationTimer; F32 LLViewerTexture::sDesiredDiscardBias = 0.f; F32 LLViewerTexture::sDesiredDiscardScale = 1.1f; -S32 LLViewerTexture::sBoundTextureMemoryInBytes = 0; -S32 LLViewerTexture::sTotalTextureMemoryInBytes = 0; -S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0; -S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0; -S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ; -S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ; -F32 LLViewerTexture::sCameraMovingBias = 0.0f ; -S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size -const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ; -const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez ; -const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128 ; -S32 LLViewerTexture::sMinLargeImageSize = 65536 ; //256 * 256. -S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ; -BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ; -F32 LLViewerTexture::sCurrentTime = 0.0f ; -//BOOL LLViewerTexture::sUseTextureAtlas = FALSE ; +S64Bytes LLViewerTexture::sBoundTextureMemory; +S64Bytes LLViewerTexture::sTotalTextureMemory; +S32Megabytes LLViewerTexture::sMaxBoundTextureMemory; +S32Megabytes LLViewerTexture::sMaxTotalTextureMem; +S64Bytes LLViewerTexture::sMaxDesiredTextureMem; +S32 LLViewerTexture::sCameraMovingDiscardBias = 0; +F32 LLViewerTexture::sCameraMovingBias = 0.0f; +S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size +const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64; +const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez; +const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128; +const S32 DEFAULT_ICON_DIMENTIONS = 32; +S32 LLViewerTexture::sMinLargeImageSize = 65536; //256 * 256. +S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA; +BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE; +F32 LLViewerTexture::sCurrentTime = 0.0f; +//BOOL LLViewerTexture::sUseTextureAtlas = FALSE; F32 LLViewerTexture::sTexelPixelRatio = 1.0f; LLViewerTexture::EDebugTexels LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF; @@ -107,6 +113,8 @@ const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve const F32 desired_discard_bias_max = (F32)MAX_DISCARD_LEVEL; // max number of levels to reduce image quality by const F64 log_2 = log(2.0); +const U32 DESIRED_NORMAL_TEXTURE_SIZE = (U32)LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT; + //---------------------------------------------------------------------------------------------- //namespace: LLViewerTextureAccess //---------------------------------------------------------------------------------------------- @@ -128,7 +136,7 @@ LLLoadedCallbackEntry::LLLoadedCallbackEntry(loaded_callback_func cb, { if(mSourceCallbackList) { - mSourceCallbackList->insert(target->getID()); + mSourceCallbackList->insert(LLTextureKey(target->getID(), (ETexListType)target->getTextureListType())); } } @@ -140,7 +148,7 @@ void LLLoadedCallbackEntry::removeTexture(LLViewerFetchedTexture* tex) { if(mSourceCallbackList) { - mSourceCallbackList->erase(tex->getID()) ; + mSourceCallbackList->erase(LLTextureKey(tex->getID(), (ETexListType)tex->getTextureListType())); } } @@ -153,118 +161,134 @@ void LLLoadedCallbackEntry::cleanUpCallbackList(LLLoadedCallbackEntry::source_ca for(LLLoadedCallbackEntry::source_callback_list_t::iterator iter = callback_list->begin(); iter != callback_list->end(); ++iter) { - LLViewerFetchedTexture* tex = gTextureList.findImage(*iter) ; + LLViewerFetchedTexture* tex = gTextureList.findImage(*iter); if(tex) { - tex->deleteCallbackEntry(callback_list) ; + tex->deleteCallbackEntry(callback_list); } } - callback_list->clear() ; + callback_list->clear(); } } LLViewerMediaTexture* LLViewerTextureManager::createMediaTexture(const LLUUID &media_id, BOOL usemipmaps, LLImageGL* gl_image) { - return new LLViewerMediaTexture(media_id, usemipmaps, gl_image) ; + return new LLViewerMediaTexture(media_id, usemipmaps, gl_image); } - -LLViewerTexture* LLViewerTextureManager::findTexture(const LLUUID& id) + +void LLViewerTextureManager::findFetchedTextures(const LLUUID& id, std::vector &output) { - LLViewerTexture* tex ; - //search fetched texture list - tex = gTextureList.findImage(id) ; - - //search media texture list - if(!tex) - { - tex = LLViewerTextureManager::findMediaTexture(id) ; - } - return tex ; + return gTextureList.findTexturesByID(id, output); +} + +void LLViewerTextureManager::findTextures(const LLUUID& id, std::vector &output) +{ + std::vector fetched_output; + gTextureList.findTexturesByID(id, fetched_output); + std::vector::iterator iter = fetched_output.begin(); + while (iter != fetched_output.end()) + { + output.push_back(*iter); + iter++; + } + + //search media texture list + if (output.empty()) + { + LLViewerTexture* tex; + tex = LLViewerTextureManager::findMediaTexture(id); + if (tex) + { + output.push_back(tex); + } + } + } -LLViewerFetchedTexture* LLViewerTextureManager::findFetchedTexture(const LLUUID& id) +LLViewerFetchedTexture* LLViewerTextureManager::findFetchedTexture(const LLUUID& id, S32 tex_type) { - return gTextureList.findImage(id); + return gTextureList.findImage(id, (ETexListType)tex_type); } LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id) { - return LLViewerMediaTexture::findMediaTexture(media_id) ; + return LLViewerMediaTexture::findMediaTexture(media_id); } LLViewerMediaTexture* LLViewerTextureManager::getMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image) { - LLViewerMediaTexture* tex = LLViewerMediaTexture::findMediaTexture(id) ; + LLViewerMediaTexture* tex = LLViewerMediaTexture::findMediaTexture(id); if(!tex) { - tex = LLViewerTextureManager::createMediaTexture(id, usemipmaps, gl_image) ; + tex = LLViewerTextureManager::createMediaTexture(id, usemipmaps, gl_image); } - tex->initVirtualSize() ; + tex->initVirtualSize(); - return tex ; + return tex; } LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLTexture* tex, BOOL report_error) { if(!tex) { - return NULL ; + return NULL; } - S8 type = tex->getType() ; + S8 type = tex->getType(); if(type == LLViewerTexture::FETCHED_TEXTURE || type == LLViewerTexture::LOD_TEXTURE) { - return static_cast(tex) ; + return static_cast(tex); } if(report_error) { - LL_ERRS() << "not a fetched texture type: " << type << LL_ENDL ; + LL_ERRS() << "not a fetched texture type: " << type << LL_ENDL; } - return NULL ; + return NULL; } LLPointer LLViewerTextureManager::getLocalTexture(BOOL usemipmaps, BOOL generate_gl_tex) { - LLPointer tex = new LLViewerTexture(usemipmaps) ; + LLPointer tex = new LLViewerTexture(usemipmaps); if(generate_gl_tex) { - tex->generateGLTexture() ; - tex->setCategory(LLGLTexture::LOCAL) ; + tex->generateGLTexture(); + tex->setCategory(LLGLTexture::LOCAL); } - return tex ; + return tex; } LLPointer LLViewerTextureManager::getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex) { - LLPointer tex = new LLViewerTexture(id, usemipmaps) ; + LLPointer tex = new LLViewerTexture(id, usemipmaps); if(generate_gl_tex) { - tex->generateGLTexture() ; - tex->setCategory(LLGLTexture::LOCAL) ; + tex->generateGLTexture(); + tex->setCategory(LLGLTexture::LOCAL); } - return tex ; + return tex; } LLPointer LLViewerTextureManager::getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) { - LLPointer tex = new LLViewerTexture(raw, usemipmaps) ; - tex->setCategory(LLGLTexture::LOCAL) ; - return tex ; + LLPointer tex = new LLViewerTexture(raw, usemipmaps); + tex->setCategory(LLGLTexture::LOCAL); + return tex; } LLPointer LLViewerTextureManager::getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex) { - LLPointer tex = new LLViewerTexture(width, height, components, usemipmaps) ; + LLPointer tex = new LLViewerTexture(width, height, components, usemipmaps); if(generate_gl_tex) { - tex->generateGLTexture() ; - tex->setCategory(LLGLTexture::LOCAL) ; + tex->generateGLTexture(); + tex->setCategory(LLGLTexture::LOCAL); } - return tex ; + return tex; } LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( const LLUUID &image_id, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -272,11 +296,12 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( LLGLenum primary_format, LLHost request_from_host) { - return gTextureList.getImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; + return gTextureList.getImage(image_id, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host); } LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( const std::string& filename, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -284,11 +309,12 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( LLGLenum primary_format, const LLUUID& force_id) { - return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; + return gTextureList.getImageFromFile(filename, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); } //static LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -297,12 +323,12 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const s const LLUUID& force_id ) { - return gTextureList.getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; + return gTextureList.getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); } -LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) { - return gTextureList.getImageFromHost(image_id, host) ; + return gTextureList.getImageFromHost(image_id, f_type, host); } // Create a bridge to the viewer texture manager. @@ -330,15 +356,15 @@ void LLViewerTextureManager::init() { LLPointer raw = new LLImageRaw(1,1,3); raw->clear(0x77, 0x77, 0x77, 0xFF); - LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ; + LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE); } const S32 dim = 128; LLPointer image_raw = new LLImageRaw(dim,dim,3); U8* data = image_raw->getData(); - memset(data, 0, dim * dim * 3) ; - LLViewerTexture::sBlackImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE) ; + memset(data, 0, dim * dim * 3); + LLViewerTexture::sBlackImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE); #if 1 LLPointer imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT); @@ -367,18 +393,18 @@ void LLViewerTextureManager::init() } imagep->createGLTexture(0, image_raw); //cache the raw image - imagep->setCachedRawImage(0, image_raw) ; + imagep->setCachedRawImage(0, image_raw); image_raw = NULL; #else - LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); #endif LLViewerFetchedTexture::sDefaultImagep->dontDiscard(); - LLViewerFetchedTexture::sDefaultImagep->setCategory(LLGLTexture::OTHER) ; + LLViewerFetchedTexture::sDefaultImagep->setCategory(LLGLTexture::OTHER); - LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLGLTexture::BOOST_UI); - LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ; + LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + LLViewerFetchedTexture::sSmokeImagep->setNoDelete(); - LLViewerTexture::initClass() ; + LLViewerTexture::initClass(); // Create a texture manager bridge. gTextureManagerBridgep = new LLViewerTextureManagerBridge(); @@ -386,7 +412,7 @@ void LLViewerTextureManager::init() #if 0 if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName)) { - sTesterp = new LLTexturePipelineTester() ; + sTesterp = new LLTexturePipelineTester(); if (!sTesterp->isValid()) { delete sTesterp; @@ -401,7 +427,7 @@ void LLViewerTextureManager::cleanup() stop_glerror(); delete gTextureManagerBridgep; - LLImageGL::sDefaultGLTexture = NULL ; + LLImageGL::sDefaultGLTexture = NULL; LLViewerTexture::sNullImagep = NULL; LLViewerTexture::sBlackImagep = NULL; LLViewerFetchedTexture::sDefaultImagep = NULL; @@ -410,7 +436,7 @@ void LLViewerTextureManager::cleanup() LLViewerFetchedTexture::sWhiteImagep = NULL; LLViewerFetchedTexture::sFlatNormalImagep = NULL; - LLViewerMediaTexture::cleanUpClass() ; + LLViewerMediaTexture::cleanUpClass(); } //---------------------------------------------------------------------------------------------- @@ -420,11 +446,11 @@ void LLViewerTextureManager::cleanup() // static void LLViewerTexture::initClass() { - LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ; + LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture(); sTexelPixelRatio = gSavedSettings.getF32("TexelPixelRatio"); if(gAuditTexture) { - LLImageGL::setHighlightTexture(LLViewerTexture::OTHER) ; + LLImageGL::setHighlightTexture(LLViewerTexture::OTHER); } } @@ -436,40 +462,41 @@ const S32 min_non_tex_system_mem = (128<<20); // 128 MB F32 texmem_lower_bound_scale = 0.85f; F32 texmem_middle_bound_scale = 0.925f; -static LLFastTimer::DeclareTimer FTM_TEXTURE_MEMORY_CHECK("Memory Check"); +static LLTrace::BlockTimerStatHandle FTM_TEXTURE_MEMORY_CHECK("Memory Check"); //static bool LLViewerTexture::isMemoryForTextureLow() { - const F32 WAIT_TIME = 1.0f ; //second - static LLFrameTimer timer ; + const F32 WAIT_TIME = 1.0f; //second + static LLFrameTimer timer; if(timer.getElapsedTimeF32() < WAIT_TIME) //call this once per second. { return false; } - timer.reset() ; + timer.reset(); + + LL_RECORD_BLOCK_TIME(FTM_TEXTURE_MEMORY_CHECK); - LLFastTimer t(FTM_TEXTURE_MEMORY_CHECK); - const static S32 MIN_FREE_TEXTURE_MEMORY = 5 ; //MB - const static S32 MIN_FREE_MAIN_MEMORy = 100 ; //MB + static const S32Megabytes MIN_FREE_TEXTURE_MEMORY(20); //MB + static const S32Megabytes MIN_FREE_MAIN_MEMORY(100); //MB - bool low_mem = false ; + bool low_mem = false; if (gGLManager.mHasATIMemInfo) { S32 meminfo[4]; glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); - if(meminfo[0] / 1024 < MIN_FREE_TEXTURE_MEMORY) + if((S32Megabytes)meminfo[0] < MIN_FREE_TEXTURE_MEMORY) { - low_mem = true ; + low_mem = true; } if(!low_mem) //check main memory, only works for windows. { - LLMemory::updateMemoryInfo() ; - if(LLMemory::getAvailableMemKB() / 1024 < MIN_FREE_MAIN_MEMORy) + LLMemory::updateMemoryInfo(); + if(LLMemory::getAvailableMemKB() < MIN_FREE_TEXTURE_MEMORY) { - low_mem = true ; + low_mem = true; } } } @@ -481,47 +508,47 @@ bool LLViewerTexture::isMemoryForTextureLow() if(free_memory / 1024 < MIN_FREE_TEXTURE_MEMORY) { - low_mem = true ; + low_mem = true; } } #endif - return low_mem ; + return low_mem; } -static LLFastTimer::DeclareTimer FTM_TEXTURE_UPDATE_MEDIA("Media"); +static LLTrace::BlockTimerStatHandle FTM_TEXTURE_UPDATE_MEDIA("Media"); #if 0 -static LLFastTimer::DeclareTimer FTM_TEXTURE_UPDATE_TEST("Test"); +static LLTrace::BlockTimerStatHandle FTM_TEXTURE_UPDATE_TEST("Test"); #endif //static void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity) { - sCurrentTime = gFrameTimeSeconds ; + sCurrentTime = gFrameTimeSeconds; #if 0 LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { - LLFastTimer t(FTM_TEXTURE_UPDATE_TEST); - tester->update() ; + LL_RECORD_BLOCK_TIME(FTM_TEXTURE_UPDATE_TEST); + tester->update(); } #endif { - LLFastTimer t(FTM_TEXTURE_UPDATE_MEDIA); - LLViewerMediaTexture::updateClass() ; + LL_RECORD_BLOCK_TIME(FTM_TEXTURE_UPDATE_MEDIA); + LLViewerMediaTexture::updateClass(); } - sBoundTextureMemoryInBytes = LLImageGL::sBoundTextureMemoryInBytes;//in bytes - sTotalTextureMemoryInBytes = LLImageGL::sGlobalTextureMemoryInBytes;//in bytes - sMaxBoundTextureMemInMegaBytes = gTextureList.getMaxResidentTexMem();//in MB - sMaxTotalTextureMemInMegaBytes = gTextureList.getMaxTotalTextureMem() ;//in MB - sMaxDesiredTextureMemInBytes = MEGA_BYTES_TO_BYTES(sMaxTotalTextureMemInMegaBytes) ; //in Bytes, by default and when total used texture memory is small. + sBoundTextureMemory = LLImageGL::sBoundTextureMemory; + sTotalTextureMemory = LLImageGL::sGlobalTextureMemory; + sMaxBoundTextureMemory = gTextureList.getMaxResidentTexMem(); + sMaxTotalTextureMem = gTextureList.getMaxTotalTextureMem(); + sMaxDesiredTextureMem = sMaxTotalTextureMem; //in Bytes, by default and when total used texture memory is small. - if (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) >= sMaxBoundTextureMemInMegaBytes || - BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) >= sMaxTotalTextureMemInMegaBytes) + if (sBoundTextureMemory >= sMaxBoundTextureMemory || + sTotalTextureMemory >= sMaxTotalTextureMem) { - //when texture memory overflows, lower down the threashold to release the textures more aggressively. - sMaxDesiredTextureMemInBytes = llmin((S32)(sMaxDesiredTextureMemInBytes * 0.75f) , MEGA_BYTES_TO_BYTES(MAX_VIDEO_RAM_IN_MEGA_BYTES)) ;//512 MB + //when texture memory overflows, lower down the threshold to release the textures more aggressively. + sMaxDesiredTextureMem = llmin(F64Bytes(sMaxDesiredTextureMem) * 0.75f, F64Bytes(gMaxVideoRam)); // If we are using more texture memory than we should, // scale up the desired discard level @@ -537,8 +564,8 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity sEvaluationTimer.reset(); } else if (sDesiredDiscardBias > 0.0f && - BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < sMaxBoundTextureMemInMegaBytes * texmem_lower_bound_scale && - BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < sMaxTotalTextureMemInMegaBytes * texmem_lower_bound_scale) + sBoundTextureMemory < sMaxBoundTextureMemory * texmem_lower_bound_scale && + sTotalTextureMemory < sMaxTotalTextureMem * texmem_lower_bound_scale) { // If we are using less texture memory than we should, // scale down the desired discard level @@ -549,23 +576,22 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity } } sDesiredDiscardBias = llclamp(sDesiredDiscardBias, desired_discard_bias_min, desired_discard_bias_max); - //LLViewerTexture::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ; - F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; + F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed(); F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); sCameraMovingBias = llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1); - sCameraMovingDiscardBias = (S8)(sCameraMovingBias); + sCameraMovingDiscardBias = sCameraMovingBias; - LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && - (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ; + LLViewerTexture::sFreezeImageScalingDown = (sBoundTextureMemory < 0.75f * sMaxBoundTextureMemory * texmem_middle_bound_scale) && + (sTotalTextureMemory < 0.75f * sMaxTotalTextureMem * texmem_middle_bound_scale); } //end of static functions //------------------------------------------------------------------------------------------- const U32 LLViewerTexture::sCurrentFileVersion = 1; -LLViewerTexture::LLViewerTexture(BOOL usemipmaps) : - LLGLTexture(usemipmaps) +LLViewerTexture::LLViewerTexture(BOOL usemipmaps, bool allow_compression) : + LLGLTexture(usemipmaps, allow_compression) { init(true); @@ -573,8 +599,8 @@ LLViewerTexture::LLViewerTexture(BOOL usemipmaps) : sImageCount++; } -LLViewerTexture::LLViewerTexture(const LLUUID& id, BOOL usemipmaps) : - LLGLTexture(usemipmaps), +LLViewerTexture::LLViewerTexture(const LLUUID& id, BOOL usemipmaps, bool allow_compression) : + LLGLTexture(usemipmaps, allow_compression), mID(id) { init(true); @@ -582,8 +608,8 @@ LLViewerTexture::LLViewerTexture(const LLUUID& id, BOOL usemipmaps) : sImageCount++; } -LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) : - LLGLTexture(width, height, components, usemipmaps) +LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, bool allow_compression) : + LLGLTexture(width, height, components, usemipmaps, allow_compression) { init(true); @@ -591,8 +617,8 @@ LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 com sImageCount++; } -LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) : - LLGLTexture(raw, usemipmaps) +LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps, bool allow_compression) : + LLGLTexture(raw, usemipmaps, allow_compression) { init(true); @@ -602,6 +628,7 @@ LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) : LLViewerTexture::~LLViewerTexture() { + // LL_DEBUGS("Avatar") << mID << LL_ENDL; cleanup(); sImageCount--; } @@ -609,37 +636,66 @@ LLViewerTexture::~LLViewerTexture() // virtual void LLViewerTexture::init(bool firstinit) { + mSelectedTime = 0.f; mMaxVirtualSize = 0.f; - mNeedsGLTexture = FALSE ; + mNeedsGLTexture = FALSE; mMaxVirtualSizeResetInterval = 1; - mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval ; - mAdditionalDecodePriority = 0.f ; - mParcelMedia = NULL ; + mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval; + mAdditionalDecodePriority = 0.f; + mParcelMedia = NULL; - mNumVolumes = 0; - mFaceList[LLRender::DIFFUSE_MAP].clear() ; - mFaceList[LLRender::NORMAL_MAP].clear() ; - mFaceList[LLRender::SPECULAR_MAP].clear() ; + memset(&mNumVolumes, 0, sizeof(U32)* LLRender::NUM_VOLUME_TEXTURE_CHANNELS); + mFaceList[LLRender::DIFFUSE_MAP].clear(); + mFaceList[LLRender::NORMAL_MAP].clear(); + mFaceList[LLRender::SPECULAR_MAP].clear(); mNumFaces[LLRender::DIFFUSE_MAP] = mNumFaces[LLRender::NORMAL_MAP] = - mNumFaces[LLRender::SPECULAR_MAP] = 0 ; - mVolumeList.clear(); + mNumFaces[LLRender::SPECULAR_MAP] = 0; + + mVolumeList[LLRender::LIGHT_TEX].clear(); + mVolumeList[LLRender::SCULPT_TEX].clear(); } //virtual S8 LLViewerTexture::getType() const { - return LLViewerTexture::LOCAL_TEXTURE ; + return LLViewerTexture::LOCAL_TEXTURE; } void LLViewerTexture::cleanup() { - mFaceList[LLRender::DIFFUSE_MAP].clear() ; - mFaceList[LLRender::NORMAL_MAP].clear() ; - mFaceList[LLRender::SPECULAR_MAP].clear() ; - mVolumeList.clear(); + notifyAboutMissingAsset(); + + mFaceList[LLRender::DIFFUSE_MAP].clear(); + mFaceList[LLRender::NORMAL_MAP].clear(); + mFaceList[LLRender::SPECULAR_MAP].clear(); + mVolumeList[LLRender::LIGHT_TEX].clear(); + mVolumeList[LLRender::SCULPT_TEX].clear(); +} + +void LLViewerTexture::notifyAboutCreatingTexture() +{ + for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) + { + for(U32 f = 0; f < mNumFaces[ch]; f++) + { + mFaceList[ch][f]->notifyAboutCreatingTexture(this); + } + } +} + +void LLViewerTexture::notifyAboutMissingAsset() +{ + for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) + { + for(U32 f = 0; f < mNumFaces[ch]; f++) + { + mFaceList[ch][f]->notifyAboutMissingAsset(this); + } + } } +// virtual void LLViewerTexture::dump() { LLGLTexture::dump(); @@ -649,6 +705,32 @@ void LLViewerTexture::dump() << LL_ENDL; } +void LLViewerTexture::setBoostLevel(S32 level) +{ + if(mBoostLevel != level) + { + mBoostLevel = level; + if(mBoostLevel != LLViewerTexture::BOOST_NONE && + mBoostLevel != LLViewerTexture::BOOST_ALM && + mBoostLevel != LLViewerTexture::BOOST_SELECTED && + mBoostLevel != LLViewerTexture::BOOST_ICON) + { + setNoDelete(); + } + } + + if (mBoostLevel == LLViewerTexture::BOOST_SELECTED) + { + mSelectedTime = gFrameTimeSeconds; + } + +} + +bool LLViewerTexture::isActiveFetching() +{ + return false; +} + bool LLViewerTexture::bindDefaultImage(S32 stage) { if (stage < 0) return false; @@ -661,7 +743,7 @@ bool LLViewerTexture::bindDefaultImage(S32 stage) } if (!res && LLViewerTexture::sNullImagep.notNull() && (this != LLViewerTexture::sNullImagep)) { - res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep) ; + res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep); } if (!res) { @@ -670,13 +752,13 @@ bool LLViewerTexture::bindDefaultImage(S32 stage) stop_glerror(); //check if there is cached raw image and switch to it if possible - switchToCachedImage() ; + switchToCachedImage(); #if 0 LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { - tester->updateGrayTextureBinding() ; + tester->updateGrayTextureBinding(); } #endif return res; @@ -697,17 +779,17 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co { if(needs_gltexture) { - mNeedsGLTexture = TRUE ; + mNeedsGLTexture = TRUE; } virtual_size *= sTexelPixelRatio; if(!mMaxVirtualSizeResetCounter) { //flag to reset the values because the old values are used. - resetMaxVirtualSizeResetCounter() ; + resetMaxVirtualSizeResetCounter(); mMaxVirtualSize = virtual_size; - mAdditionalDecodePriority = 0.f ; - mNeedsGLTexture = needs_gltexture ; + mAdditionalDecodePriority = 0.f; + mNeedsGLTexture = needs_gltexture; } else if (virtual_size > mMaxVirtualSize) { @@ -717,15 +799,15 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co void LLViewerTexture::resetTextureStats() { - mMaxVirtualSize = 0.0f ; - mAdditionalDecodePriority = 0.f ; - mMaxVirtualSizeResetCounter = 0 ; + mMaxVirtualSize = 0.0f; + mAdditionalDecodePriority = 0.f; + mMaxVirtualSizeResetCounter = 0; } //virtual F32 LLViewerTexture::getMaxVirtualSize() { - return mMaxVirtualSize ; + return mMaxVirtualSize; } //virtual @@ -741,12 +823,12 @@ void LLViewerTexture::addFace(U32 ch, LLFace* facep) if(mNumFaces[ch] >= mFaceList[ch].size()) { - mFaceList[ch].resize(2 * mNumFaces[ch] + 1) ; + mFaceList[ch].resize(2 * mNumFaces[ch] + 1); } - mFaceList[ch][mNumFaces[ch]] = facep ; - facep->setIndexInTex(ch, mNumFaces[ch]) ; - mNumFaces[ch]++ ; - mLastFaceListUpdateTimer.reset() ; + mFaceList[ch][mNumFaces[ch]] = facep; + facep->setIndexInTex(ch, mNumFaces[ch]); + mNumFaces[ch]++; + mLastFaceListUpdateTimer.reset(); } //virtual @@ -760,18 +842,18 @@ void LLViewerTexture::removeFace(U32 ch, LLFace* facep) if(mNumFaces[ch] > 1) { - S32 index = facep->getIndexInTex(ch) ; + S32 index = facep->getIndexInTex(ch); llassert(index < (S32)mFaceList[ch].size()); llassert(index < (S32)mNumFaces[ch]); - mFaceList[ch][index] = mFaceList[ch][--mNumFaces[ch]] ; - mFaceList[ch][index]->setIndexInTex(ch, index) ; + mFaceList[ch][index] = mFaceList[ch][--mNumFaces[ch]]; + mFaceList[ch][index]->setIndexInTex(ch, index); } else { - mFaceList[ch].clear() ; - mNumFaces[ch] = 0 ; + mFaceList[ch].clear(); + mNumFaces[ch] = 0; } - mLastFaceListUpdateTimer.reset() ; + mLastFaceListUpdateTimer.reset(); } S32 LLViewerTexture::getTotalNumFaces() const @@ -794,46 +876,46 @@ S32 LLViewerTexture::getNumFaces(U32 ch) const //virtual -void LLViewerTexture::addVolume(LLVOVolume* volumep) +void LLViewerTexture::addVolume(U32 ch, LLVOVolume* volumep) { - if( mNumVolumes >= mVolumeList.size()) + if (mNumVolumes[ch] >= mVolumeList[ch].size()) { - mVolumeList.resize(2 * mNumVolumes + 1) ; + mVolumeList[ch].resize(2 * mNumVolumes[ch] + 1); } - mVolumeList[mNumVolumes] = volumep ; - volumep->setIndexInTex(mNumVolumes) ; - mNumVolumes++ ; - mLastVolumeListUpdateTimer.reset() ; + mVolumeList[ch][mNumVolumes[ch]] = volumep; + volumep->setIndexInTex(ch, mNumVolumes[ch]); + mNumVolumes[ch]++; + mLastVolumeListUpdateTimer.reset(); } //virtual -void LLViewerTexture::removeVolume(LLVOVolume* volumep) +void LLViewerTexture::removeVolume(U32 ch, LLVOVolume* volumep) { - if(mNumVolumes > 1) + if (mNumVolumes[ch] > 1) { - S32 index = volumep->getIndexInTex() ; - llassert(index < (S32)mVolumeList.size()); - llassert(index < (S32)mNumVolumes); - mVolumeList[index] = mVolumeList[--mNumVolumes] ; - mVolumeList[index]->setIndexInTex(index) ; + S32 index = volumep->getIndexInTex(ch); + llassert(index < (S32)mVolumeList[ch].size()); + llassert(index < (S32)mNumVolumes[ch]); + mVolumeList[ch][index] = mVolumeList[ch][--mNumVolumes[ch]]; + mVolumeList[ch][index]->setIndexInTex(ch, index); } else { - mVolumeList.clear() ; - mNumVolumes = 0 ; + mVolumeList[ch].clear(); + mNumVolumes[ch] = 0; } - mLastVolumeListUpdateTimer.reset() ; + mLastVolumeListUpdateTimer.reset(); } -S32 LLViewerTexture::getNumVolumes() const +S32 LLViewerTexture::getNumVolumes(U32 ch) const { - return mNumVolumes ; + return mNumVolumes[ch]; } void LLViewerTexture::reorganizeFaceList() { static const F32 MAX_WAIT_TIME = 20.f; // seconds - static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ; + static const U32 MAX_EXTRA_BUFFER_SIZE = 4; if(mLastFaceListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) { @@ -844,43 +926,47 @@ void LLViewerTexture::reorganizeFaceList() { if(mNumFaces[i] + MAX_EXTRA_BUFFER_SIZE > mFaceList[i].size()) { - return ; + return; } - + mFaceList[i].erase(mFaceList[i].begin() + mNumFaces[i], mFaceList[i].end()); } - mLastFaceListUpdateTimer.reset() ; + mLastFaceListUpdateTimer.reset(); } void LLViewerTexture::reorganizeVolumeList() { static const F32 MAX_WAIT_TIME = 20.f; // seconds - static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ; + static const U32 MAX_EXTRA_BUFFER_SIZE = 4; + - if(mNumVolumes + MAX_EXTRA_BUFFER_SIZE > mVolumeList.size()) + for (U32 i = 0; i < LLRender::NUM_VOLUME_TEXTURE_CHANNELS; ++i) { - return ; + if (mNumVolumes[i] + MAX_EXTRA_BUFFER_SIZE > mVolumeList[i].size()) + { + return; + } } if(mLastVolumeListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) { - return ; + return; } - mLastVolumeListUpdateTimer.reset() ; - mVolumeList.erase(mVolumeList.begin() + mNumVolumes, mVolumeList.end()); + mLastVolumeListUpdateTimer.reset(); + for (U32 i = 0; i < LLRender::NUM_VOLUME_TEXTURE_CHANNELS; ++i) + { + mVolumeList[i].erase(mVolumeList[i].begin() + mNumVolumes[i], mVolumeList[i].end()); + } } - - //virtual void LLViewerTexture::switchToCachedImage() { //nothing here. } - //virtual void LLViewerTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) { @@ -889,7 +975,7 @@ void LLViewerTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) BOOL LLViewerTexture::isLargeImage() { - return (S32)mTexelsPerImage > LLViewerTexture::sMinLargeImageSize ; + return (S32)mTexelsPerImage > LLViewerTexture::sMinLargeImageSize; } //virtual @@ -899,7 +985,7 @@ void LLViewerTexture::updateBindStatsForTester() LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { - tester->updateTextureBindingStats(this) ; + tester->updateTextureBindingStats(this); } #endif } @@ -908,43 +994,71 @@ void LLViewerTexture::updateBindStatsForTester() //end of LLViewerTexture //---------------------------------------------------------------------------------------------- +const std::string& fttype_to_string(const FTType& fttype) +{ + static const std::string ftt_unknown("FTT_UNKNOWN"); + static const std::string ftt_default("FTT_DEFAULT"); + static const std::string ftt_server_bake("FTT_SERVER_BAKE"); + static const std::string ftt_host_bake("FTT_HOST_BAKE"); + static const std::string ftt_map_tile("FTT_MAP_TILE"); + static const std::string ftt_local_file("FTT_LOCAL_FILE"); + static const std::string ftt_error("FTT_ERROR"); + switch(fttype) + { + case FTT_UNKNOWN: return ftt_unknown; break; + case FTT_DEFAULT: return ftt_default; break; + case FTT_SERVER_BAKE: return ftt_server_bake; break; + case FTT_HOST_BAKE: return ftt_host_bake; break; + case FTT_MAP_TILE: return ftt_map_tile; break; + case FTT_LOCAL_FILE: return ftt_local_file; break; + } + return ftt_error; +} + //---------------------------------------------------------------------------------------------- //start of LLViewerFetchedTexture //---------------------------------------------------------------------------------------------- -LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps) - : LLViewerTexture(id, usemipmaps), - mTargetHost(host) +LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host, BOOL usemipmaps) + : LLViewerTexture(id, usemipmaps, f_type == FTT_DEFAULT || f_type == FTT_MAP_TILE), + mTargetHost(host), mFTType(f_type) { - init(TRUE) ; - generateGLTexture() ; - mGLTexturep->setNeedsAlphaAndPickMask(TRUE) ; + init(TRUE); + if (mFTType == FTT_HOST_BAKE) + { + LL_WARNS() << "Unsupported fetch type " << mFTType << LL_ENDL; + } + generateGLTexture(); + mGLTexturep->setNeedsAlphaAndPickMask(TRUE); } -LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps) - : LLViewerTexture(raw, usemipmaps) +LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps) + : LLViewerTexture(raw, usemipmaps, f_type == FTT_DEFAULT || f_type == FTT_MAP_TILE), + mFTType(f_type) { - init(TRUE) ; + init(TRUE); + mGLTexturep->setNeedsAlphaAndPickMask(TRUE); } -LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps) - : LLViewerTexture(id, usemipmaps), - mUrl(url) +LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps) + : LLViewerTexture(id, usemipmaps, f_type == FTT_DEFAULT || f_type == FTT_MAP_TILE), + mUrl(url), mFTType(f_type) { - init(TRUE) ; - generateGLTexture() ; - mGLTexturep->setNeedsAlphaAndPickMask(TRUE) ; + init(TRUE); + generateGLTexture(); + mGLTexturep->setNeedsAlphaAndPickMask(TRUE); } void LLViewerFetchedTexture::init(bool firstinit) { mOrigWidth = 0; mOrigHeight = 0; + mHasAux = FALSE; mNeedsAux = FALSE; mRequestedDiscardLevel = -1; mRequestedDownloadPriority = 0.f; mFullyLoaded = FALSE; - mCanUseHTTP = true ; + mCanUseHTTP = true; mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; @@ -952,7 +1066,7 @@ void LLViewerFetchedTexture::init(bool firstinit) mKnownDrawWidth = 0; mKnownDrawHeight = 0; - mKnownDrawSizeChanged = FALSE ; + mKnownDrawSizeChanged = FALSE; if (firstinit) { @@ -965,7 +1079,7 @@ void LLViewerFetchedTexture::init(bool firstinit) mIsMissingAsset = FALSE; mLoadedCallbackDesiredDiscardLevel = S8_MAX; - mPauseLoadedCallBacks = FALSE ; + mPauseLoadedCallBacks = FALSE; mNeedsCreateTexture = FALSE; @@ -980,23 +1094,24 @@ void LLViewerFetchedTexture::init(bool firstinit) mDownloadProgress = 0.f; mFetchDeltaTime = 999999.f; mRequestDeltaTime = 0.f; - mForSculpt = FALSE ; - mIsFetched = FALSE ; + mForSculpt = FALSE; + mIsFetched = FALSE; if(!firstinit && mCachedRawImage.notNull()) mCachedRawImage->setInCache(false); - mCachedRawImage = NULL ; - mCachedRawDiscardLevel = -1 ; - mCachedRawImageReady = FALSE ; + mCachedRawImage = NULL; + mCachedRawDiscardLevel = -1; + mCachedRawImageReady = FALSE; - mSavedRawImage = NULL ; - mForceToSaveRawImage = FALSE ; - mSaveRawImage = FALSE ; - mSavedRawDiscardLevel = -1 ; - mDesiredSavedRawDiscardLevel = -1 ; - mLastReferencedSavedRawImageTime = 0.0f ; - mKeptSavedRawImageTime = 0.f ; + mSavedRawImage = NULL; + mForceToSaveRawImage = FALSE; + mSaveRawImage = FALSE; + mSavedRawDiscardLevel = -1; + mDesiredSavedRawDiscardLevel = -1; + mLastReferencedSavedRawImageTime = 0.0f; + mKeptSavedRawImageTime = 0.f; mLastCallBackActiveTime = 0.f; + mForceCallbackFetch = FALSE; } LLViewerFetchedTexture::~LLViewerFetchedTexture() @@ -1014,7 +1129,12 @@ LLViewerFetchedTexture::~LLViewerFetchedTexture() //virtual S8 LLViewerFetchedTexture::getType() const { - return LLViewerTexture::FETCHED_TEXTURE ; + return LLViewerTexture::FETCHED_TEXTURE; +} + +FTType LLViewerFetchedTexture::getFTType() const +{ + return mFTType; } void LLViewerFetchedTexture::cleanup() @@ -1026,7 +1146,7 @@ void LLViewerFetchedTexture::cleanup() // We never finished loading the image. Indicate failure. // Note: this allows mLoadedCallbackUserData to be cleaned up. entryp->mCallback( FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData ); - entryp->removeTexture(this) ; + entryp->removeTexture(this); delete entryp; } mLoadedCallbackList.clear(); @@ -1036,10 +1156,10 @@ void LLViewerFetchedTexture::cleanup() destroyRawImage(); if(mCachedRawImage.notNull()) mCachedRawImage->setInCache(false); - mCachedRawImage = NULL ; - mCachedRawDiscardLevel = -1 ; - mCachedRawImageReady = FALSE ; - mSavedRawImage = NULL ; + mCachedRawImage = NULL; + mCachedRawDiscardLevel = -1; + mCachedRawImageReady = FALSE; + mSavedRawImage = NULL; mSavedRawDiscardLevel = -1; } @@ -1069,43 +1189,43 @@ void LLViewerFetchedTexture::forceRefetch() void LLViewerFetchedTexture::setForSculpt() { - static const S32 MAX_INTERVAL = 8 ; //frames + static const S32 MAX_INTERVAL = 8; //frames - mForSculpt = TRUE ; + mForSculpt = TRUE; if(isForSculptOnly() && hasGLTexture() && !getBoundRecently()) { - destroyGLTexture() ; //sculpt image does not need gl texture. + destroyGLTexture(); //sculpt image does not need gl texture. mTextureState = ACTIVE; } - checkCachedRawSculptImage() ; - setMaxVirtualSizeResetInterval(MAX_INTERVAL) ; + checkCachedRawSculptImage(); + setMaxVirtualSizeResetInterval(MAX_INTERVAL); } BOOL LLViewerFetchedTexture::isForSculptOnly() const { - return mForSculpt && !mNeedsGLTexture ; + return mForSculpt && !mNeedsGLTexture; } BOOL LLViewerFetchedTexture::isDeleted() { - return mTextureState == DELETED ; + return mTextureState == DELETED; } BOOL LLViewerFetchedTexture::isInactive() { - return mTextureState == INACTIVE ; + return mTextureState == INACTIVE; } BOOL LLViewerFetchedTexture::isDeletionCandidate() { - return mTextureState == DELETION_CANDIDATE ; + return mTextureState == DELETION_CANDIDATE; } void LLViewerFetchedTexture::setDeletionCandidate() { if(mGLTexturep.notNull() && mGLTexturep->getTexName() && (mTextureState == INACTIVE)) { - mTextureState = DELETION_CANDIDATE ; + mTextureState = DELETION_CANDIDATE; } } @@ -1114,7 +1234,7 @@ void LLViewerFetchedTexture::setInactive() { if(mTextureState == ACTIVE && mGLTexturep.notNull() && mGLTexturep->getTexName() && !mGLTexturep->getBoundRecently()) { - mTextureState = INACTIVE ; + mTextureState = INACTIVE; } } @@ -1156,60 +1276,61 @@ void LLViewerFetchedTexture::dump() // ONLY called from LLViewerFetchedTextureList void LLViewerFetchedTexture::destroyTexture() { - if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes * 0.95f)//not ready to release unused memory. + if(LLImageGL::sGlobalTextureMemory < sMaxDesiredTextureMem * 0.95f)//not ready to release unused memory. { return ; } if (mNeedsCreateTexture)//return if in the process of generating a new texture. { - return ; + return; } - - destroyGLTexture() ; - mFullyLoaded = FALSE ; + + //LL_DEBUGS("Avatar") << mID << LL_ENDL; + destroyGLTexture(); + mFullyLoaded = FALSE; } void LLViewerFetchedTexture::addToCreateTexture() { - bool force_update = false ; + bool force_update = false; if (getComponents() != mRawImage->getComponents()) { // We've changed the number of components, so we need to move any // objects using this pool to a different pool. mComponents = mRawImage->getComponents(); - mGLTexturep->setComponents(mComponents) ; - force_update = true ; + mGLTexturep->setComponents(mComponents); + force_update = true; for (U32 j = 0; j < LLRender::NUM_TEXTURE_CHANNELS; ++j) { llassert(mNumFaces[j] <= mFaceList[j].size()); - for(U32 i = 0 ; i < mNumFaces[j]; i++) + for(U32 i = 0; i < mNumFaces[j]; i++) { - mFaceList[j][i]->dirtyTexture() ; + mFaceList[j][i]->dirtyTexture(); } } //discard the cached raw image and the saved raw image - mCachedRawImageReady = FALSE ; - mCachedRawDiscardLevel = -1 ; + mCachedRawImageReady = FALSE; + mCachedRawDiscardLevel = -1; if(mCachedRawImage.notNull()) mCachedRawImage->setInCache(false); - mCachedRawImage = NULL ; - mSavedRawDiscardLevel = -1 ; - mSavedRawImage = NULL ; + mCachedRawImage = NULL; + mSavedRawDiscardLevel = -1; + mSavedRawImage = NULL; } if(isForSculptOnly()) { //just update some variables, not to create a real GL texture. - createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE) ; - mNeedsCreateTexture = FALSE ; + createGLTexture(mRawDiscardLevel, mRawImage, nullptr, FALSE); + mNeedsCreateTexture = FALSE; destroyRawImage(); } else if(!force_update && getDiscardLevel() > -1 && getDiscardLevel() <= mRawDiscardLevel) { - mNeedsCreateTexture = FALSE ; + mNeedsCreateTexture = FALSE; destroyRawImage(); } else @@ -1229,11 +1350,11 @@ void LLViewerFetchedTexture::addToCreateTexture() //scale it down to size >= LLViewerTexture::sMinLargeImageSize if(w * h > LLViewerTexture::sMinLargeImageSize) { - S32 d_level = llmin(mRequestedDiscardLevel, (S32)mDesiredDiscardLevel) - mRawDiscardLevel ; + S32 d_level = llmin(mRequestedDiscardLevel, (S32)mDesiredDiscardLevel) - mRawDiscardLevel; if(d_level > 0) { - S32 i = 0 ; + S32 i = 0; while((d_level > 0) && ((w >> i) * (h >> i) > LLViewerTexture::sMinLargeImageSize)) { i++; @@ -1241,18 +1362,18 @@ void LLViewerFetchedTexture::addToCreateTexture() } if(i > 0) { - mRawDiscardLevel += i ; + mRawDiscardLevel += i; if(mRawDiscardLevel >= getDiscardLevel() && getDiscardLevel() > 0) { - mNeedsCreateTexture = FALSE ; + mNeedsCreateTexture = FALSE; destroyRawImage(); - return ; + return; } { //make a duplicate in case somebody else is using this raw image mRawImage = mRawImage->duplicate(); - mRawImage->scale(w >> i, h >> i) ; + mRawImage->scale(w >> i, h >> i); } } } @@ -1262,18 +1383,18 @@ void LLViewerFetchedTexture::addToCreateTexture() mNeedsCreateTexture = TRUE; gTextureList.mCreateTextureList.insert(this); } - return ; + return; } // ONLY called from LLViewerTextureList -BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) +BOOL LLViewerFetchedTexture::createTexture(LLImageGL::GLTextureName* usename) { if (!mNeedsCreateTexture) { destroyRawImage(); return FALSE; } - mNeedsCreateTexture = FALSE; + mNeedsCreateTexture = FALSE; if (mRawImage.isNull()) { LL_WARNS() << "LLViewerTexture trying to create texture with no Raw Image" << LL_ENDL; @@ -1283,75 +1404,114 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) // mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize()) // << mID.getString() << LL_ENDL; BOOL res = TRUE; - if (!gNoRender) + + // store original size only for locally-sourced images + if (mUrl.compare(0, 7, "file://") == 0) { - // store original size only for locally-sourced images - if (mUrl.compare(0, 7, "file://") == 0) - { - mOrigWidth = mRawImage->getWidth(); - mOrigHeight = mRawImage->getHeight(); + mOrigWidth = mRawImage->getWidth(); + mOrigHeight = mRawImage->getHeight(); - if (mBoostLevel == BOOST_PREVIEW) - { - mRawImage->biasedScaleToPowerOfTwo(1024); - } - else - { // leave black border, do not scale image content - mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE); - } - - mFullWidth = mRawImage->getWidth(); - mFullHeight = mRawImage->getHeight(); - setTexelsPerImage(); + if (mBoostLevel == BOOST_PREVIEW) + { + mRawImage->biasedScaleToPowerOfTwo(1024); } else - { - mOrigWidth = mFullWidth; - mOrigHeight = mFullHeight; - } - - bool size_okay = true; - - U32 raw_width = mRawImage->getWidth() << mRawDiscardLevel; - U32 raw_height = mRawImage->getHeight() << mRawDiscardLevel; - if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE ) - { - LL_INFOS() << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << LL_ENDL; - size_okay = false; - } - - if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight())) - { - // A non power-of-two image was uploaded (through a non standard client) - LL_INFOS() << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << LL_ENDL; - size_okay = false; + { // leave black border, do not scale image content + mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE); } - if( !size_okay ) + mFullWidth = mRawImage->getWidth(); + mFullHeight = mRawImage->getHeight(); + setTexelsPerImage(); + } + else + { + mOrigWidth = mFullWidth; + mOrigHeight = mFullHeight; + } + + if (!mRawImage->mComment.empty()) + { + // a is for uploader + // z is for time + // K is the whole thing (just coz) + std::string comment = mRawImage->getComment(); + mComment['K'] = comment; + size_t position = 0; + size_t length = comment.length(); + while (position < length) { - // An inappropriately-sized image was uploaded (through a non standard client) - // We treat these images as missing assets which causes them to - // be renderd as 'missing image' and to stop requesting data - LL_WARNS() << "!size_ok, setting as missing" << LL_ENDL; - setIsMissingAsset(); - destroyRawImage(); - return FALSE; + std::size_t equals_position = comment.find('=', position); + if (equals_position != std::string::npos) + { + S8 type = comment.at(equals_position - 1); + position = comment.find('&', position); + if (position != std::string::npos) + { + mComment[type] = comment.substr(equals_position + 1, position - (equals_position + 1)); + position++; + } + else + { + mComment[type] = comment.substr(equals_position + 1, length - (equals_position + 1)); + } + } + else + { + position = equals_position; + } } - - //if(!(res = insertToAtlas())) - //{ - res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel); - //resetFaceAtlas() ; - //} - setActive() ; } + bool size_okay = true; + + S32 discard_level = mRawDiscardLevel; + if (mRawDiscardLevel < 0) + { + LL_DEBUGS() << "Negative raw discard level when creating image: " << mRawDiscardLevel << LL_ENDL; + discard_level = 0; + } + + U32 raw_width = mRawImage->getWidth() << discard_level; + U32 raw_height = mRawImage->getHeight() << discard_level; + + if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE ) + { + LL_INFOS() << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << LL_ENDL; + size_okay = false; + } + + if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight())) + { + // A non power-of-two image was uploaded (through a non standard client) + LL_INFOS() << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << LL_ENDL; + size_okay = false; + } + + if( !size_okay ) + { + // An inappropriately-sized image was uploaded (through a non standard client) + // We treat these images as missing assets which causes them to + // be renderd as 'missing image' and to stop requesting data + LL_WARNS() << "!size_ok, setting as missing" << LL_ENDL; + setIsMissingAsset(); + destroyRawImage(); + return FALSE; + } + + res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel); + + notifyAboutCreatingTexture(); + + setActive(); + if (!needsToSaveRawImage()) { mNeedsAux = FALSE; destroyRawImage(); } + return res; } @@ -1361,11 +1521,11 @@ void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height) { if(mKnownDrawWidth < width || mKnownDrawHeight < height) { - mKnownDrawWidth = llmax(mKnownDrawWidth, width) ; - mKnownDrawHeight = llmax(mKnownDrawHeight, height) ; + mKnownDrawWidth = llmax(mKnownDrawWidth, width); + mKnownDrawHeight = llmax(mKnownDrawHeight, height); - mKnownDrawSizeChanged = TRUE ; - mFullyLoaded = FALSE ; + mKnownDrawSizeChanged = TRUE; + mFullyLoaded = FALSE; } addTextureStats((F32)(mKnownDrawWidth * mKnownDrawHeight)); } @@ -1377,29 +1537,45 @@ void LLViewerFetchedTexture::processTextureStats() { if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more { - mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ; - mFullyLoaded = FALSE ; + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel); + mFullyLoaded = FALSE; } } else { - updateVirtualSize() ; + updateVirtualSize(); - static LLCachedControl textures_fullres(gSavedSettings,"TextureLoadFullRes"); + static LLCachedControl textures_fullres(gSavedSettings,"TextureLoadFullRes", false); if (textures_fullres) { mDesiredDiscardLevel = 0; } + else if (!LLPipeline::sRenderDeferred && mBoostLevel == LLGLTexture::BOOST_ALM) + { + mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; + } + else if (mDontDiscard && mBoostLevel == LLGLTexture::BOOST_ICON) + { + if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) + { + mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + } + else + { + mDesiredDiscardLevel = 0; + } + } else if(!mFullWidth || !mFullHeight) { - mDesiredDiscardLevel = llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel) ; + mDesiredDiscardLevel = llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel); } else { + U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight) { - if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) + if ((U32)mFullWidth > desired_size || (U32)mFullHeight > desired_size) { mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 } @@ -1411,36 +1587,36 @@ void LLViewerFetchedTexture::processTextureStats() else if(mKnownDrawSizeChanged)//known draw size is set { mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, - log((F32)mFullHeight / mKnownDrawHeight) / log_2) ; - mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ; - mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ; + log((F32)mFullHeight / mKnownDrawHeight) / log_2); + mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()); + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel); } - mKnownDrawSizeChanged = FALSE ; + mKnownDrawSizeChanged = FALSE; if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel)) { - mFullyLoaded = TRUE ; + mFullyLoaded = TRUE; } } } if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) //force to refetch the texture. { - mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel) ; + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel); if(getDiscardLevel() < 0 || getDiscardLevel() > mDesiredDiscardLevel) { - mFullyLoaded = FALSE ; + mFullyLoaded = FALSE; } } } -const F32 MAX_PRIORITY_PIXEL = 999.f ; //pixel area -const F32 PRIORITY_BOOST_LEVEL_FACTOR = 1000.f ; //boost level -const F32 PRIORITY_DELTA_DISCARD_LEVEL_FACTOR = 100000.f ; //delta discard -const S32 MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY = 4 ; -const F32 PRIORITY_ADDITIONAL_FACTOR = 1000000.f ; //additional -const S32 MAX_ADDITIONAL_LEVEL_FOR_PRIORITY = 8 ; -const F32 PRIORITY_BOOST_HIGH_FACTOR = 10000000.f ;//boost high +const F32 MAX_PRIORITY_PIXEL = 999.f; //pixel area +const F32 PRIORITY_BOOST_LEVEL_FACTOR = 1000.f; //boost level +const F32 PRIORITY_DELTA_DISCARD_LEVEL_FACTOR = 100000.f; //delta discard +const S32 MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY = 4; +const F32 PRIORITY_ADDITIONAL_FACTOR = 1000000.f; //additional +const S32 MAX_ADDITIONAL_LEVEL_FOR_PRIORITY = 8; +const F32 PRIORITY_BOOST_HIGH_FACTOR = 10000000.f;//boost high F32 LLViewerFetchedTexture::calcDecodePriority() { #ifndef LL_RELEASE_FOR_DOWNLOAD @@ -1456,7 +1632,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority() } if(mFullyLoaded && !mForceToSaveRawImage)//already loaded for static texture { - return -1.0f ; //alreay fetched + return -1.0f; //alreay fetched } S32 cur_discard = getCurrentDiscardLevelForFetching(); @@ -1471,7 +1647,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority() } else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1) { - priority = -2.0f ; + priority = -2.0f; } else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel) { @@ -1508,7 +1684,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority() S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired; ddiscard = llclamp(ddiscard, 0, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY); priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR; - setAdditionalDecodePriority(1.0f) ;//boost the textures without any data so far. + setAdditionalDecodePriority(0.1f);//boost the textures without any data so far. } else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel)) { @@ -1543,13 +1719,13 @@ F32 LLViewerFetchedTexture::calcDecodePriority() // [10,000,000] + [1,000,000-9,000,000] + [100,000-500,000] + [1-20,000] + [0-999] if (priority > 0.0f) { - bool large_enough = mCachedRawImageReady && ((S32)mTexelsPerImage > sMinLargeImageSize) ; + bool large_enough = mCachedRawImageReady && ((S32)mTexelsPerImage > sMinLargeImageSize); if(large_enough) { //Note: //to give small, low-priority textures some chance to be fetched, //cut the priority in half if the texture size is larger than 256 * 256 and has a 64*64 ready. - priority *= 0.5f ; + priority *= 0.5f; } pixel_priority = llclamp(pixel_priority, 0.0f, MAX_PRIORITY_PIXEL); @@ -1568,7 +1744,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority() //Note: //to give small, low-priority textures some chance to be fetched, //if high priority texture has a 64*64 ready, lower its fetching priority. - setAdditionalDecodePriority(0.5f) ; + setAdditionalDecodePriority(0.5f); } else { @@ -1585,7 +1761,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority() //Note: //to give small, low-priority textures some chance to be fetched, //cut the additional priority to a quarter if the texture size is larger than 256 * 256 and has a 64*64 ready. - additional *= 0.25f ; + additional *= 0.25f; } priority += additional; } @@ -1600,9 +1776,9 @@ F32 LLViewerFetchedTexture::maxDecodePriority() PRIORITY_ADDITIONAL_FACTOR * (MAX_ADDITIONAL_LEVEL_FOR_PRIORITY + 1) + //additional (view dependent factors) PRIORITY_DELTA_DISCARD_LEVEL_FACTOR * (MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY + 1) + //delta discard PRIORITY_BOOST_LEVEL_FACTOR * (BOOST_MAX_LEVEL - 1) + //boost level - MAX_PRIORITY_PIXEL + 1.0f ; //pixel area. + MAX_PRIORITY_PIXEL + 1.0f; //pixel area. - return max_priority ; + return max_priority; } //============================================================================ @@ -1615,7 +1791,7 @@ void LLViewerFetchedTexture::setDecodePriority(F32 priority) if(mDecodePriority < F_ALMOST_ZERO) { - mStopFetchingTimer.reset() ; + mStopFetchingTimer.reset(); } } @@ -1632,16 +1808,16 @@ void LLViewerFetchedTexture::updateVirtualSize() { if(!mMaxVirtualSizeResetCounter) { - addTextureStats(0.f, FALSE) ;//reset + addTextureStats(0.f, FALSE);//reset } for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) { llassert(mNumFaces[ch] <= mFaceList[ch].size()); - for(U32 i = 0 ; i < mNumFaces[ch]; i++) + for(U32 i = 0; i < mNumFaces[ch]; i++) { - LLFace* facep = mFaceList[ch][i] ; + LLFace* facep = mFaceList[ch][i]; if( facep ) { LLDrawable* drawable = facep->getDrawable(); @@ -1649,43 +1825,73 @@ void LLViewerFetchedTexture::updateVirtualSize() { if(drawable->isRecentlyVisible()) { - if (getBoostLevel() == LLViewerTexture::BOOST_NONE && - drawable->getVObj() && drawable->getVObj()->isSelected()) - { - setBoostLevel(LLViewerTexture::BOOST_SELECTED); + if ((getBoostLevel() == LLViewerTexture::BOOST_NONE || getBoostLevel() == LLViewerTexture::BOOST_ALM) + && drawable->getVObj() + && drawable->getVObj()->isSelected()) + { + setBoostLevel(LLViewerTexture::BOOST_SELECTED); } - addTextureStats(facep->getVirtualSize()) ; - setAdditionalDecodePriority(facep->getImportanceToCamera()) ; + addTextureStats(facep->getVirtualSize()); + setAdditionalDecodePriority(facep->getImportanceToCamera()); } } } } } + //reset whether or not a face was selected after 10 seconds + const F32 SELECTION_RESET_TIME = 10.f; + + if (getBoostLevel() == LLViewerTexture::BOOST_SELECTED && + gFrameTimeSeconds - mSelectedTime > SELECTION_RESET_TIME) + { + setBoostLevel(LLViewerTexture::BOOST_NONE); + } if(mMaxVirtualSizeResetCounter > 0) { mMaxVirtualSizeResetCounter--; } - reorganizeFaceList() ; + reorganizeFaceList(); reorganizeVolumeList(); } S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching() { - S32 current_discard = getDiscardLevel() ; + S32 current_discard = getDiscardLevel(); if(mForceToSaveRawImage) { if(mSavedRawDiscardLevel < 0 || current_discard < 0) { - current_discard = -1 ; + current_discard = -1; } else { - current_discard = llmax(current_discard, mSavedRawDiscardLevel) ; + current_discard = llmax(current_discard, mSavedRawDiscardLevel); } } - return current_discard ; + return current_discard; +} + +bool LLViewerFetchedTexture::setDebugFetching(S32 debug_level) +{ + if(debug_level < 0) + { + mInDebug = FALSE; + return false; + } + mInDebug = TRUE; + + mDesiredDiscardLevel = debug_level; + + return true; +} + +bool LLViewerFetchedTexture::isActiveFetching() +{ + static LLCachedControl monitor_enabled(gSavedSettings,"DebugShowTextureInfo"); + + return mFetchState > 7 && mFetchState < 10 && monitor_enabled; //in state of WAIT_HTTP_REQ or DECODE_IMAGE. } bool LLViewerFetchedTexture::updateFetch() @@ -1693,9 +1899,10 @@ bool LLViewerFetchedTexture::updateFetch() static LLCachedControl textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); static LLCachedControl sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold"); static LLCachedControl sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost"); - if(textures_decode_disabled) + if(textures_decode_disabled || + (gUseWireframe && mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED_SELF)) // don't fetch the surface textures in wireframe mode { - return false ; + return false; } mFetchState = 0; @@ -1726,7 +1933,7 @@ bool LLViewerFetchedTexture::updateFetch() return false; // process any raw image data in callbacks before replacing } - S32 current_discard = getCurrentDiscardLevelForFetching() ; + S32 current_discard = getCurrentDiscardLevelForFetching(); S32 desired_discard = getDesiredDiscardLevel(); F32 decode_priority = getDecodePriority(); decode_priority = llclamp(decode_priority, 0.0f, maxDecodePriority()); @@ -1740,11 +1947,15 @@ bool LLViewerFetchedTexture::updateFetch() if (mAuxRawImage.notNull()) sAuxCount--; bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage); if (mRawImage.notNull()) sRawCount++; - if (mAuxRawImage.notNull()) sAuxCount++; + if (mAuxRawImage.notNull()) + { + mHasAux = TRUE; + sAuxCount++; + } if (finished) { mIsFetching = FALSE; - mLastPacketTimer.reset() ; + mLastPacketTimer.reset(); } else { @@ -1759,8 +1970,8 @@ bool LLViewerFetchedTexture::updateFetch() LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { - mIsFetched = TRUE ; - tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)) ; + mIsFetched = TRUE; + tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)); } #endif mRawDiscardLevel = fetch_discard; @@ -1777,17 +1988,28 @@ bool LLViewerFetchedTexture::updateFetch() destroyRawImage(); LL_WARNS() << "oversize, setting as missing" << LL_ENDL; setIsMissingAsset(); - mRawDiscardLevel = INVALID_DISCARD_LEVEL ; - mIsFetching = FALSE ; + mRawDiscardLevel = INVALID_DISCARD_LEVEL; + mIsFetching = FALSE; mLastPacketTimer.reset(); } else { mIsRawImageValid = TRUE; - addToCreateTexture() ; + addToCreateTexture(); + } + + if (mBoostLevel == LLGLTexture::BOOST_ICON) + { + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) + { + // scale oversized icon, no need to give more work to gl + mRawImage->scale(expected_width, expected_height); + } } - return TRUE ; + return TRUE; } else { @@ -1803,20 +2025,33 @@ bool LLViewerFetchedTexture::updateFetch() if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL)) { // We finished but received no data - if (current_discard < 0) + if (getDiscardLevel() < 0) { - LL_WARNS() << "!mIsFetching, setting as missing, decode_priority " << decode_priority - << " mRawDiscardLevel " << mRawDiscardLevel - << " current_discard " << current_discard - << LL_ENDL; + if (getFTType() != FTT_MAP_TILE) + { + LL_WARNS() << mID + << " Fetch failure, setting as missing, decode_priority " << decode_priority + << " mRawDiscardLevel " << mRawDiscardLevel + << " current_discard " << current_discard + << LL_ENDL; + } setIsMissingAsset(); desired_discard = -1; } else { //LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL; - mMinDiscardLevel = current_discard; - desired_discard = current_discard; + if(current_discard >= 0) + { + mMinDiscardLevel = current_discard; + desired_discard = current_discard; + } + else + { + S32 dis_level = getDiscardLevel(); + mMinDiscardLevel = dis_level; + desired_discard = dis_level; + } } destroyRawImage(); } @@ -1835,10 +2070,10 @@ bool LLViewerFetchedTexture::updateFetch() // LL_INFOS() << "Calling updateRequestPriority() with decode_priority = 0.0f" << LL_ENDL; // calcDecodePriority(); // } - static const F32 MAX_HOLD_TIME = 5.0f ; //seconds to wait before canceling fecthing if decode_priority is 0.f. + static const F32 MAX_HOLD_TIME = 5.0f; //seconds to wait before canceling fecthing if decode_priority is 0.f. if(decode_priority > 0.0f || mStopFetchingTimer.getElapsedTimeF32() > MAX_HOLD_TIME) { - mStopFetchingTimer.reset() ; + mStopFetchingTimer.reset(); LLAppViewer::getTextureFetch()->updateRequestPriority(mID, decode_priority); } } @@ -1861,20 +2096,24 @@ bool LLViewerFetchedTexture::updateFetch() { make_request = false; } - else if(mCachedRawImage.notNull() && (current_discard < 0 || current_discard > mCachedRawDiscardLevel)) + else if(mCachedRawImage.notNull() // can be empty + && mCachedRawImageReady + && (current_discard < 0 || current_discard > mCachedRawDiscardLevel)) { make_request = false; - switchToCachedImage() ; //use the cached raw data first + switchToCachedImage(); //use the cached raw data first } //else if (!isJustBound() && mCachedRawImageReady) //{ // make_request = false; //} - if(make_request) + if (make_request) { - //load the texture progressively. - S32 delta_level = (mBoostLevel > LLGLTexture::BOOST_NONE) ? 2 : 1 ; + // Load the texture progressively: we try not to rush to the desired discard too fast. + // If the camera is not moving, we do not tweak the discard level notch by notch but go to the desired discard with larger boosted steps + // This mitigates the "textures stay blurry" problem when loading while not killing the texture memory while moving around + S32 delta_level = (mBoostLevel > LLGLTexture::BOOST_ALM) ? 2 : 1; if (current_discard < 0) { desired_discard = llmax(desired_discard, getMaxDiscardLevel() - delta_level); @@ -1914,7 +2153,7 @@ bool LLViewerFetchedTexture::updateFetch() c = mComponents; } - static const LLCachedControl override_tex_discard_level("TextureDiscardLevel"); + static LLCachedControl override_tex_discard_level(gSavedSettings, "TextureDiscardLevel"); if (override_tex_discard_level != 0) { desired_discard = override_tex_discard_level; @@ -1922,7 +2161,7 @@ bool LLViewerFetchedTexture::updateFetch() // bypass texturefetch directly by pulling from LLTextureCache bool fetch_request_created = false; - fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority, + fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority, w, h, c, desired_discard, needsAux(), mCanUseHTTP); if (fetch_request_created) @@ -1939,11 +2178,13 @@ bool LLViewerFetchedTexture::updateFetch() } else if (mHasFetcher && !mIsFetching) { - // Only delete requests that haven't receeived any network data for a while + // Only delete requests that haven't received any network data + // for a while. Note - this is the normal mechanism for + // deleting requests, not just a place to handle timeouts. const F32 FETCH_IDLE_TIME = 5.f; if (mLastPacketTimer.getElapsedTimeF32() > FETCH_IDLE_TIME) { -// LL_INFOS() << "Deleting request: " << getID() << " Discard: " << current_discard << " <= min:" << mMinDiscardLevel << " or priority == 0: " << decode_priority << LL_ENDL; + LL_DEBUGS("Texture") << "exceeded idle time " << FETCH_IDLE_TIME << ", deleting request: " << getID() << LL_ENDL; LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); mHasFetcher = FALSE; } @@ -1954,13 +2195,29 @@ bool LLViewerFetchedTexture::updateFetch() return mIsFetching ? true : false; } +void LLViewerFetchedTexture::clearFetchedResults() +{ + if(mNeedsCreateTexture || mIsFetching) + { + return; + } + + cleanup(); + destroyGLTexture(); + + if(getDiscardLevel() >= 0) //sculpty texture, force to invalidate + { + mGLTexturep->forceToInvalidateGLTexture(); + } +} + void LLViewerFetchedTexture::forceToDeleteRequest() { if (mHasFetcher) { //LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); mHasFetcher = FALSE; - mIsFetching = FALSE ; + mIsFetching = FALSE; } resetTextureStats(); @@ -1968,26 +2225,45 @@ void LLViewerFetchedTexture::forceToDeleteRequest() mDesiredDiscardLevel = getMaxDiscardLevel() + 1; //defer LLAppViewer::getTextureFetch()->deleteRequest to updateFetch? } -void LLViewerFetchedTexture::setIsMissingAsset() +void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing) { - if (mUrl.empty()) + if (is_missing == mIsMissingAsset) { - LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL; + return; } - else + if (is_missing) { - LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL; + notifyAboutMissingAsset(); + + if (mUrl.empty()) + { + LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL; + } + else + { + // This may or may not be an error - it is normal to have no + // map tile on an empty region, but bad if we're failing on a + // server bake texture. + if (getFTType() != FTT_MAP_TILE) + { + LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL; + } + } + if (mHasFetcher) + { + LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); + mHasFetcher = FALSE; + mIsFetching = FALSE; + mLastPacketTimer.reset(); + mFetchState = 0; + mFetchPriority = 0; + } } - if (mHasFetcher) + else { - LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); - mHasFetcher = FALSE; - mIsFetching = FALSE; - mLastPacketTimer.reset(); - mFetchState = 0; - mFetchPriority = 0; + LL_INFOS() << mID << ": un-flagging missing asset" << LL_ENDL; } - mIsMissingAsset = TRUE; + mIsMissingAsset = is_missing; } void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback, @@ -2005,19 +2281,19 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call } else { - mLoadedCallbackDesiredDiscardLevel = llmin(mLoadedCallbackDesiredDiscardLevel, (S8)discard_level) ; + mLoadedCallbackDesiredDiscardLevel = llmin(mLoadedCallbackDesiredDiscardLevel, (S8)discard_level); } if(mPauseLoadedCallBacks) { if(!pause) { - unpauseLoadedCallbacks(src_callback_list) ; + unpauseLoadedCallbacks(src_callback_list); } } else if(pause) { - pauseLoadedCallbacks(src_callback_list) ; + pauseLoadedCallbacks(src_callback_list); } LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata, src_callback_list, this, pause); @@ -2026,21 +2302,30 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call mNeedsAux |= needs_aux; if(keep_imageraw) { - mSaveRawImage = TRUE ; + mSaveRawImage = TRUE; } if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0) { - // We need aux data, but we've already loaded the image, and it didn't have any - LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL; + if(mHasAux) + { + //trigger a refetch + forceToRefetchTexture(); + } + else + { + // We need aux data, but we've already loaded the image, and it didn't have any + LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL; + } } mLastCallBackActiveTime = sCurrentTime ; + mLastReferencedSavedRawImageTime = sCurrentTime; } void LLViewerFetchedTexture::clearCallbackEntryList() { if(mLoadedCallbackList.empty()) { - return ; + return; } for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); @@ -2051,29 +2336,29 @@ void LLViewerFetchedTexture::clearCallbackEntryList() // We never finished loading the image. Indicate failure. // Note: this allows mLoadedCallbackUserData to be cleaned up. entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData); - iter = mLoadedCallbackList.erase(iter) ; + iter = mLoadedCallbackList.erase(iter); delete entryp; } gTextureList.mCallbackList.erase(this); - mLoadedCallbackDesiredDiscardLevel = S8_MAX ; + mLoadedCallbackDesiredDiscardLevel = S8_MAX; if(needsToSaveRawImage()) { - destroySavedRawImage() ; + destroySavedRawImage(); } - return ; + return; } void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::source_callback_list_t* callback_list) { if(mLoadedCallbackList.empty() || !callback_list) { - return ; + return; } - S32 desired_discard = S8_MAX ; - S32 desired_raw_discard = INVALID_DISCARD_LEVEL ; + S32 desired_discard = S8_MAX; + S32 desired_raw_discard = INVALID_DISCARD_LEVEL; for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) { @@ -2083,17 +2368,17 @@ void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::so // We never finished loading the image. Indicate failure. // Note: this allows mLoadedCallbackUserData to be cleaned up. entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData); - iter = mLoadedCallbackList.erase(iter) ; + iter = mLoadedCallbackList.erase(iter); delete entryp; } else { ++iter; - desired_discard = llmin(desired_discard, entryp->mDesiredDiscard) ; + desired_discard = llmin(desired_discard, entryp->mDesiredDiscard); if(entryp->mNeedsImageRaw) { - desired_raw_discard = llmin(desired_raw_discard, entryp->mDesiredDiscard) ; + desired_raw_discard = llmin(desired_raw_discard, entryp->mDesiredDiscard); } } } @@ -2106,18 +2391,18 @@ void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::so if(needsToSaveRawImage()) { - destroySavedRawImage() ; + destroySavedRawImage(); } } else if(needsToSaveRawImage() && mBoostLevel != LLGLTexture::BOOST_PREVIEW) { if(desired_raw_discard != INVALID_DISCARD_LEVEL) { - mDesiredSavedRawDiscardLevel = desired_raw_discard ; + mDesiredSavedRawDiscardLevel = desired_raw_discard; } else { - destroySavedRawImage() ; + destroySavedRawImage(); } } } @@ -2126,29 +2411,30 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry: { if(!callback_list) { - mPauseLoadedCallBacks = FALSE ; - return ; + mPauseLoadedCallBacks = FALSE; + return; } - BOOL need_raw = FALSE ; + BOOL need_raw = FALSE; for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) { LLLoadedCallbackEntry *entryp = *iter++; if(entryp->mSourceCallbackList == callback_list) { - entryp->mPaused = FALSE ; + entryp->mPaused = FALSE; if(entryp->mNeedsImageRaw) { - need_raw = TRUE ; + need_raw = TRUE; } } } mPauseLoadedCallBacks = FALSE ; mLastCallBackActiveTime = sCurrentTime ; + mForceCallbackFetch = TRUE; if(need_raw) { - mSaveRawImage = TRUE ; + mSaveRawImage = TRUE; } } @@ -2156,10 +2442,10 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s { if(!callback_list) { - return ; + return; } - bool paused = true ; + bool paused = true; for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) @@ -2167,25 +2453,26 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s LLLoadedCallbackEntry *entryp = *iter++; if(entryp->mSourceCallbackList == callback_list) { - entryp->mPaused = TRUE ; + entryp->mPaused = TRUE; } else if(!entryp->mPaused) { - paused = false ; + paused = false; } } if(paused) { - mPauseLoadedCallBacks = TRUE ;//when set, loaded callback is paused. + mPauseLoadedCallBacks = TRUE;//when set, loaded callback is paused. resetTextureStats(); - mSaveRawImage = FALSE ; + mSaveRawImage = FALSE; } } bool LLViewerFetchedTexture::doLoadedCallbacks() { - static const F32 MAX_INACTIVE_TIME = 120.f ; //seconds + static const F32 MAX_INACTIVE_TIME = 900.f ; //seconds + static const F32 MAX_IDLE_WAIT_TIME = 5.f ; //seconds if (mNeedsCreateTexture) { @@ -2198,6 +2485,15 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() } if(sCurrentTime - mLastCallBackActiveTime > MAX_INACTIVE_TIME && !mIsFetching) { + if (mFTType == FTT_SERVER_BAKE) + { + //output some debug info + LL_INFOS() << "baked texture: " << mID << "clears all call backs due to inactivity." << LL_ENDL; + LL_INFOS() << mUrl << LL_ENDL; + LL_INFOS() << "current discard: " << getDiscardLevel() << " current discard for fetch: " << getCurrentDiscardLevelForFetching() << + " Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << getDecodePriority() << LL_ENDL; + } + clearCallbackEntryList() ; //remove all callbacks. return false ; } @@ -2206,6 +2502,13 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() if (isMissingAsset()) { + if (mFTType == FTT_SERVER_BAKE) + { + //output some debug info + LL_INFOS() << "baked texture: " << mID << "is missing." << LL_ENDL; + LL_INFOS() << mUrl << LL_ENDL; + } + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) { @@ -2219,7 +2522,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() // Remove ourself from the global list of textures with callbacks gTextureList.mCallbackList.erase(this); - return false ; + return false; } S32 gl_discard = getDiscardLevel(); @@ -2340,7 +2643,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() // to satisfy the interested party, then this is the last time that // we're going to call them. - mLastCallBackActiveTime = sCurrentTime ; + mLastCallBackActiveTime = sCurrentTime; //llassert_always(mRawImage.notNull()); if(mNeedsAux && mAuxRawImage.isNull()) { @@ -2376,7 +2679,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() LLLoadedCallbackEntry *entryp = *curiter; if (!entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > gl_discard)) { - mLastCallBackActiveTime = sCurrentTime ; + mLastCallBackActiveTime = sCurrentTime; BOOL final = gl_discard <= entryp->mDesiredDiscard ? TRUE : FALSE; entryp->mLastUsedDiscard = gl_discard; entryp->mCallback(TRUE, this, NULL, NULL, gl_discard, final, entryp->mUserData); @@ -2390,6 +2693,9 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() } } + // Done with any raw image data at this point (will be re-created if we still have callbacks) + destroyRawImage(); + // // If we have no callbacks, take us off of the image callback list. // @@ -2397,10 +2703,12 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() { gTextureList.mCallbackList.erase(this); } - - // Done with any raw image data at this point (will be re-created if we still have callbacks) - destroyRawImage(); - + else if(!res && mForceCallbackFetch && sCurrentTime - mLastCallBackActiveTime > MAX_IDLE_WAIT_TIME && !mIsFetching) + { + //wait for long enough but no fetching request issued, force one. + forceToRefetchTexture(mLoadedCallbackDesiredDiscardLevel, 5.f); + mForceCallbackFetch = FALSE; //fire once. + } return res; } @@ -2410,66 +2718,66 @@ void LLViewerFetchedTexture::forceImmediateUpdate() //only immediately update a deleted texture which is now being re-used. if(!isDeleted()) { - return ; + return; } //if already called forceImmediateUpdate() if(mInImageList && mDecodePriority == LLViewerFetchedTexture::maxDecodePriority()) { - return ; + return; } - gTextureList.forceImmediateUpdate(this) ; - return ; + gTextureList.forceImmediateUpdate(this); + return; } LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level) { - llassert_always(mGLTexturep.notNull()) ; + llassert_always(mGLTexturep.notNull()); llassert_always(discard_level >= 0); llassert_always(mComponents > 0); if (mRawImage.notNull()) { //mRawImage is in use by somebody else, do not delete it. - return NULL ; + return NULL; } if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level) { - if(mSavedRawDiscardLevel != discard_level) + if (mSavedRawDiscardLevel != discard_level && mBoostLevel != BOOST_ICON) { - mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ; - mRawImage->copy(getSavedRawImage()) ; + mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()); + mRawImage->copy(getSavedRawImage()); } else { - mRawImage = getSavedRawImage() ; + mRawImage = getSavedRawImage(); } - mRawDiscardLevel = discard_level ; + mRawDiscardLevel = discard_level; } else { //force to fetch raw image again if cached raw image is not good enough. if(mCachedRawDiscardLevel > discard_level) { - mRawImage = mCachedRawImage ; + mRawImage = mCachedRawImage; mRawDiscardLevel = mCachedRawDiscardLevel; } else //cached raw image is good enough, copy it. { if(mCachedRawDiscardLevel != discard_level) { - mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ; - mRawImage->copy(mCachedRawImage) ; + mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()); + mRawImage->copy(mCachedRawImage); } else { - mRawImage = mCachedRawImage ; + mRawImage = mCachedRawImage; } - mRawDiscardLevel = discard_level ; + mRawDiscardLevel = discard_level; } } - mIsRawImageValid = TRUE ; + mIsRawImageValid = TRUE; sRawCount++; return mRawImage; @@ -2477,12 +2785,12 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level) bool LLViewerFetchedTexture::needsToSaveRawImage() { - return mForceToSaveRawImage || mSaveRawImage ; + return mForceToSaveRawImage || mSaveRawImage; } void LLViewerFetchedTexture::destroyRawImage() { - if (mAuxRawImage.notNull()) + if (mAuxRawImage.notNull() && !needsToSaveRawImage()) { sAuxCount--; mAuxRawImage = NULL; @@ -2496,9 +2804,9 @@ void LLViewerFetchedTexture::destroyRawImage() { if(needsToSaveRawImage()) { - saveRawImage() ; + saveRawImage(); } - setCachedRawImage() ; + setCachedRawImage(); } mRawImage = NULL; @@ -2514,19 +2822,19 @@ void LLViewerFetchedTexture::switchToCachedImage() { if(mCachedRawImage.notNull()) { - mRawImage = mCachedRawImage ; + mRawImage = mCachedRawImage; if (getComponents() != mRawImage->getComponents()) { // We've changed the number of components, so we need to move any // objects using this pool to a different pool. mComponents = mRawImage->getComponents(); - mGLTexturep->setComponents(mComponents) ; + mGLTexturep->setComponents(mComponents); gTextureList.dirtyImage(this); } mIsRawImageValid = TRUE; - mRawDiscardLevel = mCachedRawDiscardLevel ; + mRawDiscardLevel = mCachedRawDiscardLevel; gTextureList.mCreateTextureList.insert(this); mNeedsCreateTexture = TRUE; } @@ -2540,11 +2848,28 @@ void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* im { if(mCachedRawImage.notNull()) mCachedRawImage->setInCache(false); - mCachedRawImage = imageraw ; + if (mBoostLevel == LLGLTexture::BOOST_ICON) + { + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + { + mCachedRawImage = new LLImageRaw(expected_width, expected_height, imageraw->getComponents()); + mCachedRawImage->copyScaled(imageraw); + } + else + { + mCachedRawImage = imageraw; + } + } + else + { + mCachedRawImage = imageraw; + } if(mCachedRawImage.notNull()) mCachedRawImage->setInCache(true); - mCachedRawDiscardLevel = discard_level ; - mCachedRawImageReady = TRUE ; + mCachedRawDiscardLevel = discard_level; + mCachedRawImageReady = TRUE; } } @@ -2552,49 +2877,49 @@ void LLViewerFetchedTexture::setCachedRawImage() { if(mRawImage == mCachedRawImage) { - return ; + return; } if(!mIsRawImageValid) { - return ; + return; } if(mCachedRawImageReady) { - return ; + return; } if(mCachedRawDiscardLevel < 0 || mCachedRawDiscardLevel > mRawDiscardLevel) { - S32 i = 0 ; - S32 w = mRawImage->getWidth() ; - S32 h = mRawImage->getHeight() ; + S32 i = 0; + S32 w = mRawImage->getWidth(); + S32 h = mRawImage->getHeight(); - S32 max_size = MAX_CACHED_RAW_IMAGE_AREA ; + S32 max_size = MAX_CACHED_RAW_IMAGE_AREA; if(LLGLTexture::BOOST_TERRAIN == mBoostLevel) { - max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA ; + max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA; } if(mForSculpt) { - max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA ; - mCachedRawImageReady = !mRawDiscardLevel ; + max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA; + mCachedRawImageReady = !mRawDiscardLevel; } else { - mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size)) ; + mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size)); } while(((w >> i) * (h >> i)) > max_size) { - ++i ; + ++i; } if(i) { if(!(w >> i) || !(h >> i)) { - --i ; + --i; } if (mRawImage->getComponents() == 5) { @@ -2605,16 +2930,16 @@ void LLViewerFetchedTexture::setCachedRawImage() { //make a duplicate in case somebody else is using this raw image mRawImage = mRawImage->duplicate(); - mRawImage->scale(w >> i, h >> i) ; + mRawImage->scale(w >> i, h >> i); } } if(mCachedRawImage.notNull()) mCachedRawImage->setInCache(false); - mCachedRawImage = mRawImage ; + mCachedRawImage = mRawImage; if(mCachedRawImage.notNull()) mCachedRawImage->setInCache(true); - mRawDiscardLevel += i ; - mCachedRawDiscardLevel = mRawDiscardLevel ; + mRawDiscardLevel += i; + mCachedRawDiscardLevel = mRawDiscardLevel; } } @@ -2624,11 +2949,11 @@ void LLViewerFetchedTexture::checkCachedRawSculptImage() { if(getDiscardLevel() != 0) { - mCachedRawImageReady = FALSE ; + mCachedRawImageReady = FALSE; } else if(isForSculptOnly()) { - resetTextureStats() ; //do not update this image any more. + resetTextureStats(); //do not update this image any more. } } } @@ -2637,7 +2962,7 @@ void LLViewerFetchedTexture::saveRawImage() { if(mRawImage.isNull() || mRawImage == mSavedRawImage || (mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= mRawDiscardLevel)) { - return ; + return; } // This shouldn't happen, but it did on Snowglobe 1.5. Better safe than sorry? @@ -2647,42 +2972,77 @@ void LLViewerFetchedTexture::saveRawImage() return; } - mSavedRawDiscardLevel = mRawDiscardLevel ; - mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()) ; + mSavedRawDiscardLevel = mRawDiscardLevel; + if (mBoostLevel == LLGLTexture::BOOST_ICON) + { + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + { + mSavedRawImage = new LLImageRaw(expected_width, expected_height, mRawImage->getComponents()); + mSavedRawImage->copyScaled(mRawImage); + } + else + { + mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()); + } + } + else + { + mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()); + } if(mForceToSaveRawImage && mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel) { - mForceToSaveRawImage = FALSE ; + mForceToSaveRawImage = FALSE; } + mLastReferencedSavedRawImageTime = sCurrentTime; +} + +//force to refetch the texture to the discard level +void LLViewerFetchedTexture::forceToRefetchTexture(S32 desired_discard, F32 kept_time) +{ + if(mForceToSaveRawImage) + { + desired_discard = llmin(desired_discard, mDesiredSavedRawDiscardLevel); + kept_time = llmax(kept_time, mKeptSavedRawImageTime); + } + + //trigger a new fetch. + mForceToSaveRawImage = TRUE ; + mDesiredSavedRawDiscardLevel = desired_discard ; + mKeptSavedRawImageTime = kept_time ; mLastReferencedSavedRawImageTime = sCurrentTime ; + mSavedRawImage = NULL ; + mSavedRawDiscardLevel = -1 ; } void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time) { - mKeptSavedRawImageTime = kept_time ; - mLastReferencedSavedRawImageTime = sCurrentTime ; + mKeptSavedRawImageTime = kept_time; + mLastReferencedSavedRawImageTime = sCurrentTime; if(mSavedRawDiscardLevel > -1 && mSavedRawDiscardLevel <= desired_discard) { - return ; //raw imge is ready. + return; //raw imge is ready. } if(!mForceToSaveRawImage || mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard) { - mForceToSaveRawImage = TRUE ; - mDesiredSavedRawDiscardLevel = desired_discard ; + mForceToSaveRawImage = TRUE; + mDesiredSavedRawDiscardLevel = desired_discard; //copy from the cached raw image if exists. if(mCachedRawImage.notNull() && mRawImage.isNull() ) { - mRawImage = mCachedRawImage ; - mRawDiscardLevel = mCachedRawDiscardLevel ; + mRawImage = mCachedRawImage; + mRawDiscardLevel = mCachedRawDiscardLevel; - saveRawImage() ; + saveRawImage(); - mRawImage = NULL ; - mRawDiscardLevel = INVALID_DISCARD_LEVEL ; + mRawImage = NULL; + mRawDiscardLevel = INVALID_DISCARD_LEVEL; } } } @@ -2690,13 +3050,13 @@ void LLViewerFetchedTexture::destroySavedRawImage() { if(mLastReferencedSavedRawImageTime < mKeptSavedRawImageTime) { - return ; //keep the saved raw image. + return; //keep the saved raw image. } - mForceToSaveRawImage = FALSE ; - mSaveRawImage = FALSE ; + mForceToSaveRawImage = FALSE; + mSaveRawImage = FALSE; - clearCallbackEntryList() ; + clearCallbackEntryList(); mSavedRawImage = NULL ; mForceToSaveRawImage = FALSE ; @@ -2705,208 +3065,53 @@ void LLViewerFetchedTexture::destroySavedRawImage() mDesiredSavedRawDiscardLevel = -1 ; mLastReferencedSavedRawImageTime = 0.0f ; mKeptSavedRawImageTime = 0.f ; + + if(mAuxRawImage.notNull()) + { + sAuxCount--; + mAuxRawImage = NULL; + } } LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() { - mLastReferencedSavedRawImageTime = sCurrentTime ; + mLastReferencedSavedRawImageTime = sCurrentTime; - return mSavedRawImage ; + return mSavedRawImage; } BOOL LLViewerFetchedTexture::hasSavedRawImage() const { - return mSavedRawImage.notNull() ; + return mSavedRawImage.notNull(); } F32 LLViewerFetchedTexture::getElapsedLastReferencedSavedRawImageTime() const { - return sCurrentTime - mLastReferencedSavedRawImageTime ; + return sCurrentTime - mLastReferencedSavedRawImageTime; } -//---------------------------------------------------------------------------------------------- -//atlasing -//---------------------------------------------------------------------------------------------- -/*void LLViewerFetchedTexture::resetFaceAtlas() + +LLUUID LLViewerFetchedTexture::getUploader() { - //Nothing should be done here. + return (mComment.find('a') != mComment.end()) ? LLUUID(mComment['a']) : LLUUID::null; } -//invalidate all atlas slots for this image. -void LLViewerFetchedTexture::invalidateAtlas(BOOL rebuild_geom) +LLDate LLViewerFetchedTexture::getUploadTime() { - for(U32 i = 0 ; i < mNumFaces ; i++) + if (mComment.find('z') != mComment.end()) { - LLFace* facep = mFaceList[i] ; - facep->removeAtlas() ; - if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup()) - { - facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY); - } + struct tm t = {}; + sscanf(mComment['z'].c_str(), "%4d%2d%2d%2d%2d%2d", + &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec); + std::string iso_date = llformat("%d-%d-%dT%d:%d:%dZ", t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); + return LLDate(iso_date); } + return LLDate(); } -BOOL LLViewerFetchedTexture::insertToAtlas() +std::string LLViewerFetchedTexture::getComment() { - if(!LLViewerTexture::sUseTextureAtlas) - { - return FALSE ; - } - if(getNumFaces() < 1) - { - return FALSE ; - } - if(mGLTexturep->getDiscardLevelInAtlas() > 0 && mRawDiscardLevel >= mGLTexturep->getDiscardLevelInAtlas()) - { - return FALSE ; - } - if(!LLTextureAtlasManager::getInstance()->canAddToAtlas(mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents(), mGLTexturep->getTexTarget())) - { - return FALSE ; - } - - BOOL ret = TRUE ;//if ret is set to false, will generate a gl texture for this image. - S32 raw_w = mRawImage->getWidth() ; - S32 raw_h = mRawImage->getHeight() ; - F32 xscale = 1.0f, yscale = 1.0f ; - LLPointer slot_infop; - LLTextureAtlasSlot* cur_slotp ;//no need to be smart pointer. - LLSpatialGroup* groupp ; - LLFace* facep; - - //if the atlas slot pointers for some faces are null, process them later. - ll_face_list_t waiting_list ; - for(U32 i = 0 ; i < mNumFaces ; i++) - { - { - facep = mFaceList[i] ; - - //face can not use atlas. - if(!facep->canUseAtlas()) - { - if(facep->getAtlasInfo()) - { - facep->removeAtlas() ; - } - ret = FALSE ; - continue ; - } - - //the atlas slot is updated - slot_infop = facep->getAtlasInfo() ; - groupp = facep->getDrawable()->getSpatialGroup() ; - - if(slot_infop) - { - if(slot_infop->getSpatialGroup() != groupp) - { - if((cur_slotp = groupp->getCurUpdatingSlot(this))) //switch slot - { - facep->setAtlasInfo(cur_slotp) ; - facep->setAtlasInUse(TRUE) ; - continue ; - } - else //do not forget to update slot_infop->getSpatialGroup(). - { - LLSpatialGroup* gp = slot_infop->getSpatialGroup() ; - gp->setCurUpdatingTime(gFrameCount) ; - gp->setCurUpdatingTexture(this) ; - gp->setCurUpdatingSlot(slot_infop) ; - } - } - else //same group - { - if(gFrameCount && slot_infop->getUpdatedTime() == gFrameCount)//slot is just updated - { - facep->setAtlasInUse(TRUE) ; - continue ; - } - } - } - else - { - //if the slot is null, wait to process them later. - waiting_list.push_back(facep) ; - continue ; - } - - //---------- - //insert to atlas - if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow())) - { - - //the texture does not qualify to add to atlas, do not bother to try for other faces. - //invalidateAtlas(); - return FALSE ; - } - - //update texture scale - slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ; - slot_infop->setTexCoordScale(xscale, yscale) ; - slot_infop->setValid() ; - slot_infop->setUpdatedTime(gFrameCount) ; - - //update spatial group atlas info - groupp->setCurUpdatingTime(gFrameCount) ; - groupp->setCurUpdatingTexture(this) ; - groupp->setCurUpdatingSlot(slot_infop) ; - - //make the face to switch to the atlas. - facep->setAtlasInUse(TRUE) ; - } - } - - //process the waiting_list - for(ll_face_list_t::iterator iter = waiting_list.begin(); iter != waiting_list.end(); ++iter) - { - facep = (LLFace*)*iter ; - groupp = facep->getDrawable()->getSpatialGroup() ; - - //check if this texture already inserted to atlas for this group - if((cur_slotp = groupp->getCurUpdatingSlot(this))) - { - facep->setAtlasInfo(cur_slotp) ; - facep->setAtlasInUse(TRUE) ; - continue ; - } - - //need to reserve a slot from atlas - slot_infop = LLTextureAtlasManager::getInstance()->reserveAtlasSlot(llmax(mFullWidth, mFullHeight), getComponents(), groupp, this) ; - - facep->setAtlasInfo(slot_infop) ; - - groupp->setCurUpdatingTime(gFrameCount) ; - groupp->setCurUpdatingTexture(this) ; - groupp->setCurUpdatingSlot(slot_infop) ; - - //slot allocation failed. - if(!slot_infop || !slot_infop->getAtlas()) - { - ret = FALSE ; - facep->setAtlasInUse(FALSE) ; - continue ; - } - - //insert to atlas - if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow())) - { - //the texture does not qualify to add to atlas, do not bother to try for other faces. - ret = FALSE ; - //invalidateAtlas(); - break ; - } - - //update texture scale - slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ; - slot_infop->setTexCoordScale(xscale, yscale) ; - slot_infop->setValid() ; - slot_infop->setUpdatedTime(gFrameCount) ; - - //make the face to switch to the atlas. - facep->setAtlasInUse(TRUE) ; - } - - return ret ; -}*/ + return (mComment.find('K') != mComment.end()) ? mComment['K'] : LLStringUtil::null; +} //---------------------------------------------------------------------------------------------- //end of LLViewerFetchedTexture @@ -2915,16 +3120,16 @@ BOOL LLViewerFetchedTexture::insertToAtlas() //---------------------------------------------------------------------------------------------- //start of LLViewerLODTexture //---------------------------------------------------------------------------------------------- -LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps) - : LLViewerFetchedTexture(id, host, usemipmaps) +LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host, BOOL usemipmaps) + : LLViewerFetchedTexture(id, f_type, host, usemipmaps) { - init(TRUE) ; + init(TRUE); } -LLViewerLODTexture::LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps) - : LLViewerFetchedTexture(url, id, usemipmaps) +LLViewerLODTexture::LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps) + : LLViewerFetchedTexture(url, f_type, id, usemipmaps) { - init(TRUE) ; + init(TRUE); } void LLViewerLODTexture::init(bool firstinit) @@ -2937,21 +3142,21 @@ void LLViewerLODTexture::init(bool firstinit) //virtual S8 LLViewerLODTexture::getType() const { - return LLViewerTexture::LOD_TEXTURE ; + return LLViewerTexture::LOD_TEXTURE; } BOOL LLViewerLODTexture::isUpdateFrozen() { - return LLViewerTexture::sFreezeImageScalingDown && !getDiscardLevel() ; + return LLViewerTexture::sFreezeImageScalingDown && !getDiscardLevel(); } // This is gauranteed to get called periodically for every texture //virtual void LLViewerLODTexture::processTextureStats() { - updateVirtualSize() ; + updateVirtualSize(); - static LLCachedControl textures_fullres(gSavedSettings,"TextureLoadFullRes"); + static LLCachedControl textures_fullres(gSavedSettings,"TextureLoadFullRes", false); if (textures_fullres) { @@ -2964,6 +3169,10 @@ void LLViewerLODTexture::processTextureStats() if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 } + else if (!LLPipeline::sRenderDeferred && mBoostLevel == LLGLTexture::BOOST_ALM) + { + mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; + } else if (mBoostLevel < LLGLTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f) { // If the image has not been significantly visible in a while, we don't want it @@ -2971,7 +3180,7 @@ void LLViewerLODTexture::processTextureStats() } else if (!mFullWidth || !mFullHeight) { - mDesiredDiscardLevel = getMaxDiscardLevel() ; + mDesiredDiscardLevel = getMaxDiscardLevel(); } else { @@ -2986,6 +3195,7 @@ void LLViewerLODTexture::processTextureStats() if (mKnownDrawWidth && mKnownDrawHeight) { S32 draw_texels = mKnownDrawWidth * mKnownDrawHeight; + draw_texels = llclamp(draw_texels, MIN_IMAGE_AREA, MAX_IMAGE_AREA); // Use log_4 because we're in square-pixel space, so an image // with twice the width and twice the height will have mTexelsPerImage @@ -2997,7 +3207,7 @@ void LLViewerLODTexture::processTextureStats() if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 0.3f) { //if is a big image and not being used recently, nor close to the view point, do not load hi-res data. - mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerTexture::sMinLargeImageSize) ; + mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerTexture::sMinLargeImageSize); } if ((mCalculatedDiscardLevel >= 0.f) && @@ -3018,13 +3228,18 @@ void LLViewerLODTexture::processTextureStats() { discard_level += sDesiredDiscardBias; discard_level *= sDesiredDiscardScale; // scale - discard_level += sCameraMovingDiscardBias ; + discard_level += sCameraMovingDiscardBias; } discard_level = floorf(discard_level); F32 min_discard = 0.f; - if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) - min_discard = 1.f; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + if (mBoostLevel <= LLGLTexture::BOOST_SCULPTED) + { + desired_size = DESIRED_NORMAL_TEXTURE_SIZE; + } + if ((U32)mFullWidth > desired_size || (U32)mFullHeight > desired_size) + min_discard = 1.f; discard_level = llclamp(discard_level, min_discard, (F32)MAX_DISCARD_LEVEL); @@ -3046,32 +3261,32 @@ void LLViewerLODTexture::processTextureStats() if(desired_discard_bias_max <= sDesiredDiscardBias && !mForceToSaveRawImage) { //needs to release texture memory urgently - scaleDown() ; + scaleDown(); } // Limit the amount of GL memory bound each frame - else if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale && + else if ( sBoundTextureMemory > sMaxBoundTextureMemory * texmem_middle_bound_scale && (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) { - scaleDown() ; + scaleDown(); } // Only allow GL to have 2x the video card memory - else if ( BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale && + else if ( sTotalTextureMemory > sMaxTotalTextureMem * texmem_middle_bound_scale && (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) { - scaleDown() ; + scaleDown(); } } } if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) { - mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel) ; + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel); } else if(LLPipeline::sMemAllocationThrottled)//release memory of large textures by decrease their resolutions. { if(scaleDown()) { - mDesiredDiscardLevel = mCachedRawDiscardLevel ; + mDesiredDiscardLevel = mCachedRawDiscardLevel; } } } @@ -3080,18 +3295,18 @@ bool LLViewerLODTexture::scaleDown() { if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel()) { - switchToCachedImage() ; + switchToCachedImage(); #if 0 LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { - tester->setStablizingTime() ; + tester->setStablizingTime(); } #endif - return true ; + return true; } - return false ; + return false; } //---------------------------------------------------------------------------------------------- //end of LLViewerLODTexture @@ -3103,14 +3318,14 @@ bool LLViewerLODTexture::scaleDown() //static void LLViewerMediaTexture::updateClass() { - static const F32 MAX_INACTIVE_TIME = 30.f ; + static const F32 MAX_INACTIVE_TIME = 30.f; #if 0 //force to play media. - gSavedSettings.setBOOL("AudioStreamingMedia", true) ; + gSavedSettings.setBOOL("AudioStreamingMedia", true); #endif - for(media_map_t::iterator iter = sMediaMap.begin() ; iter != sMediaMap.end(); ) + for(media_map_t::iterator iter = sMediaMap.begin(); iter != sMediaMap.end(); ) { LLViewerMediaTexture* mediap = iter->second; @@ -3121,29 +3336,29 @@ void LLViewerMediaTexture::updateClass() // if(mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) { - media_map_t::iterator cur = iter++ ; - sMediaMap.erase(cur) ; - continue ; + media_map_t::iterator cur = iter++; + sMediaMap.erase(cur); + continue; } } - ++iter ; + ++iter; } } //static void LLViewerMediaTexture::removeMediaImplFromTexture(const LLUUID& media_id) { - LLViewerMediaTexture* media_tex = findMediaTexture(media_id) ; + LLViewerMediaTexture* media_tex = findMediaTexture(media_id); if(media_tex) { - media_tex->invalidateMediaImpl() ; + media_tex->invalidateMediaImpl(); } } //static void LLViewerMediaTexture::cleanUpClass() { - sMediaMap.clear() ; + sMediaMap.clear(); } //static @@ -3155,9 +3370,9 @@ LLViewerMediaTexture* LLViewerMediaTexture::findMediaTexture(const LLUUID& media return NULL; } - LLViewerMediaTexture* media_tex = iter->second ; - media_tex->setMediaImpl() ; - media_tex->getLastReferencedTimer()->reset() ; + LLViewerMediaTexture* media_tex = iter->second; + media_tex->setMediaImpl(); + media_tex->getLastReferencedTimer()->reset(); return media_tex; } @@ -3169,45 +3384,48 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL { sMediaMap.insert(std::make_pair(id, this)); - mGLTexturep = gl_image ; + mGLTexturep = gl_image; if(mGLTexturep.isNull()) { - generateGLTexture() ; + generateGLTexture(); } mGLTexturep->setAllowCompression(false); - mIsPlaying = FALSE ; + mGLTexturep->setNeedsAlphaAndPickMask(FALSE); + + mIsPlaying = FALSE; - setMediaImpl() ; + setMediaImpl(); - setCategory(LLGLTexture::MEDIA) ; + setCategory(LLGLTexture::MEDIA); - LLViewerTexture* tex = gTextureList.findImage(mID) ; + LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); if(tex) //this media is a parcel media for tex. { - tex->setParcelMedia(this) ; + tex->setParcelMedia(this); } } //virtual LLViewerMediaTexture::~LLViewerMediaTexture() { - LLViewerTexture* tex = gTextureList.findImage(mID) ; + LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); if(tex) //this media is a parcel media for tex. { - tex->setParcelMedia(NULL) ; + tex->setParcelMedia(NULL); } } void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */) { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()); - mUseMipMaps = usemipmaps ; - getLastReferencedTimer()->reset() ; - mGLTexturep->setUseMipMaps(mUseMipMaps) ; + mUseMipMaps = usemipmaps; + getLastReferencedTimer()->reset(); + mGLTexturep->setUseMipMaps(mUseMipMaps); + mGLTexturep->setNeedsAlphaAndPickMask(FALSE); } void LLViewerMediaTexture::setUseMipMaps(BOOL mipmap) @@ -3216,26 +3434,26 @@ void LLViewerMediaTexture::setUseMipMaps(BOOL mipmap) if(mGLTexturep.notNull()) { - mGLTexturep->setUseMipMaps(mipmap) ; + mGLTexturep->setUseMipMaps(mipmap); } } //virtual S8 LLViewerMediaTexture::getType() const { - return LLViewerTexture::MEDIA_TEXTURE ; + return LLViewerTexture::MEDIA_TEXTURE; } void LLViewerMediaTexture::invalidateMediaImpl() { - mMediaImplp = NULL ; + mMediaImplp = NULL; } void LLViewerMediaTexture::setMediaImpl() { if(!mMediaImplp) { - mMediaImplp = LLViewerMedia::getMediaImplFromTextureID(mID) ; + mMediaImplp = LLViewerMedia::getMediaImplFromTextureID(mID); } } @@ -3244,71 +3462,71 @@ void LLViewerMediaTexture::setMediaImpl() // because it does not check the face validity after the current frame. BOOL LLViewerMediaTexture::findFaces() { - mMediaFaceList.clear() ; + mMediaFaceList.clear(); - BOOL ret = TRUE ; + BOOL ret = TRUE; - LLViewerTexture* tex = gTextureList.findImage(mID) ; + LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); if(tex) //this media is a parcel media for tex. { for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) { - const ll_face_list_t* face_list = tex->getFaceList(ch) ; - U32 end = tex->getNumFaces(ch) ; - for(U32 i = 0 ; i < end ; i++) + const ll_face_list_t* face_list = tex->getFaceList(ch); + U32 end = tex->getNumFaces(ch); + for(U32 i = 0; i < end; i++) { - mMediaFaceList.push_back((*face_list)[i]) ; + mMediaFaceList.push_back((*face_list)[i]); } } } if(!mMediaImplp) { - return TRUE ; + return TRUE; } //for media on a face. - const std::list< LLVOVolume* >* obj_list = mMediaImplp->getObjectList() ; - std::list< LLVOVolume* >::const_iterator iter = obj_list->begin() ; + const std::list< LLVOVolume* >* obj_list = mMediaImplp->getObjectList(); + std::list< LLVOVolume* >::const_iterator iter = obj_list->begin(); for(; iter != obj_list->end(); ++iter) { - LLVOVolume* obj = *iter ; + LLVOVolume* obj = *iter; if(obj->mDrawable.isNull()) { - ret = FALSE ; - continue ; + ret = FALSE; + continue; } - S32 face_id = -1 ; - S32 num_faces = obj->mDrawable->getNumFaces() ; + S32 face_id = -1; + S32 num_faces = obj->mDrawable->getNumFaces(); while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1 && face_id < num_faces) { - LLFace* facep = obj->mDrawable->getFace(face_id) ; + LLFace* facep = obj->mDrawable->getFace(face_id); if(facep) { - mMediaFaceList.push_back(facep) ; + mMediaFaceList.push_back(facep); } else { - ret = FALSE ; + ret = FALSE; } } } - return ret ; + return ret; } void LLViewerMediaTexture::initVirtualSize() { if(mIsPlaying) { - return ; + return; } - findFaces() ; + findFaces(); for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) { - addTextureStats((*iter)->getVirtualSize()) ; + addTextureStats((*iter)->getVirtualSize()); } } @@ -3316,77 +3534,77 @@ void LLViewerMediaTexture::addMediaToFace(LLFace* facep) { if(facep) { - facep->setHasMedia(true) ; + facep->setHasMedia(true); } if(!mIsPlaying) { - return ; //no need to add the face because the media is not in playing. + return; //no need to add the face because the media is not in playing. } - switchTexture(LLRender::DIFFUSE_MAP, facep) ; + switchTexture(LLRender::DIFFUSE_MAP, facep); } void LLViewerMediaTexture::removeMediaFromFace(LLFace* facep) { if(!facep) { - return ; + return; } - facep->setHasMedia(false) ; + facep->setHasMedia(false); if(!mIsPlaying) { - return ; //no need to remove the face because the media is not in playing. + return; //no need to remove the face because the media is not in playing. } - mIsPlaying = FALSE ; //set to remove the media from the face. - switchTexture(LLRender::DIFFUSE_MAP, facep) ; - mIsPlaying = TRUE ; //set the flag back. + mIsPlaying = FALSE; //set to remove the media from the face. + switchTexture(LLRender::DIFFUSE_MAP, facep); + mIsPlaying = TRUE; //set the flag back. if(getTotalNumFaces() < 1) //no face referencing to this media { - stopPlaying() ; + stopPlaying(); } } //virtual void LLViewerMediaTexture::addFace(U32 ch, LLFace* facep) { - LLViewerTexture::addFace(ch, facep) ; + LLViewerTexture::addFace(ch, facep); - const LLTextureEntry* te = facep->getTextureEntry() ; + const LLTextureEntry* te = facep->getTextureEntry(); if(te && te->getID().notNull()) { - LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; + LLViewerTexture* tex = gTextureList.findImage(te->getID(), TEX_LIST_STANDARD); if(tex) { - mTextureList.push_back(tex) ;//increase the reference number by one for tex to avoid deleting it. - return ; + mTextureList.push_back(tex);//increase the reference number by one for tex to avoid deleting it. + return; } } //check if it is a parcel media if(facep->getTexture() && facep->getTexture() != this && facep->getTexture()->getID() == mID) { - mTextureList.push_back(facep->getTexture()) ; //a parcel media. - return ; + mTextureList.push_back(facep->getTexture()); //a parcel media. + return; } if(te && te->getID().notNull()) //should have a texture { - LL_ERRS() << "The face does not have a valid texture before media texture." << LL_ENDL ; + LL_ERRS() << "The face does not have a valid texture before media texture." << LL_ENDL; } } //virtual void LLViewerMediaTexture::removeFace(U32 ch, LLFace* facep) { - LLViewerTexture::removeFace(ch, facep) ; + LLViewerTexture::removeFace(ch, facep); - const LLTextureEntry* te = facep->getTextureEntry() ; + const LLTextureEntry* te = facep->getTextureEntry(); if(te && te->getID().notNull()) { - LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; + LLViewerTexture* tex = gTextureList.findImage(te->getID(), TEX_LIST_STANDARD); if(tex) { for(std::list< LLPointer >::iterator iter = mTextureList.begin(); @@ -3394,8 +3612,8 @@ void LLViewerMediaTexture::removeFace(U32 ch, LLFace* facep) { if(*iter == tex) { - mTextureList.erase(iter) ; //decrease the reference number for tex by one. - return ; + mTextureList.erase(iter); //decrease the reference number for tex by one. + return; } } @@ -3409,7 +3627,7 @@ void LLViewerMediaTexture::removeFace(U32 ch, LLFace* facep) llassert(mNumFaces[ch] <= mFaceList[ch].size()); - for(U32 j = 0 ; j < mNumFaces[ch] ; j++) + for(U32 j = 0; j < mNumFaces[ch]; j++) { te_list.push_back(mFaceList[ch][j]->getTextureEntry());//all textures are in use. } @@ -3417,8 +3635,8 @@ void LLViewerMediaTexture::removeFace(U32 ch, LLFace* facep) if (te_list.empty()) { - mTextureList.clear() ; - return ; + mTextureList.clear(); + return; } S32 end = te_list.size(); @@ -3428,18 +3646,18 @@ void LLViewerMediaTexture::removeFace(U32 ch, LLFace* facep) { S32 i = 0; - for(i = 0 ; i < end ; i++) + for(i = 0; i < end; i++) { if(te_list[i] && te_list[i]->getID() == (*iter)->getID())//the texture is in use. { - te_list[i] = NULL ; - break ; + te_list[i] = NULL; + break; } } if(i == end) //no hit for this texture, remove it. { - mTextureList.erase(iter) ; //decrease the reference number for tex by one. - return ; + mTextureList.erase(iter); //decrease the reference number for tex by one. + return; } } } @@ -3451,14 +3669,14 @@ void LLViewerMediaTexture::removeFace(U32 ch, LLFace* facep) { if((*iter)->getID() == mID) { - mTextureList.erase(iter) ; //decrease the reference number for tex by one. - return ; + mTextureList.erase(iter); //decrease the reference number for tex by one. + return; } } if(te && te->getID().notNull()) //should have a texture { - LL_ERRS() << "mTextureList texture reference number is corrupted." << LL_ENDL ; + LL_ERRS() << "mTextureList texture reference number is corrupted. Texture id: " << te->getID() << " List size: " << (U32)mTextureList.size() << LL_ENDL; } } @@ -3467,9 +3685,9 @@ void LLViewerMediaTexture::stopPlaying() // Don't stop the media impl playing here -- this breaks non-inworld media (login screen, search, and media browser). // if(mMediaImplp) // { -// mMediaImplp->stop() ; +// mMediaImplp->stop(); // } - mIsPlaying = FALSE ; + mIsPlaying = FALSE; } void LLViewerMediaTexture::switchTexture(U32 ch, LLFace* facep) @@ -3482,29 +3700,29 @@ void LLViewerMediaTexture::switchTexture(U32 ch, LLFace* facep) { if(mID == facep->getTexture()->getID()) //this is a parcel media { - return ; //let the prim media win. + return; //let the prim media win. } } if(mIsPlaying) //old textures switch to the media texture { - facep->switchTexture(ch, this) ; + facep->switchTexture(ch, this); } else //switch to old textures. { - const LLTextureEntry* te = facep->getTextureEntry() ; + const LLTextureEntry* te = facep->getTextureEntry(); if(te) { - LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL ; + LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_STANDARD) : NULL; if(!tex && te->getID() != mID)//try parcel media. { - tex = gTextureList.findImage(mID) ; + tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); } if(!tex) { - tex = LLViewerFetchedTexture::sDefaultImagep ; + tex = LLViewerFetchedTexture::sDefaultImagep; } - facep->switchTexture(ch, tex) ; + facep->switchTexture(ch, tex); } } } @@ -3514,36 +3732,36 @@ void LLViewerMediaTexture::setPlaying(BOOL playing) { if(!mMediaImplp) { - return ; + return; } if(!playing && !mIsPlaying) { - return ; //media is already off + return; //media is already off } if(playing == mIsPlaying && !mMediaImplp->isUpdated()) { - return ; //nothing has changed since last time. + return; //nothing has changed since last time. } - mIsPlaying = playing ; + mIsPlaying = playing; if(mIsPlaying) //is about to play this media { if(findFaces()) { //about to update all faces. - mMediaImplp->setUpdated(FALSE) ; + mMediaImplp->setUpdated(FALSE); } if(mMediaFaceList.empty())//no face pointing to this media { - stopPlaying() ; - return ; + stopPlaying(); + return; } for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) { - switchTexture(LLRender::DIFFUSE_MAP, *iter) ; + switchTexture(LLRender::DIFFUSE_MAP, *iter); } } else //stop playing this media @@ -3551,12 +3769,12 @@ void LLViewerMediaTexture::setPlaying(BOOL playing) U32 ch = LLRender::DIFFUSE_MAP; llassert(mNumFaces[ch] <= mFaceList[ch].size()); - for(U32 i = mNumFaces[ch] ; i ; i--) + for(U32 i = mNumFaces[ch]; i; i--) { - switchTexture(ch, mFaceList[ch][i - 1]) ; //current face could be removed in this function. + switchTexture(ch, mFaceList[ch][i - 1]); //current face could be removed in this function. } } - return ; + return; } //virtual @@ -3564,13 +3782,13 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() { if(LLFrameTimer::getFrameCount() == mUpdateVirtualSizeTime) { - return mMaxVirtualSize ; + return mMaxVirtualSize; } - mUpdateVirtualSizeTime = LLFrameTimer::getFrameCount() ; + mUpdateVirtualSizeTime = LLFrameTimer::getFrameCount(); if(!mMaxVirtualSizeResetCounter) { - addTextureStats(0.f, FALSE) ;//reset + addTextureStats(0.f, FALSE);//reset } if(mIsPlaying) //media is playing @@ -3578,28 +3796,28 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) { llassert(mNumFaces[ch] <= mFaceList[ch].size()); - for(U32 i = 0 ; i < mNumFaces[ch] ; i++) + for(U32 i = 0; i < mNumFaces[ch]; i++) { - LLFace* facep = mFaceList[ch][i] ; + LLFace* facep = mFaceList[ch][i]; if(facep->getDrawable()->isRecentlyVisible()) { - addTextureStats(facep->getVirtualSize()) ; + addTextureStats(facep->getVirtualSize()); } } } } else //media is not in playing { - findFaces() ; + findFaces(); if(!mMediaFaceList.empty()) { for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) { - LLFace* facep = *iter ; + LLFace* facep = *iter; if(facep->getDrawable()->isRecentlyVisible()) { - addTextureStats(facep->getVirtualSize()) ; + addTextureStats(facep->getVirtualSize()); } } } @@ -3609,10 +3827,10 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() { mMaxVirtualSizeResetCounter--; } - reorganizeFaceList() ; + reorganizeFaceList(); reorganizeVolumeList(); - return mMaxVirtualSize ; + return mMaxVirtualSize; } //---------------------------------------------------------------------------------------------- //end of LLViewerMediaTexture @@ -3624,252 +3842,252 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() #if 0 LLTexturePipelineTester::LLTexturePipelineTester() : LLMetricPerformanceTesterWithSession(sTesterName) { - addMetric("TotalBytesLoaded") ; - addMetric("TotalBytesLoadedFromCache") ; - addMetric("TotalBytesLoadedForLargeImage") ; - addMetric("TotalBytesLoadedForSculpties") ; - addMetric("StartFetchingTime") ; - addMetric("TotalGrayTime") ; - addMetric("TotalStablizingTime") ; - addMetric("StartTimeLoadingSculpties") ; - addMetric("EndTimeLoadingSculpties") ; - - addMetric("Time") ; - addMetric("TotalBytesBound") ; - addMetric("TotalBytesBoundForLargeImage") ; - addMetric("PercentageBytesBound") ; + addMetric("TotalBytesLoaded"); + addMetric("TotalBytesLoadedFromCache"); + addMetric("TotalBytesLoadedForLargeImage"); + addMetric("TotalBytesLoadedForSculpties"); + addMetric("StartFetchingTime"); + addMetric("TotalGrayTime"); + addMetric("TotalStablizingTime"); + addMetric("StartTimeLoadingSculpties"); + addMetric("EndTimeLoadingSculpties"); + + addMetric("Time"); + addMetric("TotalBytesBound"); + addMetric("TotalBytesBoundForLargeImage"); + addMetric("PercentageBytesBound"); - mTotalBytesLoaded = 0 ; - mTotalBytesLoadedFromCache = 0 ; - mTotalBytesLoadedForLargeImage = 0 ; - mTotalBytesLoadedForSculpties = 0 ; + mTotalBytesLoaded = (S32Bytes)0; + mTotalBytesLoadedFromCache = (S32Bytes)0; + mTotalBytesLoadedForLargeImage = (S32Bytes)0; + mTotalBytesLoadedForSculpties = (S32Bytes)0; - reset() ; + reset(); } LLTexturePipelineTester::~LLTexturePipelineTester() { - LLViewerTextureManager::sTesterp = NULL ; + LLViewerTextureManager::sTesterp = NULL; } void LLTexturePipelineTester::update() { - mLastTotalBytesUsed = mTotalBytesUsed ; - mLastTotalBytesUsedForLargeImage = mTotalBytesUsedForLargeImage ; - mTotalBytesUsed = 0 ; - mTotalBytesUsedForLargeImage = 0 ; + mLastTotalBytesUsed = mTotalBytesUsed; + mLastTotalBytesUsedForLargeImage = mTotalBytesUsedForLargeImage; + mTotalBytesUsed = (S32Bytes)0; + mTotalBytesUsedForLargeImage = (S32Bytes)0; if(LLAppViewer::getTextureFetch()->getNumRequests() > 0) //fetching list is not empty { if(mPause) { //start a new fetching session - reset() ; - mStartFetchingTime = LLImageGL::sLastFrameTime ; - mPause = FALSE ; + reset(); + mStartFetchingTime = LLImageGL::sLastFrameTime; + mPause = FALSE; } //update total gray time if(mUsingDefaultTexture) { - mUsingDefaultTexture = FALSE ; - mTotalGrayTime = LLImageGL::sLastFrameTime - mStartFetchingTime ; + mUsingDefaultTexture = FALSE; + mTotalGrayTime = LLImageGL::sLastFrameTime - mStartFetchingTime; } //update the stablizing timer. - updateStablizingTime() ; + updateStablizingTime(); - outputTestResults() ; + outputTestResults(); } else if(!mPause) { //stop the current fetching session - mPause = TRUE ; - outputTestResults() ; - reset() ; + mPause = TRUE; + outputTestResults(); + reset(); } } void LLTexturePipelineTester::reset() { - mPause = TRUE ; + mPause = TRUE; - mUsingDefaultTexture = FALSE ; - mStartStablizingTime = 0.0f ; - mEndStablizingTime = 0.0f ; + mUsingDefaultTexture = FALSE; + mStartStablizingTime = 0.0f; + mEndStablizingTime = 0.0f; - mTotalBytesUsed = 0 ; - mTotalBytesUsedForLargeImage = 0 ; - mLastTotalBytesUsed = 0 ; - mLastTotalBytesUsedForLargeImage = 0 ; + mTotalBytesUsed = (S32Bytes)0; + mTotalBytesUsedForLargeImage = (S32Bytes)0; + mLastTotalBytesUsed = (S32Bytes)0; + mLastTotalBytesUsedForLargeImage = (S32Bytes)0; - mStartFetchingTime = 0.0f ; + mStartFetchingTime = 0.0f; - mTotalGrayTime = 0.0f ; - mTotalStablizingTime = 0.0f ; + mTotalGrayTime = 0.0f; + mTotalStablizingTime = 0.0f; - mStartTimeLoadingSculpties = 1.0f ; - mEndTimeLoadingSculpties = 0.0f ; + mStartTimeLoadingSculpties = 1.0f; + mEndTimeLoadingSculpties = 0.0f; } //virtual void LLTexturePipelineTester::outputTestRecord(LLSD *sd) { std::string currentLabel = getCurrentLabelName(); - (*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded ; - (*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache ; - (*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ; - (*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties ; + (*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded.value(); + (*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache.value(); + (*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage.value(); + (*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties.value(); - (*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime ; - (*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime ; - (*sd)[currentLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime ; + (*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime; + (*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime; + (*sd)[currentLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime; - (*sd)[currentLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties ; - (*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties ; + (*sd)[currentLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties; + (*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties; - (*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime ; - (*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed ; - (*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ; - (*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ; + (*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime; + (*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed.value(); + (*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage.value(); + (*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded); } void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep) { - U32 mem_size = (U32)imagep->getTextureMemory() ; - mTotalBytesUsed += mem_size ; + U32Bytes mem_size = imagep->getTextureMemory(); + mTotalBytesUsed += mem_size; - if(MIN_LARGE_IMAGE_AREA <= (U32)(mem_size / (U32)imagep->getComponents())) + if(MIN_LARGE_IMAGE_AREA <= (U32)(mem_size.value() / (U32)imagep->getComponents())) { - mTotalBytesUsedForLargeImage += mem_size ; + mTotalBytesUsedForLargeImage += mem_size; } } void LLTexturePipelineTester::updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache) { - U32 data_size = (U32)raw_imagep->getDataSize() ; - mTotalBytesLoaded += data_size ; + U32Bytes data_size = (U32Bytes)raw_imagep->getDataSize(); + mTotalBytesLoaded += data_size; if(from_cache) { - mTotalBytesLoadedFromCache += data_size ; + mTotalBytesLoadedFromCache += data_size; } - if(MIN_LARGE_IMAGE_AREA <= (U32)(data_size / (U32)raw_imagep->getComponents())) + if(MIN_LARGE_IMAGE_AREA <= (U32)(data_size.value() / (U32)raw_imagep->getComponents())) { - mTotalBytesLoadedForLargeImage += data_size ; + mTotalBytesLoadedForLargeImage += data_size; } if(imagep->forSculpt()) { - mTotalBytesLoadedForSculpties += data_size ; + mTotalBytesLoadedForSculpties += data_size; if(mStartTimeLoadingSculpties > mEndTimeLoadingSculpties) { - mStartTimeLoadingSculpties = LLImageGL::sLastFrameTime ; + mStartTimeLoadingSculpties = LLImageGL::sLastFrameTime; } - mEndTimeLoadingSculpties = LLImageGL::sLastFrameTime ; + mEndTimeLoadingSculpties = LLImageGL::sLastFrameTime; } } void LLTexturePipelineTester::updateGrayTextureBinding() { - mUsingDefaultTexture = TRUE ; + mUsingDefaultTexture = TRUE; } void LLTexturePipelineTester::setStablizingTime() { if(mStartStablizingTime <= mStartFetchingTime) { - mStartStablizingTime = LLImageGL::sLastFrameTime ; + mStartStablizingTime = LLImageGL::sLastFrameTime; } - mEndStablizingTime = LLImageGL::sLastFrameTime ; + mEndStablizingTime = LLImageGL::sLastFrameTime; } void LLTexturePipelineTester::updateStablizingTime() { if(mStartStablizingTime > mStartFetchingTime) { - F32 t = mEndStablizingTime - mStartStablizingTime ; + F32 t = mEndStablizingTime - mStartStablizingTime; if(t > F_ALMOST_ZERO && (t - mTotalStablizingTime) < F_ALMOST_ZERO) { //already stablized - mTotalStablizingTime = LLImageGL::sLastFrameTime - mStartStablizingTime ; + mTotalStablizingTime = LLImageGL::sLastFrameTime - mStartStablizingTime; //cancel the timer - mStartStablizingTime = 0.f ; - mEndStablizingTime = 0.f ; + mStartStablizingTime = 0.f; + mEndStablizingTime = 0.f; } else { - mTotalStablizingTime = t ; + mTotalStablizingTime = t; } } - mTotalStablizingTime = 0.f ; + mTotalStablizingTime = 0.f; } //virtual void LLTexturePipelineTester::compareTestSessions(std::ofstream* os) { - LLTexturePipelineTester::LLTextureTestSession* base_sessionp = dynamic_cast(mBaseSessionp) ; - LLTexturePipelineTester::LLTextureTestSession* current_sessionp = dynamic_cast(mCurrentSessionp) ; + LLTexturePipelineTester::LLTextureTestSession* base_sessionp = dynamic_cast(mBaseSessionp); + LLTexturePipelineTester::LLTextureTestSession* current_sessionp = dynamic_cast(mCurrentSessionp); if(!base_sessionp || !current_sessionp) { - LL_ERRS() << "type of test session does not match!" << LL_ENDL ; + LL_ERRS() << "type of test session does not match!" << LL_ENDL; } //compare and output the comparison - *os << llformat("%s\n", getTesterName().c_str()) ; - *os << llformat("AggregateResults\n") ; + *os << llformat("%s\n", getTesterName().c_str()); + *os << llformat("AggregateResults\n"); - compareTestResults(os, "TotalFetchingTime", base_sessionp->mTotalFetchingTime, current_sessionp->mTotalFetchingTime) ; - compareTestResults(os, "TotalGrayTime", base_sessionp->mTotalGrayTime, current_sessionp->mTotalGrayTime) ; + compareTestResults(os, "TotalFetchingTime", base_sessionp->mTotalFetchingTime, current_sessionp->mTotalFetchingTime); + compareTestResults(os, "TotalGrayTime", base_sessionp->mTotalGrayTime, current_sessionp->mTotalGrayTime); compareTestResults(os, "TotalStablizingTime", base_sessionp->mTotalStablizingTime, current_sessionp->mTotalStablizingTime); - compareTestResults(os, "StartTimeLoadingSculpties", base_sessionp->mStartTimeLoadingSculpties, current_sessionp->mStartTimeLoadingSculpties) ; - compareTestResults(os, "TotalTimeLoadingSculpties", base_sessionp->mTotalTimeLoadingSculpties, current_sessionp->mTotalTimeLoadingSculpties) ; + compareTestResults(os, "StartTimeLoadingSculpties", base_sessionp->mStartTimeLoadingSculpties, current_sessionp->mStartTimeLoadingSculpties); + compareTestResults(os, "TotalTimeLoadingSculpties", base_sessionp->mTotalTimeLoadingSculpties, current_sessionp->mTotalTimeLoadingSculpties); - compareTestResults(os, "TotalBytesLoaded", base_sessionp->mTotalBytesLoaded, current_sessionp->mTotalBytesLoaded) ; - compareTestResults(os, "TotalBytesLoadedFromCache", base_sessionp->mTotalBytesLoadedFromCache, current_sessionp->mTotalBytesLoadedFromCache) ; - compareTestResults(os, "TotalBytesLoadedForLargeImage", base_sessionp->mTotalBytesLoadedForLargeImage, current_sessionp->mTotalBytesLoadedForLargeImage) ; - compareTestResults(os, "TotalBytesLoadedForSculpties", base_sessionp->mTotalBytesLoadedForSculpties, current_sessionp->mTotalBytesLoadedForSculpties) ; + compareTestResults(os, "TotalBytesLoaded", base_sessionp->mTotalBytesLoaded, current_sessionp->mTotalBytesLoaded); + compareTestResults(os, "TotalBytesLoadedFromCache", base_sessionp->mTotalBytesLoadedFromCache, current_sessionp->mTotalBytesLoadedFromCache); + compareTestResults(os, "TotalBytesLoadedForLargeImage", base_sessionp->mTotalBytesLoadedForLargeImage, current_sessionp->mTotalBytesLoadedForLargeImage); + compareTestResults(os, "TotalBytesLoadedForSculpties", base_sessionp->mTotalBytesLoadedForSculpties, current_sessionp->mTotalBytesLoadedForSculpties); - *os << llformat("InstantResults\n") ; - S32 size = llmin(base_sessionp->mInstantPerformanceListCounter, current_sessionp->mInstantPerformanceListCounter) ; - for(S32 i = 0 ; i < size ; i++) + *os << llformat("InstantResults\n"); + S32 size = llmin(base_sessionp->mInstantPerformanceListCounter, current_sessionp->mInstantPerformanceListCounter); + for(S32 i = 0; i < size; i++) { - *os << llformat("Time(B-T)-%.4f-%.4f\n", base_sessionp->mInstantPerformanceList[i].mTime, current_sessionp->mInstantPerformanceList[i].mTime) ; + *os << llformat("Time(B-T)-%.4f-%.4f\n", base_sessionp->mInstantPerformanceList[i].mTime, current_sessionp->mInstantPerformanceList[i].mTime); compareTestResults(os, "AverageBytesUsedPerSecond", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond, - current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond) ; + current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond); compareTestResults(os, "AverageBytesUsedForLargeImagePerSecond", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond, - current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond) ; + current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond); compareTestResults(os, "AveragePercentageBytesUsedPerSecond", base_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond, - current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond) ; + current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond); } if(size < base_sessionp->mInstantPerformanceListCounter) { - for(S32 i = size ; i < base_sessionp->mInstantPerformanceListCounter ; i++) + for(S32 i = size; i < base_sessionp->mInstantPerformanceListCounter; i++) { - *os << llformat("Time(B-T)-%.4f- \n", base_sessionp->mInstantPerformanceList[i].mTime) ; + *os << llformat("Time(B-T)-%.4f- \n", base_sessionp->mInstantPerformanceList[i].mTime); - *os << llformat(", AverageBytesUsedPerSecond, %d, N/A \n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond) ; - *os << llformat(", AverageBytesUsedForLargeImagePerSecond, %d, N/A \n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond) ; - *os << llformat(", AveragePercentageBytesUsedPerSecond, %.4f, N/A \n", base_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond) ; + *os << llformat(", AverageBytesUsedPerSecond, %d, N/A \n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond); + *os << llformat(", AverageBytesUsedForLargeImagePerSecond, %d, N/A \n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond); + *os << llformat(", AveragePercentageBytesUsedPerSecond, %.4f, N/A \n", base_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond); } } else if(size < current_sessionp->mInstantPerformanceListCounter) { - for(S32 i = size ; i < current_sessionp->mInstantPerformanceListCounter ; i++) + for(S32 i = size; i < current_sessionp->mInstantPerformanceListCounter; i++) { - *os << llformat("Time(B-T)- -%.4f\n", current_sessionp->mInstantPerformanceList[i].mTime) ; + *os << llformat("Time(B-T)- -%.4f\n", current_sessionp->mInstantPerformanceList[i].mTime); - *os << llformat(", AverageBytesUsedPerSecond, N/A, %d\n", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond) ; - *os << llformat(", AverageBytesUsedForLargeImagePerSecond, N/A, %d\n", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond) ; - *os << llformat(", AveragePercentageBytesUsedPerSecond, N/A, %.4f\n", current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond) ; + *os << llformat(", AverageBytesUsedPerSecond, N/A, %d\n", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond); + *os << llformat(", AverageBytesUsedForLargeImagePerSecond, N/A, %d\n", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond); + *os << llformat(", AveragePercentageBytesUsedPerSecond, N/A, %.4f\n", current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond); } } } @@ -3877,144 +4095,144 @@ void LLTexturePipelineTester::compareTestSessions(std::ofstream* os) //virtual LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log) { - LLTexturePipelineTester::LLTextureTestSession* sessionp = new LLTexturePipelineTester::LLTextureTestSession() ; + LLTexturePipelineTester::LLTextureTestSession* sessionp = new LLTexturePipelineTester::LLTextureTestSession(); if(!sessionp) { - return NULL ; + return NULL; } - F32 total_fetching_time = 0.f ; - F32 total_gray_time = 0.f ; - F32 total_stablizing_time = 0.f ; - F32 total_loading_sculpties_time = 0.f ; - - F32 start_fetching_time = -1.f ; - F32 start_fetching_sculpties_time = 0.f ; - - F32 last_time = 0.0f ; - S32 frame_count = 0 ; - - sessionp->mInstantPerformanceListCounter = 0 ; - sessionp->mInstantPerformanceList.resize(128) ; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0 ; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0 ; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f ; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ; + F32 total_fetching_time = 0.f; + F32 total_gray_time = 0.f; + F32 total_stablizing_time = 0.f; + F32 total_loading_sculpties_time = 0.f; + + F32 start_fetching_time = -1.f; + F32 start_fetching_sculpties_time = 0.f; + + F32 last_time = 0.0f; + S32 frame_count = 0; + + sessionp->mInstantPerformanceListCounter = 0; + sessionp->mInstantPerformanceList.resize(128); + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f; //load a session std::string currentLabel = getCurrentLabelName(); - BOOL in_log = (*log).has(currentLabel) ; + BOOL in_log = (*log).has(currentLabel); while (in_log) { - LLSD::String label = currentLabel ; + LLSD::String label = currentLabel; if(sessionp->mInstantPerformanceListCounter >= (S32)sessionp->mInstantPerformanceList.size()) { - sessionp->mInstantPerformanceList.resize(sessionp->mInstantPerformanceListCounter + 128) ; + sessionp->mInstantPerformanceList.resize(sessionp->mInstantPerformanceListCounter + 128); } //time - F32 start_time = (*log)[label]["StartFetchingTime"].asReal() ; - F32 cur_time = (*log)[label]["Time"].asReal() ; + F32 start_time = (*log)[label]["StartFetchingTime"].asReal(); + F32 cur_time = (*log)[label]["Time"].asReal(); if(start_time - start_fetching_time > F_ALMOST_ZERO) //fetching has paused for a while { - sessionp->mTotalFetchingTime += total_fetching_time ; - sessionp->mTotalGrayTime += total_gray_time ; - sessionp->mTotalStablizingTime += total_stablizing_time ; - - sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time ; - sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time ; - - start_fetching_time = start_time ; - total_fetching_time = 0.0f ; - total_gray_time = 0.f ; - total_stablizing_time = 0.f ; - total_loading_sculpties_time = 0.f ; + sessionp->mTotalFetchingTime += total_fetching_time; + sessionp->mTotalGrayTime += total_gray_time; + sessionp->mTotalStablizingTime += total_stablizing_time; + + sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time; + sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time; + + start_fetching_time = start_time; + total_fetching_time = 0.0f; + total_gray_time = 0.f; + total_stablizing_time = 0.f; + total_loading_sculpties_time = 0.f; } else { - total_fetching_time = cur_time - start_time ; - total_gray_time = (*log)[label]["TotalGrayTime"].asReal() ; - total_stablizing_time = (*log)[label]["TotalStablizingTime"].asReal() ; + total_fetching_time = cur_time - start_time; + total_gray_time = (*log)[label]["TotalGrayTime"].asReal(); + total_stablizing_time = (*log)[label]["TotalStablizingTime"].asReal(); - total_loading_sculpties_time = (*log)[label]["EndTimeLoadingSculpties"].asReal() - (*log)[label]["StartTimeLoadingSculpties"].asReal() ; + total_loading_sculpties_time = (*log)[label]["EndTimeLoadingSculpties"].asReal() - (*log)[label]["StartTimeLoadingSculpties"].asReal(); if(start_fetching_sculpties_time < 0.f && total_loading_sculpties_time > 0.f) { - start_fetching_sculpties_time = (*log)[label]["StartTimeLoadingSculpties"].asReal() ; + start_fetching_sculpties_time = (*log)[label]["StartTimeLoadingSculpties"].asReal(); } } //total loaded bytes - sessionp->mTotalBytesLoaded = (*log)[label]["TotalBytesLoaded"].asInteger() ; - sessionp->mTotalBytesLoadedFromCache = (*log)[label]["TotalBytesLoadedFromCache"].asInteger() ; - sessionp->mTotalBytesLoadedForLargeImage = (*log)[label]["TotalBytesLoadedForLargeImage"].asInteger() ; - sessionp->mTotalBytesLoadedForSculpties = (*log)[label]["TotalBytesLoadedForSculpties"].asInteger() ; + sessionp->mTotalBytesLoaded = (*log)[label]["TotalBytesLoaded"].asInteger(); + sessionp->mTotalBytesLoadedFromCache = (*log)[label]["TotalBytesLoadedFromCache"].asInteger(); + sessionp->mTotalBytesLoadedForLargeImage = (*log)[label]["TotalBytesLoadedForLargeImage"].asInteger(); + sessionp->mTotalBytesLoadedForSculpties = (*log)[label]["TotalBytesLoadedForSculpties"].asInteger(); //instant metrics sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond += - (*log)[label]["TotalBytesBound"].asInteger() ; + (*log)[label]["TotalBytesBound"].asInteger(); sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond += - (*log)[label]["TotalBytesBoundForLargeImage"].asInteger() ; + (*log)[label]["TotalBytesBoundForLargeImage"].asInteger(); sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond += - (*log)[label]["PercentageBytesBound"].asReal() ; - frame_count++ ; + (*log)[label]["PercentageBytesBound"].asReal(); + frame_count++; if(cur_time - last_time >= 1.0f) { - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond /= frame_count ; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond /= frame_count ; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond /= frame_count ; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = last_time ; - - frame_count = 0 ; - last_time = cur_time ; - sessionp->mInstantPerformanceListCounter++ ; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0 ; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0 ; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f ; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond /= frame_count; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond /= frame_count; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond /= frame_count; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = last_time; + + frame_count = 0; + last_time = cur_time; + sessionp->mInstantPerformanceListCounter++; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f; } // Next label - incrementCurrentCount() ; + incrementCurrentCount(); currentLabel = getCurrentLabelName(); - in_log = (*log).has(currentLabel) ; + in_log = (*log).has(currentLabel); } - sessionp->mTotalFetchingTime += total_fetching_time ; - sessionp->mTotalGrayTime += total_gray_time ; - sessionp->mTotalStablizingTime += total_stablizing_time ; + sessionp->mTotalFetchingTime += total_fetching_time; + sessionp->mTotalGrayTime += total_gray_time; + sessionp->mTotalStablizingTime += total_stablizing_time; if(sessionp->mStartTimeLoadingSculpties < 0.f) { - sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time ; + sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time; } - sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time ; + sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time; return sessionp; } LLTexturePipelineTester::LLTextureTestSession::LLTextureTestSession() { - reset() ; + reset(); } LLTexturePipelineTester::LLTextureTestSession::~LLTextureTestSession() { } void LLTexturePipelineTester::LLTextureTestSession::reset() { - mTotalFetchingTime = 0.0f ; + mTotalFetchingTime = 0.0f; - mTotalGrayTime = 0.0f ; - mTotalStablizingTime = 0.0f ; + mTotalGrayTime = 0.0f; + mTotalStablizingTime = 0.0f; - mStartTimeLoadingSculpties = 0.0f ; - mTotalTimeLoadingSculpties = 0.0f ; + mStartTimeLoadingSculpties = 0.0f; + mTotalTimeLoadingSculpties = 0.0f; - mTotalBytesLoaded = 0 ; - mTotalBytesLoadedFromCache = 0 ; - mTotalBytesLoadedForLargeImage = 0 ; - mTotalBytesLoadedForSculpties = 0 ; + mTotalBytesLoaded = 0; + mTotalBytesLoadedFromCache = 0; + mTotalBytesLoadedForLargeImage = 0; + mTotalBytesLoadedForSculpties = 0; - mInstantPerformanceListCounter = 0 ; + mInstantPerformanceListCounter = 0; } #endif //0 //---------------------------------------------------------------------------------------------- diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 94eeaf19ea..0a68570598 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -41,8 +41,9 @@ #include #include -#define MIN_VIDEO_RAM_IN_MEGA_BYTES 32 -#define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons. +extern const S32Megabytes gMinVideoRam; +extern const S32Megabytes gMaxVideoRam; + class LLImageGL ; class LLImageRaw; @@ -60,11 +61,12 @@ class LLMessageSystem; class LLViewerMediaImpl ; class LLVOVolume ; class LLFace ; //But llface.h is already included...(?) +struct LLTextureKey; class LLLoadedCallbackEntry { public: - typedef std::set< LLUUID > source_callback_list_t; + typedef std::set< LLTextureKey > source_callback_list_t; public: LLLoadedCallbackEntry(loaded_callback_func cb, @@ -118,10 +120,10 @@ class LLViewerTexture : public LLGLTexture static void initClass(); static void updateClass(const F32 velocity, const F32 angular_velocity) ; - LLViewerTexture(BOOL usemipmaps = TRUE); - LLViewerTexture(const LLUUID& id, BOOL usemipmaps) ; - LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) ; - LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; + LLViewerTexture(BOOL usemipmaps = TRUE, bool allow_compression = false); + LLViewerTexture(const LLUUID& id, BOOL usemipmaps, bool allow_compression = false) ; + LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps, bool allow_compression = false) ; + LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, bool allow_compression = false) ; void setNeedsAlphaAndPickMask(BOOL need_mask) { if(mGLTexturep)mGLTexturep->setNeedsAlphaAndPickMask(need_mask); } @@ -131,10 +133,14 @@ class LLViewerTexture : public LLGLTexture /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; /*virtual*/ void forceImmediateUpdate() ; + /*virtual*/ bool isActiveFetching(); /*virtual*/ const LLUUID& getID() const { return mID; } - //void setBoostLevel(S32 level); + void setID(const LLUUID& id) { mID = id; } // Edit for local assets to cut down on reloads, be sure to remove from wherever this has been added first. + void setBoostLevel(S32 level); S32 getBoostLevel() { return mBoostLevel; } + void setTextureListType(S32 tex_type) { mTextureListType = tex_type; } + S32 getTextureListType() { return mTextureListType; } void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const; void resetTextureStats(); @@ -146,6 +152,8 @@ class LLViewerTexture : public LLGLTexture LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;} + S32 getFullWidth() const { return mFullWidth; } + S32 getFullHeight() const { return mFullHeight; } /*virtual*/ void setKnownDrawSize(S32 width, S32 height); virtual void addFace(U32 channel, LLFace* facep) ; @@ -154,10 +162,10 @@ class LLViewerTexture : public LLGLTexture S32 getNumFaces(U32 ch) const; const ll_face_list_t* getFaceList(U32 channel) const {llassert(channel < LLRender::NUM_TEXTURE_CHANNELS); return &mFaceList[channel];} - virtual void addVolume(LLVOVolume* volumep); - virtual void removeVolume(LLVOVolume* volumep); - S32 getNumVolumes() const; - const ll_volume_list_t* getVolumeList() const { return &mVolumeList; } + virtual void addVolume(U32 channel, LLVOVolume* volumep); + virtual void removeVolume(U32 channel, LLVOVolume* volumep); + S32 getNumVolumes(U32 channel) const; + const ll_volume_list_t* getVolumeList(U32 channel) const { return &mVolumeList[channel]; } virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; @@ -173,6 +181,10 @@ class LLViewerTexture : public LLGLTexture void init(bool firstinit) ; void reorganizeFaceList() ; void reorganizeVolumeList() ; + + void notifyAboutMissingAsset(); + void notifyAboutCreatingTexture(); + private: friend class LLBumpImageList; friend class LLUIImageList; @@ -183,7 +195,9 @@ class LLViewerTexture : public LLGLTexture static bool isMemoryForTextureLow() ; protected: LLUUID mID; + S32 mTextureListType; // along with mID identifies where to search for this texture in TextureList + F32 mSelectedTime; // time texture was last selected mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need? mutable S32 mMaxVirtualSizeResetCounter ; mutable S32 mMaxVirtualSizeResetInterval; @@ -194,8 +208,8 @@ class LLViewerTexture : public LLGLTexture U32 mNumFaces[LLRender::NUM_TEXTURE_CHANNELS]; LLFrameTimer mLastFaceListUpdateTimer ; - ll_volume_list_t mVolumeList; - U32 mNumVolumes; + ll_volume_list_t mVolumeList[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; + U32 mNumVolumes[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; LLFrameTimer mLastVolumeListUpdateTimer; //do not use LLPointer here. @@ -210,12 +224,12 @@ class LLViewerTexture : public LLGLTexture static LLFrameTimer sEvaluationTimer; static F32 sDesiredDiscardBias; static F32 sDesiredDiscardScale; - static S32 sBoundTextureMemoryInBytes; - static S32 sTotalTextureMemoryInBytes; - static S32 sMaxBoundTextureMemInMegaBytes; - static S32 sMaxTotalTextureMemInMegaBytes; - static S32 sMaxDesiredTextureMemInBytes ; - static S8 sCameraMovingDiscardBias; + static S64Bytes sBoundTextureMemory; + static S64Bytes sTotalTextureMemory; + static S32Megabytes sMaxBoundTextureMemory; + static S32Megabytes sMaxTotalTextureMem; + static S64Bytes sMaxDesiredTextureMem ; + static S32 sCameraMovingDiscardBias; static F32 sCameraMovingBias; static S32 sMaxSculptRez ; static S32 sMinLargeImageSize ; @@ -239,6 +253,18 @@ class LLViewerTexture : public LLGLTexture }; +enum FTType +{ + FTT_UNKNOWN = -1, + FTT_DEFAULT = 0, // standard texture fetched by id. + FTT_SERVER_BAKE, // texture produced by appearance service and fetched from there. + FTT_HOST_BAKE, // old-style baked texture uploaded by viewer and fetched from avatar's host. + FTT_MAP_TILE, // tiles are fetched from map server directly. + FTT_LOCAL_FILE // fetch directly from a local file. +}; + +const std::string& fttype_to_string(const FTType& fttype); + // //textures are managed in gTextureList. //raw image data is fetched from remote or local cache @@ -252,9 +278,9 @@ class LLViewerFetchedTexture : public LLViewerTexture protected: /*virtual*/ ~LLViewerFetchedTexture(); public: - LLViewerFetchedTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); - LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps); - LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps); + LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); public: static F32 maxDecodePriority(); @@ -279,6 +305,7 @@ class LLViewerFetchedTexture : public LLViewerTexture public: /*virtual*/ S8 getType() const ; + FTType getFTType() const; /*virtual*/ void forceImmediateUpdate() ; /*virtual*/ void dump() ; @@ -297,7 +324,7 @@ class LLViewerFetchedTexture : public LLViewerTexture void addToCreateTexture(); // ONLY call from LLViewerTextureList - BOOL createTexture(S32 usename = 0); + BOOL createTexture(LLImageGL::GLTextureName* usename = nullptr); void destroyTexture() ; virtual void processTextureStats() ; @@ -324,13 +351,17 @@ class LLViewerFetchedTexture : public LLViewerTexture void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); } bool updateFetch(); + bool setDebugFetching(S32 debug_level); + bool isInDebug() {return mInDebug;} + void clearFetchedResults(); //clear all fetched results, for debug use. + // Override the computation of discard levels if we know the exact output // size of the image. Used for UI textures to not decode, even if we have // more data. /*virtual*/ void setKnownDrawSize(S32 width, S32 height); - void setIsMissingAsset(); + void setIsMissingAsset(BOOL is_missing = true); /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } // returns dimensions of original image for local files (before power of two scaling) @@ -373,6 +404,7 @@ class LLViewerFetchedTexture : public LLViewerTexture BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;} BOOL isRawImageValid()const { return mIsRawImageValid ; } void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ; + void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f); /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; void destroySavedRawImage() ; LLImageRaw* getSavedRawImage() ; @@ -385,6 +417,11 @@ class LLViewerFetchedTexture : public LLViewerTexture void forceToDeleteRequest(); void forceRefetch(); + /*virtual*/bool isActiveFetching(); //is actively in fetching by the fetching pipeline. + + LLUUID getUploader(); + LLDate getUploadTime(); + std::string getComment(); protected: /*virtual*/ void switchToCachedImage(); @@ -405,6 +442,8 @@ class LLViewerFetchedTexture : public LLViewerTexture private: BOOL mFullyLoaded; + BOOL mInDebug; + BOOL mForceCallbackFetch; protected: std::string mLocalFileName; @@ -432,12 +471,14 @@ class LLViewerFetchedTexture : public LLViewerTexture S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have S8 mNeedsAux; // We need to decode the auxiliary channels + S8 mHasAux; // We have aux channels S8 mDecodingAux; // Are we decoding high components S8 mIsRawImageValid; S8 mHasFetcher; // We've made a fecth request S8 mIsFetching; // Fetch request is active bool mCanUseHTTP ; //This texture can be fetched through http if true. - + + const FTType mFTType; // What category of image is this - map tile, server bake, etc? mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. typedef std::list callback_list_t; @@ -479,6 +520,8 @@ class LLViewerFetchedTexture : public LLViewerTexture BOOL mForSculpt ; //a flag if the texture is used as sculpt data. BOOL mIsFetched ; //is loaded from remote or from cache, not generated locally. + + std::map mComment; public: static LLPointer sMissingAssetImagep; // Texture to show for an image asset that is not in the database @@ -498,8 +541,8 @@ class LLViewerLODTexture : public LLViewerFetchedTexture /*virtual*/ ~LLViewerLODTexture(){} public: - LLViewerLODTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); - LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE); + LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); + LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); /*virtual*/ S8 getType() const; // Process image stats to determine priority/quality requirements. @@ -565,7 +608,7 @@ class LLViewerMediaTexture : public LLViewerTexture LLViewerMediaImpl* mMediaImplp ; BOOL mIsPlaying ; - U32 mUpdateVirtualSizeTime ; + U64 mUpdateVirtualSizeTime ; public: static void updateClass() ; @@ -598,8 +641,9 @@ class LLViewerTextureManager // //"find-texture" just check if the texture exists, if yes, return it, otherwise return null. // - static LLViewerTexture* findTexture(const LLUUID& id) ; - static LLViewerFetchedTexture* findFetchedTexture(const LLUUID& id) ; + static void findFetchedTextures(const LLUUID& id, std::vector &output); + static void findTextures(const LLUUID& id, std::vector &output); + static LLViewerFetchedTexture* findFetchedTexture(const LLUUID& id, S32 tex_type); static LLViewerMediaTexture* findMediaTexture(const LLUUID& id) ; static LLViewerMediaTexture* createMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; @@ -615,6 +659,7 @@ class LLViewerTextureManager static LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ; static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id, + FTType f_type = FTT_DEFAULT, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -624,6 +669,7 @@ class LLViewerTextureManager ); static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename, + FTType f_type = FTT_LOCAL_FILE, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -633,6 +679,7 @@ class LLViewerTextureManager ); static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url, + FTType f_type, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -641,7 +688,7 @@ class LLViewerTextureManager const LLUUID& force_id = LLUUID::null ); - static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) ; + static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) ; static void init() ; static void cleanup() ; @@ -679,18 +726,18 @@ class LLTexturePipelineTester : public LLMetricPerformanceTesterWithSession private: BOOL mUsingDefaultTexture; //if set, some textures are still gray. - U32 mTotalBytesUsed ; //total bytes of textures bound/used for the current frame. - U32 mTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the current frame for images larger than 256 * 256. - U32 mLastTotalBytesUsed ; //total bytes of textures bound/used for the previous frame. - U32 mLastTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the previous frame for images larger than 256 * 256. + U32Bytes mTotalBytesUsed ; //total bytes of textures bound/used for the current frame. + U32Bytes mTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the current frame for images larger than 256 * 256. + U32Bytes mLastTotalBytesUsed ; //total bytes of textures bound/used for the previous frame. + U32Bytes mLastTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the previous frame for images larger than 256 * 256. // //data size // - U32 mTotalBytesLoaded ; //total bytes fetched by texture pipeline - U32 mTotalBytesLoadedFromCache ; //total bytes fetched by texture pipeline from local cache - U32 mTotalBytesLoadedForLargeImage ; //total bytes fetched by texture pipeline for images larger than 256 * 256. - U32 mTotalBytesLoadedForSculpties ; //total bytes fetched by texture pipeline for sculpties + U32Bytes mTotalBytesLoaded ; //total bytes fetched by texture pipeline + U32Bytes mTotalBytesLoadedFromCache ; //total bytes fetched by texture pipeline from local cache + U32Bytes mTotalBytesLoadedForLargeImage ; //total bytes fetched by texture pipeline for images larger than 256 * 256. + U32Bytes mTotalBytesLoadedForSculpties ; //total bytes fetched by texture pipeline for sculpties // //time diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index a5ec4c9a7f..5bcd717b6e 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -64,23 +64,43 @@ #include "llviewerstats.h" #include "pipeline.h" #include "llappviewer.h" +#include "llxuiparser.h" #include "llagent.h" #include "llviewerdisplay.h" +#include "llviewerwindow.h" +#include "llprogressview.h" #include "llflexibleobject.h" //////////////////////////////////////////////////////////////////////////// void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL; -U32 LLViewerTextureList::sTextureBits = 0; +U32Bits LLViewerTextureList::sTextureBits(0); U32 LLViewerTextureList::sTexturePackets = 0; S32 LLViewerTextureList::sNumImages = 0; LLViewerTextureList gTextureList; -static LLFastTimer::DeclareTimer FTM_PROCESS_IMAGES("Process Images"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_IMAGES("Process Images"); + +ETexListType get_element_type(S32 priority) +{ + return (priority == LLViewerFetchedTexture::BOOST_ICON) ? TEX_LIST_SCALE : TEX_LIST_STANDARD; +} /////////////////////////////////////////////////////////////////////////////// +LLTextureKey::LLTextureKey() +: textureId(LLUUID::null), +textureType(TEX_LIST_STANDARD) +{ +} + +LLTextureKey::LLTextureKey(LLUUID id, ETexListType tex_type) +: textureId(id), textureType(tex_type) +{ +} + +/////////////////////////////////////////////////////////////////////////////// LLViewerTextureList::LLViewerTextureList() : mForceResetTextureStats(FALSE), mUpdateStats(FALSE), @@ -95,8 +115,8 @@ void LLViewerTextureList::init() mInitialized = TRUE ; sNumImages = 0; mUpdateStats = TRUE; - mMaxResidentTexMemInMegaBytes = 0; - mMaxTotalTextureMemInMegaBytes = 0 ; + mMaxResidentTexMemInMegaBytes = (U32Bytes)0; + mMaxTotalTextureMemInMegaBytes = (U32Bytes)0; if (gNoRender) { // Don't initialize GL stuff if we're not rendering. @@ -104,7 +124,7 @@ void LLViewerTextureList::init() } // Update how much texture RAM we're allowed to use. - updateMaxResidentTexMem(0); // 0 = use current + updateMaxResidentTexMem(S32Megabytes(0)); // 0 = use current doPreloadImages(); } @@ -117,16 +137,17 @@ void LLViewerTextureList::doPreloadImages() llassert_always(mInitialized) ; llassert_always(mImageList.empty()) ; llassert_always(mUUIDMap.empty()) ; + llassert_always(mUUIDDict.empty()); // Set the "missing asset" image - LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); + LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); // Set the "white" image - LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); + LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); LLUIImageList* image_list = LLUIImageList::getInstance(); - LLViewerFetchedTexture::sFlatNormalImagep = LLViewerTextureManager::getFetchedTextureFromFile("flatnormal.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_BUMP); + LLViewerFetchedTexture::sFlatNormalImagep = LLViewerTextureManager::getFetchedTextureFromFile("flatnormal.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_BUMP); image_list->initFromFile(); // turn off clamping and bilinear filtering for uv picking images @@ -138,42 +159,56 @@ void LLViewerTextureList::doPreloadImages() //uv_test->setMipFilterNearest(TRUE, TRUE); // prefetch specific UUIDs - LLViewerTextureManager::getFetchedTexture(IMG_SHOT, TRUE); - LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF, TRUE); - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + LLViewerTextureManager::getFetchedTexture(IMG_SHOT); + LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF); + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("noentrylines.j2c"/*"world/NoEntryLines.png"*/, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("noentrypasslines.j2c"/*"world/NoEntryPassLines.png"*/, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, FTT_DEFAULT, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, + image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, 0,0,LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903")); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } + image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, + 0,0,LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); + if (image) + { + image->setAddressMode(LLTexUnit::TAM_WRAP); + mImagePreloads.insert(image); + } + image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, + 0,0,LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); + if (image) + { + image->setAddressMode(LLTexUnit::TAM_WRAP); + mImagePreloads.insert(image); + } //Hideous hack to set filtering and address modes without messing with our texture classes. { - LLPointer temp_image = image_list->getUIImage("checkerboard.tga",LLViewerFetchedTexture::BOOST_UI); + LLPointer temp_image = image_list->getUIImage("checkerboard.tga", LLViewerFetchedTexture::BOOST_UI); if(temp_image.notNull() && temp_image->getImage().notNull()) { LLViewerTexture *tex = (LLViewerTexture*)temp_image->getImage().get(); @@ -186,7 +221,7 @@ void LLViewerTextureList::doPreloadImages() static std::string get_texture_list_name() { - return std::string("texture_list_") + gSavedSettings.getString("LoginLocation") + ".xml"; + return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "texture_list_" + gSavedSettings.getString("LoginLocation") + ".xml"); } void LLViewerTextureList::doPrefetchImages() @@ -199,13 +234,22 @@ void LLViewerTextureList::doPrefetchImages() // Pre-fetch textures from last logout LLSD imagelist; - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, get_texture_list_name()); + std::string filename = get_texture_list_name(); llifstream file; - file.open(filename); + file.open(filename.c_str()); if (file.is_open()) { - LLSDSerialize::fromXML(imagelist, file); - } + if ( ! LLSDSerialize::fromXML(imagelist, file) ) + { + file.close(); + LL_WARNS() << "XML parse error reading texture list '" << filename << "'" << LL_ENDL; + LL_WARNS() << "Removing invalid texture list '" << filename << "'" << LL_ENDL; + LLFile::remove(filename); + return; + } + file.close(); + } + S32 texture_count = 0; for (LLSD::array_iterator iter = imagelist.beginArray(); iter != imagelist.endArray(); ++iter) { @@ -216,13 +260,15 @@ void LLViewerTextureList::doPrefetchImages() if(LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type) { - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, texture_type); + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, texture_type); if (image) { + texture_count += 1; image->addTextureStats((F32)pixel_area); } } } + LL_DEBUGS() << "fetched " << texture_count << " images from " << filename << LL_ENDL; } /////////////////////////////////////////////////////////////////////////////// @@ -243,11 +289,17 @@ void LLViewerTextureList::shutdown() iter != mImageList.end(); ++iter) { LLViewerFetchedTexture* image = *iter; + if (!(image->getType() == LLViewerTexture::FETCHED_TEXTURE || image->getType() == LLViewerTexture::LOD_TEXTURE) || + image->getFTType() != FTT_DEFAULT || + image->getID() == IMG_DEFAULT) + { + continue; + } if (!image->hasGLTexture() || !image->getUseDiscard() || - image->needsAux() || - image->getTargetHost() != LLHost::invalid || - !image->getUrl().empty() + image->needsAux()// || + //image->getTargetHost() != LLHost::invalid || + //!image->getUrl().empty() ) { continue; // avoid UI, baked, and other special images @@ -282,7 +334,7 @@ void LLViewerTextureList::shutdown() if (count > 0 && !gDirUtilp->getLindenUserDir(true).empty()) { - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, get_texture_list_name()); + std::string filename = get_texture_list_name(); llofstream file; file.open(filename); LLSDSerialize::toPrettyXML(imagelist, file); @@ -298,6 +350,7 @@ void LLViewerTextureList::shutdown() mCreateTextureList.clear(); mUUIDMap.clear(); + mUUIDDict.clear(); mImageList.clear(); @@ -323,6 +376,7 @@ void LLViewerTextureList::dump() void LLViewerTextureList::destroyGL(BOOL save_state) { + clearFetchingRequests(); LLImageGL::destroyGL(save_state); } @@ -342,6 +396,7 @@ void LLViewerTextureList::restoreGL() /////////////////////////////////////////////////////////////////////////////// LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -354,19 +409,29 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& return NULL ; } - std::string full_path = gDirUtilp->findSkinnedFilename("textures", filename); - if (full_path.empty()) + // Singu Note: Detect if we were given a full path already, require being over a certain size, so we have more than just a path + bool full = filename.size() > +#ifdef LL_WINDOWS + 3 && filename.substr(1, 2) == ":\\"; // Drive letter comes first +#else + 1 && filename.front() == '/'; // delim is root +#endif + + std::string full_path = full ? filename : gDirUtilp->findSkinnedFilename("textures", filename); + if (full_path.empty() || (full && !gDirUtilp->fileExists(full_path))) { LL_WARNS() << "Failed to find local image file: " << filename << LL_ENDL; - return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + LLViewerTexture::EBoostLevel priority = LLGLTexture::BOOST_UI; + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, priority); } std::string url = "file://" + full_path; - return getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); + return getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); } LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& url, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -383,7 +448,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& { // Never mind that this ignores image_set_id; // getImage() will handle that later. - return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); } // generate UUID based on hash of filename @@ -397,7 +462,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& new_id.generate(url); } - LLPointer imagep = findImage(new_id); + LLPointer imagep = findImage(new_id, get_element_type(boost_priority)); if (!imagep.isNull()) { @@ -421,10 +486,10 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& switch(texture_type) { case LLViewerTexture::FETCHED_TEXTURE: - imagep = new LLViewerFetchedTexture(url, new_id, usemipmaps); + imagep = new LLViewerFetchedTexture(url, f_type, new_id, usemipmaps); break ; case LLViewerTexture::LOD_TEXTURE: - imagep = new LLViewerLODTexture(url, new_id, usemipmaps); + imagep = new LLViewerLODTexture(url, f_type, new_id, usemipmaps); break ; default: LL_ERRS() << "Invalid texture type " << texture_type << LL_ENDL ; @@ -435,15 +500,21 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& imagep->setExplicitFormat(internal_format, primary_format); } - addImage(imagep); - + addImage(imagep, get_element_type(boost_priority)); + if (boost_priority != 0) { - if (boost_priority == LLViewerFetchedTexture::BOOST_UI || - boost_priority == LLViewerFetchedTexture::BOOST_ICON) + if (boost_priority == LLViewerFetchedTexture::BOOST_UI) { imagep->dontDiscard(); } + if (boost_priority == LLViewerFetchedTexture::BOOST_ICON) + { + // Agent and group Icons are downloadable content, nothing manages + // icon deletion yet, so they should not persist + imagep->dontDiscard(); + imagep->forceActive(); + } imagep->setBoostLevel(boost_priority); } } @@ -454,7 +525,8 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& } -LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, +LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -473,12 +545,18 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, if ((&image_id == NULL) || image_id.isNull()) { - return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI)); + return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI)); } - LLPointer imagep = findImage(image_id); + LLPointer imagep = findImage(image_id, get_element_type(boost_priority)); if (!imagep.isNull()) { + if (boost_priority != LLViewerTexture::BOOST_ALM && imagep->getBoostLevel() == LLViewerTexture::BOOST_ALM) + { + // Workaround: we need BOOST_ALM texture for something, 'rise' to NONE + imagep->setBoostLevel(LLViewerTexture::BOOST_NONE); + } + LLViewerFetchedTexture *texture = imagep.get(); if (request_from_host.isOk() && !texture->getTargetHost().isOk()) @@ -492,11 +570,15 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, LL_WARNS() << "Requested texture " << image_id << " already exists with a different target host, requested: " << request_from_host << " current: " << texture->getTargetHost() << LL_ENDL; } + if (f_type != FTT_DEFAULT && imagep->getFTType() != f_type) + { + LL_WARNS() << "FTType mismatch: requested " << f_type << " image has " << imagep->getFTType() << LL_ENDL; + } } if (imagep.isNull()) { - imagep = createImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; + imagep = createImage(image_id, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; } imagep->setGLTextureCreated(true); @@ -506,6 +588,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, //when this function is called, there is no such texture in the gTextureList with image_id. LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -517,10 +600,10 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, switch(texture_type) { case LLViewerTexture::FETCHED_TEXTURE: - imagep = new LLViewerFetchedTexture(image_id, request_from_host, usemipmaps); + imagep = new LLViewerFetchedTexture(image_id, f_type, request_from_host, usemipmaps); break ; case LLViewerTexture::LOD_TEXTURE: - imagep = new LLViewerLODTexture(image_id, request_from_host, usemipmaps); + imagep = new LLViewerLODTexture(image_id, f_type, request_from_host, usemipmaps); break ; default: LL_ERRS() << "Invalid texture type " << texture_type << LL_ENDL ; @@ -530,15 +613,21 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, { imagep->setExplicitFormat(internal_format, primary_format); } - - addImage(imagep); + + addImage(imagep, get_element_type(boost_priority)); if (boost_priority != 0) { - if (boost_priority == LLViewerFetchedTexture::BOOST_UI || - boost_priority == LLViewerFetchedTexture::BOOST_ICON) + if (boost_priority == LLViewerFetchedTexture::BOOST_UI) + { + imagep->dontDiscard(); + } + if (boost_priority == LLViewerFetchedTexture::BOOST_ICON) { + // Agent and group Icons are downloadable content, nothing manages + // icon deletion yet, so they should not persist. imagep->dontDiscard(); + imagep->forceActive(); } imagep->setBoostLevel(boost_priority); } @@ -553,12 +642,29 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, return imagep ; } -LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLUUID &image_id) +void LLViewerTextureList::findTexturesByID(const LLUUID &image_id, std::vector &output) +{ + LLTextureKey search_key(image_id, TEX_LIST_STANDARD); + uuid_map_t::iterator iter = mUUIDMap.lower_bound(search_key); + while (iter != mUUIDMap.end() && iter->first.textureId == image_id) + { + output.push_back(iter->second); + iter++; + } +} + +LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLTextureKey &search_key) { - uuid_map_t::iterator iter = mUUIDMap.find(image_id); - if(iter == mUUIDMap.end()) + // Singu note: Reworked hotspot + const auto& iter = mUUIDDict.find(search_key); + if(iter == mUUIDDict.end()) return NULL; - return iter->second; + return iter->second; +} + +LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLUUID &image_id, ETexListType tex_type) +{ + return findImage(LLTextureKey(image_id, tex_type)); } void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image) @@ -567,15 +673,17 @@ void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image) llassert_always(mInitialized) ; llassert(image); if (image->isInImageList()) - { - LL_ERRS() << "LLViewerTextureList::addImageToList - Image already in list" << LL_ENDL; + { // Flag is already set? + LL_WARNS() << "LLViewerTextureList::addImageToList - image " << image->getID() << " already in list" << LL_ENDL; } - if((mImageList.insert(image)).second != true) + else { - LL_ERRS() << "Error happens when insert image to mImageList!" << LL_ENDL ; + if((mImageList.insert(image)).second != true) + { + LL_WARNS() << "Error happens when insert image " << image->getID() << " into mImageList!" << LL_ENDL ; + } + image->setInImageList(TRUE) ; } - - image->setInImageList(TRUE) ; } void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image) @@ -583,28 +691,50 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image) assert_main_thread(); llassert_always(mInitialized) ; llassert(image); - if (!image->isInImageList()) + + S32 count = 0; + if (image->isInImageList()) { - LL_INFOS() << "RefCount: " << image->getNumRefs() << LL_ENDL ; - uuid_map_t::iterator iter = mUUIDMap.find(image->getID()); - if(iter == mUUIDMap.end() || iter->second != image) + count = mImageList.erase(image) ; + if(count != 1) + { + LL_INFOS() << "Image " << image->getID() + << " had mInImageList set but mImageList.erase() returned " << count + << LL_ENDL; + } + } + else + { // Something is wrong, image is expected in list or callers should check first + LL_INFOS() << "Calling removeImageFromList() for " << image->getID() + << " but doesn't have mInImageList set" + << " ref count is " << image->getNumRefs() + << LL_ENDL; + const auto& iter = mUUIDDict.find(LLTextureKey(image->getID(), (ETexListType)image->getTextureListType())); + if(iter == mUUIDDict.end()) { - LL_INFOS() << "Image is not in mUUIDMap!" << LL_ENDL ; + LL_INFOS() << "Image " << image->getID() << " is also not in mUUIDMap!" << LL_ENDL ; } - LL_ERRS() << "LLViewerTextureList::removeImageFromList - Image not in list" << LL_ENDL; + else if (iter->second != image) + { + LL_INFOS() << "Image " << image->getID() << " was in mUUIDMap but with different pointer" << LL_ENDL ; } - - S32 count = mImageList.erase(image) ; - if(count != 1) + else { - LL_INFOS() << image->getID() << LL_ENDL ; - LL_ERRS() << "Error happens when remove image from mImageList: " << count << LL_ENDL ; + LL_INFOS() << "Image " << image->getID() << " was in mUUIDMap with same pointer" << LL_ENDL ; + } + count = mImageList.erase(image) ; + if(count != 0) + { // it was in the list already? + LL_WARNS() << "Image " << image->getID() + << " had mInImageList false but mImageList.erase() returned " << count + << LL_ENDL; + } } image->setInImageList(FALSE) ; } -void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image) +void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListType tex_type) { if (!new_image) { @@ -612,16 +742,23 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image) return; } LLUUID image_id = new_image->getID(); + LLTextureKey key(image_id, tex_type); - LLViewerFetchedTexture *image = findImage(image_id); + LLViewerFetchedTexture *image = findImage(key); if (image) { - LL_WARNS() << "Image with ID " << image_id << " already in list" << LL_ENDL; + LL_INFOS() << "Image with ID " << image_id << " already in list" << LL_ENDL; } sNumImages++; addImageToList(new_image); - mUUIDMap[image_id] = new_image; + auto ret_pair = mUUIDMap.emplace(key, new_image); + if (!ret_pair.second) + { + ret_pair.first->second = new_image; + } + mUUIDDict.insert_or_assign(key, new_image); + new_image->setTextureListType(tex_type); } @@ -634,7 +771,9 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image) mCallbackList.erase(image); } - llverify(mUUIDMap.erase(image->getID()) == 1); + const LLTextureKey key(image->getID(), (ETexListType)image->getTextureListType()); + llverify(mUUIDMap.erase(key) == 1); + llverify(mUUIDDict.erase(key) == 1); sNumImages--; removeImageFromList(image); } @@ -651,13 +790,13 @@ void LLViewerTextureList::dirtyImage(LLViewerFetchedTexture *image) } //////////////////////////////////////////////////////////////////////////// -static LLFastTimer::DeclareTimer FTM_IMAGE_MARK_DIRTY("Dirty Images"); -static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_PRIORITIES("Prioritize"); -static LLFastTimer::DeclareTimer FTM_IMAGE_CALLBACKS("Callbacks"); -static LLFastTimer::DeclareTimer FTM_IMAGE_FETCH("Fetch"); -static LLFastTimer::DeclareTimer FTM_IMAGE_CREATE("Create"); -static LLFastTimer::DeclareTimer FTM_IMAGE_STATS("Stats"); -static LLFastTimer::DeclareTimer FTM_IMAGE_MEDIA("Media"); +static LLTrace::BlockTimerStatHandle FTM_IMAGE_MARK_DIRTY("Dirty Images"); +static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_PRIORITIES("Prioritize"); +static LLTrace::BlockTimerStatHandle FTM_IMAGE_CALLBACKS("Callbacks"); +static LLTrace::BlockTimerStatHandle FTM_IMAGE_FETCH("Fetch"); +static LLTrace::BlockTimerStatHandle FTM_IMAGE_CREATE("Create"); +static LLTrace::BlockTimerStatHandle FTM_IMAGE_STATS("Stats"); +static LLTrace::BlockTimerStatHandle FTM_IMAGE_MEDIA("Media"); void LLViewerTextureList::updateImages(F32 max_time) { @@ -686,45 +825,45 @@ void LLViewerTextureList::updateImages(F32 max_time) } cleared = FALSE; - S32 global_raw_memory; + S64 global_raw_memory; { - global_raw_memory = *AIAccess(LLImageRaw::sGlobalRawMemory); + global_raw_memory = *AIAccess(LLImageRaw::sGlobalRawMemory); } LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages); LLViewerStats::getInstance()->mNumRawImagesStat.addValue(LLImageRaw::sRawImageCount); - LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes)); - LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes)); + LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)LLImageGL::sGlobalTextureMemory.valueInUnits()); + LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)LLImageGL::sBoundTextureMemory.valueInUnits()); LLViewerStats::getInstance()->mRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(global_raw_memory)); LLViewerStats::getInstance()->mFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory)); { - LLFastTimer t(FTM_IMAGE_UPDATE_PRIORITIES); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_PRIORITIES); updateImagesDecodePriorities(); } F32 total_max_time = max_time; { - LLFastTimer t(FTM_IMAGE_FETCH); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_FETCH); max_time -= updateImagesFetchTextures(max_time); } { - LLFastTimer t(FTM_IMAGE_CREATE); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_CREATE); max_time = llmax(max_time, total_max_time*.50f); // at least 50% of max_time max_time -= updateImagesCreateTextures(max_time); } if (!mDirtyTextureList.empty()) { - LLFastTimer t(FTM_IMAGE_MARK_DIRTY); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_MARK_DIRTY); gPipeline.dirtyPoolObjectTextures(mDirtyTextureList); mDirtyTextureList.clear(); } { - LLFastTimer t(FTM_IMAGE_CALLBACKS); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_CALLBACKS); bool didone = false; for (image_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); ) @@ -745,7 +884,7 @@ void LLViewerTextureList::updateImages(F32 max_time) } { - LLFastTimer t(FTM_IMAGE_STATS); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_STATS); updateImagesUpdateStats(); } } @@ -771,31 +910,38 @@ void LLViewerTextureList::updateImagesDecodePriorities() { // Update the decode priority for N images each frame { + F32 lazy_flush_timeout = 30.f; // stop decoding + F32 max_inactive_time = 20.f; // actually delete + S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference + + //reset imagep->getLastReferencedTimer() when screen is showing the progress view to avoid removing pre-fetched textures too soon. + bool reset_timer = gViewerWindow->getProgressView()->getVisible(); + static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities"); // default: 32 const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds) + 1, MAX_PRIO_UPDATES); S32 update_counter = llmin(max_update_count, mUUIDMap.size()); - uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateUUID); + uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey); while ((update_counter-- > 0) && !mUUIDMap.empty()) { if (iter == mUUIDMap.end()) { iter = mUUIDMap.begin(); } - mLastUpdateUUID = iter->first; + mLastUpdateKey = iter->first; LLPointer imagep = iter->second; ++iter; // safe to incrament now // // Flush formatted images using a lazy flush // - const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding - const F32 MAX_INACTIVE_TIME = 50.f; // actually delete - S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference - S32 num_refs = imagep->getNumRefs(); if (num_refs == min_refs) { - if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > LAZY_FLUSH_TIMEOUT) + if(reset_timer) + { + imagep->getLastReferencedTimer()->reset(); + } + else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout) { // Remove the unused image from the image list deleteImage(imagep); @@ -807,7 +953,7 @@ void LLViewerTextureList::updateImagesDecodePriorities() { if(imagep->hasSavedRawImage()) { - if(imagep->getElapsedLastReferencedSavedRawImageTime() > MAX_INACTIVE_TIME) + if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time) { imagep->destroySavedRawImage() ; } @@ -824,7 +970,11 @@ void LLViewerTextureList::updateImagesDecodePriorities() } else if(imagep->isInactive()) { - if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) + if(reset_timer) + { + imagep->getLastReferencedTimer()->reset(); + } + else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time) { imagep->setDeletionCandidate() ; } @@ -895,7 +1045,7 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time) // Create GL textures for all textures that need them (images which have been // decoded, but haven't been pushed into GL). // - LLFastTimer t(FTM_IMAGE_CREATE); + LL_RECORD_BLOCK_TIME(FTM_IMAGE_CREATE); LLTimer create_timer; image_list_t::iterator enditer = mCreateTextureList.begin(); @@ -946,12 +1096,10 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) static const bool SKIP_LOW_PRIO = gSavedSettings.getBOOL("TextureFetchUpdateSkipLowPriority"); // default: false size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*MAX_HIGH_PRIO_COUNT*gFrameIntervalSeconds)+1, MAX_HIGH_PRIO_COUNT); - //Old: size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*40.f*gFrameIntervalSeconds)+1, MAX_HIGH_PRIO_COUNT); max_priority_count = llmin(max_priority_count, mImageList.size()); size_t total_update_count = mUUIDMap.size(); size_t max_update_count = llmin((S32) (MAX_UPDATE_COUNT*MAX_UPDATE_COUNT*gFrameIntervalSeconds)+1, MAX_UPDATE_COUNT); - //Old: size_t max_priority_count = llmin((S32) (MAX_UPDATE_COUNT*40.f*gFrameIntervalSeconds)+1, MAX_UPDATE_COUNT); max_update_count = llmin(max_update_count, total_update_count); // MAX_HIGH_PRIO_COUNT high priority entries @@ -971,7 +1119,7 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) update_counter = max_update_count; if(update_counter > 0) { - uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID); + uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchKey); while ((update_counter > 0) && (total_update_count > 0)) { if (iter2 == mUUIDMap.end()) @@ -1001,7 +1149,7 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) fetch_count += (imagep->updateFetch() ? 1 : 0); if (min_count <= (S32)min_update_count) { - mLastFetchUUID = imagep->getID(); + mLastFetchKey = LLTextureKey(imagep->getID(), (ETexListType)imagep->getTextureListType()); } if ((min_count-- <= 0) && (image_op_timer.getElapsedTimeF32() > max_time)) { @@ -1204,20 +1352,17 @@ LLPointer LLViewerTextureList::convertToUploadFile(LLPointer 2000) - return 128; - else if (system_ram > 1000) - return 64; - else - return MIN_VIDEO_RAM_IN_MEGA_BYTES; + S32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); + //LL_INFOS() << system_ram << LL_ENDL; + //min texture mem sets to 64M if total physical mem is more than 1.5GB + return (system_ram > S32Megabytes(1500)) ? S32Megabytes(64) : gMinVideoRam ; } //static // Returns max setting for TextureMemory (in MB) -S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended) +S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_multiplier) { #if LL_LINUX if (gGLManager.mIsIntel && gGLManager.mGLVersion >= 3.f && !gGLManager.mVRAM) @@ -1225,12 +1370,12 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended) gGLManager.mVRAM = 512; } #endif - S32 max_texmem; + S32Megabytes max_texmem; if (gGLManager.mVRAM != 0) { // Treat any card with < 32 MB (shudder) as having 32 MB // - it's going to be swapping constantly regardless - S32 max_vram = gGLManager.mVRAM; + S32Megabytes max_vram(gGLManager.mVRAM); max_vram = llmax(max_vram, getMinVideoRamSetting()); max_texmem = max_vram; if (!get_recommended) @@ -1238,80 +1383,75 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended) } else { - if (get_recommended) - max_texmem = 128; + if (!get_recommended) + { + max_texmem = S32Megabytes(512); + } + else if (gSavedSettings.getBOOL("NoHardwareProbe")) //did not do hardware detection at startup + { + max_texmem = S32Megabytes(512); + } else - max_texmem = 512; + { + max_texmem = S32Megabytes(128); + } + LL_WARNS() << "VRAM amount not detected, defaulting to " << max_texmem << " MB" << LL_ENDL; } - S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); // In MB - //LL_INFOS() << "*** DETECTED " << system_ram << " MB of system memory." << LL_ENDL; + S32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); // In MB + LL_INFOS() << "get_recommended: " << get_recommended << LL_ENDL; + LL_INFOS() << "system_ram: " << system_ram << LL_ENDL; + LL_INFOS() << "max_texmem: " << max_texmem << LL_ENDL; if (get_recommended) - max_texmem = llmin(max_texmem, (S32)(system_ram/2)); + max_texmem = llmin(S32Megabytes(max_texmem * .7f), system_ram/2); else - max_texmem = llmin(max_texmem, (S32)(system_ram)); - - max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM_IN_MEGA_BYTES); + max_texmem = llmin(max_texmem, system_ram); + + // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise + max_texmem = llmin(max_texmem, (S32Megabytes) (mem_multiplier * max_texmem)); + + max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), gMaxVideoRam); return max_texmem; } -const S32 VIDEO_CARD_FRAMEBUFFER_MEM = 12; // MB -const S32 MIN_MEM_FOR_NON_TEXTURE = 512 ; //MB -void LLViewerTextureList::updateMaxResidentTexMem(S32 mem) +const S32Megabytes VIDEO_CARD_FRAMEBUFFER_MEM_MIN(12); +const S32Megabytes VIDEO_CARD_FRAMEBUFFER_MEM_MAX(512); +const S32Megabytes MIN_MEM_FOR_NON_TEXTURE(16); +void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem) { // Initialize the image pipeline VRAM settings - S32 cur_mem = gSavedSettings.getS32("TextureMemory"); - F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); - S32 default_mem = getMaxVideoRamSetting(true); // recommended default + const S32Megabytes cur_mem(gSavedSettings.getS32("TextureMemory")); + const F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); + const S32Megabytes default_mem = getMaxVideoRamSetting(true, mem_multiplier); // recommended default + const S32Megabytes max_mem = getMaxVideoRamSetting(false, mem_multiplier); + const S32Megabytes min_mem = getMinVideoRamSetting(); + if (mem == 0) { - mem = cur_mem > 0 ? cur_mem : default_mem; + mem = cur_mem > (S32Bytes)0 ? cur_mem : default_mem; } else if (mem < 0) { mem = default_mem; } - // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise - mem = llmin(mem, (S32) (mem_multiplier * (F32) default_mem)); - - mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting()); - if (mem != cur_mem) + S32Megabytes reported_mem = llclamp(mem, min_mem, max_mem); + if (reported_mem != cur_mem) { - gSavedSettings.setS32("TextureMemory", mem); + gSavedSettings.setS32("TextureMemory", reported_mem.value()); return; //listener will re-enter this function } - // TODO: set available resident texture mem based on use by other subsystems - // currently max(12MB, VRAM/4) assumed... - - S32 vb_mem = mem; - S32 fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vb_mem/4); - mMaxResidentTexMemInMegaBytes = (vb_mem - fb_mem) ; //in MB - - mMaxTotalTextureMemInMegaBytes = mMaxResidentTexMemInMegaBytes * 2; - if (mMaxResidentTexMemInMegaBytes > 640) - { - mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes >> 2); - } - - //system mem - S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); // In MB + S32Megabytes fb_mem = llmin(llmax(VIDEO_CARD_FRAMEBUFFER_MEM_MIN, mem / 4), VIDEO_CARD_FRAMEBUFFER_MEM_MAX); // 25% for framebuffers. + S32Megabytes misc_mem = llmax(MIN_MEM_FOR_NON_TEXTURE, mem / 5); // 20% for misc. - //minimum memory reserved for non-texture use. - //if system_raw >= 1GB, reserve at least 512MB for non-texture use; - //otherwise reserve half of the system_ram for non-texture use. - S32 min_non_texture_mem = llmin(system_ram / 2, MIN_MEM_FOR_NON_TEXTURE) ; + mMaxTotalTextureMemInMegaBytes = llmin(mem - misc_mem, max_mem); + mMaxResidentTexMemInMegaBytes = llmin(mem - misc_mem - fb_mem, max_mem); - if (mMaxTotalTextureMemInMegaBytes > system_ram - min_non_texture_mem) - { - mMaxTotalTextureMemInMegaBytes = system_ram - min_non_texture_mem ; - } - - LL_INFOS() << "Total Video Memory set to: " << vb_mem << " MB" << LL_ENDL; - LL_INFOS() << "Available Texture Memory set to: " << (vb_mem - fb_mem) << " MB" << LL_ENDL; + LL_INFOS() << "Available Texture Memory set to: " << mMaxResidentTexMemInMegaBytes << LL_ENDL; + LL_INFOS() << "Total Texture Memory set to: " << mMaxTotalTextureMemInMegaBytes << LL_ENDL; } /////////////////////////////////////////////////////////////////////////////// @@ -1321,7 +1461,7 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d { static LLCachedControl log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; - LLFastTimer t(FTM_PROCESS_IMAGES); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_IMAGES); // Receive image header, copy into image object and decompresses // if this is a one-packet image. @@ -1331,17 +1471,17 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d char ip_string[256]; u32_to_ip_string(msg->getSenderIP(),ip_string); - U32 received_size ; + U32Bytes received_size ; if (msg->getReceiveCompressedSize()) { - received_size = msg->getReceiveCompressedSize() ; + received_size = (U32Bytes)msg->getReceiveCompressedSize() ; } else { - received_size = msg->getReceiveSize() ; + received_size = (U32Bytes)msg->getReceiveSize() ; } // Only used for statistics and texture console. - gTextureList.sTextureBits += received_size * 8; + gTextureList.sTextureBits += received_size; gTextureList.sTexturePackets++; U8 codec; @@ -1370,7 +1510,7 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d U8 *data = new U8[data_size]; msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (!image) { delete [] data; @@ -1394,7 +1534,7 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d { static LLCachedControl log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; - LLFastTimer t(FTM_PROCESS_IMAGES); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_IMAGES); // Receives image packet, copy into image object, // checks if all packets received, decompresses if so. @@ -1405,16 +1545,16 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d char ip_string[256]; u32_to_ip_string(msg->getSenderIP(),ip_string); - U32 received_size ; + U32Bytes received_size ; if (msg->getReceiveCompressedSize()) { - received_size = msg->getReceiveCompressedSize() ; + received_size = (U32Bytes)msg->getReceiveCompressedSize() ; } else { - received_size = msg->getReceiveSize() ; + received_size = (U32Bytes)msg->getReceiveSize() ; } - gTextureList.sTextureBits += received_size * 8; + gTextureList.sTextureBits += received_size; gTextureList.sTexturePackets++; //llprintline("Start decode, image header..."); @@ -1442,7 +1582,7 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d U8 *data = new U8[data_size]; msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (!image) { delete [] data; @@ -1466,36 +1606,26 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d // static void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem *msg,void **user_data) { - LLFastTimer t(FTM_PROCESS_IMAGES); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_IMAGES); LLUUID image_id; msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, image_id); - LLViewerFetchedTexture* image = gTextureList.findImage( image_id ); + LLViewerFetchedTexture* image = gTextureList.findImage( image_id, TEX_LIST_STANDARD); if( image ) { - LL_WARNS() << "not in db" << LL_ENDL; + LL_WARNS() << "Image not in db" << LL_ENDL; image->setIsMissingAsset(); } -} - -/////////////////////////////////////////////////////////////////////////////// -//static -const U32 SIXTEEN_MEG = 0x1000000; -S32 LLViewerTextureList::calcMaxTextureRAM() -{ - // Decide the maximum amount of RAM we should allow the user to allocate to texture cache - LLMemoryInfo memory_info; - U32 available_memory = memory_info.getPhysicalMemoryClamped(); - - clamp_rescale((F32)available_memory, - (F32)(SIXTEEN_MEG * 16), - (F32)U32_MAX, - (F32)(SIXTEEN_MEG * 4), - (F32)(U32_MAX >> 1)); - return available_memory; + image = gTextureList.findImage(image_id, TEX_LIST_SCALE); + if (image) + { + LL_WARNS() << "Icon not in db" << LL_ENDL; + image->setIsMissingAsset(); + } } + /////////////////////////////////////////////////////////////////////////////// // explicitly cleanup resources, as this is a singleton class with process @@ -1541,28 +1671,31 @@ LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name, S32 priori } LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename, - BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority ) + BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority, + LLUIImage::EScaleStyle scale_style) { if (boost_priority == LLGLTexture::BOOST_NONE) { boost_priority = LLGLTexture::BOOST_UI; } - LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO, boost_priority); - return loadUIImage(imagep, name, use_mips, scale_rect, clip_rect); + LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, FTT_LOCAL_FILE, MIPMAP_NO, boost_priority); + return loadUIImage(imagep, name, use_mips, scale_rect, clip_rect, scale_style); } LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id, - BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority) + BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority, + LLUIImage::EScaleStyle scale_style) { if (boost_priority == LLGLTexture::BOOST_NONE) { boost_priority = LLGLTexture::BOOST_UI; } - LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, boost_priority); - return loadUIImage(imagep, id.asString(), use_mips, scale_rect, clip_rect); + LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, MIPMAP_NO, boost_priority); + return loadUIImage(imagep, id.asString(), use_mips, scale_rect, clip_rect, scale_style); } -LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect) +LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, + LLUIImage::EScaleStyle scale_style) { if (!imagep) return NULL; @@ -1571,12 +1704,18 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st //don't compress UI images imagep->getGLTexture()->setAllowCompression(false); - //all UI images are non-deletable - imagep->setNoDelete(); - LLUIImagePtr new_imagep = new LLUIImage(name, imagep); - mUIImages.insert(std::make_pair(name, new_imagep)); - mUITextureList.push_back(imagep); + new_imagep->setScaleStyle(scale_style); + + if (imagep->getBoostLevel() != LLGLTexture::BOOST_ICON && + imagep->getBoostLevel() != LLGLTexture::BOOST_PREVIEW) + { + // Don't add downloadable content into this list + // all UI images are non-deletable and list does not support deletion + imagep->setNoDelete(); + mUIImages.insert(std::make_pair(name, new_imagep)); + mUITextureList.push_back(imagep); + } //Note: //Some other textures such as ICON also through this flow to be fetched. @@ -1593,7 +1732,7 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st return new_imagep; } -LLUIImagePtr LLUIImageList::preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect) +LLUIImagePtr LLUIImageList::preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLUIImage::EScaleStyle scale_style) { // look for existing image uuid_ui_image_map_t::iterator found_it = mUIImages.find(name); @@ -1603,7 +1742,7 @@ LLUIImagePtr LLUIImageList::preloadUIImage(const std::string& name, const std::s LL_ERRS() << "UI Image " << name << " already loaded." << LL_ENDL; } - return loadUIImageByName(name, filename, use_mips, scale_rect, clip_rect); + return loadUIImageByName(name, filename, use_mips, scale_rect, clip_rect, LLGLTexture::BOOST_UI, scale_style); } //static @@ -1663,20 +1802,37 @@ void LLUIImageList::onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_v } } -/*struct UIImageDeclaration : public LLInitParam::Block +namespace LLInitParam { - Mandatory name; - Optional file_name; - Optional preload; - Optional scale; - Optional use_mips; + template<> + struct TypeValues : public TypeValuesHelper + { + static void declareValues() + { + declare("scale_inner", LLUIImage::SCALE_INNER); + declare("scale_outer", LLUIImage::SCALE_OUTER); + } + }; +} + +struct UIImageDeclaration : public LLInitParam::Block +{ + Mandatory name; + Optional file_name; + Optional preload; + Optional scale; + Optional clip; + Optional use_mips; + Optional scale_type; UIImageDeclaration() : name("name"), file_name("file_name"), preload("preload", false), scale("scale"), - use_mips("use_mips", false) + clip("clip"), + use_mips("use_mips", false), + scale_type("scale_type", LLUIImage::SCALE_INNER) {} }; @@ -1693,49 +1849,43 @@ struct UIImageDeclarations : public LLInitParam::Block bool LLUIImageList::initFromFile() { - // construct path to canonical textures.xml in default skin dir - std::string base_file_path = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "default", "textures", "textures.xml"); + // Look for textures.xml in all the right places. Pass + // constraint=LLDir::ALL_SKINS because we want to overlay textures.xml + // from all the skins directories. + std::vector textures_paths = + gDirUtilp->findSkinnedFilenames(LLDir::TEXTURES, "textures.xml", LLDir::ALL_SKINS); + std::vector::const_iterator pi(textures_paths.begin()), pend(textures_paths.end()); + if (pi == pend) + { + LL_WARNS() << "No textures.xml found in skins directories" << LL_ENDL; + return false; + } + // The first (most generic) file gets special validations LLXMLNodePtr root; - - if (!LLXMLNode::parseFile(base_file_path, root, NULL)) + if (!LLXMLNode::parseFile(*pi, root, NULL)) { - LL_WARNS() << "Unable to parse UI image list file " << base_file_path << LL_ENDL; + LL_WARNS() << "Unable to parse UI image list file " << *pi << LL_ENDL; return false; } if (!root->hasAttribute("version")) { - LL_WARNS() << "No valid version number in UI image list file " << base_file_path << LL_ENDL; + LL_WARNS() << "No valid version number in UI image list file " << *pi << LL_ENDL; return false; } UIImageDeclarations images; LLXUIParser parser; - parser.readXUI(root, images, base_file_path); + parser.readXUI(root, images, *pi); - // add components defined in current skin - std::string skin_update_path = gDirUtilp->getSkinDir() - + gDirUtilp->getDirDelimiter() - + "textures" - + gDirUtilp->getDirDelimiter() - + "textures.xml"; - LLXMLNodePtr update_root; - if (skin_update_path != base_file_path - && LLXMLNode::parseFile(skin_update_path, update_root, NULL)) + // add components defined in the rest of the skin paths + while (++pi != pend) { - parser.readXUI(update_root, images, skin_update_path); - } - - // add components defined in user override of current skin - skin_update_path = gDirUtilp->getUserSkinDir() - + gDirUtilp->getDirDelimiter() - + "textures" - + gDirUtilp->getDirDelimiter() - + "textures.xml"; - if (skin_update_path != base_file_path - && LLXMLNode::parseFile(skin_update_path, update_root, NULL)) - { - parser.readXUI(update_root, images, skin_update_path); + LLXMLNodePtr update_root; + if (LLXMLNode::parseFile(*pi, update_root, NULL)) + { + parser.readXUI(update_root, images, *pi); + } } if (!images.validateBlock()) return false; @@ -1770,7 +1920,7 @@ bool LLUIImageList::initFromFile() { continue; } - preloadUIImage(image.name, file_name, image.use_mips, image.scale); + preloadUIImage(image.name, file_name, image.use_mips, image.scale, image.clip, image.scale_type); } if (cur_pass == PASS_DECODE_NOW && !gSavedSettings.getBOOL("NoPreload")) @@ -1779,115 +1929,6 @@ bool LLUIImageList::initFromFile() } } return true; -}*/ -bool LLUIImageList::initFromFile() -{ - // construct path to canonical textures.xml in default skin dir - std::string base_file_path = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "default", "textures", "textures.xml"); - - LLXMLNodePtr root; - - if (!LLXMLNode::parseFile(base_file_path, root, NULL)) - { - LL_WARNS() << "Unable to parse UI image list file " << base_file_path << LL_ENDL; - return false; - } - - if (!root->hasAttribute("version")) - { - LL_WARNS() << "No valid version number in UI image list file " << base_file_path << LL_ENDL; - return false; - } - - std::vector paths; - // path to current selected skin - paths.push_back(gDirUtilp->getSkinDir() - + gDirUtilp->getDirDelimiter() - + "textures" - + gDirUtilp->getDirDelimiter() - + "textures.xml"); - // path to user overrides on current skin - paths.push_back(gDirUtilp->getUserSkinDir() - + gDirUtilp->getDirDelimiter() - + "textures" - + gDirUtilp->getDirDelimiter() - + "textures.xml"); - - // apply skinned xml files incrementally - for(std::vector::iterator path_it = paths.begin(); - path_it != paths.end(); - ++path_it) - { - // don't reapply base file to itself - if (!path_it->empty() && (*path_it) != base_file_path) - { - LLXMLNodePtr update_root; - if (LLXMLNode::parseFile(*path_it, update_root, NULL)) - { - LLXMLNode::updateNode(root, update_root); - } - } - } - - enum - { - PASS_DECODE_NOW, - PASS_DECODE_LATER, - NUM_PASSES - }; - - for (S32 pass = PASS_DECODE_NOW; pass < NUM_PASSES; pass++) - { - LLXMLNodePtr child_nodep = root->getFirstChild(); - while(child_nodep.notNull()) - { - std::string image_name; - child_nodep->getAttributeString("name", image_name); - - std::string file_name = image_name; - LLRect scale_rect; - BOOL use_mip_maps = FALSE; - - BOOL preload = FALSE; - child_nodep->getAttributeBOOL("preload", preload); - - // load high priority textures on first pass (to kick off decode) - if (preload) - { - if (pass == PASS_DECODE_LATER) - { - child_nodep = child_nodep->getNextSibling(); - continue; - } - } - else - { - if (pass == PASS_DECODE_NOW) - { - child_nodep = child_nodep->getNextSibling(); - continue; - } - } - - child_nodep->getAttributeString("file_name", file_name); - child_nodep->getAttributeBOOL("use_mips", use_mip_maps); - - child_nodep->getAttributeS32("scale_left", scale_rect.mLeft); - child_nodep->getAttributeS32("scale_right", scale_rect.mRight); - child_nodep->getAttributeS32("scale_bottom", scale_rect.mBottom); - child_nodep->getAttributeS32("scale_top", scale_rect.mTop); - - preloadUIImage(image_name, file_name, use_mip_maps, scale_rect, LLRectBase::null); - - child_nodep = child_nodep->getNextSibling(); - } - - if (pass == PASS_DECODE_NOW && !gSavedSettings.getBOOL("NoPreload")) - { - gTextureList.decodeAllImages(10.f); // decode preloaded images - } - } - return true; } diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 57d6bc91de..fd2e4a8668 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -35,6 +35,9 @@ #include "llui.h" #include #include +#include + +#include "absl/container/flat_hash_map.h" const U32 LL_IMAGE_REZ_LOSSLESS_CUTOFF = 128; @@ -59,19 +62,54 @@ typedef void (*LLImageCallback)(BOOL success, BOOL final, void* userdata); +enum ETexListType +{ + TEX_LIST_STANDARD = 0, + TEX_LIST_SCALE +}; + +struct LLTextureKey +{ + LLTextureKey(); + LLTextureKey(LLUUID id, ETexListType tex_type); + LLUUID textureId; + ETexListType textureType; + + friend bool operator == (const LLTextureKey& lhs, const LLTextureKey& rhs) { + return lhs.textureId == rhs.textureId && lhs.textureType == rhs.textureType; + } + + friend bool operator<(const LLTextureKey& key1, const LLTextureKey& key2) + { + if (key1.textureId != key2.textureId) + { + return key1.textureId < key2.textureId; + } + else + { + return key1.textureType < key2.textureType; + } + } + template + friend H AbslHashValue(H h, const LLTextureKey& key) { + return H::combine(std::move(h), key.textureId, key.textureType); + } +}; + class LLViewerTextureList { LOG_CLASS(LLViewerTextureList); friend class LLTextureView; friend class LLViewerTextureManager; + friend class LocalBitmap; + friend class LocalAssetBrowser; public: static BOOL createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec); static BOOL verifyUploadFile(const std::string& out_filename, const U8 codec); static LLPointer convertToUploadFile(LLPointer raw_image); static void processImageNotInDatabase( LLMessageSystem *msg, void **user_data ); - static S32 calcMaxTextureRAM(); static void receiveImageHeader(LLMessageSystem *msg, void **user_data); static void receiveImagePacket(LLMessageSystem *msg, void **user_data); @@ -86,7 +124,9 @@ class LLViewerTextureList void restoreGL(); BOOL isInitialized() const {return mInitialized;} - LLViewerFetchedTexture *findImage(const LLUUID &image_id); + void findTexturesByID(const LLUUID &image_id, std::vector &output); + LLViewerFetchedTexture *findImage(const LLUUID &image_id, ETexListType tex_type); + LLViewerFetchedTexture *findImage(const LLTextureKey &search_key); void dirtyImage(LLViewerFetchedTexture *image); @@ -101,19 +141,19 @@ class LLViewerTextureList void setUpdateStats(BOOL b) { mUpdateStats = b; } - S32 getMaxResidentTexMem() const { return mMaxResidentTexMemInMegaBytes; } - S32 getMaxTotalTextureMem() const { return mMaxTotalTextureMemInMegaBytes;} + S32Megabytes getMaxResidentTexMem() const { return mMaxResidentTexMemInMegaBytes; } + S32Megabytes getMaxTotalTextureMem() const { return mMaxTotalTextureMemInMegaBytes;} S32 getNumImages() { return mImageList.size(); } - void updateMaxResidentTexMem(S32 mem); + void updateMaxResidentTexMem(S32Megabytes mem); void doPreloadImages(); void doPrefetchImages(); void clearFetchingRequests(); - static S32 getMinVideoRamSetting(); - static S32 getMaxVideoRamSetting(bool get_recommended = false); + static S32Megabytes getMinVideoRamSetting(); + static S32Megabytes getMaxVideoRamSetting(bool get_recommended, float mem_multiplier); private: void updateImagesDecodePriorities(); @@ -121,15 +161,14 @@ class LLViewerTextureList F32 updateImagesFetchTextures(F32 max_time); void updateImagesUpdateStats(); -public: - void addImage(LLViewerFetchedTexture *image); + void addImage(LLViewerFetchedTexture *image, ETexListType tex_type); void deleteImage(LLViewerFetchedTexture *image); -private: void addImageToList(LLViewerFetchedTexture *image); void removeImageFromList(LLViewerFetchedTexture *image); LLViewerFetchedTexture * getImage(const LLUUID &image_id, + FTType f_type = FTT_DEFAULT, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -139,6 +178,7 @@ class LLViewerTextureList ); LLViewerFetchedTexture * getImageFromFile(const std::string& filename, + FTType f_type = FTT_LOCAL_FILE, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -148,6 +188,7 @@ class LLViewerTextureList ); LLViewerFetchedTexture* getImageFromUrl(const std::string& url, + FTType f_type, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -157,6 +198,7 @@ class LLViewerTextureList ); LLViewerFetchedTexture* createImage(const LLUUID &image_id, + FTType f_type, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -167,8 +209,8 @@ class LLViewerTextureList // Request image from a specific host, used for baked avatar textures. // Implemented in header in case someone changes default params above. JC - LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, LLHost host) - { return getImage(image_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } + LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, FTType f_type, LLHost host) + { return getImage(image_id, f_type, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } public: typedef std::set > image_list_t; @@ -182,10 +224,12 @@ class LLViewerTextureList BOOL mForceResetTextureStats; private: - typedef std::map< LLUUID, LLPointer > uuid_map_t; + typedef std::map< LLTextureKey, LLPointer > uuid_map_t; uuid_map_t mUUIDMap; - LLUUID mLastUpdateUUID; - LLUUID mLastFetchUUID; + typedef absl::flat_hash_map< LLTextureKey, LLViewerFetchedTexture* > uuid_dict_t; + uuid_dict_t mUUIDDict; + LLTextureKey mLastUpdateKey; + LLTextureKey mLastFetchKey; typedef std::set, LLViewerFetchedTexture::Compare> image_priority_list_t; image_priority_list_t mImageList; @@ -195,12 +239,12 @@ class LLViewerTextureList BOOL mInitialized ; BOOL mUpdateStats; - S32 mMaxResidentTexMemInMegaBytes; - S32 mMaxTotalTextureMemInMegaBytes; + S32Megabytes mMaxResidentTexMemInMegaBytes; + S32Megabytes mMaxTotalTextureMemInMegaBytes; LLFrameTimer mForceDecodeTimer; public: - static U32 sTextureBits; + static U32Bits sTextureBits; static U32 sTexturePackets; private: @@ -218,20 +262,22 @@ class LLUIImageList : public LLImageProviderInterface, public LLSingleton preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect); + LLPointer preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLUIImage::EScaleStyle stype); static void onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); private: LLPointer loadUIImageByName(const std::string& name, const std::string& filename, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null, - LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI); + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI, + LLUIImage::EScaleStyle = LLUIImage::SCALE_INNER); LLPointer loadUIImageByID(const LLUUID& id, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null, - LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI); + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI, + LLUIImage::EScaleStyle = LLUIImage::SCALE_INNER); - LLPointer loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null); + LLPointer loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null, LLUIImage::EScaleStyle = LLUIImage::SCALE_INNER); struct LLUIImageLoadData diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 1f8add5c2c..1297ca9de4 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -130,14 +130,14 @@ LLWearable::EImportResult LLViewerWearable::importStream( std::istream& input_st LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( textureid ); if(gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) { - image->setLoadedCallback(LLVOAvatarSelf::debugOnTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(textureid, (LLAvatarAppearanceDefines::ETextureIndex)te), NULL); + image->setLoadedCallback(LLVOAvatarSelf::debugOnTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(textureid, (LLAvatarAppearanceDefines::ETextureIndex)te), nullptr); } } return result; } -AIArchetype LLViewerWearable::getArchetype(void) const +AIArchetype LLViewerWearable::getArchetype() const { AIArchetype archetype(this); for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) @@ -235,7 +235,6 @@ BOOL LLViewerWearable::isDirty() const U8 a = F32_to_U8( saved_weight, param->getMinWeight(), param->getMaxWeight() ); U8 b = F32_to_U8( current_weight, param->getMinWeight(), param->getMaxWeight() ); - if( a != b ) { //LL_WARNS() << "param ID " << param->getID() << " was changed." << LL_ENDL; @@ -317,8 +316,8 @@ void LLViewerWearable::setTexturesToDefaults() const LLUUID LLViewerWearable::getDefaultTextureImageID(ETextureIndex index) const { const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); - const std::string &default_image_name = texture_dict->mDefaultImageName; - if (default_image_name == "") + const std::string &default_image_name = texture_dict ? texture_dict->mDefaultImageName : ""; + if (default_image_name.empty()) { return IMG_DEFAULT_AVATAR; } @@ -333,22 +332,13 @@ const LLUUID LLViewerWearable::getDefaultTextureImageID(ETextureIndex index) con //virtual void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp) { - LLVOAvatarSelf* viewer_avatar = dynamic_cast(avatarp); + if (!avatarp || !avatarp->isSelf() || !avatarp->isValid()) return; + LLVOAvatarSelf* viewer_avatar = static_cast(avatarp); if (!avatarp || !viewer_avatar) return; if (!viewer_avatar->isValid()) return; -#if 0 - // FIXME DRANO - kludgy way to avoid overwriting avatar state from wearables. - // Ideally would avoid calling this func in the first place. - if (viewer_avatar->isUsingServerBakes() && - !viewer_avatar->isUsingLocalAppearance()) - { - return; - } -#endif - ESex old_sex = avatarp->getSex(); LLWearable::writeToAvatar(avatarp); @@ -369,7 +359,7 @@ void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp) { image_id = getDefaultTextureImageID((ETextureIndex) te); } - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); // MULTI-WEARABLE: assume index 0 will be used when writing to avatar. TODO: eliminate the need for this. viewer_avatar->setLocalTextureTE(te, image, 0); } @@ -459,7 +449,7 @@ void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) { te_map_t::const_iterator iter = src->mTEMap.find(te); LLUUID image_id; - LLViewerFetchedTexture *image = NULL; + LLViewerFetchedTexture *image = nullptr; if(iter != src->mTEMap.end()) { image = dynamic_cast (src->getLocalTextureObject(te)->getImage()); @@ -492,13 +482,6 @@ void LLViewerWearable::setItemID(const LLUUID& item_id) void LLViewerWearable::revertValues() { -#if 0 - // DRANO avoid overwrite when not in local appearance - if (isAgentAvatarValid() && gAgentAvatarp->isUsingServerBakes() && !gAgentAvatarp->isUsingLocalAppearance()) - { - return; - } -#endif LLWearable::revertValues(); @@ -600,18 +583,7 @@ void LLViewerWearable::saveNewAsset() const //LL_INFOS() << *this << LL_ENDL; const std::string filename = asset_id_to_filename(mAssetID); - LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */ - BOOL successful_save = FALSE; - if(fp && exportFile(fp)) - { - successful_save = TRUE; - } - if(fp) - { - fclose(fp); - fp = NULL; - } - if(!successful_save) + if(! exportFile(filename)) { std::string buffer = llformat("Unable to save '%s' to wearable file.", mName.c_str()); LL_WARNS() << buffer << LL_ENDL; @@ -625,28 +597,29 @@ void LLViewerWearable::saveNewAsset() const // save it out to database if( gAssetStorage ) { - /* - std::string url = gAgent.getRegion()->getCapability("NewAgentInventory"); +#if 0 + const std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); if (!url.empty()) { LL_INFOS() << "Update Agent Inventory via capability" << LL_ENDL; LLSD body; - body["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetToFolderType(getAssetType())); + body["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(getAssetType())); body["asset_type"] = LLAssetType::lookup(getAssetType()); body["inventory_type"] = LLInventoryType::lookup(LLInventoryType::IT_WEARABLE); body["name"] = getName(); body["description"] = getDescription(); - LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, filename)); + LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, filename, + getAssetType())); } else +#endif // 0 { - } - */ - LLWearableSaveData* data = new LLWearableSaveData; - data->mType = mType; - gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(), + LLWearableSaveData* data = new LLWearableSaveData; + data->mType = mType; + gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(), &LLViewerWearable::onSaveNewAssetComplete, (void*)data); + } } } @@ -687,21 +660,19 @@ std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w) //w.mSaleInfo s << " Params:" << "\n"; - for (LLViewerWearable::visual_param_index_map_t::const_iterator iter = w.mVisualParamIndexMap.begin(); - iter != w.mVisualParamIndexMap.end(); ++iter) + for (const auto& iter : w.mVisualParamIndexMap) { - S32 param_id = iter->first; - LLVisualParam *wearable_param = iter->second; + S32 param_id = iter.first; + LLVisualParam *wearable_param = iter.second; F32 param_weight = wearable_param->getWeight(); s << " " << param_id << " " << param_weight << "\n"; } s << " Textures:" << "\n"; - for (LLViewerWearable::te_map_t::const_iterator iter = w.mTEMap.begin(); - iter != w.mTEMap.end(); ++iter) + for (const auto& iter : w.mTEMap) { - S32 te = iter->first; - const LLUUID& image_id = iter->second->getID(); + S32 te = iter.first; + const LLUUID& image_id = iter.second->getID(); s << " " << te << " " << image_id << "\n"; } return s; diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index 3f5d8ec176..94f70fefae 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -29,7 +29,6 @@ #include "llwearable.h" #include "llavatarappearancedefines.h" -#include "aixmllindengenepool.h" class LLVOAvatar; class LLAPRFile; @@ -69,7 +68,7 @@ class LLViewerWearable : public LLWearable /*virtual*/ EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ); // Singu extension. - AIArchetype getArchetype(void) const; + class AIArchetype getArchetype() const; void setParamsToDefaults(); void setTexturesToDefaults(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 4a896285ff..b3ca313cf3 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -180,6 +180,7 @@ #include "llviewernetwork.h" #include "llpostprocess.h" #include "llwearablelist.h" +#include "llfloaterinspect.h" #include "llnotifications.h" #include "llnotificationsutil.h" @@ -187,6 +188,7 @@ #include "llfloaternotificationsconsole.h" #include "llpanelnearbymedia.h" +#include "llmessagetemplate.h" // [RLVa:KB] #include "rlvhandler.h" @@ -219,7 +221,9 @@ BOOL gShowOverlayTitle = FALSE; BOOL gPickTransparent = TRUE; LLViewerObject* gDebugRaycastObject = NULL; +LLVOPartGroup* gDebugRaycastParticle = NULL; LLVector4a gDebugRaycastIntersection; +LLVector4a gDebugRaycastParticleIntersection; LLVector2 gDebugRaycastTexCoord; LLVector4a gDebugRaycastNormal; LLVector4a gDebugRaycastTangent; @@ -243,7 +247,7 @@ const F32 MIN_AFK_TIME = 2.f; // minimum time after setting away state before co const F32 MAX_FAST_FRAME_TIME = 0.5f; const F32 FAST_FRAME_INCREMENT = 0.1f; -const F32 MIN_DISPLAY_SCALE = 0.75f; +const F32 MIN_DISPLAY_SCALE = 0.5f; std::string LLViewerWindow::sSnapshotBaseName; std::string LLViewerWindow::sSnapshotDir; @@ -351,7 +355,7 @@ class LLDebugText if(obj) { S32 te = nodep ? nodep->getLastSelectedTE() : -1; - if(te > 0) + if(te >= 0) { LLViewerTexture* imagep = obj->getTEImage(te); if(imagep && imagep != (LLViewerTexture*)LLViewerFetchedTexture::sDefaultImagep.get()) @@ -368,7 +372,8 @@ class LLDebugText }*/ static const LLCachedControl use_rmse_auto_mask("SHUseRMSEAutoMask",false); static const LLCachedControl auto_mask_max_rmse("SHAutoMaskMaxRMSE",.09f); - addText(xpos, ypos, llformat("Mask: %s", imagep->getIsAlphaMask(use_rmse_auto_mask ? auto_mask_max_rmse : -1.f) ? "TRUE":"FALSE")); ypos += y_inc; + static const LLCachedControl auto_mask_max_mid("SHAutoMaskMaxMid", .25f); + addText(xpos, ypos, llformat("Mask: %s", imagep->getIsAlphaMask(use_rmse_auto_mask ? auto_mask_max_rmse : -1.f, auto_mask_max_mid) ? "TRUE":"FALSE")); ypos += y_inc; addText(xpos, ypos, llformat("ID: %s", imagep->getID().asString().c_str())); ypos += y_inc; } } @@ -380,7 +385,7 @@ class LLDebugText static const LLCachedControl debug_show_memory("DebugShowMemory"); if (debug_show_memory) { - addText(xpos, ypos, llformat("Memory: %d (KB)", LLMemory::getWorkingSetSize() / 1024)); + addText(xpos, ypos, llformat("Memory: %d (KB)", LLMemory::getCurrentRSS() / 1024)); ypos += y_inc; } #endif @@ -503,7 +508,7 @@ class LLDebugText //show streaming cost/triangle count of known prims in current region OR selection //Note: This is SUPER slow - { + /*{ F32 cost = 0.f; S32 count = 0; S32 vcount = 0; @@ -552,7 +557,7 @@ class LLDebugText count/1000.f, vcount/1000.f, visible_bytes/1024.f, total_bytes/1024.f, object_count)); ypos += y_inc; - } + }*/ addText(xpos, ypos, llformat("%d MB Index Data (%d MB Pooled, %d KIndices)", LLVertexBuffer::sAllocatedIndexBytes/(1024*1024), LLVBOPool::sIndexBytesPooled/(1024*1024), LLVertexBuffer::sIndexCount/1024)); ypos += y_inc; @@ -651,7 +656,7 @@ class LLDebugText } } } - for(std::set::iterator it = gObjectList.mDeadObjects.begin();it!=gObjectList.mDeadObjects.end();++it) + for(auto it = gObjectList.mDeadObjects.begin();it!=gObjectList.mDeadObjects.end();++it) { LLViewerObject *obj = gObjectList.findObject(*it); if(obj && obj->isAvatar()) @@ -681,7 +686,7 @@ class LLDebugText LLMeshRepository::sHTTPRetryCount)); ypos += y_inc; - addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing)); + addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, (U32)LLMeshRepository::sLODProcessing)); ypos += y_inc; addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f))); @@ -689,10 +694,16 @@ class LLDebugText ypos += y_inc; } + addText(xpos, ypos, llformat("%d/%d bytes allocted to messages", sMsgDataAllocSize, sMsgdataAllocCount)); + LLVertexBuffer::sBindCount = LLImageGL::sBindCount = LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; } + + sMsgDataAllocSize = 0; + sMsgdataAllocCount = 0; + static const LLCachedControl debug_show_render_matrices("DebugShowRenderMatrices"); if (debug_show_render_matrices) { @@ -1095,7 +1106,9 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi if (prim_media_dnd_enabled) { - LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY, TRUE /*BOOL pick_transparent*/ ); + LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY, + TRUE /* pick_transparent */, + FALSE /* pick_rigged */); LLUUID object_id = pick_info.getObjectID(); S32 object_face = pick_info.mObjectFace; @@ -1103,7 +1116,8 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi LL_DEBUGS() << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << LL_ENDL; - LLVOVolume *obj = dynamic_cast(static_cast(pick_info.getObject())); + LLViewerObject* vobjp = static_cast(pick_info.getObject()); + LLVOVolume *obj = vobjp ? vobjp->asVolume() : nullptr; if (obj && !obj->getRegion()->getCapability("ObjectMedia").empty()) { @@ -1362,7 +1376,11 @@ BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated) // it's all entered/processed. if (key == KEY_RETURN && mask == MASK_NONE) { - return FALSE; + // RIDER: although, at times some of the controlls (in particular the CEF viewer + // would like to know about the KEYDOWN for an enter key... so ask and pass it along. + LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); + if (keyboard_focus && !keyboard_focus->wantsReturnKey()) + return FALSE; } return gViewerKeyboard.handleKey(key, mask, repeated); @@ -1380,10 +1398,9 @@ BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask) tool_inspectp->keyUp(key, mask); } - return FALSE; + return gViewerKeyboard.handleKeyUp(key, mask); } - void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) { LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); @@ -1395,6 +1412,9 @@ void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) { + if (mActive == (bool)activated) { + return TRUE; + } if (activated) { mActive = true; @@ -1402,7 +1422,8 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) gAgent.clearAFK(); if (mWindow->getFullscreen() && !mIgnoreActivate) { - if (!LLApp::isExiting() ) + // Opengl doesn't need torn down when alt tabbing. + /*if (!LLApp::isExiting() ) { if (LLStartUp::getStartupState() >= STATE_STARTED) { @@ -1416,7 +1437,7 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) restoreGL(); } } - else + else*/ { LL_WARNS() << "Activating while quitting" << LL_ENDL; } @@ -1442,11 +1463,12 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) send_agent_pause(); - if (mWindow->getFullscreen() && !mIgnoreActivate) + // Opengl doesn't need torn down when alt tabbing. + /*if (mWindow->getFullscreen() && !mIgnoreActivate) { LL_INFOS() << "Stopping GL during deactivation" << LL_ENDL; stopGL(); - } + }*/ // Mute audio audio_update_volume(false); } @@ -1486,12 +1508,8 @@ BOOL LLViewerWindow::handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S //SetBKColor(hdc, RGB(255, 255, 255)); FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255))); - std::string name_str; - gAgent.getName(name_str); - std::string temp_str; - temp_str = llformat( "%s FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */ - name_str.c_str(), + temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */ LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(), LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0), LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0)); @@ -1569,6 +1587,22 @@ BOOL LLViewerWindow::handleDeviceChange(LLWindow *window) return FALSE; } +bool LLViewerWindow::handleDPIScaleChange(LLWindow *window, float xDPIScale, float yDPIScale, U32 width, U32 height) +{ + LL_INFOS() << "handleDPIScaleChange" << LL_ENDL; + if (mDPIScaleX != xDPIScale || mDPIScaleY != yDPIScale) + { + LL_INFOS() << "handleDPIScaleChange APPLY" << LL_ENDL; + mDPIScaleX = xDPIScale; + mDPIScaleY = yDPIScale; + if (!mWindow->getFullscreen()) { + reshape(width ? width : getWindowWidthRaw(), height ? height : getWindowHeightRaw()); + return true; + } + } + return false; +} + void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg) { LLAppViewer::instance()->pingMainloopTimeout(msg); @@ -1607,6 +1641,17 @@ std::string LLViewerWindow::translateString(const char* tag, return LLTrans::getString( std::string(tag), args_copy); } +static const std::string font_dir() +{ + return gDirUtilp->getExecutableDir() + #if LL_DARWIN + + "/../Resources" + #elif !defined(LL_WINDOWS) + + "/.." + #endif + ; +} + // // Classes // @@ -1632,12 +1677,13 @@ LLViewerWindow::LLViewerWindow( mHideCursorPermanent( FALSE ), mCursorHidden(FALSE), mIgnoreActivate( FALSE ), - mHoverPick(), mResDirty(false), //mStatesDirty(false), //Singu Note: No longer needed. State update is now in restoreGL. mIsFullscreenChecked(false), mCurrResolutionIndex(0), - mProgressView(NULL) + mProgressView(NULL), + mDPIScaleX(1.f), + mDPIScaleY(1.f) { LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "alert")); LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "alertmodal")); @@ -1706,10 +1752,9 @@ LLViewerWindow::LLViewerWindow( // Get the real window rect the window was created with (since there are various OS-dependent reasons why // the size of a window or fullscreen context may have been adjusted slightly...) - F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor"); - mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); - mDisplayScale *= ui_scale_factor; + mDisplayScale.scaleVec(getUIScale()); + LLUI::setScaleFactor(mDisplayScale); { @@ -1774,8 +1819,7 @@ LLViewerWindow::LLViewerWindow( LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), mDisplayScale.mV[VX], mDisplayScale.mV[VY], - gDirUtilp->getAppRODataDir(), - LLUICtrlFactory::getXUIPaths()); + font_dir()); } // Create container for all sub-views LLView::Params rvp; @@ -1800,6 +1844,8 @@ LLViewerWindow::LLViewerWindow( mDebugText = new LLDebugText(this); + mWindow->postInitialized(); + } void LLViewerWindow::initGLDefaults() @@ -2035,8 +2081,6 @@ void LLViewerWindow::adjustRectanglesForFirstUse(const LLRect& window) adjust_rect_top_right("FloaterMiniMapRect", window); - adjust_rect_top_right("FloaterLagMeter", window); - adjust_rect_top_left("FloaterBuildOptionsRect", window); adjust_rect_bottom_left("FloaterActiveSpeakersRect", window); @@ -2364,7 +2408,7 @@ void LLViewerWindow::reshape(S32 width, S32 height) // reshape messages. We don't care about these, and we // don't want to send messages because the message system // may have been destructed. - if (!LLApp::isExiting()) + if (!LLApp::isExiting()/* && !gGLManager.mIsDisabled*/) { if (gNoRender) { @@ -2372,7 +2416,7 @@ void LLViewerWindow::reshape(S32 width, S32 height) } gWindowResized = TRUE; - glViewport(0, 0, width, height ); + gGL.setViewport(0, 0, width, height ); if (height > 0) { @@ -2536,8 +2580,6 @@ void LLViewerWindow::draw() LLView::sIsDrawing = TRUE; #endif stop_glerror(); - - LLUI::setLineWidth(1.f); LLUI::setLineWidth(1.f); // Reset any left-over transforms @@ -2681,6 +2723,46 @@ void LLViewerWindow::draw() #endif } +// Takes a single keyup event, usually when UI is visible +BOOL LLViewerWindow::handleKeyUp(KEY key, MASK mask) +{ + LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); + + if (keyboard_focus + && !(mask & (MASK_CONTROL | MASK_ALT)) + && !gFocusMgr.getKeystrokesOnly()) + { + // We have keyboard focus, and it's not an accelerator + if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown()) + { + return keyboard_focus->handleKeyUp(key, mask, FALSE); + } + else if (key < 0x80) + { + // Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first. + return (gFocusMgr.getKeyboardFocus() != NULL); + } + } + + if (keyboard_focus) + { + if (keyboard_focus->handleKeyUp(key, mask, FALSE)) + { + LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned true" << LL_ENDL; + //LLViewerEventRecorder::instance().logKeyEvent(key, mask); + return TRUE; + } + else { + LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned FALSE" << LL_ENDL; + } + } + + // don't pass keys on to world when something in ui has focus + return gFocusMgr.childHasKeyboardFocus(mRootView) + || LLMenuGL::getKeyboardMode() + || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive()); +} + // Takes a single keydown event, usually when UI is visible BOOL LLViewerWindow::handleKey(KEY key, MASK mask) { @@ -2699,7 +2781,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) && !gFocusMgr.getKeystrokesOnly()) { // We have keyboard focus, and it's not an accelerator - if (key < 0x80) + if (gFocusMgr.getKeyboardFocus() && gFocusMgr.getKeyboardFocus()->wantsKeyUpKeyDown()) + { + return gFocusMgr.getKeyboardFocus()->handleKey(key, mask, FALSE ); + } + else if (key < 0x80) { // Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first. return (gFocusMgr.getKeyboardFocus() != NULL); @@ -2860,7 +2946,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) { { // passing NULL here, character will be added later when it is handled by character handler. - gChatBar->startChat(NULL); + LLChatBar::startChat(NULL); return TRUE; } } @@ -3005,8 +3091,8 @@ void LLViewerWindow::moveCursorToCenter() // event processing. void LLViewerWindow::updateUI() { - static LLFastTimer::DeclareTimer ftm("Update UI"); - LLFastTimer t(ftm); + static LLTrace::BlockTimerStatHandle ftm("Update UI"); + LL_RECORD_BLOCK_TIME(ftm); static std::string last_handle_msg; // animate layout stacks so we have up to date rect for world view @@ -3022,7 +3108,7 @@ void LLViewerWindow::updateUI() if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) { gDebugRaycastFaceHit = -1; - gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, + gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, &gDebugRaycastFaceHit, &gDebugRaycastIntersection, &gDebugRaycastTexCoord, @@ -3030,6 +3116,7 @@ void LLViewerWindow::updateUI() &gDebugRaycastTangent, &gDebugRaycastStart, &gDebugRaycastEnd); + gDebugRaycastParticle = gPipeline.lineSegmentIntersectParticle(gDebugRaycastStart, gDebugRaycastEnd, &gDebugRaycastParticleIntersection, NULL); } updateMouseDelta(); @@ -3172,6 +3259,7 @@ void LLViewerWindow::updateUI() // only handle hover events when UI is enabled // if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + if (mMouseInWindow) { if( mouse_captor ) @@ -3326,40 +3414,9 @@ void LLViewerWindow::updateUI() { LLSelectMgr::getInstance()->deselectUnused(); } - - // per frame picking - for tooltips and changing cursor over interactive objects - static S32 previous_x = -1; - static S32 previous_y = -1; - static BOOL mouse_moved_since_pick = FALSE; - - if ((previous_x != x) || (previous_y != y)) - mouse_moved_since_pick = TRUE; - - static const LLCachedControl picks_moving("PicksPerSecondMouseMoving",5.f); - static const LLCachedControl picks_stationary("PicksPerSecondMouseStationary",0.f); - if( !getCursorHidden() - // When in-world media is in focus, pick every frame so that browser mouse-overs, dragging scrollbars, etc. work properly. - && (LLViewerMediaFocus::getInstance()->getFocus() - || ((mouse_moved_since_pick) && (picks_moving > 0.0) && (mPickTimer.getElapsedTimeF32() > 1.0f / picks_moving)) - || ((!mouse_moved_since_pick) && (picks_stationary > 0.0) && (mPickTimer.getElapsedTimeF32() > 1.0f / picks_stationary)))) - { - mouse_moved_since_pick = FALSE; - mPickTimer.reset(); - pickAsync(getCurrentMouseX(), getCurrentMouseY(), mask, hoverPickCallback, TRUE, TRUE); - } - - previous_x = x; - previous_y = y; - return; } -/* static */ -void LLViewerWindow::hoverPickCallback(const LLPickInfo& pick_info) -{ - gViewerWindow->mHoverPick = pick_info; -} - void LLViewerWindow::updateLayout() { static const LLCachedControl freeze_time("FreezeTime",0); @@ -3491,7 +3548,7 @@ void LLViewerWindow::updateLayout() && gFocusMgr.getKeyboardFocus() == NULL && gChatBar->isInVisibleChain()) { - gChatBar->startChat(NULL); + LLChatBar::startChat(NULL); } } @@ -3524,8 +3581,8 @@ void LLViewerWindow::updateMouseDelta() static F32 fdy = 0.f; F32 amount = 16.f; - fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f); - fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f); + fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds.value()*amount,1.f); + fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds.value()*amount,1.f); mCurrentMouseDelta.set(ll_round(fdx), ll_round(fdy)); mouse_vel.setVec(fdx,fdy); @@ -3702,8 +3759,8 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, if (LLSelectMgr::sRenderLightRadius && LLToolMgr::getInstance()->inEdit()) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLEnable gls_blend(GL_BLEND); - LLGLEnable gls_cull(GL_CULL_FACE); + LLGLEnable gls_blend; + LLGLEnable gls_cull; LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); @@ -3874,7 +3931,14 @@ BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewe return intersect; } -void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent, BOOL get_surface_info) +void LLViewerWindow::pickAsync( S32 x, + S32 y_from_bot, + MASK mask, + void (*callback)(const LLPickInfo& info), + BOOL pick_transparent, + BOOL pick_rigged, + BOOL pick_unselectable, + BOOL get_surface_info) { if (gNoRender) { @@ -3889,8 +3953,7 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback // "Show Debug Alpha" means no object actually transparent pick_transparent = TRUE; } - - LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, get_surface_info, callback); + LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, FALSE, get_surface_info, pick_unselectable, callback); schedulePick(pick_info); } @@ -3922,6 +3985,11 @@ void LLViewerWindow::performPick() return; } + if (!gFocusMgr.getAppHasFocus()) + { + return; + } + if (!mPicks.empty()) { std::vector::iterator pick_it; @@ -3951,13 +4019,18 @@ void LLViewerWindow::returnEmptyPicks() } // Performs the GL object/land pick. -LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent) +LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_particle) { if (gNoRender) { return LLPickInfo(); } + if (!gFocusMgr.getAppHasFocus()) + { + return LLPickInfo(); + } + // push back pick info object BOOL in_build_mode = gFloaterTools && gFloaterTools->getVisible(); if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha) @@ -3966,10 +4039,9 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_trans // "Show Debug Alpha" means no object actually transparent pick_transparent = TRUE; } - // shortcut queueing in mPicks and just update mLastPick in place MASK key_mask = gKeyboard->currentMask(TRUE); - mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, TRUE, NULL); + mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, pick_rigged, pick_particle, TRUE, FALSE, NULL); mLastPick.fetchResults(); return mLastPick; @@ -4005,6 +4077,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de LLViewerObject *this_object, S32 this_face, BOOL pick_transparent, + BOOL pick_rigged, S32* face_hit, LLVector4a *intersection, LLVector2 *uv, @@ -4075,7 +4148,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de { if (this_object->isHUDAttachment()) // is a HUD object? { - if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, + if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, pick_rigged, face_hit, intersection, uv, normal, tangent)) { found = this_object; @@ -4083,7 +4156,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de } else // is a world object { - if (this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, + if (this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, pick_rigged, face_hit, intersection, uv, normal, tangent)) { found = this_object; @@ -4104,7 +4177,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de if (!found) // if not found in HUD, look in world: { - found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, + found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged, face_hit, intersection, uv, normal, tangent); if (found && !pick_transparent) @@ -4249,7 +4322,7 @@ BOOL LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, con // Returns global position -BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_position_global) +BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_position_global, BOOL ignore_distance) { LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y); F32 mouse_dir_scale; @@ -4258,6 +4331,7 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d F32 land_z; const F32 FIRST_PASS_STEP = 1.0f; // meters const F32 SECOND_PASS_STEP = 0.1f; // meters + const F32 draw_distance = ignore_distance ? MAX_FAR_CLIP : (gAgentCamera.mDrawDistance * 4); LLVector3d camera_pos_global; camera_pos_global = gAgentCamera.getCameraPositionGlobal(); @@ -4265,7 +4339,7 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d LLVector3 probe_point_region; // walk forwards to find the point - for (mouse_dir_scale = FIRST_PASS_STEP; mouse_dir_scale < gAgentCamera.mDrawDistance * 4; mouse_dir_scale += FIRST_PASS_STEP) + for (mouse_dir_scale = FIRST_PASS_STEP; mouse_dir_scale < draw_distance; mouse_dir_scale += FIRST_PASS_STEP) { LLVector3d mouse_direction_global_d; mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale); @@ -4478,14 +4552,14 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height) if (gViewerWindow->getWindow()->getFullscreen()) { - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); gViewerWindow->changeDisplaySettings(FALSE, new_size, vsync_mode, TRUE); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); } else { @@ -4703,6 +4777,7 @@ bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, // PRE SNAPSHOT gDisplaySwapBuffers = FALSE; + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); setCursor(UI_CURSOR_WAIT); @@ -5155,11 +5230,10 @@ void LLViewerWindow::setup2DRender() void LLViewerWindow::setup2DViewport(S32 x_offset, S32 y_offset) { - gGLViewport[0] = mWindowRectRaw.mLeft + x_offset; - gGLViewport[1] = mWindowRectRaw.mBottom + y_offset; - gGLViewport[2] = mWindowRectRaw.getWidth(); - gGLViewport[3] = mWindowRectRaw.getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + gGLViewport = mWindowRectRaw; + gGLViewport.translate(x_offset, y_offset); + gGL.setViewport(gGLViewport); + gGL.setScissor(gGLViewport); } @@ -5172,11 +5246,10 @@ void LLViewerWindow::setup3DRender() void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset) { - gGLViewport[0] = getWindowRectRaw().mLeft + x_offset; - gGLViewport[1] = getWindowRectRaw().mBottom + y_offset; - gGLViewport[2] = getWindowRectRaw().getWidth(); - gGLViewport[3] = getWindowRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + gGLViewport = mWindowRectRaw; + gGLViewport.translate(x_offset, y_offset); + gGL.setViewport(gGLViewport); + gGL.setScissor(gGLViewport); } void LLViewerWindow::revealIntroPanel() @@ -5256,6 +5329,7 @@ void LLViewerWindow::dumpState() void LLViewerWindow::stopGL(BOOL save_state) { + stop_glerror(); //Note: --bao //if not necessary, do not change the order of the function calls in this function. //if change something, make sure it will not break anything. @@ -5285,6 +5359,7 @@ void LLViewerWindow::stopGL(BOOL save_state) stop_glerror(); LLVOPartGroup::destroyGL(); + stop_glerror(); LLViewerDynamicTexture::destroyGL(); stop_glerror(); @@ -5293,8 +5368,10 @@ void LLViewerWindow::stopGL(BOOL save_state) { gPipeline.destroyGL(); } + stop_glerror(); gBox.cleanupGL(); + stop_glerror(); if(LLPostProcess::instanceExists()) { @@ -5303,46 +5380,78 @@ void LLViewerWindow::stopGL(BOOL save_state) gTextureList.destroyGL(save_state); stop_glerror(); + gGL.destroyGL(); + stop_glerror(); gGLManager.mIsDisabled = TRUE; stop_glerror(); - gGL.resetVertexBuffers(); + LLVertexBuffer::cleanupClass(); + + stop_glerror(); - LL_INFOS() << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemoryInBytes << " bytes" << LL_ENDL; + LL_INFOS() << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemory << " bytes" << LL_ENDL; } } -void LLViewerWindow::restoreGL(const std::string& progress_message) +void LLViewerWindow::restoreGLState() +{ + gGL.init(); + stop_glerror(); + initGLDefaults(); + stop_glerror(); + gGL.refreshState(); //Singu Note: Call immediately. Cached states may have prevented initGLDefaults from actually applying changes. + stop_glerror(); + LLGLStateValidator::restoreGL(); + stop_glerror(); +} + +void LLViewerWindow::restoreGL(bool full_restore, const std::string& progress_message) { //Note: --bao //if not necessary, do not change the order of the function calls in this function. //if change something, make sure it will not break anything. //especially, be careful to put something before gTextureList.restoreGL(); + if (!gGLManager.mIsDisabled && !full_restore) + { + LL_INFOS() << "Restoring GL state..." << LL_ENDL; + restoreGLState(); + gPipeline.releaseOcclusionBuffers(); // Occlusion handles must be invalidated + return; + } if (gGLManager.mIsDisabled) { + stop_glerror(); LL_INFOS() << "Restoring GL..." << LL_ENDL; gGLManager.mIsDisabled = FALSE; - gGL.init(); - initGLDefaults(); - gGL.refreshState(); //Singu Note: Call immediately. Cached states may have prevented initGLDefaults from actually applying changes. - LLGLState::restoreGL(); + restoreGLState(); + gTextureList.restoreGL(); + stop_glerror(); // for future support of non-square pixels, and fonts that are properly stretched //LLFontGL::destroyDefaultFonts(); initFonts(); + stop_glerror(); gSky.restoreGL(); + stop_glerror(); gPipeline.restoreGL(); + stop_glerror(); LLDrawPoolWater::restoreGL(); + stop_glerror(); LLManipTranslate::restoreGL(); + stop_glerror(); gBumpImageList.restoreGL(); + stop_glerror(); LLViewerDynamicTexture::restoreGL(); + stop_glerror(); LLVOAvatar::restoreGL(); + stop_glerror(); LLVOPartGroup::restoreGL(); + stop_glerror(); gResizeScreenTexture = TRUE; gWindowResized = TRUE; @@ -5364,8 +5473,9 @@ void LLViewerWindow::restoreGL(const std::string& progress_message) { LL_WARNS() << " Someone took over my signal/exception handler (post restoreGL)!" << LL_ENDL; } - + stop_glerror(); } + } void LLViewerWindow::initFonts(F32 zoom_factor) @@ -5378,8 +5488,8 @@ void LLViewerWindow::initFonts(F32 zoom_factor) LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), mDisplayScale.mV[VX] * zoom_factor, mDisplayScale.mV[VY] * zoom_factor, - gDirUtilp->getAppRODataDir(), - LLUICtrlFactory::getXUIPaths()); + font_dir()); + // Force font reloads, which can be very slow LLFontGL::loadDefaultFonts(); } void LLViewerWindow::toggleFullscreen(BOOL show_progress) @@ -5425,7 +5535,7 @@ BOOL LLViewerWindow::checkSettings() { //Singu Note: Don't do the following. //setShaders is already called in restoreGL(), and gGL.refreshState() is too as to maintain blend states. - //This maintaining of blend states is needed for LLGLState::checkStates() to not error out. + //This maintaining of blend states is needed for LLGLStateValidator::checkStates() to not error out. /*if (mStatesDirty) { gGL.refreshState(); @@ -5459,6 +5569,9 @@ BOOL LLViewerWindow::checkSettings() BOOL is_fullscreen = mWindow->getFullscreen(); if(mWantFullscreen) { + if (mWindow->getMinimized()) { + return FALSE; + } LLCoordScreen screen_size; LLCoordScreen desired_screen_size(gSavedSettings.getS32("FullScreenWidth"), gSavedSettings.getS32("FullScreenHeight")); @@ -5472,8 +5585,8 @@ BOOL LLViewerWindow::checkSettings() return FALSE; } - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); S32 vsync_mode = gSavedSettings.getS32("SHRenderVsyncMode"); if(vsync_mode == -1 && !gGLManager.mHasAdaptiveVsync) @@ -5485,8 +5598,8 @@ BOOL LLViewerWindow::checkSettings() desired_screen_size, vsync_mode, mShowFullscreenProgress); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); return TRUE; } } @@ -5495,15 +5608,15 @@ BOOL LLViewerWindow::checkSettings() if(is_fullscreen) { // Changing to windowed mode. - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); changeDisplaySettings(FALSE, LLCoordScreen(gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight")), TRUE, mShowFullscreenProgress); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); return TRUE; } } @@ -5516,11 +5629,11 @@ void LLViewerWindow::restartDisplay(BOOL show_progress_bar) stopGL(); if (show_progress_bar) { - restoreGL(LLTrans::getString("ProgressChangingResolution")); + restoreGL(true, LLTrans::getString("ProgressChangingResolution")); } else { - restoreGL(); + restoreGL(true); } } @@ -5568,7 +5681,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); send_agent_pause(); LL_INFOS() << "Stopping GL during changeDisplaySettings" << LL_ENDL; - stopGL(); + //stopGL(); mIgnoreActivate = TRUE; LLCoordScreen old_size; LLCoordScreen old_pos; @@ -5594,12 +5707,18 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, mWindow->setFSAASamples(fsaa); mWindow->setVsyncMode(vsync_mode); - result_first_try = mWindow->switchContext(fullscreen, size, vsync_mode, &new_pos); + auto stopfn = [this]() { this->stopGL(); }; + auto restoreFn = [this, show_progress_bar](bool full_restore) { + LL_INFOS() << "Restoring GL during resolution change" << LL_ENDL; + this->restoreGL(full_restore, show_progress_bar ? LLTrans::getString("ProgressChangingResolution") : ""); + }; + + result_first_try = mWindow->switchContext(fullscreen, size, vsync_mode, stopfn, restoreFn, &new_pos); if (!result_first_try) { // try to switch back mWindow->setFSAASamples(old_fsaa); - result_second_try = mWindow->switchContext(old_fullscreen, old_size, vsync_mode, &new_pos); + result_second_try = mWindow->switchContext(old_fullscreen, old_size, vsync_mode, stopfn, restoreFn, &new_pos); if (!result_second_try) { @@ -5611,16 +5730,6 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, } send_agent_resume(); - LL_INFOS() << "Restoring GL during resolution change" << LL_ENDL; - if (show_progress_bar) - { - restoreGL(LLTrans::getString("ProgressChangingResolution")); - } - else - { - restoreGL(); - } - if (!result_first_try) { LLSD args; @@ -5688,17 +5797,17 @@ F32 LLViewerWindow::getDisplayAspectRatio() const void LLViewerWindow::calcDisplayScale() { - F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor"); + LLVector2 ui_scale_factor = getUIScale(); LLVector2 display_scale; display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); if(mWindow->getFullscreen()) { F32 height_normalization = gSavedSettings.getBOOL("UIAutoScale") ? ((F32)mWindowRectRaw.getHeight() / display_scale.mV[VY]) / 768.f : 1.f; - display_scale *= (ui_scale_factor * height_normalization); + display_scale.scaleVec(ui_scale_factor * height_normalization); } else { - display_scale *= ui_scale_factor; + display_scale.scaleVec(ui_scale_factor); } // limit minimum display scale @@ -5723,6 +5832,19 @@ void LLViewerWindow::calcDisplayScale() } } +LLVector2 LLViewerWindow::getUIScale() const +{ + static LLCachedControl ui_scale_factor("UIScaleFactor"); + if (mWindow->getFullscreen()) + { + return LLVector2(ui_scale_factor, ui_scale_factor); + } + else + { + return LLVector2(mDPIScaleX * ui_scale_factor, mDPIScaleY * ui_scale_factor); + } +} + S32 LLViewerWindow::getChatConsoleBottomPad() { static const LLCachedControl user_offset("ConsoleBottomOffset"); @@ -5855,15 +5977,20 @@ LLPickInfo::LLPickInfo() mTangent(), mBinormal(), mHUDIcon(NULL), - mPickTransparent(FALSE) + mPickTransparent(FALSE), + mPickRigged(FALSE), + mPickParticle(FALSE) { } LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, MASK keyboard_mask, - BOOL pick_transparent, - BOOL pick_uv_coords, - void (*pick_callback)(const LLPickInfo& pick_info)) + BOOL pick_transparent, + BOOL pick_rigged, + BOOL pick_particle, + BOOL pick_uv_coords, + BOOL pick_unselectable, + void (*pick_callback)(const LLPickInfo& pick_info)) : mMousePt(mouse_pos), mKeyMask(keyboard_mask), mPickCallback(pick_callback), @@ -5877,7 +6004,10 @@ LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, mTangent(), mBinormal(), mHUDIcon(NULL), - mPickTransparent(pick_transparent) + mPickTransparent(pick_transparent), + mPickRigged(pick_rigged), + mPickParticle(pick_particle), + mPickUnselectable(pick_unselectable) { } @@ -5895,6 +6025,9 @@ void LLPickInfo::fetchResults() LLVector4a origin; origin.load3(LLViewerCamera::getInstance()->getOrigin().mV); F32 icon_dist = 0.f; + LLVector4a start; + LLVector4a end; + LLVector4a particle_end; if (hit_icon) { LLVector4a delta; @@ -5903,15 +6036,25 @@ void LLPickInfo::fetchResults() } LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f, - NULL, -1, mPickTransparent, &face_hit, - &intersection, &uv, &normal, &tangent); + NULL, -1, mPickTransparent, mPickRigged, &face_hit, + &intersection, &uv, &normal, &tangent, &start, &end); mPickPt = mMousePt; U32 te_offset = face_hit > -1 ? face_hit : 0; - //unproject relative clicked coordinate from window coordinate using GL - + if (mPickParticle) + { //get the end point of line segement to use for particle raycast + if (hit_object) + { + particle_end = intersection; + } + else + { + particle_end = end; + } + } + LLViewerObject* objectp = hit_object; @@ -5937,7 +6080,7 @@ void LLPickInfo::fetchResults() // put global position into land_pos LLVector3d land_pos; - if (!gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos)) + if (!gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos, mPickUnselectable)) { // The selected point is beyond the draw distance or is otherwise // not selectable. Return before calling mPickCallback(). @@ -5975,6 +6118,18 @@ void LLPickInfo::fetchResults() } } + if (mPickParticle) + { //search for closest particle to click origin out to intersection point + S32 part_face = -1; + + LLVOPartGroup* group = gPipeline.lineSegmentIntersectParticle(start, particle_end, NULL, &part_face); + if (group) + { + mParticleOwnerID = group->getPartOwner(part_face); + mParticleSourceID = group->getPartSource(part_face); + } + } + if (mPickCallback) { mPickCallback(*this); @@ -6025,7 +6180,7 @@ void LLPickInfo::getSurfaceInfo() if (objectp) { if (gViewerWindow->cursorIntersect(ll_round((F32)mMousePt.mX), ll_round((F32)mMousePt.mY), 1024.f, - objectp, -1, mPickTransparent, + objectp, -1, mPickTransparent, mPickRigged, &mObjectFace, &intersection, &mSTCoords, diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 7e47a1a1bb..c47efb95cb 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -88,7 +88,10 @@ class LLPickInfo LLPickInfo(const LLCoordGL& mouse_pos, MASK keyboard_mask, BOOL pick_transparent, + BOOL pick_rigged, + BOOL pick_particle, BOOL pick_surface_info, + BOOL pick_unselectable, void (*pick_callback)(const LLPickInfo& pick_info)); void fetchResults(); @@ -108,6 +111,8 @@ class LLPickInfo LLVector3d mPosGlobal; LLVector3 mObjectOffset; LLUUID mObjectID; + LLUUID mParticleOwnerID; + LLUUID mParticleSourceID; S32 mObjectFace; LLHUDIcon* mHUDIcon; LLVector3 mIntersection; @@ -118,6 +123,9 @@ class LLPickInfo LLVector4 mTangent; LLVector3 mBinormal; BOOL mPickTransparent; + BOOL mPickRigged; + BOOL mPickParticle; + BOOL mPickUnselectable; void getSurfaceInfo(); private: @@ -181,6 +189,7 @@ class LLViewerWindow : public LLWindowCallbacks /*virtual*/ void handleDataCopy(LLWindow *window, S32 data_type, void *data); /*virtual*/ BOOL handleTimerEvent(LLWindow *window); /*virtual*/ BOOL handleDeviceChange(LLWindow *window); + /*virtual*/ bool handleDPIScaleChange(LLWindow *window, float xDPIScale, float yDPIScale, U32 width = 0, U32 height = 0); /*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg); /*virtual*/ void handlePauseWatchdog(LLWindow *window); @@ -241,7 +250,6 @@ class LLViewerWindow : public LLWindowCallbacks BOOL getRightMouseDown() const { return mRightMouseDown; } const LLPickInfo& getLastPick() const { return mLastPick; } - const LLPickInfo& getHoverPick() const { return mHoverPick; } void setup2DViewport(S32 x_offset = 0, S32 y_offset = 0); void setup3DViewport(S32 x_offset = 0, S32 y_offset = 0); @@ -292,6 +300,7 @@ class LLViewerWindow : public LLWindowCallbacks void updateKeyboardFocus(); BOOL handleKey(KEY key, MASK mask); + BOOL handleKeyUp(KEY key, MASK mask); void handleScrollWheel (S32 clicks); // Hide normal UI when a logon fails, re-show everything when logon is attempted again @@ -342,9 +351,15 @@ class LLViewerWindow : public LLWindowCallbacks void returnEmptyPicks(); - void pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& pick_info), - BOOL pick_transparent = FALSE, BOOL get_surface_info = FALSE); - LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent); + void pickAsync( S32 x, + S32 y_from_bot, + MASK mask, + void (*callback)(const LLPickInfo& pick_info), + BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, + BOOL pick_unselectable = FALSE, + BOOL get_surface_info = FALSE); + LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_rigged = FALSE, BOOL pick_particle = FALSE); static void hoverPickCallback(const LLPickInfo& pick_info); LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth, @@ -354,6 +369,7 @@ class LLViewerWindow : public LLWindowCallbacks LLViewerObject *this_object = NULL, S32 this_face = -1, BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, S32* face_hit = NULL, LLVector4a *intersection = NULL, LLVector2 *uv = NULL, @@ -371,7 +387,7 @@ class LLViewerWindow : public LLWindowCallbacks //const LLVector3d& lastNonFloraObjectHitOffset(); // mousePointOnLand() returns true if found point - BOOL mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_pos_global); + BOOL mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_pos_global, BOOL ignore_distance = FALSE); BOOL mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, const LLVector3d &plane_point, const LLVector3 &plane_normal); LLVector3d clickPointInWorldGlobal(const S32 x, const S32 y_from_bot, LLViewerObject* clicked_object) const; BOOL clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const; @@ -392,15 +408,17 @@ class LLViewerWindow : public LLWindowCallbacks const LLVector2& getDisplayScale() const { return mDisplayScale; } void calcDisplayScale(); + LLVector2 getUIScale() const; + private: bool shouldShowToolTipFor(LLMouseHandler *mh); static bool onAlert(const LLSD& notify); - void switchToolByMask(MASK mask); void destroyWindow(); void drawMouselookInstructions(); void stopGL(BOOL save_state = TRUE); - void restoreGL(const std::string& progress_message = LLStringUtil::null); + void restoreGLState(); + void restoreGL(bool full_restore, const std::string& progress_message = LLStringUtil::null); void initFonts(F32 zoom_factor = 1.f); void schedulePick(LLPickInfo& pick_info); S32 getChatConsoleBottomPad(); // Vertical padding for child console rect, varied by bottom clutter @@ -445,7 +463,6 @@ class LLViewerWindow : public LLWindowCallbacks BOOL mHideCursorPermanent; // true during drags, mouselook BOOL mCursorHidden; LLPickInfo mLastPick; - LLPickInfo mHoverPick; std::vector mPicks; LLRect mPickScreenRegion; // area of frame buffer for rendering pick frames (generally follows mouse to avoid going offscreen) LLTimer mPickTimer; // timer for scheduling n picks per second @@ -463,6 +480,9 @@ class LLViewerWindow : public LLWindowCallbacks bool mIsFullscreenChecked; // Did the user check the fullscreen checkbox in the display settings U32 mCurrResolutionIndex; + float mDPIScaleX; + float mDPIScaleY; + protected: static std::string sSnapshotBaseName; static std::string sSnapshotDir; diff --git a/indra/newview/llvlmanager.cpp b/indra/newview/llvlmanager.cpp index d570428bdb..f3dd91ab51 100644 --- a/indra/newview/llvlmanager.cpp +++ b/indra/newview/llvlmanager.cpp @@ -42,6 +42,16 @@ #include "llframetimer.h" #include "llsurface.h" +const char LAND_LAYER_CODE = 'L'; +const char WATER_LAYER_CODE = 'W'; +const char WIND_LAYER_CODE = '7'; +const char CLOUD_LAYER_CODE = '8'; + +const char WHITECORE_LAND_LAYER_CODE = 'M'; +const char WHITECORE_WATER_LAYER_CODE = 'X'; +const char WHITECORE_WIND_LAYER_CODE = '9'; +const char WHITECORE_CLOUD_LAYER_CODE = ':'; + LLVLManager gVLManager; LLVLManager::~LLVLManager() @@ -56,33 +66,22 @@ LLVLManager::~LLVLManager() void LLVLManager::addLayerData(LLVLData *vl_datap, const S32 mesg_size) { -// Aurora Sim - //if (LAND_LAYER_CODE == vl_datap->mType) - if (LAND_LAYER_CODE == vl_datap->mType || AURORA_LAND_LAYER_CODE == vl_datap->mType) -// Aurora Sim + if (LAND_LAYER_CODE == vl_datap->mType || WHITECORE_LAND_LAYER_CODE == vl_datap->mType) { mLandBits += mesg_size * 8; } -// Aurora Sim - //else if (WIND_LAYER_CODE == vl_datap->mType) - else if (WIND_LAYER_CODE == vl_datap->mType || AURORA_WIND_LAYER_CODE == vl_datap->mType) -// Aurora Sim + else if (WATER_LAYER_CODE == vl_datap->mType || WHITECORE_WATER_LAYER_CODE == vl_datap->mType) { - mWindBits += mesg_size * 8; + mWaterBits += mesg_size * 8; } -// Aurora Sim - //else if (CLOUD_LAYER_CODE == vl_datap->mType) - else if (CLOUD_LAYER_CODE == vl_datap->mType || AURORA_CLOUD_LAYER_CODE == vl_datap->mType) -// Aurora Sim + else if (WIND_LAYER_CODE == vl_datap->mType || WHITECORE_WIND_LAYER_CODE == vl_datap->mType) { - mCloudBits += mesg_size * 8; + mWindBits += mesg_size * 8; } -// Aurora Sim - else if (WATER_LAYER_CODE == vl_datap->mType || AURORA_CLOUD_LAYER_CODE == vl_datap->mType) + else if (CLOUD_LAYER_CODE == vl_datap->mType || WHITECORE_CLOUD_LAYER_CODE == vl_datap->mType) { - mWaterBits += mesg_size * 8; + mCloudBits += mesg_size * 8; } -// Aurora Sim else { LL_ERRS() << "Unknown layer type!" << (S32)vl_datap->mType << LL_ENDL; @@ -108,19 +107,16 @@ void LLVLManager::unpackData(const S32 num_packets) { datap->mRegionp->getLand().decompressDCTPatch(bit_pack, &goph, FALSE); } -// Aurora Sim - else if (AURORA_LAND_LAYER_CODE == datap->mType) + else if (WHITECORE_LAND_LAYER_CODE == datap->mType) { datap->mRegionp->getLand().decompressDCTPatch(bit_pack, &goph, TRUE); } - //else if (WIND_LAYER_CODE == datap->mType) - else if (WIND_LAYER_CODE == datap->mType || AURORA_WIND_LAYER_CODE == datap->mType) -// Aurora Sim + else if (WIND_LAYER_CODE == datap->mType || WHITECORE_WIND_LAYER_CODE == datap->mType) { datap->mRegionp->mWind.decompress(bit_pack, &goph); } - else if (CLOUD_LAYER_CODE == datap->mType || AURORA_CLOUD_LAYER_CODE == datap->mType) + else if (CLOUD_LAYER_CODE == datap->mType || WHITECORE_CLOUD_LAYER_CODE == datap->mType) { #if ENABLE_CLASSIC_CLOUDS datap->mRegionp->mCloudLayer.decompress(bit_pack, &goph); @@ -156,6 +152,11 @@ S32 LLVLManager::getCloudBits() const return mCloudBits; } +S32 LLVLManager::getWaterBits() const +{ + return mWaterBits; +} + S32 LLVLManager::getTotalBytes() const { return mLandBits + mWindBits + mCloudBits; @@ -189,6 +190,6 @@ LLVLData::LLVLData(LLViewerRegion *regionp, const S8 type, U8 *data, const S32 s LLVLData::~LLVLData() { delete [] mData; - mData = NULL; - mRegionp = NULL; + mData = nullptr; + mRegionp = nullptr; } diff --git a/indra/newview/llvlmanager.h b/indra/newview/llvlmanager.h index 153abfa531..03d26d0db1 100644 --- a/indra/newview/llvlmanager.h +++ b/indra/newview/llvlmanager.h @@ -54,6 +54,7 @@ class LLVLManager S32 getLandBits() const; S32 getWindBits() const; S32 getCloudBits() const; + S32 getWaterBits() const; void resetBitCounts(); @@ -64,9 +65,7 @@ class LLVLManager U32 mLandBits; U32 mWindBits; U32 mCloudBits; -// Aurora Sim U32 mWaterBits; -// Aurora Sim }; class LLVLData @@ -76,10 +75,10 @@ class LLVLData const S8 type, U8 *data, const S32 size); ~LLVLData(); - S8 mType; + LLViewerRegion *mRegionp; U8 *mData; + S8 mType; S32 mSize; - LLViewerRegion *mRegionp; }; extern LLVLManager gVLManager; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 56cf792fdd..b4a25bd166 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -24,12 +24,6 @@ * $/LicenseInfo$ */ -#if LL_MSVC -// disable warning about boost::lexical_cast returning uninitialized data -// when it fails to parse the string -#pragma warning (disable:4701) -#endif - #include "llviewerprecompiledheaders.h" #include "llvoavatar.h" @@ -42,11 +36,14 @@ #include "raytrace.h" #include "llagent.h" // Get state values from here +#include "llagentbenefits.h" #include "llagentcamera.h" #include "llagentwearables.h" #include "llanimationstates.h" +#include "llavataractions.h" #include "llavatarnamecache.h" #include "llavatarpropertiesprocessor.h" +#include "llcontrolavatar.h" #include "llphysicsmotion.h" #include "llviewercontrol.h" #include "lldrawpoolavatar.h" @@ -88,6 +85,7 @@ #include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" +#include "llviewerregion.h" #include "llviewershadermgr.h" #include "llviewerstats.h" #include "llviewerwearable.h" @@ -106,30 +104,27 @@ #include "llvoicevisualizer.h" // Ventrella #include "llsdserialize.h" //For the client definitions +#include "aosystem.h" #include "llcachename.h" -#include "floaterao.h" #include "llsdutil.h" +#include "llskinningutil.h" + #include "llfloaterexploreanimations.h" #include "aixmllindengenepool.h" -#include "aifile.h" #include "llavatarname.h" #include "../lscript/lscript_byteformat.h" #include "hippogridmanager.h" +#include "llrendersphere.h" + // [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.2.0c) #include "rlvhandler.h" // [/RLVa:KB] -#if LL_MSVC -// disable boost::lexical_cast warning -#pragma warning (disable:4702) -#endif - #include -#include #if LL_DARWIN size_t strnlen(const char *s, size_t n) @@ -139,10 +134,13 @@ size_t strnlen(const char *s, size_t n) } #endif +extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG; + const F32 MAX_HOVER_Z = 2.0; const F32 MIN_HOVER_Z = -2.0; -// #define OUTPUT_BREAST_DATA +const F32 MIN_ATTACHMENT_COMPLEXITY = 0.f; +const F32 DEFAULT_MAX_ATTACHMENT_COMPLEXITY = 1.0e6f; using namespace LLAvatarAppearanceDefines; @@ -151,7 +149,6 @@ using namespace LLAvatarAppearanceDefines; //----------------------------------------------------------------------------- const LLUUID ANIM_AGENT_BODY_NOISE_ID = LLUUID("9aa8b0a6-0c6f-9518-c7c3-4f41f2c001ad"); //"body_noise" const LLUUID ANIM_AGENT_BREATHE_ROT_ID = LLUUID("4c5a103e-b830-2f1c-16bc-224aa0ad5bc8"); //"breathe_rot" -const LLUUID ANIM_AGENT_PHYSICS_MOTION_ID = LLUUID("7360e029-3cb8-ebc4-863e-212df440d987"); //"physics_motion" const LLUUID ANIM_AGENT_EDITING_ID = LLUUID("2a8eba1d-a7f8-5596-d44a-b4977bf8c8bb"); //"editing" const LLUUID ANIM_AGENT_EYE_ID = LLUUID("5c780ea8-1cd1-c463-a128-48c023f6fbea"); //"eye" const LLUUID ANIM_AGENT_FLY_ADJUST_ID = LLUUID("db95561f-f1b0-9f9a-7224-b12f71af126e"); //"fly_adjust" @@ -160,6 +157,7 @@ const LLUUID ANIM_AGENT_HEAD_ROT_ID = LLUUID("e6e8d1dd-e643-fff7-b238-c6b4b056a6 const LLUUID ANIM_AGENT_PELVIS_FIX_ID = LLUUID("0c5dd2a2-514d-8893-d44d-05beffad208b"); //"pelvis_fix" const LLUUID ANIM_AGENT_TARGET_ID = LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55"); //"target" const LLUUID ANIM_AGENT_WALK_ADJUST_ID = LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d"); //"walk_adjust" +const LLUUID ANIM_AGENT_PHYSICS_MOTION_ID = LLUUID("7360e029-3cb8-ebc4-863e-212df440d987"); //"physics_motion" // // This must be in the same order as ANIM_AGENT_BODY_NOISE through ANIM_AGENT_WALK_ADJUST (see llmotion.h)! @@ -290,6 +288,9 @@ const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f; const S32 MORPH_MASK_REQUESTED_DISCARD = 0; +const F32 MAX_STANDOFF_FROM_ORIGIN = 3; +const F32 MAX_STANDOFF_DISTANCE_CHANGE = 32; + // Discard level at which to switch to baked textures // Should probably be 4 or 3, but didn't want to change it while change other logic - SJB const S32 SWITCH_TO_BAKED_DISCARD = 5; @@ -309,6 +310,14 @@ const S32 MAX_BUBBLE_CHAT_LENGTH = DB_CHAT_MSG_STR_LEN; const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12; const F32 CHAT_FADE_TIME = 8.0; const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; +const F32 NAMETAG_UPDATE_THRESHOLD = 0.3f; +const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f; +const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f; + +const U32 LLVOAvatar::VISUAL_COMPLEXITY_UNKNOWN = 0; +const F64 HUD_OVERSIZED_TEXTURE_DATA_SIZE = 1024 * 1024; + +#define SLOW_ATTACHMENT_LIST 0 //Singu note: FADE and ALWAYS are swapped around from LL's source to match our preference panel. // Changing the "RenderName" order would cause confusion when 'always' setting suddenly gets @@ -345,7 +354,7 @@ struct LLTextureMaskData ** **/ -struct LLAppearanceMessageContents +struct LLAppearanceMessageContents: public LLRefCount { LLAppearanceMessageContents(): mAppearanceVersion(-1), @@ -1021,28 +1030,27 @@ const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] = S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS; bool LLVOAvatar::sRenderGroupTitles = true; S32 LLVOAvatar::sNumVisibleChatBubbles = 0; -BOOL LLVOAvatar::sDebugInvisible = FALSE; -BOOL LLVOAvatar::sShowAttachmentPoints = FALSE; -BOOL LLVOAvatar::sShowAnimationDebug = FALSE; -BOOL LLVOAvatar::sShowFootPlane = FALSE; -BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE; +BOOL LLVOAvatar::sDebugInvisible = false; +bool LLVOAvatar::sShowAttachmentPoints = false; +BOOL LLVOAvatar::sShowAnimationDebug = false; +bool LLVOAvatar::sShowFootPlane = false; +bool LLVOAvatar::sVisibleInFirstPerson = false; F32 LLVOAvatar::sLODFactor = 1.f; F32 LLVOAvatar::sPhysicsLODFactor = 1.f; -BOOL LLVOAvatar::sUseImpostors = FALSE; -BOOL LLVOAvatar::sJointDebug = FALSE; +bool LLVOAvatar::sUseImpostors = false; +BOOL LLVOAvatar::sJointDebug = false; F32 LLVOAvatar::sUnbakedTime = 0.f; F32 LLVOAvatar::sUnbakedUpdateTime = 0.f; F32 LLVOAvatar::sGreyTime = 0.f; F32 LLVOAvatar::sGreyUpdateTime = 0.f; //Move to LLVOAvatarSelf -BOOL LLVOAvatar::sDebugAvatarRotation = FALSE; +BOOL LLVOAvatar::sDebugAvatarRotation = false; //----------------------------------------------------------------------------- // Helper functions //----------------------------------------------------------------------------- static F32 calc_bouncy_animation(F32 x); -static U32 calc_shame(LLVOVolume* volume, std::set &textures); //----------------------------------------------------------------------------- // LLVOAvatar() @@ -1053,8 +1061,10 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, LLAvatarAppearance(&gAgentWearables), LLViewerObject(id, pcode, regionp), mSpecialRenderMode(0), - mAttachmentGeometryBytes(0), mAttachmentSurfaceArea(0.f), + mAttachmentVisibleTriangleCount(0), + mAttachmentEstTriangleCount(0.f), + mReportedVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN), mTurning(FALSE), mFreezeTimeLangolier(false), mFreezeTimeDead(false), @@ -1064,6 +1074,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mTyping(FALSE), mMeshValid(FALSE), mVisible(FALSE), + mLastImpostorUpdateFrameTime(0.f), mWindFreq(0.f), mRipplePhase( 0.f ), mBelowWater(FALSE), @@ -1086,26 +1097,30 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mNeedsSkin(FALSE), mLastSkinTime(0.f), mUpdatePeriod(1), + mVisualComplexityStale(true), mFirstFullyVisible(TRUE), mFullyLoaded(FALSE), mPreviousFullyLoaded(FALSE), mFullyLoadedInitialized(FALSE), + mVisualComplexity(0), mSupportsAlphaLayers(FALSE), mLoadedCallbacksPaused(FALSE), - mHasPelvisOffset( FALSE ), mLastRezzedStatus(-1), mIsEditingAppearance(FALSE), mUseLocalAppearance(FALSE), - mUseServerBakes(FALSE), // FIXME DRANO consider using boost::optional, defaulting to unknown. + mUseServerBakes(FALSE), mLastUpdateRequestCOFVersion(-1), mLastUpdateReceivedCOFVersion(-1), + mIsControlAvatar(false), + mIsUIAvatar(false), + mEnableDefaultMotions(true), // mHasPhysicsParameters( false ), mIdleMinute(0), mCCSChatTextOverride(false) // { - mAttachedObjectsVector.reserve(MAX_AGENT_ATTACHMENTS); + mAttachedObjectsVector.reserve(38); static LLCachedControl const freeze_time("FreezeTime", false); mFreezeTimeLangolier = freeze_time; @@ -1117,7 +1132,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, const bool needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); - LL_DEBUGS() << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL; + LL_DEBUGS("Avatar","Message") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL; mPelvisp = NULL; @@ -1133,6 +1148,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mNeedsImpostorUpdate = TRUE; mNeedsAnimUpdate = TRUE; + mNeedsExtentUpdate = true; + mImpostorDistance = 0; mImpostorPixelArea = 0; @@ -1166,16 +1183,19 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRuthDebugTimer.reset(); mDebugExistenceTimer.reset(); mLastAppearanceMessageTimer.reset(); - mPelvisOffset = LLVector3(0.0f,0.0f,0.0f); - mLastPelvisToFoot = 0.0f; - mPelvisFixup = 0.0f; - mLastPelvisFixup = 0.0f; } std::string LLVOAvatar::avString() const { - std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); - return " Avatar '" + getFullname() + "' " + viz_string + " "; + if (isControlAvatar()) + { + return getFullname(); + } + else + { + std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); + return " Avatar '" + getFullname() + "' " + viz_string + " "; + } } void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string comment) @@ -1219,10 +1239,9 @@ LLVOAvatar::~LLVOAvatar() //logPendingPhases(); - LL_DEBUGS() << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << LL_ENDL; + LL_DEBUGS("Avatar") << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << LL_ENDL; std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer()); - //mAttachmentPoints.clear(); mDead = TRUE; @@ -1269,7 +1288,8 @@ BOOL LLVOAvatar::isFullyBaked() for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { if (!isTextureDefined(mBakedTextureDatas[i].mTextureIndex) - && ( (i != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT) ) ) + && ( (i != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT) ) + && (i != BAKED_LEFT_ARM) && (i != BAKED_LEFT_LEG) && (i != BAKED_AUX1) && (i != BAKED_AUX2) && (i != BAKED_AUX3) ) { return FALSE; } @@ -1340,11 +1360,7 @@ void LLVOAvatar::deleteLayerSetCaches(bool clearAll) mBakedTextureDatas[i].mTexLayerSet->deleteCaches(); } } - if (mBakedTextureDatas[i].mMaskTexName) - { - LLImageGL::deleteTextures(1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName)); - mBakedTextureDatas[i].mMaskTexName = 0 ; - } + mBakedTextureDatas[i].mMaskTexName.reset(); } } @@ -1382,10 +1398,11 @@ void LLVOAvatar::getNearbyRezzedStats(std::vector& counts) iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* inst = (LLVOAvatar*) *iter; - if (!inst) - continue; - S32 rez_status = inst->getRezzedStatus(); - counts[rez_status]++; + if (inst) + { + S32 rez_status = inst->getRezzedStatus(); + counts[rez_status]++; + } } } @@ -1394,8 +1411,8 @@ std::string LLVOAvatar::rezStatusToString(S32 rez_status) { if (rez_status==0) return "cloud"; if (rez_status==1) return "gray"; - if (rez_status==2) return "textured"; - if (rez_status==3) return "textured_and_downloaded"; + if (rez_status==2) return "downloading"; + if (rez_status==3) return "full"; return "unknown"; } @@ -1465,7 +1482,7 @@ void LLVOAvatar::dumpBakedStatus() const ETextureIndex index = baked_dict->mTextureIndex; if (!inst->isTextureDefined(index)) { - LL_CONT << " " << LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mName; + LL_CONT << " " << (LLAvatarAppearanceDictionary::getInstance()->getTexture(index) ? LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mName : ""); } } LL_CONT << " ) " << inst->getUnbakedPixelAreaRank(); @@ -1507,6 +1524,7 @@ void LLVOAvatar::resetImpostors() { LLVOAvatar* avatar = (LLVOAvatar*) *iter; avatar->mImpostor.release(); + avatar->mNeedsImpostorUpdate = TRUE; } } @@ -1524,7 +1542,6 @@ void LLVOAvatar::deleteCachedImages(bool clearAll) } LLViewerTexLayerSet::sHasCaches = FALSE; } - LLVOAvatarSelf::deleteScratchTextures(); LLTexLayerStaticImageList::getInstance()->deleteCachedImages(); } @@ -1548,6 +1565,8 @@ void LLVOAvatar::initClass() gAnimLibrary.animStateSetString(ANIM_AGENT_WALK_ADJUST_ID,"walk_adjust"); SHClientTagMgr::instance(); //Instantiate. Parse. Will fetch a new tag file if AscentUpdateTagsOnLoad is true. + + LLControlAvatar::sRegionChangedSlot = gAgent.addRegionChangedCallback(&LLControlAvatar::onRegionChanged); } @@ -1556,7 +1575,7 @@ void LLVOAvatar::cleanupClass() } // virtual -void LLVOAvatar::initInstance(void) +void LLVOAvatar::initInstance() { //------------------------------------------------------------------------- // register motions @@ -1564,7 +1583,7 @@ void LLVOAvatar::initInstance(void) if (LLCharacter::sInstances.size() == 1) { LLKeyframeMotion::setVFS(gStaticVFS); - registerMotion( ANIM_AGENT_BUSY, LLNullMotion::create ); + registerMotion(ANIM_AGENT_DO_NOT_DISTURB, LLNullMotion::create ); registerMotion( ANIM_AGENT_CROUCH, LLKeyframeStandMotion::create ); registerMotion( ANIM_AGENT_CROUCHWALK, LLKeyframeWalkMotion::create ); registerMotion( ANIM_AGENT_EXPRESS_AFRAID, LLEmote::create ); @@ -1608,6 +1627,7 @@ void LLVOAvatar::initInstance(void) registerMotion( ANIM_AGENT_PHYSICS_MOTION_ID, LLPhysicsMotionController::create ); registerMotion( ANIM_AGENT_EDITING_ID, LLEditingMotion::create ); registerMotion( ANIM_AGENT_EYE_ID, LLEyeMotion::create ); + //registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create ); registerMotion( ANIM_AGENT_FLY_ADJUST_ID, LLFlyAdjustMotion::create ); registerMotion( ANIM_AGENT_HAND_MOTION_ID, LLHandMotion::create ); registerMotion( ANIM_AGENT_HEAD_ROT_ID, LLHeadRotMotion::create ); @@ -1619,11 +1639,6 @@ void LLVOAvatar::initInstance(void) LLAvatarAppearance::initInstance(); - if (gNoRender) - { - return; - } - // preload specific motions here createMotion( ANIM_AGENT_CUSTOMIZE); createMotion( ANIM_AGENT_CUSTOMIZE_DONE); @@ -1631,6 +1646,8 @@ void LLVOAvatar::initInstance(void) //VTPause(); // VTune mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) ); + + mInitFlags |= 1<<1; } // virtual @@ -1659,23 +1676,25 @@ LLTexLayerSet* LLVOAvatar::createTexLayerSet() const LLVector3 LLVOAvatar::getRenderPosition() const { + if (mDrawable.isNull() || mDrawable->getGeneration() < 0) { return getPositionAgent(); } - else if (isRoot() || !mDrawable->getParent()) + else if (isRoot()/* || !mDrawable->getParent()*/) // Animesh- { - if ( !mHasPelvisOffset ) - { - return mDrawable->getPositionAgent(); - } - else + F32 fixup; + if ( hasPelvisFixup( fixup) ) { //Apply a pelvis fixup (as defined by the avs skin) LLVector3 pos = mDrawable->getPositionAgent(); - pos[VZ] += mPelvisFixup; + pos[VZ] += fixup; return pos; } + else + { + return mDrawable->getPositionAgent(); + } } else { @@ -1700,6 +1719,29 @@ void LLVOAvatar::onShift(const LLVector4a& shift_vector) void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) { + if (mDrawable.isNull()) + { + return; + } + + if (mNeedsExtentUpdate) + { + calculateSpatialExtents(newMin,newMax); + mLastAnimExtents[0].set(newMin.getF32ptr()); + mLastAnimExtents[1].set(newMax.getF32ptr()); + mLastAnimBasePos = mPelvisp->getWorldPosition(); + mNeedsExtentUpdate = false; + } + else + { + LLVector3 new_base_pos = mPelvisp->getWorldPosition(); + LLVector3 shift = new_base_pos-mLastAnimBasePos; + mLastAnimExtents[0] += shift; + mLastAnimExtents[1] += shift; + mLastAnimBasePos = new_base_pos; + + } + if (isImpostor() && !needsImpostorUpdate()) { LLVector3 delta = getRenderPosition() - @@ -1710,9 +1752,8 @@ void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) } else { - getSpatialExtents(newMin,newMax); - mLastAnimExtents[0].set(newMin.getF32ptr()); - mLastAnimExtents[1].set(newMax.getF32ptr()); + newMin.load3(mLastAnimExtents[0].mV); + newMax.load3(mLastAnimExtents[1].mV); LLVector4a pos_group; pos_group.setAdd(newMin,newMax); pos_group.mul(0.5f); @@ -1721,83 +1762,139 @@ void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) } } -void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) -{ - static const LLCachedControl control_derender_huge_attachments("DerenderHugeAttachments", true); - static const LLCachedControl control_max_attachment_span("MaxAttachmentSpan", 5.0f * DEFAULT_MAX_PRIM_SCALE); - LLVector4a buffer(0.25f); - LLVector4a pos; - pos.load3(getRenderPosition().mV); - newMin.setSub(pos, buffer); - newMax.setAdd(pos, buffer); +static LLTrace::BlockTimerStatHandle FTM_AVATAR_EXTENT_UPDATE("Av Upd Extent"); - float max_attachment_span = llmax(DEFAULT_MAX_PRIM_SCALE, control_max_attachment_span); +void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) +{ - //stretch bounding box by joint positions - for (polymesh_map_t::iterator i = mPolyMeshes.begin(); i != mPolyMeshes.end(); ++i) - { - LLPolyMesh* mesh = i->second; - for (U32 joint_num = 0; joint_num < mesh->mJointRenderData.size(); joint_num++) - { - update_min_max(newMin, newMax, mesh->mJointRenderData[joint_num]->mWorldMatrix->getRow()); - } - } + LL_RECORD_BLOCK_TIME(FTM_AVATAR_EXTENT_UPDATE); - LLVector4a center, size; - center.setAdd(newMin, newMax); - center.mul(0.5f); - - size.setSub(newMax,newMin); - size.mul(0.5f); - - mPixelArea = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); + static const LLCachedControl control_derender_huge_attachments("DerenderHugeAttachments", true); + static const LLCachedControl box_detail("AvatarBoundingBoxComplexity"); + // FIXME the update_min_max function used below assumes there is a + // known starting point, but in general there isn't. Ideally the + // box update logic should be modified to handle the no-point-yet + // case. For most models, starting with the pelvis is safe though. + LLVector3 zero_pos; + LLVector4a pos; + if (dist_vec(zero_pos, mPelvisp->getWorldPosition())<0.001) + { + // Don't use pelvis until av initialized + pos.load3(getRenderPosition().mV); + } + else + { + pos.load3(mPelvisp->getWorldPosition().mV); + } + newMin = pos; + newMax = pos; + + //stretch bounding box by joint positions. Doing this for + //control avs, where the polymeshes aren't maintained or + //displayed, can give inaccurate boxes due to joints stuck at (0,0,0). + if ((box_detail >= 1) && !isControlAvatar()) + { + for (polymesh_map_t::iterator i = mPolyMeshes.begin(); i != mPolyMeshes.end(); ++i) + { + LLPolyMesh* mesh = i->second; + for (const auto& joint : mesh->mJointRenderData) + { + static const LLVector4Logical mask = _mm_load_ps((F32*)&S_V4LOGICAL_MASK_TABLE[3 * 4]); + LLVector4a trans; + trans.setSelectWithMask(mask, _mm_setzero_ps(), joint->mWorldMatrix->getRow<3>()); + update_min_max(newMin, newMax, trans); + } + } + } + + // Pad bounding box for starting joint, plus polymesh if + // applicable. Subsequent calcs should be accurate enough to not + // need padding. + LLVector4a padding(0.25); + newMin.sub(padding); + newMax.add(padding); + static std::vector removal; - //stretch bounding box by attachments - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) + //stretch bounding box by static attachments + if (box_detail >= 2) { - LLViewerJointAttachment* attachment = iter->second; - - if (!attachment->getValid()) + + float max_attachment_span = get_default_max_prim_scale() * 5.0f; +#if SLOW_ATTACHMENT_LIST + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { - continue ; - } + LLViewerJointAttachment* attachment = iter->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - const LLViewerObject* attached_object = (*attachment_iter); - if (attached_object && !attached_object->isHUDAttachment()) + if (attachment->getValid()) { - LLDrawable* drawable = attached_object->mDrawable; - if (drawable && !drawable->isState(LLDrawable::RIGGED)) + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) { - LLSpatialBridge* bridge = drawable->getSpatialBridge(); - if (bridge) + // Don't we need to look at children of attached_object as well? + const LLViewerObject* attached_object = (*attachment_iter); +#else + for(auto& iter : mAttachedObjectsVector) + {{{ + LLViewerJointAttachment* attachment = iter.second; + if (!attachment->getValid()) + continue; + const LLViewerObject* attached_object = iter.first; +#endif + if (attached_object && !attached_object->isHUDAttachment()) { - const LLVector4a* ext = bridge->getSpatialExtents(); - LLVector4a distance; - distance.setSub(ext[1], ext[0]); - LLVector4a max_span(max_attachment_span); - - S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7; - - // Only add the prim to spatial extents calculations if it isn't a megaprim. - // max_attachment_span calculated at the start of the function - // (currently 5 times our max prim size) - if (lt == 0x7) + const LLVOVolume *vol = dynamic_cast(attached_object); + if (vol && vol->isAnimatedObject()) + { + // Animated objects already have a bounding box in their control av, use that. + // Could lag by a frame if there's no guarantee on order of processing for avatars. + LLControlAvatar *cav = vol->getControlAvatar(); + if (cav) + { + LLVector4a cav_min; + cav_min.load3(cav->mLastAnimExtents[0].mV); + LLVector4a cav_max; + cav_max.load3(cav->mLastAnimExtents[1].mV); + update_min_max(newMin,newMax,cav_min); + update_min_max(newMin,newMax,cav_max); + continue; + } + } + if (vol && vol->isRiggedMesh()) { - update_min_max(newMin,newMax,ext[0]); - update_min_max(newMin,newMax,ext[1]); + continue; } - else if(control_derender_huge_attachments) + LLDrawable* drawable = attached_object->mDrawable; + if (drawable && !drawable->isState(LLDrawable::RIGGED)) { - removal.push_back((LLViewerObject *)attached_object); + LLSpatialBridge* bridge = drawable->getSpatialBridge(); + if (bridge) + { + const LLVector4a* ext = bridge->getSpatialExtents(); + LLVector4a distance; + distance.setSub(ext[1], ext[0]); + LLVector4a max_span(max_attachment_span); + + S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7; + + // Only add the prim to spatial extents calculations if it isn't a megaprim. + // max_attachment_span calculated at the start of the function + // (currently 5 times our max prim size) + if (lt == 0x7) + { + update_min_max(newMin,newMax,ext[0]); + update_min_max(newMin,newMax,ext[1]); + } + else if(control_derender_huge_attachments) + { + removal.push_back((LLViewerObject *)attached_object); + } + } } } } @@ -1815,10 +1912,87 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) removal.clear(); } - //pad bounding box - - newMin.sub(buffer); - newMax.add(buffer); + // Stretch bounding box by rigged mesh joint boxes + if (box_detail>=3 && gMeshRepo.meshRezEnabled()) + { + updateRiggingInfo(); + for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++) + { + LLJoint *joint = getJoint(joint_num); + LLJointRiggingInfo *rig_info = NULL; + if (joint_num < mJointRiggingInfoTab.size()) + { + rig_info = &mJointRiggingInfoTab[joint_num]; + } + + if (joint && rig_info && rig_info->isRiggedTo()) + { + LLViewerJointAttachment *as_joint_attach = dynamic_cast(joint); + if (as_joint_attach && as_joint_attach->getIsHUDAttachment()) + { + // Ignore bounding box of HUD joints + continue; + } + const LLMatrix4a& mat = joint->getWorldMatrix(); + LLVector4a new_extents[2]; + matMulBoundBox(mat, rig_info->getRiggedExtents(), new_extents); + update_min_max(newMin, newMax, new_extents[0]); + update_min_max(newMin, newMax, new_extents[1]); + //if (isSelf()) + //{ + // LL_INFOS() << joint->getName() << " extents " << new_extents[0] << "," << new_extents[1] << LL_ENDL; + // LL_INFOS() << joint->getName() << " av box is " << newMin << "," << newMax << LL_ENDL; + //} + } + } + } + + // Update pixel area + LLVector4a center, size; + center.setAdd(newMin, newMax); + center.mul(0.5f); + + size.setSub(newMax,newMin); + size.mul(0.5f); + + mPixelArea = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); +} + +void render_sphere_and_line(const LLVector3& begin_pos, const LLVector3& end_pos, F32 sphere_scale, const LLVector3& occ_color, const LLVector3& visible_color) +{ + // Unoccluded bone portions + LLGLDepthTest normal_depth(GL_TRUE); + + // Draw line segment for unoccluded joint + gGL.diffuseColor3f(visible_color[0], visible_color[1], visible_color[2]); + + gGL.begin(LLRender::LINES); + gGL.vertex3fv(begin_pos.mV); + gGL.vertex3fv(end_pos.mV); + gGL.end(); + + + // Draw sphere representing joint pos + gGL.pushMatrix(); + gGL.scalef(sphere_scale, sphere_scale, sphere_scale); + gSphere.renderGGL(); + gGL.popMatrix(); + + LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); + + // Occluded bone portions + gGL.diffuseColor3f(occ_color[0], occ_color[1], occ_color[2]); + + gGL.begin(LLRender::LINES); + gGL.vertex3fv(begin_pos.mV); + gGL.vertex3fv(end_pos.mV); + gGL.end(); + + // Draw sphere representing joint pos + gGL.pushMatrix(); + gGL.scalef(sphere_scale, sphere_scale, sphere_scale); + gSphere.renderGGL(); + gGL.popMatrix(); } //----------------------------------------------------------------------------- @@ -1828,10 +2002,46 @@ void LLVOAvatar::renderCollisionVolumes() { std::ostringstream ostr; LLGLDepthTest gls_depth(GL_FALSE); - for (S32 i = 0; i < (S32)mCollisionVolumes.size(); i++) + for (size_t i = 0; i < mCollisionVolumes.size(); i++) { - mCollisionVolumes[i]->renderCollision(); ostr << mCollisionVolumes[i]->getName() << ", "; + LLAvatarJointCollisionVolume& collision_volume = *mCollisionVolumes[i]; + + collision_volume.updateWorldMatrix(); + + gGL.pushMatrix(); + gGL.multMatrix( collision_volume.getXform()->getWorldMatrix() ); + + LLVector3 begin_pos(0,0,0); + LLVector3 end_pos(collision_volume.getEnd()); + static F32 sphere_scale = 1.0f; + static F32 center_dot_scale = 0.05f; + + static LLVector3 BLUE(0.0f, 0.0f, 1.0f); + static LLVector3 PASTEL_BLUE(0.5f, 0.5f, 1.0f); + static LLVector3 RED(1.0f, 0.0f, 0.0f); + static LLVector3 PASTEL_RED(1.0f, 0.5f, 0.5f); + static LLVector3 WHITE(1.0f, 1.0f, 1.0f); + + + LLVector3 cv_color_occluded; + LLVector3 cv_color_visible; + LLVector3 dot_color_occluded(WHITE); + LLVector3 dot_color_visible(WHITE); + if (isControlAvatar()) + { + cv_color_occluded = RED; + cv_color_visible = PASTEL_RED; + } + else + { + cv_color_occluded = BLUE; + cv_color_visible = PASTEL_BLUE; + } + render_sphere_and_line(begin_pos, end_pos, sphere_scale, cv_color_occluded, cv_color_visible); + render_sphere_and_line(begin_pos, end_pos, center_dot_scale, dot_color_occluded, dot_color_visible); + + gGL.popMatrix(); } if (mNameText.notNull()) @@ -1845,6 +2055,71 @@ void LLVOAvatar::renderCollisionVolumes() addDebugText(ostr.str()); } +void LLVOAvatar::renderBones() +{ + LLGLEnable blend; + + avatar_joint_list_t::iterator iter = mSkeleton.begin(); + avatar_joint_list_t::iterator end = mSkeleton.end(); + + // For bones with position overrides defined + static LLVector3 OVERRIDE_COLOR_OCCLUDED(1.0f, 0.0f, 0.0f); + static LLVector3 OVERRIDE_COLOR_VISIBLE(0.5f, 0.5f, 0.5f); + // For bones which are rigged to by at least one attachment + static LLVector3 RIGGED_COLOR_OCCLUDED(0.0f, 1.0f, 1.0f); + static LLVector3 RIGGED_COLOR_VISIBLE(0.5f, 0.5f, 0.5f); + // For bones not otherwise colored + static LLVector3 OTHER_COLOR_OCCLUDED(0.0f, 1.0f, 0.0f); + static LLVector3 OTHER_COLOR_VISIBLE(0.5f, 0.5f, 0.5f); + + static F32 SPHERE_SCALEF = 0.001f; + + for (; iter != end; ++iter) + { + LLJoint* jointp = *iter; + if (!jointp) + { + continue; + } + + jointp->updateWorldMatrix(); + + LLVector3 occ_color, visible_color; + + LLVector3 pos; + LLUUID mesh_id; + if (jointp->hasAttachmentPosOverride(pos,mesh_id)) + { + occ_color = OVERRIDE_COLOR_OCCLUDED; + visible_color = OVERRIDE_COLOR_VISIBLE; + } + else + { + if (jointIsRiggedTo(jointp)) + { + occ_color = RIGGED_COLOR_OCCLUDED; + visible_color = RIGGED_COLOR_VISIBLE; + } + else + { + occ_color = OTHER_COLOR_OCCLUDED; + visible_color = OTHER_COLOR_VISIBLE; + } + } + LLVector3 begin_pos(0,0,0); + LLVector3 end_pos(jointp->getEnd()); + + F32 sphere_scale = SPHERE_SCALEF; + + gGL.pushMatrix(); + gGL.multMatrix( jointp->getXform()->getWorldMatrix() ); + + render_sphere_and_line(begin_pos, end_pos, sphere_scale, occ_color, visible_color); + + gGL.popMatrix(); + } +} + void LLVOAvatar::renderJoints() { std::ostringstream ostr; @@ -1936,6 +2211,7 @@ void LLVOAvatar::renderJoints() BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, + BOOL pick_rigged, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, @@ -1947,6 +2223,12 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& return FALSE; } + + if (isControlAvatar()) + { + return FALSE; + } + if (lineSegmentBoundingBox(start, end)) { for (S32 i = 0; i < (S32)mCollisionVolumes.size(); ++i) @@ -1992,6 +2274,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& if (isSelf()) { +#if SLOW_ATTACHMENT_LIST for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -2003,6 +2286,12 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& ++attachment_iter) { LLViewerObject* attached_object = (*attachment_iter); +#else + for(auto& iter : mAttachedObjectsVector) + {{ + const LLViewerJointAttachment* attachment = iter.second; + const LLViewerObject* attached_object = iter.first; +#endif if (attached_object && !attached_object->isDead() && attachment->getValid()) { @@ -2018,6 +2307,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& } + LLVector4a position; if (mNameText.notNull() && mNameText->lineSegmentIntersect(start, end, position)) { @@ -2035,15 +2325,14 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, + BOOL pick_rigged, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { - static const LLCachedControl allow_mesh_picking("SGAllowRiggedMeshSelection"); - - if (!allow_mesh_picking || (isSelf() && !gAgent.needsRenderAvatar())) + if (isSelf() && !gAgent.needsRenderAvatar()) { return NULL; } @@ -2054,7 +2343,8 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector { LLVector4a local_end = end; LLVector4a local_intersection; - + +#if SLOW_ATTACHMENT_LIST for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -2066,8 +2356,13 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector ++attachment_iter) { LLViewerObject* attached_object = (*attachment_iter); - - if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, face_hit, &local_intersection, tex_coord, normal, tangent)) +#else + for(auto& iter : mAttachedObjectsVector) + {{ + LLViewerObject* attached_object = iter.first; +#endif + + if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent)) { local_end = local_intersection; if (intersection) @@ -2148,7 +2443,11 @@ void LLVOAvatar::buildCharacter() mAahMorph = getVisualParam( "Express_Open_Mouth" ); } - startDefaultMotions(); + // Currently disabled for control avatars (animated objects), enabled for all others. + if (mEnableDefaultMotions) + { + startDefaultMotions(); + } //------------------------------------------------------------------------- // restart any currently active motions @@ -2161,19 +2460,147 @@ void LLVOAvatar::buildCharacter() mMeshValid = TRUE; } +//----------------------------------------------------------------------------- +// resetVisualParams() +//----------------------------------------------------------------------------- +void LLVOAvatar::resetVisualParams() +{ + // Skeletal params + { + LLAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin(); + iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); + ++iter) + { + LLPolySkeletalDistortionInfo *info = (LLPolySkeletalDistortionInfo*)*iter; + LLPolySkeletalDistortion *param = dynamic_cast(getVisualParam(info->getID())); + *param = LLPolySkeletalDistortion(this); + llassert(param); + if (!param->setInfo(info)) + { + llassert(false); + } + } + } + + // Driver parameters + for (LLAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin(); + iter != sAvatarXmlInfo->mDriverInfoList.end(); + ++iter) + { + LLDriverParamInfo *info = *iter; + LLDriverParam *param = dynamic_cast(getVisualParam(info->getID())); + LLDriverParam::entry_list_t driven_list = param->getDrivenList(); + *param = LLDriverParam(this); + llassert(param); + if (!param->setInfo(info)) + { + llassert(false); + } + param->setDrivenList(driven_list); + } +} + +//----------------------------------------------------------------------------- +// resetSkeleton() +//----------------------------------------------------------------------------- +void LLVOAvatar::resetSkeleton(bool reset_animations) +{ + LL_DEBUGS("Avatar") << avString() << " reset starts" << LL_ENDL; + if (!isControlAvatar() && !mLastProcessedAppearance) + { + LL_WARNS() << "Can't reset avatar; no appearance message has been received yet." << LL_ENDL; + return; + } + + // Save mPelvis state + //LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition(); + //LLQuaternion pelvis_rot = getJoint("mPelvis")->getRotation(); + + // Clear all attachment pos and scale overrides + clearAttachmentOverrides(); + + // Note that we call buildSkeleton twice in this function. The first time is + // just to get the right scale for the collision volumes, because + // this will be used in setting the mJointScales for the + // LLPolySkeletalDistortions of which the CVs are children. + if( !buildSkeleton(sAvatarSkeletonInfo) ) + { + LL_ERRS() << "Error resetting skeleton" << LL_ENDL; + } + + // Reset some params to default state, without propagating changes downstream. + resetVisualParams(); + + // Now we have to reset the skeleton again, because its state + // got clobbered by the resetVisualParams() calls + // above. + if( !buildSkeleton(sAvatarSkeletonInfo) ) + { + LL_ERRS() << "Error resetting skeleton" << LL_ENDL; + } + + // Reset attachment points (buildSkeleton only does bones and CVs) + bool ignore_hud_joints = true; + initAttachmentPoints(ignore_hud_joints); + + // Fix up collision volumes + for (LLVisualParam *param = getFirstVisualParam(); + param; + param = getNextVisualParam()) + { + LLPolyMorphTarget *poly_morph = dynamic_cast(param); + if (poly_morph) + { + // This is a kludgy way to correct for the fact that the + // collision volumes have been reset out from under the + // poly morph sliders. + F32 delta_weight = poly_morph->getLastWeight() - poly_morph->getDefaultWeight(); + poly_morph->applyVolumeChanges(delta_weight); + } + } + + // Reset tweakable params to preserved state + if (mLastProcessedAppearance) + { + bool slam_params = true; + applyParsedAppearanceMessage(*mLastProcessedAppearance, slam_params); + } + updateVisualParams(); + + // Restore attachment pos overrides + updateAttachmentOverrides(); + + // Animations + if (reset_animations) + { + if (isSelf()) + { + // This is equivalent to "Stop Animating Me". Will reset + // all animations and propagate the changes to other + // viewers. + gAgent.stopCurrentAnimations(); + } + else + { + // Local viewer-side reset for non-self avatars. + resetAnimations(); + } + } + + LL_DEBUGS("Avatar") << avString() << " reset ends" << LL_ENDL; +} //----------------------------------------------------------------------------- // releaseMeshData() //----------------------------------------------------------------------------- void LLVOAvatar::releaseMeshData() { - if (sInstances.size() < AVATAR_RELEASE_THRESHOLD || mIsDummy) + if (sInstances.size() < AVATAR_RELEASE_THRESHOLD || isUIAvatar()) { return; } - //LL_DEBUGS() << "Releasing mesh data" << LL_ENDL; - // cleanup mesh data for (avatar_joint_list_t::iterator iter = mMeshLOD.begin(); iter != mMeshLOD.end(); @@ -2221,6 +2648,10 @@ void LLVOAvatar::releaseMeshData() void LLVOAvatar::restoreMeshData() { llassert(!isSelf()); + if (mDrawable.isNull()) + { + return; + } //LL_INFOS() << "Restoring" << LL_ENDL; mMeshValid = TRUE; @@ -2399,9 +2830,6 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, } } - //LL_INFOS() << getRotation() << LL_ENDL; - //LL_INFOS() << getPosition() << LL_ENDL; - return retval; } @@ -2414,24 +2842,29 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU uuid == IMG_INVISIBLE) { // Should already exist, don't need to find it on sim or baked-texture host. - result = gTextureList.findImage(uuid); + result = gTextureList.findImage(uuid, TEX_LIST_STANDARD); } if (!result) { const std::string url = getImageURL(te,uuid); + if (!url.empty()) { - LL_DEBUGS("Avatar") << avString() << "from URL " << url << LL_ENDL; + LL_DEBUGS("Avatar") << avString() << "get server-bake image from URL " << url << LL_ENDL; result = LLViewerTextureManager::getFetchedTextureFromUrl( - url, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); + url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); + if (result->isMissingAsset()) + { + result->setIsMissingAsset(false); + } } else { LL_DEBUGS("Avatar") << avString() << "from host " << uuid << LL_ENDL; LLHost host = getObjectHost(); result = LLViewerTextureManager::getFetchedTexture( - uuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); + uuid, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } } return result; @@ -2490,7 +2923,7 @@ void LLVOAvatar::dumpAnimationState() //------------------------------------------------------------------------ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - LLFastTimer t(FTM_AVATAR_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_AVATAR_UPDATE); if (isDead()) { @@ -2503,6 +2936,18 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return; } + // Update should be happening max once per frame. + const S32 upd_freq = 4; // force update every upd_freq frames. + if ((mLastAnimExtents[0]==LLVector3())|| + (mLastAnimExtents[1])==LLVector3()) + { + mNeedsExtentUpdate = true; + } + else + { + mNeedsExtentUpdate = ((LLDrawable::getCurrentFrame()+mID.mData[0])%upd_freq==0); + } + checkTextureLoading() ; // force immediate pixel area update on avatars using last frames data (before drawable or camera updates) @@ -2511,9 +2956,9 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // force asynchronous drawable update if(mDrawable.notNull() && !gNoRender) { - LLFastTimer t(FTM_JOINT_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_JOINT_UPDATE); - if (mIsSitting && getParent()) + if (isSitting() && getParent()) { LLViewerObject *root_object = (LLViewerObject*)getRoot(); LLDrawable* drawablep = root_object->mDrawable; @@ -2543,7 +2988,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) if (isSelf()) { { - LLFastTimer t(FTM_BASE_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_BASE_UPDATE); LLViewerObject::idleUpdate(agent, world, time); } @@ -2558,7 +3003,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // Should override the idleUpdate stuff and leave out the angular update part. LLQuaternion rotation = getRotation(); { - LLFastTimer t(FTM_BASE_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_BASE_UPDATE); LLViewerObject::idleUpdate(agent, world, time); } setRotation(rotation); @@ -2569,10 +3014,10 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // animate the character // store off last frame's root position to be consistent with camera position - LLVector3 root_pos_last = mRoot->getWorldPosition(); + mLastRootPos = mRoot->getWorldPosition(); bool detailed_update; { - LLFastTimer t(FTM_CHARACTER_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_CHARACTER_UPDATE); detailed_update = updateCharacter(agent); } if (gNoRender) @@ -2584,23 +3029,21 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) bool voice_enabled = (visualizers_in_calls || LLVoiceClient::getInstance()->inProximalChannel()) && LLVoiceClient::getInstance()->getVoiceEnabled(mID); + LL_RECORD_BLOCK_TIME(FTM_MISC_UPDATE); + idleUpdateVoiceVisualizer(voice_enabled); + idleUpdateMisc(detailed_update); + idleUpdateAppearanceAnimation(); + if (detailed_update) { - LLFastTimer t(FTM_MISC_UPDATE); - idleUpdateVoiceVisualizer(voice_enabled); - idleUpdateMisc(detailed_update); - idleUpdateAppearanceAnimation(); - if (detailed_update) - { - LLFastTimer t(FTM_DETAIL_UPDATE); - idleUpdateLipSync(voice_enabled); - idleUpdateLoadingEffect(); - idleUpdateBelowWater(); // wind effect uses this - idleUpdateWindEffect(); - } - - idleUpdateNameTag(root_pos_last); - idleUpdateRenderCost(); + LL_RECORD_BLOCK_TIME(FTM_DETAIL_UPDATE); + idleUpdateLipSync(voice_enabled); + idleUpdateLoadingEffect(); + idleUpdateBelowWater(); // wind effect uses this + idleUpdateWindEffect(); } + + idleUpdateNameTag(mLastRootPos); + idleUpdateRenderComplexity(); } void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) @@ -2703,7 +3146,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) // (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing) //-------------------------------------------------------------------------------------------- - if ( mIsSitting ) + if ( isSitting() ) { LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] ); mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot->getWorldPosition() + headOffset ); @@ -2735,8 +3178,9 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) // update attachments positions if (detailed_update || !sUseImpostors) { - LLFastTimer t(FTM_ATTACHMENT_UPDATE); - /*for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + LL_RECORD_BLOCK_TIME(FTM_ATTACHMENT_UPDATE); +#if SLOW_ATTACHMENT_LIST + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) { @@ -2746,25 +3190,19 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { - LLViewerObject* attached_object = (*attachment_iter);*/ - std::vector >::iterator attachment_iter = mAttachedObjectsVector.begin(); - for(;attachment_iter!=mAttachedObjectsVector.end();++attachment_iter) + LLViewerObject* attached_object = (*attachment_iter); +#else + for(auto& iter : mAttachedObjectsVector) {{ - LLViewerJointAttachment* attachment = attachment_iter->second; - LLViewerObject* attached_object = attachment_iter->first; - - if( !attached_object || - attached_object->isDead() || - !attached_object->mDrawable || - !attachment || - !attachment->getValid()) - continue; - - BOOL visibleAttachment = visible || - !attached_object->mDrawable->getSpatialBridge() || - attached_object->mDrawable->getSpatialBridge()->getRadius() >= 2.f; + LLViewerJointAttachment* attachment = iter.second; + LLViewerObject* attached_object = iter.first; +#endif + + BOOL visibleAttachment = visible || (attached_object && + !(attached_object->mDrawable->getSpatialBridge() && + attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0)); - if (visibleAttachment) + if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid()) { // if selecting any attachments, update all of them as non-damped if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment()) @@ -2820,8 +3258,10 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) } else { - //VECTORIZE THIS - getSpatialExtents(ext[0], ext[1]); + ext[0].load3(mLastAnimExtents[0].mV); + ext[1].load3(mLastAnimExtents[1].mV); + // Expensive. Just call this once per frame, in updateSpatialExtents(); + //calculateSpatialExtents(ext[0], ext[1]); LLVector4a diff; diff.setSub(ext[1], mImpostorExtents[1]); if (diff.getLength3().getF32() > 0.05f) @@ -2840,7 +3280,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) } } - if(mDrawable) + if (mDrawable.notNull()) { mDrawable->movePartition(); @@ -2968,19 +3408,22 @@ void LLVOAvatar::idleUpdateLoadingEffect() // update visibility when avatar is partially loaded if (updateIsFullyLoaded()) // changed? { - if (isFullyLoaded() && mFirstFullyVisible && isSelf()) - { - LL_INFOS("Avatar") << avString() << "self isFullyLoaded, mFirstFullyVisible" << LL_ENDL; - mFirstFullyVisible = FALSE; - LLAppearanceMgr::instance().onFirstFullyVisible(); - } - if (isFullyLoaded() && mFirstFullyVisible && !isSelf()) - { - LL_INFOS("Avatar") << avString() << "other isFullyLoaded, mFirstFullyVisible" << LL_ENDL; - mFirstFullyVisible = FALSE; - } if (isFullyLoaded()) { + if (mFirstFullyVisible) + { + mFirstFullyVisible = FALSE; + if (isSelf()) + { + LL_INFOS("Avatar") << avString() << "self isFullyLoaded, mFirstFullyVisible" << LL_ENDL; + LLAppearanceMgr::instance().onFirstFullyVisible(); + } + else + { + LL_INFOS("Avatar") << avString() << "other isFullyLoaded, mFirstFullyVisible" << LL_ENDL; + } + } + deleteParticleSource(); updateLOD(); } @@ -3013,7 +3456,7 @@ void LLVOAvatar::idleUpdateLoadingEffect() LLPartData::LL_PART_EMISSIVE_MASK | // LLPartData::LL_PART_FOLLOW_SRC_MASK | LLPartData::LL_PART_TARGET_POS_MASK ); - if (!isTooComplex()) // do not generate particles for overly-complex avatars + if (!mIsDummy && !isTooComplex()) { setParticleSource(particle_parameters, getID()); } @@ -3033,7 +3476,7 @@ void LLVOAvatar::idleUpdateWindEffect() LLVector3 velocity = getVelocity(); F32 speed = velocity.length(); //RN: velocity varies too much frame to frame for this to work - mRippleAccel.clearVec();//lerp(mRippleAccel, (velocity - mLastVel) * time_delta, LLCriticalDamp::getInterpolant(0.02f)); + mRippleAccel.clearVec();//lerp(mRippleAccel, (velocity - mLastVel) * time_delta, LLSmoothInterpolation::getInterpolant(0.02f)); mLastVel = velocity; LLVector4 wind; wind.setVec(getRegion()->mWind.getVelocityNoisy(getPositionAgent(), 4.f) - velocity); @@ -3056,11 +3499,11 @@ void LLVOAvatar::idleUpdateWindEffect() F32 interp; if (wind.mV[VW] > mWindVec.mV[VW]) { - interp = LLCriticalDamp::getInterpolant(0.2f); + interp = LLSmoothInterpolation::getInterpolant(0.2f); } else { - interp = LLCriticalDamp::getInterpolant(0.4f); + interp = LLSmoothInterpolation::getInterpolant(0.4f); } mWindVec = lerp(mWindVec, wind, interp); @@ -3318,7 +3761,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) bool fRlvShowNames = gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES); // [/RLVa:KB] bool is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); - bool is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end(); + bool is_busy = mSignaledAnimations.find(ANIM_AGENT_DO_NOT_DISTURB) != mSignaledAnimations.end(); bool is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); bool is_muted; if (isSelf()) @@ -3699,10 +4142,7 @@ void LLVOAvatar::clearNameTag() //static void LLVOAvatar::invalidateNameTag(const LLUUID& agent_id) { - LLViewerObject* obj = gObjectList.findObject(agent_id); - if (!obj) return; - - LLVOAvatar* avatar = dynamic_cast(obj); + LLVOAvatar* avatar = gObjectList.findAvatar(agent_id); if (!avatar) return; avatar->clearNameTag(); @@ -3726,24 +4166,38 @@ void LLVOAvatar::invalidateNameTags() LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) { LLQuaternion root_rot = mRoot->getWorldRotation(); + LLQuaternion inv_root_rot = ~root_rot; LLVector3 pixel_right_vec; LLVector3 pixel_up_vec; LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec); LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin(); camera_to_av.normalize(); - LLVector3 local_camera_at = camera_to_av * ~root_rot; + LLVector3 local_camera_at = camera_to_av * inv_root_rot; LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis(); local_camera_up.normalize(); - local_camera_up = local_camera_up * ~root_rot; + local_camera_up = local_camera_up * inv_root_rot; + - local_camera_up.scaleVec((mBodySize + mAvatarOffset) * 0.5f); - local_camera_at.scaleVec((mBodySize + mAvatarOffset) * 0.5f); + // position is based on head position, does not require mAvatarOffset here. - Nyx + LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f, + mBodySize.mV[VY] * 0.4f, + mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT); - LLVector3 name_position = mRoot->getWorldPosition(); - name_position[VZ] -= mPelvisToFoot; - name_position[VZ] += ((mBodySize[VZ] + mAvatarOffset[VZ])* 0.55f); + local_camera_up.scaleVec(avatar_ellipsoid); + local_camera_at.scaleVec(avatar_ellipsoid); + + LLVector3 head_offset = (mHeadp->getLastWorldPosition() - mRoot->getLastWorldPosition()) * inv_root_rot; + + if (dist_vec(head_offset, mTargetRootToHeadOffset) > NAMETAG_UPDATE_THRESHOLD) + { + mTargetRootToHeadOffset = head_offset; + } + + mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLSmoothInterpolation::getInterpolant(0.2f)); + + LLVector3 name_position = mRoot->getLastWorldPosition() + (mCurRootToHeadOffset * root_rot); name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av)); - name_position += pixel_up_vec * 15.f; + name_position += pixel_up_vec * NAMETAG_VERTICAL_SCREEN_OFFSET; return name_position; } @@ -3798,7 +4252,11 @@ void LLVOAvatar::idleUpdateBelowWater() F32 water_height; water_height = getRegion()->getWaterHeight(); + BOOL old_below = mBelowWater; mBelowWater = avatar_height < water_height; + if (old_below != mBelowWater) + if (auto ao = AOSystem::getIfExists()) + ao->toggleSwim(mBelowWater); } void LLVOAvatar::slamPosition() @@ -3815,23 +4273,17 @@ void LLVOAvatar::slamPosition() bool LLVOAvatar::isVisuallyMuted() const { - bool muted = false; - if (!isSelf()) { - static LLCachedControl max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit", 0); - static LLCachedControl max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 0.0); static const LLCachedControl show_muted(gSavedSettings, "LiruLegacyDisplayMuteds", false); - - muted = (!show_muted && LLMuteList::getInstance()->isMuted(getID())) || - (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || - (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) || + return (!show_muted && LLMuteList::getInstance()->isMuted(getID()) || // [RLVa:LF] - RLV 2.9 camavdist (gRlvHandler.hasBehaviour(RLV_BHVR_CAMAVDIST) && (gAgent.getPosGlobalFromAgent(const_cast(*this).getCharacterPosition()) - gAgent.getPosGlobalFromAgent(gAgentAvatarp->getRenderPosition())).magVec() > gRlvHandler.camPole(RLV_BHVR_CAMAVDIST)) || // [/RLVa:LF] - isLangolier(); + isLangolier() || + isTooComplex()); } - return muted; + return false; } void LLVOAvatar::resetFreezeTime() @@ -3845,165 +4297,325 @@ void LLVOAvatar::resetFreezeTime() } -//------------------------------------------------------------------------ -// updateCharacter() -// called on both your avatar and other avatars -//------------------------------------------------------------------------ -BOOL LLVOAvatar::updateCharacter(LLAgent &agent) +void LLVOAvatar::updateAppearanceMessageDebugText() { - // Frozen! - if (areAnimationsPaused()) + S32 central_bake_version = -1; + LLViewerRegion* region = getRegion(); + if (region) + { + central_bake_version = getRegion()->getCentralBakeVersion(); + } + bool all_baked_downloaded = allBakedTexturesCompletelyDownloaded(); + bool all_local_downloaded = allLocalTexturesCompletelyDownloaded(); + std::string debug_line = llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d", + isSelf() ? (all_local_downloaded ? "L" : "l") : "-", + all_baked_downloaded ? "B" : "b", + mUseLocalAppearance, mIsEditingAppearance, + mUseServerBakes, central_bake_version); + std::string origin_string = bakedTextureOriginInfo(); + debug_line += " [" + origin_string + "]"; + S32 curr_cof_version = LLAppearanceMgr::instance().getCOFVersion(); + S32 last_request_cof_version = mLastUpdateRequestCOFVersion; + S32 last_received_cof_version = mLastUpdateReceivedCOFVersion; + if (isSelf()) { - updateMotions(LLCharacter::NORMAL_UPDATE); // This is necessary to get unpaused again. - return FALSE; + debug_line += llformat(" - cof: %d req: %d rcv:%d", + curr_cof_version, last_request_cof_version, last_received_cof_version); + } + else + { + debug_line += llformat(" - cof rcv:%d", last_received_cof_version); + } + debug_line += llformat(" bsz-z: %.3f", mBodySize[2]); + if (mAvatarOffset[2] != 0.0f) + { + debug_line += llformat("avofs-z: %.3f", mAvatarOffset[2]); } + bool hover_enabled = region && region->avatarHoverHeightEnabled(); + debug_line += hover_enabled ? " H" : " h"; + const LLVector3& hover_offset = getHoverOffset(); + if (hover_offset[2] != 0.0) + { + debug_line += llformat(" hov_z: %.3f", hover_offset[2]); + debug_line += llformat(" %s", (isSitting() ? "S" : "T")); + debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-")); + } + LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition(); + LLVector3 normal; + LLVector3 ankle_right_ground_agent = ankle_right_pos_agent; + resolveHeightAgent(ankle_right_pos_agent, ankle_right_ground_agent, normal); + F32 rightElev = llmax(-0.2f, ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]); + debug_line += llformat(" relev %.3f", rightElev); - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + LLVector3 root_pos = mRoot->getPosition(); + LLVector3 pelvis_pos = mPelvisp->getPosition(); + debug_line += llformat(" rp %.3f pp %.3f", root_pos[2], pelvis_pos[2]); + + S32 is_visible = (S32) isVisible(); + S32 is_m_visible = (S32) mVisible; + debug_line += llformat(" v %d/%d", is_visible, is_m_visible); + F32 elapsed = mLastAppearanceMessageTimer.getElapsedTimeF32(); + static const char *elapsed_chars = "Xx*..."; + U32 bucket = U32(elapsed*2); + if (bucket < strlen(elapsed_chars)) { - S32 central_bake_version = -1; - LLViewerRegion* region = getRegion(); - if (region) - { - central_bake_version = getRegion()->getCentralBakeVersion(); - } - bool all_baked_downloaded = allBakedTexturesCompletelyDownloaded(); - bool all_local_downloaded = allLocalTexturesCompletelyDownloaded(); - std::string debug_line = llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d", - isSelf() ? (all_local_downloaded ? "L" : "l") : "-", - all_baked_downloaded ? "B" : "b", - mUseLocalAppearance, mIsEditingAppearance, - mUseServerBakes, central_bake_version); - std::string origin_string = bakedTextureOriginInfo(); - debug_line += " [" + origin_string + "]"; - S32 curr_cof_version = LLAppearanceMgr::instance().getCOFVersion(); - S32 last_request_cof_version = mLastUpdateRequestCOFVersion; - S32 last_received_cof_version = mLastUpdateReceivedCOFVersion; - if (isSelf()) - { - debug_line += llformat(" - cof: %d req: %d rcv:%d", - curr_cof_version, last_request_cof_version, last_received_cof_version); - } - else - { - debug_line += llformat(" - cof rcv:%d", last_received_cof_version); - } - debug_line += llformat(" bsz-z: %f avofs-z: %f", mBodySize[2], mAvatarOffset[2]); - bool hover_enabled = region && region->avatarHoverHeightEnabled(); - debug_line += hover_enabled ? " H" : " h"; - const LLVector3& hover_offset = getHoverOffset(); - if (hover_offset[2] != 0.0) - { - debug_line += llformat(" hov_z: %f", hover_offset[2]); - debug_line += llformat(" %s", (mIsSitting ? "S" : "T")); - debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-")); - } - F32 elapsed = mLastAppearanceMessageTimer.getElapsedTimeF32(); - static const char *elapsed_chars = "Xx*..."; - U32 bucket = U32(elapsed*2); - if (bucket < strlen(elapsed_chars)) - { - debug_line += llformat(" %c", elapsed_chars[bucket]); - } - addDebugText(debug_line); + debug_line += llformat(" %c", elapsed_chars[bucket]); } - if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) + addDebugText(debug_line); +} + +LLViewerInventoryItem* getObjectInventoryItem(LLViewerObject *vobj, LLUUID asset_id) +{ + LLViewerInventoryItem *item = NULL; + + if (vobj) { - if (!mBakedTextureDebugText.empty()) - addDebugText(mBakedTextureDebugText); + if (vobj->getInventorySerial() <= 0) + { + vobj->requestInventory(); + } + item = vobj->getInventoryItemByAsset(asset_id); } + return item; +} - if (LLVOAvatar::sShowAnimationDebug) +LLViewerInventoryItem* recursiveGetObjectInventoryItem(LLViewerObject *vobj, LLUUID asset_id) +{ + LLViewerInventoryItem *item = getObjectInventoryItem(vobj, asset_id); + if (!item) { - addDebugText(llformat("at=%.1f", mMotionController.getAnimTime())); - for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin(); - iter != mMotionController.getActiveMotions().end(); ++iter) + LLViewerObject::const_child_list_t& children = vobj->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); + it != children.end(); ++it) { - LLMotion* motionp = *iter; - if (motionp->getMinPixelArea() < getPixelArea()) + LLViewerObject *childp = *it; + item = getObjectInventoryItem(childp, asset_id); + if (item) { - std::string output; - if (motionp->getName().empty()) - { - output = llformat("%s - %d", - motionp->getID().asString().c_str(), - (U32)motionp->getPriority()); - } - else + break; + } + } + } + return item; +} + +void LLVOAvatar::updateAnimationDebugText() +{ + addDebugText(llformat("at=%.1f", mMotionController.getAnimTime())); + for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin(); + iter != mMotionController.getActiveMotions().end(); ++iter) + { + LLMotion* motionp = *iter; + if (motionp->getMinPixelArea() < getPixelArea()) + { + std::string output; + std::string motion_name = motionp->getName(); + if (motion_name.empty()) + { + if (isControlAvatar()) { - output = llformat("%s - %d", - motionp->getName().c_str(), - (U32)motionp->getPriority()); + LLControlAvatar *control_av = dynamic_cast(this); + // Try to get name from inventory of associated object + LLVOVolume *volp = control_av->mRootVolp; + LLViewerInventoryItem *item = recursiveGetObjectInventoryItem(volp, motionp->getID()); + if (item) + { + motion_name = item->getName(); + } } - if (motionp->server()) - { + } + if (motion_name.empty()) + { + std::string name; + name = motionp->getID().asString(); + output = llformat("%s - %d", + name.c_str(), + (U32)motionp->getPriority()); + } + else + { + output = llformat("%s - %d", + motion_name.c_str(), + (U32)motionp->getPriority()); + } + if (motionp->server()) + { #ifdef SHOW_ASSERT - output += llformat(" rt=%.1f r=%d s=0x%xl", motionp->getRuntime(), motionp->mReadyEvents, motionp->server()); + output += llformat(" rt=%.1f r=%d s=0x%xl", motionp->getRuntime(), motionp->mReadyEvents, motionp->server()); #else - output += llformat(" rt=%.1f s=0x%xl", motionp->getRuntime(), motionp->server()); + output += llformat(" rt=%.1f s=0x%xl", motionp->getRuntime(), motionp->server()); #endif - } - addDebugText(output); } + addDebugText(output); } } +} - if (gNoRender) +void LLVOAvatar::updateDebugText() +{ + // Leave mDebugText uncleared here, in case a derived class has added some state first + + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { - // Hack if we're running drones... - if (isSelf()) - { - gAgent.setPositionAgent(getPositionAgent()); - } - return FALSE; + updateAppearanceMessageDebugText(); } + if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) + { + if (!mBakedTextureDebugText.empty()) + addDebugText(mBakedTextureDebugText); + } - LLVector3d root_pos_global; + // Develop -> Avatar -> Animation Info + if (LLVOAvatar::sShowAnimationDebug) + { + updateAnimationDebugText(); + } - if (!mIsBuilt) + if (!mDebugText.size() && mText.notNull()) { - return FALSE; + mText->markDead(); + mText = NULL; + } + else if (mDebugText.size()) + { + setDebugText(mDebugText); } + mDebugText.clear(); - BOOL visible = isVisible(); +} - // For fading out the names above heads, only let the timer - // run if we're visible. - if (mDrawable.notNull() && !visible) +//------------------------------------------------------------------------ +// updateFootstepSounds +// Factored out from updateCharacter() +// Generate footstep sounds when feet hit the ground +//------------------------------------------------------------------------ +void LLVOAvatar::updateFootstepSounds() +{ + if (mIsDummy) { - mTimeVisible.reset(); + return; } - //-------------------------------------------------------------------- - // the rest should only be done occasionally for far away avatars - //-------------------------------------------------------------------- + //------------------------------------------------------------------------- + // Find the ground under each foot, these are used for a variety + // of things that follow + //------------------------------------------------------------------------- + LLVector3 ankle_left_pos_agent = mFootLeftp->getWorldPosition(); + LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition(); + + LLVector3 ankle_left_ground_agent = ankle_left_pos_agent; + LLVector3 ankle_right_ground_agent = ankle_right_pos_agent; + LLVector3 normal; + resolveHeightAgent(ankle_left_pos_agent, ankle_left_ground_agent, normal); + resolveHeightAgent(ankle_right_pos_agent, ankle_right_ground_agent, normal); + F32 leftElev = llmax(-0.2f, ankle_left_pos_agent.mV[VZ] - ankle_left_ground_agent.mV[VZ]); + F32 rightElev = llmax(-0.2f, ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]); + + if (!isSitting()) + { + //------------------------------------------------------------------------- + // Figure out which foot is on ground + //------------------------------------------------------------------------- + if (!mInAir) + { + if ((leftElev < 0.0f) || (rightElev < 0.0f)) + { + ankle_left_pos_agent = mFootLeftp->getWorldPosition(); + ankle_right_pos_agent = mFootRightp->getWorldPosition(); + leftElev = ankle_left_pos_agent.mV[VZ] - ankle_left_ground_agent.mV[VZ]; + rightElev = ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]; + } + } + } + + //------------------------------------------------------------------------- + // Generate footstep sounds when feet hit the ground + //------------------------------------------------------------------------- + const LLUUID AGENT_FOOTSTEP_ANIMS[] = {ANIM_AGENT_WALK, ANIM_AGENT_RUN, ANIM_AGENT_LAND}; + const S32 NUM_AGENT_FOOTSTEP_ANIMS = LL_ARRAY_SIZE(AGENT_FOOTSTEP_ANIMS); + + if ( gAudiop && isAnyAnimationSignaled(AGENT_FOOTSTEP_ANIMS, NUM_AGENT_FOOTSTEP_ANIMS) ) + { + BOOL playSound = FALSE; + LLVector3 foot_pos_agent; + + BOOL onGroundLeft = (leftElev <= 0.05f); + BOOL onGroundRight = (rightElev <= 0.05f); + + // did left foot hit the ground? + if ( onGroundLeft && !mWasOnGroundLeft ) + { + foot_pos_agent = ankle_left_pos_agent; + playSound = TRUE; + } + + // did right foot hit the ground? + if ( onGroundRight && !mWasOnGroundRight ) + { + foot_pos_agent = ankle_right_pos_agent; + playSound = TRUE; + } + + mWasOnGroundLeft = onGroundLeft; + mWasOnGroundRight = onGroundRight; + + if ( playSound ) + { + const F32 STEP_VOLUME = 0.5f; + const LLUUID& step_sound_id = getStepSound(); + + LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent); + + if (LLViewerParcelMgr::getInstance()->canHearSound(foot_pos_global) + && !LLMuteList::getInstance()->isMuted(getID(), LLMute::flagObjectSounds)) + { + gAudiop->triggerSound(step_sound_id, getID(), STEP_VOLUME, LLAudioEngine::AUDIO_TYPE_AMBIENT, foot_pos_global); + } + } + } +} + +//------------------------------------------------------------------------ +// computeUpdatePeriod() +// Factored out from updateCharacter() +// Set new value for mUpdatePeriod based on distance and various other factors. +//------------------------------------------------------------------------ +void LLVOAvatar::computeUpdatePeriod() +{ bool visually_muted = isVisuallyMuted(); - if (visible && (!isSelf() || visually_muted) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter) + if (mDrawable.notNull() + && isVisible() + && (!isSelf() || visually_muted) + && !isUIAvatar() + && sUseImpostors + && !mNeedsAnimUpdate + && !sFreezeCounter) { const LLVector4a* ext = mDrawable->getSpatialExtents(); LLVector4a size; size.setSub(ext[1],ext[0]); F32 mag = size.getLength3().getF32()*0.5f; - + F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f); if (visually_muted) { // visually muted avatars update at 16 hz mUpdatePeriod = 16; } - else if (mVisibilityRank <= LLVOAvatar::sMaxVisible || - mDrawable->mDistanceWRTCamera < 1.f + mag) - { //first 25% of max visible avatars are not impostored - //also, don't impostor avatars whose bounding box may be penetrating the - //impostor camera near clip plane + else if (! shouldImpostor() + || mDrawable->mDistanceWRTCamera < 1.f + mag) + { // first 25% of max visible avatars are not impostored + // also, don't impostor avatars whose bounding box may be penetrating the + // impostor camera near clip plane mUpdatePeriod = 1; } - else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 4) + else if ( shouldImpostor(4) ) { //background avatars are REALLY slow updating impostors mUpdatePeriod = 16; } - else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 3) + else if ( shouldImpostor(3) ) { //back 25% of max visible avatars are slow updating impostors mUpdatePeriod = 8; } @@ -4016,26 +4628,193 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) //nearby avatars, update the impostors more frequently. mUpdatePeriod = 4; } - - visible = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0 ? TRUE : FALSE; } else { mUpdatePeriod = 1; } +} +//------------------------------------------------------------------------ +// updateOrientation() +// Factored out from updateCharacter() +// This is used by updateCharacter() to update the avatar's orientation: +// - updates mTurning state +// - updates rotation of the mRoot joint in the skeleton +// - for self, calls setControlFlags() to notify the simulator about any turns +//------------------------------------------------------------------------ +void LLVOAvatar::updateOrientation(LLAgent& agent, F32 speed, F32 delta_time) +{ + LLQuaternion iQ; + LLVector3 upDir( 0.0f, 0.0f, 1.0f ); + + // Compute a forward direction vector derived from the primitive rotation + // and the velocity vector. When walking or jumping, don't let body deviate + // more than 90 from the view, if necessary, flip the velocity vector. - // don't early out for your own avatar, as we rely on your animations playing reliably - // for example, the "turn around" animation when entering customize avatar needs to trigger - // even when your avatar is offscreen - if (!visible && !isSelf()) + LLVector3 primDir; + if (isSelf()) { - updateMotions(LLCharacter::HIDDEN_UPDATE); - return FALSE; + primDir = agent.getAtAxis() - projected_vec(agent.getAtAxis(), agent.getReferenceUpVector()); + primDir.normalize(); + } + else + { + primDir = getRotation().getMatrix3().getFwdRow(); + } + LLVector3 velDir = getVelocity(); + velDir.normalize(); + static LLCachedControl TurnAround("TurnAroundWhenWalkingBackwards"); + if (!TurnAround && (mSignaledAnimations.find(ANIM_AGENT_WALK) != mSignaledAnimations.end())) + { + F32 vpD = velDir * primDir; + if (vpD < -0.5f) + { + velDir *= -1.0f; + } + } + LLVector3 fwdDir = lerp(primDir, velDir, clamp_rescale(speed, 0.5f, 2.0f, 0.0f, 1.0f)); + if (isSelf() && gAgentCamera.cameraMouselook()) + { + // make sure fwdDir stays in same general direction as primdir + if (gAgent.getFlying()) + { + fwdDir = LLViewerCamera::getInstance()->getAtAxis(); + } + else + { + LLVector3 at_axis = LLViewerCamera::getInstance()->getAtAxis(); + LLVector3 up_vector = gAgent.getReferenceUpVector(); + at_axis -= up_vector * (at_axis * up_vector); + at_axis.normalize(); + + F32 dot = fwdDir * at_axis; + if (dot < 0.f) + { + fwdDir -= 2.f * at_axis * dot; + fwdDir.normalize(); + } + } + } - // change animation time quanta based on avatar render load - if (!isSelf() && !mIsDummy) + LLQuaternion root_rotation = LLMatrix4(mRoot->getWorldMatrix().getF32ptr()).quaternion(); + F32 root_roll, root_pitch, root_yaw; + root_rotation.getEulerAngles(&root_roll, &root_pitch, &root_yaw); + + if (sDebugAvatarRotation) + { + LL_INFOS() << "root_roll " << RAD_TO_DEG * root_roll + << " root_pitch " << RAD_TO_DEG * root_pitch + << " root_yaw " << RAD_TO_DEG * root_yaw + << LL_ENDL; + } + + // When moving very slow, the pelvis is allowed to deviate from the + // forward direction to allow it to hold it's position while the torso + // and head turn. Once in motion, it must conform however. + BOOL self_in_mouselook = isSelf() && gAgentCamera.cameraMouselook(); + + LLVector3 pelvisDir( mRoot->getWorldMatrix().getRow().getF32ptr() ); + + static const LLCachedControl s_pelvis_rot_threshold_slow(gSavedSettings, "AvatarRotateThresholdSlow", 60.0); + static const LLCachedControl s_pelvis_rot_threshold_fast(gSavedSettings, "AvatarRotateThresholdFast", 2.0); + static const LLCachedControl useRealisticMouselook("UseRealisticMouselook"); + F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, useRealisticMouselook ? s_pelvis_rot_threshold_slow * 2 : s_pelvis_rot_threshold_slow, s_pelvis_rot_threshold_fast); + + if (self_in_mouselook && !useRealisticMouselook) + { + pelvis_rot_threshold *= MOUSELOOK_PELVIS_FOLLOW_FACTOR; + } + pelvis_rot_threshold *= DEG_TO_RAD; + + F32 angle = angle_between( pelvisDir, fwdDir ); + + // The avatar's root is allowed to have a yaw that deviates widely + // from the forward direction, but if roll or pitch are off even + // a little bit we need to correct the rotation. + if(root_roll < 1.f * DEG_TO_RAD + && root_pitch < 5.f * DEG_TO_RAD) + { + // smaller correction vector means pelvis follows prim direction more closely + if (!mTurning && angle > pelvis_rot_threshold*0.75f) + { + mTurning = TRUE; + } + + // use tighter threshold when turning + if (mTurning) + { + pelvis_rot_threshold *= 0.4f; + } + + // am I done turning? + if (angle < pelvis_rot_threshold) + { + mTurning = FALSE; + } + + LLVector3 correction_vector = (pelvisDir - fwdDir) * clamp_rescale(angle, pelvis_rot_threshold*0.75f, pelvis_rot_threshold, 1.0f, 0.0f); + fwdDir += correction_vector; + } + else + { + mTurning = FALSE; + } + + // Now compute the full world space rotation for the whole body (wQv) + LLVector3 leftDir = upDir % fwdDir; + leftDir.normalize(); + fwdDir = leftDir % upDir; + LLQuaternion wQv( fwdDir, leftDir, upDir ); + + if (isSelf() && mTurning) + { + if ((fwdDir % pelvisDir) * upDir > 0.f) + { + gAgent.setControlFlags(AGENT_CONTROL_TURN_RIGHT); + } + else + { + gAgent.setControlFlags(AGENT_CONTROL_TURN_LEFT); + } + } + + // Set the root rotation, but do so incrementally so that it + // lags in time by some fixed amount. + //F32 u = LLSmoothInterpolation::getInterpolant(PELVIS_LAG); + F32 pelvis_lag_time = 0.f; + if (self_in_mouselook) + { + pelvis_lag_time = PELVIS_LAG_MOUSELOOK; + } + else if (mInAir) + { + pelvis_lag_time = PELVIS_LAG_FLYING; + // increase pelvis lag time when moving slowly + pelvis_lag_time *= clamp_rescale(mSpeedAccum, 0.f, 15.f, 3.f, 1.f); + } + else + { + pelvis_lag_time = PELVIS_LAG_WALKING; + } + +F32 u = llclamp((delta_time / pelvis_lag_time), 0.0f, 1.0f); + + mRoot->setWorldRotation( slerp(u, mRoot->getWorldRotation(), wQv) ); +} + +//------------------------------------------------------------------------ +// updateTimeStep() +// Factored out from updateCharacter(). +// +// Updates the time step used by the motion controller, based on area +// and avatar count criteria. This will also stop the +// ANIM_AGENT_WALK_ADJUST animation under some circumstances. +// ------------------------------------------------------------------------ +void LLVOAvatar::updateTimeStep() +{ + if (!isSelf() && !isUIAvatar()) // ie, non-self avatars, and animated objects will be affected. { F32 time_quantum = clamp_rescale((F32)sInstances.size(), 10.f, 35.f, 0.f, 0.25f); F32 pixel_area_scale = clamp_rescale(mPixelArea, 100, 5000, 1.f, 0.f); @@ -4047,50 +4826,16 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) removeAnimationData("Walk Speed"); } mMotionController.setTimeStep(time_step); -// LL_INFOS() << "Setting timestep to " << time_quantum * pixel_area_scale << LL_ENDL; } +} - if (getParent() && !mIsSitting) - { - sitOnObject((LLViewerObject*)getParent()); - } - else if (!getParent() && mIsSitting && !isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED)) +void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool was_sit_ground_constrained) +{ + if (!(isSitting() && getParent())) { - getOffObject(); - // - //Singu note: this appears to be a safety catch: - // when getParent() is NULL and we're not playing ANIM_AGENT_SIT_GROUND_CONSTRAINED then we aren't sitting! - // The previous call existed in an attempt to fix this inconsistent state by standing up from an object. - // However, since getParent() is NULL that function would crash! - // Since we never got crash reports regarding to this, that apparently never happened, except, I discovered - // today, when you are ground sitting and then LLMotionController::deleteAllMotions or - // LLMotionController::deactivateAllMotions is called, which seems to only happen when previewing an - // to-be-uploaded animation on your own avatar (while ground sitting). - // Hence, we DO need this safety net but not for standing up from an object but for standing up from the ground. - // I fixed the crash in getOffObject(), so it's ok to call that. In order to make things consistent with - // the server we need to actually stand up though, or we can't move anymore afterwards. - if (isSelf()) - { - gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); - } - // - } - - //-------------------------------------------------------------------- - // create local variables in world coords for region position values - //-------------------------------------------------------------------- - F32 speed; - LLVector3 normal; + // This case includes all configurations except sitting on an + // object, so does include ground sit. - LLVector3 xyVel = getVelocity(); - xyVel.mV[VZ] = 0.0f; - speed = xyVel.length(); - // remembering the value here prevents a display glitch if the - // animation gets toggled during this update. - bool was_sit_ground_constrained = isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED); - - if (!(mIsSitting && getParent())) - { //-------------------------------------------------------------------- // get timing info // handle initial condition case @@ -4108,9 +4853,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) //-------------------------------------------------------------------- // dont' let dT get larger than 1/5th of a second //-------------------------------------------------------------------- - F32 deltaTime = animation_time - mTimeLast; + F32 delta_time = animation_time - mTimeLast; - deltaTime = llclamp( deltaTime, DELTA_TIME_MIN, DELTA_TIME_MAX ); + delta_time = llclamp( delta_time, DELTA_TIME_MIN, DELTA_TIME_MAX ); mTimeLast = animation_time; mSpeedAccum = (mSpeedAccum * 0.95f) + (speed * 0.05f); @@ -4129,7 +4874,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) root_pos = gAgent.getPosGlobalFromAgent(getRenderPosition()); root_pos.mdV[VZ] += getVisualParamWeight(AVATAR_HOVER); - + LLVector3 normal; resolveHeightGlobal(root_pos, ground_under_pelvis, normal); F32 foot_to_ground = (F32) (root_pos.mdV[VZ] - mPelvisToFoot - ground_under_pelvis.mdV[VZ]); BOOL in_air = ((!LLWorld::getInstance()->getRegionFromPosGlobal(ground_under_pelvis)) || @@ -4141,186 +4886,46 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } mInAir = in_air; + // SL-402: with the ability to animate the position of joints + // that affect the body size calculation, computed body size + // can get stale much more easily. Simplest fix is to update + // it frequently. + // SL-427: this appears to be too frequent, moving to only do on animation state change. + //computeBodySize(); + // correct for the fact that the pelvis is not necessarily the center // of the agent's physical representation root_pos.mdV[VZ] -= (0.5f * mBodySize.mV[VZ]) - mPelvisToFoot; - if (!mIsSitting && !was_sit_ground_constrained) + if (!isSitting() && !was_sit_ground_constrained) { root_pos += LLVector3d(getHoverOffset()); } - - LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos); - if (newPosition != mRoot->getXform()->getWorldPosition()) - { - mRoot->touch(); - mRoot->setWorldPosition( newPosition ); // regular update + LLControlAvatar *cav = asControlAvatar(); + if (cav) + { + // SL-1350: Moved to LLDrawable::updateXform() + cav->matchVolumeTransform(); } + else + { + LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos); + if (newPosition != mRoot->getXform()->getWorldPosition()) + { + mRoot->touch(); + mRoot->setWorldPosition( newPosition ); // regular update + } + } //-------------------------------------------------------------------- // Propagate viewer object rotation to root of avatar //-------------------------------------------------------------------- - if (!isAnyAnimationSignaled(AGENT_NO_ROTATE_ANIMS, NUM_AGENT_NO_ROTATE_ANIMS)) + if (!isControlAvatar() && !isAnyAnimationSignaled(AGENT_NO_ROTATE_ANIMS, NUM_AGENT_NO_ROTATE_ANIMS)) { - LLQuaternion iQ; - LLVector3 upDir( 0.0f, 0.0f, 1.0f ); - - // Compute a forward direction vector derived from the primitive rotation - // and the velocity vector. When walking or jumping, don't let body deviate - // more than 90 from the view, if necessary, flip the velocity vector. - - LLVector3 primDir; - if (isSelf()) - { - primDir = agent.getAtAxis() - projected_vec(agent.getAtAxis(), agent.getReferenceUpVector()); - primDir.normalize(); - } - else - { - primDir = getRotation().getMatrix3().getFwdRow(); - } - LLVector3 velDir = getVelocity(); - velDir.normalize(); - static LLCachedControl TurnAround("TurnAroundWhenWalkingBackwards"); - if (!TurnAround && (mSignaledAnimations.find(ANIM_AGENT_WALK) != mSignaledAnimations.end())) - { - F32 vpD = velDir * primDir; - if (vpD < -0.5f) - { - velDir *= -1.0f; - } - } - LLVector3 fwdDir = lerp(primDir, velDir, clamp_rescale(speed, 0.5f, 2.0f, 0.0f, 1.0f)); - if (isSelf() && gAgentCamera.cameraMouselook()) - { - // make sure fwdDir stays in same general direction as primdir - if (gAgent.getFlying()) - { - fwdDir = LLViewerCamera::getInstance()->getAtAxis(); - } - else - { - LLVector3 at_axis = LLViewerCamera::getInstance()->getAtAxis(); - LLVector3 up_vector = gAgent.getReferenceUpVector(); - at_axis -= up_vector * (at_axis * up_vector); - at_axis.normalize(); - - F32 dot = fwdDir * at_axis; - if (dot < 0.f) - { - fwdDir -= 2.f * at_axis * dot; - fwdDir.normalize(); - } - } - - } - - LLQuaternion root_rotation = LLMatrix4(mRoot->getWorldMatrix().getF32ptr()).quaternion(); - F32 root_roll, root_pitch, root_yaw; - root_rotation.getEulerAngles(&root_roll, &root_pitch, &root_yaw); - - if (sDebugAvatarRotation) - { - LL_INFOS() << "root_roll " << RAD_TO_DEG * root_roll - << " root_pitch " << RAD_TO_DEG * root_pitch - << " root_yaw " << RAD_TO_DEG * root_yaw - << LL_ENDL; - } - - // When moving very slow, the pelvis is allowed to deviate from the - // forward direction to allow it to hold it's position while the torso - // and head turn. Once in motion, it must conform however. - BOOL self_in_mouselook = isSelf() && gAgentCamera.cameraMouselook(); - - LLVector3 pelvisDir( mRoot->getWorldMatrix().getRow().getF32ptr() ); - - static const LLCachedControl s_pelvis_rot_threshold_slow(gSavedSettings, "AvatarRotateThresholdSlow", 60.0); - static const LLCachedControl s_pelvis_rot_threshold_fast(gSavedSettings, "AvatarRotateThresholdFast", 2.0); - static const LLCachedControl useRealisticMouselook("UseRealisticMouselook"); - F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, useRealisticMouselook ? s_pelvis_rot_threshold_slow * 2 : s_pelvis_rot_threshold_slow, s_pelvis_rot_threshold_fast); - - if (self_in_mouselook && !useRealisticMouselook) - { - pelvis_rot_threshold *= MOUSELOOK_PELVIS_FOLLOW_FACTOR; - } - pelvis_rot_threshold *= DEG_TO_RAD; - - F32 angle = angle_between( pelvisDir, fwdDir ); - - // The avatar's root is allowed to have a yaw that deviates widely - // from the forward direction, but if roll or pitch are off even - // a little bit we need to correct the rotation. - if(root_roll < 1.f * DEG_TO_RAD - && root_pitch < 5.f * DEG_TO_RAD) - { - // smaller correction vector means pelvis follows prim direction more closely - if (!mTurning && angle > pelvis_rot_threshold*0.75f) - { - mTurning = TRUE; - } - - // use tighter threshold when turning - if (mTurning) - { - pelvis_rot_threshold *= 0.4f; - } - - // am I done turning? - if (angle < pelvis_rot_threshold) - { - mTurning = FALSE; - } - - LLVector3 correction_vector = (pelvisDir - fwdDir) * clamp_rescale(angle, pelvis_rot_threshold*0.75f, pelvis_rot_threshold, 1.0f, 0.0f); - fwdDir += correction_vector; - } - else - { - mTurning = FALSE; - } - - // Now compute the full world space rotation for the whole body (wQv) - LLVector3 leftDir = upDir % fwdDir; - leftDir.normalize(); - fwdDir = leftDir % upDir; - LLQuaternion wQv( fwdDir, leftDir, upDir ); - - if (isSelf() && mTurning) - { - if ((fwdDir % pelvisDir) * upDir > 0.f) - { - gAgent.setControlFlags(AGENT_CONTROL_TURN_RIGHT); - } - else - { - gAgent.setControlFlags(AGENT_CONTROL_TURN_LEFT); - } - } - - // Set the root rotation, but do so incrementally so that it - // lags in time by some fixed amount. - //F32 u = LLCriticalDamp::getInterpolant(PELVIS_LAG); - F32 pelvis_lag_time = 0.f; - if (self_in_mouselook) - { - pelvis_lag_time = PELVIS_LAG_MOUSELOOK; - } - else if (mInAir) - { - pelvis_lag_time = PELVIS_LAG_FLYING; - // increase pelvis lag time when moving slowly - pelvis_lag_time *= clamp_rescale(mSpeedAccum, 0.f, 15.f, 3.f, 1.f); - } - else - { - pelvis_lag_time = PELVIS_LAG_WALKING; - } - - F32 u = llclamp((deltaTime / pelvis_lag_time), 0.0f, 1.0f); - - mRoot->setWorldRotation( slerp(u, mRoot->getWorldRotation(), wQv) ); - + // Rotation fixups for avatars in motion. + // Skip for animated objects. + updateOrientation(agent, speed, delta_time); } } else if (mDrawable.notNull()) @@ -4331,135 +4936,181 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) mRoot->setPosition(pos); mRoot->setRotation(rot); } - - //------------------------------------------------------------------------- - // Update character motions - //------------------------------------------------------------------------- - // store data relevant to motions - mSpeed = speed; - - // update animations - if (mSpecialRenderMode == 1) // Animation Preview - updateMotions(LLCharacter::FORCE_UPDATE); - else - updateMotions(LLCharacter::NORMAL_UPDATE); +} - // Special handling for sitting on ground. - if (!getParent() && (mIsSitting || was_sit_ground_constrained)) +//------------------------------------------------------------------------ +// updateCharacter() +// +// This is called for all avatars, so there are 4 possible situations: +// +// 1) Avatar is your own. In this case the class is LLVOAvatarSelf, +// isSelf() is true, and agent specifies the corresponding agent +// information for you. In all the other cases, agent is irrelevant +// and it would be less confusing if it were null or something. +// +// 2) Avatar is controlled by another resident. Class is LLVOAvatar, +// and isSelf() is false. +// +// 3) Avatar is the controller for an animated object. Class is +// LLControlAvatar and mIsDummy is true. Avatar is a purely +// viewer-side entity with no representation on the simulator. +// +// 4) Avatar is a UI avatar used in some areas of the UI, such as when +// previewing uploaded animations. Class is LLUIAvatar, and mIsDummy +// is true. Avatar is purely viewer-side with no representation on the +// simulator. +// +//------------------------------------------------------------------------ +BOOL LLVOAvatar::updateCharacter(LLAgent &agent) +{ + // Frozen! + if (areAnimationsPaused()) { - F32 off_z = LLVector3d(getHoverOffset()).mdV[VZ]; - if (off_z != 0.0) - { - LLVector3 pos = mRoot->getWorldPosition(); - pos.mV[VZ] += off_z; - mRoot->touch(); - mRoot->setWorldPosition(pos); - } + updateMotions(LLCharacter::NORMAL_UPDATE); // This is necessary to get unpaused again. + return FALSE; } - - // update head position - updateHeadOffset(); - - //------------------------------------------------------------------------- - // Find the ground under each foot, these are used for a variety - // of things that follow - //------------------------------------------------------------------------- - LLVector3 ankle_left_pos_agent = mFootLeftp->getWorldPosition(); - LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition(); - - LLVector3 ankle_left_ground_agent = ankle_left_pos_agent; - LLVector3 ankle_right_ground_agent = ankle_right_pos_agent; - resolveHeightAgent(ankle_left_pos_agent, ankle_left_ground_agent, normal); - resolveHeightAgent(ankle_right_pos_agent, ankle_right_ground_agent, normal); - - F32 leftElev = llmax(-0.2f, ankle_left_pos_agent.mV[VZ] - ankle_left_ground_agent.mV[VZ]); - F32 rightElev = llmax(-0.2f, ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]); - - if (!mIsSitting) + + updateDebugText(); + + if (gNoRender) { - //------------------------------------------------------------------------- - // Figure out which foot is on ground - //------------------------------------------------------------------------- - if (!mInAir) + // Hack if we're running drones... + if (isSelf()) { - if ((leftElev < 0.0f) || (rightElev < 0.0f)) - { - ankle_left_pos_agent = mFootLeftp->getWorldPosition(); - ankle_right_pos_agent = mFootRightp->getWorldPosition(); - leftElev = ankle_left_pos_agent.mV[VZ] - ankle_left_ground_agent.mV[VZ]; - rightElev = ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]; - } + gAgent.setPositionAgent(getPositionAgent()); } + return FALSE; } - - //------------------------------------------------------------------------- - // Generate footstep sounds when feet hit the ground - //------------------------------------------------------------------------- - const LLUUID AGENT_FOOTSTEP_ANIMS[] = {ANIM_AGENT_WALK, ANIM_AGENT_RUN, ANIM_AGENT_LAND}; - const S32 NUM_AGENT_FOOTSTEP_ANIMS = LL_ARRAY_SIZE(AGENT_FOOTSTEP_ANIMS); - if ( gAudiop && isAnyAnimationSignaled(AGENT_FOOTSTEP_ANIMS, NUM_AGENT_FOOTSTEP_ANIMS) ) + if (!mIsBuilt) { - BOOL playSound = FALSE; - LLVector3 foot_pos_agent; - - BOOL onGroundLeft = (leftElev <= 0.05f); - BOOL onGroundRight = (rightElev <= 0.05f); - - // did left foot hit the ground? - if ( onGroundLeft && !mWasOnGroundLeft ) - { - foot_pos_agent = ankle_left_pos_agent; - playSound = TRUE; - } + return FALSE; + } - // did right foot hit the ground? - if ( onGroundRight && !mWasOnGroundRight ) - { - foot_pos_agent = ankle_right_pos_agent; - playSound = TRUE; - } + bool visible = isVisible(); + bool is_control_avatar = isControlAvatar(); // capture state to simplify tracing + bool is_attachment = false; + if (is_control_avatar) + { + LLControlAvatar *cav = asControlAvatar(); + is_attachment = cav && cav->mRootVolp && cav->mRootVolp->isAttachment(); // For attached animated objects + } - mWasOnGroundLeft = onGroundLeft; - mWasOnGroundRight = onGroundRight; + // For fading out the names above heads, only let the timer + // run if we're visible. + if (mDrawable.notNull() && !visible) + { + mTimeVisible.reset(); + } - if ( playSound ) - { -// F32 gain = clamp_rescale( mSpeedAccum, -// AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, -// AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); + //-------------------------------------------------------------------- + // The rest should only be done occasionally for far away avatars. + // Set mUpdatePeriod and visible based on distance and other criteria. + //-------------------------------------------------------------------- + computeUpdatePeriod(); + visible = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0 ? TRUE : FALSE; - const F32 STEP_VOLUME = 0.5f; - const LLUUID& step_sound_id = getStepSound(); + //-------------------------------------------------------------------- - LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent); + // don't early out for your own avatar, as we rely on your animations playing reliably + // for example, the "turn around" animation when entering customize avatar needs to trigger + // even when your avatar is offscreen + if (!visible && !isSelf()) + { + updateMotions(LLCharacter::HIDDEN_UPDATE); + return FALSE; + } - if (LLViewerParcelMgr::getInstance()->canHearSound(foot_pos_global) - && !LLMuteList::getInstance()->isMuted(getID(), LLMute::flagObjectSounds)) - { - gAudiop->triggerSound(step_sound_id, getID(), STEP_VOLUME, LLAudioEngine::AUDIO_TYPE_AMBIENT, foot_pos_global); - } + // change animation time quanta based on avatar render load + //updateTimeStep(); + if (getParent() && !isSitting()) + { + sitOnObject((LLViewerObject*)getParent()); + } + else if (!getParent() && isSitting() && !isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED)) + { + getOffObject(); + // + //Singu note: this appears to be a safety catch: + // when getParent() is NULL and we're not playing ANIM_AGENT_SIT_GROUND_CONSTRAINED then we aren't sitting! + // The previous call existed in an attempt to fix this inconsistent state by standing up from an object. + // However, since getParent() is NULL that function would crash! + // Since we never got crash reports regarding to this, that apparently never happened, except, I discovered + // today, when you are ground sitting and then LLMotionController::deleteAllMotions or + // LLMotionController::deactivateAllMotions is called, which seems to only happen when previewing an + // to-be-uploaded animation on your own avatar (while ground sitting). + // Hence, we DO need this safety net but not for standing up from an object but for standing up from the ground. + // I fixed the crash in getOffObject(), so it's ok to call that. In order to make things consistent with + // the server we need to actually stand up though, or we can't move anymore afterwards. + if (isSelf()) + { + gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); } + // } - mRoot->updateWorldMatrixChildren(); + //-------------------------------------------------------------------- + // create local variables in world coords for region position values + //-------------------------------------------------------------------- + LLVector3 xyVel = getVelocity(); + xyVel.mV[VZ] = 0.0f; + F32 speed = xyVel.length(); + // remembering the value here prevents a display glitch if the + // animation gets toggled during this update. + bool was_sit_ground_constrained = isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED); - if (!mDebugText.size() && mText.notNull()) + //-------------------------------------------------------------------- + // This does a bunch of state updating, including figuring out + // whether av is in the air, setting mRoot position and rotation + // In some cases, calls updateOrientation() for a lot of the + // work + // -------------------------------------------------------------------- + updateRootPositionAndRotation(agent, speed, was_sit_ground_constrained); + + //------------------------------------------------------------------------- + // Update character motions + //------------------------------------------------------------------------- + // store data relevant to motions + mSpeed = speed; + + // update animations + if (mSpecialRenderMode == 1) // Animation Preview { - mText->markDead(); - mText = NULL; + updateMotions(LLCharacter::FORCE_UPDATE); } - else if (mDebugText.size()) + else { - setDebugText(mDebugText); + updateMotions(LLCharacter::NORMAL_UPDATE); } - mDebugText.clear(); + + // Special handling for sitting on ground. + if (!getParent() && (isSitting() || was_sit_ground_constrained)) + { + F32 off_z = LLVector3d(getHoverOffset()).mdV[VZ]; + if (off_z != 0.0) + { + LLVector3 pos = mRoot->getWorldPosition(); + pos.mV[VZ] += off_z; + mRoot->touch(); + mRoot->setWorldPosition(pos); + } + } + + // update head position + updateHeadOffset(); + + // Generate footstep sounds when feet hit the ground + updateFootstepSounds(); + + // Update child joints as needed. + mRoot->updateWorldMatrixChildren(); //mesh vertices need to be reskinned mNeedsSkin = TRUE; return TRUE; } + //----------------------------------------------------------------------------- // updateHeadOffset() //----------------------------------------------------------------------------- @@ -4474,50 +5125,24 @@ void LLVOAvatar::updateHeadOffset() { midEyePt = midEyePt * ~mDrawable->getWorldRotation(); } - if (mIsSitting) + if (isSitting()) { - mHeadOffset = midEyePt; + mHeadOffset = midEyePt; } else { F32 u = llmax(0.f, HEAD_MOVEMENT_AVG_TIME - (1.f / gFPSClamped)); - mHeadOffset = lerp(midEyePt, mHeadOffset, u); - } -} -//------------------------------------------------------------------------ -// setPelvisOffset -//------------------------------------------------------------------------ -void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount, F32 pelvisFixup ) -{ - mHasPelvisOffset = hasOffset; - if ( mHasPelvisOffset ) - { - //Store off last pelvis to foot value - mLastPelvisToFoot = mPelvisToFoot; - mPelvisOffset = offsetAmount; - mLastPelvisFixup = mPelvisFixup; - mPelvisFixup = pelvisFixup; + mHeadOffset = lerp(midEyePt, mHeadOffset, u); } } //------------------------------------------------------------------------ // postPelvisSetRecalc //------------------------------------------------------------------------ -void LLVOAvatar::postPelvisSetRecalc( void ) -{ - computeBodySize(); - mRoot->touch(); - mRoot->updateWorldMatrixChildren(); - dirtyMesh(); - updateHeadOffset(); -} -//------------------------------------------------------------------------ -// pelisPoke -//------------------------------------------------------------------------ -void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount ) -{ - mHasPelvisOffset = true; - mLastPelvisFixup = mPelvisFixup; - mPelvisFixup = pelvisFixupAmount; +void LLVOAvatar::postPelvisSetRecalc() +{ + mRoot->updateWorldMatrixChildren(); + computeBodySize(); + dirtyMesh(2); } //------------------------------------------------------------------------ // updateVisibility() @@ -4528,7 +5153,7 @@ void LLVOAvatar::updateVisibility() if (mIsDummy) { - visible = TRUE; + visible = FALSE; } else if (mDrawable.isNull()) { @@ -4545,14 +5170,14 @@ void LLVOAvatar::updateVisibility() visible = FALSE; } - if(isSelf()) + if (isSelf()) { if (!gAgentWearables.areWearablesLoaded()) { visible = FALSE; } } - else if( !mFirstAppearanceMessageReceived ) + else if (!mFirstAppearanceMessageReceived) { visible = FALSE; } @@ -4602,19 +5227,29 @@ void LLVOAvatar::updateVisibility() LL_INFOS() << "PA: " << getPositionAgent() << LL_ENDL; /*LL_INFOS() << "SPA: " << sel_pos_agent << LL_ENDL; LL_INFOS() << "WPA: " << wrist_right_pos_agent << LL_ENDL;*/ - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) + + +#if SLOW_ATTACHMENT_LIST + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { LLViewerJointAttachment* attachment = iter->second; for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) { if (LLViewerObject *attached_object = (*attachment_iter)) +#else + for (auto& iter : mAttachedObjectsVector) + {{ + const LLViewerObject *attached_object = iter.first; + const LLViewerJointAttachment *attachment = iter.second; + if (attachment) +#endif { - if (attached_object->mDrawable->isVisible()) + if (attached_object && attached_object->mDrawable->isVisible()) { LL_INFOS() << attachment->getName() << " visible" << LL_ENDL; } @@ -4642,7 +5277,8 @@ void LLVOAvatar::updateVisibility() } else { - if (mMeshValid && mMeshInvisibleTime.getElapsedTimeF32() > TIME_BEFORE_MESH_CLEANUP) + if (mMeshValid && + (isControlAvatar() || mMeshInvisibleTime.getElapsedTimeF32() > TIME_BEFORE_MESH_CLEANUP)) { releaseMeshData(); } @@ -4673,6 +5309,11 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) return num_indices; } + if (mDrawable.isNull()) + { + return num_indices; + } + LLFace* face = mDrawable->getFace(0); bool needs_rebuild = !face || !face->getVertexBuffer() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY); @@ -4833,7 +5474,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) { bool is_muted = LLPipeline::sImpostorRender && isVisuallyMuted(); //Disable masking and also disable alpha in LLViewerJoint::render const bool should_alpha_mask = !is_muted && shouldAlphaMask(); - LLGLState test(GL_ALPHA_TEST, should_alpha_mask); + LLGLState test(should_alpha_mask); if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) { @@ -4845,7 +5486,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) { if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { - if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy) + if (isTextureVisible(TEX_HEAD_BAKED) || isUIAvatar()) { LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); if (head_mesh) @@ -4855,7 +5496,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) first_pass = FALSE; } } - if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy) + if (isTextureVisible(TEX_UPPER_BAKED) || isUIAvatar()) { LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); if (upper_mesh) @@ -4865,7 +5506,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) first_pass = FALSE; } - if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy) + if (isTextureVisible(TEX_LOWER_BAKED) || isUIAvatar()) { LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); if (lower_mesh) @@ -4883,8 +5524,8 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) { - LLGLState blend(GL_BLEND, !mIsDummy); - LLGLState test(GL_ALPHA_TEST, !mIsDummy); + LLGLState blend(!mIsDummy); + LLGLState test(!mIsDummy); num_indices += renderTransparent(first_pass); } } @@ -4897,7 +5538,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) U32 LLVOAvatar::renderTransparent(BOOL first_pass) { U32 num_indices = 0; - if( isWearingWearableType( LLWearableType::WT_SKIRT ) && (mIsDummy || isTextureVisible(TEX_SKIRT_BAKED)) ) + if( isWearingWearableType( LLWearableType::WT_SKIRT ) && (isUIAvatar() || isTextureVisible(TEX_SKIRT_BAKED)) ) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f); LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT); @@ -4925,10 +5566,19 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) } first_pass = FALSE; } - // Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair) - // TODO: 1.25 will be able to switch this logic back to calling isTextureVisible(); - if ((getImage(TEX_HAIR_BAKED, 0) && - getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE) || LLDrawPoolAlpha::sShowDebugAlpha) + bool show_hair = false; + if (isControlAvatar()) + { + show_hair = isTextureVisible(TEX_HAIR_BAKED); + } + else + { + // Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair) + // TODO: 1.25 will be able to switch this logic back to calling isTextureVisible(); + auto image = getImage(TEX_HAIR_BAKED, 0); + show_hair = LLDrawPoolAlpha::sShowDebugAlpha || (image && image->getID() != IMG_INVISIBLE); + } + if (show_hair) { LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); if (hair_mesh) @@ -4969,14 +5619,14 @@ U32 LLVOAvatar::renderRigid() } const bool should_alpha_mask = shouldAlphaMask(); - LLGLState test(GL_ALPHA_TEST, should_alpha_mask); + LLGLState test(should_alpha_mask); if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); } - if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy) + if (isTextureVisible(TEX_EYES_BAKED) || isUIAvatar()) { LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT); LLViewerJoint* eyeball_right = getViewerJoint(MESH_ID_EYEBALL_RIGHT); @@ -5036,7 +5686,7 @@ U32 LLVOAvatar::renderRigid() LLGLDepthTest test(GL_TRUE, GL_FALSE); //render foot shadows - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.getTexUnit(0)->bind(mShadowImagep.get(), TRUE); gGL.diffuseColor4fv(mShadow0Facep->getRenderColor().mV); mShadow0Facep->renderIndexed(foot_mask); @@ -5062,31 +5712,31 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) left *= mImpostorDim.mV[0]; up *= mImpostorDim.mV[1]; - LLGLEnable test(GL_ALPHA_TEST); + LLGLEnable test; gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); gGL.color4ubv(color.mV); gGL.getTexUnit(diffuse_channel)->bind(&mImpostor); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(0,0); gGL.vertex3fv((pos+left-up).mV); gGL.texCoord2f(1,0); gGL.vertex3fv((pos-left-up).mV); + gGL.texCoord2f(0, 1); + gGL.vertex3fv((pos + left + up).mV); gGL.texCoord2f(1,1); gGL.vertex3fv((pos-left+up).mV); - gGL.texCoord2f(0,1); - gGL.vertex3fv((pos+left+up).mV); gGL.end(); gGL.flush(); return 6; } -bool LLVOAvatar::allTexturesCompletelyDownloaded(std::set& ids) const +bool LLVOAvatar::allTexturesCompletelyDownloaded(uuid_set_t& ids) const { - for (std::set::const_iterator it = ids.begin(); it != ids.end(); ++it) + for (auto it = ids.begin(); it != ids.end(); ++it) { - LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD); if (imagep && imagep->getDiscardLevel()!=0) { return false; @@ -5097,14 +5747,14 @@ bool LLVOAvatar::allTexturesCompletelyDownloaded(std::set& ids) const bool LLVOAvatar::allLocalTexturesCompletelyDownloaded() const { - std::set local_ids; + uuid_set_t local_ids; collectLocalTextureUUIDs(local_ids); return allTexturesCompletelyDownloaded(local_ids); } bool LLVOAvatar::allBakedTexturesCompletelyDownloaded() const { - std::set baked_ids; + uuid_set_t baked_ids; collectBakedTextureUUIDs(baked_ids); return allTexturesCompletelyDownloaded(baked_ids); } @@ -5116,11 +5766,11 @@ void LLVOAvatar::bakedTextureOriginCounts(S32 &sb_count, // server-bake, has ori { sb_count = host_count = both_count = neither_count = 0; - std::set baked_ids; + uuid_set_t baked_ids; collectBakedTextureUUIDs(baked_ids); - for (std::set::const_iterator it = baked_ids.begin(); it != baked_ids.end(); ++it) + for (auto it = baked_ids.begin(); it != baked_ids.end(); ++it) { - LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD); bool has_url = false, has_host = false; if (!imagep->getUrl().empty()) { @@ -5141,11 +5791,11 @@ std::string LLVOAvatar::bakedTextureOriginInfo() { std::string result; - std::set baked_ids; + uuid_set_t baked_ids; collectBakedTextureUUIDs(baked_ids); - for (std::set::const_iterator it = baked_ids.begin(); it != baked_ids.end(); ++it) + for (auto it = baked_ids.begin(); it != baked_ids.end(); ++it) { - LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD); bool has_url = false, has_host = false; if (!imagep->getUrl().empty()) { @@ -5169,12 +5819,12 @@ std::string LLVOAvatar::bakedTextureOriginInfo() return result; } -S32 LLVOAvatar::totalTextureMemForUUIDS(std::set& ids) +S32Bytes LLVOAvatar::totalTextureMemForUUIDS(uuid_set_t& ids) { - S32 result = 0; - for (std::set::const_iterator it = ids.begin(); it != ids.end(); ++it) + S32Bytes result(0); + for (auto it = ids.begin(); it != ids.end(); ++it) { - LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD); if (imagep) { result += imagep->getTextureMemory(); @@ -5183,7 +5833,7 @@ S32 LLVOAvatar::totalTextureMemForUUIDS(std::set& ids) return result; } -void LLVOAvatar::collectLocalTextureUUIDs(std::set& ids) const +void LLVOAvatar::collectLocalTextureUUIDs(uuid_set_t& ids) const { for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { @@ -5197,7 +5847,7 @@ void LLVOAvatar::collectLocalTextureUUIDs(std::set& ids) const if (imagep) { const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)texture_index); - if (texture_dict->mIsLocalTexture) + if (texture_dict && texture_dict->mIsLocalTexture) { ids.insert(imagep->getID()); } @@ -5209,7 +5859,7 @@ void LLVOAvatar::collectLocalTextureUUIDs(std::set& ids) const ids.erase(IMG_INVISIBLE); } -void LLVOAvatar::collectBakedTextureUUIDs(std::set& ids) const +void LLVOAvatar::collectBakedTextureUUIDs(uuid_set_t& ids) const { for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { @@ -5228,7 +5878,7 @@ void LLVOAvatar::collectBakedTextureUUIDs(std::set& ids) const ids.erase(IMG_INVISIBLE); } -void LLVOAvatar::collectTextureUUIDs(std::set& ids) +void LLVOAvatar::collectTextureUUIDs(uuid_set_t& ids) { collectLocalTextureUUIDs(ids); collectBakedTextureUUIDs(ids); @@ -5236,21 +5886,21 @@ void LLVOAvatar::collectTextureUUIDs(std::set& ids) void LLVOAvatar::releaseOldTextures() { - S32 current_texture_mem = 0; + S32Bytes current_texture_mem; // Any textures that we used to be using but are no longer using should no longer be flagged as "NO_DELETE" - std::set baked_texture_ids; + uuid_set_t baked_texture_ids; collectBakedTextureUUIDs(baked_texture_ids); - S32 new_baked_mem = totalTextureMemForUUIDS(baked_texture_ids); + S32Bytes new_baked_mem = totalTextureMemForUUIDS(baked_texture_ids); - std::set local_texture_ids; + uuid_set_t local_texture_ids; collectLocalTextureUUIDs(local_texture_ids); //S32 new_local_mem = totalTextureMemForUUIDS(local_texture_ids); - std::set new_texture_ids; + uuid_set_t new_texture_ids; new_texture_ids.insert(baked_texture_ids.begin(),baked_texture_ids.end()); new_texture_ids.insert(local_texture_ids.begin(),local_texture_ids.end()); - S32 new_total_mem = totalTextureMemForUUIDS(new_texture_ids); + S32Bytes new_total_mem = totalTextureMemForUUIDS(new_texture_ids); //S32 old_total_mem = totalTextureMemForUUIDS(mTextureIDs); //LL_DEBUGS("Avatar") << getFullname() << " old_total_mem: " << old_total_mem << " new_total_mem (L/B): " << new_total_mem << " (" << new_local_mem <<", " << new_baked_mem << ")" << LL_ENDL; @@ -5258,11 +5908,11 @@ void LLVOAvatar::releaseOldTextures() { LL_WARNS() << "extra local textures stored for non-self av" << LL_ENDL; } - for (std::set::iterator it = mTextureIDs.begin(); it != mTextureIDs.end(); ++it) + for (auto it = mTextureIDs.begin(); it != mTextureIDs.end(); ++it) { if (new_texture_ids.find(*it) == new_texture_ids.end()) { - LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD); if (imagep) { current_texture_mem += imagep->getTextureMemory(); @@ -5287,7 +5937,7 @@ void LLVOAvatar::releaseOldTextures() static LLFastTimer::DeclareTimer FTM_TEXTURE_UPDATE("Update Textures"); void LLVOAvatar::updateTextures() { - LLFastTimer t(FTM_TEXTURE_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_TEXTURE_UPDATE); releaseOldTextures(); BOOL render_avatar = TRUE; @@ -5356,8 +6006,8 @@ void LLVOAvatar::updateTextures() if (imagep) { const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)texture_index); - const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - if (texture_dict->mIsLocalTexture) + const EBakedTextureIndex baked_index = texture_dict ? texture_dict->mBakedTextureIndex : EBakedTextureIndex::BAKED_NUM_INDICES; + if (texture_dict && texture_dict->mIsLocalTexture) { addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, mBakedTextureDatas[baked_index].mIsUsed); } @@ -5609,10 +6259,13 @@ void LLVOAvatar::processAnimationStateChanges() startMotion(ANIM_AGENT_WALK_ADJUST); stopMotion(ANIM_AGENT_FLY_ADJUST); } - else if (mInAir && !mIsSitting) + else if (mInAir && !isSitting()) { stopMotion(ANIM_AGENT_WALK_ADJUST); - startMotion(ANIM_AGENT_FLY_ADJUST); + if (mEnableDefaultMotions) + { + startMotion(ANIM_AGENT_FLY_ADJUST); + } } else { @@ -5622,17 +6275,23 @@ void LLVOAvatar::processAnimationStateChanges() if ( isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) ) { - startMotion(ANIM_AGENT_TARGET); + if (mEnableDefaultMotions) + { + startMotion(ANIM_AGENT_TARGET); + } stopMotion(ANIM_AGENT_BODY_NOISE); } else { stopMotion(ANIM_AGENT_TARGET); - startMotion(ANIM_AGENT_BODY_NOISE); + if (mEnableDefaultMotions) + { + startMotion(ANIM_AGENT_BODY_NOISE); + } } // clear all current animations - const bool AOEnabled(gSavedSettings.getBOOL("AOEnabled")); // + auto ao = isSelf() ? AOSystem::getIfExists() : nullptr; // AO is only for ME AnimIterator anim_it; for (anim_it = mPlayingAnimations.begin(); anim_it != mPlayingAnimations.end();) { @@ -5641,14 +6300,13 @@ void LLVOAvatar::processAnimationStateChanges() // playing, but not signaled, so stop if (found_anim == mSignaledAnimations.end()) { - if (AOEnabled && isSelf()) - LLFloaterAO::stopMotion(anim_it->first, FALSE); // if the AO replaced this anim serverside then stop it serverside + if (ao) ao->stopMotion(anim_it->first); // if the AO replaced this anim serverside then stop it serverside processSingleAnimationStateChange(anim_it->first, FALSE); // LLFloaterExploreAnimations::processAnim(getID(), anim_it->first, false); // - mPlayingAnimations.erase(anim_it++); + anim_it = mPlayingAnimations.erase(anim_it); continue; } @@ -5668,10 +6326,7 @@ void LLVOAvatar::processAnimationStateChanges() // if (processSingleAnimationStateChange(anim_it->first, TRUE)) { - if (AOEnabled && isSelf()) // AO is only for ME - { - LLFloaterAO::startMotion(anim_it->first, 0,FALSE); // AO overrides the anim if needed - } + if (ao) ao->startMotion(anim_it->first); // AO overrides the anim if needed mPlayingAnimations[anim_it->first] = anim_it->second; ++anim_it; @@ -5709,6 +6364,12 @@ void LLVOAvatar::processAnimationStateChanges() //----------------------------------------------------------------------------- BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL start ) { + // SL-402, SL-427 - we need to update body size often enough to + // keep appearances in sync, but not so often that animations + // cause constant jiggling of the body or camera. Possible + // compromise is to do it on animation changes: + computeBodySize(); + BOOL result = FALSE; if ( start ) // start animation @@ -5750,8 +6411,8 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL LLAvatarNameCache::getNSName(mID, name); LLChat chat; chat.mFromName = name; - chat.mText = name + " " + LLTrans::getString("took_a_snapshot") + "."; - chat.mURL = llformat("secondlife:///app/agent/%s/about",mID.asString().c_str()); + chat.mText = name + ' ' + LLTrans::getString("took_a_snapshot") + '.'; + chat.mURL = LLAvatarActions::getSLURL(mID); chat.mSourceType = CHAT_SOURCE_SYSTEM; LLFloaterChat::addChat(chat); } @@ -5773,6 +6434,12 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL { sitDown(FALSE); } + if ((anim_id == ANIM_AGENT_DO_NOT_DISTURB) && gAgent.isDoNotDisturb()) + { + // re-assert DND tag animation + gAgent.sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, ANIM_REQUEST_START); + return result; + } stopMotion(anim_id); result = TRUE; } @@ -5876,6 +6543,11 @@ LLUUID LLVOAvatar::remapMotionID(const LLUUID& id) if (use_new_walk_run) result = ANIM_AGENT_RUN_NEW; } + // keeps in sync with setSex() related code (viewer controls sit's sex) + else if (id == ANIM_AGENT_SIT_FEMALE) + { + result = ANIM_AGENT_SIT; + } } @@ -5938,6 +6610,15 @@ BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate) return LLCharacter::stopMotion(remap_id, stop_immediate); } +//----------------------------------------------------------------------------- +// hasMotionFromSource() +//----------------------------------------------------------------------------- +// virtual +bool LLVOAvatar::hasMotionFromSource(const LLUUID& source_id) +{ + return false; +} + //----------------------------------------------------------------------------- // stopMotionFromSource() //----------------------------------------------------------------------------- @@ -5969,14 +6650,17 @@ const LLUUID& LLVOAvatar::getID() const // RN: avatar joints are multi-rooted to include screen-based attachments LLJoint *LLVOAvatar::getJoint( const std::string &name ) { - joint_map_t::iterator iter = mJointMap.find(name); + joint_map_t::iterator iter = std::find_if(mJointMap.begin(), mJointMap.end(), [&name](joint_map_t::value_type &pair) { return strcmp(name.c_str(), pair.first) == 0; }); LLJoint* jointp = NULL; if (iter == mJointMap.end() || iter->second == NULL) { //search for joint and cache found joint in lookup table jointp = mRoot->findJoint(name); - mJointMap[name] = jointp; + joint_map_t::value_type entry; + strncpy(entry.first, name.c_str(), sizeof(entry.first)); + entry.second = jointp; + mJointMap.emplace_back(entry); } else { //return cached pointer @@ -5985,39 +6669,491 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) return jointp; } + +LLJoint *LLVOAvatar::getJoint( S32 joint_num ) +{ + LLJoint *pJoint = NULL; + S32 collision_start = mNumBones; + S32 attachment_start = mNumBones + mCollisionVolumes.size(); + if (joint_num>=attachment_start) + { + // Attachment IDs start at 1 + S32 attachment_id = joint_num - attachment_start + 1; + attachment_map_t::iterator iter = mAttachmentPoints.find(attachment_id); + if (iter != mAttachmentPoints.end()) + { + pJoint = iter->second; + } + } + else if (joint_num>=collision_start) + { + S32 collision_id = joint_num-collision_start; + pJoint = mCollisionVolumes[collision_id]; + } + else if (joint_num>=0) + { + pJoint = mSkeleton[joint_num]; + } + llassert(!pJoint || pJoint->getJointNum() == joint_num); + return pJoint; +} + +//----------------------------------------------------------------------------- +// getRiggedMeshID +// +// If viewer object is a rigged mesh, set the mesh id and return true. +// Otherwise, null out the id and return false. //----------------------------------------------------------------------------- -// resetJointPositionsToDefault +// static +bool LLVOAvatar::getRiggedMeshID(LLViewerObject* pVO, LLUUID& mesh_id) +{ + mesh_id.setNull(); + + //If a VO has a skin that we'll reset the joint positions to their default + if ( pVO && pVO->mDrawable ) + { + LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); + if ( pVObj ) + { + const LLMeshSkinInfo* pSkinData = pVObj->getSkinInfo(); + if (pSkinData + && pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG // full rig + && pSkinData->mAlternateBindMatrix.size() > 0 ) + { + mesh_id = pSkinData->mMeshID; + return true; + } + } + } + return false; +} + +bool LLVOAvatar::jointIsRiggedTo(const LLJoint *joint) const +{ + if (joint) + { + const LLJointRiggingInfoTab& tab = mJointRiggingInfoTab; + S32 joint_num = joint->getJointNum(); + if (joint_num < tab.size() && tab[joint_num].isRiggedTo()) + { + return true; + } + } + return false; +} + +void LLVOAvatar::clearAttachmentOverrides() +{ + for (S32 i=0; iclearAttachmentPosOverrides(); + pJoint->clearAttachmentScaleOverrides(); + } + } + + if (mPelvisFixups.count()>0) + { + mPelvisFixups.clear(); + LLJoint* pJointPelvis = getJoint("mPelvis"); + if (pJointPelvis) + { + pJointPelvis->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) ); + } + postPelvisSetRecalc(); + } + + mActiveOverrideMeshes.clear(); + onActiveOverrideMeshesChanged(); +} + +//----------------------------------------------------------------------------- +// rebuildAttachmentOverrides +//----------------------------------------------------------------------------- +void LLVOAvatar::rebuildAttachmentOverrides() +{ + clearAttachmentOverrides(); + + // Handle the case that we're resetting the skeleton of an animated object. + LLControlAvatar *control_av = asControlAvatar(); + if (control_av) + { + LLVOVolume *volp = control_av->mRootVolp; + if (volp) + { + LL_DEBUGS("Avatar") << volp->getID() << " adding attachment overrides for root vol, prim count " + << (S32) (1+volp->numChildren()) << LL_ENDL; + addAttachmentOverridesForObject(volp); + } + } + + // Attached objects +#if SLOW_ATTACHMENT_LIST + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment *attachment_pt = (*iter).second; + if (attachment_pt) + { + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator at_it = attachment_pt->mAttachedObjects.begin(); + at_it != attachment_pt->mAttachedObjects.end(); ++at_it) + { + LLViewerObject *vo = *at_it; +#else + for(auto& iter : mAttachedObjectsVector) + {{{ + LLViewerObject *vo = iter.first; +#endif + // Attached animated objects affect joints in their control + // avs, not the avs to which they are attached. + if (vo && !vo->isAnimatedObject()) + { + addAttachmentOverridesForObject(vo); + } + } + } + } +} + //----------------------------------------------------------------------------- -void LLVOAvatar::resetJointPositionsToDefault( void ) +// updateAttachmentOverrides +// +// This is intended to give the same results as +// rebuildAttachmentOverrides(), while avoiding redundant work. +// ----------------------------------------------------------------------------- +void LLVOAvatar::updateAttachmentOverrides() { - //Subsequent joints are relative to pelvis - avatar_joint_list_t::iterator iter = mSkeleton.begin(); - avatar_joint_list_t::iterator end = mSkeleton.end(); + LL_DEBUGS("AnimatedObjects") << "updating" << LL_ENDL; - LLJoint* pJointPelvis = getJoint("mPelvis"); + uuid_set_t meshes_seen; + + // Handle the case that we're updating the skeleton of an animated object. + LLControlAvatar *control_av = asControlAvatar(); + if (control_av) + { + LLVOVolume *volp = control_av->mRootVolp; + if (volp) + { + LL_DEBUGS("Avatar") << volp->getID() << " adding attachment overrides for root vol, prim count " + << (S32) (1+volp->numChildren()) << LL_ENDL; + addAttachmentOverridesForObject(volp, &meshes_seen); + } + } - for (; iter != end; ++iter) + // Attached objects +#if SLOW_ATTACHMENT_LIST + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { - LLJoint* pJoint = (*iter); - //Reset joints except for pelvis - if ( pJoint && pJoint != pJointPelvis && pJoint->doesJointNeedToBeReset() ) + LLViewerJointAttachment *attachment_pt = (*iter).second; + if (attachment_pt) { - pJoint->setId( LLUUID::null ); - pJoint->restoreOldXform(); + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator at_it = attachment_pt->mAttachedObjects.begin(); + at_it != attachment_pt->mAttachedObjects.end(); ++at_it) + { + LLViewerObject *vo = *at_it; +#else + for(auto& iter : mAttachedObjectsVector) + {{{ + LLViewerObject *vo = iter.first; +#endif + // Attached animated objects affect joints in their control + // avs, not the avs to which they are attached. + if (!vo->isAnimatedObject()) + { + addAttachmentOverridesForObject(vo, &meshes_seen); + } + } } - else - if ( pJoint && pJoint == pJointPelvis && pJoint->doesJointNeedToBeReset() ) + } + // Remove meshes that are no longer present on the skeleton + + // have to work with a copy because removeAttachmentOverrides() will change mActiveOverrideMeshes. + uuid_set_t active_override_meshes = mActiveOverrideMeshes; + for (auto it = active_override_meshes.begin(); it != active_override_meshes.end(); ++it) + { + if (meshes_seen.find(*it) == meshes_seen.end()) + { + removeAttachmentOverridesForObject(*it); + } + } +} +// addAttachmentPosOverridesForObject +//----------------------------------------------------------------------------- +void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, uuid_set_t* meshes_seen, bool recursive) +{ + if (vo->getAvatar() != this && vo->getAvatarAncestor() != this) + { + LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; + return; + } + + LL_DEBUGS("AnimatedObjects") << "adding" << LL_ENDL; + + // Process all children + if (recursive) + { + LLViewerObject::const_child_list_t& children = vo->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); + it != children.end(); ++it) + { + LLViewerObject *childp = *it; + addAttachmentOverridesForObject(childp, meshes_seen, true); + } + } + + LLVOVolume *vobj = vo->asVolume(); + if (vobj && vobj->isRiggedMesh() && + vobj->getVolume() && vobj->getVolume()->isMeshAssetLoaded() && gMeshRepo.meshRezEnabled()) + { + bool pelvisGotSet = false; + const LLMeshSkinInfo* pSkinData = vobj->getSkinInfo(); + const U32 bindCnt = pSkinData->mAlternateBindMatrix.size(); + const U32 jointCnt = pSkinData->mJointNames.size(); + if ((bindCnt > 0) && (bindCnt != jointCnt)) + { + LL_WARNS_ONCE() << "invalid mesh, bindCnt " << bindCnt << "!= jointCnt " << jointCnt << ", joint overrides will be ignored." << LL_ENDL; + } + if ((bindCnt > 0) && (bindCnt == jointCnt)) + { + const F32 pelvisZOffset = pSkinData->mPelvisOffset; + const LLUUID& mesh_id = pSkinData->mMeshID; + + if (meshes_seen) + { + meshes_seen->insert(mesh_id); + } + bool mesh_overrides_loaded = (mActiveOverrideMeshes.find(mesh_id) != mActiveOverrideMeshes.end()); + bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false; + if ( fullRig && !mesh_overrides_loaded ) + { + for ( U32 i=0; imJointNames[i].c_str(); + LLJoint* pJoint = getJoint( lookingForJoint ); + if ( pJoint ) + { + const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); + if (pJoint->aboveJointPosThreshold(jointPos)) + { + bool override_changed; + pJoint->addAttachmentPosOverride( jointPos, mesh_id, avString(), override_changed ); + + if (override_changed) + { + //If joint is a pelvis then handle old/new pelvis to foot values + if ( lookingForJoint == "mPelvis" ) + { + pelvisGotSet = true; + } + } + if (pSkinData->mLockScaleIfJointPosition) + { + // Note that unlike positions, there's no threshold check here, + // just a lock at the default value. + pJoint->addAttachmentScaleOverride(pJoint->getDefaultScale(), mesh_id, avString()); + } + } + } + } + if (pelvisZOffset != 0.0F) + { + F32 pelvis_fixup_before; + bool has_fixup_before = hasPelvisFixup(pelvis_fixup_before); + addPelvisFixup( pelvisZOffset, mesh_id ); + F32 pelvis_fixup_after; + hasPelvisFixup(pelvis_fixup_after); // Don't have to check bool here because we just added it... + if (!has_fixup_before || (pelvis_fixup_before != pelvis_fixup_after)) + { + pelvisGotSet = true; + } + + } + mActiveOverrideMeshes.insert(mesh_id); + onActiveOverrideMeshesChanged(); + } + } + //Rebuild body data if we altered joints/pelvis + if (pelvisGotSet) { - pJoint->setId( LLUUID::null ); - pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) ); - //pJoint->setJointResetFlag( false ); // Singu TODO + postPelvisSetRecalc(); + } + } +} + +//----------------------------------------------------------------------------- +// getAttachmentOverrideNames +//----------------------------------------------------------------------------- +void LLVOAvatar::getAttachmentOverrideNames(std::set& pos_names, std::set& scale_names) const +{ + LLVector3 pos; + LLVector3 scale; + LLUUID mesh_id; + + // Bones + for (avatar_joint_list_t::const_iterator iter = mSkeleton.begin(); + iter != mSkeleton.end(); ++iter) + { + const LLJoint* pJoint = (*iter); + if (pJoint && pJoint->hasAttachmentPosOverride(pos,mesh_id)) + { + pos_names.insert(pJoint->getName()); } + if (pJoint && pJoint->hasAttachmentScaleOverride(scale,mesh_id)) + { + scale_names.insert(pJoint->getName()); + } + } + + // Attachment points + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + const LLViewerJointAttachment *attachment_pt = (*iter).second; + if (attachment_pt && attachment_pt->hasAttachmentPosOverride(pos,mesh_id)) + { + pos_names.insert(attachment_pt->getName()); + } + // Attachment points don't have scales. + } + +} + +//----------------------------------------------------------------------------- +// showAttachmentOverrides +//----------------------------------------------------------------------------- +void LLVOAvatar::showAttachmentOverrides(bool verbose) const +{ + std::set pos_names, scale_names; + getAttachmentOverrideNames(pos_names, scale_names); + if (pos_names.size()) + { + std::stringstream ss; + std::copy(pos_names.begin(), pos_names.end(), std::ostream_iterator(ss, ",")); + LL_INFOS() << getFullname() << " attachment positions defined for joints: " << ss.str() << "\n" << LL_ENDL; + } + else + { + LL_DEBUGS("Avatar") << getFullname() << " no attachment positions defined for any joints" << "\n" << LL_ENDL; + } + if (scale_names.size()) + { + std::stringstream ss; + std::copy(scale_names.begin(), scale_names.end(), std::ostream_iterator(ss, ",")); + LL_INFOS() << getFullname() << " attachment scales defined for joints: " << ss.str() << "\n" << LL_ENDL; + } + else + { + LL_INFOS() << getFullname() << " no attachment scales defined for any joints" << "\n" << LL_ENDL; + } + + if (!verbose) + { + return; + } + + LLVector3 pos, scale; + LLUUID mesh_id; + S32 count = 0; + + // Bones + for (avatar_joint_list_t::const_iterator iter = mSkeleton.begin(); + iter != mSkeleton.end(); ++iter) + { + const LLJoint* pJoint = (*iter); + if (pJoint && pJoint->hasAttachmentPosOverride(pos,mesh_id)) + { + pJoint->showAttachmentPosOverrides(getFullname()); + count++; + } + if (pJoint && pJoint->hasAttachmentScaleOverride(scale,mesh_id)) + { + pJoint->showAttachmentScaleOverrides(getFullname()); + count++; + } + } + + // Attachment points + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + const LLViewerJointAttachment *attachment_pt = (*iter).second; + if (attachment_pt && attachment_pt->hasAttachmentPosOverride(pos,mesh_id)) + { + attachment_pt->showAttachmentPosOverrides(getFullname()); + count++; + } + } + + if (count) + { + LL_DEBUGS("Avatar") << avString() << " end of pos, scale overrides" << LL_ENDL; + LL_DEBUGS("Avatar") << "=================================" << LL_ENDL; + } +} + +//----------------------------------------------------------------------------- +// removeAttachmentOverridesForObject +//----------------------------------------------------------------------------- +void LLVOAvatar::removeAttachmentOverridesForObject(LLViewerObject *vo) +{ + if (vo->getAvatar() != this && vo->getAvatarAncestor() != this) + { + LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; + return; + } + + // Process all children + LLViewerObject::const_child_list_t& children = vo->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); + it != children.end(); ++it) + { + LLViewerObject *childp = *it; + removeAttachmentOverridesForObject(childp); } - //make sure we don't apply the joint offset - mHasPelvisOffset = false; - mPelvisFixup = mLastPelvisFixup; - postPelvisSetRecalc(); + // Process self. + LLUUID mesh_id; + if (getRiggedMeshID(vo,mesh_id)) + { + removeAttachmentOverridesForObject(mesh_id); + } +} + +//----------------------------------------------------------------------------- +// removeAttachmentOverridesForObject +//----------------------------------------------------------------------------- +void LLVOAvatar::removeAttachmentOverridesForObject(const LLUUID& mesh_id) +{ + LLJoint* pJointPelvis = getJoint("mPelvis"); + const std::string av_string = avString(); + for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++) + { + LLJoint *pJoint = getJoint(joint_num); + if ( pJoint ) + { + bool dummy; // unused + pJoint->removeAttachmentPosOverride(mesh_id, av_string, dummy); + pJoint->removeAttachmentScaleOverride(mesh_id, av_string); + } + if ( pJoint && pJoint == pJointPelvis) + { + removePelvisFixup( mesh_id ); + // SL-315 + pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) ); + } + } + + postPelvisSetRecalc(); + + mActiveOverrideMeshes.erase(mesh_id); + onActiveOverrideMeshesChanged(); } //----------------------------------------------------------------------------- // getCharacterPosition() @@ -6069,7 +7205,7 @@ void LLVOAvatar::getGround(const LLVector3 &in_pos_agent, LLVector3 &out_pos_age LLVector3d z_vec(0.0f, 0.0f, 1.0f); LLVector3d p0_global, p1_global; - if (mIsDummy) + if (isUIAvatar()) { outNorm.setVec(z_vec); out_pos_agent = in_pos_agent; @@ -6089,7 +7225,7 @@ void LLVOAvatar::getGround(const LLVector3 &in_pos_agent, LLVector3 &out_pos_age //----------------------------------------------------------------------------- F32 LLVOAvatar::getTimeDilation() { - return mTimeDilation; + return mRegionp ? mRegionp->getTimeDilation() : 1.f; } @@ -6098,7 +7234,7 @@ F32 LLVOAvatar::getTimeDilation() //----------------------------------------------------------------------------- F32 LLVOAvatar::getPixelArea() const { - if (mIsDummy) + if (isUIAvatar()) { return 100000.f; } @@ -6143,84 +7279,104 @@ BOOL LLVOAvatar::loadSkeletonNode () { return FALSE; } + + bool ignore_hud_joints = false; + initAttachmentPoints(ignore_hud_joints); + + return TRUE; +} - // ATTACHMENTS +//----------------------------------------------------------------------------- +// initAttachmentPoints(): creates attachment points if needed, sets state based on avatar_lad.xml. +//----------------------------------------------------------------------------- +void LLVOAvatar::initAttachmentPoints(bool ignore_hud_joints) +{ + LLAvatarXmlInfo::attachment_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin(); + iter != sAvatarXmlInfo->mAttachmentInfoList.end(); + ++iter) { - LLAvatarXmlInfo::attachment_info_list_t::iterator iter; - for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin(); - iter != sAvatarXmlInfo->mAttachmentInfoList.end(); - ++iter) + LLAvatarXmlInfo::LLAvatarAttachmentInfo *info = *iter; + if (info->mIsHUDAttachment && (!isSelf() || ignore_hud_joints)) { - LLAvatarXmlInfo::LLAvatarAttachmentInfo *info = *iter; - if (!isSelf() && info->mJointName == "mScreen") - { //don't process screen joint for other avatars - continue; - } - - LLViewerJointAttachment* attachment = new LLViewerJointAttachment(); - - attachment->setName(info->mName); - LLJoint *parentJoint = getJoint(info->mJointName); - if (!parentJoint) - { - LL_WARNS() << "No parent joint by name " << info->mJointName << " found for attachment point " << info->mName << LL_ENDL; - delete attachment; - continue; - } + //don't process hud joint for other avatars, or when doing a skeleton reset. + continue; + } - if (info->mHasPosition) - { - attachment->setOriginalPosition(info->mPosition); - } + S32 attachmentID = info->mAttachmentID; + if (attachmentID < 1 || attachmentID > 255) + { + LL_WARNS() << "Attachment point out of range [1-255]: " << attachmentID << " on attachment point " << info->mName << LL_ENDL; + continue; + } - if (info->mHasRotation) - { - LLQuaternion rotation; - rotation.setQuat(info->mRotationEuler.mV[VX] * DEG_TO_RAD, - info->mRotationEuler.mV[VY] * DEG_TO_RAD, - info->mRotationEuler.mV[VZ] * DEG_TO_RAD); - attachment->setRotation(rotation); - } + LLViewerJointAttachment* attachment = NULL; + bool newly_created = false; + if (mAttachmentPoints.find(attachmentID) == mAttachmentPoints.end()) + { + attachment = new LLViewerJointAttachment(); + newly_created = true; + } + else + { + attachment = mAttachmentPoints[attachmentID]; + } - int group = info->mGroup; - if (group >= 0) + attachment->setName(info->mName); + LLJoint *parent_joint = getJoint(info->mJointName); + if (!parent_joint) + { + // If the intended parent for attachment point is unavailable, avatar_lad.xml is corrupt. + LL_WARNS() << "No parent joint by name " << info->mJointName << " found for attachment point " << info->mName << LL_ENDL; + if( newly_created ) { - if (group < 0 || group >= 9) - { - LL_WARNS() << "Invalid group number (" << group << ") for attachment point " << info->mName << LL_ENDL; - } - else - { - attachment->setGroup(group); - } + delete attachment; } + continue; + } + + if (info->mHasPosition) + { + attachment->setOriginalPosition(info->mPosition); + attachment->setDefaultPosition(info->mPosition); + } - S32 attachmentID = info->mAttachmentID; - if (attachmentID < 1 || attachmentID > 255) + if (info->mHasRotation) + { + LLQuaternion rotation; + rotation.setQuat(info->mRotationEuler.mV[VX] * DEG_TO_RAD, + info->mRotationEuler.mV[VY] * DEG_TO_RAD, + info->mRotationEuler.mV[VZ] * DEG_TO_RAD); + attachment->setRotation(rotation); + } + + int group = info->mGroup; + if (group >= 0) + { + if (group < 0 || group >= NUM_ATTACHMENT_GROUPS ) { - LL_WARNS() << "Attachment point out of range [1-255]: " << attachmentID << " on attachment point " << info->mName << LL_ENDL; - delete attachment; - continue; + LL_WARNS() << "Invalid group number (" << group << ") for attachment point " << info->mName << LL_ENDL; } - if (mAttachmentPoints.find(attachmentID) != mAttachmentPoints.end()) + else { - LL_WARNS() << "Attachment point redefined with id " << attachmentID << " on attachment point " << info->mName << LL_ENDL; - delete attachment; - continue; + attachment->setGroup(group); } + } - attachment->setPieSlice(info->mPieMenuSlice); - attachment->setVisibleInFirstPerson(info->mVisibleFirstPerson); - attachment->setIsHUDAttachment(info->mIsHUDAttachment); + attachment->setPieSlice(info->mPieMenuSlice); + attachment->setVisibleInFirstPerson(info->mVisibleFirstPerson); + attachment->setIsHUDAttachment(info->mIsHUDAttachment); + // attachment can potentially be animated, needs a number. + attachment->setJointNum(mNumBones + mCollisionVolumes.size() + attachmentID - 1); + if (newly_created) + { mAttachmentPoints[attachmentID] = attachment; // now add attachment joint - parentJoint->addChild(attachment); + parent_joint->addChild(attachment); } } - - return TRUE; } //----------------------------------------------------------------------------- @@ -6228,7 +7384,26 @@ BOOL LLVOAvatar::loadSkeletonNode () //----------------------------------------------------------------------------- void LLVOAvatar::updateVisualParams() { - setSex( (getVisualParamWeight( "male" ) > 0.5f) ? SEX_MALE : SEX_FEMALE ); + ESex avatar_sex = (getVisualParamWeight("male") > 0.5f) ? SEX_MALE : SEX_FEMALE; + if (getSex() != avatar_sex) + { + if (mIsSitting && findMotion(avatar_sex == SEX_MALE ? ANIM_AGENT_SIT_FEMALE : ANIM_AGENT_SIT) != NULL) + { + // In some cases of gender change server changes sit motion with motion message, + // but in case of some avatars (legacy?) there is no update from server side, + // likely because server doesn't know about difference between motions + // (female and male sit ids are same server side, so it is likely unaware that it + // need to send update) + // Make sure motion is up to date + stopMotion(ANIM_AGENT_SIT); + setSex(avatar_sex); + startMotion(ANIM_AGENT_SIT); + } + else + { + setSex(avatar_sex); + } + } LLCharacter::updateVisualParams(); @@ -6256,7 +7431,7 @@ BOOL LLVOAvatar::isActive() const static LLFastTimer::DeclareTimer FTM_PIXEL_AREA("Pixel Area"); void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) { - LLFastTimer t(FTM_PIXEL_AREA); + LL_RECORD_BLOCK_TIME(FTM_PIXEL_AREA); if (mDrawable.isNull()) { return; @@ -6378,7 +7553,7 @@ void LLVOAvatar::updateGL() static LLFastTimer::DeclareTimer FTM_UPDATE_AVATAR("Update Avatar"); BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(FTM_UPDATE_AVATAR); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_AVATAR); if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR))) { return TRUE; @@ -6461,12 +7636,20 @@ BOOL LLVOAvatar::setParent(LLViewerObject* parent) void LLVOAvatar::addChild(LLViewerObject *childp) { childp->extractAttachmentItemID(); // find the inventory item this object is associated with. + if (isSelf()) + { + const LLUUID& item_id = childp->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attachment child added " << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + + } + LLViewerObject::addChild(childp); if (childp->mDrawable) { if (!attachObject(childp)) { - LL_WARNS() << "addChild() failed for " + LL_WARNS() << "ATT addChild() failed for " << childp->getID() << " item " << childp->getAttachmentItemID() << LL_ENDL; @@ -6489,20 +7672,9 @@ void LLVOAvatar::removeChild(LLViewerObject *childp) } } -namespace -{ - boost::signals2::connection sDetachBridgeConnection; - void detach_bridge(const LLViewerObject* obj, const LLViewerObject* bridge) - { - if (obj != bridge) return; - sDetachBridgeConnection.disconnect(); - LLVOAvatarSelf::detachAttachmentIntoInventory(obj->getAttachmentItemID()); - } -} - LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object) { - S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getState()); + S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getAttachmentState()); // This should never happen unless the server didn't process the attachment point // correctly, but putting this check in here to be safe. @@ -6520,11 +7692,6 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi << " trying to use 1 (chest)" << LL_ENDL; - if (isSelf() && attachmentID == 127 && gSavedSettings.getBOOL("SGDetachBridge")) - { - LL_INFOS() << "Bridge detected! detaching" << LL_ENDL; - sDetachBridgeConnection = gAgentAvatarp->setAttachmentCallback(boost::bind(detach_bridge, _1, viewer_object)); - } attachment = get_if_there(mAttachmentPoints, 1, (LLViewerJointAttachment*)NULL); // Arbitrary using 1 (chest) if (attachment) { @@ -6552,12 +7719,37 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi //----------------------------------------------------------------------------- const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object) { + if (isSelf()) + { + const LLUUID& item_id = viewer_object->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attaching object " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + } LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object); if (!attachment || !attachment->addObject(viewer_object)) { + const LLUUID& item_id = viewer_object->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_WARNS("Avatar") << "ATT attach failed " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; return 0; } + + // The object can already exist in the vector if it was attached while was already attached (causing a re-attach). + std::pair const val(viewer_object, attachment); + if (std::find(mAttachedObjectsVector.begin(), mAttachedObjectsVector.end(), val) == mAttachedObjectsVector.end()) + { + mAttachedObjectsVector.push_back(val); + } + + if (!viewer_object->isAnimatedObject()) + { + updateAttachmentOverrides(); + } + + updateVisualComplexity(); if (viewer_object->isSelected()) { @@ -6565,13 +7757,21 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o LLSelectMgr::getInstance()->updatePointAt(); } - // The object can already exist in the vector if it was attached while was already attached (causing a re-attach). - std::pair const val(viewer_object, attachment); - if (std::find(mAttachedObjectsVector.begin(), mAttachedObjectsVector.end(), val) == mAttachedObjectsVector.end()) - { - mAttachedObjectsVector.push_back(val); + viewer_object->refreshBakeTexture(); + + + LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); + for (const auto& iter : child_list) + { + LLViewerObject* objectp = iter; + if (objectp) + { + objectp->refreshBakeTexture(); + } } + updateMeshVisibility(); + return attachment; } @@ -6593,19 +7793,47 @@ U32 LLVOAvatar::getNumAttachments() const //----------------------------------------------------------------------------- // canAttachMoreObjects() +// Returns true if we can attach more objects. //----------------------------------------------------------------------------- -BOOL LLVOAvatar::canAttachMoreObjects() const +BOOL LLVOAvatar::canAttachMoreObjects(U32 n) const { - return (getNumAttachments() < MAX_AGENT_ATTACHMENTS); + return (getNumAttachments() + n) <= (U32)LLAgentBenefitsMgr::current().getAttachmentLimit(); } //----------------------------------------------------------------------------- -// canAttachMoreObjects() -// Returns true if we can attach more objects. +// getNumAnimatedObjectAttachments() //----------------------------------------------------------------------------- -BOOL LLVOAvatar::canAttachMoreObjects(U32 n) const +U32 LLVOAvatar::getNumAnimatedObjectAttachments() const +{ + U32 num_attachments = 0; + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + const LLViewerJointAttachment *attachment_pt = (*iter).second; + num_attachments += attachment_pt->getNumAnimatedObjects(); + } + return num_attachments; +} + +//----------------------------------------------------------------------------- +// getMaxAnimatedObjectAttachments() +// Gets from simulator feature if available, otherwise 0. +//----------------------------------------------------------------------------- +U32 LLVOAvatar::getMaxAnimatedObjectAttachments() const +{ + if (gSavedSettings.getBOOL("AnimatedObjectsIgnoreLimits")) + return U32_MAX; + return LLAgentBenefitsMgr::current().getAnimatedObjectLimit(); +} + +//----------------------------------------------------------------------------- +// canAttachMoreAnimatedObjects() +// Returns true if we can attach more animated objects. +//----------------------------------------------------------------------------- +BOOL LLVOAvatar::canAttachMoreAnimatedObjects(U32 n) const { - return (getNumAttachments() + n) <= MAX_AGENT_ATTACHMENTS; + return (getNumAnimatedObjectAttachments() + n) <= getMaxAnimatedObjectAttachments(); } //----------------------------------------------------------------------------- @@ -6620,7 +7848,14 @@ void LLVOAvatar::lazyAttach() LLPointer cur_attachment = mPendingAttachment[i]; if (cur_attachment->mDrawable) { - if(!attachObject(cur_attachment)) + if (isSelf()) + { + const LLUUID& item_id = cur_attachment->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attaching object " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + } + if (!attachObject(cur_attachment)) { // Drop it LL_WARNS() << "attachObject() failed for " << cur_attachment->getID() @@ -6641,7 +7876,7 @@ void LLVOAvatar::lazyAttach() void LLVOAvatar::resetHUDAttachments() { - +#if SLOW_ATTACHMENT_LIST for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -6654,6 +7889,14 @@ void LLVOAvatar::resetHUDAttachments() ++attachment_iter) { const LLViewerObject* attached_object = (*attachment_iter); +#else + for(auto& iter : mAttachedObjectsVector) + {{{ + const LLViewerJointAttachment* attachment = iter.second; + if (!attachment->getIsHUDAttachment()) + continue; + const LLViewerObject* attached_object = iter.first; +#endif if (attached_object && attached_object->mDrawable.notNull()) { gPipeline.markMoved(attached_object->mDrawable); @@ -6665,6 +7908,7 @@ void LLVOAvatar::resetHUDAttachments() void LLVOAvatar::rebuildRiggedAttachments( void ) { +#if SLOW_ATTACHMENT_LIST for ( attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter ) { LLViewerJointAttachment* pAttachment = iter->second; @@ -6674,6 +7918,12 @@ void LLVOAvatar::rebuildRiggedAttachments( void ) attachmentIter != attachmentIterEnd; ++attachmentIter) { const LLViewerObject* pAttachedObject = *attachmentIter; +#else + for(auto& iter : mAttachedObjectsVector) + {{ + const LLViewerObject* pAttachedObject = iter.first; + const LLViewerJointAttachment* pAttachment = iter.second; +#endif if ( pAttachment && pAttachedObject->mDrawable.notNull() ) { gPipeline.markRebuild(pAttachedObject->mDrawable); @@ -6686,27 +7936,15 @@ void LLVOAvatar::rebuildRiggedAttachments( void ) //----------------------------------------------------------------------------- void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO ) { - //If a VO has a skin that we'll reset the joint positions to their default - if ( pVO && pVO->mDrawable ) + LLUUID mesh_id; + if (getRiggedMeshID(pVO, mesh_id)) { - LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); - if ( pVObj ) + //resetJointsOnDetach(mesh_id); + if ( gAgentCamera.cameraCustomizeAvatar() ) { - const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); - if ( pSkinData - && pSkinData->mJointNames.size() > 20 // full rig - && pSkinData->mAlternateBindMatrix.size() > 0 ) - { - LLVOAvatar::resetJointPositionsToDefault(); - //Need to handle the repositioning of the cam, updating rig data etc during outfit editing - //This handles the case where we detach a replacement rig. - if ( gAgentCamera.cameraCustomizeAvatar() ) - { - gAgent.unpauseAnimation(); - //Still want to refocus on head bone - gAgentCamera.changeCameraToCustomizeAvatar(); - } - } + gAgent.unpauseAnimation(); + //Still want to refocus on head bone + gAgentCamera.changeCameraToCustomizeAvatar(); } } } @@ -6725,11 +7963,30 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) if (attachment->isObjectAttached(viewer_object)) { + updateVisualComplexity(); vector_replace_with_last(mAttachedObjectsVector,std::make_pair(viewer_object,attachment)); - + bool is_animated_object = viewer_object->isAnimatedObject(); cleanupAttachedMesh( viewer_object ); attachment->removeObject(viewer_object); + if (!is_animated_object) + { + updateAttachmentOverrides(); + } + viewer_object->refreshBakeTexture(); + + LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); + for (const auto& iter1 : child_list) + { + LLViewerObject* objectp = iter1; + if (objectp) + { + objectp->refreshBakeTexture(); + } + } + + updateMeshVisibility(); + LL_DEBUGS() << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << LL_ENDL; return TRUE; } @@ -6750,12 +8007,10 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) //----------------------------------------------------------------------------- void LLVOAvatar::sitDown(BOOL bSitting) { - if (mIsSitting != bSitting) mIdleTimer.reset(); // Sitting changed, not idle + if (isSitting() != bSitting) mIdleTimer.reset(); // Sitting changed, not idle mIsSitting = bSitting; if (isSelf()) { - LLFloaterAO::ChangeStand(); - // [RLVa:KB] - Checked: 2010-08-29 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c if (rlv_handler_t::isEnabled()) { @@ -6845,9 +8100,18 @@ void LLVOAvatar::getOffObject() LLVector3 cur_position_world = mDrawable->getWorldPosition(); LLQuaternion cur_rotation_world = mDrawable->getWorldRotation(); + if (mLastRootPos.length() >= MAX_STANDOFF_FROM_ORIGIN + && (cur_position_world.length() < MAX_STANDOFF_FROM_ORIGIN + || dist_vec(cur_position_world, mLastRootPos) > MAX_STANDOFF_DISTANCE_CHANGE)) + { + // Most likely drawable got updated too early or some updates were missed - we got relative position to non-existing parent + // restore coordinates from cache + cur_position_world = mLastRootPos; + } + // set *local* position based on last *world* position, since we're unparenting the avatar mDrawable->mXform.setPosition(cur_position_world); - mDrawable->mXform.setRotation(cur_rotation_world); + mDrawable->mXform.setRotation(cur_rotation_world); gPipeline.markMoved(mDrawable, TRUE); @@ -6858,7 +8122,10 @@ void LLVOAvatar::getOffObject() mRoot->setRotation(cur_rotation_world); mRoot->getXform()->update(); + if (mEnableDefaultMotions) + { startMotion(ANIM_AGENT_BODY_NOISE); + } if (isSelf()) { @@ -6993,8 +8260,9 @@ LLViewerObject* LLVOAvatar::getWornAttachment( const LLUUID& inv_item_id ) LLViewerObject * LLVOAvatar::findAttachmentByID( const LLUUID & target_id ) const { +#if SLOW_ATTACHMENT_LIST for(attachment_map_t::const_iterator attachment_points_iter = mAttachmentPoints.begin(); - attachment_points_iter != gAgentAvatarp->mAttachmentPoints.end(); + attachment_points_iter != mAttachmentPoints.end(); ++attachment_points_iter) { LLViewerJointAttachment* attachment = attachment_points_iter->second; @@ -7003,6 +8271,11 @@ LLViewerObject * LLVOAvatar::findAttachmentByID( const LLUUID & target_id ) cons ++attachment_iter) { LLViewerObject *attached_object = (*attachment_iter); +#else + for(auto& iter : mAttachedObjectsVector) + {{ + LLViewerObject* attached_object = iter.first; +#endif if (attached_object && attached_object->getID() == target_id) { @@ -7062,33 +8335,39 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, bool updateMeshTextures(); } +// virtual +bool LLVOAvatar::shouldRenderRigged() const +{ + return true; +} + +// FIXME: We have an mVisible member, set in updateVisibility(), but this +// function doesn't return it! isVisible() and mVisible are used +// different places for different purposes. mVisible seems to be more +// related to whether the actual avatar mesh is shown, and isVisible() +// to whether anything about the avatar is displayed in the scene. +// Maybe better naming could make this clearer? BOOL LLVOAvatar::isVisible() const { return mDrawable.notNull() + && (!mOrphaned || isSelf()) && (mDrawable->isVisible() || mIsDummy); } // Determine if we have enough avatar data to render BOOL LLVOAvatar::getIsCloud() const { - // Do we have a shape? - if ((const_cast(this))->visualParamWeightsAreDefault()) - { - return TRUE; - } - - if (!isTextureDefined(TEX_LOWER_BAKED) || - !isTextureDefined(TEX_UPPER_BAKED) || - !isTextureDefined(TEX_HEAD_BAKED)) + if (mIsDummy) { - return TRUE; + return false; } - if (isTooComplex()) - { - return TRUE; - } - return FALSE; + return ( ((const_cast(this))->visualParamWeightsAreDefault())// Do we have a shape? + || ( !isTextureDefined(TEX_LOWER_BAKED) + || !isTextureDefined(TEX_UPPER_BAKED) + || !isTextureDefined(TEX_HEAD_BAKED) + ) + ); } void LLVOAvatar::updateRezzedStatusTimers() @@ -7109,6 +8388,7 @@ void LLVOAvatar::updateRezzedStatusTimers() for (S32 i = 1; i < 4; i++) { startPhase("load_" + LLVOAvatar::rezStatusToString(i)); + startPhase("first_load_" + LLVOAvatar::rezStatusToString(i)); } } if (rez_status < mLastRezzedStatus) @@ -7125,6 +8405,7 @@ void LLVOAvatar::updateRezzedStatusTimers() for (S32 i = llmax(mLastRezzedStatus+1,1); i <= rez_status; i++) { stopPhase("load_" + LLVOAvatar::rezStatusToString(i)); + stopPhase("first_load_" + LLVOAvatar::rezStatusToString(i), false); } if (rez_status == 3) { @@ -7132,9 +8413,10 @@ void LLVOAvatar::updateRezzedStatusTimers() selfStopPhase("update_appearance_from_cof"); selfStopPhase("wear_inventory_category", false); selfStopPhase("process_initial_wearables_update", false); + + updateVisualComplexity(); } } - mLastRezzedStatus = rez_status; } } @@ -7254,14 +8536,7 @@ void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapse record["grid_y"] = LLSD::Integer(grid_y); record["is_using_server_bakes"] = ((bool) isUsingServerBakes()); record["is_self"] = isSelf(); - - -#if 0 // verbose logging - std::ostringstream ostr; - ostr << LLSDNotationStreamer(record); - LL_DEBUGS("Avatar") << "record\n" << ostr.str() << LL_ENDL; -#endif - + if (isAgentAvatarValid()) { gAgentAvatarp->addMetricsTimerRecord(record); @@ -7339,9 +8614,9 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) BOOL LLVOAvatar::isFullyLoaded() const { - static LLCachedControl const render_unloaded_avatar("RenderUnloadedAvatar", false); + static const LLCachedControl render_unloaded_avatar("RenderUnloadedAvatar", false); -// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-2.2.0a) | Added: Catznip-2.2.0a +// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-2.2) // Changes to LLAppearanceMgr::updateAppearanceFromCOF() expect this function to actually return mFullyLoaded for gAgentAvatarp return (render_unloaded_avatar && !isSelf()) ||(mFullyLoaded); // [/SL:KB] @@ -7350,13 +8625,33 @@ BOOL LLVOAvatar::isFullyLoaded() const bool LLVOAvatar::isTooComplex() const { - static LLCachedControl ava_complexity_limit(gSavedSettings, "RenderAvatarComplexityLimit"); - if (ava_complexity_limit > 0 && mVisualComplexity >= ava_complexity_limit) + static const LLCachedControl always_render_friends("AlwaysRenderFriends", 0); + bool too_complex; + // 'AlwaysRenderFriends' == 0, or an animesh, falls through to the complexity limits, if not self. Self is always rendered. + // 1 always render friends, 2 render only friends, 3 render only self + if (isSelf() || (always_render_friends && always_render_friends != 3 && !isControlAvatar() && LLAvatarTracker::instance().isBuddy(getID()))) { - return true; + too_complex = false; + } + else if (always_render_friends >= 2 && !isControlAvatar()) + { + too_complex = true; + } + else + { + // Determine if visually muted or not + static LLCachedControl max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0U); + static LLCachedControl max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 1000.0f); + // If the user has chosen unlimited max complexity, we also disregard max attachment area + // so that unlimited will completely disable the overly complex impostor rendering + // yes, this leaves them vulnerable to griefing objects... their choice + too_complex = ( max_render_cost > 0 + && (mVisualComplexity > max_render_cost + || (max_attachment_area > 0.0f && mAttachmentSurfaceArea > max_attachment_area) + )); } - return false; + return too_complex; } @@ -7388,6 +8683,109 @@ void LLVOAvatar::debugColorizeSubMeshes(U32 i, const LLColor4& color) } } + +//----------------------------------------------------------------------------- +// updateMeshVisibility() +// Hide the mesh joints if attachments are using baked textures +//----------------------------------------------------------------------------- +void LLVOAvatar::updateMeshVisibility() +{ + bool bake_flag[BAKED_NUM_INDICES]; + memset(bake_flag, 0, BAKED_NUM_INDICES*sizeof(bool)); + + for (auto& attachment_point : mAttachmentPoints) + { + LLViewerJointAttachment* attachment = attachment_point.second; + if (attachment) + { + for (auto objectp : attachment->mAttachedObjects) + { + if (objectp) + { + for (int face_index = 0; face_index < objectp->getNumTEs(); face_index++) + { + LLTextureEntry* tex_entry = objectp->getTE(face_index); + bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD); + bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES); + bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR); + bake_flag[BAKED_LOWER] |= (tex_entry->getID() == IMG_USE_BAKED_LOWER); + bake_flag[BAKED_UPPER] |= (tex_entry->getID() == IMG_USE_BAKED_UPPER); + bake_flag[BAKED_SKIRT] |= (tex_entry->getID() == IMG_USE_BAKED_SKIRT); + bake_flag[BAKED_LEFT_ARM] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTARM); + bake_flag[BAKED_LEFT_LEG] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTLEG); + bake_flag[BAKED_AUX1] |= (tex_entry->getID() == IMG_USE_BAKED_AUX1); + bake_flag[BAKED_AUX2] |= (tex_entry->getID() == IMG_USE_BAKED_AUX2); + bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3); + } + } + + LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); + for (const auto& iter1 : child_list) + { + LLViewerObject* objectchild = iter1; + if (objectchild) + { + for (int face_index = 0; face_index < objectchild->getNumTEs(); face_index++) + { + LLTextureEntry* tex_entry = objectchild->getTE(face_index); + bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD); + bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES); + bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR); + bake_flag[BAKED_LOWER] |= (tex_entry->getID() == IMG_USE_BAKED_LOWER); + bake_flag[BAKED_UPPER] |= (tex_entry->getID() == IMG_USE_BAKED_UPPER); + bake_flag[BAKED_SKIRT] |= (tex_entry->getID() == IMG_USE_BAKED_SKIRT); + bake_flag[BAKED_LEFT_ARM] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTARM); + bake_flag[BAKED_LEFT_LEG] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTLEG); + bake_flag[BAKED_AUX1] |= (tex_entry->getID() == IMG_USE_BAKED_AUX1); + bake_flag[BAKED_AUX2] |= (tex_entry->getID() == IMG_USE_BAKED_AUX2); + bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3); + } + } + } + } + } + } + + //LL_INFOS() << "head " << bake_flag[BAKED_HEAD] << "eyes " << bake_flag[BAKED_EYES] << "hair " << bake_flag[BAKED_HAIR] << "lower " << bake_flag[BAKED_LOWER] << "upper " << bake_flag[BAKED_UPPER] << "skirt " << bake_flag[BAKED_SKIRT] << LL_ENDL; + + for (size_t i = 0; i < mMeshLOD.size(); i++) + { + LLAvatarJoint* joint = mMeshLOD[i]; + if (i == MESH_ID_HAIR) + { + joint->setVisible(!bake_flag[BAKED_HAIR], TRUE); + } + else if (i == MESH_ID_HEAD) + { + joint->setVisible(!bake_flag[BAKED_HEAD], TRUE); + } + else if (i == MESH_ID_SKIRT) + { + joint->setVisible(!bake_flag[BAKED_SKIRT], TRUE); + } + else if (i == MESH_ID_UPPER_BODY) + { + joint->setVisible(!bake_flag[BAKED_UPPER], TRUE); + } + else if (i == MESH_ID_LOWER_BODY) + { + joint->setVisible(!bake_flag[BAKED_LOWER], TRUE); + } + else if (i == MESH_ID_EYEBALL_LEFT) + { + joint->setVisible(!bake_flag[BAKED_EYES], TRUE); + } + else if (i == MESH_ID_EYEBALL_RIGHT) + { + joint->setVisible(!bake_flag[BAKED_EYES], TRUE); + } + else if (i == MESH_ID_EYELASH) + { + joint->setVisible(!bake_flag[BAKED_HEAD], TRUE); + } + } +} + //----------------------------------------------------------------------------- // updateMeshTextures() // Uses the current TE values to set the meshes' and layersets' textures. @@ -7397,7 +8795,6 @@ void LLVOAvatar::updateMeshTextures() { static S32 update_counter = 0; mBakedTextureDebugText.clear(); - if (gNoRender) return; // if user has never specified a texture, assign the default for (U32 i=0; i < getNumTEs(); i++) @@ -7494,7 +8891,7 @@ void LLVOAvatar::updateMeshTextures() const std::string url = getImageURL(te, mBakedTextureDatas[i].mLastTextureID); if (!url.empty()) { - baked_img = LLViewerTextureManager::getFetchedTextureFromUrl(url, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, mBakedTextureDatas[i].mLastTextureID); + baked_img = LLViewerTextureManager::getFetchedTextureFromUrl(url, FTT_HOST_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, mBakedTextureDatas[i].mLastTextureID); } else { @@ -7505,7 +8902,7 @@ void LLVOAvatar::updateMeshTextures() LL_WARNS() << "updateMeshTextures: invalid host for object: " << getID() << LL_ENDL; } - baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureDatas[i].mLastTextureID, target_host ); + baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureDatas[i].mLastTextureID, FTT_HOST_BAKE, target_host ); } llassert(baked_img == existing_baked_img); @@ -7535,6 +8932,8 @@ void LLVOAvatar::updateMeshTextures() // we'll consider it loaded and use it (rather than // doing compositing). useBakedTexture( baked_img->getID() ); + mLoadedCallbacksPaused |= !isVisible(); + checkTextureLoading(); } else { @@ -7547,6 +8946,10 @@ void LLVOAvatar::updateMeshTextures() } baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ), src_callback_list, paused ); + + // this could add paused texture callbacks + mLoadedCallbacksPaused |= paused; + checkTextureLoading(); } } else if (layerset && isUsingLocalAppearance()) @@ -7577,7 +8980,7 @@ void LLVOAvatar::updateMeshTextures() // set texture and color of hair manually if we are not using a baked image. // This can happen while loading hair for yourself, or for clients that did not // bake a hair texture. Still needed for yourself after 1.22 is depricated. - if (!is_layer_baked[BAKED_HAIR] || isEditingAppearance()) + if (!is_layer_baked[BAKED_HAIR]) { const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1); LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 ); @@ -7615,7 +9018,39 @@ void LLVOAvatar::updateMeshTextures() } } } - removeMissingBakedTextures(); + + // removeMissingBakedTextures() will call back into this rountine if something is removed, and can blow up the stack + static bool call_remove_missing = true; + if (call_remove_missing) + { + call_remove_missing = false; + removeMissingBakedTextures(); // May call back into this function if anything is removed + call_remove_missing = true; + } + + //refresh bakes on any attached objects + for (auto& attachment_point : mAttachmentPoints) + { + LLViewerJointAttachment* attachment = attachment_point.second; + + for (auto attached_object : attachment->mAttachedObjects) + { + if (attached_object && !attached_object->isDead()) + { + attached_object->refreshBakeTexture(); + + LLViewerObject::const_child_list_t& child_list = attached_object->getChildren(); + for (const auto& iter : child_list) + { + LLViewerObject* objectp = iter; + if (objectp && !objectp->isDead()) + { + objectp->refreshBakeTexture(); + } + } + } + } + } } // virtual @@ -7843,6 +9278,7 @@ BOOL LLVOAvatar::hasHUDAttachment() const LLBBox LLVOAvatar::getHUDBBox() const { LLBBox bbox; +#if SLOW_ATTACHMENT_LIST for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -7855,6 +9291,14 @@ LLBBox LLVOAvatar::getHUDBBox() const ++attachment_iter) { const LLViewerObject* attached_object = (*attachment_iter); +#else + for(auto& iter : mAttachedObjectsVector) + {{{ + const LLViewerJointAttachment* attachment = iter.second; + if (!attachment || !attachment->getIsHUDAttachment()) + continue; + const LLViewerObject* attached_object = iter.first; +#endif if (attached_object == NULL) { LL_WARNS() << "HUD attached object is NULL!" << LL_ENDL; @@ -7916,6 +9360,9 @@ void LLVOAvatar::onFirstTEMessageReceived() LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL; image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ), src_callback_list, paused ); + + // this could add paused texture callbacks + mLoadedCallbacksPaused |= paused; } } @@ -7958,20 +9405,21 @@ bool LLVOAvatar::visualParamWeightsAreDefault() return rtn; } -void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value) +void dump_visual_param(apr_file_t* file, LLVisualParam const* viewer_param, F32 value) { S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight()); - apr_file_printf(file.getFileHandle(), " \n", + apr_file_printf(file, " \n", viewer_param->getID(), viewer_param->getName().c_str(), value, u8_value, viewer_param->getTypeString(), viewer_param->getDumpWearableTypeName().c_str()); } void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix, - const std::vector& params_for_dump, - const LLTEContents& tec) + const LLAppearanceMessageContents& contents) { std::string outfilename = get_sequential_numbered_file_name(dump_prefix,".xml"); + const std::vector& params_for_dump = contents.mParamWeights; + const LLTEContents& tec = contents.mTEContents; LLAPRFile outfile; std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); @@ -7986,9 +9434,14 @@ void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix, LL_DEBUGS("Avatar") << "dumping appearance message to " << fullpath << LL_ENDL; } + apr_file_printf(file, "
    \n"); + apr_file_printf(file, "\t\t\n", contents.mCOFVersion); + apr_file_printf(file, "\t\t\n", contents.mAppearanceVersion); + apr_file_printf(file, "
    \n"); + apr_file_printf(file, "\n\n"); LLVisualParam* param = getFirstVisualParam(); - for (S32 i = 0; i < (S32)params_for_dump.size(); i++) + for (const auto& param_for_dump : params_for_dump) { while( param && ((param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && (param->getGroup() != VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE)) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT @@ -7996,16 +9449,20 @@ void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix, param = getNextVisualParam(); } LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; - F32 value = params_for_dump[i]; - dump_visual_param(outfile, viewer_param, value); + F32 value = param_for_dump; + dump_visual_param(file, viewer_param, value); param = getNextVisualParam(); } + apr_file_printf(file, "\n"); + + apr_file_printf(file, "\n\n"); for (U32 i = 0; i < tec.face_count; i++) { std::string uuid_str; ((LLUUID*)tec.image_data)[i].toString(uuid_str); apr_file_printf( file, "\t\t\n", i, uuid_str.c_str()); } + apr_file_printf(file, "\n"); } void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMessageContents& contents) @@ -8141,6 +9598,7 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32 //----------------------------------------------------------------------------- void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { + static S32 largestSelfCOFSeen(LLViewerInventoryCategory::VERSION_UNKNOWN); LL_DEBUGS("Avatar") << "starts" << LL_ENDL; bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"); @@ -8153,64 +9611,56 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) mLastAppearanceMessageTimer.reset(); - ESex old_sex = getSex(); - - LLAppearanceMessageContents contents; - parseAppearanceMessage(mesgsys, contents); + LLPointer contents(new LLAppearanceMessageContents); + parseAppearanceMessage(mesgsys, *contents); if (enable_verbose_dumps) { - dumpAppearanceMsgParams(dump_prefix + "appearance_msg", contents.mParamWeights, contents.mTEContents); + dumpAppearanceMsgParams(dump_prefix + "appearance_msg", *contents); } S32 appearance_version; - if (!resolve_appearance_version(contents, appearance_version)) + if (!resolve_appearance_version(*contents, appearance_version)) { LL_WARNS() << "bad appearance version info, discarding" << LL_ENDL; return; } - + llassert(appearance_version > 0); if (appearance_version > 1) { LL_WARNS() << "unsupported appearance version " << appearance_version << ", discarding appearance message" << LL_ENDL; return; } - S32 this_update_cof_version = contents.mCOFVersion; - S32 last_update_request_cof_version = mLastUpdateRequestCOFVersion; + S32 thisAppearanceVersion(contents->mCOFVersion); // Only now that we have result of appearance_version can we decide whether to bail out. if( isSelf() ) { - LL_DEBUGS("Avatar") << "this_update_cof_version " << this_update_cof_version - << " last_update_request_cof_version " << last_update_request_cof_version + LL_DEBUGS("Avatar") << "thisAppearanceVersion " << thisAppearanceVersion + << " mLastUpdateRequestCOFVersion " << mLastUpdateRequestCOFVersion << " my_cof_version " << LLAppearanceMgr::instance().getCOFVersion() << LL_ENDL; - if (getRegion() && (getRegion()->getCentralBakeVersion()==0)) - { - LL_WARNS() << avString() << "Received AvatarAppearance message for self in non-server-bake region" << LL_ENDL; - } - if( mFirstTEMessageReceived && (appearance_version == 0)) + if (largestSelfCOFSeen > thisAppearanceVersion) { + LL_WARNS("Avatar") << "Already processed appearance for COF version " << + largestSelfCOFSeen << ", discarding appearance with COF " << thisAppearanceVersion << LL_ENDL; return; } + largestSelfCOFSeen = thisAppearanceVersion; + } else { LL_DEBUGS("Avatar") << "appearance message received" << LL_ENDL; } - if (gNoRender) - { - return; - } - // Check for stale update. if (isSelf() && (appearance_version>0) - && (this_update_cof_version < last_update_request_cof_version)) + && (thisAppearanceVersion < mLastUpdateRequestCOFVersion)) { - LL_WARNS() << "Stale appearance update, wanted version " << last_update_request_cof_version - << ", got " << this_update_cof_version << LL_ENDL; + LL_WARNS() << "Stale appearance update, wanted version " << mLastUpdateRequestCOFVersion + << ", got " << thisAppearanceVersion << LL_ENDL; return; } @@ -8221,7 +9671,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } // SUNSHINE CLEANUP - is this case OK now? - S32 num_params = contents.mParamWeights.size(); + S32 num_params = contents->mParamWeights.size(); if (num_params <= 1) { // In this case, we have no reliable basis for knowing @@ -8233,29 +9683,42 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } // No backsies zone - if we get here, the message should be valid and usable, will be processed. - + LL_INFOS("Avatar") << "Processing appearance message version " << thisAppearanceVersion << LL_ENDL; setIsUsingServerBakes(appearance_version > 0); // Note: // RequestAgentUpdateAppearanceResponder::onRequestRequested() // assumes that cof version is only updated with server-bake // appearance messages. - mLastUpdateReceivedCOFVersion = this_update_cof_version; - - applyParsedTEMessage(contents.mTEContents); + mLastUpdateReceivedCOFVersion = thisAppearanceVersion; SHClientTagMgr::instance().updateAvatarTag(this); + mLastProcessedAppearance = contents; + + bool slam_params = false; + applyParsedAppearanceMessage(*contents, slam_params); +} + +void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& contents, bool slam_params) +{ + S32 num_params = contents.mParamWeights.size(); + ESex old_sex = getSex(); + + if (applyParsedTEMessage(contents.mTEContents) > 0 && isChanged(TEXTURE)) + { + updateVisualComplexity(); + } // prevent the overwriting of valid baked textures with invalid baked textures for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++) { if (!isTextureDefined(mBakedTextureDatas[baked_index].mTextureIndex) && mBakedTextureDatas[baked_index].mLastTextureID != IMG_DEFAULT - && baked_index != BAKED_SKIRT) + && baked_index != BAKED_SKIRT && baked_index != BAKED_LEFT_ARM && baked_index != BAKED_LEFT_LEG && baked_index != BAKED_AUX1 && baked_index != BAKED_AUX2 && baked_index != BAKED_AUX3) { LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using mLastTextureID " << mBakedTextureDatas[baked_index].mLastTextureID << LL_ENDL; setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, - LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureID, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureID, FTT_HOST_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } else { @@ -8296,17 +9759,15 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) LLVisualParam* param = contents.mParams[i]; F32 newWeight = contents.mParamWeights[i]; - if(param->getID() == 10000) - { + if (!mHasPhysicsParameters && param->getID() == 10000) mHasPhysicsParameters = true; - } - if (is_first_appearance_message || (param->getWeight() != newWeight)) + if (slam_params || is_first_appearance_message || (param->getWeight() != newWeight)) { params_changed = TRUE; params_changed_count++; - if(is_first_appearance_message) + if(is_first_appearance_message || slam_params ) { //LL_DEBUGS("Avatar") << "param slam " << i << " " << newWeight << LL_ENDL; param->setWeight(newWeight, FALSE); @@ -8387,11 +9848,41 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) if (isSelf()) { - mUseLocalAppearance = false; + mUseLocalAppearance = false; + } + + updateMeshTextures(); + //if (enable_verbose_dumps) dumpArchetypeXML(dump_prefix + "process_end"); + updateMeshVisibility(); +} + +LLViewerTexture* LLVOAvatar::getBakedTexture(const U8 te) +{ + if (te < 0 || te >= BAKED_NUM_INDICES) + { + return NULL; + } + + BOOL is_layer_baked = isTextureDefined(mBakedTextureDatas[te].mTextureIndex); + + LLViewerTexLayerSet* layerset = NULL; + layerset = getTexLayerSet(te); + + + if (!isEditingAppearance() && is_layer_baked) + { + LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage(mBakedTextureDatas[te].mTextureIndex, 0), TRUE); + return baked_img; + } + else if (layerset && isEditingAppearance()) + { + layerset->createComposite(); + layerset->setUpdatesEnabled(TRUE); + + return layerset->getViewerComposite(); } - updateMeshTextures(); - //if (enable_verbose_dumps) dumpArchetypeXML(dump_prefix + "process_end"); + return NULL; } // static @@ -8446,11 +9937,10 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture return; } - U32 gl_name; - LLImageGL::generateTextures(1, &gl_name ); + auto gl_name = LLImageGL::createTextureName(); stop_glerror(); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name->getTexName()); stop_glerror(); LLImageGL::setManualImage( @@ -8482,10 +9972,6 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; self->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1, baked_index); maskData->mLastDiscardLevel = discard_level; - if (self->mBakedTextureDatas[baked_index].mMaskTexName) - { - LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName)); - } self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name; found_texture_id = true; break; @@ -8494,7 +9980,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture } if (!found_texture_id) { - LL_INFOS() << "onBakedTextureMasksLoaded(): unexpected image id: " << id << LL_ENDL; + LL_INFOS() << "unexpected image id: " << id << LL_ENDL; } self->dirtyMesh(); } @@ -8655,6 +10141,40 @@ void dump_sequential_xml(const std::string outprefix, const LLSD& content) LL_DEBUGS("Avatar") << "results saved to: " << fullpath << LL_ENDL; } + +void LLVOAvatar::getSortedJointNames(S32 joint_type, std::vector& result) const +{ + result.clear(); + if (joint_type==0) + { + avatar_joint_list_t::const_iterator iter = mSkeleton.begin(); + avatar_joint_list_t::const_iterator end = mSkeleton.end(); + for (; iter != end; ++iter) + { + LLJoint* pJoint = (*iter); + result.push_back(pJoint->getName()); + } + } + else if (joint_type==1) + { + for (const auto& pJoint : mCollisionVolumes) + { + result.push_back(pJoint->getName()); + } + } + else if (joint_type==2) + { + for (LLVOAvatar::attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); ++iter) + { + LLViewerJointAttachment* pJoint = iter->second; + if (!pJoint) continue; + result.push_back(pJoint->getName()); + } + } + std::sort(result.begin(), result.end()); +} + void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_wearables ) { std::string outprefix(prefix); @@ -8672,8 +10192,7 @@ void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_b { try { - AIFile outfile(fullpath, "wb"); - AIXMLLindenGenepool linden_genepool(outfile); + AIXMLLindenGenepool linden_genepool(fullpath); if (group_by_wearables) { @@ -8833,14 +10352,14 @@ void LLVOAvatar::cullAvatarsByPixelArea() if (gFrameTimeSeconds != sUnbakedUpdateTime) // only update once per frame { sUnbakedUpdateTime = gFrameTimeSeconds; - sUnbakedTime += gFrameIntervalSeconds; + sUnbakedTime += gFrameIntervalSeconds.value(); } if (grey_avatars > 0) { if (gFrameTimeSeconds != sGreyUpdateTime) // only update once per frame { sGreyUpdateTime = gFrameTimeSeconds; - sGreyTime += gFrameIntervalSeconds; + sGreyTime += gFrameIntervalSeconds.value(); } } } @@ -8856,16 +10375,6 @@ void LLVOAvatar::startAppearanceAnimation() } } -//virtual -void LLVOAvatar::bodySizeChanged() -{ - if (isSelf() && !LLAppearanceMgr::instance().isInUpdateAppearanceFromCOF()) - { // notify simulator of change in size - // but not if we are in the middle of updating appearance - gAgent.sendAgentSetAppearance(); - } -} - BOOL LLVOAvatar::isUsingServerBakes() const { #if 1 @@ -8902,6 +10411,7 @@ void LLVOAvatar::updateRegion(LLViewerRegion *regionp) LLViewerObject::updateRegion(regionp); } +// virtual std::string LLVOAvatar::getFullname() const { std::string name; @@ -8948,7 +10458,12 @@ void LLVOAvatar::updateFreezeCounter(S32 counter) BOOL LLVOAvatar::updateLOD() { - if (isImpostor()) + if (mDrawable.isNull()) + { + return FALSE; + } + + if (isImpostor() && 0 != mDrawable->getNumFaces() && mDrawable->getFace(0)->hasGeometry()) { return TRUE; } @@ -8973,12 +10488,155 @@ BOOL LLVOAvatar::updateLOD() return res; } -void LLVOAvatar::updateLODRiggedAttachments( void ) +void LLVOAvatar::updateLODRiggedAttachments() { updateLOD(); rebuildRiggedAttachments(); } +void showRigInfoTabExtents(LLVOAvatar *avatar, LLJointRiggingInfoTab& tab, S32& count_rigged, S32& count_box) +{ + count_rigged = count_box = 0; + LLVector4a zero_vec; + zero_vec.clear(); + for (S32 i=0; igetJoint(i); + LL_DEBUGS("RigSpam") << "joint " << i << " name " << joint->getName() << " box " + << tab[i].getRiggedExtents()[0] << ", " << tab[i].getRiggedExtents()[1] << LL_ENDL; + if ((!tab[i].getRiggedExtents()[0].equals3(zero_vec)) || + (!tab[i].getRiggedExtents()[1].equals3(zero_vec))) + { + count_box++; + } + } + } +} + +void LLVOAvatar::getAssociatedVolumes(std::vector& volumes) +{ +#if SLOW_ATTACHMENT_LIST + for ( LLVOAvatar::attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter ) + { + LLViewerJointAttachment* attachment = iter->second; + LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_end = attachment->mAttachedObjects.end(); + + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_iter = attachment->mAttachedObjects.begin(); + attach_iter != attach_end; ++attach_iter) + { + LLViewerObject* attached_object = *attach_iter; +#else + for(auto& iter : mAttachedObjectsVector) + {{ + LLViewerObject* attached_object = iter.first; +#endif + LLVOVolume *volume = attached_object->asVolume(); + if (volume) + { + volumes.push_back(volume); + if (volume->isAnimatedObject()) + { + // For animated object attachment, don't need + // the children. Will just get bounding box + // from the control avatar. + continue; + } + } + LLViewerObject::const_child_list_t& children = attached_object->getChildren(); + for (LLViewerObject* childp : children) + { + if (!childp) + continue; + + LLVOVolume *volume = childp->asVolume(); + if (volume) + { + volumes.push_back(volume); + } + } + } + } + + LLControlAvatar *control_av = asControlAvatar(); + if (control_av) + { + LLVOVolume *volp = control_av->mRootVolp; + if (volp) + { + volumes.push_back(volp); + LLViewerObject::const_child_list_t& children = volp->getChildren(); + for (LLViewerObject* childp : children) + { + LLVOVolume *volume = childp ? childp->asVolume() : nullptr; + if (volume) + { + volumes.push_back(volume); + } + } + } + } +} + +static LLTrace::BlockTimerStatHandle FTM_AVATAR_RIGGING_INFO_UPDATE("Av Upd Rig Info"); +static LLTrace::BlockTimerStatHandle FTM_AVATAR_RIGGING_KEY_UPDATE("Av Upd Rig Key"); +static LLTrace::BlockTimerStatHandle FTM_AVATAR_RIGGING_AVOL_UPDATE("Av Upd Avol"); + +// virtual +void LLVOAvatar::updateRiggingInfo() +{ + LL_RECORD_BLOCK_TIME(FTM_AVATAR_RIGGING_INFO_UPDATE); + + LL_DEBUGS("RigSpammish") << getFullname() << " updating rig tab" << LL_ENDL; + + std::vector volumes; + + { + LL_RECORD_BLOCK_TIME(FTM_AVATAR_RIGGING_AVOL_UPDATE); + getAssociatedVolumes(volumes); + } + + std::map curr_rigging_info_key; + { + LL_RECORD_BLOCK_TIME(FTM_AVATAR_RIGGING_KEY_UPDATE); + // Get current rigging info key + for (std::vector::iterator it = volumes.begin(); it != volumes.end(); ++it) + { + LLVOVolume *vol = *it; + if (vol->isRiggedMesh() && vol->getVolume() && vol->getVolume()->isMeshAssetLoaded()) + { + const LLUUID& mesh_id = vol->getVolume()->getParams().getSculptID(); + S32 max_lod = llmax(vol->getLOD(), vol->mLastRiggingInfoLOD); + curr_rigging_info_key[mesh_id] = max_lod; + } + } + + // Check for key change, which indicates some change in volume composition or LOD. + if (curr_rigging_info_key == mLastRiggingInfoKey) + { + return; + } + } + + // Something changed. Update. + mLastRiggingInfoKey = curr_rigging_info_key; + mJointRiggingInfoTab.clear(); + for (std::vector::iterator it = volumes.begin(); it != volumes.end(); ++it) + { + LLVOVolume *vol = *it; + vol->updateRiggingInfo(); + mJointRiggingInfoTab.merge(vol->mJointRiggingInfoTab); + } + + //LL_INFOS() << "done update rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL; + LL_DEBUGS("RigSpammish") << getFullname() << " after update rig tab:" << LL_ENDL; + S32 joint_count, box_count; + showRigInfoTabExtents(this, mJointRiggingInfoTab, joint_count, box_count); + LL_DEBUGS("RigSpammish") << "uses " << joint_count << " joints " << " nonzero boxes: " << box_count << LL_ENDL; +} + void LLVOAvatar::updateSoftwareSkinnedVertices(const LLMeshSkinInfo* skin, const LLVector4a* weight, const LLVolumeFace& vol_face, LLVertexBuffer *buffer) { //perform software vertex skinning for this face @@ -8996,76 +10654,48 @@ void LLVOAvatar::updateSoftwareSkinnedVertices(const LLMeshSkinInfo* skin, const LLVector4a* pos = (LLVector4a*) position.get(); LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL; - - //build matrix palette - LLMatrix4a mp[JOINT_COUNT]; - U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT); - - llassert_always(count); - - for (U32 j = 0; j < count; ++j) - { - LLJoint* joint = getJoint(skin->mJointNames[j]); - if(!joint) - { - joint = getJoint("mRoot"); - } - if (joint) - { - LLMatrix4a mat; - mat.loadu((F32*)skin->mInvBindMatrix[j].mMatrix); - mp[j].setMul(joint->getWorldMatrix(),mat); - } - } + //build matrix palette + LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; + U32 count = LLSkinningUtil::getMeshJointCount(skin); + LLSkinningUtil::initSkinningMatrixPalette(mat, count, skin, this, true); + LLSkinningUtil::checkSkinWeights(weight, buffer->getNumVerts(), skin); LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); + LLVector4a av_pos; + av_pos.load3(getPosition().mV); + + const U32 max_joints = LLSkinningUtil::getMaxJointCount(); for (U32 j = 0; j < (U32)buffer->getNumVerts(); ++j) { LLMatrix4a final_mat; - final_mat.clear(); - - S32 idx[4]; - - LLVector4 wght; - - F32 scale = 0.f; - for (U32 k = 0; k < 4; k++) - { - F32 w = weight[j][k]; - - idx[k] = (S32) floorf(w); - wght[k] = w - floorf(w); - scale += wght[k]; - } + LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); - if(scale > 0.f) - wght *= 1.f/scale; - else - wght = LLVector4(F32_MAX,F32_MAX,F32_MAX,F32_MAX); + LLVector4a& v = vol_face.mPositions[j]; - for (U32 k = 0; k < 4; k++) - { - F32 w = wght[k]; - LLMatrix4a src; - src.setMul(mp[idx[k]], w); + LLVector4a t; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, pos[j]); - final_mat.add(src); - } - - final_mat.mul(bind_shape_matrix); - final_mat.affineTransform(vol_face.mPositions[j], pos[j]); + pos[j].add(av_pos); // Algorithm tweaked to stop hosing up normals. if (norm) { + LLVector4a& n = vol_face.mNormals[j]; final_mat.invert(); final_mat.transpose(); - final_mat.affineTransform(vol_face.mNormals[j], norm[j]); + final_mat.affineTransform(n, norm[j]); } } } + +void LLVOAvatar::onActiveOverrideMeshesChanged() +{ + mJointRiggingInfoTab.setNeedsUpdate(true); +} + U32 LLVOAvatar::getPartitionType() const { // Avatars merely exist as drawables in the bridge partition @@ -9075,10 +10705,10 @@ U32 LLVOAvatar::getPartitionType() const //static void LLVOAvatar::updateImpostors() { - LLCharacter::sAllowInstancesChange = FALSE ; - - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + std::vector instances_copy = LLCharacter::sInstances; + for (std::vector::iterator iter = instances_copy.begin(); + iter != instances_copy.end(); ++iter) { LLVOAvatar* avatar = (LLVOAvatar*) *iter; if (!avatar->isDead() && avatar->needsImpostorUpdate() && avatar->isVisible() && avatar->isImpostor()) @@ -9086,8 +10716,6 @@ void LLVOAvatar::updateImpostors() gPipeline.generateImpostor(avatar); } } - - LLCharacter::sAllowInstancesChange = TRUE ; } BOOL LLVOAvatar::isImpostor() const @@ -9095,6 +10723,10 @@ BOOL LLVOAvatar::isImpostor() const return (isVisuallyMuted() || (sUseImpostors && mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE; } +BOOL LLVOAvatar::shouldImpostor(const U32 rank_factor) const +{ + return (!isSelf() && sUseImpostors && mVisibilityRank > (sMaxVisible * rank_factor)); +} BOOL LLVOAvatar::needsImpostorUpdate() const { @@ -9136,136 +10768,320 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d } -void LLVOAvatar::idleUpdateRenderCost() +void LLVOAvatar::idleUpdateRenderComplexity() { - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) + if (isControlAvatar()) { - return; + LLControlAvatar *cav = asControlAvatar(); + bool is_attachment = cav && cav->mRootVolp && cav->mRootVolp->isAttachment(); // For attached animated objects + if (is_attachment) + { + // ARC for animated object attachments is accounted with the avatar they're attached to. + return; + } } - F32 red, green; + if (mComplexityTimer.getElapsedTimeF32() > 5.f) + { + // Render Complexity + calculateUpdateRenderComplexity(); // Update mVisualComplexity if needed + mComplexityTimer.start(); + } - static LLCachedControl UseOldARC(gSavedSettings, "LiruSensibleARC", true); - if(UseOldARC) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) { - U32 shame = 1; + std::string info_line; + F32 red_level; + F32 green_level; + LLColor4 info_color; + LLFontGL::StyleFlags info_style; + + if ( !mText ) + { + initHudText(); + mText->setFadeDistance(20.0, 5.0); // limit clutter in large crowds + } + else + { + mText->clearString(); // clear debug text + } - std::set textures; + /* + * NOTE: the logic for whether or not each of the values below + * controls muting MUST match that in the isVisuallyMuted and isTooComplex methods. + */ - /*attachment_map_t::const_iterator iter; - for (iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) + static LLCachedControl max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0); + info_line = llformat("%d Complexity", mVisualComplexity); + + if (max_render_cost != 0) // zero means don't care, so don't bother coloring based on this { - LLViewerJointAttachment* attachment = iter->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) + green_level = 1.f-llclamp(((F32) mVisualComplexity-(F32)max_render_cost)/(F32)max_render_cost, 0.f, 1.f); + red_level = llmin((F32) mVisualComplexity/(F32)max_render_cost, 1.f); + info_color.set(red_level, green_level, 0.0, 1.0); + info_style = ( mVisualComplexity > max_render_cost + ? LLFontGL::BOLD : LLFontGL::NORMAL ); + } + else + { + info_color.set(LLColor4::grey); + info_style = LLFontGL::NORMAL; + } + mText->addLine(info_line, info_color, info_style); + + // Visual rank + info_line = llformat("%d rank", mVisibilityRank); + // Use grey for imposters, white for normal rendering or no impostors + info_color.set(isImpostor() ? LLColor4::grey : (isControlAvatar() ? LLColor4::yellow : LLColor4::white)); + info_style = LLFontGL::NORMAL; + mText->addLine(info_line, info_color, info_style); + + // Triangle count + mText->addLine(std::string("VisTris ") + LLStringOps::getReadableNumber(mAttachmentVisibleTriangleCount), + info_color, info_style); + mText->addLine(std::string("EstMaxTris ") + LLStringOps::getReadableNumber(mAttachmentEstTriangleCount), + info_color, info_style); + + // Attachment Surface Area + static LLCachedControl max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 1000.0f); + info_line = llformat("%.0f m^2", mAttachmentSurfaceArea); + + if (max_render_cost != 0 && max_attachment_area != 0) // zero means don't care, so don't bother coloring based on this + { + green_level = 1.f-llclamp((mAttachmentSurfaceArea-max_attachment_area)/max_attachment_area, 0.f, 1.f); + red_level = llmin(mAttachmentSurfaceArea/max_attachment_area, 1.f); + info_color.set(red_level, green_level, 0.0, 1.0); + info_style = ( mAttachmentSurfaceArea > max_attachment_area + ? LLFontGL::BOLD : LLFontGL::NORMAL ); + + } + else + { + info_color.set(LLColor4::grey); + info_style = LLFontGL::NORMAL; + } + + mText->addLine(info_line, info_color, info_style); + + updateText(); // corrects position + } +} + +void LLVOAvatar::updateVisualComplexity() +{ + LL_DEBUGS("AvatarRender") << "avatar " << getID() << " appearance changed" << LL_ENDL; + // Set the cache time to in the past so it's updated ASAP + mVisualComplexityStale = true; +} + +// Account for the complexity of a single top-level object associated +// with an avatar. This will be either an attached object or an animated +// object. +void LLVOAvatar::accountRenderComplexityForObject( + const LLViewerObject *attached_object, + const F32 max_attachment_complexity, + LLVOVolume::texture_cost_t& textures, + U32& cost/*, + hud_complexity_list_t& hud_complexity_list*/) +{ + if (attached_object && !attached_object->isHUDAttachment()) + { + mAttachmentVisibleTriangleCount += attached_object->recursiveGetTriangleCount(); + mAttachmentEstTriangleCount += attached_object->recursiveGetEstTrianglesMax(); + mAttachmentSurfaceArea += attached_object->recursiveGetScaledSurfaceArea(); + + textures.clear(); + const LLDrawable* drawable = attached_object->mDrawable; + if (drawable) + { + const LLVOVolume* volume = drawable->getVOVolume(); + if (volume) { - const LLViewerObject* object = (*attachment_iter);*/ - std::vector >::iterator attachment_iter = mAttachedObjectsVector.begin(); - for(;attachment_iter!=mAttachedObjectsVector.end();++attachment_iter) - {{ - const LLViewerObject* object = attachment_iter->first; - if (object && !object->isHUDAttachment()) + F32 attachment_total_cost = 0; + F32 attachment_volume_cost = 0; + F32 attachment_texture_cost = 0; + F32 attachment_children_cost = 0; + const F32 animated_object_attachment_surcharge = 1000; + + if (attached_object->isAnimatedObject()) + { + attachment_volume_cost += animated_object_attachment_surcharge; + } + attachment_volume_cost += volume->getRenderCost(textures); + + const_child_list_t children = volume->getChildren(); + for (const_child_list_t::const_iterator child_iter = children.begin(); + child_iter != children.end(); + ++child_iter) { - LLDrawable* drawable = object->mDrawable; - if (drawable) + LLViewerObject* child_obj = *child_iter; + LLVOVolume *child = child_obj ? child_obj->asVolume() : nullptr; + if (child) { - shame += 10; - LLVOVolume* volume = drawable->getVOVolume(); - if (volume) - { - shame += calc_shame(volume, textures); - } + attachment_children_cost += child->getRenderCost(textures); } } + + for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin(); + volume_texture != textures.end(); + ++volume_texture) + { + // add the cost of each individual texture in the linkset + attachment_texture_cost += volume_texture->second; + } + attachment_total_cost = attachment_volume_cost + attachment_texture_cost + attachment_children_cost; + LL_DEBUGS("ARCdetail") << "Attachment costs " << attached_object->getAttachmentItemID() + << " total: " << attachment_total_cost + << ", volume: " << attachment_volume_cost + << ", textures: " << attachment_texture_cost + << ", " << volume->numChildren() + << " children: " << attachment_children_cost + << LL_ENDL; + // Limit attachment complexity to avoid signed integer flipping of the wearer's ACI + cost += (U32)llclamp(attachment_total_cost, MIN_ATTACHMENT_COMPLEXITY, max_attachment_complexity); } } - - shame += textures.size() * 5; - - setDebugText(llformat("%d", shame)); - green = 1.f-llclamp(((F32) shame-1024.f)/1024.f, 0.f, 1.f); - red = llmin((F32) shame/1024.f, 1.f); } - else + if (isSelf() + && attached_object + && attached_object->isHUDAttachment() + && !attached_object->isTempAttachment() + && attached_object->mDrawable) { - static const U32 ARC_BODY_PART_COST = 200; - static const LLCachedControl ARC_LIMIT("LiruNewARCLimit", 20000); + textures.clear(); + + mAttachmentSurfaceArea += attached_object->recursiveGetScaledSurfaceArea(); + +#if 0 + const LLVOVolume* volume = attached_object->mDrawable->getVOVolume(); + if (volume) + { + + LLHUDComplexity hud_object_complexity; + hud_object_complexity.objectName = attached_object->getAttachmentItemName(); + hud_object_complexity.objectId = attached_object->getAttachmentItemID(); + std::string joint_name; + gAgentAvatarp->getAttachedPointName(attached_object->getAttachmentItemID(), joint_name); + hud_object_complexity.jointName = joint_name; + // get cost and individual textures + hud_object_complexity.objectsCost += volume->getRenderCost(textures); + hud_object_complexity.objectsCount++; + + LLViewerObject::const_child_list_t& child_list = attached_object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); ++iter) + { + LLViewerObject* childp = *iter; + const LLVOVolume* chld_volume = childp ? childp->asVolume() : nullptr; + if (chld_volume) + { + // get cost and individual textures + hud_object_complexity.objectsCost += chld_volume->getRenderCost(textures); + hud_object_complexity.objectsCount++; + } + } - static std::set all_textures; + hud_object_complexity.texturesCount += textures.size(); - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES)) - { //set debug text to attachment geometry bytes here so render cost will override - setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea)); + for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin(); + volume_texture != textures.end(); + ++volume_texture) + { + // add the cost of each individual texture (ignores duplicates) + hud_object_complexity.texturesCost += volume_texture->second; + LLViewerFetchedTexture *tex = LLViewerTextureManager::getFetchedTexture(volume_texture->first); + if (tex) + { + // Note: Texture memory might be incorect since texture might be still loading. + hud_object_complexity.texturesMemoryTotal += tex->getTextureMemory(); + if (tex->getOriginalHeight() * tex->getOriginalWidth() >= HUD_OVERSIZED_TEXTURE_DATA_SIZE) + { + hud_object_complexity.largeTexturesCount++; + } + } + } + hud_complexity_list.push_back(hud_object_complexity); } +#endif + } +} - U32 cost = 0; +// Calculations for mVisualComplexity value +void LLVOAvatar::calculateUpdateRenderComplexity() +{ + /***************************************************************** + * This calculation should not be modified by third party viewers, + * since it is used to limit rendering and should be uniform for + * everyone. If you have suggested improvements, submit them to + * the official viewer for consideration. + *****************************************************************/ + static const U32 COMPLEXITY_BODY_PART_COST = 200; + static LLCachedControl max_complexity_setting(gSavedSettings,"MaxAttachmentComplexity"); + F32 max_attachment_complexity = max_complexity_setting; + max_attachment_complexity = llmax(max_attachment_complexity, DEFAULT_MAX_ATTACHMENT_COMPLEXITY); + + // Diagnostic list of all textures on our avatar + static uuid_set_t all_textures; + + if (mVisualComplexityStale) + { + U32 cost = VISUAL_COMPLEXITY_UNKNOWN; LLVOVolume::texture_cost_t textures; + //hud_complexity_list_t hud_complexity_list; for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict + = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); ETextureIndex tex_index = baked_dict->mTextureIndex; if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT))) { if (isTextureVisible(tex_index)) { - cost +=ARC_BODY_PART_COST; + cost +=COMPLEXITY_BODY_PART_COST; } } } + LL_DEBUGS("ARCdetail") << "Avatar body parts complexity: " << cost << LL_ENDL; + mAttachmentVisibleTriangleCount = 0; + mAttachmentEstTriangleCount = 0.f; + mAttachmentSurfaceArea = 0.f; - /*for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) + // A standalone animated object needs to be accounted for + // using its associated volume. Attached animated objects + // will be covered by the subsequent loop over attachments. + LLControlAvatar *control_av = asControlAvatar(); + if (control_av) { - LLViewerJointAttachment* attachment = iter->second; + LLVOVolume *volp = control_av->mRootVolp; + if (volp && !volp->isAttachment()) + { + accountRenderComplexityForObject(volp, max_attachment_complexity, + textures, cost/*, hud_complexity_list*/); + } + } + + // Account for complexity of all attachments. +#if SLOW_ATTACHMENT_LIST + for (attachment_map_t::const_iterator attachment_point = mAttachmentPoints.begin(); + attachment_point != mAttachmentPoints.end(); + ++attachment_point) + { + LLViewerJointAttachment* attachment = attachment_point->second; for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { - const LLViewerObject* attached_object = (*attachment_iter);*/ - std::vector >::iterator attachment_iter = mAttachedObjectsVector.begin(); - for(;attachment_iter!=mAttachedObjectsVector.end();++attachment_iter) + const LLViewerObject* attached_object = (*attachment_iter); +#else + for(auto& iter : mAttachedObjectsVector) {{ - const LLViewerObject* attached_object = attachment_iter->first; - if (attached_object && !attached_object->isHUDAttachment()) - { - textures.clear(); - const LLDrawable* drawable = attached_object->mDrawable; - if (drawable) - { - const LLVOVolume* volume = drawable->getVOVolume(); - if (volume) - { - cost += volume->getRenderCost(textures); - - const_child_list_t children = volume->getChildren(); - for (const_child_list_t::const_iterator child_iter = children.begin(); - child_iter != children.end(); - ++child_iter) - { - LLViewerObject* child_obj = *child_iter; - LLVOVolume *child = dynamic_cast( child_obj ); - if (child) - { - cost += child->getRenderCost(textures); - } - } - - for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) - { - // add the cost of each individual texture in the linkset - cost += iter->second; - } - } - } - } + const LLViewerObject* attached_object = iter.first; +#endif + accountRenderComplexityForObject(attached_object, max_attachment_complexity, + textures, cost/*, hud_complexity_list*/); } - } // Diagnostic output to identify all avatar-related textures. @@ -9277,12 +11093,11 @@ void LLVOAvatar::idleUpdateRenderCost() for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it) { LLUUID image_id = it->first; - if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) - continue; - if (all_textures.find(image_id) == all_textures.end()) + if( ! (image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) + && (all_textures.find(image_id) == all_textures.end())) { // attachment texture not previously seen. - LL_INFOS() << "attachment_texture: " << image_id.asString() << LL_ENDL; + LL_DEBUGS("ARCdetail") << "attachment_texture: " << image_id.asString() << LL_ENDL; all_textures.insert(image_id); } } @@ -9302,33 +11117,32 @@ void LLVOAvatar::idleUpdateRenderCost() continue; if (all_textures.find(image_id) == all_textures.end()) { - LL_INFOS() << "local_texture: " << texture_dict->mName << ": " << image_id << LL_ENDL; + LL_DEBUGS("ARCdetail") << "local_texture: " << texture_dict->mName << ": " << image_id << LL_ENDL; all_textures.insert(image_id); } } } - std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); - setDebugText(llformat("%s %d", viz_string.c_str(), cost)); mVisualComplexity = cost; - green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f); - red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f); + mVisualComplexityStale = false; } - mText->setColor(LLColor4(red,green,0,1)); + } // static BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index) { - if (index < 0 || index >= TEX_NUM_INDICES) return false; - return LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsLocalTexture; + return (index < 0 || index >= TEX_NUM_INDICES) + ? false + : LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsLocalTexture; } // static BOOL LLVOAvatar::isIndexBakedTexture(ETextureIndex index) { - if (index < 0 || index >= TEX_NUM_INDICES) return false; - return LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsBakedTexture; + return (index < 0 || index >= TEX_NUM_INDICES) + ? false + : LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsBakedTexture; } const std::string LLVOAvatar::getBakedStatusForPrintout() const @@ -9412,107 +11226,3 @@ BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, return FALSE; } -U32 calc_shame(LLVOVolume* volume, std::set &textures) -{ - if (!volume) - { - return 0; - } - - U32 shame = 0; - - U32 invisi = 0; - U32 shiny = 0; - U32 glow = 0; - U32 alpha = 0; - U32 flexi = 0; - U32 animtex = 0; - U32 particles = 0; - U32 scale = 0; - U32 bump = 0; - U32 planar = 0; - - const LLVector3& sc = volume->getScale(); - scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2]; - - if (volume->isFlexible()) - { - flexi = 1; - } - if (volume->isParticleSource()) - { - particles = 1; - } - - LLDrawable* drawablep = volume->mDrawable; - - if (volume->isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *) volume->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID sculpt_id = sculpt_params->getSculptTexture(); - textures.insert(sculpt_id); - } - - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - const LLTextureEntry* te = face->getTextureEntry(); - LLViewerTexture* img = face->getTexture(); - - textures.insert(img->getID()); - - if (face->getPoolType() == LLDrawPool::POOL_ALPHA) - { - alpha++; - } - else if (img->getPrimaryFormat() == GL_ALPHA) - { - invisi = 1; - } - - if (te) - { - if (te->getBumpmap()) - { - bump = 1; - } - if (te->getShiny()) - { - shiny = 1; - } - if (te->getGlow() > 0.f) - { - glow = 1; - } - if (face->mTextureMatrix != NULL) - { - animtex++; - } - if (te->getTexGen()) - { - planar++; - } - } - } - - shame += invisi + shiny + glow + alpha*4 + flexi*8 + animtex*4 + particles*16+bump*4+scale+planar; - - LLViewerObject::const_child_list_t& child_list = volume->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child_objectp = *iter; - LLDrawable* child_drawablep = child_objectp->mDrawable; - if (child_drawablep) - { - LLVOVolume* child_volumep = child_drawablep->getVOVolume(); - if (child_volumep) - { - shame += calc_shame(child_volumep, textures); - } - } - } - - return shame; -} - diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 8e3ece6d92..d285274998 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -50,8 +50,9 @@ #include "lldriverparam.h" #include "llviewertexlayer.h" #include "material_codes.h" // LL_MCODE_END +#include "llrigginginfo.h" #include "llviewerstats.h" - +#include "llvovolume.h" #include "llavatarname.h" // @@ -80,6 +81,8 @@ class LLTexGlobalColor; class LLViewerJoint; struct LLAppearanceMessageContents; class LLMeshSkinInfo; +class LLViewerJointMesh; +class LLControlAvatar; class SHClientTagMgr : public LLSingleton, public boost::signals2::trackable { @@ -184,16 +187,16 @@ class LLVOAvatar : void updateLODRiggedAttachments( void ); void updateSoftwareSkinnedVertices(const LLMeshSkinInfo* skin, const LLVector4a* weight, const LLVolumeFace& vol_face, LLVertexBuffer *buffer); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. - S32 totalTextureMemForUUIDS(std::set& ids); - bool allTexturesCompletelyDownloaded(std::set& ids) const; + S32Bytes totalTextureMemForUUIDS(uuid_set_t& ids); + bool allTexturesCompletelyDownloaded(uuid_set_t& ids) const; bool allLocalTexturesCompletelyDownloaded() const; bool allBakedTexturesCompletelyDownloaded() const; void bakedTextureOriginCounts(S32 &sb_count, S32 &host_count, S32 &both_count, S32 &neither_count); std::string bakedTextureOriginInfo(); - void collectLocalTextureUUIDs(std::set& ids) const; - void collectBakedTextureUUIDs(std::set& ids) const; - void collectTextureUUIDs(std::set& ids); + void collectLocalTextureUUIDs(uuid_set_t& ids) const; + void collectBakedTextureUUIDs(uuid_set_t& ids) const; + void collectTextureUUIDs(uuid_set_t& ids); void releaseOldTextures(); /*virtual*/ void updateTextures(); LLViewerFetchedTexture* getBakedTextureImage(const U8 te, const LLUUID& uuid); @@ -207,18 +210,21 @@ class LLVOAvatar : /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); /*virtual*/ void updateRegion(LLViewerRegion *regionp); /*virtual*/ void updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax); - /*virtual*/ void getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); + void calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point LLVector4a* normal = NULL, // return the surface normal at the intersection point LLVector4a* tangent = NULL); // return the surface tangent at the intersection point - LLViewerObject* lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end, + virtual LLViewerObject* lineSegmentIntersectRiggedAttachments( + const LLVector4a& start, const LLVector4a& end, S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point @@ -241,6 +247,7 @@ class LLVOAvatar : void startMotion(U32 bit, F32 start_offset = 0.f); void stopMotion(U32 bit, BOOL stop_immediate = FALSE); // + virtual bool hasMotionFromSource(const LLUUID& source_id); virtual void stopMotionFromSource(const LLUUID& source_id); virtual void requestStopMotion(LLMotion* motion); LLMotion* findMotion(const LLUUID& id) const; @@ -248,9 +255,29 @@ class LLVOAvatar : void dumpAnimationState(); virtual LLJoint* getJoint(const std::string &name); + LLJoint* getJoint(S32 num); - void resetJointPositionsToDefault( void ); + void addAttachmentOverridesForObject(LLViewerObject *vo, uuid_set_t* meshes_seen = NULL, bool recursive = true); + void removeAttachmentOverridesForObject(const LLUUID& mesh_id); + void removeAttachmentOverridesForObject(LLViewerObject *vo); + bool jointIsRiggedTo(const LLJoint *joint) const; + void clearAttachmentOverrides(); + void rebuildAttachmentOverrides(); + void updateAttachmentOverrides(); + void showAttachmentOverrides(bool verbose = false) const; + void getAttachmentOverrideNames( std::set& pos_names, + std::set& scale_names) const; + + void getAssociatedVolumes(std::vector& volumes); + + // virtual + void updateRiggingInfo(); + // This encodes mesh id and LOD, so we can see whether display is up-to-date. + std::map mLastRiggingInfoKey; + uuid_set_t mActiveOverrideMeshes; + virtual void onActiveOverrideMeshesChanged(); + /*virtual*/ const LLUUID& getID() const; /*virtual*/ void addDebugText(const std::string& text); /*virtual*/ F32 getTimeDilation(); @@ -273,6 +300,9 @@ class LLVOAvatar : public: virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent + bool isControlAvatar() const { return mIsControlAvatar; } // True if this avatar is a control av (no associated user) + virtual LLControlAvatar* asControlAvatar() { return nullptr; } + bool isUIAvatar() const { return mIsUIAvatar; } // True if this avatar is a supplemental av used in some UI views (no associated user) private: //aligned members LL_ALIGN_16(LLVector4a mImpostorExtents[2]); @@ -283,7 +313,16 @@ class LLVOAvatar : // Updates //-------------------------------------------------------------------- public: + void updateAppearanceMessageDebugText(); + void updateAnimationDebugText(); + virtual void updateDebugText(); virtual BOOL updateCharacter(LLAgent &agent); + void updateFootstepSounds(); + void computeUpdatePeriod(); + void updateOrientation(LLAgent &agent, F32 speed, F32 delta_time); + void updateTimeStep(); + void updateRootPositionAndRotation(LLAgent &agent, F32 speed, bool was_sit_ground_constrained); + void idleUpdateVoiceVisualizer(bool voice_enabled); void idleUpdateMisc(bool detailed_update); virtual void idleUpdateAppearanceAnimation(); @@ -300,7 +339,26 @@ class LLVOAvatar : // force all name tags to rebuild, useful when display names turned on/off static void invalidateNameTags(); void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font); - void idleUpdateRenderCost(); + void idleUpdateRenderComplexity(); + void accountRenderComplexityForObject(const LLViewerObject *attached_object, + const F32 max_attachment_complexity, + LLVOVolume::texture_cost_t& textures, + U32& cost/*, + hud_complexity_list_t& hud_complexity_list*/); + void calculateUpdateRenderComplexity(); + static const U32 VISUAL_COMPLEXITY_UNKNOWN; + void updateVisualComplexity(); + + U32 getVisualComplexity() { return mVisualComplexity; }; // Numbers calculated here by rendering AV + F32 getAttachmentSurfaceArea() { return mAttachmentSurfaceArea; }; // estimated surface area of attachments + + U32 getReportedVisualComplexity() { return mReportedVisualComplexity; }; // Numbers as reported by the SL server + void setReportedVisualComplexity(S32 value) { mReportedVisualComplexity = value; }; + + S32 getUpdatePeriod() { return mUpdatePeriod; }; + + static void updateImpostorRendering(U32 newMaxNonImpostorsValue); + void idleUpdateBelowWater(); //-------------------------------------------------------------------- @@ -312,13 +370,13 @@ class LLVOAvatar : static U32 sMaxVisible; //(affected by control "RenderAvatarMaxVisible") static F32 sRenderDistance; //distance at which avatars will render. static BOOL sShowAnimationDebug; // show animation debug info - static BOOL sUseImpostors; //use impostors for far away avatars - static BOOL sShowFootPlane; // show foot collision plane reported by server - static BOOL sVisibleInFirstPerson; + static bool sUseImpostors; //use impostors for far away avatars + static bool sShowFootPlane; // show foot collision plane reported by server + static bool sVisibleInFirstPerson; static S32 sNumLODChangesThisFrame; static S32 sNumVisibleChatBubbles; static BOOL sDebugInvisible; - static BOOL sShowAttachmentPoints; + static bool sShowAttachmentPoints; static F32 sLODFactor; // user-settable LOD factor static F32 sPhysicsLODFactor; // user-settable physics LOD factor static BOOL sJointDebug; // output total number of joints being touched for each avatar @@ -347,6 +405,7 @@ class LLVOAvatar : S32 mLastRezzedStatus; + void startPhase(const std::string& phase_name); void stopPhase(const std::string& phase_name, bool err_check = true); void clearPhases(); @@ -360,13 +419,13 @@ class LLVOAvatar : BOOL processFullyLoadedChange(bool loading); void updateRuthTimer(bool loading); F32 calcMorphAmount(); + private: BOOL mFirstFullyVisible; BOOL mFullyLoaded; BOOL mPreviousFullyLoaded; BOOL mFullyLoadedInitialized; S32 mFullyLoadedFrameCounter; - S32 mVisualComplexity; LLFrameTimer mFullyLoadedTimer; LLFrameTimer mRuthTimer; bool mFreezeTimeLangolier; // True when this avatar was created during snapshot FreezeTime mode, and that mode is still active. @@ -393,19 +452,16 @@ class LLVOAvatar : /*virtual*/ LLAvatarJointMesh* createAvatarJointMesh(); // Returns LLViewerJointMesh public: void updateHeadOffset(); - void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ; - bool hasPelvisOffset( void ) { return mHasPelvisOffset; } void postPelvisSetRecalc( void ); - void setPelvisOffset( F32 pelvixFixupAmount ); /*virtual*/ BOOL loadSkeletonNode(); + void initAttachmentPoints(bool ignore_hud_joints = false); /*virtual*/ void buildCharacter(); + void resetVisualParams(); + void resetSkeleton(bool reset_animations); - bool mHasPelvisOffset; - LLVector3 mPelvisOffset; - F32 mLastPelvisToFoot; - F32 mPelvisFixup; - F32 mLastPelvisFixup; + LLVector3 mCurRootToHeadOffset; + LLVector3 mTargetRootToHeadOffset; S32 mLastSkeletonSerialNum; @@ -430,15 +486,16 @@ class LLVOAvatar : U32 renderSkinnedAttachments(); U32 renderTransparent(BOOL first_pass); void renderCollisionVolumes(); + void renderBones(); void renderJoints(); static void deleteCachedImages(bool clearAll=true); static void destroyGL(); static void restoreGL(); S32 mSpecialRenderMode; // special lighting - U32 mAttachmentGeometryBytes; //number of bytes in attached geometry - F32 mAttachmentSurfaceArea; //estimated surface area of attachments - private: + F32 mAttachmentSurfaceArea; //estimated surface area of attachments + U32 mAttachmentVisibleTriangleCount; + F32 mAttachmentEstTriangleCount; bool shouldAlphaMask(); BOOL mNeedsSkin; // avatar has been animated and verts have not been updated @@ -447,6 +504,19 @@ class LLVOAvatar : S32 mUpdatePeriod; S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. + // the isTooComplex method uses these mutable values to avoid recalculating too frequently + mutable U32 mVisualComplexity; + mutable bool mVisualComplexityStale; + U32 mReportedVisualComplexity; // from other viewers through the simulator + + //-------------------------------------------------------------------- + // animated object status + //-------------------------------------------------------------------- +public: + bool mIsControlAvatar; + bool mIsUIAvatar; + bool mEnableDefaultMotions; + //-------------------------------------------------------------------- // Morph masks //-------------------------------------------------------------------- @@ -485,8 +555,9 @@ class LLVOAvatar : // Impostors //-------------------------------------------------------------------- public: - BOOL isImpostor() const; - BOOL needsImpostorUpdate() const; + virtual BOOL isImpostor() const; + BOOL shouldImpostor(const U32 rank_factor = 1) const; + BOOL needsImpostorUpdate() const; const LLVector3& getImpostorOffset() const; const LLVector2& getImpostorDim() const; void getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& distance) const; @@ -496,14 +567,20 @@ class LLVOAvatar : static void updateImpostors(); LLRenderTarget mImpostor; BOOL mNeedsImpostorUpdate; + F32SecondsImplicit mLastImpostorUpdateFrameTime; + const LLVector3* getLastAnimExtents() const { return mLastAnimExtents; } + void setNeedsExtentUpdate(bool val) { mNeedsExtentUpdate = val; } + private: LLVector3 mImpostorOffset; LLVector2 mImpostorDim; BOOL mNeedsAnimUpdate; + bool mNeedsExtentUpdate; LLVector3 mImpostorAngle; F32 mImpostorDistance; F32 mImpostorPixelArea; LLVector3 mLastAnimExtents[2]; + LLVector3 mLastAnimBasePos; //-------------------------------------------------------------------- // Wind rippling in clothes @@ -584,7 +661,7 @@ class LLVOAvatar : LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList ; BOOL mLoadedCallbacksPaused; - std::set mTextureIDs; + uuid_set_t mTextureIDs; //-------------------------------------------------------------------- // Local Textures //-------------------------------------------------------------------- @@ -657,6 +734,9 @@ class LLVOAvatar : void updateSexDependentLayerSets(bool upload_bake = false); virtual void dirtyMesh(); // Dirty the avatar mesh void updateMeshData(); + void updateMeshVisibility(); + LLViewerTexture* getBakedTexture(const U8 te); + protected: void releaseMeshData(); virtual void restoreMeshData(); @@ -682,12 +762,14 @@ class LLVOAvatar : ** APPEARANCE **/ + LLPointer mLastProcessedAppearance; + public: void parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMessageContents& msg); void processAvatarAppearance(LLMessageSystem* mesgsys); + void applyParsedAppearanceMessage(LLAppearanceMessageContents& contents, bool slam_params); void hideSkirt(); void startAppearanceAnimation(); - /*virtual*/ void bodySizeChanged(); //-------------------------------------------------------------------- // Appearance morphing @@ -725,6 +807,7 @@ class LLVOAvatar : //-------------------------------------------------------------------- public: BOOL isVisible() const; + virtual bool shouldRenderRigged() const; void setVisibilityRank(U32 rank); U32 getVisibilityRank() const { return mVisibilityRank; } // unused static S32 sNumVisibleAvatars; // Number of instances of this class @@ -744,13 +827,14 @@ class LLVOAvatar : void clampAttachmentPositions(); virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object); virtual BOOL detachObject(LLViewerObject *viewer_object); + static bool getRiggedMeshID( LLViewerObject* pVO, LLUUID& mesh_id ); void cleanupAttachedMesh( LLViewerObject* pVO ); static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj); /*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type ) const; LLViewerObject * findAttachmentByID( const LLUUID & target_id ) const; + LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object); protected: - LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object); void lazyAttach(); void rebuildRiggedAttachments( void ); @@ -772,11 +856,12 @@ class LLVOAvatar : BOOL hasHUDAttachment() const; LLBBox getHUDBBox() const; void resetHUDAttachments(); - BOOL canAttachMoreObjects() const; - BOOL canAttachMoreObjects(U32 n) const; + BOOL canAttachMoreObjects(U32 n=1) const; + U32 getMaxAnimatedObjectAttachments() const; + BOOL canAttachMoreAnimatedObjects(U32 n=1) const; protected: U32 getNumAttachments() const; // O(N), not O(1) - + U32 getNumAnimatedObjectAttachments() const; // O(N), not O(1) //-------------------------------------------------------------------- // Old/nonstandard/Agent-only functions //-------------------------------------------------------------------- @@ -905,6 +990,8 @@ class LLVOAvatar : private: // set this property only with LLVOAvatar::sitDown method BOOL mIsSitting; + // position backup in case of missing data + LLVector3 mLastRootPos; /** Hierarchy ** ** @@ -999,13 +1086,13 @@ class LLVOAvatar : // General //-------------------------------------------------------------------- public: + void getSortedJointNames(S32 joint_type, std::vector& result) const; static void dumpArchetypeXML_header(LLAPRFile& file, std::string const& archetype_name = "???"); static void dumpArchetypeXML_footer(LLAPRFile& file); void dumpArchetypeXML(const std::string& prefix, bool group_by_wearables = false); void dumpArchetypeXML_cont(std::string const& fullpath, bool group_by_wearables); void dumpAppearanceMsgParams( const std::string& dump_prefix, - const std::vector& paramsForDump, - const LLTEContents& tec); + const LLAppearanceMessageContents& contents); static void dumpBakedStatus(); const std::string getBakedStatusForPrintout() const; void dumpAvatarTEs(const std::string& context) const; @@ -1063,6 +1150,21 @@ class LLVOAvatar : /** Support classes ** ** *******************************************************************************/ + +public: + typedef std::array rigged_matrix_array_t; + typedef std::vector > > rigged_transformation_cache_t; + rigged_transformation_cache_t& getRiggedMatrixCache() + { + return mRiggedMatrixDataCache; + } + void clearRiggedMatrixCache() + { + mRiggedMatrixDataCache.clear(); + } +private: + rigged_transformation_cache_t mRiggedMatrixDataCache; + // //Avatar idle timer @@ -1073,6 +1175,8 @@ class LLVOAvatar : private: S32 mIdleMinute; + LLTimer mComplexityTimer; + //CCS Nametag public: void setNameFromChat(const std::string &text); @@ -1092,6 +1196,8 @@ extern const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL; extern const F32 MAX_HOVER_Z; extern const F32 MIN_HOVER_Z; +constexpr U32 NUM_ATTACHMENT_GROUPS = 24; + void dump_sequential_xml(const std::string outprefix, const LLSD& content); #endif // LL_VOAVATAR_H diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 46b991c9e2..29d31f0902 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -24,11 +24,6 @@ * $/LicenseInfo$ */ -#if LL_MSVC -// disable warning about boost::lexical_cast returning uninitialized data -// when it fails to parse the string -#pragma warning (disable:4701) -#endif #include "llviewerprecompiledheaders.h" @@ -70,12 +65,6 @@ #include "rlvlocks.h" // [/RLVa:KB] -#if LL_MSVC -// disable boost::lexical_cast warning -#pragma warning (disable:4702) -#endif - -#include LLPointer gAgentAvatarp = NULL; @@ -137,11 +126,6 @@ struct LocalTextureData LLTextureEntry *mTexEntry; }; -// TODO - this class doesn't really do anything, could just use a base -// class responder if nothing else gets added. -// Singu Note: Okay, sure, it's a responder ignore then! -typedef LLHTTPClient::ResponderIgnore LLHoverHeightResponder; - //----------------------------------------------------------------------------- // Callback data //----------------------------------------------------------------------------- @@ -153,15 +137,6 @@ typedef LLHTTPClient::ResponderIgnore LLHoverHeightResponder; ** ** *********************************************************************************/ - -//----------------------------------------------------------------------------- -// Static Data -//----------------------------------------------------------------------------- -S32 LLVOAvatarSelf::sScratchTexBytes = 0; -LLMap< LLGLenum, LLGLuint*> LLVOAvatarSelf::sScratchTexNames; -LLMap< LLGLenum, F32*> LLVOAvatarSelf::sScratchTexLastBindTime; - - /********************************************************************************* ** ** ** Begin LLVOAvatarSelf Constructor routines @@ -178,7 +153,7 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id, mScreenp(NULL), mLastRegionHandle(0), mRegionCrossingCount(0), - mInitialBakesLoaded(false), + //mInitialBakesLoaded(false), // Value outside legal range, so will always be a mismatch the // first time through. mLastHoverOffsetSent(LLVector3(0.0f, 0.0f, -999.0f)) @@ -274,9 +249,11 @@ void LLVOAvatarSelf::initInstance() doPeriodically(update_avatar_rez_metrics, 5.0); doPeriodically(check_for_unsupported_baked_appearance, 120.0); doPeriodically(boost::bind(&LLVOAvatarSelf::checkStuckAppearance, this), 30.0); + + mInitFlags |= 1<<2; } -void LLVOAvatarSelf::setHoverIfRegionEnabled() +void LLVOAvatarSelf::setHoverIfRegionEnabled(bool send_update) { LLViewerRegion* region = getRegion(); if (region && region->simulatorFeaturesReceived()) @@ -342,7 +319,7 @@ void LLVOAvatarSelf::markDead() { BOOL success = LLVOAvatar::loadAvatar(); - // set all parameters sotred directly in the avatar to have + // set all parameters stored directly in the avatar to have // the isSelfParam to be TRUE - this is used to prevent // them from being animated or trigger accidental rebakes // when we copy params from the wearable to the base avatar. @@ -393,8 +370,6 @@ BOOL LLVOAvatarSelf::buildMenus() //------------------------------------------------------------------------- // build the attach and detach menus //------------------------------------------------------------------------- - if(gNoRender) - return TRUE; buildContextMenus(); init_meshes_and_morphs_menu(); @@ -410,130 +385,121 @@ static LLContextMenu* make_part_menu(const std::string& label, bool context) void LLVOAvatarSelf::buildContextMenus() { - gAttachBodyPartPieMenus[0] = gDetachBodyPartPieMenus[0] = NULL; - bool context(gSavedSettings.getBOOL("LiruUseContextMenus")); - std::string label = LLTrans::getString("BodyPartsRightArm"); - gAttachBodyPartPieMenus[1] = make_part_menu(label, context); - gDetachBodyPartPieMenus[1] = make_part_menu(label, context); - - label = LLTrans::getString("BodyPartsHead"); - gAttachBodyPartPieMenus[2] = make_part_menu(label, context); - gDetachBodyPartPieMenus[2] = make_part_menu(label, context); - - label = LLTrans::getString("BodyPartsLeftArm"); - gAttachBodyPartPieMenus[3] = make_part_menu(label, context); - gDetachBodyPartPieMenus[3] = make_part_menu(label, context); - - gAttachBodyPartPieMenus[4] = gDetachBodyPartPieMenus[4] = NULL; - - label = LLTrans::getString("BodyPartsLeftLeg"); - gAttachBodyPartPieMenus[5] = make_part_menu(label, context); - gDetachBodyPartPieMenus[5] = make_part_menu(label, context); - label = LLTrans::getString("BodyPartsTorso"); - gAttachBodyPartPieMenus[6] = make_part_menu(label, context); - gDetachBodyPartPieMenus[6] = make_part_menu(label, context); - - label = LLTrans::getString("BodyPartsRightLeg"); - gAttachBodyPartPieMenus[7] = make_part_menu(label, context); - gDetachBodyPartPieMenus[7] = make_part_menu(label, context); - - for (S32 i = 0; i < 8; i++) - { - if (gAttachBodyPartPieMenus[i]) - { - gAttachPieMenu->appendContextSubMenu( gAttachBodyPartPieMenus[i] ); - } - else - { - BOOL attachment_found = FALSE; - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) + struct EntryData + { + const char * subMenu; + LLContextMenu* attachMenu; + LLContextMenu* detachMenu; + } entries[NUM_ATTACHMENT_GROUPS] = { + { nullptr, gAttachPieMenu, gDetachPieMenu }, //Group 0 = Right Hand + { "BodyPartsRightArm", gAttachPieMenu, gDetachPieMenu }, + { "BodyPartsHead", gAttachPieMenu, gDetachPieMenu }, + { "BodyPartsLeftArm", gAttachPieMenu, gDetachPieMenu }, + { nullptr, gAttachPieMenu, gDetachPieMenu }, //Group 4 = Left Hand + { "BodyPartsLeftLeg", gAttachPieMenu, gDetachPieMenu }, + { "BodyPartsTorso", gAttachPieMenu, gDetachPieMenu }, + { "BodyPartsRightLeg", gAttachPieMenu, gDetachPieMenu }, + + // BENTO + { nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 8 = Right Ring Finger + { nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 9 = Right Wing + { "BodyPartsHead", gAttachPieMenu2, gDetachPieMenu2 }, + { nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 11 = Left Wing + { nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 12 = Left Ring Finger + { nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 13 = Left Hind Foot + { "BodyPartsWaist", gAttachPieMenu2, gDetachPieMenu2 }, + { nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 15 = Right Hind Foot + + // HUD + { nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 16 = Center 2 + { nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 17 = Top Right + { nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 18 = Top + { nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 19 = Top Left + { nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 20 = Center + { nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 21 = Bottom Left + { nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 22 = Bottom + { nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu } // Group 23 = Bottom Right + }; + + for (S32 group = 0; group < NUM_ATTACHMENT_GROUPS; group++) + { + LLContextMenu* attach_menu = entries[group].attachMenu; + LLContextMenu* detach_menu = entries[group].detachMenu; + + if (attach_menu && detach_menu) + { + if (entries[group].subMenu != nullptr) { - LLViewerJointAttachment* attachment = iter->second; - if (attachment->getGroup() == i) - { - LLMenuItemCallGL* item; -// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) - // We need the userdata param to disable options in this pie menu later on (Left Hand / Right Hand option) - item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), - NULL, - object_selected_and_point_valid, attachment); -// [/RLVa:KB] -// item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), -// NULL, -// object_selected_and_point_valid); - item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", iter->first); - - gAttachPieMenu->addChild(item); - - attachment_found = TRUE; - break; - - } + std::string label = LLTrans::getString(entries[group].subMenu); + LLContextMenu* new_menu = make_part_menu(label, context); // Attach + attach_menu->appendContextSubMenu(new_menu); + attach_menu = new_menu; + new_menu = make_part_menu(label, context); // Detach + detach_menu->appendContextSubMenu(new_menu); + detach_menu = new_menu; } - if (!context && !attachment_found) + if (!attach_menu || !detach_menu) { - gAttachPieMenu->addSeparator(); + continue; } - } - if (gDetachBodyPartPieMenus[i]) - { - gDetachPieMenu->appendContextSubMenu( gDetachBodyPartPieMenus[i] ); - } - else - { - BOOL attachment_found = FALSE; - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) + std::multimap attachment_pie_menu_map; + + // gather up all attachment points assigned to this group, and throw into map sorted by pie slice number + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { LLViewerJointAttachment* attachment = iter->second; - if (attachment->getGroup() == i) + if (attachment && attachment->getGroup() == group) { - gDetachPieMenu->addChild(new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), - &handle_detach_from_avatar, object_attached, attachment)); - - attachment_found = TRUE; - break; + // use multimap to provide a partial order off of the pie slice key + S32 pie_index = attachment->getPieSlice(); + attachment_pie_menu_map.insert(std::make_pair(pie_index, iter->first)); } } - if (!context && !attachment_found) + // add in requested order to pie menu, inserting separators as necessary + for (std::multimap::iterator attach_it = attachment_pie_menu_map.begin(); + attach_it != attachment_pie_menu_map.end(); ++attach_it) { - gDetachPieMenu->addSeparator(); + if (!context) // Singu Note: Separators are only needed to keep slices of pies from moving + { + S32 requested_pie_slice = attach_it->first; + while ((S32)attach_menu->getItemCount() < requested_pie_slice) + { + attach_menu->addSeparator(); + detach_menu->addSeparator(); + } + } + S32 attach_index = attach_it->second; + + LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL); + if (attachment) + { + // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) + // We need the userdata param to disable options in this pie menu later on + LLMenuItemCallGL* item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), + NULL, object_selected_and_point_valid, attachment); + // [/RLVa:KB] + // LLMenuItemCallGL* item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), + // NULL, object_selected_and_point_valid); + attach_menu->addChild(item); + item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", attach_index); + detach_menu->addChild(new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), + &handle_detach_from_avatar, + object_attached, attachment)); + } } } } - // add screen attachments - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (attachment->getGroup() == 8) - { - LLMenuItemCallGL* item; -// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) - // We need the userdata param to disable options in this pie menu later on - item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), - NULL, - object_selected_and_point_valid, attachment); -// [/RLVa:KB] -// item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), -// NULL, -// object_selected_and_point_valid); - item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", iter->first); - gAttachScreenPieMenu->addChild(item); - gDetachScreenPieMenu->addChild(new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), - &handle_detach_from_avatar, object_attached, attachment)); - } - } + //buildContextMenus can be called whenever "LiruUseContextMenus" setting changes. Clear out Edit->Attach/Detach menus before (re)populating them. + gAttachSubMenu->empty(); + gDetachSubMenu->empty(); for (S32 pass = 0; pass < 2; pass++) { @@ -569,67 +535,6 @@ void LLVOAvatarSelf::buildContextMenus() gDetachSubMenu->addSeparator(); } } - - for (S32 group = 0; group < 8; group++) - { - // skip over groups that don't have sub menus - if (!gAttachBodyPartPieMenus[group] || !gDetachBodyPartPieMenus[group]) - { - continue; - } - - std::multimap attachment_pie_menu_map; - - // gather up all attachment points assigned to this group, and throw into map sorted by pie slice number - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if(attachment->getGroup() == group) - { - // use multimap to provide a partial order off of the pie slice key - S32 pie_index = attachment->getPieSlice(); - attachment_pie_menu_map.insert(std::make_pair(pie_index, iter->first)); - } - } - - // add in requested order to pie menu, inserting separators as necessary - S32 cur_pie_slice = 0; - for (std::multimap::iterator attach_it = attachment_pie_menu_map.begin(); - attach_it != attachment_pie_menu_map.end(); ++attach_it) - { - if (!context) // Singu Note: Separators are only needed to keep slices of pies from moving - { - S32 requested_pie_slice = attach_it->first; - while (cur_pie_slice < requested_pie_slice) - { - gAttachBodyPartPieMenus[group]->addSeparator(); - gDetachBodyPartPieMenus[group]->addSeparator(); - cur_pie_slice++; - } - } - S32 attach_index = attach_it->second; - - LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL); - if (attachment) - { -// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) - // We need the userdata param to disable options in this pie menu later on - LLMenuItemCallGL* item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), - NULL, object_selected_and_point_valid, attachment); -// [/RLVa:KB] -// LLMenuItemCallGL* item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), -// NULL, object_selected_and_point_valid); - gAttachBodyPartPieMenus[group]->addChild(item); - item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", attach_index); - gDetachBodyPartPieMenus[group]->addChild(new LLMenuItemCallGL(LLTrans::getString(attachment->getName()), - &handle_detach_from_avatar, - object_attached, attachment)); - if (!context) cur_pie_slice++; - } - } - } } void LLVOAvatarSelf::cleanup() @@ -695,6 +600,13 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name) if (!jointp && mScreenp) { jointp = mScreenp->findJoint(name); + if (jointp) + { + joint_map_t::value_type entry; + strncpy(entry.first, name.c_str(), sizeof(entry.first)); + entry.second = jointp; + mJointMap.emplace_back(entry); + } } return jointp; @@ -767,7 +679,7 @@ void LLVOAvatarSelf::updateVisualParams() void LLVOAvatarSelf::writeWearablesToAvatar() { -for (U32 type = 0; type < LLWearableType::WT_COUNT; type++) + for (U32 type = 0; type < LLWearableType::WT_COUNT; type++) { LLWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type); if (wearable) @@ -801,6 +713,13 @@ void LLVOAvatarSelf::requestStopMotion(LLMotion* motion) gAgent.requestStopMotion(motion); } +// virtual +bool LLVOAvatarSelf::hasMotionFromSource(const LLUUID& source_id) +{ + AnimSourceIterator motion_it = mAnimationSources.find(source_id); + return motion_it != mAnimationSources.end(); +} + // virtual void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id) { @@ -939,6 +858,7 @@ void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp) } mRegionCrossingTimer.reset(); LLViewerObject::updateRegion(regionp); + gAgent.setIsCrossingRegion(false); // Attachments getting lost on TP } //-------------------------------------------------------------------- @@ -1115,13 +1035,6 @@ void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_re } } } - - // Physics type has no associated baked textures, but change of params needs to be sent to - // other avatars. - if (type == LLWearableType::WT_PHYSICS) - { - gAgent.sendAgentSetAppearance(); - } } //----------------------------------------------------------------------------- @@ -1143,44 +1056,6 @@ BOOL LLVOAvatarSelf::isWearingAttachment(const LLUUID& inv_item_id) const return FALSE; } -//----------------------------------------------------------------------------- -BOOL LLVOAvatarSelf::attachmentWasRequested(const LLUUID& inv_item_id) const -{ - const F32 REQUEST_EXPIRATION_SECONDS = 5.0; // any request older than this is ignored/removed. - std::map::iterator it = mAttachmentRequests.find(inv_item_id); - if (it != mAttachmentRequests.end()) - { - const LLTimer& request_time = it->second; - F32 request_time_elapsed = request_time.getElapsedTimeF32(); - if (request_time_elapsed > REQUEST_EXPIRATION_SECONDS) - { - mAttachmentRequests.erase(it); - return FALSE; - } - else - { - return TRUE; - } - } - else - { - return FALSE; - } -} - -//----------------------------------------------------------------------------- -void LLVOAvatarSelf::addAttachmentRequest(const LLUUID& inv_item_id) -{ - LLTimer current_time; - mAttachmentRequests[inv_item_id] = current_time; -} - -//----------------------------------------------------------------------------- -void LLVOAvatarSelf::removeAttachmentRequest(const LLUUID& inv_item_id) -{ - mAttachmentRequests.erase(inv_item_id); -} - //----------------------------------------------------------------------------- // getWornAttachment() //----------------------------------------------------------------------------- @@ -1269,8 +1144,6 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view { const LLUUID& attachment_id = viewer_object->getAttachmentItemID(); LLAppearanceMgr::instance().registerAttachment(attachment_id); - // Clear any pending requests once the attachment arrives. - removeAttachmentRequest(attachment_id); updateLODRiggedAttachments(); // [RLVa:KB] - Checked: 2010-08-22 (RLVa-1.2.1a) | Modified: RLVa-1.2.1a @@ -2685,13 +2558,9 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe { F32 desired_pixels; desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); - - // DRANO what priority should wearable-based textures have? - if (isUsingLocalAppearance()) - { - imagep->setBoostLevel(getAvatarBoostLevel()); - imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; - } + + imagep->setBoostLevel(getAvatarBoostLevel()); + imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; imagep->resetTextureStats(); imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); imagep->addTextureStats( desired_pixels / texel_area_ratio ); @@ -2755,7 +2624,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) { // Baked textures live on other sims. LLHost target_host = getObjectHost(); - setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, target_host ) ); + setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, FTT_HOST_BAKE, target_host ) ); updateMeshTextures(); dirtyMesh(); @@ -3013,6 +2882,8 @@ void LLVOAvatarSelf::requestLayerSetUpdate(ETextureIndex index ) if( mUpperBodyLayerSet ) mUpperBodyLayerSet->requestUpdate(); */ const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); + if (!texture_dict) + return; if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) return; const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; @@ -3029,7 +2900,7 @@ LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const case TEX_HEAD_BODYPAINT: return mHeadLayerSet; */ const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); - if (texture_dict->mIsUsedByBakedTexture) + if (texture_dict && texture_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; return getLayerSet(baked_index); @@ -3110,6 +2981,12 @@ void LLVOAvatarSelf::onCustomizeEnd(bool disable_camera_switch) } } +// virtual +bool LLVOAvatarSelf::shouldRenderRigged() const +{ + return gAgent.needsRenderAvatar(); +} + // HACK: this will null out the avatar's local texture IDs before the TE message is sent // to ensure local texture IDs are not sent to other clients in the area. // this is a short-term solution. The long term solution will be to not set the texture @@ -3169,7 +3046,11 @@ void LLVOAvatarSelf::sendHoverHeight() const update["hover_height"] = hover_offset[2]; LL_DEBUGS("Avatar") << avString() << "sending hover height value " << hover_offset[2] << LL_ENDL; - LLHTTPClient::post(url, update, new LLHoverHeightResponder); + + // *TODO: - this class doesn't really do anything, could just use a base + // class responder if nothing else gets added. + // (comment from removed Responder) + LLHTTPClient::post(url, update, new LLHTTPClient::ResponderIgnore); mLastHoverOffsetSent = hover_offset; } @@ -3194,10 +3075,6 @@ void LLVOAvatarSelf::setHoverOffset(const LLVector3& hover_offset, bool send_upd //------------------------------------------------------------------------ BOOL LLVOAvatarSelf::needsRenderBeam() { - if (gNoRender) - { - return FALSE; - } LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); BOOL is_touching_or_grabbing = (tool == LLToolGrab::getInstance() && LLToolGrab::getInstance()->isEditing()); @@ -3207,81 +3084,10 @@ BOOL LLVOAvatarSelf::needsRenderBeam() // don't render selection beam on hud objects is_touching_or_grabbing = FALSE; } - return is_touching_or_grabbing || (mState & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection()); -} - -// static -void LLVOAvatarSelf::deleteScratchTextures() -{ - if(gAuditTexture) - { - S32 total_tex_size = sScratchTexBytes ; - S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ; - - if( sScratchTexNames.checkData( GL_LUMINANCE ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( GL_ALPHA ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( GL_COLOR_INDEX ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( LLRender::sGLCoreProfile ? GL_RG : GL_LUMINANCE_ALPHA ) ) - { - LLImageGL::decTextureCounter(tex_size, 2, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 2 * tex_size ; - } - if( sScratchTexNames.checkData( GL_RGB ) ) - { - LLImageGL::decTextureCounter(tex_size, 3, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 3 * tex_size ; - } - if( sScratchTexNames.checkData( GL_RGBA ) ) - { - LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 4 * tex_size ; - } - //others - while(total_tex_size > 0) - { - LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 4 * tex_size ; - } - } - - for( LLGLuint* namep = sScratchTexNames.getFirstData(); - namep; - namep = sScratchTexNames.getNextData() ) - { - LLImageGL::deleteTextures(1, (U32 *)namep ); - stop_glerror(); - } - - if( sScratchTexBytes ) - { - LL_DEBUGS() << "Clearing Scratch Textures " << (sScratchTexBytes/1024) << "KB" << LL_ENDL; - - sScratchTexNames.deleteAllData(); - sScratchTexLastBindTime.deleteAllData(); - LLImageGL::sGlobalTextureMemoryInBytes -= sScratchTexBytes; - sScratchTexBytes = 0; - } -} - -// static -void LLVOAvatarSelf::dumpScratchTextureByteCount() -{ - LL_INFOS() << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << LL_ENDL; + return is_touching_or_grabbing || (getAttachmentState() & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection()); } -void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value); +void dump_visual_param(apr_file_t* file, LLVisualParam const* viewer_param, F32 value); void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile) { @@ -3309,7 +3115,7 @@ void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile) it != v_params.end(); ++it) { LLVisualParam *param = *it; - dump_visual_param(outfile, param, param->getWeight()); + dump_visual_param(file, param, param->getWeight()); } } } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 1988a51fd5..7d9f9d12ad 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -28,8 +28,10 @@ #ifndef LL_LLVOAVATARSELF_H #define LL_LLVOAVATARSELF_H +#include "llavatarappearancedefines.h" #include "llviewertexture.h" #include "llvoavatar.h" +#include struct LocalTextureData; class LLInventoryCallback; @@ -95,6 +97,7 @@ class LLVOAvatarSelf : // LLCharacter interface and related //-------------------------------------------------------------------- public: + /*virtual*/ bool hasMotionFromSource(const LLUUID& source_id); /*virtual*/ void stopMotionFromSource(const LLUUID& source_id); /*virtual*/ void requestStopMotion(LLMotion* motion); /*virtual*/ LLJoint* getJoint(const std::string &name); @@ -117,8 +120,8 @@ class LLVOAvatarSelf : *******************************************************************************/ private: - LLUUID mInitialBakeIDs[6]; - bool mInitialBakesLoaded; + LLUUID mInitialBakeIDs[LLAvatarAppearanceDefines::BAKED_NUM_INDICES]; + //bool mInitialBakesLoaded; /******************************************************************************** @@ -266,17 +269,6 @@ class LLVOAvatarSelf : const LLUUID& grabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; BOOL canGrabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; - - //-------------------------------------------------------------------- - // Scratch textures (used for compositing) - //-------------------------------------------------------------------- -public: - static void deleteScratchTextures(); -private: - static S32 sScratchTexBytes; - static LLMap< LLGLenum, LLGLuint*> sScratchTexNames; - static LLMap< LLGLenum, F32*> sScratchTexLastBindTime; - /** Textures ** ** *******************************************************************************/ @@ -307,9 +299,6 @@ class LLVOAvatarSelf : public: void updateAttachmentVisibility(U32 camera_mode); BOOL isWearingAttachment(const LLUUID& inv_item_id) const; - BOOL attachmentWasRequested(const LLUUID& inv_item_id) const; - void addAttachmentRequest(const LLUUID& inv_item_id); - void removeAttachmentRequest(const LLUUID& inv_item_id); LLViewerObject* getWornAttachment(const LLUUID& inv_item_id); bool getAttachedPointName(const LLUUID& inv_item_id, std::string& name) const; // [RLVa:KB] - Checked: 2009-12-18 (RLVa-1.1.0i) | Added: RLVa-1.1.0i @@ -325,8 +314,6 @@ class LLVOAvatarSelf : boost::signals2::connection setAttachmentCallback(const attachment_signal_t::slot_type& cb); // [/RLVa:KB] private: - // Track attachments that have been requested but have not arrived yet. - mutable std::map mAttachmentRequests; // [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7) attachment_signal_t* mAttachmentSignal; // [/RLVa:KB] @@ -354,11 +341,14 @@ class LLVOAvatarSelf : //-------------------------------------------------------------------- // Visibility //-------------------------------------------------------------------- + + /* virtual */ bool shouldRenderRigged() const; + public: bool sendAppearanceMessage(LLMessageSystem *mesgsys) const; // -- care and feeding of hover height. - void setHoverIfRegionEnabled(); + void setHoverIfRegionEnabled(bool send_update = true); void sendHoverHeight() const; /*virtual*/ void setHoverOffset(const LLVector3& hover_offset, bool send_update=true); @@ -383,7 +373,6 @@ class LLVOAvatarSelf : public: static void dumpTotalLocalTextureByteCount(); void dumpLocalTextures() const; - static void dumpScratchTextureByteCount(); void dumpWearableInfo(LLAPRFile& outfile); //-------------------------------------------------------------------- diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp index 8b7ca2905f..93bfa29cbf 100644 --- a/indra/newview/llvoclouds.cpp +++ b/indra/newview/llvoclouds.cpp @@ -114,10 +114,10 @@ LLDrawable* LLVOClouds::createDrawable(LLPipeline *pipeline) return mDrawable; } -static LLFastTimer::DeclareTimer FTM_UPDATE_CLOUDS("Cloud Update"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_CLOUDS("Cloud Update"); BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(FTM_UPDATE_CLOUDS); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_CLOUDS); dirtySpatialGroup(); @@ -295,7 +295,8 @@ void LLVOClouds::updateDrawable(BOOL force_damped) clearChanged(SHIFTED); } -LLCloudPartition::LLCloudPartition() +LLCloudPartition::LLCloudPartition(LLViewerRegion* region) + : LLParticlePartition(region) { mDrawableType = LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS; mPartitionType = LLViewerRegion::PARTITION_CLOUD; diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 57f83616f8..e39dedba40 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -81,7 +81,6 @@ LLVOGrass::SpeciesNames LLVOGrass::sSpeciesNames; LLVOGrass::LLVOGrass(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : LLAlphaObject(id, pcode, regionp) { - mPatch = NULL; mLastPatchUpdateTime = 0; mGrassVel.clearVec(); mGrassBend.clearVec(); @@ -103,7 +102,7 @@ LLVOGrass::~LLVOGrass() void LLVOGrass::updateSpecies() { - mSpecies = mState; + mSpecies = getAttachmentState(); if (!sSpeciesTable.count(mSpecies)) { @@ -111,7 +110,7 @@ void LLVOGrass::updateSpecies() SpeciesMap::const_iterator it = sSpeciesTable.begin(); mSpecies = (*it).first; } - setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } @@ -331,7 +330,8 @@ void LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return; } - if (mPatch && (mLastPatchUpdateTime != mPatch->getLastUpdateTime())) + const auto& patch = mPatch.lock(); + if (patch && (mLastPatchUpdateTime != patch->getLastUpdateTime())) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); } @@ -437,11 +437,11 @@ LLDrawable* LLVOGrass::createDrawable(LLPipeline *pipeline) return mDrawable; } -static LLFastTimer::DeclareTimer FTM_UPDATE_GRASS("Update Grass"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_GRASS("Update Grass"); BOOL LLVOGrass::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(FTM_UPDATE_GRASS); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_GRASS); dirtySpatialGroup(); @@ -507,9 +507,10 @@ void LLVOGrass::getGeometry(S32 idx, return ; } - mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion()); - if (mPatch) - mLastPatchUpdateTime = mPatch->getLastUpdateTime(); + const auto& patch = mRegionp->getLand().resolvePatchRegion(getPositionRegion()); + if (patch) + mLastPatchUpdateTime = patch->getLastUpdateTime(); + mPatch = patch; LLVector3 position; // Create random blades of grass with gaussian distribution @@ -626,8 +627,8 @@ U32 LLVOGrass::getPartitionType() const return LLViewerRegion::PARTITION_GRASS; } -LLGrassPartition::LLGrassPartition() -: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB) +LLGrassPartition::LLGrassPartition(LLViewerRegion* regionp) +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB, regionp) { mDrawableType = LLPipeline::RENDER_TYPE_GRASS; mPartitionType = LLViewerRegion::PARTITION_GRASS; @@ -695,11 +696,11 @@ void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count } } -static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_GRASS_VB("Grass VB"); void LLGrassPartition::getGeometry(LLSpatialGroup* group) { - LLFastTimer ftm(FTM_REBUILD_GRASS_VB); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_GRASS_VB); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); @@ -798,7 +799,7 @@ void LLVOGrass::updateDrawable(BOOL force_damped) } // virtual -BOOL LLVOGrass::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, S32 *face_hitp, +BOOL LLVOGrass::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h index 10708c74bb..f4f1da6fe2 100644 --- a/indra/newview/llvograss.h +++ b/indra/newview/llvograss.h @@ -84,6 +84,7 @@ class LLVOGrass : public LLAlphaObject /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point @@ -107,7 +108,7 @@ class LLVOGrass : public LLAlphaObject F32 mBladeSizeX; F32 mBladeSizeY; - LLSurfacePatch *mPatch; // Stores the land patch where the grass is centered + std::weak_ptr mPatch; // Stores the land patch where the grass is centered U64 mLastPatchUpdateTime; diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index b42749d289..4acfad1eb2 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -35,21 +35,6 @@ extern AIHTTPTimeoutPolicy voiceCallCapResponder_timeout; - -LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap; -LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap; -LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL; -LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL; -LLVoiceChannel::channel_changed_signal_t LLVoiceChannel::sCurrentVoiceChannelChangedSignal; - -BOOL LLVoiceChannel::sSuspended = FALSE; - -// -// Constants -// -const U32 DEFAULT_RETRIES_COUNT = 3; - - class LLVoiceCallCapResponder : public LLHTTPClient::ResponderWithResult { public: @@ -66,59 +51,29 @@ class LLVoiceCallCapResponder : public LLHTTPClient::ResponderWithResult }; -void LLVoiceCallCapResponder::httpFailure(void) -{ - LL_WARNS("Voice") << "LLVoiceCallCapResponder error [status:" - << mStatus << "]: " << mReason << LL_ENDL; - LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID); - if ( channelp ) - { - if ( 403 == mStatus ) - { - //403 == no ability - LLNotificationsUtil::add( - "VoiceNotAllowed", - channelp->getNotifyArgs()); - } - else - { - LLNotificationsUtil::add( - "VoiceCallGenericError", - channelp->getNotifyArgs()); - } - channelp->deactivate(); - } -} +LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap; +LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap; +LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = nullptr; +LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = nullptr; +LLVoiceChannel::channel_changed_signal_t LLVoiceChannel::sCurrentVoiceChannelChangedSignal; -void LLVoiceCallCapResponder::httpSuccess(void) -{ - LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID); - if (channelp) - { - // *TODO: DEBUG SPAM - LLSD::map_const_iterator iter; - for(iter = mContent.beginMap(); iter != mContent.endMap(); ++iter) - { - LL_DEBUGS("Voice") << "LLVoiceCallCapResponder::result got " - << iter->first << LL_ENDL; - } +BOOL LLVoiceChannel::sSuspended = FALSE; - channelp->setChannelInfo( - mContent["voice_credentials"]["channel_uri"].asString(), - mContent["voice_credentials"]["channel_credentials"].asString()); - } -} +// +// Constants +// +const U32 DEFAULT_RETRIES_COUNT = 3; // // LLVoiceChannel // LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& session_name) : + mCallDirection(OUTGOING_CALL), mSessionID(session_id), mState(STATE_NO_CHANNEL_INFO), mSessionName(session_name), - mCallDirection(OUTGOING_CALL), - mIgnoreNextSessionLeave(FALSE), - mCallEndedByAgent(false) + mCallEndedByAgent(false), + mIgnoreNextSessionLeave(FALSE) { mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName; @@ -203,19 +158,9 @@ void LLVoiceChannel::handleStatusChange(EStatusType type) switch(type) { case STATUS_LOGIN_RETRY: - //mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle(); - LLNotificationsUtil::add("VoiceLoginRetry"); + // no user notice break; case STATUS_LOGGED_IN: - //if (!mLoginNotificationHandle.isDead()) - //{ - // LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get(); - // if (notifyp) - // { - // notifyp->close(); - // } - // mLoginNotificationHandle.markDead(); - //} break; case STATUS_LEFT_CHANNEL: if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended) @@ -276,11 +221,11 @@ void LLVoiceChannel::deactivate() //Default mic is OFF when leaving voice calls if (gSavedSettings.getBOOL("AutoDisengageMic") && - sCurrentVoiceChannel == this && - LLVoiceClient::getInstance()->getUserPTTState()) + sCurrentVoiceChannel == this /*&& + LLVoiceClient::getInstance()->getUserPTTState()*/) // Singu Note: This could be false, but we still need to do this. { gSavedSettings.setBOOL("PTTCurrentlyEnabled", true); - LLVoiceClient::getInstance()->inputUserControlState(true); + LLVoiceClient::getInstance()->setUserPTTState(false); } } LLVoiceClient::getInstance()->removeObserver(this); @@ -346,7 +291,7 @@ LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id) voice_channel_map_t::iterator found_it = sVoiceChannelMap.find(session_id); if (found_it == sVoiceChannelMap.end()) { - return NULL; + return nullptr; } else { @@ -360,7 +305,7 @@ LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri) voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri); if (found_it == sVoiceChannelURIMap.end()) { - return NULL; + return nullptr; } else { @@ -664,6 +609,50 @@ void LLVoiceChannelGroup::setState(EState state) } } +void LLVoiceCallCapResponder::httpFailure(void) +{ + LL_WARNS("Voice") << "LLVoiceCallCapResponder error [status:" + << mStatus << "]: " << mReason << LL_ENDL; + LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID); + if ( channelp ) + { + if ( 403 == mStatus ) + { + //403 == no ability + LLNotificationsUtil::add( + "VoiceNotAllowed", + channelp->getNotifyArgs()); + } + else + { + LLNotificationsUtil::add( + "VoiceCallGenericError", + channelp->getNotifyArgs()); + } + channelp->deactivate(); + } +} + +void LLVoiceCallCapResponder::httpSuccess(void) +{ + LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID); + if (channelp) + { + // *TODO: DEBUG SPAM + LLSD::map_const_iterator iter; + for(iter = mContent.beginMap(); iter != mContent.endMap(); ++iter) + { + LL_DEBUGS("Voice") << "LLVoiceCallCapResponder::result got " + << iter->first << LL_ENDL; + } + + channelp->setChannelInfo( + mContent["voice_credentials"]["channel_uri"].asString(), + mContent["voice_credentials"]["channel_credentials"].asString()); + } +} + + // // LLVoiceChannelProximal // @@ -723,6 +712,7 @@ void LLVoiceChannelProximal::handleStatusChange(EStatusType status) // do not notify user when leaving proximal channel return; case STATUS_VOICE_DISABLED: + LLVoiceClient::getInstance()->setUserPTTState(false); //skip showing "Voice not available at your current location" when agent voice is disabled (EXT-4749) if(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking()) { @@ -940,7 +930,7 @@ void LLVoiceChannelP2P::setState(EState state) { // you only "answer" voice invites in p2p mode // so provide a special purpose message here - if (mReceivedCall && state == STATE_RINGING) + if (state == STATE_RINGING) { gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs); doSetState(state); diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index a50dfff6a9..c98d19f823 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com /** * @file llvoiceclient.cpp * @brief Voice client delegation class implementation. @@ -51,7 +53,7 @@ class LLVoiceHandler : public LLCommandHandler // requests will be throttled from a non-trusted browser LLVoiceHandler() : LLCommandHandler("voice", UNTRUSTED_THROTTLE) {} - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) override { if (params[0].asString() == "effects") { @@ -111,8 +113,8 @@ std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserv LLVoiceClient::LLVoiceClient() : - mVoiceModule(NULL), - m_servicePump(NULL), + mVoiceModule(nullptr), + m_servicePump(nullptr), mVoiceEffectEnabled(LLCachedControl(gSavedSettings, "VoiceMorphingEnabled", true)), mVoiceEffectDefault(LLCachedControl(gSavedPerAccountSettings, "VoiceEffectDefault", "00000000-0000-0000-0000-000000000000")), mPTTDirty(true), @@ -153,18 +155,17 @@ void LLVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &age } else { - mVoiceModule = NULL; + mVoiceModule = nullptr; return; } mVoiceModule->init(m_servicePump); mVoiceModule->userAuthorized(user_id, agentID); } - void LLVoiceClient::terminate() { if (mVoiceModule) mVoiceModule->terminate(); - mVoiceModule = NULL; + mVoiceModule = nullptr; } const LLVoiceVersionInfo LLVoiceClient::getVersion() @@ -192,7 +193,10 @@ void LLVoiceClient::updateSettings() updateMicMuteLogic(); - if (mVoiceModule) mVoiceModule->updateSettings(); + if (mVoiceModule) + { + mVoiceModule->updateSettings(); + } } //-------------------------------------------------- @@ -305,7 +309,7 @@ const LLVoiceDeviceList& LLVoiceClient::getRenderDevices() //-------------------------------------------------- // participants -void LLVoiceClient::getParticipantList(std::set &participants) +void LLVoiceClient::getParticipantList(uuid_set_t &participants) { if (mVoiceModule) { @@ -313,7 +317,7 @@ void LLVoiceClient::getParticipantList(std::set &participants) } else { - participants = std::set(); + participants = uuid_set_t(); } } @@ -394,24 +398,36 @@ void LLVoiceClient::setNonSpatialChannel( const std::string &uri, const std::string &credentials) { - if (mVoiceModule) mVoiceModule->setNonSpatialChannel(uri, credentials); + if (mVoiceModule) + { + mVoiceModule->setNonSpatialChannel(uri, credentials); + } } void LLVoiceClient::setSpatialChannel( const std::string &uri, const std::string &credentials) { - if (mVoiceModule) mVoiceModule->setSpatialChannel(uri, credentials); + if (mVoiceModule) + { + mVoiceModule->setSpatialChannel(uri, credentials); + } } void LLVoiceClient::leaveNonSpatialChannel() { - if (mVoiceModule) mVoiceModule->leaveNonSpatialChannel(); + if (mVoiceModule) + { + mVoiceModule->leaveNonSpatialChannel(); + } } void LLVoiceClient::leaveChannel(void) { - if (mVoiceModule) mVoiceModule->leaveChannel(); + if (mVoiceModule) + { + mVoiceModule->leaveChannel(); + } } std::string LLVoiceClient::getCurrentChannel() @@ -497,7 +513,10 @@ bool LLVoiceClient::voiceEnabled() void LLVoiceClient::setVoiceEnabled(bool enabled) { - if (mVoiceModule) mVoiceModule->setVoiceEnabled(enabled); + if (mVoiceModule) + { + mVoiceModule->setVoiceEnabled(enabled); + } } void LLVoiceClient::updateMicMuteLogic() @@ -637,31 +656,32 @@ void LLVoiceClient::keyDown(KEY key, MASK mask) return; } - if(!mPTTIsMiddleMouse) + if(!mPTTIsMiddleMouse && mPTTKey != KEY_NONE) { - bool down = (mPTTKey != KEY_NONE) - && gKeyboard->getKeyDown(mPTTKey); - inputUserControlState(down); + bool down = gKeyboard->getKeyDown(mPTTKey); + if (down) + { + inputUserControlState(down); + } } } void LLVoiceClient::keyUp(KEY key, MASK mask) { - if(!mPTTIsMiddleMouse) + if(!mPTTIsMiddleMouse && mPTTKey != KEY_NONE) { - bool down = (mPTTKey != KEY_NONE) - && gKeyboard->getKeyDown(mPTTKey); - inputUserControlState(down); + bool down = gKeyboard->getKeyDown(mPTTKey); + if (!down) + { + inputUserControlState(down); + } } } void LLVoiceClient::middleMouseState(bool down) { if(mPTTIsMiddleMouse) { - if(mPTTIsMiddleMouse) - { inputUserControlState(down); - } } } @@ -840,10 +860,11 @@ LLVoiceEffectInterface* LLVoiceClient::getVoiceEffectInterface() const class LLViewerRequiredVoiceVersion : public LLHTTPNode { static BOOL sAlertedUser; - virtual void post( + + void post( LLHTTPNode::ResponsePtr response, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { //You received this messsage (most likely on region cross or //teleport) @@ -870,10 +891,10 @@ class LLViewerRequiredVoiceVersion : public LLHTTPNode class LLViewerParcelVoiceInfo : public LLHTTPNode { - virtual void post( + void post( LLHTTPNode::ResponsePtr response, const LLSD& context, - const LLSD& input) const + const LLSD& input) const override { //the parcel you are in has changed something about its //voice information diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index b8cf474cce..1c2640085c 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -139,7 +139,7 @@ class LLVoiceModuleInterface virtual LLVoiceDeviceList& getCaptureDevices()=0; virtual LLVoiceDeviceList& getRenderDevices()=0; - virtual void getParticipantList(std::set &participants)=0; + virtual void getParticipantList(uuid_set_t &participants)=0; virtual bool isParticipant(const LLUUID& speaker_id)=0; //@} @@ -420,7 +420,7 @@ class LLVoiceClient: public LLSingleton ///////////////////////////// BOOL getAreaVoiceDisabled(); // returns true if the area the avatar is in is speech-disabled. // Use this to determine whether to show a "no speech" icon in the menu bar. - void getParticipantList(std::set &participants); + void getParticipantList(uuid_set_t &participants); bool isParticipant(const LLUUID& speaker_id); ////////////////////////// diff --git a/indra/newview/llvoiceremotectrl.cpp b/indra/newview/llvoiceremotectrl.cpp index 7566db6b1c..fb6988378d 100644 --- a/indra/newview/llvoiceremotectrl.cpp +++ b/indra/newview/llvoiceremotectrl.cpp @@ -49,14 +49,7 @@ LLVoiceRemoteCtrl::LLVoiceRemoteCtrl (const std::string& name) : LLPanel(name) { setIsChrome(TRUE); - if (gSavedSettings.getBOOL("ShowVoiceChannelPopup")) - { - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_voice_remote_expanded.xml"); - } - else - { - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_voice_remote.xml"); - } + LLUICtrlFactory::getInstance()->buildPanel(this, gSavedSettings.getBOOL("ShowVoiceChannelPopup") ? "panel_voice_remote_expanded.xml" : "panel_voice_remote.xml"); setFocusRoot(TRUE); } @@ -73,7 +66,6 @@ BOOL LLVoiceRemoteCtrl::postBuild() mTalkBtn->setMouseUpCallback(boost::bind(&LLVoiceRemoteCtrl::onBtnTalkReleased)); mTalkLockBtn = getChild("ptt_lock"); - mTalkLockBtn->setClickedCallback(boost::bind(&LLVoiceRemoteCtrl::onBtnLock,this)); mSpeakersBtn = getChild("speakers_btn"); mSpeakersBtn->setClickedCallback(boost::bind(&LLVoiceRemoteCtrl::onClickSpeakers)); @@ -92,12 +84,12 @@ BOOL LLVoiceRemoteCtrl::postBuild() voice_channel_bg->setClickedCallback(boost::bind(&LLVoiceRemoteCtrl::onClickVoiceChannel)); mVoiceVolIcon.connect(this,"voice_volume"); - mShowChanBtn.connect(this,"show_channel"); return TRUE; } void LLVoiceRemoteCtrl::draw() { + // Singu TODO: I'm pretty sure voice channel changing can be done outside of draw call ~Liru BOOL voice_active = FALSE; LLVoiceChannel* channelp = LLVoiceChannel::getCurrentVoiceChannel(); if (channelp) @@ -108,15 +100,13 @@ void LLVoiceRemoteCtrl::draw() mTalkBtn->setEnabled(voice_active); mTalkLockBtn->setEnabled(voice_active); - static LLCachedControl ptt_currently_enabled("PTTCurrentlyEnabled",false); // propagate ptt state to button display, if (!mTalkBtn->hasMouseCapture()) { // not in push to talk mode, or push to talk is active means I'm talking - mTalkBtn->setToggleState(!ptt_currently_enabled || LLVoiceClient::getInstance()->getUserPTTState()); + mTalkBtn->setToggleState(!mTalkLockBtn->getToggleState() || LLVoiceClient::getInstance()->getUserPTTState()); } mSpeakersBtn->setToggleState(LLFloaterActiveSpeakers::instanceVisible(LLSD())); - mTalkLockBtn->setToggleState(!ptt_currently_enabled); std::string talk_blip_image; if (LLVoiceClient::getInstance()->getIsSpeaking(gAgent.getID())) @@ -207,19 +197,6 @@ void LLVoiceRemoteCtrl::draw() } } - LLButton* expand_button = mShowChanBtn; - if (expand_button) - { - if (expand_button->getToggleState()) - { - expand_button->setImageOverlay(std::string("arrow_down.tga")); - } - else - { - expand_button->setImageOverlay(std::string("arrow_up.tga")); - } - } - LLPanel::draw(); } @@ -250,27 +227,13 @@ void LLVoiceRemoteCtrl::onBtnTalkReleased() } } -void LLVoiceRemoteCtrl::onBtnLock(void* user_data) -{ - LLVoiceRemoteCtrl* remotep = (LLVoiceRemoteCtrl*)user_data; - - gSavedSettings.setBOOL("PTTCurrentlyEnabled", !remotep->mTalkLockBtn->getToggleState()); -} - //static void LLVoiceRemoteCtrl::onClickPopupBtn(void* user_data) { LLVoiceRemoteCtrl* remotep = (LLVoiceRemoteCtrl*)user_data; remotep->deleteAllChildren(); - if (gSavedSettings.getBOOL("ShowVoiceChannelPopup")) - { - LLUICtrlFactory::getInstance()->buildPanel(remotep, "panel_voice_remote_expanded.xml"); - } - else - { - LLUICtrlFactory::getInstance()->buildPanel(remotep, "panel_voice_remote.xml"); - } + LLUICtrlFactory::getInstance()->buildPanel(remotep, gSavedSettings.getBOOL("ShowVoiceChannelPopup") ? "panel_voice_remote_expanded.xml" : "panel_voice_remote.xml"); gOverlayBar->layoutButtons(); } diff --git a/indra/newview/llvoiceremotectrl.h b/indra/newview/llvoiceremotectrl.h index 69ea20ae10..f6ea337050 100644 --- a/indra/newview/llvoiceremotectrl.h +++ b/indra/newview/llvoiceremotectrl.h @@ -48,7 +48,6 @@ class LLVoiceRemoteCtrl : public LLPanel /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); - static void onBtnLock(void* user_data); static void onBtnTalkHeld(); static void onBtnTalkReleased(); static void onBtnTalkClicked(); @@ -62,7 +61,6 @@ class LLVoiceRemoteCtrl : public LLPanel LLButton* mTalkLockBtn; LLButton* mSpeakersBtn; CachedUICtrl mVoiceVolIcon; - CachedUICtrl mShowChanBtn; }; #endif // LL_LLVOICEREMOTECTRL_H diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 05479878c1..bfed1afcf1 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -142,7 +142,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) for (int i=0; imIsSelf) { // scale from the range 0.0-1.0 to vivox volume in the range 0-100 - S32 volume = ll_round(p->mVolume / VOLUME_SCALE_VIVOX); + S32 volume = ll_pos_round(p->mVolume / VOLUME_SCALE_VIVOX); bool mute = p->mOnMuteList; if(mute) @@ -3564,6 +3564,11 @@ void LLVivoxVoiceClient::participantUpdatedEvent( */ LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel(); + // Singu Note: This block is different so we also update the active speaker list. + // also initialize voice moderate_mode depend on Agent's participant. See EXT-6937. + // *TODO: remove once a way to request the current voice channel moderation mode is implemented. + bool moderate = gAgentID == participant->mAvatarID; + // ignore session ID of local chat if (voice_cnl && voice_cnl->getSessionID().notNull()) { @@ -3576,14 +3581,20 @@ void LLVivoxVoiceClient::participantUpdatedEvent( { speaker_manager->update(true); - // also initialize voice moderate_mode depend on Agent's participant. See EXT-6937. - // *TODO: remove once a way to request the current voice channel moderation mode is implemented. - if (gAgent.getID() == participant->mAvatarID) + if (moderate) { speaker_manager->initVoiceModerateMode(); } } } + else if (voice_cnl) // Local + { + LLLocalSpeakerMgr::instance().update(true); + } + // Always update active speakers + auto& inst(LLActiveSpeakerMgr::instance()); + inst.update(true); + if (moderate) inst.initVoiceModerateMode(); } else { @@ -3912,7 +3923,7 @@ void LLVivoxVoiceClient::sessionState::removeParticipant(const std::string& uri) vector_replace_with_last(mParticipantList, iter); if (mParticipantList.empty() || mParticipantList.capacity() - mParticipantList.size() > 16) { - vector_shrink_to_fit(mParticipantList); + mParticipantList.shrink_to_fit(); } mParticipantsChanged = true; LL_DEBUGS("Voice") << "participant \"" << uri << "\" (" << iter->mAvatarID << ") removed." << LL_ENDL; @@ -3929,10 +3940,10 @@ void LLVivoxVoiceClient::sessionState::removeAllParticipants() // Singu Note: mParticipantList has replaced both mParticipantsByURI and mParticipantsByUUID, meaning we don't have two maps to maintain any longer. mParticipantList.clear(); - vector_shrink_to_fit(mParticipantList); + mParticipantList.shrink_to_fit(); } -void LLVivoxVoiceClient::getParticipantList(std::set &participants) +void LLVivoxVoiceClient::getParticipantList(uuid_set_t &participants) { if(mAudioSession) { @@ -6364,7 +6375,7 @@ LLVivoxProtocolParser::~LLVivoxProtocolParser() XML_ParserFree(parser); } -static LLFastTimer::DeclareTimer FTM_VIVOX_PROCESS("Vivox Process"); +static LLTrace::BlockTimerStatHandle FTM_VIVOX_PROCESS("Vivox Process"); // virtual LLIOPipe::EStatus LLVivoxProtocolParser::process_impl( @@ -6374,7 +6385,7 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl( LLSD& context, LLPumpIO* pump) { - LLFastTimer t(FTM_VIVOX_PROCESS); + LL_RECORD_BLOCK_TIME(FTM_VIVOX_PROCESS); LLBufferStream istr(channels, buffer.get()); std::ostringstream ostr; while (istr.good()) diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 2d723184bf..9cdf4126c5 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -88,7 +88,7 @@ class LLVivoxVoiceClient : public LLSingleton, virtual LLVoiceDeviceList& getRenderDevices(); //@} - virtual void getParticipantList(std::set &participants); + virtual void getParticipantList(uuid_set_t &participants); virtual bool isParticipant(const LLUUID& speaker_id); // Send a text message to the specified user, initiating the session if necessary. diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 92296ceb43..310558b648 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -53,7 +53,7 @@ const F32 MAX_PART_LIFETIME = 120.f; -extern U64 gFrameTime; +extern U64MicrosecondsImplicit gFrameTime; LLPointer LLVOPartGroup::sVB = NULL; S32 LLVOPartGroup::sVBSlotFree[]; @@ -312,10 +312,10 @@ LLVector3 LLVOPartGroup::getCameraPosition() const return gAgentCamera.getCameraPositionAgent(); } -static LLFastTimer::DeclareTimer FTM_UPDATE_PARTICLES("Update Particles"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_PARTICLES("Update Particles"); BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(FTM_UPDATE_PARTICLES); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_PARTICLES); dirtySpatialGroup(); @@ -408,8 +408,8 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) else inv_camera_dist_squared = 1.f; - llassert(llfinite(inv_camera_dist_squared)); - llassert(!llisnan(inv_camera_dist_squared)); + llassert(std::isfinite(inv_camera_dist_squared)); + llassert(!std::isnan(inv_camera_dist_squared)); F32 area = part->mScale.mV[0] * part->mScale.mV[1] * inv_camera_dist_squared; tot_area = llmax(tot_area, area); @@ -489,6 +489,7 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) BOOL LLVOPartGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, + BOOL pick_rigged, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, @@ -739,8 +740,8 @@ U32 LLVOPartGroup::getPartitionType() const return LLViewerRegion::PARTITION_PARTICLE; } -LLParticlePartition::LLParticlePartition() -: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB) +LLParticlePartition::LLParticlePartition(LLViewerRegion* regionp) +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB, regionp) { mRenderPass = LLRenderPass::PASS_ALPHA; mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES; @@ -749,14 +750,14 @@ LLParticlePartition::LLParticlePartition() mLODPeriod = 1; } -LLHUDParticlePartition::LLHUDParticlePartition() : - LLParticlePartition() +LLHUDParticlePartition::LLHUDParticlePartition(LLViewerRegion* regionp) : + LLParticlePartition(regionp) { mDrawableType = LLPipeline::RENDER_TYPE_HUD_PARTICLES; mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE; } -static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VBO("Particle VBO"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_PARTICLE_VBO("Particle VBO"); void LLParticlePartition::rebuildGeom(LLSpatialGroup* group) { @@ -771,7 +772,7 @@ void LLParticlePartition::rebuildGeom(LLSpatialGroup* group) group->mLastUpdateViewAngle = group->mViewAngle; } - LLFastTimer ftm(FTM_REBUILD_PARTICLE_VBO); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_PARTICLE_VBO); group->clearDrawMap(); @@ -792,7 +793,7 @@ void LLParticlePartition::rebuildGeom(LLSpatialGroup* group) else { group->mVertexBuffer = NULL; - group->mBufferMap.clear(); + group->mBufferVec.clear(); } group->mLastUpdateTime = gFrameTimeSeconds; @@ -846,11 +847,11 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co } -static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_GEOM("Particle Geom"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_PARTICLE_GEOM("Particle Geom"); void LLParticlePartition::getGeometry(LLSpatialGroup* group) { - LLFastTimer ftm(FTM_REBUILD_PARTICLE_GEOM); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_PARTICLE_GEOM); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index 7647fe9920..4f8d144689 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -80,6 +80,7 @@ class LLVOPartGroup : public LLAlphaObject /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, + BOOL pick_rigged, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 48095c2055..6854acb629 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -216,7 +216,8 @@ LLSkyTex::LLSkyTex() : void LLSkyTex::init() { - mSkyData = new LLColor4[sResolution * sResolution]; + // Singu Note: Store as unsigned to avoid casting. + mSkyData = new LLColor4U[sResolution * sResolution]; mSkyDirs = new LLVector3[sResolution * sResolution]; for (S32 i = 0; i < 2; ++i) @@ -286,8 +287,7 @@ void LLSkyTex::create(const F32 brightness) const S32 basic_offset = (i * sResolution + j); S32 offset = basic_offset * sComponents; U32* pix = (U32*)(data + offset); - LLColor4U temp = LLColor4U(mSkyData[basic_offset]); - *pix = temp.mAll; + *pix = mSkyData[basic_offset].mAll; } } createGLImage(sCurrent); @@ -298,7 +298,7 @@ void LLSkyTex::create(const F32 brightness) void LLSkyTex::createGLImage(S32 which) { - mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLGLTexture::LOCAL); + mTexture[which]->createGLTexture(0, mImageRaw[which], nullptr, TRUE, LLGLTexture::LOCAL); mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } @@ -384,9 +384,9 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mSun.setIntensity(SUN_INTENSITY); mMoon.setIntensity(0.1f * SUN_INTENSITY); - mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLGLTexture::BOOST_UI); + mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLGLTexture::BOOST_UI); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); mBloomTexturep->setNoDelete() ; @@ -478,9 +478,9 @@ void LLVOSky::restoreGL() { mSkyTex[i].restoreGL(); } - mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLGLTexture::BOOST_UI); + mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLGLTexture::BOOST_UI); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); mBloomTexturep->setNoDelete() ; @@ -1246,7 +1246,7 @@ void LLVOSky::createDummyVertexBuffer() } } -static LLFastTimer::DeclareTimer FTM_RENDER_FAKE_VBO_UPDATE("Fake VBO Update"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_FAKE_VBO_UPDATE("Fake VBO Update"); void LLVOSky::updateDummyVertexBuffer() { @@ -1259,7 +1259,7 @@ void LLVOSky::updateDummyVertexBuffer() return ; } - LLFastTimer t(FTM_RENDER_FAKE_VBO_UPDATE) ; + LL_RECORD_BLOCK_TIME(FTM_RENDER_FAKE_VBO_UPDATE) ; if(!mFace[FACE_DUMMY] || !mFace[FACE_DUMMY]->getVertexBuffer()) createDummyVertexBuffer() ; @@ -1272,11 +1272,11 @@ void LLVOSky::updateDummyVertexBuffer() //---------------------------------- //end of fake vertex buffer updating //---------------------------------- -static LLFastTimer::DeclareTimer FTM_GEO_SKY("Sky Geometry"); +static LLTrace::BlockTimerStatHandle FTM_GEO_SKY("Sky Geometry"); BOOL LLVOSky::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(FTM_GEO_SKY); + LL_RECORD_BLOCK_TIME(FTM_GEO_SKY); if (mFace[FACE_REFLECTION] == NULL) { LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h index 2a150eccb9..37793b8d20 100644 --- a/indra/newview/llvosky.h +++ b/indra/newview/llvosky.h @@ -42,28 +42,28 @@ // Will clean these up at some point... // -const F32 HORIZON_DIST = 1024.0f; -const F32 SKY_BOX_MULT = 16.0f; -const F32 HEAVENLY_BODY_DIST = HORIZON_DIST - 10.f; -const F32 HEAVENLY_BODY_FACTOR = 0.1f; -const F32 HEAVENLY_BODY_SCALE = HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR; -const F32 EARTH_RADIUS = 6.4e6f; // exact radius = 6.37 x 10^6 m -const F32 ATM_EXP_FALLOFF = 0.000126f; -const F32 ATM_SEA_LEVEL_NDENS = 2.55e25f; +constexpr F32 HORIZON_DIST = 1024.0f; +constexpr F32 SKY_BOX_MULT = 16.0f; +constexpr F32 HEAVENLY_BODY_DIST = HORIZON_DIST - 10.f; +constexpr F32 HEAVENLY_BODY_FACTOR = 0.1f; +constexpr F32 HEAVENLY_BODY_SCALE = HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR; +constexpr F32 EARTH_RADIUS = 6.4e6f; // exact radius = 6.37 x 10^6 m +constexpr F32 ATM_EXP_FALLOFF = 0.000126f; +constexpr F32 ATM_SEA_LEVEL_NDENS = 2.55e25f; // Somewhat arbitrary: -const F32 ATM_HEIGHT = 100000.f; +constexpr F32 ATM_HEIGHT = 100000.f; -const F32 FIRST_STEP = 5000.f; -const F32 INV_FIRST_STEP = 1.f/FIRST_STEP; -const S32 NO_STEPS = 15; -const F32 INV_NO_STEPS = 1.f/NO_STEPS; +constexpr F32 FIRST_STEP = 5000.f; +constexpr F32 INV_FIRST_STEP = 1.f/FIRST_STEP; +constexpr S32 NO_STEPS = 15; +constexpr F32 INV_NO_STEPS = 1.f/NO_STEPS; // constants used in calculation of scattering coeff of clear air -const F32 sigma = 0.035f; -const F32 fsigma = (6.f + 3.f * sigma) / (6.f-7.f*sigma); -const F64 Ndens = 2.55e25; -const F64 Ndens2 = Ndens*Ndens; +constexpr F32 sigma = 0.035f; +constexpr F32 fsigma = (6.f + 3.f * sigma) / (6.f-7.f*sigma); +constexpr F64 Ndens = 2.55e25; +constexpr F64 Ndens2 = Ndens*Ndens; // HACK: Allow server to change sun and moon IDs. // I can't figure out how to pass the appropriate @@ -118,7 +118,8 @@ class LLSkyTex static S32 sComponents; LLPointer mTexture[2]; LLPointer mImageRaw[2]; - LLColor4 *mSkyData; + // Singu Note: Store as unsigned to avoid casting. + LLColor4U *mSkyData; LLVector3 *mSkyDirs; // Cache of sky direction vectors static S32 sCurrent; static F32 sInterpVal; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index a661b0e34b..99312e1ca5 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -218,7 +218,7 @@ LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline) return mDrawable; } -static LLFastTimer::DeclareTimer FTM_UPDATE_TERRAIN("Update Terrain"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_TERRAIN("Update Terrain"); void LLVOSurfacePatch::updateGL() { @@ -230,7 +230,7 @@ void LLVOSurfacePatch::updateGL() BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(FTM_UPDATE_TERRAIN); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_TERRAIN); dirtySpatialGroup(TRUE); @@ -267,18 +267,19 @@ BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) length = patch_width / render_stride; - if (mPatchp->getNeighborPatch(NORTH)) + LLSurfacePatch* neighborPatch; + if (neighborPatch = mPatchp->getNeighborPatch(NORTH)) { - north_stride = mPatchp->getNeighborPatch(NORTH)->getRenderStride(); + north_stride = neighborPatch->getRenderStride(); } else { north_stride = render_stride; } - if (mPatchp->getNeighborPatch(EAST)) + if (neighborPatch = mPatchp->getNeighborPatch(EAST)) { - east_stride = mPatchp->getNeighborPatch(EAST)->getRenderStride(); + east_stride = neighborPatch->getRenderStride(); } else { @@ -942,7 +943,7 @@ void LLVOSurfacePatch::getGeomSizesEast(const S32 stride, const S32 east_stride, } } -BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, S32 *face_hitp, +BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { @@ -1062,8 +1063,8 @@ U32 LLVOSurfacePatch::getPartitionType() const return LLViewerRegion::PARTITION_TERRAIN; } -LLTerrainPartition::LLTerrainPartition() -: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB) +LLTerrainPartition::LLTerrainPartition(LLViewerRegion* regionp) +: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB, regionp) { mOcclusionEnabled = FALSE; mInfiniteFarClip = TRUE; @@ -1076,10 +1077,10 @@ LLVertexBuffer* LLTerrainPartition::createVertexBuffer(U32 type_mask, U32 usage) return new LLVertexBufferTerrain(); } -static LLFastTimer::DeclareTimer FTM_REBUILD_TERRAIN_VB("Terrain VB"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_TERRAIN_VB("Terrain VB"); void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { - LLFastTimer ftm(FTM_REBUILD_TERRAIN_VB); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_TERRAIN_VB); LLVertexBuffer* buffer = group->mVertexBuffer; diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index 6818c98f03..e073e9df77 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -88,6 +88,7 @@ class LLVOSurfacePatch : public LLStaticViewerObject /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 48fca70a98..16ccc97b59 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -337,7 +337,7 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, // Load Species-Specific data // static const S32 MAX_TREE_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL = 32 ; //frames. - mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mTreeImagep->setMaxVirtualSizeResetInterval(MAX_TREE_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); //allow to wait for at most 16 frames to reset virtual size. mBranchLength = sSpeciesTable[mSpecies]->mBranchLength; @@ -548,7 +548,7 @@ LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline) const S32 LEAF_INDICES = 24; const S32 LEAF_VERTICES = 16; -static LLFastTimer::DeclareTimer FTM_UPDATE_TREE("Update Tree"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_TREE("Update Tree"); void LLVOTree::resetVertexBuffers() { @@ -557,7 +557,7 @@ void LLVOTree::resetVertexBuffers() BOOL LLVOTree::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(FTM_UPDATE_TREE); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_TREE); for(std::vector >::iterator iter = mDrawList.begin(); iter != mDrawList.end(); iter++) { @@ -1205,7 +1205,7 @@ void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) mDrawable->setPositionGroup(pos); } -BOOL LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, S32 *face_hitp, +BOOL LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { @@ -1260,8 +1260,8 @@ U32 LLVOTree::getPartitionType() const return LLViewerRegion::PARTITION_TREE; } -LLTreePartition::LLTreePartition() -: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB) +LLTreePartition::LLTreePartition(LLViewerRegion* regionp) +: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB, regionp) { mDrawableType = LLPipeline::RENDER_TYPE_TREE; mPartitionType = LLViewerRegion::PARTITION_TREE; diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h index 4751b81eb3..54f629c407 100644 --- a/indra/newview/llvotree.h +++ b/indra/newview/llvotree.h @@ -116,6 +116,7 @@ class LLVOTree : public LLViewerObject /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index ae2d312178..722aaca160 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -61,6 +61,7 @@ #include "llspatialpartition.h" #include "llhudmanager.h" #include "llflexibleobject.h" +#include "llskinningutil.h" #include "llsky.h" #include "lltexturefetch.h" #include "llvector4a.h" @@ -82,8 +83,11 @@ #include "lldatapacker.h" #include "llviewershadermgr.h" #include "llvoavatar.h" +#include "llcontrolavatar.h" +#include "llvoavatarself.h" #include "llvocache.h" #include "llmaterialmgr.h" +#include "llsculptidsize.h" // [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0d) #include "rlvhandler.h" @@ -93,6 +97,7 @@ const S32 MIN_QUIET_FRAMES_COALESCE = 30; const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; const F32 FORCE_CULL_AREA = 8.f; +U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 1; BOOL gAnimateTextures = TRUE; //extern BOOL gHideSelectedObjects; @@ -106,9 +111,9 @@ S32 LLVOVolume::mRenderComplexity_current = 0; LLPointer LLVOVolume::sObjectMediaClient = NULL; LLPointer LLVOVolume::sObjectMediaNavigateClient = NULL; -static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles"); -static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes"); -static LLFastTimer::DeclareTimer FTM_VOLUME_TEXTURES("Volume Textures"); +static LLTrace::BlockTimerStatHandle FTM_GEN_TRIANGLES("Generate Triangles"); +static LLTrace::BlockTimerStatHandle FTM_GEN_VOLUME("Generate Volumes"); +static LLTrace::BlockTimerStatHandle FTM_VOLUME_TEXTURES("Volume Textures"); // Implementation class of LLMediaDataClientObject. See llmediadataclient.h class LLMediaDataClientObjectImpl : public LLMediaDataClientObject @@ -221,6 +226,9 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mFaceMappingChanged = FALSE; mLOD = MIN_LOD; + mLODDistance = 0.0f; + mLODAdjustedDistance = 0.0f; + mLODRadius = 0.0f; mTextureAnimp = NULL; mVolumeChanged = FALSE; mVObjRadius = LLVector3(1,1,0.5f).length(); @@ -231,8 +239,9 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mMediaImplList.resize(getNumTEs()); mLastFetchedMediaVersion = -1; - mIndexInTex = 0; + memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS); mMDCImplCount = 0; + mLastRiggingInfoLOD = -1; } LLVOVolume::~LLVOVolume() @@ -242,6 +251,8 @@ LLVOVolume::~LLVOVolume() delete mVolumeImpl; mVolumeImpl = NULL; + gMeshRepo.unregisterMesh(this); + if(!mMediaImplList.empty()) { for(U32 i = 0 ; i < mMediaImplList.size() ; i++) @@ -254,10 +265,16 @@ LLVOVolume::~LLVOVolume() } } +LLVOVolume* LLVOVolume::asVolume() +{ + return this; +} + void LLVOVolume::markDead() { if (!mDead) { + LLSculptIDSize::instance().rem(getVolume()->getParams().getSculptID()); if(getMDCImplCount() > 0) { LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast(this), false); @@ -273,7 +290,12 @@ void LLVOVolume::markDead() if (mSculptTexture.notNull()) { - mSculptTexture->removeVolume(this); + mSculptTexture->removeVolume(LLRender::SCULPT_TEX, this); + } + + if (mLightTexture.notNull()) + { + mLightTexture->removeVolume(LLRender::LIGHT_TEX, this); } } @@ -321,7 +343,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, U8 sculpt_type = 0; if (isSculpted()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = getSculptParams(); sculpt_id = sculpt_params->getSculptTexture(); sculpt_type = sculpt_params->getSculptType(); } @@ -476,7 +498,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, { U8 tdpbuffer[1024]; LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num); + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num, 1024); S32 result = unpackTEMessage(tdp); if (result & teDirtyBits) { @@ -675,7 +697,7 @@ BOOL LLVOVolume::isVisible() const void LLVOVolume::updateTextureVirtualSize(bool forced) { - LLFastTimer ftm(FTM_VOLUME_TEXTURES); + LL_RECORD_BLOCK_TIME(FTM_VOLUME_TEXTURES); // Update the pixel area of all faces if(mDrawable.isNull()) @@ -838,9 +860,9 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) if (getLightTextureID().notNull()) { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + const LLLightImageParams* params = getLightImageParams(); LLUUID id = params->getLightTexture(); - mLightTexture = LLViewerTextureManager::getFetchedTexture(id); + mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); if (mLightTexture.notNull()) { F32 rad = getLightRadius(); @@ -965,13 +987,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo // if it's a mesh if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { //meshes might not have all LODs, get the force detail to best existing LOD - LLUUID mesh_id = volume_params.getSculptID(); - - lod = gMeshRepo.getActualMeshLOD(volume_params, lod); - if (lod == -1) + if (NO_LOD != lod) { - is404 = TRUE; - lod = 0; + lod = gMeshRepo.getActualMeshLOD(volume_params, lod); + if (lod == -1) + { + is404 = TRUE; + lod = 0; + } } } } @@ -983,7 +1006,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false); if (!mVolumeImpl) { - LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData* data = (LLFlexibleObjectData*)getFlexibleObjectData(); mVolumeImpl = new LLVolumeImplFlexible(this, data); } } @@ -1005,7 +1028,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo if (is404) { - setIcon(LLViewerTextureManager::getFetchedTextureFromFile("inv_item_mesh.tga", TRUE, LLGLTexture::BOOST_UI)); + setIcon(LLViewerTextureManager::getFetchedTextureFromFile("inv_item_mesh.tga", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); //render prim proxy when mesh loading attempts give up volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); @@ -1073,8 +1096,10 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo return TRUE; } - - + else if (NO_LOD == lod) + { + LLSculptIDSize::instance().resetSizeSum(volume_params.getSculptID()); + } return FALSE; } @@ -1085,11 +1110,11 @@ void LLVOVolume::updateSculptTexture() if (isSculpted() && !isMesh()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = getSculptParams(); LLUUID id = sculpt_params->getSculptTexture(); if (id.notNull()) { - mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); } } else @@ -1101,20 +1126,44 @@ void LLVOVolume::updateSculptTexture() { if (old_sculpt.notNull()) { - old_sculpt->removeVolume(this); + old_sculpt->removeVolume(LLRender::SCULPT_TEX, this); } if (mSculptTexture.notNull()) { - mSculptTexture->addVolume(this); + mSculptTexture->addVolume(LLRender::SCULPT_TEX, this); } } + +} +void LLVOVolume::updateVisualComplexity() +{ + LLVOAvatar* avatar = getAvatarAncestor(); + if (avatar) + { + avatar->updateVisualComplexity(); + } + LLVOAvatar* rigged_avatar = getAvatar(); + if(rigged_avatar && (rigged_avatar != avatar)) + { + rigged_avatar->updateVisualComplexity(); + } } void LLVOVolume::notifyMeshLoaded() { mSculptChanged = TRUE; gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); + + if (getAvatar() && !isAnimatedObject()) + { + getAvatar()->addAttachmentOverridesForObject(this); + } + if (getControlAvatar() && isAnimatedObject()) + { + getControlAvatar()->addAttachmentOverridesForObject(this); + } + updateVisualComplexity(); } // sculpt replaces generate() for sculpted surfaces @@ -1189,12 +1238,12 @@ void LLVOVolume::sculpt() sculpt_data = raw_image->getData(); } - getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level); + getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level, mSculptTexture->isMissingAsset()); //notify rebuild any other VOVolumes that reference this sculpty volume - for (S32 i = 0; i < mSculptTexture->getNumVolumes(); ++i) + for (S32 i = 0; i < mSculptTexture->getNumVolumes(LLRender::SCULPT_TEX); ++i) { - LLVOVolume* volume = (*(mSculptTexture->getVolumeList()))[i]; + LLVOVolume* volume = (*(mSculptTexture->getVolumeList(LLRender::SCULPT_TEX)))[i]; if (volume != this && volume->getVolume() == getVolume()) { gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); @@ -1203,18 +1252,18 @@ void LLVOVolume::sculpt() } } -S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius) +S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor) { S32 cur_detail; if (LLPipeline::sDynamicLOD) { // We've got LOD in the profile, and in the twist. Use radius. - F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; + F32 tan_angle = (lod_factor*radius)/distance; cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); } else { - cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3); + cur_detail = llclamp((S32) (sqrtf(radius)*lod_factor*4.f), 0, 3); } return cur_detail; } @@ -1230,20 +1279,61 @@ BOOL LLVOVolume::calcLOD() F32 radius; F32 distance; + F32 lod_factor = LLVOVolume::sLODFactor; if (mDrawable->isState(LLDrawable::RIGGED) && getAvatar() && getAvatar()->mDrawable) { LLVOAvatar* avatar = getAvatar(); + // Not sure how this can really happen, but alas it does. Better exit here than crashing. + if( !avatar || !avatar->mDrawable ) + { + return FALSE; + } + distance = avatar->mDrawable->mDistanceWRTCamera; - radius = avatar->getBinRadius(); + + + if (avatar->isControlAvatar()) + { + // MAINT-7926 Handle volumes in an animated object as a special case + const LLVector3* box = avatar->getLastAnimExtents(); + LLVector3 diag = box[1] - box[0]; + radius = diag.magVec() * 0.5f; + LL_DEBUGS("DynamicBox") << avatar->getFullname() << " diag " << diag << " radius " << radius << LL_ENDL; + } + else + { + // Volume in a rigged mesh attached to a regular avatar. + // Note this isn't really a radius, so distance calcs are off by factor of 2 + //radius = avatar->getBinRadius(); + // SL-937: add dynamic box handling for rigged mesh on regular avatars. + const LLVector3* box = avatar->getLastAnimExtents(); + LLVector3 diag = box[1] - box[0]; + radius = diag.magVec(); // preserve old BinRadius behavior - 2x off + LL_DEBUGS("DynamicBox") << avatar->getFullname() << " diag " << diag << " radius " << radius << LL_ENDL; + } + if (distance <= 0.f || radius <= 0.f) + { + LL_DEBUGS("DynamicBox","CalcLOD") << "avatar distance/radius uninitialized, skipping" << LL_ENDL; + return FALSE; + } } else { distance = mDrawable->mDistanceWRTCamera; radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); + if (distance <= 0.f || radius <= 0.f) + { + LL_DEBUGS("DynamicBox","CalcLOD") << "non-avatar distance/radius uninitialized, skipping" << LL_ENDL; + return FALSE; + } } + //hold onto unmodified distance for debugging + //F32 debug_distance = distance; + mLODDistance = distance; + mLODRadius = radius; distance *= sDistanceFactor; F32 rampDist = LLVOVolume::sLODFactor * 2; @@ -1257,16 +1347,25 @@ BOOL LLVOVolume::calcLOD() // DON'T Compensate for field of view changing on FOV zoom. distance *= F_PI/3.f; - cur_detail = computeLODDetail(ll_round(distance, 0.01f), - ll_round(radius, 0.01f)); + + mLODAdjustedDistance = distance; + + if (isHUDAttachment()) + { + // HUDs always show at highest detail + cur_detail = 3; + } + else + { + cur_detail = computeLODDetail(ll_round(distance, 0.01f), ll_round(radius, 0.01f), lod_factor); + } if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && mDrawable->getFace(0)) { - //setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail)); - - setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex())); + // This is a debug display for LODs. Please don't put the texture index here. + setDebugText(llformat("%d", cur_detail)); } if (cur_detail != mLOD) @@ -1275,10 +1374,7 @@ BOOL LLVOVolume::calcLOD() mLOD = cur_detail; return TRUE; } - else - { - return FALSE; - } + return FALSE; } BOOL LLVOVolume::updateLOD() @@ -1288,7 +1384,16 @@ BOOL LLVOVolume::updateLOD() return FALSE; } - BOOL lod_changed = calcLOD(); + BOOL lod_changed = FALSE; + + if (!LLSculptIDSize::instance().isUnloaded(getVolume()->getParams().getSculptID())) + { + lod_changed = calcLOD(); + } + else + { + return FALSE; + } if (lod_changed) { @@ -1338,7 +1443,8 @@ BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp) void LLVOVolume::updateFaceFlags() { - for (S32 i = 0; i < getVolume()->getNumFaces(); i++) + // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() + for (S32 i = 0; i < getVolume()->getNumFaces() && i < mDrawable->getNumFaces(); i++) { LLFace *face = mDrawable->getFace(i); if (face) @@ -1368,7 +1474,8 @@ void LLVOVolume::updateFaceFlags() BOOL LLVOVolume::setParent(LLViewerObject* parent) { BOOL ret = FALSE ; - if (parent != getParent()) + LLViewerObject *old_parent = (LLViewerObject*) getParent(); + if (parent != old_parent) { ret = LLViewerObject::setParent(parent); if (ret && mDrawable) @@ -1376,6 +1483,7 @@ BOOL LLVOVolume::setParent(LLViewerObject* parent) gPipeline.markMoved(mDrawable); gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); } + onReparent(old_parent, parent); } return ret ; @@ -1431,7 +1539,7 @@ void LLVOVolume::regenFaces() BOOL LLVOVolume::genBBoxes(BOOL force_global) { - BOOL res = TRUE; + bool res = true; LLVector4a min,max; @@ -1440,30 +1548,71 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); - // bool rigged = false; + if (getRiggedVolume()) + { + // MAINT-8264 - better to use the existing call in calling + // func LLVOVolume::updateGeometry() if we can detect when + // updates needed, set REBUILD_RIGGED accordingly. + + // Without the flag, this will remove unused rigged volumes, which we are not currently very aggressive about. + updateRiggedVolume(); + } + LLVolume* volume = mRiggedVolume; if (!volume) { volume = getVolume(); } - for (S32 i = 0; i < getVolume()->getNumVolumeFaces(); i++) + bool any_valid_boxes = false; + + static LLCachedControl sh_override_rigged_bounds("SHOverrideRiggedBounds", false); + if (sh_override_rigged_bounds && isAttachment() && (mDrawable->isState(LLDrawable::RIGGED) || isRiggedMesh())) + { + LLVOAvatar* root = getAvatar(); + if (root) + { + any_valid_boxes = true; + static const LLVector3 PAD_SIZE(.1f, .1f, .1f); + LLVector3 minpos = -PAD_SIZE; + LLVector3 maxpos = PAD_SIZE; + min.load3(minpos.mV,1.f); + max.load3(maxpos.mV, 1.f); + } + } + if (!any_valid_boxes) { +// There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() + for (S32 i = 0; + i < getVolume()->getNumVolumeFaces() && i < mDrawable->getNumFaces() && i < getNumTEs(); + i++) { LLFace *face = mDrawable->getFace(i); if (!face) { continue; } - res &= face->genVolumeBBoxes(*volume, i, + bool face_res = face->genVolumeBBoxes(*volume, i, mRelativeXform, (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); + // Singu note: Don't let one bad face to ruin the whole volume. &= bad. |= good. + res &= face_res; + // MAINT-8264 - ignore bboxes of ill-formed faces. + if (!face_res) + { + continue; + } if (rebuild) { - if (i == 0) + if (getRiggedVolume()) + { + LL_DEBUGS("RiggedBox") << "rebuilding box, face " << i << " extents " << face->mExtents[0] << ", " << face->mExtents[1] << LL_ENDL; + } + if (!any_valid_boxes) { min = face->mExtents[0]; max = face->mExtents[1]; + any_valid_boxes = true; } else { @@ -1472,18 +1621,30 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) } } } - - if (rebuild) + } + + if (any_valid_boxes) + { + if (rebuild) + { + if (getRiggedVolume()) + { + LL_DEBUGS("RiggedBox") << "rebuilding got extents " << min << ", " << max << LL_ENDL; + } + mDrawable->setSpatialExtents(min, max); + min.add(max); + min.mul(0.5f); + mDrawable->setPositionGroup(min); + } + + updateRadius(); + mDrawable->movePartition(); + } + else { - mDrawable->setSpatialExtents(min,max); - min.add(max); - min.mul(0.5f); - mDrawable->setPositionGroup(min); + LL_DEBUGS("RiggedBox") << "genBBoxes failed to find any valid face boxes" << LL_ENDL; } - updateRadius(); - mDrawable->movePartition(); - return res; } @@ -1560,18 +1721,83 @@ void LLVOVolume::updateRelativeXform(bool force_identity) } } -static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies"); -static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives"); -static LLFastTimer::DeclareTimer FTM_UPDATE_RIGGED_VOLUME("Update Rigged"); +static LLTrace::BlockTimerStatHandle FTM_GEN_FLEX("Generate Flexies"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_PRIMITIVES("Update Primitives"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_RIGGED_VOLUME("Update Rigged"); + +bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) +{ + bool regen_faces = false; + + LLVolume *old_volumep, *new_volumep; + F32 old_lod, new_lod; + S32 old_num_faces, new_num_faces ; + + old_volumep = getVolume(); + old_lod = old_volumep->getDetail(); + old_num_faces = old_volumep->getNumFaces() ; + old_volumep = NULL ; + + { + LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); + const LLVolumeParams &volume_params = getVolume()->getParams(); + setVolume(volume_params, 0); + } + + new_volumep = getVolume(); + new_lod = new_volumep->getDetail(); + new_num_faces = new_volumep->getNumFaces() ; + new_volumep = NULL ; + + if ((new_lod != old_lod) || mSculptChanged) + { + if (mDrawable->isState(LLDrawable::RIGGED)) + { + updateVisualComplexity(); + } + + compiled = TRUE; + sNumLODChanges += new_num_faces ; + + if((S32)getNumTEs() != getVolume()->getNumFaces()) + { + setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. + } + + drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() + + { + LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); + regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs(); + if (regen_faces) + { + regenFaces(); + } + + if (mSculptChanged) + { //changes in sculpt maps can thrash an object bounding box without + //triggering a spatial group bounding box update -- force spatial group + //to update bounding boxes + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->unbound(); + } + } + } + } + + return regen_faces; +} BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { - LLFastTimer t(FTM_UPDATE_PRIMITIVES); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_PRIMITIVES); if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) { { - LLFastTimer t(FTM_UPDATE_RIGGED_VOLUME); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_RIGGED_VOLUME); updateRiggedVolume(); } genBBoxes(FALSE); @@ -1582,7 +1808,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { BOOL res; { - LLFastTimer t(FTM_GEN_FLEX); + LL_RECORD_BLOCK_TIME(FTM_GEN_FLEX); res = mVolumeImpl->doUpdateGeometry(drawable); } updateFaceFlags(); @@ -1608,91 +1834,56 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); - compiled = TRUE; + bool was_regen_faces = false; if (mVolumeChanged) { - LLFastTimer ftm(FTM_GEN_VOLUME); - LLVolumeParams volume_params = getVolume()->getParams(); - setVolume(volume_params, 0); + was_regen_faces = lodOrSculptChanged(drawable, compiled); drawable->setState(LLDrawable::REBUILD_VOLUME); } - + else if (mSculptChanged || mLODChanged) { - LLFastTimer t(FTM_GEN_TRIANGLES); + compiled = TRUE; + was_regen_faces = lodOrSculptChanged(drawable, compiled); + } + + if (!was_regen_faces) { + LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); regenFaces(); - genBBoxes(FALSE); } + + genBBoxes(FALSE); } - else if ((mLODChanged) || (mSculptChanged)) + else if (mLODChanged || mSculptChanged) { dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); - - LLVolume *old_volumep, *new_volumep; - F32 old_lod, new_lod; - S32 old_num_faces, new_num_faces ; - - old_volumep = getVolume(); - old_lod = old_volumep->getDetail(); - old_num_faces = old_volumep->getNumFaces() ; - old_volumep = NULL ; - + compiled = TRUE; + lodOrSculptChanged(drawable, compiled); + + if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED)) { - LLFastTimer ftm(FTM_GEN_VOLUME); - LLVolumeParams volume_params = getVolume()->getParams(); - setVolume(volume_params, 0); + updateRiggedVolume(false); } + genBBoxes(FALSE); - new_volumep = getVolume(); - new_lod = new_volumep->getDetail(); - new_num_faces = new_volumep->getNumFaces() ; - new_volumep = NULL ; - - if ((new_lod != old_lod) || mSculptChanged) - { - compiled = TRUE; - sNumLODChanges += new_num_faces ; - - if((S32)getNumTEs() != getVolume()->getNumFaces()) - { - setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. - } - - drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() - - { - LLFastTimer t(FTM_GEN_TRIANGLES); - if (new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs()) - { - regenFaces(); - } - genBBoxes(FALSE); - - if (mSculptChanged) - { //changes in sculpt maps can thrash an object bounding box without - //triggering a spatial group bounding box update -- force spatial group - //to update bounding boxes - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - group->unbound(); - } - } - } - } } // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local else { compiled = TRUE; // All it did was move or we changed the texture coordinate offset - LLFastTimer t(FTM_GEN_TRIANGLES); + LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); genBBoxes(FALSE); } // Update face flags updateFaceFlags(); + if(compiled) + { + LLPipeline::sCompiles++; + } + mVolumeChanged = FALSE; mLODChanged = FALSE; mSculptChanged = FALSE; @@ -1757,7 +1948,7 @@ void LLVOVolume::setNumTEs(const U8 num_tes) } else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed { - U8 end = mMediaImplList.size() ; + size_t end = mMediaImplList.size() ; for(U8 i = num_tes; i < end ; i++) { removeMediaImpl(i) ; @@ -1819,7 +2010,7 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) const LLTextureEntry *tep = getTE(te); if (!tep) { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + LL_WARNS("MaterialTEs") << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; } else if (color != tep->getColor()) { @@ -1971,10 +2162,243 @@ S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) return res; } +bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture) +{ //Ok, here we have confirmation about texture creation, check our wait-list + //and make changes, or return false + + std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); + + typedef std::map map_te_material; + map_te_material new_material; + + for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) + { + LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); + + //here we just interesting in DIFFUSE_MAP only! + if(cur_material.notNull() && LLRender::DIFFUSE_MAP == range_it->second.map && GL_RGBA != texture->getPrimaryFormat()) + { //ok let's check the diffuse mode + switch(cur_material->getDiffuseAlphaMode()) + { + case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: + case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: + case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: + { //uups... we have non 32 bit texture with LLMaterial::DIFFUSE_ALPHA_MODE_* => LLMaterial::DIFFUSE_ALPHA_MODE_NONE + + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + + } break; + } //switch + } //if + } //for + + //setup new materials + for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) + { + LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); + LLViewerObject::setTEMaterialParams(it->first, it->second); + } + + //clear wait-list + mWaitingTextureInfo.erase(range.first, range.second); + + return 0 != new_material.size(); +} + +bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) +{ //Ok, here if we wait information about texture and it's missing + //then depending from the texture map (diffuse, normal, or specular) + //make changes in material and confirm it. If not return false. + std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); + if(range.first == range.second) return false; + + typedef std::map map_te_material; + map_te_material new_material; + + for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) + { + LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); + if (cur_material.isNull()) + continue; + + switch(range_it->second.map) + { + case LLRender::DIFFUSE_MAP: + { + if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode()) + { //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + } + } break; + case LLRender::NORMAL_MAP: + { //missing texture => reset material texture id + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setNormalID(LLUUID::null); + } break; + case LLRender::SPECULAR_MAP: + { //missing texture => reset material texture id + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setSpecularID(LLUUID::null); + } break; + case LLRender::NUM_TEXTURE_CHANNELS: + //nothing to do, make compiler happy + break; + } //switch + } //for + + //setup new materials + for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) + { + LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), it->second); + LLViewerObject::setTEMaterialParams(it->first, it->second); + } + + //clear wait-list + mWaitingTextureInfo.erase(range.first, range.second); + + return 0 != new_material.size(); +} + S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) { - S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams); - LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterialParams) ? pMaterialParams->asLLSD() : LLSD("null")) << " res " << res + LLMaterialPtr pMaterial = const_cast(pMaterialParams); + + if(pMaterialParams) + { //check all of them according to material settings + + LLViewerTexture *img_diffuse = getTEImage(te); + LLViewerTexture *img_normal = getTENormalMap(te); + LLViewerTexture *img_specular = getTESpecularMap(te); + + llassert(NULL != img_diffuse); + + LLMaterialPtr new_material = NULL; + + //diffuse + if(NULL != img_diffuse) + { //guard + if(0 == img_diffuse->getPrimaryFormat() && !img_diffuse->isMissingAsset()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(img_diffuse->getID(), material_info(LLRender::DIFFUSE_MAP, te))); + } + else + { + bool bSetDiffuseNone = false; + if(img_diffuse->isMissingAsset()) + { + bSetDiffuseNone = true; + } + else + { + switch(pMaterialParams->getDiffuseAlphaMode()) + { + case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: + case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: + case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: + { //all of them modes available only for 32 bit textures + LLTextureEntry* tex_entry = getTE(te); + bool bIsBakedImageId = false; + if (tex_entry && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(tex_entry->getID())) + { + bIsBakedImageId = true; + } + if (GL_RGBA != img_diffuse->getPrimaryFormat() && !bIsBakedImageId) + { + bSetDiffuseNone = true; + } + } break; + } + } //else + + + if(bSetDiffuseNone) + { //upps... we should substitute this material with LLMaterial::DIFFUSE_ALPHA_MODE_NONE + new_material = new LLMaterial(pMaterialParams->asLLSD()); + new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + } + } + } + + //normal + if(LLUUID::null != pMaterialParams->getNormalID()) + { + if(img_normal && img_normal->isMissingAsset() && img_normal->getID() == pMaterialParams->getNormalID()) + { + if(!new_material) { + new_material = new LLMaterial(pMaterialParams->asLLSD()); + } + new_material->setNormalID(LLUUID::null); + } + else if(NULL == img_normal || 0 == img_normal->getPrimaryFormat()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getNormalID(), material_info(LLRender::NORMAL_MAP,te))); + } + + } + + + //specular + if(LLUUID::null != pMaterialParams->getSpecularID()) + { + if(img_specular && img_specular->isMissingAsset() && img_specular->getID() == pMaterialParams->getSpecularID()) + { + if(!new_material) { + new_material = new LLMaterial(pMaterialParams->asLLSD()); + } + new_material->setSpecularID(LLUUID::null); + } + else if(NULL == img_specular || 0 == img_specular->getPrimaryFormat()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getSpecularID(), material_info(LLRender::SPECULAR_MAP, te))); + } + } + + if(new_material) { + pMaterial = new_material; + LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), pMaterial); + } + } + + S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial); + + LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) << LL_ENDL; setChanged(ALL_CHANGED); @@ -2109,12 +2533,10 @@ void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std:: mLastFetchedMediaVersion = fetched_version; //LL_INFOS() << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << LL_ENDL; - LLSD::array_const_iterator iter = media_data_array.beginArray(); - LLSD::array_const_iterator end = media_data_array.endArray(); U8 texture_index = 0; - for (; iter != end; ++iter, ++texture_index) + for (auto const& entry : media_data_array.array()) { - syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); + syncMediaData(texture_index++, entry, false/*merge*/, false/*ignore_agent*/); } } } @@ -2218,7 +2640,9 @@ void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL; impl->setMediaFailed(true); } - else { + // Make sure we are not bouncing to url we came from + else if (impl->getCurrentMediaURL() != url) + { // Okay, navigate now LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL; impl->navigateTo(url, "", false, true); @@ -2530,33 +2954,48 @@ S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S void LLVOVolume::setLightTextureID(LLUUID id) { + LLViewerTexture* old_texturep = getLightTexture(); // same as mLightTexture, but inits if nessesary if (id.notNull()) { if (!hasLightTexture()) { setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); } - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + else if (old_texturep) + { + old_texturep->removeVolume(LLRender::LIGHT_TEX, this); + } + LLLightImageParams* param_block = (LLLightImageParams*)getLightImageParams(); if (param_block && param_block->getLightTexture() != id) { param_block->setLightTexture(id); parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); } + LLViewerTexture* tex = getLightTexture(); + if (tex) + { + tex->addVolume(LLRender::LIGHT_TEX, this); // new texture + } + else + { + LL_WARNS() << "Can't get light texture for ID " << id.asString() << LL_ENDL; + } } - else + else if (hasLightTexture()) { - if (hasLightTexture()) + if (old_texturep) { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - mLightTexture = NULL; + old_texturep->removeVolume(LLRender::LIGHT_TEX, this); } + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + mLightTexture = NULL; } } void LLVOVolume::setSpotLightParams(LLVector3 params) { - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLLightImageParams* param_block = (LLLightImageParams*)getLightImageParams(); if (param_block && param_block->getParams() != params) { param_block->setParams(params); @@ -2593,7 +3032,7 @@ void LLVOVolume::setIsLight(BOOL is_light) void LLVOVolume::setLightColor(const LLColor3& color) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = (LLLightParams *)getLightParams(); if (param_block) { if (param_block->getColor() != color) @@ -2608,7 +3047,7 @@ void LLVOVolume::setLightColor(const LLColor3& color) void LLVOVolume::setLightIntensity(F32 intensity) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = (LLLightParams *)getLightParams(); if (param_block) { if (param_block->getColor().mV[3] != intensity) @@ -2621,7 +3060,7 @@ void LLVOVolume::setLightIntensity(F32 intensity) void LLVOVolume::setLightRadius(F32 radius) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = (LLLightParams *)getLightParams(); if (param_block) { if (param_block->getRadius() != radius) @@ -2634,7 +3073,7 @@ void LLVOVolume::setLightRadius(F32 radius) void LLVOVolume::setLightFalloff(F32 falloff) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = (LLLightParams *)getLightParams(); if (param_block) { if (param_block->getFalloff() != falloff) @@ -2647,7 +3086,7 @@ void LLVOVolume::setLightFalloff(F32 falloff) void LLVOVolume::setLightCutoff(F32 cutoff) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = (LLLightParams *)getLightParams(); if (param_block) { if (param_block->getCutoff() != cutoff) @@ -2662,12 +3101,12 @@ void LLVOVolume::setLightCutoff(F32 cutoff) BOOL LLVOVolume::getIsLight() const { - return getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT); + return getLightParams() != nullptr; } LLColor3 LLVOVolume::getLightBaseColor() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return LLColor3(param_block->getColor()); @@ -2680,7 +3119,7 @@ LLColor3 LLVOVolume::getLightBaseColor() const LLColor3 LLVOVolume::getLightColor() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return LLColor3(param_block->getColor()) * param_block->getColor().mV[3]; @@ -2693,13 +3132,10 @@ LLColor3 LLVOVolume::getLightColor() 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; @@ -2708,13 +3144,10 @@ LLUUID LLVOVolume::getLightTextureID() 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(); @@ -2751,8 +3184,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(); } @@ -2768,7 +3201,7 @@ LLViewerTexture* LLVOVolume::getLightTexture() { if (mLightTexture.isNull() || id != mLightTexture->getID()) { - mLightTexture = LLViewerTextureManager::getFetchedTexture(id); + mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); } } else @@ -2781,7 +3214,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->getColor().mV[3]; @@ -2794,7 +3227,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(); @@ -2807,7 +3240,7 @@ F32 LLVOVolume::getLightRadius() const F32 LLVOVolume::getLightFalloff() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return param_block->getFalloff(); @@ -2820,7 +3253,7 @@ F32 LLVOVolume::getLightFalloff() 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(); @@ -2843,7 +3276,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) @@ -2862,7 +3295,7 @@ BOOL LLVOVolume::isFlexible() const BOOL LLVOVolume::isSculpted() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + if (getSculptParams()) { return TRUE; } @@ -2874,7 +3307,7 @@ BOOL LLVOVolume::isMesh() const { if (isSculpted()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = getSculptParams(); U8 sculpt_type = sculpt_params->getSculptType(); if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) @@ -2889,7 +3322,7 @@ BOOL LLVOVolume::isMesh() const BOOL LLVOVolume::hasLightTexture() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + if (getLightImageParams()) { return TRUE; } @@ -2911,55 +3344,254 @@ BOOL LLVOVolume::isVolumeGlobal() const return FALSE; } -BOOL LLVOVolume::canBeFlexible() const +BOOL LLVOVolume::canBeFlexible() const +{ + U8 path = getVolume()->getParams().getPathParams().getCurveType(); + return (path == LL_PCODE_PATH_FLEXIBLE || path == LL_PCODE_PATH_LINE); +} + +BOOL LLVOVolume::setIsFlexible(BOOL is_flexible) +{ + BOOL res = FALSE; + BOOL was_flexible = isFlexible(); + LLVolumeParams volume_params; + if (is_flexible) + { + if (!was_flexible) + { + volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); + res = TRUE; + setFlags(FLAGS_USE_PHYSICS, FALSE); + setFlags(FLAGS_PHANTOM, TRUE); + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); + if (mDrawable) + { + mDrawable->makeActive(); + } + } + } + else + { + if (was_flexible) + { + volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_LINE); + res = TRUE; + setFlags(FLAGS_PHANTOM, FALSE); + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true); + } + } + if (res) + { + res = setVolume(volume_params, 1); + if (res) + { + markForUpdate(TRUE); + } + } + return res; +} + +const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const +{ + if (getVolume()) + { + return gMeshRepo.getSkinInfo(getVolume()->getParams().getSculptID(), this); + } + else + { + return NULL; + } +} + +// virtual +BOOL LLVOVolume::isRiggedMesh() const +{ + return isMesh() && getSkinInfo(); +} + +//---------------------------------------------------------------------------- +U32 LLVOVolume::getExtendedMeshFlags() const +{ + const LLExtendedMeshParams *param_block = getExtendedMeshParams(); + if (param_block) + { + return param_block->getFlags(); + } + else + { + return 0; + } +} + +void LLVOVolume::onSetExtendedMeshFlags(U32 flags) +{ + + // The isAnySelected() check was needed at one point to prevent + // graphics problems. These are now believed to be fixed so the + // check has been disabled. + if (/*!getRootEdit()->isAnySelected() &&*/ mDrawable.notNull()) + { + // Need to trigger rebuildGeom(), which is where control avatars get created/removed + getRootEdit()->recursiveMarkForUpdate(TRUE); + } + if (isAttachment() && getAvatarAncestor()) + { + updateVisualComplexity(); + if (flags & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG) + { + // Making a rigged mesh into an animated object + getAvatarAncestor()->updateAttachmentOverrides(); + } + else + { + // Making an animated object into a rigged mesh + getAvatarAncestor()->updateAttachmentOverrides(); + } + } +} + +void LLVOVolume::setExtendedMeshFlags(U32 flags) +{ + U32 curr_flags = getExtendedMeshFlags(); + if (curr_flags != flags) + { + bool in_use = true; + setParameterEntryInUse(LLNetworkData::PARAMS_EXTENDED_MESH, in_use, true); + LLExtendedMeshParams *param_block = (LLExtendedMeshParams *)getExtendedMeshParams(); + if (param_block) + { + param_block->setFlags(flags); + } + parameterChanged(LLNetworkData::PARAMS_EXTENDED_MESH, true); + LL_DEBUGS("AnimatedObjects") << this + << " new flags " << flags << " curr_flags " << curr_flags + << ", calling onSetExtendedMeshFlags()" + << LL_ENDL; + onSetExtendedMeshFlags(flags); + } +} + +bool LLVOVolume::canBeAnimatedObject() const +{ + F32 est_tris = recursiveGetEstTrianglesMax(); + if (est_tris < 0 || est_tris > getAnimatedObjectMaxTris()) + { + return false; + } + return true; +} + +bool LLVOVolume::isAnimatedObject() const +{ + LLVOVolume *root_vol = (LLVOVolume*)getRootEdit(); + bool root_is_animated_flag = root_vol->getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; + return root_is_animated_flag; +} + +// Called any time parenting changes for a volume. Update flags and +// control av accordingly. This is called after parent has been +// changed to new_parent, but before new_parent's mChildList has changed. + +// virtual +void LLVOVolume::onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent) +{ + if (new_parent && !new_parent->isAvatar()) + { + if (mControlAvatar.notNull()) + { + // Here an animated object is being made the child of some + // other prim. Should remove the control av from the child. + LLControlAvatar *av = mControlAvatar; + mControlAvatar = NULL; + av->markForDeath(); + } + } + LLVOVolume *old_volp = old_parent ? old_parent->asVolume() : nullptr; + if (old_volp && old_volp->isAnimatedObject()) + { + if (old_volp->getControlAvatar()) + { + // We have been removed from an animated object, need to do cleanup. + old_volp->getControlAvatar()->updateAttachmentOverrides(); + old_volp->getControlAvatar()->updateAnimations(); + } + } +} + +// This needs to be called after onReparent(), because mChildList is +// not updated until the end of LLViewerObject::addChild() + +// virtual +void LLVOVolume::afterReparent() { - U8 path = getVolume()->getParams().getPathParams().getCurveType(); - return (path == LL_PCODE_PATH_FLEXIBLE || path == LL_PCODE_PATH_LINE); + { + LL_DEBUGS("AnimatedObjects") << "new child added for parent " + << ((LLViewerObject*)getParent())->getID() << LL_ENDL; + } + + if (isAnimatedObject() && getControlAvatar()) + { + LL_DEBUGS("AnimatedObjects") << "adding attachment overrides, parent is animated object " + << ((LLViewerObject*)getParent())->getID() << LL_ENDL; + + // MAINT-8239 - doing a full rebuild whenever parent is set + // makes the joint overrides load more robustly. In theory, + // addAttachmentOverrides should be sufficient, but in + // practice doing a full rebuild helps compensate for + // notifyMeshLoaded() not being called reliably enough. + + // was: getControlAvatar()->addAttachmentOverridesForObject(this); + //getControlAvatar()->rebuildAttachmentOverrides(); + getControlAvatar()->updateAnimations(); + } + else + { + LL_DEBUGS("AnimatedObjects") << "not adding overrides, parent: " + << ((LLViewerObject*)getParent())->getID() + << " isAnimated: " << isAnimatedObject() << " cav " + << getControlAvatar() << LL_ENDL; + } } -BOOL LLVOVolume::setIsFlexible(BOOL is_flexible) +//---------------------------------------------------------------------------- +static LLTrace::BlockTimerStatHandle FTM_VOVOL_RIGGING_INFO("VOVol Rigging Info"); + +void LLVOVolume::updateRiggingInfo() { - BOOL res = FALSE; - BOOL was_flexible = isFlexible(); - LLVolumeParams volume_params; - if (is_flexible) - { - if (!was_flexible) - { - volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); - res = TRUE; - setFlags(FLAGS_USE_PHYSICS, FALSE); - setFlags(FLAGS_PHANTOM, TRUE); - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); - if (mDrawable) - { - mDrawable->makeActive(); - } - } - } - else - { - if (was_flexible) - { - volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_LINE); - res = TRUE; - setFlags(FLAGS_PHANTOM, FALSE); - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true); - } - } - if (res) - { - res = setVolume(volume_params, 1); - if (res) - { - markForUpdate(TRUE); - } - } - return res; + LL_RECORD_BLOCK_TIME(FTM_VOVOL_RIGGING_INFO); + if (isRiggedMesh()) + { + const LLMeshSkinInfo* skin = getSkinInfo(); + LLVOAvatar *avatar = getAvatar(); + LLVolume *volume = getVolume(); + if (skin && avatar && volume) + { + LL_DEBUGS("RigSpammish") << "starting, vovol " << this << " lod " << getLOD() << " last " << mLastRiggingInfoLOD << LL_ENDL; + if (getLOD()>mLastRiggingInfoLOD || getLOD()==3) + { + // Rigging info may need update + mJointRiggingInfoTab.clear(); + for (S32 f = 0; f < volume->getNumVolumeFaces(); ++f) + { + LLVolumeFace& vol_face = volume->getVolumeFace(f); + LLSkinningUtil::updateRiggingInfo(skin, avatar, vol_face); + if (vol_face.mJointRiggingInfoTab.size()>0) + { + mJointRiggingInfoTab.merge(vol_face.mJointRiggingInfoTab); + } + } + // Keep the highest LOD info available. + mLastRiggingInfoLOD = getLOD(); + LL_DEBUGS("RigSpammish") << "updated rigging info for LLVOVolume " + << this << " lod " << mLastRiggingInfoLOD + << LL_ENDL; + } + } + } } //---------------------------------------------------------------------------- @@ -2975,7 +3607,7 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p //transform view vector into volume space view_vector -= getRenderPosition(); - mDrawable->mDistanceWRTCamera = view_vector.length(); + //mDrawable->mDistanceWRTCamera = view_vector.length(); LLQuaternion worldRot = getRenderRotation(); view_vector = view_vector * ~worldRot; if (!isVolumeGlobal()) @@ -3023,7 +3655,7 @@ void LLVOVolume::updateRadius() BOOL LLVOVolume::isAttachment() const { - return mState != 0 ; + return mAttachmentState != 0 ; } BOOL LLVOVolume::isHUDAttachment() const @@ -3031,7 +3663,7 @@ BOOL LLVOVolume::isHUDAttachment() const // *NOTE: we assume hud attachment points are in defined range // since this range is constant for backwards compatibility // reasons this is probably a reasonable assumption to make - S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mState); + S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mAttachmentState); return ( attachment_id >= 31 && attachment_id <= 38 ); } @@ -3104,16 +3736,25 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const path_params = volume_params.getPathParams(); profile_params = volume_params.getProfileParams(); - F32 weighted_triangles = -1.0; - getStreamingCost(NULL, NULL, &weighted_triangles); - - if (weighted_triangles > 0.0) + LLMeshCostData costs; + if (getCostData(costs)) { - num_triangles = (U32)(weighted_triangles); + if (isAnimatedObject() && isRiggedMesh()) + { + // Scaling here is to make animated object vs + // non-animated object ARC proportional to the + // corresponding calculations for streaming cost. + num_triangles = (ANIMATED_OBJECT_COST_PER_KTRI * 0.001 * costs.getEstTrisForStreamingCost())/0.06; + } + else + { + F32 radius = getScale().length()*0.5f; + num_triangles = costs.getRadiusWeightedTris(radius); + } } } - if (num_triangles == 0) + if (num_triangles <= 0) { num_triangles = 4; } @@ -3124,15 +3765,14 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const { // base cost is dependent on mesh complexity // note that 3 is the highest LOD as of the time of this coding. - S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(),3); + S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(), getLOD()); if ( size > 0) { - if (gMeshRepo.getSkinInfo(volume_params.getSculptID(), this)) + if (isRiggedMesh()) { // weighted attachment - 1 point for every 3 bytes weighted_mesh = 1; } - } else { @@ -3142,7 +3782,7 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const } else { - const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = getSculptParams(); LLUUID sculpt_id = sculpt_params->getSculptTexture(); if (textures.find(sculpt_id) == textures.end()) { @@ -3301,6 +3941,13 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const shame += media_faces * ARC_MEDIA_FACE_COST; } + // Streaming cost for animated objects includes a fixed cost + // per linkset. Add a corresponding charge here translated into + // triangles, but not weighted by any graphics properties. + if (isAnimatedObject() && isRootEdit()) + { + shame += (ANIMATED_OBJECT_BASE_COST/0.06) * 5.0f; + } if (shame > mRenderComplexity_current) { mRenderComplexity_current = (S32)shame; @@ -3309,15 +3956,65 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const return (U32)shame; } -F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_value) const +F32 LLVOVolume::getEstTrianglesMax() const +{ + if (isMesh() && getVolume()) + { + return gMeshRepo.getEstTrianglesMax(getVolume()->getParams().getSculptID()); + } + return 0.f; +} + +F32 LLVOVolume::getEstTrianglesStreamingCost() const +{ + if (isMesh() && getVolume()) + { + return gMeshRepo.getEstTrianglesStreamingCost(getVolume()->getParams().getSculptID()); + } + return 0.f; +} + +F32 LLVOVolume::getStreamingCost() const { F32 radius = getScale().length()*0.5f; + F32 linkset_base_cost = 0.f; - if (isMesh()) - { - LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID()); + LLMeshCostData costs; + if (getCostData(costs)) + { + if (isAnimatedObject() && isRootEdit()) + { + // Root object of an animated object has this to account for skeleton overhead. + linkset_base_cost = ANIMATED_OBJECT_BASE_COST; + } + if (isMesh()) + { + if (isAnimatedObject() && isRiggedMesh()) + { + return linkset_base_cost + costs.getTriangleBasedStreamingCost(); + } + else + { + return linkset_base_cost + costs.getRadiusBasedStreamingCost(radius); + } + } + else + { + return linkset_base_cost + costs.getRadiusBasedStreamingCost(radius); + } + } + else + { + return 0.f; + } +} - return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD, unscaled_value); +// virtual +bool LLVOVolume::getCostData(LLMeshCostData& costs) const +{ + if (isMesh()) + { + return gMeshRepo.getCostData(getVolume()->getParams().getSculptID(), costs); } else { @@ -3331,8 +4028,8 @@ F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_v header["medium_lod"]["size"] = counts[2] * 10; header["high_lod"]["size"] = counts[3] * 10; - return LLMeshRepository::getStreamingCost(header, radius, NULL, NULL, -1, unscaled_value); - } + return LLMeshRepository::getCostData(header, costs); + } } //static @@ -3402,6 +4099,21 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u { mVolumeImpl->onParameterChanged(param_type, data, in_use, local_origin); } + if (!local_origin && param_type == LLNetworkData::PARAMS_EXTENDED_MESH) + { + U32 extended_mesh_flags = getExtendedMeshFlags(); + bool enabled = (extended_mesh_flags & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG); + bool was_enabled = (getControlAvatar() != NULL); + if (enabled != was_enabled) + { + LL_DEBUGS("AnimatedObjects") << this + << " calling onSetExtendedMeshFlags, enabled " << (U32) enabled + << " was_enabled " << (U32) was_enabled + << " local_origin " << (U32) local_origin + << LL_ENDL; + onSetExtendedMeshFlags(extended_mesh_flags); + } + } if (mDrawable.notNull()) { BOOL is_light = getIsLight(); @@ -3415,10 +4127,17 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u void LLVOVolume::setSelected(BOOL sel) { LLViewerObject::setSelected(sel); - if (mDrawable.notNull()) - { - markForUpdate(TRUE); - } + if (isAnimatedObject()) + { + getRootEdit()->recursiveMarkForUpdate(TRUE); + } + else + { + if (mDrawable.notNull()) + { + markForUpdate(TRUE); + } + } } void LLVOVolume::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) @@ -3481,7 +4200,12 @@ F32 LLVOVolume::getBinRadius() } else if (mDrawable->isStatic()) { - radius = llmax((S32) mDrawable->getRadius(), 1)*size_factor; + F32 szf = size_factor; + + radius = llmax(mDrawable->getRadius(), szf); + + radius = powf(radius, 1.f+szf/radius); + radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1]; radius += mDrawable->mDistanceWRTCamera * distance_factor[0]; } @@ -3527,6 +4251,12 @@ const LLMatrix4a& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const return xform->getWorldMatrix(); } +void LLVOVolume::markForUpdate(BOOL priority) +{ + LLViewerObject::markForUpdate(priority); + mVolumeChanged = TRUE; +} + LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const { LLVector3 ret = pos - getRenderPosition(); @@ -3577,8 +4307,7 @@ LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const return ret; } - -BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, S32 *face_hitp, +BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { @@ -3604,16 +4333,14 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& if (mDrawable->isState(LLDrawable::RIGGED)) { - static const LLCachedControl allow_mesh_picking("SGAllowRiggedMeshSelection"); - if (allow_mesh_picking && (gFloaterTools->getVisible() || LLFloaterInspect::findInstance())) + if (pick_rigged) { - updateRiggedVolume(); - //genBBoxes(FALSE); + updateRiggedVolume(true); volume = mRiggedVolume; transform = false; } else - { //cannot pick rigged attachments on other avatars or when not in build mode + { return FALSE; } } @@ -3787,8 +4514,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& bool LLVOVolume::treatAsRigged() { - return (gFloaterTools->getVisible() || LLFloaterInspect::findInstance()) && - isAttachment() && + return isSelected() && + (isAttachment() || isAnimatedObject()) && mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED); } @@ -3807,12 +4534,12 @@ void LLVOVolume::clearRiggedVolume() } } -void LLVOVolume::updateRiggedVolume() +void LLVOVolume::updateRiggedVolume(bool force_update) { //Update mRiggedVolume to match current animation frame of avatar. //Also update position/size in octree. - if (!treatAsRigged()) + if ((!force_update) && (!treatAsRigged())) { clearRiggedVolume(); @@ -3820,9 +4547,7 @@ void LLVOVolume::updateRiggedVolume() } LLVolume* volume = getVolume(); - - const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID(), this); - + const LLMeshSkinInfo* skin = getSkinInfo(); if (!skin) { clearRiggedVolume(); @@ -3848,8 +4573,8 @@ void LLVOVolume::updateRiggedVolume() } -static LLFastTimer::DeclareTimer FTM_SKIN_RIGGED("Skin"); -static LLFastTimer::DeclareTimer FTM_RIGGED_OCTREE("Octree"); +static LLTrace::BlockTimerStatHandle FTM_SKIN_RIGGED("Skin"); +static LLTrace::BlockTimerStatHandle FTM_RIGGED_OCTREE("Octree"); void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume) { @@ -3871,32 +4596,34 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons } } + U64 frame = LLFrameTimer::getFrameCount(); if (copy) { copyVolumeFaces(volume); } + else if (avatar && avatar->areAnimationsPaused()) + { + frame = avatar->getMotionController().getPausedFrame(); + } + if (frame == mFrame) + { + return; + } + mFrame = frame; //build matrix palette - LLMatrix4a mp[JOINT_COUNT]; + static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT; - U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT); + LLMatrix4a mat[kMaxJoints]; + U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin); + LLSkinningUtil::initSkinningMatrixPalette(mat, maxJoints, skin, avatar, true); - llassert_always(count); + + LLMatrix4a bind_shape_matrix; + bind_shape_matrix.loadu(skin->mBindShapeMatrix); - for (U32 j = 0; j < count; ++j) - { - LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); - if(!joint) - { - joint = avatar->getJoint("mRoot"); - } - if (joint) - { - LLMatrix4a mat; - mat.loadu((F32*)skin->mInvBindMatrix[j].mMatrix); - mp[j].setMul(joint->getWorldMatrix(), mat); - } - } + LLVector4a av_pos; + av_pos.load3(avatar->getPosition().mV); for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) { @@ -3910,59 +4637,27 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons { continue; } - - LLMatrix4a bind_shape_matrix; - bind_shape_matrix.loadu(skin->mBindShapeMatrix); + LLSkinningUtil::checkSkinWeights(weight, dst_face.mNumVertices, skin); LLVector4a* pos = dst_face.mPositions; if( pos && dst_face.mExtents ) { - LLFastTimer t(FTM_SKIN_RIGGED); + LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED); + U32 max_joints = LLSkinningUtil::getMaxJointCount(); for (U32 j = 0; j < (U32)dst_face.mNumVertices; ++j) { LLMatrix4a final_mat; - final_mat.clear(); - - S32 idx[4]; - - LLVector4 wght; - - F32 scale = 0.f; - for (U32 k = 0; k < 4; k++) - { - F32 w = weight[j][k]; - - const F32 w_floor = floorf(w); - idx[k] = (S32) w_floor; - wght[k] = w - w_floor; - scale += wght[k]; - } - - if(scale > 0.f) - wght *= 1.f/scale; - else - wght = LLVector4(F32_MAX,F32_MAX,F32_MAX,F32_MAX); - - for (U32 k = 0; k < 4; k++) - { - F32 w = wght[k]; - - LLMatrix4a src; - // clamp k to kMaxJoints to avoid reading garbage off stack in release - src.setMul(mp[(idx[k] < count) ? idx[k] : 0], w); - - final_mat.add(src); - } - + LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; - LLVector4a dst; bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; + final_mat.affineTransform(t, pos[j]); + + pos[j].add(av_pos); // Algorithm tweaked to stop hosing up normals. } //update bounding box @@ -3984,7 +4679,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons } { - LLFastTimer t(FTM_RIGGED_OCTREE); + LL_RECORD_BLOCK_TIME(FTM_RIGGED_OCTREE); delete dst_face.mOctree; dst_face.mOctree = NULL; @@ -4011,8 +4706,9 @@ U32 LLVOVolume::getPartitionType() const return LLViewerRegion::PARTITION_VOLUME; } -LLVolumePartition::LLVolumePartition() -: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB) +LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp) +: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp), +LLVolumeGeometryManager() { mLODPeriod = 32; mDepthMask = FALSE; @@ -4022,8 +4718,9 @@ LLVolumePartition::LLVolumePartition() mBufferUsage = GL_DYNAMIC_DRAW_ARB; } -LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) -: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK) +LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, LLViewerRegion* regionp) +: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp), +LLVolumeGeometryManager() { mDepthMask = FALSE; mLODPeriod = 32; @@ -4035,8 +4732,8 @@ LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) mSlopRatio = 0.25f; } -LLAttachmentBridge::LLAttachmentBridge(LLDrawable* drawablep) - : LLVolumeBridge(drawablep) +LLAttachmentBridge::LLAttachmentBridge(LLDrawable* drawablep, LLViewerRegion* regionp) + : LLVolumeBridge(drawablep, regionp) { mPartitionType = LLViewerRegion::PARTITION_ATTACHMENT; } @@ -4057,11 +4754,6 @@ bool can_batch_texture(const LLFace* facep) return false; } - if (facep->getTexture() && facep->getTexture()->getPrimaryFormat() == GL_ALPHA) - { //can't batch invisiprims - return false; - } - if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) { //texture animation breaks batches return false; @@ -4080,11 +4772,6 @@ bool can_batch_texture(const LLFace* facep) return false; } - if (facep->getPoolType() != LLDrawPool::POOL_ALPHA && facep->getTexture() && facep->getTexture()->getPrimaryFormat() == GL_ALPHA) - { //can't batch invisiprims - return false; - } - if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) { //texture animation breaks batches return false; @@ -4094,11 +4781,75 @@ bool can_batch_texture(const LLFace* facep) return true; } -static LLFastTimer::DeclareTimer FTM_REGISTER_FACE("Register Face"); +const static U32 MAX_FACE_COUNT = 4096U; +int32_t LLVolumeGeometryManager::sInstanceCount = 0; +LLFace** LLVolumeGeometryManager::sFullbrightFaces = NULL; +LLFace** LLVolumeGeometryManager::sBumpFaces = NULL; +LLFace** LLVolumeGeometryManager::sSimpleFaces = NULL; +LLFace** LLVolumeGeometryManager::sNormFaces = NULL; +LLFace** LLVolumeGeometryManager::sSpecFaces = NULL; +LLFace** LLVolumeGeometryManager::sNormSpecFaces = NULL; +LLFace** LLVolumeGeometryManager::sAlphaFaces = NULL; + +LLVolumeGeometryManager::LLVolumeGeometryManager() + : LLGeometryManager() +{ + llassert(sInstanceCount >= 0); + if (sInstanceCount == 0) + { + allocateFaces(MAX_FACE_COUNT); + } + + ++sInstanceCount; +} + +LLVolumeGeometryManager::~LLVolumeGeometryManager() +{ + llassert(sInstanceCount > 0); + --sInstanceCount; + + if (sInstanceCount <= 0) + { + freeFaces(); + sInstanceCount = 0; + } +} + +void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount) +{ + sFullbrightFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sBumpFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sSimpleFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sNormFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sNormSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sAlphaFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); +} + +void LLVolumeGeometryManager::freeFaces() +{ + ll_aligned_free<64>(sFullbrightFaces); + ll_aligned_free<64>(sBumpFaces); + ll_aligned_free<64>(sSimpleFaces); + ll_aligned_free<64>(sNormFaces); + ll_aligned_free<64>(sSpecFaces); + ll_aligned_free<64>(sNormSpecFaces); + ll_aligned_free<64>(sAlphaFaces); + + sFullbrightFaces = NULL; + sBumpFaces = NULL; + sSimpleFaces = NULL; + sNormFaces = NULL; + sSpecFaces = NULL; + sNormSpecFaces = NULL; + sAlphaFaces = NULL; +} + +static LLTrace::BlockTimerStatHandle FTM_REGISTER_FACE("Register Face"); void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { - LLFastTimer t(FTM_REGISTER_FACE); + LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE); //if (type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT)) //{ // LL_WARNS("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; @@ -4118,7 +4869,6 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, if(!facep->mShinyInAlpha) facep->mShinyInAlpha = (type == LLRenderPass::PASS_FULLBRIGHT_SHINY) || - (type == LLRenderPass::PASS_INVISI_SHINY) || (type == LLRenderPass::PASS_SHINY) || (LLPipeline::sRenderDeferred && type == LLRenderPass::PASS_BUMP) || (LLPipeline::sRenderDeferred && type == LLRenderPass::PASS_SIMPLE); @@ -4133,7 +4883,6 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, if(!alt_batching) { fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) || - (type == LLRenderPass::PASS_INVISIBLE) || (type == LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK) || (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)) || (facep->getTextureEntry()->getFullbright()); @@ -4315,7 +5064,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f); specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f); specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f); - specColor.mV[3] = llmax(0.0001f, mat->getSpecularLightExponent() * (1.f / 255.f)); + specColor.mV[3] = llmax(0.0000f, mat->getSpecularLightExponent() * (1.f / 255.f)); draw_info->mSpecColor = specColor; draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f); draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset()); @@ -4360,9 +5109,9 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) } -static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume VB"); -static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_FACE_LIST("Build Face List"); -static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_GEN_DRAW_INFO("Gen Draw Info"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_VB("Volume VB"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_FACE_LIST("Build Face List"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_GEN_DRAW_INFO("Gen Draw Info"); static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) { @@ -4391,6 +5140,81 @@ static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) return NULL; } +void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value) +{ + static LLCachedControl render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U); + + if (0 != render_auto_mute_byte_limit) + { + //for unload + LLSculptIDSize::container_BY_SIZE_view::iterator + itL = LLSculptIDSize::instance().getSizeInfo().get().lower_bound(render_auto_mute_byte_limit), + itU = LLSculptIDSize::instance().getSizeInfo().get().end(); + + for (; itL != itU; ++itL) + { + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD != pVVol->getLOD() + ) + { + //postponed + pVVol->markForUnload(); + LLSculptIDSize::instance().addToUnloaded(nfo.getSculptId()); + } + } + + //for load if it was unload + itL = LLSculptIDSize::instance().getSizeInfo().get().begin(); + itU = LLSculptIDSize::instance().getSizeInfo().get().upper_bound(render_auto_mute_byte_limit); + + for (; itL != itU; ++itL) + { + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD == pVVol->getLOD() + ) + { + LLSculptIDSize::instance().remFromUnloaded(nfo.getSculptId()); + pVVol->updateLOD(); + pVVol->markForUpdate(TRUE); + } + } + } + else + { + LLSculptIDSize::instance().clearUnloaded(); + + LLSculptIDSize::container_BY_SIZE_view::iterator + itL = LLSculptIDSize::instance().getSizeInfo().get().begin(), + itU = LLSculptIDSize::instance().getSizeInfo().get().end(); + + for (; itL != itU; ++itL) + { + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD == pVVol->getLOD() + ) + { + pVVol->updateLOD(); + pVVol->markForUpdate(TRUE); + } + } + } +} + void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (LLPipeline::sSkipUpdate) @@ -4414,52 +5238,34 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) return; } - LLFastTimer ftm(FTM_REBUILD_VOLUME_VB); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); group->mBuilt = 1.f; - LLVOAvatar* pAvatarVO = NULL; - LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); - if (bridge) - { - if (bridge->mAvatar.isNull()) - { - LLViewerObject* vobj = bridge->mDrawable->getVObj(); - if (vobj) - { - bridge->mAvatar = vobj->getAvatar(); - } - } - - pAvatarVO = bridge->mAvatar; - } + LLViewerObject *vobj = NULL; + LLVOVolume *vol_obj = NULL; - if (pAvatarVO) + if (bridge) { - pAvatarVO->mAttachmentGeometryBytes -= group->mGeometryBytes; - pAvatarVO->mAttachmentSurfaceArea -= group->mSurfaceArea; + vobj = bridge->mDrawable->getVObj(); + vol_obj = vobj ? vobj->asVolume() : nullptr; } + if (vol_obj) + { + vol_obj->updateVisualComplexity(); + } group->mGeometryBytes = 0; group->mSurfaceArea = 0; //cache object box size since it might be used for determining visibility - group->mObjectBoxSize = group->getObjectBounds()[1].getLength3().getF32(); + const LLVector4a* bounds = group->getObjectBounds(); + group->mObjectBoxSize = bounds[1].getLength3().getF32(); group->clearDrawMap(); mFaceList.clear(); - - const U32 MAX_FACE_COUNT = 4096; - - static LLFace** fullbright_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); - static LLFace** bump_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); - static LLFace** simple_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); - static LLFace** norm_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64); - static LLFace** spec_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64); - static LLFace** normspec_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64); - static LLFace** alpha_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); U32 fullbright_count = 0; U32 bump_count = 0; @@ -4482,7 +5288,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) bool emissive = false; { - LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_FACE_LIST); //get all the faces into a list OctreeGuard guard(group->getOctreeNode()); @@ -4490,7 +5296,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) + if (!drawablep || drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) { continue; } @@ -4520,17 +5326,28 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); } + vobj->updateControlAvatar(); llassert_always(vobj); vobj->updateTextureVirtualSize(true); vobj->preRebuild(); drawablep->clearState(LLDrawable::HAS_ALPHA); - bool rigged = vobj->isAttachment() && - vobj->isMesh() && - gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); - - bool is_rigged = false; + if (vobj->isRiggedMesh() && + ((vobj->isAnimatedObject() && vobj->getControlAvatar()) || + (!vobj->isAnimatedObject() && vobj->getAvatar()))) + { + vobj->getAvatar()->addAttachmentOverridesForObject(vobj, NULL, false); + } + + // Standard rigged mesh attachments: + bool rigged = !vobj->isAnimatedObject() && vobj->isRiggedMesh() && 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); + + bool any_rigged_face = false; static const LLCachedControl alt_batching("SHAltBatching",true); @@ -4560,65 +5377,17 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } facep->setState(LLFace::RIGGED); - is_rigged = true; + any_rigged_face = true; //get drawpool of avatar with rigged face LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); - - //Determine if we've received skininfo that contains an - //alternate bind matrix - if it does then apply the translational component - //to the joints of the avatar. - bool pelvisGotSet = false; - - if ( pAvatarVO ) - { - LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); - const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); - if ( pSkinData ) - { - const int bindCnt = pSkinData->mAlternateBindMatrix.size(); - if ( bindCnt > 0 ) - { - const int jointCnt = pSkinData->mJointNames.size(); - const F32 pelvisZOffset = pSkinData->mPelvisOffset; - bool fullRig = (jointCnt>=20) ? true : false; - if ( fullRig ) - { - for ( int i=0; imJointNames[i].c_str(); - //LL_INFOS() <<"joint name "<getJoint( lookingForJoint ); - if ( pJoint && pJoint->getId() != currentId ) - { - pJoint->setId( currentId ); - const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); - //Set the joint position - pJoint->storeCurrentXform( jointPos ); - //If joint is a pelvis then handle old/new pelvis to foot values - if ( lookingForJoint == "mPelvis" ) - { - pJoint->storeCurrentXform( jointPos ); - if ( !pAvatarVO->hasPelvisOffset() ) - { - pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); - //Trigger to rebuild viewer AV - pelvisGotSet = true; - } - } - } - } - } - } - } - } - //If we've set the pelvis to a new position we need to also rebuild some information that the - //viewer does at launch (e.g. body size etc.) - if ( pelvisGotSet ) + // FIXME should this be inside the face loop? + // doesn't seem to depend on any per-face state. + /*if ( pAvatarVO ) { - pAvatarVO->postPelvisSetRecalc(); - } + pAvatarVO->addAttachmentOverridesForObject(vobj); + }*/ if (pool) { @@ -4765,9 +5534,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if(te->getColor().mV[3] > 0.f) { U32 mask = te->getFullbright() ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA; - if (mat && LLPipeline::sRenderDeferred && te->getColor().mV[3] >= 0.999f ) + if (mat && LLPipeline::sRenderDeferred) { - if(mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND) + if(te->getColor().mV[3] < 0.999f || mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND) mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND); else mask = mat->getShaderMask(); @@ -4800,15 +5569,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) else { - if( type == LLDrawPool::POOL_FULLBRIGHT || type == LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } //Annoying exception to the rule. getPoolTypeFromTE will return POOL_ALPHA_MASK for legacy bumpmaps, but there is no POOL_ALPHA_MASK in deferred. - else if(type == LLDrawPool::POOL_MATERIALS || (type == LLDrawPool::POOL_ALPHA_MASK && mat)) + if (type == LLDrawPool::POOL_MATERIALS || ((type == LLDrawPool::POOL_ALPHA_MASK || type == LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK) && mat)) { pool->addRiggedFace(facep, mat->getShaderMask()); } + else if (type == LLDrawPool::POOL_FULLBRIGHT || type == LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); + } else if (type == LLDrawPool::POOL_BUMP && te->getBumpmap()) { pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); @@ -4895,12 +5664,17 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } else if (force_fullbright) //Hud is done in a forward render. Fullbright cannot be shared with simple. { - if(type == LLDrawPool::POOL_ALPHA_MASK) + LLMaterial* mat = te->getMaterialParams().get(); + if (type == LLDrawPool::POOL_ALPHA_MASK || (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK ) ) + { type = LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK; + } else + { type = LLDrawPool::POOL_FULLBRIGHT; + } } - else if(force_simple && type != LLDrawPool::POOL_FULLBRIGHT && type != LLDrawPool::POOL_ALPHA_MASK && type != LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK) + else if(force_simple && type != LLDrawPool::POOL_FULLBRIGHT && (!LLPipeline::sRenderDeferred && (type != LLDrawPool::POOL_ALPHA_MASK && type != LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK))) { type = LLDrawPool::POOL_SIMPLE; } @@ -4954,7 +5728,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //can be treated as alpha mask if (simple_count < MAX_FACE_COUNT) { - simple_faces[simple_count++] = facep; + sSimpleFaces[simple_count++] = facep; } } else @@ -4965,7 +5739,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } if (alpha_count < MAX_FACE_COUNT) { - alpha_faces[alpha_count++] = facep; + sAlphaFaces[alpha_count++] = facep; } } } @@ -4990,14 +5764,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) if (normspec_count < MAX_FACE_COUNT) { - normspec_faces[normspec_count++] = facep; + sNormSpecFaces[normspec_count++] = facep; } } else { //has normal map (needs texcoord1 and tangent) if (norm_count < MAX_FACE_COUNT) { - norm_faces[norm_count++] = facep; + sNormFaces[norm_count++] = facep; } } } @@ -5005,14 +5779,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //has specular map but no normal map, needs texcoord2 if (spec_count < MAX_FACE_COUNT) { - spec_faces[spec_count++] = facep; + sSpecFaces[spec_count++] = facep; } } else { //has neither specular map nor normal map, only needs texcoord0 if (simple_count < MAX_FACE_COUNT) { - simple_faces[simple_count++] = facep; + sSimpleFaces[simple_count++] = facep; } } } @@ -5020,14 +5794,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //needs normal + tangent if (bump_count < MAX_FACE_COUNT) { - bump_faces[bump_count++] = facep; + sBumpFaces[bump_count++] = facep; } } else if (te->getShiny() || !te->getFullbright()) { //needs normal if (simple_count < MAX_FACE_COUNT) { - simple_faces[simple_count++] = facep; + sSimpleFaces[simple_count++] = facep; } } else @@ -5035,7 +5809,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) facep->setState(LLFace::FULLBRIGHT); if (fullbright_count < MAX_FACE_COUNT) { - fullbright_faces[fullbright_count++] = facep; + sFullbrightFaces[fullbright_count++] = facep; } } } @@ -5045,7 +5819,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //needs normal + tangent if (bump_count < MAX_FACE_COUNT) { - bump_faces[bump_count++] = facep; + sBumpFaces[bump_count++] = facep; } } else if ((te->getShiny() && LLPipeline::sRenderBump) || @@ -5053,7 +5827,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //needs normal if (simple_count < MAX_FACE_COUNT) { - simple_faces[simple_count++] = facep; + sSimpleFaces[simple_count++] = facep; } } else @@ -5061,7 +5835,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) facep->setState(LLFace::FULLBRIGHT); if (fullbright_count < MAX_FACE_COUNT) { - fullbright_faces[fullbright_count++] = facep; + sFullbrightFaces[fullbright_count++] = facep; } } } @@ -5074,7 +5848,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (type == LLDrawPool::POOL_ALPHA) { - cur_type = &alpha_faces; + cur_type = &sAlphaFaces; cur_count = &alpha_count; if (te->getColor().mV[3] > 0.f) @@ -5089,30 +5863,30 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (mat->getSpecularID().notNull()) { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) - cur_type = &normspec_faces; + cur_type = &sNormSpecFaces; cur_count = &normspec_count; } else { //has normal map (needs texcoord1 and tangent) - cur_type = &norm_faces; + cur_type = &sNormFaces; cur_count = &norm_count; } } else if (mat->getSpecularID().notNull()) { //has specular map but no normal map, needs texcoord2 - cur_type = &spec_faces; + cur_type = &sSpecFaces; cur_count = &spec_count; } } } else if(type == LLDrawPool::POOL_ALPHA_MASK) { - cur_type = &simple_faces; + cur_type = &sSimpleFaces; cur_count = &simple_count; } else if(type == LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK) { - cur_type = &fullbright_faces; + cur_type = &sFullbrightFaces; cur_count = &fullbright_count; } else @@ -5126,30 +5900,30 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //needs normal + tangent if(te->getBumpmap() > 0 && te->getBumpmap() < 18) { - cur_type = &bump_faces; + cur_type = &sBumpFaces; cur_count = &bump_count; } else if(te->getShiny()) { - cur_type = &simple_faces; + cur_type = &sSimpleFaces; cur_count = &simple_count; } } else if (type == LLDrawPool::POOL_SIMPLE) { //needs normal + tangent - cur_type = &simple_faces; + cur_type = &sSimpleFaces; cur_count = &simple_count; } else if (type == LLDrawPool::POOL_FULLBRIGHT) { //doesn't need normal... if(LLPipeline::sRenderBump && te->getShiny()) //unless it's shiny.. { - cur_type = &simple_faces; + cur_type = &sSimpleFaces; cur_count = &simple_count; } else { - cur_type = &fullbright_faces; + cur_type = &sFullbrightFaces; cur_count = &fullbright_count; } } @@ -5163,23 +5937,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (mat->getSpecularID().notNull()) { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) - cur_type = &normspec_faces; + cur_type = &sNormSpecFaces; cur_count = &normspec_count; } else { //has normal map (needs texcoord1 and tangent) - cur_type = &norm_faces; + cur_type = &sNormFaces; cur_count = &norm_count; } } else if (mat->getSpecularID().notNull()) { //has specular map but no normal map, needs texcoord2 - cur_type = &spec_faces; + cur_type = &sSpecFaces; cur_count = &spec_count; } else { //has neither specular map nor normal map, only needs texcoord0 - cur_type = &simple_faces; + cur_type = &sSimpleFaces; cur_count = &simple_count; } } @@ -5199,7 +5973,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } } - if (is_rigged) + if (any_rigged_face) { if (!drawablep->isState(LLDrawable::RIGGED)) { @@ -5213,6 +5987,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) else { drawablep->clearState(LLDrawable::RIGGED); + vobj->updateRiggedVolume(); } } } @@ -5241,13 +6016,13 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if(emissive) additional_flags |= LLVertexBuffer::MAP_EMISSIVE; - genDrawInfo(group, simple_mask | additional_flags, simple_faces, simple_count, FALSE, batch_textures); - genDrawInfo(group, fullbright_mask | additional_flags, fullbright_faces, fullbright_count, FALSE, batch_textures); - genDrawInfo(group, alpha_mask | additional_flags, alpha_faces, alpha_count, TRUE, batch_textures); - genDrawInfo(group, bump_mask | additional_flags, bump_faces, bump_count, FALSE); - genDrawInfo(group, norm_mask | additional_flags, norm_faces, norm_count, FALSE); - genDrawInfo(group, spec_mask | additional_flags, spec_faces, spec_count, FALSE); - genDrawInfo(group, normspec_mask | additional_flags, normspec_faces, normspec_count, FALSE); + genDrawInfo(group, simple_mask | additional_flags, sSimpleFaces, simple_count, FALSE, batch_textures); + genDrawInfo(group, fullbright_mask | additional_flags, sFullbrightFaces, fullbright_count, FALSE, batch_textures); + genDrawInfo(group, alpha_mask | additional_flags, sAlphaFaces, alpha_count, TRUE, batch_textures); + genDrawInfo(group, bump_mask | additional_flags, sBumpFaces, bump_count, FALSE); + genDrawInfo(group, norm_mask | additional_flags, sNormFaces, norm_count, FALSE); + genDrawInfo(group, spec_mask | additional_flags, sSpecFaces, spec_count, FALSE); + genDrawInfo(group, normspec_mask | additional_flags, sNormSpecFaces, normspec_count, FALSE); if (!LLPipeline::sDelayVBUpdate) { @@ -5270,12 +6045,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } mFaceList.clear(); - - if (pAvatarVO) - { - pAvatarVO->mAttachmentGeometryBytes += group->mGeometryBytes; - pAvatarVO->mAttachmentSurfaceArea += group->mSurfaceArea; - } } @@ -5285,8 +6054,8 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) static int warningsCount = 20; if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY)) { - LLFastTimer ftm(FTM_REBUILD_VOLUME_VB); - LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers group->mBuilt = 1.f; @@ -5302,9 +6071,11 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) + if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) { LLVOVolume* vobj = drawablep->getVOVolume(); + if (vobj->isNoLOD()) continue; + vobj->preRebuild(); if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) @@ -5374,6 +6145,10 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + if(!drawablep) + { + continue; + } for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { LLFace* face = drawablep->getFace(i); @@ -5472,11 +6247,11 @@ struct CompareBatchBreakerModified } }; -static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_SORT("Draw Info Face Sort"); -static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_FACE_SIZE("Face Sizing"); -static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_ALLOCATE("Allocate VB"); -static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_FIND_VB("Find VB"); -static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); +static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_SORT("Draw Info Face Sort"); +static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_FACE_SIZE("Face Sizing"); +static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_ALLOCATE("Allocate VB"); +static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_FIND_VB("Find VB"); +static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); @@ -5484,7 +6259,7 @@ static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures) { - LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); U32 buffer_usage = group->mBufferUsage; @@ -5505,7 +6280,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac max_vertices = llmin(max_vertices, (U32) 65535); { - LLFastTimer t(FTM_GEN_DRAW_INFO_SORT); + LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_SORT); if (!distance_sort) { //sort faces by things that break batches @@ -5522,7 +6297,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac LLFace** face_iter = faces; LLFace** end_faces = faces+face_count; - LLSpatialGroup::buffer_map_t buffer_map; + LLSpatialGroup::buffer_vec_t buffer_vec; S32 texture_index_channels = llmax(LLGLSLShader::sIndexedTextureChannels-1,1); //always reserve one for shiny for now just for simplicity @@ -5563,7 +6338,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac U32 texture_count = 0; { - LLFastTimer t(FTM_GEN_DRAW_INFO_FACE_SIZE); + LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_FACE_SIZE); if (batch_textures) { U8 cur_tex = 0; @@ -5676,7 +6451,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac } else { - LLFastTimer t(FTM_GEN_DRAW_INFO_FACE_SIZE); + LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_FACE_SIZE); if (batch_textures) { @@ -5809,15 +6584,14 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac LLVertexBuffer* buffer = NULL; { - LLFastTimer t(FTM_GEN_DRAW_INFO_ALLOCATE); + LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_ALLOCATE); buffer = createVertexBuffer(mask, buffer_usage); buffer->allocateBuffer(geom_count, index_count, TRUE); } group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize(); - - buffer_map[mask][*face_iter].push_back(buffer); + get_val_in_pair_vec(get_val_in_pair_vec(buffer_vec, mask),*face_iter).push_back(buffer); //add face geometry @@ -5965,7 +6739,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac if (material_pass) { - U32 pass[] = + static const U32 pass[] = { LLRenderPass::PASS_MATERIAL, LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_MATERIAL_ALPHA, @@ -6050,12 +6824,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac && te->getShiny() && can_be_shiny) { //shiny - if (tex->getPrimaryFormat() == GL_ALPHA) - { //invisiprim+shiny - registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (LLPipeline::sRenderDeferred && !hud_group) + if (LLPipeline::sRenderDeferred && !hud_group) { //deferred rendering if (te->getFullbright()) { //register in post deferred fullbright shiny pass @@ -6086,11 +6855,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac } else { //not alpha and not shiny - if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) - { //invisiprim - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (fullbright) + if (fullbright) { //fullbright if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) { @@ -6213,15 +6978,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac } else { - if (tex->getPrimaryFormat() == GL_ALPHA) - { - if(is_shiny_shader && facep->getPoolType() == LLDrawPool::POOL_BUMP) - { - registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); - } - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (facep->getPoolType() == LLDrawPool::POOL_SIMPLE) + if (facep->getPoolType() == LLDrawPool::POOL_SIMPLE) { registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } @@ -6328,10 +7085,12 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac buffer->flush(); } - group->mBufferMap[mask].clear(); - for (LLSpatialGroup::buffer_texture_map_t::iterator i = buffer_map[mask].begin(); i != buffer_map[mask].end(); ++i) + auto buffVec = get_val_in_pair_vec(group->mBufferVec, mask); + buffVec.clear(); + auto map = get_val_in_pair_vec(buffer_vec, mask); + for (LLSpatialGroup::buffer_texture_vec_t::iterator i = map.begin(); i != map.end(); ++i) { - group->mBufferMap[mask][i->first] = i->second; + get_val_in_pair_vec(buffVec, i->first) = i->second; } } @@ -6388,7 +7147,8 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun group->mBufferUsage = usage; } -LLHUDPartition::LLHUDPartition() +LLHUDPartition::LLHUDPartition(LLViewerRegion* regionp) + : LLBridgePartition(regionp) { mPartitionType = LLViewerRegion::PARTITION_HUD; mDrawableType = LLPipeline::RENDER_TYPE_HUD; diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index e70a6a64d6..db91548e8b 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -61,9 +61,10 @@ enum LLVolumeInterfaceType class LLRiggedVolume : public LLVolume { + U64 mFrame; public: LLRiggedVolume(const LLVolumeParams& params) - : LLVolume(params, 0.f) + : LLVolume(params, 0.f), mFrame(-1) { } @@ -93,7 +94,7 @@ class LLVolumeInterface }; // Class which embodies all Volume objects (with pcode LL_PCODE_VOLUME) -class LLVOVolume : public LLViewerObject +class LLVOVolume final : public LLViewerObject { LOG_CLASS(LLVOVolume); protected: @@ -125,7 +126,9 @@ class LLVOVolume : public LLViewerObject public: LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); - /*virtual*/ void markDead(); // Override (and call through to parent) to clean up media references + + LLVOVolume* asVolume() final; + /*virtual*/ void markDead() override; // Override (and call through to parent) to clean up media references /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); @@ -142,19 +145,25 @@ class LLVOVolume : public LLViewerObject void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point); /*virtual*/ BOOL setParent(LLViewerObject* parent); S32 getLOD() const { return mLOD; } + void setNoLOD() { mLOD = NO_LOD; mLODChanged = TRUE; } + bool isNoLOD() const { return NO_LOD == mLOD; } const LLVector3 getPivotPositionAgent() const; const LLMatrix4a& getRelativeXform() const { return mRelativeXform; } const LLMatrix4a& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; } /*virtual*/ const LLMatrix4a& getRenderMatrix() const; typedef std::map texture_cost_t; U32 getRenderCost(texture_cost_t &textures) const; - /*virtual*/ F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL, F32* unscaled_value = NULL) const; + /*virtual*/ F32 getEstTrianglesMax() const; + /*virtual*/ F32 getEstTrianglesStreamingCost() const; + /* virtual*/ F32 getStreamingCost() const; + /*virtual*/ bool getCostData(LLMeshCostData& costs) const; /*virtual*/ U32 getTriangleCount(S32* vcount = NULL) const; /*virtual*/ U32 getHighLODTriangleCount(); /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, S32* face_hit = NULL, // which face was hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point @@ -173,8 +182,9 @@ class LLVOVolume : public LLViewerObject /*virtual*/ F32 getRadius() const { return mVObjRadius; }; const LLMatrix4a& getWorldMatrix(LLXformMatrix* xform) const; - void markForUpdate(BOOL priority) { LLViewerObject::markForUpdate(priority); mVolumeChanged = TRUE; } - void faceMappingChanged() { mFaceMappingChanged=TRUE; }; + void markForUpdate(BOOL priority); + void markForUnload() { LLViewerObject::markForUnload(TRUE); mVolumeChanged = TRUE; } + void faceMappingChanged() { mFaceMappingChanged=TRUE; }; /*virtual*/ void onShift(const LLVector4a &shift_vector); // Called when the drawable shifts @@ -216,10 +226,10 @@ class LLVOVolume : public LLViewerObject /*virtual*/ BOOL setMaterial(const U8 material); void setTexture(const S32 face); - S32 getIndexInTex() const {return mIndexInTex ;} + S32 getIndexInTex(U32 ch) const {return mIndexInTex[ch];} /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false); void updateSculptTexture(); - void setIndexInTex(S32 index) { mIndexInTex = index ;} + void setIndexInTex(U32 ch, S32 index) { mIndexInTex[ch] = index ;} void sculpt(); static void rebuildMeshAssetCallback(LLVFS *vfs, const LLUUID& asset_uuid, @@ -273,13 +283,28 @@ class LLVOVolume : public LLViewerObject virtual BOOL isFlexible() const; virtual BOOL isSculpted() const; virtual BOOL isMesh() const; + virtual BOOL isRiggedMesh() const; virtual BOOL hasLightTexture() const; BOOL isVolumeGlobal() const; BOOL canBeFlexible() const; BOOL setIsFlexible(BOOL is_flexible); - + const LLMeshSkinInfo* getSkinInfo() const; + + // Extended Mesh Properties + U32 getExtendedMeshFlags() const; + void onSetExtendedMeshFlags(U32 flags); + void setExtendedMeshFlags(U32 flags); + bool canBeAnimatedObject() const; + bool isAnimatedObject() const; + virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent); + virtual void afterReparent(); + + //virtual + void updateRiggingInfo(); + S32 mLastRiggingInfoLOD; + // Functions that deal with media, or media navigation // Update this object's media data with the given media data array @@ -317,6 +342,8 @@ class LLVOVolume : public LLViewerObject // tag: vaa emerald local_asset_browser void setSculptChanged(BOOL has_changed) { mSculptChanged = has_changed; } + // Flag any corresponding avatars as needing update. + void updateVisualComplexity(); void notifyMeshLoaded(); // Returns 'true' iff the media data for this object is in flight @@ -331,7 +358,7 @@ class LLVOVolume : public LLViewerObject //rigged volume update (for raycasting) - void updateRiggedVolume(); + void updateRiggedVolume(bool force_update = false); LLRiggedVolume* getRiggedVolume(); //returns true if volume should be treated as a rigged volume @@ -345,7 +372,7 @@ class LLVOVolume : public LLViewerObject void clearRiggedVolume(); protected: - S32 computeLODDetail(F32 distance, F32 radius); + S32 computeLODDetail(F32 distance, F32 radius, F32 lod_factor); BOOL calcLOD(); LLFace* addFace(S32 face_index); void updateTEData(); @@ -358,6 +385,10 @@ class LLVOVolume : public LLViewerObject void cleanUpMediaImpls(); void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ; void removeMediaImpl(S32 texture_index) ; + +private: + bool lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled); + public: static S32 getRenderComplexityMax() {return mRenderComplexity_last;} @@ -365,6 +396,9 @@ class LLVOVolume : public LLViewerObject LLViewerTextureAnim *mTextureAnimp; U8 mTexAnimMode; + F32 mLODDistance; + F32 mLODAdjustedDistance; + F32 mLODRadius; private: friend class LLDrawable; friend class LLFace; @@ -384,7 +418,7 @@ class LLVOVolume : public LLViewerObject LLPointer mLightTexture; media_list_t mMediaImplList; S32 mLastFetchedMediaVersion; // as fetched from the server, starts as -1 - S32 mIndexInTex; + S32 mIndexInTex[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; S32 mMDCImplCount; LLPointer mRiggedVolume; @@ -402,6 +436,26 @@ class LLVOVolume : public LLViewerObject static S32 sNumLODChanges; friend class LLVolumeImplFlexible; + +public: + bool notifyAboutCreatingTexture(LLViewerTexture *texture); + bool notifyAboutMissingAsset(LLViewerTexture *texture); + +private: + struct material_info + { + LLRender::eTexIndex map; + U8 te; + + material_info(LLRender::eTexIndex map_, U8 te_) + : map(map_) + , te(te_) + {} + }; + + typedef std::multimap mmap_UUID_MAP_t; + mmap_UUID_MAP_t mWaitingTextureInfo; + }; #endif // LL_LLVOVOLUME_H diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 516429f224..7e97a601d0 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -133,11 +133,11 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline) return mDrawable; } -static LLFastTimer::DeclareTimer FTM_UPDATE_WATER("Update Water"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_WATER("Update Water"); BOOL LLVOWater::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(FTM_UPDATE_WATER); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_WATER); LLFace *face; if (drawable->getNumFaces() < 1) @@ -307,15 +307,16 @@ U32 LLVOVoidWater::getPartitionType() const return LLViewerRegion::PARTITION_VOIDWATER; } -LLWaterPartition::LLWaterPartition() -: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB) +LLWaterPartition::LLWaterPartition(LLViewerRegion* regionp) +: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB, regionp) { mInfiniteFarClip = TRUE; mDrawableType = LLPipeline::RENDER_TYPE_WATER; mPartitionType = LLViewerRegion::PARTITION_WATER; } -LLVoidWaterPartition::LLVoidWaterPartition() +LLVoidWaterPartition::LLVoidWaterPartition(LLViewerRegion* regionp) + : LLWaterPartition(regionp) { //mOcclusionEnabled = FALSE; mDrawableType = LLPipeline::RENDER_TYPE_VOIDWATER; diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 28e57b429f..8e4cec604e 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -307,11 +307,11 @@ void LLVOWLSky::restoreGL() gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } -static LLFastTimer::DeclareTimer FTM_GEO_SKY("Sky Geometry"); +static LLTrace::BlockTimerStatHandle FTM_GEO_SKY("Sky Geometry"); BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) { - LLFastTimer ftm(FTM_GEO_SKY); + LL_RECORD_BLOCK_TIME(FTM_GEO_SKY); LLStrider vertices; LLStrider texCoords; LLStrider indices; diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index 763292e3b4..7646620794 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -76,6 +76,14 @@ #include "llagentcamera.h" +static LLStaticHashedString sLightNorm ("lightnorm"); +static LLStaticHashedString sCamPosLocal("camPosLocal"); +static LLStaticHashedString sWaterFogColor("waterFogColor"); +static LLStaticHashedString sWaterPlane("waterPlane"); +static LLStaticHashedString sWaterFogDensity("waterFogDensity"); +static LLStaticHashedString sWaterFogKS("waterFogKS"); +static LLStaticHashedString sDistanceMultiplier("distance_multiplier"); + LLWaterParamManager::LLWaterParamManager() : mFogColor(22.f/255.f, 43.f/255.f, 54.f/255.f, 0.0f, 0.0f, "waterFogColor", "WaterFogColor"), mFogDensity(4, "waterFogDensity", 2), @@ -347,7 +355,7 @@ void LLWaterParamManager::applyParams(const LLSD& params, bool interpolate) } } -static LLFastTimer::DeclareTimer FTM_UPDATE_WATERPARAM("Update Water Params"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERPARAM("Update Water Params"); void LLWaterParamManager::updateShaderLinks() { @@ -359,13 +367,13 @@ void LLWaterParamManager::updateShaderLinks() if (shaders_iter->mProgramObject != 0 && shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER) { - if( glGetUniformLocationARB(shaders_iter->mProgramObject,"lightnorm")>=0 || - glGetUniformLocationARB(shaders_iter->mProgramObject,"camPosLocal")>=0 || - glGetUniformLocationARB(shaders_iter->mProgramObject,"waterFogColor")>=0 || - glGetUniformLocationARB(shaders_iter->mProgramObject,"waterPlane")>=0 || - glGetUniformLocationARB(shaders_iter->mProgramObject,"waterFogDensity")>=0 || - glGetUniformLocationARB(shaders_iter->mProgramObject,"waterFogKS")>=0 || - glGetUniformLocationARB(shaders_iter->mProgramObject,"distance_multiplier")>=0) + if( shaders_iter->getUniformLocation(sLightNorm) >=0 || + shaders_iter->getUniformLocation(sCamPosLocal) >=0 || + shaders_iter->getUniformLocation(sWaterFogColor) >=0 || + shaders_iter->getUniformLocation(sWaterPlane) >=0 || + shaders_iter->getUniformLocation(sWaterFogDensity) >=0 || + shaders_iter->getUniformLocation(sWaterFogKS) >=0 || + shaders_iter->getUniformLocation(sDistanceMultiplier) >=0) mShaderList.push_back(&(*shaders_iter)); } } @@ -373,7 +381,7 @@ void LLWaterParamManager::updateShaderLinks() void LLWaterParamManager::update(LLViewerCamera * cam) { - LLFastTimer ftm(FTM_UPDATE_WATERPARAM); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_WATERPARAM); // update the shaders and the menu propagateParameters(); diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index aed18769eb..b99ff33509 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -47,7 +47,7 @@ #include "llalertdialog.h" #include "llui.h" #include "lluri.h" -#include "sgversion.h" +#include "llversioninfo.h" #include "llviewercontrol.h" #include "llviewernetwork.h" #include "llviewerparcelmgr.h" @@ -214,12 +214,12 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url, const LLSD &default_subs) { LLSD substitution = default_subs; - substitution["VERSION"] = gCurrentVersion; - substitution["VERSION_MAJOR"] = gVersionMajor; - substitution["VERSION_MINOR"] = gVersionMinor; - substitution["VERSION_PATCH"] = gVersionPatch; - substitution["VERSION_BUILD"] = gVersionBuild; - substitution["CHANNEL"] = gVersionChannel; + substitution["VERSION"] = LLVersionInfo::getVersion(); + substitution["VERSION_MAJOR"] = LLVersionInfo::getMajor(); + substitution["VERSION_MINOR"] = LLVersionInfo::getMinor(); + substitution["VERSION_PATCH"] = LLVersionInfo::getPatch(); + substitution["VERSION_BUILD"] = LLVersionInfo::getBuild(); + substitution["CHANNEL"] = LLVersionInfo::getChannel(); const HippoGridInfo* grid(gHippoGridManager->getCurrentGrid()); std::string gridId(grid->isSecondLife() ? getLoginUriDomain() : grid->getGridName()); if (grid->isSecondLife()) @@ -259,8 +259,7 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url, { parcel_id = parcel->getLocalID(); } - substitution["PARCEL_ID"] = llformat("%d", parcel_id); - + substitution["PARCEL_ID"] = fmt::to_string(parcel_id); // expand all of the substitution strings and escape the url std::string expanded_url = url; LLStringUtil::format(expanded_url, substitution); diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index aa3acc14a4..db258fbdb8 100644 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -32,14 +32,13 @@ #include "llbufferstream.h" #include "llhttpclient.h" #include "llimagepng.h" -#include "llplugincookiestore.h" +//#include "llplugincookiestore.h" // newview #include "llpanelprofile.h" // getProfileURL (this is the original location LL put it). #include "llviewermedia.h" // FIXME: don't use LLViewerMedia internals -// third-party JSONCPP -#include // JSONCPP +#include "llsdjson.h" /* * Workflow: @@ -78,16 +77,15 @@ class LLWebProfileResponders::ConfigResponder : public LLHTTPClient::ResponderWi if (mStatus != HTTP_OK) { - LL_WARNS() << "Failed to get upload config (" << mStatus << ")" << LL_ENDL; + LL_WARNS() << "Failed to get upload config (" << mStatus << ')' << LL_ENDL; LLWebProfile::reportImageUploadStatus(false); return; } - Json::Value root; - Json::Reader reader; - if (!reader.parse(body, root)) + auto root = LlsdFromJsonString(body); + if (root.isUndefined()) { - LL_WARNS() << "Failed to parse upload config: " << reader.getFormatedErrorMessages() << LL_ENDL; + LL_WARNS() << "Failed to get valid json body" << LL_ENDL; LLWebProfile::reportImageUploadStatus(false); return; } @@ -96,21 +94,14 @@ class LLWebProfileResponders::ConfigResponder : public LLHTTPClient::ResponderWi // *TODO: increase timeout or handle HTTP_INTERNAL_ERROR_* time errors. // Convert config to LLSD. - const Json::Value data = root["data"]; + const auto data = root["data"]; const std::string upload_url = root["url"].asString(); - LLSD config; - config["acl"] = data["acl"].asString(); - config["AWSAccessKeyId"] = data["AWSAccessKeyId"].asString(); - config["Content-Type"] = data["Content-Type"].asString(); - config["key"] = data["key"].asString(); - config["policy"] = data["policy"].asString(); - config["success_action_redirect"] = data["success_action_redirect"].asString(); - config["signature"] = data["signature"].asString(); - config["add_loc"] = data.get("add_loc", "0").asString(); - config["caption"] = data.get("caption", "").asString(); + LLSD config = data; + if (!data.has("add_loc")) config["add_loc"] = "0"; + if (!data.has("caption")) config["caption"] = LLStringUtil::null; // Do the actual image upload using the configuration. - LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << "]" << LL_ENDL; + LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << ']' << LL_ENDL; LLWebProfile::post(mImagep, config, upload_url); } @@ -133,7 +124,7 @@ class LLWebProfileResponders::PostImageRedirectResponder : public LLHTTPClient:: { if (mStatus != HTTP_OK) { - LL_WARNS() << "Failed to upload image: " << mStatus << " " << mReason << LL_ENDL; + LL_WARNS() << "Failed to upload image: " << mStatus << ' ' << mReason << LL_ENDL; LLWebProfile::reportImageUploadStatus(false); return; } @@ -143,7 +134,7 @@ class LLWebProfileResponders::PostImageRedirectResponder : public LLHTTPClient:: strstrm << istr.rdbuf(); const std::string body = strstrm.str(); LL_INFOS() << "Image uploaded." << LL_ENDL; - LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << LL_ENDL; + LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << ']' << LL_ENDL; LLWebProfile::reportImageUploadStatus(true); } @@ -184,8 +175,8 @@ class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::Responde } else { - LL_WARNS() << "Unexpected POST status: " << mStatus << " " << mReason << LL_ENDL; - LL_DEBUGS("Snapshots") << "received_headers: [" << mReceivedHeaders << "]" << LL_ENDL; + LL_WARNS() << "Unexpected POST status: " << mStatus << ' ' << mReason << LL_ENDL; + LL_DEBUGS("Snapshots") << "received_headers: [" << mReceivedHeaders << ']' << LL_ENDL; LLWebProfile::reportImageUploadStatus(false); } } diff --git a/indra/newview/llwlanimator.cpp b/indra/newview/llwlanimator.cpp index 2d4983416d..1c8f211271 100644 --- a/indra/newview/llwlanimator.cpp +++ b/indra/newview/llwlanimator.cpp @@ -267,7 +267,7 @@ std::string LLWLAnimator::timeToString(F32 curTime) // get hours and minutes hours = (S32) (24.0 * curTime); curTime -= ((F32) hours / 24.0f); - min = ll_round(24.0f * 60.0f * curTime); + min = ll_pos_round(24.0f * 60.0f * curTime); // handle case where it's 60 if(min == 60) diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index 33c9c3cf74..dd11408455 100644 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -158,7 +158,7 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) sLastUpdate = current; // Send update request. - std::string url = gAgent.getRegion()->getCapability("EnvironmentSettings"); + std::string url = gAgent.getRegionCapability("EnvironmentSettings"); if (url.empty()) { LL_WARNS("WindlightCaps") << "Applying windlight settings not supported" << LL_ENDL; diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index 850e25c0c4..b5c01ff0b5 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -268,9 +268,7 @@ void LLWLParamManager::addAllSkies(const LLWLParamKey::EScope scope, const LLSD& { for(LLSD::map_const_iterator iter = sky_presets.beginMap(); iter != sky_presets.endMap(); ++iter) { - LLWLParamSet set; - set.setAll(iter->second); - mParamList[LLWLParamKey(iter->first, scope)] = set; + setParamSet(LLWLParamKey(iter->first, scope), iter->second); } } @@ -405,11 +403,11 @@ void LLWLParamManager::updateShaderLinks() } } -static LLFastTimer::DeclareTimer FTM_UPDATE_WLPARAM("Update Windlight Params"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_WLPARAM("Update Windlight Params"); void LLWLParamManager::propagateParameters(void) { - LLFastTimer ftm(FTM_UPDATE_WLPARAM); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_WLPARAM); LLVector4 sunDir; LLVector4 moonDir; @@ -474,7 +472,7 @@ void LLWLParamManager::propagateParameters(void) void LLWLParamManager::update(LLViewerCamera * cam) { - LLFastTimer ftm(FTM_UPDATE_WLPARAM); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_WLPARAM); // update clouds, sun, and general mCurParams.updateCloudScrolling(); @@ -606,9 +604,9 @@ bool LLWLParamManager::hasParamSet(const LLWLParamKey& key) return getParamSet(key, dummy); } -bool LLWLParamManager::setParamSet(const std::string& name, LLWLParamSet& param) +bool LLWLParamManager::setParamSet(const std::string& name, LLWLParamSet& param, LLEnvKey::EScope scope) { - const LLWLParamKey key(name, LLEnvKey::SCOPE_LOCAL); + const LLWLParamKey key(name, scope); return setParamSet(key, param); } @@ -621,9 +619,9 @@ bool LLWLParamManager::setParamSet(const LLWLParamKey& key, LLWLParamSet& param) return true; } -bool LLWLParamManager::setParamSet(const std::string& name, const LLSD & param) +bool LLWLParamManager::setParamSet(const std::string& name, const LLSD & param, LLEnvKey::EScope scope) { - const LLWLParamKey key(name, LLEnvKey::SCOPE_LOCAL); + const LLWLParamKey key(name, scope); return setParamSet(key, param); } diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h index d244d4c479..8318f0414d 100644 --- a/indra/newview/llwlparammanager.h +++ b/indra/newview/llwlparammanager.h @@ -205,11 +205,11 @@ class LLWLParamManager : public LLSingleton bool hasParamSet(const LLWLParamKey& key); /// set the param in the list with a new param - bool setParamSet(const std::string& name, LLWLParamSet& param); + bool setParamSet(const std::string& name, LLWLParamSet& param, LLEnvKey::EScope scope = LLEnvKey::SCOPE_LOCAL); bool setParamSet(const LLWLParamKey& key, LLWLParamSet& param); /// set the param in the list with a new param - bool setParamSet(const std::string& name, LLSD const & param); + bool setParamSet(const std::string& name, LLSD const & param, LLEnvKey::EScope scope = LLEnvKey::SCOPE_LOCAL); bool setParamSet(const LLWLParamKey& key, LLSD const & param); /// gets rid of a parameter and any references to it diff --git a/indra/newview/llwlparamset.cpp b/indra/newview/llwlparamset.cpp index 63b58f4d30..0e2769df26 100644 --- a/indra/newview/llwlparamset.cpp +++ b/indra/newview/llwlparamset.cpp @@ -65,11 +65,11 @@ LLWLParamSet::LLWLParamSet(void) : mCloudScrollXOffset(0.f), mCloudScrollYOffset(0.f) {} -static LLFastTimer::DeclareTimer FTM_WL_PARAM_UPDATE("WL Param Update"); +static LLTrace::BlockTimerStatHandle FTM_WL_PARAM_UPDATE("WL Param Update"); void LLWLParamSet::update(LLGLSLShader * shader) const { - LLFastTimer t(FTM_WL_PARAM_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_WL_PARAM_UPDATE); LLSD::map_const_iterator i = mParamValues.beginMap(); std::vector::const_iterator n = mParamHashedNames.begin(); for(;(i != mParamValues.endMap()) && (n != mParamHashedNames.end());++i, n++) @@ -86,8 +86,7 @@ void LLWLParamSet::update(LLGLSLShader * shader) const { continue; } - - if (param == sCloudDensity) + else if (param == sCloudDensity) { LLVector4 val; val.mV[0] = F32(i->second[0].asReal()) + mCloudScrollXOffset; @@ -99,55 +98,58 @@ void LLWLParamSet::update(LLGLSLShader * shader) const shader->uniform4fv(param, 1, val.mV); stop_glerror(); } - else if (param == sCloudScale || param == sCloudShadow || - param == sDensityMultiplier || param == sDistanceMultiplier || - param == sHazeDensity || param == sHazeHorizon || - param == sMaxY ) - { - F32 val = (F32) i->second[0].asReal(); - - stop_glerror(); - shader->uniform1f(param, val); - stop_glerror(); - } else // param is the uniform name { // handle all the different cases - if (i->second.isArray() && i->second.size() == 4) + if (i->second.isArray()) { - LLVector4 val; - - val.mV[0] = (F32) i->second[0].asReal(); - val.mV[1] = (F32) i->second[1].asReal(); - val.mV[2] = (F32) i->second[2].asReal(); - val.mV[3] = (F32) i->second[3].asReal(); - stop_glerror(); - shader->uniform4fv(param, 1, val.mV); + // Switch statement here breaks msbuild for some reason + if (i->second.size() == 4) + { + LLVector4 val( + i->second[0].asFloat(), + i->second[1].asFloat(), + i->second[2].asFloat(), + i->second[3].asFloat() + ); + shader->uniform4fv(param, 1, val.mV); + } + else if (i->second.size() == 3) + { + shader->uniform3f(param, + i->second[0].asFloat(), + i->second[1].asFloat(), + i->second[2].asFloat()); + } + else if (i->second.size() == 2) + { + shader->uniform2f(param, + i->second[0].asFloat(), + i->second[1].asFloat()); + } + else if (i->second.size() == 1) + { + shader->uniform1f(param, i->second[0].asFloat()); + } stop_glerror(); } else if (i->second.isReal()) { - F32 val = (F32) i->second.asReal(); - stop_glerror(); - shader->uniform1f(param, val); + shader->uniform1f(param, i->second.asFloat()); stop_glerror(); } else if (i->second.isInteger()) { - S32 val = (S32) i->second.asInteger(); - stop_glerror(); - shader->uniform1i(param, val); + shader->uniform1i(param, i->second.asInteger()); stop_glerror(); } else if (i->second.isBoolean()) { - S32 val = (i->second.asBoolean() ? 1 : 0); - stop_glerror(); - shader->uniform1i(param, val); + shader->uniform1i(param, i->second.asBoolean() ? 1 : 0); stop_glerror(); } } @@ -155,9 +157,9 @@ void LLWLParamSet::update(LLGLSLShader * shader) const } void LLWLParamSet::set(const std::string& paramName, float x) -{ +{ // handle case where no array - if(mParamValues[paramName].isReal()) + if(mParamValues.isUndefined() || mParamValues[paramName].isReal()) { mParamValues[paramName] = x; } @@ -265,7 +267,7 @@ void LLWLParamSet::setSunAngle(float val) val = F_TWO_PI * num; } - mParamValues["sun_angle"] = val; + set("sun_angle", val); } @@ -279,7 +281,7 @@ void LLWLParamSet::setEastAngle(float val) val = F_TWO_PI * num; } - mParamValues["east_angle"] = val; + set("east_angle", val); } void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) @@ -292,7 +294,7 @@ void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) F32 cloudPos1Y = (F32) mParamValues["cloud_pos_density1"][1].asReal(); F32 cloudPos2X = (F32) mParamValues["cloud_pos_density2"][0].asReal(); F32 cloudPos2Y = (F32) mParamValues["cloud_pos_density2"][1].asReal(); - F32 cloudCover = (F32) mParamValues["cloud_shadow"][0].asReal(); + F32 cloudCover = (F32) mParamValues["cloud_shadow"].asReal(); LLSD srcVal; LLSD destVal; @@ -381,11 +383,9 @@ void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) // now setup the sun properly // reset those cloud positions - mParamValues["cloud_pos_density1"][0] = cloudPos1X; - mParamValues["cloud_pos_density1"][1] = cloudPos1Y; - mParamValues["cloud_pos_density2"][0] = cloudPos2X; - mParamValues["cloud_pos_density2"][1] = cloudPos2Y; - mParamValues["cloud_shadow"][0] = cloudCover; + set("cloud_pos_density1", cloudPos1X, cloudPos1Y); + set("cloud_pos_density2", cloudPos2X, cloudPos2Y); + set("cloud_shadow", cloudCover); } void LLWLParamSet::updateCloudScrolling(void) @@ -410,7 +410,16 @@ void LLWLParamSet::updateHashedNames() // Iterate through values for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter) { - mParamHashedNames.push_back(LLStaticHashedString(iter->first)); + LLStaticHashedString param(iter->first); + mParamHashedNames.push_back(param); + if (iter->second.isArray() && (param == sCloudScale || param == sCloudShadow || + param == sDensityMultiplier || param == sDistanceMultiplier || + param == sHazeDensity || param == sHazeHorizon || + param == sMaxY)) + { + // Params are incorrect in the XML files. These SHOULD be F32, not arrays. + iter->second.assign(iter->second[0]); + } } } diff --git a/indra/newview/llwlparamset.h b/indra/newview/llwlparamset.h index 16bdf8ba32..afede29f1b 100644 --- a/indra/newview/llwlparamset.h +++ b/indra/newview/llwlparamset.h @@ -198,7 +198,7 @@ inline const LLSD& LLWLParamSet::getAll() } inline void LLWLParamSet::setStarBrightness(float val) { - mParamValues["star_brightness"] = val; + set("star_brightness", val); } inline F32 LLWLParamSet::getStarBrightness() { @@ -213,7 +213,6 @@ inline F32 LLWLParamSet::getEastAngle() { return (F32) mParamValues["east_angle"].asReal(); } - inline void LLWLParamSet::setEnableCloudScrollX(bool val) { mParamValues["enable_cloud_scroll"][0] = val; } diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index d10279ca51..b27055552c 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -172,6 +172,7 @@ LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) { LL_INFOS() << "Add region with handle: " << region_handle << " on host " << host << LL_ENDL; LLViewerRegion *regionp = getRegionFromHandle(region_handle); + std::string seedUrl; if (regionp) { LLHost old_host = regionp->getHost(); @@ -191,9 +192,12 @@ LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) } if (!regionp->isAlive()) { - LL_WARNS() << "LLWorld::addRegion exists, but isn't alive" << LL_ENDL; + LL_WARNS() << "LLWorld::addRegion exists, but isn't alive. Removing old region and creating new" << LL_ENDL; } + // Save capabilities seed URL + seedUrl = regionp->getCapability("Seed"); + // Kill the old host, and then we can continue on and add the new host. We have to kill even if the host // matches, because all the agent state for the new camera is completely different. removeRegion(old_host); @@ -229,6 +233,11 @@ LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) LL_ERRS() << "Unable to create new region!" << LL_ENDL; } + if ( !seedUrl.empty() ) + { + regionp->setCapability("Seed", seedUrl); + } + //Classic clouds #if ENABLE_CLASSIC_CLOUDS regionp->mCloudLayer.create(regionp); @@ -673,7 +682,7 @@ LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global) return NULL; } - return regionp->getLand().resolvePatchGlobal(pos_global); + return regionp->getLand().resolvePatchGlobal(pos_global).get(); } @@ -769,6 +778,17 @@ void LLWorld::updateRegions(F32 max_update_time) } } + +void LLWorld::clearAllVisibleObjects() +{ + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + //clear all cached visible objects. + (*iter)->clearCachedVisibleObjects(); + } +} + void LLWorld::updateParticles() { static const LLCachedControl freeze_time("FreezeTime",false); @@ -842,7 +862,6 @@ LLCloudGroup* LLWorld::findCloudGroup(const LLCloudPuff &puff) } #endif - void LLWorld::renderPropertyLines() { S32 region_count = 0; @@ -1354,11 +1373,11 @@ void LLWorld::disconnectRegions() } } -static LLFastTimer::DeclareTimer FTM_ENABLE_SIMULATOR("Enable Sim"); +static LLTrace::BlockTimerStatHandle FTM_ENABLE_SIMULATOR("Enable Sim"); void process_enable_simulator(LLMessageSystem *msg, void **user_data) { - LLFastTimer t(FTM_ENABLE_SIMULATOR); + LL_RECORD_BLOCK_TIME(FTM_ENABLE_SIMULATOR); if (!gAgent.getRegion()) return; @@ -1437,6 +1456,8 @@ class LLEstablishAgentCommunication : public LLHTTPNode << sim << LL_ENDL; return; } + LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from LLEstablishAgentCommunication::post. Seed cap == " + << input["body"]["seed-capability"] << LL_ENDL; regionp->setSeedCapability(input["body"]["seed-capability"]); } }; diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index fa65c364a9..1620a92415 100644 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -157,6 +157,7 @@ class LLWorld : public LLSingleton void getInfo(LLSD& info); + void clearAllVisibleObjects(); public: typedef std::list region_list_t; const region_list_t& getRegionList() const { return mActiveRegionList; } diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 2111ec4374..61a8d976bb 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -95,8 +95,8 @@ LLSimInfo::LLSimInfo(U64 handle) void LLSimInfo::setLandForSaleImage (LLUUID image_id) { - const bool is_aurora = gHippoGridManager->getConnectedGrid()->isAurora(); - if (is_aurora && mMapImageID[SIM_LAYER_OVERLAY].isNull() && image_id.notNull() && gTextureList.findImage(image_id)) + const bool is_whitecore = gHippoGridManager->getConnectedGrid()->isWhiteCore(); + if (is_whitecore && mMapImageID[SIM_LAYER_OVERLAY].isNull() && image_id.notNull() && gTextureList.findImage(image_id, TEX_LIST_STANDARD)) LLAppViewer::getTextureCache()->removeFromCache(image_id); mMapImageID[SIM_LAYER_OVERLAY] = image_id; @@ -104,8 +104,8 @@ void LLSimInfo::setLandForSaleImage (LLUUID image_id) // Fetch the image if (mMapImageID[SIM_LAYER_OVERLAY].notNull()) { - mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); - if (is_aurora) mLayerImage[SIM_LAYER_OVERLAY]->forceImmediateUpdate(); + mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + if (is_whitecore) mLayerImage[SIM_LAYER_OVERLAY]->forceImmediateUpdate(); mLayerImage[SIM_LAYER_OVERLAY]->setAddressMode(LLTexUnit::TAM_CLAMP); } else @@ -119,7 +119,7 @@ LLPointer LLSimInfo::getLandForSaleImage () if (mLayerImage[SIM_LAYER_OVERLAY].isNull() && mMapImageID[SIM_LAYER_OVERLAY].notNull()) { // Fetch the image if it hasn't been done yet (unlikely but...) - mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); mLayerImage[SIM_LAYER_OVERLAY]->setAddressMode(LLTexUnit::TAM_CLAMP); } if (!mLayerImage[SIM_LAYER_OVERLAY].isNull()) @@ -517,7 +517,7 @@ void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**) msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Top, top, block); msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Bottom, bottom, block); - new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, FTT_MAP_TILE, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); gGL.getTexUnit(0)->bind(new_layer.LayerImage.get()); new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp index f423a95f74..66cd1209ee 100644 --- a/indra/newview/llworldmapmessage.cpp +++ b/indra/newview/llworldmapmessage.cpp @@ -74,10 +74,10 @@ void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle) void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name) { - //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL; + //LL_INFOS("WorldMap") << LL_ENDL; LLMessageSystem* msg = gMessageSystem; - // Request for layer + // Request for region data msg->newMessageFast(_PREHASH_MapNameRequest); msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); @@ -95,7 +95,7 @@ void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name, const std::string& callback_url, bool teleport) // immediately teleport when result returned { - //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL; + //LL_INFOS("WorldMap") << LL_ENDL; mSLURLRegionName = region_name; mSLURLRegionHandle = 0; mSLURL = callback_url; @@ -110,7 +110,7 @@ void LLWorldMapMessage::sendHandleRegionRequest(U64 region_handle, const std::string& callback_url, bool teleport) // immediately teleport when result returned { - //LL_INFOS("World Map") << "LLWorldMap::sendHandleRegionRequest()" << LL_ENDL; + //LL_INFOS("WorldMap") << LL_ENDL; mSLURLRegionName.clear(); mSLURLRegionHandle = region_handle; mSLURL = callback_url; @@ -123,13 +123,12 @@ void LLWorldMapMessage::sendHandleRegionRequest(U64 region_handle, U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS); U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS); - sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true, LAYER_FLAG); + sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); } -// public void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent, S32 layer) { - //LL_INFOS("World Map") << "LLWorldMap::sendMapBlockRequest()" << ", min = (" << min_x << ", " << min_y << "), max = (" << max_x << ", " << max_y << "), nonexistent = " << return_nonexistent << LL_ENDL; + //LL_INFOS("WorldMap" << " min = (" << min_x << ", " << min_y << "), max = (" << max_x << ", " << max_y << ", nonexistent = " << return_nonexistent << LL_ENDL; LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_MapBlockRequest); msg->nextBlockFast(_PREHASH_AgentData); @@ -162,7 +161,7 @@ void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**) } S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data); - //LL_INFOS("World Map") << "LLWorldMap::processMapBlockReply(), num_blocks = " << num_blocks << LL_ENDL; + //LL_INFOS("WorldMap") << "num_blocks = " << num_blocks << LL_ENDL; bool found_null_sim = false; @@ -239,7 +238,6 @@ void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**) url_callback_t callback = LLWorldMapMessage::getInstance()->mSLURLCallback; if(callback != NULL) { - // Check if we reached the requested region if ((LLStringUtil::compareInsensitive(LLWorldMapMessage::getInstance()->mSLURLRegionName, name)==0) || (LLWorldMapMessage::getInstance()->mSLURLRegionHandle == handle)) @@ -264,7 +262,7 @@ void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**) // public static void LLWorldMapMessage::processMapItemReply(LLMessageSystem* msg, void**) { - //LL_INFOS("World Map") << "LLWorldMap::processMapItemReply()" << LL_ENDL; + //LL_INFOS("WorldMap") << LL_ENDL; U32 type; msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type); diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 6e1e1b0e04..5fd4821dd3 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -149,10 +149,10 @@ void LLWorldMapView::initClass() sHomeImage = LLUI::getUIImage("map_home.tga"); sTelehubImage = LLUI::getUIImage("map_telehub.tga"); sInfohubImage = LLUI::getUIImage("map_infohub.tga"); - sEventImage = LLUI::getUIImage("map_event.tga"); - sEventMatureImage = LLUI::getUIImage("map_event_mature.tga"); + sEventImage = LLUI::getUIImage("Parcel_PG_Light"); + sEventMatureImage = LLUI::getUIImage("Parcel_M_Light"); // To Do: update the image resource for adult events. - sEventAdultImage = LLUI::getUIImage("map_event_adult.tga"); + sEventAdultImage = LLUI::getUIImage("Parcel_R_Light"); sTrackCircleImage = LLUI::getUIImage("map_track_16.tga"); sTrackArrowImage = LLUI::getUIImage("direction_arrow.tga"); @@ -337,8 +337,8 @@ void LLWorldMapView::draw() mVisibleRegions.clear(); // animate pan if necessary - sPanX = lerp(sPanX, sTargetPanX, LLCriticalDamp::getInterpolant(0.1f)); - sPanY = lerp(sPanY, sTargetPanY, LLCriticalDamp::getInterpolant(0.1f)); + sPanX = lerp(sPanX, sTargetPanX, LLSmoothInterpolation::getInterpolant(0.1f)); + sPanY = lerp(sPanY, sTargetPanY, LLSmoothInterpolation::getInterpolant(0.1f)); const S32 width = getRect().getWidth(); const S32 height = getRect().getHeight(); @@ -433,11 +433,11 @@ void LLWorldMapView::draw() gGL.color4f(0.2f, 0.0f, 0.0f, 0.4f); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.vertex2f(left, top); gGL.vertex2f(left, bottom); - gGL.vertex2f(right, bottom); gGL.vertex2f(right, top); + gGL.vertex2f(right, bottom); gGL.end(); gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); } @@ -475,15 +475,15 @@ void LLWorldMapView::draw() { gGL.getTexUnit(0)->bind(overlayimage); gGL.color4f(1.f, 1.f, 1.f, alpha); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(0.f, 1.f); gGL.vertex3f(left, top, -0.5f); gGL.texCoord2f(0.f, 0.f); gGL.vertex3f(left, bottom, -0.5f); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex3f(right, bottom, -0.5f); gGL.texCoord2f(1.f, 1.f); gGL.vertex3f(right, top, -0.5f); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex3f(right, bottom, -0.5f); gGL.end(); } } @@ -582,11 +582,11 @@ void LLWorldMapView::draw() gGL.color4f(0.5f, 0.0f, 0.0f, 0.4f); else gGL.color4f(0.2f, .2f, 0.2f, 0.4f); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.vertex2f(base_left+padding, base_top-padding); gGL.vertex2f(base_left+padding, base_bottom+padding); + gGL.vertex2f(base_right - padding, base_top - padding); gGL.vertex2f(base_right-padding, base_bottom+padding); - gGL.vertex2f(base_right-padding, base_top-padding); gGL.end(); if(it != LLWorldMap::getInstance()->getMapBlockEnd(SIM_LAYER_OVERLAY)) { @@ -610,11 +610,11 @@ void LLWorldMapView::draw() gGL.color4f(0.0f, 0.5f, 0.0f, 0.4f); else gGL.color4f(0.4f, 0.0f, 0.0f, 0.4f); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.vertex2f(block_left+padding, block_top-padding); gGL.vertex2f(block_left+padding, block_bottom+padding); + gGL.vertex2f(block_right - padding, block_top - padding); gGL.vertex2f(block_right-padding, block_bottom+padding); - gGL.vertex2f(block_right-padding, block_top-padding); gGL.end(); for(U32 sim_x=0;sim_x no_scissor; updateDirections(); @@ -840,29 +840,29 @@ void LLWorldMapView::drawLegacyBackgroundLayers(S32 width, S32 height) { // Draw map image into RGB gGL.setColorMask(true, false); gGL.color4f(1.f, 1.f, 1.f, 1.f); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(0.0f, 1.0f); gGL.vertex3f(left, top, -1.0f); gGL.texCoord2f(0.0f, 0.0f); gGL.vertex3f(left, bottom, -1.0f); - gGL.texCoord2f(1.0f, 0.0f); - gGL.vertex3f(right, bottom, -1.0f); gGL.texCoord2f(1.0f, 1.0f); gGL.vertex3f(right, top, -1.0f); + gGL.texCoord2f(1.0f, 0.0f); + gGL.vertex3f(right, bottom, -1.0f); gGL.end(); // draw an alpha of 1 where the sims are visible gGL.setColorMask(false, true); gGL.color4f(1.f, 1.f, 1.f, 1.f); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(0.0f, 1.0f); gGL.vertex2f(left, top); gGL.texCoord2f(0.0f, 0.0f); gGL.vertex2f(left, bottom); - gGL.texCoord2f(1.0f, 0.0f); - gGL.vertex2f(right, bottom); gGL.texCoord2f(1.0f, 1.0f); gGL.vertex2f(right, top); + gGL.texCoord2f(1.0f, 0.0f); + gGL.vertex2f(right, bottom); gGL.end(); gGL.setColorMask(true, true); @@ -890,7 +890,7 @@ F32 LLWorldMapView::drawLegacySimTile(LLSimInfo& sim_info, S32 left, S32 top, S3 (textures_requested_this_tick < MAX_REQUEST_PER_TICK))) { textures_requested_this_tick++; - simimage = sim_info.mLayerImage[SIM_LAYER_COMPOSITE] = LLViewerTextureManager::getFetchedTexture(sim_info.mMapImageID[SIM_LAYER_COMPOSITE], MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + simimage = sim_info.mLayerImage[SIM_LAYER_COMPOSITE] = LLViewerTextureManager::getFetchedTexture(sim_info.mMapImageID[SIM_LAYER_COMPOSITE], FTT_MAP_TILE, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); simimage->setAddressMode(LLTexUnit::TAM_CLAMP); } } @@ -905,7 +905,7 @@ F32 LLWorldMapView::drawLegacySimTile(LLSimInfo& sim_info, S32 left, S32 top, S3 if (!sim_drawable || sim_fetching) sim_info.setAlpha( 0.f ); else if (llabs(sim_info.getAlpha() - fade_target) > ALPHA_CUTOFF) //This gives us a nice fade when a visible sims texture finishes loading, or visiblity has changed. - sim_info.setAlpha(lerp(sim_info.getAlpha(), fade_target, LLCriticalDamp::getInterpolant(0.15f))); + sim_info.setAlpha(lerp(sim_info.getAlpha(), fade_target, LLSmoothInterpolation::getInterpolant(0.15f))); F32 alpha = sim_info.getAlpha(); //call setKnownDrawSize if image is still loading, or its actually being drawn. @@ -919,15 +919,15 @@ F32 LLWorldMapView::drawLegacySimTile(LLSimInfo& sim_info, S32 left, S32 top, S3 { gGL.getTexUnit(0)->bind(simimage); gGL.color4f(1.f, 1.f, 1.f, alpha); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(left, top); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(left, bottom); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2f(right, bottom); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(right, top); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2f(right, bottom); gGL.end(); } } @@ -1045,15 +1045,15 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load gGL.getTexUnit(0)->bind(simimage.get()); simimage->setAddressMode(LLTexUnit::TAM_CLAMP); gGL.color4f(1.f, 1.0f, 1.0f, 1.0f); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(0.f, 1.f); gGL.vertex3f(left, top, 0.f); gGL.texCoord2f(0.f, 0.f); gGL.vertex3f(left, bottom, 0.f); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex3f(right, bottom, 0.f); gGL.texCoord2f(1.f, 1.f); gGL.vertex3f(right, top, 0.f); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex3f(right, bottom, 0.f); gGL.end(); #if DEBUG_DRAW_TILE drawTileOutline(level, top, left, bottom, right); @@ -1250,9 +1250,9 @@ void LLWorldMapView::drawFrustum() F32 half_width_pixels = half_width_meters * meters_to_pixels; // Compute the frustum coordinates. Take the UI scale into account. - static LLCachedControl ui_scale_factor("UIScaleFactor"); - F32 ctr_x = (getLocalRect().getWidth() * 0.5f + sPanX) * ui_scale_factor; - F32 ctr_y = (getLocalRect().getHeight() * 0.5f + sPanY) * ui_scale_factor; + LLVector2 ui_scale_factor = gViewerWindow->getUIScale(); + F32 ctr_x = (getLocalRect().getWidth() * 0.5f + sPanX) * ui_scale_factor.mV[VX]; + F32 ctr_y = (getLocalRect().getHeight() * 0.5f + sPanY) * ui_scale_factor.mV[VY]; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -1688,12 +1688,10 @@ void LLWorldMapView::drawTrackingCircle( const LLRect& rect, S32 x, S32 y, const end_theta -= angle_adjust_y; } - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.translatef((F32)x, (F32)y, 0.f); + gGL.pushUIMatrix(); + gGL.translateUI(x, y, 0.f); gl_washer_segment_2d(inner_radius, outer_radius, start_theta, end_theta, 40, color, color); - gGL.popMatrix(); - + gGL.popUIMatrix(); } // static diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp index 66ee60d475..6de118940b 100644 --- a/indra/newview/llworldmipmap.cpp +++ b/indra/newview/llworldmipmap.cpp @@ -198,7 +198,7 @@ LLPointer LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 // END DEBUG //LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL; - LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); img->setBoostLevel(LLGLTexture::BOOST_MAP); // Return the smart pointer diff --git a/indra/newview/m7wlinterface.cpp b/indra/newview/m7wlinterface.cpp index c2bceeaf21..e57bf4c05c 100644 --- a/indra/newview/m7wlinterface.cpp +++ b/indra/newview/m7wlinterface.cpp @@ -110,17 +110,17 @@ void M7WindlightInterface::receiveMessage(LLMessageSystem* msg) mWindlight.set("ambient", wl->ambient.red * 3.0f, wl->ambient.green * 3.0f, wl->ambient.blue * 3.0f, wl->ambient.alpha * 3.0f); mWindlight.set("blue_horizon", wl->horizon.red * 2.0f, wl->horizon.green *2.0f, wl->horizon.blue * 2.0f, wl->horizon.alpha * 2.0f); mWindlight.set("blue_density", wl->blueDensity.red * 2.0f, wl->blueDensity.green * 2.0f, wl->blueDensity.blue * 2.0f, wl->blueDensity.alpha * 2.0f); - mWindlight.set("haze_horizon", wl->hazeHorizon, wl->hazeHorizon, wl->hazeHorizon, 1.f); - mWindlight.set("haze_density", wl->hazeDensity, wl->hazeDensity, wl->hazeDensity, 1.f); - mWindlight.set("cloud_shadow", wl->cloudCoverage, wl->cloudCoverage, wl->cloudCoverage, wl->cloudCoverage); + mWindlight.set("haze_horizon", wl->hazeHorizon); + mWindlight.set("haze_density", wl->hazeDensity); + mWindlight.set("cloud_shadow", wl->cloudCoverage); mWindlight.set("density_multiplier", wl->densityMultiplier / 1000.0f); - mWindlight.set("distance_multiplier", wl->distanceMultiplier, wl->distanceMultiplier, wl->distanceMultiplier, wl->distanceMultiplier); + mWindlight.set("distance_multiplier", wl->distanceMultiplier); mWindlight.set("max_y",(F32)wl->maxAltitude); mWindlight.set("cloud_color", wl->cloudColor.red, wl->cloudColor.green, wl->cloudColor.blue, wl->cloudColor.alpha); mWindlight.set("cloud_pos_density1", wl->cloudXYDensity.X, wl->cloudXYDensity.Y, wl->cloudXYDensity.Z); mWindlight.set("cloud_pos_density2", wl->cloudDetailXYDensity.X, wl->cloudDetailXYDensity.Y, wl->cloudDetailXYDensity.Z); - mWindlight.set("cloud_scale", wl->cloudScale, 0.f, 0.f, 1.f); - mWindlight.set("gamma", wl->sceneGamma, wl->sceneGamma, wl->sceneGamma, 0.0f); + mWindlight.set("cloud_scale", wl->cloudScale); + mWindlight.set("gamma", wl->sceneGamma); mWindlight.set("glow",(2 - wl->sunGlowSize) * 20 , 0.f, -wl->sunGlowFocus * 5); mWindlight.setCloudScrollX(wl->cloudScrollX + 10.0f); mWindlight.setCloudScrollY(wl->cloudScrollY + 10.0f); diff --git a/indra/newview/macview_Prefix.h b/indra/newview/macview_Prefix.h index 8cbabb5103..c3f0c6e6ff 100644 --- a/indra/newview/macview_Prefix.h +++ b/indra/newview/macview_Prefix.h @@ -76,7 +76,7 @@ #include "llfloatertools.h" #include "llhudeffectlookat.h" #include "llhudmanager.h" -#include "llinventoryview.h" +#include "llpanelmaininventory.h" #include "lljoystickbutton.h" #include "llmenugl.h" #include "llmorphview.h" diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f0f71c1122..db626588ed 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -152,11 +152,19 @@ const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f; const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f; const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40; const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10; -const U32 REFLECTION_MAP_RES = 128; +const U32 NOISE_MAP_RES = 256; const U32 AUX_VB_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1; // Max number of occluders to search for. JC const S32 MAX_OCCLUDER_COUNT = 2; +enum { + LIGHT_MODE_NORMAL, + LIGHT_MODE_EDIT, + LIGHT_MODE_BACKLIGHT, + LIGHT_MODE_PREVIEW +}; + + extern S32 gBoxFrame; //extern BOOL gHideSelectedObjects; extern BOOL gDisplaySwapBuffers; @@ -172,69 +180,60 @@ BOOL gDebugPipeline = FALSE; LLPipeline gPipeline; const LLMatrix4a* gGLLastMatrix = NULL; -LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Geometry"); -LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass"); -LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible"); -LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion"); -LLFastTimer::DeclareTimer FTM_RENDER_SHINY("Shiny"); -LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE("Simple"); -LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN("Terrain"); -LLFastTimer::DeclareTimer FTM_RENDER_TREES("Trees"); -LLFastTimer::DeclareTimer FTM_RENDER_UI("UI"); -LLFastTimer::DeclareTimer FTM_RENDER_WATER("Water"); -LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY("Windlight Sky"); -LLFastTimer::DeclareTimer FTM_RENDER_ALPHA("Alpha Objects"); -LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS("Avatars"); -LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump"); -LLFastTimer::DeclareTimer FTM_RENDER_MATERIALS("Materials"); -LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright"); -LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow"); -LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update"); -LLFastTimer::DeclareTimer FTM_PIPELINE_CREATE("Pipeline Create"); -LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool"); -LLFastTimer::DeclareTimer FTM_POOLS("Pools"); -LLFastTimer::DeclareTimer FTM_DEFERRED_POOLRENDER("RenderPool (Deferred)"); -LLFastTimer::DeclareTimer FTM_DEFERRED_POOLS("Pools (Deferred)"); -LLFastTimer::DeclareTimer FTM_POST_DEFERRED_POOLRENDER("RenderPool (Post)"); -LLFastTimer::DeclareTimer FTM_POST_DEFERRED_POOLS("Pools (Post)"); -LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO"); -LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State"); -LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline"); -LLFastTimer::DeclareTimer FTM_CLIENT_COPY("Client Copy"); -LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading"); - - -static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables"); -static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort"); - -//static LLStaticHashedString sTint("tint"); -//static LLStaticHashedString sAmbiance("ambiance"); -//static LLStaticHashedString sAlphaScale("alpha_scale"); -static LLStaticHashedString sNormMat("norm_mat"); -//static LLStaticHashedString sOffset("offset"); +LLTrace::BlockTimerStatHandle FTM_RENDER_GEOMETRY("Geometry"); +LLTrace::BlockTimerStatHandle FTM_RENDER_GRASS("Grass"); +LLTrace::BlockTimerStatHandle FTM_RENDER_OCCLUSION("Occlusion"); +LLTrace::BlockTimerStatHandle FTM_RENDER_SHINY("Shiny"); +LLTrace::BlockTimerStatHandle FTM_RENDER_SIMPLE("Simple"); +LLTrace::BlockTimerStatHandle FTM_RENDER_TERRAIN("Terrain"); +LLTrace::BlockTimerStatHandle FTM_RENDER_TREES("Trees"); +LLTrace::BlockTimerStatHandle FTM_RENDER_UI("UI"); +LLTrace::BlockTimerStatHandle FTM_RENDER_WATER("Water"); +LLTrace::BlockTimerStatHandle FTM_RENDER_WL_SKY("Windlight Sky"); +LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA("Alpha Objects"); +LLTrace::BlockTimerStatHandle FTM_RENDER_CHARACTERS("Avatars"); +LLTrace::BlockTimerStatHandle FTM_RENDER_BUMP("Bump"); +LLTrace::BlockTimerStatHandle FTM_RENDER_MATERIALS("Materials"); +LLTrace::BlockTimerStatHandle FTM_RENDER_FULLBRIGHT("Fullbright"); +LLTrace::BlockTimerStatHandle FTM_RENDER_GLOW("Glow"); +LLTrace::BlockTimerStatHandle FTM_GEO_UPDATE("Geo Update"); +LLTrace::BlockTimerStatHandle FTM_PIPELINE_CREATE("Pipeline Create"); +LLTrace::BlockTimerStatHandle FTM_POOLRENDER("RenderPool"); +LLTrace::BlockTimerStatHandle FTM_POOLS("Pools"); +LLTrace::BlockTimerStatHandle FTM_DEFERRED_POOLRENDER("RenderPool (Deferred)"); +LLTrace::BlockTimerStatHandle FTM_DEFERRED_POOLS("Pools (Deferred)"); +LLTrace::BlockTimerStatHandle FTM_POST_DEFERRED_POOLRENDER("RenderPool (Post)"); +LLTrace::BlockTimerStatHandle FTM_POST_DEFERRED_POOLS("Pools (Post)"); +LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM_FBO("First FBO"); +LLTrace::BlockTimerStatHandle FTM_STATESORT("Sort Draw State"); +LLTrace::BlockTimerStatHandle FTM_PIPELINE("Pipeline"); +LLTrace::BlockTimerStatHandle FTM_CLIENT_COPY("Client Copy"); +LLTrace::BlockTimerStatHandle FTM_RENDER_DEFERRED("Deferred Shading"); + + +static LLTrace::BlockTimerStatHandle FTM_STATESORT_DRAWABLE("Sort Drawables"); +static LLTrace::BlockTimerStatHandle FTM_STATESORT_POSTSORT("Post Sort"); + static LLStaticHashedString sDelta("delta"); static LLStaticHashedString sDistFactor("dist_factor"); -static LLStaticHashedString sKern("kern"); -static LLStaticHashedString sKernScale("kern_scale"); //---------------------------------------- std::string gPoolNames[] = { // Correspond to LLDrawpool enum render type "NONE", - "POOL_SIMPLE", "POOL_GROUND", + "POOL_TERRAIN", + "POOL_SIMPLE", "POOL_FULLBRIGHT", "POOL_BUMP", "POOL_MATERIALS", - "POOL_TERRAIN", "POOL_TREE", // Singu Note: Before sky for zcull. "POOL_ALPHA_MASK", "POOL_FULLBRIGHT_ALPHA_MASK", "POOL_SKY", "POOL_WL_SKY", "POOL_GRASS", - "POOL_INVISIBLE", "POOL_AVATAR", "POOL_VOIDWATER", "POOL_WATER", @@ -291,6 +290,8 @@ void glh_set_last_projection(const LLMatrix4a& mat) void display_update_camera(bool tiling=false); //---------------------------------------- +S32 LLPipeline::sCompiles = 0; + BOOL LLPipeline::sPickAvatar = TRUE; BOOL LLPipeline::sDynamicLOD = TRUE; BOOL LLPipeline::sShowHUDAttachments = TRUE; @@ -371,6 +372,7 @@ LLPipeline::LLPipeline() : mGroupQ1Locked(false), mGroupQ2Locked(false), mResetVertexBuffers(false), + mInRenderPass(false), mLastRebuildPool(NULL), mAlphaPool(NULL), mSkyPool(NULL), @@ -382,35 +384,19 @@ LLPipeline::LLPipeline() : mAlphaMaskPool(NULL), mFullbrightAlphaMaskPool(NULL), mFullbrightPool(NULL), - mInvisiblePool(NULL), mGlowPool(NULL), mBumpPool(NULL), mMaterialsPool(NULL), mWLSkyPool(NULL), mLightMask(0), - mLightMovingMask(0), - mLightingDetail(0) -{ - mNoiseMap = 0; - mTrueNoiseMap = 0; - mLightFunc = 0; -} + mLightMode(LIGHT_MODE_NORMAL) +{} void LLPipeline::init() { refreshCachedSettings(); - gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); - gOctreeReserveCapacity = llmin(gSavedSettings.getU32("OctreeReserveNodeCapacity"),U32(512)); - sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); - sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); - LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("ShyotlRenderUseStreamVBO"); - LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO") && gSavedSettings.getBOOL("VertexShaderEnable"); //Temporary workaround for vaos being broken when shaders are off - LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw"); - sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); - sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); - - mInitialized = TRUE; + mInitialized = true; stop_glerror(); @@ -421,7 +407,6 @@ void LLPipeline::init() getPool(LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK); getPool(LLDrawPool::POOL_GRASS); getPool(LLDrawPool::POOL_FULLBRIGHT); - getPool(LLDrawPool::POOL_INVISIBLE); getPool(LLDrawPool::POOL_BUMP); getPool(LLDrawPool::POOL_MATERIALS); getPool(LLDrawPool::POOL_GLOW); @@ -467,19 +452,20 @@ void LLPipeline::init() mBackfaceCull = TRUE; stop_glerror(); - + // Enable features - + LLViewerShaderMgr::instance()->setShaders(); stop_glerror(); + for (U32 i = 0; i < 2; ++i) { mSpotLightFade[i] = 1.f; } - setLightingDetail(-1); + updateLocalLightingEnabled(); gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("RenderUseFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); @@ -553,8 +539,6 @@ void LLPipeline::cleanup() mSimplePool = NULL; delete mFullbrightPool; mFullbrightPool = NULL; - delete mInvisiblePool; - mInvisiblePool = NULL; delete mGlowPool; mGlowPool = NULL; delete mBumpPool; @@ -572,6 +556,7 @@ void LLPipeline::cleanup() mInitialized = FALSE; mAuxScreenRectVB = NULL; + mCubeVB = NULL; } @@ -585,7 +570,7 @@ void LLPipeline::destroyGL() resetDrawOrders(); - resetVertexBuffers(); + releaseVertexBuffers(); releaseGLBuffers(); @@ -606,7 +591,7 @@ void LLPipeline::destroyGL() } } -static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); +static LLTrace::BlockTimerStatHandle FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); //static void LLPipeline::throttleNewMemoryAllocation(BOOL disable) @@ -628,7 +613,7 @@ void LLPipeline::throttleNewMemoryAllocation(BOOL disable) void LLPipeline::resizeScreenTexture() { - LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE); + LL_RECORD_BLOCK_TIME(FTM_RESIZE_SCREEN_TEXTURE); if (LLGLSLShader::sNoFixedFunction && assertInitialized()) { GLuint resX = gViewerWindow->getWorldViewWidthRaw(); @@ -672,7 +657,7 @@ void LLPipeline::allocatePhysicsBuffer() if (mPhysicsDisplay.getWidth() != resX || mPhysicsDisplay.getHeight() != resY) { - mPhysicsDisplay.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + mPhysicsDisplay.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_TEXTURE, FALSE); } } @@ -722,7 +707,6 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY) // - on failure, shrink number of samples and try again // - if not multisampled, shrink resolution and try again (favor X resolution over Y) // Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state - eFBOStatus ret = FBO_SUCCESS_FULLRES; if (!allocateScreenBuffer(resX, resY, samples)) { @@ -781,6 +765,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) mSampleBuffer.release(); mScreen.release(); + mFinalScreen.release(); mDeferredDownsampledDepth.release(); @@ -795,9 +780,8 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) const U32 occlusion_divisor = 3; //allocate deferred rendering color buffers - if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; - if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; - if (!mOcclusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; + if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_TEXTURE, FALSE)) return false; + if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) return false; if (!addDeferredAttachments(mDeferredScreen)) return false; GLuint screenFormat = GL_RGBA16; @@ -811,7 +795,8 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) screenFormat = GL_RGBA16F_ARB; } - if (!mScreen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; + if (!mScreen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) return false; + if (!mFinalScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) return false; if (samples > 0) { if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) return false; @@ -823,11 +808,11 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0) { //only need mDeferredLight for shadows OR ssao OR dof OR fxaa - if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; + if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) return false; if(ssao) { F32 scale = llclamp(RenderSSAOResolutionScale.get(),.01f,1.f); - if( scale < 1.f && !mDeferredDownsampledDepth.allocate(llceil(F32(resX)*scale), llceil(F32(resY)*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE) ) return false; + if( scale < 1.f && !mDeferredDownsampledDepth.allocate(llceil(F32(resX)*scale), llceil(F32(resY)*scale), 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE, FALSE) ) return false; } } else @@ -843,7 +828,6 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) for (U32 i = 0; i < 4; i++) { if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false; - if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false; } } else @@ -851,7 +835,6 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) for (U32 i = 0; i < 4; i++) { mShadow[i].release(); - mShadowOcclusion[i].release(); } } @@ -864,7 +847,6 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) for (U32 i = 4; i < 6; i++) { if (!mShadow[i].allocate(spot_shadow_map_width, height, 0, TRUE, FALSE)) return false; - if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE)) return false; } } else @@ -872,7 +854,6 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) for (U32 i = 4; i < 6; i++) { mShadow[i].release(); - mShadowOcclusion[i].release(); } } @@ -889,19 +870,18 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) for (U32 i = 0; i < 6; i++) { mShadow[i].release(); - mShadowOcclusion[i].release(); } mFXAABuffer.release(); mScreen.release(); + mFinalScreen.release(); mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first mDeferredDepth.release(); mDeferredDownsampledDepth.release(); - mOcclusionDepth.release(); - if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; + if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_TEXTURE, FALSE)) return false; if(samples > 1 && mScreen.getFBO()) { - if(mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples)) + if(mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_TEXTURE,FALSE,samples)) mScreen.setSampleBuffer(&mSampleBuffer); else { @@ -915,6 +895,8 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (LLPipeline::sRenderDeferred) { //share depth buffer between deferred targets mDeferredScreen.shareDepthBuffer(mScreen); + mDeferredScreen.shareDepthBuffer(mFinalScreen); + //mDeferredScreen.shareDepthBuffer(mDeferredLight); /*for (U32 i = 0; i < 3; i++) { //share stencil buffer with screen space lightmap to stencil out sky if (mDeferredLight[i].getTexture(0)) @@ -949,6 +931,23 @@ bool LLPipeline::isRenderDeferredDesired() gSavedSettings.getBOOL("WindLightUseAtmosShaders"); } +//static +void LLPipeline::updateRenderDeferred() +{ + bool deferred = (bool(LLRenderTarget::sUseFBO && + LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && + LLPipeline::sRenderBump && + isRenderDeferredDesired())) && + !gUseWireframe; + + sRenderDeferred = deferred; + if (deferred) + { //must render glow when rendering deferred since post effect pass is needed to present any lighting at all + sRenderGlow = true; + } +} + + //static void LLPipeline::refreshCachedSettings() { @@ -958,6 +957,19 @@ void LLPipeline::refreshCachedSettings() LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible"); //LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate"); + gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); + gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize"); + gOctreeReserveCapacity = llmin(gSavedSettings.getU32("OctreeReserveNodeCapacity"), U32(512)); + LLPipeline::sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); + LLPipeline::sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); + LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("ShyotlRenderUseStreamVBO"); + LLVertexBuffer::sEnableVBOs = gSavedSettings.getBOOL("RenderVBOEnable"); + LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO") && gSavedSettings.getBOOL("VertexShaderEnable"); //Temporary workaround for vaos being broken when shaders are off + LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs;// && gSavedSettings.getBOOL("RenderVBOMappingDisable") ; //Temporary workaround for vbo mapping being straight up broken + LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw"); + LLPipeline::sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); + LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); + LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind"); LLPipeline::sUseOcclusion = (!gUseWireframe @@ -967,22 +979,73 @@ void LLPipeline::refreshCachedSettings() && gGLManager.mHasOcclusionQuery) ? 2 : 0; } -void LLPipeline::releaseGLBuffers() +void LLPipeline::releaseOcclusionBuffers() { - assertInitialized(); - - if (mNoiseMap) + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { - LLImageGL::deleteTextures(1, &mNoiseMap); - mNoiseMap = 0; + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + part->resetVertexBuffers(); + } + } + } +} +void LLPipeline::releaseVertexBuffers() +{ + mCubeVB = NULL; + mAuxScreenRectVB = NULL; + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + part->resetVertexBuffers(); + } + } } - if (mTrueNoiseMap) + resetDrawOrders(); + + gSky.resetVertexBuffers(); + + LLVOPartGroup::destroyGL(); + + if (LLPostProcess::instanceExists()) + LLPostProcess::getInstance()->destroyGL(); + + LLVOPartGroup::destroyGL(); + + //delete all name pool caches + LLGLNamePool::cleanupPools(); + + gGL.resetVertexBuffers(); + + LLVertexBuffer::cleanupClass(); + + if (LLVertexBuffer::sGLCount > 0) { - LLImageGL::deleteTextures(1, &mTrueNoiseMap); - mTrueNoiseMap = 0; + LL_WARNS() << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining. " << LLVertexBuffer::sCount << LL_ENDL; } + LLVertexBuffer::unbind(); +} + +void LLPipeline::releaseGLBuffers() +{ + assertInitialized(); + + mNoiseMap.reset(); + releaseLUTBuffers(); mWaterRef.release(); @@ -1004,33 +1067,24 @@ void LLPipeline::releaseGLBuffers() void LLPipeline::releaseLUTBuffers() { - if (mLightFunc) - { - LLImageGL::deleteTextures(1, &mLightFunc); - mLightFunc = 0; - } + mLightFunc.reset(); } void LLPipeline::releaseScreenBuffers() { mScreen.release(); + mFinalScreen.release(); mFXAABuffer.release(); mPhysicsDisplay.release(); mDeferredScreen.release(); mDeferredDepth.release(); mDeferredDownsampledDepth.release(); mDeferredLight.release(); - mOcclusionDepth.release(); - - //mHighlight.release(); for (U32 i = 0; i < 6; i++) { mShadow[i].release(); - mShadowOcclusion[i].release(); } - - mSampleBuffer.release(); } @@ -1099,36 +1153,20 @@ void LLPipeline::createGLBuffers() { if (!mNoiseMap) { - const U32 noiseRes = 128; - LLVector3 noise[noiseRes*noiseRes]; + std::array noise; F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f; - for (U32 i = 0; i < noiseRes*noiseRes; ++i) + for (auto& val : noise) { - noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f); - noise[i].normVec(); - noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; + val = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f); + val.normVec(); + val.mV[2] = ll_frand()*scaler+1.f-scaler/2.f; } - LLImageGL::generateTextures(1, &mNoiseMap); + mNoiseMap = LLImageGL::createTextureName(); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - - if (!mTrueNoiseMap) - { - const U32 noiseRes = 128; - F32 noise[noiseRes*noiseRes*3]; - for (U32 i = 0; i < noiseRes*noiseRes*3; i++) - { - noise[i] = ll_frand()*2.0-1.0; - } - - LLImageGL::generateTextures(1, &mTrueNoiseMap); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap->getTexName()); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, NOISE_MAP_RES, NOISE_MAP_RES, GL_RGB, GL_FLOAT, noise.data()); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } @@ -1189,9 +1227,9 @@ void LLPipeline::createLUTBuffers() // pix_format = GL_R32F; #endif - LLImageGL::generateTextures(1, &mLightFunc); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, pix_format, lightResX, lightResY, GL_RED, GL_FLOAT, ls, false); + mLightFunc = LLImageGL::createTextureName(); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc->getTexName()); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, pix_format, lightResX, lightResY, GL_RED, GL_FLOAT, ls); //LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_UNSIGNED_BYTE, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); @@ -1224,7 +1262,7 @@ void LLPipeline::restoreGL() } } - resetLocalLights(); //Default all gl light parameters. Fixes light brightness problems on fullscren toggle + updateLocalLightingEnabled(); //Default all gl light parameters. Fixes light brightness problems on fullscren toggle } BOOL LLPipeline::canUseWindLightShaders() const @@ -1261,43 +1299,18 @@ void LLPipeline::enableShadows(const BOOL enable_shadows) //should probably do something here to wrangle shadows.... } -S32 LLPipeline::getMaxLightingDetail() const -{ - /*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS) - { - return 3; - } - else*/ - { - return 1; - } -} - -S32 LLPipeline::setLightingDetail(S32 level) +void LLPipeline::updateLocalLightingEnabled() { refreshCachedSettings(); - if (level < 0) - { - if (gSavedSettings.getBOOL("RenderLocalLights")) - { - level = 1; - } - else - { - level = 0; - } - } - level = llclamp(level, 0, getMaxLightingDetail()); + static const LLCachedControl render_local_lights("RenderLocalLights", true); //Bugfix: If setshaders was called with RenderLocalLights off then enabling RenderLocalLights later will not work. Reloading shaders fixes this. - if (level != mLightingDetail) + if (render_local_lights != mLightingEnabled) { - mLightingDetail = level; + mLightingEnabled = render_local_lights; if (LLGLSLShader::sNoFixedFunction) LLViewerShaderMgr::instance()->setShaders(); } - - return mLightingDetail; } class LLOctreeDirtyTexture : public OctreeTraveler @@ -1395,10 +1408,6 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0) poolp = mFullbrightPool; break; - case LLDrawPool::POOL_INVISIBLE: - poolp = mInvisiblePool; - break; - case LLDrawPool::POOL_GLOW: poolp = mGlowPool; break; @@ -1458,6 +1467,7 @@ LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerTexture *tex0) return poolp; } + LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0); addPool( new_poolp ); @@ -1605,15 +1615,15 @@ void LLPipeline::allocDrawable(LLViewerObject *vobj) } -static LLFastTimer::DeclareTimer FTM_UNLINK("Unlink"); -static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_MOVE_LIST("Movelist"); -static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_SPATIAL_PARTITION("Spatial Partition"); -static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_LIGHT_SET("Light Set"); -//static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_HIGHLIGHT_SET("Highlight Set"); +static LLTrace::BlockTimerStatHandle FTM_UNLINK("Unlink"); +static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_MOVE_LIST("Movelist"); +static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_SPATIAL_PARTITION("Spatial Partition"); +static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_LIGHT_SET("Light Set"); +//static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_HIGHLIGHT_SET("Highlight Set"); void LLPipeline::unlinkDrawable(LLDrawable *drawable) { - LLFastTimer t(FTM_UNLINK); + LL_RECORD_BLOCK_TIME(FTM_UNLINK); assertInitialized(); @@ -1622,7 +1632,7 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) // Based on flags, remove the drawable from the queues that it's on. if (drawablep->isState(LLDrawable::ON_MOVE_LIST)) { - LLFastTimer t(FTM_REMOVE_FROM_MOVE_LIST); + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_MOVE_LIST); LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep); if (iter != mMovedList.end()) { @@ -1632,7 +1642,7 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) if (drawablep->getSpatialGroup()) { - LLFastTimer t(FTM_REMOVE_FROM_SPATIAL_PARTITION); + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_SPATIAL_PARTITION); if (!drawablep->getSpatialGroup()->getSpatialPartition()->remove(drawablep, drawablep->getSpatialGroup())) { #ifdef LL_RELEASE_FOR_DOWNLOAD @@ -1644,7 +1654,7 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) } { - LLFastTimer t(FTM_REMOVE_FROM_LIGHT_SET); + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_LIGHT_SET); mLights.erase(drawablep); for (light_set_t::iterator iter = mNearbyLights.begin(); @@ -1677,7 +1687,7 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) //static void LLPipeline::removeMutedAVsLights(LLVOAvatar* muted_avatar) { - LLFastTimer t(FTM_REMOVE_FROM_LIGHT_SET); + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_LIGHT_SET); for (light_set_t::iterator iter = gPipeline.mNearbyLights.begin(); iter != gPipeline.mNearbyLights.end();) { @@ -1713,7 +1723,7 @@ U32 LLPipeline::addObject(LLViewerObject *vobj) void LLPipeline::createObjects(F32 max_dtime) { - LLFastTimer ftm(FTM_PIPELINE_CREATE); + LL_RECORD_BLOCK_TIME(FTM_PIPELINE_CREATE); LLTimer update_timer; @@ -1777,6 +1787,8 @@ void LLPipeline::resetFrameStats() { assertInitialized(); + sCompiles = 0; + LLViewerStats::getInstance()->mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f); if (mBatchCount > 0) @@ -1891,12 +1903,12 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) } } -static LLFastTimer::DeclareTimer FTM_OCTREE_BALANCE("Balance Octree"); -static LLFastTimer::DeclareTimer FTM_UPDATE_MOVE("Update Move"); +static LLTrace::BlockTimerStatHandle FTM_OCTREE_BALANCE("Balance Octree"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_MOVE("Update Move"); void LLPipeline::updateMove() { - LLFastTimer t(FTM_UPDATE_MOVE); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_MOVE); static const LLCachedControl freeze_time("FreezeTime",false); if (freeze_time) @@ -1907,8 +1919,8 @@ void LLPipeline::updateMove() assertInitialized(); { - static LLFastTimer::DeclareTimer ftm("Retexture"); - LLFastTimer t(ftm); + static LLTrace::BlockTimerStatHandle ftm("Retexture"); + LL_RECORD_BLOCK_TIME(ftm); for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); iter != mRetexturedList.end(); ++iter) @@ -1923,14 +1935,14 @@ void LLPipeline::updateMove() } { - static LLFastTimer::DeclareTimer ftm("Moved List"); - LLFastTimer t(ftm); + static LLTrace::BlockTimerStatHandle ftm("Moved List"); + LL_RECORD_BLOCK_TIME(ftm); updateMovedList(mMovedList); } //balance octrees { - LLFastTimer ot(FTM_OCTREE_BALANCE); + LL_RECORD_BLOCK_TIME(FTM_OCTREE_BALANCE); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -2249,11 +2261,11 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& return res; } -static LLFastTimer::DeclareTimer FTM_CULL("Object Culling"); +static LLTrace::BlockTimerStatHandle FTM_CULL("Object Culling"); void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip, LLPlane* planep) { - LLFastTimer t(FTM_CULL); + LL_RECORD_BLOCK_TIME(FTM_CULL); grabReferences(result); @@ -2262,19 +2274,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl BOOL to_texture = LLPipeline::sUseOcclusion > 1 && !hasRenderType(LLPipeline::RENDER_TYPE_HUD) && LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && - LLGLSLShader::sNoFixedFunction && - sRenderGlow; + LLGLSLShader::sNoFixedFunction; if (to_texture) { - /*if (LLPipeline::sRenderDeferred) - { - mOcclusionDepth.bindTarget(); - } - else*/ - { - mScreen.bindTarget(); - } + mScreen.bindTarget(); } if (sUseOcclusion > 1) @@ -2290,9 +2294,9 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl gGLLastMatrix = NULL; gGL.loadMatrix(glh_get_last_modelview()); - LLGLDisable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - LLGLDisable stencil(GL_STENCIL_TEST); + LLGLDisable blend; + LLGLDisable test; + LLGLDisable stencil; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -2413,14 +2417,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl if (to_texture) { - /*if (LLPipeline::sRenderDeferred) - { - mOcclusionDepth.flush(); - } - else*/ - { - mScreen.flush(); - } + mScreen.flush(); } } @@ -2505,26 +2502,15 @@ void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& d dest.bindTarget(); dest.clear(GL_DEPTH_BUFFER_BIT); - if (source.getUsage() == LLTexUnit::TT_RECT_TEXTURE) - { - shader = &gDownsampleDepthRectProgram; - shader->bind(); - shader->uniform2f(sDelta, 1.f, 1.f); - shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, source.getWidth(), source.getHeight()); - } - else - { - shader = &gDownsampleDepthProgram; - shader->bind(); - shader->uniform2f(sDelta, 1.f/source.getWidth(), 1.f/source.getHeight()); - shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, 1.f, 1.f); - } + shader = &gDownsampleDepthProgram; + shader->bind(); + shader->uniform2f(sDelta, 1.f/source.getWidth(), 1.f/source.getHeight()); gGL.getTexUnit(0)->bind(scratch_space ? scratch_space : &source, TRUE); { LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } dest.flush(); @@ -2549,7 +2535,7 @@ void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderT void LLPipeline::doOcclusion(LLCamera& camera) { - if (LLGLSLShader::sNoFixedFunction && LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups()) + if (LLGLSLShader::sNoFixedFunction && LLPipeline::sUseOcclusion > 1 && !LLSpatialPartition::sTeleportRequested && sCull->hasOcclusionGroups()) { LLVertexBuffer::unbind(); @@ -2561,12 +2547,12 @@ void LLPipeline::doOcclusion(LLCamera& camera) { gGL.setColorMask(false, false); } - LLGLDisable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); + LLGLDisable blend; + LLGLDisable test; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLGLDepthTest depth(GL_TRUE, GL_FALSE); - LLGLDisable cull(GL_CULL_FACE); + LLGLDisable cull; bool bind_shader = LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShader == 0; @@ -2621,14 +2607,14 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) return update_complete; } -static LLFastTimer::DeclareTimer FTM_SEED_VBO_POOLS("Seed VBO Pool"); +static LLTrace::BlockTimerStatHandle FTM_SEED_VBO_POOLS("Seed VBO Pool"); -static LLFastTimer::DeclareTimer FTM_UPDATE_GL("Update GL"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_GL("Update GL"); void LLPipeline::updateGL() { { - LLFastTimer t(FTM_UPDATE_GL); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_GL); while (!LLGLUpdate::sGLQ.empty()) { LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); @@ -2639,7 +2625,7 @@ void LLPipeline::updateGL() } { //seed VBO Pools - LLFastTimer t(FTM_SEED_VBO_POOLS); + LL_RECORD_BLOCK_TIME(FTM_SEED_VBO_POOLS); LLVertexBuffer::seedPools(); } } @@ -2682,6 +2668,9 @@ void LLPipeline::clearRebuildGroups() iter != mGroupQ2.end(); ++iter) { LLSpatialGroup* group = *iter; + if (group == nullptr) { + LL_WARNS() << "Null spatial group in Pipeline::mGroupQ2." << LL_ENDL; + } // If the group contains HUD objects, save the group if (group->isHUDGroup()) @@ -2703,11 +2692,57 @@ void LLPipeline::clearRebuildGroups() mGroupQ2Locked = false; } -static LLFastTimer::DeclareTimer FTM_REBUILD_PRIORITY_GROUPS("Rebuild Priority Groups"); +void LLPipeline::clearRebuildDrawables() +{ + // Clear all drawables on the priority build queue, + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); + iter != mBuildQ1.end(); ++iter) + { + LLDrawable* drawablep = *iter; + if (drawablep && !drawablep->isDead()) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q2); + drawablep->clearState(LLDrawable::IN_REBUILD_Q1); + } + } + mBuildQ1.clear(); + + // clear drawables on the non-priority build queue + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin(); + iter != mBuildQ2.end(); ++iter) + { + LLDrawable* drawablep = *iter; + if (!drawablep->isDead()) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q2); + } + } + mBuildQ2.clear(); + + //clear all moving bridges + for (LLDrawable::drawable_vector_t::iterator iter = mMovedBridge.begin(); + iter != mMovedBridge.end(); ++iter) + { + LLDrawable *drawablep = *iter; + drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); + } + mMovedBridge.clear(); + + //clear all moving drawables + for (LLDrawable::drawable_vector_t::iterator iter = mMovedList.begin(); + iter != mMovedList.end(); ++iter) + { + LLDrawable *drawablep = *iter; + drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); + } + mMovedList.clear(); +} + +static LLTrace::BlockTimerStatHandle FTM_REBUILD_PRIORITY_GROUPS("Rebuild Priority Groups"); void LLPipeline::rebuildPriorityGroups() { - LLFastTimer t(FTM_REBUILD_PRIORITY_GROUPS); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_PRIORITY_GROUPS); LLTimer update_timer; assertInitialized(); @@ -2730,7 +2765,7 @@ void LLPipeline::rebuildPriorityGroups() } -static LLFastTimer::DeclareTimer FTM_REBUILD_GROUPS("Rebuild Groups"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_GROUPS("Rebuild Groups"); void LLPipeline::rebuildGroups() { @@ -2739,7 +2774,7 @@ void LLPipeline::rebuildGroups() return; } - LLFastTimer t(FTM_REBUILD_GROUPS); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_GROUPS); mGroupQ2Locked = true; // Iterate through some drawables on the non-priority build queue S32 size = (S32) mGroupQ2.size(); @@ -2778,12 +2813,12 @@ void LLPipeline::rebuildGroups() updateMovedList(mMovedBridge); } -void LLPipeline::updateGeom(F32 max_dtime) +void LLPipeline::updateGeom(F32 max_dtime, LLCamera& camera) { LLTimer update_timer; LLPointer drawablep; - LLFastTimer t(FTM_GEO_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_GEO_UPDATE); assertInitialized(); @@ -2818,6 +2853,11 @@ void LLPipeline::updateGeom(F32 max_dtime) } } + if (drawablep->isUnload()) + { + drawablep->unload(); + drawablep->clearState(LLDrawable::FOR_UNLOAD); + } if (updateDrawableGeom(drawablep, TRUE)) { drawablep->clearState(LLDrawable::IN_REBUILD_Q1); @@ -2840,7 +2880,7 @@ void LLPipeline::updateGeom(F32 max_dtime) S32 count = 0; - max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime); + max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, F32SecondsImplicit(max_dtime)); LLSpatialGroup* last_group = NULL; LLSpatialBridge* last_bridge = NULL; @@ -2879,6 +2919,9 @@ void LLPipeline::updateGeom(F32 max_dtime) } updateMovedList(mMovedBridge); + calcNearbyLights(camera); + mLightMode = LIGHT_MODE_NORMAL; + setupHWLights(); } void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera) @@ -2989,14 +3032,15 @@ void LLPipeline::markShift(LLDrawable *drawablep) } } -static LLFastTimer::DeclareTimer FTM_SHIFT_DRAWABLE("Shift Drawable"); -static LLFastTimer::DeclareTimer FTM_SHIFT_OCTREE("Shift Octree"); -static LLFastTimer::DeclareTimer FTM_SHIFT_HUD("Shift HUD"); +static LLTrace::BlockTimerStatHandle FTM_SHIFT_DRAWABLE("Shift Drawable"); +static LLTrace::BlockTimerStatHandle FTM_SHIFT_OCTREE("Shift Octree"); +static LLTrace::BlockTimerStatHandle FTM_SHIFT_HUD("Shift HUD"); void LLPipeline::shiftObjects(const LLVector3 &offset) { assertInitialized(); + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT); gDepthDirty = TRUE; @@ -3004,7 +3048,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) offseta.load3(offset.mV); { - LLFastTimer t(FTM_SHIFT_DRAWABLE); + LL_RECORD_BLOCK_TIME(FTM_SHIFT_DRAWABLE); for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); iter != mShiftList.end(); iter++) { @@ -3020,7 +3064,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) } { - LLFastTimer t(FTM_SHIFT_OCTREE); + LL_RECORD_BLOCK_TIME(FTM_SHIFT_OCTREE); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { @@ -3037,7 +3081,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) } { - LLFastTimer t(FTM_SHIFT_HUD); + LL_RECORD_BLOCK_TIME(FTM_SHIFT_HUD); LLHUDText::shiftAll(offset); LLHUDNameTag::shiftAll(offset); } @@ -3071,10 +3115,10 @@ void LLPipeline::markPartitionMove(LLDrawable* drawable) } } -static LLFastTimer::DeclareTimer FTM_PROCESS_PARTITIONQ("PartitionQ"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_PARTITIONQ("PartitionQ"); void LLPipeline::processPartitionQ() { - LLFastTimer t(FTM_PROCESS_PARTITIONQ); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_PARTITIONQ); for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter) { LLDrawable* drawable = *iter; @@ -3167,7 +3211,7 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f } } -static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order"); +static LLTrace::BlockTimerStatHandle FTM_RESET_DRAWORDER("Reset Draw Order"); void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { @@ -3181,11 +3225,11 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) LLPipeline::END_RENDER_TYPES)) { //clear faces from face pools - LLFastTimer t(FTM_RESET_DRAWORDER); + LL_RECORD_BLOCK_TIME(FTM_RESET_DRAWORDER); gPipeline.resetDrawOrders(); } - LLFastTimer ftm(FTM_STATESORT); + LL_RECORD_BLOCK_TIME(FTM_STATESORT); //LLVertexBuffer::unbind(); @@ -3270,7 +3314,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } { - LLFastTimer ftm(FTM_STATESORT_DRAWABLE); + LL_RECORD_BLOCK_TIME(FTM_STATESORT_DRAWABLE); for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { @@ -3415,8 +3459,9 @@ void forAllDrawables(LLCullResult::sg_iterator begin, { for (LLCullResult::sg_iterator i = begin; i != end; ++i) { - OctreeGuard guard((*i)->getOctreeNode()); - for (LLSpatialGroup::element_iter j = (*i)->getDataBegin(); j != (*i)->getDataEnd(); ++j) + LLSpatialGroup* group = (*i).get(); + OctreeGuard guard(group->getOctreeNode()); + for (LLSpatialGroup::element_iter j = group->getDataBegin(); j != group->getDataEnd(); ++j) { func((LLDrawable*)(*j)->getDrawable()); } @@ -3618,7 +3663,7 @@ void updateParticleActivity(LLDrawable *drawablep); void LLPipeline::postSort(LLCamera& camera) { - LLFastTimer ftm(FTM_STATESORT_POSTSORT); + LL_RECORD_BLOCK_TIME(FTM_STATESORT_POSTSORT); assertInitialized(); @@ -3876,13 +3921,12 @@ void LLPipeline::postSort(LLCamera& camera) void render_hud_elements() { - LLFastTimer t(FTM_RENDER_UI); - gPipeline.disableLights(); + LL_RECORD_BLOCK_TIME(FTM_RENDER_UI); - LLGLDisable fog(GL_FOG); + LLGLDisable fog; LLGLSUIDefault gls_ui; - LLGLEnable stencil(GL_STENCIL_TEST); + LLGLEnable stencil; glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF); glStencilMask(0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); @@ -3898,7 +3942,7 @@ void render_hud_elements() if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { static const LLCachedControl RenderFSAASamples("RenderFSAASamples",0); - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + LLGLEnable multisample(RenderFSAASamples > 0); gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d() // Draw the tracking overlays @@ -3997,8 +4041,9 @@ void LLPipeline::renderHighlights() // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) // Render highlighted faces. LLGLSPipelineAlpha gls_pipeline_alpha; - LLGLEnable color_mat(GL_COLOR_MATERIAL); - disableLights(); + LLGLEnable color_mat; + LLGLState light_state; + gPipeline.disableLights(light_state); // Singu Note: Logic here changed, and behavior changed as well. Always draw overlays of some nature over all selected faces. // Faces that wont undergo any change if the current active channel is edited should have a 'faded' overlay @@ -4030,7 +4075,7 @@ U32 LLPipeline::sCurRenderPoolType = 0 ; extern void check_blend_funcs(); void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) { - LLFastTimer t(FTM_RENDER_GEOMETRY); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY); assertInitialized(); @@ -4056,9 +4101,9 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLVertexBuffer::unbind(); // Do verification of GL state - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + LLGLStateValidator::checkClientArrays(); if (mRenderDebugMask & RENDER_DEBUG_VERIFY) { if (!verify()) @@ -4079,21 +4124,17 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLGLSPipeline gls_pipeline; static const LLCachedControl RenderFSAASamples("RenderFSAASamples",0); - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + LLGLEnable multisample(RenderFSAASamples > 0); - LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2); + LLGLEnable gls_color_material; // Toggle backface culling for debugging - LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0); - // Set fog + LLGLEnable cull_face(mBackfaceCull); + + // Set fog only if not using shaders and is underwater render. BOOL use_fog = hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG); - LLGLEnable fog_enable(use_fog && - !gPipeline.canUseWindLightShadersOnObjects() ? GL_FOG : 0); + LLGLEnable fog_enable(use_fog && sUnderWaterRender && !LLGLSLShader::sNoFixedFunction); gSky.updateFog(camera.getFar()); - if (!use_fog) - { - sUnderWaterRender = FALSE; - } gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sDefaultImagep); LLViewerFetchedTexture::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP); @@ -4117,15 +4158,15 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) } { - LLFastTimer t(FTM_POOLS); + LL_RECORD_BLOCK_TIME(FTM_POOLS); // HACK: don't calculate local lights if we're rendering the HUD! // Removing this check will cause bad flickering when there are // HUD elements being rendered AND the user is in flycam mode -nyx if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { - calcNearbyLights(camera); - setupHWLights(NULL); + updateHWLightMode(LIGHT_MODE_NORMAL); + llassert(LLGLState::checkEnabled()); } BOOL occlude = sUseOcclusion > 1; @@ -4153,7 +4194,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0) { - LLFastTimer t(FTM_POOLRENDER); + LL_RECORD_BLOCK_TIME(FTM_POOLRENDER); gGLLastMatrix = NULL; gGL.loadMatrix(glh_get_current_modelview()); @@ -4162,6 +4203,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) { LLVertexBuffer::unbind(); if(gDebugGL)check_blend_funcs(); + mInRenderPass = true; poolp->beginRenderPass(i); for (iter2 = iter1; iter2 != mPools.end(); iter2++) { @@ -4173,14 +4215,15 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) p->render(i); } poolp->endRenderPass(i); + clearRenderPassStates(); if(gDebugGL)check_blend_funcs(); LLVertexBuffer::unbind(); if (gDebugGL) { std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i); - LLGLState::checkStates(msg); - //LLGLState::checkTextureChannels(msg); - //LLGLState::checkClientArrays(msg); + LLGLStateValidator::checkStates(msg); + //LLGLStateValidator::checkTextureChannels(msg); + //LLGLStateValidator::checkClientArrays(msg); } } } @@ -4218,17 +4261,17 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) } LLVertexBuffer::unbind(); - LLGLState::checkStates(); - //LLGLState::checkTextureChannels(); - //LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + //LLGLStateValidator::checkTextureChannels(); + //LLGLStateValidator::checkClientArrays(); //stop_glerror(); - //LLGLState::checkStates(); - //LLGLState::checkTextureChannels(); - //LLGLState::checkClientArrays(); + //LLGLStateValidator::checkStates(); + //LLGLStateValidator::checkTextureChannels(); + //LLGLStateValidator::checkClientArrays(); if (!LLPipeline::sImpostorRender) { @@ -4281,21 +4324,21 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLVertexBuffer::unbind(); - LLGLState::checkStates(); - //LLGLState::checkTextureChannels(); - //LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + //LLGLStateValidator::checkTextureChannels(); + //LLGLStateValidator::checkClientArrays(); } void LLPipeline::renderGeomDeferred(LLCamera& camera) { LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred"); - LLFastTimer t(FTM_RENDER_GEOMETRY); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY); - LLFastTimer t2(FTM_DEFERRED_POOLS); + LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS); - LLGLEnable cull(GL_CULL_FACE); + LLGLEnable cull; - LLGLEnable stencil(GL_STENCIL_TEST); + LLGLEnable stencil; glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); stop_glerror(); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); @@ -4310,14 +4353,14 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) } } - static const LLCachedControl fsaa_samples("RenderFSAASamples",0); - LLGLEnable multisample(fsaa_samples > 0 ? GL_MULTISAMPLE_ARB : 0); + static const LLCachedControl RenderFSAASamples("RenderFSAASamples",0); + LLGLEnable multisample(RenderFSAASamples > 0); LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + //LLGLStateValidator::checkStates(); + //LLGLStateValidator::checkTextureChannels(); + //LLGLStateValidator::checkClientArrays(); U32 cur_type = 0; @@ -4334,7 +4377,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) { - LLFastTimer t(FTM_DEFERRED_POOLRENDER); + LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLRENDER); gGLLastMatrix = NULL; gGL.loadMatrix(glh_get_current_modelview()); @@ -4342,6 +4385,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ ) { LLVertexBuffer::unbind(); + mInRenderPass = true; poolp->beginDeferredPass(i); for (iter2 = iter1; iter2 != mPools.end(); iter2++) { @@ -4354,13 +4398,14 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) p->renderDeferred(i); } poolp->endDeferredPass(i); + clearRenderPassStates(); LLVertexBuffer::unbind(); if (gDebugGL || gDebugPipeline) { - LLGLState::checkStates(); - //LLGLState::checkTextureChannels(); - //LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + //LLGLStateValidator::checkTextureChannels(); + //LLGLStateValidator::checkClientArrays(); } } } @@ -4388,16 +4433,15 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion) { - LLFastTimer t(FTM_POST_DEFERRED_POOLS); + LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLS); U32 cur_type = 0; - LLGLEnable cull(GL_CULL_FACE); + LLGLEnable cull; static const LLCachedControl RenderFSAASamples("RenderFSAASamples",0); - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + LLGLEnable multisample(RenderFSAASamples > 0); - calcNearbyLights(camera); - setupHWLights(NULL); + updateHWLightMode(LIGHT_MODE_NORMAL); gGL.setColorMask(true, false); @@ -4416,14 +4460,14 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion) gGLLastMatrix = NULL; gGL.loadMatrix(glh_get_current_modelview()); LLGLSLShader::bindNoShader(); - doOcclusion(camera/*, mScreen, mOcclusionDepth, &mDeferredDepth*/); + doOcclusion(camera); gGL.setColorMask(true, false); } pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) { - LLFastTimer t(FTM_POST_DEFERRED_POOLRENDER); + LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLRENDER); gGLLastMatrix = NULL; gGL.loadMatrix(glh_get_current_modelview()); @@ -4431,6 +4475,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion) for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ ) { LLVertexBuffer::unbind(); + mInRenderPass = true; poolp->beginPostDeferredPass(i); for (iter2 = iter1; iter2 != mPools.end(); iter2++) { @@ -4443,11 +4488,12 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion) p->renderPostDeferred(i); } poolp->endPostDeferredPass(i); + clearRenderPassStates(); LLVertexBuffer::unbind(); if (gDebugGL || gDebugPipeline) { - LLGLState::checkStates(); + LLGLStateValidator::checkStates(); } } } @@ -4486,7 +4532,7 @@ void LLPipeline::renderGeomShadow(LLCamera& camera) { U32 cur_type = 0; - LLGLEnable cull(GL_CULL_FACE); + LLGLEnable cull; LLVertexBuffer::unbind(); @@ -4509,6 +4555,7 @@ void LLPipeline::renderGeomShadow(LLCamera& camera) for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ ) { LLVertexBuffer::unbind(); + mInRenderPass = true; poolp->beginShadowPass(i); for (iter2 = iter1; iter2 != mPools.end(); iter2++) { @@ -4521,9 +4568,10 @@ void LLPipeline::renderGeomShadow(LLCamera& camera) p->renderShadow(i); } poolp->endShadowPass(i); + clearRenderPassStates(); LLVertexBuffer::unbind(); - LLGLState::checkStates(); + LLGLStateValidator::checkStates(); } } else @@ -4644,7 +4692,7 @@ void LLPipeline::renderDebug() gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true); - glPointSize(8.f); + gGL.setPointSize(8.f); LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); gGL.begin(LLRender::POINTS); @@ -4668,8 +4716,7 @@ void LLPipeline::renderDebug() gGL.vertex3fv(blip.mPosition.mV); } gGL.end(); - gGL.flush(); - glPointSize(1.f); + gGL.setPointSize(1.f); if (LLGLSLShader::sNoFixedFunction) { @@ -4723,9 +4770,9 @@ void LLPipeline::renderDebug() { LLVertexBuffer::unbind(); - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; LLGLDepthTest depth(TRUE, FALSE); - LLGLDisable cull(GL_CULL_FACE); + LLGLDisable cull; gGL.color4f(1,1,1,1); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -4789,8 +4836,7 @@ void LLPipeline::renderDebug() //if (i == 0 || !mShadowFrustPoints[i].empty()) { //render visible point cloud - gGL.flush(); - glPointSize(8.f); + gGL.setPointSize(8.f); gGL.begin(LLRender::POINTS); F32* c = col+i*4; @@ -4803,8 +4849,7 @@ void LLPipeline::renderDebug() } gGL.end(); - gGL.flush(); - glPointSize(1.f); + gGL.setPointSize(1.f); LLVector3* ext = mShadowExtents[i]; LLVector3 pos = (ext[0]+ext[1])*0.5f; @@ -4897,7 +4942,7 @@ void LLPipeline::renderDebug() LLColor4 col; LLVertexBuffer::unbind(); - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.setSceneBlendType(LLRender::BT_ALPHA); LLGLDepthTest depth(GL_TRUE, GL_FALSE); gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); @@ -4954,11 +4999,11 @@ void LLPipeline::renderDebug() } } -static LLFastTimer::DeclareTimer FTM_REBUILD_POOLS("Rebuild Pools"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_POOLS("Rebuild Pools"); void LLPipeline::rebuildPools() { - LLFastTimer t(FTM_REBUILD_POOLS); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_POOLS); assertInitialized(); @@ -5059,18 +5104,6 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) } break; - case LLDrawPool::POOL_INVISIBLE: - if (mInvisiblePool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; - } - else - { - mInvisiblePool = (LLRenderPass*) new_poolp; - } - break; - case LLDrawPool::POOL_GLOW: if (mGlowPool) { @@ -5221,11 +5254,6 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) mFullbrightPool = NULL; break; - case LLDrawPool::POOL_INVISIBLE: - llassert(mInvisiblePool == poolp); - mInvisiblePool = NULL; - break; - case LLDrawPool::POOL_WL_SKY: llassert(mWLSkyPool == poolp); mWLSkyPool = NULL; @@ -5313,11 +5341,11 @@ void LLPipeline::resetDrawOrders() // Once-per-frame setup of hardware lights, // including sun/moon, avatar backlight, and up to 6 local lights -void LLPipeline::setupAvatarLights(BOOL for_edit) +U8 LLPipeline::setupFeatureLights(U8 cur_count) { - assertInitialized(); + //assertInitialized(); - if (for_edit) + if (mLightMode == LIGHT_MODE_EDIT) { LLColor4 diffuse(1.f, 1.f, 1.f, 0.f); LLVector4a light_pos_cam(-8.f, 0.25f, 10.f, 0.f); // w==0 => directional light @@ -5330,12 +5358,9 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) light_pos.normalize3fast(); - LLLightState* light = gGL.getLight(1); - - mHWLightColors[1] = diffuse; + LLLightState* light = gGL.getLight(cur_count++); light->setDiffuse(diffuse); - light->setAmbient(LLColor4::black); light->setSpecular(LLColor4::black); light->setPosition(LLVector4(light_pos.getF32ptr())); light->setConstantAttenuation(1.f); @@ -5344,7 +5369,7 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) light->setSpotExponent(0.f); light->setSpotCutoff(180.f); } - else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini) + else if (mLightMode == LIGHT_MODE_BACKLIGHT) // Always true (unless overridden in a devs .ini) { LLVector3 opposite_pos = -1.f * mSunDir; LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis; @@ -5372,13 +5397,10 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) } backlight_diffuse *= backlight_mag / max_component; - mHWLightColors[1] = backlight_diffuse; - - LLLightState* light = gGL.getLight(1); + LLLightState* light = gGL.getLight(cur_count++); light->setPosition(backlight_pos); light->setDiffuse(backlight_diffuse); - light->setAmbient(LLColor4::black); light->setSpecular(LLColor4::black); light->setConstantAttenuation(1.f); light->setLinearAttenuation(0.f); @@ -5386,16 +5408,69 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) light->setSpotExponent(0.f); light->setSpotCutoff(180.f); } - else + else if (mLightMode == LIGHT_MODE_PREVIEW) { - LLLightState* light = gGL.getLight(1); + static LLCachedControl PreviewAmbientColor("PreviewAmbientColor"); - mHWLightColors[1] = LLColor4::black; + LLColor4 ambient = PreviewAmbientColor; + gGL.setAmbientLightColor(ambient); - light->setDiffuse(LLColor4::black); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); + static LLCachedControl PreviewDiffuse0("PreviewDiffuse0"); + static LLCachedControl PreviewSpecular0("PreviewSpecular0"); + static LLCachedControl PreviewDiffuse1("PreviewDiffuse1"); + static LLCachedControl PreviewSpecular1("PreviewSpecular1"); + static LLCachedControl PreviewDiffuse2("PreviewDiffuse2"); + static LLCachedControl PreviewSpecular2("PreviewSpecular2"); + static LLCachedControl PreviewDirection0("PreviewDirection0"); + static LLCachedControl PreviewDirection1("PreviewDirection1"); + static LLCachedControl PreviewDirection2("PreviewDirection2"); + + LLColor4 diffuse0 = PreviewDiffuse0; + LLColor4 specular0 = PreviewSpecular0; + LLColor4 diffuse1 = PreviewDiffuse1; + LLColor4 specular1 = PreviewSpecular1; + LLColor4 diffuse2 = PreviewDiffuse2; + LLColor4 specular2 = PreviewSpecular2; + + LLVector3 dir0 = PreviewDirection0; + LLVector3 dir1 = PreviewDirection1; + LLVector3 dir2 = PreviewDirection2; + + dir0.normVec(); + dir1.normVec(); + dir2.normVec(); + + LLVector4 light_pos(dir0, 0.0f); + + LLLightState* light = gGL.getLight(cur_count++); + + light->enable(); + light->setPosition(light_pos); + light->setDiffuse(diffuse0); + light->setSpecular(specular0); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + + light_pos = LLVector4(dir1, 0.f); + + light = gGL.getLight(cur_count++); + light->enable(); + light->setPosition(light_pos); + light->setDiffuse(diffuse1); + light->setSpecular(specular1); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + + light_pos = LLVector4(dir2, 0.f); + light = gGL.getLight(cur_count++); + light->enable(); + light->setPosition(light_pos); + light->setDiffuse(diffuse2); + light->setSpecular(specular2); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); } + return cur_count; } static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist) @@ -5431,13 +5506,11 @@ static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_ //Default all gl light parameters. Used upon restoreGL. Fixes brightness problems on fullscren toggle void LLPipeline::resetLocalLights() { - if (!LLGLSLShader::sNoFixedFunction) - glEnable(GL_LIGHTING); - for (S32 i = 0; i < 8; ++i) + LLGLEnable enable; + for (S32 i = 0; i < LLRender::NUM_LIGHTS; ++i) { LLLightState *pLight = gGL.getLight(i); pLight->enable(); - pLight->setAmbient(LLColor4::black); pLight->setConstantAttenuation(0.f); pLight->setDiffuse(LLColor4::black); pLight->setLinearAttenuation(0.f); @@ -5449,8 +5522,6 @@ void LLPipeline::resetLocalLights() pLight->setSpotExponent(0.f); pLight->disable(); } - if (!LLGLSLShader::sNoFixedFunction) - glDisable(GL_LIGHTING); } void LLPipeline::calcNearbyLights(LLCamera& camera) @@ -5462,11 +5533,11 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) return; } - if (mLightingDetail >= 1) + if (isLocalLightingEnabled()) { // mNearbyLight (and all light_set_t's) are sorted such that // begin() == the closest light and rbegin() == the farthest light - const S32 MAX_LOCAL_LIGHTS = 6; + const S32 MAX_LOCAL_LIGHTS = 7; // LLVector3 cam_pos = gAgentCamera.getCameraPositionAgent(); LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ? camera.getOrigin() : @@ -5565,68 +5636,15 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) } } } - } + gatherLocalLights(); } -void LLPipeline::setupHWLights(LLDrawPool* pool) -{ - assertInitialized(); - - // Ambient - if (!LLGLSLShader::sNoFixedFunction) - { - gGL.syncMatrices(); - LLColor4 ambient = gSky.getTotalAmbientColor(); - gGL.setAmbientLightColor(ambient); - } - - // Light 0 = Sun or Moon (All objects) - { - if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS) - { - mSunDir.setVec(gSky.getSunDirection()); - mSunDiffuse.setVec(gSky.getSunDiffuseColor()); - } - else - { - mSunDir.setVec(gSky.getMoonDirection()); - mSunDiffuse.setVec(gSky.getMoonDiffuseColor()); - } - F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]); - if (max_color > 1.f) - { - mSunDiffuse *= 1.f/max_color; - } - mSunDiffuse.clamp(); - - LLVector4 light_pos(mSunDir, 0.0f); - LLColor4 light_diffuse = mSunDiffuse; - mHWLightColors[0] = light_diffuse; - - LLLightState* light = gGL.getLight(0); - light->setPosition(light_pos); - light->setDiffuse(light_diffuse); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); - light->setConstantAttenuation(1.f); - light->setLinearAttenuation(0.f); - light->setQuadraticAttenuation(0.f); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - } - - // Light 1 = Backlight (for avatars) - // (set by enableLightsAvatar) - - S32 cur_light = 2; - - // Nearby lights = LIGHT 2-7 - - mLightMovingMask = 0; - - if (mLightingDetail >= 1) +void LLPipeline::gatherLocalLights() +{ + mLocalLights.clear(); + if (isLocalLightingEnabled()) { for (light_set_t::iterator iter = mNearbyLights.begin(); iter != mNearbyLights.end(); ++iter) @@ -5637,11 +5655,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) { continue; } - if (drawable->isState(LLDrawable::ACTIVE)) - { - mLightMovingMask |= (1<getLightColor(); light_color.mV[3] = 0.0f; @@ -5671,23 +5685,19 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic? probably trying to match a historic behavior. float linatten = x / (light_radius); // % of brightness at radius - mHWLightColors[cur_light] = light_color; - LLLightState* light_state = gGL.getLight(cur_light); - - light_state->setPosition(light_pos_gl); - light_state->setDiffuse(light_color); - light_state->setAmbient(LLColor4::black); - light_state->setConstantAttenuation(0.f); + LLLightStateData light_state = LLLightStateData(); + light_state.mPosition = light_pos_gl; + light_state.mDiffuse = light_color; + light_state.mConstantAtten = 0.f; + if (sRenderDeferred) { - F32 size = light_radius*1.5f; - light_state->setLinearAttenuation(size); - light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f); + light_state.mLinearAtten = light_radius * 1.5f; + light_state.mQuadraticAtten = light->getLightFalloff()*0.5f + 1.f; } else { - light_state->setLinearAttenuation(linatten); - light_state->setQuadraticAttenuation(0.f); + light_state.mLinearAtten = linatten; } static const LLCachedControl RenderSpotLightsInNondeferred("RenderSpotLightsInNondeferred",false); @@ -5698,266 +5708,214 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction at_axis *= quat; - light_state->setSpotDirection(at_axis); - light_state->setSpotCutoff(90.f); - light_state->setSpotExponent(2.f); - - const LLColor4 specular(0.f, 0.f, 0.f, 0.f); - light_state->setSpecular(specular); + light_state.mSpotDirection = at_axis; + light_state.mSpotCutoff = 90.f; + light_state.mSpotExponent = 2.f; + light_state.mSpecular = LLColor4::transparent; } else // omnidirectional (point) light { - light_state->setSpotExponent(0.f); - light_state->setSpotCutoff(180.f); - // we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight - const LLColor4 specular(0.f, 0.f, 0.f, 1.f); - light_state->setSpecular(specular); - } - cur_light++; - if (cur_light >= 8) - { - break; // safety + light_state.mSpecular = LLColor4::black; } + mLocalLights.push_back(light_state); } } - for ( ; cur_light < 8 ; cur_light++) - { - mHWLightColors[cur_light] = LLColor4::black; - LLLightState* light = gGL.getLight(cur_light); +} - light->setDiffuse(LLColor4::black); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); +LLVector3 getSunDir() +{ + if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS) + { + return gSky.getSunDirection(); } - if (gAgentAvatarp && - gAgentAvatarp->mSpecialRenderMode == 3) + else { - LLColor4 light_color = LLColor4::white; - light_color.mV[3] = 0.0f; + return gSky.getMoonDirection(); + } +} + - LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin()); - LLVector4 light_pos_gl(light_pos, 1.0f); +extern U32 sLightMask; +void LLPipeline::setupHWLights() +{ + static LLCachedControl LightMask("LightMask", 0xFFFFFFFF); + sLightMask = LightMask; - F32 light_radius = 16.f; + // Ambient + if (mLightMode == LIGHT_MODE_PREVIEW) + { + static LLCachedControl PreviewAmbientColor("PreviewAmbientColor"); + LLColor4 ambient = PreviewAmbientColor; + gGL.setAmbientLightColor(ambient); + } + else if (!LLGLSLShader::sNoFixedFunction) + { + LLColor4 ambient = gSky.getTotalAmbientColor(); + gGL.setAmbientLightColor(ambient); + } - F32 x = 3.f; - float linatten = x / (light_radius); // % of brightness at radius + U8 cur_light = 0; + // Light 0 = Sun or Moon (All objects) + { + if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS) + { + mSunDir.setVec(gSky.getSunDirection()); + mSunDiffuse.setVec(gSky.getSunDiffuseColor()); + } + else + { + mSunDir.setVec(gSky.getMoonDirection()); + mSunDiffuse.setVec(gSky.getMoonDiffuseColor()); + } - mHWLightColors[2] = light_color; - LLLightState* light = gGL.getLight(2); + F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]); + if (max_color > 1.f) + { + mSunDiffuse *= 1.f/max_color; + } + mSunDiffuse.clamp(); - light->setPosition(light_pos_gl); - light->setDiffuse(light_color); - light->setAmbient(LLColor4::black); + LLVector4 light_pos(mSunDir, 0.0f); + LLColor4 light_diffuse = mSunDiffuse; + + LLLightState* light = gGL.getLight(cur_light++); + light->setPosition(light_pos); + light->setDiffuse(light_diffuse); light->setSpecular(LLColor4::black); + light->setConstantAttenuation(1.f); + light->setLinearAttenuation(0.f); light->setQuadraticAttenuation(0.f); - light->setConstantAttenuation(0.f); - light->setLinearAttenuation(linatten); light->setSpotExponent(0.f); light->setSpotCutoff(180.f); } - - // Init GL state - if (!LLGLSLShader::sNoFixedFunction) + + // Edit mode lights + cur_light = setupFeatureLights(cur_light); + + // Nearby lights + if (isLocalLightingEnabled()) + { + for (auto& local_light : mLocalLights) + { + gGL.getLight(cur_light++)->setState(local_light); + if (cur_light >= LLRender::NUM_LIGHTS) + break; + } + } + for (S32 i = cur_light; i < LLRender::NUM_LIGHTS; ++i) { - glDisable(GL_LIGHTING); + //gGL.getLight(cur_light++)->setState(LLLightStateData()); + gGL.getLight(i)->disable(); } - - for (S32 i = 0; i < 8; ++i) + /*for (S32 i = 0; i < LLRender::NUM_LIGHTS; ++i) { gGL.getLight(i)->disable(); } - mLightMask = 0; + mLightMask = 0;*/ + mHWLightCount = cur_light; } -void LLPipeline::enableLights(U32 mask) -{ - assertInitialized(); - if (mLightingDetail == 0) +void LLPipeline::updateHWLightMode(U8 mode) +{ + if (mLightMode != mode) { - mask &= 0xf003; // sun and backlight only (and fullbright bit) + mLightMode = mode; + setupHWLights(); } +} + +void LLPipeline::enableLights(U32 mask, LLGLState& light_state, const LLColor4* color) +{ if (mLightMask != mask) { stop_glerror(); if (!mLightMask) { - if (!LLGLSLShader::sNoFixedFunction) - { - glEnable(GL_LIGHTING); - } + light_state.enable(); } if (mask) { stop_glerror(); - for (S32 i=0; i<8; i++) + for (S32 i=0; i < LLRender::NUM_LIGHTS; i++) { LLLightState* light = gGL.getLight(i); - if (mask & (1<enable(); - light->setDiffuse(mHWLightColors[i]); } else { light->disable(); - light->setDiffuse(LLColor4::black); } } stop_glerror(); } else { - if (!LLGLSLShader::sNoFixedFunction) - { - glDisable(GL_LIGHTING); - } + light_state.disable(); } mLightMask = mask; stop_glerror(); - - LLColor4 ambient = gSky.getTotalAmbientColor(); - gGL.setAmbientLightColor(ambient); } + LLColor4 ambient = color ? *color : gSky.getTotalAmbientColor(); + gGL.setAmbientLightColor(ambient); } -void LLPipeline::enableLightsStatic() +void LLPipeline::enableLightsStatic(LLGLState& light_state) { - assertInitialized(); - U32 mask = 0x01; // Sun - if (mLightingDetail >= 2) - { - mask |= mLightMovingMask; // Hardware moving lights - } - else - { - mask |= 0xff & (~2); // Hardware local lights - } - enableLights(mask); + updateHWLightMode(LIGHT_MODE_NORMAL); + enableLights(0xFFFFFFFF, light_state); } -void LLPipeline::enableLightsDynamic() +void LLPipeline::enableLightsDynamic(LLGLState& light_state) { assertInitialized(); - U32 mask = 0xff & (~2); // Local lights - enableLights(mask); - if (isAgentAvatarValid() && getLightingDetail() <= 0) + if (isAgentAvatarValid() && !isLocalLightingEnabled()) { if (gAgentAvatarp->mSpecialRenderMode == 0) // normal { - gPipeline.enableLightsAvatar(); + gPipeline.enableLightsAvatar(light_state); + return; } else if (gAgentAvatarp->mSpecialRenderMode >= 1) // anim preview { - gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f)); + gPipeline.enableLightsAvatarEdit(light_state, LLColor4(0.7f, 0.6f, 0.3f, 1.f)); + return; } } + + updateHWLightMode(LIGHT_MODE_NORMAL); + enableLights(0xFFFFFFFF, light_state); } -void LLPipeline::enableLightsAvatar() +void LLPipeline::enableLightsAvatar(LLGLState& light_state) { - U32 mask = 0xff; // All lights - setupAvatarLights(FALSE); - enableLights(mask); + updateHWLightMode(gAvatarBacklight ? LIGHT_MODE_BACKLIGHT : LIGHT_MODE_NORMAL); // Avatar backlight only, set ambient + enableLights(0xFFFFFFFF, light_state); } -void LLPipeline::enableLightsPreview() +void LLPipeline::enableLightsPreview(LLGLState& light_state) { - disableLights(); - - if (!LLGLSLShader::sNoFixedFunction) - { - glEnable(GL_LIGHTING); - } - - static LLCachedControl PreviewAmbientColor("PreviewAmbientColor"); - - LLColor4 ambient = PreviewAmbientColor; - gGL.setAmbientLightColor(ambient); - - static LLCachedControl PreviewDiffuse0("PreviewDiffuse0"); - static LLCachedControl PreviewSpecular0("PreviewSpecular0"); - static LLCachedControl PreviewDiffuse1("PreviewDiffuse1"); - static LLCachedControl PreviewSpecular1("PreviewSpecular1"); - static LLCachedControl PreviewDiffuse2("PreviewDiffuse2"); - static LLCachedControl PreviewSpecular2("PreviewSpecular2"); - static LLCachedControl PreviewDirection0("PreviewDirection0"); - static LLCachedControl PreviewDirection1("PreviewDirection1"); - static LLCachedControl PreviewDirection2("PreviewDirection2"); - - LLColor4 diffuse0 = PreviewDiffuse0; - LLColor4 specular0 = PreviewSpecular0; - LLColor4 diffuse1 = PreviewDiffuse1; - LLColor4 specular1 = PreviewSpecular1; - LLColor4 diffuse2 = PreviewDiffuse2; - LLColor4 specular2 = PreviewSpecular2; - - LLVector3 dir0 = PreviewDirection0; - LLVector3 dir1 = PreviewDirection1; - LLVector3 dir2 = PreviewDirection2; - - dir0.normVec(); - dir1.normVec(); - dir2.normVec(); - - LLVector4 light_pos(dir0, 0.0f); - - LLLightState* light = gGL.getLight(1); - - light->enable(); - light->setPosition(light_pos); - light->setDiffuse(diffuse0); - light->setAmbient(LLColor4::black); - light->setSpecular(specular0); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - - light_pos = LLVector4(dir1, 0.f); - - light = gGL.getLight(2); - light->enable(); - light->setPosition(light_pos); - light->setDiffuse(diffuse1); - light->setAmbient(LLColor4::black); - light->setSpecular(specular1); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - - light_pos = LLVector4(dir2, 0.f); - light = gGL.getLight(3); - light->enable(); - light->setPosition(light_pos); - light->setDiffuse(diffuse2); - light->setAmbient(LLColor4::black); - light->setSpecular(specular2); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); + updateHWLightMode(LIGHT_MODE_PREVIEW); + enableLights(0xFFFFFFFF, light_state); } -void LLPipeline::enableLightsAvatarEdit(const LLColor4& color) +void LLPipeline::enableLightsAvatarEdit(LLGLState& light_state, const LLColor4& color) { - U32 mask = 0x2002; // Avatar backlight only, set ambient - setupAvatarLights(TRUE); - enableLights(mask); - - gGL.setAmbientLightColor(color); + updateHWLightMode(LIGHT_MODE_EDIT); + enableLights(0xFFFFFFFF, light_state, &color); } -void LLPipeline::enableLightsFullbright(const LLColor4& color) +void LLPipeline::enableLightsFullbright(LLGLState& light_state) { - assertInitialized(); - U32 mask = 0x1000; // Non-0 mask, set ambient - enableLights(mask); - - gGL.setAmbientLightColor(color); + enableLights(0, light_state); } -void LLPipeline::disableLights() +void LLPipeline::disableLights(LLGLState& light_state) { - enableLights(0); // no lighting (full bright) -// gGL.diffuseColor4f(1.f, 1.f, 1.f, 1.f); + enableLights(0, light_state); // no lighting (full bright) } //============================================================================ @@ -6437,6 +6395,7 @@ LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, LLVector4a local_end = end; LLVector4a position; + position.clear(); LLDrawable* drawable = NULL; @@ -6448,7 +6407,7 @@ LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE); if (part && hasRenderType(part->mDrawableType)) { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, face_hit, &position, NULL, NULL, NULL); + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, face_hit, &position, NULL, NULL, NULL); if (hit) { drawable = hit; @@ -6475,6 +6434,7 @@ LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, + bool pick_rigged, S32* face_hit, LLVector4a* intersection, // return the intersection point LLVector2* tex_coord, // return the texture coordinates of the intersection point @@ -6487,6 +6447,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, LLVector4a local_end = end; LLVector4a position; + position.clear(); sPickAvatar = FALSE; //LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE; @@ -6507,7 +6468,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, LLSpatialPartition* part = region->getSpatialPartition(j); if (part && hasRenderType(part->mDrawableType)) { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, tangent); + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent); if (hit) { drawable = hit; @@ -6564,7 +6525,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_ATTACHMENT); if (part && hasRenderType(part->mDrawableType)) { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, tangent); + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent); if (hit) { LLVector4a delta; @@ -6652,7 +6613,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector4a& start, c LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD); if (part) { - LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, tangent); + LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, face_hit, intersection, tex_coord, normal, tangent); if (hit) { drawable = hit; @@ -6699,71 +6660,46 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable) void LLPipeline::resetVertexBuffers() { + // Only set to true if pipeline has been initialized (No vbo's to reset, otherwise) + //if (mInitialized) mResetVertexBuffers = true; } -static LLFastTimer::DeclareTimer FTM_RESET_VB("Reset VB"); +static LLTrace::BlockTimerStatHandle FTM_RESET_VB("Reset VB"); -void LLPipeline::doResetVertexBuffers() +void LLPipeline::doResetVertexBuffers(bool forced) { - if (!mResetVertexBuffers) + if ( !mResetVertexBuffers) { return; } - - LLFastTimer t(FTM_RESET_VB); - mResetVertexBuffers = false; - - mCubeVB = NULL; - mAuxScreenRectVB = NULL; - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + if(!forced && LLSpatialPartition::sTeleportRequested) { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + if(gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - part->resetVertexBuffers(); - } + return; //wait for teleporting to finish + } + else + { + //teleporting aborted + LLSpatialPartition::sTeleportRequested = FALSE; + mResetVertexBuffers = false; + return; } } - resetDrawOrders(); - - gSky.resetVertexBuffers(); - - LLVOPartGroup::destroyGL(); - - if(LLPostProcess::instanceExists()) - LLPostProcess::getInstance()->destroyGL(); - - LLVOPartGroup::destroyGL(); - - LLVertexBuffer::cleanupClass(); - - //delete all name pool caches - LLGLNamePool::cleanupPools(); - - gGL.resetVertexBuffers(); - - if (LLVertexBuffer::sGLCount > 0) + LL_RECORD_BLOCK_TIME(FTM_RESET_VB); + mResetVertexBuffers = false; + releaseVertexBuffers(); + if(LLSpatialPartition::sTeleportRequested) { - LL_WARNS() << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining. " << LLVertexBuffer::sCount << LL_ENDL; - } + LLSpatialPartition::sTeleportRequested = FALSE; - LLVertexBuffer::unbind(); + LLWorld::getInstance()->clearAllVisibleObjects(); + clearRebuildDrawables(); + } - sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); - LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("ShyotlRenderUseStreamVBO"); - LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO") && LLGLSLShader::sNoFixedFunction; //Temporary workaround for vaos being broken when shaders are off - LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw"); - LLVertexBuffer::sEnableVBOs = gSavedSettings.getBOOL("RenderVBOEnable"); - LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs;// && gSavedSettings.getBOOL("RenderVBOMappingDisable") ; //Temporary workaround for vbo mapping being straight up broken - sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha"); - LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind"); + refreshCachedSettings(); LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping); @@ -6867,7 +6803,7 @@ void LLPipeline::bindScreenToTexture() } -static LLFastTimer::DeclareTimer FTM_RENDER_BLOOM("Bloom"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM("Bloom"); void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, bool tiling) { if (!(LLGLSLShader::sNoFixedFunction && @@ -6896,14 +6832,14 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b static const LLCachedControl RenderFSAASamples("RenderFSAASamples",0); LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); assertInitialized(); if (gUseWireframe) { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.setPolygonMode(LLRender::PF_FRONT_AND_BACK, LLRender::PM_FILL); } //U32 res_mod = RenderResolutionDivisor;//.get(); @@ -6913,13 +6849,14 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b tc2 /= (F32) res_mod; }*/ - LLFastTimer ftm(FTM_RENDER_BLOOM); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM); gGL.color4f(1,1,1,1); LLGLDepthTest depth(GL_FALSE); - LLGLDisable blend(GL_BLEND); - LLGLDisable cull(GL_CULL_FACE); + LLGLDisable blend; + LLGLDisable cull; - enableLightsFullbright(LLColor4(1,1,1,1)); + LLGLState light_state; + enableLightsFullbright(light_state); gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); @@ -6928,11 +6865,19 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGL.pushMatrix(); gGL.loadIdentity(); - LLGLDisable test(GL_ALPHA_TEST); + LLGLDisable test; gGL.setColorMask(true, true); glClearColor(0,0,0,0); + //static LLRender::Context sOldContext = LLRender::Context(); + //const LLRender::Context& newContext = gGL.getContextSnapshot(); + //if (memcmp(&sOldContext, &newContext, sizeof(LLRender::Context)) != 0) + //{ + //newContext.printDiff(sOldContext); + //} + //sOldContext = newContext; + if (tiling && !LLPipeline::sRenderDeferred) //Need to coax this into working with deferred now that tiling is back. { gGlowCombineProgram.bind(); @@ -6942,7 +6887,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b //LLGLEnable stencil(GL_STENCIL_TEST); //glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF); //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - //LLGLDisable blend(GL_BLEND); + //LLGLDisable blend; // If the snapshot is constructed from tiles, calculate which // tile we're in. @@ -6955,7 +6900,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b LLVector2 tc1 = tile*tile_size; // Top left texture coordinates LLVector2 tc2 = (tile+LLVector2(1,1))*tile_size; // Bottom right texture coordinates - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.setSceneBlendType(LLRender::BT_ADD); LLPointer buff = new LLVertexBuffer(AUX_VB_MASK, 0); @@ -6998,7 +6943,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b { { - LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); mGlow[1].bindTarget(); mGlow[1].clear(); } @@ -7016,19 +6961,21 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]); gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]); gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount); - LLGLEnable blend_on(GL_BLEND); - LLGLEnable test(GL_ALPHA_TEST); + LLGLEnable blend_on; + LLGLEnable test; gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); - - mScreen.bindTexture(0, 0); + + LLRenderTarget& render_target = LLPipeline::sRenderDeferred ? mFinalScreen : mScreen; + render_target.bindTexture(0, 0); gGL.color4f(1,1,1,1); - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + LLGLState light_state; + gPipeline.enableLightsFullbright(light_state); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + drawFullScreenRect(); - gGL.getTexUnit(0)->unbind(mScreen.getUsage()); + gGL.getTexUnit(0)->unbind(render_target.getUsage()); mGlow[1].flush(); } @@ -7054,7 +7001,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b for (S32 i = 0; i < kernel; i++) { { - LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); mGlow[i%2].bindTarget(); mGlow[i%2].clear(); } @@ -7070,7 +7017,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta); } - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD1); + drawFullScreenRect(); mGlow[i%2].flush(); } @@ -7079,15 +7026,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b /*if (LLRenderTarget::sUseFBO) { - LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); glBindFramebuffer(GL_FRAMEBUFFER, 0); }*/ - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + gGLViewport = gViewerWindow->getWorldViewRectRaw(); + gGL.setViewport(gGLViewport); gGL.flush(); @@ -7108,7 +7052,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b if (dof_enabled) { LLGLSLShader* shader = &gDeferredPostProgram; - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; //depth of field focal plane calculations static F32 current_distance = 16.f; @@ -7142,7 +7086,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b LLVector4a result; result.clear(); - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, NULL, &result); @@ -7215,13 +7159,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b mDeferredLight.bindTarget(); shader = &gDeferredCoFProgram; - bindDeferredShader(*shader); - - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); - if (channel > -1) - { - mScreen.bindTexture(0, channel); - } + bindDeferredShader(*shader, &mFinalScreen); shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f); shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant); @@ -7230,9 +7168,9 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + drawFullScreenRect(); - unbindDeferredShader(*shader); + unbindDeferredShader(*shader, &mFinalScreen); mDeferredLight.flush(); } @@ -7240,50 +7178,41 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b U32 dof_height = (U32) (mScreen.getHeight()*CameraDoFResScale); { //perform DoF sampling at half-res (preserve alpha channel) - mScreen.bindTarget(); - glViewport(0,0, dof_width, dof_height); + mFinalScreen.bindTarget(); + gGL.setViewport(0,0, dof_width, dof_height); gGL.setColorMask(true, false); shader = &gDeferredPostProgram; - bindDeferredShader(*shader); - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage()); - if (channel > -1) - { - mDeferredLight.bindTexture(0, channel); - } + bindDeferredShader(*shader, &mDeferredLight); shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + drawFullScreenRect(); - unbindDeferredShader(*shader); - mScreen.flush(); + unbindDeferredShader(*shader, &mDeferredLight); + mFinalScreen.flush(); gGL.setColorMask(true, true); } { //combine result based on alpha if (multisample) { - mDeferredLight.bindTarget(); - glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); + mScreen.bindTarget(); + gGL.setViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); } else { - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + gGLViewport = gViewerWindow->getWorldViewRectRaw(); + gGL.setViewport(gGLViewport); } shader = &gDeferredDoFCombineProgram; - bindDeferredShader(*shader); + bindDeferredShader(*shader, &mFinalScreen); S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); if (channel > -1) { - mScreen.bindTexture(0, channel); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); } @@ -7296,21 +7225,21 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); - shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width-1); - shader->uniform1f(LLShaderMgr::DOF_HEIGHT, dof_height-1); + shader->uniform1f(LLShaderMgr::DOF_WIDTH, CameraDoFResScale - CameraDoFResScale / dof_width); + shader->uniform1f(LLShaderMgr::DOF_HEIGHT, CameraDoFResScale - CameraDoFResScale / dof_height); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + drawFullScreenRect(); if (channel > -1) { gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - unbindDeferredShader(*shader); + unbindDeferredShader(*shader, &mFinalScreen); if (multisample) { - mDeferredLight.flush(); + mScreen.flush(); } } } @@ -7322,12 +7251,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b } LLGLSLShader* shader = &gDeferredPostNoDoFProgram; - bindDeferredShader(*shader); + bindDeferredShader(*shader, &mFinalScreen); S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); if (channel > -1) { - mScreen.bindTexture(0, channel); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); } @@ -7338,14 +7266,14 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0f); } - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + drawFullScreenRect(); if (channel > -1) { gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - unbindDeferredShader(*shader); + unbindDeferredShader(*shader, &mFinalScreen); if (multisample) { @@ -7358,26 +7286,29 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b //bake out texture2D with RGBL for FXAA shader mFXAABuffer.bindTarget(); - S32 width = mScreen.getWidth(); - S32 height = mScreen.getHeight(); - glViewport(0, 0, width, height); + LLRenderTarget& render_target = dof_enabled ? mScreen : mDeferredLight; + S32 width = render_target.getWidth(); + S32 height = render_target.getHeight(); + gGL.setViewport(0, 0, width, height); LLGLSLShader* shader = &gGlowCombineFXAAProgram; - shader->bind(); - shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height); + bindDeferredShader(*shader, &render_target); - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage()); + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, render_target.getUsage()); if (channel > -1) { - mDeferredLight.bindTexture(0, channel); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); } - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); - shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage()); - shader->unbind(); + if (channel > -1) + { + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + unbindDeferredShader(*shader, &render_target); mFXAABuffer.flush(); @@ -7391,20 +7322,14 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); } - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - - F32 scale_x = (F32) width/mFXAABuffer.getWidth(); - F32 scale_y = (F32) height/mFXAABuffer.getHeight(); - shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y); - shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f/width*scale_x, 1.f/height*scale_y); - shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f/width*scale_x, -0.5f/height*scale_y, 0.5f/width*scale_x, 0.5f/height*scale_y); - shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f/width*scale_x, -2.f/height*scale_y, 2.f/width*scale_x, 2.f/height*scale_y); + gGLViewport = gViewerWindow->getWorldViewRectRaw(); + gGL.setViewport(gGLViewport); + + shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f/width, 1.f/height); + shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f/width, -0.5f/height, 0.5f/width, 0.5f/height); + shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f/width, -2.f/height, 2.f/width, 2.f/height); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); shader->unbind(); } @@ -7416,7 +7341,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b tc2 /= (F32) res_mod; }*/ - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; if (LLGLSLShader::sNoFixedFunction) { @@ -7433,9 +7358,9 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGL.getTexUnit(0)->bind(&mGlow[1]); gGL.getTexUnit(1)->bind(&mScreen); - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + LLGLEnable multisample(RenderFSAASamples > 0); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1); + drawFullScreenRect(); if (LLGLSLShader::sNoFixedFunction) { @@ -7463,12 +7388,20 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGL.setColorMask(true, false); - LLGLEnable blend(GL_BLEND); + LLGLEnable blend; gGL.color4f(1,1,1,0.75f); gGL.getTexUnit(0)->bind(&mPhysicsDisplay); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + gGL.begin(LLRender::TRIANGLES); + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2f(-1.f, -1.f); + gGL.texCoord2f(0.f,2.f); + gGL.vertex2f(-1.f, 3.f); + gGL.texCoord2f(2.f, 0.f); + gGL.vertex2f( 3.f, -1.f); + gGL.end(); + gGL.flush(); if (LLGLSLShader::sNoFixedFunction) { @@ -7491,16 +7424,21 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); } -static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred"); +static LLTrace::BlockTimerStatHandle FTM_BIND_DEFERRED("Bind Deferred"); -void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 noise_map) +void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* diffuse_source, LLRenderTarget* light_source) { - LLFastTimer t(FTM_BIND_DEFERRED); + if (shader.mShaderClass != LLViewerShaderMgr::SHADER_DEFERRED && shader.mShaderClass != LLViewerShaderMgr::SHADER_INTERFACE) + { + shader.bind(); + return; + } + LL_RECORD_BLOCK_TIME(FTM_BIND_DEFERRED); static const LLCachedControl RenderDeferredSunWash("RenderDeferredSunWash",.5f); static const LLCachedControl RenderShadowNoise("RenderShadowNoise",-.0001f); @@ -7520,17 +7458,15 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n static const LLCachedControl RenderEdgeNormCutoff("RenderEdgeNormCutoff",.25f); static const LLCachedControl RenderSSAOResolutionScale("SHRenderSSAOResolutionScale",.5f); - if (noise_map == 0xFFFFFFFF) - { - noise_map = mNoiseMap; - } + diffuse_source = diffuse_source ? diffuse_source : &mDeferredScreen; + light_source = light_source ? light_source : &mDeferredLight; shader.bind(); S32 channel = 0; - channel = shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage()); + channel = shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, diffuse_source->getUsage()); if (channel > -1) { - mDeferredScreen.bindTexture(0,channel); + diffuse_source->bindTexture(0, channel); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } @@ -7575,38 +7511,27 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n inv_proj.invert(); shader.uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.getF32ptr()); - shader.uniform4f(LLShaderMgr::VIEWPORT, (F32) gGLViewport[0], - (F32) gGLViewport[1], - (F32) gGLViewport[2], - (F32) gGLViewport[3]); } channel = shader.enableTexture(LLShaderMgr::DEFERRED_NOISE); if (channel > -1) { - gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, noise_map); + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap->getTexName()); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC); if (channel > -1) { - gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc->getTexName()); } stop_glerror(); - channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage()); + channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHT, light_source->getUsage()); if (channel > -1) { - if (light_index > 0) - { - mScreen.bindTexture(0, channel); - } - else - { - mDeferredLight.bindTexture(0, channel); - } + light_source->bindTexture(0, channel); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } @@ -7620,7 +7545,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n for (U32 i = 0; i < 4; i++) { - channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE); + channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i); stop_glerror(); if (channel > -1) { @@ -7691,15 +7616,17 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n F32 ssao_factor = RenderSSAOFactor; shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor); - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0/ssao_factor); + shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.f/ssao_factor); LLVector3 ssao_effect = RenderSSAOEffect; shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_EFFECT, ssao_effect[0]); + shader.uniform2f(LLShaderMgr::DEFERRED_KERN_SCALE, 1.f / mDeferredScreen.getWidth(), 1.f / mDeferredScreen.getHeight()); + shader.uniform2f(LLShaderMgr::DEFERRED_NOISE_SCALE, mDeferredScreen.getWidth() / NOISE_MAP_RES, mDeferredScreen.getHeight() / NOISE_MAP_RES); + //F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); F32 shadow_bias_error = RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2])/3000.f; - shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f); shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset); //*shadow_offset_error); shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias+shadow_bias_error); @@ -7720,20 +7647,18 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n norm_mat.transpose(); shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.getF32ptr()); } - - shader.uniform1f(LLShaderMgr::DEFERRED_DOWNSAMPLED_DEPTH_SCALE, llclamp(RenderSSAOResolutionScale.get(),.01f,1.f)); } -static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace"); -static LLFastTimer::DeclareTimer FTM_GI_GATHER("Gather"); -static LLFastTimer::DeclareTimer FTM_SUN_SHADOW("Shadow Map"); -static LLFastTimer::DeclareTimer FTM_SOFTEN_SHADOW("Shadow Soften"); -static LLFastTimer::DeclareTimer FTM_EDGE_DETECTION("Find Edges"); -static LLFastTimer::DeclareTimer FTM_LOCAL_LIGHTS("Local Lights"); -static LLFastTimer::DeclareTimer FTM_ATMOSPHERICS("Atmospherics"); -static LLFastTimer::DeclareTimer FTM_FULLSCREEN_LIGHTS("Fullscreen Lights"); -static LLFastTimer::DeclareTimer FTM_PROJECTORS("Projectors"); -static LLFastTimer::DeclareTimer FTM_POST("Post"); +static LLTrace::BlockTimerStatHandle FTM_GI_TRACE("Trace"); +static LLTrace::BlockTimerStatHandle FTM_GI_GATHER("Gather"); +static LLTrace::BlockTimerStatHandle FTM_SUN_SHADOW("Shadow Map"); +static LLTrace::BlockTimerStatHandle FTM_SOFTEN_SHADOW("Shadow Soften"); +static LLTrace::BlockTimerStatHandle FTM_EDGE_DETECTION("Find Edges"); +static LLTrace::BlockTimerStatHandle FTM_LOCAL_LIGHTS("Local Lights"); +static LLTrace::BlockTimerStatHandle FTM_ATMOSPHERICS("Atmospherics"); +static LLTrace::BlockTimerStatHandle FTM_FULLSCREEN_LIGHTS("Fullscreen Lights"); +static LLTrace::BlockTimerStatHandle FTM_PROJECTORS("Projectors"); +static LLTrace::BlockTimerStatHandle FTM_POST("Post"); void LLPipeline::renderDeferredLighting() @@ -7754,7 +7679,7 @@ void LLPipeline::renderDeferredLighting() static const LLCachedControl RenderLocalLights("RenderLocalLights",false); { - LLFastTimer ftm(FTM_RENDER_DEFERRED); + LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED); LLViewerCamera* camera = LLViewerCamera::getInstance(); { @@ -7763,7 +7688,7 @@ void LLPipeline::renderDeferredLighting() 0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); } - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + LLGLEnable multisample(RenderFSAASamples > 0); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { @@ -7771,7 +7696,7 @@ void LLPipeline::renderDeferredLighting() } //ati doesn't seem to love actually using the stencil buffer on FBO's - LLGLDisable stencil(GL_STENCIL_TEST); + LLGLDisable stencil; //glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); @@ -7780,15 +7705,16 @@ void LLPipeline::renderDeferredLighting() //draw a cube around every light LLVertexBuffer::unbind(); - LLGLEnable cull(GL_CULL_FACE); - LLGLEnable blend(GL_BLEND); + LLGLEnable cull; + LLGLEnable blend; { - setupHWLights(NULL); //to set mSunDir; - mTransformedSunDir.load3(mSunDir.mV); + mTransformedSunDir.load3(getSunDir().mV); glh_get_current_modelview().rotate(mTransformedSunDir,mTransformedSunDir); } + llassert_always(LLGLState::checkEnabled()); + gGL.pushMatrix(); gGL.loadIdentity(); gGL.matrixMode(LLRender::MM_PROJECTION); @@ -7799,18 +7725,17 @@ void LLPipeline::renderDeferredLighting() { F32 ssao_scale = llclamp(RenderSSAOResolutionScale.get(),.01f,1.f); - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; //Downsample with fullscreen quad. GL_NEAREST if(ssao_scale < 1.f) { mDeferredDownsampledDepth.bindTarget(); mDeferredDownsampledDepth.clear(GL_DEPTH_BUFFER_BIT); - bindDeferredShader(gDeferredDownsampleDepthNearestProgram, 0); - gDeferredDownsampleDepthNearestProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale); + bindDeferredShader(gDeferredDownsampleDepthNearestProgram); { LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } mDeferredDownsampledDepth.flush(); unbindDeferredShader(gDeferredDownsampleDepthNearestProgram); @@ -7822,15 +7747,14 @@ void LLPipeline::renderDeferredLighting() glClearColor(1,1,1,1); mScreen.clear(GL_COLOR_BUFFER_BIT); glClearColor(0,0,0,0); - bindDeferredShader(gDeferredSSAOProgram, 0); + bindDeferredShader(gDeferredSSAOProgram); if(ssao_scale < 1.f) { - glViewport(0,0,mDeferredDownsampledDepth.getWidth(),mDeferredDownsampledDepth.getHeight()); - gDeferredSSAOProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale); + gGL.setViewport(0,0,mDeferredDownsampledDepth.getWidth(),mDeferredDownsampledDepth.getHeight()); } { LLGLDepthTest depth(GL_FALSE); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } mScreen.flush(); unbindDeferredShader(gDeferredSSAOProgram); @@ -7841,13 +7765,14 @@ void LLPipeline::renderDeferredLighting() { mDeferredLight.bindTarget(); { //paint shadow/SSAO light map (direct lighting lightmap) - LLFastTimer ftm(FTM_SUN_SHADOW); - bindDeferredShader(gDeferredSunProgram, 0); + LL_RECORD_BLOCK_TIME(FTM_SUN_SHADOW); + bindDeferredShader(gDeferredSunProgram); glClearColor(1,1,1,1); mDeferredLight.clear(GL_COLOR_BUFFER_BIT); glClearColor(0,0,0,0); - gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight()); + F32 ssao_scale = llclamp(RenderSSAOResolutionScale.get(), .01f, 1.f); + gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SSAO_SCALE, ssao_scale, ssao_scale); //Enable bilinear filtering, as the screen tex resolution may not match current framebuffer resolution. Eg, half-res SSAO // diffuse map should only be found if the sun shader is the SSAO variant. @@ -7859,9 +7784,9 @@ void LLPipeline::renderDeferredLighting() } { - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } if (channel > -1) @@ -7877,7 +7802,7 @@ void LLPipeline::renderDeferredLighting() static const LLCachedControl SHAlwaysSoftenShadows("SHAlwaysSoftenShadows",true); if (RenderDeferredSSAO || (RenderShadowDetail > 0 && SHAlwaysSoftenShadows)) { //soften direct lighting lightmap - LLFastTimer ftm(FTM_SOFTEN_SHADOW); + LL_RECORD_BLOCK_TIME(FTM_SOFTEN_SHADOW); //blur lightmap mScreen.bindTarget(); glClearColor(1,1,1,1); @@ -7890,45 +7815,30 @@ void LLPipeline::renderDeferredLighting() F32 blur_size = RenderShadowBlurSize; F32 dist_factor = RenderShadowBlurDistFactor; - // sample symmetrically with the middle sample falling exactly on 0.0 - F32 x = 0.f; - - LLVector3 gauss[32]; // xweight, yweight, offset - - for (U32 i = 0; i < kern_length; i++) - { - gauss[i].mV[0] = llgaussian(x, go.mV[0]); - gauss[i].mV[1] = llgaussian(x, go.mV[1]); - gauss[i].mV[2] = x; - x += 1.f; - } - - gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f); + gDeferredBlurLightProgram.uniform2f(sDelta, (blur_size * (kern_length / 2.f - 0.5f)) / mScreen.getWidth(), 0.f); gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor); - gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length/2.f - 0.5f)); { - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } mScreen.flush(); unbindDeferredShader(gDeferredBlurLightProgram); - bindDeferredShader(gDeferredBlurLightProgram, 1); + bindDeferredShader(gDeferredBlurLightProgram, &mScreen, &mScreen); mDeferredLight.bindTarget(); - gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f); + gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, (blur_size * (kern_length / 2.f - 0.5f)) / mScreen.getHeight()); { - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } mDeferredLight.flush(); - unbindDeferredShader(gDeferredBlurLightProgram); + unbindDeferredShader(gDeferredBlurLightProgram, &mScreen, &mScreen); } stop_glerror(); @@ -7946,12 +7856,12 @@ void LLPipeline::renderDeferredLighting() if (RenderDeferredAtmospheric) { //apply sunlight contribution - LLFastTimer ftm(FTM_ATMOSPHERICS); + LL_RECORD_BLOCK_TIME(FTM_ATMOSPHERICS); bindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram); { LLGLDepthTest depth(GL_FALSE); - LLGLDisable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); + LLGLDisable blend; + LLGLDisable test; //full screen blit gGL.pushMatrix(); @@ -7960,7 +7870,7 @@ void LLPipeline::renderDeferredLighting() gGL.pushMatrix(); gGL.loadIdentity(); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); gGL.popMatrix(); gGL.matrixMode(LLRender::MM_MODELVIEW); @@ -7971,8 +7881,8 @@ void LLPipeline::renderDeferredLighting() } { //render non-deferred geometry (fullbright, alpha, etc) - LLGLDisable blend(GL_BLEND); - LLGLDisable stencil(GL_STENCIL_TEST); + LLGLDisable blend; + LLGLDisable stencil; gGL.setSceneBlendType(LLRender::BT_ALPHA); gPipeline.pushRenderTypeMask(); @@ -8037,6 +7947,12 @@ void LLPipeline::renderDeferredLighting() } } + const LLViewerObject *vobj = drawablep->getVObj(); + if(vobj && vobj->getAvatar() + && (vobj->getAvatar()->isTooComplex())) + { + continue; + } LLVector4a center; center.load3(drawablep->getPositionAgent().mV); @@ -8063,13 +7979,14 @@ void LLPipeline::renderDeferredLighting() } sVisibleLightCount++; - - if (camera->getOrigin().mV[0] > c[0] + s + 0.2f || - camera->getOrigin().mV[0] < c[0] - s - 0.2f || - camera->getOrigin().mV[1] > c[1] + s + 0.2f || - camera->getOrigin().mV[1] < c[1] - s - 0.2f || - camera->getOrigin().mV[2] > c[2] + s + 0.2f || - camera->getOrigin().mV[2] < c[2] - s - 0.2f) + + const auto& camera_origin = camera->getOrigin(); + if (camera_origin.mV[0] > c[0] + s + 0.2f || + camera_origin.mV[0] < c[0] - s - 0.2f || + camera_origin.mV[1] > c[1] + s + 0.2f || + camera_origin.mV[1] < c[1] - s - 0.2f || + camera_origin.mV[2] > c[2] + s + 0.2f || + camera_origin.mV[2] < c[2] - s - 0.2f) { //draw box if camera is outside box if (render_local) { @@ -8080,12 +7997,11 @@ void LLPipeline::renderDeferredLighting() continue; } - LLFastTimer ftm(FTM_LOCAL_LIGHTS); + LL_RECORD_BLOCK_TIME(FTM_LOCAL_LIGHTS); gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); - gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); stop_glerror(); @@ -8122,7 +8038,7 @@ void LLPipeline::renderDeferredLighting() for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter) { - LLFastTimer ftm(FTM_PROJECTORS); + LL_RECORD_BLOCK_TIME(FTM_PROJECTORS); LLDrawable* drawablep = *iter; LLVOVolume* volume = drawablep->getVOVolume(); @@ -8142,7 +8058,6 @@ void LLPipeline::renderDeferredLighting() gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); - gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); } @@ -8170,7 +8085,7 @@ void LLPipeline::renderDeferredLighting() while (!fullscreen_lights.empty()) { - LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS); + LL_RECORD_BLOCK_TIME(FTM_FULLSCREEN_LIGHTS); light[count] = fullscreen_lights.front(); fullscreen_lights.pop_front(); col[count] = light_colors.front(); @@ -8193,7 +8108,7 @@ void LLPipeline::renderDeferredLighting() gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z); far_z = 0.f; count = 0; - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); unbindDeferredShader(gDeferredMultiLightProgram[idx]); } } @@ -8204,7 +8119,7 @@ void LLPipeline::renderDeferredLighting() for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter) { - LLFastTimer ftm(FTM_PROJECTORS); + LL_RECORD_BLOCK_TIME(FTM_PROJECTORS); LLDrawable* drawablep = *iter; LLVOVolume* volume = drawablep->getVOVolume(); @@ -8229,7 +8144,7 @@ void LLPipeline::renderDeferredLighting() gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION); @@ -8258,24 +8173,21 @@ void LLPipeline::renderDeferredLighting() { LLGLDepthTest depth(GL_FALSE, GL_FALSE); - mScreen.bindTarget(); + mFinalScreen.bindTarget(); // Apply gamma correction to the frame here. gDeferredPostGammaCorrectProgram.bind(); - S32 channel = 0; - channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); + S32 channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); if (channel > -1) { mScreen.bindTexture(0,channel); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mScreen.getWidth(), mScreen.getHeight()); - - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); gGL.getTexUnit(channel)->unbind(mScreen.getUsage()); gDeferredPostGammaCorrectProgram.unbind(); - mScreen.flush(); + mFinalScreen.flush(); } gGL.matrixMode(LLRender::MM_PROJECTION); @@ -8283,11 +8195,11 @@ void LLPipeline::renderDeferredLighting() gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.popMatrix(); - mScreen.bindTarget(); + mFinalScreen.bindTarget(); { //render non-deferred geometry (alpha, fullbright, glow) - LLGLDisable blend(GL_BLEND); - LLGLDisable stencil(GL_STENCIL_TEST); + LLGLDisable blend; + LLGLDisable stencil; pushRenderTypeMask(); andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, @@ -8306,8 +8218,6 @@ void LLPipeline::renderDeferredLighting() LLPipeline::RENDER_TYPE_PASS_GLOW, LLPipeline::RENDER_TYPE_PASS_GRASS, LLPipeline::RENDER_TYPE_PASS_SHINY, - LLPipeline::RENDER_TYPE_PASS_INVISIBLE, - LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::RENDER_TYPE_ALPHA_MASK, LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, @@ -8334,7 +8244,7 @@ void LLPipeline::renderDeferredLighting() } } - mScreen.flush(); + mFinalScreen.flush(); } @@ -8356,7 +8266,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) static const LLCachedControl RenderLocalLights("RenderLocalLights",false); { - LLFastTimer ftm(FTM_RENDER_DEFERRED); + LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED); LLViewerCamera* camera = LLViewerCamera::getInstance(); { @@ -8365,7 +8275,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) 0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); } - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + LLGLEnable multisample(RenderFSAASamples > 0); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { @@ -8373,7 +8283,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) } //ati doesn't seem to love actually using the stencil buffer on FBO's - LLGLDisable stencil(GL_STENCIL_TEST); + LLGLDisable stencil; //glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); @@ -8382,12 +8292,11 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) //draw a cube around every light LLVertexBuffer::unbind(); - LLGLEnable cull(GL_CULL_FACE); - LLGLEnable blend(GL_BLEND); + LLGLEnable cull; + LLGLEnable blend; { - setupHWLights(NULL); //to set mSunDir; - mTransformedSunDir.load3(mSunDir.mV); + mTransformedSunDir.load3(getSunDir().mV); glh_get_current_modelview().rotate(mTransformedSunDir,mTransformedSunDir); } @@ -8401,18 +8310,17 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) { F32 ssao_scale = llclamp(RenderSSAOResolutionScale.get(),.01f,1.f); - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; //Downsample with fullscreen quad. GL_NEAREST if(ssao_scale < 1.f) { mDeferredDownsampledDepth.bindTarget(); mDeferredDownsampledDepth.clear(GL_DEPTH_BUFFER_BIT); - bindDeferredShader(gDeferredDownsampleDepthNearestProgram, 0); - gDeferredDownsampleDepthNearestProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale); + bindDeferredShader(gDeferredDownsampleDepthNearestProgram); { LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } mDeferredDownsampledDepth.flush(); unbindDeferredShader(gDeferredDownsampleDepthNearestProgram); @@ -8424,15 +8332,14 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) glClearColor(1,1,1,1); mScreen.clear(GL_COLOR_BUFFER_BIT); glClearColor(0,0,0,0); - bindDeferredShader(gDeferredSSAOProgram, 0); + bindDeferredShader(gDeferredSSAOProgram); if(ssao_scale < 1.f) { - glViewport(0,0,mDeferredDownsampledDepth.getWidth(),mDeferredDownsampledDepth.getHeight()); - gDeferredSSAOProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale); + gGL.setViewport(0,0,mDeferredDownsampledDepth.getWidth(),mDeferredDownsampledDepth.getHeight()); } { LLGLDepthTest depth(GL_FALSE); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } mScreen.flush(); unbindDeferredShader(gDeferredSSAOProgram); @@ -8443,13 +8350,15 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) { mDeferredLight.bindTarget(); { //paint shadow/SSAO light map (direct lighting lightmap) - LLFastTimer ftm(FTM_SUN_SHADOW); + LL_RECORD_BLOCK_TIME(FTM_SUN_SHADOW); bindDeferredShader(gDeferredSunProgram); + + F32 ssao_scale = llclamp(RenderSSAOResolutionScale.get(), .01f, 1.f); + gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SSAO_SCALE, ssao_scale, ssao_scale); + glClearColor(1,1,1,1); mDeferredLight.clear(GL_COLOR_BUFFER_BIT); glClearColor(0,0,0,0); - - gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight()); //Enable bilinear filtering, as the screen tex resolution may not match current framebuffer resolution. Eg, half-res SSAO // diffuse map should only be found if the sun shader is the SSAO variant. @@ -8461,9 +8370,9 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) } { - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } if (channel > -1) @@ -8492,12 +8401,12 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) if (RenderDeferredAtmospheric) { //apply sunlight contribution - LLFastTimer ftm(FTM_ATMOSPHERICS); + LL_RECORD_BLOCK_TIME(FTM_ATMOSPHERICS); bindDeferredShader(gDeferredSoftenProgram); { LLGLDepthTest depth(GL_FALSE); - LLGLDisable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); + LLGLDisable blend; + LLGLDisable test; //full screen blit gGL.pushMatrix(); @@ -8506,7 +8415,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) gGL.pushMatrix(); gGL.loadIdentity(); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); gGL.popMatrix(); gGL.matrixMode(LLRender::MM_MODELVIEW); @@ -8517,8 +8426,8 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) } { //render non-deferred geometry (fullbright, alpha, etc) - LLGLDisable blend(GL_BLEND); - LLGLDisable stencil(GL_STENCIL_TEST); + LLGLDisable blend; + LLGLDisable stencil; gGL.setSceneBlendType(LLRender::BT_ALPHA); gPipeline.pushRenderTypeMask(); @@ -8609,13 +8518,14 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) } sVisibleLightCount++; - - if (camera->getOrigin().mV[0] > c[0] + s + 0.2f || - camera->getOrigin().mV[0] < c[0] - s - 0.2f || - camera->getOrigin().mV[1] > c[1] + s + 0.2f || - camera->getOrigin().mV[1] < c[1] - s - 0.2f || - camera->getOrigin().mV[2] > c[2] + s + 0.2f || - camera->getOrigin().mV[2] < c[2] - s - 0.2f) + + const auto& camera_origin = camera->getOrigin(); + if (camera_origin.mV[0] > c[0] + s + 0.2f || + camera_origin.mV[0] < c[0] - s - 0.2f || + camera_origin.mV[1] > c[1] + s + 0.2f || + camera_origin.mV[1] < c[1] - s - 0.2f || + camera_origin.mV[2] > c[2] + s + 0.2f || + camera_origin.mV[2] < c[2] - s - 0.2f) { //draw box if camera is outside box if (render_local) { @@ -8630,12 +8540,11 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) col.mV[1] = powf(col.mV[1], 2.2f); col.mV[2] = powf(col.mV[2], 2.2f);*/ - LLFastTimer ftm(FTM_LOCAL_LIGHTS); + LL_RECORD_BLOCK_TIME(FTM_LOCAL_LIGHTS); gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); - gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); stop_glerror(); @@ -8672,7 +8581,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter) { - LLFastTimer ftm(FTM_PROJECTORS); + LL_RECORD_BLOCK_TIME(FTM_PROJECTORS); LLDrawable* drawablep = *iter; LLVOVolume* volume = drawablep->getVOVolume(); @@ -8695,7 +8604,6 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); - gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); } @@ -8723,7 +8631,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) while (!fullscreen_lights.empty()) { - LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS); + LL_RECORD_BLOCK_TIME(FTM_FULLSCREEN_LIGHTS); light[count] = fullscreen_lights.front(); fullscreen_lights.pop_front(); col[count] = light_colors.front(); @@ -8746,7 +8654,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z); far_z = 0.f; count = 0; - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } } @@ -8758,7 +8666,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter) { - LLFastTimer ftm(FTM_PROJECTORS); + LL_RECORD_BLOCK_TIME(FTM_PROJECTORS); LLDrawable* drawablep = *iter; LLVOVolume* volume = drawablep->getVOVolume(); @@ -8783,7 +8691,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); - drawFullScreenRect(LLVertexBuffer::MAP_VERTEX); + drawFullScreenRect(); } gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION); @@ -8798,7 +8706,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) gGL.setColorMask(true, true); } - /*mScreen.flush(); + mScreen.flush(); //gamma correct lighting gGL.matrixMode(LLRender::MM_PROJECTION); @@ -8811,14 +8719,9 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) { LLGLDepthTest depth(GL_FALSE, GL_FALSE); - LLVector2 tc1(0,0); - LLVector2 tc2((F32) mScreen.getWidth()*2, - (F32) mScreen.getHeight()*2); - - mScreen.bindTarget(); + mFinalScreen.bindTarget(); // Apply gamma correction to the frame here. gDeferredPostGammaCorrectProgram.bind(); - //mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); S32 channel = 0; channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); if (channel > -1) @@ -8827,27 +8730,11 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mScreen.getWidth(), mScreen.getHeight()); - - F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); - - gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3,-1); - - gGL.end(); + drawFullScreenRect(); gGL.getTexUnit(channel)->unbind(mScreen.getUsage()); gDeferredPostGammaCorrectProgram.unbind(); - mScreen.flush(); + mFinalScreen.flush(); } gGL.matrixMode(LLRender::MM_PROJECTION); @@ -8855,11 +8742,11 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.popMatrix(); - mScreen.bindTarget();*/ + mFinalScreen.bindTarget(); { //render non-deferred geometry (alpha, fullbright, glow) - LLGLDisable blend(GL_BLEND); - LLGLDisable stencil(GL_STENCIL_TEST); + LLGLDisable blend; + LLGLDisable stencil; pushRenderTypeMask(); andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, @@ -8878,8 +8765,6 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) LLPipeline::RENDER_TYPE_PASS_GLOW, LLPipeline::RENDER_TYPE_PASS_GRASS, LLPipeline::RENDER_TYPE_PASS_SHINY, - LLPipeline::RENDER_TYPE_PASS_INVISIBLE, - LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::RENDER_TYPE_ALPHA_MASK, LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, @@ -9031,14 +8916,23 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) } -void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) +void LLPipeline::unbindDeferredShader(LLGLSLShader &shader, LLRenderTarget* diffuse_source, LLRenderTarget* light_source) { + if (shader.mShaderClass != LLViewerShaderMgr::SHADER_DEFERRED && shader.mShaderClass != LLViewerShaderMgr::SHADER_INTERFACE) + { + shader.unbind(); + return; + } + + diffuse_source = diffuse_source ? diffuse_source : &mDeferredScreen; + light_source = light_source ? light_source : &mDeferredLight; + stop_glerror(); shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage()); - shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage()); + shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, diffuse_source->getUsage()); shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage()); - shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredScreen.getUsage()); - shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage()); + shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage()); + shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, light_source->getUsage()); shader.disableTexture(LLShaderMgr::DIFFUSE_MAP); shader.disableTexture(LLShaderMgr::DEFERRED_BLOOM); @@ -9099,9 +8993,9 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) } LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + LLGLStateValidator::checkClientArrays(); LLCamera camera = camera_in; camera.setFar(camera.getFar()*0.87654321f); @@ -9218,7 +9112,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) } else { - renderGeom(camera, TRUE); + renderGeom(camera, TRUE); } gPipeline.popRenderTypeMask(); @@ -9256,7 +9150,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) static const LLCachedControl skip_distortion_updates("SkipReflectOcclusionUpdates",false); LLPipeline::sSkipUpdate = skip_distortion_updates; LLGLUserClipPlane clip_plane(plane, mat, projection); - LLGLDisable cull(GL_CULL_FACE); + LLGLDisable cull; updateCull(camera, ref_result, -water_clip, &plane); stateSort(camera, ref_result); @@ -9378,6 +9272,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) if (!LLRenderTarget::sUseFBO) { + gGL.syncContextState(); glClear(GL_DEPTH_BUFFER_BIT); } glClearColor(0.f, 0.f, 0.f, 0.f); @@ -9388,7 +9283,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLPlane npnorm(-pnorm, -pd); LLViewerCamera::getInstance()->setUserClipPlane(npnorm); - LLGLState::checkStates(); + LLGLStateValidator::checkStates(); if (!skip_avatar_update) { @@ -9399,13 +9294,13 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) } } -static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows"); -static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow"); -static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_RENDER("Render Shadows"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA("Alpha Shadow"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_SIMPLE("Simple Shadow"); void LLPipeline::renderShadow(const LLMatrix4a& view, const LLMatrix4a& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion, U32 target_width) { - LLFastTimer t(FTM_SHADOW_RENDER); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER); //clip out geometry on the same side of water as the camera S32 occlude = LLPipeline::sUseOcclusion; @@ -9431,18 +9326,14 @@ void LLPipeline::renderShadow(const LLMatrix4a& view, const LLMatrix4a& proj, LL LLRenderPass::PASS_NORMSPEC_EMISSIVE, }; - LLGLEnable cull(GL_CULL_FACE); + LLGLEnable cull; if (use_shader) { gDeferredShadowCubeProgram.bind(); } - //LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID-1]; - - //occlusion_target.bindTarget(); updateCull(shadow_cam, result); - //occlusion_target.flush(); stateSort(shadow_cam, result); @@ -9477,7 +9368,7 @@ void LLPipeline::renderShadow(const LLMatrix4a& view, const LLMatrix4a& proj, LL gGL.diffuseColor4f(1,1,1,1); gGL.setColorMask(false, false); - LLFastTimer ftm(FTM_SHADOW_SIMPLE); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE); gGL.getTexUnit(0)->disable(); for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) { @@ -9502,7 +9393,7 @@ void LLPipeline::renderShadow(const LLMatrix4a& view, const LLMatrix4a& proj, LL } { - LLFastTimer ftm(FTM_SHADOW_ALPHA); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA); gDeferredShadowAlphaMaskProgram.bind(); gDeferredShadowAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); @@ -9536,7 +9427,7 @@ void LLPipeline::renderShadow(const LLMatrix4a& view, const LLMatrix4a& proj, LL //LLRenderTarget& occlusion_source = mShadow[LLViewerCamera::sCurCameraID-1]; - doOcclusion(shadow_cam/*, occlusion_source, occlusion_target*/); + doOcclusion(shadow_cam); if (use_shader) { @@ -9555,10 +9446,10 @@ void LLPipeline::renderShadow(const LLMatrix4a& view, const LLMatrix4a& proj, LL LLPipeline::sShadowRender = FALSE; } -static LLFastTimer::DeclareTimer FTM_VISIBLE_CLOUD("Visible Cloud"); +static LLTrace::BlockTimerStatHandle FTM_VISIBLE_CLOUD("Visible Cloud"); BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector& fp, LLVector3 light_dir) { - LLFastTimer t(FTM_VISIBLE_CLOUD); + LL_RECORD_BLOCK_TIME(FTM_VISIBLE_CLOUD); //get point cloud of intersection of frust and min, max if (getVisibleExtents(camera, min, max)) @@ -9728,7 +9619,7 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector } -static LLFastTimer::DeclareTimer FTM_GEN_SUN_SHADOW("Gen Sun Shadow"); +static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow"); void LLPipeline::generateSunShadow(LLCamera& camera) { @@ -9747,7 +9638,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) return; } - LLFastTimer t(FTM_GEN_SUN_SHADOW); + LL_RECORD_BLOCK_TIME(FTM_GEN_SUN_SHADOW); BOOL skip_avatar_update = FALSE; if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson) @@ -9829,14 +9720,16 @@ void LLPipeline::generateSunShadow(LLCamera& camera) //F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] }; //put together a universal "near clip" plane for shadow frusta + LLVector3 sunDir = getSunDir(); LLPlane shadow_near_clip; { + ; LLVector3 p = gAgent.getPositionAgent(); - p += mSunDir * RenderFarClip*2.f; - shadow_near_clip.setVec(p, mSunDir); + p += sunDir * RenderFarClip*2.f; + shadow_near_clip.setVec(p, sunDir); } - LLVector3 lightDir = -mSunDir; + LLVector3 lightDir = -sunDir; lightDir.normVec(); //create light space camera matrix @@ -10485,17 +10378,17 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu } } -static LLFastTimer::DeclareTimer FTM_IMPOSTOR_MARK_VISIBLE("Impostor Mark Visible"); -static LLFastTimer::DeclareTimer FTM_IMPOSTOR_SETUP("Impostor Setup"); -static LLFastTimer::DeclareTimer FTM_IMPOSTOR_BACKGROUND("Impostor Background"); -static LLFastTimer::DeclareTimer FTM_IMPOSTOR_ALLOCATE("Impostor Allocate"); -static LLFastTimer::DeclareTimer FTM_IMPOSTOR_RESIZE("Impostor Resize"); +static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_MARK_VISIBLE("Impostor Mark Visible"); +static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_SETUP("Impostor Setup"); +static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_BACKGROUND("Impostor Background"); +static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_ALLOCATE("Impostor Allocate"); +static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_RESIZE("Impostor Resize"); void LLPipeline::generateImpostor(LLVOAvatar* avatar) { - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + LLGLStateValidator::checkClientArrays(); static LLCullResult result; result.clear(); @@ -10534,12 +10427,9 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLPipeline::RENDER_TYPE_PASS_GLOW, LLPipeline::RENDER_TYPE_PASS_GRASS, LLPipeline::RENDER_TYPE_PASS_SHINY, - LLPipeline::RENDER_TYPE_PASS_INVISIBLE, - LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::RENDER_TYPE_ALPHA_MASK, LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, - LLPipeline::RENDER_TYPE_INVISIBLE, LLPipeline::RENDER_TYPE_SIMPLE, END_RENDER_TYPES); } @@ -10553,7 +10443,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLViewerCamera* viewer_camera = LLViewerCamera::getInstance(); { - LLFastTimer t(FTM_IMPOSTOR_MARK_VISIBLE); + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_MARK_VISIBLE); markVisible(avatar->mDrawable, *viewer_camera); LLVOAvatar::sUseImpostors = FALSE; @@ -10588,7 +10478,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) U32 resX = 0; { - LLFastTimer t(FTM_IMPOSTOR_SETUP); + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_SETUP); const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); @@ -10646,7 +10536,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (!avatar->mImpostor.isComplete()) { - LLFastTimer t(FTM_IMPOSTOR_ALLOCATE); + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_ALLOCATE); if (LLPipeline::sRenderDeferred) @@ -10665,7 +10555,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) } else if(resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight()) { - LLFastTimer t(FTM_IMPOSTOR_RESIZE); + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_RESIZE); avatar->mImpostor.resize(resX,resY); } @@ -10703,8 +10593,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) } else { - LLGLEnable scissor(GL_SCISSOR_TEST); - glScissor(0, 0, resX, resY); + LLGLEnable scissor; + gGL.setScissor(0, 0, resX, resY); avatar->mImpostor.clear(); renderGeom(camera); @@ -10727,14 +10617,14 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLDrawPoolAvatar::sMinimumAlpha = old_alpha; { //create alpha mask based on depth buffer (grey out if muted) - LLFastTimer t(FTM_IMPOSTOR_BACKGROUND); + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_BACKGROUND); if (LLPipeline::sRenderDeferred) { GLuint buff = GL_COLOR_ATTACHMENT0; glDrawBuffersARB(1, &buff); } - LLGLDisable blend(GL_BLEND); + LLGLDisable blend; if (visually_muted) { @@ -10765,11 +10655,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) } gGL.diffuseColor4ub(64,64,64,255); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.vertex3f(-1, -1, clip_plane); gGL.vertex3f(1, -1, clip_plane); - gGL.vertex3f(1, 1, clip_plane); gGL.vertex3f(-1, 1, clip_plane); + gGL.vertex3f(1, 1, clip_plane); gGL.end(); gGL.flush(); @@ -10787,11 +10677,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) avatar->setImpostorDim(tdim); - LLVOAvatar::sUseImpostors = TRUE; + LLVOAvatar::sUseImpostors = true; sUseOcclusion = occlusion; - sReflectionRender = FALSE; - sImpostorRender = FALSE; - sShadowRender = FALSE; + sReflectionRender = false; + sImpostorRender = false; + sShadowRender = false; popRenderTypeMask(); gGL.matrixMode(LLRender::MM_PROJECTION); @@ -10801,11 +10691,12 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) avatar->mNeedsImpostorUpdate = FALSE; avatar->cacheImpostorValues(); + avatar->mLastImpostorUpdateFrameTime = gFrameTimeSeconds; LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLStateValidator::checkStates(); + LLGLStateValidator::checkTextureChannels(); + LLGLStateValidator::checkClientArrays(); } BOOL LLPipeline::hasRenderBatches(const U32 type) const @@ -10868,6 +10759,7 @@ BOOL LLPipeline::hasAnyRenderType(U32 type, ...) const { if (mRenderTypeEnabled[type]) { + va_end(args); return TRUE; } type = va_arg(args, U32); @@ -11044,31 +10936,21 @@ void LLPipeline::restoreHiddenObject( const LLUUID& id ) } */ -void LLPipeline::drawFullScreenRect(U32 data_mask) +void LLPipeline::drawFullScreenRect() { if(mAuxScreenRectVB.isNull()) { mAuxScreenRectVB = new LLVertexBuffer(AUX_VB_MASK, 0); mAuxScreenRectVB->allocateBuffer(3, 0, true); LLStrider vert; - LLStrider tc0, tc1; mAuxScreenRectVB->getVertexStrider(vert); - mAuxScreenRectVB->getTexCoord0Strider(tc0); - mAuxScreenRectVB->getTexCoord1Strider(tc1); vert[0].set(-1.f,-1.f,0.f); vert[1].set(3.f,-1.f,0.f); vert[2].set(-1.f,3.f,0.f); - tc0[0].set(0.f, 0.f); - tc0[1].set(mScreen.getWidth()*2.f, 0.f); - tc0[2].set(0.f, mScreen.getHeight()*2.f); - - tc1[0].set(0.f, 0.f); - tc1[1].set(2.f, 0.f); - tc1[2].set(0.f, 2.f); } - mAuxScreenRectVB->setBuffer(data_mask); + mAuxScreenRectVB->setBuffer(LLVertexBuffer::MAP_VERTEX); mAuxScreenRectVB->drawArrays(LLRender::TRIANGLES, 0, 3); } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 1cf400446b..09d438b83c 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -84,26 +84,25 @@ void glh_set_current_modelview(const LLMatrix4a& mat); const LLMatrix4a& glh_get_current_projection(); void glh_set_current_projection(const LLMatrix4a& mat); -extern LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY; -extern LLFastTimer::DeclareTimer FTM_RENDER_GRASS; -extern LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE; -extern LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION; -extern LLFastTimer::DeclareTimer FTM_RENDER_SHINY; -extern LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE; -extern LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN; -extern LLFastTimer::DeclareTimer FTM_RENDER_TREES; -extern LLFastTimer::DeclareTimer FTM_RENDER_UI; -extern LLFastTimer::DeclareTimer FTM_RENDER_WATER; -extern LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY; -extern LLFastTimer::DeclareTimer FTM_RENDER_ALPHA; -extern LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS; -extern LLFastTimer::DeclareTimer FTM_RENDER_BUMP; -extern LLFastTimer::DeclareTimer FTM_RENDER_MATERIALS; -extern LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT; -extern LLFastTimer::DeclareTimer FTM_RENDER_GLOW; -extern LLFastTimer::DeclareTimer FTM_STATESORT; -extern LLFastTimer::DeclareTimer FTM_PIPELINE; -extern LLFastTimer::DeclareTimer FTM_CLIENT_COPY; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_GEOMETRY; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_GRASS; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_OCCLUSION; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_SHINY; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_SIMPLE; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_TERRAIN; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_TREES; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_WATER; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_WL_SKY; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_CHARACTERS; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_BUMP; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_MATERIALS; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_FULLBRIGHT; +extern LLTrace::BlockTimerStatHandle FTM_RENDER_GLOW; +extern LLTrace::BlockTimerStatHandle FTM_STATESORT; +extern LLTrace::BlockTimerStatHandle FTM_PIPELINE; +extern LLTrace::BlockTimerStatHandle FTM_CLIENT_COPY; LL_ALIGN_PREFIX(16) @@ -116,8 +115,10 @@ class LLPipeline void destroyGL(); void restoreGL(); void resetVertexBuffers(); - void doResetVertexBuffers(); + void doResetVertexBuffers(bool forced = false); void resizeScreenTexture(); + void releaseOcclusionBuffers(); + void releaseVertexBuffers(); void releaseGLBuffers(); void releaseLUTBuffers(); void releaseScreenBuffers(); @@ -198,6 +199,7 @@ class LLPipeline //get the object between start and end that's closest to start. LLViewerObject* lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, + bool pick_rigged, S32* face_hit, // return the face hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point @@ -228,11 +230,8 @@ class LLPipeline void enableShadows(const BOOL enable_shadows); -// void setLocalLighting(const BOOL local_lighting); -// BOOL isLocalLightingEnabled() const; - S32 setLightingDetail(S32 level); - S32 getLightingDetail() const { return mLightingDetail; } - S32 getMaxLightingDetail() const; + void updateLocalLightingEnabled(); + bool isLocalLightingEnabled() const { return mLightingEnabled; } BOOL canUseWindLightShaders() const; BOOL canUseWindLightShadersOnObjects() const; @@ -252,11 +251,12 @@ class LLPipeline void createObjects(F32 max_dtime); void createObject(LLViewerObject* vobj); void processPartitionQ(); - void updateGeom(F32 max_dtime); + void updateGeom(F32 max_dtime, LLCamera& camera); void updateGL(); void rebuildPriorityGroups(); void rebuildGroups(); void clearRebuildGroups(); + void clearRebuildDrawables(); //calculate pixel area of given box from vantage point of given camera static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera); @@ -287,10 +287,10 @@ class LLPipeline void renderGeomDeferred(LLCamera& camera); void renderGeomPostDeferred(LLCamera& camera, bool do_occlusion=true); void renderGeomShadow(LLCamera& camera); - void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, U32 noise_map = 0xFFFFFFFF); + void bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* diffuse_source = NULL, LLRenderTarget* light_source = NULL); void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep); - void unbindDeferredShader(LLGLSLShader& shader); + void unbindDeferredShader(LLGLSLShader& shader, LLRenderTarget* diffuse_source = NULL, LLRenderTarget* light_source = NULL); void renderDeferredLighting(); void renderDeferredLightingToRT(LLRenderTarget* target); @@ -312,16 +312,18 @@ class LLPipeline void resetLocalLights(); //Default all gl light parameters. Used upon restoreGL. Fixes light brightness problems on fullscren toggle void calcNearbyLights(LLCamera& camera); - void setupHWLights(LLDrawPool* pool); - void setupAvatarLights(BOOL for_edit = FALSE); - void enableLights(U32 mask); - void enableLightsStatic(); - void enableLightsDynamic(); - void enableLightsAvatar(); - void enableLightsPreview(); - void enableLightsAvatarEdit(const LLColor4& color); - void enableLightsFullbright(const LLColor4& color); - void disableLights(); + void gatherLocalLights(); + void setupHWLights(); + void updateHWLightMode(U8 mode); + U8 setupFeatureLights(U8 cur_count); + void enableLights(U32 mask, LLGLState& light_state, const LLColor4* color = nullptr); + void enableLightsStatic(LLGLState& light_state); + void enableLightsDynamic(LLGLState& light_state); + void enableLightsAvatar(LLGLState& light_state); + void enableLightsPreview(LLGLState& light_state); + void enableLightsAvatarEdit(LLGLState& light_state, const LLColor4& color); + void enableLightsFullbright(LLGLState& light_state); + void disableLights(LLGLState& light_state); void shiftObjects(const LLVector3 &offset); @@ -360,6 +362,14 @@ class LLPipeline void pushRenderDebugFeatureMask(); void popRenderDebugFeatureMask(); + template + LLGLStateIface* pushRenderPassState(U8 newState = LLGLStateIface::CURRENT_STATE) { + llassert_always(mInRenderPass); + LLGLStateIface* stateObject = new LLGLState(newState); + mRenderPassStates.emplace_back(stateObject); + return stateObject; + } + static void toggleRenderType(U32 type); // For UI control of render features @@ -409,6 +419,7 @@ class LLPipeline static bool isRenderDeferredCapable(); static bool isRenderDeferredDesired(); + static void updateRenderDeferred(); static void refreshCachedSettings(); static void throttleNewMemoryAllocation(BOOL disable); @@ -428,7 +439,14 @@ class LLPipeline void hideDrawable( LLDrawable *pDrawable ); void unhideDrawable( LLDrawable *pDrawable ); - void drawFullScreenRect( U32 data_mask ); + void drawFullScreenRect(); + + void clearRenderPassStates() { + while (!mRenderPassStates.empty()) { + mRenderPassStates.pop_back(); + } + mInRenderPass = false; + } public: enum {GPU_CLASS_MAX = 3 }; @@ -448,7 +466,6 @@ class LLPipeline RENDER_TYPE_MATERIALS = LLDrawPool::POOL_MATERIALS, RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, - RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE, RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER, RENDER_TYPE_WATER = LLDrawPool::POOL_WATER, RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA, @@ -456,8 +473,6 @@ class LLPipeline RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE, RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS, RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT, - RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE, - RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY, RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY, RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY, RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP, @@ -557,6 +572,8 @@ class LLPipeline S32 mTrianglesDrawn; S32 mNumVisibleNodes; + static S32 sCompiles; + static BOOL sShowHUDAttachments; static BOOL sForceOldBakedUpload; // If true will not use capabilities to upload baked textures. static S32 sUseOcclusion; // 0 = no occlusion, 1 = read only, 2 = read/write @@ -590,6 +607,7 @@ class LLPipeline public: //screen texture LLRenderTarget mScreen; + LLRenderTarget mFinalScreen; LLRenderTarget mDeferredScreen; private: LLRenderTarget mFXAABuffer; @@ -597,7 +615,6 @@ class LLPipeline LLRenderTarget mDeferredDepth; private: LLRenderTarget mDeferredDownsampledDepth; - LLRenderTarget mOcclusionDepth; LLRenderTarget mDeferredLight; public: LLMultisampleBuffer mSampleBuffer; @@ -614,7 +631,6 @@ class LLPipeline private: //sun shadow map LLRenderTarget mShadow[6]; - LLRenderTarget mShadowOcclusion[6]; std::vector mShadowFrustPoints[4]; public: LLCamera mShadowCamera[8]; @@ -641,9 +657,8 @@ class LLPipeline LLRenderTarget mGlow[2]; //noise map - U32 mNoiseMap; - U32 mTrueNoiseMap; - U32 mLightFunc; + LLImageGL::GLTextureName mNoiseMap; + LLImageGL::GLTextureName mLightFunc; LLColor4 mSunDiffuse; LLVector3 mSunDir; @@ -701,7 +716,6 @@ class LLPipeline LLDrawable::drawable_set_t mLights; light_set_t mNearbyLights; // lights near camera - LLColor4 mHWLightColors[8]; ///////////////////////////////////////////// // @@ -728,6 +742,9 @@ class LLPipeline LLDrawable::drawable_set_t mRetexturedList; + bool mInRenderPass; + std::vector< std::unique_ptr > mRenderPassStates; + ////////////////////////////////////////////////// // // Draw pools are responsible for storing all rendered data, @@ -771,7 +788,6 @@ class LLPipeline LLRenderPass* mAlphaMaskPool; LLRenderPass* mFullbrightAlphaMaskPool; LLRenderPass* mFullbrightPool; - LLDrawPool* mInvisiblePool; LLDrawPool* mGlowPool; LLDrawPool* mBumpPool; LLDrawPool* mMaterialsPool; @@ -799,9 +815,11 @@ class LLPipeline LLPointer mFaceSelectImagep; + std::vector mLocalLights; + U8 mHWLightCount; + U8 mLightMode; U32 mLightMask; - U32 mLightMovingMask; - S32 mLightingDetail; + bool mLightingEnabled; static BOOL sRenderPhysicalBeacons; static BOOL sRenderMOAPBeacons; diff --git a/indra/newview/qtoolalign.cpp b/indra/newview/qtoolalign.cpp index 240bbffcb1..7e537233bd 100644 --- a/indra/newview/qtoolalign.cpp +++ b/indra/newview/qtoolalign.cpp @@ -370,8 +370,8 @@ void QToolAlign::render() // Draw bounding box LLGLSUIDefault gls_ui; - LLGLEnable gl_blend(GL_BLEND); - LLGLEnable gls_alpha_test(GL_ALPHA_TEST); + LLGLEnable gl_blend; + LLGLEnable gls_alpha_test; LLGLDepthTest gls_depth(GL_FALSE); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); diff --git a/indra/newview/res-sdl/singularity_icon.BMP b/indra/newview/res-sdl/singularity_icon.BMP deleted file mode 100644 index 7e27d0eca4..0000000000 Binary files a/indra/newview/res-sdl/singularity_icon.BMP and /dev/null differ diff --git a/indra/newview/res/singularity_icon.ico b/indra/newview/res/singularity_icon.ico deleted file mode 100644 index 84a455a226..0000000000 Binary files a/indra/newview/res/singularity_icon.ico and /dev/null differ diff --git a/indra/newview/res/viewerRes.rc.in b/indra/newview/res/viewerRes.rc.in index 0119f9fd9c..44c8104aab 100644 --- a/indra/newview/res/viewerRes.rc.in +++ b/indra/newview/res/viewerRes.rc.in @@ -2,19 +2,12 @@ // #include "resource.h" -#ifdef IDC_STATIC -#undef IDC_STATIC -#endif -#define IDC_STATIC (-1) -#include "winresrc.h" - #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // -// Commented out because it only compiles if you have MFC installed. -//#include "winres.h" +#include "windows.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -41,7 +34,7 @@ END 2 TEXTINCLUDE BEGIN - "#include ""winres.h""\r\n" + "#include ""windows.h""\r\n" "\0" END @@ -61,8 +54,8 @@ END // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -IDI_LL_ICON ICON "${VIEWER_BRANDING_ID}_icon.ico" -IDI_LCD_LL_ICON ICON "${VIEWER_BRANDING_ID}_icon.ico" +IDI_LL_ICON ICON "viewer_icon.ico" +IDI_LCD_LL_ICON ICON "viewer_icon.ico" ///////////////////////////////////////////////////////////////////////////// // @@ -74,7 +67,7 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE FONT 8, "MS Sans Serif" BEGIN ICON IDI_LL_ICON,IDC_STATIC,7,7,20,20 - LTEXT "Loading ${VIEWER_CHANNEL}...",666,36,13,91,8 + LTEXT "Loading ${VIEWER_CHANNEL} Viewer...",666,36,13,91,8 END @@ -123,14 +116,14 @@ TOOLPICKOBJECT3 CURSOR "toolpickobject3.cur" ARROWCOPY CURSOR "arrowcop.cur" ARROWDRAGMULTI CURSOR "llarrowdragmulti.cur" ARROWCOPYMULTI CURSOR "arrowcopmulti.cur" -TOOLSIT CURSOR "toolsit.cur" -TOOLBUY CURSOR "toolbuy.cur" -TOOLPAY CURSOR "toolpay.cur" -TOOLOPEN CURSOR "toolopen.cur" TOOLPIPETTE CURSOR "toolpipette.cur" TOOLPLAY CURSOR "toolplay.cur" TOOLPAUSE CURSOR "toolpause.cur" TOOLMEDIAOPEN CURSOR "toolmediaopen.cur" +TOOLBUY CURSOR "toolbuy.cur" +TOOLPAY CURSOR "toolpay.cur" +TOOLOPEN CURSOR "toolopen.cur" +TOOLSIT CURSOR "toolsit.cur" ///////////////////////////////////////////////////////////////////////////// // @@ -138,8 +131,8 @@ TOOLMEDIAOPEN CURSOR "toolmediaopen.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION ${vMAJOR},${vMINOR},${vPATCH},${vBUILD} - PRODUCTVERSION ${vMAJOR},${vMINOR},${vPATCH},${vBUILD} + FILEVERSION ${VIEWER_VERSION_MAJOR},${VIEWER_VERSION_MINOR},${VIEWER_VERSION_PATCH},${VIEWER_VERSION_REVISION} + PRODUCTVERSION ${VIEWER_VERSION_MAJOR},${VIEWER_VERSION_MINOR},${VIEWER_VERSION_PATCH},${VIEWER_VERSION_REVISION} FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -155,13 +148,13 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Siana Gearz" - VALUE "FileDescription", "Singularity Viewer" - VALUE "FileVersion", "${vMAJOR}.${vMINOR}.${vPATCH}.${vBUILD}" + VALUE "FileDescription", "${VIEWER_CHANNEL} Viewer" + VALUE "FileVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}" VALUE "InternalName", "Second Life" VALUE "LegalCopyright", "Copyright 2001-2010, Linden Research, Inc., Copyright 2010 Siana Gearz" VALUE "OriginalFilename", "SingularityViewer.exe" - VALUE "ProductName", "Singularity Viewer" - VALUE "ProductVersion", "${vMAJOR}.${vMINOR}.${vPATCH}.${vBUILD}" + VALUE "ProductName", "${VIEWER_CHANNEL} Viewer" + VALUE "ProductVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}" END END BLOCK "VarFileInfo" @@ -170,12 +163,6 @@ BEGIN END END - -///////////////////////////////////////////////////////////////////////////// -// -// Bitmap -// - #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/rlvactions.cpp b/indra/newview/rlvactions.cpp index b746cda4a4..6dd15cf49a 100644 --- a/indra/newview/rlvactions.cpp +++ b/indra/newview/rlvactions.cpp @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2009-2013, Kitty Barnett + * Copyright (c) 2009-2016, Kitty Barnett * * The source code in this file is provided to you under the terms of the * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; @@ -38,6 +38,13 @@ bool RlvActions::canReceiveIM(const LLUUID& idSender) ( (!gRlvHandler.hasBehaviour(RLV_BHVR_RECVIMFROM)) || (!gRlvHandler.isException(RLV_BHVR_RECVIMFROM, idSender)) ) ); } +bool RlvActions::canSendChannel(int nChannel) +{ + return + ( (!gRlvHandler.hasBehaviour(RLV_BHVR_SENDCHANNEL)) || (gRlvHandler.isException(RLV_BHVR_SENDCHANNEL, nChannel)) ) /*&& + ( (!gRlvHandler.hasBehaviour(RLV_BHVR_SENDCHANNELEXCEPT)) || (!gRlvHandler.isException(RLV_BHVR_SENDCHANNELEXCEPT, nChannel)) )*/; +} + // Checked: 2010-11-30 (RLVa-1.3.0) bool RlvActions::canSendIM(const LLUUID& idRecipient) { @@ -62,29 +69,44 @@ bool RlvActions::canStartIM(const LLUUID& idRecipient) ( (!gRlvHandler.hasBehaviour(RLV_BHVR_STARTIMTO)) || (!gRlvHandler.isException(RLV_BHVR_STARTIMTO, idRecipient)) ) ); } +// Handles: @chatwhisper, @chatnormal and @chatshout +EChatType RlvActions::checkChatVolume(EChatType chatType) +{ + // In vs Bhvr | whisper | normal | shout | n+w | n+s | s+w | s+n+w | + // --------------------------------------------------------------------------------- + // whisper | normal | - | - | normal | - | normal | normal | + // normal | - | whisper | - | whisper | whisper | - | whisper | + // shout | - | whisper | normal | whisper | whisper | normal | whisper | + + RlvHandler& rlvHandler = gRlvHandler; + if ( ((CHAT_TYPE_SHOUT == chatType) || (CHAT_TYPE_NORMAL == chatType)) && (rlvHandler.hasBehaviour(RLV_BHVR_CHATNORMAL)) ) + chatType = CHAT_TYPE_WHISPER; + else if ( (CHAT_TYPE_SHOUT == chatType) && (rlvHandler.hasBehaviour(RLV_BHVR_CHATSHOUT)) ) + chatType = CHAT_TYPE_NORMAL; + else if ( (CHAT_TYPE_WHISPER == chatType) && (rlvHandler.hasBehaviour(RLV_BHVR_CHATWHISPER)) ) + chatType = CHAT_TYPE_NORMAL; + return chatType; +} + // ============================================================================ // Movement // -// Checked: 2010-12-11 (RLVa-1.2.2) bool RlvActions::canAcceptTpOffer(const LLUUID& idSender) { return ((!gRlvHandler.hasBehaviour(RLV_BHVR_TPLURE)) || (gRlvHandler.isException(RLV_BHVR_TPLURE, idSender))) && (canStand()); } -// Checked: 2013-11-08 (RLVa-1.4.9) bool RlvActions::autoAcceptTeleportOffer(const LLUUID& idSender) { return ((idSender.notNull()) && (gRlvHandler.isException(RLV_BHVR_ACCEPTTP, idSender))) || (gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTTP)); } -// Checked: 2013-11-08 (RLVa-1.4.9) bool RlvActions::canAcceptTpRequest(const LLUUID& idSender) { return (!gRlvHandler.hasBehaviour(RLV_BHVR_TPREQUEST)) || (gRlvHandler.isException(RLV_BHVR_TPREQUEST, idSender)); } -// Checked: 2013-11-08 (RLVa-1.4.9) bool RlvActions::autoAcceptTeleportRequest(const LLUUID& idRequester) { return ((idRequester.notNull()) && (gRlvHandler.isException(RLV_BHVR_ACCEPTTPREQUEST, idRequester))) || (gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTTPREQUEST)); diff --git a/indra/newview/rlvactions.h b/indra/newview/rlvactions.h index fbc8ab12ba..175926797e 100644 --- a/indra/newview/rlvactions.h +++ b/indra/newview/rlvactions.h @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2009-2013, Kitty Barnett + * Copyright (c) 2009-2016, Kitty Barnett * * The source code in this file is provided to you under the terms of the * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; @@ -17,6 +17,7 @@ #ifndef RLV_ACTIONS_H #define RLV_ACTIONS_H +#include "llchat.h" #include "rlvdefines.h" // ============================================================================ @@ -34,6 +35,11 @@ class RlvActions */ static bool canReceiveIM(const LLUUID& idSender); + /* + * Returns true if the user is allowed to chat on the specified channel + */ + static bool canSendChannel(int nChannel); + /* * Returns true if the user is allowed to send IMs to the specified recipient (can be an avatar or a group) */ @@ -53,6 +59,11 @@ class RlvActions static bool canShowName(EShowNamesContext eContext) { return (eContext < SNC_COUNT) ? !s_BlockNamesContexts[eContext] : false; } static void setShowName(EShowNamesContext eContext, bool fShowName) { if ( (eContext < SNC_COUNT) && (isRlvEnabled()) ) { s_BlockNamesContexts[eContext] = !fShowName; } } + /* + * Checks if the user is allowed to use the specified volume in (main) chat and returns the appropriate chat volume type + */ + static EChatType checkChatVolume(EChatType chatType); + protected: // Backwards logic so that we can initialize to 0 and it won't block when we forget to/don't check if RLVa is disabled static bool s_BlockNamesContexts[SNC_COUNT]; @@ -108,7 +119,7 @@ class RlvActions static bool hasBehaviour(ERlvBehaviour eBhvr); /* - * Returns true if a - P2P or group - IM session is open with the specified UUID. + * Returns true if a - P2P or group - IM session is open with the specified UUID */ static bool hasOpenP2PSession(const LLUUID& idAgent); static bool hasOpenGroupSession(const LLUUID& idGroup); diff --git a/indra/newview/rlvcommon.cpp b/indra/newview/rlvcommon.cpp index d6a6b9d3f6..7410c58970 100644 --- a/indra/newview/rlvcommon.cpp +++ b/indra/newview/rlvcommon.cpp @@ -459,11 +459,11 @@ bool RlvUtil::isNearbyAgent(const LLUUID& idAgent) RLV_ASSERT(idAgent.notNull()); if ( (idAgent.notNull()) && (gAgent.getID() != idAgent) ) { - std::vector idAgents; + uuid_vec_t idAgents; LLWorld::getInstance()->getAvatars(&idAgents, NULL); - for (int idxAgent = 0, cntAgent = idAgents.size(); idxAgent < cntAgent; idxAgent++) - if (idAgents[idxAgent] == idAgent) + for (const auto& id : idAgents) + if (id == idAgent) return true; } return false; diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index 31d70ef5fb..0127fc0758 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -57,14 +57,14 @@ // Version of the specifcation we support const S32 RLV_VERSION_MAJOR = 2; -const S32 RLV_VERSION_MINOR = 8; +const S32 RLV_VERSION_MINOR = 9; const S32 RLV_VERSION_PATCH = 0; const S32 RLV_VERSION_BUILD = 0; // Implementation version -const S32 RLVa_VERSION_MAJOR = 1; -const S32 RLVa_VERSION_MINOR = 4; -const S32 RLVa_VERSION_PATCH = 10; +const S32 RLVa_VERSION_MAJOR = 2; +const S32 RLVa_VERSION_MINOR = 1; +const S32 RLVa_VERSION_PATCH = 0; const S32 RLVa_VERSION_BUILD = 0; // Uncomment before a final release diff --git a/indra/newview/rlvfloaters.cpp b/indra/newview/rlvfloaters.cpp index b4c0e917f5..60441765b9 100644 --- a/indra/newview/rlvfloaters.cpp +++ b/indra/newview/rlvfloaters.cpp @@ -86,7 +86,7 @@ std::string rlvGetItemNameFromObjID(const LLUUID& idObj, bool fIncludeAttachPt = return strItemName; const LLViewerJointAttachment* pAttachPt = - get_if_there(gAgentAvatarp->mAttachmentPoints, RlvAttachPtLookup::getAttachPointIndex(pObjRoot), (LLViewerJointAttachment*)NULL); + get_if_there(gAgentAvatarp->mAttachmentPoints, RlvAttachPtLookup::getAttachPointIndex(pObjRoot), static_cast(NULL)); std::string strAttachPtName = (pAttachPt) ? pAttachPt->getName() : std::string("Unknown"); return llformat("%s (%s%s)", strItemName.c_str(), strAttachPtName.c_str(), (pObj == pObjRoot) ? "" : ", child"); } @@ -228,7 +228,7 @@ void RlvFloaterBehaviours::onAvatarNameLookup(const LLUUID& idAgent, const LLAva } // Checked: 2011-05-26 (RLVa-1.3.1c) | Added: RLVa-1.3.1c -void RlvFloaterBehaviours::onBtnCopyToClipboard() +void RlvFloaterBehaviours::onBtnCopyToClipboard() const { std::ostringstream strRestrictions; @@ -394,7 +394,7 @@ BOOL RlvFloaterLocks::postBuild() } // Checked: 2010-03-11 (RLVa-1.2.0a) | Added: RLVa-1.2.0a -void RlvFloaterLocks::onRlvCommand(const RlvCommand& rlvCmd, ERlvCmdRet eRet) +void RlvFloaterLocks::onRlvCommand(const RlvCommand& rlvCmd, ERlvCmdRet eRet) const { // Refresh on any successful @XXX=y|n command where XXX is any of the attachment or wearable locking behaviours if ( (RLV_RET_SUCCESS == eRet) && ((RLV_TYPE_ADD == rlvCmd.getParamType()) || (RLV_TYPE_REMOVE == rlvCmd.getParamType())) ) @@ -415,7 +415,7 @@ void RlvFloaterLocks::onRlvCommand(const RlvCommand& rlvCmd, ERlvCmdRet eRet) } // Checked: 2010-03-18 (RLVa-1.2.0) -void RlvFloaterLocks::refreshAll() +void RlvFloaterLocks::refreshAll() const { LLScrollListCtrl* pLockList = getChild("lock_list"); pLockList->operateOnAll(LLCtrlListInterface::OP_DELETE); @@ -460,7 +460,7 @@ void RlvFloaterLocks::refreshAll() itAttachPt != attachPtAdd.end(); ++itAttachPt) { const LLViewerJointAttachment* pAttachPt = - get_if_there(gAgentAvatarp->mAttachmentPoints, itAttachPt->first, (LLViewerJointAttachment*)NULL); + get_if_there(gAgentAvatarp->mAttachmentPoints, itAttachPt->first, static_cast(NULL)); sdColumns[2]["value"] = pAttachPt->getName(); sdColumns[3]["value"] = rlvGetItemNameFromObjID(itAttachPt->second); @@ -473,7 +473,7 @@ void RlvFloaterLocks::refreshAll() itAttachPt != attachPtRem.end(); ++itAttachPt) { const LLViewerJointAttachment* pAttachPt = - get_if_there(gAgentAvatarp->mAttachmentPoints, itAttachPt->first, (LLViewerJointAttachment*)NULL); + get_if_there(gAgentAvatarp->mAttachmentPoints, itAttachPt->first, static_cast(NULL)); sdColumns[2]["value"] = pAttachPt->getName(); sdColumns[3]["value"] = rlvGetItemNameFromObjID(itAttachPt->second); diff --git a/indra/newview/rlvfloaters.h b/indra/newview/rlvfloaters.h index daeac993b9..f055fe0e7a 100644 --- a/indra/newview/rlvfloaters.h +++ b/indra/newview/rlvfloaters.h @@ -53,7 +53,7 @@ class RlvFloaterBehaviours : public LLFloater */ protected: void onAvatarNameLookup(const LLUUID& idAgent, const LLAvatarName& avName); - void onBtnCopyToClipboard(); + void onBtnCopyToClipboard() const; void onCommand(const RlvCommand& rlvCmd, ERlvCmdRet eRet); void refreshAll(); @@ -88,8 +88,8 @@ class RlvFloaterLocks : public LLFloater * Member functions */ protected: - void onRlvCommand(const RlvCommand& rlvCmd, ERlvCmdRet eRet); - void refreshAll(); + void onRlvCommand(const RlvCommand& rlvCmd, ERlvCmdRet eRet) const; + void refreshAll() const; /* * Member variables diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 119b4332c5..09b7ab37c3 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -1035,7 +1035,7 @@ LLColor3 RlvHandler::camDrawColor() const case LLAssetType::AT_CLOTHING: { // NOTE: without its asset we don't know what type the wearable is so we need to look at the item's flags instead - LLWearableType::EType wtType = (LLWearableType::EType)(pItem->getFlags() & LLInventoryItem::II_FLAGS_WEARABLES_MASK); + LLWearableType::EType wtType = (LLWearableType::EType)(pItem->getFlags() & LLInventoryItem::II_FLAGS_SUBTYPE_MASK); LLViewerInventoryCategory* pFolder; if ( (!isWearable(wtType)) || ( (gAgent.getWearable(wtType)) && (!isRemovable(wtType)) ) || @@ -1791,18 +1791,24 @@ ERlvCmdRet RlvHandler::onForceRemAttach(const RlvCommand& rlvCmd) const // @remattach=force - force detach all attachments points else if ( (rlvCmdOption.isAttachmentPointGroup()) || (rlvCmdOption.isEmpty()) ) { - for (LLVOAvatar::attachment_map_t::const_iterator itAttach = gAgentAvatarp->mAttachmentPoints.begin(); - itAttach != gAgentAvatarp->mAttachmentPoints.end(); ++itAttach) + for (const auto& entryAttachPt : gAgentAvatarp->mAttachmentPoints) { - const LLViewerJointAttachment* pAttachPt = itAttach->second; - if ( (pAttachPt) && (pAttachPt->getNumObjects()) && - ((rlvCmdOption.isEmpty()) || (rlvAttachGroupFromIndex(pAttachPt->getGroup()) == rlvCmdOption.getAttachmentPointGroup())) ) + const LLViewerJointAttachment* pAttachPt = entryAttachPt.second; + if ( (pAttachPt) && (pAttachPt->getNumObjects()) && ((rlvCmdOption.isEmpty()) || (rlvAttachGroupFromIndex(pAttachPt->getGroup()) == rlvCmdOption.getAttachmentPointGroup())) ) { RlvForceWear::instance().forceDetach(pAttachPt); } } return RLV_RET_SUCCESS; } + // @remattach:=force - force detach a specific attachment + else if (rlvCmdOption.isUUID()) + { + const LLViewerObject* pAttachObj = gObjectList.findObject(rlvCmdOption.getUUID()); + if ( (pAttachObj) && (pAttachObj->isAttachment()) && (pAttachObj->permYouOwner()) ) + RlvForceWear::instance().forceDetach(pAttachObj); + return RLV_RET_SUCCESS; + } return RLV_RET_FAILED_OPTION; } @@ -1830,16 +1836,30 @@ ERlvCmdRet RlvHandler::onForceGroup(const RlvCommand& rlvCmd) const } LLUUID idGroup; bool fValid = false; - if (idGroup.set(rlvCmd.getOption())) + if ("none" == rlvCmd.getOption()) + { + idGroup.setNull(); + fValid = true; + } + else if (idGroup.set(rlvCmd.getOption())) { fValid = (idGroup.isNull()) || (gAgent.isInGroup(idGroup, true)); } else { - for (S32 idxGroup = 0, cntGroup = gAgent.mGroups.size(); (idxGroup < cntGroup) && (idGroup.isNull()); idxGroup++) - if (boost::iequals(gAgent.mGroups[idxGroup].mName, rlvCmd.getOption())) - idGroup = gAgent.mGroups[idxGroup].mID; - fValid = (idGroup.notNull()) || ("none" == rlvCmd.getOption()); + bool fExactMatch = false; + for (const auto& groupData : gAgent.mGroups) + { + // NOTE: exact matches take precedence over partial matches; in case of partial matches the last match wins + if (boost::istarts_with(groupData.mName, rlvCmd.getOption())) + { + idGroup = groupData.mID; + fExactMatch = groupData.mName.length() == rlvCmd.getOption().length(); + if (fExactMatch) + break; + } + } + fValid = idGroup.notNull(); } if (fValid) @@ -1955,27 +1975,21 @@ ERlvCmdRet RlvHandler::processReplyCommand(const RlvCommand& rlvCmd) const case RLV_BHVR_GETATTACH: // @getattach[:]= eRet = onGetAttach(rlvCmd, strReply); break; -#ifdef RLV_EXTENSION_CMD_GETXXXNAMES case RLV_BHVR_GETATTACHNAMES: // @getattachnames[:]= case RLV_BHVR_GETADDATTACHNAMES:// @getaddattachnames[:]= case RLV_BHVR_GETREMATTACHNAMES:// @getremattachnames[:]= eRet = onGetAttachNames(rlvCmd, strReply); break; -#endif // RLV_EXTENSION_CMD_GETXXXNAMES case RLV_BHVR_GETOUTFIT: // @getoutfit[:]= eRet = onGetOutfit(rlvCmd, strReply); break; -#ifdef RLV_EXTENSION_CMD_GETXXXNAMES case RLV_BHVR_GETOUTFITNAMES: // @getoutfitnames= case RLV_BHVR_GETADDOUTFITNAMES:// @getaddoutfitnames= case RLV_BHVR_GETREMOUTFITNAMES:// @getremoutfitnames= eRet = onGetOutfitNames(rlvCmd, strReply); break; -#endif // RLV_EXTENSION_CMD_GETXXXNAMES case RLV_BHVR_FINDFOLDER: // @findfolder:= -#ifdef RLV_EXTENSION_CMD_FINDFOLDERS case RLV_BHVR_FINDFOLDERS: // @findfolders:= -#endif // RLV_EXTENSION_CMD_FINDFOLDERS eRet = onFindFolder(rlvCmd, strReply); break; case RLV_BHVR_GETPATH: // @getpath[: diff --git a/indra/newview/skins/apollo/colors.xml b/indra/newview/skins/apollo/colors.xml index 155efaceea..970076ed34 100644 --- a/indra/newview/skins/apollo/colors.xml +++ b/indra/newview/skins/apollo/colors.xml @@ -103,6 +103,7 @@ + @@ -185,7 +186,6 @@ - diff --git a/indra/newview/skins/apollo/keywords.ini b/indra/newview/skins/apollo/keywords.ini index 8d0fd6b718..33130fc758 100644 --- a/indra/newview/skins/apollo/keywords.ini +++ b/indra/newview/skins/apollo/keywords.ini @@ -54,6 +54,9 @@ http_response http_response(key request_id, integer status, list metad http_request http_request(key id, string method, string body):Triggered when task receives an http request against a public URL transaction_result transaction_result(key id, integer success, string data): Triggered when currency is given to task path_update path_update(integer type, list reserved):Triggered when the state of a pathfinder character changes. Note; "list reserved" is not currently used +experience_permissions experience_permissions(key agent): Triggered when agent has approved an experience permissions request. This may be through interaction with the experience permission dialog or the experience profile, or automatically if the agent has previously approved the experience. +experience_permissions_denied experience_permissions_denied(key agent, integer reason): Triggered when agent has denied experience permission. reason is the reason for denial; one of the Experience Tools XP_ERROR_* errors flags. + # integer constants [word .679, .503, .996] @@ -102,6 +105,23 @@ PERMISSION_TELEPORT Passed to llRequestPermissions library function to reque SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT Passed to llRequestPermissions library function to request permission to silently modify estate access lists PERMISSION_OVERRIDE_ANIMATIONS Passed to llRequestPermissions library function to request permission to override animations on agent PERMISSION_RETURN_OBJECTS Passed to llRequestPermissions library function to request permission to return objects +XP_ERROR_NONE No error was detected. +XP_ERROR_THROTTLED The call failed due to too many recent calls. +XP_ERROR_EXPERIENCES_DISABLED The region currently has experiences disabled. +XP_ERROR_INVALID_PARAMETERS One of the string arguments was too big to fit in the key-value store. +XP_ERROR_NOT_PERMITTED This experience is not allowed to run on the current region. +XP_ERROR_NO_EXPERIENCE This script is not associated with an experience. +XP_ERROR_NOT_FOUND The sim was unable to verify the validity of the experience. Retrying after a short wait is advised. +XP_ERROR_INVALID_EXPERIENCE The script is associated with an experience that no longer exists. +XP_ERROR_EXPERIENCE_DISABLED The experience owner has temporarily disabled the experience. +XP_ERROR_EXPERIENCE_SUSPENDED The experience has been suspended by Linden Lab customer support. +XP_ERROR_UNKNOWN_ERROR An unknown error not covered by any of the other predetermined error states. +XP_ERROR_QUOTA_EXCEEDED An attempt to write data to the key-value store failed due to the data quota being met. +XP_ERROR_STORE_DISABLED The key-value store is currently disabled on this region. +XP_ERROR_STORAGE_EXCEPTION Unable to communicate with the key-value store. +XP_ERROR_KEY_NOT_FOUND The requested key does not exist. +XP_ERROR_RETRY_UPDATE A checked update failed due to an out of date request. +XP_ERROR_MATURITY_EXCEEDED The content rating of the experience exceeds that of the region. DEBUG_CHANNEL Chat channel reserved for debug and error messages from scripts PUBLIC_CHANNEL Chat channel that broadcasts to all nearby users @@ -182,6 +202,8 @@ PSYS_SRC_PATTERN_ANGLE_CONE PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY OBJECT_UNKNOWN_DETAIL Returned by llGetObjectDetails when passed an invalid object parameter type +OBJECT_HOVER_HEIGHT This is a flag used with llGetObjectDetails to get hover height of the avatar. If no data is available, 0.0 is returned. +OBJECT_LAST_OWNER_ID Gets the object's last owner ID. OBJECT_NAME Used with llGetObjectDetails to get an object's name OBJECT_DESC Used with llGetObjectDetails to get an object's description OBJECT_POS Used with llGetObjectDetails to get an object's position @@ -189,6 +211,7 @@ OBJECT_ROT Used with llGetObjectDetails to get an o OBJECT_VELOCITY Used with llGetObjectDetails to get an object's velocity OBJECT_OWNER Used with llGetObjectDetails to get an object's owner's key. Will be NULL_KEY if group owned OBJECT_GROUP Used with llGetObjectDetails to get an object's group's key +OBJECT_CLICK_ACTION This is a flag used with llGetObjectDetails to get the click action. The default is 0. OBJECT_CREATOR Used with llGetObjectDetails to get an object's creator's key OBJECT_RUNNING_SCRIPT_COUNT Gets the number of running scripts attached to the object or agent OBJECT_TOTAL_SCRIPT_COUNT Gets the number of scripts, both running and stopped, attached to the object or agent. @@ -199,6 +222,7 @@ OBJECT_SERVER_COST Used with llGetObjectDetails to get the OBJECT_STREAMING_COST Used with llGetObjectDetails to get the streaming (download) cost. OBJECT_PHYSICS_COST Used with llGetObjectDetails to get the physics cost. OBJECT_PATHFINDING_TYPE Used with llGetObjectDetails to get an object's pathfinding settings. +OBJECT_BODY_SHAPE_TYPE This is a flag used with llGetObjectDetails to get the body type of the avatar, based on shape data. If no data is available, -1.0 is returned. This is normally between 0 and 1.0, with 0.5 and larger considered 'male' OBJECT_CHARACTER_TIME Used with llGetObjectDetails to get an object's average CPU time (in seconds) used by the object for navigation, if the object is a pathfinding character. Returns 0 for non-characters. OBJECT_ROOT Used with llGetObjectDetails to get an object's root prim ID. OBJECT_ATTACHED_POINT Used with llGetObjectDetails to get an object's attachment point. @@ -915,6 +939,25 @@ TEXTURE_TRANSPARENT UUID for the "White - Transparent" texture URL_REQUEST_GRANTED Used with http_request when a public URL is successfully granted URL_REQUEST_DENIED Used with http_request when a public URL is not available +XP_ERROR_NONE No error was detected +XP_ERROR_THROTTLED The call failed due to too many recent calls. +XP_ERROR_EXPERIENCES_DISABLED The region currently has experiences disabled. +XP_ERROR_INVALID_PARAMETERS One of the string arguments was too big to fit in the key-value store. +XP_ERROR_NOT_PERMITTED This experience is not allowed to run on the current region. +XP_ERROR_NO_EXPERIENCE This script is not associated with an experience. +XP_ERROR_NOT_FOUND The sim was unable to verify the validity of the experience. Retrying after a short wait is advised. +XP_ERROR_INVALID_EXPERIENCE The script is associated with an experience that no longer exists. +XP_ERROR_EXPERIENCE_DISABLED The experience owner has temporarily disabled the experience. +XP_ERROR_EXPERIENCE_SUSPENDED The experience has been suspended by Linden Customer Support. +XP_ERROR_QUOTA_EXCEEDED An attempted write data to the key-value store failed due to the data quota being met. +XP_ERROR_STORE_DISABLED The key-value store is currently disabled on this region. +XP_ERROR_STORAGE_EXCEPTION Unable to communicate with the key-value store. +XP_ERROR_KEY_NOT_FOUND The requested key does not exist. +XP_ERROR_RETRY_UPDATE A checked update failed due to an out of date request. +XP_ERROR_MATURITY_EXCEEDED The request failed due to agent content preferences. +XP_ERROR_UNKNOWN_ERROR Other unknown error. + + # float constants [word .679, .503, .996] PI 3.1415926535897932384626433832795 diff --git a/indra/newview/skins/apollo/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/apollo/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e3793097..0000000000 Binary files a/indra/newview/skins/apollo/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/account_id_green.tga b/indra/newview/skins/apollo/textures/account_id_green.tga deleted file mode 100644 index 9be215eed4..0000000000 Binary files a/indra/newview/skins/apollo/textures/account_id_green.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/account_id_orange.tga b/indra/newview/skins/apollo/textures/account_id_orange.tga deleted file mode 100644 index 6b41e86632..0000000000 Binary files a/indra/newview/skins/apollo/textures/account_id_orange.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/active_speakers.tga b/indra/newview/skins/apollo/textures/active_speakers.tga deleted file mode 100644 index 02d3643d7f..0000000000 Binary files a/indra/newview/skins/apollo/textures/active_speakers.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/active_voice_tab.tga b/indra/newview/skins/apollo/textures/active_voice_tab.tga deleted file mode 100644 index 2d0dfaabc5..0000000000 Binary files a/indra/newview/skins/apollo/textures/active_voice_tab.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/alpha_gradient.tga b/indra/newview/skins/apollo/textures/alpha_gradient.tga deleted file mode 100644 index 6fdba25d4e..0000000000 Binary files a/indra/newview/skins/apollo/textures/alpha_gradient.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/arrow_down.tga b/indra/newview/skins/apollo/textures/arrow_down.tga deleted file mode 100644 index 81dc9d3b6c..0000000000 Binary files a/indra/newview/skins/apollo/textures/arrow_down.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/arrow_up.tga b/indra/newview/skins/apollo/textures/arrow_up.tga deleted file mode 100644 index 22195cf7fb..0000000000 Binary files a/indra/newview/skins/apollo/textures/arrow_up.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/avatar_gone.tga b/indra/newview/skins/apollo/textures/avatar_gone.tga deleted file mode 100644 index e5c2c070bc..0000000000 Binary files a/indra/newview/skins/apollo/textures/avatar_gone.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/avatar_new.tga b/indra/newview/skins/apollo/textures/avatar_new.tga deleted file mode 100644 index 854b70c326..0000000000 Binary files a/indra/newview/skins/apollo/textures/avatar_new.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/avatar_typing.tga b/indra/newview/skins/apollo/textures/avatar_typing.tga deleted file mode 100644 index 2c549025dd..0000000000 Binary files a/indra/newview/skins/apollo/textures/avatar_typing.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/button_anim_pause_disabled.tga b/indra/newview/skins/apollo/textures/button_anim_pause_disabled.tga deleted file mode 100644 index 4d604c63c3..0000000000 Binary files a/indra/newview/skins/apollo/textures/button_anim_pause_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/button_anim_play_disabled.tga b/indra/newview/skins/apollo/textures/button_anim_play_disabled.tga deleted file mode 100644 index 444062f375..0000000000 Binary files a/indra/newview/skins/apollo/textures/button_anim_play_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/button_anim_stop_disabled.tga b/indra/newview/skins/apollo/textures/button_anim_stop_disabled.tga deleted file mode 100644 index cf1532a426..0000000000 Binary files a/indra/newview/skins/apollo/textures/button_anim_stop_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/checkerboard_transparency_bg.png b/indra/newview/skins/apollo/textures/checkerboard_transparency_bg.png deleted file mode 100644 index fe06d38eff..0000000000 Binary files a/indra/newview/skins/apollo/textures/checkerboard_transparency_bg.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/circle.tga b/indra/newview/skins/apollo/textures/circle.tga deleted file mode 100644 index d7097e3a35..0000000000 Binary files a/indra/newview/skins/apollo/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/color_swatch_alpha.tga b/indra/newview/skins/apollo/textures/color_swatch_alpha.tga deleted file mode 100644 index 814a004e62..0000000000 Binary files a/indra/newview/skins/apollo/textures/color_swatch_alpha.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/crosshairs.tga b/indra/newview/skins/apollo/textures/crosshairs.tga deleted file mode 100644 index ac4d63dc59..0000000000 Binary files a/indra/newview/skins/apollo/textures/crosshairs.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/down_arrow.png b/indra/newview/skins/apollo/textures/down_arrow.png deleted file mode 100644 index d376d980d2..0000000000 Binary files a/indra/newview/skins/apollo/textures/down_arrow.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/ff_edit_mine.tga b/indra/newview/skins/apollo/textures/ff_edit_mine.tga deleted file mode 100644 index 8f0c35b98f..0000000000 Binary files a/indra/newview/skins/apollo/textures/ff_edit_mine.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/ff_edit_theirs.tga b/indra/newview/skins/apollo/textures/ff_edit_theirs.tga deleted file mode 100644 index 005ada2dea..0000000000 Binary files a/indra/newview/skins/apollo/textures/ff_edit_theirs.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/ff_visible_map.tga b/indra/newview/skins/apollo/textures/ff_visible_map.tga deleted file mode 100644 index a4dad78dad..0000000000 Binary files a/indra/newview/skins/apollo/textures/ff_visible_map.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/ff_visible_online.tga b/indra/newview/skins/apollo/textures/ff_visible_online.tga deleted file mode 100644 index 74e3a4e318..0000000000 Binary files a/indra/newview/skins/apollo/textures/ff_visible_online.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef32..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa9..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1f..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0f..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f9461..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad344..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_clear_lineeditor.tga b/indra/newview/skins/apollo/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c66..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-pause.tga b/indra/newview/skins/apollo/textures/icn_media-pause.tga deleted file mode 100644 index 0713af0b40..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-pause.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-pause_active.tga b/indra/newview/skins/apollo/textures/icn_media-pause_active.tga deleted file mode 100644 index 21384316a8..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-pause_active.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-pause_disabled.tga b/indra/newview/skins/apollo/textures/icn_media-pause_disabled.tga deleted file mode 100644 index 4d604c63c3..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-pause_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-pause_enabled.tga b/indra/newview/skins/apollo/textures/icn_media-pause_enabled.tga deleted file mode 100644 index 577f9195d0..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-pause_enabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-play.tga b/indra/newview/skins/apollo/textures/icn_media-play.tga deleted file mode 100644 index bdd9f16110..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-play.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-play_active.tga b/indra/newview/skins/apollo/textures/icn_media-play_active.tga deleted file mode 100644 index b166a4178d..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-play_active.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-play_disabled.tga b/indra/newview/skins/apollo/textures/icn_media-play_disabled.tga deleted file mode 100644 index 444062f375..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-play_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-play_enabled.tga b/indra/newview/skins/apollo/textures/icn_media-play_enabled.tga deleted file mode 100644 index 9ed55f829d..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-play_enabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-stop_active.tga b/indra/newview/skins/apollo/textures/icn_media-stop_active.tga deleted file mode 100644 index 03efac206f..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-stop_active.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-stop_disabled.tga b/indra/newview/skins/apollo/textures/icn_media-stop_disabled.tga deleted file mode 100644 index cf1532a426..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-stop_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-stop_enabled.tga b/indra/newview/skins/apollo/textures/icn_media-stop_enabled.tga deleted file mode 100644 index 011b98c496..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-stop_enabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media.tga b/indra/newview/skins/apollo/textures/icn_media.tga deleted file mode 100644 index 43dd342c9d..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_music-pause.tga b/indra/newview/skins/apollo/textures/icn_music-pause.tga deleted file mode 100644 index 548ccf4e47..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_music-pause.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_music-play.tga b/indra/newview/skins/apollo/textures/icn_music-play.tga deleted file mode 100644 index 1a67d3440a..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_music-play.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_music.tga b/indra/newview/skins/apollo/textures/icn_music.tga deleted file mode 100644 index 9470601dbf..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_music.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_scrollbar.tga b/indra/newview/skins/apollo/textures/icn_scrollbar.tga deleted file mode 100644 index a19a8a5d1a..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_scrollbar.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_scrollbar_bg.tga b/indra/newview/skins/apollo/textures/icn_scrollbar_bg.tga deleted file mode 100644 index 1e4bc7a8a3..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_scrollbar_bg.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_scrollbar_thumb.tga b/indra/newview/skins/apollo/textures/icn_scrollbar_thumb.tga deleted file mode 100644 index d63c314724..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_scrollbar_thumb.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_speaker-muted_dark.tga b/indra/newview/skins/apollo/textures/icn_speaker-muted_dark.tga deleted file mode 100644 index a7d29a14b9..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_speaker-muted_dark.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_stop.tga b/indra/newview/skins/apollo/textures/icn_stop.tga deleted file mode 100644 index 7a53bccc2f..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_stop.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_textfield_enabled.tga b/indra/newview/skins/apollo/textures/icn_textfield_enabled.tga deleted file mode 100644 index fc681a1957..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_textfield_enabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice-call-end.tga b/indra/newview/skins/apollo/textures/icn_voice-call-end.tga deleted file mode 100644 index 2da4e856b4..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice-call-end.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice-call-start.tga b/indra/newview/skins/apollo/textures/icn_voice-call-start.tga deleted file mode 100644 index 07701cb5a2..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice-call-start.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice-groupfocus.tga b/indra/newview/skins/apollo/textures/icn_voice-groupfocus.tga deleted file mode 100644 index 9f48d4609d..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice-groupfocus.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice-localchat.tga b/indra/newview/skins/apollo/textures/icn_voice-localchat.tga deleted file mode 100644 index 7cf267eaf5..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice-localchat.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice-pvtfocus.tga b/indra/newview/skins/apollo/textures/icn_voice-pvtfocus.tga deleted file mode 100644 index abadb09aaf..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice-pvtfocus.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice_ptt-off.tga b/indra/newview/skins/apollo/textures/icn_voice_ptt-off.tga deleted file mode 100644 index 15ecbdff95..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice_ptt-off.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl1.tga b/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl1.tga deleted file mode 100644 index ae72af131d..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl2.tga b/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl2.tga deleted file mode 100644 index 4dfc2dd292..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl3.tga b/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl3.tga deleted file mode 100644 index 018b0bef42..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl3.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice_ptt-on.tga b/indra/newview/skins/apollo/textures/icn_voice_ptt-on.tga deleted file mode 100644 index 9eb6431106..0000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice_ptt-on.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_auction.tga b/indra/newview/skins/apollo/textures/icon_auction.tga deleted file mode 100644 index d121833b47..0000000000 Binary files a/indra/newview/skins/apollo/textures/icon_auction.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_avatar_online.tga b/indra/newview/skins/apollo/textures/icon_avatar_online.tga deleted file mode 100644 index 45221213eb..0000000000 Binary files a/indra/newview/skins/apollo/textures/icon_avatar_online.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_day_cycle.tga b/indra/newview/skins/apollo/textures/icon_day_cycle.tga deleted file mode 100644 index 2d5dee1e94..0000000000 Binary files a/indra/newview/skins/apollo/textures/icon_day_cycle.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_diurnal.tga b/indra/newview/skins/apollo/textures/icon_diurnal.tga deleted file mode 100644 index fc720c8269..0000000000 Binary files a/indra/newview/skins/apollo/textures/icon_diurnal.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_event_mature.tga b/indra/newview/skins/apollo/textures/icon_event_mature.tga deleted file mode 100644 index 61c879bc92..0000000000 Binary files a/indra/newview/skins/apollo/textures/icon_event_mature.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_popular.tga b/indra/newview/skins/apollo/textures/icon_popular.tga deleted file mode 100644 index f1165b8aaa..0000000000 Binary files a/indra/newview/skins/apollo/textures/icon_popular.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/lag_status_critical.tga b/indra/newview/skins/apollo/textures/lag_status_critical.tga deleted file mode 100644 index bbc71d9e77..0000000000 Binary files a/indra/newview/skins/apollo/textures/lag_status_critical.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/lag_status_good.tga b/indra/newview/skins/apollo/textures/lag_status_good.tga deleted file mode 100644 index 680ba90f17..0000000000 Binary files a/indra/newview/skins/apollo/textures/lag_status_good.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/lag_status_warning.tga b/indra/newview/skins/apollo/textures/lag_status_warning.tga deleted file mode 100644 index 13ce3cc396..0000000000 Binary files a/indra/newview/skins/apollo/textures/lag_status_warning.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/legend.tga b/indra/newview/skins/apollo/textures/legend.tga deleted file mode 100644 index 0dbb8fda4f..0000000000 Binary files a/indra/newview/skins/apollo/textures/legend.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/lightgray.tga b/indra/newview/skins/apollo/textures/lightgray.tga deleted file mode 100644 index 2063d685aa..0000000000 Binary files a/indra/newview/skins/apollo/textures/lightgray.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_16.tga b/indra/newview/skins/apollo/textures/map_avatar_16.tga deleted file mode 100644 index ce129e3590..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_16.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_32.tga b/indra/newview/skins/apollo/textures/map_avatar_32.tga deleted file mode 100644 index aebeab4093..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_32.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_8.tga b/indra/newview/skins/apollo/textures/map_avatar_8.tga deleted file mode 100644 index 28552f2237..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_8.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_above_32.tga b/indra/newview/skins/apollo/textures/map_avatar_above_32.tga deleted file mode 100644 index 65bd0561a7..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_above_32.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_above_8.tga b/indra/newview/skins/apollo/textures/map_avatar_above_8.tga deleted file mode 100644 index 193428e530..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_above_8.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_below_32.tga b/indra/newview/skins/apollo/textures/map_avatar_below_32.tga deleted file mode 100644 index 496c44b369..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_below_32.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_below_8.tga b/indra/newview/skins/apollo/textures/map_avatar_below_8.tga deleted file mode 100644 index 9e14bfab90..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_below_8.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_you_32.tga b/indra/newview/skins/apollo/textures/map_avatar_you_32.tga deleted file mode 100644 index 782207efd6..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_you_32.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_you_8.tga b/indra/newview/skins/apollo/textures/map_avatar_you_8.tga deleted file mode 100644 index 61f319fd9d..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_you_8.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_home.tga b/indra/newview/skins/apollo/textures/map_home.tga deleted file mode 100644 index 7478de371a..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_home.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_infohub.tga b/indra/newview/skins/apollo/textures/map_infohub.tga deleted file mode 100644 index 173b93e399..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_track_16.tga b/indra/newview/skins/apollo/textures/map_track_16.tga deleted file mode 100644 index 451ce24cf0..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_track_16.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_track_8.tga b/indra/newview/skins/apollo/textures/map_track_8.tga deleted file mode 100644 index 53425ff45b..0000000000 Binary files a/indra/newview/skins/apollo/textures/map_track_8.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/media_icon.tga b/indra/newview/skins/apollo/textures/media_icon.tga deleted file mode 100644 index 289520cde8..0000000000 Binary files a/indra/newview/skins/apollo/textures/media_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/minimize.tga b/indra/newview/skins/apollo/textures/minimize.tga deleted file mode 100644 index a21fd91481..0000000000 Binary files a/indra/newview/skins/apollo/textures/minimize.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/missing_asset.tga b/indra/newview/skins/apollo/textures/missing_asset.tga deleted file mode 100644 index 9a43f4db5d..0000000000 Binary files a/indra/newview/skins/apollo/textures/missing_asset.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/music_icon.tga b/indra/newview/skins/apollo/textures/music_icon.tga deleted file mode 100644 index aeaff02e0a..0000000000 Binary files a/indra/newview/skins/apollo/textures/music_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/mute_icon.tga b/indra/newview/skins/apollo/textures/mute_icon.tga deleted file mode 100644 index 879b9e6188..0000000000 Binary files a/indra/newview/skins/apollo/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/notify_box_icon.tga b/indra/newview/skins/apollo/textures/notify_box_icon.tga deleted file mode 100644 index 0672c89ee2..0000000000 Binary files a/indra/newview/skins/apollo/textures/notify_box_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/notify_caution_icon.tga b/indra/newview/skins/apollo/textures/notify_caution_icon.tga deleted file mode 100644 index abc23d1d7a..0000000000 Binary files a/indra/newview/skins/apollo/textures/notify_caution_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/notify_tip_icon.tga b/indra/newview/skins/apollo/textures/notify_tip_icon.tga deleted file mode 100644 index f79a634a91..0000000000 Binary files a/indra/newview/skins/apollo/textures/notify_tip_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/progress_fill.tga b/indra/newview/skins/apollo/textures/progress_fill.tga deleted file mode 100644 index a913fe7627..0000000000 Binary files a/indra/newview/skins/apollo/textures/progress_fill.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/propertyline.tga b/indra/newview/skins/apollo/textures/propertyline.tga deleted file mode 100644 index 0c504eea71..0000000000 Binary files a/indra/newview/skins/apollo/textures/propertyline.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_dark.png b/indra/newview/skins/apollo/textures/skin_thumbnail_dark.png deleted file mode 100644 index fc102a0147..0000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_dark.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_default.png b/indra/newview/skins/apollo/textures/skin_thumbnail_default.png deleted file mode 100644 index e22b1c1644..0000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_default.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_gred.png b/indra/newview/skins/apollo/textures/skin_thumbnail_gred.png deleted file mode 100644 index d605847434..0000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_gred.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_phoenix.png b/indra/newview/skins/apollo/textures/skin_thumbnail_phoenix.png deleted file mode 100644 index f2ab49e6db..0000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_phoenix.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_pslgreen.png b/indra/newview/skins/apollo/textures/skin_thumbnail_pslgreen.png deleted file mode 100644 index 3eb7263d6a..0000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_pslgreen.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_pslpurple.png b/indra/newview/skins/apollo/textures/skin_thumbnail_pslpurple.png deleted file mode 100644 index 877514d8cc..0000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_pslpurple.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_ruby.png b/indra/newview/skins/apollo/textures/skin_thumbnail_ruby.png deleted file mode 100644 index 944b519857..0000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_ruby.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_saphire.png b/indra/newview/skins/apollo/textures/skin_thumbnail_saphire.png deleted file mode 100644 index 2ee8967807..0000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_saphire.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_silver.png b/indra/newview/skins/apollo/textures/skin_thumbnail_silver.png deleted file mode 100644 index 51f4cceb08..0000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_silver.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/slim_icon_16_viewer.tga b/indra/newview/skins/apollo/textures/slim_icon_16_viewer.tga deleted file mode 100644 index 552181d36a..0000000000 Binary files a/indra/newview/skins/apollo/textures/slim_icon_16_viewer.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/sm_rounded_corners_simple.tga b/indra/newview/skins/apollo/textures/sm_rounded_corners_simple.tga deleted file mode 100644 index 85157e4612..0000000000 Binary files a/indra/newview/skins/apollo/textures/sm_rounded_corners_simple.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/smicon_warn.tga b/indra/newview/skins/apollo/textures/smicon_warn.tga deleted file mode 100644 index 90ccaa07e5..0000000000 Binary files a/indra/newview/skins/apollo/textures/smicon_warn.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spacer24.tga b/indra/newview/skins/apollo/textures/spacer24.tga deleted file mode 100644 index c7cab6b38c..0000000000 Binary files a/indra/newview/skins/apollo/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spacer35.tga b/indra/newview/skins/apollo/textures/spacer35.tga deleted file mode 100644 index b88bc6680a..0000000000 Binary files a/indra/newview/skins/apollo/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spin_down_in_blue.tga b/indra/newview/skins/apollo/textures/spin_down_in_blue.tga deleted file mode 100644 index b9eb36ba9f..0000000000 Binary files a/indra/newview/skins/apollo/textures/spin_down_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spin_down_out_blue.tga b/indra/newview/skins/apollo/textures/spin_down_out_blue.tga deleted file mode 100644 index c9cb5e8bf6..0000000000 Binary files a/indra/newview/skins/apollo/textures/spin_down_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spin_up_in_blue.tga b/indra/newview/skins/apollo/textures/spin_up_in_blue.tga deleted file mode 100644 index b604b8843c..0000000000 Binary files a/indra/newview/skins/apollo/textures/spin_up_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spin_up_out_blue.tga b/indra/newview/skins/apollo/textures/spin_up_out_blue.tga deleted file mode 100644 index 4e3941e458..0000000000 Binary files a/indra/newview/skins/apollo/textures/spin_up_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_busy.tga b/indra/newview/skins/apollo/textures/status_busy.tga deleted file mode 100644 index 7743d9c7bb..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_busy.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_health.tga b/indra/newview/skins/apollo/textures/status_health.tga deleted file mode 100644 index 3d5f455fcd..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_health.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_money.tga b/indra/newview/skins/apollo/textures/status_money.tga deleted file mode 100644 index d5be31fc60..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_money.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_no_build.tga b/indra/newview/skins/apollo/textures/status_no_build.tga deleted file mode 100644 index 8e471e1851..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_no_build.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_no_fly.tga b/indra/newview/skins/apollo/textures/status_no_fly.tga deleted file mode 100644 index cde2700ab2..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_no_fly.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_no_push.tga b/indra/newview/skins/apollo/textures/status_no_push.tga deleted file mode 100644 index 5ccbfa50f1..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_no_push.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_no_scripts.tga b/indra/newview/skins/apollo/textures/status_no_scripts.tga deleted file mode 100644 index 52ecdb1b84..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_no_scripts.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_no_voice.tga b/indra/newview/skins/apollo/textures/status_no_voice.tga deleted file mode 100644 index 4ab4498cbc..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_no_voice.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_script_debug.tga b/indra/newview/skins/apollo/textures/status_script_debug.tga deleted file mode 100644 index 6fca614835..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_script_debug.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_search.tga b/indra/newview/skins/apollo/textures/status_search.tga deleted file mode 100644 index 3ac10c4769..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_search.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_search_btn.png b/indra/newview/skins/apollo/textures/status_search_btn.png deleted file mode 100644 index e648ba8490..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_search_btn.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_search_btn_pressed.png b/indra/newview/skins/apollo/textures/status_search_btn_pressed.png deleted file mode 100644 index ec4254f4d9..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_search_btn_pressed.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_voice.tga b/indra/newview/skins/apollo/textures/status_voice.tga deleted file mode 100644 index 4ab4498cbc..0000000000 Binary files a/indra/newview/skins/apollo/textures/status_voice.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/tab_background_darkpurple.tga b/indra/newview/skins/apollo/textures/tab_background_darkpurple.tga deleted file mode 100644 index 8169f98694..0000000000 Binary files a/indra/newview/skins/apollo/textures/tab_background_darkpurple.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/tab_background_lightgrey.tga b/indra/newview/skins/apollo/textures/tab_background_lightgrey.tga deleted file mode 100644 index c2f8818f73..0000000000 Binary files a/indra/newview/skins/apollo/textures/tab_background_lightgrey.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/tab_background_purple.tga b/indra/newview/skins/apollo/textures/tab_background_purple.tga deleted file mode 100644 index aa01b3cb68..0000000000 Binary files a/indra/newview/skins/apollo/textures/tab_background_purple.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/tabarea.tga b/indra/newview/skins/apollo/textures/tabarea.tga deleted file mode 100644 index 5517aebfc8..0000000000 Binary files a/indra/newview/skins/apollo/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/textures.xml b/indra/newview/skins/apollo/textures/textures.xml index 2c4b0cbea6..48fcecbfeb 100644 --- a/indra/newview/skins/apollo/textures/textures.xml +++ b/indra/newview/skins/apollo/textures/textures.xml @@ -1,382 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/indra/newview/skins/apollo/textures/toolbar_bg.tga b/indra/newview/skins/apollo/textures/toolbar_bg.tga deleted file mode 100644 index 3a05776276..0000000000 Binary files a/indra/newview/skins/apollo/textures/toolbar_bg.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/toolbar_tab.tga b/indra/newview/skins/apollo/textures/toolbar_tab.tga deleted file mode 100644 index 5ea1a28d29..0000000000 Binary files a/indra/newview/skins/apollo/textures/toolbar_tab.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/up_arrow.png b/indra/newview/skins/apollo/textures/up_arrow.png deleted file mode 100644 index a1a5d38233..0000000000 Binary files a/indra/newview/skins/apollo/textures/up_arrow.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/up_arrow.tga b/indra/newview/skins/apollo/textures/up_arrow.tga deleted file mode 100644 index c2bd8ccebf..0000000000 Binary files a/indra/newview/skins/apollo/textures/up_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/uv_test2.tga b/indra/newview/skins/apollo/textures/uv_test2.tga deleted file mode 100644 index a16000d1e4..0000000000 Binary files a/indra/newview/skins/apollo/textures/uv_test2.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/white.tga b/indra/newview/skins/apollo/textures/white.tga deleted file mode 100644 index 9fe68631cf..0000000000 Binary files a/indra/newview/skins/apollo/textures/white.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/colors.xml b/indra/newview/skins/blackdark/colors.xml index e076f94ebe..99773245ce 100644 --- a/indra/newview/skins/blackdark/colors.xml +++ b/indra/newview/skins/blackdark/colors.xml @@ -168,7 +168,6 @@ - diff --git a/indra/newview/skins/blackdark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/blackdark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e3793097..0000000000 Binary files a/indra/newview/skins/blackdark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/circle.tga b/indra/newview/skins/blackdark/textures/circle.tga deleted file mode 100644 index d7097e3a35..0000000000 Binary files a/indra/newview/skins/blackdark/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef32..0000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa9..0000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1f..0000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0f..0000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f9461..0000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad344..0000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_clear_lineeditor.tga b/indra/newview/skins/blackdark/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c66..0000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/map_infohub.tga b/indra/newview/skins/blackdark/textures/map_infohub.tga deleted file mode 100644 index 173b93e399..0000000000 Binary files a/indra/newview/skins/blackdark/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/mute_icon.tga b/indra/newview/skins/blackdark/textures/mute_icon.tga deleted file mode 100644 index 879b9e6188..0000000000 Binary files a/indra/newview/skins/blackdark/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/rounded_square.j2c b/indra/newview/skins/blackdark/textures/rounded_square.j2c deleted file mode 100644 index c3dfe8f10e..0000000000 Binary files a/indra/newview/skins/blackdark/textures/rounded_square.j2c and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/spacer24.tga b/indra/newview/skins/blackdark/textures/spacer24.tga deleted file mode 100644 index c7cab6b38c..0000000000 Binary files a/indra/newview/skins/blackdark/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/spacer35.tga b/indra/newview/skins/blackdark/textures/spacer35.tga deleted file mode 100644 index b88bc6680a..0000000000 Binary files a/indra/newview/skins/blackdark/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/tabarea.tga b/indra/newview/skins/blackdark/textures/tabarea.tga deleted file mode 100644 index 5517aebfc8..0000000000 Binary files a/indra/newview/skins/blackdark/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/textures.xml b/indra/newview/skins/blackdark/textures/textures.xml index 9f617f56b5..1d61522a18 100644 --- a/indra/newview/skins/blackdark/textures/textures.xml +++ b/indra/newview/skins/blackdark/textures/textures.xml @@ -1,385 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/indra/newview/skins/blacklightblue/colors.xml b/indra/newview/skins/blacklightblue/colors.xml index ac4ad8772d..ef813f43f5 100644 --- a/indra/newview/skins/blacklightblue/colors.xml +++ b/indra/newview/skins/blacklightblue/colors.xml @@ -168,7 +168,6 @@ - diff --git a/indra/newview/skins/blacklightblue/textures/icon_diurnal.tga b/indra/newview/skins/blacklightblue/textures/icon_diurnal.tga deleted file mode 100644 index fc720c8269..0000000000 Binary files a/indra/newview/skins/blacklightblue/textures/icon_diurnal.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/map_infohub.tga b/indra/newview/skins/blacklightblue/textures/map_infohub.tga deleted file mode 100644 index 173b93e399..0000000000 Binary files a/indra/newview/skins/blacklightblue/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/mute_icon.tga b/indra/newview/skins/blacklightblue/textures/mute_icon.tga deleted file mode 100644 index 879b9e6188..0000000000 Binary files a/indra/newview/skins/blacklightblue/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/rounded_square.j2c b/indra/newview/skins/blacklightblue/textures/rounded_square.j2c deleted file mode 100644 index c3dfe8f10e..0000000000 Binary files a/indra/newview/skins/blacklightblue/textures/rounded_square.j2c and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/spacer24.tga b/indra/newview/skins/blacklightblue/textures/spacer24.tga deleted file mode 100644 index c7cab6b38c..0000000000 Binary files a/indra/newview/skins/blacklightblue/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/spacer35.tga b/indra/newview/skins/blacklightblue/textures/spacer35.tga deleted file mode 100644 index b88bc6680a..0000000000 Binary files a/indra/newview/skins/blacklightblue/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/tabarea.tga b/indra/newview/skins/blacklightblue/textures/tabarea.tga deleted file mode 100644 index 5517aebfc8..0000000000 Binary files a/indra/newview/skins/blacklightblue/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/textures.xml b/indra/newview/skins/blacklightblue/textures/textures.xml index 9f617f56b5..1d61522a18 100644 --- a/indra/newview/skins/blacklightblue/textures/textures.xml +++ b/indra/newview/skins/blacklightblue/textures/textures.xml @@ -1,385 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/indra/newview/skins/blackred/colors.xml b/indra/newview/skins/blackred/colors.xml index 640ef35d9d..fc87595ae0 100644 --- a/indra/newview/skins/blackred/colors.xml +++ b/indra/newview/skins/blackred/colors.xml @@ -168,7 +168,6 @@ - diff --git a/indra/newview/skins/blackred/textures/map_infohub.tga b/indra/newview/skins/blackred/textures/map_infohub.tga deleted file mode 100644 index 173b93e399..0000000000 Binary files a/indra/newview/skins/blackred/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/blackred/textures/rounded_square.j2c b/indra/newview/skins/blackred/textures/rounded_square.j2c deleted file mode 100644 index c3dfe8f10e..0000000000 Binary files a/indra/newview/skins/blackred/textures/rounded_square.j2c and /dev/null differ diff --git a/indra/newview/skins/blackred/textures/textures.xml b/indra/newview/skins/blackred/textures/textures.xml index 9f617f56b5..1d61522a18 100644 --- a/indra/newview/skins/blackred/textures/textures.xml +++ b/indra/newview/skins/blackred/textures/textures.xml @@ -1,385 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/indra/newview/skins/blackred/textures/textures_new.xml b/indra/newview/skins/blackred/textures/textures_new.xml new file mode 100644 index 0000000000..1d61522a18 --- /dev/null +++ b/indra/newview/skins/blackred/textures/textures_new.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/dark/colors.xml b/indra/newview/skins/dark/colors.xml index c36e5759a4..4d9ce08f23 100644 --- a/indra/newview/skins/dark/colors.xml +++ b/indra/newview/skins/dark/colors.xml @@ -99,6 +99,7 @@ + diff --git a/indra/newview/skins/dark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/dark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e3793097..0000000000 Binary files a/indra/newview/skins/dark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/circle.tga b/indra/newview/skins/dark/textures/circle.tga deleted file mode 100644 index d7097e3a35..0000000000 Binary files a/indra/newview/skins/dark/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/folder_arrow.tga b/indra/newview/skins/dark/textures/folder_arrow.tga deleted file mode 100644 index 77d470731b..0000000000 Binary files a/indra/newview/skins/dark/textures/folder_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef32..0000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa9..0000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1f..0000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/dark/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0f..0000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/dark/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f9461..0000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/dark/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad344..0000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_clear_lineeditor.tga b/indra/newview/skins/dark/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c66..0000000000 Binary files a/indra/newview/skins/dark/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_scrollbar.tga b/indra/newview/skins/dark/textures/icn_scrollbar.tga deleted file mode 100644 index a19a8a5d1a..0000000000 Binary files a/indra/newview/skins/dark/textures/icn_scrollbar.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/mute_icon.tga b/indra/newview/skins/dark/textures/mute_icon.tga deleted file mode 100644 index 879b9e6188..0000000000 Binary files a/indra/newview/skins/dark/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/spacer24.tga b/indra/newview/skins/dark/textures/spacer24.tga deleted file mode 100644 index c7cab6b38c..0000000000 Binary files a/indra/newview/skins/dark/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/spacer35.tga b/indra/newview/skins/dark/textures/spacer35.tga deleted file mode 100644 index b88bc6680a..0000000000 Binary files a/indra/newview/skins/dark/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/tabarea.tga b/indra/newview/skins/dark/textures/tabarea.tga deleted file mode 100644 index 5517aebfc8..0000000000 Binary files a/indra/newview/skins/dark/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/textures.xml b/indra/newview/skins/dark/textures/textures.xml deleted file mode 100644 index 451b700622..0000000000 --- a/indra/newview/skins/dark/textures/textures.xml +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/darkcatalan/colors.xml b/indra/newview/skins/darkcatalan/colors.xml index f8a009e0d7..5c8bb76be9 100644 --- a/indra/newview/skins/darkcatalan/colors.xml +++ b/indra/newview/skins/darkcatalan/colors.xml @@ -182,7 +182,6 @@ - diff --git a/indra/newview/skins/darkcatalan/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/darkcatalan/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e3793097..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/account_id_green.tga b/indra/newview/skins/darkcatalan/textures/account_id_green.tga deleted file mode 100644 index 9be215eed4..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/account_id_green.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/account_id_orange.tga b/indra/newview/skins/darkcatalan/textures/account_id_orange.tga deleted file mode 100644 index 6b41e86632..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/account_id_orange.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/active_speakers.tga b/indra/newview/skins/darkcatalan/textures/active_speakers.tga deleted file mode 100644 index 02d3643d7f..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/active_speakers.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/alpha_gradient.tga b/indra/newview/skins/darkcatalan/textures/alpha_gradient.tga deleted file mode 100644 index 6fdba25d4e..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/alpha_gradient.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/avatar_gone.tga b/indra/newview/skins/darkcatalan/textures/avatar_gone.tga deleted file mode 100644 index e5c2c070bc..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/avatar_gone.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/avatar_new.tga b/indra/newview/skins/darkcatalan/textures/avatar_new.tga deleted file mode 100644 index 854b70c326..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/avatar_new.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/checkerboard_transparency_bg.png b/indra/newview/skins/darkcatalan/textures/checkerboard_transparency_bg.png deleted file mode 100644 index fe06d38eff..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/checkerboard_transparency_bg.png and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/circle.tga b/indra/newview/skins/darkcatalan/textures/circle.tga deleted file mode 100644 index d7097e3a35..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/close_in_blue.tga b/indra/newview/skins/darkcatalan/textures/close_in_blue.tga deleted file mode 100644 index 8200eba327..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/close_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/close_inactive_blue.tga b/indra/newview/skins/darkcatalan/textures/close_inactive_blue.tga deleted file mode 100644 index 191c5d3e80..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/close_inactive_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/closebox.tga b/indra/newview/skins/darkcatalan/textures/closebox.tga deleted file mode 100644 index 294d4fb241..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/closebox.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/color_swatch_alpha.tga b/indra/newview/skins/darkcatalan/textures/color_swatch_alpha.tga deleted file mode 100644 index 814a004e62..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/color_swatch_alpha.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/combobox_arrow.tga b/indra/newview/skins/darkcatalan/textures/combobox_arrow.tga deleted file mode 100644 index ad08f32bb5..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/combobox_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/crosshairs.tga b/indra/newview/skins/darkcatalan/textures/crosshairs.tga deleted file mode 100644 index ac4d63dc59..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/crosshairs.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/darkgray.tga b/indra/newview/skins/darkcatalan/textures/darkgray.tga deleted file mode 100644 index 2063d685aa..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/darkgray.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/down_arrow.png b/indra/newview/skins/darkcatalan/textures/down_arrow.png deleted file mode 100644 index d376d980d2..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/down_arrow.png and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/folder_arrow.tga b/indra/newview/skins/darkcatalan/textures/folder_arrow.tga deleted file mode 100644 index 77d470731b..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/folder_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef32..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa9..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1f..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0f..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f9461..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad344..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_clear_lineeditor.tga b/indra/newview/skins/darkcatalan/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c66..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_rounded-text-field.tga b/indra/newview/skins/darkcatalan/textures/icn_rounded-text-field.tga deleted file mode 100644 index 7da504f93f..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_rounded-text-field.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_scrollbar.tga b/indra/newview/skins/darkcatalan/textures/icn_scrollbar.tga deleted file mode 100644 index a19a8a5d1a..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_scrollbar.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_scrollbar_bg.tga b/indra/newview/skins/darkcatalan/textures/icn_scrollbar_bg.tga deleted file mode 100644 index 1e4bc7a8a3..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_scrollbar_bg.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_scrollbar_thumb.tga b/indra/newview/skins/darkcatalan/textures/icn_scrollbar_thumb.tga deleted file mode 100644 index d63c314724..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_scrollbar_thumb.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_speaker-muted_dark.tga b/indra/newview/skins/darkcatalan/textures/icn_speaker-muted_dark.tga deleted file mode 100644 index a7d29a14b9..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_speaker-muted_dark.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_textfield_enabled.tga b/indra/newview/skins/darkcatalan/textures/icn_textfield_enabled.tga deleted file mode 100644 index fc681a1957..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_textfield_enabled.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice-call-end.tga b/indra/newview/skins/darkcatalan/textures/icn_voice-call-end.tga deleted file mode 100644 index 2da4e856b4..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice-call-end.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice-call-start.tga b/indra/newview/skins/darkcatalan/textures/icn_voice-call-start.tga deleted file mode 100644 index 07701cb5a2..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice-call-start.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice-groupfocus.tga b/indra/newview/skins/darkcatalan/textures/icn_voice-groupfocus.tga deleted file mode 100644 index 9f48d4609d..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice-groupfocus.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice-pvtfocus.tga b/indra/newview/skins/darkcatalan/textures/icn_voice-pvtfocus.tga deleted file mode 100644 index abadb09aaf..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice-pvtfocus.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl1.tga b/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl1.tga deleted file mode 100644 index ae72af131d..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl2.tga b/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl2.tga deleted file mode 100644 index 4dfc2dd292..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl3.tga b/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl3.tga deleted file mode 100644 index 018b0bef42..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl3.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on.tga b/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on.tga deleted file mode 100644 index 9eb6431106..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_auction.tga b/indra/newview/skins/darkcatalan/textures/icon_auction.tga deleted file mode 100644 index d121833b47..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_auction.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_day_cycle.tga b/indra/newview/skins/darkcatalan/textures/icon_day_cycle.tga deleted file mode 100644 index 2d5dee1e94..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_day_cycle.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_diurnal.tga b/indra/newview/skins/darkcatalan/textures/icon_diurnal.tga deleted file mode 100644 index fc720c8269..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_diurnal.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_event.tga b/indra/newview/skins/darkcatalan/textures/icon_event.tga deleted file mode 100644 index 7805dbce60..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_event.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_event_mature.tga b/indra/newview/skins/darkcatalan/textures/icon_event_mature.tga deleted file mode 100644 index 61c879bc92..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_event_mature.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_for_sale.tga b/indra/newview/skins/darkcatalan/textures/icon_for_sale.tga deleted file mode 100644 index 455b1aeb19..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_for_sale.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_group.tga b/indra/newview/skins/darkcatalan/textures/icon_group.tga deleted file mode 100644 index 22122d6cf1..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_group.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_groupnotice.tga b/indra/newview/skins/darkcatalan/textures/icon_groupnotice.tga deleted file mode 100644 index edf2c6180f..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_groupnotice.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_groupnoticeinventory.tga b/indra/newview/skins/darkcatalan/textures/icon_groupnoticeinventory.tga deleted file mode 100644 index f313906327..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_groupnoticeinventory.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_lock.tga b/indra/newview/skins/darkcatalan/textures/icon_lock.tga deleted file mode 100644 index 23521aa113..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_lock.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_place.tga b/indra/newview/skins/darkcatalan/textures/icon_place.tga deleted file mode 100644 index 2170c98499..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_place.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_popular.tga b/indra/newview/skins/darkcatalan/textures/icon_popular.tga deleted file mode 100644 index f1165b8aaa..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_popular.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_animation.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_animation.tga deleted file mode 100644 index 1b4df7a2d8..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_animation.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_bodypart.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_bodypart.tga deleted file mode 100644 index abcb1bda71..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_bodypart.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_callingcard.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_callingcard.tga deleted file mode 100644 index db7d8f7b0e..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_callingcard.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_clothing.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_clothing.tga deleted file mode 100644 index d214789cb7..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_clothing.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_gesture.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_gesture.tga deleted file mode 100644 index 83accbb1ea..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_gesture.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_landmark.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_landmark.tga deleted file mode 100644 index 6923dd2283..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_landmark.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_lostandfound.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_lostandfound.tga deleted file mode 100644 index 67f9a9a83c..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_lostandfound.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_notecard.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_notecard.tga deleted file mode 100644 index 400ef3cc4e..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_notecard.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_object.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_object.tga deleted file mode 100644 index c3d04bf27c..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_object.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_plain_closed.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_plain_closed.tga deleted file mode 100644 index e351836e2d..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_plain_closed.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_plain_open.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_plain_open.tga deleted file mode 100644 index 7bc80347b4..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_plain_open.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_script.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_script.tga deleted file mode 100644 index 3e1a164da7..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_script.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_snapshot.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_snapshot.tga deleted file mode 100644 index d32538d9ca..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_snapshot.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_sound.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_sound.tga deleted file mode 100644 index 5e54c47746..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_sound.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_texture.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_texture.tga deleted file mode 100644 index 4fe75d07df..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_texture.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_trash.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_trash.tga deleted file mode 100644 index 54043e9cf7..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_trash.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_animation.tga b/indra/newview/skins/darkcatalan/textures/inv_item_animation.tga deleted file mode 100644 index 2b12b28094..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_animation.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_attach.tga b/indra/newview/skins/darkcatalan/textures/inv_item_attach.tga deleted file mode 100644 index 0538993329..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_attach.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_offline.tga b/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_offline.tga deleted file mode 100644 index 44222d306c..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_offline.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_online.tga b/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_online.tga deleted file mode 100644 index 42be4d2e13..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_online.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_clothing.tga b/indra/newview/skins/darkcatalan/textures/inv_item_clothing.tga deleted file mode 100644 index 4c4c9391bd..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_clothing.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_eyes.tga b/indra/newview/skins/darkcatalan/textures/inv_item_eyes.tga deleted file mode 100644 index 053ffbe23d..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_eyes.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_gesture.tga b/indra/newview/skins/darkcatalan/textures/inv_item_gesture.tga deleted file mode 100644 index 52ac90c90d..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_gesture.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_gloves.tga b/indra/newview/skins/darkcatalan/textures/inv_item_gloves.tga deleted file mode 100644 index 26041711b4..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_gloves.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_hair.tga b/indra/newview/skins/darkcatalan/textures/inv_item_hair.tga deleted file mode 100644 index 03156a7b78..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_hair.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_jacket.tga b/indra/newview/skins/darkcatalan/textures/inv_item_jacket.tga deleted file mode 100644 index f37c593d85..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_jacket.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_landmark.tga b/indra/newview/skins/darkcatalan/textures/inv_item_landmark.tga deleted file mode 100644 index c161deb387..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_landmark.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_landmark_visited.tga b/indra/newview/skins/darkcatalan/textures/inv_item_landmark_visited.tga deleted file mode 100644 index 372a0f63ff..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_landmark_visited.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_notecard.tga b/indra/newview/skins/darkcatalan/textures/inv_item_notecard.tga deleted file mode 100644 index 2534d1b2a8..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_notecard.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_object.tga b/indra/newview/skins/darkcatalan/textures/inv_item_object.tga deleted file mode 100644 index edad15fdc7..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_object.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_object_multi.tga b/indra/newview/skins/darkcatalan/textures/inv_item_object_multi.tga deleted file mode 100644 index 7af666b61a..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_object_multi.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_pants.tga b/indra/newview/skins/darkcatalan/textures/inv_item_pants.tga deleted file mode 100644 index ec3246ea7a..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_pants.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_script.tga b/indra/newview/skins/darkcatalan/textures/inv_item_script.tga deleted file mode 100644 index e396d0986e..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_script.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_script_dangerous.tga b/indra/newview/skins/darkcatalan/textures/inv_item_script_dangerous.tga deleted file mode 100644 index 1ee742a8b6..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_script_dangerous.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_shape.tga b/indra/newview/skins/darkcatalan/textures/inv_item_shape.tga deleted file mode 100644 index 5d9db4e443..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_shape.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_shirt.tga b/indra/newview/skins/darkcatalan/textures/inv_item_shirt.tga deleted file mode 100644 index 2e1c627dad..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_shirt.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_shoes.tga b/indra/newview/skins/darkcatalan/textures/inv_item_shoes.tga deleted file mode 100644 index ae93bfe70b..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_shoes.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_skin.tga b/indra/newview/skins/darkcatalan/textures/inv_item_skin.tga deleted file mode 100644 index f0d7f2059d..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_skin.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_skirt.tga b/indra/newview/skins/darkcatalan/textures/inv_item_skirt.tga deleted file mode 100644 index d8f397285f..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_skirt.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_snapshot.tga b/indra/newview/skins/darkcatalan/textures/inv_item_snapshot.tga deleted file mode 100644 index c9d41a68db..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_snapshot.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_socks.tga b/indra/newview/skins/darkcatalan/textures/inv_item_socks.tga deleted file mode 100644 index dabcf6d821..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_socks.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_sound.tga b/indra/newview/skins/darkcatalan/textures/inv_item_sound.tga deleted file mode 100644 index efa113226b..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_sound.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_texture.tga b/indra/newview/skins/darkcatalan/textures/inv_item_texture.tga deleted file mode 100644 index fc5a42061e..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_texture.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_underpants.tga b/indra/newview/skins/darkcatalan/textures/inv_item_underpants.tga deleted file mode 100644 index e712f9c5d3..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_underpants.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_undershirt.tga b/indra/newview/skins/darkcatalan/textures/inv_item_undershirt.tga deleted file mode 100644 index c7b4aae786..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_undershirt.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/lag_status_critical.tga b/indra/newview/skins/darkcatalan/textures/lag_status_critical.tga deleted file mode 100644 index bbc71d9e77..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/lag_status_critical.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/lag_status_good.tga b/indra/newview/skins/darkcatalan/textures/lag_status_good.tga deleted file mode 100644 index 680ba90f17..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/lag_status_good.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/lag_status_warning.tga b/indra/newview/skins/darkcatalan/textures/lag_status_warning.tga deleted file mode 100644 index 13ce3cc396..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/lag_status_warning.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/legend.tga b/indra/newview/skins/darkcatalan/textures/legend.tga deleted file mode 100644 index 0dbb8fda4f..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/legend.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/lightgray.tga b/indra/newview/skins/darkcatalan/textures/lightgray.tga deleted file mode 100644 index 2063d685aa..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/lightgray.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_avatar_16.tga b/indra/newview/skins/darkcatalan/textures/map_avatar_16.tga deleted file mode 100644 index ce129e3590..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_avatar_16.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_avatar_32.tga b/indra/newview/skins/darkcatalan/textures/map_avatar_32.tga deleted file mode 100644 index aebeab4093..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_avatar_32.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_avatar_8.tga b/indra/newview/skins/darkcatalan/textures/map_avatar_8.tga deleted file mode 100644 index 28552f2237..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_avatar_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_avatar_you_32.tga b/indra/newview/skins/darkcatalan/textures/map_avatar_you_32.tga deleted file mode 100644 index 782207efd6..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_avatar_you_32.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_avatar_you_8.tga b/indra/newview/skins/darkcatalan/textures/map_avatar_you_8.tga deleted file mode 100644 index 61f319fd9d..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_avatar_you_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_event.tga b/indra/newview/skins/darkcatalan/textures/map_event.tga deleted file mode 100644 index c229b379a2..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_event.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_event_mature.tga b/indra/newview/skins/darkcatalan/textures/map_event_mature.tga deleted file mode 100644 index 61c879bc92..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_event_mature.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_home.tga b/indra/newview/skins/darkcatalan/textures/map_home.tga deleted file mode 100644 index 7478de371a..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_home.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_infohub.tga b/indra/newview/skins/darkcatalan/textures/map_infohub.tga deleted file mode 100644 index d0134fa5fe..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_telehub.tga b/indra/newview/skins/darkcatalan/textures/map_telehub.tga deleted file mode 100644 index ef63a3eb72..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_telehub.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_track_16.tga b/indra/newview/skins/darkcatalan/textures/map_track_16.tga deleted file mode 100644 index 451ce24cf0..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_track_16.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_track_8.tga b/indra/newview/skins/darkcatalan/textures/map_track_8.tga deleted file mode 100644 index 53425ff45b..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_track_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/media_icon.tga b/indra/newview/skins/darkcatalan/textures/media_icon.tga deleted file mode 100644 index 289520cde8..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/media_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/minimize.tga b/indra/newview/skins/darkcatalan/textures/minimize.tga deleted file mode 100644 index a21fd91481..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/minimize.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/minimize_inactive.tga b/indra/newview/skins/darkcatalan/textures/minimize_inactive.tga deleted file mode 100644 index fcd62aa35e..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/minimize_inactive.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/minimize_pressed.tga b/indra/newview/skins/darkcatalan/textures/minimize_pressed.tga deleted file mode 100644 index 0061dd5f5c..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/minimize_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/missing_asset.tga b/indra/newview/skins/darkcatalan/textures/missing_asset.tga deleted file mode 100644 index 9a43f4db5d..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/missing_asset.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/music_icon.tga b/indra/newview/skins/darkcatalan/textures/music_icon.tga deleted file mode 100644 index aeaff02e0a..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/music_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/mute_icon.tga b/indra/newview/skins/darkcatalan/textures/mute_icon.tga deleted file mode 100644 index 879b9e6188..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/notify_caution_icon.tga b/indra/newview/skins/darkcatalan/textures/notify_caution_icon.tga deleted file mode 100644 index 48c76ad912..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/notify_caution_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/propertyline.tga b/indra/newview/skins/darkcatalan/textures/propertyline.tga deleted file mode 100644 index 0c504eea71..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/propertyline.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/restore.tga b/indra/newview/skins/darkcatalan/textures/restore.tga deleted file mode 100644 index 87910e288e..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/restore.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/restore_inactive.tga b/indra/newview/skins/darkcatalan/textures/restore_inactive.tga deleted file mode 100644 index dbbec7ea1e..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/restore_inactive.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/restore_pressed.tga b/indra/newview/skins/darkcatalan/textures/restore_pressed.tga deleted file mode 100644 index 1922ca8815..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/restore_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/scrollbutton_down_in_blue.tga b/indra/newview/skins/darkcatalan/textures/scrollbutton_down_in_blue.tga deleted file mode 100644 index 5e73799505..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/scrollbutton_down_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/scrollbutton_left_in_blue.tga b/indra/newview/skins/darkcatalan/textures/scrollbutton_left_in_blue.tga deleted file mode 100644 index 480842a3b5..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/scrollbutton_left_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/scrollbutton_right_in_blue.tga b/indra/newview/skins/darkcatalan/textures/scrollbutton_right_in_blue.tga deleted file mode 100644 index 6d7f13bfcc..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/scrollbutton_right_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/scrollbutton_up_in_blue.tga b/indra/newview/skins/darkcatalan/textures/scrollbutton_up_in_blue.tga deleted file mode 100644 index 4c6a8fe414..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/scrollbutton_up_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/slim_icon_16_viewer.tga b/indra/newview/skins/darkcatalan/textures/slim_icon_16_viewer.tga deleted file mode 100644 index 552181d36a..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/slim_icon_16_viewer.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/sm_rounded_corners_simple.tga b/indra/newview/skins/darkcatalan/textures/sm_rounded_corners_simple.tga deleted file mode 100644 index 85157e4612..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/sm_rounded_corners_simple.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/smicon_warn.tga b/indra/newview/skins/darkcatalan/textures/smicon_warn.tga deleted file mode 100644 index 90ccaa07e5..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/smicon_warn.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/spacer24.tga b/indra/newview/skins/darkcatalan/textures/spacer24.tga deleted file mode 100644 index c7cab6b38c..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/spacer35.tga b/indra/newview/skins/darkcatalan/textures/spacer35.tga deleted file mode 100644 index b88bc6680a..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/startup_logo.jpg b/indra/newview/skins/darkcatalan/textures/startup_logo.jpg index 333df5779e..a2b127bc93 100644 Binary files a/indra/newview/skins/darkcatalan/textures/startup_logo.jpg and b/indra/newview/skins/darkcatalan/textures/startup_logo.jpg differ diff --git a/indra/newview/skins/darkcatalan/textures/status_busy.tga b/indra/newview/skins/darkcatalan/textures/status_busy.tga deleted file mode 100644 index 7743d9c7bb..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_busy.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_health.tga b/indra/newview/skins/darkcatalan/textures/status_health.tga deleted file mode 100644 index 3d5f455fcd..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_health.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_money.tga b/indra/newview/skins/darkcatalan/textures/status_money.tga deleted file mode 100644 index d5be31fc60..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_money.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_no_build.tga b/indra/newview/skins/darkcatalan/textures/status_no_build.tga deleted file mode 100644 index 8e471e1851..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_no_build.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_no_fly.tga b/indra/newview/skins/darkcatalan/textures/status_no_fly.tga deleted file mode 100644 index cde2700ab2..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_no_fly.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_no_push.tga b/indra/newview/skins/darkcatalan/textures/status_no_push.tga deleted file mode 100644 index 5ccbfa50f1..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_no_push.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_no_scripts.tga b/indra/newview/skins/darkcatalan/textures/status_no_scripts.tga deleted file mode 100644 index 52ecdb1b84..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_no_scripts.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_no_voice.tga b/indra/newview/skins/darkcatalan/textures/status_no_voice.tga deleted file mode 100644 index 4ab4498cbc..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_no_voice.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_script_debug.tga b/indra/newview/skins/darkcatalan/textures/status_script_debug.tga deleted file mode 100644 index 6fca614835..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_script_debug.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_search.tga b/indra/newview/skins/darkcatalan/textures/status_search.tga deleted file mode 100644 index 3ac10c4769..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_search.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_search_btn.png b/indra/newview/skins/darkcatalan/textures/status_search_btn.png deleted file mode 100644 index e648ba8490..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_search_btn.png and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_search_btn_pressed.png b/indra/newview/skins/darkcatalan/textures/status_search_btn_pressed.png deleted file mode 100644 index ec4254f4d9..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_search_btn_pressed.png and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_voice.tga b/indra/newview/skins/darkcatalan/textures/status_voice.tga deleted file mode 100644 index 4ab4498cbc..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_voice.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tab_background_darkpurple.tga b/indra/newview/skins/darkcatalan/textures/tab_background_darkpurple.tga deleted file mode 100644 index 8169f98694..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tab_background_darkpurple.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tab_background_lightgrey.tga b/indra/newview/skins/darkcatalan/textures/tab_background_lightgrey.tga deleted file mode 100644 index c2f8818f73..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tab_background_lightgrey.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tab_background_purple.tga b/indra/newview/skins/darkcatalan/textures/tab_background_purple.tga deleted file mode 100644 index aa01b3cb68..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tab_background_purple.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tabarea.tga b/indra/newview/skins/darkcatalan/textures/tabarea.tga deleted file mode 100644 index 5517aebfc8..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tearoff_pressed.tga b/indra/newview/skins/darkcatalan/textures/tearoff_pressed.tga deleted file mode 100644 index 620d109de0..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tearoff_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tearoffbox.tga b/indra/newview/skins/darkcatalan/textures/tearoffbox.tga deleted file mode 100644 index 0670d2e91b..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tearoffbox.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/textures.xml b/indra/newview/skins/darkcatalan/textures/textures.xml index 2c4b0cbea6..48fcecbfeb 100644 --- a/indra/newview/skins/darkcatalan/textures/textures.xml +++ b/indra/newview/skins/darkcatalan/textures/textures.xml @@ -1,382 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/indra/newview/skins/darkcatalan/textures/uv_test2.tga b/indra/newview/skins/darkcatalan/textures/uv_test2.tga deleted file mode 100644 index a16000d1e4..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/uv_test2.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/white.tga b/indra/newview/skins/darkcatalan/textures/white.tga deleted file mode 100644 index 9fe68631cf..0000000000 Binary files a/indra/newview/skins/darkcatalan/textures/white.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/colors.xml b/indra/newview/skins/darkgred/colors.xml index c005b75fc5..f79be836ea 100644 --- a/indra/newview/skins/darkgred/colors.xml +++ b/indra/newview/skins/darkgred/colors.xml @@ -100,6 +100,7 @@ + diff --git a/indra/newview/skins/darkgred/textures/alpha_gradient.tga b/indra/newview/skins/darkgred/textures/alpha_gradient.tga deleted file mode 100644 index 6fdba25d4e..0000000000 Binary files a/indra/newview/skins/darkgred/textures/alpha_gradient.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/circle.tga b/indra/newview/skins/darkgred/textures/circle.tga deleted file mode 100644 index d7097e3a35..0000000000 Binary files a/indra/newview/skins/darkgred/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/color_swatch_alpha.tga b/indra/newview/skins/darkgred/textures/color_swatch_alpha.tga deleted file mode 100644 index 814a004e62..0000000000 Binary files a/indra/newview/skins/darkgred/textures/color_swatch_alpha.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/crosshairs.tga b/indra/newview/skins/darkgred/textures/crosshairs.tga deleted file mode 100644 index ac4d63dc59..0000000000 Binary files a/indra/newview/skins/darkgred/textures/crosshairs.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/direction_arrow.tga b/indra/newview/skins/darkgred/textures/direction_arrow.tga deleted file mode 100644 index f3ef1068c4..0000000000 Binary files a/indra/newview/skins/darkgred/textures/direction_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/ff_edit_mine.tga b/indra/newview/skins/darkgred/textures/ff_edit_mine.tga deleted file mode 100644 index 8f0c35b98f..0000000000 Binary files a/indra/newview/skins/darkgred/textures/ff_edit_mine.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/ff_edit_theirs.tga b/indra/newview/skins/darkgred/textures/ff_edit_theirs.tga deleted file mode 100644 index 005ada2dea..0000000000 Binary files a/indra/newview/skins/darkgred/textures/ff_edit_theirs.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/icn_clear_lineeditor.tga b/indra/newview/skins/darkgred/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c66..0000000000 Binary files a/indra/newview/skins/darkgred/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/icn_scrollbar.tga b/indra/newview/skins/darkgred/textures/icn_scrollbar.tga deleted file mode 100644 index a19a8a5d1a..0000000000 Binary files a/indra/newview/skins/darkgred/textures/icn_scrollbar.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/map_avatar_above_8.tga b/indra/newview/skins/darkgred/textures/map_avatar_above_8.tga deleted file mode 100644 index 193428e530..0000000000 Binary files a/indra/newview/skins/darkgred/textures/map_avatar_above_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/map_avatar_below_8.tga b/indra/newview/skins/darkgred/textures/map_avatar_below_8.tga deleted file mode 100644 index 9e14bfab90..0000000000 Binary files a/indra/newview/skins/darkgred/textures/map_avatar_below_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/propertyline.tga b/indra/newview/skins/darkgred/textures/propertyline.tga deleted file mode 100644 index 0c504eea71..0000000000 Binary files a/indra/newview/skins/darkgred/textures/propertyline.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/tabarea.tga b/indra/newview/skins/darkgred/textures/tabarea.tga deleted file mode 100644 index 5517aebfc8..0000000000 Binary files a/indra/newview/skins/darkgred/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/textures.xml b/indra/newview/skins/darkgred/textures/textures.xml deleted file mode 100644 index 451b700622..0000000000 --- a/indra/newview/skins/darkgred/textures/textures.xml +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/darkgreen/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/darkgreen/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e3793097..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/circle.tga b/indra/newview/skins/darkgreen/textures/circle.tga deleted file mode 100644 index d7097e3a35..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/folder_arrow.tga b/indra/newview/skins/darkgreen/textures/folder_arrow.tga deleted file mode 100644 index 77d470731b..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/folder_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef32..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa9..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1f..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0f..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f9461..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad344..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_clear_lineeditor.tga b/indra/newview/skins/darkgreen/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c66..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_scrollbar.tga b/indra/newview/skins/darkgreen/textures/icn_scrollbar.tga deleted file mode 100644 index a19a8a5d1a..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_scrollbar.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/mute_icon.tga b/indra/newview/skins/darkgreen/textures/mute_icon.tga deleted file mode 100644 index 879b9e6188..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/spacer24.tga b/indra/newview/skins/darkgreen/textures/spacer24.tga deleted file mode 100644 index c7cab6b38c..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/spacer35.tga b/indra/newview/skins/darkgreen/textures/spacer35.tga deleted file mode 100644 index b88bc6680a..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/tabarea.tga b/indra/newview/skins/darkgreen/textures/tabarea.tga deleted file mode 100644 index 5517aebfc8..0000000000 Binary files a/indra/newview/skins/darkgreen/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/textures.xml b/indra/newview/skins/darkgreen/textures/textures.xml deleted file mode 100644 index 451b700622..0000000000 --- a/indra/newview/skins/darkgreen/textures/textures.xml +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/darkorange/colors.xml b/indra/newview/skins/darkorange/colors.xml index 07c97ce6e4..cb3021e93e 100644 --- a/indra/newview/skins/darkorange/colors.xml +++ b/indra/newview/skins/darkorange/colors.xml @@ -167,7 +167,6 @@ - diff --git a/indra/newview/skins/darkorange/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga b/indra/newview/skins/darkorange/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga deleted file mode 100644 index fb6dac0c3d..0000000000 Binary files a/indra/newview/skins/darkorange/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/darkorange/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e3793097..0000000000 Binary files a/indra/newview/skins/darkorange/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga b/indra/newview/skins/darkorange/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga deleted file mode 100644 index 010c748c2a..0000000000 Binary files a/indra/newview/skins/darkorange/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga b/indra/newview/skins/darkorange/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga deleted file mode 100644 index e0656c901d..0000000000 Binary files a/indra/newview/skins/darkorange/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/account_id_green.tga b/indra/newview/skins/darkorange/textures/account_id_green.tga deleted file mode 100644 index 9be215eed4..0000000000 Binary files a/indra/newview/skins/darkorange/textures/account_id_green.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/account_id_orange.tga b/indra/newview/skins/darkorange/textures/account_id_orange.tga deleted file mode 100644 index 6b41e86632..0000000000 Binary files a/indra/newview/skins/darkorange/textures/account_id_orange.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/active_speakers.tga b/indra/newview/skins/darkorange/textures/active_speakers.tga deleted file mode 100644 index 02d3643d7f..0000000000 Binary files a/indra/newview/skins/darkorange/textures/active_speakers.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/active_voice_tab.tga b/indra/newview/skins/darkorange/textures/active_voice_tab.tga deleted file mode 100644 index 2d0dfaabc5..0000000000 Binary files a/indra/newview/skins/darkorange/textures/active_voice_tab.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/alpha_gradient.tga b/indra/newview/skins/darkorange/textures/alpha_gradient.tga deleted file mode 100644 index 6fdba25d4e..0000000000 Binary files a/indra/newview/skins/darkorange/textures/alpha_gradient.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/alpha_gradient_2d.j2c b/indra/newview/skins/darkorange/textures/alpha_gradient_2d.j2c deleted file mode 100644 index 5de5a80a65..0000000000 Binary files a/indra/newview/skins/darkorange/textures/alpha_gradient_2d.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/arrow_down.tga b/indra/newview/skins/darkorange/textures/arrow_down.tga deleted file mode 100644 index 81dc9d3b6c..0000000000 Binary files a/indra/newview/skins/darkorange/textures/arrow_down.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/arrow_up.tga b/indra/newview/skins/darkorange/textures/arrow_up.tga deleted file mode 100644 index 22195cf7fb..0000000000 Binary files a/indra/newview/skins/darkorange/textures/arrow_up.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/avatar_gone.tga b/indra/newview/skins/darkorange/textures/avatar_gone.tga deleted file mode 100644 index e5c2c070bc..0000000000 Binary files a/indra/newview/skins/darkorange/textures/avatar_gone.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/avatar_new.tga b/indra/newview/skins/darkorange/textures/avatar_new.tga deleted file mode 100644 index 854b70c326..0000000000 Binary files a/indra/newview/skins/darkorange/textures/avatar_new.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/avatar_thumb_bkgrnd.j2c b/indra/newview/skins/darkorange/textures/avatar_thumb_bkgrnd.j2c deleted file mode 100644 index 555551ba11..0000000000 Binary files a/indra/newview/skins/darkorange/textures/avatar_thumb_bkgrnd.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/avatar_typing.tga b/indra/newview/skins/darkorange/textures/avatar_typing.tga deleted file mode 100644 index 2c549025dd..0000000000 Binary files a/indra/newview/skins/darkorange/textures/avatar_typing.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/badge_error.j2c b/indra/newview/skins/darkorange/textures/badge_error.j2c deleted file mode 100644 index e8f3da507a..0000000000 Binary files a/indra/newview/skins/darkorange/textures/badge_error.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/badge_note.j2c b/indra/newview/skins/darkorange/textures/badge_note.j2c deleted file mode 100644 index 1ab5233faf..0000000000 Binary files a/indra/newview/skins/darkorange/textures/badge_note.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/badge_ok.j2c b/indra/newview/skins/darkorange/textures/badge_ok.j2c deleted file mode 100644 index f85b880f1d..0000000000 Binary files a/indra/newview/skins/darkorange/textures/badge_ok.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/badge_warn.j2c b/indra/newview/skins/darkorange/textures/badge_warn.j2c deleted file mode 100644 index 26437ca426..0000000000 Binary files a/indra/newview/skins/darkorange/textures/badge_warn.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/black.tga b/indra/newview/skins/darkorange/textures/black.tga deleted file mode 100644 index e69be08937..0000000000 Binary files a/indra/newview/skins/darkorange/textures/black.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/checkbox_disabled_false.tga b/indra/newview/skins/darkorange/textures/checkbox_disabled_false.tga deleted file mode 100644 index 16c239227f..0000000000 Binary files a/indra/newview/skins/darkorange/textures/checkbox_disabled_false.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/checkbox_disabled_true.tga b/indra/newview/skins/darkorange/textures/checkbox_disabled_true.tga deleted file mode 100644 index 04a8d516f6..0000000000 Binary files a/indra/newview/skins/darkorange/textures/checkbox_disabled_true.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/checkbox_enabled_false.tga b/indra/newview/skins/darkorange/textures/checkbox_enabled_false.tga deleted file mode 100644 index a604a44092..0000000000 Binary files a/indra/newview/skins/darkorange/textures/checkbox_enabled_false.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/checkbox_enabled_true.tga b/indra/newview/skins/darkorange/textures/checkbox_enabled_true.tga deleted file mode 100644 index 4a1b504eaf..0000000000 Binary files a/indra/newview/skins/darkorange/textures/checkbox_enabled_true.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/checkerboard_transparency_bg.png b/indra/newview/skins/darkorange/textures/checkerboard_transparency_bg.png deleted file mode 100644 index fe06d38eff..0000000000 Binary files a/indra/newview/skins/darkorange/textures/checkerboard_transparency_bg.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/circle.tga b/indra/newview/skins/darkorange/textures/circle.tga deleted file mode 100644 index d7097e3a35..0000000000 Binary files a/indra/newview/skins/darkorange/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/close_in_blue.tga b/indra/newview/skins/darkorange/textures/close_in_blue.tga deleted file mode 100644 index 8200eba327..0000000000 Binary files a/indra/newview/skins/darkorange/textures/close_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/close_inactive_blue.tga b/indra/newview/skins/darkorange/textures/close_inactive_blue.tga deleted file mode 100644 index 191c5d3e80..0000000000 Binary files a/indra/newview/skins/darkorange/textures/close_inactive_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/closebox.tga b/indra/newview/skins/darkorange/textures/closebox.tga deleted file mode 100644 index 294d4fb241..0000000000 Binary files a/indra/newview/skins/darkorange/textures/closebox.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/cloud-particle.j2c b/indra/newview/skins/darkorange/textures/cloud-particle.j2c deleted file mode 100644 index 6c03bf6d05..0000000000 Binary files a/indra/newview/skins/darkorange/textures/cloud-particle.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/color_swatch_alpha.tga b/indra/newview/skins/darkorange/textures/color_swatch_alpha.tga deleted file mode 100644 index 814a004e62..0000000000 Binary files a/indra/newview/skins/darkorange/textures/color_swatch_alpha.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/combobox_arrow.tga b/indra/newview/skins/darkorange/textures/combobox_arrow.tga deleted file mode 100644 index ad08f32bb5..0000000000 Binary files a/indra/newview/skins/darkorange/textures/combobox_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/crosshairs.tga b/indra/newview/skins/darkorange/textures/crosshairs.tga deleted file mode 100644 index ac4d63dc59..0000000000 Binary files a/indra/newview/skins/darkorange/textures/crosshairs.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/darkgray.tga b/indra/newview/skins/darkorange/textures/darkgray.tga deleted file mode 100644 index 2063d685aa..0000000000 Binary files a/indra/newview/skins/darkorange/textures/darkgray.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/direction_arrow.tga b/indra/newview/skins/darkorange/textures/direction_arrow.tga deleted file mode 100644 index f3ef1068c4..0000000000 Binary files a/indra/newview/skins/darkorange/textures/direction_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/down_arrow.png b/indra/newview/skins/darkorange/textures/down_arrow.png deleted file mode 100644 index d376d980d2..0000000000 Binary files a/indra/newview/skins/darkorange/textures/down_arrow.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/eye_button_active.tga b/indra/newview/skins/darkorange/textures/eye_button_active.tga deleted file mode 100644 index 014f785a7b..0000000000 Binary files a/indra/newview/skins/darkorange/textures/eye_button_active.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/eye_button_inactive.tga b/indra/newview/skins/darkorange/textures/eye_button_inactive.tga deleted file mode 100644 index 8666f0bbe6..0000000000 Binary files a/indra/newview/skins/darkorange/textures/eye_button_inactive.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/folder_arrow.tga b/indra/newview/skins/darkorange/textures/folder_arrow.tga deleted file mode 100644 index 77d470731b..0000000000 Binary files a/indra/newview/skins/darkorange/textures/folder_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/foot_shadow.j2c b/indra/newview/skins/darkorange/textures/foot_shadow.j2c deleted file mode 100644 index f9ce9da7d1..0000000000 Binary files a/indra/newview/skins/darkorange/textures/foot_shadow.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef32..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa9..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1f..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0f..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f9461..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad344..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_clear_lineeditor.tga b/indra/newview/skins/darkorange/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c66..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_rounded-text-field.tga b/indra/newview/skins/darkorange/textures/icn_rounded-text-field.tga deleted file mode 100644 index 7da504f93f..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_rounded-text-field.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice-call-end.tga b/indra/newview/skins/darkorange/textures/icn_voice-call-end.tga deleted file mode 100644 index 2da4e856b4..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice-call-end.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice-call-start.tga b/indra/newview/skins/darkorange/textures/icn_voice-call-start.tga deleted file mode 100644 index 07701cb5a2..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice-call-start.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice-groupfocus.tga b/indra/newview/skins/darkorange/textures/icn_voice-groupfocus.tga deleted file mode 100644 index 9f48d4609d..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice-groupfocus.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice-localchat.tga b/indra/newview/skins/darkorange/textures/icn_voice-localchat.tga deleted file mode 100644 index 7cf267eaf5..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice-localchat.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice-pvtfocus.tga b/indra/newview/skins/darkorange/textures/icn_voice-pvtfocus.tga deleted file mode 100644 index abadb09aaf..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice-pvtfocus.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice_ptt-off.tga b/indra/newview/skins/darkorange/textures/icn_voice_ptt-off.tga deleted file mode 100644 index 15ecbdff95..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice_ptt-off.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl1.tga b/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl1.tga deleted file mode 100644 index ae72af131d..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl2.tga b/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl2.tga deleted file mode 100644 index 4dfc2dd292..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl3.tga b/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl3.tga deleted file mode 100644 index 018b0bef42..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl3.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on.tga b/indra/newview/skins/darkorange/textures/icn_voice_ptt-on.tga deleted file mode 100644 index 9eb6431106..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_auction.tga b/indra/newview/skins/darkorange/textures/icon_auction.tga deleted file mode 100644 index d121833b47..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_auction.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_day_cycle.tga b/indra/newview/skins/darkorange/textures/icon_day_cycle.tga deleted file mode 100644 index 2d5dee1e94..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_day_cycle.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_diurnal.tga b/indra/newview/skins/darkorange/textures/icon_diurnal.tga deleted file mode 100644 index fc720c8269..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_diurnal.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_event.tga b/indra/newview/skins/darkorange/textures/icon_event.tga deleted file mode 100644 index 7805dbce60..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_event.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_event_mature.tga b/indra/newview/skins/darkorange/textures/icon_event_mature.tga deleted file mode 100644 index 61c879bc92..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_event_mature.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_for_sale.tga b/indra/newview/skins/darkorange/textures/icon_for_sale.tga deleted file mode 100644 index 455b1aeb19..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_for_sale.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_group.tga b/indra/newview/skins/darkorange/textures/icon_group.tga deleted file mode 100644 index 22122d6cf1..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_group.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_groupnotice.tga b/indra/newview/skins/darkorange/textures/icon_groupnotice.tga deleted file mode 100644 index edf2c6180f..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_groupnotice.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_groupnoticeinventory.tga b/indra/newview/skins/darkorange/textures/icon_groupnoticeinventory.tga deleted file mode 100644 index f313906327..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_groupnoticeinventory.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_lock.tga b/indra/newview/skins/darkorange/textures/icon_lock.tga deleted file mode 100644 index 23521aa113..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_lock.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_place.tga b/indra/newview/skins/darkorange/textures/icon_place.tga deleted file mode 100644 index 2170c98499..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_place.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_popular.tga b/indra/newview/skins/darkorange/textures/icon_popular.tga deleted file mode 100644 index f1165b8aaa..0000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_popular.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_folder_trash.tga b/indra/newview/skins/darkorange/textures/inv_folder_trash.tga deleted file mode 100644 index 54043e9cf7..0000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_folder_trash.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_animation.tga b/indra/newview/skins/darkorange/textures/inv_item_animation.tga deleted file mode 100644 index 2b12b28094..0000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_animation.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_attach.tga b/indra/newview/skins/darkorange/textures/inv_item_attach.tga deleted file mode 100644 index 0538993329..0000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_attach.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_callingcard_offline.tga b/indra/newview/skins/darkorange/textures/inv_item_callingcard_offline.tga deleted file mode 100644 index 44222d306c..0000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_callingcard_offline.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_callingcard_online.tga b/indra/newview/skins/darkorange/textures/inv_item_callingcard_online.tga deleted file mode 100644 index 42be4d2e13..0000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_callingcard_online.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_gesture.tga b/indra/newview/skins/darkorange/textures/inv_item_gesture.tga deleted file mode 100644 index 52ac90c90d..0000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_gesture.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_notecard.tga b/indra/newview/skins/darkorange/textures/inv_item_notecard.tga deleted file mode 100644 index 2534d1b2a8..0000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_notecard.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/lag_status_critical.tga b/indra/newview/skins/darkorange/textures/lag_status_critical.tga deleted file mode 100644 index bbc71d9e77..0000000000 Binary files a/indra/newview/skins/darkorange/textures/lag_status_critical.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/lag_status_good.tga b/indra/newview/skins/darkorange/textures/lag_status_good.tga deleted file mode 100644 index 680ba90f17..0000000000 Binary files a/indra/newview/skins/darkorange/textures/lag_status_good.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/lag_status_warning.tga b/indra/newview/skins/darkorange/textures/lag_status_warning.tga deleted file mode 100644 index 13ce3cc396..0000000000 Binary files a/indra/newview/skins/darkorange/textures/lag_status_warning.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/legend.tga b/indra/newview/skins/darkorange/textures/legend.tga deleted file mode 100644 index 0dbb8fda4f..0000000000 Binary files a/indra/newview/skins/darkorange/textures/legend.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/lightgray.tga b/indra/newview/skins/darkorange/textures/lightgray.tga deleted file mode 100644 index 2063d685aa..0000000000 Binary files a/indra/newview/skins/darkorange/textures/lightgray.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_avatar_16.tga b/indra/newview/skins/darkorange/textures/map_avatar_16.tga deleted file mode 100644 index ce129e3590..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_avatar_16.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_avatar_8.tga b/indra/newview/skins/darkorange/textures/map_avatar_8.tga deleted file mode 100644 index 28552f2237..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_avatar_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_avatar_above_8.tga b/indra/newview/skins/darkorange/textures/map_avatar_above_8.tga deleted file mode 100644 index 193428e530..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_avatar_above_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_avatar_below_8.tga b/indra/newview/skins/darkorange/textures/map_avatar_below_8.tga deleted file mode 100644 index 9e14bfab90..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_avatar_below_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_avatar_you_8.tga b/indra/newview/skins/darkorange/textures/map_avatar_you_8.tga deleted file mode 100644 index 61f319fd9d..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_avatar_you_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_event.tga b/indra/newview/skins/darkorange/textures/map_event.tga deleted file mode 100644 index c229b379a2..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_event.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_event_mature.tga b/indra/newview/skins/darkorange/textures/map_event_mature.tga deleted file mode 100644 index 61c879bc92..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_event_mature.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_home.tga b/indra/newview/skins/darkorange/textures/map_home.tga deleted file mode 100644 index 7478de371a..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_home.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_infohub.tga b/indra/newview/skins/darkorange/textures/map_infohub.tga deleted file mode 100644 index d0134fa5fe..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_telehub.tga b/indra/newview/skins/darkorange/textures/map_telehub.tga deleted file mode 100644 index ef63a3eb72..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_telehub.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_track_16.tga b/indra/newview/skins/darkorange/textures/map_track_16.tga deleted file mode 100644 index 451ce24cf0..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_track_16.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_track_8.tga b/indra/newview/skins/darkorange/textures/map_track_8.tga deleted file mode 100644 index 53425ff45b..0000000000 Binary files a/indra/newview/skins/darkorange/textures/map_track_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/minimize.tga b/indra/newview/skins/darkorange/textures/minimize.tga deleted file mode 100644 index a21fd91481..0000000000 Binary files a/indra/newview/skins/darkorange/textures/minimize.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/minimize_inactive.tga b/indra/newview/skins/darkorange/textures/minimize_inactive.tga deleted file mode 100644 index fcd62aa35e..0000000000 Binary files a/indra/newview/skins/darkorange/textures/minimize_inactive.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/minimize_pressed.tga b/indra/newview/skins/darkorange/textures/minimize_pressed.tga deleted file mode 100644 index 0061dd5f5c..0000000000 Binary files a/indra/newview/skins/darkorange/textures/minimize_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/missing_asset.tga b/indra/newview/skins/darkorange/textures/missing_asset.tga deleted file mode 100644 index 9a43f4db5d..0000000000 Binary files a/indra/newview/skins/darkorange/textures/missing_asset.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/mute_icon.tga b/indra/newview/skins/darkorange/textures/mute_icon.tga deleted file mode 100644 index 879b9e6188..0000000000 Binary files a/indra/newview/skins/darkorange/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/noentrylines.j2c b/indra/newview/skins/darkorange/textures/noentrylines.j2c deleted file mode 100644 index 93ec17659d..0000000000 Binary files a/indra/newview/skins/darkorange/textures/noentrylines.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/noentrypasslines.j2c b/indra/newview/skins/darkorange/textures/noentrypasslines.j2c deleted file mode 100644 index 800c466964..0000000000 Binary files a/indra/newview/skins/darkorange/textures/noentrypasslines.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/notify_caution_icon.tga b/indra/newview/skins/darkorange/textures/notify_caution_icon.tga deleted file mode 100644 index abc23d1d7a..0000000000 Binary files a/indra/newview/skins/darkorange/textures/notify_caution_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/notify_next.png b/indra/newview/skins/darkorange/textures/notify_next.png deleted file mode 100644 index 7b4aba9d35..0000000000 Binary files a/indra/newview/skins/darkorange/textures/notify_next.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/pixiesmall.j2c b/indra/newview/skins/darkorange/textures/pixiesmall.j2c deleted file mode 100644 index a1ff64014b..0000000000 Binary files a/indra/newview/skins/darkorange/textures/pixiesmall.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/propertyline.tga b/indra/newview/skins/darkorange/textures/propertyline.tga deleted file mode 100644 index 0c504eea71..0000000000 Binary files a/indra/newview/skins/darkorange/textures/propertyline.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/ptt_lock_off.tga b/indra/newview/skins/darkorange/textures/ptt_lock_off.tga deleted file mode 100644 index 09c4798070..0000000000 Binary files a/indra/newview/skins/darkorange/textures/ptt_lock_off.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/ptt_lock_on.tga b/indra/newview/skins/darkorange/textures/ptt_lock_on.tga deleted file mode 100644 index dfb8ce2841..0000000000 Binary files a/indra/newview/skins/darkorange/textures/ptt_lock_on.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/radio_active_false.tga b/indra/newview/skins/darkorange/textures/radio_active_false.tga deleted file mode 100644 index 963037392c..0000000000 Binary files a/indra/newview/skins/darkorange/textures/radio_active_false.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/radio_active_true.tga b/indra/newview/skins/darkorange/textures/radio_active_true.tga deleted file mode 100644 index f49297fd2c..0000000000 Binary files a/indra/newview/skins/darkorange/textures/radio_active_true.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/radio_inactive_false.tga b/indra/newview/skins/darkorange/textures/radio_inactive_false.tga deleted file mode 100644 index 9f9589e645..0000000000 Binary files a/indra/newview/skins/darkorange/textures/radio_inactive_false.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/radio_inactive_true.tga b/indra/newview/skins/darkorange/textures/radio_inactive_true.tga deleted file mode 100644 index ca69cc6b5d..0000000000 Binary files a/indra/newview/skins/darkorange/textures/radio_inactive_true.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/resize_handle_bottom_right_blue.tga b/indra/newview/skins/darkorange/textures/resize_handle_bottom_right_blue.tga deleted file mode 100644 index f47aacfa42..0000000000 Binary files a/indra/newview/skins/darkorange/textures/resize_handle_bottom_right_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/restore.tga b/indra/newview/skins/darkorange/textures/restore.tga deleted file mode 100644 index 87910e288e..0000000000 Binary files a/indra/newview/skins/darkorange/textures/restore.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/restore_inactive.tga b/indra/newview/skins/darkorange/textures/restore_inactive.tga deleted file mode 100644 index dbbec7ea1e..0000000000 Binary files a/indra/newview/skins/darkorange/textures/restore_inactive.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/restore_pressed.tga b/indra/newview/skins/darkorange/textures/restore_pressed.tga deleted file mode 100644 index 1922ca8815..0000000000 Binary files a/indra/newview/skins/darkorange/textures/restore_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/rounded_square.j2c b/indra/newview/skins/darkorange/textures/rounded_square.j2c deleted file mode 100644 index c8bb572fa9..0000000000 Binary files a/indra/newview/skins/darkorange/textures/rounded_square.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/rounded_square_soft.j2c b/indra/newview/skins/darkorange/textures/rounded_square_soft.j2c deleted file mode 100644 index 56e56c1ec9..0000000000 Binary files a/indra/newview/skins/darkorange/textures/rounded_square_soft.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/script_error.j2c b/indra/newview/skins/darkorange/textures/script_error.j2c deleted file mode 100644 index 893cb642e7..0000000000 Binary files a/indra/newview/skins/darkorange/textures/script_error.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_down_in_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_down_in_blue.tga deleted file mode 100644 index 5e73799505..0000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_down_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_down_out_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_down_out_blue.tga deleted file mode 100644 index c5cf9bf9f9..0000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_down_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_left_in_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_left_in_blue.tga deleted file mode 100644 index 480842a3b5..0000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_left_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_left_out_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_left_out_blue.tga deleted file mode 100644 index 71aad797b0..0000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_left_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_right_in_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_right_in_blue.tga deleted file mode 100644 index 6d7f13bfcc..0000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_right_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_right_out_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_right_out_blue.tga deleted file mode 100644 index 0edc59af3e..0000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_right_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_up_in_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_up_in_blue.tga deleted file mode 100644 index 4c6a8fe414..0000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_up_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_up_out_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_up_out_blue.tga deleted file mode 100644 index 5cd5dff467..0000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_up_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/silhouette.j2c b/indra/newview/skins/darkorange/textures/silhouette.j2c deleted file mode 100644 index 3859d4cb34..0000000000 Binary files a/indra/newview/skins/darkorange/textures/silhouette.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_dark.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_dark.png deleted file mode 100644 index fc102a0147..0000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_dark.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_default.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_default.png deleted file mode 100644 index e22b1c1644..0000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_default.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_emerald.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_emerald.png deleted file mode 100644 index f2ab49e6db..0000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_emerald.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_gred.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_gred.png deleted file mode 100644 index d605847434..0000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_gred.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_pslgreen.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_pslgreen.png deleted file mode 100644 index 3eb7263d6a..0000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_pslgreen.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_pslpurple.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_pslpurple.png deleted file mode 100644 index 877514d8cc..0000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_pslpurple.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_ruby.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_ruby.png deleted file mode 100644 index 944b519857..0000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_ruby.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_saphire.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_saphire.png deleted file mode 100644 index 2ee8967807..0000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_saphire.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_silver.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_silver.png deleted file mode 100644 index 51f4cceb08..0000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_silver.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/slim_icon_16_viewer.tga b/indra/newview/skins/darkorange/textures/slim_icon_16_viewer.tga deleted file mode 100644 index 552181d36a..0000000000 Binary files a/indra/newview/skins/darkorange/textures/slim_icon_16_viewer.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/sm_rounded_corners_simple.tga b/indra/newview/skins/darkorange/textures/sm_rounded_corners_simple.tga deleted file mode 100644 index 85157e4612..0000000000 Binary files a/indra/newview/skins/darkorange/textures/sm_rounded_corners_simple.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/smicon_warn.tga b/indra/newview/skins/darkorange/textures/smicon_warn.tga deleted file mode 100644 index 90ccaa07e5..0000000000 Binary files a/indra/newview/skins/darkorange/textures/smicon_warn.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spacer24.tga b/indra/newview/skins/darkorange/textures/spacer24.tga deleted file mode 100644 index c7cab6b38c..0000000000 Binary files a/indra/newview/skins/darkorange/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spacer35.tga b/indra/newview/skins/darkorange/textures/spacer35.tga deleted file mode 100644 index b88bc6680a..0000000000 Binary files a/indra/newview/skins/darkorange/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spin_down_in_blue.tga b/indra/newview/skins/darkorange/textures/spin_down_in_blue.tga deleted file mode 100644 index b9eb36ba9f..0000000000 Binary files a/indra/newview/skins/darkorange/textures/spin_down_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spin_down_out_blue.tga b/indra/newview/skins/darkorange/textures/spin_down_out_blue.tga deleted file mode 100644 index c9cb5e8bf6..0000000000 Binary files a/indra/newview/skins/darkorange/textures/spin_down_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spin_up_in_blue.tga b/indra/newview/skins/darkorange/textures/spin_up_in_blue.tga deleted file mode 100644 index b604b8843c..0000000000 Binary files a/indra/newview/skins/darkorange/textures/spin_up_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spin_up_out_blue.tga b/indra/newview/skins/darkorange/textures/spin_up_out_blue.tga deleted file mode 100644 index 4e3941e458..0000000000 Binary files a/indra/newview/skins/darkorange/textures/spin_up_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/startup_logo.j2c b/indra/newview/skins/darkorange/textures/startup_logo.j2c deleted file mode 100644 index d1b991f17f..0000000000 Binary files a/indra/newview/skins/darkorange/textures/startup_logo.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_busy.tga b/indra/newview/skins/darkorange/textures/status_busy.tga deleted file mode 100644 index 7743d9c7bb..0000000000 Binary files a/indra/newview/skins/darkorange/textures/status_busy.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_health.tga b/indra/newview/skins/darkorange/textures/status_health.tga deleted file mode 100644 index 3d5f455fcd..0000000000 Binary files a/indra/newview/skins/darkorange/textures/status_health.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_money.tga b/indra/newview/skins/darkorange/textures/status_money.tga deleted file mode 100644 index d5be31fc60..0000000000 Binary files a/indra/newview/skins/darkorange/textures/status_money.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_script_debug.tga b/indra/newview/skins/darkorange/textures/status_script_debug.tga deleted file mode 100644 index 6fca614835..0000000000 Binary files a/indra/newview/skins/darkorange/textures/status_script_debug.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_search.tga b/indra/newview/skins/darkorange/textures/status_search.tga deleted file mode 100644 index 3ac10c4769..0000000000 Binary files a/indra/newview/skins/darkorange/textures/status_search.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_search_btn.png b/indra/newview/skins/darkorange/textures/status_search_btn.png deleted file mode 100644 index e648ba8490..0000000000 Binary files a/indra/newview/skins/darkorange/textures/status_search_btn.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_search_btn_pressed.png b/indra/newview/skins/darkorange/textures/status_search_btn_pressed.png deleted file mode 100644 index ec4254f4d9..0000000000 Binary files a/indra/newview/skins/darkorange/textures/status_search_btn_pressed.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_voice.tga b/indra/newview/skins/darkorange/textures/status_voice.tga deleted file mode 100644 index 4ab4498cbc..0000000000 Binary files a/indra/newview/skins/darkorange/textures/status_voice.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tab_background_darkpurple.tga b/indra/newview/skins/darkorange/textures/tab_background_darkpurple.tga deleted file mode 100644 index 8169f98694..0000000000 Binary files a/indra/newview/skins/darkorange/textures/tab_background_darkpurple.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tab_background_lightgrey.tga b/indra/newview/skins/darkorange/textures/tab_background_lightgrey.tga deleted file mode 100644 index c2f8818f73..0000000000 Binary files a/indra/newview/skins/darkorange/textures/tab_background_lightgrey.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tab_background_purple.tga b/indra/newview/skins/darkorange/textures/tab_background_purple.tga deleted file mode 100644 index aa01b3cb68..0000000000 Binary files a/indra/newview/skins/darkorange/textures/tab_background_purple.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tabarea.tga b/indra/newview/skins/darkorange/textures/tabarea.tga deleted file mode 100644 index 5517aebfc8..0000000000 Binary files a/indra/newview/skins/darkorange/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tearoff_pressed.tga b/indra/newview/skins/darkorange/textures/tearoff_pressed.tga deleted file mode 100644 index 620d109de0..0000000000 Binary files a/indra/newview/skins/darkorange/textures/tearoff_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tearoffbox.tga b/indra/newview/skins/darkorange/textures/tearoffbox.tga deleted file mode 100644 index 0670d2e91b..0000000000 Binary files a/indra/newview/skins/darkorange/textures/tearoffbox.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/textures.xml b/indra/newview/skins/darkorange/textures/textures.xml index 41fe7a9f9b..48fcecbfeb 100644 --- a/indra/newview/skins/darkorange/textures/textures.xml +++ b/indra/newview/skins/darkorange/textures/textures.xml @@ -1,386 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/indra/newview/skins/darkorange/textures/uv_test1.j2c b/indra/newview/skins/darkorange/textures/uv_test1.j2c deleted file mode 100644 index 3d5b541796..0000000000 Binary files a/indra/newview/skins/darkorange/textures/uv_test1.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/white.tga b/indra/newview/skins/darkorange/textures/white.tga deleted file mode 100644 index 9fe68631cf..0000000000 Binary files a/indra/newview/skins/darkorange/textures/white.tga and /dev/null differ diff --git a/indra/newview/skins/default/colors_base.xml b/indra/newview/skins/default/colors_base.xml index f3d78b9e9c..070fed106c 100644 --- a/indra/newview/skins/default/colors_base.xml +++ b/indra/newview/skins/default/colors_base.xml @@ -103,6 +103,7 @@ + @@ -186,7 +187,6 @@ - diff --git a/indra/newview/skins/default/textures/Accordion_ArrowClosed_Off.png b/indra/newview/skins/default/textures/Accordion_ArrowClosed_Off.png new file mode 100644 index 0000000000..3dfe6d4549 Binary files /dev/null and b/indra/newview/skins/default/textures/Accordion_ArrowClosed_Off.png differ diff --git a/indra/newview/skins/default/textures/Accordion_ArrowClosed_Press.png b/indra/newview/skins/default/textures/Accordion_ArrowClosed_Press.png new file mode 100644 index 0000000000..c381e8e1d5 Binary files /dev/null and b/indra/newview/skins/default/textures/Accordion_ArrowClosed_Press.png differ diff --git a/indra/newview/skins/default/textures/Accordion_ArrowOpened_Off.png b/indra/newview/skins/default/textures/Accordion_ArrowOpened_Off.png new file mode 100644 index 0000000000..1a898834c4 Binary files /dev/null and b/indra/newview/skins/default/textures/Accordion_ArrowOpened_Off.png differ diff --git a/indra/newview/skins/default/textures/Accordion_ArrowOpened_Press.png b/indra/newview/skins/default/textures/Accordion_ArrowOpened_Press.png new file mode 100644 index 0000000000..05b381bdbc Binary files /dev/null and b/indra/newview/skins/default/textures/Accordion_ArrowOpened_Press.png differ diff --git a/indra/newview/skins/default/textures/Accordion_Off.png b/indra/newview/skins/default/textures/Accordion_Off.png new file mode 100644 index 0000000000..47b63618f5 Binary files /dev/null and b/indra/newview/skins/default/textures/Accordion_Off.png differ diff --git a/indra/newview/skins/default/textures/Accordion_Over.png b/indra/newview/skins/default/textures/Accordion_Over.png new file mode 100644 index 0000000000..6dcb4401ec Binary files /dev/null and b/indra/newview/skins/default/textures/Accordion_Over.png differ diff --git a/indra/newview/skins/default/textures/Accordion_Press.png b/indra/newview/skins/default/textures/Accordion_Press.png new file mode 100644 index 0000000000..a6b17a91fb Binary files /dev/null and b/indra/newview/skins/default/textures/Accordion_Press.png differ diff --git a/indra/newview/skins/default/textures/Accordion_Selected.png b/indra/newview/skins/default/textures/Accordion_Selected.png new file mode 100644 index 0000000000..27091d3bdc Binary files /dev/null and b/indra/newview/skins/default/textures/Accordion_Selected.png differ diff --git a/indra/newview/skins/default/textures/Blank.png b/indra/newview/skins/default/textures/Blank.png new file mode 100644 index 0000000000..f38e9f9100 Binary files /dev/null and b/indra/newview/skins/default/textures/Blank.png differ diff --git a/indra/newview/skins/default/textures/Conv_toolbar_plus.png b/indra/newview/skins/default/textures/Conv_toolbar_plus.png new file mode 100644 index 0000000000..25a32cb2ba Binary files /dev/null and b/indra/newview/skins/default/textures/Conv_toolbar_plus.png differ diff --git a/indra/newview/skins/default/textures/Conv_toolbar_sort.png b/indra/newview/skins/default/textures/Conv_toolbar_sort.png new file mode 100644 index 0000000000..08debeb91f Binary files /dev/null and b/indra/newview/skins/default/textures/Conv_toolbar_sort.png differ diff --git a/indra/newview/skins/default/textures/FMOD Logo.png b/indra/newview/skins/default/textures/FMOD Logo.png new file mode 100644 index 0000000000..3ddda90e2a Binary files /dev/null and b/indra/newview/skins/default/textures/FMOD Logo.png differ diff --git a/indra/newview/skins/default/textures/Inv_Post_Process.png b/indra/newview/skins/default/textures/Inv_Post_Process.png new file mode 100644 index 0000000000..2bdc31c637 Binary files /dev/null and b/indra/newview/skins/default/textures/Inv_Post_Process.png differ diff --git a/indra/newview/skins/default/textures/Inv_Settings.png b/indra/newview/skins/default/textures/Inv_Settings.png new file mode 100644 index 0000000000..49cfbe65cf Binary files /dev/null and b/indra/newview/skins/default/textures/Inv_Settings.png differ diff --git a/indra/newview/skins/default/textures/Inv_SettingsDay.png b/indra/newview/skins/default/textures/Inv_SettingsDay.png new file mode 100644 index 0000000000..2b36b1516e Binary files /dev/null and b/indra/newview/skins/default/textures/Inv_SettingsDay.png differ diff --git a/indra/newview/skins/default/textures/Inv_SettingsSky.png b/indra/newview/skins/default/textures/Inv_SettingsSky.png new file mode 100644 index 0000000000..4a85b3e8b3 Binary files /dev/null and b/indra/newview/skins/default/textures/Inv_SettingsSky.png differ diff --git a/indra/newview/skins/default/textures/Inv_SettingsWater.png b/indra/newview/skins/default/textures/Inv_SettingsWater.png new file mode 100644 index 0000000000..a0d879e441 Binary files /dev/null and b/indra/newview/skins/default/textures/Inv_SettingsWater.png differ diff --git a/indra/newview/skins/default/textures/Inv_StockFolderClosed.png b/indra/newview/skins/default/textures/Inv_StockFolderClosed.png new file mode 100644 index 0000000000..4dc484dc22 Binary files /dev/null and b/indra/newview/skins/default/textures/Inv_StockFolderClosed.png differ diff --git a/indra/newview/skins/default/textures/Inv_StockFolderOpen.png b/indra/newview/skins/default/textures/Inv_StockFolderOpen.png new file mode 100644 index 0000000000..0d140b56a7 Binary files /dev/null and b/indra/newview/skins/default/textures/Inv_StockFolderOpen.png differ diff --git a/indra/newview/skins/default/textures/Inv_Universal.png b/indra/newview/skins/default/textures/Inv_Universal.png new file mode 100644 index 0000000000..470febb9b5 Binary files /dev/null and b/indra/newview/skins/default/textures/Inv_Universal.png differ diff --git a/indra/newview/skins/default/textures/Inv_UnknownObject.png b/indra/newview/skins/default/textures/Inv_UnknownObject.png new file mode 100644 index 0000000000..2516afe7ab Binary files /dev/null and b/indra/newview/skins/default/textures/Inv_UnknownObject.png differ diff --git a/indra/newview/skins/default/textures/Inv_VersionFolderClosed.png b/indra/newview/skins/default/textures/Inv_VersionFolderClosed.png new file mode 100644 index 0000000000..e89a4d7f31 Binary files /dev/null and b/indra/newview/skins/default/textures/Inv_VersionFolderClosed.png differ diff --git a/indra/newview/skins/default/textures/Inv_VersionFolderOpen.png b/indra/newview/skins/default/textures/Inv_VersionFolderOpen.png new file mode 100644 index 0000000000..659d7d392f Binary files /dev/null and b/indra/newview/skins/default/textures/Inv_VersionFolderOpen.png differ diff --git a/indra/newview/skins/default/textures/MarketplaceBtn_Off.png b/indra/newview/skins/default/textures/MarketplaceBtn_Off.png new file mode 100644 index 0000000000..e603c44384 Binary files /dev/null and b/indra/newview/skins/default/textures/MarketplaceBtn_Off.png differ diff --git a/indra/newview/skins/default/textures/MarketplaceBtn_Selected.png b/indra/newview/skins/default/textures/MarketplaceBtn_Selected.png new file mode 100644 index 0000000000..fbc164123f Binary files /dev/null and b/indra/newview/skins/default/textures/MarketplaceBtn_Selected.png differ diff --git a/indra/newview/skins/default/textures/Marketplace_Dropzone_Background.png b/indra/newview/skins/default/textures/Marketplace_Dropzone_Background.png new file mode 100644 index 0000000000..9478f7b813 Binary files /dev/null and b/indra/newview/skins/default/textures/Marketplace_Dropzone_Background.png differ diff --git a/indra/newview/skins/default/textures/Progress_1.png b/indra/newview/skins/default/textures/Progress_1.png new file mode 100644 index 0000000000..69b9af5cd9 Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_1.png differ diff --git a/indra/newview/skins/default/textures/Progress_10.png b/indra/newview/skins/default/textures/Progress_10.png new file mode 100644 index 0000000000..2fe5328f42 Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_10.png differ diff --git a/indra/newview/skins/default/textures/Progress_11.png b/indra/newview/skins/default/textures/Progress_11.png new file mode 100644 index 0000000000..37a03fb621 Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_11.png differ diff --git a/indra/newview/skins/default/textures/Progress_12.png b/indra/newview/skins/default/textures/Progress_12.png new file mode 100644 index 0000000000..243e514064 Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_12.png differ diff --git a/indra/newview/skins/default/textures/Progress_2.png b/indra/newview/skins/default/textures/Progress_2.png new file mode 100644 index 0000000000..805175486f Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_2.png differ diff --git a/indra/newview/skins/default/textures/Progress_3.png b/indra/newview/skins/default/textures/Progress_3.png new file mode 100644 index 0000000000..4b47177908 Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_3.png differ diff --git a/indra/newview/skins/default/textures/Progress_4.png b/indra/newview/skins/default/textures/Progress_4.png new file mode 100644 index 0000000000..bdc3f886a9 Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_4.png differ diff --git a/indra/newview/skins/default/textures/Progress_5.png b/indra/newview/skins/default/textures/Progress_5.png new file mode 100644 index 0000000000..3ee2d32ec2 Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_5.png differ diff --git a/indra/newview/skins/default/textures/Progress_6.png b/indra/newview/skins/default/textures/Progress_6.png new file mode 100644 index 0000000000..3a5a45546e Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_6.png differ diff --git a/indra/newview/skins/default/textures/Progress_7.png b/indra/newview/skins/default/textures/Progress_7.png new file mode 100644 index 0000000000..b9029cade2 Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_7.png differ diff --git a/indra/newview/skins/default/textures/Progress_8.png b/indra/newview/skins/default/textures/Progress_8.png new file mode 100644 index 0000000000..357b1132f4 Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_8.png differ diff --git a/indra/newview/skins/default/textures/Progress_9.png b/indra/newview/skins/default/textures/Progress_9.png new file mode 100644 index 0000000000..05c919072b Binary files /dev/null and b/indra/newview/skins/default/textures/Progress_9.png differ diff --git a/indra/newview/skins/default/textures/icn_toolbar_experiences.tga b/indra/newview/skins/default/textures/icn_toolbar_experiences.tga new file mode 100644 index 0000000000..0a1a235f35 Binary files /dev/null and b/indra/newview/skins/default/textures/icn_toolbar_experiences.tga differ diff --git a/indra/newview/skins/default/textures/icn_toolbar_lag_meter.tga b/indra/newview/skins/default/textures/icn_toolbar_marketplace.tga similarity index 100% rename from indra/newview/skins/default/textures/icn_toolbar_lag_meter.tga rename to indra/newview/skins/default/textures/icn_toolbar_marketplace.tga diff --git a/indra/newview/skins/default/textures/icn_toolbar_outbox.tga b/indra/newview/skins/default/textures/icn_toolbar_marketplace_listings.tga similarity index 100% rename from indra/newview/skins/default/textures/icn_toolbar_outbox.tga rename to indra/newview/skins/default/textures/icn_toolbar_marketplace_listings.tga diff --git a/indra/newview/skins/default/textures/icn_toolbar_received_items.tga b/indra/newview/skins/default/textures/icn_toolbar_received_items.tga new file mode 100644 index 0000000000..49e5d11a21 Binary files /dev/null and b/indra/newview/skins/default/textures/icn_toolbar_received_items.tga differ diff --git a/indra/newview/skins/default/textures/navbar/Arrow_Left_Off.png b/indra/newview/skins/default/textures/navbar/Arrow_Left_Off.png new file mode 100644 index 0000000000..e1f28dc9b3 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Arrow_Left_Off.png differ diff --git a/indra/newview/skins/default/textures/navbar/Arrow_Right_Off.png b/indra/newview/skins/default/textures/navbar/Arrow_Right_Off.png new file mode 100644 index 0000000000..b38cc89ad5 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Arrow_Right_Off.png differ diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png new file mode 100644 index 0000000000..bb387c9f98 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png differ diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png new file mode 100644 index 0000000000..c873fe920c Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png differ diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Link_Over.png b/indra/newview/skins/default/textures/navbar/Favorite_Link_Over.png new file mode 100644 index 0000000000..50b70e68e1 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Favorite_Link_Over.png differ diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png new file mode 100644 index 0000000000..27076d2f41 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png differ diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Off.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Off.png new file mode 100644 index 0000000000..46b68a7575 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Favorite_Star_Off.png differ diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png new file mode 100644 index 0000000000..310b316bb6 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png differ diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Press.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Press.png new file mode 100644 index 0000000000..aa178320a5 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Favorite_Star_Press.png differ diff --git a/indra/newview/skins/default/textures/navbar/FileMenu_Divider.png b/indra/newview/skins/default/textures/navbar/FileMenu_Divider.png new file mode 100644 index 0000000000..133eb4a3c2 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/FileMenu_Divider.png differ diff --git a/indra/newview/skins/default/textures/navbar/Flag.png b/indra/newview/skins/default/textures/navbar/Flag.png new file mode 100644 index 0000000000..b027733c33 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Flag.png differ diff --git a/indra/newview/skins/default/textures/navbar/Help_Press.png b/indra/newview/skins/default/textures/navbar/Help_Press.png new file mode 100644 index 0000000000..a5794bb31a Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Help_Press.png differ diff --git a/indra/newview/skins/default/textures/navbar/Home_Off.png b/indra/newview/skins/default/textures/navbar/Home_Off.png new file mode 100644 index 0000000000..d70de58f10 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Home_Off.png differ diff --git a/indra/newview/skins/default/textures/navbar/Icon_Lightshare.png b/indra/newview/skins/default/textures/navbar/Icon_Lightshare.png new file mode 100644 index 0000000000..52630389b1 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Icon_Lightshare.png differ diff --git a/indra/newview/skins/default/textures/navbar/Info_Off.png b/indra/newview/skins/default/textures/navbar/Info_Off.png new file mode 100644 index 0000000000..44a5136794 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Info_Off.png differ diff --git a/indra/newview/skins/default/textures/navbar/Info_Over.png b/indra/newview/skins/default/textures/navbar/Info_Over.png new file mode 100644 index 0000000000..3220339a7e Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Info_Over.png differ diff --git a/indra/newview/skins/default/textures/navbar/Info_Press.png b/indra/newview/skins/default/textures/navbar/Info_Press.png new file mode 100644 index 0000000000..66494e2a41 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Info_Press.png differ diff --git a/indra/newview/skins/default/textures/navbar/Lock.png b/indra/newview/skins/default/textures/navbar/Lock.png new file mode 100644 index 0000000000..1f3ceb9517 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Lock.png differ diff --git a/indra/newview/skins/default/textures/navbar/NavBar_BG.png b/indra/newview/skins/default/textures/navbar/NavBar_BG.png new file mode 100644 index 0000000000..bc523f9912 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/NavBar_BG.png differ diff --git a/indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.png b/indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.png new file mode 100644 index 0000000000..62a8d286c0 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.png differ diff --git a/indra/newview/skins/default/textures/navbar/NavBar_BG_NoNav_Bevel.png b/indra/newview/skins/default/textures/navbar/NavBar_BG_NoNav_Bevel.png new file mode 100644 index 0000000000..473dcd83d6 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/NavBar_BG_NoNav_Bevel.png differ diff --git a/indra/newview/skins/default/textures/navbar/Row_Selection.png b/indra/newview/skins/default/textures/navbar/Row_Selection.png new file mode 100644 index 0000000000..0f82246aec Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Row_Selection.png differ diff --git a/indra/newview/skins/default/textures/navbar/Search.png b/indra/newview/skins/default/textures/navbar/Search.png new file mode 100644 index 0000000000..35021add61 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Search.png differ diff --git a/indra/newview/skins/default/textures/navbar/separator.png b/indra/newview/skins/default/textures/navbar/separator.png new file mode 100644 index 0000000000..89e2807db5 Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/separator.png differ diff --git a/indra/newview/skins/default/textures/noentrylines.j2c b/indra/newview/skins/default/textures/noentrylines.j2c deleted file mode 100644 index 93ec17659d..0000000000 Binary files a/indra/newview/skins/default/textures/noentrylines.j2c and /dev/null differ diff --git a/indra/newview/skins/default/textures/noentrypasslines.j2c b/indra/newview/skins/default/textures/noentrypasslines.j2c deleted file mode 100644 index 800c466964..0000000000 Binary files a/indra/newview/skins/default/textures/noentrypasslines.j2c and /dev/null differ diff --git a/indra/newview/skins/default/textures/skin_thumbnail_default.png b/indra/newview/skins/default/textures/skin_thumbnail_default.png deleted file mode 100644 index e22b1c1644..0000000000 Binary files a/indra/newview/skins/default/textures/skin_thumbnail_default.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/skin_thumbnail_silver.png b/indra/newview/skins/default/textures/skin_thumbnail_silver.png deleted file mode 100644 index 51f4cceb08..0000000000 Binary files a/indra/newview/skins/default/textures/skin_thumbnail_silver.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index b6420d4e03..e91c1b3c35 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -1,107 +1,312 @@ + + + + + + + + + + + - - - - - - - - - - + + + + + + - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + - + - + - - - - - - - - - - - - - - - - + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - @@ -114,8 +319,8 @@ - + @@ -123,9 +328,12 @@ + + + + - @@ -135,48 +343,52 @@ + - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - + - + + @@ -207,214 +419,53 @@ - - - - - - - + + + + + + + + + + + + + - + + - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/indra/newview/skins/default/textures/world/BeaconArrow.png b/indra/newview/skins/default/textures/world/BeaconArrow.png new file mode 100644 index 0000000000..ac7993f09b Binary files /dev/null and b/indra/newview/skins/default/textures/world/BeaconArrow.png differ diff --git a/indra/newview/skins/default/textures/world/CameraDragDot.png b/indra/newview/skins/default/textures/world/CameraDragDot.png new file mode 100644 index 0000000000..786f0de914 Binary files /dev/null and b/indra/newview/skins/default/textures/world/CameraDragDot.png differ diff --git a/indra/newview/skins/default/textures/world/NoEntryLines.png b/indra/newview/skins/default/textures/world/NoEntryLines.png new file mode 100644 index 0000000000..d16f69a459 Binary files /dev/null and b/indra/newview/skins/default/textures/world/NoEntryLines.png differ diff --git a/indra/newview/skins/default/textures/world/NoEntryPassLines.png b/indra/newview/skins/default/textures/world/NoEntryPassLines.png new file mode 100644 index 0000000000..87ed0b3958 Binary files /dev/null and b/indra/newview/skins/default/textures/world/NoEntryPassLines.png differ diff --git a/indra/newview/skins/default/xui/de/floater_about_land.xml b/indra/newview/skins/default/xui/de/floater_about_land.xml index b3ffed9f91..412f26181f 100644 --- a/indra/newview/skins/default/xui/de/floater_about_land.xml +++ b/indra/newview/skins/default/xui/de/floater_about_land.xml @@ -11,12 +11,9 @@ Einstuf.: Adult Eigentümer: - Leyla Linden - + + diff --git a/indra/newview/skins/default/xui/en-us/floater_buy_currency.xml b/indra/newview/skins/default/xui/en-us/floater_buy_currency.xml index 560a5cad25..a0ea720937 100644 --- a/indra/newview/skins/default/xui/en-us/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/en-us/floater_buy_currency.xml @@ -46,7 +46,7 @@ - for approx. US$ [USD] + for approx. [REALCURRENCY] [USD] @@ -91,6 +91,6 @@ Increase the amount to buy. + + + Loading... + Done + http://search.secondlife.com/ Loading... Done - http://secondlife.com/app/search/notfound.html "http://secondlife.com/app/showcase/index.php?" + multi_select="false" name="results" search_column="2" width="339" menu_num="1"> @@ -754,22 +764,7 @@ To buy direct, visit the land and click on the place name in the title bar. Loading... Done - [APP_SITE]/404 https://marketplace.secondlife.com/ - - - - - - Loading... - Done - [APP_SITE]/404 - http://search.secondlife.com/ + + diff --git a/indra/newview/skins/default/xui/en-us/floater_experienceprofile.xml b/indra/newview/skins/default/xui/en-us/floater_experienceprofile.xml new file mode 100644 index 0000000000..84bde7ed46 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/floater_experienceprofile.xml @@ -0,0 +1,618 @@ + + + + + (none) + + + map_event.tga + + + map_event_mature.tga + + + map_event_adult.tga + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/floater_instant_message_ad_hoc_concisebuttons.xml b/indra/newview/skins/default/xui/en-us/floater_instant_message_ad_hoc_concisebuttons.xml index 65196f003b..2d0a69f5cd 100644 --- a/indra/newview/skins/default/xui/en-us/floater_instant_message_ad_hoc_concisebuttons.xml +++ b/indra/newview/skins/default/xui/en-us/floater_instant_message_ad_hoc_concisebuttons.xml @@ -8,7 +8,9 @@ [NAME] is typing... Starting session with [NAME], please wait. Click here to instant message. - diff --git a/indra/newview/skins/default/xui/en-us/floater_instant_message_concisebuttons.xml b/indra/newview/skins/default/xui/en-us/floater_instant_message_concisebuttons.xml index aca3157e84..a2590a7ed8 100644 --- a/indra/newview/skins/default/xui/en-us/floater_instant_message_concisebuttons.xml +++ b/indra/newview/skins/default/xui/en-us/floater_instant_message_concisebuttons.xml @@ -19,6 +19,8 @@ + + @@ -29,6 +31,7 @@ + + + diff --git a/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml index 96edd82dc5..97604e99f6 100644 --- a/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml @@ -19,19 +19,19 @@ Dimensions: [DIMENSIONS] @@ -450,48 +454,36 @@ mouse_opaque="true" name="Creator:" v_pad="0" width="78"> Creator: - + mouse_opaque="true" name="Creator Name" v_pad="0" rlv_sensitive="true"> Thrax Linden - - + diff --git a/indra/newview/skins/default/xui/en-us/floater_tos.xml b/indra/newview/skins/default/xui/en-us/floater_tos.xml index 5451b35ef8..437ed18920 100644 --- a/indra/newview/skins/default/xui/en-us/floater_tos.xml +++ b/indra/newview/skins/default/xui/en-us/floater_tos.xml @@ -29,7 +29,7 @@ you must accept the agreement. height="340" left="16" max_length="65536" mouse_opaque="true" trusted_content="true" name="tos_html" - start_url="data:text/html,%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody text=%22000000%22%3E%3Ch2%3E Loading %3Ca%20target%3D%22_external%22%20href%3D%22http%3A//secondlife.com/app/tos/%22%3ETerms%20of%20Service%3C/a%3E...%3C/h2%3E %3C/body%3E %3C/html%3E" + start_url="data:text/html;charset=utf-8;base64,PGh0bWw+DQo8aGVhZD4NCjxzdHlsZT4NCmJvZHkgew0KICBmb250LWZhbWlseTogIkRlamEgVnUgU2FucyIsIEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWY7DQogIGNvbG9yOiAjZmZmOw0KICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2IoMzEsIDMxLCAzMSk7DQp9DQphIHsNCiAgICBjb2xvcjogcmdiKDkyLCAxNzcsIDE0Nik7DQogICAgdGV4dC1kZWNvcmF0aW9uOiBub25lOw0KfQ0KI2NlbnRlcmVkIHsNCiAgcG9zaXRpb246IHJlbGF0aXZlOw0KICBmbG9hdDogbGVmdDsNCiAgdG9wOiA1MCU7DQogIGxlZnQ6IDUwJTsNCiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSk7DQp9DQo8L3N0eWxlPg0KPC9oZWFkPg0KPGJvZHk+DQo8ZGl2IGlkPSJjZW50ZXJlZCI+TG9hZGluZyA8YSB0YXJnZXQ9Il9leHRlcm5hbCIgaHJlZj0iaHR0cDovL3NlY29uZGxpZmUuY29tL2FwcC90b3MvIj5UZXJtcyBvZiBTZXJ2aWNlPC9hPi4uLjwvZGl2Pg0KPC9ib2R5Pg0KPC9odG1sPg==" width="568" word_wrap="true" /> http://secondlife.com/app/tos/ diff --git a/indra/newview/skins/default/xui/en-us/floater_voice_license.xml b/indra/newview/skins/default/xui/en-us/floater_voice_license.xml index 6f573eba20..065f6b8c09 100644 --- a/indra/newview/skins/default/xui/en-us/floater_voice_license.xml +++ b/indra/newview/skins/default/xui/en-us/floater_voice_license.xml @@ -32,9 +32,9 @@ To use voice, you must accept the license agreement. start_url="data:text/html,%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody text=%22000000%22%3E%3Ch2%3E Loading %3Ca%20target%3D%22_external%22%20href%3D%22http%3A//vivox.com/vivox_aup.html%22%3EVivox%20Acceptable%20Use%20Policy%3C/a%3E...%3C/h2%3E %3C/body%3E %3C/html%3E" width="568" word_wrap="true" /> - http://replex-viewer.github.io/pages/vivox_aup.html + https://www.vivox.com/policies/acceptable_use.html - vivox_aup.html + http://replex-viewer.github.io/pages/vivox_aup.html diff --git a/indra/newview/skins/default/xui/en-us/fonts.xml b/indra/newview/skins/default/xui/en-us/fonts.xml index 78114c9de8..a3899f2392 100644 --- a/indra/newview/skins/default/xui/en-us/fonts.xml +++ b/indra/newview/skins/default/xui/en-us/fonts.xml @@ -3,11 +3,20 @@ DejaVuSansCondensed.ttf + NotoSansDisplay-Regular.ttf + SourceHanSansJP-Regular.otf + SourceHanSansKR-Regular.otf + SourceHanSansCN-Regular.otf + SourceHanSansHK-Regular.otf + SourceHanSansTW-Regular.otf + YuGothR.ttc + meiryo.TTC MSGOTHIC.TTC gulim.ttc simhei.ttf ArialUni.ttf + seguisym.ttf ヒラギノ角ゴ ProN W3.otf @@ -20,14 +29,48 @@ + + DroidSans-Bold.ttf + DejaVuSansCondensed-Bold.ttf + NotoSansDisplay-Bold.ttf + SourceHanSansJP-Bold.otf + SourceHanSansKR-Bold.otf + SourceHanSansCN-Bold.otf + SourceHanSansHK-Bold.otf + SourceHanSansTW-Bold.otf + + DroidSans.ttf - + font_style="BOLD"> DroidSans-Bold.ttf + DejaVuSansCondensed-Bold.ttf + NotoSansDisplay-Bold.ttf + SourceHanSansJP-Bold.otf + SourceHanSansKR-Bold.otf + SourceHanSansCN-Bold.otf + SourceHanSansHK-Bold.otf + SourceHanSansTW-Bold.otf + + + + DejaVuSansCondensed-Oblique.ttf + NotoSansDisplay-Italic.ttf + + + + DejaVuSansCondensed-BoldOblique.ttf + NotoSansDisplay-BoldItalic.ttf - DejaVuSans.ttf + DejaVuSansCondensed.ttf - DejaVuSansBold.ttf + DejaVuSansCondensed-Bold.ttf - DejaVuSansOblique.ttf + DejaVuSansCondensed-Oblique.ttf - DejaVuSansBoldOblique.ttf + DejaVuSansCondensed-BoldOblique.ttf - diff --git a/indra/newview/skins/default/xui/en-us/menu_avs_list.xml b/indra/newview/skins/default/xui/en-us/menu_avs_list.xml index 1bd2aea101..17350a7d07 100644 --- a/indra/newview/skins/default/xui/en-us/menu_avs_list.xml +++ b/indra/newview/skins/default/xui/en-us/menu_avs_list.xml @@ -4,78 +4,139 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_experiences.xml b/indra/newview/skins/default/xui/en-us/menu_experiences.xml new file mode 100644 index 0000000000..421eda40a1 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_experiences.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_groups_list.xml b/indra/newview/skins/default/xui/en-us/menu_groups_list.xml new file mode 100644 index 0000000000..67c84ed544 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_groups_list.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_inventory.xml b/indra/newview/skins/default/xui/en-us/menu_inventory.xml index 6811527c86..dd516bc28c 100644 --- a/indra/newview/skins/default/xui/en-us/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en-us/menu_inventory.xml @@ -1,6 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -45,6 +94,9 @@ + + + @@ -108,6 +160,9 @@ mouse_opaque="true" name="New Alpha" width="128"> + + + @@ -346,13 +401,11 @@ - - + + - - + + diff --git a/indra/newview/skins/default/xui/en-us/menu_local_avs.xml b/indra/newview/skins/default/xui/en-us/menu_local_avs.xml new file mode 100644 index 0000000000..87e6272f48 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_local_avs.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_marketplace_view.xml b/indra/newview/skins/default/xui/en-us/menu_marketplace_view.xml new file mode 100644 index 0000000000..2a266f5fb0 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_marketplace_view.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml b/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml index ca9deedcc6..bc1cb29ca9 100644 --- a/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml +++ b/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml @@ -1,6 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_mini_map.xml b/indra/newview/skins/default/xui/en-us/menu_mini_map.xml index 9e43a178a5..dfa3450df8 100644 --- a/indra/newview/skins/default/xui/en-us/menu_mini_map.xml +++ b/indra/newview/skins/default/xui/en-us/menu_mini_map.xml @@ -12,11 +12,11 @@ - - + + - + @@ -35,8 +35,9 @@ label="Property Lines" name="Property Lines"> + @@ -44,8 +45,9 @@ label="Parcels for Sale" name="Parcels for Sale"> + @@ -69,29 +71,21 @@ - + - + - + - - - - - - - - - - + + @@ -109,13 +103,14 @@ - - - - - + + + + + + - + diff --git a/indra/newview/skins/default/xui/en-us/menu_nameeditor_avatar.xml b/indra/newview/skins/default/xui/en-us/menu_nameeditor_avatar.xml new file mode 100644 index 0000000000..7f7f6995aa --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_nameeditor_avatar.xml @@ -0,0 +1,3 @@ + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_nameeditor_group.xml b/indra/newview/skins/default/xui/en-us/menu_nameeditor_group.xml new file mode 100644 index 0000000000..cd237eee95 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_nameeditor_group.xml @@ -0,0 +1,3 @@ + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_objects_list.xml b/indra/newview/skins/default/xui/en-us/menu_objects_list.xml new file mode 100644 index 0000000000..ef7619d5e7 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_objects_list.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_objects_list_owners.xml b/indra/newview/skins/default/xui/en-us/menu_objects_list_owners.xml new file mode 100644 index 0000000000..cf21c07562 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_objects_list_owners.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_pie_attachment.xml b/indra/newview/skins/default/xui/en-us/menu_pie_attachment.xml index 5c4b9487e2..ba3fb21058 100644 --- a/indra/newview/skins/default/xui/en-us/menu_pie_attachment.xml +++ b/indra/newview/skins/default/xui/en-us/menu_pie_attachment.xml @@ -68,6 +68,34 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_pie_avatar.xml b/indra/newview/skins/default/xui/en-us/menu_pie_avatar.xml index 78e8fca38c..8ea82e222e 100644 --- a/indra/newview/skins/default/xui/en-us/menu_pie_avatar.xml +++ b/indra/newview/skins/default/xui/en-us/menu_pie_avatar.xml @@ -17,7 +17,7 @@ - + @@ -33,6 +33,17 @@ + + + + + + + + + + + @@ -59,6 +67,9 @@ + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_pie_object.xml b/indra/newview/skins/default/xui/en-us/menu_pie_object.xml index 69d8885627..776b8d01d1 100644 --- a/indra/newview/skins/default/xui/en-us/menu_pie_object.xml +++ b/indra/newview/skins/default/xui/en-us/menu_pie_object.xml @@ -39,6 +39,7 @@ + @@ -73,8 +74,12 @@ - - + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_pie_self.xml b/indra/newview/skins/default/xui/en-us/menu_pie_self.xml index beaf530624..81ee09fd6f 100644 --- a/indra/newview/skins/default/xui/en-us/menu_pie_self.xml +++ b/indra/newview/skins/default/xui/en-us/menu_pie_self.xml @@ -1,109 +1,122 @@ - - - - - - - - - + + + + + + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - - + + + + - - - - - + + + + - - - + + - - - - + + + - - - - + + + - - - + + + - - + - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_radar.xml b/indra/newview/skins/default/xui/en-us/menu_radar.xml index 540416be0e..fc1a00689d 100644 --- a/indra/newview/skins/default/xui/en-us/menu_radar.xml +++ b/indra/newview/skins/default/xui/en-us/menu_radar.xml @@ -45,29 +45,50 @@ + + + + + + + + - + - - + + + + + + + + + + - + + - + + + + + @@ -97,6 +118,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -172,10 +214,6 @@ - - - - @@ -192,6 +230,10 @@ + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_texteditor.xml b/indra/newview/skins/default/xui/en-us/menu_texteditor.xml new file mode 100644 index 0000000000..8292d8d911 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_texteditor.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_agent.xml b/indra/newview/skins/default/xui/en-us/menu_url_agent.xml new file mode 100644 index 0000000000..da88c9fced --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_agent.xml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_email.xml b/indra/newview/skins/default/xui/en-us/menu_url_email.xml new file mode 100644 index 0000000000..cfd91a65d5 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_email.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_experience.xml b/indra/newview/skins/default/xui/en-us/menu_url_experience.xml new file mode 100644 index 0000000000..7ab1c710ff --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_experience.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_group.xml b/indra/newview/skins/default/xui/en-us/menu_url_group.xml new file mode 100644 index 0000000000..7200b6e035 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_group.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_http.xml b/indra/newview/skins/default/xui/en-us/menu_url_http.xml new file mode 100644 index 0000000000..ed2d714352 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_http.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_inventory.xml b/indra/newview/skins/default/xui/en-us/menu_url_inventory.xml new file mode 100644 index 0000000000..f1b4acbbb7 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_inventory.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_map.xml b/indra/newview/skins/default/xui/en-us/menu_url_map.xml new file mode 100644 index 0000000000..4cad974448 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_map.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_object_owner.xml b/indra/newview/skins/default/xui/en-us/menu_url_object_owner.xml new file mode 100644 index 0000000000..3ee8b614b8 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_object_owner.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_objectim.xml b/indra/newview/skins/default/xui/en-us/menu_url_objectim.xml new file mode 100644 index 0000000000..6ec0dac59c --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_objectim.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_parcel.xml b/indra/newview/skins/default/xui/en-us/menu_url_parcel.xml new file mode 100644 index 0000000000..372454835a --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_parcel.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_slapp.xml b/indra/newview/skins/default/xui/en-us/menu_url_slapp.xml new file mode 100644 index 0000000000..7fdb07d9ee --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_slapp.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_slurl.xml b/indra/newview/skins/default/xui/en-us/menu_url_slurl.xml new file mode 100644 index 0000000000..8d3900228c --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_slurl.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_url_teleport.xml b/indra/newview/skins/default/xui/en-us/menu_url_teleport.xml new file mode 100644 index 0000000000..f1b3ad5faa --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_url_teleport.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_viewer.xml b/indra/newview/skins/default/xui/en-us/menu_viewer.xml index c41b11c075..b83ffe4f6b 100644 --- a/indra/newview/skins/default/xui/en-us/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en-us/menu_viewer.xml @@ -8,24 +8,24 @@ - + - + - + - @@ -598,18 +598,21 @@ + userdata="WebLaunchAccountHistory,https://accounts.secondlife.com/transaction_history/" /> + userdata="WebLaunchJoinNow,https://secondlife.com/my/account/index.php" /> + + + - - + label="Marketplace Listings..." + name="MarketplaceListings"> + + @@ -617,12 +620,18 @@ - - - - - - + + + + + + + + + + + + @@ -633,6 +642,10 @@ + + + + @@ -988,9 +1001,6 @@ width="166"> - - - + userdata="WebLaunchSinguIssue,https://singularityviewer.atlassian.net/secure/CreateIssue!default.jspa?issuetype=1" /> - + + + + + @@ -1075,6 +1089,10 @@ + + + diff --git a/indra/newview/skins/default/xui/en-us/mime_types_linux.xml b/indra/newview/skins/default/xui/en-us/mime_types_linux.xml index e95b371d00..22a0024874 100644 --- a/indra/newview/skins/default/xui/en-us/mime_types_linux.xml +++ b/indra/newview/skins/default/xui/en-us/mime_types_linux.xml @@ -7,7 +7,7 @@ none - media_plugin_webkit + media_plugin_cef + + + + none/none + + + icn_media_web.tga + + + No media here + + + + false + + + false + +
  • ...